From 1c1aef021d011f0243a2ff962f725f82331dd215 Mon Sep 17 00:00:00 2001 From: coolsnowwolf Date: Sat, 4 Jul 2020 11:23:36 +0800 Subject: [PATCH] add mt proprietary driver for linux 5.4 (Thx MeIsReallyBa and hanwckf) --- package/lean/mt/drivers/mt7603e/Makefile | 62 + package/lean/mt/drivers/mt7603e/config.in | 526 + .../mt7603e/src/mt7603_wifi/History.txt | 96 + .../drivers/mt7603e/src/mt7603_wifi/Kconfig | 533 + .../mt7603e/src/mt7603_wifi/Kconfig.mt_wifi | 513 + .../drivers/mt7603e/src/mt7603_wifi/Makefile | 678 + .../mt7603e/src/mt7603_wifi/RT2860AP.dat | 147 + .../mt7603e/src/mt7603_wifi/RT2860APCard.dat | 19 + .../drivers/mt7603e/src/mt7603_wifi/ap/ap.c | 3983 +++ .../mt7603e/src/mt7603_wifi/ap/ap_acl_v2.c | 724 + .../mt7603e/src/mt7603_wifi/ap/ap_apcli.c | 4961 +++ .../mt7603e/src/mt7603_wifi/ap/ap_apcli_inf.c | 195 + .../mt7603e/src/mt7603_wifi/ap/ap_assoc.c | 3417 ++ .../mt7603e/src/mt7603_wifi/ap/ap_auth.c | 1374 + .../mt7603e/src/mt7603_wifi/ap/ap_autoChSel.c | 1563 + .../src/mt7603_wifi/ap/ap_band_steering.c | 2065 ++ .../mt7603e/src/mt7603_wifi/ap/ap_cfg.c | 17758 ++++++++++ .../mt7603e/src/mt7603_wifi/ap/ap_connect.c | 1890 ++ .../mt7603e/src/mt7603_wifi/ap/ap_data.c | 4133 +++ .../mt7603e/src/mt7603_wifi/ap/ap_dls.c | 27 + .../mt7603e/src/mt7603_wifi/ap/ap_ftkd.c | 1775 + .../mt7603e/src/mt7603_wifi/ap/ap_ids.c | 481 + .../mt7603e/src/mt7603_wifi/ap/ap_mbss.c | 454 + .../mt7603e/src/mt7603_wifi/ap/ap_mbss_inf.c | 202 + .../mt7603e/src/mt7603_wifi/ap/ap_mix_mode.c | 533 + .../mt7603e/src/mt7603_wifi/ap/ap_mlme.c | 769 + .../mt7603e/src/mt7603_wifi/ap/ap_nintendo.c | 31 + .../mt7603e/src/mt7603_wifi/ap/ap_nps.c | 309 + .../mt7603e/src/mt7603_wifi/ap/ap_qload.c | 923 + .../mt7603e/src/mt7603_wifi/ap/ap_repeater.c | 1027 + .../mt7603e/src/mt7603_wifi/ap/ap_sanity.c | 30 + .../mt7603e/src/mt7603_wifi/ap/ap_sync.c | 2296 ++ .../mt7603e/src/mt7603_wifi/ap/ap_wds.c | 1403 + .../mt7603e/src/mt7603_wifi/ap/ap_wds_inf.c | 113 + .../mt7603e/src/mt7603_wifi/ap/ap_wpa.c | 1545 + .../mt7603e/src/mt7603_wifi/ap/apcli_assoc.c | 1288 + .../mt7603e/src/mt7603_wifi/ap/apcli_auth.c | 1132 + .../mt7603e/src/mt7603_wifi/ap/apcli_ctrl.c | 2105 ++ .../src/mt7603_wifi/ap/apcli_link_cover.c | 144 + .../mt7603e/src/mt7603_wifi/ap/apcli_sync.c | 1581 + .../mt7603e/src/mt7603_wifi/ap/sniffer_mib.c | 551 + .../mt7603e/src/mt7603_wifi/ate/ate_agent.c | 1231 + .../mt7603e/src/mt7603_wifi/ate/include/ate.h | 243 + .../src/mt7603_wifi/ate/include/ate_agent.h | 83 + .../src/mt7603_wifi/ate/include/qa_agent.h | 82 + .../src/mt7603_wifi/ate/include/rt_ate.h | 799 + .../src/mt7603_wifi/ate/include/rt_qa.h | 179 + .../mt7603e/src/mt7603_wifi/ate/inf/ate_pci.c | 530 + .../mt7603e/src/mt7603_wifi/ate/inf/ate_usb.c | 29 + .../src/mt7603_wifi/ate/mt_mac/mt_ate.c | 1183 + .../mt7603e/src/mt7603_wifi/ate/qa_agent.c | 2094 ++ .../mt7603e/src/mt7603_wifi/chips/mt7603.c | 1389 + .../mt7603e/src/mt7603_wifi/chips/mt7628.c | 1018 + .../mt7603e/src/mt7603_wifi/chips/mt7636.c | 1036 + .../mt7603e/src/mt7603_wifi/chips/rt28xx.c | 400 + .../mt7603e/src/mt7603_wifi/chips/rt65xx.c | 29 + .../mt7603e/src/mt7603_wifi/chips/rtmp_chip.c | 539 + .../mt7603e/src/mt7603_wifi/chips/rtxx_dft.c | 395 + .../src/mt7603_wifi/common/RT85592.bin | Bin 0 -> 25740 bytes .../mt7603e/src/mt7603_wifi/common/a4_conn.c | 731 + .../mt7603e/src/mt7603_wifi/common/action.c | 1185 + .../src/mt7603_wifi/common/all_net_event.c | 20 + .../src/mt7603_wifi/common/ba_action.c | 2320 ++ .../mt7603e/src/mt7603_wifi/common/bn_lib.c | 6977 ++++ .../src/mt7603_wifi/common/client_wds.c | 192 + .../mt7603e/src/mt7603_wifi/common/cmm_aes.c | 1153 + .../mt7603e/src/mt7603_wifi/common/cmm_cfg.c | 2771 ++ .../mt7603e/src/mt7603_wifi/common/cmm_cmd.c | 179 + .../mt7603e/src/mt7603_wifi/common/cmm_cs.c | 880 + .../mt7603e/src/mt7603_wifi/common/cmm_data.c | 5293 +++ .../src/mt7603_wifi/common/cmm_data_pci.c | 2765 ++ .../src/mt7603_wifi/common/cmm_data_sdio.c | 147 + .../mt7603e/src/mt7603_wifi/common/cmm_dfs.c | 2677 ++ .../mt7603e/src/mt7603_wifi/common/cmm_info.c | 9797 ++++++ .../src/mt7603_wifi/common/cmm_loft_cal.c | 32 + .../src/mt7603_wifi/common/cmm_mac_pci.c | 3274 ++ .../src/mt7603_wifi/common/cmm_mac_sdio.c | 170 + .../mt7603e/src/mt7603_wifi/common/cmm_mat.c | 474 + .../src/mt7603_wifi/common/cmm_mat_iparp.c | 807 + .../src/mt7603_wifi/common/cmm_mat_ipv6.c | 821 + .../src/mt7603_wifi/common/cmm_mat_pppoe.c | 1058 + .../src/mt7603_wifi/common/cmm_profile.c | 5440 +++ .../src/mt7603_wifi/common/cmm_radar.c | 428 + .../src/mt7603_wifi/common/cmm_rf_cal.c | 2996 ++ .../src/mt7603_wifi/common/cmm_sanity.c | 2262 ++ .../mt7603e/src/mt7603_wifi/common/cmm_sync.c | 635 + .../mt7603e/src/mt7603_wifi/common/cmm_tkip.c | 929 + .../src/mt7603_wifi/common/cmm_usb_io.c | 1197 + .../src/mt7603_wifi/common/cmm_video.c | 168 + .../mt7603e/src/mt7603_wifi/common/cmm_wep.c | 370 + .../mt7603e/src/mt7603_wifi/common/cmm_wpa.c | 7025 ++++ .../src/mt7603_wifi/common/crypt_aes.c | 1599 + .../src/mt7603_wifi/common/crypt_arc4.c | 139 + .../src/mt7603_wifi/common/crypt_biginteger.c | 4448 +++ .../src/mt7603_wifi/common/crypt_bignum.c | 551 + .../mt7603e/src/mt7603_wifi/common/crypt_dh.c | 227 + .../src/mt7603_wifi/common/crypt_hmac.c | 505 + .../src/mt7603_wifi/common/crypt_md5.c | 356 + .../src/mt7603_wifi/common/crypt_sha2.c | 849 + .../mt7603e/src/mt7603_wifi/common/ecc.c | 1178 + .../mt7603e/src/mt7603_wifi/common/ee_efuse.c | 1404 + .../mt7603e/src/mt7603_wifi/common/ee_flash.c | 531 + .../mt7603e/src/mt7603_wifi/common/ee_prom.c | 269 + .../mt7603e/src/mt7603_wifi/common/eeprom.c | 1134 + .../src/mt7603_wifi/common/event_notifier.c | 694 + .../mt7603_wifi/common/event_notifier_old.c | 125 + .../mt7603e/src/mt7603_wifi/common/frq_cal.c | 28 + .../mt7603e/src/mt7603_wifi/common/ft.c | 3055 ++ .../mt7603e/src/mt7603_wifi/common/ft_iocl.c | 1093 + .../mt7603e/src/mt7603_wifi/common/ft_rc.c | 383 + .../mt7603e/src/mt7603_wifi/common/ft_tlv.c | 206 + .../mt7603e/src/mt7603_wifi/common/gas.c | 1320 + .../mt7603e/src/mt7603_wifi/common/hotspot.c | 841 + .../src/mt7603_wifi/common/igmp_snoop.c | 1759 + .../mt7603e/src/mt7603_wifi/common/map.c | 386 + .../mt7603e/src/mt7603_wifi/common/mbo.c | 1135 + .../mt7603e/src/mt7603_wifi/common/misc.c | 35 + .../mt7603e/src/mt7603_wifi/common/mlme.c | 6403 ++++ .../mt7603e/src/mt7603_wifi/common/mt_io.c | 132 + .../mt7603e/src/mt7603_wifi/common/mt_ps.c | 666 + .../src/mt7603_wifi/common/mtsdio_data.c | 710 + .../src/mt7603_wifi/common/mtsdio_io.c | 121 + .../mt7603e/src/mt7603_wifi/common/mtusb_io.c | 625 + .../mt7603e/src/mt7603_wifi/common/mwds.c | 282 + .../src/mt7603_wifi/common/netif_block.c | 87 + .../mt7603e/src/mt7603_wifi/common/nfc.c | 906 + .../mt7603e/src/mt7603_wifi/common/op_class.c | 375 + .../mt7603e/src/mt7603_wifi/common/owe.c | 595 + .../mt7603e/src/mt7603_wifi/common/pmf.c | 1797 + .../mt7603e/src/mt7603_wifi/common/ps.c | 255 + .../mt7603e/src/mt7603_wifi/common/ral_ps.c | 215 + .../src/mt7603_wifi/common/routing_tab.c | 1644 + .../mt7603e/src/mt7603_wifi/common/rrm.c | 2559 ++ .../src/mt7603_wifi/common/rrm_sanity.c | 147 + .../mt7603e/src/mt7603_wifi/common/rrm_tlv.c | 941 + .../mt7603e/src/mt7603_wifi/common/rt2860.bin | Bin 0 -> 8192 bytes .../src/mt7603_wifi/common/rt2860.bin.dfs | Bin 0 -> 8192 bytes .../common/rt2870_sw_ch_offload.bin | Bin 0 -> 8192 bytes .../src/mt7603_wifi/common/rt_channel.c | 2275 ++ .../mt7603e/src/mt7603_wifi/common/rt_led.c | 565 + .../src/mt7603_wifi/common/rt_os_util.c | 140 + .../src/mt7603_wifi/common/rtmp_init.c | 2737 ++ .../src/mt7603_wifi/common/rtmp_init_inf.c | 1095 + .../src/mt7603_wifi/common/rtmp_timer.c | 368 + .../mt7603e/src/mt7603_wifi/common/sae.c | 2759 ++ .../mt7603e/src/mt7603_wifi/common/scan.c | 729 + .../mt7603e/src/mt7603_wifi/common/spectrum.c | 2415 ++ .../mt7603e/src/mt7603_wifi/common/sys_log.c | 282 + .../mt7603e/src/mt7603_wifi/common/txpower.c | 1948 ++ .../mt7603e/src/mt7603_wifi/common/uapsd.c | 2513 ++ .../mt7603e/src/mt7603_wifi/common/vendor.c | 802 + .../mt7603e/src/mt7603_wifi/common/vht.c | 638 + .../mt7603e/src/mt7603_wifi/common/wapi.c | 1219 + .../src/mt7603_wifi/common/wapi_crypt.c | 509 + .../src/mt7603_wifi/common/wapi_sms4.c | 127 + .../mt7603e/src/mt7603_wifi/common/wfd.c | 18 + .../mt7603e/src/mt7603_wifi/common/wnm.c | 3561 ++ .../mt7603e/src/mt7603_wifi/common/wnm_tlv.c | 63 + .../mt7603e/src/mt7603_wifi/common/wsc.c | 9890 ++++++ .../mt7603e/src/mt7603_wifi/common/wsc_tlv.c | 4324 +++ .../mt7603e/src/mt7603_wifi/common/wsc_ufd.c | 598 + .../mt7603e/src/mt7603_wifi/common/wsc_v2.c | 296 + .../mt7603e/src/mt7603_wifi/conf/RT2860AP.dat | 147 + .../src/mt7603_wifi/conf/RT2860AP.dat_ac | 133 + .../src/mt7603_wifi/conf/RT2860APCard.dat | 19 + .../src/mt7603_wifi/conf/RT2860STA.dat | 95 + .../src/mt7603_wifi/conf/RT2860STACard.dat | 19 + .../mt7603e/src/mt7603_wifi/conf/RT2870AP.dat | 128 + .../src/mt7603_wifi/conf/RT2870APCard.dat | 19 + .../src/mt7603_wifi/conf/RT2870STA.dat | 104 + .../src/mt7603_wifi/conf/RT2870STACard.dat | 19 + .../mt7603e/src/mt7603_wifi/doc/History.txt | 96 + .../mt7603e/src/mt7603_wifi/doc/README | 68 + .../src/mt7603_wifi/doc/README_STA_pci | 528 + .../src/mt7603_wifi/doc/README_STA_usb | 534 + .../src/mt7603_wifi/doc/RT2860card.readme | 84 + .../RT_WIFI_Revision_History_2010_April.xls | Bin 0 -> 123904 bytes .../src/mt7603_wifi/doc/VxWorks.README | 4 + .../src/mt7603_wifi/doc/ate_iwpriv_usage.txt | 444 + .../src/mt7603_wifi/doc/brftph_usage.txt | 68 + .../src/mt7603_wifi/doc/iwpriv_usage.txt | 447 + .../src/mt7603_wifi/doc/mbss_phy.readme | 65 + .../mt7603_wifi/doc/sta_ate_iwpriv_usage.txt | 445 + .../src/mt7603_wifi/doc/wps_iwpriv_usage.txt | 173 + .../src/mt7603_wifi/easy_setup/ez_hooks.c | 4784 +++ .../mt7603_wifi/easy_setup/mt7603_chip_ops.c | 1401 + .../easy_setup/mt7603_chip_ops_api.c | 2103 ++ .../easy_setup/mt7603_driver_specific_func.c | 173 + .../eeprom/MT7601_USB_V0_D-20130416.bin | Bin 0 -> 512 bytes .../MT7603E1E2_EEPROM_layout_2014011.bin | Bin 0 -> 512 bytes ...7603E1E2_EEPROM_layout_2014011_ePAeLNA.bin | Bin 0 -> 512 bytes .../MT7603E1E2_EEPROM_layout_20140226.bin | Bin 0 -> 512 bytes .../MT7603E1_EEPROM_layout_20131112.bin | Bin 0 -> 512 bytes .../MT7603E1_EEPROM_layout_20131206.bin | Bin 0 -> 512 bytes .../src/mt7603_wifi/eeprom/MT7603E_EEPROM.bin | Bin 0 -> 512 bytes .../MT7662E1_EEPROM_layout_20130301.bin | Bin 0 -> 512 bytes .../eeprom/MT7662E2_EEPROM_20130412.bin | Bin 0 -> 512 bytes .../eeprom/MT7662E2_EEPROM_20130527.bin | Bin 0 -> 512 bytes .../eeprom/MT7662E2_EEPROM_20130528.bin | Bin 0 -> 512 bytes .../eeprom/MT7662E2_EEPROM_20130903_ePA.bin | Bin 0 -> 512 bytes .../mt7603e/src/mt7603_wifi/hif/hif_pci.c | 36 + .../src/mt7603_wifi/hw_ctrl/cmm_asic.c | 3310 ++ .../src/mt7603_wifi/hw_ctrl/cmm_asic_mt.c | 6817 ++++ .../src/mt7603_wifi/hw_ctrl/cmm_chip_mt.c | 87 + .../mt7603e/src/mt7603_wifi/hw_ctrl/coex.c | 26 + .../mt7603e/src/mt7603_wifi/hw_ctrl/greenap.c | 170 + .../mt7603e/src/mt7603_wifi/hw_ctrl/mt_gpio.c | 368 + .../mt7603e/src/mt7603_wifi/include/a4_conn.h | 144 + .../mt7603e/src/mt7603_wifi/include/action.h | 97 + .../mt7603e/src/mt7603_wifi/include/ags.h | 102 + .../src/mt7603_wifi/include/all_net_event.h | 23 + .../mt7603e/src/mt7603_wifi/include/ap.h | 410 + .../src/mt7603_wifi/include/ap_acl_v2.h | 125 + .../src/mt7603_wifi/include/ap_apcli.h | 374 + .../src/mt7603_wifi/include/ap_autoChSel.h | 83 + .../mt7603_wifi/include/ap_autoChSel_cmm.h | 104 + .../mt7603e/src/mt7603_wifi/include/ap_cfg.h | 259 + .../src/mt7603_wifi/include/ap_diversity.h | 138 + .../mt7603e/src/mt7603_wifi/include/ap_ids.h | 68 + .../mt7603e/src/mt7603_wifi/include/ap_mbss.h | 87 + .../mt7603e/src/mt7603_wifi/include/ap_wds.h | 159 + .../src/mt7603_wifi/include/band_steering.h | 112 + .../mt7603_wifi/include/band_steering_def.h | 381 + .../mt7603e/src/mt7603_wifi/include/bn.h | 646 + .../mt7603e/src/mt7603_wifi/include/br_ftph.h | 81 + .../src/mt7603_wifi/include/cfg80211.h | 28 + .../src/mt7603_wifi/include/cfg80211_cmm.h | 30 + .../src/mt7603_wifi/include/cfg80211extr.h | 32 + .../src/mt7603_wifi/include/chip/chip_id.h | 85 + .../src/mt7603_wifi/include/chip/mt7603.h | 38 + .../src/mt7603_wifi/include/chip/mt7628.h | 33 + .../src/mt7603_wifi/include/chip/mt7636.h | 22 + .../src/mt7603_wifi/include/chip/mt76x0.h | 193 + .../src/mt7603_wifi/include/chip/rt65xx.h | 72 + .../src/mt7603_wifi/include/chip/rt8592.h | 50 + .../mt7603e/src/mt7603_wifi/include/chlist.h | 169 + .../src/mt7603_wifi/include/client_wds.h | 57 + .../src/mt7603_wifi/include/client_wds_cmm.h | 46 + .../src/mt7603_wifi/include/cmm_asic_mt.h | 26 + .../src/mt7603_wifi/include/crypt_aes.h | 176 + .../src/mt7603_wifi/include/crypt_arc4.h | 57 + .../mt7603_wifi/include/crypt_biginteger.h | 523 + .../src/mt7603_wifi/include/crypt_bignum.h | 328 + .../src/mt7603_wifi/include/crypt_dh.h | 65 + .../src/mt7603_wifi/include/crypt_hmac.h | 111 + .../src/mt7603_wifi/include/crypt_md5.h | 63 + .../src/mt7603_wifi/include/crypt_sha2.h | 151 + .../mt7603e/src/mt7603_wifi/include/cs.h | 154 + .../mt7603e/src/mt7603_wifi/include/dfs.h | 430 + .../mt7603e/src/mt7603_wifi/include/diag.h | 94 + .../src/mt7603_wifi/include/dot11_base.h | 152 + .../src/mt7603_wifi/include/dot11ac_vht.h | 665 + .../src/mt7603_wifi/include/dot11i_wpa.h | 334 + .../src/mt7603_wifi/include/dot11k_rrm.h | 375 + .../src/mt7603_wifi/include/dot11n_ht.h | 353 + .../src/mt7603_wifi/include/dot11r_ft.h | 343 + .../mt7603_wifi/include/dot11u_interworking.h | 117 + .../src/mt7603_wifi/include/dot11v_wnm.h | 106 + .../src/mt7603_wifi/include/dot11w_pmf.h | 112 + .../src/mt7603_wifi/include/drs_extr.h | 453 + .../mt7603_wifi/include/easy_setup/ez_cmm.h | 547 + .../mt7603_wifi/include/easy_setup/ez_hooks.h | 342 + .../include/easy_setup/ez_hooks_proto.h | 384 + .../include/easy_setup/ez_mod_hooks.h | 293 + .../include/easy_setup/mt7603_chip_ops.h | 369 + .../include/easy_setup/mt7603_chip_ops_api.h | 277 + .../easy_setup/mt7603_driver_specific_func.h | 206 + .../mt7603e/src/mt7603_wifi/include/ecc.h | 149 + .../mt7603e/src/mt7603_wifi/include/eeprom.h | 764 + .../mt7603_wifi/include/eeprom/mt7601_e2p.h | 37 + .../mt7603_wifi/include/eeprom/mt7603_e2p.h | 37 + .../mt7603_wifi/include/eeprom/mt76x2_e2p.h | 37 + .../mt7603_wifi/include/eeprom/mt_e2p_def.h | 436 + .../mt7603e/src/mt7603_wifi/include/efuse.h | 86 + .../src/mt7603_wifi/include/event_notifier.h | 202 + .../mt7603_wifi/include/event_notifier_old.h | 110 + .../src/mt7603_wifi/include/firmware.h | 517 + .../src/mt7603_wifi/include/fpga/fpga_ctl.h | 62 + .../src/mt7603_wifi/include/frame_hdr.h | 81 + .../mt7603e/src/mt7603_wifi/include/frq_cal.h | 77 + .../mt7603e/src/mt7603_wifi/include/ft.h | 1259 + .../mt7603e/src/mt7603_wifi/include/ft_cmm.h | 249 + .../mt7603e/src/mt7603_wifi/include/gas.h | 201 + .../mt7603e/src/mt7603_wifi/include/hotspot.h | 195 + .../src/mt7603_wifi/include/iface/iface.h | 13 + .../mt7603_wifi/include/iface/iface_util.h | 66 + .../include/iface/mt_hif_pci_usb.h | 472 + .../mt7603_wifi/include/iface/mt_hif_sdio.h | 132 + .../src/mt7603_wifi/include/iface/mt_sdio.h | 43 + .../include/iface/rtmp_inf_pcirbs.h | 171 + .../src/mt7603_wifi/include/iface/rtmp_pci.h | 93 + .../include/iface/rtmp_reg_pcirbs.h | 456 + .../src/mt7603_wifi/include/igmp_snoop.h | 155 + .../mt7603e/src/mt7603_wifi/include/ipv6.h | 205 + .../src/mt7603_wifi/include/link_list.h | 174 + .../mt7603e/src/mt7603_wifi/include/mac/mac.h | 177 + .../mt7603_wifi/include/mac/mac_mt/client.h | 33 + .../src/mt7603_wifi/include/mac/mac_mt/gpio.h | 127 + .../mt7603_wifi/include/mac/mac_mt/mt_mac.h | 1734 + .../include/mac/mac_mt/mt_mac_pci.h | 661 + .../include/mac/mac_mt/mt_mac_sdio.h | 203 + .../include/mac/mac_mt/mt_mac_usb.h | 576 + .../src/mt7603_wifi/include/mac/mac_mt/pse.h | 193 + .../include/mac/mac_mt/ral_nmac_usb.h | 33 + .../src/mt7603_wifi/include/mac/mac_mt/top.h | 48 + .../mt7603_wifi/include/mac/mac_mt/wf_agg.h | 207 + .../mt7603_wifi/include/mac/mac_mt/wf_aon.h | 37 + .../mt7603_wifi/include/mac/mac_mt/wf_arb.h | 124 + .../include/mac/mac_mt/wf_cfgoff.h | 37 + .../mt7603_wifi/include/mac/mac_mt/wf_dma.h | 76 + .../include/mac/mac_mt/wf_int_wakeup_top.h | 59 + .../include/mac/mac_mt/wf_lpon_top.h | 148 + .../mt7603_wifi/include/mac/mac_mt/wf_mib.h | 72 + .../mt7603_wifi/include/mac/mac_mt/wf_pf.h | 37 + .../mt7603_wifi/include/mac/mac_mt/wf_phy.h | 93 + .../mt7603_wifi/include/mac/mac_mt/wf_rmac.h | 194 + .../mt7603_wifi/include/mac/mac_mt/wf_sec.h | 37 + .../mt7603_wifi/include/mac/mac_mt/wf_tmac.h | 238 + .../mt7603_wifi/include/mac/mac_mt/wf_trb.h | 39 + .../mt7603_wifi/include/mac/mac_mt/wf_wtbl.h | 547 + .../include/mac/mac_mt/wf_wtbloff.h | 50 + .../include/mac/mac_mt/wf_wtblon.h | 236 + .../src/mt7603_wifi/include/mac/mac_ral/fce.h | 94 + .../mt7603_wifi/include/mac/mac_ral/mac_pci.h | 303 + .../mt7603_wifi/include/mac/mac_ral/mac_usb.h | 518 + .../include/mac/mac_ral/nmac/ral_nmac.h | 1171 + .../include/mac/mac_ral/nmac/ral_nmac_pbf.h | 99 + .../include/mac/mac_ral/nmac/ral_nmac_pci.h | 326 + .../mac/mac_ral/nmac/ral_nmac_rf_ctrl.h | 43 + .../include/mac/mac_ral/nmac/ral_nmac_usb.h | 33 + .../include/mac/mac_ral/omac/ral_omac.h | 348 + .../include/mac/mac_ral/omac/ral_omac_pbf.h | 102 + .../include/mac/mac_ral/omac/ral_omac_pci.h | 233 + .../mac/mac_ral/omac/ral_omac_rf_ctrl.h | 103 + .../include/mac/mac_ral/omac/ral_omac_usb.h | 30 + .../src/mt7603_wifi/include/mac/mac_ral/pbf.h | 86 + .../mt7603_wifi/include/mac/mac_ral/rf_ctrl.h | 151 + .../include/mac/mac_ral/rtmp_mac.h | 2466 ++ .../mt7603e/src/mt7603_wifi/include/map.h | 184 + .../mt7603e/src/mt7603_wifi/include/mat.h | 211 + .../mt7603e/src/mt7603_wifi/include/mbo.h | 296 + .../src/mt7603_wifi/include/mcu/andes_core.h | 281 + .../src/mt7603_wifi/include/mcu/andes_mt.h | 971 + .../src/mt7603_wifi/include/mcu/andes_rlt.h | 319 + .../src/mt7603_wifi/include/mcu/btcoex.h | 344 + .../mt7603e/src/mt7603_wifi/include/mcu/mcu.h | 66 + .../mt7603_wifi/include/mcu/mt7601_firmware.h | 2945 ++ .../include/mcu/mt7603_e2_firmware.h | 4654 +++ .../mt7603_wifi/include/mcu/mt7603_firmware.h | 4014 +++ .../mt7603_wifi/include/mcu/mt7636_firmware.h | 14300 ++++++++ .../include/mcu/mt7636_rom_patch.h | 97 + .../include/mcu/mt7662_rom_patch.h | 731 + .../mt7603e/src/mt7603_wifi/include/misc.h | 32 + .../src/mt7603_wifi/include/misc_cmm.h | 32 + .../src/mt7603_wifi/include/mix_mode.h | 151 + .../mt7603e/src/mt7603_wifi/include/mlme.h | 1545 + .../src/mt7603_wifi/include/mlme_sys.h | 9 + .../mt7603e/src/mt7603_wifi/include/mt_io.h | 22 + .../mt7603e/src/mt7603_wifi/include/mt_ps.h | 57 + .../src/mt7603_wifi/include/mt_tx_pwr.h | 59 + .../src/mt7603_wifi/include/mtsdio_data.h | 33 + .../src/mt7603_wifi/include/mtsdio_io.h | 28 + .../mt7603e/src/mt7603_wifi/include/mwds.h | 81 + .../src/mt7603_wifi/include/netif_block.h | 31 + .../mt7603e/src/mt7603_wifi/include/nfc.h | 46 + .../mt7603e/src/mt7603_wifi/include/oid.h | 2204 ++ .../src/mt7603_wifi/include/os/bb_soc.h | 55 + .../src/mt7603_wifi/include/os/pkt_meta.h | 413 + .../src/mt7603_wifi/include/os/rt_drv.h | 849 + .../src/mt7603_wifi/include/os/rt_linux.h | 1805 + .../src/mt7603_wifi/include/os/rt_linux_cmm.h | 498 + .../include/os/rt_linux_txrx_hook.h | 51 + .../src/mt7603_wifi/include/os/rt_os.h | 92 + .../src/mt7603_wifi/include/os/trace_linux.h | 152 + .../mt7603e/src/mt7603_wifi/include/owe_cmm.h | 92 + .../src/mt7603_wifi/include/phy/mt76x2_rf.h | 143 + .../src/mt7603_wifi/include/phy/mt_bbp.h | 25 + .../src/mt7603_wifi/include/phy/mt_phy.h | 2 + .../src/mt7603_wifi/include/phy/mt_rf.h | 26 + .../mt7603e/src/mt7603_wifi/include/phy/phy.h | 281 + .../src/mt7603_wifi/include/phy/rlt_bbp.h | 340 + .../src/mt7603_wifi/include/phy/rlt_rf.h | 107 + .../src/mt7603_wifi/include/phy/rtmp_bbp.h | 542 + .../src/mt7603_wifi/include/phy/wf_phy_back.h | 186 + .../mt7603e/src/mt7603_wifi/include/pmf.h | 130 + .../mt7603e/src/mt7603_wifi/include/pmf_cmm.h | 86 + .../mt7603e/src/mt7603_wifi/include/radar.h | 100 + .../src/mt7603_wifi/include/routing_tab.h | 468 + .../mt7603e/src/mt7603_wifi/include/rrm.h | 576 + .../mt7603e/src/mt7603_wifi/include/rrm_cmm.h | 206 + .../mt7603e/src/mt7603_wifi/include/rt_cal.h | 86 + .../src/mt7603_wifi/include/rt_config.h | 342 + .../mt7603e/src/mt7603_wifi/include/rt_led.h | 185 + .../src/mt7603_wifi/include/rt_os_net.h | 467 + .../src/mt7603_wifi/include/rt_os_util.h | 695 + .../mt7603e/src/mt7603_wifi/include/rt_txbf.h | 35 + .../mt7603e/src/mt7603_wifi/include/rtmp.h | 10795 ++++++ .../src/mt7603_wifi/include/rtmp_chip.h | 1500 + .../src/mt7603_wifi/include/rtmp_cmd.h | 602 + .../src/mt7603_wifi/include/rtmp_comm.h | 457 + .../src/mt7603_wifi/include/rtmp_def.h | 2447 ++ .../src/mt7603_wifi/include/rtmp_dot11.h | 103 + .../src/mt7603_wifi/include/rtmp_iface.h | 62 + .../mt7603e/src/mt7603_wifi/include/rtmp_os.h | 145 + .../src/mt7603_wifi/include/rtmp_osabl.h | 65 + .../src/mt7603_wifi/include/rtmp_timer.h | 221 + .../src/mt7603_wifi/include/rtmp_type.h | 228 + .../mt7603e/src/mt7603_wifi/include/sae.h | 347 + .../mt7603e/src/mt7603_wifi/include/sae_cmm.h | 2099 ++ .../mt7603_wifi/include/sniffer/radiotap.h | 301 + .../src/mt7603_wifi/include/sniffer/sniffer.h | 171 + .../src/mt7603_wifi/include/sniffer_mib.h | 81 + .../src/mt7603_wifi/include/spectrum.h | 219 + .../src/mt7603_wifi/include/spectrum_def.h | 261 + .../mt7603e/src/mt7603_wifi/include/sta.h | 131 + .../mt7603e/src/mt7603_wifi/include/sta_cfg.h | 63 + .../src/mt7603_wifi/include/tx_power.h | 70 + .../mt7603e/src/mt7603_wifi/include/uapsd.h | 729 + .../mt7603e/src/mt7603_wifi/include/vendor.h | 166 + .../mt7603e/src/mt7603_wifi/include/vht.h | 58 + .../mt7603e/src/mt7603_wifi/include/video.h | 12 + .../src/mt7603_wifi/include/vr_ikans.h | 59 + .../src/mt7603_wifi/include/vrut_ubm.h | 42 + .../mt7603e/src/mt7603_wifi/include/wapi.h | 185 + .../src/mt7603_wifi/include/wapi_def.h | 179 + .../src/mt7603_wifi/include/wapi_sms4.h | 12 + .../mt7603e/src/mt7603_wifi/include/wfa_p2p.h | 37 + .../mt7603e/src/mt7603_wifi/include/wfd.h | 79 + .../mt7603e/src/mt7603_wifi/include/wfd_cmm.h | 79 + .../mt7603e/src/mt7603_wifi/include/wnm.h | 660 + .../mt7603e/src/mt7603_wifi/include/wnm_cmm.h | 54 + .../mt7603e/src/mt7603_wifi/include/wpa.h | 566 + .../mt7603e/src/mt7603_wifi/include/wpa_cmm.h | 240 + .../mt7603e/src/mt7603_wifi/include/wsc.h | 873 + .../mt7603e/src/mt7603_wifi/include/wsc_tlv.h | 282 + .../src/mt7603_wifi/license/MTK_LICENSE | 42 + .../mt7603e/src/mt7603_wifi/license/NOTICE | 124 + .../mt7603e/src/mt7603_wifi/mac/mt_mac.c | 2181 ++ .../mt7603e/src/mt7603_wifi/mac/ral_nmac.c | 407 + .../mt7603e/src/mt7603_wifi/mac/ral_omac.c | 172 + .../mt7603e/src/mt7603_wifi/mac/rtmp_mac.c | 1816 + .../mt7603e/src/mt7603_wifi/mcu/andes_core.c | 891 + .../mt7603e/src/mt7603_wifi/mcu/andes_mt.c | 4324 +++ .../mt7603e/src/mt7603_wifi/mcu/andes_rlt.c | 1766 + .../mt7603_wifi/mcu/bin/MT7601_formal_1.7.bin | Bin 0 -> 47032 bytes .../bin/MT7603_ram_20140305_e2_drv_tv01.bin | Bin 0 -> 56484 bytes .../src/mt7603_wifi/mcu/bin/MT7610.bin | Bin 0 -> 80360 bytes .../src/mt7603_wifi/mcu/bin/MT7650.bin | Bin 0 -> 75228 bytes .../mcu/bin/WIFI_RAM_CODE_MT7603_e1.bin | Bin 0 -> 64132 bytes .../mcu/bin/WIFI_RAM_CODE_MT7603_e2.bin | Bin 0 -> 77020 bytes .../mcu/bin/WIFI_RAM_CODE_MT7636.bin | Bin 0 -> 228712 bytes .../mcu/bin/mt7612_patch_e1_hdr.bin | Bin 0 -> 16038 bytes .../mcu/bin/mt7612_patch_e1_hdr_0417.bin | Bin 0 -> 19778 bytes .../mcu/bin/mt7636_patch_e1_hdr.bin | Bin 0 -> 1470 bytes .../mcu/bin/mt7662_firmware_e3_20131211.bin | Bin 0 -> 88440 bytes .../mcu/bin/mt7662_patch_e3_hdr_v0.0.2_P8.bin | Bin 0 -> 11602 bytes .../mcu/bin/mt7662_patch_release_history.xlsx | Bin 0 -> 16871 bytes .../drivers/mt7603e/src/mt7603_wifi/mcu/mcu.c | 194 + .../mt7603e/src/mt7603_wifi/mgmt/mgmt_dev.c | 116 + .../src/mt7603_wifi/mgmt/mgmt_entrytb.c | 1405 + .../mt7603e/src/mt7603_wifi/mgmt/mgmt_ht.c | 801 + .../mt7603e/src/mt7603_wifi/mgmt/mgmt_hw.c | 66 + .../mt7603e/src/mt7603_wifi/mgmt/mgmt_vht.c | 83 + .../drivers/mt7603e/src/mt7603_wifi/naf/cso.c | 27 + .../mt7603e/src/mt7603_wifi/naf/net_acc.c | 31 + .../drivers/mt7603e/src/mt7603_wifi/naf/tso.c | 27 + .../src/mt7603_wifi/os/linux/Kconfig.ap.soc | 161 + .../src/mt7603_wifi/os/linux/Kconfig.ap.usb | 116 + .../src/mt7603_wifi/os/linux/Kconfig.rlt_wifi | 216 + .../mt7603_wifi/os/linux/Kconfig.rlt_wifi_ap | 89 + .../mt7603_wifi/os/linux/Kconfig.rlt_wifi_sta | 19 + .../src/mt7603_wifi/os/linux/Kconfig.sta.soc | 91 + .../src/mt7603_wifi/os/linux/Kconfig.wifi | 416 + .../src/mt7603_wifi/os/linux/Makefile.4 | 313 + .../src/mt7603_wifi/os/linux/Makefile.4.netif | 103 + .../src/mt7603_wifi/os/linux/Makefile.4.util | 82 + .../src/mt7603_wifi/os/linux/Makefile.6 | 707 + .../src/mt7603_wifi/os/linux/Makefile.6.netif | 97 + .../src/mt7603_wifi/os/linux/Makefile.6.util | 72 + .../src/mt7603_wifi/os/linux/Makefile.ap.soc | 394 + .../src/mt7603_wifi/os/linux/Makefile.ap.usb | 346 + .../src/mt7603_wifi/os/linux/Makefile.clean | 79 + .../os/linux/Makefile.libautoprovision.6 | 9 + .../mt7603_wifi/os/linux/Makefile.libwapi.4 | 23 + .../mt7603_wifi/os/linux/Makefile.libwapi.6 | 11 + .../mt7603_wifi/os/linux/Makefile.rlt_wifi_ap | 693 + .../os/linux/Makefile.rlt_wifi_sta | 514 + .../src/mt7603_wifi/os/linux/Makefile.sta.soc | 275 + .../mt7603_wifi/os/linux/android_priv_cmd.c | 120 + .../src/mt7603_wifi/os/linux/ap_ioctl.c | 494 + .../mt7603e/src/mt7603_wifi/os/linux/bb_soc.c | 190 + .../src/mt7603_wifi/os/linux/br_ftph.c | 194 + .../src/mt7603_wifi/os/linux/config.mk | 1958 ++ .../mt7603_wifi/os/linux/config.mk.cfg80211 | 2653 ++ .../mt7603e/src/mt7603_wifi/os/linux/diag.c | 1471 + .../src/mt7603_wifi/os/linux/inf_ppa.c | 57 + .../mt7603e/src/mt7603_wifi/os/linux/load | 6 + .../src/mt7603_wifi/os/linux/monitor_mode.c | 7 + .../src/mt7603_wifi/os/linux/multi_main_dev.c | 72 + .../src/mt7603_wifi/os/linux/pci_main_dev.c | 489 + .../src/mt7603_wifi/os/linux/rt_linux.c | 4638 +++ .../src/mt7603_wifi/os/linux/rt_linux_symb.c | 281 + .../src/mt7603_wifi/os/linux/rt_main_dev.c | 853 + .../src/mt7603_wifi/os/linux/rt_pci_rbus.c | 83 + .../src/mt7603_wifi/os/linux/rt_proc.c | 539 + .../src/mt7603_wifi/os/linux/rt_profile.c | 2028 ++ .../mt7603_wifi/os/linux/rt_rbus_pci_drv.c | 2008 ++ .../mt7603_wifi/os/linux/rt_rbus_pci_util.c | 518 + .../src/mt7603_wifi/os/linux/rt_sdio.c | 145 + .../src/mt7603_wifi/os/linux/rt_symb.c | 9 + .../src/mt7603_wifi/os/linux/rt_txrx_hook.c | 119 + .../src/mt7603_wifi/os/linux/sdio_main_dev.c | 277 + .../mt7603e/src/mt7603_wifi/os/linux/unload | 2 + .../src/mt7603_wifi/os/linux/vr_bdlt.c | 63 + .../src/mt7603_wifi/os/linux/vr_ikans.c | 301 + .../mt7603e/src/mt7603_wifi/phy/mt76x2_rf.c | 127 + .../mt7603e/src/mt7603_wifi/phy/mt_phy.c | 287 + .../mt7603e/src/mt7603_wifi/phy/mt_rf.c | 54 + .../drivers/mt7603e/src/mt7603_wifi/phy/phy.c | 294 + .../drivers/mt7603e/src/mt7603_wifi/phy/rf.c | 25 + .../mt7603e/src/mt7603_wifi/phy/rlt_phy.c | 550 + .../mt7603e/src/mt7603_wifi/phy/rlt_rf.c | 190 + .../mt7603e/src/mt7603_wifi/phy/rt_rf.c | 343 + .../mt7603e/src/mt7603_wifi/phy/rtmp_phy.c | 886 + .../src/mt7603_wifi/rate_ctrl/alg_ags.c | 1189 + .../src/mt7603_wifi/rate_ctrl/alg_grp.c | 3054 ++ .../src/mt7603_wifi/rate_ctrl/alg_legacy.c | 884 + .../src/mt7603_wifi/rate_ctrl/ra_ctrl.c | 2946 ++ .../src/mt7603_wifi/sniffer/sniffer_prism.c | 256 + .../mt7603_wifi/sniffer/sniffer_radiotap.c | 521 + .../mt7603e/src/mt7603_wifi/tools/Makefile | 6 + .../mt7603e/src/mt7603_wifi/tools/bin2h | Bin 0 -> 29886 bytes .../mt7603e/src/mt7603_wifi/tools/bin2h.c | 357 + .../mt7603e/src/mt7603_wifi/tools/i.sh | 18 + .../src/mt7603_wifi/tools/mt7662_freq_plan.c | 137 + .../src/mt7603_wifi/tools/mt7662e_ap.sh | 4 + .../src/mt7603_wifi/tools/mt7662e_sta.sh | 4 + .../src/mt7603_wifi/tools/plug_in/Makefile | 25 + .../mt7603e/src/mt7603_wifi/tools/r.sh | 2 + .../mt7603e/src/mt7603_wifi/tx_rx/hdr_trans.c | 8 + .../mt7603e/src/mt7603_wifi/tx_rx/txs.c | 814 + .../mt7603e/src/mt7603_wifi/tx_rx/wdev.c | 270 + .../mt7603e/src/mt7603_wifi/tx_rx/wdev_rx.c | 3197 ++ .../mt7603e/src/mt7603_wifi/tx_rx/wdev_tx.c | 199 + .../mt7603e/src/mt7603_wifi_ap/Kconfig | 183 + .../src/mt7603_wifi_ap/Kconfig.mt_wifi_ap | 115 + .../mt7603e/src/mt7603_wifi_ap/Makefile | 1016 + .../src/mt7603_wifi_ap/Makefile.mt_wifi_ap | 772 + package/lean/mt/drivers/mt7615d/Makefile | 225 + package/lean/mt/drivers/mt7615d/config.in | 871 + .../mt/drivers/mt7615d/files/SingleSKU.dat | 65 + .../mt/drivers/mt7615d/files/SingleSKU_BF.dat | 65 + .../lean/mt/drivers/mt7615d/files/firmware.sh | 16 + .../mt/drivers/mt7615d/files/l1profile.dat | 21 + .../mt/drivers/mt7615d/files/mt7615.1.2G.dat | 375 + .../mt/drivers/mt7615d/files/mt7615.1.dat | 327 + .../mt/drivers/mt7615d/files/mt7615.2.dat | 375 + .../lean/mt/drivers/mt7615d/files/mt7615.lua | 219 + .../drivers/mt7615d/files/mt7615e-sku-bf.dat | 65 + .../mt/drivers/mt7615d/files/mt7615e-sku.dat | 65 + .../mt/drivers/mt7615d/files/mt7615e.1.dat | 410 + .../mt/drivers/mt7615d/files/mt7615e.2.dat | 412 + .../drivers/mt7615d/files/mt7615e.eeprom.bin | Bin 0 -> 1024 bytes .../mt/drivers/mt7615d/files/mt7622.1.dat | 412 + .../drivers/mt7615d/files/wifi_services.lua | 98 + .../src/bin/mt7615/MT7615E1_EEPROM.bin | Bin 0 -> 1024 bytes .../mt7615d/src/bin/mt7615/MT7615_cr4.bin | Bin 0 -> 134132 bytes .../bin/mt7615/MT7615_cr4_noReOrdering.bin | Bin 0 -> 122644 bytes .../src/bin/mt7615/MT7615_cr4_plain.bin | Bin 0 -> 59220 bytes .../mt7615/MT7615_cr4_plain_20141024_1.bin | Bin 0 -> 74884 bytes .../MT7615_cr4_plain_20150206_1_asic.bin | Bin 0 -> 98740 bytes .../src/bin/mt7615/WIFI_RAM_CODE_MT7615.bin | Bin 0 -> 453000 bytes .../bin/mt7615/WIFI_RAM_CODE_MT7615_E1.bin | Bin 0 -> 401160 bytes .../bin/mt7615/WIFI_RAM_CODE_MT7615_plain.bin | Bin 0 -> 384728 bytes .../src/bin/mt7615/ePAeLNA/MT7615_EEPROM1.bin | Bin 0 -> 1200 bytes .../src/bin/mt7615/ePAeLNA/MT7615_EEPROM2.bin | Bin 0 -> 1200 bytes .../src/bin/mt7615/ePAeLNA/MT7615_EEPROM3.bin | Bin 0 -> 1200 bytes .../src/bin/mt7615/ePAiLNA/MT7615_EEPROM1.bin | Bin 0 -> 1200 bytes .../src/bin/mt7615/ePAiLNA/MT7615_EEPROM2.bin | Bin 0 -> 1200 bytes .../src/bin/mt7615/ePAiLNA/MT7615_EEPROM3.bin | Bin 0 -> 1200 bytes .../src/bin/mt7615/iPAeLNA/MT7615_EEPROM1.bin | Bin 0 -> 1024 bytes .../src/bin/mt7615/iPAeLNA/MT7615_EEPROM2.bin | Bin 0 -> 1024 bytes .../src/bin/mt7615/iPAeLNA/MT7615_EEPROM3.bin | Bin 0 -> 1024 bytes .../src/bin/mt7615/iPAiLNA/MT7615_EEPROM1.bin | Bin 0 -> 1024 bytes .../src/bin/mt7615/iPAiLNA/MT7615_EEPROM2.bin | Bin 0 -> 1024 bytes .../src/bin/mt7615/iPAiLNA/MT7615_EEPROM3.bin | Bin 0 -> 1024 bytes .../src/bin/mt7615/mt7615_patch_e3_hdr.bin | Bin 0 -> 11102 bytes .../mt7615d/src/bin/mt7622/MT7622_EEPROM.bin | Bin 0 -> 1024 bytes .../bin/mt7622/WIFI_RAM_CODE_MT7622_E2.bin | Bin 0 -> 296888 bytes .../src/bin/mt7622/ePAeLNA/MT7622_EEPROM.bin | Bin 0 -> 1024 bytes .../src/bin/mt7622/iPAeLNA/MT7622_EEPROM.bin | Bin 0 -> 1024 bytes .../src/bin/mt7622/iPAiLNA/MT7622_EEPROM.bin | Bin 0 -> 1024 bytes .../src/bin/mt7622/mt7622_patch_e2_hdr.bin | Bin 0 -> 82110 bytes .../mt7615d/src/mt_wifi/ate/LoopBack.c | 624 + .../mt7615d/src/mt_wifi/ate/ate_agent.c | 6174 ++++ .../src/mt_wifi/ate/include/LoopBack.h | 99 + .../mt7615d/src/mt_wifi/ate/include/ate.h | 681 + .../src/mt_wifi/ate/include/ate_agent.h | 161 + .../src/mt_wifi/ate/include/meta_agent.h | 93 + .../src/mt_wifi/ate/include/mt_testmode.h | 210 + .../mt_wifi/ate/include/mt_testmode_dmac.h | 27 + .../mt_wifi/ate/include/mt_testmode_smac.h | 25 + .../src/mt_wifi/ate/include/qa_agent.h | 83 + .../src/mt_wifi/ate/include/testmode_common.h | 47 + .../src/mt_wifi/ate/include/testmode_ioctl.h | 524 + .../mt7615d/src/mt_wifi/ate/meta_agent.c | 2131 ++ .../mt7615d/src/mt_wifi/ate/mt_mac/mt_ate.c | 1379 + .../src/mt_wifi/ate/mt_mac/mt_testmode.c | 8003 +++++ .../src/mt_wifi/ate/mt_mac/mt_testmode_dmac.c | 214 + .../src/mt_wifi/ate/mt_mac/mt_testmode_smac.c | 56 + .../mt7615d/src/mt_wifi/ate/qa_agent.c | 1806 + .../mt7615d/src/mt_wifi/ate/testmode_ioctl.c | 7071 ++++ .../mt7615d/src/mt_wifi/chips/mt7615.c | 3144 ++ .../mt7615d/src/mt_wifi/chips/mt7615_dbg.c | 1154 + .../mt7615d/src/mt_wifi/chips/mt7622.c | 2298 ++ .../mt7615d/src/mt_wifi/chips/mt7622_dbg.c | 1333 + .../mt7615d/src/mt_wifi/chips/rtmp_chip.c | 255 + .../mt7615d/src/mt_wifi/embedded/Kconfig | 546 + .../mt7615d/src/mt_wifi/embedded/Makefile | 597 + .../src/mt_wifi/embedded/Pack_Release.sh | 92 + .../mt7615d/src/mt_wifi/embedded/Release.sh | 134 + .../src/mt_wifi/embedded/Release_Notes.txt | 97 + .../mt7615d/src/mt_wifi/embedded/ap/ap.c | 4453 +++ .../src/mt_wifi/embedded/ap/ap_apcli.c | 6032 ++++ .../src/mt_wifi/embedded/ap/ap_apcli_inf.c | 180 + .../src/mt_wifi/embedded/ap/ap_assoc.c | 3145 ++ .../mt7615d/src/mt_wifi/embedded/ap/ap_auth.c | 1236 + .../src/mt_wifi/embedded/ap/ap_autoChSel.c | 3266 ++ .../mt_wifi/embedded/ap/ap_band_steering.c | 2328 ++ .../mt7615d/src/mt_wifi/embedded/ap/ap_cfg.c | 19290 +++++++++++ .../mt7615d/src/mt_wifi/embedded/ap/ap_data.c | 4404 +++ .../mt7615d/src/mt_wifi/embedded/ap/ap_ftkd.c | 1629 + .../mt7615d/src/mt_wifi/embedded/ap/ap_ids.c | 461 + .../mt7615d/src/mt_wifi/embedded/ap/ap_mbss.c | 348 + .../src/mt_wifi/embedded/ap/ap_mbss_inf.c | 186 + .../mt7615d/src/mt_wifi/embedded/ap/ap_mlme.c | 768 + .../src/mt_wifi/embedded/ap/ap_mumimo.c | 4695 +++ .../mt7615d/src/mt_wifi/embedded/ap/ap_mura.c | 2090 ++ .../mt7615d/src/mt_wifi/embedded/ap/ap_nps.c | 276 + .../src/mt_wifi/embedded/ap/ap_qload.c | 941 + .../src/mt_wifi/embedded/ap/ap_repeater.c | 1511 + .../src/mt_wifi/embedded/ap/ap_sanity.c | 30 + .../mt7615d/src/mt_wifi/embedded/ap/ap_sec.c | 809 + .../mt7615d/src/mt_wifi/embedded/ap/ap_sync.c | 2697 ++ .../mt7615d/src/mt_wifi/embedded/ap/ap_vow.c | 4473 +++ .../mt7615d/src/mt_wifi/embedded/ap/ap_wds.c | 1832 + .../src/mt_wifi/embedded/ap/ap_wds_inf.c | 111 + .../mt7615d/src/mt_wifi/embedded/ap/ap_wpa.c | 216 + .../src/mt_wifi/embedded/ap/apcli_assoc.c | 1611 + .../src/mt_wifi/embedded/ap/apcli_auth.c | 982 + .../src/mt_wifi/embedded/ap/apcli_ctrl.c | 2552 ++ .../mt_wifi/embedded/ap/apcli_link_cover.c | 136 + .../src/mt_wifi/embedded/ap/apcli_sync.c | 1549 + .../src/mt_wifi/embedded/common/a4_conn.c | 780 + .../src/mt_wifi/embedded/common/action.c | 1448 + .../src/mt_wifi/embedded/common/ba_action.c | 2009 ++ .../mt7615d/src/mt_wifi/embedded/common/bcn.c | 1930 ++ .../src/mt_wifi/embedded/common/bgnd_scan.c | 1482 + .../src/mt_wifi/embedded/common/client_wds.c | 323 + .../src/mt_wifi/embedded/common/cmm_cfg.c | 7123 ++++ .../src/mt_wifi/embedded/common/cmm_cmd.c | 621 + .../src/mt_wifi/embedded/common/cmm_cs.c | 745 + .../src/mt_wifi/embedded/common/cmm_data.c | 8117 +++++ .../src/mt_wifi/embedded/common/cmm_info.c | 14745 ++++++++ .../embedded/common/cmm_info_element.c | 396 + .../src/mt_wifi/embedded/common/cmm_mac_pci.c | 2453 ++ .../src/mt_wifi/embedded/common/cmm_mat.c | 443 + .../mt_wifi/embedded/common/cmm_mat_iparp.c | 765 + .../mt_wifi/embedded/common/cmm_mat_ipv6.c | 762 + .../mt_wifi/embedded/common/cmm_mat_pppoe.c | 966 + .../src/mt_wifi/embedded/common/cmm_mumimo.c | 237 + .../src/mt_wifi/embedded/common/cmm_profile.c | 7338 ++++ .../src/mt_wifi/embedded/common/cmm_radar.c | 885 + .../src/mt_wifi/embedded/common/cmm_rdm_mt.c | 5037 +++ .../src/mt_wifi/embedded/common/cmm_rf_cal.c | 2659 ++ .../src/mt_wifi/embedded/common/cmm_rvr_dbg.c | 737 + .../src/mt_wifi/embedded/common/cmm_sanity.c | 1696 + .../src/mt_wifi/embedded/common/cmm_sync.c | 1150 + .../src/mt_wifi/embedded/common/cmm_tcprack.c | 1304 + .../src/mt_wifi/embedded/common/cmm_txbf.c | 1209 + .../src/mt_wifi/embedded/common/cmm_video.c | 154 + .../src/mt_wifi/embedded/common/cut_through.c | 908 + .../src/mt_wifi/embedded/common/ee_efuse.c | 1319 + .../src/mt_wifi/embedded/common/ee_flash.c | 540 + .../src/mt_wifi/embedded/common/ee_prom.c | 212 + .../src/mt_wifi/embedded/common/eeprom.c | 1558 + .../src/mt_wifi/embedded/common/fp_fair_qm.c | 399 + .../src/mt_wifi/embedded/common/fp_qm.c | 352 + .../src/mt_wifi/embedded/common/fpga.c | 34 + .../src/mt_wifi/embedded/common/fq_qm.c | 1597 + .../mt7615d/src/mt_wifi/embedded/common/ft.c | 3117 ++ .../src/mt_wifi/embedded/common/ft_iocl.c | 1129 + .../src/mt_wifi/embedded/common/ft_rc.c | 341 + .../src/mt_wifi/embedded/common/ft_tlv.c | 193 + .../mt7615d/src/mt_wifi/embedded/common/ftm.c | 3691 ++ .../mt7615d/src/mt_wifi/embedded/common/gas.c | 1179 + .../src/mt_wifi/embedded/common/hif_pci.c | 3037 ++ .../src/mt_wifi/embedded/common/hotspot.c | 1031 + .../src/mt_wifi/embedded/common/icap.c | 83 + .../src/mt_wifi/embedded/common/igmp_snoop.c | 3111 ++ .../mt7615d/src/mt_wifi/embedded/common/map.c | 471 + .../mt7615d/src/mt_wifi/embedded/common/mbo.c | 1114 + .../src/mt_wifi/embedded/common/misc_app.c | 173 + .../src/mt_wifi/embedded/common/mlme.c | 5294 +++ .../src/mt_wifi/embedded/common/mt_io.c | 205 + .../src/mt_wifi/embedded/common/mt_ps.c | 168 + .../mt_wifi/embedded/common/multi_channel.c | 87 + .../mt_wifi/embedded/common/multi_profile.c | 2318 ++ .../src/mt_wifi/embedded/common/netif_block.c | 87 + .../mt7615d/src/mt_wifi/embedded/common/nfc.c | 24 + .../src/mt_wifi/embedded/common/op_class.c | 819 + .../mt7615d/src/mt_wifi/embedded/common/ps.c | 231 + .../mt7615d/src/mt_wifi/embedded/common/qm.c | 1895 ++ .../mt_wifi/embedded/common/ra_ac_q_mgmt.c | 631 + .../src/mt_wifi/embedded/common/ral_ps.c | 201 + .../src/mt_wifi/embedded/common/routing_tab.c | 626 + .../mt7615d/src/mt_wifi/embedded/common/rrm.c | 2528 ++ .../src/mt_wifi/embedded/common/rrm_sanity.c | 167 + .../src/mt_wifi/embedded/common/rrm_tlv.c | 1201 + .../src/mt_wifi/embedded/common/rt_channel.c | 2233 ++ .../src/mt_wifi/embedded/common/rt_led.c | 534 + .../src/mt_wifi/embedded/common/rt_os_util.c | 284 + .../src/mt_wifi/embedded/common/rtmp_init.c | 2669 ++ .../mt_wifi/embedded/common/rtmp_init_inf.c | 974 + .../src/mt_wifi/embedded/common/rtmp_timer.c | 371 + .../src/mt_wifi/embedded/common/scan.c | 916 + .../mt7615d/src/mt_wifi/embedded/common/scs.c | 469 + .../src/mt_wifi/embedded/common/smartant.c | 3809 +++ .../mt_wifi/embedded/common/sniffer_prism.c | 250 + .../embedded/common/sniffer_radiotap.c | 1200 + .../src/mt_wifi/embedded/common/spectrum.c | 2772 ++ .../src/mt_wifi/embedded/common/sys_log.c | 257 + .../src/mt_wifi/embedded/common/txpower.c | 630 + .../mt7615d/src/mt_wifi/embedded/common/txs.c | 470 + .../src/mt_wifi/embedded/common/uapsd.c | 2116 ++ .../src/mt_wifi/embedded/common/vendor.c | 695 + .../src/mt_wifi/embedded/common/verf.c | 29 + .../mt7615d/src/mt_wifi/embedded/common/vht.c | 1172 + .../src/mt_wifi/embedded/common/wdev.c | 926 + .../mt_wifi/embedded/common/wifi_sys_info.c | 1233 + .../mt_wifi/embedded/common/wifi_sys_notify.c | 114 + .../mt7615d/src/mt_wifi/embedded/common/wnm.c | 3606 ++ .../mt7615d/src/mt_wifi/embedded/common/wsc.c | 10490 ++++++ .../src/mt_wifi/embedded/common/wsc_tlv.c | 4085 +++ .../src/mt_wifi/embedded/common/wsc_ufd.c | 575 + .../src/mt_wifi/embedded/common/wsc_v2.c | 424 + .../mt7615d/src/mt_wifi/embedded/doc/Doxyfile | 2331 ++ .../mt_wifi/embedded/doc/FirmwareHistory.txt | 53 + .../src/mt_wifi/embedded/doc/History.txt | 325 + .../mt_wifi/embedded/doc/History_sta_pci.txt | 255 + .../mt_wifi/embedded/doc/History_sta_usb.txt | 258 + .../mt7615d/src/mt_wifi/embedded/doc/README | 68 + .../src/mt_wifi/embedded/doc/README_STA_pci | 528 + .../src/mt_wifi/embedded/doc/README_STA_usb | 534 + .../mt_wifi/embedded/doc/RT2860card.readme | 84 + .../RT_WIFI_Revision_History_2010_April.xls | Bin 0 -> 123904 bytes .../src/mt_wifi/embedded/doc/VxWorks.README | 4 + .../mt_wifi/embedded/doc/ate_iwpriv_usage.txt | 444 + .../src/mt_wifi/embedded/doc/brftph_usage.txt | 68 + .../embedded/doc/header_translation.txt | 84 + .../src/mt_wifi/embedded/doc/iwpriv_usage.txt | 447 + .../src/mt_wifi/embedded/doc/mainpage.dox | 8 + .../src/mt_wifi/embedded/doc/mbss_phy.readme | 65 + .../embedded/doc/sta_ate_iwpriv_usage.txt | 445 + .../mt_wifi/embedded/doc/wps_iwpriv_usage.txt | 173 + .../embedded/hw_ctrl/hdev/hdev_basic.c | 266 + .../mt_wifi/embedded/hw_ctrl/hdev/omac_ctrl.c | 256 + .../embedded/hw_ctrl/hdev/radio_ctrl.c | 1103 + .../mt_wifi/embedded/hw_ctrl/hdev/wmm_ctrl.c | 308 + .../mt_wifi/embedded/hw_ctrl/hdev/wtbl_ctrl.c | 352 + .../src/mt_wifi/embedded/hw_ctrl/hdev_ctrl.c | 1673 + .../src/mt_wifi/embedded/hw_ctrl/hw_ctrl.c | 1555 + .../mt_wifi/embedded/hw_ctrl/hw_ctrl_basic.c | 639 + .../mt_wifi/embedded/hw_ctrl/hw_ctrl_cmd.c | 860 + .../mt_wifi/embedded/hw_ctrl/hw_ctrl_ops_v1.c | 300 + .../mt_wifi/embedded/hw_ctrl/hw_ctrl_ops_v2.c | 279 + .../src/mt_wifi/embedded/include/a4_conn.h | 143 + .../src/mt_wifi/embedded/include/action.h | 94 + .../src/mt_wifi/embedded/include/ags.h | 102 + .../mt7615d/src/mt_wifi/embedded/include/ap.h | 481 + .../src/mt_wifi/embedded/include/ap_apcli.h | 400 + .../mt_wifi/embedded/include/ap_autoChSel.h | 208 + .../embedded/include/ap_autoChSel_cmm.h | 180 + .../src/mt_wifi/embedded/include/ap_cfg.h | 311 + .../src/mt_wifi/embedded/include/ap_ids.h | 72 + .../src/mt_wifi/embedded/include/ap_mbss.h | 76 + .../src/mt_wifi/embedded/include/ap_mumimo.h | 894 + .../src/mt_wifi/embedded/include/ap_mura.h | 494 + .../mt_wifi/embedded/include/ap_repeater.h | 156 + .../src/mt_wifi/embedded/include/ap_vow.h | 798 + .../src/mt_wifi/embedded/include/ap_wds.h | 168 + .../mt_wifi/embedded/include/arris_mod_api.h | 74 + .../embedded/include/arris_wps_gpio_handler.h | 40 + .../mt_wifi/embedded/include/band_steering.h | 109 + .../embedded/include/band_steering_def.h | 377 + .../src/mt_wifi/embedded/include/bcn.h | 115 + .../src/mt_wifi/embedded/include/bgnd_scan.h | 69 + .../mt_wifi/embedded/include/bgnd_scan_cmm.h | 203 + .../src/mt_wifi/embedded/include/br_ftph.h | 81 + .../src/mt_wifi/embedded/include/cfg80211.h | 98 + .../mt_wifi/embedded/include/cfg80211_cmm.h | 188 + .../mt_wifi/embedded/include/cfg80211extr.h | 454 + .../src/mt_wifi/embedded/include/chlist.h | 160 + .../src/mt_wifi/embedded/include/client_wds.h | 73 + .../mt_wifi/embedded/include/client_wds_cmm.h | 51 + .../src/mt_wifi/embedded/include/cmm_cmd.h | 178 + .../mt_wifi/embedded/include/cmm_rvr_dbg.h | 76 + .../mt_wifi/embedded/include/cmm_tcprack.h | 199 + .../mt7615d/src/mt_wifi/embedded/include/cs.h | 118 + .../mt_wifi/embedded/include/cut_through.h | 210 + .../src/mt_wifi/embedded/include/dot11_base.h | 169 + .../mt_wifi/embedded/include/dot11ac_vht.h | 677 + .../src/mt_wifi/embedded/include/dot11k_rrm.h | 365 + .../src/mt_wifi/embedded/include/dot11n_ht.h | 353 + .../src/mt_wifi/embedded/include/dot11r_ft.h | 328 + .../embedded/include/dot11u_interworking.h | 117 + .../src/mt_wifi/embedded/include/dot11v_wnm.h | 105 + .../src/mt_wifi/embedded/include/eeprom.h | 851 + .../include/eeprom/mt7615_e2p_ePAeLNA.h | 243 + .../include/eeprom/mt7615_e2p_ePAiLNA.h | 243 + .../include/eeprom/mt7615_e2p_iPAeLNA.h | 210 + .../include/eeprom/mt7615_e2p_iPAiLNA.h | 210 + .../include/eeprom/mt7622_e2p_ePAeLNA.h | 70 + .../include/eeprom/mt7622_e2p_iPAeLNA.h | 70 + .../include/eeprom/mt7622_e2p_iPAiLNA.h | 70 + .../embedded/include/eeprom/mt7663_e2p.h | 70 + .../embedded/include/eeprom/mt_dmac_e2p_def.h | 61 + .../embedded/include/eeprom/mt_e2p_def.h | 430 + .../src/mt_wifi/embedded/include/efuse.h | 86 + .../mt_wifi/embedded/include/event_common.h | 154 + .../src/mt_wifi/embedded/include/firmware.h | 518 + .../src/mt_wifi/embedded/include/fp_qm.h | 32 + .../src/mt_wifi/embedded/include/fq_qm.h | 150 + .../src/mt_wifi/embedded/include/frame_hdr.h | 84 + .../src/mt_wifi/embedded/include/frq_cal.h | 71 + .../mt_wifi/embedded/include/fsm/fsm_sync.h | 43 + .../mt7615d/src/mt_wifi/embedded/include/ft.h | 1275 + .../src/mt_wifi/embedded/include/ft_cmm.h | 247 + .../src/mt_wifi/embedded/include/ftm.h | 286 + .../src/mt_wifi/embedded/include/ftm_cmm.h | 574 + .../src/mt_wifi/embedded/include/gas.h | 223 + .../src/mt_wifi/embedded/include/hdev/hdev.h | 108 + .../embedded/include/hdev/hdev_basic.h | 167 + .../src/mt_wifi/embedded/include/hdev_ctrl.h | 186 + .../src/mt_wifi/embedded/include/hotspot.h | 252 + .../src/mt_wifi/embedded/include/hw_ctrl.h | 697 + .../mt_wifi/embedded/include/hw_ctrl_basic.h | 22 + .../src/mt_wifi/embedded/include/icap.h | 285 + .../mt_wifi/embedded/include/iface/iface.h | 13 + .../embedded/include/iface/iface_util.h | 48 + .../mt_wifi/embedded/include/iface/mtk_hif.h | 64 + .../embedded/include/iface/rtmp_inf_pcirbs.h | 145 + .../mt_wifi/embedded/include/iface/rtmp_pci.h | 100 + .../mt_wifi/embedded/include/iface/rtmp_rbs.h | 114 + .../src/mt_wifi/embedded/include/igmp_snoop.h | 263 + .../src/mt_wifi/embedded/include/ipv6.h | 190 + .../src/mt_wifi/embedded/include/l1profile.h | 88 + .../src/mt_wifi/embedded/include/map.h | 211 + .../src/mt_wifi/embedded/include/mat.h | 209 + .../src/mt_wifi/embedded/include/mbo.h | 323 + .../mt_wifi/embedded/include/mcu/andes_core.h | 221 + .../mt_wifi/embedded/include/mcu/andes_mt.h | 266 + .../src/mt_wifi/embedded/include/mcu/btcoex.h | 232 + .../src/mt_wifi/embedded/include/mcu/mcu.h | 71 + .../include/mcu/mt7615_cr4_firmware.h | 7672 +++++ .../embedded/include/mcu/mt7615_firmware.h | 28319 ++++++++++++++++ .../embedded/include/mcu/mt7615_firmware_e1.h | 25079 ++++++++++++++ .../embedded/include/mcu/mt7615_rom_patch.h | 700 + .../include/mcu/mt7615_rom_patch_e1.h | 335 + .../embedded/include/mcu/mt7622_firmware.h | 18362 ++++++++++ .../embedded/include/mcu/mt7622_firmware_e2.h | 18562 ++++++++++ .../include/mcu/mt7622_rom_patch_e2.h | 5138 +++ .../mt_wifi/embedded/include/meminfo_list.h | 267 + .../mt_wifi/embedded/include/mgmt/be_export.h | 273 + .../embedded/include/mgmt/be_internal.h | 102 + .../src/mt_wifi/embedded/include/misc_app.h | 108 + .../src/mt_wifi/embedded/include/mlme.h | 1692 + .../src/mt_wifi/embedded/include/mlme_sys.h | 9 + .../src/mt_wifi/embedded/include/mt_io.h | 25 + .../src/mt_wifi/embedded/include/mt_rdm.h | 894 + .../mt_wifi/embedded/include/netif_block.h | 30 + .../src/mt_wifi/embedded/include/nfc.h | 46 + .../src/mt_wifi/embedded/include/oid.h | 2381 ++ .../src/mt_wifi/embedded/include/oid_struct.h | 163 + .../mt7615d/src/mt_wifi/embedded/include/qm.h | 222 + .../mt_wifi/embedded/include/ra_ac_q_mgmt.h | 178 + .../src/mt_wifi/embedded/include/radar.h | 198 + .../mt_wifi/embedded/include/routing_tab.h | 160 + .../src/mt_wifi/embedded/include/rrm.h | 600 + .../src/mt_wifi/embedded/include/rrm_cmm.h | 206 + .../src/mt_wifi/embedded/include/rt_cal.h | 86 + .../src/mt_wifi/embedded/include/rt_config.h | 396 + .../src/mt_wifi/embedded/include/rt_led.h | 236 + .../src/mt_wifi/embedded/include/rt_os_net.h | 756 + .../src/mt_wifi/embedded/include/rt_os_util.h | 870 + .../src/mt_wifi/embedded/include/rt_txbf.h | 262 + .../src/mt_wifi/embedded/include/rt_udma.h | 25 + .../src/mt_wifi/embedded/include/rtmp.h | 12320 +++++++ .../src/mt_wifi/embedded/include/rtmp_chip.h | 529 + .../src/mt_wifi/embedded/include/rtmp_cmd.h | 894 + .../src/mt_wifi/embedded/include/rtmp_comm.h | 442 + .../src/mt_wifi/embedded/include/rtmp_def.h | 2437 ++ .../src/mt_wifi/embedded/include/rtmp_dmacb.h | 35 + .../src/mt_wifi/embedded/include/rtmp_dot11.h | 109 + .../src/mt_wifi/embedded/include/rtmp_iface.h | 62 + .../src/mt_wifi/embedded/include/rtmp_os.h | 159 + .../src/mt_wifi/embedded/include/rtmp_osabl.h | 67 + .../src/mt_wifi/embedded/include/rtmp_timer.h | 252 + .../src/mt_wifi/embedded/include/rtmp_type.h | 222 + .../src/mt_wifi/embedded/include/scs.h | 142 + .../mt_wifi/embedded/include/security/bn.h | 646 + .../embedded/include/security/crypt_aes.h | 185 + .../embedded/include/security/crypt_arc4.h | 66 + .../include/security/crypt_biginteger.h | 416 + .../embedded/include/security/crypt_bignum.h | 231 + .../embedded/include/security/crypt_dh.h | 74 + .../embedded/include/security/crypt_hmac.h | 103 + .../embedded/include/security/crypt_md5.h | 74 + .../embedded/include/security/crypt_sha2.h | 147 + .../embedded/include/security/dh_key.h | 19 + .../embedded/include/security/dot11i_wpa.h | 314 + .../embedded/include/security/dot11w_pmf.h | 107 + .../mt_wifi/embedded/include/security/ecc.h | 149 + .../embedded/include/security/owe_cmm.h | 94 + .../mt_wifi/embedded/include/security/pmf.h | 126 + .../embedded/include/security/pmf_cmm.h | 96 + .../mt_wifi/embedded/include/security/sae.h | 347 + .../embedded/include/security/sae_cmm.h | 2100 ++ .../mt_wifi/embedded/include/security/sec.h | 228 + .../embedded/include/security/sec_cmm.h | 478 + .../mt_wifi/embedded/include/security/wpa.h | 700 + .../embedded/include/security/wpa_cmm.h | 242 + .../src/mt_wifi/embedded/include/smartant.h | 102 + .../embedded/include/sniffer/radiotap.h | 308 + .../embedded/include/sniffer/sniffer.h | 351 + .../src/mt_wifi/embedded/include/spectrum.h | 271 + .../mt_wifi/embedded/include/spectrum_def.h | 250 + .../src/mt_wifi/embedded/include/sta.h | 147 + .../src/mt_wifi/embedded/include/sta_cfg.h | 61 + .../mt7615d/src/mt_wifi/embedded/include/tm.h | 52 + .../mt7615d/src/mt_wifi/embedded/include/tr.h | 141 + .../src/mt_wifi/embedded/include/tx_power.h | 66 + .../src/mt_wifi/embedded/include/uapsd.h | 728 + .../src/mt_wifi/embedded/include/vendor.h | 160 + .../src/mt_wifi/embedded/include/vht.h | 79 + .../src/mt_wifi/embedded/include/video.h | 12 + .../src/mt_wifi/embedded/include/vr_ikans.h | 54 + .../src/mt_wifi/embedded/include/vrut_ubm.h | 42 + .../src/mt_wifi/embedded/include/wapp/wapp.h | 195 + .../embedded/include/wapp/wapp_cmm_type.h | 542 + .../src/mt_wifi/embedded/include/wfa_p2p.h | 174 + .../embedded/include/wifi_sys_notify.h | 38 + .../include/wlan_config/config_export.h | 152 + .../include/wlan_config/config_internal.h | 49 + .../src/mt_wifi/embedded/include/wnm.h | 465 + .../src/mt_wifi/embedded/include/wnm_cmm.h | 30 + .../src/mt_wifi/embedded/include/wsc.h | 909 + .../src/mt_wifi/embedded/include/wsc_tlv.h | 285 + .../src/mt_wifi/embedded/mcu/andes_core.c | 944 + .../src/mt_wifi/embedded/mcu/andes_mt.c | 4315 +++ .../mt7615d/src/mt_wifi/embedded/mcu/mcu.c | 151 + .../src/mt_wifi/embedded/mgmt/be_basic.c | 177 + .../mt7615d/src/mt_wifi/embedded/mgmt/be_ht.c | 564 + .../src/mt_wifi/embedded/mgmt/be_phy.c | 493 + .../src/mt_wifi/embedded/mgmt/be_vht.c | 94 + .../src/mt_wifi/embedded/mgmt/bss_ops.c | 1192 + .../src/mt_wifi/embedded/mgmt/mgmt_dev.c | 117 + .../src/mt_wifi/embedded/mgmt/mgmt_entrytb.c | 1619 + .../src/mt_wifi/embedded/mgmt/mgmt_ht.c | 1029 + .../src/mt_wifi/embedded/mgmt/mgmt_hw.c | 28 + .../src/mt_wifi/embedded/mgmt/mgmt_vht.c | 109 + .../src/mt_wifi/embedded/plug_in/Makefile | 15 + .../mt_wifi/embedded/plug_in/whnat/Makefile | 26 + .../src/mt_wifi/embedded/plug_in/whnat/wdma.c | 300 + .../src/mt_wifi/embedded/plug_in/whnat/wdma.h | 232 + .../src/mt_wifi/embedded/plug_in/whnat/wed.c | 1090 + .../src/mt_wifi/embedded/plug_in/whnat/wed.h | 241 + .../mt_wifi/embedded/plug_in/whnat/wed_def.h | 508 + .../src/mt_wifi/embedded/plug_in/whnat/woe.h | 87 + .../embedded/plug_in/whnat/woe_basic.c | 129 + .../embedded/plug_in/whnat/woe_basic.h | 184 + .../mt_wifi/embedded/plug_in/whnat/woe_hif.c | 137 + .../mt_wifi/embedded/plug_in/whnat/woe_hif.h | 95 + .../mt_wifi/embedded/plug_in/whnat/woe_hw.c | 1481 + .../mt_wifi/embedded/plug_in/whnat/woe_hw.h | 97 + .../mt_wifi/embedded/plug_in/whnat/woe_main.c | 877 + .../embedded/plug_in/whnat/woe_mt7615.c | 447 + .../embedded/plug_in/whnat/woe_mt7615.h | 83 + .../mt_wifi/embedded/plug_in/whnat/woe_proc.c | 780 + .../mt_wifi/embedded/plug_in/whnat/woe_ser.c | 318 + .../mt_wifi/embedded/plug_in/whnat/woe_wifi.h | 66 + .../src/mt_wifi/embedded/security/bn_lib.c | 6980 ++++ .../src/mt_wifi/embedded/security/cmm_aes.c | 1073 + .../src/mt_wifi/embedded/security/cmm_sec.c | 1915 ++ .../src/mt_wifi/embedded/security/cmm_tkip.c | 863 + .../src/mt_wifi/embedded/security/cmm_wep.c | 351 + .../src/mt_wifi/embedded/security/cmm_wpa.c | 5995 ++++ .../src/mt_wifi/embedded/security/crypt_aes.c | 1625 + .../mt_wifi/embedded/security/crypt_arc4.c | 130 + .../embedded/security/crypt_biginteger.c | 3342 ++ .../mt_wifi/embedded/security/crypt_bignum.c | 553 + .../src/mt_wifi/embedded/security/crypt_dh.c | 229 + .../mt_wifi/embedded/security/crypt_hmac.c | 506 + .../src/mt_wifi/embedded/security/crypt_md5.c | 347 + .../mt_wifi/embedded/security/crypt_sha2.c | 843 + .../src/mt_wifi/embedded/security/dh_key.c | 4954 +++ .../src/mt_wifi/embedded/security/ecc.c | 1177 + .../src/mt_wifi/embedded/security/owe.c | 593 + .../src/mt_wifi/embedded/security/pmf.c | 1579 + .../src/mt_wifi/embedded/security/sae.c | 2769 ++ .../src/mt_wifi/embedded/tools/Makefile | 4 + .../embedded/tools/auto_build_kernel_4_4.sh | 153 + .../mt7615d/src/mt_wifi/embedded/tools/bin2h | Bin 0 -> 31443 bytes .../src/mt_wifi/embedded/tools/bin2h.c | 482 + .../embedded/tools/build-check-jedi.sh | 55 + .../embedded/tools/check_build_script.sh | 53 + .../mt7615d/src/mt_wifi/embedded/tools/i.sh | 18 + .../mt_wifi/embedded/tools/mt7662_freq_plan.c | 132 + .../src/mt_wifi/embedded/tools/mt7662e_ap.sh | 4 + .../src/mt_wifi/embedded/tools/mt7662e_sta.sh | 4 + .../mt7615d/src/mt_wifi/embedded/tools/r.sh | 2 + .../mt7615d/src/mt_wifi/embedded/unload | 3 + .../mt7615d/src/mt_wifi/embedded/wapp/wapp.c | 2089 ++ .../embedded/wlan_config/config_basic.c | 240 + .../mt_wifi/embedded/wlan_config/config_ht.c | 367 + .../mt_wifi/embedded/wlan_config/config_phy.c | 169 + .../mt_wifi/embedded/wlan_config/config_vht.c | 147 + .../mt7615d/src/mt_wifi/hw_ctrl/cmm_asic.c | 2830 ++ .../mt7615d/src/mt_wifi/hw_ctrl/cmm_asic_mt.c | 5160 +++ .../src/mt_wifi/hw_ctrl/cmm_asic_mt_dmac.c | 3829 +++ .../src/mt_wifi/hw_ctrl/cmm_asic_mt_fw.c | 1491 + .../mt7615d/src/mt_wifi/hw_ctrl/cmm_chip.c | 386 + .../mt7615d/src/mt_wifi/hw_ctrl/cmm_chip_mt.c | 789 + .../mt7615d/src/mt_wifi/hw_ctrl/coex.c | 26 + .../mt7615d/src/mt_wifi/hw_ctrl/greenap.c | 728 + .../mt7615d/src/mt_wifi/hw_ctrl/hw_init.c | 422 + .../mt7615d/src/mt_wifi/hw_ctrl/mt_gpio.c | 360 + .../src/mt_wifi/include/chip/chip_id.h | 93 + .../mt7615d/src/mt_wifi/include/chip/mt7615.h | 139 + .../src/mt_wifi/include/chip/mt7615_cr.h | 122 + .../mt7615d/src/mt_wifi/include/chip/mt7622.h | 336 + .../src/mt_wifi/include/chip/mt7622_cr.h | 106 + .../src/mt_wifi/include/chip/mt7663_cr.h | 85 + .../mt7615d/src/mt_wifi/include/chip/p18_cr.h | 85 + .../src/mt_wifi/include/common/debug.h | 166 + .../src/mt_wifi/include/common/link_list.h | 179 + .../src/mt_wifi/include/common/module.h | 140 + .../src/mt_wifi/include/common/mt_os_util.h | 149 + .../mt_wifi/include/common/wifi_sys_info.h | 260 + .../src/mt_wifi/include/eeprom/mt_tx_pwr.h | 220 + .../mt7615d/src/mt_wifi/include/hif/hif.h | 59 + .../src/mt_wifi/include/hif/mt_hif_pci.h | 1017 + .../src/mt_wifi/include/hw_ctrl/cmm_asic.h | 633 + .../src/mt_wifi/include/hw_ctrl/cmm_asic_mt.h | 677 + .../mt_wifi/include/hw_ctrl/cmm_asic_mt_fw.h | 157 + .../src/mt_wifi/include/hw_ctrl/cmm_chip.h | 1089 + .../src/mt_wifi/include/hw_ctrl/hw_init.h | 63 + .../mt7615d/src/mt_wifi/include/mac/mac.h | 243 + .../mt_wifi/include/mac/mac_mt/dmac/client.h | 33 + .../mt_wifi/include/mac/mac_mt/dmac/dma_sch.h | 178 + .../mt_wifi/include/mac/mac_mt/dmac/gpio.h | 127 + .../include/mac/mac_mt/dmac/hw_amsdu.h | 75 + .../mt_wifi/include/mac/mac_mt/dmac/mt_dmac.h | 2221 ++ .../src/mt_wifi/include/mac/mac_mt/dmac/pse.h | 261 + .../mt_wifi/include/mac/mac_mt/dmac/wf_agg.h | 345 + .../mt_wifi/include/mac/mac_mt/dmac/wf_aon.h | 37 + .../mt_wifi/include/mac/mac_mt/dmac/wf_arb.h | 154 + .../mt_wifi/include/mac/mac_mt/dmac/wf_cfg.h | 99 + .../include/mac/mac_mt/dmac/wf_cfgoff.h | 36 + .../mt_wifi/include/mac/mac_mt/dmac/wf_dma.h | 132 + .../mt_wifi/include/mac/mac_mt/dmac/wf_etbf.h | 36 + .../mac/mac_mt/dmac/wf_int_wakeup_top.h | 83 + .../include/mac/mac_mt/dmac/wf_lpon_top.h | 189 + .../mt_wifi/include/mac/mac_mt/dmac/wf_mib.h | 141 + .../mt_wifi/include/mac/mac_mt/dmac/wf_mu.h | 112 + .../mt_wifi/include/mac/mac_mt/dmac/wf_pf.h | 36 + .../mt_wifi/include/mac/mac_mt/dmac/wf_phy.h | 137 + .../mt_wifi/include/mac/mac_mt/dmac/wf_ple.h | 222 + .../mt_wifi/include/mac/mac_mt/dmac/wf_pp.h | 59 + .../mt_wifi/include/mac/mac_mt/dmac/wf_rmac.h | 301 + .../mt_wifi/include/mac/mac_mt/dmac/wf_sec.h | 37 + .../mt_wifi/include/mac/mac_mt/dmac/wf_tmac.h | 280 + .../mt_wifi/include/mac/mac_mt/dmac/wf_trb.h | 50 + .../mt_wifi/include/mac/mac_mt/dmac/wf_wtbl.h | 608 + .../include/mac/mac_mt/dmac/wf_wtbloff.h | 61 + .../include/mac/mac_mt/dmac/wf_wtblon.h | 63 + .../src/mt_wifi/include/mac/mac_mt/mt_mac.h | 102 + .../mt_wifi/include/mac/mac_mt/mt_mac_ctrl.h | 147 + .../mt_wifi/include/mac/mac_mt/mt_mac_pci.h | 108 + .../mt_wifi/include/mac/mac_mt/smac/client.h | 33 + .../mt_wifi/include/mac/mac_mt/smac/dma_sch.h | 454 + .../mt_wifi/include/mac/mac_mt/smac/gpio.h | 127 + .../mt_wifi/include/mac/mac_mt/smac/mt_mac.h | 2095 ++ .../mt_wifi/include/mac/mac_mt/smac/mt_smac.h | 2043 ++ .../src/mt_wifi/include/mac/mac_mt/smac/pse.h | 234 + .../mt_wifi/include/mac/mac_mt/smac/wf_agg.h | 263 + .../mt_wifi/include/mac/mac_mt/smac/wf_aon.h | 37 + .../mt_wifi/include/mac/mac_mt/smac/wf_arb.h | 132 + .../include/mac/mac_mt/smac/wf_cfgoff.h | 37 + .../mt_wifi/include/mac/mac_mt/smac/wf_dma.h | 197 + .../mac/mac_mt/smac/wf_int_wakeup_top.h | 82 + .../include/mac/mac_mt/smac/wf_lpon_top.h | 192 + .../mt_wifi/include/mac/mac_mt/smac/wf_mib.h | 72 + .../mt_wifi/include/mac/mac_mt/smac/wf_pf.h | 37 + .../mt_wifi/include/mac/mac_mt/smac/wf_phy.h | 163 + .../mt_wifi/include/mac/mac_mt/smac/wf_rmac.h | 224 + .../mt_wifi/include/mac/mac_mt/smac/wf_sec.h | 37 + .../mt_wifi/include/mac/mac_mt/smac/wf_tmac.h | 238 + .../mt_wifi/include/mac/mac_mt/smac/wf_trb.h | 39 + .../mt_wifi/include/mac/mac_mt/smac/wf_wtbl.h | 567 + .../include/mac/mac_mt/smac/wf_wtbloff.h | 53 + .../include/mac/mac_mt/smac/wf_wtblon.h | 296 + .../src/mt_wifi/include/mac/mac_mt/top.h | 63 + .../mt7615d/src/mt_wifi/include/mcu/fwdl.h | 212 + .../mt7615d/src/mt_wifi/include/mcu/mt_cmd.h | 6554 ++++ .../mt7615d/src/mt_wifi/include/mcu/mt_fdb.h | 354 + .../mt7615d/src/mt_wifi/include/os/bb_soc.h | 55 + .../mt7615d/src/mt_wifi/include/os/diag.h | 74 + .../mt7615d/src/mt_wifi/include/os/pkt_meta.h | 429 + .../mt7615d/src/mt_wifi/include/os/rt_drv.h | 800 + .../src/mt_wifi/include/os/rt_ecos_type.h | 73 + .../mt7615d/src/mt_wifi/include/os/rt_linux.h | 1916 ++ .../src/mt_wifi/include/os/rt_linux_cmm.h | 467 + .../mt_wifi/include/os/rt_linux_txrx_hook.h | 54 + .../mt7615d/src/mt_wifi/include/os/rt_os.h | 106 + .../mt7615d/src/mt_wifi/include/os/rt_win.h | 317 + .../mt7615d/src/mt_wifi/include/os/rt_wince.h | 85 + .../mt7615d/src/mt_wifi/include/os/trace.h | 1570 + .../src/mt_wifi/include/os/wbsys_res.h | 76 + .../mt7615d/src/mt_wifi/include/phy/mt_bbp.h | 25 + .../mt7615d/src/mt_wifi/include/phy/mt_phy.h | 2 + .../mt7615d/src/mt_wifi/include/phy/mt_rf.h | 26 + .../mt7615d/src/mt_wifi/include/phy/phy.h | 275 + .../src/mt_wifi/include/phy/rlm_cal_cache.h | 230 + .../src/mt_wifi/include/phy/wf_phy_back.h | 183 + .../src/mt_wifi/include/protocol/protection.h | 78 + .../src/mt_wifi/include/protocol/tmr.h | 65 + .../src/mt_wifi/include/rate_ctrl/ra_ctrl.h | 1509 + .../src/mt_wifi/include/txbf/mt_txbf.h | 1032 + .../src/mt_wifi/include/txbf/mt_txbf_cal.h | 364 + .../mt_wifi/include/txpwr/BFBackoffTable_1.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_10.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_11.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_12.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_13.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_14.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_15.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_16.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_17.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_18.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_19.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_2.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_20.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_3.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_4.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_5.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_6.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_7.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_8.h | 41 + .../mt_wifi/include/txpwr/BFBackoffTable_9.h | 41 + .../src/mt_wifi/include/txpwr/SKUTable_1.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_10.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_11.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_12.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_13.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_14.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_15.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_16.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_17.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_18.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_19.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_2.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_20.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_3.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_4.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_5.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_6.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_7.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_8.h | 38 + .../src/mt_wifi/include/txpwr/SKUTable_9.h | 38 + .../src/mt_wifi/include/txpwr/single_sku.h | 323 + .../mt7615d/src/mt_wifi/license/MTK_LICENSE | 42 + .../mt7615d/src/mt_wifi/license/NOTICE | 124 + .../drivers/mt7615d/src/mt_wifi/mac/mt_dmac.c | 3156 ++ .../drivers/mt7615d/src/mt_wifi/mac/mt_mac.c | 2537 ++ .../drivers/mt7615d/src/mt_wifi/mcu/fw_cmd.c | 3819 +++ .../mt/drivers/mt7615d/src/mt_wifi/mcu/fwdl.c | 63 + .../drivers/mt7615d/src/mt_wifi/mcu/fwdl_mt.c | 1106 + .../drivers/mt7615d/src/mt_wifi/mcu/mt_cmd.c | 12274 +++++++ .../drivers/mt7615d/src/mt_wifi/mcu/mt_fdb.c | 760 + .../src/mt_wifi/os/linux/Kconfig.ap.soc | 161 + .../src/mt_wifi/os/linux/Kconfig.mt_wifi | 546 + .../src/mt_wifi/os/linux/Kconfig.mt_wifi_3_18 | 685 + .../src/mt_wifi/os/linux/Kconfig.mt_wifi_4_4 | 529 + .../src/mt_wifi/os/linux/Kconfig.mt_wifi_ap | 327 + .../src/mt_wifi/os/linux/Kconfig.mt_wifi_sta | 75 + .../src/mt_wifi/os/linux/Kconfig.rlt_wifi | 216 + .../src/mt_wifi/os/linux/Kconfig.rlt_wifi_ap | 84 + .../src/mt_wifi/os/linux/Kconfig.rlt_wifi_sta | 19 + .../src/mt_wifi/os/linux/Kconfig.sta.soc | 91 + .../mt7615d/src/mt_wifi/os/linux/Kconfig.wifi | 416 + .../os/linux/Makefile-3.10.14.mt_wifi_ap | 1351 + .../mt7615d/src/mt_wifi/os/linux/Makefile.4 | 470 + .../src/mt_wifi/os/linux/Makefile.4.netif | 118 + .../src/mt_wifi/os/linux/Makefile.4.util | 96 + .../mt7615d/src/mt_wifi/os/linux/Makefile.6 | 831 + .../src/mt_wifi/os/linux/Makefile.6.netif | 114 + .../src/mt_wifi/os/linux/Makefile.6.util | 108 + .../src/mt_wifi/os/linux/Makefile.ap.soc | 394 + .../src/mt_wifi/os/linux/Makefile.ap.usb | 346 + .../src/mt_wifi/os/linux/Makefile.clean | 90 + .../os/linux/Makefile.libautoprovision.6 | 9 + .../src/mt_wifi/os/linux/Makefile.mt_wifi_ap | 1436 + .../src/mt_wifi/os/linux/Makefile.mt_wifi_sta | 794 + .../src/mt_wifi/os/linux/Makefile.rlt_wifi_ap | 652 + .../os/linux/Makefile.rlt_wifi_ap.7637e | 671 + .../mt_wifi/os/linux/Makefile.rlt_wifi_sta | 514 + .../src/mt_wifi/os/linux/Makefile.sta.soc | 275 + .../src/mt_wifi/os/linux/android_priv_cmd.c | 108 + .../mt7615d/src/mt_wifi/os/linux/ap_ioctl.c | 529 + .../mt7615d/src/mt_wifi/os/linux/bb_soc.c | 194 + .../mt7615d/src/mt_wifi/os/linux/br_ftph.c | 185 + .../src/mt_wifi/os/linux/cfg80211/cfg80211.c | 2841 ++ .../mt_wifi/os/linux/cfg80211/cfg80211_ap.c | 1725 + .../os/linux/cfg80211/cfg80211_apcli.c | 354 + .../mt_wifi/os/linux/cfg80211/cfg80211_inf.c | 759 + .../mt_wifi/os/linux/cfg80211/cfg80211_p2p.c | 26 + .../mt_wifi/os/linux/cfg80211/cfg80211_rx.c | 848 + .../mt_wifi/os/linux/cfg80211/cfg80211_scan.c | 464 + .../mt_wifi/os/linux/cfg80211/cfg80211_tdls.c | 2285 ++ .../mt_wifi/os/linux/cfg80211/cfg80211_tx.c | 2875 ++ .../mt_wifi/os/linux/cfg80211/cfg80211_util.c | 1263 + .../mt_wifi/os/linux/cfg80211/cfg80211drv.c | 1541 + .../mt7615d/src/mt_wifi/os/linux/config.mk | 1521 + .../src/mt_wifi/os/linux/config.mk.cfg80211 | 2498 ++ .../mt7615d/src/mt_wifi/os/linux/diag.c | 1502 + .../mt7615d/src/mt_wifi/os/linux/inf_ppa.c | 52 + .../mt7615d/src/mt_wifi/os/linux/mt_fwdump.c | 149 + .../src/mt_wifi/os/linux/multi_main_dev.c | 175 + .../src/mt_wifi/os/linux/pci_main_dev.c | 593 + .../src/mt_wifi/os/linux/rbus_main_dev.c | 212 + .../src/mt_wifi/os/linux/rbus_prop_dev.c | 276 + .../mt7615d/src/mt_wifi/os/linux/rt_linux.c | 5100 +++ .../src/mt_wifi/os/linux/rt_linux_symb.c | 304 + .../src/mt_wifi/os/linux/rt_main_dev.c | 946 + .../src/mt_wifi/os/linux/rt_pci_rbus.c | 60 + .../mt7615d/src/mt_wifi/os/linux/rt_proc.c | 558 + .../mt7615d/src/mt_wifi/os/linux/rt_profile.c | 1912 ++ .../src/mt_wifi/os/linux/rt_rbus_pci_drv.c | 313 + .../src/mt_wifi/os/linux/rt_rbus_pci_util.c | 506 + .../mt7615d/src/mt_wifi/os/linux/rt_symb.c | 9 + .../src/mt_wifi/os/linux/rt_txrx_hook.c | 84 + .../mt7615d/src/mt_wifi/os/linux/rt_udma.c | 222 + .../drivers/mt7615d/src/mt_wifi/os/linux/tm.c | 659 + .../mt7615d/src/mt_wifi/os/linux/trace.c | 240 + .../mt7615d/src/mt_wifi/os/linux/unload | 2 + .../mt7615d/src/mt_wifi/os/linux/vr_bdlt.c | 60 + .../mt7615d/src/mt_wifi/os/linux/vr_ikans.c | 279 + .../src/mt_wifi/os/linux/wbsys_main_dev.c | 328 + .../drivers/mt7615d/src/mt_wifi/phy/mt_phy.c | 103 + .../drivers/mt7615d/src/mt_wifi/phy/mt_rf.c | 63 + .../mt/drivers/mt7615d/src/mt_wifi/phy/phy.c | 277 + .../mt/drivers/mt7615d/src/mt_wifi/phy/rf.c | 27 + .../mt7615d/src/mt_wifi/phy/rlm_cal_cache.c | 422 + .../mt7615d/src/mt_wifi/protocol/protection.c | 57 + .../mt7615d/src/mt_wifi/protocol/tmr.c | 353 + .../mt7615d/src/mt_wifi/rate_ctrl/ra_cfg.c | 689 + .../src/mt_wifi/rate_ctrl/ra_ctrl_mt.c | 1478 + .../src/mt_wifi/rate_ctrl/ra_ctrl_mt_drv.c | 548 + .../mt_wifi/rate_ctrl/ra_wrapper_embedded.c | 866 + .../src/mt_wifi/txbf/cmm_txbf_cal_mt.c | 905 + .../mt7615d/src/mt_wifi/txbf/cmm_txbf_mt.c | 1616 + .../src/mt_wifi/txbf/txbf_wrapper_embedded.c | 172 + .../mt7615d/src/mt_wifi/txpwr/Makefile | 6 + .../drivers/mt7615d/src/mt_wifi/txpwr/dat2h.c | 216 + .../mt7615d/src/mt_wifi/txpwr/single_sku.c | 1856 + .../txpwr/sku_tables/7615_SingleSKU_1.dat | 65 + .../txpwr/sku_tables/7615_SingleSKU_BF_1.dat | 71 + .../sku_tables/7615_SingleSKU_BF_default.dat | 71 + .../sku_tables/7615_SingleSKU_default.dat | 65 + .../mt/drivers/mt7615d/src/mt_wifi_ap/Kconfig | 327 + .../drivers/mt7615d/src/mt_wifi_ap/Makefile | 1436 + .../drivers/mt7615d/src/mt_wifi_sta/Kconfig | 75 + .../drivers/mt7615d/src/mt_wifi_sta/Makefile | 794 + .../mt7615d/src/wlan_cfg/mt7622/RT2860.dat | 406 + .../mt7615d/src/wlan_cfg/mt7622/Readme.txt | 18 + .../mt7615d/src/wlan_cfg/mt7622/iNic_ap.dat | 406 + .../mt7615d/src/wlan_cfg/mt7622/l1profile.dat | 40 + .../mt7615d/src/wlan_cfg/mt7622/mt7615_3.dat | 406 + package/lean/mt/drivers/mt_wifi/Makefile | 9 +- package/lean/mt/drivers/mt_wifi/config.in | 50 +- .../lean/mt/drivers/mt_wifi/files/firmware.sh | 2 +- .../drivers/mt_wifi/src/mt_wifi/History.txt | 51 - .../src/mt_wifi/embedded/common/cmm_data.c | 1 - package/lean/mt/luci-app-mtwifi/Makefile | 2 +- .../luasrc/controller/mtkwifi.lua | 24 +- target/linux/ramips/image/mt7621.mk | 4 +- .../mt7621/base-files/etc/board.d/02_network | 5 +- 1298 files changed, 1046072 insertions(+), 104 deletions(-) create mode 100644 package/lean/mt/drivers/mt7603e/Makefile create mode 100644 package/lean/mt/drivers/mt7603e/config.in create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/History.txt create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/Kconfig create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/Kconfig.mt_wifi create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/Makefile create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/RT2860AP.dat create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/RT2860APCard.dat create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_acl_v2.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_apcli.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_apcli_inf.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_assoc.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_auth.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_autoChSel.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_band_steering.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_cfg.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_connect.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_data.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_dls.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_ftkd.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_ids.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_mbss.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_mbss_inf.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_mix_mode.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_mlme.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_nintendo.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_nps.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_qload.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_repeater.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_sanity.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_sync.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_wds.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_wds_inf.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_wpa.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_assoc.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_auth.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_ctrl.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_link_cover.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_sync.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/sniffer_mib.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/ate_agent.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/ate.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/ate_agent.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/qa_agent.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/rt_ate.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/rt_qa.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/inf/ate_pci.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/inf/ate_usb.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/mt_mac/mt_ate.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/qa_agent.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/mt7603.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/mt7628.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/mt7636.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/rt28xx.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/rt65xx.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/rtmp_chip.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/rtxx_dft.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/RT85592.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/a4_conn.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/action.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/all_net_event.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ba_action.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/bn_lib.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/client_wds.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_aes.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_cfg.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_cmd.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_cs.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_data.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_data_pci.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_data_sdio.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_dfs.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_info.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_loft_cal.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mac_pci.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mac_sdio.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mat.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mat_iparp.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mat_ipv6.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mat_pppoe.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_profile.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_radar.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_rf_cal.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_sanity.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_sync.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_tkip.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_usb_io.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_video.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_wep.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_wpa.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_aes.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_arc4.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_biginteger.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_bignum.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_dh.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_hmac.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_md5.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_sha2.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ecc.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ee_efuse.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ee_flash.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ee_prom.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/eeprom.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/event_notifier.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/event_notifier_old.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/frq_cal.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ft.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ft_iocl.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ft_rc.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ft_tlv.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/gas.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/hotspot.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/igmp_snoop.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/map.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mbo.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/misc.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mlme.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mt_io.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mt_ps.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mtsdio_data.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mtsdio_io.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mtusb_io.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mwds.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/netif_block.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/nfc.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/op_class.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/owe.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/pmf.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ps.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ral_ps.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/routing_tab.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rrm.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rrm_sanity.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rrm_tlv.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt2860.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt2860.bin.dfs create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt2870_sw_ch_offload.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt_channel.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt_led.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt_os_util.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rtmp_init.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rtmp_init_inf.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rtmp_timer.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/sae.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/scan.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/spectrum.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/sys_log.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/txpower.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/uapsd.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/vendor.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/vht.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wapi.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wapi_crypt.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wapi_sms4.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wfd.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wnm.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wnm_tlv.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wsc.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wsc_tlv.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wsc_ufd.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wsc_v2.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2860AP.dat create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2860AP.dat_ac create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2860APCard.dat create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2860STA.dat create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2860STACard.dat create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2870AP.dat create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2870APCard.dat create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2870STA.dat create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2870STACard.dat create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/History.txt create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/README create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/README_STA_pci create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/README_STA_usb create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/RT2860card.readme create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/RT_WIFI_Revision_History_2010_April.xls create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/VxWorks.README create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/ate_iwpriv_usage.txt create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/brftph_usage.txt create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/iwpriv_usage.txt create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/mbss_phy.readme create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/sta_ate_iwpriv_usage.txt create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/wps_iwpriv_usage.txt create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/easy_setup/ez_hooks.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/easy_setup/mt7603_chip_ops.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/easy_setup/mt7603_chip_ops_api.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/easy_setup/mt7603_driver_specific_func.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7601_USB_V0_D-20130416.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7603E1E2_EEPROM_layout_2014011.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7603E1E2_EEPROM_layout_2014011_ePAeLNA.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7603E1E2_EEPROM_layout_20140226.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7603E1_EEPROM_layout_20131112.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7603E1_EEPROM_layout_20131206.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7603E_EEPROM.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7662E1_EEPROM_layout_20130301.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7662E2_EEPROM_20130412.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7662E2_EEPROM_20130527.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7662E2_EEPROM_20130528.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7662E2_EEPROM_20130903_ePA.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hif/hif_pci.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/cmm_asic.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/cmm_asic_mt.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/cmm_chip_mt.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/coex.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/greenap.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/mt_gpio.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/a4_conn.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/action.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ags.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/all_net_event.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_acl_v2.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_apcli.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_autoChSel.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_autoChSel_cmm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_cfg.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_diversity.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_ids.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_mbss.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_wds.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/band_steering.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/band_steering_def.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/bn.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/br_ftph.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cfg80211.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cfg80211_cmm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cfg80211extr.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/chip_id.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/mt7603.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/mt7628.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/mt7636.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/mt76x0.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/rt65xx.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/rt8592.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chlist.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/client_wds.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/client_wds_cmm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cmm_asic_mt.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_aes.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_arc4.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_biginteger.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_bignum.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_dh.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_hmac.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_md5.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_sha2.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cs.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dfs.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/diag.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11_base.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11ac_vht.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11i_wpa.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11k_rrm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11n_ht.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11r_ft.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11u_interworking.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11v_wnm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11w_pmf.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/drs_extr.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/ez_cmm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/ez_hooks.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/ez_hooks_proto.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/ez_mod_hooks.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/mt7603_chip_ops.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/mt7603_chip_ops_api.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/mt7603_driver_specific_func.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ecc.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom/mt7601_e2p.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom/mt7603_e2p.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom/mt76x2_e2p.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom/mt_e2p_def.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/efuse.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/event_notifier.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/event_notifier_old.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/firmware.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/fpga/fpga_ctl.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/frame_hdr.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/frq_cal.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ft.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ft_cmm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/gas.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/hotspot.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/iface.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/iface_util.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/mt_hif_pci_usb.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/mt_hif_sdio.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/mt_sdio.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/rtmp_inf_pcirbs.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/rtmp_pci.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/rtmp_reg_pcirbs.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/igmp_snoop.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ipv6.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/link_list.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/client.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/gpio.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/mt_mac.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/mt_mac_pci.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/mt_mac_sdio.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/mt_mac_usb.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/pse.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/ral_nmac_usb.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/top.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_agg.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_aon.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_arb.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_cfgoff.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_dma.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_int_wakeup_top.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_lpon_top.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_mib.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_pf.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_phy.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_rmac.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_sec.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_tmac.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_trb.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_wtbl.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_wtbloff.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_wtblon.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/fce.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/mac_pci.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/mac_usb.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac_pbf.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac_pci.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac_rf_ctrl.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac_usb.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac_pbf.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac_pci.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac_rf_ctrl.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac_usb.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/pbf.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/rf_ctrl.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/rtmp_mac.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/map.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mat.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mbo.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/andes_core.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/andes_mt.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/andes_rlt.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/btcoex.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mcu.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7601_firmware.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7603_e2_firmware.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7603_firmware.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7636_firmware.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7636_rom_patch.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7662_rom_patch.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/misc.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/misc_cmm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mix_mode.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mlme.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mlme_sys.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mt_io.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mt_ps.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mt_tx_pwr.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mtsdio_data.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mtsdio_io.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mwds.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/netif_block.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/nfc.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/oid.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/bb_soc.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/pkt_meta.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_drv.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_linux.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_linux_cmm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_linux_txrx_hook.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_os.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/trace_linux.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/owe_cmm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/mt76x2_rf.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/mt_bbp.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/mt_phy.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/mt_rf.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/phy.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/rlt_bbp.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/rlt_rf.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/rtmp_bbp.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/wf_phy_back.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/pmf.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/pmf_cmm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/radar.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/routing_tab.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rrm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rrm_cmm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_cal.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_config.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_led.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_os_net.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_os_util.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_txbf.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_chip.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_cmd.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_comm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_def.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_dot11.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_iface.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_os.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_osabl.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_timer.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_type.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sae.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sae_cmm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sniffer/radiotap.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sniffer/sniffer.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sniffer_mib.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/spectrum.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/spectrum_def.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sta.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sta_cfg.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/tx_power.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/uapsd.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/vendor.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/vht.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/video.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/vr_ikans.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/vrut_ubm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wapi.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wapi_def.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wapi_sms4.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wfa_p2p.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wfd.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wfd_cmm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wnm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wnm_cmm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wpa.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wpa_cmm.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wsc.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wsc_tlv.h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/license/MTK_LICENSE create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/license/NOTICE create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mac/mt_mac.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mac/ral_nmac.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mac/ral_omac.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mac/rtmp_mac.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/andes_core.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/andes_mt.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/andes_rlt.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/MT7601_formal_1.7.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/MT7603_ram_20140305_e2_drv_tv01.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/MT7610.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/MT7650.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/WIFI_RAM_CODE_MT7603_e1.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/WIFI_RAM_CODE_MT7603_e2.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/WIFI_RAM_CODE_MT7636.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/mt7612_patch_e1_hdr.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/mt7612_patch_e1_hdr_0417.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/mt7636_patch_e1_hdr.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/mt7662_firmware_e3_20131211.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/mt7662_patch_e3_hdr_v0.0.2_P8.bin create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/mt7662_patch_release_history.xlsx create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/mcu.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mgmt/mgmt_dev.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mgmt/mgmt_entrytb.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mgmt/mgmt_ht.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mgmt/mgmt_hw.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mgmt/mgmt_vht.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/naf/cso.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/naf/net_acc.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/naf/tso.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Kconfig.ap.soc create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Kconfig.ap.usb create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Kconfig.rlt_wifi create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Kconfig.rlt_wifi_ap create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Kconfig.rlt_wifi_sta create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Kconfig.sta.soc create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Kconfig.wifi create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Makefile.4 create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Makefile.4.netif create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Makefile.4.util create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Makefile.6 create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Makefile.6.netif create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Makefile.6.util create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Makefile.ap.soc create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Makefile.ap.usb create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Makefile.clean create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Makefile.libautoprovision.6 create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Makefile.libwapi.4 create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Makefile.libwapi.6 create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Makefile.rlt_wifi_ap create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Makefile.rlt_wifi_sta create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/Makefile.sta.soc create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/android_priv_cmd.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/ap_ioctl.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/bb_soc.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/br_ftph.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/config.mk create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/config.mk.cfg80211 create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/diag.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/inf_ppa.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/load create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/monitor_mode.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/multi_main_dev.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/pci_main_dev.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/rt_linux.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/rt_linux_symb.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/rt_main_dev.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/rt_pci_rbus.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/rt_proc.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/rt_profile.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/rt_rbus_pci_drv.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/rt_rbus_pci_util.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/rt_sdio.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/rt_symb.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/rt_txrx_hook.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/sdio_main_dev.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/unload create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/vr_bdlt.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/os/linux/vr_ikans.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/phy/mt76x2_rf.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/phy/mt_phy.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/phy/mt_rf.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/phy/phy.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/phy/rf.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/phy/rlt_phy.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/phy/rlt_rf.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/phy/rt_rf.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/phy/rtmp_phy.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/rate_ctrl/alg_ags.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/rate_ctrl/alg_grp.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/rate_ctrl/alg_legacy.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/rate_ctrl/ra_ctrl.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/sniffer/sniffer_prism.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/sniffer/sniffer_radiotap.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/tools/Makefile create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/tools/bin2h create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/tools/bin2h.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/tools/i.sh create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/tools/mt7662_freq_plan.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/tools/mt7662e_ap.sh create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/tools/mt7662e_sta.sh create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/tools/plug_in/Makefile create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/tools/r.sh create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/tx_rx/hdr_trans.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/tx_rx/txs.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/tx_rx/wdev.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/tx_rx/wdev_rx.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi/tx_rx/wdev_tx.c create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi_ap/Kconfig create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi_ap/Kconfig.mt_wifi_ap create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi_ap/Makefile create mode 100644 package/lean/mt/drivers/mt7603e/src/mt7603_wifi_ap/Makefile.mt_wifi_ap create mode 100644 package/lean/mt/drivers/mt7615d/Makefile create mode 100644 package/lean/mt/drivers/mt7615d/config.in create mode 100644 package/lean/mt/drivers/mt7615d/files/SingleSKU.dat create mode 100644 package/lean/mt/drivers/mt7615d/files/SingleSKU_BF.dat create mode 100644 package/lean/mt/drivers/mt7615d/files/firmware.sh create mode 100644 package/lean/mt/drivers/mt7615d/files/l1profile.dat create mode 100644 package/lean/mt/drivers/mt7615d/files/mt7615.1.2G.dat create mode 100644 package/lean/mt/drivers/mt7615d/files/mt7615.1.dat create mode 100644 package/lean/mt/drivers/mt7615d/files/mt7615.2.dat create mode 100644 package/lean/mt/drivers/mt7615d/files/mt7615.lua create mode 100644 package/lean/mt/drivers/mt7615d/files/mt7615e-sku-bf.dat create mode 100644 package/lean/mt/drivers/mt7615d/files/mt7615e-sku.dat create mode 100644 package/lean/mt/drivers/mt7615d/files/mt7615e.1.dat create mode 100644 package/lean/mt/drivers/mt7615d/files/mt7615e.2.dat create mode 100644 package/lean/mt/drivers/mt7615d/files/mt7615e.eeprom.bin create mode 100644 package/lean/mt/drivers/mt7615d/files/mt7622.1.dat create mode 100644 package/lean/mt/drivers/mt7615d/files/wifi_services.lua create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/MT7615E1_EEPROM.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/MT7615_cr4.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/MT7615_cr4_noReOrdering.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/MT7615_cr4_plain.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/MT7615_cr4_plain_20141024_1.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/MT7615_cr4_plain_20150206_1_asic.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/WIFI_RAM_CODE_MT7615.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/WIFI_RAM_CODE_MT7615_E1.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/WIFI_RAM_CODE_MT7615_plain.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/ePAeLNA/MT7615_EEPROM1.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/ePAeLNA/MT7615_EEPROM2.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/ePAeLNA/MT7615_EEPROM3.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/ePAiLNA/MT7615_EEPROM1.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/ePAiLNA/MT7615_EEPROM2.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/ePAiLNA/MT7615_EEPROM3.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/iPAeLNA/MT7615_EEPROM1.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/iPAeLNA/MT7615_EEPROM2.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/iPAeLNA/MT7615_EEPROM3.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/iPAiLNA/MT7615_EEPROM1.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/iPAiLNA/MT7615_EEPROM2.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/iPAiLNA/MT7615_EEPROM3.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7615/mt7615_patch_e3_hdr.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7622/MT7622_EEPROM.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7622/WIFI_RAM_CODE_MT7622_E2.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7622/ePAeLNA/MT7622_EEPROM.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7622/iPAeLNA/MT7622_EEPROM.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7622/iPAiLNA/MT7622_EEPROM.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/bin/mt7622/mt7622_patch_e2_hdr.bin create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/LoopBack.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/ate_agent.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/LoopBack.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/ate.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/ate_agent.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/meta_agent.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/mt_testmode.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/mt_testmode_dmac.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/mt_testmode_smac.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/qa_agent.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/testmode_common.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/include/testmode_ioctl.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/meta_agent.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/mt_mac/mt_ate.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/mt_mac/mt_testmode.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/mt_mac/mt_testmode_dmac.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/mt_mac/mt_testmode_smac.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/qa_agent.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/ate/testmode_ioctl.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/chips/mt7615.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/chips/mt7615_dbg.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/chips/mt7622.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/chips/mt7622_dbg.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/chips/rtmp_chip.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/Kconfig create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/Makefile create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/Pack_Release.sh create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/Release.sh create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/Release_Notes.txt create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_apcli.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_apcli_inf.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_assoc.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_auth.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_autoChSel.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_band_steering.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_cfg.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_data.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_ftkd.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_ids.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_mbss.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_mbss_inf.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_mlme.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_mumimo.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_mura.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_nps.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_qload.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_repeater.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_sanity.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_sec.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_sync.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_vow.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_wds.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_wds_inf.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/ap_wpa.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/apcli_assoc.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/apcli_auth.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/apcli_ctrl.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/apcli_link_cover.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/ap/apcli_sync.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/a4_conn.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/action.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ba_action.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/bcn.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/bgnd_scan.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/client_wds.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_cfg.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_cmd.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_cs.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_data.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_info.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_info_element.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_mac_pci.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_mat.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_mat_iparp.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_mat_ipv6.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_mat_pppoe.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_mumimo.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_profile.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_radar.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_rdm_mt.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_rf_cal.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_rvr_dbg.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_sanity.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_sync.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_tcprack.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_txbf.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cmm_video.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/cut_through.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ee_efuse.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ee_flash.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ee_prom.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/eeprom.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/fp_fair_qm.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/fp_qm.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/fpga.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/fq_qm.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ft.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ft_iocl.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ft_rc.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ft_tlv.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ftm.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/gas.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/hif_pci.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/hotspot.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/icap.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/igmp_snoop.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/map.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/mbo.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/misc_app.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/mlme.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/mt_io.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/mt_ps.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/multi_channel.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/multi_profile.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/netif_block.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/nfc.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/op_class.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ps.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/qm.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ra_ac_q_mgmt.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/ral_ps.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/routing_tab.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rrm.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rrm_sanity.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rrm_tlv.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rt_channel.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rt_led.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rt_os_util.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rtmp_init.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rtmp_init_inf.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/rtmp_timer.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/scan.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/scs.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/smartant.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/sniffer_prism.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/sniffer_radiotap.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/spectrum.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/sys_log.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/txpower.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/txs.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/uapsd.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/vendor.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/verf.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/vht.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wdev.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wifi_sys_info.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wifi_sys_notify.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wnm.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wsc.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wsc_tlv.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wsc_ufd.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/common/wsc_v2.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/Doxyfile create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/FirmwareHistory.txt create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/History.txt create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/History_sta_pci.txt create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/History_sta_usb.txt create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/README create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/README_STA_pci create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/README_STA_usb create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/RT2860card.readme create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/RT_WIFI_Revision_History_2010_April.xls create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/VxWorks.README create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/ate_iwpriv_usage.txt create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/brftph_usage.txt create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/header_translation.txt create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/iwpriv_usage.txt create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/mainpage.dox create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/mbss_phy.readme create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/sta_ate_iwpriv_usage.txt create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/doc/wps_iwpriv_usage.txt create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hdev/hdev_basic.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hdev/omac_ctrl.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hdev/radio_ctrl.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hdev/wmm_ctrl.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hdev/wtbl_ctrl.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hdev_ctrl.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hw_ctrl.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_basic.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_cmd.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_ops_v1.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/hw_ctrl/hw_ctrl_ops_v2.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/a4_conn.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/action.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ags.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_apcli.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_autoChSel.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_autoChSel_cmm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_cfg.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_ids.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_mbss.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_mumimo.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_mura.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_repeater.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_vow.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ap_wds.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/arris_mod_api.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/arris_wps_gpio_handler.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/band_steering.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/band_steering_def.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/bcn.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/bgnd_scan.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/bgnd_scan_cmm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/br_ftph.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cfg80211.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cfg80211_cmm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cfg80211extr.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/chlist.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/client_wds.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/client_wds_cmm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cmm_cmd.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cmm_rvr_dbg.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cmm_tcprack.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cs.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/cut_through.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11_base.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11ac_vht.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11k_rrm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11n_ht.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11r_ft.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11u_interworking.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/dot11v_wnm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_ePAeLNA.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_ePAiLNA.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_iPAeLNA.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7615_e2p_iPAiLNA.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7622_e2p_ePAeLNA.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7622_e2p_iPAeLNA.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7622_e2p_iPAiLNA.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt7663_e2p.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt_dmac_e2p_def.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/eeprom/mt_e2p_def.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/efuse.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/event_common.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/firmware.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/fp_qm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/fq_qm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/frame_hdr.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/frq_cal.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/fsm/fsm_sync.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ft.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ft_cmm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ftm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ftm_cmm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/gas.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/hdev/hdev.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/hdev/hdev_basic.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/hdev_ctrl.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/hotspot.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/hw_ctrl.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/hw_ctrl_basic.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/icap.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/iface/iface.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/iface/iface_util.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/iface/mtk_hif.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/iface/rtmp_inf_pcirbs.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/iface/rtmp_pci.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/iface/rtmp_rbs.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/igmp_snoop.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ipv6.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/l1profile.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/map.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mat.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mbo.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/andes_core.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/andes_mt.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/btcoex.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mcu.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7615_cr4_firmware.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7615_firmware.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7615_firmware_e1.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7615_rom_patch.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7615_rom_patch_e1.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7622_firmware.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7622_firmware_e2.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mcu/mt7622_rom_patch_e2.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/meminfo_list.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mgmt/be_export.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mgmt/be_internal.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/misc_app.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mlme.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mlme_sys.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mt_io.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/mt_rdm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/netif_block.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/nfc.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/oid.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/oid_struct.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/qm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/ra_ac_q_mgmt.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/radar.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/routing_tab.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rrm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rrm_cmm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_cal.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_config.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_led.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_os_net.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_os_util.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_txbf.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rt_udma.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_chip.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_cmd.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_comm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_def.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_dmacb.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_dot11.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_iface.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_os.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_osabl.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_timer.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/rtmp_type.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/scs.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/bn.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_aes.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_arc4.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_biginteger.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_bignum.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_dh.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_hmac.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_md5.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/crypt_sha2.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/dh_key.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/dot11i_wpa.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/dot11w_pmf.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/ecc.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/owe_cmm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/pmf.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/pmf_cmm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/sae.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/sae_cmm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/sec.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/sec_cmm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/wpa.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/security/wpa_cmm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/smartant.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/sniffer/radiotap.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/sniffer/sniffer.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/spectrum.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/spectrum_def.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/sta.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/sta_cfg.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/tm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/tr.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/tx_power.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/uapsd.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/vendor.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/vht.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/video.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/vr_ikans.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/vrut_ubm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wapp/wapp.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wapp/wapp_cmm_type.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wfa_p2p.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wifi_sys_notify.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wlan_config/config_export.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wlan_config/config_internal.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wnm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wnm_cmm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wsc.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/include/wsc_tlv.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mcu/andes_core.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mcu/andes_mt.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mcu/mcu.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/be_basic.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/be_ht.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/be_phy.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/be_vht.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/bss_ops.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/mgmt_dev.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/mgmt_entrytb.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/mgmt_ht.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/mgmt_hw.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/mgmt/mgmt_vht.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/Makefile create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/Makefile create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/wdma.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/wdma.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/wed.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/wed.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/wed_def.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_basic.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_basic.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_hif.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_hif.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_hw.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_hw.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_main.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_mt7615.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_mt7615.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_proc.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_ser.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/plug_in/whnat/woe_wifi.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/bn_lib.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/cmm_aes.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/cmm_sec.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/cmm_tkip.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/cmm_wep.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/cmm_wpa.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_aes.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_arc4.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_biginteger.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_bignum.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_dh.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_hmac.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_md5.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/crypt_sha2.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/dh_key.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/ecc.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/owe.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/pmf.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/security/sae.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/Makefile create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/auto_build_kernel_4_4.sh create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/bin2h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/bin2h.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/build-check-jedi.sh create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/check_build_script.sh create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/i.sh create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/mt7662_freq_plan.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/mt7662e_ap.sh create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/mt7662e_sta.sh create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/tools/r.sh create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/unload create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/wapp/wapp.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/wlan_config/config_basic.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/wlan_config/config_ht.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/wlan_config/config_phy.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/embedded/wlan_config/config_vht.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/cmm_asic.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/cmm_asic_mt.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/cmm_asic_mt_dmac.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/cmm_asic_mt_fw.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/cmm_chip.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/cmm_chip_mt.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/coex.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/greenap.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/hw_init.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/hw_ctrl/mt_gpio.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/chip_id.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/mt7615.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/mt7615_cr.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/mt7622.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/mt7622_cr.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/mt7663_cr.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/chip/p18_cr.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/common/debug.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/common/link_list.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/common/module.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/common/mt_os_util.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/common/wifi_sys_info.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/eeprom/mt_tx_pwr.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hif/hif.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hif/mt_hif_pci.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hw_ctrl/cmm_asic.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hw_ctrl/cmm_asic_mt.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hw_ctrl/cmm_asic_mt_fw.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hw_ctrl/cmm_chip.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/hw_ctrl/hw_init.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/client.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/dma_sch.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/gpio.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/hw_amsdu.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/mt_dmac.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/pse.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_agg.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_aon.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_arb.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_cfg.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_cfgoff.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_dma.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_etbf.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_int_wakeup_top.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_lpon_top.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_mib.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_mu.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_pf.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_phy.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_ple.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_pp.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_rmac.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_sec.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_tmac.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_trb.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_wtbl.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_wtbloff.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/dmac/wf_wtblon.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/mt_mac.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/mt_mac_ctrl.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/mt_mac_pci.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/client.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/dma_sch.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/gpio.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/mt_mac.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/mt_smac.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/pse.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_agg.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_aon.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_arb.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_cfgoff.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_dma.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_int_wakeup_top.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_lpon_top.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_mib.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_pf.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_phy.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_rmac.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_sec.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_tmac.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_trb.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_wtbl.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_wtbloff.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/smac/wf_wtblon.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mac/mac_mt/top.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mcu/fwdl.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mcu/mt_cmd.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/mcu/mt_fdb.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/bb_soc.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/diag.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/pkt_meta.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_drv.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_ecos_type.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_linux.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_linux_cmm.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_linux_txrx_hook.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_os.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_win.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/rt_wince.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/trace.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/os/wbsys_res.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/phy/mt_bbp.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/phy/mt_phy.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/phy/mt_rf.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/phy/phy.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/phy/rlm_cal_cache.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/phy/wf_phy_back.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/protocol/protection.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/protocol/tmr.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/rate_ctrl/ra_ctrl.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txbf/mt_txbf.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txbf/mt_txbf_cal.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_1.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_10.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_11.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_12.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_13.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_14.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_15.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_16.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_17.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_18.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_19.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_2.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_20.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_3.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_4.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_5.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_6.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_7.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_8.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/BFBackoffTable_9.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_1.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_10.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_11.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_12.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_13.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_14.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_15.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_16.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_17.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_18.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_19.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_2.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_20.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_3.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_4.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_5.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_6.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_7.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_8.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/SKUTable_9.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/include/txpwr/single_sku.h create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/license/MTK_LICENSE create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/license/NOTICE create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/mac/mt_dmac.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/mac/mt_mac.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/mcu/fw_cmd.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/mcu/fwdl.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/mcu/fwdl_mt.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/mcu/mt_cmd.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/mcu/mt_fdb.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.ap.soc create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.mt_wifi create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.mt_wifi_3_18 create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.mt_wifi_4_4 create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.mt_wifi_ap create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.mt_wifi_sta create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.rlt_wifi create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.rlt_wifi_ap create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.rlt_wifi_sta create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.sta.soc create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Kconfig.wifi create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile-3.10.14.mt_wifi_ap create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.4 create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.4.netif create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.4.util create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.6 create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.6.netif create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.6.util create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.ap.soc create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.ap.usb create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.clean create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.libautoprovision.6 create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.mt_wifi_ap create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.mt_wifi_sta create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.rlt_wifi_ap create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.rlt_wifi_ap.7637e create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.rlt_wifi_sta create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/Makefile.sta.soc create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/android_priv_cmd.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/ap_ioctl.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/bb_soc.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/br_ftph.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_ap.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_apcli.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_inf.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_p2p.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_rx.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_scan.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_tdls.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_tx.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211_util.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/cfg80211/cfg80211drv.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/config.mk create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/config.mk.cfg80211 create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/diag.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/inf_ppa.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/mt_fwdump.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/multi_main_dev.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/pci_main_dev.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rbus_main_dev.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rbus_prop_dev.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_linux.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_linux_symb.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_main_dev.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_pci_rbus.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_proc.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_profile.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_rbus_pci_drv.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_rbus_pci_util.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_symb.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_txrx_hook.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/rt_udma.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/tm.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/trace.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/unload create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/vr_bdlt.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/vr_ikans.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/os/linux/wbsys_main_dev.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/phy/mt_phy.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/phy/mt_rf.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/phy/phy.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/phy/rf.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/phy/rlm_cal_cache.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/protocol/protection.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/protocol/tmr.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/rate_ctrl/ra_cfg.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/rate_ctrl/ra_ctrl_mt.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/rate_ctrl/ra_ctrl_mt_drv.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/rate_ctrl/ra_wrapper_embedded.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/txbf/cmm_txbf_cal_mt.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/txbf/cmm_txbf_mt.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/txbf/txbf_wrapper_embedded.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/Makefile create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/dat2h.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/single_sku.c create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_1.dat create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_BF_1.dat create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_BF_default.dat create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi/txpwr/sku_tables/7615_SingleSKU_default.dat create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi_ap/Kconfig create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi_ap/Makefile create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi_sta/Kconfig create mode 100644 package/lean/mt/drivers/mt7615d/src/mt_wifi_sta/Makefile create mode 100644 package/lean/mt/drivers/mt7615d/src/wlan_cfg/mt7622/RT2860.dat create mode 100644 package/lean/mt/drivers/mt7615d/src/wlan_cfg/mt7622/Readme.txt create mode 100644 package/lean/mt/drivers/mt7615d/src/wlan_cfg/mt7622/iNic_ap.dat create mode 100644 package/lean/mt/drivers/mt7615d/src/wlan_cfg/mt7622/l1profile.dat create mode 100644 package/lean/mt/drivers/mt7615d/src/wlan_cfg/mt7622/mt7615_3.dat delete mode 100644 package/lean/mt/drivers/mt_wifi/src/mt_wifi/History.txt diff --git a/package/lean/mt/drivers/mt7603e/Makefile b/package/lean/mt/drivers/mt7603e/Makefile new file mode 100644 index 000000000..875104b3c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/Makefile @@ -0,0 +1,62 @@ +# All rights reserved. +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=mt7603e +P4REV:=2 +PKG_VERSION:=4.1.2.0 +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/mt7603_wifi +PKG_KCONFIG:= \ + RALINK_MT7620 RALINK_RT7621 RLT_WIFI MT_WIFI_PATH FIRST_IF_MT7603E\ + FIRST_IF_EEPROM_PROM FIRST_IF_EEPROM_EFUSE FIRST_IF_EEPROM_FLASH RT_FIRST_CARD_EEPROM WIFI_BASIC_FUNC\ + MULTI_INF_SUPPORT WSC_INCLUDED WSC_V2_SUPPORT DOT11N_DRAFT3 DOT11_VHT_AC DOT11W_PMF_SUPPORT\ + TXBF_SUPPORT WMM_ACM_SUPPORT QOS_DLS_SUPPORT WAPI_SUPPORT CARRIER_DETECTION_SUPPORT\ + IGMP_SNOOP_SUPPORT BLOCK_NET_IF RATE_ADAPTION NEW_RATE_ADAPT_SUPPORT AGS_SUPPORT\ + IDS_SUPPORT WIFI_WORK_QUEUE WIFI_SKB_RECYCLE RTMP_FLASH_SUPPORT LED_CONTROL_SUPPORT\ + SINGLE_SKU_V2 HW_ANTENNA_DIVERSITY ATE_SUPPORT RT2860V2_AP_V24_DATA_STRUCTURE RT2860V2_AP_32B_DESC\ + MEMORY_OPTIMIZATION HOTSPOT HOTSPOT_R2 ACL_V2_SUPPORT UAPSD PA_LNA RLT_BBP RLT_RF RTMP_BBP RTMP_RF RLT_MAC RLT_BBP RLT_RF RTMP_MAC RTMP_BBP RTMP_RF \ + RTMP_PCI_SUPPORT RTMP_USB_SUPPORT RTMP_RBUS_SUPPORT RLT_AP_SUPPORT RALINK_MT7603E MT_MAC AP_SUPPORT\ + WDS_SUPPORT MBSS_SUPPORT NEW_MBSSID_MODE ENHANCE_NEW_MBSSID_MODE APCLI_SUPPORT MULTI_APCLI_SUPPORT \ + AIRPLAY_SUPPORT MAC_REPEATER_SUPPORT DFS_SUPPORT NINTENDO_AP DOT11K_RRM_SUPPORT RT2860V2_SNMP\ + LLTD_SUPPORT NINTENDO_AP COC_SUPPORT MULTI_CORE_SUPPORT MCAST_RATE_SPECIFIC PREVENT_ARP_SPOOFING_SUPPORT \ + EXT_BUILD_CHANNEL_LIST AUTO_CH_SELECT_ENHANCE MEMORY_OPTIMIZATION RTMP_TEMPERATURE_CALIBRATION\ + SNIFFER_SUPPORT CFG80211_SUPPORT SNIFFER_MIB_CMD ALL_NET_EVENT + + +PKG_CONFIG_DEPENDS:=$(foreach c, $(PKG_KCONFIG),$(if $(CONFIG_$c),CONFIG_$(c))) + +include $(INCLUDE_DIR)/package.mk + +TAR_CMD=$(HOST_TAR) -C $(1)/ $(TAR_OPTIONS) + +define KernelPackage/mt7603e + CATEGORY:=Kernel modules + TITLE:=MTK wifi AP driver + FILES:=$(PKG_BUILD_DIR)/mt7603_wifi_ap/mt7603e.ko + SUBMENU:=Wireless Drivers + AUTOLOAD:=$(call AutoProbe,mt7603e) + MENU:=1 +endef + +define KernelPackage/mt7603e/config + source "$(SOURCE)/config.in" +endef + +define Build/Compile + $(MAKE) -C "$(LINUX_DIR)" V=1 \ + CROSS_COMPILE="$(TARGET_CROSS)" \ + ARCH="$(LINUX_KARCH)" \ + M="$(PKG_BUILD_DIR)/mt7603_wifi_ap" \ + $(foreach c, $(PKG_KCONFIG),$(if $(CONFIG_MT7603E_$c),CONFIG_$(c)=$(CONFIG_MT7603E_$(c)))) \ + modules +endef + +define KernelPackage/mt7603e/install + $(INSTALL_DIR) $(1)/etc/wireless/mt7603/ +endef + +$(eval $(call KernelPackage,mt7603e)) diff --git a/package/lean/mt/drivers/mt7603e/config.in b/package/lean/mt/drivers/mt7603e/config.in new file mode 100644 index 000000000..cb130d1df --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/config.in @@ -0,0 +1,526 @@ +if PACKAGE_kmod-mt7603e + +#if FIRST_IF_MT7603E || SECOND_IF_MT7603E +config MT7603E_FIRST_IF_MT7603E + bool + default y + depends on PACKAGE_kmod-mt7603e + +config MT7603E_RLT_WIFI + tristate "MT WIFI Driver" + default y + +config MT7603E_MT_WIFI_PATH + string + depends on MT7603E_RLT_WIFI + default "rlt_wifi" + +if MT7603E_RLT_WIFI +menu "WiFi Generic Feature Options" + +if MT7603E_FIRST_IF_MT7603E +choice + prompt "EEPROM Type of 1st Card" + default MT7603E_FIRST_IF_EEPROM_FLASH + #depends on ! FIRST_IF_NONE + + config MT7603E_FIRST_IF_EEPROM_FLASH + bool "FLASH" + + config MT7603E_FIRST_IF_EEPROM_PROM + bool "EEPROM" + + config MT7603E_FIRST_IF_EEPROM_EFUSE + bool "EFUSE" +endchoice + +config MT7603E_RT_FIRST_CARD_EEPROM + string + #depends on ! FIRST_IF_NONE + default "prom" if MT7603E_FIRST_IF_EEPROM_PROM + default "efuse" if MT7603E_FIRST_IF_EEPROM_EFUSE + default "flash" if MT7603E_FIRST_IF_EEPROM_FLASH +endif + + + + +config MT7603E_MULTI_INF_SUPPORT + bool + #default y if !FIRST_IF_NONE && !SECOND_IF_NONE + default y + +#config MT7603E_WIFI_BASIC_FUNC +# bool "Basic Functions" +# select WIRELESS_EXT +# select WEXT_SPY +# select WEXT_PRIV + +config MT7603E_WSC_INCLUDED + bool "WSC (WiFi Simple Config)" +# depends on WIFI_DRIVER + default y + +config MT7603E_WSC_V2_SUPPORT + bool "WSC V2(WiFi Simple Config Version 2.0)" + depends on MT7603E_MMT_WSC_INCLUDED + default y +config MT7603E_WSC_NFC_SUPPORT + bool "WSC out-of-band(NFC)" + # depends on WIFI_DRIVER + default n +config MT7603E_DOT11N_DRAFT3 + bool "802.11n Draft3" +# depends on WIFI_DRIVER + default y + +#config MT7603E_DOT11_VHT_AC +# bool "802.11 ac" +# depends on WIFI_DRIVER +# default n + +config MT7603E_DOT11W_PMF_SUPPORT + bool "PMF Support" +# depends on WIFI_DRIVER + default y + +config MT7603E_TXBF_SUPPORT + bool "Tx Bean Forming Support" +# depends on WIFI_DRIVER + default n + +#config MT7603E_WMM_ACM_SUPPORT +# bool "WMM ACM" +# depends on WIFI_DRIVER +# default n + +config MT7603E_LLTD_SUPPORT + bool "LLTD (Link Layer Topology Discovery Protocol)" +# depends on WIFI_DRIVER + default y + +config MT7603E_QOS_DLS_SUPPORT + bool "802.11e DLS ((Direct-Link Setup) Support" +# depends on WIFI_DRIVER + default n + +config MT7603E_WAPI_SUPPORT + bool "WAPI Support" +# depends on WIFI_DRIVER + default n + +config MT7603E_CARRIER_DETECTION_SUPPORT + bool "Carrier Detect" +# depends on WIFI_DRIVER + default n + +config MT7603E_IGMP_SNOOP_SUPPORT + bool "IGMP Snooping" +# depends on WIFI_DRIVER + default n + +config MT7603E_BLOCK_NET_IF + bool "NETIF Block" +# depends on WIFI_DRIVER + default n + help + Support Net interface block while Tx-Sw queue full + +#config MT7603E_MT_TXBF_SUPPORT +# bool "Tx Bean Forming Support (Only 3883)" +# depends on WIFI_DRIVER +# depends on RALINK_RT2883 || RALINK_RT3883 +# default n + +#config MT7603E_MT_VIDEO_TURBINE_SUPPORT +# bool "Video Turbine support" +# depends on WIFI_DRIVER +# default n + +#config MT7603E_RATE_ADAPTION +# tristate "Ralink Flow Classifier" +# depends on WIFI_DRIVER +# default n + +config MT7603E_NEW_RATE_ADAPT_SUPPORT + bool "New Rate Adaptation support" +# depends on WIFI_DRIVER + default y + +config MT7603E_MT_NEW_RATE_ADAPT_SUPPORT + bool "Intelligent Rate Adaption" +# depends on WIFI_DRIVER && MT_RATE_ADAPTION + default y + +config MT7603E_AGS_SUPPORT + bool "Adaptive Group Switching" + depends on MT7603E_MT_RATE_ADAPTION + default n + +config MT7603E_IDS_SUPPORT + bool "IDS (Intrusion Detection System) Support" +# depends on WIFI_DRIVER + default n + +config MT7603E_WIFI_WORK_QUEUE + bool "Work Queue" +# depends on WIFI_DRIVER + default n + +config MT7603E_WIFI_SKB_RECYCLE + bool "SKB Recycle(Linux)" +# depends on WIFI_DRIVER + default n + +config MT7603E_RTMP_FLASH_SUPPORT + bool "Flash Support" +# depends on WIFI_DRIVER + default y + +config MT7603E_LED_CONTROL_SUPPORT + bool "LED Support" +# depends on WIFI_DRIVER + default n + +config MT7603E_SINGLE_SKU + bool "Single SKU" +# depends on WIFI_DRIVER + default n + +config MT7603E_SINGLE_SKU_V2 + bool "Single SKU V2" + depends on MT7603E_SINGLE_SKU && RALINK_RT6352 + default n + +config MT7603E_HW_ANTENNA_DIVERSITY + bool "Antenna Diversity Support" + depends on MT7603E_RLT_AP_SUPPORT || MT7603E_RLT_STA_SUPPORT + depends on RALINK_RT5350 + default n + +config MT7603E_ATE_SUPPORT + bool "ATE/QA Support" +# depends on WIFI_DRIVER + default y + +config MT7603E_RT2860V2_AP_V24_DATA_STRUCTURE + bool +# depends on WIFI_DRIVER + default y + +config MT7603E_RT2860V2_AP_32B_DESC + bool "32 Byte Descriptor Support" +# depends on WIFI_DRIVER + depends on RALINK_RT6352 || RALINK_MT7620 + default n + +config MT7603E_MEMORY_OPTIMIZATION + bool "Memory Optimization" +# depends on WIFI_DRIVER + default n + +#config MT7603E_RTMP_INTERNAL_TX_ALC +# bool "TSSI Compensation" +# depends on WIFI_DRIVER +# depends on RALINK_RT3350 || RALINK_RT3352 || RALINK_RT5350 || RALINK_RT6352 +# default n + +#config MT7603E_RTMP_TEMPERATURE_CALIBRATION +# bool "Temperature Calibration" +# depends on WIFI_DRIVER +# depends on RALINK_RT6352 +# default n + +config MT7603E_HOTSPOT + bool "Passpoint-R1" +# depends on WIFI_DRIVER + default n + +config MT7603E_MT_HOTSPOT_R2 + bool "Passpoint Release-2 Support" + depends on HOTSPOT + select MT7603E_MT_DOT11W_PMF_SUPPORT + default n + +config MT7603E_MT_RTMP_TEMPERATURE_TX_ALC + bool "Temperature Tx Power Compensation" +# depends on WIFI_DRIVER + default n + +config MT7603E_UAPSD + bool "UAPSD support" +# depends on WIFI_DRIVER + default y + + +# +# Section for chip architectures +# +# "RLT MAC Support" +config MT7603E_RLT_MAC + bool +# depends on WIFI_DRIVER + default n + +config MT7603E_RLT_BBP + bool + +config MT7603E_RLT_RF + bool + +# "RTMP MAC Support" +config MT7603E_RTMP_MAC + bool + depends on WIFI_DRIVER + default n + +config MT7603E_RTMP_BBP + bool + +config MT7603E_RTMP_RF + bool + +#config MT7603E_MT_EPA_ELNA +# bool "ePAeLNA" +# depends on WIFI_DRIVER +# default n +#choice +# prompt "PA,LNA Type" +# depends on MT7603E_MT_WIFI +# +# config MT7603E_MT_IPA_ILNA +# bool "iPAiLNA" +# +# config MT7603E_MT_IPA_ELNA +# bool "iPAeLNA" +# +# config MT7603E_MT_EPA_ILNA +# bool "ePAiLNA" +# +# config MT7603E_MT_EPA_ELNA +# bool "ePAeLNA" +#endchoice +# +#config MT7603E_MT_PA_LNA +# string +# depends on MT7603E_MT_WIFI +# default "iPAiLNA" if MT7603E_MT_IPA_ILNA +# default "iPAeLNA" if MT7603E_MT_IPA_ELNA +# default "ePAiLNA" if MT7603E_MT_EPA_ILNA +# default "ePAeLNA" if MT7603E_MT_EPA_ELNA +# +# +# Section for chip architectures +# +# "RLT MAC Support" +#config MT7603E_RLT_MAC +# bool +# depends on WIFI_DRIVER +# default n + +#config MT7603E_RLT_BBP +# bool + +#config MT7603E_RLT_RF +# bool + +# "RTMP MAC Support" +#config MT7603E_RTMP_MAC +# bool +# depends on WIFI_DRIVER +# default n + +#config MT7603E_RTMP_BBP +# bool + +#config MT7603E_RTMP_RF +# bool + +# +# Section for interfaces +# +config MT7603E_RTMP_PCI_SUPPORT + bool + +config MT7603E_RTMP_USB_SUPPORT + bool + +config MT7603E_RTMP_RBUS_SUPPORT + bool + +endmenu + +menu "WiFi Operation Modes" + choice + prompt "Main Mode" + default MT7603E_MT_WIFI_MODE_AP + + config MT7603E_MT_WIFI_MODE_AP + bool "AP" + + config MT7603E_MT_WIFI_MODE_STA + bool "STA" + + config MT7603E_MT_WIFI_MODE_BOTH + bool "APSTA" + endchoice + + if MT7603E_MT_WIFI_MODE_AP || MT7603E_MT_WIFI_MODE_BOTH + +config MT7603E_RLT_AP_SUPPORT + tristate "UnifyMAC 802.11n AP support" + default y +# depends on NET_RADIO + select WIRELESS_EXT + select WEXT_SPY + select WEXT_PRIV + +config MT7603E_WDS_SUPPORT + bool "WDS" + depends on MT7603E_RLT_AP_SUPPORT + default n + +config MT7603E_MBSS_SUPPORT + bool "MBSSID" + depends on MT7603E_RLT_AP_SUPPORT + default y + +config MT7603E_NEW_MBSSID_MODE + bool "New MBSSID MODE" + depends on MT7603E_RLT_AP_SUPPORT && MT7603E_MBSS_SUPPORT + # depends on RALINK_RT3883 || RALINK_RT3352 || RALINK_RT5350 || RALINK_RT6352 || RALINK_MT7620 || RALINK_MT7621 + default n + +config MT7603E_ENHANCE_NEW_MBSSID_MODE + bool "Enhanced MBSSID mode" + depends on MT7603E_NEW_MBSSID_MODE + default n +config MT7603E_CFG80211_SUPPORT + bool "CFG80211" + depends on MT7603E_RLT_AP_SUPPORT + default n + +config MT7603E_SNIFFER_MIB_CMD + bool "SNIFFER_MIB_CMD" + depends on MT7603E_SNIFFER_SUPPORT + default n + +config MT7603E_ALL_NET_EVENT + bool "ALL_NET_EVENT" + depends on MT7603E_RLT_AP_SUPPORT + default n + +config MT7603E_ACL_V2_SUPPORT + bool "ACL_V2" + depends on MT7603E_RLT_AP_SUPPORT + + +config MT7603E_APCLI_SUPPORT + bool "AP-Client Support" + depends on MT7603E_RLT_AP_SUPPORT + default y +config MT7603E_MULTI_APCLI_SUPPORT + bool "MULTI AP-Client Support" + depends on MT7603E_APCLI_SUPPORT + default y +config MT7603E_MAC_REPEATER_SUPPORT + bool "MAC Repeater Support" + depends on MT7603E_RLT_AP_SUPPORT + depends on MT7603E_APCLI_SUPPORT + depends on RALINK_RT6352 || RALINK_MT7620 || MT7603E_RALINK_MT7603E + default y +config MT7603E_AIRPLAY_SUPPORT + bool "AirPlay Support" + depends on MT7603E_APCLI_SUPPORT + +#config MT7603E_MT_MESH_SUPPORT +# bool "MESH Support" +# depends on MT7603E_RLT_AP_SUPPORT + +config MT7603E_DFS_SUPPORT + bool "DFS" + depends on MT7603E_RLT_AP_SUPPORT + select RALINK_TIMER_DFS + +#config MT7603E_DOT11R_FT_SUPPORT +# bool "802.11r Fast BSS Transition" +# depends on MT7603E_RLT_AP_SUPPORT + +#config MT7603E_DOT11K_RRM_SUPPORT +# bool "802.11k Radio Resource Management" +# depends on MT7603E_RLT_AP_SUPPORT + +config MT7603E_LLTD_SUPPORT + bool "LLTD (Link Layer Topology Discovery Protocol)" + depends on MT7603E_RLT_AP_SUPPORT + default y + +config MT7603E_NINTENDO_AP + bool "Nintendo AP" + depends on MT7603E_RLT_AP_SUPPORT + +config MT7603E_COC_SUPPORT + bool "CoC Support" + depends on MT7603E_RLT_AP_SUPPORT + default n + +#config MT7603E_ RT2860V2_SNMP +# bool "Net-SNMP Support" +# depends on MT7603E_RLT_AP_SUPPORT + +config MT7603E_MCAST_RATE_SPECIFIC + bool "User specific tx rate of mcast pkt" + depends on MT7603E_RLT_AP_SUPPORT +config MT7603E_PREVENT_ARP_SPOOFING_SUPPORT + bool "Detect ARP spoof pkts attack" + depends on MT7603E_RLT_AP_SUPPORT + +#config MT7603E_EXT_BUILD_CHANNEL_LIST +# bool "Extension Channel List" +# depends on MT7603E_RLT_AP_SUPPORT + +#config MT7603E_AUTO_CH_SELECT_ENHANCE +# bool "Auto Channel Selection Enhancement" +# depends on MT7603E_RLT_AP_SUPPORT + +config MT7603E_MULTI_CORE_SUPPORT + bool "multi core support" + depends on TARGET_ramips_mt7621 + default n + + endif + + source "./src/mt7603_wifi_ap/Kconfig" + +endmenu + +#"MT7603E" +config MT7603E_RALINK_MT7603E + bool + default y + select MT7603E_RTMP_PCI_SUPPORT + +endif + +#if MT7603E_RLT_MAC +# config MT7603E_RLT_MAC +# bool +# default y +#endif + +#if MT7603E_RTMP_MAC +# config MT7603E_RTMP_MAC +# bool +# default y +#endif + +#if MT7603E_MT_MAC +if MT7603E_RALINK_MT7603E + config MT7603E_MT_MAC + bool + default y +endif +#endif MT7603E_MT_WIFI +#endif +#endif FIRST_IF_MT7603E || SECOND_IF_MT7603E +endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/History.txt b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/History.txt new file mode 100644 index 000000000..67af4f5f9 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/History.txt @@ -0,0 +1,96 @@ +Release Note: + +[V4.0.0.7] +Host Driver: +1. Bug fixed for TGn 4.2.12 PMK caching and 4.2.11 pre-authentication issue. +2. Bug fixed for 802.1x issue of WEP encryption. +3. Add UAPSD support. +4. Add APCLI_AUTO_CONNECT_SUPPORT function. +5. Fix MCU INT CR read/write issue. +6. modify rate retry rule. +7. Fix QA tool: check the writing length to write all to flash. +8. Fix memory leak issue when command TxPwr send fail. +9. Fix MT7603E load fw fail issue that need to adjust PCIe LDO setting to 1.2V. +10. Fix the WSC config status( in beacon & probe resp ) is wrong when we key the wrong DUT's enrolee PIN. +11. ATE tool: + a. fix txpower can not be set at ATE mode issue. + b. Add code for TxTone Power HQADLL command and iwpriv. +12. Fix Makefile/Kconfig: + a. we should use CONFIG_SINGLE_SKU_V2, not CONFIG_SINGLE_SKU. + b. Remove RTMP_TEMPERATURE_TX_ALC because this driver flag is not valid. (controlled by FW) + +F/W: +1. Add EDCA and Slot time set command. +2. Enable and update CCK_MRC fix. +3. Enable TX PA dynamic GC +4. Support negative TMAC PWR +5. Set CR_TSSI_PA_OFFSET_HPA +6. Lower WF0/WF1 TSSI ON TH to 0dBm + + +[V4.0.0.6 ] +Host Driver: +1.Add tx power percentage function for iPA +2. Modify AP PS, use CR replace AP PS CMD +3.fix apcli vs DIR655 IOT can't set ba size to 21 +4.Set MSSID *7, iPhone5 connect then ping overnight, still ping fail (?¶çˆ¾PSE Redirection bit被è?èµ? STA ping fail) +for ps retrieve function, rename "token_enq_fail" to "token_enq_all_fail" to let it more clear. +5. MT7603 auto rate update +6. Fix [AP][TGn]:4.2.47 Power Save, fail on step 8,each PS poll the station sends to the APUT, the APUT is expected to send only one directed data packet in response. +7. Fix TGn 4.2.11 & 4.2.12 PMK cache is delete in Auth. Req. +8. add PSE logical reset when detect pse abonormal condition +9. add sw based PDMA watchdog to detect & recovery PDMA TX/RX hang + +F/W: +Fix PCIE FW download fail when sw reboot, reset HIF then trigger WDT. +1. Add DMA scheduler workaround. +2. Add Admission control. +3. Add TX power % support. + + +[MT7603E_DPA_LinuxAP_4.0.0.5_20140511] +1. Fixed Cal Free IC eeprom endian issue. +2. Fixed IOT issue with Linksys WUSB6300. +3. AP-client repeater: fixed icv error when authmode/encryptype update. +4. Fixed crash issue that tasklet for processing pci dma done for mcu cmd sometimes will execute after event tasklet. +5. Update auto fall back config and algorithm. +6. Update firmware to fixed FW re-download fail issue. +7. Do 802.11 header endian swap for ps retrieve packet. +8. Fixed LED command big endian issue. +9. Fixed MlmeHardTransmitTxRing cache flush issue that will cause memory for dma and cache non sync at big endian platform. +10. Modify check en/disable RTS/CTS conditions. +11. Fixed radio on/off cmd parameters to correct value. +12. Update patch for flash mode. +13. Fixed LED RadioOff issue. +14. ATE: + a. fixed Tx/Rx antenna switch resulting wrong Tx power level work around. + b. patch PCIE ASPM write efuse Add PCIe Compile flag. + c. add iwpriv TXCONT + d. add iwpriv for carrier suppression test TXCARR + e. Initialize Tx power with EEPROM array when ATESTART + f. Fix CONFIG_QA blocking setting power when only CONFIG_ATE is chosen + + +[MT7603E_DPA_LinuxAP_4.0.0.4_20140411] +1. Support IGMP Snooping function. +2. Fix NewRateAdapt Error in STA mode. +3. Fixed apcli ICV error issue to decrypt Broadcast packet from AP. +4. Fixed BAR issues: + a. Change SW BAR rate to CCK 1M. + b. Send SW BAR for ap power saving to refresh peer sta side reordering buffer (Intel IOT). + c. Add SW BAR mechanism which SN will control by wtbl per tid. + d. Considering the BAR data rate in both 2.4G & 5G + e. SendRefreshBar when recv. CmdPsClearRsp, this modify will make sure the 1st. packet in PSE is BAR after PS. +5. Update new firmware for BBP issue. +6. Upload E1/E2 default EEPROM bin file. +7. Fixed ATE bugs for Tx power setting, BW40 channel control, and Rx issue. +8. Change MAX_NUMBER_OF_MAC definition to support 32 association STAs. +9. Correct ApCli entry setting to fix throughput issue. +10. Fix sometimes software tx will stuck since Intel STA in ps mode is very frequently. +11. Fine tune TXOP settings. +12. Fixed the bug when spatial extension on/off. +13. Fixed AP client TKIP/WEP connection issue with Broadcom AP. + + +[MT7603E_DPA_LinuxAP_4.0.0.4_20140401] +1. Init AP Driver version diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/Kconfig b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/Kconfig new file mode 100644 index 000000000..5e3d0e6ca --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/Kconfig @@ -0,0 +1,533 @@ +if FIRST_IF_MT7603E || SECOND_IF_MT7603E +config MT7603E_RLT_WIFI + tristate "RLT 7603 WIFI Driver" + select MT7603E_WIFI_BASIC_FUNC if MT7603E_RLT_WIFI + +config MT7603E_MT_WIFI_PATH + string + depends on MT7603E_RLT_WIFI + default "rlt_wifi" + +if MT7603E_RLT_WIFI +menu "WiFi Generic Feature Options" + +if FIRST_IF_MT7603E +choice + prompt "EEPROM Type of 1st Card" + depends on ! FIRST_IF_NONE + + config MT7603E_FIRST_IF_EEPROM_PROM + bool "EEPROM" + + config MT7603E_FIRST_IF_EEPROM_EFUSE + bool "EFUSE" + + config MT7603E_FIRST_IF_EEPROM_FLASH + bool "FLASH" +endchoice + +config MT7603E_RT_FIRST_CARD_EEPROM + string + depends on ! FIRST_IF_NONE + default "prom" if MT7603E_FIRST_IF_EEPROM_PROM + default "efuse" if MT7603E_FIRST_IF_EEPROM_EFUSE + default "flash" if MT7603E_FIRST_IF_EEPROM_FLASH +endif +# endif FIRST_IF_MT7603E + +if SECOND_IF_MT7603E +choice + prompt "EEPROM Type of 2nd Card" + depends on ! SECOND_IF_NONE + + config MT7603E_SECOND_IF_EEPROM_PROM + bool "EEPROM" + + config MT7603E_SECOND_IF_EEPROM_EFUSE + bool "EFUSE" + + config MT7603E_SECOND_IF_EEPROM_FLASH + bool "FLASH" +endchoice + +config MT7603E_RT_SECOND_CARD_EEPROM + string + depends on ! SECOND_IF_NONE + default "prom" if MT7603E_SECOND_IF_EEPROM_PROM + default "efuse" if MT7603E_SECOND_IF_EEPROM_EFUSE + default "flash" if MT7603E_SECOND_IF_EEPROM_FLASH +endif +#endif SECOND_IF_MT7603E + +config MT7603E_MULTI_INF_SUPPORT + bool + default y if !FIRST_IF_NONE && !SECOND_IF_NONE + +config MT7603E_WIFI_BASIC_FUNC + bool "Basic Functions" + select WIRELESS_EXT + select WEXT_SPY + select WEXT_PRIV + +config MT7603E_WSC_INCLUDED + bool "WSC (WiFi Simple Config)" + depends on WIFI_DRIVER + default y + +config MT7603E_WSC_V2_SUPPORT + bool "WSC V2(WiFi Simple Config Version 2.0)" + depends on WIFI_DRIVER + default y + +config MT7603E_WSC_NFC_SUPPORT + bool "WSC out-of-band(NFC)" + depends on WIFI_DRIVER + default n + +config MT7603E_DOT11N_DRAFT3 + bool "802.11n Draft3" + depends on WIFI_DRIVER + default n + +#config MT7603E_DOT11_VHT_AC +# bool "802.11 ac" +# depends on WIFI_DRIVER +# default n + +config MT7603E_DOT11W_PMF_SUPPORT + bool "PMF" + depends on WIFI_DRIVER + default y + +#config MT7603E_TXBF_SUPPORT +# bool "Tx Bean Forming Support" +# depends on WIFI_DRIVER +# default n + +#config MT7603E_WMM_ACM_SUPPORT +# bool "WMM ACM" +# depends on WIFI_DRIVER +# default n + +config MT7603E_LLTD_SUPPORT + bool "LLTD (Link Layer Topology Discovery Protocol)" + depends on WIFI_DRIVER + default y + +config MT7603E_QOS_DLS_SUPPORT + bool "802.11e DLS ((Direct-Link Setup) Support" + depends on WIFI_DRIVER + default n + + +config MT7603E_WAPI_SUPPORT + bool "WAPI Support" + depends on WIFI_DRIVER + default y + +config MT7603E_CARRIER_DETECTION_SUPPORT + bool "Carrier Detect" + depends on WIFI_DRIVER + default n + +config MT7603E_IGMP_SNOOP_SUPPORT + bool "IGMP Snooping" + depends on WIFI_DRIVER + default n + +config MT7603E_BLOCK_NET_IF + bool "NETIF Block" + depends on WIFI_DRIVER + default n + help + Support Net interface block while Tx-Sw queue full + +config MT7603E_TXBF_SUPPORT + bool "Tx Bean Forming Support (Only 3883)" + depends on WIFI_DRIVER + depends on RALINK_RT2883 || RALINK_RT3883 + default n +# +# optimize dma cache mapping for internal mips platform +# +config MT7603E_DMA_CACHE_OPTIMIZE + bool "optimize dma cache mapping for internal mips platform" + depends on WIFI_DRIVER + default n + +#config MT7603E_VIDEO_TURBINE_SUPPORT +# bool "Video Turbine support" +# depends on WIFI_DRIVER +# default n + +#config MT7603E_RA_CLASSIFIER +# tristate "Ralink Flow Classifier" +# depends on WIFI_DRIVER +# default n + +config MT7603E_RATE_ADAPTION + bool "New Rate Adaptation support" + depends on WIFI_DRIVER + default y + +config MT7603E_NEW_RATE_ADAPT_SUPPORT + bool "Intelligent Rate Adaption" + depends on WIFI_DRIVER && MT7603E_RATE_ADAPTION + default y + +config MT7603E_AGS_SUPPORT + bool "Adaptive Group Switching" + depends on WIFI_DRIVER && MT7603E_RATE_ADAPTION + default n + +config MT7603E_IDS_SUPPORT + bool "IDS (Intrusion Detection System) Support" + depends on WIFI_DRIVER + default n + +config MT7603E_WIFI_WORK_QUEUE + bool "Work Queue" + depends on WIFI_DRIVER + default n + +config MT7603E_WIFI_SKB_RECYCLE + bool "SKB Recycle(Linux)" + depends on WIFI_DRIVER + default n + +config MT7603E_PUSH_SUPPORT + bool "Config Push Support" + depends on WIFI_DRIVER + default n + +#config MT7603E_EASY_SETUP_SUPPORT +# bool "Whole Home Coverage - Easy Setup" +# depends on WIFI_DRIVER +# default n + +config MT7603E_EVENT_NOTIFIER_SUPPORT + bool "Whole Home Coverage - Event Notifier" + depends on WIFI_DRIVER + default n + +config MT7603E_SMART_CARRIER_SENSE_SUPPORT + bool "Smart Carrier Sense" + depends on WIFI_DRIVER + default y +config MT7603E_MBO_SUPPORT + bool "MBO Support" + depends on WIFI_DRIVER + select INTERWORKING + select WNM_SUPPORT + select DOT11K_RRM_SUPPORT + select DOT11R_FT_SUPPORT + select DOT11W_PMF_SUPPORT + select PASSPOINT_R2 + default n +config MT7603E_RTMP_FLASH_SUPPORT + bool "Flash Support" + depends on WIFI_DRIVER + default n + +config MT7603E_MWDS_SUPPORT + bool "Mixed WDS(MWDS)" + default n + +config MT7603E_AIR_MONITOR_SUPPORT + bool "Air Monitor Support" + depends on WIFI_DRIVER + default n + +config MT7603E_STA_FORCE_ROAM_SUPPORT + bool "Sta Force Roam Support" + depends on WIFI_DRIVER + default n + +config MT7603E_ROAMING_ENHANCE_SUPPORT + bool "Roaming Enhance Support" + depends on WIFI_DRIVER + default n + +config MT7603E_WIFI_FWD_UPDATED + bool "Wifi Forwarding Support Update" + depends on WIFI_DRIVER + default n + +config MT_BTCOEX_CONCURRENT + bool "Coexisence Event Notify between BT and WiFi" + depends on WIFI_DRIVER + default n + +config MT7603E_LED_CONTROL_SUPPORT + bool "LED Support" + depends on WIFI_DRIVER + default n + +config MT7603E_SINGLE_SKU_V2 + bool "Single SKU V2" + depends on WIFI_DRIVER + default n + +config MT7603E_HW_ANTENNA_DIVERSITY + bool "Antenna Diversity Support" + depends on MT7603E_RLT_AP_SUPPORT || RLT_STA_SUPPORT + depends on RALINK_RT5350 + default n + +config MT7603E_ATE_SUPPORT + bool "ATE/QA Support" + depends on WIFI_DRIVER + default y + +config MT7603E_RT2860V2_AP_V24_DATA_STRUCTURE + bool + depends on WIFI_DRIVER + default y + +config MT7603E_RT2860V2_AP_32B_DESC + bool "32 Byte Descriptor Support" + depends on WIFI_DRIVER + depends on MT7603E_RALINK_RT6352 || RALINK_MT7620 + default n + +config MT7603E_MEMORY_OPTIMIZATION + bool "Memory Optimization" + depends on WIFI_DRIVER + default n + +config MT7603E_RTMP_INTERNAL_TX_ALC + bool "TSSI Compensation" + depends on WIFI_DRIVER + depends on RALINK_RT3350 || RALINK_RT3352 || RALINK_RT5350 || MT7603E_RALINK_RT6352 + default n + +config MT7603E_RTMP_TEMPERATURE_CALIBRATION + bool "Temperature Calibration" + depends on WIFI_DRIVER + depends on MT7603E_RALINK_RT6352 + default n + +config MT7603E_HOTSPOT + bool "Passpoint-R1" + depends on WIFI_DRIVER + default n + +config MT7603E_PASSPOINT_R2 + bool "Passpoint Release-2 Support" + depends on MT7603E_HOTSPOT + select MT7603E_DOT11W_PMF_SUPPORT + default n + +config MT7603E_UAPSD + bool "MT7603E_UAPSD support" + depends on WIFI_DRIVER + default y + +#config MT7603E_EPA_ELNA +# bool "ePAeLNA" +# depends on WIFI_DRIVER +# default n + +choice + prompt "PA,LNA Type" + depends on MT7603E_RLT_WIFI + + config MT7603E_IPA_ILNA + bool "iPAiLNA" + + config MT7603E_IPA_ELNA + bool "iPAeLNA" + + config MT7603E_EPA_ILNA + bool "ePAiLNA" + + config MT7603E_EPA_ELNA + bool "ePAeLNA" +endchoice + +config MT7603E_PA_LNA + string + depends on MT7603E_RLT_WIFI + default "iPAiLNA" if MT7603E_IPA_ILNA + default "iPAeLNA" if MT7603E_IPA_ELNA + default "ePAiLNA" if MT7603E_EPA_ILNA + default "ePAeLNA" if MT7603E_EPA_ELNA + +# +# Section for chip architectures +# +# "RLT MAC Support" +config MT7603E_RLT_MAC + bool + depends on WIFI_DRIVER + default n + +config MT7603E_RLT_BBP + bool + +config MT7603E_RLT_RF + bool + +# "RTMP MAC Support" +config MT7603E_RTMP_MAC + bool + depends on WIFI_DRIVER + default n + +config MT7603E_RTMP_BBP + bool + +config MT7603E_RTMP_RF + bool + +# +# Section for interfaces +# +config MT7603E_RTMP_PCI_SUPPORT + bool + +config MT7603E_RTMP_USB_SUPPORT + bool + +config MT7603E_RTMP_RBUS_SUPPORT + bool + +endmenu + +menu "WiFi Operation Modes" + choice + prompt "Main Mode" + default MT7603E_WIFI_MODE_AP + + config MT7603E_WIFI_MODE_AP + bool "AP" + + config MT7603E_WIFI_MODE_STA + bool "STA" + + config MT7603E_WIFI_MODE_BOTH + bool "APSTA" + endchoice + + if MT7603E_WIFI_MODE_AP || MT7603E_WIFI_MODE_BOTH + source "drivers/net/wireless/mtk/mt7603e/mt7603_wifi_ap/Kconfig" + endif + + #if MT7603E_WIFI_MODE_STA || MT7603E_WIFI_MODE_BOTH + # source "drivers/net/wireless/rlt_wifi_sta/Kconfig" + #endif +endmenu + +#"RT2860 series" +config MT7603E_RALINK_RT28XX + bool + default n + select MT7603E_RTMP_PCI_SUPPORT + +#"RT3092" +config MT7603E_RALINK_RT3092 + bool + default n + select MT7603E_RTMP_PCI_SUPPORT + +#"RT3572" +config MT7603E_RALINK_RT3572 + bool + default n + select MT7603E_RTMP_USB_SUPPORT + +#"RT5392" +config MT7603E_RALINK_RT5392 + bool + default n + select MT7603E_RTMP_PCI_SUPPORT + +#"RT5572" +config MT7603E_RALINK_RT5572 + bool + default n + select MT7603E_RTMP_USB_SUPPORT + +#"RT5592" +config MT7603E_RALINK_RT5592 + bool + default n + select MT7603E_RTMP_PCI_SUPPORT + +#"MT7620/RT6352" +config MT7603E_RALINK_RT6352 + bool + default n + select MT7603E_RTMP_RBUS_SUPPORT +# select MT7603E_RTMP_TEMPERATURE_CALIBRATION +# select MT7603E_RTMP_INTERNAL_TX_ALC + +#"MT7610E" +config MT7603E_RALINK_MT7610E + bool + default n + select MT7603E_RTMP_PCI_SUPPORT + +#"MT7610U" +config MT7603E_RALINK_MT7610U + bool + default n + select MT7603E_RTMP_USB_SUPPORT + +#"RT8592" +config MT7603E_RALINK_RT8592 + bool + default n + select MT7603E_RTMP_PCI_SUPPORT + +#"MT7612E" +config MT7603E_RALINK_MT7612E + bool + default n + select MT7603E_RTMP_PCI_SUPPORT + +#"MT7612U" +config MT7603E_RALINK_MT7612U + bool + default n + select MT7603E_RTMP_USB_SUPPORT + +#"MT7603E" +config MT7603E_RALINK_MT7603E + bool + default y + select MT7603E_RTMP_PCI_SUPPORT + +#"MT7603U" +config MT7603E_RALINK_MT7603U + bool + default n + select MT7603E_RTMP_USB_SUPPORT + +endif + +#if MT7603E_RLT_MAC +# config MT7603E_RLT_MAC +# bool +# default y +#endif + +#if MT7603E_RTMP_MAC +# config MT7603E_RTMP_MAC +# bool +# default y +#endif + +if MT7603E_RALINK_MT7603E + config MT7603E_MT_MAC + bool + default y +endif + +if MT7603E_RALINK_MT7603U + config MT7603E_MT_MAC + bool + default y +endif +endif +#endif FIRST_IF_MT7603E || SECOND_IF_MT7603E diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/Kconfig.mt_wifi b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/Kconfig.mt_wifi new file mode 100644 index 000000000..978f7f97c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/Kconfig.mt_wifi @@ -0,0 +1,513 @@ +if FIRST_IF_MT7603E || SECOND_IF_MT7603E +config MT_WIFI + tristate "MT WIFI Driver" + +config MT_WIFI_PATH + string + depends on MT_WIFI + default "mt_wifi" + +if MT_WIFI +menu "WiFi Generic Feature Options" + +if FIRST_IF_MT7603E +choice + prompt "EEPROM Type of 1st Card" + depends on ! FIRST_IF_NONE + + config FIRST_MT_IF_EEPROM_PROM + bool "EEPROM" + + config FIRST_MT_IF_EEPROM_EFUSE + bool "EFUSE" + + config FIRST_MT_IF_EEPROM_FLASH + bool "FLASH" +endchoice + +config RT_FIRST_CARD_EEPROM + string + depends on ! FIRST_IF_NONE + default "prom" if FIRST_MT_IF_EEPROM_PROM + default "efuse" if FIRST_MT_IF_EEPROM_EFUSE + default "flash" if FIRST_MT_IF_EEPROM_FLASH +endif +# endif FIRST_IF_MT7603E + +if SECOND_IF_MT7603E +choice + prompt "EEPROM Type of 2nd Card" + depends on ! SECOND_IF_NONE + + config SECOND_MT_IF_EEPROM_PROM + bool "EEPROM" + + config SECOND_MT_IF_EEPROM_EFUSE + bool "EFUSE" + + config SECOND_MT_IF_EEPROM_FLASH + bool "FLASH" +endchoice + +config RT_SECOND_CARD_EEPROM + string + depends on ! SECOND_IF_NONE + default "prom" if SECOND_MT_IF_EEPROM_PROM + default "efuse" if SECOND_MT_IF_EEPROM_EFUSE + default "flash" if SECOND_MT_IF_EEPROM_FLASH +endif +#endif SECOND_IF_MT7603E + +config MULTI_INF_SUPPORT + bool + default y if !FIRST_IF_NONE && !SECOND_IF_NONE + +#config WIFI_BASIC_FUNC +# bool "Basic Functions" +# select WIRELESS_EXT +# select WEXT_SPY +# select WEXT_PRIV + +config MT_WSC_INCLUDED + bool "WSC (WiFi Simple Config)" + depends on WIFI_DRIVER + default y + +config MT_WSC_V2_SUPPORT + bool "WSC V2(WiFi Simple Config Version 2.0)" + depends on MT_WSC_INCLUDED + default y + +config MT_DOT11N_DRAFT3 + bool "802.11n Draft3" + depends on WIFI_DRIVER + default y + +config MT_DOT11_VHT_AC + bool "802.11 ac" + depends on WIFI_DRIVER + default n + +config WSC_NFC_SUPPORT + bool "WSC out-of-band(NFC)" + depends on WIFI_DRIVER + default n + +config MT_DOT11W_PMF_SUPPORT + bool "PMF Support" + depends on WIFI_DRIVER + default y + +config MT_TXBF_SUPPORT + bool "Tx Bean Forming Support" + depends on WIFI_DRIVER + default n + +#config MT_WMM_ACM_SUPPORT +# bool "WMM ACM" +# depends on WIFI_DRIVER +# default n + +config MT_LLTD_SUPPORT + bool "LLTD (Link Layer Topology Discovery Protocol)" + depends on WIFI_DRIVER + default y + +config MT_QOS_DLS_SUPPORT + bool "802.11e DLS ((Direct-Link Setup) Support" + depends on WIFI_DRIVER + default n + +config MT_WAPI_SUPPORT + bool "WAPI Support" + depends on WIFI_DRIVER + default y + +config MT_CARRIER_DETECTION_SUPPORT + bool "Carrier Detect" + depends on WIFI_DRIVER + default n + +config MT7603E_MBO_SUPPORT + bool "MBO Support" + depends on WIFI_DRIVER + select INTERWORKING + select WNM_SUPPORT + select DOT11K_RRM_SUPPORT + select DOT11R_FT_SUPPORT + select DOT11W_PMF_SUPPORT + select PASSPOINT_R2 + default n + +config MT_IGMP_SNOOP_SUPPORT + bool "IGMP Snooping" + depends on WIFI_DRIVER + default n + +config MT_BLOCK_NET_IF + bool "NETIF Block" + depends on WIFI_DRIVER + default n + help + Support Net interface block while Tx-Sw queue full + +config MT_DMA_CACHE_OPTIMIZE + bool "optimize dma cache mapping for internal mips platform" + depends on WIFI_DRIVER + default n + +#config MT_TXBF_SUPPORT +# bool "Tx Bean Forming Support (Only 3883)" +# depends on WIFI_DRIVER +# depends on RALINK_RT2883 || RALINK_RT3883 +# default n + +#config MT_VIDEO_TURBINE_SUPPORT +# bool "Video Turbine support" +# depends on WIFI_DRIVER +# default n + +#config MT_RA_CLASSIFIER +# tristate "Ralink Flow Classifier" +# depends on WIFI_DRIVER +# default n + +config MT_RATE_ADAPTION + bool "New Rate Adaptation support" + depends on WIFI_DRIVER + default y + +config MT_NEW_RATE_ADAPT_SUPPORT + bool "Intelligent Rate Adaption" + depends on WIFI_DRIVER && MT_RATE_ADAPTION + default y + +config MT_AGS_SUPPORT + bool "Adaptive Group Switching" + depends on WIFI_DRIVER && MT_RATE_ADAPTION + default n + +config MT_IDS_SUPPORT + bool "IDS (Intrusion Detection System) Support" + depends on WIFI_DRIVER + default n + +config MT_WIFI_WORK_QUEUE + bool "Work Queue" + depends on WIFI_DRIVER + default n + +config MT_WIFI_SKB_RECYCLE + bool "SKB Recycle(Linux)" + depends on WIFI_DRIVER + default n + +config MT_RTMP_FLASH_SUPPORT + bool "Flash Support" + depends on WIFI_DRIVER + default n + +config CONFIG_PUSH_SUPPORT + bool "Config Push Support" + depends on WIFI_DRIVER + default y +config CONFIG_EASY_SETUP_SUPPORT + bool "Whole Home Coverage - Easy Setup" + depends on WIFI_DRIVER + default n + +config EVENT_NOTIFIER_SUPPORT + bool "Whole Home Coverage - Event Notifier" + depends on WIFI_DRIVER + default n +config MWDS_SUPPORT + bool "Mixed WDS(MWDS)" + default y +config AIR_MONITOR_SUPPORT + bool "Air Monitor Support" + depends on WIFI_DRIVER + default y + +config STA_FORCE_ROAM_SUPPORT + bool "Sta Force Roam Support" + depends on WIFI_DRIVER + default y + +config ROAMING_ENHANCE_SUPPORT + bool "Roaming Enhance Support" + depends on WIFI_DRIVER + default y + +config WIFI_FWD_UPDATED + bool "Wifi Forwarding Support Update" + depends on WIFI_DRIVER + default n + +config MT_BTCOEX_CONCURRENT + bool "Coexisence Event Notify between BT and WiFi" + depends on WIFI_DRIVER + default n + +config MT_LED_CONTROL_SUPPORT + bool "LED Support" + depends on WIFI_DRIVER + default n + +config MT_SINGLE_SKU_V2 + bool "Single SKU V2" + depends on WIFI_DRIVER + default n + +config MT_HW_ANTENNA_DIVERSITY + bool "Antenna Diversity Support" + depends on RLT_AP_SUPPORT || RLT_STA_SUPPORT + depends on RALINK_RT5350 + default n + +config MT_ATE_SUPPORT + bool "ATE/QA Support" + depends on WIFI_DRIVER + default y + +config MT_RT2860V2_AP_V24_DATA_STRUCTURE + bool + depends on WIFI_DRIVER + default y + +config MT_RT2860V2_AP_32B_DESC + bool "32 Byte Descriptor Support" + depends on WIFI_DRIVER + depends on RALINK_RT6352 || RALINK_MT7620 + default n + +config MT_MEMORY_OPTIMIZATION + bool "Memory Optimization" + depends on WIFI_DRIVER + default n + +#config MT_RTMP_INTERNAL_TX_ALC +# bool "TSSI Compensation" +# depends on WIFI_DRIVER +# depends on RALINK_RT3350 || RALINK_RT3352 || RALINK_RT5350 || RALINK_RT6352 +# default n + +#config MT_RTMP_TEMPERATURE_CALIBRATION +# bool "Temperature Calibration" +# depends on WIFI_DRIVER +# depends on RALINK_RT6352 +# default n + +config MT_HOTSPOT + bool "Passpoint-R1" + depends on WIFI_DRIVER + default n + +config MT_HOTSPOT_R2 + bool "Passpoint Release-2 Support" + depends on HOTSPOT + select MT_DOT11W_PMF_SUPPORT + default n + +config MT_UAPSD + bool "UAPSD support" + depends on WIFI_DRIVER + default y + +#config MT_EPA_ELNA +# bool "ePAeLNA" +# depends on WIFI_DRIVER +# default n + +choice + prompt "PA,LNA Type" + depends on MT_WIFI + + config MT_IPA_ILNA + bool "iPAiLNA" + + config MT_IPA_ELNA + bool "iPAeLNA" + + config MT_EPA_ILNA + bool "ePAiLNA" + + config MT_EPA_ELNA + bool "ePAeLNA" +endchoice + +config MT_PA_LNA + string + depends on MT_WIFI + default "iPAiLNA" if MT_IPA_ILNA + default "iPAeLNA" if MT_IPA_ELNA + default "ePAiLNA" if MT_EPA_ILNA + default "ePAeLNA" if MT_EPA_ELNA + +# +# Section for chip architectures +# +# "RLT MAC Support" +config RLT_MAC + bool + depends on WIFI_DRIVER + default n + +config RLT_BBP + bool + +config RLT_RF + bool + +# "RTMP MAC Support" +config RTMP_MAC + bool + depends on WIFI_DRIVER + default n + +config RTMP_BBP + bool + +config RTMP_RF + bool + +# +# Section for interfaces +# +config RTMP_PCI_SUPPORT + bool + +config RTMP_USB_SUPPORT + bool + +config RTMP_RBUS_SUPPORT + bool + +endmenu + +menu "WiFi Operation Modes" + choice + prompt "Main Mode" + default MT_WIFI_MODE_AP + + config MT_WIFI_MODE_AP + bool "AP" + + config MT_WIFI_MODE_STA + bool "STA" + + config MT_WIFI_MODE_BOTH + bool "APSTA" + endchoice + + if MT_WIFI_MODE_AP || MT_WIFI_MODE_BOTH + source "drivers/net/wireless/mt_wifi_ap/Kconfig" + endif + + #if MT_WIFI_MODE_STA || MT_WIFI_MODE_BOTH + # source "drivers/net/wireless/rlt_wifi_sta/Kconfig" + #endif +endmenu + +#"RT2860 series" +config RALINK_RT28XX + bool + default n + select RTMP_PCI_SUPPORT + +#"RT3092" +config RALINK_RT3092 + bool + default n + select RTMP_PCI_SUPPORT + +#"RT3572" +config RALINK_RT3572 + bool + default n + select RTMP_USB_SUPPORT + +#"RT5392" +config RALINK_RT5392 + bool + default n + select RTMP_PCI_SUPPORT + +#"RT5572" +config RALINK_RT5572 + bool + default n + select RTMP_USB_SUPPORT + +#"RT5592" +config RALINK_RT5592 + bool + default n + select RTMP_PCI_SUPPORT + +#"MT7620/RT6352" +config RALINK_RT6352 + bool + default n + select RTMP_RBUS_SUPPORT +# select RTMP_TEMPERATURE_CALIBRATION +# select RTMP_INTERNAL_TX_ALC + +#"MT7610E" +config RALINK_MT7610E + bool + default n + select RTMP_PCI_SUPPORT + +#"MT7610U" +config RALINK_MT7610U + bool + default n + select RTMP_USB_SUPPORT + +#"RT8592" +config RALINK_RT8592 + bool + default n + select RTMP_PCI_SUPPORT + +#"MT7612E" +config RALINK_MT7612E + bool + default n + select RTMP_PCI_SUPPORT + +#"MT7612U" +config RALINK_MT7612U + bool + default n + select RTMP_USB_SUPPORT + +#"MT7603E" +config RALINK_MT7603E + bool + default n + select RTMP_PCI_SUPPORT + +endif + +#if RLT_MAC +# config RLT_MAC +# bool +# default y +#endif + +#if RTMP_MAC +# config RTMP_MAC +# bool +# default y +#endif + +#if MT_MAC +if RALINK_MT7603E + config MT_MAC + bool + default y +endif +#endif MT_WIFI +endif +#endif FIRST_IF_MT7603E || SECOND_IF_MT7603E diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/Makefile b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/Makefile new file mode 100644 index 000000000..bc074835b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/Makefile @@ -0,0 +1,678 @@ +RT28xx_MODE = AP + + + +TARGET = LINUX + + +# CHIPSET +# rt2860, rt2870, rt2880, rt2070, rt3070, rt3090, rt3572, rt3062, rt3562, rt3593, rt3573 +# rt3562(for rt3592), rt3050, rt3350, rt3352, rt5350, rt5370, rt5390, rt5572, rt5592, +# rt8592(for rt85592), +# mt7601e, mt7601u, +# mt7650e, mt7630e, mt7610e, mt7650u, mt7630u, mt7610u +# mt7662e, mt7632e, mt7612e, mt7662u, mt7632u, mt7612u +# mt7603e, mt7603u, mt7636u, mt7636s + + +CHIPSET = mt7603e + + +MODULE = $(word 1, $(CHIPSET)) + +#OS ABL - YES or NO +OSABL = NO + +#Build Prealloc ko +PREALLOC = 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 = MT53XX +#PLATFORM = PC_AUTO_BUILD +#PLATFORM = BB_SOC +#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 +#PLATFORM = MT7620 +#PLATFORM = MT7621 +#PLATFORM = MSTAR + +#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 +ifeq ($(CHIPSET),mt7628) +PLATFORM = MT7628 +endif + +#RELEASE Package +RELEASE = DPA + + +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),BB_SOC) +LINUX_SRC = $(KERNEL_DIR) +#CROSS_COMPILE = /opt/trendchip/mips-linux-uclibc/usr/bin/mips-linux-uclibc- +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) +ifeq ($(OSABL),YES) +LINUX_SRC = $(RT28xx_DIR)/../../../../../build_linux +else +LINUX_SRC = $(RT28xx_DIR)/../../../../build_linux +endif +ifeq ($(CROSS_COMPILE),) +CROSS_COMPILE=armv7a-mediatek451_001_vfp-linux-gnueabi- +endif +CC=$(CROSS_COMPILE)gcc +$(warning =============================================) +$(warning CC=$(CC) for wifi driver) +$(warning =============================================) +endif + +ifeq ($(PLATFORM),MT53XX) +TARGET = LINUX +#****** For system auto build ****** +#LINUX_SRC=$(KERNEL_OBJ_ROOT)/$(KERNEL_VER)/$(KERNEL_CONFIG)_modules +#****** For local build ****** +# uncomment the following lines +VM_LINUX_ROOT ?= $(word 1, $(subst /vm_linux/,/vm_linux /, $(shell pwd))) +LINUX_ROOT ?= $(VM_LINUX_ROOT) +LINUX_SRC=$(VM_LINUX_ROOT)/output/mtk_android/mt5399_cn_android/rel/obj/kernel/chiling/kernel/linux-3.10/mt5399_android_smp_mod_defconfig_modules +OBJ_ROOT ?= $(VM_LINUX_ROOT)/output/mtk_android/mt5399_cn_android/rel/obj +export KERNEL_OBJ_ROOT=$(LINUX_SRC)/../.. +ifeq ($(CROSS_COMPILE),) +CROSS_COMPILE=/mtkoss/gnuarm/vfp_4.5.1_2.6.27_cortex-a9-rhel4/i686/bin/armv7a-mediatek451_001_vfp-linux-gnueabi- +endif +ifeq "$(CC)" "gcc" +CC ?= $(CROSS_COMPILE)gcc +endif +$(warning =============================================) +$(warning CC=$(CC) for wifi driver LINUX_SRC=$(LINUX_SRC)) +$(warning TARGET=$(TARGET)) +$(warning =============================================) +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),PC_AUTO_BUILD) +LINUX_SRC=/proj/srv_wcnautobuild/external/linux-3.10.59/ +#CROSS_COMPILE=/proj/srv_wcnautobuild/external/gcc-4.9.2/bin/ +CROSS_COMPILE= +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 + +ifeq ($(PLATFORM),MT7620) +LINUX_SRC = /home/share/src/MT7601/AP/RT288x_SDK/source/linux-2.6.36.x +CROSS_COMPILE = /opt/buildroot-gcc342/bin/mipsel-linux- +endif + +ifeq ($(PLATFORM),MT7621) +LINUX_SRC = /root/SDK_4_2_0_0/RT288x_SDK/source/linux-2.6.36.x +CROSS_COMPILE = /opt/buildroot-gcc463/usr/bin/mipsel-linux- +endif + + +ifeq ($(PLATFORM),MT7628) +LINUX_SRC = /root/Working/MT7628_SDK_2013_0912/RT288x_SDK/source/linux-2.6.36.x +CROSS_COMPILE = /opt/buildroot-gcc342/bin/mipsel-linux- +endif + + +ifeq ($(PLATFORM),MSTAR) +PREALLOC = YES + +#628 TV Platform +#LINUX_SRC = /proj/mtk05650/share/mstar/628/kernel/RedLion/3.1.10/ +#LINUX_SRC = /proj/mtk05650/share/mstar/628/kernel/3.10.23/3.10.23/ +#LINUX_SRC = /proj/mtk05650/share/mstar/628/kernel/3.1.10_Madison_TVOS/3.1.10/ + +#918 TV Android4.3 Platform +#LINUX_SRC = /proj/mtk05650/share/mstar/918_TV/android4.3/kernel/3.1.10_Napoli_tvos/3.1.10/ + +#918 Box Android4.4 Platform +#LINUX_SRC = /proj/mtk05650/share/mstar/toolchain/918_Box_android4.4/3.1.10_Napoli_tvos_0616_new_kernel/3.1.10/ + +#928 Box Android4.4 Platform +#LINUX_SRC = /proj/mtk05650/share/mstar/928/928_kernel_0716/3.10.23/ +#LINUX_SRC = /proj/mtk05650/share/mstar/928/928_kernel_0722/3.10.23/ +LINUX_SRC = /proj/mtk05650/share/mstar/928/20140710_KERN-3.10.23-00911089/3.10.23/ + +#ToolChian Setting +#CROSS_COMPILE = /proj/mtk05650/share/mstar/628/toolchain/arm-2012.09/bin/arm-none-linux-gnueabi- +CROSS_COMPILE = /proj/mtk05650/share/mstar/toolchain/arm-2010.09/bin/arm-none-linux-gnueabi- +#CROSS_COMPILE = /proj/mtk05650/share/mstar/toolchain/918_Box_android4.4/arm-2012.09/bin/arm-none-linux-gnueabi- +#CROSS_COMPILE = /proj/mtk05650/share/mstar/toolchain/918_Box_android4.4/arm-2012.09/bin/arm-none-linux-gnueabi- +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 sdk_build_tools + +ifeq ($(TARGET),LINUX) +all: build_tools $(TARGET) plug_in +else +all: $(TARGET) +endif + +build_tools: + $(MAKE) -C tools + $(RT28xx_DIR)/tools/bin2h + +sdk_build_tools: + if [ -f $(RT28xx_DIR)/eeprom_log ]; then \ + rm -f $(RT28xx_DIR)/eeprom_log + fi + echo $(EE_TYPE) >> eeprom_log + echo $(CHIPSET) >> eeprom_log + if [ -f $(RT28xx_DIR)/eeprom/SA/MT7603E_EEPROM.bin ]; then \ + echo 'find SA/MT7603E_EEPROM.bin' >> eeprom_log ; \ + cp -f $(RT28xx_DIR)/eeprom/SA/MT7603E_EEPROM.bin $(RT28xx_DIR)/eeprom/MT7603E_EEPROM.bin ; \ + else \ + cp -f $(RT28xx_DIR)/eeprom/$(EE_TYPE)/MT7603E_EEPROM.bin $(RT28xx_DIR)/eeprom/MT7603E_EEPROM.bin ; \ + fi + $(MAKE) -C tools + $(RT28xx_DIR)/tools/bin2h +# rm -f $(RT28xx_DIR)/eeprom/SA/MT7603E_EEPROM.bin + +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) +ifneq ($(PLATFORM),BB_SOC) + cp -f $(RT28xx_DIR)/os/linux/$(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 +endif +else +ifeq ($(RT28xx_MODE),APSTA) + cp -f $(RT28xx_DIR)/os/linux/$(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/$(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 +ifeq ($(PREALLOC), YES) + cp -f PREALLOC/os/linux/Makefile.6.prealloc PREALLOC/os/linux/Makefile + $(MAKE) -C $(LINUX_SRC) SUBDIRS=$(RT28xx_DIR)/PREALLOC/os/linux modules + $(SHELL) cp_prealloc.sh +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) +ifneq ($(PLATFORM),BB_SOC) + cp -f $(RT28xx_DIR)/os/linux/$(MODULE)_ap.ko /tftpboot +ifeq ($(OSABL),YES) + cp -f $(RT28xx_DIR)/os/linux/$(MODULE)_ap_util.ko /tftpboot + cp -f $(RT28xx_DIR)/os/linux/$(MODULE)_ap_net.ko /tftpboot +endif +else + rm -f os/linux/$(MODULE)_ap.ko.lzma + /root/bin/lzma e os/linux/$(MODULE)_ap.ko os/linux/$(MODULE)_ap.ko.lzma +endif +else +ifeq ($(RT28xx_MODE),APSTA) + cp -f $(RT28xx_DIR)/os/linux/$(MODULE)_apsta.ko /tftpboot +ifeq ($(OSABL),YES) + cp -f $(RT28xx_DIR)/os/linux/$(MODULE)_apsta_util.ko /tftpboot + cp -f $(RT28xx_DIR)/os/linux/$(MODULE)_apsta_net.ko /tftpboot +endif +else +ifeq ($(PLATFORM),PC_AUTO_BUILD) +else + cp -f $(RT28xx_DIR)/os/linux/$(MODULE)_sta.ko /tftpboot +endif +ifeq ($(OSABL),YES) + cp -f $(RT28xx_DIR)/os/linux/$(MODULE)_sta_util.ko /tftpboot + cp -f $(RT28xx_DIR)/os/linux/$(MODULE)_sta_net.ko /tftpboot +endif +endif +endif +endif +ifeq ($(PLATFORM),MT85XX) + mkdir -p $(RT28xx_DIR)/../../../../../BDP_Generic/build_linux_ko/src/driver/wlan/ + cp -f $(RT28xx_DIR)/os/linux/mt7603u_sta.ko $(RT28xx_DIR)/../../../../../BDP_Generic/build_linux_ko/src/driver/wlan/ +endif + +plug_in: + $(MAKE) -C $(LINUX_SRC) SUBDIRS=$(RT28xx_DIR)/tools/plug_in MODULE_FLAGS="$(WFLAGS)" + +release: build_tools + $(MAKE) -C $(RT28xx_DIR)/striptool -f Makefile.release clean + $(MAKE) -C $(RT28xx_DIR)/striptool -f Makefile.release + striptool/striptool.out +ifeq ($(PLATFORM),MT85XX) + cp -f tools/osabl_check.sh $(RELEASE)/ +endif +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 +ifeq ($(PREALLOC), YES) + cp -f PREALLOC/os/linux/Makefile.clean PREALLOC/os/linux/Makefile + $(MAKE) -C PREALLOC/os/linux clean + rm -rf PREALLOC/os/linux/Makefile +endif +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 +ifeq ($(PLATFORM),MT85XX) + cp -f $(RT28xx_DIR)/os/linux/mt7603u_sta.ko $(RT28xx_DIR)/../../../../../../BDP_Generic/build_linux_ko/src/driver/wlan/ +endif +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 +ifeq ($(PLATFORM),MT85XX) + cp -f $(RT28xx_DIR)/os/linux/mt7603u_sta.ko $(RT28xx_DIR)/../../../../../../BDP_Generic/build_linux_ko/src/driver/wlan/ +endif +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 +ifeq ($(PLATFORM),MT85XX) +ifeq ($(OSABL),YES) + cp -f $(RT28xx_DIR)/os/linux/mt7603u_sta.ko $(RT28xx_DIR)/../../../../../../BDP_Generic/build_linux_ko/src/driver/wlan/ +endif +endif +endif + +# Declare the contents of the .PHONY variable as phony. We keep that information in a variable +.PHONY: $(PHONY) + + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/RT2860AP.dat b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/RT2860AP.dat new file mode 100644 index 000000000..b81ced989 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/RT2860AP.dat @@ -0,0 +1,147 @@ +#The word of "Default" must not be removed +Default +ed_th_nonCE=52 +Cts2SelfTh=1500 +CountryRegion=5 +CountryRegionABand=7 +CountryCode=TW +BssidNum=1 +SSID1=RT2860AP1 +SSID2= +SSID3= +SSID4= +WirelessMode=9 +TxRate=0 +Channel=11 +BasicRate=15 +BeaconPeriod=100 +DtimPeriod=1 +TxPower=100 +DisableOLBC=0 +BGProtection=0 +MaxStaNum=0 +TxPreamble=0 +RTSThreshold=2347 +FragThreshold=2346 +TxBurst=1 +PktAggregate=0 +TurboRate=0 +WmmCapable=0 +APSDCapable=0 +DLSCapable=0 +APAifsn=3;7;1;1 +APCwmin=4;4;3;2 +APCwmax=6;10;4;3 +APTxop=0;0;94;47 +APACM=0;0;0;0 +BSSAifsn=3;7;2;2 +BSSCwmin=4;4;3;2 +BSSCwmax=10;10;4;3 +BSSTxop=0;0;94;47 +BSSACM=0;0;0;0 +AckPolicy=0;0;0;0 +NoForwarding=0 +NoForwardingBTNBSSID=0 +HideSSID=0 +StationKeepAlive=0 +ShortSlot=1 +AutoChannelSelect=0 +IEEE8021X=0 +IEEE80211H=0 +CSPeriod=10 +WirelessEvent=0 +IdsEnable=0 +AuthFloodThreshold=32 +AssocReqFloodThreshold=32 +ReassocReqFloodThreshold=32 +ProbeReqFloodThreshold=32 +DisassocFloodThreshold=32 +DeauthFloodThreshold=32 +EapReqFooldThreshold=32 +PreAuth=0 +AuthMode=OPEN +EncrypType=NONE +RekeyInterval=0 +RekeyMethod=DISABLE +PMKCachePeriod=10 +WPAPSK1= +WPAPSK2= +WPAPSK3= +WPAPSK4= +DefaultKeyID=1 +Key1Type=0 +Key1Str1= +Key1Str2= +Key1Str3= +Key1Str4= +Key2Type=0 +Key2Str1= +Key2Str2= +Key2Str3= +Key2Str4= +Key3Type=0 +Key3Str1= +Key3Str2= +Key3Str3= +Key3Str4= +Key4Type=0 +Key4Str1= +Key4Str2= +Key4Str3= +Key4Str4= +HSCounter=0 +AccessPolicy0=0 +AccessControlList0= +AccessPolicy1=0 +AccessControlList1= +AccessPolicy2=0 +AccessControlList2= +AccessPolicy3=0 +AccessControlList3= +WdsEnable=0 +WdsEncrypType=NONE +WdsList= +WdsKey= +RADIUS_Server=192.168.2.3 +RADIUS_Port=1812 +RADIUS_Key=ralink +own_ip_addr=192.168.5.234 +EAPifname=br0 +PreAuthifname=br0 +HT_HTC=0 +HT_RDG=0 +HT_EXTCHA=0 +HT_LinkAdapt=0 +HT_OpMode=0 +HT_MpduDensity=5 +HT_BW=1 +HT_AutoBA=1 +HT_AMSDU=0 +HT_BAWinSize=64 +HT_GI=1 +HT_LDPC=0 +HT_MCS=33 +VHT_BW=1 +VHT_SGI=1 +VHT_STBC=0 +VHT_BW_SIGNAL=0 +VHT_DisallowNonVHT=0 +VHT_LDPC=0 +MeshId=MESH +MeshAutoLink=1 +MeshAuthMode=OPEN +MeshEncrypType=NONE +MeshWPAKEY= +MeshDefaultkey=1 +MeshWEPKEY= +WscManufacturer= +WscModelName= +WscDeviceName= +WscModelNumber= +WscSerialNumber= +RadioOn=1 +PMFMFPC=0 +PMFMFPR=0 +PMFSHA256=0 +LoadCodeMethod=0 +ed_th_nonCE=52 diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/RT2860APCard.dat b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/RT2860APCard.dat new file mode 100644 index 000000000..4532b4ba4 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/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/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap.c new file mode 100644 index 000000000..e452c6f55 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap.c @@ -0,0 +1,3983 @@ +/**************************************************************************** + * 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" +#include "ap.h" + + +#ifdef SW_ATF_SUPPORT +#define WcidTxThr 43 +#define goodNodeMinDeqThr 433 +#define goodNodeMaxDeqThr 520 +#define badNodeMinDeqThr 43 +#define badNodeMinEnqThr 3 +#define badNodeMaxEnqThr 4 +#define FalseCCAThr 200 +#endif + +#ifdef MULTI_CLIENT_SUPPORT +#define MULTI_CLIENT_NUM 5 +UINT is_multiclient_mode_on(RTMP_ADAPTER *pAd) +{ + UINT res = 0; + //INT test = 1; //lk added for test + if (pAd->bManualMultiClientOn == 99) + return res; + + if (pAd->MultiClientOnMode == 0) + { + /* check by MacTable Size */ + if (pAd->MacTab.Size >= MULTI_CLIENT_NUM) + res = 1; + } +#ifdef TRAFFIC_BASED_TXOP + else if (pAd->MultiClientOnMode == 1) + { + /* check by pEntry's Traffic */ + if (pAd->StaTxopAbledCnt >= MULTI_CLIENT_NUM) + res = 1; + } +#endif + + return ( res || pAd->bManualMultiClientOn); +} +#endif + +#ifdef INTERFERENCE_RA_SUPPORT +UINT is_interference_mode_on(RTMP_ADAPTER *pAd) +{ + UINT res = 0; + + if (pAd->CommonCfg.Interfra >= 1) + res = 1; + + return res; +} +#endif + +char const *pEventText[EVENT_MAX_EVENT_TYPE] = { + "restart access point", + "successfully associated", + "has disassociated", + "has been aged-out and disassociated" , + "active countermeasures", + "has disassociated with invalid PSK password"}; + + +UCHAR get_apidx_by_addr(RTMP_ADAPTER *pAd, UCHAR *addr) +{ + UCHAR apidx; + + for (apidx=0; apidxApCfg.BssidNum; apidx++) + { + if (RTMPEqualMemory(addr, pAd->ApCfg.MBSSID[apidx].wdev.bssid, MAC_ADDR_LEN)) + break; + } + + return apidx; +} + + +// TODO: shiang-usw, need to revise this to asic specific functions! +INT set_wdev_if_addr(RTMP_ADAPTER *pAd, struct wifi_dev *wdev, INT opmode) +{ + INT idx = wdev->func_idx; + + if (opmode == OPMODE_AP) + { + COPY_MAC_ADDR(wdev->if_addr, pAd->CurrentAddress); +//+++Add by Carter for MT7603 +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (pAd->chipCap.hif_type == HIF_RTMP || pAd->chipCap.hif_type == HIF_RLT) + { + if (pAd->chipCap.MBSSIDMode >= MBSSID_MODE1) + { + UCHAR MacMask = 0; + + if ((pAd->ApCfg.BssidNum + MAX_APCLI_NUM + MAX_MESH_NUM) <= 2) + MacMask = 0xFE; + else if ((pAd->ApCfg.BssidNum + MAX_APCLI_NUM + MAX_MESH_NUM) <= 4) + MacMask = 0xFC; + else if ((pAd->ApCfg.BssidNum + MAX_APCLI_NUM + MAX_MESH_NUM) <= 8) + MacMask = 0xF8; + else if ((pAd->ApCfg.BssidNum + MAX_APCLI_NUM + MAX_MESH_NUM) <= 16) + MacMask = 0xF0; + + if (idx > 0) + { + wdev->if_addr[0] |= 0x2; + if (pAd->chipCap.MBSSIDMode == MBSSID_MODE1) + { + /* + Refer to HW definition - + Bit1 of MAC address Byte0 is local administration bit + and should be set to 1 in extended multiple BSSIDs' + Bit3~ of MAC address Byte0 is extended multiple BSSID index. + */ +#ifdef ENHANCE_NEW_MBSSID_MODE + wdev->if_addr[0] &= ((MacMask << 2) + 3); +#endif /* ENHANCE_NEW_MBSSID_MODE */ + wdev->if_addr[0] += ((wdev->func_idx - 1) << 2); + } +#ifdef ENHANCE_NEW_MBSSID_MODE + else + { + wdev->if_addr[pAd->chipCap.MBSSIDMode - 1] &= (MacMask); + wdev->if_addr[pAd->chipCap.MBSSIDMode - 1] += (idx - 1); + } +#endif /* ENHANCE_NEW_MBSSID_MODE */ + } + } + else + wdev->if_addr[5] += idx; + } +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + //TODO: Carter, Apcli interface and MESH interface shall use HWBSSID1 or HWBSSID2??? + UINT32 Value; + UCHAR MacMask = 0; + + //TODO: shall we make choosing which byte to be selectable??? + Value = 0x00000000; + RTMP_IO_READ32(pAd, LPON_BTEIR, &Value);//read BTEIR bit[31:29] for determine to choose which byte to extend BSSID mac address. + Value = Value | ((pAd->chipCap.MBSSIDMode -2) << 29); + RTMP_IO_WRITE32(pAd, LPON_BTEIR, Value); + + Value = 0x00000000; + RTMP_IO_READ32(pAd, RMAC_RMACDR, &Value); + Value = Value & 0xfcffffff;/* clear bit[25:24] */ + + if (pAd->ApCfg.BssidNum <= 2) { + Value &= ~RMACDR_MBSSID_MASK; + Value |= RMACDR_MBSSID(0x0); + MacMask = 0xef; + } + else if (pAd->ApCfg.BssidNum <= 4) { + Value &= ~RMACDR_MBSSID_MASK; + Value |= RMACDR_MBSSID(0x1); + MacMask = 0xcf; + } + else if (pAd->ApCfg.BssidNum <= 8) { + Value &= ~RMACDR_MBSSID_MASK; + Value |= RMACDR_MBSSID(0x2); + MacMask = 0x8f; + } + else if (pAd->ApCfg.BssidNum <= 16) { + Value &= ~RMACDR_MBSSID_MASK; + Value |= RMACDR_MBSSID(0x3); + MacMask = 0x0f; + } + else { + Value &= ~RMACDR_MBSSID_MASK; + Value |= RMACDR_MBSSID(0x3); + MacMask = 0x0f; + } + + RTMP_IO_WRITE32(pAd, RMAC_RMACDR, Value); + + if (idx > 0) + { + /* MT7603, bit1 in byte0 shall always be b'1 for Multiple BSSID */ + wdev->if_addr[0] |= 0x2; + + switch ((pAd->chipCap.MBSSIDMode -2)) { + case 0x1: /* choose bit[23:20]*/ + //mapping to MBSSID_MODE3 + wdev->if_addr[2] = wdev->if_addr[2] & MacMask;//clear high 4 bits, + wdev->if_addr[2] = (wdev->if_addr[2] | (idx << 4)); + break; + case 0x2: /* choose bit[31:28]*/ + //mapping to MBSSID_MODE4 + wdev->if_addr[3] = wdev->if_addr[3] & MacMask;//clear high 4 bits, + wdev->if_addr[3] = (wdev->if_addr[3] | (idx << 4)); + break; + case 0x3: /* choose bit[39:36]*/ + //mapping to MBSSID_MODE5 + wdev->if_addr[4] = wdev->if_addr[4] & MacMask;//clear high 4 bits, + wdev->if_addr[4] = (wdev->if_addr[4] | (idx << 4)); + break; + case 0x4: /* choose bit [47:44]*/ + //mapping to MBSSID_MODE6 + wdev->if_addr[5] = wdev->if_addr[5] & MacMask;//clear high 4 bits, + wdev->if_addr[5] = (wdev->if_addr[5] | (idx << 4)); + break; + default: /* choose bit[15:12]*/ + //mapping to MBSSID_MODE2 + wdev->if_addr[1] = wdev->if_addr[1] & MacMask;//clear high 4 bits, + wdev->if_addr[1] = (wdev->if_addr[1] | (idx << 4)); + break; + } + } + } +#endif /* MT_MAC */ +//---Add by Carter for MT7603 + } + + return 0; +} + + +/* + ========================================================================== + Description: + Initialize AP specific data especially the NDIS packet pool that's + used for wireless client bridging. + ========================================================================== + */ +NDIS_STATUS APInitialize(RTMP_ADAPTER *pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + INT i; + + DBGPRINT(RT_DEBUG_TRACE, ("---> APInitialize\n")); + + /* Init Group key update timer, and countermeasures timer */ + for (i = 0; i < MAX_MBSSID_NUM(pAd); i++) + RTMPInitTimer(pAd, &pAd->ApCfg.MBSSID[i].REKEYTimer, GET_TIMER_FUNCTION(GREKEYPeriodicExec), pAd, TRUE); + + RTMPInitTimer(pAd, &pAd->ApCfg.CounterMeasureTimer, GET_TIMER_FUNCTION(CMTimerExec), pAd, FALSE); +#ifndef BCN_OFFLOAD_SUPPORT +#endif + +#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 IGMP_SNOOP_SUPPORT + MulticastFilterTableInit(pAd, &pAd->pMulticastFilterTable); +#endif /* IGMP_SNOOP_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + initList(&pAd->DMSEntryList); +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT + RRM_CfgInit(pAd); +#endif /* DOT11K_RRM_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("<--- APInitialize\n")); + return Status; +} + + +/* + ========================================================================== + Description: + Shutdown AP and free AP specific resources + ========================================================================== + */ +VOID APShutdown(RTMP_ADAPTER *pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("---> APShutdown\n")); + + MlmeRadioOff(pAd); + +#ifdef RTMP_MAC_PCI + APStop(pAd); +#endif /* RTMP_MAC_PCI */ + +#ifdef IGMP_SNOOP_SUPPORT + MultiCastFilterTableReset(&pAd->pMulticastFilterTable); +#endif /* IGMP_SNOOP_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + DMSTable_Release(pAd); +#endif /* DOT11V_WNM_SUPPORT */ + + NdisFreeSpinLock(&pAd->MacTabLock); + +#ifdef WDS_SUPPORT + NdisFreeSpinLock(&pAd->WdsTabLock); +#endif /* WDS_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("<--- APShutdown\n")); +} + + +#ifdef DOT11W_PMF_SUPPORT +static INT ap_pmf_init(RTMP_ADAPTER *pAd, BSS_STRUCT *pMbss, INT idx) +{ + struct wifi_dev *wdev = &pMbss->wdev; + + /* + IEEE 802.11W/P.10 - + A STA that has associated with Management Frame Protection enabled + shall not use pairwise cipher suite selectors WEP-40, WEP-104, + TKIP, or "Use Group cipher suite". + + IEEE 802.11W/P.3 - + IEEE Std 802.11 provides one security protocol, CCMP, for protection + of unicast Robust Management frames. + */ + pMbss->PmfCfg.MFPC = FALSE; + pMbss->PmfCfg.MFPR = FALSE; + pMbss->PmfCfg.PMFSHA256 = FALSE; + +#ifdef DOT11_SAE_SUPPORT + if (wdev->AuthMode == Ndis802_11AuthModeWPA3PSK || wdev->AuthMode == Ndis802_11AuthModeWPA2PSKWPA3PSK) { + /* In WPA3 spec, When a WPA3-Personal only BSS is configured, + * Protected Management Frame (PMF) shall be set to required (MFPR=1) + * When WPA2-Personal and WPA3-Personal are configured on the same BSS (mixed mode), + * Protected Management Frame (PMF) shall be set to capable (MFPC = 1, MFPR = 0) + */ + pMbss->PmfCfg.MFPC = TRUE; + pMbss->PmfCfg.MFPR = (wdev->AuthMode == Ndis802_11AuthModeWPA2PSKWPA3PSK) ? FALSE : TRUE; + } +#endif +#ifdef CONFIG_OWE_SUPPORT + if (wdev->AuthMode == Ndis802_11AuthModeOWE) { + pMbss->PmfCfg.MFPC = TRUE; + pMbss->PmfCfg.MFPR = TRUE; + } +#endif +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + if (pMbss->PmfCfg.Desired_MFPR != pMbss->PmfCfg.MFPR && + (wdev->AuthMode == Ndis802_11AuthModeWPA3PSK || + wdev->AuthMode == Ndis802_11AuthModeWPA2PSKWPA3PSK || + wdev->AuthMode == Ndis802_11AuthModeOWE)) { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: PmfCfg Desired MFPR error\n", __func__)); + } +#endif +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + if (pMbss->PmfCfg.Desired_MFPC != pMbss->PmfCfg.MFPC && + (wdev->AuthMode == Ndis802_11AuthModeWPA3PSK || + wdev->AuthMode == Ndis802_11AuthModeWPA2PSKWPA3PSK || + wdev->AuthMode == Ndis802_11AuthModeOWE)) { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: PmfCfg Desired MFPC error\n", __func__)); + } +#endif + if (((((wdev->AuthMode == Ndis802_11AuthModeWPA2) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) && + (pMbss->PmfCfg.Desired_MFPC)) + #if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + || (((wdev->AuthMode == Ndis802_11AuthModeWPA3PSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSKWPA3PSK) || + wdev->AuthMode == Ndis802_11AuthModeOWE)) + #endif + ) + && (wdev->WepStatus == Ndis802_11AESEnable)) + { + pMbss->PmfCfg.MFPC = TRUE; + +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + if (wdev->AuthMode != Ndis802_11AuthModeWPA3PSK && + wdev->AuthMode != Ndis802_11AuthModeWPA2PSKWPA3PSK && + wdev->AuthMode != Ndis802_11AuthModeOWE) +#endif + pMbss->PmfCfg.MFPR = pMbss->PmfCfg.Desired_MFPR; + + /* IGTK default key index as 4 */ + pMbss->PmfCfg.IGTK_KeyIdx = 4; + + /* Derive IGTK */ + PMF_DeriveIGTK(pAd, &pMbss->PmfCfg.IGTK[0][0]); + +#ifdef MT_MAC + if ((pAd->chipCap.hif_type == HIF_MT) && (pAd->chipCap.FlgPMFEncrtptMode == PMF_ENCRYPT_MODE_2)) + { + CIPHER_KEY CipherKey; + USHORT Wcid; + + GET_PMF_GroupKey_WCID(pAd, Wcid, pMbss->mbss_idx); + CipherKey.KeyLen = 16; + memcpy(CipherKey.Key, &pMbss->PmfCfg.IGTK[0][0], CipherKey.KeyLen); + CipherKey.CipherAlg = CIPHER_BIP; + CmdProcAddRemoveKey(pAd, 0, pMbss->mbss_idx, 0, Wcid, SHAREDKEYTABLE, &CipherKey, BROADCAST_ADDR); + } +#endif + if ((pMbss->PmfCfg.Desired_PMFSHA256) || (pMbss->PmfCfg.MFPR)) + pMbss->PmfCfg.PMFSHA256 = TRUE; + + } else if (pMbss->PmfCfg.Desired_MFPC) { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: Security is not WPA2/WPA2PSK AES\n", __FUNCTION__)); + } + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: apidx=%d, MFPC=%d, MFPR=%d, SHA256=%d\n", + __FUNCTION__, idx, pMbss->PmfCfg.MFPC, + pMbss->PmfCfg.MFPR, pMbss->PmfCfg.PMFSHA256)); + + return TRUE; +} +#endif /* DOT11W_PMF_SUPPORT */ + + + +INT ap_security_init(RTMP_ADAPTER *pAd, struct wifi_dev *wdev, INT idx) +{ +#ifdef DOT11W_PMF_SUPPORT + ap_pmf_init(pAd, &pAd->ApCfg.MBSSID[idx], idx); +#endif /* DOT11W_PMF_SUPPORT */ + + /* decide the mixed WPA cipher combination */ + if (wdev->WepStatus == Ndis802_11TKIPAESMix) + { + switch ((UCHAR)wdev->AuthMode) + { + /* WPA mode */ + case Ndis802_11AuthModeWPA: + case Ndis802_11AuthModeWPAPSK: + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_NONE; + break; + + /* WPA2 mode */ + case Ndis802_11AuthModeWPA2: + case Ndis802_11AuthModeWPA2PSK: + wdev->WpaMixPairCipher = WPA_NONE_WPA2_TKIPAES; + break; + + /* WPA and WPA2 both mode */ + case Ndis802_11AuthModeWPA1WPA2: + case Ndis802_11AuthModeWPA1PSKWPA2PSK: + + /* In WPA-WPA2 and TKIP-AES mixed mode, it shall use the maximum */ + /* cipher capability unless users assign the desired setting. */ + if (wdev->WpaMixPairCipher == MIX_CIPHER_NOTUSE || + wdev->WpaMixPairCipher == WPA_TKIPAES_WPA2_NONE || + wdev->WpaMixPairCipher == WPA_NONE_WPA2_TKIPAES) + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIPAES; + break; + } + + } + else + wdev->WpaMixPairCipher = MIX_CIPHER_NOTUSE; + + if (wdev->WepStatus == Ndis802_11Encryption2Enabled || + wdev->WepStatus == Ndis802_11Encryption3Enabled || + wdev->WepStatus == Ndis802_11Encryption4Enabled) + { + RT_CfgSetWPAPSKKey(pAd, pAd->ApCfg.MBSSID[idx].WPAKeyString, + strlen(pAd->ApCfg.MBSSID[idx].WPAKeyString), + (PUCHAR)pAd->ApCfg.MBSSID[idx].Ssid, + pAd->ApCfg.MBSSID[idx].SsidLen, + pAd->ApCfg.MBSSID[idx].PMK); + } + /* Generate the corresponding RSNIE */ + RTMPMakeRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, idx); + + return TRUE; +} + +#ifndef WH_EZ_SETUP +static +#endif +INT ap_key_tb_init(RTMP_ADAPTER *pAd) +{ + BSS_STRUCT *pMbss; + struct wifi_dev *wdev; + USHORT Wcid; + INT idx, i; + + /* + Initialize security variable per entry, + 1. pairwise key table, re-set all WCID entry as NO-security mode. + 2. access control port status + */ + /* Init Security variables */ + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) + { + pMbss = &pAd->ApCfg.MBSSID[idx]; + wdev = &pAd->ApCfg.MBSSID[idx].wdev; + Wcid = 0; + + wdev->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + if (IS_WPA_CAPABILITY(wdev->AuthMode)) + wdev->DefaultKeyId = 1; + + /* Get a specific WCID to record this MBSS key attribute */ + GET_GroupKey_WCID(pAd, Wcid, idx); + + /* When WEP, TKIP or AES is enabled, set group key info to Asic */ + if (wdev->WepStatus == Ndis802_11WEPEnabled) + { + UCHAR CipherAlg, key_idx; + + for (key_idx=0; key_idx < SHARE_KEY_NUM; key_idx++) + { + CipherAlg = pAd->SharedKey[idx][key_idx].CipherAlg; + + if (pAd->SharedKey[idx][key_idx].KeyLen > 0) + { + /* Set key material to Asic */ + AsicAddSharedKeyEntry(pAd, idx, key_idx, &pAd->SharedKey[idx][key_idx]); + + if (key_idx == wdev->DefaultKeyId) + { + /* Generate 3-bytes IV randomly for software encryption using */ + for(i = 0; i < LEN_WEP_TSC; i++) + pAd->SharedKey[idx][key_idx].TxTsc[i] = RandomByte(pAd); + + /* Update WCID attribute table and IVEIV table */ + RTMPSetWcidSecurityInfo(pAd, + idx, + key_idx, + CipherAlg, + Wcid, + SHAREDKEYTABLE); + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + CmdProcAddRemoveKey(pAd, 0, idx, key_idx, Wcid, SHAREDKEYTABLE, &pAd->SharedKey[idx][key_idx], BROADCAST_ADDR); +#endif + } + } + } + } + else if ((wdev->WepStatus == Ndis802_11TKIPEnable) || + (wdev->WepStatus == Ndis802_11AESEnable) || + (wdev->WepStatus == Ndis802_11TKIPAESMix)) + { + /* Generate GMK and GNonce randomly per MBSS */ + GenRandom(pAd, wdev->bssid, pMbss->GMK); + GenRandom(pAd, wdev->bssid, pMbss->GNonce); + + /* Derive GTK per BSSID */ + WpaDeriveGTK(pMbss->GMK, + (UCHAR*)pMbss->GNonce, + wdev->bssid, + pMbss->GTK, + LEN_TKIP_GTK); + + /* Install Shared key */ + WPAInstallSharedKey(pAd, + wdev->GroupKeyWepStatus, + idx, + wdev->DefaultKeyId, + Wcid, + TRUE, + pMbss->GTK, + LEN_TKIP_GTK); + + } +#ifdef WAPI_SUPPORT + else if (pMbss->wdev.WepStatus == Ndis802_11EncryptionSMS4Enabled) + { + INT cnt; + + /* Initial the related variables */ + pMbss->wdev.DefaultKeyId = 0; + NdisMoveMemory(pMbss->key_announce_flag, AE_BCAST_PN, LEN_WAPI_TSC); + if (IS_HW_WAPI_SUPPORT(pAd)) + pMbss->sw_wpi_encrypt = FALSE; + else + pMbss->sw_wpi_encrypt = TRUE; + + /* Generate NMK randomly */ + for (cnt = 0; cnt < LEN_WAPI_NMK; cnt++) + pMbss->NMK[cnt] = RandomByte(pAd); + + /* Count GTK for this BSSID */ + RTMPDeriveWapiGTK(pMbss->NMK, pMbss->GTK); + + /* Install Shared key */ + WAPIInstallSharedKey(pAd, + wdev->GroupKeyWepStatus, + idx, + wdev->DefaultKeyId, + Wcid, + pMbss->GTK); + + } +#endif /* WAPI_SUPPORT */ + +#ifdef DOT1X_SUPPORT + /* Send singal to daemon to indicate driver had restarted */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPA2) + || (wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (wdev->IEEE8021X == TRUE)) + { + ;/*bDot1xReload = TRUE; */ + } +#endif /* DOT1X_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("### BSS(%d) AuthMode(%d)=%s, WepStatus(%d)=%s, AccessControlList.Policy=%ld\n", + idx, wdev->AuthMode, GetAuthMode(wdev->AuthMode), + wdev->WepStatus, GetEncryptType(wdev->WepStatus), + pMbss->AccessControlList.Policy)); + } + + + return TRUE; +} + +INT ap_key_tb_single_init(RTMP_ADAPTER *pAd, BSS_STRUCT *pDstMbss) +{ + BSS_STRUCT *pMbss; + struct wifi_dev *wdev; + USHORT Wcid; + INT idx, i; + +/* +* Initialize security variable per entry, +* 1. pairwise key table, re-set all WCID entry as NO-security mode. +* 2. access control port status +*/ + /* Init Security variables */ + + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) { + pMbss = &pAd->ApCfg.MBSSID[idx]; + wdev = &pAd->ApCfg.MBSSID[idx].wdev; + Wcid = 0; + + if (pMbss == pDstMbss) { + wdev->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + if (IS_WPA_CAPABILITY(wdev->AuthMode)) + wdev->DefaultKeyId = 1; + + /* Get a specific WCID to record this MBSS key attribute */ + GET_GroupKey_WCID(pAd, Wcid, idx); + + /* When WEP, TKIP or AES is enabled, set group key info to Asic */ + if (wdev->WepStatus == Ndis802_11WEPEnabled) { + UCHAR CipherAlg, key_idx; + + for (key_idx = 0; key_idx < SHARE_KEY_NUM; key_idx++) { + CipherAlg = pAd->SharedKey[idx][key_idx].CipherAlg; + + if (pAd->SharedKey[idx][key_idx].KeyLen > 0) { + /* Set key material to Asic */ + AsicAddSharedKeyEntry(pAd, idx, key_idx, + &pAd->SharedKey[idx][key_idx]); + + if (key_idx == wdev->DefaultKeyId) { + /* Generate 3-bytes IV randomly for software encryption using */ + for (i = 0; i < LEN_WEP_TSC; i++) + pAd->SharedKey[idx][key_idx].TxTsc[i] = RandomByte(pAd); + + /* Update WCID attribute table and IVEIV table */ + RTMPSetWcidSecurityInfo(pAd, + idx, + key_idx, + CipherAlg, + Wcid, + SHAREDKEYTABLE); +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + CmdProcAddRemoveKey(pAd, 0, idx, key_idx, Wcid, + SHAREDKEYTABLE, + &pAd->SharedKey[idx][key_idx], + BROADCAST_ADDR); +#endif + } + } + } + } else if ((wdev->WepStatus == Ndis802_11TKIPEnable) || + (wdev->WepStatus == Ndis802_11AESEnable) || + (wdev->WepStatus == Ndis802_11TKIPAESMix)) { + /* Generate GMK and GNonce randomly per MBSS */ + GenRandom(pAd, wdev->bssid, pMbss->GMK); + GenRandom(pAd, wdev->bssid, pMbss->GNonce); + + /* Derive GTK per BSSID */ + WpaDeriveGTK(pMbss->GMK, + (UCHAR *)pMbss->GNonce, + wdev->bssid, + pMbss->GTK, + LEN_TKIP_GTK); + + /* Install Shared key */ + WPAInstallSharedKey(pAd, + wdev->GroupKeyWepStatus, + idx, + wdev->DefaultKeyId, + Wcid, + TRUE, + pMbss->GTK, + LEN_TKIP_GTK); + + } +#ifdef WAPI_SUPPORT + else if (pMbss->wdev.WepStatus == Ndis802_11EncryptionSMS4Enabled) { + INT cnt; + + /* Initial the related variables */ + pMbss->wdev.DefaultKeyId = 0; + NdisMoveMemory(pMbss->key_announce_flag, AE_BCAST_PN, LEN_WAPI_TSC); + if (IS_HW_WAPI_SUPPORT(pAd)) + pMbss->sw_wpi_encrypt = FALSE; + else + pMbss->sw_wpi_encrypt = TRUE; + + /* Generate NMK randomly */ + for (cnt = 0; cnt < LEN_WAPI_NMK; cnt++) + pMbss->NMK[cnt] = RandomByte(pAd); + + /* Count GTK for this BSSID */ + RTMPDeriveWapiGTK(pMbss->NMK, pMbss->GTK); + + /* Install Shared key */ + WAPIInstallSharedKey(pAd, + wdev->GroupKeyWepStatus, + idx, + wdev->DefaultKeyId, + Wcid, + pMbss->GTK); + + } +#endif /* WAPI_SUPPORT */ + +#ifdef DOT1X_SUPPORT + /* Send signal to daemon to indicate driver had restarted */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2) || + (wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (wdev->IEEE8021X == TRUE)) { + ;/*bDot1xReload = TRUE; */ + } +#endif /* DOT1X_SUPPORT */ + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("### BSS(%d) AuthMode(%d)=%s, WepStatus(%d)=%s, AccessControlList.Policy=%ld\n", + idx, wdev->AuthMode, GetAuthMode(wdev->AuthMode), + wdev->WepStatus, GetEncryptType(wdev->WepStatus), + pMbss->AccessControlList.Policy)); + } + + } + + return TRUE; +} + + +static INT ap_hw_tb_init(RTMP_ADAPTER *pAd) +{ + INT i; +#ifdef A4_CONN + APCLI_STRUCT *pApCliEntry = NULL; +#endif + MAC_TABLE_ENTRY *pEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():Reset WCID Table\n", __FUNCTION__)); + + for (i=0; iMacTab.Content[i]; +#ifdef A4_CONN + if (IS_ENTRY_APCLI(pEntry)) { + pApCliEntry = &pAd->ApCfg.ApCliTab[pEntry->func_tb_idx]; + if (IS_APCLI_A4(pApCliEntry) && pEntry->Sst == SST_ASSOC + && pAd->MacTab.tr_entry[i].PortSecured == WPA_802_1X_PORT_SECURED) + continue; + } + if (pEntry->wcid == APCLI_MCAST_WCID) + continue; +#endif + AsicDelWcidTab(pAd, pEntry->wcid); + pAd->MacTab.tr_entry[i].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + AsicRemovePairwiseKeyEntry(pAd, (UCHAR)i); + } + + return TRUE; +} + +/*Nobody uses it currently*/ +INT ap_phy_rrm_init(RTMP_ADAPTER *pAd) +{ + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + AsicSetTxStream(pAd, pAd->Antenna.field.TxPath); + else +#endif /* MT_MAC */ + ASIC_RLT_SET_TX_STREAM(pAd, OPMODE_AP, TRUE); + + AsicSetRxStream(pAd, pAd->Antenna.field.RxPath); + + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + + // TODO: shiang-usw, get from MT7620_MT7610 Single driver, check this!! + N_ChannelCheck(pAd);//correct central channel offset + + AsicBBPAdjust(pAd); +#ifdef DOT11_VHT_AC + if (pAd->CommonCfg.BBPCurrentBW == BW_80) + pAd->hw_cfg.cent_ch = pAd->CommonCfg.vht_cent_ch; + else +#endif /* DOT11_VHT_AC */ + pAd->hw_cfg.cent_ch = pAd->CommonCfg.CentralChannel; + + AsicSwitchChannel(pAd, pAd->hw_cfg.cent_ch, FALSE); + AsicLockChannel(pAd, pAd->hw_cfg.cent_ch); + +#ifdef DOT11_VHT_AC +//+++Add by shiang for debug + DBGPRINT(RT_DEBUG_OFF, ("%s(): AP Set CentralFreq at %d(Prim=%d, HT-CentCh=%d, VHT-CentCh=%d, BBP_BW=%d)\n", + __FUNCTION__, pAd->hw_cfg.cent_ch, pAd->CommonCfg.Channel, + pAd->CommonCfg.CentralChannel, pAd->CommonCfg.vht_cent_ch, + pAd->CommonCfg.BBPCurrentBW)); +//---Add by shiang for debug +#endif /* DOT11_VHT_AC */ + + return TRUE; +} +INT ap_mlme_set_capability(RTMP_ADAPTER *pAd, BSS_STRUCT *pMbss) +{ + struct wifi_dev *wdev = &pMbss->wdev; + BOOLEAN SpectrumMgmt = FALSE; + +#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 */ + + pMbss->CapabilityInfo = CAP_GENERATE(1, + 0, + (wdev->WepStatus != Ndis802_11EncryptionDisabled), + (pAd->CommonCfg.TxPreamble == Rt802_11PreambleLong ? 0 : 1), + pAd->CommonCfg.bUseShortSlotTime, + SpectrumMgmt); + +#ifdef DOT11K_RRM_SUPPORT + if (pMbss->RrmCfg.bDot11kRRMEnable == TRUE) + pMbss->CapabilityInfo |= RRM_CAP_BIT; +#endif /* DOT11K_RRM_SUPPORT */ + + if (pMbss->wdev.bWmmCapable == TRUE) + { + /* + In WMM spec v1.1, A WMM-only AP or STA does not set the "QoS" + bit in the capability field of association, beacon and probe + management frames. + */ +/* pMbss->CapabilityInfo |= 0x0200; */ + } + +#ifdef UAPSD_SUPPORT + if (pMbss->wdev.UapsdInfo.bAPSDCapable == TRUE) + { + /* + QAPs set the APSD subfield to 1 within the Capability + Information field when the MIB attribute + dot11APSDOptionImplemented is true and set it to 0 otherwise. + STAs always set this subfield to 0. + */ + pMbss->CapabilityInfo |= 0x0800; + } +#endif /* UAPSD_SUPPORT */ + + return TRUE; +} + + +INT ap_func_init(RTMP_ADAPTER *pAd) +{ + +#ifdef MAT_SUPPORT + MATEngineInit(pAd); +#endif /* MAT_SUPPORT */ + +#ifdef CLIENT_WDS + CliWds_ProxyTabInit(pAd); +#endif /* CLIENT_WDS */ + + return TRUE; +} + + +static void update_edca_param(RTMP_ADAPTER *pAd) +{ + //TODO: + return ; +} + +/* + ========================================================================== + Description: + Start AP service. If any vital AP parameter is changed, a STOP-START + sequence is required to disassociate all STAs. + + IRQL = DISPATCH_LEVEL.(from SetInformationHandler) + IRQL = PASSIVE_LEVEL. (from InitializeHandler) + + Note: + Can't call NdisMIndicateStatus on this routine. + + RT61 is a serialized driver on Win2KXP and is a deserialized on Win9X + Serialized callers of NdisMIndicateStatus must run at IRQL = DISPATCH_LEVEL. + + ========================================================================== + */ +VOID APStartUp(RTMP_ADAPTER *pAd) +{ +#if defined(INF_AMAZON_SE) || defined(RTMP_MAC_USB) + UINT32 i; +#endif /* defined(INF_AMAZON_SE) || defined(RTMP_MAC_USB) */ + UCHAR idx; + UCHAR phy_mode = pAd->CommonCfg.cfg_wmode; + BOOLEAN bWmmCapable = FALSE; + EDCA_PARM *edca_param; + + DBGPRINT(RT_DEBUG_TRACE, ("===> APStartUp\n")); + +#ifdef INF_AMAZON_SE + for (i=0;iBulkOutDataSizeLimit[i]=24576; +#endif /* INF_AMAZON_SE */ + + AsicDisableSync(pAd); + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) + { + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[idx]; + struct wifi_dev *wdev = &pMbss->wdev; + UCHAR tr_tb_idx = MAX_LEN_OF_MAC_TABLE + idx; + + pMbss->mbss_idx = idx; +#ifdef AIRPLAY_SUPPORT + if (AIRPLAY_ON(pAd)) + pMbss->bcn_buf.bBcnSntReq = TRUE; + else + pMbss->bcn_buf.bBcnSntReq = FALSE; +#endif /* AIRPLAY_SUPPORT */ + pMbss->bcn_buf.bcn_state = BCN_TX_IDLE; + +#ifdef BCN_OFFLOAD_SUPPORT + pMbss->updateEventIsTriggered = FALSE; +#endif /* BCN_OFFLOAD_SUPPORT */ + + if ((pMbss->SsidLen <= 0) || (pMbss->SsidLen > MAX_LEN_OF_SSID)) + { + NdisMoveMemory(pMbss->Ssid, "HT_AP", 5); + pMbss->Ssid[5] = '0' + idx; + 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... + */ + wdev->func_idx = idx; + wdev->tr_tb_idx = tr_tb_idx; +//+++Add by Carter for MT7603 + wdev->func_dev = (VOID *)pMbss;//FIXME: dirty code for prevent ra1 up crash. +//---Add by Carter for MT7603 + set_wdev_if_addr(pAd, wdev, OPMODE_AP); + if (wdev->if_dev) + { + NdisMoveMemory(RTMP_OS_NETDEV_GET_PHYADDR(wdev->if_dev), + wdev->if_addr, MAC_ADDR_LEN); + } + COPY_MAC_ADDR(wdev->bssid, wdev->if_addr); + + wdev_init(pAd, wdev, WDEV_TYPE_AP); + if (idx == 0) + mgmt_tb_set_mcast_entry(pAd, MCAST_WCID); + + tr_tb_set_mcast_entry(pAd, tr_tb_idx, wdev); + COPY_MAC_ADDR(pAd->CommonCfg.Bssid, pAd->CurrentAddress); + + ap_security_init(pAd, wdev, idx); +#ifdef STA_FORCE_ROAM_SUPPORT + DBGPRINT(RT_DEBUG_OFF, + ("\n[Force Roam] => Force Roam Support = %d\n",pAd->en_force_roam_supp)); + DBGPRINT(RT_DEBUG_OFF, + ("[Force Roam] => StaLowRssiThr=%d dBm low_sta_renotify=%d sec StaAgeTime=%d sec\n",pAd->sta_low_rssi, pAd->low_sta_renotify,pAd->sta_age_time)); + DBGPRINT(RT_DEBUG_OFF, + ("[Force Roam] => MntrAgeTime=%d sec mntr_min_pkt_count=%d mntr_min_time=%d sec mntr_avg_rssi_pkt_count=%d\n", + pAd->mntr_age_time, pAd->mntr_min_pkt_count,pAd->mntr_min_time, pAd->mntr_avg_rssi_pkt_count)); + DBGPRINT(RT_DEBUG_OFF, + ("[Force Roam] => AclAgeTime=%d sec AclHoldTime=%d sec\n",pAd->acl_age_time, pAd->acl_hold_time)); +#endif + +#ifdef MWDS + if (wdev->bDefaultMwdsStatus == TRUE) + MWDSEnable(pAd, wdev->func_idx, TRUE, TRUE); +#endif + +#if defined(MAP_SUPPORT) && defined(A4_CONN) + if (IS_MAP_ENABLE(pAd)) + map_a4_init(pAd, pMbss->mbss_idx, TRUE); +#endif +#if defined(WAPP_SUPPORT) + wapp_init(pAd, pMbss); +#endif + +#ifdef WH_EZ_SETUP + if (IS_CONF_EZ_SETUP_ENABLED(wdev)) + ez_start(wdev, TRUE); + else + { +// ez_allocate_or_update_non_ez_band(wdev); + } +#endif /* WH_EZ_SETUP */ + + + ap_mlme_set_capability(pAd, pMbss); + +#ifdef WSC_V2_SUPPORT + if (pMbss->WscControl.WscV2Info.bEnableWpsV2) + { + /* WPS V2 doesn't support WEP and WPA/WPAPSK-TKIP. */ + if ((wdev->WepStatus == Ndis802_11WEPEnabled) || + (wdev->WepStatus == Ndis802_11TKIPEnable) || + (pMbss->bHideSsid)) + WscOnOff(pAd, idx, TRUE); + else + WscOnOff(pAd, idx, FALSE); + } +#endif /* WSC_V2_SUPPORT */ + + /* If any BSS is WMM Capable, we need to config HW CRs */ + if (pMbss->wdev.bWmmCapable) + bWmmCapable = TRUE; +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) +#if (MT7615_MT7603_COMBO_FORWARDING == 1) + { + if (wf_fwd_check_device_hook) + wf_fwd_check_device_hook(wdev->if_dev, INT_MBSSID, pMbss->mbss_idx, pAd->CommonCfg.Channel, 1); + } +#endif /* MT7615_MT7603_COMBO_FORWARDING */ +#endif +#ifdef DOT11U_INTERWORKING + pMbss->GASCtrl.b11U_enable = 1; +#endif/* DOT11U_INTERWORKING */ +#if defined(MAP_SUPPORT) && defined(WAPP_SUPPORT) + if (wdev->if_dev && pAd->net_dev) + wapp_send_bss_state_change(pAd, wdev, WAPP_BSS_START); +#endif + } + +#ifdef DOT11_N_SUPPORT + if (phy_mode != pAd->CommonCfg.PhyMode) + RTMPSetPhyMode(pAd, phy_mode); + + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) || bWmmCapable) + { + /* EDCA parameters used for AP's own transmission */ + if (pAd->CommonCfg.APEdcaParm.bValid == FALSE) + set_default_ap_edca_param(pAd); + + /* EDCA parameters to be annouced in outgoing BEACON, used by WMM STA */ + if (pAd->ApCfg.BssEdcaParm.bValid == FALSE) + set_default_sta_edca_param(pAd); + + edca_param = &pAd->CommonCfg.APEdcaParm; + } + else + edca_param = NULL; + AsicSetEdcaParm(pAd, edca_param); + + +#ifdef DOT11_N_SUPPORT + if (!WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = BW_20; /* Patch UI */ + + if (pAd->chipCap.hif_type == HIF_MT) + { + AsicSetRDG(pAd, pAd->CommonCfg.bRdg); + AsicWtblSetRDG(pAd, pAd->CommonCfg.bRdg); + + if (pAd->CommonCfg.bRdg) + AsicUpdateTxOP(pAd, WMM_PARAM_AC_1, 0x80); + else + AsicUpdateTxOP(pAd, WMM_PARAM_AC_1, 0); + } + + AsicSetRalinkBurstMode(pAd, pAd->CommonCfg.bRalinkBurstMode); + + /*update edca depend on CommCfg*/ + update_edca_param(pAd); // Currently do nothing inside... + +#ifdef PIGGYBACK_SUPPORT + RTMPSetPiggyBack(pAd, pAd->CommonCfg.bPiggyBackCapable); +#endif /* PIGGYBACK_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + + AsicSetBssid(pAd, pAd->CurrentAddress, 0x0); + + ap_hw_tb_init(pAd); + +#if defined(RTMP_MAC) || defined(RLT_MAC) +#ifdef FIFO_EXT_SUPPORT + if ((pAd->chipCap.hif_type == HIF_RTMP) || (pAd->chipCap.hif_type == HIF_RLT)) + AsicFifoExtSet(pAd); +#endif /* FIFO_EXT_SUPPORT */ +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + ap_phy_rrm_init(pAd); + + /* Clear BG-Protection flag */ + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); + +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPEnable == TRUE) + { + RTMP_CHIP_ENABLE_AP_MIMOPS(pAd,TRUE); + pAd->ApCfg.GreenAPLevel=GREENAP_WITHOUT_ANY_STAS_CONNECT; + } +#endif /* GREENAP_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + + MlmeSetTxPreamble(pAd, (USHORT)pAd->CommonCfg.TxPreamble); + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) + { + MlmeUpdateTxRates(pAd, FALSE, idx); + +#ifdef DYNAMIC_RX_RATE_ADJ + UpdateSuppRateBitmap(pAd); +#endif /* DYNAMIC_RX_RATE_ADJ */ + +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + MlmeUpdateHtTxRates(pAd, idx); +#endif /* DOT11_N_SUPPORT */ + } + + /* Set the RadarDetect Mode as Normal, bc the APUpdateAllBeaconFram() will refer this parameter. */ + 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 LED_CONTROL_SUPPORT + RTMPSetLED(pAd, LED_LINK_UP); +#endif /* LED_CONTROL_SUPPORT */ + +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) +#if (MT7615_MT7603_COMBO_FORWARDING == 1) + WifiFwdSet(pAd->CommonCfg.WfFwdDisabled); +#endif /* CONFIG_WIFI_PKT_FWD */ +#endif /* CONFIG_WIFI_PKT_FWD */ + ap_key_tb_init(pAd); + + ApLogEvent(pAd, pAd->CurrentAddress, EVENT_RESET_ACCESS_POINT); + pAd->Mlme.PeriodicRound = 0; + pAd->Mlme.OneSecPeriodicRound = 0; + pAd->MacTab.MsduLifeTime = 5; /* default 5 seconds */ + + OPSTATUS_SET_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED); + + RTMP_IndicateMediaState(pAd, NdisMediaStateConnected); + + + /* + NOTE!!!: + All timer setting shall be set after following flag be cleared + fRTMP_ADAPTER_HALT_IN_PROGRESS + */ + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + + RadarStateCheck(pAd); + + + + /* start sending BEACON out */ + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + +#ifdef DFS_SUPPORT + if (IS_DOT11_H_RADAR_STATE(pAd, RD_SILENCE_MODE)) + NewRadarDetectionStart(pAd); +#endif /* DFS_SUPPORT */ +#ifdef CARRIER_DETECTION_SUPPORT + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + CarrierDetectionStart(pAd); +#endif /* CARRIER_DETECTION_SUPPORT */ + + if (pAd->Dot11_H.RDMode == RD_NORMAL_MODE) + AsicEnableBssSync(pAd, pAd->CommonCfg.BeaconPeriod); + + /* Pre-tbtt interrupt setting. */ + AsicSetPreTbtt(pAd, TRUE); + +#ifdef WAPI_SUPPORT + RTMPStartWapiRekeyTimerAction(pAd, NULL); +#endif /* WAPI_SUPPORT */ + + /* + Set group re-key timer if necessary. + It must be processed after clear flag "fRTMP_ADAPTER_HALT_IN_PROGRESS" + */ + WPA_APSetGroupRekeyAction(pAd); + +#ifdef WDS_SUPPORT + /* Prepare WEP key */ + WdsPrepareWepKeyFromMainBss(pAd); + + /* Add wds key infomation to ASIC */ + AsicUpdateWdsRxWCIDTable(pAd); +#endif /* WDS_SUPPORT */ + +#ifdef IDS_SUPPORT + /* Start IDS timer */ + if (pAd->ApCfg.IdsEnable) + { +#ifdef SYSTEM_LOG_SUPPORT + if (pAd->CommonCfg.bWirelessEvent == FALSE) + DBGPRINT(RT_DEBUG_WARN, ("!!! WARNING !!! The WirelessEvent parameter doesn't be enabled \n")); +#endif /* SYSTEM_LOG_SUPPORT */ + + RTMPIdsStart(pAd); + } +#endif /* IDS_SUPPORT */ + + + +#ifdef DOT11R_FT_SUPPORT + FT_Init(pAd); +#endif /* DOT11R_FT_SUPPORT */ + + +#ifdef BAND_STEERING + if (pAd->ApCfg.BandSteering) { + PBND_STRG_CLI_TABLE table; + BSS_STRUCT *pBMbss; + + BndStrg_Init(pAd); + for (idx = 0; idx < MAX_MBSSID_NUM(pAd); idx++) { + pBMbss = &pAd->ApCfg.MBSSID[idx]; + table = Get_BndStrgTable(pAd, idx); + if (table) { + /* Inform daemon interface ready */ + BndStrg_SetInfFlags(pAd, &pBMbss->wdev, table, TRUE); + } + } + } +#endif /* BAND_STEERING */ + + +#ifdef CONFIG_MAC_PCI + RTMP_ASIC_INTERRUPT_ENABLE(pAd); +#endif + + DBGPRINT(RT_DEBUG_OFF, ("Main bssid = %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pAd->ApCfg.MBSSID[BSS0].wdev.bssid))); + +#ifdef SW_ATF_SUPPORT + pAd->AtfParaSet.lastTimerCnt = 0; + pAd->AtfParaSet.flagATF = FALSE; + pAd->AtfParaSet.dropDelta = 2; + pAd->AtfParaSet.flagOnce = FALSE; + pAd->AtfParaSet.wcidTxThr = WcidTxThr; + pAd->AtfParaSet.deq_goodNodeMaxThr = goodNodeMaxDeqThr; + pAd->AtfParaSet.deq_goodNodeMinThr = goodNodeMinDeqThr; + pAd->AtfParaSet.deq_badNodeMinThr = badNodeMinDeqThr; + pAd->AtfParaSet.enq_badNodeMaxThr = badNodeMaxEnqThr; + pAd->AtfParaSet.enq_badNodeMinThr = badNodeMinEnqThr; + pAd->AtfParaSet.enq_badNodeCurrent = 3; + pAd->AtfParaSet.atfFalseCCAThr = FalseCCAThr; +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("<=== APStartUp\n")); +} + + +/* + ========================================================================== + Description: + disassociate all STAs and stop AP service. + Note: + ========================================================================== + */ +VOID APStop(RTMP_ADAPTER *pAd) +{ + BOOLEAN Cancelled; + INT idx; + BSS_STRUCT *pMbss; +#ifdef WH_EZ_SETUP + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + struct wifi_dev *wdev; + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("!!! APStop !!!\n")); + +#ifdef CONFIG_MAC_PCI + RTMP_ASIC_INTERRUPT_DISABLE(pAd); +#endif + +#ifdef DFS_SUPPORT + NewRadarDetectionStop(pAd); +#endif /* DFS_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef CARRIER_DETECTION_SUPPORT + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + { + /* make sure CarrierDetect wont send CTS */ + CarrierDetectionStop(pAd); + } +#endif /* CARRIER_DETECTION_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef WDS_SUPPORT + WdsDown(pAd); +#endif /* WDS_SUPPORT */ + +#ifdef APCLI_SUPPORT + ApCliIfDown(pAd); +#endif /* APCLI_SUPPORT */ + + MacTableReset(pAd, 1); + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + + /* Disable pre-tbtt interrupt */ + AsicSetPreTbtt(pAd, FALSE); + + /* Disable piggyback */ + RTMPSetPiggyBack(pAd, FALSE); + + AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT|CCKSETPROTECT|OFDMSETPROTECT), TRUE, FALSE); + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + AsicDisableSync(pAd); + +#ifdef LED_CONTROL_SUPPORT + /* Set LED */ + RTMPSetLED(pAd, LED_LINK_DOWN); +#endif /* LED_CONTROL_SUPPORT */ + } + + + + for (idx = 0; idx < MAX_MBSSID_NUM(pAd); idx++) + { + pMbss = &pAd->ApCfg.MBSSID[idx]; + if (pMbss->REKEYTimerRunning == TRUE) + { + RTMPCancelTimer(&pMbss->REKEYTimer, &Cancelled); + pMbss->REKEYTimerRunning = FALSE; + } + +#ifdef MWDS + MWDSDisable(pAd, idx, TRUE, TRUE); +#endif /* MWDS */ +#if defined(MAP_SUPPORT) && defined(A4_CONN) + if (IS_MAP_ENABLE(pAd)) + map_a4_deinit(pAd, pMbss->mbss_idx, TRUE); +#endif +#if defined(MAP_SUPPORT) && defined(WAPP_SUPPORT) + if (pMbss->wdev.if_dev && pAd->net_dev) + wapp_send_bss_state_change(pAd, &pMbss->wdev, WAPP_BSS_STOP); +#endif /*WAPP_SUPPORT*/ +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) +#if (MT7615_MT7603_COMBO_FORWARDING == 1) + { + if (wf_fwd_entry_delete_hook) + wf_fwd_entry_delete_hook (pAd->net_dev, pMbss->wdev.if_dev, 0); + + if (wf_fwd_check_device_hook) + wf_fwd_check_device_hook(pMbss->wdev.if_dev, INT_MBSSID, pMbss->mbss_idx, pMbss->wdev.channel, 0); + } +#endif /* CONFIG_WIFI_PKT_FWD */ +#endif + pMbss->bcn_buf.bcn_state = BCN_TX_IDLE; +#ifdef WH_EZ_SETUP + if(IS_CONF_EZ_SETUP_ENABLED(&pMbss->wdev)) + ez_stop(&pMbss->wdev); +#endif /* WH_EZ_SETUP */ + +#ifdef BAND_STEERING + if(pAd->ApCfg.BandSteering) + { + PBND_STRG_CLI_TABLE table; + table = Get_BndStrgTable(pAd, idx); + if(table) + { + /* Inform daemon interface ready */ + BndStrg_SetInfFlags(pAd, &pMbss->wdev, table, FALSE); + } + } +#endif /* BAND_STEERING */ + + } + + if (pAd->ApCfg.CMTimerRunning == TRUE) + { + RTMPCancelTimer(&pAd->ApCfg.CounterMeasureTimer, &Cancelled); + pAd->ApCfg.CMTimerRunning = FALSE; + } + pAd->ApCfg.BANClass3Data = FALSE; + +#ifdef WAPI_SUPPORT + RTMPCancelWapiRekeyTimerAction(pAd, NULL); +#endif /* WAPI_SUPPORT */ + + /* */ + /* Cancel the Timer, to make sure the timer was not queued. */ + /* */ + OPSTATUS_CLEAR_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED); + RTMP_IndicateMediaState(pAd, NdisMediaStateDisconnected); + +#ifdef IDS_SUPPORT + /* if necessary, cancel IDS timer */ + RTMPIdsStop(pAd); +#endif /* IDS_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + FT_Release(pAd); +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + DMSTable_Release(pAd); +#endif /* DOT11V_WNM_SUPPORT */ + + +} + +VOID APStopBssOnly(RTMP_ADAPTER *pAd, BSS_STRUCT *pMbss) +{ + BOOLEAN Cancelled; + struct wifi_dev *wdev_bss; +#ifdef WH_EZ_SETUP + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; +#endif + + wdev_bss = &pMbss->wdev; + + if (!wdev_bss) { + DBGPRINT(RT_DEBUG_ERROR, ("Error!!! wdev_map is null !!!\n")); + return; + } + DBGPRINT(RT_DEBUG_TRACE, ("!!! APStop !!!\n")); + +#ifdef CONFIG_MAC_PCI + RTMP_ASIC_INTERRUPT_DISABLE(pAd); +#endif + +#ifdef DFS_SUPPORT + NewRadarDetectionStop(pAd); +#endif /* DFS_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef CARRIER_DETECTION_SUPPORT + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) { + /* make sure CarrierDetect wont send CTS */ + CarrierDetectionStop(pAd); + } +#endif /* CARRIER_DETECTION_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef WDS_SUPPORT + WdsDown(pAd); +#endif /* WDS_SUPPORT */ + +#if defined(APCLI_SUPPORT) && defined(MAP_SUPPORT) && defined(A4_CONN) + { + for (idx = 0; idx < MAX_APCLI_NUM; idx++) { + wdev_apcli = &pAd->ApCfg.ApCliTab[idx].wdev; + + /* WPS cli will disconnect and connect again */ + pWscControl = &pAd->ApCfg.ApCliTab[idx].WscControl; + if (pWscControl->bWscTrigger == TRUE) + continue; + + if (wdev_apcli->channel == wdev_bss->channel) { + UINT8 enable = pAd->ApCfg.ApCliTab[idx].Enable; + + if (enable) { + pAd->ApCfg.ApCliTab[idx].Enable = FALSE; + ApCliIfDown(pAd); + pAd->ApCfg.ApCliTab[idx].Enable = enable; + } + } + } + } +#endif /* APCLI_SUPPORT */ + + MacTableResetWdev(pAd, wdev_bss); + + /*RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); */ + + /* Disable pre-tbtt interrupt */ + /*CMDHandler(pAd); */ + AsicSetPreTbtt(pAd, FALSE); + + /* Disable piggyback */ + RTMPSetPiggyBack(pAd, FALSE); + + AsicUpdateProtect(pAd, 0, (ALLN_SETPROTECT|CCKSETPROTECT|OFDMSETPROTECT), TRUE, FALSE); + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) { + AsicDisableSync(pAd); + +#ifdef LED_CONTROL_SUPPORT + /* Set LED */ + RTMPSetLED(pAd, LED_LINK_DOWN); +#endif /* LED_CONTROL_SUPPORT */ + } + + + + if (pMbss->REKEYTimerRunning == TRUE) { + RTMPCancelTimer(&pMbss->REKEYTimer, &Cancelled); + pMbss->REKEYTimerRunning = FALSE; + } + +#ifdef MWDS + MWDSDisable(pAd, wdev_bss->func_idx, TRUE, TRUE); +#endif /* MWDS */ +#if defined(MAP_SUPPORT) && defined(A4_CONN) + if (IS_MAP_ENABLE(pAd)) + map_a4_deinit(pAd, pMbss->mbss_idx, TRUE); +#endif +#if defined(MAP_SUPPORT) && defined(WAPP_SUPPORT) + if (wdev_bss->if_dev && pAd->net_dev) + wapp_send_bss_state_change(pAd, wdev_bss, WAPP_BSS_STOP); +#endif /*WAPP_SUPPORT*/ +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) +#if (MT7615_MT7603_COMBO_FORWARDING == 1) + { + if (wf_fwd_entry_delete_hook) + wf_fwd_entry_delete_hook(pAd->net_dev, pMbss->wdev.if_dev, 0); + + if (wf_fwd_check_device_hook) + wf_fwd_check_device_hook(pMbss->wdev.if_dev, INT_MBSSID, + pMbss->mbss_idx, pMbss->wdev.channel, 0); + } +#endif /* CONFIG_WIFI_PKT_FWD */ +#endif + pMbss->bcn_buf.bcn_state = BCN_TX_IDLE; +#ifdef WH_EZ_SETUP + if (IS_CONF_EZ_SETUP_ENABLED(&pMbss->wdev)) + ez_stop(&pMbss->wdev); +#endif /* WH_EZ_SETUP */ + +#ifdef BAND_STEERING + if (pAd->ApCfg.BandSteering) { + PBND_STRG_CLI_TABLE table; + + table = Get_BndStrgTable(pAd, wdev_bss->func_idx); + if (table) { + /* Inform daemon interface ready */ + BndStrg_SetInfFlags(pAd, &pMbss->wdev, table, FALSE); + } + } +#endif /* BAND_STEERING */ + + if (pAd->ApCfg.CMTimerRunning == TRUE) { + RTMPCancelTimer(&pAd->ApCfg.CounterMeasureTimer, &Cancelled); + pAd->ApCfg.CMTimerRunning = FALSE; + pAd->ApCfg.BANClass3Data = FALSE; + } + +#ifdef WAPI_SUPPORT + RTMPCancelWapiRekeyTimerAction(pAd, NULL); +#endif /* WAPI_SUPPORT */ + + /* */ + /* Cancel the Timer, to make sure the timer was not queued. */ + /* */ + /* OPSTATUS_CLEAR_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED); */ + RTMP_IndicateMediaState(pAd, NdisMediaStateDisconnected); + +#ifdef IDS_SUPPORT + /* if necessary, cancel IDS timer */ + RTMPIdsStop(pAd); +#endif /* IDS_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + FT_Release(pAd); +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + DMSTable_Release(pAd); +#endif /* DOT11V_WNM_SUPPORT */ + + +} + +/* + ========================================================================== + Description: + This routine is used to clean up a specified power-saving queue. It's + used whenever a wireless client is deleted. + ========================================================================== + */ +VOID APCleanupPsQueue(RTMP_ADAPTER *pAd, QUEUE_HEADER *pQueue) +{ + PQUEUE_ENTRY pEntry; + PNDIS_PACKET pPacket; + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): (0x%08lx)...\n", __FUNCTION__, (ULONG)pQueue)); + + while (pQueue->Head) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s():%u...\n", __FUNCTION__, pQueue->Number)); + + pEntry = RemoveHeadQueue(pQueue); + /*pPacket = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReservedEx); */ + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } +} + +#ifdef APCLI_SUPPORT +#ifdef TRAFFIC_BASED_TXOP +static VOID CheckApEntryInTraffic(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, STA_TR_ENTRY *tr_entry) +{ + UINT32 TxTotalByteCnt = 0; + UINT32 RxTotalByteCnt = 0; + + if((IS_ENTRY_APCLI(pEntry) || IS_ENTRY_CLIENT(pEntry)) + && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + TxTotalByteCnt = pEntry->OneSecTxBytes; + RxTotalByteCnt = pEntry->OneSecRxBytes; + DBGPRINT(RT_DEBUG_INFO,("WICD%d, %dM, TxBytes:%d, RxBytes:%d\n", pEntry->wcid, (((TxTotalByteCnt + RxTotalByteCnt) << 3) >> 20), + TxTotalByteCnt, RxTotalByteCnt)); + + if ((TxTotalByteCnt == 0) || (RxTotalByteCnt == 0)) + { + } + else if ((((TxTotalByteCnt + RxTotalByteCnt) << 3) >> 20) > pAd->CommonCfg.ManualTxopThreshold) + { + //printk("%dM, %d, %d, %d\n", (((TxTotalByteCnt + RxTotalByteCnt) << 3) >> 20), TxTotalByteCnt, RxTotalByteCnt, (TxTotalByteCnt/RxTotalByteCnt)); + if (TxTotalByteCnt > RxTotalByteCnt) + { + if ((TxTotalByteCnt/RxTotalByteCnt) >= pAd->CommonCfg.ManualTxopUpBound) + { + if (IS_ENTRY_CLIENT(pEntry)) + pAd->StaTxopAbledCnt++; + else + pAd->ApClientTxopAbledCnt++; + } + } + } + } +} +#endif /* TRAFFIC_BASED_TXOP */ +#endif /* APCLI_SUPPORT */ + +#ifdef MULTI_CLIENT_SUPPORT +extern UINT RtsRetryCnt; +#endif +#ifdef STA_FORCE_ROAM_SUPPORT +void load_froam_defaults(RTMP_ADAPTER *pAd) +{ + pAd->en_force_roam_supp = FROAM_SUPP_DEF; + pAd->sta_low_rssi = (-1) * STA_LOW_RSSI; + pAd->low_sta_renotify = LOW_RSSI_STA_RENOTIFY_TIME; + pAd->sta_age_time = STALIST_AGEOUT_TIME; + pAd->mntr_age_time = MNTRLIST_AGEOUT_TIME; + pAd->mntr_min_pkt_count = MNTR_MIN_PKT_COUNT; + pAd->mntr_min_time = MNTR_MIN_TIME; + pAd->mntr_avg_rssi_pkt_count = AVG_RSSI_PKT_COUNT; + pAd->sta_good_rssi = (-1) * STA_DETECT_RSSI; + pAd->acl_age_time = ACLLIST_AGEOUT_TIME; + pAd->acl_hold_time = ACLLIST_HOLD_TIME; + DBGPRINT(RT_DEBUG_TRACE, + ("\n[Force Roam] => Force Roam Support = %d\n",pAd->en_force_roam_supp)); + DBGPRINT(RT_DEBUG_TRACE, + ("[Force Roam] => StaLowRssiThr=%d dBm low_sta_renotify=%d sec StaAgeTime=%d sec\n",pAd->sta_low_rssi, pAd->low_sta_renotify,pAd->sta_age_time)); + DBGPRINT(RT_DEBUG_TRACE, + ("[Force Roam] => MntrAgeTime=%d sec mntr_min_pkt_count=%d mntr_min_time=%d sec mntr_avg_rssi_pkt_count=%d\n", + pAd->mntr_age_time, pAd->mntr_min_pkt_count,pAd->mntr_min_time, pAd->mntr_avg_rssi_pkt_count)); + DBGPRINT(RT_DEBUG_TRACE, + ("[Force Roam] => AclAgeTime=%d sec AclHoldTime=%d sec\n",pAd->acl_age_time, pAd->acl_hold_time)); +} +#define MINIMUM_POWER_VALUE -127 +static CHAR staMaxRssi(RTMP_ADAPTER *pAd, struct wifi_dev *wdev, RSSI_SAMPLE *pRssi) +{ + CHAR Rssi = MINIMUM_POWER_VALUE; + UINT32 rx_stream; + rx_stream = pAd->Antenna.field.RxPath; + if ((rx_stream == 1) && (pRssi->AvgRssi[0] < 0)) + { + Rssi = pRssi->AvgRssi[0]; + } + if ((rx_stream >= 2) && (pRssi->AvgRssi[1] < 0)) + { + Rssi = max(pRssi->AvgRssi[0], pRssi->AvgRssi[1]); + } + if ((rx_stream >= 3) && (pRssi->AvgRssi[2] < 0)) + { + Rssi = max(Rssi, pRssi->AvgRssi[2]); + } + return Rssi; +} +static void sta_rssi_check(void *ad_obj, void *pEntry) +{ + CHAR maxRssi = MINIMUM_POWER_VALUE; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ad_obj; + MAC_TABLE_ENTRY *pMacEntry = (MAC_TABLE_ENTRY *)pEntry; + + // average value of rssi for all antenna is not being considered, as it depends on whether all antenna slots as usage + // have got antenna connected. + // Instead Max value would be used + + maxRssi = staMaxRssi(pAd, pMacEntry->wdev, &pMacEntry->RssiSample); + + printk("STA %02x-%02x-%02x-%02x-%02x-%02x maxRssi:%d !!\n", + pMacEntry->Addr[0],pMacEntry->Addr[1],pMacEntry->Addr[2],pMacEntry->Addr[3],pMacEntry->Addr[4],pMacEntry->Addr[5],maxRssi); + + if(pMacEntry->low_rssi_notified) // i.e rssi improved + { + if(maxRssi > pAd->sta_low_rssi ){ + froam_event_sta_good_rssi event_data; + + printk("issue FROAM_EVT_STA_RSSI_GOOD -> for STA %02x-%02x-%02x-%02x-%02x-%02x\n", + pMacEntry->Addr[0],pMacEntry->Addr[1],pMacEntry->Addr[2],pMacEntry->Addr[3],pMacEntry->Addr[4],pMacEntry->Addr[5]); + + memset(&event_data,0,sizeof(event_data)); + + event_data.hdr.event_id = FROAM_EVT_STA_RSSI_GOOD; + event_data.hdr.event_len = sizeof(froam_event_sta_good_rssi) - sizeof(froam_event_hdr); + + //DBGPRINT(RT_DEBUG_TRACE,("FROAM_EVT_STA_RSSI_GOOD payload len:%d datLen: %d-> \n", + // event_data.hdr.event_len,sizeof(event_data))); + + memcpy(event_data.mac,pMacEntry->Addr,MAC_ADDR_LEN); + + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_FROAM_EVENT, + NULL, + (UCHAR *) &event_data, + sizeof(event_data)); + + pMacEntry->low_rssi_notified = FALSE; + pMacEntry->tick_sec = 0; + //printk("Froam event sent <- \n"); + } + else{ + pMacEntry->tick_sec++; + if(pMacEntry->tick_sec >= pAd->low_sta_renotify){ + pMacEntry->tick_sec = 0; + pMacEntry->low_rssi_notified = FALSE; + } + } + } + else if((maxRssi != MINIMUM_POWER_VALUE) && (maxRssi < pAd->sta_low_rssi )) //pAd->ApCfg.EventNotifyCfg.StaRssiDetectThreshold)) + { + froam_event_sta_low_rssi event_data; + + DBGPRINT(RT_DEBUG_TRACE,("issue FROAM_EVT_STA_RSSI_LOW -> for STA %02x-%02x-%02x-%02x-%02x-%02x\n", + pMacEntry->Addr[0],pMacEntry->Addr[1],pMacEntry->Addr[2],pMacEntry->Addr[3],pMacEntry->Addr[4],pMacEntry->Addr[5])); + + memset(&event_data,0,sizeof(event_data)); + + event_data.hdr.event_id = FROAM_EVT_STA_RSSI_LOW; + event_data.hdr.event_len = sizeof(froam_event_sta_low_rssi) - sizeof(froam_event_hdr); + + //event_data.channel = pMacEntry->wdev->channel; + event_data.channel = pAd->CommonCfg.Channel; + memcpy(event_data.mac,pMacEntry->Addr,MAC_ADDR_LEN); + + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_FROAM_EVENT, + NULL, + (UCHAR *) &event_data, + sizeof(event_data)); + + pMacEntry->low_rssi_notified = TRUE; + pMacEntry->tick_sec = 0; + + //DBGPRINT(RT_DEBUG_TRACE,("Froam event sent <- \n")); + } +} +#endif + +/* + ========================================================================== + Description: + This routine is called by APMlmePeriodicExec() every second to check if + 1. any associated client in PSM. If yes, then TX MCAST/BCAST should be + out in DTIM only + 2. any client being idle for too long and should be aged-out from MAC table + 3. garbage collect PSQ + ========================================================================== +*/ +VOID MacTableMaintenance(RTMP_ADAPTER *pAd) +{ + int i, startWcid; +#ifdef DOT11_N_SUPPORT + ULONG MinimumAMPDUSize = pAd->CommonCfg.DesiredHtPhy.MaxRAmpduFactor; /*Default set minimum AMPDU Size to 2, i.e. 32K */ + BOOLEAN bRdgActive; + BOOLEAN bRalinkBurstMode; +#ifdef MT_MAC + UCHAR nLegacySTA = 0; /* number of legacy stations */ + UCHAR iLegacySTA[MAX_LEN_OF_TR_TABLE]; /* wtbl index of legacy stations */ +#endif /* MT_MAC */ +#endif /* DOT11_N_SUPPORT */ +#ifdef RTMP_MAC_PCI + ULONG IrqFlags = 0; +#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) */ + CHAR avgRssi; + BSS_STRUCT *pMbss; +#ifdef WFA_VHT_PF + RSSI_SAMPLE *worst_rssi = NULL; + int worst_rssi_sta_idx = 0; +#endif /* WFA_VHT_PF */ +#ifdef MT_MAC + BOOLEAN bPreAnyStationInPsm = FALSE; +#endif /* MT_MAC */ +#ifdef EDCCA_RB + int client_rb=0; + int client_b=0; +#endif + + NdisZeroMemory(fAnyStationPortSecured, sizeof(fAnyStationPortSecured)); + + pMacTable = &pAd->MacTab; + +#ifdef MT_MAC + bPreAnyStationInPsm = pMacTable->fAnyStationInPsm; +#endif /* MT_MAC */ + + pMacTable->fAnyStationInPsm = FALSE; + pMacTable->fAnyStationBadAtheros = FALSE; + pMacTable->fAnyTxOPForceDisable = FALSE; + pMacTable->fAllStationAsRalink = TRUE; +#ifdef DOT11_N_SUPPORT + pMacTable->fAnyStationNonGF = FALSE; + pMacTable->fAnyStation20Only = FALSE; + pMacTable->fAnyStationIsLegacy = FALSE; + pMacTable->fAnyStationMIMOPSDynamic = FALSE; +#ifdef GREENAP_SUPPORT + /*Support Green AP */ + pMacTable->fAnyStationIsHT=FALSE; +#endif /* GREENAP_SUPPORT */ + +#ifdef DOT11N_DRAFT3 + pMacTable->fAnyStaFortyIntolerant = FALSE; +#endif /* DOT11N_DRAFT3 */ + pMacTable->fAllStationGainGoodMCS = TRUE; +#endif /* DOT11_N_SUPPORT */ + +#ifdef WAPI_SUPPORT + pMacTable->fAnyWapiStation = FALSE; +#endif /* WAPI_SUPPORT */ + + startWcid = 1; + + +#ifdef SMART_CARRIER_SENSE_SUPPORT + pAd->SCSCtrl.SCSMinRssi = 0; /* (Reset)The minimum RSSI of STA */ +#endif /* SMART_CARRIER_SENSE_SUPPORT */ + +#ifdef APCLI_SUPPORT +#ifdef TRAFFIC_BASED_TXOP + pAd->StaTxopAbledCnt = 0; + pAd->ApClientTxopAbledCnt = 0; +#endif /* TRAFFIC_BASED_TXOP */ +#endif /* APCLI_SUPPORT */ + + for (i = startWcid; i < MAX_LEN_OF_MAC_TABLE; i++) + { + MAC_TABLE_ENTRY *pEntry = &pMacTable->Content[i]; + STA_TR_ENTRY *tr_entry = &pMacTable->tr_entry[i]; + BOOLEAN bDisconnectSta = FALSE; +#ifdef APCLI_SUPPORT + +#ifdef TRAFFIC_BASED_TXOP + CheckApEntryInTraffic(pAd, pEntry, tr_entry); +#endif /* TRAFFIC_BASED_TXOP */ + + pEntry->AvgTxBytes = (pEntry->AvgTxBytes == 0) ? pEntry->OneSecTxBytes : \ + ((pEntry->AvgTxBytes + pEntry->OneSecTxBytes) >> 1); + pEntry->OneSecTxBytes = 0; + pEntry->AvgRxBytes = (pEntry->AvgRxBytes == 0) ? pEntry->OneSecRxBytes : \ + ((pEntry->AvgRxBytes + pEntry->OneSecRxBytes) >> 1); + pEntry->OneSecRxBytes = 0; + + if(IS_ENTRY_APCLI(pEntry) && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) + { +#ifdef MAC_REPEATER_SUPPORT + if (pEntry->bReptCli) + { + pEntry->ReptCliIdleCount++; + + if ((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->func_tb_idx) + pEntry->MatchReptCliIdx)); + RTMP_MLME_HANDLER(pAd); + //RTMPRemoveRepeaterEntry(pAd, pEntry->func_tb_idx, pEntry->MatchReptCliIdx); + continue; + } + } +#endif /* MAC_REPEATER_SUPPORT */ + + + if ((pAd->Mlme.OneSecPeriodicRound % 10) == 8) + { + /* use Null or QoS Null to detect the ACTIVE station*/ + BOOLEAN ApclibQosNull = FALSE; + + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)) + ApclibQosNull = TRUE; +#ifdef WH_EZ_SETUP + if (IS_ADPTR_EZ_SETUP_ENABLED(pAd) && (ScanRunning(pAd) == FALSE)){ +#endif + ApCliRTMPSendNullFrame(pAd,pEntry->CurrTxRate, ApclibQosNull, pEntry, PWR_ACTIVE); +#ifdef WH_EZ_SETUP + } +#endif + + continue; + } + } +#endif /* APCLI_SUPPORT */ + + if (!IS_ENTRY_CLIENT(pEntry)) + continue; + +#if defined(MAP_SUPPORT) && defined(WAPP_SUPPORT) + if ((pEntry->wdev) && (IS_MAP_ENABLE(pAd))) { + UINT32 tx_tp = (pEntry->AvgTxBytes >> BYTES_PER_SEC_TO_MBPS); + UINT32 rx_tp = (pEntry->AvgRxBytes >> BYTES_PER_SEC_TO_MBPS); + ULONG data_rate = 0; + UINT32 tp_ratio = 0; + UINT8 bidir_traffc_mode = 0; + + getRate(pEntry->HTPhyMode, &data_rate); + tp_ratio = ((tx_tp + rx_tp) * 100) / data_rate; + + if (tp_ratio > STA_TP_IDLE_THRESHOLD) + bidir_traffc_mode = TRAFFIC_BIDIR_ACTIVE_MODE; + else + bidir_traffc_mode = TRAFFIC_BIDIR_IDLE_MODE; + + if ((pEntry->pre_traffic_mode == TRAFFIC_BIDIR_ACTIVE_MODE) && + (tp_ratio <= STA_TP_IDLE_THRESHOLD)) + wapp_send_cli_active_change(pAd, pEntry, INACTIVE); + else if ((pEntry->pre_traffic_mode == TRAFFIC_BIDIR_IDLE_MODE) && + (tp_ratio > STA_TP_IDLE_THRESHOLD)) + wapp_send_cli_active_change(pAd, pEntry, ACTIVE); + + pEntry->pre_traffic_mode = bidir_traffc_mode; + } +#endif + +#ifdef MT_PS + CheckSkipTX(pAd, pEntry); +#endif /* MT_PS */ + if (pEntry->NoDataIdleCount == 0) + pEntry->StationKeepAliveCount = 0; + + pEntry->NoDataIdleCount ++; + // TODO: shiang-usw, remove upper setting becasue we need to migrate to tr_entry! + pAd->MacTab.tr_entry[pEntry->wcid].NoDataIdleCount = 0; + + pEntry->StaConnectTime ++; + + pMbss = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx]; + + /* 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 %lu sec\n", + PRINT_MAC(pEntry->Addr), pEntry->AssocDeadLine)); +#ifdef WSC_AP_SUPPORT + if (NdisEqualMemory(pEntry->Addr, pMbss->WscControl.EntryAddr, MAC_ADDR_LEN)) + NdisZeroMemory(pMbss->WscControl.EntryAddr, MAC_ADDR_LEN); +#endif /* WSC_AP_SUPPORT */ +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(pEntry->wdev)) + { + struct _ez_peer_security_info * ez_peer = NULL; + //BOOLEAN ez_peer = FALSE; + ez_peer = ez_peer_table_search_by_addr(pEntry->wdev, pEntry->Addr); + if (ez_peer) + { + ez_set_delete_peer_in_differed_context(pEntry->wdev, ez_peer, TRUE); + ez_send_unicast_deauth(pAd,pEntry->Addr); + } else { + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + } + } + else { +#endif + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); +#ifdef WH_EZ_SETUP + } +#endif + 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; + if (pEntry->wdev && pEntry->wdev->wdev_type == WDEV_TYPE_AP) { + pAd->MacTab.tr_entry[pEntry->wdev->tr_tb_idx].PsMode = PWR_SAVE; + if (tr_entry->PsDeQWaitCnt) + { + tr_entry->PsDeQWaitCnt++; + if (tr_entry->PsDeQWaitCnt > 2) + tr_entry->PsDeQWaitCnt = 0; + } + } + } + +#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 MT_MAC + iLegacySTA[nLegacySTA] = i; + nLegacySTA ++; +#endif /* MT_MAC */ + } +#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 */ + } + +#ifdef MAC_REPEATER_SUPPORT + { + + } +#endif /* MAC_REPEATER_SUPPORT */ + /* detect the station alive status */ + /* detect the station alive status */ +#ifdef NEW_IXIA_METHOD + if (force_connect == 1) + pEntry->NoDataIdleCount = 0; +#endif + if ((pMbss->StationKeepAliveTime > 0) && + (pEntry->NoDataIdleCount >= pMbss->StationKeepAliveTime)) + { + /* + If no any data success between ap and the station for + StationKeepAliveTime, try to detect whether the station is + still alive. + + Note: Just only keepalive station function, no disassociation + function if too many no response. + */ + + /* + For example as below: + + 1. Station in ACTIVE mode, + + ...... + sam> tx ok! + sam> count = 1! ==> 1 second after the Null Frame is acked + sam> count = 2! ==> 2 second after the Null Frame is acked + sam> count = 3! + sam> count = 4! + sam> count = 5! + sam> count = 6! + sam> count = 7! + sam> count = 8! + sam> count = 9! + sam> count = 10! + sam> count = 11! + sam> count = 12! + sam> count = 13! + sam> count = 14! + sam> count = 15! ==> 15 second after the Null Frame is acked + sam> tx ok! ==> (KeepAlive Mechanism) send a Null Frame to + detect the STA life status + sam> count = 1! ==> 1 second after the Null Frame is acked + sam> count = 2! + sam> count = 3! + sam> count = 4! + ...... + + If the station acknowledges the QoS Null Frame, + the NoDataIdleCount will be reset to 0. + + + 2. Station in legacy PS mode, + + We will set TIM bit after 15 seconds, the station will send a + PS-Poll frame and we will send a QoS Null frame to it. + If the station acknowledges the QoS Null Frame, the + NoDataIdleCount will be reset to 0. + + + 3. Station in legacy UAPSD mode, + + Currently we do not support the keep alive mechanism. + So if your station is in UAPSD mode, the station will be + kicked out after 300 seconds. + + Note: the rate of QoS Null frame can not be 1M of 2.4GHz or + 6M of 5GHz, or no any statistics count will occur. + */ + + if (pEntry->StationKeepAliveCount++ == 0) + { + if (pEntry->PsMode == PWR_SAVE) + { + /* use TIM bit to detect the PS station */ + WLAN_MR_TIM_BIT_SET(pAd, pEntry->func_tb_idx, pEntry->Aid); + } + else + { + /* use Null or QoS Null to detect the ACTIVE station */ + BOOLEAN bQosNull = FALSE; + + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)) + bQosNull = TRUE; + + RtmpEnqueueNullFrame(pAd, pEntry->Addr, pEntry->CurrTxRate, + pEntry->Aid, pEntry->func_tb_idx, 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->TxSucCnt == 0) && (pEntry->NoDataIdleCount >= pEntry->StaIdleTimeout)) + { + bDisconnectSta = TRUE; + DBGPRINT(RT_DEBUG_WARN, ("ageout %02x:%02x:%02x:%02x:%02x:%02x after %d-sec silence\n", + PRINT_MAC(pEntry->Addr), pEntry->StaIdleTimeout)); + ApLogEvent(pAd, pEntry->Addr, EVENT_AGED_OUT); +#ifdef WIFI_DIAG + if (IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_FRAME_LOST, REASON_AGING_TIME_OUT); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + REASON_DEAUTH_STA_LEAVING); +#endif + } +#ifdef FAST_DETECT_STA_OFF + else if (pEntry->ConCounters.DisconnectFlag && Flag_fast_detect_sta_off == 1) { + bDisconnectSta = TRUE; + pEntry->ConCounters.DisconnectFlag = 0; + DBGPRINT(RT_DEBUG_ERROR, ("STA-%02x:%02x:%02x:%02x:%02x:%02x is inactive!!!\n", + PRINT_MAC(pEntry->Addr))); +#ifdef WIFI_DIAG + if (IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_FRAME_LOST, REASON_AGING_TIME_OUT); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + REASON_DEAUTH_STA_LEAVING); +#endif + } +#endif + 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", + PRINT_MAC(pEntry->Addr), + pEntry->ContinueTxFailCnt, pAd->ApCfg.EntryLifeCheck)); +#ifdef WH_EVENT_NOTIFIER + if(pEntry) + { + EventHdlr pEventHdlrHook = NULL; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_STA_TIMEOUT); + if(pEventHdlrHook && pEntry->wdev) + pEventHdlrHook(pAd, pEntry); + } +#endif /* WH_EVENT_NOTIFIER */ +#ifdef WIFI_DIAG + if (IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_FRAME_LOST, REASON_CONTINUE_TX_FAIL); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + REASON_DEAUTH_STA_LEAVING); +#endif + } + } + + if ((pMbss->RssiLowForStaKickOut != 0) && + ( (avgRssi=RTMPAvgRssi(pAd, &pEntry->RssiSample)) < pMbss->RssiLowForStaKickOut)) + { + bDisconnectSta = TRUE; + DBGPRINT(RT_DEBUG_WARN, ("Disassoc STA %02x:%02x:%02x:%02x:%02x:%02x , RSSI Kickout Thres[%d]-[%d]\n", + PRINT_MAC(pEntry->Addr), pMbss->RssiLowForStaKickOut, + avgRssi)); +#ifdef WIFI_DIAG + if (IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_DEAUTH, REASON_RSSI_TOO_LOW); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + REASON_DEAUTH_STA_LEAVING); +#endif + } + +#ifdef SMART_CARRIER_SENSE_SUPPORT + if (pAd->SCSCtrl.SCSEnable == SCS_ENABLE) + { + CHAR tmpRssi = RTMPMinRssi(pAd, pEntry->RssiSample.AvgRssi[0], pEntry->RssiSample.AvgRssi[1], pEntry->RssiSample.AvgRssi[2]); + if (tmpRssi < pAd->SCSCtrl.SCSMinRssi ) + pAd->SCSCtrl.SCSMinRssi = tmpRssi; + } +#endif /* SMART_CARRIER_SENSE_SUPPORT */ + + +#ifdef ALL_NET_EVENT + { + CHAR tmpRssi = RTMPAvgRssi(pAd, &pEntry->RssiSample); + if (tmpRssi > -75) + { + wext_send_event(pEntry->wdev->if_dev, + pEntry->Addr, + pEntry->bssid, + pAd->CommonCfg.Channel, + tmpRssi, + FBT_LINK_STRONG_NOTIFY); + } + else if (tmpRssi <= -75) + { + wext_send_event(pEntry->wdev->if_dev, + pEntry->Addr, + pEntry->bssid, + pAd->CommonCfg.Channel, + tmpRssi, + FBT_LINK_WEAK_NOTIFY); + } + } +#endif /* ALL_NET_EVENT */ + + + if (bDisconnectSta) + { +#ifdef FAST_DETECT_STA_OFF + UCHAR flush_wcid = pEntry->wcid; +#endif + /* 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; + } + +#ifdef FAST_DETECT_STA_OFF + if (Flag_fast_detect_sta_off == 1) + pEntry->detect_deauth = TRUE; +#endif + + Reason = REASON_DEAUTH_STA_LEAVING; + DBGPRINT(RT_DEBUG_WARN, ("Send DEAUTH - Reason = %d frame TO %x %x %x %x %x %x \n", + Reason, PRINT_MAC(pEntry->Addr))); + MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0, pEntry->Addr, + pMbss->wdev.if_addr, + pMbss->wdev.bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DeAuthHdr, + 2, &Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + +#ifdef MAC_REPEATER_SUPPORT + if ((pAd->ApCfg.bMACRepeaterEn == TRUE) && IS_ENTRY_CLIENT(pEntry) +#ifdef A4_CONN + && (IS_ENTRY_A4(pEntry) == FALSE) +#endif /* A4_CONN */ + ) + { + UCHAR apCliIdx, CliIdx, isLinkValid ; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, TRUE, pEntry->Addr, TRUE, &isLinkValid); + if (pReptEntry && (pReptEntry->CliConnectState != 0)) + { + apCliIdx = pReptEntry->MatchApCliIdx; + CliIdx = pReptEntry->MatchLinkIdx; + 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 */ + } + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(pEntry->wdev)) + { + struct _ez_peer_security_info * ez_peer = NULL; + ez_peer = ez_peer_table_search_by_addr(pEntry->wdev,pEntry->Addr); + if (ez_peer) + { + ez_set_delete_peer_in_differed_context(pEntry->wdev, ez_peer, TRUE); + ez_send_unicast_deauth(pAd,pEntry->Addr); + } else { + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + } + } + else { +#endif + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); +#ifdef FAST_DETECT_STA_OFF + if (Flag_fast_detect_sta_off == 1) + CmdFlushFrameByWlanIdx(pAd, flush_wcid); +#endif +#ifdef WH_EZ_SETUP + } +#endif + + continue; + } + +#if defined(CONFIG_HOTSPOT_R2) || defined(CONFIG_DOT11V_WNM) + if (pEntry->BTMDisassocCount == 1) + { + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + HEADER_802_11 DisassocHdr; + USHORT Reason; + + /* send out a DISASSOC request frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, (" MlmeAllocateMemory fail ..\n")); + /*NdisReleaseSpinLock(&pAd->MacTabLock); */ + continue; + } + + Reason = REASON_DISASSOC_INACTIVE; + DBGPRINT(RT_DEBUG_ERROR, ("BTM ASSOC - Send DISASSOC Reason = %d frame TO %x %x %x %x %x %x \n",Reason,pEntry->Addr[0], + pEntry->Addr[1],pEntry->Addr[2],pEntry->Addr[3],pEntry->Addr[4],pEntry->Addr[5])); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pEntry->Addr, pMbss->wdev.if_addr, pMbss->wdev.bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &DisassocHdr, 2, &Reason, END_OF_ARGS); + MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | QID_AC_BE), pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +#ifdef WIFI_DIAG + if (IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_DEAUTH, Reason); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + Reason); +#endif + //JERRY + if (!pEntry->IsKeep) { +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(pEntry->wdev)) + { + void * ez_peer = NULL; + ez_peer = ez_peer_table_search_by_addr(pEntry->wdev,pEntry->Addr); + if (ez_peer) + { + ez_set_delete_peer_in_differed_context(pEntry->wdev, ez_peer, TRUE); + ez_send_unicast_deauth(pAd,pEntry->Addr); + } else { + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + } + } + else { +#endif + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); +#ifdef WH_EZ_SETUP + } +#endif + } + continue; + } + if (pEntry->BTMDisassocCount != 0) + pEntry->BTMDisassocCount--; +#endif /* CONFIG_HOTSPOT_R2 */ + + /* 3. garbage collect the ps_queue if the STA has being idle for a while */ + if ((pEntry->PsMode == PWR_SAVE) && (tr_entry->ps_state == APPS_RETRIEVE_DONE || tr_entry->ps_state == APPS_RETRIEVE_IDLE)) + { + if (tr_entry->enqCount > 0) + { + tr_entry->PsQIdleCount++; + if (tr_entry->PsQIdleCount > 2) + { + rtmp_tx_swq_exit(pAd, pEntry->wcid); + tr_entry->PsQIdleCount = 0; + WLAN_MR_TIM_BIT_CLEAR(pAd, pEntry->func_tb_idx, pEntry->Aid); + DBGPRINT(RT_DEBUG_TRACE, ("%s():Clear WCID[%d] packets\n",__FUNCTION__, pEntry->wcid)); + } + } + } + else + { + tr_entry->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 (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED) + fAnyStationPortSecured[pEntry->func_tb_idx]++; +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if ((pEntry->BSS2040CoexistenceMgmtSupport) + && (pAd->CommonCfg.Bss2040CoexistFlag & BSS_2040_COEXIST_INFO_NOTIFY) + && (pAd->CommonCfg.bBssCoexEnable == TRUE) + ) + { + SendNotifyBWActionFrame(pAd, pEntry->wcid, pEntry->func_tb_idx); + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ +#ifdef WAPI_SUPPORT + if (pEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled) + pMacTable->fAnyWapiStation = TRUE; +#endif /* WAPI_SUPPORT */ + +#if defined(PRE_ANT_SWITCH) || defined(CFO_TRACK) + lastClient = i; +#endif /* defined(PRE_ANT_SWITCH) || defined(CFO_TRACK) */ + + /* only apply burst when run in MCS0,1,8,9,16,17, not care about phymode */ + if ((pEntry->HTPhyMode.field.MCS != 32) && + ((pEntry->HTPhyMode.field.MCS % 8 == 0) || (pEntry->HTPhyMode.field.MCS % 8 == 1))) + { + pMacTable->fAllStationGainGoodMCS = FALSE; + } + +#ifdef WFA_VHT_PF + if (worst_rssi == NULL) { + worst_rssi = &pEntry->RssiSample; + worst_rssi_sta_idx = i; + } else { + if (worst_rssi->AvgRssi[0] > pEntry->RssiSample.AvgRssi[0]) { + worst_rssi = &pEntry->RssiSample; + worst_rssi_sta_idx = i; + } + } +#endif /* WFA_VHT_PF */ +#ifdef STA_FORCE_ROAM_SUPPORT + if (IS_ENTRY_CLIENT(pEntry) && + tr_entry && (!pEntry->is_peer_entry_apcli) + && (((PRTMP_ADAPTER)(pEntry->wdev->sys_handle))->en_force_roam_supp) + && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + sta_rssi_check(pAd, pEntry); + } +#endif + +#ifdef WH_EVENT_NOTIFIER + if(pAd->ApCfg.EventNotifyCfg.bStaRssiDetect) + { + avgRssi = RTMPAvgRssi(pAd, &pEntry->RssiSample); + if(avgRssi < pAd->ApCfg.EventNotifyCfg.StaRssiDetectThreshold) + { + if(pEntry && IS_ENTRY_CLIENT(pEntry) +#ifdef A4_CONN + && !IS_ENTRY_A4(pEntry) +#endif /* A4_CONN */ + && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED) + ) + { + EventHdlr pEventHdlrHook = NULL; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_STA_RSSI_TOO_LOW); + if(pEventHdlrHook && pEntry->wdev) + pEventHdlrHook(pAd, pEntry->wdev, pEntry->Addr, avgRssi); + } + } + } + + if(pEntry && IS_ENTRY_CLIENT(pEntry) +#ifdef A4_CONN + && !IS_ENTRY_A4(pEntry) +#endif /* A4_CONN */ + && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED) + ) + { + EventHdlr pEventHdlrHook = NULL; + struct EventNotifierCfg *pEventNotifierCfg = &pAd->ApCfg.EventNotifyCfg; + if(pEventNotifierCfg->bStaStateTxDetect && (pEventNotifierCfg->StaTxPktDetectPeriod > 0)) + { + pEventNotifierCfg->StaTxPktDetectRound++; + if(((pEventNotifierCfg->StaTxPktDetectRound % pEventNotifierCfg->StaTxPktDetectPeriod) == 0)) + { + if((pEntry->tx_state.CurrentState == WHC_STA_STATE_ACTIVE) && + (pEntry->tx_state.PacketCount < pEventNotifierCfg->StaStateTxThreshold)) + { + pEntry->tx_state.CurrentState = WHC_STA_STATE_IDLE; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_STA_ACTIVITY_STATE); + if(pEventHdlrHook && pEntry->wdev) + pEventHdlrHook(pAd, pEntry, TRUE); + } + else if((pEntry->tx_state.CurrentState == WHC_STA_STATE_IDLE) && + (pEntry->tx_state.PacketCount >= pEventNotifierCfg->StaStateTxThreshold)) + { + + pEntry->tx_state.CurrentState = WHC_STA_STATE_ACTIVE; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_STA_ACTIVITY_STATE); + if(pEventHdlrHook && pEntry->wdev) + pEventHdlrHook(pAd, pEntry, TRUE); + } + pEventNotifierCfg->StaTxPktDetectRound = 0; + pEntry->tx_state.PacketCount = 0; + } + } + + if(pEventNotifierCfg->bStaStateRxDetect && (pEventNotifierCfg->StaRxPktDetectPeriod > 0)) + { + pEventNotifierCfg->StaRxPktDetectRound++; + if(((pEventNotifierCfg->StaRxPktDetectRound % pEventNotifierCfg->StaRxPktDetectPeriod) == 0)) + { + if((pEntry->rx_state.CurrentState == WHC_STA_STATE_ACTIVE) && + (pEntry->rx_state.PacketCount < pEventNotifierCfg->StaStateRxThreshold)) + { + pEntry->rx_state.CurrentState = WHC_STA_STATE_IDLE; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_STA_ACTIVITY_STATE); + if(pEventHdlrHook && pEntry->wdev) + pEventHdlrHook(pAd, pEntry, FALSE); + } + else if((pEntry->rx_state.CurrentState == WHC_STA_STATE_IDLE) && + (pEntry->rx_state.PacketCount >= pEventNotifierCfg->StaStateRxThreshold)) + { + pEntry->rx_state.CurrentState = WHC_STA_STATE_ACTIVE; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_STA_ACTIVITY_STATE); + if(pEventHdlrHook && pEntry->wdev) + pEventHdlrHook(pAd, pEntry, FALSE); + } + pEventNotifierCfg->StaRxPktDetectRound = 0; + pEntry->rx_state.PacketCount = 0; + } + } + } +#endif /* WH_EVENT_NOTIFIER */ + + +#ifdef EDCCA_RB + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) + { + client_rb++; + + if (pEntry->MaxHTPhyMode.field.MODE == MODE_CCK) + client_b++; + } +#endif /* EDCCA_RB */ + + } + + +#ifdef EDCCA_RB + if ((client_rb == 1) && + (client_b == 1) && + (pAd->CommonCfg.PhyMode == WMODE_B)) + RTMP_IO_WRITE32(pAd, CR_PHYMUX_11, 0xa0a10000); //0x1422C + else + RTMP_IO_WRITE32(pAd, CR_PHYMUX_11, 0x00000000); //0x1422C +#endif + +#ifdef MT_MAC + /* If we check that any preview stations are in Psm and no stations are in Psm now. */ + /* AP will dequeue all buffer broadcast packets */ + + if ((pAd->chipCap.hif_type == HIF_MT) && (pMacTable->fAnyStationInPsm == FALSE)) { + UINT apidx = 0; + for (apidx = 0; apidxApCfg.BssidNum; apidx++) + { + BSS_STRUCT *pMbss; + UINT wcid = 0; + STA_TR_ENTRY *tr_entry = NULL; + + pMbss = &pAd->ApCfg.MBSSID[apidx]; + + wcid = pMbss->wdev.tr_tb_idx; + tr_entry = &pAd->MacTab.tr_entry[wcid]; + + if ((bPreAnyStationInPsm == TRUE) && (tr_entry->tx_queue[QID_AC_BE].Head != NULL)) { + if (tr_entry->tx_queue[QID_AC_BE].Number > MAX_PACKETS_IN_MCAST_PS_QUEUE) + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, wcid, MAX_PACKETS_IN_MCAST_PS_QUEUE); + else + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, wcid, tr_entry->tx_queue[QID_AC_BE].Number); + } + } + } +#endif + +#ifdef WFA_VHT_PF + if (worst_rssi != NULL && + ((pAd->Mlme.OneSecPeriodicRound % 10) == 5) && + (worst_rssi_sta_idx >= 1)) + { + CHAR gain = 2; + if (worst_rssi->AvgRssi[0] >= -40) + gain = 1; + else if (worst_rssi->AvgRssi[0] <= -50) + gain = 2; + rt85592_lna_gain_adjust(pAd, gain); + DBGPRINT(RT_DEBUG_TRACE, ("%s():WorstRSSI for STA(%02x:%02x:%02x:%02x:%02x:%02x):%d,%d,%d, Set Gain as %s\n", + __FUNCTION__, + PRINT_MAC(pMacTable->Content[worst_rssi_sta_idx].Addr), + worst_rssi->AvgRssi[0], worst_rssi->AvgRssi[1], worst_rssi->AvgRssi[2], + (gain == 2 ? "Mid" : "Low"))); + } +#endif /* WFA_VHT_PF */ + +#ifdef PRE_ANT_SWITCH +#endif /* PRE_ANT_SWITCH */ + +#ifdef CFO_TRACK +#endif /* CFO_TRACK */ + + /* Update the state of port per MBSS */ + for (bss_index = BSS0; bss_index < MAX_MBSSID_NUM(pAd); bss_index++) + { + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[bss_index].wdev; + if ((fAnyStationPortSecured[bss_index] > 0) +#ifdef CONFIG_FPGA_MODE + || (pAd->fpga_ctl.fpga_on & 0x1) +#endif /* CONFIG_FPGA_MODE */ + ) + { + wdev->PortSecured = WPA_802_1X_PORT_SECURED; + pAd->MacTab.tr_entry[wdev->tr_tb_idx].PortSecured = WPA_802_1X_PORT_SECURED; + } + else { + wdev->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + pAd->MacTab.tr_entry[wdev->tr_tb_idx].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 GREENAP_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + if(pAd->MacTab.fAnyStationIsHT == FALSE + && pAd->ApCfg.bGreenAPEnable == TRUE) + { + 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 (pAd->MacTab.Size > 3) + { +#ifdef MULTI_CLIENT_SUPPORT + AsicSetRTSTxCntLimit(pAd, TRUE, RtsRetryCnt); +#else + AsicSetRTSTxCntLimit(pAd, TRUE, 0x7); +#endif + } else { + AsicSetRTSTxCntLimit(pAd, TRUE, MT_RTS_RETRY); + } + + if (bRdgActive != RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE)) + { + AsicSetRDG(pAd, bRdgActive); +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + AsicWtblSetRDG(pAd, bRdgActive); + } +#endif /* MT_MAC */ + } + + if (bRalinkBurstMode != RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE)) + AsicSetRalinkBurstMode(pAd, bRalinkBurstMode); + + if ((pMacTable->fAnyStationBadAtheros == FALSE) && (pAd->CommonCfg.IOTestParm.bRTSLongProtOn == TRUE)) + { + AsicUpdateProtect(pAd, pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode, ALLN_SETPROTECT, FALSE, pMacTable->fAnyStationNonGF); + } + +#ifdef MT_MAC + /* Under EDCCA_OFF condition, for TGn 4.2.7 fail issue, + Tx PER rate is very high when running with Intel 6300 testbed STA, + but low data rate has no any imprevement to get Tx PER lower. + That should be caused by collision situation. + + Thus we enable RTS/CTS to let retrying happens on RTS frames. + Data frame can keeps low Tx PER and can slow down the rate adaption. + Only legacy STAs are focused because we don't expect any behavior of 11n STA is changed. + */ + if (nLegacySTA == 1) + { + AsicWtblSetRTS(pAd, iLegacySTA[0], FALSE); + } + else if (nLegacySTA >= 2) + { + UCHAR j; + + for (j = 0; j < nLegacySTA; j ++) + AsicWtblSetRTS(pAd, iLegacySTA[j], TRUE); + } +#endif /* MT_MAC */ + +#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. + */ + // TODO: shiang-usw. revise this becasue now we have per-BSS McastPsQueue! + if (pMacTable->McastPsQueue.Head) + { + UINT bss_index; + + pMacTable->PsQIdleCount ++; + if (pMacTable->PsQIdleCount > 1) + { + + APCleanupPsQueue(pAd, &pMacTable->McastPsQueue); + pMacTable->PsQIdleCount = 0; + + if (pAd->ApCfg.BssidNum > MAX_MBSSID_NUM(pAd)) + pAd->ApCfg.BssidNum = MAX_MBSSID_NUM(pAd); + + /* clear MCAST/BCAST backlog bit for all BSS */ + for(bss_index=BSS0; bss_indexApCfg.BssidNum; bss_index++) + WLAN_MR_TIM_BCMC_CLEAR(bss_index); + } + } + else + pMacTable->PsQIdleCount = 0; +#ifdef RTMP_MAC_PCI + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); +#endif /* RTMP_MAC_PCI */ +} + + +UINT32 MacTableAssocStaNumGet(RTMP_ADAPTER *pAd) +{ + UINT32 num = 0; + UINT32 i; + + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i]; + + if (!IS_ENTRY_CLIENT(pEntry)) + continue; + + if (pEntry->Sst == SST_ASSOC) + num ++; + } + + return num; +} + + +/* + ========================================================================== + Description: + Look up a STA MAC table. Return its Sst to decide if an incoming + frame from this STA or an outgoing frame to this STA is permitted. + Return: + ========================================================================== +*/ +MAC_TABLE_ENTRY *APSsPsInquiry( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + OUT SST *Sst, + OUT USHORT *Aid, + OUT UCHAR *PsMode, + OUT UCHAR *Rate) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + + if (MAC_ADDR_IS_GROUP(pAddr)) /* mcast & broadcast address */ + { + *Sst = SST_ASSOC; + *Aid = MCAST_WCID; /* Softap supports 1 BSSID and use WCID=0 as multicast Wcid index */ + *PsMode = PWR_ACTIVE; + *Rate = pAd->CommonCfg.MlmeRate; + } + else /* unicast address */ + { + pEntry = MacTableLookup(pAd, pAddr); + if (pEntry) + { + *Sst = pEntry->Sst; + *Aid = pEntry->Aid; + *PsMode = pEntry->PsMode; + if ((pEntry->AuthMode >= Ndis802_11AuthModeWPA) && (pEntry->GTKState != REKEY_ESTABLISHED)) + *Rate = pAd->CommonCfg.MlmeRate; + else + *Rate = pEntry->CurrTxRate; + } + else + { + *Sst = SST_NOT_AUTH; + *Aid = MCAST_WCID; + *PsMode = PWR_ACTIVE; + *Rate = pAd->CommonCfg.MlmeRate; + } + } + + return pEntry; +} + + +#ifdef SYSTEM_LOG_SUPPORT +/* + ========================================================================== + Description: + This routine is called to log a specific event into the event table. + The table is a QUERY-n-CLEAR array that stop at full. + ========================================================================== + */ +VOID ApLogEvent(RTMP_ADAPTER *pAd, UCHAR *pAddr, 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(RTMP_ADAPTER *pAd) +{ + BOOLEAN bDisableBGProtect = FALSE, bNonGFExist = FALSE; + + pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 0; + if ((pAd->ApCfg.LastNoneHTOLBCDetectTime + (5 * OS_HZ)) > pAd->Mlme.Now32) /* non HT BSS exist within 5 sec */ + { + pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 1; + bDisableBGProtect = FALSE; + bNonGFExist = TRUE; + } + + /* If I am 40MHz BSS, and there exist HT-20MHz station. */ + /* Update to 2 when it's zero. Because OperaionMode = 1 or 3 has more protection. */ + if ((pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode == 0) && + (pAd->MacTab.fAnyStation20Only) && + (pAd->CommonCfg.DesiredHtPhy.ChannelWidth == 1)) + { + pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 2; + bDisableBGProtect = TRUE; + } + + if (pAd->MacTab.fAnyStationIsLegacy || pAd->MacTab.Size > 1) + { + pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode = 3; + bDisableBGProtect = TRUE; + } + + if (bNonGFExist == FALSE) + bNonGFExist = pAd->MacTab.fAnyStationNonGF; + + AsicUpdateProtect(pAd, + pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode, + (ALLN_SETPROTECT), + bDisableBGProtect, + bNonGFExist); + + pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = pAd->MacTab.fAnyStationNonGF; +} +#endif /* DOT11_N_SUPPORT */ + + +/* + ========================================================================== + Description: + Check to see the exist of long preamble STA in associated list + ========================================================================== + */ +BOOLEAN ApCheckLongPreambleSTA(RTMP_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: + 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(RTMP_ADAPTER *pAd) +{ + UCHAR i, ErpIeContent = 0; + BOOLEAN ShortSlotCapable = pAd->CommonCfg.bUseShortSlotTime; + UCHAR apidx; + BOOLEAN bUseBGProtection; + BOOLEAN LegacyBssExist; + + + if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B)) + return; + + for (i=1; iMacTab.Content[i]; + if (!IS_ENTRY_CLIENT(pEntry) || (pEntry->Sst != SST_ASSOC)) + continue; + + /* at least one 11b client associated, turn on ERP.NonERPPresent bit */ + /* almost all 11b client won't support "Short Slot" time, turn off for maximum compatibility */ + if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE) + { + ShortSlotCapable = FALSE; + ErpIeContent |= 0x01; + } + + /* at least one client can't support short slot */ + if ((pEntry->CapabilityInfo & 0x0400) == 0) + ShortSlotCapable = FALSE; + } + + /* legacy BSS exist within 5 sec */ + if ((pAd->ApCfg.LastOLBCDetectTime + (5 * OS_HZ)) > pAd->Mlme.Now32) + LegacyBssExist = TRUE; + else + LegacyBssExist = FALSE; + + /* decide ErpIR.UseProtection bit, depending on pAd->CommonCfg.UseBGProtection + AUTO (0): UseProtection = 1 if any 11b STA associated + ON (1): always USE protection + OFF (2): always NOT USE protection + */ + if (pAd->CommonCfg.UseBGProtection == 0) + { + ErpIeContent = (ErpIeContent)? 0x03 : 0x00; + /*if ((pAd->ApCfg.LastOLBCDetectTime + (5 * OS_HZ)) > pAd->Mlme.Now32) // legacy BSS exist within 5 sec */ + if (LegacyBssExist) + { + ErpIeContent |= 0x02; /* set Use_Protection bit */ + } + } + else if (pAd->CommonCfg.UseBGProtection == 1) + ErpIeContent |= 0x02; + + + bUseBGProtection = (pAd->CommonCfg.UseBGProtection == 1) || /* always use */ + ((pAd->CommonCfg.UseBGProtection == 0) && ERP_IS_USE_PROTECTION(ErpIeContent)); + +#ifdef A_BAND_SUPPORT + /* always no BG protection in A-band. falsely happened when switching A/G band to a dual-band AP */ + if (pAd->CommonCfg.Channel > 14) + bUseBGProtection = FALSE; +#endif /* A_BAND_SUPPORT */ + + if (bUseBGProtection != OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + { + USHORT OperationMode = 0; + BOOLEAN bNonGFExist = 0; + +#ifdef DOT11_N_SUPPORT + OperationMode = pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode; + bNonGFExist = pAd->MacTab.fAnyStationNonGF; +#endif /* DOT11_N_SUPPORT */ + if (bUseBGProtection) + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); + AsicUpdateProtect(pAd, OperationMode, (OFDMSETPROTECT), FALSE, bNonGFExist); + } + else + { + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED); + AsicUpdateProtect(pAd, OperationMode, (OFDMSETPROTECT), TRUE, bNonGFExist); + } + } + + /* Decide Barker Preamble bit of ERP IE */ + if ((pAd->CommonCfg.TxPreamble == Rt802_11PreambleLong) || (ApCheckLongPreambleSTA(pAd) == TRUE)) + pAd->ApCfg.ErpIeContent = (ErpIeContent | 0x04); + else + pAd->ApCfg.ErpIeContent = ErpIeContent; + +#ifdef A_BAND_SUPPORT + /* Force to use ShortSlotTime at A-band */ + if (pAd->CommonCfg.Channel > 14) + ShortSlotCapable = TRUE; +#endif /* A_BAND_SUPPORT */ + + /* deicide CapabilityInfo.ShortSlotTime bit */ + for (apidx=0; apidxApCfg.BssidNum; apidx++) + { + USHORT *pCapInfo = &(pAd->ApCfg.MBSSID[apidx].CapabilityInfo); + + /* In A-band, the ShortSlotTime bit should be ignored. */ + if (ShortSlotCapable +#ifdef A_BAND_SUPPORT + && (pAd->CommonCfg.Channel <= 14) +#endif /* A_BAND_SUPPORT */ + ) + (*pCapInfo) |= 0x0400; + else + (*pCapInfo) &= 0xfbff; + + + if (pAd->CommonCfg.TxPreamble == Rt802_11PreambleLong) + (*pCapInfo) &= (~0x020); + else + (*pCapInfo) |= 0x020; + + } + + AsicSetSlotTime(pAd, ShortSlotCapable, pAd->CommonCfg.Channel); + +} + +#ifdef STA_FORCE_ROAM_SUPPORT +BOOLEAN ApCheckFroamAccessControlList( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR Apidx) +{ + BOOLEAN Result = TRUE; + ULONG i; + + if (pAd->en_force_roam_supp) { + Result = TRUE; + for (i = 0; i < pAd->ApCfg.MBSSID[Apidx].FroamAccessControlList.Num; i++) { + if (MAC_ADDR_EQUAL(pAddr, pAd->ApCfg.MBSSID[Apidx].FroamAccessControlList.Entry[i].Addr)) { + Result = FALSE; + 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; +} +#endif + +/* + ========================================================================== + 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(RTMP_ADAPTER *pAd, UCHAR *pAddr, UCHAR Apidx) +{ + BOOLEAN Result = TRUE; + ULONG i; +#ifdef ACL_BLK_COUNT_SUPPORT + ULONG idx; +#endif +#ifdef ACL_V2_SUPPORT + if((Result = ACL_V2_List_Check(pAd,pAddr,Apidx)) == FALSE) + { + goto done; + } +#endif /* ACL_V2_SUPPORT */ + +#ifdef STA_FORCE_ROAM_SUPPORT + if (pAd->en_force_roam_supp) { + Result = TRUE; + for (i = 0; i < pAd->ApCfg.MBSSID[Apidx].FroamAccessControlList.Num; i++) { + if (MAC_ADDR_EQUAL(pAddr, + pAd->ApCfg.MBSSID[Apidx].FroamAccessControlList.Entry[i].Addr)) { + Result = FALSE; + break; + } + } + } +#endif + if (Result == TRUE) { + if (pAd->ApCfg.MBSSID[Apidx].AccessControlList.Policy == 0) /* ACL is disabled */ + Result = TRUE; + else + { + 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; i < pAd->ApCfg.MBSSID[Apidx].AccessControlList.Num; i++) { + if (MAC_ADDR_EQUAL(pAddr, pAd->ApCfg.MBSSID[Apidx].AccessControlList.Entry[i].Addr)) { + Result = !Result; + break; + } + } + } + } +#ifdef ACL_V2_SUPPORT +done: +#endif /* ACL_V2_SUPPORT */ +#ifdef ACL_BLK_COUNT_SUPPORT + if (pAd->ApCfg.MBSSID[Apidx].AccessControlList.Policy != 2) { + for (i = 0; i < pAd->ApCfg.MBSSID[Apidx].AccessControlList.Num; i++) + (pAd->ApCfg.MBSSID[Apidx].AccessControlList.Entry[i].Reject_Count) = 0; + } +#endif + if (FALSE == Result) + { +#ifdef ACL_BLK_COUNT_SUPPORT + + if (pAd->ApCfg.MBSSID[Apidx].AccessControlList.Policy == 2) { + for (idx = 0; idx < pAd->ApCfg.MBSSID[Apidx].AccessControlList.Num; idx++) { + if (MAC_ADDR_EQUAL(pAddr, pAd->ApCfg.MBSSID[Apidx].AccessControlList.Entry[idx].Addr)) { + (pAd->ApCfg.MBSSID[Apidx].AccessControlList.Entry[idx].Reject_Count) += 1; + break; + } + } + } +#endif + DBGPRINT(RT_DEBUG_TRACE, ("%02x:%02x:%02x:%02x:%02x:%02x failed in ACL checking\n", + PRINT_MAC(pAddr))); + } + + return Result; +} + + +/* + ========================================================================== + Description: + This routine update the current MAC table based on the current ACL. + If ACL change causing an associated STA become un-authorized. This STA + will be kicked out immediately. + ========================================================================== +*/ +VOID ApUpdateAccessControlList(RTMP_ADAPTER *pAd, UCHAR Apidx) +{ + USHORT AclIdx, MacIdx; + BOOLEAN Matched; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + HEADER_802_11 DisassocHdr; + USHORT Reason; + MAC_TABLE_ENTRY *pEntry; + BSS_STRUCT *pMbss; + BOOLEAN drop; + + ASSERT(Apidx < MAX_MBSSID_NUM(pAd)); + if (Apidx >= MAX_MBSSID_NUM(pAd)) + return; + DBGPRINT(RT_DEBUG_TRACE, ("ApUpdateAccessControlList : Apidx = %d\n", Apidx)); + + /* ACL is disabled. Do nothing about the MAC table. */ + pMbss = &pAd->ApCfg.MBSSID[Apidx]; +#ifdef STA_FORCE_ROAM_SUPPORT + if (pMbss->AccessControlList.Policy == 0) { + if (pAd->en_force_roam_supp == 0) + return; + } +#else + if (pMbss->AccessControlList.Policy == 0) + return; +#endif + + for (MacIdx=0; MacIdx < MAX_LEN_OF_MAC_TABLE; MacIdx++) + { + pEntry = &pAd->MacTab.Content[MacIdx]; + if (!IS_ENTRY_CLIENT(pEntry)) + continue; + + /* We only need to update associations related to ACL of MBSSID[Apidx]. */ + if (pEntry->func_tb_idx != Apidx) + continue; + + drop = FALSE; + Matched = FALSE; +#ifdef STA_FORCE_ROAM_SUPPORT + if (pAd->en_force_roam_supp) { + for (AclIdx = 0; AclIdx < pMbss->FroamAccessControlList.Num; AclIdx++) { + if (MAC_ADDR_EQUAL(&pEntry->Addr[0], + pMbss->FroamAccessControlList.Entry[AclIdx].Addr)) { + Matched = TRUE; + drop = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("STA on negative ACL. remove it...\n")); + break; + } + } + } + if (drop == FALSE) +#endif + { + Matched = FALSE; + for (AclIdx = 0; AclIdx < pMbss->AccessControlList.Num; AclIdx++) { + if (MAC_ADDR_EQUAL(&pEntry->Addr[0], pMbss->AccessControlList.Entry[AclIdx].Addr)) { + Matched = TRUE; + break; + } + } + if ((Matched == FALSE) && (pMbss->AccessControlList.Policy == 1)) { + drop = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("STA not on positive ACL. remove it...\n")); + } else if ((Matched == TRUE) && (pMbss->AccessControlList.Policy == 2)) { + drop = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("STA on negative ACL. remove it...\n")); + } + } + if (drop == TRUE) { + DBGPRINT(RT_DEBUG_TRACE, ("Apidx = %d\n", Apidx)); + DBGPRINT(RT_DEBUG_TRACE, ("pAd->ApCfg.MBSSID[%d].AccessControlList.Policy = %ld\n", Apidx, + pMbss->AccessControlList.Policy)); + + /* Before delete the entry from MacTable, send disassociation packet to client. */ + if (pEntry->Sst == SST_ASSOC) + { + /* send out a DISASSOC frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, (" MlmeAllocateMemory fail ..\n")); + return; + } + + Reason = REASON_DECLINED; + DBGPRINT(RT_DEBUG_ERROR, ("ASSOC - Send DISASSOC Reason = %d frame TO %x %x %x %x %x %x \n", + Reason, PRINT_MAC(pEntry->Addr))); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, + pEntry->Addr, + pMbss->wdev.if_addr, + pMbss->wdev.bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, sizeof(HEADER_802_11), &DisassocHdr, 2, &Reason, END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + RtmpusecDelay(5000); + } +#ifdef WIFI_DIAG + if (IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_ACL_BLK, 0); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + REASON_DECLINED); +#endif + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + } + } +} + + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 +/* + Depends on the 802.11n Draft 4.0, Before the HT AP start a BSS, it should scan some specific channels to +collect information of existing BSSs, then depens on the collected channel information, adjust the primary channel +and secondary channel setting. + + For 5GHz, + Rule 1: If the AP chooses to start a 20/40 MHz BSS in 5GHz and that occupies the same two channels + as any existing 20/40 MHz BSSs, then the AP shall ensure that the primary channel of the + new BSS is identical to the primary channel of the existing 20/40 MHz BSSs and that the + secondary channel of the new 20/40 MHz BSS is identical to the secondary channel of the + existing 20/40 MHz BSSs, unless the AP discoverr that on those two channels are existing + 20/40 MHz BSSs with different primary and secondary channels. + Rule 2: If the AP chooses to start a 20/40MHz BSS in 5GHz, the selected secondary channel should + correspond to a channel on which no beacons are detected during the overlapping BSS + scan time performed by the AP, unless there are beacons detected on both the selected + primary and secondary channels. + Rule 3: An HT AP should not start a 20 MHz BSS in 5GHz on a channel that is the secondary channel + of a 20/40 MHz BSS. + For 2.4GHz, + Rule 1: The AP shall not start a 20/40 MHz BSS in 2.4GHz if the value of the local variable "20/40 + Operation Permitted" is FALSE. + + 20/40OperationPermitted = (P == OPi for all values of i) AND + (P == OTi for all values of i) AND + (S == OSi for all values if i) + where + P is the operating or intended primary channel of the 20/40 MHz BSS + S is the operating or intended secondary channel of the 20/40 MHz BSS + OPi is member i of the set of channels that are members of the channel set C and that are the + primary operating channel of at least one 20/40 MHz BSS that is detected within the AP's + BSA during the previous X seconds + OSi is member i of the set of channels that are members of the channel set C and that are the + secondary operating channel of at least one 20/40 MHz BSS that is detected within AP's + BSA during the previous X seconds + OTi is member i of the set of channels that comparises all channels that are members of the + channel set C that were listed once in the Channel List fields of 20/40 BSS Intolerant Channel + Report elements receved during the previous X seconds and all channels that are members + of the channel set C and that are the primary operating channel of at least one 20/40 MHz + BSS that were detected within the AP's BSA during the previous X seconds. + C is the set of all channels that are allowed operating channels within the current operational + regulatory domain and whose center frequency falls within the 40 MHz affected channel + range given by following equation: + Fp + Fs Fp + Fs + 40MHz affected channel range = [ ------ - 25MHz, ------- + 25MHz ] + 2 2 + Where + Fp = the center frequency of channel P + Fs = the center frequency of channel S + + "==" means that the values on either side of the "==" are to be tested for equaliy with a resulting + Boolean value. + =>When the value of OPi is the empty set, then the expression (P == OPi for all values of i) + is defined to be TRUE + =>When the value of OTi is the empty set, then the expression (P == OTi for all values of i) + is defined to be TRUE + =>When the value of OSi is the empty set, then the expression (S == OSi for all values of i) + is defined to be TRUE +*/ +INT GetBssCoexEffectedChRange( + IN RTMP_ADAPTER *pAd, + IN BSS_COEX_CH_RANGE *pCoexChRange) +{ + INT index, cntrCh = 0; + + memset(pCoexChRange, 0, sizeof(BSS_COEX_CH_RANGE)); + + /* Build the effected channel list, if something wrong, return directly. */ +#ifdef A_BAND_SUPPORT + if (pAd->CommonCfg.Channel > 14) + { /* For 5GHz band */ + for (index = 0; index < pAd->ChannelListNum; index++) + { + if(pAd->ChannelList[index].Channel == pAd->CommonCfg.Channel) + break; + } + + if (index < pAd->ChannelListNum) + { + /* First get the primary channel */ + pCoexChRange->primaryCh = pAd->ChannelList[index].Channel; + + /* Now check about the secondary and central channel */ + if(pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + { + pCoexChRange->effectChStart = pCoexChRange->primaryCh; + pCoexChRange->effectChEnd = pCoexChRange->primaryCh + 4; + pCoexChRange->secondaryCh = pCoexChRange->effectChEnd; + } + else + { + pCoexChRange->effectChStart = pCoexChRange->primaryCh -4; + pCoexChRange->effectChEnd = pCoexChRange->primaryCh; + pCoexChRange->secondaryCh = pCoexChRange->effectChStart; + } + + DBGPRINT(RT_DEBUG_TRACE,("5.0GHz: Found CtrlCh idx(%d) from the ChList, ExtCh=%s, PriCh=[Idx:%d, CH:%d], SecCh=[Idx:%d, CH:%d], effected Ch=[CH:%d~CH:%d]!\n", + index, + ((pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) ? "ABOVE" : "BELOW"), + pCoexChRange->primaryCh, pAd->ChannelList[pCoexChRange->primaryCh].Channel, + pCoexChRange->secondaryCh, pAd->ChannelList[pCoexChRange->secondaryCh].Channel, + pAd->ChannelList[pCoexChRange->effectChStart].Channel, + pAd->ChannelList[pCoexChRange->effectChEnd].Channel)); + return TRUE; + } + else + { + /* It should not happened! */ + DBGPRINT(RT_DEBUG_ERROR, ("5GHz: Cannot found the CtrlCh(%d) in ChList, something wrong?\n", + pAd->CommonCfg.Channel)); + } + } + else +#endif /* A_BAND_SUPPORT */ + { /* For 2.4GHz band */ + for (index = 0; index < pAd->ChannelListNum; index++) + { + if(pAd->ChannelList[index].Channel == pAd->CommonCfg.Channel) + break; + } + + if (index < pAd->ChannelListNum) + { + /* First get the primary channel */ + pCoexChRange->primaryCh = index; + + /* Now check about the secondary and central channel */ + if(pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + { + if ((index + 4) < pAd->ChannelListNum) + { + cntrCh = index + 2; + pCoexChRange->secondaryCh = index + 4; + } + } + else + { + if ((index - 4) >=0) + { + cntrCh = index - 2; + pCoexChRange->secondaryCh = index - 4; + } + } + + if (cntrCh) + { + pCoexChRange->effectChStart = (cntrCh - 5) > 0 ? (cntrCh - 5) : 0; + pCoexChRange->effectChEnd= cntrCh + 5; + DBGPRINT(RT_DEBUG_TRACE,("2.4GHz: 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; + } + + /* It should not happened! */ + DBGPRINT(RT_DEBUG_ERROR, ("2.4GHz: Didn't found valid channel range, Ch index=%d, ChListNum=%d, CtrlCh=%d\n", + index, pAd->ChannelListNum, pAd->CommonCfg.Channel)); + } + + return FALSE; +} + + +VOID APOverlappingBSSScan(RTMP_ADAPTER *pAd) +{ + BOOLEAN needFallBack = FALSE; + UCHAR Channel = pAd->CommonCfg.Channel; + INT chStartIdx, chEndIdx, index,curPriChIdx, curSecChIdx; +#ifdef WH_EZ_SETUP + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + struct wifi_dev *wdev; + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; +#endif + + /* We just care BSS who operating in 40MHz N Mode. */ + if ((!WMODE_CAP_N(pAd->CommonCfg.PhyMode)) || + (pAd->CommonCfg.Channel > 14) || + (pAd->CommonCfg.ori_bw_before_2040_coex == BW_20)) + { + 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) + { + DBGPRINT(RT_DEBUG_TRACE, ("Card still not enable Tx/Rx, enable it now!\n")); +#ifdef RTMP_MAC_PCI + /* Enable Interrupt */ + rtmp_irq_init(pAd); + + RTMP_IRQ_ENABLE(pAd); +#endif /* RTMP_MAC_PCI */ + + + /* rtmp_rx_done_handle() API will check this flag to decide accept incoming packet or not. */ + /* Set the flag be ready to receive Beacon frame for autochannel select. */ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP); + } + + RTMPEnableRxTx(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Ready to do passive scanning for Channel[%d] to Channel[%d]!\n", + pAd->ChannelList[chStartIdx].Channel, pAd->ChannelList[chEndIdx].Channel)); + + /* Now start to do the passive scanning. */ + pAd->CommonCfg.bOverlapScanning = TRUE; + for (index = chStartIdx; index<=chEndIdx; index++) + { + Channel = pAd->ChannelList[index].Channel; + AsicSetChannel(pAd, Channel, BW_20, EXTCHA_NONE, TRUE); + + DBGPRINT(RT_DEBUG_ERROR, ("SYNC - BBP R4 to 20MHz.l\n")); + /*DBGPRINT(RT_DEBUG_TRACE, ("Passive scanning for Channel %d.....\n", Channel)); */ + OS_WAIT(300); /* wait for 200 ms at each channel. */ + } + pAd->CommonCfg.bOverlapScanning = FALSE; + + /* After scan all relate channels, now check the scan result to find out if we need fallback to 20MHz. */ + for (index = chStartIdx; index <= chEndIdx; index++) + { + DBGPRINT(RT_DEBUG_TRACE, ("Channel[Idx=%d, Ch=%d].bEffectedChannel=0x%x!\n", + index, pAd->ChannelList[index].Channel, pAd->ChannelList[index].bEffectedChannel)); + if ((pAd->ChannelList[index].bEffectedChannel & (EFFECTED_CH_PRIMARY | EFFECTED_CH_LEGACY)) && (index != curPriChIdx) ) + { + needFallBack = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("needFallBack=TRUE due to OP/OT!\n")); + } + if ((pAd->ChannelList[index].bEffectedChannel & EFFECTED_CH_SECONDARY) && (index != curSecChIdx)) + { + needFallBack = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("needFallBack=TRUE due to OS!\n")); + } + } + + /* If need fallback, now do it. */ + if ((needFallBack == TRUE) + && (pAd->CommonCfg.BssCoexApCnt > pAd->CommonCfg.BssCoexApCntThr) + ) + { +#if (defined(WH_EZ_SETUP) && defined(EZ_NETWORK_MERGE_SUPPORT)) + if(IS_EZ_SETUP_ENABLED(wdev)){ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("\nAPOverlappingBSSScan: Fallback at bootup ****\n")); + ez_set_ap_fallback_context(wdev,TRUE,pAd->CommonCfg.Channel); + } +#endif /* WH_EZ_SETUP */ + 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; +#ifdef NEW_BW2040_COEXIST_SUPPORT + pAd->CommonCfg.RegTransmitSetting.field.BW = 0;/* radio fallback */ +#endif /* NEW_BW2040_COEXIST_SUPPORT */ + pAd->CommonCfg.Bss2040NeedFallBack = 1; + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = 0; + } + + /* Recover the bandwidth to support 20/40Mhz if the original setting does support that, and no need to fallback */ + if ((needFallBack == FALSE) + && (pAd->CommonCfg.ori_bw_before_2040_coex == BW_40)) { + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = pAd->CommonCfg.ori_bw_before_2040_coex; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = pAd->CommonCfg.ori_ext_channel_before_2040_coex; + pAd->CommonCfg.LastBSSCoexist2040.field.BSS20WidthReq = 0; + pAd->CommonCfg.Bss2040CoexistFlag &= (~BSS_2040_COEXIST_INFO_SYNC); + pAd->CommonCfg.Bss2040NeedFallBack = 0; + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = pAd->CommonCfg.ori_ext_channel_before_2040_coex; + DBGPRINT(RT_DEBUG_ERROR, ("rollback the bandwidth setting to support 20/40Mhz\n")); + } + + return; +} +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + +#ifdef DOT1X_SUPPORT +/* + ======================================================================== + Routine Description: + Send Leyer 2 Frame to notify 802.1x daemon. This is a internal command + + Arguments: + + Return Value: + TRUE - send successfully + FAIL - send fail + + Note: + ======================================================================== +*/ +BOOLEAN DOT1X_InternalCmdAction( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UINT8 cmd) +{ + // TODO: shiang-usw, fix me for pEntry->apidx to func_tb_idx + 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->func_tb_idx; + NdisMoveMemory(s_addr, pEntry->Addr, MAC_ADDR_LEN); + } + else + { + /* Fake a Source Address for transmission */ + NdisMoveMemory(s_addr, pAd->ApCfg.MBSSID[apidx].wdev.bssid, MAC_ADDR_LEN); + s_addr[0] |= 0x80; + } + + /* Assign internal command for Ralink dot1x daemon */ + RalinkIe[5] = cmd; + + /* Prepare the 802.3 header */ + MAKE_802_3_HEADER(FrameBuf, + pAd->ApCfg.MBSSID[apidx].wdev.bssid, + s_addr, + EAPOL_IE); + offset += LENGTH_802_3; + + /* Prepare the specific header of internal command */ + NdisMoveMemory(&FrameBuf[offset], RalinkIe, sizeof(RalinkIe)); + + /* Report to upper layer */ + if (RTMP_L2_FRAME_TX_ACTION(pAd, apidx, FrameBuf, frame_len) == FALSE) + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s done. (cmd=%d)\n", __FUNCTION__, cmd)); + + return TRUE; +} + + +/* + ======================================================================== + Routine Description: + Send Leyer 2 Frame to trigger 802.1x EAP state machine. + + Arguments: + + Return Value: + TRUE - send successfully + FAIL - send fail + + Note: + ======================================================================== +*/ +BOOLEAN DOT1X_EapTriggerAction(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + // TODO: shiang-usw, fix me for pEntry->apidx to func_tb_idx + INT apidx = MAIN_MBSSID; + UCHAR eapol_start_1x_hdr[4] = {0x01, 0x01, 0x00, 0x00}; + UINT8 frame_len = LENGTH_802_3 + sizeof(eapol_start_1x_hdr); + UCHAR FrameBuf[frame_len+32]; + UINT8 offset = 0; + + if((pEntry->AuthMode == Ndis802_11AuthModeWPA) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pAd->ApCfg.MBSSID[apidx].wdev.IEEE8021X == TRUE)) + { + /* Init the frame buffer */ + NdisZeroMemory(FrameBuf, frame_len); + + /* Assign apidx */ + apidx = pEntry->func_tb_idx; + + /* Prepare the 802.3 header */ + MAKE_802_3_HEADER(FrameBuf, pAd->ApCfg.MBSSID[apidx].wdev.bssid, pEntry->Addr, EAPOL); + offset += LENGTH_802_3; + + /* Prepare a fake eapol-start body */ + NdisMoveMemory(&FrameBuf[offset], eapol_start_1x_hdr, sizeof(eapol_start_1x_hdr)); + +#ifdef CONFIG_HOTSPOT_R2 + if (pEntry) + { + BSS_STRUCT *pMbss = pEntry->pMbss; + if ((pMbss->HotSpotCtrl.HotSpotEnable == 1) && (pMbss->wdev.AuthMode == Ndis802_11AuthModeWPA2) && (pEntry->hs_info.ppsmo_exist == 1)) + { + UCHAR HS2_Header[4] = {0x50,0x6f,0x9a,0x12}; + memcpy(&FrameBuf[offset+sizeof(eapol_start_1x_hdr)], HS2_Header, 4); + memcpy(&FrameBuf[offset+sizeof(eapol_start_1x_hdr)+4], &pEntry->hs_info, sizeof(struct _sta_hs_info)); + frame_len += 4+sizeof(struct _sta_hs_info); + printk("event eapol start, %x:%x:%x:%x\n", + FrameBuf[offset+sizeof(eapol_start_1x_hdr)+4],FrameBuf[offset+sizeof(eapol_start_1x_hdr)+5], + FrameBuf[offset+sizeof(eapol_start_1x_hdr)+6],FrameBuf[offset+sizeof(eapol_start_1x_hdr)+7]); + } + } +#endif + /* Report to upper layer */ + if (RTMP_L2_FRAME_TX_ACTION(pAd, apidx, FrameBuf, frame_len) == FALSE) + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Notify 8021.x daemon to trigger EAP-SM for this sta(%02x:%02x:%02x:%02x:%02x:%02x)\n", PRINT_MAC(pEntry->Addr))); + + } + + return TRUE; +} + +#endif /* DOT1X_SUPPORT */ + +#ifdef CONN_FAIL_EVENT +void ApSendConnFailMsg( + PRTMP_ADAPTER pAd, + CHAR *Ssid, + UCHAR SsidLen, + UCHAR *StaAddr, + USHORT ReasonCode) +{ + struct CONN_FAIL_MSG msg; + + if (!pAd) + return; + + memset(&msg, 0, sizeof(msg)); + + if (SsidLen > 32) + msg.SsidLen = 32; + else + msg.SsidLen = SsidLen; + + if (Ssid && (msg.SsidLen > 0)) + memcpy(msg.Ssid, Ssid, msg.SsidLen); + + if (StaAddr) + memcpy(msg.StaAddr, StaAddr, 6); + + msg.ReasonCode = ReasonCode; + + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_802_11_CONN_FAIL_MSG, + NULL, + (UCHAR *)&msg, + sizeof(msg)); + + DBGPRINT(RT_DEBUG_TRACE, + ("%s, SsidLen=%d, Ssid=%s, StaAddr=%02x:%02x:%02x:%02x:%02x:%02x, ReasonCode=%d\n", + __func__, msg.SsidLen, msg.Ssid, PRINT_MAC(msg.StaAddr), msg.ReasonCode)); +} +#endif + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_acl_v2.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_acl_v2.c new file mode 100644 index 000000000..52ae89126 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_acl_v2.c @@ -0,0 +1,724 @@ + +#ifdef ACL_V2_SUPPORT + +#include "rt_config.h" + +// check http://www.coffer.com/mac_find/ not all can be found, need huawei to refine this table!! +OUI_ENTRY OUI_ACL_TABLE[] = +{ + {FBT_IOT_PEER_UNKNOWN, {0x00,0x00,0x00}}, + + /*Realtek why need 5 IDs ??, only 3 can be found*/ + {FBT_IOT_PEER_REALTEK, {0x00,0x48,0x54}}, //first three + {FBT_IOT_PEER_REALTEK_92SE, {0x00,0xe0,0x4c}}, //first three + {FBT_IOT_PEER_REALTEK_SOFTAP, {0x52,0x54,0x05}}, //first three + //{FBT_IOT_PEER_RTK_APCLIENT, {0x00,0x00,0x00}}, //can't be found + //{FBT_IOT_PEER_REALTEK_81XX, {0x00,0x00,0x00}}, //can't be found + //{FBT_IOT_PEER_REALTEK_WOW, {0x00,0x00,0x00}}, //can't be found + + {FBT_IOT_PEER_BROADCOM, {0x00,0x05,0xb5}}, + + {FBT_IOT_PEER_RALINK, {0x00,0x0c,0x43}}, + + {FBT_IOT_PEER_ATHEROS, {0x00,0x03,0x7f}}, + {FBT_IOT_PEER_ATHEROS, {0x00,0x13,0x74}}, + {FBT_IOT_PEER_ATHEROS, {0x88,0x12,0x4e}}, + + /*too many cisco OUIs, only keep 3*/ + {FBT_IOT_PEER_CISCO, {0x00,0x00,0x0c}}, + {FBT_IOT_PEER_CISCO, {0x00,0x01,0x42}}, + {FBT_IOT_PEER_CISCO, {0x00,0x01,0x43}}, + + {FBT_IOT_PEER_MERU, {0x00,0x0c,0xe6}}, + + {FBT_IOT_PEER_MARVEL, {0x00,0x50,0x43}}, + + //{FBT_IOT_PEER_SELF_SOFTAP, {000000}}, // can't be found + + {FBT_IOT_PEER_AIRGO, {0x00,0x0a,0xf5}}, + + /*too many cisco OUIs, only keep 3*/ + {FBT_IOT_PEER_INTEL, {0x00,0x02,0xb3}}, + {FBT_IOT_PEER_INTEL, {0x00,0x03,0x47}}, + {FBT_IOT_PEER_INTEL, {0x00,0x04,0x23}}, + + /*too many , only keep 1! */ + {FBT_IOT_PEER_HTC, {0x00,0x04,0x23}}, + //{FBT_IOT_PEER_MAX, {0x00,0x00,0x00}}, // can't be found +}; + +INT OUI_ACL_TABLE_NUM = (sizeof(OUI_ACL_TABLE)/sizeof(OUI_ENTRY)); + + + +VOID ACL_V2_Timeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + + +BUILD_TIMER_FUNCTION(ACL_V2_Timeout); + + + +VOID ACL_V2_CtrlInit(IN PRTMP_ADAPTER pAd) +{ + PACL_V2_CTRL pACLCtrl; +#ifdef CONFIG_AP_SUPPORT + UCHAR APIndex; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + pACLCtrl = &pAd->ApCfg.MBSSID[APIndex].AccessControlList_V2; + + NdisZeroMemory(pACLCtrl, sizeof(*pACLCtrl)); + pACLCtrl->BlockTime = 2; //spec is 2 seconds by default + + pACLCtrl->pAd = pAd; + + RTMPInitTimer(pAd, &pACLCtrl->AgeOutTimer, + GET_TIMER_FUNCTION(ACL_V2_Timeout), pACLCtrl, FALSE); + + pACLCtrl->AgeOutTimer_Running = FALSE; + NdisAllocateSpinLock(pAd, &pACLCtrl->MAC_ListLock); + NdisAllocateSpinLock(pAd, &pACLCtrl->OUI_ListLock); + + DlListInit(&pACLCtrl->MAC_List); + DlListInit(&pACLCtrl->OUI_List); + } +#endif +} + +VOID ACL_V2_CtrlExit(IN PRTMP_ADAPTER pAd) +{ + PACL_V2_CTRL pACLCtrl; + UINT32 Ret; + BOOLEAN Cancelled; + +#ifdef CONFIG_AP_SUPPORT + ACL_MAC_CTRL *pMACEntry, *pMACEntryTmp; + ACL_OUI_CTRL *pOUIEntry, *pOUITmp; + UCHAR APIndex; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + pACLCtrl = &pAd->ApCfg.MBSSID[APIndex].AccessControlList_V2; + + RTMP_SEM_LOCK(&pACLCtrl->MAC_ListLock); + + DlListForEachSafe(pMACEntry, pMACEntryTmp, &pACLCtrl->MAC_List, ACL_MAC_CTRL, List) + { + DlListDel(&pMACEntry->List); + os_free_mem(NULL, pMACEntry); + } + DlListInit(&pACLCtrl->MAC_List); + RTMP_SEM_UNLOCK(&pACLCtrl->MAC_ListLock); + + RTMP_SEM_LOCK(&pACLCtrl->OUI_ListLock); + DlListForEachSafe(pOUIEntry, pOUITmp, &pACLCtrl->OUI_List, ACL_OUI_CTRL, List) + { + DlListDel(&pOUIEntry->List); + os_free_mem(NULL, pOUIEntry); + } + DlListInit(&pACLCtrl->OUI_List); + RTMP_SEM_UNLOCK(&pACLCtrl->OUI_ListLock); + + if(pACLCtrl->AgeOutTimer_Running == TRUE) + { + RTMPCancelTimer(&pACLCtrl->AgeOutTimer, &Cancelled); + pACLCtrl->AgeOutTimer_Running = FALSE; + } + RTMPReleaseTimer(&pACLCtrl->AgeOutTimer, &Cancelled); + + NdisFreeSpinLock(&pACLCtrl->MAC_ListLock); + NdisFreeSpinLock(&pACLCtrl->OUI_ListLock); + + } +#endif /* CONFIG_AP_SUPPORT */ +} + +INT Set_ACL_V2_DisConnectSta_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + UCHAR macAddr[MAC_ADDR_LEN]; + RTMP_STRING *value; + INT i; + MAC_TABLE_ENTRY *pEntry = NULL; + + if(strlen(arg) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid */ + + AtoH(value, (UCHAR *)&macAddr[i++], 1); + } + + pEntry = MacTableLookup(pAd, macAddr); + + + Set_ACL_V2_AddSTAEntry_Proc(pAd, macAddr); + + if (pEntry) + { + MlmeDeAuthAction(pAd, pEntry, REASON_DISASSOC_STA_LEAVING, FALSE); + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: MAC=%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__,PRINT_MAC(macAddr))); + + return TRUE; +} + + +INT Set_ACL_V2_DisConnectOUI_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + INT i=0; + INT32 Ret; + BOOLEAN Cancelled; + PACL_V2_CTRL pACLCtrl; + ACL_OUI_CTRL *pOUIEntry, *pOUIEntryTmp; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + ULONG Value = (ULONG) simple_strtol(arg, 0, 16); + + pACLCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList_V2; + if(pACLCtrl->AgeOutTimer_Running == TRUE) + { + RTMPCancelTimer(&pACLCtrl->AgeOutTimer, &Cancelled); + pACLCtrl->AgeOutTimer_Running = FALSE; + } + if (Value) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:: OUI=0x%08x\n", __FUNCTION__,Value)); + RTMP_SEM_LOCK(&pACLCtrl->OUI_ListLock); + if(pACLCtrl->OUI_Enable) + { + DlListForEachSafe(pOUIEntry, pOUIEntryTmp, &pACLCtrl->OUI_List, ACL_OUI_CTRL, List) + { + DlListDel(&pOUIEntry->List); + pACLCtrl->OUI_ListNum --; + if(pACLCtrl->OUI_ListNum == 0) + { + pACLCtrl->OUI_Enable = 0; + } + os_free_mem(NULL, pOUIEntry); + } + } + + DlListInit(&pACLCtrl->OUI_List); + RTMP_SEM_UNLOCK(&pACLCtrl->OUI_ListLock); + + for (i=0; i OUI_ListLock); + if(pACLCtrl->OUI_Enable) + { + DlListForEachSafe(pOUIEntry, pOUIEntryTmp, &pACLCtrl->OUI_List, ACL_OUI_CTRL, List) + { + DlListDel(&pOUIEntry->List); + pACLCtrl->OUI_ListNum --; + if(pACLCtrl->OUI_ListNum == 0) + { + pACLCtrl->OUI_Enable = 0; + } + os_free_mem(NULL, pOUIEntry); + } + } + + DlListInit(&pACLCtrl->OUI_List); + RTMP_SEM_UNLOCK(&pACLCtrl->OUI_ListLock); + } + + i=0; + + //dump all OUI list + RTMP_SEM_LOCK(&pACLCtrl->OUI_ListLock); + DlListForEach(pOUIEntry, &pACLCtrl->OUI_List, ACL_OUI_CTRL, List) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:: OUI [%d]=%02x:%02x:%02x\n", __FUNCTION__,i++, pOUIEntry->OUI[0],pOUIEntry->OUI[1],pOUIEntry->OUI[2])); + + } + RTMP_SEM_UNLOCK(&pACLCtrl->OUI_ListLock); + if(pACLCtrl->BlockTime) + { + RTMPSetTimer(&pACLCtrl->AgeOutTimer, pACLCtrl->BlockTime * 1000); + pACLCtrl->AgeOutTimer_Running = TRUE; + } + DBGPRINT(RT_DEBUG_ERROR, ("%s:: OUI count=%d\n", __FUNCTION__,i)); + + return TRUE; +} + +UINT32 Set_ACL_V2_AddSTAEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pTargetMACAddr) +{ + BOOLEAN find_list = FALSE; + PACL_V2_CTRL pACLCtrl; + ACL_MAC_CTRL *pMACEntry; + ULONG Now32; + INT32 Ret; + BOOLEAN Cancelled; + + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + pACLCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList_V2; + + if (pACLCtrl->MAC_ListNum >= (MAX_NUM_OF_ACL_V2_MAC - 1)) + { + DBGPRINT(RT_DEBUG_WARN, ("%s : AccessControlList is full, and no more entry can join the list!\n",__FUNCTION__)); + return FALSE; + } + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + if(pACLCtrl->AgeOutTimer_Running == TRUE) + { + RTMPCancelTimer(&pACLCtrl->AgeOutTimer, &Cancelled); + pACLCtrl->AgeOutTimer_Running = FALSE; + } + RTMP_SEM_LOCK(&pACLCtrl->MAC_ListLock); + DlListForEach(pMACEntry, &pACLCtrl->MAC_List, ACL_MAC_CTRL, List) + { + if (MAC_ADDR_EQUAL(pMACEntry->MACAddr, pTargetMACAddr)) + { + find_list = TRUE; + DBGPRINT(RT_DEBUG_ERROR, ("%s : duplicate mac =%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__,PRINT_MAC(pTargetMACAddr))); + break; + } + } + RTMP_SEM_UNLOCK(&pACLCtrl->MAC_ListLock); + + if (find_list == FALSE) + os_alloc_mem(NULL, (UCHAR **)&pMACEntry, sizeof(*pMACEntry)); + + if (!pMACEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return FALSE; + } + + if (find_list == FALSE) + { + RTMP_SEM_LOCK(&pACLCtrl->MAC_ListLock); + + NdisMoveMemory(pMACEntry->MACAddr, pTargetMACAddr, 6); + NdisGetSystemUpTime(&Now32); + pMACEntry->SetTime = Now32; + + DlListAddTail(&pACLCtrl->MAC_List, &pMACEntry->List); + + pACLCtrl->MAC_ListNum ++; + + if(pACLCtrl->MAC_ListNum) + { + pACLCtrl->MAC_Enable = 1; + } + + RTMP_SEM_UNLOCK(&pACLCtrl->MAC_ListLock); + } + else + { + NdisGetSystemUpTime(&Now32); + pMACEntry->SetTime = Now32; + } + if(pACLCtrl->BlockTime) + { + RTMPSetTimer(&pACLCtrl->AgeOutTimer, pACLCtrl->BlockTime * 1000); + pACLCtrl->AgeOutTimer_Running = TRUE; + } + + return TRUE; +} + + +INT Show_ACL_V2_OUI_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + INT i=0; + INT32 Ret; + PACL_V2_CTRL pACLCtrl; + ACL_OUI_CTRL *pOUIEntry; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + pACLCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList_V2; + + //dump all OUI list + RTMP_SEM_LOCK(&pACLCtrl->OUI_ListLock); + DlListForEach(pOUIEntry, &pACLCtrl->OUI_List, ACL_OUI_CTRL, List) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:: OUI [%d]=%02x:%02x:%02x\n", __FUNCTION__,i++, pOUIEntry->OUI[0],pOUIEntry->OUI[1],pOUIEntry->OUI[2])); + } + RTMP_SEM_UNLOCK(&pACLCtrl->OUI_ListLock); + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: OUI count=%d\n", __FUNCTION__,i)); + + return TRUE; +} + + +INT Show_ACL_V2_STAEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + INT i=0; + INT32 Ret; + PACL_V2_CTRL pACLCtrl; + ACL_MAC_CTRL *pMACEntry; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + pACLCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList_V2; + + //dump all OUI list + RTMP_SEM_LOCK(&pACLCtrl->MAC_ListLock); + DlListForEach(pMACEntry, &pACLCtrl->MAC_List, ACL_MAC_CTRL, List) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:: MAC [%d]=%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__,i++, PRINT_MAC(pMACEntry->MACAddr))); + } + RTMP_SEM_UNLOCK(&pACLCtrl->MAC_ListLock); + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: MAC count=%d\n", __FUNCTION__,i)); + + return TRUE; +} + +VOID Set_ACL_V2_DelSTAEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pTargetMACAddr) +{ + PACL_V2_CTRL pACLCtrl; + ACL_MAC_CTRL *pMACEntry, *pMACEntryTmp; + + INT32 Ret; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + pACLCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList_V2; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + RTMP_SEM_LOCK(&pACLCtrl->MAC_ListLock); + + DlListForEachSafe(pMACEntry, pMACEntryTmp, &pACLCtrl->MAC_List, ACL_MAC_CTRL, List) + { + if (!pMACEntry) + break; + + if (MAC_ADDR_EQUAL(pMACEntry->MACAddr, pTargetMACAddr)) + { + DlListDel(&pMACEntry->List); + + pACLCtrl->MAC_ListNum --; + + if(pACLCtrl->MAC_ListNum == 0) + { + pACLCtrl->MAC_Enable = 0; + } + + os_free_mem(NULL, pMACEntry); + break; + } + } + RTMP_SEM_UNLOCK(&pACLCtrl->MAC_ListLock); +} + + +UINT32 Set_ACL_V2_AddOUIEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pTargetOUIAddr) +{ + BOOLEAN find_list = FALSE; + PACL_V2_CTRL pACLCtrl; + ACL_OUI_CTRL *pOUIEntry; + ULONG Now32; + INT32 Ret; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + pACLCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList_V2; + + if (pACLCtrl->OUI_ListNum >= (MAX_NUM_OF_ACL_V2_OUI - 1)) + { + DBGPRINT(RT_DEBUG_WARN, ("%s : AccessControlList is full, and no more entry can join the list!\n",__FUNCTION__)); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + RTMP_SEM_LOCK(&pACLCtrl->OUI_ListLock); + DlListForEach(pOUIEntry, &pACLCtrl->OUI_List, ACL_OUI_CTRL, List) + { + if (RTMPEqualMemory(pOUIEntry->OUI, pTargetOUIAddr, OUI_LEN)) + { + find_list = TRUE; + break; + } + } + RTMP_SEM_UNLOCK(&pACLCtrl->OUI_ListLock); + + if (find_list == FALSE) + os_alloc_mem(NULL, (UCHAR **)&pOUIEntry, sizeof(*pOUIEntry)); + + if (!pOUIEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return FALSE; + } + + + if (find_list == FALSE) + { + RTMP_SEM_LOCK(&pACLCtrl->OUI_ListLock); + + NdisMoveMemory(pOUIEntry->OUI, pTargetOUIAddr, OUI_LEN); + NdisGetSystemUpTime(&Now32); + pOUIEntry->SetTime = Now32; + + DlListAddTail(&pACLCtrl->OUI_List, &pOUIEntry->List); + + pACLCtrl->OUI_ListNum ++; + if (pACLCtrl->OUI_ListNum) + { + pACLCtrl->OUI_Enable = 1; + } + RTMP_SEM_UNLOCK(&pACLCtrl->OUI_ListLock); + } + else + { // only update timestamp + NdisGetSystemUpTime(&Now32); + pOUIEntry->SetTime = Now32; + } + + return TRUE; +} + +VOID Set_ACL_V2_DelOUIEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pTargetOUIAddr) +{ + PACL_V2_CTRL pACLCtrl; + ACL_OUI_CTRL *pOUIEntry, *pOUIEntryTmp; + + INT32 Ret; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + pACLCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList_V2; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + RTMP_SEM_LOCK(&pACLCtrl->OUI_ListLock); + + DlListForEachSafe(pOUIEntry, pOUIEntryTmp, &pACLCtrl->OUI_List, ACL_OUI_CTRL, List) + { + if (!pOUIEntry) + break; + + if (RTMPEqualMemory(pOUIEntry->OUI, pTargetOUIAddr, OUI_LEN)) + { + DlListDel(&pOUIEntry->List); + + pACLCtrl->OUI_ListNum --; + if(pACLCtrl->OUI_ListNum == 0) + { + pACLCtrl->OUI_Enable = 0; + } + os_free_mem(NULL, pOUIEntry); + break; + } + } + RTMP_SEM_UNLOCK(&pACLCtrl->OUI_ListLock); +} + +VOID Set_ACL_V2_EntryExpire_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + PACL_V2_CTRL pACLCtrl; + ULONG Value; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + pACLCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList_V2; + + Value = (ULONG) simple_strtol(arg, 0, 10); + pACLCtrl->BlockTime = Value; + + DBGPRINT(RT_DEBUG_ERROR, ("%s : pACLCtrl->BlockTime=%lu\n", __FUNCTION__,pACLCtrl->BlockTime)); + +} + + +VOID Show_ACL_V2_EntryExpire_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + PACL_V2_CTRL pACLCtrl; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + pACLCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList_V2; + + DBGPRINT(RT_DEBUG_ERROR, ("%s : pACLCtrl->BlockTime=%lu\n", __FUNCTION__,pACLCtrl->BlockTime)); + +} + +BOOLEAN ACL_V2_List_Check( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + IN UCHAR Apidx) +{ + BOOLEAN Result = TRUE; + PACL_V2_CTRL pACLCtrl; + ACL_MAC_CTRL *pMACEntry; + ACL_OUI_CTRL *pOUIEntry; + + INT32 Ret; + + pACLCtrl = &pAd->ApCfg.MBSSID[Apidx].AccessControlList_V2; + + +check_oui: + RTMP_SEM_LOCK(&pACLCtrl->OUI_ListLock); + DlListForEach(pOUIEntry, &pACLCtrl->OUI_List, ACL_OUI_CTRL, List) + { + if (RTMPEqualMemory(pOUIEntry->OUI, pAddr, OUI_LEN)) + { + Result = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s : hit OUI =%02x:%02x:%02x\n", __FUNCTION__,pOUIEntry->OUI[0],pOUIEntry->OUI[1],pOUIEntry->OUI[2])); + break; + } + } + RTMP_SEM_UNLOCK(&pACLCtrl->OUI_ListLock); + + +if (Result == FALSE) + goto done; + + +check_mac: + RTMP_SEM_LOCK(&pACLCtrl->MAC_ListLock); + DlListForEach(pMACEntry, &pACLCtrl->MAC_List, ACL_MAC_CTRL, List) + { + if (MAC_ADDR_EQUAL(pMACEntry->MACAddr, pAddr)) + { + Result = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s : hit mac =%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__,PRINT_MAC(pAddr))); + break; + } + } + RTMP_SEM_UNLOCK(&pACLCtrl->MAC_ListLock); + +done: + return Result; +} + + +VOID ACL_V2_AgeOut( +IN PACL_V2_CTRL pACLCtrl) +{ + ACL_MAC_CTRL *pMACEntry, *pMACEntryTmp; + ACL_OUI_CTRL *pOUIEntry, *pOUIEntryTmp; + + INT32 Ret; + UINT32 Now32; + INT i = 0; + +#ifdef CONFIG_AP_SUPPORT + UCHAR Apidx; + + NdisGetSystemUpTime(&Now32); + { + RTMP_SEM_LOCK(&pACLCtrl->OUI_ListLock); + if(pACLCtrl->OUI_Enable) + { + DlListForEachSafe(pOUIEntry, pOUIEntryTmp, &pACLCtrl->OUI_List, ACL_OUI_CTRL, List) + { + if(RTMP_TIME_AFTER(Now32, pOUIEntry->SetTime + (pACLCtrl->BlockTime * OS_HZ))) + { + DlListDel(&pOUIEntry->List); + + DBGPRINT(RT_DEBUG_ERROR, ("%s : age OUI[%d] =%02x:%02x:%02x\n", __FUNCTION__, i, pOUIEntry->OUI[0], pOUIEntry->OUI[1], pOUIEntry->OUI[2])); + i++; + pACLCtrl->OUI_ListNum --; + if(pACLCtrl->OUI_ListNum == 0) + { + pACLCtrl->OUI_Enable = 0; + } + os_free_mem(NULL, pOUIEntry); + } + } + + DlListInit(&pACLCtrl->OUI_List); + + } + RTMP_SEM_UNLOCK(&pACLCtrl->OUI_ListLock); + + + i=0; + + RTMP_SEM_LOCK(&pACLCtrl->MAC_ListLock); + + if(pACLCtrl->MAC_Enable) + { + DlListForEachSafe(pMACEntry, pMACEntryTmp, &pACLCtrl->MAC_List, ACL_MAC_CTRL, List) + { + if(RTMP_TIME_AFTER(Now32, pMACEntry->SetTime + (pACLCtrl->BlockTime * OS_HZ))) + { + DlListDel(&pMACEntry->List); + + DBGPRINT(RT_DEBUG_ERROR, ("%s : age MAC[%d] =%02x:%02x:%02x,%02x:%02x:%02x\n", __FUNCTION__, i, PRINT_MAC(pMACEntry->MACAddr))); + i++; + + pACLCtrl->MAC_ListNum --; + if(pACLCtrl->MAC_ListNum == 0) + { + pACLCtrl->MAC_Enable = 0; + } + os_free_mem(NULL, pMACEntry); + } + } + + DlListInit(&pACLCtrl->MAC_List); + } + RTMP_SEM_UNLOCK(&pACLCtrl->MAC_ListLock); + + } +#endif + +} + +void ACL_V2_Timeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PACL_V2_CTRL pACLCtrl = (ACL_V2_CTRL *)FunctionContext; + PRTMP_ADAPTER pAd = pACLCtrl->pAd; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s: fRTMP_ADAPTER_HALT_IN_PROGRESS\n", __FUNCTION__)); + return; + } + + ACL_V2_AgeOut(pACLCtrl); + +} + +#endif /* ACL_V2_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_apcli.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_apcli.c new file mode 100644 index 000000000..10336b6b5 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_apcli.c @@ -0,0 +1,4961 @@ +/* + *************************************************************************** + * 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 + + 4. ApCli index (0) of different tx packet is assigned in + + 5. ApCli index (0) of different interface is got in APHardTransmit() by using + + 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" +#ifdef ROAMING_ENHANCE_SUPPORT +#include +#endif /* ROAMING_ENHANCE_SUPPORT */ + +static VOID set_mlme_rsn_ie(PRTMP_ADAPTER pAd, struct wifi_dev *wdev, PMAC_TABLE_ENTRY pEntry) +{ + UINT32 Idx; + + /* Set New WPA information */ + Idx = BssTableSearch(&pAd->ScanTab, pEntry->Addr, wdev->channel); + if (Idx == BSS_NOT_FOUND) { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Can't find BSS after receiving Assoc response\n")); + } else { + /* Init variable */ + pEntry->RSNIE_Len = 0; + NdisZeroMemory(pEntry->RSN_IE, MAX_LEN_OF_RSNIE); + + /* Store appropriate RSN_IE for WPA SM negotiation later */ + if ((wdev->AuthMode >= Ndis802_11AuthModeWPA) + && (Idx < MAX_LEN_OF_BSS_TABLE) + && (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; + + while (len > 0) { + pEid = (PEID_STRUCT) pVIE; + /* For WPA/WPAPSK */ + if ((pEid->Eid == IE_WPA) + && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) + && ((Ndis802_11AuthModeWPA == wdev->AuthMode) + || (Ndis802_11AuthModeWPAPSK == wdev->AuthMode))) { + NdisMoveMemory(pEntry->RSN_IE, pVIE, (pEid->Len + 2)); + pEntry->RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE,("%s():=> Store RSN_IE for WPA SM negotiation\n", __FUNCTION__)); + } + /* For WPA2/WPA2PSK */ + else if ((pEid->Eid == IE_RSN) + && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) + && ((Ndis802_11AuthModeWPA2 == wdev->AuthMode) + || (Ndis802_11AuthModeWPA2PSK == wdev->AuthMode) +#ifdef APCLI_SAE_SUPPORT + || (Ndis802_11AuthModeWPA3PSK == wdev->AuthMode) +#endif +#ifdef APCLI_OWE_SUPPORT + || (Ndis802_11AuthModeOWE == wdev->AuthMode) +#endif + )) { + NdisMoveMemory(pEntry->RSN_IE, pVIE, (pEid->Len + 2)); + pEntry->RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE,("%s():=> Store RSN_IE for WPA2 SM negotiation\n", __FUNCTION__)); + } + +#ifdef WAPI_SUPPORT + /* For WAPI */ + else if ((pEid->Eid == IE_WAPI) + && (NdisEqualMemory(pEid->Octet + 4, WAPI_OUI, 3)) + && ((Ndis802_11AuthModeWAICERT == wdev->AuthMode) + || (Ndis802_11AuthModeWAIPSK == wdev->AuthMode))) { + NdisMoveMemory(pEntry->RSN_IE, pVIE, (pEid->Len + 2)); + pEntry->RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE,("%s():=> Store RSN_IE for WAPI SM negotiation\n", __FUNCTION__)); + } +#endif /* WAPI_SUPPORT */ + + pVIE += (pEid->Len + 2); + len -= (pEid->Len + 2); + } + + } + + if (pEntry->RSNIE_Len == 0) { + DBGPRINT(RT_DEBUG_TRACE, ("%s():=> no RSN_IE\n", __FUNCTION__)); + } else { + hex_dump("RSN_IE", pEntry->RSN_IE, pEntry->RSNIE_Len); + } + } + +} + + + +BOOLEAN ApCliWaitProbRsp(PRTMP_ADAPTER pAd, USHORT ifIndex) +{ + if (ifIndex >= MAX_APCLI_NUM) + return FALSE; + + printk("%s()[%d]: %lu\n", __FUNCTION__, ifIndex, pAd->ApCfg.ApCliTab[ifIndex].SyncCurrState); + return (pAd->ApCfg.ApCliTab[ifIndex].SyncCurrState == APCLI_JOIN_WAIT_PROBE_RSP) ? + TRUE : FALSE; +} + +VOID ApCliSimulateRecvBeacon(RTMP_ADAPTER *pAd) +{ + INT loop; + ULONG Now32, BPtoJiffies; + PAPCLI_STRUCT pApCliEntry = NULL; + LONG timeDiff; + + NdisGetSystemUpTime(&Now32); + for (loop = 0; loop < MAX_APCLI_NUM; loop++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[loop]; + if ((pApCliEntry->Valid == TRUE) && (pApCliEntry->MacTabWCID < MAX_LEN_OF_MAC_TABLE)) + { + /* + When we are connected and do the scan progress, it's very possible we cannot receive + the beacon of the AP. So, here we simulate that we received the beacon. + */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS) && + (RTMP_TIME_AFTER(pAd->Mlme.Now32, pApCliEntry->ApCliRcvBeaconTime + (1 * OS_HZ)))) + { + BPtoJiffies = (((pApCliEntry->ApCliBeaconPeriod * 1024 / 1000) * OS_HZ) / 1000); + timeDiff = (pAd->Mlme.Now32 - pApCliEntry->ApCliRcvBeaconTime) / BPtoJiffies; + if (timeDiff > 0) + pApCliEntry->ApCliRcvBeaconTime += (timeDiff * BPtoJiffies); + + if (RTMP_TIME_AFTER(pApCliEntry->ApCliRcvBeaconTime, pAd->Mlme.Now32)) + { + DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - APCli BeaconRxTime adjust wrong(BeaconRx=0x%lx, Now=0x%lx)\n", + pApCliEntry->ApCliRcvBeaconTime, pAd->Mlme.Now32)); + } + } + + /* update channel quality for Roaming and UI LinkQuality display */ + MlmeCalculateChannelQuality(pAd, &pAd->MacTab.Content[pApCliEntry->MacTabWCID], Now32); + } + } +} + +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); + + +/* +======================================================================== +Routine Description: + Close ApCli network interface. + +Arguments: + ad_p points to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT28xx_ApCli_Close(RTMP_ADAPTER *ad_p) +{ + UINT index; + + + for(index = 0; index < MAX_APCLI_NUM; index++) + { + if (ad_p->ApCfg.ApCliTab[index].wdev.if_dev) + RtmpOSNetDevClose(ad_p->ApCfg.ApCliTab[index].wdev.if_dev); + } + +} + + +/* --------------------------------- Private -------------------------------- */ +INT ApCliIfLookUp(RTMP_ADAPTER *pAd, UCHAR *pAddr) +{ + SHORT if_idx; + + for(if_idx = 0; if_idx < MAX_APCLI_NUM; if_idx++) + { + if(MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[if_idx].wdev.if_addr, pAddr)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s():ApCliIfIndex=%d\n", + __FUNCTION__, if_idx)); + return if_idx; + } + } + + return -1; +} + + +BOOLEAN isValidApCliIf(SHORT if_idx) +{ + return (((if_idx >= 0) && (if_idx < MAX_APCLI_NUM)) ? TRUE : FALSE); +} + + +/*! \brief init the management mac frame header + * \param p_hdr mac header + * \param subtype subtype of the frame + * \param p_ds destination address, don't care if it is a broadcast address + * \return none + * \pre the station has the following information in the pAd->UserCfg + * - bssid + * - station address + * \post + * \note this function initializes the following field + */ +VOID ApCliMgtMacHeaderInit( + IN RTMP_ADAPTER *pAd, + INOUT HEADER_802_11 *pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN UCHAR *pDA, + IN UCHAR *pBssid, + IN USHORT ifIndex) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + pHdr80211->FC.Type = FC_TYPE_MGMT; + pHdr80211->FC.SubType = SubType; + pHdr80211->FC.ToDs = ToDs; + COPY_MAC_ADDR(pHdr80211->Addr1, pDA); + COPY_MAC_ADDR(pHdr80211->Addr2, pAd->ApCfg.ApCliTab[ifIndex].wdev.if_addr); + COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); +} + + +#ifdef DOT11_N_SUPPORT +/* + ======================================================================== + + Routine Description: + Verify the support rate for HT phy type + + Arguments: + pAd Pointer to our adapter + + Return Value: + FALSE if pAd->CommonCfg.SupportedHtPhy doesn't accept the pHtCapability. (AP Mode) + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +BOOLEAN ApCliCheckHt( + IN RTMP_ADAPTER *pAd, + IN USHORT IfIndex, + INOUT HT_CAPABILITY_IE *pHtCapability, + INOUT ADD_HT_INFO_IE *pAddHtInfo) +{ + APCLI_STRUCT *pApCliEntry = NULL; + HT_CAPABILITY_IE *aux_ht_cap; + RT_HT_CAPABILITY *rt_ht_cap = &pAd->CommonCfg.DesiredHtPhy; + + + if (IfIndex >= MAX_APCLI_NUM) + return FALSE; + + pApCliEntry = &pAd->ApCfg.ApCliTab[IfIndex]; + + aux_ht_cap = &pApCliEntry->MlmeAux.HtCapability; + aux_ht_cap->MCSSet[0] = 0xff; + aux_ht_cap->MCSSet[4] = 0x1; + switch (pAd->CommonCfg.RxStream) + { + case 1: + aux_ht_cap->MCSSet[0] = 0xff; + aux_ht_cap->MCSSet[1] = 0x00; + aux_ht_cap->MCSSet[2] = 0x00; + aux_ht_cap->MCSSet[3] = 0x00; + break; + case 2: + aux_ht_cap->MCSSet[0] = 0xff; + aux_ht_cap->MCSSet[1] = 0xff; + aux_ht_cap->MCSSet[2] = 0x00; + aux_ht_cap->MCSSet[3] = 0x00; + break; + case 3: + aux_ht_cap->MCSSet[0] = 0xff; + aux_ht_cap->MCSSet[1] = 0xff; + aux_ht_cap->MCSSet[2] = 0xff; + aux_ht_cap->MCSSet[3] = 0x00; + break; + } + + /* Record the RxMcs of AP */ + NdisMoveMemory(pApCliEntry->RxMcsSet, pHtCapability->MCSSet, 16); + + /* choose smaller setting */ + aux_ht_cap->HtCapInfo.ChannelWidth = pAddHtInfo->AddHtInfo.RecomWidth & rt_ht_cap->ChannelWidth; + aux_ht_cap->HtCapInfo.GF = pHtCapability->HtCapInfo.GF & rt_ht_cap->GF; + + + + /* Send Assoc Req with my HT capability. */ + aux_ht_cap->HtCapInfo.AMsduSize = rt_ht_cap->AmsduSize; + aux_ht_cap->HtCapInfo.MimoPs = pHtCapability->HtCapInfo.MimoPs; + aux_ht_cap->HtCapInfo.ShortGIfor20 = (rt_ht_cap->ShortGIfor20) & (pHtCapability->HtCapInfo.ShortGIfor20); + aux_ht_cap->HtCapInfo.ShortGIfor40 = (rt_ht_cap->ShortGIfor40) & (pHtCapability->HtCapInfo.ShortGIfor40); + aux_ht_cap->HtCapInfo.TxSTBC = (rt_ht_cap->TxSTBC)&(pHtCapability->HtCapInfo.RxSTBC); + aux_ht_cap->HtCapInfo.RxSTBC = (rt_ht_cap->RxSTBC)&(pHtCapability->HtCapInfo.TxSTBC); + + /* Fix throughput issue for some vendor AP with AES mode */ + if (pAddHtInfo->AddHtInfo.RecomWidth & rt_ht_cap->ChannelWidth) + aux_ht_cap->HtCapInfo.CCKmodein40 = pHtCapability->HtCapInfo.CCKmodein40; + else + aux_ht_cap->HtCapInfo.CCKmodein40 = 0; + + aux_ht_cap->HtCapParm.MaxRAmpduFactor = rt_ht_cap->MaxRAmpduFactor; + aux_ht_cap->HtCapParm.MpduDensity = pHtCapability->HtCapParm.MpduDensity; + aux_ht_cap->ExtHtCapInfo.PlusHTC = pHtCapability->ExtHtCapInfo.PlusHTC; + if (pAd->CommonCfg.bRdg) + { + aux_ht_cap->ExtHtCapInfo.RDGSupport = pHtCapability->ExtHtCapInfo.RDGSupport; + } + + /*COPY_AP_HTSETTINGS_FROM_BEACON(pAd, pHtCapability); */ + return TRUE; +} +#endif /* DOT11_N_SUPPORT */ + +#ifdef WH_EZ_SETUP +#ifdef IF_UP_DOWN + +static VOID ApCliCompleteInit(APCLI_STRUCT *pApCliEntry) +{ + RTMP_OS_INIT_COMPLETION(&pApCliEntry->ifdown_complete); + RTMP_OS_INIT_COMPLETION(&pApCliEntry->linkdown_complete); +} + +static VOID ApCliLinkDownComplete(APCLI_STRUCT *pApCliEntry) +{ + RTMP_OS_COMPLETE(&pApCliEntry->linkdown_complete); +} + +static VOID ApCliWaitLinkDown(APCLI_STRUCT *pApCliEntry) +{ + if (pApCliEntry->Valid && + !RTMP_OS_WAIT_FOR_COMPLETION_TIMEOUT(&pApCliEntry->linkdown_complete, APCLI_WAIT_TIMEOUT)) { + DBGPRINT(RT_DEBUG_ERROR, + ("(%s) ApCli [%d] can't done.\n", __func__, pApCliEntry->wdev.func_idx)); + } +} + +static VOID ApCliWaitIfDown(APCLI_STRUCT *pApCliEntry) +{ + if (pApCliEntry->Valid && + !RTMP_OS_WAIT_FOR_COMPLETION_TIMEOUT(&pApCliEntry->ifdown_complete, APCLI_WAIT_TIMEOUT)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: wait ApCli [%d] interface down failed!!\n", __func__, pApCliEntry->wdev.func_idx)); + } +} + +static VOID ApCliWaitStateDisconnect(APCLI_STRUCT *pApCliEntry) +{ + /* + * Before doing WifiSysClose,we have to make sure the ctrl + * state machine has switched to APCLI_CTRL_DISCONNECTED + */ + int wait_cnt = 0; + int wait_times = 50; + int delay_time = 100; + + while(pApCliEntry->CtrlCurrState != APCLI_CTRL_DISCONNECTED) { + if (wait_cnt >= wait_times) { + DBGPRINT(RT_DEBUG_ERROR, + ("Need to debug apcli ctrl state machine(Ctrl State=%lu)\n\r", + pApCliEntry->CtrlCurrState)); + break; + } + RtmpOsMsDelay(delay_time); + wait_cnt++; + } +} + +static VOID ApCliIfDownComplete(APCLI_STRUCT *pApCliEntry) +{ + RTMP_OS_COMPLETE(&pApCliEntry->ifdown_complete); +} +#endif +#endif + +/* + ========================================================================== + + Routine Description: + Connected to the BSSID + + Arguments: + pAd - Pointer to our adapter + ApCliIdx - Which ApCli interface + Return Value: + FALSE: fail to alloc Mac entry. + + Note: + + ========================================================================== +*/ +BOOLEAN ApCliLinkUp(RTMP_ADAPTER *pAd, UCHAR ifIndex) +{ + BOOLEAN result = FALSE; + PAPCLI_STRUCT pApCliEntry = NULL; + PMAC_TABLE_ENTRY pMacEntry = NULL; + STA_TR_ENTRY *tr_entry; + struct wifi_dev *wdev; +#if defined(MAC_REPEATER_SUPPORT) || defined(MT_MAC) + UCHAR CliIdx = 0xFF; +#ifdef MAC_REPEATER_SUPPORT + INVAILD_TRIGGER_MAC_ENTRY *pSkipEntry = NULL; +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* defined(MAC_REPEATER_SUPPORT) || defined(MT_MAC) */ + + 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) + { +#ifdef LINUX + struct net_device *pNetDev; + struct net *net= &init_net; + +/* old kernerl older than 2.6.21 didn't have for_each_netdev()*/ +#ifndef for_each_netdev + for(pNetDev=dev_base; pNetDev!=NULL; pNetDev=pNetDev->next) +#else + for_each_netdev(net, pNetDev) +#endif + { + if (pNetDev->priv_flags == IFF_EBRIDGE) + { + COPY_MAC_ADDR(pAd->ApCfg.BridgeAddress, pNetDev->dev_addr); + DBGPRINT(RT_DEBUG_ERROR, (" Bridge Addr = %02X:%02X:%02X:%02X:%02X:%02X. !!!\n", + PRINT_MAC(pAd->ApCfg.BridgeAddress))); + + } + pSkipEntry = RepeaterInvaildMacLookup(pAd, pNetDev->dev_addr); + + if (pSkipEntry == NULL) + RTMPRepeaterInsertInvaildMacEntry(pAd, pNetDev->dev_addr); + } +#endif + } + + 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 */ + + 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].wdev.AuthMode, +GetAuthMode(pAd->ApCfg.ApCliTab[ifIndex].wdev.AuthMode), +pAd->ApCfg.ApCliTab[ifIndex].wdev.WepStatus, +GetEncryptType(pAd->ApCfg.ApCliTab[ifIndex].wdev.WepStatus))); + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("!!! ERROR : APCLI LINK UP - IF(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 */ + + if (ifIndex >= MAX_APCLI_NUM) { + result = FALSE; + break; + } + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + if ((pApCliEntry != NULL) && (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; + } + + wdev = &pApCliEntry->wdev; + DBGPRINT(RT_DEBUG_TRACE, ("!!! APCLI LINK UP - IF(apcli%d) AuthMode(%d)=%s, WepStatus(%d)=%s!\n", + ifIndex, + wdev->AuthMode, GetAuthMode(wdev->AuthMode), + wdev->WepStatus, GetEncryptType(wdev->WepStatus))); + +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + { + if (wf_fwd_get_rep_hook) + wf_fwd_get_rep_hook(pAd->CommonCfg.EtherTrafficBand); + +#if (MT7615_MT7603_COMBO_FORWARDING == 1) + if (wf_fwd_check_device_hook) + wf_fwd_check_device_hook(wdev->if_dev, INT_APCLI, CliIdx, pAd->CommonCfg.Channel, 1); +#endif + if (wf_fwd_entry_insert_hook) + wf_fwd_entry_insert_hook (wdev->if_dev, pAd->net_dev, pAd); + + if (wf_fwd_insert_repeater_mapping_hook) +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +#ifdef MAC_REPEATER_SUPPORT + wf_fwd_insert_repeater_mapping_hook (pAd, &pAd->ApCfg.ReptCliEntryLock, &pAd->ApCfg.ReptCliHash[0], &pAd->ApCfg.ReptMapHash[0], &pAd->ApCfg.ApCliTab[ifIndex].wdev.if_addr); +#else + wf_fwd_insert_repeater_mapping_hook (pAd, NULL, NULL, NULL, &pAd->ApCfg.ApCliTab[ifIndex].wdev.if_addr); +#endif /* MAC_REPEATER_SUPPORT */ +#else + wf_fwd_insert_repeater_mapping_hook (pAd, &pAd->ApCfg.ReptCliEntryLock, &pAd->ApCfg.ReptCliHash[0], &pAd->ApCfg.ReptMapHash[0], &pAd->ApCfg.ApCliTab[0].wdev.if_addr); +#endif + } +#endif /* CONFIG_WIFI_PKT_FWD */ + + /* Insert the Remote AP to our MacTable. */ + /*pMacEntry = MacTableInsertApCliEntry(pAd, (PUCHAR)(pAd->ApCfg.ApCliTab[0].MlmeAux.Bssid)); */ +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn && (pAd->chipCap.hif_type == HIF_RLT || pAd->chipCap.hif_type == HIF_RTMP)) + pMacEntry = RTMPInsertRepeaterMacEntry( + pAd, + (PUCHAR)(pApCliEntry->MlmeAux.Bssid), + wdev, + (ifIndex + MIN_NET_DEVICE_FOR_APCLI), + CliIdx, + TRUE); + else +#endif /* MAC_REPEATER_SUPPORT */ + pMacEntry = MacTableInsertEntry(pAd, (PUCHAR)(pApCliEntry->MlmeAux.Bssid), + wdev, ENTRY_APCLI, + OPMODE_AP, TRUE); + +#ifdef MT_MAC +{ + if (CliIdx == 0xff && pAd->chipCap.hif_type == HIF_MT) + { + #ifdef MULTI_APCLI_SUPPORT + AsicUpdateRxWCIDTable(pAd, APCLI_MCAST_WCID(ifIndex), (PUCHAR)(pApCliEntry->MlmeAux.Bssid)); + #else /* MULTI_APCLI_SUPPORT */ + AsicUpdateRxWCIDTable(pAd, APCLI_MCAST_WCID, (PUCHAR)(pApCliEntry->MlmeAux.Bssid)); + #endif /*! MULTI_APCLI_SUPPORT */ + } +} +#endif /* MT_MAC */ + + if (pMacEntry) + { + UCHAR Rates[MAX_LEN_OF_SUPPORTED_RATES]; + PUCHAR pRates = Rates; + UCHAR RatesLen; + UCHAR MaxSupportedRate = 0; + + tr_entry = &pAd->MacTab.tr_entry[pMacEntry->wcid]; + pMacEntry->Sst = SST_ASSOC; + pMacEntry->wdev = &pApCliEntry->wdev; + +#ifdef MULTI_APCLI_SUPPORT + pMacEntry->wdev ->tr_tb_idx = APCLI_MCAST_WCID(ifIndex); + tr_tb_set_mcast_entry(pAd, APCLI_MCAST_WCID(ifIndex), pMacEntry->wdev); +#endif /* MULTI_APCLI_SUPPORT */ + +#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->wcid; +#ifdef MAC_REPEATER_SUPPORT + pMacEntry->bReptCli = FALSE; +#endif /* MAC_REPEATER_SUPPORT */ + COPY_MAC_ADDR(&wdev->bssid[0], &pApCliEntry->MlmeAux.Bssid[0]); + COPY_MAC_ADDR(APCLI_ROOT_BSSID_GET(pAd, pApCliEntry->MacTabWCID), pApCliEntry->MlmeAux.Bssid); + pApCliEntry->SsidLen = pApCliEntry->MlmeAux.SsidLen; + NdisMoveMemory(pApCliEntry->Ssid, pApCliEntry->MlmeAux.Ssid, pApCliEntry->SsidLen); + } + + set_mlme_rsn_ie(pAd, &pApCliEntry->wdev, pMacEntry); + + +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef DOT11W_PMF_SUPPORT + if ((pApCliEntry->PmfCfg.MFPC) && + (pApCliEntry->MlmeAux.RsnCap.field.MFPC)) + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_PMF_CAPABLE); + + if ((pApCliEntry->PmfCfg.PMFSHA256 && + pApCliEntry->MlmeAux.IsSupportSHA256KeyDerivation) + || (pApCliEntry->PmfCfg.MFPC && + pApCliEntry->MlmeAux.RsnCap.field.MFPR) + || (pApCliEntry->PmfCfg.MFPC && + pApCliEntry->MlmeAux.IsSupportSHA256KeyDerivation)) + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_USE_SHA256); + + if ((pApCliEntry->PmfCfg.MFPR == TRUE) && + (pApCliEntry->MlmeAux.RsnCap.field.MFPC == FALSE)) { + CLIENT_STATUS_CLEAR_FLAG(pMacEntry, fCLIENT_STATUS_PMF_CAPABLE); + CLIENT_STATUS_CLEAR_FLAG(pMacEntry, fCLIENT_STATUS_USE_SHA256); + } + + if (((pApCliEntry->PmfCfg.MFPC == FALSE) && + (pApCliEntry->MlmeAux.RsnCap.field.MFPC == FALSE)) || + ((pApCliEntry->PmfCfg.MFPC == TRUE) && + (pApCliEntry->MlmeAux.RsnCap.field.MFPC == TRUE) && + (pApCliEntry->PmfCfg.MFPR == FALSE) && + (pApCliEntry->MlmeAux.RsnCap.field.MFPR == FALSE))) { + if ((pApCliEntry->PmfCfg.PMFSHA256) && + (pApCliEntry->MlmeAux.IsSupportSHA256KeyDerivation == FALSE)) { + CLIENT_STATUS_CLEAR_FLAG(pMacEntry, fCLIENT_STATUS_PMF_CAPABLE); + CLIENT_STATUS_CLEAR_FLAG(pMacEntry, fCLIENT_STATUS_USE_SHA256); + } + } +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + + if (pMacEntry->AuthMode >= Ndis802_11AuthModeWPA) + tr_entry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + else + { + + tr_entry->PortSecured = WPA_802_1X_PORT_SECURED; +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pApCliEntry->RepeaterCli[CliIdx].CliConnectState = 2; +#endif /* MAC_REPEATER_SUPPORT */ + } + +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if ((pAd->ApCfg.ApCliAutoConnectRunning == TRUE) && +#ifdef MAC_REPEATER_SUPPORT + (CliIdx == 0xFF) && +#endif /* MAC_REPEATER_SUPPORT */ + (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + DBGPRINT(RT_DEBUG_TRACE, ("ApCli auto connected: ApCliLinkUp()\n")); + pAd->ApCfg.ApCliAutoConnectRunning = FALSE; + } +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + NdisGetSystemUpTime(&pApCliEntry->ApCliLinkUpTime); + + /* + Store appropriate RSN_IE for WPA SM negotiation later + If WPAPSK/WPA2SPK mix mode, driver just stores either WPAPSK or + WPA2PSK RSNIE. It depends on the AP-Client's authentication mode + to store the corresponding RSNIE. + */ + if ((pMacEntry->AuthMode >= Ndis802_11AuthModeWPA) && (pApCliEntry->MlmeAux.VarIELen != 0)) + { + PUCHAR pVIE; + UCHAR len; + PEID_STRUCT pEid; + + pVIE = pApCliEntry->MlmeAux.VarIEs; + len = pApCliEntry->MlmeAux.VarIELen; + + while (len > 0) + { + pEid = (PEID_STRUCT) pVIE; + /* For WPA/WPAPSK */ + if ((pEid->Eid == IE_WPA) && (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) + && (pMacEntry->AuthMode == Ndis802_11AuthModeWPA || pMacEntry->AuthMode == Ndis802_11AuthModeWPAPSK)) + { + NdisMoveMemory(pMacEntry->RSN_IE, pVIE, (pEid->Len + 2)); + pMacEntry->RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkUp: Store RSN_IE for WPA SM negotiation \n")); + } + /* For WPA2/WPA2PSK */ + else if ((pEid->Eid == IE_RSN) && (NdisEqualMemory(pEid->Octet + 2, RSN_OUI, 3)) + && (pMacEntry->AuthMode == Ndis802_11AuthModeWPA2 + || pMacEntry->AuthMode == Ndis802_11AuthModeWPA2PSK +#ifdef APCLI_SAE_SUPPORT + || pMacEntry->AuthMode == Ndis802_11AuthModeWPA3PSK +#endif +#ifdef APCLI_OWE_SUPPORT + || pMacEntry->AuthMode == Ndis802_11AuthModeOWE +#endif + )) + { + NdisMoveMemory(pMacEntry->RSN_IE, pVIE, (pEid->Len + 2)); + pMacEntry->RSNIE_Len = (pEid->Len + 2); + DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkUp: Store RSN_IE for WPA2 SM negotiation \n")); + } + + pVIE += (pEid->Len + 2); + len -= (pEid->Len + 2); + } + } + + if (pMacEntry->RSNIE_Len == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkUp: root-AP has no RSN_IE \n")); + } + else + { + hex_dump("The RSN_IE of root-AP", pMacEntry->RSN_IE, pMacEntry->RSNIE_Len); + } + + SupportRate(pApCliEntry->MlmeAux.SupRate, pApCliEntry->MlmeAux.SupRateLen, pApCliEntry->MlmeAux.ExtRate, + pApCliEntry->MlmeAux.ExtRateLen, &pRates, &RatesLen, &MaxSupportedRate); + + pMacEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); + pMacEntry->RateLen = RatesLen; + set_entry_phy_cfg(pAd, pMacEntry); + + pMacEntry->CapabilityInfo = pApCliEntry->MlmeAux.CapabilityInfo; + + pApCliEntry->ApCliBeaconPeriod = pApCliEntry->MlmeAux.BeaconPeriod; + + if ((wdev->WepStatus == Ndis802_11WEPEnabled) + ) + { + CIPHER_KEY *pKey; + INT idx, BssIdx; + + BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + ifIndex; +#ifdef MAC_APCLI_SUPPORT + BssIdx = APCLI_BSS_BASE + ifIndex; +#endif /* MAC_APCLI_SUPPORT */ + for (idx=0; idx < SHARE_KEY_NUM; idx++) + { + pKey = &pApCliEntry->SharedKey[idx]; + if (pKey->KeyLen > 0) + { + /* Set key material and cipherAlg to Asic */ +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + { + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + BssIdx, + idx, + pKey); + } + + if (idx == wdev->DefaultKeyId) + { + INT cnt; + + /* Generate 3-bytes IV randomly for software encryption using */ + for(cnt = 0; cnt < LEN_WEP_TSC; cnt++) + pKey->TxTsc[cnt] = RandomByte(pAd); + + RTMP_SET_WCID_SEC_INFO(pAd, + BssIdx, + idx, + pKey->CipherAlg, + pMacEntry->wcid, + SHAREDKEYTABLE); + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + CmdProcAddRemoveKey(pAd, 0, pMacEntry->func_tb_idx, idx, pMacEntry->wcid, PAIRWISEKEYTABLE, pKey, pMacEntry->Addr); +#ifdef MULTI_APCLI_SUPPORT + CmdProcAddRemoveKey(pAd, 0, pMacEntry->func_tb_idx, idx, APCLI_MCAST_WCID(ifIndex), SHAREDKEYTABLE, pKey, BROADCAST_ADDR); +#else /* MULTI_APCLI_SUPPORT */ + CmdProcAddRemoveKey(pAd, 0, pMacEntry->func_tb_idx, idx, APCLI_MCAST_WCID, SHAREDKEYTABLE, pKey, BROADCAST_ADDR); +#endif /* !MULTI_APCLI_SUPPORT */ + } +#endif /* MT_MAC */ + + } + } + } + } + +#ifdef DOT11_N_SUPPORT + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if (pApCliEntry->MlmeAux.HtCapabilityLen != 0) + { + PHT_CAPABILITY_IE pHtCapability = (PHT_CAPABILITY_IE)&pApCliEntry->MlmeAux.HtCapability; + + ht_mode_adjust(pAd, pMacEntry, pHtCapability, &pAd->CommonCfg.DesiredHtPhy); + + /* find max fixed rate */ + pMacEntry->MaxHTPhyMode.field.MCS = get_ht_max_mcs(pAd, &wdev->DesiredHtPhyInfo.MCSSet[0], + &pHtCapability->MCSSet[0]); + + if (wdev->DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF-apcli%d : Desired MCS = %d\n", + ifIndex, wdev->DesiredTransmitSetting.field.MCS)); + + set_ht_fixed_mcs(pAd, pMacEntry, wdev->DesiredTransmitSetting.field.MCS, wdev->HTPhyMode.field.MCS); + } + + pMacEntry->MaxHTPhyMode.field.STBC = (pHtCapability->HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + 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); + + set_sta_ht_cap(pAd, pMacEntry, pHtCapability); + + NdisMoveMemory(&pMacEntry->HTCapability, &pApCliEntry->MlmeAux.HtCapability, sizeof(HT_CAPABILITY_IE)); + NdisMoveMemory(pMacEntry->HTCapability.MCSSet, pApCliEntry->RxMcsSet, 16); + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + AsicUpdateRxWCIDTable(pAd, pMacEntry->wcid, (PUCHAR)(pApCliEntry->MlmeAux.Bssid)); +#endif + } + else + { + pAd->MacTab.fAnyStationIsLegacy = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("ApCliLinkUp - MaxSupRate=%d Mbps\n", + RateIdToMbps[pMacEntry->MaxSupportedRate])); + } +#endif /* DOT11_N_SUPPORT */ + + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && pApCliEntry->MlmeAux.vht_cap_len && pApCliEntry->MlmeAux.vht_op_len) + vht_mode_adjust(pAd, pMacEntry, &(pApCliEntry->MlmeAux.vht_cap), &(pApCliEntry->MlmeAux.vht_op)); +#endif /* DOT11_VHT_AC */ + + pMacEntry->HTPhyMode.word = pMacEntry->MaxHTPhyMode.word; + pMacEntry->CurrTxRate = pMacEntry->MaxSupportedRate; + + RTMPSetSupportMCS(pAd, + OPMODE_AP, + pMacEntry, + pApCliEntry->MlmeAux.SupRate, + pApCliEntry->MlmeAux.SupRateLen, + pApCliEntry->MlmeAux.ExtRate, + pApCliEntry->MlmeAux.ExtRateLen, +#ifdef DOT11_VHT_AC + pApCliEntry->MlmeAux.vht_cap_len, + &pApCliEntry->MlmeAux.vht_cap, +#endif /* DOT11_VHT_AC */ + &pApCliEntry->MlmeAux.HtCapability, + pApCliEntry->MlmeAux.HtCapabilityLen); + + if (wdev->bAutoTxRateSwitch == FALSE) + { + pMacEntry->bAutoTxRateSwitch = FALSE; + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((UCHAR)wdev->DesiredTransmitSetting.field.FixedTxMode, pMacEntry); + } + else + { + UCHAR TableSize = 0; + + pMacEntry->bAutoTxRateSwitch = TRUE; + + MlmeSelectTxRateTable(pAd, pMacEntry, &pMacEntry->pTable, &TableSize, &pMacEntry->CurrTxRateIndex); + MlmeNewTxRate(pAd, pMacEntry); +#ifdef NEW_RATE_ADAPT_SUPPORT + if (! ADAPT_RATE_TABLE(pMacEntry->pTable)) +#endif /* NEW_RATE_ADAPT_SUPPORT */ + pMacEntry->HTPhyMode.field.ShortGI = GI_800; + } + + /* set this entry WMM capable or not */ + if ((pApCliEntry->MlmeAux.APEdcaParm.bValid) +#ifdef DOT11_N_SUPPORT + || IS_HT_STA(pMacEntry) +#endif /* DOT11_N_SUPPORT */ + ) + { + CLIENT_STATUS_SET_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE); + } + else + { + CLIENT_STATUS_CLEAR_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE); + } + + set_sta_ra_cap(pAd, pMacEntry, pApCliEntry->MlmeAux.APRalinkIe); + +#ifdef PIGGYBACK_SUPPORT + if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE)) + { + RTMPSetPiggyBack(pAd, TRUE); + DBGPRINT(RT_DEBUG_TRACE, ("Turn on Piggy-Back\n")); + } +#endif /* PIGGYBACK_SUPPORT */ + +#ifdef WH_EZ_SETUP + if (CliIdx == 0xff) { + if (IS_EZ_SETUP_ENABLED(wdev)) { + if (pApCliEntry->MlmeAux.support_easy_setup) { + result = ez_port_secured(pAd, pMacEntry, ifIndex, FALSE); + if(result == FALSE){ + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("ApCliLinkUp: connection failed/broken\n")); + break; + } + } + +#ifdef IF_UP_DOWN + wdev->ez_driver_params.ez_apcli_peer_ap_config_cnt = 0; +#endif + } + } +#endif /* WH_EZ_SETUP */ + + +#ifdef MWDS + if((CliIdx == 0xff) && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) + { +#ifdef WH_EZ_SETUP + if (IS_AKM_PSK_Entry(pMacEntry)) + MWDSAPCliPeerEnable(pAd, pApCliEntry, pMacEntry); + else +#endif /* WH_EZ_SETUP */ + { + MWDSAPCliPeerEnable(pAd, pApCliEntry, pMacEntry); +#ifdef WH_EZ_SETUP + //! If security is disabled on this link, + //!ez_hanle_pairmsg4 needs to be called to trigger config push + if (IS_EZ_SETUP_ENABLED(wdev) +#ifdef WSC_AP_SUPPORT + && (!((pApCliEntry->WscControl.WscConfMode != WSC_DISABLE) + && (pApCliEntry->WscControl.bWscTrigger == TRUE))) +#endif /* WSC_AP_SUPPORT */ + ) { + ez_handle_pairmsg4(pAd, pMacEntry); + } +#endif + } + } +#endif /* MWDS */ + + + NdisGetSystemUpTime(&pApCliEntry->ApCliRcvBeaconTime); + /* set the apcli interface be valid. */ +#ifdef MAC_APCLI_SUPPORT +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* MAC_APCLI_SUPPORT */ + { + pApCliEntry->Valid = TRUE; + pApCliEntry->wdev.allow_data_tx = TRUE; + pApCliEntry->wdev.PortSecured = WPA_802_1X_PORT_SECURED; +#ifdef MAC_APCLI_SUPPORT + AsicSetApCliBssid(pAd, pApCliEntry->MlmeAux.Bssid, ifIndex); +#endif /* MAC_APCLI_SUPPORT */ +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + #ifdef MULTI_APCLI_SUPPORT + AsicSetBssid(pAd, pApCliEntry->MlmeAux.Bssid, (0x1 + ifIndex)); + #else /* MULTI_APCLI_SUPPORT */ + AsicSetBssid(pAd, pApCliEntry->MlmeAux.Bssid, 0x1); + #endif /* !MULTI_APCLI_SUPPORT */ + } +#endif + } + +#ifdef MT_MAC + if (CliIdx != 0xff && pAd->chipCap.hif_type == HIF_MT) + { +#ifdef MAC_REPEATER_SUPPORT + insert_repeater_root_entry(pAd, pMacEntry, (PUCHAR)(pApCliEntry->MlmeAux.Bssid), CliIdx); +#endif /* MAC_REPEATER_SUPPORT */ + } +#endif /* MT_MAC */ + + result = TRUE; + pAd->ApCfg.ApCliInfRunned++; + + break; + } + result = FALSE; + } while(FALSE); + + + if (result == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, (" (%s) alloc mac entry fail!!!\n", __FUNCTION__)); + return result; + } + + +#ifdef WSC_AP_SUPPORT + /* WSC initial connect to AP, jump to Wsc start action and set the correct parameters */ + + if ((result == TRUE) && (ifIndex < MAX_APCLI_NUM) && + (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->MlmeAux.Bssid, MAC_ADDR_LEN); + WscSendEapolStart(pAd, pMacEntry->Addr, AP_MODE); + } + else + { + WscStop(pAd, TRUE, &pAd->ApCfg.ApCliTab[ifIndex].WscControl); + } +#endif /* WSC_AP_SUPPORT */ + +/* When root AP is Open WEP, it will cause a fake connection state if user keys in wrong password. */ + if((result == TRUE) && + (wdev->AuthMode == Ndis802_11AuthModeOpen) && + (wdev->WepStatus == Ndis802_11WEPEnabled)) + pApCliEntry->OpenWEPErrPktChk = TRUE; + else + pApCliEntry->OpenWEPErrPktChk = FALSE; + pApCliEntry->OpenWEPErrPktCnt = 0; + pApCliEntry->OpenWEPErrMCPktCnt = 0; + +#ifdef WH_EVENT_NOTIFIER + if ((result == TRUE) && pMacEntry && + tr_entry && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + EventHdlr pEventHdlrHook = NULL; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_EXT_UPLINK_STAT); + if(pEventHdlrHook && pMacEntry->wdev) + pEventHdlrHook(pAd, pMacEntry, (UINT32)WHC_UPLINK_STAT_CONNECTED); + } +#endif /* WH_EVENT_NOTIFIER */ +#if defined(MAP_SUPPORT) && defined(WAPP_SUPPORT) + /*For security NONE & WEP case*/ + if ((CliIdx == 0xFF) && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) { + wapp_send_apcli_association_change(WAPP_APCLI_ASSOCIATED, pAd, pApCliEntry); + DBGPRINT(RT_DEBUG_OFF, ("APCLIENT MAP_ENABLE (No Security)\n")); +#ifdef A4_CONN + map_a4_peer_enable(pAd, pMacEntry, FALSE); +#endif + if (pApCliEntry->WscControl.bWscTrigger == FALSE) + map_send_bh_sta_wps_done_event(pAd, pMacEntry, FALSE); + } +#endif /*WAPP_SUPPORT*/ +#ifdef MTFWD +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + RTMP_OS_NETDEV_CARRIER_ON(wdev->if_dev); +#endif + + return result; +} + + +/* + ========================================================================== + + Routine Description: + Disconnect current BSSID + + Arguments: + pAd - Pointer to our adapter + ApCliIdx - Which ApCli interface + Return Value: + None + + Note: + + ========================================================================== +*/ +VOID ApCliLinkDown(RTMP_ADAPTER *pAd, UCHAR ifIndex) +{ + APCLI_STRUCT *pApCliEntry = NULL; + UCHAR CliIdx = 0xFF; +#if (defined(WH_EVENT_NOTIFIER) && defined(MAC_REPEATER_SUPPORT)) + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; +#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_OFF, ("!!! APCLI LINK DOWN - IF(apcli%d)!!!\n", ifIndex)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("!!! 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 MTFWD +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + RTMP_OS_NETDEV_CARRIER_OFF(pApCliEntry->wdev.if_dev); +#endif + +#if defined (CONFIG_WIFI_PKT_FWD) +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + { + if (wf_fwd_entry_delete_hook) + wf_fwd_entry_delete_hook (pApCliEntry->wdev.if_dev, pAd->net_dev, 1); +#if (MT7615_MT7603_COMBO_FORWARDING == 1) + if (wf_fwd_check_device_hook) + wf_fwd_check_device_hook (pApCliEntry->wdev.if_dev, INT_APCLI, CliIdx, pApCliEntry->wdev.channel, 0); +#endif + } +#ifdef MAC_REPEATER_SUPPORT + else + { + if (packet_source_delete_entry_hook) + packet_source_delete_entry_hook(100); + } +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* CONFIG_WIFI_PKT_FWD */ + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + pAd->ApCfg.ApCliInfRunned--; + +#ifdef WH_EVENT_NOTIFIER + { + MAC_TABLE_ENTRY *pMacEntry = NULL; + EventHdlr pEventHdlrHook = NULL; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + pReptEntry = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx]; + if(VALID_UCAST_ENTRY_WCID(pReptEntry->MacTabWCID)) + pMacEntry = &pAd->MacTab.Content[pReptEntry->MacTabWCID]; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + if(VALID_UCAST_ENTRY_WCID(pApCliEntry->MacTabWCID)) + pMacEntry = &pAd->MacTab.Content[pApCliEntry->MacTabWCID]; + } + + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_EXT_UPLINK_STAT); + if(pEventHdlrHook && pMacEntry->wdev) + pEventHdlrHook(pAd, pMacEntry, (UINT32)WHC_UPLINK_STAT_DISCONNECT); + } +#endif /* WH_EVENT_NOTIFIER */ + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + MacTabWCID = pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].MacTabWCID; + else +#endif /* MAC_REPEATER_SUPPORT */ + { +#ifdef WH_EZ_SETUP + if(IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev)) + ez_apcli_link_down(pAd, pApCliEntry, ifIndex); +#endif /* WH_EZ_SETUP */ + MacTabWCID = pApCliEntry->MacTabWCID; + } + MacTableDeleteEntry(pAd, MacTabWCID, APCLI_ROOT_BSSID_GET(pAd, pApCliEntry->MacTabWCID)); +#ifdef MT_MAC +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx == 0xFF) +#endif +#ifdef MULTI_APCLI_SUPPORT + RTMP_STA_ENTRY_MAC_RESET(pAd, APCLI_MCAST_WCID(ifIndex));//MT_MAC clear mcast entry of rootAP. +#else /* MULTI_APCLI_SUPPORT */ + RTMP_STA_ENTRY_MAC_RESET(pAd, APCLI_MCAST_WCID);//MT_MAC clear mcast entry of rootAP. +#endif /* !MULTI_APCLI_SUPPORT */ +#endif + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid = FALSE; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry->Valid = FALSE; /* This link doesn't associated with any remote-AP */ + pApCliEntry->wdev.allow_data_tx = FALSE; + pApCliEntry->wdev.PortSecured = WPA_802_1X_PORT_NOT_SECURED; +#ifdef WH_EZ_SETUP + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) + BssTableDeleteEntry(&pAd->ScanTab, pApCliEntry->MlmeAux.Bssid, pApCliEntry->wdev.channel); +#endif +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef DOT11W_PMF_SUPPORT + BssTableDeleteEntry(&pAd->ScanTab, pApCliEntry->MlmeAux.Bssid, pAd->CommonCfg.Channel); +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + } + pApCliEntry->OpenWEPErrPktChk = FALSE; + pApCliEntry->OpenWEPErrPktCnt = 0; + pApCliEntry->OpenWEPErrMCPktCnt = 0; +#ifdef MWDS + MWDSAPCliPeerDisable(pAd, pApCliEntry, &pAd->MacTab.Content[MacTabWCID]); +#endif /* MWDS */ + +#if defined(MAP_SUPPORT) && defined(A4_CONN) + map_a4_peer_disable(pAd, &pAd->MacTab.Content[MacTabWCID], FALSE); +#endif + + + + /*for APCLI linkdown*/ +#if defined(MAP_SUPPORT) && defined(WAPP_SUPPORT) + if (CliIdx == 0xFF) + wapp_send_apcli_association_change(WAPP_APCLI_DISASSOCIATED, pAd, pApCliEntry); +#endif + +#ifdef WH_EZ_SETUP +#ifdef IF_UP_DOWN + if (CliIdx == 0xFF) + ApCliLinkDownComplete(pApCliEntry); +#endif +#endif +} + + +/* + ========================================================================== + Description: + APCLI Interface Up. + ========================================================================== + */ +VOID ApCliIfUp(RTMP_ADAPTER *pAd) +{ + UCHAR ifIndex; + APCLI_STRUCT *pApCliEntry; + + /* Reset is in progress, stop immediately */ + if ( RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS)) || + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP))) + return; + + /* sanity check whether the interface is initialized. */ + if (pAd->flg_apcli_init != TRUE) + return; + + for(ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + 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(RTMP_ADAPTER *pAd) +{ + UCHAR ifIndex; + PAPCLI_STRUCT pApCliEntry; + +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx,idx; + INVAILD_TRIGGER_MAC_ENTRY *pEntry = NULL; +#endif /* MAC_REPEATER_SUPPORT */ + + for(ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + +#if defined (CONFIG_WIFI_PKT_FWD) + if (wf_fwd_entry_delete_hook) + wf_fwd_entry_delete_hook(pApCliEntry->wdev.if_dev, pAd->net_dev, 1); +#endif /* CONFIG_WIFI_PKT_FWD */ + DBGPRINT(RT_DEBUG_TRACE, ("%s():ApCli interface[%d] start down.\n", __FUNCTION__, ifIndex)); + + if (pApCliEntry->Enable == TRUE) + continue; + +#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); +#ifdef WH_EZ_SETUP +#ifdef IF_UP_DOWN + ApCliWaitLinkDown(pApCliEntry); +#endif +#endif + } + +#ifdef MAC_REPEATER_SUPPORT + for (idx = 0; idx< 32; idx++) + { + pEntry = &pAd->ApCfg.ReptControl.RepeaterInvaildEntry[idx]; + + RTMPRepeaterRemoveInvaildMacEntry(pAd, idx, pEntry->MacAddr); + } +#endif /* MAC_REPEATER_SUPPORT */ + + return; +} + + +/* + ========================================================================== + Description: + APCLI Interface Monitor. + ========================================================================== + */ +VOID ApCliIfMonitor(RTMP_ADAPTER *pAd) +{ + UCHAR index; + APCLI_STRUCT *pApCliEntry; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx; + PREPEATER_CLIENT_ENTRY pReptCliEntry = NULL; +#endif /* MAC_REPEATER_SUPPORT */ +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + BOOLEAN bWpa_4way_too_log = FALSE; + UCHAR TimeoutVal = 30; + +#endif + + /* 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; + STA_TR_ENTRY *tr_entry; + BOOLEAN bForceBrocken = FALSE; +#ifdef WH_EZ_SETUP + BOOLEAN bBeacon_miss = FALSE; +#endif + pApCliEntry = &pAd->ApCfg.ApCliTab[index]; +#ifdef MAC_REPEATER_SUPPORT + if ((pAd->ApCfg.bMACRepeaterEn) && (pApCliEntry->Enable)) + { + for(CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) + { + pReptCliEntry = &pAd->ApCfg.ApCliTab[index].RepeaterCli[CliIdx]; + + if (pReptCliEntry->CliEnable) + { + + if (pReptCliEntry->CliValid) + { + Wcid = pAd->ApCfg.ApCliTab[index].RepeaterCli[CliIdx].MacTabWCID; + + if (!VALID_WCID(Wcid)) + continue; + + pMacEntry = &pAd->MacTab.Content[Wcid]; + tr_entry = &pAd->MacTab.tr_entry[Wcid]; + if ((tr_entry->PortSecured != WPA_802_1X_PORT_SECURED) && + RTMP_TIME_AFTER(pAd->Mlme.Now32 + , (pReptCliEntry->CliTriggerTime + ( +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + TimeoutVal +#else + 5 +#endif + * OS_HZ)))) { +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + APCLI_STRUCT *papcli_entry = pApCliEntry; + + if (papcli_entry->pre_mac_entry.AuthMode == Ndis802_11AuthModeWPA3PSK + || papcli_entry->pre_mac_entry.AuthMode == Ndis802_11AuthModeOWE) { + UCHAR pmkid[80]; + UCHAR pmk[LEN_PMK]; + INT cached_idx; + UCHAR if_index = papcli_entry->wdev.func_idx; + + /*Update PMK cache and delete sae instance*/ + if (FALSE || +#ifdef APCLI_SAE_SUPPORT + (papcli_entry->pre_mac_entry.AuthMode == Ndis802_11AuthModeWPA3PSK && + sae_get_pmk_cache(&pAd->SaeCfg, pReptCliEntry->CurrentAddress, papcli_entry->MlmeAux.Bssid, pmkid, pmk)) +#endif +#ifdef APCLI_OWE_SUPPORT + || papcli_entry->pre_mac_entry.AuthMode == Ndis802_11AuthModeOWE +#endif + ) { + + cached_idx = apcli_search_pmkid_cache(pAd, papcli_entry->MlmeAux.Bssid, if_index +#ifdef MAC_REPEATER_SUPPORT + , CliIdx +#endif + ); + + if (cached_idx != INVALID_PMKID_IDX) { +#ifdef APCLI_SAE_SUPPORT + SAE_INSTANCE *pSaeIns = search_sae_instance(&pAd->SaeCfg, pReptCliEntry->CurrentAddress, papcli_entry->MlmeAux.Bssid); + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s:Connection falied with pmkid ,delete cache entry and sae instance\n", __func__)); + if (pSaeIns != NULL) { + delete_sae_instance(pSaeIns); + pSaeIns = NULL; + } +#endif + apcli_delete_pmkid_cache(pAd, papcli_entry->MlmeAux.Bssid, if_index +#ifdef MAC_REPEATER_SUPPORT + , CliIdx +#endif + ); + } + } + } +#endif + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, (64 + MAX_EXT_MAC_ADDR_SIZE*index + CliIdx)); + RTMP_MLME_HANDLER(pAd); + } + } + else + { + if (RTMP_TIME_AFTER(pAd->Mlme.Now32 , (pReptCliEntry->CliTriggerTime + (5 * OS_HZ)))) + { + DBGPRINT(RT_DEBUG_OFF, + ("%s, ApCli%d, CliIdx = %d\n", + __func__, index, CliIdx)); + MlmeEnqueue(pAd, + APCLI_CTRL_STATE_MACHINE, + APCLI_CTRL_DEL_MACREPENTRY, + 0, + NULL, + (64 + MAX_EXT_MAC_ADDR_SIZE*index + CliIdx)); + RTMP_MLME_HANDLER(pAd); + } + } + } + } + } +#endif /* MAC_REPEATER_SUPPORT */ + + if (pApCliEntry->Valid == TRUE) + { + BOOLEAN ApclibQosNull = FALSE; + + Wcid = pAd->ApCfg.ApCliTab[index].MacTabWCID; + if (!VALID_WCID(Wcid)) + continue; + pMacEntry = &pAd->MacTab.Content[Wcid]; + tr_entry = &pAd->MacTab.tr_entry[Wcid]; + + if ((pMacEntry->AuthMode >= Ndis802_11AuthModeWPA) + && (tr_entry->PortSecured != WPA_802_1X_PORT_SECURED) + && (RTMP_TIME_AFTER(pAd->Mlme.Now32, (pApCliEntry->ApCliLinkUpTime + (30 * OS_HZ))))) { +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + bWpa_4way_too_log = TRUE; +#endif + bForceBrocken = TRUE; + } + + if (RTMP_TIME_AFTER(pAd->Mlme.Now32 , (pApCliEntry->ApCliRcvBeaconTime + (4 * OS_HZ)))) + { +#ifdef WH_EZ_SETUP +#ifdef EZ_NETWORK_MERGE_SUPPORT + if(IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev)){ + unsigned char delay_disconnect_count = ez_get_delay_disconnect_count(&pApCliEntry->wdev); + if (delay_disconnect_count > 0) { + delay_disconnect_count--; + ez_set_delay_disconnect_count(&pApCliEntry->wdev, delay_disconnect_count); + } + else + { + bForceBrocken = TRUE; +#ifdef WH_EZ_SETUP + bBeacon_miss = TRUE; +#endif + } + } + else +#endif +#endif + { + bForceBrocken = TRUE; + } + + } + + if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)) + ApclibQosNull = TRUE; +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + if (bWpa_4way_too_log == TRUE) { + if (pMacEntry->AuthMode == Ndis802_11AuthModeWPA3PSK || + pMacEntry->AuthMode == Ndis802_11AuthModeOWE) { + UCHAR pmkid[80]; + UCHAR pmk[LEN_PMK]; + INT cached_idx; + UCHAR if_index = pApCliEntry->wdev.func_idx; + UCHAR cli_idx = 0xFF; + + /* Connection taking too long update PMK cache and delete sae instance*/ + if ( +#ifdef APCLI_SAE_SUPPORT + + (pMacEntry->AuthMode >= Ndis802_11AuthModeWPA3PSK && + sae_get_pmk_cache(&pAd->SaeCfg, pApCliEntry->wdev.if_addr, + pApCliEntry->MlmeAux.Bssid, pmkid, pmk)) +#endif + +#ifdef APCLI_OWE_SUPPORT + || pMacEntry->AuthMode == Ndis802_11AuthModeOWE +#endif + ) { + + cached_idx = apcli_search_pmkid_cache(pAd, + pApCliEntry->MlmeAux.Bssid, if_index +#ifdef MAC_REPEATER_SUPPORT + , cli_idx +#endif + ); + if (cached_idx != INVALID_PMKID_IDX) { +#ifdef APCLI_SAE_SUPPORT + SAE_INSTANCE *pSaeIns = search_sae_instance(&pAd->SaeCfg, + pApCliEntry->wdev.if_addr, pApCliEntry->MlmeAux.Bssid); + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("Reconnection falied with pmkid ,delete cache entry and sae instance\n")); + + if (pSaeIns != NULL) + delete_sae_instance(pSaeIns); +#endif + apcli_delete_pmkid_cache(pAd, + pApCliEntry->MlmeAux.Bssid, if_index +#ifdef MAC_REPEATER_SUPPORT + , cli_idx +#endif + ); + } + } + + } + } +#endif + + if (bForceBrocken == FALSE) + ApCliRTMPSendNullFrame(pAd, pMacEntry->CurrTxRate, ApclibQosNull, pMacEntry, PWR_ACTIVE); + } + 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) + { +#ifdef WH_EZ_SETUP + if (bBeacon_miss) + { + pAd->ApCfg.ApCliTab[index].RepeaterCli[CliIdx].Disconnect_Sub_Reason = APCLI_DISCONNECT_SUB_REASON_MNT_NO_BEACON; + } +#endif + 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 */ + //MCC TODO: WCID Not Correct when MCC on +#ifdef WH_EZ_SETUP + if (bBeacon_miss) + { + pApCliEntry->Disconnect_Sub_Reason = APCLI_DISCONNECT_SUB_REASON_MNT_NO_BEACON; + } +#endif + 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; +#ifdef APCLI_SAE_SUPPORT + USHORT Alg; +#endif + UCHAR EAPType; + BOOLEAN Return = FALSE; +#ifdef WSC_AP_SUPPORT + UCHAR EAPCode; + PMAC_TABLE_ENTRY pEntry; +#endif /* WSC_AP_SUPPORT */ + unsigned char hdr_len = LENGTH_802_11; + +#ifdef A4_CONN + if ((pFrame->Hdr.FC.FrDs == 1) && (pFrame->Hdr.FC.ToDs == 1)) + hdr_len = LENGTH_802_11_WITH_ADDR4; +#endif + + /* only PROBE_REQ can be broadcast, all others must be unicast-to-me && is_mybssid; otherwise, */ + /* ignore this frame */ + + /* WPA EAPOL PACKET */ + if (pFrame->Hdr.FC.Type == FC_TYPE_DATA) + { +#ifdef WSC_AP_SUPPORT + /*WSC EAPOL PACKET */ + pEntry = MacTableLookup(pAd, pFrame->Hdr.Addr2); + if (pEntry && IS_ENTRY_APCLI(pEntry) && pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].WscControl.WscConfMode == WSC_ENROLLEE) + { + *Machine = WSC_STATE_MACHINE; + EAPType = *((UCHAR *)pFrame + hdr_len + LENGTH_802_1_H + 1); + EAPCode = *((UCHAR *)pFrame + hdr_len + LENGTH_802_1_H + 4); + Return = WscMsgTypeSubst(EAPType, EAPCode, MsgType); + } + if (!Return) +#endif /* WSC_AP_SUPPORT */ + { + *Machine = WPA_STATE_MACHINE; + EAPType = *((UCHAR *)pFrame + hdr_len + LENGTH_802_1_H + 1); + Return = WpaMsgTypeSubst(EAPType, MsgType); + } + return Return; + } + else if (pFrame->Hdr.FC.Type == FC_TYPE_MGMT) + { + switch (pFrame->Hdr.FC.SubType) + { + case SUBTYPE_ASSOC_RSP: + *Machine = APCLI_ASSOC_STATE_MACHINE; + *MsgType = APCLI_MT2_PEER_ASSOC_RSP; + break; + + case SUBTYPE_DISASSOC: + *Machine = APCLI_ASSOC_STATE_MACHINE; + *MsgType = APCLI_MT2_PEER_DISASSOC_REQ; + break; + + case SUBTYPE_DEAUTH: + *Machine = APCLI_AUTH_STATE_MACHINE; + *MsgType = APCLI_MT2_PEER_DEAUTH; + break; + + case SUBTYPE_AUTH: + /* get the sequence number from payload 24 Mac Header + 2 bytes algorithm */ +#ifdef APCLI_SAE_SUPPORT + NdisMoveMemory(&Alg, &pFrame->Octet[0], sizeof(USHORT)); +#endif /* APCLI_SAE_SUPPORT */ + + NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT)); +#ifdef APCLI_SAE_SUPPORT + if (Alg == AUTH_MODE_SAE && Seq == 1) { + *Machine = APCLI_AUTH_STATE_MACHINE; + *MsgType = APCLI_MT2_MLME_SAE_AUTH_COMMIT; + } else if (Alg == AUTH_MODE_SAE && Seq == 2) { + *Machine = APCLI_AUTH_STATE_MACHINE; + *MsgType = APCLI_MT2_MLME_SAE_AUTH_CONFIRM; + } else +#endif /* APCLI_SAE_SUPPORT */ + + if (Seq == 2 || Seq == 4) + { + *Machine = APCLI_AUTH_STATE_MACHINE; + *MsgType = APCLI_MT2_PEER_AUTH_EVEN; + } + else + { + return FALSE; + } + break; + + case SUBTYPE_ACTION: + *Machine = ACTION_STATE_MACHINE; + /* Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support */ + if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG) + *MsgType = MT2_ACT_INVALID; + else + *MsgType = (pFrame->Octet[0]&0x7F); + break; + + default: + return FALSE; + } + + return TRUE; + } + + return FALSE; +} + + +BOOLEAN preCheckMsgTypeSubset( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT INT *MsgType) +{ + if (pFrame->Hdr.FC.Type == FC_TYPE_MGMT) + { + switch (pFrame->Hdr.FC.SubType) + { + /* Beacon must be processed by AP Sync state machine. */ + case SUBTYPE_BEACON: + *Machine = AP_SYNC_STATE_MACHINE; + *MsgType = APMT2_PEER_BEACON; + break; + + /* Only Sta have chance to receive Probe-Rsp. */ + case SUBTYPE_PROBE_RSP: +#ifdef MULTI_APCLI_SUPPORT + DBGPRINT(RT_DEBUG_TRACE,("\x1b[36m preCheckMsgTypeSubset SUBTYPE_PROBE_RSP....\x1b[m\n")); +#endif /* MULTI_APCLI_SUPPORT */ + + *Machine = APCLI_SYNC_STATE_MACHINE; + *MsgType = APCLI_MT2_PEER_PROBE_RSP; + break; + + default: + return FALSE; + } + return TRUE; + } + return FALSE; +} + + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN ApCliPeerAssocRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pStatus, + OUT USHORT *pAid, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT ADD_HT_INFO_IE *pAddHtInfo, /* AP might use this additional ht info IE */ + OUT UCHAR *pHtCapabilityLen, + OUT UCHAR *pAddHtInfoLen, + OUT UCHAR *pNewExtChannelOffset, + OUT PEDCA_PARM pEdcaParm, + OUT UCHAR *pCkipFlag, + OUT IE_LISTS *ie_list) +{ + CHAR IeType/*, *Ptr*/; + PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; + PEID_STRUCT pEid; + ULONG Length = 0; +#ifdef APCLI_OWE_SUPPORT + UCHAR *extension_id; + UCHAR *ext_ie_length; +#endif + + *pNewExtChannelOffset = 0xff; + *pHtCapabilityLen = 0; + *pAddHtInfoLen = 0; + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + //Ptr = (CHAR *) pFrame->Octet; + Length += LENGTH_802_11; + + NdisMoveMemory(pCapabilityInfo, &pFrame->Octet[0], 2); + Length += 2; + NdisMoveMemory(pStatus, &pFrame->Octet[2], 2); + Length += 2; + *pCkipFlag = 0; + *pExtRateLen = 0; + pEdcaParm->bValid = FALSE; + + if (*pStatus != MLME_SUCCESS) + return TRUE; + + NdisMoveMemory(pAid, &pFrame->Octet[4], 2); + Length += 2; + + /* Aid already swaped byte order in RTMPFrameEndianChange() for big endian platform */ + *pAid = (*pAid) & 0x3fff; /* AID is low 14-bit */ + + /* -- get supported rates from payload and advance the pointer */ + IeType = pFrame->Octet[6]; + *pSupRateLen = pFrame->Octet[7]; + if ((IeType != IE_SUPP_RATES) || (*pSupRateLen > MAX_LEN_OF_SUPPORTED_RATES)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): fail - wrong SupportedRates IE\n", __FUNCTION__)); + return FALSE; + } + else + NdisMoveMemory(SupRate, &pFrame->Octet[8], *pSupRateLen); + + Length = Length + 2 + *pSupRateLen; + + /* many AP implement proprietary IEs in non-standard order, we'd better */ + /* tolerate mis-ordered IEs to get best compatibility */ + pEid = (PEID_STRUCT) &pFrame->Octet[8 + (*pSupRateLen)]; + + /* get variable fields from payload and advance the pointer */ + while ((Length + 2 + pEid->Len) <= MsgLen) + { + switch (pEid->Eid) + { + case IE_EXT_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(ExtRate, pEid->Octet, pEid->Len); + *pExtRateLen = pEid->Len; + } + break; +#ifdef DOT11_N_SUPPORT + case IE_HT_CAP: + case IE_HT_CAP2: + if (pEid->Len >= SIZE_HT_CAP_IE) /*Note: allow extension.!! */ + { + NdisMoveMemory(pHtCapability, pEid->Octet, SIZE_HT_CAP_IE); + *(USHORT *) (&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); + *(USHORT *) (&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); + *pHtCapabilityLen = SIZE_HT_CAP_IE; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_HT_CAP\n", __FUNCTION__)); + } + + break; + case IE_ADD_HT: + case IE_ADD_HT2: + if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) + { + /* This IE allows extension, but we can ignore extra bytes beyond our knowledge , so only */ + /* copy first sizeof(ADD_HT_INFO_IE) */ + NdisMoveMemory(pAddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); + *pAddHtInfoLen = SIZE_ADD_HT_INFO_IE; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_ADD_HT\n", __FUNCTION__)); + } + break; + case IE_SECONDARY_CH_OFFSET: + if (pEid->Len == 1) + { + *pNewExtChannelOffset = pEid->Octet[0]; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_SECONDARY_CH_OFFSET\n", __FUNCTION__)); + } + break; +#ifdef DOT11_VHT_AC + case IE_VHT_CAP: + if (pEid->Len == sizeof(VHT_CAP_IE)) { + NdisMoveMemory(&ie_list->vht_cap, pEid->Octet, sizeof(VHT_CAP_IE)); + ie_list->vht_cap_len = sizeof(VHT_CAP_IE); + } else { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_VHT_CAP\n", __FUNCTION__)); + } + break; + case IE_VHT_OP: + if (pEid->Len == sizeof(VHT_OP_IE)) { + NdisMoveMemory(&ie_list->vht_op, pEid->Octet, sizeof(VHT_OP_IE)); + ie_list->vht_op_len = sizeof(VHT_OP_IE); + }else { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_VHT_OP\n", __FUNCTION__)); + } + break; +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + /* CCX2, WMM use the same IE value */ + /* case IE_CCX_V2: */ + case IE_VENDOR_SPECIFIC: + /* handle WME PARAMTER ELEMENT */ + if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24)) + { + PUCHAR ptr; + int i; + + /* parsing EDCA parameters */ + pEdcaParm->bValid = TRUE; + pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10; */ + pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20; */ + pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40; */ + /*pEdcaParm->bMoreDataAck = FALSE; // pEid->Octet[0] & 0x80; */ + pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; + pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; + ptr = (PUCHAR) &pEid->Octet[8]; + for (i=0; i<4; i++) + { + UCHAR aci = (*ptr & 0x60) >> 5; /* b5~6 is AC INDEX */ + pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); /* b5 is ACM */ + pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; /* b0~3 is AIFSN */ + pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; /* b0~4 is Cwmin */ + pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; /* b5~8 is Cwmax */ + pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); /* in unit of 32-us */ + ptr += 4; /* point to next AC */ + } + } + break; +#ifdef APCLI_OWE_SUPPORT + case IE_RSN: + /* Copy whole RSNIE context */ + NdisMoveMemory(&ie_list->RSN_IE[0], pEid, pEid->Len + 2); + ie_list->RSNIE_Len = pEid->Len + 2; + break; + + case IE_WLAN_EXTENSION: + /*parse EXTENSION EID*/ + extension_id = (UCHAR *)pEid + 2; + switch (*extension_id) { + case IE_EXTENSION_ID_ECDH: + ext_ie_length = (UCHAR *)pEid + 1; + if (*ext_ie_length - 3 <= sizeof(ie_list->ecdh_ie.public_key)) + os_zero_mem(ie_list->ecdh_ie.public_key, *ext_ie_length - 3); + else { + DBGPRINT(RT_DEBUG_ERROR, ("%s():IE_ECDH error\n", __func__)); + break; + } + ie_list->ecdh_ie.ext_ie_id = IE_WLAN_EXTENSION; + ie_list->ecdh_ie.length = pEid->Len; + if (pEid->Len <= sizeof(ie_list->ecdh_ie) - 2) + NdisMoveMemory(&ie_list->ecdh_ie.ext_id_ecdh, pEid->Octet, pEid->Len); + else { + DBGPRINT(RT_DEBUG_ERROR, ("%s():IE_ECDH error\n", __func__)); + break; + } + break; + + default: + DBGPRINT(RT_DEBUG_ERROR, + ("RESP IE_WLAN_EXTENSION: no handler for extension_id:%d\n", *extension_id)); + break; + } +#endif + default: + DBGPRINT(RT_DEBUG_TRACE, ("%s():ignore unrecognized EID = %d\n", __FUNCTION__, pEid->Eid)); + break; + } + + Length = Length + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + return TRUE; +} + + +MAC_TABLE_ENTRY *ApCliTableLookUpByWcid(RTMP_ADAPTER *pAd, UCHAR wcid, UCHAR *pAddrs) +{ + ULONG ApCliIndex; + PMAC_TABLE_ENTRY pCurEntry = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + + if (!VALID_WCID(wcid)) + return NULL; + + NdisAcquireSpinLock(&pAd->MacTabLock); + + do + { + pCurEntry = &pAd->MacTab.Content[wcid]; + + ApCliIndex = 0xff; + if ((pCurEntry) && IS_ENTRY_APCLI(pCurEntry)) + { + ApCliIndex = pCurEntry->func_tb_idx; + } + + if ((ApCliIndex == 0xff) || (ApCliIndex >= MAX_APCLI_NUM)) + break; + + if (pAd->ApCfg.ApCliTab[ApCliIndex].Valid != TRUE) + break; + + if (MAC_ADDR_EQUAL(pCurEntry->Addr, pAddrs)) + { + pEntry = pCurEntry; + break; + } + } while(FALSE); + + NdisReleaseSpinLock(&pAd->MacTabLock); + + return pEntry; +} + + +/* + ========================================================================== + Description: + Check the Apcli Entry is valid or not. + ========================================================================== + */ +static inline BOOLEAN ValidApCliEntry(RTMP_ADAPTER *pAd, INT apCliIdx) +{ + BOOLEAN result; + PMAC_TABLE_ENTRY pMacEntry; + APCLI_STRUCT *pApCliEntry; + + do + { + if ((apCliIdx < 0) || (apCliIdx >= MAX_APCLI_NUM)) + { + result = FALSE; + break; + } + + pApCliEntry = (APCLI_STRUCT *)&pAd->ApCfg.ApCliTab[apCliIdx]; + if (pApCliEntry->Valid != TRUE) + { + result = FALSE; + break; + } + + if ((pApCliEntry->MacTabWCID <= 0) + || (pApCliEntry->MacTabWCID >= MAX_LEN_OF_MAC_TABLE)) + { + result = FALSE; + break; + } + + pMacEntry = &pAd->MacTab.Content[pApCliEntry->MacTabWCID]; + if (!IS_ENTRY_APCLI(pMacEntry)) + { + result = FALSE; + break; + } + + result = TRUE; + } while(FALSE); + + return result; +} + + +INT ApCliAllowToSendPacket( + IN RTMP_ADAPTER *pAd, + IN struct wifi_dev *wdev, + IN PNDIS_PACKET pPacket, + OUT UCHAR *pWcid) +{ + UCHAR idx; + BOOLEAN allowed = FALSE; + APCLI_STRUCT *apcli_entry; + STA_TR_ENTRY *rpt_peer_entry = NULL, *apcli_peer_entry = NULL; + + + for(idx = 0; idx < MAX_APCLI_NUM; idx++) + { + apcli_entry = &pAd->ApCfg.ApCliTab[idx]; + if (&apcli_entry->wdev == wdev) + { + if (ValidApCliEntry(pAd, idx) == FALSE) + return FALSE; + +#ifdef WSC_AP_SUPPORT + if ((apcli_entry->WscControl.WscConfMode != WSC_DISABLE) && + (apcli_entry->WscControl.bWscTrigger == TRUE)) { + DBGPRINT(RT_DEBUG_ERROR, ("apcli during wps, os should not send packets!!!\n")); + return FALSE; + } +#endif /* WSC_AP_SUPPORT */ + + apcli_peer_entry = &pAd->MacTab.tr_entry[apcli_entry->MacTabWCID]; + if (apcli_peer_entry && + (apcli_peer_entry->PortSecured != WPA_802_1X_PORT_SECURED)) { + DBGPRINT(RT_DEBUG_ERROR, ("apcli peer entry port not secure, drop os packets!!!\n")); + return FALSE; + } + +#ifdef MAC_REPEATER_SUPPORT + if ((pAd->ApCfg.bMACRepeaterEn == TRUE) +#ifdef A4_CONN + && (IS_APCLI_A4(apcli_entry) == FALSE) +#endif /* A4_CONN */ + + ) + { + PUCHAR pSrcBufVA = NULL; + PACKET_INFO PacketInfo; + UINT SrcBufLen; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + UCHAR isLinkValid; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, TRUE, (pSrcBufVA + MAC_ADDR_LEN), TRUE, &isLinkValid); + if (pReptEntry) + { +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) + if ((pReptEntry->MatchApCliIdx != apcli_entry->wdev.func_idx) && + (wf_fwd_check_active_hook && wf_fwd_check_active_hook())) + { + UCHAR apCliIdx, CliIdx; + apCliIdx = pReptEntry->MatchApCliIdx; + CliIdx = pReptEntry->MatchLinkIdx; + MlmeEnqueue(pAd, + APCLI_CTRL_STATE_MACHINE, + APCLI_CTRL_DISCONNECT_REQ, + 0, + NULL, + (64 + CliIdx)); + RTMP_MLME_HANDLER(pAd); + return FALSE; + } +#endif /* CONFIG_WIFI_PKT_FWD */ +#endif + rpt_peer_entry = &pAd->MacTab.tr_entry[pReptEntry->MacTabWCID]; + if (rpt_peer_entry && + (rpt_peer_entry->PortSecured != WPA_802_1X_PORT_SECURED)) { + allowed = FALSE; + DBGPRINT(RT_DEBUG_ERROR, + ("rpt peer entry not secure, drop os packets!!!\n")); + } + *pWcid = pReptEntry->MacTabWCID; + return TRUE; + } + else + { + if (!isLinkValid) + return FALSE; +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) + if ((wf_fwd_check_active_hook && wf_fwd_check_active_hook())) +#endif + { +#endif + if (RTMPRepeaterVaildMacEntry(pAd, pSrcBufVA + MAC_ADDR_LEN)) + { + RTMPInsertRepeaterEntry(pAd, idx, (pSrcBufVA + MAC_ADDR_LEN)); + DBGPRINT(RT_DEBUG_ERROR, (" Receive trigger packet !!!\n")); + return FALSE; +#if (MT7615_MT7603_COMBO_FORWARDING == 1) + } +#endif + } + } + + *pWcid = apcli_entry->MacTabWCID; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pAd->RalinkCounters.PendingNdisPacketCount ++; + RTMP_SET_PACKET_WDEV(pPacket, wdev->wdev_idx); + *pWcid = apcli_entry->MacTabWCID; + } + allowed = TRUE; + + break; + } + } + + return allowed; +} + + +/* + ======================================================================== + + Routine Description: + Validate the security configuration against the RSN information + element + + Arguments: + pAdapter Pointer to our adapter + eid_ptr Pointer to VIE + + Return Value: + TRUE for configuration match + FALSE for otherwise + + Note: + + ======================================================================== +*/ +BOOLEAN ApCliValidateRSNIE( + IN RTMP_ADAPTER *pAd, + IN PEID_STRUCT pEid_ptr, + IN USHORT eid_len, + IN USHORT idx +#ifdef APCLI_OWE_SUPPORT + , IN UCHAR Privacy +#endif + ) +{ + PUCHAR pVIE, pTmp; + UCHAR len; + PEID_STRUCT pEid; + CIPHER_SUITE WPA; /* AP announced WPA cipher suite */ + CIPHER_SUITE WPA2; /* AP announced WPA2 cipher suite */ + USHORT Count; + UCHAR Sanity; + PAPCLI_STRUCT pApCliEntry = NULL; + PRSN_IE_HEADER_STRUCT pRsnHeader; + NDIS_802_11_ENCRYPTION_STATUS TmpCipher; + NDIS_802_11_AUTHENTICATION_MODE TmpAuthMode; + NDIS_802_11_AUTHENTICATION_MODE WPA_AuthMode; + NDIS_802_11_AUTHENTICATION_MODE WPA_AuthModeAux; + NDIS_802_11_AUTHENTICATION_MODE WPA2_AuthMode; + NDIS_802_11_AUTHENTICATION_MODE WPA2_AuthModeAux; + struct wifi_dev *wdev; +#ifdef APCLI_SECURITY_IMPROVEMENT_SUPPORT + UCHAR end_field = 0; + UCHAR res = TRUE; +#ifdef APCLI_OWE_SUPPORT + RSN_CAPABILITIES *pRSN_Cap = NULL; +#endif +#endif + +#if defined(APCLI_OWE_SUPPORT) || defined(APCLI_SAE_SUPPORT) + pApCliEntry = &pAd->ApCfg.ApCliTab[idx]; +#endif + +#ifdef APCLI_OWE_SUPPORT + if (pAd->ApCfg.ApCliTab[idx].wdev.AuthMode == Ndis802_11AuthModeOWE && (Privacy == 0)) { + pApCliEntry->pre_mac_entry.AuthMode = Ndis802_11AuthModeOpen; + pApCliEntry->pre_mac_entry.WepStatus = Ndis802_11WEPDisabled; + pApCliEntry->pre_mac_entry.GroupKeyWepStatus = Ndis802_11WEPDisabled; + pApCliEntry->PairCipher = Ndis802_11WEPDisabled; + pApCliEntry->GroupCipher = Ndis802_11WEPDisabled; + pApCliEntry->RsnCapability = 0; + pApCliEntry->bMixCipher = FALSE; + return TRUE; /* No Security */ + } +#endif + + + pVIE = (PUCHAR) pEid_ptr; + len = eid_len; + + /*if (len >= MAX_LEN_OF_RSNIE || len <= MIN_LEN_OF_RSNIE) */ + /* return FALSE; */ + + /* Init WPA setting */ + WPA.PairCipher = Ndis802_11WEPDisabled; + WPA.PairCipherAux = Ndis802_11WEPDisabled; + WPA.GroupCipher = Ndis802_11WEPDisabled; + WPA.RsnCapability = 0; + WPA.bMixMode = FALSE; + WPA_AuthMode = Ndis802_11AuthModeOpen; + WPA_AuthModeAux = Ndis802_11AuthModeOpen; + + /* Init WPA2 setting */ + WPA2.PairCipher = Ndis802_11WEPDisabled; + WPA2.PairCipherAux = Ndis802_11WEPDisabled; + WPA2.GroupCipher = Ndis802_11WEPDisabled; + WPA2.RsnCapability = 0; + WPA2.bMixMode = FALSE; + WPA2_AuthMode = Ndis802_11AuthModeOpen; + WPA2_AuthModeAux = Ndis802_11AuthModeOpen; + + Sanity = 0; + + /* 1. Parse Cipher this received RSNIE */ + while (len > 0) + { + pTmp = pVIE; + pEid = (PEID_STRUCT) pTmp; + + switch(pEid->Eid) + { + case IE_WPA: + if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1) + { + /* if unsupported vendor specific IE */ + break; + } + /* Skip OUI ,version and multicast suite OUI */ + pTmp += 11; + + /* + Cipher Suite Selectors from Spec P802.11i/D3.2 P26. + Value Meaning + 0 None + 1 WEP-40 + 2 Tkip + 3 WRAP + 4 AES + 5 WEP-104 + */ + /* Parse group cipher */ + switch (*pTmp) + { + case 1: + case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */ + WPA.GroupCipher = Ndis802_11WEPEnabled; + break; + case 2: + WPA.GroupCipher = Ndis802_11TKIPEnable; + break; + case 4: + WPA.GroupCipher = Ndis802_11AESEnable; + break; + default: + break; + } + + /* number of unicast suite */ + pTmp += 1; + + /* Store unicast cipher count */ + NdisMoveMemory(&Count, pTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + + /* pointer to unicast cipher */ + pTmp += sizeof(USHORT); + + /* Parsing all unicast cipher suite */ + while (Count > 0) + { + /* Skip cipher suite OUI */ + pTmp += 3; + TmpCipher = Ndis802_11WEPDisabled; + switch (*pTmp) + { + case 1: + case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */ + TmpCipher = Ndis802_11WEPEnabled; + break; + case 2: + TmpCipher = Ndis802_11TKIPEnable; + break; + case 4: + TmpCipher = Ndis802_11AESEnable; + break; + default: + break; + } + if (TmpCipher > WPA.PairCipher) + { + /* Move the lower cipher suite to PairCipherAux */ + WPA.PairCipherAux = WPA.PairCipher; + WPA.PairCipher = TmpCipher; + } + else + { + WPA.PairCipherAux = TmpCipher; + } + pTmp++; + Count--; + } + + /* Get AKM suite counts */ + NdisMoveMemory(&Count, pTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + + pTmp += sizeof(USHORT); + + /* Parse AKM ciphers */ + /* Parsing all AKM cipher suite */ + while (Count > 0) + { + /* Skip cipher suite OUI */ + pTmp += 3; + TmpAuthMode = Ndis802_11AuthModeOpen; + switch (*pTmp) + { + case 1: + /* WPA-enterprise */ + TmpAuthMode = Ndis802_11AuthModeWPA; + break; + case 2: + /* WPA-personal */ + TmpAuthMode = Ndis802_11AuthModeWPAPSK; + break; + default: + break; + } + if (TmpAuthMode > WPA_AuthMode) + { + /* Move the lower AKM suite to WPA_AuthModeAux */ + WPA_AuthModeAux = WPA_AuthMode; + WPA_AuthMode = TmpAuthMode; + } + else + { + WPA_AuthModeAux = TmpAuthMode; + } + pTmp++; + Count--; + } + + /* ToDo - Support WPA-None ? */ + + /* Check the Pair & Group, if different, turn on mixed mode flag */ + if (WPA.GroupCipher != WPA.PairCipher) + WPA.bMixMode = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("ApCliValidateRSNIE - RSN-WPA1 PairWiseCipher(%s), GroupCipher(%s), AuthMode(%s)\n", + ((WPA.bMixMode) ? "Mix" : GetEncryptType(WPA.PairCipher)), + GetEncryptType(WPA.GroupCipher), + GetAuthMode(WPA_AuthMode))); + + Sanity |= 0x1; + break; /* End of case IE_WPA */ + case IE_RSN: + pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp; +#ifdef APCLI_SECURITY_IMPROVEMENT_SUPPORT + res = wpa_rsne_sanity(pTmp, le2cpu16(pRsnHeader->Length) + 2, &end_field); + if (res == FALSE) + return FALSE; + + if (end_field < RSN_FIELD_GROUP_CIPHER) + WPA2.GroupCipher = Ndis802_11AESEnable; + if (end_field < RSN_FIELD_PAIRWISE_CIPHER) + WPA2.PairCipher = Ndis802_11AESEnable; + if (end_field < RSN_FIELD_AKM) + WPA2_AuthMode = Ndis802_11AuthModeWPA2PSK; +#endif + /* 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; + } +#ifdef APCLI_SECURITY_IMPROVEMENT_SUPPORT + /*Check group cipher*/ + if (end_field < RSN_FIELD_GROUP_CIPHER) + break; +#endif + + pTmp += sizeof(RSN_IE_HEADER_STRUCT); + + /* 1. Check cipher OUI */ + if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) + { + /* if unsupported vendor specific IE */ + break; + } + + /* Skip cipher suite OUI */ + pTmp += 3; + + /* Parse group cipher */ + switch (*pTmp) + { + case 1: + case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */ + WPA2.GroupCipher = Ndis802_11WEPEnabled; + break; + case 2: + WPA2.GroupCipher = Ndis802_11TKIPEnable; + break; + case 4: + WPA2.GroupCipher = Ndis802_11AESEnable; + break; + default: + break; + } + + /* number of unicast suite */ + pTmp += 1; + + /* Get pairwise cipher counts */ +#ifdef APCLI_SECURITY_IMPROVEMENT_SUPPORT + if (end_field < RSN_FIELD_PAIRWISE_CIPHER) + break; +#endif + NdisMoveMemory(&Count, pTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + + pTmp += sizeof(USHORT); + + /* 3. Get pairwise cipher */ +#ifdef APCLI_SECURITY_IMPROVEMENT_SUPPORT + if (Count == 0) { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]%s : pairwise cipher count =0 !!!\n", __func__)); + return FALSE; + } +#endif + /* Parsing all unicast cipher suite */ + while (Count > 0) + { + /* Skip OUI */ + pTmp += 3; + TmpCipher = Ndis802_11WEPDisabled; + switch (*pTmp) + { + case 1: + case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway */ + TmpCipher = Ndis802_11WEPEnabled; + break; + case 2: + TmpCipher = Ndis802_11TKIPEnable; + break; + case 4: + TmpCipher = Ndis802_11AESEnable; + break; + default: + break; + } + if (TmpCipher > WPA2.PairCipher) + { + /* Move the lower cipher suite to PairCipherAux */ + WPA2.PairCipherAux = WPA2.PairCipher; + WPA2.PairCipher = TmpCipher; + } + else + { + WPA2.PairCipherAux = TmpCipher; + } + pTmp ++; + Count--; + } + + /* Get AKM suite counts */ +#ifdef APCLI_SECURITY_IMPROVEMENT_SUPPORT + if (end_field < RSN_FIELD_AKM) + break; +#endif + NdisMoveMemory(&Count, pTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + + pTmp += sizeof(USHORT); + + /* Parse AKM ciphers */ +#ifdef APCLI_SECURITY_IMPROVEMENT_SUPPORT + if (Count == 0) { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]%s : AKM cipher count =0 !!!\n", __func__)); + return FALSE; + } +#endif + /* 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: +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef DOT11W_PMF_SUPPORT + case 6: +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + /* WPA2-personal */ + TmpAuthMode = Ndis802_11AuthModeWPA2PSK; + break; +#ifdef APCLI_SAE_SUPPORT + case 8: + TmpAuthMode = Ndis802_11AuthModeWPA3PSK; + break; +#endif +#ifdef APCLI_OWE_SUPPORT + case 18: + TmpAuthMode = Ndis802_11AuthModeOWE; + break; +#endif + 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--; + } + +#ifdef APCLI_OWE_SUPPORT + if (end_field >= RSN_FIELD_RSN_CAP) { + + pRSN_Cap = (RSN_CAPABILITIES *) pTmp; + + if (pApCliEntry->pre_mac_entry.AuthMode == Ndis802_11AuthModeOWE) { + /*OWE connection should be allowed with only OWE AP*/ + /*which has PMF Capable and PMF required set*/ + if ((pRSN_Cap->field.MFPC == 0) || (pRSN_Cap->field.MFPR == 0)) + return FALSE; + } + } +#endif + + /* Check the Pair & Group, if different, turn on mixed mode flag */ + if (WPA2.GroupCipher != WPA2.PairCipher) + WPA2.bMixMode = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("ApCliValidateRSNIE - RSN-WPA2 PairWiseCipher(%s), GroupCipher(%s), AuthMode(%s)\n", + (WPA2.bMixMode ? "Mix" : GetEncryptType(WPA2.PairCipher)), GetEncryptType(WPA2.GroupCipher), + GetAuthMode(WPA2_AuthMode))); + + Sanity |= 0x2; + break; /* End of case IE_RSN */ + default: + DBGPRINT(RT_DEBUG_WARN, ("ApCliValidateRSNIE - Unknown pEid->Eid(%d) \n", pEid->Eid)); + break; + } + + /* skip this Eid */ + pVIE += (pEid->Len + 2); + len -= (pEid->Len + 2); + + } + + /* 2. Validate this RSNIE with mine */ + pApCliEntry = &pAd->ApCfg.ApCliTab[idx]; + wdev = &pApCliEntry->wdev; + + /* Peer AP doesn't include WPA/WPA2 capable */ + if (Sanity == 0) + { + /* Check the authenticaton mode */ + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s - The authentication mode doesn't match \n", __FUNCTION__)); + return FALSE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s - The pre-RSNA authentication mode is used. \n", __FUNCTION__)); + return TRUE; + } + } + else if (wdev->AuthMode < Ndis802_11AuthModeWPA) + { + /* Peer AP has RSN capability, but our AP-Client is pre-RSNA. Discard this */ + DBGPRINT(RT_DEBUG_ERROR, ("%s - The authentication mode doesn't match. AP is WPA security but APCLI is not. \n", __FUNCTION__)); + return FALSE; + } + + + /* Recovery user-defined cipher suite */ + pApCliEntry->PairCipher = wdev->WepStatus; + pApCliEntry->GroupCipher = wdev->WepStatus; + pApCliEntry->bMixCipher = FALSE; + + Sanity = 0; + + /* Check AuthMode and WPA_AuthModeAux for matching, in case AP support dual-AuthMode */ + /* WPAPSK */ + if ((WPA_AuthMode == wdev->AuthMode) || + ((WPA_AuthModeAux != Ndis802_11AuthModeOpen) && (WPA_AuthModeAux == wdev->AuthMode))) + { + /* Check cipher suite, AP must have more secured cipher than station setting */ + if (WPA.bMixMode == FALSE) + { + if (wdev->WepStatus != WPA.GroupCipher) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA validate cipher suite error \n")); + return FALSE; + } + } + + /* check group cipher */ + if (wdev->WepStatus < WPA.GroupCipher) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA validate group cipher error \n")); + return FALSE; + } + + /* + check pairwise cipher, skip if none matched + If profile set to AES, let it pass without question. + If profile set to TKIP, we must find one mateched + */ + if ((wdev->WepStatus == Ndis802_11TKIPEnable) && + (wdev->WepStatus != WPA.PairCipher) && + (wdev->WepStatus != WPA.PairCipherAux)) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA validate pairwise cipher error \n")); + return FALSE; + } + + Sanity |= 0x1; + } + /* WPA2PSK */ + else if ((WPA2_AuthMode == wdev->AuthMode) || + ((WPA2_AuthModeAux != Ndis802_11AuthModeOpen) && (WPA2_AuthModeAux == wdev->AuthMode))) + { + /* Check cipher suite, AP must have more secured cipher than station setting */ + if (WPA2.bMixMode == FALSE) + { + if (wdev->WepStatus != WPA2.GroupCipher) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA2 validate cipher suite error \n")); + return FALSE; + } + } + + /* check group cipher */ + if (wdev->WepStatus < WPA2.GroupCipher) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA2 validate group cipher error \n")); + return FALSE; + } + + /* + check pairwise cipher, skip if none matched + If profile set to AES, let it pass without question. + If profile set to TKIP, we must find one mateched + */ + if ((wdev->WepStatus == Ndis802_11TKIPEnable) && + (wdev->WepStatus != WPA2.PairCipher) && + (wdev->WepStatus != WPA2.PairCipherAux)) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - WPA2 validate pairwise cipher error \n")); + return FALSE; + } + + Sanity |= 0x2; + } +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + else if (wdev->AuthMode == Ndis802_11AuthModeWPA3PSK || wdev->AuthMode == Ndis802_11AuthModeOWE) { + +#ifdef APCLI_SAE_SUPPORT + if (WPA2_AuthMode == Ndis802_11AuthModeWPA2PSK && + wdev->AuthMode == Ndis802_11AuthModeWPA3PSK) { + pApCliEntry->pre_mac_entry.AuthMode = Ndis802_11AuthModeWPA2PSK; + Sanity |= 0x2; + } +#endif +#ifdef APCLI_OWE_SUPPORT + /*Disallow TKIP cipher with OWE*/ + if (WPA2_AuthMode == Ndis802_11AuthModeOWE && + pApCliEntry->PairCipher == Ndis802_11TKIPEnable) + Sanity = 0; +#endif +#ifdef APCLI_SAE_SUPPORT + else if ((WPA2_AuthMode == Ndis802_11AuthModeWPA3PSK && + WPA2_AuthModeAux == Ndis802_11AuthModeWPA2PSK) && + (wdev->AuthMode == Ndis802_11AuthModeWPA3PSK)) { + pApCliEntry->pre_mac_entry.AuthMode = Ndis802_11AuthModeWPA3PSK; + Sanity |= 0x2; + } +#endif + + } +#endif + if (Sanity == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("ApCliValidateRSNIE - Validate RSIE Failure \n")); + return FALSE; + } + + + + /*Re-assign pairwise-cipher and group-cipher. Re-build RSNIE. */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) + { + pApCliEntry->GroupCipher = WPA.GroupCipher; + + if (wdev->WepStatus == WPA.PairCipher) + pApCliEntry->PairCipher = WPA.PairCipher; + else if (WPA.PairCipherAux != Ndis802_11WEPDisabled) + pApCliEntry->PairCipher = WPA.PairCipherAux; + else /* There is no PairCipher Aux, downgrade our capability to TKIP */ + pApCliEntry->PairCipher = Ndis802_11TKIPEnable; + } else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) + || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef APCLI_SAE_SUPPORT + || (wdev->AuthMode == Ndis802_11AuthModeWPA3PSK) +#endif +#ifdef APCLI_OWE_SUPPORT + || (wdev->AuthMode == Ndis802_11AuthModeOWE) +#endif + ) { + pApCliEntry->GroupCipher = WPA2.GroupCipher; + + if (wdev->WepStatus == WPA2.PairCipher) + pApCliEntry->PairCipher = WPA2.PairCipher; + else if (WPA2.PairCipherAux != Ndis802_11WEPDisabled) + pApCliEntry->PairCipher = WPA2.PairCipherAux; + else /* There is no PairCipher Aux, downgrade our capability to TKIP */ + pApCliEntry->PairCipher = Ndis802_11TKIPEnable; + } + + /* Set Mix cipher flag */ + if (pApCliEntry->PairCipher != pApCliEntry->GroupCipher) + { + pApCliEntry->bMixCipher = TRUE; + + /* re-build RSNIE */ + /*RTMPMakeRSNIE(pAd, pApCliEntry->AuthMode, pApCliEntry->WepStatus, (idx + MIN_NET_DEVICE_FOR_APCLI)); */ + } + + /* re-build RSNIE */ + RTMPMakeRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, (idx + MIN_NET_DEVICE_FOR_APCLI)); + + return TRUE; +} + + +BOOLEAN ApCliHandleRxBroadcastFrame( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR wdev_idx) +{ + RXINFO_STRUC *pRxInfo = pRxBlk->pRxInfo; + PHEADER_802_11 pHeader = pRxBlk->pHeader; + APCLI_STRUCT *pApCliEntry = NULL; +#ifdef MAC_REPEATER_SUPPORT + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; +#endif /* MAC_REPEATER_SUPPORT */ + + /* + 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->func_tb_idx]; + + /* Filter out Bcast frame which AP relayed for us */ + /* Multicast packet send from AP1 , received by AP2 and send back to AP1, drop this frame */ + if (MAC_ADDR_EQUAL(pHeader->Addr3, pApCliEntry->wdev.if_addr)) + return FALSE; + + if (pEntry->PrivacyFilter != Ndis802_11PrivFilterAcceptAll) + return FALSE; + +#ifdef MAC_REPEATER_SUPPORT + if ((pAd->ApCfg.bMACRepeaterEn) +#ifdef A4_CONN + && (IS_APCLI_A4(pApCliEntry) == FALSE) +#endif /* A4_CONN */ + ) + { + UCHAR isLinkValid; + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, FALSE, pHeader->Addr3, TRUE, &isLinkValid); + if (pReptEntry) + return FALSE; /* give up this frame */ + } +#endif /* MAC_REPEATER_SUPPORT */ + + + +#ifdef A4_CONN + if (IS_ENTRY_A4(pEntry)) { + pRxBlk->pData += LENGTH_802_11_WITH_ADDR4; + pRxBlk->DataSize -= LENGTH_802_11_WITH_ADDR4; + } + else +#endif + + /* 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 ((pRxInfo->MyBss == 0) && (pRxInfo->Decrypted == 0) && (pHeader->FC.Wep == 1)) + { + if (RTMPSoftDecryptionAction(pAd, + (PUCHAR)pHeader, 0, + &pApCliEntry->SharedKey[pRxBlk->key_idx], + pRxBlk->pData, + &(pRxBlk->DataSize)) == NDIS_STATUS_FAILURE) + { + return FALSE; /* give up this frame */ + } + } + pRxInfo->MyBss = 1; + + Indicate_Legacy_Packet(pAd, pRxBlk, wdev_idx); + + return TRUE; +} + + +VOID APCliInstallPairwiseKey( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + UCHAR IfIdx; + UINT8 BssIdx; + + IfIdx = pEntry->func_tb_idx; + BssIdx = pAd->ApCfg.BssidNum + MAX_MESH_NUM + IfIdx; +#ifdef MAC_APCLI_SUPPORT + BssIdx = APCLI_BSSID_IDX + IfIdx; +#endif /* MAC_APCLI_SUPPORT */ + + WPAInstallPairwiseKey(pAd, BssIdx, pEntry, FALSE); +} + + +BOOLEAN APCliInstallSharedKey( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKey, + IN UCHAR KeyLen, + IN UCHAR DefaultKeyIdx, + IN MAC_TABLE_ENTRY *pEntry) +{ + UCHAR IfIdx; + UCHAR GTK_len = 0; + APCLI_STRUCT *apcli_entry; + + + if (!pEntry || !IS_ENTRY_APCLI(pEntry)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : This Entry doesn't exist!!! \n", __FUNCTION__)); + return FALSE; + } + + IfIdx = pEntry->func_tb_idx; + ASSERT((IfIdx < MAX_APCLI_NUM)); + + apcli_entry = &pAd->ApCfg.ApCliTab[IfIdx]; + if (apcli_entry->GroupCipher == Ndis802_11TKIPEnable && KeyLen >= LEN_TKIP_GTK) + GTK_len = LEN_TKIP_GTK; + else if (apcli_entry->GroupCipher == Ndis802_11AESEnable && KeyLen >= LEN_AES_GTK) + GTK_len = LEN_AES_GTK; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : GTK is invalid (GroupCipher=%d, DataLen=%d) !!! \n", + __FUNCTION__, apcli_entry->GroupCipher, KeyLen)); + return FALSE; + } + + /* Update GTK */ + /* set key material, TxMic and RxMic for WPAPSK */ + NdisMoveMemory(apcli_entry->GTK, pKey, GTK_len); + apcli_entry->wdev.DefaultKeyId = DefaultKeyIdx; + + /* Update shared key table */ + NdisZeroMemory(&apcli_entry->SharedKey[DefaultKeyIdx], sizeof(CIPHER_KEY)); + apcli_entry->SharedKey[DefaultKeyIdx].KeyLen = GTK_len; + NdisMoveMemory(apcli_entry->SharedKey[DefaultKeyIdx].Key, pKey, LEN_TK); + if (GTK_len == LEN_TKIP_GTK) + { + NdisMoveMemory(apcli_entry->SharedKey[DefaultKeyIdx].RxMic, pKey + 16, LEN_TKIP_MIC); + NdisMoveMemory(apcli_entry->SharedKey[DefaultKeyIdx].TxMic, pKey + 24, LEN_TKIP_MIC); + } + + /* Update Shared Key CipherAlg */ + apcli_entry->SharedKey[DefaultKeyIdx].CipherAlg = CIPHER_NONE; + if (apcli_entry->GroupCipher == Ndis802_11TKIPEnable) + apcli_entry->SharedKey[DefaultKeyIdx].CipherAlg = CIPHER_TKIP; + else if (apcli_entry->GroupCipher == Ndis802_11AESEnable) + apcli_entry->SharedKey[DefaultKeyIdx].CipherAlg = CIPHER_AES; + +#ifdef MAC_APCLI_SUPPORT + RTMP_ASIC_SHARED_KEY_TABLE(pAd, + APCLI_BSS_BASE + IfIdx, + DefaultKeyIdx, + &apcli_entry->SharedKey[DefaultKeyIdx]); +#endif /* MAC_APCLI_SUPPORT */ + + return TRUE; +} + + +/* + ======================================================================== + + Routine Description: + Verify the support rate for different PHY type + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +// TODO: shiang-6590, modify this due to it's really a duplication of "RTMPUpdateMlmeRate()" in common/mlme.c +VOID ApCliUpdateMlmeRate(RTMP_ADAPTER *pAd, USHORT ifIndex) +{ + UCHAR MinimumRate; + UCHAR ProperMlmeRate; /*= RATE_54; */ + UCHAR i, j, RateIdx = 12; /* 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ + BOOLEAN bMatch = FALSE; + + PAPCLI_STRUCT pApCliEntry = NULL; + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + switch (pAd->CommonCfg.PhyMode) + { + case (WMODE_B): + ProperMlmeRate = RATE_11; + MinimumRate = RATE_1; + break; + case (WMODE_B | WMODE_G): +#ifdef DOT11_N_SUPPORT + case (WMODE_A |WMODE_B | WMODE_G | WMODE_GN | WMODE_AN): + case (WMODE_B | WMODE_G | WMODE_GN): +#ifdef DOT11_VHT_AC + case (WMODE_A |WMODE_B | WMODE_G | WMODE_GN | WMODE_AN | WMODE_AC): +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + if ((pApCliEntry->MlmeAux.SupRateLen == 4) && + (pApCliEntry->MlmeAux.ExtRateLen == 0)) + ProperMlmeRate = RATE_11; /* B only AP */ + else + ProperMlmeRate = RATE_24; + + if (pApCliEntry->MlmeAux.Channel <= 14) + MinimumRate = RATE_1; + else + MinimumRate = RATE_6; + break; + case (WMODE_A): +#ifdef DOT11_N_SUPPORT + case (WMODE_GN): + case (WMODE_G | WMODE_GN): + case (WMODE_A | WMODE_G | WMODE_AN | WMODE_GN): + case (WMODE_A | WMODE_AN): + case (WMODE_AN): +#ifdef DOT11_VHT_AC + case (WMODE_AC): + case (WMODE_AN | WMODE_AC): + case (WMODE_A | WMODE_AN | WMODE_AC): +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + ProperMlmeRate = RATE_24; + MinimumRate = RATE_6; + break; + case (WMODE_B | WMODE_A | WMODE_G): + ProperMlmeRate = RATE_24; + if (pApCliEntry->MlmeAux.Channel <= 14) + MinimumRate = RATE_1; + else + MinimumRate = RATE_6; + break; + default: /* error */ + ProperMlmeRate = RATE_1; + MinimumRate = RATE_1; + break; + } + + for (i = 0; i < pApCliEntry->MlmeAux.SupRateLen; i++) + { + for (j = 0; j < RateIdx; j++) + { + if ((pApCliEntry->MlmeAux.SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) + { + if (j == ProperMlmeRate) + { + bMatch = TRUE; + break; + } + } + } + + if (bMatch) + break; + } + + if (bMatch == FALSE) + { + for (i = 0; i < pApCliEntry->MlmeAux.ExtRateLen; i++) + { + for (j = 0; j < RateIdx; j++) + { + if ((pApCliEntry->MlmeAux.ExtRate[i] & 0x7f) == RateIdTo500Kbps[j]) + { + if (j == ProperMlmeRate) + { + bMatch = TRUE; + break; + } + } + } + + if (bMatch) + break; + } + } + + if (bMatch == FALSE) + ProperMlmeRate = MinimumRate; + + if(!OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED)) + { + pAd->CommonCfg.MlmeRate = MinimumRate; + pAd->CommonCfg.RtsRate = ProperMlmeRate; + if (pAd->CommonCfg.MlmeRate >= RATE_6) + { + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_OFDM; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + } + else + { + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; + pAd->CommonCfg.MlmeTransmit.field.MCS = pAd->CommonCfg.MlmeRate; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MODE = MODE_CCK; + pAd->MacTab.Content[BSS0Mcast_WCID].HTPhyMode.field.MCS = pAd->CommonCfg.MlmeRate; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s():=>MlmeTransmit=0x%x, MinimumRate=%d, ProperMlmeRate=%d\n", + __FUNCTION__, pAd->CommonCfg.MlmeTransmit.word, MinimumRate, ProperMlmeRate)); +} + + +extern INT sta_rx_fwd_hnd(RTMP_ADAPTER *pAd, struct wifi_dev *wdev, PNDIS_PACKET pPacket); +extern INT sta_rx_pkt_allow(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); + +VOID APCli_Init(RTMP_ADAPTER *pAd, RTMP_OS_NETDEV_OP_HOOK *pNetDevOps) +{ +#define APCLI_MAX_DEV_NUM 32 + PNET_DEV new_dev_p; + INT idx; + APCLI_STRUCT *pApCliEntry; + struct wifi_dev *wdev; + + /* sanity check to avoid redundant virtual interfaces are created */ + if (pAd->flg_apcli_init != FALSE) + return; + + + /* init */ + for(idx = 0; idx < MAX_APCLI_NUM; idx++) + pAd->ApCfg.ApCliTab[idx].wdev.if_dev = NULL; + + /* create virtual network interface */ + for (idx = 0; idx < MAX_APCLI_NUM; idx++) + { + UINT32 MC_RowID = 0, IoctlIF = 0; + char *dev_name; + +#ifdef MULTIPLE_CARD_SUPPORT + MC_RowID = pAd->MC_RowID; +#endif /* MULTIPLE_CARD_SUPPORT */ +#ifdef HOSTAPD_SUPPORT + IoctlIF = pAd->IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + + dev_name = get_dev_name_prefix(pAd, INT_APCLI); + new_dev_p = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, INT_APCLI, idx, + sizeof(struct mt_dev_priv), dev_name); + if (!new_dev_p) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Create net_device for %s(%d) fail!\n", + __FUNCTION__, dev_name, idx)); + break; + } +#ifdef HOSTAPD_SUPPORT + pAd->IoctlIF = IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + + pApCliEntry = &pAd->ApCfg.ApCliTab[idx]; +#ifdef APCLI_SAE_SUPPORT + pApCliEntry->sae_cfg_group = SAE_DEFAULT_GROUP; +#endif +#ifdef APCLI_OWE_SUPPORT + pApCliEntry->curr_owe_group = ECDH_GROUP_256; +#endif + pApCliEntry->OpenWEPErrPktChk = FALSE; + pApCliEntry->OpenWEPErrPktCnt = 0; + pApCliEntry->OpenWEPErrMCPktCnt = 0; + wdev = &pApCliEntry->wdev; + wdev->wdev_type = WDEV_TYPE_STA; + wdev->func_dev = pApCliEntry; + wdev->func_idx = idx; + wdev->sys_handle = (void *)pAd; + wdev->if_dev = new_dev_p; + wdev->tx_pkt_allowed = ApCliAllowToSendPacket; + // TODO: shiang-usw, modify this to STASendPacket! + wdev->tx_pkt_handle = APSendPacket; + wdev->wdev_hard_tx = APHardTransmit; + wdev->rx_pkt_allowed = sta_rx_pkt_allow; + wdev->rx_pkt_foward = sta_rx_fwd_hnd; +#ifdef WH_EZ_SETUP +#ifdef IF_UP_DOWN + ApCliCompleteInit(pApCliEntry); +#endif +#endif + + RTMP_OS_NETDEV_SET_PRIV(new_dev_p, pAd); + RTMP_OS_NETDEV_SET_WDEV(new_dev_p, wdev); + if (rtmp_wdev_idx_reg(pAd, wdev) < 0) { + DBGPRINT(RT_DEBUG_ERROR, ("Assign wdev idx for %s failed, free net device!\n", + RTMP_OS_NETDEV_GET_DEVNAME(new_dev_p))); + RtmpOSNetDevFree(new_dev_p); + break; + } + + /* init MAC address of virtual network interface */ + COPY_MAC_ADDR(wdev->if_addr, pAd->CurrentAddress); + +#ifdef MT_MAC + if (pAd->chipCap.hif_type != HIF_MT) + { +#endif /* MT_MAC */ + if (pAd->chipCap.MBSSIDMode >= MBSSID_MODE1) + { + if ((pAd->ApCfg.BssidNum > 0) || (MAX_MESH_NUM > 0)) + { +#ifdef ENHANCE_NEW_MBSSID_MODE + 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; +#endif /* ENHANCE_NEW_MBSSID_MODE */ + /* + Refer to HW definition - + Bit1 of MAC address Byte0 is local administration bit + and should be set to 1 in extended multiple BSSIDs' + Bit3~ of MAC address Byte0 is extended multiple BSSID index. + */ + if (pAd->chipCap.MBSSIDMode == MBSSID_MODE1) + { + /* + Refer to HW definition - + Bit1 of MAC address Byte0 is local administration bit + and should be set to 1 in extended multiple BSSIDs' + Bit3~ of MAC address Byte0 is extended multiple BSSID index. + */ +#ifdef ENHANCE_NEW_MBSSID_MODE + wdev->if_addr[0] &= (MacMask << 2); +#endif /* ENHANCE_NEW_MBSSID_MODE */ + wdev->if_addr[0] |= 0x2; + wdev->if_addr[0] += (((pAd->ApCfg.BssidNum + MAX_MESH_NUM) - 1) << 2); + } +#ifdef ENHANCE_NEW_MBSSID_MODE + else + { + wdev->if_addr[0] |= 0x2; + wdev->if_addr[pAd->chipCap.MBSSIDMode - 1] &= (MacMask); + wdev->if_addr[pAd->chipCap.MBSSIDMode - 1] += ((pAd->ApCfg.BssidNum + MAX_MESH_NUM) - 1); + } +#endif /* ENHANCE_NEW_MBSSID_MODE */ + } + } + else + { + wdev->if_addr[MAC_ADDR_LEN - 1] = (wdev->if_addr[MAC_ADDR_LEN - 1] + pAd->ApCfg.BssidNum + MAX_MESH_NUM) & 0xFF; + } +#ifdef MT_MAC + } + else { + UINT32 Value; + + //TODO: shall we make choosing which byte to be selectable??? + Value = 0x00000000L; + RTMP_IO_READ32(pAd, LPON_BTEIR, &Value);//read BTEIR bit[31:29] for determine to choose which byte to extend BSSID mac address. + Value = Value | ((pAd->chipCap.MBSSIDMode -2) << 29); + + + //Carter, I make apcli interface use HWBSSID1 to go. + //so fill own_mac and BSSID here. + wdev->if_addr[0] |= 0x2; + + switch ((pAd->chipCap.MBSSIDMode -2)) { + case 0x1: /* choose bit[23:20]*/ + //mapping to MBSSID_MODE3 + wdev->if_addr[2] = (wdev->if_addr[2] & 0x0f); + break; + case 0x2: /* choose bit[31:28]*/ + //mapping to MBSSID_MODE4 + wdev->if_addr[3] = (wdev->if_addr[3] & 0x0f); + break; + case 0x3: /* choose bit[39:36]*/ + //mapping to MBSSID_MODE5 + wdev->if_addr[4] = (wdev->if_addr[4] & 0x0f); + break; + case 0x4: /* choose bit [47:44]*/ + //mapping to MBSSID_MODE6 + wdev->if_addr[5] = (wdev->if_addr[5] & 0x0f); + break; + default: /* choose bit[15:12]*/ + //mapping to MBSSID_MODE2 + wdev->if_addr[1] = (wdev->if_addr[1] & 0x0f); + break; + } + +#ifdef MULTI_APCLI_SUPPORT //tmp use byte5 to distinguish, may refine this by setting + wdev->if_addr[MAC_ADDR_LEN - 1] = (wdev->if_addr[MAC_ADDR_LEN - 1] + idx); +#endif /* MULTI_APCLI_SUPPORT */ +// AsicSetDevMac(pAd, wdev->if_addr, 0x1);//set own_mac to HWBSSID1 + //AsicSetBssid(pAd, wdev->if_addr, 0x1); + } +#endif /* MT_MAC */ + + pNetDevOps->priv_flags = INT_APCLI; /* we are virtual interface */ + pNetDevOps->needProtcted = TRUE; + pNetDevOps->wdev = wdev; + NdisMoveMemory(pNetDevOps->devAddr, &wdev->if_addr[0], MAC_ADDR_LEN); + + /* register this device to OS */ + RtmpOSNetDevAttach(pAd->OpMode, new_dev_p, pNetDevOps); + } + + pAd->flg_apcli_init = TRUE; + +} + + +VOID ApCli_Remove(RTMP_ADAPTER *pAd) +{ + UINT index; + struct wifi_dev *wdev; + + for(index = 0; index < MAX_APCLI_NUM; index++) + { + wdev = &pAd->ApCfg.ApCliTab[index].wdev; + if (wdev->if_dev) + { + RtmpOSNetDevProtect(1); + RtmpOSNetDevDetach(wdev->if_dev); + RtmpOSNetDevProtect(0); + + rtmp_wdev_idx_unreg(pAd, wdev); + RtmpOSNetDevFree(wdev->if_dev); + + + /* Clear it as NULL to prevent latter access error. */ + pAd->flg_apcli_init = FALSE; + wdev->if_dev = NULL; + } + } +} + + +BOOLEAN ApCli_Open(RTMP_ADAPTER *pAd, PNET_DEV dev_p) +{ + UCHAR ifIndex; + + APCLI_STRUCT *pApCliEntry; + struct wifi_dev *wdev = NULL; + +#if defined (CONFIG_WIFI_PKT_FWD) + if (wf_fwd_probe_adapter) + wf_fwd_probe_adapter(pAd); +#endif + + for (ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + if (pAd->ApCfg.ApCliTab[ifIndex].wdev.if_dev == dev_p) + { + RTMP_OS_NETDEV_START_QUEUE(dev_p); + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + wdev = &pApCliEntry->wdev; + +#ifdef IF_UP_DOWN + ApCliWaitIfDown(pApCliEntry); +#endif + +#ifdef MULTI_APCLI_SUPPORT + AsicSetDevMac(pAd, wdev->if_addr, (1+ifIndex));//Apcli OwnMac start from HWBSSID 1. +#else /* MULTI_APCLI_SUPPORT */ + AsicSetDevMac(pAd, wdev->if_addr, 1);//Apcli OwnMac start from HWBSSID 1. +#endif /* !MULTI_APCLI_SUPPORT */ + +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef DOT11W_PMF_SUPPORT + pAd->ApCfg.ApCliTab[ifIndex].PmfCfg.MFPC = FALSE; + pAd->ApCfg.ApCliTab[ifIndex].PmfCfg.MFPR = FALSE; + pAd->ApCfg.ApCliTab[ifIndex].PmfCfg.PMFSHA256 = FALSE; + if (((pAd->ApCfg.ApCliTab[ifIndex].wdev.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->ApCfg.ApCliTab[ifIndex].wdev.AuthMode == Ndis802_11AuthModeWPA2PSK) +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + || (pAd->ApCfg.ApCliTab[ifIndex].wdev.AuthMode == Ndis802_11AuthModeWPA3PSK) + || (pAd->ApCfg.ApCliTab[ifIndex].wdev.AuthMode == Ndis802_11AuthModeOWE) +#endif + ) && (pAd->ApCfg.ApCliTab[ifIndex].wdev.WepStatus == Ndis802_11AESEnable)) { + pAd->ApCfg.ApCliTab[ifIndex].PmfCfg.PMFSHA256 = + pAd->ApCfg.ApCliTab[ifIndex].PmfCfg.Desired_PMFSHA256; + + if (pAd->ApCfg.ApCliTab[ifIndex].PmfCfg.Desired_MFPC) { + pAd->ApCfg.ApCliTab[ifIndex].PmfCfg.MFPC = TRUE; + pAd->ApCfg.ApCliTab[ifIndex].PmfCfg.MFPR = + pAd->ApCfg.ApCliTab[ifIndex].PmfCfg.Desired_MFPR; + + if (pAd->ApCfg.ApCliTab[ifIndex].PmfCfg.MFPR) + pAd->ApCfg.ApCliTab[ifIndex].PmfCfg.PMFSHA256 = TRUE; + } + } else if (pAd->ApCfg.ApCliTab[ifIndex].PmfCfg.Desired_MFPC) { + DBGPRINT(RT_DEBUG_ERROR, + ("[PMF]%s:: Security is not WPA2/WPA2PSK AES\n", __func__)); + } + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: MFPC=%d, MFPR=%d, SHA256=%d\n", + __func__, + pAd->ApCfg.ApCliTab[ifIndex].PmfCfg.MFPC, + pAd->ApCfg.ApCliTab[ifIndex].PmfCfg.MFPR, + pAd->ApCfg.ApCliTab[ifIndex].PmfCfg.PMFSHA256)); +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ +#ifdef MWDS + if (wdev->bDefaultMwdsStatus == TRUE) + MWDSEnable(pAd, ifIndex, FALSE, TRUE); +#endif + +#if defined(MAP_SUPPORT) && defined(A4_CONN) + if (IS_MAP_ENABLE(pAd)) + map_a4_init(pAd, wdev->func_idx, FALSE); +#endif + +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + NdisAllocateSpinLock(pAd, &pApCliEntry->SavedPMK_lock); +#endif + +#ifdef WH_EZ_SETUP + if (IS_CONF_EZ_SETUP_ENABLED(wdev)) + ez_start(wdev, FALSE); +#endif /* WH_EZ_SETUP */ + + ApCliIfUp(pAd); + + return TRUE; + } + } + + return FALSE; +} + + +BOOLEAN ApCli_Close(RTMP_ADAPTER *pAd, PNET_DEV dev_p) +{ + UCHAR ifIndex; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx; +#endif /* MAC_REPEATER_SUPPORT */ + struct wifi_dev *wdev; + APCLI_STRUCT *apcli_entry; + + for (ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + apcli_entry = &pAd->ApCfg.ApCliTab[ifIndex]; + wdev = &apcli_entry->wdev; + if (wdev->if_dev == dev_p) + { +#ifdef MWDS + MWDSDisable(pAd, ifIndex, FALSE, TRUE); +#endif /* MWDS */ + +#if defined(MAP_SUPPORT) && defined(A4_CONN) + if (IS_MAP_ENABLE(pAd)) + map_a4_deinit(pAd, wdev->func_idx, FALSE); +#endif + +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + NdisFreeSpinLock(&apcli_entry->SavedPMK_lock); +#endif +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) + if (wf_fwd_delete_repeater_mapping) { + DBGPRINT(RT_DEBUG_OFF, ("%s() 7603 wf_fwd_delete_repeater_mapping.\n", __func__)); + wf_fwd_delete_repeater_mapping(pAd); + } + + if (wf_fwd_remove_adapter) { + DBGPRINT(RT_DEBUG_OFF, ("%s() 7603 wf_fwd_remove_adapter.\n", __func__)); + wf_fwd_remove_adapter(pAd); + } +#endif + + RTMP_OS_NETDEV_STOP_QUEUE(dev_p); + + /* send disconnect-req to sta State Machine. */ + if (apcli_entry->Enable) + { +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + { + for(CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) + { + if (pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliEnable) + { + 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 */ +#ifdef WH_EZ_SETUP +#ifdef IF_UP_DOWN + RTMP_OS_INIT_COMPLETION(&apcli_entry->linkdown_complete); +#endif +#endif + + 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)); +#ifdef WH_EZ_SETUP +#ifdef IF_UP_DOWN + ApCliWaitLinkDown(apcli_entry); + ApCliWaitStateDisconnect(apcli_entry); +#endif +#endif + + //clean CfgApCliBssid + NdisZeroMemory(&(apcli_entry->CfgApCliBssid), MAC_ADDR_LEN); + } +#ifdef WH_EZ_SETUP + if (IS_CONF_EZ_SETUP_ENABLED(wdev)) + ez_stop(wdev); +#ifdef IF_UP_DOWN + ApCliIfDownComplete(apcli_entry); +#endif +#endif /* WH_EZ_SETUP */ + return TRUE; + } + } + + return FALSE; +} + +#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; + RTMP_STRING *pCfgSsid; + BSS_TABLE *pScanTab, *pSsidBssTab; + + BSS_ENTRY *pBssEntry = NULL; + +#ifdef APCLI_OWE_SUPPORT + UCHAR switch_to_owe_channel = 0; + BOOLEAN bupdate_owe_trans = FALSE; + BSS_TABLE *powe_bss_tab = NULL; + APCLI_STRUCT *papcli_entry = NULL; + UCHAR Channel = 0; + struct wifi_dev *wdev = NULL; +#endif + UCHAR tempBuf[20]; + 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->ApCfg.ApCliTab[ifIdx].MlmeAux.SsidBssTab; + pSsidBssTab->BssNr = 0; + + if (pAd->ApCfg.ApCliTab[ifIdx].AutoConnectFlag != TRUE) { + DBGPRINT(RT_DEBUG_TRACE, ("AutoConnect is not Enable.\n")); + return FALSE; + } +#ifdef APCLI_OWE_SUPPORT + papcli_entry = &pAd->ApCfg.ApCliTab[ifIdx]; + if (papcli_entry->wdev.AuthMode == Ndis802_11AuthModeOWE) { + + powe_bss_tab = &papcli_entry->MlmeAux.owe_bss_tab; + powe_bss_tab->BssNr = 0; + + + BssTableInit(powe_bss_tab); + + apcli_reset_owe_parameters(pAd, ifIdx); + + + /*Find out APs with the OWE transition IE and store in owe_bss_tab**/ + for (entryIdx = 0; entryIdx < pScanTab->BssNr; entryIdx++) { + BSS_ENTRY *pBssEntry = &pScanTab->BssEntry[entryIdx]; + + if (pBssEntry->Channel == 0) + continue; + + if ((pBssEntry->owe_trans_ie_len > 0) && + (powe_bss_tab->BssNr < MAX_LEN_OF_BSS_TABLE)) { + NdisMoveMemory(&powe_bss_tab->BssEntry[powe_bss_tab->BssNr++], + pBssEntry, sizeof(BSS_ENTRY)); + + } + } + + if (powe_bss_tab->BssNr < MAX_LEN_OF_BSS_TABLE) + NdisZeroMemory(&powe_bss_tab->BssEntry[powe_bss_tab->BssNr], sizeof(BSS_ENTRY)); + } + +#endif + + /* + Find out APs with the desired SSID. + */ + for (entryIdx=0; entryIdxBssNr;entryIdx++) + { + 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 + */ + +#ifdef APCLI_OWE_SUPPORT + pBssEntry = &pSsidBssTab->BssEntry[pSsidBssTab->BssNr - 1]; + wdev = &papcli_entry->wdev; + + if (wdev->AuthMode == Ndis802_11AuthModeOWE && + (pBssEntry->AuthMode == Ndis802_11AuthModeOpen && pBssEntry->WepStatus == Ndis802_11WEPDisabled)) { + + if (pBssEntry->owe_trans_ie_len > 0) { + + + UCHAR pair_ch = 0; + UCHAR pair_bssid[MAC_ADDR_LEN] = {0}; + UCHAR pair_ssid[MAX_LEN_OF_SSID] = {0}; + UCHAR pair_band = 0; + UCHAR pair_ssid_len = 0; + + + extract_pair_owe_bss_info(pBssEntry->owe_trans_ie, + pBssEntry->owe_trans_ie_len, + pair_bssid, + pair_ssid, + &pair_ssid_len, + &pair_band, + &pair_ch); + + + if (pair_ch != 0) { + /*OWE Entry found ,update OweTransBssid and OweTranSsid*/ + + + /*OWE bss is on different channel*/ + + if (BOARD_IS_5G_ONLY(pAd)) { + + } else { + + + /*Check if the OWE bss is on the same band as the CLI,then check if channel change required*/ + if ((WMODE_2G_ONLY(papcli_entry->wdev.PhyMode) && (pair_ch <= 14)) + || (WMODE_5G_ONLY(papcli_entry->wdev.PhyMode) && (pair_ch > 14))) { + if ((pair_ch != pBssEntry->Channel) || (papcli_entry->wdev.channel != pair_ch)) { + + /*OWE send EVENT to host for OWE indicating different channel*/ + MTWF_LOG(DBG_CAT_CLIENT, CATCLIENT_APCLI, DBG_LVL_ERROR, + ("%s:%d Different channel same band\n", __func__, __LINE__)); + switch_to_owe_channel = pair_ch; + bupdate_owe_trans = TRUE; + wext_send_owe_trans_chan_event(wdev->if_dev, + OID_802_11_OWE_EVT_SAME_BAND_DIFF_CHANNEL, + pair_bssid, + pair_ssid, + &pair_ssid_len, + &pair_band, + &pair_ch); + } else /*Same Channel send directed probe request to OWE BSS*/ + bupdate_owe_trans = TRUE; + + } else { + /*Channel not in group of current band , but entry exists so send event to host to trigger connection on other band*/ + + wext_send_owe_trans_chan_event(wdev->if_dev, + OID_802_11_OWE_EVT_DIFF_BAND, + pair_bssid, + pair_ssid, + &pair_ssid_len, + &pair_band, + &pair_ch); + + } + + } + } else { /*Same Channel send directed probe request to OWE BSS*/ + bupdate_owe_trans = TRUE; + if (papcli_entry->wdev.channel != pBssEntry->Channel) + switch_to_owe_channel = pBssEntry->Channel; + + } + + if (bupdate_owe_trans) { + NdisMoveMemory(&papcli_entry->owe_trans_bssid, pair_bssid, MAC_ADDR_LEN); + NdisMoveMemory(&papcli_entry->owe_trans_ssid, pair_ssid, pair_ssid_len); + papcli_entry->owe_trans_ssid_len = pair_ssid_len; + + NdisMoveMemory(&papcli_entry->owe_trans_open_bssid, pBssEntry->Bssid, MAC_ADDR_LEN); + NdisMoveMemory(&papcli_entry->owe_trans_open_ssid, pBssEntry->Ssid, pBssEntry->SsidLen); + papcli_entry->owe_trans_open_ssid_len = pBssEntry->SsidLen; + + /*Clear last update settings before trying connection with OWE BSS*/ + papcli_entry->pre_mac_entry.AuthMode = 0; + papcli_entry->pre_mac_entry.WepStatus = 0; + papcli_entry->pre_mac_entry.GroupKeyWepStatus = 0; + + /*Delete the Open Bss entry from Scan table*/ + /*because apcli does not ageout scan tab entries*/ + BssTableDeleteEntry(pScanTab, pBssEntry->Bssid, pBssEntry->Channel); + } + } + } +#endif + +#ifdef APCLI_OWE_SUPPORT + if (papcli_entry->wdev.AuthMode == Ndis802_11AuthModeOWE && (pBssEntry->owe_trans_ie_len > 0)) { + if (switch_to_owe_channel > 0) + Channel = switch_to_owe_channel; + } +#endif + + + if (pAd->CommonCfg.Channel != pSsidBssTab->BssEntry[pSsidBssTab->BssNr - 1].Channel +#ifdef APCLI_OWE_SUPPORT + || Channel != 0 +#endif + ) + { +#ifdef APCLI_OWE_SUPPORT + if (Channel != 0) + sprintf(tempBuf, "%d", Channel); + else +#endif + sprintf(tempBuf, "%d", pSsidBssTab->BssEntry[pSsidBssTab->BssNr - 1].Channel); + DBGPRINT(RT_DEBUG_TRACE, ("Switch to channel :%s\n", tempBuf)); +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(&pAd->ApCfg.ApCliTab[ifIdx].wdev)) + rtmp_set_channel(pAd, &pAd->ApCfg.ApCliTab[ifIdx].wdev, + pSsidBssTab->BssEntry[pSsidBssTab->BssNr - 1].Channel); + else +#endif + 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; + +#ifdef AP_PARTIAL_SCAN_SUPPORT + if (pAd->ApCfg.bPartialScanning == TRUE) + return; +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("---> ApCliSwitchCandidateAP()\n")); + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIdx]; + pSsidBssTab = &pApCliEntry->MlmeAux.SsidBssTab; + + if (pAd->ApCfg.ApCliTab[ifIdx].AutoConnectFlag != TRUE) { + DBGPRINT(RT_DEBUG_TRACE, ("AutoConnect is not Enable.\n")); + return; + } + + /* + 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)); +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(&pAd->ApCfg.ApCliTab[ifIdx].wdev)) + rtmp_set_channel(pAd, &pAd->ApCfg.ApCliTab[ifIdx].wdev, + pSsidBssTab->BssEntry[lastEntryIdx].Channel); + else +#endif + 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->wdev.AuthMode; + NDIS_802_11_WEP_STATUS tempWEPstatus = pApCliEntry->wdev.WepStatus; + + DBGPRINT(RT_DEBUG_TRACE, ("ApcliAuthMode=%s, AuthMode=%s, AuthModeAux=%s, ApcliWepStatus=%s, WepStatus=%s, GroupCipher=%s, PairCipher=%s, \n", + GetAuthMode(pApCliEntry->wdev.AuthMode), + GetAuthMode(AuthMode), + GetAuthMode(AuthModeAux), + GetEncryptType(pApCliEntry->wdev.WepStatus), + GetEncryptType(WEPstatus), + GetEncryptType(WPA.GroupCipher), + GetEncryptType(WPA.PairCipher))); + + if (tempAuthMode <= Ndis802_11AuthModeAutoSwitch) + { + tempAuthMode = Ndis802_11AuthModeOpen; + return ((tempAuthMode == AuthMode || + tempAuthMode == AuthModeAux) && + (tempWEPstatus == WEPstatus) ); + } + else if (tempAuthMode <= Ndis802_11AuthModeWPA2PSK) + { + return ((tempAuthMode == AuthMode || + tempAuthMode == AuthModeAux) && + (tempWEPstatus == WPA.GroupCipher|| + tempWEPstatus == WPA.PairCipher) ); + } +#ifdef APCLI_SAE_SUPPORT + else if (tempAuthMode == Ndis802_11AuthModeWPA3PSK) { + return ((tempAuthMode == AuthMode || + tempAuthMode == AuthModeAux || + AuthMode == Ndis802_11AuthModeWPA2PSK) && + (tempWEPstatus == WPA.GroupCipher || + tempWEPstatus == WPA.PairCipher)); + } +#endif +#ifdef APCLI_OWE_SUPPORT + else if (tempAuthMode == Ndis802_11AuthModeOWE) { + return ((tempAuthMode == AuthMode || + tempAuthMode == AuthModeAux || + AuthMode == Ndis802_11AuthModeOpen) && + (tempWEPstatus == WPA.GroupCipher || + tempWEPstatus == WPA.PairCipher)); + } +#endif + + else { + /* not supported cases */ + return FALSE; + } + +} +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + +/* + =================================================== + + Description: + + When root AP is Open WEP, it will cause a fake connection state if user keys in + wrong password. So we need this to fix the issue. + + Arguments: + pAd: pointer to our adapter + pRxBlk: carry necessary packet info 802.11 format + bSuccessPkt: see if it is a successfully decrypted packet. + Note: + =================================================== +*/ +VOID ApCliRxOpenWEPCheck( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk, + IN BOOLEAN bSuccessPkt) +{ + APCLI_STRUCT *pApCliEntry = NULL; + MAC_TABLE_ENTRY *pEntry = NULL; + STA_TR_ENTRY *tr_entry; + HEADER_802_11 *pHeader = NULL; + struct rxd_base_struct *rxd_base = NULL; + int FirstWcid = 1, idx, wcid; + BOOLEAN isMCPkt = FALSE; + + if(!pRxBlk) + return; + + if(!bSuccessPkt) + { + rxd_base = (struct rxd_base_struct *)pRxBlk->rmac_info; + idx = rxd_base->rxd_2.wlan_idx; + } + else + idx = pRxBlk->wcid; + wcid = idx; + + if((wcid >= WCID_ALL) || (wcid == MCAST_WCID)) + return; + +#ifdef MT_MAC + if(pAd->chipCap.hif_type == HIF_MT) + { +#ifdef MULTI_APCLI_SUPPORT + if((wcid >= APCLI_MCAST_WCID(0))) + wcid = (idx - APCLI_MCAST_WCID(0))+FirstWcid; +#else + if((wcid >= APCLI_MCAST_WCID)) + wcid = (idx - APCLI_MCAST_WCID)+FirstWcid; +#endif + isMCPkt = TRUE; + } +#endif + + if(!VALID_WCID(wcid)) + { + DBGPRINT(RT_DEBUG_OFF, ("(%s:%d): Invalid wcid (%d) found! From MCPkt: %d\n", + __func__,__LINE__,wcid,isMCPkt)); + return; + } + + pEntry = &pAd->MacTab.Content[wcid]; + if(!pEntry || !IS_ENTRY_APCLI(pEntry)) + return; + + if(!VALID_TR_WCID(pEntry->wcid)) + return; + + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + if(!tr_entry) + return; + + if (pEntry->func_tb_idx >= MAX_APCLI_NUM) { + DBGPRINT(RT_DEBUG_OFF, ("(%s:%d): func_tb_idx over MAX_APCLI_NUM!\n",__func__,__LINE__)); + return; + } + + pApCliEntry = &pAd->ApCfg.ApCliTab[pEntry->func_tb_idx]; + if(!pApCliEntry || + !pApCliEntry->Valid || + !pApCliEntry->OpenWEPErrPktChk) + return; + + if(bSuccessPkt) + { + pHeader = pRxBlk->pHeader; + if( pHeader && + (pHeader->FC.Type == FC_TYPE_DATA) && + (pHeader->FC.SubType != SUBTYPE_DATA_NULL) && + (pHeader->FC.SubType != SUBTYPE_QOS_NULL) && + (pRxBlk->DataSize > 0)) + { + pApCliEntry->OpenWEPErrPktCnt = 0; + pApCliEntry->OpenWEPErrMCPktCnt = 0; + pApCliEntry->OpenWEPErrPktChk = FALSE; + } + } + else + { + pApCliEntry->OpenWEPErrPktCnt++; + if(pApCliEntry->OpenWEPErrPktCnt >= OPENWEP_ERRPKT_MAX_COUNT) + { + DBGPRINT(RT_DEBUG_OFF, ("(%s:%d): Stop Open WEP check!\n",__func__,__LINE__)); + tr_entry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + pApCliEntry->OpenWEPErrPktChk = FALSE; + } + if(isMCPkt) pApCliEntry->OpenWEPErrMCPktCnt++; + } +} +#ifdef ROAMING_ENHANCE_SUPPORT +#ifndef ETH_HDR_LEN +#define ETH_HDR_LEN 14 /* dstMac(6) + srcMac(6) + protoType(2) */ +#endif + +#ifndef ETH_P_VLAN +#define ETH_P_VLAN 0x8100 /* 802.1q (VLAN) */ +#endif + +#ifndef VLAN_ETH_HDR_LEN +#define VLAN_ETH_HDR_LEN (ETH_HDR_LEN+4) /* 4 for h_vlan_TCI and h_vlan_encapsulated_proto */ +#endif + +#ifndef IP_HDR_SRC_OFFSET +#define IP_HDR_SRC_OFFSET 12 /* shift 12 for IP header len. */ +#endif + +#ifndef ARP_OP_OFFSET +#define ARP_OP_OFFSET 6 /* shift 6 len for ARP. */ +#endif + +BOOLEAN ApCliDoRoamingRefresh( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN PNDIS_PACKET pRxPacket, + IN struct wifi_dev *wdev, + IN UCHAR *DestAddr) +{ + UCHAR *pPktHdr = NULL, *pLayerHdr = NULL; + UINT16 ProtoType; + BOOLEAN bUnicastARPReq = FALSE, bSendARP = FALSE; + PNDIS_PACKET pPacket = NULL; + struct sk_buff *skb = NULL; + + if(!pRxPacket || !wdev) + return FALSE; + + /* Get the upper layer protocol type of this 802.3 pkt */ + pPktHdr = GET_OS_PKT_DATAPTR(pRxPacket); + ProtoType = OS_NTOHS(get_unaligned((PUINT16)(pPktHdr + (ETH_HDR_LEN-2)))); + if (ProtoType == ETH_P_VLAN) + { + pLayerHdr = (pPktHdr + VLAN_ETH_HDR_LEN); + ProtoType = OS_NTOHS(get_unaligned((PUINT16)pLayerHdr)); + } + else + pLayerHdr = (pPktHdr + ETH_HDR_LEN); + + if(ProtoType == ETH_P_ARP) + { + UINT16 OpType; + OpType = OS_NTOHS(get_unaligned((PUINT16)(pLayerHdr+ARP_OP_OFFSET))); /* ARP Operation */ + if(OpType == 0x0001) // ARP Request + { + if(DestAddr && !MAC_ADDR_IS_GROUP(DestAddr)) + bUnicastARPReq = TRUE; + + if(bUnicastARPReq) + { + skb = skb_copy(RTPKT_TO_OSPKT(pRxPacket), GFP_ATOMIC); + if(skb) + { + bSendARP = TRUE; + skb->dev = wdev->if_dev; + pPacket = OSPKT_TO_RTPKT(skb); + NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket), BROADCAST_ADDR, MAC_ADDR_LEN); + } + } + else + pEntry->bRoamingRefreshDone = TRUE; + // MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_OFF, + // ("Got original ARP Request(Unicast:%d) from wireless STA!\n",bUnicastARPReq)); + } + } + else if(ProtoType == ETH_P_IP) + { + UINT32 SrcIP = 0; + NdisMoveMemory(&SrcIP, (pLayerHdr + IP_HDR_SRC_OFFSET), 4); + if(SrcIP != 0) + { + bSendARP = TRUE; + pPacket = (PNDIS_PACKET)arp_create(ARPOP_REQUEST, ETH_P_ARP, SrcIP, wdev->if_dev, + SrcIP, BROADCAST_ADDR, pEntry->Addr, BROADCAST_ADDR); + } + } + + if(bSendARP && pPacket) + { +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) + /*Avishad Not needed*/ + //set_wf_fwd_cb(pAd, pPacket, wdev); +#endif /* CONFIG_WIFI_PKT_FWD */ + RtmpOsPktProtocolAssign(pPacket); + RtmpOsPktRcvHandle(pPacket); + pEntry->bRoamingRefreshDone = TRUE; + //MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_OFF,("Send roaming refresh done!\n")); + return TRUE; + } + + return FALSE; +} +#endif /* ROAMING_ENHANCE_SUPPORT */ +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef DOT11W_PMF_SUPPORT +/* chane the cmd depend on security mode first, and update to run time flag*/ +INT Set_ApCliPMFMFPC_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj; + + if (strlen(arg) == 0) + return FALSE; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (simple_strtol(arg, 0, 10)) + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.Desired_MFPC = TRUE; + else { + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.Desired_MFPC = FALSE; + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.MFPC = FALSE; + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.MFPR = FALSE; + } + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: Desired MFPC=%d\n", + __func__, pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.Desired_MFPC)); + + if (((pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev.AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef APCLI_SAE_SUPPORT + || (pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev.AuthMode == Ndis802_11AuthModeWPA3PSK) +#endif +#ifdef APCLI_OWE_SUPPORT + || (pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev.AuthMode == Ndis802_11AuthModeOWE) +#endif + ) && (pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev.WepStatus == Ndis802_11AESEnable)) { + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.PMFSHA256 = + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.Desired_PMFSHA256; + if (pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.Desired_MFPC) { + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.MFPC = TRUE; + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.MFPR = + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.Desired_MFPR; + + if (pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.MFPR) + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.PMFSHA256 = TRUE; + } + } else if (pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.Desired_MFPC) + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: Security is not WPA2/WPA2PSK AES\n", __func__)); + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: MFPC=%d, MFPR=%d, SHA256=%d\n", + __func__, + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.MFPC, + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.MFPR, + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.PMFSHA256)); + + return TRUE; +} + +/* chane the cmd depend on security mode first, and update to run time flag*/ +INT Set_ApCliPMFMFPR_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj; + + if (strlen(arg) == 0) + return FALSE; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (simple_strtol(arg, 0, 10)) + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.Desired_MFPR = TRUE; + else { + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.Desired_MFPR = FALSE; + + /* only close the MFPR */ + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.MFPR = FALSE; + } + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: Desired MFPR=%d\n", + __func__, pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.Desired_MFPR)); + + if (((pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev.AuthMode == Ndis802_11AuthModeWPA2) || + (pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev.AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef APCLI_SAE_SUPPORT + || (pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev.AuthMode == Ndis802_11AuthModeWPA3PSK) +#endif +#ifdef APCLI_OWE_SUPPORT + || (pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev.AuthMode == Ndis802_11AuthModeOWE) +#endif + ) + && (pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev.WepStatus == Ndis802_11AESEnable)) { + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.PMFSHA256 = + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.Desired_PMFSHA256; + if (pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.Desired_MFPC) { + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.MFPC = TRUE; + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.MFPR = + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.Desired_MFPR; + + if (pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.MFPR) + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.PMFSHA256 = TRUE; + } + } else if (pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.Desired_MFPC) + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: Security is not WPA2/WPA2PSK AES\n", __func__)); + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: MFPC=%d, MFPR=%d, SHA256=%d\n", + __func__, pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.MFPC, + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.MFPR, + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.PMFSHA256)); + + return TRUE; +} + +INT Set_ApCliPMFSHA256_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj; + + if (strlen(arg) == 0) + return FALSE; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (simple_strtol(arg, 0, 10)) + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.Desired_PMFSHA256 = TRUE; + else + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.Desired_PMFSHA256 = FALSE; + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: Desired PMFSHA256=%d\n", + __func__, pAd->ApCfg.ApCliTab[pObj->ioctl_if].PmfCfg.Desired_PMFSHA256)); + + return TRUE; +} +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + +#ifdef APCLI_SAE_SUPPORT +INT set_apcli_sae_group_proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj; + UCHAR *pSaeCfgGroup = NULL; + UCHAR group = 0; + + if (strlen(arg) == 0) + return FALSE; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + pSaeCfgGroup = &pAd->ApCfg.ApCliTab[pObj->ioctl_if].sae_cfg_group; + + + group = simple_strtol(arg, 0, 10); + + if ((group == 19) || (group == 20)) { + *pSaeCfgGroup = (UCHAR) group; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("[SAE]%s:: Set group=%d\n", + __func__, group)); + + } else { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("[SAE]%s:: group=%d not supported\n", + __func__, group)); + + return FALSE; + } + return TRUE; +} +#endif/*APCLI_SAE_SUPPORT*/ + + + +#ifdef APCLI_OWE_SUPPORT +INT set_apcli_owe_group_proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj; + UCHAR group = 0; + UCHAR *pcurr_group = NULL; + + if (strlen(arg) == 0) + return FALSE; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + pcurr_group = &pAd->ApCfg.ApCliTab[pObj->ioctl_if].curr_owe_group; + + + group = simple_strtol(arg, 0, 10); +/*OWE-currently allowing configuration of groups 19(mandatory) and 20(optional) */ + if ((group == 19) || (group == 20)) { + *pcurr_group = (UCHAR) group; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("[OWE]%s:: Set group=%d\n", + __func__, group)); + + } else { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("[OWE]%s:: group=%d not supported\n", + __func__, group)); + + return FALSE; + } + return TRUE; +} +#endif/*APCLI_SAE_SUPPORT*/ + + +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) +INT set_apcli_del_pmkid_list( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj; + UCHAR action = 0; + + if (strlen(arg) == 0) + return FALSE; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + + action = simple_strtol(arg, 0, 10); + +/*Delete all pmkid list associated with this ApCli Interface*/ + if (action == 1) { + apcli_delete_pmkid_cache_all(pAd, pObj->ioctl_if); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s:: Delete PMKID list (%d)\n", + __func__, action)); + + } + return TRUE; +} + + + +INT apcli_add_pmkid_cache( + IN PRTMP_ADAPTER pAd, + IN UCHAR *paddr, + IN UCHAR *pmkid, + IN UCHAR *pmk, + IN UINT8 pmk_len, + IN UINT8 if_index +#ifdef MAC_REPEATER_SUPPORT + , IN UINT8 cli_idx +#endif + ) + +{ + PAPCLI_STRUCT papcli_entry = NULL; +#ifdef MAC_REPEATER_SUPPORT + PREPEATER_CLIENT_ENTRY preptcli_entry = NULL; +#endif + INT cached_idx; + PBSSID_INFO psaved_pmk = NULL; + PUINT psaved_pmk_num = NULL; + UCHAR update_pmkid = FALSE; + VOID *psaved_pmk_lock = NULL; + + +#ifdef MAC_REPEATER_SUPPORT + if (cli_idx != 0xff) { + preptcli_entry = &pAd->ApCfg.ApCliTab[if_index].RepeaterCli[cli_idx]; + papcli_entry = &pAd->ApCfg.ApCliTab[if_index]; + psaved_pmk = (PBSSID_INFO)&preptcli_entry->SavedPMK[0]; + psaved_pmk_num = &preptcli_entry->SavedPMKNum; + psaved_pmk_lock = (VOID *)&preptcli_entry->SavedPMK_lock; + + + } else +#endif + { + papcli_entry = &pAd->ApCfg.ApCliTab[if_index]; + psaved_pmk = (PBSSID_INFO)&papcli_entry->SavedPMK[0]; + psaved_pmk_num = &papcli_entry->SavedPMKNum; + psaved_pmk_lock = (VOID *)&papcli_entry->SavedPMK_lock; + } + + cached_idx = apcli_search_pmkid_cache(pAd, paddr, if_index +#ifdef MAC_REPEATER_SUPPORT + , cli_idx +#endif + ); + + if (psaved_pmk_lock) + NdisAcquireSpinLock(psaved_pmk_lock); + + + if (cached_idx != INVALID_PMKID_IDX) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_OFF, + ("%s :PMKID found, %d\n", __func__, cached_idx)); + } else { +/* Find free cache entry */ + for (cached_idx = 0; cached_idx < PMKID_NO; cached_idx++) { + if (psaved_pmk[cached_idx].Valid == FALSE) + break; + } + + if (cached_idx < PMKID_NO) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_OFF, + ("Free Cache entry found,cached_idx %d\n", cached_idx)); + *psaved_pmk_num = *psaved_pmk_num + 1; + + } else { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_OFF, + ("cache full, overwrite cached_idx 0\n")); + + cached_idx = 0; + } + update_pmkid = TRUE; + } + + if (update_pmkid == TRUE) { + psaved_pmk[cached_idx].Valid = TRUE; + COPY_MAC_ADDR(&psaved_pmk[cached_idx].BSSID, paddr); + NdisMoveMemory(&psaved_pmk[cached_idx].PMKID, pmkid, LEN_PMKID); + NdisMoveMemory(&psaved_pmk[cached_idx].PMK, pmk, pmk_len); + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s(): add %02x:%02x:%02x:%02x:%02x:%02x cache(%d)\n", + __func__, PRINT_MAC(paddr), cached_idx)); + } + + if (psaved_pmk_lock) + NdisReleaseSpinLock(psaved_pmk_lock); + + + return cached_idx; +} + + +INT apcli_search_pmkid_cache( + IN PRTMP_ADAPTER pAd, + IN UCHAR *paddr, + IN UCHAR if_index +#ifdef MAC_REPEATER_SUPPORT + , IN UINT8 cli_idx +#endif + ) + +{ + INT i = 0; + PBSSID_INFO psaved_pmk = NULL; + PAPCLI_STRUCT papcli_entry = NULL; +#ifdef MAC_REPEATER_SUPPORT + PREPEATER_CLIENT_ENTRY preptcli_entry = NULL; +#endif + VOID *psaved_pmk_lock = NULL; + + + +#ifdef MAC_REPEATER_SUPPORT + if (cli_idx != 0xff) { + preptcli_entry = &pAd->ApCfg.ApCliTab[if_index].RepeaterCli[cli_idx]; + papcli_entry = &pAd->ApCfg.ApCliTab[if_index]; + psaved_pmk = (PBSSID_INFO)&preptcli_entry->SavedPMK[0]; + psaved_pmk_lock = (VOID *)&preptcli_entry->SavedPMK_lock; + + + } else +#endif + { + papcli_entry = &pAd->ApCfg.ApCliTab[if_index]; + psaved_pmk = (PBSSID_INFO)&papcli_entry->SavedPMK[0]; + psaved_pmk_lock = (VOID *)&papcli_entry->SavedPMK_lock; + + } + + if (psaved_pmk_lock) + NdisAcquireSpinLock(psaved_pmk_lock); + + for (i = 0; i < PMKID_NO; i++) { + if ((psaved_pmk[i].Valid == TRUE) + && MAC_ADDR_EQUAL(&psaved_pmk[i].BSSID, paddr)) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s():%02x:%02x:%02x:%02x:%02x:%02x cache(%d)\n", + __func__, PRINT_MAC(paddr), i)); + break; + } + } + + if (psaved_pmk_lock) + NdisReleaseSpinLock(psaved_pmk_lock); + + if (i >= PMKID_NO) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s(): not found\n", __func__)); + return INVALID_PMKID_IDX; + } + + return i; +} + + + +VOID apcli_delete_pmkid_cache( + IN PRTMP_ADAPTER pAd, + IN UCHAR *paddr, + IN UCHAR if_index +#ifdef MAC_REPEATER_SUPPORT + , IN UINT8 cli_idx +#endif + ) + +{ + + INT cached_idx; + PBSSID_INFO psaved_pmk = NULL; + PAPCLI_STRUCT papcli_entry = NULL; +#ifdef MAC_REPEATER_SUPPORT + PREPEATER_CLIENT_ENTRY preptcli_entry = NULL; +#endif + VOID *psaved_pmk_lock = NULL; + PUINT psaved_pmk_num = NULL; + + +#ifdef MAC_REPEATER_SUPPORT + if (cli_idx != 0xff) { + preptcli_entry = &pAd->ApCfg.ApCliTab[if_index].RepeaterCli[cli_idx]; + psaved_pmk = (PBSSID_INFO)&preptcli_entry->SavedPMK[0]; + psaved_pmk_num = &preptcli_entry->SavedPMKNum; + psaved_pmk_lock = (VOID *)&preptcli_entry->SavedPMK_lock; + + + } else +#endif + { + papcli_entry = &pAd->ApCfg.ApCliTab[if_index]; + psaved_pmk = (PBSSID_INFO)&papcli_entry->SavedPMK[0]; + psaved_pmk_num = &papcli_entry->SavedPMKNum; + psaved_pmk_lock = (VOID *)&papcli_entry->SavedPMK_lock; + + } + + + cached_idx = apcli_search_pmkid_cache(pAd, paddr, if_index +#ifdef MAC_REPEATER_SUPPORT + , cli_idx +#endif + ); + + if (cached_idx != INVALID_PMKID_IDX) { + + if (psaved_pmk_lock) + NdisAcquireSpinLock(psaved_pmk_lock); + + if (psaved_pmk[cached_idx].Valid == TRUE) { + psaved_pmk[cached_idx].Valid = FALSE; + + if (*psaved_pmk_num) + *psaved_pmk_num = *psaved_pmk_num - 1; + } + + if (psaved_pmk_lock) + NdisReleaseSpinLock(psaved_pmk_lock); + + + } + +} + +VOID apcli_delete_pmkid_cache_all( + IN PRTMP_ADAPTER pAd, + IN UCHAR if_index) +{ + + INT cli_idx = 0; + INT cached_idx; + PBSSID_INFO psaved_pmk = NULL; + PAPCLI_STRUCT papcli_entry = NULL; +#ifdef MAC_REPEATER_SUPPORT + PREPEATER_CLIENT_ENTRY preptcli_entry = NULL; +#endif +#ifdef APCLI_SAE_SUPPORT + SAE_INSTANCE *pSaeIns = NULL; + SAE_CFG *pSaeCfg = NULL; + UINT32 i; + UINT32 ins_cnt = 0; +#endif + + VOID *psaved_pmk_lock = NULL; + PUINT psaved_pmk_num = NULL; + + + + papcli_entry = &pAd->ApCfg.ApCliTab[if_index]; + psaved_pmk = (PBSSID_INFO)&papcli_entry->SavedPMK[0]; + psaved_pmk_num = &papcli_entry->SavedPMKNum; + psaved_pmk_lock = (VOID *)&papcli_entry->SavedPMK_lock; + +#ifdef APCLI_SAE_SUPPORT + pSaeCfg = &pAd->SaeCfg; +/*Delete all SAE instances for this ApCli Interface*/ + NdisAcquireSpinLock(&pSaeCfg->sae_cfg_lock); + + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) { + + if (pSaeCfg->sae_ins[i].valid == FALSE) + continue; + + if (RTMPEqualMemory(pSaeCfg->sae_ins[i].own_mac, papcli_entry->wdev.if_addr, MAC_ADDR_LEN)) { + pSaeIns = &pSaeCfg->sae_ins[i]; + if (pSaeIns != NULL && (pSaeIns->valid == TRUE)) { + NdisReleaseSpinLock(&pSaeCfg->sae_cfg_lock); + delete_sae_instance(pSaeIns); + NdisAcquireSpinLock(&pSaeCfg->sae_cfg_lock); + } + } + + ins_cnt++; + + if (ins_cnt == pSaeCfg->total_ins) + break; + } + + NdisReleaseSpinLock(&pSaeCfg->sae_cfg_lock); +#endif + + + +/*Delete ApCli PMKID list*/ + for (cached_idx = 0; cached_idx < PMKID_NO; cached_idx++) { + + if (psaved_pmk_lock) + NdisAcquireSpinLock(psaved_pmk_lock); + + if (psaved_pmk[cached_idx].Valid == TRUE) { + psaved_pmk[cached_idx].Valid = FALSE; + + if (*psaved_pmk_num) + *psaved_pmk_num = *psaved_pmk_num - 1; + + } + + if (psaved_pmk_lock) + NdisReleaseSpinLock(psaved_pmk_lock); + + } +/*Delete PMKID list for MacRepeater linked with ApCli */ + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn == TRUE) { + + for (cli_idx = 0; cli_idx < MAX_EXT_MAC_ADDR_SIZE; cli_idx++) { + + preptcli_entry = &pAd->ApCfg.ApCliTab[if_index].RepeaterCli[cli_idx]; + + if (preptcli_entry && (preptcli_entry->CliValid == TRUE) && + (preptcli_entry->MatchApCliIdx == papcli_entry->wdev.func_idx)) { + +#ifdef APCLI_SAE_SUPPORT + /*Delete all SAE instances for this Rept entry*/ + NdisAcquireSpinLock(&pSaeCfg->sae_cfg_lock); + ins_cnt = 0; + + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) { + if (pSaeCfg->sae_ins[i].valid == FALSE) + continue; + + if (RTMPEqualMemory(pSaeCfg->sae_ins[i].own_mac, + preptcli_entry->CurrentAddress, MAC_ADDR_LEN)) { + pSaeIns = &pSaeCfg->sae_ins[i]; + if (pSaeIns != NULL && (pSaeIns->valid == TRUE)) { + NdisReleaseSpinLock(&pSaeCfg->sae_cfg_lock); + delete_sae_instance(pSaeIns); + NdisAcquireSpinLock(&pSaeCfg->sae_cfg_lock); + + } + } + + ins_cnt++; + + if (ins_cnt == pSaeCfg->total_ins) + break; + } + + NdisReleaseSpinLock(&pSaeCfg->sae_cfg_lock); +#endif + psaved_pmk = (PBSSID_INFO)&preptcli_entry->SavedPMK[0]; + psaved_pmk_num = &preptcli_entry->SavedPMKNum; + psaved_pmk_lock = (VOID *)&preptcli_entry->SavedPMK_lock; + + + for (cached_idx = 0; cached_idx < PMKID_NO; cached_idx++) { + + if (psaved_pmk_lock) + NdisAcquireSpinLock(psaved_pmk_lock); + + if (psaved_pmk[cached_idx].Valid == TRUE) { + psaved_pmk[cached_idx].Valid = FALSE; + + if (*psaved_pmk_num) + *psaved_pmk_num = *psaved_pmk_num - 1; + } + + if (psaved_pmk_lock) + NdisReleaseSpinLock(psaved_pmk_lock); + } + + } + } + } +#endif + +} +#endif + + +#ifdef APCLI_OWE_SUPPORT + +VOID apcli_reset_owe_parameters( + IN PRTMP_ADAPTER pAd, + IN UCHAR if_index) { + + PAPCLI_STRUCT papcli_entry = NULL; + + papcli_entry = &pAd->ApCfg.ApCliTab[if_index]; + + /*OWE Trans reset the OWE trans bssid and ssid*/ + + if (papcli_entry + && papcli_entry->wdev.AuthMode == Ndis802_11AuthModeOWE + && (papcli_entry->owe_trans_ssid_len > 0)) { + NdisZeroMemory(papcli_entry->owe_trans_bssid, MAC_ADDR_LEN); + NdisZeroMemory(papcli_entry->owe_trans_ssid, MAX_LEN_OF_SSID); + papcli_entry->owe_trans_ssid_len = 0; + + NdisZeroMemory(papcli_entry->owe_trans_open_bssid, MAC_ADDR_LEN); + NdisZeroMemory(papcli_entry->owe_trans_open_ssid, MAX_LEN_OF_SSID); + papcli_entry->owe_trans_open_ssid_len = 0; + } +} + +#endif + + +#endif /* APCLI_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_apcli_inf.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_apcli_inf.c new file mode 100644 index 000000000..73add46ac --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_apcli_inf.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-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 + + 4. ApCli index (0) of different tx packet is assigned in + + 5. ApCli index (0) of different interface is got in APHardTransmit() by using + + 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(VOID *pAd, PNET_DEV main_dev_p) +{ + RTMP_OS_NETDEV_OP_HOOK netDevOpHook; + + /* init operation functions */ + NdisZeroMemory(&netDevOpHook, sizeof(RTMP_OS_NETDEV_OP_HOOK)); + netDevOpHook.open = ApCli_VirtualIF_Open; + netDevOpHook.stop = ApCli_VirtualIF_Close; + netDevOpHook.xmit = rt28xx_send_packets; + netDevOpHook.ioctl = rt28xx_ioctl; + RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_APC_INIT, + 0, &netDevOpHook, 0); +} + +/* +======================================================================== +Routine Description: + Open a virtual network interface. + +Arguments: + dev_p which WLAN network interface + +Return Value: + 0: open successfully + otherwise: open fail + +Note: +======================================================================== +*/ +INT ApCli_VirtualIF_Open(PNET_DEV dev_p) +{ + VOID *pAd; + + /* increase MODULE use count */ + RT_MOD_INC_USE_COUNT(); + + 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; + +#ifdef CONFIG_RA_HW_NAT_WIFI_NEW_ARCH + RT_MOD_HNAT_REG(dev_p); +#endif + + + + RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_APC_OPEN, 0, dev_p, 0); + +#ifdef MTFWD + RTMP_OS_NETDEV_CARRIER_OFF(dev_p); +#endif + + return 0; +} + + +/* +======================================================================== +Routine Description: + Close a virtual network interface. + +Arguments: + dev_p which WLAN network interface + +Return Value: + 0: close successfully + otherwise: close fail + +Note: +======================================================================== +*/ +INT ApCli_VirtualIF_Close(PNET_DEV dev_p) +{ + VOID *pAd; + + pAd = RTMP_OS_NETDEV_GET_PRIV(dev_p); + ASSERT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: ===> %s\n", __FUNCTION__, RTMP_OS_NETDEV_GET_DEVNAME(dev_p))); + + + RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_APC_CLOSE, 0, dev_p, 0); + +#ifdef CONFIG_RA_HW_NAT_WIFI_NEW_ARCH + RT_MOD_HNAT_DEREG(dev_p); +#endif + + VIRTUAL_IF_DOWN(pAd); + + RT_MOD_DEC_USE_COUNT(); + + return 0; +} + + +/* +======================================================================== +Routine Description: + Remove ApCli-BSS network interface. + +Arguments: + pAd points to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT28xx_ApCli_Remove(VOID *pAd) +{ + + RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_APC_REMOVE, 0, NULL, 0); + + +} + +#endif /* APCLI_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_assoc.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_assoc.c new file mode 100644 index 000000000..fdd56fb78 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_assoc.c @@ -0,0 +1,3417 @@ +/**************************************************************************** + * 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" + +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 WH_EZ_SETUP +extern unsigned char mtk_oui[]; +#endif /* WH_EZ_SETUP */ + +#ifdef DBG +static void ap_assoc_info_debugshow( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN isReassoc, + IN MAC_TABLE_ENTRY *pEntry, + IN IE_LISTS *ie_list) +{ + PUCHAR sAssoc = isReassoc ? (PUCHAR)"ReASSOC" : (PUCHAR)"ASSOC"; + struct wifi_dev *wdev; + wdev = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev; + + DBGPRINT(RT_DEBUG_TRACE, ("%s - \n\tAssign AID=%d to STA %02x:%02x:%02x:%02x:%02x:%02x\n", + sAssoc, pEntry->Aid, PRINT_MAC(pEntry->Addr))); + +#ifdef DOT11_N_SUPPORT + if (ie_list->ht_cap_len && WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + assoc_ht_info_debugshow(pAd, pEntry, ie_list->ht_cap_len, &ie_list->HTCapability); + + DBGPRINT(RT_DEBUG_TRACE, ("\n%s - Update AP OperaionMode=%d, fAnyStationIsLegacy=%d, fAnyStation20Only=%d, fAnyStationNonGF=%d\n\n", + sAssoc, + pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode, + pAd->MacTab.fAnyStationIsLegacy, + pAd->MacTab.fAnyStation20Only, + pAd->MacTab.fAnyStationNonGF)); + +#ifdef DOT11_VHT_AC + if ((ie_list->vht_cap_len) && + WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14)) + { + assoc_vht_info_debugshow(pAd, pEntry, &ie_list->vht_cap, NULL); + } +#endif /* DOT11_VHT_AC */ + + + DBGPRINT(RT_DEBUG_TRACE, ("\tExt Cap Info: \n")); +#ifdef DOT11N_DRAFT3 + DBGPRINT(RT_DEBUG_TRACE, ("\t\tBss2040CoexistMgmt=%d\n", + pEntry->BSS2040CoexistenceMgmtSupport)); +#endif /* DOT11N_DRAFT3 */ +#ifdef DOT11_VHT_AC + DBGPRINT(RT_DEBUG_TRACE, ("\t\tOperatinModeNotification(%d)\n", + pEntry->ext_cap.operating_mode_notification)); + if (pEntry->ext_cap.operating_mode_notification) { + DBGPRINT(RT_DEBUG_TRACE, ("\t\t\tChannelWidth(%d), RxNss(%d), RxNssType(%d), ForceOpMode(%d)\n", + pEntry->operating_mode.ch_width, + pEntry->operating_mode.rx_nss, + pEntry->operating_mode.rx_nss_type, + pEntry->force_op_mode)); + } +#endif /* DOT11_VHT_AC */ + } + else +#endif /* DOT11_N_SUPPORT */ + { + DBGPRINT(RT_DEBUG_TRACE, ("%s - legacy STA\n", sAssoc)); + DBGPRINT(RT_DEBUG_TRACE, ("\n%s - MODE=%d, MCS=%d\n", sAssoc, + pEntry->HTPhyMode.field.MODE, pEntry->HTPhyMode.field.MCS)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("\tAuthMode=%d, WepStatus=%d, WpaState=%d, GroupKeyWepStatus=%d\n", + pEntry->AuthMode, pEntry->WepStatus, pEntry->WpaState, wdev->GroupKeyWepStatus)); + + DBGPRINT(RT_DEBUG_TRACE, ("\tWMMCap=%d, RalinkAgg=%d, PiggyBack=%d, RDG=%d, TxAMSDU=%d, IdleTimeout=%d\n", + CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE), + CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE), + CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PIGGYBACK_CAPABLE), + CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RDG_CAPABLE), + CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED), + pEntry->StaIdleTimeout)); + +} +#endif /* DBG */ + + +static USHORT update_associated_mac_entry( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN IE_LISTS *ie_list, + IN UCHAR MaxSupportedRate) +{ + struct wifi_dev *wdev; + STA_TR_ENTRY *tr_entry; +#ifdef DOT11R_FT_SUPPORT + UCHAR zeroFT[LEN_TK]; +#endif + + ASSERT((pEntry->func_tb_idx < pAd->ApCfg.BssidNum)); + wdev = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev; + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + + /* Update auth, wep, legacy transmit rate setting . */ + pEntry->Sst = SST_ASSOC; + + pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); + + set_entry_phy_cfg(pAd, pEntry); + + pEntry->CapabilityInfo = ie_list->CapabilityInfo; + + if ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef DOT11_SAE_SUPPORT + || (pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK) +#endif +#ifdef CONFIG_OWE_SUPPORT + || (pEntry->AuthMode == Ndis802_11AuthModeOWE) +#endif + ) + { + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pEntry->WpaState = AS_INITPSK; + } +#ifdef DOT1X_SUPPORT + else if ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2) || + (wdev->IEEE8021X == TRUE)) + { + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pEntry->WpaState = AS_AUTHENTICATION; + } +#endif /* DOT1X_SUPPORT */ +#ifdef WAPI_SUPPORT + else if ((pEntry->AuthMode == Ndis802_11AuthModeWAICERT) || + (pEntry->AuthMode == Ndis802_11AuthModeWAIPSK)) + { + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pEntry->WpaState = AS_AUTHENTICATION2; + } +#endif /* WAPI_SUPPORT */ + + + /* Ralink proprietary Piggyback and Aggregation support for legacy RT61 chip */ + set_sta_ra_cap(pAd, pEntry, ie_list->RalinkIe); + + /* In WPA or 802.1x mode, the port is not secured, otherwise is secued. */ + if ((pEntry->AuthMode >= Ndis802_11AuthModeWPA) +#ifdef DOT1X_SUPPORT + || (wdev->IEEE8021X == TRUE) +#endif /* DOT1X_SUPPORT */ + ) + tr_entry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + else + tr_entry->PortSecured = WPA_802_1X_PORT_SECURED; + +#ifdef SOFT_ENCRYPT + /* There are some situation to need to encryption by software + 1. The Client support PMF. It shall ony support AES cipher. + 2. The Client support WAPI. + If use RT3883 or later, HW can handle the above. + */ +#ifdef WAPI_SUPPORT + if (!(IS_HW_WAPI_SUPPORT(pAd)) + && (pEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled)) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT); + } +#endif /* WAPI_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT + if ((pAd->chipCap.FlgPMFEncrtptMode == PMF_ENCRYPT_MODE_0) + && CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE)) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT); + } +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* SOFT_ENCRYPT */ + +#ifdef DOT11_N_SUPPORT + /* + WFA recommend to restrict the encryption type in 11n-HT mode. + So, the WEP and TKIP are not allowed in HT rate. + */ + if (pAd->CommonCfg.HT_DisallowTKIP && + IS_INVALID_HT_SECURITY(pEntry->WepStatus)) + { + /* Force to None-HT mode due to WiFi 11n policy */ + ie_list->ht_cap_len = 0; +#ifdef DOT11_VHT_AC + ie_list->vht_cap_len = 0; +#endif /* DOT11_VHT_AC */ + DBGPRINT(RT_DEBUG_TRACE, ("%s : Force the STA as Non-HT mode\n", __FUNCTION__)); + } + + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if ((ie_list->ht_cap_len != 0) && + (wdev->DesiredHtPhyInfo.bHtEnable) && + WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + ht_mode_adjust(pAd, pEntry, &ie_list->HTCapability, &pAd->CommonCfg.DesiredHtPhy); + +#ifdef DOT11N_DRAFT3 + if (ie_list->ExtCapInfo.BssCoexistMgmtSupport) + pEntry->BSS2040CoexistenceMgmtSupport = 1; +#endif /* DOT11N_DRAFT3 */ +#ifdef CONFIG_HOTSPOT_R2 + if (ie_list->ExtCapInfo.qosmap) + pEntry->QosMapSupport = 1; +#endif + +#ifdef CONFIG_DOT11V_WNM + if (ie_list->ExtCapInfo.BssTransitionManmt) + pEntry->BssTransitionManmtSupport = 1; +#endif /* CONFIG_DOT11V_WNM */ + +#ifdef DOT11V_WNM_SUPPORT + if(IS_BSS_TRANSIT_MANMT_SUPPORT(pAd, pEntry->func_tb_idx)) + { + if(ie_list->ExtCapInfo.BssTransitionManmt) + pEntry->BssTransitionManmtSupport = 1; + } + if(IS_WNMDMS_SUPPORT(pAd, pEntry->func_tb_idx)) + { + if(ie_list->ExtCapInfo.DMSSupport) + pEntry->DMSSupport = 1; + } +#endif /* DOT11V_WNM_SUPPORT */ + + /* 40Mhz BSS Width Trigger events */ + if (ie_list->HTCapability.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; +#if (defined(WH_EZ_SETUP) && defined(EZ_NETWORK_MERGE_SUPPORT)) + if (IS_EZ_SETUP_ENABLED(wdev)){ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("\nupdate_associated_mac_entry: Fallback thru asoc req ****\n")); + ez_set_ap_fallback_context(wdev,TRUE, pAd->CommonCfg.Channel); + } +#endif /* WH_EZ_SETUP */ + + } + DBGPRINT(RT_DEBUG_TRACE, ("pEntry set 40MHz Intolerant as 1\n")); +#endif /* DOT11N_DRAFT3 */ + Handle_BSS_Width_Trigger_Events(pAd); + } + + + /* find max fixed rate */ + pEntry->MaxHTPhyMode.field.MCS = get_ht_max_mcs(pAd, &wdev->DesiredHtPhyInfo.MCSSet[0], + &ie_list->HTCapability.MCSSet[0]); + + if (wdev->DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("@@@ IF-ra%d DesiredTransmitSetting.field.MCS = %d\n", + pEntry->func_tb_idx, + wdev->DesiredTransmitSetting.field.MCS)); + + set_ht_fixed_mcs(pAd, pEntry, wdev->DesiredTransmitSetting.field.MCS, wdev->HTPhyMode.field.MCS); + } + + pEntry->MaxHTPhyMode.field.STBC = (ie_list->HTCapability.HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + // TODO: shiang-6590, check if this is necessary here, perforce didn't have this + if (ie_list->HTCapability.HtCapParm.MpduDensity < 5) + ie_list->HTCapability.HtCapParm.MpduDensity = 5; + + pEntry->MpduDensity = ie_list->HTCapability.HtCapParm.MpduDensity; + pEntry->MaxRAmpduFactor = ie_list->HTCapability.HtCapParm.MaxRAmpduFactor; + pEntry->MmpsMode = (UCHAR)ie_list->HTCapability.HtCapInfo.MimoPs; + pEntry->AMsduSize = (UCHAR)ie_list->HTCapability.HtCapInfo.AMsduSize; + + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE)) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED); + + if (pAd->CommonCfg.ht_ldpc && (pAd->chipCap.phy_caps & fPHY_CAP_LDPC)) { + if (ie_list->HTCapability.HtCapInfo.ht_rx_ldpc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_HT_RX_LDPC_CAPABLE); + } + + set_sta_ht_cap(pAd, pEntry, &ie_list->HTCapability); + + /* Record the received capability from association request */ + NdisMoveMemory(&pEntry->HTCapability, &ie_list->HTCapability, sizeof(HT_CAPABILITY_IE)); + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14) && + ie_list->vht_cap_len) + { + VHT_CAP_INFO *vht_cap_info = (VHT_CAP_INFO *)&ie_list->vht_cap; + + pEntry->MaxHTPhyMode.field.MODE = MODE_VHT; + if ((pEntry->MaxHTPhyMode.field.BW== BW_40) && (wdev->DesiredHtPhyInfo.vht_bw == VHT_BW_80)) + pEntry->MaxHTPhyMode.field.BW = BW_80; + + /* TODO: implement get_vht_max_mcs to get peer max MCS */ + if (ie_list->vht_cap.mcs_set.rx_mcs_map.mcs_ss1 == VHT_MCS_CAP_9) { + if ((pEntry->MaxHTPhyMode.field.BW == BW_20)) + pEntry->MaxHTPhyMode.field.MCS = 8; + else + pEntry->MaxHTPhyMode.field.MCS = 9; + } else if (ie_list->vht_cap.mcs_set.rx_mcs_map.mcs_ss1 == VHT_MCS_CAP_8) { + pEntry->MaxHTPhyMode.field.MCS = 8; + } else if (ie_list->vht_cap.mcs_set.rx_mcs_map.mcs_ss1 == VHT_MCS_CAP_7) { + pEntry->MaxHTPhyMode.field.MCS = 7; + } + + if (ie_list->vht_cap.mcs_set.rx_mcs_map.mcs_ss2 == VHT_MCS_CAP_9) { + if ((pEntry->MaxHTPhyMode.field.BW == BW_20)) + pEntry->MaxHTPhyMode.field.MCS = ((1 << 4) | 8); + else + pEntry->MaxHTPhyMode.field.MCS = ((1 << 4) | 9); + } else if (ie_list->vht_cap.mcs_set.rx_mcs_map.mcs_ss2 == VHT_MCS_CAP_8) { + pEntry->MaxHTPhyMode.field.MCS = ((1 << 4) | 8); + } else if (ie_list->vht_cap.mcs_set.rx_mcs_map.mcs_ss2 == VHT_MCS_CAP_7) { + pEntry->MaxHTPhyMode.field.MCS = ((1 << 4) | 7); + } + + +DBGPRINT(RT_DEBUG_OFF, ("%s(): Peer's PhyCap=>Mode:%s, BW:%s\n", + __FUNCTION__, + get_phymode_str(pEntry->MaxHTPhyMode.field.MODE), + get_bw_str(pEntry->MaxHTPhyMode.field.BW))); + + if (pAd->CommonCfg.vht_ldpc && (pAd->chipCap.phy_caps & fPHY_CAP_LDPC)) { + if (vht_cap_info->rx_ldpc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_RX_LDPC_CAPABLE); + } + + if (vht_cap_info->sgi_80M) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI80_CAPABLE); + + if (vht_cap_info->sgi_160M) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_SGI160_CAPABLE); + + if (pAd->CommonCfg.vht_stbc) + { + if (vht_cap_info->tx_stbc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_TXSTBC_CAPABLE); + if (vht_cap_info->rx_stbc) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_VHT_RXSTBC_CAPABLE); + } + NdisMoveMemory(&pEntry->vht_cap_ie, &ie_list->vht_cap, sizeof(VHT_CAP_IE)); + } + + if (ie_list->operating_mode_len == sizeof(OPERATING_MODE) && + ie_list->operating_mode.rx_nss_type == 0) + { + pEntry->operating_mode = ie_list->operating_mode; + pEntry->force_op_mode = TRUE; + DBGPRINT(RT_DEBUG_OFF, ("%s(): Peer's OperatingMode=>RxNssType: %d, RxNss: %d, ChBW: %d\n", + __FUNCTION__, pEntry->operating_mode.rx_nss_type, + pEntry->operating_mode.rx_nss, + pEntry->operating_mode.ch_width)); + } + else + pEntry->force_op_mode = FALSE; +#endif /* DOT11_VHT_AC */ + } + else + { +#ifdef CONFIG_HOTSPOT_R2 + if (ie_list->ExtCapInfo.qosmap) + pEntry->QosMapSupport = 1; +#endif + pAd->MacTab.fAnyStationIsLegacy = TRUE; + NdisZeroMemory(&pEntry->HTCapability, sizeof(HT_CAPABILITY_IE)); +#ifdef DOT11_VHT_AC + // TODO: shiang-usw, it's ugly and need to revise it + NdisZeroMemory(&pEntry->vht_cap_ie, sizeof(VHT_CAP_IE)); + NdisZeroMemory(&pEntry->SupportVHTMCS, sizeof(pEntry->SupportVHTMCS)); + pEntry->SupportRateMode &= (~SUPPORT_VHT_MODE); +#endif /* DOT11_VHT_AC */ + } +#endif /* DOT11_N_SUPPORT */ + + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + + pEntry->CurrTxRate = pEntry->MaxSupportedRate; + +#ifdef MFB_SUPPORT + pEntry->lastLegalMfb = 0; + pEntry->isMfbChanged = FALSE; + pEntry->fLastChangeAccordingMfb = FALSE; + + pEntry->toTxMrq = TRUE; + pEntry->msiToTx = 0;/*has to increment whenever a mrq is sent */ + pEntry->mrqCnt = 0; + + pEntry->pendingMfsi = 0; + + pEntry->toTxMfb = FALSE; + pEntry->mfbToTx = 0; + pEntry->mfb0 = 0; + pEntry->mfb1 = 0; +#endif /* MFB_SUPPORT */ + + pEntry->freqOffsetValid = FALSE; + +#ifdef DOT11R_FT_SUPPORT + NdisZeroMemory(zeroFT, LEN_TK); +#endif + // Initialize Rate Adaptation + MlmeRAInit(pAd, pEntry); + + /* Set asic auto fall back */ + if (wdev->bAutoTxRateSwitch == TRUE) + { + UCHAR TableSize = 0; + + pEntry->bAutoTxRateSwitch = TRUE; + + MlmeSelectTxRateTable(pAd, pEntry, &pEntry->pTable, &TableSize, &pEntry->CurrTxRateIndex); + + MlmeNewTxRate(pAd, pEntry); + +#ifdef NEW_RATE_ADAPT_SUPPORT + if (! ADAPT_RATE_TABLE(pEntry->pTable)) +#endif /* NEW_RATE_ADAPT_SUPPORT */ + pEntry->HTPhyMode.field.ShortGI = GI_800; + } + else + { + pEntry->HTPhyMode.field.MCS = wdev->HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; +#ifdef WFA_VHT_PF + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) { + pEntry->HTPhyMode.field.MCS = wdev->DesiredTransmitSetting.field.MCS + + ((pAd->CommonCfg.TxStream - 1) << 4); + } +#endif /* WFA_VHT_PF */ + + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((UCHAR)wdev->DesiredTransmitSetting.field.FixedTxMode, pEntry); + +#ifdef MCS_LUT_SUPPORT + if ( pAd->chipCap.hif_type == HIF_MT) + { + asic_mcs_lut_update(pAd, pEntry); + pEntry->LastTxRate = (USHORT) (pEntry->HTPhyMode.word); + } +#endif /* MCS_LUT_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("%s(SS=%d): pMbss(FixedTxMode=%d, MCS=%d), pEntry(Mode=%d, MCS=%d)\n", + __FUNCTION__, pAd->CommonCfg.TxStream, + wdev->DesiredTransmitSetting.field.FixedTxMode, + wdev->DesiredTransmitSetting.field.MCS, + pEntry->HTPhyMode.field.MODE, pEntry->HTPhyMode.field.MCS)); + } + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT +#ifdef DOT11R_FT_SUPPORT + && (!IS_FT_STA(pEntry) || (IS_FT_STA(pEntry) && (NdisEqualMemory(&pEntry->PTK[OFFSET_OF_PTK_TK], + zeroFT, LEN_TK) || !NdisEqualMemory(&pEntry->PTK[OFFSET_OF_PTK_TK], pEntry->LastTK, LEN_TK)))) +#endif + ) + { + AsicUpdateRxWCIDTable(pAd, pEntry->wcid, pEntry->Addr); + AsicRcpiReset(pAd, pEntry->wcid); + } +#endif + + if (pEntry->AuthMode < Ndis802_11AuthModeWPA) + ApLogEvent(pAd, pEntry->Addr, EVENT_ASSOCIATED); + + APUpdateCapabilityAndErpIe(pAd); +#ifdef DOT11_N_SUPPORT + APUpdateOperationMode(pAd); +#endif /* DOT11_N_SUPPORT */ + + pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; + +#ifdef HOSTAPD_SUPPORT + if((wdev->Hostapd == Hostapd_EXT) && + ((wdev->AuthMode >= Ndis802_11AuthModeWPA) || wdev->IEEE8021X)) + { + RtmpOSWrielessEventSendExt(pAd->net_dev, RT_WLAN_EVENT_EXPIRED, + -1, pEntry->Addr, NULL, 0, + ((pEntry->CapabilityInfo & 0x0010) == 0 ? 0xFFFD : 0xFFFC)); + } +#endif /*HOSTAPD_SUPPORT*/ + + return MLME_SUCCESS; +} + + +/* + ========================================================================== + Description: + assign a new AID to the newly associated/re-associated STA and + decide its MaxSupportedRate and CurrTxRate. Both rates should not + exceed AP's capapbility + Return: + MLME_SUCCESS - association successfully built + others - association failed due to resource issue + ========================================================================== + */ +static USHORT APBuildAssociation( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN IE_LISTS *ie_list, + IN UCHAR MaxSupportedRateIn500Kbps, + OUT USHORT *pAid) +{ + USHORT StatusCode = MLME_SUCCESS; + UCHAR MaxSupportedRate = RATE_11; +#ifdef WH_EZ_SETUP + struct wifi_dev *wdev = NULL; +#else + struct wifi_dev *wdev; +#endif +#ifdef WSC_AP_SUPPORT + WSC_CTRL *wsc_ctrl; +#endif /* WSC_AP_SUPPORT */ + STA_TR_ENTRY *tr_entry; +#if defined(CONFIG_OWE_SUPPORT) || defined(DOT11_SAE_SUPPORT) + PUINT8 pPmkid = NULL; + UINT8 pmkid_count = 0; +#endif /*CONFIG_OWE_SUPPORT*/ +#ifdef DOT11_SAE_SUPPORT + INT cacheidx; +#endif + + + MaxSupportedRate = dot11_2_ra_rate(MaxSupportedRateIn500Kbps); + + if (pAd && (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_G) +#ifdef DOT11_N_SUPPORT + || WMODE_EQUAL(pAd->CommonCfg.PhyMode, (WMODE_G | WMODE_GN)) +#endif /* DOT11_N_SUPPORT */ + ) + && (MaxSupportedRate < RATE_FIRST_OFDM_RATE) + ) + return MLME_ASSOC_REJ_DATA_RATE; + +#ifdef DOT11_N_SUPPORT + /* 11n only */ + if (WMODE_HT_ONLY(pAd->CommonCfg.PhyMode)&& (ie_list->ht_cap_len == 0)) + return MLME_ASSOC_REJ_DATA_RATE; +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14) && + (ie_list->vht_cap_len == 0) && + (pAd->CommonCfg.bNonVhtDisallow)) + return MLME_ASSOC_REJ_DATA_RATE; +#endif /* DOT11_VHT_AC */ + + if (!pEntry) + return MLME_UNSPECIFY_FAIL; + + if (pEntry && ((pEntry->Sst == SST_AUTH) || (pEntry->Sst == SST_ASSOC))) + { + /* TODO: + should qualify other parameters, for example - + capablity, supported rates, listen interval, etc., to + decide the Status Code + */ + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + if (tr_entry == NULL) + DBGPRINT(RT_DEBUG_TRACE, ("tr_entry is NULL.\n")); + + *pAid = pEntry->Aid; + pEntry->NoDataIdleCount = 0; + // TODO: shiang-usw, remove upper setting becasue we need to migrate to tr_entry! + pAd->MacTab.tr_entry[pEntry->wcid].NoDataIdleCount = 0; + + pEntry->StaConnectTime = 0; +#ifdef CONFIG_HOTSPOT_R2 + if (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_OSEN_CAPABLE)) +#endif + { +#ifdef WSC_AP_SUPPORT + if (pEntry->bWscCapable == FALSE) +#endif /* WSC_AP_SUPPORT */ + { + /* check the validity of the received RSNIE */ + StatusCode = APValidateRSNIE(pAd, pEntry, &ie_list->RSN_IE[0], ie_list->RSNIE_Len); + if (StatusCode != MLME_SUCCESS) + return StatusCode; +#ifdef DOT11_SAE_SUPPORT + + if ((StatusCode == MLME_SUCCESS) + && pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK) { + + pPmkid = WPA_ExtractSuiteFromRSNIE(ie_list->RSN_IE, + ie_list->RSNIE_Len, PMKID_LIST, &pmkid_count); + if (pPmkid != NULL) { + cacheidx = RTMPSearchPMKIDCache(pAd, pEntry->func_tb_idx, pEntry->Addr); + if (cacheidx == -1 + || RTMPEqualMemory(pPmkid, + &pAd->ApCfg.MBSSID[pEntry->func_tb_idx]. + PMKIDCache.BSSIDInfo[cacheidx].PMKID, + LEN_PMKID) == 0) { + StatusCode = MLME_INVALID_PMKID; + } + } + } +#endif /* DOT11_SAE_SUPPORT */ + +#ifdef CONFIG_OWE_SUPPORT + if (StatusCode == MLME_SUCCESS + && pEntry->AuthMode == Ndis802_11AuthModeOWE) { + StatusCode = owe_pmkid_ecdh_process(pAd, + pEntry, + ie_list->RSN_IE, + ie_list->RSNIE_Len, + &ie_list->ecdh_ie, + ie_list->ecdh_ie.length, + pPmkid, + &pmkid_count, + SUBTYPE_ASSOC_REQ); + + } + +#endif /*CONFIG_OWE_SUPPORT*/ + +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + if (StatusCode != MLME_SUCCESS) + return StatusCode; +#endif + } + } + NdisMoveMemory(pEntry->RSN_IE, &ie_list->RSN_IE[0], ie_list->RSNIE_Len); + pEntry->RSNIE_Len = ie_list->RSNIE_Len; + + + wdev = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev; + if (*pAid == 0) + StatusCode = MLME_ASSOC_REJ_UNABLE_HANDLE_STA; + else if ((pEntry->RSNIE_Len == 0) && + (wdev->AuthMode >= Ndis802_11AuthModeWPA) +#ifdef HOSTAPD_SUPPORT + && (wdev->Hostapd == Hostapd_EXT) +#endif /* HOSTAPD_SUPPORT */ + ) + { +#ifdef WSC_AP_SUPPORT + wsc_ctrl = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].WscControl; + if (((wsc_ctrl->WscConfMode != WSC_DISABLE) && + pEntry->bWscCapable +#ifdef WSC_V2_SUPPORT + && (wsc_ctrl->WscV2Info.bWpsEnable || + (wsc_ctrl->WscV2Info.bEnableWpsV2 == FALSE)) +#endif /* WSC_V2_SUPPORT */ + ) +#ifdef HOSTAPD_SUPPORT + || wdev->Hostapd == Hostapd_EXT +#endif /*HOSTAPD_SUPPORT*/ + ) + { + pEntry->Sst = SST_ASSOC; + StatusCode = MLME_SUCCESS; + /* In WPA or 802.1x mode, the port is not secured. */ + if ((pEntry->AuthMode >= Ndis802_11AuthModeWPA) +#ifdef DOT1X_SUPPORT + || (wdev->IEEE8021X == TRUE) +#endif /* DOT1X_SUPPORT */ + ) + { + if(tr_entry) + tr_entry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + } + else + { + if(tr_entry) + tr_entry->PortSecured = WPA_802_1X_PORT_SECURED; + } + if ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef DOT11_SAE_SUPPORT + || (pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK) +#endif +#ifdef CONFIG_OWE_SUPPORT + || (pEntry->AuthMode == Ndis802_11AuthModeOWE) +#endif + ) + { + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pEntry->WpaState = AS_INITPSK; + } +#ifdef DOT1X_SUPPORT + else if ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2) || + (wdev->IEEE8021X == TRUE)) + { + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pEntry->WpaState = AS_AUTHENTICATION; + } +#endif /* DOT1X_SUPPORT */ + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - WSC_STATE_MACHINE is OFF.\n", + wsc_ctrl->WscConfMode, pEntry->func_tb_idx)); + StatusCode = MLME_ASSOC_DENY_OUT_SCOPE; + } +#else /* WSC_AP_SUPPORT */ + StatusCode = MLME_ASSOC_DENY_OUT_SCOPE; +#endif /* WSC_AP_SUPPORT */ + +#ifdef HOSTAPD_SUPPORT + if(wdev->Hostapd == Hostapd_EXT + && (wdev->AuthMode >= Ndis802_11AuthModeWPA + || wdev->IEEE8021X)) + { + + RtmpOSWrielessEventSendExt(pAd->net_dev, RT_WLAN_EVENT_EXPIRED, + -1, pEntry->Addr, NULL, 0, + ((pEntry->CapabilityInfo & 0x0010) == 0 ? 0xFFFD : 0xFFFC)); + } +#endif /*HOSTAPD_SUPPORT*/ + } + else + { + StatusCode = update_associated_mac_entry(pAd, pEntry, ie_list, MaxSupportedRate); + } + } + else /* CLASS 3 error should have been handled beforehand; here should be MAC table full */ + StatusCode = MLME_ASSOC_REJ_UNABLE_HANDLE_STA; + +#ifdef WH_EZ_SETUP + +#ifdef NEW_CONNECTION_ALGO + if (IS_EZ_SETUP_ENABLED(wdev) && (ez_is_connection_allowed(wdev) == FALSE)) + StatusCode = MLME_ASSOC_REJ_TEMPORARILY; +#endif + + if ((StatusCode == MLME_SUCCESS) + && pEntry->easy_setup_enabled) { + if (pEntry->easy_setup_mic_valid == FALSE) + StatusCode = MLME_REJ_CHALLENGE_FAILURE; + } +#endif /* WH_EZ_SETUP */ + + if (StatusCode == MLME_SUCCESS) + { + if (ie_list->bWmmCapable) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + } + else + { + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + } + } + + return StatusCode; +} + + +#ifdef IAPP_SUPPORT +/* + ======================================================================== + Routine Description: + Send Leyer 2 Update Frame to update forwarding table in Layer 2 devices. + + Arguments: + *mac_p - the STATION MAC address pointer + + Return Value: + TRUE - send successfully + FAIL - send fail + + Note: + ======================================================================== +*/ +static BOOLEAN IAPP_L2_Update_Frame_Send(RTMP_ADAPTER *pAd, UINT8 *mac, INT wdev_idx) +{ + + NDIS_PACKET *pNetBuf; +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) +#if (MT7615_MT7603_COMBO_FORWARDING == 1) + struct wifi_dev *wdev; + wdev = pAd->wdev_list[wdev_idx]; +#endif +#endif + pNetBuf = RtmpOsPktIappMakeUp(get_netdev_from_bssid(pAd, wdev_idx), mac); + if (pNetBuf == NULL) + return FALSE; + +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) +#if (MT7615_MT7603_COMBO_FORWARDING == 1) + if (wf_fwd_needed_hook != NULL && wf_fwd_needed_hook() == TRUE) + set_wf_fwd_cb(pAd, pNetBuf, wdev); +#endif /* CONFIG_WIFI_PKT_FWD */ +#endif + /* 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, wdev_idx); + + return TRUE; +} /* End of IAPP_L2_Update_Frame_Send */ +#endif /* IAPP_SUPPORT */ + + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ +BOOLEAN PeerAssocReqCmmSanity( + RTMP_ADAPTER *pAd, + BOOLEAN isReassoc, + VOID *Msg, + INT MsgLen, + IE_LISTS *ie_lists) +{ + //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 }; +#ifdef CONFIG_HOTSPOT_R2 + UCHAR HS2_OSEN_OUI[4] = { 0x50, 0x6f, 0x9a, 0x12 }; + UCHAR HS2OUIBYTE[4] = {0x50, 0x6f, 0x9a, 0x10}; +#endif +#ifdef MBO_SUPPORT + UCHAR MBO_OCE_OUI_BYTE[4] = {0x50, 0x6f, 0x9a, 0x16}; +#endif/* MBO_SUPPORT */ + MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY *)NULL; +#ifdef DOT11R_FT_SUPPORT + FT_INFO *pFtInfo = &ie_lists->FtInfo; +#endif /* DOT11R_FT_SUPPORT */ +#ifdef DOT11K_RRM_SUPPORT + RRM_EN_CAP_IE *pRrmEnCap = &ie_lists->RrmEnCap; +#endif /* DOT11K_RRM_SUPPORT */ + HT_CAPABILITY_IE *pHtCapability = &ie_lists->HTCapability; +#ifdef WH_EZ_SETUP +#ifdef DOT1X_SUPPORT + PUINT8 pPmkid = NULL; + UINT8 pmkid_count = 0; + BSS_STRUCT *pMbss; + struct wifi_dev *wdev; +#endif /* DOT1X_SUPPORT */ +#endif +#ifdef CONFIG_OWE_SUPPORT + UCHAR *extension_id; + UCHAR *ext_ie_length; +#endif + if(pAd == NULL) + return FALSE; + + pEntry = MacTableLookup(pAd, &Fr->Hdr.Addr2[0]); + if (pEntry == NULL) + return FALSE; + COPY_MAC_ADDR(&ie_lists->Addr1[0], &Fr->Hdr.Addr1[0]); + COPY_MAC_ADDR(&ie_lists->Addr2[0], &Fr->Hdr.Addr2[0]); + + //Ptr = (PCHAR)Fr->Octet; + + NdisMoveMemory(&ie_lists->CapabilityInfo, &Fr->Octet[0], 2); + NdisMoveMemory(&ie_lists->ListenInterval, &Fr->Octet[2], 2); + + if (isReassoc) + { + NdisMoveMemory(&ie_lists->ApAddr[0], &Fr->Octet[4], 6); + eid_ptr = (PEID_STRUCT) &Fr->Octet[10]; + } + else + { + eid_ptr = (PEID_STRUCT) &Fr->Octet[4]; + } + + + /* get variable fields from payload and advance the pointer */ + while (((UCHAR *)eid_ptr + eid_ptr->Len + 1) < ((UCHAR *)Fr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_SSID: + if (((Sanity&0x1) == 1)) + break; + + if ((eid_ptr->Len <= MAX_LEN_OF_SSID)) + { + Sanity |= 0x01; + NdisMoveMemory(&ie_lists->Ssid[0], eid_ptr->Octet, eid_ptr->Len); + ie_lists->SsidLen = eid_ptr->Len; + DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - SsidLen = %d \n", ie_lists->SsidLen)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - wrong IE_SSID\n")); + return FALSE; + } + break; + + case IE_SUPP_RATES: + if ((eid_ptr->Len <= MAX_LEN_OF_SUPPORTED_RATES) && + (eid_ptr->Len > 0)) + { + Sanity |= 0x02; + NdisMoveMemory(&ie_lists->SupportedRates[0], eid_ptr->Octet, eid_ptr->Len); + + DBGPRINT(RT_DEBUG_TRACE, + ("PeerAssocReqSanity - IE_SUPP_RATES., Len=%d. " + "Rates[0]=%x\n", eid_ptr->Len, ie_lists->SupportedRates[0])); + DBGPRINT(RT_DEBUG_TRACE, + ("Rates[1]=%x %x %x %x %x %x %x\n", + ie_lists->SupportedRates[1], ie_lists->SupportedRates[2], + ie_lists->SupportedRates[3], ie_lists->SupportedRates[4], + ie_lists->SupportedRates[5], ie_lists->SupportedRates[6], + ie_lists->SupportedRates[7])); + + ie_lists->SupportedRatesLen = eid_ptr->Len; + } + else + { + UCHAR RateDefault[8] = \ + { 0x82, 0x84, 0x8b, 0x96, 0x12, 0x24, 0x48, 0x6c }; + + /* HT rate not ready yet. return true temporarily. rt2860c */ + /*DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - wrong IE_SUPP_RATES\n")); */ + Sanity |= 0x02; + ie_lists->SupportedRatesLen = 8; + NdisMoveMemory(&ie_lists->SupportedRates[0], RateDefault, 8); + + DBGPRINT(RT_DEBUG_TRACE, + ("PeerAssocReqSanity - wrong IE_SUPP_RATES., Len=%d\n", + eid_ptr->Len)); + } + break; + + case IE_EXT_SUPP_RATES: + if (eid_ptr->Len + ie_lists->SupportedRatesLen <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(&ie_lists->SupportedRates[ie_lists->SupportedRatesLen], eid_ptr->Octet, + eid_ptr->Len); + ie_lists->SupportedRatesLen += eid_ptr->Len; + } + else + { + NdisMoveMemory(&ie_lists->SupportedRates[ie_lists->SupportedRatesLen], eid_ptr->Octet, + MAX_LEN_OF_SUPPORTED_RATES - (ie_lists->SupportedRatesLen)); + ie_lists->SupportedRatesLen = MAX_LEN_OF_SUPPORTED_RATES; + } + break; + + case IE_HT_CAP: + if (eid_ptr->Len >= sizeof(HT_CAPABILITY_IE)) + { + NdisMoveMemory(pHtCapability, eid_ptr->Octet, SIZE_HT_CAP_IE); + + *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); + +#ifdef UNALIGNMENT_SUPPORT + { + EXT_HT_CAP_INFO extHtCapInfo; + + NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&pHtCapability->ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); + NdisMoveMemory((PUCHAR)(&pHtCapability->ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + } +#else + *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); +#endif /* UNALIGNMENT_SUPPORT */ + + ie_lists->ht_cap_len = SIZE_HT_CAP_IE; + Sanity |= 0x10; + DBGPRINT(RT_DEBUG_WARN, ("PeerAssocReqSanity - IE_HT_CAP\n")); + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("PeerAssocReqSanity - wrong IE_HT_CAP.eid_ptr->Len = %d\n", eid_ptr->Len)); + } + + break; + case IE_EXT_CAPABILITY: + if (eid_ptr->Len) + { + INT ext_len = eid_ptr->Len; +#ifdef RT_BIG_ENDIAN + UCHAR *pextCapInfo = NULL; +#endif + + ext_len = ext_len > sizeof(EXT_CAP_INFO_ELEMENT) ? sizeof(EXT_CAP_INFO_ELEMENT) : ext_len; + NdisMoveMemory(&ie_lists->ExtCapInfo, eid_ptr->Octet, ext_len); +#ifdef RT_BIG_ENDIAN + pextCapInfo = (UCHAR *)&ie_lists->ExtCapInfo; + *((UINT32*)pextCapInfo) = cpu2le32(*((UINT32 *)pextCapInfo)); + *((UINT32*)(pextCapInfo + 4)) = cpu2le32(*((UINT32 *)(pextCapInfo + 4))); +#endif + DBGPRINT(RT_DEBUG_WARN, ("PeerAssocReqSanity - IE_EXT_CAPABILITY!\n")); + } + + break; + + case IE_WPA: /* same as IE_VENDOR_SPECIFIC */ +#ifdef MBO_SUPPORT + if (NdisEqualMemory(eid_ptr->Octet, MBO_OCE_OUI_BYTE, sizeof(MBO_OCE_OUI_BYTE)) + && (eid_ptr->Len >= 5)) { + MboParseStaMboIE(pAd, &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev, + pEntry, eid_ptr->Octet, eid_ptr->Len, MBO_FRAME_TYPE_ASSOC_REQ); + break; + } +#endif/* MBO_SUPPORT */ +#ifdef MWDS + if(NdisEqualMemory(MTK_OUI, eid_ptr->Octet, 3)) + { + if(MWDS_SUPPORT(eid_ptr->Octet[3])) + { + pEntry->bSupportMWDS = TRUE; + DBGPRINT(RT_DEBUG_OFF, ("Peer supports MWDS\n")); + } + else + pEntry->bSupportMWDS = FALSE; + } +#endif /* MWDS */ + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED((pEntry->wdev)) && NdisEqualMemory(&mtk_oui[0], &eid_ptr->Octet[0], MTK_OUI_LEN)) { + if (eid_ptr->Octet[MTK_OUI_LEN] & MTK_VENDOR_EASY_SETUP) { + EZ_DEBUG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s(%d) - Found MTK Easy Setup OUI.\n", + __FUNCTION__, __LINE__)); + pEntry->easy_setup_enabled = TRUE; + break; + } + } +#endif /* WH_EZ_SETUP */ +#ifdef STA_FORCE_ROAM_SUPPORT + if (pAd->en_force_roam_supp) { + if (NdisEqualMemory(MTK_OUI, eid_ptr->Octet, 3)) { + if (IS_MEDIATEK_CLI_ENTRY(eid_ptr->Octet[3])) { + pEntry->is_peer_entry_apcli = TRUE; + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("Peer ENTRY IS MTK CLI\n")); + } else + pEntry->is_peer_entry_apcli = FALSE; + } + } +#endif +#ifdef WH_EVENT_NOTIFIER + if(pAd->ApCfg.EventNotifyCfg.CustomOUILen && + (eid_ptr->Len >= pAd->ApCfg.EventNotifyCfg.CustomOUILen) && + NdisEqualMemory(eid_ptr->Octet, pAd->ApCfg.EventNotifyCfg.CustomOUI, pAd->ApCfg.EventNotifyCfg.CustomOUILen)) + { + pEntry->custom_ie_len = eid_ptr->Len; + NdisMoveMemory(pEntry->custom_ie, eid_ptr->Octet, eid_ptr->Len); + break; + } +#endif /* WH_EVENT_NOTIFIER */ + case IE_WPA2: +#ifdef DOT11R_FT_SUPPORT +#endif /* DOT11R_FT_SUPPORT */ +#ifdef CONFIG_HOTSPOT_R2 + if (NdisEqualMemory(eid_ptr->Octet, HS2OUIBYTE, sizeof(HS2OUIBYTE)) && (eid_ptr->Len >= 5)) + { + //UCHAR tmp2 = 0x12; + UCHAR *hs2_config = (UCHAR *)&eid_ptr->Octet[4]; + UCHAR ppomo_exist = ((*hs2_config) >> 1) & 0x01; + UCHAR hs2_version = ((*hs2_config) >> 4) & 0x0f; + //UCHAR *tmp3 = (UCHAR *)&pEntry->hs_info.ppsmo_id; + //UCHAR tmp[2] = {0x12,0x34}; + + pEntry->hs_info.version = hs2_version; + pEntry->hs_info.ppsmo_exist = ppomo_exist; + if (pEntry->hs_info.ppsmo_exist) + { + NdisMoveMemory(&pEntry->hs_info.ppsmo_id, &eid_ptr->Octet[5], 2); + //NdisMoveMemory(tmp3, tmp, 2); + } + printk("Assoc HS2 STA:version:%d,ppomo exist:%d, value:0x%x\n", pEntry->hs_info.version, pEntry->hs_info.ppsmo_exist, pEntry->hs_info.ppsmo_id); + break; + } +#endif /* CONFIG_HOTSPOT_R2 */ + + if (NdisEqualMemory(eid_ptr->Octet, WPS_OUI, 4)) + { +#ifdef WSC_AP_SUPPORT +#ifdef WSC_V2_SUPPORT + if ((pAd->ApCfg.MBSSID[pEntry->func_tb_idx].WscControl.WscV2Info.bWpsEnable) || + (pAd->ApCfg.MBSSID[pEntry->func_tb_idx].WscControl.WscV2Info.bEnableWpsV2 == FALSE)) +#endif /* WSC_V2_SUPPORT */ + ie_lists->bWscCapable = TRUE; +#endif /* WSC_AP_SUPPORT */ + 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 */ + + ie_lists->ht_cap_len = SIZE_HT_CAP_IE; + } + break; + + default: + /* ignore other cases */ + break; + } + } + + if (NdisEqualMemory(eid_ptr->Octet, RALINK_OUI, 3) && (eid_ptr->Len == 7)) + { + if (eid_ptr->Octet[3] != 0) + ie_lists->RalinkIe = eid_ptr->Octet[3]; + else + ie_lists->RalinkIe = 0xf0000000; /* Set to non-zero value (can't set bit0-2) to represent this is Ralink Chip. So at linkup, we will set ralinkchip flag. */ + break; + } +#if defined(MWDS) || defined(MAP_SUPPORT) + check_vendor_ie(pAd, (UCHAR *)eid_ptr, &(ie_lists->vendor_ie)); +#endif + + /* WMM_IE */ + if (NdisEqualMemory(eid_ptr->Octet, WME_INFO_ELEM, 6) && (eid_ptr->Len == 7)) + { + ie_lists->bWmmCapable = TRUE; + +#ifdef UAPSD_SUPPORT + if (pEntry) + { + UAPSD_AssocParse(pAd, + pEntry, (UINT8 *)&eid_ptr->Octet[6], + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.UapsdInfo.bAPSDCapable); + } +#endif /* UAPSD_SUPPORT */ + + break; + } + + if (pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.AuthMode < Ndis802_11AuthModeWPA) + break; + + /* If this IE did not begins with 00:0x50:0xf2:0x01, + it would be proprietary. So we ignore it. */ + if (!NdisEqualMemory(eid_ptr->Octet, WPA1_OUI, sizeof(WPA1_OUI)) + && !NdisEqualMemory(&eid_ptr->Octet[2], WPA2_OUI, sizeof(WPA2_OUI)) +#ifdef CONFIG_SECURITY_IMPROVEMENT_SUPPORT + && eid_ptr->Len != 2 +#endif + ) + { + DBGPRINT(RT_DEBUG_TRACE, ("Not RSN IE, maybe WMM IE!!!\n")); + +#ifdef CONFIG_HOTSPOT_R2 + if (!NdisEqualMemory(eid_ptr->Octet, HS2_OSEN_OUI, sizeof(HS2_OSEN_OUI))) + { + unsigned char *tmp = (unsigned char *)eid_ptr->Octet; + + DBGPRINT(RT_DEBUG_OFF, ("!!!!!!not found OSEN IE,%x:%x:%x:%x\n", *tmp, *(tmp+1), *(tmp+2), *(tmp+3))); + pEntry->OSEN_IE_Len = 0; + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_OSEN_CAPABLE); + break; + } + else + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_OSEN_CAPABLE); + NdisMoveMemory(pEntry->OSEN_IE, eid_ptr, eid_ptr->Len + 2); + pEntry->OSEN_IE_Len = eid_ptr->Len + 2; + + DBGPRINT(RT_DEBUG_OFF, ("!!!!!!found OSEN IE\n")); + } +#else + break; +#endif + } + + if (/*(eid_ptr->Len <= MAX_LEN_OF_RSNIE) &&*/ (eid_ptr->Len >= MIN_LEN_OF_RSNIE)) + { + hex_dump("Received RSNIE in Assoc-Req", (UCHAR *)eid_ptr, eid_ptr->Len + 2); + + /* Copy whole RSNIE context */ + NdisMoveMemory(&ie_lists->RSN_IE[0], eid_ptr, eid_ptr->Len + 2); + ie_lists->RSNIE_Len =eid_ptr->Len + 2; + +#ifdef DOT11R_FT_SUPPORT + NdisMoveMemory(pFtInfo->RSN_IE, eid_ptr, eid_ptr->Len + 2); + pFtInfo->RSNIE_Len = eid_ptr->Len + 2; +#endif /* DOT11R_FT_SUPPORT */ + } + else + { + ie_lists->RSNIE_Len = 0; + DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - missing IE_WPA(%d)\n",eid_ptr->Len)); + return FALSE; + } + break; + +#ifdef WAPI_SUPPORT + case IE_WAPI: + if ((pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.AuthMode != Ndis802_11AuthModeWAICERT) && + (pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.AuthMode != Ndis802_11AuthModeWAIPSK)) + break; + + /* Sanity check the validity of WIE */ + /* Todo - AlbertY */ + + /* Copy whole WAPI-IE context */ + NdisMoveMemory(&ie_lists->RSN_IE[0], eid_ptr, eid_ptr->Len + 2); + ie_lists->RSNIE_Len =eid_ptr->Len + 2; + DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - IE_WAPI(%d)\n",eid_ptr->Len)); + break; +#endif /* WAPI_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + case IE_FT_MDIE: + FT_FillMdIeInfo(eid_ptr, &pFtInfo->MdIeInfo); + break; + + case IE_FT_FTIE: + FT_FillFtIeInfo(eid_ptr, &pFtInfo->FtIeInfo); + break; + + case IE_FT_RIC_DATA: + /* record the pointer of first RDIE. */ + if (pFtInfo->RicInfo.pRicInfo == NULL) + { + pFtInfo->RicInfo.pRicInfo = &eid_ptr->Eid; + pFtInfo->RicInfo.Len = ((UCHAR*)Fr + MsgLen) - (UCHAR*)eid_ptr + 1; + } + case IE_FT_RIC_DESCRIPTOR: + if ((pFtInfo->RicInfo.RicIEsLen + eid_ptr->Len + 2) < MAX_RICIES_LEN) + { + NdisMoveMemory(&pFtInfo->RicInfo.RicIEs[pFtInfo->RicInfo.RicIEsLen], + &eid_ptr->Eid, eid_ptr->Len + 2); + pFtInfo->RicInfo.RicIEsLen += eid_ptr->Len + 2; + } + break; +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT + case IE_RRM_EN_CAP: + { + UINT64 value; + NdisMoveMemory(&value, eid_ptr->Octet, sizeof(UINT64)); + pRrmEnCap->word = le2cpu64(value); + } + break; +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11_VHT_AC + case IE_VHT_CAP: + if (eid_ptr->Len == sizeof(VHT_CAP_IE)) + { + NdisMoveMemory(&ie_lists->vht_cap, eid_ptr->Octet, sizeof(VHT_CAP_IE)); + ie_lists->vht_cap_len = eid_ptr->Len; + DBGPRINT(RT_DEBUG_TRACE, ("%s():IE_VHT_CAP\n", __FUNCTION__)); + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s():wrong IE_VHT_CAP, eid->Len = %d\n", + __FUNCTION__, eid_ptr->Len)); + } + + case IE_VHT_OP: + if (eid_ptr->Len == sizeof(VHT_OP_IE)) + { + NdisMoveMemory(&ie_lists->vht_op, eid_ptr->Octet, sizeof(VHT_OP_IE)); + ie_lists->vht_op_len = eid_ptr->Len; + DBGPRINT(RT_DEBUG_TRACE, ("%s():IE_VHT_OP\n", __FUNCTION__)); + } + + case IE_OPERATING_MODE_NOTIFY: + if (eid_ptr->Len == sizeof(OPERATING_MODE)) { + ie_lists->operating_mode_len = sizeof(OPERATING_MODE); + NdisMoveMemory(&ie_lists->operating_mode, &eid_ptr->Octet[0], sizeof(OPERATING_MODE)); + DBGPRINT(RT_DEBUG_TRACE, ("%s():IE_OPERATING_MODE_NOTIFY!\n", __FUNCTION__)); + } + break; +#endif /* DOT11_VHT_AC */ +#ifdef CONFIG_OWE_SUPPORT + case IE_WLAN_EXTENSION: + /*parse EXTENSION EID*/ + extension_id = (UCHAR *)eid_ptr + 2; + switch (*extension_id) { + case IE_EXTENSION_ID_ECDH: + ext_ie_length = (UCHAR *)eid_ptr + 1; + if (*ext_ie_length - 3 <= sizeof(ie_lists->ecdh_ie.public_key)) + os_zero_mem(ie_lists->ecdh_ie.public_key, *ext_ie_length - 3); + else { + DBGPRINT(RT_DEBUG_ERROR, ("%s():IE_ECDH error\n", __func__)); + break; + } + ie_lists->ecdh_ie.ext_ie_id = IE_WLAN_EXTENSION; + ie_lists->ecdh_ie.length = eid_ptr->Len; + if (eid_ptr->Len <= sizeof(ie_lists->ecdh_ie) - 2) + NdisMoveMemory(&ie_lists->ecdh_ie.ext_id_ecdh, eid_ptr->Octet, eid_ptr->Len); + else { + DBGPRINT(RT_DEBUG_ERROR, ("%s():IE_ECDH error\n", __func__)); + break; + } + break; + default: + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("IE_WLAN_EXTENSION: no handler for extension_id:%d\n", *extension_id)); + break; + } + break; +#endif /*CONFIG_OWE_SUPPORT*/ + + default: + break; + } + + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + +#ifdef WH_EZ_SETUP +#ifdef DOT1X_SUPPORT + wdev = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev; + + if(IS_EZ_SETUP_ENABLED(wdev) && ((APValidateRSNIE(pAd, pEntry, &ie_lists->RSN_IE[0], ie_lists->RSNIE_Len)) == MLME_SUCCESS)) + { + if (/*IS_AKM_WPA2_Entry(pEntry)*/ (pEntry->AuthMode == Ndis802_11AuthModeWPA2) && + ((pPmkid = WPA_ExtractSuiteFromRSNIE(ie_lists->RSN_IE, ie_lists->RSNIE_Len, PMKID_LIST, &pmkid_count)) != NULL)) + { /* Key cache */ + INT CacheIdx; + + pMbss = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx]; + + if (((CacheIdx = RTMPSearchPMKIDCache(pAd, pEntry->func_tb_idx, pEntry->Addr)) == -1) + || ((RTMPEqualMemory(pPmkid, &pMbss->PMKIDCache.BSSIDInfo[CacheIdx].PMKID, LEN_PMKID)) == 0)) + { + MlmeDeAuthAction(pAd, pEntry, REASON_DISASSOC_STA_LEAVING, FALSE); + EZ_DEBUG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s: PMKID not found \n", __FUNCTION__)); + return FALSE; + } + } + } +#endif /* DOT1X_SUPPORT */ +#endif + + if ((Sanity&0x3) != 0x03) + { + DBGPRINT(RT_DEBUG_WARN, ("%s(): - missing mandatory field\n", __FUNCTION__)); + return FALSE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - success\n", __FUNCTION__)); + return TRUE; + } +} + + +VOID ap_cmm_peer_assoc_req_action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem, + IN BOOLEAN isReassoc) +{ +#ifdef WH_EZ_SETUP + struct wifi_dev *wdev = NULL; +#else + struct wifi_dev *wdev = NULL; +#endif + BSS_STRUCT *pMbss; + BOOLEAN bAssocSkip = FALSE; + CHAR rssi; +#ifdef DOT11R_FT_SUPPORT + UCHAR zeroFT[LEN_TK]; +#endif + IE_LISTS *ie_list = NULL; + HEADER_802_11 AssocRspHdr; + USHORT CapabilityInfoForAssocResp; + USHORT StatusCode = MLME_SUCCESS; + USHORT Aid = 0; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + UCHAR MaxSupportedRate = 0; + UCHAR SupRateLen, PhyMode, FlgIs11bSta; + UCHAR i; + MAC_TABLE_ENTRY *pEntry = NULL; + STA_TR_ENTRY *tr_entry; +#ifdef DBG + UCHAR *sAssoc = isReassoc ? (PUCHAR)"ReASSOC" : (PUCHAR)"ASSOC"; +#endif /* DBG */ + UCHAR SubType; + BOOLEAN bACLReject = FALSE; +#if defined(DOT1X_SUPPORT) || defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + PUINT8 pPmkid = NULL; + UINT8 pmkid_count = 0; +#endif /* DOT1X_SUPPORT */ +#ifdef DOT11R_FT_SUPPORT + PFT_CFG pFtCfg = NULL; + FT_INFO FtInfoBuf = {0}; +#endif /* DOT11R_FT_SUPPORT */ +#ifdef WSC_AP_SUPPORT + WSC_CTRL *wsc_ctrl; +#endif /* WSC_AP_SUPPORT */ +#ifdef RT_BIG_ENDIAN + UINT32 tmp_1; + UINT64 tmp_2; +#endif /*RT_BIG_ENDIAN*/ +#ifdef MBO_SUPPORT + BOOLEAN bMboReject = FALSE; +#endif/* MBO_SUPPORT */ +#ifdef WAPP_SUPPORT + UINT8 wapp_cnnct_stage = WAPP_ASSOC; + UINT16 wapp_assoc_fail = NOT_FAILURE; +#endif/* WAPP_SUPPORT */ + +#ifdef WH_EZ_SETUP + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) + EZ_DEBUG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("ap_cmm_peer_assoc_req_action()\n")); +#endif + + /* disallow new association */ + if (pAd && (pAd->ApCfg.BANClass3Data == TRUE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Disallow new Association\n")); +#ifdef WAPP_SUPPORT + wapp_assoc_fail = DISALLOW_NEW_ASSOCI; +#endif/* WAPP_SUPPORT */ + goto assoc_check; + /*return; sync 7615*/ + } + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&ie_list, sizeof(IE_LISTS)); + if (ie_list == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): mem alloc failed\n", __FUNCTION__)); +#ifdef WAPP_SUPPORT + wapp_assoc_fail = MLME_NO_RESOURCE; +#endif/* WAPP_SUPPORT */ + goto assoc_check; + /*return; sync 7615*/ + } + NdisZeroMemory(ie_list, sizeof(IE_LISTS)); + + if (!PeerAssocReqCmmSanity(pAd, isReassoc, Elem->Msg, Elem->MsgLen, ie_list)) + goto LabelOK; + + pEntry = MacTableLookup(pAd, ie_list->Addr2); + if (!pEntry) { + DBGPRINT(RT_DEBUG_ERROR, ("NoAuth MAC - %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(ie_list->Addr2))); + goto LabelOK; + } + + if (!VALID_MBSS(pAd, pEntry->func_tb_idx)) { + DBGPRINT(RT_DEBUG_ERROR, ("%s():pEntry bounding invalid wdev(apidx=%d)\n", + __FUNCTION__, pEntry->func_tb_idx)); + goto LabelOK; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s():pEntry->func_tb_idx=%d\n", __FUNCTION__, pEntry->func_tb_idx)); + pMbss = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx]; + wdev = &pMbss->wdev; + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + if(pEntry) { + INT32 prev = -1; + prev =(INT32)pEntry->AuthAssocNotInProgressFlag; + pEntry->AuthAssocNotInProgressFlag = 0; + DBGPRINT(RT_DEBUG_TRACE,("===[%s] prev_val = %d AuthAssocNotInProgressFlag = %u pEntry->wcid = %d \n", + __FUNCTION__, prev, pEntry->AuthAssocNotInProgressFlag, pEntry->wcid)); + } + if(tr_entry == NULL) + DBGPRINT(RT_DEBUG_TRACE, ("tr_entry is NULL.\n")); + +/* WPS_BandSteering Support */ +#if defined(BAND_STEERING) && defined(WSC_INCLUDED) + if (pAd->ApCfg.BandSteering) { + + PWSC_CTRL pWscControl = NULL; + PBND_STRG_CLI_ENTRY cli_entry = NULL; + PBND_STRG_CLI_TABLE table = NULL; + PWPS_WHITELIST_ENTRY wps_entry = NULL; + PBS_LIST_ENTRY bs_whitelist_entry = NULL; + + pWscControl = &pAd->ApCfg.MBSSID[wdev->func_idx].WscControl; + table = Get_BndStrgTable(pAd, wdev->func_idx); + if (table && table->bEnabled) { + + cli_entry = BndStrg_TableLookup(table, pEntry->Addr); + wps_entry = FindWpsWhiteListEntry(&table->WpsWhiteList, pEntry->Addr); + + /* WPS: special WIN7 case: no wps/rsn ie in assoc */ + /* and send eapol start, consider it as wps station */ + if ((ie_list->RSNIE_Len == 0) && (BNDSTRG_IS_WPA_CAPABILITY(wdev->AuthMode)) + && (pWscControl->WscConfMode != WSC_DISABLE)) + ie_list->bWscCapable = TRUE; + + /* in case probe did not have wps ie, but assoc has, create wps whitelist entry here */ + if (!wps_entry && ie_list->bWscCapable && pWscControl->bWscTrigger) { + + NdisAcquireSpinLock(&table->WpsWhiteListLock); + AddWpsWhiteList(&table->WpsWhiteList, pEntry->Addr); + NdisReleaseSpinLock(&table->WpsWhiteListLock); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("channel %u: WPS Assoc req: STA %02x:%02x:%02x:%02x:%02x:%02x wps whitelisted\n", + table->Channel, PRINT_MAC(pEntry->Addr))); + BND_STRG_PRINTQAMSG(table, pEntry->Addr, ("ASSOC STA %02x:%02x:%02x:%02x:%02x:%02x channel %u added in WPS Whitelist\n", + PRINT_MAC(pEntry->Addr), table->Channel)); + } + + bs_whitelist_entry = FindBsListEntry(&table->WhiteList, pEntry->Addr); + + /* handle case: where a client has wps ie in probe, not have bndstrg entry/bndstrg whitelist, */ + /* but doing normal assoc: dont allow */ + if ((pWscControl->bWscTrigger) && (!cli_entry) && (!ie_list->bWscCapable) && (!bs_whitelist_entry)) { + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("\n%s():reject assoc:bWscTrigger:%d, cli_entry:%p,bWscCapable:%d, bs_whitelist_entry:%p\n", + __func__, pWscControl->bWscTrigger, cli_entry, ie_list->bWscCapable, bs_whitelist_entry)); + BND_STRG_PRINTQAMSG(table, pEntry->Addr, ("STA %02x:%02x:%02x:%02x:%02x:%02x Normal Assoc Rejected for BS unauthorized client\n", + PRINT_MAC(pEntry->Addr))); + goto LabelOK; + } + } + } +#endif + +#ifdef WSC_AP_SUPPORT + wsc_ctrl = &pMbss->WscControl; +#endif /* WSC_AP_SUPPORT */ + + PhyMode = wdev->PhyMode; + + FlgIs11bSta = 1; + for(i=0; iSupportedRatesLen; i++) + { + if (((ie_list->SupportedRates[i] & 0x7F) != 2) && + ((ie_list->SupportedRates[i] & 0x7F) != 4) && + ((ie_list->SupportedRates[i] & 0x7F) != 11) && + ((ie_list->SupportedRates[i] & 0x7F) != 22)) + { + FlgIs11bSta = 0; + break; + } + } +#ifdef MBO_SUPPORT + if (!MBO_AP_ALLOW_ASSOC(wdev)) { + StatusCode = MLME_ASSOC_REJ_UNABLE_HANDLE_STA; + bMboReject = TRUE; +#ifdef WAPP_SUPPORT + wapp_assoc_fail = MLME_UNABLE_HANDLE_STA; +#endif/* WAPP_SUPPORT */ + goto SendAssocResponse; + } +#endif/* MBO_SUPPORT */ +#ifdef DOT11W_PMF_SUPPORT + if (tr_entry && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED) + && (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE)) +#ifdef DOT11R_FT_SUPPORT + && (!IS_FT_RSN_STA(pEntry)) +#endif /* DOT11R_FT_SUPPORT */ + ) + { + StatusCode = MLME_ASSOC_REJ_TEMPORARILY; +#ifdef WAPP_SUPPORT + wapp_assoc_fail = MLME_ASSOC_REJ_TEMP; +#endif/* WAPP_SUPPORT */ + goto SendAssocResponse; + } +#endif /* DOT11W_PMF_SUPPORT */ + + /* clear the previous Pairwise key table */ +#ifdef DOT11R_FT_SUPPORT + NdisZeroMemory(zeroFT, LEN_TK); +#endif + + if (pEntry->Aid != 0 && +#ifdef DOT11R_FT_SUPPORT + (!IS_FT_STA(pEntry) || (IS_FT_STA(pEntry) && (NdisEqualMemory(&pEntry->PTK[OFFSET_OF_PTK_TK], + zeroFT, LEN_TK) || !NdisEqualMemory(&pEntry->PTK[OFFSET_OF_PTK_TK], pEntry->LastTK, LEN_TK)))) && +#endif + (pEntry->WepStatus >= Ndis802_11TKIPEnable +#ifdef DOT1X_SUPPORT + || wdev->IEEE8021X +#endif /* DOT1X_SUPPORT */ + )) + { + /* clear GTK state */ + pEntry->GTKState = REKEY_NEGOTIATING; + + NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY)); + + /* clear this entry as no-security mode */ + AsicRemovePairwiseKeyEntry(pAd, pEntry->wcid); + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + CmdProcAddRemoveKey(pAd, 1, pEntry->func_tb_idx, 0, pEntry->wcid, PAIRWISEKEYTABLE, &pEntry->PairwiseKey, pEntry->Addr); +#endif + +#ifdef DOT1X_SUPPORT + /* Notify 802.1x daemon to clear this sta info */ + if (pEntry->AuthMode == Ndis802_11AuthModeWPA || + pEntry->AuthMode == Ndis802_11AuthModeWPA2 || + wdev->IEEE8021X) + DOT1X_InternalCmdAction(pAd, pEntry, DOT1X_DISCONNECT_ENTRY); +#endif /* DOT1X_SUPPORT */ + +#ifdef WAPI_SUPPORT + WAPI_InternalCmdAction(pAd, + pEntry->AuthMode, + pEntry->func_tb_idx, + pEntry->Addr, + WAI_MLME_DISCONNECT); + + RTMPCancelWapiRekeyTimerAction(pAd, pEntry); +#endif /* WAPI_SUPPORT */ + } + +#ifdef MT_PS +#ifdef MT_MAC + + tr_entry->ps_state = APPS_RETRIEVE_IDLE; + +#endif /* MT_MAC */ +#endif /* MT_PS */ + +#ifdef WSC_AP_SUPPORT + /* since sta has been left, ap should receive EapolStart and EapRspId again. */ + pEntry->Receive_EapolStart_EapRspId = 0; + pEntry->bWscCapable = ie_list->bWscCapable; +#ifdef WSC_V2_SUPPORT + if ((wsc_ctrl->WscV2Info.bEnableWpsV2) && + (wsc_ctrl->WscV2Info.bWpsEnable == FALSE)) + ; + else +#endif /* WSC_V2_SUPPORT */ + { + if (pEntry->func_tb_idx < pAd->ApCfg.BssidNum) + { + if (MAC_ADDR_EQUAL(pEntry->Addr, wsc_ctrl->EntryAddr)) + { + BOOLEAN Cancelled; + RTMPZeroMemory(wsc_ctrl->EntryAddr, MAC_ADDR_LEN); + RTMPCancelTimer(&wsc_ctrl->EapolTimer, &Cancelled); + wsc_ctrl->EapolTimerRunning = FALSE; + } + } + + if ((ie_list->RSNIE_Len == 0) && + (wdev->AuthMode >= Ndis802_11AuthModeWPA) && + (wsc_ctrl->WscConfMode != WSC_DISABLE)) + pEntry->bWscCapable = TRUE; + } +#endif /* WSC_AP_SUPPORT */ + + /* for hidden SSID sake, SSID in AssociateRequest should be fully verified */ + if ((ie_list->SsidLen != pMbss->SsidLen) || + (NdisEqualMemory(ie_list->Ssid, pMbss->Ssid, ie_list->SsidLen)==0)) + goto LabelOK; + +#ifdef WSC_V2_SUPPORT + /* Do not check ACL when WPS V2 is enabled and ACL policy is positive. */ + if ((pEntry->bWscCapable) && + (wsc_ctrl->WscConfMode != WSC_DISABLE) && + (wsc_ctrl->WscV2Info.bEnableWpsV2) && + (wsc_ctrl->WscV2Info.bWpsEnable) && + (MAC_ADDR_EQUAL(wsc_ctrl->EntryAddr, ZERO_MAC_ADDR))) + ; + else +#endif /* WSC_V2_SUPPORT */ +#ifdef WH_EZ_SETUP + /* + Do not check ACL when easy setup is enabled. + */ + if (IS_EZ_SETUP_ENABLED(wdev) && + pEntry->easy_setup_enabled) { + EZ_DEBUG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("Easy Setup Peer - %02x:%02x:%02x:%02x:%02x:%02x, ignore acl checking.\n", + PRINT_MAC(pEntry->Addr))); + } + else +#endif /* WH_EZ_SETUP */ + + /* set a flag for sending Assoc-Fail response to unwanted STA later. */ + if (!ApCheckAccessControlList(pAd, ie_list->Addr2, pEntry->func_tb_idx)) + bACLReject = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s - MBSS(%d), receive %s request from %02x:%02x:%02x:%02x:%02x:%02x\n", + sAssoc, pEntry->func_tb_idx, sAssoc, PRINT_MAC(ie_list->Addr2))); + + /* supported rates array may not be sorted. sort it and find the maximum rate */ + for (i=0; iSupportedRatesLen; i++) + { + if (MaxSupportedRate < (ie_list->SupportedRates[i] & 0x7f)) + MaxSupportedRate = ie_list->SupportedRates[i] & 0x7f; + } + + /* + Assign RateLen here or we will select wrong rate table in + APBuildAssociation() when 11N compile option is disabled. + */ + pEntry->RateLen = ie_list->SupportedRatesLen; + +#ifdef DOT11_VHT_AC +#ifdef RT_BIG_ENDIAN + // TODO: shiang-usw, change this endian swap mechanism! + NdisCopyMemory(&tmp_1,&ie_list->vht_cap.vht_cap, 4); + tmp_1=SWAP32(tmp_1); + NdisCopyMemory(&ie_list->vht_cap.vht_cap,&tmp_1, 4); + + NdisCopyMemory(&tmp_2,&(ie_list->vht_cap.mcs_set), 8); + tmp_2=SWAP64(tmp_2); + NdisCopyMemory(&(ie_list->vht_cap.mcs_set),&tmp_2, 8); + //SWAP32((UINT32)vht_cap_ie.vht_cap); + //SWAP32((UINT32)vht_cap_ie.mcs_set); +#endif /* RT_BIG_ENDIAN */ +#endif + + RTMPSetSupportMCS(pAd, + OPMODE_AP, + pEntry, + ie_list->SupportedRates, + ie_list->SupportedRatesLen, + NULL, + 0, +#ifdef DOT11_VHT_AC + ie_list->vht_cap_len, + &ie_list->vht_cap, +#endif /* DOT11_VHT_AC */ + &ie_list->HTCapability, + ie_list->ht_cap_len); + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev) && + pEntry->easy_setup_enabled) { + unsigned short Status = ez_process_assoc_request(wdev, pEntry, isReassoc, Elem->Msg, Elem->MsgLen); + if (Status == EZ_STATUS_CODE_UNKNOWN) { + StatusCode = MLME_REJ_TIMEOUT; +#ifdef WAPP_SUPPORT + wapp_assoc_fail = MLME_REJECT_TIMEOUT; +#endif/* WAPP_SUPPORT */ + } else if (Status == EZ_STATUS_CODE_INVALID_DATA) { + StatusCode = MLME_REQUEST_WITH_INVALID_PARAM; +#ifdef WAPP_SUPPORT + wapp_assoc_fail = MLME_REQ_WITH_INVALID_PARAM; +#endif/* WAPP_SUPPORT */ + } else if (Status == EZ_STATUS_CODE_LOOP) { + StatusCode = MLME_EZ_CONNECTION_LOOP; +#ifdef WAPP_SUPPORT + wapp_assoc_fail = MLME_EZ_CNNCT_LOOP; +#endif/* WAPP_SUPPORT */ + } + if (StatusCode != MLME_SUCCESS) + { + goto SendAssocResponse; + } + } +#endif /* WH_EZ_SETUP */ + + /* 2. qualify this STA's auth_asoc status in the MAC table, decide StatusCode */ + StatusCode = APBuildAssociation(pAd, pEntry, ie_list, MaxSupportedRate, &Aid); +#ifdef WAPP_SUPPORT + if (StatusCode != MLME_SUCCESS) + wapp_assoc_fail = MLME_UNABLE_HANDLE_STA; +#endif/* WAPP_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + if (pEntry->func_tb_idx < pAd->ApCfg.BssidNum) + { + pFtCfg = &(pMbss->FtCfg); + if ((pFtCfg->FtCapFlag.Dot11rFtEnable) + && (StatusCode == MLME_SUCCESS)) + StatusCode = FT_AssocReqHandler(pAd, isReassoc, pFtCfg, pEntry, + &ie_list->FtInfo, &FtInfoBuf); +#ifdef WAPP_SUPPORT + if (StatusCode != MLME_SUCCESS) + wapp_assoc_fail = FT_ERROR; +#endif/* WAPP_SUPPORT */ + /* just silencely discard this frame */ + if (StatusCode == 0xFFFF) + goto LabelOK; + } +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT + if ((pEntry->func_tb_idx < pAd->ApCfg.BssidNum) + && IS_RRM_ENABLE(pAd, pEntry->func_tb_idx)) + { + pEntry->RrmEnCap.word = ie_list->RrmEnCap.word; + } +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11_VHT_AC + if (ie_list->vht_cap_len) + { +//+++Add by shiang for debug + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) { + DBGPRINT(RT_DEBUG_TRACE, ("%s():Peer is VHT capable device!\n", __FUNCTION__)); + + NdisMoveMemory(&pEntry->ext_cap, &ie_list->ExtCapInfo, sizeof(ie_list->ExtCapInfo)); + DBGPRINT(RT_DEBUG_TRACE, ("\tOperatingModeNotification=%d\n", + pEntry->ext_cap.operating_mode_notification)); + //dump_vht_cap(pAd, &ie_list->vht_cap); + } +//---Add by shiang for debug + } +#endif /* DOT11_VHT_AC */ + + if (StatusCode == MLME_ASSOC_REJ_DATA_RATE) + RTMPSendWirelessEvent(pAd, IW_STA_MODE_EVENT_FLAG, pEntry->Addr, wdev->wdev_idx, 0); + +#ifdef WH_EVENT_NOTIFIER + if (pEntry && tr_entry && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + EventHdlr pEventHdlrHook = NULL; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_STA_JOIN); + if(pEventHdlrHook && pEntry->wdev) + pEventHdlrHook(pAd, pEntry, Elem); + } +#endif /* WH_EVENT_NOTIFIER */ + + +#if (defined(DOT11W_PMF_SUPPORT) || defined(WH_EZ_SETUP)) +SendAssocResponse: +#endif /* DOT11W_PMF_SUPPORT */ + /* 3. send Association Response */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + goto LabelOK; + + DBGPRINT(RT_DEBUG_TRACE, ("%s - Send %s response (Status=%d)...\n", sAssoc, sAssoc, StatusCode)); + Aid |= 0xc000; /* 2 most significant bits should be ON */ + + SubType = isReassoc ? SUBTYPE_REASSOC_RSP : SUBTYPE_ASSOC_RSP; + + CapabilityInfoForAssocResp = pMbss->CapabilityInfo; /*use AP's cability */ +#ifdef WSC_AP_SUPPORT +#ifdef WSC_V2_SUPPORT + if ((wsc_ctrl->WscV2Info.bEnableWpsV2) && + (wsc_ctrl->WscV2Info.bWpsEnable == FALSE)) + ; + else +#endif /* WSC_V2_SUPPORT */ + { + if ((wsc_ctrl->WscConfMode != WSC_DISABLE) && + (ie_list->CapabilityInfo & 0x0010)) + { + CapabilityInfoForAssocResp |= 0x0010; + } + } +#endif /* WSC_AP_SUPPORT */ + + /* fail in ACL checking => send an Assoc-Fail resp. */ +#ifdef DYNAMIC_RX_RATE_ADJ + SupRateLen = pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SupRateLen; +#else + SupRateLen = pAd->CommonCfg.SupRateLen; +#endif /* DYNAMIC_RX_RATE_ADJ */ + + /* TODO: need to check rate in support rate element, not number */ + if (PhyMode == WMODE_B) + SupRateLen = 4; + + /* YF@20120419: Refuse the weak signal of AssocReq */ + rssi = RTMPMaxRssi(pAd, + ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_0), + ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_1), + ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_2)); + DBGPRINT(RT_DEBUG_TRACE, ("ra[%d] ASSOC_REQ Threshold = %d, PktMaxRssi=%d\n", + pEntry->func_tb_idx, pAd->ApCfg.MBSSID[pEntry->func_tb_idx].AssocReqRssiThreshold, + rssi)); + if ((pAd->ApCfg.MBSSID[pEntry->func_tb_idx].AssocReqRssiThreshold != 0) && (rssi < pAd->ApCfg.MBSSID[pEntry->func_tb_idx].AssocReqRssiThreshold)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Reject this ASSOC_REQ due to Weak Signal.\n")); + bAssocSkip = TRUE; + } + + if (bACLReject == TRUE || bAssocSkip) + { + MgtMacHeaderInit(pAd, &AssocRspHdr, SubType, 0, ie_list->Addr2, + wdev->if_addr, wdev->bssid); + StatusCode = MLME_UNSPECIFY_FAIL; +#ifdef WAPP_SUPPORT + wapp_assoc_fail = MLME_UNSPECIFY_FAILURE; +#endif/* WAPP_SUPPORT */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &AssocRspHdr, + 2, &CapabilityInfoForAssocResp, + 2, &StatusCode, + 2, &Aid, + 1, &SupRateIe, + 1, &SupRateLen, +#ifdef DYNAMIC_RX_RATE_ADJ + SupRateLen, pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SupRate, +#else + SupRateLen, pAd->CommonCfg.SupRate, +#endif /* DYNAMIC_RX_RATE_ADJ */ + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, (PVOID) pOutBuffer); + + RTMPSendWirelessEvent(pAd, IW_MAC_FILTER_LIST_EVENT_FLAG, ie_list->Addr2, wdev->wdev_idx, 0); + +#ifdef WSC_V2_SUPPORT + /* If this STA exists, delete it. */ + if (pEntry) + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); +#endif /* WSC_V2_SUPPORT */ + + if (bAssocSkip == TRUE) + { + pEntry = MacTableLookup(pAd, ie_list->Addr2); + if (pEntry) + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + } + + goto LabelOK; + } + + MgtMacHeaderInit(pAd, &AssocRspHdr, SubType, 0, ie_list->Addr2, + wdev->if_addr, wdev->bssid); + { + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &AssocRspHdr, + 2, &CapabilityInfoForAssocResp, + 2, &StatusCode, + 2, &Aid, + 1, &SupRateIe, + 1, &SupRateLen, +#ifdef DYNAMIC_RX_RATE_ADJ + SupRateLen, pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SupRate, +#else + SupRateLen, pAd->CommonCfg.SupRate, +#endif /* DYNAMIC_RX_RATE_ADJ */ + END_OF_ARGS); + } + +#ifdef DYNAMIC_RX_RATE_ADJ + if ((pAd->ApCfg.MBSSID[pEntry->func_tb_idx].ExtRateLen) && (PhyMode != WMODE_B) && (FlgIs11bSta == 0)) +#else + if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != WMODE_B) && (FlgIs11bSta == 0)) +#endif /* DYNAMIC_RX_RATE_ADJ */ + { + ULONG TmpLen; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &ExtRateIe, +#ifdef DYNAMIC_RX_RATE_ADJ + 1, &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].ExtRateLen, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].ExtRateLen, pAd->ApCfg.MBSSID[pEntry->func_tb_idx].ExtRate, + +#else + 1, &pAd->CommonCfg.ExtRateLen, + pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, +#endif /* DYNAMIC_RX_RATE_ADJ */ + END_OF_ARGS); + FrameLen += TmpLen; + } + +#ifdef DOT11R_FT_SUPPORT + if ((pFtCfg != NULL) && (pFtCfg->FtCapFlag.Dot11rFtEnable)) + { + PUINT8 mdie_ptr; + UINT8 mdie_len; + PUINT8 ftie_ptr = NULL; + UINT8 ftie_len = 0; + PUINT8 ricie_ptr = NULL; + UINT8 ricie_len = 0; + + /* Insert RSNIE if necessary */ + if (FtInfoBuf.RSNIE_Len != 0) + { + ULONG TmpLen; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + FtInfoBuf.RSNIE_Len, FtInfoBuf.RSN_IE, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* Insert MDIE. */ + mdie_ptr = pOutBuffer+FrameLen; + mdie_len = 5; + /* Insert MdId only if the Peer has sent one */ + if (FtInfoBuf.MdIeInfo.Len != 0) { + FT_InsertMdIE(pAd, pOutBuffer+FrameLen, &FrameLen, + FtInfoBuf.MdIeInfo.MdId, FtInfoBuf.MdIeInfo.FtCapPlc); + } + /* Insert FTIE. */ + if (FtInfoBuf.FtIeInfo.Len != 0) + { + ftie_ptr = pOutBuffer+FrameLen; + ftie_len = (2 + FtInfoBuf.FtIeInfo.Len); + FT_InsertFTIE(pAd, pOutBuffer+FrameLen, &FrameLen, + FtInfoBuf.FtIeInfo.Len, FtInfoBuf.FtIeInfo.MICCtr, + FtInfoBuf.FtIeInfo.MIC, FtInfoBuf.FtIeInfo.ANonce, + FtInfoBuf.FtIeInfo.SNonce); + } + /* Insert R1KH IE into FTIE. */ + if (FtInfoBuf.FtIeInfo.R1khIdLen!= 0) + FT_FTIE_InsertKhIdSubIE(pAd, pOutBuffer+FrameLen, &FrameLen, + FT_R1KH_ID, FtInfoBuf.FtIeInfo.R1khId, + FtInfoBuf.FtIeInfo.R1khIdLen); + + /* Insert GTK Key info into FTIE. */ + if (FtInfoBuf.FtIeInfo.GtkLen!= 0) + FT_FTIE_InsertGTKSubIE(pAd, pOutBuffer+FrameLen, &FrameLen, + FtInfoBuf.FtIeInfo.GtkSubIE, FtInfoBuf.FtIeInfo.GtkLen); + + /* Insert R0KH IE into FTIE. */ + if (FtInfoBuf.FtIeInfo.R0khIdLen!= 0) + FT_FTIE_InsertKhIdSubIE(pAd, pOutBuffer+FrameLen, &FrameLen, + FT_R0KH_ID, FtInfoBuf.FtIeInfo.R0khId, + FtInfoBuf.FtIeInfo.R0khIdLen); + + /* Insert RIC. */ + if (ie_list->FtInfo.RicInfo.Len) + { + ULONG TempLen; + + FT_RIC_ResourceRequestHandle(pAd, pEntry, + (PUCHAR)ie_list->FtInfo.RicInfo.pRicInfo, + ie_list->FtInfo.RicInfo.Len, + (PUCHAR)pOutBuffer+FrameLen, + (PUINT32)&TempLen); + ricie_ptr = (PUCHAR)(pOutBuffer+FrameLen); + ricie_len = TempLen; + FrameLen += TempLen; + } + + /* Calculate the FT MIC for FT procedure */ + if (FtInfoBuf.FtIeInfo.MICCtr.field.IECnt) + { + UINT8 ft_mic[FT_MIC_LEN]; + PFT_FTIE pFtIe; + + NdisZeroMemory(ft_mic, sizeof(ft_mic)); + FT_CalculateMIC(pEntry->Addr, + wdev->bssid, + pEntry->PTK, + 6, + FtInfoBuf.RSN_IE, + FtInfoBuf.RSNIE_Len, + mdie_ptr, + mdie_len, + ftie_ptr, + ftie_len, + ricie_ptr, + ricie_len, + ft_mic); + + /* Update the MIC field of FTIE */ + pFtIe = (PFT_FTIE)(ftie_ptr + 2); + NdisMoveMemory(pFtIe->MIC, ft_mic, FT_MIC_LEN); + /*Install pairwise key,Update status,set Port as Secured*/ + if (!IS_FT_STA(pEntry) || (IS_FT_STA(pEntry) && + (NdisEqualMemory(&pEntry->PTK[OFFSET_OF_PTK_TK], zeroFT, LEN_TK) || + !NdisEqualMemory(&pEntry->PTK[OFFSET_OF_PTK_TK], pEntry->LastTK, LEN_TK)))) { + WPAInstallPairwiseKey(pAd, pEntry->func_tb_idx, pEntry, TRUE); + NdisMoveMemory(pEntry->LastTK, &pEntry->PTK[OFFSET_OF_PTK_TK], LEN_TK); + } +#ifdef MBO_SUPPORT + /* YF_FT */ + if (IS_MBO_ENABLE(wdev)) + /* update STA bssid & security info to daemon */ + MboIndicateStaBssidInfo(pAd, wdev, pEntry->Addr); +#endif/* MBO_SUPPORT */ + pEntry->WpaState = AS_PTKINITDONE; + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + tr_entry->PortSecured = WPA_802_1X_PORT_SECURED; + +#ifdef WH_EVENT_NOTIFIER + { /*Hasan Add this event to cover FT case*/ + EventHdlr pEventHdlrHook = NULL; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_STA_JOIN); + if(pEventHdlrHook && pEntry->wdev) + pEventHdlrHook(pAd, pEntry, Elem); + } +#endif + + } + + /* Record the MDIE & FTIE of (re)association response of + Initial Mobility Domain Association. It's used in + FT 4-Way handshaking */ + if (pEntry->AuthMode >= Ndis802_11AuthModeWPA2 && + ie_list->FtInfo.FtIeInfo.Len == 0) + { + NdisMoveMemory(&pEntry->InitialMDIE, mdie_ptr, mdie_len); + + pEntry->InitialFTIE_Len = ftie_len; + NdisMoveMemory(pEntry->InitialFTIE, ftie_ptr, ftie_len); + } + } +#endif /* DOT11R_FT_SUPPORT */ +#ifdef DOT11K_RRM_SUPPORT + if (IS_RRM_ENABLE(pAd, pEntry->func_tb_idx)) + RRM_InsertRRMEnCapIE(pAd, pOutBuffer+FrameLen, &FrameLen, pEntry->func_tb_idx); +#endif /* DOT11K_RRM_SUPPORT */ + + /* add WMM IE here */ + if (wdev->bWmmCapable && CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)) + { + ULONG TmpLen; + UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; + + WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; +#ifdef UAPSD_SUPPORT + UAPSD_MR_IE_FILL(WmeParmIe[8], &pMbss->wdev.UapsdInfo); +#endif /* UAPSD_SUPPORT */ + for (i = QID_AC_BE; i <= QID_AC_VO; i++) + { + WmeParmIe[10+ (i*4)] = (i << 5) + /* b5-6 is ACI */ + ((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + /* b4 is ACM */ + (pAd->ApCfg.BssEdcaParm.Aifsn[i] & 0x0f); /* b0-3 is AIFSN */ + WmeParmIe[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + /* b5-8 is CWMAX */ + (pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); /* b0-3 is CWMIN */ + WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff); /* low byte of TXOP */ + WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); /* high byte of TXOP */ + } + + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 26, WmeParmIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + +#ifdef DOT11W_PMF_SUPPORT + if (StatusCode == MLME_ASSOC_REJ_TEMPORARILY) { + ULONG TmpLen; + UCHAR IEType = IE_TIMEOUT_INTERVAL; //IE:0x15 + UCHAR IELen = 5; + UCHAR TIType = 3; + UINT32 units = 1 << 10; //1 seconds, should be 0x3E8 + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &IEType, + 1, &IELen, + 1, &TIType, + 4, &units, + END_OF_ARGS); + FrameLen += TmpLen; + } +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + /* HT capability in AssocRsp frame. */ + if ((ie_list->ht_cap_len > 0) && WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + ULONG TmpLen; + UCHAR HtLen1 = sizeof(pAd->CommonCfg.AddHTInfo); + HT_CAPABILITY_IE HtCapabilityRsp; +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; + ADD_HT_INFO_IE addHTInfoTmp; +#endif + + NdisMoveMemory(&HtCapabilityRsp, &pAd->CommonCfg.HtCapability, ie_list->ht_cap_len); + +#ifdef DYNAMIC_RX_RATE_ADJ + NdisMoveMemory(HtCapabilityRsp.MCSSet, pAd->ApCfg.MBSSID[pEntry->func_tb_idx].ExpectedSuppHTMCSSet, 4); +#endif /* DYNAMIC_RX_RATE_ADJ */ + + /* add HT Capability IE */ +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &ie_list->ht_cap_len, + ie_list->ht_cap_len, &HtCapabilityRsp, + 1, &AddHtInfoIe, + 1, &HtLen1, + HtLen1, &pAd->CommonCfg.AddHTInfo, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &HtCapabilityRsp, ie_list->ht_cap_len); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); +#ifdef UNALIGNMENT_SUPPORT + { + EXT_HT_CAP_INFO extHtCapInfo; + + NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); + NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + } +#else + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); +#endif /* UNALIGNMENT_SUPPORT */ + + NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, HtLen1); + *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); + *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &ie_list->ht_cap_len, + ie_list->ht_cap_len, &HtCapabilityTmp, + 1, &AddHtInfoIe, + 1, &HtLen1, + HtLen1, &addHTInfoTmp, + END_OF_ARGS); +#endif + FrameLen += TmpLen; + + if ((ie_list->RalinkIe) == 0 || (pAd->bBroadComHT == TRUE)) + { + UCHAR epigram_ie_len; + UCHAR BROADCOM_HTC[4] = {0x0, 0x90, 0x4c, 0x33}; + UCHAR BROADCOM_AHTINFO[4] = {0x0, 0x90, 0x4c, 0x34}; + + + epigram_ie_len = ie_list->ht_cap_len + 4; +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_HTC[0], + ie_list->ht_cap_len, &HtCapabilityRsp, + END_OF_ARGS); +#else + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_HTC[0], + ie_list->ht_cap_len, &HtCapabilityTmp, + END_OF_ARGS); +#endif + + FrameLen += TmpLen; + epigram_ie_len = HtLen1 + 4; +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_AHTINFO[0], + HtLen1, &pAd->CommonCfg.AddHTInfo, + END_OF_ARGS); +#else + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_AHTINFO[0], + HtLen1, &addHTInfoTmp, + END_OF_ARGS); +#endif + FrameLen += TmpLen; + } + +#ifdef DOT11N_DRAFT3 + /* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */ + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1)) + { + OVERLAP_BSS_SCAN_IE OverlapScanParam; + ULONG TmpLen; + UCHAR OverlapScanIE, ScanIELen; + + OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; + ScanIELen = 14; + OverlapScanParam.ScanPassiveDwell = cpu2le16(pAd->CommonCfg.Dot11OBssScanPassiveDwell); + OverlapScanParam.ScanActiveDwell = cpu2le16(pAd->CommonCfg.Dot11OBssScanActiveDwell); + OverlapScanParam.TriggerScanInt = cpu2le16(pAd->CommonCfg.Dot11BssWidthTriggerScanInt); + OverlapScanParam.PassiveTalPerChannel = cpu2le16(pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel); + OverlapScanParam.ActiveTalPerChannel = cpu2le16(pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel); + OverlapScanParam.DelayFactor = cpu2le16(pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor); + OverlapScanParam.ScanActThre = cpu2le16(pAd->CommonCfg.Dot11OBssScanActivityThre); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &OverlapScanIE, + 1, &ScanIELen, + ScanIELen, &OverlapScanParam, + END_OF_ARGS); + + FrameLen += TmpLen; + } +#endif /* DOT11N_DRAFT3 */ + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14) && + (ie_list->vht_cap_len)) + { + FrameLen += build_vht_ies(pAd, pOutBuffer + FrameLen, SUBTYPE_ASSOC_RSP); + } +#endif /* DOT11_VHT_AC */ + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef CONFIG_HOTSPOT_R2 + /* qosmap IE */ + printk("entry=%d\n", pEntry->QosMapSupport); + if (pEntry->QosMapSupport) + { + ULONG TmpLen; + UCHAR QosMapIE, ielen = 0, i = 0, explen = 0; + PHOTSPOT_CTRL pHSCtrl = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].HotSpotCtrl; + + if (pHSCtrl->QosMapEnable) + { + QosMapIE = IE_QOS_MAP_SET; + + for (i=0;i<21;i++) + { + if (pHSCtrl->DscpException[i] == 0xffff) + break; + else + explen += 2; + } + + pEntry->DscpExceptionCount = explen; + memcpy((UCHAR *)pEntry->DscpRange, (UCHAR *)pHSCtrl->DscpRange, 16); + memcpy((UCHAR *)pEntry->DscpException, (UCHAR *)pHSCtrl->DscpException, 42); + + ielen = explen+16; + + MakeOutgoingFrame(pOutBuffer+ FrameLen, &TmpLen, + 1, &QosMapIE, + 1, &ielen, + explen, pEntry->DscpException, + 16, pEntry->DscpRange, + END_OF_ARGS); + + FrameLen += TmpLen; + } + } +#endif /* CONFIG_HOTSPOT_R2 */ + +#ifdef CONFIG_OWE_SUPPORT + if (pEntry->AuthMode == Ndis802_11AuthModeOWE) { + ULONG TmpLen; + UCHAR RSNE_EID; + UCHAR RSNIE_Len; + UCHAR *RSN_IE; + + WPAMakeEntryRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, pEntry); + RSNE_EID = IE_WPA2; + RSNIE_Len = pEntry->RSNE_Len[0]; + RSN_IE = pEntry->RSNE_Content[0]; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &RSNE_EID, + 1, &RSNIE_Len, + RSNIE_Len, + RSN_IE, + END_OF_ARGS); + + FrameLen += TmpLen; + } + +#endif + + /* 7.3.2.27 Extended Capabilities IE */ + { + ULONG TmpLen, infoPos; + PUCHAR pInfo; + UCHAR extInfoLen; + BOOLEAN bNeedAppendExtIE = FALSE; + EXT_CAP_INFO_ELEMENT extCapInfo = {0}; + + + extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); + //NdisZeroMemory(&extCapInfo, extInfoLen); + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* P802.11n_D1.10, HT Information Exchange Support */ + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) + && (pAd->CommonCfg.Channel <= 14) + && (pAd->CommonCfg.bBssCoexEnable == TRUE) + ) + { + extCapInfo.BssCoexistMgmtSupport = 1; + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef CONFIG_DOT11V_WNM + if (pMbss->WNMCtrl.WNMBTMEnable) + extCapInfo.BssTransitionManmt = 1; + if (ie_list->ExtCapInfo.BssTransitionManmt == 1) + pEntry->bBSSMantSTASupport = TRUE; +#endif /* CONFIG_DOT11V_WNM */ +#ifdef DOT11U_INTERWORKING + if (pMbss->GASCtrl.b11U_enable) + extCapInfo.interworking = 1; +#endif/* DOT11U_INTERWORKING */ + +#ifdef DOT11V_WNM_SUPPORT + if (IS_BSS_TRANSIT_MANMT_SUPPORT(pAd, pEntry->func_tb_idx)) + { + if( ie_list->ExtCapInfo.BssTransitionManmt == 1) + { + extCapInfo.BssTransitionManmt = 1; + pEntry->bBSSMantSTASupport = TRUE; + } + } + if (IS_WNMDMS_SUPPORT(pAd, pEntry->func_tb_idx)) + { + if ( ie_list->ExtCapInfo.DMSSupport == 1) + { + extCapInfo.DMSSupport = 1; + pEntry->bDMSSTASupport = TRUE; + } + } +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14)) + extCapInfo.operating_mode_notification = 1; +#endif /* DOT11_VHT_AC */ + + pInfo = (UCHAR *)(&extCapInfo); + for (infoPos = 0; infoPos < extInfoLen; infoPos++) + { + if (pInfo[infoPos] != 0) + { + bNeedAppendExtIE = TRUE; + break; + } + } + + if (bNeedAppendExtIE == TRUE) + { +#ifdef RT_BIG_ENDIAN + *((UINT32*)(pInfo)) = SWAP32(*((UINT32*)(pInfo))); + *((UINT32*)(pInfo+4)) = SWAP32(*((UINT32*)(pInfo+4))); +#endif + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &ExtCapIe, + 1, &extInfoLen, + extInfoLen, &extCapInfo, + END_OF_ARGS); + FrameLen += TmpLen; + } + } +#ifdef WH_EZ_SETUP + /* + To prevent old device has trouble to parse MTK vendor IE, + insert easy setup IE first. + */ + if ((StatusCode == MLME_SUCCESS) + && IS_EZ_SETUP_ENABLED(wdev) + && pEntry->easy_setup_enabled) { + + FrameLen += ez_build_assoc_response_ie(wdev, + pEntry->Addr, &pMbss->GTK[0], LEN_MAX_GTK, pOutBuffer+FrameLen); + } + //FrameLen += build_vendor_ie(pAd, wdev, (pOutBuffer + FrameLen), SubType); +#endif /* WH_EZ_SETUP */ + + /* add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back */ +#if defined(MWDS) || defined(WH_EZ_SETUP) + FrameLen += build_vendor_ie(pAd, wdev, pOutBuffer+FrameLen +#ifdef CONFIG_OWE_SUPPORT + , VIE_ASSOC_RESP +#endif +#ifdef WH_EZ_SETUP + , SubType +#endif + ); +#else +{ + 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; + +} +#endif + +#ifdef MBO_SUPPORT + if (IS_MBO_ENABLE(wdev)) + MakeMboOceIE(pAd, wdev, pOutBuffer+FrameLen, &FrameLen, MBO_FRAME_TYPE_ASSOC_RSP); +#endif/* MBO_SUPPORT */ + +#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->func_tb_idx, 0, pWscBuf, &WscIeLen); + MakeOutgoingFrame(pOutBuffer + FrameLen, &WscTmpLen, + WscIeLen, pWscBuf, + END_OF_ARGS); + + FrameLen += WscTmpLen; + os_free_mem(NULL, pWscBuf); + } + } +#endif /* WSC_AP_SUPPORT */ + + +#ifdef CONFIG_OWE_SUPPORT + if ((pEntry->AuthMode == Ndis802_11AuthModeOWE) && (StatusCode == MLME_SUCCESS)) { + BOOLEAN need_ecdh_ie = FALSE; + INT CacheIdx;/* Key cache */ + + pPmkid = WPA_ExtractSuiteFromRSNIE(ie_list->RSN_IE, ie_list->RSNIE_Len, PMKID_LIST, &pmkid_count); + if (pPmkid != NULL) { + CacheIdx = RTMPSearchPMKIDCache(pAd, pEntry->func_tb_idx, pEntry->Addr); + if ((CacheIdx == -1) || + ((RTMPEqualMemory(pPmkid, + &pMbss->PMKIDCache.BSSIDInfo[CacheIdx].PMKID, + LEN_PMKID)) == 0)) { + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s: AKM_OWE_Entry PMKID not found, do normal ECDH procedure\n", + __func__)); + need_ecdh_ie = TRUE; + } + } else + need_ecdh_ie = TRUE; + + if (need_ecdh_ie == TRUE) { + FrameLen += build_owe_dh_ie(pAd, + pEntry, + (UCHAR *)pOutBuffer + FrameLen, + pEntry->owe.last_try_group); + } + } +#endif /*CONFIG_OWE_SUPPORT*/ + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, (PVOID) pOutBuffer); + +#ifdef DOT11W_PMF_SUPPORT + if (StatusCode == MLME_ASSOC_REJ_TEMPORARILY) + { + PMF_MlmeSAQueryReq(pAd, pEntry); + } +#endif /* DOT11W_PMF_SUPPORT */ + + /* set up BA session */ + if (StatusCode == MLME_SUCCESS) + { + pEntry->PsMode = PWR_ACTIVE; + // TODO: shiang-usw, we need to rmove upper setting and migrate to tr_entry->PsMode + pAd->MacTab.tr_entry[pEntry->wcid].PsMode = PWR_ACTIVE; + + wdev->allow_data_tx = TRUE; + +#ifdef IAPP_SUPPORT + /*PFRAME_802_11 Fr = (PFRAME_802_11)Elem->Msg; */ +/* POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; */ + +#ifdef WH_EZ_SETUP + if( !IS_EZ_SETUP_ENABLED(wdev) ) +#endif + { + /* send association ok message to IAPPD */ + IAPP_L2_Update_Frame_Send(pAd, pEntry->Addr, pEntry->wdev->wdev_idx); + DBGPRINT(RT_DEBUG_TRACE, ("####### Send L2 Frame Mac=%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pEntry->Addr))); + } +/* SendSingalToDaemon(SIGUSR2, pObj->IappPid); */ + +#ifdef DOT11R_FT_SUPPORT +#ifdef WH_EZ_SETUP + if (!IS_EZ_SETUP_ENABLED(wdev) /*&& !ez_is_triband()*/) // Arvind not reqiured triband check. +#endif + { + /* + Do not do any check here. + We need to send MOVE-Req frame to AP1 even open mode. + */ +/* if (IS_FT_RSN_STA(pEntry) && (FtInfo.FtIeInfo.Len != 0)) */ + if (isReassoc == 1) + { + /* only for reassociation frame */ + FT_KDP_EVT_REASSOC EvtReAssoc; + + EvtReAssoc.SeqNum = 0; + NdisMoveMemory(EvtReAssoc.MacAddr, pEntry->Addr, MAC_ADDR_LEN); + NdisMoveMemory(EvtReAssoc.OldApMacAddr, ie_list->ApAddr, MAC_ADDR_LEN); + + FT_KDP_EVENT_INFORM(pAd, pEntry->func_tb_idx, FT_KDP_SIG_FT_REASSOCIATION, + &EvtReAssoc, sizeof(EvtReAssoc), NULL); + } + } +#endif /* DOT11R_FT_SUPPORT */ + +#endif /* IAPP_SUPPORT */ + +#ifdef DBG + ap_assoc_info_debugshow(pAd, isReassoc, pEntry, ie_list); +#endif /* DBG */ + + /* send wireless event - for association */ + RTMPSendWirelessEvent(pAd, IW_ASSOC_EVENT_FLAG, pEntry->Addr, 0, 0); + +#ifdef ALL_NET_EVENT + wext_send_event(pEntry->wdev->if_dev, + pEntry->Addr, + pEntry->bssid, + pAd->CommonCfg.Channel, + RTMPAvgRssi(pAd, &pEntry->RssiSample), + FBT_LINK_ONLINE_NOTIFY); +#endif /* ALL_NET_EVENT */ + + /* This is a reassociation procedure */ + pEntry->IsReassocSta = isReassoc; + +#ifdef DOT11_N_SUPPORT + /* clear txBA bitmap */ + pEntry->TXBAbitmap = 0; + if (pEntry->MaxHTPhyMode.field.MODE >= MODE_HTMIX) + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + if ((pAd->CommonCfg.Channel <=14) && + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset && + (ie_list->HTCapability.HtCapInfo.ChannelWidth==BW_40)) + { + SendBeaconRequest(pAd, pEntry->wcid); + } + /*BAOriSessionSetUp(pAd, pEntry, 0, 0, 3000, FALSE); */ + } +#endif /* DOT11_N_SUPPORT */ + + +#ifdef DOT11R_FT_SUPPORT + /* If the length of FTIE field of the (re)association-request frame + is larger than zero, it shall indicate the Fast-BSS transition is in progress. */ + if (ie_list->FtInfo.FtIeInfo.Len > 0) + { + ; + } + else +#endif /* DOT11R_FT_SUPPORT */ +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev) && + pEntry->easy_setup_enabled) { + ez_port_secured(pAd, pEntry, pEntry->func_tb_idx, TRUE); + } + else +#endif /* WH_EZ_SETUP */ + /* enqueue a EAPOL_START message to trigger EAP state machine doing the authentication */ + + + if ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + || (pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK) + || (pEntry->AuthMode == Ndis802_11AuthModeOWE) +#endif + ) { + +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + + if (pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK || + pEntry->AuthMode == Ndis802_11AuthModeOWE) { + pPmkid = WPA_ExtractSuiteFromRSNIE(ie_list->RSN_IE, + ie_list->RSNIE_Len, + PMKID_LIST, + &pmkid_count); + + if (pPmkid != NULL) { + INT CacheIdx; + + CacheIdx = RTMPSearchPMKIDCache(pAd, pEntry->func_tb_idx, pEntry->Addr); + if (CacheIdx != -1 + && (RTMPEqualMemory(pPmkid, + &pMbss->PMKIDCache.BSSIDInfo[CacheIdx].PMKID[0], LEN_PMKID))) { + + pEntry->pmkid = pPmkid; + NdisMoveMemory(pEntry->PMK, pMbss->PMKIDCache.BSSIDInfo[CacheIdx].PMK, LEN_PMK); + pEntry->PMKID_CacheIdx = CacheIdx; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("ASSOC - 2.PMKID matched and start key cache algorithm\n")); + } else { + pEntry->pmkid = NULL; + pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("ASSOC - 2.PMKID not found\n")); + } + + + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("ASSOC - CacheIdx = %d\n", + CacheIdx)); + + } + } +#endif + +#ifdef WSC_AP_SUPPORT + /* + In WPA-PSK mode, + If Association Request of station has RSN/SSN, WPS AP Must Not send EAP-Request/Identity to station + no matter WPS AP does receive EAPoL-Start from STA or not. + Marvell WPS test bed(v2.1.1.5) will send AssocReq with WPS IE and RSN/SSN IE. + */ + if (pEntry->bWscCapable || (ie_list->RSNIE_Len == 0)) + { + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - IF(ra%d) This is a WPS Client.\n\n", pEntry->func_tb_idx)); + goto LabelOK; + } + else + { + pEntry->bWscCapable = FALSE; + pEntry->Receive_EapolStart_EapRspId = (WSC_ENTRY_GET_EAPOL_START | WSC_ENTRY_GET_EAP_RSP_ID); + /* This STA is not a WPS STA */ + NdisZeroMemory(wsc_ctrl->EntryAddr, 6); + } +#endif /* WSC_AP_SUPPORT */ + + /* Enqueue a EAPOL-start message with the pEntry for WPAPSK State Machine */ + if ((pEntry->EnqueueEapolStartTimerRunning == EAPOL_START_DISABLE +#ifdef HOSTAPD_SUPPORT + && wdev->Hostapd == Hostapd_Diable +#endif/*HOSTAPD_SUPPORT*/ + ) +#ifdef WSC_AP_SUPPORT + && !pEntry->bWscCapable +#endif /* WSC_AP_SUPPORT */ + ) + { + /* Enqueue a EAPOL-start message with the pEntry */ +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + + if ((pEntry->AuthMode != Ndis802_11AuthModeWPA3PSK) + && (pEntry->AuthMode != Ndis802_11AuthModeOWE)) + NdisMoveMemory(&pEntry->PMK, &pMbss->PMK, LEN_PMK); +#endif + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_PSK; + RTMPSetTimer(&pEntry->EnqueueStartForPSKTimer, ENQUEUE_EAPOL_START_TIMER); + } + } +#ifdef DOT1X_SUPPORT + /*else if (isReassoc && */ + else if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) && + ((pPmkid = WPA_ExtractSuiteFromRSNIE(ie_list->RSN_IE, ie_list->RSNIE_Len, PMKID_LIST, &pmkid_count)) != NULL)) + { /* Key cache */ + INT CacheIdx; + + if (((CacheIdx = RTMPSearchPMKIDCache(pAd, pEntry->func_tb_idx, pEntry->Addr)) != -1) + && (RTMPEqualMemory(pPmkid, &pMbss->PMKIDCache.BSSIDInfo[CacheIdx].PMKID, LEN_PMKID))) + { + /* Enqueue a EAPOL-start message with the pEntry for WPAPSK State Machine */ + if ((pEntry->EnqueueEapolStartTimerRunning == EAPOL_START_DISABLE +#ifdef HOSTAPD_SUPPORT + && wdev->Hostapd == Hostapd_Diable +#endif /*HOSTAPD_SUPPORT*/ + ) +#ifdef WSC_AP_SUPPORT + && !pEntry->bWscCapable +#endif /* WSC_AP_SUPPORT */ + ) + { + /* Enqueue a EAPOL-start message with the pEntry */ + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_PSK; + RTMPSetTimer(&pEntry->EnqueueStartForPSKTimer, ENQUEUE_EAPOL_START_TIMER); + } + + pEntry->PMKID_CacheIdx = CacheIdx; + DBGPRINT(RT_DEBUG_ERROR, ("ASSOC - 2.PMKID matched and start key cache algorithm\n")); + } + else + { + pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND; + DBGPRINT(RT_DEBUG_ERROR, ("ASSOC - 2.PMKID not found \n")); + } + } + else if ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2) || + ((wdev->IEEE8021X) +#ifdef WSC_AP_SUPPORT + && (!pEntry->bWscCapable) +#endif /* WSC_AP_SUPPORT */ + ) + ) + { + /* Enqueue a EAPOL-start message to trigger EAP SM */ + if (pEntry->EnqueueEapolStartTimerRunning == EAPOL_START_DISABLE +#ifdef HOSTAPD_SUPPORT + && wdev->Hostapd == Hostapd_Diable +#endif/*HOSTAPD_SUPPORT*/ + ) + { + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_1X; + RTMPSetTimer(&pEntry->EnqueueStartForPSKTimer, ENQUEUE_EAPOL_START_TIMER); + } + } +#endif /* DOT1X_SUPPORT */ +#ifdef WAPI_SUPPORT + else if (pEntry->AuthMode == Ndis802_11AuthModeWAICERT) + { + WAPI_InternalCmdAction(pAd, + pEntry->AuthMode, + pEntry->func_tb_idx, + pEntry->Addr, + WAI_MLME_CERT_AUTH_START); + + RTMPInitWapiRekeyTimerAction(pAd, pEntry); + } + else if (pEntry->AuthMode == Ndis802_11AuthModeWAIPSK) + { + WAPI_InternalCmdAction(pAd, + pEntry->AuthMode, + pEntry->func_tb_idx, + pEntry->Addr, + WAI_MLME_KEY_HS_START); + RTMPInitWapiRekeyTimerAction(pAd, pEntry); + } +#endif /* WAPI_SUPPORT */ + else + { + if (pEntry->WepStatus == Ndis802_11WEPEnabled) + { + /* Set WEP key to ASIC */ + UCHAR KeyIdx = 0; + UCHAR CipherAlg = 0; + + KeyIdx = wdev->DefaultKeyId; + CipherAlg = pAd->SharedKey[pEntry->func_tb_idx][KeyIdx].CipherAlg; + + /* + If WEP is used, set pair-wise cipherAlg into WCID + attribute table for this entry. + */ + RTMP_SET_WCID_SEC_INFO(pAd, + pEntry->func_tb_idx, + KeyIdx, + CipherAlg, + pEntry->wcid, + SHAREDKEYTABLE); +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + CmdProcAddRemoveKey(pAd, 0, pEntry->func_tb_idx, KeyIdx, pEntry->wcid, PAIRWISEKEYTABLE, &pAd->SharedKey[pEntry->func_tb_idx][KeyIdx], pEntry->Addr); +#endif + } + } + + +#if defined(MWDS) || defined(MAP_SUPPORT) || defined(WAPP_SUPPORT) + if(tr_entry && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) + { +#ifdef MWDS + MWDSAPPeerEnable(pAd, pEntry); +#endif +#if defined(MAP_SUPPORT) && defined(A4_CONN) + map_a4_peer_enable(pAd, pEntry, TRUE); +#endif /* MAP_SUPPORT */ +#ifdef WAPP_SUPPORT + wapp_send_cli_join_event(pAd, pEntry); +#endif + } +#endif /* MWDS */ + + +#ifdef WH_EZ_SETUP +#ifdef IAPP_SUPPORT + if( IS_EZ_SETUP_ENABLED(wdev) /*|| ez_is_triband()*/){ + /* send association ok message to IAPPD */ + EZ_DEBUG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("####### Send L2 Frame Mac=%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pEntry->Addr))); + IAPP_L2_Update_Frame_Send(pAd, pEntry->Addr, pEntry->wdev->wdev_idx); + } +#endif +#endif + + } + +LabelOK: +#ifdef BAND_STEERING + if ((pAd->ApCfg.BandSteering) +#ifdef WH_EZ_SETUP + && !((pEntry != NULL) && (pEntry->easy_setup_enabled == TRUE) && IS_EZ_SETUP_ENABLED(wdev)) +#endif + + ) { + BndStrg_UpdateEntry(pAd, pEntry, ie_list, TRUE); + } +#endif + +#ifdef WH_EZ_SETUP +#ifdef NEW_CONNECTION_ALGO + if ((wdev != NULL) && (StatusCode != MLME_SUCCESS) && IS_EZ_SETUP_ENABLED(wdev) + && (ez_is_connection_allowed(wdev) == TRUE)){ + + ez_update_connection(pAd, wdev); + } + +#endif +#endif +assoc_check: +#ifdef WAPP_SUPPORT + if (StatusCode != MLME_SUCCESS && wapp_assoc_fail != NOT_FAILURE) + wapp_send_sta_connect_rejected(pAd, wdev, ie_list->Addr2, + ie_list->Addr1, wapp_cnnct_stage, wapp_assoc_fail); +#endif/* WAPP_SUPPORT */ + if (ie_list != NULL) + os_free_mem(NULL, ie_list); + + return; +} + + + +/* + ========================================================================== + Description: + peer assoc req handling procedure + Parameters: + Adapter - Adapter pointer + Elem - MLME Queue Element + Pre: + the station has been authenticated and the following information is stored + Post : + -# An association response frame is generated and sent to the air + ========================================================================== + */ +VOID APPeerAssocReqAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + ap_cmm_peer_assoc_req_action(pAd, Elem, 0); +} + +/* + ========================================================================== + Description: + mlme reassoc req handling procedure + Parameters: + Elem - + Pre: + -# SSID (Adapter->ApCfg.ssid[]) + -# BSSID (AP address, Adapter->ApCfg.bssid) + -# Supported rates (Adapter->ApCfg.supported_rates[]) + -# Supported rates length (Adapter->ApCfg.supported_rates_len) + -# Tx power (Adapter->ApCfg.tx_power) + ========================================================================== + */ +VOID APPeerReassocReqAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + ap_cmm_peer_assoc_req_action(pAd, Elem, 1); +} + + +/* + ========================================================================== + Description: + 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: + left part of IEEE 802.11/1999 p.374 + Parameters: + Elem - MLME message containing the received frame + ========================================================================== + */ +VOID APPeerDisassocReqAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Reason; + UINT16 SeqNum; + MAC_TABLE_ENTRY *pEntry; + struct wifi_dev *wdev; + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - 1 receive DIS-ASSOC request \n")); + if (! PeerDisassocReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &SeqNum, &Reason)) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - receive DIS-ASSOC(seq-%d) request from %02x:%02x:%02x:%02x:%02x:%02x, reason=%d\n", + SeqNum, PRINT_MAC(Addr2), Reason)); + + pEntry = MacTableLookup(pAd, Addr2); + if (pEntry == NULL) + return; + + if (pEntry->wcid < MAX_LEN_OF_MAC_TABLE) + { + +#ifdef DOT1X_SUPPORT + wdev = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev; + /* Notify 802.1x daemon to clear this sta info */ + if (pEntry->AuthMode == Ndis802_11AuthModeWPA || + pEntry->AuthMode == Ndis802_11AuthModeWPA2 || + wdev->IEEE8021X) + DOT1X_InternalCmdAction(pAd, pEntry, DOT1X_DISCONNECT_ENTRY); +#endif /* DOT1X_SUPPORT */ + +#ifdef WAPI_SUPPORT + WAPI_InternalCmdAction(pAd, + pEntry->AuthMode, + pEntry->func_tb_idx, + pEntry->Addr, + WAI_MLME_DISCONNECT); +#endif /* WAPI_SUPPORT */ + + /* send wireless event - for disassociation */ + RTMPSendWirelessEvent(pAd, IW_DISASSOC_EVENT_FLAG, Addr2, 0, 0); + +#ifdef ALL_NET_EVENT + wext_send_event(pEntry->wdev->if_dev, + pEntry->Addr, + pEntry->bssid, + pAd->CommonCfg.Channel, + RTMPAvgRssi(pAd, &pEntry->RssiSample), + FBT_LINK_OFFLINE_NOTIFY); +#endif /* ALL_NET_EVENT */ + + ApLogEvent(pAd, Addr2, EVENT_DISASSOCIATED); + +#ifdef WIFI_DIAG + if (pEntry && IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_DEAUTH, REASON_DEAUTH_STA_LEAVING); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + REASON_DEAUTH_STA_LEAVING); +#endif + + MacTableDeleteEntry(pAd, pEntry->wcid, Addr2); + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn == TRUE) + { + UCHAR apCliIdx, CliIdx, isLinkValid; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, TRUE, Addr2, TRUE, &isLinkValid); + if (pReptEntry && (pReptEntry->CliConnectState != 0)) + { + apCliIdx = pReptEntry->MatchApCliIdx; + CliIdx = pReptEntry->MatchLinkIdx; + 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 */ + + +#ifdef WH_EVENT_NOTIFIER + { + EventHdlr pEventHdlrHook = NULL; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_STA_LEAVE); + if(pEventHdlrHook && wdev) + pEventHdlrHook(pAd, wdev, Addr2, Elem->Channel); + } +#endif /* WH_EVENT_NOTIFIER */ + + + } +} + + +/* + ========================================================================== + Description: + delete it from STA and disassoc s STA + Parameters: + Elem - + ========================================================================== + */ +VOID MbssKickOutStas(RTMP_ADAPTER *pAd, INT apidx, USHORT Reason) +{ + INT i; + PMAC_TABLE_ENTRY pEntry; +#ifdef MBO_SUPPORT + MboIndicateStaDisassocToDaemon(pAd, NULL, MBO_MSG_AP_TERMINATION); +#endif/* MBO_SUPPORT */ + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + pEntry = &pAd->MacTab.Content[i]; + if (pEntry && IS_ENTRY_CLIENT(pEntry) && pEntry->func_tb_idx == apidx) + APMlmeKickOutSta(pAd, pEntry->Addr, pEntry->wcid, Reason); + } + /* mbo wait for max 500ms and check all IsKeep is zero */ +#ifdef MBO_SUPPORT + MboWaitAllStaGone(pAd, apidx); +#endif/* MBO_SUPPORT */ + return; +} + + +/* + ========================================================================== + Description: + delete it from STA and disassoc s STA + Parameters: + Elem - + ========================================================================== + */ +VOID APMlmeKickOutSta(RTMP_ADAPTER *pAd, UCHAR *pStaAddr, UCHAR Wcid, USHORT Reason) +{ + HEADER_802_11 DisassocHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + MAC_TABLE_ENTRY *pEntry; + UCHAR Aid; + UCHAR ApIdx; + + pEntry = MacTableLookup(pAd, pStaAddr); + + if (pEntry == NULL) + { + return; + } + Aid = pEntry->Aid; + ApIdx = pEntry->func_tb_idx; + + 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); + +#ifdef ALL_NET_EVENT + wext_send_event(pEntry->wdev->if_dev, + pEntry->Addr, + pEntry->bssid, + pAd->CommonCfg.Channel, + RTMPAvgRssi(pAd, &pEntry->RssiSample), + FBT_LINK_OFFLINE_NOTIFY); +#endif /* ALL_NET_EVENT */ + + ApLogEvent(pAd, pStaAddr, EVENT_DISASSOCIATED); + + /* 2. send out a DISASSOC request frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - MLME disassociates %02x:%02x:%02x:%02x:%02x:%02x; Send DISASSOC request\n", + PRINT_MAC(pStaAddr))); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pStaAddr, + pAd->ApCfg.MBSSID[ApIdx].wdev.if_addr, + pAd->ApCfg.MBSSID[ApIdx].wdev.bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DisassocHdr, + 2, &Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +#ifdef WIFI_DIAG + if (IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_DEAUTH, Reason); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + Reason); +#endif + MacTableDeleteEntry(pAd, Aid, pStaAddr); + } +} + + +#ifdef DOT11W_PMF_SUPPORT +VOID APMlmeKickOutAllSta(RTMP_ADAPTER *pAd, UCHAR apidx, USHORT Reason) +{ + HEADER_802_11 DisassocHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + PPMF_CFG pPmfCfg = NULL; + + pPmfCfg = &pAd->ApCfg.MBSSID[apidx].PmfCfg; + if ((apidx < pAd->ApCfg.BssidNum) && (pPmfCfg)) + { + /* Send out a Deauthentication request frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + DBGPRINT(RT_DEBUG_ERROR, ("Send DISASSOC Broadcast frame(%d) with ra%d \n", Reason, apidx)); + + /* 802.11 Header */ + NdisZeroMemory(&DisassocHdr, sizeof(HEADER_802_11)); + DisassocHdr.FC.Type = FC_TYPE_MGMT; + DisassocHdr.FC.SubType = SUBTYPE_DISASSOC; + DisassocHdr.FC.ToDs = 0; + DisassocHdr.FC.Wep = 0; + COPY_MAC_ADDR(DisassocHdr.Addr1, BROADCAST_ADDR); + COPY_MAC_ADDR(DisassocHdr.Addr2, pAd->ApCfg.MBSSID[apidx].wdev.bssid); + COPY_MAC_ADDR(DisassocHdr.Addr3, pAd->ApCfg.MBSSID[apidx].wdev.bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DisassocHdr, + 2, &Reason, + END_OF_ARGS); + + if (pPmfCfg->MFPC == TRUE) + { + ULONG TmpLen; + UCHAR res_buf[LEN_PMF_MMIE]; + USHORT EID, ELen; + + EID = IE_PMF_MMIE; + ELen = LEN_PMF_MMIE; + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &EID, + 1, &ELen, + LEN_PMF_MMIE, res_buf, + END_OF_ARGS); + FrameLen += TmpLen; + DBGPRINT(RT_DEBUG_WARN, ("[PMF]: This is a Broadcast Robust management frame, Add 0x4C(76) EID\n")); + } + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } +} +#endif /* DOT11W_PMF_PLUGFEST */ + + +/* + ========================================================================== + Description: + Upper layer orders to disassoc s STA + Parameters: + Elem - + ========================================================================== + */ +VOID APMlmeDisassocReqAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + MLME_DISASSOC_REQ_STRUCT *DisassocReq = (MLME_DISASSOC_REQ_STRUCT *)(Elem->Msg); + +#ifdef WH_EZ_SETUP + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) + EZ_DEBUG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("APMlmeDisassocReqAction()\n")); +#endif + + APMlmeKickOutSta(pAd, DisassocReq->Addr, Elem->Wcid, DisassocReq->Reason); +} + + +/* + ========================================================================== + Description: + right part of IEEE 802.11/1999 page 374 + Note: + This event should never cause ASSOC state machine perform state + transition, and has no relationship with CNTL machine. So we separate + this routine as a service outside of ASSOC state transition table. + ========================================================================== + */ +VOID APCls3errAction(RTMP_ADAPTER *pAd, ULONG Wcid, HEADER_802_11 *pHeader) +{ + HEADER_802_11 DisassocHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + USHORT Reason = REASON_CLS3ERR; + MAC_TABLE_ENTRY *pEntry = NULL; + + if (Wcid < MAX_LEN_OF_MAC_TABLE) + pEntry = &(pAd->MacTab.Content[Wcid]); + + if (pEntry) { +#ifdef WIFI_DIAG + if (IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_DEAUTH, Reason); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + Reason); +#endif + /*ApLogEvent(pAd, pAddr, EVENT_DISASSOCIATED); */ + MacTableDeleteEntry(pAd, pEntry->wcid, pHeader->Addr2); + } + + /* 2. send out a DISASSOC request frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("ASSOC - Class 3 Error, Send DISASSOC frame to %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pHeader->Addr2))); + MgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pHeader->Addr2, + pHeader->Addr1, + pHeader->Addr1); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DisassocHdr, + 2, &Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + + +/* + ========================================================================== + Description: + association state machine init, including state transition and timer init + Parameters: + S - pointer to the association state machine + Note: + The state machine looks like the following + + AP_ASSOC_IDLE + APMT2_MLME_DISASSOC_REQ mlme_disassoc_req_action + APMT2_PEER_DISASSOC_REQ peer_disassoc_action + APMT2_PEER_ASSOC_REQ drop + APMT2_PEER_REASSOC_REQ drop + APMT2_CLS3ERR cls3err_action + ========================================================================== + */ +VOID APAssocStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, AP_MAX_ASSOC_STATE, AP_MAX_ASSOC_MSG, (STATE_MACHINE_FUNC)Drop, AP_ASSOC_IDLE, AP_ASSOC_MACHINE_BASE); + + StateMachineSetAction(S, AP_ASSOC_IDLE, APMT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)APMlmeDisassocReqAction); + StateMachineSetAction(S, AP_ASSOC_IDLE, APMT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)APPeerDisassocReqAction); + StateMachineSetAction(S, AP_ASSOC_IDLE, APMT2_PEER_ASSOC_REQ, (STATE_MACHINE_FUNC)APPeerAssocReqAction); + StateMachineSetAction(S, AP_ASSOC_IDLE, APMT2_PEER_REASSOC_REQ, (STATE_MACHINE_FUNC)APPeerReassocReqAction); +/* StateMachineSetAction(S, AP_ASSOC_IDLE, APMT2_CLS3ERR, APCls3errAction); */ +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_auth.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_auth.c new file mode 100644 index 000000000..91ba20708 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_auth.c @@ -0,0 +1,1374 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + auth.c + + Abstract: + Handle de-auth request from local MLME + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 08-04-2003 created for 11g soft-AP + */ + +#include "rt_config.h" +#ifdef DOT11R_FT_SUPPORT +#include "ft.h" +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef WH_EZ_SETUP +#ifdef DUAL_CHIP +extern NDIS_SPIN_LOCK ez_conn_perm_lock; +#endif +#endif + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ +static 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; +} + +VOID ap_mlme_broadcast_deauth_req_action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem) +{ + MLME_BROADCAST_DEAUTH_REQ_STRUCT *pInfo; + HEADER_802_11 Hdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + MAC_TABLE_ENTRY *pEntry; + UCHAR apidx = 0; + struct wifi_dev *wdev; + int wcid, startWcid; + + startWcid = 1; + pInfo = (PMLME_BROADCAST_DEAUTH_REQ_STRUCT)Elem->Msg; + if (!MAC_ADDR_EQUAL(pInfo->Addr, BROADCAST_ADDR)) + return; + wdev = pInfo->wdev; + apidx = wdev->func_idx; + for (wcid = startWcid; VALID_UCAST_ENTRY_WCID(wcid); wcid++) { + pEntry = &pAd->MacTab.Content[wcid]; + if (pEntry->wdev != wdev) + continue; + RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, + pEntry->Addr, 0, 0); + ApLogEvent(pAd, pInfo->Addr, EVENT_DISASSOCIATED); + MacTableDeleteEntry(pAd, wcid, pEntry->Addr); + } + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + MgtMacHeaderInit(pAd, &Hdr, SUBTYPE_DEAUTH, 0, pInfo->Addr, + pAd->ApCfg.MBSSID[apidx].wdev.if_addr, + pAd->ApCfg.MBSSID[apidx].wdev.bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr, + 2, &pInfo->Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + +void ap_send_broadcast_deauth(void *ad_obj, struct wifi_dev *wdev) +{ + MLME_BROADCAST_DEAUTH_REQ_STRUCT *pInfo = NULL; + MLME_QUEUE_ELEM *Elem; + RTMP_ADAPTER *pAd = ad_obj; + + MlmeAllocateMemory(pAd, (UCHAR **)&Elem); + if (Elem == NULL) + return; + if (Elem) { + pInfo = (MLME_BROADCAST_DEAUTH_REQ_STRUCT *)Elem->Msg; + pInfo->wdev = wdev; + Elem->Wcid = WCID_ALL; + pInfo->Reason = MLME_UNSPECIFY_FAIL; + NdisCopyMemory(pInfo->Addr, BROADCAST_ADDR, MAC_ADDR_LEN); + APMlmeDeauthReqAction(pAd, Elem); + MlmeFreeMemory(pAd, Elem); + } +} + + +/* + ========================================================================== + Description: + Upper Layer request to kick out a STA + ========================================================================== + */ +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; +#if (defined(WH_EZ_SETUP) || defined (WH_EVENT_NOTIFIER)) + struct wifi_dev *wdev; +#endif + + + pInfo = (MLME_DEAUTH_REQ_STRUCT *)Elem->Msg; + +#ifdef WH_EZ_SETUP + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,(" ---> %s, wcid = %d\n", __FUNCTION__,Elem->Wcid)); +#endif + + if (Elem->Wcid < MAX_LEN_OF_MAC_TABLE) + { +#ifdef WH_EZ_SETUP + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("Valid unicast entry\n")); +#endif + + pEntry = &pAd->MacTab.Content[Elem->Wcid]; + if (!pEntry) + return; + +#if (defined(WH_EZ_SETUP) || defined (WH_EVENT_NOTIFIER)) + wdev = pEntry->wdev; +#endif + +#ifdef WAPI_SUPPORT + WAPI_InternalCmdAction(pAd, + pEntry->AuthMode, + pEntry->func_tb_idx, + pEntry->Addr, + WAI_MLME_DISCONNECT); +#endif /* WAPI_SUPPORT */ + + /* send wireless event - for deauthentication */ + RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pInfo->Addr, 0, 0); + +#ifdef ALL_NET_EVENT + wext_send_event(pEntry->wdev->if_dev, + pEntry->Addr, + pEntry->bssid, + pAd->CommonCfg.Channel, + RTMPAvgRssi(pAd, &pEntry->RssiSample), + FBT_LINK_OFFLINE_NOTIFY); +#endif /* ALL_NET_EVENT */ + + ApLogEvent(pAd, pInfo->Addr, EVENT_DISASSOCIATED); + + apidx = pEntry->func_tb_idx; +#ifdef WIFI_DIAG + if (IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_DEAUTH, pInfo->Reason); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + pInfo->Reason); +#endif + /* 1. remove this STA from MAC table */ + MacTableDeleteEntry(pAd, Elem->Wcid, pInfo->Addr); + + /* 2. send out DE-AUTH request frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - Send DE-AUTH req to %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pInfo->Addr))); + + MgtMacHeaderInit(pAd, &Hdr, SUBTYPE_DEAUTH, 0, pInfo->Addr, + pAd->ApCfg.MBSSID[apidx].wdev.if_addr, + pAd->ApCfg.MBSSID[apidx].wdev.bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr, + 2, &pInfo->Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + +#ifdef WH_EVENT_NOTIFIER + { + EventHdlr pEventHdlrHook = NULL; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_STA_LEAVE); + if(pEventHdlrHook && wdev) + pEventHdlrHook(pAd, wdev, pInfo->Addr, Elem->Channel); + } +#endif /* WH_EVENT_NOTIFIER */ + } else { + ap_mlme_broadcast_deauth_req_action(pAd, Elem); + } +} + + +static VOID APPeerDeauthReqAction( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + UINT16 Reason, SeqNum; + MAC_TABLE_ENTRY *pEntry; +#if (defined(WH_EZ_SETUP) || defined(WH_EVENT_NOTIFIER)) + struct wifi_dev *wdev; +#endif + +#ifdef WH_EZ_SETUP + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) + EZ_DEBUG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_OFF,("AUTH_RSP - APPeerDeauthReqAction\n")); +#endif + + + 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]; +#if (defined(WH_EZ_SETUP) || defined(WH_EVENT_NOTIFIER)) + wdev = pEntry->wdev; +#endif + + { + /* + Add Hotspot2.0 Rlease 1 Prestested Code + */ + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx]; + PFRAME_802_11 Fr = (PFRAME_802_11)Elem->Msg; +#ifdef DBG + unsigned char *tmp = (unsigned char *)pMbss->wdev.bssid; + unsigned char *tmp2 = (unsigned char *)&Fr->Hdr.Addr1; +#endif /* DBG */ + if (memcmp(&Fr->Hdr.Addr1, pMbss->wdev.bssid, 6) != 0) + { + DBGPRINT(RT_DEBUG_INFO, + ("da not match bssid,bssid:0x%02x%02x%02x%02x%02x%02x, addr1:0x%02x%02x%02x%02x%02x%02x\n", + *tmp, *(tmp+1), *(tmp+2), *(tmp+3), *(tmp+4), *(tmp+5), *tmp2, *(tmp2+1), *(tmp2+2), *(tmp2+3), *(tmp2+4), *(tmp2+5))); + return; + } + else + DBGPRINT(RT_DEBUG_INFO,("da match,0x%02x%02x%02x%02x%02x%02x\n", + *tmp, *(tmp+1), *(tmp+2), *(tmp+3), *(tmp+4), *(tmp+5))); + } +#ifdef DOT1X_SUPPORT + /* Notify 802.1x daemon to clear this sta info */ + if (pEntry->AuthMode == Ndis802_11AuthModeWPA || + pEntry->AuthMode == Ndis802_11AuthModeWPA2 || + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.IEEE8021X) + DOT1X_InternalCmdAction(pAd, pEntry, DOT1X_DISCONNECT_ENTRY); +#endif /* DOT1X_SUPPORT */ + +#ifdef WAPI_SUPPORT + WAPI_InternalCmdAction(pAd, + pEntry->AuthMode, + pEntry->func_tb_idx, + pEntry->Addr, + WAI_MLME_DISCONNECT); +#endif /* WAPI_SUPPORT */ + + /* send wireless event - for deauthentication */ + RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, Addr2, 0, 0); + +#ifdef ALL_NET_EVENT + wext_send_event(pEntry->wdev->if_dev, + pEntry->Addr, + pEntry->bssid, + pAd->CommonCfg.Channel, + RTMPAvgRssi(pAd, &pEntry->RssiSample), + FBT_LINK_OFFLINE_NOTIFY); +#endif /* ALL_NET_EVENT */ + + ApLogEvent(pAd, Addr2, EVENT_DISASSOCIATED); + + if (pEntry->CMTimerRunning == TRUE) + { + /* + If one who initilized Counter Measure deauth itself, + AP doesn't log the MICFailTime + */ + pAd->ApCfg.aMICFailTime = pAd->ApCfg.PrevaMICFailTime; + } + +#ifdef WIFI_DIAG + if (pEntry && IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_DEAUTH, REASON_DEAUTH_STA_LEAVING); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + REASON_DEAUTH_STA_LEAVING); +#endif + 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, PRINT_MAC(Addr2), Reason)); + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn == TRUE) + { + UCHAR apCliIdx, CliIdx, isLinkValid; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, TRUE, Addr2, TRUE, &isLinkValid); + if (pReptEntry && (pReptEntry->CliConnectState != 0)) + { + apCliIdx = pReptEntry->MatchApCliIdx; + CliIdx = pReptEntry->MatchLinkIdx; + 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 */ + + +#ifdef WH_EVENT_NOTIFIER + { + EventHdlr pEventHdlrHook = NULL; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_STA_LEAVE); + if(pEventHdlrHook && wdev) + pEventHdlrHook(pAd, wdev, Addr2, Elem->Channel); + } +#endif /* WH_EVENT_NOTIFIER */ + + } +} + + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ +static BOOLEAN APPeerAuthSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN AUTH_FRAME_INFO *auth_info) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)Msg; + + COPY_MAC_ADDR(auth_info->addr1, &Fr->Hdr.Addr1); /* BSSID */ + COPY_MAC_ADDR(auth_info->addr2, &Fr->Hdr.Addr2); /* SA */ + // TODO: shiang-usw, how about the endian issue here?? + NdisMoveMemory(&auth_info->auth_alg, &Fr->Octet[0], 2); + NdisMoveMemory(&auth_info->auth_seq, &Fr->Octet[2], 2); + NdisMoveMemory(&auth_info->auth_status, &Fr->Octet[4], 2); + +#ifdef WH_EZ_SETUP + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) + auth_info->auth_alg = le2cpu16(auth_info->auth_alg); +#endif + + if (auth_info->auth_alg == AUTH_MODE_OPEN) + { + if (auth_info->auth_seq == 1 || auth_info->auth_seq == 2) + return TRUE; + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): fail - wrong Seg# (=%d)\n", + __FUNCTION__, auth_info->auth_seq)); + return FALSE; + } + } + else if (auth_info->auth_alg == AUTH_MODE_KEY) + { + if (auth_info->auth_seq == 1 || auth_info->auth_seq == 4) + return TRUE; + else if (auth_info->auth_seq == 2 || auth_info->auth_seq == 3) + { + NdisMoveMemory(auth_info->Chtxt, &Fr->Octet[8], CIPHER_TEXT_LEN); + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): fail - wrong Seg# (=%d)\n", + __FUNCTION__, auth_info->auth_seq)); + return FALSE; + } + } +#ifdef DOT11R_FT_SUPPORT + else if (auth_info->auth_alg == AUTH_MODE_FT) + { + PEID_STRUCT eid_ptr; + UCHAR *Ptr; + UCHAR WPA2_OUI[3]={0x00,0x0F,0xAC}; + PFT_INFO pFtInfo = &auth_info->FtInfo; + + NdisZeroMemory(pFtInfo, sizeof(FT_INFO)); + + Ptr = &Fr->Octet[6]; + eid_ptr = (PEID_STRUCT) Ptr; + + /* get variable fields from payload and advance the pointer */ + while(((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((UCHAR*)Fr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_FT_MDIE: + FT_FillMdIeInfo(eid_ptr, &pFtInfo->MdIeInfo); + break; + + case IE_FT_FTIE: + FT_FillFtIeInfo(eid_ptr, &pFtInfo->FtIeInfo); + break; + + case IE_FT_RIC_DATA: + /* record the pointer of first RDIE. */ + if (pFtInfo->RicInfo.pRicInfo == NULL) + { + pFtInfo->RicInfo.pRicInfo = &eid_ptr->Eid; + pFtInfo->RicInfo.Len = ((UCHAR*)Fr + MsgLen) + - (UCHAR*)eid_ptr + 1; + } + + if ((pFtInfo->RicInfo.RicIEsLen + eid_ptr->Len + 2) < MAX_RICIES_LEN) + { + NdisMoveMemory(&pFtInfo->RicInfo.RicIEs[pFtInfo->RicInfo.RicIEsLen], + &eid_ptr->Eid, eid_ptr->Len + 2); + pFtInfo->RicInfo.RicIEsLen += eid_ptr->Len + 2; + } + break; + + + case IE_FT_RIC_DESCRIPTOR: + if ((pFtInfo->RicInfo.RicIEsLen + eid_ptr->Len + 2) < MAX_RICIES_LEN) + { + NdisMoveMemory(&pFtInfo->RicInfo.RicIEs[pFtInfo->RicInfo.RicIEsLen], + &eid_ptr->Eid, eid_ptr->Len + 2); + pFtInfo->RicInfo.RicIEsLen += eid_ptr->Len + 2; + } + break; + + case IE_RSN: + if (NdisEqualMemory(&eid_ptr->Octet[2], WPA2_OUI, sizeof(WPA2_OUI))) + { + NdisMoveMemory(pFtInfo->RSN_IE, eid_ptr, eid_ptr->Len + 2); + pFtInfo->RSNIE_Len = eid_ptr->Len + 2; + } + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + } +#endif /* DOT11R_FT_SUPPORT */ +#ifdef WH_EZ_SETUP + else if(IS_ADPTR_EZ_SETUP_ENABLED(pAd) && (auth_info->auth_alg == AUTH_MODE_EZ)){ + EZ_DEBUG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s(): receive easy setup auth request (alg=0x%02x)\n", + __FUNCTION__, auth_info->auth_alg)); + return TRUE; + } +#endif /* WH_EZ_SETUP */ +#ifdef DOT11_SAE_SUPPORT + else if (auth_info->auth_alg == AUTH_MODE_SAE) { + if (auth_info->auth_seq != SAE_COMMIT_SEQ && auth_info->auth_seq != SAE_CONFIRM_SEQ) + return FALSE; + } +#endif /* DOT11_SAE_SUPPORT */ + + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): fail - wrong algorithm (=%d)\n", + __FUNCTION__, auth_info->auth_alg)); + return FALSE; + } + + return TRUE; +} + + +/* + ========================================================================== + 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, + pHdr->Addr1, + 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); +} + + +static VOID APPeerAuthReqAtIdleAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + INT i; + USHORT RspReason; + AUTH_FRAME_INFO auth_info; + UINT32 apidx; + PHEADER_802_11 pRcvHdr; + HEADER_802_11 AuthHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + MAC_TABLE_ENTRY *pEntry; +#ifdef DOT11W_PMF_SUPPORT + STA_TR_ENTRY *tr_entry; +#endif /* DOT11W_PMF_SUPPORT */ + UCHAR ChTxtIe = 16, ChTxtLen = CIPHER_TEXT_LEN; +#ifdef DOT11R_FT_SUPPORT + PFT_CFG pFtCfg; + PFT_INFO pFtInfoBuf; +#endif /* DOT11R_FT_SUPPORT */ + BSS_STRUCT *pMbss; + struct wifi_dev *wdev = NULL; + UINT32 u4MaxMBSSIDSize = sizeof(pAd->ApCfg.MBSSID)/sizeof(pAd->ApCfg.MBSSID[0]); +#ifdef WAPP_SUPPORT + UINT8 wapp_cnnct_stage = WAPP_AUTH; + UINT16 wapp_auth_fail = NOT_FAILURE; +#endif/* WAPP_SUPPORT */ + +#ifdef WH_EZ_SETUP + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) + EZ_DEBUG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("AUTH - APPeerAuthReqAtIdleAction\n")); +#endif + + + if (pAd->ApCfg.BANClass3Data == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Disallow new Association\n")); + /*return;*/ +#ifdef WAPP_SUPPORT + wapp_auth_fail = DISALLOW_NEW_ASSOCI; +#endif/* WAPP_SUPPORT */ + goto auth_failure; + } + + if (!APPeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, &auth_info)) { + /*return;*/ +#ifdef WAPP_SUPPORT + wapp_auth_fail = PEER_REQ_SANITY_FAIL; +#endif /* WAPP_SUPPORT */ + goto auth_failure; + } + + /* Find which MBSSID to be authenticate */ + apidx = get_apidx_by_addr(pAd, auth_info.addr1); + if ((apidx >= pAd->ApCfg.BssidNum) || (apidx >= u4MaxMBSSIDSize)) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Bssid not found\n")); + /*return;*/ +#ifdef WAPP_SUPPORT + wapp_auth_fail = BSSID_NOT_FOUND; +#endif/* WAPP_SUPPORT */ + goto auth_failure; + } + + pMbss = &pAd->ApCfg.MBSSID[apidx]; + wdev = &pMbss->wdev; + ASSERT((wdev->func_idx == apidx)); + + if ((wdev->if_dev == NULL) || ((wdev->if_dev != NULL) && + !(RTMP_OS_NETDEV_STATE_RUNNING(wdev->if_dev)))) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Bssid IF didn't up yet.\n")); + /*return;*/ +#ifdef WAPP_SUPPORT + wapp_auth_fail = BSSID_IF_NOT_READY; +#endif /* WAPP_SUPPORT */ + goto auth_failure; + } + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev) && (ez_is_connection_allowed(wdev) == FALSE)) { + /*return;*/ +#ifdef WAPP_SUPPORT + wapp_auth_fail = EZ_CONNECT_DISALLOW; +#endif /* WAPP_SUPPORT */ + goto auth_failure; + } + if ((auth_info.auth_alg == AUTH_MODE_EZ) + && (!IS_EZ_SETUP_ENABLED(wdev))) { + // ez_update_connection_permission(pAd,NULL,EZ_ALLOW_ALL); + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("AUTH - Easy setup function is disabled. Reject easy setup auth request.\n")); + /*return;*/ +#ifdef WAPP_SUPPORT + wapp_auth_fail = EZ_SETUP_FUNC_DISABLED; +#endif/* WAPP_SUPPORT */ + goto auth_failure; + } +#endif /* WH_EZ_SETUP */ + + pEntry = MacTableLookup(pAd, auth_info.addr2); + if (pEntry && IS_ENTRY_CLIENT(pEntry)) + { + /* reset NoDataIdleCount to prevent unexpected STA assoc timeout and kicked by MacTableMaintenance */ + pEntry->NoDataIdleCount = 0; +#ifdef DOT11W_PMF_SUPPORT + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + + if ((CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE)) + && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) + goto SendAuth; +#endif /* DOT11W_PMF_SUPPORT */ + + if (!RTMPEqualMemory(auth_info.addr1, pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid, MAC_ADDR_LEN)) + { + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + pEntry = NULL; + DBGPRINT(RT_DEBUG_WARN, ("AUTH - Bssid does not match\n")); +#ifdef WAPP_SUPPORT + wapp_auth_fail = BSSID_MISMATCH; +#endif/* WAPP_SUPPORT */ + goto auth_failure; + + } + else + { + if (pEntry->bIAmBadAtheros == TRUE) + { + AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, FALSE, FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("Atheros Problem. Turn on RTS/CTS!!!\n")); + pEntry->bIAmBadAtheros = FALSE; + } + +#ifdef DOT11_N_SUPPORT + BASessionTearDownALL(pAd, pEntry->wcid); +#endif /* DOT11_N_SUPPORT */ + ASSERT(pEntry->Aid == Elem->Wcid); + } + } + +#ifdef DOT11W_PMF_SUPPORT +SendAuth: +#endif /* DOT11W_PMF_SUPPORT */ + + pRcvHdr = (PHEADER_802_11)(Elem->Msg); + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - MBSS(%d), Rcv AUTH seq#%d, Alg=%d, Status=%d from " + "[wcid=%d]%02x:%02x:%02x:%02x:%02x:%02x\n", + apidx, auth_info.auth_seq, auth_info.auth_alg, + auth_info.auth_status, Elem->Wcid, + PRINT_MAC(auth_info.addr2))); + if(pEntry) { + INT32 prev = -1; + prev = (INT32)pEntry->AuthAssocNotInProgressFlag; + pEntry->AuthAssocNotInProgressFlag = 0; + DBGPRINT(RT_DEBUG_TRACE,("===[%s] prev_val = %d AuthAssocNotInProgressFlag = %u \n", + __FUNCTION__, prev, pEntry->AuthAssocNotInProgressFlag)); + } + +#ifdef WH_EZ_SETUP + if ((auth_info.auth_alg == AUTH_MODE_EZ) + && IS_EZ_SETUP_ENABLED(wdev)) { + /* + Do not check ACL when easy setup is enabled + and ACL policy is positive. + */ + EZ_DEBUG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s: This is an easy setup device.\n", __FUNCTION__)); + } + else +#endif /* WH_EZ_SETUP */ +#ifdef WSC_V2_SUPPORT + /* Do not check ACL when WPS V2 is enabled and ACL policy is positive. */ + if ((pMbss->WscControl.WscConfMode != WSC_DISABLE) && + (pMbss->WscControl.WscV2Info.bEnableWpsV2) && + (pMbss->WscControl.WscV2Info.bWpsEnable) && + (pMbss->AccessControlList.Policy == 1)) + ; + else +#endif /* WSC_V2_SUPPORT */ + /* fail in ACL checking => send an AUTH-Fail seq#2. */ + if (! ApCheckAccessControlList(pAd, auth_info.addr2, apidx)) + { + ASSERT(auth_info.auth_seq == 1); + ASSERT(pEntry == NULL); + APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, auth_info.auth_alg, auth_info.auth_seq + 1, MLME_UNSPECIFY_FAIL); + +#ifdef WIFI_DIAG + DiagConnError(pAd, apidx, auth_info.addr2, DIAG_CONN_ACL_BLK, 0); +#endif +#ifdef CONN_FAIL_EVENT + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[apidx].Ssid, + pAd->ApCfg.MBSSID[apidx].SsidLen, + auth_info.addr2, + REASON_DECLINED); +#endif + /* If this STA exists, delete it. */ + if (pEntry) + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + + RTMPSendWirelessEvent(pAd, IW_MAC_FILTER_LIST_EVENT_FLAG, auth_info.addr2, wdev->wdev_idx, 0); + + DBGPRINT(RT_DEBUG_TRACE, + ("Failed in ACL checking => send an AUTH seq#2 with " + "Status code = %d\n", MLME_UNSPECIFY_FAIL)); + +#ifdef WH_EVENT_NOTIFIER + { + EventHdlr pEventHdlrHook = NULL; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_STA_AUTH_REJECT); + if(pEventHdlrHook && wdev) + pEventHdlrHook(pAd, wdev, auth_info.addr2, Elem); + } +#endif /* WH_EVENT_NOTIFIER */ + + /*return;*/ +#ifdef WAPP_SUPPORT + wapp_auth_fail = ACL_CHECK_FAIL; +#endif /* WAPP_SUPPORT */ + goto auth_failure; + } +#ifdef BAND_STEERING + if ((pAd->ApCfg.BandSteering) +#ifdef WH_EZ_SETUP + && !((wdev != NULL) && (IS_EZ_SETUP_ENABLED(wdev)) && (auth_info.auth_alg == AUTH_MODE_EZ)) +#endif + ) { + BOOLEAN bBndStrgCheck = TRUE; + bBndStrgCheck = BndStrg_CheckConnectionReq(pAd, wdev, auth_info.addr2, Elem, NULL); + if (bBndStrgCheck == FALSE) { + APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, auth_info.auth_alg, auth_info.auth_seq + 1, MLME_UNSPECIFY_FAIL); + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - BndStrg check failed.\n")); + /*return;*/ +#ifdef WAPP_SUPPORT + wapp_auth_fail = BND_STRG_CONNECT_CHECK_FAIL; +#endif /* WAPP_SUPPORT */ +#ifdef WIFI_DIAG + DiagConnError(pAd, apidx, auth_info.addr2, DIAG_CONN_BAND_STE, 0); +#endif +#ifdef CONN_FAIL_EVENT + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[apidx].Ssid, + pAd->ApCfg.MBSSID[apidx].SsidLen, + auth_info.addr2, + REASON_UNSPECIFY); +#endif + goto auth_failure; + } + } +#endif /* BAND_STEERING */ +#ifdef DOT11R_FT_SUPPORT + pFtCfg = &pMbss->FtCfg; + if ((pFtCfg->FtCapFlag.Dot11rFtEnable) + && (auth_info.auth_alg == AUTH_MODE_FT)) + { + USHORT result; + + if (!pEntry) + pEntry = MacTableInsertEntry(pAd, auth_info.addr2, wdev, ENTRY_CLIENT, OPMODE_AP, TRUE); + + if (pEntry != NULL) + { + os_alloc_mem(pAd, (UCHAR **)&pFtInfoBuf, sizeof(FT_INFO)); + + if (pFtInfoBuf) + { + result = FT_AuthReqHandler(pAd, pEntry, &auth_info.FtInfo, pFtInfoBuf); + if (result == MLME_SUCCESS) + { + NdisMoveMemory(&pEntry->MdIeInfo, &auth_info.FtInfo.MdIeInfo, sizeof(FT_MDIE_INFO)); + + pEntry->AuthState = AS_AUTH_OPEN; + pEntry->Sst = SST_AUTH; + } else if (result == MLME_FAIL_NO_RESOURCE) { + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s - give up this AUTH pkt => Query R1KH from backbone(Wcid%d, %d)\n", + __func__, pEntry->wcid, pEntry->FT_R1kh_CacheMiss_Times)); + os_free_mem(NULL, pFtInfoBuf); + /*return;*/ +#ifdef WAPP_SUPPORT + wapp_auth_fail = MLME_NO_RESOURCE; +#endif /* WAPP_SUPPORT */ + goto auth_failure; + } + + FT_EnqueueAuthReply(pAd, pRcvHdr, auth_info.auth_alg, 2, result, + &pFtInfoBuf->MdIeInfo, &pFtInfoBuf->FtIeInfo, NULL, + pFtInfoBuf->RSN_IE, pFtInfoBuf->RSNIE_Len); + NdisZeroMemory(pEntry->LastTK, LEN_TK); + os_free_mem(NULL, pFtInfoBuf); + } + } + return; + } + else +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11_SAE_SUPPORT + if ((auth_info.auth_alg == AUTH_MODE_SAE) && + (pMbss->wdev.AuthMode == Ndis802_11AuthModeWPA3PSK || + pMbss->wdev.AuthMode == Ndis802_11AuthModeWPA2PSKWPA3PSK)) { + UCHAR *pmk; +#ifdef DOT11W_PMF_SUPPORT + + if (pEntry) { + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + + if ((CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE) == TRUE) + && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) { + APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, + auth_info.auth_alg, + auth_info.auth_seq, + MLME_ASSOC_REJ_TEMPORARILY); + PMF_MlmeSAQueryReq(pAd, pEntry); + return; + } + } + +#endif /* DOT11W_PMF_SUPPORT */ + + sae_handle_auth(pAd, &pAd->SaeCfg, Elem->Msg, Elem->MsgLen, + pMbss->PSK, + auth_info.auth_seq, auth_info.auth_status, &pmk); + + if (pmk) { + + if (!pEntry) + pEntry = MacTableInsertEntry(pAd, auth_info.addr2, wdev, ENTRY_CLIENT, OPMODE_AP, TRUE); + + if (pEntry) { + UCHAR pmkid[80]; + + NdisMoveMemory(pEntry->PMK, pmk, LEN_PMK); + pEntry->AuthState = AS_AUTH_OPEN; + pEntry->Sst = SST_AUTH; /* what if it already in SST_ASSOC ??????? */ + if (sae_get_pmk_cache(&pAd->SaeCfg, auth_info.addr1, auth_info.addr2, pmkid, NULL)) { + + RTMPAddPMKIDCache(pAd, + apidx, + pEntry->Addr, + pmkid, + pmk +#ifdef CONFIG_OWE_SUPPORT + , LEN_PMK +#endif + ); + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("WPA3PSK(SAE):(%02x:%02x:%02x:%02x:%02x:%02x)" + "Calc PMKID=%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pEntry->Addr), pmkid[0], pmkid[1], + pmkid[2], pmkid[3], pmkid[4], pmkid[5])); + } + } + } + } else +#endif /* DOT11_SAE_SUPPORT */ + + if ((auth_info.auth_alg == AUTH_MODE_OPEN) && + (pMbss->wdev.AuthMode != Ndis802_11AuthModeShared)) + { + if (!pEntry) + pEntry = MacTableInsertEntry(pAd, auth_info.addr2, wdev, ENTRY_CLIENT, OPMODE_AP, TRUE); + + if (pEntry) + { +#ifdef DOT11W_PMF_SUPPORT + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + + if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE)) + || (tr_entry->PortSecured != WPA_802_1X_PORT_SECURED)) +#endif /* DOT11W_PMF_SUPPORT */ + { + pEntry->AuthState = AS_AUTH_OPEN; + pEntry->Sst = SST_AUTH; /* what if it already in SST_ASSOC ??????? */ + } + APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, auth_info.auth_alg, auth_info.auth_seq + 1, MLME_SUCCESS); + + } else { +#ifdef WIFI_DIAG + DiagConnError(pAd, apidx, auth_info.addr2, DIAG_CONN_STA_LIM, 0); +#endif +#ifdef CONN_FAIL_EVENT + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[apidx].Ssid, + pAd->ApCfg.MBSSID[apidx].SsidLen, + auth_info.addr2, + REASON_DISASSPC_AP_UNABLE); +#endif + } + + } + else if ((auth_info.auth_alg == AUTH_MODE_KEY) && + ((wdev->AuthMode == Ndis802_11AuthModeShared) + || (wdev->AuthMode == Ndis802_11AuthModeAutoSwitch))) + { + if (!pEntry) + pEntry = MacTableInsertEntry(pAd, auth_info.addr2, wdev, ENTRY_CLIENT, 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, auth_info.addr2); + for(i=0; iApMlmeAux.Challenge[i] = RandomByte(pAd); + + RspReason = 0; + auth_info.auth_seq++; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) { + /*return;*/ /* if no memory, can't do anything */ +#ifdef WAPP_SUPPORT + wapp_auth_fail = MLME_NO_RESOURCE; +#endif /* WAPP_SUPPORT */ + goto auth_failure; /* if no memory, can't do anything */ + } + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH seq#2 (Challenge)\n")); + + MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, auth_info.addr2, + wdev->if_addr, + wdev->bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &AuthHdr, + 2, &auth_info.auth_alg, + 2, &auth_info.auth_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 { +#ifdef WIFI_DIAG + DiagConnError(pAd, apidx, auth_info.addr2, DIAG_CONN_STA_LIM, 0); +#endif +#ifdef CONN_FAIL_EVENT + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[apidx].Ssid, + pAd->ApCfg.MBSSID[apidx].SsidLen, + auth_info.addr2, + REASON_DISASSPC_AP_UNABLE); +#endif + } + + } +#ifdef WH_EZ_SETUP /* Move to ez_cmm.c */ + else if ((auth_info.auth_alg == AUTH_MODE_EZ) + && IS_EZ_SETUP_ENABLED(wdev)) { + if (!pEntry) + pEntry = MacTableInsertEntry(pAd, auth_info.addr2, wdev, ENTRY_CLIENT, OPMODE_AP, TRUE); + + if (pEntry) { + if (ez_process_auth_request(pAd, wdev, &auth_info, Elem->Msg, Elem->MsgLen)) { + pEntry->AuthState = AS_AUTH_OPEN; + pEntry->Sst = SST_AUTH; + } + else + { + ez_update_connection(pAd, wdev); + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + } + + } + } +#endif /* WH_EZ_SETUP */ + else + { + /* wrong algorithm */ + APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, auth_info.auth_alg, auth_info.auth_seq + 1, MLME_ALG_NOT_SUPPORT); +#ifdef WIFI_DIAG + DiagConnError(pAd, apidx, auth_info.addr2, + DIAG_CONN_AUTH_FAIL, REASON_AUTH_WRONG_ALGORITHM); +#endif +#ifdef CONN_FAIL_EVENT + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[apidx].Ssid, + pAd->ApCfg.MBSSID[apidx].SsidLen, + auth_info.addr2, + REASON_AKMP_NOT_VALID); +#endif + /* If this STA exists, delete it. */ + if (pEntry) + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Alg=%d, Seq=%d, AuthMode=%d\n", + auth_info.auth_alg, auth_info.auth_seq, pAd->ApCfg.MBSSID[apidx].wdev.AuthMode)); + } + return; +auth_failure: +#ifdef WAPP_SUPPORT + wapp_send_sta_connect_rejected(pAd, wdev, auth_info.addr2, auth_info.addr1, wapp_cnnct_stage, wapp_auth_fail); +#endif/* WAPP_SUPPORT */ + return; +} + + +static VOID APPeerAuthConfirmAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + AUTH_FRAME_INFO auth_info; + PHEADER_802_11 pRcvHdr; + MAC_TABLE_ENTRY *pEntry; + UINT32 apidx, u4MaxMBSSIDSize; +#ifdef DOT11R_FT_SUPPORT + PFT_CFG pFtCfg; + PFT_INFO pFtInfoBuf; +#endif /* DOT11R_FT_SUPPORT */ + + + + if (pAd == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pAd is NULL\n",__FUNCTION__)); + return; + } + + + if (!APPeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, &auth_info)) + return; + + u4MaxMBSSIDSize = sizeof(pAd->ApCfg.MBSSID)/sizeof(pAd->ApCfg.MBSSID[0]); + apidx = get_apidx_by_addr(pAd, auth_info.addr1); + if ((apidx >= pAd->ApCfg.BssidNum) || (apidx >= u4MaxMBSSIDSize)) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Bssid not found\n")); + return; + } + + if ((pAd->ApCfg.MBSSID[apidx].wdev.if_dev != NULL) && + !(RTMP_OS_NETDEV_STATE_RUNNING(pAd->ApCfg.MBSSID[apidx].wdev.if_dev))) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Bssid IF didn't up yet.\n")); + return; + } /* End of if */ + + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + { + DBGPRINT(RT_DEBUG_ERROR, ("AUTH - Invalid wcid (%d).\n", Elem->Wcid)); + return; + } + + pEntry = &pAd->MacTab.Content[Elem->Wcid]; + if (pEntry && IS_ENTRY_CLIENT(pEntry)) + { + if (!RTMPEqualMemory(auth_info.addr1, pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid, MAC_ADDR_LEN)) + { + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + pEntry = NULL; + DBGPRINT(RT_DEBUG_WARN, ("AUTH - Bssid does not match\n")); + } + else + { + if (pEntry->bIAmBadAtheros == TRUE) + { + AsicUpdateProtect(pAd, 8, ALLN_SETPROTECT, FALSE, FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("Atheros Problem. Turn on RTS/CTS!!!\n")); + pEntry->bIAmBadAtheros = FALSE; + } + + ASSERT(pEntry->Aid == Elem->Wcid); + +#ifdef DOT11_N_SUPPORT + BASessionTearDownALL(pAd, pEntry->wcid); +#endif /* DOT11_N_SUPPORT */ + } + } + + pRcvHdr = (PHEADER_802_11)(Elem->Msg); + + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - MBSS(%d), Rcv AUTH seq#%d, Alg=%d, Status=%d from " + "[wcid=%d]%02x:%02x:%02x:%02x:%02x:%02x\n", + apidx, auth_info.auth_seq, auth_info.auth_alg, + auth_info.auth_status, Elem->Wcid, + PRINT_MAC(auth_info.addr2))); + if(pEntry) { + INT32 prev = -1; + prev = (INT32)pEntry->AuthAssocNotInProgressFlag; + pEntry->AuthAssocNotInProgressFlag = 0; + DBGPRINT(RT_DEBUG_TRACE,("===[%s]..2 prev_val = %d AuthAssocNotInProgressFlag = %u \n", + __FUNCTION__, prev, pEntry->AuthAssocNotInProgressFlag)); + } + if (pEntry && MAC_ADDR_EQUAL(auth_info.addr2, pAd->ApMlmeAux.Addr)) + { +#ifdef DOT11R_FT_SUPPORT + pFtCfg = &pAd->ApCfg.MBSSID[apidx].FtCfg; + if ((pFtCfg->FtCapFlag.Dot11rFtEnable) && (auth_info.auth_alg == AUTH_MODE_FT)) + { + USHORT result; + + os_alloc_mem(pAd, (UCHAR **)&pFtInfoBuf, sizeof(FT_INFO)); + if (pFtInfoBuf) + { + os_alloc_mem(pAd, (UCHAR **)&(pFtInfoBuf->RicInfo.pRicInfo), 512); + if (pFtInfoBuf->RicInfo.pRicInfo != NULL) + { + result = FT_AuthConfirmHandler(pAd, pEntry, &auth_info.FtInfo, pFtInfoBuf); + + FT_EnqueueAuthReply(pAd, pRcvHdr, auth_info.auth_alg, 4, result, + &pFtInfoBuf->MdIeInfo, &pFtInfoBuf->FtIeInfo, + &pFtInfoBuf->RicInfo, pFtInfoBuf->RSN_IE, pFtInfoBuf->RSNIE_Len); + + os_free_mem(NULL, pFtInfoBuf->RicInfo.pRicInfo); + } + os_free_mem(NULL, pFtInfoBuf); + } + } + else +#endif /* DOT11R_FT_SUPPORT */ + if ((pRcvHdr->FC.Wep == 1) && + NdisEqualMemory(auth_info.Chtxt, pAd->ApMlmeAux.Challenge, CIPHER_TEXT_LEN)) + { + /* Successful */ + APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, auth_info.auth_alg, auth_info.auth_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, auth_info.auth_alg, + auth_info.auth_seq + 1, + MLME_REJ_CHALLENGE_FAILURE); +#ifdef WIFI_DIAG + if (IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_AUTH_FAIL, REASON_CHALLENGE_FAIL); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + REASON_MIC_FAILURE); +#endif + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + + /*Chtxt[127]='\0'; */ + /*pAd->ApMlmeAux.Challenge[127]='\0'; */ + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", + ((pRcvHdr->FC.Wep == 1) ? "challenge text is not equal" : "wep bit is not set"))); + /*DBGPRINT(RT_DEBUG_TRACE, ("Sent Challenge = %s\n",&pAd->ApMlmeAux.Challenge[100])); */ + /*DBGPRINT(RT_DEBUG_TRACE, ("Rcv Challenge = %s\n",&Chtxt[100])); */ + } + } + else + { + /* fail for unknown reason. most likely is AuthRspAux machine be overwritten by another */ + /* STA also using SHARED_KEY authentication */ + APPeerAuthSimpleRspGenAndSend(pAd, pRcvHdr, auth_info.auth_alg, auth_info.auth_seq + 1, MLME_UNSPECIFY_FAIL); + + /* If this STA exists, delete it. */ + if (pEntry) { +#ifdef WIFI_DIAG + if (IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_AUTH_FAIL, REASON_UNKNOWN); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + REASON_MIC_FAILURE); +#endif + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + } + } +} + + +/* + ========================================================================== + Description: + Some STA/AP + Note: + This action should never trigger AUTH state transition, therefore we + separate it from AUTH state machine, and make it as a standalone service + ========================================================================== + */ +VOID APCls2errAction( + IN RTMP_ADAPTER *pAd, + IN ULONG Wcid, + IN HEADER_802_11 *pHeader) +{ + HEADER_802_11 Hdr; + UCHAR *pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + USHORT Reason = REASON_CLS2ERR; + MAC_TABLE_ENTRY *pEntry = NULL; + UCHAR apidx; + + if (Wcid < MAX_LEN_OF_MAC_TABLE) + pEntry = &(pAd->MacTab.Content[Wcid]); + + if (pEntry && IS_ENTRY_CLIENT(pEntry)) { +#ifdef WIFI_DIAG + if (IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_DEAUTH, Reason); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + REASON_CLS2ERR); +#endif + /*ApLogEvent(pAd, pAddr, EVENT_DISASSOCIATED); */ + MacTableDeleteEntry(pAd, pEntry->wcid, pHeader->Addr2); + } + else + { + apidx = get_apidx_by_addr(pAd, pHeader->Addr1); + if (apidx >= pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_TRACE,("AUTH - Class 2 error but not my bssid %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pHeader->Addr1))); + return; + } + } + + /* send out DEAUTH frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, + ("AUTH - Class 2 error, Send DEAUTH frame to " + "%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pHeader->Addr2))); + + MgtMacHeaderInit(pAd, &Hdr, SUBTYPE_DEAUTH, 0, pHeader->Addr2, + pHeader->Addr1, + pHeader->Addr1); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr, + 2, &Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + + +/* + ========================================================================== + Description: + 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); +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_autoChSel.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_autoChSel.c new file mode 100644 index 000000000..a02abd0a4 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_autoChSel.c @@ -0,0 +1,1563 @@ +/**************************************************************************** + * 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; + INT Score; + if (Alg == ChannelAlgCCA || Alg == ChannelAlgCombined) + { + UINT32 cca_cnt = AsicGetCCACnt(pAd); + + pAd->RalinkCounters.OneSecFalseCCACnt += cca_cnt; + pAd->pChannelInfo->FalseCCA[ch_index] = cca_cnt; + } + + /* + do busy time statistics for primary channel + scan time 400ms, beacon interval 100 ms + */ + BusyTime = AsicGetChBusyCnt(pAd, 0); + Score = 100 - BusyTime/(AUTO_CHANNEL_SEL_TIMEOUT * 10); + if (Score < 0) + Score = 0; + +//#ifdef AP_QLOAD_SUPPORT + pAd->pChannelInfo->chanbusytime[ch_index] = (BusyTime * 100) / AUTO_CHANNEL_SEL_TIMEOUT; +//#endif /* AP_QLOAD_SUPPORT */ +#ifdef ACS_CTCC_SUPPORT + pAd->pChannelInfo->suppChList[ch_index].BusyTime = (BusyTime * 100) / AUTO_CHANNEL_SEL_TIMEOUT; + pAd->pChannelInfo->ChannelScore[ch_index].Score = Score; + pAd->pChannelInfo->ChannelScore[ch_index].Channel = pAd->ChannelList[ch_index].Channel; + DBGPRINT(RT_DEBUG_TRACE, ("channel %d busytime %d\n", + pAd->ChannelList[ch_index].Channel, pAd->pChannelInfo->chanbusytime[ch_index])); +#endif + } + else + DBGPRINT(RT_DEBUG_TRACE, ("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 = get_channel_by_reference(pAd, 1); + } + + } + 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 >= -50) + { + /* high signal >= -50 dbm */ + pChannelInfo->dirtyness[channel_idx] += 50; + } + else if (pBss->Rssi <= -80) + { + /* low signal <= -80 dbm */ + pChannelInfo->dirtyness[channel_idx] += 30; + } + else + { + /* mid signal -50 ~ -80 dbm */ + pChannelInfo->dirtyness[channel_idx] += 40; + } + + pChannelInfo->dirtyness[channel_idx] += 40; + + { + INT BelowBound; + INT AboveBound; + INT loop; + + switch(pBss->ExtChOffset) + { + case EXTCHA_ABOVE: + BelowBound = pChannelInfo->IsABand ? 1 : 4; + AboveBound = pChannelInfo->IsABand ? 2 : 8; + break; + + case EXTCHA_BELOW: + BelowBound = pChannelInfo->IsABand ? 2 : 8; + AboveBound = pChannelInfo->IsABand ? 1 : 4; + break; + + default: + BelowBound = pChannelInfo->IsABand ? 1 : 4; + AboveBound = pChannelInfo->IsABand ? 1 : 4; + break; + } + + /* check neighbor channel */ + for (loop = (channel_idx+1); loop <= (channel_idx+AboveBound); loop++) + { + if (loop >= MAX_NUM_OF_CHANNELS) + break; + + if (pAd->ChannelList[loop].Channel - pAd->ChannelList[loop-1].Channel > 4) + break; + + pChannelInfo->dirtyness[loop] += ((9 - (loop - channel_idx)) * 4); + } + /* check neighbor channel */ + for (loop=(channel_idx-1); loop >= (channel_idx-BelowBound); loop--) + { + if (loop < 0) + break; + + if (pAd->ChannelList[loop+1].Channel - pAd->ChannelList[loop].Channel > 4) + continue; + + pChannelInfo->dirtyness[loop] += + ((9 - (channel_idx - loop)) * 4); + } + } + + 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_ERROR, ("=====================================================\n")); + for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++) + { + DBGPRINT(RT_DEBUG_ERROR, ("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], + pChannelInfo->chanbusytime[channel_idx], + (pChannelInfo->SkipList[channel_idx] == TRUE) ? "TRUE" : "FALSE")); + } + DBGPRINT(RT_DEBUG_ERROR, ("=====================================================\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_ERROR, ("Rule 1 CCA value : Min Dirtiness (Include extension channel) ==> Select Channel %d \n", ch)); + DBGPRINT(RT_DEBUG_ERROR, ("Min Dirty = %u\n", min_dirty)); + DBGPRINT(RT_DEBUG_ERROR, ("ExChannel = %d , %d\n", candidate_ExChannel[0], candidate_ExChannel[1])); + DBGPRINT(RT_DEBUG_ERROR, ("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_ERROR, ("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_ERROR, ("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], + pChannelInfo->chanbusytime[channel_index], + (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; + +} + +#ifdef ACS_CTCC_SUPPORT +VOID BuildAcsScanChList(RTMP_ADAPTER *pAd) +{ + INT channel_idx, ChListNum = 0; + UCHAR ch; + UCHAR cfg_ht_bw = pAd->CommonCfg.RegTransmitSetting.field.BW; + UCHAR op_ext_cha = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; + AutoChannelSkipListSetDirty(pAd); + if (pAd->pChannelInfo->IsABand) { + for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++) { + ch = pAd->ChannelList[channel_idx].Channel; + pAd->pChannelInfo->suppChList[ChListNum].ApCnt = pAd->pChannelInfo->ApCnt[channel_idx]; + if (cfg_ht_bw == BW_20) { + pAd->pChannelInfo->suppChList[ChListNum].Channel = pAd->ChannelList[channel_idx].Channel; + pAd->pChannelInfo->suppChList[ChListNum].CenChannel = pAd->ChannelList[channel_idx].Channel; + pAd->pChannelInfo->suppChList[ChListNum].DfsReq = pAd->ChannelList[channel_idx].DfsReq; + if (pAd->pChannelInfo->SkipList[channel_idx] == TRUE) + pAd->pChannelInfo->suppChList[ChListNum].SkipChannel = TRUE; + ChListNum++; + } +#ifdef DOT11_N_SUPPORT + else if (((cfg_ht_bw == BW_40) +#ifdef DOT11_VHT_AC + && (pAd->CommonCfg.vht_bw == VHT_BW_2040) +#endif /* DOT11_VHT_AC */ + ) + && N_ChannelGroupCheck(pAd, ch)) { + pAd->pChannelInfo->suppChList[ChListNum].Channel = pAd->ChannelList[channel_idx].Channel; + if (GetABandChOffset(ch) == 1) + pAd->pChannelInfo->suppChList[ChListNum].CenChannel = pAd->ChannelList[channel_idx].Channel + 2; + else + pAd->pChannelInfo->suppChList[ChListNum].CenChannel = pAd->ChannelList[channel_idx].Channel - 2; + pAd->pChannelInfo->suppChList[ChListNum].DfsReq = pAd->ChannelList[channel_idx].DfsReq; + if (pAd->pChannelInfo->SkipList[channel_idx] == TRUE) + pAd->pChannelInfo->suppChList[ChListNum].SkipChannel = TRUE; + ChListNum++; + } +#ifdef DOT11_VHT_AC + else if (pAd->CommonCfg.vht_bw == VHT_BW_80) { + if (vht80_channel_group(pAd, ch)) { + pAd->pChannelInfo->suppChList[ChListNum].Channel = pAd->ChannelList[channel_idx].Channel; + pAd->pChannelInfo->suppChList[ChListNum].CenChannel = vht_cent_ch_freq (ch, VHT_BW_80); + pAd->pChannelInfo->suppChList[ChListNum].DfsReq = pAd->ChannelList[channel_idx].DfsReq; + if (pAd->pChannelInfo->SkipList[channel_idx] == TRUE) + pAd->pChannelInfo->suppChList[ChListNum].SkipChannel = TRUE; + ChListNum++; + } + } +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + } + } else { + for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++) { + if (cfg_ht_bw == BW_40) { + if (op_ext_cha == EXTCHA_ABOVE) + pAd->pChannelInfo->suppChList[ChListNum].CenChannel = pAd->ChannelList[channel_idx].Channel + 2; + else { + if (pAd->ChannelList[channel_idx].Channel == 14) + pAd->pChannelInfo->suppChList[ChListNum].CenChannel = pAd->ChannelList[channel_idx].Channel - 1; + else + pAd->pChannelInfo->suppChList[ChListNum].CenChannel = pAd->ChannelList[channel_idx].Channel - 2; + } + } else + pAd->pChannelInfo->suppChList[ChListNum].CenChannel = pAd->ChannelList[channel_idx].Channel; + pAd->pChannelInfo->suppChList[ChListNum].Channel = pAd->ChannelList[channel_idx].Channel; + if (pAd->pChannelInfo->SkipList[channel_idx] == TRUE) + pAd->pChannelInfo->suppChList[ChListNum].SkipChannel = TRUE; + ChListNum++; + } + } + pAd->pChannelInfo->ChannelListNum = ChListNum; + for (channel_idx = 0; channel_idx < pAd->pChannelInfo->ChannelListNum; channel_idx++) { + DBGPRINT(RT_DEBUG_TRACE, ("[%s] Support channel: PrimCh=%d, CentCh=%d, DFS=%d, skip %d\n", + __FUNCTION__, pAd->pChannelInfo->suppChList[channel_idx].Channel, pAd->pChannelInfo->suppChList[channel_idx].CenChannel, + pAd->pChannelInfo->suppChList[channel_idx].DfsReq, pAd->pChannelInfo->suppChList[ChListNum].SkipChannel)); + } +} +UINT8 GroupChListSearch(PRTMP_ADAPTER pAd, UCHAR CenChannel) +{ + UCHAR i; + PACS_SCAN_CH_GROUP_LIST GroupChList = pAd->pChannelInfo->GroupChList; + + for (i = 0; i < pAd->pChannelInfo->GroupChListNum; i++) { + if (GroupChList->CenChannel == CenChannel) + return i; + GroupChList++; + } + return 0xff; +} +VOID GroupChListInsert(PRTMP_ADAPTER pAd, PACS_SCAN_SUPP_CH_LIST pSource) +{ + UCHAR i = pAd->pChannelInfo->GroupChListNum; + PACS_SCAN_CH_GROUP_LIST GroupChList = &pAd->pChannelInfo->GroupChList[i]; + GroupChList->BestCtrlChannel = pSource->Channel; + GroupChList->CenChannel = pSource->CenChannel; + + if (pSource->Channel > 1 && pSource->Channel < 6) { + pSource->BusyTime += pAd->pChannelInfo->suppChList[0].BusyTime; + } else if (pSource->Channel > 6 && pSource->Channel < 11) { + pSource->BusyTime += pAd->pChannelInfo->suppChList[5].BusyTime; + } else { + pSource->BusyTime += pAd->pChannelInfo->suppChList[10].BusyTime; + } + GroupChList->Max_Busy_Time = pSource->BusyTime; + GroupChList->SkipGroup = pSource->SkipChannel; + DBGPRINT(RT_DEBUG_ERROR, ("[%s] Insert Grp Ch Idx=%d,CenChannel=%d,CtrlCh=%d,BusyTime=%d,SkipGrp=%d\n", + __FUNCTION__, pAd->pChannelInfo->GroupChListNum, GroupChList->CenChannel, + pSource->Channel, pSource->BusyTime, GroupChList->SkipGroup)); + pAd->pChannelInfo->GroupChListNum = i + 1; +} +VOID GroupChListUpdate(PRTMP_ADAPTER pAd, UCHAR index, PACS_SCAN_SUPP_CH_LIST pSource) +{ + PACS_SCAN_CH_GROUP_LIST GroupChList = &pAd->pChannelInfo->GroupChList[index]; + if (pSource->Channel > 1 && pSource->Channel < 6) { + pSource->BusyTime += pAd->pChannelInfo->suppChList[0].BusyTime; + } else if (pSource->Channel > 6 && pSource->Channel < 11) { + pSource->BusyTime += pAd->pChannelInfo->suppChList[5].BusyTime; + } else { + pSource->BusyTime += pAd->pChannelInfo->suppChList[10].BusyTime; + } + if (pSource->BusyTime > GroupChList->Max_Busy_Time) { + GroupChList->Max_Busy_Time = pSource->BusyTime; + } + if (pSource->BusyTime < GroupChList->Min_Busy_Time) { + GroupChList->BestCtrlChannel = pSource->Channel; + } + if (GroupChList->SkipGroup == 0 && pSource->SkipChannel == 1) + GroupChList->SkipGroup = pSource->SkipChannel; + DBGPRINT(RT_DEBUG_ERROR, ("%s CtrlCh %d, BusyTime %d, Skip %d\n", + __FUNCTION__, pSource->Channel, pSource->BusyTime, pSource->SkipChannel)); + DBGPRINT(RT_DEBUG_ERROR, ("%s Update grp ch idx=%d," + " CenCh=%d CtrlCh=%d MaxBusyTime=%d SkipGrp=%d\n", + __FUNCTION__, pAd->pChannelInfo->GroupChListNum, GroupChList->CenChannel, + GroupChList->BestCtrlChannel, GroupChList->Max_Busy_Time, GroupChList->SkipGroup)); +} +VOID GenerateGroupChannelList(PRTMP_ADAPTER pAd) +{ + UCHAR i, ListIndex; + PACS_SCAN_SUPP_CH_LIST SuppChList = pAd->pChannelInfo->suppChList; + memset(pAd->pChannelInfo->GroupChList, 0, (MAX_NUM_OF_CHANNELS+1) * sizeof(ACS_SCAN_SUPP_CH_LIST)); + pAd->pChannelInfo->GroupChListNum = 0; + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + ListIndex = GroupChListSearch(pAd, SuppChList->CenChannel); + if (ListIndex == 0xff) { + GroupChListInsert(pAd, SuppChList); + } else { + GroupChListUpdate(pAd, ListIndex, SuppChList); + } + SuppChList++; + } +} +UCHAR FindBestChannelOfAllGrp(RTMP_ADAPTER *pAd) +{ + int i; + UCHAR BestChannel = 0; + UINT32 MinBusy = 0xffffffff; + UINT32 Busy = 0; + for (i = 0; i < pAd->pChannelInfo->GroupChListNum; i++) { + if (pAd->pChannelInfo->GroupChList[i].SkipGroup == FALSE) { + Busy = pAd->pChannelInfo->GroupChList[i].Max_Busy_Time; + DBGPRINT(RT_DEBUG_ERROR, ("Group Idx=%d,control-Channle=%d,cen-channel=%d,Max-Busy-Time=%d\n", + i, pAd->pChannelInfo->GroupChList[i].BestCtrlChannel, + pAd->pChannelInfo->GroupChList[i].CenChannel, pAd->pChannelInfo->GroupChList[i].Max_Busy_Time)); + if (Busy < MinBusy) { + MinBusy = Busy; + BestChannel = pAd->pChannelInfo->GroupChList[i].BestCtrlChannel; + } + } + } + DBGPRINT(RT_DEBUG_ERROR, ("Min Busy Time=%d,select best ch %d\n", MinBusy, BestChannel)); + return BestChannel; +} +static inline UCHAR SelectClearChannelBusyTime( + IN PRTMP_ADAPTER pAd) +{ + int i, Score; + UCHAR BestChannel = 0; + UINT32 Ch1BusyTime = 0xffffffff; + UINT32 Ch6BusyTime = 0xffffffff; + UINT32 Ch11BusyTime = 0xffffffff; + UINT32 MinBusy = 0xffffffff; + UINT32 MaxBusy = 0; + UINT8 BitMap = 0; + UCHAR cfg_ht_bw = pAd->CommonCfg.RegTransmitSetting.field.BW; + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + if (((pAd->pChannelInfo->suppChList[i].Channel == 1) || + (pAd->pChannelInfo->suppChList[i].Channel == 6) || + (pAd->pChannelInfo->suppChList[i].Channel == 11))) { + if (pAd->pChannelInfo->suppChList[i].BusyTime < MinBusy) { + MinBusy = pAd->pChannelInfo->suppChList[i].BusyTime; + BestChannel = pAd->pChannelInfo->suppChList[i].Channel; + } + if (pAd->pChannelInfo->suppChList[i].BusyTime > MaxBusy) + MaxBusy = pAd->pChannelInfo->suppChList[i].BusyTime; + } + if ((pAd->pChannelInfo->ApCnt[i] != 0)) { + if (pAd->ChannelList[i].Channel == 1) { + BitMap |= (1<<0); + } else if (pAd->ChannelList[i].Channel == 6) { + BitMap |= (1<<1); + } else if (pAd->ChannelList[i].Channel == 11) { + BitMap |= (1<<2); + } + } + } + switch (BitMap) { + case 7: + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + if (((pAd->pChannelInfo->suppChList[i].Channel == 1) || + (pAd->pChannelInfo->suppChList[i].Channel == 6) || + (pAd->pChannelInfo->suppChList[i].Channel == 11))) { + if (pAd->pChannelInfo->suppChList[i].BusyTime < MinBusy) { + MinBusy = pAd->pChannelInfo->suppChList[i].BusyTime; + BestChannel = pAd->pChannelInfo->suppChList[i].Channel; + } + } + } + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + if (((pAd->pChannelInfo->suppChList[i].Channel != 1) && + (pAd->pChannelInfo->suppChList[i].Channel != 6) && + (pAd->pChannelInfo->suppChList[i].Channel != 11))) { + pAd->pChannelInfo->suppChList[i].BusyTime += MaxBusy; + } + } + break; + case 6: + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + if (pAd->pChannelInfo->suppChList[i].Channel != 1) { + pAd->pChannelInfo->suppChList[i].BusyTime += MaxBusy; + } else + BestChannel = pAd->pChannelInfo->suppChList[i].Channel; + } + break; + case 5: + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + if (pAd->pChannelInfo->suppChList[i].Channel != 6) { + pAd->pChannelInfo->suppChList[i].BusyTime += MaxBusy; + } else + BestChannel = pAd->pChannelInfo->suppChList[i].Channel; + } + break; + case 4: + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + if (pAd->pChannelInfo->suppChList[i].Channel == 1) + Ch1BusyTime = pAd->pChannelInfo->suppChList[i].BusyTime; + else if (pAd->pChannelInfo->suppChList[i].Channel == 6) + Ch6BusyTime = pAd->pChannelInfo->suppChList[i].BusyTime; + } + if (Ch1BusyTime <= Ch6BusyTime) { + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + if (pAd->pChannelInfo->suppChList[i].Channel != 1) { + pAd->pChannelInfo->suppChList[i].BusyTime += MaxBusy; + } else + BestChannel = pAd->pChannelInfo->suppChList[i].Channel; + } + } else { + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + if (pAd->pChannelInfo->suppChList[i].Channel != 6) { + pAd->pChannelInfo->suppChList[i].BusyTime += MaxBusy; + } else + BestChannel = pAd->pChannelInfo->suppChList[i].Channel; + } + } + break; + case 3: + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + if (pAd->pChannelInfo->suppChList[i].Channel != 11) { + pAd->pChannelInfo->suppChList[i].BusyTime += MaxBusy; + } else + BestChannel = pAd->pChannelInfo->suppChList[i].Channel; + } + break; + case 2: + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + if (pAd->pChannelInfo->suppChList[i].Channel == 1) + Ch1BusyTime = pAd->pChannelInfo->suppChList[i].BusyTime; + else if (pAd->pChannelInfo->suppChList[i].Channel == 11) + Ch11BusyTime = pAd->pChannelInfo->suppChList[i].BusyTime; + } + if (Ch1BusyTime <= Ch11BusyTime) { + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + if (pAd->pChannelInfo->suppChList[i].Channel != 1) { + pAd->pChannelInfo->suppChList[i].BusyTime += MaxBusy; + } else + BestChannel = pAd->pChannelInfo->suppChList[i].Channel; + } + } else { + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + if (pAd->pChannelInfo->suppChList[i].Channel != 11) { + pAd->pChannelInfo->suppChList[i].BusyTime += MaxBusy; + } else + BestChannel = pAd->pChannelInfo->suppChList[i].Channel; + } + } + break; + case 1: + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + if (pAd->pChannelInfo->suppChList[i].Channel == 6) + Ch6BusyTime = pAd->pChannelInfo->suppChList[i].BusyTime; + else if (pAd->pChannelInfo->suppChList[i].Channel == 11) + Ch11BusyTime = pAd->pChannelInfo->suppChList[i].BusyTime; + } + if (Ch6BusyTime <= Ch11BusyTime) { + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + if (pAd->pChannelInfo->suppChList[i].Channel != 6) { + pAd->pChannelInfo->suppChList[i].BusyTime += MaxBusy; + } else + BestChannel = pAd->pChannelInfo->suppChList[i].Channel; + } + } else { + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + if (pAd->pChannelInfo->suppChList[i].Channel != 11) { + pAd->pChannelInfo->suppChList[i].BusyTime += MaxBusy; + } else + BestChannel = pAd->pChannelInfo->suppChList[i].Channel; + } + } + break; + case 0: + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + if (pAd->pChannelInfo->suppChList[i].BusyTime != MinBusy) { + pAd->pChannelInfo->suppChList[i].BusyTime += MaxBusy; + } else { + if (((pAd->pChannelInfo->suppChList[i].Channel != 1) && + (pAd->pChannelInfo->suppChList[i].Channel != 6) && + (pAd->pChannelInfo->suppChList[i].Channel != 11))) + continue; + BestChannel = pAd->pChannelInfo->suppChList[i].Channel; + } + } + break; + default: + break; + } + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + Score = 100 - (pAd->pChannelInfo->suppChList[i].BusyTime / 1000); + if (Score < 0) + Score = 0; + pAd->pChannelInfo->ChannelScore[i].Score = Score; + pAd->pChannelInfo->ChannelScore[i].Channel = pAd->pChannelInfo->suppChList[i].Channel; + } + DBGPRINT(RT_DEBUG_ERROR, ("=====================================================\n")); + for (i = 0; i < pAd->pChannelInfo->ChannelListNum; i++) { + for (i = 0; i < pAd->ChannelListNum; i++) { + DBGPRINT(RT_DEBUG_ERROR, ("Channel %d : Busy Time = %u, Score %d,Skip Channel = %s\n", + pAd->pChannelInfo->suppChList[i].Channel, + pAd->pChannelInfo->suppChList[i].BusyTime, + pAd->pChannelInfo->ChannelScore[i].Score, + (pAd->pChannelInfo->suppChList[i].SkipChannel == TRUE) ? "TRUE" : "FALSE")); + } + DBGPRINT(RT_DEBUG_ERROR, ("=====================================================\n")); + } + if (cfg_ht_bw == BW_20) + return BestChannel; + else + GenerateGroupChannelList(pAd); + BestChannel = FindBestChannelOfAllGrp(pAd); + return BestChannel; +} +#else +static inline UCHAR SelectClearChannelBusyTime( + IN PRTMP_ADAPTER pAd + ) +{ + PCHANNELINFO pChannelInfo = pAd->pChannelInfo; + INT ch = 1, channel_idx; + UINT32 min_busytime; + int candidate_ch; + UCHAR base; + if (pChannelInfo == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("pAd->pChannelInfo equal NULL.\n")); + ch = FirstChannel(pAd); + return ch; + } + AutoChannelSkipListSetDirty(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("=====================================================\n")); + for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++) { + DBGPRINT(RT_DEBUG_TRACE, ("Channel %d : Busy Time = %u, Skip Channel = %s\n", + pAd->ChannelList[channel_idx].Channel, + pChannelInfo->chanbusytime[channel_idx], + (pChannelInfo->SkipList[channel_idx] == TRUE) ? "TRUE" : "FALSE")); + } + DBGPRINT(RT_DEBUG_TRACE, ("=====================================================\n")); + min_busytime = 0xFFFFFFFF; + candidate_ch = -1; + for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++) { + if (pChannelInfo->SkipList[channel_idx] == TRUE) + continue; + if (pChannelInfo->chanbusytime[channel_idx] < min_busytime) { + min_busytime = pChannelInfo->chanbusytime[channel_idx]; + candidate_ch = channel_idx; + } + } + if (candidate_ch >= 0) { + ch = pAd->ChannelList[candidate_ch].Channel; + DBGPRINT(RT_DEBUG_TRACE, ("Rule 3 Channel Busy time value : Min Channel Busy ==> Select Channel %d\n", ch)); + DBGPRINT(RT_DEBUG_TRACE, ("Min Channel Busy = %u\n", min_busytime)); + DBGPRINT(RT_DEBUG_TRACE, ("BW = %s\n", (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) ? "40" : "20")); + 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, ("Randomly Select ==> Select Channel %d\n", ch)); + return ch; +} +#endif +ULONG AutoChBssInsertEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBssid, + IN CHAR Ssid[], + IN UCHAR SsidLen, + IN UCHAR ChannelNo, + IN UCHAR ExtChOffset, + IN CHAR Rssi) +{ + 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) +{ + os_alloc_mem(pAd, (UCHAR **)&pAd->pBssInfoTab, sizeof(BSSINFO)); + if (pAd->pBssInfoTab) + NdisZeroMemory(pAd->pBssInfoTab, sizeof(BSSINFO)); + else + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->pBssInfoTab", __FUNCTION__)); + + return; +} + +void ChannelInfoInit( + IN PRTMP_ADAPTER pAd) +{ + os_alloc_mem(pAd, (UCHAR **)&pAd->pChannelInfo, sizeof(CHANNELINFO)); + if (pAd->pChannelInfo) + NdisZeroMemory(pAd->pChannelInfo, sizeof(CHANNELINFO)); + else + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->pChannelInfo", __FUNCTION__)); + + + return; +} + +void AutoChBssTableDestroy( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->pBssInfoTab) + { + os_free_mem(NULL, pAd->pBssInfoTab); + pAd->pBssInfoTab = NULL; + } + + return; +} + +void ChannelInfoDestroy( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->pChannelInfo) + { + os_free_mem(NULL, pAd->pChannelInfo); + pAd->pChannelInfo = NULL; + } + + return; +} + +/* + ========================================================================== + Description: + This routine sets the current PhyMode for calculating + the dirtyness. + Return: + none + NOTE: + ========================================================================== + */ +void CheckPhyModeIsABand(RTMP_ADAPTER *pAd) +{ + pAd->pChannelInfo->IsABand = (WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) ? TRUE : FALSE; + + return; +} + + +UCHAR SelectBestChannel(RTMP_ADAPTER *pAd, ChannelSel_Alg Alg) +{ + UCHAR ch = 0; + + /* init pAd->pChannelInfo->IsABand */ + CheckPhyModeIsABand(pAd); + +#ifdef MICROWAVE_OVEN_SUPPORT + if (Alg == ChannelAlgCCA) + pAd->CommonCfg.MO_Cfg.bEnable = TRUE; +#endif /* MICROWAVE_OVEN_SUPPORT */ + + switch ( Alg ) + { + case ChannelAlgRandom: + case ChannelAlgApCnt: + ch = SelectClearChannelApCnt(pAd); + break; + case ChannelAlgCCA: + ch = SelectClearChannelCCA(pAd); + break; + case ChannelAlgBusyTime: + ch = SelectClearChannelBusyTime(pAd); + break; + default: + ch = SelectClearChannelBusyTime(pAd); + break; + } + + RTMPSendWirelessEvent(pAd, IW_CHANNEL_CHANGE_EVENT_FLAG, 0, 0, ch); + + return ch; + +} + +VOID APAutoChannelInit(RTMP_ADAPTER *pAd) +{ + //UINT32 BusyTime; + + /* Allocate structure memory */ + AutoChBssTableInit(pAd); + ChannelInfoInit(pAd); + + /* reset bss table */ + AutoChBssTableReset(pAd); + + /* clear Channel Info */ + ChannelInfoReset(pAd); + + /* init pAd->pChannelInfo->IsABand */ + CheckPhyModeIsABand(pAd); +#ifdef ACS_CTCC_SUPPORT + BuildAcsScanChList(pAd); +#endif + pAd->ApCfg.current_channel_index = 0; + + /* read clear for primary channel */ + /*BusyTime =*/ AsicGetChBusyCnt(pAd, 0); +} + +#ifdef AP_SCAN_SUPPORT +/* + ========================================================================== + Description: + trigger Auto Channel Selection every period of ACSCheckTime. + + NOTE: + This function is called in a 1-sec mlme periodic check. + ========================================================================== + */ +VOID AutoChannelSelCheck(RTMP_ADAPTER *pAd) +{ + /* Do nothing if ACSCheckTime is not configured or AP is doing site survey */ + if (pAd->ApCfg.ACSCheckTime == 0 || ApScanRunning(pAd)) + return; + else + pAd->ApCfg.ACSCheckCount++; + + if (pAd->ApCfg.ACSCheckCount >= pAd->ApCfg.ACSCheckTime) + { + /* Reset Counter */ + pAd->ApCfg.ACSCheckCount = 0; + + /* Do Auto Channel Selection only when no client is associated */ + if (pAd->MacTab.Size != 0) + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): ignore Channel Selection checking because has %u associated clients\n", + __FUNCTION__, pAd->MacTab.Size)); + return; + } + else + { + /* Do Auto Channel Selection */ + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): Scanning channels for channel selection.\n", __FUNCTION__)); + ApSiteSurvey(pAd, NULL, SCAN_PASSIVE, TRUE, NULL); + } + } + +} +#endif /* AP_SCAN_SUPPORT */ + + +/* + ========================================================================== + Description: + This routine is called at initialization. It returns a channel number + that complies to regulation domain and less interference with current + enviornment. + Return: + ch - channel number that + NOTE: + The retruned channel number is guaranteed to comply to current regulation + domain that recorded in pAd->CommonCfg.CountryRegion + Usage: + 1.) iwpriv ra0 set AutoChannelSel=1 + Ues the number of AP and inference status to choose + 2.) iwpriv ra0 set AutoChannelSel=2 + Ues the False CCA count and Rssi to choose + ========================================================================== + */ +UCHAR APAutoSelectChannel(RTMP_ADAPTER *pAd, ChannelSel_Alg Alg) +{ + UCHAR ch = 0, i; + //UINT32 BusyTime; + /* passive scan channel 1-14. collect statistics */ + + /* + In the autochannel select case. AP didn't get channel yet. + So have no way to determine which Band AP used by channel number. + */ + + /* Init some structures before doing AutoChannelSelect() */ + APAutoChannelInit(pAd); + + if (( Alg == ChannelAlgRandom ) && (pAd->pChannelInfo->IsABand == TRUE)) + { /*for Dfs */ + ch = SelectClearChannelRandom(pAd); + } + else + { + +#ifdef MICROWAVE_OVEN_SUPPORT + pAd->CommonCfg.MO_Cfg.bEnable = FALSE; + AsicMeasureFalseCCA(pAd); +#endif /* MICROWAVE_OVEN_SUPPORT */ + + /*find RSSI in each channel */ + for (i=0; iChannelListNum; i++) + { + ULONG wait_time = 200; /* wait for 200 ms at each channel. */ + + AsicSwitchChannel(pAd, pAd->ChannelList[i].Channel, TRUE); + AsicLockChannel(pAd, pAd->ChannelList[i].Channel);/*do nothing */ + pAd->ApCfg.current_channel_index = i; + + pAd->ApCfg.AutoChannel_Channel = pAd->ChannelList[i].Channel; + + /* Read-Clear reset Channel busy time counter */ + /*BusyTime =*/ AsicGetChBusyCnt(pAd, 0); +#ifdef AP_QLOAD_SUPPORT + /* QLOAD ALARM, ever alarm from QLOAD module */ + if (QLOAD_DOES_ALARM_OCCUR(pAd)) + wait_time = 400; +#endif /* AP_QLOAD_SUPPORT */ + OS_WAIT(wait_time); + + UpdateChannelInfo(pAd, i,Alg); + } + + ch = SelectBestChannel(pAd, Alg); + } + + return ch; +} diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_band_steering.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_band_steering.c new file mode 100644 index 000000000..4412fa15f --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_band_steering.c @@ -0,0 +1,2065 @@ +/* + *************************************************************************** + * 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" + +#define BNDSTRG_DRIVER_VER "3.1.3" +#define ONE_SEC_2_US 0xF4240 + +extern UCHAR get_regulatory_class(PRTMP_ADAPTER pAd, UCHAR Channel); + +static inline PBND_STRG_CLI_TABLE Get_BndStrgTableByBand( + PRTMP_ADAPTER pAd, + UINT8 Band) +{ + PBND_STRG_CLI_TABLE table = NULL; + INT i; + + for (i = 0; i < DBDC_BAND_NUM; i++) { + table = P_BND_STRG_TABLE(i); + + if (table->bInitialized && (table->Band == Band)) + return table; + } + + return NULL; +} + +inline PBND_STRG_CLI_TABLE Get_BndStrgTable( + PRTMP_ADAPTER pAd, + INT apidx) +{ + BSS_STRUCT *pMbss = NULL; + UINT8 Band; + + if (apidx < HW_BEACON_MAX_NUM) + pMbss = &pAd->ApCfg.MBSSID[apidx]; + + if (pMbss) { + Band = WMODE_CAP_5G(pMbss->wdev.PhyMode)?BAND_5G : BAND_24G; + return Get_BndStrgTableByBand(pAd, Band); + } + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, (RED("%s:(%d):invalid pMbss. apidx=%d\n"), __func__, __LINE__, apidx)); + return NULL; +} + +/* WPS_BandSteering Support */ +PWPS_WHITELIST_ENTRY FindWpsWhiteListEntry( + PLIST_HEADER pWpsWhiteList, + PUCHAR pMacAddr) +{ + PWPS_WHITELIST_ENTRY pWpsWhiteListEntry = NULL; + RT_LIST_ENTRY *pListEntry = NULL; + + pListEntry = pWpsWhiteList->pHead; + pWpsWhiteListEntry = (PWPS_WHITELIST_ENTRY)pListEntry; + while (pWpsWhiteListEntry != NULL) { + + if (NdisEqualMemory(pWpsWhiteListEntry->addr, pMacAddr, MAC_ADDR_LEN)) + return pWpsWhiteListEntry; + pListEntry = pListEntry->pNext; + pWpsWhiteListEntry = (PWPS_WHITELIST_ENTRY)pListEntry; + } + + return NULL; +} + +VOID AddWpsWhiteList( + PLIST_HEADER pWpsWhiteList, + PUCHAR pMacAddr) +{ + PWPS_WHITELIST_ENTRY pWpsWhiteListEntry = NULL; + + pWpsWhiteListEntry = FindWpsWhiteListEntry(pWpsWhiteList, pMacAddr); + + if (pWpsWhiteListEntry) { + /* the Entry already exist */ + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s: Found %02x:%02x:%02x:%02x:%02x:%02x in Wps White List\n", + __func__, PRINT_MAC(pMacAddr))); + } else { + /* Add new Entry */ + os_alloc_mem(NULL, (UCHAR **)&pWpsWhiteListEntry, sizeof(WPS_WHITELIST_ENTRY)); + if (pWpsWhiteListEntry) { + NdisZeroMemory(pWpsWhiteListEntry, sizeof(WPS_WHITELIST_ENTRY)); + pWpsWhiteListEntry->pNext = NULL; + NdisCopyMemory(pWpsWhiteListEntry->addr, pMacAddr, MAC_ADDR_LEN); + insertTailList(pWpsWhiteList, (RT_LIST_ENTRY *)pWpsWhiteListEntry); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("[%s]%02x:%02x:%02x:%02x:%02x:%02x added to WpsList:size::%d\n", + __func__, PRINT_MAC(pWpsWhiteListEntry->addr), pWpsWhiteList->size)); + } else + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("[%s] Mem alloc fail\n", __func__)); + } +} + +VOID DelWpsWhiteListExceptMac( + PLIST_HEADER pWpsWhiteList, + PUCHAR pMacAddr) +{ + + RT_LIST_ENTRY *pListEntry = NULL, *pDelEntry = NULL; + PWPS_WHITELIST_ENTRY pWpsWhiteListEntry = NULL; + PLIST_HEADER pListHeader = pWpsWhiteList; + UCHAR Addr[6]; + + NdisCopyMemory(Addr, pMacAddr, MAC_ADDR_LEN); + + if (pListHeader->size == 0) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("%s: WpsWhiteList Empty.\n", __func__)); + return; + } + + pListEntry = pListHeader->pHead; + pWpsWhiteListEntry = (PWPS_WHITELIST_ENTRY)pListEntry; + + while (pWpsWhiteListEntry != NULL) { + + if (MAC_ADDR_EQUAL(pWpsWhiteListEntry->addr, Addr)) { + pListEntry = pListEntry->pNext; + } else { + pDelEntry = delEntryList(pWpsWhiteList, pListEntry); + pListEntry = pDelEntry->pNext; + os_free_mem(NULL, pDelEntry); + } + pWpsWhiteListEntry = (PWPS_WHITELIST_ENTRY)pListEntry; + } + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("%s: WpsWhiteList size : %d\n", + __func__, pWpsWhiteList->size)); +} + +VOID ClearWpsWhiteList( + PLIST_HEADER pWpsWhiteList) +{ + RT_LIST_ENTRY *pListEntry = NULL; + PLIST_HEADER pListHeader = pWpsWhiteList; + + if (pListHeader->size == 0) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("%s: WpsWhiteList already Empty.\n", __func__)); + return; + } + + pListEntry = pListHeader->pHead; + while (pListEntry != NULL) { + /*Remove ListEntry from Header*/ + removeHeadList(pListHeader); + os_free_mem(NULL, pListEntry); + pListEntry = pListHeader->pHead; + } + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("%s: Clean WpsWhiteList.\n", __func__)); +} + +PBS_LIST_ENTRY FindBsListEntry( + PLIST_HEADER pBsList, + PUCHAR pMacAddr) +{ + PBS_LIST_ENTRY pBsListEntry = NULL; + RT_LIST_ENTRY *pListEntry = NULL; + + pListEntry = pBsList->pHead; + pBsListEntry = (PBS_LIST_ENTRY)pListEntry; + while (pBsListEntry != NULL) { + + if (NdisEqualMemory(pBsListEntry->addr, pMacAddr, MAC_ADDR_LEN)) + return pBsListEntry; + pListEntry = pListEntry->pNext; + pBsListEntry = (PBS_LIST_ENTRY)pListEntry; + } + + return NULL; +} + +VOID AddBsListEntry( + PLIST_HEADER pBsList, + PUCHAR pMacAddr) +{ + PBS_LIST_ENTRY pBsListEntry = NULL; + + pBsListEntry = FindBsListEntry(pBsList, pMacAddr); + + if (pBsListEntry) { + /* the Entry already exist */ + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s: Found %02x:%02x:%02x:%02x:%02x:%02x in BsList.\n", + __func__, PRINT_MAC(pMacAddr))); + } else { + /* Add new Entry */ + os_alloc_mem(NULL, (UCHAR **)&pBsListEntry, sizeof(BS_LIST_ENTRY)); + if (pBsListEntry) { + NdisZeroMemory(pBsListEntry, sizeof(BS_LIST_ENTRY)); + pBsListEntry->pNext = NULL; + NdisCopyMemory(pBsListEntry->addr, pMacAddr, MAC_ADDR_LEN); + insertTailList(pBsList, (RT_LIST_ENTRY *)pBsListEntry); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("[%s] %02x:%02x:%02x:%02x:%02x:%02x added in BsList:size::%d\n", + __func__, PRINT_MAC(pBsListEntry->addr), pBsList->size)); + } else + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("[%s]Mem alloc fail\n", __func__)); + } +} + +VOID DelBsListEntry( + PLIST_HEADER pBsList, + PUCHAR pMacAddr) +{ + PBS_LIST_ENTRY pBsListEntry = NULL; + RT_LIST_ENTRY *pListEntry = NULL, *pDelEntry = NULL; + + pBsListEntry = FindBsListEntry(pBsList, pMacAddr); + + if (!pBsListEntry) { + /* the Entry already exist */ + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("%s: Not Found %02x:%02x:%02x:%02x:%02x:%02x in BsList.\n", + __func__, PRINT_MAC(pMacAddr))); + } else { + pListEntry = (RT_LIST_ENTRY *)pBsListEntry; + /* Delete the Entry */ + pDelEntry = delEntryList(pBsList, pListEntry); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("%s: Sta %02x:%02x:%02x:%02x:%02x:%02x deleted from BsList:size::%d\n", + __func__, PRINT_MAC(pBsListEntry->addr), pBsList->size)); + os_free_mem(NULL, pDelEntry); + } +} + +VOID ClearBsList( + PLIST_HEADER pBsList) +{ + RT_LIST_ENTRY *pListEntry = NULL; + PLIST_HEADER pListHeader = pBsList; + + if (pListHeader->size == 0) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("%s: BsList already Empty.\n", __func__)); + return; + } + + pListEntry = pListHeader->pHead; + while (pListEntry != NULL) { + /*Remove ListEntry from Header*/ + removeHeadList(pListHeader); + os_free_mem(NULL, pListEntry); + pListEntry = pListHeader->pHead; + } + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("%s: Clean BsList.\n", __func__)); +} + +INT Show_BndStrg_Info( + PRTMP_ADAPTER pAd, + RTMP_STRING *arg) +{ + PBND_STRG_CLI_TABLE table; + POS_COOKIE pObj; + UCHAR ifIndex; + struct wifi_dev *wdev = NULL; + BNDSTRG_MSG msg = { 0 }; + UINT8 idx = 0; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + if (ifIndex >= HW_BEACON_MAX_NUM) + return FALSE; + + wdev = &pAd->ApCfg.MBSSID[ifIndex].wdev; + + if (!pAd->ApCfg.BndStrgBssIdx[wdev->func_idx]) + return TRUE; + + table = Get_BndStrgTable(pAd, ifIndex); + + if (!table) + return FALSE; + + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("Band Steering Driver Ver - %s\n", BNDSTRG_DRIVER_VER)); + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("\t BndStrgBssIdx")); + + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, (":%d", pAd->ApCfg.BndStrgBssIdx[idx])); + + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("\n")); + + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("\t WhiteListSize:%d\n", table->WhiteList.size)); + + if (table->WhiteList.size) { + PBS_LIST_ENTRY pBsListEntry = NULL; + RT_LIST_ENTRY *pListEntry = NULL; + + pListEntry = table->WhiteList.pHead; + pBsListEntry = (PBS_LIST_ENTRY)pListEntry; + + while (pBsListEntry != NULL) { + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("\t -> %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pBsListEntry->addr))); + pListEntry = pListEntry->pNext; + pBsListEntry = (PBS_LIST_ENTRY)pListEntry; + } + } + + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("\t BlackListSize:%d\n", table->BlackList.size)); + + if (table->BlackList.size) { + PBS_LIST_ENTRY pBsListEntry = NULL; + RT_LIST_ENTRY *pListEntry = NULL; + + pListEntry = table->BlackList.pHead; + pBsListEntry = (PBS_LIST_ENTRY)pListEntry; + + while (pBsListEntry != NULL) { + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("\t -> %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pBsListEntry->addr))); + pListEntry = pListEntry->pNext; + pBsListEntry = (PBS_LIST_ENTRY)pListEntry; + } + } + + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("\n")); + msg.Action = TABLE_INFO; + BndStrgSendMsg(pAd, &msg); + return TRUE; +} + +INT Show_BndStrg_List( + PRTMP_ADAPTER pAd, + RTMP_STRING *arg) +{ + PBND_STRG_CLI_TABLE table; + POS_COOKIE pObj; + UCHAR ifIndex; + UINT32 display_type; + BNDSTRG_MSG msg = { 0 }; + CHAR band_str[4][10] = {"", "5G", "2.4G", "2.4G/5G"}; + INT i; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + table = Get_BndStrgTable(pAd, ifIndex); + + if (!table) + return FALSE; + + if (arg == NULL) + display_type = 0; + else + display_type = (UINT32) simple_strtol(arg, 0, 10); + + if (display_type > 3) + display_type = 0; + + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("\t%s Accessible Clients: %d\n", band_str[table->Band], table->Size)); + + for (i = 0; i < BND_STRG_MAX_TABLE_SIZE; i++) { + if (table->Entry[i].bValid) { + if (MAC_ADDR_EQUAL(table->MonitorAddr, table->Entry[i].Addr)) { + BND_STRG_PRINTQAMSG(table, table->Entry[i].Addr, + (YLW("\t%d: %02x:%02x:%02x:%02x:%02x:%02x [TblIdx:%d]\n"), + i, PRINT_MAC(table->Entry[i].Addr), table->Entry[i].TableIndex)); + } else { + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("\t%d: %02x:%02x:%02x:%02x:%02x:%02x [TblIdx:%d]\n", + i, PRINT_MAC(table->Entry[i].Addr), table->Entry[i].TableIndex)); + } + } + } + + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("\tBndStrg Table Entries:\n")); + msg.Action = ENTRY_LIST; + msg.data.display_type.display_type = display_type; + msg.data.display_type.filer_band = table->Band; + msg.data.display_type.channel = table->Channel; + BndStrgSendMsg(pAd, &msg); + + return TRUE; +} + +INT Set_BndStrg_Enable( + PRTMP_ADAPTER pAd, + RTMP_STRING *arg) +{ + PBND_STRG_CLI_TABLE table; + POS_COOKIE pObj; + UCHAR ifIndex; + BOOLEAN enable; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + enable = (BOOLEAN) simple_strtol(arg, 0, 10); + + if (!(enable ^ pAd->ApCfg.BandSteering)) { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, (GRN("BndStrg is already %s\n"), pAd->ApCfg.BandSteering?"Enable":"Disable")); + return TRUE; + } + + if (enable) { + BSS_STRUCT *pMbss = NULL; + INT apidx, IdBss; + + apidx = ifIndex; + + if (apidx < HW_BEACON_MAX_NUM) + pMbss = &pAd->ApCfg.MBSSID[apidx]; + + if (pMbss == NULL) { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, (RED("%s:(%d):invalid pMbss. apidx=%d\n"), __func__, __LINE__, apidx)); + return FALSE; + } + + /* bnstrg table does not init yet, call BndStrg_Init directly */ + BndStrg_Init(pAd); + + /* enable all active mbss BndStrg InfFlags to nitify daemon */ + for (IdBss = 0; IdBss < pAd->ApCfg.BssidNum; IdBss++) { + pMbss = &pAd->ApCfg.MBSSID[IdBss]; + table = Get_BndStrgTable(pAd, IdBss); + + if (table) { + /* Inform daemon interface ready */ + BndStrg_SetInfFlags(pAd, &pMbss->wdev, table, TRUE); + } + } + + pAd->ApCfg.BandSteering = enable; + } else { + BndStrg_Release(pAd); + pAd->ApCfg.BandSteering = enable; + } + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, (GRN("BndStrg %s Success\n"), pAd->ApCfg.BandSteering?"Enable":"Disable")); + return TRUE; +} + +INT Set_BndStrg_Param(PRTMP_ADAPTER pAd, RTMP_STRING *arg) +{ + PBND_STRG_CLI_TABLE table; + POS_COOKIE pObj; + UCHAR ifIndex; + BNDSTRG_MSG msg = { 0 }; + struct bnd_msg_param *bndstrg_param = &msg.data.bndstrg_param; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + if (ifIndex > HW_BEACON_MAX_NUM) + return FALSE; + + table = Get_BndStrgTable(pAd, ifIndex); + + if (!table) + return FALSE; + + msg.Action = BNDSTRG_PARAM; + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s(): BndStrg param = %s\n", __func__, arg)); + + bndstrg_param->Band = table->Band; + bndstrg_param->Channel = table->Channel; + bndstrg_param->len = strlen(arg); + strncpy(bndstrg_param->arg, arg, sizeof(bndstrg_param->arg)); + BndStrgSendMsg(pAd, &msg); + + return TRUE; +} + +#ifdef BND_STRG_DBG +INT Set_BndStrg_MonitorAddr( + PRTMP_ADAPTER pAd, + RTMP_STRING *arg) +{ + UCHAR MonitorAddr[MAC_ADDR_LEN]; + RTMP_STRING *value; + INT i; + PBND_STRG_CLI_TABLE table; + POS_COOKIE pObj; + UCHAR ifIndex; + BNDSTRG_MSG msg = { 0 }; + struct bnd_msg_mnt_addr *mnt_addr = &msg.data.mnt_addr; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + table = Get_BndStrgTable(pAd, ifIndex); + + if (!table) + return FALSE; + + 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); + } + + COPY_MAC_ADDR(table->MonitorAddr, MonitorAddr); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s(): %02x:%02x:%02x:%02x:%02x:%02x\n", + __func__, PRINT_MAC(table->MonitorAddr))); + msg.Action = SET_MNT_ADDR; + COPY_MAC_ADDR(mnt_addr->Addr, table->MonitorAddr); + BndStrgSendMsg(pAd, &msg); + + return TRUE; +} +#endif /* BND_STRG_DBG */ + +INT BndStrg_Init(PRTMP_ADAPTER pAd) +{ + INT ret_val = BND_STRG_SUCCESS; + INT max_mbss_check_num; + INT apidx; + + max_mbss_check_num = pAd->ApCfg.BssidNum; + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, (YLW("%s()\n"), __func__)); + + for (apidx = 0; apidx < max_mbss_check_num; apidx++) { + ret_val = BndStrg_TableInit(pAd, apidx); + + if (ret_val != BND_STRG_SUCCESS) { + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("Error in %s(), error code = %d on apidx = %d\n", + __func__, ret_val, apidx)); + } + } + EnableRadioChstats(pAd); //configure register for channel busy time + return ret_val; +} + +#ifdef DOT11K_RRM_SUPPORT +VOID BndStrg_InsertNeighborRepIE(PRTMP_ADAPTER pAd, PBND_STRG_CLI_TABLE init_table) +{ + RRM_NEIGHBOR_REP_INFO NeighborRepInfo = { {0} }; + BSS_STRUCT *pMbss = NULL; + RRM_BSSID_INFO BssidInfo; + UINT8 CondensedPhyType = 0; /* 7:2G,9:5G */ + + pMbss = &pAd->ApCfg.MBSSID[BSS0]; + COPY_MAC_ADDR(NeighborRepInfo.Bssid, pMbss->wdev.bssid); + CondensedPhyType = (pAd->CommonCfg.Channel > 14)?9:7; /* 7:2G,9:5G */ + /* our own info */ + BssidInfo.word = 0; + BssidInfo.field.APReachAble = 3; + BssidInfo.field.Security = 1; /* rrm to do. */ + BssidInfo.field.KeyScope = 1; /* "report AP has same authenticator as the AP. */ + BssidInfo.field.SepctrumMng = (pMbss->CapabilityInfo & (1 << 8))?1:0; + BssidInfo.field.Qos = (pMbss->CapabilityInfo & (1 << 9))?1:0; + BssidInfo.field.APSD = (pMbss->CapabilityInfo & (1 << 11))?1:0; + BssidInfo.field.RRM = (pMbss->CapabilityInfo & RRM_CAP_BIT)?1:0; + BssidInfo.field.DelayBlockAck = (pMbss->CapabilityInfo & (1 << 14))?1:0; + BssidInfo.field.ImmediateBA = (pMbss->CapabilityInfo & (1 << 15))?1:0; + + NeighborRepInfo.BssidInfo = BssidInfo.word; + NeighborRepInfo.RegulatoryClass = get_regulatory_class(pAd, 0); + NeighborRepInfo.ChNum = pAd->CommonCfg.Channel; + NeighborRepInfo.PhyType = CondensedPhyType; + + NdisCopyMemory(&init_table->NeighborRepInfo, &NeighborRepInfo, sizeof(RRM_NEIGHBOR_REP_INFO)); +} +#endif + +INT BndStrg_TableInit(PRTMP_ADAPTER pAd, INT apidx) +{ + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; + PBND_STRG_CLI_TABLE table = NULL, init_table = NULL; + INT i; + UINT8 Band; + + if (pMbss) + Band = WMODE_CAP_5G(pMbss->wdev.PhyMode)?BAND_5G : BAND_24G; + else { + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("Error in %s(), pMbss is NULL!\n", __func__)); + return BND_STRG_UNEXP; + } + + for (i = 0; i < DBDC_BAND_NUM; i++) { + table = P_BND_STRG_TABLE(i); + + if (!table->bInitialized && !init_table) { + init_table = table; + continue; + } + + if (table->bInitialized && (table->Band == Band)) + return BND_STRG_SUCCESS; + } + + if (init_table) { + NdisZeroMemory(init_table, sizeof(BND_STRG_CLI_TABLE)); + OS_NdisAllocateSpinLock(&init_table->Lock); +/* WPS_BandSteering Support */ + OS_NdisAllocateSpinLock(&init_table->WpsWhiteListLock); + OS_NdisAllocateSpinLock(&init_table->WhiteListLock); + OS_NdisAllocateSpinLock(&init_table->BlackListLock); + + init_table->DaemonPid = 0xffffffff; + init_table->priv = (VOID *) pAd; + init_table->Band = Band; + init_table->bInitialized = TRUE; +#ifdef DOT11K_RRM_SUPPORT + BndStrg_InsertNeighborRepIE(pAd, init_table); +#endif + } + return BND_STRG_SUCCESS; +} + +INT BndStrg_Release(PRTMP_ADAPTER pAd) +{ + INT ret_val = BND_STRG_SUCCESS; + INT apidx; + PBND_STRG_CLI_TABLE table = NULL; + BSS_STRUCT *pMbss = NULL; + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, (YLW("%s()\n"), __func__)); + + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) { + table = Get_BndStrgTable(pAd, apidx); + + if (table) { + pMbss = &pAd->ApCfg.MBSSID[apidx]; + BndStrg_SetInfFlags(pAd, &pMbss->wdev, table, FALSE); + } + } + + if (table) + BndStrg_TableRelease(table); + + return ret_val; +} + +INT BndStrg_TableRelease(PBND_STRG_CLI_TABLE table) +{ + INT ret_val = BND_STRG_SUCCESS; + + if (table->bInitialized == FALSE) + return BND_STRG_NOT_INITIALIZED; + + OS_NdisFreeSpinLock(&table->Lock); + + NdisAcquireSpinLock(&table->WhiteListLock); + ClearBsList(&table->WhiteList); + NdisReleaseSpinLock(&table->WhiteListLock); + + NdisAcquireSpinLock(&table->BlackListLock); + ClearBsList(&table->BlackList); + NdisReleaseSpinLock(&table->BlackListLock); + + NdisAcquireSpinLock(&table->WpsWhiteListLock); + ClearWpsWhiteList(&table->WpsWhiteList); + NdisReleaseSpinLock(&table->WpsWhiteListLock); + + OS_NdisFreeSpinLock(&table->WpsWhiteListLock); + OS_NdisFreeSpinLock(&table->WhiteListLock); + OS_NdisFreeSpinLock(&table->BlackListLock); + table->bInitialized = FALSE; + + if (ret_val != BND_STRG_SUCCESS) { + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("Error in %s(), error code = %d!\n", __func__, ret_val)); + } + return ret_val; +} + +INT BndStrg_InsertEntry( + PBND_STRG_CLI_TABLE table, + struct bnd_msg_cli_add *cli_add, + 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) { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_WARN, ("%s(): Table is full!\n", __func__)); + 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, cli_add->Addr); + entry->TableIndex = cli_add->TableIndex; + entry->BndStrg_Sta_State = BNDSTRG_STA_INIT; + entry->bValid = TRUE; + break; + } + + entry = NULL; + } + + if (entry) { + /* add this MAC entry into HASH table */ + HashIdx = MAC_ADDR_HASH_INDEX(cli_add->Addr); + + 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); + + if (Index >= BND_STRG_MAX_TABLE_SIZE) { + if (pAddr == NULL) + return BND_STRG_INVALID_ARG; + + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + 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_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_INFO, + ("%s(): Index=%u, %02x:%02x:%02x:%02x:%02x:%02x, Entry not found.\n", + __func__, Index, PRINT_MAC(pAddr))); + NdisReleaseSpinLock(&table->Lock); + return BND_STRG_INVALID_ARG; + } + } else { + entry = &table->Entry[Index]; + HashIdx = MAC_ADDR_HASH_INDEX(entry->Addr); + } + + if (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--; + } + } else { + } + + NdisReleaseSpinLock(&table->Lock); + + return ret_val; +} + + +PBND_STRG_CLI_ENTRY BndStrg_TableLookup(PBND_STRG_CLI_TABLE table, PUCHAR pAddr) +{ + ULONG HashIdx; + BND_STRG_CLI_ENTRY *entry = NULL; + + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + entry = table->Hash[HashIdx]; + + while (entry && entry->bValid) { + if (MAC_ADDR_EQUAL(entry->Addr, pAddr)) + break; + else + entry = entry->pNext; + } + + return entry; +} + +BOOLEAN BndStrg_CheckConnectionReq( + PRTMP_ADAPTER pAd, + struct wifi_dev *wdev, + PUCHAR pSrcAddr, + MLME_QUEUE_ELEM * Elem, + PEER_PROBE_REQ_PARAM * ProbeReqParam) +{ + UINT8 FrameType = Elem->MsgType; + CHAR Rssi[4] = {0}; + PBND_STRG_CLI_TABLE table = Get_BndStrgTable(pAd, wdev->func_idx); + BNDSTRG_MSG msg = { 0 }; + struct bnd_msg_cli_event *cli_event = &msg.data.cli_event; + CHAR i, rssi_max; + PBND_STRG_CLI_ENTRY entry = NULL; + + if (!pAd->ApCfg.BndStrgBssIdx[wdev->func_idx]) + return TRUE; + + if (!table || !table->bEnabled) + return TRUE; + + /* send response to white listed clients*/ + if (table->WhiteList.size > 0) { + + PBS_LIST_ENTRY bs_whitelist_entry = NULL; + + bs_whitelist_entry = FindBsListEntry(&table->WhiteList, pSrcAddr); + + if (bs_whitelist_entry) { + BND_STRG_PRINTQAMSG(table, pSrcAddr, ("BndStrg STA %02x:%02x:%02x:%02x:%02x:%02x whitelisted\n", PRINT_MAC(pSrcAddr))); + return TRUE; + } + } + + Rssi[0] = Elem->rssi_info.raw_rssi[0] ? ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_0) : 0; + Rssi[1] = Elem->rssi_info.raw_rssi[1] ? ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_1) : 0; + Rssi[2] = Elem->rssi_info.raw_rssi[2] ? ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_2) : 0; + //Rssi[3] = Elem->rssi_info.raw_rssi[3] ? ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_3) : 0; + +#ifdef DBDC_MODE + + if (pAd->CommonCfg.dbdc_mode) { + UCHAR band_idx = HcGetBandByWdev(wdev); + + if (band_idx == DBDC_BAND0) + rssi_max = pAd->dbdc_2G_rx_stream; + else + rssi_max = pAd->dbdc_5G_rx_stream; + } else +#endif + rssi_max = pAd->Antenna.field.RxPath; + + msg.Action = CLI_EVENT; + + if (WMODE_CAP_2G(wdev->PhyMode) && + wdev->channel <= 14) { + cli_event->Band = BAND_24G; + } + + if (WMODE_CAP_5G(wdev->PhyMode) && + wdev->channel > 14) + cli_event->Band = BAND_5G; + + cli_event->Channel = table->Channel; + cli_event->FrameType = FrameType; + + if (FrameType == APMT2_PEER_PROBE_REQ) { + struct bnd_msg_cli_probe *cli_probe = &cli_event->data.cli_probe; + + if (ProbeReqParam->IsHtSupport && WMODE_CAP_N(wdev->PhyMode)) + cli_probe->bAllowStaConnectInHt = TRUE; + if (ProbeReqParam->IsVhtSupport && WMODE_CAP_AC(wdev->PhyMode)) + cli_probe->bVHTCapable = TRUE; + + if (ProbeReqParam->IsFromIos) + cli_probe->bIosCapable = TRUE; + + cli_probe->Nss = GetNssFromHTCapRxMCSBitmask(ProbeReqParam->RxMCSBitmask); + + memset(cli_probe->Rssi, 0x80, sizeof(cli_probe->Rssi)); + for (i = 0; i < rssi_max; i++) + cli_probe->Rssi[i] = Rssi[i]; + } else if (FrameType == APMT2_PEER_AUTH_REQ) { + struct bnd_msg_cli_auth *cli_auth = &cli_event->data.cli_auth; + + memset(cli_auth->Rssi, 0x80, sizeof(cli_auth->Rssi)); + for (i = 0; i < rssi_max; i++) + cli_auth->Rssi[i] = Rssi[i]; + } + COPY_MAC_ADDR(cli_event->Addr, pSrcAddr); + BndStrgSendMsg(pAd, &msg); + + /* check for backlist client, stop response for them */ + if (table->BlackList.size > 0) { + PBS_LIST_ENTRY bs_blacklist_entry = NULL; + + bs_blacklist_entry = FindBsListEntry(&table->BlackList, pSrcAddr); + + if (bs_blacklist_entry) { + BND_STRG_PRINTQAMSG(table, pSrcAddr, ("BndStrg STA %02x:%02x:%02x:%02x:%02x:%02x blacklisted\n", PRINT_MAC(pSrcAddr))); + return FALSE; + } + } + +/* WPS_BandSteering Support */ + { + PWSC_CTRL pWscControl; + + pWscControl = &pAd->ApCfg.MBSSID[wdev->func_idx].WscControl; + + if (FrameType == APMT2_PEER_PROBE_REQ) { + if (pWscControl->bWscTrigger) { + if (ProbeReqParam->bWpsCapable) { + NdisAcquireSpinLock(&table->WpsWhiteListLock); + AddWpsWhiteList(&table->WpsWhiteList, pSrcAddr); + NdisReleaseSpinLock(&table->WpsWhiteListLock); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("channel %u: Probe req: STA %02x:%02x:%02x:%02x:%02x:%02x wps whitelisted\n", + table->Channel, PRINT_MAC(pSrcAddr))); + BND_STRG_PRINTQAMSG(table, pSrcAddr, ("STA %02x:%02x:%02x:%02x:%02x:%02x channel %u added in WPS Whitelist\n", + PRINT_MAC(pSrcAddr), table->Channel)); + } + return TRUE; + } + } + + if (FrameType == APMT2_PEER_AUTH_REQ) { + if (pWscControl->bWscTrigger) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("channel %u: Auth req: STA %02x:%02x:%02x:%02x:%02x:%02x wps whitelisted\n", + table->Channel, PRINT_MAC(pSrcAddr))); + BND_STRG_PRINTQAMSG(table, pSrcAddr, ("STA %02x:%02x:%02x:%02x:%02x:%02x channel %u allowed Auth as per WPS Whitelist\n", + PRINT_MAC(pSrcAddr), table->Channel)); + return TRUE; + } + } + } + + if (table->BndStrgMode == POST_CONNECTION_STEERING) + return TRUE; + + entry = BndStrg_TableLookup(table, pSrcAddr); + + if (entry && (FrameType == APMT2_PEER_AUTH_REQ) && (entry->BndStrg_Sta_State == BNDSTRG_STA_ASSOC)) { + BND_STRG_PRINTQAMSG(table, pSrcAddr, + (RED("%s: (ch%d) check %s request failed. client's (%02x:%02x:%02x:%02x:%02x:%02x) request is ignored. Client disconnected without DeAuth.!!Waiting for bndstrg result!!\n" + ), (table->Band == BAND_24G ? "2.4G" : "5G"), table->Channel, "Auth", PRINT_MAC(pSrcAddr))); + return FALSE; + } + + if (entry) { +#ifdef BND_STRG_QA + BND_STRG_PRINTQAMSG(table, pSrcAddr, + (GRN("%s: (ch%d) check %s request ok. client's (%02x:%02x:%02x:%02x:%02x:%02x) request is accepted.\n" + ), (table->Band == BAND_24G ? "2.4G" : "5G"), table->Channel, + FrameType == 0 ? ("probe") : (FrameType == 3 ? "auth" : "unknow"), PRINT_MAC(pSrcAddr))); +#endif + return TRUE; + } else { +#ifdef BND_STRG_QA + BND_STRG_PRINTQAMSG(table, pSrcAddr, + (RED("%s: (ch%d) check %s request failed. client's (%02x:%02x:%02x:%02x:%02x:%02x) request is ignored.\n" + ), (table->Band == BAND_24G ? "2.4G" : "5G"), table->Channel, + FrameType == 0 ? ("probe") : (FrameType == 3 ? "auth" : "unknow"), PRINT_MAC(pSrcAddr))); +#endif + return FALSE; + } + return TRUE; +} + +INT BndStrg_Tbl_Enable(PBND_STRG_CLI_TABLE table, BOOLEAN enable, CHAR *IfName) +{ + BNDSTRG_MSG msg = { 0 }; + PRTMP_ADAPTER pAd = NULL; + struct bnd_msg_onoff *onoff = &msg.data.onoff; + + 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_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, /* TRACE */ + (GRN("%s(): Band steering is already %s.\n"), + __func__, (enable ? "enabled" : "disabled"))); + return BND_STRG_SUCCESS; + } + + if (enable) { + table->bEnabled = TRUE; + strncpy(table->ucIfName, IfName, sizeof(table->ucIfName)); /* decide it by daemon */ + } else + table->bEnabled = FALSE; + + pAd = (PRTMP_ADAPTER) table->priv; + msg.Action = BNDSTRG_ONOFF; + onoff->OnOff = table->bEnabled; + onoff->Band = table->Band; + onoff->Channel = table->Channel; + strncpy(onoff->ucIfName, IfName, sizeof(onoff->ucIfName)); + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_BNDSTRG_MSG, + NULL, + (UCHAR *)&msg, + sizeof(msg)); + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + (GRN("%s(): Band steering %s running.\n"), + __func__, (enable ? "start" : "stop"))); + return BND_STRG_SUCCESS; +} + +INT 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)); +} + +INT BndStrg_SetInfFlags( + PRTMP_ADAPTER pAd, + struct wifi_dev *wdev, + PBND_STRG_CLI_TABLE table, + BOOLEAN bInfReady) +{ + INT ret_val = BND_STRG_SUCCESS; + UINT8 Band; + BNDSTRG_MSG msg = { 0 }; + struct bnd_msg_inf_status_rsp *inf_status_rsp = &msg.data.inf_status_rsp; + + if (!wdev) { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("%s(): wdev is NULL!\n", __func__)); + return BND_STRG_UNEXP; + } + + if (!wdev->if_dev) { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("%s(): if_dev is NULL!\n", __func__)); + return BND_STRG_UNEXP; + } + + Band = WMODE_CAP_5G(wdev->PhyMode)?BAND_5G : BAND_24G; + + if (!(wdev->bInfReady^bInfReady)) { + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + (GRN("%s(): %s Inf %s Band steering is already %s.\n"), __func__, + (IS_5G_BAND(Band) ? "5G" : "2G"), wdev->if_dev->name, + (bInfReady ? "up" : "down"))); + return BND_STRG_SUCCESS; + } + + wdev->bInfReady = bInfReady; + + if (bInfReady) { /* Exec. by each interface up */ + table->uIdx = wdev->func_idx; + table->Channel = pAd->CommonCfg.Channel; + + if (WMODE_CAP_5G(wdev->PhyMode) && WMODE_CAP_AC(wdev->PhyMode)) + table->bVHTCapable = TRUE; + else + table->bVHTCapable = FALSE; + + table->ActiveCount++; + } else { /* Exec. by each interface down */ + if (table->ActiveCount > 0) + table->ActiveCount--; + } + + table->nss = pAd->CommonCfg.TxStream; + msg.Action = INF_STATUS_RSP; + + inf_status_rsp->band = Band; + inf_status_rsp->bInfReady = bInfReady; + inf_status_rsp->Channel = table->Channel; + inf_status_rsp->bVHTCapable = table->bVHTCapable; + inf_status_rsp->nss = table->nss; + inf_status_rsp->table_src_addr = (ULONG)table; + inf_status_rsp->table_size = BND_STRG_MAX_TABLE_SIZE; + strncpy(inf_status_rsp->ucIfName, wdev->if_dev->name, sizeof(inf_status_rsp->ucIfName)); +#ifdef VENDOR_FEATURE5_SUPPORT + inf_status_rsp->nvram_support = 1; +#else + inf_status_rsp->nvram_support = 0; +#endif + BndStrgSendMsg(pAd, &msg); + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + (BLUE("%s(): BSS(%02X:%02X:%02X:%02X:%02X:%02X)") + BLUE(" set %s Inf %s %s.\n"), __func__, + PRINT_MAC(wdev->bssid), IS_5G_BAND(Band) ? "5G" : "2G", + wdev->if_dev->name, bInfReady ? "ready" : "not ready")); + + if (table->bInfReady ^ bInfReady) { + if (bInfReady) { + table->bInfReady = TRUE; + table->Band |= Band; + } else { + if (!bInfReady && (table->ActiveCount == 0)) { + table->bInfReady = FALSE; + + if (table->bEnabled) + BndStrg_Tbl_Enable(table, FALSE, table->ucIfName); + } + } + } + + return ret_val; +} + +void BndStrg_UpdateEntry(PRTMP_ADAPTER pAd, + MAC_TABLE_ENTRY *pEntry, + IE_LISTS *ie_list, + BOOLEAN bConnStatus) +{ + struct wifi_dev *wdev; + BNDSTRG_MSG msg = { 0 }; + struct bnd_msg_cli_event *cli_event = &msg.data.cli_event; + UINT8 Nss = 1; + UINT32 RxMCSBitmask = 0; + PBND_STRG_CLI_ENTRY entry = NULL; + PBND_STRG_CLI_TABLE table = NULL; + + if (!pEntry || !pEntry->wdev || (pAd->ApCfg.BndStrgBssIdx[pEntry->func_tb_idx] != 1)) + return; + + table = Get_BndStrgTable(pAd, pEntry->wdev->func_idx); + + if (!table) + return; + + wdev = pEntry->wdev; + + if (WMODE_CAP_5G(wdev->PhyMode)) + cli_event->Band = BAND_5G; + else + cli_event->Band = BAND_24G; + + cli_event->Channel = table->Channel; + COPY_MAC_ADDR(cli_event->Addr, pEntry->Addr); + msg.Action = CLI_EVENT; + + if (bConnStatus) { + struct bnd_msg_cli_assoc *cli_assoc = &cli_event->data.cli_assoc; + + cli_event->FrameType = APMT2_PEER_ASSOC_REQ; + if (ie_list->ht_cap_len > 0) { + cli_assoc->bAllowStaConnectInHt = TRUE; + RxMCSBitmask = *(UINT32 *)(ie_list->HTCapability.MCSSet); + Nss = GetNssFromHTCapRxMCSBitmask(RxMCSBitmask); + } +#ifdef DOT11_VHT_AC + if (ie_list->vht_cap_len > 0) + cli_assoc->bVHTCapable = TRUE; +#endif + cli_assoc->Nss = Nss; +/* WPS_BandSteering Support */ + cli_assoc->bWpsAssoc = ie_list->bWscCapable; +#ifdef CONFIG_DOT11V_WNM + cli_assoc->BTMSupport = pEntry->BssTransitionManmtSupport; +#endif + } else { + cli_event->FrameType = APMT2_PEER_DISASSOC_REQ; + } + + BndStrgSendMsg(pAd, &msg); + entry = BndStrg_TableLookup(table, pEntry->Addr); + + if (entry) { + if (bConnStatus) + entry->BndStrg_Sta_State = BNDSTRG_STA_ASSOC; + else + entry->BndStrg_Sta_State = BNDSTRG_STA_DISASSOC; + entry->bConnStatus = bConnStatus; + } + return; +} + +INT Set_BndStrg_BssIdx( + PRTMP_ADAPTER pAd, + RTMP_STRING *arg) +{ + UINT8 i; + RTMP_STRING *macptr; + + for (i = 0, macptr = rstrtok(arg, ";"); macptr; macptr = rstrtok(NULL, ";"), i++) { + pAd->ApCfg.BndStrgBssIdx[i] = simple_strtoul(macptr, 0, 10); + } + + return TRUE; +} + +#ifdef VENDOR_FEATURE5_SUPPORT +INT Show_BndStrg_NvramTable( + PRTMP_ADAPTER pAd, + RTMP_STRING *arg) +{ + PBND_STRG_CLI_TABLE table; + POS_COOKIE pObj; + UCHAR ifIndex; + PBNDSTRG_NVRAM_CLIENT table_nvram_client; + int i; + char PhyMode[10]; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + table = Get_BndStrgTable(pAd, ifIndex); + + if (!table) + return FALSE; + + printk("%s bndstrg_nvram_client_count %d\n", __func__, table->bndstrg_nvram_client_count); + printk("Addr Band\tPhymde\t\t\t\tNSS\tManipulable\n"); + + for (i = 0; i < table->bndstrg_nvram_client_count; i++) { + table_nvram_client = &table->nvram_entry[i]; + memset(PhyMode, 0x00, 10); + + if (table_nvram_client->PhyMode == fPhyMode_Legacy) + sprintf(PhyMode, "%s", "Legacy"); + else if (table_nvram_client->PhyMode == fPhyMode_HT) + sprintf(PhyMode, "%s", "11n"); + else if (table_nvram_client->PhyMode == fPhyMode_VHT) + sprintf(PhyMode, "%s", "11ac"); + + printk("%02x:%02x:%02x:%02x:%02x:%02x \t%-3s\t%-20s\t\t%d\t%s\n", PRINT_MAC(table_nvram_client->Addr), + (IS_5G_BAND(table_nvram_client->Band) ? "5G":"2G"), PhyMode, table_nvram_client->Nss, (table_nvram_client->Manipulable ? "YES":"NO")); + } + return TRUE; +} + +static BOOLEAN BndStrg_NvramTableLookup(PBND_STRG_CLI_TABLE table, unsigned char *pAddr) +{ + int i; + + for (i = 0; i < NVRAM_TABLE_SIZE; i++) { + if (MAC_ADDR_EQUAL(table->nvram_entry[i].Addr, pAddr)) + return TRUE; + } + return FALSE; +} + +static BOOLEAN BndStrg_NvramInsertEntry(PBND_STRG_CLI_TABLE table, PBNDSTRG_NVRAM_CLIENT msg) +{ + PBNDSTRG_NVRAM_CLIENT nvram_entry = NULL; + int i = 0; + + if (!BndStrg_NvramTableLookup(table, msg->Addr)) { + if (table->bndstrg_nvram_client_count < NVRAM_TABLE_SIZE) { + nvram_entry = &table->nvram_entry[table->bndstrg_nvram_client_count]; + memset(nvram_entry, 0, sizeof(BNDSTRG_NVRAM_CLIENT)); + memcpy(nvram_entry->Addr, msg->Addr, MAC_ADDR_LEN); + table->bndstrg_nvram_client_count++; + } + } else { + for (i = 0; i < table->bndstrg_nvram_client_count; i++) { + if (MAC_ADDR_EQUAL(table->nvram_entry[i].Addr, msg->Addr)) + break; + } + + nvram_entry = &table->nvram_entry[i]; + } + + if (nvram_entry) { + nvram_entry->Band = msg->Band; + nvram_entry->Nss = msg->Nss; + nvram_entry->Manipulable = msg->Manipulable; + nvram_entry->PhyMode = msg->PhyMode; + } else { + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("%s: nvram_entry is NULL!\n", __func__)); + return FALSE; + } + + return TRUE; +} + +void BndStrg_SetNvram(PRTMP_ADAPTER pAd, RTMP_IOCTL_INPUT_STRUCT *wrq, INT apidx) +{ + BNDSTRG_NVRAM_CLIENT bsdmsg; + PBND_STRG_CLI_TABLE table = NULL; + BNDSTRG_MSG msg = { 0 }; + struct bnd_msg_nvram_entry_update *entry_update = &msg.data.entry_update; + INT Status; + + table = Get_BndStrgTable(pAd, apidx); + + if (!table || + (table->bInitialized == FALSE) || + (wrq->u.data.length != sizeof(BNDSTRG_NVRAM_CLIENT))) + return; + + Status = copy_from_user(&bsdmsg, wrq->u.data.pointer, wrq->u.data.length); + + if ((BndStrg_NvramInsertEntry(table, &bsdmsg))) { + msg.Action = NVRAM_UPDATE; + memcpy(entry_update->nvram_entry.Addr, bsdmsg.Addr, MAC_ADDR_LEN); + memcpy(entry_update->Addr, bsdmsg.Addr, MAC_ADDR_LEN); + entry_update->nvram_entry.Band = bsdmsg.Band; + entry_update->nvram_entry.Manipulable = bsdmsg.Manipulable; + entry_update->nvram_entry.Nss = bsdmsg.Nss; + entry_update->nvram_entry.PhyMode = bsdmsg.PhyMode; + BndStrgSendMsg(pAd, &msg); + } else + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_INFO, ("%s: NVRAM table full\n", __func__)); +} + +void BndStrg_GetNvram(PRTMP_ADAPTER pAd, RTMP_IOCTL_INPUT_STRUCT *wrq, INT apidx) +{ + PBND_STRG_CLI_TABLE table = NULL; + BNDSTRG_NVRAM_LIST *nvram_list = NULL; + PBNDSTRG_NVRAM_CLIENT nvram_client; + PBNDSTRG_NVRAM_CLIENT table_nvram_client; + int i; + + table = Get_BndStrgTable(pAd, apidx); + + if (!table || + (table->bInitialized == FALSE)) + return; + + os_alloc_mem(pAd, (UCHAR **)&nvram_list, sizeof(BNDSTRG_NVRAM_LIST)); + + if (nvram_list == NULL) + return; + + NdisZeroMemory(nvram_list, sizeof(BNDSTRG_NVRAM_LIST)); + nvram_list->Num = table->bndstrg_nvram_client_count; + + for (i = 0; i < nvram_list->Num; i++) { + table_nvram_client = &table->nvram_entry[i]; + nvram_client = &nvram_list->nvram_entry[i]; + memcpy(nvram_client->Addr, table_nvram_client->Addr, MAC_ADDR_LEN); + nvram_client->Band = table_nvram_client->Band; + nvram_client->Manipulable = table_nvram_client->Manipulable; + nvram_client->PhyMode = table_nvram_client->PhyMode; + nvram_client->Nss = table_nvram_client->Nss; + } + + wrq->u.data.length = sizeof(BNDSTRG_NVRAM_LIST); + copy_to_user(wrq->u.data.pointer, nvram_list, wrq->u.data.length); + + if (nvram_list != NULL) + os_free_mem(nvram_list); + + return; +} +#endif /* VENDOR_FEATURE5_SUPPORT */ + +UINT8 GetNssFromHTCapRxMCSBitmask(UINT32 RxMCSBitmask) +{ + UCHAR RxMCS[4]; + UINT8 nss; + *((UINT32 *)RxMCS) = RxMCSBitmask; + + if (RxMCS[3] != 0) + nss = 4; + else if (RxMCS[2] != 0) + nss = 3; + else if (RxMCS[1] != 0) + nss = 2; + else + nss = 1; + + return nss; +} + +VOID BndStrg_CLIStatusRsp(PRTMP_ADAPTER pAd, PBND_STRG_CLI_TABLE table, BNDSTRG_MSG *msg) +{ + if (table->bInitialized == TRUE) { + BNDSTRG_MSG new_msg = { 0 }; + struct bnd_msg_cli_status_rsp *cli_status_rsp = &new_msg.data.cli_status_rsp; + MAC_TABLE_ENTRY *pEntry = NULL; + PBND_STRG_CLI_ENTRY entry = NULL; + int i = 0; + /* Send to daemon */ + new_msg.Action = CLI_STATUS_RSP; + memset(cli_status_rsp, 0x00, sizeof(struct bnd_msg_cli_status_rsp)); + + for (i = 0; i < BND_STRG_MAX_TABLE_SIZE; i++) { + entry = &table->Entry[i]; + + /* pick up the first available vacancy*/ + if (!entry || entry->bValid == FALSE || !entry->bConnStatus) + continue; + + cli_status_rsp->TableIndex = entry->TableIndex; + pEntry = MacTableLookup(pAd, entry->Addr); + + if (pEntry && IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC) && (pEntry->pMbss != NULL)) { + INT32 avgrssi = 0; + /* get information */ + /* RSSI */ + avgrssi = RTMPAvgRssi(pAd, &pEntry->RssiSample); + { + { + ULONG DataRate = 0; + ULONG DataRate_r = 0; + UINT32 lastRxRate = pEntry->LastRxRate; + HTTRANSMIT_SETTING LastRxRate; + UCHAR phy_mode_r, rate_r; + + LastRxRate.word = (USHORT)lastRxRate; + phy_mode_r = LastRxRate.field.MODE; + rate_r = LastRxRate.word & 0x3F; + + if (phy_mode_r == MODE_OFDM) { + if (rate_r == TMI_TX_RATE_OFDM_6M) + LastRxRate.field.MCS = 0; + else if (rate_r == TMI_TX_RATE_OFDM_9M) + LastRxRate.field.MCS = 1; + else if (rate_r == TMI_TX_RATE_OFDM_12M) + LastRxRate.field.MCS = 2; + else if (rate_r == TMI_TX_RATE_OFDM_18M) + LastRxRate.field.MCS = 3; + else if (rate_r == TMI_TX_RATE_OFDM_24M) + LastRxRate.field.MCS = 4; + else if (rate_r == TMI_TX_RATE_OFDM_36M) + LastRxRate.field.MCS = 5; + else if (rate_r == TMI_TX_RATE_OFDM_48M) + LastRxRate.field.MCS = 6; + else if (rate_r == TMI_TX_RATE_OFDM_54M) + LastRxRate.field.MCS = 7; + else + LastRxRate.field.MCS = 0; + } else if (phy_mode_r == MODE_CCK) { + if (rate_r == TMI_TX_RATE_CCK_1M_LP) + LastRxRate.field.MCS = 0; + else if (rate_r == TMI_TX_RATE_CCK_2M_LP) + LastRxRate.field.MCS = 1; + else if (rate_r == TMI_TX_RATE_CCK_5M_LP) + LastRxRate.field.MCS = 2; + else if (rate_r == TMI_TX_RATE_CCK_11M_LP) + LastRxRate.field.MCS = 3; + else if (rate_r == TMI_TX_RATE_CCK_2M_SP) + LastRxRate.field.MCS = 1; + else if (rate_r == TMI_TX_RATE_CCK_5M_SP) + LastRxRate.field.MCS = 2; + else if (rate_r == TMI_TX_RATE_CCK_11M_SP) + LastRxRate.field.MCS = 3; + else + LastRxRate.field.MCS = 0; + } + + getRate(pEntry->HTPhyMode, &DataRate); + getRate(LastRxRate, &DataRate_r); + cli_status_rsp->data_tx_Rate = DataRate; + cli_status_rsp->data_rx_Rate = DataRate_r; + cli_status_rsp->data_tx_Phymode = pEntry->HTPhyMode.field.MODE; + cli_status_rsp->data_rx_Phymode = 0; + + if (pEntry->HTPhyMode.field.MODE >= MODE_VHT) { + cli_status_rsp->data_tx_mcs = (pEntry->HTPhyMode.field.MCS & 0xf); + cli_status_rsp->data_tx_ant = (pEntry->HTPhyMode.field.MCS>>4) + 1; + } else if (pEntry->HTPhyMode.field.MODE >= MODE_HTMIX) { + cli_status_rsp->data_tx_mcs = pEntry->HTPhyMode.field.MCS; + cli_status_rsp->data_tx_ant = (pEntry->HTPhyMode.field.MCS >> 3)+1; + + if (cli_status_rsp->data_tx_mcs > 7) + cli_status_rsp->data_tx_mcs %= 8; + } else if (pEntry->HTPhyMode.field.MODE >= MODE_OFDM) { + cli_status_rsp->data_tx_mcs = pEntry->HTPhyMode.field.MCS; + cli_status_rsp->data_tx_ant = 1; + } else if (pEntry->HTPhyMode.field.MODE >= MODE_CCK) { + cli_status_rsp->data_tx_mcs = pEntry->HTPhyMode.field.MCS; + cli_status_rsp->data_tx_ant = 1; + } + + if (LastRxRate.field.MODE >= MODE_VHT) { + cli_status_rsp->data_rx_mcs = LastRxRate.field.MCS & 0xf; + cli_status_rsp->data_rx_ant = (LastRxRate.field.MCS>>4) + 1; + } else if (LastRxRate.field.MODE >= MODE_HTMIX) { + cli_status_rsp->data_rx_mcs = LastRxRate.field.MCS; + cli_status_rsp->data_rx_ant = (LastRxRate.field.MCS >> 3)+1; + + if (cli_status_rsp->data_rx_mcs > 7) + cli_status_rsp->data_rx_mcs %= 8; + } else if (LastRxRate.field.MODE >= MODE_OFDM) { + cli_status_rsp->data_rx_mcs = LastRxRate.field.MCS; + cli_status_rsp->data_rx_ant = 1; + } else if (LastRxRate.field.MODE >= MODE_CCK) { + cli_status_rsp->data_rx_mcs = LastRxRate.field.MCS; + cli_status_rsp->data_rx_ant = 1; + } + + cli_status_rsp->data_tx_bw = pEntry->HTPhyMode.field.BW; + cli_status_rsp->data_rx_bw = LastRxRate.field.BW; + cli_status_rsp->data_tx_sgi = pEntry->HTPhyMode.field.ShortGI; + cli_status_rsp->data_rx_sgi = LastRxRate.field.ShortGI; + cli_status_rsp->data_tx_stbc = pEntry->HTPhyMode.field.STBC; + cli_status_rsp->data_rx_stbc = LastRxRate.field.STBC; + cli_status_rsp->data_tx_packets = pEntry->TxPackets.QuadPart; + cli_status_rsp->data_rx_packets = pEntry->RxPackets.QuadPart; + } + } + cli_status_rsp->data_Rssi = (char)avgrssi; + /* cli_status_rsp->data_tx_TP = pEntry->AvgTxBytes >> 17; //Mbps */ + /* cli_status_rsp->data_rx_TP = pEntry->AvgRxBytes >> 17; //Mbps */ + cli_status_rsp->data_tx_Byte = pEntry->AvgTxBytes; + cli_status_rsp->data_rx_Byte = pEntry->AvgRxBytes; + memcpy(cli_status_rsp->Addr, entry->Addr, MAC_ADDR_LEN); + cli_status_rsp->ReturnCode = BND_STRG_SUCCESS; + BndStrgSendMsg(pAd, &new_msg); + } + } + } + + return; +} + +VOID BndStrg_ChannelLoadStatusRsp(PRTMP_ADAPTER pAd, PBND_STRG_CLI_TABLE table, BNDSTRG_MSG *msg) +{ + if (table->bInitialized == TRUE) { + BNDSTRG_MSG new_msg = { 0 }; + struct bnd_msg_chanload_status_rsp *chanload_status_rsp = &new_msg.data.chanload_status_rsp; + /* Send to daemon */ + new_msg.Action = CHANLOAD_STATUS_RSP; + chanload_status_rsp->ReturnCode = BND_STRG_SUCCESS; + chanload_status_rsp->band = table->Band; + chanload_status_rsp->Channel = table->Channel; + chanload_status_rsp->chanload = (pAd->ApCfg.BndStrgOneSecChBusyTime * 100)/ONE_SEC_2_US; + BndStrgSendMsg(pAd, &new_msg); + } +} + +VOID BndStrg_InfStatusRsp(PRTMP_ADAPTER pAd, PBND_STRG_CLI_TABLE table, BNDSTRG_MSG *msg) +{ + struct bnd_msg_inf_status_req *inf_status_req = &msg->data.inf_status_req; + + if (table->bInitialized == TRUE) { + BNDSTRG_MSG new_msg = { 0 }; + struct bnd_msg_inf_status_rsp *inf_status_rsp = &new_msg.data.inf_status_rsp; + /* Send to daemon */ + new_msg.Action = INF_STATUS_RSP; + + inf_status_rsp->band = table->Band; + inf_status_rsp->bInfReady = table->bInfReady; + inf_status_rsp->Channel = table->Channel; + inf_status_rsp->bVHTCapable = table->bVHTCapable; + inf_status_rsp->nss = table->nss; + inf_status_rsp->table_src_addr = (ULONG)table; + inf_status_rsp->table_size = BND_STRG_MAX_TABLE_SIZE; + strncpy(inf_status_rsp->ucIfName, inf_status_req->ucIfName, sizeof(inf_status_rsp->ucIfName)); +#ifdef VENDOR_FEATURE5_SUPPORT + inf_status_rsp->nvram_support = 1; +#else + inf_status_rsp->nvram_support = 0; +#endif + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("\n%s:INF [%s]STATUS QUERY ON\n", __func__, inf_status_req->ucIfName)); + BndStrgSendMsg(pAd, &new_msg); + } +} + +VOID BndStrg_handle_onoff_event(PRTMP_ADAPTER pAd, PBND_STRG_CLI_TABLE table, BNDSTRG_MSG *msg) +{ + struct bnd_msg_onoff *onoff = &msg->data.onoff; + UINT32 ap_idx; + UINT32 i; + + if (onoff->OnOff && (table->bEnabled ^ onoff->OnOff)) { + /* disconnect all connected STA to keep the link status + * between bndstrg daemon and driver + */ + for (ap_idx = MAIN_MBSSID; ap_idx < pAd->ApCfg.BssidNum; ap_idx++) { + if (pAd->ApCfg.BndStrgBssIdx[ap_idx] == TRUE) + BndStrg_KickOutAllSta(pAd, ap_idx, REASON_DEAUTH_STA_LEAVING); + } + + for (i=1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i]; + if (IS_ENTRY_CLIENT(pEntry) && + pAd->ApCfg.BndStrgBssIdx[pEntry->func_tb_idx] == TRUE) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("[PMF]%s: MacTableDeleteEntry %x:%x:%x:%x:%x:%x\n", + __func__, PRINT_MAC(pEntry->Addr))); + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + } + } + + BndStrg_Send_NeighborReport(pAd, table); + table->BndStrgMode = onoff->BndStrgMode; + } else if ((onoff->OnOff == 0) && (table->bEnabled ^ onoff->OnOff)) { + if (table->Size > 0) { + PBND_STRG_CLI_ENTRY entry = NULL; + + for (i = 0; i < BND_STRG_MAX_TABLE_SIZE; i++) { + entry = &table->Entry[i]; + + if (entry->bValid == TRUE) + BndStrg_DeleteEntry(table, entry->Addr, i); + } + } + } + + BndStrg_Tbl_Enable(table, onoff->OnOff, onoff->ucIfName); + + if (table->bEnabled) + table->DaemonPid = current->pid; + else + table->DaemonPid = 0xffffffff; + return; +} + +VOID BndStrg_UpdateWhiteBlackList(PRTMP_ADAPTER pAd, PBND_STRG_CLI_TABLE table, BNDSTRG_MSG *msg) +{ + struct bnd_msg_update_white_black_list *update_list = &msg->data.update_white_black_list; + PLIST_HEADER pUpdateList = NULL; + NDIS_SPIN_LOCK *pBsListLock = NULL; + + BND_STRG_PRINTQAMSG(table, update_list->Addr, ("%s: client[%02x:%02x:%02x:%02x:%02x:%02x] %s %s\n", __func__, PRINT_MAC(update_list->Addr), + (update_list->deladd ? "Add to":"Remove From"), ((update_list->list_type == bndstrg_whitelist) ? "WhiteList" : "BlackList"))); + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("%s: client[%02x:%02x:%02x:%02x:%02x:%02x] %s %s\n", __func__, PRINT_MAC(update_list->Addr), + (update_list->deladd ? "Add to":"Remove From"), ((update_list->list_type == bndstrg_whitelist) ? "WhiteList" : "BlackList"))); + + if (update_list->list_type == bndstrg_whitelist) { + pUpdateList = &table->WhiteList; + pBsListLock = &table->WhiteListLock; + } else if (update_list->list_type == bndstrg_blacklist) { + pUpdateList = &table->BlackList; + pBsListLock = &table->BlackListLock; + } else + return; + + if (update_list->deladd) { + NdisAcquireSpinLock(pBsListLock); + AddBsListEntry(pUpdateList, update_list->Addr); + NdisReleaseSpinLock(pBsListLock); + } else { + NdisAcquireSpinLock(pBsListLock); + DelBsListEntry(pUpdateList, update_list->Addr); + NdisReleaseSpinLock(pBsListLock); + } +} + +INT BndStrg_MsgHandle(PRTMP_ADAPTER pAd, RTMP_IOCTL_INPUT_STRUCT *wrq, INT apidx) +{ + PBND_STRG_CLI_ENTRY entry = NULL; + BNDSTRG_MSG msg_copy = { 0 }; + BNDSTRG_MSG *msg = &msg_copy; + PBND_STRG_CLI_TABLE table = NULL; + INT Status = NDIS_STATUS_SUCCESS; + + table = Get_BndStrgTable(pAd, apidx); + + if (!table || (table->bInitialized == FALSE)) { + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_WARN, + ("%s: BND_STRG_NOT_INITIALIZED on apidex[%d]!\n", __func__, apidx)); + return BND_STRG_NOT_INITIALIZED; + } + + if (wrq->u.data.length > sizeof(BNDSTRG_MSG)) { + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s: The length of message not match!\n", __func__)); + return BND_STRG_INVALID_ARG; + } else { + Status = copy_from_user(&msg_copy, wrq->u.data.pointer, wrq->u.data.length); + } + + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_INFO, ("%s: action code (%d)\n", __func__, msg->Action)); + + if ((table->DaemonPid != 0xffffffff) && (table->DaemonPid != current->pid)) { + BNDSTRG_MSG new_msg = { 0 }; + + new_msg.Action = REJECT_EVENT; + new_msg.data.reject_body.DaemonPid = table->DaemonPid; + BndStrgSendMsg(pAd, &new_msg); + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("%s:Unknown BndStrg PID\n", __func__)); + return BND_STRG_SUCCESS; + } + + switch (msg->Action) { + case CLI_ADD: { + struct bnd_msg_cli_add *cli_add = &msg->data.cli_add; + +#ifdef BND_STRG_QA + BND_STRG_PRINTQAMSG(table, cli_add->Addr, (("%s[%d][Channel:%d]: Add (%02x:%02x:%02x:%02x:%02x:%02x) client to %s driver table\n\r"), + __func__, __LINE__, table->Channel, PRINT_MAC(cli_add->Addr), (IS_5G_BAND(table->Band) ? "5G":"2.4G"))); +#endif + + entry = BndStrg_TableLookup(table, cli_add->Addr); + + if (entry == NULL) { + if (BndStrg_InsertEntry(table, cli_add, &entry) == BND_STRG_SUCCESS) { + if (table->BndStrgMode == POST_CONNECTION_STEERING) { + entry->bConnStatus = TRUE; + entry->BndStrg_Sta_State = BNDSTRG_STA_ASSOC; + } + } + } + else + entry->BndStrg_Sta_State = BNDSTRG_STA_INIT; + } + break; + + case CLI_DEL: { + struct bnd_msg_cli_del *cli_del = &msg->data.cli_del; + MAC_TABLE_ENTRY *pEntry = NULL; + + if (BndStrg_TableLookup(table, cli_del->Addr)) { + /*remove sta if sta is existed*/ + pEntry = MacTableLookup(pAd, cli_del->Addr); + + if (pEntry && apidx == pEntry->func_tb_idx && + pAd->ApCfg.BndStrgBssIdx[pEntry->func_tb_idx]) { +#ifdef BND_STRG_QA + BND_STRG_PRINTQAMSG(table, cli_del->Addr, (("%s[%d]: kick out client's (%02x:%02x:%02x:%02x:%02x:%02x)\n\r"), + __func__, __LINE__, PRINT_MAC(cli_del->Addr))); +#endif + MlmeDeAuthAction(pAd, pEntry, REASON_DISASSOC_STA_LEAVING, FALSE); + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + } + + BndStrg_DeleteEntry(table, cli_del->Addr, 0xFF); +#ifdef BND_STRG_QA + BND_STRG_PRINTQAMSG(table, cli_del->Addr, (("%s[%d][Channel:%d]:DEL (%02x:%02x:%02x:%02x:%02x:%02x) client from %s driver table\n\r"), + __func__, __LINE__, table->Channel, PRINT_MAC(cli_del->Addr), (IS_5G_BAND(table->Band) ? "5G":"2.4G"))); +#endif + } + } + break; + case CLI_STATUS_REQ: + if (table->bInfReady) + BndStrg_CLIStatusRsp(pAd, table, msg); + + break; + + case CHANLOAD_STATUS_REQ: + if (table->bInfReady) + BndStrg_ChannelLoadStatusRsp(pAd, table, msg); + + break; + + case INF_STATUS_QUERY: + if (table->bInfReady) + BndStrg_InfStatusRsp(pAd, table, msg); + + break; + + case HEARTBEAT_MONITOR: + if (table->bInfReady) + pAd->ApCfg.BndStrgHeartbeatCount++; + + break; + + case BNDSTRG_ONOFF: + if (table && table->bInitialized) + BndStrg_handle_onoff_event(pAd, table, msg); + break; +#ifdef VENDOR_FEATURE5_SUPPORT + case NVRAM_UPDATE: { + struct bnd_msg_nvram_entry_update *entry_update = &msg->data.entry_update; + + if (!(BndStrg_NvramInsertEntry(table, &entry_update->nvram_entry))) + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_INFO, ("%s: NVRAM table full\n", __func__)); + } + break; +#endif /* VENDOR_FEATURE5_SUPPORT */ + + case BNDSTRG_WNM_BTM: +#ifdef CONFIG_DOT11V_WNM + { + struct wnm_command *cmd_data = (struct wnm_command *)&msg->data.wnm_cmd_data; + + hex_dump("BNDSTRG_WNM_BTM MSG", (unsigned char *)msg, sizeof(BNDSTRG_MSG)); + if (cmd_data->command_id == OID_802_11_WNM_CMD_SEND_BTM_REQ) { + MAC_TABLE_ENTRY *pEntry; + unsigned char *request_mode; + struct btm_req_data *req_data; +#define DISASSOC_IMMINENT (0x01 << 2) + req_data = (struct btm_req_data *)cmd_data->command_body; + request_mode = (unsigned char *)req_data->btm_req; + if ((*request_mode) & DISASSOC_IMMINENT) { + /* imminent dis-assoc BTM Req, delete entry from driver table */ + BndStrg_DeleteEntry(table, req_data->peer_mac_addr, 0xFF); + } + pEntry = MacTableLookup(pAd, req_data->peer_mac_addr); + if (pEntry != NULL) { + BndStrg_send_BTM_req(pAd, + req_data->peer_mac_addr, + req_data->btm_req, + req_data->btm_req_len, + table); + } + } else{ + hex_dump("BNDSTRG_WNM_BTM", (unsigned char *)cmd_data, cmd_data->command_len); + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("%s: Unknow wnm cmd id %d\n", __func__, cmd_data->command_id)); + } + } +#endif + break; + + case UPDATE_WHITE_BLACK_LIST: + if (table->bInfReady) { + BndStrg_UpdateWhiteBlackList(pAd, table, msg); + } + break; + + default: + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_WARN, ("%s: unknown action code. (%d)\n", __func__, msg->Action)); + break; + } + + return BND_STRG_SUCCESS; +} + +void BndStrgHeartBeatMonitor(PRTMP_ADAPTER pAd) +{ + if (pAd->ApCfg.BndStrgTable[0].bEnabled ) { + if (pAd->ApCfg.BndStrgHeartbeatMonitor != pAd->ApCfg.BndStrgHeartbeatCount) { + pAd->ApCfg.BndStrgHeartbeatMonitor = pAd->ApCfg.BndStrgHeartbeatCount; + pAd->ApCfg.BndStrgHeartbeatNoChange = 0; + return; + } else + pAd->ApCfg.BndStrgHeartbeatNoChange++; + + if (pAd->ApCfg.BndStrgHeartbeatNoChange == 20) { + BND_STRG_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("%s:BndStrg Daemon Killed\n", __func__)); + pAd->ApCfg.BndStrgHeartbeatNoChange = 0; + BndStrg_Release(pAd); + } + } +} + +void BndStrgSetProfileParam(struct _RTMP_ADAPTER *pAd, RTMP_STRING *tmpbuf, RTMP_STRING *pBuffer) +{ + INT i = 0; + RTMP_STRING *macptr = NULL; + + if (RTMPGetKeyParameter("BandSteering", tmpbuf, 10, pBuffer, TRUE)) { + pAd->ApCfg.BandSteering = (UCHAR) simple_strtol(tmpbuf, 0, 10); + MTWF_LOG(DBG_CAT_CFG, DBG_CAT_AP, DBG_LVL_OFF, ("BandSteering=%d\n", pAd->ApCfg.BandSteering)); + } + + if (RTMPGetKeyParameter("BndStrgBssIdx", tmpbuf, 50, pBuffer, TRUE)) { + MTWF_LOG(DBG_CAT_CFG, DBG_CAT_AP, DBG_LVL_OFF, ("BndStrgBssIdx=%s\n", tmpbuf)); + + for (i = 0, macptr = rstrtok(tmpbuf, ";"); macptr; macptr = rstrtok(NULL, ";"), i++) + pAd->ApCfg.BndStrgBssIdx[i] = simple_strtoul(macptr, 0, 10); + + if (i == 0) + pAd->ApCfg.BndStrgBssIdx[MAIN_MBSSID] = 1; + } else + pAd->ApCfg.BndStrgBssIdx[MAIN_MBSSID] = 1; +} +#ifdef CONFIG_DOT11V_WNM +void BndStrg_send_BTM_req( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *PeerMACAddr, + IN RTMP_STRING *BTMReq, + IN UINT32 BTMReqLen, + PBND_STRG_CLI_TABLE table) +{ + UCHAR *Buf; + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UCHAR APIndex = pObj->ioctl_if; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; + BTM_EVENT_DATA *Event; + BTM_PEER_ENTRY *BTMPeerEntry; +#ifdef DOT11K_RRM_SUPPORT + RRM_NEIGHBOR_REP_INFO *NeighborReport = NULL; + ULONG FrameLen = 0; +#endif + UINT32 Len = 0; + INT32 Ret; + BOOLEAN IsFound = FALSE; + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("%s\n", __func__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListForEach(BTMPeerEntry, &pWNMCtrl->BTMPeerList, BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, PeerMACAddr)) { + IsFound = TRUE; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + + if (!IsFound) { + os_alloc_mem(NULL, (UCHAR **)&BTMPeerEntry, sizeof(*BTMPeerEntry)); + + if (!BTMPeerEntry) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("%s Not available memory\n", __func__)); + goto error0; + } + + NdisZeroMemory(BTMPeerEntry, sizeof(*BTMPeerEntry)); + + BTMPeerEntry->CurrentState = WAIT_BTM_REQ; + BTMPeerEntry->ControlIndex = APIndex; + NdisMoveMemory(BTMPeerEntry->PeerMACAddr, PeerMACAddr, MAC_ADDR_LEN); + BTMPeerEntry->DialogToken = 1; + BTMPeerEntry->Priv = pAd; + + RTMPInitTimer(pAd, &BTMPeerEntry->WaitPeerBTMRspTimer, + GET_TIMER_FUNCTION(WaitPeerBTMRspTimeout), BTMPeerEntry, FALSE); + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListAddTail(&pWNMCtrl->BTMPeerList, &BTMPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + } + +#ifdef DOT11K_RRM_SUPPORT + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + BTMReqLen + sizeof(RRM_NEIGHBOR_REP_INFO) + 3); + /* Size 3 is for the preference sub element in neighbor report*/ +#else + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + BTMReqLen); +#endif + + if (!Buf) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("%s Not available memory\n", __func__)); + goto error1; + } + +#ifdef DOT11K_RRM_SUPPORT + NdisZeroMemory(Buf, sizeof(*Event) + BTMReqLen + sizeof(RRM_NEIGHBOR_REP_INFO) + 3); + /* Size 3 is for the preference sub element in neighbor report*/ +#else + NdisZeroMemory(Buf, sizeof(*Event) + BTMReqLen); +#endif + + Event = (BTM_EVENT_DATA *)Buf; + + Event->ControlIndex = APIndex; + Len += 1; + + NdisMoveMemory(Event->PeerMACAddr, PeerMACAddr, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + Event->EventType = BTM_REQ; + Len += 2; + + Event->u.BTM_REQ_DATA.DialogToken = BTMPeerEntry->DialogToken; + Len += 1; + + Event->u.BTM_REQ_DATA.BTMReqLen = BTMReqLen; + Len += 2; + + NdisMoveMemory(Event->u.BTM_REQ_DATA.BTMReq, BTMReq, BTMReqLen); + + BTMReq += BTMReqLen; /*advance pointer to neighbour report*/ +#ifdef DOT11K_RRM_SUPPORT + hex_dump("BndStrg_send_BTM_req NeighborReport", (unsigned char *)BTMReq, sizeof(RRM_NEIGHBOR_REP_INFO)); + NeighborReport = (RRM_NEIGHBOR_REP_INFO *)BTMReq; + + RRM_InsertNeighborRepIE(pAd, (Event->u.BTM_REQ_DATA.BTMReq + BTMReqLen), &FrameLen, + sizeof(RRM_NEIGHBOR_REP_INFO)+3, NeighborReport->Bssid, (RRM_BSSID_INFO)NeighborReport->BssidInfo, + NeighborReport->RegulatoryClass, NeighborReport->ChNum, NeighborReport->PhyType); + BTMReqLen += FrameLen; + { + ULONG TempLen = 0; + UINT8 IEId = 3; + UINT8 Len = 1; + UINT8 BssPreference = 255; + + MakeOutgoingFrame((Event->u.BTM_REQ_DATA.BTMReq + BTMReqLen), &TempLen, + 1, &IEId, + 1, &Len, + 1, &BssPreference, + END_OF_ARGS); + BTMReqLen += TempLen; + } + Event->u.BTM_REQ_DATA.BTMReqLen = BTMReqLen; + Len += BTMReqLen; +#endif + hex_dump("BndStrg_send_BTM_req Enque", (unsigned char *)Buf, Len); + hex_dump("BndStrg_send_BTM_req Event length", (unsigned char *)Event->u.BTM_REQ_DATA.BTMReq, + Event->u.BTM_REQ_DATA.BTMReqLen); + MlmeEnqueue(pAd, BTM_STATE_MACHINE, BTM_REQ, Len, Buf, 0); + + os_free_mem(NULL, Buf); + + return; + +error1: + if (!IsFound) + os_free_mem(NULL, BTMPeerEntry); +error0: + return; +} + +#endif + +void BndStrg_Send_NeighborReport(PRTMP_ADAPTER pAd, PBND_STRG_CLI_TABLE table) +{ +#ifdef DOT11K_RRM_SUPPORT + BNDSTRG_MSG msg = { 0 }; + struct bnd_msg_neighbor_report *NeighborReport = &msg.data.Neighbor_Report; + + msg.Action = BNDSTRG_NEIGHBOR_REPORT; + + NeighborReport->Band = table->Band; + NeighborReport->Channel = table->Channel; + NdisCopyMemory(&NeighborReport->NeighborRepInfo, &table->NeighborRepInfo, sizeof(RRM_NEIGHBOR_REP_INFO)); + BndStrgSendMsg(pAd, &msg); +#endif + return; +} + +VOID BndStrg_KickOutAllSta(PRTMP_ADAPTER pAd, UCHAR apidx, USHORT Reason) +{ + HEADER_802_11 DisassocHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + if ((apidx < pAd->ApCfg.BssidNum)) + { + /* Send out a Deauthentication request frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + DBGPRINT(RT_DEBUG_ERROR, ("Send DISASSOC Broadcast frame(%d) with ra%d \n", Reason, apidx)); + + /* 802.11 Header */ + NdisZeroMemory(&DisassocHdr, sizeof(HEADER_802_11)); + DisassocHdr.FC.Type = FC_TYPE_MGMT; + DisassocHdr.FC.SubType = SUBTYPE_DISASSOC; + DisassocHdr.FC.ToDs = 0; + DisassocHdr.FC.Wep = 0; + COPY_MAC_ADDR(DisassocHdr.Addr1, BROADCAST_ADDR); + COPY_MAC_ADDR(DisassocHdr.Addr2, pAd->ApCfg.MBSSID[apidx].wdev.bssid); + COPY_MAC_ADDR(DisassocHdr.Addr3, pAd->ApCfg.MBSSID[apidx].wdev.bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DisassocHdr, + 2, &Reason, + END_OF_ARGS); + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } +} + +#endif /* BAND_STEERING */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_cfg.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_cfg.c new file mode 100644 index 000000000..ffda51937 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_cfg.c @@ -0,0 +1,17758 @@ +/**************************************************************************** + * 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" + +#ifdef STA_FORCE_ROAM_SUPPORT +extern int handle_froam_query_cmd(RTMP_ADAPTER *pAd, RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif +#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)) + +static const struct apcfg_parameters apcfg_for_peak = { + .cfg_mode[0] = 9, /*WirelessMode*/ + .cfg_mode[1] = 14, + .tx_power_percentage = 100, /*TxPower*/ + .tx_preamble = 1, /*TxPreamble*/ + .conf_len_thld = 2347, /*RTSThreshold*/ + .oper_len_thld = 2347, + .conf_frag_thld = 2346, /*FragThreshold*/ + .oper_frag_thld = 2346, + .bEnableTxBurst = 1, /*TxBurst*/ + .bUseShortSlotTime = 1, /*ShortSlot*/ +#ifdef DOT11_N_SUPPORT + .conf_ht_bw = 1, /*HT_BW*/ + .oper_ht_bw = 1, +#ifdef DOT11N_DRAFT3 + .bBssCoexEnable = 0, /*HT_BSSCoexistence*/ +#endif + + .ht_tx_streams = 2, /*HT_TxStream*/ + .ht_rx_streams = 2, /*HT_RxStream*/ + + .bBADecline = 0, /*HT_BADecline*/ + .AutoBA = 1, /*HT_AutoBA*/ + .AmsduEnable = 0, /*HT_AMSDU*/ + .RxBAWinLimit = 64, /*HT_BAWinSize*/ + .ht_gi = 1, /*HT_GI*/ + .ht_stbc = 1, /*HT_STBC*/ + .ht_ldpc = 1, /*HT_LDPC*/ + .bRdg = 0, /*HT_RDG*/ +#endif + + .HT_DisallowTKIP = 1, /*HT_DisallowTKIP*/ + +#ifdef DOT11_N_SUPPORT +#endif + + .ITxBfEn = 0, /*ITxBfEn*/ + +#ifdef DOT11_N_SUPPORT +#endif +}; + +INT Set_CountryString_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_CountryCode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef EXT_BUILD_CHANNEL_LIST +INT Set_ChGeography_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* EXT_BUILD_CHANNEL_LIST */ + +#ifdef SPECIFIC_TX_POWER_SUPPORT +INT Set_AP_PKT_PWR(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + +INT Set_AP_TEST2_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_AP_TEST3_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_AP_SSID_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_AP_SSIDSingle_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef CONFIG_SNIFFER_SUPPORT +INT Set_AP_Monitor_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* CONFIG_SNIFFER_SUPPORT */ + +#ifdef PREVENT_ARP_SPOOFING +INT Set_ARPSpoofChk_Enable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Show_ARPSpoofChk_Enable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* PREVENT_ARP_SPOOFING */ + +INT Set_TxRate_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + +INT Set_OLBCDetection_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_AP_MaxStaNum_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_AP_IdleTimeout_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#ifdef IAPP_SUPPORT +INT Set_IappPID_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* IAPP_SUPPORT */ + +INT Set_AP_AuthMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_AP_AuthMode_Single_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + +INT Set_AP_EncrypType_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_AP_WpaMixPairCipher_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_AP_RekeyInterval_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_AP_RekeyMethod_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_AP_PMKCachePeriod_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_AP_ASSOC_REQ_RSSI_THRESHOLD(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_AP_KickStaRssiLow_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_AP_DefaultKeyID_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_AP_Key1_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_AP_Key2_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_AP_Key3_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_AP_Key4_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_AP_WPAPSK_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_BasicRate_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_BeaconPeriod_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_DtimPeriod_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_NoForwarding_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_NoForwardingBTNSSID_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_AP_WmmCapable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_HideSSID_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_VLANID_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_VLANPriority_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_VLAN_TAG_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_AccessPolicy_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ACLAddEntry_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ACLDelEntry_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ACLShowAll_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ACLClearAll_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_RadioOn_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_SiteSurvey_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_AutoChannelSel_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef AP_PARTIAL_SCAN_SUPPORT +INT Set_PartialScan_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + +#ifdef AP_SCAN_SUPPORT +INT Set_AutoChannelSelCheckTime_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* AP_SCAN_SUPPORT */ + +#ifdef NEIGHBORING_AP_STAT +INT Set_CustomScanResult_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif + +INT Set_BADecline_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#ifdef DBG +INT Show_StaCount_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Show_StaSecurityInfo_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Show_DriverInfo_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +static INT show_apcfg_info(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Show_Sat_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Show_RAInfo_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Show_Sat_Reset_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* DBG */ +#ifdef RTMP_MAC_PCI +#ifdef DBG_DIAGNOSE +INT Set_DiagOpt_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_BDInfo_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_diag_cond_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Show_Diag_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* DBG_DAIGNOSE */ +#endif /* RTMP_MAC_PCI */ + +INT Show_MATTable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#ifdef DOT1X_SUPPORT +VOID RTMPIoctlQueryRadiusConf( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +INT Set_IEEE8021X_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_PreAuth_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_RADIUS_Server_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_RADIUS_Port_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_RADIUS_Key_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* DOT1X_SUPPORT */ + +INT Set_DisConnectSta_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_DisConnectAllSta_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef MULTI_CLIENT_SUPPORT +INT Set_ManualMultiClientOn_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_MultiClientOnMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_RtsRetryCnt_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_MidRate_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_FarRate_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_FarDropRssi_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_TxSwQMaxLen_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_FalseCCARateTable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif + +INT Set_PingFixRate_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + +#ifdef APCLI_SUPPORT +INT Set_ApCli_Enable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ApCli_Ssid_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ApCli_UniCode_Ssid_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ApCli_Bssid_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ApCli_DefaultKeyID_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ApCli_WPAPSK_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ApCli_Key1_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ApCli_Key2_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ApCli_Key3_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ApCli_Key4_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ApCli_TxMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ApCli_TxMcs_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +static INT Set_ApCli_Cert_Enable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#ifdef APCLI_AUTO_CONNECT_SUPPORT +INT Set_ApCli_AutoConnect_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + + +#ifdef MAC_REPEATER_SUPPORT +INT Set_ReptMode_Enable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_BaSnReset_Disable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ReptOUIMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_MACReptAddEntry_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_MACReptMACShowAll_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef WSC_AP_SUPPORT +INT Set_AP_WscSsid_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#ifdef APCLI_SUPPORT +INT Set_ApCli_WscScanMode_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +#endif /* APCLI_SUPPORT */ +#endif /* WSC_AP_SUPPORT */ +#ifdef ROAMING_ENHANCE_SUPPORT +INT Set_RoamingEnhance_Enable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* ROAMING_ENHANCE_SUPPORT */ +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef APCLI_CERT_SUPPORT +/* Add for APCLI PMF 5.3.3.3 option test item. (Only Tx De-auth Req. and make sure the pkt can be Encrypted)*/ +INT ApCliTxDeAuth(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* APCLI_CERT_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ +#endif /* APCLI_SUPPORT */ +#ifdef UAPSD_SUPPORT +INT Set_UAPSD_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* UAPSD_SUPPORT */ + +#ifdef WSC_AP_SUPPORT +INT Set_WscStatus_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef BB_SOC +INT Set_WscOOB_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif + +INT Set_WscStop_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +VOID RTMPIoctlWscProfile( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +#ifdef WSC_NFC_SUPPORT +VOID RTMPIoctlNfcStatus( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif /* WSC_NFC_SUPPORT */ + +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 RTMP_STRING *pData, + IN USHORT Length, + IN PWSC_CTRL pWscControl); + +UCHAR WscRxMsgTypeFromUpnp( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_STRING *pData, + IN USHORT Length); + +INT WscGetConfForUpnp( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl); + +INT Set_AP_WscConfMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_AP_WscConfStatus_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_AP_WscMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_AP_WscGetConf_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_AP_WscPinCode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_AP_WscSecurityMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_AP_WscMultiByteCheck_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_WscVersion_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_WscSetupLock_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef WSC_V2_SUPPORT +INT Set_WscV2Support_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_WscVersion2_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_WscExtraTlvTag_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_WscExtraTlvType_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_WscExtraTlvData_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_WscFragment_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_WscFragmentSize_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* WSC_V2_SUPPORT */ + +INT Set_WscMaxPinAttack_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_WscSetupLockTime_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_WscAutoTriggerDisable_Proc( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *arg); +#endif /* WSC_AP_SUPPORT */ + +#ifdef CONFIG_RA_HW_NAT_WIFI_NEW_ARCH +static INT set_hnat_register(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /*CONFIG_RA_HW_NAT_WIFI_NEW_ARCH*/ + + +#ifdef CONFIG_AP_SUPPORT +#ifdef MCAST_RATE_SPECIFIC +INT Set_McastPhyMode(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_McastMcs(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Show_McastRate(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* MCAST_RATE_SPECIFIC */ + +#ifdef DOT11N_DRAFT3 +INT Set_OBSSScanParam_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_AP2040ReScan_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* DOT11N_DRAFT3 */ + +INT Set_EntryLifeCheck_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + +#ifdef AP_QLOAD_SUPPORT +INT Set_QloadClr_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +/* QLOAD ALARM */ +INT Set_QloadAlarmTimeThreshold_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_QloadAlarmNumThreshold_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* AP_QLOAD_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +INT set_lower_mcs_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_higher_mcs_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Show_lower_mcs_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Show_higher_mcs_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + +INT Set_MemDebug_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef CONFIG_AP_SUPPORT +INT Set_PowerSaveLifeTime_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef AIR_MONITOR +INT Set_Enable_Air_Monitor_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_MonitorRule_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_MonitorTarget_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_MonitorIndex_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_MonitorShowAll_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_MonitorClearCounter_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_MonitorTarget0_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_MonitorTarget1_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_MonitorTarget2_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_MonitorTarget3_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_MonitorTarget4_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_MonitorTarget5_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_MonitorTarget6_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_MonitorTarget7_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +VOID Air_Monitor_Pkt_Report_Action(PRTMP_ADAPTER pAd, UCHAR wcid, RX_BLK *pRxBlk); +BOOLEAN IsValidUnicastToMe(IN PRTMP_ADAPTER pAd, + IN UCHAR WCID, + IN PUCHAR pDA); +#endif /* AIR_MONITOR */ + + +#ifdef AIRPLAY_SUPPORT +int Set_Airplay_Enable( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); +#endif /* AIRPLAY_SUPPORT */ + +#ifdef DYNAMIC_VGA_SUPPORT +INT Set_DyncVgaEnable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT set_false_cca_hi_th(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_false_cca_low_th(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* DYNAMIC_VGA_SUPPORT */ + +#ifdef MT_MAC +INT Set_AP_TimEnable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT setApTmrEnableProc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef DBG +INT Set_AP_DumpTime_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_BcnStateCtrl_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +#endif + +INT set_ping_log_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef DATA_QUEUE_RESERVE +INT set_queue_rsv_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_dump_on_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_rsv_cnt_clear_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* DATA_QUEUE_RESERVE */ + +#endif /* MT_MAC */ +#ifdef CONFIG_PUSH_SUPPORT +INT Set_EasySetup_ssid_psk_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_EasySetup_Ftmdid_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif +int add_mntr_entry(void *ad_obj, RTMP_IOCTL_INPUT_STRUCT *wrq); +int del_mntr_entry(void *ad_obj, RTMP_IOCTL_INPUT_STRUCT *wrq); +int set_mntr_rule(void *ad_obj, RTMP_IOCTL_INPUT_STRUCT *wrq); + + +static struct { + RTMP_STRING *name; + INT (*set_proc)(PRTMP_ADAPTER pAdapter, RTMP_STRING *arg); +} *PRTMP_PRIVATE_SET_PROC, RTMP_PRIVATE_SUPPORT_PROC[] = { + {"RateAlg", Set_RateAlg_Proc}, +#ifdef NEW_RATE_ADAPT_SUPPORT +#ifdef DBG + {"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 /* DBG */ +#endif /* NEW_RATE_ADAPT_SUPPORT */ + {"DriverVersion", Set_DriverVersion_Proc}, + {"CountryRegion", Set_CountryRegion_Proc}, + {"CountryRegionABand", Set_CountryRegionABand_Proc}, + {"CountryString", Set_CountryString_Proc}, + {"CountryCode", Set_CountryCode_Proc}, +#ifdef EXT_BUILD_CHANNEL_LIST + {"ChGeography", Set_ChGeography_Proc}, +#endif /* EXT_BUILD_CHANNEL_LIST */ +#ifdef AIR_MONITOR + {"mnt_en", Set_Enable_Air_Monitor_Proc}, + {"mnt_rule", Set_MonitorRule_Proc}, + {"mnt_sta", Set_MonitorTarget_Proc}, + {"mnt_idx", Set_MonitorIndex_Proc}, + {"mnt_show", Set_MonitorShowAll_Proc}, + {"mnt_clr", Set_MonitorClearCounter_Proc}, + {"mnt_sta0", Set_MonitorTarget0_Proc}, + {"mnt_sta1", Set_MonitorTarget1_Proc}, + {"mnt_sta2", Set_MonitorTarget2_Proc}, + {"mnt_sta3", Set_MonitorTarget3_Proc}, + {"mnt_sta4", Set_MonitorTarget4_Proc}, + {"mnt_sta5", Set_MonitorTarget5_Proc}, + {"mnt_sta6", Set_MonitorTarget6_Proc}, + {"mnt_sta7", Set_MonitorTarget7_Proc}, +#endif /* AIR_MONITOR */ +#ifdef MWDS + {"ApMWDS", Set_Ap_MWDS_Proc}, +#endif /* MWDS */ +#ifdef A4_CONN + {"APProxyStatus", Set_APProxy_Status_Show_Proc}, + {"APProxyRefresh", Set_APProxy_Refresh_Proc}, +#endif /* A4_CONN */ +#ifdef WH_EVENT_NOTIFIER + {"CustomOUI", SetCustomOUIProc}, + {"CustomVIE", SetCustomVIEProc}, + {"ChLoadDetectPeriod", SetChannelLoadDetectPeriodProc}, + {"StaRssiDetectThrd", SetStaRssiDetectThresholdProc}, + {"StaTxPktDetectPeriod", SetStaTxPktDetectPeriodProc}, + {"StaTxPktDetectThrd", SetStaTxPacketDetectThresholdProc}, + {"StaRxPktDetectPeriod", SetStaRxPktDetectPeriodProc}, + {"StaRxPktDetectThrd", SetStaRxPacketDetectThresholdProc}, +#endif /* WH_EVENT_NOTIFIER */ + {"SSID", Set_AP_SSID_Proc}, + {"SSIDSingle", Set_AP_SSIDSingle_Proc}, +#ifdef CONFIG_SNIFFER_SUPPORT + {"Monitor", Set_AP_Monitor_Proc}, +#endif /* CONFIG_SNIFFER_SUPPORT */ + {"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}, + {"MaxTxPwr", Set_MaxTxPwr_Proc}, + {"BGProtection", Set_BGProtection_Proc}, + {"DisableOLBC", Set_OLBCDetection_Proc}, + {"TxPreamble", Set_TxPreamble_Proc}, + {"RTSThreshold", Set_RTSThreshold_Proc}, + {"FragThreshold", Set_FragThreshold_Proc}, + {"TxBurst", Set_TxBurst_Proc}, + {"MaxStaNum", Set_AP_MaxStaNum_Proc}, +#ifdef RTMP_MAC_PCI + {"ShowRF", Set_ShowRF_Proc}, +#endif /* RTMP_MAC_PCI */ + {"IdleTimeout", Set_AP_IdleTimeout_Proc}, +#ifdef DOT11_N_SUPPORT + {"BASetup", Set_BASetup_Proc}, + {"BADecline", Set_BADecline_Proc}, + {"SendMIMOPS", Set_SendSMPSAction_Proc}, + {"BAOriTearDown", Set_BAOriTearDown_Proc}, + {"BARecTearDown", Set_BARecTearDown_Proc}, + {"HtBw", Set_HtBw_Proc}, + {"HtMcs", Set_HtMcs_Proc}, + {"HtGi", Set_HtGi_Proc}, + {"HtOpMode", Set_HtOpMode_Proc}, + {"HtStbc", Set_HtStbc_Proc}, + {"HtExtcha", Set_HtExtcha_Proc}, + {"HtMpduDensity", Set_HtMpduDensity_Proc}, + {"HtBaWinSize", Set_HtBaWinSize_Proc}, + {"HtMIMOPS", Set_HtMIMOPSmode_Proc}, + {"HtRdg", Set_HtRdg_Proc}, + {"HtLinkAdapt", Set_HtLinkAdapt_Proc}, + {"HtAmsdu", Set_HtAmsdu_Proc}, + {"HtAutoBa", Set_HtAutoBa_Proc}, + {"HtProtect", Set_HtProtect_Proc}, + {"HtMimoPs", Set_HtMimoPs_Proc}, + {"HtTxStream", Set_HtTxStream_Proc}, + {"HtRxStream", Set_HtRxStream_Proc}, + {"ForceShortGI", Set_ForceShortGI_Proc}, + {"ForceGF", Set_ForceGF_Proc}, + {"HtTxBASize", Set_HtTxBASize_Proc}, + {"BurstMode", Set_BurstMode_Proc}, +#ifdef GREENAP_SUPPORT + {"GreenAP", Set_GreenAP_Proc}, +#endif /* GREENAP_SUPPORT */ + {"HtDisallowTKIP", Set_HtDisallowTKIP_Proc}, +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + {"VhtBw", Set_VhtBw_Proc}, + {"VhtStbc", Set_VhtStbc_Proc}, + {"VhtBwSignal", set_VhtBwSignal_Proc}, + {"VhtDisallowNonVHT", Set_VhtDisallowNonVHT_Proc}, +#endif /* DOT11_VHT_AC */ + +#ifdef IAPP_SUPPORT + {"IappPID", Set_IappPID_Proc}, +#endif /* IAPP_SUPPORT */ + +#ifdef AGGREGATION_SUPPORT + {"PktAggregate", Set_PktAggregate_Proc}, +#endif /* AGGREGATION_SUPPORT */ + +#ifdef INF_PPA_SUPPORT + {"INF_AMAZON_SE_PPA", Set_INF_AMAZON_SE_PPA_Proc}, +#endif /* INF_PPA_SUPPORT */ + + {"WmmCapable", Set_AP_WmmCapable_Proc}, + + {"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}, + {"AuthModeSingle", Set_AP_AuthMode_Single_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 */ + {"AssocReqRssiThres", Set_AP_ASSOC_REQ_RSSI_THRESHOLD}, + {"KickStaRssiLow", Set_AP_KickStaRssiLow_Proc}, +#ifdef AP_SCAN_SUPPORT + {"SiteSurvey", Set_SiteSurvey_Proc}, + {"AutoChannelSel", Set_AutoChannelSel_Proc}, + {"ACSCheckTime", Set_AutoChannelSelCheckTime_Proc}, +#ifdef AP_PARTIAL_SCAN_SUPPORT + {"PartialScan", Set_PartialScan_Proc}, +#endif /* AP_PARTIAL_SCAN_SUPPORT */ +#ifdef NEIGHBORING_AP_STAT + {"CustomScanResult", Set_CustomScanResult_Proc}, +#endif +#endif /* AP_SCAN_SUPPORT */ + {"ResetCounter", Set_ResetStatCounter_Proc}, + {"DisConnectSta", Set_DisConnectSta_Proc}, + {"DisConnectAllSta", Set_DisConnectAllSta_Proc}, +#ifdef ACL_V2_SUPPORT + {"del_sta", Set_ACL_V2_DisConnectSta_Proc}, + {"fbt_delsta_vendor", Set_ACL_V2_DisConnectOUI_Proc}, + {"fbt_delsta_interval", Set_ACL_V2_EntryExpire_Proc}, +#endif /* ACL_V2_SUPPORT */ +#if defined(CONFIG_OWE_SUPPORT) || defined(DOT1X_SUPPORT) + {"PMKCachePeriod", Set_AP_PMKCachePeriod_Proc}, +#endif +#ifdef CONFIG_OWE_SUPPORT + {"vie_op", vie_oper_proc}, +#endif +#ifdef DOT1X_SUPPORT + {"IEEE8021X", Set_IEEE8021X_Proc}, + {"PreAuth", Set_PreAuth_Proc}, + {"own_ip_addr", Set_OwnIPAddr_Proc}, + {"EAPifname", Set_EAPIfName_Proc}, + {"PreAuthifname", Set_PreAuthIfName_Proc}, + {"RADIUS_Server", Set_RADIUS_Server_Proc}, + {"RADIUS_Port", Set_RADIUS_Port_Proc}, + {"RADIUS_Key", Set_RADIUS_Key_Proc}, +#endif /* DOT1X_SUPPORT */ +#ifdef DBG + {"Debug", Set_Debug_Proc}, + {"DebugFunc", Set_DebugFunc_Proc}, +#endif /* DBG */ + {"ApProbeRspTimes", Set_Ap_Probe_Rsp_Times}, +#ifdef FAST_DETECT_STA_OFF + {"flag_fast_detect_staoff", Set_FlagFastDetectStaOff_Proc}, +#endif +#ifdef MULTI_CLIENT_SUPPORT + {"ManualMultiClientOn", Set_ManualMultiClientOn_Proc}, + {"MultiClientCheckMode", Set_MultiClientOnMode_Proc}, + {"RtsRetryCnt", Set_RtsRetryCnt_Proc}, + {"MidRate", Set_MidRate_Proc}, + {"FarRate", Set_FarRate_Proc}, + {"FarDropRssi", Set_FarDropRssi_Proc}, + {"TxSwQLen", Set_TxSwQMaxLen_Proc}, + {"FalseCCAThreshold", Set_FalseCCARateTable_Proc}, + {"PingFixRate", Set_PingFixRate_Proc}, +#endif + +#if defined(DFS_SUPPORT) || defined(CARRIER_DETECTION_SUPPORT) + {"RadarShow", Set_RadarShow_Proc}, +#ifdef DFS_SUPPORT + {"RadarDebug", Set_RadarDebug_Proc}, + /*{"RadarHit", Set_RadarHit_Proc},*/ + {"CSPeriod", Set_CSPeriod_Proc}, + {"ResetRadarHwDetect", Set_ResetRadarHwDetect_Proc}, + {"DfsSwDisable", Set_DfsSwDisable_Proc}, + {"DfsEvDropAdjTime", Set_DfsEnvtDropAdjTime_Proc}, + {"RadarStart", Set_RadarStart_Proc}, + {"RadarStop", Set_RadarStop_Proc}, + {"RadarT1", Set_RadarSetTbl1_Proc}, + {"RadarT2", Set_RadarSetTbl2_Proc}, + {"PollTime", Set_PollTime_Proc}, + {"PrintBusyIdle", Set_PrintBusyIdle_Proc}, + {"BusyIdleRatio", Set_BusyIdleRatio_Proc}, + {"DfsRssiHigh", Set_DfsRssiHigh_Proc}, + {"DfsRssiLow", Set_DfsRssiLow_Proc}, + {"ChMovTime", Set_ChMovingTime_Proc}, + {"BlockChReset", Set_BlockChReset_Proc}, +#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 CONFIG_ATE + {"ATE", SetATE}, + {"ATEDA", SetATEDa}, + {"ATESA", SetATESa}, + {"ADCDump", SetADCDump}, + {"ATEBSSID", SetATEBssid}, + {"ATECHANNEL", SetATEChannel}, + {"ATEINITCHAN", SetATEInitChan}, +#ifdef RTMP_TEMPERATURE_CALIBRATION + {"ATETEMPCAL", SetATETempCal}, + {"ATESHOWTSSI", SetATEShowTssi}, +#endif /* RTMP_TEMPERATURE_CALIBRATION */ +#ifdef RTMP_INTERNAL_TX_ALC + {"ATETSSICBA", SetATETssiCalibration}, +#if defined(RT3350) || defined(RT3352) + {"ATETSSICALBRENABLE", RT335x_Set_ATE_TSSI_CALIBRATION_ENABLE_Proc}, +#endif /* defined(RT3350) || defined(RT3352) */ +#endif /* RTMP_INTERNAL_TX_ALC */ +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) + {"ATETSSICBAEX", SetATETssiCalibrationEx}, +#endif /* defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) */ + {"ATETXPOW0", SetATETxPower0}, + {"ATETXPOW1", SetATETxPower1}, +#ifdef DOT11N_SS3_SUPPORT + {"ATETXPOW2", SetATETxPower2}, +#endif /* DOT11N_SS3_SUPPORT */ + {"ATETXPOWEVAL", SetATETxPowerEvaluation}, + {"ATETXANT", SetATETxAntenna}, + {"ATERXANT", SetATERxAntenna}, +#ifdef RT3350 + {"ATEPABIAS", SetATEPABias}, +#endif /* RT3350 */ + {"ATETXFREQOFFSET", SetATETxFreqOffset}, + {"ATETXBW", SetATETxBw}, + {"ATETXLEN", SetATETxLength}, + {"ATETXCNT", SetATETxCount}, + {"ATETXMCS", SetATETxMcs}, + {"ATETXSTBC", SetATETxStbc}, + {"ATETXMODE", SetATETxMode}, + {"ATETXGI", SetATETxGi}, + {"ATERXFER", SetATERxFer}, + {"ATERRF", SetATEReadRF}, +#if (!defined(RTMP_RF_RW_SUPPORT)) && (!defined(RLT_RF)) + {"ATEWRF1", SetATEWriteRF1}, + {"ATEWRF2", SetATEWriteRF2}, + {"ATEWRF3", SetATEWriteRF3}, + {"ATEWRF4", SetATEWriteRF4}, +#endif /* (!defined(RTMP_RF_RW_SUPPORT)) && (!defined(RLT_RF)) */ + {"ATELDE2P", SetATELoadE2p}, + {"ATERE2P", SetATEReadE2p}, +#ifdef LED_CONTROL_SUPPORT +#endif /* LED_CONTROL_SUPPORT */ + {"ATEAUTOALC", SetATEAutoAlc}, + {"ATETEMPSENSOR", SetATETempSensor}, + {"ATEIPG", SetATEIpg}, + {"ATEPAYLOAD", SetATEPayload}, + {"ATEFIXEDPAYLOAD", SetATEFixedPayload}, + {"ATETTR", SetATETtr}, + {"ATESHOW", SetATEShow}, + {"ATEHELP", SetATEHelp}, +#ifdef CONFIG_QA + {"TxStop", SetTxStop}, + {"RxStop", SetRxStop}, +#ifdef DBG + {"EERead", SetEERead}, + {"EEWrite", SetEEWrite}, + {"BBPRead", SetBBPRead}, + {"BBPWrite", SetBBPWrite}, +#endif /* DBG */ +#endif /* CONFIG_QA */ +#endif /* CONFIG_ATE */ + +#ifdef APCLI_SUPPORT + {"ApCliEnable", Set_ApCli_Enable_Proc}, + {"ApCliSsid", Set_ApCli_Ssid_Proc}, + {"ApCliUniCodeSsid", Set_ApCli_UniCode_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}, + {"ApCliCertEnable", Set_ApCli_Cert_Enable_Proc}, +#ifdef WH_EZ_SETUP + {"ApCliHideSSID", Set_ApCli_Hide_Ssid_Proc}, +#endif +#ifdef APCLI_AUTO_CONNECT_SUPPORT + {"ApCliAutoConnect", Set_ApCli_AutoConnect_Proc}, +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT + {"MACRepeaterEn", Set_ReptMode_Enable_Proc}, + {"MACBaSnResetDis", Set_BaSnReset_Disable_Proc}, + {"MACRepeaterOuiMode", Set_ReptOUIMode_Proc}, + {"MACReptAddEntry", Set_MACReptAddEntry_Proc}, + {"MACReptShowAll", Set_MACReptMACShowAll_Proc}, +#endif /* MAC_REPEATER_SUPPORT */ +#ifdef MWDS + {"ApCliMWDS", Set_ApCli_MWDS_Proc}, +#endif /* MWDS */ +#ifdef WSC_AP_SUPPORT + {"ApCliWscSsid", Set_AP_WscSsid_Proc}, + {"ApCliWscScanMode", Set_ApCli_WscScanMode_Proc}, +#endif /* WSC_AP_SUPPORT */ +#ifdef ROAMING_ENHANCE_SUPPORT + {"RoamingEnhance", Set_RoamingEnhance_Enable_Proc}, +#endif /* ROAMING_ENHANCE_SUPPORT */ +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef APCLI_CERT_SUPPORT + /*Add for APCLI PMF 5.3.3.3 option test item. (Only Tx De-auth Req. and make sure the pkt can be Encrypted)*/ + {"ApCliTxDeAuth", ApCliTxDeAuth}, +#endif /* APCLI_CERT_SUPPORT */ +#ifdef DOT11W_PMF_SUPPORT + {"ApCliPMFMFPC", Set_ApCliPMFMFPC_Proc}, + {"ApCliPMFMFPR", Set_ApCliPMFMFPR_Proc}, + {"ApCliPMFSHA256", Set_ApCliPMFSHA256_Proc}, +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ +#ifdef APCLI_SAE_SUPPORT + {"ApCliSAEGroup", set_apcli_sae_group_proc}, +#endif /* APCLI_SAE_SUPPORT */ +#ifdef APCLI_OWE_SUPPORT + {"ApCliOWEGroup", set_apcli_owe_group_proc}, +#endif /* APCLI_SAE_SUPPORT */ +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + {"ApCliDelPMKIDList", set_apcli_del_pmkid_list}, +#endif /* defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) */ +#endif /* APCLI_SUPPORT */ +#ifdef CONFIG_RA_HW_NAT_WIFI_NEW_ARCH + {"hw_nat_register", set_hnat_register}, +#endif /* (CONFIG_RA_HW_NAT_WIFI_NEW_ARCH) */ +#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}, + {"WscSetupLock", Set_WscSetupLock_Proc}, +#ifdef WSC_V2_SUPPORT + {"WscV2Support", Set_WscV2Support_Proc}, + {"WscVersion2", Set_WscVersion2_Proc}, + {"WscExtraTlvTag", Set_WscExtraTlvTag_Proc}, + {"WscExtraTlvType", Set_WscExtraTlvType_Proc}, + {"WscExtraTlvData", Set_WscExtraTlvData_Proc}, + {"WscFragment", Set_WscFragment_Proc}, + {"WscFragmentSize", Set_WscFragmentSize_Proc}, +#endif /* WSC_V2_SUPPORT */ + {"WscMaxPinAttack", Set_WscMaxPinAttack_Proc}, + {"WscSetupLockTime", Set_WscSetupLockTime_Proc}, +#ifdef WSC_NFC_SUPPORT + {"NfcStatus", Set_NfcStatus_Proc}, + {"NfcPasswdToken", Set_NfcPasswdToken_Proc}, + {"NfcConfigToken", Set_NfcConfigurationToken_Proc}, + {"DoWpsByNFC", Set_DoWpsByNFC_Proc}, + {"NfcRegenPK", Set_NfcRegenPK_Proc}, /* For NFC negative test */ +#endif /* WSC_NFC_SUPPORT */ + {"WscAutoTriggerDisable", Set_WscAutoTriggerDisable_Proc}, +#endif /* WSC_AP_SUPPORT */ +#ifdef UAPSD_SUPPORT + {"UAPSDCapable", Set_UAPSD_Proc}, +#endif /* UAPSD_SUPPORT */ +#ifdef IGMP_SNOOP_SUPPORT + {"IgmpSnEnable", Set_IgmpSn_Enable_Proc}, + {"IgmpAdd", Set_IgmpSn_AddEntry_Proc}, + {"IgmpDel", Set_IgmpSn_DelEntry_Proc}, +#endif /* IGMP_SNOOP_SUPPORT */ + +#ifdef PREVENT_ARP_SPOOFING + {"ArpSpoofChk", Set_ARPSpoofChk_Enable_Proc}, +#endif /* PREVENT_ARP_SPOOFING */ + +#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 VHT_TXBF_SUPPORT + {"VhtNDPA", Set_VhtNDPA_Sounding_Proc}, +#endif /* VHT_TXBF_SUPPORT */ + +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) + {"wf_fwd", Set_WifiFwd_Proc}, +#if (MT7615_MT7603_COMBO_FORWARDING == 1) + {"wf_fwd_down", Set_WifiFwd_Down}, + {"wf_fwd_bpdu", Set_WifiFwdBpdu_Proc}, +#endif + {"wf_fwd_acs", Set_WifiFwdAccessSchedule_Proc}, + {"wf_fwd_hij", Set_WifiFwdHijack_Proc}, + {"wf_fwd_rep", Set_WifiFwdRepDevice}, + {"wf_fwd_show", Set_WifiFwdShowEntry}, + {"wf_fwd_del", Set_WifiFwdDeleteEntry}, + {"pkt_src_show", Set_PacketSourceShowEntry}, + {"pkt_src_del", Set_PacketSourceDeleteEntry}, +#endif /* CONFIG_WIFI_PKT_FWD */ + + +#ifdef PRE_ANT_SWITCH + {"PreAntSwitch", Set_PreAntSwitch_Proc}, + {"PreAntSwitchRSSI", Set_PreAntSwitchRSSI_Proc}, + {"PreAntSwitchTimeout", Set_PreAntSwitchTimeout_Proc}, +#endif /* PRE_ANT_SWITCH */ + +#ifdef MT_MAC +#ifdef DBG + {"FixedRate", Set_Fixed_Rate_Proc}, +#endif /* DBG */ +#endif /* MT_MAC */ +#ifdef ANTI_INTERFERENCE_SUPPORT + {"DynamicRaInterval", Set_DynamicRaInterval}, + {"SwiftTrainThrd", Set_SwiftTrainThrd}, +#endif /* ANTI_INTERFERENCE_SUPPORT */ + +#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}, + {"diag_cond", Set_diag_cond_Proc}, +#endif /* DBG_DIAGNOSE */ +#endif /* RTMP_MAC_PCI */ + + {"MeasureReq", Set_MeasureReq_Proc}, + {"TpcReq", Set_TpcReq_Proc}, + {"PwrConstraint", Set_PwrConstraint}, +#ifdef DOT11K_RRM_SUPPORT + {"BcnReq", Set_BeaconReq_Proc}, + {"BcnReqRandInt", Set_BeaconReq_RandInt_Proc}, + {"LinkReq", Set_LinkMeasureReq_Proc}, + {"RrmEnable", Set_Dot11kRRM_Enable_Proc}, + {"TxReq", Set_TxStreamMeasureReq_Proc}, + + + /* only for selftesting and debugging. */ + {"rrm", Set_RRM_Selftest_Proc}, + {"RegDomain", Set_Reg_Domain_Proc}, +#endif /* DOT11K_RRM_SUPPORT */ +#ifdef DOT11V_WNM_SUPPORT +/* {"WnmMaxIdlePeriod", Set_WnmMaxIdlePeriod_Proc}, */ + {"WNMTransMantREQ", Set_WNMTransMantREQ_Proc}, + {"APWNMDMSShow", Set_APWNMDMSShow_Proc}, +#endif /* DOT11V_WNM_SUPPORT */ +#ifdef DOT11N_DRAFT3 + {"OBSSScanParam", Set_OBSSScanParam_Proc}, + {"AP2040Rescan", Set_AP2040ReScan_Proc}, + {"HtBssCoex", Set_HT_BssCoex_Proc}, + {"HtBssCoexApCntThr", Set_HT_BssCoexApCntThr_Proc}, +#endif /* DOT11N_DRAFT3 */ + {"EntryLifeCheck", Set_EntryLifeCheck_Proc}, +#ifdef DOT11R_FT_SUPPORT + {"ft", FT_Ioctl}, + {"ftenable", Set_FT_Enable}, + {"ftmdid", Set_FT_Mdid}, + {"ftr0khid", Set_FT_R0khid}, + {"ftric", Set_FT_RIC}, + {"ftotd", Set_FT_OTD}, +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef RTMP_EFUSE_SUPPORT + {"efuseLoadFromBin", set_eFuseLoadFromBin_Proc}, /* For backward compatible, the usage is the same as bufferLoadFromBin + bufferWriteBack */ + {"efuseFreeNumber", set_eFuseGetFreeBlockCount_Proc}, + {"efuseDump", set_eFusedump_Proc}, +#ifdef CONFIG_ATE + {"bufferLoadFromEfuse", Set_LoadEepromBufferFromEfuse_Proc}, +#ifdef BB_SOC + {"efuseBufferModeWriteBack", set_BinModeWriteBack_Proc}, +#else + {"efuseBufferModeWriteBack", set_eFuseBufferModeWriteBack_Proc}, /* For backward compatible, the usage is the same as bufferWriteBack */ +#endif +#endif /* CONFIG_ATE */ +#endif /* RTMP_EFUSE_SUPPORT */ + {"bufferLoadFromBin", Set_LoadEepromBufferFromBin_Proc}, + {"bufferWriteBack", Set_EepromBufferWriteBack_Proc}, + + + + +#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}, + +#ifdef THERMAL_PROTECT_SUPPORT + {"tpc", set_thermal_protection_criteria_proc}, +#endif /* THERMAL_PROTECT_SUPPORT */ + + + {"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 AIRPLAY_SUPPORT + {"airplayEnable", Set_Airplay_Enable}, +#endif /* AIRPLAY_SUPPORT*/ + + {"VcoPeriod", Set_VcoPeriod_Proc}, +#ifdef CONFIG_SNIFFER_SUPPORT + {"MonitorMode", Set_MonitorMode_Proc}, +#endif /* CONFIG_SNIFFER_SUPPORT */ +#ifdef SINGLE_SKU + {"ModuleTxpower", Set_ModuleTxpower_Proc}, +#endif /* SINGLE_SKU */ + + +#ifdef DOT11W_PMF_SUPPORT + {"PMFMFPC", Set_PMFMFPC_Proc}, + {"PMFMFPR", Set_PMFMFPR_Proc}, + {"PMFSHA256", Set_PMFSHA256_Proc}, +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef MICROWAVE_OVEN_SUPPORT + {"MO_FalseCCATh", Set_MO_FalseCCATh_Proc}, +#endif /* MICROWAVE_OVEN_SUPPORT */ + +#ifdef CONFIG_FPGA_MODE + {"fpga_on", set_fpga_mode}, /* 1 = manual mode, 2 = fix phy/mode/rate/mcs */ + {"dataphy", set_data_phy_mode}, /* 0 = CCK, 1 = OFDM, 2 = MODE_HTMIX, 3 = HT-GF, 4 = VHT */ + {"databw", set_data_bw}, /* 0 = 20M, 1 = 40M, 2 = 80M */ + {"datamcs", set_data_mcs}, /* 0~ 15 */ + {"databasize", set_data_basize}, + {"datagi", set_data_gi}, + {"dataldpc", set_data_ldpc}, + {"txcnt", set_tx_kickcnt}, + {"stop_tr", set_tr_stop}, + {"vco_cal", set_vco_cal}, + +#ifdef MT_MAC + {"txs_type", set_txs_report_type}, + {"no_bcn", set_no_bcn}, +#endif /* MT_MAC */ + +#ifdef CAPTURE_MODE + {"cap_start", set_cap_start}, + {"cap_trigger", set_cap_trigger}, + {"cap_dump", set_cap_dump}, +#endif /* CAPTURE_MODE */ +#endif /* CONFIG_FPGA_MODE */ + +#if defined(WFA_VHT_PF) || defined(MT7603_FPGA) || defined(MT7628_FPGA) + {"force_amsdu", set_force_amsdu}, +#endif /* defined(WFA_VHT_PF) || defined(MT7603_FPGA) */ + +#ifdef WFA_VHT_PF + {"nss_mcs_opt", set_vht_nss_mcs_opt}, // SIGMA + {"opt_md_notif_ie", set_vht_opmode_notify_ie}, // SIGMA + {"force_op", set_force_operating_mode}, + {"force_noack", set_force_noack}, + {"force_vht_sgi", set_force_vht_sgi}, + {"force_vht_stbc", set_force_vht_tx_stbc}, + {"ext_cca", set_force_ext_cca}, +#endif /* WFA_VHT_PF */ + {"rf", SetRF}, + {"tssi_enable", set_tssi_enable}, +#ifdef RLT_MAC +#ifdef CONFIG_WIFI_TEST + {"pbf_loopback", set_pbf_loopback}, + {"pbf_rx_drop", set_pbf_rx_drop}, +#endif +#endif +#ifdef DYNAMIC_VGA_SUPPORT + {"DyncVgaEnable", Set_DyncVgaEnable_Proc}, + {"fc_hth", set_false_cca_hi_th}, + {"fc_lth", set_false_cca_low_th}, +#endif /* DYNAMIC_VGA_SUPPORT */ +#ifdef MT_MAC + {"TimEnable", Set_AP_TimEnable_Proc},//only for development purpose!! iwpriv ra0 set + {"TmrEnable", setApTmrEnableProc},//0: disalbe, 1: initialiter, 2: responser. + {"get_fid", set_get_fid}, + {"fwlog", set_fw_log}, +#ifdef DYNAMIC_WMM + {"dynamic_wmm", SetDynamicWMM}, +#endif /* DYNAMIC_WMM */ +#ifdef INTERFERENCE_RA_SUPPORT + {"interfra", SetInterfRA}, +#endif + {"manual_txop", SetManualTxOP}, + {"manual_txop_thld", SetManualTxOPThreshold}, + {"manual_txop_upbound", SetManualTxOPUpBound}, + {"manual_txop_lowbound", SetManualTxOPLowBound}, +#ifdef DBG + {"DumpTime", Set_AP_DumpTime_Proc},//only for development purpose!! iwpriv ra0 set + {"BcnStateCtrl", Set_BcnStateCtrl_Proc},//only for development purpose!! iwpriv ra0 set +#endif +#ifdef LED_CONTROL_SUPPORT + {"MT7603LED", Set_MT7603LED_Proc}, + {"MT7603LEDEnhance", Set_MT7603LED_Enhance_Proc}, + {"MT7603LEDBehavior", Set_MT7603LED_Behavor_Proc}, +#endif /* LED_CONTROL_SUPPORT */ +#ifdef RTMP_MAC_PCI + {"pdma_dbg", Set_PDMAWatchDog_Proc}, + {"pse_dbg", SetPSEWatchDog_Proc}, +#endif + +#ifdef TXRXCR_DEBUG_SUPPORT + {"tr_cr_dbg", SetTxRxCr_Proc}, +#endif /* TXRXCR_DEBUG_SUPPORT */ + + {"get_thermal_sensor", Set_themal_sensor}, + {"rx_pspoll_filter", Set_rx_pspoll_filter_proc}, +#endif +#ifdef SINGLE_SKU_V2 + {"SKUEnable", SetSKUEnable_Proc}, +#endif /* SINGLE_SKU_V2 */ +#ifdef SNIFFER_MIB_CMD + {"exsta", exsta_proc}, //add the MAC want to sniffer + {"exsta_list", exsta_list_proc}, // show the MAC's want to sniffer + {"exsta_clear", exsta_clear_proc}, //clear all tje MAC's want to sniffer + {"exstascan", exsta_scan_proc}, //trigger sniffer + + {"set_mib_passive_scan", set_mib_passive_scan_proc}, //select the scan type, 0 => uknown, 1 => passive, 2 => active + {"set_mib_scan_interval", set_mib_scan_interval_proc}, //set the listen interval , unit : ms + {"set_mib_scan_scope", set_mib_scan_scope_proc}, // 0 => all channel (no need to implement), 1 => dedicate channel + {"set_mib_scan_channel", set_mib_scan_channel_proc}, // set the channel to listen +#endif /* SNIFFER_MIB_CMD */ + + {"ed_chk", Set_ed_chk_proc}, +#ifdef DBG + {"ed_stat", show_ed_stat_proc}, +#endif /* DBG */ +#ifdef BAND_STEERING + {"BndStrgEnable", Set_BndStrg_Enable}, + {"BndStrgBssIdx", Set_BndStrg_BssIdx}, + {"BndStrgParam", Set_BndStrg_Param}, +#ifdef BND_STRG_DBG + {"BndStrgMntAddr", Set_BndStrg_MonitorAddr}, +#endif /* BND_STRG_DBG */ +#endif /* BAND_STEERING */ +#ifdef SMART_CARRIER_SENSE_SUPPORT + {"SCSEnable", SetSCSEnable_Proc}, + {"SCSCfg", SetSCSCfg_Proc}, +#endif /* SMART_CARRIER_SENSE_SUPPORT */ + +#ifdef SW_ATF_SUPPORT + {"goodNodePara", SetGoodNodePara_Proc}, + {"badNodePara", SetBadNodePara_Proc}, + {"badNodeMinDeqCnt", SetBadNodeMinDeq_Proc}, + {"txThr", SetTxThr_Proc}, + {"fixAtfPara", SetFixAtfPara_Proc}, + {"dropDelta", SetAtfDropDelta_Proc}, + {"atfFalseCCAThr", SetAtfFalseCCAThr_Proc}, +#endif + + {"ping_log", set_ping_log_proc}, +#ifdef DATA_QUEUE_RESERVE + {"queue_rsv", set_queue_rsv_proc}, + {"dumpon", set_dump_on_proc}, + {"rsv_cnt_clear", set_rsv_cnt_clear_proc}, +#endif /* DATA_QUEUE_RESERVE */ + {"SendBMToAir", Set_SendBMToAir_Proc}, +#if defined(MAX_CONTINUOUS_TX_CNT) || defined(NEW_IXIA_METHOD) + {"TxSwqCtrl",Set_TxSwqCtrl_Proc}, + {"RssiTh",Set_Rssi_Threshold_Proc}, + {"ForceTxCnt",Set_ContinousTxCnt_Proc}, + {"RateTh",Set_Rate_Threshold_Proc}, +#endif + {"set_lower_mcs", set_lower_mcs_proc}, + {"set_higher_mcs", set_higher_mcs_proc}, +#ifdef CONFIG_PUSH_SUPPORT + {"ez_set_ssid_psk", Set_EasySetup_ssid_psk_proc}, +// {"ez_set_ftmdid", Set_EasySetup_Ftmdid_proc}, +#endif +#ifdef WH_EZ_SETUP + {"ez_rssi_threshold", Set_EasySetup_RssiThreshold_Proc}, +#ifdef EZ_NETWORK_MERGE_SUPPORT + {"ez_merge_group", set_EasySetup_MergeGroup_proc}, +#endif +#ifdef EZ_API_SUPPORT + {"ez_api_mode", set_EasySetup_Api_Mode}, +#endif +#ifdef NEW_CONNECTION_ALGO + {"ez_apcli_force_ssid", Set_EasySetup_ForceSsid_Proc}, + {"ez_apcli_force_bssid", Set_EasySetup_ForceBssid_Proc}, +// {"ez_apcli_force_channel", Set_EasySetup_ForceChannel_Proc}, + {"ez_open_group_id", Set_EasySetup_Open_GenGroupID_Proc}, + {"ez_connection_allow_all", Set_ez_connection_allow_all}, + +#endif +#ifdef EZ_ROAM_SUPPORT + {"ez_apcli_roam_bssid", Set_EasySetup_RoamBssid_Proc}, +#endif +#ifdef EZ_DUAL_BAND_SUPPORT +// {"ez_test_loop_pkt_send", Set_EasySetup_LoopPktSend}, +#endif + {"ez_max_scan_delay", Set_EasySetup_MaxScanDelay}, + {"ezstart", Set_EasySetup_Start_Proc}, + {"ez_debug", Set_EasySetup_Debug_Proc}, + {"ez_roam_time", Set_EasySetup_RoamTime_Proc}, + {"ez_best_ap_rssi", Set_EasySetup_Best_Ap_RSSI_Threshold}, + {"ez_delay_disconnect_count", Set_EasySetup_Delay_Disconnect_Count_Proc}, + {"ez_wait_for_info_transfer", Set_EasySetup_Wait_For_Info_Transfer_Proc}, + {"ez_wdl_missing_time", Set_EasySetup_WDL_Missing_Time_Proc}, + {"ez_force_connect_bssid_time", Set_EasySetup_Force_Connect_Bssid_Time_Proc}, + {"ez_peer_entry_age_out_time", Set_EasySetup_Peer_Entry_Age_Out_time_Proc}, + {"ez_scan_same_channel_time", Set_EasySetup_Scan_Same_Channel_Time_Proc}, + {"ez_scan_partial_scan_time", Set_EasySetup_Partial_Scan_Time_Proc}, + {"ez_set_ssid_psk", Set_EasySetup_ssid_psk_proc}, + {"ez_conf_ssid_psk", Set_EasySetup_conf_ssid_psk_proc}, +// {"ez_nonman_info", Set_EasySetup_nonman_proc}, + {"ez_send_broadcast_deauth", ez_send_broadcast_deauth_proc}, + +#ifdef EZ_PUSH_BW_SUPPORT + {"ez_push_bw_config", Set_EasySetup_BWPushConfig}, +#endif +#endif /* WH_EZ_SETUP */ +#ifdef STA_FORCE_ROAM_SUPPORT + {"force_roam_enable", Set_FroamEn}, + {"froam_sta_low_rssi_trigger", Set_FroamStaLowRssi}, + {"froam_sta_low_rssi_renotify", Set_FroamStaLowRssiRenotify}, + {"froam_sta_ageout_time", Set_FroamStaAgeTime}, + {"froam_mntr_ageout_time", Set_FroamMntrAgeTime}, + {"froam_mntr_min_pkt_count", Set_FroamMntrMinPktCount}, + {"froam_mntr_min_time", Set_FroamMntrMinTime}, + {"froam_mntr_avg_rssi_pkt_count", Set_FroamMntrRssiPktCount}, + {"froam_sta_good_rssi", Set_FroamStaGoodRssi}, + {"froam_acl_ageout_time", Set_FroamAclAgeTime}, + {"froam_acl_hold_time", Set_FroamAclHoldTime}, +#endif +#ifdef NEW_IXIA_METHOD + {"fcont", force_connect_Proc}, + {"chkt", Set_chkT_Proc}, + {"pkthd", Set_pkt_threshld_Proc}, + {"pktlendct", Set_statistic_pktlen_Proc}, + {"protectset", set_Protection_Parameter_Set_proc}, +#endif +#ifdef MBO_SUPPORT + {"mbo_nr", SetMboNRIndicateProc}, +#endif/* MBO_SUPPORT */ +#ifdef MIXMODE_SUPPORT + {"enter_mixmode", SetMixMode_Proc}, +#endif /* MIXMODE_SUPPORT */ + {NULL,} +}; + + +static struct { + RTMP_STRING *name; + INT (*set_proc)(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +} *PRTMP_PRIVATE_SHOW_PROC, RTMP_PRIVATE_SHOW_SUPPORT_PROC[] = { +#ifdef ACL_BLK_COUNT_SUPPORT + {"ACLRejectCount", Show_ACLRejectCount_Proc}, +#endif/*ACL_BLK_COUNT_SUPPORT*/ +#ifdef DBG + {"stainfo", Show_MacTable_Proc}, + {"StationKeepAlive", Show_StationKeepAliveTime_Proc}, +#ifdef MT_MAC + {"psinfo", Show_PSTable_Proc}, + {"wtbl", show_wtbl_proc}, + {"mibinfo", show_mib_proc}, + {"tmacinfo", ShowTmacInfo}, + {"agginfo", ShowAggInfo}, + {"manual_txop", ShowManualTxOP}, + {"pseinfo", ShowPseInfo}, + {"psedata", ShowPseData}, +#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT) + {"dschinfo", ShowDMASchInfo}, +#endif +#endif /* MT_MAC */ + {"sta_tr", Show_sta_tr_proc}, + {"peerinfo", show_stainfo_proc}, + {"stacountinfo", Show_StaCount_Proc}, + {"stasecinfo", Show_StaSecurityInfo_Proc}, + {"descinfo", Show_DescInfo_Proc}, + {"driverinfo", Show_DriverInfo_Proc}, + {"apcfginfo", show_apcfg_info}, + {"devinfo", show_devinfo_proc}, + {"sysinfo", show_sysinfo_proc}, + {"trinfo", show_trinfo_proc}, + {"pwrinfo", show_pwr_info}, + {"txqinfo", show_txqinfo_proc}, +#ifdef MULTI_CLIENT_SUPPORT + {"configinfo", show_configinfo_proc}, +#endif +#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 RTMP_MAC_PCI +#ifdef DBG_DIAGNOSE + {"diag", Show_Diag_Proc}, +#endif /* DBG_DIAGNOSE */ +#endif /* RTMP_MAC_PCI */ + {"stat_reset", Show_Sat_Reset_Proc}, +#ifdef IGMP_SNOOP_SUPPORT + {"igmpinfo", Set_IgmpSn_TabDisplay_Proc}, +#endif /* IGMP_SNOOP_SUPPORT */ + +#ifdef PREVENT_ARP_SPOOFING + {"arpspoofchk", Show_ARPSpoofChk_Enable_Proc}, +#endif /* PREVENT_ARP_SPOOFING */ + +#ifdef MCAST_RATE_SPECIFIC + {"mcastrate", Show_McastRate}, +#endif /* MCAST_RATE_SPECIFIC */ +#ifdef MAT_SUPPORT + {"matinfo", Show_MATTable_Proc}, +#endif /* MAT_SUPPORT */ +#ifdef DFS_SUPPORT + {"blockch", Show_BlockCh_Proc}, +#endif /* DFS_SUPPORT */ +#ifdef DOT11R_FT_SUPPORT + {"ftinfo", Show_FTConfig_Proc}, +#endif /* DOT11R_FT_SUPPORT */ +#ifdef DOT11K_RRM_SUPPORT + {"rrminfo", RRM_InfoDisplay_Proc}, +#endif /* DOT11K_RRM_SUPPORT */ +#ifdef AP_QLOAD_SUPPORT + {"qload", Show_QoSLoad_Proc}, +#endif /* AP_QLOAD_SUPPORT */ +#ifdef APCLI_SUPPORT + {"connStatus", RTMPIoctlConnStatus}, +#endif /* APCLI_SUPPORT */ +#ifdef MAC_REPEATER_SUPPORT + {"reptinfo", Show_Repeater_Cli_Proc}, +#endif /* MAC_REPEATER_SUPPORT */ + + {"rainfo", Show_RAInfo_Proc}, + +#ifdef MBSS_SUPPORT + {"mbss", Show_MbssInfo_Display_Proc}, +#endif /* MBSS_SUPPORT */ +#ifdef WSC_AP_SUPPORT + {"WscPeerList", WscApShowPeerList}, +#ifdef WSC_NFC_SUPPORT + {"NfcStatus", Get_NfcStatus_Proc}, +#endif /* WSC_NFC_SUPPORT */ +#ifdef ACL_V2_SUPPORT + {"del_sta", Show_ACL_V2_STAEntry_Proc}, + {"fbt_delsta_vendor", Show_ACL_V2_OUI_Proc}, + {"fbt_delsta_interval", Show_ACL_V2_EntryExpire_Proc}, +#endif /* ACL_V2_SUPPORT */ +#endif /* WSC_AP_SUPPORT */ + {"bbpinfo", ShowBBPInfo}, +#ifdef SMART_CARRIER_SENSE_SUPPORT + {"SCSInfo", ShowSCSInfo}, +#endif /* SMART_CARRIER_SENSE_SUPPORT */ +#endif /* DBG */ +#ifdef BAND_STEERING + {"BndStrgList", Show_BndStrg_List}, + {"BndStrgInfo", Show_BndStrg_Info}, +#ifdef VENDOR_FEATURE5_SUPPORT + {"BndStrgNvramtable", Show_BndStrg_NvramTable}, +#endif /* VENDOR_FEATURE5_SUPPORT */ +#endif /* BAND_STEERING */ +#ifdef MAX_CONTINUOUS_TX_CNT + {"TxSwqInfo", Show_TxSwqInfo_Proc}, +#endif + {"set_lower_mcs", Show_lower_mcs_proc}, + {"set_higher_mcs", Show_higher_mcs_proc}, +#ifdef WH_EZ_SETUP + {"ez_info", Show_EasySetupInfo_Proc}, +#endif /* WH_EZ_SETUP */ +#ifdef MBO_SUPPORT + {"mbo", ShowMboStatProc}, +#endif/* MBO_SUPPORT */ +#ifdef MIXMODE_SUPPORT + {"mixmode", ShowMixModeProc}, + {"get_mac_table_structure", GetMacTableStaInfo_Proc}, + {"cancel_mixmode", MixModeCancel_Proc}, + {"get_mixmode_rssi", GetMixModeRssi_Proc}, +#endif /* MIXMODE_SUPPORT */ +#ifdef DOT11_SAE_SUPPORT + {"saeinfo", show_sae_info_proc}, +#endif + {"l1profile", ShowL1profile}, + {NULL,} +}; + + +INT RTMPAPPrivIoctlSet( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *pIoctlCmdStr) +{ + RTMP_STRING *this_char, *value; + INT Status = NDIS_STATUS_SUCCESS; + + while ((this_char = strsep((char **)&pIoctlCmdStr->u.data.pointer, ",")) != NULL) + { + if (!*this_char) + continue; + + if ((value = strchr(this_char, '=')) != NULL) + *value++ = 0; + + if (!value +#ifdef WSC_AP_SUPPORT + && ( + (strcmp(this_char, "WscStop") != 0) && +#ifdef BB_SOC + (strcmp(this_char, "WscResetPinCode") != 0) && +#endif + (strcmp(this_char, "WscGenPinCode")!= 0) + ) +#endif /* WSC_AP_SUPPORT */ + ) + continue; + + for (PRTMP_PRIVATE_SET_PROC = RTMP_PRIVATE_SUPPORT_PROC; PRTMP_PRIVATE_SET_PROC->name; PRTMP_PRIVATE_SET_PROC++) + { + if (!strcmp(this_char, PRTMP_PRIVATE_SET_PROC->name)) + { + if(!PRTMP_PRIVATE_SET_PROC->set_proc(pAd, value)) + { /*FALSE:Set private failed then return Invalid argument */ + Status = -EINVAL; + } + break; /*Exit for loop. */ + } + } + + if(PRTMP_PRIVATE_SET_PROC->name == NULL) + { /*Not found argument */ + Status = -EINVAL; + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::(iwpriv) Command not Support [%s=%s]\n", this_char, value)); + break; + } + } + + return Status; +} + + +INT RTMPAPPrivIoctlShow( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *pIoctlCmdStr) +{ + RTMP_STRING *this_char, *value = NULL; + INT Status = NDIS_STATUS_SUCCESS; + + while ((this_char = strsep((char **)&pIoctlCmdStr->u.data.pointer, ",")) != NULL) + { + if (!*this_char) + continue; + + value = strchr(this_char, '='); + if (value) { + if (strlen(value) > 1) { + *value=0; + value++; + } else + value = NULL; + } + + 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; + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::(iwpriv) Command not Support [%s=%s]\n", this_char, value)); + break; + } + } + + return Status; + +} + +#if defined(INF_AR9) || defined(BB_SOC) +#if defined(AR9_MAPI_SUPPORT) || defined(BB_SOC) +INT RTMPAPPrivIoctlAR9Show( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *pIoctlCmdStr) +{ + INT Status = NDIS_STATUS_SUCCESS; + + if(!strcmp(pIoctlCmdStr->u.data.pointer, "get_mac_table")) + { + RTMPAR9IoctlGetMacTable(pAd,pIoctlCmdStr); + } + else if(!strcmp(pIoctlCmdStr->u.data.pointer, "get_stat2")) + { + RTMPIoctlGetSTAT2(pAd,pIoctlCmdStr); + } + else if(!strcmp(pIoctlCmdStr->u.data.pointer, "get_radio_dyn_info")) + { + RTMPIoctlGetRadioDynInfo(pAd,pIoctlCmdStr); + } +#ifdef WSC_AP_SUPPORT + else if(!strcmp(pIoctlCmdStr->u.data.pointer, "get_wsc_profile")) + { + RTMPAR9IoctlWscProfile(pAd,pIoctlCmdStr); + } + else if(!strcmp(pIoctlCmdStr->u.data.pointer, "get_wsc_pincode")) + { + RTMPIoctlWscPINCode(pAd,pIoctlCmdStr); + } + else if(!strcmp(pIoctlCmdStr->u.data.pointer, "get_wsc_status")) + { + RTMPIoctlWscStatus(pAd,pIoctlCmdStr); + } + else if(!strcmp(pIoctlCmdStr->u.data.pointer, "get_wps_dyn_info")) + { + RTMPIoctlGetWscDynInfo(pAd,pIoctlCmdStr); + } + else if(!strcmp(pIoctlCmdStr->u.data.pointer, "get_wps_regs_dyn_info")) + { + RTMPIoctlGetWscRegsDynInfo(pAd,pIoctlCmdStr); + } +#endif + return Status; +} +#endif /*AR9_MAPI_SUPPORT*/ +#endif/*AR9_INF*/ + +INT RTMPAPSetInformation( + IN PRTMP_ADAPTER pAd, + INOUT RTMP_IOCTL_INPUT_STRUCT *rq, + IN INT cmd) +{ + RTMP_IOCTL_INPUT_STRUCT *wrq = (RTMP_IOCTL_INPUT_STRUCT *) rq; + UCHAR Addr[MAC_ADDR_LEN]; + INT Status = NDIS_STATUS_SUCCESS; + +#ifdef SNMP_SUPPORT + /*snmp */ + UINT KeyIdx = 0; + PNDIS_AP_802_11_KEY pKey = NULL; + TX_RTY_CFG_STRUC tx_rty_cfg; + ULONG ShortRetryLimit, LongRetryLimit; + UCHAR ctmp; +#endif /* SNMP_SUPPORT */ + + + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeMax; + NDIS_802_11_SSID Ssid; + +#ifdef HOSTAPD_SUPPORT + MAC_TABLE_ENTRY *pEntry; + STA_TR_ENTRY *tr_entry; + struct ieee80211req_mlme mlme; + + struct ieee80211req_key Key; + struct ieee80211req_del_key delkey; + UINT8 Wcid; + BSS_STRUCT *pMbss ; + WSC_LV_INFO WscIEBeacon; + WSC_LV_INFO WscIEProbeResp; + int i; +#endif /*HOSTAPD_SUPPORT*/ + + +#ifdef APCLI_SUPPORT +#endif/*APCLI_SUPPORT*/ +#ifdef WAPP_SUPPORT + RTMP_STRING driverVersion[16]; +#endif + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + switch(cmd & 0x7FFF) + { +#ifdef APCLI_SUPPORT +#endif/*APCLI_SUPPORT*/ + + + case OID_802_11_DEAUTHENTICATION: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DEAUTHENTICATION\n")); + if (wrq->u.data.length != sizeof(MLME_DEAUTH_REQ_STRUCT)) + Status = -EINVAL; + else + { + MAC_TABLE_ENTRY *pEntry = NULL; + MLME_DEAUTH_REQ_STRUCT *pInfo = NULL; + MLME_QUEUE_ELEM *Elem; + + os_alloc_mem(pAd, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + + if(Elem == NULL) + { + Status = -ENOMEM; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DEAUTHENTICATION, Failed!!\n")); + break; + } + +#ifdef APCLI_SUPPORT +#endif/*APCLI_SUPPORT*/ + { + if (Elem) { + pInfo = (MLME_DEAUTH_REQ_STRUCT *) Elem->Msg; + Status = copy_from_user(pInfo, wrq->u.data.pointer, wrq->u.data.length); + + if ((pEntry = MacTableLookup(pAd, pInfo->Addr)) != NULL) + { + Elem->Wcid = pEntry->wcid; + MlmeEnqueue(pAd, AP_AUTH_STATE_MACHINE, APMT2_MLME_DEAUTH_REQ, + sizeof(MLME_DEAUTH_REQ_STRUCT), Elem, 0); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_DEAUTHENTICATION (Reason=%d)\n", pInfo->Reason)); + } + os_free_mem(NULL, Elem); + } + } + } + + 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%lx))\n", IappPid, (ULONG)pObj->IappPid)); + } + } + break; +#endif /* IAPP_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + case RT_SET_FT_STATION_NOTIFY: + case RT_SET_FT_KEY_REQ: + case RT_SET_FT_KEY_RSP: + case RT_FT_KEY_SET: + case RT_FT_NEIGHBOR_REPORT: + case RT_FT_NEIGHBOR_REQUEST: + case RT_FT_NEIGHBOR_RESPONSE: + case RT_FT_ACTION_FORWARD: + { + UCHAR *pBuffer; + + FT_MEM_ALLOC(pAd, &pBuffer, wrq->u.data.length+1); + if (pBuffer == NULL) + break; + + if (copy_from_user(pBuffer, wrq->u.data.pointer, wrq->u.data.length)) + { + Status = -EFAULT; + FT_MEM_FREE(pAd, pBuffer); + break; + } + + switch(cmd & 0x7FFF) + { + case RT_SET_FT_STATION_NOTIFY: + DBGPRINT(RT_DEBUG_TRACE, ("RT_SET_FT_STATION_NOTIFY\n")); + FT_KDP_StationInform(pAd, pBuffer, wrq->u.data.length); + break; + case RT_SET_FT_KEY_REQ: + DBGPRINT(RT_DEBUG_TRACE, ("RT_SET_FT_KEY_REQ\n")); + FT_KDP_IOCTL_KEY_REQ(pAd, pBuffer, wrq->u.data.length); + break; + case RT_SET_FT_KEY_RSP: + DBGPRINT(RT_DEBUG_TRACE, ("RT_SET_FT_KEY_RSP\n")); + FT_KDP_KeyResponseToUs(pAd, pBuffer, wrq->u.data.length); + break; + case RT_FT_KEY_SET: + DBGPRINT(RT_DEBUG_TRACE, ("RT_FT_KEY_SET\n")); + /* Note: the key must be ended by 0x00 */ + pBuffer[wrq->u.data.length] = 0x00; + FT_KDP_CryptKeySet(pAd, pBuffer, wrq->u.data.length); + break; + case RT_FT_NEIGHBOR_REPORT: + DBGPRINT(RT_DEBUG_TRACE, ("RT_FT_NEIGHBOR_REPORT\n")); +#ifdef FT_KDP_FUNC_INFO_BROADCAST + FT_KDP_NeighborReportHandle(pAd, pBuffer, wrq->u.data.length); +#endif /* FT_KDP_FUNC_INFO_BROADCAST */ + break; + case RT_FT_NEIGHBOR_REQUEST: + DBGPRINT(RT_DEBUG_TRACE, ("RT_FT_NEIGHBOR_REPORT\n")); + FT_KDP_NeighborRequestHandle(pAd, pBuffer, wrq->u.data.length); + break; + case RT_FT_NEIGHBOR_RESPONSE: + DBGPRINT(RT_DEBUG_TRACE, ("RT_FT_NEIGHBOR_RESPONSE\n")); + FT_KDP_NeighborResponseHandle(pAd, pBuffer, wrq->u.data.length); + break; + case RT_FT_ACTION_FORWARD: + DBGPRINT(RT_DEBUG_TRACE, ("RT_FT_ACTION_FORWARD\n")); + FT_RRB_ActionHandle(pAd, pBuffer, wrq->u.data.length); + break; + } + + FT_MEM_FREE(pAd, pBuffer); + } + break; + + case OID_802_11R_SUPPORT: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + UCHAR apidx = pObj->ioctl_if; + ULONG value; + Status = copy_from_user(&value, wrq->u.data.pointer, wrq->u.data.length); + pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable = (value == 0 ? FALSE : TRUE); + DBGPRINT(RT_DEBUG_TRACE,("Set::OID_802_11R_SUPPORT(=%d) \n", + pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable)); + } + break; + + case OID_802_11R_MDID: + if (wrq->u.data.length != FT_MDID_LEN) + Status = -EINVAL; + else + { + UCHAR apidx = pObj->ioctl_if; + Status = copy_from_user(pAd->ApCfg.MBSSID[apidx].FtCfg.FtMdId, wrq->u.data.pointer, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE,("Set::OID_802_11R_MDID(=%c%c) \n", + pAd->ApCfg.MBSSID[apidx].FtCfg.FtMdId[0], + pAd->ApCfg.MBSSID[apidx].FtCfg.FtMdId[0])); + } + + break; + + + case OID_802_11R_R0KHID: + if (wrq->u.data.length <= FT_ROKH_ID_LEN) + Status = -EINVAL; + else + { + UCHAR apidx = pObj->ioctl_if; + Status = copy_from_user(pAd->ApCfg.MBSSID[apidx].FtCfg.FtR0khId, wrq->u.data.pointer, wrq->u.data.length); + pAd->ApCfg.MBSSID[apidx].FtCfg.FtR0khIdLen = wrq->u.data.length; + DBGPRINT(RT_DEBUG_TRACE,("Set::OID_802_11R_OID_802_11R_R0KHID(=%s) Len=%d\n", + pAd->ApCfg.MBSSID[apidx].FtCfg.FtR0khId, + pAd->ApCfg.MBSSID[apidx].FtCfg.FtR0khIdLen)); + } + break; + + case OID_802_11R_RIC: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + UCHAR apidx = pObj->ioctl_if; + ULONG value; + Status = copy_from_user(&value, wrq->u.data.pointer, wrq->u.data.length); + pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.RsrReqCap = (value == 0 ? FALSE : TRUE); + DBGPRINT(RT_DEBUG_TRACE,("Set::OID_802_11R_RIC(=%d) \n", + pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable)); + } + break; + + case OID_802_11R_OTD: + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + UCHAR apidx = pObj->ioctl_if; + ULONG value; + Status = copy_from_user(&value, wrq->u.data.pointer, wrq->u.data.length); + pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.FtOverDs = (value == 0 ? FALSE : TRUE); + DBGPRINT(RT_DEBUG_TRACE,("Set::OID_802_11R_OTD(=%d) \n", + pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable)); + } + break; +#endif /* DOT11R_FT_SUPPORT */ + case RT_SET_APD_PID: + { + unsigned long apd_pid; + if (copy_from_user(&apd_pid, wrq->u.data.pointer, wrq->u.data.length)) + { + Status = -EFAULT; + } + else + { + RTMP_GET_OS_PID(pObj->apd_pid, apd_pid); + pObj->apd_pid_nr = apd_pid; + DBGPRINT(RT_DEBUG_TRACE, ("RT_SET_APD_PID::(ApdPid=%lu(0x%lx))\n", apd_pid, (ULONG)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) + { +#ifdef DOT11R_FT_SUPPORT + /* + If AP send de-auth to Apple STA, + Apple STA will re-do auth/assoc and security handshaking with AP again. + @20150313 + */ + if (IS_FT_RSN_STA(pEntry)) + { + MacTableDeleteEntry(pAd, pEntry->Aid, Addr); + } + else +#endif /* DOT11R_FT_SUPPORT */ + MlmeDeAuthAction(pAd, pEntry, REASON_DISASSOC_STA_LEAVING, FALSE); + } + } + break; +#ifdef WSC_AP_SUPPORT + case RT_OID_WSC_SET_SELECTED_REGISTRAR: + { + PUCHAR upnpInfo; + UCHAR apidx = pObj->ioctl_if; + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + Status = -EINVAL; + } + else + { +#endif /*HOSTAPD_SUPPORT*/ + + + DBGPRINT(RT_DEBUG_TRACE, ("WSC::RT_OID_WSC_SET_SELECTED_REGISTRAR, wrq->u.data.length=%d!\n", wrq->u.data.length)); + 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; + } + } + os_free_mem(NULL, upnpInfo); + } + else + { + Status = -EINVAL; + } +#ifdef HOSTAPD_SUPPORT + } +#endif /*HOSTAPD_SUPPORT*/ + + } + break; + case RT_OID_WSC_EAPMSG: + { + RTMP_WSC_U2KMSG_HDR *msgHdr = NULL; + PUCHAR pUPnPMsg = NULL; + UINT msgLen = 0, Machine = 0, msgType = 0; + int retVal, senderID = 0; +#ifdef HOSTAPD_SUPPORT + UCHAR apidx = pObj->ioctl_if; + + if (pAd->ApCfg.MBSSID[apidx].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + Status = -EINVAL; + } + else + { +#endif /*HOSTAPD_SUPPORT*/ + + + DBGPRINT(RT_DEBUG_TRACE, ("WSC::RT_OID_WSC_EAPMSG, wrq->u.data.length=%d, ioctl_if=%d\n", wrq->u.data.length, pObj->ioctl_if)); + + msgLen = wrq->u.data.length; + os_alloc_mem(pAd, (UCHAR **)&pUPnPMsg, msgLen); + if (pUPnPMsg == NULL) + Status = -EINVAL; + else + { + int HeaderLen; + RTMP_STRING *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 = (RTMP_STRING *)&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; +#ifdef WSC_UFD + case RT_OID_WSC_READ_UFD_FILE: + if (wrq->u.data.length > 0) + { + RTMP_STRING *pWscUfdFileName = NULL; + UCHAR apIdx = pObj->ioctl_if; + WSC_CTRL *pWscCtrl = &pAd->ApCfg.MBSSID[apIdx].WscControl; + + 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; + } + } + 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) + { + RTMP_STRING*pWscUfdFileName = NULL; + UCHAR apIdx = pObj->ioctl_if; + WSC_CTRL *pWscCtrl = &pAd->ApCfg.MBSSID[apIdx].WscControl; + + 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; + } + } + os_free_mem(NULL, pWscUfdFileName); + } + else + Status = -ENOMEM; + } + else + Status = -EINVAL; + break; +#endif /* WSC_UFD */ + case OID_WSC_UUID: + 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))); + } + DBGPRINT(RT_DEBUG_OFF, ("\n")); + } + else + Status = -EINVAL; + break; +#endif /* WSC_AP_SUPPORT */ + + case OID_SET_SSID: + if (wrq->u.data.length <= MAX_LEN_OF_SSID) { + UCHAR apcli_idx = pObj->ioctl_if; + struct wifi_dev *wdev; + BOOLEAN apcliEn; + APCLI_STRUCT *apcli_entry; + BSS_STRUCT *pMbss = NULL; +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) { + apcli_entry = &pAd->ApCfg.ApCliTab[apcli_idx]; + wdev = &apcli_entry->wdev; + /* bring apcli interface down first */ + apcliEn = apcli_entry->Enable; + + if (apcliEn == TRUE) { + apcli_entry->Enable = FALSE; + ApCliIfDown(pAd); + } + + /* apcli_entry->bPeerExist = FALSE; */ + NdisZeroMemory(apcli_entry->CfgSsid, MAX_LEN_OF_SSID); + Status = copy_from_user(apcli_entry->CfgSsid, + wrq->u.data.pointer, + wrq->u.data.length); + apcli_entry->CfgSsidLen = (UCHAR)wrq->u.data.length; + DBGPRINT(RT_DEBUG_TRACE, + ("OID_APCLI_SSID::(Len=%d,Ssid=%s)\n", + apcli_entry->CfgSsidLen, + apcli_entry->CfgSsid)); + apcli_entry->Enable = apcliEn; + + /* Upadte PMK and restart WPAPSK state machine for ApCli link */ + if (((wdev->AuthMode == Ndis802_11AuthModeWPAPSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) && + apcli_entry->PSKLen > 0) { + RT_CfgSetWPAPSKKey(pAd, (RTMP_STRING *)apcli_entry->PSK, + apcli_entry->PSKLen, + (PUCHAR)apcli_entry->CfgSsid, + apcli_entry->CfgSsidLen, + apcli_entry->PMK); + } + } else { +#endif + if (pObj->ioctl_if < HW_BEACON_MAX_NUM) { + pMbss = &pAd->ApCfg.MBSSID[pObj->ioctl_if]; + wdev = &pMbss->wdev; + NdisZeroMemory(pMbss->Ssid, MAX_LEN_OF_SSID); + Status = copy_from_user(pMbss->Ssid, + wrq->u.data.pointer, + wrq->u.data.length); + pMbss->SsidLen = wrq->u.data.length; + if (wdev == NULL) { + Status = -EINVAL; + break; + } + { + ap_send_broadcast_deauth(pAd, wdev); + if ((&wdev->AuthMode) && (&wdev->WpaMixPairCipher)) + pMbss->CapabilityInfo |= 0x0010; + else + pMbss->CapabilityInfo &= ~(0x0010); + if (pAd->Dot11_H.RDMode != RD_SWITCHING_MODE) { + MbssKickOutStas(pAd, pObj->ioctl_if, REASON_DISASSOC_INACTIVE); + ap_security_init(pAd, wdev, pObj->ioctl_if); + ap_mlme_set_capability(pAd, pMbss); + ap_key_tb_single_init(pAd, pMbss); + APMakeBssBeacon(pAd, pObj->ioctl_if); + APUpdateBeaconFrame(pAd, pObj->ioctl_if); + } + DBGPRINT(RT_DEBUG_TRACE, + ("I/F(ra%d) Set_SSID::(Len=%d,Ssid=%s)\n", + pObj->ioctl_if, + pMbss->SsidLen, pMbss->Ssid)); + } + } else + Status = -EINVAL; + break; + } + } else + Status = -EINVAL; + break; + + case OID_SET_PSK: + { + UCHAR PSK[64 + 1]; /* Add "\0" length */ + + if (wrq->u.data.length < 65) { + Status = copy_from_user(PSK, + wrq->u.data.pointer, + wrq->u.data.length); + PSK[wrq->u.data.length] = '\0'; + } else + PSK[0] = '\0'; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: PSK = %s\n", + __func__, PSK)); + if (pObj->ioctl_if_type == INT_APCLI) { + copy_from_user(pAd->ApCfg.ApCliTab[pObj->ioctl_if].PSK, wrq->u.data.pointer, wrq->u.data.length); + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PSK[wrq->u.data.length] = '\0'; + pAd->ApCfg.ApCliTab[pObj->ioctl_if].PSKLen = wrq->u.data.length; + } else if ((pObj->ioctl_if_type == INT_MAIN || pObj->ioctl_if_type == INT_MBSSID)) { + copy_from_user(pAd->ApCfg.MBSSID[pObj->ioctl_if].WPAKeyString, wrq->u.data.pointer, wrq->u.data.length); + pAd->ApCfg.MBSSID[pObj->ioctl_if].WPAKeyString[wrq->u.data.length] = '\0'; + ap_security_init(pAd, &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev, pObj->ioctl_if); + } +#ifdef CONFIG_AP_SUPPORT +#ifdef WSC_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { + WSC_CTRL *pWscControl = NULL; + + if ((pObj->ioctl_if_type == INT_MAIN || pObj->ioctl_if_type == INT_MBSSID)) { + UCHAR apidx = pObj->ioctl_if; + + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + } + +#ifdef APCLI_SUPPORT + else if (pObj->ioctl_if_type == INT_APCLI) { + UCHAR apcli_idx = pObj->ioctl_if; + + pWscControl = &pAd->ApCfg.ApCliTab[apcli_idx].WscControl; + } +#endif /* APCLI_SUPPORT */ + + if (pWscControl) { + NdisZeroMemory(pWscControl->WpaPsk, 64); + pWscControl->WpaPskLen = 0; + pWscControl->WpaPskLen = wrq->u.data.length; + Status = copy_from_user(pWscControl->WpaPsk, + wrq->u.data.pointer, + wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("%s: PSK = %s\n", + __func__, pWscControl->WpaPsk)); + } + } +#endif /* WSC_AP_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + break; + } + + +#ifdef SNMP_SUPPORT + case OID_802_11_SHORTRETRYLIMIT: + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + Status = copy_from_user(&ShortRetryLimit, wrq->u.data.pointer, wrq->u.data.length); + AsicSetRetryLimit(pAd, TX_RTY_CFG_RTY_LIMIT_SHORT, ShortRetryLimit); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_SHORTRETRYLIMIT (ShortRetryLimit=%ld)\n", ShortRetryLimit)); + } + break; + + case OID_802_11_LONGRETRYLIMIT: + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_LONGRETRYLIMIT \n")); + if (wrq->u.data.length != sizeof(ULONG)) + Status = -EINVAL; + else + { + Status = copy_from_user(&LongRetryLimit, wrq->u.data.pointer, wrq->u.data.length); + AsicSetRetryLimit(pAd, TX_RTY_CFG_RTY_LIMIT_LONG, LongRetryLimit); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_LONGRETRYLIMIT (,LongRetryLimit=%ld)\n", LongRetryLimit)); + } + break; + + case OID_802_11_WEPDEFAULTKEYVALUE: + { + UINT KeyIdx; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEPDEFAULTKEYVALUE\n")); + + os_alloc_mem(pAd, (UCHAR **)&pKey, wrq->u.data.length); + if (pKey == NULL) + { + Status= -EINVAL; + 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; + + + 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 + { + RTMP_STRING ChStr[5] = {0}; + Status = copy_from_user(&ctmp, wrq->u.data.pointer, wrq->u.data.length); + snprintf(ChStr, sizeof(ChStr), "%d", ctmp); + Set_Channel_Proc(pAd, ChStr); + } + break; +#endif /* SNMP_SUPPORT */ + + +#ifdef WAPI_SUPPORT + case OID_802_11_WAPI_PID: + { + unsigned long wapi_pid; + 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, (UINT32)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; + STA_TR_ENTRY *tr_entry; + + 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) + { + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + switch (wapi_port.state) + { + case WAPI_PORT_SECURED: + tr_entry->PortSecured = WPA_802_1X_PORT_SECURED; + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + break; + + default: + tr_entry->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 +#endif/*APCLI_SUPPORT*/ + else + { + if (pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.AuthMode != AuthMode) + { + /* Config has changed */ + pAd->bConfigChanged = TRUE; + } + pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.AuthMode = AuthMode; + } + pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_AUTHENTICATION_MODE (=%d) \n", pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.AuthMode)); + } + APStop(pAd); + APStartUp(pAd); + break; + + case OID_802_11_WEP_STATUS: + if (wrq->u.data.length != sizeof(NDIS_802_11_WEP_STATUS)) + Status = -EINVAL; + else + { + Status = copy_from_user(&WepStatus, wrq->u.data.pointer, wrq->u.data.length); + +#ifdef APCLI_SUPPORT +#endif/*APCLI_SUPPORT*/ + { + /* Since TKIP, AES, WEP are all supported. It should not have any invalid setting */ + if (WepStatus <= Ndis802_11GroupWEP104Enabled) + { + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + if (wdev->WepStatus != WepStatus) + { + /* Config has changed */ + pAd->bConfigChanged = TRUE; + } + wdev->WepStatus = WepStatus; + + if (wdev->WepStatus == Ndis802_11TKIPAESMix) + wdev->GroupKeyWepStatus = Ndis802_11TKIPEnable; + else + wdev->GroupKeyWepStatus = WepStatus; + } + else + { + Status = -EINVAL; + break; + } + APStop(pAd); + APStartUp(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("Set::OID_802_11_WEP_STATUS (=%d)\n",WepStatus)); + } + } + + break; + + case OID_802_11_SSID: + if (wrq->u.data.length != sizeof(NDIS_802_11_SSID)) + Status = -EINVAL; + else + { + RTMP_STRING *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 +#endif/*APCLI_SUPPORT*/ + { + NdisZeroMemory((PCHAR)pAd->ApCfg.MBSSID[pObj->ioctl_if].Ssid,MAX_LEN_OF_SSID); + strncpy((PCHAR)pAd->ApCfg.MBSSID[pObj->ioctl_if].Ssid, + pSsidString, MAX_LEN_OF_SSID); + pAd->ApCfg.MBSSID[pObj->ioctl_if].SsidLen=strlen(pSsidString); + } + os_free_mem(NULL, pSsidString); + } + else + Status = -ENOMEM; + } + } + } + break; + +#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->func_tb_idx].DefaultKeyId; + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->wcid, + &pEntry->PairwiseKey); + + RTMPAddWcidAttributeEntry( + pAd, + pEntry->func_tb_idx, + KeyIdx, /* The value may be not zero */ + pEntry->PairwiseKey.CipherAlg, + pEntry); + } + else/*group key */ + { + pMbss = &pAd->ApCfg.MBSSID[apidx]; + printk("Key.ik_keyix=%x\n",Key.ik_keyix); + KeyIdx = Key.ik_keyix& 0x0fff; + printk("ra%d KeyIdx=%d\n",apidx,KeyIdx); + printk("Key.ik_keyix=%x\n",Key.ik_keyix); + /* it is a shared key */ + if (KeyIdx < 4) + { + pAd->SharedKey[apidx][KeyIdx].KeyLen = (UCHAR) Key.ik_keylen; + NdisMoveMemory(pAd->SharedKey[apidx][KeyIdx].Key, &Key.ik_keydata, Key.ik_keylen); + if (Key.ik_keyix & 0x8000) + { + /* Default key for tx (shared key) */ + printk("ra%d DefaultKeyId=%d\n",apidx,KeyIdx); + pMbss->DefaultKeyId = (UCHAR) KeyIdx; + } + /*pMbss->DefaultKeyId=1; */ + + pAd->SharedKey[apidx][KeyIdx].CipherAlg = Key.ik_type; + AsicAddSharedKeyEntry( + pAd, + apidx, + KeyIdx, + &pAd->SharedKey[apidx][KeyIdx] + ); + + RTMPAddWcidAttributeEntry( + pAd, + apidx, + KeyIdx, + pAd->SharedKey[apidx][pMbss->DefaultKeyId].CipherAlg, + NULL); + } + } + } + else if (pEntry) + { + KeyIdx = Key.ik_keyix& 0x0fff; + if (pEntry->WepStatus == Ndis802_11TKIPEnable) + { + 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_11AESEnable) + { + 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_11TKIPEnable) + pEntry->PairwiseKey.CipherAlg = CIPHER_TKIP; + else if (pEntry->WepStatus == Ndis802_11AESEnable) + pEntry->PairwiseKey.CipherAlg = CIPHER_AES; + + pEntry->PairwiseKey.CipherAlg = Key.ik_type; + + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->wcid, + &pEntry->PairwiseKey); + + RTMPSetWcidSecurityInfo(pAd, + pEntry->func_tb_idx, + (UINT8)KeyIdx, + pEntry->PairwiseKey.CipherAlg, + pEntry->wcid, + PAIRWISEKEYTABLE); + } + else + { + pMbss = &pAd->ApCfg.MBSSID[apidx]; + KeyIdx = Key.ik_keyix& 0x0fff; + + /*if (Key.ik_keyix & 0x8000) */ + { + pMbss->DefaultKeyId = (UCHAR) KeyIdx; + } + + if (pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus == Ndis802_11TKIPEnable) + { + 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_11AESEnable) + { + 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_11TKIPEnable) + pAd->SharedKey[apidx][pMbss->DefaultKeyId].CipherAlg = CIPHER_TKIP; + else if (pAd->ApCfg.MBSSID[apidx].GroupKeyWepStatus == Ndis802_11AESEnable) + pAd->SharedKey[apidx][pMbss->DefaultKeyId].CipherAlg = CIPHER_AES; + + hex_dump("Key.ik_keydata,", (unsigned char*) Key.ik_keydata, 32); + + AsicAddSharedKeyEntry( + pAd, + apidx, + pMbss->DefaultKeyId, + &pAd->SharedKey[apidx][pMbss->DefaultKeyId] + ); + GET_GroupKey_WCID(pAd, Wcid, apidx); + + RTMPSetWcidSecurityInfo(pAd, apidx,(UINT8)KeyIdx, + pAd->SharedKey[apidx][pMbss->DefaultKeyId].CipherAlg, Wcid, SHAREDKEYTABLE); + + /*RTMPAddWcidAttributeEntry( + pAd, + apidx, + pMbss->DefaultKeyId, + pAd->SharedKey[apidx][pMbss->DefaultKeyId].CipherAlg, + NULL);*/ + } + break; + } + case HOSTAPD_OID_DEL_KEY: + + Status = -EINVAL; + if(wrq->u.data.length != sizeof(struct ieee80211req_del_key) || !wrq->u.data.pointer) + break; + Status = copy_from_user(&delkey, wrq->u.data.pointer, wrq->u.data.length); + pEntry = MacTableLookup(pAd, delkey.idk_macaddr); + if (pEntry){ + /* clear the previous Pairwise key table */ + if(pEntry->wcid != 0) + { + NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY)); + AsicRemovePairwiseKeyEntry(pAd,(UCHAR)pEntry->wcid); + } + } + else if((delkey.idk_macaddr == NULL) && (delkey.idk_keyix < 4)) + /* remove group key */ + AsicRemoveSharedKeyEntry(pAd, pEntry->func_tb_idx, 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 + { + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + 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; */ + tr_entry->PortSecured = WPA_802_1X_PORT_SECURED; + break; + case IEEE80211_MLME_UNAUTHORIZE: + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + tr_entry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + break; + default: + Status = -EINVAL; + } + } + } + break; + + case HOSTAPD_OID_STATIC_WEP_COPY: + { + UINT KeyIdx; + INT apidx; + if (wrq->u.data.length != sizeof(struct ieee80211req_mlme)) + { + Status = -EINVAL; + } + else + { + Status = copy_from_user(&mlme, wrq->u.data.pointer, wrq->u.data.length); + pEntry = MacTableLookup(pAd, mlme.im_macaddr); + if (!pEntry){ + Status = -EINVAL; + } + else{ + /*Status = -EINVAL; */ + printk("Woody HOSTAPD_OID_STATIC_WEP_COPY IEEE8021X=%d WepStatus=%d\n", + pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.IEEE8021X, pEntry->WepStatus); + if (pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.IEEE8021X != TRUE) + break; + if (pEntry->WepStatus != Ndis802_11WEPEnabled) + break; + + apidx = pObj->ioctl_if; + pMbss = &pAd->ApCfg.MBSSID[apidx]; + + KeyIdx=pMbss->DefaultKeyId; + printk("Woody HOSTAPD_OID_STATIC_WEP_COPY=%d\n",KeyIdx); + pEntry->AuthMode=pAd->ApCfg.MBSSID[apidx].AuthMode; + pEntry->PairwiseKey.KeyLen = pAd->SharedKey[apidx][KeyIdx].KeyLen; + NdisMoveMemory(pEntry->PairwiseKey.Key, pAd->SharedKey[apidx][KeyIdx].Key, pAd->SharedKey[apidx][KeyIdx].KeyLen); + pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[apidx][KeyIdx].CipherAlg; + + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->wcid, + &pEntry->PairwiseKey); + + RTMPAddWcidAttributeEntry( + pAd, + pEntry->func_tb_idx, + 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; + + os_alloc_mem(NULL, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + if(Elem) + { + pInfo = (MLME_DEAUTH_REQ_STRUCT *) Elem->Msg; + + if (wrq->u.data.length != sizeof(struct ieee80211req_mlme)) + { + Status = -EINVAL; + } + else + { + Status = copy_from_user(&mlme, wrq->u.data.pointer, wrq->u.data.length); + NdisMoveMemory(pInfo->Addr, mlme.im_macaddr, MAC_ADDR_LEN); + if ((pEntry = MacTableLookup(pAd, pInfo->Addr)) != NULL) + { + pInfo->Reason = mlme.im_reason; + Elem->Wcid = pEntry->wcid; + MlmeEnqueue(pAd, AP_AUTH_STATE_MACHINE, APMT2_MLME_DEAUTH_REQ, sizeof(MLME_DEAUTH_REQ_STRUCT), Elem,0); + } + } + os_free_mem(NULL, Elem); + } + break; + + case HOSTAPD_OID_SET_STA_DISASSOC:/*hostapd request to disassoc the station. */ + DBGPRINT(RT_DEBUG_TRACE, ("Set::HOSTAPD_OID_SET_STA_DISASSOC\n")); + MLME_DISASSOC_REQ_STRUCT DisassocReq; + if (wrq->u.data.length != sizeof(struct ieee80211req_mlme)) + { + Status = -EINVAL; + } + else + { + Status = copy_from_user(&mlme, wrq->u.data.pointer, wrq->u.data.length); + NdisMoveMemory(DisassocReq.Addr, mlme.im_macaddr, MAC_ADDR_LEN); + DisassocReq.Reason = mlme.im_reason; + MlmeEnqueue(pAd, AP_ASSOC_STATE_MACHINE, APMT2_MLME_DISASSOC_REQ, sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq,0); + } + break; + + case OID_HOSTAPD_SUPPORT:/*notify the driver to support hostapd. */ + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + BOOLEAN hostapd_enable; + int v, apidx; + apidx = pObj->ioctl_if; + Status = copy_from_user(&hostapd_enable, wrq->u.data.pointer, wrq->u.data.length); + printk("OID_HOSTAPD_SUPPORT apidx=%d\n",apidx); + pAd->ApCfg.MBSSID[apidx].Hostapd = hostapd_enable; + BSS_STRUCT *pMBSSStruct; + + for(v=0;vMBSSID[%d].Hostapd == %s\n", v, + (pAd->ApCfg.MBSSID[v].Hostapd == Hostapd_EXT ? "TRUE" : "FALSE")); + pMBSSStruct = &pAd->ApCfg.MBSSID[v]; + pMBSSStruct->WPAREKEY.ReKeyInterval = 0; + pMBSSStruct->WPAREKEY.ReKeyMethod = DISABLE_REKEY; + } + } + break; + + case HOSTAPD_OID_COUNTERMEASURES:/*report txtsc to hostapd. */ + + if (wrq->u.data.length != sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + BOOLEAN countermeasures_enable; + Status = copy_from_user(&countermeasures_enable, wrq->u.data.pointer, wrq->u.data.length); + + if(countermeasures_enable) + { + + { + DBGPRINT(RT_DEBUG_ERROR, ("Receive CM Attack Twice within 60 seconds ====>>> \n")); + + /* send wireless event - for counter measures */ + pAd->ApCfg.CMTimerRunning = FALSE; + + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[i]; + /* happened twice within 60 sec, AP SENDS disaccociate all associated STAs. All STA's transition to State 2 */ + if (IS_ENTRY_CLIENT(pEntry)) + { + MlmeDeAuthAction(pAd, &pAd->MacTab.Content[i], REASON_MIC_FAILURE,FALSE); + } + } + + /* Further, ban all Class 3 DATA transportation for a period of 60 sec */ + /* disallow new association , too */ + pAd->ApCfg.BANClass3Data = TRUE; + } + + + } + else + { + pAd->ApCfg.BANClass3Data = FALSE; + } + } + break; + + case HOSTAPD_OID_SET_WPS_BEACON_IE:/*pure 1x is enabled. */ + DBGPRINT(RT_DEBUG_TRACE,("HOSTAPD_OID_SET_WPS_BEACON_IE\n")); + if (wrq->u.data.length != sizeof(WSC_LV_INFO)) + { + Status = -EINVAL; + } + else + { + INT apidx; + apidx = pObj->ioctl_if; + pAd->ApCfg.MBSSID[apidx].HostapdWPS = TRUE; + BSS_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; + BSS_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 AIRPLAY_SUPPORT + /* + *Get Airplay IE content from user + */ + case OID_AIRPLAY_IE_INSERT: + { + printk(KERN_ALERT"!!##-----OID_AIRPLAY_IE_INSERT start...length=%d\n",wrq->u.data.length); + + if (wrq->u.data.length != 0) + { + /*Free IE spaces*/ + if (pAd->pAirplayIe) + { + Status = os_free_mem(NULL, pAd->pAirplayIe); + } + if (Status == NDIS_STATUS_FAILURE) + { + DBGPRINT(RT_DEBUG_ERROR, ("os_free_mem fail\n")); + break; + } + + pAd->pAirplayIe = NULL; + pAd->AirplayIeLen = wrq->u.data.length; + + Status = os_alloc_mem(NULL, &pAd->pAirplayIe, pAd->AirplayIeLen); + if (Status == NDIS_STATUS_FAILURE) + { + DBGPRINT(RT_DEBUG_ERROR, ("os_alloc_mem fail\n")); + break; + } + + Status = copy_from_user(pAd->pAirplayIe, wrq->u.data.pointer, pAd->AirplayIeLen); + if (Status == NDIS_STATUS_FAILURE) + { + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_AIRPLAY_IE_INSERT error!!\n")); + break; + } + /*show out the IE content for debug*/ + //hex_dump("The primary AIRPLAYIE", pAd->pAirplayIe, pAd->AirplayIeLen); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("wrq->u.data.length == 0, no data need to update\n")); + } + } + break; + + /* + * Enable/Disable driver Airplay functionality + * Value: + * 0: Not enable + * 1: Enable + */ + case OID_AIRPLAY_ENABLE: + { + if (wrq->u.data.length > sizeof(BOOLEAN)) + Status = -EINVAL; + else + { + BOOLEAN bEnable; + + Status = copy_from_user(&bEnable, wrq->u.data.pointer, wrq->u.data.length); + + if (Status == NDIS_STATUS_SUCCESS) + { + if (bEnable == TRUE) + { + INT apidx; + apidx = pObj->ioctl_if; + pAd->bAirplayEnable= TRUE; + pAd->ApCfg.MBSSID[apidx].bcn_buf.bBcnSntReq = TRUE; + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + pAd->bAirplayEnable= TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("%s:: Enable Airplay Support!\n", __FUNCTION__)); + printk("[wifi]=== Enable Airplay ===\n"); + } + else + { + pAd->bAirplayEnable = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s:: Disable Airplay Support!\n", __FUNCTION__)); + printk("[wifi]=== Disable Airplay ===\n"); + } + } + else + DBGPRINT(RT_DEBUG_ERROR, ("Set::OID_AIRPLAY_ENABLE error!!\n")); + } + } + break; +#endif /* AIRPLAY_SUPPORT */ + +#if defined(WAPP_SUPPORT) +/* + case OID_802_11_HS_TEST: + DBGPRINT(RT_DEBUG_TRACE, ("hotspot test\n")); + break; + case OID_802_11_HS_IE: + { + UCHAR *IE; + os_alloc_mem(NULL, (UCHAR **)&IE, wrq->u.data.length); + copy_from_user(IE, wrq->u.data.pointer, wrq->u.data.length); + Set_AP_IE(pAd, IE, wrq->u.data.length); + os_free_mem(NULL, IE); + } + break; +*/ +#if defined(DOT11U_INTERWORKING) + case OID_802_11_HS_ANQP_RSP: + { + UCHAR *Buf; + struct anqp_rsp_data *rsp_data; + os_alloc_mem(NULL, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + rsp_data = (struct anqp_rsp_data *)Buf; + Send_ANQP_Rsp(pAd, + rsp_data->peer_mac_addr, + rsp_data->anqp_rsp, + rsp_data->anqp_rsp_len); + os_free_mem(NULL, Buf); + } + break; +#endif +#ifdef CONFIG_HOTSPOT_R2 + case OID_802_11_HS_ONOFF: + { + UCHAR *Buf; + struct hs_onoff *onoff; + os_alloc_mem(NULL, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + onoff = (struct hs_onoff *)Buf; + Set_HotSpot_OnOff(pAd, onoff->hs_onoff, onoff->event_trigger, onoff->event_type); + os_free_mem(NULL, Buf); + } + break; + /*case OID_802_11_HS_PARAM_SETTING: + { + UCHAR *Buf; + struct hs_param_setting *param_setting; + os_alloc_mem(NULL, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + param_setting = (struct hs_param_setting *)Buf; + Set_HotSpot_Param(pAd, param_setting->param, param_setting->value); + os_free_mem(NULL, Buf); + } + break; +*/ + case OID_802_11_HS_RESET_RESOURCE: + DBGPRINT(RT_DEBUG_TRACE, ("hotspot reset some resource\n")); + Clear_Hotspot_All_IE(pAd); + //Clear_All_PROXY_TABLE(pAd); + break; + case OID_802_11_HS_SASN_ENABLE: + { + UCHAR *Buf; + PHOTSPOT_CTRL pHSCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].HotSpotCtrl; + os_alloc_mem(NULL, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + pHSCtrl->bASANEnable = Buf[0]; + os_free_mem(NULL, Buf); + } + break; + case OID_802_11_BSS_LOAD: + { + UCHAR *Buf; + PHOTSPOT_CTRL pHSCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].HotSpotCtrl; + os_alloc_mem(NULL, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + pHSCtrl->QLoadTestEnable = Buf[0]; + pHSCtrl->QLoadCU = Buf[1]; + memcpy(&pHSCtrl->QLoadStaCnt, &Buf[2], 2); + os_free_mem(NULL, Buf); + } + break; +#endif +#endif + +#ifdef CONFIG_DOT11V_WNM +#ifndef WAPP_SUPPORT + case OID_802_11_WNM_COMMAND: + { + UCHAR *Buf; + struct wnm_command *cmd_data; + + os_alloc_mem(NULL, (UCHAR **)&Buf, wrq->u.data.length); + Status = copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + cmd_data = (struct wnm_command *)Buf; + if (wnm_handle_command(pAd, cmd_data) != NDIS_STATUS_SUCCESS) + Status = -EINVAL; + + os_free_mem(NULL, Buf); + } + break; +#endif +#if defined(CONFIG_HOTSPOT_R2) || defined(WAPP_SUPPORT) + case OID_802_11_WAPP_IE: { + UCHAR *IE; + + os_alloc_mem(NULL, (UCHAR **)&IE, wrq->u.data.length); + Status = copy_from_user(IE, wrq->u.data.pointer, wrq->u.data.length); + wapp_set_ap_ie(pAd, IE, wrq->u.data.length); + os_free_mem(NULL, IE); + } + break; + case OID_802_11_WAPP_PARAM_SETTING: { + UCHAR *Buf; + struct wapp_param_setting *param_setting; + + os_alloc_mem(NULL, (UCHAR **)&Buf, wrq->u.data.length); + Status = copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + param_setting = (struct wapp_param_setting *)Buf; + set_wapp_param(pAd, param_setting->param, param_setting->value); + os_free_mem(NULL, Buf); + } + break; +#ifdef DOT11U_INTERWORKING + case OID_802_11_INTERWORKING_ENABLE: { + UCHAR *Buf; + PGAS_CTRL pGASCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].GASCtrl; + os_alloc_mem(NULL, (UCHAR **)&Buf, wrq->u.data.length); + Status = copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + pGASCtrl->b11U_enable = Buf[0] ? TRUE : FALSE; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s GAS service for MBSSID[%d]\n", pGASCtrl->b11U_enable?"Enable":"Disable", pObj->ioctl_if)); + os_free_mem(NULL, Buf); + } + break; +#endif + case OID_802_11_WNM_BTM_REQ: + { + UCHAR *Buf; + MAC_TABLE_ENTRY *pEntry; + struct btm_req_data *req_data; + + os_alloc_mem(Buf, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + req_data = (struct btm_req_data *)Buf; + + pEntry = MacTableLookup(pAd, req_data->peer_mac_addr); + if (pEntry) { + if ((pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.AuthMode <= Ndis802_11AuthModeAutoSwitch) + || ((pEntry->WpaState == AS_PTKINITDONE) && (pEntry->GTKState == REKEY_ESTABLISHED))) { + DBGPRINT(RT_DEBUG_TRACE, ("btm1\n")); + Send_BTM_Req(pAd, + req_data->peer_mac_addr, + req_data->btm_req, + req_data->btm_req_len); + } else { + DBGPRINT(RT_DEBUG_TRACE, ("btm2\n")); + pEntry->IsBTMReqValid = TRUE; + os_alloc_mem(pEntry->ReqbtmData, (UCHAR **)&pEntry->ReqbtmData, sizeof(struct btm_req_data)+req_data->btm_req_len); + memcpy(pEntry->ReqbtmData, Buf, sizeof(struct btm_req_data)+req_data->btm_req_len); + } + } + os_free_mem(NULL, Buf); + } + break; + case OID_802_11_WNM_NOTIFY_REQ: + { + UCHAR *Buf; + MAC_TABLE_ENTRY *pEntry; + struct wnm_req_data *req_data; + + os_alloc_mem(Buf, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + + req_data = (struct wnm_req_data *)Buf; + //printk("addr=%02x:%02x:%02x:%02x:%02x:%02x\n", req_data->peer_mac_addr[0],req_data->peer_mac_addr[1],req_data->peer_mac_addr[2],req_data->peer_mac_addr[3],req_data->peer_mac_addr[4],req_data->peer_mac_addr[5]); + //for(k=0;kwnm_req_len;k++) + // printk("%02x:", *(req_data->wnm_req+k)); + + //printk("req len=%d\n",req_data->wnm_req_len); + pEntry = MacTableLookup(pAd, req_data->peer_mac_addr); + if (pEntry) { + if (((pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.AuthMode <= Ndis802_11AuthModeAutoSwitch)) + || ((pEntry->WpaState == AS_PTKINITDONE) && (pEntry->GTKState == REKEY_ESTABLISHED))) { + DBGPRINT(RT_DEBUG_TRACE, ("wnm1\n")); + Send_WNM_Notify_Req(pAd, + req_data->peer_mac_addr, + req_data->wnm_req, + req_data->wnm_req_len, + req_data->type); + } +#ifdef CONFIG_HOTSPOT_R2 + else { + DBGPRINT(RT_DEBUG_TRACE, ("wnm2\n")); + pEntry->IsWNMReqValid = TRUE; + os_alloc_mem(pEntry->ReqData, (UCHAR **)&pEntry->ReqData, sizeof(struct wnm_req_data)+req_data->wnm_req_len); + memcpy(pEntry->ReqData, Buf, sizeof(struct wnm_req_data)+req_data->wnm_req_len); + } +#endif + } + os_free_mem(NULL, Buf); + } + break; +#ifdef CONFIG_HOTSPOT_R2 + case OID_802_11_QOSMAP_CONFIGURE: + { + UCHAR *Buf; + MAC_TABLE_ENTRY *pEntry; + struct qosmap_data *req_data; + unsigned int i; + + os_alloc_mem(Buf, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + + req_data = (struct qosmap_data *)Buf; + + if ((pEntry = MacTableLookup(pAd, req_data->peer_mac_addr)) != NULL) + { + //clear previous data + pEntry->DscpExceptionCount = 0; + memset(pEntry->DscpRange, 0xff, 16); + memset(pEntry->DscpException, 0xff, 42); + + pEntry->DscpExceptionCount = req_data->qosmap_len-16; + memcpy((UCHAR *)pEntry->DscpRange, &req_data->qosmap[pEntry->DscpExceptionCount], 16); + if (pEntry->DscpExceptionCount != 0) + memcpy((UCHAR *)pEntry->DscpException, req_data->qosmap, pEntry->DscpExceptionCount); + + Send_QOSMAP_Configure(pAd, + req_data->peer_mac_addr, + req_data->qosmap, + req_data->qosmap_len, + pEntry->func_tb_idx); + } + else if ((req_data->peer_mac_addr[0] == 0) + && (req_data->peer_mac_addr[1] == 0) + && (req_data->peer_mac_addr[2] == 0) + && (req_data->peer_mac_addr[3] == 0) + && (req_data->peer_mac_addr[4] == 0) + && (req_data->peer_mac_addr[5] == 0) ) { + /* Special MAC 00:00:00:00:00:00 for HS2 QoS Map Change using. */ + for (i=0; iMacTab.Content[i]; + + if ((IS_ENTRY_CLIENT(pEntry)) + && (pEntry->Sst == SST_ASSOC)) { + if (pEntry->QosMapSupport) { + pEntry->DscpExceptionCount = 0; + memset(pEntry->DscpRange, 0xff, 16); + memset(pEntry->DscpException, 0xff, 42); + + pEntry->DscpExceptionCount = req_data->qosmap_len-16; + memcpy((UCHAR *)pEntry->DscpRange, + &req_data->qosmap[pEntry->DscpExceptionCount], 16); + if (pEntry->DscpExceptionCount != 0) { + memcpy((UCHAR *)pEntry->DscpException, + req_data->qosmap, pEntry->DscpExceptionCount); + } + printk ("send QoS map frame: apidx=%d\n", pEntry->func_tb_idx); + Send_QOSMAP_Configure(pAd, + pEntry->Addr, + req_data->qosmap, + req_data->qosmap_len, + pEntry->func_tb_idx); + } + } + } + } + os_free_mem(NULL, Buf); + } + break; +#endif /* CONFIG_HOTSPOT_R2 */ +#endif +#endif + +#ifdef DOT11K_RRM_SUPPORT + case OID_802_11_RRM_COMMAND: + Status = rrm_MsgHandle(pAd, wrq); + if (Status != NDIS_STATUS_SUCCESS) + Status = -NDIS_STATUS_FAILURE; + break; +#endif +#ifdef MBO_SUPPORT + case OID_802_11_MBO_MSG: + { + UCHAR *Buf; + + struct wapp_param_setting *param_setting; + os_alloc_mem(NULL, (UCHAR **)&Buf, wrq->u.data.length); + copy_from_user(Buf, wrq->u.data.pointer, wrq->u.data.length); + param_setting = (struct wapp_param_setting *)Buf; + MBO_MsgHandle(pAd, param_setting->param, param_setting->value); + os_free_mem(NULL, Buf); + } + break; +#endif/* MBO_SUPPORT */ +#ifdef WAPP_SUPPORT + case OID_WAPP_EVENT: + { + UCHAR *buf; + struct wapp_req *req; + + os_alloc_mem(NULL, (UCHAR **)&buf, wrq->u.data.length); + copy_from_user(buf, wrq->u.data.pointer, wrq->u.data.length); + req = (struct wapp_req *)buf; + wapp_event_handle(pAd, req); + os_free_mem(NULL, buf); + } + break; +#endif/* WAPP_SUPPORT */ + +#ifdef BAND_STEERING + case OID_BNDSTRG_MSG: + BndStrg_MsgHandle(pAd, wrq, pObj->ioctl_if); + break; +#ifdef VENDOR_FEATURE5_SUPPORT + case OID_BNDSTRG_GET_NVRAM: + BndStrg_GetNvram(pAd, wrq, pObj->ioctl_if); + break; + + case OID_BNDSTRG_SET_NVRAM: + BndStrg_SetNvram(pAd, wrq, pObj->ioctl_if); + break; +#endif /* VENDOR_FEATURE5_SUPPORT */ +#endif /* BAND_STEERING */ + break; +#ifdef STA_FORCE_ROAM_SUPPORT + case OID_802_11_FROAM_ACL_ADD_ENTRY: + { + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("OID_802_11_ACL_ADD_ENTRY\n")); + Status = froam_add_acl_entry(pAd, wrq); + if (Status != NDIS_STATUS_SUCCESS) + Status = -NDIS_STATUS_FAILURE; + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("OID_802_11_ACL_ADD_ENTRY Status : %d\n", Status)); + } + break; + case OID_802_11_FROAM_ACL_DEL_ENTRY: + { + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("OID_802_11_ACL_DEL_ENTRY\n")); + Status = froam_del_acl_entry(pAd, wrq); + if (Status != NDIS_STATUS_SUCCESS) + Status = -NDIS_STATUS_FAILURE; + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("OID_802_11_ACL_DEL_ENTRY Status : %d\n", Status)); + } + break; +#endif +#ifdef AIR_MONITOR + case OID_AIR_MNTR_ADD_ENTRY: + { + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("OID_AIR_MNTR_ADD_ENTRY \n")); + + Status = add_mntr_entry(pAd, wrq); + + if(Status != NDIS_STATUS_SUCCESS) + { + Status = -NDIS_STATUS_FAILURE; + } + + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("OID_AIR_MNTR_ADD_ENTRY Status : %d\n", Status)); + + break; + } + + case OID_AIR_MNTR_DEL_ENTRY: + { + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("OID_AIR_MNTR_DEL_ENTRY \n")); + + Status = del_mntr_entry(pAd, wrq); + + if(Status != NDIS_STATUS_SUCCESS) + { + Status = -NDIS_STATUS_FAILURE; + } + + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("OID_AIR_MNTR_DEL_ENTRY Status : %d\n", Status)); + + break; + } + + case OID_AIR_MNTR_SET_RULE: + { + + Status = set_mntr_rule(pAd, wrq); + + if(Status != NDIS_STATUS_SUCCESS) + { + Status = -NDIS_STATUS_FAILURE; + } + + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("OID_AIR_MNTR_SET_RULE Status : %d\n", Status)); + break; + } +#endif +#ifdef WAPP_SUPPORT + case OID_802_11_WIFI_VER: { + wrq->u.data.length = strlen(AP_DRIVER_VERSION); + snprintf(&driverVersion[0], sizeof(driverVersion), "%s", AP_DRIVER_VERSION); + driverVersion[wrq->u.data.length] = '\0'; + Status = copy_to_user(wrq->u.data.pointer, driverVersion, wrq->u.data.length); + } + break; + case OID_802_11_WAPP_SUPPORT_VER: { + RTMP_STRING wapp_support_ver[16]; + wrq->u.data.length = strlen(WAPP_SUPPORT_VERSION); + snprintf(&wapp_support_ver[0], sizeof(wapp_support_ver), "%s", WAPP_SUPPORT_VERSION); + wapp_support_ver[wrq->u.data.length] = '\0'; + Status = copy_to_user(wrq->u.data.pointer, wapp_support_ver, wrq->u.data.length); + } + break; +#endif/* WAPP_SUPPORT */ +#ifdef MIXMODE_SUPPORT + case OID_SET_MIXMODE: + { + INT ret; + struct mix_peer_parameter *sta_info; + if (wrq->u.data.length == 0 || wrq->u.data.length != sizeof(struct mix_peer_parameter)) { + Status = -EFAULT; + DBGPRINT(RT_DEBUG_OFF, + ("data len is invalid, return!!!\n")); + break; + } + ret = os_alloc_mem(pAd, + (UCHAR **)&sta_info, + wrq->u.data.length); + if (ret == NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_OFF, + ("Set::OID_SET_MIXMODE\n")); + if (copy_from_user(sta_info, + wrq->u.data.pointer, wrq->u.data.length)) { + Status = -EFAULT; + DBGPRINT(RT_DEBUG_OFF, + ("%s()::copy from user fail\n", __func__)); + } else + Status = MixModeSet(pAd, sta_info, 0); + os_free_mem(NULL, sta_info); + } else { + Status = -EFAULT; + DBGPRINT(RT_DEBUG_OFF, + ("%s()::alloc memory fail\n", __func__)); + } + } + break; + case OID_CANCEL_MIXMODE: + MixModeCancel(pAd); + break; +#endif /* MIXMODE_SUPPORT */ + default: + DBGPRINT(RT_DEBUG_TRACE, ("Set::unknown IOCTL's subcmd = 0x%08x\n", cmd)); + Status = -EOPNOTSUPP; + break; + } +#ifdef WH_EZ_SETUP + if (Status == -EOPNOTSUPP) + { + Status = ez_parse_set_command(pAd, wrq, cmd); + } +#endif + + + return Status; +} + + +#define OID_EZ_MAN_STATUS 0x2012 + +INT RTMPAPQueryInformation( + IN RTMP_ADAPTER *pAd, + IN OUT RTMP_IOCTL_INPUT_STRUCT *rq, + IN INT cmd) +{ + RTMP_IOCTL_INPUT_STRUCT *wrq = (RTMP_IOCTL_INPUT_STRUCT *) rq; + INT Status = NDIS_STATUS_SUCCESS; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + RTMP_STRING driverVersion[16]; + UCHAR apidx = pObj->ioctl_if; +#ifdef WSC_AP_SUPPORT + UINT WscPinCode = 0; + PWSC_PROFILE pProfile; + PWSC_CTRL pWscControl; +#endif /* WSC_AP_SUPPORT */ + +#ifdef SNMP_SUPPORT + 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; + BSS_STRUCT *pMbss; +#endif /*HOSTAPD_SUPPORT*/ +#ifdef WH_EZ_SETUP + BSS_STRUCT *pezMbss; +#endif + +#ifdef APCLI_SUPPORT +#if defined(WPA_SUPPLICANT_SUPPORT) || defined(APCLI_DOT11W_PMF_SUPPORT) + BOOLEAN apcliEn = FALSE; + UCHAR ifIndex; + NDIS_802_11_SSID Ssid; + PAPCLI_STRUCT pApCliEntry = NULL; +#endif/*defined(WPA_SUPPLICANT_SUPPORT) || defined(APCLI_DOT11W_PMF_SUPPORT)*/ +#endif/*APCLI_SUPPORT*/ + + + NDIS_802_11_STATISTICS *pStatistics; + + + +#ifdef ANDLINK_FEATURE_SUPPORT + struct wifi_event event; + struct wifi_ioctl_sta_info sta_info; + struct wifi_ioctl_up_link uplink_stas; + REPEATER_CLIENT_ENTRY *pRepEnt = NULL; + int idx; + UCHAR isLinkValid; +#endif + INT IEEE8021X = 0, mBss_staCount = 0; + NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeMax; +#if defined(RTMP_RBUS_SUPPORT) || defined(WH_EZ_SETUP) || defined(CONFIG_MAP_SUPPORT) + struct wifi_dev *wdev = NULL; +#endif /* RTMP_RBUS_SUPPORT */ +#ifdef WH_EZ_SETUP + NDIS_802_11_PASSPHRASE *pass_phrase; +#endif + + /* For all ioctl to this function, we assume that's query for AP/APCLI/GO device */ + if ((pObj->ioctl_if_type == INT_MBSSID) || (pObj->ioctl_if_type == INT_MAIN)) + { + if (apidx >= pAd->ApCfg.BssidNum) + return EFAULT; + } + + switch(cmd) + { +#ifdef ACS_CTCC_SUPPORT + case OID_802_11_GET_ACS_CHANNEL_SCORE: + { + INT channel_idx = 0; + ACS_CHANNEL_SCORE *pchannelscore; + PCHANNELINFO pChannelInfo = pAd->pChannelInfo; + os_alloc_mem(pAd, (UCHAR **)&pchannelscore, sizeof(ACS_CHANNEL_SCORE)); + if (pchannelscore == NULL) { + printk("allocate memory is failed\n"); + Status = RTMP_IO_EFAULT; + break; + } + pchannelscore->AcsAlg = pAd->ApCfg.AutoChannelAlg; + for (channel_idx = 0; channel_idx < pAd->ChannelListNum; channel_idx++) { + pchannelscore->AcsChannelScore[channel_idx].Score = pChannelInfo->ChannelScore[channel_idx].Score; + pchannelscore->AcsChannelScore[channel_idx].Channel = pChannelInfo->ChannelScore[channel_idx].Channel; + } + wrq->u.data.length = sizeof(ACS_CHANNEL_SCORE); + Status = copy_to_user(wrq->u.data.pointer, pchannelscore, wrq->u.data.length); + if (Status != 0) { + Status = RTMP_IO_EFAULT; + DBGPRINT(RT_DEBUG_TRACE, ("%s: OID_802_11_GET_ACS_CHANNEL_SCORE is falied \n", __FUNCTION__)); + } + os_free_mem(NULL, pchannelscore); + break; + } +#endif +#ifdef NEIGHBORING_AP_STAT + case OID_CUST_SCAN_REPORT_GET: + if (wrq->u.data.pointer) + Status = ReportScanResult(pAd, wrq); + break; +#endif + case OID_802_11_MBSS_GET_STA_COUNT: + wrq->u.data.length = sizeof(INT); + mBss_staCount = pAd->ApCfg.MBSSID[apidx].StaCount; + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MBSS_GET_STA_COUNT ==> %d \n", mBss_staCount)); + Status = copy_to_user(wrq->u.data.pointer, &mBss_staCount, wrq->u.data.length); + break; +#ifdef DOT1X_SUPPORT + case OID_802_11_SET_IEEE8021X: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_SET_IEEE8021X \n")); + wrq->u.data.length = sizeof(INT); + if(pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.IEEE8021X == TRUE) + IEEE8021X=1; + else + IEEE8021X=0; + + Status = copy_to_user(wrq->u.data.pointer, &IEEE8021X, wrq->u.data.length); + break; +#endif /* DOT1X_SUPPORT */ + case OID_802_11_AUTHENTICATION_MODE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_AUTHENTICATION_MODE \n")); + wrq->u.data.length = sizeof(NDIS_802_11_AUTHENTICATION_MODE); + AuthMode=pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.AuthMode; + Status = copy_to_user(wrq->u.data.pointer, &AuthMode, wrq->u.data.length); + break; + +#if defined(MT7603) || defined(MT7628) + case OID_GET_CPU_TEMPERATURE:{ + + INT32 temperature = 0; + + temperature = MtAsicGetThemalSensor(pAd, 0); + DBGPRINT(RT_DEBUG_OFF, ("CurrentTemperature = %d\n", temperature)); + wrq->u.data.length = sizeof(INT32); + Status = copy_to_user(wrq->u.data.pointer, &temperature, wrq->u.data.length); + break; + } +#endif + +#ifdef APCLI_SUPPORT +#if defined(WPA_SUPPLICANT_SUPPORT) || defined(APCLI_DOT11W_PMF_SUPPORT) + + 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; +#ifndef APCLI_DOT11W_PMF_SUPPORT + 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 + +/*PMF STA Sigma DUT will call this IOCTL to get the BSSID. */ + + if (1) { + Status = copy_to_user(wrq->u.data.pointer, + pApCliEntry->MlmeAux.Bssid, + sizeof(NDIS_802_11_MAC_ADDRESS)); + DBGPRINT(RT_DEBUG_ERROR, + ("IOCTL::SIOCGIWAP(=%02x:%02x:%02x:%02x:%02x:%02x)\n", + PRINT_MAC(pApCliEntry->MlmeAux.Bssid))); + + } +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + 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) +#ifndef WH_EZ_SETUP + return FALSE; +#endif +#ifdef WH_EZ_SETUP + { +#endif + + 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); +#ifdef WH_EZ_SETUP + } +#endif +#ifdef WH_EZ_SETUP + else { + ifIndex = pObj->ioctl_if; + NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID)); + + BSS_STRUCT *ap_mbss; + ap_mbss = &pAd->ApCfg.MBSSID[ifIndex]; + Ssid.SsidLength = ap_mbss->SsidLen; + NdisMoveMemory(Ssid.Ssid, ap_mbss->Ssid, Ssid.SsidLength); + } +#endif + 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/*defined(WPA_SUPPLICANT_SUPPORT) || defined(APCLI_DOT11W_PMF_SUPPORT)*/ +#endif/*APCLI_SUPPORT*/ + +#ifdef ANDLINK_FEATURE_SUPPORT + case OID_ANDLINK_POLL: + event.type = EVENTTYPE_INF_POLL; + event.data.poll.channel = pAd->CommonCfg.Channel; + memcpy(event.MAC, pAd->ApCfg.MBSSID[apidx].wdev.bssid, MAC_ADDR_LEN); + memcpy(event.SSID, pAd->ApCfg.MBSSID[apidx].Ssid, MAX_LEN_OF_SSID); + + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_ANDLINK_EVENT, + NULL, + (char *)&event, + sizeof(struct wifi_event)); + + Status = NDIS_STATUS_SUCCESS; + break; + case OID_ANDLINK_STAINFO: + memset(&sta_info, 0, sizeof(struct wifi_ioctl_sta_info)); + sta_info.sta_cnt = 0; + sta_info.rept_sta_cnt=0; + + for (idx = 0; idx < MAX_LEN_OF_MAC_TABLE; idx++) { + MAC_TABLE_ENTRY *pEnt = &pAd->MacTab.Content[idx]; + if ((IS_ENTRY_CLIENT(pEnt) || IS_ENTRY_APCLI(pEnt)) + && (pEnt->Sst != SST_ASSOC)) + continue; +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn && pEnt && IS_ENTRY_APCLI(pEnt) + && (pEnt->Sst == SST_ASSOC) && (pEnt->bReptCli)) { + pRepEnt = RTMPLookupRepeaterCliEntry(pAd, FALSE, pEnt->ReptCliAddr, TRUE, &isLinkValid); + memcpy(sta_info.rept_item[sta_info.rept_sta_cnt].MacAddress, pRepEnt->OriginalAddress, MAC_ADDR_LEN); + memcpy(sta_info.rept_item[sta_info.rept_sta_cnt].VMacAddr, pEnt->ReptCliAddr, MAC_ADDR_LEN); + sta_info.rept_sta_cnt++; + } +#endif//#endif MAC_REPEATER_SUPPORT + if (pEnt->Sst == SST_ASSOC && pEnt->EntryType == ENTRY_CLIENT) { + memset(sta_info.item[sta_info.sta_cnt].MacAddress, 0, MAC_ADDR_LEN); + memset(sta_info.item[sta_info.sta_cnt].VMacAddr, 0, MAC_ADDR_LEN); + memcpy(sta_info.item[sta_info.sta_cnt].MacAddress, pEnt->Addr, MAC_ADDR_LEN); +#ifdef MAC_REPEATER_SUPPORT + pRepEnt = RTMPLookupRepeaterCliEntry(pAd, TRUE, pEnt->Addr, TRUE, &isLinkValid); + if(pRepEnt != NULL && pAd->ApCfg.bMACRepeaterEn) { + memcpy(sta_info.item[sta_info.sta_cnt].VMacAddr, pRepEnt->CurrentAddress, MAC_ADDR_LEN); + } else +#endif//#endif MAC_REPEATER_SUPPORT + + memcpy(sta_info.item[sta_info.sta_cnt].VMacAddr, pEnt->Addr, MAC_ADDR_LEN); + + + /* RSSI */ + sta_info.item[sta_info.sta_cnt].RSSI = RTMPMaxRssi(pAd, pEnt->RssiSample.AvgRssi[0], + pEnt->RssiSample.AvgRssi[1],pEnt->RssiSample.AvgRssi[2]); + + ANDLINK_GET_CURRENT_SEC(&sta_info.item[sta_info.sta_cnt].UpTime); + sta_info.item[sta_info.sta_cnt].UpTime -= pEnt->upTime; + + getRate(pEnt->HTPhyMode, &sta_info.item[sta_info.sta_cnt].TxRate); + sta_info.item[sta_info.sta_cnt].RxRate = sta_info.item[sta_info.sta_cnt].TxRate; + + sta_info.sta_cnt++; + } + } + + if (wrq->u.data.length >= sizeof(struct wifi_ioctl_sta_info)) { + wrq->u.data.length = sizeof(struct wifi_ioctl_sta_info); + Status = copy_to_user(wrq->u.data.pointer, &sta_info, wrq->u.data.length); + } else + Status = -EFAULT; + + break; + case OID_ANDLINK_UPLINK: + memset(&uplink_stas, 0, sizeof(struct wifi_ioctl_up_link)); + memset(uplink_stas.MAC, 0, MAC_ADDR_LEN); + memcpy(uplink_stas.MAC, pAd->ApCfg.ApCliTab[0].wdev.if_addr, MAC_ADDR_LEN);//mac + memset(uplink_stas.SSID, 0, MAX_LEN_OF_SSID); + memcpy(uplink_stas.SSID,pAd->ApCfg.ApCliTab[0].Ssid, MAX_LEN_OF_SSID);//ssid + for (idx = 0; idx < MAX_LEN_OF_MAC_TABLE; idx++) { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[idx]; + if (IS_ENTRY_APCLI(pEntry) && pEntry->Sst==SST_ASSOC && (!pEntry->bReptCli)) + { + UINT8 ShortGI=0; + UINT8 BW=0; + UINT8 MCS=0; + UINT32 lastRxRate = pEntry->LastRxRate; + UINT32 lastTxRate = pEntry->LastTxRate; + uplink_stas.Channel = pAd->CommonCfg.Channel;//channel + printk("\n%s:%d Channel: %d\n", __FUNCTION__,__LINE__, uplink_stas.Channel); + uplink_stas.SNR = RTMPMinSnr(pAd, pAd->ApCfg.ApCliTab->wdev.LastSNR0, + pAd->ApCfg.ApCliTab->wdev.LastSNR1); + uplink_stas.RSSI = RTMPMaxRssi(pAd, pEntry->RssiSample.LastRssi[0], + pEntry->RssiSample.LastRssi[1], + pEntry->RssiSample.LastRssi[2]);//rssi + uplink_stas.Noise = uplink_stas.RSSI - uplink_stas.SNR;//noise + /*TXRate*/ + MCS = lastTxRate & 0x7F; + ShortGI = (lastTxRate>>8) & 0x1; + BW = (lastTxRate>>7) & 0x1; + pEntry->HTPhyMode.field.BW = BW; + pEntry->HTPhyMode.field.ShortGI = ShortGI; + pEntry->HTPhyMode.field.MCS = MCS; + getRate(pEntry->HTPhyMode, (ULONG *)&uplink_stas.TxRate); + /*RXRate*/ + MCS = lastRxRate & 0x7F; + ShortGI = (lastRxRate>>8) & 0x1; + BW = (lastRxRate>>7) & 0x1; + pEntry->HTPhyMode.field.BW = BW; + pEntry->HTPhyMode.field.ShortGI = ShortGI; + pEntry->HTPhyMode.field.MCS = MCS; + getRate(pEntry->HTPhyMode, (ULONG *)&uplink_stas.RxRate); + break; + } + } + if (wrq->u.data.length >= sizeof(struct wifi_ioctl_up_link)) { + wrq->u.data.length = sizeof(struct wifi_ioctl_up_link); + Status = copy_to_user(wrq->u.data.pointer, &uplink_stas, wrq->u.data.length); + } else + Status = -EFAULT; + break; +#endif/* ANDLINK_FEATURE_SUPPORT */ + case RT_OID_VERSION_INFO: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_VERSION_INFO \n")); + wrq->u.data.length = strlen(AP_DRIVER_VERSION); + snprintf(&driverVersion[0], sizeof(driverVersion), "%s", AP_DRIVER_VERSION); + driverVersion[wrq->u.data.length] = '\0'; + if (copy_to_user(wrq->u.data.pointer, &driverVersion, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + +#if (defined(VENDOR_FEATURE6_SUPPORT) || defined(MAP_SUPPORT)) + 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); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("Query::OID_802_11_COEXISTENCE (=%d)\n", pAd->CommonCfg.bBssCoexEnable)); + break; +#endif + + case OID_802_11_NETWORK_TYPES_SUPPORTED: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_NETWORK_TYPES_SUPPORTED\n")); + wrq->u.data.length = sizeof(UCHAR); + if (copy_to_user(wrq->u.data.pointer, &pAd->RfIcType, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + +#ifdef IAPP_SUPPORT + case RT_QUERY_SIGNAL_CONTEXT: + { + BOOLEAN FlgIs11rSup = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_QUERY_SIGNAL_CONTEXT \n")); + +#ifdef DOT11R_FT_SUPPORT + FlgIs11rSup = TRUE; +#endif /* DOT11R_FT_SUPPORT */ + + if (FlgIs11rSup == FALSE) + { + { + Status = -EFAULT; + } + } +#ifdef DOT11R_FT_SUPPORT + else + { + FT_KDP_SIGNAL *pFtKdp; + FT_KDP_EVT_HEADER *pEvtHdr; + + + /* query signal content for 11r */ + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_QUERY_FT_KDP_CONTEXT \n")); + + FT_KDP_EventGet(pAd, &pFtKdp); + if (pFtKdp != NULL) + pEvtHdr = (FT_KDP_EVT_HEADER *)pFtKdp->Content; + /* End of if */ + + if ((pFtKdp != NULL) && + ((RT_SIGNAL_STRUC_HDR_SIZE + pEvtHdr->EventLen) <= + wrq->u.data.length)) + { + /* copy the event */ + if (copy_to_user( + wrq->u.data.pointer, + pFtKdp, + RT_SIGNAL_STRUC_HDR_SIZE + pEvtHdr->EventLen)) + { + wrq->u.data.length = 0; + Status = -EFAULT; + } + else + { + wrq->u.data.length = RT_SIGNAL_STRUC_HDR_SIZE; + wrq->u.data.length += pEvtHdr->EventLen; + } + + FT_MEM_FREE(pAd, pFtKdp); + } + else + { + /* no event is queued */ + DBGPRINT(RT_DEBUG_TRACE, ("ft_kdp> no event is queued!\n")); + wrq->u.data.length = 0; + } + } +#endif /* DOT11R_FT_SUPPORT */ + } + break; + +#ifdef DOT11R_FT_SUPPORT + case RT_FT_DATA_ENCRYPT: + case RT_FT_DATA_DECRYPT: + { + UCHAR *pBuffer; + UINT32 DataLen; + + DataLen = wrq->u.data.length; + + /* + Make sure the data length is multiple of 8 + due to AES_KEY_WRAP() limitation. + */ + if (DataLen & 0x07) + DataLen += 8 - (DataLen & 0x07); + /* End of if */ + + FT_MEM_ALLOC(pAd, &pBuffer, DataLen+FT_KDP_KEY_ENCRYPTION_EXTEND); + if (pBuffer == NULL) + break; + NdisZeroMemory(pBuffer, DataLen+FT_KDP_KEY_ENCRYPTION_EXTEND); + + if (copy_from_user(pBuffer, wrq->u.data.pointer, wrq->u.data.length)) + { + Status = -EFAULT; + FT_MEM_FREE(pAd, pBuffer); + break; + } + + switch(cmd) + { + case RT_FT_DATA_ENCRYPT: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_FT_DATA_ENCRYPT \n")); + FT_KDP_DataEncrypt(pAd, (UCHAR *)pBuffer, &DataLen); + break; + + case RT_FT_DATA_DECRYPT: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_FT_DATA_DECRYPT \n")); + FT_KDP_DataDecrypt(pAd, (UCHAR *)pBuffer, &DataLen); + break; + } + + wrq->u.data.length = DataLen; + if (copy_to_user(wrq->u.data.pointer, pBuffer, wrq->u.data.length)) + Status = -EFAULT; + FT_MEM_FREE(pAd, pBuffer); + } + break; + + case RT_OID_802_11R_INFO: + { + UCHAR apidx = pObj->ioctl_if; + PFT_CONFIG_INFO pFtConfig; + PFT_CFG pFtCfg; + + os_alloc_mem(pAd, (UCHAR **)&pFtConfig, sizeof(FT_CONFIG_INFO)); + if (pFtConfig == NULL) + break; + + pFtCfg = &pAd->ApCfg.MBSSID[apidx].FtCfg; + NdisZeroMemory(pFtConfig, sizeof(FT_CONFIG_INFO)); + + pFtConfig->FtSupport = pFtCfg->FtCapFlag.Dot11rFtEnable; + pFtConfig->FtRicSupport = pFtCfg->FtCapFlag.RsrReqCap; + pFtConfig->FtOtdSupport = pFtCfg->FtCapFlag.FtOverDs; + NdisMoveMemory(pFtConfig->MdId, pFtCfg->FtMdId, FT_MDID_LEN); + pFtConfig->R0KHIdLen = pFtCfg->FtR0khIdLen; + NdisMoveMemory(pFtConfig->R0KHId, pFtCfg->FtR0khId, pFtCfg->FtR0khIdLen); + + wrq->u.data.length = sizeof(FT_CONFIG_INFO); + Status = copy_to_user(wrq->u.data.pointer, pFtConfig, wrq->u.data.length); + os_free_mem(NULL, pFtConfig); + } + break; +#endif /* DOT11R_FT_SUPPORT */ + +#endif /* IAPP_SUPPORT */ + + +#ifdef CONFIG_DOT11V_WNM + case RT_QUERY_WNM_CAPABILITY: + { + PUCHAR p_wnm_query_data = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + PUINT8 p_cap = NULL; + struct wnm_command *p_wnm_command = NULL; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[apidx].WNMCtrl; + UINT16 TotalLen = 0; + + TotalLen = wrq->u.data.length; + if (TotalLen != sizeof(*p_wnm_command) + MAC_ADDR_LEN + 1) { + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("RT_QUERY_WNM_CAPABILITY: length(%d) check failed\n", + TotalLen)); + Status = EINVAL; + break; + } + + if (!pWNMCtrl->WNMBTMEnable) { + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("RT_QUERY_WNM_CAPABILITY: btm off\n")); + Status = EINVAL; + break; + } + + os_alloc_mem(NULL, (UCHAR **)&p_wnm_command, wrq->u.data.length); + if (p_wnm_command == NULL) { + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("RT_QUERY_WNM_CAPABILITY: no memory!!!\n")); + Status = ENOMEM; + break; + } + + if (copy_from_user(p_wnm_command, wrq->u.data.pointer, wrq->u.data.length)) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("RT_QUERY_WNM_CAPABILITY: copy from user failed!\n")); + Status = EFAULT; + os_free_mem(NULL, p_wnm_command); + break; + } + + p_wnm_query_data = p_wnm_command->command_body; + + /*first six bytes of data is sta mac*/ + pEntry = MacTableLookup(pAd, p_wnm_query_data); + if (!pEntry || !((Ndis802_11AuthModeAutoSwitch >= + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.AuthMode) || + ((pEntry->WpaState == AS_PTKINITDONE) && + (pEntry->GTKState == REKEY_ESTABLISHED)))) { + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("RT_QUERY_WNM_CAPABILITY: ")); + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("STA(%02x:%02x:%02x:%02x:%02x:%02x) not associates with AP!\n", + PRINT_MAC(p_wnm_query_data))); + Status = EINVAL; + os_free_mem(NULL, p_wnm_command); + break; + } + /*check for btm capablility*/ + p_cap = (UINT8 *)(p_wnm_query_data+MAC_ADDR_LEN); + *p_cap = 0; + + if (p_wnm_command->command_id == + OID_802_11_WNM_CMD_QUERY_BTM_CAP) { + if (pEntry->BssTransitionManmtSupport) { + *p_cap = 1; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("RT_QUERY_WNM_CAPABILITY: BTMCap=%d\n", (*p_cap))); + } + } else { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("RT_QUERY_WNM_CAPABILITY: only check btm cap now\n")); + Status = EINVAL; + os_free_mem(NULL, p_wnm_command); + break; + } + if (copy_to_user(wrq->u.data.pointer, (PUCHAR)p_wnm_command, wrq->u.data.length)) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("RT_QUERY_WNM_CAPABILITY: copy to user failed!\n")); + Status = EFAULT; + os_free_mem(NULL, p_wnm_command); + break; + } + os_free_mem(NULL, p_wnm_command); + break; + } +#endif +#ifdef DOT11K_RRM_SUPPORT + case RT_QUERY_RRM_CAPABILITY: + { + PUCHAR p_rrm_query_data = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + p_rrm_command_t p_rrm_command = NULL; + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; + PUINT8 p_cap = NULL; + UINT16 TotalLen = 0; + + TotalLen = wrq->u.data.length; + if (TotalLen != sizeof(*p_rrm_command) + MAC_ADDR_LEN + 8) { + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("RT_QUERY_RRM_CAPABILITY: length(%d) check failed\n", + TotalLen)); + Status = EINVAL; + break; + } + if (!pMbss->RrmCfg.bDot11kRRMEnable) { + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("RT_QUERY_RRM_CAPABILITY: rrm off\n")); + Status = EINVAL; + break; + } + os_alloc_mem(NULL, (UCHAR **)&p_rrm_command, wrq->u.data.length); + if (p_rrm_command == NULL) { + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_RRM, DBG_LVL_ERROR, + ("RT_QUERY_RRM_CAPABILITY : no memory!!!\n")); + Status = ENOMEM; + break; + } + + if (copy_from_user(p_rrm_command, wrq->u.data.pointer, wrq->u.data.length)) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("RT_QUERY_RRM_CAPABILITY: copy from user failed!\n")); + Status = EFAULT; + os_free_mem(NULL, p_rrm_command); + break; + } + + p_rrm_query_data = p_rrm_command->command_body; + + /*first six bytes of data is sta mac*/ + pEntry = MacTableLookup(pAd, p_rrm_query_data); + if (!pEntry || !((Ndis802_11AuthModeAutoSwitch >= + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.AuthMode) || + ((pEntry->WpaState == AS_PTKINITDONE) && + (pEntry->GTKState == REKEY_ESTABLISHED)))) { + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("RT_QUERY_RRM_CAPABILITY: ")); + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("STA(%02x:%02x:%02x:%02x:%02x:%02x) not associates with AP!\n", + PRINT_MAC(p_rrm_query_data))); + Status = EINVAL; + os_free_mem(NULL, p_rrm_command); + break; + } + /*check for btm capablility*/ + p_cap = (UINT8 *)(p_rrm_query_data+MAC_ADDR_LEN); + memset(p_cap, 0, 8); + + if (p_rrm_command->command_id == + OID_802_11_RRM_CMD_QUERY_CAP) { + memcpy(p_cap, (PUCHAR)&(pEntry->RrmEnCap), sizeof(pEntry->RrmEnCap)); + } else { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("RT_QUERY_WNM_CAPABILITY: only check rrm cap now\n")); + Status = EINVAL; + os_free_mem(NULL, p_rrm_command); + break; + } + if (copy_to_user(wrq->u.data.pointer, (PUCHAR)p_rrm_command, wrq->u.data.length)) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("RT_QUERY_RRM_CAPABILITY: copy to user failed!\n")); + Status = EFAULT; + os_free_mem(NULL, p_rrm_command); + break; + } + os_free_mem(NULL, p_rrm_command); + break; + } +#endif + +#ifdef WSC_AP_SUPPORT + case RT_OID_WSC_QUERY_STATUS: + { + INT WscStatus; + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_QUERY_STATUS \n")); +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + INT ApCliIdx = pObj->ioctl_if; + APCLI_MR_APIDX_SANITY_CHECK(ApCliIdx); + WscStatus = pAd->ApCfg.ApCliTab[ApCliIdx].WscControl.WscStatus; + } + else +#endif /* APCLI_SUPPORT */ + { + WscStatus = pAd->ApCfg.MBSSID[apidx].WscControl.WscStatus; + } + + wrq->u.data.length = sizeof(INT); + if (copy_to_user(wrq->u.data.pointer, &WscStatus, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + } + case RT_OID_WSC_PIN_CODE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_PIN_CODE \n")); + wrq->u.data.length = sizeof(UINT); + /*WscPinCode = GenerateWpsPinCode(pAd, FALSE, apidx); */ + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + + WscPinCode = pWscControl->WscEnrolleePinCode; + if (copy_to_user(wrq->u.data.pointer, &WscPinCode, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; +#ifdef APCLI_SUPPORT + case RT_OID_APCLI_WSC_PIN_CODE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_APCLI_WSC_PIN_CODE \n")); + wrq->u.data.length = sizeof(UINT); + /*WscPinCode = GenerateWpsPinCode(pAd, TRUE, apidx); */ + WscPinCode = pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCode; + + if (copy_to_user(wrq->u.data.pointer, &WscPinCode, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; +#endif /* APCLI_SUPPORT */ + + case OID_WSC_UUID: + { + int i = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_WSC_QUERY_UUID\n")); + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + wrq->u.data.length = UUID_LEN_HEX; + if (copy_to_user(wrq->u.data.pointer, &pWscControl->Wsc_Uuid_E[0], UUID_LEN_HEX)) + Status = -EFAULT; + + DBGPRINT(RT_DEBUG_TRACE, ("7603 The UUID Hex string is:")); + for (i = 0; i < UUID_LEN_HEX; i++) + DBGPRINT(RT_DEBUG_TRACE, ("%02x", (pWscControl->Wsc_Uuid_E[i]))); + DBGPRINT(RT_DEBUG_TRACE, ("\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; + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + if (copy_to_user(wrq->u.data.pointer, &pWscControl->Wsc_Uuid_Str[0], UUID_LEN_STR)) + { + Status = -EFAULT; + } + break; + case RT_OID_WSC_MAC_ADDRESS: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_MAC_ADDRESS \n")); + wrq->u.data.length = MAC_ADDR_LEN; + if (copy_to_user(wrq->u.data.pointer, pAd->ApCfg.MBSSID[apidx].wdev.bssid, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + case RT_OID_WSC_CONFIG_STATUS: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_CONFIG_STATUS \n")); + wrq->u.data.length = sizeof(UCHAR); + if (copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[apidx].WscControl.WscConfStatus, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + + case RT_OID_WSC_QUERY_PEER_INFO_ON_RUNNING: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_QUERY_PEER_INFO_ON_RUNNING \n")); + + if (pAd->ApCfg.MBSSID[apidx].WscControl.WscState > WSC_STATE_WAIT_M2) + { + wrq->u.data.length = sizeof(WSC_PEER_DEV_INFO); + if (copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[apidx].WscControl.WscPeerInfo, wrq->u.data.length)) + { + Status = -EFAULT; + } + } + else + { + Status = -EFAULT; + } + break; + + case RT_OID_802_11_WSC_QUERY_PROFILE: + wrq->u.data.length = sizeof(WSC_PROFILE); + os_alloc_mem(pAd, (UCHAR **)&pProfile, sizeof(WSC_PROFILE)); + if (pProfile == NULL) + { + Status = -EFAULT; + DBGPRINT(RT_DEBUG_TRACE, ("RT_OID_802_11_WSC_QUERY_PROFILE fail!\n")); + break; + } + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + + RTMPZeroMemory(pProfile, sizeof(WSC_PROFILE)); + NdisMoveMemory(pProfile, &pWscControl->WscProfile, sizeof(WSC_PROFILE)); + if ((pProfile->Profile[0].AuthType == WSC_AUTHTYPE_OPEN) && (pProfile->Profile[0].EncrType == WSC_ENCRTYPE_NONE)) + { + pProfile->Profile[0].KeyLength = 0; + NdisZeroMemory(pProfile->Profile[0].Key, 64); + } + if (copy_to_user(wrq->u.data.pointer, pProfile, wrq->u.data.length)) + { + Status = -EFAULT; + } + + os_free_mem(NULL, pProfile); + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_WSC_QUERY_PROFILE \n")); + break; +#ifdef WSC_V2_SUPPORT + case RT_OID_WSC_V2_SUPPORT: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_V2_SUPPORT (=%d)\n", pAd->ApCfg.MBSSID[apidx].WscControl.WscV2Info.bEnableWpsV2)); + wrq->u.data.length = sizeof(BOOLEAN); + if (copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[apidx].WscControl.WscV2Info.bEnableWpsV2, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; + case RT_OID_WSC_FRAGMENT_SIZE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_WSC_FRAGMENT_SIZE (=%d)\n", pAd->ApCfg.MBSSID[apidx].WscControl.WscFragSize)); + wrq->u.data.length = sizeof(USHORT); + if (copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[apidx].WscControl.WscFragSize, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; +#endif /* WSC_V2_SUPPORT */ + +#ifdef WSC_NFC_SUPPORT + case RT_OID_NFC_STATUS: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_NFC_STATUS (=%d)\n", pAd->ApCfg.MBSSID[apidx].WscControl.NfcStatus)); + wrq->u.data.length = sizeof(UCHAR); + if (copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[apidx].WscControl.NfcStatus, wrq->u.data.length)) + { + Status = -EFAULT; + } + break; +#endif /* WSC_NFC_SUPPORT */ + +#endif /* WSC_AP_SUPPORT */ +#ifdef LLTD_SUPPORT + case RT_OID_GET_LLTD_ASSO_TABLE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::Get LLTD association table\n")); + if ((wrq->u.data.pointer == NULL) || (apidx != MAIN_MBSSID)) + { + Status = -EFAULT; + } + else + { + INT i; + RT_LLTD_ASSOICATION_TABLE AssocTab; + + AssocTab.Num = 0; + for (i=0; iMacTab.Content[i]) && (pAd->MacTab.Content[i].Sst == SST_ASSOC)) + { + 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 DOT1X_SUPPORT + case OID_802_DOT1X_CONFIGURATION: + DBGPRINT(RT_DEBUG_TRACE, ("Query::Get Radius setting(%u)\n", sizeof(DOT1X_CMM_CONF))); + RTMPIoctlQueryRadiusConf(pAd, wrq); + break; + + case OID_802_DOT1X_QUERY_STA_AID: + RTMPIoctlQueryStaAid(pAd, wrq); + break; + +#endif /* DOT1X_SUPPORT */ + + case RT_OID_802_11_MAC_ADDRESS: + wrq->u.data.length = MAC_ADDR_LEN; + Status = copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[apidx].wdev.bssid, wrq->u.data.length); + break; + +#ifdef SNMP_SUPPORT + case RT_OID_802_11_MANUFACTUREROUI: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTUREROUI \n")); + wrq->u.data.length = ManufacturerOUI_LEN; + Status = copy_to_user(wrq->u.data.pointer, &pAd->CurrentAddress, wrq->u.data.length); + break; + + case RT_OID_802_11_MANUFACTURERNAME: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MANUFACTURERNAME \n")); + wrq->u.data.length = strlen(ManufacturerNAME); + Status = copy_to_user(wrq->u.data.pointer, ManufacturerNAME, wrq->u.data.length); + break; + + case RT_OID_802_11_RESOURCETYPEIDNAME: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_RESOURCETYPEIDNAME \n")); + wrq->u.data.length = strlen(ResourceTypeIdName); + Status = copy_to_user(wrq->u.data.pointer, ResourceTypeIdName, wrq->u.data.length); + break; + + case RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED: + { + ULONG ulInfo; + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED \n")); + ulInfo = 1; /* 1 is support wep else 2 is not support. */ + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + } + case RT_OID_802_11_POWERMANAGEMENTMODE: + { + ULONG ulInfo; + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_POWERMANAGEMENTMODE \n")); + ulInfo = 1; /* 1 is power active else 2 is power save. */ + wrq->u.data.length = sizeof(ulInfo); + Status = copy_to_user(wrq->u.data.pointer, &ulInfo, wrq->u.data.length); + break; + } + case OID_802_11_WEPDEFAULTKEYVALUE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WEPDEFAULTKEYVALUE \n")); + pKeyIdxValue = 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); + ShortRetryLimit = AsicGetRetryLimit(pAd, TX_RTY_CFG_RTY_LIMIT_SHORT); + DBGPRINT(RT_DEBUG_TRACE, ("ShortRetryLimit =%ld\n", ShortRetryLimit)); + Status = copy_to_user(wrq->u.data.pointer, &ShortRetryLimit, wrq->u.data.length); + break; + + case OID_802_11_LONGRETRYLIMIT: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_LONGRETRYLIMIT \n")); + wrq->u.data.length = sizeof(ULONG); + LongRetryLimit = AsicGetRetryLimit(pAd, TX_RTY_CFG_RTY_LIMIT_LONG); + DBGPRINT(RT_DEBUG_TRACE, ("LongRetryLimit =%ld\n", LongRetryLimit)); + Status = copy_to_user(wrq->u.data.pointer, &LongRetryLimit, wrq->u.data.length); + break; + + case RT_OID_802_11_PRODUCTID: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_PRODUCTID \n")); + +#ifdef RTMP_MAC_PCI + { + + USHORT device_id; + if (((POS_COOKIE)pAd->OS_Cookie)->pci_dev != NULL) + pci_read_config_word(((POS_COOKIE)pAd->OS_Cookie)->pci_dev, PCI_DEVICE_ID, &device_id); + else + DBGPRINT(RT_DEBUG_TRACE, (" pci_dev = NULL\n")); + snprintf((RTMP_STRING *)snmp_tmp, sizeof(snmp_tmp), "%04x %04x\n", NIC_PCI_VENDOR_ID, device_id); + } +#endif /* RTMP_MAC_PCI */ + wrq->u.data.length = strlen((RTMP_STRING *) 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; + + case OID_802_11_CURRENTCHANNEL: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_CURRENTCHANNEL \n")); + wrq->u.data.length = sizeof(UCHAR); + DBGPRINT(RT_DEBUG_TRACE, ("sizeof UCHAR=%d, channel=%d \n", sizeof(UCHAR), pAd->CommonCfg.Channel)); + Status = copy_to_user(wrq->u.data.pointer, &pAd->CommonCfg.Channel, wrq->u.data.length); + DBGPRINT(RT_DEBUG_TRACE, ("Status=%d\n", Status)); + break; +#endif /* SNMP_SUPPORT */ + + case OID_802_11_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); + os_free_mem(NULL, pStatistics); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_STATISTICS(mem alloc failed)\n")); + Status = -EFAULT; + } + break; +#ifdef ACL_BLK_COUNT_SUPPORT + case OID_802_11_ACL_BLK_REJCT_COUNT_STATICS: + { + int count = 0; + ULONG Policy; + ULONG Num; + ULONG Reject_Count = 0; + UCHAR *pAddr; + + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_ACL_BLK_REJCT_COUNT_STATICS \n")); + wrq->u.data.length = sizeof(RT_802_11_ACL); + Policy = pAd->ApCfg.MBSSID[apidx].AccessControlList.Policy; + Num = pAd->ApCfg.MBSSID[apidx].AccessControlList.Num; + pAddr = (pAd->ApCfg.MBSSID[apidx].AccessControlList.Entry[count].Addr); + DBGPRINT(RT_DEBUG_TRACE, ("(%s): AccessControlList: ACL: Policy=%lu ACL: Num=%lu \n", __func__, (ULONG)Policy, (ULONG)Num)); + if (Policy == 2) + Status = copy_to_user(wrq->u.data.pointer, + &pAd->ApCfg.MBSSID[apidx].AccessControlList, wrq->u.data.length); + else { + for (count = 0; count < pAd->ApCfg.MBSSID[apidx].AccessControlList.Num; count++) + pAd->ApCfg.MBSSID[apidx].AccessControlList.Entry[count].Reject_Count = 0; + Status = copy_to_user(wrq->u.data.pointer, + &pAd->ApCfg.MBSSID[apidx].AccessControlList, wrq->u.data.length); + } + DBGPRINT(RT_DEBUG_TRACE, ("(%s):Status=%d(0:SUCCESS,1:FAILURE)\n", __func__, Status)); + for (count = 0; count < pAd->ApCfg.MBSSID[apidx].AccessControlList.Num; count++) { + pAddr = pAd->ApCfg.MBSSID[apidx].AccessControlList.Entry[count].Addr; + DBGPRINT(RT_DEBUG_TRACE, ("MAC:%02x:%02x:%02x:%02x:%02x:%02x", + pAddr[0], pAddr[1], pAddr[2], pAddr[3], pAddr[4], pAddr[5])); + Reject_Count = pAd->ApCfg.MBSSID[apidx].AccessControlList.Entry[count].Reject_Count; + DBGPRINT(RT_DEBUG_TRACE, (", Count: %lu\n", (ULONG)Reject_Count)); + } + break; + } +#endif/*ACL_BLK_COUNT_SUPPORT*/ + case RT_OID_802_11_PER_BSS_STATISTICS: + { + PMBSS_STATISTICS pMbssStat; + INT apidx = pObj->ioctl_if; + BSS_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 +#endif /* DOT11_N_SUPPORT */ + + +#ifdef WAPI_SUPPORT + case OID_802_11_MCAST_TXIV: + DBGPRINT(RT_DEBUG_TRACE, ("Query::RT_OID_802_11_MCAST_TXIV \n")); + Status = -EINVAL; + break; + case OID_802_11_WAPI_CONFIGURATION: + DBGPRINT(RT_DEBUG_TRACE, ("Query::Get WAPI Configuration(%d)\n", sizeof(WAPI_CONF))); + RTMPIoctlQueryWapiConf(pAd, wrq); + break; + case OID_802_11_WAPI_IE: + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WAPI_IE\n")); + if (wrq->u.data.length != sizeof(WAPI_WIE_STRUCT)) + Status = -EINVAL; + else + { + WAPI_WIE_STRUCT wapi_ie; + MAC_TABLE_ENTRY *pWapiEntry; + + NdisZeroMemory(&wapi_ie, sizeof(WAPI_WIE_STRUCT)); + NdisMoveMemory(wapi_ie.addr, wrq->u.data.pointer, MAC_ADDR_LEN); + + pWapiEntry = MacTableLookup(pAd, wapi_ie.addr); + + if (pWapiEntry && IS_ENTRY_CLIENT(pWapiEntry) && (pWapiEntry->RSNIE_Len > 0)) + { + wapi_ie.wie_len = pWapiEntry->RSNIE_Len; + NdisMoveMemory(wapi_ie.wie, pWapiEntry->RSN_IE, pWapiEntry->RSNIE_Len); + } + + if (copy_to_user(wrq->u.data.pointer, &wapi_ie, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + } + break; + + case OID_802_11_MCAST_KEY_INFO: + { + BSS_STRUCT *pMbss; + WAPI_MCAST_KEY_STRUCT wapi_mkey; + + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_MCAST_KEY_INFO\n")); + + pMbss = &pAd->ApCfg.MBSSID[pObj->ioctl_if]; + NdisZeroMemory(&wapi_mkey, sizeof(WAPI_MCAST_KEY_STRUCT)); + + if (pMbss->sw_wpi_encrypt) + { + NdisMoveMemory(wapi_mkey.m_tx_iv, + pAd->SharedKey[pObj->ioctl_if][pMbss->wdev.DefaultKeyId].TxTsc, + LEN_WAPI_TSC); + } + else + { + INT m_wcid; + + GET_GroupKey_WCID(pAd, m_wcid, apidx); + RTMPGetWapiTxTscFromAsic(pAd, m_wcid, wapi_mkey.m_tx_iv); + } + wapi_mkey.key_id = pMbss->wdev.DefaultKeyId; + NdisMoveMemory(wapi_mkey.key_announce, pMbss->key_announce_flag, LEN_WAPI_TSC); + NdisMoveMemory(wapi_mkey.NMK, pMbss->NMK, 16); + + wrq->u.data.length = sizeof(WAPI_MCAST_KEY_STRUCT); + Status = copy_to_user(wrq->u.data.pointer, &wapi_mkey, wrq->u.data.length); + } + break; + +#endif /* WAPI_SUPPORT */ + +#ifdef HOSTAPD_SUPPORT + + case HOSTAPD_OID_GETWPAIE:/*report wpa ie of the new station to hostapd. */ + + if (wrq->u.data.length != sizeof(wpaie)) + { + Status = -EINVAL; + } + else if (copy_from_user(&wpaie, wrq->u.data.pointer, IEEE80211_ADDR_LEN)) + { + Status = -EFAULT; + } + else + { + pEntry = MacTableLookup(pAd, wpaie.wpa_macaddr); + if (!pEntry){ + Status = -EINVAL; + break; + } + NdisZeroMemory(wpaie.rsn_ie,sizeof(wpaie.rsn_ie)); + /* For WPA1, RSN_IE=221 */ + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || (pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) + ||(pEntry->AuthMode == Ndis802_11AuthModeWPA2) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) + || (pEntry->AuthMode == Ndis802_11AuthModeWPA1WPA2) ||(pEntry->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + ) + { + int ielen = pEntry->RSNIE_Len; + DBGPRINT(RT_DEBUG_TRACE, ("pEntry->RSNIE_Len=%d\n",pEntry->RSNIE_Len)); + if (ielen > sizeof(wpaie.rsn_ie)) + ielen = sizeof(wpaie.rsn_ie)-1; + p = wpaie.rsn_ie; + hex_dump("HOSTAPD_OID_GETWPAIE woody==>pEntry->RSN_IE", (unsigned char*)pEntry->RSN_IE,ielen); + NdisMoveMemory(p, pEntry->RSN_IE, ielen); + } + } + if(copy_to_user(wrq->u.data.pointer, &wpaie, sizeof(wpaie))) + Status = -EFAULT; + break; + + + case HOSTAPD_OID_GET_SEQ:/*report txtsc to hostapd. */ + + pMbss = &pAd->ApCfg.MBSSID[apidx]; + if (wrq->u.data.length != sizeof(ik)) + { + Status = -EINVAL; + } + else if (copy_from_user(&ik, wrq->u.data.pointer, IEEE80211_ADDR_LEN)) + { + Status = -EFAULT; + } + else + { + NdisZeroMemory(&ik.ik_keytsc, sizeof(ik.ik_keytsc)); + p = (unsigned char *)&ik.ik_keytsc; + NdisMoveMemory(p+2, pAd->SharedKey[apidx][ pMbss->DefaultKeyId].TxTsc, 6); + if(copy_to_user(wrq->u.data.pointer, &ik, sizeof(ik))) + Status = -EFAULT; + } + break; + + + case HOSTAPD_OID_GET_1X_GROUP_KEY:/*report default group key to hostapd. */ + + pMbss = &pAd->ApCfg.MBSSID[apidx]; + if (wrq->u.data.length != sizeof(group_key)) + { + Status = -EINVAL; + } + else + { + if(pAd->SharedKey[apidx][ pMbss->DefaultKeyId].KeyLen!=0 && pAd->SharedKey[apidx][ pMbss->DefaultKeyId].Key!=NULL) + { + group_key.ik_keyix = pMbss->DefaultKeyId; + group_key.ik_keylen = pAd->SharedKey[apidx][ pMbss->DefaultKeyId].KeyLen; + NdisMoveMemory(group_key.ik_keydata, pAd->SharedKey[apidx][ pMbss->DefaultKeyId].Key,pAd->SharedKey[apidx][ pMbss->DefaultKeyId].KeyLen); + if(copy_to_user(wrq->u.data.pointer, &group_key, sizeof(group_key))) + Status = -EFAULT; + } + } + break; + +#endif/*HOSTAPD_SUPPORT*/ + +#ifdef APCLI_SUPPORT + case OID_GEN_MEDIA_CONNECT_STATUS: + { + ULONG ApCliIdx = pObj->ioctl_if; + + NDIS_MEDIA_STATE MediaState; + PMAC_TABLE_ENTRY pEntry; + STA_TR_ENTRY *tr_entry; + 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]; + tr_entry = &pAd->MacTab.tr_entry[pApCliEntry->MacTabWCID]; + if (!IS_ENTRY_APCLI(pEntry)) + { + Status = -EOPNOTSUPP; + break; + } + + if ((pAd->ApCfg.ApCliTab[ApCliIdx].Valid == TRUE) + && (tr_entry->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 */ + + + + + case OID_802_11_ACL_LIST: + if (wrq->u.data.length < sizeof(RT_802_11_ACL)) + { + Status = -EINVAL; + } + else + { + Status = copy_to_user(wrq->u.data.pointer, &pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList, sizeof(RT_802_11_ACL)); + } + break; +#ifdef CONFIG_HOTSPOT +#ifdef CONFIG_DOT11V_WNM + case OID_802_11_WNM_IPV4_PROXY_ARP_LIST: + { + BSS_STRUCT *pMbss; + PUCHAR pProxyARPTable; + UINT32 ARPTableLen; + pMbss = &pAd->ApCfg.MBSSID[pObj->ioctl_if]; + ARPTableLen = IPv4ProxyARPTableLen(pAd, pMbss); + os_alloc_mem(NULL, &pProxyARPTable, ARPTableLen); + GetIPv4ProxyARPTable(pAd, pMbss, &pProxyARPTable); + wrq->u.data.length = ARPTableLen; + Status = copy_to_user(wrq->u.data.pointer, pProxyARPTable, ARPTableLen); + os_free_mem(NULL, pProxyARPTable); + } + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_11_WNM_PROXY_ARP_LIST\n")); + break; + case OID_802_11_WNM_IPV6_PROXY_ARP_LIST: + { + BSS_STRUCT *pMbss; + PUCHAR pProxyARPTable; + UINT32 ARPTableLen; + pMbss = &pAd->ApCfg.MBSSID[pObj->ioctl_if]; + ARPTableLen = IPv6ProxyARPTableLen(pAd, pMbss); + os_alloc_mem(NULL, &pProxyARPTable, ARPTableLen); + GetIPv6ProxyARPTable(pAd, pMbss, &pProxyARPTable); + wrq->u.data.length = ARPTableLen; + Status = copy_to_user(wrq->u.data.pointer, pProxyARPTable, ARPTableLen); + os_free_mem(NULL, pProxyARPTable); + } + break; +#endif + case OID_802_11_SECURITY_TYPE: + { + BSS_STRUCT *pMbss; + PUCHAR pType; + struct security_type *SecurityType; + //DBGPRINT(RT_DEBUG_TRACE, ("Query:OID_802_11_SECURITY_TYPE\n")); + printk("Query:OID_802_11_SECURITY_TYPE\n"); + os_alloc_mem(NULL, &pType, sizeof(*SecurityType)); + SecurityType = (struct security_type *)pType; + pMbss = &pAd->ApCfg.MBSSID[pObj->ioctl_if]; + SecurityType->ifindex = pObj->ioctl_if; + SecurityType->auth_mode = pMbss->wdev.AuthMode; //pMbss->AuthMode; + SecurityType->encryp_type = pMbss->wdev.WepStatus; //pMbss->WepStatus; + wrq->u.data.length = sizeof(*SecurityType); + Status = copy_to_user(wrq->u.data.pointer, pType, sizeof(*SecurityType)); + os_free_mem(NULL, pType); + } + break; + case OID_802_11_HS_BSSID: + { + BSS_STRUCT *pMbss; + pMbss = &pAd->ApCfg.MBSSID[pObj->ioctl_if]; + wrq->u.data.length = 6; + Status = copy_to_user(wrq->u.data.pointer, pMbss->wdev.bssid, 6); + } + break; +#ifdef CONFIG_HOTSPOT_R2 + case OID_802_11_HS_OSU_SSID: + { + wrq->u.data.length = pAd->ApCfg.MBSSID[pObj->ioctl_if].SsidLen; //+2; + Status = copy_to_user(wrq->u.data.pointer, pAd->ApCfg.MBSSID[pObj->ioctl_if].Ssid, pAd->ApCfg.MBSSID[pObj->ioctl_if].SsidLen); + } + break; +//JERRY for hs test +#endif /* CONFIG_HOTSPOT_R2 */ +#endif +#ifdef RLT_MAC +#ifdef CONFIG_WIFI_TEST + case OID_WIFI_TEST_BBP: + + break; + case OID_WIFI_TEST_BBP32: + { + UINT32 Index; + UINT32 j = 0; + struct bbp32_info *Info; + char *buf; + + os_alloc_mem(pAd, (UCHAR **)&buf, wrq->u.data.length); + + if (!buf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("Memory is not available\n")); + break; + } + + Status = copy_from_user(buf, wrq->u.data.pointer, wrq->u.data.length); + Info = (struct bbp32_info *)buf; + + printk("Info->bbp_start = %x\n", Info->bbp_start); + printk("Info->bbp_end = %x\n", Info->bbp_end); + + + for (Index = Info->bbp_start; Index <= Info->bbp_end; Index += 4) + { + UINT32 Value; + RTMP_BBP_IO_READ32(pAd, Index + pAd->chipCap.BBPMemMapOffset, &Value); + printk("Offset = %x\n", Index + pAd->chipCap.BBPMemMapOffset); + printk("Value = %x\n", Value); + NdisMoveMemory(Info->bbp_value + j, &Value, 4); + j++; + } + + Status = copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length); + + os_free_mem(NULL, buf); + } + + + break; + case OID_WIFI_TEST_RF: + + break; +#ifdef RLT_RF + case OID_WIFI_TEST_RF_BANK: + { + UINT16 Index; + UINT16 j = 0; + struct rf_bank_info *Info; + char *buf; + + os_alloc_mem(pAd, (UCHAR **)&buf, wrq->u.data.length); + + if (!buf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("memory is not available\n")); + break; + } + + Status = copy_from_user(buf, wrq->u.data.pointer, wrq->u.data.length); + Info = (struct rf_bank_info *)buf; + + printk("Info->rf_bank = %x\n", Info->rf_bank); + printk("Info->rf_start = %x\n", Info->rf_start); + printk("Info->rf_end = %x\n", Info->rf_end); + + + for (Index = Info->rf_start; Index <= Info->rf_end; Index ++) + { + UINT8 Value; + rlt_rf_read(pAd, Info->rf_bank, Index, &Value); + printk("Offset = %x\n", Index); + printk("Value = %x\n", Value); + NdisMoveMemory(Info->rf_value + j, &Value, 1); + j++; + } + + Status = copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length); + + os_free_mem(NULL, buf); + } + break; +#endif /* RLT_RF */ +#ifdef MT_RF + case OID_WIFI_TEST_RF_INDEX: + { + UINT16 Index; + UINT16 j = 0; + struct rf_index_info *Info; + char *buf; + + os_alloc_mem(pAd, (UCHAR **)&buf, wrq->u.data.length); + + if (!buf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("memory is not available\n")); + break; + } + + Status = copy_from_user(buf, wrq->u.data.pointer, wrq->u.data.length); + Info = (struct rf_bank_info *)buf; + + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_index = %x\n", Info->rf_index)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_start = %x\n", Info->rf_start)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_end = %x\n", Info->rf_end)); + + for (Index = Info->rf_start; Index <= Info->rf_end; Index += 4) + { + UINT32 Value; + mt76x2_rf_read(pAd, Info->rf_index, Index, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Offset = %x\n", Index)); + DBGPRINT(RT_DEBUG_OFF, ("Value = %x\n", Value)); + NdisMoveMemory(Info->rf_value + j, &Value, 4); + j++; + } + + Status = copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length); + + os_free_mem(NULL, buf); + } + break; +#endif /* MT_RF */ + case OID_WIFI_TEST_MEM_MAP_INFO: + { + UINT16 Index; + UINT16 j = 0; + struct mem_map_info *Info; + char *buf; + + os_alloc_mem(pAd, (UCHAR **)&buf, wrq->u.data.length); + + if (!buf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("memory is not available\n")); + break; + } + + Status = copy_from_user(buf, wrq->u.data.pointer, wrq->u.data.length); + Info = (struct mem_map_info *)buf; + + printk("Info->base = %x\n", Info->base); + printk("Info->mem_map_start = %x\n", Info->mem_map_start); + printk("Info->mem_map_end = %x\n", Info->mem_map_end); + + + for (Index = Info->mem_map_start; Index <= Info->mem_map_end; Index += 4) + { + UINT32 Value; + read_reg(pAd, Info->base, Index, &Value); + NdisMoveMemory(Info->mem_map_value + j, &Value, 4); + j++; + } + + Status = copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length); + + os_free_mem(NULL, buf); + } + break; + case OID_WIFI_TEST_E2P: + { + UINT16 Index; + UINT16 j = 0; + struct e2p_info *Info; + char *buf; + + os_alloc_mem(pAd, (UCHAR **)&buf, wrq->u.data.length); + + if (!buf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("Memory is not available\n")); + break; + } + + Status = copy_from_user(buf, wrq->u.data.pointer, wrq->u.data.length); + Info = (struct e2p_info *)buf; + + printk("Info->e2p_start = %x\n", Info->e2p_start); + printk("Info->e2p_end = %x\n", Info->e2p_end); + + + for (Index = Info->e2p_start; Index <= Info->e2p_end; Index += 2) + { + UINT16 Value; + RT28xx_EEPROM_READ16(pAd, Index, Value); + NdisMoveMemory(Info->e2p_value + j, &Value, 2); + j++; + } + + Status = copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length); + + os_free_mem(NULL, buf); + } + break; + case OID_WIFI_TEST_MAC: + { + UINT32 Index; + UINT32 j = 0; + struct mac_info *Info; + char *buf; + + os_alloc_mem(pAd, (UCHAR **)&buf, wrq->u.data.length); + + if (!buf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("memory is not available\n")); + break; + } + + Status = copy_from_user(buf, wrq->u.data.pointer, wrq->u.data.length); + Info = (struct mac_info *)buf; + + printk("Info->mac_start = %x\n", Info->mac_start); + printk("Info->mac_end = %x\n", Info->mac_end); + + + for (Index = Info->mac_start; Index <= Info->mac_end; Index += 4) + { + UINT32 Value; + RTMP_IO_READ32(pAd, Index + pAd->chipCap.MacMemMapOffset, &Value); + printk("Offset = %x\n", Index + pAd->chipCap.MacMemMapOffset); + printk("Value = %x\n", Value); + NdisMoveMemory(Info->mac_value + j, &Value, 4); + j++; + } + + Status = copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length); + + os_free_mem(NULL, buf); + } + break; + case OID_WIFI_TEST_BBP_NUM: + { + struct bbp32_info Info; + Info.bbp_start = pAd->chipCap.BBPStart; + Info.bbp_end = pAd->chipCap.BBPEnd; + wrq->u.data.length = sizeof(Info); + Status = copy_to_user(wrq->u.data.pointer, &Info, wrq->u.data.length); + } + break; + case OID_WIFI_TEST_RF_NUM: + + break; + +#ifdef RLT_RF + case OID_WIFI_TEST_RF_BANK_OFFSET: + { + struct rf_bank_info *Info; + struct RF_BANK_OFFSET *Offset; + UINT8 Index; + char *buf; + + os_alloc_mem(pAd, (UCHAR **)&buf, sizeof(*Info) * pAd->chipCap.RFBankNum); + + if (!buf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("Memory is not available\n")); + break; + } + + Info = (struct rf_bank_info *)buf; + Offset = pAd->chipCap.RFBankOffset; + + printk("pAd->chipCap.RFBankNum = %d\n", pAd->chipCap.RFBankNum); + + for (Index = 0; Index < pAd->chipCap.RFBankNum; Index++) + { + Info->rf_bank = Offset->RFBankIndex; + Info->rf_start = Offset->RFStart; + Info->rf_end =Offset->RFEnd; + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_bank = %d\n", Info->rf_bank)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_start = %x\n", Info->rf_start)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_end = %x\n", Info->rf_end)); + Info++; + Offset++; + } + + wrq->u.data.length = sizeof(*Info) * pAd->chipCap.RFBankNum; + Status = copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length); + + os_free_mem(NULL, buf); + } + break; +#endif /* RLT_RF */ + +#ifdef MT_RF + case OID_WIFI_TEST_RF_INDEX_OFFSET: + { + struct rf_index_info *Info; + struct RF_INDEX_OFFSET *Offset; + UINT8 Index; + char *buf; + + os_alloc_mem(pAd, (UCHAR **)&buf, sizeof(*Info) * pAd->chipCap.RFIndexNum); + + if (!buf) + { + Status = -EINVAL; + DBGPRINT(RT_DEBUG_ERROR, ("Memory is not available\n")); + break; + } + + Info = (struct rf_index_info *)buf; + Offset = pAd->chipCap.RFIndexOffset; + + DBGPRINT(RT_DEBUG_OFF, ("pAd->chipCap.RFIndexNum = %d\n", pAd->chipCap.RFIndexNum)); + + for (Index = 0; Index < pAd->chipCap.RFIndexNum; Index++) + { + Info->rf_index = Offset->RFIndex; + Info->rf_start = Offset->RFStart; + Info->rf_end =Offset->RFEnd; + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_index = %d\n", Info->rf_index)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_start = %x\n", Info->rf_start)); + DBGPRINT(RT_DEBUG_OFF, ("Info->rf_end = %x\n", Info->rf_end)); + Info++; + Offset++; + } + + wrq->u.data.length = sizeof(*Info) * pAd->chipCap.RFIndexNum; + Status = copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length); + + os_free_mem(NULL, buf); + } + break; +#endif + case OID_WIFI_TEST_MAC_NUM: + { + struct mac_info Info; + Info.mac_start = pAd->chipCap.MacStart; + Info.mac_end = pAd->chipCap.MacEnd; + wrq->u.data.length = sizeof(Info); + Status = copy_to_user(wrq->u.data.pointer, &Info, wrq->u.data.length); + } + break; + case OID_WIFI_TEST_E2P_NUM: + { + struct e2p_info Info; + Info.e2p_start = pAd->chipCap.E2PStart; + Info.e2p_end = pAd->chipCap.E2PEnd; + wrq->u.data.length = sizeof(Info); + Status = copy_to_user(wrq->u.data.pointer, &Info, wrq->u.data.length); + } + break; + case OID_WIFI_TEST_MEM_MAP_NUM: + { + struct mem_map_info Info; + Info.mem_map_start = pAd->chipCap.MemMapStart; + Info.mem_map_end = pAd->chipCap.MemMapEnd; + wrq->u.data.length = sizeof(Info); + Status = copy_to_user(wrq->u.data.pointer, &Info, wrq->u.data.length); + } + break; + case OID_WIFI_TEST_PHY_MODE: + { + struct phy_mode_info info; + info.data_phy = pAd->fpga_ctl.rx_data_phy; + info.data_bw = pAd->fpga_ctl.rx_data_bw; + info.data_ldpc = pAd->fpga_ctl.rx_data_ldpc; + info.data_mcs = pAd->fpga_ctl.rx_data_mcs; + info.data_gi = pAd->fpga_ctl.rx_data_gi; + info.data_stbc = pAd->fpga_ctl.rx_data_stbc; + wrq->u.data.length = sizeof(info); + Status = copy_to_user(wrq->u.data.pointer, &info, wrq->u.data.length); + } + break; +#endif +#endif +#if (MT7615_MT7603_COMBO_OID_FOR_WEBUI == 1) + case OID_EZ_MAN_STATUS: + { + UCHAR ucresp = 0; + wrq->u.data.length = sizeof(CHAR); + Status = copy_to_user(wrq->u.data.pointer, &ucresp , wrq->u.data.length); + } + break; +#endif +#ifdef WH_EZ_SETUP + case OID_802_11_PASSPHRASE: +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) { + wdev = &pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev; + if (!pAd->ApCfg.ApCliTab[pObj->ioctl_if].Enable) + return FALSE; + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + } + os_alloc_mem(NULL, (unsigned char **)&pass_phrase, sizeof(NDIS_802_11_PASSPHRASE) + LEN_PSK + 1); + if (pass_phrase == NULL) + return FALSE; + + pezMbss = &pAd->ApCfg.MBSSID[apidx]; + + NdisZeroMemory(pass_phrase, sizeof(NDIS_802_11_PASSPHRASE) + LEN_PSK + 1); + pass_phrase->KeyLength = strlen(pezMbss->PSK); + NdisMoveMemory(pass_phrase->KeyMaterial, pezMbss->PSK, pass_phrase->KeyLength); + wrq->u.data.length = sizeof(NDIS_802_11_PASSPHRASE)+ LEN_PSK + 1; + Status = copy_to_user(wrq->u.data.pointer, pass_phrase, wrq->u.data.length); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("Query OID_802_11_PASSPHRASE (Len=%d, passphrase=%s)\n", + pass_phrase->KeyLength, pass_phrase->KeyMaterial)); + os_free_mem(NULL, pass_phrase); + break; +#endif + +#ifdef STA_FORCE_ROAM_SUPPORT + case OID_FROAM_COMMAND: + DBGPRINT(RT_DEBUG_TRACE, + ("Query OID_FROAM_COMMAND \n")); + Status = handle_froam_query_cmd(pAd, wrq); + break; +#endif + +#ifdef MIXMODE_SUPPORT + case OID_MIXMODE_GET_RSSI: + if (MixMode_On(pAd)) { + DBGPRINT(RT_DEBUG_ERROR, + ("\n\n\nQuery::!!!Mix Mode runnning, CANNOT GET RESULT NOW!!!\n\n\n")); + Status = -EBUSY; + break; + } + Status = RTMPIoctlQueryMixModeRssi(pAd, wrq); + break; +#endif /* MIXMODE_SUPPORT */ + + + default: +#ifdef WH_EZ_SETUP +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) { + wdev = &pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev; + if (!pAd->ApCfg.ApCliTab[pObj->ioctl_if].Enable) + return FALSE; + } + else +#endif /* APCLI_SUPPORT */ + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + + if (IS_EZ_SETUP_ENABLED(wdev)) + Status = ez_parse_query_command(pAd, wrq, cmd); +#else + Status = -EOPNOTSUPP; +#endif + 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(RTMP_ADAPTER *pAd, RTMP_STRING *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, + sizeof(pAd->CommonCfg.CountryCode)); + 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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT index = 0; + INT success = TRUE; + RTMP_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\"", (RTMP_STRING *) allCountry[index].pCountryName); + + if (strncmp((RTMP_STRING *) allCountry[index].pCountryName, arg, strlen(arg)) == 0) + break; + else if (strncmp(name_buffer, arg, strlen(arg)) == 0) + break; + } + + if (index == NUM_OF_COUNTRIES) + success = FALSE; + } + else + { + success = FALSE; + } + + if (success == TRUE) + { + if (pAd->CommonCfg.CountryRegion & 0x80) + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryString_Proc::parameter of CountryRegion in eeprom is programmed \n")); + success = FALSE; + } + else + { + success = FALSE; + if (WMODE_CAP_2G(pAd->CommonCfg.PhyMode)) + { + if (allCountry[index].SupportGBand == TRUE) + { + pAd->CommonCfg.CountryRegion = (UCHAR) allCountry[index].RegDomainNum11G; + success = TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("The Country are not Support G Band Channel\n")); + } + } + + if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + { + if (allCountry[index].SupportABand == TRUE) + { + pAd->CommonCfg.CountryRegionForABand = (UCHAR) allCountry[index].RegDomainNum11A; + success = TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("The Country are not Support A Band Channel\n")); + } + } + } + } + + if (success == TRUE) + { + NdisZeroMemory(pAd->CommonCfg.CountryCode, sizeof(pAd->CommonCfg.CountryCode)); + NdisMoveMemory(pAd->CommonCfg.CountryCode, allCountry[index].IsoName, 2); + pAd->CommonCfg.CountryCode[2] = ' '; + /* After Set ChGeography need invoke SSID change procedural again for Beacon update. */ + /* it's no longer necessary since APStartUp will rebuild channel again. */ + /*BuildChannelList(pAd); */ + + pAd->CommonCfg.bCountryFlag = TRUE; + + /* if set country string, driver needs to be reset */ + DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryString_Proc::(CountryString=%s CountryRegin=%d CountryCode=%s)\n", + allCountry[index].pCountryName, pAd->CommonCfg.CountryRegion, pAd->CommonCfg.CountryCode)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_CountryString_Proc::Parameters out of range\n")); + } + + return success; +} + + +/* + ========================================================================== + Description: + Set SSID + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_SSID_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT success = FALSE; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + BSS_STRUCT *mbss; + struct wifi_dev *wdev = NULL; + + if(((pObj->ioctl_if < HW_BEACON_MAX_NUM)) && (strlen(arg) <= MAX_LEN_OF_SSID)) + { + mbss = &pAd->ApCfg.MBSSID[pObj->ioctl_if]; + wdev = &mbss->wdev; + if (wdev == NULL) + return FALSE; + NdisZeroMemory(mbss->Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(mbss->Ssid, arg, strlen(arg)); + mbss->SsidLen = (UCHAR)strlen(arg); + success = TRUE; + + { + ap_send_broadcast_deauth(pAd, wdev); + /* If in detection mode, need to stop detect first. */ + if (pAd->CommonCfg.bIEEE80211H == FALSE) + { + APStop(pAd); + APStartUp(pAd); + } + else + { + /* each mode has different restart method */ + if (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) + { + APStop(pAd); + APStartUp(pAd); + } + else if (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE) + { + } + else if (pAd->Dot11_H.RDMode == RD_NORMAL_MODE) + { + APStop(pAd); + APStartUp(pAd); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Set_SSID_Proc::(Len=%d,Ssid=%s)\n", pObj->ioctl_if, + mbss->SsidLen, mbss->Ssid)); + } + } + else + success = FALSE; + + return success; +} + +/* + ========================================================================== + Description: + Set SSIDSingle + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_SSIDSingle_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) + { + INT success = FALSE; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + BSS_STRUCT *mbss; + struct wifi_dev *wdev; + UCHAR apidx = pObj->ioctl_if; + if(((pObj->ioctl_if < HW_BEACON_MAX_NUM)) && (strlen(arg) <= MAX_LEN_OF_SSID)) + { + mbss = &pAd->ApCfg.MBSSID[pObj->ioctl_if]; + NdisZeroMemory(mbss->Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(mbss->Ssid, arg, strlen(arg)); + mbss->SsidLen = (UCHAR)strlen(arg); + success = TRUE; + wdev = &mbss->wdev; + if (pAd->Dot11_H.RDMode != RD_SWITCHING_MODE) { + MbssKickOutStas(pAd, apidx, REASON_DISASSOC_INACTIVE); + ap_security_init(pAd, wdev, apidx); + ap_mlme_set_capability(pAd, mbss); + ap_key_tb_single_init(pAd, mbss); + APMakeBssBeacon(pAd, apidx); + APUpdateBeaconFrame(pAd, apidx); + } + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Set_SSID_Proc::(Len=%d,Ssid=%s)\n", pObj->ioctl_if, + mbss->SsidLen, mbss->Ssid)); + } + else + success = FALSE; + return success; +} + +#ifdef CONFIG_SNIFFER_SUPPORT +INT Set_AP_Monitor_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 IdMbss =0; + + pAd->ApCfg.bMonitorON = (UCHAR) simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE,("%s: pAd->ApCfg.OriginalType=%u\n", __FUNCTION__ ,pAd->ApCfg.OriginalType)); + + if (pAd->ApCfg.bMonitorON) + { +#define RADIOTAP_TYPE 0 +#define PRISM_TYPE 1 + + pAd->sniffer_ctl.sniffer_type = RADIOTAP_TYPE; + + if (RTMP_OS_NETDEV_GET_TYPE(pAd->ApCfg.MBSSID[IdMbss].wdev.if_dev) != ARPHRD_IEEE80211_RADIOTAP) + { + set_sniffer_mode(pAd->ApCfg.MBSSID[IdMbss].wdev.if_dev, pAd->sniffer_ctl.sniffer_type); + pAd->ApCfg.OriginalType = RTMP_OS_NETDEV_GET_TYPE(pAd->ApCfg.MBSSID[IdMbss].wdev.if_dev); + RTMP_OS_NETDEV_SET_TYPE(pAd->ApCfg.MBSSID[IdMbss].wdev.if_dev, ARPHRD_IEEE80211_RADIOTAP); + } + DBGPRINT(RT_DEBUG_TRACE, ("===>:: (MONITOR ON)\n")); + } + else + { + if (RTMP_OS_NETDEV_GET_TYPE(pAd->ApCfg.MBSSID[IdMbss].wdev.if_dev) == ARPHRD_IEEE80211_RADIOTAP) + { + RTMP_OS_NETDEV_SET_TYPE(pAd->ApCfg.MBSSID[IdMbss].wdev.if_dev, pAd->ApCfg.OriginalType); + } + DBGPRINT(RT_DEBUG_TRACE, ("===>:: (MONITOR OFF)\n")); + } + + /* Set Rx Filter after eaxctly know what mode currently we work on */ + AsicSetRxFilter(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("%s::(bMonitorON=%u)\n",__FUNCTION__ ,pAd->ApCfg.bMonitorON)); + + return TRUE; +} +#endif + + +/* + ========================================================================== + Description: + Set TxRate + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_TxRate_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + NdisZeroMemory(pAd->ApCfg.MBSSID[pObj->ioctl_if].DesiredRates, MAX_LEN_OF_SUPPORTED_RATES); + + pAd->ApCfg.MBSSID[pObj->ioctl_if].DesiredRatesIndex = simple_strtol(arg, 0, 10); + /* todo RTMPBuildDesireRate(pAd, pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].DesiredRatesIndex); */ + + /*todo MlmeUpdateTxRates(pAd); */ + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set BasicRate + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_BasicRate_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *arg) +{ + USHORT DtimPeriod; + INT success = FALSE; + + DtimPeriod = (USHORT) simple_strtol(arg, 0, 10); + if((DtimPeriod >= 1) && (DtimPeriod <= 255)) + { + pAd->ApCfg.DtimPeriod = DtimPeriod; + success = TRUE; + } + else + success = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_DtimPeriod_Proc::(DtimPeriod=%d)\n", pAd->ApCfg.DtimPeriod)); + + return success; +} + + + +/* + ========================================================================== + Description: + Disable/enable OLBC detection manually + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_OLBCDetection_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *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; +} + + +/* + ========================================================================== + 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 RTMP_STRING *arg) +{ + BOOLEAN bWmmCapable; + POS_COOKIE pObj= (POS_COOKIE)pAd->OS_Cookie; + + bWmmCapable = simple_strtol(arg, 0, 10); + + if (bWmmCapable == 1) + pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.bWmmCapable = TRUE; + else if (bWmmCapable == 0) + pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.bWmmCapable = FALSE; + else + return FALSE; /*Invalid argument */ + + pAd->ApCfg.MBSSID[pObj->ioctl_if].bWmmCapableOrg = \ + pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.bWmmCapable; + +#ifdef 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].wdev.bWmmCapable)); + + return TRUE; +} + + +INT Set_AP_MaxStaNum_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + struct wifi_dev *wdev; + + + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + wdev->VLAN_VID = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_VLANID_Proc::(VLAN_VID=%d)\n", + pObj->ioctl_if, wdev->VLAN_VID)); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set VLAN's priority field + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_VLANPriority_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + + wdev->VLAN_Priority = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_VLANPriority_Proc::(VLAN_Priority=%d)\n", pObj->ioctl_if, wdev->VLAN_Priority)); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set enable or disable carry VLAN in the air + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_VLAN_TAG_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + BOOLEAN bVLAN_Tag; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + struct wifi_dev *wdev; + + + bVLAN_Tag = simple_strtol(arg, 0, 10); + + if (bVLAN_Tag == 1) + bVLAN_Tag = TRUE; + else if (bVLAN_Tag == 0) + bVLAN_Tag = FALSE; + else + return FALSE; //Invalid argument + + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + wdev->bVLAN_Tag = bVLAN_Tag; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_VLAN_TAG_Proc::(VLAN_Tag=%d)\n", + pObj->ioctl_if, wdev->bVLAN_Tag)); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set Authentication mode + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + ULONG i; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + struct wifi_dev *wdev; + + + if (apidx >= pAd->ApCfg.BssidNum) + return FALSE; + +#ifdef WH_EZ_SETUP + if(IS_EZ_SETUP_ENABLED(&pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev)) + { + if (rtstrcasecmp(arg, "WPA2PSK") == TRUE) + { + //SetWdevAuthMode(pSecConfig, arg); + //return TRUE; + } else { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("Easy Setup is enabled on this interface AP, AuthMode Cannot be updated\n")); + return FALSE; + } + } +#endif + /* Set Authentication mode */ + ApCfg_Set_AuthMode_Proc(pAd, apidx, arg); + + /* reset the portSecure for all entries */ + for (i=0; iMacTab.Content[i])) + { + pAd->MacTab.tr_entry[i].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + } + } + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + /* reset the PortSecure this BSS */ + wdev->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + /* Default key index is always 2 in WPA mode */ + if(wdev->AuthMode >= Ndis802_11AuthModeWPA) + wdev->DefaultKeyId = 1; + + return TRUE; +} + +INT Set_AP_AuthMode_Single_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + ULONG i; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + struct wifi_dev *wdev; + + + if (apidx >= pAd->ApCfg.BssidNum) + return FALSE; + +#ifdef WH_EZ_SETUP + if(IS_EZ_SETUP_ENABLED(&pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev)) + { + if (rtstrcasecmp(arg, "WPA2PSK") == TRUE) + { + //SetWdevAuthMode(pSecConfig, arg); + //return TRUE; + } else { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("Easy Setup is enabled on this interface AP, AuthMode Cannot be updated\n")); + return FALSE; + } + } +#endif + /* Set Authentication mode */ + ApCfg_Set_AuthMode_Proc(pAd, apidx, arg); + + /* reset the portSecure for all entries */ + for (i=0; iMacTab.Content[i])) + { + if (pAd->MacTab.tr_entry[i].wdev == &pAd->ApCfg.MBSSID[apidx].wdev) + pAd->MacTab.tr_entry[i].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + } + } + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + /* reset the PortSecure this BSS */ + wdev->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + /* Default key index is always 2 in WPA mode */ + if(wdev->AuthMode >= Ndis802_11AuthModeWPA) + wdev->DefaultKeyId = 1; + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set Encryption Type + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_EncrypType_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + struct wifi_dev *wdev; +#ifdef AIRPLAY_SUPPORT + BSS_STRUCT *pMbss ; +#endif /* AIRPLAY_SUPPORT*/ + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + +#ifdef WH_EZ_SETUP + if(IS_EZ_SETUP_ENABLED(wdev)) + { + if (rtstrcasecmp(arg, "AES") == TRUE){ + //SetWdevEncrypMode(pSecConfig, arg); + } else { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("Easy Setup is enabled on this interface AP, EncrypType Cannot be updated\n")); + return FALSE; + } + } +#endif + + if ((strcmp(arg, "NONE") == 0) || (strcmp(arg, "none") == 0)) + wdev->WepStatus = Ndis802_11WEPDisabled; + else if ((strcmp(arg, "WEP") == 0) || (strcmp(arg, "wep") == 0)) + wdev->WepStatus = Ndis802_11WEPEnabled; + else if ((strcmp(arg, "TKIP") == 0) || (strcmp(arg, "tkip") == 0)) + wdev->WepStatus = Ndis802_11TKIPEnable; + else if ((strcmp(arg, "AES") == 0) || (strcmp(arg, "aes") == 0)) + wdev->WepStatus = Ndis802_11AESEnable; + else if ((strcmp(arg, "TKIPAES") == 0) || (strcmp(arg, "tkipaes") == 0)) + wdev->WepStatus = Ndis802_11TKIPAESMix; +#ifdef WAPI_SUPPORT + else if ((strcmp(arg, "SMS4") == 0) || (strcmp(arg, "sms4") == 0)) + wdev->WepStatus = Ndis802_11EncryptionSMS4Enabled; +#endif /* WAPI_SUPPORT */ +#ifdef CONFIG_OWE_SUPPORT + else if (rtstrcasecmp(arg, "CCMP128") == TRUE) + wdev->WepStatus = Ndis802_11CCMP128Enable; + else if (rtstrcasecmp(arg, "CCMP256") == TRUE) + wdev->WepStatus = Ndis802_11CCMP256Enable; +#endif + else + return FALSE; + + if (wdev->WepStatus >= Ndis802_11TKIPEnable) + wdev->DefaultKeyId = 1; + + /* decide the group key encryption type */ + if (wdev->WepStatus == Ndis802_11TKIPAESMix) + wdev->GroupKeyWepStatus = Ndis802_11TKIPEnable; + else + wdev->GroupKeyWepStatus = wdev->WepStatus; + + /* move to ap.c::APStartUp to process */ + /*RTMPMakeRSNIE(pAd, pAd->ApCfg.MBSSID[apidx].AuthMode, pAd->ApCfg.MBSSID[apidx].WepStatus, apidx); */ + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_EncrypType_Proc::(EncrypType=%d)\n", apidx, wdev->WepStatus)); + +#ifdef AIRPLAY_SUPPORT + pMbss = &pAd->ApCfg.MBSSID[apidx]; + /*If EncryptionDisabled, set privacy bit in CapabilityInfo to zero*/ + if(pMbss->wdev.WepStatus == Ndis802_11EncryptionDisabled) + { + pMbss->CapabilityInfo &= 0xFFEF; + DBGPRINT(RT_DEBUG_ERROR,("##Diaplbe privacy ####")); + } + else + { + /* Enable encryption*/ + pMbss->CapabilityInfo |= 0x0010; + } +#endif /* AIRPLAY_SUPPORT*/ + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set WPA pairwise mix-cipher combination + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_WpaMixPairCipher_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + struct wifi_dev *wdev; + + /* + In WPA-WPA2 mix mode, it provides a more flexible cipher combination. + - WPA-AES and WPA2-TKIP + - WPA-AES and WPA2-TKIPAES + - WPA-TKIP and WPA2-AES + - WPA-TKIP and WPA2-TKIPAES + - WPA-TKIPAES and WPA2-AES + - WPA-TKIPAES and WPA2-TKIP + - WPA-TKIPAES and WPA2-TKIPAES (default) + */ + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + if ((strncmp(arg, "WPA_AES_WPA2_TKIPAES", 20) == 0) || (strncmp(arg, "wpa_aes_wpa2_tkipaes", 20) == 0)) + wdev->WpaMixPairCipher = WPA_AES_WPA2_TKIPAES; + else if ((strncmp(arg, "WPA_AES_WPA2_TKIP", 17) == 0) || (strncmp(arg, "wpa_aes_wpa2_tkip", 17) == 0)) + wdev->WpaMixPairCipher = WPA_AES_WPA2_TKIP; + else if ((strncmp(arg, "WPA_TKIP_WPA2_AES", 17) == 0) || (strncmp(arg, "wpa_tkip_wpa2_aes", 17) == 0)) + wdev->WpaMixPairCipher = WPA_TKIP_WPA2_AES; + else if ((strncmp(arg, "WPA_TKIP_WPA2_TKIPAES", 21) == 0) || (strncmp(arg, "wpa_tkip_wpa2_tkipaes", 21) == 0)) + wdev->WpaMixPairCipher = WPA_TKIP_WPA2_TKIPAES; + else if ((strncmp(arg, "WPA_TKIPAES_WPA2_AES", 20) == 0) || (strncmp(arg, "wpa_tkipaes_wpa2_aes", 20) == 0)) + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_AES; + else if ((strncmp(arg, "WPA_TKIPAES_WPA2_TKIPAES", 24) == 0) || (strncmp(arg, "wpa_tkipaes_wpa2_tkipaes", 24) == 0)) + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIPAES; + else if ((strncmp(arg, "WPA_TKIPAES_WPA2_TKIP", 21) == 0) || (strncmp(arg, "wpa_tkipaes_wpa2_tkip", 21) == 0)) + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIP; + else + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Set_AP_WpaMixPairCipher_Proc=0x%02x\n", apidx, wdev->WpaMixPairCipher)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set WPA rekey interval value + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_RekeyInterval_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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 AssocReq RSSI Threshold to reject STA with weak signal. + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_ASSOC_REQ_RSSI_THRESHOLD( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + UINT j; + CHAR rssi; + rssi = simple_strtol(arg, 0, 10); + + if (rssi == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("Disable AP_ASSOC_REQ_RSSI_THRESHOLD\n")); + } + else if (rssi > 0 || rssi < -100) + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_AP_ASSOC_REQ_RSSI_THRESHOLD Value Error.\n")); + return FALSE; + } + + + pAd->ApCfg.MBSSID[apidx].AssocReqRssiThreshold = rssi; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Set_AP_ASSOC_REQ_RSSI_THRESHOLD=%d\n", apidx, + pAd->ApCfg.MBSSID[apidx].AssocReqRssiThreshold )); + + for(j = BSS0; j < pAd->ApCfg.BssidNum; j++) + { + DBGPRINT(RT_DEBUG_TRACE, ("%d. ==> %d\n", j, pAd->ApCfg.MBSSID[j].AssocReqRssiThreshold )); + } + + + return TRUE; +} + +/* + ========================================================================== + Description: + Set lower limit for AP kicking out a STA. + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_KickStaRssiLow_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + UINT j; + CHAR rssi; + rssi = simple_strtol(arg, 0, 10); + + if (rssi == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("Disable RssiLowForStaKickOut Function\n")); + } + else if (rssi > 0 || rssi < -100) + { + DBGPRINT(RT_DEBUG_TRACE, ("RssiLowForStaKickOut Value Error.\n")); + return FALSE; + } + + + pAd->ApCfg.MBSSID[apidx].RssiLowForStaKickOut = rssi; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) RssiLowForStaKickOut=%d\n", apidx, + pAd->ApCfg.MBSSID[apidx].RssiLowForStaKickOut )); + + for(j = BSS0; j < pAd->ApCfg.BssidNum; j++) + { + DBGPRINT(RT_DEBUG_TRACE, ("%d. ==> %d\n", j, pAd->ApCfg.MBSSID[j].RssiLowForStaKickOut )); + } + + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set Default Key ID + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + ULONG KeyIdx; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + + + KeyIdx = simple_strtol(arg, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId = (UCHAR) (KeyIdx - 1 ); + else + return FALSE; /* Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_DefaultKeyID_Proc::(DefaultKeyID(0~3)=%d)\n", apidx, pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId)); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Set WEP KEY1 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_Key1_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj; + UCHAR apidx; + CIPHER_KEY *pSharedKey; + INT retVal; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + pSharedKey = &pAd->SharedKey[apidx][0]; + retVal = RT_CfgSetWepKey(pAd, arg, pSharedKey, 0); + if (retVal == TRUE) + { + /* Set keys (into ASIC) */ + if (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + AsicAddSharedKeyEntry(pAd, apidx, 0, pSharedKey); + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_Key1_Proc::(Key1=%s) success!\n", apidx, arg)); + } + + return retVal; +} + + +/* + ========================================================================== + Description: + Set WEP KEY2 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_Key2_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj; + UCHAR apidx; + CIPHER_KEY *pSharedKey; + INT retVal; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + pSharedKey = &pAd->SharedKey[apidx][1]; + retVal = RT_CfgSetWepKey(pAd, arg, pSharedKey, 1); + if (retVal == TRUE) + { + /* Set keys (into ASIC) */ + if (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + AsicAddSharedKeyEntry(pAd, apidx, 1, pSharedKey); + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_Key2_Proc::(Key2=%s) success!\n", apidx, arg)); + } + + return retVal; +} + + +/* + ========================================================================== + Description: + Set WEP KEY3 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_Key3_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj; + UCHAR apidx; + CIPHER_KEY *pSharedKey; + INT retVal; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + pSharedKey = &pAd->SharedKey[apidx][2]; + retVal = RT_CfgSetWepKey(pAd, arg, pSharedKey, 2); + if (retVal == TRUE) + { + /* Set keys (into ASIC) */ + if (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + AsicAddSharedKeyEntry(pAd, apidx, 2, pSharedKey); + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_Key3_Proc::(Key3=%s) success!\n", apidx, arg)); + } + + return retVal; +} + + +/* + ========================================================================== + Description: + Set WEP KEY4 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_Key4_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + + POS_COOKIE pObj; + UCHAR apidx; + CIPHER_KEY *pSharedKey; + INT retVal; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + pSharedKey = &pAd->SharedKey[apidx][3]; + retVal = RT_CfgSetWepKey(pAd, arg, pSharedKey, 3); + if (retVal == TRUE) + { + /* Set keys (into ASIC) */ + if (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode >= Ndis802_11AuthModeWPA) + ; /* not support */ + else /* Old WEP stuff */ + { + AsicAddSharedKeyEntry(pAd, apidx, 3, pSharedKey); + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_Key4_Proc::(Key4=%s) success!\n", apidx, arg)); + } + + return retVal; +} + + +/* + ========================================================================== + Description: + Set Access ctrol policy + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AccessPolicy_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; +#ifdef ACL_BLK_COUNT_SUPPORT + int count = 0; + + if (simple_strtol(arg, 0, 10) != 2) { + for (count = 0; count < pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Num; count++) + pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Entry[count].Reject_Count = 0; + } +#endif + 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 RTMP_STRING *arg) +{ + UCHAR macAddr[MAC_ADDR_LEN]; +/* RT_802_11_ACL acl; */ + RT_802_11_ACL *pacl = NULL; + RTMP_STRING *this_char; + RTMP_STRING *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; i < pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Num; i++) + { + DBGPRINT(RT_DEBUG_TRACE, ("Entry #%02d: ", i+1)); + for (j = 0; j < MAC_ADDR_LEN; j++) + DBGPRINT(RT_DEBUG_TRACE, ("%02X ", pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Entry[i].Addr[j])); + DBGPRINT(RT_DEBUG_TRACE, ("\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 RTMP_STRING *arg) +{ + UCHAR macAddr[MAC_ADDR_LEN]; + UCHAR nullAddr[MAC_ADDR_LEN]; + RT_802_11_ACL acl; + RTMP_STRING *this_char; + RTMP_STRING *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], sizeof(RT_802_11_ACL_ENTRY)); +#else + NdisMoveMemory(&(pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Entry[i++]), + acl.Entry[j].Addr, MAC_ADDR_LEN); +#endif/*ACL_BLK_COUNT_SUPPORT*/ + } + } + + 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; i < pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Num; i++) + { + DBGPRINT(RT_DEBUG_TRACE, ("Entry #%02d: ", i+1)); + for (j = 0; j < MAC_ADDR_LEN; j++) + DBGPRINT(RT_DEBUG_TRACE, ("%02X ", pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Entry[i].Addr[j])); + DBGPRINT(RT_DEBUG_TRACE, ("\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 RTMP_STRING *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; i < acl.Num; i++) + { + DBGPRINT(RT_DEBUG_TRACE, ("Entry #%02d: ", i+1)); + for (j = 0; j < MAC_ADDR_LEN; j++) + DBGPRINT(RT_DEBUG_TRACE, ("%02X ", acl.Entry[i].Addr[j])); + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + } + + return TRUE; +} + +#ifdef MAC_REPEATER_SUPPORT +/* + ========================================================================== + 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_MACReptAddEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + UCHAR macAddr[MAC_ADDR_LEN]; + RTMP_STRING *this_char; + RTMP_STRING *value; + INT i, j; + BOOLEAN isDuplicate=FALSE; + + + pAd->ApCfg.ReptMacList.Num = 0; + for (i=0; iApCfg.ReptMacList.Entry[i].bSet = 0; + pAd->ApCfg.ReptMacList.Entry[i].bUsed = 0; + //NdisZeroMemory(pAd->ApCfg.ReptMacList.Entry[i].Addr, 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 is duplicate. */ + isDuplicate = FALSE; + for (j=0; jApCfg.ReptMacList.Num; j++) + { + if (memcmp(pAd->ApCfg.ReptMacList.Entry[j].Addr, &macAddr, MAC_ADDR_LEN) == 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(pAd->ApCfg.ReptMacList.Entry[pAd->ApCfg.ReptMacList.Num++].Addr, &macAddr, MAC_ADDR_LEN); + pAd->ApCfg.ReptMacList.Entry[pAd->ApCfg.ReptMacList.Num].bSet = 1; + } + + if (pAd->ApCfg.ReptMacList.Num == MAX_NUMBER_OF_MAC_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(pAd->ApCfg.ReptMacList.Num < MAX_NUMBER_OF_MAC_LIST); + + DBGPRINT(RT_DEBUG_TRACE, ("Set::%s(Entry#=%ld)\n", + __FUNCTION__ , pAd->ApCfg.ReptMacList.Num)); + + return TRUE; +} + +/* + ========================================================================== + 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_MACReptMACShowAll_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + BOOLEAN bDumpAll=FALSE; + 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 */ + } + + /* Check if the list is already empty. */ + if (pAd->ApCfg.ReptMacList.Num == 0) + { + DBGPRINT(RT_DEBUG_WARN, ("The MAC Entry List is empty!\n")); + return TRUE; + } + + ASSERT(((bDumpAll == 1) && (pAd->ApCfg.ReptMacList.Num > 0))); + + /* Dump the entry in the list one by one */ + printk("=============== MAC Entry List ===============\n"); + for (i = 0; i < pAd->ApCfg.ReptMacList.Num; i++) + { + DBGPRINT(RT_DEBUG_TRACE, ("Entry #%02d: ", i+1)); + for (j = 0; j < MAC_ADDR_LEN; j++) + DBGPRINT(RT_DEBUG_TRACE, ("%02X ", pAd->ApCfg.ReptMacList.Entry[i].Addr[j])); + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + } + + return TRUE; +} +#endif /* MAC_REPEATER_SUPPORT */ + + +/* + ========================================================================== + Description: + Clear 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_ACLClearAll_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ +/* RT_802_11_ACL acl; */ + RT_802_11_ACL *pacl = NULL; + BOOLEAN bClearAll=FALSE; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + bClearAll = simple_strtol(arg, 0, 10); + + if (bClearAll == 1) + { + bClearAll = TRUE; + } + else if (bClearAll == 0) + { + bClearAll = FALSE; + DBGPRINT(RT_DEBUG_WARN, ("Your input is 0!\n")); + DBGPRINT(RT_DEBUG_WARN, ("The Access Control List will be kept unchanged!\n")); + return TRUE; + } + else + { + return FALSE; /* Invalid argument */ + } + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&pacl, sizeof(RT_802_11_ACL)); + if (pacl == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return FALSE; + } + + NdisZeroMemory(pacl, sizeof(RT_802_11_ACL)); + NdisMoveMemory(pacl, &pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList, sizeof(RT_802_11_ACL)); + + /* Check if the list is already empty. */ + if (pacl->Num == 0) + { + DBGPRINT(RT_DEBUG_WARN, ("The Access Control List is empty!\n")); + DBGPRINT(RT_DEBUG_WARN, ("No need to clear the Access Control List!\n")); + + if (pacl != NULL) + os_free_mem(NULL, pacl); + + return TRUE; + } + + ASSERT(((bClearAll == 1) && (pacl->Num > 0))); + + /* Clear the entry in the list one by one */ + /* Keep the corresponding policy unchanged. */ + do + { + NdisZeroMemory(pacl->Entry[pacl->Num - 1].Addr, MAC_ADDR_LEN); +#ifdef ACL_BLK_COUNT_SUPPORT + pacl->Entry[pacl->Num - 1].Reject_Count = 0; +#endif + 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 STA_FORCE_ROAM_SUPPORT +int froam_add_acl_entry(void *ad_obj, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + RTMP_ADAPTER *pAd; + POS_COOKIE pObj; + INT j; + BOOLEAN isDuplicate = FALSE; + u8 macAddr[MAC_ADDR_LEN] = {0, 0, 0, 0, 0, 0}; + RT_802_11_ACL *pacl = NULL; + int Status = NDIS_STATUS_SUCCESS; + + pAd = (RTMP_ADAPTER *)ad_obj; + pObj = (POS_COOKIE) pAd->OS_Cookie; + + DBGPRINT(RT_DEBUG_TRACE, + ("add_acl_entry: -->\n")); + if (wrq->u.data.length != MAC_ADDR_LEN) { + DBGPRINT(RT_DEBUG_ERROR, + ("add_acl_entry: invalid payload size:%d\n", wrq->u.data.length)); + return -EINVAL; + } + + copy_from_user(macAddr, wrq->u.data.pointer, wrq->u.data.length); + + if (!memcmp(macAddr, ZERO_MAC_ADDR, MAC_ADDR_LEN)) { + DBGPRINT(RT_DEBUG_ERROR, + ("add_acl_entry: invalid mac addr\n")); + return -EINVAL; + } + + if (pAd->ApCfg.MBSSID[pObj->ioctl_if].FroamAccessControlList.Num >= (MAX_NUM_OF_ACL_LIST - 1)) { + DBGPRINT(RT_DEBUG_ERROR, + ("The Froam AccessControlList is full, and no more entry can join the list!\n")); + return -ENOMEM; + } + + /* 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", __func__)); + return -ENOMEM; + } + + NdisZeroMemory(pacl, sizeof(RT_802_11_ACL)); + NdisMoveMemory(pacl, &pAd->ApCfg.MBSSID[pObj->ioctl_if].FroamAccessControlList, + sizeof(RT_802_11_ACL)); + /* Check if this entry is duplicate. */ + isDuplicate = FALSE; + for (j = 0; j < pacl->Num; j++) { + if (memcmp(pacl->Entry[j].Addr, &macAddr, 6) == 0) { + isDuplicate = TRUE; + DBGPRINT(RT_DEBUG_WARN, ("Duplicate entry for %02x:%02x:%02x:%02x:%02x:%02x\n", + macAddr[0], macAddr[1], macAddr[2], macAddr[3], + macAddr[4], macAddr[5])); + } + } + + if (!isDuplicate) { + DBGPRINT(RT_DEBUG_WARN, + ("ACL entry added at %d for %02x:%02x:%02x:%02x:%02x:%02x\n", + (int)pacl->Num, macAddr[0], macAddr[1], macAddr[2], + macAddr[3], macAddr[4], macAddr[5])); + NdisMoveMemory(pacl->Entry[pacl->Num++].Addr, &macAddr, MAC_ADDR_LEN); + if (pacl->Num == MAX_NUM_OF_ACL_LIST) { + DBGPRINT(RT_DEBUG_WARN, + ("The Froam ACL is NOW full and no more entry can join the list!\n")); + } + /*ASSERT(pacl->Num <= MAX_NUM_OF_ACL_LIST);*/ + NdisZeroMemory(&pAd->ApCfg.MBSSID[pObj->ioctl_if].FroamAccessControlList, sizeof(RT_802_11_ACL)); + NdisMoveMemory(&pAd->ApCfg.MBSSID[pObj->ioctl_if].FroamAccessControlList, pacl, sizeof(RT_802_11_ACL)); + /* check if the change in ACL affects any existent association */ + ApUpdateAccessControlList(pAd, pObj->ioctl_if); + DBGPRINT(RT_DEBUG_ERROR, ("Set::%s( Entry#=%ld)\n", __func__, + pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Num)); + } + if (pacl != NULL) + os_free_mem(NULL, pacl); + + DBGPRINT(RT_DEBUG_TRACE, ("add_acl_entry: -->\n")); + return Status; +} + +int froam_del_acl_entry(void *ad_obj, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + RTMP_ADAPTER *pAd; + POS_COOKIE pObj; + INT i, j; + BOOLEAN isFound = FALSE; + u8 macAddr[MAC_ADDR_LEN] = {0, 0, 0, 0, 0, 0}; + u8 nullAddr[MAC_ADDR_LEN] = {0, 0, 0, 0, 0, 0}; + RT_802_11_ACL *pacl = NULL; + int Status = NDIS_STATUS_SUCCESS; + + pAd = (RTMP_ADAPTER *)ad_obj; + pObj = (POS_COOKIE) pAd->OS_Cookie; + DBGPRINT(RT_DEBUG_TRACE, ("del_acl_entry: -->\n")); + if (wrq->u.data.length != MAC_ADDR_LEN) { + DBGPRINT(RT_DEBUG_TRACE, + ("del_acl_entry: invalid payload size:%d\n", wrq->u.data.length)); + return -EINVAL; + } + + copy_from_user(macAddr, wrq->u.data.pointer, wrq->u.data.length); + + if (!memcmp(macAddr, nullAddr, MAC_ADDR_LEN)) { + DBGPRINT(RT_DEBUG_ERROR, + ("del_acl_entry: invalid mac addr\n")); + return -EINVAL; + } + + /* 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", __func__)); + return -ENOMEM; + } + + NdisZeroMemory(pacl, sizeof(RT_802_11_ACL)); + NdisMoveMemory(pacl, &pAd->ApCfg.MBSSID[pObj->ioctl_if].FroamAccessControlList, + sizeof(RT_802_11_ACL)); + + /* Check if this entry existed. */ + isFound = FALSE; + for (j = 0; j < pacl->Num; j++) { + if (memcmp(pacl->Entry[j].Addr, &macAddr, MAC_ADDR_LEN) == 0) { + isFound = TRUE; + NdisZeroMemory(pacl->Entry[j].Addr, MAC_ADDR_LEN); + DBGPRINT(RT_DEBUG_ERROR, + ("The entry(%d) %02x:%02x:%02x:%02x:%02x:%02x found will be deleted!\n", + j, macAddr[0], macAddr[1], macAddr[2], macAddr[3], + macAddr[4], macAddr[5])); + } + } + + if (isFound) { + NdisZeroMemory(&pAd->ApCfg.MBSSID[pObj->ioctl_if].FroamAccessControlList, sizeof(RT_802_11_ACL)); + i = 0; + for (j = 0; j < pacl->Num; j++) { + if (memcmp(pacl->Entry[j].Addr, &nullAddr, MAC_ADDR_LEN) == 0) { + continue; + } else { + NdisMoveMemory(&(pAd->ApCfg.MBSSID[pObj->ioctl_if].FroamAccessControlList.Entry[i++]), + pacl->Entry[j].Addr, MAC_ADDR_LEN); + } + } + + pAd->ApCfg.MBSSID[pObj->ioctl_if].FroamAccessControlList.Num = i; + ASSERT(pacl->Num >= pAd->ApCfg.MBSSID[pObj->ioctl_if].FroamAccessControlList.Num); + + /* check if the change in ACL affects any existent association */ + ApUpdateAccessControlList(pAd, pObj->ioctl_if); + DBGPRINT(RT_DEBUG_ERROR, ("Set::%s(Entry#=%ld)\n", __func__, + pAd->ApCfg.MBSSID[pObj->ioctl_if].AccessControlList.Num)); + } else + DBGPRINT(RT_DEBUG_ERROR, ("The entry %02x:%02x:%02x:%02x:%02x:%02x is not in the list!\n", + macAddr[0], macAddr[1], macAddr[2], macAddr[3], + macAddr[4], macAddr[5])); + if (pacl != NULL) + os_free_mem(NULL, pacl); + DBGPRINT(RT_DEBUG_TRACE, ("del_acl_entry: <--\n")); + return Status; +} +#endif +#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 RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + INT retval; + BSS_STRUCT *pMBSSStruct; +#if defined(DOT11_SAE_SUPPORT) || defined(WH_EZ_SETUP) + INT boundary = 65; +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WPAPSK_Proc::(WPAPSK=%s)\n", arg)); + + pMBSSStruct = &pAd->ApCfg.MBSSID[apidx]; +#if defined(WH_EZ_SETUP) || defined(DOT11_SAE_SUPPORT) + +#if defined(DOT11_SAE_SUPPORT) + + if (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode == Ndis802_11AuthModeWPA3PSK + || pAd->ApCfg.MBSSID[apidx].wdev.AuthMode == Ndis802_11AuthModeWPA2PSKWPA3PSK) + boundary = LEN_MAX_WPA3PSK_PSD + 1; + else + boundary = LEN_MAX_WPA2PSK_PSD + 1; +#endif + if (strlen(arg) < boundary) { + NdisMoveMemory(pMBSSStruct->PSK, arg, strlen(arg)); + pMBSSStruct->PSK[strlen(arg)] = '\0'; + } else { + pMBSSStruct->PSK[0] = '\0'; +#ifdef DOT11_SAE_SUPPORT + return FALSE; +#endif + } +#endif + retval = RT_CfgSetWPAPSKKey(pAd, arg, strlen(arg), (PUCHAR)pMBSSStruct->Ssid, pMBSSStruct->SsidLen, pMBSSStruct->PMK); + if (retval == FALSE) + return FALSE; + + strcpy(pAd->ApCfg.MBSSID[apidx].WPAKeyString, arg); +#ifdef WSC_AP_SUPPORT + NdisZeroMemory(pMBSSStruct->WscControl.WpaPsk, 64); + pMBSSStruct->WscControl.WpaPskLen = 0; + pMBSSStruct->WscControl.WpaPskLen = strlen(arg); + NdisMoveMemory(pMBSSStruct->WscControl.WpaPsk, arg, pMBSSStruct->WscControl.WpaPskLen); +#endif /* WSC_AP_SUPPORT */ + + return TRUE; +} + + +#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 RTMP_STRING *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 if (strcmp(arg,"3") == 0) + pAd->ApCfg.AutoChannelAlg =ChannelAlgBusyTime; +#ifdef ACS_CTCC_SUPPORT + else if (strcmp(arg, "5") == 0) { + pAd->ApCfg.AutoChannelAlg = ChannelAlgApCnt; + pAd->ApCfg.AutoChannelScoreFlag = TRUE; + } else if (strcmp(arg, "6") == 0) { + pAd->ApCfg.AutoChannelAlg = ChannelAlgCCA; + pAd->ApCfg.AutoChannelScoreFlag = TRUE; + } else if (strcmp(arg, "7") == 0) { + pAd->ApCfg.AutoChannelAlg = ChannelAlgBusyTime; + pAd->ApCfg.AutoChannelScoreFlag = TRUE; + } +#endif + 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, NULL); + else + ApSiteSurvey(pAd, &Ssid, SCAN_ACTIVE, TRUE, NULL); + + return TRUE; + +} + +#ifdef AP_PARTIAL_SCAN_SUPPORT +INT Set_PartialScan_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + UINT8 bPartialScanning = simple_strtol(arg, 0, 10); + pAd->ApCfg.bPartialScanning = bPartialScanning ? TRUE:FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("%s(): bPartialScanning = %u \n", __FUNCTION__, pAd->ApCfg.bPartialScanning)); + return TRUE; +} +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + +#ifdef NEIGHBORING_AP_STAT +/*Dump Custom scan result*/ +INT Set_CustomScanResult_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + int j, bssIdx = 0; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + /*UINT8 bPartialScanning;*/ + CUSTOM_SCAN_RESULT *rpt = NULL; + BSS_ENTRY *pBss = NULL; + SCAN_RPT_ITEM *item = NULL; + UCHAR idx = 0, b_idx = 0, s_idx = 0; + + if ((pObj->ioctl_if_type != INT_APCLI) && + (pObj->ioctl_if_type != INT_MAIN) && + (pObj->ioctl_if_type != INT_MBSSID)) + return FALSE; + + /* reset scan entries */ + if (pAd->ScanTab.ScanResult.cnt > 0) { + pAd->ScanTab.ScanResult.cnt = 0; + RTMPZeroMemory(pAd->ScanTab.ScanResult.items, MAX_COUNT_OF_BSS_ENTRIES * sizeof(SCAN_RPT_ITEM)); + } + + printk("Report Total Neighbouring AP Count: %d\n", pAd->ScanTab.BssNr); + + rpt = &pAd->ScanTab.ScanResult; + for (bssIdx = 0; bssIdx < pAd->ScanTab.BssNr; bssIdx++) { + pBss = &pAd->ScanTab.BssEntry[bssIdx]; + if (bssIdx < MAX_COUNT_OF_BSS_ENTRIES) { + item = &pAd->ScanTab.ScanResult.items[bssIdx]; + NdisMoveMemory(item->ssid, pBss->Ssid, pBss->SsidLen); + NdisMoveMemory(item->macAddr, pBss->Bssid, MAC_ADDR_LEN); + item->noise = pBss->Rssi - pBss->Snr0; + item->beaconPeriod = pBss->BeaconPeriod; + item->dtimPeriod = pBss->DtimPeriod; + item->channel = pBss->Channel; + + b_idx = 0, s_idx = 0; + for (idx = 0; idx < pBss->SupRateLen; idx++) { + if (pBss->SupRate[idx] & 0x80) + item->basicRate[b_idx++] = pBss->SupRate[idx] & 0x7F; + else + item->suppoRate[s_idx++] = pBss->SupRate[idx]; + } + pAd->ScanTab.ScanResult.cnt++; + + printk("\n-------------- No.%03d -------------------\n", bssIdx); + printk("\tSSID : %s\n", rpt->items[bssIdx].ssid); + printk("\tMac Address : %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(rpt->items[bssIdx].macAddr)); + printk("\tNoise : %d\n", rpt->items[bssIdx].noise); + printk("\tBeaconPeriod: %d\n", rpt->items[bssIdx].beaconPeriod); + printk("\tDtimPeriod : %d\n", rpt->items[bssIdx].dtimPeriod); + printk("\tChannel : %d\n", rpt->items[bssIdx].channel); + printk("\tBasic Rate : "); + j = 0; + while (rpt->items[bssIdx].basicRate[j] != 0 && j < MAX_LENGTH_OF_SUPPORT_RATES) { + printk("%d ", rpt->items[bssIdx].basicRate[j++] / 2); + } + printk("\n\tSupport Rate: "); + j = 0; + while (rpt->items[bssIdx].suppoRate[j] != 0 && j < MAX_LENGTH_OF_SUPPORT_RATES) { + printk("%d ", rpt->items[bssIdx].suppoRate[j++] / 2); + } + printk("\n"); + } + } + + return TRUE; +} +#endif + +/* + ========================================================================== + 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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 Time = simple_strtol(arg, 0, 10); + +#ifndef ACS_CTCC_SUPPORT + Time = Time * 3600; /* second */ +#endif + pAd->ApCfg.ACSCheckTime = Time; + pAd->ApCfg.ACSCheckCount = 0; /* Reset counter */ + DBGPRINT(RT_DEBUG_TRACE, ("%s(): ACSCheckTime=%u seconds\n", + __FUNCTION__, pAd->ApCfg.ACSCheckTime)); + return TRUE; +} +#endif /* AP_SCAN_SUPPORT */ + +#ifdef PREVENT_ARP_SPOOFING +INT Set_ARPSpoofChk_Enable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT Enable; + + Enable = (UINT) simple_strtol(arg, 0, 10); + + pAd->ApCfg.ARPSpoofChk = (BOOLEAN)(Enable == 0 ? FALSE : TRUE); + DBGPRINT(RT_DEBUG_TRACE, ("%s: ARPSpoofChk=%d\n", __FUNCTION__, pAd->ApCfg.ARPSpoofChk)); + + return TRUE; +} +#endif /* PREVENT_ARP_SPOOFING */ + +#ifdef DBG +INT Show_DriverInfo_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + DBGPRINT(RT_DEBUG_OFF, ("Driver version: %s \n", AP_DRIVER_VERSION)); +#ifdef CONFIG_ANDES_SUPPORT + if (pAd->chipCap.MCUType == ANDES) { + UINT32 loop = 0; + RTMP_CHIP_CAP *cap = &pAd->chipCap; + + if (pAd->chipCap.need_load_fw) { + USHORT fw_ver, build_ver; + fw_ver = (*(cap->FWImageName + 11) << 8) | (*(cap->FWImageName + 10)); + build_ver = (*(cap->FWImageName + 9) << 8) | (*(cap->FWImageName + 8)); + + DBGPRINT(RT_DEBUG_OFF, ("fw version:%d.%d.%02d ", (fw_ver & 0xf000) >> 8, + (fw_ver & 0x0f00) >> 8, fw_ver & 0x00ff)); + DBGPRINT(RT_DEBUG_OFF, ("build:%x\n", build_ver)); + DBGPRINT(RT_DEBUG_OFF, ("build time:")); + + for (loop = 0; loop < 16; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->FWImageName + 16 + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + } + + if (pAd->chipCap.need_load_rom_patch) { + DBGPRINT(RT_DEBUG_OFF, ("rom patch version = \n")); + + for (loop = 0; loop < 4; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->rom_patch + 24 + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("build time = \n")); + + for (loop = 0; loop < 16; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->rom_patch + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + } + } +#endif + +#if defined(MT7603_FPGA) || defined(MT7628_FPGA) + if ((IS_MT7603(pAd) || IS_MT7628(pAd)) && pAd->chipCap.hif_type == HIF_MT) { + UINT32 mac_val, ver, date_code, rev; + + RTMP_IO_READ32(pAd, 0x2700, &ver); + RTMP_IO_READ32(pAd, 0x2704, &rev); + RTMP_IO_READ32(pAd, 0x2708, &date_code); + RTMP_IO_READ32(pAd, 0x21f8, &mac_val); + DBGPRINT(RT_DEBUG_OFF, ("##########################################\n")); + DBGPRINT(RT_DEBUG_OFF, ("MT7603 FPGA Version:\n")); + + DBGPRINT(RT_DEBUG_OFF, ("\tFGPA1: Code[0x700]:0x%x, [0x704]:0x%x, [0x708]:0x%x\n", + ver, rev, date_code)); + DBGPRINT(RT_DEBUG_OFF, ("\tFPGA2: Version[0x21f8]:0x%x\n", mac_val)); + DBGPRINT(RT_DEBUG_OFF, ("##########################################\n")); + } +#endif /* MT7603_FPGA */ + + return TRUE; +} + +static INT show_apcfg_info(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + struct wifi_dev *wdev = NULL; + struct apcfg_parameters apcfg_para_setting; + LONG cfg_mode; + UCHAR wmode; + POS_COOKIE pObj = NULL; + CHAR str[10] = ""; + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("\nshow ap cfg info:\n")); + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj == NULL) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("pObj is NULL\n")); + return FALSE; + } + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + if (wdev == NULL) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("wdev is NULL\n")); + return FALSE; + } + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16s%-8s\n", " ", "WIFI_DRIVER", "PEAK_VALUE")); + + /*WirelessMode*/ + wmode = pAd->CommonCfg.PhyMode; + cfg_mode = wmode_2_cfgmode(wmode); + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16ld%ld\n", "WirelessMode", cfg_mode, + apcfg_for_peak.cfg_mode[0])); + + /*TxPower*/ +#ifdef DBDC_MODE + if (pAd->CommonCfg.dbdc_mode) { + band_idx = HcGetBandByWdev(wdev); + apcfg_para_setting.tx_power_percentage = pAd->CommonCfg.TxPowerPercentage[band_idx]; + } else + apcfg_para_setting.tx_power_percentage = pAd->CommonCfg.TxPowerPercentage; +#else + apcfg_para_setting.tx_power_percentage = pAd->CommonCfg.TxPowerPercentage; +#endif + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16lu%lu\n", "TxPower", + apcfg_para_setting.tx_power_percentage, + apcfg_for_peak.tx_power_percentage)); + + /*TxPreamble*/ + apcfg_para_setting.tx_preamble = pAd->CommonCfg.TxPreamble; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16lu%lu\n", "TxPreamble", + apcfg_para_setting.tx_preamble, + apcfg_for_peak.tx_preamble)); + + /*RTSThreshold*/ + apcfg_para_setting.conf_len_thld = pAd->CommonCfg.RtsThreshold; + apcfg_para_setting.oper_len_thld = pAd->CommonCfg.RtsThreshold; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "RTSThreshold(config)", + apcfg_para_setting.conf_len_thld, + apcfg_for_peak.conf_len_thld)); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "RTSThreshold(operate)", + apcfg_para_setting.oper_len_thld, + apcfg_for_peak.oper_len_thld)); + + /*FragThreshold*/ + apcfg_para_setting.conf_frag_thld = pAd->CommonCfg.FragmentThreshold; + apcfg_para_setting.oper_frag_thld = pAd->CommonCfg.FragmentThreshold; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "FragThreshold(config)", + apcfg_para_setting.conf_frag_thld, + apcfg_for_peak.conf_frag_thld)); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "FragThreshold(operate)", + apcfg_para_setting.oper_frag_thld, + apcfg_for_peak.oper_frag_thld)); + + /*TxBurst*/ + apcfg_para_setting.bEnableTxBurst = pAd->CommonCfg.bEnableTxBurst; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "TxBurst", + apcfg_para_setting.bEnableTxBurst, + apcfg_for_peak.bEnableTxBurst)); + + /*ShortSlot*/ + apcfg_para_setting.bUseShortSlotTime = pAd->CommonCfg.bUseShortSlotTime; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "ShortSlot", + apcfg_para_setting.bUseShortSlotTime, + apcfg_for_peak.bUseShortSlotTime)); + +#ifdef DOT11_N_SUPPORT + /*HT_BW*/ + apcfg_para_setting.conf_ht_bw = pAd->CommonCfg.RegTransmitSetting.field.BW; + apcfg_para_setting.oper_ht_bw = pAd->CommonCfg.RegTransmitSetting.field.BW; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "HT_BW(config)", + apcfg_para_setting.conf_ht_bw, + apcfg_for_peak.conf_ht_bw)); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "HT_BW(operate)", + apcfg_para_setting.oper_ht_bw, + apcfg_for_peak.oper_ht_bw)); + +#ifdef DOT11N_DRAFT3 + /*HT_BSSCoexistence */ + apcfg_para_setting.bBssCoexEnable = pAd->CommonCfg.bBssCoexEnable; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "HT_BSSCoexistence", + apcfg_para_setting.bBssCoexEnable, + apcfg_for_peak.bBssCoexEnable)); +#endif + + /*HT_TxStream */ + apcfg_para_setting.ht_tx_streams = pAd->CommonCfg.TxStream; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "HT_TxStream", + apcfg_para_setting.ht_tx_streams, + apcfg_for_peak.ht_tx_streams)); + + /*HT_RxStream */ + apcfg_para_setting.ht_rx_streams = pAd->CommonCfg.RxStream; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "HT_RxStream", + apcfg_para_setting.ht_rx_streams, + apcfg_for_peak.ht_rx_streams)); + + /*HT_BADecline*/ + apcfg_para_setting.bBADecline = pAd->CommonCfg.bBADecline; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "HT_BADecline", + apcfg_para_setting.bBADecline, + apcfg_for_peak.bBADecline)); + + /*HT_AutoBA*/ + apcfg_para_setting.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "HT_AutoBA", + apcfg_para_setting.AutoBA, + apcfg_for_peak.AutoBA)); + + /*HT_AMSDU */ + apcfg_para_setting.AmsduEnable = pAd->CommonCfg.BACapability.field.AmsduEnable; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "HT_AMSDU", + apcfg_para_setting.AmsduEnable, + apcfg_for_peak.AmsduEnable)); + + /*HT_BAWinSize*/ + apcfg_para_setting.RxBAWinLimit = pAd->CommonCfg.BACapability.field.RxBAWinLimit; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "HT_BAWinSize", + apcfg_para_setting.RxBAWinLimit, + apcfg_for_peak.RxBAWinLimit)); + + /*HT_GI*/ + apcfg_para_setting.ht_gi = pAd->CommonCfg.RegTransmitSetting.field.ShortGI; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "HT_GI", + apcfg_para_setting.ht_gi, + apcfg_for_peak.ht_gi)); + + /*HT_STBC*/ + apcfg_para_setting.ht_stbc = pAd->CommonCfg.RegTransmitSetting.field.STBC; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "HT_STBC", + apcfg_para_setting.ht_stbc, + apcfg_for_peak.ht_stbc)); + + /*HT_LDPC*/ + apcfg_para_setting.ht_ldpc = pAd->CommonCfg.ht_ldpc; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "HT_LDPC", + apcfg_para_setting.ht_ldpc, + apcfg_for_peak.ht_ldpc)); + + /*HT_RDG*/ + apcfg_para_setting.bRdg = pAd->CommonCfg.bRdg; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "HT_RDG", + apcfg_para_setting.bRdg, + apcfg_for_peak.bRdg)); +#endif + + /*HT_DisallowTKIP*/ + apcfg_para_setting.HT_DisallowTKIP = pAd->CommonCfg.HT_DisallowTKIP; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "HT_DisallowTKIP", + apcfg_para_setting.HT_DisallowTKIP, + apcfg_for_peak.HT_DisallowTKIP)); + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_5G(wmode)) { + /*VHT_BW*/ + apcfg_para_setting.conf_vht_bw = wlan_config_get_vht_bw(wdev); + apcfg_para_setting.oper_vht_bw = wlan_operate_get_vht_bw(wdev); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "VHT_BW(config)", + apcfg_para_setting.conf_vht_bw, + apcfg_for_peak.conf_vht_bw)); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "VHT_BW(operate)", + apcfg_para_setting.oper_vht_bw, + apcfg_for_peak.oper_vht_bw)); + + /*VHT_SGI */ + apcfg_para_setting.vht_sgi = pAd->CommonCfg.vht_sgi; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "VHT_SGI", + apcfg_para_setting.vht_sgi, + apcfg_for_peak.vht_sgi)); + + /*VHT_STBC*/ + apcfg_para_setting.vht_stbc = wlan_config_get_vht_stbc(wdev); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "VHT_STBC", + apcfg_para_setting.vht_stbc, + apcfg_for_peak.vht_stbc)); + + /*VHT_BW_SIGNAL*/ + apcfg_para_setting.vht_bw_signal = pAd->CommonCfg.vht_bw_signal; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "VHT_BW_SIGNAL", + apcfg_para_setting.vht_bw_signal, + apcfg_for_peak.vht_bw_signal)); + + /*VHT_LDPC*/ + apcfg_para_setting.vht_ldpc = wlan_config_get_vht_ldpc(wdev); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "VHT_LDPC", + apcfg_para_setting.vht_ldpc, + apcfg_for_peak.vht_ldpc)); + } + + if (WMODE_CAP_2G(wmode)) { + /*G_BAND_256QAM*/ + apcfg_para_setting.g_band_256_qam = pAd->CommonCfg.g_band_256_qam; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "G_BAND_256QAM", + apcfg_para_setting.g_band_256_qam, + apcfg_for_peak.g_band_256_qam)); + } +#endif + +#ifdef MT_DFS_SUPPORT + /*DfsEnable*/ + if (WMODE_CAP_5G(wmode)) { + apcfg_para_setting.bDfsEnable = pAd->CommonCfg.DfsParameter.bDfsEnable; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "DfsEnable", + apcfg_para_setting.bDfsEnable, + apcfg_for_peak.bDfsEnable)); + } +#endif + +#ifdef BACKGROUND_SCAN_SUPPORT + /*DfsZeroWait*/ + if (!(pAd->CommonCfg.dbdc_mode)) { + apcfg_para_setting.DfsZeroWaitSupport = pAd->BgndScanCtrl.DfsZeroWaitSupport; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "DfsZeroWait", + apcfg_para_setting.DfsZeroWaitSupport, + apcfg_for_peak.DfsZeroWaitSupport)); + } +#endif + +#ifdef DOT11_N_SUPPORT +#endif + + /*ITxBfEn*/ + apcfg_para_setting.ITxBfEn = pAd->CommonCfg.RegTransmitSetting.field.ITxBfEn; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16d%d\n", "ITxBfEn", + apcfg_para_setting.ITxBfEn, + apcfg_for_peak.ITxBfEn)); + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("-----------------------------------------------------\n")); + + /*external channel*/ + apcfg_para_setting.channel = pAd->CommonCfg.Channel; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16u\n", "current channel", + apcfg_para_setting.channel)); + + apcfg_para_setting.CentralChannel = pAd->CommonCfg.CentralChannel; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16u\n", "central channel", + apcfg_para_setting.CentralChannel)); + + apcfg_para_setting.ext_channel = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; + + if (pAd->CommonCfg.RegTransmitSetting.field.BW == 0) + sprintf(str, "NONE"); + else if (apcfg_para_setting.ext_channel == EXTCHA_ABOVE) + sprintf(str, "ABOVE"); + else if (apcfg_para_setting.ext_channel == EXTCHA_BELOW) + sprintf(str, "BELOW"); + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-24s%-16s\n", "extension channel", str)); + + return TRUE; +} +#ifdef PREVENT_ARP_SPOOFING +INT Show_ARPSpoofChk_Enable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + DBGPRINT(RT_DEBUG_OFF, ("ARPSpoofChk=%d\n",pAd->ApCfg.ARPSpoofChk)); + return TRUE; +} +#endif /* PREVENT_ARP_SPOOFING */ + +INT Show_StaCount_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT i = 0, bss_idx=0; + BSS_STRUCT *pMbss = NULL; + UCHAR temp_str[20]; + INT temp_len = sizeof(temp_str); + + printk("\n"); + for (bss_idx=0; bss_idx < pAd->ApCfg.BssidNum; bss_idx++) + { + pMbss = &pAd->ApCfg.MBSSID[bss_idx]; + printk("BSS[%02d]: %5d\n", bss_idx, pMbss->StaCount); + } + + printk("\n"); +#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%-12s%-12s\n", + "MAC", "AID", "TxPackets", "RxPackets", "TxBytes", "RxBytes", "TP(Tx)", "TP(Rx)"); + + 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); + snprintf(temp_str, temp_len, "%lu%s", (pEntry->AvgTxBytes >> 17), "Mbps");/* (n Bytes x 8) / (1024*1024) = (n >> 17) */ + printk("%-12s", temp_str); + snprintf(temp_str, temp_len, "%lu%s", (pEntry->AvgRxBytes >> 17), "Mbps");/* (n Bytes x 8) / (1024*1024) = (n >> 17) */ + printk("%-12s", temp_str); + printk("\n"); + } + } + + return TRUE; +} + + +INT Show_StaSecurityInfo_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT i; + UCHAR apidx; + struct wifi_dev *wdev; + + printk("\n"); + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + printk(" BSS(%d) AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s, WPAMixPairCipher(0x%02X)\n", + apidx, + wdev->AuthMode, GetAuthMode(wdev->AuthMode), + wdev->WepStatus, GetEncryptType(wdev->WepStatus), + wdev->GroupKeyWepStatus, GetEncryptType(wdev->GroupKeyWepStatus), + wdev->WpaMixPairCipher); + } + printk("\n"); + + printk("\n%-19s%-4s%-4s%-15s%-12s\n", + "MAC", "AID", "BSS", "Auth", "Encrypt"); + + for (i=0; iMacTab.Content[i]; + if (pEntry && IS_ENTRY_CLIENT(pEntry) && pEntry->Sst == SST_ASSOC) + { + printk("%02X:%02X:%02X:%02X:%02X:%02X ", + PRINT_MAC(pEntry->Addr)); + printk("%-4d", (int)pEntry->Aid); + printk("%-4d", (int)pEntry->func_tb_idx); + printk("%-15s", GetAuthMode(pEntry->AuthMode)); + printk("%-12s", GetEncryptType(pEntry->WepStatus)); + printk("\n"); + } + } + + return TRUE; +} + + +INT Show_RAInfo_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ +#ifdef PRE_ANT_SWITCH + DBGPRINT(RT_DEBUG_OFF, ("PreAntSwitch: %d\n", pAd->CommonCfg.PreAntSwitch)); + DBGPRINT(RT_DEBUG_OFF, ("PreAntSwitchRSSI: %d\n", pAd->CommonCfg.PreAntSwitchRSSI)); +#endif /* PRE_ANT_SWITCH */ + +#ifdef CFO_TRACK + DBGPRINT(RT_DEBUG_OFF, ("CFOTrack: %d\n", pAd->CommonCfg.CFOTrack)); +#endif /* CFO_TRACK */ + + +#ifdef NEW_RATE_ADAPT_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("LowTrafficThrd: %d\n", pAd->CommonCfg.lowTrafficThrd)); + DBGPRINT(RT_DEBUG_OFF, ("TrainUpRule: %d\n", pAd->CommonCfg.TrainUpRule)); + DBGPRINT(RT_DEBUG_OFF, ("TrainUpRuleRSSI: %d\n", pAd->CommonCfg.TrainUpRuleRSSI)); + DBGPRINT(RT_DEBUG_OFF, ("TrainUpLowThrd: %d\n", pAd->CommonCfg.TrainUpLowThrd)); + DBGPRINT(RT_DEBUG_OFF, ("TrainUpHighThrd: %d\n", pAd->CommonCfg.TrainUpHighThrd)); +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#ifdef STREAM_MODE_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("StreamMode: %d\n", pAd->CommonCfg.StreamMode)); + DBGPRINT(RT_DEBUG_OFF, ("StreamModeMCS: 0x%04x\n", pAd->CommonCfg.StreamModeMCS)); +#endif /* STREAM_MODE_SUPPORT */ + +#ifdef DBG_CTRL_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("DebugFlags: 0x%lx\n", pAd->CommonCfg.DebugFlags)); +#endif /* DBG_CTRL_SUPPORT */ + + return TRUE; +} +#endif /* DBG */ + +#ifdef RTMP_MAC_PCI +#ifdef DBG_DIAGNOSE +INT Set_DiagOpt_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG diagOpt; + /*POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; */ + + diagOpt = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("DiagOpt=%ld!\n", diagOpt)); + + return TRUE; +} + + +INT Set_BDInfo_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT32 i, QueIdx=0; + UINT32 RegValue; + RXD_STRUC *pRxD; + TXD_STRUC *pTxD; +#ifdef RT_BIG_ENDIAN + RXD_STRUC *pDestRxD, *pDestTxD; + RXD_STRUC RxD, TxD; +#endif /* RT_BIG_ENDIAN */ + RTMP_TX_RING *pTxRing = &pAd->TxRing[QueIdx]; + RTMP_MGMT_RING *pMgmtRing = &pAd->MgmtRing; + RTMP_RX_RING *pRxRing = &pAd->RxRing[0]; + + printk("\n"); + +#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 = (TXD_STRUC *) pTxRing->Cell[pAd->TxRing[QueIdx].TxSwFreeIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_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 = (TXD_STRUC *) pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_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 = (TXD_STRUC *) pTxRing->Cell[pAd->TxRing[QueIdx].TxDmaIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_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 = (TXD_STRUC *) pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_STRUC *) pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa; +#endif /* RT_BIG_ENDIAN */ + hex_dump("Mgmt SwFreeIdx Descriptor", (char *)pTxD, 16); + +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *) pMgmtRing->Cell[pAd->MgmtRing.TxCpuIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_STRUC *) pMgmtRing->Cell[pAd->MgmtRing.TxCpuIdx].AllocVa; +#endif /* RT_BIG_ENDIAN */ + hex_dump("Mgmt CpuIdx Descriptor", (char *)pTxD, 16); + +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *) pMgmtRing->Cell[pAd->MgmtRing.TxDmaIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_STRUC *) pMgmtRing->Cell[pAd->MgmtRing.TxDmaIdx].AllocVa; +#endif /* RT_BIG_ENDIAN */ + hex_dump("Mgmt DmaIdx Descriptor", (char *)pTxD, 16); + printk("\n"); + printk("[Rx]: SwRedIdx=%d, CpuIdx=%d, DmaIdx=%d\n", + pAd->RxRing[0].RxSwReadIdx, + pAd->RxRing[0].RxCpuIdx, + pAd->RxRing[0].RxDmaIdx); + +#ifdef RT_BIG_ENDIAN + pDestRxD = (RXD_STRUC *) pRxRing->Cell[pAd->RxRing[0].RxSwReadIdx].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + pRxD = (RXD_STRUC *) pRxRing->Cell[pAd->RxRing[0].RxSwReadIdx].AllocVa; +#endif /* RT_BIG_ENDIAN */ + hex_dump("RX SwRedIdx Descriptor", (char *)pRxD, 16); + +#ifdef RT_BIG_ENDIAN + pDestRxD = (RXD_STRUC *) pRxRing->Cell[pAd->RxRing[0].RxCpuIdx].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + pRxD = (RXD_STRUC *) pRxRing->Cell[pAd->RxRing[0].RxCpuIdx].AllocVa; +#endif /* RT_BIG_ENDIAN */ + hex_dump("RX RxCupIdx Descriptor", (char *)pRxD, 16); + +#ifdef RT_BIG_ENDIAN + pDestRxD = (RXD_STRUC *) pRxRing->Cell[pAd->RxRing[0].RxDmaIdx].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + pRxD = (RXD_STRUC *) pRxRing->Cell[pAd->RxRing[0].RxDmaIdx].AllocVa; +#endif /* RT_BIG_ENDIAN */ + hex_dump("RX RxDmaIdx Descritpro", (char *)pRxD, 16); + printk("\n%-19s%-4s%-4s%-7s%-7s%-7s%-10s%-6s%-6s%-6s%-6s\n", + "MAC", "AID", "PSM", "RSSI0", "RSSI1", "RSSI2", "PhMd", "BW", "MCS", "SGI", "STBC"); + + for (i=0; iMacTab.Content[i]; + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) + { + printk("%02X:%02X:%02X:%02X:%02X:%02X ", + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], + pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]); + printk("%-4d", (int)pEntry->Aid); + printk("%-4d", (int)pEntry->PsMode); + printk("%-7d", pEntry->RssiSample.AvgRssi[0]); + printk("%-7d", pEntry->RssiSample.AvgRssi[1]); + printk("%-7d", pEntry->RssiSample.AvgRssi[2]); + + + printk("%-10s", get_phymode_str(pEntry->HTPhyMode.field.MODE)); + printk("%-6s", get_bw_str(pEntry->HTPhyMode.field.BW)); + printk("%-6d", pEntry->HTPhyMode.field.MCS); + printk("%-6d", pEntry->HTPhyMode.field.ShortGI); + printk("%-6d", pEntry->HTPhyMode.field.STBC); + printk("%-10d, %d, %d\n", pEntry->FIFOCount, pEntry->DebugTxCount, pEntry->DebugTxCount-pEntry->FIFOCount); + + printk("\n"); + } + } + + return TRUE; +} + + +INT Set_diag_cond_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 cond; + + cond = simple_strtol(arg, 0, 10); + pAd->DiagStruct.diag_cond = cond; + + return TRUE; +} + + +INT Show_Diag_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + RtmpDiagStruct *pDiag = NULL; + UCHAR i, start, stop, McsIdx, SwQNumLevel, TxDescNumLevel, que_idx; + unsigned long irqFlags; + UCHAR McsMaxIdx = MAX_MCS_SET; +#ifdef DOT11_VHT_AC + UCHAR vht_mcs_max_idx = MAX_VHT_MCS_SET; +#endif /* DOT11_VHT_AC */ + + os_alloc_mem(pAd, (UCHAR **)&pDiag, sizeof(RtmpDiagStruct)); + if (!pDiag) { + DBGPRINT(RT_DEBUG_ERROR, ("%s():AllocMem failed!\n", __FUNCTION__)); + return FALSE; + } + + RTMP_IRQ_LOCK(&pAd->irq_lock, irqFlags); + NdisMoveMemory(pDiag, &pAd->DiagStruct, sizeof(RtmpDiagStruct)); + RTMP_IRQ_UNLOCK(&pAd->irq_lock, irqFlags); + +#ifdef DOT11N_SS3_SUPPORT + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + McsMaxIdx = 24; +#endif /* DOT11N_SS3_SUPPORT */ + + if (pDiag->inited == FALSE) + goto done; + + start = pDiag->ArrayStartIdx; + stop = pDiag->ArrayCurIdx; + printk("Start=%d, stop=%d!\n\n", start, stop); + printk(" %-12s", "Time(Sec)"); + for(i=1; i< DIAGNOSE_TIME; i++) + { + printk("%-7d", i); + } + printk("\n -------------------------------------------------------------------------------\n"); + printk("Tx Info:\n"); + printk(" %-12s", "TxDataCnt\n"); + for (que_idx = 0; que_idx < WMM_NUM_OF_AC; que_idx++) { + printk("\tQueue[%d]:", que_idx); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->diag_info[i].TxDataCnt[que_idx]); + } + printk("\n"); + } + printk("\n %-12s", "TxFailCnt"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->diag_info[i].TxFailCnt); + } + +#ifdef DBG_TX_AGG_CNT + printk("\n %-12s", "TxAggCnt"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->diag_info[i].TxAggCnt); + } + printk("\n"); +#endif /* DBG_TX_AGG_CNT */ + +#ifdef DBG_TXQ_DEPTH + printk("DeQueue Info:\n"); + + printk("\n %-12s\n", "DeQueueFunc Called Distribution"); + printk("\t"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + printk("%-8d", pDiag->diag_info[i].deq_called); + + printk("\n %-12s\n", "DeQueueRound(Per-Call) Distribution"); + printk("\t"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + printk("%-8d", pDiag->diag_info[i].deq_round); + + printk("\n %-12s\n", "DeQueueCount(Per-Round) Distribution"); + for (SwQNumLevel = 0 ; SwQNumLevel < 9; SwQNumLevel++) + { + if (SwQNumLevel == 8) + printk("\t>%-5d", SwQNumLevel); + else + printk("\t%-6d", SwQNumLevel); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + printk("%-7d", pDiag->diag_info[i].deq_cnt[SwQNumLevel]); + + printk("\n"); + } + + printk("\n %-12s%d", "Sw-Queued TxSwQCnt for WCID ", pDiag->wcid); + for (que_idx = 0; que_idx < WMM_NUM_OF_AC; que_idx++) { + printk("\n %s[%d]\n", "Queue", que_idx); + for (SwQNumLevel = 0 ; SwQNumLevel < 9; SwQNumLevel++) + { + if (SwQNumLevel == 8) + printk("\t>%-5d", SwQNumLevel); + else + printk("\t%-6d", SwQNumLevel); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + printk("%-7d", pDiag->diag_info[i].TxSWQueCnt[que_idx][SwQNumLevel]); + + printk("\n"); + } + printk(" %-12s\n", "TxEnQFailCnt"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("\t%-7d", pDiag->diag_info[i].enq_fall_cnt[que_idx]); + } + printk("\n"); + } + + printk("\n %s\n", "DeQueFailedCnt:Reason NotTxResource"); + for (que_idx = 0; que_idx < WMM_NUM_OF_AC; que_idx++) { + printk("\n %s[%d]:", "Queue", que_idx); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + printk("\t%-7d", pDiag->diag_info[i].deq_fail_no_resource_cnt[que_idx]); + } +#endif /* DBG_TXQ_DEPTH */ + +#ifdef DBG_TX_RING_DEPTH + printk("\n %-12s\n", "DMA-Queued TxDescCnt"); + for (que_idx = 0; que_idx < WMM_NUM_OF_AC; que_idx++) { + printk("\n Queue[%d]\n", que_idx); + for(TxDescNumLevel = 0; TxDescNumLevel < 16; TxDescNumLevel++) + { + if (TxDescNumLevel == 15) + printk("\t>%-5d", TxDescNumLevel); + else + printk("\t%-6d", TxDescNumLevel); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + printk("%-7d", pDiag->diag_info[i].TxDescCnt[que_idx][TxDescNumLevel]); + + printk("\n"); + } + } +#endif /* DBG_TX_RING_DEPTH */ + +#ifdef MT_MAC +#ifdef DBG_PSE_DEPTH + printk("\n %-12s\n", "PSE-Queued TxPageCnt in unit of Packets (mod 13)"); + { + UCHAR pg_level; + for(pg_level = 0; pg_level < 50; pg_level++) + { + if (pg_level == 49) + printk("\t>%-5d", pg_level); + else + printk("\t%-6d", pg_level); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + printk("%-7d", pDiag->diag_info[i].pse_pg_cnt[pg_level]); + + printk("\n"); + } + } +#endif /* DBG_PSE_DEPTH */ +#endif /* MT_MAC */ + +#ifdef DOT11_N_SUPPORT +#ifdef DBG_TX_AGG_CNT + printk("\n %-12s\n", "Tx-Agged AMPDUCnt"); + for (McsIdx =0 ; McsIdx < 16; McsIdx++) + { + printk("\t%-6d", (McsIdx+1)); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%d(%d%%) ", pDiag->diag_info[i].TxAMPDUCnt[McsIdx], + pDiag->diag_info[i].TxAMPDUCnt[McsIdx] ? (pDiag->diag_info[i].TxAMPDUCnt[McsIdx] * 100 / pDiag->diag_info[i].TxAggCnt) : 0); + } + printk("\n"); + } +#endif /* DBG_TX_AGG_CNT */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef DBG_TX_MCS + printk("\n %-12s\n", "TxMcsCnt_HT"); + for (McsIdx =0 ; McsIdx < McsMaxIdx; McsIdx++) + { + printk("\t%-6d", McsIdx); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + printk("%-7d", pDiag->diag_info[i].TxMcsCnt_HT[McsIdx]); + printk("\n"); + } + +#ifdef DOT11_VHT_AC + printk("\n %-12s\n", "TxMcsCnt_VHT"); + for (McsIdx =0 ; McsIdx < vht_mcs_max_idx; McsIdx++) + { + printk("\t%-6d", McsIdx); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + printk("%-7d", pDiag->diag_info[i].TxMcsCnt_VHT[McsIdx]); + printk("\n"); + } +#endif /* DOT11_VHT_AC */ +#endif /* DBG_TX_MCS */ + + + + printk("Rx Info\n"); + printk(" %-12s", "RxDataCnt"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->diag_info[i].RxDataCnt); + } + printk("\n %-12s", "RxCrcErrCnt"); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->diag_info[i].RxCrcErrCnt); + } + +#ifdef DBG_RX_MCS + printk("\n %-12s\n", "RxMcsCnt_HT"); + for (McsIdx =0 ; McsIdx < McsMaxIdx; McsIdx++) + { + printk("\t%-6d", McsIdx); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->diag_info[i].RxMcsCnt_HT[McsIdx]); + } + printk("\n"); + } + +#ifdef DOT11_VHT_AC + printk("\n %-12s\n", "RxMcsCnt_VHT"); + for (McsIdx =0 ; McsIdx < vht_mcs_max_idx; McsIdx++) + { + printk("\t%-6d", McsIdx); + for (i = start; i != stop; i = (i+1) % DIAGNOSE_TIME) + { + printk("%-7d", pDiag->diag_info[i].RxMcsCnt_VHT[McsIdx]); + } + printk("\n"); + } +#endif /* DOT11_VHT_AC */ + +#endif /* DBG_RX_MCS */ + + printk("\n-------------\n"); + +done: + os_free_mem(pAd, pDiag); + return TRUE; +} +#endif /* DBG_DIAGNOSE */ +#endif /* RTMP_MAC_PCI */ + + +#ifdef DBG +INT Show_Sat_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ +#ifdef ANDLINK_FEATURE_SUPPORT + struct wifi_event event; +#endif + /* Sanity check for calculation of sucessful count */ + printk("TransmitCountFromOS = %d\n", pAd->WlanCounters.TransmitCountFrmOs.u.LowPart); + printk("TransmittedFragmentCount = %lld\n", pAd->WlanCounters.TransmittedFragmentCount.u.LowPart + pAd->WlanCounters.MulticastTransmittedFrameCount.QuadPart); + printk("MulticastTransmittedFrameCount = %d\n", pAd->WlanCounters.MulticastTransmittedFrameCount.u.LowPart); + printk("FailedCount = %d\n", pAd->WlanCounters.FailedCount.u.LowPart); + printk("RetryCount = %d\n", pAd->WlanCounters.RetryCount.u.LowPart); + printk("MultipleRetryCount = %d\n", pAd->WlanCounters.MultipleRetryCount.u.LowPart); + printk("RTSSuccessCount = %d\n", pAd->WlanCounters.RTSSuccessCount.u.LowPart); + printk("RTSFailureCount = %d\n", pAd->WlanCounters.RTSFailureCount.u.LowPart); + printk("ACKFailureCount = %d\n", pAd->WlanCounters.ACKFailureCount.u.LowPart); + printk("FrameDuplicateCount = %d\n", pAd->WlanCounters.FrameDuplicateCount.u.LowPart); + printk("ReceivedFragmentCount = %d\n", pAd->WlanCounters.ReceivedFragmentCount.u.LowPart); + printk("MulticastReceivedFrameCount = %d\n", pAd->WlanCounters.MulticastReceivedFrameCount.u.LowPart); + printk("Rx drop due to out of resource = %ld\n", (ULONG)pAd->Counters8023.RxNoBuffer); +#ifdef DBG + printk("RealFcsErrCount = %d\n", pAd->RalinkCounters.RealFcsErrCount.u.LowPart); +#else + printk("FCSErrorCount = %d\n", pAd->WlanCounters.FCSErrorCount.u.LowPart); + printk("FrameDuplicateCount.LowPart = %d\n", pAd->WlanCounters.FrameDuplicateCount.u.LowPart / 100); +#endif + printk("TransmittedFrameCount = %d\n", pAd->WlanCounters.TransmittedFragmentCount.u.LowPart); + printk("WEPUndecryptableCount = %d\n", pAd->WlanCounters.WEPUndecryptableCount.u.LowPart); + +#ifdef DOT11_N_SUPPORT + printk("\n===Some 11n statistics variables: \n"); + /* Some 11n statistics variables */ + printk("TxAMSDUCount = %ld\n", (ULONG)pAd->RalinkCounters.TxAMSDUCount.u.LowPart); + printk("RxAMSDUCount = %ld\n", (ULONG)pAd->RalinkCounters.RxAMSDUCount.u.LowPart); + 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 ANDLINK_FEATURE_SUPPORT + event.type = EVENTTYPE_INF_STATS; + memcpy(event.MAC, pAd->ApCfg.MBSSID[apidx].wdev.bssid, MAC_ADDR_LEN); + memcpy(event.SSID, pAd->ApCfg.MBSSID[apidx].Ssid, MAX_LEN_OF_SSID); + event.data.inf_stats.PacketsReceived = pAd->ApCfg.MBSSID[apidx].RxCount; + event.data.inf_stats.PacketsSent = pAd->ApCfg.MBSSID[apidx].TxCount; + event.data.inf_stats.BytesReceived = pAd->ApCfg.MBSSID[apidx].ReceivedByteCount; + event.data.inf_stats.BytesSent = pAd->ApCfg.MBSSID[apidx].TransmittedByteCount; + event.data.inf_stats.ErrorReceived = pAd->ApCfg.MBSSID[apidx].RxErrorCount; + event.data.inf_stats.DropPacketsReceived = pAd->ApCfg.MBSSID[apidx].RxDropCount; + + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_ANDLINK_EVENT, + NULL, + (char *)&event, + sizeof(struct wifi_event)); +#endif +#ifdef WSC_INCLUDED + if (pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode != WSC_DISABLE) + { + WSC_CTRL *pWscCtrl; + + pWscCtrl = &pAd->ApCfg.MBSSID[apidx].WscControl; + printk("WscInfo:\n" + "\tWscConfMode=%d\n" + "\tWscMode=%s\n" + "\tWscConfStatus=%d\n" + "\tWscPinCode=%d\n" + "\tWscState=0x%x\n" + "\tWscStatus=0x%x\n", + pWscCtrl->WscConfMode, + ((pWscCtrl->WscMode == WSC_PIN_MODE) ? "PIN" : "PBC"), + pWscCtrl->WscConfStatus, pWscCtrl->WscEnrolleePinCode, + pWscCtrl->WscState, pWscCtrl->WscStatus); + } +#endif /* WSC_INCLUDED */ + + printk("-- IF-ra%d end -- \n", apidx); + } +} + +{ + int i, j, k, maxMcs = MAX_MCS_SET -1; + PMAC_TABLE_ENTRY pEntry; + +#ifdef DOT11N_SS3_SUPPORT + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + maxMcs = 23; +#endif /* DOT11N_SS3_SUPPORT */ + + for (i=0; iMacTab.Content[i]; + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) + { + printk("\n%02x:%02x:%02x:%02x:%02x:%02x - ", PRINT_MAC(pEntry->Addr)); + printk("%-4d\n", (int)pEntry->Aid); + + for (j=maxMcs; j>=0; j--) + { + if ((pEntry->TXMCSExpected[j] != 0) || (pEntry->TXMCSFailed[j] !=0)) + { + printk("MCS[%02d]: Expected %u, Successful %u (%d%%), Failed %u\n", + j, pEntry->TXMCSExpected[j], pEntry->TXMCSSuccessful[j], + pEntry->TXMCSExpected[j] ? (100*pEntry->TXMCSSuccessful[j])/pEntry->TXMCSExpected[j] : 0, + pEntry->TXMCSFailed[j]); + for(k=maxMcs; k>=0; k--) + { + if (pEntry->TXMCSAutoFallBack[j][k] != 0) + { + printk("\t\t\tAutoMCS[%02d]: %u (%d%%)\n", k, pEntry->TXMCSAutoFallBack[j][k], + (100*pEntry->TXMCSAutoFallBack[j][k])/pEntry->TXMCSExpected[j]); + } + } + } + } + } + } + +} + +#ifdef DOT11_N_SUPPORT + /* Display Tx Aggregation statistics */ + DisplayTxAgg(pAd); +#endif /* DOT11_N_SUPPORT */ + + return TRUE; +} + + +INT Show_Sat_Reset_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + /* Sanity check for calculation of sucessful count */ + + printk("TransmittedFragmentCount = %lld\n", pAd->WlanCounters.TransmittedFragmentCount.u.LowPart + pAd->WlanCounters.MulticastTransmittedFrameCount.QuadPart); + printk("MulticastTransmittedFrameCount = %d\n", pAd->WlanCounters.MulticastTransmittedFrameCount.u.LowPart); + printk("FailedCount = %d\n", pAd->WlanCounters.FailedCount.u.LowPart); + printk("RetryCount = %d\n", pAd->WlanCounters.RetryCount.u.LowPart); + printk("MultipleRetryCount = %d\n", pAd->WlanCounters.MultipleRetryCount.u.LowPart); + printk("RTSSuccessCount = %d\n", pAd->WlanCounters.RTSSuccessCount.u.LowPart); + printk("RTSFailureCount = %d\n", pAd->WlanCounters.RTSFailureCount.u.LowPart); + printk("ACKFailureCount = %d\n", pAd->WlanCounters.ACKFailureCount.u.LowPart); + printk("FrameDuplicateCount = %d\n", pAd->WlanCounters.FrameDuplicateCount.u.LowPart); + printk("ReceivedFragmentCount = %d\n", pAd->WlanCounters.ReceivedFragmentCount.u.LowPart); + printk("MulticastReceivedFrameCount = %d\n", pAd->WlanCounters.MulticastReceivedFrameCount.u.LowPart); + printk("Rx drop due to out of resource = %ld\n", (ULONG)pAd->Counters8023.RxNoBuffer); +#ifdef DBG + printk("RealFcsErrCount = %d\n", pAd->RalinkCounters.RealFcsErrCount.u.LowPart); +#else + printk("FCSErrorCount = %d\n", pAd->WlanCounters.FCSErrorCount.u.LowPart); + printk("FrameDuplicateCount.LowPart = %d\n", pAd->WlanCounters.FrameDuplicateCount.u.LowPart / 100); +#endif + printk("TransmittedFrameCount = %d\n", pAd->WlanCounters.TransmittedFrameCount.u.LowPart); + printk("WEPUndecryptableCount = %d\n", pAd->WlanCounters.WEPUndecryptableCount.u.LowPart); + + pAd->WlanCounters.TransmittedFragmentCount.u.LowPart = 0; + pAd->WlanCounters.MulticastTransmittedFrameCount.u.LowPart = 0; + pAd->WlanCounters.FailedCount.u.LowPart = 0; + pAd->WlanCounters.RetryCount.u.LowPart = 0; + pAd->WlanCounters.MultipleRetryCount.u.LowPart = 0; + pAd->WlanCounters.RTSSuccessCount.u.LowPart = 0; + pAd->WlanCounters.RTSFailureCount.u.LowPart = 0; + pAd->WlanCounters.ACKFailureCount.u.LowPart = 0; + pAd->WlanCounters.FrameDuplicateCount.u.LowPart = 0; + pAd->WlanCounters.ReceivedFragmentCount.u.LowPart = 0; + pAd->WlanCounters.MulticastReceivedFrameCount.u.LowPart = 0; + pAd->Counters8023.RxNoBuffer = 0; +#ifdef DBG + pAd->RalinkCounters.RealFcsErrCount.u.LowPart = 0; +#else + pAd->WlanCounters.FCSErrorCount.u.LowPart = 0; + pAd->WlanCounters.FrameDuplicateCount.u.LowPart = 0; +#endif + + pAd->WlanCounters.TransmittedFrameCount.u.LowPart = 0; + pAd->WlanCounters.WEPUndecryptableCount.u.LowPart = 0; + + { + int i, j, k, maxMcs = 15; + PMAC_TABLE_ENTRY pEntry; + +#ifdef DOT11N_SS3_SUPPORT + if (IS_RT2883(pAd) || IS_RT3883(pAd)) + maxMcs = 23; +#endif /* DOT11N_SS3_SUPPORT */ + + for (i=0; iMacTab.Content[i]; + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) + { + + printk("\n%02X:%02X:%02X:%02X:%02X:%02X - ", + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], + pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]); + printk("%-4d\n", (int)pEntry->Aid); + + for (j = maxMcs; j >= 0; j--) + { + if ((pEntry->TXMCSExpected[j] != 0) || (pEntry->TXMCSFailed[j] !=0)) + { + printk("MCS[%02d]: Expected %u, Successful %u (%d%%), Failed %u\n", + j, pEntry->TXMCSExpected[j], pEntry->TXMCSSuccessful[j], + pEntry->TXMCSExpected[j] ? (100*pEntry->TXMCSSuccessful[j])/pEntry->TXMCSExpected[j] : 0, + pEntry->TXMCSFailed[j] + ); + for(k = maxMcs; k >= 0; k--) + { + if (pEntry->TXMCSAutoFallBack[j][k] != 0) + { + printk("\t\t\tAutoMCS[%02d]: %u (%d%%)\n", k, pEntry->TXMCSAutoFallBack[j][k], + (100*pEntry->TXMCSAutoFallBack[j][k])/pEntry->TXMCSExpected[j]); + } + } + } + } + } + for (j = 0; j < (maxMcs + 1); j++) + { + pEntry->TXMCSExpected[j] = 0; + pEntry->TXMCSSuccessful[j] = 0; + pEntry->TXMCSFailed[j] = 0; + for(k = maxMcs; k >= 0; k--) + { + pEntry->TXMCSAutoFallBack[j][k] = 0; + } + } + } + } +#ifdef DOT11_N_SUPPORT + /* Display Tx Aggregation statistics */ + DisplayTxAgg(pAd); +#endif /* DOT11_N_SUPPORT */ + + return TRUE; +} +#endif /* DBG */ + + +#ifdef MAT_SUPPORT +INT Show_MATTable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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++) + { + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; + PDOT1X_BSS_INFO p1xBssInfo = &pConf->Dot1xBssInfo[apidx]; + + p1xBssInfo->radius_srv_num = pMbss->radius_srv_num; + + /* prepare radius ip, port and key */ + for (srv_idx = 0; srv_idx < pMbss->radius_srv_num; srv_idx++) + { + if (pMbss->radius_srv_info[srv_idx].radius_ip != 0) + { + p1xBssInfo->radius_srv_info[srv_idx].radius_ip = pMbss->radius_srv_info[srv_idx].radius_ip; + p1xBssInfo->radius_srv_info[srv_idx].radius_port = pMbss->radius_srv_info[srv_idx].radius_port; + p1xBssInfo->radius_srv_info[srv_idx].radius_key_len = pMbss->radius_srv_info[srv_idx].radius_key_len; + if (pMbss->radius_srv_info[srv_idx].radius_key_len > 0) + { + NdisMoveMemory(p1xBssInfo->radius_srv_info[srv_idx].radius_key, + pMbss->radius_srv_info[srv_idx].radius_key, + pMbss->radius_srv_info[srv_idx].radius_key_len); + } + } + } + + p1xBssInfo->ieee8021xWEP = (pMbss->wdev.IEEE8021X) ? 1 : 0; + + if (p1xBssInfo->ieee8021xWEP) + { + /* Default Key index, length and material */ + keyidx = pMbss->wdev.DefaultKeyId; + p1xBssInfo->key_index = keyidx; + + /* Determine if the key is valid. */ + KeyLen = pAd->SharedKey[apidx][keyidx].KeyLen; + if (KeyLen == 5 || KeyLen == 13) + { + p1xBssInfo->key_length = KeyLen; + NdisMoveMemory(p1xBssInfo->key_material, pAd->SharedKey[apidx][keyidx].Key, KeyLen); + } + } + + /* Get NAS-ID per BSS */ + if (pMbss->NasIdLen > 0) + { + p1xBssInfo->nasId_len = pMbss->NasIdLen; + NdisMoveMemory(p1xBssInfo->nasId, pMbss->NasId, pMbss->NasIdLen); + } + + /* get EAPifname */ + if (pAd->ApCfg.EAPifname_len[apidx] > 0) + { + pConf->EAPifname_len[apidx] = pAd->ApCfg.EAPifname_len[apidx]; + NdisMoveMemory(pConf->EAPifname[apidx], pAd->ApCfg.EAPifname[apidx], pAd->ApCfg.EAPifname_len[apidx]); + } + + /* get PreAuthifname */ + if (pAd->ApCfg.PreAuthifname_len[apidx] > 0) + { + pConf->PreAuthifname_len[apidx] = pAd->ApCfg.PreAuthifname_len[apidx]; + NdisMoveMemory(pConf->PreAuthifname[apidx], pAd->ApCfg.PreAuthifname[apidx], pAd->ApCfg.PreAuthifname_len[apidx]); + } + + } + + wrq->u.data.length = sizeof(DOT1X_CMM_CONF); + if (copy_to_user(wrq->u.data.pointer, pConf, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + + os_free_mem(NULL, mpool); + +} + + +/* + ========================================================================== + Description: + UI should not call this function, it only used by 802.1x daemon + Arguments: + pAd Pointer to our adapter + wrq Pointer to the ioctl argument + ========================================================================== +*/ +VOID RTMPIoctlRadiusData( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + struct wifi_dev *wdev; + + + if (pObj->ioctl_if > pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Invalid MBSSID index(%d)!\n", + __FUNCTION__, pObj->ioctl_if)); + return; + } + + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + if ((wdev->AuthMode == Ndis802_11AuthModeWPA) + || (wdev->AuthMode == Ndis802_11AuthModeWPA2) + || (wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) + || (wdev->IEEE8021X == TRUE)) + WpaSend(pAd, (PUCHAR)wrq->u.data.pointer, wrq->u.data.length); +} + + +/* + ========================================================================== + Description: + UI should not call this function, it only used by 802.1x daemon + Arguments: + pAd Pointer to our adapter + wrq Pointer to the ioctl argument + ========================================================================== +*/ +VOID RTMPIoctlAddWPAKey( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + NDIS_AP_802_11_KEY *pKey; + ULONG KeyIdx; + MAC_TABLE_ENTRY *pEntry; + UCHAR apidx; + + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = (UCHAR) pObj->ioctl_if; + + + pKey = (PNDIS_AP_802_11_KEY) wrq->u.data.pointer; + + if (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode >= Ndis802_11AuthModeWPA) + { + if ((pKey->KeyLength == 32) || (pKey->KeyLength == 64)) + { + if ((pEntry = MacTableLookup(pAd, pKey->addr)) != NULL) + { + INT k_offset = 0; + +#ifdef DOT11R_FT_SUPPORT + /* The key shall be the second 256 bits of the MSK. */ + if (IS_FT_RSN_STA(pEntry) && pKey->KeyLength == 64) + k_offset = 32; +#endif /* DOT11R_FT_SUPPORT */ + + NdisMoveMemory(pAd->ApCfg.MBSSID[apidx].PMK, pKey->KeyMaterial + k_offset, 32); + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlAddWPAKey-IF(ra%d) : Add PMK=%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x....\n", apidx, + pAd->ApCfg.MBSSID[apidx].PMK[0],pAd->ApCfg.MBSSID[apidx].PMK[1],pAd->ApCfg.MBSSID[apidx].PMK[2],pAd->ApCfg.MBSSID[apidx].PMK[3], + pAd->ApCfg.MBSSID[apidx].PMK[4],pAd->ApCfg.MBSSID[apidx].PMK[5],pAd->ApCfg.MBSSID[apidx].PMK[6],pAd->ApCfg.MBSSID[apidx].PMK[7])); + } + } + } + else /* Old WEP stuff */ + { + UCHAR CipherAlg; + //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].wdev.DefaultKeyId = (UCHAR) KeyIdx; + + /* set key material and key length */ + if (pKey->KeyLength > 16) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlAddWPAKey-IF(ra%d) : Key length too long %d\n", apidx, pKey->KeyLength)); + pKey->KeyLength = 16; + } + pAd->SharedKey[apidx][KeyIdx].KeyLen = (UCHAR) pKey->KeyLength; + NdisMoveMemory(pAd->SharedKey[apidx][KeyIdx].Key, &pKey->KeyMaterial, pKey->KeyLength); + + /* Set Ciper type */ + if (pKey->KeyLength == 5) + pAd->SharedKey[apidx][KeyIdx].CipherAlg = CIPHER_WEP64; + else + pAd->SharedKey[apidx][KeyIdx].CipherAlg = CIPHER_WEP128; + + CipherAlg = pAd->SharedKey[apidx][KeyIdx].CipherAlg; + //Key = pAd->SharedKey[apidx][KeyIdx].Key; + + /* Set Group key material to Asic */ + AsicAddSharedKeyEntry(pAd, apidx, (UINT8)KeyIdx, &pAd->SharedKey[apidx][KeyIdx]); + + /* Get a specific WCID to record this MBSS key attribute */ + GET_GroupKey_WCID(pAd, Wcid, apidx); + + RTMPSetWcidSecurityInfo(pAd, apidx,(UINT8)KeyIdx, + CipherAlg, Wcid, SHAREDKEYTABLE); +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + CmdProcAddRemoveKey(pAd, 0, apidx, KeyIdx, Wcid, SHAREDKEYTABLE, &pAd->SharedKey[apidx][KeyIdx], BROADCAST_ADDR); +#endif + } + else /* For Pairwise key setting */ + { + pEntry = MacTableLookup(pAd, pKey->addr); + if (pEntry) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlAddWPAKey-IF(ra%d) : Set Pair-wise Key\n", apidx)); + + /* set key material and key length */ + pEntry->PairwiseKey.KeyLen = (UCHAR)pKey->KeyLength; + NdisMoveMemory(pEntry->PairwiseKey.Key, &pKey->KeyMaterial, pKey->KeyLength); + + /* set Cipher type */ + if (pKey->KeyLength == 5) + pEntry->PairwiseKey.CipherAlg = CIPHER_WEP64; + else + pEntry->PairwiseKey.CipherAlg = CIPHER_WEP128; + + /* Add Pair-wise key to Asic */ + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->wcid, + &pEntry->PairwiseKey); + + /* update WCID attribute table and IVEIV table for this entry */ + RTMPSetWcidSecurityInfo(pAd, + pEntry->func_tb_idx, + (UINT8)KeyIdx, + pEntry->PairwiseKey.CipherAlg, + pEntry->wcid, + PAIRWISEKEYTABLE); +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + CmdProcAddRemoveKey(pAd, 0, pEntry->func_tb_idx, KeyIdx, pEntry->wcid, PAIRWISEKEYTABLE, &pEntry->PairwiseKey, pEntry->Addr); +#endif + + } + } + } + } +} + + +/* + ========================================================================== + Description: + UI should not call this function, it only used by 802.1x daemon + Arguments: + pAd Pointer to our adapter + wrq Pointer to the ioctl argument + ========================================================================== +*/ +VOID RTMPIoctlAddPMKIDCache( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + UCHAR apidx; + NDIS_AP_802_11_KEY *pKey; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + apidx = (UCHAR) pObj->ioctl_if; + + pKey = (PNDIS_AP_802_11_KEY) wrq->u.data.pointer; + + if (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode >= Ndis802_11AuthModeWPA2) + { + if(pKey->KeyLength == 32) + { + UCHAR digest[80], PMK_key[20], macaddr[MAC_ADDR_LEN]; + + /* Calculate PMKID */ + NdisMoveMemory(&PMK_key[0], "PMK Name", 8); + NdisMoveMemory(&PMK_key[8], pAd->ApCfg.MBSSID[apidx].wdev.bssid, MAC_ADDR_LEN); + NdisMoveMemory(&PMK_key[14], pKey->addr, MAC_ADDR_LEN); + RT_HMAC_SHA1(pKey->KeyMaterial, PMK_LEN, PMK_key, 20, digest, SHA1_DIGEST_SIZE); + + NdisMoveMemory(macaddr, pKey->addr, MAC_ADDR_LEN); + RTMPAddPMKIDCache(pAd, apidx, macaddr, digest, pKey->KeyMaterial +#ifdef CONFIG_OWE_SUPPORT + , LEN_PMK +#endif + ); + + 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].wdev.DefaultKeyId; + + /* need to copy the default shared-key to pairwise key table for this entry in 802.1x mode */ + if (pAd->SharedKey[apidx][KeyIdx].KeyLen == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: Can not get Default shared-key (index-%d)\n", KeyIdx)); + return; + } + else + { + pEntry->PairwiseKey.KeyLen = pAd->SharedKey[apidx][KeyIdx].KeyLen; + NdisMoveMemory(pEntry->PairwiseKey.Key, pAd->SharedKey[apidx][KeyIdx].Key, pEntry->PairwiseKey.KeyLen); + pEntry->PairwiseKey.CipherAlg = pAd->SharedKey[apidx][KeyIdx].CipherAlg; + + /* Add Pair-wise key to Asic */ + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->wcid, + &pEntry->PairwiseKey); + + /* update WCID attribute table and IVEIV table for this entry */ + RTMPSetWcidSecurityInfo(pAd, + pEntry->func_tb_idx, + (UINT8)KeyIdx, + pEntry->PairwiseKey.CipherAlg, + pEntry->wcid, + PAIRWISEKEYTABLE); + } + + } + } + return; +} + +/* + ========================================================================== + Description: + UI should not call this function, it only used by 802.1x daemon + Arguments: + pAd Pointer to our adapter + wrq Pointer to the ioctl argument + ========================================================================== +*/ +VOID RTMPIoctlSetIdleTimeout( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + MAC_TABLE_ENTRY *pEntry; + PDOT1X_IDLE_TIMEOUT pIdleTime; + + if (wrq->u.data.length != sizeof(DOT1X_IDLE_TIMEOUT)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : the length is mis-match\n", __FUNCTION__)); + return; + } + + pIdleTime = (PDOT1X_IDLE_TIMEOUT)wrq->u.data.pointer; + + if ((pEntry = MacTableLookup(pAd, pIdleTime->StaAddr)) == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : the entry is empty\n", __FUNCTION__)); + return; + } + else + { + pEntry->NoDataIdleCount = 0; + // TODO: shiang-usw, remove upper setting becasue we need to migrate to tr_entry! + pAd->MacTab.tr_entry[pEntry->wcid].NoDataIdleCount = 0; + + pEntry->StaIdleTimeout = pIdleTime->idle_timeout; + DBGPRINT(RT_DEBUG_TRACE, ("%s : Update Idle-Timeout(%d) from dot1x daemon\n", + __FUNCTION__, pEntry->StaIdleTimeout)); + } + + return; +} + + +VOID RTMPIoctlQueryStaAid( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + DOT1X_QUERY_STA_AID macBuf; + MAC_TABLE_ENTRY *pEntry = NULL; + + if (wrq->u.data.length != sizeof(DOT1X_QUERY_STA_AID)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : the length is mis-match\n", __FUNCTION__)); + return; + } + else + { + copy_from_user(&macBuf, wrq->u.data.pointer, wrq->u.data.length); + pEntry = MacTableLookup(pAd, macBuf.StaAddr); + + if (pEntry != NULL) + { + wrq->u.data.length = sizeof(DOT1X_QUERY_STA_AID); + macBuf.aid = pEntry->Aid; + if (copy_to_user(wrq->u.data.pointer, &macBuf, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_DOT1X_QUERY_STA_AID(%02x:%02x:%02x:%02x:%02x:%02x, AID=%d)\n", + PRINT_MAC(macBuf.StaAddr), macBuf.aid)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Query::OID_802_DOT1X_QUERY_STA_AID(%02x:%02x:%02x:%02x:%02x:%02x, Not Found)\n", + PRINT_MAC(macBuf.StaAddr))); + } + } +} +#endif /* DOT1X_SUPPORT */ + + +#if defined(DBG) ||(defined(BB_SOC)&&defined(CONFIG_ATE)) + + + +/* + ========================================================================== + Description: + Read / Write BBP +Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 bbp ==> read all BBP + 2.) iwpriv ra0 bbp 1 ==> read BBP where RegID=1 + 3.) iwpriv ra0 bbp 1=10 ==> write BBP R1=0x10 + ========================================================================== +*/ +VOID RTMPAPIoctlBBP( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ +#ifdef RTMP_BBP + RTMP_STRING *this_char, *value; + UCHAR regBBP = 0; + RTMP_STRING *mpool, *msg; /*msg[2048]; */ + RTMP_STRING *arg; /*arg[255]; */ + RTMP_STRING *ptr; + INT bbpId; + LONG bbpValue; + BOOLEAN bIsPrintAllBBP = FALSE, bAllowDump, bCopyMsg; + INT argLen; +#endif /* RTMP_BBP */ + + + +#ifdef RTMP_BBP + os_alloc_mem(NULL, (UCHAR **)&mpool, sizeof(CHAR)*(MAX_BBP_MSG_SIZE+256+12)); + if (mpool == NULL) { + return; + } + + NdisZeroMemory(mpool, MAX_BBP_MSG_SIZE+256+12); + msg = (RTMP_STRING *)((ULONG)(mpool+3) & (ULONG)~0x03); + arg = (RTMP_STRING *)((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 CONFIG_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 /* CONFIG_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 CONFIG_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 /* CONFIG_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 CONFIG_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 /* CONFIG_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)); + } + + os_free_mem(NULL, mpool); + if (!bAllowDump) + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlBBP\n\n")); +#endif /* RTMP_BBP */ +} + + + +//CFG TODO +#if defined (MT7603) || defined (MT7628) +VOID RTMPAPIoctlRF_mt7603(RTMP_ADAPTER *pAd, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + UINT32 regRF = 0; + CHAR *mpool, *msg; + BOOLEAN bIsPrintAllRF = TRUE; + UINT offset = 0; + INT memLen = sizeof(CHAR) * 50000; + + DBGPRINT(RT_DEBUG_TRACE, ("==>RTMPIoctlRF\n")); + + os_alloc_mem(NULL, (UCHAR **)&mpool, memLen); + if (mpool == NULL) { + return; + } + + NdisZeroMemory(mpool, memLen); + msg = (RTMP_STRING *)((ULONG)(mpool+3) & (ULONG)~0x03); + + if (bIsPrintAllRF) + { + RTMPZeroMemory(msg, memLen); + sprintf(msg, "WF0 : \n"); + for (offset = 0; offset < 0x1000; offset+=4) + { + CmdRFRegAccessRead(pAd, (UINT32)0, (UINT32)offset, (UINT32 *)®RF); + sprintf(msg+strlen(msg), "0x%08X = 0x%08X\n", offset, regRF); + } + + sprintf(msg+strlen(msg), "\n"); + sprintf(msg+strlen(msg), "WF1 : \n"); + for (offset = 0; offset < 0x1000; offset+=4) + { + CmdRFRegAccessRead(pAd, (UINT32)1, (UINT32)offset, (UINT32 *)®RF); + sprintf(msg+strlen(msg), "0x%08X = 0x%08X\n", offset, regRF); + } + + RtmpDrvAllRFPrint(NULL, msg, strlen(msg)); + + DBGPRINT(RT_DEBUG_TRACE, ("strlen(msg)=%d\n", (UINT32)strlen(msg))); + /* Copy the information into the user buffer */ +#ifdef LINUX + wrq->u.data.length = strlen("Dump to RFDump.txt"); + if (copy_to_user(wrq->u.data.pointer, "Dump to RFDump.txt", wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } +#endif /* LINUX */ + } + + os_free_mem(NULL, mpool); + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlRF\n\n")); +} +#endif /* MT7603 */ + +#ifdef RLT_RF +VOID RTMPAPIoctlRF_rlt(RTMP_ADAPTER *pAdapter, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + UCHAR regRF = 0; + RTMP_STRING *mpool, *msg; + RTMP_STRING *arg; + INT rfId, maxRFIdx, bank_Id; + BOOLEAN bIsPrintAllRF = TRUE, bFromUI; + INT memLen = sizeof(CHAR) * (2048+256+12); + INT argLen; + + maxRFIdx = pAdapter->chipCap.MaxNumOfRfId; + + DBGPRINT(RT_DEBUG_TRACE, ("==>RTMPIoctlRF (maxRFIdx = %d)\n", maxRFIdx)); + + memLen = 12*(maxRFIdx+1)*MAC_RF_BANK; + os_alloc_mem(NULL, (UCHAR **)&mpool, memLen); + if (mpool == NULL) { + return; + } + + bFromUI = ((wrq->u.data.flags & RTPRIV_IOCTL_FLAG_UI) == RTPRIV_IOCTL_FLAG_UI) ? TRUE : FALSE; + + NdisZeroMemory(mpool, memLen); + msg = (RTMP_STRING *)((ULONG)(mpool+3) & (ULONG)~0x03); + arg = (RTMP_STRING *)((ULONG)(msg+2048+3) & (ULONG)~0x03); + argLen = strlen((char *)(wrq->u.data.pointer)); + if (bIsPrintAllRF) + { + RTMPZeroMemory(msg, memLen); + sprintf(msg, "\n"); + for (bank_Id = 0; bank_Id <= MAC_RF_BANK; bank_Id++) + { + if (IS_MT76x0(pAdapter)) + { + if ((bank_Id <=4) && (bank_Id >=1)) + continue; + } + for (rfId = 0; rfId <= maxRFIdx; rfId++) + { + rlt_rf_read(pAdapter, bank_Id, rfId, ®RF); + sprintf(msg+strlen(msg), "%d %03d = %02X\n", bank_Id, rfId, regRF); + } + } + RtmpDrvAllRFPrint(NULL, msg, strlen(msg)); + /* Copy the information into the user buffer */ + +#ifdef LINUX + wrq->u.data.length = strlen("Dump to RFDump.txt"); + if (copy_to_user(wrq->u.data.pointer, "Dump to RFDump.txt", wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } +#endif /* LINUX */ + } + + os_free_mem(NULL, mpool); + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlRF\n")); +} +#endif /* RLT_RF */ + + +#ifdef RTMP_RF_RW_SUPPORT +/* + ========================================================================== + Description: + Read / Write RF register +Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 rf ==> read all RF registers + 2.) iwpriv ra0 rf 1 ==> read RF where RegID=1 + 3.) iwpriv ra0 rf 1=10 ==> write RF R1=0x10 + ========================================================================== +*/ +VOID RTMPAPIoctlRF( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ +#ifdef RT_RF + RTMP_STRING *this_char; + RTMP_STRING *value; + UCHAR regRF = 0; + RTMP_STRING *mpool, *msg; /*msg[2048]; */ + RTMP_STRING *arg; /*arg[255]; */ + RTMP_STRING *ptr; + INT rfId, maxRFIdx; + LONG rfValue; + BOOLEAN bIsPrintAllRF = FALSE, bFromUI; + INT memLen = sizeof(CHAR) * (2048+256+12); +#endif /* RT_RF */ + +#ifdef RLT_RF + if (IS_MT7601(pAdapter) || IS_MT76x0(pAdapter)) { + RTMPAPIoctlRF_rlt(pAdapter, wrq); + return; + } +#endif /* RLT_RF */ + + +#if defined (MT7603) || defined (MT7628) + if (IS_MT7603(pAdapter) || IS_MT7628(pAdapter)) { + RTMPAPIoctlRF_mt7603(pAdapter, wrq); + return; + } +#endif /* MT7603 */ + +#ifdef RT_RF + maxRFIdx = pAdapter->chipCap.MaxNumOfRfId; + + 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 = (RTMP_STRING *)((ULONG)(mpool+3) & (ULONG)~0x03); + arg = (RTMP_STRING *)((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 CONFIG_ATE + if (ATE_ON(pAdapter)) + { + RT30xxReadRFRegister(pAdapter, rfId, ®RF); + + /* Sync with QA for comparation */ + sprintf(msg+strlen(msg), "%03d = %02X\n", rfId, regRF); + } + else +#endif /* CONFIG_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); */ + { + 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 CONFIG_ATE + if (ATE_ON(pAdapter)) + { + { + RT30xxReadRFRegister(pAdapter, rfId, ®RF); + RT30xxWriteRFRegister(pAdapter, (UCHAR)rfId,(UCHAR) rfValue); + } + + + /* Read it back for showing. */ + RT30xxReadRFRegister(pAdapter, rfId, ®RF); + + /* Sync with QA for comparation */ + sprintf(msg+strlen(msg), "%03d = %02X\n", rfId, regRF); + } + else +#endif /* CONFIG_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); */ + { + 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 CONFIG_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)) + { + RT30xxReadRFRegister(pAdapter, rfId, ®RF); + + /* Sync with QA for comparation */ + sprintf(msg+strlen(msg), "%03d = %02X\n", rfId, regRF); + } + else +#endif /* CONFIG_ATE */ + { + /* according to Andy, Gary, David require. */ + /* the command RF shall read/write RF register directly for dubug. */ + { + RT30xxReadRFRegister(pAdapter, rfId, ®RF); + sprintf(msg+strlen(msg), "R%02d[0x%02X]:%02X ", rfId, rfId*2, regRF); + if (rfId%5 == 4) + sprintf(msg+strlen(msg), "\n"); + } + } + } + /* Copy the information into the user buffer */ + +#ifdef LINUX + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } +#endif /* LINUX */ + } + else + { +#ifdef LINUX + /* Copy the information into the user buffer */ + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } +#endif /* LINUX */ + } + + if (!bFromUI) + { + DBGPRINT(RT_DEBUG_ERROR, ("Dump RF msg[%d]=\n", (UINT32)strlen(msg))); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", msg)); + } + + os_free_mem(NULL, mpool); + if (!bFromUI) + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlRF\n\n")); +#endif /* RT_RF */ + +} +#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) +{ + RTMP_STRING *this_char, *value; + INT j = 0, k = 0; + RTMP_STRING *mpool, *msg;/*msg[1024]; */ + RTMP_STRING *arg, *ptr; + USHORT eepAddr = 0; + UCHAR temp[16]; + RTMP_STRING temp2[16]; + USHORT eepValue; + BOOLEAN bIsPrintAllE2PROM = FALSE; + + os_alloc_mem(NULL, (UCHAR **)&mpool, sizeof(CHAR)*(4096+256+12)); + + if (mpool == NULL) { + return; + } + + msg = (RTMP_STRING *)((ULONG)(mpool+3) & (ULONG)~0x03); + arg = (RTMP_STRING *)((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 */ + + if (strlen(value) > 16) + return; + + 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: + os_free_mem(NULL, mpool); + if (wrq->u.data.flags != RT_OID_802_11_HARDWARE_REGISTER) + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlE2PROM\n")); +} + + +//#define ENHANCED_STAT_DISPLAY // Display PER and PLR statistics + + +/* + ========================================================================== + Description: + Read statistics counter +Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 stat 0 ==> Read statistics counter + ========================================================================== +*/ +VOID RTMPIoctlStatistics(RTMP_ADAPTER *pAd, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + //INT Status; + RTMP_STRING *msg; +#ifdef WSC_AP_SUPPORT + UCHAR idx = 0; +#endif /* WSC_AP_SUPPORT */ + ULONG txCount = 0; +#ifdef MT_MAC + //ULONG txFailCount = 0; +#endif /* MT_MAC */ + UINT32 rxCount = 0; +#ifdef ENHANCED_STAT_DISPLAY + ULONG per, plr; + INT i; +#endif +#ifdef RTMP_EFUSE_SUPPORT + UINT efusefreenum=0; +#endif /* RTMP_EFUSE_SUPPORT */ + +#ifdef BB_SOC + ULONG txPackets=0, rxPackets=0, txBytes=0, rxBytes=0; + UCHAR index=0; +#endif + + os_alloc_mem(pAd, (UCHAR **)&msg, sizeof(CHAR)*(2048)); + if (msg == NULL) { + return; + } + + + memset(msg, 0x00, 1600); + sprintf(msg, "\n"); + +#ifdef CONFIG_ATE + if(ATE_ON(pAd)) + { +#ifdef CONFIG_QA + txCount = pAd->ATECtrl.TxDoneCount; + //rxCount = pAd->ATECtrl.U2M + pAd->ATECtrl.OtherData + pAd->ATECtrl.OtherCount; + rxCount = pAd->ATECtrl.RxTotalCnt; +#else + txCount = pAd->ATECtrl.TxDoneCount; + rxCount = pAd->ATECtrl.RxTotalCnt; +#endif + } + else +#endif /* CONFIG_ATE */ + { + txCount = pAd->WlanCounters.TransmittedFragmentCount.u.LowPart; + rxCount = pAd->WlanCounters.ReceivedFragmentCount.QuadPart; + } + + sprintf(msg+strlen(msg), "Tx success = %ld\n", txCount); +#ifdef ENHANCED_STAT_DISPLAY + if (pAd->chipCap.hif_type == HIF_MT) { + per = txCount==0? 0: 1000*(pAd->WlanCounters.FailedCount.u.LowPart)/(pAd->WlanCounters.FailedCount.u.LowPart+txCount); + sprintf(msg+strlen(msg), "Tx fail count = %ld, PER=%ld.%1ld%%\n", + (ULONG)pAd->WlanCounters.FailedCount.u.LowPart, + per/10, per % 10); + } else { + 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 CONFIG_QA + if(ATE_ON(pAd)) + per = rxCount==0? 0: 1000*(pAd->WlanCounters.FCSErrorCount.u.LowPart)/(pAd->WlanCounters.FCSErrorCount.u.LowPart+rxCount); + else +#endif /* CONFIG_QA */ + per = pAd->WlanCounters.ReceivedFragmentCount.u.LowPart==0? 0: 1000*(pAd->WlanCounters.FCSErrorCount.u.LowPart)/(pAd->WlanCounters.FCSErrorCount.u.LowPart+pAd->WlanCounters.ReceivedFragmentCount.u.LowPart); + sprintf(msg+strlen(msg), "Rx with CRC = %ld, PER=%ld.%1ld%%\n", + (ULONG)pAd->WlanCounters.FCSErrorCount.u.LowPart, per/10, per % 10); + sprintf(msg+strlen(msg), "Rx with PhyErr = %ld\n", + (ULONG)pAd->RalinkCounters.PhyErrCnt); + sprintf(msg+strlen(msg), "Rx with PlcpErr = %ld\n", + (ULONG)pAd->RalinkCounters.PlcpErrCnt); + sprintf(msg+strlen(msg), "Rx drop due to out of resource = %ld\n", (ULONG)pAd->Counters8023.RxNoBuffer); + sprintf(msg+strlen(msg), "Rx duplicate frame = %ld\n", (ULONG)pAd->WlanCounters.FrameDuplicateCount.u.LowPart); + + //sprintf(msg+strlen(msg), "False CCA = %ld\n", (ULONG)pAd->RalinkCounters.FalseCCACnt); + sprintf(msg+strlen(msg), "False CCA (one second) = %ld (CCK %d + OFDM %d)\n" + , (ULONG)pAd->RalinkCounters.OneSecFalseCCACnt,pAd->RalinkCounters.OneSecCCKFalseCCACnt,pAd->RalinkCounters.OneSecOFDMFalseCCACnt); +#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 (CCK %d + OFDM %d)\n" + , (ULONG)pAd->RalinkCounters.OneSecFalseCCACnt,pAd->RalinkCounters.OneSecCCKFalseCCACnt,pAd->RalinkCounters.OneSecOFDMFalseCCACnt); +#endif /* ENHANCED_STAT_DISPLAY */ + +#ifdef CONFIG_QA + if(ATE_ON(pAd)) + { + if (pAd->ATECtrl.RxAntennaSel == 0) + { + sprintf(msg+strlen(msg), "RSSI-A = %ld\n", (LONG)(pAd->ATECtrl.LastRssi0 - pAd->BbpRssiToDbmDelta)); + sprintf(msg+strlen(msg), "RSSI-B (if available) = %ld\n", (LONG)(pAd->ATECtrl.LastRssi1 - pAd->BbpRssiToDbmDelta)); + sprintf(msg+strlen(msg), "RSSI-C (if available) = %ld\n\n", (LONG)(pAd->ATECtrl.LastRssi2 - pAd->BbpRssiToDbmDelta)); + } + else + { + sprintf(msg+strlen(msg), "RSSI = %ld\n", (LONG)(pAd->ATECtrl.LastRssi0 - pAd->BbpRssiToDbmDelta)); + } + sprintf(msg+strlen(msg), "Rx U2M = %ld\n", (ULONG)pAd->ATECtrl.U2M); + sprintf(msg+strlen(msg), "Rx other Data = %ld\n", (ULONG)pAd->ATECtrl.OtherData); + sprintf(msg+strlen(msg), "Rx others(Mgmt+Cntl) = %ld\n", (ULONG)pAd->ATECtrl.OtherCount); + } + else +#endif /* CONFIG_QA */ + { +#ifdef ENHANCED_STAT_DISPLAY + sprintf(msg+strlen(msg), "RSSI = %ld %ld %ld\n", + (LONG)(pAd->ApCfg.RssiSample.LastRssi[0] - pAd->BbpRssiToDbmDelta), + (LONG)(pAd->ApCfg.RssiSample.LastRssi[1] - pAd->BbpRssiToDbmDelta), + (LONG)(pAd->ApCfg.RssiSample.LastRssi[2] - pAd->BbpRssiToDbmDelta)); + + /* Display Last Rx Rate and BF SNR of first Associated entry in MAC table */ + if (pAd->MacTab.Size > 0) + { + static char *phyMode[5] = {"CCK", "OFDM", "MM", "GF", "VHT"}; + + for (i=1; iMacTab.Content[i]); + if ((IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry)) && pEntry->Sst == SST_ASSOC) + { + //sprintf(msg+strlen(msg), "sta mac: %02x:%02x:%02x:%02x:%02x:%02x\n", pEntry->wdev->if_addr[0], pEntry->wdev->if_addr[1], pEntry->wdev->if_addr[2], pEntry->wdev->if_addr[3], pEntry->wdev->if_addr[4], pEntry->wdev->if_addr[5]); + UINT32 lastRxRate = pEntry->LastRxRate; + UINT32 lastTxRate = pEntry->LastTxRate; +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + StatRateToString(pAd, msg, 0, lastTxRate); + StatRateToString(pAd, msg, 1, lastRxRate); + } + else +#endif /* MT_MAC */ + { + sprintf(msg+strlen(msg), + "%s Last TX Rate = MCS%d, %2dM, %cGI, %s%s\n", + IS_ENTRY_CLIENT(pEntry) ? "AP" : "Apcli", + lastTxRate & 0x7F, ((lastTxRate>>7) & 0x1)? 40: 20, + ((lastTxRate>>8) & 0x1)? 'S': 'L', + phyMode[(lastTxRate>>14) & 0x3], + ((lastTxRate>>9) & 0x3)? ", STBC": " "); + sprintf(msg+strlen(msg), + "%s Last RX Rate = MCS%d, %2dM, %cGI, %s%s\n", + IS_ENTRY_CLIENT(pEntry) ? "AP" : "Apcli", + lastRxRate & 0x7F, ((lastRxRate>>7) & 0x1)? 40: 20, + ((lastRxRate>>8) & 0x1)? 'S': 'L', + phyMode[(lastRxRate>>14) & 0x3], + ((lastRxRate>>9) & 0x3)? ", STBC": " "); + } + + break; + } + } + } +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + sprintf(msg+strlen(msg), "TX AGG Range 1 (1) = %ld\n", (LONG)(pAd->WlanCounters.TxAggRange1Count.u.LowPart)); + sprintf(msg+strlen(msg), "TX AGG Range 2 (2~5) = %ld\n", (LONG)(pAd->WlanCounters.TxAggRange2Count.u.LowPart)); + sprintf(msg+strlen(msg), "TX AGG Range 3 (6~15) = %ld\n", (LONG)(pAd->WlanCounters.TxAggRange3Count.u.LowPart)); + sprintf(msg+strlen(msg), "TX AGG Range 4 (>15) = %ld\n", (LONG)(pAd->WlanCounters.TxAggRange4Count.u.LowPart)); + { + ULONG mpduTXCount; +#ifdef ANTI_INTERFERENCE_SUPPORT + UINT32 ampdu_fail_cnt; + UINT32 ampdu_fail_ratio; +#endif /* ANTI_INTERFERENCE_SUPPORT */ + + mpduTXCount = pAd->WlanCounters.AmpduSuccessCount.u.LowPart; + + sprintf(msg+strlen(msg), "AMPDU Tx success = %ld\n", mpduTXCount); + + per = mpduTXCount==0? 0: 1000*(pAd->WlanCounters.AmpduFailCount.u.LowPart)/(pAd->WlanCounters.AmpduFailCount.u.LowPart+mpduTXCount); + sprintf(msg+strlen(msg), "AMPDU Tx fail count = %ld, PER=%ld.%1ld%%\n", + (ULONG)pAd->WlanCounters.AmpduFailCount.u.LowPart, + per/10, per % 10); +#ifdef ANTI_INTERFERENCE_SUPPORT + ampdu_fail_cnt = pAd->RalinkCounters.OneSecTxAMpduCnt - pAd->RalinkCounters.OneSecTxBACnt; + ampdu_fail_ratio = (ampdu_fail_cnt * 100) / pAd->RalinkCounters.OneSecTxAMpduCnt; + sprintf(msg+strlen(msg), "AMPDU Fail Ratio(No BA) = %d%% (%d/%d)\n", + ampdu_fail_ratio, ampdu_fail_cnt, pAd->RalinkCounters.OneSecTxAMpduCnt); +#endif /* ANTI_INTERFERENCE_SUPPORT */ + + } + + if (pAd->CommonCfg.bTXRX_RXV_ON) { + sprintf(msg+strlen(msg), "/* Condition Number should enable mode4 of 0x6020_426c */\n"); + sprintf(msg+strlen(msg), + "--10 packets Condition Number = [%d|%d|%d|%d|%d|%d|%d|%d|%d|%d]\n", + (UINT8)(pAd->rxv2_cyc3[0] & 0xff), + (UINT8)(pAd->rxv2_cyc3[1] & 0xff), + (UINT8)(pAd->rxv2_cyc3[2] & 0xff), + (UINT8)(pAd->rxv2_cyc3[3] & 0xff), + (UINT8)(pAd->rxv2_cyc3[4] & 0xff), + (UINT8)(pAd->rxv2_cyc3[5] & 0xff), + (UINT8)(pAd->rxv2_cyc3[6] & 0xff), + (UINT8)(pAd->rxv2_cyc3[7] & 0xff), + (UINT8)(pAd->rxv2_cyc3[8] & 0xff), + (UINT8)(pAd->rxv2_cyc3[9] & 0xff) + ); + } + } +#endif /* MT_MAC */ + + #else + sprintf(msg+strlen(msg), "RSSI-A = %ld\n", (LONG)(pAd->ApCfg.RssiSample.LastRssi[0] - pAd->BbpRssiToDbmDelta)); + sprintf(msg+strlen(msg), "RSSI-B (if available) = %ld\n", (LONG)(pAd->ApCfg.RssiSample.LastRssi[1] - pAd->BbpRssiToDbmDelta)); + sprintf(msg+strlen(msg), "RSSI-C (if available) = %ld\n\n", (LONG)(pAd->ApCfg.RssiSample.LastRssi[2] - pAd->BbpRssiToDbmDelta)); +#endif /* ENHANCED_STAT_DISPLAY */ + sprintf(msg+strlen(msg), "SNR-A = %ld\n", (LONG)(pAd->ApCfg.RssiSample.AvgSnr[0])); + sprintf(msg+strlen(msg), "SNR-B (if available) = %ld\n", (LONG)(pAd->ApCfg.RssiSample.AvgSnr[1])); + } + +#ifdef WSC_AP_SUPPORT + sprintf(msg+strlen(msg), "WPS Information:\n"); + { +#ifdef BB_SOC + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++){ +// sprintf(msg+strlen(msg), "Enrollee PinCode(ra%d) = %08u\n", idx, pAd->ApCfg.MBSSID[idx].WscControl.WscEnrolleePinCode); +// sprintf(msg+strlen(msg), "WPS Query Status(ra%d) = %d\n", idx, pAd->ApCfg.MBSSID[idx].WscControl.WscStatus); + sprintf(msg+strlen(msg), "WPS Wsc2MinsTimerRunning(ra%d) = %d\n", idx, pAd->ApCfg.MBSSID[idx].WscControl.Wsc2MinsTimerRunning); + } +#else + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) + { + /* display pin code */ + if (pAd->ApCfg.MBSSID[idx].WscControl.WscEnrolleePinCodeLen == 8) + sprintf(msg+strlen(msg), "Enrollee PinCode(ra%d) %08u\n", idx, pAd->ApCfg.MBSSID[idx].WscControl.WscEnrolleePinCode); + else + sprintf(msg+strlen(msg), "Enrollee PinCode(ra%d) %04u\n", idx, pAd->ApCfg.MBSSID[idx].WscControl.WscEnrolleePinCode); + } +#endif + } +#ifdef APCLI_SUPPORT + sprintf(msg+strlen(msg), "\n"); + if (pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCodeLen == 8) + sprintf(msg+strlen(msg), "Enrollee PinCode(ApCli0) %08u\n", pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCode); + else + sprintf(msg+strlen(msg), "Enrollee PinCode(ApCli0) %04u\n", pAd->ApCfg.ApCliTab[0].WscControl.WscEnrolleePinCode); + sprintf(msg+strlen(msg), "Ap Client WPS Profile Count = %d\n", pAd->ApCfg.ApCliTab[0].WscControl.WscProfile.ProfileCnt); + for (idx = 0; idx < pAd->ApCfg.ApCliTab[0].WscControl.WscProfile.ProfileCnt ; idx++) + { + PWSC_CREDENTIAL pCredential = &pAd->ApCfg.ApCliTab[0].WscControl.WscProfile.Profile[idx]; + sprintf(msg+strlen(msg), "Profile[%d]:\n", idx); + sprintf(msg+strlen(msg), "SSID = %s\n", pCredential->SSID.Ssid); + sprintf(msg+strlen(msg), "AuthType = %s\n", WscGetAuthTypeStr(pCredential->AuthType)); + sprintf(msg+strlen(msg), "EncrypType = %s\n", WscGetEncryTypeStr(pCredential->EncrType)); + sprintf(msg+strlen(msg), "KeyIndex = %d\n", pCredential->KeyIndex); + if (pCredential->KeyLength != 0) + { + sprintf(msg+strlen(msg), "Key = %s\n", pCredential->Key); + } + } + sprintf(msg+strlen(msg), "\n"); +#endif /* APCLI_SUPPORT */ +#endif /* WSC_AP_SUPPORT */ + +#if /*TCSUPPORT_COMPILE*/ defined(TCSUPPORT_SCHEDULE) + if(pAd->Flags & fRTMP_ADAPTER_RADIO_OFF) + sprintf(msg+strlen(msg), "Enable Wireless LAN = %s\n", "0"); + else + sprintf(msg+strlen(msg), "Enable Wireless LAN = %s\n", "1"); + sprintf(msg+strlen(msg), "\n"); +#endif /*TCSUPPORT_COMPILE*/ + +/* + * Let "iwpriv ra0 stat" can print out Tx/Rx Packet and Byte count. + * Therefore, we can parse them out in cfg_manager. --Trey */ +#ifdef BB_SOC + for (index = 0; index < pAd->ApCfg.BssidNum; index++){ + rxPackets += (ULONG)pAd->ApCfg.MBSSID[index].RxCount; + txPackets += (ULONG)pAd->ApCfg.MBSSID[index].TxCount; + rxBytes += (ULONG)pAd->ApCfg.MBSSID[index].ReceivedByteCount; + txBytes += (ULONG)pAd->ApCfg.MBSSID[index].TransmittedByteCount; + } + sprintf(msg+strlen(msg), "Packets Received = %lu\n", rxPackets); + sprintf(msg+strlen(msg), "Packets Sent = %lu\n", txPackets); + sprintf(msg+strlen(msg), "Bytes Received = %lu\n", rxBytes); + sprintf(msg+strlen(msg), "Bytes Sent = %lu\n", txBytes); + sprintf(msg+strlen(msg), "\n"); +#endif + +#ifdef RTMP_EFUSE_SUPPORT + if (pAd->bUseEfuse == TRUE) + { + eFuseGetFreeBlockCount(pAd, &efusefreenum); + sprintf(msg+strlen(msg), "efuseFreeNumber = %d\n", efusefreenum); + } +#endif /* RTMP_EFUSE_SUPPORT */ + +#ifdef CONFIG_HOTSPOT + { + PHOTSPOT_CTRL pHSCtrl; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PGAS_CTRL pGASCtrl = &pAd->ApCfg.MBSSID[apidx].GASCtrl; + +#ifdef CONFIG_DOT11V_WNM + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[apidx].WNMCtrl; +#endif + pHSCtrl = &pAd->ApCfg.MBSSID[apidx].HotSpotCtrl; + sprintf(msg+strlen(msg), "\n"); + sprintf(msg+strlen(msg), "hotspot enable = %d\n", pHSCtrl->HotSpotEnable); + sprintf(msg+strlen(msg), "daemon ready = %d\n", pHSCtrl->HSDaemonReady); + sprintf(msg+strlen(msg), "hotspot DGAFDisable = %d\n", pHSCtrl->DGAFDisable); + sprintf(msg+strlen(msg), "hotspot L2Filter = %d\n", pHSCtrl->L2Filter); + sprintf(msg+strlen(msg), "hotspot ICMPv4Deny = %d\n", pHSCtrl->ICMPv4Deny); + sprintf(msg+strlen(msg), "hotspot QosMapEnable = %d\n", pHSCtrl->QosMapEnable); +#ifdef CONFIG_DOT11V_WNM + sprintf(msg+strlen(msg), "proxy arp enable = %d\n", pWNMCtrl->ProxyARPEnable); + sprintf(msg+strlen(msg), "WNMNotify enable = %d\n", pWNMCtrl->WNMNotifyEnable); +#endif + sprintf(msg+strlen(msg), "hotspot OSEN enable = %d\n", pHSCtrl->bASANEnable); + sprintf(msg+strlen(msg), "GAS come back delay = %d\n", pGASCtrl->cb_delay); + sprintf(msg+strlen(msg), "\n"); + } +#endif +#ifdef DOT11U_INTERWORKING + { + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PGAS_CTRL pGASCtrl = &pAd->ApCfg.MBSSID[apidx].GASCtrl; + + sprintf(msg + strlen(msg), "GAS enable = %d\n", pGASCtrl->b11U_enable); + } +#endif/* DOT11U_INTERWORKING */ + /* 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); + +#if defined(TXBF_SUPPORT) && defined(ENHANCED_STAT_DISPLAY) +#ifdef DBG_CTRL_SUPPORT + /* Debug code to display BF statistics */ + if (pAd->CommonCfg.DebugFlags & DBF_SHOW_BF_STATS) + { + for (i=0; iMacTab.Content[i]); + COUNTER_TXBF *pCnt; + ULONG totalNBF, totalEBF, totalIBF, totalTx, totalRetry, totalSuccess; + + if (!IS_ENTRY_CLIENT(pEntry) || pEntry->Sst!=SST_ASSOC) + continue; + + pCnt = &pEntry->TxBFCounters; + + totalNBF = pCnt->TxSuccessCount + pCnt->TxFailCount; + totalEBF = pCnt->ETxSuccessCount + pCnt->ETxFailCount; + totalIBF = pCnt->ITxSuccessCount + pCnt->ITxFailCount; + + totalTx = totalNBF + totalEBF + totalIBF; + totalRetry = pCnt->TxRetryCount + pCnt->ETxRetryCount + pCnt->ITxRetryCount; + totalSuccess = pCnt->TxSuccessCount + pCnt->ETxSuccessCount + pCnt->ITxSuccessCount; + + DBGPRINT(RT_DEBUG_OFF, ("MacTable[%d] Success Retry/PER Fail/PLR\n", i) ); + if (totalTx==0) { + DBGPRINT(RT_DEBUG_OFF, (" Total = 0\n") ); + continue; + } + + if (totalNBF!=0) { + DBGPRINT(RT_DEBUG_OFF, (" NonBF (%3lu%%): %7lu %7lu (%2lu%%) %5lu (%1lu%%)\n", + 100*totalNBF/totalTx, pCnt->TxSuccessCount, + pCnt->TxRetryCount, 100*pCnt->TxRetryCount/(pCnt->TxSuccessCount+pCnt->TxRetryCount), + pCnt->TxFailCount, 100*pCnt->TxFailCount/totalNBF) ); + } + + if (totalEBF!=0) { + DBGPRINT(RT_DEBUG_OFF, (" ETxBF (%3lu%%): %7lu %7lu (%2lu%%) %5lu (%1lu%%)\n", + 100*totalEBF/totalTx, pCnt->ETxSuccessCount, + pCnt->ETxRetryCount, 100*pCnt->ETxRetryCount/(pCnt->ETxSuccessCount+pCnt->ETxRetryCount), + pCnt->ETxFailCount, 100*pCnt->ETxFailCount/totalEBF) ); + } + + if (totalIBF!=0) { + DBGPRINT(RT_DEBUG_OFF, (" ITxBF (%3lu%%): %7lu %7lu (%2lu%%) %5lu (%1lu%%)\n", + 100*totalIBF/totalTx, pCnt->ITxSuccessCount, + pCnt->ITxRetryCount, 100*pCnt->ITxRetryCount/(pCnt->ITxSuccessCount+pCnt->ITxRetryCount), + pCnt->ITxFailCount, 100*pCnt->ITxFailCount/totalIBF) ); + } + + DBGPRINT(RT_DEBUG_OFF, (" Total %7lu %7lu (%2lu%%) %5lu (%1lu%%)\n", + totalSuccess, totalRetry, 100*totalRetry/(totalSuccess + totalRetry), + pCnt->TxFailCount+pCnt->ETxFailCount+pCnt->ITxFailCount, + 100*(pCnt->TxFailCount+pCnt->ETxFailCount+pCnt->ITxFailCount)/totalTx) ); + } + } +#endif /* DBG_CTRL_SUPPORT */ +#endif /* defined(TXBF_SUPPORT) && defined(ENHANCED_STAT_DISPLAY) */ + + DBGPRINT(RT_DEBUG_TRACE, ("<==RTMPIoctlStatistics\n")); +} + + +#ifdef DOT11_N_SUPPORT +/* + ========================================================================== + Description: + Get Block ACK Table + Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 get_ba_table + 3.) UI needs to prepare at least 4096bytes to get the results + ========================================================================== +*/ +VOID RTMPIoctlQueryBaTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + /*char *msg; */ + UCHAR TotalEntry, i, j, index; + QUERYBA_TABLE *BAT; + + BAT = vmalloc(sizeof(QUERYBA_TABLE)); + + if (BAT == NULL) + return; + + RTMPZeroMemory(BAT, sizeof(QUERYBA_TABLE)); + + TotalEntry = pAd->MacTab.Size; + index = 0; + for (i=0; ((i < MAX_LEN_OF_MAC_TABLE) && (TotalEntry > 0)); i++) + { + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i]; + + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC) && (pEntry->TXBAbitmap)) + { + NdisMoveMemory(BAT->BAOriEntry[index].MACAddr, pEntry->Addr, 6); + for (j=0;j<8;j++) + { + if (pEntry->BAOriWcidArray[j] != 0) + BAT->BAOriEntry[index].BufSize[j] = pAd->BATable.BAOriEntry[pEntry->BAOriWcidArray[j]].BAWinSize; + else + BAT->BAOriEntry[index].BufSize[j] = 0; + } + + TotalEntry--; + index++; + BAT->OriNum++; + } + } + + TotalEntry = pAd->MacTab.Size; + index = 0; + for (i=0; ((i < MAX_LEN_OF_MAC_TABLE) && (TotalEntry > 0)); i++) + { + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i]; + + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC) && (pEntry->RXBAbitmap)) + { + NdisMoveMemory(BAT->BARecEntry[index].MACAddr, pEntry->Addr, 6); + BAT->BARecEntry[index].BaBitmap = (UCHAR)pEntry->RXBAbitmap; + for (j = 0; j < 8; j++) + { + if (pEntry->BARecWcidArray[j] != 0) + BAT->BARecEntry[index].BufSize[j] = pAd->BATable.BARecEntry[pEntry->BARecWcidArray[j]].BAWinSize; + else + BAT->BARecEntry[index].BufSize[j] = 0; + } + + TotalEntry--; + index++; + BAT->RecNum++; + } + } + + wrq->u.data.length = sizeof(QUERYBA_TABLE); + + if (copy_to_user(wrq->u.data.pointer, BAT, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + + vfree(BAT); + +} +#endif /* DOT11_N_SUPPORT */ + + +#ifdef APCLI_SUPPORT +INT Set_ApCli_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + UINT Enable; + POS_COOKIE pObj; + UCHAR ifIndex; +#ifdef WH_EZ_SETUP + struct wifi_dev *wdev; +#endif + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + +#ifdef APCLI_OWE_SUPPORT + apcli_reset_owe_parameters(pAd, ifIndex); +#endif + + Enable = simple_strtol(arg, 0, 16); + + pAd->ApCfg.ApCliTab[ifIndex].Enable = (Enable > 0) ? TRUE : FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_Enable_Proc::(enable = %d)\n", ifIndex, pAd->ApCfg.ApCliTab[ifIndex].Enable)); + +#ifdef WH_EZ_SETUP + wdev = &pAd->ApCfg.ApCliTab[ifIndex].wdev; +#endif + + ApCliIfDown(pAd); + +#ifdef WH_EZ_SETUP + if(IS_EZ_SETUP_ENABLED(wdev)){ + if (pAd->ApCfg.ApCliTab[ifIndex].Enable) { + + NdisGetSystemUpTime(&wdev->ez_driver_params.partial_scan_time_stamp); + } + } + +#ifdef EZ_REGROUP_SUPPORT + wdev->ez_driver_params.regrp_mode = NON_REGRP_MODE; +#endif +#endif /* WH_EZ_SETUP */ + + return TRUE; +} + + +INT Set_ApCli_Ssid_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + BOOLEAN apcliEn; + INT success = FALSE; + /*UCHAR keyMaterial[40]; */ + UCHAR PskKey[100]; + APCLI_STRUCT *apcli_entry; + struct wifi_dev *wdev; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + +#ifdef APCLI_OWE_SUPPORT + apcli_reset_owe_parameters(pAd, ifIndex); +#endif + + + if(strlen(arg) <= MAX_LEN_OF_SSID) + { + apcli_entry = &pAd->ApCfg.ApCliTab[ifIndex]; + wdev = &apcli_entry->wdev; + + /* bring apcli interface down first */ + apcliEn = apcli_entry->Enable; + if(apcliEn == TRUE ) + { + apcli_entry->Enable = FALSE; + ApCliIfDown(pAd); + } + + NdisZeroMemory(apcli_entry->CfgSsid, MAX_LEN_OF_SSID); + NdisMoveMemory(apcli_entry->CfgSsid, arg, strlen(arg)); + apcli_entry->CfgSsidLen = (UCHAR)strlen(arg); + success = TRUE; + if (strlen(arg) == 0) + NdisZeroMemory(apcli_entry->CfgApCliBssid, MAC_ADDR_LEN); + + /* Upadte PMK and restart WPAPSK state machine for ApCli link */ + if (((wdev->AuthMode == Ndis802_11AuthModeWPAPSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + || (wdev->AuthMode == Ndis802_11AuthModeWPA3PSK) + || (wdev->AuthMode == Ndis802_11AuthModeOWE) +#endif + ) && + apcli_entry->PSKLen > 0) + { + NdisZeroMemory(PskKey, 100); + NdisMoveMemory(PskKey, apcli_entry->PSK, apcli_entry->PSKLen); + + RT_CfgSetWPAPSKKey(pAd, (RTMP_STRING *)PskKey, + apcli_entry->PSKLen, + (PUCHAR)apcli_entry->CfgSsid, + apcli_entry->CfgSsidLen, + apcli_entry->PMK); + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_Ssid_Proc::(Len=%d,Ssid=%s)\n", + ifIndex, apcli_entry->CfgSsidLen, apcli_entry->CfgSsid)); + + apcli_entry->Enable = apcliEn; + } + else + success = FALSE; + + return success; +} + +INT Set_ApCli_UniCode_Ssid_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + BOOLEAN apcliEn; + INT success = FALSE; + /*UCHAR keyMaterial[40]; */ + UCHAR PskKey[100]; + APCLI_STRUCT *apcli_entry; + struct wifi_dev *wdev; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + +#ifdef APCLI_OWE_SUPPORT + apcli_reset_owe_parameters(pAd, ifIndex); +#endif + + { + apcli_entry = &pAd->ApCfg.ApCliTab[ifIndex]; + wdev = &apcli_entry->wdev; + + /* bring apcli interface down first */ + apcliEn = apcli_entry->Enable; +#ifdef APCLI_CONNECTION_TRIAL + if (pAd->ApCfg.ApCliTab[ifIndex].TrialCh == 0) + { +#endif /* APCLI_CONNECTION_TRIAL */ + if(apcliEn == TRUE ) + { + apcli_entry->Enable = FALSE; + ApCliIfDown(pAd); + } +#ifdef APCLI_CONNECTION_TRIAL + } +#endif /* APCLI_CONNECTION_TRIAL */ + + NdisZeroMemory(apcli_entry->CfgSsid, MAX_LEN_OF_SSID); + apcli_entry->CfgSsidLen = 0; + if(strlen(arg) <= MAX_LEN_OF_SSID) + { + NdisMoveMemory(apcli_entry->CfgSsid, arg, strlen(arg)); + apcli_entry->CfgSsidLen = (UCHAR)strlen(arg); + success = TRUE; + } + + if(arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X')) + { + int ii,jj; + CHAR temp[MAX_LEN_OF_SSID*2+1]; + + NdisZeroMemory(apcli_entry->CfgSsid, MAX_LEN_OF_SSID); + if (strlen(arg) >= (MAX_LEN_OF_SSID*2+1)) { + return FALSE; + } + for(ii=2; ii= '0' && arg[ii] <= '9') + temp[ii-2] = arg[ii] - '0'; + else if(arg[ii] >= 'A' && arg[ii] <= 'F') + temp[ii-2] = arg[ii] - 'A' + 10; + else if(arg[ii] >= 'a' && arg[ii] <= 'f') + temp[ii-2] = arg[ii] - 'a' + 10; + } + + temp[strlen(arg)-2]= '\0'; + DBGPRINT(RT_DEBUG_OFF,("%s=>arg:",__FUNCTION__)); + for(ii=0; iiCfgSsid[jj++] = (UCHAR)(temp[ii]*16+temp[ii+1]); + } + apcli_entry->CfgSsid[jj] = '\0'; + apcli_entry->CfgSsidLen = jj; + + success = TRUE; + + DBGPRINT(RT_DEBUG_OFF,("%s=>SSID:",__FUNCTION__)); + for(ii=0; iiCfgSsid[ii])); + DBGPRINT(RT_DEBUG_OFF,("\n")); + } + + + /* Upadte PMK and restart WPAPSK state machine for ApCli link */ + if (((wdev->AuthMode == Ndis802_11AuthModeWPAPSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) && + apcli_entry->PSKLen > 0) + { + NdisZeroMemory(PskKey, 100); + NdisMoveMemory(PskKey, apcli_entry->PSK, apcli_entry->PSKLen); + + RT_CfgSetWPAPSKKey(pAd, (RTMP_STRING *)PskKey, + apcli_entry->PSKLen, + (PUCHAR)apcli_entry->CfgSsid, + apcli_entry->CfgSsidLen, + apcli_entry->PMK); + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_Ssid_Proc::(Len=%d,Ssid=%s)\n", + ifIndex, apcli_entry->CfgSsidLen, apcli_entry->CfgSsid)); + + apcli_entry->Enable = apcliEn; + } + + return success; +} + +#ifdef WH_EZ_SETUP +INT Set_ApCli_Hide_Ssid_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + INT success = FALSE; + APCLI_STRUCT *apcli_entry; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + ifIndex = pObj->ioctl_if; + + if(strlen(arg) <= MAX_LEN_OF_SSID) + { + apcli_entry = &pAd->ApCfg.ApCliTab[ifIndex]; + + NdisZeroMemory(apcli_entry->CfgHideSsid, MAX_LEN_OF_SSID); + NdisMoveMemory(apcli_entry->CfgHideSsid, arg, strlen(arg)); + apcli_entry->CfgHideSsidLen = (UCHAR)strlen(arg); + success = TRUE; + + MTWF_LOG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("I/F(apcli%d) Set_ApCli_Ssid_Proc::(Len=%d,Ssid=%s)\n", + ifIndex, apcli_entry->CfgHideSsidLen, apcli_entry->CfgHideSsid)); + } + else + success = FALSE; + + return success; +} +#endif + +INT Set_ApCli_Bssid_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + INT i; + RTMP_STRING *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; + +#ifdef APCLI_OWE_SUPPORT + apcli_reset_owe_parameters(pAd, ifIndex); +#endif + + 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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG i; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex; + struct wifi_dev *wdev; + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + wdev = &pAd->ApCfg.ApCliTab[ifIndex].wdev; + + if (rtstrcasecmp(arg, "WEPAUTO") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeAutoSwitch; + else if (rtstrcasecmp(arg, "SHARED") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeShared; + else if (rtstrcasecmp(arg, "WPAPSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((rtstrcasecmp(arg, "WPA2PSK") == TRUE) || (rtstrcasecmp(arg, "WPAPSKWPA2PSK") == TRUE)) + wdev->AuthMode = Ndis802_11AuthModeWPA2PSK; +#ifdef APCLI_SAE_SUPPORT + else if ((strcmp(arg, "WPA3PSK") == 0) || (strcmp(arg, "wpa3psk") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA3PSK; + else if ((strcmp(arg, "WPA2PSKWPA3PSK") == 0) || (strcmp(arg, "wpa2pskwpa3psk") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA3PSK; /* WPA3PSK has transition function in station mode */ +#endif /* APCLI_SAE_SUPPORT */ +#ifdef APCLI_OWE_SUPPORT + else if (rtstrcasecmp(arg, "OWE") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeOWE; +#endif + else + wdev->AuthMode = Ndis802_11AuthModeOpen; + + for (i=0; iMacTab.Content[i])) + { + pAd->MacTab.tr_entry[i].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + } + } + + RTMPMakeRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, (ifIndex + MIN_NET_DEVICE_FOR_APCLI)); + + wdev->DefaultKeyId = 0; + + if(wdev->AuthMode >= Ndis802_11AuthModeWPA) + wdev->DefaultKeyId = 1; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_ApCli_AuthMode_Proc::(AuthMode=%d)\n", ifIndex, wdev->AuthMode)); + return TRUE; +} + + +/* + ========================================================================== + Description: + Set ApCli-IF Encryption Type + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ApCli_EncrypType_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex; + PAPCLI_STRUCT pApCliEntry = NULL; + struct wifi_dev *wdev; + + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + wdev = &pApCliEntry->wdev; + + wdev->WepStatus = Ndis802_11WEPDisabled; + if (rtstrcasecmp(arg, "WEP") == TRUE) + { + if (wdev->AuthMode < Ndis802_11AuthModeWPA) + wdev->WepStatus = Ndis802_11WEPEnabled; + } + else if (rtstrcasecmp(arg, "TKIP") == TRUE) + { + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + wdev->WepStatus = Ndis802_11TKIPEnable; + } + else if ((rtstrcasecmp(arg, "AES") == TRUE) || (rtstrcasecmp(arg, "TKIPAES") == TRUE)) + { + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + wdev->WepStatus = Ndis802_11AESEnable; + } +#ifdef APCLI_OWE_SUPPORT + else if (rtstrcasecmp(arg, "CCMP128") == TRUE) + wdev->WepStatus = Ndis802_11CCMP128Enable; + else if (rtstrcasecmp(arg, "CCMP256") == TRUE) + wdev->WepStatus = Ndis802_11CCMP256Enable; +#endif + + else + { + wdev->WepStatus = Ndis802_11WEPDisabled; + } + + pApCliEntry->PairCipher = wdev->WepStatus; + pApCliEntry->GroupCipher = wdev->WepStatus; + pApCliEntry->bMixCipher = FALSE; + + if (wdev->WepStatus >= Ndis802_11TKIPEnable) + wdev->DefaultKeyId = 1; + + RTMPMakeRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, (ifIndex + MIN_NET_DEVICE_FOR_APCLI)); + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_ApCli_EncrypType_Proc::(EncrypType=%d)\n", ifIndex, wdev->WepStatus)); + + return TRUE; +} + + + +/* + ========================================================================== + Description: + Set Default Key ID + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ApCli_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + ULONG KeyIdx; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + struct wifi_dev *wdev; + + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + wdev = &pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev; + + KeyIdx = simple_strtol(arg, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + wdev->DefaultKeyId = (UCHAR) (KeyIdx - 1 ); + else + return FALSE; /* Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_DefaultKeyID_Proc::(DefaultKeyID(0~3)=%d)\n", pObj->ioctl_if, wdev->DefaultKeyId)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set WPA PSK key for ApCli link + + Arguments: + pAdapter Pointer to our adapter + arg WPA pre-shared key string + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ApCli_WPAPSK_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + UCHAR ifIndex; + POS_COOKIE pObj; + PAPCLI_STRUCT pApCliEntry = NULL; + INT retval; +#ifdef APCLI_SAE_SUPPORT + INT boundary = 65; +#endif + + 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)); + +#ifdef APCLI_SAE_SUPPORT + + if (pApCliEntry->wdev.AuthMode == Ndis802_11AuthModeWPA3PSK) + boundary = LEN_MAX_WPA3PSK_PSD + 1; + else + boundary = LEN_MAX_WPA2PSK_PSD + 1; + + if (strlen(arg) >= boundary) + return FALSE; + +#endif + + 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 RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + struct wifi_dev *wdev; + + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + wdev = &pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev; + + wdev->DesiredTransmitSetting.field.FixedTxMode = RT_CfgSetFixedTxPhyMode(arg); + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_TxMode_Proc = %d\n", + pObj->ioctl_if, wdev->DesiredTransmitSetting.field.FixedTxMode)); + + return TRUE; +} + +INT Set_ApCli_TxMcs_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + struct wifi_dev *wdev; + + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + wdev = &pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev; + + wdev->DesiredTransmitSetting.field.MCS = + RT_CfgSetTxMCSProc(arg, &wdev->bAutoTxRateSwitch); + + if (wdev->DesiredTransmitSetting.field.MCS == MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_TxMcs_Proc = AUTO\n", pObj->ioctl_if)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Set_ApCli_TxMcs_Proc = %d\n", + pObj->ioctl_if, wdev->DesiredTransmitSetting.field.MCS)); + } + + return TRUE; +} + +INT Set_ApCli_Cert_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *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].ApCliCertTest = (Enable > 0) ? TRUE : FALSE; + + if (pAd->ApCfg.ApCliTab[ifIndex].ApCliCertTest) + PingFixRate = 0; + else + PingFixRate = 1; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) %s (enable = %d)\n", ifIndex, __func__, Enable)); + + return TRUE; +} + + +#ifdef MAC_REPEATER_SUPPORT + +INT Set_BaSnReset_Disable_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + UCHAR Enable = simple_strtol(arg, 0, 10); + + pAd->ApCfg.bBaSnResetDis = (Enable ? TRUE : FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("bBaSnResetDis = %d, Repeater Mode (%s)\n", + pAd->ApCfg.bBaSnResetDis, (Enable ? "ON" : "OFF"))); + + return TRUE; +} + + +INT Set_ReptMode_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + UCHAR Enable = simple_strtol(arg, 0, 10); + + pAd->ApCfg.bMACRepeaterEn = (Enable ? TRUE : FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("MACRepeaterEn = %d, Repeater Mode (%s)\n", + pAd->ApCfg.bMACRepeaterEn, (Enable ? "ON" : "OFF"))); + + AsicSetMacAddrExt(pAd, pAd->ApCfg.bMACRepeaterEn); + return TRUE; +} + + +INT Set_ReptOUIMode_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + UCHAR oui_mode = simple_strtol(arg, 0, 10); + + //sofar only 1~3 + if (oui_mode > 1 && oui_mode <=3) + { + pAd->ApCfg.MACRepeaterOuiMode = oui_mode; + DBGPRINT(RT_DEBUG_TRACE, ("MACRepeaterOuiMode = %d\n", pAd->ApCfg.MACRepeaterOuiMode)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("illigal oui_mode = %d\n", oui_mode)); + } + + 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 RTMP_STRING *arg) +{ + POS_COOKIE pObj= (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex; + AP_ADMIN_CONFIG *pApCfg; + long scan_mode = simple_strtol(arg, 0, 10); + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + pApCfg = &pAd->ApCfg; + ifIndex = pObj->ioctl_if; + + if (scan_mode) { + pApCfg->ApCliTab[ifIndex].AutoConnectFlag = TRUE; + Set_ApCli_Enable_Proc(pAd, "0"); + pApCfg->ApCliAutoConnectRunning = TRUE; + } else { + pApCfg->ApCliTab[ifIndex].AutoConnectFlag = FALSE; + pApCfg->ApCliAutoConnectRunning = FALSE; + 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)); + +#ifdef AP_PARTIAL_SCAN_SUPPORT +#define AUTO_SCAN_MODE_FULL 1 +#define AUTO_SCAN_MODE_PARTIAL 2 + + if(scan_mode != AUTO_SCAN_MODE_PARTIAL) + { + pAd->ApCfg.bPartialScanEnable = FALSE; + pAd->ApCfg.bPartialScanning = FALSE; + } + + if (scan_mode == AUTO_SCAN_MODE_PARTIAL) + { + pAd->ApCfg.bPartialScanEnable = TRUE; + pAd->ApCfg.bPartialScanning = TRUE; + } + else +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + + /* + 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 RTMP_STRING *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; + +} + +#ifdef APCLI_SUPPORT +INT Set_ApCli_WscScanMode_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + UCHAR Mode = TRIGGER_FULL_SCAN; + 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; + + Mode = simple_strtol(arg, 0, 10); + if (Mode != TRIGGER_PARTIAL_SCAN) + Mode = TRIGGER_FULL_SCAN; + +#ifdef AP_SCAN_SUPPORT + if ((pWscControl->WscApCliScanMode == TRIGGER_PARTIAL_SCAN) && + (Mode != TRIGGER_PARTIAL_SCAN)) { + pAd->ScanCtrl.PartialScan.pwdev = NULL; + pAd->ScanCtrl.PartialScan.LastScanChannel = 0; + pAd->ScanCtrl.PartialScan.bScanning = FALSE; + } +#endif /* AP_SCAN_SUPPORT */ + pWscControl->WscApCliScanMode = Mode; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("%s:: (WscApCliScanMode=%d)\n", __func__, Mode)); + + return TRUE; +} +#endif /* APCLI_SUPPORT */ + +#endif /* WSC_AP_SUPPORT */ +#ifdef ROAMING_ENHANCE_SUPPORT +INT Set_RoamingEnhance_Enable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT Enable; + + Enable = simple_strtol(arg, 0, 16); + pAd->ApCfg.bRoamingEnhance = (Enable > 0) ? TRUE : FALSE; + +// MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("I/F(apcli%d) %s::(enable = %d)\n", + // ifIndex, __func__, pAd->ApCfg.bRoamingEnhance)); + return TRUE; +} +#endif /* ROAMING_ENHANCE_SUPPORT */ + +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef APCLI_CERT_SUPPORT +/*Add for APCLI PMF 5.3.3.3 option test item. (Only Tx De-auth Req. and make sure the pkt can be Encrypted)*/ +INT ApCliTxDeAuth( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + USHORT Reason = (USHORT)REASON_DEAUTH_STA_LEAVING; + +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + HEADER_802_11 DeauthHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + POS_COOKIE pObj; + UCHAR ifIndex; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + + DBGPRINT(RT_DEBUG_TRACE, ("%s : ifIndex=%u\n", __func__, ifIndex)); + + if ((ifIndex >= MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + && (ifIndex < 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return FALSE; + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + } +#endif /* MAC_REPEATER_SUPPORT */ + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + return FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: DE-AUTH request (Reason=%d)...\n", __func__, Reason)); + + ApCliMgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, ifIndex); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + COPY_MAC_ADDR(DeauthHdr.Addr2, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CurrentAddress); +#endif /* MAC_REPEATER_SUPPORT */ + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DeauthHdr, + 2, &Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + return TRUE; +} +#endif /* APCLI_CERT_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ +#endif /* APCLI_SUPPORT */ + +#ifdef CONFIG_RA_HW_NAT_WIFI_NEW_ARCH +INT set_hnat_register(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 reg_en; + INT idx; + struct wifi_dev *wdev; + + reg_en = simple_strtol(arg, 0, 10); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("Device Instance\n")); + for (idx = 0; idx < WDEV_NUM_MAX; idx++) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("\tWDEV %02d:", idx)); + if (pAd->wdev_list[idx]) { + wdev = pAd->wdev_list[idx]; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("\n\t\tName:%s\n", + RTMP_OS_NETDEV_GET_DEVNAME(wdev->if_dev))); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("\t\tWdev(list) Idx:%d\n", wdev->wdev_idx)); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("\t\t Idx:%d\n", RtmpOsGetNetIfIndex(wdev->if_dev))); +#if !defined(CONFIG_RA_NAT_NONE) +#ifdef CONFIG_RA_HW_NAT_WIFI_NEW_ARCH + if (ppe_dev_unregister_hook != NULL && + ppe_dev_register_hook != NULL) { + if (reg_en) + ppe_dev_register_hook(wdev->if_dev); + else + ppe_dev_unregister_hook(wdev->if_dev); + } +#endif +#endif + } else { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("\n")); + } + + } + return TRUE; +} +#endif /* (CONFIG_RA_HW_NAT_WIFI_NEW_ARCH) */ + +#ifdef WSC_AP_SUPPORT +INT Set_AP_WscConfMode_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + INT ConfModeIdx; + /*INT IsAPConfigured; */ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if, mac_addr[MAC_ADDR_LEN]; + BOOLEAN bFromApCli = FALSE; + PWSC_CTRL pWscControl; + + ConfModeIdx = simple_strtol(arg, 0, 10); + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + return FALSE; + } +#endif /*HOSTAPD_SUPPORT*/ + + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + bFromApCli = TRUE; + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscConfMode_Proc:: This command is from apcli interface now.\n", apidx)); + } + else +#endif /* APCLI_SUPPORT */ + { + bFromApCli = FALSE; + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscConfMode_Proc:: This command is from ra interface now.\n", apidx)); + } + + 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].wdev.if_addr[0], MAC_ADDR_LEN); + } + else +#endif /* APCLI_SUPPORT */ + { + memcpy(mac_addr, &pAd->ApCfg.MBSSID[apidx].wdev.bssid[0], MAC_ADDR_LEN); + } + + DBGPRINT(RT_DEBUG_TRACE, ("IF(%02X:%02X:%02X:%02X:%02X:%02X) Set_WscConfMode_Proc::(WscConfMode(0~7)=%d)\n", + PRINT_MAC(mac_addr), pWscControl->WscConfMode)); + return TRUE; +} + +INT Set_AP_WscConfStatus_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + UCHAR IsAPConfigured = 0; + INT IsSelectedRegistrar; + USHORT WscMode; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + return FALSE; + } +#endif /*HOSTAPD_SUPPORT*/ + + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscConfStatus_Proc:: Ap Client doesn't need this command.\n", apidx)); + return FALSE; + } +#endif /* APCLI_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef WSC_V2_SUPPORT + if ((pAd->ApCfg.MBSSID[apidx].WscControl.WscV2Info.bWpsEnable == FALSE) && + (pAd->ApCfg.MBSSID[apidx].WscControl.WscV2Info.bEnableWpsV2)) + { + pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen = 0; + pAd->ApCfg.MBSSID[apidx].WscIEProbeResp.ValueLen = 0; + return FALSE; + } +#endif /* WSC_V2_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + + IsAPConfigured = (UCHAR)simple_strtol(arg, 0, 10); + IsSelectedRegistrar = pAd->ApCfg.MBSSID[apidx].WscControl.WscSelReg; + if (pAd->ApCfg.MBSSID[apidx].WscControl.WscMode == 1) + WscMode = DEV_PASS_ID_PIN; + else + WscMode = DEV_PASS_ID_PBC; + + if ((IsAPConfigured > 0) && (IsAPConfigured <= 2)) + { + pAd->ApCfg.MBSSID[apidx].WscControl.WscConfStatus = IsAPConfigured; + /* Change SC State of WPS IE in Beacon and ProbeResp */ + WscBuildBeaconIE(pAd, IsAPConfigured, IsSelectedRegistrar, WscMode, 0, apidx, NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, IsSelectedRegistrar, WscMode, 0, apidx, NULL, 0, AP_MODE); + APUpdateBeaconFrame(pAd, apidx); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscConfStatus_Proc:: Set failed!!(WscConfStatus=%s), WscConfStatus is 1 or 2 \n", apidx, arg)); + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscConfStatus_Proc:: WscConfStatus is not changed (%d) \n", apidx, pAd->ApCfg.MBSSID[apidx].WscControl.WscConfStatus)); + return FALSE; /*Invalid argument */ + } + + DBGPRINT(RT_DEBUG_TRACE, ("IF(%02X:%02X:%02X:%02X:%02X:%02X) Set_WscConfStatus_Proc::(WscConfStatus=%d)\n", + PRINT_MAC(pAd->ApCfg.MBSSID[apidx].wdev.bssid), + pAd->ApCfg.MBSSID[apidx].WscControl.WscConfStatus)); + + return TRUE; +} + +INT Set_AP_WscMode_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + INT WscMode; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if, mac_addr[MAC_ADDR_LEN]; + PWSC_CTRL pWscControl; +#ifdef APCLI_SUPPORT + BOOLEAN bFromApCli = FALSE; +#endif /* APCLI_SUPPORT */ + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + return FALSE; + } +#endif /*HOSTAPD_SUPPORT*/ + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + 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 APCLI_SUPPORT + bFromApCli = FALSE; +#endif /* APCLI_SUPPORT */ + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscMode_Proc:: This command is from ra interface now.\n", apidx)); + } + + WscMode = simple_strtol(arg, 0, 10); + + if ((WscMode > 0) && (WscMode <= 2)) + { + pWscControl->WscMode = WscMode; + if (WscMode == WSC_PBC_MODE) + { + WscGetRegDataPIN(pAd, pWscControl->WscPinCode, pWscControl); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscMode_Proc:: Set failed!!(Set_WscMode_Proc=%s), WscConfStatus is 1 or 2 \n", arg)); + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscMode_Proc:: WscMode is not changed (%d) \n", pWscControl->WscMode)); + return FALSE; /*Invalid argument */ + } + +#ifdef APCLI_SUPPORT + if (bFromApCli) + { + memcpy(mac_addr, pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, MAC_ADDR_LEN); + } + else +#endif /* APCLI_SUPPORT */ + { + memcpy(mac_addr, pAd->ApCfg.MBSSID[apidx].wdev.bssid, MAC_ADDR_LEN); + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(%02X:%02X:%02X:%02X:%02X:%02X) Set_WscMode_Proc::(WscMode=%d)\n", + PRINT_MAC(mac_addr), pWscControl->WscMode)); + + return TRUE; +} + +INT Set_WscStatus_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ +#ifdef DBG + 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)); +#endif /* DBG */ + 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 RTMP_STRING *arg) +{ + INT WscMode; +#ifdef DBG + INT wscGetConfMode = 0; +#endif /* DBG */ + 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 == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + return FALSE; + } +#endif /*HOSTAPD_SUPPORT*/ + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + if (apcliEn == 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 */ + { + 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 */ +#ifdef DBG + wscGetConfMode = simple_strtol(arg, 0, 10); +#endif /* DBG */ + 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); + + if (WscMode == DEV_PASS_ID_PIN) + { + NdisMoveMemory(pWscControl->RegData.SelfInfo.MacAddr, + pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, + 6); + + pAd->ApCfg.ApCliTab[apidx].Enable = apcliEn; + NdisMoveMemory(mac_addr, pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, MAC_ADDR_LEN); + } + else + { + pWscControl->WscSsid.SsidLength = 0; + NdisZeroMemory(&pWscControl->WscSsid, sizeof(NDIS_802_11_SSID)); + pWscControl->WscPBCBssCount = 0; + /* WPS - SW PBC */ + WscPushPBCAction(pAd, pWscControl); + } + } + else +#endif /* APCLI_SUPPORT */ + { + WscBuildBeaconIE(pAd, IsAPConfigured, TRUE, WscMode, pWscControl->WscConfigMethods, apidx, NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, TRUE, WscMode, pWscControl->WscConfigMethods, apidx, NULL, 0, AP_MODE); + APUpdateBeaconFrame(pAd, apidx); + NdisMoveMemory(mac_addr, pAd->ApCfg.MBSSID[apidx].wdev.bssid, MAC_ADDR_LEN); + } + +#ifdef APCLI_SUPPORT + if (bFromApCli && (WscMode == DEV_PASS_ID_PBC)) + ; + else +#endif /* APCLI_SUPPORT */ + { + /* 2mins time-out timer */ + RTMPSetTimer(&pWscControl->Wsc2MinsTimer, WSC_TWO_MINS_TIME_OUT); + pWscControl->Wsc2MinsTimerRunning = TRUE; + pWscControl->WscStatus = STATUS_WSC_LINK_UP; +/* WPS_BandSteering Support */ +#ifdef BAND_STEERING +/* WPS: clear any previosly existing WPS WHITELIST in case of AP wps trigger */ + if (!bFromApCli && (pAd->ApCfg.BandSteering)) { + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + PBND_STRG_CLI_TABLE table = Get_BndStrgTable(pAd, wdev->func_idx); + + if (table || table->bEnabled) { + NdisAcquireSpinLock(&table->WpsWhiteListLock); + ClearWpsWhiteList(&table->WpsWhiteList); + NdisReleaseSpinLock(&table->WpsWhiteListLock); + + MTWF_LOG(DBG_CAT_SEC, CATSEC_WPS, DBG_LVL_TRACE, ("%s:channel %u wps whitelist cleared, size : %d\n", + __func__, table->Channel, table->WpsWhiteList.size)); + } + } +#endif + + pWscControl->bWscTrigger = TRUE; + } + pWscControl->bWscAutoTigeer = FALSE; + + if (!bFromApCli) + { + if (WscMode == DEV_PASS_ID_PIN) + { + WscAssignEntryMAC(pAd, pWscControl); + WscSendUPnPConfReqMsg(pAd, pWscControl->EntryIfIdx, + (PUCHAR)pAd->ApCfg.MBSSID[pWscControl->EntryIfIdx].Ssid, + pAd->ApCfg.MBSSID[apidx].wdev.bssid, 3, 0, AP_MODE); + } + else + { + RTMP_SEM_LOCK(&pWscControl->WscPeerListSemLock); + WscClearPeerList(&pWscControl->WscPeerList); + RTMP_SEM_UNLOCK(&pWscControl->WscPeerListSemLock); + } + } + +#ifdef WSC_LED_SUPPORT + WPSLEDStatus = LED_WPS_IN_PROCESS; + RTMPSetLED(pAd, WPSLEDStatus); +#endif /* WSC_LED_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(%02X:%02X:%02X:%02X:%02X:%02X) Set_WscGetConf_Proc trigger WSC state machine, wscGetConfMode=%d\n", + PRINT_MAC(mac_addr), wscGetConfMode)); + + return TRUE; +} + +INT Set_AP_WscPinCode_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + UINT PinCode = 0; + BOOLEAN validatePin; +#ifdef APCLI_SUPPORT + BOOLEAN bFromApCli = FALSE; +#endif /* APCLI_SUPPORT */ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if, mac_addr[MAC_ADDR_LEN]; + PWSC_CTRL pWscControl; +#define IsZero(c) ('0' == (c) ? TRUE:FALSE) + PinCode = simple_strtol(arg, 0, 10); /* When PinCode is 03571361, return value is 3571361. */ + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + return FALSE; + } +#endif /*HOSTAPD_SUPPORT*/ + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + bFromApCli = TRUE; + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscPinCode_Proc:: This command is from apcli interface now.\n", apidx)); + } + else +#endif /* APCLI_SUPPORT */ + { +#ifdef APCLI_SUPPORT + bFromApCli = FALSE; +#endif + 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].wdev.if_addr, MAC_ADDR_LEN); + } + else +#endif /* APCLI_SUPPORT */ + { + memcpy(mac_addr, pAd->ApCfg.MBSSID[apidx].wdev.bssid, MAC_ADDR_LEN); + } + DBGPRINT(RT_DEBUG_TRACE, ("IF(%02X:%02X:%02X:%02X:%02X:%02X) Set_WscPinCode_Proc::(PinCode=%d)\n", + PRINT_MAC(mac_addr), pWscControl->WscPinCode)); + + return TRUE; +} + +INT Set_WscOOB_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + char *pTempSsid = NULL; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + return FALSE; + } +#endif /*HOSTAPD_SUPPORT*/ + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscPinCode_Proc:: Ap Client doesn't need this command.\n", apidx)); + return FALSE; + } +#endif /* APCLI_SUPPORT */ + + Set_WscSetupLock_Proc(pAd, "0"); + Set_AP_WscConfStatus_Proc(pAd, "1"); + Set_AP_AuthMode_Proc(pAd, "WPA2PSK"); + Set_AP_EncrypType_Proc(pAd, "AES"); + pTempSsid = vmalloc(33); + if (pTempSsid) + { + memset(pTempSsid, 0, 33); + snprintf(pTempSsid, 33,"RalinkInitialAP%02X%02X%02X", + pAd->ApCfg.MBSSID[apidx].wdev.bssid[3], + pAd->ApCfg.MBSSID[apidx].wdev.bssid[4], + pAd->ApCfg.MBSSID[apidx].wdev.bssid[5]); + Set_AP_SSID_Proc(pAd, pTempSsid); + vfree(pTempSsid); + } + Set_AP_WPAPSK_Proc(pAd, "RalinkInitialAPxx1234"); + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscOOB_Proc\n", apidx)); + return TRUE; +} + +INT Set_WscStop_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PWSC_CTRL pWscControl; +#ifdef APCLI_SUPPORT + BOOLEAN bFromApCli = FALSE; +#endif + +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + return FALSE; + } +#endif /*HOSTAPD_SUPPORT*/ + + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + bFromApCli = TRUE; + pWscControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscStop_Proc:: This command is from apcli interface now.\n", apidx)); + } + else +#endif /* APCLI_SUPPORT */ + { +#ifdef APCLI_SUPPORT + bFromApCli = FALSE; +#endif + 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; + RTMP_STRING *msg; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + BSS_STRUCT *pMbss; + struct wifi_dev *wdev; + + + pMbss = &pAd->ApCfg.MBSSID[apidx]; + wdev = &pMbss->wdev; +#ifdef HOSTAPD_SUPPORT + if (pMbss->Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + return; + } +#endif /*HOSTAPD_SUPPORT*/ + + + memset(&Profile, 0x00, sizeof(WSC_CONFIGURED_VALUE)); + Profile.WscConfigured = pMbss->WscControl.WscConfStatus; + NdisZeroMemory(Profile.WscSsid, 32 + 1); + NdisMoveMemory(Profile.WscSsid, pMbss->Ssid, pMbss->SsidLen); + Profile.WscSsid[pMbss->SsidLen] = '\0'; + if (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + Profile.WscAuthMode = WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK; + else + Profile.WscAuthMode = WscGetAuthType(wdev->AuthMode); + if (wdev->WepStatus == Ndis802_11TKIPAESMix) + Profile.WscEncrypType = WSC_ENCRTYPE_TKIP |WSC_ENCRTYPE_AES; + else + Profile.WscEncrypType = WscGetEncryType(wdev->WepStatus); + NdisZeroMemory(Profile.WscWPAKey, 64 + 1); + + if (Profile.WscEncrypType == 2) + { + Profile.DefaultKeyIdx = wdev->DefaultKeyId + 1; + { + int i; + for (i=0; iSharedKey[apidx][wdev->DefaultKeyId].KeyLen; i++) + { + snprintf((RTMP_STRING *) Profile.WscWPAKey, sizeof(Profile.WscWPAKey), + "%s%02x", Profile.WscWPAKey, + pAd->SharedKey[apidx][wdev->DefaultKeyId].Key[i]); + } + Profile.WscWPAKey[(pAd->SharedKey[apidx][wdev->DefaultKeyId].KeyLen)*2] = '\0'; + } + } + else if (Profile.WscEncrypType >= 4) + { + Profile.DefaultKeyIdx = 2; + NdisMoveMemory(Profile.WscWPAKey, pMbss->WscControl.WpaPsk, + pMbss->WscControl.WpaPskLen); + Profile.WscWPAKey[pMbss->WscControl.WpaPskLen] = '\0'; + } + else + { + Profile.DefaultKeyIdx = 1; + } + + wrq->u.data.length = sizeof(Profile); + + if (copy_to_user(wrq->u.data.pointer, &Profile, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + + os_alloc_mem(pAd, (UCHAR **)&msg, sizeof(CHAR)*(2048)); + if (msg == NULL) { + return; + } + + memset(msg, 0x00, 2048); + sprintf(msg,"%s","\n"); + + if (Profile.WscEncrypType == 1) + { + sprintf(msg+strlen(msg),"%-12s%-33s%-12s%-12s\n", "Configured", "SSID", "AuthMode", "EncrypType"); + } + else if (Profile.WscEncrypType == 2) + { + sprintf(msg+strlen(msg),"%-12s%-33s%-12s%-12s%-13s%-26s\n", "Configured", "SSID", "AuthMode", "EncrypType", "DefaultKeyID", "Key"); + } + else + { + sprintf(msg+strlen(msg),"%-12s%-33s%-12s%-12s%-64s\n", "Configured", "SSID", "AuthMode", "EncrypType", "Key"); + } + + if (Profile.WscConfigured == 1) + sprintf(msg+strlen(msg),"%-12s", "No"); + else + sprintf(msg+strlen(msg),"%-12s", "Yes"); + sprintf(msg+strlen(msg), "%-33s", Profile.WscSsid); + if (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + sprintf(msg+strlen(msg), "%-12s", "WPAPSKWPA2PSK"); + else + sprintf(msg+strlen(msg), "%-12s", WscGetAuthTypeStr(Profile.WscAuthMode)); + if (wdev->WepStatus == Ndis802_11TKIPAESMix) + 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)); + os_free_mem(NULL, msg); +} + +#ifdef WSC_NFC_SUPPORT +VOID RTMPIoctlNfcStatus( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + RTMP_STRING *msg; + INT Status=0; + UCHAR data = 0; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl; + + os_alloc_mem(NULL, (PUCHAR *)&msg, 128); + + if (msg == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlNfcStatus - msg memory alloc fail.\n")); + return; + } + + memset(msg, 0 ,128 ); + + /* + Action: b��<7:6>: 0x0 �V To NFC, 0x1 �V From NFC + b��<5:0>: 0x0 �V Get, 0x01 - Set + */ + UCHAR action = 0, type = TYPE_NFC_STATUS; /* 5 - NFC Status */ + + NfcCommand(pAd, action, type, 0, NULL); + //wait_for_completion_interruptible_timeout(&pWscCtrl->NfcComplete, 10); /* Use timeout to prevent nfchod not exist */ + DBGPRINT(RT_DEBUG_OFF, ("NfcStatus=%d \n", pWscCtrl->NfcStatus)); + //printk("NfcCmdResult=%d \n", pWscCtrl->NfcCmdResult); + sprintf(msg,"%s","\n"); + sprintf(msg+strlen(msg),"NfcStatus=%d\n", pWscCtrl->NfcStatus); + //sprintf(msg+strlen(msg),"NfcCmdResult=%x\n", pWscCtrl->NfcCmdResult); + + wrq->u.data.length = strlen(msg); + Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlNfcStatus - wrq->u.data.length = %d\n", wrq->u.data.length)); + os_free_mem(NULL, (PUCHAR)msg); + +} +#endif /* WSC_NFC_SUPPORT */ + +#if defined(INF_AR9) || defined(BB_SOC) +#if defined(AR9_MAPI_SUPPORT) || defined(BB_SOC) + +/* + ========================================================================== + Description: + Get WSC Profile + Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 ar9_show get_wsc_profile + 3.) UI needs to prepare at least 4096bytes to get the results + ========================================================================== +*/ +VOID RTMPAR9IoctlWscProfile( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + WSC_CONFIGURED_VALUE Profile; + RTMP_STRING *msg; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + BSS_STRUCT *pMbss; + struct wifi_dev *wdev; + + pMbss = &pAd->ApCfg.MBSSID[apidx]; + wdev = &pMbss->wdev; + + memset(&Profile, 0x00, sizeof(WSC_CONFIGURED_VALUE)); + Profile.WscConfigured = pAd->ApCfg.MBSSID[apidx].WscControl.WscConfStatus; + NdisZeroMemory(Profile.WscSsid, 32 + 1); + NdisMoveMemory(Profile.WscSsid, pAd->ApCfg.MBSSID[apidx].Ssid, + pAd->ApCfg.MBSSID[apidx].SsidLen); + Profile.WscSsid[pAd->ApCfg.MBSSID[apidx].SsidLen] = '\0'; + if (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + Profile.WscAuthMode = WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK; + else + Profile.WscAuthMode = WscGetAuthType(wdev->AuthMode); + if (wdev->WepStatus == Ndis802_11Encryption4Enabled) + Profile.WscEncrypType = WSC_ENCRTYPE_TKIP |WSC_ENCRTYPE_AES; + else + Profile.WscEncrypType = WscGetEncryType(wdev->WepStatus); + NdisZeroMemory(Profile.WscWPAKey, 64 + 1); + + if (Profile.WscEncrypType == 2) + { + Profile.DefaultKeyIdx = wdev->DefaultKeyId + 1; + { + int i; + for (i=0; iSharedKey[apidx][wdev->DefaultKeyId].KeyLen; i++) + { + snprintf((RTMP_STRING *) Profile.WscWPAKey, sizeof(Profile.WscWPAKey), + "%s%02x", Profile.WscWPAKey, + pAd->SharedKey[apidx][wdev->DefaultKeyId].Key[i]); + } + Profile.WscWPAKey[(pAd->SharedKey[apidx][wdev->DefaultKeyId].KeyLen)*2] = '\0'; + } + } + else if (Profile.WscEncrypType >= 4) + { + Profile.DefaultKeyIdx = 2; + NdisMoveMemory(Profile.WscWPAKey, pAd->ApCfg.MBSSID[apidx].WscControl.WpaPsk, + pAd->ApCfg.MBSSID[apidx].WscControl.WpaPskLen); + Profile.WscWPAKey[pAd->ApCfg.MBSSID[apidx].WscControl.WpaPskLen] = '\0'; + } + else + { + Profile.DefaultKeyIdx = 1; + } + + os_alloc_mem(pAd, (UCHAR **)&msg, sizeof(CHAR)*(2048)); + if (msg == NULL) { + return; + } + + memset(msg, 0x00, 2048); + sprintf(msg,"%s","\n"); + + if (Profile.WscEncrypType == 1) + { + sprintf(msg+strlen(msg),"%-12s%-33s%-12s%-12s\n", "Configured", "SSID", "AuthMode", "EncrypType"); + } + else if (Profile.WscEncrypType == 2) + { + sprintf(msg+strlen(msg),"%-12s%-33s%-12s%-12s%-13s%-26s\n", "Configured", "SSID", "AuthMode", "EncrypType", "DefaultKeyID", "Key"); + } + else + { + sprintf(msg+strlen(msg),"%-12s%-33s%-12s%-12s%-64s\n", "Configured", "SSID", "AuthMode", "EncrypType", "Key"); + } + + if (Profile.WscConfigured == 1) + sprintf(msg+strlen(msg),"%-12s", "No"); + else + sprintf(msg+strlen(msg),"%-12s", "Yes"); + sprintf(msg+strlen(msg), "%-33s", Profile.WscSsid); + if (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + sprintf(msg+strlen(msg), "%-12s", "WPAPSKWPA2PSK"); + else + sprintf(msg+strlen(msg), "%-12s", WscGetAuthTypeStr(Profile.WscAuthMode)); + if (wdev->WepStatus == Ndis802_11Encryption4Enabled) + sprintf(msg+strlen(msg), "%-12s", "TKIPAES"); + else + sprintf(msg+strlen(msg), "%-12s", WscGetEncryTypeStr(Profile.WscEncrypType)); + + if (Profile.WscEncrypType == 1) + { + sprintf(msg+strlen(msg), "%s\n", ""); + } + else if (Profile.WscEncrypType == 2) + { + sprintf(msg+strlen(msg), "%-13d",Profile.DefaultKeyIdx); + sprintf(msg+strlen(msg), "%-26s\n",Profile.WscWPAKey); + } + else if (Profile.WscEncrypType >= 4) + { + sprintf(msg+strlen(msg), "%-64s\n",Profile.WscWPAKey); + } + + wrq->u.data.length = strlen(msg); + copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + { + DBGPRINT(RT_DEBUG_TRACE, ("%s", msg)); + } + os_free_mem(NULL, msg); +} + +VOID RTMPIoctlWscPINCode( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + RTMP_STRING *msg; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + UCHAR tempPIN[9]={0}; + + 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((RTMP_STRING *) tempPIN, "%08u", pAd->ApCfg.MBSSID[apidx].WscControl.WscEnrolleePinCode); + else + sprintf((RTMP_STRING *) 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)); + } + + os_free_mem(NULL, msg); +} + +VOID RTMPIoctlWscStatus( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + RTMP_STRING *msg; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + + 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)); + } + + os_free_mem(NULL, msg); +} + +VOID RTMPIoctlGetWscDynInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + char *msg; + BSS_STRUCT *pMbss; + INT apidx,configstate; + + os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(pAd->ApCfg.BssidNum*(14*128))); + if (msg == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + return; + } + memset(msg, 0 ,pAd->ApCfg.BssidNum*(14*128)); + sprintf(msg,"%s","\n"); + + for (apidx=0; apidxApCfg.BssidNum; apidx++) + { + pMbss=&pAd->ApCfg.MBSSID[apidx]; + + if(pMbss->WscControl.WscConfStatus == WSC_SCSTATE_UNCONFIGURED) + configstate = 0; + else + configstate = 1; + + sprintf(msg+strlen(msg),"ra%d\n",apidx); +#ifdef BB_SOC + sprintf(msg+strlen(msg),"DeviceName = %s\n",(pMbss->WscControl.RegData.SelfInfo.DeviceName)); +#endif + sprintf(msg+strlen(msg),"UUID = %s\n",(pMbss->WscControl.Wsc_Uuid_Str)); + sprintf(msg+strlen(msg),"wpsVersion = 0x%x\n",WSC_VERSION); + sprintf(msg+strlen(msg),"setuoLockedState = %d\n",0); + sprintf(msg+strlen(msg),"configstate = %d\n",configstate); + sprintf(msg+strlen(msg),"lastConfigError = %d\n",0); + + } + + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s", msg)); + } + + os_free_mem(NULL, msg); +} + +VOID RTMPIoctlGetWscRegsDynInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + char *msg; + BSS_STRUCT *pMbss; + INT apidx; + + os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(pAd->ApCfg.BssidNum*(14*128))); + if (msg == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + return; + } + memset(msg, 0 ,pAd->ApCfg.BssidNum*(14*128)); + sprintf(msg,"%s","\n"); + + for (apidx=0; apidxApCfg.BssidNum; apidx++) + { + pMbss=&pAd->ApCfg.MBSSID[apidx]; + sprintf(msg+strlen(msg),"ra%d\n",apidx); +#ifdef BB_SOC + sprintf(msg+strlen(msg),"DeviceName = %s\n",(pMbss->WscControl.RegData.SelfInfo.DeviceName)); +#endif + sprintf(msg+strlen(msg),"UUID_R = %s\n",(pMbss->WscControl.RegData.PeerInfo.Uuid)); + } + + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s", msg)); + } + + os_free_mem(NULL, msg); +} +#endif /* defined(AR9_MAPI_SUPPORT) || defined(BB_SOC) */ +#endif /* defined(INF_AR9) || defined(BB_SOC) */ + +BOOLEAN WscCheckEnrolleeNonceFromUpnp( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_STRING *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 RTMP_STRING * pData, + IN USHORT Length) +{ + + USHORT WscType, WscLen; + + { /* Eap-Esp(Messages) */ + /* the first TLV item in EAP Messages must be WSC_IE_VERSION */ + NdisMoveMemory(&WscType, pData, 2); + if (ntohs(WscType) != WSC_ID_VERSION) + goto out; + + /* Not Wsc Start, We have to look for WSC_IE_MSG_TYPE to classify M2 ~ M8, the remain size must large than 4 */ + while (Length > 4) + { + /* arm-cpu has packet alignment issue, it's better to use memcpy to retrieve data */ + NdisMoveMemory(&WscType, pData, 2); + NdisMoveMemory(&WscLen, pData + 2, 2); + WscLen = ntohs(WscLen); + if (ntohs(WscType) == WSC_ID_MSG_TYPE) + { + return(*(pData + 4)); /* Found the message type */ + } + else + { + pData += (WscLen + 4); + Length -= (WscLen + 4); + } + } + } + +out: + return WSC_MSG_UNKNOWN; +} + +VOID RTMPIoctlSetWSCOOB( + IN PRTMP_ADAPTER pAd) +{ + char *pTempSsid = NULL; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF(apcli%d) Set_WscPinCode_Proc:: Ap Client doesn't need this command.\n", apidx)); + return; + } +#endif /* APCLI_SUPPORT */ + + Set_WscSetupLock_Proc(pAd, "0"); + Set_AP_WscConfStatus_Proc(pAd, "1"); + Set_AP_AuthMode_Proc(pAd, "WPAPSK"); + Set_AP_EncrypType_Proc(pAd, "TKIP"); + pTempSsid = vmalloc(33); + if (pTempSsid) + { + memset(pTempSsid, 0, 33); + snprintf(pTempSsid, 33, "RalinkInitialAP%02X%02X%02X", + pAd->ApCfg.MBSSID[apidx].wdev.bssid[3], + pAd->ApCfg.MBSSID[apidx].wdev.bssid[4], + pAd->ApCfg.MBSSID[apidx].wdev.bssid[5]); + Set_AP_SSID_Proc(pAd, pTempSsid); + vfree(pTempSsid); + } + Set_AP_WPAPSK_Proc(pAd, "RalinkInitialAPxx1234"); + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscOOB_Proc\n", apidx)); + return; +} + +/* + ========================================================================== + Description: + Set Wsc Security Mode + 0 : WPA2PSK AES + 1 : WPA2PSK TKIP + 2 : WPAPSK AES + 3 : WPAPSK TKIP + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_AP_WscSecurityMode_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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_WscSetupLock_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *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; + pWscControl->PinAttackCount = 0; + if (pWscControl->WscSetupLockTimerRunning) + { + RTMPCancelTimer(&pWscControl->WscSetupLockTimer, &bCancelled); + } + WscSetupLockTimeout(NULL, pWscControl, NULL, NULL); + } + else + { + pWscControl->bSetupLock = TRUE; + WscBuildBeaconIE(pAd, + pWscControl->WscConfStatus, + FALSE, + 0, + 0, + pObj->ioctl_if, + NULL, + 0, + AP_MODE); + WscBuildProbeRespIE(pAd, + WSC_MSGTYPE_AP_WLAN_MGR, + pWscControl->WscConfStatus, + FALSE, + 0, + 0, + pObj->ioctl_if, + NULL, + 0, + AP_MODE); + APUpdateBeaconFrame(pAd, pObj->ioctl_if); + } + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscSetupLock_Proc::(bSetupLock=%d)\n", + pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.bSetupLock)); + return TRUE; +} + +#ifdef WSC_V2_SUPPORT +INT Set_WscFragment_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *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 RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + USHORT WscFragSize = (USHORT)simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscFragmentSize_Proc::(WscFragSize=%d)\n", WscFragSize)); + if ((WscFragSize >=128) && (WscFragSize <=300)) + pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl.WscFragSize = WscFragSize; + return TRUE; +} + +INT Set_WscV2Support_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR bEnable = (UCHAR)simple_strtol(arg, 0, 10); + PWSC_CTRL pWscControl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl; + + if (bEnable == 0) + pWscControl->WscV2Info.bEnableWpsV2 = FALSE; + else + pWscControl->WscV2Info.bEnableWpsV2 = TRUE; + + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* + WPS V2 doesn't support WEP and WPA/WPAPSK-TKIP. + */ + if ((pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.WepStatus == Ndis802_11WEPEnabled) || + (pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.WepStatus == Ndis802_11TKIPEnable) || + (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 RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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 */ + +INT Set_WscMaxPinAttack_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *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 RTMP_STRING *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; +} + +INT Set_WscAutoTriggerDisable_Proc( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR bEnable = (UCHAR)simple_strtol(arg, 0, 10); + PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl; + + if (bEnable == 0) + pWscCtrl->bWscAutoTriggerDisable = FALSE; + else + pWscCtrl->bWscAutoTriggerDisable = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscAutoTriggerDisable_Proc::(bWscAutoTriggerDisable=%d)\n", + pWscCtrl->bWscAutoTriggerDisable)); + return TRUE; +} + +#endif /* WSC_AP_SUPPORT */ + + + +#ifdef IAPP_SUPPORT +INT Set_IappPID_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *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 RTMP_STRING *arg) +{ + UCHAR macAddr[MAC_ADDR_LEN]; + RTMP_STRING *value; + INT i; + MAC_TABLE_ENTRY *pEntry = NULL; + + if(strlen(arg) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid */ + + AtoH(value, (UCHAR *)&macAddr[i++], 1); + } + + pEntry = MacTableLookup(pAd, macAddr); + if (pEntry) + { + MlmeDeAuthAction(pAd, pEntry, REASON_DISASSOC_STA_LEAVING, FALSE); +/* MacTableDeleteEntry(pAd, pEntry->wcid, Addr); */ + } + + return TRUE; +} + +INT Set_DisConnectAllSta_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ +#ifdef DOT11W_PMF_SUPPORT + CHAR value = simple_strtol(arg, 0, 10); + + if (value == 2) + { + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + INT i; + + DBGPRINT(RT_DEBUG_WARN, ("[PMF]%s:: apidx=%d\n", __FUNCTION__, pObj->ioctl_if)); + APMlmeKickOutAllSta(pAd, pObj->ioctl_if, REASON_DEAUTH_STA_LEAVING); + for (i=1; iMacTab.Content[i]; + if (IS_ENTRY_CLIENT(pEntry)) { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: MacTableDeleteEntry %x:%x:%x:%x:%x:%x\n", + __FUNCTION__, PRINT_MAC(pEntry->Addr))); + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + } + } + } else +#endif /* DOT11W_PMF_SUPPORT */ + { + MacTableReset(pAd, 1); + } + + 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 RTMP_STRING *arg) +{ + ULONG ieee8021x; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + struct wifi_dev *wdev; + + ieee8021x = simple_strtol(arg, 0, 10); + + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + if (ieee8021x == 1) + wdev->IEEE8021X = TRUE; + else if (ieee8021x == 0) + wdev->IEEE8021X = FALSE; + else + return FALSE; /*Invalid argument */ + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_IEEE8021X_Proc::(IEEE8021X=%d)\n", pObj->ioctl_if, wdev->IEEE8021X)); + + return TRUE; +} + +/* + ========================================================================== + Description: + Set pre-authentication enable or disable when WPA/WPA2 turn on + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_PreAuth_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *arg) +{ + INT i; + RTMP_STRING *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 RTMP_STRING *arg) +{ + INT i; + RTMP_STRING *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 RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + RTMP_STRING *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 RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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].wdev.UapsdInfo.bAPSDCapable = TRUE; + else + pAd->ApCfg.MBSSID[IdMbss].wdev.UapsdInfo.bAPSDCapable = FALSE; + + return TRUE; +} /* End of Set_UAPSD_Proc */ +#endif /* UAPSD_SUPPORT */ + + + +#ifdef MCAST_RATE_SPECIFIC +INT Set_McastPhyMode( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT ObssScanValue; + UINT Idx; + RTMP_STRING *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 RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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 RTMP_STRING *arg) +{ + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + + if ((strcmp(arg, "WEPAUTO") == 0) || (strcmp(arg, "wepauto") == 0)) + wdev->AuthMode = Ndis802_11AuthModeAutoSwitch; + else if ((strcmp(arg, "OPEN") == 0) || (strcmp(arg, "open") == 0)) + wdev->AuthMode = Ndis802_11AuthModeOpen; + else if ((strcmp(arg, "SHARED") == 0) || (strcmp(arg, "shared") == 0)) + wdev->AuthMode = Ndis802_11AuthModeShared; + else if ((strcmp(arg, "WPAPSK") == 0) || (strcmp(arg, "wpapsk") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((strcmp(arg, "WPA2PSK") == 0) || (strcmp(arg, "wpa2psk") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA2PSK; + else if ((strcmp(arg, "WPAPSKWPA2PSK") == 0) || (strcmp(arg, "wpapskwpa2psk") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA1PSKWPA2PSK; +#ifdef DOT1X_SUPPORT + else if ((strcmp(arg, "WPA") == 0) || (strcmp(arg, "wpa") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA; + else if ((strcmp(arg, "WPA2") == 0) || (strcmp(arg, "wpa2") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA2; + else if ((strcmp(arg, "WPA1WPA2") == 0) || (strcmp(arg, "wpa1wpa2") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA1WPA2; +#endif /* DOT1X_SUPPORT */ +#ifdef DOT11_SAE_SUPPORT + else if ((strcmp(arg, "WPA3PSK") == 0) || (strcmp(arg, "wpa3psk") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA3PSK; + else if ((strcmp(arg, "WPA2PSKWPA3PSK") == 0) || (strcmp(arg, "wpa2pskwpa3psk") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA2PSKWPA3PSK; +#endif /* DOT11_SAE_SUPPORT */ +#ifdef CONFIG_OWE_SUPPORT + else if (rtstrcasecmp(arg, "OWE") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeOWE; +#endif +#ifdef WAPI_SUPPORT + else if ((strcmp(arg, "WAICERT") == 0) || (strcmp(arg, "waicert") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWAICERT; + else if ((strcmp(arg, "WAIPSK") == 0) || (strcmp(arg, "waipsk") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWAIPSK; +#endif /* WAPI_SUPPORT */ + else + wdev->AuthMode = Ndis802_11AuthModeOpen; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d)::AuthMode=%d\n", apidx, wdev->AuthMode)); + + return TRUE; +} + +INT ApCfg_Set_MaxStaNum_Proc( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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 +#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(RTMP_ADAPTER *pAd, RTMP_STRING *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 +#ifdef DBG +/* +======================================================================== +Routine Description: + Show MBSS information. + +Arguments: + pAd - WLAN control block pointer + Arg - Input arguments + +Return Value: + None + +Note: +======================================================================== +*/ +INT Show_MbssInfo_Display_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 IdBss; + UCHAR PhyMode; + CHAR *mod_str = NULL; + + DBGPRINT(RT_DEBUG_ERROR, ("\n\tBSS Idx\t\tPhy Mode\n")); + + for(IdBss=0; IdBss<=pAd->ApCfg.BssidNum; IdBss++) + { + if (IdBss == 0) + { + PhyMode = pAd->CommonCfg.PhyMode; + DBGPRINT(RT_DEBUG_ERROR, ("\tMAX\t\t")); + } + else + { + PhyMode = pAd->ApCfg.MBSSID[IdBss-1].wdev.PhyMode; + DBGPRINT(RT_DEBUG_ERROR, ("\t%d\t\t", IdBss-1)); + } /* End of if */ + + switch(PhyMode) + { + case (WMODE_B | WMODE_G): + mod_str = "BG Mixed"; + break; + + case (WMODE_B): + mod_str = "B Only"; + break; + + case (WMODE_A): + mod_str = "A Only"; + break; + + case (WMODE_A | WMODE_B | WMODE_G): + mod_str = "ABG Mixed ==> BG Mixed"; + break; + + case (WMODE_G): + mod_str = "G Only"; + break; + +#ifdef DOT11_N_SUPPORT + case (WMODE_A | WMODE_B | WMODE_G | WMODE_AN | WMODE_GN): + mod_str = "ABGN Mixed ==> BGN Mixed"; + break; + + case (WMODE_GN): + mod_str = "2.4G N Only"; + break; + + case (WMODE_G | WMODE_GN): + mod_str = "GN Mixed"; + break; + + case (WMODE_A | WMODE_AN): + mod_str = "AN Mixed"; + break; + + case (WMODE_B | WMODE_G | WMODE_GN): + mod_str = "BGN Mixed"; + break; + + case (WMODE_A | WMODE_G | WMODE_GN | WMODE_AN): + mod_str = "AGN Mixed"; + break; + + case (WMODE_AN): + mod_str = "5G N Only"; + break; +#endif /* DOT11_N_SUPPORT */ + } + } + + if (mod_str) + DBGPRINT(RT_DEBUG_ERROR, ("%s\n", mod_str)); + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + + return TRUE; +} /* End of Show_MbssInfo_Display_Proc */ +#endif /* DBG */ +#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 */ + +#ifdef MT_MAC +/* Only for TimReq frame generating */ +//TODO: Tim service establish. +INT Set_AP_TimEnable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR interval; + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UCHAR APIndex = pObj->ioctl_if; + BSS_STRUCT *pMbss; + UINT32 Value = 0; + + interval = simple_strtol(arg, 0, 10); + + if ((interval < 0) || (interval > 255)) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: interval is incorrect!!\n", __func__)); + return FALSE; + } + + pMbss = &pAd->ApCfg.MBSSID[APIndex]; + + ASSERT(pMbss); + if (pMbss) + wdev_tim_buf_init(pAd, &pMbss->tim_buf); + + if (interval > 0) //valid interval --> enable + { + RTMP_IO_WRITE32(pAd, LPON_PTTISR, 0x50);//set PreTTTT interval. + + RTMP_IO_READ32(pAd, LPON_TT0TPCR, &Value); + Value = 0; + //Carter, test 10ms after TBTT//Carter, I make TTTT always before than TBTT 10ms. + Value &= ~TTTTn_OFFSET_OF_TBTTn_MASK; + Value |= TTTTn_OFFSET_OF_TBTTn(0x2800); + Value |= TTTTn_CAL_EN; + RTMP_IO_WRITE32(pAd, LPON_TT0TPCR, Value);//enable TTTT0 calculation. + + RTMP_IO_READ32(pAd, LPON_TT4TPCR, &Value); + Value = 0; + Value &= ~TIM_PERIODn_MASK; + Value |= TIM_PERIODn(interval * pAd->CommonCfg.BeaconPeriod); + RTMP_IO_WRITE32(pAd, LPON_TT4TPCR, Value);//enable TTTT0 tim interval. + + RTMP_IO_READ32(pAd, LPON_MPTCR4, &Value); + Value = 0; + Value |= TTTT0_PERIODTIMER_EN; + Value |= TTTT0_TIMEUP_EN; + Value |= PRETTTT0TIMEUP_EN; + Value |= PRETTTT0_TRIG_EN; + Value |= PRETTTT0INT_EN; + RTMP_IO_WRITE32(pAd, LPON_MPTCR4, Value); + + //enable dual_btim_enable + RTMP_IO_READ32(pAd, AGG_ARCR, &Value); + Value = Value | (1 << 31); + RTMP_IO_WRITE32(pAd, AGG_ARCR, Value); + + RTMP_IO_WRITE32(pAd, 0x21280, 0x4f);//setting rate OFDM 9M + + Value = 0x00000000; + + if (APIndex == 0) + Value |= 0x1; + else if ((APIndex >= 1) && (APIndex <= 15)) + Value |= (0x1 << (APIndex + 15)); + + RTMP_IO_WRITE32(pAd, ARB_BTIMCR0, Value);//enable BTIM_EN bit in ARB_BTIMCR0 + RTMP_IO_WRITE32(pAd, ARB_BTIMCR1, Value);//enable 2 TIM broadcast + + RTMP_IO_WRITE32(pAd, HWIER4, 0x80008000);//enable TTTT0/PRETTTT0 interrupt. + } + else //interval 0 --> disable + { + if (APIndex == 0) + Value = Value & 0x0; + else if ((APIndex >= 1) && (APIndex <= 15)) + Value = Value & (0x0 << (APIndex + 15)); + + RTMP_IO_WRITE32(pAd, ARB_BTIMCR0, Value);//disable BTIM_EN bit in ARB_BTIMCR0 + } + + return TRUE; +} + +#ifdef DBG +INT Set_AP_DumpTime_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + int apidx = 0, i = 0; + BSS_STRUCT *pMbss; + + printk("\n\t%-10s\t%-10s\n", "PreTBTTTime", "TBTTTime"); + printk("Idx[%d]:%-10lu\t%-10lu\n", i, pAd->HandlePreInterruptTime, pAd->HandleInterruptTime); + + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) { + pMbss = &pAd->ApCfg.MBSSID[apidx]; + + if(!BeaconTransmitRequired(pAd, apidx, pMbss)) + continue; + + printk("\n%s:%d\tBcn_State:%d\t%-10s: %d\n", "Apidx", apidx, pMbss->bcn_buf.bcn_state, "recover", pMbss->bcn_recovery_num); + printk("\t%-10s\t%-10s\t%-10s\t%-10s\n", "WriteBcnRing", "BcnDmaDone", "TXS_TSF", "TXS_SN"); + for (i = 0; i < MAX_TIME_RECORD; i++) { + printk("Idx[%d]:\t%-10lu\t%-10lu\t%-10lu\t%-10lu\n", i, pMbss->WriteBcnDoneTime[i], pMbss->BcnDmaDoneTime[i], pMbss->TXS_TSF[i], pMbss->TXS_SN[i]); + } + } + + return TRUE; +} + +INT Set_BcnStateCtrl_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + UCHAR bcn_state; + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UCHAR apIndex = pObj->ioctl_if; + BSS_STRUCT *pMbss = NULL; + + bcn_state = simple_strtol(arg, 0, 10); + + if (pAd->chipCap.hif_type != HIF_MT) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: chipCap is not HIF_MT\n", __func__)); + return FALSE; + } + + if ((bcn_state < BCN_TX_IDLE) || (bcn_state > BCN_TX_STOP)) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: bcn_state is incorrect!!\n", __func__)); + return FALSE; + } + + pMbss = &pAd->ApCfg.MBSSID[apIndex]; + + ASSERT(pMbss); + if (pMbss == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pMbss == NULL!!\n", __func__)); + return FALSE; + } + + if (pMbss->bcn_buf.bcn_state != BCN_TX_IDLE) { + printk("MBSSID[%d], bcn_buf.bcn_state = %d, will change to %d\n", apIndex, pMbss->bcn_buf.bcn_state, bcn_state); + RTMP_SEM_LOCK(&pAd->BcnRingLock); + pMbss->bcn_buf.bcn_state = bcn_state; + RTMP_SEM_UNLOCK(&pAd->BcnRingLock); + } + + return TRUE; +} +#endif + +INT setApTmrEnableProc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + UCHAR enable; + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UCHAR apIndex = pObj->ioctl_if; + BSS_STRUCT *pMbss = NULL; + UINT32 value = 0; + + enable = simple_strtol(arg, 0, 10); + + if (pAd->chipCap.hif_type != HIF_MT) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: chipCap is not HIF_MT\n", __func__)); + return FALSE; + } + + if ((enable < 0) || (enable > 2)) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: enable is incorrect!!\n", __func__)); + return FALSE; + } + + pMbss = &pAd->ApCfg.MBSSID[apIndex]; + + ASSERT(pMbss); + if (pMbss == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pMbss == NULL!!\n", __func__)); + return FALSE; + } + + switch (enable) + { + case 1://initialiter + { + DBGPRINT(RT_DEBUG_OFF, ("%s: enable TMR report, as Initialiter\n", __func__)); + RTMP_IO_READ32(pAd, RMAC_TMR_PA, &value); + value = value | BIT31; + value = value & ~BIT30; + value = value | 0x34;//Action frame register + RTMP_IO_WRITE32(pAd, RMAC_TMR_PA, value); + pAd->chipCap.TmrEnable = 1; + } + break; + case 2://responder + { + DBGPRINT(RT_DEBUG_OFF, ("%s: enable TMR report, as Responser\n", __func__)); + RTMP_IO_READ32(pAd, RMAC_TMR_PA, &value); + value = value | BIT31; + value = value | BIT30; + value = value | 0x34;//Action frame register + RTMP_IO_WRITE32(pAd, RMAC_TMR_PA, value); + pAd->chipCap.TmrEnable = 2; + } + break; + + case 0://disable + default: + { + DBGPRINT(RT_DEBUG_OFF, ("%s: disable TMR report\n", __func__)); + RTMP_IO_READ32(pAd, RMAC_TMR_PA, &value); + value = value & ~BIT31; + RTMP_IO_WRITE32(pAd, RMAC_TMR_PA, value); + pAd->chipCap.TmrEnable = FALSE; + } + } + return TRUE; +} +#endif /* MT_MAC */ + +#ifdef NEIGHBORING_AP_STAT +INT ReportScanResult(IN void *pAdSrc, IN PRTMP_IOCTL_INPUT_STRUCT wrq) +{ + int bssIdx = 0; + UCHAR idx = 0, b_idx = 0, s_idx = 0; + BSS_ENTRY *pBss = NULL; + SCAN_RPT_ITEM *item = NULL; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + + if (access_ok(VERIFY_WRITE, wrq->u.data.pointer, sizeof(CUSTOM_SCAN_RESULT)) != TRUE) { + return RTMP_IO_EFAULT; + } + + if (sizeof(CUSTOM_SCAN_RESULT) <= wrq->u.data.length) { + /* reset scan entries */ + if (pAd->ScanTab.ScanResult.cnt > 0) { + pAd->ScanTab.ScanResult.cnt = 0; + RTMPZeroMemory(pAd->ScanTab.ScanResult.items, MAX_COUNT_OF_BSS_ENTRIES * sizeof(SCAN_RPT_ITEM)); + } + + for (bssIdx = 0; bssIdx < pAd->ScanTab.BssNr; bssIdx++) { + pBss = &pAd->ScanTab.BssEntry[bssIdx]; + if (bssIdx < MAX_COUNT_OF_BSS_ENTRIES) { + item = &pAd->ScanTab.ScanResult.items[bssIdx]; + NdisMoveMemory(item->ssid, pBss->Ssid, pBss->SsidLen); + NdisMoveMemory(item->macAddr, pBss->Bssid, MAC_ADDR_LEN); + item->noise = pBss->Rssi - pBss->Snr0; + item->beaconPeriod = pBss->BeaconPeriod; + item->dtimPeriod = pBss->DtimPeriod; + item->channel = pBss->Channel; + + b_idx = 0, s_idx = 0; + for (idx = 0; idx < pBss->SupRateLen; idx++) { + if (pBss->SupRate[idx] & 0x80) + item->basicRate[b_idx++] = pBss->SupRate[idx] & 0x7F; + else + item->suppoRate[s_idx++] = pBss->SupRate[idx]; + } + pAd->ScanTab.ScanResult.cnt++; + } + } + + wrq->u.data.length = (__u16)sizeof(CUSTOM_SCAN_RESULT); + if (copy_to_user(wrq->u.data.pointer, &pAd->ScanTab.ScanResult, sizeof(CUSTOM_SCAN_RESULT))) { + return RTMP_IO_EFAULT; + } + return NDIS_STATUS_SUCCESS; + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s: user space buffer is not enough\n", __func__)); + return RTMP_IO_E2BIG; +} +#endif + + +/* +======================================================================== +Routine Description: + Driver Ioctl for AP. + +Arguments: + pAdSrc - WLAN control block pointer + wrq - the IOCTL parameters + cmd - the command ID + subcmd - the sub-command ID + pData - the IOCTL private data pointer + Data - the IOCTL private data + +Return Value: + NDIS_STATUS_SUCCESS - IOCTL OK + Otherwise - IOCTL fail + +Note: +======================================================================== +*/ +INT RTMP_AP_IoctlHandle( + IN VOID *pAdSrc, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + INT Status = NDIS_STATUS_SUCCESS; + + + switch(cmd) + { + case CMD_RTPRIV_IOCTL_SET: + Status = RTMPAPPrivIoctlSet(pAd, wrq); + break; + + case CMD_RT_PRIV_IOCTL: + if (subcmd & OID_GET_SET_TOGGLE) + Status = RTMPAPSetInformation(pAd, wrq, (INT)subcmd); + else + { +#ifdef LLTD_SUPPORT + if (subcmd == RT_OID_GET_PHY_MODE) + { + if(pData != NULL) + { + UINT modetmp = 0; + DBGPRINT(RT_DEBUG_TRACE, ("Query::Get phy mode (%02X) \n", pAd->CommonCfg.PhyMode)); + modetmp = (UINT)wmode_2_cfgmode(pAd->CommonCfg.PhyMode); + wrq->u.data.length = 1; + /**(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 */ + +#ifdef WH_EZ_SETUP + case CMD_RTPRIV_IOCTL_GET_EZ_SCAN_TABLE: + RTMPIoctlGetEzScanTable(pAd,wrq); + break; +#endif /* WH_EZ_SETUP */ + case CMD_RTPRIV_IOCTL_STATISTICS: + RTMPIoctlStatistics(pAd, wrq); + break; + +#ifdef WSC_AP_SUPPORT + case CMD_RTPRIV_IOCTL_WSC_PROFILE: + RTMPIoctlWscProfile(pAd, wrq); + break; +#ifdef WSC_NFC_SUPPORT + case CMD_RTPRIV_IOCTL_NFC_STATUS: + RTMPIoctlNfcStatus(pAd, wrq); + break; +#endif /* WSC_NFC_SUPPORT */ +#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: + RTMPIoctlMAC(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: + RTMPIoctlGetMacTableStaInfo(pAd, wrq); + break; + + case CMD_RTPRIV_IOCTL_GET_DRIVER_INFO: + RTMPIoctlGetDriverInfo(pAd, wrq); + break; + + case CMD_RTPRIV_IOCTL_AP_SIOCGIFHWADDR: + if (pObj->ioctl_if < MAX_MBSSID_NUM(pAd)) + NdisCopyMemory((RTMP_STRING *) wrq->u.name, (RTMP_STRING *) pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.bssid, 6); + break; + + case CMD_RTPRIV_IOCTL_AP_SIOCGIWESSID: + { + RT_CMD_AP_IOCTL_SSID *pSSID = (RT_CMD_AP_IOCTL_SSID *)pData; + +#ifdef APCLI_SUPPORT + if (pSSID->priv_flags == INT_APCLI) + { + if (pAd->ApCfg.ApCliTab[pObj->ioctl_if].Valid == TRUE) + { + pSSID->length = pAd->ApCfg.ApCliTab[pObj->ioctl_if].SsidLen; + pSSID->pSsidStr = (char *)&pAd->ApCfg.ApCliTab[pObj->ioctl_if].Ssid; + } + else { + pSSID->length = 0; + pSSID->pSsidStr = NULL; + } + } + else +#endif /* APCLI_SUPPORT */ + { + pSSID->length = pAd->ApCfg.MBSSID[pSSID->apidx].SsidLen; + pSSID->pSsidStr = (char *)pAd->ApCfg.MBSSID[pSSID->apidx].Ssid; + } + } + break; + +#ifdef MBSS_SUPPORT + case CMD_RTPRIV_IOCTL_MBSS_BEACON_UPDATE: + //CFG TODO + 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; + +#ifdef MT_MAC + case CMD_RTPRIV_IOCTL_MBSS_CR_ENABLE: + if (mbss_cr_enable(pData) != 0) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_MBSS_CR_DISABLE: + if (mbss_cr_disable(pData) != 0) + return NDIS_STATUS_FAILURE; + break; +#endif /* MT_MAC */ +#endif /* MBSS_SUPPORT */ + + case CMD_RTPRIV_IOCTL_WSC_INIT: + { +#ifdef APCLI_SUPPORT +#ifdef WSC_AP_SUPPORT +#ifdef WSC_V2_SUPPORT + PWSC_V2_INFO pWscV2Info; +#endif /* WSC_V2_SUPPORT */ + APCLI_STRUCT *pApCliEntry = (APCLI_STRUCT *)pData; + WscGenerateUUID(pAd, &pApCliEntry->WscControl.Wsc_Uuid_E[0], + &pApCliEntry->WscControl.Wsc_Uuid_Str[0], 0, FALSE); + pApCliEntry->WscControl.bWscFragment = FALSE; + pApCliEntry->WscControl.WscFragSize = 128; + pApCliEntry->WscControl.WscRxBufLen = 0; + pApCliEntry->WscControl.pWscRxBuf = NULL; + os_alloc_mem(pAd, &pApCliEntry->WscControl.pWscRxBuf, MGMT_DMA_BUFFER_SIZE); + if (pApCliEntry->WscControl.pWscRxBuf) + NdisZeroMemory(pApCliEntry->WscControl.pWscRxBuf, MGMT_DMA_BUFFER_SIZE); + pApCliEntry->WscControl.WscTxBufLen = 0; + pApCliEntry->WscControl.pWscTxBuf = NULL; + os_alloc_mem(pAd, &pApCliEntry->WscControl.pWscTxBuf, MGMT_DMA_BUFFER_SIZE); + if (pApCliEntry->WscControl.pWscTxBuf) + NdisZeroMemory(pApCliEntry->WscControl.pWscTxBuf, MGMT_DMA_BUFFER_SIZE); + initList(&pApCliEntry->WscControl.WscPeerList); + NdisAllocateSpinLock(pAd, &pApCliEntry->WscControl.WscPeerListSemLock); + pApCliEntry->WscControl.PinAttackCount = 0; + pApCliEntry->WscControl.bSetupLock = FALSE; +#ifdef WSC_V2_SUPPORT + pWscV2Info = &pApCliEntry->WscControl.WscV2Info; + pWscV2Info->bWpsEnable = TRUE; + pWscV2Info->ExtraTlv.TlvLen = 0; + pWscV2Info->ExtraTlv.TlvTag = 0; + pWscV2Info->ExtraTlv.pTlvData = NULL; + pWscV2Info->ExtraTlv.TlvType = TLV_ASCII; + pWscV2Info->bEnableWpsV2 = TRUE; +#endif /* WSC_V2_SUPPORT */ + WscInit(pAd, TRUE, Data); +#endif /* WSC_AP_SUPPORT */ +#endif /* APCLI_SUPPORT */ + } + break; + +#ifdef APCLI_SUPPORT + case CMD_RTPRIV_IOCTL_APC_UP: + ApCliIfUp(pAd); + break; + + case CMD_RTPRIV_IOCTL_APC_DISCONNECT: + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, Data); + RTMP_MLME_HANDLER(pAd); + break; + + case CMD_RTPRIV_IOCTL_APC_INIT: + APCli_Init(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_APC_OPEN: + if (ApCli_Open(pAd, pData) != TRUE) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_APC_CLOSE: + if (ApCli_Close(pAd, pData) != TRUE) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_APC_REMOVE: + ApCli_Remove(pAd); + break; +#endif /* APCLI_SUPPORT */ + + case CMD_RTPRIV_IOCTL_MAIN_OPEN: +#ifdef AIRPLAY_SUPPORT + if (AIRPLAY_ON(pAd)) +#endif /* AIRPLAY_SUPPORT */ + pAd->ApCfg.MBSSID[MAIN_MBSSID].bcn_buf.bBcnSntReq = TRUE; +#ifdef BAND_STEERING + if(pAd->ApCfg.BandSteering) + { + PBND_STRG_CLI_TABLE table; + table = Get_BndStrgTable(pAd, MAIN_MBSSID); + if(table) + { + /* Inform daemon interface ready */ + BndStrg_SetInfFlags(pAd, &pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev, table, TRUE); + } + } +#endif /* BAND_STEERING */ + break; + + case CMD_RTPRIV_IOCTL_PREPARE: + { + RT_CMD_AP_IOCTL_CONFIG *pConfig = (RT_CMD_AP_IOCTL_CONFIG *)pData; + pConfig->Status = RTMP_AP_IoctlPrepare(pAd, pData); + if (pConfig->Status != 0) + return NDIS_STATUS_FAILURE; + } + break; + + case CMD_RTPRIV_IOCTL_AP_SIOCGIWAP: + { + UCHAR *pBssidDest = (UCHAR *)pData; + PCHAR pBssidStr; + +#ifdef APCLI_SUPPORT + if (Data == INT_APCLI) + { + if (pAd->ApCfg.ApCliTab[pObj->ioctl_if].Valid == TRUE) + pBssidStr = (PCHAR)&APCLI_ROOT_BSSID_GET(pAd, pAd->ApCfg.ApCliTab[pObj->ioctl_if].MacTabWCID); + else + pBssidStr = NULL; + } + else +#endif /* APCLI_SUPPORT */ + { + pBssidStr = (PCHAR) &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.bssid[0]; + } + + if (pBssidStr != NULL) + { + memcpy(pBssidDest, pBssidStr, ETH_ALEN); + DBGPRINT(RT_DEBUG_TRACE, ("IOCTL::SIOCGIWAP(=%02x:%02x:%02x:%02x:%02x:%02x)\n", + PRINT_MAC(pBssidStr))); + } + else + { + memset(pBssidDest, 0, ETH_ALEN); + } + } + break; + + case CMD_RTPRIV_IOCTL_AP_SIOCGIWRATEQ: + /* handle for SIOCGIWRATEQ */ + { + RT_CMD_IOCTL_RATE *pRate = (RT_CMD_IOCTL_RATE *)pData; + HTTRANSMIT_SETTING HtPhyMode; + +#ifdef APCLI_SUPPORT + if (pRate->priv_flags == INT_APCLI) + HtPhyMode = pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev.HTPhyMode; + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (pRate->priv_flags == INT_WDS) + HtPhyMode = pAd->WdsTab.WdsEntry[pObj->ioctl_if].wdev.HTPhyMode; + else +#endif /* WDS_SUPPORT */ + HtPhyMode = pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.HTPhyMode; + + 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 */ +#ifdef WIFI_DIAG + case CMD_RTPRIV_IOCTL_GET_PROCESS_INFO: + DiagGetProcessInfo(pAd, wrq); + break; +#endif + default: + Status = RTMP_COM_IoctlHandle(pAd, wrq, cmd, subcmd, pData, Data); + break; + } + + return Status; +} + + + +#ifdef DYNAMIC_VGA_SUPPORT +INT Set_DyncVgaEnable_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + UINT Enable; + + Enable = simple_strtol(arg, 0, 10); + + pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable = (Enable > 0) ? TRUE : FALSE; + + if (pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable == TRUE) { + dynamic_vga_enable(pAd); + } else { + dynamic_vga_disable(pAd); + } + + DBGPRINT(RT_DEBUG_TRACE, + ("Set_DyncVgaEnable_Proc::(enable = %d)\n", + pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable)); + + return TRUE; +} + + +INT set_false_cca_hi_th(PRTMP_ADAPTER pAd, RTMP_STRING *arg) +{ + INT32 val = simple_strtol(arg, 0, 10); + + pAd->CommonCfg.lna_vga_ctl.nFalseCCATh = (val <= 0) ? 800 : val; + + DBGPRINT(RT_DEBUG_OFF, ("%s::(false cca high threshould = %d)\n", + __FUNCTION__, pAd->CommonCfg.lna_vga_ctl.nFalseCCATh)); + + return TRUE; +} + + +INT set_false_cca_low_th(PRTMP_ADAPTER pAd, RTMP_STRING *arg) +{ + INT32 val = simple_strtol(arg, 0, 10); + + pAd->CommonCfg.lna_vga_ctl.nLowFalseCCATh = (val <= 0) ? 10 : val; + + DBGPRINT(RT_DEBUG_OFF, ("%s::(false cca low threshould = %d)\n", + __FUNCTION__, pAd->CommonCfg.lna_vga_ctl.nLowFalseCCATh)); + + return TRUE; +} +#endif /* DYNAMIC_VGA_SUPPORT */ + +#ifdef CONFIG_HOTSPOT +static INT Set_AP_HS_IE( + IN PRTMP_ADAPTER pAd, + IN UINT8 EID, + IN RTMP_STRING *IE, + IN UINT32 IELen) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PHOTSPOT_CTRL pHSCtrl = &pAd->ApCfg.MBSSID[apidx].HotSpotCtrl; + + switch (EID) + { + /*case IE_INTERWORKING: + os_alloc_mem(NULL, &pHSCtrl->InterWorkingIE, IELen); + NdisMoveMemory(pHSCtrl->InterWorkingIE, IE, IELen); + pHSCtrl->InterWorkingIELen = IELen; + pHSCtrl->AccessNetWorkType = (*(IE + 2)) & 0x0F; + if (IELen > 3) + { + pHSCtrl->IsHessid = TRUE; + if (IELen == 7) + NdisMoveMemory(pHSCtrl->Hessid, IE + 3, MAC_ADDR_LEN); + else + NdisMoveMemory(pHSCtrl->Hessid, IE + 5 , MAC_ADDR_LEN); + } + DBGPRINT(RT_DEBUG_TRACE, ("Set Interworking IE\n")); + break; + case IE_ADVERTISEMENT_PROTO: + os_alloc_mem(NULL, &pHSCtrl->AdvertisementProtoIE, IELen); + NdisMoveMemory(pHSCtrl->AdvertisementProtoIE, IE, IELen); + pHSCtrl->AdvertisementProtoIELen = IELen; + DBGPRINT(RT_DEBUG_TRACE, ("Set Advertisement Protocol IE\n")); + break;*/ + case IE_QOS_MAP_SET: + { + int tmp = 0; + char *pos = (char *)(IE+2); + os_alloc_mem(NULL, &pHSCtrl->QosMapSetIE, IELen); + NdisMoveMemory(pHSCtrl->QosMapSetIE, IE, IELen); + pHSCtrl->QosMapSetIELen = IELen; + for(tmp = 0;tmp<(IELen-16-2)/2;tmp++) + { + pHSCtrl->DscpException[tmp] = *pos & 0xff; + pHSCtrl->DscpException[tmp] |= (*(pos+1) & 0xff) << 8; + pos += 2; + } + for(tmp = 0;tmp<8;tmp++) + { + pHSCtrl->DscpRange[tmp] = *pos & 0xff; + pHSCtrl->DscpRange[tmp] |= (*(pos+1) & 0xff) << 8; + pos += 2; + } + DBGPRINT(RT_DEBUG_TRACE, ("Set Qos MAP Set IE\n")); + } + break; + case IE_ROAMING_CONSORTIUM: + os_alloc_mem(NULL, &pHSCtrl->RoamingConsortiumIE, IELen); + NdisMoveMemory(pHSCtrl->RoamingConsortiumIE, IE, IELen); + pHSCtrl->RoamingConsortiumIELen = IELen; + DBGPRINT(RT_DEBUG_TRACE, ("Set Roaming Consortium IE\n")); + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknown IE(EID = %d)\n", __FUNCTION__, EID)); + break; + } + + return TRUE; +} +#endif + +INT _Set_AP_VENDOR_SPECIFIC_IE( + IN PRTMP_ADAPTER pAd, + IN UINT8 OUIType, + IN RTMP_STRING *IE, + IN UINT32 IELen) +{ +#ifdef CONFIG_HOTSPOT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + + PHOTSPOT_CTRL pHSCtrl = &pAd->ApCfg.MBSSID[apidx].HotSpotCtrl; +#endif + + switch (OUIType) { +#ifdef CONFIG_HOTSPOT + case OUI_P2P: + if (pHSCtrl->P2PIE) { + os_free_mem(NULL, pHSCtrl->P2PIE); + pHSCtrl->P2PIE = NULL; + pHSCtrl->P2PIELen = 0; + } + os_alloc_mem(NULL, &pHSCtrl->P2PIE, IELen); + NdisMoveMemory(pHSCtrl->P2PIE, IE, IELen); + pHSCtrl->P2PIELen = IELen; + DBGPRINT(RT_DEBUG_TRACE, ("Set P2P IE\n")); + break; + case OUI_HS2_INDICATION: + if (pHSCtrl->HSIndicationIE) { + os_free_mem(NULL, pHSCtrl->HSIndicationIE); + pHSCtrl->HSIndicationIE = NULL; + pHSCtrl->HSIndicationIELen = 0; + } + os_alloc_mem(NULL, &pHSCtrl->HSIndicationIE, IELen); + NdisMoveMemory(pHSCtrl->HSIndicationIE, IE, IELen); + pHSCtrl->HSIndicationIELen = IELen; + DBGPRINT(RT_DEBUG_TRACE, ("Set HS2.0 Indication IE\n")); + break; +#endif + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknown OUIType = %d\n", __FUNCTION__, OUIType)); + break; + + } + + return TRUE; +} + +#ifdef CONFIG_DOT11V_WNM +static INT Set_AP_WNM_IE( + IN PRTMP_ADAPTER pAd, + IN UINT8 EID, + IN RTMP_STRING *IE, + IN UINT32 IELen) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[apidx].WNMCtrl; + + switch (EID) + { + case IE_TIME_ADVERTISEMENT: + os_alloc_mem(NULL, &pWNMCtrl->TimeadvertisementIE, IELen); + NdisMoveMemory(pWNMCtrl->TimeadvertisementIE, IE, IELen); + pWNMCtrl->TimeadvertisementIELen = IELen; + DBGPRINT(RT_DEBUG_TRACE, ("Set Time Advertisement IE\n")); + break; + case IE_TIME_ZONE: + os_alloc_mem(NULL, &pWNMCtrl->TimezoneIE, IELen); + NdisMoveMemory(pWNMCtrl->TimezoneIE, IE, IELen); + pWNMCtrl->TimezoneIELen = IELen; + DBGPRINT(RT_DEBUG_TRACE, ("Set Time Zone IE\n")); + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknown IE(EID = %d)\n", __FUNCTION__, EID)); + break; + } + + return TRUE; +} +#endif + +INT Set_AP_IE( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *IE, + IN UINT32 IELen) +{ + UINT8 EID; + UINT8 OUIType; + + EID = *IE; + + switch (EID) + { +#ifdef CONFIG_HOTSPOT + case IE_INTERWORKING: + case IE_ADVERTISEMENT_PROTO: + case IE_QOS_MAP_SET: + case IE_ROAMING_CONSORTIUM: + Set_AP_HS_IE(pAd, EID, IE, IELen); + break; +#endif + +#ifdef CONFIG_DOT11V_WNM + case IE_TIME_ADVERTISEMENT: + case IE_TIME_ZONE: + Set_AP_WNM_IE(pAd, EID, IE, IELen); + break; +#endif + case IE_VENDOR_SPECIFIC: + OUIType = *(IE + 5); + _Set_AP_VENDOR_SPECIFIC_IE(pAd, OUIType, IE, IELen); + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknown IE(EID = %d)\n", __FUNCTION__, EID)); + break; + } + + return TRUE; +} + +#if defined(WAPP_SUPPORT) && defined(DOT11U_INTERWORKING) +INT Send_ANQP_Rsp( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *PeerMACAddr, + IN RTMP_STRING *ANQPRsp, + IN UINT32 ANQPRspLen) +{ + UCHAR *Buf; + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PGAS_CTRL pGASCtrl = &pAd->ApCfg.MBSSID[apidx].GASCtrl; + GAS_EVENT_DATA *Event; + GAS_PEER_ENTRY *GASPeerEntry; + GAS_QUERY_RSP_FRAGMENT *GASQueryRspFrag, *Tmp; + UINT32 Len = 0, i, QueryRspOffset = 0; + BOOLEAN Cancelled; + BOOLEAN IsFound = FALSE; + unsigned long irqFlags=0; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + /* Cancel PostReply timer after receiving daemon response */ + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, PeerMACAddr)) + { + if (GASPeerEntry->PostReplyTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->PostReplyTimerRunning = FALSE; + } + + break; + } + } + + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + ANQPRspLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + + //RTMP_SEM_EVENT_WAIT(&pGASCtrl->GASPeerListLock, Ret); + RTMP_INT_LOCK(&pAd->irq_lock, irqFlags); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, PeerMACAddr)) + { + IsFound = TRUE; + printk("!!GAS RSP DialogToken!! = %x\n", GASPeerEntry->DialogToken); + break; + } + } + //RTMP_SEM_EVENT_UP(&pGASCtrl->GASPeerListLock); + RTMP_INT_UNLOCK(&pAd->irq_lock, irqFlags); + + if (IsFound) { + //RTMP_SEM_EVENT_WAIT(&pGASCtrl->GASPeerListLock, Ret); + RTMP_INT_LOCK(&pAd->irq_lock, irqFlags); + DlListDel(&GASPeerEntry->List); + DlListInit(&GASPeerEntry->GASQueryRspFragList); + //RTMP_SEM_EVENT_UP(&pGASCtrl->GASPeerListLock); + RTMP_INT_UNLOCK(&pAd->irq_lock, irqFlags); + if (GASPeerEntry->PostReplyTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->PostReplyTimerRunning = FALSE; + } + RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + + if (GASPeerEntry->GASRspBufferingTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + GASPeerEntry->GASRspBufferingTimerRunning = FALSE; + } + RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + os_free_mem(NULL, GASPeerEntry); + } + goto error0; + } + + NdisZeroMemory(Buf, sizeof(*Event) + ANQPRspLen); + + Event = (GAS_EVENT_DATA *)Buf; + + Event->ControlIndex = apidx; + Len += 1; + NdisMoveMemory(Event->PeerMACAddr, PeerMACAddr, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ANQPRspLen %d pGASCtrl->MMPDUSize %d\n", + __func__, ANQPRspLen, pGASCtrl->MMPDUSize)); + + if ((ANQPRspLen > pGASCtrl->MMPDUSize) || (pGASCtrl->cb_delay != 0)) { + Event->EventType = GAS_RSP_MORE; + Len += 2; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, PeerMACAddr)) + { + IsFound = TRUE; + + Event->u.GAS_RSP_MORE_DATA.DialogToken = GASPeerEntry->DialogToken; + Len += 1; + + if ((ANQPRspLen % pGASCtrl->MMPDUSize) == 0) + GASPeerEntry->GASRspFragNum = ANQPRspLen / pGASCtrl->MMPDUSize; + else + GASPeerEntry->GASRspFragNum = (ANQPRspLen / pGASCtrl->MMPDUSize) + 1; + + GASPeerEntry->CurrentGASFragNum = 0; + + for (i = 0; i < GASPeerEntry->GASRspFragNum; i++) + { + os_alloc_mem(NULL, (UCHAR **)&GASQueryRspFrag, sizeof(*GASQueryRspFrag)); + + if (!GASQueryRspFrag) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + goto error1; + } + GASPeerEntry->AllocResource++; + + NdisZeroMemory(GASQueryRspFrag, sizeof(*GASQueryRspFrag)); + + GASQueryRspFrag->GASRspFragID = i; + + if (i < (GASPeerEntry->GASRspFragNum - 1)) + GASQueryRspFrag->FragQueryRspLen = pGASCtrl->MMPDUSize; + else + GASQueryRspFrag->FragQueryRspLen = ANQPRspLen - \ + (pGASCtrl->MMPDUSize * i); + + os_alloc_mem(NULL, (UCHAR **)&GASQueryRspFrag->FragQueryRsp, + GASQueryRspFrag->FragQueryRspLen); + GASPeerEntry->AllocResource++; + + if (!GASQueryRspFrag->FragQueryRsp) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + goto error2; + } + + NdisMoveMemory(GASQueryRspFrag->FragQueryRsp, &ANQPRsp[QueryRspOffset], + GASQueryRspFrag->FragQueryRspLen); + + QueryRspOffset += GASQueryRspFrag->FragQueryRspLen; + + DlListAddTail(&GASPeerEntry->GASQueryRspFragList, + &GASQueryRspFrag->List); + } + break; + } + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + if (!IsFound) { + DBGPRINT(RT_DEBUG_OFF, ("%s Can not find peer address[%02x:%02x:%02x:%02x:%02x:%02x] in GASPeerList (ComeRsp)\n", __FUNCTION__, PeerMACAddr[0],PeerMACAddr[1],PeerMACAddr[2],PeerMACAddr[3],PeerMACAddr[4],PeerMACAddr[5])); + goto error1; + } + + Event->u.GAS_RSP_MORE_DATA.StatusCode = 0; + Len += 2; + Event->u.GAS_RSP_MORE_DATA.GASComebackDelay = pGASCtrl->cb_delay ? \ + pGASCtrl->cb_delay : 3; //1000; + Len += 2; + Event->u.GAS_RSP_MORE_DATA.AdvertisementProID = ACCESS_NETWORK_QUERY_PROTOCOL; + Len += 1; + + GASPeerEntry->CurrentState = WAIT_GAS_RSP; + + SendGASRsp(pAd, (GAS_EVENT_DATA *)Buf); + } else { + Event->EventType = GAS_RSP; + Len += 2; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, PeerMACAddr)) { + IsFound = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("GAS RSP DialogToken = %x\n", + GASPeerEntry->DialogToken)); + Event->u.GAS_RSP_DATA.DialogToken = GASPeerEntry->DialogToken; + Len += 1; + } + break; + } + + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + if (!IsFound) { + DBGPRINT(DBG_LVL_ERROR, + ("%s Can not find peer address in GASPeerList\n", __func__)); + goto error1; + } + + Event->u.GAS_RSP_DATA.StatusCode = 0; + Len += 2; + Event->u.GAS_RSP_DATA.GASComebackDelay = 0; + Len += 2; + Event->u.GAS_RSP_DATA.AdvertisementProID = ACCESS_NETWORK_QUERY_PROTOCOL; + Len += 1; + Event->u.GAS_RSP_DATA.QueryRspLen = ANQPRspLen; + Len += 2; + + NdisMoveMemory(Event->u.GAS_RSP_DATA.QueryRsp, ANQPRsp, ANQPRspLen); + Len += ANQPRspLen; + + GASPeerEntry->CurrentState = WAIT_GAS_RSP; + + SendGASRsp(pAd, (GAS_EVENT_DATA *)Buf); + } + + os_free_mem(NULL, Buf); + + return TRUE; + +error2: + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEachSafe(GASQueryRspFrag, Tmp, &GASPeerEntry->GASQueryRspFragList, + GAS_QUERY_RSP_FRAGMENT, List) + { + DlListDel(&GASQueryRspFrag->List); + os_free_mem(NULL, GASQueryRspFrag); + } + + DlListInit(&GASPeerEntry->GASQueryRspFragList); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); +error1: + os_free_mem(NULL, Buf); +error0: + return FALSE; +} + +#endif + +#ifdef CONFIG_DOT11V_WNM +INT Send_BTM_Req( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *PeerMACAddr, + IN RTMP_STRING *BTMReq, + IN UINT32 BTMReqLen) +{ + UCHAR *Buf; + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UCHAR APIndex = pObj->ioctl_if; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; + BTM_EVENT_DATA *Event; + BTM_PEER_ENTRY *BTMPeerEntry; + UINT32 Len = 0; + INT32 Ret; + BOOLEAN IsFound = FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_ERROR, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(BTMPeerEntry, &pWNMCtrl->BTMPeerList, BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, PeerMACAddr)) + { + IsFound = TRUE; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + + if (!IsFound) + { + os_alloc_mem(NULL, (UCHAR **)&BTMPeerEntry, sizeof(*BTMPeerEntry)); + + if (!BTMPeerEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + goto error0; + } + + NdisZeroMemory(BTMPeerEntry, sizeof(*BTMPeerEntry)); + + BTMPeerEntry->CurrentState = WAIT_BTM_REQ; + BTMPeerEntry->ControlIndex = APIndex; + NdisMoveMemory(BTMPeerEntry->PeerMACAddr, PeerMACAddr, MAC_ADDR_LEN); + BTMPeerEntry->DialogToken = 1; + BTMPeerEntry->Priv = pAd; + + RTMPInitTimer(pAd, &BTMPeerEntry->WaitPeerBTMRspTimer, + GET_TIMER_FUNCTION(WaitPeerBTMRspTimeout), BTMPeerEntry, FALSE); + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_ERROR, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListAddTail(&pWNMCtrl->BTMPeerList, &BTMPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + } + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + BTMReqLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + goto error1; + } + + NdisZeroMemory(Buf, sizeof(*Event) + BTMReqLen); + + Event = (BTM_EVENT_DATA *)Buf; + + Event->ControlIndex = APIndex; + Len += 1; + + NdisMoveMemory(Event->PeerMACAddr, PeerMACAddr, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + Event->EventType = BTM_REQ; + Len += 2; + + Event->u.BTM_REQ_DATA.DialogToken = BTMPeerEntry->DialogToken; + Len += 1; + + Event->u.BTM_REQ_DATA.BTMReqLen = BTMReqLen; + Len += 2; + + NdisMoveMemory(Event->u.BTM_REQ_DATA.BTMReq, BTMReq, BTMReqLen); + Len += BTMReqLen; + + MlmeEnqueue(pAd, BTM_STATE_MACHINE, BTM_REQ, Len, Buf, 0); + + os_free_mem(NULL, Buf); + + return TRUE; + +error1: + if (!IsFound) + os_free_mem(NULL, BTMPeerEntry); +error0: + return FALSE; +} + +INT Send_WNM_Notify_Req( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *PeerMACAddr, + IN RTMP_STRING *WNMNotifyReq, + IN UINT32 WNMNotifyReqLen, + IN UINT32 type) +{ + UCHAR *Buf; + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UCHAR APIndex = pObj->ioctl_if; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; + WNM_NOTIFY_EVENT_DATA *Event; + WNM_NOTIFY_PEER_ENTRY *WNMNotifyPeerEntry; + UINT32 Len = 0; + INT32 Ret; + BOOLEAN IsFound = FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->WNMNotifyPeerListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_ERROR, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(WNMNotifyPeerEntry, &pWNMCtrl->WNMNotifyPeerList, WNM_NOTIFY_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(WNMNotifyPeerEntry->PeerMACAddr, PeerMACAddr)) + { + IsFound = TRUE; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); + + if (!IsFound) + { + os_alloc_mem(NULL, (UCHAR **)&WNMNotifyPeerEntry, sizeof(*WNMNotifyPeerEntry)); + + if (!WNMNotifyPeerEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + goto error0; + } + + NdisZeroMemory(WNMNotifyPeerEntry, sizeof(*WNMNotifyPeerEntry)); + + WNMNotifyPeerEntry->CurrentState = WNM_NOTIFY_REQ; + WNMNotifyPeerEntry->ControlIndex = APIndex; + NdisMoveMemory(WNMNotifyPeerEntry->PeerMACAddr, PeerMACAddr, MAC_ADDR_LEN); + WNMNotifyPeerEntry->DialogToken = 1; + WNMNotifyPeerEntry->Priv = pAd; + + RTMPInitTimer(pAd, &WNMNotifyPeerEntry->WaitPeerWNMNotifyRspTimer, + GET_TIMER_FUNCTION(WaitPeerWNMNotifyRspTimeout), WNMNotifyPeerEntry, FALSE); + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->WNMNotifyPeerListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_ERROR, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListAddTail(&pWNMCtrl->WNMNotifyPeerList, &WNMNotifyPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); + } + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + WNMNotifyReqLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + goto error1; + } + + //RTMPusecDelay(200000); //200ms + + NdisZeroMemory(Buf, sizeof(*Event) + WNMNotifyReqLen); + + Event = (WNM_NOTIFY_EVENT_DATA *)Buf; + + Event->ControlIndex = APIndex; + Len += 1; + + NdisMoveMemory(Event->PeerMACAddr, PeerMACAddr, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + Event->EventType = type; //WNM_NOTIFY_REQ; + Len += 2; + + Event->u.WNM_NOTIFY_REQ_DATA.DialogToken = WNMNotifyPeerEntry->DialogToken; + Len += 1; + + Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen = WNMNotifyReqLen; + Len += 2; + + NdisMoveMemory(Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReq, WNMNotifyReq, WNMNotifyReqLen); + Len += WNMNotifyReqLen; + + MlmeEnqueue(pAd, WNM_NOTIFY_STATE_MACHINE, WNM_NOTIFY_REQ, Len, Buf, 0); + + os_free_mem(NULL, Buf); + + return TRUE; + +error1: + if (!IsFound) + os_free_mem(NULL, WNMNotifyPeerEntry); +error0: + return FALSE; +} + +#ifdef CONFIG_HOTSPOT_R2 +INT Send_QOSMAP_Configure( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *PeerMACAddr, + IN RTMP_STRING *QosMapBuf, + IN UINT32 QosMapLen, + IN UINT8 Apidx) +{ + MLME_QOS_ACTION_STRUCT QosMapConfig; + QOSMAP_SET *pQOSMap = &QosMapConfig.QOSMap; + + NdisZeroMemory(&QosMapConfig, sizeof(MLME_QOS_ACTION_STRUCT)); + COPY_MAC_ADDR(QosMapConfig.Addr, PeerMACAddr); + QosMapConfig.ActionField = ACTION_QOSMAP_CONFIG; + QosMapConfig.apidx = Apidx; + pQOSMap->DSCP_Field_Len = QosMapLen; + NdisMoveMemory(pQOSMap->DSCP_Field, QosMapBuf, QosMapLen); + MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_QOS_CATE, sizeof(MLME_QOS_ACTION_STRUCT), (PVOID)&QosMapConfig, 0); + RTMP_MLME_HANDLER(pAd); + + return TRUE; +} +#endif /* CONFIG_HOTSPOT_R2 */ +#endif /* CONFIG_DOT11V_WNM */ + +#ifdef AIRPLAY_SUPPORT +/* +======================================================================== +Routine Description: + Set airplay function enable. +Arguments: + pAd - WLAN control block pointer + arg - 1: Open airplay function; + - 0: Close airplay function. +Return Value: + 0 :NDIS_STATUS_SUCCESS + 1 :NDIS_STATUS_FAILURE +Note: +======================================================================== +*/ +INT Set_Airplay_Enable( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg) +{ + UINT enable = 0/*, apidx = 0*/; + //POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + //apidx = pObj->ioctl_if; + + /*test IE*/ +// UCHAR AirplayIEFixed[9] = {0xdd, 0x07, 0x00, 0x03, 0x93, 0x01, 0x73, 0x0B, 0x22}; + enable = simple_strtol(arg, 0, 16); + + if (enable==0x1) + { + /*Enable boolean flag*/ + pAd->bAirplayEnable = 1; + pAd->ApCfg.MBSSID[MAIN_MBSSID].bcn_buf.bBcnSntReq = TRUE; + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + DBGPRINT(RT_DEBUG_ERROR, ("###Set to Apple IE BCN..\n")); + } + else if (enable==0x2) + { + pAd->bAirplayEnable = 1; + pAd->pAirplayIe = NULL; + pAd->AirplayIeLen = 0; + pAd->ApCfg.MBSSID[MAIN_MBSSID].bcn_buf.bBcnSntReq = TRUE; + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + DBGPRINT(RT_DEBUG_ERROR, ("###Set back to Normal BCN...\n")); + + } + else /* Disable Airplay*/ + { + /* Close airplay flag*/ + pAd->bAirplayEnable = 0; + DBGPRINT(RT_DEBUG_ERROR, ("###Set to no BCN...\n")); + } + + return NDIS_STATUS_SUCCESS; +} + +#endif /* AIRPLAY_SUPPORT*/ +INT set_ping_log_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 value; + + value = simple_strtol(arg, 0, 10); + + if (value != 0) + { + pAd->bPingLog = TRUE; + printk("\033[1;32m ping log on \033[0m\n"); + } + else + { + pAd->bPingLog = FALSE; + printk("\033[1;32m ping log off \033[0m\n"); + } + + return TRUE; +} +#ifdef DATA_QUEUE_RESERVE +INT set_queue_rsv_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 value; + + value = simple_strtol(arg, 0, 10); + + if (value != 0) + { + pAd->bQueueRsv = TRUE; + DBGPRINT(RT_DEBUG_ERROR,("\033[1;32m queue rsv on \033[0m\n")); + } + else + { + pAd->bQueueRsv = FALSE; + DBGPRINT(RT_DEBUG_ERROR,("\033[1;32m queue rsv off \033[0m\n")); + } + + return TRUE; +} + + +INT set_dump_on_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 value; + + value = simple_strtol(arg, 0, 10); + + if (value != 0) + { + pAd->bDump = TRUE; + DBGPRINT(RT_DEBUG_ERROR,("\033[1;32m dump on \033[0m\n")); + } + else + { + pAd->bDump = FALSE; + DBGPRINT(RT_DEBUG_ERROR,("\033[1;32m dump off \033[0m\n")); + } + + return TRUE; +} + + +INT set_rsv_cnt_clear_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 value; + INT i; + value = simple_strtol(arg, 0, 10); + + if (value != 0) + { + for (i=0; iMacTab.tr_entry[i]; + tr_entry->high_pkt_cnt = 0; + tr_entry->high_pkt_drop_cnt = 0; + } + DBGPRINT(RT_DEBUG_ERROR,("\033[1;32m clear cnts \033[0m\n")); + } + + return TRUE; +} +#endif /* DATA_QUEUE_RESERVE */ +INT set_lower_mcs_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 value; + + value = simple_strtol(arg, 0, 10); + + if (value >= 0 && value <= 6) + { + pAd->LowerMcsValue = value; + DBGPRINT(RT_DEBUG_OFF,("lower MCS value set to:%d \n", value)); + } else { + pAd->LowerMcsValue = 0; //Default value + DBGPRINT(RT_DEBUG_ERROR,("ERROR:invalid lower MCS value(%d) valid range is 0-6 \n", value)); + } + + return TRUE; +} +INT set_higher_mcs_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 value; + + value = simple_strtol(arg, 0, 10); + if (value >= 0 && value <= 15) + { + if(pAd->LowerMcsValue && value <= pAd->LowerMcsValue) + { + DBGPRINT(RT_DEBUG_OFF,("ERROR: Higher MCS value(%d) should be greater than Lower MCS value(%d) \n", value, pAd->LowerMcsValue)); + pAd->HigherMcsValue = 0; + return TRUE; + } + pAd->HigherMcsValue = value; + DBGPRINT(RT_DEBUG_OFF,("Higher MCS set to:%d \n", value)); + } else { + pAd->HigherMcsValue = 0; //Default value + DBGPRINT(RT_DEBUG_ERROR,("ERROR: invalid Higher MCS value(%d) valid range is 0-15 \n", value)); + } + return TRUE; +} + +INT Show_lower_mcs_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + if(pAd->LowerMcsValue) + DBGPRINT(RT_DEBUG_OFF,("Lower MCS value set to:%d \n", pAd->LowerMcsValue)); + else + DBGPRINT(RT_DEBUG_OFF,("Lower MCS value is not set \n")); + return TRUE; +} +INT Show_higher_mcs_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + if(pAd->HigherMcsValue) + DBGPRINT(RT_DEBUG_OFF,("Higher MCS value set to:%d \n", pAd->HigherMcsValue)); + else + DBGPRINT(RT_DEBUG_OFF,("Higher MCS value is not set \n")); + return TRUE; +} + +#ifdef AIR_MONITOR +#ifndef _LINUX_BITOPS_H +#define BIT(n) ((UINT32) 1 << (n)) +#endif /* BIT */ +#define BITS(m,n) (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n))) +#define SMESH_RX_CTL BIT(20) +#define SMESH_RX_CTL_OFFSET 20 +#define SMESH_RX_MGT BIT(19) +#define SMESH_RX_MGT_OFFSET 19 +#define SMESH_RX_DATA BIT(18) +#define SMESH_RX_DATA_OFFSET 18 +#define SMESH_RX_A1 BIT(17) +#define SMESH_RX_A2 BIT(16) +#define SMESH_ADDR_EN BITS(0,7) +#define MAR1_MAR_GROUP_MASK BITS(30,31) +#define MAR1_MAR_GROUP_OFFSET 30 +#define MAR1_MAR_HASH_MODE_BSSID1 BIT(30) +#define MAR1_MAR_HASH_MODE_BSSID2 BIT(31) +#define MAR1_MAR_HASH_MODE_BSSID3 BITS(30,31) +#define MAR1_ADDR_INDEX_MASK BITS(24,29) +#define MAR1_ADDR_INDEX_OFFSET 24 +#define MAR1_READ 0 +#define MAR1_WRITE BIT(17) +#define MAR1_ACCESS_START_STATUS BIT(16) +INT Set_Enable_Air_Monitor_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + UCHAR mnt_enable = 0; + //UCHAR flush_all = FALSE; + UINT32 i; + //UINT32 u4SMESH = 0; + //UINT32 u4MAR0 = 0, u4MAR1 = 0; + //UCHAR *p = ZERO_MAC_ADDR; + //BOOLEAN bSMESHEn = FALSE; + MNT_STA_ENTRY *pMntEntry = NULL; + MAC_TABLE_ENTRY *pMacEntry = NULL; + UINT32 Value; + + DBGPRINT(RT_DEBUG_OFF, ("--> %s()\n", __FUNCTION__)); + mnt_enable = (UCHAR)simple_strtol(arg, 0, 10); + + if(pAd->MntEnable != mnt_enable) + { + if(mnt_enable == 0) + { + + { + for (i=0; iMntTable[i]; + if(!pMntEntry->bValid) + continue; + + pMacEntry = pMntEntry->pMacEntry; + if (pMacEntry) + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s::call MacTableDeleteEntry(WCID=%d)- %02X:%02X:%02X:%02X:%02X:%02X\n", + __FUNCTION__, pMacEntry->wcid, PRINT_MAC(pMacEntry->Addr))); + MacTableDeleteEntry(pAd, pMacEntry->wcid, pMacEntry->Addr); + } + pAd->MonitrCnt--; + NdisZeroMemory(pMntEntry, sizeof(*pMntEntry)); + } + + } + + RTMP_IO_READ32(pAd, RMAC_RFCR, &Value); + Value |= DROP_NOT_UC2ME; + Value |= DROP_NOT_MY_BSSID; + RTMP_IO_WRITE32(pAd, RMAC_RFCR, Value); + + pAd->MntEnable = 0; + NdisZeroMemory(&pAd->MntTable, sizeof(pAd->MntTable)); + } + else + { + RTMP_IO_READ32(pAd, RMAC_RFCR, &Value); + Value &= ~DROP_NOT_UC2ME; + Value &= ~DROP_NOT_MY_BSSID; + RTMP_IO_WRITE32(pAd, RMAC_RFCR, Value); + + pAd->MntEnable = 1; + } + } + + DBGPRINT(RT_DEBUG_OFF, ("<-- %s()\n", __FUNCTION__)); + return TRUE; +} + + +INT Set_MonitorRule_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + INT ret = TRUE; + RTMP_STRING *this_char = NULL, *value = NULL; + INT idx = 0; + UCHAR rx_rule[3]; + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("--> %s()\n", __FUNCTION__)); + + while ((this_char = strsep((char **)&arg, ";")) != NULL) + { + if (*this_char == '\0') + { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_WARN, ("An unnecessary delimiter entered!\n")); + continue; + } + + if (strlen(this_char) != 5) /* the acceptable format is like 0:1:1 with length 5 */ + { + DBGPRINT(RT_DEBUG_TRACE, + ("illegal length! (acceptable format 0:1 length 3)\n")); + continue; + } + + for (idx=0, value=rstrtok(this_char,":"); value; value=rstrtok(NULL,":")) + { + if ((strlen(value) != 1) || (!isxdigit(*value))) + { + DBGPRINT(RT_DEBUG_TRACE, ("illegal format!\n")); + break; + } + + rx_rule[idx++] = (UCHAR)simple_strtol(value, 0, 10); + } + + if (idx != 3) + continue; + } + + pAd->MntRuleBitMap &= ~RULE_CTL; + pAd->MntRuleBitMap &= ~RULE_MGT; + pAd->MntRuleBitMap &= ~RULE_DATA; + pAd->MntRuleBitMap |= (RULE_DATA & ((UINT32)rx_rule[0] << RULE_DATA_OFFSET)) + | (RULE_MGT & ((UINT32)rx_rule[1] << RULE_MGT_OFFSET)) + | (RULE_CTL & ((UINT32)rx_rule[2] << RULE_CTL_OFFSET)); + printk("AIR Capture Rule %x \n",pAd->MntRuleBitMap); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("<-- %s()\n", __FUNCTION__)); + return ret; +} + + +INT Set_MonitorTarget_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + INT ret = TRUE; + RTMP_STRING *this_char = NULL; + RTMP_STRING *value = NULL; + INT idx = 0; + + DBGPRINT(RT_DEBUG_OFF, ("--> %s()\n", __FUNCTION__)); + + while ((this_char = strsep((char **)&arg, ";")) != NULL) + { + if (*this_char == '\0') + { + DBGPRINT(RT_DEBUG_OFF, ("An unnecessary delimiter entered!\n")); + continue; + } + + if (strlen(this_char) != 17) /* the acceptable format of MAC address is like 01:02:03:04:05:06 with length 17 */ + { + DBGPRINT(RT_DEBUG_OFF, ("illegal MAC address length! (acceptable format 01:02:03:04:05:06 length 17)\n")); + continue; + } + + for (idx=0, value=rstrtok(this_char,":"); value; value=rstrtok(NULL,":")) + { + if ((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1)))) + { + DBGPRINT(RT_DEBUG_OFF, ("illegal MAC address format or octet!\n")); + break; + } + + AtoH(value, &pAd->curMntAddr[idx++], 1); + } + + if (idx != MAC_ADDR_LEN) + continue; + } + + for (idx=0; idxcurMntAddr[idx])); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + return ret; +} + + +INT Set_MonitorIndex_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + INT ret = TRUE; + //UINT32 u4MAR0 = 0, u4MAR1 = 0; + UCHAR mnt_idx = 0; + BOOLEAN bCreate = TRUE; + MNT_STA_ENTRY *pMntEntry = NULL; + MAC_TABLE_ENTRY *pMacEntry = NULL; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("--> %s()\n", __FUNCTION__)); + + mnt_idx = (UCHAR)simple_strtol(arg, 0, 10); + if (mnt_idx < MAX_NUM_OF_MONITOR_STA) + { + pAd->MntIdx = mnt_idx; + pMntEntry = &pAd->MntTable[mnt_idx]; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, + ("The index is over the maximum limit.\n")); + + + return FALSE; + } + + if(MAC_ADDR_EQUAL(ZERO_MAC_ADDR, pAd->curMntAddr)) + { + bCreate = FALSE; + if(pMntEntry->bValid) + { + pMacEntry = pMntEntry->pMacEntry; + if(pMacEntry) + { + MacTableDeleteEntry(pAd, pMacEntry->wcid, pMacEntry->Addr); + } + + pMntEntry->bValid = FALSE; + if (pAd->MonitrCnt > 0) + pAd->MonitrCnt--; + } + else + return TRUE; + } + else + { + if(pMntEntry->bValid) + { + DBGPRINT(RT_DEBUG_TRACE, + ("The index of existed monitor entry.\n")); + + return TRUE; + } + + NdisZeroMemory(pMntEntry, sizeof(MNT_STA_ENTRY)); + COPY_MAC_ADDR(pMntEntry->addr, pAd->curMntAddr); + + if (pAd->MonitrCnt < MAX_NUM_OF_MONITOR_STA) + pAd->MonitrCnt++; + + pMntEntry->bValid = TRUE; + } + + + if(bCreate) + { + pMacEntry = MacTableInsertEntry( + pAd, + pAd->curMntAddr, + wdev, + ENTRY_CAT_MONITOR, + OPMODE_STA, + TRUE); + + pMacEntry->mnt_idx = mnt_idx; + pMntEntry->pMacEntry = pMacEntry; + } + ret = Set_Enable_Air_Monitor_Proc(pAd, (pAd->MonitrCnt>0)?"1":"0"); + + + DBGPRINT(RT_DEBUG_OFF, ("<-- %s()\n", __FUNCTION__)); + return ret; +} + + +INT Set_MonitorShowAll_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + INT ret = TRUE; + UCHAR i = 0; + MNT_STA_ENTRY *pEntry = NULL; + + DBGPRINT(RT_DEBUG_OFF, ("--> %s()\n", __FUNCTION__)); + DBGPRINT(RT_DEBUG_OFF, (" Monitor Enable: %d\n", pAd->MntEnable)); + DBGPRINT(RT_DEBUG_OFF, (" Index last set: %d\n", pAd->MntIdx)); + + for (i=0; iMntTable[i]; + if(pEntry->bValid) + { + DBGPRINT(RT_DEBUG_OFF, ("Monitor STA[%d]\t", i)); + DBGPRINT(RT_DEBUG_OFF, ("%02X:%02X:%02X:%02X:%02X:%02X\t", PRINT_MAC(pEntry->addr))); + DBGPRINT(RT_DEBUG_OFF, ("[DATA]=%08lu\t", pEntry->data_cnt)); + DBGPRINT(RT_DEBUG_OFF, ("[MGMT]=%08lu\t", pEntry->mgmt_cnt)); + DBGPRINT(RT_DEBUG_OFF, ("[TOTAL]=%08lu\t", pEntry->Count)); + DBGPRINT(RT_DEBUG_OFF, ("RSSI:%d,%d,%d\n", + pEntry->RssiSample.AvgRssi[0], pEntry->RssiSample.AvgRssi[1], + pEntry->RssiSample.AvgRssi[2])); + } + } + + DBGPRINT(RT_DEBUG_OFF, ("<-- %s()\n", __FUNCTION__)); + return ret; +} + + +INT Set_MonitorClearCounter_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + INT ret = TRUE; + UCHAR i = 0; + MNT_STA_ENTRY *pEntry = NULL; + + DBGPRINT(RT_DEBUG_OFF, ("--> %s()\n", __FUNCTION__)); + + for (i=0; iMntTable + i; + pEntry->data_cnt = 0; + pEntry->mgmt_cnt = 0; + pEntry->cntl_cnt = 0; + pEntry->Count = 0; + NdisZeroMemory(&pEntry->RssiSample, sizeof(RSSI_SAMPLE)); + } + + DBGPRINT(RT_DEBUG_OFF, ("<-- %s()\n", __FUNCTION__)); + return ret; +} + + +INT Set_Enable_MonitorTarget_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg, + IN USHORT index) +{ + INT ret = TRUE; + CHAR str[8]; + + ret = Set_MonitorTarget_Proc(pAd, arg); + if (!ret) + return ret; + + if (index < MAX_NUM_OF_MONITOR_STA) + { + sprintf(str, "%u", index); + ret = Set_MonitorIndex_Proc(pAd, str); + } + else + { + DBGPRINT(RT_DEBUG_OFF, ("The index is over the maximum limit.\n")); + ret = FALSE; + } + + return ret; +} + + +INT Set_MonitorTarget0_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + return Set_Enable_MonitorTarget_Proc(pAd, arg, 0); +} + +INT Set_MonitorTarget1_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + return Set_Enable_MonitorTarget_Proc(pAd, arg, 1); +} + +INT Set_MonitorTarget2_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + return Set_Enable_MonitorTarget_Proc(pAd, arg, 2); +} + + +INT Set_MonitorTarget3_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + return Set_Enable_MonitorTarget_Proc(pAd, arg, 3); +} + + +INT Set_MonitorTarget4_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + return Set_Enable_MonitorTarget_Proc(pAd, arg, 4); +} + + +INT Set_MonitorTarget5_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + return Set_Enable_MonitorTarget_Proc(pAd, arg, 5); +} + + +INT Set_MonitorTarget6_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + return Set_Enable_MonitorTarget_Proc(pAd, arg, 6); +} + + +INT Set_MonitorTarget7_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + return Set_Enable_MonitorTarget_Proc(pAd, arg, 7); +} + + +int add_mntr_entry(void *ad_obj, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + RTMP_ADAPTER *pAd; + INT ret = NDIS_STATUS_SUCCESS; + UCHAR *p = ZERO_MAC_ADDR, mnt_idx = 0 ; + INT idx = 0; + BOOLEAN bCreate = TRUE; + MNT_STA_ENTRY *pMntEntry = NULL; + MAC_TABLE_ENTRY *pMacEntry = NULL; + mntr_entry_info entry_info; + POS_COOKIE pObj; + UCHAR apidx; + struct wifi_dev *wdev; + + pAd = (RTMP_ADAPTER *)ad_obj; + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + //apidx = pObj->ioctl_if; + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + + DBGPRINT(RT_DEBUG_OFF, ("--> %s()\n", __FUNCTION__)); + + if(!wdev) + { + DBGPRINT(RT_DEBUG_OFF, ("wdev is NULL\n")); + return FALSE; + } + //band_idx = HcGetBandByWdev(wdev); + + if (wrq->u.data.length != sizeof(mntr_entry_info)){ + DBGPRINT(RT_DEBUG_OFF, ("add_mntr_entry: invalid payload size:%d\n",wrq->u.data.length )); + return -EINVAL; + } + + copy_from_user(&entry_info, wrq->u.data.pointer, wrq->u.data.length); + + if (entry_info.index > MAX_NUM_OF_MONITOR_STA) + { + DBGPRINT(RT_DEBUG_OFF, ("The index is over the maximum limit.\n")); + return -EINVAL; + } + + if (!memcmp(entry_info.mac,p,MAC_ADDR_LEN)){ + DBGPRINT(RT_DEBUG_OFF, ("add_mntr_entry: invalid mac addr\n")); + return -EINVAL; + } + else + DBGPRINT(RT_DEBUG_OFF, ("add_mntr_entry: Ind:%d, Chan:%d, Peer:%02x-%02x-%02x-%02x-%02x-%02x\n", + entry_info.index,entry_info.channel,entry_info.mac[0],entry_info.mac[1], + entry_info.mac[2],entry_info.mac[3],entry_info.mac[4],entry_info.mac[5])); + + // current entry count check + + memcpy(pAd->curMntAddr,entry_info.mac,MAC_ADDR_LEN); + + for (idx=0; idxcurMntAddr[idx])); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + pAd->MntIdx = entry_info.index; + pMntEntry = &pAd->MntTable[pAd->MntIdx]; + mnt_idx = entry_info.index; + + if(MAC_ADDR_EQUAL(ZERO_MAC_ADDR, pAd->curMntAddr)) + { + bCreate = FALSE; + if(pMntEntry->bValid) + { + pMacEntry = pMntEntry->pMacEntry; + if(pMacEntry) + { + MacTableDeleteEntry(pAd, pMacEntry->wcid, pMacEntry->Addr); + } + + pMntEntry->bValid = FALSE; + if (pAd->MonitrCnt > 0) + pAd->MonitrCnt--; + } + else + return TRUE; + } + else + { + if(pMntEntry->bValid) + { + DBGPRINT(RT_DEBUG_TRACE, + ("The index of existed monitor entry.\n")); + + return TRUE; + } + + NdisZeroMemory(pMntEntry, sizeof(MNT_STA_ENTRY)); + COPY_MAC_ADDR(pMntEntry->addr, pAd->curMntAddr); + + if (pAd->MonitrCnt < MAX_NUM_OF_MONITOR_STA) + pAd->MonitrCnt++; + + pMntEntry->bValid = TRUE; + p = pMntEntry->addr; + } + + + if(bCreate) + { + pMacEntry = MacTableInsertEntry( + pAd, + pAd->curMntAddr, + wdev, + ENTRY_CAT_MONITOR, + OPMODE_STA, + TRUE); + + pMacEntry->mnt_idx = mnt_idx; + pMntEntry->pMacEntry = pMacEntry; + } + Set_Enable_Air_Monitor_Proc(pAd, (pAd->MonitrCnt>0)?"1":"0"); + + DBGPRINT(RT_DEBUG_OFF, ("<-- %s()\n", __FUNCTION__)); + return ret; +} + +int del_mntr_entry(void *ad_obj, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + RTMP_ADAPTER *pAd; + INT ret = NDIS_STATUS_SUCCESS; + UCHAR *p = ZERO_MAC_ADDR; + INT idx = 0; + MNT_STA_ENTRY *pMntEntry = NULL; + MAC_TABLE_ENTRY *pMacEntry = NULL; + mntr_entry_info entry_info; + POS_COOKIE pObj; + UCHAR apidx; + struct wifi_dev *wdev; + + + pAd = (RTMP_ADAPTER *)ad_obj; + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + //apidx = pObj->ioctl_if; + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + + DBGPRINT(RT_DEBUG_OFF, ("--> %s()\n", __FUNCTION__)); + + if(!wdev) + { + DBGPRINT(RT_DEBUG_OFF, ("wdev is NULL\n")); + return FALSE; + } + //band_idx = HcGetBandByWdev(wdev); + + if (wrq->u.data.length != sizeof(mntr_entry_info)){ + DBGPRINT(RT_DEBUG_OFF, ("add_mntr_entry: invalid payload size:%d\n",wrq->u.data.length )); + return -EINVAL; + } + + copy_from_user(&entry_info, wrq->u.data.pointer, wrq->u.data.length); + + if (entry_info.index > MAX_NUM_OF_MONITOR_STA) + { + DBGPRINT(RT_DEBUG_OFF, ("The index is over the maximum limit.\n")); + return -EINVAL; + } + + if (!memcmp(entry_info.mac,p,MAC_ADDR_LEN)){ + DBGPRINT(RT_DEBUG_OFF, ("del_mntr_entry: invalid mac addr\n")); + return -EINVAL; + } + else + DBGPRINT(RT_DEBUG_OFF, ("del_mntr_entry: Ind:%d, Chan:%d, Peer:%02x-%02x-%02x-%02x-%02x-%02x\n", + entry_info.index,entry_info.channel,entry_info.mac[0],entry_info.mac[1], + entry_info.mac[2],entry_info.mac[3],entry_info.mac[4],entry_info.mac[5])); + + // current entry count check + + memset(pAd->curMntAddr,0x0,MAC_ADDR_LEN); + + for (idx=0; idxcurMntAddr[idx])); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + pAd->MntIdx = entry_info.index; + pMntEntry = &pAd->MntTable[pAd->MntIdx]; + + if(MAC_ADDR_EQUAL(ZERO_MAC_ADDR, pAd->curMntAddr)) + { + if(pMntEntry->bValid) + { + pMacEntry = pMntEntry->pMacEntry; + if(pMacEntry) + { + MacTableDeleteEntry(pAd, pMacEntry->wcid, pMacEntry->Addr); + } + + pMntEntry->bValid = FALSE; + if (pAd->MonitrCnt > 0) + pAd->MonitrCnt--; + } + else + return TRUE; + } + else + { + return ret; + } + + Set_Enable_Air_Monitor_Proc(pAd, (pAd->MonitrCnt>0)?"1":"0"); + + DBGPRINT(RT_DEBUG_OFF, ("<-- %s()\n", __FUNCTION__)); + return ret; + +} + + +INT32 getLegacyOFDMMCSIndex(UINT8 MCS) +{ + INT32 mcs_index = MCS; + if(MCS == 0xb) + mcs_index = 0; + else if(MCS == 0xf) + mcs_index = 1; + else if(MCS == 0xa) + mcs_index = 2; + else if(MCS == 0xe) + mcs_index = 3; + else if(MCS == 0x9) + mcs_index = 4; + else if(MCS == 0xd) + mcs_index = 5; + else if(MCS == 0x8) + mcs_index = 6; + else if(MCS == 0xc) + mcs_index = 7; + + return mcs_index; +} + +INT MCSMappingRateTable[] = + { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108, 109, 110, 111, 112,/* CCK and OFDM */ + 13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260, + 39, 78,117,156,234, 312, 351, 390, /* BW 20, 800ns GI, MCS 0~23 */ + 27, 54, 81,108,162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, + 81,162,243,324,486, 648, 729, 810, /* BW 40, 800ns GI, MCS 0~23 */ + 14, 29, 43, 57, 87, 115, 130, 144, 29, 59, 87, 115, 173, 230, 260, 288, + 43, 87,130,173,260, 317, 390, 433, /* BW 20, 400ns GI, MCS 0~23 */ + 30, 60, 90,120,180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, + 90,180,270,360,540, 720, 810, 900, /* BW 40, 400ns GI, MCS 0~23 */ + + /*for 11ac:20 Mhz 800ns GI*/ + 6, 13, 19, 26, 39, 52, 58, 65, 78, 0, /*1ss mcs 0~8*/ + 13, 26, 39, 52, 78, 104, 117, 130, 156, 0, /*2ss mcs 0~8*/ + 19, 39, 58, 78, 117, 156, 175, 195, 234, 260, /*3ss mcs 0~9*/ + 26, 52, 78, 104, 156, 208, 234, 260, 312, 0, /*4ss mcs 0~8*/ + + /*for 11ac:40 Mhz 800ns GI*/ + 13, 27, 40, 54, 81, 108, 121, 135, 162, 180, /*1ss mcs 0~9*/ + 27, 54, 81, 108, 162, 216, 243, 270, 324, 360, /*2ss mcs 0~9*/ + 40, 81, 121,162, 243, 324, 364, 405, 486, 540, /*3ss mcs 0~9*/ + 54, 108,162,216, 324, 432, 486, 540, 648, 720, /*4ss mcs 0~9*/ + + /*for 11ac:80 Mhz 800ns GI*/ + 29, 58, 87, 117, 175, 234, 263, 292, 351, 390, /*1ss mcs 0~9*/ + 58, 117,175,243, 351, 468, 526, 585, 702, 780, /*2ss mcs 0~9*/ + 87, 175,263,351, 526, 702, 0, 877, 1053,1170, /*3ss mcs 0~9*/ + 117,234,351,468, 702, 936, 1053,1170,1404,1560, /*4ss mcs 0~9*/ + + /*for 11ac:160 Mhz 800ns GI*/ + 58, 117,175,234, 351, 468, 526, 585, 702, 780, /*1ss mcs 0~9*/ + 117,234,351,468, 702, 936, 1053,1170,1404,1560, /*2ss mcs 0~9*/ + 175,351,526,702, 1053,1404,1579,1755,2160,0, /*3ss mcs 0~8*/ + 234,468,702,936, 1404,1872,2106,2340,2808,3120, /*4ss mcs 0~9*/ + + /*for 11ac:20 Mhz 400ns GI*/ + 7, 14, 21, 28, 43, 57, 65, 72, 86, 0, /*1ss mcs 0~8*/ + 14, 28, 43, 57, 86, 115, 130, 144, 173, 0, /*2ss mcs 0~8*/ + 21, 43, 65, 86, 130, 173, 195, 216, 260, 288, /*3ss mcs 0~9*/ + 28, 57, 86, 115, 173, 231, 260, 288, 346, 0, /*4ss mcs 0~8*/ + + /*for 11ac:40 Mhz 400ns GI*/ + 15, 30, 45, 60, 90, 120, 135, 150, 180, 200, /*1ss mcs 0~9*/ + 30, 60, 90, 120, 180, 240, 270, 300, 360, 400, /*2ss mcs 0~9*/ + 45, 90, 135,180, 270, 360, 405, 450, 540, 600, /*3ss mcs 0~9*/ + 60, 120,180,240, 360, 480, 540, 600, 720, 800, /*4ss mcs 0~9*/ + + /*for 11ac:80 Mhz 400ns GI*/ + 32, 65, 97, 130, 195, 260, 292, 325, 390, 433, /*1ss mcs 0~9*/ + 65, 130,195,260, 390, 520, 585, 650, 780, 866, /*2ss mcs 0~9*/ + 97, 195,292,390, 585, 780, 0, 975, 1170,1300, /*3ss mcs 0~9*/ + 130,260,390,520, 780, 1040, 1170,1300,1560,1733, /*4ss mcs 0~9*/ + + /*for 11ac:160 Mhz 400ns GI*/ + 65, 130,195,260, 390, 520, 585, 650, 780, 866, /*1ss mcs 0~9*/ + 130,260,390,520, 780, 1040, 1170,1300,1560,1733, /*2ss mcs 0~9*/ + 195,390,585,780, 1170,1560, 1755,1950,2340,0, /*3ss mcs 0~8*/ + 260,520,780,1040,1560,2080, 2340,2600,3120,3466, /*4ss mcs 0~9*/ + + 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}; /* 3*3 */ + +void getRateNew(HTTRANSMIT_SETTING HTSetting, ULONG* fLastTxRxRate) + +{ + UINT8 Antenna = 0; + UINT8 MCS = HTSetting.field.MCS; + int rate_count = sizeof(MCSMappingRateTable)/sizeof(int); + int rate_index = 0; + int value = 0; + +#ifdef DOT11_VHT_AC + if (HTSetting.field.MODE >= MODE_VHT) + { + MCS = HTSetting.field.MCS & 0xf; + Antenna = (HTSetting.field.MCS>>4) + 1; + if (HTSetting.field.BW == BW_20) { + rate_index = 112 + ((Antenna - 1) * 10) + + ((UCHAR)HTSetting.field.ShortGI * 160) + + ((UCHAR)MCS); + } + else if (HTSetting.field.BW == BW_40) { + rate_index = 152 + ((Antenna - 1) * 10) + + ((UCHAR)HTSetting.field.ShortGI * 160) + + ((UCHAR)MCS); + } + else if (HTSetting.field.BW == BW_80) { + rate_index = 192 + ((Antenna - 1) * 10) + + ((UCHAR)HTSetting.field.ShortGI * 160) + + ((UCHAR)MCS); + } + else if (HTSetting.field.BW == BW_160) { + rate_index = 232 + ((Antenna - 1) * 10) + + ((UCHAR)HTSetting.field.ShortGI * 160) + + ((UCHAR)MCS); + } + } + else +#endif /* DOT11_VHT_AC */ +#ifdef DOT11_N_SUPPORT + if (HTSetting.field.MODE >= MODE_HTMIX) + { + MCS = HTSetting.field.MCS; + if ((HTSetting.field.MODE == MODE_HTMIX) + || (HTSetting.field.MODE == MODE_HTGREENFIELD)) { + Antenna = (MCS >> 3)+1; + } + /* map back to 1SS MCS , multiply by antenna numbers later */ + if(MCS > 7) + MCS %= 8; + rate_index = 16 + ((UCHAR)HTSetting.field.BW *24) + ((UCHAR)HTSetting.field.ShortGI *48) + ((UCHAR)MCS); + } + else +#endif /* DOT11_N_SUPPORT */ + if (HTSetting.field.MODE == MODE_OFDM) + rate_index = getLegacyOFDMMCSIndex(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; + if(HTSetting.field.MODE != MODE_VHT) + value = (MCSMappingRateTable[rate_index] * 5)/10; + else + value = MCSMappingRateTable[rate_index]; + +#if defined(DOT11_VHT_AC) || defined(DOT11_N_SUPPORT) + if (HTSetting.field.MODE >= MODE_HTMIX && HTSetting.field.MODE < MODE_VHT) + value *= Antenna; +#endif /* DOT11_VHT_AC */ + + *fLastTxRxRate=(ULONG)value; + return; +} + +int set_mntr_rule(void *ad_obj, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + RTMP_ADAPTER *pAd; + POS_COOKIE pObj; + int Status = NDIS_STATUS_SUCCESS; + UINT8 new_rule; + pAd = (RTMP_ADAPTER *)ad_obj; + pObj = (POS_COOKIE) pAd->OS_Cookie; + + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("set_mntr_rule: ->\n")); + + new_rule = pAd->MntRuleBitMap; + + if (wrq->u.data.length != sizeof(UINT8)){ + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("set_mntr_rule: invalid payload size:%d\n",wrq->u.data.length )); + return -EINVAL; + } + + copy_from_user(&new_rule, wrq->u.data.pointer, wrq->u.data.length); + + if(new_rule == pAd->MntRuleBitMap){ + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("set_mntr_rule: already same rule : 0x%x\n",new_rule)); + return Status; + } + + pAd->MntRuleBitMap = new_rule; + + // assume no entry added yet + // todo: delete existing entries + + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("IF(ra%d) set_mntr_rule::(MntRuleBitMap=0x%x)\n", pObj->ioctl_if, pAd->MntRuleBitMap)); + + return Status; +} + + +VOID Air_Monitor_Pkt_Report_Action( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN RX_BLK *pRxBlk) +{ + UCHAR FrameBuf[512]; + AIR_RAW AirRaw; + UCHAR s_addr[MAC_ADDR_LEN]; + HTTRANSMIT_SETTING HTSetting; + UINT32 i; + PHEADER_802_11 pHeader = (PHEADER_802_11)pRxBlk->pHeader; + UCHAR Apidx = MAIN_MBSSID, Channel = 0; + UINT32 frame_len; + UINT32 offset=0; + struct sk_buff *skb = NULL; + MAC_TABLE_ENTRY *pMacEntry = &pAd->MacTab.Content[wcid]; + MNT_STA_ENTRY *pMntEntry=NULL; + UCHAR ETH_P_AIR_MONITOR[LENGTH_802_3_TYPE] = {0x51, 0xA0}; + + struct rxd_base_struct *rxd_base = (struct rxd_base_struct *)pRxBlk->rmac_info; + if(!rxd_base) + return; + Channel = rxd_base->rxd_1.ch_freq; + if (Channel == 0) + return; + + if(!pMacEntry) + return; + + pMntEntry = pAd->MntTable + pMacEntry->mnt_idx; + + if(!pMntEntry) + return; + + if (!pMntEntry->bValid) + return; + + switch(pHeader->FC.Type) + { + case FC_TYPE_MGMT: + if(pAd->MntRuleBitMap & RULE_MGT) + { + pMntEntry->mgmt_cnt++; + } + else + goto done; + break; + + case FC_TYPE_CNTL: + if(pAd->MntRuleBitMap & RULE_CTL) + { + pMntEntry->cntl_cnt++; + } + else + goto done; + break; + + case FC_TYPE_DATA: + if(pAd->MntRuleBitMap & RULE_DATA) + { + pMntEntry->data_cnt++; + } + else + goto done; + break; + + default: + goto done; + break; + } + pMntEntry->Count++; + + if(pHeader->FC.Type == FC_TYPE_DATA) + { + Update_Rssi_Sample(pAd, &pMntEntry->RssiSample, &pRxBlk->rx_signal, + pRxBlk->rx_rate.field.MODE, pRxBlk->rx_rate.field.BW); + } + else + { + Update_Rssi_Sample(pAd, &pMntEntry->RssiSample, &pRxBlk->rx_signal, + 0, pRxBlk->rx_rate.field.BW); + } + + /* Init frame buffer */ + NdisZeroMemory(FrameBuf, sizeof(FrameBuf)); + NdisZeroMemory(&AirRaw, sizeof(AirRaw)); + + /* Fake a Source Address for transmission */ + COPY_MAC_ADDR(s_addr, pAd->ApCfg.MBSSID[Apidx].wdev.if_addr); + if(s_addr[1] == 0xff) + s_addr[1]=0; + else + s_addr[1]++; + + /* Prepare the 802.3 header */ + MAKE_802_3_HEADER(FrameBuf, pAd->ApCfg.MBSSID[Apidx].wdev.if_addr, s_addr, ETH_P_AIR_MONITOR); + offset += LENGTH_802_3; + + /* For Rate Info */ + HTSetting.field.MODE = pRxBlk->rx_rate.field.MODE; + HTSetting.field.MCS = pRxBlk->rx_rate.field.MCS; + HTSetting.field.BW = pRxBlk->rx_rate.field.BW; + HTSetting.field.ShortGI = pRxBlk->rx_rate.field.ShortGI; + getRateNew(HTSetting, &AirRaw.wlan_radio_tap.RATE); + AirRaw.wlan_radio_tap.PHYMODE = pRxBlk->rx_rate.field.MODE; + AirRaw.wlan_radio_tap.MCS = pRxBlk->rx_rate.field.MCS; + AirRaw.wlan_radio_tap.BW = pRxBlk->rx_rate.field.BW; + AirRaw.wlan_radio_tap.ShortGI = pRxBlk->rx_rate.field.ShortGI; + + if(AirRaw.wlan_radio_tap.PHYMODE == MODE_OFDM) + { + AirRaw.wlan_radio_tap.MCS = getLegacyOFDMMCSIndex(pRxBlk->rx_rate.field.MCS); + } + /* For RSSI */ + for(i=0; iAntenna.field.RxPath; i++) + AirRaw.wlan_radio_tap.RSSI[i] = pMntEntry->RssiSample.AvgRssi[i]; + + AirRaw.wlan_radio_tap.Channel = Channel; + AirRaw.wlan_radio_tap.Channel = pAd->CommonCfg.Channel; + + /* For 802.11 Header */ + NdisMoveMemory(&AirRaw.wlan_header.FC, &pHeader->FC, sizeof(pHeader->FC)); + AirRaw.wlan_header.Duration = pHeader->Duration; + AirRaw.wlan_header.SN = pHeader->Sequence; + AirRaw.wlan_header.FN = pHeader->Frag; + COPY_MAC_ADDR(AirRaw.wlan_header.Addr1, pHeader->Addr1); + COPY_MAC_ADDR(AirRaw.wlan_header.Addr2, pHeader->Addr2); + COPY_MAC_ADDR(AirRaw.wlan_header.Addr3, pHeader->Addr3); + if(pHeader->FC.ToDs == 1 && pHeader->FC.FrDs == 1) + COPY_MAC_ADDR(AirRaw.wlan_header.Addr4, pHeader->Octet); + + /* Prepare payload*/ + NdisCopyMemory(&FrameBuf[offset], (CHAR*)&AirRaw, sizeof(AirRaw)); + offset += sizeof(AirRaw); + frame_len = offset; + /* Create skb */ + skb = dev_alloc_skb((frame_len + 2)); + if (!skb) { + printk("%s : Error! Can't allocate a skb.\n", __FUNCTION__); + return; + } + SET_OS_PKT_NETDEV(skb, pAd->ApCfg.MBSSID[Apidx].wdev.if_dev); + + /* 16 byte align the IP header */ + skb_reserve(skb, 2); + + /* Insert the frame content */ + NdisMoveMemory(GET_OS_PKT_DATAPTR(skb), FrameBuf, frame_len); + /* End this frame */ + skb_put(skb, frame_len); + + /* Report to upper layer */ + RtmpOsPktProtocolAssign(skb); + RtmpOsPktRcvHandle(skb); +#if defined(WAPP_SUPPORT) && defined(MAP_SUPPORT) + wapp_send_air_mnt_rssi(pAd, pMacEntry, pMntEntry); +#endif +done: + DBGPRINT(RT_DEBUG_TRACE,("%s : Done.\n", __FUNCTION__)); + return; +} + +BOOLEAN IsValidUnicastToMe(IN PRTMP_ADAPTER pAd, + IN UCHAR WCID, + IN PUCHAR pDA) +{ + BOOLEAN bUToMe = FALSE; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (!VALID_WCID(WCID)) + bUToMe = FALSE; + + if (MAC_ADDR_EQUAL(pDA, pAd->CurrentAddress)) + bUToMe = TRUE; + + if (!bUToMe) + { +#ifdef APCLI_SUPPORT + UINT index; + PAPCLI_STRUCT pApCliEntry = NULL; + for(index = 0; index < MAX_APCLI_NUM; index++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[index]; + if (pApCliEntry && + (pApCliEntry->Enable && pApCliEntry->Valid)) + { + if (MAC_ADDR_EQUAL(pApCliEntry->wdev.if_addr,pDA)) + { + bUToMe = TRUE; + break; + } + } + } + +#ifdef MAC_REPEATER_SUPPORT + if (!bUToMe && + (pAd->ApCfg.bMACRepeaterEn == TRUE) && + (RTMPQueryLookupRepeaterCliEntryMT(pAd, pDA) == TRUE)) + bUToMe = TRUE; +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* APCLI_SUPPORT */ + } + } +#endif /* CONFIG_AP_SUPPORT */ + + return bUToMe; +} + + +#endif /* AIR_MONITOR */ +#ifdef STA_FORCE_ROAM_SUPPORT +int handle_froam_query_cmd(RTMP_ADAPTER *pAd, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + int Status = NDIS_STATUS_SUCCESS; + + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + pfroam_command_hdr p_froam_cmd; + UCHAR ifIndex; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + if(wrq->u.data.length < sizeof(froam_command_hdr)) + return FALSE; + + p_froam_cmd = (pfroam_command_hdr)(wrq->u.data.pointer); + + switch(p_froam_cmd->command_id) + { + case OID_FROAM_CMD_FROAM_ENABLED: + { + pcmd_froam_en pthr_cmd = (pcmd_froam_en)(wrq->u.data.pointer); + + if(wrq->u.data.length >= sizeof(cmd_froam_en)){ + pthr_cmd->froam_en = pAd->en_force_roam_supp; + pthr_cmd->channel = pAd->ApCfg.MBSSID[ifIndex].wdev.channel; + + DBGPRINT(RT_DEBUG_TRACE, + ("Query OID_FROAM_CMD_FROAM_ENABLED => FroamEn:%d IntfChannel: %d\n", + pthr_cmd->froam_en, pthr_cmd->channel)); + } + else + DBGPRINT(RT_DEBUG_TRACE, + ("Query OID_FROAM_CMD_FROAM_ENABLED Invalid length\n")); + + break; + } + + case OID_FROAM_CMD_GET_THRESHOLD: + { + pcmd_threshold pthr_cmd = (pcmd_threshold)(wrq->u.data.pointer); + DBGPRINT(RT_DEBUG_TRACE, + ("Query OID_FROAM_CMD_GET_THRESHOLD\n")); + + if(pAd->en_force_roam_supp){ + if(wrq->u.data.length >= sizeof(cmd_threshold)){ + pthr_cmd->info.sta_ageout_time = pAd->sta_age_time; + pthr_cmd->info.mntr_ageout_time = pAd->mntr_age_time; + pthr_cmd->info.mntr_min_pkt_count = pAd->mntr_min_pkt_count; + pthr_cmd->info.mntr_min_time = pAd->mntr_min_time; + pthr_cmd->info.mntr_avg_rssi_pkt_count = pAd->mntr_avg_rssi_pkt_count; + pthr_cmd->info.sta_detect_rssi_threshold = pAd->sta_good_rssi; + pthr_cmd->info.acl_ageout_time = pAd->acl_age_time; + pthr_cmd->info.acl_hold_time = pAd->acl_hold_time; + } + } + else + Status = -EOPNOTSUPP; + + break; + } + default: + DBGPRINT(RT_DEBUG_TRACE, + ("Query::unknown IOCTL's subcmd = 0x%08x, IFidx=%d\n", p_froam_cmd->command_id, ifIndex)); + Status = -EOPNOTSUPP; + break; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("OID_FROAM_COMMAND Status : %d\n", Status)); + + return Status; + +} + +void froam_notify_sta_disconnect(void *ad_obj, void *pEntry) +{ + froam_event_sta_disconn event_data; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ad_obj; + MAC_TABLE_ENTRY *pMacEntry = (MAC_TABLE_ENTRY *)pEntry; + + DBGPRINT(RT_DEBUG_TRACE,("issue FROAM_EVT_STA_DISCONNECT -> \n")); + + memset(&event_data,0,sizeof(event_data)); + + event_data.hdr.event_id = FROAM_EVT_STA_DISCONNECT; + event_data.hdr.event_len = sizeof(froam_event_sta_disconn) - sizeof(froam_event_hdr); + + memcpy(event_data.mac,pMacEntry->Addr,MAC_ADDR_LEN); + + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_FROAM_EVENT, + NULL, + (UCHAR *) &event_data, + sizeof(event_data)); + + pMacEntry->low_rssi_notified = FALSE; + pMacEntry->tick_sec = 0; + DBGPRINT(RT_DEBUG_TRACE,("Froam event sent <- \n")); +} + +void notify_force_roam_supp(RTMP_ADAPTER *pAd) +{ + froam_event_param_cfg cfg_event; + + DBGPRINT(RT_DEBUG_TRACE,("issue FROAM_EVT_FROAM_SUPP -> \n")); + + memset(&cfg_event,0,sizeof(cfg_event)); + + cfg_event.hdr.event_id = FROAM_EVT_FROAM_SUPP; + cfg_event.hdr.event_len = sizeof(froam_event_param_cfg) - sizeof(froam_event_hdr); + + cfg_event.value = pAd->en_force_roam_supp; + + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_FROAM_EVENT, + NULL, + (UCHAR *) &cfg_event, + sizeof(cfg_event)); + + DBGPRINT(RT_DEBUG_TRACE,("Froam event sent <- \n")); +} + +void froam_notify_sta_age_time(RTMP_ADAPTER *pAd) +{ + froam_event_param_cfg cfg_event; + + DBGPRINT(RT_DEBUG_TRACE,("issue FROAM_EVT_STA_AGEOUT_TIME -> \n")); + + memset(&cfg_event,0,sizeof(cfg_event)); + + cfg_event.hdr.event_id = FROAM_EVT_STA_AGEOUT_TIME; + cfg_event.hdr.event_len = sizeof(froam_event_param_cfg) - sizeof(froam_event_hdr); + + cfg_event.value = pAd->sta_age_time; + + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_FROAM_EVENT, + NULL, + (UCHAR *) &cfg_event, + sizeof(cfg_event)); + + DBGPRINT(RT_DEBUG_TRACE,("Froam event sent <- \n")); +} + +void froam_notify_mntr_age_time(RTMP_ADAPTER *pAd) +{ + froam_event_param_cfg cfg_event; + + DBGPRINT(RT_DEBUG_TRACE,("issue FROAM_EVT_MNTR_AGEOUT_TIME -> \n")); + + memset(&cfg_event,0,sizeof(cfg_event)); + + cfg_event.hdr.event_id = FROAM_EVT_MNTR_AGEOUT_TIME; + cfg_event.hdr.event_len = sizeof(froam_event_param_cfg) - sizeof(froam_event_hdr); + + cfg_event.value = pAd->mntr_age_time; + + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_FROAM_EVENT, + NULL, + (UCHAR *) &cfg_event, + sizeof(cfg_event)); + + DBGPRINT(RT_DEBUG_TRACE,("Froam event sent <- \n")); +} + +void froam_notify_mntr_min_pkt_count(RTMP_ADAPTER *pAd) +{ + froam_event_param_cfg cfg_event; + + DBGPRINT(RT_DEBUG_TRACE,("issue FROAM_EVT_MNTR_MIN_PKT_COUNT -> \n")); + + memset(&cfg_event,0,sizeof(cfg_event)); + + cfg_event.hdr.event_id = FROAM_EVT_MNTR_MIN_PKT_COUNT; + cfg_event.hdr.event_len = sizeof(froam_event_param_cfg) - sizeof(froam_event_hdr); + + cfg_event.value = pAd->mntr_min_pkt_count; + + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_FROAM_EVENT, + NULL, + (UCHAR *) &cfg_event, + sizeof(cfg_event)); + + DBGPRINT(RT_DEBUG_TRACE,("Froam event sent <- \n")); +} + +void froam_notify_mntr_min_time(RTMP_ADAPTER *pAd) +{ + froam_event_param_cfg cfg_event; + + DBGPRINT(RT_DEBUG_TRACE,("issue FROAM_EVT_MNTR_MIN_TIME -> \n")); + + memset(&cfg_event,0,sizeof(cfg_event)); + + cfg_event.hdr.event_id = FROAM_EVT_MNTR_MIN_TIME; + cfg_event.hdr.event_len = sizeof(froam_event_param_cfg) - sizeof(froam_event_hdr); + + cfg_event.value = pAd->mntr_min_time; + + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_FROAM_EVENT, + NULL, + (UCHAR *) &cfg_event, + sizeof(cfg_event)); + + DBGPRINT(RT_DEBUG_TRACE,("Froam event sent <- \n")); +} + +void froam_notify_mntr_avg_rssi_pkt_count(RTMP_ADAPTER *pAd) +{ + froam_event_param_cfg cfg_event; + + DBGPRINT(RT_DEBUG_TRACE,("issue FROAM_EVT_STA_AVG_RSSI_PKT_COUNT -> \n")); + + memset(&cfg_event,0,sizeof(cfg_event)); + + cfg_event.hdr.event_id = FROAM_EVT_STA_AVG_RSSI_PKT_COUNT; + cfg_event.hdr.event_len = sizeof(froam_event_param_cfg) - sizeof(froam_event_hdr); + + cfg_event.value = pAd->mntr_avg_rssi_pkt_count; + + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_FROAM_EVENT, + NULL, + (UCHAR *) &cfg_event, + sizeof(cfg_event)); + + DBGPRINT(RT_DEBUG_TRACE,("Froam event sent <- \n")); +} + +void froam_notify_sta_good_rssi(RTMP_ADAPTER *pAd) +{ + froam_event_param_cfg cfg_event; + + DBGPRINT(RT_DEBUG_TRACE,("issue FROAM_EVT_STA_DETECT_RSSI_THRESHOLD -> \n")); + + memset(&cfg_event,0,sizeof(cfg_event)); + + cfg_event.hdr.event_id = FROAM_EVT_STA_DETECT_RSSI_THRESHOLD; + cfg_event.hdr.event_len = sizeof(froam_event_param_cfg) - sizeof(froam_event_hdr); + + cfg_event.value = pAd->sta_good_rssi; + + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_FROAM_EVENT, + NULL, + (UCHAR *) &cfg_event, + sizeof(cfg_event)); + + DBGPRINT(RT_DEBUG_TRACE,("Froam event sent <- \n")); +} + +void froam_notify_acl_age_time(RTMP_ADAPTER *pAd) +{ + froam_event_param_cfg cfg_event; + + DBGPRINT(RT_DEBUG_TRACE,("issue FROAM_EVT_ACL_AGEOUT_TIME -> \n")); + + memset(&cfg_event,0,sizeof(cfg_event)); + + cfg_event.hdr.event_id = FROAM_EVT_ACL_AGEOUT_TIME; + cfg_event.hdr.event_len = sizeof(froam_event_param_cfg) - sizeof(froam_event_hdr); + + cfg_event.value = pAd->acl_age_time; + + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_FROAM_EVENT, + NULL, + (UCHAR *) &cfg_event, + sizeof(cfg_event)); + + DBGPRINT(RT_DEBUG_TRACE,("Froam event sent <- \n")); +} + +void froam_notify_acl_hold_time(RTMP_ADAPTER *pAd) +{ + froam_event_param_cfg cfg_event; + + DBGPRINT(RT_DEBUG_TRACE,("issue FROAM_EVT_ACL_HOLD_TIME -> \n")); + + memset(&cfg_event,0,sizeof(cfg_event)); + + cfg_event.hdr.event_id = FROAM_EVT_ACL_HOLD_TIME; + cfg_event.hdr.event_len = sizeof(froam_event_param_cfg) - sizeof(froam_event_hdr); + + cfg_event.value = pAd->acl_hold_time; + + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_FROAM_EVENT, + NULL, + (UCHAR *) &cfg_event, + sizeof(cfg_event)); + + DBGPRINT(RT_DEBUG_TRACE,("Froam event sent <- \n")); +} + +INT Set_FroamEn( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + POS_COOKIE pObj; + UCHAR apidx; +#endif + //struct _ez_security *ez_sec_info; + UINT8 en_force_roam_supp; + +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; +#endif + en_force_roam_supp = simple_strtol(arg, 0, 10); + + // validation + if((en_force_roam_supp !=0) && (en_force_roam_supp != 1)){ + DBGPRINT(RT_DEBUG_TRACE, + ("------> %s(): Error: Invalid value : %d\n", __FUNCTION__,en_force_roam_supp)); + return FALSE; + } + + pAd->en_force_roam_supp = en_force_roam_supp; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): ForceRoamEn : %d\n", __FUNCTION__,en_force_roam_supp)); + + notify_force_roam_supp(pAd); + + return TRUE; +} + +INT Set_FroamStaLowRssi( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + POS_COOKIE pObj; + UCHAR apidx; +#endif + //struct _ez_security *ez_sec_info; + CHAR sta_low_rssi; + +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; +#endif + sta_low_rssi = simple_strtol(arg, 0, 10); + + // validation + if( !((sta_low_rssi >=0) && (sta_low_rssi <= 127)) ){ + DBGPRINT(RT_DEBUG_TRACE, + ("------> %s(): Error: Invalid value : %d\n", __FUNCTION__,sta_low_rssi)); + return FALSE; + } + + sta_low_rssi = (-1) * sta_low_rssi; + + pAd->sta_low_rssi = sta_low_rssi; + printk + ("%s(): sta_low_rssi : %d\n", __FUNCTION__,sta_low_rssi); + + return TRUE; +} + +INT Set_FroamStaLowRssiRenotify( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + POS_COOKIE pObj; + UCHAR apidx; +#endif + //struct _ez_security *ez_sec_info; + UINT8 sta_renotify; + +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; +#endif + sta_renotify = simple_strtol(arg, 0, 10); + + // validation todo: define max range + + pAd->low_sta_renotify = sta_renotify; + printk + ("%s(): sta_renotify : %d\n", __FUNCTION__,sta_renotify); + + return TRUE; +} + +INT Set_FroamStaAgeTime( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + POS_COOKIE pObj; + UCHAR apidx; +#endif + //struct _ez_security *ez_sec_info; + UINT8 sta_age_time; + +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; +#endif + sta_age_time = simple_strtol(arg, 0, 10); + + // validation todo: define max range + // check against low_sta_renotify ?? + + pAd->sta_age_time = sta_age_time; + printk("%s(): sta_age_time : %d\n", __FUNCTION__,sta_age_time); + + if(pAd->en_force_roam_supp) + froam_notify_sta_age_time(pAd); + + return TRUE; +} + +INT Set_FroamMntrAgeTime( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + POS_COOKIE pObj; + UCHAR apidx; +#endif + //struct _ez_security *ez_sec_info; + UINT8 mntr_age_time; + +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; +#endif + mntr_age_time = simple_strtol(arg, 0, 10); + + // validation todo: define max range + // check against low_sta_renotify ?? + + pAd->mntr_age_time = mntr_age_time; + printk + ("%s(): mntr_age_time : %d\n", __FUNCTION__,mntr_age_time); + + if(pAd->en_force_roam_supp) + froam_notify_mntr_age_time(pAd); + + return TRUE; +} + +INT Set_FroamMntrMinPktCount( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + POS_COOKIE pObj; + UCHAR apidx; +#endif + //struct _ez_security *ez_sec_info; + UINT8 mntr_min_pkt_count; + +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; +#endif + mntr_min_pkt_count = simple_strtol(arg, 0, 10); + + // validation + if(!((mntr_min_pkt_count >=1) && (mntr_min_pkt_count <= 5))){ + DBGPRINT(RT_DEBUG_TRACE, + ("------> %s(): Error: Invalid value : %d\n", __FUNCTION__,mntr_min_pkt_count)); + return FALSE; + } + + pAd->mntr_min_pkt_count = mntr_min_pkt_count; + printk("%s(): mntr_min_pkt_count : %d\n", __FUNCTION__,mntr_min_pkt_count); + + if(pAd->en_force_roam_supp) + froam_notify_mntr_min_pkt_count(pAd); + + return TRUE; +} + +INT Set_FroamMntrMinTime( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + POS_COOKIE pObj; + UCHAR apidx; +#endif + //struct _ez_security *ez_sec_info; + UINT8 mntr_min_time; + +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; +#endif + mntr_min_time = simple_strtol(arg, 0, 10); + + // validation todo: define max range + // check against mntr_age_time ?? + + pAd->mntr_min_time = mntr_min_time; + printk("%s(): mntr_min_time : %d\n", __FUNCTION__,mntr_min_time); + + if(pAd->en_force_roam_supp) + froam_notify_mntr_min_time(pAd); + + return TRUE; +} + +INT Set_FroamMntrRssiPktCount( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + POS_COOKIE pObj; + UCHAR apidx; +#endif + //struct _ez_security *ez_sec_info; + UINT8 mntr_avg_rssi_pkt_count; + +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; +#endif + mntr_avg_rssi_pkt_count = simple_strtol(arg, 0, 10); + + // validation + if(!((mntr_avg_rssi_pkt_count >=1) && (mntr_avg_rssi_pkt_count <= 5))){ + DBGPRINT(RT_DEBUG_TRACE, + ("------> %s(): Error: Invalid value : %d\n", __FUNCTION__,mntr_avg_rssi_pkt_count)); + return FALSE; + } + + pAd->mntr_avg_rssi_pkt_count = mntr_avg_rssi_pkt_count; + printk("%s(): mntr_avg_rssi_pkt_count : %d\n", __FUNCTION__,mntr_avg_rssi_pkt_count); + + if(pAd->en_force_roam_supp) + froam_notify_mntr_avg_rssi_pkt_count(pAd); + + return TRUE; +} + +INT Set_FroamStaGoodRssi( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + POS_COOKIE pObj; + UCHAR apidx; +#endif + //struct _ez_security *ez_sec_info; + CHAR sta_good_rssi; + +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; +#endif + sta_good_rssi = simple_strtol(arg, 0, 10); + + // validation + if( !((sta_good_rssi >=0) && (sta_good_rssi <= 127)) ){ + DBGPRINT(RT_DEBUG_TRACE, + ("------> %s(): Error: Invalid value : %d\n", __FUNCTION__,sta_good_rssi)); + return FALSE; + } + + sta_good_rssi = (-1) * sta_good_rssi; + + pAd->sta_good_rssi = sta_good_rssi; + printk("%s(): sta_good_rssi : %d\n", __FUNCTION__,sta_good_rssi); + + if(pAd->en_force_roam_supp) + froam_notify_sta_good_rssi(pAd); + + return TRUE; +} + +INT Set_FroamAclAgeTime( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + POS_COOKIE pObj; + UCHAR apidx; +#endif + //struct _ez_security *ez_sec_info; + UINT8 acl_age_time; + +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; +#endif + acl_age_time = simple_strtol(arg, 0, 10); + + // validation todo: define max range + + pAd->acl_age_time = acl_age_time; + printk("%s(): acl_age_time : %d\n", __FUNCTION__,acl_age_time); + + if(pAd->en_force_roam_supp) + froam_notify_acl_age_time(pAd); + + return TRUE; +} + +INT Set_FroamAclHoldTime( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + POS_COOKIE pObj; + UCHAR apidx; +#endif + //struct _ez_security *ez_sec_info; + UINT8 acl_hold_time; + +#if defined(WH_EZ_SETUP) && defined(DUAL_CHIP) + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; +#endif + acl_hold_time = simple_strtol(arg, 0, 10); + + // validation todo: define max range + // check against (low_sta_renotify - mntr_min_time) ?? + + pAd->acl_hold_time = acl_hold_time; + printk("%s(): acl_hold_time : %d\n", __FUNCTION__,acl_hold_time); + + if(pAd->en_force_roam_supp) + froam_notify_acl_hold_time(pAd); + + return TRUE; +} + +#endif + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_connect.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_connect.c new file mode 100644 index 000000000..0c7565b84 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_connect.c @@ -0,0 +1,1890 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + connect.c + + Abstract: + Routines to deal Link UP/DOWN and build/update BEACON frame contents + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 08-04-2003 created for 11g soft-AP + */ + +#include "rt_config.h" + +UCHAR PowerConstraintIE[3] = {IE_POWER_CONSTRAINT, 1, 3}; + + +/* + ========================================================================== + Description: + Used to check the necessary to send Beancon. + return value + 0: mean no necessary. + 0: mean need to send Beacon for the service. + ========================================================================== +*/ +BOOLEAN BeaconTransmitRequired(RTMP_ADAPTER *pAd, INT apidx, BSS_STRUCT *pMbss) +{ +#ifdef WDS_SUPPORT + UCHAR idx; +#endif /* WDS_SUPPORT */ + BOOLEAN result = FALSE; + BCN_BUF_STRUC *bcn_info; + + do + { +#ifdef WDS_SUPPORT + if (pAd->WdsTab.Mode == WDS_BRIDGE_MODE) + break; +#endif /* WDS_SUPPORT */ + +#ifdef CARRIER_DETECTION_SUPPORT + if (isCarrierDetectExist(pAd) == TRUE) + break; +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT +#ifdef QUIET_SUPPORT + if ((apidx < pAd->ApCfg.BssidNum) && IS_RRM_QUIET(pAd, apidx)) + break; +#endif /* QUIET_SUPPORT */ +#endif /* DOT11K_RRM_SUPPORT */ + + bcn_info = &pMbss->bcn_buf; + if (bcn_info->BcnBufIdx >= HW_BEACON_MAX_NUM) + break; + + if (apidx == MAIN_MBSSID) + { + if (bcn_info->bBcnSntReq == TRUE) + { + result = TRUE; + break; + } + +#ifdef WDS_SUPPORT + for (idx = 0; idx < MAX_WDS_ENTRY; idx++) + { + if ((pAd->WdsTab.WdsEntry[idx].wdev.if_dev != NULL) + && (RTMP_OS_NETDEV_STATE_RUNNING(pAd->WdsTab.WdsEntry[idx].wdev.if_dev))) + { + result = TRUE; + break; + } + } +#endif /* WDS_SUPPORT */ + } + else + { + if (bcn_info->bBcnSntReq == TRUE) + result = TRUE; + } + } + while (FALSE); + + return result; +} + + +#ifdef MT_MAC +VOID write_tmac_info_beacon(RTMP_ADAPTER *pAd, INT apidx, UCHAR *tmac_buf, HTTRANSMIT_SETTING *BeaconTransmit, ULONG frmLen) +{ + MAC_TX_INFO mac_info; + + NdisZeroMemory((UCHAR *)&mac_info, sizeof(mac_info)); + + mac_info.FRAG = FALSE; + mac_info.CFACK = FALSE; + mac_info.InsTimestamp = TRUE; + mac_info.AMPDU = FALSE; + mac_info.BM = 1; + mac_info.Ack = FALSE; + mac_info.NSeq = TRUE; + mac_info.BASize = 0; + mac_info.WCID = 0; + mac_info.Length = frmLen; + mac_info.TID = 0; + mac_info.TxRate = 0; + mac_info.Txopmode = IFS_HTTXOP; +#ifdef MT_MAC + mac_info.q_idx = Q_IDX_BCN; + mac_info.TxSPriv = apidx; +#endif /* MT_MAC */ + mac_info.hdr_len = 24; + mac_info.bss_idx = apidx; + mac_info.SpeEn = 1; + mac_info.Preamble = LONG_PREAMBLE; + NdisZeroMemory(tmac_buf, sizeof(TMAC_TXD_L)); + write_tmac_info(pAd, tmac_buf, &mac_info, BeaconTransmit); +} + + +VOID asic_write_bcn_buf(RTMP_ADAPTER *pAd, UCHAR *tmac_info, INT info_len, UCHAR *bcn_buf, INT buf_len, UINT32 hw_addr) +{ +#ifdef RT_BIG_ENDIAN + UCHAR *ptr; +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (pAd->chipCap.hif_type == HIF_RTMP || pAd->chipCap.hif_type == HIF_RLT) + { + RTMPWIEndianChange(pAd, tmac_info, TYPE_TXWI); + } +#endif +#endif + /* update BEACON frame content. start right after the TXWI field. */ +#ifdef RT_BIG_ENDIAN + ptr = bcn_buf; + + RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); +#endif + + // TODO: shiang-MT7603, Send to ASIC! + +} +#endif /* MT_MAC */ + + +#if defined(RTMP_MAC) || defined(RLT_MAC) +VOID write_tmac_info_beacon(RTMP_ADAPTER *pAd, INT apidx, UCHAR *tmac_buf, HTTRANSMIT_SETTING *BeaconTransmit, ULONG frmLen) +{ + MAC_TX_INFO mac_info; + + NdisZeroMemory((UCHAR *)&mac_info, sizeof(mac_info)); + + mac_info.FRAG = FALSE; + mac_info.CFACK = FALSE; + mac_info.InsTimestamp = TRUE; + mac_info.AMPDU = FALSE; + mac_info.BM = 1; + mac_info.Ack = FALSE; + mac_info.NSeq = TRUE; + mac_info.BASize = 0; + mac_info.WCID = RESERVED_WCID; + mac_info.Length = frmLen; + mac_info.PID = PID_MGMT; + mac_info.TID = 0; + mac_info.TxRate = 0; + mac_info.Txopmode = IFS_HTTXOP; + mac_info.Preamble = LONG_PREAMBLE; + write_tmac_info(pAd, tmac_buf, &mac_info, BeaconTransmit); + +#ifdef SPECIFIC_TX_POWER_SUPPORT + /* Specific Power for Long-Range Beacon */ + if ((pAd->ApCfg.MBSSID[apidx].TxPwrAdj != -1) && + (BeaconTransmit->field.MODE == MODE_CCK)) + { + UCHAR TxPwrAdj = 0; + TXWI_STRUC *pTxWI = (TXWI_STRUC *)tmac_buf; + + TxPwrAdj = pAd->ApCfg.MBSSID[apidx].TxPwrAdj; +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + pTxWI->TXWI_O.TxPwrAdj = TxPwrAdj; +#endif /* RTMP_MAC */ +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + pTxWI->TXWI_N.TxPwrAdj = TxPwrAdj; +#endif /* RLT_MAC */ + } +#endif /* SPECIFIC_TX_POWER_SUPPORT */ +} + + +VOID asic_write_bcn_buf(RTMP_ADAPTER *pAd, UCHAR *tmac_info, INT info_len, UCHAR *bcn_buf, INT buf_len, UINT32 hw_addr) +{ + INT i; + UCHAR *ptr = tmac_info; + UINT32 longValue, reg_base = hw_addr; + +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, tmac_info, TYPE_TXWI); +#endif + + for (i = 0; i < info_len; i += 4) + { + longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); + RTMP_CHIP_UPDATE_BEACON(pAd, reg_base + i, longValue, 4); + ptr += 4; + } + + /* update BEACON frame content. start right after the TXWI field. */ + ptr = bcn_buf; +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); +#endif + + reg_base = hw_addr + info_len; + for (i= 0; i< buf_len; i+=4) + { + longValue = *ptr + (*(ptr+1)<<8) + (*(ptr+2)<<16) + (*(ptr+3)<<24); + RTMP_CHIP_UPDATE_BEACON(pAd, reg_base + i, longValue, 4); + ptr += 4; + } + +} +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + +/* + ========================================================================== + Description: + Pre-build a BEACON frame in the shared memory + ========================================================================== +*/ +VOID APMakeBssBeacon(RTMP_ADAPTER *pAd, INT apidx) +{ + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; + UCHAR DsLen = 1, SsidLen; + HEADER_802_11 BcnHdr; + LARGE_INTEGER FakeTimestamp; + ULONG FrameLen = 0; + UCHAR *pBeaconFrame, *tmac_info; +#if defined(DOT11_N_SUPPORT) && defined(DOT11K_RRM_SUPPORT) + UINT i; +#endif /* defined(DOT11_N_SUPPORT) && defined(DOT11K_RRM_SUPPORT) */ + HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at HT rate. */ + UCHAR PhyMode, SupRateLen; + UINT8 TXWISize = pAd->chipCap.TXWISize; + UINT8 tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len; + UCHAR Environment = 0x20; + struct wifi_dev *wdev; + + wdev = &pMbss->wdev; + if(!BeaconTransmitRequired(pAd, apidx, pMbss)) + return; + + if (pMbss->bcn_buf.BeaconPkt == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Invalid BeaconPkt for MBSS[%d]\n", + __FUNCTION__, apidx)); + return; + } + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + return; +//Carter, 20140306 for MT7603, merge MakeAllBeacon into UpdateAllBeacon + } +#endif + tmac_info = (UCHAR *)GET_OS_PKT_DATAPTR(pMbss->bcn_buf.BeaconPkt); + if (pAd->chipCap.hif_type == HIF_MT) + { + pBeaconFrame = (UCHAR *)(tmac_info + tx_hw_hdr_len); + } + else + { + pBeaconFrame = (UCHAR *)(tmac_info + TXWISize); + } + + PhyMode = pMbss->wdev.PhyMode; + SsidLen = (pMbss->bHideSsid) ? 0 : pMbss->SsidLen; + MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, + 0, BROADCAST_ADDR, + pMbss->wdev.if_addr, + pMbss->wdev.bssid); + + /* for update framelen to TxWI later. */ +#ifdef DYNAMIC_RX_RATE_ADJ + SupRateLen = pAd->ApCfg.MBSSID[apidx].SupRateLen; +#else + SupRateLen = pAd->CommonCfg.SupRateLen; +#endif /* DYNAMIC_RX_RATE_ADJ */ + + if (PhyMode == WMODE_B) + SupRateLen = 4; + + MakeOutgoingFrame(pBeaconFrame, &FrameLen, + sizeof(HEADER_802_11), &BcnHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &pMbss->CapabilityInfo, + 1, &SsidIe, + 1, &SsidLen, + SsidLen, pMbss->Ssid, + 1, &SupRateIe, + 1, &SupRateLen, +#ifdef DYNAMIC_RX_RATE_ADJ + SupRateLen, &pAd->ApCfg.MBSSID[apidx].SupRate, +#else + SupRateLen, pAd->CommonCfg.SupRate, +#endif /* DYNAMIC_RX_RATE_ADJ */ + 1, &DsIe, + 1, &DsLen, + 1, &pAd->CommonCfg.Channel, + END_OF_ARGS); + +#ifdef DYNAMIC_RX_RATE_ADJ + if ((pAd->ApCfg.MBSSID[apidx].ExtRateLen) && (PhyMode != WMODE_B)) +#else + if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != WMODE_B)) +#endif /* DYNAMIC_RX_RATE_ADJ */ + { + ULONG TmpLen; + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &ExtRateIe, +#ifdef DYNAMIC_RX_RATE_ADJ + 1, &pAd->ApCfg.MBSSID[apidx].ExtRateLen, + pAd->ApCfg.MBSSID[apidx].ExtRateLen, pAd->ApCfg.MBSSID[apidx].ExtRate, +#else + 1, &pAd->CommonCfg.ExtRateLen, + pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, +#endif /* DYNAMIC_RX_RATE_ADJ */ + END_OF_ARGS); + FrameLen += TmpLen; + } + + + /* add country IE, power constraint IE */ + if (pAd->CommonCfg.bCountryFlag) + { + ULONG TmpLen, TmpLen2=0; + UCHAR *TmpFrame = NULL; + UCHAR CountryIe = IE_COUNTRY; + + os_alloc_mem(NULL, (UCHAR **)&TmpFrame, 256); + if (TmpFrame != NULL) + { + NdisZeroMemory(TmpFrame, 256); + + /* prepare channel information */ +#ifdef EXT_BUILD_CHANNEL_LIST + BuildBeaconChList(pAd, TmpFrame, &TmpLen2); +#else + { + UCHAR MaxTxPower = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); + MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, + 1, &pAd->ChannelList[0].Channel, + 1, &pAd->ChannelListNum, + 1, &MaxTxPower, + END_OF_ARGS); + TmpLen2 += TmpLen; + } +#endif /* EXT_BUILD_CHANNEL_LIST */ + +#ifdef DOT11K_RRM_SUPPORT + if (IS_RRM_ENABLE(pAd, apidx) + && (pAd->CommonCfg.RegulatoryClass[0] != 0)) + { + TmpLen2 = 0; + NdisZeroMemory(TmpFrame, 256); + RguClass_BuildBcnChList(pAd, TmpFrame, &TmpLen2); + } +#endif /* DOT11K_RRM_SUPPORT */ +#ifdef MBO_SUPPORT + if (IS_MBO_ENABLE(wdev)) + Environment = MBO_AP_USE_GLOBAL_OPERATING_CLASS; +#endif/* MBO_SUPPORT */ + /* need to do the padding bit check, and concatenate it */ + if ((TmpLen2%2) == 0) + { + UCHAR TmpLen3 = TmpLen2+4; + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &CountryIe, + 1, &TmpLen3, + 1, &pAd->CommonCfg.CountryCode[0], + 1, &pAd->CommonCfg.CountryCode[1], + 1, &Environment, + TmpLen2+1, TmpFrame, + END_OF_ARGS); + } else { + UCHAR TmpLen3 = TmpLen2 + 3; + + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + 1, &CountryIe, + 1, &TmpLen3, + 1, &pAd->CommonCfg.CountryCode[0], + 1, &pAd->CommonCfg.CountryCode[1], + 1, &Environment, + TmpLen2, TmpFrame, + END_OF_ARGS); + } + FrameLen += TmpLen; + + os_free_mem(NULL, TmpFrame); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + } + +#ifdef DOT11K_RRM_SUPPORT + if (IS_RRM_ENABLE(pAd, apidx)) + { + InsertTpcReportIE(pAd, pBeaconFrame+FrameLen, &FrameLen, + RTMP_GetTxPwr(pAd, pAd->CommonCfg.MlmeTransmit), 0); + RRM_InsertRRMEnCapIE(pAd, pBeaconFrame+FrameLen, &FrameLen, apidx); + } +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + /* AP Channel Report */ +#ifdef DOT11K_RRM_SUPPORT + for (i=0; iCommonCfg.RegulatoryClass[i] == 0) + break; + + InsertChannelRepIE(pAd, pBeaconFrame+FrameLen, &FrameLen, + (RTMP_STRING *)pAd->CommonCfg.CountryCode, + pAd->CommonCfg.RegulatoryClass[i], NULL); + + } +#else + { + UCHAR APChannelReportIe = IE_AP_CHANNEL_REPORT; + ULONG TmpLen; + + /* + 802.11n D2.0 Annex J, USA regulatory + class 32, channel set 1~7 + class 33, channel set 5-11 + */ + UCHAR rclass32[]={32, 1, 2, 3, 4, 5, 6, 7}; + UCHAR rclass33[]={33, 5, 6, 7, 8, 9, 10, 11}; + UCHAR rclasslen = 8; /*sizeof(rclass32); */ + if (PhyMode == (WMODE_B | WMODE_G | WMODE_GN)) + { + MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, + 1, &APChannelReportIe, + 1, &rclasslen, + rclasslen, rclass32, + 1, &APChannelReportIe, + 1, &rclasslen, + rclasslen, rclass33, + END_OF_ARGS); + FrameLen += TmpLen; + } + } +#endif + +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + /* + The Mobility Domain information element (MDIE) is present in Beacon + frame when dot11FastBssTransitionEnable is set to true. + */ + if (pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable) + { + PFT_CFG pFtCfg = &pAd->ApCfg.MBSSID[apidx].FtCfg; + FT_CAP_AND_POLICY FtCap; + NdisZeroMemory(&FtCap, sizeof(FT_CAP_AND_POLICY)); + FtCap.field.FtOverDs = pFtCfg->FtCapFlag.FtOverDs; + FtCap.field.RsrReqCap = pFtCfg->FtCapFlag.RsrReqCap; + FT_InsertMdIE(pAd, pBeaconFrame + FrameLen, &FrameLen, + pFtCfg->FtMdId, FtCap); + } +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#if defined(WH_EZ_SETUP) || defined(CONFIG_OWE_SUPPORT) + + /* add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back */ + FrameLen += build_vendor_ie(pAd, &pAd->ApCfg.MBSSID[apidx].wdev, (pBeaconFrame + FrameLen) +#ifdef CONFIG_OWE_SUPPORT + , VIE_BEACON +#endif +#ifdef WH_EZ_SETUP +, SUBTYPE_BEACON +#endif +); +#endif +#endif /*CONFIG_AP_SUPPORT*/ + BeaconTransmit.word = 0; +#ifdef MBO_SUPPORT + if (IS_MBO_ENABLE(wdev)) + MakeMboOceIE(pAd, wdev, pBeaconFrame+FrameLen, &FrameLen, MBO_FRAME_TYPE_BEACON); +#endif/* MBO_SUPPORT */ + + write_tmac_info_beacon(pAd, apidx, tmac_info, &BeaconTransmit, FrameLen); + + /* step 6. move BEACON TXD and frame content to on-chip memory */ + asic_write_bcn_buf(pAd, + tmac_info, TXWISize, + pBeaconFrame, FrameLen, + pAd->BeaconOffset[pMbss->bcn_buf.BcnBufIdx]); + + pMbss->TimIELocationInBeacon = (UCHAR)FrameLen; + pMbss->bcn_buf.cap_ie_pos = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; + + //pMbss->bcn_buf.bcn_state = BCN_TX_IDLE; +//+++Add by shiang for debug +//---Add by shiang for debug +} + + +/* + ========================================================================== + Description: + Update the BEACON frame in the shared memory. Because TIM IE is variable + length. other IEs after TIM has to shift and total frame length may change + for each BEACON period. + Output: + pAd->ApCfg.MBSSID[apidx].CapabilityInfo + pAd->ApCfg.ErpIeContent + ========================================================================== +*/ +VOID APUpdateBeaconFrame(RTMP_ADAPTER *pAd, INT apidx) +{ + UCHAR *pBeaconFrame, *tmac_info; + UCHAR *ptr; + ULONG FrameLen = 0; + ULONG UpdatePos = 0; + UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; + UCHAR ID_1B, TimFirst, TimLast, *pTim; + BSS_STRUCT *pMbss; + COMMON_CONFIG *pComCfg; + BOOLEAN bHasWpsIE = FALSE; + UINT i; + HTTRANSMIT_SETTING BeaconTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at Ht rate. */ + struct wifi_dev *wdev; + UCHAR tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len; + UINT8 TXWISize = pAd->chipCap.TXWISize; + + UCHAR DsLen = 1, SsidLen; + HEADER_802_11 BcnHdr; + LARGE_INTEGER FakeTimestamp; + UCHAR PhyMode = 0, SupRateLen; + UINT32 mac_val = 0, bmc_cnt = 0; + UCHAR Environment = 0x20; + + if (apidx < 0) + return; + + pComCfg = &pAd->CommonCfg; + pMbss = &pAd->ApCfg.MBSSID[apidx]; + wdev = &pMbss->wdev; + + if (!pMbss || !pMbss->bcn_buf.BeaconPkt) + return; + + tmac_info = (UCHAR *)GET_OS_PKT_DATAPTR(pMbss->bcn_buf.BeaconPkt); + if (pAd->chipCap.hif_type == HIF_MT) + { + pBeaconFrame = (UCHAR *)(tmac_info + tx_hw_hdr_len); + } + else + { + pBeaconFrame = (UCHAR *)(tmac_info + TXWISize); + } + + if(!BeaconTransmitRequired(pAd, apidx, pMbss)) { +#ifdef BCN_OFFLOAD_SUPPORT + RT28xx_UpdateBeaconToMcu(pAd, apidx, FALSE, 0, 0, 0); + pMbss->updateEventIsTriggered = FALSE; +#endif /* BCN_OFFLOAD_SUPPORT */ + return; + } + + +#ifdef CONFIG_FPGA_MODE + if (pAd->fpga_ctl.fpga_on & 0x1) { + if (pAd->fpga_ctl.tx_kick_cnt == 0) + return; + } + +#ifdef MT_MAC + if (pAd->fpga_ctl.no_bcn) { + DBGPRINT(RT_DEBUG_OFF, ("%s():Bcn Tx is blocked!\n", __FUNCTION__)); + return; + } +#endif /* MT_MAC */ +#endif /* CONFIG_FPGA_MODE */ + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + + +#ifdef RTMP_PCI_SUPPORT + BOOLEAN is_pretbtt_int = FALSE; + + USHORT FreeNum = GET_BCNRING_FREENO(pAd); + if (FreeNum <= 0) { + DBGPRINT(RT_DEBUG_ERROR, ("%s()=>BSS%d:BcnRing FreeNum is not enough!\n", + __FUNCTION__, apidx)); + return; + } +#endif /* RTMP_PCI_SUPPORT */ + + if (pMbss->bcn_buf.bcn_state != BCN_TX_IDLE) { + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) { + DBGPRINT(RT_DEBUG_TRACE, ("%s()=>BSS%d:BcnPkt not idle(%d)!\n", + __FUNCTION__, apidx, pMbss->bcn_buf.bcn_state)); + } +#ifdef RTMP_PCI_SUPPORT + APCheckBcnQHandler(pAd, apidx, &is_pretbtt_int); + if (is_pretbtt_int == FALSE) +#endif /* RTMP_PCI_SUPPORT */ + return; + } + + PhyMode = pMbss->wdev.PhyMode; + SsidLen = (pMbss->bHideSsid) ? 0 : pMbss->SsidLen; + MgtMacHeaderInit(pAd, &BcnHdr, SUBTYPE_BEACON, + 0, BROADCAST_ADDR, + pMbss->wdev.if_addr, + pMbss->wdev.bssid); + + /* for update framelen to TxWI later. */ +#ifdef DYNAMIC_RX_RATE_ADJ + SupRateLen = pAd->ApCfg.MBSSID[apidx].SupRateLen; +#else + SupRateLen = pAd->CommonCfg.SupRateLen; +#endif /* DYNAMIC_RX_RATE_ADJ */ + if (PhyMode == WMODE_B) + SupRateLen = 4; + + MakeOutgoingFrame(pBeaconFrame, &FrameLen, + sizeof(HEADER_802_11), &BcnHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &pMbss->CapabilityInfo, + 1, &SsidIe, + 1, &SsidLen, + SsidLen, pMbss->Ssid, + 1, &SupRateIe, + 1, &SupRateLen, +#ifdef DYNAMIC_RX_RATE_ADJ + SupRateLen, pAd->ApCfg.MBSSID[apidx].SupRate, +#else + SupRateLen, pAd->CommonCfg.SupRate, +#endif /* DYNAMIC_RX_RATE_ADJ */ + 1, &DsIe, + 1, &DsLen, + 1, &pAd->CommonCfg.Channel, + END_OF_ARGS); + +#ifdef DYNAMIC_RX_RATE_ADJ + if ((pAd->ApCfg.MBSSID[apidx].ExtRateLen) && (PhyMode != WMODE_B)) +#else + if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != WMODE_B)) +#endif /* DYNAMIC_RX_RATE_ADJ */ + { + ULONG TmpLen; + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &ExtRateIe, +#ifdef DYNAMIC_RX_RATE_ADJ + 1, &pAd->ApCfg.MBSSID[apidx].ExtRateLen, + pAd->ApCfg.MBSSID[apidx].ExtRateLen, pAd->ApCfg.MBSSID[apidx].ExtRate, +#else + 1, &pAd->CommonCfg.ExtRateLen, + pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, +#endif /* DYNAMIC_RX_RATE_ADJ */ + END_OF_ARGS); + FrameLen += TmpLen; + } + + + /* add country IE, power constraint IE */ + if (pAd->CommonCfg.bCountryFlag) + { + ULONG TmpLen, TmpLen2=0; + UCHAR *TmpFrame = NULL; + UCHAR CountryIe = IE_COUNTRY; + + os_alloc_mem(NULL, (UCHAR **)&TmpFrame, 256); + if (TmpFrame != NULL) + { + NdisZeroMemory(TmpFrame, 256); + + /* prepare channel information */ +#ifdef EXT_BUILD_CHANNEL_LIST + BuildBeaconChList(pAd, TmpFrame, &TmpLen2); +#else + { + UCHAR MaxTxPower = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); + MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, + 1, &pAd->ChannelList[0].Channel, + 1, &pAd->ChannelListNum, + 1, &MaxTxPower, + END_OF_ARGS); + TmpLen2 += TmpLen; + } +#endif /* EXT_BUILD_CHANNEL_LIST */ + +#ifdef DOT11K_RRM_SUPPORT + if (IS_RRM_ENABLE(pAd, apidx) + && (pAd->CommonCfg.RegulatoryClass[0] != 0)) + { + TmpLen2 = 0; + NdisZeroMemory(TmpFrame, 256); + RguClass_BuildBcnChList(pAd, TmpFrame, &TmpLen2); + } +#endif /* DOT11K_RRM_SUPPORT */ +#ifdef MBO_SUPPORT + if (IS_MBO_ENABLE(wdev)) + Environment = MBO_AP_USE_GLOBAL_OPERATING_CLASS; +#endif/* MBO_SUPPORT */ + + /* need to do the padding bit check, and concatenate it */ + if ((TmpLen2%2) == 0) + { + UCHAR TmpLen3 = TmpLen2+4; + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &CountryIe, + 1, &TmpLen3, + 1, &pAd->CommonCfg.CountryCode[0], + 1, &pAd->CommonCfg.CountryCode[1], + 1, &Environment, + TmpLen2+1, TmpFrame, + END_OF_ARGS); + } else { + UCHAR TmpLen3 = TmpLen2 + 3; + + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + 1, &CountryIe, + 1, &TmpLen3, + 1, &pAd->CommonCfg.CountryCode[0], + 1, &pAd->CommonCfg.CountryCode[1], + 1, &Environment, + TmpLen2, TmpFrame, + END_OF_ARGS); + } + FrameLen += TmpLen; + + os_free_mem(NULL, TmpFrame); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + } + +#ifdef DOT11K_RRM_SUPPORT + if (IS_RRM_ENABLE(pAd, apidx)) + { + InsertTpcReportIE(pAd, pBeaconFrame+FrameLen, &FrameLen, + RTMP_GetTxPwr(pAd, pAd->CommonCfg.MlmeTransmit), 0); + RRM_InsertRRMEnCapIE(pAd, pBeaconFrame+FrameLen, &FrameLen, apidx); + } +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + /* AP Channel Report */ +#ifdef DOT11K_RRM_SUPPORT + for (i=0; iCommonCfg.RegulatoryClass[i] == 0) + break; + + InsertChannelRepIE(pAd, pBeaconFrame+FrameLen, &FrameLen, + (RTMP_STRING *)pAd->CommonCfg.CountryCode, + pAd->CommonCfg.RegulatoryClass[i], NULL); + + } +#else + { + UCHAR APChannelReportIe = IE_AP_CHANNEL_REPORT; + ULONG TmpLen; + + /* + 802.11n D2.0 Annex J, USA regulatory + class 32, channel set 1~7 + class 33, channel set 5-11 + */ + UCHAR rclass32[]={32, 1, 2, 3, 4, 5, 6, 7}; + UCHAR rclass33[]={33, 5, 6, 7, 8, 9, 10, 11}; + UCHAR rclasslen = 8; /*sizeof(rclass32); */ + if (PhyMode == (WMODE_B | WMODE_G | WMODE_GN)) + { + MakeOutgoingFrame(pBeaconFrame+FrameLen,&TmpLen, + 1, &APChannelReportIe, + 1, &rclasslen, + rclasslen, rclass32, + 1, &APChannelReportIe, + 1, &rclasslen, + rclasslen, rclass33, + END_OF_ARGS); + FrameLen += TmpLen; + } + } +#endif +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + /* + The Mobility Domain information element (MDIE) is present in Beacon + frame when dot11FastBssTransitionEnable is set to true. + */ + if (pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable) + { + PFT_CFG pFtCfg = &pAd->ApCfg.MBSSID[apidx].FtCfg; + FT_CAP_AND_POLICY FtCap; + NdisZeroMemory(&FtCap, sizeof(FT_CAP_AND_POLICY)); + FtCap.field.FtOverDs = pFtCfg->FtCapFlag.FtOverDs; + FtCap.field.RsrReqCap = pFtCfg->FtCapFlag.RsrReqCap; + FT_InsertMdIE(pAd, pBeaconFrame + FrameLen, &FrameLen, + pFtCfg->FtMdId, FtCap); + } +#endif /* DOT11R_FT_SUPPORT */ + + BeaconTransmit.word = 0; + + //write_tmac_info_beacon(pAd, apidx, tmac_info, &BeaconTransmit, FrameLen); + + pMbss->TimIELocationInBeacon = (UCHAR)FrameLen; + pMbss->bcn_buf.cap_ie_pos = sizeof(HEADER_802_11) + TIMESTAMP_LEN + 2; + + FrameLen = UpdatePos = pMbss->TimIELocationInBeacon; + PhyMode = wdev->PhyMode; + + + + } +#endif /* MT_MAC */ + + /* + step 1 - update BEACON's Capability + */ + ptr = pBeaconFrame + pMbss->bcn_buf.cap_ie_pos; + + //prevent little/big endian issue. and let asic_write_bcn_buf() handle it. + *(UINT16 *)ptr = pMbss->CapabilityInfo; + + + + AsicSetBmcQCR(pAd, BMC_CNT_UPDATE, CR_READ, apidx, &mac_val); + + if ((apidx >= 0) && (apidx <= 4)) + { + if (apidx == 0) + bmc_cnt = mac_val & 0xf; + else + bmc_cnt = (mac_val >> (12+ (4*apidx))) & 0xf; + } + else if ((apidx >= 5) && (apidx <= 12)) + { + bmc_cnt = (mac_val >> (4*(apidx-5))) & 0xf; + } + else if ((apidx >=13) && (apidx <= 15)) + { + bmc_cnt = (mac_val >> (4*(apidx-13))) & 0xf; + } + + if (bmc_cnt > 0) + { + WLAN_MR_TIM_BCMC_SET(apidx); + } + //else + //{ + //WLAN_MR_TIM_BCMC_CLEAR(apidx); + //} + + /* + step 2 - update TIM IE + TODO: enlarge TIM bitmap to support up to 64 STAs + TODO: re-measure if RT2600 TBTT interrupt happens faster than BEACON sent out time + */ + ptr = pBeaconFrame + pMbss->TimIELocationInBeacon; + *ptr = IE_TIM; + *(ptr + 2) = pAd->ApCfg.DtimCount; + *(ptr + 3) = pAd->ApCfg.DtimPeriod; + + /* find the smallest AID (PS mode) */ + TimFirst = 0; /* record first TIM byte != 0x00 */ + TimLast = 0; /* record last TIM byte != 0x00 */ + pTim = pMbss->TimBitmaps; + + for(ID_1B=0; ID_1BApCfg.DtimCount == 0) + *(ptr + 4) |= (pMbss->TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] & 0x01); + + /* adjust BEACON length according to the new TIM */ + FrameLen += (2 + *(ptr+1)); + + /* move RSN IE from below to here for Ralink Win7 v3.0.0.61 version parse beacon issue. */ + /* sync the order with BRCM's AP. */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || + (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) + RSNIe = IE_WPA; + else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef DOT11_SAE_SUPPORT + || (wdev->AuthMode == Ndis802_11AuthModeWPA3PSK) + || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSKWPA3PSK) +#endif +#ifdef CONFIG_OWE_SUPPORT + || (wdev->AuthMode == Ndis802_11AuthModeOWE) +#endif + ) + RSNIe = IE_WPA2; +#ifdef WAPI_SUPPORT + else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) || + (wdev->AuthMode == Ndis802_11AuthModeWAIPSK)) + RSNIe = IE_WAPI; +#endif /* WAPI_SUPPORT */ + + /* Append RSN_IE when WPA OR WPAPSK, */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + { + ULONG TmpLen; + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &RSNIe, + 1, &pMbss->RSNIE_Len[0], + pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], + 1, &RSNIe2, + 1, &pMbss->RSNIE_Len[1], + pMbss->RSNIE_Len[1], pMbss->RSN_IE[1], + END_OF_ARGS); + FrameLen += TmpLen; + } + else if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + { + ULONG TmpLen; +#ifdef CONFIG_HOTSPOT_R2 + extern UCHAR OSEN_IE[]; + extern UCHAR OSEN_IELEN; + + if ((pMbss->HotSpotCtrl.HotSpotEnable == 0) && (pMbss->HotSpotCtrl.bASANEnable == 1) && (pMbss->wdev.AuthMode == Ndis802_11AuthModeWPA2)) + { + RSNIe = IE_WPA; + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &RSNIe, + 1, &OSEN_IELEN, + OSEN_IELEN, OSEN_IE, + END_OF_ARGS); + FrameLen += TmpLen; + } + else +#endif /* CONFIG_HOTSPOT_R2 */ + { + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &RSNIe, + 1, &pMbss->RSNIE_Len[0], + pMbss->RSNIE_Len[0], pMbss->RSN_IE[0], + END_OF_ARGS); + FrameLen += TmpLen; + } + } + +#ifdef HOSTAPD_SUPPORT + if (pMbss->HostapdWPS && (pMbss->WscIEBeacon.ValueLen)) + bHasWpsIE = TRUE; +#endif + +#ifdef WSC_AP_SUPPORT + /* add Simple Config Information Element */ + if (((pMbss->WscControl.WscConfMode >= 1) && (pMbss->WscIEBeacon.ValueLen))) + bHasWpsIE = TRUE; +#endif /* WSC_AP_SUPPORT */ + + if (bHasWpsIE) + { + ULONG WscTmpLen = 0; + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &WscTmpLen, + pMbss->WscIEBeacon.ValueLen, pMbss->WscIEBeacon.Value, + END_OF_ARGS); + FrameLen += WscTmpLen; + } + +#ifdef WSC_AP_SUPPORT + if ((pMbss->WscControl.WscConfMode != WSC_DISABLE) && +#ifdef DOT1X_SUPPORT + (pMbss->wdev.IEEE8021X == FALSE) && +#endif /* DOT1X_SUPPORT */ + (pMbss->wdev.WepStatus == Ndis802_11WEPEnabled)) + { + /* + Non-WPS Windows XP and Vista PCs are unable to determine if a WEP enalbed network is static key based + or 802.1X based. If the legacy station gets an EAP-Rquest/Identity from the AP, it assume the WEP + network is 802.1X enabled & will prompt the user for 802.1X credentials. If the legacy station doesn't + receive anything after sending an EAPOL-Start, it will assume the WEP network is static key based and + prompt user for the WEP key. <> + A WPS enabled AP should include this IE in the beacon when the AP is hosting a static WEP key network. + The IE would be 7 bytes long with the Extended Capability field set to 0 (all bits zero) + http:msdn.microsoft.com/library/default.asp?url=/library/en-us/randz/protocol/securing_public_wi-fi_hotspots.asp + */ + ULONG TempLen = 0; + UCHAR PROVISION_SERVICE_IE[7] = {0xDD, 0x05, 0x00, 0x50, 0xF2, 0x05, 0x00}; + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TempLen, + 7, PROVISION_SERVICE_IE, + END_OF_ARGS); + FrameLen += TempLen; + } +#endif /* WSC_AP_SUPPORT */ + + + /* Update ERP */ +#ifdef DYNAMIC_RX_RATE_ADJ + if ((pAd->ApCfg.MBSSID[apidx].ExtRateLen) && (PhyMode != WMODE_B)) +#else + if ((pComCfg->ExtRateLen) && (PhyMode != WMODE_B)) +#endif /* DYNAMIC_RX_RATE_ADJ */ + { + /* 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); + } + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(PhyMode)) { + INT tp_len, wb_len = 0; + UCHAR *ch_sw_wrapper; + VHT_TXPWR_ENV_IE txpwr_env; + + + *ptr = IE_CH_SWITCH_WRAPPER; + ch_sw_wrapper = (UCHAR *)(ptr + 1); // reserve for length + ptr += 2; // skip len + + if (pComCfg->RegTransmitSetting.field.BW == BW_40) { + WIDE_BW_CH_SWITCH_ELEMENT wb_info; + + *ptr = IE_WIDE_BW_CH_SWITCH; + *(ptr + 1) = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); + ptr += 2; + NdisZeroMemory(&wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); + if (pComCfg->vht_bw == VHT_BW_2040) + wb_info.new_ch_width = 0; + else + wb_info.new_ch_width = 1; + + if (pComCfg->vht_bw == VHT_BW_80) { + wb_info.center_freq_1 = vht_cent_ch_freq(pAd, pComCfg->Channel); + wb_info.center_freq_2 = 0; + } + NdisMoveMemory(ptr, &wb_info, sizeof(WIDE_BW_CH_SWITCH_ELEMENT)); + wb_len = sizeof(WIDE_BW_CH_SWITCH_ELEMENT); + ptr += wb_len; + wb_len += 2; + } + + *ptr = IE_VHT_TXPWR_ENV; + NdisZeroMemory(&txpwr_env, sizeof(VHT_TXPWR_ENV_IE)); + tp_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env); + *(ptr + 1) = tp_len; + ptr += 2; + NdisMoveMemory(ptr, &txpwr_env, tp_len); + ptr += tp_len; + tp_len += 2; + *ch_sw_wrapper = wb_len + tp_len; + + FrameLen += (2 + wb_len + tp_len); + } +#endif /* DOT11_VHT_AC */ + +#endif /* DOT11_N_SUPPORT */ + } +#endif /* A_BAND_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + /* step 5. Update HT. Since some fields might change in the same BSS. */ + if (WMODE_CAP_N(PhyMode) && (wdev->DesiredHtPhyInfo.bHtEnable)) + { + ULONG TmpLen; + UCHAR HtLen, HtLen1; + /*UCHAR i; */ + + HT_CAPABILITY_IE HtCapabilityTmp; +#ifdef RT_BIG_ENDIAN + 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 + NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); +#ifdef DYNAMIC_RX_RATE_ADJ + NdisMoveMemory(HtCapabilityTmp.MCSSet, pAd->ApCfg.MBSSID[apidx].ExpectedSuppHTMCSSet, 4); +#endif /* DYNAMIC_RX_RATE_ADJ */ + HtCapabilityTmp.HtCapInfo.ChannelWidth = pComCfg->AddHTInfo.AddHtInfo.RecomWidth; + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + 1, &AddHtInfoIe, + 1, &HtLen1, + HtLen1, &pComCfg->AddHTInfo, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); +#ifdef DYNAMIC_RX_RATE_ADJ + NdisMoveMemory(HtCapabilityTmp.MCSSet, pAd->ApCfg.MBSSID[apidx].ExpectedSuppHTMCSSet, 4); +#endif /* DYNAMIC_RX_RATE_ADJ */ + HtCapabilityTmp.HtCapInfo.ChannelWidth = pComCfg->AddHTInfo.AddHtInfo.RecomWidth; + *(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 ((pComCfg->Channel <= 14) && + (pComCfg->HtCapability.HtCapInfo.ChannelWidth == 1)) + { + OVERLAP_BSS_SCAN_IE OverlapScanParam; + ULONG TmpLen; + UCHAR OverlapScanIE, ScanIELen; + + OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; + ScanIELen = 14; + OverlapScanParam.ScanPassiveDwell = cpu2le16(pComCfg->Dot11OBssScanPassiveDwell); + OverlapScanParam.ScanActiveDwell = cpu2le16(pComCfg->Dot11OBssScanActiveDwell); + OverlapScanParam.TriggerScanInt = cpu2le16(pComCfg->Dot11BssWidthTriggerScanInt); + OverlapScanParam.PassiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanPassiveTotalPerChannel); + OverlapScanParam.ActiveTalPerChannel = cpu2le16(pComCfg->Dot11OBssScanActiveTotalPerChannel); + OverlapScanParam.DelayFactor = cpu2le16(pComCfg->Dot11BssWidthChanTranDelayFactor); + OverlapScanParam.ScanActThre = cpu2le16(pComCfg->Dot11OBssScanActivityThre); + + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + 1, &OverlapScanIE, + 1, &ScanIELen, + ScanIELen, &OverlapScanParam, + END_OF_ARGS); + + FrameLen += TmpLen; + } +#endif /* DOT11N_DRAFT3 */ + +#ifdef CONFIG_HOTSPOT + if (pMbss->HotSpotCtrl.HotSpotEnable) + { + ULONG TmpLen; + + /* Indication element */ + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + pMbss->HotSpotCtrl.HSIndicationIELen, + pMbss->HotSpotCtrl.HSIndicationIE, END_OF_ARGS); + + FrameLen += TmpLen; + + /* Interworking element */ + /*MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + pMbss->HotSpotCtrl.InterWorkingIELen, + pMbss->HotSpotCtrl.InterWorkingIE, END_OF_ARGS); + + FrameLen += TmpLen; +*/ + + /* Advertisement Protocol element */ + /*MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + pMbss->HotSpotCtrl.AdvertisementProtoIELen, + pMbss->HotSpotCtrl.AdvertisementProtoIE, END_OF_ARGS); + + FrameLen += TmpLen; +*/ + + /* Roaming Consortium element */ + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + pMbss->HotSpotCtrl.RoamingConsortiumIELen, + pMbss->HotSpotCtrl.RoamingConsortiumIE, END_OF_ARGS); + + FrameLen += TmpLen; + + /* P2P element */ + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + pMbss->HotSpotCtrl.P2PIELen, + pMbss->HotSpotCtrl.P2PIE, END_OF_ARGS); + + FrameLen += TmpLen; + + } +#endif + + +#ifdef DOT11U_INTERWORKING + if (pMbss->GASCtrl.b11U_enable) { + ULONG TmpLen; + /* Interworking element */ + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + pMbss->GASCtrl.InterWorkingIELen, + pMbss->GASCtrl.InterWorkingIE, END_OF_ARGS); + FrameLen += TmpLen; + /* Advertisement Protocol element */ + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + pMbss->GASCtrl.AdvertisementProtoIELen, + pMbss->GASCtrl.AdvertisementProtoIE, END_OF_ARGS); + FrameLen += TmpLen; + } +#endif /* DOT11U_INTERWORKING */ + + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(PhyMode) && (pComCfg->Channel > 14)) + { + int _len = build_vht_ies(pAd, (UCHAR *)(pBeaconFrame+FrameLen), SUBTYPE_BEACON); + FrameLen += _len; + } +#endif /* DOT11_VHT_AC */ + } +#endif /* DOT11_N_SUPPORT */ + + /* 7.3.2.27 Extended Capabilities IE */ + { + ULONG TmpLen, infoPos; + PUCHAR pInfo; + UCHAR extInfoLen; + BOOLEAN bNeedAppendExtIE = FALSE; + EXT_CAP_INFO_ELEMENT extCapInfo; + + + extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); + NdisZeroMemory(&extCapInfo, extInfoLen); + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* P802.11n_D1.10, HT Information Exchange Support */ + if (WMODE_CAP_N(PhyMode) && (pComCfg->Channel <= 14) && + (pMbss->wdev.DesiredHtPhyInfo.bHtEnable) && + (pComCfg->bBssCoexEnable == TRUE) + ) + { + extCapInfo.BssCoexistMgmtSupport = 1; + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef CONFIG_DOT11V_WNM + if (pMbss->WNMCtrl.ProxyARPEnable) + extCapInfo.proxy_arp = 1; + if (pMbss->WNMCtrl.WNMBTMEnable) + extCapInfo.BssTransitionManmt = 1; +#ifdef CONFIG_HOTSPOT_R2 + if (pMbss->WNMCtrl.WNMNotifyEnable) + extCapInfo.wnm_notification = 1; + + if (pMbss->HotSpotCtrl.QosMapEnable) + extCapInfo.qosmap= 1; +#endif /* CONFIG_HOTSPOT_R2 */ +#endif /* CONFIG_DOT11V_WNM */ + +#ifdef CONFIG_HOTSPOT + if (pMbss->HotSpotCtrl.HotSpotEnable) + extCapInfo.interworking = 1; +#endif /* CONFIG_HOTSPOT */ +#ifdef DOT11U_INTERWORKING + if (pMbss->GASCtrl.b11U_enable) + extCapInfo.interworking = 1; +#endif/* DOT11U_INTERWORKING */ + +#ifdef DOT11V_WNM_SUPPORT + if (IS_BSS_TRANSIT_MANMT_SUPPORT(pAd, apidx)) + { + extCapInfo.BssTransitionManmt = 1; + } + if (IS_WNMDMS_SUPPORT(pAd, apidx)) + { + extCapInfo.DMSSupport = 1; + } +#endif /* DOT11V_WNM_SUPPORT */ +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(PhyMode) && + (pAd->CommonCfg.Channel > 14)) + extCapInfo.operating_mode_notification = 1; +#endif /* DOT11_VHT_AC */ + + pInfo = (PUCHAR)(&extCapInfo); + for (infoPos = 0; infoPos < extInfoLen; infoPos++) + { + if (pInfo[infoPos] != 0) + { + bNeedAppendExtIE = TRUE; + break; + } + } + + if (bNeedAppendExtIE == TRUE) + { +#ifdef RT_BIG_ENDIAN + *((UINT32*)(pInfo)) = SWAP32(*((UINT32*)(pInfo))); + *((UINT32*)(pInfo+4)) = SWAP32(*((UINT32*)(pInfo+4))); +#endif + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &ExtCapIe, + 1, &extInfoLen, + extInfoLen, &extCapInfo, + END_OF_ARGS); + FrameLen += TmpLen; + } + } + +#ifdef WFA_VHT_PF + if (pAd->force_vht_op_mode == TRUE) + { + ULONG TmpLen; + UCHAR operating_ie = IE_OPERATING_MODE_NOTIFY, operating_len = 1; + OPERATING_MODE operating_mode; + + operating_mode.rx_nss_type = 0; + operating_mode.rx_nss = (pAd->vht_pf_op_ss - 1); + operating_mode.ch_width = pAd->vht_pf_op_bw; + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &operating_ie, + 1, &operating_len, + 1, &operating_mode, + END_OF_ARGS); + FrameLen += TmpLen; + } +#endif /* WFA_VHT_PF */ +#ifdef DOT11U_INTERWORKING + if (pMbss->GASCtrl.b11U_enable) { + ULONG TmpLen; + /* Interworking element */ + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + pMbss->GASCtrl.InterWorkingIELen, + pMbss->GASCtrl.InterWorkingIE, END_OF_ARGS); + FrameLen += TmpLen; + /* Advertisement Protocol element */ + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + pMbss->GASCtrl.AdvertisementProtoIELen, + pMbss->GASCtrl.AdvertisementProtoIE, END_OF_ARGS); + FrameLen += TmpLen; + } +#endif/* DOT11U_INTERWORKING */ + + /* add WMM IE here */ + if (pMbss->wdev.bWmmCapable) + { + ULONG TmpLen; + UCHAR i; + UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; + UINT8 AIFSN[4]; + + WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; + +#ifdef UAPSD_SUPPORT + UAPSD_MR_IE_FILL(WmeParmIe[8], &pMbss->wdev.UapsdInfo); +#endif /* UAPSD_SUPPORT */ + + NdisMoveMemory(AIFSN, pAd->ApCfg.BssEdcaParm.Aifsn, sizeof(AIFSN)); + + + for (i=QID_AC_BE; i<=QID_AC_VO; i++) + { + WmeParmIe[10+ (i*4)] = (i << 5) + /* b5-6 is ACI */ + ((UCHAR)pAd->ApCfg.BssEdcaParm.bACM[i] << 4) + /* b4 is ACM */ + (AIFSN[i] & 0x0f); /* b0-3 is AIFSN */ + WmeParmIe[11+ (i*4)] = (pAd->ApCfg.BssEdcaParm.Cwmax[i] << 4) + /* b5-8 is CWMAX */ + (pAd->ApCfg.BssEdcaParm.Cwmin[i] & 0x0f); /* b0-3 is CWMIN */ + WmeParmIe[12+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] & 0xff); /* low byte of TXOP */ + WmeParmIe[13+ (i*4)] = (UCHAR)(pAd->ApCfg.BssEdcaParm.Txop[i] >> 8); /* high byte of TXOP */ + } + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 26, WmeParmIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + +#ifdef AP_QLOAD_SUPPORT + if (pAd->phy_ctrl.FlgQloadEnable != 0) + { +#ifdef CONFIG_HOTSPOT_R2 + if (pMbss->HotSpotCtrl.QLoadTestEnable == 1) + FrameLen += QBSS_LoadElementAppend_HSTEST(pAd, pBeaconFrame+FrameLen, apidx); + else if (pMbss->HotSpotCtrl.QLoadTestEnable == 0) +#endif + FrameLen += QBSS_LoadElementAppend(pAd, pBeaconFrame+FrameLen); + } +#endif /* AP_QLOAD_SUPPORT */ + +#ifdef A_BAND_SUPPORT + /* + Only 802.11a APs that comply with 802.11h are required to include a + Power Constrint Element(IE=32) in beacons and probe response frames + */ + if (((pComCfg->Channel > 14) && pComCfg->bIEEE80211H == TRUE) +#ifdef DOT11K_RRM_SUPPORT + || IS_RRM_ENABLE(pAd, apidx) +#endif /* DOT11K_RRM_SUPPORT */ + ) + { + ULONG TmpLen; + UINT8 PwrConstraintIE = IE_POWER_CONSTRAINT; + UINT8 PwrConstraintLen = 1; + UINT8 PwrConstraint = pComCfg->PwrConstraint; + + /* prepare power constraint IE */ + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &PwrConstraintIE, + 1, &PwrConstraintLen, + 1, &PwrConstraint, + END_OF_ARGS); + FrameLen += TmpLen; + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(PhyMode)) { + ULONG TmpLen; + UINT8 vht_txpwr_env_ie = IE_VHT_TXPWR_ENV; + UINT8 ie_len; + VHT_TXPWR_ENV_IE txpwr_env; + + ie_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env); + MakeOutgoingFrame(pBeaconFrame+FrameLen, &TmpLen, + 1, &vht_txpwr_env_ie, + 1, &ie_len, + ie_len, &txpwr_env, + END_OF_ARGS); + FrameLen += TmpLen; + } +#endif /* DOT11_VHT_AC */ + + } +#endif /* A_BAND_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT + if (IS_RRM_ENABLE(pAd, apidx)) + { +#ifdef QUIET_SUPPORT + PRRM_QUIET_CB pQuietCB = &pMbss->RrmCfg.QuietCB; + RRM_InsertQuietIE(pAd, pBeaconFrame+FrameLen, &FrameLen, + pQuietCB->QuietCnt ,pQuietCB->QuietPeriod, + pQuietCB->QuietDuration, pQuietCB->QuietOffset); +#endif +#ifndef APPLE_11K_IOT + /* Insert BSS AC Access Delay IE. */ + RRM_InsertBssACDelayIE(pAd, pBeaconFrame+FrameLen, &FrameLen); + + /* Insert BSS Available Access Capacity IE. */ + RRM_InsertBssAvailableACIE(pAd, pBeaconFrame+FrameLen, &FrameLen); +#endif /* !APPLE_11K_IOT */ + } +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(PhyMode) && + (wdev->DesiredHtPhyInfo.bHtEnable)) + { + ULONG TmpLen; + UCHAR HtLen, HtLen1; + HT_CAPABILITY_IE HtCapabilityTmp; +#ifdef RT_BIG_ENDIAN + ADD_HT_INFO_IE addHTInfoTmp; +#endif + /* add HT Capability IE */ + HtLen = sizeof(pComCfg->HtCapability); + HtLen1 = sizeof(pComCfg->AddHTInfo); + + if (pAd->bBroadComHT == TRUE) + { + UCHAR epigram_ie_len; + UCHAR BROADCOM_HTC[4] = {0x0, 0x90, 0x4c, 0x33}; + UCHAR BROADCOM_AHTINFO[4] = {0x0, 0x90, 0x4c, 0x34}; + + + epigram_ie_len = HtLen + 4; + + NdisMoveMemory(&HtCapabilityTmp, &pComCfg->HtCapability, HtLen); + +#ifdef DYNAMIC_RX_RATE_ADJ + NdisMoveMemory(HtCapabilityTmp.MCSSet, pAd->ApCfg.MBSSID[apidx].ExpectedSuppHTMCSSet, 4); +#endif /* DYNAMIC_RX_RATE_ADJ */ + +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pBeaconFrame + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_HTC[0], + HtLen, &HtCapabilityTmp, + END_OF_ARGS); +#else + *(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 */ +#if defined(MWDS) || defined(CONFIG_OWE_SUPPORT) + FrameLen += build_vendor_ie(pAd, wdev, (pBeaconFrame + FrameLen) +#ifdef CONFIG_OWE_SUPPORT + , VIE_BEACON +#endif +#ifdef WH_EZ_SETUP + , SUBTYPE_BEACON +#endif + ); +#else +{ + 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; + +} +#endif +#ifdef MBO_SUPPORT + if (IS_MBO_ENABLE(wdev)) + MakeMboOceIE(pAd, wdev, pBeaconFrame+FrameLen, &FrameLen, MBO_FRAME_TYPE_BEACON); +#endif/* MBO_SUPPORT */ + + +#ifdef AIRPLAY_SUPPORT + if (AIRPLAY_ON(pAd)) + { + ULONG AirplayTmpLen = 0; + + /*Aiplay use normal softAP mode, so MCS no need to be OFDM*/ +// BeaconTransmit.field.MODE = MODE_CCK; +// BeaconTransmit.field.MCS = MCS_LONGP_RATE_1; + + /*User user setting IE*/ + if (pAd->pAirplayIe && (pAd->AirplayIeLen != 0)) + { + //hex_dump("[BCN]IE:", pAd->pAirplayIe , pAd->AirplayIeLen); + + MakeOutgoingFrame(pBeaconFrame+FrameLen, &AirplayTmpLen, + pAd->AirplayIeLen, pAd->pAirplayIe, + END_OF_ARGS); + FrameLen += AirplayTmpLen; + } + + } +#endif /* AIRPLAY_SUPPORT*/ + +#ifdef WIFI_DIAG + DiagBcnTx(pAd, pMbss, pBeaconFrame, FrameLen); +#endif + + /* step 6. Since FrameLen may change, update TXWI. */ +#ifdef A_BAND_SUPPORT + if (pAd->CommonCfg.Channel > 14) { + BeaconTransmit.field.MODE = MODE_OFDM; + BeaconTransmit.field.MCS = MCS_RATE_6; + } +#endif /* A_BAND_SUPPORT */ + + write_tmac_info_beacon(pAd, apidx, tmac_info, &BeaconTransmit, FrameLen); + + /* step 6. move BEACON TXD and frame content to on-chip memory */ + asic_write_bcn_buf(pAd, + tmac_info, TXWISize, + pBeaconFrame, FrameLen, + pAd->BeaconOffset[pMbss->bcn_buf.BcnBufIdx]); + +#if defined(MT7603_FPGA) || defined(MT7628_FPGA) + // TODO: shiang-7603, we use different way to update beacon packet! + if (0)//IS_MT7603(pAd)) + { + hex_dump("Beacon_TMAC_INFO", (UCHAR *)tmac_info, tx_hw_hdr_len); + dump_tmac_info(pAd, tmac_info); + hex_dump("BeaconFrame", pBeaconFrame, FrameLen); + } +#endif /* MT7603_FPGA */ + + /* step 7. move BEACON TXWI and frame content to on-chip memory */ +#ifdef BCN_OFFLOAD_SUPPORT + if (pMbss->updateEventIsTriggered == FALSE) { + RT28xx_UpdateBeaconToMcu(pAd, apidx, 0, TRUE, FrameLen, UpdatePos); + pMbss->updateEventIsTriggered = TRUE; + } +#endif + RT28xx_UpdateBeaconToAsic(pAd, apidx, FrameLen, UpdatePos); + + { + UINT32 Lowpart, Highpart; + + AsicGetTsfTime(pAd, &Highpart, &Lowpart); + pMbss->WriteBcnDoneTime[pMbss->timer_loop] = Lowpart; + } +} + + +/* + ========================================================================== + Description: + Pre-build All BEACON frame in the shared memory + ========================================================================== +*/ +static UCHAR GetBcnNum(RTMP_ADAPTER *pAd) +{ + int i; + int NumBcn; + BCN_BUF_STRUC *bcn_info; + + NumBcn = 0; + for (i=0; iApCfg.BssidNum; i++) + { + bcn_info = &pAd->ApCfg.MBSSID[i].bcn_buf; + if (bcn_info->bBcnSntReq) + { + bcn_info->BcnBufIdx = NumBcn; + NumBcn ++; + } + } + + + return NumBcn; +} + + +VOID APMakeAllBssBeacon(RTMP_ADAPTER *pAd) +{ + INT i; + UCHAR NumOfBcns; + + /* choose the Beacon number */ + NumOfBcns = GetBcnNum(pAd); + +#if defined(RTMP_MAC) || defined(RLT_MAC) + if ((pAd->chipCap.hif_type == HIF_RTMP) || (pAd->chipCap.hif_type == HIF_RLT)) { + INT j; + /* + 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 of chip. + + use pAd->ApCfg.BssidNum to avoid the case is best + */ + UINT8 TXWISize = pAd->chipCap.TXWISize; + + for (i=0; iBeaconOffset[i] + j, 0, 4); + } + } + } +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + + for(i=0; iApCfg.BssidNum; i++) + APMakeBssBeacon(pAd, i); + + AsicSetMbssMode(pAd, NumOfBcns); + + +} + + +/* + ========================================================================== + Description: + Pre-build All BEACON frame in the shared memory + ========================================================================== +*/ +VOID APUpdateAllBeaconFrame(RTMP_ADAPTER *pAd) +{ + INT i; +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + BOOLEAN FlgQloadIsAlarmIssued = FALSE; +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + if (pAd->ApCfg.DtimCount == 0) + pAd->ApCfg.DtimCount = pAd->ApCfg.DtimPeriod - 1; + else + pAd->ApCfg.DtimCount -= 1; +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* QLOAD ALARM */ +#ifdef AP_QLOAD_SUPPORT + FlgQloadIsAlarmIssued = QBSS_LoadIsAlarmIssued(pAd); +#endif /* AP_QLOAD_SUPPORT */ + + if ((pAd->ApCfg.DtimCount == 0) && + (((pAd->CommonCfg.Bss2040CoexistFlag & BSS_2040_COEXIST_INFO_SYNC) && + (pAd->CommonCfg.bForty_Mhz_Intolerant == FALSE)) || + (FlgQloadIsAlarmIssued == TRUE))) + { +#ifdef DBG + UCHAR prevBW, prevExtChOffset; +#ifdef WH_EZ_SETUP + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[0].wdev; +#endif + prevBW = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; + prevExtChOffset = pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset; +#endif /* DBG */ + 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); + + 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; +#if (defined(WH_EZ_SETUP) && defined(EZ_NETWORK_MERGE_SUPPORT)) + if (IS_EZ_SETUP_ENABLED(wdev)){ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("\nPeerPublicAction: Fallback thru ACTION_BSS_2040_COEXIST ****\n")); + ez_set_ap_fallback_context(wdev,TRUE, pAd->CommonCfg.Channel); + } +#endif /* WH_EZ_SETUP */ + } + else + { + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = pAd->CommonCfg.RegTransmitSetting.field.BW; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; +#if (defined(WH_EZ_SETUP) && defined(EZ_NETWORK_MERGE_SUPPORT)) + if (IS_EZ_SETUP_ENABLED(wdev)){ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("\nPeerPublicAction: recover cfg setting thru ACTION_BSS_2040_COEXIST ****\n")); + ez_set_ap_fallback_context(wdev,FALSE,0); + } +#endif /* WH_EZ_SETUP */ + } + 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; + pAd->CommonCfg.Bss2040CoexistFlag |= BSS_2040_COEXIST_BW_SYNC; + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + for(i=0; iApCfg.BssidNum; i++) + { + APUpdateBeaconFrame(pAd, i); + } +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_data.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_data.c new file mode 100644 index 000000000..1f5088a7c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_data.c @@ -0,0 +1,4133 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + ap_data.c + + Abstract: + Data path subroutines + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#include "rt_config.h" + + +INT ApAllowToSendPacket( + IN RTMP_ADAPTER *pAd, + IN struct wifi_dev *wdev, + IN PNDIS_PACKET pPacket, + IN UCHAR *pWcid) +{ + PACKET_INFO PacketInfo; + UCHAR *pSrcBufVA; + UINT SrcBufLen; + MAC_TABLE_ENTRY *pEntry = NULL; +#ifdef NEW_IXIA_METHOD + MAC_TABLE_ENTRY *pIXIAEntry = NULL; + UINT16 TypeLen; +#endif + STA_TR_ENTRY *tr_entry = NULL; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); +#ifdef NEW_IXIA_METHOD + if (pAd->ContinousTxCnt != 1) { + pIXIAEntry = &pAd->MacTab.Content[1]; + TypeLen = (pSrcBufVA[12] << 8) | pSrcBufVA[13]; + if (pIXIAEntry && IS_ENTRY_CLIENT(pIXIAEntry) + && (TypeLen == 0x0800)) { + COPY_MAC_ADDR(pSrcBufVA, pIXIAEntry->Addr); + } + } +#endif + /* 0 is main BSS, FIRST_MBSSID = 1 */ + ASSERT(wdev->func_idx < pAd->ApCfg.BssidNum); + ASSERT (wdev->wdev_type == WDEV_TYPE_AP); + + if (wdev != &pAd->ApCfg.MBSSID[wdev->func_idx].wdev) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): wdev(0x%p) not equal MBSS(0x%p), func_idx=%d\n", + __FUNCTION__, wdev, &pAd->ApCfg.MBSSID[wdev->func_idx].wdev, wdev->func_idx)); + } + +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) + if ((wf_fwd_needed_hook != NULL) && (wf_fwd_needed_hook() == TRUE)) { + if (is_looping_packet(pAd, pPacket)) + return FALSE; + } +#endif /* CONFIG_WIFI_PKT_FWD */ +#endif + if (MAC_ADDR_IS_GROUP(pSrcBufVA)) + { + *pWcid = wdev->tr_tb_idx; +#ifdef A4_CONN + /* If we check an ethernet source move to this device, we should remove it. */ + a4_proxy_delete(pAd, wdev->func_idx, (pSrcBufVA + MAC_ADDR_LEN)); +#endif /* A4_CONN */ + return TRUE; + } + else + { + pEntry = MacTableLookup(pAd, pSrcBufVA); + if (pEntry && (pEntry->Sst == SST_ASSOC)) + { +#ifdef WH_EVENT_NOTIFIER + if(IS_ENTRY_CLIENT(pEntry) +#ifdef A4_CONN + && !IS_ENTRY_A4(pEntry) +#endif /* A4_CONN */ + ) + pEntry->tx_state.PacketCount++; +#endif /* WH_EVENT_NOTIFIER */ + + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + if (tr_entry && (tr_entry->PortSecured != WPA_802_1X_PORT_SECURED)) { + DBGPRINT(RT_DEBUG_ERROR, ("sta port not secure, os should not send packets!!!\n")); + return FALSE; + } + *pWcid = (UCHAR)pEntry->wcid; + return TRUE; + } + +#ifdef CLIENT_WDS + if (pEntry == NULL) { + SST Sst; + USHORT Aid; + UCHAR PsMode, Rate; + + PUCHAR pEntryAddr = CliWds_ProxyLookup(pAd, pSrcBufVA); + if (pEntryAddr != NULL) { + pEntry = APSsPsInquiry(pAd, pEntryAddr, &Sst, &Aid, &PsMode, &Rate); + if ((pEntry && (pEntry->Sst == SST_ASSOC)) { + *pWcid = (UCHAR)Aid; + return TRUE; + } + } + } +#endif /* CLIENT_WDS */ + } +#ifdef A4_CONN + if (pEntry == NULL) { + UCHAR main_wcid = 0; + /* If we check an ethernet source move to this device, we should remove it. */ + a4_proxy_delete(pAd, wdev->func_idx, (pSrcBufVA + MAC_ADDR_LEN)); + if (a4_proxy_lookup(pAd, wdev->func_idx, pSrcBufVA, FALSE, FALSE, &main_wcid)) { + if (VALID_WCID(main_wcid)) + pEntry = &pAd->MacTab.Content[main_wcid]; + + if (pEntry && (pEntry->Sst == SST_ASSOC)){ + tr_entry = &pAd->MacTab.tr_entry[main_wcid]; + if (tr_entry && (tr_entry->PortSecured != WPA_802_1X_PORT_SECURED)) { + DBGPRINT(RT_DEBUG_ERROR, + ("a4 port not secure, os should not send packets!!!\n")); + return FALSE; + } + *pWcid = main_wcid; + return TRUE; + } + } + } +#endif + + return FALSE; +} + +#ifndef NEW_IXIA_METHOD +enum pkt_tx_status{ + PKT_SUCCESS = 0, + INVALID_PKT_LEN = 1, + INVALID_TR_WCID = 2, + INVALID_TR_ENTRY = 3, + INVALID_WDEV = 4, + INVALID_ETH_TYPE = 5, + DROP_PORT_SECURE = 6, + DROP_PSQ_FULL = 7, + DROP_TXQ_FULL = 8, + DROP_TX_JAM = 9, + DROP_TXQ_ENQ_FAIL = 10, +}; +#endif +struct reason_id_str{ + INT id; + RTMP_STRING *code_str; +}; + +/*Nobody uses it currently*/ + +/* + ======================================================================== + Routine Description: + This routine is used to do packet parsing and classification for Tx packet + to AP device, and it will en-queue packets to our TxSwQ depends on AC + class. + + Arguments: + pAd Pointer to our adapter + pPacket Pointer to send packet + + Return Value: + NDIS_STATUS_SUCCESS If succes to queue the packet into TxSwQ. + NDIS_STATUS_FAILURE If failed to do en-queue. + + pre: Before calling this routine, caller should have filled the following fields + + pPacket->MiniportReserved[6] - contains packet source + pPacket->MiniportReserved[5] - contains RA's WDS index (if RA on WDS link) or AID + (if RA directly associated to this AP) + post:This routine should decide the remaining pPacket->MiniportReserved[] fields + before calling APHardTransmit(), such as: + + pPacket->MiniportReserved[4] - Fragment # and User PRiority + pPacket->MiniportReserved[7] - RTS/CTS-to-self protection method and TX rate + + Note: + You only can put OS-indepened & AP related code in here. +======================================================================== +*/ +INT APSendPacket(RTMP_ADAPTER *pAd, PNDIS_PACKET pPacket) +{ + PACKET_INFO PacketInfo; + UCHAR *pSrcBufVA; + UINT SrcBufLen, frag_sz, pkt_len; + UCHAR NumberOfFrag; + UCHAR wcid = RESERVED_WCID, QueIdx, UserPriority; +#ifdef IGMP_SNOOP_SUPPORT + UCHAR Repeat; + INT InIgmpGroup = IGMP_NONE; + MULTICAST_FILTER_TABLE_ENTRY *pGroupEntry = NULL; + MAC_TABLE_ENTRY *pEntry = NULL; +#endif /* IGMP_SNOOP_SUPPORT */ + STA_TR_ENTRY *tr_entry = NULL; + struct wifi_dev *wdev; +#ifdef DBG +#ifndef NEW_IXIA_METHOD + enum pkt_tx_status drop_reason = PKT_SUCCESS; +#else + T_DROP_RESON drop_reason = 0; +#endif +#endif /* DBG */ + INT ret=0; + + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + if ((!pSrcBufVA) || (SrcBufLen <= 14)) { +#ifdef DBG + drop_reason = INVALID_PKT_LEN; +#endif /* DBG */ + goto drop_pkt; + } + + wcid = RTMP_GET_PACKET_WCID(pPacket); +#ifdef IGMP_SNOOP_SUPPORT + if (VALID_WCID(wcid)) + pEntry = &pAd->MacTab.Content[wcid]; +#endif /* IGMP_SNOOP_SUPPORT */ + DBGPRINT(RT_DEBUG_INFO, ("%s(): wcid=%d\n", __FUNCTION__, wcid)); + if (!(VALID_TR_WCID(wcid) && IS_VALID_ENTRY(&pAd->MacTab.tr_entry[wcid]))) { +#ifdef DBG + drop_reason = INVALID_TR_WCID; +#endif /* DBG */ + goto drop_pkt; + } + + tr_entry = &pAd->MacTab.tr_entry[wcid]; + if (!tr_entry->wdev) { +#ifdef DBG + drop_reason = INVALID_WDEV; +#endif /* DBG */ + goto drop_pkt; + } + + wdev = tr_entry->wdev; + UserPriority = 0; + QueIdx = QID_AC_BE; + if (RTMPCheckEtherType(pAd, pPacket, tr_entry, wdev, &UserPriority, &QueIdx, &wcid) == FALSE) { +#ifdef DBG + drop_reason = INVALID_ETH_TYPE; +#endif /* DBG */ + goto drop_pkt; + } + /*add hook point when enqueue*/ + RTMP_OS_TXRXHOOK_CALL(WLAN_TX_ENQUEUE,pPacket,QueIdx,pAd); + +#ifdef CONFIG_HOTSPOT + /* + Re-check the wcid, it maybe broadcast to unicast by RTMPCheckEtherType. + */ + if (wcid != RTMP_GET_PACKET_WCID(pPacket)) + { + wcid = RTMP_GET_PACKET_WCID(pPacket); + //pMacEntry = &pAd->MacTab.Content[wcid]; + tr_entry = &pAd->MacTab.tr_entry[wcid]; + wdev = tr_entry->wdev; + } + + /* Drop broadcast/multicast packet if disable dgaf */ + // TODO: shiang-usw, fix me because MCAST_WCID is not used now! + if (IS_ENTRY_CLIENT(tr_entry)) { + BSS_STRUCT *pMbss = (BSS_STRUCT *)wdev->func_dev; + + if ((wcid == pMbss->wdev.tr_tb_idx) && + (pMbss->HotSpotCtrl.HotSpotEnable || pMbss->HotSpotCtrl.bASANEnable) && + pMbss->HotSpotCtrl.DGAFDisable) { + DBGPRINT(RT_DEBUG_INFO, ("Drop broadcast/multicast packet when dgaf disable\n")); + goto drop_pkt; + } + } +#endif + + /* AP does not send packets before port secured */ + if (tr_entry->PortSecured == WPA_802_1X_PORT_NOT_SECURED && FALSE == pAd->BSendBMToAir) + { + if (!(((wdev->AuthMode >= Ndis802_11AuthModeWPA) +#ifdef DOT1X_SUPPORT + || (wdev->IEEE8021X == TRUE) +#endif /* DOT1X_SUPPORT */ + ) && ((RTMP_GET_PACKET_EAPOL(pPacket) || + RTMP_GET_PACKET_WAI(pPacket)))) + ) + { +#ifdef DBG + drop_reason = DROP_PORT_SECURE; +#endif /* DBG */ + goto drop_pkt; + } + } + +#ifdef MAC_REPEATER_SUPPORT + if (VALID_WCID(wcid)){ + // TODO: shiang-usw, remove pMacEntry here! + MAC_TABLE_ENTRY *pMacEntry = &pAd->MacTab.Content[wcid]; + if (pMacEntry->bReptCli) + pMacEntry->ReptCliIdleCount = 0; + } +#endif /* MAC_REPEATER_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. + + 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. + + exception: + a). fragmentation not allowed on multicast & broadcast + b). Aggregation overwhelms fragmentation (fCLIENT_STATUS_AGGREGATION_CAPABLE) + c). TSO/CSO not do fragmentation + */ + // TODO: shiang-usw. we need to modify the TxPktClassificatio to adjust the NumberOfFrag! + pkt_len = PacketInfo.TotalPacketLength - LENGTH_802_3 + LENGTH_802_1_H; + frag_sz = (pAd->CommonCfg.FragmentThreshold) - LENGTH_802_11 - LENGTH_CRC; + if (pkt_len < frag_sz) + NumberOfFrag = 1; + else + NumberOfFrag = (pkt_len / frag_sz) + 1; + + /* Save fragment number to Ndis packet reserved field */ + RTMP_SET_PACKET_FRAGMENTS(pPacket, NumberOfFrag); + + + /* + 3. Put to corrsponding TxSwQ or Power-saving queue + + a).WDS/ApClient/Mesh link should never go into power-save mode; just send out the frame + b).multicast packets in IgmpSn table should never send to Power-Saving queue. + c). M/BCAST frames are put to PSQ as long as there's any associated STA in power-save mode + */ + // TODO: shiang-usw, remove "ApCfg.IgmpSnoopEnable" and use "wdev->IgmpSnoopEnable" replace it! + if (tr_entry->EntryType == ENTRY_CAT_MCAST) + { +#ifdef IGMP_SNOOP_SUPPORT + //TODO : check global setting only! + if (pAd->ApCfg.IgmpSnoopEnable /*&& wdev->IgmpSnoopEnable*/) + { + if (IgmpPktInfoQuery(pAd, pSrcBufVA, pPacket, wdev, + &InIgmpGroup, &pGroupEntry) != NDIS_STATUS_SUCCESS) + return NDIS_STATUS_FAILURE; + } + + // TODO: shiang-usw, need to revise for Igmp snooping case!! + if (InIgmpGroup) + { + /* 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) + )) + { +#ifdef A4_CONN + if (VALID_WCID(wcid) && pEntry && IS_ENTRY_A4(pEntry)) { + /* do nothing send as it is*/ + } else +#endif + { + NDIS_STATUS PktCloneResult = IgmpPktClone(pAd, pPacket, InIgmpGroup, + pGroupEntry, QueIdx, UserPriority, GET_OS_PKT_NETDEV(pPacket)); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + return PktCloneResult; /* need to alway return to prevent skb double free.*/ + } + } else if (InIgmpGroup == IGMP_PKT) { + NDIS_STATUS CloneResult =0; + UserPriority = 0; + QueIdx = QID_AC_BE; + RTMP_SET_PACKET_UP(pPacket, UserPriority); + RTMP_SET_PACKET_TXTYPE(pPacket, TX_MCAST_FRAME); + + for (Repeat=0; Repeat<3; Repeat++) + { + CloneResult = IgmpProtocolPktClone(pAd, pPacket, InIgmpGroup, NULL, + QueIdx, UserPriority, GET_OS_PKT_NETDEV(pPacket)); + if (CloneResult == NDIS_STATUS_FAILURE) + break; +#ifdef A4_CONN + if (VALID_WCID(wcid) && pEntry && IS_ENTRY_A4(pEntry)) { + /* Do not need retry because it is a unicast packet */ + break; + } +#endif + } + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + return CloneResult; + } + } + else +#endif /* IGMP_SNOOP_SUPPORT */ + { + UserPriority = 0; + QueIdx = QID_AC_BE; + RTMP_SET_PACKET_UP(pPacket, UserPriority); + } + RTMP_SET_PACKET_TXTYPE(pPacket, TX_MCAST_FRAME); + } + else + { +#if defined(RTMP_MAC) || defined(RLT_MAC) + /* detect AC Category of tx packets to tune AC0(BE) TX_OP (MAC reg 0x1300) */ + // TODO: shiang-usw, check this for REG access, it should not be here! + if ((pAd->chipCap.hif_type == HIF_RTMP) || (pAd->chipCap.hif_type == HIF_RLT)) + detect_wmm_traffic(pAd, UserPriority, 1); +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + RTMP_SET_PACKET_UP(pPacket, UserPriority); + + } + +//DBGPRINT(RT_DEBUG_OFF, ("%s(%d): shiang-dbg, QueIdx=%d, tr_entry=%p\n", __FUNCTION__, __LINE__, QueIdx, tr_entry)); + if (pAd->TxSwQueue[QueIdx].Number >= pAd->TxSwQMaxLen) + { + { +#ifdef BLOCK_NET_IF + StopNetIfQueue(pAd, QueIdx, pPacket); +#endif /* BLOCK_NET_IF */ +#ifdef DBG + drop_reason = DROP_TXQ_FULL; +#endif /* DBG */ + goto drop_pkt; + } + } +#ifdef WDS_SUPPORT + else if(IS_ENTRY_WDS(tr_entry)) { + /* when WDS Jam happen, drop following 1min to SWQueue Pkts */ + ULONG Now32; + NdisGetSystemUpTime(&Now32); + + if ((tr_entry->LockEntryTx == TRUE) + && RTMP_TIME_BEFORE(Now32, tr_entry->TimeStamp_toTxRing + WDS_ENTRY_RETRY_INTERVAL)) { +#ifdef DBG + drop_reason = DROP_TX_JAM; +#endif /* DBG */ + goto drop_pkt; + } else { + if (rtmp_enq_req(pAd, pPacket, QueIdx, tr_entry, FALSE,NULL) == FALSE) { +#ifdef DBG + drop_reason = DROP_TXQ_ENQ_FAIL; +#endif /* DBG */ + goto drop_pkt; + } + } + } +#endif /* WDS_SUPPORT */ + else + { +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + if ((pAd->MacTab.fAnyStationInPsm == 1) && (tr_entry->EntryType == ENTRY_CAT_MCAST)) { + if (tr_entry->tx_queue[QID_AC_BE].Number > MAX_PACKETS_IN_MCAST_PS_QUEUE) { + DBGPRINT(RT_DEBUG_INFO, ("%s(%d): BSS tx_queue full\n", __FUNCTION__, __LINE__)); +#ifdef DBG + #ifdef NEW_IXIA_METHOD + drop_reason = DROP_TXQ_ENQ_PS; + #else + drop_reason = DROP_TXQ_ENQ_FAIL; + #endif +#endif /* DBG */ + goto drop_pkt; + } + } else if ((tr_entry->EntryType != ENTRY_CAT_MCAST) && (tr_entry->PsMode == PWR_SAVE)) { + if (tr_entry->tx_queue[QID_AC_BE].Number+tr_entry->tx_queue[QID_AC_BK].Number+tr_entry->tx_queue[QID_AC_VI].Number+tr_entry->tx_queue[QID_AC_VO].Number > MAX_PACKETS_IN_PS_QUEUE) { + DBGPRINT(RT_DEBUG_INFO, ("%s(%d): STA tx_queue full\n", __FUNCTION__, __LINE__)); +#ifdef DBG + #ifdef NEW_IXIA_METHOD + drop_reason = DROP_TXQ_ENQ_PS; + #else + drop_reason = DROP_TXQ_ENQ_FAIL; + #endif +#endif /* DBG */ + goto drop_pkt; + } + } + } +#endif /* MT_MAC */ + +#ifdef UAPSD_SUPPORT + if (IS_ENTRY_CLIENT(tr_entry) + && (tr_entry->PsMode == PWR_SAVE) + && UAPSD_MR_IS_UAPSD_AC(&pAd->MacTab.Content[wcid], QueIdx)) + { + UAPSD_PacketEnqueue(pAd, &pAd->MacTab.Content[wcid], pPacket, QueIdx, FALSE); + } + else +#endif /* UAPSD_SUPPORT */ +#ifdef IP_ASSEMBLY + if ((pAd->CommonCfg.BACapability.field.AutoBA == FALSE) && (ret = rtmp_IpAssembleHandle(pAd,tr_entry, pPacket,QueIdx,PacketInfo))!=NDIS_STATUS_INVALID_DATA) + { + if(ret == NDIS_STATUS_FAILURE) + { + goto nofree_drop_pkt; + } + /*else if success do normal path means*/ + + }else +#endif /* IP_ASSEMBLY */ + if (rtmp_enq_req(pAd, pPacket, QueIdx, tr_entry, FALSE,NULL) == FALSE) { +#ifdef DBG + drop_reason = DROP_TXQ_ENQ_FAIL; +#endif /* DBG */ + goto drop_pkt; + } + + /* If the data is broadcast/multicast and any stations are in PWR_SAVE, we set BCAST TIM bit. */ + /* If the data is unicast and the station is in PWR_SAVE, we set STA TIM bit */ + if (tr_entry->EntryType == ENTRY_CAT_MCAST) + { + if (pAd->MacTab.fAnyStationInPsm == TRUE) + WLAN_MR_TIM_BCMC_SET(tr_entry->func_tb_idx); /* mark MCAST/BCAST TIM bit */ + } + else + { + if (IS_ENTRY_CLIENT(tr_entry) && (tr_entry->PsMode == PWR_SAVE)) + { + /* mark corresponding TIM bit in outgoing BEACON frame */ +#ifdef UAPSD_SUPPORT + if (UAPSD_MR_IS_NOT_TIM_BIT_NEEDED_HANDLED(&pAd->MacTab.Content[wcid], 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, tr_entry->func_tb_idx, tr_entry->wcid); + } + } + } + } + +//dump_tr_entry(pAd, wcid, __FUNCTION__, __LINE__); +//DBGPRINT(RT_DEBUG_OFF, ("%s(%d): shiang-dbg EnQDone done\n", __FUNCTION__, __LINE__)); + + // TODO: shiang-usw, backup code here for ACM/WDS->LockTx related functions + +#ifdef DOT11_N_SUPPORT + RTMP_BASetup(pAd, tr_entry, UserPriority); +#endif /* DOT11_N_SUPPORT */ + + return NDIS_STATUS_SUCCESS; + +drop_pkt: + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); +#ifdef NEW_IXIA_METHOD + if (IS_EXPECTED_LENGTH(RTPKT_TO_OSPKT(pPacket)->len)) + pAd->tr_ststic.tx[drop_reason]++; +#endif +nofree_drop_pkt: + /*add hook point when drop*/ + RTMP_OS_TXRXHOOK_CALL(WLAN_TX_DROP,NULL,QueIdx,pAd); + DBGPRINT(RT_DEBUG_INFO, ("%s():drop pkt, drop_reason=%d!, wcid = %d\n", __FUNCTION__, drop_reason, wcid)); + + return NDIS_STATUS_FAILURE; +} + + +/* + -------------------------------------------------------- + FIND ENCRYPT KEY AND DECIDE CIPHER ALGORITHM + Find the WPA key, either Group or Pairwise Key + LEAP + TKIP also use WPA key. + -------------------------------------------------------- + Decide WEP bit and cipher suite to be used. + Same cipher suite should be used for whole fragment burst + In Cisco CCX 2.0 Leap Authentication + WepStatus is Ndis802_11WEPEnabled but the key will use PairwiseKey + Instead of the SharedKey, SharedKey Length may be Zero. +*/ +static inline VOID APFindCipherAlgorithm(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + CIPHER_KEY *pKey = NULL; + UCHAR KeyIdx = 0, CipherAlg = CIPHER_NONE; + UCHAR RAWcid = pTxBlk->Wcid; + MAC_TABLE_ENTRY *pMacEntry = pTxBlk->pMacEntry; +#if defined(APCLI_SUPPORT) && defined(WPA_SUPPLICANT_SUPPORT) + STA_TR_ENTRY *tr_entry = pTxBlk->tr_entry; +#endif /* defined(APCLI_SUPPORT) && defined(WPA_SUPPLICANT_SUPPORT) */ +#ifdef WAPI_SUPPORT + BSS_STRUCT *pMbss; +#endif /* WAPI_SUPPORT */ + struct wifi_dev *wdev; + + ASSERT(pTxBlk->wdev_idx < WDEV_NUM_MAX); + wdev = pAd->wdev_list[pTxBlk->wdev_idx]; + + if (wdev->wdev_type == WDEV_TYPE_WDS) { + ASSERT(wdev->func_idx < MAX_WDS_ENTRY); + DBGPRINT(RT_DEBUG_TRACE, ("%s():WDS func_idx %d\n", __func__, wdev->func_idx)); + } else { + ASSERT(wdev->func_idx < pAd->ApCfg.BssidNum); + DBGPRINT(RT_DEBUG_TRACE, ("%s():BSS func_idx %d\n", __func__, wdev->func_idx)); + } + +#ifdef WAPI_SUPPORT + pMbss = &pAd->ApCfg.MBSSID[wdev->func_idx]; +#endif /* WAPI_SUPPORT */ + // TODO: shiang-usw, we should use this check to replace rest of the codes! + + /* These EAPoL frames must be clear before 4-way handshaking is completed. */ + if ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame))) + { + CipherAlg = CIPHER_NONE; + pKey = NULL; + } else +#ifdef APCLI_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bApCliPacket)) + { + APCLI_STRUCT *pApCliEntry = pTxBlk->pApCliEntry; + wdev = &pApCliEntry->wdev; + + if (RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) + { + /* These EAPoL frames must be clear before 4-way handshaking is completed. */ + if ((pMacEntry->PairwiseKey.CipherAlg) && (pMacEntry->PairwiseKey.KeyLen)) + { + CipherAlg = pMacEntry->PairwiseKey.CipherAlg; + pKey = &pMacEntry->PairwiseKey; + } + else + { + CipherAlg = CIPHER_NONE; + pKey = NULL; + } + } + else if (pMacEntry->WepStatus == Ndis802_11WEPEnabled) + { + CipherAlg = pApCliEntry->SharedKey[wdev->DefaultKeyId].CipherAlg; + pKey = &pApCliEntry->SharedKey[wdev->DefaultKeyId]; + } + else if (pMacEntry->WepStatus == Ndis802_11TKIPEnable || + pMacEntry->WepStatus == Ndis802_11AESEnable) + { + CipherAlg = pMacEntry->PairwiseKey.CipherAlg; + pKey = &pMacEntry->PairwiseKey; + } + else + { + CipherAlg = CIPHER_NONE; + pKey = NULL; + } + } + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk,fTX_bWDSEntry)) + { + wdev = &pAd->WdsTab.WdsEntry[pMacEntry->func_tb_idx].wdev; + if (wdev->WepStatus == Ndis802_11WEPEnabled || + wdev->WepStatus == Ndis802_11TKIPEnable || + wdev->WepStatus == Ndis802_11AESEnable) + { + CipherAlg = pAd->WdsTab.WdsEntry[pMacEntry->func_tb_idx].WdsKey.CipherAlg; + pKey = &pAd->WdsTab.WdsEntry[pMacEntry->func_tb_idx].WdsKey; + } + else + { + CipherAlg = CIPHER_NONE; + pKey = NULL; + } + } + else +#endif /* WDS_SUPPORT */ +#ifdef WAPI_SUPPORT + if (pMbss->wdev.WepStatus == Ndis802_11EncryptionSMS4Enabled) + { + if (RTMP_GET_PACKET_WAI(pTxBlk->pPacket)) { + /* WAI negotiation packet is always clear. */ + CipherAlg = CIPHER_NONE; + pKey = NULL; + } + else if (!pMacEntry) + { + KeyIdx = pMbss->wdev.DefaultKeyId; /* MSK ID */ + CipherAlg = pAd->SharedKey[wdev->func_idx][KeyIdx].CipherAlg; + if (CipherAlg == CIPHER_SMS4) { + pKey = &pAd->SharedKey[wdev->func_idx][KeyIdx]; +#ifdef SOFT_ENCRYPT + if (pMbss->sw_wpi_encrypt) { + TX_BLK_SET_FLAG(pTxBlk, fTX_bSwEncrypt); + /* TSC increment pre encryption transmittion */ + inc_iv_byte(pKey->TxTsc, LEN_WAPI_TSC, 1); + } +#endif /* SOFT_ENCRYPT */ + } + } + else + { + KeyIdx = pTxBlk->pMacEntry->usk_id; /* USK ID */ + CipherAlg = pAd->MacTab.Content[RAWcid].PairwiseKey.CipherAlg; + if (CipherAlg == CIPHER_SMS4) + { + pKey = &pAd->MacTab.Content[RAWcid].PairwiseKey; +#ifdef SOFT_ENCRYPT + if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT)) { + TX_BLK_SET_FLAG(pTxBlk, fTX_bSwEncrypt); + /* TSC increment pre encryption transmittion */ + inc_iv_byte(pKey->TxTsc, LEN_WAPI_TSC, 2); + } +#endif /* SOFT_ENCRYPT */ + } + } + } + else +#endif /* WAPI_SUPPORT */ + if ((RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) || +#ifdef DOT1X_SUPPORT + ((wdev->WepStatus == Ndis802_11WEPEnabled) && (wdev->IEEE8021X == TRUE)) || +#endif /* DOT1X_SUPPORT */ + (wdev->WepStatus == Ndis802_11TKIPEnable) || + (wdev->WepStatus == Ndis802_11AESEnable) || + (wdev->WepStatus == Ndis802_11TKIPAESMix)) + { + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bClearEAPFrame)) + { + DBGPRINT(RT_DEBUG_TRACE,("%s():clear EAP frm\n", __FUNCTION__)); + CipherAlg = CIPHER_NONE; + pKey = NULL; + } + else if (!pMacEntry) /* M/BCAST to local BSS, use default key in shared key table */ + { + KeyIdx = wdev->DefaultKeyId; + CipherAlg = pAd->SharedKey[wdev->func_idx][KeyIdx].CipherAlg; + pKey = &pAd->SharedKey[wdev->func_idx][KeyIdx]; + } + else /* unicast to local BSS */ + { + CipherAlg = pAd->MacTab.Content[RAWcid].PairwiseKey.CipherAlg; + pKey = &pAd->MacTab.Content[RAWcid].PairwiseKey; + +#ifdef SOFT_ENCRYPT + if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bSwEncrypt); + + /* TSC increment pre encryption transmittion */ + if (pKey == NULL) + DBGPRINT(RT_DEBUG_ERROR, ("%s pKey == NULL!\n", __FUNCTION__)); + else + { + INC_TX_TSC(pKey->TxTsc, LEN_WPA_TSC); + } + } +#endif /* SOFT_ENCRYPT */ + } + } + else if (wdev->WepStatus == Ndis802_11WEPEnabled) /* WEP always uses shared key table */ + { + KeyIdx = wdev->DefaultKeyId; + CipherAlg = pAd->SharedKey[wdev->func_idx][KeyIdx].CipherAlg; + pKey = &pAd->SharedKey[wdev->func_idx][KeyIdx]; + } + else + { + CipherAlg = CIPHER_NONE; + pKey = NULL; + } + + pTxBlk->CipherAlg = CipherAlg; + if (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) +{ + STA_TR_ENTRY *tr_entry; + HEADER_802_11 *pHeader80211; +#if defined(MESH_SUPPORT) || defined(APCLI_SUPPORT) + MAC_TABLE_ENTRY *pMacEntry = pTxBlk->pMacEntry; +#endif + pHeader80211 = (PHEADER_802_11)pHeader; + tr_entry = pTxBlk->tr_entry; + + /* + Update the cached 802.11 HEADER + */ + + /* normal wlan header size : 24 octets */ + pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11); + pTxBlk->wifi_hdr_len = sizeof(HEADER_802_11); + + /* More Bit */ + pHeader80211->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); + + /* Sequence */ + pHeader80211->Sequence = tr_entry->TxSeq[pTxBlk->UserPriority]; + tr_entry->TxSeq[pTxBlk->UserPriority] = (tr_entry->TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ; + + /* SA */ +#if defined(WDS_SUPPORT) || defined(CLIENT_WDS) + if (FALSE +#ifdef WDS_SUPPORT + || TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry) +#endif /* WDS_SUPPORT */ +#ifdef CLIENT_WDS + || TX_BLK_TEST_FLAG(pTxBlk, fTX_bClientWDSFrame) +#endif /* CLIENT_WDS */ + ) + { /* The addr3 of WDS packet is Destination Mac address and Addr4 is the Source Mac address. */ + COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader); + COPY_MAC_ADDR(pHeader80211->Octet, pTxBlk->pSrcBufHeader + MAC_ADDR_LEN); + pTxBlk->MpduHeaderLen += MAC_ADDR_LEN; + pTxBlk->wifi_hdr_len += MAC_ADDR_LEN; + } + else +#endif /* WDS_SUPPORT || CLIENT_WDS */ +#ifdef A4_CONN + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bA4Frame)) + { + pHeader80211->FC.ToDs = 1; + pHeader80211->FC.FrDs = 1; + if(pTxBlk->pMacEntry) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pTxBlk->pMacEntry)) + { + COPY_MAC_ADDR(pHeader80211->Addr1, APCLI_ROOT_BSSID_GET(pAd, pTxBlk->Wcid)); /* to AP2 */ + COPY_MAC_ADDR(pHeader80211->Addr2, pTxBlk->pApCliEntry->wdev.if_addr); + } + else +#endif /* APCLI_SUPPORT */ + if (IS_ENTRY_CLIENT(pTxBlk->pMacEntry)) + { + COPY_MAC_ADDR(pHeader80211->Addr1, pTxBlk->pMacEntry->Addr);/* to AP2 */ + COPY_MAC_ADDR(pHeader80211->Addr2, pTxBlk->pMacEntry->wdev->bssid); + } + COPY_MAC_ADDR(pHeader80211->Addr3, pTxBlk->pSrcBufHeader); /* DA */ + COPY_MAC_ADDR(pHeader80211->Octet, pTxBlk->pSrcBufHeader + MAC_ADDR_LEN);/* ADDR4 = SA */ + pTxBlk->MpduHeaderLen += MAC_ADDR_LEN; + pTxBlk->wifi_hdr_len += MAC_ADDR_LEN; + } + else + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("%s pTxBlk->pMacEntry == NULL!\n", __FUNCTION__)); + } + else +#endif /* A4_CONN */ +#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); + } +} + + +#ifdef HDR_TRANS_TX_SUPPORT +static inline VOID APBuildCacheWifiInfo( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN UCHAR *pWiInfo) +{ + STA_TR_ENTRY *tr_entry; + + TX_WIFI_INFO *pWI; + + pWI = (TX_WIFI_INFO *)pWiInfo; + tr_entry = pTxBlk->tr_entry; + + /* WIFI INFO size : 4 octets */ + pTxBlk->MpduHeaderLen = TX_WIFI_INFO_SIZE; + + /* More Bit */ + pWI->field.More_Data = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); + + /* Sequence */ + pWI->field.Seq_Num = tr_entry->TxSeq[pTxBlk->UserPriority]; + tr_entry->TxSeq[pTxBlk->UserPriority] = (tr_entry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ; +} +#endif /* HDR_TRANS_TX_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + + +#ifdef HDR_TRANS_TX_SUPPORT +static inline VOID APBuildWifiInfo(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + UINT8 TXWISize = pAd->chipCap.TXWISize; + TX_WIFI_INFO *pWI; + STA_TR_ENTRY *tr_entry = pTxBlk->tr_entry; + + /* WIFI INFO size : 4 octets */ + pTxBlk->MpduHeaderLen = TX_WIFI_INFO_SIZE; + + pWI = (TX_WIFI_INFO *)&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]; + + NdisZeroMemory(pWI, TX_WIFI_INFO_SIZE); + +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pTxBlk->pMacEntry)) + pWI->field.Mode = 2; /* STA */ + else +#endif /* APCLI_SUPPORT */ + pWI->field.Mode = 1; /* AP */ + + pWI->field.QoS = (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? 1 : 0; + + if (pTxBlk->pMacEntry && tr_entry) + { + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) + { + pWI->field.Seq_Num = tr_entry->TxSeq[pTxBlk->UserPriority]; + tr_entry->TxSeq[pTxBlk->UserPriority] = (tr_entry->TxSeq[pTxBlk->UserPriority]+1) & MAXSEQ; + } else { + pWI->field.Seq_Num = tr_entry->NonQosDataSeq; + tr_entry->NonQosDataSeq = (tr_entry->NonQosDataSeq+1) & MAXSEQ; + } + pWI->field.BssIdx = pTxBlk->pMacEntry->func_tb_idx; + } + else + { + pWI->field.Seq_Num = pAd->Sequence; + pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; /* next sequence */ + } + + pWI->field.More_Data = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); + + if (pTxBlk->CipherAlg != CIPHER_NONE) + pWI->field.WEP = 1; +} +#endif /* HDR_TRANS_TX_SUPPORT */ + + +static inline VOID APBuildCommon802_11Header(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + HEADER_802_11 *wifi_hdr; + UINT8 tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len; + struct wifi_dev *wdev = pAd->wdev_list[pTxBlk->wdev_idx]; + STA_TR_ENTRY *tr_entry = pTxBlk->tr_entry; + + /* + MAKE A COMMON 802.11 HEADER + */ + + /* normal wlan header size : 24 octets */ + pTxBlk->MpduHeaderLen = sizeof(HEADER_802_11); + pTxBlk->wifi_hdr_len = sizeof(HEADER_802_11); + // TODO: shiang-7603 + pTxBlk->wifi_hdr = &pTxBlk->HeaderBuf[tx_hw_hdr_len]; + + wifi_hdr = (HEADER_802_11 *)pTxBlk->wifi_hdr; + NdisZeroMemory(wifi_hdr, sizeof(HEADER_802_11)); + + wifi_hdr->FC.FrDs = 1; + wifi_hdr->FC.Type = FC_TYPE_DATA; + wifi_hdr->FC.SubType = ((TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) ? SUBTYPE_QDATA : SUBTYPE_DATA); + + // TODO: shiang-usw, for BCAST/MCAST, original it's sequence assigned by "pAd->Sequence", how about now? + if (tr_entry) { + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) { + wifi_hdr->Sequence = tr_entry->TxSeq[pTxBlk->UserPriority]; + tr_entry->TxSeq[pTxBlk->UserPriority] = (tr_entry->TxSeq[pTxBlk->UserPriority] + 1) & MAXSEQ; + } else { + wifi_hdr->Sequence = tr_entry->NonQosDataSeq; + tr_entry->NonQosDataSeq = (tr_entry->NonQosDataSeq + 1) & MAXSEQ; + } + } + else + { + wifi_hdr->Sequence = pAd->Sequence; + pAd->Sequence = (pAd->Sequence + 1) & MAXSEQ; /* next sequence */ + } + + wifi_hdr->Frag = 0; + wifi_hdr->FC.MoreData = TX_BLK_TEST_FLAG(pTxBlk, fTX_bMoreData); + +#ifdef A4_CONN + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bA4Frame)) + { + wifi_hdr->FC.ToDs = 1; + wifi_hdr->FC.FrDs = 1; + if(pTxBlk->pMacEntry) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pTxBlk->pMacEntry)) + { + COPY_MAC_ADDR(wifi_hdr->Addr1, APCLI_ROOT_BSSID_GET(pAd, pTxBlk->Wcid)); /* to AP2 */ + COPY_MAC_ADDR(wifi_hdr->Addr2, pTxBlk->pApCliEntry->wdev.if_addr); + } + else +#endif /* APCLI_SUPPORT */ + if (IS_ENTRY_CLIENT(pTxBlk->pMacEntry)) + { + COPY_MAC_ADDR(wifi_hdr->Addr1, pTxBlk->pMacEntry->Addr);/* to AP2 */ + COPY_MAC_ADDR(wifi_hdr->Addr2, pTxBlk->pMacEntry->wdev->bssid); + } + COPY_MAC_ADDR(wifi_hdr->Addr3, pTxBlk->pSrcBufHeader); /* DA */ + COPY_MAC_ADDR(&wifi_hdr->Octet[0], pTxBlk->pSrcBufHeader + MAC_ADDR_LEN);/* ADDR4 = SA */ + pTxBlk->MpduHeaderLen += MAC_ADDR_LEN; + pTxBlk->wifi_hdr_len += MAC_ADDR_LEN; + } + else + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("%s pTxBlk->pMacEntry == NULL!\n", __FUNCTION__)); + } + else +#endif /* A4_CONN */ +#ifdef APCLI_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bApCliPacket)) + { + wifi_hdr->FC.ToDs = 1; + wifi_hdr->FC.FrDs = 0; + COPY_MAC_ADDR(wifi_hdr->Addr1, APCLI_ROOT_BSSID_GET(pAd, pTxBlk->Wcid)); /* to AP2 */ +#ifdef MAC_REPEATER_SUPPORT + if (pTxBlk->pMacEntry && (pTxBlk->pMacEntry->bReptCli == TRUE)) + COPY_MAC_ADDR(wifi_hdr->Addr2, pTxBlk->pMacEntry->ReptCliAddr); + else +#endif /* MAC_REPEATER_SUPPORT */ + COPY_MAC_ADDR(wifi_hdr->Addr2, pTxBlk->pApCliEntry->wdev.if_addr); /* from AP1 */ + COPY_MAC_ADDR(wifi_hdr->Addr3, pTxBlk->pSrcBufHeader); /* DA */ + } + else +#endif /* APCLI_SUPPORT */ +#if defined(WDS_SUPPORT) || defined(CLIENT_WDS) + if (FALSE +#ifdef WDS_SUPPORT + || TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry) +#endif /* WDS_SUPPORT */ +#ifdef CLIENT_WDS + || TX_BLK_TEST_FLAG(pTxBlk, fTX_bClientWDSFrame) +#endif /* CLIENT_WDS */ + ) + { + wifi_hdr->FC.ToDs = 1; + if (pTxBlk->pMacEntry == NULL) + DBGPRINT(RT_DEBUG_ERROR, ("%s pTxBlk->pMacEntry == NULL!\n", __FUNCTION__)); + else + COPY_MAC_ADDR(wifi_hdr->Addr1, pTxBlk->pMacEntry->Addr); /* to AP2 */ + + COPY_MAC_ADDR(wifi_hdr->Addr2, pAd->CurrentAddress); /* from AP1 */ + COPY_MAC_ADDR(wifi_hdr->Addr3, pTxBlk->pSrcBufHeader); /* DA */ + COPY_MAC_ADDR(&wifi_hdr->Octet[0], pTxBlk->pSrcBufHeader + MAC_ADDR_LEN);/* ADDR4 = SA */ + pTxBlk->MpduHeaderLen += MAC_ADDR_LEN; + pTxBlk->wifi_hdr_len += 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 */ +#if defined(IGMP_SNOOP_SUPPORT) || defined(DOT11V_WNM_SUPPORT) + if (pTxBlk->tr_entry->EntryType != ENTRY_CAT_MCAST) + { + COPY_MAC_ADDR(wifi_hdr->Addr1, pTxBlk->pMacEntry->Addr); /* DA */ + } + else +#endif /* defined(IGMP_SNOOP_SUPPORT) || defined(DOT11V_WNM_SUPPORT) */ + { + COPY_MAC_ADDR(wifi_hdr->Addr1, pTxBlk->pSrcBufHeader); + } + COPY_MAC_ADDR(wifi_hdr->Addr2, pAd->ApCfg.MBSSID[wdev->func_idx].wdev.bssid); /* BSSID */ + COPY_MAC_ADDR(wifi_hdr->Addr3, pTxBlk->pSrcBufHeader + MAC_ADDR_LEN); /* SA */ + } + + if (pTxBlk->CipherAlg != CIPHER_NONE) + wifi_hdr->FC.Wep = 1; +} + + +static inline PUCHAR AP_Build_ARalink_Frame_Header(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + UCHAR *pHeaderBufPtr; + HEADER_802_11 *wifi_hdr; + PNDIS_PACKET pNextPacket; + UINT32 nextBufLen; + PQUEUE_ENTRY pQEntry; + + APFindCipherAlgorithm(pAd, pTxBlk); + APBuildCommon802_11Header(pAd, pTxBlk); + + pHeaderBufPtr = pTxBlk->wifi_hdr; + + wifi_hdr = (HEADER_802_11 *)pHeaderBufPtr; + + /* steal "order" bit to mark "aggregation" */ + wifi_hdr->FC.Order = 1; + + /* skip common header */ + pHeaderBufPtr += pTxBlk->wifi_hdr_len; + + 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; + pTxBlk->wifi_hdr_len += 2; + } + + /* padding at front of LLC header. LLC header should at 4-bytes aligment. */ + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (UCHAR *)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; + pTxBlk->wifi_hdr_len += 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(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + UCHAR *buf_ptr; + HEADER_802_11 *wifi_hdr; + + APFindCipherAlgorithm(pAd, pTxBlk); + APBuildCommon802_11Header(pAd, pTxBlk); + + buf_ptr = pTxBlk->wifi_hdr; + wifi_hdr = (HEADER_802_11 *)buf_ptr; + + if(wifi_hdr == NULL) + DBGPRINT(RT_DEBUG_TRACE, ("wifi_hdr is NULL.\n")); + + /* skip common header */ + buf_ptr += pTxBlk->wifi_hdr_len; + + /* build QOS Control bytes */ + *buf_ptr = (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)) + *buf_ptr |= (1 << 4); + } +#endif /* UAPSD_SUPPORT */ + + /* A-MSDU packet */ + *buf_ptr |= 0x80; + + *(buf_ptr + 1) = 0; + buf_ptr += 2; + pTxBlk->MpduHeaderLen += 2; + pTxBlk->wifi_hdr_len += 2; + + + /* + padding at front of LLC header + LLC header should locate at 4-octets aligment + @@@ MpduHeaderLen excluding padding @@@ + */ + pTxBlk->HdrPadLen = (ULONG)buf_ptr; + buf_ptr = (UCHAR *)(ROUND_UP(buf_ptr, 4)); + pTxBlk->HdrPadLen = (ULONG)(buf_ptr - pTxBlk->HdrPadLen); + + return buf_ptr; + +} + +#ifdef NEW_IXIA_METHOD +int tx_pkt_to_hw = 1; +int rx_pkt_len = 9999; +int rx_pkt_from_hw = 1; +UINT rxpktdetect2s = 1; +#endif +VOID AP_AMPDU_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + HEADER_802_11 *wifi_hdr; + UCHAR *pHeaderBufPtr, *src_ptr; + USHORT freeCnt = 1; + BOOLEAN bVLANPkt; + MAC_TABLE_ENTRY *pMacEntry; + STA_TR_ENTRY *tr_entry; + PQUEUE_ENTRY pQEntry; + BOOLEAN bHTCPlus = FALSE; + UINT hdr_offset, cache_sz; +#ifdef NEW_IXIA_METHOD + struct sk_buff *kickout_pkt = (struct sk_buff *)(pTxBlk->pPacket); +#endif + ASSERT(pTxBlk); + + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) { +#ifdef STATS_COUNT_SUPPORT + BSS_STRUCT *pMbss = pTxBlk->pMbss; + + if (pMbss != NULL) + { + pMbss->TxDropCount++; + } +#endif /* STATS_COUNT_SUPPORT */ +#ifdef NEW_IXIA_METHOD + if (IS_EXPECTED_LENGTH(kickout_pkt->len)) + pAd->tr_ststic.tx[DROP_BLK_INFO_ERROR]++; +#endif + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + +#if defined(MT7603) || defined(MT7628) + // TODO: shiang-7603 + hdr_offset = pAd->chipCap.tx_hw_hdr_len; +#else + hdr_offset = TXINFO_SIZE + pAd->chipCap.TXWISize + TSO_SIZE; +#endif /* defined(MT7603) || defined(MT7628) */ + pMacEntry = pTxBlk->pMacEntry; + tr_entry = pTxBlk->tr_entry; + if ((tr_entry->isCached) + ) + { +#if defined(MT7603) || defined(MT7628) +#ifndef VENDOR_FEATURE1_SUPPORT + NdisMoveMemory((UCHAR *)(&pTxBlk->HeaderBuf[0]), + (UCHAR *)(&tr_entry->CachedBuf[0]), + pAd->chipCap.tx_hw_hdr_len + sizeof(HEADER_802_11)); +#else + pTxBlk->HeaderBuf = (UCHAR *)(tr_entry->HeaderBuf); +#endif /* VENDOR_FEATURE1_SUPPORT */ +#else +#ifndef VENDOR_FEATURE1_SUPPORT + NdisMoveMemory((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), + (UCHAR *)(&tr_entry->CachedBuf[0]), + pAd->chipCap.TXWISize + sizeof(HEADER_802_11)); +#else + pTxBlk->HeaderBuf = (UCHAR *)(tr_entry->HeaderBuf); +#endif /* VENDOR_FEATURE1_SUPPORT */ +#endif /* defined(MT7603) || defined(MT7628) */ + + pHeaderBufPtr = (UCHAR *)(&pTxBlk->HeaderBuf[hdr_offset]); + APBuildCache802_11Header(pAd, pTxBlk, pHeaderBufPtr); + +#ifdef SOFT_ENCRYPT + RTMPUpdateSwCacheCipherInfo(pAd, pTxBlk, pHeaderBufPtr); +#endif /* SOFT_ENCRYPT */ + } + else + { + APFindCipherAlgorithm(pAd, pTxBlk); + APBuildCommon802_11Header(pAd, pTxBlk); + + pHeaderBufPtr = &pTxBlk->HeaderBuf[hdr_offset]; + } + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) { + if (RTMPExpandPacketForSwEncrypt(pAd, pTxBlk) == FALSE) { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + } +#endif /* SOFT_ENCRYPT */ + + wifi_hdr = (HEADER_802_11 *)pHeaderBufPtr; + +//+++Add by shiang for debug +//---Add by shiang for debug + + /* skip common header */ + pHeaderBufPtr += pTxBlk->MpduHeaderLen; + +#ifdef VENDOR_FEATURE1_SUPPORT + if (tr_entry->isCached + && (tr_entry->Protocol == (RTMP_GET_PACKET_PROTOCOL(pTxBlk->pPacket))) +#ifdef SOFT_ENCRYPT + && !TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt) +#endif /* SOFT_ENCRYPT */ + ) + { + /* build QOS Control bytes */ + *pHeaderBufPtr = (pTxBlk->UserPriority & 0x0F); +#ifdef UAPSD_SUPPORT + if (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE) +#ifdef WDS_SUPPORT + && (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry) == FALSE) +#endif /* WDS_SUPPORT */ + ) + { + /* + * we can not use bMoreData bit to get EOSP bit because + * maybe bMoreData = 1 & EOSP = 1 when Max SP Length != 0 + */ + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP)) + *pHeaderBufPtr |= (1 << 4); + } +#endif /* UAPSD_SUPPORT */ + pTxBlk->MpduHeaderLen = tr_entry->MpduHeaderLen; + pTxBlk->wifi_hdr_len = tr_entry->wifi_hdr_len; + pHeaderBufPtr = ((UCHAR *)wifi_hdr) + pTxBlk->MpduHeaderLen; + + pTxBlk->HdrPadLen = tr_entry->HdrPadLen; + + /* skip 802.3 header */ + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + /* skip vlan tag */ + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + if (bVLANPkt) { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + } + else +#endif /* VENDOR_FEATURE1_SUPPORT */ + { + /* 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; + pTxBlk->wifi_hdr_len += 2; + +#ifndef MT_MAC + // TODO: Shiang-usw, we need a more proper way to handle this instead of ifndef MT_MAC ! + /* For MT_MAC, SW not to prepare the HTC field for RDG enable */ + /* build HTC control field after QoS field */ + if ((pAd->CommonCfg.bRdg == TRUE) + && (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)) + ) + { + NdisZeroMemory(pHeaderBufPtr, sizeof(HT_CONTROL)); + ((PHT_CONTROL)pHeaderBufPtr)->RDG = 1; + bHTCPlus = TRUE; + } +#endif /* MT_MAC */ + + + if (bHTCPlus == TRUE) + { + wifi_hdr->FC.Order = 1; + pHeaderBufPtr += 4; + pTxBlk->MpduHeaderLen += 4; + pTxBlk->wifi_hdr_len += 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; + } + + /* + padding at front of LLC header + LLC header should locate at 4-octets aligment + + @@@ MpduHeaderLen excluding padding @@@ + */ + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (UCHAR *)ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + +#ifdef VENDOR_FEATURE1_SUPPORT + tr_entry->HdrPadLen = pTxBlk->HdrPadLen; +#endif /* VENDOR_FEATURE1_SUPPORT */ + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) { + tx_sw_encrypt(pAd, pTxBlk, pHeaderBufPtr, wifi_hdr); + } + else +#endif /* SOFT_ENCRYPT */ + { + + /* + Insert LLC-SNAP encapsulation - 8 octets + if original Ethernet frame contains no LLC/SNAP, + then an extra LLC/SNAP encap is required + */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_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 + tr_entry->Protocol = RTMP_GET_PACKET_PROTOCOL(pTxBlk->pPacket); + tr_entry->MpduHeaderLen = pTxBlk->MpduHeaderLen; + tr_entry->wifi_hdr_len = pTxBlk->wifi_hdr_len; +#endif /* VENDOR_FEATURE1_SUPPORT */ + } + + if ((tr_entry->isCached) + ) + { + write_tmac_info_Cache(pAd, &pTxBlk->HeaderBuf[0], pTxBlk); + } + else + { + write_tmac_info_Data(pAd, &pTxBlk->HeaderBuf[0], pTxBlk); + + if (RTMP_GET_PACKET_LOWRATE(pTxBlk->pPacket)) + tr_entry->isCached = FALSE; + + + NdisZeroMemory((UCHAR *)(&tr_entry->CachedBuf[0]), sizeof(tr_entry->CachedBuf)); +#if defined(MT7603) || defined(MT7628) + cache_sz = (pHeaderBufPtr - (UCHAR *)(&pTxBlk->HeaderBuf[0])); + src_ptr = (UCHAR *)&pTxBlk->HeaderBuf[0]; +#else + cache_sz = (pHeaderBufPtr - (UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE])); + src_ptr = (UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]); +#endif /* defined(MT7603) || defined(MT7628) */ + NdisMoveMemory((UCHAR *)(&tr_entry->CachedBuf[0]), src_ptr, cache_sz); + +#ifdef VENDOR_FEATURE1_SUPPORT + /* use space to get performance enhancement */ + NdisZeroMemory((UCHAR *)(&tr_entry->HeaderBuf[0]), sizeof(tr_entry->HeaderBuf)); +#if defined(MT7603) || defined(MT7628) + NdisMoveMemory((UCHAR *)(&tr_entry->HeaderBuf[0]), + (UCHAR *)(&pTxBlk->HeaderBuf[0]), cache_sz); +#else + NdisMoveMemory((UCHAR *)(&tr_entry->HeaderBuf[0]), + (UCHAR *)(&pTxBlk->HeaderBuf[0]), + (pHeaderBufPtr - (UCHAR *)(&pTxBlk->HeaderBuf[0]))); +#endif /* defined(MT7603) || defined(MT7628) */ +#endif /* VENDOR_FEATURE1_SUPPORT */ + +//+++Mark by shiang test +// tr_entry->isCached = TRUE; +//---Mark by shiang for test + } + +//+++Add by shiang for debug +#if defined(MT7603) || defined(MT7628) +#endif /* MT7603 */ +//---Add by shiang for debug + + +#ifdef STATS_COUNT_SUPPORT + pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart++; + pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen; + + /* calculate Tx count and ByteCount per BSS */ + { + BSS_STRUCT *pMbss = pTxBlk->pMbss; + +#ifdef WAPI_SUPPORT + if (IS_ENTRY_CLIENT(pMacEntry)) + { + 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; + pMacEntry->OneSecTxBytes+=pTxBlk->SrcBufLen; + pAd->TxTotalByteCnt += pTxBlk->SrcBufLen; +#ifdef DYNAMIC_WMM + pAd->TxTotalByteCnt_Dyn[pTxBlk->QueIdx] += pTxBlk->SrcBufLen; +#endif /* DYNAMIC_WMM */ + } + } + +#ifdef WDS_SUPPORT + if (pMacEntry && IS_ENTRY_WDS(pMacEntry)) + { + INC_COUNTER64(pAd->WdsTab.WdsEntry[pMacEntry->func_tb_idx].WdsCounter.TransmittedFragmentCount); + pAd->WdsTab.WdsEntry[pMacEntry->func_tb_idx].WdsCounter.TransmittedByteCount+= pTxBlk->SrcBufLen; + } +#endif /* WDS_SUPPORT */ +#endif /* STATS_COUNT_SUPPORT */ + + HAL_WriteTxResource(pAd, pTxBlk, TRUE, &freeCnt); + + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (UCHAR *)wifi_hdr); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + /* + Kick out Tx + */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); +#ifdef NEW_IXIA_METHOD + if (IS_EXPECTED_LENGTH(kickout_pkt->len)) + tx_pkt_to_hw++; +#endif + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; +} + + +#ifdef HDR_TRANS_TX_SUPPORT +VOID AP_AMPDU_Frame_Tx_Hdr_Trns( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ + PUCHAR pWiBufPtr; + USHORT FreeNumber = 1; /* no use */ + MAC_TABLE_ENTRY *pMacEntry; + STA_TR_ENTRY *tr_entry; + PQUEUE_ENTRY pQEntry; + UINT8 TXWISize = pAd->chipCap.TXWISize; + TX_WIFI_INFO *pWI; + + ASSERT(pTxBlk); + + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { +#ifdef STATS_COUNT_SUPPORT + BSS_STRUCT *pMbss = pTxBlk->pMbss; + + if (pMbss != NULL) + pMbss->TxDropCount ++; +#endif /* STATS_COUNT_SUPPORT */ + + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + +/* + if ( pAd->debug_on ) + { + UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket); + do_gettimeofday(&(pAd->debug_time_2[index])); + } +*/ + + pMacEntry = pTxBlk->pMacEntry; + tr_entry = pTxBlk->tr_entry; + if ((tr_entry->isCached) + ) + { + /* It should be cleared!!! */ + /*NdisZeroMemory((PUCHAR)(&pTxBlk->HeaderBuf[0]), sizeof(pTxBlk->HeaderBuf)); */ + NdisMoveMemory((PUCHAR) + (&pTxBlk->HeaderBuf[TXINFO_SIZE]), + (PUCHAR) (&tr_entry->CachedBuf[0]), + TXWISize + TX_WIFI_INFO_SIZE); + + pWiBufPtr = (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]); + APBuildCacheWifiInfo(pAd, pTxBlk, pWiBufPtr); + } + else + { + APFindCipherAlgorithm(pAd, pTxBlk); + APBuildWifiInfo(pAd, pTxBlk); + + pWiBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]; + } + + pWI = (TX_WIFI_INFO *)pWiBufPtr; + + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader; + + if (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket)) + pWI->field.VLAN = TRUE; + + pWI->field.TID = (pTxBlk->UserPriority & 0x0F); +#ifdef UAPSD_SUPPORT + if (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE) + && TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP)) + pWI->field.EOSP = TRUE; +#endif /* UAPSD_SUPPORT */ + + { + + /* + build HTC+ + HTC control filed following QoS field + */ + if ((pAd->CommonCfg.bRdg == TRUE) + && (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_RDG_CAPABLE)) + ) + { + pWI->field.RDG = 1; + } + + } + +/* + if ( pAd->debug_on ) + { + UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket); + do_gettimeofday(&(pAd->debug_time_3[index])); + } +*/ + + if ((tr_entry->isCached) + ) + { + write_tmac_info_Cache(pAd, &pTxBlk->HeaderBuf[0], pTxBlk); + } + else + { + write_tmac_info_Data(pAd, &pTxBlk->HeaderBuf[0], pTxBlk); + + NdisZeroMemory((PUCHAR)(&tr_entry->CachedBuf[0]), sizeof(tr_entry->CachedBuf)); + NdisMoveMemory((PUCHAR)(&tr_entry->CachedBuf[0]), + (PUCHAR)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), + TXWISize + TX_WIFI_INFO_SIZE); + + + tr_entry->isCached = TRUE; + + } + +#ifdef STATS_COUNT_SUPPORT + pAd->RalinkCounters.TransmittedMPDUsInAMPDUCount.u.LowPart ++; + pAd->RalinkCounters.TransmittedOctetsInAMPDUCount.QuadPart += pTxBlk->SrcBufLen; + + /* calculate Tx count and ByteCount per BSS */ + { + BSS_STRUCT *pMbss = pTxBlk->pMbss; + +#ifdef WAPI_SUPPORT + if (IS_ENTRY_CLIENT(pMacEntry)) + { + 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; + pMacEntry->OneSecTxBytes+=pTxBlk->SrcBufLen; + } + } + +#endif /* STATS_COUNT_SUPPORT */ + + /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */ + + HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber); + + + /* + if ( pAd->debug_on ) + { + UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket); + do_gettimeofday(&(pAd->debug_time_4[index])); + } +*/ + + /* + Kick out Tx + */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + +/* + if ( pAd->debug_on ) + { + UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket); + do_gettimeofday(&(pAd->debug_time_5[index])); + if ( pAd->debug_index < 201 ) + { + pAd->debug_index ++; + } else { + pAd->debug_on = 0; + } + } +*/ + +} +#endif /* HDR_TRANS_TX_SUPPORT */ + + +VOID AP_AMSDU_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + UCHAR *pHeaderBufPtr, *subFrameHeader; + USHORT freeCnt = 1; /* no use */ + USHORT subFramePayloadLen = 0; /* AMSDU Subframe length without AMSDU-Header / Padding */ + USHORT totalMPDUSize = 0; + UCHAR padding = 0; + USHORT FirstTx = 0/*, LastTxIdx = 0*/; + int frameNum = 0; + PQUEUE_ENTRY pQEntry; + //STA_TR_ENTRY *tr_entry; +#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 */ +#ifdef WFA_VHT_PF + MAC_TABLE_ENTRY *pMacEntry = pTxBlk->pMacEntry; +#endif /* WFA_VHT_PF */ + + 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 + BSS_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->TxWIMPDUByteCnt will be updated after final frame was handled. */ +#ifdef WFA_VHT_PF + if (pAd->force_amsdu) + { + UCHAR RABAOriIdx; + + if (pMacEntry) { + RABAOriIdx = pMacEntry->BAOriWcidArray[pTxBlk->UserPriority]; + if (((pMacEntry->TXBAbitmap & (1<UserPriority)) != 0) && + (pAd->BATable.BAOriEntry[RABAOriIdx].amsdu_cap == TRUE)) + TX_BLK_SET_FLAG (pTxBlk, fTX_AmsduInAmpdu); + } + } +#endif /* WFA_VHT_PF */ + + write_tmac_info_Data(pAd, &pTxBlk->HeaderBuf[0], pTxBlk); + + + if (RTMP_GET_PACKET_LOWRATE(pTxBlk->pPacket)) + if (pTxBlk->tr_entry) + pTxBlk->tr_entry->isCached = FALSE; + } + else + { +#if defined(MT7603) || defined(MT7628) + pHeaderBufPtr = &pTxBlk->HeaderBuf[0]; +#else + // TODO: shiang-usw, check this, original code is use pTxBlk->HeaderBuf[0] + pHeaderBufPtr = &pTxBlk->HeaderBuf[TXINFO_SIZE]; +#endif /* defined(MT7603) || defined(MT7628) */ + padding = ROUND_UP(AMSDU_SUBHEAD_LEN + subFramePayloadLen, 4) - (AMSDU_SUBHEAD_LEN + subFramePayloadLen); + NdisZeroMemory(pHeaderBufPtr, padding + AMSDU_SUBHEAD_LEN); + pHeaderBufPtr += padding; + pTxBlk->MpduHeaderLen = padding; + } + + /* + A-MSDU subframe + DA(6)+SA(6)+Length(2) + LLC/SNAP Encap + */ + subFrameHeader = pHeaderBufPtr; + subFramePayloadLen = pTxBlk->SrcBufLen; + + NdisMoveMemory(subFrameHeader, pTxBlk->pSrcBufHeader, 12); + +#ifdef APCLI_SUPPORT + if(TX_BLK_TEST_FLAG(pTxBlk, fTX_bApCliPacket)) + { +#ifdef MAC_REPEATER_SUPPORT + if (pTxBlk->pMacEntry->bReptCli) + { + pReptEntry = &pAd->ApCfg.ApCliTab[pTxBlk->pMacEntry->func_tb_idx].RepeaterCli[pTxBlk->pMacEntry->MatchReptCliIdx]; + if (pReptEntry->CliValid) + NdisMoveMemory(&subFrameHeader[6] , pReptEntry->CurrentAddress, 6); + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry = &pAd->ApCfg.ApCliTab[pTxBlk->pMacEntry->func_tb_idx]; + if (pApCliEntry->Valid) + NdisMoveMemory(&subFrameHeader[6] , pApCliEntry->wdev.if_addr, 6); + } + } +#endif /* APCLI_SUPPORT */ + + + pHeaderBufPtr += AMSDU_SUBHEAD_LEN; + pTxBlk->MpduHeaderLen += AMSDU_SUBHEAD_LEN; + + + + /* Insert LLC-SNAP encapsulation - 8 octets */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2, pTxBlk->pExtraLlcSnapEncap); + + subFramePayloadLen = pTxBlk->SrcBufLen; + + if (pTxBlk->pExtraLlcSnapEncap) { + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pSrcBufData - 2, 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + subFramePayloadLen += LENGTH_802_1_H; + } + + /* update subFrame Length field */ + subFrameHeader[12] = (subFramePayloadLen & 0xFF00) >> 8; + subFrameHeader[13] = subFramePayloadLen & 0xFF; + +#if defined(MT7603) || defined(MT7628) + if (frameNum == 0) + totalMPDUSize += pAd->chipCap.tx_hw_hdr_len - pTxBlk->hw_rsv_len + pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen + pTxBlk->SrcBufLen; + else + totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; +#else + totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; +#endif /* MT7603 */ + + if (frameNum == 0) + FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &freeCnt); + else + /*LastTxIdx = */HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &freeCnt); + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), NULL); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + frameNum++; + + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + +#ifdef STATS_COUNT_SUPPORT + { + /* calculate Transmitted AMSDU Count and ByteCount */ + pAd->RalinkCounters.TxAMSDUCount.u.LowPart++; + } + + /* calculate Tx count and ByteCount per BSS */ + { + BSS_STRUCT *pMbss = pTxBlk->pMbss; + MAC_TABLE_ENTRY *pMacEntry = pTxBlk->pMacEntry; + +#ifdef WAPI_SUPPORT + if (IS_ENTRY_CLIENT(pTxBlk->pMacEntry)) + { + 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; + pMacEntry->OneSecTxBytes+=pTxBlk->SrcBufLen; + pAd->TxTotalByteCnt += pTxBlk->SrcBufLen; +#ifdef DYNAMIC_WMM + pAd->TxTotalByteCnt_Dyn[pTxBlk->QueIdx] += pTxBlk->SrcBufLen; +#endif /* DYNAMIC_WMM */ + } + } + +#ifdef WDS_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_WDS(pTxBlk->pMacEntry)) + { + INC_COUNTER64(pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->func_tb_idx].WdsCounter.TransmittedFragmentCount); + pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->func_tb_idx].WdsCounter.TransmittedByteCount+= pTxBlk->SrcBufLen; + } +#endif /* WDS_SUPPORT */ +#endif /* STATS_COUNT_SUPPORT */ + } + + HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, FirstTx); + HAL_LastTxIdx(pAd, pTxBlk->QueIdx, 0/*LastTxIdx*/); + + /* + Kick out Tx + */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); +} +#endif /* DOT11_N_SUPPORT */ + + +VOID AP_Legacy_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + HEADER_802_11 *wifi_hdr; + UCHAR *pHeaderBufPtr; + USHORT freeCnt = 1; + BOOLEAN bVLANPkt; + QUEUE_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 + BSS_STRUCT *pMbss = pTxBlk->pMbss; + + if (pMbss != NULL) + { + pMbss->TxDropCount++; + } +#endif /* STATS_COUNT_SUPPORT */ + + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); +DBGPRINT(RT_DEBUG_TRACE, ("<--%s(%d): ##########Fail#########\n", __FUNCTION__, __LINE__)); + return; + } + + APFindCipherAlgorithm(pAd, pTxBlk); + APBuildCommon802_11Header(pAd, pTxBlk); + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) { + if (RTMPExpandPacketForSwEncrypt(pAd, pTxBlk) == FALSE) { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + } +#endif /* SOFT_ENCRYPT */ + + /* skip 802.3 header */ + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader + LENGTH_802_3; + pTxBlk->SrcBufLen -= LENGTH_802_3; + + /* skip vlan tag */ + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + if (bVLANPkt) { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + /* record these MCAST_TX frames for group key rekey */ + if (pTxBlk->TxFrameType == TX_MCAST_FRAME) + { + INT idx; + +#ifdef STATS_COUNT_SUPPORT + INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount); +#endif /* STATS_COUNT_SUPPORT */ + + 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 */ + } + else + { + /* Unicast */ + if (pTxBlk->tr_entry && pTxBlk->tr_entry->PsDeQWaitCnt) + pTxBlk->Pid = PID_PS_DATA; + } + +#if defined(MT_MAC) && defined(WSC_INCLUDED) && defined(CONFIG_AP_SUPPORT) + if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket) & 0x80) + { + pTxBlk->Pid = PID_WSC_EAP; + } +#endif /* defined(MT_MAC) && defined(WSC_INCLUDED) && defined(CONFIG_AP_SUPPORT) */ + + pHeaderBufPtr = pTxBlk->wifi_hdr; + wifi_hdr = (HEADER_802_11 *)pHeaderBufPtr; + if(wifi_hdr == NULL) + DBGPRINT(RT_DEBUG_TRACE, ("wifi_hdr is NULL.\n")); + + /* skip common header */ + pHeaderBufPtr += pTxBlk->wifi_hdr_len; + + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM)) { + /* build QOS Control bytes */ + *pHeaderBufPtr = ((pTxBlk->UserPriority & 0x0F) | (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx] << 5)); +#ifdef WFA_VHT_PF + if (pAd->force_noack) + *pHeaderBufPtr |= (1 << 5); +#endif /* WFA_VHT_PF */ + +#ifdef UAPSD_SUPPORT + if (CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE) +#ifdef WDS_SUPPORT + && (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry) == FALSE) +#endif /* WDS_SUPPORT */ + ) + { + /* + we can not use bMoreData bit to get EOSP bit because + maybe bMoreData = 1 & EOSP = 1 when Max SP Length != 0 + */ + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP)) + *pHeaderBufPtr |= (1 << 4); + } +#endif /* UAPSD_SUPPORT */ + + *(pHeaderBufPtr + 1) = 0; + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += 2; + pTxBlk->wifi_hdr_len += 2; + + } + + /* The remaining content of MPDU header should locate at 4-octets aligment */ + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (UCHAR *)ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + pTxBlk->MpduHeaderLen = pTxBlk->wifi_hdr_len; + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) { + tx_sw_encrypt(pAd, pTxBlk, pHeaderBufPtr, wifi_hdr); + } + else +#endif /* SOFT_ENCRYPT */ + { + + /* + Insert LLC-SNAP encapsulation - 8 octets + if original Ethernet frame contains no LLC/SNAP, + then an extra LLC/SNAP encap is required + */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, + pTxBlk->pExtraLlcSnapEncap); + if (pTxBlk->pExtraLlcSnapEncap) { + UCHAR vlan_size; + + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + /* skip vlan tag */ + vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0; + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, + pTxBlk->pSrcBufHeader + 12 + vlan_size, + 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + } + +#ifdef STATS_COUNT_SUPPORT + /* calculate Tx count and ByteCount per BSS */ + { + BSS_STRUCT *pMbss = pTxBlk->pMbss; + MAC_TABLE_ENTRY *pMacEntry=pTxBlk->pMacEntry; + +#ifdef WAPI_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_CLIENT(pTxBlk->pMacEntry)) + { + 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; + pMacEntry->OneSecTxBytes+=pTxBlk->SrcBufLen; + pAd->TxTotalByteCnt += pTxBlk->SrcBufLen; +#ifdef DYNAMIC_WMM + pAd->TxTotalByteCnt_Dyn[pTxBlk->QueIdx] += pTxBlk->SrcBufLen; +#endif /* DYNAMIC_WMM */ + } + } + +#ifdef WDS_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_WDS(pTxBlk->pMacEntry)) + { + INC_COUNTER64(pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->func_tb_idx].WdsCounter.TransmittedFragmentCount); + pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->func_tb_idx].WdsCounter.TransmittedByteCount+= pTxBlk->SrcBufLen; + } +#endif /* WDS_SUPPORT */ +#endif /* STATS_COUNT_SUPPORT */ + + /* + prepare for TXWI + use Wcid as Hardware Key Index + */ + + /* update Hardware Group Key Index */ + if (!pTxBlk->pMacEntry) { + struct wifi_dev *wdev = pAd->wdev_list[pTxBlk->wdev_idx]; + ASSERT(wdev != NULL); + if(wdev != NULL) + { + GET_GroupKey_WCID(pAd, pTxBlk->Wcid, wdev->func_idx); + } + } + + write_tmac_info_Data(pAd, &pTxBlk->HeaderBuf[0], pTxBlk); + +//hex_dump("Legacy_Frame-FirstBufContent", pTxBlk->HeaderBuf, 128); +//hex_dump("Legacy_Frame-FirstBufContent - WiFi Hdr Segment", pTxBlk->wifi_hdr, pTxBlk->wifi_hdr_len); +//DBGPRINT(RT_DEBUG_OFF, ("%s(): pTxBlk->MpduHeaderLen=%d, wifi_hdr_len=%d, HdrPadLen=%d, hw_rsv_len=%d\n", +// __FUNCTION__, pTxBlk->MpduHeaderLen, pTxBlk->wifi_hdr_len, pTxBlk->HdrPadLen, pTxBlk->hw_rsv_len)); +//dump_tmac_info(pAd, &pTxBlk->HeaderBuf[pTxBlk->hw_rsv_len]); + + if (RTMP_GET_PACKET_LOWRATE(pTxBlk->pPacket)) + if (pTxBlk->tr_entry) + pTxBlk->tr_entry->isCached = FALSE; + + HAL_WriteTxResource(pAd, pTxBlk, TRUE, &freeCnt); + + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (UCHAR *)wifi_hdr); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + /* + Kick out Tx + */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + +//DBGPRINT(RT_DEBUG_TRACE, ("<--%s(%d):Success\n", __FUNCTION__, __LINE__)); +} + + +#ifdef HDR_TRANS_TX_SUPPORT +VOID AP_Legacy_Frame_Tx_Hdr_Trns( + IN PRTMP_ADAPTER pAd, + IN TX_BLK *pTxBlk) +{ +/* UCHAR QueIdx = pTxBlk->QueIdx; */ + USHORT FreeNumber = 1; /* no use */ + BOOLEAN bVLANPkt; + PQUEUE_ENTRY pQEntry; + UINT8 TXWISize = pAd->chipCap.TXWISize; + TX_WIFI_INFO *pWI; + + ASSERT(pTxBlk); + + + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) + { +#ifdef STATS_COUNT_SUPPORT + BSS_STRUCT *pMbss = pTxBlk->pMbss; + + if (pMbss != NULL) + pMbss->TxDropCount++; +#endif /* STATS_COUNT_SUPPORT */ + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + +#ifdef STATS_COUNT_SUPPORT + if (pTxBlk->TxFrameType == TX_MCAST_FRAME) + { + INC_COUNTER64(pAd->WlanCounters.MulticastTransmittedFrameCount); + } +#endif /* STATS_COUNT_SUPPORT */ + + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + + APFindCipherAlgorithm(pAd, pTxBlk); + +/* + if ( pAd->debug_on ) + { + UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket); + do_gettimeofday(&(pAd->debug_time_2[index])); + } +*/ + + APBuildWifiInfo(pAd, pTxBlk); + + pWI = (TX_WIFI_INFO *)&pTxBlk->HeaderBuf[TXINFO_SIZE + TXWISize]; + pTxBlk->pSrcBufData = pTxBlk->pSrcBufHeader; + if (bVLANPkt) + pWI->field.VLAN = TRUE; + + pWI->field.TID = (pTxBlk->UserPriority & 0x0F); +#ifdef UAPSD_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM) + && CLIENT_STATUS_TEST_FLAG(pTxBlk->pMacEntry, fCLIENT_STATUS_APSD_CAPABLE) + && TX_BLK_TEST_FLAG(pTxBlk, fTX_bWMM_UAPSD_EOSP)) + pWI->field.EOSP = TRUE; +#endif /* UAPSD_SUPPORT */ + +#ifdef STATS_COUNT_SUPPORT + /* calculate Tx count and ByteCount per BSS */ + { + BSS_STRUCT *pMbss = pTxBlk->pMbss; + MAC_TABLE_ENTRY *pMacEntry=pTxBlk->pMacEntry; + +#ifdef WAPI_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_CLIENT(pTxBlk->pMacEntry)) + { + 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; + pMacEntry->OneSecTxBytes+=pTxBlk->SrcBufLen; + } + } + +#endif /* STATS_COUNT_SUPPORT */ + + /* + if ( pAd->debug_on ) + { + UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket); + do_gettimeofday(&(pAd->debug_time_3[index])); + } +*/ + + /* + prepare for TXWI + */ + + /* update Hardware Group Key Index */ + if (!pTxBlk->pMacEntry) + { + /* use Wcid as Hardware Key Index */ + struct wifi_dev *wdev = pAd->wdev_list[pTxBlk->wdev_idx]; + ASSERT(wdev != NULL); + GET_GroupKey_WCID(pAd, pTxBlk->Wcid, wdev->func_idx); + } + + write_tmac_info_Data(pAd, &pTxBlk->HeaderBuf[0], pTxBlk); + + /*FreeNumber = GET_TXRING_FREENO(pAd, QueIdx); */ + + HAL_WriteTxResource(pAd, pTxBlk, TRUE, &FreeNumber); + + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (UCHAR *)pHeader_802_11); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + /* + if (pAd->debug_on) + { + UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket); + do_gettimeofday(&(pAd->debug_time_4[index])); + } +*/ + + /* + Kick out Tx + */ + HAL_KickOutTx(pAd, pTxBlk, pTxBlk->QueIdx); + +/* + if ( pAd->debug_on ) + { + UCHAR index = RTMP_GET_DEBUG_INDEX(pTxBlk->pPacket); + do_gettimeofday(&(pAd->debug_time_5[index])); + if ( pAd->debug_index < 201 ) + { + pAd->debug_index ++; + } else { + pAd->debug_on = 0; + } + + } +*/ + +} +#endif /* HDR_TRANS_TX_SUPPORT */ + + +VOID AP_Fragment_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + HEADER_802_11 *wifi_hdr; + UCHAR *pHeaderBufPtr; + USHORT freeCnt = 1; + BOOLEAN bVLANPkt; + QUEUE_ENTRY *pQEntry; + //UINT8 TXWISize = pAd->chipCap.TXWISize; + PACKET_INFO PacketInfo; +#ifdef SOFT_ENCRYPT + UCHAR *tmp_ptr = NULL; + UINT32 buf_offset = 0; +#endif /* SOFT_ENCRYPT */ + HTTRANSMIT_SETTING *pTransmit; + UCHAR fragNum = 0; + USHORT EncryptionOverhead = 0; + UINT32 FreeMpduSize, SrcRemainingBytes; + USHORT AckDuration; + UINT NextMpduSize; + //UINT8 tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len; + + ASSERT(pTxBlk); + ASSERT(TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag)); + +//DBGPRINT(RT_DEBUG_TRACE, ("%s()-->\n", __FUNCTION__)); + + pQEntry = RemoveHeadQueue(&pTxBlk->TxPacketList); + pTxBlk->pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + if (RTMP_FillTxBlkInfo(pAd, pTxBlk) != TRUE) { +#ifdef STATS_COUNT_SUPPORT + BSS_STRUCT *pMbss = pTxBlk->pMbss; + + if (pMbss != NULL) + { + pMbss->TxDropCount++; + } +#endif /* STATS_COUNT_SUPPORT */ + + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); +DBGPRINT(RT_DEBUG_TRACE, ("<--%s(%d): ##########Fail#########\n", __FUNCTION__, __LINE__)); + return; + } + + 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 */ + + 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 */ + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + if (bVLANPkt) { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + pHeaderBufPtr = pTxBlk->wifi_hdr; + wifi_hdr = (HEADER_802_11 *)pHeaderBufPtr; + +DBGPRINT(RT_DEBUG_TRACE, ("%s(): Before Frag, pTxBlk->MpduHeaderLen=%d, wifi_hdr_len=%d, HdrPadLen=%d, hw_rsv_len=%d\n", + __FUNCTION__, pTxBlk->MpduHeaderLen, pTxBlk->wifi_hdr_len, pTxBlk->HdrPadLen, pTxBlk->hw_rsv_len)); + + /* skip common header */ + pHeaderBufPtr += pTxBlk->wifi_hdr_len; + + 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; + pTxBlk->wifi_hdr_len += 2; + } + + /* The remaining content of MPDU header should locate at 4-octets aligment */ + pTxBlk->HdrPadLen = (ULONG)pHeaderBufPtr; + pHeaderBufPtr = (UCHAR *)ROUND_UP(pHeaderBufPtr, 4); + pTxBlk->HdrPadLen = (ULONG)(pHeaderBufPtr - pTxBlk->HdrPadLen); + pTxBlk->MpduHeaderLen = pTxBlk->wifi_hdr_len; + +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) { + UCHAR iv_offset = 0; + + /* + If original Ethernet frame contains no LLC/SNAP, + then an extra LLC/SNAP encap is required + */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2, + pTxBlk->pExtraLlcSnapEncap); + + /* Insert LLC-SNAP encapsulation (8 octets) to MPDU data buffer */ + if (pTxBlk->pExtraLlcSnapEncap) { + /* Reserve the front 8 bytes of data for LLC header */ + pTxBlk->pSrcBufData -= LENGTH_802_1_H; + pTxBlk->SrcBufLen += LENGTH_802_1_H; + + NdisMoveMemory(pTxBlk->pSrcBufData, pTxBlk->pExtraLlcSnapEncap, 6); + } + + /* Construct and insert specific IV header to MPDU header */ + RTMPSoftConstructIVHdr(pTxBlk->CipherAlg, + pTxBlk->KeyIdx, + pTxBlk->pKey->TxTsc, + pHeaderBufPtr, &iv_offset); + pHeaderBufPtr += iv_offset; + pTxBlk->MpduHeaderLen += iv_offset; + + } + else +#endif /* SOFT_ENCRYPT */ + { + + /* + Insert LLC-SNAP encapsulation - 8 octets + if original Ethernet frame contains no LLC/SNAP, + then an extra LLC/SNAP encap is required + */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_START(pTxBlk->pSrcBufHeader, + pTxBlk->pExtraLlcSnapEncap); + if (pTxBlk->pExtraLlcSnapEncap) { + UCHAR vlan_size; + + NdisMoveMemory(pHeaderBufPtr, pTxBlk->pExtraLlcSnapEncap, 6); + pHeaderBufPtr += 6; + /* skip vlan tag */ + vlan_size = (bVLANPkt) ? LENGTH_802_1Q : 0; + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(pHeaderBufPtr, + pTxBlk->pSrcBufHeader + 12 + vlan_size, + 2); + pHeaderBufPtr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + } + + /* 1. If TKIP is used and fragmentation is required. Driver has to + append TKIP MIC at tail of the scatter buffer + 2. When TXWI->FRAG is set as 1 in TKIP mode, + MAC ASIC will only perform IV/EIV/ICV insertion but no TKIP MIC */ + /* TKIP appends the computed MIC to the MSDU data prior to fragmentation into MPDUs. */ + if (pTxBlk->CipherAlg == CIPHER_TKIP) { + struct wifi_dev *wdev = pAd->wdev_list[pTxBlk->wdev_idx]; + ASSERT(wdev != NULL); + if(wdev != NULL) + { + RTMPCalculateMICValue(pAd, pTxBlk->pPacket, pTxBlk->pExtraLlcSnapEncap, pTxBlk->pKey, wdev->func_idx); + } + + /* + NOTE: DON'T refer the skb->len directly after following copy. Becasue the length is not adjust + to correct lenght, refer to pTxBlk->SrcBufLen for the packet length in following progress. + */ + NdisMoveMemory(pTxBlk->pSrcBufData + pTxBlk->SrcBufLen, &pAd->PrivateInfo.Tx.MIC[0], 8); + pTxBlk->SrcBufLen += 8; + pTxBlk->TotalFrameLen += 8; + } + +#ifdef STATS_COUNT_SUPPORT + /* calculate Tx count and ByteCount per BSS */ + { + BSS_STRUCT *pMbss = pTxBlk->pMbss; + MAC_TABLE_ENTRY *pMacEntry=pTxBlk->pMacEntry; + +#ifdef WAPI_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_CLIENT(pTxBlk->pMacEntry)) + { + 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; + pMacEntry->OneSecTxBytes+=pTxBlk->SrcBufLen; + pAd->TxTotalByteCnt += pTxBlk->SrcBufLen; +#ifdef DYNAMIC_WMM + pAd->TxTotalByteCnt_Dyn[pTxBlk->QueIdx] += pTxBlk->SrcBufLen; +#endif /* DYNAMIC_WMM */ + } + } + +#ifdef WDS_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_WDS(pTxBlk->pMacEntry)) + { + INC_COUNTER64(pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->func_tb_idx].WdsCounter.TransmittedFragmentCount); + pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->func_tb_idx].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) || (pTxBlk->CipherAlg == CIPHER_WEP152)) + 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)); */ + +#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 MIC calculation!\n", + __FUNCTION__)); + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return; + } + NdisMoveMemory(tmp_ptr, pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); + } +#endif /* SOFT_ENCRYPT */ + + /* Init the total payload length of this frame. */ + SrcRemainingBytes = pTxBlk->SrcBufLen; + pTxBlk->TotalFragNum = 0xff; + + do { + FreeMpduSize = pAd->CommonCfg.FragmentThreshold - LENGTH_CRC; + FreeMpduSize -= pTxBlk->MpduHeaderLen; + + if (SrcRemainingBytes <= FreeMpduSize) + { + /* This is the last or only fragment */ + pTxBlk->SrcBufLen = SrcRemainingBytes; + + wifi_hdr->FC.MoreFrag = 0; + wifi_hdr->Duration = pAd->CommonCfg.Dsifs + AckDuration; + + /* Indicate the lower layer that this's the last fragment. */ + pTxBlk->TotalFragNum = fragNum; +#ifdef MT_MAC + pTxBlk->FragIdx = ((fragNum == 0) ? TX_FRAG_ID_NO : TX_FRAG_ID_LAST); +#endif /* MT_MAC */ + } + else + { /* more fragment is required */ + pTxBlk->SrcBufLen = FreeMpduSize; + + NextMpduSize = min(((UINT)SrcRemainingBytes - pTxBlk->SrcBufLen), + ((UINT)pAd->CommonCfg.FragmentThreshold)); + wifi_hdr->FC.MoreFrag = 1; + wifi_hdr->Duration = (3 * pAd->CommonCfg.Dsifs) + (2 * AckDuration) + + RTMPCalcDuration(pAd, pTxBlk->TxRate, NextMpduSize + EncryptionOverhead); +#ifdef MT_MAC + pTxBlk->FragIdx = ((fragNum == 0) ? TX_FRAG_ID_FIRST : TX_FRAG_ID_MIDDLE); +#endif /* MT_MAC */ + } + + 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, + (UCHAR *)wifi_hdr, + pTxBlk->pSrcBufData, + pTxBlk->SrcBufLen, + pTxBlk->KeyIdx, + pTxBlk->pKey, + &ext_offset); + pTxBlk->SrcBufLen += ext_offset; + pTxBlk->TotalFrameLen += ext_offset; + } +#endif /* SOFT_ENCRYPT */ + write_tmac_info_Data(pAd, &pTxBlk->HeaderBuf[0], pTxBlk); + + + HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, &freeCnt); + + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), (UCHAR *)wifi_hdr); +#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; + + wifi_hdr->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); + +//DBGPRINT(RT_DEBUG_TRACE, ("<--%s(%d):Success\n", __FUNCTION__, __LINE__)); +} + + +VOID AP_ARalink_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + UCHAR *buf_ptr; + USHORT freeCnt = 1; + 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 + BSS_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 */ + bVLANPkt = (RTMP_GET_PACKET_VLAN(pTxBlk->pPacket) ? TRUE : FALSE); + if (bVLANPkt) { + pTxBlk->pSrcBufData += LENGTH_802_1Q; + pTxBlk->SrcBufLen -= LENGTH_802_1Q; + } + + /* + For first frame, we need to create: + 802.11 header + padding(optional) + RA-AGG-LEN + SNAP Header + For second aggregated frame, we need create: + the 802.3 header to headerBuf, because PCI will copy it to SDPtr0 + */ + if (frameNum == 0) + { + buf_ptr = AP_Build_ARalink_Frame_Header(pAd, pTxBlk); + + /* + It's ok write the TxWI here, because the TxWI->TxWIMPDUByteCnt + will be updated after final frame was handled. + */ + write_tmac_info_Data(pAd, &pTxBlk->HeaderBuf[0], pTxBlk); + + + /* Insert LLC-SNAP encapsulation - 8 octets */ + EXTRA_LLCSNAP_ENCAP_FROM_PKT_OFFSET(pTxBlk->pSrcBufData - 2, + pTxBlk->pExtraLlcSnapEncap); + + if (pTxBlk->pExtraLlcSnapEncap) { + NdisMoveMemory(buf_ptr, pTxBlk->pExtraLlcSnapEncap, 6); + buf_ptr += 6; + + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(buf_ptr, pTxBlk->pSrcBufData - 2, 2); + buf_ptr += 2; + pTxBlk->MpduHeaderLen += LENGTH_802_1_H; + } + } + else + { + buf_ptr = &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(buf_ptr, pTxBlk->pSrcBufHeader, 12); + buf_ptr += 12; + /* get 2 octets (TypeofLen) */ + NdisMoveMemory(buf_ptr, pTxBlk->pSrcBufData - 2, 2); + buf_ptr += 2; + pTxBlk->MpduHeaderLen = ARALINK_SUBHEAD_LEN; + } + +#if defined(MT7603) || defined(MT7628) + if (frameNum == 0) + totalMPDUSize += pAd->chipCap.tx_hw_hdr_len - pTxBlk->hw_rsv_len + pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen + pTxBlk->SrcBufLen; + else + totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; +#else + totalMPDUSize += pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; +#endif /* defined(MT7603) || defined(MT7628) */ + + if (frameNum == 0) + FirstTx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &freeCnt); + else + LastTxIdx = HAL_WriteMultiTxResource(pAd, pTxBlk, frameNum, &freeCnt); + + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFRAME) + dbQueueEnqueueTxFrame((UCHAR *)(&pTxBlk->HeaderBuf[TXINFO_SIZE]), NULL); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + frameNum++; + + pAd->RalinkCounters.OneSecTxARalinkCnt++; + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + +#ifdef STATS_COUNT_SUPPORT + /* calculate Tx count and ByteCount per BSS */ + { + BSS_STRUCT *pMbss = pTxBlk->pMbss; + MAC_TABLE_ENTRY *pMacEntry=pTxBlk->pMacEntry; + +#ifdef WAPI_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_CLIENT(pTxBlk->pMacEntry)) + { + 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; + pMacEntry->OneSecTxBytes+=pTxBlk->SrcBufLen; + pAd->TxTotalByteCnt += pTxBlk->SrcBufLen; +#ifdef DYNAMIC_WMM + pAd->TxTotalByteCnt_Dyn[pTxBlk->QueIdx] += pTxBlk->SrcBufLen; +#endif /* DYNAMIC_WMM */ + } + + } + +#ifdef WDS_SUPPORT + if (pTxBlk->pMacEntry && IS_ENTRY_WDS(pTxBlk->pMacEntry)) + { + INC_COUNTER64(pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->func_tb_idx].WdsCounter.TransmittedFragmentCount); + pAd->WdsTab.WdsEntry[pTxBlk->pMacEntry->func_tb_idx].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); + +} + + +#ifdef VHT_TXBF_SUPPORT +VOID AP_NDPA_Frame_Tx(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + UCHAR *buf; + VHT_NDPA_FRAME *vht_ndpa; + struct wifi_dev *wdev; + UINT frm_len, sta_cnt; + SNDING_STA_INFO *sta_info; + MAC_TABLE_ENTRY *pMacEntry; + + pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pTxBlk->pPacket); + pTxBlk->pMacEntry = &pAd->MacTab.Content[pTxBlk->Wcid]; + pMacEntry = pTxBlk->pMacEntry; + + if (pMacEntry) + { + wdev = pMacEntry->wdev; + + if (MlmeAllocateMemory(pAd, &buf) != NDIS_STATUS_SUCCESS) + return; + + NdisZeroMemory(buf, MGMT_DMA_BUFFER_SIZE); + + vht_ndpa = (VHT_NDPA_FRAME *)buf; + frm_len = sizeof(VHT_NDPA_FRAME); + vht_ndpa->fc.Type = FC_TYPE_CNTL; + vht_ndpa->fc.SubType = SUBTYPE_VHT_NDPA; + COPY_MAC_ADDR(vht_ndpa->ra, pMacEntry->Addr); + COPY_MAC_ADDR(vht_ndpa->ta, wdev->if_addr); + + /* Currnetly we only support 1 STA for a VHT DNPA */ + sta_info = vht_ndpa->sta_info; + for (sta_cnt = 0; sta_cnt < 1; sta_cnt++) { + sta_info->aid12 = pMacEntry->Aid; + sta_info->fb_type = SNDING_FB_SU; + sta_info->nc_idx = 0; + vht_ndpa->token.token_num = pMacEntry->snd_dialog_token; + frm_len += sizeof(SNDING_STA_INFO); + sta_info++; + if (frm_len >= (MGMT_DMA_BUFFER_SIZE - sizeof(SNDING_STA_INFO))) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): len(%d) too large!cnt=%d\n", + __FUNCTION__, frm_len, sta_cnt)); + break; + } + } + if (pMacEntry->snd_dialog_token & 0xc0) + pMacEntry->snd_dialog_token = 0; + else + pMacEntry->snd_dialog_token++; + + vht_ndpa->duration = 100; + + //DBGPRINT(RT_DEBUG_OFF, ("Send VHT NDPA Frame to STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", + // PRINT_MAC(pMacEntry->Addr))); + //hex_dump("VHT NDPA Frame", buf, frm_len); + + // NDPA's BW needs to sync with Tx BW + pAd->CommonCfg.MlmeTransmit.field.BW = pMacEntry->HTPhyMode.field.BW; + + pTxBlk->Flags = FALSE; // No Acq Request + + // TODO: shiang-lock, fix ME!! + MiniportMMRequest(pAd, 0, buf, frm_len); + MlmeFreeMemory(pAd, buf); + } + + pMacEntry->TxSndgType = SNDG_TYPE_DISABLE; +} +#endif /* VHT_TXBF_SUPPORT */ + + +/* + ======================================================================== + Routine Description: + Copy frame from waiting queue into relative ring buffer and set + appropriate ASIC register to kick hardware encryption before really + sent out to air. + + Arguments: + pAd Pointer to our adapter + pTxBlk Pointer to outgoing TxBlk structure. + QueIdx Queue index for processing + + Return Value: + None + ======================================================================== +*/ +NDIS_STATUS APHardTransmit(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + PQUEUE_ENTRY pQEntry; + PNDIS_PACKET pPacket = NULL; + + DBGPRINT(RT_DEBUG_INFO, ("%s(%d)-->\n", __FUNCTION__, __LINE__)); + + 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); +#ifdef NEW_IXIA_METHOD + if (IS_EXPECTED_LENGTH(RTPKT_TO_OSPKT(pPacket)->len)) + pAd->tr_ststic.tx[DROP_80211H_MODE]++; +#endif + } + DBGPRINT(RT_DEBUG_INFO, ("<--%s(%d)\n", __FUNCTION__, __LINE__)); + return NDIS_STATUS_FAILURE; + } + + if (pTxBlk->wdev->bVLAN_Tag == TRUE) + { + RTMP_SET_PACKET_VLAN(pTxBlk->pPacket, FALSE); + } + + /*add hook point when dequeue*/ + RTMP_OS_TXRXHOOK_CALL(WLAN_TX_DEQUEUE,pPacket,pTxBlk->QueIdx,pAd); + +#ifdef DOT11K_RRM_SUPPORT +#ifdef QUIET_SUPPORT +{ + struct wifi_dev *wdev = pAd->wdev_list[pTxBlk->wdev_idx]; + + if ((wdev->func_idx < pAd->ApCfg.BssidNum) + && IS_RRM_QUIET(pAd, wdev->func_idx)) + { + RELEASE_NDIS_PACKET(pAd, pTxBlk->pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } +} +#endif /* QUIET_SUPPORT */ +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef HDR_TRANS_TX_SUPPORT +#ifdef SOFT_ENCRYPT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bSwEncrypt)) /* need LLC, not yet generated */ + pTxBlk->NeedTrans = FALSE; + else +#endif /* SOFT_ENCRYPT */ +#ifdef WDS_SUPPORT + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_bWDSEntry)) + pTxBlk->NeedTrans = FALSE; + else +#endif /* WDS_SUPPORT */ + { + pTxBlk->NeedTrans = TRUE; + } +#endif /* HDR_TRANS_TX_SUPPORT */ + +#ifdef VHT_TXBF_SUPPORT + if ((pTxBlk->TxFrameType & TX_NDPA_FRAME) > 0) + { + UCHAR mlmeMCS, mlmeBW, mlmeMode; + + mlmeMCS = pAd->CommonCfg.MlmeTransmit.field.MCS; + mlmeBW = pAd->CommonCfg.MlmeTransmit.field.BW; + mlmeMode = pAd->CommonCfg.MlmeTransmit.field.MODE; + + pAd->NDPA_Request = TRUE; + + AP_NDPA_Frame_Tx(pAd, pTxBlk); + + pAd->NDPA_Request = FALSE; + pTxBlk->TxFrameType &= ~TX_NDPA_FRAME; + + // Finish NDPA and then recover to mlme's own setting + pAd->CommonCfg.MlmeTransmit.field.MCS = mlmeMCS; + pAd->CommonCfg.MlmeTransmit.field.BW = mlmeBW; + pAd->CommonCfg.MlmeTransmit.field.MODE = mlmeMode; + } +#endif + +#ifdef FAST_DETECT_STA_OFF + if ((Flag_fast_detect_sta_off == 1)&&(pTxBlk->pMacEntry->detect_deauth == TRUE)) { + 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; + } +#endif + + switch (pTxBlk->TxFrameType) + { +#ifdef DOT11_N_SUPPORT + case TX_AMPDU_FRAME: +#ifdef HDR_TRANS_TX_SUPPORT + if (pTxBlk->NeedTrans) + AP_AMPDU_Frame_Tx_Hdr_Trns(pAd, pTxBlk); + else +#endif /* HDR_TRANS_TX_SUPPORT */ + AP_AMPDU_Frame_Tx(pAd, pTxBlk); + break; +#endif /* DOT11_N_SUPPORT */ + case TX_LEGACY_FRAME: +#ifdef HDR_TRANS_TX_SUPPORT + if (pTxBlk->NeedTrans) + AP_Legacy_Frame_Tx_Hdr_Trns(pAd, pTxBlk); + else +#endif /* HDR_TRANS_TX_SUPPORT */ + AP_Legacy_Frame_Tx(pAd, pTxBlk); + break; + case TX_MCAST_FRAME: +#ifdef HDR_TRANS_TX_SUPPORT + pTxBlk->NeedTrans = FALSE; +#endif /* HDR_TRANS_TX_SUPPORT */ + 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!!\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; + } + + DBGPRINT(RT_DEBUG_INFO, ("<--%s(%d)\n", __FUNCTION__, __LINE__)); + + return (NDIS_STATUS_SUCCESS); + +} + + +/* + ======================================================================== + Description: + This routine checks if a received frame causes class 2 or class 3 + error, and perform error action (DEAUTH or DISASSOC) accordingly + ======================================================================== +*/ +BOOLEAN APChkCls2Cls3Err(RTMP_ADAPTER *pAd, UCHAR wcid, HEADER_802_11 *hdr) +{ + /* software MAC table might be smaller than ASIC on-chip total size. */ + /* If no mathed wcid index in ASIC on chip, do we need more check??? need to check again. 06-06-2006 */ + if (wcid >= MAX_LEN_OF_MAC_TABLE) + { + MAC_TABLE_ENTRY *pEntry; + + DBGPRINT(RT_DEBUG_WARN, ("%s():Rx a frame from %02x:%02x:%02x:%02x:%02x:%02x with WCID(%d) > %d\n", + __FUNCTION__, PRINT_MAC(hdr->Addr2), + wcid, MAX_LEN_OF_MAC_TABLE)); +//+++Add by shiang for debug + pEntry = MacTableLookup(pAd, hdr->Addr2); + if (pEntry) + return FALSE; +//---Add by shiang for debug + + APCls2errAction(pAd, MAX_LEN_OF_MAC_TABLE, hdr); + return TRUE; + } + + if (pAd->MacTab.Content[wcid].Sst == SST_ASSOC) + ; /* okay to receive this DATA frame */ + else if (pAd->MacTab.Content[wcid].Sst == SST_AUTH) + { + APCls3errAction(pAd, wcid, hdr); + return TRUE; + } + else + { + APCls2errAction(pAd, wcid, hdr); + return TRUE; + } + return FALSE; +} + + +/* + detect AC Category of trasmitting packets + to turn AC0(BE) TX_OP (MAC reg 0x1300) +*/ +// TODO: shiang-usw, this function should move to other place!! +VOID detect_wmm_traffic( + IN RTMP_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 (WMM_UP2AC_MAP[UserPriority] == QID_AC_BK) + { + /* has any BK traffic */ + if (pAd->flg_be_adjust == 0) + { + /* yet adjust */ +#ifdef RTMP_MAC_PCI + AsicSetWmmParam(pAd, WMM_PARAM_AC_0, WMM_PARAM_TXOP, 0x20); +#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) + { + QUEUE_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 + // TODO: shiang-7603 + AsicSetWmmParam(pAd, WMM_PARAM_AC_0, WMM_PARAM_TXOP, 0x0); +#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 + // TODO: shiang-7603 + 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 + // TODO: shiang-7603 + RTMP_IO_WRITE32(pAd, EXP_ACK_TIME, 0x002400ca ); +#endif /* RTMP_MAC_PCI */ + pAd->is_on = 0; + } + } + } +} + + +VOID APRxErrorHandle(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + RXINFO_STRUC *pRxInfo = pRxBlk->pRxInfo; + + if (pRxInfo->CipherErr) + INC_COUNTER64(pAd->WlanCounters.WEPUndecryptableCount); + + if (pRxInfo->U2M && pRxInfo->CipherErr) + { + if (pRxBlk->wcid < MAX_LEN_OF_MAC_TABLE) + { +#ifdef APCLI_SUPPORT +#endif /* APCLI_SUPPORT */ + { + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + + /* + MIC error + Before verifying the MIC, the receiver shall check FCS, ICV and TSC. + This avoids unnecessary MIC failure events. + */ + if ((pEntry->WepStatus == Ndis802_11TKIPEnable) + && (pRxInfo->CipherErr == 2)) + { +#ifdef HOSTAPD_SUPPORT + if(pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Hostapd == Hostapd_EXT) + ieee80211_notify_michael_failure(pAd, pRxBlk->pHeader, (UINT32)pRxBlk->key_idx, 0); + else +#endif/*HOSTAPD_SUPPORT*/ + { + RTMP_HANDLE_COUNTER_MEASURE(pAd, pEntry); + } + } + + /* send wireless event - for icv error */ + if ((pRxInfo->CipherErr & 1) == 1) + RTMPSendWirelessEvent(pAd, IW_ICV_ERROR_EVENT_FLAG, pEntry->Addr, 0, 0); +#ifdef WIFI_DIAG + /* WEP + open, wrong passowrd can association success, but rx data error */ + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->WepStatus == Ndis802_11WEPEnabled)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_AUTH_FAIL, REASON_MIC_FAILURE); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->WepStatus == Ndis802_11WEPEnabled)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + REASON_MIC_FAILURE); +#endif + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("Rx u2me Cipher Err(MPDUsize=%d, WCID=%d, CipherErr=%d)\n", + pRxBlk->MPDUtotalByteCnt, pRxBlk->wcid, pRxInfo->CipherErr)); + + } +} + +#ifdef RLT_MAC_DBG +static int dump_next_valid = 0; +#endif +BOOLEAN APCheckVaildDataFrame(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + HEADER_802_11 *pHeader = pRxBlk->pHeader; + BOOLEAN isVaild = FALSE; + + do + { + if (pHeader->FC.ToDs == 0) + break; + +#ifdef IDS_SUPPORT + if ((pHeader->FC.FrDs == 0) && (pRxBlk->wcid == RESERVED_WCID)) /* not in RX WCID MAC table */ + { + if (++pAd->ApCfg.RcvdMaliciousDataCount > pAd->ApCfg.DataFloodThreshold) + break; + } +#endif /* IDS_SUPPORT */ + + /* check if Class2 or 3 error */ + if ((pHeader->FC.FrDs == 0) && (APChkCls2Cls3Err(pAd, pRxBlk->wcid, pHeader))) + break; + +//+++Add by shiang for debug +#ifdef RLT_MAC_DBG + if (pAd->chipCap.hif_type == HIF_RLT) { + if (pRxBlk->wcid >= MAX_LEN_OF_MAC_TABLE) { + MAC_TABLE_ENTRY *pEntry = NULL; + + DBGPRINT(RT_DEBUG_WARN, ("ErrWcidPkt: seq=%d\n", pHeader->Sequence)); + pEntry = MacTableLookup(pAd, pHeader->Addr2); + if (pEntry && (pEntry->Sst == SST_ASSOC) && IS_ENTRY_CLIENT(pEntry)) + pRxBlk->wcid = pEntry->wcid; + + dump_next_valid = 1; + } + else if (dump_next_valid) + { + DBGPRINT(RT_DEBUG_WARN, ("NextValidWcidPkt: seq=%d\n", pHeader->Sequence)); + dump_next_valid = 0; + } + } +#endif /* RLT_MAC_DBG */ +//---Add by shiang for debug + + if(pAd->ApCfg.BANClass3Data == TRUE) + break; + + isVaild = TRUE; + } while (0); + + return isVaild; +} + + +INT ap_rx_pkt_allow(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + RXINFO_STRUC *pRxInfo = pRxBlk->pRxInfo; + HEADER_802_11 *pHeader = pRxBlk->pHeader; +#if defined(WDS_SUPPORT) || defined(CLIENT_WDS) || defined(IDS_SUPPORT)\ + || defined(A4_CONN) || defined(WH_EVENT_NOTIFIER) + FRAME_CONTROL *pFmeCtrl = &pHeader->FC; +#endif + MAC_TABLE_ENTRY *pEntry = NULL; + INT hdr_len = 0; + + pEntry = PACInquiry(pAd, pRxBlk->wcid); + +#if defined(WDS_SUPPORT) || defined(CLIENT_WDS) || defined(A4_CONN) + if ((pFmeCtrl->FrDs == 1) && (pFmeCtrl->ToDs == 1)) + { +#ifdef CLIENT_WDS + if (pEntry) { + /* The CLIENT WDS must be a associated STA */ + if (IS_ENTRY_CLIWDS(pEntry)) + ; + else if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) + SET_ENTRY_CLIWDS(pEntry); + else + return FALSE; + + CliWds_ProxyTabUpdate(pAd, pEntry->Aid, pHeader->Octet); + } +#endif /* CLIENT_WDS */ +#ifdef A4_CONN + if(!pEntry) + pEntry = MacTableLookup(pAd, pHeader->Addr2); + if (pEntry && IS_ENTRY_A4(pEntry)) + { + MAC_TABLE_ENTRY *pMovedEntry = NULL; + UINT16 ProtoType = 0; + UINT32 ARPSenderIP = 0; + UINT8 ARPSenderIPSkipLen=0; + UCHAR *Pos = NULL; + BOOLEAN bTAMatchSA = FALSE; + /*this is a 4-addr pkt*/ + ARPSenderIPSkipLen += sizeof(*pHeader)+6; + if (pFmeCtrl->SubType & 0x08) { + ARPSenderIPSkipLen += 2; + } + if (pFmeCtrl->Order +#ifdef AGGREGATION_SUPPORT + && !(pRxBlk->rx_rate.field.MODE <= MODE_OFDM && + CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_AGGREGATION_CAPABLE)) +#endif + ) { + ARPSenderIPSkipLen += 4; + } + if (pRxInfo->L2PAD) { + ARPSenderIPSkipLen += 2; + } + if (NdisEqualMemory(SNAP_802_1H, pRxBlk->pData + ARPSenderIPSkipLen, 6) || + NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pRxBlk->pData + ARPSenderIPSkipLen, 6)) { + ARPSenderIPSkipLen += 6; + } + + Pos = (pRxBlk->pData + ARPSenderIPSkipLen); + bTAMatchSA = MAC_ADDR_EQUAL(pEntry->Addr, pHeader->Octet); + + hex_dump("RA",pHeader->Addr1,6); + hex_dump("TA",pHeader->Addr2,6); + hex_dump("DA",pHeader->Addr3,6); + hex_dump("SA",pHeader->Octet,6); + ProtoType = OS_NTOHS(*((UINT16*)Pos)); + if(ProtoType == 0x0806) /* ETH_P_ARP */ + NdisCopyMemory(&ARPSenderIP, (Pos + 16), 4); + + /* + It means this source entry has moved to another one and hidden behind it. + So delete this source entry! + */ + if(!bTAMatchSA) /* TA isn't same with SA case*/ + { + pMovedEntry = MacTableLookup(pAd, pHeader->Octet); + if(pMovedEntry +#ifdef AIR_MONITOR + && !IS_ENTRY_MONITOR(pMovedEntry) +#endif /* AIR_MONITOR */ + && IS_ENTRY_CLIENT(pMovedEntry) + ) + { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("APRxPktAllow: AP found a entry(%02X:%02X:%02X:%02X:%02X:%02X) who has moved to another side! Delete it from MAC table.\n", + PRINT_MAC(pMovedEntry->Addr))); + +#ifdef WH_EVENT_NOTIFIER + { + EventHdlr pEventHdlrHook = NULL; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_STA_LEAVE); + if(pEventHdlrHook && pMovedEntry->wdev) + pEventHdlrHook(pAd, pMovedEntry->wdev, pMovedEntry->Addr, pAd->CommonCfg.Channel); + } +#endif /* WH_EVENT_NOTIFIER */ + MacTableDeleteEntry(pAd, pMovedEntry->wcid, pMovedEntry->Addr); + } + } + a4_proxy_update(pAd, pEntry->func_tb_idx, pEntry->wcid, pHeader->Octet, ARPSenderIP); + } else { + pEntry = NULL; + } +#endif /* A4_CONN */ + +#ifdef WDS_SUPPORT + if (!pEntry) + { + /* + The WDS frame only can go here when in auto learning mode and + this is the first trigger frame from peer + + So we check if this is un-registered WDS entry by call function + "FindWdsEntry()" + */ + if (MAC_ADDR_EQUAL(pHeader->Addr1, pAd->CurrentAddress)) + pEntry = FindWdsEntry(pAd, pRxBlk->wcid, pHeader->Addr2, pRxBlk->rx_rate.field.MODE); + + /* have no valid wds entry exist, then discard the incoming packet.*/ + if (!(pEntry && WDS_IF_UP_CHECK(pAd, pEntry->func_tb_idx))) + return FALSE; + + /*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; + // TODO: shiang-usw, remove upper setting because we need to mirgate to tr_entry! + pAd->MacTab.tr_entry[pEntry->wcid].ContinueTxFailCnt = 0; + pAd->MacTab.tr_entry[pEntry->wcid].LockEntryTx = FALSE; + } + } +#endif /* WDS_SUPPORT */ + + if (pEntry) + { +#ifdef STATS_COUNT_SUPPORT +#ifdef WDS_SUPPORT + RT_802_11_WDS_ENTRY *pWdsEntry = &pAd->WdsTab.WdsEntry[pEntry->func_tb_idx]; + + pWdsEntry->WdsCounter.ReceivedByteCount += pRxBlk->MPDUtotalByteCnt; + INC_COUNTER64(pWdsEntry->WdsCounter.ReceivedFragmentCount); + + if(IS_MULTICAST_MAC_ADDR(pHeader->Addr3)) + INC_COUNTER64(pWdsEntry->WdsCounter.MulticastReceivedFrameCount); +#endif /* STATS_COUNT_SUPPORT */ +#endif + RX_BLK_SET_FLAG(pRxBlk, fRX_WDS); + hdr_len = LENGTH_802_11_WITH_ADDR4; + return hdr_len; + } + + return FALSE; + } +#endif /* defined(WDS_SUPPORT) || defined(CLIENT_WDS) */ + + if (!pEntry) { +#ifdef IDS_SUPPORT + if ((pHeader->FC.FrDs == 0) && (pRxBlk->wcid == RESERVED_WCID)) /* not in RX WCID MAC table */ + pAd->ApCfg.RcvdMaliciousDataCount++; +#endif /* IDS_SUPPORT */ + + return FALSE; + } + + if (!((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 1))) { +#ifdef IDS_SUPPORT + /* + Replay attack detection, + drop it if detect a spoofed data frame from a rogue AP + */ + if (pFmeCtrl->FrDs == 1) + RTMPReplayAttackDetection(pAd, pHeader->Addr2, pRxBlk); +#endif /* IDS_SUPPORT */ + + return FALSE; + } +#ifdef A4_CONN + if (((pFmeCtrl->FrDs == 0) && (pFmeCtrl->ToDs == 1))) { + if((pFmeCtrl->SubType != SUBTYPE_DATA_NULL) && (pFmeCtrl->SubType != SUBTYPE_QOS_NULL)) { +#ifdef MWDS + if (pEntry && GET_ENTRY_A4(pEntry) == A4_TYPE_MWDS) { + return FALSE; + } +#endif + } + } +#endif /* A4_CONN */ + + /* check if Class2 or 3 error */ + if (APChkCls2Cls3Err(pAd, pRxBlk->wcid, pHeader)) + return FALSE; + +//+++Add by shiang for debug +#ifdef RLT_MAC_DBG + if (pAd->chipCap.hif_type == HIF_RLT) { + if (pRxBlk->wcid >= MAX_LEN_OF_MAC_TABLE) { + MAC_TABLE_ENTRY *pEntry = NULL; + + DBGPRINT(RT_DEBUG_WARN, ("ErrWcidPkt: seq=%d\n", pHeader->Sequence)); + pEntry = MacTableLookup(pAd, pHeader->Addr2); + if (pEntry && (pEntry->Sst == SST_ASSOC) && IS_ENTRY_CLIENT(pEntry)) + pRxBlk->wcid = pEntry->wcid; + + dump_next_valid = 1; + } + else if (dump_next_valid) + { + DBGPRINT(RT_DEBUG_WARN, ("NextValidWcidPkt: seq=%d\n", pHeader->Sequence)); + dump_next_valid = 0; + } + } +#endif /* RLT_MAC_DBG */ +//---Add by shiang for debug + + if(pAd->ApCfg.BANClass3Data == TRUE) + return FALSE; + +#ifdef STATS_COUNT_SUPPORT + /* Increase received byte counter per BSS */ + if (pHeader->FC.FrDs == 0 && pRxInfo->U2M) + { + BSS_STRUCT *pMbss = pEntry->pMbss; + if (pMbss != NULL) + { + pMbss->ReceivedByteCount += pRxBlk->MPDUtotalByteCnt; + pMbss->RxCount ++; + } + } + + /* update multicast counter */ + if (IS_MULTICAST_MAC_ADDR(pHeader->Addr3)) + INC_COUNTER64(pAd->WlanCounters.MulticastReceivedFrameCount); +#endif /* STATS_COUNT_SUPPORT */ + +#ifdef WH_EVENT_NOTIFIER + if(pEntry && IS_ENTRY_CLIENT(pEntry) +#ifdef A4_CONN + && !IS_ENTRY_A4(pEntry) +#endif /* A4_CONN */ + && ((pFmeCtrl->SubType != SUBTYPE_DATA_NULL) && (pFmeCtrl->SubType != SUBTYPE_QOS_NULL)) + ) + pEntry->rx_state.PacketCount++; +#endif /* WH_EVENT_NOTIFIER */ + + hdr_len = LENGTH_802_11; + RX_BLK_SET_FLAG(pRxBlk, fRX_STA); + + ASSERT(pEntry->Aid == pRxBlk->wcid); + + return hdr_len; + +} + + +INT ap_rx_ps_handle(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + HEADER_802_11 *pHeader = pRxBlk->pHeader; + UCHAR OldPwrMgmt = PWR_ACTIVE; /* 1: PWR_SAVE, 0: PWR_ACTIVE */ + +#ifdef UAPSD_SUPPORT + UCHAR *pData = pRxBlk->pData; +#endif /* UAPSD_SUPPORT */ + /* 1: PWR_SAVE, 0: PWR_ACTIVE */ + + OldPwrMgmt = RtmpPsIndicate(pAd, pHeader->Addr2, pEntry->wcid, pHeader->FC.PwrMgmt); + + if(OldPwrMgmt > 2) + DBGPRINT(RT_DEBUG_TRACE, ("OldPwrMgmt is %d\n", OldPwrMgmt)); + +#ifdef UAPSD_SUPPORT + + if ((pHeader->FC.PwrMgmt == PWR_SAVE) && + (OldPwrMgmt == PWR_SAVE) && + (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_APSD_CAPABLE)) && + (pHeader->FC.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; + + // TODO: shiang-usw, check this!!! +#ifdef HDR_TRANS_SUPPORT + if (pRxBlk->bHdrRxTrans) { + // TODO: different chip has different position @20130129. (+32 is for MT7650) + OldUP = (*(pData+32) & 0x07); + } + else +#endif /* HDR_TRANS_SUPPORT */ + OldUP = (*(pData+LENGTH_802_11) & 0x07); +#ifdef MT_PS + if (pEntry->i_psm == I_PSM_DISABLE) + { + MT_SET_IGNORE_PSM(pAd, pEntry, I_PSM_ENABLE); + } +#endif /* MT_PS */ + UAPSD_TriggerFrameHandle(pAd, pEntry, OldUP); + } +#endif /* UAPSD_SUPPORT */ + + return TRUE; +} + + +INT ap_rx_foward_handle(RTMP_ADAPTER *pAd, struct wifi_dev *wdev, PNDIS_PACKET pPacket) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + BOOLEAN to_os, to_air; + UCHAR *pHeader802_3; + PNDIS_PACKET pForwardPacket; + BSS_STRUCT *pMbss; + struct wifi_dev *dst_wdev = NULL; +#ifdef A4_CONN + UCHAR wcid; + UCHAR *pSrcAddr = NULL; + UCHAR *pSrcBufVA = NULL; +#endif /* A4_CONN */ + + if ((wdev->func_idx >= MAX_MBSSID_NUM(pAd)) || + (wdev->func_idx >= HW_BEACON_MAX_NUM)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Invalid func_idx(%d), type(%d)!\n", + __FUNCTION__, wdev->func_idx, wdev->wdev_type)); + return FALSE; + } + + /* only one connected sta, directly to upper layer */ + if (pAd->MacTab.Size <= 1) + return TRUE; + + // TODO: shiang-usw, remove pMbss structure here to make it more generic! + pMbss = &pAd->ApCfg.MBSSID[wdev->func_idx]; + pHeader802_3 = GET_OS_PKT_DATAPTR(pPacket); + + /* by default, announce this pkt to upper layer (bridge) and not to air */ + to_os = TRUE; + to_air = FALSE; + + if (pHeader802_3[0] & 0x01) + { + if ((pMbss->StaCount > 1) + ) { + /* forward the M/Bcast packet back to air if connected STA > 1 */ + to_air = TRUE; + } + } + else + { + /* if destinated STA is a associated wireless STA */ + pEntry = MacTableLookup(pAd, pHeader802_3); + if (pEntry && pEntry->Sst == SST_ASSOC && pEntry->wdev) + { + dst_wdev = pEntry->wdev; + if (wdev == dst_wdev) + { + /* + STAs in same SSID, default send to air and not to os, + but not to air if match following case: + a). pMbss->IsolateInterStaTraffic == TRUE + */ + to_air = TRUE; + to_os = FALSE; + if (pMbss->IsolateInterStaTraffic == 1) + to_air = FALSE; + } + else + { + /* + STAs in different SSID, default send to os and not to air + but not to os if match any of following cases: + a). destination VLAN ID != source VLAN ID + b). pAd->ApCfg.IsolateInterStaTrafficBTNBSSID + */ + to_os = TRUE; + to_air = FALSE; + if (pAd->ApCfg.IsolateInterStaTrafficBTNBSSID == 1 || + (wdev->VLAN_VID != dst_wdev->VLAN_VID)) + to_os = FALSE; + } +#ifdef WH_EVENT_NOTIFIER + if(to_air && IS_ENTRY_CLIENT(pEntry) +#ifdef A4_CONN + && !IS_ENTRY_A4(pEntry) +#endif /* A4_CONN */ + ) + pEntry->tx_state.PacketCount++; +#endif /* WH_EVENT_NOTIFIER */ + } +#ifdef A4_CONN + else if (!pEntry && a4_proxy_lookup(pAd, wdev->func_idx, pHeader802_3, FALSE, TRUE, &wcid)) + { + if (VALID_WCID(wcid)) + pEntry = &pAd->MacTab.Content[wcid]; + + if (pEntry && IS_ENTRY_CLIENT(pEntry)) { + to_os = FALSE; + to_air = TRUE; + dst_wdev = pEntry->wdev; + } + } +#endif /* A4_CONN */ + } + +#ifdef PREVENT_ARP_SPOOFING + if (pAd->ApCfg.ARPSpoofChk) + { + /* + This is on AP Rx data Path : + sofar both direction will be checked, maybe we can check to_air case only + */ + if (to_os || to_air) + { + if (check_arp_spoofing(wdev->if_dev, pPacket)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): DROP: Detected ARP spoofing (func_idx=%d,wdev_type=%d)!\n", + __FUNCTION__, wdev->func_idx, wdev->wdev_type)); + to_os = FALSE; + return to_os; //Free pPacket out side + } + } + } +#endif /* PREVENT_ARP_SPOOFING */ + + if (to_air) + { +#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 */ + + pForwardPacket = DuplicatePacket(wdev->if_dev, pPacket); + if (pForwardPacket == NULL) + return to_os; + + /* 1.1 apidx != 0, then we need set packet mbssid attribute. */ + if (pEntry) { + RTMP_SET_PACKET_WDEV(pForwardPacket, dst_wdev->wdev_idx); + RTMP_SET_PACKET_WCID(pForwardPacket, pEntry->wcid); + } + else /* send bc/mc frame back to the same bss */ + { + RTMP_SET_PACKET_WDEV(pForwardPacket, wdev->wdev_idx); + RTMP_SET_PACKET_WCID(pForwardPacket, wdev->tr_tb_idx); + } + + RTMP_SET_PACKET_MOREDATA(pForwardPacket, FALSE); + +#ifdef INF_AMAZON_SE + /*Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */ + RTMP_SET_PACKET_NOBULKOUT(pForwardPacket, TRUE); +#endif /* INF_AMAZON_SE */ + +#ifndef A4_CONN + APSendPacket(pAd, pForwardPacket); +#else + /* send bc/mc frame back to the same bss */ + pSrcBufVA = pHeader802_3; + pSrcAddr = pHeader802_3 + MAC_ADDR_LEN; + + if (pSrcBufVA && IS_BROADCAST_MAC_ADDR(pSrcBufVA)) { + a4_send_clone_pkt(pAd, wdev->func_idx, pPacket, pSrcAddr); + } else if (pSrcBufVA && IS_MULTICAST_MAC_ADDR(pSrcBufVA) +#ifdef IGMP_SNOOP_SUPPORT + && (!pAd->ApCfg.IgmpSnoopEnable) +#endif + ) + { + a4_send_clone_pkt(pAd, wdev->func_idx, pPacket, pSrcAddr); + } else { + DBGPRINT(RT_DEBUG_TRACE, ("This packet is a uc or IGMP is on, no need MWDS CLONE\n")); + } + + APSendPacket(pAd, pForwardPacket); +#endif /* A4_CONN */ + + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, WCID_ALL, MAX_TX_PROCESS); + } + + return to_os; +} + + +/* + ======================================================================== + 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 TxSwQ. + NDIS_STATUS_FAILURE: If failed to do en-queue. +======================================================================== +*/ +NDIS_STATUS APInsertPsQueue( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN STA_TR_ENTRY *tr_entry, + IN UCHAR QueIdx) +{ + return NDIS_STATUS_SUCCESS; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_dls.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_dls.c new file mode 100644 index 000000000..d80bc46a6 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_dls.c @@ -0,0 +1,27 @@ +/**************************************************************************** + * 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" + + + +/* End of ap_dls.c */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_ftkd.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_ftkd.c new file mode 100644 index 000000000..488af9a97 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_ftkd.c @@ -0,0 +1,1775 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + + Abstract: + + All related IEEE802.11r Key Distribution Protocol (FT KDP) body. + + Overview: + + 1. A station associates to us, send out a broadcast ADD-Notify packet. + + ASSOC --> + FT_KDP_EVENT_INFORM(FT_KDP_SIG_FT_ASSOCIATION) --> + FT_KDP_EventInform(FT_KDP_SIG_FT_ASSOCIATION) --> + Notify IAPP daemon, IAPP_RcvHandlerRawDrv(), IAPP_SIG_Process() --> + Send ADD-Notify packet, IAPP_UDP_PacketSend(), IAPP_L2UpdateFrameSend() + + 2. When receiving a ADD-Notify packet, send a unicast SSB packet to + request PMK-R1 key for the station with our R0KH. + + IAPP daemon, IAPP_RcvHandlerUdp() --> + Notify driver, IAPP_MsgProcess() --> + IOCTL, RTMPAPSetInformation() --> + FT_KDP_StationInform() --> + Notify IAPP daemon, FT_KDP_EventInform(FT_KDP_SIG_KEY_REQ_AUTO) --> + Notify IAPP daemon, IAPP_RcvHandlerRawDrv(), IAPP_SIG_Process() --> + Send SSB packet with R0KHID = 0, by using TCP or UDP based on peerIP + + 3. A station reassociates to us, send out a MOVE-Request packet. + + REASSOC --> + FT_KDP_EVENT_INFORM(FT_KDP_SIG_FT_REASSOCIATION) --> + FT_KDP_EventInform(FT_KDP_SIG_FT_REASSOCIATION) --> + Notify IAPP daemon, IAPP_RcvHandlerRawDrv(), IAPP_SIG_Process() --> + Send MOVE-Request packet by using TCP or UDP, IAPP_L2UpdateFrameSend() + + 4. When receiving a MOVE-Request packet, delete the STA MAC entry. + + IAPP daemon, IAPP_RcvHandlerUdp()/ IAPP_RcvHandlerTcp() --> + Notify driver, IAPP_MsgProcess() --> + IOCTL, RTMPAPSetInformation() --> + RT_SET_DEL_MAC_ENTRY --> + Send MOVE-Response packet by using TCP, FT_KDP_MoveFrameSend() + + 5. When receiving a MOVE-Response packet, nothing to do. + + 6. When receiving a SSB packet (i.e. key request), send a unicast SAB + packet to response the key to the R1KH. + + IAPP daemon --> + Notify driver, IAPP_MsgProcess() --> + IOCTL, RTMPAPSetInformation() --> + FT_KDP_IOCTL_KEY_REQ() --> + Notify IAPP daemon, FT_KDP_EventInform(FT_KDP_SIG_KEY_RSP_AUTO) --> + Send SAB packet with my R0KHID, FT_KDP_SecurityBlockSend() by using TCP + + 7. When receiving a SAB packet (i.e. key response), set the PMK-R1 key. + + IAPP daemon --> + Notify driver, IAPP_MsgProcess() --> + IOCTL, RTMPAPSetInformation() --> + FT_KDP_KeyResponseToUs() + + 8. Send a information broadcast to the LAN periodically. + +***************************************************************************/ + +#ifdef DOT11R_FT_SUPPORT + +#include "rt_config.h" +#include "ft_cmm.h" + +#define TYPE_FUNC +#define FT_KDP_DEBUG +#define FT_KDP_FUNC_TEST +/*#define FT_KDP_EMPTY */ /* empty codes to debug */ + +#define IAPP_SHOW_IP_HTONL(__IP) \ + (htonl(__IP) >> 24) & 0xFF, \ + (htonl(__IP) >> 16) & 0xFF, \ + (htonl(__IP) >> 8) & 0xFF, \ + (htonl(__IP) & 0xFF) + +#define IAPP_DAEMON_CMD_PARSE(__pInfo, __InfoLen, __PeerIP, __pData, __DataLen) \ + NdisMoveMemory(&__PeerIP, __pInfo, FT_IP_ADDRESS_SIZE); \ + __pData = (UCHAR *)(__pInfo + FT_IP_ADDRESS_SIZE); \ + __DataLen = __InfoLen - FT_IP_ADDRESS_SIZE; + +/* private variable */ +UINT32 FT_KDP_MemAllocNum, FT_KDP_MemFreeNum; + +/* extern variable */ +#ifdef FT_KDP_FUNC_TEST +extern UCHAR gFT_MAC_OldAP[]; +#endif /* FT_KDP_FUNC_TEST */ + +/* private function prototype */ +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD +BOOLEAN FT_KDP_R0KH_InfoAdd( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pR0KHID, + IN UCHAR *pMAC, + IN UINT32 IP); +VOID FT_KDP_R0KH_InfoDel( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pR0KHID, + IN UCHAR *pMAC, + IN UINT32 IP); +static BOOLEAN FT_KDP_R0KH_InfoGet( + IN PRTMP_ADAPTER pAd, + INOUT UCHAR *pR0KHID, + INOUT UCHAR *pMAC, + OUT UINT32 *pIP); +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + + + + +/* public function */ +/* +======================================================================== +Routine Description: + Initialize FT KDP Module. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_Init( + IN PRTMP_ADAPTER pAd) +{ +#ifndef FT_KDP_EMPTY + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 1) + return; + + DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> Initialize FT KDP Module...\n")); + + /* allocate control block */ + FT_MEM_ALLOC(pAd, &pAd->ApCfg.FtTab.pFT_KDP_Ctrl_BK, sizeof(FT_KDP_CTRL_BLOCK)); + if (pAd->ApCfg.FtTab.pFT_KDP_Ctrl_BK == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> Allocate control block fail!\n")); + return; + } + + NdisAllocateSpinLock(pAd, &(pAd->ApCfg.FtTab.FT_KdpLock)); + +#ifndef FT_KDP_FUNC_SOCK_COMM + /* init event list */ + initList(&(FT_KDP_CB->EventList)); +#endif /* FT_KDP_FUNC_SOCK_COMM */ + +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD + /* init R0KH information record */ + FT_KDP_CB->R0KH_InfoHead = NULL; + FT_KDP_CB->R0KH_InfoTail = NULL; + FT_KDP_CB->R0KH_Size = 0; +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + +#ifdef FT_KDP_FUNC_INFO_BROADCAST + RTMPInitTimer(pAd, &FT_KDP_CB->TimerReport, + GET_TIMER_FUNCTION(FT_KDP_InfoBroadcast), + (PVOID)pAd, TRUE); + RTMPSetTimer(&FT_KDP_CB->TimerReport, FT_KDP_INFO_BC_PERIOD_TIME); +#endif /* FT_KDP_FUNC_INFO_BROADCAST */ +#endif /* FT_KDP_EMPTY */ + + pAd->ApCfg.FtTab.FlgIsFtKdpInit = 1; +} + + +/* +======================================================================== +Routine Description: + Release FT KDP Module. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_Release( + IN PRTMP_ADAPTER pAd) +{ +#ifndef FT_KDP_EMPTY +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD + FT_KDP_R0KH_INFO *pInfoHead, *pInfo; +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + return; + + DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> Release FT KDP Module...\n")); + +#ifndef FT_KDP_FUNC_SOCK_COMM + /* free event list */ + FT_KDP_EVT_LIST_EMPTY(pAd, &(FT_KDP_CB->EventList)); +#endif /* FT_KDP_FUNC_SOCK_COMM */ + +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD + /* free all R0KH information */ + pInfoHead = FT_KDP_CB->R0KH_InfoHead; + while(pInfoHead != NULL) + { + pInfo = pInfoHead; + pInfoHead = pInfoHead->pNext; + + FT_MEM_FREE(pAd, pInfo); + } +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + + if (pAd->ApCfg.FtTab.pFT_KDP_Ctrl_BK != NULL) + { + FT_MEM_FREE(pAd, pAd->ApCfg.FtTab.pFT_KDP_Ctrl_BK); + pAd->ApCfg.FtTab.pFT_KDP_Ctrl_BK = NULL; + } + +#ifdef FT_KDP_FUNC_INFO_BROADCAST +{ + BOOLEAN Status; + RTMPCancelTimer(&FT_KDP_CB->TimerReport, &Status); +} +#endif /* FT_KDP_FUNC_INFO_BROADCAST */ + + /* free spin lock */ + NdisFreeSpinLock(&(pAd->ApCfg.FtTab.FT_KdpLock)); +#endif /* FT_KDP_EMPTY */ + + pAd->ApCfg.FtTab.FlgIsFtKdpInit = 0; +} + + +/* +======================================================================== +Routine Description: + Inform us a event occurs. + +Arguments: + pAd - WLAN control block pointer + ApIdx - MBSS ID + EventId - which event, such as FT_KDP_SIG_FT_ASSOCIATION + *pEvent - event body + EventLen - event body length + PeerIP - peer IP address + pCB - for special use (such as FT_KDP_SIG_ACTION) + +Return Value: + None + +Note: + EventId *pEvent + -------------------------------------------------------------------- + FT_KDP_SIG_FT_ASSOCIATION FT_KDP_EVT_ASSOC + FT_KDP_SIG_FT_REASSOCIATION FT_KDP_EVT_REASSOC + FT_KDP_SIG_KEY_TIMEOUT yet implement + FT_KDP_SIG_KEY_REQ FT_KDP_EVT_KEY_ELM + FT_KDP_SIG_ACTION WLAN Frame Body (Start from Category field) + pCB == FT_KDP_EVT_ACTION + +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_EventInform( + IN PRTMP_ADAPTER pAd, + IN UINT32 ApIdx, + IN UCHAR EventId, + IN VOID *pEvent, + IN UINT16 EventLen, + IN UINT32 PeerIP, + IN VOID *pCB) +{ +#ifndef FT_KDP_EMPTY +#ifndef FT_KDP_FUNC_SOCK_COMM + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR Size; +#endif /* FT_KDP_FUNC_SOCK_COMM */ + FT_KDP_SIGNAL *pFtKdp; + FT_KDP_EVT_HEADER EvtHdr; + + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } + +#ifndef FT_KDP_FUNC_SOCK_COMM + CHECK_PID_LEGALITY(pObj->IappPid) + { + /* valid, can do next step */ + } + else + return; + + FT_KDP_EVT_LIST_SIZE_GET(pAd, &FT_KDP_CB->EventList, Size); + if (Size > FT_KDP_EVENT_MAX) + { + DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Queued Events are too much!\n")); + return; + } +#endif /* FT_KDP_FUNC_SOCK_COMM */ + + /* make up event content */ + NdisZeroMemory(&EvtHdr, sizeof(FT_KDP_EVT_HEADER)); + FT_MEM_ALLOC(pAd, &pFtKdp, sizeof(FT_KDP_SIGNAL)); + if (pFtKdp == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Allocate signal content fail!\n")); + return; + } + pFtKdp->Sig = EventId; + + /* handle different event */ + switch(EventId) + { + case FT_KDP_SIG_FT_ASSOCIATION: + { + /* a station associates to us */ + + /* + When a STA uses the 802.11 Association Request, rather than + the Reassociation Request, the IAPP may not be able to notify + the AP at which the STA was previously associated of the new + association. + */ + + FT_KDP_EVT_ASSOC *pEvtAssoc; + + pEvtAssoc = (FT_KDP_EVT_ASSOC *)pEvent; + + pFtKdp->Sequence = pEvtAssoc->SeqNum; + NdisMoveMemory(pFtKdp->MacAddr, pEvtAssoc->MacAddr, MAC_ADDR_LEN); + } + break; + + case FT_KDP_SIG_FT_REASSOCIATION: + { + /* a station reassociates to us */ + + /* + IEEE802.11f, 1.3 Inter-AP recommended practice overview + + In particular, the IAPP entity must be able to find and use + a RADIUS server to look up the IP addresses of other APs in + the ESS when given the Basic Service Set Identifier (BSSIDs) + of those other APs (if a local capability to perform such a + translation is not present), and to obtain security information + to protect the content of certain IAPP packets. + + Here we dont use any Radius server so sometimes we can not + send the MOVE-notify frame. + */ + + /* + The IAPP is not a routing protocol. The IAPP does not deal + directly with the delivery of 802.11 data frames to the STA; + instead the DS utilizes existing network functionality for + data frame delivery. + + When a STA associates or reassociates, the STA must ascertain + that its network layer address(es) is configured such that the + normal routing functions of the network attaching to the BSS + will correctly deliver the STA¡¦s traffic to the BSS to which + it is associated. + + Two mechanisms for a STA to accomplish this are to renew a + Dynamic Host Configuration Protocol (DHCP) lease for its IP + address and to use Mobile IP to obtain a local IP address. + */ + + FT_KDP_EVT_REASSOC *pEvtReAssoc; + + pEvtReAssoc = (FT_KDP_EVT_REASSOC *)pEvent; + + pFtKdp->Sequence = pEvtReAssoc->SeqNum; + NdisMoveMemory(pFtKdp->MacAddr, pEvtReAssoc->MacAddr, MAC_ADDR_LEN); + + /* try to get the IP of old AP */ + if (FT_KDP_R0KH_InfoGet(pAd, NULL, + pEvtReAssoc->OldApMacAddr, + &PeerIP) == FALSE) + { + } + } + break; + + + case FT_KDP_SIG_KEY_TIMEOUT: + /* PMK-R1 Key timeout */ + break; + + + case FT_KDP_SIG_KEY_REQ: + { + FT_KDP_EVT_KEY_ELM *pEvtKeyReq; + + /* PMK-R1 Key Request */ + if (PeerIP != 0) + break; + + /* try to find the Peer IP address */ + pEvtKeyReq = (FT_KDP_EVT_KEY_ELM *)pEvent; + + if (FT_KDP_R0KH_InfoGet(pAd, pEvtKeyReq->KeyInfo.R0KHID, + NULL, &PeerIP) == FALSE) + { + + /* send a broadcast key request packet */ + } + } + break; + + + case FT_KDP_SIG_ACTION: + { + /* forward FT Action frame by using RRB protocol */ + FT_KDP_EVT_ACTION *pActionCB = (FT_KDP_EVT_ACTION *)pCB; + + if (pCB == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> pCB == NULL!\n")); + FT_MEM_FREE(pAd, pFtKdp); + return; + } + + pFtKdp->Sequence = pActionCB->RequestType; + NdisMoveMemory(pFtKdp->MacAddr, pActionCB->MacDa, ETH_ALEN); + NdisMoveMemory(pFtKdp->MacAddrSa, pActionCB->MacSa, ETH_ALEN); + NdisMoveMemory(pFtKdp->CurrAPAddr, pActionCB->MacAp, ETH_ALEN); + } + break; + + + case FT_KDP_SIG_KEY_REQ_AUTO: + /* PMK-R1 Key Request */ + break; + + + case FT_KDP_SIG_KEY_RSP_AUTO: + /* PMK-R1 Key Response */ + break; + + + case FT_KDP_SIG_INFO_BROADCAST: + /* broadcast our AP information to neighbor APs */ + break; + + + case FT_KDP_SIG_AP_INFO_REQ: + /* request neighbor AP information */ + break; + + + case FT_KDP_SIG_AP_INFO_RSP: + /* response my information to a AP */ + break; + + + case FT_KSP_SIG_DEBUG_TRACE: + /* change the debug level of IAPP daemon */ + break; + + + case FT_KDP_SIG_TERMINATE: + /* terminate FT KDP daemon */ + break; + + + default: + /* error event */ + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Signal is not supported %d!\n", EventId)); + FT_MEM_FREE(pAd, pFtKdp); + return; + } + + /* init event content */ + EvtHdr.PeerIpAddr = PeerIP; + EvtHdr.EventLen = EventLen; + + NdisMoveMemory(pFtKdp->Content, &EvtHdr, sizeof(FT_KDP_EVT_HEADER)); + + if (pEvent != NULL) + { + NdisMoveMemory(pFtKdp->Content+sizeof(FT_KDP_EVT_HEADER), + pEvent, EventLen); + } + + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Event ID = %d, EventLen = %d (%d, %d)\n", + EventId, EventLen, FT_KDP_MemAllocNum, FT_KDP_MemFreeNum)); + +#ifndef FT_KDP_FUNC_SOCK_COMM + /* insert to the event queue */ + FT_KDP_EVT_LIST_INSERT_TAIL(pAd, &FT_KDP_CB->EventList, pFtKdp); + + /* inform FT KDP daemon to handle the event */ + if ((EventId == FT_KDP_SIG_TERMINATE) || + (EventId == FT_KSP_SIG_DEBUG_TRACE) || + (EventId == FT_KDP_SIG_FT_ASSOCIATION) || + (EventId == FT_KDP_SIG_FT_REASSOCIATION) || + (EventId == FT_KDP_SIG_KEY_REQ) || + (EventId == FT_KDP_SIG_KEY_TIMEOUT)) + { + /* + Note: in VxWorks, we can not send any signal to same task + which issues a ioctl path. + */ + + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Send signal to ft kdp daemon... (EventLen = %d)\n", + EventLen)); + SendSignalToDaemon(SIGUSR2, pObj->IappPid, pObj->IappPid_nr); + } /* End of if */ +#endif /* FT_KDP_FUNC_SOCK_COMM */ + +#ifdef FT_KDP_FUNC_SOCK_COMM + /* inform FT KDP daemon to handle the event */ +{ + FT_DRV_ETH_HEADER Hdr8023, *pHdr8023 = &Hdr8023; + NDIS_PACKET *pPktComm; + UINT32 FrameLen; +#ifdef FT_OS_VXWORKS + END_OBJ *pEndEth; +#endif /* FT_OS_VXWORKS */ + + /* allocate a rx packet */ + pPktComm = RtmpOSNetPktAlloc(pAd, sizeof(RT_SIGNAL_STRUC)+LENGTH_802_3); + if (pPktComm != NULL) + { + /* make up 802.3 header */ + NdisMoveMemory(pHdr8023->DA, pAd->ApCfg.MBSSID[ApIdx].wdev.bssid, MAC_ADDR_LEN); + + /* can not send a packet with same SA & DA in 5VT board */ +/* NdisMoveMemory(pHdr8023->SA, pAd->ApCfg.MBSSID[ApIdx].Bssid, 6); */ + NdisZeroMemory(pHdr8023->SA, ETH_ALEN); + pHdr8023->SA[5] = 0x01; + pHdr8023->Len = IAPP_ETH_PRO; + + /* convert 802.11 to 802.3 packet */ +#ifdef FT_OS_VXWORKS + pEndEth = endFindByName("mirror", 0); + if (pEndEth != NULL) + { + /* + Sometimes if I use ra0 to send the command packet, daemon + can not receive the command packet! + So I use bridge to do the receive network interface. + + Support IEEE802.11r DS, must have bridge network interface. + */ + SET_OS_PKT_NETDEV(pPktComm, pEndEth->devObject.pDevice); + } + else +#endif /* FT_OS_VXWORKS */ + SET_OS_PKT_NETDEV(pPktComm, get_netdev_from_bssid(pAd, ApIdx)); + + OS_PKT_RESERVE(RTPKT_TO_OSPKT(pPktComm), 2); /* 16 byte align the IP header */ + NdisMoveMemory(OS_PKT_TAIL_BUF_EXTEND(RTPKT_TO_OSPKT(pPktComm), LENGTH_802_3), + pHdr8023, LENGTH_802_3); + + FrameLen = RT_SIGNAL_STRUC_HDR_SIZE+sizeof(FT_KDP_EVT_HEADER)+EventLen; + NdisMoveMemory(OS_PKT_TAIL_BUF_EXTEND(RTPKT_TO_OSPKT(pPktComm), FrameLen), + pFtKdp, FrameLen); + + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Send a command (MBSS%d, Frame Len%d) to IAPP daemon.\n", + ApIdx, FrameLen)); + + /* pass this packet to upper layer */ + announce_802_3_packet(pAd, pPktComm, OPMODE_AP); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Allocate signal to ft kdp daemon fail!\n")); + } +} +#endif + +#ifdef FT_KDP_FUNC_SOCK_COMM + FT_MEM_FREE(pAd, pFtKdp); +#endif /* FT_KDP_FUNC_SOCK_COMM */ +#endif /* FT_KDP_EMPTY */ +} + + +/* +======================================================================== +Routine Description: + Get a event. + +Arguments: + pAd - WLAN control block pointer + **pFtKdp - the queued event; if NULL, no event is queued. + +Return Value: + None + +Note: + Used in IOCTL from FT KDP daemon. +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_EventGet( + IN PRTMP_ADAPTER pAd, + OUT FT_KDP_SIGNAL **pFtKdp) +{ +#ifndef FT_KDP_EMPTY +#ifndef FT_KDP_FUNC_SOCK_COMM + UCHAR Size; + + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } + + /* init */ + FT_KDP_EVT_LIST_SIZE_GET(pAd, &FT_KDP_CB->EventList, Size); + + /* check if any event is queued */ + if (Size <= 0) + { + *pFtKdp = NULL; + return; + } + + /* return a event */ + FT_KDP_EVT_LIST_REMOVE_HEAD(pAd, &FT_KDP_CB->EventList, (*pFtKdp)); +#else + + *pFtKdp = NULL; +#endif /* FT_KDP_FUNC_SOCK_COMM */ +#endif /* FT_KDP_EMPTY */ +} + + +/* +======================================================================== +Routine Description: + Inform us a AP request the key. + +Arguments: + pAd - WLAN control block pointer + PeerIP - the IP of R1KH, must not be 0 + *pNonce - the nonce for key request + *pEvtKeyReq - information for key request + +Return Value: + TRUE - request ok + FALSE - can not find the IP of R0KH + +Note: + If PeerIP == 0, search its IP from our information record. +======================================================================== +*/ +BOOLEAN TYPE_FUNC FT_KDP_KeyRequestToUs( + IN PRTMP_ADAPTER pAd, + IN UINT32 PeerIP, + IN UCHAR *pNonce, + IN FT_KDP_EVT_KEY_ELM *pEvtKeyReq) +{ +#ifndef FT_KDP_EMPTY + UINT32 IDR0KH; + UINT32 ApIdx; + + + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Key Req from Peer IP = %d.%d.%d.%d!\n", + IAPP_SHOW_IP_HTONL(PeerIP))); + + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return FALSE; + } + + if (PeerIP == 0) + return FALSE; + + /* sanity check for R0KHID */ +#ifdef FT_KDP_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Key Req: R0KH-ID = " + "0x%02x:%02x:%02x:%02x:%02x:%02x!\n", + pEvtKeyReq->KeyInfo.R0KHID[0], + pEvtKeyReq->KeyInfo.R0KHID[1], + pEvtKeyReq->KeyInfo.R0KHID[2], + pEvtKeyReq->KeyInfo.R0KHID[3], + pEvtKeyReq->KeyInfo.R0KHID[4], + pEvtKeyReq->KeyInfo.R0KHID[5])); +#endif /* FT_KDP_DEBUG */ + + ApIdx = BSS0; + + for(IDR0KH=0; IDR0KHKeyInfo.R0KHID[IDR0KH] != 0x00) + { + /* check if the R0KHID is same as us (MBSS); if not, return FALSE */ + /* yet implement */ + } + } + + /* check if the request format is correct */ + if ((pEvtKeyReq->ElmId == FT_KDP_ELM_ID_PRI) && + (pEvtKeyReq->OUI[0] == FT_KDP_ELM_PRI_OUI_0) && + (pEvtKeyReq->OUI[1] == FT_KDP_ELM_PRI_OUI_1) && + (pEvtKeyReq->OUI[2] == FT_KDP_ELM_PRI_OUI_2)) + { +#ifdef FT_KDP_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Key Req: Station MAC = " + "0x%02x:%02x:%02x:%02x:%02x:%02x!\n", + pEvtKeyReq->MacAddr[0], + pEvtKeyReq->MacAddr[1], + pEvtKeyReq->MacAddr[2], + pEvtKeyReq->MacAddr[3], + pEvtKeyReq->MacAddr[4], + pEvtKeyReq->MacAddr[5])); + + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Key Req: R1KH-ID = " + "0x%02x:%02x:%02x:%02x:%02x:%02x!\n", + pEvtKeyReq->KeyInfo.R1KHID[0], + pEvtKeyReq->KeyInfo.R1KHID[1], + pEvtKeyReq->KeyInfo.R1KHID[2], + pEvtKeyReq->KeyInfo.R1KHID[3], + pEvtKeyReq->KeyInfo.R1KHID[4], + pEvtKeyReq->KeyInfo.R1KHID[5])); +#endif /* FT_KDP_DEBUG */ + + /* calculate the PMK-R1 Key for the station vs. the AP */ + if (FT_QueryKeyInfoForKDP(pAd, ApIdx, pEvtKeyReq) == FALSE) + { + return FALSE; + } + + /* response the requested PMK-R1 Key to the R1KH */ + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Key Rsp to Peer IP = %d.%d.%d.%d!\n", + IAPP_SHOW_IP_HTONL(PeerIP))); + + FT_KDP_EventInform(pAd, ApIdx, FT_KDP_SIG_KEY_RSP_AUTO, + (VOID *)pEvtKeyReq, sizeof(FT_KDP_EVT_KEY_ELM), + PeerIP, NULL); + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Key Req format incorrect!\n")); + } +#endif /* FT_KDP_EMPTY */ + + return FALSE; +} + + +/* +======================================================================== +Routine Description: + Inform us a AP response the key. + +Arguments: + pAd - WLAN control block pointer + *pInfo - key information + InfoLen - information length + +Return Value: + None + +Note: + pInfo format is PeerIP (4B) + Nonce (8B) + FT_KDP_EVT_KEY_ELM structure +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_KeyResponseToUs( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen) +{ +#ifndef FT_KDP_EMPTY + UINT32 PeerIP, DataLen = 0; + UCHAR *pData; + + FT_KDP_EVT_KEY_ELM *pEvtKeyRsp; + UCHAR *pNonce; + + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } + + /* init */ + IAPP_DAEMON_CMD_PARSE(pInfo, InfoLen, PeerIP, pData, DataLen); + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> DataLen = %d!\n", DataLen)); + + pNonce = pData; + pEvtKeyRsp = (FT_KDP_EVT_KEY_ELM *)(pNonce + FT_NONCE_SIZE); + +#ifdef FT_KDP_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Key Rsp from Peer IP = %d.%d.%d.%d!\n", + IAPP_SHOW_IP_HTONL(PeerIP))); +#endif /* FT_KDP_DEBUG */ + + /* check if the response format is correct */ + if ((pEvtKeyRsp->ElmId == FT_KDP_ELM_ID_PRI) && + (pEvtKeyRsp->OUI[0] == FT_KDP_ELM_PRI_OUI_0) && + (pEvtKeyRsp->OUI[1] == FT_KDP_ELM_PRI_OUI_1) && + (pEvtKeyRsp->OUI[2] == FT_KDP_ELM_PRI_OUI_2)) + { + PFT_R1HK_ENTRY pR1hkEntry; + BOOLEAN bUpdateR1kh = FALSE; + +#ifdef FT_KDP_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Key Rsp: Station MAC = " + "0x%02x:%02x:%02x:%02x:%02x:%02x!\n", + pEvtKeyRsp->MacAddr[0], + pEvtKeyRsp->MacAddr[1], + pEvtKeyRsp->MacAddr[2], + pEvtKeyRsp->MacAddr[3], + pEvtKeyRsp->MacAddr[4], + pEvtKeyRsp->MacAddr[5])); + + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Key Rsp: R1KH-ID = " + "0x%02x:%02x:%02x:%02x:%02x:%02x!\n", + pEvtKeyRsp->KeyInfo.R1KHID[0], + pEvtKeyRsp->KeyInfo.R1KHID[1], + pEvtKeyRsp->KeyInfo.R1KHID[2], + pEvtKeyRsp->KeyInfo.R1KHID[3], + pEvtKeyRsp->KeyInfo.R1KHID[4], + pEvtKeyRsp->KeyInfo.R1KHID[5])); + + DBGPRINT(RT_DEBUG_TRACE, ("MacAddr")); + hex_dump("PMKR1Name", pEvtKeyRsp->PMKR1Name, FT_KDP_WPA_NAME_MAX_SIZE); + hex_dump("R0KH_MAC", pEvtKeyRsp->R0KH_MAC, ETH_ALEN); + hex_dump("AKM Suite", pEvtKeyRsp->AkmSuite, 4); + +#endif /* FT_KDP_DEBUG */ + + /* Upon receiving a new PMK-R1 key for a STA, the target AP shall + delete the prior PMK-R1 SA and PTKSAs derived from the prior + PMK-R1 key */ + pR1hkEntry = FT_R1khEntryTabLookup(pAd, pEvtKeyRsp->PMKR1Name); + if (pR1hkEntry == NULL) + { + bUpdateR1kh = TRUE; + } + if (pR1hkEntry && + RTMPEqualMemory(pR1hkEntry->PmkR1Key, pEvtKeyRsp->PMKR1, LEN_PMK) == FALSE) + { + FT_R1khEntryDelete(pAd, pR1hkEntry); + bUpdateR1kh = TRUE; + } + + if (bUpdateR1kh) + { + MAC_TABLE_ENTRY *pEntry = NULL; + + pEntry = MacTableLookup(pAd, pEvtKeyRsp->MacAddr); + /* assign the PMK-R1 key to FT kernel */ + FT_R1khEntryInsert(pAd, + pEvtKeyRsp->KeyInfo.PMKR0Name, + pEvtKeyRsp->PMKR1Name, + pEvtKeyRsp->PMKR1, + pEvtKeyRsp->PairwisChipher, + pEvtKeyRsp->AkmSuite, + pEvtKeyRsp->KeyLifeTime, + pEvtKeyRsp->ReassocDeadline, + (PUINT8)pEvtKeyRsp->KeyInfo.R0KHID, + pEvtKeyRsp->KeyInfo.R0KHIDLen, + pEvtKeyRsp->MacAddr); + /* YF_FT */ + if (pEntry && ((pEntry->FT_R1kh_CacheMiss_Times > 0) +#ifdef R1KH_HARD_RETRY /* yiwei no give up! */ + || (pEntry->FT_R1kh_CacheMiss_Hard > 0) +#endif /*R1KH_HARD_RETRY */ + )) { + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s - Reset FT_R1kh_CacheMiss_Times to Zero (Wcid%d, value:%d), time=%ld\n", + __func__, pEntry->wcid, pEntry->FT_R1kh_CacheMiss_Times, (jiffies * 1000) / OS_HZ)); + pEntry->FT_R1kh_CacheMiss_Times = 0; +#ifdef R1KH_HARD_RETRY /* yiwei no give up! */ + pEntry->FT_R1kh_CacheMiss_Hard = 0; + RTMP_OS_COMPLETE(&pEntry->ack_r1kh); +#endif /* R1KH_HARD_RETRY */ + } + } + +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD + /* add the R0KH information */ + FT_KDP_R0KH_InfoAdd(pAd, + pEvtKeyRsp->KeyInfo.R0KHID, + pEvtKeyRsp->R0KH_MAC, + PeerIP); +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Key Rsp format incorrect!\n")); + } +#endif /* FT_KDP_EMPTY */ +} + + +/* +======================================================================== +Routine Description: + Inform us a FT station joins the BSS domain. + +Arguments: + pAd - WLAN control block pointer + *pInfo - station information + InfoLen - information length + +Return Value: + None + +Note: + pInfo format is PeerIP (4B) + Station MAC (6B) +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_StationInform( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen) +{ +#ifndef FT_KDP_EMPTY + UINT32 PeerIP, DataLen = 0; + UCHAR *pData; + + FT_KDP_EVT_KEY_ELM EvtKeyReq, *pEvtKeyReq; + UCHAR StaMac[ETH_ALEN]; + UINT32 IdBssNum; + + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } + + /* init */ + IAPP_DAEMON_CMD_PARSE(pInfo, InfoLen, PeerIP, pData, DataLen); + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: DataLen = %d!\n", __FUNCTION__, DataLen)); + +#ifndef FT_KDP_FUNC_TEST + /* check if we are in security mode; if not, return */ + for(IdBssNum=0; IdBssNumApCfg.BssidNum; IdBssNum++) + { + if (pAd->ApCfg.MBSSID[IdBssNum].WepStatus != Ndis802_11WEPDisabled) + break; + } + + if (IdBssNum == pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> All BSS are open mode!\n")); + return; /* all BSS are open mode */ + } +#endif + + NdisMoveMemory(StaMac, pData, ETH_ALEN); + + NdisZeroMemory(&EvtKeyReq, sizeof(FT_KDP_EVT_KEY_ELM)); + pEvtKeyReq = &EvtKeyReq; + +#ifdef FT_KDP_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Station Inform from Peer IP = %d.%d.%d.%d!\n", + IAPP_SHOW_IP_HTONL(PeerIP))); +#endif + + /* make up request content */ + pEvtKeyReq->ElmId = FT_KDP_ELM_ID_PRI; + pEvtKeyReq->ElmLen = FT_KDP_ELM_PRI_LEN; + pEvtKeyReq->OUI[0] = FT_KDP_ELM_PRI_OUI_0; + pEvtKeyReq->OUI[1] = FT_KDP_ELM_PRI_OUI_1; + pEvtKeyReq->OUI[2] = FT_KDP_ELM_PRI_OUI_2; + + NdisMoveMemory(pEvtKeyReq->MacAddr, StaMac, ETH_ALEN); + NdisMoveMemory(pEvtKeyReq->KeyInfo.S1KHID, StaMac, FT_KDP_S1KHID_MAX_SIZE); + + /* request PMK-R1 Key (our R1KH vs. the station) from the R0KH */ +#ifdef FT_KDP_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Send Key Req to Peer IP = %d.%d.%d.%d!\n", + IAPP_SHOW_IP_HTONL(PeerIP))); +#endif /* FT_KDP_DEBUG */ + + for(IdBssNum=0; IdBssNumApCfg.BssidNum; IdBssNum++) + { +#ifndef FT_KDP_FUNC_TEST + if (pAd->ApCfg.MBSSID[IdBssNum].WepStatus != Ndis802_11WEPDisabled) +#endif /* FT_KDP_FUNC_TEST */ + { + /* copy our MAC address to be the R1KHID */ + /* different MAC for different BSS in MBSS mode */ + NdisMoveMemory(pEvtKeyReq->KeyInfo.R1KHID, + pAd->ApCfg.MBSSID[IdBssNum].wdev.bssid, + FT_KDP_R1KHID_MAX_SIZE); + + FT_KDP_EventInform(pAd, IdBssNum, FT_KDP_SIG_KEY_REQ_AUTO, + (VOID *)pEvtKeyReq, sizeof(FT_KDP_EVT_KEY_ELM), + PeerIP, NULL); + } + } +#endif /* FT_KDP_EMPTY */ +} + + +/* +======================================================================== +Routine Description: + Set the encryption/decryption key from daemon or driver. + +Arguments: + pAd - WLAN control block pointer + *pKey - the key + KeyLen - the key length + +Return Value: + None + +Note: + Key length can be 8B ~ 64B. + + We support key set from daemon or driver. + + Only one key for multiple BSS mode. +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_CryptKeySet( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pKey, + IN INT32 KeyLen) +{ +#ifndef FT_KDP_EMPTY + UCHAR KeyMaterial[40]; + + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } + + /* key set */ + if ((KeyLen >= 8) && (KeyLen <= 64)) + { + RtmpPasswordHash((RTMP_STRING *)pKey, + (PUCHAR)FT_KDP_RALINK_PASSPHRASE, + strlen(FT_KDP_RALINK_PASSPHRASE), + KeyMaterial); + } + else + { + RtmpPasswordHash((RTMP_STRING *)FT_KDP_KEY_DEFAULT, + (PUCHAR)FT_KDP_RALINK_PASSPHRASE, + strlen(FT_KDP_RALINK_PASSPHRASE), + KeyMaterial); + } + + /* use the first 16B of KeyMaterial[] */ + NdisMoveMemory(FT_KDP_CB->CryptKey, KeyMaterial, sizeof(KeyMaterial)); +#endif /* FT_KDP_EMPTY */ +} + + +/* +======================================================================== +Routine Description: + Encrypt the data. + +Arguments: + pAd - WLAN control block pointer + *pData - data buffer + *pDataLen - data buffer length + +Return Value: + None + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_DataEncrypt( + IN PRTMP_ADAPTER pAd, + INOUT UCHAR *pData, + IN UINT32 *pDataLen) +{ +#ifndef FT_KDP_EMPTY + UCHAR *pOutputBuf; + UINT OutputLen = 0; + + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } + + /* init */ + FT_MEM_ALLOC(pAd, &pOutputBuf, *pDataLen + FT_KDP_KEY_ENCRYPTION_EXTEND); + if (pOutputBuf == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> Allocate encryption buffer fail!\n")); + return; + } + NdisZeroMemory(pOutputBuf, *pDataLen + FT_KDP_KEY_ENCRYPTION_EXTEND); + + /* encrypt */ + AES_Key_Wrap(pData, *pDataLen, FT_KDP_CB->CryptKey, 16, + pOutputBuf, &OutputLen); + *pDataLen = OutputLen; + + NdisMoveMemory(pData, pOutputBuf, *pDataLen); + + FT_MEM_FREE(pAd, pOutputBuf); +#endif /* FT_KDP_EMPTY */ +} + + +/* +======================================================================== +Routine Description: + Decrypt the data. + +Arguments: + pAd - WLAN control block pointer + *pData - data buffer + *pDataLen - data buffer length + +Return Value: + None + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_DataDecrypt( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pData, + IN UINT32 *pDataLen) +{ +#ifndef FT_KDP_EMPTY + UCHAR *pOutputBuf; + UINT OutputLen = 0; + + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } + + if ((*pDataLen) <= FT_KDP_KEY_ENCRYPTION_EXTEND) + { + DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd>Decryption length is too small!\n")); + return; + } + + /* init */ + FT_MEM_ALLOC(pAd, &pOutputBuf, *pDataLen); + if (pOutputBuf == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> Allocate decryption buffer fail!\n")); + return; + } + + /* decrypt */ + AES_Key_Unwrap(pData, *pDataLen, + FT_KDP_CB->CryptKey, 16, + pOutputBuf, &OutputLen); + *pDataLen = OutputLen; + + NdisMoveMemory(pData, pOutputBuf, *pDataLen); + + FT_MEM_FREE(pAd, pOutputBuf); +#endif /* FT_KDP_EMPTY */ +} + + +/* private function */ +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD +/* +======================================================================== +Routine Description: + Add a R0KH Information. + +Arguments: + pAd - WLAN control block pointer + *pR0KHID - R0KH ID + *pMAC - R0KH MAC + IP - R0KH IP + +Return Value: + None + +Note: +======================================================================== +*/ +BOOLEAN TYPE_FUNC FT_KDP_R0KH_InfoAdd( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pR0KHID, + IN UCHAR *pMAC, + IN UINT32 IP) +{ +#ifndef FT_KDP_EMPTY + FT_KDP_R0KH_INFO *pInfo; + BOOLEAN FlgIsSameRecordFound; + + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return FALSE; + } + + /* sanity check for maximum size */ + if (FT_KDP_CB->R0KH_Size >= FT_KDP_R0KH_INFO_MAX_SIZE) + { + /* delete oldest record first */ + FT_KDP_R0KH_InfoDel(pAd, NULL, NULL, 0); + } + + RTMP_SEM_LOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + + /* sanity check if same information exists */ + FlgIsSameRecordFound = FALSE; + pInfo = FT_KDP_CB->R0KH_InfoHead; + + while(pInfo != NULL) + { + if ((NdisEqualMemory(pInfo->R0KHID, pR0KHID, sizeof(pInfo->R0KHID))) || + (NdisEqualMemory(pInfo->MAC, pMAC, sizeof(pInfo->MAC))) || + (pInfo->IP == IP)) + { + /* need to update the new information to the entry */ + FlgIsSameRecordFound = TRUE; + break; + } + + pInfo = pInfo->pNext; + } + + /* init or update */ + if (FlgIsSameRecordFound == FALSE) + { + /* allocate a new record */ + FT_MEM_ALLOC(pAd, &pInfo, sizeof(FT_KDP_R0KH_INFO)); + if (pInfo == NULL) + { + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> Allocate R0KH INFO fail!\n")); + return FALSE; + } + + pInfo->pNext = NULL; + } + + /* update other R0KH device information */ + NdisMoveMemory(pInfo->R0KHID, pR0KHID, sizeof(pInfo->R0KHID)); + NdisMoveMemory(pInfo->MAC, pMAC, sizeof(pInfo->MAC)); + pInfo->IP = IP; + NdisGetSystemUpTime(&pInfo->TimeUpdate); + + /* append the new information to the information list */ + if (FlgIsSameRecordFound == FALSE) + { + if (FT_KDP_CB->R0KH_InfoTail == NULL) + { + FT_KDP_CB->R0KH_InfoHead = pInfo; + FT_KDP_CB->R0KH_InfoTail = pInfo; + } + else + { + (FT_KDP_CB->R0KH_InfoTail)->pNext = pInfo; + FT_KDP_CB->R0KH_InfoTail = pInfo; + } + + FT_KDP_CB->R0KH_Size ++; + } + + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); +#endif /* FT_KDP_EMPTY */ + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Delete a R0KH Information. + +Arguments: + pAd - WLAN control block pointer + *pR0KHID - R0KH ID + *pMAC - R0KH MAC + IP - R0KH IP + +Return Value: + None + +Note: + If pR0KHID == NULL, pMAC == NULL, and IP = 0, means deleting the oldest. +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_R0KH_InfoDel( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pR0KHID, + IN UCHAR *pMAC, + IN UINT32 IP) +{ +#ifndef FT_KDP_EMPTY + FT_KDP_R0KH_INFO *pInfo; + FT_KDP_R0KH_INFO *pInfoBackup, *pInfoDelPrev, *pInfoDel; + ULONG TimeOldest; + + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } + + /* init */ + pInfoDelPrev = NULL; + pInfoDel = NULL; + TimeOldest = 0xFFFFFFFF; + + RTMP_SEM_LOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + + /* try to find the one expected to delete */ + pInfo = FT_KDP_CB->R0KH_InfoHead; + if (pInfo == NULL) + { + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + return; + } + + pInfoBackup = pInfo; + + while(pInfo != NULL) + { + if ((pR0KHID == NULL) && (pMAC == NULL) && (IP == 0)) + { + /* check if the info is the oldest one */ + if (pInfo->TimeUpdate < TimeOldest) + { + TimeOldest = pInfo->TimeUpdate; + + pInfoDelPrev = pInfoBackup; + pInfoDel = pInfo; + } + } + else + { + /* check if the info is the one expected to delete */ + if ((pR0KHID != NULL) && + (NdisEqualMemory(pR0KHID, pInfo->R0KHID, sizeof(pInfo->R0KHID)))) + { + pInfoDelPrev = pInfoBackup; + pInfoDel = pInfo; + break; + } + + if ((pMAC != NULL) && + (NdisEqualMemory(pMAC, pInfo->MAC, sizeof(pInfo->MAC)))) + { + pInfoDelPrev = pInfoBackup; + pInfoDel = pInfo; + break; + } + + if (IP == pInfo->IP) + { + pInfoDelPrev = pInfoBackup; + pInfoDel = pInfo; + break; + } + } + + /* check next one */ + pInfoBackup = pInfo; + pInfo = pInfo->pNext; + } + + /* delete the information record */ + if (pInfoDel != NULL) + { + FT_KDP_CB->R0KH_Size --; + + if (FT_KDP_CB->R0KH_Size == 0) + { + /* list is empty */ + FT_KDP_CB->R0KH_InfoHead = NULL; + FT_KDP_CB->R0KH_InfoTail = NULL; + } + else + { + if (pInfoDelPrev == pInfoDel) + { + /* must be the head one */ + FT_KDP_CB->R0KH_InfoHead = pInfoDel->pNext; + } + else + { + /* must not be the head one */ + pInfoDelPrev->pNext = pInfoDel->pNext; + } + } + } + else + { + /* sorry! can not find the one in the list */ + } + + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + + /* free the one */ + if (pInfoDel != NULL) + FT_MEM_FREE(pAd, pInfoDel); + +#endif /* FT_KDP_EMPTY */ +} + + +/* +======================================================================== +Routine Description: + Get the IP of R0KH by R0KHID or MAC. + +Arguments: + pAd - WLAN control block pointer + *pR0KHID - R0KH ID + *pMAC - R0KH MAC + pIP - R0KH IP + +Return Value: + TRUE - get ok + FALSE - get fail + +Note: +======================================================================== +*/ +static BOOLEAN TYPE_FUNC FT_KDP_R0KH_InfoGet( + IN PRTMP_ADAPTER pAd, + INOUT UCHAR *pR0KHID, + INOUT UCHAR *pMAC, + OUT UINT32 *pIP) +{ +#ifndef FT_KDP_EMPTY + FT_KDP_R0KH_INFO *pInfo; + + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return FALSE; + } + + RTMP_SEM_LOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + + pInfo = FT_KDP_CB->R0KH_InfoHead; + + while(pInfo != NULL) + { + /* check if the info is the one expected to get */ + if ((pR0KHID != NULL) && + (NdisEqualMemory(pR0KHID, pInfo->R0KHID, sizeof(pInfo->R0KHID)))) + { + *pIP = pInfo->IP; + goto LabelOk; + } + + if ((pMAC != NULL) && + (NdisEqualMemory(pMAC, pInfo->MAC, sizeof(pInfo->MAC)))) + { + *pIP = pInfo->IP; + goto LabelOk; + } + + /* check next one */ + pInfo = pInfo->pNext; + } + + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + return FALSE; + +LabelOk: + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + return TRUE; +#else + + return FALSE; +#endif /* FT_KDP_EMPTY */ +} +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + + +/* +======================================================================== +Routine Description: + Broadcast our AP information. + +Arguments: + SystemSpecific1 - no use + FunctionContext - WLAN control block pointer + SystemSpecific2 - no use + SystemSpecific3 - no use + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_InfoBroadcast( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ +#ifndef FT_KDP_EMPTY +#ifdef FT_KDP_FUNC_INFO_BROADCAST + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; + UINT32 IdBssNum; + + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } + + /* get my neighbor report element information */ + /* yet implement */ + + for(IdBssNum=0; IdBssNumApCfg.BssidNum; IdBssNum++) + { + /* PeerIP = 0 means destination MAC = 0xFF FF FF FF FF FF */ + FT_KDP_EventInform(pAd, IdBssNum, FT_KDP_SIG_INFO_BROADCAST, + "test", 4, 0, NULL); + } +#endif /* FT_KDP_FUNC_INFO_BROADCAST */ +#endif /* FT_KDP_EMPTY */ +} + + +#ifdef FT_KDP_FUNC_INFO_BROADCAST +/* +======================================================================== +Routine Description: + Receive a neighbor report from another AP. + +Arguments: + pAd - WLAN control block pointer + *pInfo - report information + InfoLen - information length + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_NeighborReportHandle( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen) +{ +#ifndef FT_KDP_EMPTY + UINT32 PeerIP, DataLen; + UCHAR *pData; + UINT32 IdBssNum; + + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } + + /* init */ + IAPP_DAEMON_CMD_PARSE(pInfo, InfoLen, PeerIP, pData, DataLen); + +#ifdef FT_KDP_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Neighbor Report from Peer IP = %d.%d.%d.%d!\n", + IAPP_SHOW_IP_HTONL(PeerIP))); +#endif /* FT_KDP_DEBUG */ + + /* yet implememnt */ + +#endif /* FT_KDP_EMPTY */ +} +#endif /* FT_KDP_FUNC_INFO_BROADCAST */ + + +/* +======================================================================== +Routine Description: + Receive a neighbor request from another AP. + +Arguments: + pAd - WLAN control block pointer + *pInfo - report information + InfoLen - information length + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_NeighborRequestHandle( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen) +{ +#ifndef FT_KDP_EMPTY + UINT32 PeerIP, DataLen = 0; + UCHAR *pData; + UINT16 SsidLen; + RTMP_STRING *pSSID; + + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } + + /* init */ + IAPP_DAEMON_CMD_PARSE(pInfo, InfoLen, PeerIP, pData, DataLen); + + SsidLen = DataLen; + pSSID = (RTMP_STRING *)pData; + pSSID[SsidLen] = 0x00; + +#ifdef FT_KDP_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Neighbor Request from Peer IP = %d.%d.%d.%d, SSID = %s\n", + IAPP_SHOW_IP_HTONL(PeerIP), pSSID)); +#endif /* FT_KDP_DEBUG */ + + /* check if the requested SSID is for us */ + + /* 11k yet implememnt */ +/* 11K_ApInfoGet(&ApInfo); */ + + /* reponse the neighbor request to the AP */ +/* FT_KDP_EventInform(pAd, IdBssNum, FT_KDP_SIG_AP_INFO_RSP, */ +/* &ApInfo, sizeof(ApInfo), PeerIP, NULL); */ +#endif /* FT_KDP_EMPTY */ +} + + +/* +======================================================================== +Routine Description: + Receive a neighbor response from another AP. + +Arguments: + pAd - WLAN control block pointer + *pInfo - report information + InfoLen - information length + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_NeighborResponseHandle( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen) +{ +#ifndef FT_KDP_EMPTY + UINT32 PeerIP, DataLen = 0; + UCHAR *pData = NULL; + + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } + + /* init */ + IAPP_DAEMON_CMD_PARSE(pInfo, InfoLen, PeerIP, pData, DataLen); + + if (pData == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: pData is NULL????? (DataLen=%d)\n", __FUNCTION__, DataLen)); + return; + } +#ifdef FT_KDP_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("ap_ftkd> Neighbor Response from Peer IP = %d.%d.%d.%d\n", + IAPP_SHOW_IP_HTONL(PeerIP))); +#endif /* FT_KDP_DEBUG */ + + /* 11k yet implememnt */ +/* 11K_ResponseHandle(pData, DataLen); */ +#endif /* FT_KDP_EMPTY */ +} + + +/* +======================================================================== +Routine Description: + Handle a RRB frame from DS. + +Arguments: + pAd - WLAN control block pointer + *pInfo - report information + InfoLen - information length + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_RRB_ActionHandle( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen) +{ +#ifndef FT_KDP_EMPTY + if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); + return; + } + + /* handle it */ + FT_RrbHandler(pAd, pInfo, InfoLen); +#endif /* FT_KDP_EMPTY */ +} + +#endif /* DOT11R_FT_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_ids.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_ids.c new file mode 100644 index 000000000..a53178e61 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_ids.c @@ -0,0 +1,481 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + ap_ids.c + + Abstract: + monitor intrusion detection condition + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + */ +#ifdef IDS_SUPPORT + +#include "rt_config.h" + +#define IDS_EXEC_INTV 1000 /* 1 sec */ + + +VOID RTMPIdsStart( + IN PRTMP_ADAPTER pAd) +{ + + if (pAd->ApCfg.IDSTimerRunning == FALSE) + { + RTMPSetTimer(&pAd->ApCfg.IDSTimer, IDS_EXEC_INTV); + pAd->ApCfg.IDSTimerRunning = TRUE; + } +} + +VOID RTMPIdsStop( + IN PRTMP_ADAPTER pAd) +{ + BOOLEAN Cancelled; + + if (pAd->ApCfg.IDSTimerRunning == TRUE) + { + RTMPCancelTimer(&pAd->ApCfg.IDSTimer, &Cancelled); + pAd->ApCfg.IDSTimerRunning = FALSE; + } +} + +#ifdef SYSTEM_LOG_SUPPORT +VOID RTMPHandleIdsEvent( + IN PRTMP_ADAPTER pAd) +{ + INT i, j; + + UINT32 FloodFrameCount[IW_FLOOD_EVENT_TYPE_NUM]; + UINT32 FloodFrameThreshold[IW_FLOOD_EVENT_TYPE_NUM]; + + FloodFrameCount[0] = pAd->ApCfg.RcvdAuthCount; + FloodFrameCount[1] = pAd->ApCfg.RcvdAssocReqCount; + FloodFrameCount[2] = pAd->ApCfg.RcvdReassocReqCount; + FloodFrameCount[3] = pAd->ApCfg.RcvdProbeReqCount; + FloodFrameCount[4] = pAd->ApCfg.RcvdDisassocCount; + FloodFrameCount[5] = pAd->ApCfg.RcvdDeauthCount; + FloodFrameCount[6] = pAd->ApCfg.RcvdEapReqCount; + + FloodFrameThreshold[0] = pAd->ApCfg.AuthFloodThreshold; + FloodFrameThreshold[1] = pAd->ApCfg.AssocReqFloodThreshold; + FloodFrameThreshold[2] = pAd->ApCfg.ReassocReqFloodThreshold; + FloodFrameThreshold[3] = pAd->ApCfg.ProbeReqFloodThreshold; + FloodFrameThreshold[4] = pAd->ApCfg.DisassocFloodThreshold; + FloodFrameThreshold[5] = pAd->ApCfg.DeauthFloodThreshold; + FloodFrameThreshold[6] = pAd->ApCfg.EapReqFloodThreshold; + + /* trigger flooding traffic event */ + for (j = 0; j < IW_FLOOD_EVENT_TYPE_NUM; j++) + { + if ((FloodFrameThreshold[j] > 0) && (FloodFrameCount[j] > FloodFrameThreshold[j])) + { + RTMPSendWirelessEvent(pAd, IW_FLOOD_AUTH_EVENT_FLAG + j, NULL, MAX_MBSSID_NUM(pAd), 0); + /*DBGPRINT(RT_DEBUG_TRACE, ("flooding traffic event(%d) - %d\n", IW_FLOOD_AUTH_EVENT_FLAG + j, FloodFrameCount[j])); */ + } + } + + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + UINT32 SpoofedFrameCount[IW_SPOOF_EVENT_TYPE_NUM]; + CHAR RssiOfSpoofedFrame[IW_SPOOF_EVENT_TYPE_NUM]; + INT k; + + SpoofedFrameCount[0] = pAd->ApCfg.MBSSID[i].RcvdConflictSsidCount; + SpoofedFrameCount[1] = pAd->ApCfg.MBSSID[i].RcvdSpoofedAssocRespCount; + SpoofedFrameCount[2] = pAd->ApCfg.MBSSID[i].RcvdSpoofedReassocRespCount; + SpoofedFrameCount[3] = pAd->ApCfg.MBSSID[i].RcvdSpoofedProbeRespCount; + SpoofedFrameCount[4] = pAd->ApCfg.MBSSID[i].RcvdSpoofedBeaconCount; + SpoofedFrameCount[5] = pAd->ApCfg.MBSSID[i].RcvdSpoofedDisassocCount; + SpoofedFrameCount[6] = pAd->ApCfg.MBSSID[i].RcvdSpoofedAuthCount; + SpoofedFrameCount[7] = pAd->ApCfg.MBSSID[i].RcvdSpoofedDeauthCount; + SpoofedFrameCount[8] = pAd->ApCfg.MBSSID[i].RcvdSpoofedUnknownMgmtCount; + SpoofedFrameCount[9] = pAd->ApCfg.MBSSID[i].RcvdReplayAttackCount; + + RssiOfSpoofedFrame[0] = pAd->ApCfg.MBSSID[i].RssiOfRcvdConflictSsid; + RssiOfSpoofedFrame[1] = pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedAssocResp; + RssiOfSpoofedFrame[2] = pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedReassocResp; + RssiOfSpoofedFrame[3] = pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedProbeResp; + RssiOfSpoofedFrame[4] = pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedBeacon; + RssiOfSpoofedFrame[5] = pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedDisassoc; + RssiOfSpoofedFrame[6] = pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedAuth; + RssiOfSpoofedFrame[7] = pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedDeauth; + RssiOfSpoofedFrame[8] = pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedUnknownMgmt; + RssiOfSpoofedFrame[9] = pAd->ApCfg.MBSSID[i].RssiOfRcvdReplayAttack; + + /* trigger spoofed attack event */ + for (k = 0; k < IW_SPOOF_EVENT_TYPE_NUM; k++) + { + if (SpoofedFrameCount[k] > 0) + { + RTMPSendWirelessEvent(pAd, IW_CONFLICT_SSID_EVENT_FLAG + k, NULL, i, RssiOfSpoofedFrame[k]); + /*DBGPRINT(RT_DEBUG_TRACE, ("spoofed attack event(%d) - %d\n", IW_CONFLICT_SSID_EVENT_FLAG + k, SpoofedFrameCount[k])); */ + } + } + } + +} +#endif /* SYSTEM_LOG_SUPPORT */ + +VOID RTMPClearAllIdsCounter( + IN PRTMP_ADAPTER pAd) +{ + INT i; + + pAd->ApCfg.RcvdAuthCount = 0; + pAd->ApCfg.RcvdAssocReqCount = 0; + pAd->ApCfg.RcvdReassocReqCount = 0; + pAd->ApCfg.RcvdProbeReqCount = 0; + pAd->ApCfg.RcvdDisassocCount = 0; + pAd->ApCfg.RcvdDeauthCount = 0; + pAd->ApCfg.RcvdEapReqCount = 0; + pAd->ApCfg.RcvdMaliciousDataCount = 0; + + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + pAd->ApCfg.MBSSID[i].RcvdConflictSsidCount = 0; + pAd->ApCfg.MBSSID[i].RcvdSpoofedAssocRespCount = 0; + pAd->ApCfg.MBSSID[i].RcvdSpoofedReassocRespCount = 0; + pAd->ApCfg.MBSSID[i].RcvdSpoofedProbeRespCount = 0; + pAd->ApCfg.MBSSID[i].RcvdSpoofedBeaconCount = 0; + pAd->ApCfg.MBSSID[i].RcvdSpoofedDisassocCount = 0; + pAd->ApCfg.MBSSID[i].RcvdSpoofedAuthCount = 0; + pAd->ApCfg.MBSSID[i].RcvdSpoofedDeauthCount = 0; + pAd->ApCfg.MBSSID[i].RcvdSpoofedUnknownMgmtCount = 0; + pAd->ApCfg.MBSSID[i].RcvdReplayAttackCount = 0; + + pAd->ApCfg.MBSSID[i].RssiOfRcvdConflictSsid = 0; + pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedAssocResp = 0; + pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedReassocResp = 0; + pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedProbeResp = 0; + pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedBeacon = 0; + pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedDisassoc = 0; + pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedAuth = 0; + pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedDeauth = 0; + pAd->ApCfg.MBSSID[i].RssiOfRcvdSpoofedUnknownMgmt = 0; + pAd->ApCfg.MBSSID[i].RssiOfRcvdReplayAttack = 0; + + } +} + +VOID RTMPIdsPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; + + pAd->ApCfg.IDSTimerRunning = FALSE; + +#ifdef SYSTEM_LOG_SUPPORT + /* when IDS occured, send out wireless event */ + if (pAd->CommonCfg.bWirelessEvent) + RTMPHandleIdsEvent(pAd); +#endif /* SYSTEM_LOG_SUPPORT */ + + /* clear all IDS counter */ + RTMPClearAllIdsCounter(pAd); + + /* set timer */ + if (pAd->ApCfg.IdsEnable) + { + RTMPSetTimer(&pAd->ApCfg.IDSTimer, IDS_EXEC_INTV); + pAd->ApCfg.IDSTimerRunning = TRUE; + } +} + + +/* + ======================================================================== + Routine Description: + This routine is used to check if a rogue AP sent an 802.11 management + frame to a client using our BSSID. + + Arguments: + pAd - Pointer to our adapter + pHeader - Pointer to 802.11 header + + Return Value: + TRUE - This is a spoofed frame + FALSE - This isn't a spoofed frame + + ======================================================================== +*/ +BOOLEAN RTMPSpoofedMgmtDetection( + IN RTMP_ADAPTER *pAd, + IN HEADER_802_11 *pHeader, + IN RX_BLK *rxblk) +{ + INT i; + + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + /* Spoofed BSSID detection */ + if (NdisEqualMemory(pHeader->Addr2, pAd->ApCfg.MBSSID[i].wdev.bssid, MAC_ADDR_LEN)) + { + CHAR RcvdRssi; + struct raw_rssi_info rssi_info; + + rssi_info.raw_rssi[0] = rxblk->rx_signal.raw_rssi[0]; + rssi_info.raw_rssi[1] = rxblk->rx_signal.raw_rssi[1]; + rssi_info.raw_rssi[2] = rxblk->rx_signal.raw_rssi[2]; + RcvdRssi = RTMPMaxRssi(pAd, + ConvertToRssi(pAd, &rssi_info, RSSI_IDX_0), + ConvertToRssi(pAd, &rssi_info, RSSI_IDX_1), + ConvertToRssi(pAd, &rssi_info, RSSI_IDX_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; + struct raw_rssi_info rssi_info; + + rssi_info.raw_rssi[0] = Rssi0; + rssi_info.raw_rssi[1] = Rssi1; + rssi_info.raw_rssi[2] = Rssi2; + + RcvdRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, &rssi_info, RSSI_IDX_0), + ConvertToRssi(pAd, &rssi_info, RSSI_IDX_1), + ConvertToRssi(pAd, &rssi_info, RSSI_IDX_2)); + + pAd->ApCfg.MBSSID[i].RcvdConflictSsidCount ++; + pAd->ApCfg.MBSSID[i].RssiOfRcvdConflictSsid = RcvdRssi; + return; + } + } +} + + +BOOLEAN RTMPReplayAttackDetection( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr2, + IN RX_BLK *rxblk) +{ + INT i; + + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + /* Conflict SSID detection */ + if (NdisEqualMemory(pAddr2, pAd->ApCfg.MBSSID[i].wdev.bssid, MAC_ADDR_LEN)) + { + CHAR RcvdRssi; + struct raw_rssi_info rssi_info; + + rssi_info.raw_rssi[0] = rxblk->rx_signal.raw_rssi[0]; + rssi_info.raw_rssi[1] = rxblk->rx_signal.raw_rssi[1]; + rssi_info.raw_rssi[2] = rxblk->rx_signal.raw_rssi[2]; + + RcvdRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, &rssi_info, RSSI_IDX_0), + ConvertToRssi(pAd, &rssi_info, RSSI_IDX_1), + ConvertToRssi(pAd, &rssi_info, RSSI_IDX_2)); + + pAd->ApCfg.MBSSID[i].RcvdReplayAttackCount ++; + pAd->ApCfg.MBSSID[i].RssiOfRcvdReplayAttack = RcvdRssi; + return TRUE; + } + } + return FALSE; +} + +VOID RTMPUpdateStaMgmtCounter(RTMP_ADAPTER *pAd, USHORT type) +{ + switch (type) + { + case SUBTYPE_ASSOC_REQ: + pAd->ApCfg.RcvdAssocReqCount ++; + break; + + case SUBTYPE_REASSOC_REQ: + pAd->ApCfg.RcvdReassocReqCount ++; + break; + + case SUBTYPE_PROBE_REQ: + pAd->ApCfg.RcvdProbeReqCount ++; + break; + + case SUBTYPE_DISASSOC: + pAd->ApCfg.RcvdDisassocCount ++; + break; + + case SUBTYPE_DEAUTH: + pAd->ApCfg.RcvdDeauthCount ++; + break; + + case SUBTYPE_AUTH: + pAd->ApCfg.RcvdAuthCount ++; + break; + } + + /* + DBGPRINT(RT_DEBUG_TRACE, ("RcvdAssocReqCount=%d\n", pAd->ApCfg.RcvdAssocReqCount)); + DBGPRINT(RT_DEBUG_TRACE, ("RcvdReassocReqCount=%d\n", pAd->ApCfg.RcvdReassocReqCount)); + DBGPRINT(RT_DEBUG_TRACE, ("RcvdProbeReqCount=%d\n", pAd->ApCfg.RcvdProbeReqCount)); + DBGPRINT(RT_DEBUG_TRACE, ("RcvdDisassocCount=%d\n", pAd->ApCfg.RcvdDisassocCount)); + DBGPRINT(RT_DEBUG_TRACE, ("RcvdDeauthCount=%d\n", pAd->ApCfg.RcvdDeauthCount)); + DBGPRINT(RT_DEBUG_TRACE, ("RcvdAuthCount=%d\n", pAd->ApCfg.RcvdAuthCount)); + */ + +} + +VOID rtmp_read_ids_from_file( + IN PRTMP_ADAPTER pAd, + RTMP_STRING *tmpbuf, + RTMP_STRING *buffer) +{ + /*IdsEnable */ + if(RTMPGetKeyParameter("IdsEnable", tmpbuf, 10, buffer, TRUE)) + { + if (simple_strtol(tmpbuf, 0, 10) == 1) + pAd->ApCfg.IdsEnable = TRUE; + else + pAd->ApCfg.IdsEnable = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("IDS is %s\n", pAd->ApCfg.IdsEnable ? "enabled" : "disabled")); + } + + /*AuthFloodThreshold */ + if(RTMPGetKeyParameter("AuthFloodThreshold", tmpbuf, 10, buffer, TRUE)) + { + pAd->ApCfg.AuthFloodThreshold = simple_strtol(tmpbuf, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("AuthFloodThreshold = %d\n", pAd->ApCfg.AuthFloodThreshold)); + } + + /*AssocReqFloodThreshold */ + if(RTMPGetKeyParameter("AssocReqFloodThreshold", tmpbuf, 10, buffer, TRUE)) + { + pAd->ApCfg.AssocReqFloodThreshold = simple_strtol(tmpbuf, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("AssocReqFloodThreshold = %d\n", pAd->ApCfg.AssocReqFloodThreshold)); + } + + /*ReassocReqFloodThreshold */ + if(RTMPGetKeyParameter("ReassocReqFloodThreshold", tmpbuf, 10, buffer, TRUE)) + { + pAd->ApCfg.ReassocReqFloodThreshold = simple_strtol(tmpbuf, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("ReassocReqFloodThreshold = %d\n", pAd->ApCfg.ReassocReqFloodThreshold)); + } + + /*ProbeReqFloodThreshold */ + if(RTMPGetKeyParameter("ProbeReqFloodThreshold", tmpbuf, 10, buffer, TRUE)) + { + pAd->ApCfg.ProbeReqFloodThreshold = simple_strtol(tmpbuf, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("ProbeReqFloodThreshold = %d\n", pAd->ApCfg.ProbeReqFloodThreshold)); + } + + /*DisassocFloodThreshold */ + if(RTMPGetKeyParameter("DisassocFloodThreshold", tmpbuf, 10, buffer, TRUE)) + { + pAd->ApCfg.DisassocFloodThreshold = simple_strtol(tmpbuf, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("DisassocFloodThreshold = %d\n", pAd->ApCfg.DisassocFloodThreshold)); + } + + /*DeauthFloodThreshold */ + if(RTMPGetKeyParameter("DeauthFloodThreshold", tmpbuf, 10, buffer, TRUE)) + { + pAd->ApCfg.DeauthFloodThreshold = simple_strtol(tmpbuf, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("DeauthFloodThreshold = %d\n", pAd->ApCfg.DeauthFloodThreshold)); + } + + /*EapReqFloodThreshold */ + if(RTMPGetKeyParameter("EapReqFloodThreshold", tmpbuf, 10, buffer, TRUE)) + { + pAd->ApCfg.EapReqFloodThreshold = simple_strtol(tmpbuf, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("EapReqFloodThreshold = %d\n", pAd->ApCfg.EapReqFloodThreshold)); + } + + /* DataFloodThreshold */ + if(RTMPGetKeyParameter("DataFloodThreshold", tmpbuf, 10, buffer, TRUE)) + { + pAd->ApCfg.DataFloodThreshold = simple_strtol(tmpbuf, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("DataFloodThreshold = %d\n", pAd->ApCfg.DataFloodThreshold)); + } +} + +#endif /* IDS_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_mbss.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_mbss.c new file mode 100644 index 000000000..92d3b01b7 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_mbss.c @@ -0,0 +1,454 @@ +/**************************************************************************** + * 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 + + 4. BSS Index (0 ~ 15) of different tx packet is assigned in + + 5. BSS Index (0 ~ 15) of different BSS is got in APHardTransmit() by using + + 6. BSS Index (0 ~ 15) of IOCTL command is put in pAd->OS_Cookie->ioctl_if + + 7. Beacon of different BSS is enabled in APMakeAllBssBeacon() by writing 1 + to the register MAC_BSSID_DW1 + + 8. The number of MBSS can be 1, 2, 4, or 8 + +***************************************************************************/ +#ifdef MBSS_SUPPORT + + +#include "rt_config.h" + + +/* --------------------------------- Public -------------------------------- */ +/* +======================================================================== +Routine Description: + Initialize Multi-BSS function. + +Arguments: + pAd points to our adapter + pDevMain points to the main BSS network interface + +Return Value: + None + +Note: + 1. Only create and initialize virtual network interfaces. + 2. No main network interface here. + 3. If you down ra0 and modify the BssNum of RT2860AP.dat/RT2870AP.dat, + it will not work! You must rmmod rt2860ap.ko and lsmod rt2860ap.ko again. +======================================================================== +*/ +VOID MBSS_Init(RTMP_ADAPTER *pAd, RTMP_OS_NETDEV_OP_HOOK *pNetDevOps) +{ +#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; + + + MaxNumBss = pAd->ApCfg.BssidNum; + if (MaxNumBss > MAX_MBSSID_NUM(pAd)) + MaxNumBss = MAX_MBSSID_NUM(pAd); + + /* first IdBss must not be 0 (BSS0), must be 1 (BSS1) */ + for(IdBss=FIRST_MBSSID; IdBssApCfg.MBSSID[IdBss].wdev.if_dev = NULL; + + /* create virtual network interface */ + for(IdBss=FIRST_MBSSID; IdBssMC_RowID; +#endif /* MULTIPLE_CARD_SUPPORT */ +#ifdef HOSTAPD_SUPPORT + IoctlIF = pAd->IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + BSS_STRUCT *pMbss; + + dev_name = get_dev_name_prefix(pAd, INT_MBSSID); + pDevNew = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, INT_MBSSID, IdBss, sizeof(struct mt_dev_priv), dev_name); +#ifdef HOSTAPD_SUPPORT + pAd->IoctlIF = IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + if (pDevNew == NULL) + { + pAd->ApCfg.BssidNum = IdBss; /* re-assign new MBSS number */ + break; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Register MBSSID IF (%s)\n", RTMP_OS_NETDEV_GET_DEVNAME(pDevNew))); + } + + pMbss = &pAd->ApCfg.MBSSID[IdBss]; + wdev = &pAd->ApCfg.MBSSID[IdBss].wdev; + wdev->wdev_type = WDEV_TYPE_AP; + wdev->func_dev = &pAd->ApCfg.MBSSID[IdBss]; + wdev->func_idx = IdBss; + wdev->sys_handle = (void *)pAd; + wdev->if_dev = pDevNew; + if (rtmp_wdev_idx_reg(pAd, wdev) < 0) { + DBGPRINT(RT_DEBUG_ERROR, ("Assign wdev idx for %s failed, free net device!\n", + RTMP_OS_NETDEV_GET_DEVNAME(pDevNew))); + RtmpOSNetDevFree(pDevNew); + break; + } + wdev->tx_pkt_allowed = ApAllowToSendPacket; + wdev->tx_pkt_handle = APSendPacket; + wdev->wdev_hard_tx = APHardTransmit; + + wdev->rx_pkt_allowed = ap_rx_pkt_allow; + wdev->rx_ps_handle = ap_rx_ps_handle; + wdev->rx_pkt_foward = ap_rx_foward_handle; + + RTMP_OS_NETDEV_SET_PRIV(pDevNew, pAd); + RTMP_OS_NETDEV_SET_WDEV(pDevNew, wdev); + + /* init operation functions and flags */ + NdisCopyMemory(&netDevHook, pNetDevOps, sizeof(netDevHook)); + + netDevHook.priv_flags = INT_MBSSID; + netDevHook.needProtcted = TRUE; + netDevHook.wdev = wdev; + + /* Init MAC address of virtual network interface */ + NdisMoveMemory(&netDevHook.devAddr[0], &wdev->bssid[0], MAC_ADDR_LEN); + + /* register this device to OS */ + /*status =*/ RtmpOSNetDevAttach(pAd->OpMode, pDevNew, &netDevHook); + ASSERT(pMbss); + if (pMbss) { + wdev_bcn_buf_init(pAd, &pMbss->bcn_buf); + } else { + DBGPRINT(RT_DEBUG_ERROR, ("%s():func_dev is NULL!\n", __FUNCTION__)); + return; + } + } + + pAd->FlgMbssInit = TRUE; + +} + + +/* +======================================================================== +Routine Description: + Remove Multi-BSS network interface. + +Arguments: + pAd points to our adapter + +Return Value: + None + +Note: + FIRST_MBSSID = 1 + Main BSS is not removed here. +======================================================================== +*/ +VOID MBSS_Remove(RTMP_ADAPTER *pAd) +{ + struct wifi_dev *wdev; + UINT IdBss; + BSS_STRUCT *pMbss; + + + + for(IdBss=FIRST_MBSSID; IdBssApCfg.MBSSID[IdBss].wdev; + pMbss = &pAd->ApCfg.MBSSID[IdBss]; + if (pMbss) { + wdev_bcn_buf_deinit(pAd, &pMbss->bcn_buf); + } + if (wdev->if_dev) + { + RtmpOSNetDevProtect(1); + RtmpOSNetDevDetach(wdev->if_dev); + RtmpOSNetDevProtect(0); + rtmp_wdev_idx_unreg(pAd, wdev); + RtmpOSNetDevFree(wdev->if_dev); + wdev->if_dev = NULL; + } + } +} + + +/* +======================================================================== +Routine Description: + Get multiple bss idx. + +Arguments: + pAd points to our adapter + pDev which WLAN network interface + +Return Value: + 0: close successfully + otherwise: close fail + +Note: +======================================================================== +*/ +INT32 RT28xx_MBSS_IdxGet(RTMP_ADAPTER *pAd, PNET_DEV pDev) +{ + INT32 BssId = -1; + INT32 IdBss; + + + for(IdBss=0; IdBssApCfg.BssidNum; IdBss++) + { + if (pAd->ApCfg.MBSSID[IdBss].wdev.if_dev == pDev) + { + BssId = IdBss; + break; + } + } + + return BssId; +} + +#ifdef MT_MAC +INT32 mbss_cr_enable(PNET_DEV pDev) +{ + PRTMP_ADAPTER pAd; + INT BssId; + UINT32 Value = 0; + //register for sub Bssid start from 0x603000a0 + UINT32 bssid_reg_base = LPON_SBTOR1; + + pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); + BssId = RT28xx_MBSS_IdxGet(pAd, pDev); + printk("##### %s, BssId = %d\n", __func__, BssId); + if (BssId < 0) + return -1; + + if (pAd->chipCap.hif_type != HIF_MT) + return 0; + + + if (BssId >= 1) { + //if there is any sub bssid is enable. this bit in LPON_SBTOR1 shall be 1 always. + RTMP_IO_READ32(pAd, bssid_reg_base, &Value); + Value |= SBSS_TBTT0_TSF0_EN; + RTMP_IO_WRITE32(pAd, bssid_reg_base, Value); + + RTMP_IO_READ32(pAd, (bssid_reg_base + (BssId - 1) * (0x4)), &Value); + Value = 0; + Value &= ~SUB_BSSID0_TIME_OFFSET_n_MASK; + Value |= SUB_BSSID0_TIME_OFFSET_n(BssId * (20 + 4096)); + + /* SIFS time, 20us, and assume bcn len is 512 byte, tx by 1Mbps.*/ + Value |= TBTT0_n_INT_EN; + Value |= PRE_TBTT0_n_INT_EN; + Value |= SBSS_TBTT0_TSF0_EN; + + RTMP_IO_WRITE32(pAd, (bssid_reg_base + (BssId - 1) * (0x4)), Value); + + /* Start Beacon Queue */ + RTMP_IO_READ32(pAd, ARB_BCNQCR0, &Value); + Value |= (0x1 << (BssId+15)); + RTMP_IO_WRITE32(pAd, ARB_BCNQCR0, Value); + } + + return 0; +} + +INT mbss_cr_disable(PNET_DEV pDev) +{ + PRTMP_ADAPTER pAd; + INT BssId; + UINT32 Value; + UINT32 bssid_reg_base = LPON_SBTOR1; + UCHAR loop = 0; + BOOLEAN any_mbss_enable = FALSE; + + pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); + BssId = RT28xx_MBSS_IdxGet(pAd, pDev); + if (BssId < 0) + return -1; + + if (pAd->chipCap.hif_type != HIF_MT) + return 0; + + for (loop = 1; loop < pAd->ApCfg.BssidNum; loop++) { + if (loop == BssId) + continue;//skip itself. + if (pAd->ApCfg.MBSSID[loop].bcn_buf.bBcnSntReq == TRUE) + any_mbss_enable = TRUE; + } + + if (BssId >= 1) { + RTMP_IO_READ32(pAd, (bssid_reg_base + (BssId - 1) * (0x4)), &Value); + Value = 0; + Value &= ~SUB_BSSID0_TIME_OFFSET_n_MASK; + Value |= SUB_BSSID0_TIME_OFFSET_n(BssId * (20 + 4096)); + Value &= ~TBTT0_n_INT_EN; + Value &= ~PRE_TBTT0_n_INT_EN; + if (any_mbss_enable == TRUE) + Value |= SBSS_TBTT0_TSF0_EN; + else + Value &= ~SBSS_TBTT0_TSF0_EN; + RTMP_IO_WRITE32(pAd, (bssid_reg_base + (BssId - 1) * (0x4)), Value); + RTMP_IO_READ32(pAd, ARB_BCNQCR0, &Value); + Value &= ~(0x1 << (BssId+15)); + RTMP_IO_WRITE32(pAd, ARB_BCNQCR0, Value); + } + + return 0; +} +#endif /* MT_MAC */ + +/* +======================================================================== +Routine Description: + Open a virtual network interface. + +Arguments: + pDev which WLAN network interface + +Return Value: + 0: open successfully + otherwise: open fail + +Note: +======================================================================== +*/ +INT32 MBSS_Open(PNET_DEV pDev) +{ + PRTMP_ADAPTER pAd; + INT BssId; + UINT32 u4MaxMBSSIDSize; + + u4MaxMBSSIDSize = sizeof(pAd->ApCfg.MBSSID)/sizeof(pAd->ApCfg.MBSSID[0]); + pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); + BssId = RT28xx_MBSS_IdxGet(pAd, pDev); + if (BssId < 0) + return -1; + + if(BssId >= u4MaxMBSSIDSize) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Over buffer size!\n", __FUNCTION__)); + return -1; + } + +#ifdef AIRPLAY_SUPPORT + if (AIRPLAY_ON(pAd)) + pAd->ApCfg.MBSSID[BssId].bcn_buf.bBcnSntReq = TRUE; + else + pAd->ApCfg.MBSSID[BssId].bcn_buf.bBcnSntReq = FALSE; +#else + pAd->ApCfg.MBSSID[BssId].bcn_buf.bBcnSntReq = TRUE; +#endif /* AIRPLAY_SUPPORT */ + +#ifdef BAND_STEERING + if(pAd->ApCfg.BandSteering) + { + PBND_STRG_CLI_TABLE table; + table = Get_BndStrgTable(pAd, BssId); + if(table) + { + /* Inform daemon interface ready */ + BndStrg_SetInfFlags(pAd, &pAd->ApCfg.MBSSID[BssId].wdev, table, TRUE); + } + } +#endif + + return 0; +} + + +/* +======================================================================== +Routine Description: + Close a virtual network interface. + +Arguments: + pDev which WLAN network interface + +Return Value: + 0: close successfully + otherwise: close fail + +Note: +======================================================================== +*/ +INT MBSS_Close(PNET_DEV pDev) +{ + PRTMP_ADAPTER pAd; + INT BssId; + UINT32 u4MaxMBSSIDSize; + 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); + + u4MaxMBSSIDSize = sizeof(pAd->ApCfg.MBSSID)/sizeof(pAd->ApCfg.MBSSID[0]); + if(BssId >= u4MaxMBSSIDSize) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Over buffer size!\n", __FUNCTION__)); + return -1; + } + + pAd->ApCfg.MBSSID[BssId].bcn_buf.bBcnSntReq = FALSE; + + + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + +#ifdef BAND_STEERING + if(pAd->ApCfg.BandSteering) + { + PBND_STRG_CLI_TABLE table; + table = Get_BndStrgTable(pAd, BssId); + if(table) + { + /* Inform daemon interface down */ + BndStrg_SetInfFlags(pAd, &pAd->ApCfg.MBSSID[BssId].wdev, table, FALSE); + } + } +#endif /* BAND_STEERING */ + return 0; +} + +#endif /* MBSS_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_mbss_inf.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_mbss_inf.c new file mode 100644 index 000000000..e134326fb --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_mbss_inf.c @@ -0,0 +1,202 @@ +/**************************************************************************** + * 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 + + 4. BSS Index (0 ~ 15) of different tx packet is assigned in + + 5. BSS Index (0 ~ 15) of different BSS is got in APHardTransmit() by using + + 6. BSS Index (0 ~ 15) of IOCTL command is put in pAd->OS_Cookie->ioctl_if + + 7. Beacon of different BSS is enabled in APMakeAllBssBeacon() by writing 1 + to the register MAC_BSSID_DW1 + + 8. The number of MBSS can be 1, 2, 4, or 8 + +***************************************************************************/ +#define RTMP_MODULE_OS + +#ifdef MBSS_SUPPORT + +/*#include "rt_config.h" */ +#include "rtmp_comm.h" +#include "rt_os_util.h" +#include "rt_os_net.h" + + +/* --------------------------------- Public -------------------------------- */ +NET_DEV_STATS *RT28xx_get_ether_stats(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(VOID *pAd, PNET_DEV pDevMain) +{ + RTMP_OS_NETDEV_OP_HOOK netDevHook; + + NdisZeroMemory(&netDevHook, sizeof(netDevHook)); + netDevHook.open = MBSS_VirtualIF_Open; /* device opem hook point */ + netDevHook.stop = MBSS_VirtualIF_Close; /* device close hook point */ + netDevHook.xmit = rt28xx_send_packets; /* hard transmit hook point */ + netDevHook.ioctl = rt28xx_ioctl; /* ioctl hook point */ + netDevHook.get_stats = RT28xx_get_ether_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(VOID *pAd) +{ + + RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_MBSS_REMOVE, 0, NULL, 0); + +} + + + +/* --------------------------------- Private -------------------------------- */ +/* +======================================================================== +Routine Description: + Open a virtual network interface. + +Arguments: + pDev which WLAN network interface + +Return Value: + 0: open successfully + otherwise: open fail + +Note: +======================================================================== +*/ +INT MBSS_VirtualIF_Open(PNET_DEV pDev) +{ + VOID *pAd; + + /* increase MODULE use count */ + RT_MOD_INC_USE_COUNT(); + + 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; + +#ifdef MT_MAC + RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_MBSS_CR_ENABLE, 0, pDev, 0); +#ifdef CONFIG_RA_HW_NAT_WIFI_NEW_ARCH + RT_MOD_HNAT_REG(pDev); +#endif +#endif + + RTMP_OS_NETDEV_START_QUEUE(pDev); + + return 0; +} + + +/* +======================================================================== +Routine Description: + Close a virtual network interface. + +Arguments: + pDev which WLAN network interface + +Return Value: + 0: close successfully + otherwise: close fail + +Note: +======================================================================== +*/ +INT MBSS_VirtualIF_Close(PNET_DEV pDev) +{ + VOID *pAd; + + + DBGPRINT(RT_DEBUG_TRACE, ("%s: ===> MBSSVirtualIF_close\n", RTMP_OS_NETDEV_GET_DEVNAME(pDev))); + + pAd = RTMP_OS_NETDEV_GET_PRIV(pDev); + +#ifdef MT_MAC + RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_MBSS_CR_DISABLE, 0, pDev, 0); +#endif + + RTMP_OS_NETDEV_STOP_QUEUE(pDev); + + RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_MBSS_CLOSE, 0, pDev, 0); + +#ifdef CONFIG_RA_HW_NAT_WIFI_NEW_ARCH + RT_MOD_HNAT_DEREG(pDev); +#endif + VIRTUAL_IF_DOWN(pAd); + + RT_MOD_DEC_USE_COUNT(); + return 0; +} + +#endif /* MBSS_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_mix_mode.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_mix_mode.c new file mode 100644 index 000000000..0bd261fd7 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_mix_mode.c @@ -0,0 +1,533 @@ +#include "rt_config.h" +#include "mix_mode.h" + + +static INT scan_ch_restore_for_MixMode(RTMP_ADAPTER *pAd, UCHAR OpMode) +{ + INT bw, ch; + + + if (pAd->CommonCfg.BBPCurrentBW != pAd->hw_cfg.bbp_bw) + bbp_set_bw(pAd, pAd->hw_cfg.bbp_bw); + +#ifdef DOT11_VHT_AC + if (pAd->hw_cfg.bbp_bw == BW_80) + ch = pAd->CommonCfg.vht_cent_ch; + else +#endif /* DOT11_VHT_AC */ + if (pAd->hw_cfg.bbp_bw == BW_40) + ch = pAd->CommonCfg.CentralChannel; + else + ch = pAd->CommonCfg.Channel; + + switch(pAd->CommonCfg.BBPCurrentBW) + { + case BW_80: + bw = 80; + break; + case BW_40: + bw = 40; + break; + case BW_10: + bw = 10; + break; + case BW_20: + default: + bw =20; + break; + } + + + ASSERT((ch != 0)); + AsicSwitchChannel(pAd, ch, FALSE); + AsicLockChannel(pAd, ch); + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to %dMHz channel %d, Total BSS[%02d]\n", + bw, ch, pAd->ScanTab.BssNr)); + + +#ifdef CONFIG_AP_SUPPORT + if (OpMode == OPMODE_AP) + { +#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 */ +#endif /* APCLI_SUPPORT */ + pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; + RTMPResumeMsduTransmission(pAd); + + /* 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) && (pAd->Dot11_H.RDMode != RD_NORMAL_MODE))) + AsicEnableBssSync(pAd, pAd->CommonCfg.BeaconPeriod); + } +#endif /* CONFIG_AP_SUPPORT */ + + + return TRUE; +} + + +static BOOLEAN MixModeChannelCheck(IN PRTMP_ADAPTER pAd, UCHAR channel, struct wifi_dev *wdev) +{ + + if(channel == 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s pass a invalid channel\n", __FUNCTION__)); + return FALSE; + } + + /*check channel in channel list*/ + if(ChannelSanity(pAd, channel) == 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("the channel parameter is out of channel list\n")); + return FALSE; + } + + /*check channel & phy mode*/ + if((channel < 14 && WMODE_CAP_5G(wdev->PhyMode)) || + (channel > 14 && WMODE_CAP_2G(wdev->PhyMode))) { + DBGPRINT(RT_DEBUG_ERROR, + ("the channel parameter and phy mode is not matched\n")); + return FALSE; + } + + return TRUE; +} + + +static INT MixModeSwitchCH(IN PRTMP_ADAPTER pAd) +{ + UCHAR channel; + struct wifi_dev *wdev; + struct peer_info *mon_sta_info = &pAd->MixModeCtrl.sta_info[0]; + + if(pAd == NULL) + return -1; + + channel = pAd->MixModeCtrl.sta_info[0].channel; + wdev = pAd->MixModeCtrl.pMixModewdev; + + /*check channel with current band channel*/ + if(channel == wdev->channel) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s:: current channel is the sniffer set channel %d\n", __FUNCTION__, channel)); + return 0; + } + + /* Disable BCN */ + AsicDisableSync(pAd); + + /*need to poll tx Q unitl empty*/ + + /* Suspend MSDU transmission here */ + RTMPSuspendMsduTransmission(pAd); + + bbp_set_bw(pAd, mon_sta_info->bw); + + /*Switch Channel*/ + AsicSwitchChannel(pAd, mon_sta_info->center_channel, FALSE); + AsicLockChannel(pAd, mon_sta_info->center_channel); + + DBGPRINT(RT_DEBUG_OFF, + ("%s:: switch to channel %d\n", __FUNCTION__, channel)); + + + return 0; +} + +static CHAR MixModeCalcAvgRssi(RTMP_ADAPTER *pAd, UCHAR idx) +{ + UCHAR mnt_idx = 0; + LONG avgRssi = -127; + + struct peer_info *sta = &pAd->MixModeCtrl.sta_info[mnt_idx]; + LONG mgmt_rssi = sta->mnt_sta.frm[FC_TYPE_MGMT].rssi; + LONG data_rssi = sta->mnt_sta.frm[FC_TYPE_DATA].rssi; + LONG cntl_rssi = sta->mnt_sta.frm[FC_TYPE_CNTL].rssi; + LONG total = sta->mnt_sta.Count; + + /* + * weight * rssi + * But need to check vaule + * it cannot overflow + */ + if (total) + avgRssi = (mgmt_rssi + data_rssi + cntl_rssi) / total; + + DBGPRINT(RT_DEBUG_OFF, + ("%s:: %02x:%02x:%02x:%02x:%02x:%02x, avgRssi=%ld\n", __FUNCTION__, PRINT_MAC(sta->mac_addr), avgRssi)); + + return avgRssi; +} + +static INT MixModeSniffer(RTMP_ADAPTER *pAd, UINT8 enable) +{ + if (enable == TRUE) + pAd->MixModeCtrl.current_monitor_mode = MIX_MODE_FULL; + else if (enable == FALSE) + pAd->MixModeCtrl.current_monitor_mode = MIX_MODE_OFF; + + DBGPRINT(RT_DEBUG_OFF, + ("%s(): set Current Monitor Mode = %d\n", + __FUNCTION__, pAd->MixModeCtrl.current_monitor_mode)); + + switch(pAd->MixModeCtrl.current_monitor_mode) + { + /*reset to normal */ + case MIX_MODE_OFF: + pAd->ApCfg.BssType = BSS_INFRA; + AsicSetRxFilter(pAd); + break; + + /*fully report, Enable Rx with promiscuous reception*/ + case MIX_MODE_FULL: + pAd->ApCfg.BssType = BSS_MONITOR; + AsicSetRxFilter(pAd); + break; + default: + DBGPRINT(RT_DEBUG_OFF, + ("MIX MODE index ONLY be set to 0 or 2\n")); + break; + } + + return 0; +} + +//extern INT scan_ch_restore(RTMP_ADAPTER *pAd, UCHAR OpMode); + +static VOID MixModeRestoreCH(IN PRTMP_ADAPTER pAd) +{ + if(pAd->MixModeCtrl.pMixModewdev != NULL && + (pAd->MixModeCtrl.sta_info[0].channel != (pAd->MixModeCtrl.pMixModewdev)->channel)) + /*scan ch restore for MixMode will do enable BCN*/ + scan_ch_restore_for_MixMode(pAd, OPMODE_AP); +} + +static VOID MixModeReset(IN PRTMP_ADAPTER pAd) +{ + pAd->MixModeCtrl.MixModeOn = FALSE; + pAd->MixModeCtrl.pMixModewdev = NULL; + pAd->MixModeCtrl.MixModeStatMachine.CurrState = MIX_MODE_STATE_INIT; + pAd->MixModeCtrl.ioctl_if = -1; +} + +static VOID MixModeListenExit(RTMP_ADAPTER *pAd) +{ + BOOLEAN disbleSniffer = FALSE; + BOOLEAN mixmode_done = TRUE; + + DBGPRINT(RT_DEBUG_OFF, ("%s()\n", __FUNCTION__)); + + if(MixModeSniffer(pAd,disbleSniffer) !=0) + DBGPRINT(RT_DEBUG_ERROR, ("%s fail by sniffer mode\n",__FUNCTION__)); + + MixModeRestoreCH(pAd); + MixModeReset(pAd); + + DBGPRINT(RT_DEBUG_OFF, ("%s::Exit mix mode\n", __FUNCTION__)); + /* send event to userspace */ + RtmpOSWrielessEventSend(pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + RT_MIX_MODE_EVENT_FLAG, + NULL, + (char *)&mixmode_done, + sizeof(mixmode_done)); +} + +static VOID MixModeListenCancel(RTMP_ADAPTER *pAd,MLME_QUEUE_ELEM *pElem) +{ + if(pAd == NULL) + return; + + DBGPRINT(RT_DEBUG_OFF, ("%s()\n", __FUNCTION__)); + + MixModeListenExit(pAd); +} + + +static VOID MixModeListenTimeout(RTMP_ADAPTER *pAd,MLME_QUEUE_ELEM *pElem) +{ + if(pAd == NULL) + return; + + DBGPRINT(RT_DEBUG_OFF, ("%s()\n", __FUNCTION__)); + + MixModeListenExit(pAd); + +} + + +static VOID MixModeEnterListen(RTMP_ADAPTER *pAd,MLME_QUEUE_ELEM *pElem) +{ + INT32 ret; + BOOLEAN enbleSniffer = TRUE; + + DBGPRINT(RT_DEBUG_OFF, ("%s()\n", __FUNCTION__)); + + if(pAd == NULL) + return; + + /*switch channel*/ + ret = MixModeSwitchCH(pAd); + if(ret != 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s fail by switch channel\n",__FUNCTION__)); + MixModeReset(pAd); + return; + } + + /*enter sniffer mode*/ + ret = MixModeSniffer(pAd,enbleSniffer); + if(ret != 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s fail by sniffer mode\n",__FUNCTION__)); + MixModeRestoreCH(pAd); + MixModeReset(pAd); + return; + } + pAd->MixModeCtrl.MixModeOn = TRUE; + pAd->MixModeCtrl.MixModeStatMachine.CurrState = MIX_MODE_STATE_RUNNING; + DBGPRINT(RT_DEBUG_OFF, ("pAd->MixModeCtrl.sta_info[0].duration = %d\n", pAd->MixModeCtrl.sta_info[0].duration)); + RTMPSetTimer(&pAd->MixModeCtrl.MixModeTimer, pAd->MixModeCtrl.sta_info[0].duration); +} + +static VOID MixModeStateMachineInit(IN RTMP_ADAPTER *pAd, IN STATE_MACHINE *Sm, OUT STATE_MACHINE_FUNC Trans[]) +{ + /*Init*/ + StateMachineInit(Sm,(STATE_MACHINE_FUNC *)Trans,MIX_MODE_STATE_MAX, MIX_MODE_MSG_MAX, (STATE_MACHINE_FUNC)Drop, MIX_MODE_STATE_INIT, MIX_MODE_STATE_BASE); + + /*Idle*/ + StateMachineSetAction(Sm, MIX_MODE_STATE_INIT, MIX_MODE_MSG_LISTEN, (STATE_MACHINE_FUNC)MixModeEnterListen); + /*Running*/ + StateMachineSetAction(Sm, MIX_MODE_STATE_RUNNING, MIX_MODE_MSG_CANCLE, (STATE_MACHINE_FUNC)MixModeListenCancel); + StateMachineSetAction(Sm, MIX_MODE_STATE_RUNNING, MIX_MODE_MSG_TIMEOUT, (STATE_MACHINE_FUNC)MixModeListenTimeout); +} + + +VOID MixModeTimeout(IN PVOID SystemSpecific1, IN PVOID FunctionContext, + IN PVOID SystemSpecific2, IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; + if(pAd == NULL) + return; + + DBGPRINT(RT_DEBUG_OFF, ("%s()\n", __FUNCTION__)); + + MlmeEnqueue(pAd, MIX_MODE_STATE_MACHINE, MIX_MODE_MSG_TIMEOUT, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); +} + +VOID MixModeDebugInfo(IN PRTMP_ADAPTER pAd, IN int idx) +{ + MIX_MODE_CTRL *MixModeCtrl = &pAd->MixModeCtrl; + DBGPRINT(RT_DEBUG_OFF, + ("MixMode status = %d\nMixMode CurrState = %lu\nMixMode CH = %d\n" + "targetMac = %02x:%02x:%02x:%02x:%02x:%02x\nMixMode Duration = %d\n", + MixModeCtrl->MixModeOn, MixModeCtrl->MixModeStatMachine.CurrState, + MixModeCtrl->sta_info[idx].channel, + PRINT_MAC(MixModeCtrl->sta_info[idx].mac_addr), + MixModeCtrl->sta_info[idx].duration)); + +} + +VOID MixModeProcessData(RTMP_ADAPTER *pAd, void *rxBlk) +{ + RX_BLK *pRxBlk = (RX_BLK*)rxBlk; + PHEADER_802_11 pHeader; + CHAR avg_rssi; + struct peer_info *mon_sta_info = &pAd->MixModeCtrl.sta_info[0]; + FRAME_CONTROL *fc; + struct MNT_STA_INFO *mnt_sta; + +// DBGPRINT(RT_DEBUG_OFF, ("%s()\n", __FUNCTION__)); + + ASSERT(pRxBlk->pRxPacket); + + pHeader = pRxBlk->pHeader; + fc = &pHeader->FC; + mnt_sta = &mon_sta_info->mnt_sta; + +// DBGPRINT(RT_DEBUG_OFF, ("mon_sta_info->mac_addr = %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(mon_sta_info->mac_addr))); + + if (NdisEqualMemory(pHeader->Addr2, mon_sta_info->mac_addr, MAC_ADDR_LEN)) { + if (fc->Type == FC_TYPE_DATA) + Update_Rssi_Sample(pAd, &mon_sta_info->RssiSample, &pRxBlk->rx_signal, + pRxBlk->rx_rate.field.MODE, pRxBlk->rx_rate.field.BW); + else + Update_Rssi_Sample(pAd, &mon_sta_info->RssiSample, &pRxBlk->rx_signal, + 0, pRxBlk->rx_rate.field.BW); + + avg_rssi = RTMPAvgRssi(pAd, &mon_sta_info->RssiSample); + + if (fc->Type < FC_TYPE_RSVED) { + mnt_sta->frm[fc->Type].cnt++; + mnt_sta->frm[fc->Type].rssi += avg_rssi; + mnt_sta->Count++; + } + DBGPRINT(RT_DEBUG_OFF, + ("fctype = %d ,mgmt = %ld , data = %ld , cnt = %ld " + "frame FROM %02x:%02x:%02x:%02x:%02x:%02x TO " + "%02x:%02x:%02x:%02x:%02x:%02x\n", + fc->Type, + mnt_sta->frm[FC_TYPE_MGMT].cnt, + mnt_sta->frm[FC_TYPE_DATA].cnt, + mnt_sta->frm[FC_TYPE_CNTL].cnt, + PRINT_MAC(pHeader->Addr2), + PRINT_MAC(pHeader->Addr1))); + } + + return; +} + +/* + * 1. check parameters + * 2. check other SMs + * 3. run SM +*/ +INT MixModeSet(IN PRTMP_ADAPTER pAd, struct mix_peer_parameter *sta_info, IN UCHAR idx) +{ + POS_COOKIE pObj; + struct wifi_dev *wdev; + struct peer_info *mon_sta_info = &pAd->MixModeCtrl.sta_info[0]; + + if (pAd == NULL) + return -EFAULT; + + pObj = (POS_COOKIE)pAd->OS_Cookie; + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + + if (wdev == NULL) + return -EFAULT; + + pAd->MixModeCtrl.pMixModewdev = wdev; + pAd->MixModeCtrl.ioctl_if = pObj->ioctl_if; + + if (sta_info->mac_addr == NULL) + return -EFAULT; + + if (NdisEqualMemory(sta_info->mac_addr, &BROADCAST_ADDR[0], MAC_ADDR_LEN) || + NdisEqualMemory(sta_info->mac_addr, &ZERO_MAC_ADDR[0], MAC_ADDR_LEN)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s pass a invalid mac %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, PRINT_MAC(sta_info->mac_addr))); + return -EFAULT; + } + + NdisZeroMemory(mon_sta_info, sizeof(struct peer_info)); + NdisCopyMemory(mon_sta_info->mac_addr, sta_info->mac_addr, MAC_ADDR_LEN); + + if (MixModeChannelCheck(pAd, sta_info->channel, wdev)) + mon_sta_info->channel = sta_info->channel; + else + return -EFAULT; + + if (sta_info->duration == 0) + mon_sta_info->duration = MixModeDefualtListenTime; + else + mon_sta_info->duration = sta_info->duration; + +#ifdef DOT11_VHT_AC + if (sta_info->channel > 14) { + mon_sta_info->bw = BW_80; + mon_sta_info->center_channel = vht_cent_ch_freq(pAd, sta_info->channel); + } else +#endif + { + mon_sta_info->bw = sta_info->bw; + mon_sta_info->ch_offset = sta_info->ch_offset; + + if(sta_info->bw == BW_40) { + /*check bw & channel*/ + if ((sta_info->channel < 5 && sta_info->ch_offset == EXTCHA_BELOW) + || (sta_info->channel > 9 && sta_info->ch_offset == EXTCHA_ABOVE)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s pass a invalid primary channel & second channel\n", __FUNCTION__)); + return -EFAULT; + } + + if(sta_info->ch_offset == EXTCHA_ABOVE) + mon_sta_info->center_channel = sta_info->channel + 2; + else if(sta_info->ch_offset == EXTCHA_BELOW) + mon_sta_info->center_channel = sta_info->channel - 2; + } else + mon_sta_info->center_channel = sta_info->channel; + } + + /*check other SMs like autsel or bgscan etc*/ + MlmeEnqueue(pAd, MIX_MODE_STATE_MACHINE, MIX_MODE_MSG_LISTEN, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); + + return 0; +} +INT RTMPIoctlQueryMixModeRssi(IN PRTMP_ADAPTER pAd, IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + INT Status; + CHAR avg_rssi; + + avg_rssi = MixModeCalcAvgRssi(pAd, 0); + + wrq->u.data.length = sizeof(avg_rssi); + + Status = copy_to_user(wrq->u.data.pointer, &avg_rssi, wrq->u.data.length); + + if(Status) + DBGPRINT(RT_DEBUG_ERROR, + ("%s: copy_to_user() fail\n", __FUNCTION__)); + + return Status; +} + +VOID MixModeCancel(IN PRTMP_ADAPTER pAd) +{ + BOOLEAN Cancelled; + if(pAd == NULL) + return; + + RTMPCancelTimer(&pAd->MixModeCtrl.MixModeTimer,&Cancelled); + + MlmeEnqueue(pAd, MIX_MODE_STATE_MACHINE, MIX_MODE_MSG_CANCLE, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); +} + +VOID MixModeInit(IN PRTMP_ADAPTER pAd) +{ + if(pAd == NULL) + return; + + MixModeReset(pAd); + MixModeStateMachineInit(pAd, &pAd->MixModeCtrl.MixModeStatMachine, pAd->MixModeCtrl.MixModeStateFunc); + RTMPInitTimer(pAd, &pAd->MixModeCtrl.MixModeTimer, GET_TIMER_FUNCTION(MixModeTimeout), pAd, FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("Enter %s\n", __FUNCTION__)); +} + +VOID MixModeDel(IN PRTMP_ADAPTER pAd) +{ + BOOLEAN Cancelled; + if(pAd == NULL) + return; + + RTMPReleaseTimer(&pAd->MixModeCtrl.MixModeTimer, &Cancelled); + NdisZeroMemory(&pAd->MixModeCtrl.sta_info, sizeof(pAd->MixModeCtrl.sta_info)); + + DBGPRINT(RT_DEBUG_TRACE, ("Exit %s\n", __FUNCTION__)); +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_mlme.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_mlme.c new file mode 100644 index 000000000..a09f658e8 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_mlme.c @@ -0,0 +1,769 @@ +/**************************************************************************** + * 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 + +#ifdef BTCOEX_CONCURRENT +extern void MT7662ReceCoexFromOtherCHip( + IN UCHAR channel, + IN UCHAR centralchannel, + IN UCHAR channel_bw + ); +#endif +#if defined(MAX_CONTINUOUS_TX_CNT) || defined(NEW_IXIA_METHOD) +VOID rtmp_deqmode_detect(RTMP_ADAPTER *pAd); +#endif +#ifdef DOT11_N_SUPPORT + +int DetectOverlappingPeriodicRound; + + +#ifdef DOT11N_DRAFT3 +VOID Bss2040CoexistTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + int apidx; + PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; + + DBGPRINT(RT_DEBUG_TRACE, ("Bss2040CoexistTimeOut(): Recovery to original setting!\n")); + + /* Recovery to original setting when next DTIM Interval. */ + pAd->CommonCfg.Bss2040CoexistFlag &= (~BSS_2040_COEXIST_TIMER_FIRED); + NdisZeroMemory(&pAd->CommonCfg.LastBSSCoexist2040, sizeof(BSS_2040_COEXIST_IE)); + pAd->CommonCfg.Bss2040CoexistFlag |= BSS_2040_COEXIST_INFO_SYNC; + + if (pAd->CommonCfg.bBssCoexEnable == FALSE) + { + /* TODO: Find a better way to handle this when the timer is fired and we disable the bBssCoexEable support!! */ + DBGPRINT(RT_DEBUG_TRACE, ("Bss2040CoexistTimeOut(): bBssCoexEnable is FALSE, return directly!\n")); + return; + } + + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + SendBSS2040CoexistMgmtAction(pAd, MCAST_WCID, apidx, 0); + +} +#endif /* DOT11N_DRAFT3 */ + +#endif /* DOT11_N_SUPPORT */ + + +VOID APDetectOverlappingExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ +#ifdef DOT11_N_SUPPORT + PRTMP_ADAPTER pAd = (RTMP_ADAPTER *)FunctionContext; + + if (DetectOverlappingPeriodicRound == 0) + { + /* switch back 20/40 */ + if ((pAd->CommonCfg.Channel <=14) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 1; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; + } + } + else + { + if ((DetectOverlappingPeriodicRound == 25) || (DetectOverlappingPeriodicRound == 1)) + { + if ((pAd->CommonCfg.Channel <=14) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth==BW_40)) + { + SendBeaconRequest(pAd, 1); + SendBeaconRequest(pAd, 2); + SendBeaconRequest(pAd, 3); + } + + } + DetectOverlappingPeriodicRound--; + } +#endif /* DOT11_N_SUPPORT */ +} + + +/* + ========================================================================== + Description: + This routine is executed every second - + 1. Decide the overall channel quality + 2. Check if need to upgrade the TX rate to any client + 3. perform MAC table maintenance, including ageout no-traffic clients, + and release packet buffer in PSQ is fail to TX in time. + ========================================================================== + */ +VOID APMlmePeriodicExec( + PRTMP_ADAPTER pAd) +{ +#ifdef A4_CONN + UCHAR mbss_idx; +#endif + /* + 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 BTCOEX_CONCURRENT + MT7662ReceCoexFromOtherCHip(pAd->CommonCfg.Channel,pAd->CommonCfg.CentralChannel,pAd->CommonCfg.BBPCurrentBW); +#endif + +#ifdef CARRIER_DETECTION_SUPPORT + if (isCarrierDetectExist(pAd) == TRUE) + { + PCARRIER_DETECTION_STRUCT pCarrierDetect = &pAd->CommonCfg.CarrierDetect; + if (pCarrierDetect->OneSecIntCount < pCarrierDetect->CarrierGoneThreshold) + { + pCarrierDetect->CD_State = CD_NORMAL; + pCarrierDetect->recheck = pCarrierDetect->recheck1; + if (pCarrierDetect->Debug != RT_DEBUG_TRACE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Carrier gone\n")); + /* start all TX actions. */ + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + AsicEnableBssSync(pAd, pAd->CommonCfg.BeaconPeriod); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Carrier gone\n")); + } + } + pCarrierDetect->OneSecIntCount = 0; + } + +#endif /* CARRIER_DETECTION_SUPPORT */ + + RTMP_CHIP_HIGH_POWER_TUNING(pAd, &pAd->ApCfg.RssiSample); + + + /* Disable Adjust Tx Power for WPA WiFi-test. */ + /* Because high TX power results in the abnormal disconnection of Intel BG-STA. */ +/*#ifndef WIFI_TEST */ +/* if (pAd->CommonCfg.bWiFiTest == FALSE) */ + /* for SmartBit 64-byte stream test */ + /* removed based on the decision of Ralink congress at 2011/7/06 */ +/* if (pAd->MacTab.Size > 0) */ + RTMP_CHIP_ASIC_ADJUST_TX_POWER(pAd); +/*#endif // WIFI_TEST */ + + RTMP_CHIP_ASIC_TEMPERATURE_COMPENSATION(pAd); + + /* walk through MAC table, see if switching TX rate is required */ + + /* MAC table maintenance */ + if (pAd->Mlme.PeriodicRound % MLME_TASK_EXEC_MULTIPLE == 0) + { +#if defined(BAND_STEERING) || defined(CUSTOMER_DCC_FEATURE) || defined(WIFI_DIAG)\ + || defined(WAPP_SUPPORT) + UINT32 msdr9; + + /* NAV, CCA, or TX active timer in unit of TU, used for Measurement. (channel busy time) */ + RTMP_IO_READ32(pAd, MIB_MSDR9, &msdr9); + msdr9 &= 0xFFFFFF; + pAd->OneSecChBusyTime = msdr9; +#ifdef BAND_STEERING + if (pAd->ApCfg.BandSteering) + pAd->ApCfg.BndStrgOneSecChBusyTime = (pAd->ApCfg.BndStrgOneSecChBusyTime == 0)? \ + msdr9 : ((msdr9 + pAd->ApCfg.BndStrgOneSecChBusyTime)>>1); +#endif +#endif + /* one second timer */ + MacTableMaintenance(pAd); + +#ifdef WH_EZ_SETUP +#ifdef NEW_CONNECTION_ALGO + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) { + EzMlmeEnqueue(pAd, EZ_STATE_MACHINE, EZ_PERIODIC_EXEC_REQ, 0, NULL, 0); + } +#endif +#endif +#ifdef CONFIG_FPGA_MODE + if (pAd->fpga_ctl.fpga_tr_stop) + { + INT enable = FALSE, ctrl_type; + + /* enable/disable tx/rx*/ + switch (pAd->fpga_ctl.fpga_tr_stop) + { + case 3: //stop tx + rx + ctrl_type = ASIC_MAC_TXRX; + break; + case 2: // stop rx + ctrl_type = ASIC_MAC_RX; + break; + case 1: // stop tx + ctrl_type = ASIC_MAC_TX; + break; + case 4: + default: + enable = TRUE; + ctrl_type = ASIC_MAC_TXRX; + break; + } + AsicSetMacTxRx(pAd, ctrl_type, enable); + } +#endif /* CONFIG_FPGA_MODE */ + + RTMPMaintainPMKIDCache(pAd); + +#ifdef WDS_SUPPORT + WdsTableMaintenance(pAd); +#endif /* WDS_SUPPORT */ + + +#ifdef CLIENT_WDS + CliWds_ProxyTabMaintain(pAd); +#endif /* CLIENT_WDS */ +#ifdef A4_CONN + for(mbss_idx = 0; mbss_idx < pAd->ApCfg.BssidNum; mbss_idx++) + a4_proxy_maintain(pAd, mbss_idx); + pAd->a4_need_refresh = FALSE; +#endif /* A4_CONN */ +#ifdef WH_EVENT_NOTIFIER + //WHCMlmePeriodicExec(pAd); // Arvind : Need to confirm that we have to support this event +#endif /* WH_EVENT_NOTIFIER */ + +#ifdef WIFI_DIAG + DiagApMlmeOneSecProc(pAd); +#endif + } + +#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 + && (pAd->ApCfg.ApCliAutoConnectChannelSwitching == FALSE) +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + ) { + ApCliIfUp(pAd); + } + + { + INT loop; + ULONG Now32; + +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + { + RTMPRepeaterReconnectionCheck(pAd); + } +#endif /* MAC_REPEATER_SUPPORT */ + + 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)) + { + /* update channel quality for Roaming and UI LinkQuality display */ + MlmeCalculateChannelQuality(pAd, + &pAd->MacTab.Content[pApCliEntry->MacTabWCID], Now32); + } + } + } +#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->CommonCfg.BeaconPeriod); + pAd->Dot11_H.RDMode = RD_NORMAL_MODE; + } + } +#endif /* !DFS_SUPPORT */ + } +#endif /* A_BAND_SUPPORT */ +#ifdef MBO_SUPPORT + MboCheckBssTermination(pAd); +#endif/* MBO_SUPPORT */ +#ifdef DOT11R_FT_SUPPORT + FT_R1KHInfoMaintenance(pAd); +#endif /* DOT11R_FT_SUPPORT */ +#if defined(MAX_CONTINUOUS_TX_CNT) || defined(NEW_IXIA_METHOD) + if(pAd->MonitorFlag == TRUE) + rtmp_deqmode_detect(pAd); /* 1s detect*/ +#endif +#ifdef BAND_STEERING + BndStrgHeartBeatMonitor(pAd); +#endif +#ifdef NEW_IXIA_METHOD + if (pAd->Mlme.OneSecPeriodicRound % pAd->chkTmr == 0) { + if ((txpktdetect2s < pAd->pktthld) + && (rxpktdetect2s < pAd->pktthld)) {/*Threshold*/ + pAd->tmrlogctrl++; + if (pAd->tmrlogctrl <= 1) + wifi_txrx_parmtrs_dump(pAd); + else + pAd->tmrlogctrl = 10;/*prevent pAd->tmrlogctrl overflow*/ + } else + pAd->tmrlogctrl = 0; + txpktdetect2s = 0; + rxpktdetect2s = 0; + } +#endif +} + + +/*! \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; +#ifdef DOT11_SAE_SUPPORT + USHORT Alg; +#endif /* DOT11_SAE_SUPPORT */ + UCHAR EAPType; + BOOLEAN Return = FALSE; +#ifdef WSC_AP_SUPPORT + UCHAR EAPCode; + PMAC_TABLE_ENTRY pEntry; +#endif /* WSC_AP_SUPPORT */ + unsigned char hdr_len = LENGTH_802_11; + +#ifdef A4_CONN + if ((pFrame->Hdr.FC.FrDs == 1) && (pFrame->Hdr.FC.ToDs == 1)) + hdr_len = LENGTH_802_11_WITH_ADDR4; +#endif + /* + TODO: + only PROBE_REQ can be broadcast, all others must be unicast-to-me && is_mybssid; + otherwise, ignore this frame + */ + + /* wpa EAPOL PACKET */ + if (pFrame->Hdr.FC.Type == FC_TYPE_DATA) + { +#ifdef WSC_AP_SUPPORT + WSC_CTRL *wsc_ctrl; + /*WSC EAPOL PACKET */ + pEntry = MacTableLookup(pAd, pFrame->Hdr.Addr2); + if (pEntry && + ((pEntry->bWscCapable) || + (pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.AuthMode < Ndis802_11AuthModeWPA))) + { + /* + WSC AP only can service one WSC STA in one WPS session. + Forward this EAP packet to WSC SM if this EAP packets is from + WSC STA that WSC AP services or WSC AP doesn't service any + WSC STA now. + */ + wsc_ctrl = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].WscControl; + if ((MAC_ADDR_EQUAL(wsc_ctrl->EntryAddr, pEntry->Addr) || + MAC_ADDR_EQUAL(wsc_ctrl->EntryAddr, ZERO_MAC_ADDR)) && + IS_ENTRY_CLIENT(pEntry) && + (wsc_ctrl->WscConfMode != WSC_DISABLE)) + { + *Machine = WSC_STATE_MACHINE; + EAPType = *((UCHAR *)pFrame + hdr_len + LENGTH_802_1_H + 1); + EAPCode = *((UCHAR *)pFrame + hdr_len + LENGTH_802_1_H + 4); + Return = WscMsgTypeSubst(EAPType, EAPCode, MsgType); + } + } +#endif /* WSC_AP_SUPPORT */ + if (!Return) + { + *Machine = WPA_STATE_MACHINE; + EAPType = *((UCHAR *)pFrame + hdr_len + LENGTH_802_1_H + 1); + Return = WpaMsgTypeSubst(EAPType, (INT *) MsgType); + } + return Return; + } + + if (pFrame->Hdr.FC.Type != FC_TYPE_MGMT) + return FALSE; + + switch (pFrame->Hdr.FC.SubType) + { + case SUBTYPE_ASSOC_REQ: + *Machine = AP_ASSOC_STATE_MACHINE; + *MsgType = APMT2_PEER_ASSOC_REQ; + + break; + /* + case SUBTYPE_ASSOC_RSP: + *Machine = AP_ASSOC_STATE_MACHINE; + *MsgType = APMT2_PEER_ASSOC_RSP; + break; + */ + case SUBTYPE_REASSOC_REQ: + *Machine = AP_ASSOC_STATE_MACHINE; + *MsgType = APMT2_PEER_REASSOC_REQ; + break; + /* + case SUBTYPE_REASSOC_RSP: + *Machine = AP_ASSOC_STATE_MACHINE; + *MsgType = APMT2_PEER_REASSOC_RSP; + break; + */ + case SUBTYPE_PROBE_REQ: + *Machine = AP_SYNC_STATE_MACHINE; + *MsgType = APMT2_PEER_PROBE_REQ; + break; + + /* For Active Scan */ + case SUBTYPE_PROBE_RSP: + *Machine = AP_SYNC_STATE_MACHINE; + *MsgType = APMT2_PEER_PROBE_RSP; + break; + case SUBTYPE_BEACON: + *Machine = AP_SYNC_STATE_MACHINE; + *MsgType = APMT2_PEER_BEACON; + break; + /* + case SUBTYPE_ATIM: + *Machine = AP_SYNC_STATE_MACHINE; + *MsgType = APMT2_PEER_ATIM; + break; + */ + case SUBTYPE_DISASSOC: + *Machine = AP_ASSOC_STATE_MACHINE; + *MsgType = APMT2_PEER_DISASSOC_REQ; + break; + case SUBTYPE_AUTH: + /* get the sequence number from payload 24 Mac Header + 2 bytes algorithm */ +#ifdef DOT11_SAE_SUPPORT + NdisMoveMemory(&Alg, &pFrame->Octet[0], sizeof(USHORT)); +#endif /* DOT11_SAE_SUPPORT */ + NdisMoveMemory(&Seq, &pFrame->Octet[2], sizeof(USHORT)); + + *Machine = AP_AUTH_STATE_MACHINE; + if (Seq == 1 +#ifdef DOT11_SAE_SUPPORT + || (Alg == AUTH_MODE_SAE && Seq == 2) +#endif /* DOT11_SAE_SUPPORT */ + ) + *MsgType = APMT2_PEER_AUTH_REQ; + else if (Seq == 3) + *MsgType = APMT2_PEER_AUTH_CONFIRM; + else + { + DBGPRINT(RT_DEBUG_TRACE,("wrong AUTH seq=%d Octet=%02x %02x %02x %02x %02x %02x %02x %02x\n", + Seq, + pFrame->Octet[0], pFrame->Octet[1], pFrame->Octet[2], pFrame->Octet[3], + pFrame->Octet[4], pFrame->Octet[5], pFrame->Octet[6], pFrame->Octet[7])); + return FALSE; + } + break; + + case SUBTYPE_DEAUTH: + *Machine = AP_AUTH_STATE_MACHINE; /*AP_AUTH_RSP_STATE_MACHINE;*/ + *MsgType = APMT2_PEER_DEAUTH; + break; + + case SUBTYPE_ACTION: + case SUBTYPE_ACTION_NO_ACK: + *Machine = ACTION_STATE_MACHINE; + /* Sometimes Sta will return with category bytes with MSB = 1, if they receive catogory out of their support */ + if ((pFrame->Octet[0]&0x7F) > MAX_PEER_CATE_MSG) + { + *MsgType = MT2_ACT_INVALID; + } + else + { + *MsgType = (pFrame->Octet[0]&0x7F); + } + break; + + default: + return FALSE; + break; + } + + return TRUE; +} + + +/* + ======================================================================== + Routine Description: + Periodic evaluate antenna link status + + Arguments: + pAd - Adapter pointer + + Return Value: + None + + ======================================================================== +*/ +VOID APAsicEvaluateRxAnt( + IN PRTMP_ADAPTER pAd) +{ + ULONG TxTotalCnt; + +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + return; +#endif /* CONFIG_ATE */ +#ifdef CARRIER_DETECTION_SUPPORT + if(pAd->CommonCfg.CarrierDetect.CD_State == CD_SILENCE) + return; +#endif /* CARRIER_DETECTION_SUPPORT */ + + + + + + +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == TRUE) + bbp_set_rxpath(pAd, 1); + else +#endif /* GREENAP_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + bbp_set_rxpath(pAd, pAd->Antenna.field.RxPath); + + TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + if (TxTotalCnt > 50) + { + RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 20); + pAd->Mlme.bLowThroughput = FALSE; + } + else + { + RTMPSetTimer(&pAd->Mlme.RxAntEvalTimer, 300); + pAd->Mlme.bLowThroughput = TRUE; + } +} + +/* + ======================================================================== + Routine Description: + After evaluation, check antenna link status + + Arguments: + pAd - Adapter pointer + + Return Value: + None + + ======================================================================== +*/ +VOID APAsicRxAntEvalTimeout(RTMP_ADAPTER *pAd) +{ + CHAR rssi[3], *target_rssi; + +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + return; +#endif /* CONFIG_ATE */ + + /* if the traffic is low, use average rssi as the criteria */ + if (pAd->Mlme.bLowThroughput == TRUE) + target_rssi = &pAd->ApCfg.RssiSample.LastRssi[0]; + else + target_rssi = &pAd->ApCfg.RssiSample.AvgRssi[0]; + NdisMoveMemory(&rssi[0], target_rssi, 3); + +#ifdef DOT11N_SS3_SUPPORT + if(pAd->Antenna.field.RxPath == 3) + { + CHAR larger = -127; + + larger = max(rssi[0], rssi[1]); + if (pAd->CommonCfg.RxStream >= 3) + pAd->Mlme.RealRxPath = 3; + else + { + if (larger > (rssi[2] + 20)) + pAd->Mlme.RealRxPath = 2; + else + pAd->Mlme.RealRxPath = 3; + } + } +#endif /* DOT11N_SS3_SUPPORT */ + + /* Disable the below to fix 1T/2R issue. It's suggested by Rory at 2007/7/11. */ + +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == TRUE) + bbp_set_rxpath(pAd, 1); + else +#endif /* GREENAP_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + bbp_set_rxpath(pAd, pAd->Mlme.RealRxPath); + +} + + +/* + ======================================================================== + Routine Description: + After evaluation, check antenna link status + + Arguments: + pAd - Adapter pointer + + Return Value: + None + + ======================================================================== +*/ +VOID APAsicAntennaAvg( + IN PRTMP_ADAPTER pAd, + IN UCHAR AntSelect, + IN SHORT* RssiAvg) +{ + SHORT realavgrssi; + LONG realavgrssi1; + ULONG recvPktNum = pAd->RxAnt.RcvPktNum[AntSelect]; + + realavgrssi1 = pAd->RxAnt.Pair1AvgRssiGroup1[AntSelect]; + + if(realavgrssi1 == 0) + { + *RssiAvg = 0; + return; + } + + realavgrssi = (SHORT) (realavgrssi1 / recvPktNum); + + pAd->RxAnt.Pair1AvgRssiGroup1[0] = 0; + pAd->RxAnt.Pair1AvgRssiGroup1[1] = 0; + pAd->RxAnt.Pair1AvgRssiGroup2[0] = 0; + pAd->RxAnt.Pair1AvgRssiGroup2[1] = 0; + pAd->RxAnt.RcvPktNum[0] = 0; + pAd->RxAnt.RcvPktNum[1] = 0; + *RssiAvg = realavgrssi - 256; +} +#if defined(MAX_CONTINUOUS_TX_CNT) || defined(NEW_IXIA_METHOD) +BOOLEAN Rtmp_Max_Continuous_Tx_OnOff(RTMP_ADAPTER *pAd) +{ + PMAC_TABLE_ENTRY pEntry = NULL; + INT i; + CHAR MaxRssi = -127,MinRssi = -127,myAvgRssi = -127; //for RSSI + ULONG DataRate=0; //for datarate. + for (i=0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + pEntry = &pAd->MacTab.Content[i]; + if (!(IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC))) + continue; + myAvgRssi = RTMPAvgRssi(pAd, &pEntry->RssiSample);// get my rssi average. + getRate(pEntry->HTPhyMode, &DataRate); + + if(DataRate < pAd->RateTh) + { + DBGPRINT(RT_DEBUG_WARN,("%s(%d)Some sta's rate is low. DataRate = %lu\n",__FUNCTION__,__LINE__,DataRate)); + return FALSE; + } + if((MaxRssi == -127) && (MinRssi == -127)) + { + MaxRssi= myAvgRssi; + MinRssi = myAvgRssi; + } + else + { + MaxRssi = RTMPMaxRssi(pAd,MaxRssi,myAvgRssi,0);// find the max rssi in mactable size. + MinRssi = RTMPMinRssi(pAd,MinRssi,myAvgRssi,0);// find the min rssi in mactable size. + } + + } + DBGPRINT(RT_DEBUG_WARN,("%s(%d)MaxRssi = %-3d,MinRssi = %-3d\n",__FUNCTION__,__LINE__,MaxRssi,MinRssi)); + if((MaxRssi - MinRssi) < pAd->DeltaRssiTh) /*pAd->DeltaRssiTh default 10 dBm*/ + { + DBGPRINT(RT_DEBUG_WARN,("%s(%d) in in in in in in \n",__FUNCTION__,__LINE__)); + return TRUE; + } + else + return FALSE; +} + +VOID rtmp_deqmode_detect(RTMP_ADAPTER *pAd) +{ + if(pAd->MacTab.Size >=5) + { + DBGPRINT(RT_DEBUG_WARN,("%s(%d) MacTab.Size = %d\n",__FUNCTION__,__LINE__,pAd->MacTab.Size)); + if(Rtmp_Max_Continuous_Tx_OnOff(pAd) == TRUE) + { + pAd->ContinousTxCnt = CONTINUOUS_TX_CNT;/*set tx 21 packets one time*/ + DBGPRINT(RT_DEBUG_WARN,("%s(%d)Countinous to Tx %d Packets\n",__FUNCTION__,__LINE__,pAd->ContinousTxCnt)); + } + else + { + pAd->ContinousTxCnt = 1; /*default tx 1 packet one time*/ + DBGPRINT(RT_DEBUG_WARN,("%s(%d)tx 1 packet!\n",__FUNCTION__,__LINE__)); + } + } + else + { + DBGPRINT(RT_DEBUG_WARN,("%s(%d)client num = %d\n",__FUNCTION__,__LINE__, pAd->MacTab.Size)); + pAd->ContinousTxCnt = 1; /*default tx 1 packet one time*/ + } +} +#endif + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_nintendo.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_nintendo.c new file mode 100644 index 000000000..8406434d3 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_nintendo.c @@ -0,0 +1,31 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering 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" + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_nps.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_nps.c new file mode 100644 index 000000000..9bbda26fe --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_nps.c @@ -0,0 +1,309 @@ +/**************************************************************************** + * 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_nps.c + + Abstract: + IEEE 802.11v NPS SoftAP related function + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Carter Chen 08-23-2013 created for 7603 AP + */ +#ifdef MT_MAC + +#include "rt_config.h" + +extern VOID write_tmac_info_tim(RTMP_ADAPTER *pAd, INT apidx, UCHAR *tmac_buf, HTTRANSMIT_SETTING *BeaconTransmit, ULONG frmLen); + +BOOLEAN TimTransmitRequired(RTMP_ADAPTER *pAd, INT apidx, BSS_STRUCT *pMbss) +{ + BOOLEAN result = FALSE; + TIM_BUF_STRUC *tim_info; + + tim_info = &pMbss->tim_buf; + if (tim_info->TimBufIdx >= HW_BEACON_MAX_NUM) + return result; + + if (tim_info->bTimSntReq == TRUE) + { + result = TRUE; + } + + return result; +} + +#ifdef MT_MAC +VOID RT28xx_UpdateTimToAsic( + IN RTMP_ADAPTER *pAd, + IN INT apidx, + IN ULONG FrameLen) +{ + TIM_BUF_STRUC *tim_buf = NULL; + UCHAR *buf; + INT len; + PNDIS_PACKET *pkt = NULL; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { + tim_buf = &pAd->ApCfg.MBSSID[apidx].tim_buf; + } + + if (!tim_buf) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): bcn_buf is NULL!\n", __FUNCTION__)); + return; + } + + pkt = tim_buf->TimPkt; + if (pkt) { + buf = (UCHAR *)GET_OS_PKT_DATAPTR(pkt); + len = FrameLen + pAd->chipCap.tx_hw_hdr_len; + SET_OS_PKT_LEN(pkt, len); + + /* Now do hardware-depened kick out.*/ + RTMP_SEM_LOCK(&pAd->BcnRingLock); + HAL_KickOutMgmtTx(pAd, Q_IDX_BCN, pkt, buf, len); + RTMP_SEM_UNLOCK(&pAd->BcnRingLock); + } else { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): TimPkt is NULL!\n", __FUNCTION__)); + } +} + +#endif /* MT_MAC */ + +VOID write_tmac_info_tim(RTMP_ADAPTER *pAd, INT apidx, UCHAR *tmac_buf, HTTRANSMIT_SETTING *BeaconTransmit, ULONG frmLen) +{ + MAC_TX_INFO mac_info; + + NdisZeroMemory((UCHAR *)&mac_info, sizeof(mac_info)); + + mac_info.FRAG = FALSE; + mac_info.CFACK = FALSE; + mac_info.InsTimestamp = FALSE; + mac_info.AMPDU = FALSE; + mac_info.BM = 1; + mac_info.Ack = FALSE; + mac_info.NSeq = TRUE; + mac_info.BASize = 0; + mac_info.WCID = 0; + mac_info.Length = frmLen; + mac_info.PID = PID_MGMT; + mac_info.TID = 0; + mac_info.TxRate = 0; + mac_info.Txopmode = IFS_HTTXOP; + mac_info.q_idx = Q_IDX_BCN; + mac_info.hdr_len = 24; + mac_info.bss_idx = apidx; + mac_info.SpeEn = 1; + mac_info.Preamble = LONG_PREAMBLE; + write_tmac_info(pAd, tmac_buf, &mac_info, BeaconTransmit); +} + +VOID APMakeBssTimFrame(RTMP_ADAPTER *pAd, INT apidx) +{ + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; + HEADER_802_11 TimHdr; + LARGE_INTEGER FakeTimestamp; + ULONG FrameLen = 0; + UCHAR *pTimFrame, *ptr, *tmac_info; + HTTRANSMIT_SETTING TimTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at HT rate. */ + //UINT8 TXWISize = pAd->chipCap.TXWISize; + UINT8 tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len; + UCHAR Cat = 11;//Tim Category field + UCHAR Act = 0;//Tim Action field + UCHAR ChkBcn = 0;//Check Beacon field init from 0. + //UCHAR *pTim; + //UCHAR ID_1B, TimFirst, TimLast; + //UINT i; + + if(!TimTransmitRequired(pAd, apidx, pMbss)) + return; + + if (pMbss->tim_buf.TimPkt == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Invalid TimPkt for MBSS[%d]\n", + __func__, apidx)); + return; + } + + tmac_info = (UCHAR *)GET_OS_PKT_DATAPTR(pMbss->tim_buf.TimPkt); + pTimFrame = (UCHAR *)(tmac_info + tx_hw_hdr_len); + + ActHeaderInit(pAd, + &TimHdr, + BROADCAST_ADDR, + pMbss->wdev.if_addr, + pMbss->wdev.bssid); + + + MakeOutgoingFrame(pTimFrame, &FrameLen, + sizeof(HEADER_802_11), &TimHdr, + 1, &Cat, + 1, &Act, + 1, &ChkBcn, + TIMESTAMP_LEN, &FakeTimestamp, + END_OF_ARGS); + + TimTransmit.word = 0; + + pMbss->TimIELocationInTim = (UCHAR)FrameLen; + + /* + 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 = pTimFrame + (UCHAR)FrameLen; + *ptr = IE_TIM; + *(ptr+1) = 0x0e; + *(ptr + 2) = pAd->ApCfg.DtimCount; + *(ptr + 3) = pAd->ApCfg.DtimPeriod; + + *(ptr + 4) = 0xa0; + *(ptr + 5) = 0xa0; + *(ptr + 6) = 0xa0; + *(ptr + 7) = 0xa0; + *(ptr + 8) = 0xa0; + *(ptr + 9) = 0xa0; + *(ptr + 10) = 0xa0; + *(ptr + 11) = 0xa0; + *(ptr + 12) = 0xa0; + *(ptr + 13) = 0xa0; + *(ptr + 14) = 0xa0; + *(ptr + 15) = 0xa0; + + +// /* 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); +// *(ptr + 4) = 0; + + /* adjust TIM length according to the new TIM */ + FrameLen += 16;//(2 + *(ptr+1)); + + /* When Beacon is use CCK to send, TIM shall use OFDM to send. and it's mandatory. */ + if (pAd->CommonCfg.Channel <= 14) { + TimTransmit.field.MODE = MODE_OFDM; + TimTransmit.field.MCS = MCS_RATE_6; + } + + write_tmac_info_tim(pAd, apidx, tmac_info, &TimTransmit, FrameLen); + +// asic_write_bcn_buf(pAd, +// tmac_info, TXWISize, +// pTimFrame, FrameLen, +// pAd->BeaconOffset[pMbss->bcn_buf.BcnBufIdx]); + + RT28xx_UpdateTimToAsic(pAd, apidx, FrameLen); + +//+++Add by shiang for debug + DBGPRINT(RT_DEBUG_OFF, ("%s(): Dump the Beacon Packet of BSS%d!\n", __FUNCTION__, apidx)); + hex_dump("Initial BeaconBuf", tmac_info, FrameLen + tx_hw_hdr_len); +//---Add by shiang for debug +} + +static UCHAR GetTimNum(RTMP_ADAPTER *pAd) +{ + int i; + int NumTim; + TIM_BUF_STRUC *tim_info; + + NumTim = 0; + for (i=0; iApCfg.BssidNum; i++) + { + tim_info = &pAd->ApCfg.MBSSID[i].tim_buf; + if (tim_info->bTimSntReq) + { + tim_info->TimBufIdx = NumTim; + NumTim ++; + } + } + + return NumTim; +} + +VOID APMakeAllTimFrame(RTMP_ADAPTER *pAd) +{ + INT i; + //UCHAR NumOfTims; + + /* choose the Beacon number */ + /*NumOfTims =*/ GetTimNum(pAd); + + for(i=0; iApCfg.BssidNum; i++) { + APMakeBssTimFrame(pAd, i); +// APMakeBssTimFrame2(pAd, i);//Carter, for test tttt 2 pkt purpose + } +} + +INT wdev_tim_buf_init(RTMP_ADAPTER *pAd, TIM_BUF_STRUC *tim_info) +{ + //bcn_info->bBcnSntReq = FALSE; + tim_info->TimBufIdx = HW_BEACON_MAX_NUM; + + if (!tim_info->TimPkt) { + RTMPAllocateNdisPacket(pAd, &tim_info->TimPkt, NULL, 0, NULL, MAX_TIM_SIZE); + //NdisAllocateSpinLock(pAd, &bcn_info->bcn_lock); + } else { + DBGPRINT(RT_DEBUG_OFF, ("%s():TimPkt is allocated!\n", __func__)); + + } +// if (!tim_info->TimPkt2) { +// RTMPAllocateNdisPacket(pAd, &tim_info->TimPkt2, NULL, NULL, NULL, MAX_TIM_SIZE); + //NdisAllocateSpinLock(pAd, &bcn_info->bcn_lock); +// } else { +// DBGPRINT(RT_DEBUG_OFF, ("%s():TimPkt2 is allocated!\n", __func__)); + //} + tim_info->bTimSntReq = TRUE; + + return TRUE; +} + + +#endif /* MT_MAC */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_qload.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_qload.c new file mode 100644 index 000000000..c658fecd0 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_qload.c @@ -0,0 +1,923 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + + Abstract: + + Provide information on the current STA population and traffic levels + in the QBSS. + + This attribute is available only at a QAP. This attribute, when TRUE, + indicates that the QAP implementation is capable of generating and + transmitting the QBSS load element in the Beacon and Probe Response frames. + +***************************************************************************/ + +#include "rt_config.h" + +#ifdef AP_QLOAD_SUPPORT + +typedef struct GNU_PACKED _ELM_QBSS_LOAD{ + + UINT8 ElementId; + UINT8 Length; + + /* the total number of STAs currently associated with this QBSS */ + UINT16 StationCount; + + /* defined as the percentage of time, nomalized to 255, the QAP sensed the + medium busy, as indicated by either the physical or virtual carrier + sense mechanism. + This percentage is computed using the formula: + ((channel busy time / (dot11ChannelUtilizationBeaconIntervals * + dot11BeaconPeriod * 1024)) * 255) */ + UINT8 ChanUtil; + + /* specifies the remaining amount of medium time available via explicit + admission control, in units of 32 microsecond periods per 1 second. + The field is helpful for roaming non-AP QSTAs to select a QAP that is + likely to accept future admission control requests, but it does not + represent a guarantee that the HC will admit these requests. */ + UINT16 AvalAdmCap; + +} ELM_QBSS_LOAD; + +#define ELM_QBSS_LOAD_ID 11 +#define ELM_QBSS_LOAD_LEN 5 + +/* + We will send a alarm when channel busy time (primary or secondary) >= + Time Threshold and Num Threshold. + + QBSS_LOAD_ALRAM_BUSY_TIME_THRESHOLD = 0 means alarm function is disabled. + + If you want to enable it, use command + "iwpriv ra0 set qloadalarmtimethres=90" +*/ +#define QBSS_LOAD_ALRAM_BUSY_TIME_THRESHOLD 0 /* unit: % */ +#define QBSS_LOAD_ALRAM_BUSY_NUM_THRESHOLD 10 /* unit: 1 */ + +/* a alarm will not re-issued until QBSS_LOAD_ALARM_DURATION * TBTT */ +#define QBSS_LOAD_ALARM_DURATION 100 /* unit: TBTT */ + + +static VOID QBSS_LoadAlarmSuspend( + IN RTMP_ADAPTER *pAd); + +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM +/* handle a alarm */ +static VOID QBSS_LoadAlarm( + IN RTMP_ADAPTER *pAd); +static VOID QBSS_LoadAlarmBusyTimeThresholdReset( + IN RTMP_ADAPTER *pAd, + IN UINT32 TimePeriod); +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ + + + + +/* --------------------------------- Private -------------------------------- */ + +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM +/* +======================================================================== +Routine Description: + Handle a alarm. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + You can use different methods to handle QBSS Load alarm here. + + Current methods are: + 1. Change 20/40 to 20-only. + 2. Change channel to the clear channel. +======================================================================== +*/ +static VOID QBSS_LoadAlarm( + IN RTMP_ADAPTER *pAd) +{ + /* suspend alarm until channel switch */ + QBSS_LoadAlarmSuspend(pAd); + + pAd->phy_ctrl.QloadAlarmNumber ++; + + /* check if we have already been 20M bandwidth */ +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if ((pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset != 0) && + (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth != 0)) + { + MAC_TABLE *pMacTable; + UINT32 StaId; + + + DBGPRINT(RT_DEBUG_TRACE, ("qbss> Alarm! Change to 20 bw...\n")); + + /* disassociate stations without D3 2040Coexistence function */ + pMacTable = &pAd->MacTab; + + for(StaId=1; StaIdContent[StaId]; + BOOLEAN bDisconnectSta = FALSE; + + if (!IS_ENTRY_CLIENT(pEntry)) + continue; + + if (pEntry->Sst != SST_ASSOC) + continue; + + if (pEntry->BSS2040CoexistenceMgmtSupport) + bDisconnectSta = TRUE; + + if (bDisconnectSta) + { + /* send wireless event - for ageout */ + RTMPSendWirelessEvent(pAd, IW_AGEOUT_EVENT_FLAG, pEntry->Addr, 0, 0); + + { + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + HEADER_802_11 DeAuthHdr; + USHORT Reason; + + /* send out a DISASSOC request frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, (" MlmeAllocateMemory fail ..\n")); + /*NdisReleaseSpinLock(&pAd->MacTabLock); */ + continue; + } + + Reason = REASON_DEAUTH_STA_LEAVING; + MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0, + pEntry->Addr, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.if_addr, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DeAuthHdr, + 2, &Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + + DBGPRINT(RT_DEBUG_TRACE, ("qbss> Alarm! Deauth the station " + "%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pEntry->Addr))); + + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + continue; + } + } + + /* for 11n */ + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = 0; + + /* always 20M */ + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + + /* mark alarm flag */ + pAd->phy_ctrl.FlgQloadAlarm = TRUE; + + QBSS_LoadAlarmResume(pAd); + } + else +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + { + /* we are in 20MHz bandwidth so try to switch channel */ + DBGPRINT(RT_DEBUG_TRACE, ("qbss> Alarm! Switch channel...\n")); + + /* send command to switch channel */ + RTEnqueueInternalCmd(pAd, CMDTHREAD_CHAN_RESCAN, NULL, 0); + } +} + + +/* +======================================================================== +Routine Description: + Re-calculate busy time threshold. + +Arguments: + pAd - WLAN control block pointer + TimePeriod - TBTT + +Return Value: + None + +Note: + EX: TBTT=100ms, 90%, pAd->QloadBusyTimeThreshold = 90ms +======================================================================== +*/ +static VOID QBSS_LoadAlarmBusyTimeThresholdReset( + IN RTMP_ADAPTER *pAd, + IN UINT32 TimePeriod) +{ + pAd->phy_ctrl.QloadBusyTimeThreshold = TimePeriod; + pAd->phy_ctrl.QloadBusyTimeThreshold *= pAd->phy_ctrl.QloadAlarmBusyTimeThreshold; + pAd->phy_ctrl.QloadBusyTimeThreshold /= 100; + pAd->phy_ctrl.QloadBusyTimeThreshold <<= 10; /* translate mini-sec to micro-sec */ +} +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ + + +/* +======================================================================== +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(RTMP_ADAPTER *pAd) +{ + UINT32 IdBss; + + + /* check whether any BSS enables WMM feature */ + for(IdBss=0; IdBssApCfg.BssidNum; IdBss++) + { + if ((pAd->ApCfg.MBSSID[IdBss].wdev.bWmmCapable) +#ifdef DOT11K_RRM_SUPPORT + || (IS_RRM_ENABLE(pAd, IdBss)) +#endif /* DOT11K_RRM_SUPPORT */ + ) + { + pAd->phy_ctrl.FlgQloadEnable = TRUE; + break; + } + } + + if (pAd->phy_ctrl.FlgQloadEnable == TRUE) + { + /* default value is 50, please reference to IEEE802.11e 2005 Annex D */ + pAd->phy_ctrl.QloadChanUtilBeaconInt = 50; + } + AsicSetChBusyStat(pAd, pAd->phy_ctrl.FlgQloadEnable); + + pAd->phy_ctrl.QloadChanUtilTotal = 0; + pAd->phy_ctrl.QloadUpTimeLast = 0; + +#ifdef QLOAD_FUNC_BUSY_TIME_STATS + /* clear busy time statistics */ + NdisZeroMemory(pAd->phy_ctrl.QloadBusyCountPri, sizeof(pAd->phy_ctrl.QloadBusyCountPri)); + NdisZeroMemory(pAd->phy_ctrl.QloadBusyCountSec, sizeof(pAd->phy_ctrl.QloadBusyCountSec)); +#endif /* QLOAD_FUNC_BUSY_TIME_STATS */ + +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + /* init threshold before QBSS_LoadAlarmReset */ + pAd->phy_ctrl.QloadAlarmBusyTimeThreshold = QBSS_LOAD_ALRAM_BUSY_TIME_THRESHOLD; + pAd->phy_ctrl.QloadAlarmBusyNumThreshold = QBSS_LOAD_ALRAM_BUSY_NUM_THRESHOLD; + + QBSS_LoadAlarmReset(pAd); +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ +} + + +/* +======================================================================== +Routine Description: + Reset alarm function. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID QBSS_LoadAlarmReset( + IN RTMP_ADAPTER *pAd) +{ +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + pAd->phy_ctrl.FlgQloadAlarm = FALSE; + pAd->phy_ctrl.QloadAlarmDuration = 0; + pAd->phy_ctrl.QloadAlarmNumber = 0; + + pAd->phy_ctrl.FlgQloadAlarmIsSuspended = FALSE; + + QBSS_LoadAlarmBusyTimeThresholdReset(pAd, pAd->CommonCfg.BeaconPeriod); +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ +} + + +/* +======================================================================== +Routine Description: + Resume alarm function. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID QBSS_LoadAlarmResume( + IN RTMP_ADAPTER *pAd) +{ +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + pAd->phy_ctrl.FlgQloadAlarmIsSuspended = FALSE; +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ +} + + +/* +======================================================================== +Routine Description: + Suspend alarm function. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID QBSS_LoadAlarmSuspend( + IN RTMP_ADAPTER *pAd) +{ +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + pAd->phy_ctrl.FlgQloadAlarmIsSuspended = TRUE; +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ +} + + +/* +======================================================================== +Routine Description: + Get average busy time in current channel. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + average busy time + +Note: +======================================================================== +*/ +UINT32 QBSS_LoadBusyTimeGet( + IN RTMP_ADAPTER *pAd) +{ + if (pAd->phy_ctrl.QloadChanUtilBeaconCnt == 0) + return pAd->phy_ctrl.QloadChanUtilTotal; + + return (pAd->phy_ctrl.QloadChanUtilTotal / pAd->phy_ctrl.QloadChanUtilBeaconCnt); +} + + +/* +======================================================================== +Routine Description: + Check if a alarm is occurred and clear the alarm. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + TRUE - alarm occurs + FALSE - no alarm + +Note: + We will clear the alarm in the function. +======================================================================== +*/ +BOOLEAN QBSS_LoadIsAlarmIssued( + IN RTMP_ADAPTER *pAd) +{ +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + BOOLEAN FlgQloadAlarm = pAd->phy_ctrl.FlgQloadAlarm; + + pAd->phy_ctrl.FlgQloadAlarm = FALSE; + return FlgQloadAlarm; +#else + + return FALSE; +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ +} + + +/* +======================================================================== +Routine Description: + Check if the busy time is accepted. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + TURE - ok + FALSE - fail + +Note: +======================================================================== +*/ +BOOLEAN QBSS_LoadIsBusyTimeAccepted( + IN RTMP_ADAPTER *pAd, + IN UINT32 BusyTime) +{ +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + if (pAd->phy_ctrl.QloadAlarmBusyTimeThreshold == 0) + return TRUE; /* always ok */ + + if (BusyTime >= pAd->phy_ctrl.QloadBusyTimeThreshold) + return FALSE; +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ + + return TRUE; +} + +#ifdef CONFIG_HOTSPOT_R2 +UINT32 QBSS_LoadElementAppend_HSTEST( + IN RTMP_ADAPTER *pAd, + OUT UINT8 *pBeaconBuf, + IN UCHAR apidx) +{ + ELM_QBSS_LOAD load, *pLoad = &load; + ULONG ElmLen; + + /* check whether channel busy time calculation is enabled */ + if (pAd->phy_ctrl.FlgQloadEnable == 0) + return 0; + /* End of if */ + + /* init */ + pLoad->ElementId = ELM_QBSS_LOAD_ID; + pLoad->Length = ELM_QBSS_LOAD_LEN; + + pLoad->StationCount = le2cpu16(pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.QLoadStaCnt); + pLoad->ChanUtil = pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.QLoadCU; + + /* because no ACM is supported, the available bandwidth is 1 sec */ + pLoad->AvalAdmCap = le2cpu16(0xffff); /* 0x7a12 * 32us = 1 second */ + + + /* copy the element to the frame */ + MakeOutgoingFrame(pBeaconBuf, &ElmLen, + sizeof(ELM_QBSS_LOAD), pLoad, + END_OF_ARGS); + + return ElmLen; +} /* End of QBSS_LoadElementAppend */ +#endif + +/* +======================================================================== +Routine Description: + Append the QBSS Load element to the beacon frame. + +Arguments: + pAd - WLAN control block pointer + *pBeaconBuf - the beacon or probe response frame + +Return Value: + the element total Length + +Note: + Append Condition: You must check whether WMM is enabled before the + function is using. +======================================================================== +*/ +UINT32 QBSS_LoadElementAppend(RTMP_ADAPTER *pAd, UINT8 *pBeaconBuf) +{ + ELM_QBSS_LOAD load, *pLoad = &load; + ULONG ElmLen; + + + /* check whether channel busy time calculation is enabled */ + if (pAd->phy_ctrl.FlgQloadEnable == 0) + return 0; + + /* init */ + pLoad->ElementId = ELM_QBSS_LOAD_ID; + pLoad->Length = ELM_QBSS_LOAD_LEN; + + pLoad->StationCount = le2cpu16(MacTableAssocStaNumGet(pAd)); + pLoad->ChanUtil = pAd->phy_ctrl.QloadChanUtil; + + /* because no ACM is supported, the available bandwidth is 1 sec */ + pLoad->AvalAdmCap = le2cpu16(0x7a12); /* 0x7a12 * 32us = 1 second */ + + + /* copy the element to the frame */ + MakeOutgoingFrame(pBeaconBuf, &ElmLen, + sizeof(ELM_QBSS_LOAD), pLoad, + END_OF_ARGS); + + return ElmLen; +} + + +/* +======================================================================== +Routine Description: + Update Channel Utilization. + +Arguments: + pAd - WLAN control block pointer + UpTime - current up time + +Return Value: + None + +Note: + UpTime is used in QLOAD_FUNC_BUSY_TIME_STATS & QLOAD_FUNC_BUSY_TIME_ALARM + + If UpTime != 0, it means that the time period calling the function + maybe not TBTT so we need to re-calculate the time period. + + If you call the function in kernel thread, the time period sometimes + will not accurate due to kernel thread is not real-time, so we need to + recalculate the time period. +======================================================================== +*/ +VOID QBSS_LoadUpdate( + IN RTMP_ADAPTER *pAd, + IN ULONG UpTime) +{ + UINT32 ChanUtilNu, ChanUtilDe; + UINT32 BusyTime = 0; + UINT32 BusyTimeId; + UINT32 TimePeriod = pAd->CommonCfg.BeaconPeriod; +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + BOOLEAN FlgIsBusyOverThreshold = FALSE; + BOOLEAN FlgIsAlarmNeeded = FALSE; +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ + + + /* check whether channel busy time calculation is enabled */ + if ((pAd->phy_ctrl.FlgQloadEnable == 0) || + (pAd->phy_ctrl.FlgQloadAlarmIsSuspended == TRUE)) + return; + + /* calculate new time period if needed */ + if ((UpTime > 0) && + (pAd->phy_ctrl.QloadUpTimeLast > 0) && + (UpTime > pAd->phy_ctrl.QloadUpTimeLast)) + { + /* re-calculate time period */ + TimePeriod = (UINT32)(UpTime - pAd->phy_ctrl.QloadUpTimeLast); + + /* translate to mini-second */ + TimePeriod = (TimePeriod*1000)/OS_HZ; + +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + /* re-calculate QloadBusyTimeThreshold */ + if (TimePeriod != pAd->phy_ctrl.QloadTimePeriodLast) + QBSS_LoadAlarmBusyTimeThresholdReset(pAd, TimePeriod); + + pAd->phy_ctrl.QloadTimePeriodLast = TimePeriod; +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ + } + + /* update up time */ + pAd->phy_ctrl.QloadUpTimeLast = UpTime; + + /* do busy time statistics */ +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset != 0) && + (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth != 0)) + { + /* in 20MHz, no need to check busy time of secondary channel */ + BusyTime = AsicGetChBusyCnt(pAd, 1); + pAd->phy_ctrl.QloadLatestChannelBusyTimeSec = BusyTime; + +#ifdef QLOAD_FUNC_BUSY_TIME_STATS + BusyTimeId = BusyTime >> 10; /* translate us to ms */ + + /* ex:95ms, 95*20/100 = 19 */ + BusyTimeId = (BusyTimeId*QLOAD_BUSY_INTERVALS)/TimePeriod; + + if (BusyTimeId >= QLOAD_BUSY_INTERVALS) + BusyTimeId = QLOAD_BUSY_INTERVALS - 1; + + pAd->phy_ctrl.QloadBusyCountSec[BusyTimeId] ++; +#endif /* QLOAD_FUNC_BUSY_TIME_STATS */ + +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + if ((pAd->phy_ctrl.FlgQloadAlarmIsSuspended == FALSE) && + (pAd->phy_ctrl.QloadAlarmBusyTimeThreshold > 0)) + { + /* Alarm is not suspended and is enabled */ + + if ((pAd->phy_ctrl.QloadBusyTimeThreshold != 0) && + (BusyTime >= pAd->phy_ctrl.QloadBusyTimeThreshold)) + { + FlgIsBusyOverThreshold = TRUE; + } + } +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ + } +#endif /* DOT11_N_SUPPORT */ + + /* do busy time statistics for primary channel */ + BusyTime = AsicGetChBusyCnt(pAd, 0); + pAd->phy_ctrl.QloadLatestChannelBusyTimePri = BusyTime; + +#ifdef QLOAD_FUNC_BUSY_TIME_STATS + BusyTimeId = BusyTime >> 10; /* translate us to ms */ + + /* ex:95ms, 95*20/100 = 19 */ + BusyTimeId = (BusyTimeId*QLOAD_BUSY_INTERVALS)/TimePeriod; + + if (BusyTimeId >= QLOAD_BUSY_INTERVALS) + BusyTimeId = QLOAD_BUSY_INTERVALS - 1; + + pAd->phy_ctrl.QloadBusyCountPri[BusyTimeId] ++; +#endif /* QLOAD_FUNC_BUSY_TIME_STATS */ + +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + if ((pAd->phy_ctrl.FlgQloadAlarmIsSuspended == FALSE) && + (pAd->phy_ctrl.QloadAlarmBusyTimeThreshold > 0)) + { + /* Alarm is not suspended and is enabled */ + + if ((pAd->phy_ctrl.QloadBusyTimeThreshold != 0) && + (BusyTime >= pAd->phy_ctrl.QloadBusyTimeThreshold)) + { + FlgIsBusyOverThreshold = TRUE; + } + } +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ + + /* accumulate channel busy time for primary channel */ + pAd->phy_ctrl.QloadChanUtilTotal += BusyTime; + + /* update new channel utilization for primary channel */ + if (++pAd->phy_ctrl.QloadChanUtilBeaconCnt >= pAd->phy_ctrl.QloadChanUtilBeaconInt) + { + ChanUtilNu = pAd->phy_ctrl.QloadChanUtilTotal; + ChanUtilNu *= 255; + + ChanUtilDe = pAd->phy_ctrl.QloadChanUtilBeaconInt; + + /* + Still use pAd->CommonCfg.BeaconPeriod. + Because we change QloadChanUtil not every TBTT. + */ + ChanUtilDe *= pAd->CommonCfg.BeaconPeriod; + + ChanUtilDe <<= 10; /* ms to us */ + + pAd->phy_ctrl.QloadChanUtil = (UINT8)(ChanUtilNu/ChanUtilDe); + + /* re-accumulate channel busy time */ + pAd->phy_ctrl.QloadChanUtilBeaconCnt = 0; + pAd->phy_ctrl.QloadChanUtilTotal = 0; + } + +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + /* check if alarm function is enabled */ + if ((pAd->phy_ctrl.FlgQloadAlarmIsSuspended == FALSE) && + (pAd->phy_ctrl.QloadAlarmBusyTimeThreshold > 0)) + { + /* Alarm is not suspended and is enabled */ + + /* check if we need to issue a alarm */ + if (FlgIsBusyOverThreshold == TRUE) + { + if (pAd->phy_ctrl.QloadAlarmDuration == 0) + { + /* last alarm ended so we can check new alarm */ + + pAd->phy_ctrl.QloadAlarmBusyNum ++; + + if (pAd->phy_ctrl.QloadAlarmBusyNum >= pAd->phy_ctrl.QloadAlarmBusyNumThreshold) + { + /* + The continued number of busy time >= threshold is larger + than number threshold so issuing a alarm. + */ + FlgIsAlarmNeeded = TRUE; + pAd->phy_ctrl.QloadAlarmDuration ++; + } + } + } + else + pAd->phy_ctrl.QloadAlarmBusyNum = 0; + + if (pAd->phy_ctrl.QloadAlarmDuration > 0) + { + /* + New alarm occurs so we can not re-issue new alarm during + QBSS_LOAD_ALARM_DURATION * TBTT. + */ + if (++pAd->phy_ctrl.QloadAlarmDuration >= QBSS_LOAD_ALARM_DURATION) + { + /* can re-issue next alarm */ + pAd->phy_ctrl.QloadAlarmDuration = 0; + pAd->phy_ctrl.QloadAlarmBusyNum = 0; + } + } + + if (FlgIsAlarmNeeded == TRUE) + QBSS_LoadAlarm(pAd); + } + else + { + /* clear statistics counts */ + pAd->phy_ctrl.QloadAlarmBusyNum = 0; + pAd->phy_ctrl.QloadAlarmDuration = 0; + pAd->phy_ctrl.FlgQloadAlarm = FALSE; + } +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ +} + + +/* +======================================================================== +Routine Description: + Clear QoS Load information. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID QBSS_LoadStatusClear( + IN RTMP_ADAPTER *pAd) +{ +#ifdef QLOAD_FUNC_BUSY_TIME_STATS + /* clear busy time statistics */ + NdisZeroMemory(pAd->phy_ctrl.QloadBusyCountPri, sizeof(pAd->phy_ctrl.QloadBusyCountPri)); + NdisZeroMemory(pAd->phy_ctrl.QloadBusyCountSec, sizeof(pAd->phy_ctrl.QloadBusyCountSec)); +#endif /* QLOAD_FUNC_BUSY_TIME_STATS */ + +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + /* clear alarm function variables */ + pAd->phy_ctrl.QloadChanUtilTotal = 0; + pAd->phy_ctrl.FlgQloadAlarm = FALSE; + pAd->phy_ctrl.QloadAlarmBusyNum = 0; +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ +} + + +/* +======================================================================== +Routine Description: + Show QoS Load information. + +Arguments: + pAd - WLAN control block pointer + Arg - Input arguments + +Return Value: + None + +Note: +======================================================================== +*/ +INT Show_QoSLoad_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ +#ifdef QLOAD_FUNC_BUSY_TIME_STATS + UINT32 BusyTimeId; +#ifdef DBG + UINT32 Time; + Time = pAd->CommonCfg.BeaconPeriod / QLOAD_BUSY_INTERVALS; +#endif /* DBG */ + DBGPRINT(RT_DEBUG_OFF, ("\n\tPrimary Busy Time\tTimes\n")); + + for(BusyTimeId=0; BusyTimeIdphy_ctrl.QloadBusyCountPri[BusyTimeId])); + } + + DBGPRINT(RT_DEBUG_OFF, ("\n\tSecondary Busy Time\tTimes\n")); + + for(BusyTimeId=0; BusyTimeIdphy_ctrl.QloadBusyCountSec[BusyTimeId])); + } +#else + + DBGPRINT(RT_DEBUG_OFF, ("\tBusy time statistics is not included into the driver!\n")); +#endif /* QLOAD_FUNC_BUSY_TIME_STATS */ + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Command for QoS Load information clear. + +Arguments: + pAd - WLAN control block pointer + Arg - Input arguments + +Return Value: + None + +Note: +======================================================================== +*/ +INT Set_QloadClr_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + QBSS_LoadStatusClear(pAd); + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Command for QoS Alarm Time Threshold set. + +Arguments: + pAd - WLAN control block pointer + Arg - Input arguments + +Return Value: + None + +Note: +======================================================================== +*/ +INT Set_QloadAlarmTimeThreshold_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + pAd->phy_ctrl.QloadAlarmBusyTimeThreshold = (UCHAR)simple_strtol(Arg, 0, 10); + + QBSS_LoadAlarmReset(pAd); + + pAd->phy_ctrl.QloadTimePeriodLast = pAd->CommonCfg.BeaconPeriod; +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ + + return TRUE; +} + + +/* +======================================================================== +Routine Description: + Command for QoS Alarm Number Threshold set. + +Arguments: + pAd - WLAN control block pointer + Arg - Input arguments + +Return Value: + None + +Note: +======================================================================== +*/ +INT Set_QloadAlarmNumThreshold_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ +#ifdef QLOAD_FUNC_BUSY_TIME_ALARM + pAd->phy_ctrl.QloadAlarmBusyNumThreshold = (UCHAR)simple_strtol(Arg, 0, 10); +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ + + return TRUE; +} + +#endif /* AP_QLOAD_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_repeater.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_repeater.c new file mode 100644 index 000000000..71c6d3a8d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_repeater.c @@ -0,0 +1,1027 @@ +/* + *************************************************************************** + * 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" + + +REPEATER_CLIENT_ENTRY *RTMPLookupRepeaterCliEntry( + IN PVOID pData, + IN BOOLEAN bRealMAC, + IN PUCHAR pAddr, + IN BOOLEAN bIsPad, + OUT PUCHAR pIsLinkValid) +{ + ULONG HashIdx; + UCHAR tempMAC[6]; + REPEATER_CLIENT_ENTRY *pEntry = NULL; + REPEATER_CLIENT_ENTRY_MAP *pMapEntry = NULL; + *pIsLinkValid = TRUE; + + if (bIsPad == TRUE) { + NdisAcquireSpinLock(&((PRTMP_ADAPTER)pData)->ApCfg.ReptCliEntryLock); + } else { + NdisAcquireSpinLock(((REPEATER_ADAPTER_DATA_TABLE *)pData)->EntryLock); + } + + COPY_MAC_ADDR(tempMAC, pAddr); + HashIdx = MAC_ADDR_HASH_INDEX(tempMAC); + + if (bRealMAC == TRUE) + { + if (bIsPad == TRUE) { + pMapEntry = ((PRTMP_ADAPTER)pData)->ApCfg.ReptMapHash[HashIdx]; + } else + pMapEntry = (REPEATER_CLIENT_ENTRY_MAP *)(*((((REPEATER_ADAPTER_DATA_TABLE *)pData)->MapHash) + + HashIdx)); + + while (pMapEntry) + { + pEntry = pMapEntry->pReptCliEntry; + + if (pEntry && MAC_ADDR_EQUAL(pEntry->OriginalAddress, tempMAC)) + { + if (pEntry->CliValid == FALSE) { + *pIsLinkValid = FALSE; + pEntry = NULL; + } + + break; + } + else + { + pEntry = NULL; + pMapEntry = pMapEntry->pNext; + } + } + } + else + { + if (bIsPad == TRUE) { + pEntry = ((PRTMP_ADAPTER)pData)->ApCfg.ReptCliHash[HashIdx]; + } else { + pEntry = (REPEATER_CLIENT_ENTRY *)(*((((REPEATER_ADAPTER_DATA_TABLE*)pData)->CliHash) + + HashIdx)); + } + + + while (pEntry) + { + if (MAC_ADDR_EQUAL(pEntry->CurrentAddress, tempMAC)) + { + if (pEntry->CliValid == FALSE) { + *pIsLinkValid = FALSE; + pEntry = NULL; + } + break; + } + else + pEntry = pEntry->pNext; + } + } + + if (bIsPad == TRUE) { + NdisReleaseSpinLock(&((PRTMP_ADAPTER)pData)->ApCfg.ReptCliEntryLock); + } else { + NdisReleaseSpinLock(((REPEATER_ADAPTER_DATA_TABLE *)pData)->EntryLock); + } + + return pEntry; +} + +BOOLEAN RTMPQueryLookupRepeaterCliEntryMT( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr) +{ + UCHAR isLinkValid; + + DBGPRINT(RT_DEBUG_INFO, ("%s:: %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, + pAddr[0], + pAddr[1], + pAddr[2], + pAddr[3], + pAddr[4], + pAddr[5])); + + if (RTMPLookupRepeaterCliEntry(pAd, FALSE, pAddr, TRUE, &isLinkValid) == NULL) { + DBGPRINT(RT_DEBUG_INFO, ("%s:: not the repeater client\n", __FUNCTION__)); + return FALSE; + } else { + DBGPRINT(RT_DEBUG_INFO, ("%s:: is the repeater client\n", __FUNCTION__)); + return TRUE; + } +} + +#if defined (CONFIG_WIFI_PKT_FWD) +EXPORT_SYMBOL(RTMPQueryLookupRepeaterCliEntryMT); +#endif /* CONFIG_WIFI_PKT_FWD */ + + +VOID RTMPInsertRepeaterEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx, + IN PUCHAR pAddr) +{ + INT CliIdx, idx, validIdx; + UCHAR HashIdx; + BOOLEAN Cancelled; + UCHAR tempMAC[MAC_ADDR_LEN]; + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + PREPEATER_CLIENT_ENTRY pReptCliEntry = NULL, pCurrEntry = NULL; + PREPEATER_CLIENT_ENTRY_MAP pReptCliMap; + UCHAR SPEC_ADDR[6][3] = {{0x02, 0x0F, 0xB5}, {0x02, 0x09, 0x5B}, + {0x02, 0x14, 0x6C}, {0x02, 0x18, 0x4D}, + {0x02, 0x1B, 0x2F}, {0x02, 0x1E, 0x2A}}; + + MAC_TABLE_ENTRY *pMacEntry = NULL; + STA_TR_ENTRY *tr_entry = NULL; + + DBGPRINT(RT_DEBUG_TRACE, (" %s.\n", __FUNCTION__)); + + + pMacEntry = MacTableLookup(pAd, pAddr); + + if (pMacEntry && IS_ENTRY_CLIENT(pMacEntry)) + { + + tr_entry = &pAd->MacTab.tr_entry[pMacEntry->wcid]; + if (tr_entry && tr_entry->PortSecured == WPA_802_1X_PORT_NOT_SECURED) + { + DBGPRINT(RT_DEBUG_ERROR, (" wireless client is not ready !!!\n")); + return ; + } + } + + NdisAcquireSpinLock(&pAd->ApCfg.ReptCliEntryLock); + + if (pAd->ApCfg.RepeaterCliSize >= MAX_EXT_MAC_ADDR_SIZE) + { + DBGPRINT(RT_DEBUG_ERROR, (" Repeater Client Full !!!\n")); + NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); + return ; + } + + if (pAd->ApCfg.ApCliTab[apidx].Enable == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, (" ApCli Interface is Down !!!\n")); + NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); + return ; + } + + validIdx = -1; + 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_WARN, ("\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_WARN, (" duplicate Insert !!!\n")); + NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); + return ; + } + + if (pReptCliEntry->CliEnable == FALSE && validIdx == -1) + validIdx = CliIdx; + } + + if (validIdx == -1) { + DBGPRINT(RT_DEBUG_ERROR, (" Repeater Client Full !!!\n")); + NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); + return ; + } + + pReptCliEntry = &pAd->ApCfg.ApCliTab[apidx].RepeaterCli[validIdx]; + pReptCliMap = &pAd->ApCfg.ApCliTab[apidx].RepeaterCliMap[validIdx]; + + /* 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; + pReptCliEntry->wdev = &pAd->ApCfg.ApCliTab[apidx].wdev;/*sync from 7615*/ + pReptCliMap->pReptCliEntry = pReptCliEntry; + +#ifdef APCLI_SAE_SUPPORT + pReptCliEntry->sae_cfg_group = pAd->ApCfg.ApCliTab[pReptCliEntry->MatchApCliIdx].sae_cfg_group; +#endif +#ifdef APCLI_OWE_SUPPORT + pReptCliEntry->curr_owe_group = pAd->ApCfg.ApCliTab[pReptCliEntry->MatchApCliIdx].curr_owe_group; +#endif + +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + NdisAllocateSpinLock(pAd, &pReptCliEntry->SavedPMK_lock); +#endif + + 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); + } + // replace to all real mac + else if (pAd->ApCfg.MACRepeaterOuiMode == 3) + { + INT IdxToUse; + + for (idx = 0; idx < pAd->ApCfg.ReptMacList.Num; idx++) + { + if ((pAd->ApCfg.ReptMacList.Entry[idx].bSet) && (!pAd->ApCfg.ReptMacList.Entry[idx].bUsed)) + break; + } + + /* If there is a matched one, use the next one; otherwise, use the first one. */ + if (idx >= 0 && idx < pAd->ApCfg.ReptMacList.Num) + { + IdxToUse = idx; + } + else + { + /* actually the real mac shouldn't be duplicate, this need the system to take care about this! */ + IdxToUse = 0; + } + + pAd->ApCfg.ReptMacList.Entry[IdxToUse].bUsed = 1; + + NdisCopyMemory(tempMAC, &pAd->ApCfg.ReptMacList.Entry[IdxToUse].Addr[0], MAC_ADDR_LEN); + } + else + { + NdisCopyMemory(tempMAC, pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, 3); + } + + COPY_MAC_ADDR(pReptCliEntry->CurrentAddress, tempMAC); + pReptCliEntry->CliEnable = TRUE; + pReptCliEntry->CliConnectState = 1; + pReptCliEntry->pNext = NULL; + NdisGetSystemUpTime(&pReptCliEntry->CliTriggerTime); + + RTMPInsertRepeaterAsicEntry(pAd, validIdx, 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; + if (pCurrMapEntry == pReptCliMap) + DBGPRINT(RT_DEBUG_ERROR, + ("Wrong!!! pCurrMapEntry == pReptCliMap(%p) in %s %d\n", + pReptCliMap,__FUNCTION__,__LINE__)); + else + 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 = validIdx; + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_MT2_AUTH_REQ, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, apidx); +#ifdef MTFWD + DBGPRINT(RT_DEBUG_OFF, ("Insert MacRep Sta:%pM\n", tempMAC)); + RtmpOSWrielessEventSend(pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + FWD_CMD_ADD_TX_SRC, + NULL, + tempMAC, + MAC_ADDR_LEN); +#endif + +} + +VOID RTMPRemoveRepeaterEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR func_tb_idx, + IN UCHAR CliIdx) +{ + USHORT HashIdx; + REPEATER_CLIENT_ENTRY *pEntry, *pPrevEntry, *pProbeEntry; + REPEATER_CLIENT_ENTRY_MAP *pMapEntry, *pPrevMapEntry, *pProbeMapEntry; + BOOLEAN bVaild; + + DBGPRINT(RT_DEBUG_ERROR, (" %s.\n", __FUNCTION__)); + + RTMPRemoveRepeaterAsicEntry(pAd, CliIdx); + + NdisAcquireSpinLock(&pAd->ApCfg.ReptCliEntryLock); + pEntry = &pAd->ApCfg.ApCliTab[func_tb_idx].RepeaterCli[CliIdx]; + +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + NdisFreeSpinLock(&pEntry->SavedPMK_lock); +#endif + + bVaild = TRUE; + + HashIdx = MAC_ADDR_HASH_INDEX(pEntry->CurrentAddress); + + pPrevEntry = NULL; + pProbeEntry = pAd->ApCfg.ReptCliHash[HashIdx]; + + ASSERT(pProbeEntry); + + if (pProbeEntry == NULL) + { + bVaild = FALSE; + goto done; + } + + if (pProbeEntry != NULL) + { + /* update Hash list*/ + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pAd->ApCfg.ReptCliHash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + } + + /* not found !!!*/ + ASSERT(pProbeEntry != NULL); + + if (pProbeEntry == NULL) + { + bVaild = FALSE; + goto done; + } + + pMapEntry = &pAd->ApCfg.ApCliTab[func_tb_idx].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; + } + pMapEntry->pNext=NULL; + pMapEntry->pReptCliEntry=NULL; + break; + } + + pPrevMapEntry = pProbeMapEntry; + if (pProbeMapEntry == pProbeMapEntry->pNext) + DBGPRINT(RT_DEBUG_ERROR,("Wrong!!! pProbeMapEntry == pProbeMapEntry->pNext(%p) in %s %d\n", + pProbeMapEntry,__FUNCTION__,__LINE__)); + pProbeMapEntry = pProbeMapEntry->pNext; + } while (pProbeMapEntry); + } + /* not found !!!*/ + ASSERT(pProbeMapEntry != NULL); + +done: + + pAd->ApCfg.ApCliTab[func_tb_idx].RepeaterCli[CliIdx].CliConnectState = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[func_tb_idx].RepeaterCli[CliIdx].OriginalAddress, MAC_ADDR_LEN); + + if ((bVaild == TRUE) && (pAd->ApCfg.RepeaterCliSize > 0)) + pAd->ApCfg.RepeaterCliSize--; + + /* set the apcli interface be invalid. */ + pAd->ApCfg.ApCliTab[func_tb_idx].RepeaterCli[CliIdx].CliValid = FALSE; + pAd->ApCfg.ApCliTab[func_tb_idx].RepeaterCli[CliIdx].CliEnable = FALSE; + + + NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); + +#ifdef MTFWD + DBGPRINT(RT_DEBUG_OFF, ("Remove MacRep Sta:%pM\n", pEntry->CurrentAddress)); + RtmpOSWrielessEventSend(pEntry->wdev->if_dev, + RT_WLAN_EVENT_CUSTOM, + FWD_CMD_DEL_TX_SRC, + NULL, + pEntry->CurrentAddress, + MAC_ADDR_LEN); +#endif + + return; +} + +MAC_TABLE_ENTRY *RTMPInsertRepeaterMacEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + IN struct wifi_dev *wdev, + IN UCHAR apIdx, + IN UCHAR cliIdx, + IN BOOLEAN CleanAll) +{ + UCHAR HashIdx; + int i; + MAC_TABLE_ENTRY *pEntry = NULL, *pCurrEntry; + BOOLEAN Cancelled; +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + MAC_TABLE_ENTRY *pre_mac_entry; +#endif + if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) + return NULL; + + /* allocate one MAC entry*/ + NdisAcquireSpinLock(&pAd->MacTabLock); + + i = (MAX_NUMBER_OF_MAC + ((MAX_EXT_MAC_ADDR_SIZE + 1) * (apIdx - MIN_NET_DEVICE_FOR_APCLI))); + + if (cliIdx != 0xFF) + i = i + cliIdx + 1; + + /* pick up the first available vacancy*/ + 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); +#ifdef DOT11W_PMF_SUPPORT + RTMPCancelTimer(&pEntry->SAQueryTimer, &Cancelled); + RTMPCancelTimer(&pEntry->SAQueryConfirmTimer, &Cancelled); +#endif /* DOT11W_PMF_SUPPORT */ + + 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; + } + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (apIdx >= MIN_NET_DEVICE_FOR_APCLI) + { + SET_ENTRY_APCLI(pEntry); + } +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + pEntry->wdev = wdev; + pEntry->wcid = i; + //SET_ENTRY_AP(pEntry);//Carter, why set Apcli Entry then set to AP entry? + pAd->MacTab.tr_entry[i].isCached = FALSE; + //tr_entry->isCached = FALSE; + pEntry->bIAmBadAtheros = FALSE; + + RTMPInitTimer(pAd, &pEntry->EnqueueStartForPSKTimer, GET_TIMER_FUNCTION(EnqueueStartForPSKExec), pEntry, FALSE); + +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + RTMPInitTimer(pAd, &pEntry->RetryTimer, GET_TIMER_FUNCTION(WPARetryExec), pEntry, FALSE); + } +#endif /* APCLI_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->func_tb_idx = (apIdx - MIN_NET_DEVICE_FOR_APCLI); + + if (IS_ENTRY_APCLI(pEntry)) + pEntry->func_tb_idx = (apIdx - MIN_NET_DEVICE_FOR_APCLI); + + pEntry->pMbss = NULL; + +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + pre_mac_entry = + &pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].pre_mac_entry; + + if (pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].wdev.AuthMode == Ndis802_11AuthModeOWE || + pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].wdev.AuthMode == Ndis802_11AuthModeWPA3PSK) { + pEntry->AuthMode = pre_mac_entry->AuthMode; + pEntry->WepStatus = pre_mac_entry->WepStatus; +#ifdef APCLI_SAE_SUPPORT + if (pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].wdev.AuthMode + == Ndis802_11AuthModeWPA3PSK) + NdisMoveMemory(pEntry->PMK, pre_mac_entry->PMK, LEN_PMK); +#endif + pEntry->pmk_cache = pre_mac_entry->pmk_cache; + pEntry->pmkid = pre_mac_entry->pmk_cache; +#ifdef APCLI_OWE_SUPPORT + pEntry->need_process_ecdh_ie = pre_mac_entry->need_process_ecdh_ie; + pEntry->key_deri_alg = pre_mac_entry->key_deri_alg; + NdisMoveMemory(&pEntry->owe, + &pre_mac_entry->owe, + sizeof(OWE_INFO)); + NdisMoveMemory(&pEntry->ecdh_ie, + &pre_mac_entry->ecdh_ie, + sizeof(EXT_ECDH_PARAMETER_IE)); +#endif + } else +#endif + { + pEntry->AuthMode = pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].wdev.AuthMode; + pEntry->WepStatus = pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].wdev.WepStatus; + } + + if (pEntry->AuthMode < Ndis802_11AuthModeWPA) + { + pEntry->WpaState = AS_NOTUSE; + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + } + else + { + pEntry->WpaState = AS_PTKSTART; + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + } + } +#endif /* APCLI_SUPPORT */ + + pEntry->GTKState = REKEY_NEGOTIATING; + pEntry->PairwiseKey.KeyLen = 0; + pEntry->PairwiseKey.CipherAlg = CIPHER_NONE; + pAd->MacTab.tr_entry[i].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + //pEntry->PortSecured = WPA_802_1X_PORT_NOT_SECURED; + + pEntry->PMKID_CacheIdx = ENTRY_NOT_FOUND; + COPY_MAC_ADDR(pEntry->Addr, pAddr); + +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + COPY_MAC_ADDR(pEntry->bssid, pAddr); + } +#endif // APCLI_SUPPORT // + + pEntry->Sst = SST_NOT_AUTH; + pEntry->AuthState = AS_NOT_AUTH; + pEntry->Aid = (USHORT)i; + pEntry->CapabilityInfo = 0; + pEntry->PsMode = PWR_ACTIVE; + pAd->MacTab.tr_entry[i].PsQIdleCount = 0; + pAd->MacTab.tr_entry[i].PsTokenFlag = 0; + //pEntry->PsQIdleCount = 0; + pEntry->NoDataIdleCount = 0; + pEntry->AssocDeadLine = MAC_TABLE_ASSOC_TIMEOUT; + pEntry->ContinueTxFailCnt = 0; + pEntry->TimeStamp_toTxRing = 0; + // TODO: shiang-usw, remove upper setting becasue we need to migrate to tr_entry! + pAd->MacTab.tr_entry[i].PsMode = PWR_ACTIVE; + pAd->MacTab.tr_entry[i].NoDataIdleCount = 0; + pAd->MacTab.tr_entry[i].ContinueTxFailCnt = 0; + pAd->MacTab.tr_entry[i].LockEntryTx = FALSE; + pAd->MacTab.tr_entry[i].TimeStamp_toTxRing = 0; + + 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); + + + DBGPRINT(RT_DEBUG_TRACE, ("%s - allocate entry #%d, Aid = %d, Total= %d\n",__FUNCTION__, i, pEntry->Aid, pAd->MacTab.Size)); + + } + else + { + if (pEntry) + DBGPRINT(RT_DEBUG_ERROR, ("%s - exist entry #%d, Aid = %d, Total= %d\n", + __func__, 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); + /*update tx burst, must after unlock pAd->MacTabLock*/ + rtmp_tx_burst_set(pAd); + + 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) +#ifdef AP_PARTIAL_SCAN_SUPPORT + && (pAd->ApCfg.bPartialScanning == FALSE) +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + ) + { + 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].AutoConnectFlag == FALSE) + continue; + + 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; +#ifdef AP_PARTIAL_SCAN_SUPPORT + if(pAd->ApCfg.bPartialScanEnable) + pAd->ApCfg.bPartialScanning = TRUE; +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + Ssid.SsidLength = CfgSsidLen; + NdisCopyMemory(Ssid.Ssid, pApCliCfgSsid, CfgSsidLen); + ApSiteSurvey(pAd, &Ssid, SCAN_ACTIVE, FALSE, &pAd->ApCfg.ApCliTab[i].wdev); + } + } + } +#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, (" Store Invaild MacAddr = %02x:%02x:%02x:%02x:%02x:%02x. !!!\n", + PRINT_MAC(pEntry->MacAddr))); + + pAd->ApCfg.ReptControl.ReptInVaildMacSize++; + NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); + + return; +} + +BOOLEAN RTMPRepeaterRemoveInvaildMacEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR idx, + IN PUCHAR pAddr) +{ + USHORT HashIdx; + INVAILD_TRIGGER_MAC_ENTRY *pEntry = NULL; + INVAILD_TRIGGER_MAC_ENTRY *pPrevEntry, *pProbeEntry; + + NdisAcquireSpinLock(&pAd->ApCfg.ReptCliEntryLock); + + HashIdx = MAC_ADDR_HASH_INDEX(pAddr); + pEntry = &pAd->ApCfg.ReptControl.RepeaterInvaildEntry[idx]; + + if (pEntry && pEntry->bInsert) + { + pPrevEntry = NULL; + pProbeEntry = pAd->ApCfg.ReptControl.ReptInvaildHash[HashIdx]; + ASSERT(pProbeEntry); + if (pProbeEntry != NULL) + { + /* update Hash list*/ + do + { + if (pProbeEntry == pEntry) + { + if (pPrevEntry == NULL) + { + pAd->ApCfg.ReptControl.ReptInvaildHash[HashIdx] = pEntry->pNext; + } + else + { + pPrevEntry->pNext = pEntry->pNext; + } + break; + } + + pPrevEntry = pProbeEntry; + pProbeEntry = pProbeEntry->pNext; + } while (pProbeEntry); + } + /* not found !!!*/ + ASSERT(pProbeEntry != NULL); + + pAd->ApCfg.ReptControl.ReptInVaildMacSize--; + } + + NdisZeroMemory(pEntry->MacAddr, MAC_ADDR_LEN); + pEntry->bInsert = FALSE; + + NdisReleaseSpinLock(&pAd->ApCfg.ReptCliEntryLock); + + return TRUE; +} + +INT Show_Repeater_Cli_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT i; + //UINT32 RegValue; + ULONG DataRate=0; + + if (!pAd->ApCfg.bMACRepeaterEn) + return TRUE; + + printk("\n"); + +#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 = 0; i < MAX_LEN_OF_MAC_TABLE; 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->func_tb_idx); + 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.AvgRssi[0]); + printk("%-7d", pEntry->RssiSample.AvgRssi[1]); + printk("%-7d", pEntry->RssiSample.AvgRssi[2]); + printk("%-10s", get_phymode_str(pEntry->HTPhyMode.field.MODE)); + printk("%-6s", get_bw_str(pEntry->HTPhyMode.field.BW)); + printk("%-6d", pEntry->HTPhyMode.field.MCS); + printk("%-6d", pEntry->HTPhyMode.field.ShortGI); + printk("%-6d", pEntry->HTPhyMode.field.STBC); + printk("%-7d", (int)(pEntry->StaIdleTimeout - pEntry->NoDataIdleCount)); + printk("%-7d", (int)DataRate); + printk("%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount, + (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0); + printk("\n"); + } + } + + return TRUE; +} +REPEATER_CLIENT_ENTRY *lookup_rept_entry(RTMP_ADAPTER *pAd, PUCHAR address) +{ + REPEATER_CLIENT_ENTRY *rept_entry = NULL; + UCHAR isLinkValid; + + rept_entry = RTMPLookupRepeaterCliEntry( + pAd, + FALSE, + address, + TRUE, &isLinkValid); + + if (!rept_entry) + rept_entry = RTMPLookupRepeaterCliEntry( + pAd, + TRUE, + address, + TRUE, &isLinkValid); + + if (rept_entry) + return rept_entry; + + return NULL; +} +#endif /* MAC_REPEATER_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_sanity.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_sanity.c new file mode 100644 index 000000000..c9f224c77 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_sanity.c @@ -0,0 +1,30 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + 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" + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_sync.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_sync.c new file mode 100644 index 000000000..4c621becb --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_sync.c @@ -0,0 +1,2296 @@ +/**************************************************************************** + * 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 WH_EZ_SETUP +#ifdef DUAL_CHIP +extern NDIS_SPIN_LOCK ez_conn_perm_lock; +#endif +#endif +#define OBSS_BEACON_RSSI_THRESHOLD (-85) + + +/* + ========================================================================== + Description: + Process the received ProbeRequest from clients + Parameters: + Elem - msg containing the ProbeReq frame + ========================================================================== + */ +VOID APPeerProbeReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PEER_PROBE_REQ_PARAM ProbeReqParam; + HEADER_802_11 ProbeRspHdr; + NDIS_STATUS NStatus; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0, TmpLen; + LARGE_INTEGER FakeTimestamp; + UCHAR DsLen = 1; + UCHAR ErpIeLen = 1; + UCHAR apidx = 0, PhyMode, SupRateLen; + UCHAR RSNIe=IE_WPA, RSNIe2=IE_WPA2; + BSS_STRUCT *mbss; + struct wifi_dev *wdev; + UCHAR idx = 0; + UCHAR Environment = 0x20; +#ifdef WH_EZ_SETUP + BOOLEAN ez_peer = FALSE; +#endif /* WH_EZ_SETUP */ + +#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 */ + + + if (PeerProbeReqSanity(pAd, Elem->Msg, Elem->MsgLen, &ProbeReqParam) == FALSE) { +DBGPRINT(RT_DEBUG_OFF, ("%s():shiang! PeerProbeReqSanity failed!\n", __FUNCTION__)); + return; + } + + for(apidx=0; apidxApCfg.BssidNum; apidx++) + { + mbss = &pAd->ApCfg.MBSSID[apidx]; + wdev = &mbss->wdev; + RSNIe = IE_WPA; + + if ((wdev->if_dev == NULL) || ((wdev->if_dev != NULL) && + !(RTMP_OS_NETDEV_STATE_RUNNING(wdev->if_dev)))) + { + /* the interface is down, so we can not send probe response */ + continue; + } +#ifdef AIRPLAY_SUPPORT + if (pAd->ApCfg.MBSSID[apidx].bcn_buf.bBcnSntReq == FALSE) + continue; +#endif /* AIRPLAY_SUPPORT */ +#ifdef WAPP_SUPPORT + wapp_send_cli_probe_event(pAd, RtmpOsGetNetIfIndex(wdev->if_dev), ProbeReqParam.Addr2, Elem); +#endif + + PhyMode = wdev->PhyMode; + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev)) { + unsigned ez_probe_req_action = 0; +#ifdef EZ_ROAM_SUPPORT + if (ez_is_roam_blocked_mac(wdev, ProbeReqParam.Addr2)){ + //if(MAC_ADDR_EQUAL(wdev->ez_security.ez_ap_roam_blocked_mac,ProbeReqParam.Addr2)){ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,(" Connection not allowed as roaming ongoing.\n")); + continue; + } +#endif + ez_probe_req_action = ez_process_probe_request(pAd, wdev, ProbeReqParam.Addr2, Elem->Msg, Elem->MsgLen); + if (ez_probe_req_action == 1) { + ez_peer = TRUE; + EZ_DEBUG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("Easy Setup Peer - %02x:%02x:%02x:%02x:%02x:%02x\n", + ProbeReqParam.Addr2[0], + ProbeReqParam.Addr2[1], + ProbeReqParam.Addr2[2], + ProbeReqParam.Addr2[3], + ProbeReqParam.Addr2[4], + ProbeReqParam.Addr2[5])); + } + else if (ez_probe_req_action == 2) + { + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,(" Connection not allowd\n")); + continue; + } else + { +#ifdef WH_EZ_SETUP + //! if ez_setup is enabled on this wdev and and it is a triband repeater than this AP should accept only EZ connections + if(ez_is_triband() && IS_EZ_SETUP_ENABLED(wdev)) { + if (!ez_check_for_ez_enable(wdev, Elem->Msg, Elem->MsgLen)) + { + } else { + continue; + } + } +#endif + // EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("ez_process_probe_request returned false\n")); + } + } + else{ + // EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("ez_process_probe_request not entered: %d %d\n", wdev->wdev_idx, wdev->enable_easy_setup)); + } +#endif /* WH_EZ_SETUP */ + + if ( ((((ProbeReqParam.SsidLen == 0) && (!mbss->bHideSsid)) || + ((ProbeReqParam.SsidLen == mbss->SsidLen) && NdisEqualMemory(ProbeReqParam.Ssid, mbss->Ssid, (ULONG) ProbeReqParam.SsidLen))) +#ifdef CONFIG_HOTSPOT + && ProbeReqforHSAP(pAd, apidx, &ProbeReqParam) +#endif + ) +#ifdef WSC_AP_SUPPORT + /* buffalo WPS testbed STA send ProbrRequest ssid length = 32 and ssid are not AP , but DA are AP. for WPS test send ProbeResponse */ + || ((ProbeReqParam.SsidLen == 32) && MAC_ADDR_EQUAL(Addr3, wdev->bssid) && (mbss->bHideSsid == 0)) +#endif /* WSC_AP_SUPPORT */ + ) + { + ; + } + else { +#ifdef WH_EZ_SETUP + if (!ez_peer) +#endif /* WH_EZ_SETUP */ + continue; /* check next BSS */ + } +#ifdef STA_FORCE_ROAM_SUPPORT + // Enhancement: Block probe Response to a peer on acl list to avoid conenct attempts by peer. + if (pAd->en_force_roam_supp && + ! ApCheckFroamAccessControlList(pAd, ProbeReqParam.Addr2, apidx)) { + DBGPRINT(RT_DEBUG_OFF, + ("ACL reject Peer - %02x:%02x:%02x:%02x:%02x:%02x, block Probe Response.\n", + PRINT_MAC(ProbeReqParam.Addr2))); + return; + } +#endif + +#ifdef WH_EVENT_NOTIFIER + { + EventHdlr pEventHdlrHook = NULL; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_STA_PROBE_REQ); + if(pEventHdlrHook && wdev) + pEventHdlrHook(pAd, wdev, &ProbeReqParam, Elem); + } +#endif /* WH_EVENT_NOTIFIER */ + + +#ifdef BAND_STEERING + if ((pAd->ApCfg.BandSteering) +#ifdef WH_EZ_SETUP + && !((wdev != NULL) && (IS_EZ_SETUP_ENABLED(wdev)) && (ez_peer == TRUE)) +#endif + ) { + BOOLEAN bBndStrgCheck = TRUE; + bBndStrgCheck = BndStrg_CheckConnectionReq(pAd, wdev, ProbeReqParam.Addr2, Elem, &ProbeReqParam); + if (bBndStrgCheck == FALSE) + return; + } +#endif /* BAND_STEERING */ + + /* allocate and send out ProbeRsp frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + MgtMacHeaderInit(pAd, &ProbeRspHdr, SUBTYPE_PROBE_RSP, 0, ProbeReqParam.Addr2, + wdev->if_addr, wdev->bssid); + + if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) + RSNIe = IE_WPA; + else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) + || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef DOT11_SAE_SUPPORT + || (wdev->AuthMode == Ndis802_11AuthModeWPA3PSK) + || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSKWPA3PSK) +#endif +#ifdef CONFIG_OWE_SUPPORT + || (wdev->AuthMode == Ndis802_11AuthModeOWE) +#endif + ) + RSNIe = IE_WPA2; +#ifdef WAPI_SUPPORT + else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK)) + RSNIe = IE_WAPI; +#endif /* WAPI_SUPPORT */ + + { +#ifdef DYNAMIC_RX_RATE_ADJ + SupRateLen = mbss->SupRateLen; +#else + SupRateLen = pAd->CommonCfg.SupRateLen; +#endif /* DYNAMIC_RX_RATE_ADJ */ + if (PhyMode == WMODE_B) + SupRateLen = 4; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &ProbeRspHdr, + TIMESTAMP_LEN, &FakeTimestamp, + 2, &pAd->CommonCfg.BeaconPeriod, + 2, &mbss->CapabilityInfo, + 1, &SsidIe, + 1, &mbss->SsidLen, + mbss->SsidLen, mbss->Ssid, + 1, &SupRateIe, + 1, &SupRateLen, +#ifdef DYNAMIC_RX_RATE_ADJ + SupRateLen, mbss->SupRate, +#else + SupRateLen, pAd->CommonCfg.SupRate, +#endif /* DYNAMIC_RX_RATE_ADJ */ + 1, &DsIe, + 1, &DsLen, + 1, &pAd->CommonCfg.Channel, + END_OF_ARGS); + } + +#ifdef DYNAMIC_RX_RATE_ADJ + if ((mbss->ExtRateLen) && (PhyMode != WMODE_B)) +#else + if ((pAd->CommonCfg.ExtRateLen) && (PhyMode != WMODE_B)) +#endif /* DYNAMIC_RX_RATE_ADJ */ + { + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &ErpIe, + 1, &ErpIeLen, + 1, &pAd->ApCfg.ErpIeContent, + 1, &ExtRateIe, +#ifdef DYNAMIC_RX_RATE_ADJ + 1, &mbss->ExtRateLen, + mbss->ExtRateLen, mbss->ExtRate, +#else + 1, &pAd->CommonCfg.ExtRateLen, + pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, +#endif /* DYNAMIC_RX_RATE_ADJ */ + 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 (WMODE_CAP_N(PhyMode) && + (wdev->DesiredHtPhyInfo.bHtEnable)) + { + ULONG TmpLen; + UCHAR HtLen, AddHtLen/*, NewExtLen*/; + HT_CAPABILITY_IE HtCapabilityTmp; +#ifdef RT_BIG_ENDIAN + ADD_HT_INFO_IE addHTInfoTmp; +#endif + +/* YF@20120419: Fix IOT Issue with Atheros STA on Windows 7 When IEEE80211H flag turn on. */ + + HtLen = sizeof(pAd->CommonCfg.HtCapability); + AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); + //NewExtLen = 1; + /*New extension channel offset IE is included in Beacon, Probe Rsp or channel Switch Announcement Frame */ +#ifndef RT_BIG_ENDIAN + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); +#ifdef DYNAMIC_RX_RATE_ADJ + NdisMoveMemory(HtCapabilityTmp.MCSSet, mbss->ExpectedSuppHTMCSSet, 4); +#endif /* DYNAMIC_RX_RATE_ADJ */ + HtCapabilityTmp.HtCapInfo.ChannelWidth = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HtLen, + sizeof(HT_CAPABILITY_IE), &HtCapabilityTmp, + 1, &AddHtInfoIe, + 1, &AddHtLen, + sizeof(ADD_HT_INFO_IE), &pAd->CommonCfg.AddHTInfo, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); +#ifdef DYNAMIC_RX_RATE_ADJ + NdisMoveMemory(HtCapabilityTmp.MCSSet, mbss->ExpectedSuppHTMCSSet, 4); +#endif /* DYNAMIC_RX_RATE_ADJ */ + HtCapabilityTmp.HtCapInfo.ChannelWidth = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); +#ifdef UNALIGNMENT_SUPPORT + { + EXT_HT_CAP_INFO extHtCapInfo; + + NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); + NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + } +#else + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); +#endif /* UNALIGNMENT_SUPPORT */ + + NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, AddHtLen); + *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); + *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + 1, &AddHtInfoIe, + 1, &AddHtLen, + AddHtLen, &addHTInfoTmp, + END_OF_ARGS); + +#endif + FrameLen += TmpLen; + } +#endif /* DOT11_N_SUPPORT */ + + /* Append RSN_IE when WPA OR WPAPSK, */ + if (wdev->AuthMode < Ndis802_11AuthModeWPA) + ; /* enough information */ + else if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + { + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &RSNIe, + 1, &mbss->RSNIE_Len[0], + mbss->RSNIE_Len[0], mbss->RSN_IE[0], + 1, &RSNIe2, + 1, &mbss->RSNIE_Len[1], + mbss->RSNIE_Len[1], mbss->RSN_IE[1], + END_OF_ARGS); + FrameLen += TmpLen; + } + else + { +#ifdef CONFIG_HOTSPOT_R2 + PHOTSPOT_CTRL pHSCtrl = &mbss->HotSpotCtrl; + extern UCHAR OSEN_IE[]; + extern UCHAR OSEN_IELEN; + + if ((pHSCtrl->HotSpotEnable == 0) && (pHSCtrl->bASANEnable == 1) && (wdev->AuthMode == Ndis802_11AuthModeWPA2)) + { + RSNIe = IE_WPA; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &RSNIe, + 1, &OSEN_IELEN, + OSEN_IELEN, OSEN_IE, + END_OF_ARGS); + } + else +#endif + { + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &RSNIe, + 1, &mbss->RSNIE_Len[0], + mbss->RSNIE_Len[0], mbss->RSN_IE[0], + END_OF_ARGS); + } + FrameLen += TmpLen; + } + +#ifdef CONFIG_HOTSPOT + if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.HotSpotEnable) + { + ULONG TmpLen; + + /* Hotspot 2.0 Indication */ + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.HSIndicationIELen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.HSIndicationIE, END_OF_ARGS); + + FrameLen += TmpLen; + + /* Interworking element */ + /*MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.InterWorkingIELen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.InterWorkingIE, END_OF_ARGS); + + FrameLen += TmpLen; +*/ + /* Advertisement Protocol element */ + /*MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.AdvertisementProtoIELen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.AdvertisementProtoIE, END_OF_ARGS); + FrameLen += TmpLen; +*/ + /* Roaming Consortium element */ + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.RoamingConsortiumIELen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.RoamingConsortiumIE, END_OF_ARGS); + + FrameLen += TmpLen; + + /* P2P element */ + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.P2PIELen, + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.P2PIE, END_OF_ARGS); + + FrameLen += TmpLen; + } +#endif + + + /* Extended Capabilities IE */ + { + ULONG TmpLen; + EXT_CAP_INFO_ELEMENT extCapInfo; + UCHAR extInfoLen = sizeof(EXT_CAP_INFO_ELEMENT); +#ifdef RT_BIG_ENDIAN + PUCHAR pInfo; +#endif + NdisZeroMemory(&extCapInfo, extInfoLen); + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* P802.11n_D1.10, HT Information Exchange Support */ + if ((pAd->CommonCfg.PhyMode >= PHY_11ABGN_MIXED) && (pAd->CommonCfg.Channel <= 14) && + (pAd->ApCfg.MBSSID[apidx].wdev.DesiredHtPhyInfo.bHtEnable) && + (pAd->CommonCfg.bBssCoexEnable == TRUE)) + { + extCapInfo.BssCoexistMgmtSupport = 1; + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef CONFIG_DOT11V_WNM + if (pAd->ApCfg.MBSSID[apidx].WNMCtrl.ProxyARPEnable) + extCapInfo.proxy_arp = 1; + if (pAd->ApCfg.MBSSID[apidx].WNMCtrl.WNMBTMEnable) + extCapInfo.BssTransitionManmt = 1; +#ifdef CONFIG_HOTSPOT_R2 + if (pAd->ApCfg.MBSSID[apidx].WNMCtrl.WNMNotifyEnable) + extCapInfo.wnm_notification= 1; + if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.QosMapEnable) + extCapInfo.qosmap= 1; +#endif +#endif + +#ifdef CONFIG_HOTSPOT + if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.HotSpotEnable) + extCapInfo.interworking = 1; +#endif + +#ifdef RT_BIG_ENDIAN + pInfo = (PUCHAR)(&extCapInfo); + *((UINT32*)(pInfo)) = cpu2le32(*((UINT32*)(pInfo))); + *((UINT32*)(pInfo+4)) = cpu2le32(*((UINT32*)(pInfo+4))); +#endif + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &ExtCapIe, + 1, &extInfoLen, + extInfoLen, &extCapInfo, + END_OF_ARGS); + + FrameLen += TmpLen; + } + +#ifdef AP_QLOAD_SUPPORT + if (pAd->phy_ctrl.FlgQloadEnable != 0) + { +#ifdef CONFIG_HOTSPOT_R2 + if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.QLoadTestEnable == 1) + FrameLen += QBSS_LoadElementAppend_HSTEST(pAd, pOutBuffer+FrameLen, apidx); + else if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.QLoadTestEnable == 0) +#endif + FrameLen += QBSS_LoadElementAppend(pAd, pOutBuffer+FrameLen); + } +#endif /* AP_QLOAD_SUPPORT */ +#ifdef DOT11U_INTERWORKING + if (mbss->GASCtrl.b11U_enable) { + ULONG TmpLen; + /* Interworking element */ + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + mbss->GASCtrl.InterWorkingIELen, + mbss->GASCtrl.InterWorkingIE, END_OF_ARGS); + FrameLen += TmpLen; + /* Advertisement Protocol element */ + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + mbss->GASCtrl.AdvertisementProtoIELen, + mbss->GASCtrl.AdvertisementProtoIE, END_OF_ARGS); + FrameLen += TmpLen; + } +#endif/* DOT11U_INTERWORKING */ + + /* add WMM IE here */ + if (mbss->wdev.bWmmCapable) + { + UCHAR i; + UCHAR WmeParmIe[26] = {IE_VENDOR_SPECIFIC, 24, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0, 0}; + WmeParmIe[8] = pAd->ApCfg.BssEdcaParm.EdcaUpdateCount & 0x0f; +#ifdef UAPSD_SUPPORT + UAPSD_MR_IE_FILL(WmeParmIe[8], &mbss->wdev.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; + } + + /* add country IE, power constraint IE */ + if (pAd->CommonCfg.bCountryFlag) + { +#ifndef EXT_BUILD_CHANNEL_LIST + ULONG TmpLen; +#endif /* !EXT_BUILD_CHANNEL_LIST */ + ULONG TmpLen2=0; + UCHAR *TmpFrame = NULL; + + os_alloc_mem(NULL, (UCHAR **)&TmpFrame, 256); + if (TmpFrame != NULL) + { + NdisZeroMemory(TmpFrame, 256); + + /* prepare channel information */ +#ifdef EXT_BUILD_CHANNEL_LIST + BuildBeaconChList(pAd, TmpFrame, &TmpLen2); +#else + { + UCHAR MaxTxPower = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); + MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, + 1, &pAd->ChannelList[0].Channel, + 1, &pAd->ChannelListNum, + 1, &MaxTxPower, + END_OF_ARGS); + TmpLen2 += TmpLen; + } +#endif /* EXT_BUILD_CHANNEL_LIST */ + +#ifdef DOT11K_RRM_SUPPORT + if (IS_RRM_ENABLE(pAd, apidx) + && (pAd->CommonCfg.RegulatoryClass[0] != 0)) + { + TmpLen2 = 0; + NdisZeroMemory(TmpFrame, 256); + RguClass_BuildBcnChList(pAd, TmpFrame, &TmpLen2); + } +#endif /* DOT11K_RRM_SUPPORT */ + + os_free_mem(NULL, TmpFrame); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + } + +#ifdef DOT11K_RRM_SUPPORT + if (IS_RRM_ENABLE(pAd, apidx)) + { + InsertTpcReportIE(pAd, pOutBuffer+FrameLen, &FrameLen, + RTMP_GetTxPwr(pAd, pAd->CommonCfg.MlmeTransmit), 0); + RRM_InsertRRMEnCapIE(pAd, pOutBuffer+FrameLen, &FrameLen, apidx); + } + + + { + INT loop; + for (loop=0; loopCommonCfg.RegulatoryClass[loop] == 0) + break; + InsertChannelRepIE(pAd, pOutBuffer+FrameLen, &FrameLen, + (RTMP_STRING *)pAd->CommonCfg.CountryCode, + pAd->CommonCfg.RegulatoryClass[loop], NULL); + } + } + +#ifndef APPLE_11K_IOT + /* Insert BSS AC Access Delay IE. */ + RRM_InsertBssACDelayIE(pAd, pOutBuffer+FrameLen, &FrameLen); + + /* Insert BSS Available Access Capacity IE. */ + RRM_InsertBssAvailableACIE(pAd, pOutBuffer+FrameLen, &FrameLen); +#endif /* !APPLE_11K_IOT */ + +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + /* P802.11n_D3.03, 7.3.2.60 Overlapping BSS Scan Parameters IE */ + if (WMODE_CAP_N(PhyMode) && + (pAd->CommonCfg.Channel <= 14) && + (wdev->DesiredHtPhyInfo.bHtEnable) && + (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1)) + { + OVERLAP_BSS_SCAN_IE OverlapScanParam; + ULONG TmpLen; + UCHAR OverlapScanIE, ScanIELen; + + OverlapScanIE = IE_OVERLAPBSS_SCAN_PARM; + ScanIELen = 14; + OverlapScanParam.ScanPassiveDwell = cpu2le16(pAd->CommonCfg.Dot11OBssScanPassiveDwell); + OverlapScanParam.ScanActiveDwell = cpu2le16(pAd->CommonCfg.Dot11OBssScanActiveDwell); + OverlapScanParam.TriggerScanInt = cpu2le16(pAd->CommonCfg.Dot11BssWidthTriggerScanInt); + OverlapScanParam.PassiveTalPerChannel = cpu2le16(pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel); + OverlapScanParam.ActiveTalPerChannel = cpu2le16(pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel); + OverlapScanParam.DelayFactor = cpu2le16(pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor); + OverlapScanParam.ScanActThre = cpu2le16(pAd->CommonCfg.Dot11OBssScanActivityThre); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &OverlapScanIE, + 1, &ScanIELen, + ScanIELen, &OverlapScanParam, + END_OF_ARGS); + + FrameLen += TmpLen; + } + +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + /* add country IE, power constraint IE */ + if (pAd->CommonCfg.bCountryFlag) + { + ULONG TmpLen2=0; + UCHAR TmpFrame[256] = {0}; + UCHAR CountryIe = IE_COUNTRY; + UCHAR MaxTxPower=16; + +#ifdef A_BAND_SUPPORT + /* + Only 802.11a APs that comply with 802.11h are required to include + a Power Constrint Element(IE=32) in beacons and probe response frames + */ + if (pAd->CommonCfg.Channel > 14 && pAd->CommonCfg.bIEEE80211H == TRUE) + { + /* prepare power constraint IE */ + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 3, PowerConstraintIE, + END_OF_ARGS); + FrameLen += TmpLen; + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(PhyMode)) { + ULONG TmpLen; + UINT8 vht_txpwr_env_ie = IE_VHT_TXPWR_ENV; + UINT8 ie_len; + VHT_TXPWR_ENV_IE txpwr_env; + + ie_len = build_vht_txpwr_envelope(pAd, (UCHAR *)&txpwr_env); + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &vht_txpwr_env_ie, + 1, &ie_len, + ie_len, &txpwr_env, + END_OF_ARGS); + FrameLen += TmpLen; + } +#endif /* DOT11_VHT_AC */ + } +#endif /* A_BAND_SUPPORT */ + + //NdisZeroMemory(TmpFrame, sizeof(TmpFrame)); + + /* prepare channel information */ + MakeOutgoingFrame(TmpFrame+TmpLen2, &TmpLen, + 1, &pAd->ChannelList[0].Channel, + 1, &pAd->ChannelListNum, + 1, &MaxTxPower, + END_OF_ARGS); + TmpLen2 += TmpLen; +#ifdef MBO_SUPPORT + if (IS_MBO_ENABLE(wdev)) + Environment = MBO_AP_USE_GLOBAL_OPERATING_CLASS; +#endif/* MBO_SUPPORT */ + /* need to do the padding bit check, and concatenate it */ + if ((TmpLen2%2) == 0) + { + UCHAR TmpLen3 = TmpLen2+4; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &CountryIe, + 1, &TmpLen3, + 1, &pAd->CommonCfg.CountryCode[0], + 1, &pAd->CommonCfg.CountryCode[1], + 1, &Environment, + TmpLen2+1, TmpFrame, + END_OF_ARGS); + } + else + { + UCHAR TmpLen3 = TmpLen2+3; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &CountryIe, + 1, &TmpLen3, + 1, &pAd->CommonCfg.CountryCode[0], + 1, &pAd->CommonCfg.CountryCode[1], + 1, &Environment, + TmpLen2, TmpFrame, + END_OF_ARGS); + } + FrameLen += TmpLen; + }/* Country IE - */ + +#ifdef A_BAND_SUPPORT + /* add Channel switch announcement IE */ + if ((pAd->CommonCfg.Channel > 14) + && (pAd->CommonCfg.bIEEE80211H == 1) + && (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) + { + UCHAR CSAIe=IE_CHANNEL_SWITCH_ANNOUNCEMENT; + UCHAR CSALen=3; + UCHAR CSAMode=1; + + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 1, &CSAIe, + 1, &CSALen, + 1, &CSAMode, + 1, &pAd->CommonCfg.Channel, + 1, &pAd->Dot11_H.CSCount, + END_OF_ARGS); + FrameLen += TmpLen; +#ifdef DOT11_N_SUPPORT + if (pAd->CommonCfg.bExtChannelSwitchAnnouncement) + { + HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE HtExtChannelSwitchIe; + + build_ext_channel_switch_ie(pAd, &HtExtChannelSwitchIe); + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + sizeof(HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE), &HtExtChannelSwitchIe, + END_OF_ARGS); + } +#endif /* DOT11_N_SUPPORT */ + FrameLen += TmpLen; + } +#endif /* A_BAND_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(PhyMode) && + (wdev->DesiredHtPhyInfo.bHtEnable)) + { + ULONG TmpLen; + UCHAR HtLen, AddHtLen;/*, NewExtLen; */ +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; + ADD_HT_INFO_IE addHTInfoTmp; +#endif + HtLen = sizeof(pAd->CommonCfg.HtCapability); + AddHtLen = sizeof(pAd->CommonCfg.AddHTInfo); + + if (pAd->bBroadComHT == TRUE) + { + UCHAR epigram_ie_len; + UCHAR BROADCOM_HTC[4] = {0x0, 0x90, 0x4c, 0x33}; + UCHAR BROADCOM_AHTINFO[4] = {0x0, 0x90, 0x4c, 0x34}; + + + epigram_ie_len = HtLen + 4; +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_HTC[0], + HtLen, &pAd->CommonCfg.HtCapability, + END_OF_ARGS); +#else + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, HtLen); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); +#ifdef UNALIGNMENT_SUPPORT + { + EXT_HT_CAP_INFO extHtCapInfo; + + NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); + NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + } +#else + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); +#endif /* UNALIGNMENT_SUPPORT */ + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_HTC[0], + HtLen, &HtCapabilityTmp, + END_OF_ARGS); +#endif + + FrameLen += TmpLen; + + epigram_ie_len = AddHtLen + 4; +#ifndef RT_BIG_ENDIAN + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_AHTINFO[0], + AddHtLen, &pAd->CommonCfg.AddHTInfo, + END_OF_ARGS); +#else + NdisMoveMemory(&addHTInfoTmp, &pAd->CommonCfg.AddHTInfo, AddHtLen); + *(USHORT *)(&addHTInfoTmp.AddHtInfo2) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo2)); + *(USHORT *)(&addHTInfoTmp.AddHtInfo3) = SWAP16(*(USHORT *)(&addHTInfoTmp.AddHtInfo3)); + + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &WpaIe, + 1, &epigram_ie_len, + 4, &BROADCOM_AHTINFO[0], + AddHtLen, &addHTInfoTmp, + END_OF_ARGS); +#endif + + FrameLen += TmpLen; + } + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(PhyMode) && + (pAd->CommonCfg.Channel > 14)) { + FrameLen += build_vht_ies(pAd, (UCHAR *)(pOutBuffer+FrameLen), SUBTYPE_PROBE_RSP); + } +#endif /* DOT11_VHT_AC */ + + } +#endif /* DOT11_N_SUPPORT */ + + +#ifdef WSC_AP_SUPPORT + /* for windows 7 logo test */ + if ((mbss->WscControl.WscConfMode != WSC_DISABLE) && +#ifdef DOT1X_SUPPORT + (wdev->IEEE8021X == FALSE) && +#endif /* DOT1X_SUPPORT */ + (wdev->WepStatus == Ndis802_11WEPEnabled)) + { + /* + Non-WPS Windows XP and Vista PCs are unable to determine if a WEP enalbed network is static key based + or 802.1X based. If the legacy station gets an EAP-Rquest/Identity from the AP, it assume the WEP + network is 802.1X enabled & will prompt the user for 802.1X credentials. If the legacy station doesn't + receive anything after sending an EAPOL-Start, it will assume the WEP network is static key based and + prompt user for the WEP key. <> + A WPS enabled AP should include this IE in the beacon when the AP is hosting a static WEP key network. + The IE would be 7 bytes long with the Extended Capability field set to 0 (all bits zero) + http://msdn.microsoft.com/library/default.asp?url=/library/en-us/randz/protocol/securing_public_wi-fi_hotspots.asp + */ + ULONG TempLen1 = 0; + UCHAR PROVISION_SERVICE_IE[7] = {0xDD, 0x05, 0x00, 0x50, 0xF2, 0x05, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TempLen1, + 7, PROVISION_SERVICE_IE, + END_OF_ARGS); + FrameLen += TempLen1; + } + + /* add Simple Config Information Element */ + if ((mbss->WscControl.WscConfMode > WSC_DISABLE) && (mbss->WscIEProbeResp.ValueLen)) + { + ULONG WscTmpLen = 0; + MakeOutgoingFrame(pOutBuffer+FrameLen, &WscTmpLen, + mbss->WscIEProbeResp.ValueLen, mbss->WscIEProbeResp.Value, + END_OF_ARGS); + FrameLen += WscTmpLen; + } +#endif /* WSC_AP_SUPPORT */ + + +#ifdef DOT11R_FT_SUPPORT + /* The Mobility Domain information element (MDIE) is present in Probe- + ** Request frame when dot11FastBssTransitionEnable is set to true. */ + if (pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable) + { + PFT_CFG pFtCfg = &pAd->ApCfg.MBSSID[apidx].FtCfg; + FT_CAP_AND_POLICY FtCap; + FtCap.field.FtOverDs = pFtCfg->FtCapFlag.FtOverDs; + FtCap.field.RsrReqCap = pFtCfg->FtCapFlag.RsrReqCap; + FT_InsertMdIE(pAd, pOutBuffer + FrameLen, &FrameLen, + pFtCfg->FtMdId, FtCap); + } +#endif /* DOT11R_FT_SUPPORT */ + + + /* + add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back + Byte0.b3=1 for rssi-feedback + */ +#ifdef WH_EZ_SETUP + /* + To prevent old device has trouble to parse MTK vendor IE, + insert easy setup IE first. + */ + if (IS_EZ_SETUP_ENABLED(wdev) && ez_peer) { + FrameLen += ez_build_probe_response_ie(wdev, pOutBuffer+FrameLen); + +#ifdef NEW_CONNECTION_ALGO + + if (!ez_update_connection_permission(pAd, wdev, EZ_DISALLOW_ALL_ALLOW_ME)) { + return; + } +#endif + } + /* + add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back + Byte0.b3=1 for rssi-feedback + */ + +// FrameLen += build_vendor_ie(pAd, wdev, (pOutBuffer + FrameLen), SUBTYPE_PROBE_RSP); +#endif /* WH_EZ_SETUP */ +#if defined(MWDS) || defined(CONFIG_OWE_SUPPORT) + FrameLen += build_vendor_ie(pAd, wdev, (pOutBuffer + FrameLen) +#ifdef CONFIG_OWE_SUPPORT + , VIE_PROBE_RESP +#endif +#ifdef WH_EZ_SETUP + ,SUBTYPE_PROBE_RSP +#endif + ); +#else + { + 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 WH_EZ_SETUP + /* + To prevent old device has trouble to parse MTK vendor IE, + insert easy setup IE first. + */ + if (IS_EZ_SETUP_ENABLED(wdev) && ez_peer) { + FrameLen += ez_build_probe_response_ie(wdev, pOutBuffer+FrameLen); + +#ifdef NEW_CONNECTION_ALGO + + if (!ez_update_connection_permission(pAd, wdev, EZ_DISALLOW_ALL_ALLOW_ME)) { + return; + } +#endif + } + + /* + add Ralink-specific IE here - Byte0.b0=1 for aggregation, Byte0.b1=1 for piggy-back + Byte0.b3=1 for rssi-feedback + */ + + FrameLen += build_vendor_ie(pAd, wdev, (pOutBuffer + FrameLen) +#ifdef CONFIG_OWE_SUPPORT + , VIE_PROBE_RESP +#endif + , SUBTYPE_PROBE_RSP); +#endif /* WH_EZ_SETUP */ + +#ifdef RSSI_FEEDBACK + if (ProbeReqParam.bRequestRssi == TRUE) + { + MAC_TABLE_ENTRY *pEntry=NULL; + + DBGPRINT(RT_DEBUG_ERROR, ("SYNC - Send PROBE_RSP to %02x:%02x:%02x:%02x:%02x:%02x...\n", + PRINT_MAC(Addr2))); + + RalinkSpecificIe[5] |= 0x8; + pEntry = MacTableLookup(pAd, Addr2); + + if (pEntry != NULL) + { + RalinkSpecificIe[6] = (UCHAR)pEntry->RssiSample.AvgRssi[0]; + RalinkSpecificIe[7] = (UCHAR)pEntry->RssiSample.AvgRssi[1]; + RalinkSpecificIe[8] = (UCHAR)pEntry->RssiSample.AvgRssi[2]; + } + } +#endif /* RSSI_FEEDBACK */ + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkSpecificIe, + END_OF_ARGS); + FrameLen += TmpLen; + + } +#endif /* MWDS */ +#ifdef MBO_SUPPORT + if (IS_MBO_ENABLE(wdev)) { + MakeMboOceIE(pAd, wdev, pOutBuffer+FrameLen, &FrameLen, MBO_FRAME_TYPE_PROBE_RSP); + } +#endif/* MBO_SUPPORT */ +#ifdef AIRPLAY_SUPPORT + if (AIRPLAY_ON(pAd)) + { + ULONG AirplayTmpLen = 0; + + /*User user setting IE*/ + if (pAd->pAirplayIe && (pAd->AirplayIeLen != 0)) + { + //printk("AIRPLAY IE setting : MakeOutgoingFrame IeLen=%d\n",pAd->AirplayIeLen); + //hex_dump("APPLE IE:", pAd->pAirplayIe , pAd->AirplayIeLen); + MakeOutgoingFrame(pOutBuffer+FrameLen, &AirplayTmpLen, + pAd->AirplayIeLen, pAd->pAirplayIe, + END_OF_ARGS); + FrameLen += AirplayTmpLen; + } + } +#endif /* AIRPLAY_SUPPORT*/ + + /* 802.11n 11.1.3.2.2 active scanning. sending probe response with MCS rate is */ + for (idx = 0; idx < mbss->ProbeRspTimes; idx++) + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + +#ifdef WH_EZ_SETUP + if(IS_EZ_SETUP_ENABLED(wdev) && (ez_peer)) { + ez_prepare_security_key(wdev, ProbeReqParam.Addr2, TRUE); + } +#endif /* WH_EZ_SETUP */ + } +} + + +/* + ========================================================================== + 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 + ========================================================================== + */ + +#ifdef EZ_REGROUP_SUPPORT +regrp_ap_info_struct regrp_ap_info[2][EZ_MAX_DEVICE_SUPPORT]; +#endif + +typedef struct +{ + ULONG count; + UCHAR bssid[MAC_ADDR_LEN]; +} BSSIDENTRY; + + +VOID APPeerBeaconAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Rates[MAX_LEN_OF_SUPPORTED_RATES], *pRates = NULL, RatesLen; + BOOLEAN LegacyBssExist; + CHAR RealRssi; + UCHAR *VarIE = NULL; + USHORT LenVIE; + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + UCHAR MaxSupportedRate = 0; +#ifdef APCLI_SUPPORT + UINT ApCliIndex = 0; +#ifdef MT_MAC + BOOLEAN ApCliWcid = FALSE; +#endif /* MT_MAC */ +#endif /* APCLI_SUPPORT */ + BCN_IE_LIST *ie_list = NULL; +#ifdef MWDS + ULONG BssIdx; +#endif + + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&ie_list, sizeof(BCN_IE_LIST)); + if (ie_list == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate ie_list fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + NdisZeroMemory(ie_list, sizeof(BCN_IE_LIST)); + + /* Init Variable IE structure */ + os_alloc_mem(NULL, (UCHAR **)&VarIE, MAX_VIE_LEN); + if (VarIE == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate VarIE fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + + + + pRates = (PUCHAR)Rates; + + ie_list->Channel = Elem->Channel; + RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_0), + ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_1), + ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_2)); + + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + ie_list, + &LenVIE, + pVIE, + FALSE, + FALSE)) + { +#ifdef WH_EZ_SETUP + int j; + for (j = 0; j < pAd->ApCfg.BssidNum; j++) + { + struct wifi_dev * ez_wdev = &pAd->ApCfg.MBSSID[j].wdev; + if (IS_EZ_SETUP_ENABLED(ez_wdev)) { + ez_ap_peer_beacon_action(ez_wdev, ie_list->Addr2, ie_list->vendor_ie.ez_capability, &RealRssi, ie_list); + //ez_ap_peer_beacon_action(ez_wdev, ie_list->Addr2); +#ifdef EZ_REGROUP_SUPPORT + if(IS_REGRP_SUPP(ez_wdev) && pAd->CommonCfg.Channel == ie_list->Channel) + { + UINT8 band; + //UINT8 mac[6]= {0x20,0xaa,0x4b,0x6a,0x36,0x63}; + if(pAd->CommonCfg.Channel <= 14) + band =0; + else + band = 1; + if((ie_list->vendor_ie.support_easy_setup == 1 && + ie_list->vendor_ie.open_group_id_len == ez_wdev->ez_driver_params.open_group_id_len + && NdisEqualMemory(ie_list->vendor_ie.open_group_id,ez_wdev->ez_driver_params.open_group_id,ie_list->vendor_ie.open_group_id_len)) + || + (ie_list->vendor_ie.support_easy_setup == 0 && + SSID_EQUAL(pAd->ApCfg.MBSSID[j].Ssid,pAd->ApCfg.MBSSID[j].SsidLen, ie_list->Ssid, ie_list->SsidLen)) + ) + { + p_regrp_ap_info_struct ap_info = NULL; + + // printk("Beacon: Ch=%d,EZ: %d,Bssid: %02x:%02x:%02x:%02x:%02x:%02x\n ",ie_list->Channel, + // ie_list->vendor_ie.support_easy_setup, PRINT_MAC(ie_list->Bssid)); + + ap_info = ez_find_regrp_ap_by_bssid(regrp_ap_info[band],ie_list->Bssid); + if(ap_info == NULL) + { + ap_info = ez_add_regrp_ap(regrp_ap_info[band]); + printk("Added Entry: %02x:%02x:%02x:%02x:%02x:%02x, RSSI: %d\n",PRINT_MAC(ie_list->Bssid),RealRssi); + } + if(ap_info != NULL) + { + ap_info->Non_MAN = !ie_list->vendor_ie.support_easy_setup; + COPY_MAC_ADDR(ap_info->bssid,ie_list->Bssid); + if(ap_info->Non_MAN == 0) + { + NdisCopyMemory(&ap_info->node_number, + &ie_list->vendor_ie.beacon_info.node_number, + sizeof(EZ_NODE_NUMBER)); + NdisCopyMemory(ap_info->nw_wt, + ie_list->vendor_ie.beacon_info.network_weight, + NETWORK_WEIGHT_LEN); + } + else + { + NdisZeroMemory(&ap_info->node_number, + sizeof(EZ_NODE_NUMBER)); + NdisZeroMemory(ap_info->nw_wt, + NETWORK_WEIGHT_LEN); + } + ap_info->last_rssi = RealRssi; + ap_info->rx_cnt++; + ap_info->rssi_sum += RealRssi; + if(ap_info->rx_cnt <= 0) + { + ap_info->rssi_sum = RealRssi; + ap_info->rx_cnt = 1; + } + ap_info->avg_rssi = (CHAR)( (ap_info->rssi_sum)/(INT32)(ap_info->rx_cnt)); + NdisGetSystemUpTime(&ap_info->last_rx_time); + + + } + } + } +#endif + + } + } + +#endif + + + /* ignore BEACON not in this channel */ + if (ie_list->Channel != pAd->CommonCfg.Channel +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + && (pAd->CommonCfg.bOverlapScanning == FALSE) +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + ) + { + goto __End_Of_APPeerBeaconAction; + } + +#ifdef IDS_SUPPORT + /* Conflict SSID detection */ + RTMPConflictSsidDetection(pAd, (PUCHAR)ie_list->Ssid, ie_list->SsidLen, + (CHAR)Elem->rssi_info.raw_rssi[0], + (CHAR)Elem->rssi_info.raw_rssi[1], + (CHAR)Elem->rssi_info.raw_rssi[2]); +#endif /* IDS_SUPPORT */ + + +#ifdef DOT11_N_SUPPORT + /* 40Mhz BSS Width Trigger events Intolerant devices */ + if ((RealRssi > OBSS_BEACON_RSSI_THRESHOLD) && (ie_list->HtCapability.HtCapInfo.Forty_Mhz_Intolerant)) /* || (HtCapabilityLen == 0))) */ + { + Handle_BSS_Width_Trigger_Events(pAd); + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) +#ifdef DOT11N_DRAFT3 + && (pAd->CommonCfg.bOverlapScanning == FALSE) +#endif /* DOT11N_DRAFT3 */ + ) + { + if (pAd->CommonCfg.Channel<=14) + { + if (((pAd->CommonCfg.CentralChannel+2) != ie_list->Channel) && + ((pAd->CommonCfg.CentralChannel-2) != ie_list->Channel)) + { +/* + DBGPRINT(RT_DEBUG_TRACE, ("%02x:%02x:%02x:%02x:%02x:%02x is a legacy BSS (%d) \n", + Bssid[0], Bssid[1], Bssid[2], Bssid[3], Bssid[4], Bssid[5], Channel)); +*/ + goto __End_Of_APPeerBeaconAction; + } + } + else + { + if (ie_list->Channel != pAd->CommonCfg.Channel) + { + //goto __End_Of_APPeerBeaconAction; + } + } + } +#endif /* DOT11_N_SUPPORT */ + + SupportRate(ie_list->SupRate, ie_list->SupRateLen, ie_list->ExtRate, ie_list->ExtRateLen, &pRates, &RatesLen, &MaxSupportedRate); + + if ((ie_list->Erp & 0x01) || (RatesLen <= 4)) + LegacyBssExist = TRUE; + else + LegacyBssExist = FALSE; + + if (LegacyBssExist && pAd->CommonCfg.DisableOLBCDetect == 0) + { + pAd->ApCfg.LastOLBCDetectTime = pAd->Mlme.Now32; + + } + +#ifdef DOT11_N_SUPPORT + if ((pAd->CommonCfg.bHTProtect) + && (ie_list->HtCapabilityLen == 0) && (RealRssi > OBSS_BEACON_RSSI_THRESHOLD)) + { + + pAd->ApCfg.LastNoneHTOLBCDetectTime = pAd->Mlme.Now32; + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef APCLI_SUPPORT +#ifdef MT_MAC +#ifdef MULTI_APCLI_SUPPORT + if (Elem->Wcid == APCLI_MCAST_WCID(0) || Elem->Wcid == APCLI_MCAST_WCID(1)) + { + ApCliWcid = TRUE; + } +#else /* MULTI_APCLI_SUPPORT */ + if (Elem->Wcid == APCLI_MCAST_WCID) + ApCliWcid = TRUE; +#endif /* !MULTI_APCLI_SUPPORT */ +#endif + if (Elem->Wcid < MAX_LEN_OF_MAC_TABLE +#ifdef MT_MAC + || ApCliWcid +#endif + ) + { + PMAC_TABLE_ENTRY pEntry = NULL; +#ifdef MT_MAC + if (ApCliWcid == FALSE) +#endif + pEntry = &pAd->MacTab.Content[Elem->Wcid]; +#ifdef MT_MAC + else + pEntry = MacTableLookup(pAd, ie_list->Addr2);//Found the pEntry from Peer Bcn Content +#endif /* MT_MAC */ + + + if (pEntry && IS_ENTRY_APCLI(pEntry) && (pEntry->func_tb_idx < MAX_APCLI_NUM)) + { + //printk("%s: ===> beacon FINAL WCID[%d]\n", __FUNCTION__, Elem->Wcid); + ApCliIndex = pEntry->func_tb_idx; + pAd->ApCfg.ApCliTab[ApCliIndex].ApCliRcvBeaconTime = pAd->Mlme.Now32; +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(pEntry->wdev)) { +#ifdef IF_UP_DOWN + UINT8 bcn_config_same = + ez_apcli_check_beacon_params(pEntry->wdev, + ie_list->vendor_ie.beacon_info); + + if (pAd->ApCfg.ApCliTab[ApCliIndex].Valid == 1 + && pEntry->easy_setup_enabled == 1 + && bcn_config_same == FALSE) { + pEntry->wdev->ez_driver_params.ez_apcli_peer_ap_config_cnt++; + DBGPRINT(RT_DEBUG_ERROR, + ("APCLI:Beacon params of Peer not matching %d\n", + pEntry->wdev->ez_driver_params.ez_apcli_peer_ap_config_cnt)); + + if (pEntry->wdev->ez_driver_params.ez_apcli_peer_ap_config_cnt > 100) + ez_apcli_disconnect_both_intf(pEntry->wdev); + goto __End_Of_APPeerBeaconAction; + } + if (bcn_config_same == TRUE) + pEntry->wdev->ez_driver_params.ez_apcli_peer_ap_config_cnt = 0; +#endif + } +#endif + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + /* Check if root-ap change BW to 20 */ + if ((ie_list->AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_NONE) && + (ie_list->AddHtInfo.AddHtInfo.RecomWidth == 0)) + { +#ifdef MAC_REPEATER_SUPPORT + UINT ifIndex; + UCHAR CliIdx; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; +#endif /* MAC_REPEATER_SUPPORT */ + pEntry->HTPhyMode.field.BW = 0; +#ifdef MAC_REPEATER_SUPPORT + ifIndex = pEntry->func_tb_idx; + + 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 ((ie_list->AddHtInfo.AddHtInfo.ExtChanOffset != EXTCHA_NONE) && + (ie_list->HtCapabilityLen > 0) && + (ie_list->HtCapability.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->func_tb_idx; + + 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")); + } + } + } + + //ApCliWaitProbRsp(pAd, ApCliIndex); + if ( /*ApCliWaitProbRsp(pAd, ApCliIndex) && */ + (NdisEqualMemory(pAd->ApCfg.ApCliTab[ApCliIndex].CfgApCliBssid, ie_list->Bssid, MAC_ADDR_LEN))) + { + MlmeEnqueue(pAd, APCLI_SYNC_STATE_MACHINE, APCLI_MT2_PEER_BEACON, Elem->MsgLen, Elem->Msg, ApCliIndex); + } + } +#endif /* APCLI_SUPPORT */ + +#ifdef WDS_SUPPORT + do + { + MAC_TABLE_ENTRY *pEntry; + BOOLEAN bWmmCapable; + + /* check BEACON does in WDS TABLE. */ + pEntry = WdsTableLookup(pAd, ie_list->Addr2, FALSE); + bWmmCapable = ie_list->EdcaParm.bValid ? TRUE : FALSE; + + if (pEntry) + { + WdsPeerBeaconProc(pAd, pEntry, ie_list->CapabilityInfo, + MaxSupportedRate, RatesLen, bWmmCapable, + ie_list->RalinkIe, &ie_list->HtCapability, + ie_list->HtCapabilityLen); + } + } while(FALSE); +#endif /* WDS_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (pAd->CommonCfg.bOverlapScanning == TRUE) + { + INT index,secChIdx; + //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 == ie_list->Channel) + { + secChIdx = -1; + if (ie_list->HtCapabilityLen > 0 && ie_list->AddHtInfoLen > 0) + { /* This is a 11n AP. */ + pAd->ChannelList[index].bEffectedChannel |= EFFECTED_CH_PRIMARY; /* 2; // 2 for 11N 20/40MHz AP with primary channel set as this channel. */ + pAdd_HtInfo = &ie_list->AddHtInfo.AddHtInfo; + if (pAdd_HtInfo->ExtChanOffset == EXTCHA_BELOW) + { +#ifdef A_BAND_SUPPORT + if (ie_list->Channel > 14) + secChIdx = ((index > 0) ? (index - 1) : -1); + else +#endif /* A_BAND_SUPPORT */ + secChIdx = ((index >= 4) ? (index - 4) : -1); + } + else if (pAdd_HtInfo->ExtChanOffset == EXTCHA_ABOVE) + { +#ifdef A_BAND_SUPPORT + if (ie_list->Channel > 14) + secChIdx = (((index+1) < pAd->ChannelListNum) ? (index + 1) : -1); + else +#endif /* A_BAND_SUPPORT */ + secChIdx = (((index+4) < pAd->ChannelListNum) ? (index + 4) : -1); + } + + if (secChIdx >=0) + pAd->ChannelList[secChIdx].bEffectedChannel |= EFFECTED_CH_SECONDARY; /* 1; */ + + if ((pAd->CommonCfg.Channel != ie_list->Channel) || + (pAdd_HtInfo->ExtChanOffset != pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset) + ) + pAd->CommonCfg.BssCoexApCnt++; + } + else + { + /* This is a legacy AP. */ + pAd->ChannelList[index].bEffectedChannel |= EFFECTED_CH_LEGACY; /* 4; 1 for legacy AP. */ + pAd->CommonCfg.BssCoexApCnt++; + } + + //found = TRUE; + } + } + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ +#ifdef MWDS + BssIdx = BssTableSearch(&pAd->ScanTab, ie_list->Bssid, ie_list->Channel); + if (BssIdx != BSS_NOT_FOUND) + { + pAd->ScanTab.BssEntry[BssIdx].bSupportMWDS = FALSE; + if(ie_list->vendor_ie.mtk_cap_found) + { + BOOLEAN bSupportMWDS = FALSE; + if(ie_list->vendor_ie.support_mwds) + bSupportMWDS = TRUE; + if(pAd->ScanTab.BssEntry[BssIdx].bSupportMWDS != bSupportMWDS) + pAd->ScanTab.BssEntry[BssIdx].bSupportMWDS = bSupportMWDS; + } + } +#endif /* MWDS */ + } + /* 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 (pAd->pChannelInfo != NULL) + { + if (ie_list->Channel == pAd->ApCfg.AutoChannel_Channel) + { + if (AutoChBssSearchWithSSID(pAd, ie_list->Bssid, (PUCHAR)ie_list->Ssid, ie_list->SsidLen, ie_list->Channel) == BSS_NOT_FOUND) + pAd->pChannelInfo->ApCnt[pAd->ApCfg.current_channel_index]++; + AutoChBssInsertEntry(pAd, ie_list->Bssid, ie_list->Ssid, ie_list->SsidLen, ie_list->Channel, ie_list->NewExtChannelOffset, RealRssi); + } + } +} +#endif /* CONFIG_AP_SUPPORT */ +/*#endif // AUTO_CH_SELECT_ENHANCE */ + +LabelErr: + if (VarIE != NULL) + os_free_mem(NULL, VarIE); + if (ie_list != NULL) + os_free_mem(NULL, ie_list); + + return; +} + +#ifdef AP_SCAN_SUPPORT +/* + ========================================================================== + Description: + ========================================================================== + */ +VOID APInvalidStateWhenScan(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + DBGPRINT(RT_DEBUG_TRACE, ("AYNC - InvalidStateWhenScan(state=%ld). Reset SYNC machine\n", pAd->Mlme.ApSyncMachine.CurrState)); +} + +/* + ========================================================================== + Description: + Scan timeout handler, executed in timer thread + ========================================================================== + */ +VOID APScanTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; + + DBGPRINT(RT_DEBUG_TRACE, ("AP SYNC - Scan Timeout \n")); + MlmeEnqueue(pAd, AP_SYNC_STATE_MACHINE, APMT2_SCAN_TIMEOUT, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); +} + +/* + ========================================================================== + Description: + Scan timeout procedure. basically add channel index by 1 and rescan + ========================================================================== + */ +VOID APScanTimeoutAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ +#ifdef WH_EZ_SETUP + ez_dev_t *ezdev = NULL; + BOOLEAN b_internal_force_connect_bssid = FALSE; +#endif + +#ifdef CONFIG_AP_SUPPORT +#endif +#ifdef AP_PARTIAL_SCAN_SUPPORT + pAd->ScanCtrl.Channel = RTMPFindScanChannel(pAd, pAd->ScanCtrl.Channel); +#else + pAd->ScanCtrl.Channel = NextChannel(pAd, pAd->ScanCtrl.Channel); +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* + iwpriv set auto channel selection + update the current index of the channel + */ + 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 */ + +#ifdef WH_EZ_SETUP + if (pAd->ApCfg.ScanReqwdev) { + ezdev = (ez_dev_t *)pAd->ApCfg.ScanReqwdev->ez_driver_params.ezdev; + if (ezdev) + b_internal_force_connect_bssid = ezdev->ez_security.internal_force_connect_bssid; + } + + if (IS_EZ_SETUP_ENABLED(pAd->ApCfg.ScanReqwdev) && + (pAd->ApCfg.ScanReqwdev->ez_driver_params.scan_one_channel || + b_internal_force_connect_bssid)) { + pAd->ScanCtrl.Channel = 0; + /*pAd->ScanCtrl.PartialScan.bScanning = FALSE;*/ + } +#endif /* WH_EZ_SETUP */ + + ScanNextChannel(pAd, OPMODE_AP, pAd->ApCfg.ScanReqwdev); +} + +/* + ========================================================================== + Description: + MLME SCAN req state machine procedure + ========================================================================== + */ +VOID APMlmeScanReqAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + BOOLEAN Cancelled; + UCHAR Ssid[MAX_LEN_OF_SSID], SsidLen, ScanType, BssType; +#ifdef CONFIG_AP_SUPPORT +#endif + struct wifi_dev *wdev = (struct wifi_dev *)Elem->Priv; +#ifdef WH_EZ_SETUP + CHAR apcli_idx; + MAC_TABLE_ENTRY *pMacEntry; + struct wifi_dev *wdev; +#endif + + /* Suspend MSDU transmission here */ + RTMPSuspendMsduTransmission(pAd); + + /* first check the parameter sanity */ + if (MlmeScanReqSanity(pAd, Elem->Msg, Elem->MsgLen, &BssType, (PCHAR)Ssid, &SsidLen, &ScanType + )) + { + DBGPRINT(RT_DEBUG_TRACE, ("AP SYNC - MlmeScanReqAction\n")); + NdisGetSystemUpTime(&pAd->ApCfg.LastScanTime); + + RTMPCancelTimer(&pAd->ScanCtrl.APScanTimer, &Cancelled); + + /* record desired BSS parameters */ + pAd->ScanCtrl.BssType = BssType; + pAd->ScanCtrl.ScanType = ScanType; + pAd->ScanCtrl.SsidLen = SsidLen; + NdisMoveMemory(pAd->ScanCtrl.Ssid, Ssid, SsidLen); + /* only scan the channel which binding band supported */ + pAd->ApCfg.ScanReqwdev = (struct wifi_dev *)Elem->Priv; + + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED((struct wifi_dev *)Elem->Priv)) + { + pAd->ApCfg.ScanReqwdev = (struct wifi_dev *)Elem->Priv; + apcli_idx = pAd->ApCfg.ScanReqwdev->func_idx; +#ifdef WSC_AP_SUPPORT + if(!((pAd->ApCfg.ApCliTab[apcli_idx].WscControl.WscConfMode != WSC_DISABLE) + && (pAd->ApCfg.ApCliTab[apcli_idx].WscControl.bWscTrigger == TRUE))) +#endif + { + //ez_apcli_check_partial_scan(pAd, apcli_idx); + } + } else { + pAd->ApCfg.ScanReqwdev = NULL; + DBGPRINT(RT_DEBUG_TRACE, ("%s, ScanReqwdev is NULL!!!!\n", __func__)); + } +#endif + + { + /* start from the first channel */ +#ifdef AP_PARTIAL_SCAN_SUPPORT + pAd->ScanCtrl.Channel = RTMPFindScanChannel(pAd, 0); +#else + pAd->ScanCtrl.Channel = FirstChannel(pAd); +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + } + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED((struct wifi_dev *)Elem->Priv)) + { + wdev = (struct wifi_dev *)Elem->Priv; + apcli_idx = wdev->func_idx; +#ifdef WSC_AP_SUPPORT + if(!((pAd->ApCfg.ApCliTab[apcli_idx].WscControl.WscConfMode != WSC_DISABLE) + && (pAd->ApCfg.ApCliTab[apcli_idx].WscControl.bWscTrigger == TRUE))) +#endif + { + if (IS_SINGLE_CHIP_DBDC(pAd)) + { + if (pAd->ApCfg.BssidNum == 2 && pAd->CommonCfg.dbdc_mode == 1) + { + } + } + } + } + if (IS_EZ_SETUP_ENABLED(pAd->ApCfg.ScanReqwdev) + /*&& (pAd->ApCfg.ScanReqwdev->ez_security.scan_one_channel || pAd->ApCfg.ScanReqwdev->ez_security.internal_force_connect_bssid)*/ + && ez_ap_scan_complete_handle(pAd->ApCfg.ScanReqwdev) + ) { + //pAd->ScanCtrl.Channel = pAd->ApCfg.ScanReqwdev->channel; + if(pAd->CommonCfg.Channel != 0) + pAd->ScanCtrl.Channel = pAd->CommonCfg.Channel; + + EZ_DEBUG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("AP SYNC - Only scan ch.%d and keep original BW setting.\n", pAd->ScanCtrl.Channel)); + } + else +#endif /* WH_EZ_SETUP */ + { + /* Let BBP register at 20MHz to do scan */ + bbp_set_bw(pAd, BW_20); + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - BBP R4 to 20MHz.l\n")); + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (pAd->ApCfg.bAutoChannelAtBootup == TRUE)/* iwpriv set auto channel selection */ + { + APAutoChannelInit(pAd); + pAd->ApCfg.AutoChannel_Channel = pAd->ChannelList[0].Channel; + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef WH_EZ_SETUP +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (pAd->ApCfg.ScanReqwdev) { + apcli_idx = pAd->ApCfg.ScanReqwdev->func_idx; + pMacEntry = MacTableLookup(pAd, pAd->ApCfg.ApCliTab[apcli_idx].wdev.bssid); + if (pMacEntry && pAd->ApCfg.ApCliTab[apcli_idx].Valid + && (IS_EZ_SETUP_ENABLED(&pAd->ApCfg.ApCliTab[apcli_idx].wdev))) { + pAd->Mlme.ApSyncMachine.CurrState = AP_SCAN_LISTEN; + ApCliRTMPSendNullFrame(pAd, pMacEntry->CurrTxRate, FALSE, pMacEntry, PWR_SAVE); + } + } +#endif //APCLI_SUPPORT +#endif //CONFIG_AP_SUPPORT +#endif //WH_EZ_SETUP + ScanNextChannel(pAd, OPMODE_AP, wdev); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("AP SYNC - MlmeScanReqAction() sanity check fail. BUG!!!\n")); + pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; + } +} + + +/* + ========================================================================== + Description: + peer sends beacon back when scanning + ========================================================================== + */ +VOID APPeerBeaconAtScanAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + //PFRAME_802_11 pFrame; + UCHAR *VarIE = NULL; + USHORT LenVIE; + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + CHAR RealRssi = -127; +#ifdef APCLI_SUPPORT +#ifdef WH_EVENT_NOTIFIER + PFRAME_802_11 pFrame; +#endif +#endif + + BCN_IE_LIST *ie_list = NULL; +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + UCHAR Snr0 = Elem->Snr0; + UCHAR Snr1 = Elem->Snr1; + + Snr0 = ConvertToSnr(pAd, Snr0); + Snr1 = ConvertToSnr(pAd, Snr1); +#endif + + os_alloc_mem(pAd, (UCHAR **)&ie_list, sizeof(BCN_IE_LIST)); + if (!ie_list) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Alloc memory for ie_list fail!!!\n", __FUNCTION__)); + return; + } + NdisZeroMemory((UCHAR *)ie_list, sizeof(BCN_IE_LIST)); + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&VarIE, MAX_VIE_LEN); + if (VarIE == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + +#ifdef APCLI_SUPPORT +#ifdef WH_EVENT_NOTIFIER + pFrame = (PFRAME_802_11) Elem->Msg; +#endif +#endif + + //pFrame = (PFRAME_802_11) Elem->Msg; + /* Init Variable IE structure */ + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + + + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, Elem->MsgLen, Elem->Channel, + ie_list, &LenVIE, pVIE, FALSE, FALSE)) + { + ULONG Idx; + CHAR Rssi = -127; + + RealRssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_0), + ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_1), + ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_2)); + + + +#ifdef WH_EZ_SETUP + if( !IS_ADPTR_EZ_SETUP_ENABLED(pAd) ) +#endif + { + /* ignore BEACON not in this channel */ + if (ie_list->Channel != pAd->ScanCtrl.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) && (ie_list->HtCapability.HtCapInfo.Forty_Mhz_Intolerant)) /* || (HtCapabilityLen == 0))) */ + { + Handle_BSS_Width_Trigger_Events(pAd); + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef IDS_SUPPORT + /* Conflict SSID detection */ + if (ie_list->Channel == pAd->CommonCfg.Channel) + RTMPConflictSsidDetection(pAd, ie_list->Ssid, ie_list->SsidLen, + Elem->rssi_info.raw_rssi[0], + Elem->rssi_info.raw_rssi[1], + Elem->rssi_info.raw_rssi[2]); +#endif /* IDS_SUPPORT */ + + /* + This correct im-proper RSSI indication during SITE SURVEY issue. + Always report bigger RSSI during SCANNING when receiving multiple BEACONs from the same AP. + This case happens because BEACONs come from adjacent channels, so RSSI become weaker as we + switch to more far away channels. + */ + Idx = BssTableSearch(&pAd->ScanTab, ie_list->Bssid, ie_list->Channel); + if (Idx != BSS_NOT_FOUND) + { + UINT32 u4MaxBssEntrySize = sizeof(pAd->ScanTab.BssEntry)/sizeof(pAd->ScanTab.BssEntry[0]); + if(Idx < u4MaxBssEntrySize) + Rssi = pAd->ScanTab.BssEntry[Idx].Rssi; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Over buffer size!\n", __FUNCTION__)); + } + } + + + + /* 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->rssi_info, RSSI_IDX_0), + ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_1), + ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_2)); + if ((RealRssi + pAd->BbpRssiToDbmDelta) > Rssi) + Rssi = RealRssi + pAd->BbpRssiToDbmDelta; + + Idx = BssTableSetEntry(pAd, &pAd->ScanTab, ie_list, Rssi, LenVIE, pVIE +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + , + Snr0, + Snr1 +#endif + ); + if (Idx != BSS_NOT_FOUND) + { + NdisMoveMemory(pAd->ScanTab.BssEntry[Idx].PTSF, &Elem->Msg[24], 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Idx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); + } + +#ifdef MWDS + if (Idx != BSS_NOT_FOUND) + { + pAd->ScanTab.BssEntry[Idx].bSupportMWDS = FALSE; + if(ie_list->vendor_ie.mtk_cap_found) + { + BOOLEAN bSupportMWDS = FALSE; + if(ie_list->vendor_ie.support_mwds) + bSupportMWDS = TRUE; + if(pAd->ScanTab.BssEntry[Idx].bSupportMWDS != bSupportMWDS) + pAd->ScanTab.BssEntry[Idx].bSupportMWDS = bSupportMWDS; + } + } +#endif /* MWDS */ +#ifdef APCLI_SUPPORT +#ifdef WH_EVENT_NOTIFIER + if(pFrame && (pFrame->Hdr.FC.SubType == SUBTYPE_PROBE_RSP)) + { + EventHdlr pEventHdlrHook = NULL; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_AP_PROBE_RSP); + if(pEventHdlrHook && pAd->ApCfg.ScanReqwdev) + pEventHdlrHook(pAd, pAd->ApCfg.ScanReqwdev, ie_list, Elem); + } +#endif /* WH_EVENT_NOTIFIER */ +#endif /* APCLI_SUPPORT */ + + } + + /* sanity check fail, ignored */ +__End_Of_APPeerBeaconAtScanAction: + /*scan beacon in pastive */ +#ifdef CONFIG_AP_SUPPORT +IF_DEV_CONFIG_OPMODE_ON_AP(pAd) +{ + if (pAd->pChannelInfo != NULL) + { + if (ie_list->Channel == pAd->ApCfg.AutoChannel_Channel) + { + if (AutoChBssSearchWithSSID(pAd, ie_list->Bssid, (PUCHAR)ie_list->Ssid, ie_list->SsidLen, ie_list->Channel) == BSS_NOT_FOUND) + pAd->pChannelInfo->ApCnt[pAd->ApCfg.current_channel_index]++; + AutoChBssInsertEntry(pAd, ie_list->Bssid, (CHAR *)ie_list->Ssid, ie_list->SsidLen, ie_list->Channel, ie_list->NewExtChannelOffset, RealRssi); + } + } +} +#endif /* CONFIG_AP_SUPPORT */ + +LabelErr: + if (VarIE != NULL) + os_free_mem(NULL, VarIE); + if (ie_list != NULL) + os_free_mem(NULL, ie_list); + +} + +/* + ========================================================================== + Description: + MLME Cancel the SCAN req state machine procedure + ========================================================================== + */ +VOID APScanCnclAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + BOOLEAN Cancelled; + + RTMPCancelTimer(&pAd->ScanCtrl.APScanTimer, &Cancelled); + pAd->ScanCtrl.Channel = 0; + ScanNextChannel(pAd, OPMODE_AP, pAd->ApCfg.ScanReqwdev); + + 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, + IN struct wifi_dev *wdev +) +{ + MLME_SCAN_REQ_STRUCT ScanReq; + BOOLEAN bResetBssTable = TRUE; +#ifdef WH_EZ_SETUP + struct wifi_dev* other_band_wdev; + struct wifi_dev* other_band_wdev_ap; +#endif + +#ifdef WH_EZ_SETUP + + if ((wdev != NULL) && (IS_EZ_SETUP_ENABLED(wdev)) && RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + { + /* + Still scanning, ignore this scan. + */ + EZ_DEBUG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("%s: Scanning now!\n", __FUNCTION__)); + return; + } + + if ((wdev != NULL) && (IS_EZ_SETUP_ENABLED(wdev)) && (ScanRunning(pAd) == TRUE)) + { + EZ_DEBUG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("%s: Scan Already Running! \n", __FUNCTION__)); + return; + } + + if ((wdev != NULL) && IS_SINGLE_CHIP_DBDC(pAd) && (IS_EZ_SETUP_ENABLED(wdev))) + { + if (pAd->ApCfg.BssidNum == 2 && pAd->CommonCfg.dbdc_mode == 1) + { + other_band_wdev = &pAd->ApCfg.ApCliTab[wdev->func_idx ^ 1].wdev; + other_band_wdev_ap = &pAd->ApCfg.MBSSID[wdev->func_idx ^ 1].wdev; + if ((other_band_wdev->ez_driver_params.bPartialScanRunning == TRUE) || (other_band_wdev_ap->ez_driver_params.bPartialScanRunning == TRUE)) + { + EZ_DEBUG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("%s: Partial Scan Already Running on other Band! \n", __FUNCTION__)); + return; + } + } + } + + if((wdev != NULL) && IS_EZ_SETUP_ENABLED(wdev)) + increment_best_ap_rssi_threshold(&pAd->ApCfg.ApCliTab[wdev->func_idx].wdev); +#endif + + AsicDisableSync(pAd); +#ifdef AP_PARTIAL_SCAN_SUPPORT + if (((pAd->ApCfg.bPartialScanning == TRUE) && (pAd->ApCfg.LastPartialScanChannel != 0))) + bResetBssTable = FALSE; +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + if (bResetBssTable) { + BssTableInit(&pAd->ScanTab); +#ifdef NEIGHBORING_AP_STAT + pAd->ScanTab.ScanResult.cnt = 0; + RTMPZeroMemory(pAd->ScanTab.ScanResult.items, MAX_COUNT_OF_BSS_ENTRIES * sizeof(SCAN_RPT_ITEM)); +#endif + } + pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; + + RTMPZeroMemory(ScanReq.Ssid, MAX_LEN_OF_SSID); + ScanReq.SsidLen = 0; + if (pSsid) + { + ScanReq.SsidLen = pSsid->SsidLength; + NdisMoveMemory(ScanReq.Ssid, pSsid->Ssid, pSsid->SsidLength); + } + ScanReq.BssType = BSS_ANY; + ScanReq.ScanType = ScanType; + pAd->ApCfg.bAutoChannelAtBootup = ChannelSel; + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev)) + MlmeEnqueue(pAd, AP_SYNC_STATE_MACHINE, APMT2_MLME_SCAN_REQ, + sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, (ULONG)wdev); + else +#endif + MlmeEnqueue(pAd, AP_SYNC_STATE_MACHINE, APMT2_MLME_SCAN_REQ, + sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq, (ULONG)wdev); + RTMP_MLME_HANDLER(pAd); +} + + +BOOLEAN ApScanRunning(RTMP_ADAPTER *pAd) +{ + return (pAd->Mlme.ApSyncMachine.CurrState == AP_SCAN_LISTEN) ? TRUE : FALSE; +} + +#ifdef AP_PARTIAL_SCAN_SUPPORT +/* + ========================================================================== + Description: + + Return: + scan_channel - channel to scan. + Note: + return 0 if no more next channel + ========================================================================== + */ +UCHAR FindPartialScanChannel( + IN PRTMP_ADAPTER pAd) +{ + UCHAR scan_channel = 0; + if (pAd->ApCfg.PartialScanChannelNum > 0) + { + pAd->ApCfg.PartialScanChannelNum--; + + if (pAd->ApCfg.LastPartialScanChannel == 0) + scan_channel = FirstChannel(pAd); + else + scan_channel = NextChannel(pAd, pAd->ApCfg.LastPartialScanChannel); + + /* update last scanned channel */ + pAd->ApCfg.LastPartialScanChannel = scan_channel; + if (scan_channel == 0) + { + pAd->ApCfg.bPartialScanning = FALSE; + pAd->ApCfg.PartialScanChannelNum = DEFLAUT_PARTIAL_SCAN_CH_NUM; + } + } + else + { + /* Pending for next partial scan */ + scan_channel = 0; + pAd->ApCfg.PartialScanChannelNum = DEFLAUT_PARTIAL_SCAN_CH_NUM; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s, %u, scan_channel = %u, PartialScanChannelNum = %u, LastPartialScanChannel = %u, bPartialScanning = %u\n", + __FUNCTION__, __LINE__, + scan_channel, + pAd->ApCfg.PartialScanChannelNum, + pAd->ApCfg.LastPartialScanChannel, + pAd->ApCfg.bPartialScanning)); + return scan_channel; +} +#endif /* AP_PARTIAL_SCAN_SUPPORT */ +#endif /* AP_SCAN_SUPPORT */ + + +/* + ========================================================================== + Description: + The sync state machine, + Parameters: + Sm - pointer to the state machine + Note: + the state machine looks like the following + + AP_SYNC_IDLE + APMT2_PEER_PROBE_REQ peer_probe_req_action + ========================================================================== + */ +VOID APSyncStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, (STATE_MACHINE_FUNC *)Trans, AP_MAX_SYNC_STATE, AP_MAX_SYNC_MSG, (STATE_MACHINE_FUNC)Drop, AP_SYNC_IDLE, AP_SYNC_MACHINE_BASE); + + StateMachineSetAction(Sm, AP_SYNC_IDLE, APMT2_PEER_PROBE_REQ, (STATE_MACHINE_FUNC)APPeerProbeReqAction); + StateMachineSetAction(Sm, AP_SYNC_IDLE, APMT2_PEER_BEACON, (STATE_MACHINE_FUNC)APPeerBeaconAction); +#ifdef AP_SCAN_SUPPORT + StateMachineSetAction(Sm, AP_SYNC_IDLE, APMT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)APMlmeScanReqAction); + + /* scan_listen state */ + StateMachineSetAction(Sm, AP_SCAN_LISTEN, APMT2_MLME_SCAN_REQ, (STATE_MACHINE_FUNC)APInvalidStateWhenScan); + StateMachineSetAction(Sm, AP_SCAN_LISTEN, APMT2_PEER_BEACON, (STATE_MACHINE_FUNC)APPeerBeaconAtScanAction); + StateMachineSetAction(Sm, AP_SCAN_LISTEN, APMT2_PEER_PROBE_RSP, (STATE_MACHINE_FUNC)APPeerBeaconAtScanAction); + StateMachineSetAction(Sm, AP_SCAN_LISTEN, APMT2_SCAN_TIMEOUT, (STATE_MACHINE_FUNC)APScanTimeoutAction); + StateMachineSetAction(Sm, AP_SCAN_LISTEN, APMT2_MLME_SCAN_CNCL, (STATE_MACHINE_FUNC)APScanCnclAction); + + RTMPInitTimer(pAd, &pAd->ScanCtrl.APScanTimer, GET_TIMER_FUNCTION(APScanTimeout), pAd, FALSE); +#endif /* AP_SCAN_SUPPORT */ +} + + +VOID SupportRate( + IN PUCHAR SupRate, + IN UCHAR SupRateLen, + IN PUCHAR ExtRate, + IN UCHAR ExtRateLen, + OUT PUCHAR *ppRates, + OUT PUCHAR RatesLen, + OUT PUCHAR pMaxSupportRate) +{ + INT i; + + *pMaxSupportRate = 0; + + if ((SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES) && (SupRateLen > 0)) + { + NdisMoveMemory(*ppRates, SupRate, SupRateLen); + *RatesLen = SupRateLen; + } + else + { + /* HT rate not ready yet. return true temporarily. rt2860c */ + /*DBGPRINT(RT_DEBUG_TRACE, ("PeerAssocReqSanity - wrong IE_SUPP_RATES\n")); */ + *RatesLen = 8; + *(*ppRates + 0) = 0x82; + *(*ppRates + 1) = 0x84; + *(*ppRates + 2) = 0x8b; + *(*ppRates + 3) = 0x96; + *(*ppRates + 4) = 0x12; + *(*ppRates + 5) = 0x24; + *(*ppRates + 6) = 0x48; + *(*ppRates + 7) = 0x6c; + DBGPRINT(RT_DEBUG_TRACE, ("SUPP_RATES., Len=%d\n", SupRateLen)); + } + + if (ExtRateLen + *RatesLen <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory((*ppRates + (ULONG)*RatesLen), ExtRate, ExtRateLen); + *RatesLen = (*RatesLen) + ExtRateLen; + } + else + { + NdisMoveMemory((*ppRates + (ULONG)*RatesLen), ExtRate, MAX_LEN_OF_SUPPORTED_RATES - (*RatesLen)); + *RatesLen = MAX_LEN_OF_SUPPORTED_RATES; + } + + + + for (i = 0; i < *RatesLen; i++) + { + if(*pMaxSupportRate < (*(*ppRates + i) & 0x7f)) + *pMaxSupportRate = (*(*ppRates + i) & 0x7f); + } + + return; +} + +#ifdef DOT11_N_SUPPORT +/* Regulatory classes in the USA */ + +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, 0); + pIE->NewChannelNum = pAd->CommonCfg.Channel; + pIE->ChannelSwitchCount = (pAd->Dot11_H.CSPeriod - pAd->Dot11_H.CSCount - 1); +} +#endif /* DOT11_N_SUPPORT */ +INT Set_Reg_Domain_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + pAd->reg_domain = simple_strtol(arg, 0, 10); + /* 0: REG_LOCAL 1:REG_GLOBAL */ + MTWF_LOG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("reg_domain = %u\n", pAd->reg_domain)); + return TRUE; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_wds.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_wds.c new file mode 100644 index 000000000..e4dedddf2 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_wds.c @@ -0,0 +1,1403 @@ + +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + ap_wds.c + + Abstract: + Support WDS function. + + Revision History: + Who When What + ------ ---------- ---------------------------------------------- +*/ + +#ifdef WDS_SUPPORT + +#include "rt_config.h" + + +#define VAILD_KEY_INDEX( _X ) ((((_X) >= 0) && ((_X) < 4)) ? (TRUE) : (FALSE)) + + +INT ApWdsAllowToSendPacket( + IN RTMP_ADAPTER *pAd, + IN struct wifi_dev *wdev, + IN PNDIS_PACKET pPacket, + OUT UCHAR *pWcid) +{ + UCHAR idx; + INT allowed = FALSE; + RT_802_11_WDS_ENTRY *wds_entry; + + if (!wdev) + return FALSE; + + for (idx = 0; idx < MAX_WDS_ENTRY; idx++) + { + wds_entry = &pAd->WdsTab.WdsEntry[idx]; + if (ValidWdsEntry(pAd, idx) && (wdev == (&wds_entry->wdev))) + { + RTMP_SET_PACKET_WDEV(pPacket, wdev->wdev_idx); + *pWcid = (UCHAR)pAd->WdsTab.WdsEntry[idx].MacTabMatchWCID; + allowed = TRUE; + + break; + } + } + + return allowed; +} + + +INT wds_rx_foward_handle(RTMP_ADAPTER *pAd, struct wifi_dev *wdev, PNDIS_PACKET pPacket) +{ + /* + For WDS, direct to OS and no need to forwad the packet to WM + */ + return TRUE; +} + + +INT wds_rx_pkt_allow(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + HEADER_802_11 *pHeader = pRxBlk->pHeader; + MAC_TABLE_ENTRY *pEntry = NULL; + INT hdr_len = 0; + + /* handle WDS */ + if (VALID_WCID(pRxBlk->wcid) + && IS_ENTRY_WDS(&pAd->MacTab.Content[pRxBlk->wcid])) + { + if (MAC_ADDR_EQUAL(pHeader->Addr1, pAd->CurrentAddress)) + pEntry = FindWdsEntry(pAd, pRxBlk->wcid, pHeader->Addr2, pRxBlk->rx_rate.field.MODE); + else + pEntry = NULL; + + /* have no valid wds entry exist, then discard the incoming packet.*/ + if (!(pEntry && WDS_IF_UP_CHECK(pAd, pEntry->func_tb_idx))) + return FALSE; + + /*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; + // TODO: shiang-usw, remove upper setting because we need to mirgate to tr_entry! + pAd->MacTab.tr_entry[pEntry->wcid].ContinueTxFailCnt = 0; + pAd->MacTab.tr_entry[pEntry->wcid].LockEntryTx = FALSE; + + } + + RX_BLK_SET_FLAG(pRxBlk, fRX_WDS); + hdr_len = LENGTH_802_11_WITH_ADDR4; + + return hdr_len; + } + + return FALSE; +} + + +INT WdsEntryAlloc(RTMP_ADAPTER *pAd, UCHAR *pAddr) +{ + INT i, WdsTabIdx = -1; + RT_802_11_WDS_ENTRY *wds_entry; + + 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; + + wds_entry = &pAd->WdsTab.WdsEntry[i]; + if (wds_entry->Valid == FALSE) + { + wds_entry->Valid = TRUE; + pAd->WdsTab.Size ++; + COPY_MAC_ADDR(wds_entry->PeerWdsAddr, pAddr); + WdsTabIdx = i; + break; + } + else if (MAC_ADDR_EQUAL(wds_entry->PeerWdsAddr, pAddr)) + { + WdsTabIdx = i; + break; + } + } + NdisReleaseSpinLock(&pAd->WdsTabLock); + + if (i == MAX_WDS_ENTRY) + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unable to allocate WdsEntry.\n", __FUNCTION__)); + + return WdsTabIdx; +} + + +VOID WdsEntryDel(RTMP_ADAPTER *pAd, UCHAR *pAddr) +{ + INT i; + RT_802_11_WDS_ENTRY *wds_entry; + + /* delete one WDS entry */ + NdisAcquireSpinLock(&pAd->WdsTabLock); + + for (i = 0; i < MAX_WDS_ENTRY; i++) + { + wds_entry = &pAd->WdsTab.WdsEntry[i]; + if (MAC_ADDR_EQUAL(pAddr, wds_entry->PeerWdsAddr) && (wds_entry->Valid == TRUE)) + { + wds_entry->Valid = FALSE; + NdisZeroMemory(wds_entry->PeerWdsAddr, MAC_ADDR_LEN); + pAd->WdsTab.Size--; + break; + } + } + + NdisReleaseSpinLock(&pAd->WdsTabLock); +} + + +/* + ========================================================================== + Description: + Delete all WDS Entry in pAd->MacTab + ========================================================================== + */ +BOOLEAN MacTableDeleteWDSEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT wcid, + IN PUCHAR pAddr) +{ + if (wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + else + return MacTableDeleteEntry(pAd, wcid, pAddr); +} + + +/* +================================================================ +Description : because WDS and CLI share the same WCID table in ASIC. +WDS entry also insert to pAd->MacTab.content[]. +Also fills the pairwise key. +Because front MAX_AID_BA entries have direct mapping to BAEntry, which is only used as CLI. So we insert WDS +from index MAX_AID_BA. +================================================================ +*/ +MAC_TABLE_ENTRY *MacTableInsertWDSEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + UINT WdsTabIdx) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + STA_TR_ENTRY *tr_entry; + HTTRANSMIT_SETTING HTPhyMode; + RT_802_11_WDS_ENTRY *wds_entry; + struct wifi_dev *wdev; + + + /* if FULL, return */ + if (pAd->MacTab.Size >= MAX_LEN_OF_MAC_TABLE) + return NULL; + + if((pEntry = WdsTableLookup(pAd, pAddr, TRUE)) != NULL) + return pEntry; + + wds_entry = &pAd->WdsTab.WdsEntry[WdsTabIdx]; + wdev = &wds_entry->wdev; + + /* allocate one WDS entry */ + do + { + /* allocate one MAC entry */ + pEntry = MacTableInsertEntry(pAd, pAddr, wdev, ENTRY_WDS, OPMODE_AP, TRUE); + if (pEntry) + { + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + tr_entry->PortSecured = WPA_802_1X_PORT_SECURED; + + /* specific Max Tx Rate for Wds link. */ + NdisZeroMemory(&HTPhyMode, sizeof(HTTRANSMIT_SETTING)); + switch (wdev->PhyMode) + { + case 0xff: /* user doesn't specific a Mode for WDS link. */ + case MODE_OFDM: /* specific OFDM mode. */ + HTPhyMode.field.MODE = MODE_OFDM; + HTPhyMode.field.MCS = 7; + pEntry->RateLen = 8; + break; + + case MODE_CCK: + HTPhyMode.field.MODE = MODE_CCK; + HTPhyMode.field.MCS = 3; + pEntry->RateLen = 4; + break; + +#ifdef DOT11_N_SUPPORT + case MODE_HTMIX: + HTPhyMode.field.MCS = 7; + HTPhyMode.field.ShortGI = wdev->HTPhyMode.field.ShortGI; + HTPhyMode.field.BW = wdev->HTPhyMode.field.BW; + HTPhyMode.field.STBC = wdev->HTPhyMode.field.STBC; + HTPhyMode.field.MODE = MODE_HTMIX; + pEntry->RateLen = 12; + break; + + case MODE_HTGREENFIELD: + HTPhyMode.field.MCS = 7; + HTPhyMode.field.ShortGI = wdev->HTPhyMode.field.ShortGI; + HTPhyMode.field.BW = wdev->HTPhyMode.field.BW; + HTPhyMode.field.STBC = wdev->HTPhyMode.field.STBC; + HTPhyMode.field.MODE = MODE_HTGREENFIELD; + pEntry->RateLen = 12; + break; +#endif /* DOT11_N_SUPPORT */ + + default: + break; + } + + pEntry->MaxHTPhyMode.word = HTPhyMode.word; + pEntry->MinHTPhyMode.word = wdev->MinHTPhyMode.word; + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + /* default */ + pEntry->MpduDensity = 5; + pEntry->MaxRAmpduFactor = 3; + +#ifdef DOT11_N_SUPPORT + if (wdev->PhyMode >= MODE_HTMIX) + { + if (wdev->DesiredTransmitSetting.field.MCS != MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("IF-wds%d : Desired MCS = %d\n", WdsTabIdx, + wdev->DesiredTransmitSetting.field.MCS)); + + set_ht_fixed_mcs(pAd, pEntry, wdev->DesiredTransmitSetting.field.MCS, wdev->HTPhyMode.field.MCS); + } + + pEntry->MmpsMode = MMPS_DISABLE; + NdisMoveMemory(&pEntry->HTCapability, &pAd->CommonCfg.HtCapability, sizeof(HT_CAPABILITY_IE)); + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE)) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED); + + set_sta_ht_cap(pAd, pEntry, &pEntry->HTCapability); + + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + } +#endif /* DOT11_N_SUPPORT */ + else + { + NdisZeroMemory(&pEntry->HTCapability, sizeof(HT_CAPABILITY_IE)); + } + + // for now, we set this by default! + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET); + + if (wdev->bAutoTxRateSwitch == FALSE) + { + pEntry->HTPhyMode.field.MCS = wdev->DesiredTransmitSetting.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((UCHAR)wdev->DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + else + { + // TODO: shiang-MT7603, fix me for this, because we may need to set this only when we have WTBL entry for tx_rate! + pEntry->bAutoTxRateSwitch = TRUE; + } + + wds_entry->MacTabMatchWCID = (UCHAR)pEntry->wcid; + pEntry->func_tb_idx = WdsTabIdx; + pEntry->wdev = wdev; + COPY_MAC_ADDR(&wdev->bssid[0], &pEntry->Addr[0]); + + AsicUpdateRxWCIDTable(pAd, pEntry->wcid, pAddr); + AsicUpdateWdsEncryption(pAd, pEntry->wcid); + + DBGPRINT(RT_DEBUG_OFF, ("%s() - allocate entry #%d(link to WCID %d), Total= %d\n", + __FUNCTION__, WdsTabIdx, wds_entry->MacTabMatchWCID, pAd->WdsTab.Size)); + break; + } + }while(FALSE); + + return pEntry; +} + + +MAC_TABLE_ENTRY *WdsTableLookupByWcid( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount) +{ + ULONG WdsIndex; + MAC_TABLE_ENTRY *pCurEntry = NULL, *pEntry = NULL; + + if (wcid <=0 || wcid >= MAX_LEN_OF_MAC_TABLE ) + return NULL; + + NdisAcquireSpinLock(&pAd->WdsTabLock); + NdisAcquireSpinLock(&pAd->MacTabLock); + + do + { + pCurEntry = &pAd->MacTab.Content[wcid]; + WdsIndex = 0xff; + if ((pCurEntry) && IS_ENTRY_WDS(pCurEntry)) + WdsIndex = pCurEntry->func_tb_idx; + + if (WdsIndex == 0xff) + break; + + if (pAd->WdsTab.WdsEntry[WdsIndex].Valid != TRUE) + break; + + if (MAC_ADDR_EQUAL(pCurEntry->Addr, pAddr)) + { + if(bResetIdelCount) { + pCurEntry->NoDataIdleCount = 0; + // TODO: shiang-usw, remove upper setting becasue we need to migrate to tr_entry! + pAd->MacTab.tr_entry[pCurEntry->wcid].NoDataIdleCount = 0; + } + pEntry = pCurEntry; + break; + } + } while(FALSE); + + NdisReleaseSpinLock(&pAd->MacTabLock); + NdisReleaseSpinLock(&pAd->WdsTabLock); + + return pEntry; +} + + +MAC_TABLE_ENTRY *WdsTableLookup(RTMP_ADAPTER *pAd, UCHAR *addr, BOOLEAN bResetIdelCount) +{ + USHORT HashIdx; + PMAC_TABLE_ENTRY pEntry = NULL; + + NdisAcquireSpinLock(&pAd->WdsTabLock); + NdisAcquireSpinLock(&pAd->MacTabLock); + + HashIdx = MAC_ADDR_HASH_INDEX(addr); + pEntry = pAd->MacTab.Hash[HashIdx]; + + while (pEntry) + { + if (IS_ENTRY_WDS(pEntry) && MAC_ADDR_EQUAL(pEntry->Addr, addr)) + { + if(bResetIdelCount) { + pEntry->NoDataIdleCount = 0; + // TODO: shiang-usw, remove upper setting becasue we need to migrate to tr_entry! + pAd->MacTab.tr_entry[pEntry->wcid].NoDataIdleCount = 0; + } + break; + } + else + pEntry = pEntry->pNext; + } + + NdisReleaseSpinLock(&pAd->MacTabLock); + NdisReleaseSpinLock(&pAd->WdsTabLock); + + return pEntry; +} + + +MAC_TABLE_ENTRY *FindWdsEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR *pAddr, + IN UINT32 PhyMode) +{ + MAC_TABLE_ENTRY *pEntry; + RT_802_11_WDS_ENTRY *wds_entry; + + /* 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)) + { + INT WdsIdx = WdsEntryAlloc(pAd, pAddr); + if (WdsIdx >= 0 && WdsIdx < MAX_WDS_ENTRY) + { + wds_entry = &pAd->WdsTab.WdsEntry[WdsIdx]; + + /* user doesn't specific a phy mode for WDS link. */ + if (wds_entry->wdev.PhyMode == 0xff) + wds_entry->wdev.PhyMode = PhyMode; + pEntry = MacTableInsertWDSEntry(pAd, pAddr, (UCHAR)WdsIdx); + + RTMPSetSupportMCS(pAd, + OPMODE_AP, + pEntry, + pAd->CommonCfg.SupRate, + pAd->CommonCfg.SupRateLen, + pAd->CommonCfg.ExtRate, + pAd->CommonCfg.ExtRateLen, +#ifdef DOT11_VHT_AC + 0, + NULL, +#endif /* DOT11_VHT_AC */ + &pAd->CommonCfg.HtCapability, + sizeof(pAd->CommonCfg.HtCapability)); + } + else + pEntry = NULL; + } + + return pEntry; +} + + +/* + ========================================================================== + Description: + This routine is called by APMlmePeriodicExec() every second to check if + 1. any WDS client being idle for too long and should be aged-out from MAC table + ========================================================================== +*/ +VOID WdsTableMaintenance(RTMP_ADAPTER *pAd) +{ + UCHAR idx; + + if (pAd->WdsTab.Mode == WDS_DISABLE_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 ++; + // TODO: shiang-usw, remove upper setting becasue we need to migrate to tr_entry! + pAd->MacTab.tr_entry[pEntry->wcid].NoDataIdleCount++; + NdisReleaseSpinLock(&pAd->MacTabLock); + NdisReleaseSpinLock(&pAd->WdsTabLock); + + /* delete those MAC entry that has been idle for a long time */ + if (pEntry->NoDataIdleCount >= MAC_TABLE_AGEOUT_TIME) + { + DBGPRINT(RT_DEBUG_TRACE, ("ageout %02x:%02x:%02x:%02x:%02x:%02x from WDS #%d after %d-sec silence\n", + PRINT_MAC(pEntry->Addr), idx, MAC_TABLE_AGEOUT_TIME)); + if (pAd->WdsTab.Mode != WDS_LAZY_MODE) { + pEntry->NoDataIdleCount = 0; + BASessionTearDownALL(pAd, pEntry->wcid); + } else { + WdsEntryDel(pAd, pEntry->Addr); + MacTableDeleteWDSEntry(pAd, pEntry->wcid, pEntry->Addr); + } + } + } + +} + + +VOID RT28xx_WDS_Close(RTMP_ADAPTER *pAd) +{ + UINT index; + + for(index = 0; index < MAX_WDS_ENTRY; index++) + { + if (pAd->WdsTab.WdsEntry[index].wdev.if_dev) + RtmpOSNetDevClose(pAd->WdsTab.WdsEntry[index].wdev.if_dev); + } + return; +} + + + + +VOID WdsDown(RTMP_ADAPTER *pAd) +{ + int i; + + for (i=0; iWdsTab.WdsEntry[i].PeerWdsAddr, TRUE)) + MacTableDeleteWDSEntry(pAd, pAd->WdsTab.WdsEntry[i].MacTabMatchWCID, + pAd->WdsTab.WdsEntry[i].PeerWdsAddr); + } +} + + +VOID AsicUpdateWdsRxWCIDTable(RTMP_ADAPTER *pAd) +{ + UINT index; + MAC_TABLE_ENTRY *pEntry = NULL; + RT_802_11_WDS_ENTRY *wds_entry; + + for(index = 0; index < MAX_WDS_ENTRY; index++) + { + wds_entry = &pAd->WdsTab.WdsEntry[index]; + if (pAd->WdsTab.Mode >= WDS_LAZY_MODE) { + wds_entry->wdev.PhyMode = 0xff; + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + wds_entry->wdev.PhyMode = MODE_HTMIX; + else { + if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B)) + wds_entry->wdev.PhyMode = MODE_CCK; + else + wds_entry->wdev.PhyMode = MODE_OFDM; + } + } + + if (wds_entry->Valid != TRUE) + continue; + + pEntry = MacTableInsertWDSEntry(pAd, wds_entry->PeerWdsAddr, index); + + RTMPSetSupportMCS(pAd, + OPMODE_AP, + pEntry, + pAd->CommonCfg.SupRate, + pAd->CommonCfg.SupRateLen, + pAd->CommonCfg.ExtRate, + pAd->CommonCfg.ExtRateLen, +#ifdef DOT11_VHT_AC + 0, + NULL, +#endif /* DOT11_VHT_AC */ + &pAd->CommonCfg.HtCapability, + sizeof(pAd->CommonCfg.HtCapability)); + + switch (wds_entry->wdev.PhyMode) + { + case 0xff: /* user doesn't specific a Mode for WDS link. */ + case MODE_OFDM: /* specific OFDM mode. */ + pEntry->SupportRateMode = SUPPORT_OFDM_MODE; + if (WMODE_CAP_2G(pAd->CommonCfg.PhyMode)) + pEntry->SupportRateMode |= SUPPORT_CCK_MODE; + break; + + case MODE_CCK: + pEntry->SupportRateMode = SUPPORT_CCK_MODE; + break; + +#ifdef DOT11_N_SUPPORT + case MODE_HTMIX: + case MODE_HTGREENFIELD: + pEntry->SupportRateMode = (SUPPORT_HT_MODE | SUPPORT_OFDM_MODE); + if (WMODE_CAP_2G(pAd->CommonCfg.PhyMode)) + pEntry->SupportRateMode |= SUPPORT_CCK_MODE; + break; +#endif /* DOT11_N_SUPPORT */ + default: + break; + } + } + + return; +} + + +VOID AsicUpdateWdsEncryption(RTMP_ADAPTER *pAd, UCHAR wcid) +{ + UINT WdsIdex; + PMAC_TABLE_ENTRY pEntry = NULL; + RT_802_11_WDS_ENTRY *wds_entry; + struct wifi_dev *wdev; + + do + { + if (wcid >= MAX_LEN_OF_MAC_TABLE) + break; + + pEntry = &pAd->MacTab.Content[wcid]; + if (pAd->WdsTab.WdsEntry[pEntry->func_tb_idx].Valid != TRUE) + break; + + if (!IS_ENTRY_WDS(pEntry)) + break; + + WdsIdex = pEntry->func_tb_idx; + wds_entry = &pAd->WdsTab.WdsEntry[WdsIdex]; + wdev = &wds_entry->wdev; + if (((wdev->WepStatus == Ndis802_11WEPEnabled) || + (wdev->WepStatus == Ndis802_11TKIPEnable) || + (wdev->WepStatus == Ndis802_11AESEnable)) + && (wds_entry->WdsKey.KeyLen > 0)) + { + + INT DefaultKeyId = 0; + + if (wdev->WepStatus == Ndis802_11WEPEnabled) + DefaultKeyId = wds_entry->KeyIdx; + + if (!VAILD_KEY_INDEX(DefaultKeyId)) + break; + + /* Update key into Asic Pairwise key table */ + RTMP_ASIC_PAIRWISE_KEY_TABLE( + pAd, + pEntry->wcid, + &wds_entry->WdsKey); + + /* update WCID attribute table and IVEIV table for this entry */ + RTMP_SET_WCID_SEC_INFO( + pAd, + MAIN_MBSSID + MIN_NET_DEVICE_FOR_WDS, + DefaultKeyId, + wds_entry->WdsKey.CipherAlg, + pEntry->wcid, + PAIRWISEKEY); + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + CmdProcAddRemoveKey(pAd, 0, pEntry->func_tb_idx, DefaultKeyId, pEntry->wcid, PAIRWISEKEYTABLE, &wds_entry->WdsKey, pEntry->Addr); +#endif /* MT_MAC */ + } + } 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; + + if (pEntry && IS_ENTRY_WDS(pEntry)) + { + MaxSupportedRate = dot11_2_ra_rate(MaxSupportedRateIn500Kbps); + pEntry->MaxSupportedRate = min(pAd->CommonCfg.MaxTxRate, MaxSupportedRate); + pEntry->RateLen = MaxSupportedRateLen; + + pEntry->CapabilityInfo = CapabilityInfo; + set_sta_ra_cap(pAd, pEntry, ClientRalinkIe); + + 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]; + } + +#ifdef DOT11_N_SUPPORT + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if ((HtCapabilityLen != 0) + && WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + ht_mode_adjust(pAd, pEntry, pHtCapability, &pAd->CommonCfg.DesiredHtPhy); + + /* find max fixed rate */ + pEntry->MaxHTPhyMode.field.MCS = get_ht_max_mcs(pAd, &pAd->WdsTab.WdsEntry[pEntry->func_tb_idx].wdev.DesiredHtPhyInfo.MCSSet[0], + &pHtCapability->MCSSet[0]); + + if ((pEntry->MaxHTPhyMode.field.MCS > pAd->WdsTab.WdsEntry[pEntry->func_tb_idx].wdev.HTPhyMode.field.MCS) && (pAd->WdsTab.WdsEntry[pEntry->func_tb_idx].wdev.HTPhyMode.field.MCS != MCS_AUTO)) + pEntry->MaxHTPhyMode.field.MCS = pAd->WdsTab.WdsEntry[pEntry->func_tb_idx].wdev.HTPhyMode.field.MCS; + pEntry->MaxHTPhyMode.field.STBC = (pHtCapability->HtCapInfo.RxSTBC & (pAd->CommonCfg.DesiredHtPhy.TxSTBC)); + pEntry->MpduDensity = pHtCapability->HtCapParm.MpduDensity; + pEntry->MaxRAmpduFactor = pHtCapability->HtCapParm.MaxRAmpduFactor; + pEntry->MmpsMode = (UCHAR)pHtCapability->HtCapInfo.MimoPs; + pEntry->AMsduSize = (UCHAR)pHtCapability->HtCapInfo.AMsduSize; + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable && (pAd->CommonCfg.REGBACapability.field.AutoBA == FALSE)) + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_AMSDU_INUSED); + + set_sta_ht_cap(pAd, pEntry, pHtCapability); + + NdisMoveMemory(&pEntry->HTCapability, pHtCapability, sizeof(HT_CAPABILITY_IE)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + pEntry->MaxHTPhyMode.field.BW = BW_20; + pEntry->MinHTPhyMode.field.BW = BW_20; +#ifdef DOT11_N_SUPPORT + pEntry->HTCapability.MCSSet[0] = 0; + pEntry->HTCapability.MCSSet[1] = 0; + NdisZeroMemory(&pEntry->HTCapability, sizeof(HT_CAPABILITY_IE)); + pAd->MacTab.fAnyStationIsLegacy = TRUE; +#endif /* DOT11_N_SUPPORT */ + } + + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE); + + 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(RTMP_ADAPTER *pAd) +{ + INT i; + RT_802_11_WDS_ENTRY *wds_entry; + + pAd->WdsTab.Mode = WDS_DISABLE_MODE; + pAd->WdsTab.Size = 0; + for (i = 0; i < MAX_WDS_ENTRY; i++) + { + wds_entry = &pAd->WdsTab.WdsEntry[i]; + + wds_entry->wdev.PhyMode = 0xff; + wds_entry->wdev.WepStatus = Ndis802_11EncryptionDisabled; + wds_entry->wdev.bAutoTxRateSwitch = TRUE; + wds_entry->wdev.DesiredTransmitSetting.field.MCS = MCS_AUTO; + + wds_entry->Valid = FALSE; + wds_entry->MacTabMatchWCID = 0; + wds_entry->KeyIdx = 0; + NdisZeroMemory(&wds_entry->WdsKey, sizeof(CIPHER_KEY)); + NdisZeroMemory(&wds_entry->WdsCounter, sizeof(WDS_COUNTER)); + + } + return; +} + + +#ifdef DBG +INT Show_WdsTable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT i; + + for(i = 0; i < MAX_WDS_ENTRY; i++) + { + DBGPRINT(RT_DEBUG_OFF, ("IF/WDS%d-%02x:%02x:%02x:%02x:%02x:%02x(%s) ,%s, KeyId=%d\n", i, + PRINT_MAC(pAd->WdsTab.WdsEntry[i].PeerWdsAddr), + pAd->WdsTab.WdsEntry[i].Valid == 1 ? "Valid" : "Invalid", + GetEncryptType(pAd->WdsTab.WdsEntry[i].wdev.WepStatus), + pAd->WdsTab.WdsEntry[i].KeyIdx)); + + if (pAd->WdsTab.WdsEntry[i].WdsKey.KeyLen > 0) + hex_dump("Wds Key", pAd->WdsTab.WdsEntry[i].WdsKey.Key, pAd->WdsTab.WdsEntry[i].WdsKey.KeyLen); + } + + 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->func_tb_idx)); + DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->Aid)); + DBGPRINT(RT_DEBUG_OFF, ("%-4d", (int)pEntry->PsMode)); + DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi[0])); + DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi[1])); + DBGPRINT(RT_DEBUG_OFF, ("%-7d", pEntry->RssiSample.AvgRssi[2])); + DBGPRINT(RT_DEBUG_OFF, ("%-10s", get_phymode_str(pEntry->HTPhyMode.field.MODE))); + DBGPRINT(RT_DEBUG_OFF, ("%-6s", get_bw_str(pEntry->HTPhyMode.field.BW))); + DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.MCS)); + DBGPRINT(RT_DEBUG_OFF, ("%-6d", pEntry->HTPhyMode.field.ShortGI)); + DBGPRINT(RT_DEBUG_OFF, ("%-6d\n", pEntry->HTPhyMode.field.STBC)); + } + } + + return TRUE; +} +#endif /* DBG */ + +VOID rtmp_read_wds_from_file(RTMP_ADAPTER *pAd, RTMP_STRING *tmpbuf, RTMP_STRING *buffer) +{ + RTMP_STRING *macptr; + INT i=0, j; + RTMP_STRING tok_str[16]; + BOOLEAN bUsePrevFormat = FALSE; + UCHAR macAddress[MAC_ADDR_LEN]; + UCHAR keyMaterial[40]; + UCHAR KeyLen, CipherAlg = CIPHER_NONE, KeyIdx; + PRT_802_11_WDS_ENTRY pWdsEntry; + struct wifi_dev *wdev; + + + /*WdsPhyMode */ + if (RTMPGetKeyParameter("WdsPhyMode", tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, TRUE)) + { + for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_WDS_ENTRY); macptr = rstrtok(NULL,";"), i++) + { + pWdsEntry = &pAd->WdsTab.WdsEntry[i]; + wdev = &pWdsEntry->wdev; + if (rtstrcasecmp(macptr, "CCK") == TRUE) + wdev->PhyMode = MODE_CCK; + else if (rtstrcasecmp(macptr, "OFDM") == TRUE) + wdev->PhyMode = MODE_OFDM; +#ifdef DOT11_N_SUPPORT + else if (rtstrcasecmp(macptr, "HTMIX") == TRUE) + wdev->PhyMode = MODE_HTMIX; + else if (rtstrcasecmp(macptr, "GREENFIELD") == TRUE) + wdev->PhyMode = MODE_HTGREENFIELD; +#endif /* DOT11_N_SUPPORT */ + else + wdev->PhyMode = 0xff; + + DBGPRINT(RT_DEBUG_TRACE, ("If/wds%d - PeerPhyMode=%d\n", i, wdev->PhyMode)); + } + } + + /*WdsList */ + if (RTMPGetKeyParameter("WdsList", tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, TRUE)) + { + if (pAd->WdsTab.Mode != WDS_LAZY_MODE) + { + for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_WDS_ENTRY); macptr = rstrtok(NULL,";"), i++) + { + if(strlen(macptr) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + continue; + if(strcmp(macptr,"00:00:00:00:00:00") == 0) + continue; + if(i >= MAX_WDS_ENTRY) + break; + + for (j=0; jWdsTab.WdsEntry[i]; + wdev = &pWdsEntry->wdev; + + if (rtstrcasecmp(macptr, "NONE") == TRUE) + wdev->WepStatus = Ndis802_11WEPDisabled; + else if (rtstrcasecmp(macptr, "WEP") == TRUE) + wdev->WepStatus = Ndis802_11WEPEnabled; + else if (rtstrcasecmp(macptr, "TKIP") ==TRUE) + wdev->WepStatus = Ndis802_11TKIPEnable; + else if (rtstrcasecmp(macptr, "AES") == TRUE) + wdev->WepStatus = Ndis802_11AESEnable; + else + wdev->WepStatus = Ndis802_11WEPDisabled; + + DBGPRINT(RT_DEBUG_TRACE, ("WdsEncrypType[%d]=%d(%s)\n", + i, wdev->WepStatus, GetEncryptType(wdev->WepStatus))); + } + + /* Previous WDS only supports single encryption type. */ + /* For backward compatible, other wds link encryption type shall be the same with the first. */ + if (i == 1) + { + for (j = 1; j < MAX_WDS_ENTRY; j++) + { + wdev = &pAd->WdsTab.WdsEntry[j].wdev; + wdev->WepStatus = pAd->WdsTab.WdsEntry[0].wdev.WepStatus; + DBGPRINT(RT_DEBUG_TRACE, ("WdsEncrypType[%d]=%d(%s)\n", + j, wdev->WepStatus, GetEncryptType(wdev->WepStatus))); + } + } + + } + /* WdsKey */ + /* This is a previous parameter and it only stores WPA key material, not WEP key */ + if (RTMPGetKeyParameter("WdsKey", tmpbuf, 255, buffer, FALSE)) + { + for (i = 0; i < MAX_WDS_ENTRY; i++) + NdisZeroMemory(&pAd->WdsTab.WdsEntry[i].WdsKey, sizeof(CIPHER_KEY)); + + if (strlen(tmpbuf) > 0) + bUsePrevFormat = TRUE; + + wdev = &pAd->WdsTab.WdsEntry[0].wdev; + pWdsEntry = &pAd->WdsTab.WdsEntry[0]; + /* check if the wds-0 link key material is valid */ + if (((wdev->WepStatus == Ndis802_11TKIPEnable) + || (wdev->WepStatus == Ndis802_11AESEnable)) + && (strlen(tmpbuf) >= 8) && (strlen(tmpbuf) <= 64)) + { + RT_CfgSetWPAPSKKey(pAd, tmpbuf, strlen(tmpbuf), (PUCHAR)RALINK_PASSPHRASE, sizeof(RALINK_PASSPHRASE), keyMaterial); + if (wdev->WepStatus == Ndis802_11AESEnable) + pWdsEntry->WdsKey.CipherAlg = CIPHER_AES; + else + pWdsEntry->WdsKey.CipherAlg = CIPHER_TKIP; + + NdisMoveMemory(&pWdsEntry->WdsKey.Key, keyMaterial, 16); + pWdsEntry->WdsKey.KeyLen = 16; + NdisMoveMemory(&pWdsEntry->WdsKey.RxMic, keyMaterial+16, 8); + NdisMoveMemory(&pWdsEntry->WdsKey.TxMic, keyMaterial+16, 8); + } + + /* Previous WDS only supports single key-material. */ + /* For backward compatible, other wds link key-material shall be the same with the first. */ + if (pAd->WdsTab.WdsEntry[0].WdsKey.KeyLen == 16) + { + for (j = 1; j < MAX_WDS_ENTRY; j++) + { + NdisMoveMemory(&pAd->WdsTab.WdsEntry[j].WdsKey, &pAd->WdsTab.WdsEntry[0].WdsKey, sizeof(CIPHER_KEY)); + } + } + + } + + /* The parameters can provide different key information for each WDS-Link */ + /* no matter WEP or WPA */ + if (!bUsePrevFormat) + { + for (i = 0; i < MAX_WDS_ENTRY; i++) + { + AP_WDS_KeyNameMakeUp(tok_str, sizeof(tok_str), i); + pWdsEntry = &pAd->WdsTab.WdsEntry[i]; + wdev = &pWdsEntry->wdev; + /* WdsXKey (X=0~MAX_WDS_ENTRY-1) */ + if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, FALSE)) + { + if (wdev->WepStatus == Ndis802_11WEPEnabled) + { + /* Ascii type */ + if (strlen(tmpbuf) == 5 || strlen(tmpbuf) == 13) + { + KeyLen = strlen(tmpbuf); + pWdsEntry->WdsKey.KeyLen = KeyLen; + NdisMoveMemory(pWdsEntry->WdsKey.Key, tmpbuf, KeyLen); + if (KeyLen == 5) + CipherAlg = CIPHER_WEP64; + else + CipherAlg = CIPHER_WEP128; + + pWdsEntry->WdsKey.CipherAlg = CipherAlg; + DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d Key=%s ,type=Ascii, CipherAlg(%s)\n", + i, tmpbuf, (CipherAlg == CIPHER_WEP64 ? "wep64" : "wep128"))); + } + /* Hex type */ + else if (strlen(tmpbuf) == 10 || strlen(tmpbuf) == 26) + { + KeyLen = strlen(tmpbuf); + pWdsEntry->WdsKey.KeyLen = KeyLen / 2; + AtoH(tmpbuf, pWdsEntry->WdsKey.Key, KeyLen / 2); + if (KeyLen == 10) + CipherAlg = CIPHER_WEP64; + else + CipherAlg = CIPHER_WEP128; + + pWdsEntry->WdsKey.CipherAlg = CipherAlg; + DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d Key=%s ,type=Hex, CipherAlg(%s)\n", + i, tmpbuf, (CipherAlg == CIPHER_WEP64 ? "wep64" : "wep128"))); + } + /* Invalid type */ + else + { + wdev->WepStatus = Ndis802_11EncryptionDisabled; + NdisZeroMemory(&pWdsEntry->WdsKey, sizeof(CIPHER_KEY)); + DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d has invalid key for WEP, reset encryption to OPEN\n", i)); + } + } + else if ((wdev->WepStatus == Ndis802_11TKIPEnable) + || (wdev->WepStatus == Ndis802_11AESEnable)) + { + if ((strlen(tmpbuf) >= 8) && (strlen(tmpbuf) <= 64)) + { + RT_CfgSetWPAPSKKey(pAd, tmpbuf, strlen(tmpbuf), (PUCHAR) RALINK_PASSPHRASE, sizeof(RALINK_PASSPHRASE), keyMaterial); + if (wdev->WepStatus == Ndis802_11AESEnable) + pWdsEntry->WdsKey.CipherAlg = CIPHER_AES; + else + pWdsEntry->WdsKey.CipherAlg = CIPHER_TKIP; + + NdisMoveMemory(&pWdsEntry->WdsKey.Key, keyMaterial, 16); + pWdsEntry->WdsKey.KeyLen = 16; + NdisMoveMemory(&pWdsEntry->WdsKey.RxMic, keyMaterial+16, 8); + NdisMoveMemory(&pWdsEntry->WdsKey.TxMic, keyMaterial+16, 8); + DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d Key=%s, CipherAlg(%s)\n", i, tmpbuf, (CipherAlg == CIPHER_AES ? "AES" : "TKIP"))); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d has invalid key for WPA, reset encryption to OPEN\n", i)); + wdev->WepStatus = Ndis802_11EncryptionDisabled; + NdisZeroMemory(&pWdsEntry->WdsKey, sizeof(CIPHER_KEY)); + } + + } + else + { + wdev->WepStatus = Ndis802_11EncryptionDisabled; + NdisZeroMemory(&pWdsEntry->WdsKey, sizeof(CIPHER_KEY)); + } + } + } + } + + /* WdsDefaultKeyID */ + if(RTMPGetKeyParameter("WdsDefaultKeyID", tmpbuf, 10, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_WDS_ENTRY); macptr = rstrtok(NULL,";"), i++) + { + pWdsEntry = &pAd->WdsTab.WdsEntry[i]; + wdev = &pWdsEntry->wdev; + + KeyIdx = (UCHAR) simple_strtol(macptr, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pWdsEntry->KeyIdx = (UCHAR) (KeyIdx - 1); + else + pWdsEntry->KeyIdx = 0; + + if ((wdev->WepStatus == Ndis802_11TKIPEnable) + || (wdev->WepStatus == Ndis802_11AESEnable)) + pWdsEntry->KeyIdx = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("IF/wds%d - WdsDefaultKeyID(0~3)=%d\n", + i, pWdsEntry->KeyIdx)); + } + } + + /* WdsTxMode */ + if (RTMPGetKeyParameter("WdsTxMode", tmpbuf, 25, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_WDS_ENTRY); macptr = rstrtok(NULL,";"), i++) + { + wdev = &pAd->WdsTab.WdsEntry[i].wdev; + + wdev->DesiredTransmitSetting.field.FixedTxMode = + RT_CfgSetFixedTxPhyMode(macptr); + DBGPRINT(RT_DEBUG_TRACE, ("I/F(wds%d) Tx Mode = %d\n", i, + wdev->DesiredTransmitSetting.field.FixedTxMode)); + } + } + + /* WdsTxMcs */ + if (RTMPGetKeyParameter("WdsTxMcs", tmpbuf, 50, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_WDS_ENTRY); macptr = rstrtok(NULL,";"), i++) + { + wdev = &pAd->WdsTab.WdsEntry[i].wdev; + + wdev->DesiredTransmitSetting.field.MCS = + RT_CfgSetTxMCSProc(macptr, &wdev->bAutoTxRateSwitch); + + if (wdev->DesiredTransmitSetting.field.MCS == MCS_AUTO) + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(wds%d) Tx MCS = AUTO\n", i)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("I/F(wds%d) Tx MCS = %d\n", i, + wdev->DesiredTransmitSetting.field.MCS)); + } + } + } + + /*WdsEnable */ + if(RTMPGetKeyParameter("WdsEnable", tmpbuf, 10, buffer, TRUE)) + { + RT_802_11_WDS_ENTRY *pWdsEntry; + switch(simple_strtol(tmpbuf, 0, 10)) + { + case WDS_BRIDGE_MODE: /* Bridge mode, DisAllow association(stop Beacon generation and Probe Req. */ + pAd->WdsTab.Mode = WDS_BRIDGE_MODE; + break; + case WDS_RESTRICT_MODE: + case WDS_REPEATER_MODE: /* Repeater mode */ + pAd->WdsTab.Mode = WDS_REPEATER_MODE; + break; + case WDS_LAZY_MODE: /* Lazy mode, Auto learn wds entry by same SSID, channel, security policy */ + for(i = 0; i < MAX_WDS_ENTRY; i++) + { + pWdsEntry = &pAd->WdsTab.WdsEntry[i]; + if (pWdsEntry->Valid) + WdsEntryDel(pAd, pWdsEntry->PeerWdsAddr); + + /* When Lazy mode is enabled, the all wds-link shall share the same encryption type and key material */ + if (i > 0) + { + pWdsEntry->wdev.WepStatus = pAd->WdsTab.WdsEntry[0].wdev.WepStatus; + pWdsEntry->KeyIdx = pAd->WdsTab.WdsEntry[0].KeyIdx; + NdisMoveMemory(&pWdsEntry->WdsKey, &pAd->WdsTab.WdsEntry[0].WdsKey, sizeof(CIPHER_KEY)); + } + } + pAd->WdsTab.Mode = WDS_LAZY_MODE; + break; + case WDS_DISABLE_MODE: /* Disable mode */ + default: + APWdsInitialize(pAd); + pAd->WdsTab.Mode = WDS_DISABLE_MODE; + break; + } + + DBGPRINT(RT_DEBUG_TRACE, ("WDS-Enable mode=%d\n", pAd->WdsTab.Mode)); + + } + +#ifdef WDS_VLAN_SUPPORT + /* WdsVlan */ + if (RTMPGetKeyParameter("WDS_VLANID", tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, TRUE)) + { + for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_WDS_ENTRY); macptr = rstrtok(NULL,";"), i++) + { + pAd->WdsTab.WdsEntry[i].wdev.VLAN_VID = simple_strtol(macptr, 0, 10); + pAd->WdsTab.WdsEntry[i].wdev.VLAN_Priority = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("If/wds%d - WdsVlanId=%d\n", i, pAd->WdsTab.WdsEntry[i].wdev.VLAN_VID)); + } + } +#endif /* WDS_VLAN_SUPPORT */ +} + + +VOID WdsPrepareWepKeyFromMainBss(RTMP_ADAPTER *pAd) +{ + INT i; + + /* Prepare WEP key for each wds-link if necessary */ + for (i = 0; i < MAX_WDS_ENTRY; i++) + { + /* For WDS backward compatible, refer to the WEP key of Main BSS in WEP mode */ + if (pAd->WdsTab.WdsEntry[i].wdev.WepStatus == Ndis802_11WEPEnabled && + pAd->WdsTab.WdsEntry[i].WdsKey.KeyLen == 0) + { + UCHAR main_bss_keyid = pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.DefaultKeyId; + + if (pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.WepStatus == Ndis802_11WEPEnabled && + (pAd->SharedKey[MAIN_MBSSID][main_bss_keyid].KeyLen == 5 || + pAd->SharedKey[MAIN_MBSSID][main_bss_keyid].KeyLen == 13)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Duplicate IF/WDS%d wep key from main_bssid \n", (UCHAR)i)); + pAd->WdsTab.WdsEntry[i].KeyIdx = main_bss_keyid; + NdisMoveMemory(&pAd->WdsTab.WdsEntry[i].WdsKey, &pAd->SharedKey[MAIN_MBSSID][main_bss_keyid], sizeof(CIPHER_KEY)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("No available wep key for IF/WDS%d, reset its encryption as OPEN \n", (UCHAR)i)); + pAd->WdsTab.WdsEntry[i].wdev.WepStatus = Ndis802_11EncryptionDisabled; + NdisZeroMemory(&pAd->WdsTab.WdsEntry[i].WdsKey, sizeof(CIPHER_KEY)); + } + } + } + +} + + +VOID WDS_Init(RTMP_ADAPTER *pAd, RTMP_OS_NETDEV_OP_HOOK *pNetDevOps) +{ + INT index; + PNET_DEV pWdsNetDev; + + /* sanity check to avoid redundant virtual interfaces are created */ + if (pAd->flg_wds_init != FALSE) + return; + + for(index = 0; index < MAX_WDS_ENTRY; index++) + { + UINT32 MC_RowID = 0, IoctlIF = 0; + RT_802_11_WDS_ENTRY *wds_entry; + struct wifi_dev *wdev; + char *dev_name; + +#ifdef MULTIPLE_CARD_SUPPORT + MC_RowID = pAd->MC_RowID; +#endif /* MULTIPLE_CARD_SUPPORT */ +#ifdef HOSTAPD_SUPPORT + IoctlIF = pAd->IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + + dev_name = get_dev_name_prefix(pAd, INT_WDS); + pWdsNetDev = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, INT_WDS, index, sizeof(struct mt_dev_priv), dev_name); +#ifdef HOSTAPD_SUPPORT + pAd->IoctlIF = IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + + wds_entry = &pAd->WdsTab.WdsEntry[index]; + wdev = &wds_entry->wdev; + + if (pWdsNetDev == NULL) + { + /* allocation fail, exit */ + DBGPRINT(RT_DEBUG_ERROR, ("Allocate network device fail (WDS)...\n")); + break; + } + + DBGPRINT(RT_DEBUG_TRACE, ("The new WDS interface MAC = %02X:%02X:%02X:%02X:%02X:%02X\n", + PRINT_MAC(pAd->MacTab.Content[wds_entry->MacTabMatchWCID].Addr))); + + NdisZeroMemory(&wds_entry->WdsCounter, sizeof(WDS_COUNTER)); + + wdev->wdev_type = WDEV_TYPE_WDS; + wdev->func_dev = wds_entry; + wdev->func_idx = index; + wdev->sys_handle = (void *)pAd; + wdev->if_dev = pWdsNetDev; + wdev->tx_pkt_allowed = ApWdsAllowToSendPacket; + // TODO: shiang-usw, modify this to WDSSendPacket + wdev->tx_pkt_handle = APSendPacket; + wdev->wdev_hard_tx = APHardTransmit; + wdev->rx_pkt_allowed = ap_rx_pkt_allow; + wdev->rx_pkt_foward = wds_rx_foward_handle; + + wdev->PhyMode = 0xff; + wdev->allow_data_tx = TRUE; // let tx_pkt_allowed() to check it! + wdev->PortSecured = WPA_802_1X_PORT_SECURED; + NdisMoveMemory(&wdev->if_addr[0], &pNetDevOps->devAddr[0], MAC_ADDR_LEN); + + RTMP_OS_NETDEV_SET_PRIV(pWdsNetDev, pAd); + RTMP_OS_NETDEV_SET_WDEV(pWdsNetDev, wdev); + + if (rtmp_wdev_idx_reg(pAd, wdev) < 0) { + DBGPRINT(RT_DEBUG_ERROR, ("Assign wdev idx for %s failed, free net device!\n", + RTMP_OS_NETDEV_GET_DEVNAME(pWdsNetDev))); + RtmpOSNetDevFree(pWdsNetDev); + break; + } + + pNetDevOps->priv_flags = INT_WDS; + pNetDevOps->needProtcted = TRUE; + pNetDevOps->wdev = wdev; + /* Register this device */ + RtmpOSNetDevAttach(pAd->OpMode, pWdsNetDev, pNetDevOps); + } + + if (index > 0) + pAd->flg_wds_init = TRUE; + + + NdisAllocateSpinLock(pAd, &pAd->WdsTabLock); + + DBGPRINT(RT_DEBUG_TRACE, ("Total allocated %d WDS interfaces!\n", index)); + +} + + +VOID WDS_Remove(RTMP_ADAPTER *pAd) +{ + UINT index; + struct wifi_dev *wdev; + + for(index = 0; index < MAX_WDS_ENTRY; index++) + { + wdev = &pAd->WdsTab.WdsEntry[index].wdev; + if (wdev->if_dev) + { + RtmpOSNetDevProtect(1); + RtmpOSNetDevDetach(wdev->if_dev); + RtmpOSNetDevProtect(0); + + rtmp_wdev_idx_unreg(pAd, wdev); + RtmpOSNetDevFree(wdev->if_dev); + + /* Clear it as NULL to prevent latter access error. */ + wdev->if_dev = NULL; + } + } +} + + +BOOLEAN WDS_StatsGet(RTMP_ADAPTER *pAd, RT_CMD_STATS *pStats) +{ + INT WDS_apidx = 0,index; + RT_802_11_WDS_ENTRY *wds_entry; + + + for(index = 0; index < MAX_WDS_ENTRY; index++) + { + if (pAd->WdsTab.WdsEntry[index].wdev.if_dev == pStats->pNetDev) + { + WDS_apidx = index; + break; + } + } + + if(index >= MAX_WDS_ENTRY) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): can not find wds I/F\n", __FUNCTION__)); + return FALSE; + } + + wds_entry = &pAd->WdsTab.WdsEntry[WDS_apidx]; + pStats->pStats = pAd->stats; + + pStats->rx_packets = wds_entry->WdsCounter.ReceivedFragmentCount.QuadPart; + pStats->tx_packets = wds_entry->WdsCounter.TransmittedFragmentCount.QuadPart; + + pStats->rx_bytes = wds_entry->WdsCounter.ReceivedByteCount; + pStats->tx_bytes = wds_entry->WdsCounter.TransmittedByteCount; + + pStats->rx_errors = wds_entry->WdsCounter.RxErrorCount; + pStats->tx_errors = wds_entry->WdsCounter.TxErrors; + + pStats->multicast = wds_entry->WdsCounter.MulticastReceivedFrameCount.QuadPart; /* multicast packets received */ + pStats->collisions = 0; /* Collision packets */ + + pStats->rx_over_errors = wds_entry->WdsCounter.RxNoBuffer; /* receiver ring buff overflow */ + pStats->rx_crc_errors = 0;/*pAd->WlanCounters.FCSErrorCount; // recved pkt with crc error */ + pStats->rx_frame_errors = 0; /* recv'd frame alignment error */ + pStats->rx_fifo_errors = wds_entry->WdsCounter.RxNoBuffer; /* recv'r fifo overrun */ + + return TRUE; +} + +#endif /* WDS_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_wds_inf.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_wds_inf.c new file mode 100644 index 000000000..78a2f2b73 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_wds_inf.c @@ -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: + 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(PNET_DEV net_dev); + + +/* Register WDS interface */ +VOID RT28xx_WDS_Init(VOID *pAd, PNET_DEV net_dev) +{ + RTMP_OS_NETDEV_OP_HOOK netDevOpHook; + + NdisZeroMemory((PUCHAR)&netDevOpHook, sizeof(RTMP_OS_NETDEV_OP_HOOK)); + netDevOpHook.open = WdsVirtualIF_open; + netDevOpHook.stop = WdsVirtualIF_close; + netDevOpHook.xmit = rt28xx_send_packets; + netDevOpHook.ioctl = rt28xx_ioctl; + netDevOpHook.get_stats = RT28xx_get_wds_ether_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 WdsVirtualIF_open(PNET_DEV dev) +{ + VOID *pAd; + + /* increase MODULE use count */ + RT_MOD_INC_USE_COUNT(); + + 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; + +#ifdef CONFIG_RA_HW_NAT_WIFI_NEW_ARCH + RT_MOD_HNAT_REG(dev); +#endif + RTMP_OS_NETDEV_START_QUEUE(dev); + return 0; +} + + +INT WdsVirtualIF_close(PNET_DEV dev) +{ + VOID *pAd; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: ===> VirtualIF_close\n", RTMP_OS_NETDEV_GET_DEVNAME(dev))); + + + pAd = RTMP_OS_NETDEV_GET_PRIV(dev); + + //RTMP_OS_NETDEV_CARRIER_OFF(dev); + RTMP_OS_NETDEV_STOP_QUEUE(dev); + +#ifdef CONFIG_RA_HW_NAT_WIFI_NEW_ARCH + RT_MOD_HNAT_DEREG(dev); +#endif + VIRTUAL_IF_DOWN(pAd); + + RT_MOD_DEC_USE_COUNT(); + + return 0; +} + + +VOID RT28xx_WDS_Remove(VOID *pAd) +{ + RTMP_AP_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_WDS_REMOVE, 0, NULL, 0); +} + +#endif /* WDS_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_wpa.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_wpa.c new file mode 100644 index 000000000..90289ec9c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/ap_wpa.c @@ -0,0 +1,1545 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + wpa.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan Lee 03-07-22 Initial + Rory Chen 04-11-29 Add WPA2PSK +*/ +#include "rt_config.h" + +extern UCHAR EAPOL[]; + +/* + ========================================================================== + Description: + Port Access Control Inquiry function. Return entry's Privacy and Wpastate. + Return: + pEntry + ========================================================================== +*/ +MAC_TABLE_ENTRY *PACInquiry(RTMP_ADAPTER *pAd, UCHAR Wcid) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + + if (Wcid < MAX_LEN_OF_MAC_TABLE) + pEntry = &(pAd->MacTab.Content[Wcid]); + + return pEntry; +} + +/* + ========================================================================== + Description: + Check sanity of multicast cipher selector in RSN IE. + Return: + TRUE if match + FALSE otherwise + ========================================================================== +*/ +BOOLEAN RTMPCheckMcast( + IN PRTMP_ADAPTER pAd, + IN PEID_STRUCT eid_ptr, + IN MAC_TABLE_ENTRY *pEntry) +{ + UCHAR apidx; + struct wifi_dev *wdev; + + + ASSERT(pEntry); + ASSERT(pEntry->func_tb_idx < pAd->ApCfg.BssidNum); + + apidx = pEntry->func_tb_idx; + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + pEntry->AuthMode = wdev->AuthMode; + + if (eid_ptr->Len >= 6) + { + /* WPA and WPA2 format not the same in RSN_IE */ + if (eid_ptr->Eid == IE_WPA) + { + if (wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) + pEntry->AuthMode = Ndis802_11AuthModeWPA; + else if (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + pEntry->AuthMode = Ndis802_11AuthModeWPAPSK; + + if (NdisEqualMemory(&eid_ptr->Octet[6], &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][6], 4)) + return TRUE; + } + else if (eid_ptr->Eid == IE_WPA2) + { + UCHAR IE_Idx = 0; + + /* When WPA1/WPA2 mix mode, the RSN_IE is stored in different structure */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + IE_Idx = 1; + + if (wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) + pEntry->AuthMode = Ndis802_11AuthModeWPA2; + else if (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + pEntry->AuthMode = Ndis802_11AuthModeWPA2PSK; + + if (NdisEqualMemory(&eid_ptr->Octet[2], &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][2], 4)) + return TRUE; + } + } + + return FALSE; +} + +/* + ========================================================================== + Description: + Check sanity of unicast cipher selector in RSN IE. + Return: + TRUE if match + FALSE otherwise + ========================================================================== +*/ +BOOLEAN RTMPCheckUcast( + IN PRTMP_ADAPTER pAd, + IN PEID_STRUCT eid_ptr, + IN MAC_TABLE_ENTRY *pEntry) +{ + PUCHAR pStaTmp; + USHORT Count; + UCHAR apidx; + struct wifi_dev *wdev; + + ASSERT(pEntry); + ASSERT(pEntry->func_tb_idx < pAd->ApCfg.BssidNum); + + apidx = pEntry->func_tb_idx; + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + + pEntry->WepStatus = wdev->WepStatus; + +#ifndef CONFIG_SECURITY_IMPROVEMENT_SUPPORT + if (eid_ptr->Len < 16) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]RTMPCheckUcast : the length is too short(%d) \n", eid_ptr->Len)); + return FALSE; + } +#endif + /* 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); +#ifdef CONFIG_SECURITY_IMPROVEMENT_SUPPORT + if (eid_ptr->Len >= 12) +#else + if (eid_ptr->Len >= 16) +#endif + { + if (eid_ptr->Eid == IE_WPA) + { + if (wdev->WepStatus == Ndis802_11TKIPAESMix) + {/* multiple cipher (TKIP/CCMP) */ + + while (Count > 0) + { + /* TKIP */ + if (MIX_CIPHER_WPA_TKIP_ON(wdev->WpaMixPairCipher)) + { + /* Compare if peer STA uses the TKIP as its unicast cipher */ + if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4)) + { + pEntry->WepStatus = Ndis802_11TKIPEnable; + return TRUE; + } + + /* Our AP uses the AES as the secondary cipher */ + /* Compare if the peer STA use AES as its unicast cipher */ + if (MIX_CIPHER_WPA_AES_ON(wdev->WpaMixPairCipher)) + { + if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][16], 4)) + { + pEntry->WepStatus = Ndis802_11AESEnable; + return TRUE; + } + } + } + else + { + /* AES */ + if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4)) + { + pEntry->WepStatus = Ndis802_11AESEnable; + return TRUE; + } + } + + pStaTmp += 4; + Count--; + } + } + else + {/* single cipher */ + while (Count > 0) + { + if (RTMPEqualMemory(pStaTmp , &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][12], 4)) + return TRUE; + + pStaTmp += 4; + Count--; + } + } + } + else if (eid_ptr->Eid == IE_WPA2) + { + UCHAR IE_Idx = 0; + + /* When WPA1/WPA2 mix mode, the RSN_IE is stored in different structure */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + IE_Idx = 1; + + if (wdev->WepStatus == Ndis802_11TKIPAESMix) + {/* multiple cipher (TKIP/CCMP) */ + + while (Count > 0) + { + /* WPA2 TKIP */ + if (MIX_CIPHER_WPA2_TKIP_ON(wdev->WpaMixPairCipher)) + { + /* Compare if peer STA uses the TKIP as its unicast cipher */ + if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4)) + { + pEntry->WepStatus = Ndis802_11TKIPEnable; + return TRUE; + } + + /* Our AP uses the AES as the secondary cipher */ + /* Compare if the peer STA use AES as its unicast cipher */ + if (MIX_CIPHER_WPA2_AES_ON(wdev->WpaMixPairCipher)) + { + if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][12], 4)) + { + pEntry->WepStatus = Ndis802_11AESEnable; + return TRUE; + } + } + } + else + { + /* AES */ + if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4)) + { + pEntry->WepStatus = Ndis802_11AESEnable; + return TRUE; + } + } + + pStaTmp += 4; + Count--; + } + } + else + {/* single cipher */ + while (Count > 0) + { + if (RTMPEqualMemory(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][8], 4)) + return TRUE; + + pStaTmp += 4; + Count--; + } + } + } + } + + return FALSE; +} + + +/* + ========================================================================== + Description: + Check invalidity of authentication method selection in RSN IE. + Return: + TRUE if match + FALSE otherwise + ========================================================================== +*/ +BOOLEAN RTMPCheckAKM(PUCHAR sta_akm, PUCHAR ap_rsn_ie, INT iswpa2 +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + , NDIS_802_11_AUTHENTICATION_MODE APAuthMode, MAC_TABLE_ENTRY * pEntry +#endif + ) +{ + 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 */ + +#ifdef DOT11_SAE_SUPPORT + if (APAuthMode == Ndis802_11AuthModeWPA3PSK || APAuthMode == Ndis802_11AuthModeWPA2PSKWPA3PSK) { + + if (!iswpa2) + return FALSE; + + if (NdisEqualMemory(sta_akm, &OUI_WPA2_AKM_SAE_SHA256, 4)) { + pEntry->AuthMode = Ndis802_11AuthModeWPA3PSK; + pEntry->key_deri_alg = SEC_KEY_DERI_SHA256; + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_USE_SHA256); + return TRUE; + } else if (NdisEqualMemory(sta_akm, &OUI_WPA2_PSK_SHA256, 4)) { + pEntry->AuthMode = Ndis802_11AuthModeWPA2PSK; + pEntry->key_deri_alg = SEC_KEY_DERI_SHA256; + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_USE_SHA256); + return TRUE; + } else if (NdisEqualMemory(sta_akm, &OUI_WPA2_PSK_AKM, 4)) { + pEntry->AuthMode = Ndis802_11AuthModeWPA2PSK; + pEntry->key_deri_alg = SEC_KEY_DERI_SHA1; + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_USE_SHA256); + return TRUE; + } + + } else +#endif +#ifdef CONFIG_OWE_SUPPORT + if (APAuthMode == Ndis802_11AuthModeOWE) { + if (!iswpa2) + return FALSE; + + if (NdisEqualMemory(sta_akm, &OUI_WPA2_AKM_OWE, 4)) { + pEntry->AuthMode = Ndis802_11AuthModeOWE; + pEntry->key_deri_alg = SEC_KEY_DERI_SHA256; + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_USE_SHA256); + return TRUE; + } + } else +#endif + { + while (Count > 0) { + /*rtmp_hexdump(RT_DEBUG_TRACE,"MBSS WPA_IE AKM ",pTmp,4); */ + if (RTMPEqualMemory(sta_akm, pTmp, 4)) + return TRUE; + + 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->func_tb_idx < pAd->ApCfg.BssidNum); + + apidx = pEntry->func_tb_idx; + +#ifndef CONFIG_SECURITY_IMPROVEMENT_SUPPORT + if (eid_ptr->Len < 16) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPCheckAUTH ==> WPAIE len is too short(%d) \n", eid_ptr->Len)); + return FALSE; + } +#endif + /* 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 +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + , pAd->ApCfg.MBSSID[apidx].wdev.AuthMode, pEntry +#endif + )) + return TRUE; + + pStaTmp += 4; + Count--; + } + } + else if (eid_ptr->Eid == IE_WPA2) + { + UCHAR IE_Idx = 0; + + /* When WPA1/WPA2 mix mode, the RSN_IE is stored in different structure */ + if ((pAd->ApCfg.MBSSID[apidx].wdev.AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + IE_Idx = 1; + + while (Count > 0) { + if (RTMPCheckAKM(pStaTmp, &pAd->ApCfg.MBSSID[apidx].RSN_IE[IE_Idx][0], 1 +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + , pAd->ApCfg.MBSSID[apidx].wdev.AuthMode, pEntry +#endif + )) { +#ifdef CONFIG_OWE_SUPPORT + if (pEntry->AuthMode == Ndis802_11AuthModeOWE) { + pEntry->key_deri_alg = SEC_KEY_DERI_SHA256; + /* OWE cannot derive key_deri_alg by OWE akm. + * it shall parse ECDH parameter to determine it. + * set a temporary alg here. + */ + } +#endif + return TRUE; + } + + pStaTmp += 4; + Count--; + } + } + } + + return FALSE; +} + +#if defined(CONFIG_SECURITY_IMPROVEMENT_SUPPORT) || defined(APCLI_SECURITY_IMPROVEMENT_SUPPORT) + +static BOOLEAN wpa_check_pmkid( + IN PUINT8 rsnie_ptr, + IN UINT rsnie_len, + IN NDIS_802_11_AUTHENTICATION_MODE StaAuthMode) +{ + UINT8 count = 0; + PUINT8 pBuf = NULL; + + if (StaAuthMode == Ndis802_11AuthModeWPA2PSK) { + pBuf = WPA_ExtractSuiteFromRSNIE(rsnie_ptr, rsnie_len, PMKID_LIST, &count); + + if (count > 0) + return FALSE; + } + + return TRUE; +} + + +/* Ellis: not ready for WAPI */ +BOOLEAN wpa_rsne_sanity( + IN PUCHAR rsnie_ptr, + IN UCHAR rsnie_len, + OUT UCHAR *end_field) +{ + EID_STRUCT *eid_ptr; + PUCHAR pStaTmp; + USHORT ver; + USHORT Count; + UCHAR len = 0; + + eid_ptr = (EID_STRUCT *)rsnie_ptr; + + if ((eid_ptr->Len + 2) != rsnie_len) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[ERROR]%s : the len is invalid !!!\n", __func__)); + return FALSE; + } + + if (eid_ptr->Len < MIN_LEN_OF_RSNIE) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[ERROR]%s : len is too short(len = %d) !!!\n", __func__, eid_ptr->Len)); + return FALSE; + } + + /* Store STA RSN_IE capability */ + pStaTmp = (PUCHAR)&eid_ptr->Octet[0]; + + /* check Element ID */ + if (eid_ptr->Eid == IE_WPA2) + ; + else if (eid_ptr->Eid == IE_WPA) { + /* skip OUI(4) */ + pStaTmp += 4; + len += 4; + } else if (eid_ptr->Eid == IE_WAPI) + return TRUE; + if (eid_ptr->Eid != IE_WPA2 && eid_ptr->Eid != IE_WPA && eid_ptr->Eid != IE_WAPI) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[ERROR]%s : invalid IE=%d\n", __func__, eid_ptr->Eid)); + return FALSE; + } + + /* check version */ + len += 2; + if (eid_ptr->Len < len) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[ERROR]%s : no version(len = %d)\n", __func__, eid_ptr->Len)); + return FALSE; + } + NdisMoveMemory(&ver, pStaTmp, sizeof(ver)); + ver = cpu2le16(ver); + + if (ver != 1) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[ERROR]%s : unknown version(%d)\n", __func__, ver)); + return FALSE; + } + + if (eid_ptr->Len == len) { + /* None of the optional fields are included in the RSNE */ + *end_field = RSN_FIELD_NONE; + return TRUE; + } + + pStaTmp += sizeof(USHORT); + + /* check group cipher suite */ + len += LEN_OUI_SUITE; + if (eid_ptr->Len < len) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[ERROR]%s : group cipher is truncated(len = %d)\n", __func__, eid_ptr->Len)); + return FALSE; + } else if (eid_ptr->Len == len) { + /* Group Data Cipher Suite are included in the RSNE */ + *end_field = RSN_FIELD_GROUP_CIPHER; + return TRUE; + } + + pStaTmp += LEN_OUI_SUITE; + + /* check pairwise cipher suite */ + len += 2; + if (eid_ptr->Len < len) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[ERROR]%s : pairwise cipher suite cnt is truncated(%d)\n", __func__, eid_ptr->Len)); + return FALSE; + } + + /* Store pairwise cipher count */ + NdisMoveMemory(&Count, pStaTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + + len += Count * LEN_OUI_SUITE; + + if (eid_ptr->Len < len) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[ERROR]%s : Pairwise Cipher Suite is truncated(len %d)\n", __func__, eid_ptr->Len)); + return FALSE; + } else if (eid_ptr->Len == len) { + /* Pairwise Cipher Suite are included in the RSNE */ + *end_field = RSN_FIELD_PAIRWISE_CIPHER; + return TRUE; + } + + pStaTmp += sizeof(USHORT) + Count * LEN_OUI_SUITE; + + /* check akm suite */ + len += 2; + if (eid_ptr->Len < len) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[ERROR]%s : akm suite cnt is truncated(%d)\n", __func__, eid_ptr->Len)); + return FALSE; + } + + /* Store akm count */ + NdisMoveMemory(&Count, pStaTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + + len += Count * LEN_OUI_SUITE; + if (eid_ptr->Len < len) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[ERROR]%s : Akm Suite is truncated(len %d)\n", __func__, eid_ptr->Len)); + return FALSE; + } else if (eid_ptr->Len == len) { + /* akm Suite are included in the RSNE */ + *end_field = RSN_FIELD_AKM; + return TRUE; + } + + pStaTmp += sizeof(USHORT) + Count * LEN_OUI_SUITE; + + /* check rsn capabilities */ + len += 2; + if (eid_ptr->Len < len) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[ERROR]%s : RSN capabilities is truncated(len %d)\n", __func__, eid_ptr->Len)); + return FALSE; + } else if (eid_ptr->Len == len) { + /* rsn capabilities are included in the RSNE */ + *end_field = RSN_FIELD_RSN_CAP; + return TRUE; + } + + pStaTmp += 2; + + /* check PMKID */ + len += 2; + if (eid_ptr->Len < len) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[ERROR]%s : pmkid cnt is truncated(%d)\n", __func__, eid_ptr->Len)); + return FALSE; + } + + /* Store pmkid count */ + NdisMoveMemory(&Count, pStaTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + + len += Count * 16; + + if (eid_ptr->Len < len) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[ERROR]%s : PMKID is truncated(len %d)\n", __func__, eid_ptr->Len)); + return FALSE; + } else if (eid_ptr->Len == len) { + /* PMKID are included in the RSNE */ + *end_field = RSN_FIELD_PMKID; + return TRUE; + } + + pStaTmp += 2 + Count * 16; + + +#ifdef DOT11W_PMF_SUPPORT + /* check Group Management Cipher Suite*/ + len += LEN_OUI_SUITE; + if (eid_ptr->Len < len) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[ERROR]%s : Group Management Cipher Suite is truncated(len %d)\n", __func__, eid_ptr->Len)); + return FALSE; + } else if (eid_ptr->Len == len) { + /* PMKID are included in the RSNE */ + *end_field = RSN_FIELD_GROUP_MGMT_CIPHER; + return TRUE; + } + + pStaTmp += LEN_OUI_SUITE; +#endif + + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s : extensible element len %d\n", __func__, eid_ptr->Len - len)); + *end_field = RSN_FIELD_EXTENSIBLE_ELE; + return TRUE; +} +#endif +/* + ========================================================================== + 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; +#ifdef DOT11W_PMF_SUPPORT + INT apidx; + BSS_STRUCT *pMbss; +#endif /* DOT11W_PMF_SUPPORT */ +#ifdef CONFIG_SECURITY_IMPROVEMENT_SUPPORT + UCHAR end_field = 0; +#endif + if (rsnie_len == 0) + return MLME_SUCCESS; + + eid_ptr = (PEID_STRUCT)pRsnIe; +#ifndef CONFIG_SECURITY_IMPROVEMENT_SUPPORT + if ((eid_ptr->Len + 2) != rsnie_len) { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]APValidateRSNIE : the len is invalid !!!\n")); + return MLME_UNSPECIFY_FAIL; + } +#else + if (wpa_rsne_sanity(pRsnIe, rsnie_len, &end_field) == FALSE) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s : wpa_rsne_sanity fail\n", __func__)); + return MLME_UNSPECIFY_FAIL; + } +#endif +#ifdef DOT11W_PMF_SUPPORT + apidx = pEntry->func_tb_idx; + pMbss = &pAd->ApCfg.MBSSID[apidx]; +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef WAPI_SUPPORT + if (eid_ptr->Eid == IE_WAPI) + return MLME_SUCCESS; +#endif /* WAPI_SUPPORT */ + +#ifndef CONFIG_SECURITY_IMPROVEMENT_SUPPORT + /* check group cipher */ + if (!RTMPCheckMcast(pAd, eid_ptr, pEntry)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]APValidateRSNIE : invalid group cipher !!!\n")); + StatusCode = MLME_INVALID_GROUP_CIPHER; + } + /* Check pairwise cipher */ + else if (!RTMPCheckUcast(pAd, eid_ptr, pEntry)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]APValidateRSNIE : invalid pairwise cipher !!!\n")); + StatusCode = MLME_INVALID_PAIRWISE_CIPHER; + } + /* Check AKM */ + else if (!RTMPCheckAUTH(pAd, eid_ptr, pEntry)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]APValidateRSNIE : invalid AKM !!!\n")); + StatusCode = MLME_INVALID_AKMP; + } +#ifdef DOT11W_PMF_SUPPORT + else if (PMF_RsnCapableValidation(pAd, pRsnIe, rsnie_len, + pMbss->PmfCfg.MFPC, pMbss->PmfCfg.MFPR, +#ifdef CONFIG_SECURITY_IMPROVEMENT_SUPPORT + end_field, +#endif +#ifdef CONFIG_OWE_SUPPORT + apidx, +#endif + pEntry) != PMF_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Invalid PMF Capability !!!\n", __FUNCTION__)); + StatusCode = MLME_ROBUST_MGMT_POLICY_VIOLATION; + } +#endif /* DOT11W_PMF_SUPPORT */ + +#else + /* check group cipher */ + if (end_field >= RSN_FIELD_GROUP_CIPHER && !RTMPCheckMcast(pAd, eid_ptr, pEntry)) { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]APValidateRSNIE : invalid group cipher !!!\n")); + StatusCode = MLME_INVALID_GROUP_CIPHER; + } else if (end_field < RSN_FIELD_GROUP_CIPHER + && pMbss->wdev.GroupKeyWepStatus == Ndis802_11AESEnable) + pEntry->GroupKeyWepStatus = pMbss->wdev.GroupKeyWepStatus; + else if (end_field < RSN_FIELD_GROUP_CIPHER) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[ERROR]%s : invalid group cipher(peer use default cipher) !!!\n", __func__)); + return MLME_INVALID_GROUP_CIPHER; + } + + /* Check pairwise cipher */ + if (end_field >= RSN_FIELD_PAIRWISE_CIPHER && !RTMPCheckUcast(pAd, eid_ptr, pEntry)) { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]APValidateRSNIE : invalid pairwise cipher !!!\n")); + StatusCode = MLME_INVALID_PAIRWISE_CIPHER; + } else if (end_field < RSN_FIELD_PAIRWISE_CIPHER + && pMbss->wdev.WepStatus == Ndis802_11AESEnable) + pEntry->WepStatus = pMbss->wdev.WepStatus; + else if (end_field < RSN_FIELD_PAIRWISE_CIPHER) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[ERROR]%s : invalid pairwise cipher(peer use default cipher) !!!\n", __func__)); + return MLME_INVALID_PAIRWISE_CIPHER; + } + + /* Check AKM */ + if (end_field >= RSN_FIELD_AKM && !RTMPCheckAUTH(pAd, eid_ptr, pEntry)) { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]APValidateRSNIE : invalid AKM !!!\n")); + StatusCode = MLME_INVALID_AKMP; + } else if (end_field < RSN_FIELD_AKM + && pMbss->wdev.AuthMode == Ndis802_11AuthModeWPA2) + pEntry->AuthMode = pMbss->wdev.AuthMode; + else if (end_field < RSN_FIELD_AKM) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[ERROR]%s : invalid AKM(peer use default akm) !!!\n", __func__)); + return MLME_INVALID_AKMP; + } + /* Check PMKID */ + if (end_field >= RSN_FIELD_PMKID && !wpa_check_pmkid(pRsnIe, rsnie_len, pEntry->AuthMode)) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("[ERROR]%s : invalid PMKID !!!\n", __func__)); + return MLME_UNSPECIFY_FAIL; + } + +#ifdef DOT11W_PMF_SUPPORT + else if (PMF_RsnCapableValidation(pAd, pRsnIe, rsnie_len, + pMbss->PmfCfg.MFPC, pMbss->PmfCfg.MFPR, +#ifdef CONFIG_SECURITY_IMPROVEMENT_SUPPORT + end_field, +#endif +#ifdef CONFIG_OWE_SUPPORT + apidx, +#endif + pEntry) != PMF_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Invalid PMF Capability !!!\n", __func__)); + StatusCode = MLME_ROBUST_MGMT_POLICY_VIOLATION; + } +#endif /* DOT11W_PMF_SUPPORT */ + + +#endif/* CONFIG_SECURITY_IMPROVEMENT_SUPPORT */ + if (StatusCode != MLME_SUCCESS) + { + /* send wireless event - for RSN IE sanity check fail */ + RTMPSendWirelessEvent(pAd, IW_RSNIE_SANITY_FAIL_EVENT_FLAG, pEntry->Addr, 0, 0); + DBGPRINT(RT_DEBUG_ERROR, ("%s : invalid status code(%d) !!!\n", __FUNCTION__, StatusCode)); + } + else + { +#ifdef DBG + UCHAR CipherAlg = CIPHER_NONE; + + if (pEntry->WepStatus == Ndis802_11WEPEnabled) + CipherAlg = CIPHER_WEP64; + else if (pEntry->WepStatus == Ndis802_11TKIPEnable) + CipherAlg = CIPHER_TKIP; + else if (pEntry->WepStatus == Ndis802_11AESEnable) + CipherAlg = CIPHER_AES; + DBGPRINT(RT_DEBUG_TRACE, ("%s : (AID#%d WepStatus=%s)\n", __FUNCTION__, pEntry->Aid, CipherName[CipherAlg])); +#endif /* DBG */ + } + + + + return StatusCode; + +} + +/* + ========================================================================== + Description: + Function to handle countermeasures active attack. Init 60-sec timer if necessary. + Return: + ========================================================================== +*/ +VOID HandleCounterMeasure(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + INT i; + BOOLEAN Cancelled; + + if (!pEntry) + return; + + /* Todo by AlbertY - Not support currently in ApClient-link */ + if (IS_ENTRY_APCLI(pEntry)) + return; + + /* if entry not set key done, ignore this RX MIC ERROR */ + if ((pEntry->WpaState < AS_PTKINITDONE) || (pEntry->GTKState != REKEY_ESTABLISHED)) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("HandleCounterMeasure ===> \n")); + + /* record which entry causes this MIC error, if this entry sends disauth/disassoc, AP doesn't need to log the CM */ + pEntry->CMTimerRunning = TRUE; + pAd->ApCfg.MICFailureCounter++; + + /* send wireless event - for MIC error */ + RTMPSendWirelessEvent(pAd, IW_MIC_ERROR_EVENT_FLAG, pEntry->Addr, 0, 0); + + if (pAd->ApCfg.CMTimerRunning == TRUE) + { + DBGPRINT(RT_DEBUG_ERROR, ("Receive CM Attack Twice within 60 seconds ====>>> \n")); + + /* send wireless event - for counter measures */ + RTMPSendWirelessEvent(pAd, IW_COUNTER_MEASURES_EVENT_FLAG, pEntry->Addr, 0, 0); + ApLogEvent(pAd, pEntry->Addr, EVENT_COUNTER_M); + + /* renew GTK */ + GenRandom(pAd, pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid, pAd->ApCfg.MBSSID[pEntry->func_tb_idx].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->func_tb_idx].GKeyDoneStations = pAd->MacTab.Size; */ + /*DBGPRINT(RT_DEBUG_TRACE, ("GKeyDoneStations=%d \n", pAd->ApCfg.MBSSID[pEntry->func_tb_idx].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 = NULL; + + pEntry = (MAC_TABLE_ENTRY *)FunctionContext; + MlmeEnqueue(pEntry->pAd, WPA_STATE_MACHINE, MT2_EAPOLTIMEOUT, 6, &pEntry->Addr, 0); +} + + +/* + ========================================================================== + Description: + Timer execution function for periodically updating group key. + Return: + ========================================================================== +*/ +VOID GREKEYPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + UINT i, apidx; + ULONG temp_counter = 0; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + PRALINK_TIMER_STRUCT pTimer = (PRALINK_TIMER_STRUCT) SystemSpecific3; + BSS_STRUCT *pMbss = NULL; + struct wifi_dev *wdev; + + for (apidx=0; apidxApCfg.BssidNum; apidx++) + { + if (&pAd->ApCfg.MBSSID[apidx].REKEYTimer == pTimer) + break; + } + + if (apidx == pAd->ApCfg.BssidNum) + return; + else + pMbss = &pAd->ApCfg.MBSSID[apidx]; + + wdev = &pMbss->wdev; + if (wdev->AuthMode < Ndis802_11AuthModeWPA || + wdev->AuthMode > Ndis802_11AuthModeWPA1PSKWPA2PSK) + return; + + if ((pMbss->WPAREKEY.ReKeyMethod == TIME_REKEY) && (pMbss->REKEYCOUNTER < 0xffffffff)) + temp_counter = (++pMbss->REKEYCOUNTER); + /* REKEYCOUNTER is incremented every MCAST packets transmitted, */ + /* But the unit of Rekeyinterval is 1K packets */ + else if (pMbss->WPAREKEY.ReKeyMethod == PKT_REKEY) + temp_counter = pMbss->REKEYCOUNTER/1000; + else + { + return; + } + + if (temp_counter > (pMbss->WPAREKEY.ReKeyInterval)) + { + pMbss->REKEYCOUNTER = 0; + pMbss->RekeyCountDown = 3; + DBGPRINT(RT_DEBUG_TRACE, ("Rekey Interval Excess, GKeyDoneStations=%d\n", pMbss->StaCount)); + + /* take turn updating different groupkey index, */ + if ((pMbss->StaCount) > 0) + { + /* change key index */ + wdev->DefaultKeyId = (wdev->DefaultKeyId == 1) ? 2 : 1; + + /* Generate GNonce randomly */ + GenRandom(pAd, wdev->bssid, pMbss->GNonce); + + /* Update GTK */ + WpaDeriveGTK(pMbss->GMK, + (UCHAR*)pMbss->GNonce, + wdev->bssid, pMbss->GTK, LEN_TKIP_GTK); + + /* Process 2-way handshaking */ + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + MAC_TABLE_ENTRY *pEntry; + + pEntry = &pAd->MacTab.Content[i]; + if (IS_ENTRY_CLIENT(pEntry) && + (pEntry->WpaState == AS_PTKINITDONE) && + (pEntry->func_tb_idx == apidx)) + { +#ifdef A4_CONN + if (IS_ENTRY_A4(pEntry)) + continue; +#endif /* A4_CONN */ + pEntry->GTKState = REKEY_NEGOTIATING; + + WPAStart2WayGroupHS(pAd, pEntry); + /*set retry counter for GTK update*/ + pEntry->ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR; + DBGPRINT(RT_DEBUG_TRACE, ("Rekey interval excess, Update Group Key for %x %x %x %x %x %x , DefaultKeyId= %x \n",\ + PRINT_MAC(pEntry->Addr), wdev->DefaultKeyId)); + } + } + } + } + + /* Use countdown to ensure the 2-way handshaking had completed */ + if (pMbss->RekeyCountDown > 0) + { + pMbss->RekeyCountDown--; + if (pMbss->RekeyCountDown == 0) + { + USHORT Wcid; + + /* Get a specific WCID to record this MBSS key attribute */ + GET_GroupKey_WCID(pAd, Wcid, apidx); + + /* Install shared key table */ + WPAInstallSharedKey(pAd, + wdev->GroupKeyWepStatus, + apidx, + wdev->DefaultKeyId, + Wcid, + TRUE, + pMbss->GTK, + LEN_TKIP_GTK); + } + } + +} + + +#if defined(DOT1X_SUPPORT) || defined(CONFIG_OWE_SUPPORT) || defined(DOT11_SAE_SUPPORT) +/* + ======================================================================== + + Routine Description: + Sending EAP Req. frame to station in authenticating state. + These frames come from Authenticator deamon. + + Arguments: + pAdapter Pointer to our adapter + pPacket Pointer to outgoing EAP frame body + 8023 Header + Len length of pPacket + + Return Value: + None + ======================================================================== +*/ +VOID WpaSend(RTMP_ADAPTER *pAdapter, UCHAR *pPacket, ULONG Len) +{ + PEAP_HDR pEapHdr; + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR Header802_3[LENGTH_802_3]; + MAC_TABLE_ENTRY *pEntry; + STA_TR_ENTRY *tr_entry; + 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; + } + + tr_entry = &pAdapter->MacTab.tr_entry[pEntry->wcid]; + /* Send EAP frame to STA */ + if (((pEntry->AuthMode >= Ndis802_11AuthModeWPA) && (pEapHdr->ProType != EAPOLKey)) || + (pAdapter->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.IEEE8021X == TRUE)) + RTMPToWirelessSta(pAdapter, + pEntry, + Header802_3, + LENGTH_802_3, + pData, + Len - LENGTH_802_3, + (tr_entry->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->func_tb_idx].wdev.PortSecured = WPA_802_1X_PORT_SECURED; + tr_entry->PortSecured = WPA_802_1X_PORT_SECURED; +#ifdef WSC_AP_SUPPORT + if (pAdapter->ApCfg.MBSSID[pEntry->func_tb_idx].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); + } +} + +#if defined(CONFIG_OWE_SUPPORT) || defined(DOT11_SAE_SUPPORT) +VOID store_pmkid_cache_in_entry( + IN RTMP_ADAPTER * pAd, + IN MAC_TABLE_ENTRY * pEntry, + IN INT32 cache_idx) +{ + if (!pEntry) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s(): pEntry is null\n", __func__)); + return; + } + + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_LOUD, ("EntryType = %d\n", pEntry->EntryType)); + + if (cache_idx == -1) { + pEntry->pmkid = NULL; + pEntry->pmk_cache = NULL; + } else { + if (IS_ENTRY_CLIENT(pEntry)) { +#ifdef CONFIG_AP_SUPPORT + BSS_STRUCT *pBMbss; + pBMbss = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx]; + pEntry->pmkid = &pBMbss->PMKIDCache.BSSIDInfo[cache_idx].PMKID[0]; + pEntry->pmk_cache = pBMbss->PMKIDCache.BSSIDInfo[cache_idx].PMK; +#endif + } + } + +} + + +UCHAR is_pmkid_cache_in_entry( + IN MAC_TABLE_ENTRY * pEntry) +{ + if (pEntry && pEntry->pmkid && pEntry->pmk_cache) + return TRUE; + else + return FALSE; +} +#endif +VOID RTMPAddPMKIDCache( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PUCHAR pAddr, + IN UCHAR *PMKID, + IN UCHAR *PMK +#ifdef CONFIG_OWE_SUPPORT + , IN UINT8 pmk_len +#endif + ) +{ + 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, +#ifndef CONFIG_OWE_SUPPORT + LEN_PMK +#else + pmk_len +#endif + ); + DBGPRINT(RT_DEBUG_TRACE, + ("RTMPAddPMKIDCache update %02x:%02x:%02x:%02x:%02x:%02x cache(%d) from IF(ra%d)\n", + PRINT_MAC(pAddr), CacheIdx, apidx)); + + return; + } + + /* Add a new PMKID */ + for (i = 0; i < MAX_PMKID_COUNT; i++) + { + if (!pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].Valid) + { + pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].Valid = TRUE; + NdisGetSystemUpTime(&(pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].RefreshTime)); + COPY_MAC_ADDR(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].MAC, pAddr); + NdisMoveMemory(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].PMKID, PMKID, LEN_PMKID); + NdisMoveMemory(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].PMK, PMK, +#ifndef CONFIG_OWE_SUPPORT + LEN_PMK +#else + pmk_len +#endif + ); + DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddPMKIDCache add %02x:%02x:%02x:%02x:%02x:%02x cache(%d) from IF(ra%d)\n", + PRINT_MAC(pAddr), i, apidx)); + break; + } + } + + if (i == MAX_PMKID_COUNT) + { + ULONG timestamp = 0, idx = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddPMKIDCache(IF(%d) Cache full\n", apidx)); + for (i = 0; i < MAX_PMKID_COUNT; i++) + { + if (pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].Valid) + { + if (((timestamp == 0) && (idx == 0)) || ((timestamp != 0) && timestamp < pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].RefreshTime)) + { + timestamp = pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].RefreshTime; + idx = i; + } + } + } + pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[idx].Valid = TRUE; + NdisGetSystemUpTime(&(pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[idx].RefreshTime)); + COPY_MAC_ADDR(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[idx].MAC, pAddr); + NdisMoveMemory(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[idx].PMKID, PMKID, LEN_PMKID); + NdisMoveMemory(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[idx].PMK, PMK, +#ifndef CONFIG_OWE_SUPPORT + LEN_PMK +#else + pmk_len +#endif + ); + DBGPRINT(RT_DEBUG_TRACE, ("RTMPAddPMKIDCache add %02x:%02x:%02x:%02x:%02x:%02x cache(%ld) from IF(ra%d)\n", + PRINT_MAC(pAddr), idx, apidx)); + } +} + +INT RTMPSearchPMKIDCache( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PUCHAR pAddr) +{ + INT i = 0; + + for (i = 0; i < MAX_PMKID_COUNT; i++) + { + if ((pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].Valid) + && MAC_ADDR_EQUAL(&pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[i].MAC, pAddr)) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSearchPMKIDCache %02x:%02x:%02x:%02x:%02x:%02x cache(%d) from IF(ra%d)\n", + PRINT_MAC(pAddr), i, apidx)); + break; + } + } + + if (i == MAX_PMKID_COUNT) + { + DBGPRINT(RT_DEBUG_TRACE, ("RTMPSearchPMKIDCache - IF(%d) not found\n", apidx)); + return -1; + } + + return i; +} + +VOID RTMPDeletePMKIDCache( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN INT idx) +{ + PAP_BSSID_INFO pInfo = &pAd->ApCfg.MBSSID[apidx].PMKIDCache.BSSIDInfo[idx]; + + if (pInfo->Valid) + { + pInfo->Valid = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("RTMPDeletePMKIDCache(IF(%d), del PMKID CacheIdx=%d\n", apidx, idx)); + } +} + +VOID RTMPMaintainPMKIDCache( + IN PRTMP_ADAPTER pAd) +{ + INT i, j; + ULONG Now; + for (i = 0; i < MAX_MBSSID_NUM(pAd); i++) + { + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[i]; + + for (j = 0; j < MAX_PMKID_COUNT; j++) + { + PAP_BSSID_INFO pBssInfo = &pMbss->PMKIDCache.BSSIDInfo[j]; + + NdisGetSystemUpTime(&Now); + + if ((pBssInfo->Valid) + && /*((Now - pBssInfo->RefreshTime) >= pMbss->PMKCachePeriod)*/ + (RTMP_TIME_AFTER(Now, (pBssInfo->RefreshTime + pMbss->PMKCachePeriod)))) + { + RTMPDeletePMKIDCache(pAd, i, j); + } + } + } +} +#endif /* DOT1X_SUPPORT */ + + +/* + ========================================================================== + Description: + Set group re-key timer + + Return: + + ========================================================================== +*/ +VOID WPA_APSetGroupRekeyAction( + IN PRTMP_ADAPTER pAd) +{ + UINT8 apidx = 0; + + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; + struct wifi_dev *wdev = &pMbss->wdev; + + if ((wdev->WepStatus == Ndis802_11TKIPEnable) || + (wdev->WepStatus == Ndis802_11AESEnable) || + (wdev->WepStatus == Ndis802_11TKIPAESMix)) + { + /* Group rekey related */ + if ((pMbss->WPAREKEY.ReKeyInterval != 0) + && ((pMbss->WPAREKEY.ReKeyMethod == TIME_REKEY) || ( + pMbss->WPAREKEY.ReKeyMethod == PKT_REKEY))) + { + /* Regularly check the timer */ + if (pMbss->REKEYTimerRunning == FALSE) + { + RTMPSetTimer(&pMbss->REKEYTimer, GROUP_KEY_UPDATE_EXEC_INTV); + + pMbss->REKEYTimerRunning = TRUE; + pMbss->REKEYCOUNTER = 0; + } + DBGPRINT(RT_DEBUG_TRACE, (" %s : Group rekey method= %ld , interval = 0x%lx\n", + __FUNCTION__, pMbss->WPAREKEY.ReKeyMethod, + pMbss->WPAREKEY.ReKeyInterval)); + } + else + pMbss->REKEYTimerRunning = FALSE; + } + } +} + + +#ifdef HOSTAPD_SUPPORT +/*for sending an event to notify hostapd about michael failure. */ +VOID ieee80211_notify_michael_failure( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHeader, + IN UINT keyix, + IN INT report) +{ + static const char *tag = "MLME-MICHAELMICFAILURE.indication"; +/* struct net_device *dev = pAd->net_dev; */ +/* union iwreq_data wrqu; */ + char buf[128]; /* XXX */ + + + /* TODO: needed parameters: count, keyid, key type, src address, TSC */ + if(report)/*station reports a mic error to this ap. */ + { + snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=%s)", tag, + keyix, "uni", + ether_sprintf(pHeader->Addr2)); + } + else/*ap itself receives a mic error. */ + { + snprintf(buf, sizeof(buf), "%s(keyid=%d %scast addr=%s)", tag, + keyix, IEEE80211_IS_MULTICAST(pHeader->Addr1) ? "broad" : "uni", + ether_sprintf(pHeader->Addr2)); + } + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, -1, NULL, NULL, 0); +/* NdisZeroMemory(&wrqu, sizeof(wrqu)); */ +/* wrqu.data.length = strlen(buf); */ +/* wireless_send_event(dev, RT_WLAN_EVENT_CUSTOM, &wrqu, buf); */ +} + + +const CHAR* ether_sprintf(const UINT8 *mac) +{ + static char etherbuf[18]; + snprintf(etherbuf,sizeof(etherbuf),"%02x:%02x:%02x:%02x:%02x:%02x", PRINT_MAC(mac)); + return etherbuf; +} +#endif /* HOSTAPD_SUPPORT */ + + +#ifdef APCLI_SUPPORT +#endif/*APCLI_SUPPORT*/ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_assoc.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_assoc.c new file mode 100644 index 000000000..95884f346 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_assoc.c @@ -0,0 +1,1288 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2006, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + + Module Name: + apcli_assoc.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi 2006-6-23 modified for rt61-APClinent +*/ + +#ifdef APCLI_SUPPORT + +#include "rt_config.h" + +static VOID ApCliAssocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +#ifdef MAC_REPEATER_SUPPORT +static VOID ApCliAssocTimeoutExt( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* MAC_REPEATER_SUPPORT */ + +static VOID ApCliMlmeAssocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliMlmeDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliPeerAssocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliPeerDisassocAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliAssocTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliInvalidStateWhenAssoc( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliInvalidStateWhenDisassociate( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +static VOID ApCliAssocPostProc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr2, + IN USHORT CapabilityInfo, + IN USHORT IfIndex, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN PEDCA_PARM pEdcaParm, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN ADD_HT_INFO_IE *pAddHtInfo); + +DECLARE_TIMER_FUNCTION(ApCliAssocTimeout); +BUILD_TIMER_FUNCTION(ApCliAssocTimeout); +#ifdef MAC_REPEATER_SUPPORT +DECLARE_TIMER_FUNCTION(ApCliAssocTimeoutExt); +BUILD_TIMER_FUNCTION(ApCliAssocTimeoutExt); +#endif /* MAC_REPEATER_SUPPORT */ + +/* + ========================================================================== + Description: + association state machine init, including state transition and timer init + Parameters: + S - pointer to the association state machine + Note: + The state machine looks like the following + ========================================================================== + */ +VOID ApCliAssocStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + UCHAR i; +#ifdef MAC_REPEATER_SUPPORT + UCHAR j; +#endif /* MAC_REPEATER_SUPPORT */ + + StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, + APCLI_MAX_ASSOC_STATE, APCLI_MAX_ASSOC_MSG, + (STATE_MACHINE_FUNC)Drop, APCLI_ASSOC_IDLE, + APCLI_ASSOC_MACHINE_BASE); + + /* first column */ + StateMachineSetAction(S, APCLI_ASSOC_IDLE, APCLI_MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)ApCliMlmeAssocReqAction); + StateMachineSetAction(S, APCLI_ASSOC_IDLE, APCLI_MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)ApCliMlmeDisassocReqAction); + StateMachineSetAction(S, APCLI_ASSOC_IDLE, APCLI_MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)ApCliPeerDisassocAction); + + /* second column */ + StateMachineSetAction(S, APCLI_ASSOC_WAIT_RSP, APCLI_MT2_MLME_ASSOC_REQ, (STATE_MACHINE_FUNC)ApCliInvalidStateWhenAssoc); + StateMachineSetAction(S, APCLI_ASSOC_WAIT_RSP, APCLI_MT2_MLME_DISASSOC_REQ, (STATE_MACHINE_FUNC)ApCliInvalidStateWhenDisassociate); + StateMachineSetAction(S, APCLI_ASSOC_WAIT_RSP, APCLI_MT2_PEER_DISASSOC_REQ, (STATE_MACHINE_FUNC)ApCliPeerDisassocAction); + StateMachineSetAction(S, APCLI_ASSOC_WAIT_RSP, APCLI_MT2_PEER_ASSOC_RSP, (STATE_MACHINE_FUNC)ApCliPeerAssocRspAction); + StateMachineSetAction(S, APCLI_ASSOC_WAIT_RSP, APCLI_MT2_ASSOC_TIMEOUT, (STATE_MACHINE_FUNC)ApCliAssocTimeoutAction); + + for (i=0; i < MAX_APCLI_NUM; i++) + { + pAd->ApCfg.ApCliTab[i].AssocCurrState = APCLI_ASSOC_IDLE; + + /* timer init */ + RTMPInitTimer(pAd, &pAd->ApCfg.ApCliTab[i].MlmeAux.ApCliAssocTimer, + GET_TIMER_FUNCTION(ApCliAssocTimeout), pAd, FALSE); + +#ifdef MAC_REPEATER_SUPPORT + for (j = 0; j < MAX_EXT_MAC_ADDR_SIZE; j++) + { + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].pAd = pAd; + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].MatchApCliIdx = i; + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].MatchLinkIdx = j; + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].AssocCurrState = APCLI_ASSOC_IDLE; + + /* timer init */ + RTMPInitTimer(pAd, &pAd->ApCfg.ApCliTab[i].RepeaterCli[j].ApCliAssocTimer, + GET_TIMER_FUNCTION(ApCliAssocTimeoutExt), &pAd->ApCfg.ApCliTab[i].RepeaterCli[j], FALSE); + } +#endif /* MAC_REPEATER_SUPPORT */ + } + + return; +} + +/* + ========================================================================== + Description: + Association timeout procedure. After association timeout, this function + will be called and it will put a message into the MLME queue + Parameters: + Standard timer parameters + ========================================================================== + */ +static VOID ApCliAssocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - enqueue APCLI_MT2_ASSOC_TIMEOUT \n")); + + MlmeEnqueue(pAd, APCLI_ASSOC_STATE_MACHINE, APCLI_MT2_ASSOC_TIMEOUT, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); + + return; +} + +#ifdef MAC_REPEATER_SUPPORT +/* + ========================================================================== + Description: + Association timeout procedure. After association timeout, this function + will be called and it will put a message into the MLME queue + Parameters: + Standard timer parameters + ========================================================================== + */ +static VOID ApCliAssocTimeoutExt( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PREPEATER_CLIENT_ENTRY pRepeaterCliEntry = (PREPEATER_CLIENT_ENTRY)FunctionContext; + PRTMP_ADAPTER pAd; + USHORT ifIndex = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("Repeater Cli ASSOC - enqueue APCLI_MT2_ASSOC_TIMEOUT\n")); + + pAd = pRepeaterCliEntry->pAd; + ifIndex = (64 + (16*pRepeaterCliEntry->MatchApCliIdx) + pRepeaterCliEntry->MatchLinkIdx); + + DBGPRINT(RT_DEBUG_ERROR, (" (%s) ifIndex = %d, CliIdx = %d !!!\n", + __FUNCTION__, pRepeaterCliEntry->MatchApCliIdx, pRepeaterCliEntry->MatchLinkIdx)); + + MlmeEnqueue(pAd, APCLI_ASSOC_STATE_MACHINE, APCLI_MT2_ASSOC_TIMEOUT, 0, NULL, ifIndex); + RTMP_MLME_HANDLER(pAd); + + return; +} +#endif /* MAC_REPEATER_SUPPORT */ + +/* + ========================================================================== + Description: + mlme assoc req handling procedure + Parameters: + Adapter - Adapter pointer + Elem - MLME Queue Element + Pre: + the station has been authenticated and the following information is stored in the config + -# SSID + -# supported rates and their length + Post : + -# An association request frame is generated and sent to the air + -# Association timer starts + -# Association state -> ASSOC_WAIT_RSP + + ========================================================================== + */ +static VOID ApCliMlmeAssocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + NDIS_STATUS NStatus; + BOOLEAN Cancelled; + UCHAR ApAddr[6]; + HEADER_802_11 AssocHdr; + UCHAR WmeIe[9] = {IE_VENDOR_SPECIFIC, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00}; + USHORT ListenIntv; + ULONG Timeout; + USHORT CapabilityInfo; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + ULONG tmp; + UCHAR SsidIe = IE_SSID; + UCHAR SupRateIe = IE_SUPP_RATES; + UCHAR ExtRateIe = IE_EXT_SUPP_RATES; + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; + UCHAR RSNIe = IE_WPA; + APCLI_STRUCT *apcli_entry; + struct wifi_dev *wdev; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; +#endif +#endif /* MAC_REPEATER_SUPPORT */ +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + MAC_TABLE_ENTRY *pentry = (MAC_TABLE_ENTRY *)NULL; +#endif +#ifdef APCLI_OWE_SUPPORT + OWE_INFO *owe = NULL; + UCHAR *curr_group = NULL; +#endif + + +#ifdef WH_EZ_SETUP + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("ApCliMlmeAssocReqAction()\n")); +#endif + if ((ifIndex >= MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + && (ifIndex < 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AssocCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AssocCurrState; + + apcli_entry = &pAd->ApCfg.ApCliTab[ifIndex]; + wdev = &apcli_entry->wdev; + +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + pentry = &apcli_entry->pre_mac_entry; +#endif + /* Block all authentication request durning WPA block period */ + if (apcli_entry->bBlockAssoc == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - Block Auth request durning WPA block period!\n")); + *pCurrState = APCLI_ASSOC_IDLE; + ApCliCtrlMsg.Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_ASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + } + else if(MlmeAssocReqSanity(pAd, Elem->Msg, Elem->MsgLen, ApAddr, &CapabilityInfo, &Timeout, &ListenIntv)) + { + //RTMPCancelTimer(&apcli_entry->MlmeAux.ApCliAssocTimer, &Cancelled); +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + RTMPCancelTimer(&apcli_entry->RepeaterCli[CliIdx].ApCliAssocTimer, &Cancelled); + else +#endif /* MAC_REPEATER_SUPPORT */ + RTMPCancelTimer(&apcli_entry->MlmeAux.ApCliAssocTimer, &Cancelled); + + /* allocate and send out AssocRsp frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - ApCliMlmeAssocReqAction() allocate memory failed \n")); + *pCurrState = APCLI_ASSOC_IDLE; + + ApCliCtrlMsg.Status = MLME_FAIL_NO_RESOURCE; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_ASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + + return; + } + + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - Send ASSOC request...\n")); + ApCliMgtMacHeaderInit(pAd, &AssocHdr, SUBTYPE_ASSOC_REQ, 0, ApAddr, ApAddr, ifIndex); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + COPY_MAC_ADDR(AssocHdr.Addr2, apcli_entry->RepeaterCli[CliIdx].CurrentAddress); +#endif /* MAC_REPEATER_SUPPORT */ + + /* Build basic frame first */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &AssocHdr, + 2, &CapabilityInfo, + 2, &ListenIntv, + 1, &SsidIe, + 1, &apcli_entry->MlmeAux.SsidLen, + apcli_entry->MlmeAux.SsidLen, apcli_entry->MlmeAux.Ssid, + 1, &SupRateIe, + 1, &apcli_entry->MlmeAux.SupRateLen, + apcli_entry->MlmeAux.SupRateLen, apcli_entry->MlmeAux.SupRate, + END_OF_ARGS); + + if(apcli_entry->MlmeAux.ExtRateLen != 0) + { + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &apcli_entry->MlmeAux.ExtRateLen, + apcli_entry->MlmeAux.ExtRateLen, apcli_entry->MlmeAux.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef DOT11_N_SUPPORT + /* + 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(wdev->WepStatus)) + { + /* Force to None-HT mode due to WiFi 11n policy */ + apcli_entry->MlmeAux.HtCapabilityLen = 0; +#ifdef DOT11_VHT_AC + apcli_entry->MlmeAux.vht_cap_len = 0; +#endif /* DOT11_VHT_AC */ + DBGPRINT(RT_DEBUG_TRACE, ("%s : Force AP-client as Non-HT mode\n", __FUNCTION__)); + } + + /* HT */ + if ((apcli_entry->MlmeAux.HtCapabilityLen > 0) && + WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + ULONG TmpLen; + HT_CAPABILITY_IE HtCapabilityTmp; + + NdisZeroMemory(&HtCapabilityTmp, sizeof(HT_CAPABILITY_IE)); + NdisMoveMemory(&HtCapabilityTmp, &apcli_entry->MlmeAux.HtCapability, apcli_entry->MlmeAux.HtCapabilityLen); +#ifdef DOT11N_SS3_SUPPORT + HtCapabilityTmp.MCSSet[2] = (apcli_entry->MlmeAux.HtCapability.MCSSet[2] & apcli_entry->RxMcsSet[2]); +#endif /* DOT11N_SS3_SUPPORT */ + +#ifdef RT_BIG_ENDIAN + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); +#endif /* RT_BIG_ENDINA */ + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + 1, &HtCapIe, + 1, &apcli_entry->MlmeAux.HtCapabilityLen, + apcli_entry->MlmeAux.HtCapabilityLen, &HtCapabilityTmp, + END_OF_ARGS); + FrameLen += TmpLen; + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14) && + (apcli_entry->MlmeAux.vht_cap_len)) + { + FrameLen += build_vht_ies(pAd, (UCHAR *)(pOutBuffer + FrameLen), SUBTYPE_ASSOC_REQ); + } +#endif /* DOT11_VHT_AC */ + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef WH_EZ_SETUP + /* + To prevent old device has trouble to parse MTK vendor IE, + insert easy setup IE first. + */ + if (IS_EZ_SETUP_ENABLED(wdev) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + && apcli_entry->MlmeAux.support_easy_setup) { + FrameLen += ez_build_assoc_request_ie(pAd,wdev, ApAddr, pOutBuffer+FrameLen, FrameLen); + } + //Arvind : Required to aad some info in beacon + //FrameLen += build_vendor_ie(pAd, wdev, pOutBuffer+FrameLen, SUBTYPE_ASSOC_REQ); +#endif /* WH_EZ_SETUP */ +#if defined(MWDS) || defined(WH_EZ_SETUP) || defined(STA_FORCE_ROAM_SUPPORT) + FrameLen += build_vendor_ie(pAd, wdev, pOutBuffer+FrameLen +#ifdef CONFIG_OWE_SUPPORT + , VIE_ASSOC_REQ +#endif +#ifdef WH_EZ_SETUP + , SUBTYPE_ASSOC_REQ +#endif + ); +#else + +#ifdef AGGREGATION_SUPPORT + /* + add Ralink proprietary IE to inform AP this STA is going to use AGGREGATION or PIGGY-BACK+AGGREGATION + Case I: (Aggregation + Piggy-Back) + 1. user enable aggregation, AND + 2. Mac support piggy-back + 3. AP annouces it's PIGGY-BACK+AGGREGATION-capable in BEACON + Case II: (Aggregation) + 1. user enable aggregation, AND + 2. AP annouces it's AGGREGATION-capable in BEACON + */ + if (pAd->CommonCfg.bAggregationCapable) + { +#ifdef PIGGYBACK_SUPPORT + if ((pAd->CommonCfg.bPiggyBackCapable) && ((apcli_entry->MlmeAux.APRalinkIe & 0x00000003) == 3)) + { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x03, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } else +#endif /* PIGGYBACK_SUPPORT */ + if (apcli_entry->MlmeAux.APRalinkIe & 0x00000001) + { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x01, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + } + else + { + ULONG TmpLen; + UCHAR RalinkIe[9] = {IE_VENDOR_SPECIFIC, 7, 0x00, 0x0c, 0x43, 0x06, 0x00, 0x00, 0x00}; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + 9, RalinkIe, + END_OF_ARGS); + FrameLen += TmpLen; + } +#endif /* AGGREGATION_SUPPORT */ +#endif + if (apcli_entry->MlmeAux.APEdcaParm.bValid) + { + if (apcli_entry->wdev.UapsdInfo.bAPSDCapable && + apcli_entry->MlmeAux.APEdcaParm.bAPSDCapable) + { + QBSS_STA_INFO_PARM QosInfo; + + NdisZeroMemory(&QosInfo, sizeof(QBSS_STA_INFO_PARM)); + QosInfo.UAPSD_AC_BE = pAd->CommonCfg.bAPSDAC_BE; + QosInfo.UAPSD_AC_BK = pAd->CommonCfg.bAPSDAC_BK; + QosInfo.UAPSD_AC_VI = pAd->CommonCfg.bAPSDAC_VI; + QosInfo.UAPSD_AC_VO = pAd->CommonCfg.bAPSDAC_VO; + QosInfo.MaxSPLength = pAd->CommonCfg.MaxSPLength; + WmeIe[8] |= *(PUCHAR)&QosInfo; + } + else + { + /* The Parameter Set Count is set to ¡§0¡¨ in the association request frames */ + /* WmeIe[8] |= (pAd->MlmeAux.APEdcaParm.EdcaUpdateCount & 0x0f); */ + } + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 9, &WmeIe[0], + END_OF_ARGS); + FrameLen += tmp; + } + + /* Append RSN_IE when WPAPSK OR WPA2PSK, */ + if (((wdev->AuthMode == Ndis802_11AuthModeWPAPSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef APCLI_SAE_SUPPORT + || (pentry->AuthMode == Ndis802_11AuthModeWPA3PSK) + || (pentry->AuthMode == Ndis802_11AuthModeWPA2PSK) +#endif +#ifdef APCLI_OWE_SUPPORT + || (pentry->AuthMode == Ndis802_11AuthModeOWE) +#endif + ) +#ifdef WSC_AP_SUPPORT + && ((apcli_entry->WscControl.WscConfMode == WSC_DISABLE) + || ((apcli_entry->WscControl.WscConfMode != WSC_DISABLE) + && !(apcli_entry->WscControl.bWscTrigger))) +#endif /* WSC_AP_SUPPORT */ + ) + { + RSNIe = IE_WPA; + + if ((wdev->AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef APCLI_SAE_SUPPORT + || (pentry->AuthMode == Ndis802_11AuthModeWPA3PSK) + || (pentry->AuthMode == Ndis802_11AuthModeWPA2PSK) +#endif +#ifdef APCLI_OWE_SUPPORT + || (pentry->AuthMode == Ndis802_11AuthModeOWE) +#endif + ) + RSNIe = IE_WPA2; + + +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + + if ((pentry->AuthMode == Ndis802_11AuthModeWPA3PSK) + || (pentry->AuthMode == Ndis802_11AuthModeOWE) + || (pentry->AuthMode == Ndis802_11AuthModeWPA2PSK + && wdev->AuthMode == Ndis802_11AuthModeWPA3PSK) + ) { + INT idx; + PBSSID_INFO psaved_pmk = NULL; + VOID *psaved_pmk_lock = NULL; + +#ifdef MAC_REPEATER_SUPPORT + pReptEntry = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx]; + + if ((pAd->ApCfg.bMACRepeaterEn) && + (CliIdx != 0xFF)) { + + psaved_pmk = &pReptEntry->SavedPMK[0]; + psaved_pmk_lock = (void *)&pReptEntry->SavedPMK_lock; + } else +#endif /* MAC_REPEATER_SUPPORT */ + { + + psaved_pmk = &apcli_entry->SavedPMK[0]; + psaved_pmk_lock = (VOID *)&apcli_entry->SavedPMK_lock; + + } + pentry = &apcli_entry->pre_mac_entry; /* similar to MlmeAux*/ + + idx = apcli_search_pmkid_cache(pAd, ApAddr, ifIndex +#ifdef MAC_REPEATER_SUPPORT + , CliIdx +#endif + ); + + if (idx != INVALID_PMKID_IDX) { + + if (psaved_pmk_lock) + NdisAcquireSpinLock(psaved_pmk_lock); + + /*Update the pentry->pmkcache from the Saved PMK cache */ + pentry->pmkid = psaved_pmk[idx].PMKID; + pentry->pmk_cache = psaved_pmk[idx].PMK; + + + if (psaved_pmk_lock) + NdisReleaseSpinLock(psaved_pmk_lock); + } + WPAMakeEntryRSNIE(pAd, pentry->AuthMode, pentry->WepStatus, pentry); + } +#endif /* defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) */ + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &RSNIe, + 1, &apcli_entry->RSNIE_Len, + apcli_entry->RSNIE_Len, apcli_entry->RSN_IE, + END_OF_ARGS); + + FrameLen += tmp; + } + +#ifdef WSC_AP_SUPPORT + /* Add WSC IE if we are connecting to WSC AP */ + if ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode != WSC_DISABLE) && + (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger)) + { + UCHAR *pWscBuf = NULL, WscIeLen = 0; + ULONG WscTmpLen = 0; + + 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 */ + +#ifdef APCLI_OWE_SUPPORT + +#ifdef MAC_REPEATER_SUPPORT + + if ((pAd->ApCfg.bMACRepeaterEn) && + (CliIdx != 0xFF)) + curr_group = &pReptEntry->curr_owe_group; + else +#endif /* MAC_REPEATER_SUPPORT */ + curr_group = &apcli_entry->curr_owe_group; + + pentry = &apcli_entry->pre_mac_entry; + + owe = &pentry->owe; + + if (pentry->AuthMode == Ndis802_11AuthModeOWE) { + + /* OWE use initialize group and add owe dh key ie to assoc request */ + if (init_owe_group(owe, *curr_group) == 0) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_ERROR, + ("==> %s(), init_owe_group failed. shall not happen!\n", __func__)); + *pCurrState = APCLI_ASSOC_IDLE; + ApCliCtrlMsg.Status = MLME_UNSPECIFY_FAIL; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_ASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + + return; + } + + if (*curr_group == ECDH_GROUP_384) + pentry->key_deri_alg = SEC_KEY_DERI_SHA384; + else + pentry->key_deri_alg = SEC_KEY_DERI_SHA256; + + FrameLen += build_owe_dh_ie(pAd, pentry, (UCHAR *)(pOutBuffer + FrameLen), *curr_group); + + } + +#endif /*APCLI_OWE_SUPPORT*/ + + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + RTMPSetTimer(&apcli_entry->RepeaterCli[CliIdx].ApCliAssocTimer, Timeout); + else +#endif /* MAC_REPEATER_SUPPORT */ + RTMPSetTimer(&apcli_entry->MlmeAux.ApCliAssocTimer, Timeout); + *pCurrState = APCLI_ASSOC_WAIT_RSP; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - ApCliMlmeAssocReqAction() sanity check failed. BUG!!!!!! \n")); + *pCurrState = APCLI_ASSOC_IDLE; + + ApCliCtrlMsg.Status = MLME_INVALID_FORMAT; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_ASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + } + + return; +} + +/* + ========================================================================== + Description: + Upper layer issues disassoc request + Parameters: + Elem - + ========================================================================== + */ +static VOID ApCliMlmeDisassocReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PMLME_DISASSOC_REQ_STRUCT pDisassocReq; + HEADER_802_11 DisassocHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef WH_EZ_SETUP + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("ApCliMlmeDisassocReqAction() \n")); +#endif + + if ((ifIndex >= MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + && (ifIndex < 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AssocCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AssocCurrState; + + /* skip sanity check */ + pDisassocReq = (PMLME_DISASSOC_REQ_STRUCT)(Elem->Msg); + + /* allocate and send out DeassocReq frame */ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - ApCliMlmeDisassocReqAction() allocate memory failed\n")); + *pCurrState = APCLI_ASSOC_IDLE; + + ApCliCtrlMsg.Status = MLME_FAIL_NO_RESOURCE; +#ifdef MAC_REPEATER_SUPPORT + ApCliCtrlMsg.BssIdx = ifIndex; + ApCliCtrlMsg.CliIdx = CliIdx; + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DEASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - Send DISASSOC request [BSSID::%02x:%02x:%02x:%02x:%02x:%02x] \n", + pDisassocReq->Addr[0], pDisassocReq->Addr[1], pDisassocReq->Addr[2], + pDisassocReq->Addr[3], pDisassocReq->Addr[4], pDisassocReq->Addr[5])); + ApCliMgtMacHeaderInit(pAd, &DisassocHdr, SUBTYPE_DISASSOC, 0, pDisassocReq->Addr, pDisassocReq->Addr, ifIndex); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + COPY_MAC_ADDR(DisassocHdr.Addr2, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CurrentAddress); +#endif /* MAC_REPEATER_SUPPORT */ + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DisassocHdr, + 2, &pDisassocReq->Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + *pCurrState = APCLI_ASSOC_IDLE; + + ApCliCtrlMsg.Status = MLME_SUCCESS; + +#ifdef MAC_REPEATER_SUPPORT + ApCliCtrlMsg.BssIdx = ifIndex; + ApCliCtrlMsg.CliIdx = CliIdx; + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DEASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + + + + return; +} + + +/* + ========================================================================== + Description: + peer sends assoc rsp back + Parameters: + Elme - MLME message containing the received frame + ========================================================================== + */ +static VOID ApCliPeerAssocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + BOOLEAN Cancelled; + USHORT CapabilityInfo, Status, Aid; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES], SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES], ExtRateLen; + UCHAR Addr2[MAC_ADDR_LEN]; + EDCA_PARM EdcaParm; + UCHAR CkipFlag; + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHtInfo; /* AP might use this additional ht info IE */ + UCHAR HtCapabilityLen; + UCHAR AddHtInfoLen; + UCHAR NewExtChannelOffset = 0xff; + USHORT ifIndex = (USHORT)(Elem->Priv); + ULONG *pCurrState = NULL; +#if defined(DOT11_VHT_AC) || defined(WH_EZ_SETUP) || defined(MAP_SUPPORT) + PAPCLI_STRUCT pApCliEntry = NULL; +#endif /* DOT11_VHT_AC */ +#ifdef APCLI_OWE_SUPPORT + PMAC_TABLE_ENTRY pEntry = NULL; +#endif +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + IE_LISTS *ie_list = NULL; + +#ifdef WH_EZ_SETUP + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("%s()\n", __FUNCTION__)); +#endif + + 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 defined(DOT11_VHT_AC) || defined(WH_EZ_SETUP) || defined(MAP_SUPPORT) + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; +#endif /* DOT11_VHT_AC */ + os_alloc_mem(pAd, (UCHAR **)&ie_list, sizeof(IE_LISTS)); + if (ie_list == NULL) { + DBGPRINT(RT_DEBUG_OFF, ("%s():mem alloc failed!\n", __FUNCTION__)); + return; + } + + NdisZeroMemory((UCHAR *)ie_list, sizeof(IE_LISTS)); + + if (ApCliPeerAssocRspSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &CapabilityInfo, &Status, &Aid, SupRate, &SupRateLen, ExtRate, &ExtRateLen, + &HtCapability, &AddHtInfo, &HtCapabilityLen,&AddHtInfoLen,&NewExtChannelOffset, &EdcaParm, &CkipFlag, ie_list)) + { + /* The frame is for me ? */ + if(MAC_ADDR_EQUAL(Addr2, pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid)) + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - receive ASSOC_RSP to me (status=%d)\n", Status)); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].ApCliAssocTimer, &Cancelled); + else +#endif /* MAC_REPEATER_SUPPORT */ + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.ApCliAssocTimer, &Cancelled); + +#ifdef WH_EZ_SETUP + if ((Status == MLME_SUCCESS) + && IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + && pApCliEntry->MlmeAux.support_easy_setup) { + Status = ez_process_assoc_response(&pApCliEntry->wdev, Addr2, Elem->Msg, Elem->MsgLen); + } else if (Status == MLME_EZ_CONNECTION_LOOP) + { + } +#endif /* WH_EZ_SETUP */ + + 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); +#ifdef DOT11_VHT_AC + RTMPZeroMemory(&pApCliEntry->MlmeAux.vht_cap, sizeof(VHT_CAP_IE)); + RTMPZeroMemory(&pApCliEntry->MlmeAux.vht_op, sizeof(VHT_OP_IE)); + pApCliEntry->MlmeAux.vht_cap_len = 0; + pApCliEntry->MlmeAux.vht_op_len = 0; + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && ie_list->vht_cap_len && ie_list->vht_op_len) + { + DBGPRINT(RT_DEBUG_TRACE, ("There is vht le at Assoc Rsp ifIndex=%d vht_cap_len=%d\n", ifIndex,ie_list->vht_cap_len)); + NdisMoveMemory(&pApCliEntry->MlmeAux.vht_cap, &(ie_list->vht_cap), ie_list->vht_cap_len); + pApCliEntry->MlmeAux.vht_cap_len = ie_list->vht_cap_len; + NdisMoveMemory(&pApCliEntry->MlmeAux.vht_op, &(ie_list->vht_op), ie_list->vht_op_len); + pApCliEntry->MlmeAux.vht_op_len = ie_list->vht_op_len; + } +#endif /* DOT11_VHT_AC */ + } + +#ifdef APCLI_OWE_SUPPORT + pEntry = &pAd->ApCfg.ApCliTab[ifIndex].pre_mac_entry; + + if (pEntry->AuthMode == Ndis802_11AuthModeOWE) { + UINT8 *pmkid = NULL; + UINT8 pmkid_count = 0; + INT idx = 0; + + pmkid = WPA_ExtractSuiteFromRSNIE(ie_list->RSN_IE, + ie_list->RSNIE_Len, + PMKID_LIST, + &pmkid_count); + + if (pmkid != NULL) { + idx = apcli_search_pmkid_cache(pAd, Addr2, ifIndex +#ifdef MAC_REPEATER_SUPPORT + , CliIdx +#endif + ); + + if ((idx == INVALID_PMKID_IDX) || + ((pEntry->pmkid) && + ((RTMPEqualMemory(pmkid, + pEntry->pmkid, + LEN_PMKID)) == 0))) { + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s: no OWE PMKID, do normal ECDH procedure\n", + __func__)); + ApCliCtrlMsg.Status = MLME_UNSPECIFY_FAIL; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_ASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), + &ApCliCtrlMsg, ifIndex); + RTMP_MLME_HANDLER(pAd); + } + } else { + pEntry->need_process_ecdh_ie = TRUE; + /*Process ECDH IE as no pmkid in assoc rsp rsnie,*/ + /*PMK id sent might have been invalid at AP,*/ + /*need to clear seconfig pmk cache*/ + idx = apcli_search_pmkid_cache(pAd, Addr2, ifIndex +#ifdef MAC_REPEATER_SUPPORT + , CliIdx +#endif + ); + if ((idx != INVALID_PMKID_IDX) && + (is_pmkid_cache_in_entry(pEntry))) { + apcli_delete_pmkid_cache(pAd, Addr2, ifIndex +#ifdef MAC_REPEATER_SUPPORT + , CliIdx +#endif + ); + pEntry->pmkid = NULL; + pEntry->pmk_cache = NULL; + } + } + if ((pEntry->need_process_ecdh_ie == TRUE) && (ie_list->ecdh_ie.length > 0)) + NdisMoveMemory(&pEntry->ecdh_ie, + &ie_list->ecdh_ie, + sizeof(EXT_ECDH_PARAMETER_IE)); + } +#endif /*CONFIG_OWE_SUPPORT*/ + + + ApCliCtrlMsg.Status = MLME_SUCCESS; +#ifdef MAC_REPEATER_SUPPORT + ApCliCtrlMsg.BssIdx = ifIndex; + ApCliCtrlMsg.CliIdx = CliIdx; + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_ASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + } + else + { + ApCliCtrlMsg.Status = Status; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_ASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + } + + *pCurrState = APCLI_ASSOC_IDLE; + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - ApCliPeerAssocRspAction() sanity check fail\n")); + } + + if (ie_list) + os_free_mem(pAd, ie_list); + + return; +} + +/* + ========================================================================== + Description: + left part of IEEE 802.11/1999 p.374 + Parameters: + Elem - MLME message containing the received frame + ========================================================================== + */ +static VOID ApCliPeerDisassocAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Reason; + USHORT ifIndex = (USHORT)(Elem->Priv); + ULONG *pCurrState = NULL; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef WH_EZ_SETUP + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("ApCliPeerDisassocAction()\n")); +#endif + + 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].MlmeAux.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); + ULONG *pCurrState = NULL; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + if ((ifIndex >= MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + && (ifIndex < 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AssocCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AssocCurrState; + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_ASSOC - InvalidStateWhenApCliDisassoc(state=%ld), reset APCLI_ASSOC state machine\n", *pCurrState)); + *pCurrState = APCLI_ASSOC_IDLE; + + ApCliCtrlMsg.Status = MLME_STATE_MACHINE_REJECT; + +#ifdef MAC_REPEATER_SUPPORT + ApCliCtrlMsg.BssIdx = ifIndex; + ApCliCtrlMsg.CliIdx = CliIdx; + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DEASSOC_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + + return; +} + +/* + ========================================================================== + Description: + procedures on IEEE 802.11/1999 p.376 + Parametrs: + ========================================================================== + */ +static VOID ApCliAssocPostProc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr2, + IN USHORT CapabilityInfo, + IN USHORT IfIndex, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN PEDCA_PARM pEdcaParm, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN ADD_HT_INFO_IE *pAddHtInfo) +{ + APCLI_STRUCT *pApCliEntry = NULL; + + if (IfIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[IfIndex]; + + pApCliEntry->MlmeAux.BssType = BSS_INFRA; + pApCliEntry->MlmeAux.CapabilityInfo = CapabilityInfo & SUPPORTED_CAPABILITY_INFO; + NdisMoveMemory(&pApCliEntry->MlmeAux.APEdcaParm, pEdcaParm, sizeof(EDCA_PARM)); + + /* filter out un-supported rates */ + pApCliEntry->MlmeAux.SupRateLen = SupRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.SupRate, SupRate, SupRateLen); + RTMPCheckRates(pAd, pApCliEntry->MlmeAux.SupRate, &(pApCliEntry->MlmeAux.SupRateLen)); + + /* filter out un-supported rates */ + pApCliEntry->MlmeAux.ExtRateLen = ExtRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.ExtRate, ExtRate, ExtRateLen); + RTMPCheckRates(pAd, pApCliEntry->MlmeAux.ExtRate, &(pApCliEntry->MlmeAux.ExtRateLen)); + + DBGPRINT(RT_DEBUG_TRACE, (HtCapabilityLen ? "%s===> 11n HT STA\n" : "%s===> legacy STA\n", __FUNCTION__)); + +#ifdef DOT11_N_SUPPORT + if (HtCapabilityLen > 0 && WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + ApCliCheckHt(pAd, IfIndex, pHtCapability, pAddHtInfo); +#endif /* DOT11_N_SUPPORT */ + +} + +#endif /* APCLI_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_auth.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_auth.c new file mode 100644 index 000000000..eaeb5765d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_auth.c @@ -0,0 +1,1132 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2006, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + apcli_auth.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ------------------------------------------- +*/ + +#ifdef APCLI_SUPPORT + +#include "rt_config.h" + +static VOID ApCliAuthTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +DECLARE_TIMER_FUNCTION(ApCliAuthTimeout); +BUILD_TIMER_FUNCTION(ApCliAuthTimeout); + +#ifdef MAC_REPEATER_SUPPORT +static VOID ApCliAuthTimeoutExt( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +DECLARE_TIMER_FUNCTION(ApCliAuthTimeoutExt); +BUILD_TIMER_FUNCTION(ApCliAuthTimeoutExt); +#endif /* MAC_REPEATER_SUPPORT */ + + + +/* + ========================================================================== + Description: + function to be executed at timer thread when auth timer expires + ========================================================================== + */ +static VOID ApCliAuthTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():AuthTimeout\n", __FUNCTION__)); + + MlmeEnqueue(pAd, APCLI_AUTH_STATE_MACHINE, APCLI_MT2_AUTH_TIMEOUT, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); + + return; +} + +#ifdef MAC_REPEATER_SUPPORT +static VOID ApCliAuthTimeoutExt( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PREPEATER_CLIENT_ENTRY pRepeaterCliEntry = (PREPEATER_CLIENT_ENTRY)FunctionContext; + PRTMP_ADAPTER pAd; + USHORT ifIndex = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("Repeater Cli AUTH - AuthTimeout\n")); + + pAd = pRepeaterCliEntry->pAd; + ifIndex = (64 + (16*pRepeaterCliEntry->MatchApCliIdx) + pRepeaterCliEntry->MatchLinkIdx); + + DBGPRINT(RT_DEBUG_ERROR, (" (%s) ifIndex = %d, CliIdx = %d !!!\n", + __FUNCTION__, pRepeaterCliEntry->MatchApCliIdx, pRepeaterCliEntry->MatchLinkIdx)); + + + MlmeEnqueue(pAd, APCLI_AUTH_STATE_MACHINE, APCLI_MT2_AUTH_TIMEOUT, 0, NULL, ifIndex); + RTMP_MLME_HANDLER(pAd); + + return; +} +#endif /* MAC_REPEATER_SUPPORT */ + +/* + ========================================================================== + Description: + ========================================================================== + */ +static VOID ApCliMlmeAuthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + BOOLEAN Cancelled; + NDIS_STATUS NState; + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Alg, Seq, Status; + ULONG Timeout; + HEADER_802_11 AuthHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef WH_EZ_SETUP + struct wifi_dev *wdev; + + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("ApCliMlmeAuthReqAction()\n")); +#endif /* WH_EZ_SETUP */ + + if ((ifIndex >= MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + && (ifIndex < 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState; + + /* Block all authentication request durning WPA block period */ + if (pAd->ApCfg.ApCliTab[ifIndex].bBlockAssoc == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - Block Auth request durning WPA block period!\n")); + *pCurrState = APCLI_AUTH_REQ_IDLE; + ApCliCtrlMsg.Status = MLME_STATE_MACHINE_REJECT; +#ifdef MAC_REPEATER_SUPPORT + ApCliCtrlMsg.BssIdx = ifIndex; + ApCliCtrlMsg.CliIdx = CliIdx; + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + } + else if(MlmeAuthReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr, &Timeout, &Alg)) + { +#ifdef MAC_REPEATER_SUPPORT + /* reset timer */ + if (CliIdx != 0xFF) + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].ApCliAuthTimer, &Cancelled); + else +#endif /* MAC_REPEATER_SUPPORT */ + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.ApCliAuthTimer, &Cancelled); + + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Alg = Alg; + + Seq = 1; + Status = MLME_SUCCESS; + +#ifdef WH_EZ_SETUP + wdev = &pAd->ApCfg.ApCliTab[ifIndex].wdev; + if (IS_EZ_SETUP_ENABLED(wdev) + && (Alg == AUTH_MODE_EZ)) { + Alg = cpu2le16(Alg); + } +#endif /* WH_EZ_SETUP */ + + /* allocate and send out AuthReq frame */ + NState = MlmeAllocateMemory(pAd, &pOutBuffer); + if(NState != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR, ("APCLI AUTH - MlmeAuthReqAction() allocate memory failed\n")); + *pCurrState = APCLI_AUTH_REQ_IDLE; + + ApCliCtrlMsg.Status = MLME_FAIL_NO_RESOURCE; +#ifdef MAC_REPEATER_SUPPORT + ApCliCtrlMsg.BssIdx = ifIndex; + ApCliCtrlMsg.CliIdx = CliIdx; + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - Send AUTH request seq#1 (Alg=%d)...\n", Alg)); + ApCliMgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr, pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, ifIndex); +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + COPY_MAC_ADDR(AuthHdr.Addr2, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CurrentAddress); +#endif /* MAC_REPEATER_SUPPORT */ + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11),&AuthHdr, + 2, &Alg, + 2, &Seq, + 2, &Status, + END_OF_ARGS); + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev) + && (pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.support_easy_setup)) { + FrameLen += ez_build_auth_request_ie(wdev, + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, pOutBuffer+FrameLen); + } +#endif /* WH_EZ_SETUP */ + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + RTMPSetTimer(&pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].ApCliAuthTimer, AUTH_TIMEOUT); + else +#endif /* MAC_REPEATER_SUPPORT */ + RTMPSetTimer(&pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.ApCliAuthTimer, AUTH_TIMEOUT); + *pCurrState = APCLI_AUTH_WAIT_SEQ2; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("APCLI AUTH - MlmeAuthReqAction() sanity check failed. BUG!!!!!\n")); + *pCurrState = APCLI_AUTH_REQ_IDLE; + } + + return; +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +static VOID ApCliPeerAuthRspAtSeq2Action(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM * Elem) +{ + BOOLEAN Cancelled; + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Seq, Status, Alg; + USHORT RemoteStatus; + UCHAR iv_hdr[LEN_WEP_IV_HDR]; +/* UCHAR ChlgText[CIPHER_TEXT_LEN]; */ + UCHAR *ChlgText = NULL; + UCHAR CyperChlgText[CIPHER_TEXT_LEN + 8 + 8]; + ULONG c_len = 0; + HEADER_802_11 AuthHdr; + NDIS_STATUS NState; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + UCHAR ChallengeIe = IE_CHALLENGE_TEXT; + UCHAR len_challengeText = CIPHER_TEXT_LEN; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; + APCLI_STRUCT *apcli_entry; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef WH_EZ_SETUP + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) + EZ_DEBUG(DBG_CAT_CLIENT, CATCLIENT_APCLI, DBG_LVL_OFF, ("ApCliPeerAuthRspAtSeq2Action\n")); +#endif + + if ((ifIndex >= MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + && (ifIndex < 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState; + + apcli_entry = &pAd->ApCfg.ApCliTab[ifIndex]; + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&ChlgText, CIPHER_TEXT_LEN); + if (ChlgText == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + if(PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, (CHAR *) ChlgText)) + { + if(MAC_ADDR_EQUAL(apcli_entry->MlmeAux.Bssid, Addr2) && Seq == 2) + { +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Repeater Cli Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status)); + RTMPCancelTimer(&apcli_entry->RepeaterCli[CliIdx].ApCliAuthTimer, &Cancelled); + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - Receive AUTH_RSP seq#2 to me (Alg=%d, Status=%d)\n", Alg, Status)); + RTMPCancelTimer(&apcli_entry->MlmeAux.ApCliAuthTimer, &Cancelled); + } + + if(Status == MLME_SUCCESS) + { +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(&apcli_entry->wdev) + && (Alg == AUTH_MODE_EZ)) { + ez_process_auth_response(pAd, + &apcli_entry->wdev, + Addr2, + pCurrState, + Elem->Msg, + Elem->MsgLen); + os_free_mem(NULL, ChlgText); + return; + } +#endif /* WH_EZ_SETUP */ + + if(apcli_entry->MlmeAux.Alg == Ndis802_11AuthModeOpen) + { + *pCurrState = APCLI_AUTH_REQ_IDLE; + + ApCliCtrlMsg.Status= MLME_SUCCESS; +#ifdef MAC_REPEATER_SUPPORT + ApCliCtrlMsg.CliIdx = CliIdx; + ApCliCtrlMsg.BssIdx = ifIndex; + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + } + else + { + PCIPHER_KEY pKey; + UINT default_key = apcli_entry->wdev.DefaultKeyId; + + pKey = &apcli_entry->SharedKey[default_key]; + + /* 2. shared key, need to be challenged */ + Seq++; + RemoteStatus = MLME_SUCCESS; + /* allocate and send out AuthRsp frame */ + NState = MlmeAllocateMemory(pAd, &pOutBuffer); + if(NState != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - ApCliPeerAuthRspAtSeq2Action allocate memory fail\n")); + *pCurrState = APCLI_AUTH_REQ_IDLE; + + ApCliCtrlMsg.Status= MLME_FAIL_NO_RESOURCE; +#ifdef MAC_REPEATER_SUPPORT + ApCliCtrlMsg.CliIdx = CliIdx; + ApCliCtrlMsg.BssIdx = ifIndex; + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + goto LabelOK; + } + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Repeater Cli Send AUTH request seq#3...\n")); + else +#endif /* MAC_REPEATER_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send AUTH request seq#3...\n")); + ApCliMgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, Addr2, apcli_entry->MlmeAux.Bssid, ifIndex); + AuthHdr.FC.Wep = 1; +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + COPY_MAC_ADDR(AuthHdr.Addr2, apcli_entry->RepeaterCli[CliIdx].CurrentAddress); +#endif /* MAC_REPEATER_SUPPORT */ + + /* Encrypt challenge text & auth information */ + /* TSC increment */ + INC_TX_TSC(pKey->TxTsc, LEN_WEP_TSC); + + /* Construct the 4-bytes WEP IV header */ + RTMPConstructWEPIVHdr(default_key, pKey->TxTsc, iv_hdr); + + Alg = cpu2le16(*(USHORT *)&Alg); + Seq = cpu2le16(*(USHORT *)&Seq); + RemoteStatus= cpu2le16(*(USHORT *)&RemoteStatus); + + /* Construct message text */ + MakeOutgoingFrame(CyperChlgText, &c_len, + 2, &Alg, + 2, &Seq, + 2, &RemoteStatus, + 1, &ChallengeIe, + 1, &len_challengeText, + len_challengeText, ChlgText, + END_OF_ARGS); + + if (RTMPSoftEncryptWEP(pAd, + iv_hdr, + pKey, + CyperChlgText, + c_len) == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - ApCliPeerAuthRspAtSeq2Action allocate memory fail\n")); + *pCurrState = APCLI_AUTH_REQ_IDLE; + + ApCliCtrlMsg.Status= MLME_FAIL_NO_RESOURCE; +#ifdef MAC_REPEATER_SUPPORT + ApCliCtrlMsg.BssIdx = ifIndex; + ApCliCtrlMsg.CliIdx = CliIdx; + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + goto LabelOK; + } + + /* Update the total length for 4-bytes ICV */ + c_len += LEN_ICV; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &AuthHdr, + LEN_WEP_IV_HDR, iv_hdr, + c_len, CyperChlgText, + END_OF_ARGS); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + RTMPSetTimer(&apcli_entry->RepeaterCli[CliIdx].ApCliAuthTimer, AUTH_TIMEOUT); + else +#endif /* MAC_REPEATER_SUPPORT */ + RTMPSetTimer(&apcli_entry->MlmeAux.ApCliAuthTimer, AUTH_TIMEOUT); + *pCurrState = APCLI_AUTH_WAIT_SEQ4; + } + } + else + { + *pCurrState = APCLI_AUTH_REQ_IDLE; + +#ifdef MAC_REPEATER_SUPPORT + ApCliCtrlMsg.CliIdx = CliIdx; + ApCliCtrlMsg.BssIdx = ifIndex; + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + ApCliCtrlMsg.Status= Status; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + } + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - PeerAuthSanity() sanity check fail\n")); + } + +LabelOK: + if (pOutBuffer != NULL) + MlmeFreeMemory(pAd, pOutBuffer); + if (ChlgText != NULL) + os_free_mem(NULL, ChlgText); + return; +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +static VOID ApCliPeerAuthRspAtSeq4Action(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + BOOLEAN Cancelled; + UCHAR Addr2[MAC_ADDR_LEN]; + USHORT Alg, Seq, Status; + CHAR ChlgText[CIPHER_TEXT_LEN]; + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + if ((ifIndex >= MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + && (ifIndex < 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState; + + if(PeerAuthSanity(pAd, Elem->Msg, Elem->MsgLen, Addr2, &Alg, &Seq, &Status, ChlgText)) + { + if(MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, Addr2) && Seq == 4) + { +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Repeater Cli Receive AUTH_RSP seq#4 to me\n")); + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].ApCliAuthTimer, &Cancelled); + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - Receive AUTH_RSP seq#4 to me\n")); + RTMPCancelTimer(&pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.ApCliAuthTimer, &Cancelled); + } + + ApCliCtrlMsg.Status = MLME_SUCCESS; + + if(Status != MLME_SUCCESS) + { + ApCliCtrlMsg.Status = Status; + } + +#ifdef MAC_REPEATER_SUPPORT + ApCliCtrlMsg.CliIdx = CliIdx; + ApCliCtrlMsg.BssIdx = ifIndex; + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + *pCurrState = APCLI_AUTH_REQ_IDLE; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + } + } else + { + DBGPRINT(RT_DEBUG_TRACE, ("APCLI - PeerAuthRspAtSeq4Action() sanity check fail\n")); + } + + return; +} + +/* + ========================================================================== + Description: + ========================================================================== +*/ +static VOID ApCliPeerDeauthAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + UCHAR Addr3[MAC_ADDR_LEN]; + USHORT Reason; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ +#ifdef APCLI_SAE_SUPPORT + PULONG pCtrlCurrState = NULL; +#endif + +#ifdef WH_EZ_SETUP + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) + EZ_DEBUG(DBG_CAT_CLIENT, CATCLIENT_APCLI, DBG_LVL_OFF, ("ApCliPeerDeauthAction\n")); +#endif + + 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; +#ifdef APCLI_SAE_SUPPORT + pCtrlCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CtrlCurrState; +#endif + + } else +#endif /* MAC_REPEATER_SUPPORT */ + { + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState; +#ifdef APCLI_SAE_SUPPORT + pCtrlCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; +#endif + } + + + 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_OWE_SUPPORT + apcli_reset_owe_parameters(pAd, ifIndex); +#endif + + +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + if ((*pCtrlCurrState == APCLI_CTRL_ASSOC) || (*pCtrlCurrState == APCLI_CTRL_CONNECTED)) { + UCHAR if_addr[6]; + INT CachedIdx; + UCHAR pmkid[80]; + UCHAR pmk[LEN_PMK]; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + NdisCopyMemory(if_addr, + &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CurrentAddress, + MAC_ADDR_LEN); + else +#endif /* MAC_REPEATER_SUPPORT */ + NdisCopyMemory(if_addr, &pAd->ApCfg.ApCliTab[ifIndex].wdev.if_addr, MAC_ADDR_LEN); + + /*Received PMK invalid status from AP delete entry from SavedPMK and delete SAE instance*/ + if ( +#ifdef APCLI_SAE_SUPPORT + (pAd->ApCfg.ApCliTab[ifIndex].wdev.AuthMode == Ndis802_11AuthModeWPA3PSK + && sae_get_pmk_cache(&pAd->SaeCfg, if_addr, + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, pmkid, pmk)) +#endif + +#ifdef APCLI_OWE_SUPPORT + || pAd->ApCfg.ApCliTab[ifIndex].wdev.AuthMode == Ndis802_11AuthModeOWE +#endif + ) { + + CachedIdx = apcli_search_pmkid_cache(pAd, + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, ifIndex +#ifdef MAC_REPEATER_SUPPORT + , CliIdx +#endif + ); + + if (CachedIdx != INVALID_PMKID_IDX) { +#ifdef APCLI_SAE_SUPPORT + SAE_INSTANCE *pSaeIns = + search_sae_instance(&pAd->SaeCfg, if_addr, + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid); + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_OFF, + ("%s:Reconnection falied with pmkid,delete cache entry and sae instance\n", + __func__)); + if (pSaeIns != NULL) + delete_sae_instance(pSaeIns); +#endif + apcli_delete_pmkid_cache(pAd, + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, ifIndex +#ifdef MAC_REPEATER_SUPPORT + , CliIdx +#endif + ); + } + } + + } +#endif + +#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(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + if ((ifIndex >= MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + && (ifIndex < 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState; + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - AuthTimeoutAction\n")); + + *pCurrState = APCLI_AUTH_REQ_IDLE; + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_REQ_TIMEOUT, 0, NULL, ifIndex); + + return; +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +static VOID ApCliInvalidStateWhenAuth(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + if ((ifIndex >= MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + && (ifIndex < 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState; + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - InvalidStateWhenAuth (state=%ld), reset AUTH state machine\n", *pCurrState)); + + *pCurrState= APCLI_AUTH_REQ_IDLE; + +#ifdef MAC_REPEATER_SUPPORT + ApCliCtrlMsg.BssIdx = ifIndex; + ApCliCtrlMsg.CliIdx = CliIdx; + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + ApCliCtrlMsg.Status = MLME_STATE_MACHINE_REJECT; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + + return; +} + +/* + ========================================================================== + Description: + ========================================================================== + */ +#ifndef WH_EZ_SETUP + static +#endif +VOID ApCliMlmeDeauthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PMLME_DEAUTH_REQ_STRUCT pDeauthReq; + HEADER_802_11 DeauthHdr; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI AUTH - ApCliMlmeAuthReqAction (state=%ld), reset AUTH state machine\n", + pAd->Mlme.ApCliAuthMachine.CurrState)); + + if ((ifIndex >= MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + && (ifIndex < 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState; + + pDeauthReq = (PMLME_DEAUTH_REQ_STRUCT)(Elem->Msg); + + *pCurrState= APCLI_AUTH_REQ_IDLE; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("AUTH - Send DE-AUTH request (Reason=%d)...\n", pDeauthReq->Reason)); + + ApCliMgtMacHeaderInit(pAd, &DeauthHdr, SUBTYPE_DEAUTH, 0, pDeauthReq->Addr, pDeauthReq->Addr, ifIndex); +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + COPY_MAC_ADDR(DeauthHdr.Addr2, pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CurrentAddress); +#endif /* MAC_REPEATER_SUPPORT */ + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11),&DeauthHdr, + 2, &pDeauthReq->Reason, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +#ifdef APCLI_SAE_SUPPORT + +/* ==========================================================================*/ +/* Description: */ +/* */ +/* IRQL = DISPATCH_LEVEL */ +/* */ +/* ==========================================================================*/ + +VOID ApCliMlmeSaeAuthReqAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + USHORT ifIndex = (USHORT)(Elem->Priv); +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; +#endif /* MAC_REPEATER_SUPPORT */ + /* SAE_MLME_AUTH_REQ_STRUCT *AuthReq = (SAE_MLME_AUTH_REQ_STRUCT *)Elem->Msg; */ + MLME_AUTH_REQ_STRUCT *AuthReq = (MLME_AUTH_REQ_STRUCT *)Elem->Msg; + PULONG pCurrState = NULL; + UCHAR if_addr[MAC_ADDR_LEN]; + APCLI_STRUCT *apcli_entry = NULL; + UCHAR *pSae_cfg_group = NULL; + SAE_CFG *pSaeCfg = NULL; + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + + + pSaeCfg = &pAd->SaeCfg; + + if ((ifIndex >= MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + && (ifIndex < REPT_MLME_START_IDX) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; + + NdisZeroMemory(if_addr, MAC_ADDR_LEN); +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= REPT_MLME_START_IDX) { + CliIdx = ((ifIndex - REPT_MLME_START_IDX) % 16); + ifIndex = ((ifIndex - REPT_MLME_START_IDX) / 16); + pReptEntry = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx]; + pSae_cfg_group = &pReptEntry->sae_cfg_group; + ifIndex = pReptEntry->wdev->func_idx; + apcli_entry = &pAd->ApCfg.ApCliTab[ifIndex]; + pCurrState = &pReptEntry->AuthCurrState; + COPY_MAC_ADDR(if_addr, pReptEntry->CurrentAddress); + } else +#endif /* MAC_REPEATER_SUPPORT */ + { + apcli_entry = &pAd->ApCfg.ApCliTab[ifIndex]; + pSae_cfg_group = &apcli_entry->sae_cfg_group; + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState; + COPY_MAC_ADDR(if_addr, pAd->ApCfg.ApCliTab[ifIndex].wdev.if_addr); + } + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_OFF, ("==>%s()\n", __func__)); + + if (sae_auth_init(pAd, &pAd->SaeCfg, if_addr, AuthReq->Addr, + apcli_entry->MlmeAux.Bssid, apcli_entry->PSK, *pSae_cfg_group)) + *pCurrState = APCLI_AUTH_WAIT_SAE; + else { + *pCurrState = APCLI_AUTH_REQ_IDLE; + ApCliCtrlMsg.Status = MLME_UNSPECIFY_FAIL; +#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); + RTMP_MLME_HANDLER(pAd); + + } +} + + + +/*==========================================================================*/ +/* Description: */ +/* */ +/* IRQL = DISPATCH_LEVEL */ +/* */ +/*==========================================================================*/ + +VOID ApCliMlmeSaeAuthRspAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + FRAME_802_11 *Fr = (FRAME_802_11 *)Elem->Msg; + USHORT seq; + USHORT status; + UCHAR *pmk; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pAuthCurrState = NULL; + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + APCLI_STRUCT *apcli_entry; +#ifdef MAC_REPEATER_SUPPORT + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; +#endif +#if defined(MAC_REPEATER_SUPPORT) + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + + if ((ifIndex >= MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + && (ifIndex < REPT_MLME_START_IDX) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= REPT_MLME_START_IDX) { + CliIdx = ((ifIndex - REPT_MLME_START_IDX) % 16); + ifIndex = ((ifIndex - REPT_MLME_START_IDX) / 16); + pReptEntry = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx]; + ifIndex = pReptEntry->wdev->func_idx; + pAuthCurrState = &pReptEntry->AuthCurrState; + } else +#endif /* MAC_REPEATER_SUPPORT */ + { + pAuthCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState; + } + + apcli_entry = &pAd->ApCfg.ApCliTab[ifIndex]; + + NdisMoveMemory(&seq, &Fr->Octet[2], 2); + NdisMoveMemory(&status, &Fr->Octet[4], 2); + + + if (sae_handle_auth(pAd, &pAd->SaeCfg, Elem->Msg, Elem->MsgLen, + apcli_entry->PSK, + seq, status, &pmk) == FALSE){ + + *pAuthCurrState = APCLI_AUTH_REQ_IDLE; + /*If SAE instance has been deleted*/ + ApCliCtrlMsg.Status = MLME_UNSPECIFY_FAIL; +#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); + RTMP_MLME_HANDLER(pAd); + + } else if (pmk != NULL) { + USHORT Status; + MAC_TABLE_ENTRY *pEntry = NULL; + + pEntry = &apcli_entry->pre_mac_entry; + + DebugLevel = DBG_LVL_TRACE; + hex_dump("pmk:", (char *)pmk, LEN_PMK); + DebugLevel = DBG_LVL_ERROR; + + if (pEntry) { + NdisMoveMemory(pEntry->PMK, pmk, LEN_PMK); + Status = MLME_SUCCESS; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_OFF, + ("%s(): Security AKM = 0x%x, PairwiseCipher = 0x%x, GroupCipher = 0x%x\n", + __func__, pEntry->AuthMode, pEntry->WepStatus, pEntry->GroupKeyWepStatus)); + } else + Status = MLME_UNSPECIFY_FAIL; + *pAuthCurrState = APCLI_AUTH_REQ_IDLE; + ApCliCtrlMsg.Status = Status; +#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); + RTMP_MLME_HANDLER(pAd); + } +} +#endif /* APCLI_SAE_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 RTMP_ADAPTER *pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + UCHAR i; +#ifdef MAC_REPEATER_SUPPORT + UCHAR j; +#endif /* MAC_REPEATER_SUPPORT */ + + StateMachineInit(Sm, (STATE_MACHINE_FUNC*)Trans, + APCLI_MAX_AUTH_STATE, APCLI_MAX_AUTH_MSG, + (STATE_MACHINE_FUNC)Drop, APCLI_AUTH_REQ_IDLE, + APCLI_AUTH_MACHINE_BASE); + + /* the first column */ + StateMachineSetAction(Sm, APCLI_AUTH_REQ_IDLE, APCLI_MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)ApCliMlmeAuthReqAction); + StateMachineSetAction(Sm, APCLI_AUTH_REQ_IDLE, APCLI_MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)ApCliPeerDeauthAction); + StateMachineSetAction(Sm, APCLI_AUTH_REQ_IDLE, APCLI_MT2_MLME_DEAUTH_REQ, (STATE_MACHINE_FUNC)ApCliMlmeDeauthReqAction); + + /* the second column */ + StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ2, APCLI_MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)ApCliInvalidStateWhenAuth); + StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ2, APCLI_MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)ApCliPeerAuthRspAtSeq2Action); + StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ2, APCLI_MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)ApCliPeerDeauthAction); + StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ2, APCLI_MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)ApCliAuthTimeoutAction); + StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ2, APCLI_MT2_MLME_DEAUTH_REQ, (STATE_MACHINE_FUNC)ApCliMlmeDeauthReqAction); + + /* the third column */ + StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ4, APCLI_MT2_MLME_AUTH_REQ, (STATE_MACHINE_FUNC)ApCliInvalidStateWhenAuth); + StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ4, APCLI_MT2_PEER_AUTH_EVEN, (STATE_MACHINE_FUNC)ApCliPeerAuthRspAtSeq4Action); + StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ4, APCLI_MT2_PEER_DEAUTH, (STATE_MACHINE_FUNC)ApCliPeerDeauthAction); + StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ4, APCLI_MT2_AUTH_TIMEOUT, (STATE_MACHINE_FUNC)ApCliAuthTimeoutAction); + StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SEQ4, APCLI_MT2_MLME_DEAUTH_REQ, (STATE_MACHINE_FUNC)ApCliMlmeDeauthReqAction); + +#ifdef APCLI_SAE_SUPPORT + StateMachineSetAction(Sm, APCLI_AUTH_REQ_IDLE, APCLI_MT2_MLME_SAE_AUTH_REQ, + (STATE_MACHINE_FUNC) ApCliMlmeSaeAuthReqAction); + StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SAE, APCLI_MT2_MLME_SAE_AUTH_COMMIT, + (STATE_MACHINE_FUNC) ApCliMlmeSaeAuthRspAction); + StateMachineSetAction(Sm, APCLI_AUTH_WAIT_SAE, APCLI_MT2_MLME_SAE_AUTH_CONFIRM, + (STATE_MACHINE_FUNC) ApCliMlmeSaeAuthRspAction); +#endif /*APCLI_SAE_SUPPORT */ + + + for (i=0; i < MAX_APCLI_NUM; i++) + { + pAd->ApCfg.ApCliTab[i].AuthCurrState = APCLI_AUTH_REQ_IDLE; + + /* timer init */ + RTMPInitTimer(pAd, &pAd->ApCfg.ApCliTab[i].MlmeAux.ApCliAuthTimer, GET_TIMER_FUNCTION(ApCliAuthTimeout), pAd, FALSE); + +#ifdef MAC_REPEATER_SUPPORT + for (j = 0; j < MAX_EXT_MAC_ADDR_SIZE; j++) + { + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].pAd = pAd; + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].MatchApCliIdx = i; + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].MatchLinkIdx = j; + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].AuthCurrState = APCLI_AUTH_REQ_IDLE; + + /* timer init */ + RTMPInitTimer(pAd, &pAd->ApCfg.ApCliTab[i].RepeaterCli[j].ApCliAuthTimer, + GET_TIMER_FUNCTION(ApCliAuthTimeoutExt), &pAd->ApCfg.ApCliTab[i].RepeaterCli[j], FALSE); + + } +#endif /* MAC_REPEATER_SUPPORT */ + + } + + return; +} + +#endif /* APCLI_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_ctrl.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_ctrl.c new file mode 100644 index 000000000..6e980ea96 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_ctrl.c @@ -0,0 +1,2105 @@ +/* + *************************************************************************** + * 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 WH_EZ_SETUP +#include "easy_setup/ez_mod_hooks.h" +#endif +#ifdef WH_EZ_SETUP +#ifdef DUAL_CHIP +extern NDIS_SPIN_LOCK ez_conn_perm_lock; +#endif +#endif + +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); + +#ifndef WH_EZ_SETUP +static +#endif +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; +#ifdef MAC_REPEATER_SUPPORT + UCHAR j; +#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); +#ifdef MAC_REPEATER_SUPPORT + StateMachineSetAction(Sm, APCLI_CTRL_DISCONNECTED, APCLI_CTRL_DEL_MACREPENTRY, + (STATE_MACHINE_FUNC)ApCliCtrlDisconnectReqAction); +#endif /*MAC_REPEATER_SUPPORT*/ + /* 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); +#ifdef MAC_REPEATER_SUPPORT + StateMachineSetAction(Sm, APCLI_CTRL_PROBE, APCLI_CTRL_DEL_MACREPENTRY, + (STATE_MACHINE_FUNC)ApCliCtrlDisconnectReqAction); +#endif /*MAC_REPEATER_SUPPORT*/ +#ifdef WH_EZ_SETUP + StateMachineSetAction(Sm, APCLI_CTRL_PROBE, APCLI_CTRL_JOIN_FAIL, (STATE_MACHINE_FUNC)ez_ApCliCtrlJoinFailAction); +#endif + + /* 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); +#ifdef MAC_REPEATER_SUPPORT + StateMachineSetAction(Sm, APCLI_CTRL_AUTH, APCLI_CTRL_DEL_MACREPENTRY, + (STATE_MACHINE_FUNC)ApCliCtrlDisconnectReqAction); +#endif /*MAC_REPEATER_SUPPORT*/ + StateMachineSetAction(Sm, APCLI_CTRL_AUTH, APCLI_CTRL_PEER_DISCONNECT_REQ, (STATE_MACHINE_FUNC)ApCliCtrlPeerDeAssocReqAction); +#ifdef WH_EZ_SETUP + StateMachineSetAction(Sm, APCLI_CTRL_AUTH, APCLI_CTRL_JOIN_FAIL, (STATE_MACHINE_FUNC)ez_ApCliCtrlJoinFailAction); +#endif + + /* 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); +#ifdef MAC_REPEATER_SUPPORT + StateMachineSetAction(Sm, APCLI_CTRL_AUTH_2, APCLI_CTRL_DEL_MACREPENTRY, + (STATE_MACHINE_FUNC)ApCliCtrlDisconnectReqAction); +#endif /* MAC_REPEATER_SUPPORT */ + 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); +#ifdef MAC_REPEATER_SUPPORT + StateMachineSetAction(Sm, APCLI_CTRL_ASSOC, APCLI_CTRL_DEL_MACREPENTRY, + (STATE_MACHINE_FUNC)ApCliCtrlDeAssocAction); +#endif /* MAC_REPEATER_SUPPORT */ + StateMachineSetAction(Sm, APCLI_CTRL_ASSOC, APCLI_CTRL_PEER_DISCONNECT_REQ, (STATE_MACHINE_FUNC)ApCliCtrlPeerDeAssocReqAction); +#ifdef WH_EZ_SETUP + StateMachineSetAction(Sm, APCLI_CTRL_ASSOC, APCLI_CTRL_JOIN_FAIL, (STATE_MACHINE_FUNC)ez_ApCliCtrlJoinFailAction); +#endif + + /* 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); +#ifdef MAC_REPEATER_SUPPORT + StateMachineSetAction(Sm, APCLI_CTRL_CONNECTED, APCLI_CTRL_DEL_MACREPENTRY, + (STATE_MACHINE_FUNC)ApCliCtrlDeAuthAction); +#endif /* MAC_REPEATER_SUPPORT */ + 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); +#ifdef WH_EZ_SETUP + StateMachineSetAction(Sm, APCLI_CTRL_CONNECTED, APCLI_CTRL_JOIN_FAIL, (STATE_MACHINE_FUNC)ez_ApCliCtrlJoinFailAction); +#endif + + for (i = 0; i < MAX_APCLI_NUM; i++) + { + pAd->ApCfg.ApCliTab[i].CtrlCurrState = APCLI_CTRL_DISCONNECTED; + +#ifdef MAC_REPEATER_SUPPORT + for (j = 0; j < MAX_EXT_MAC_ADDR_SIZE; j++) + { + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].pAd = pAd; + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].MatchApCliIdx = i; + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].MatchLinkIdx = j; + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].AuthCurrState = APCLI_CTRL_DISCONNECTED; + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].CliConnectState = 0; + } +#endif /* MAC_REPEATER_SUPPORT */ + } + + 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 */ + +struct wifi_dev *wdev; +#ifdef WH_EZ_SETUP +#ifndef NEW_CONNECTION_ALGO + UCHAR ez_connection; +#endif +#endif /* WH_EZ_SETUP */ + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Start Probe Req.\n", __FUNCTION__)); + if (ifIndex >= MAX_APCLI_NUM) + return; + + if (ApScanRunning(pAd) == TRUE) + return; + + wdev = &pAd->ApCfg.ApCliTab[ifIndex].wdev; + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev)) { +#ifdef EZ_REGROUP_SUPPORT + if(wdev->ez_driver_params.regrp_mode == REGRP_MODE_BLOCKED){ + EZ_DEBUG(DBG_CAT_CLIENT, CATCLIENT_APCLI, DBG_LVL_OFF,("ApCliCtrlJoinReqAction: Join block by Regrp wdev_idx=%d\n", wdev->wdev_idx)); + return; + } +#endif + if (ez_update_connection_permission(wdev->sys_handle, wdev, EZ_DISALLOW_ALL_ALLOW_ME)) { + } else { + return; + } + } +#endif + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + NdisZeroMemory(&JoinReq, sizeof(APCLI_MLME_JOIN_REQ_STRUCT)); + +#ifdef WH_EZ_SETUP + // Ensure start with empty table & complete all candidate attempt before operation is terminated + if(IS_EZ_SETUP_ENABLED(wdev)) + BssTableInit(&pApCliEntry->MlmeAux.SsidBssTab); +#endif + +#ifdef APCLI_OWE_SUPPORT + if (pApCliEntry->wdev.AuthMode == Ndis802_11AuthModeOWE) + BssTableInit(&pApCliEntry->MlmeAux.owe_bss_tab); +#endif + + 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); +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev)) { + COPY_MAC_ADDR(pApCliEntry->CfgApCliBssid, pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscBssid); + COPY_MAC_ADDR(JoinReq.Bssid, pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscBssid); + } +#endif + + if (pWpsCtrl->WscMode == 1) /* PIN */ + { +#ifdef AP_SCAN_SUPPORT + if ((pWpsCtrl->WscApCliScanMode == TRIGGER_PARTIAL_SCAN) && + pAd->ScanCtrl.PartialScan.bScanning && + pAd->ScanCtrl.PartialScan.LastScanChannel != 0) + return; +#endif /* AP_SCAN_SUPPORT */ + + bss_idx = BssSsidTableSearchBySSID(&pAd->ScanTab, (PUCHAR)(JoinReq.Ssid), JoinReq.SsidLen); + if (bss_idx == BSS_NOT_FOUND) + { +#ifdef AP_SCAN_SUPPORT + if (pWpsCtrl->WscApCliScanMode == TRIGGER_PARTIAL_SCAN) { + if (!pAd->ScanCtrl.PartialScan.bScanning && + (pAd->ScanCtrl.PartialScan.LastScanChannel == 0)) { + pAd->ScanCtrl.PartialScan.pwdev = wdev; + pAd->ScanCtrl.PartialScan.bScanning = TRUE; + } + } +#endif /* AP_SCAN_SUPPORT */ + + ApSiteSurvey(pAd, NULL, SCAN_WSC_ACTIVE, FALSE, wdev); + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev) && ez_update_connection_permission(pAd, wdev, EZ_ALLOW_ALL)) + { + return; + } else { + if (IS_EZ_SETUP_ENABLED(wdev)) + ASSERT(FALSE); + } +#endif + 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))) + { + RTMP_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); +#ifdef WH_EZ_SETUP + if(IS_EZ_SETUP_ENABLED(wdev)) + { + wdev->ez_driver_params.do_not_restart_interfaces = TRUE; + rtmp_set_channel(pAd, wdev, pAd->ScanTab.BssEntry[bss_idx].Channel); + } else +#endif + { + Set_Channel_Proc(pAd, ChStr); + } +#ifdef WH_EZ_SETUP + if(IS_EZ_SETUP_ENABLED(wdev)) + { + wdev->ez_driver_params.do_not_restart_interfaces = FALSE; + } +#endif + + /* + 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; +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev) && ez_update_connection_permission(pAd, wdev, EZ_ALLOW_ALL)) + { + return; + } else { + if (IS_EZ_SETUP_ENABLED(wdev)){ + ASSERT(FALSE); + } + } +#endif + return; + } + } + } + } + else +#endif /* WSC_AP_SUPPORT */ + { +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev) && !wdev->ez_driver_params.ez_wps_reconnect) { + pApCliEntry->MlmeAux.attempted_candidate_index = EZ_INDEX_NOT_FOUND; +#ifdef NEW_CONNECTION_ALGO + //ez_connection = TRUE; + + if (ez_is_connection_allowed(wdev) == TRUE) { + if (ez_apcli_search_best_ap(pAd,pApCliEntry,ifIndex) == FALSE) + { + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("(%s) No provider found.\n", __FUNCTION__)); + if (!ez_update_connection_permission(pAd, wdev, EZ_ALLOW_ALL)) + { + ASSERT(FALSE); + } + return; + } + } +#else + ez_connection = FALSE; + if (IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev) && + pApCliEntry->wdev.ez_driver_params.keep_finding_provider) { + ez_connection = TRUE; + if (MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ZERO_MAC_ADDR) && + (ez_search_provider(pAd, pApCliEntry, ifIndex) == FALSE)) { + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("(%s) No provider found.\n", __FUNCTION__)); + return; + } + } +#endif + if (!MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ZERO_MAC_ADDR)) + { + COPY_MAC_ADDR(JoinReq.Bssid, pApCliEntry->CfgApCliBssid); + } + } + if (IS_EZ_SETUP_ENABLED(wdev) && wdev->ez_driver_params.ez_wps_reconnect) { + COPY_MAC_ADDR(pApCliEntry->CfgApCliBssid, wdev->ez_driver_params.ez_wps_bssid); + COPY_MAC_ADDR(JoinReq.Bssid, wdev->ez_driver_params.ez_wps_bssid); + } + +#endif /* WH_EZ_SETUP */ + +#ifdef APCLI_OWE_SUPPORT + /*owe_trans_ssid present then update join request with OWE ssid, bssid parameters */ + if (pApCliEntry->owe_trans_ssid_len > 0) { + + NdisMoveMemory(&(JoinReq.Ssid), pApCliEntry->owe_trans_ssid, pApCliEntry->owe_trans_ssid_len); + COPY_MAC_ADDR(JoinReq.Bssid, pApCliEntry->owe_trans_bssid); + } else +#endif + + if (pApCliEntry->CfgSsidLen != 0) + { + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev) && !wdev->ez_driver_params.ez_wps_reconnect) + { +#ifndef NEW_CONNECTION_ALGO + // COPY_MAC_ADDR(JoinReq.Bssid, pApCliEntry->CfgApCliBssid); + if (ez_connection == FALSE) { + if (ez_avoid_looping_connection(pAd, pApCliEntry, ifIndex) == FALSE) + return; + else + COPY_MAC_ADDR(JoinReq.Bssid, pApCliEntry->CfgApCliBssid); + } +#endif +#ifdef NEW_CONNECTION_ALGO + COPY_MAC_ADDR(JoinReq.Bssid, pApCliEntry->CfgApCliBssid); +#endif + } +#endif/* WH_EZ_SETUP */ + + JoinReq.SsidLen = pApCliEntry->CfgSsidLen; +#ifdef WH_EZ_SETUP // Fix made to pass SSID properly + if( IS_EZ_SETUP_ENABLED(wdev) ){ + NdisMoveMemory((JoinReq.Ssid), pApCliEntry->CfgSsid, JoinReq.SsidLen); + } + else +#endif + + 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, PRINT_MAC(JoinReq.Bssid))); + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev)) + { + if(IS_SINGLE_CHIP_DBDC(pAd)) + { + if (!(ez_update_connection_permission(pAd, wdev, EZ_DISALLOW_ALL_ALLOW_ME))){ + ASSERT(FALSE); + return; + } + } +#ifdef DUAl_CHIP + else + { + if (!(ez_update_connection_permission(pAd, wdev, EZ_DISALLOW_ALL_ALLOW_ME))) + return; + } +#endif + } +#endif + + *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; +#ifdef WH_EZ_SETUP + BOOLEAN attempt_same_peer = TRUE; +#endif /* WH_EZ_SETUP */ + +#ifdef WH_EZ_SETUP + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + if(IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev)) + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("(%s) Probe Req Timeout.\n", __FUNCTION__)); +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Probe Req Timeout.\n", __FUNCTION__)); + + if (ifIndex >= MAX_APCLI_NUM) + return; +#ifdef WH_EZ_SETUP + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + if(IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev)){ + EZ_DEBUG(DBG_CAT_CLIENT, CATCLIENT_APCLI, DBG_LVL_ERROR, ("(%s) Probe Req Timeout.\n", __FUNCTION__)); +#ifdef EZ_REGROUP_SUPPORT + if(pApCliEntry->wdev.ez_driver_params.regrp_mode == REGRP_MODE_BLOCKED){ + EZ_DEBUG(DBG_CAT_CLIENT, CATCLIENT_APCLI, DBG_LVL_ERROR, ("(%s) Conn blocked for regroup wdev_idx:%d.\n", + __FUNCTION__, pApCliEntry->wdev.wdev_idx)); + *pCurrState = APCLI_CTRL_DISCONNECTED; + goto Fail; + } +#endif + } +#endif + + if (ApScanRunning(pAd) == TRUE) + { + *pCurrState = APCLI_CTRL_DISCONNECTED; +#ifdef WH_EZ_SETUP + if(IS_EZ_SETUP_ENABLED(&pAd->ApCfg.ApCliTab[ifIndex].wdev)){ + goto Fail; + } + else +#endif + 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)); +#ifdef WH_EZ_SETUP + if((IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev)) && ( pApCliEntry->ProbeReqCnt > 2 )) + attempt_same_peer = ez_probe_count_handle(pApCliEntry); + else +#endif + + if (pApCliEntry->ProbeReqCnt > 7) + { + /* + if exceed the APCLI_MAX_PROBE_RETRY_NUM (7), + switch to try next candidate AP. + */ + *pCurrState = APCLI_CTRL_DISCONNECTED; + NdisZeroMemory(pApCliEntry->MlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pApCliEntry->MlmeAux.Ssid, MAX_LEN_OF_SSID); + NdisZeroMemory(JoinReq.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pApCliEntry->CfgApCliBssid, MAC_ADDR_LEN); + pApCliEntry->ProbeReqCnt = 0; +#ifdef APCLI_OWE_SUPPORT + apcli_reset_owe_parameters(pAd, ifIndex); +#endif + + + if (pAd->ApCfg.ApCliAutoConnectRunning == TRUE) + ApCliSwitchCandidateAP(pAd); + return; + } +#else + +#ifdef WH_EZ_SETUP + if(IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev)) + attempt_same_peer = FALSE; +#endif + +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + + /* stay in same state. */ + *pCurrState = APCLI_CTRL_PROBE; + + /* retry Probe Req. */ +#ifdef WH_EZ_SETUP + if(!IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev)) +#endif + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Retry Probe Req.\n", __FUNCTION__)); + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + NdisZeroMemory(&JoinReq, sizeof(APCLI_MLME_JOIN_REQ_STRUCT)); + +#ifdef WH_EZ_SETUP + if (!IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev)) +#endif + 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 */ + { +#ifdef WH_EZ_SETUP + if((IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev)) && (!attempt_same_peer) && !pApCliEntry->wdev.ez_driver_params.ez_wps_reconnect){ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,(" %s(apcli%d) Band = %d-->\n", __FUNCTION__, pApCliEntry->wdev.func_idx, pApCliEntry->wdev.channel > 14)); + + if (ez_join_timeout_handle(pAd, ifIndex)== FALSE) + goto Fail; + } + + if (IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev) && pApCliEntry->wdev.ez_driver_params.ez_wps_reconnect) { + COPY_MAC_ADDR(JoinReq.Bssid, pApCliEntry->wdev.ez_driver_params.ez_wps_bssid); + } +#endif + +#ifdef APCLI_OWE_SUPPORT +/*Configure OWE ssid and bssid Join request parameters */ + if (pApCliEntry->wdev.AuthMode == Ndis802_11AuthModeOWE && (pApCliEntry->owe_trans_ssid_len != 0)) { + JoinReq.SsidLen = pApCliEntry->owe_trans_ssid_len; + NdisMoveMemory(&(JoinReq.Ssid), pApCliEntry->owe_trans_ssid, JoinReq.SsidLen); + COPY_MAC_ADDR(JoinReq.Bssid, pApCliEntry->owe_trans_bssid); + } else +#endif + if (pApCliEntry->CfgSsidLen != 0) + { + JoinReq.SsidLen = pApCliEntry->CfgSsidLen; + NdisMoveMemory(&(JoinReq.Ssid), pApCliEntry->CfgSsid, JoinReq.SsidLen); + } + } +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev)) + { + if (!MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ZERO_MAC_ADDR)) + { + COPY_MAC_ADDR(JoinReq.Bssid, pApCliEntry->CfgApCliBssid); + } + + if(IS_SINGLE_CHIP_DBDC(pAd)) + { + if (!(ez_update_connection_permission(pAd, &pApCliEntry->wdev, EZ_DISALLOW_ALL_ALLOW_ME))){ + ASSERT(FALSE); + *pCurrState = APCLI_CTRL_DISCONNECTED; + goto Fail; + } + } + } +#endif + + 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; + +#ifdef WH_EZ_SETUP +Fail: + + if (IS_EZ_SETUP_ENABLED((&pAd->ApCfg.ApCliTab[ifIndex].wdev))){ + + ez_restore_channel_config(&pAd->ApCfg.MBSSID[ifIndex].wdev); + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].CfgSsid,MAX_LEN_OF_SSID); + pAd->ApCfg.ApCliTab[ifIndex].CfgSsidLen = 0; + pAd->ApCfg.ApCliTab[ifIndex].CfgSsidLen = pAd->ApCfg.MBSSID[ifIndex].SsidLen; + NdisCopyMemory(pAd->ApCfg.ApCliTab[ifIndex].CfgSsid,pAd->ApCfg.MBSSID[ifIndex].Ssid,pAd->ApCfg.MBSSID[ifIndex].SsidLen); + //Clear scan entry as Join timeout may happen if bss entry is stale. + BssTableInit(&pAd->ScanTab); + *pCurrState = APCLI_CTRL_DISCONNECTED; + if (!ez_update_connection_permission(pAd,&pAd->ApCfg.ApCliTab[ifIndex].wdev,EZ_ALLOW_ALL)) + { + ASSERT(FALSE); + } + + } +#endif + +} + +/* + ========================================================================== + Description: + APCLI MLME Probe Rsp state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlProbeRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + APCLI_CTRL_MSG_STRUCT *Info = (APCLI_CTRL_MSG_STRUCT *)(Elem->Msg); + USHORT Status = Info->Status; + PAPCLI_STRUCT pApCliEntry; + MLME_AUTH_REQ_STRUCT AuthReq; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; + struct wifi_dev *wdev; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + if ((ifIndex >= MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + && (ifIndex < 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + } + + if (Info->CliIdx != 0xFF) + CliIdx = Info->CliIdx; +#endif /* MAC_REPEATER_SUPPORT */ + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + wdev = &pApCliEntry->wdev; + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev) + && pApCliEntry->MlmeAux.support_easy_setup) { +#ifdef NEW_CONNECTION_ALGO + if (ez_is_connection_allowed(wdev) == FALSE) + Status = MLME_ASSOC_REJ_TEMPORARILY; +#endif + } +#endif /* WH_EZ_SETUP */ + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pCurrState = &pApCliEntry->RepeaterCli[CliIdx].CtrlCurrState; + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pApCliEntry->CtrlCurrState; + + if (Status == MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s():ProbeResp success. SSID=%s, Bssid=%02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, pApCliEntry->Ssid, PRINT_MAC(pApCliEntry->MlmeAux.Bssid))); + + *pCurrState = APCLI_CTRL_AUTH; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pApCliEntry->RepeaterCli[CliIdx].AuthReqCnt = 0; + else +#endif /* MAC_REPEATER_SUPPORT */ + pApCliEntry->AuthReqCnt = 0; + + COPY_MAC_ADDR(AuthReq.Addr, pApCliEntry->MlmeAux.Bssid); + + /* start Authentication Req. */ + /* If AuthMode is Auto, try shared key first */ +#ifdef APCLI_SAE_SUPPORT + if (pApCliEntry->pre_mac_entry.AuthMode == Ndis802_11AuthModeWPA3PSK) { + UCHAR if_addr[MAC_ADDR_LEN]; + UCHAR pmkid[80]; + UCHAR pmk[LEN_PMK]; + UCHAR has_pmkid = FALSE; + + NdisZeroMemory(if_addr, MAC_ADDR_LEN); +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + NdisCopyMemory(if_addr, &pApCliEntry->RepeaterCli[CliIdx].CurrentAddress, MAC_ADDR_LEN); + else +#endif /* MAC_REPEATER_SUPPORT */ + NdisCopyMemory(if_addr, &pApCliEntry->wdev.if_addr, MAC_ADDR_LEN); + + if (sae_get_pmk_cache(&pAd->SaeCfg, if_addr, pApCliEntry->MlmeAux.Bssid, pmkid, pmk)) { + apcli_add_pmkid_cache(pAd, pApCliEntry->MlmeAux.Bssid, + pmkid, pmk, LEN_PMK, ifIndex +#ifdef MAC_REPEATER_SUPPORT + , CliIdx +#endif + ); + has_pmkid = TRUE; + } + if (has_pmkid == TRUE) { + COPY_MAC_ADDR(AuthReq.Addr, pApCliEntry->MlmeAux.Bssid); + AuthReq.Alg = AUTH_MODE_OPEN; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_OFF, + ("(%s) - use pmkid\n", __func__)); + } else { + COPY_MAC_ADDR(AuthReq.Addr, pApCliEntry->MlmeAux.Bssid); + AuthReq.Alg = AUTH_MODE_SAE; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_OFF, + ("(%s) - use SAE\n", __func__)); + } + } else + +#endif/* APCLI_SAE_SUPPORT */ + + if ((wdev->AuthMode == Ndis802_11AuthModeShared) || + (wdev->AuthMode == Ndis802_11AuthModeAutoSwitch)) + AuthReq.Alg = Ndis802_11AuthModeShared; + else + AuthReq.Alg = Ndis802_11AuthModeOpen; + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + && pApCliEntry->MlmeAux.support_easy_setup) { + AuthReq.Alg = AUTH_MODE_EZ; + } +#endif /* WH_EZ_SETUP */ + + 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 */ +#ifdef APCLI_SAE_SUPPORT + if (AuthReq.Alg == AUTH_MODE_SAE) + MlmeEnqueue(pAd, APCLI_AUTH_STATE_MACHINE, APCLI_MT2_MLME_SAE_AUTH_REQ, + sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq, ifIndex); + else +#endif + + 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 */ + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev)){ + *pCurrState = APCLI_CTRL_PROBE; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_JOIN_FAIL,0, NULL, ifIndex); + RTMP_MLME_HANDLER(pAd); + } +#endif /* WH_EZ_SETUP */ + + } + + 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; +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + PULONG pAssocCurrState = NULL; + USHORT Timeout = ASSOC_TIMEOUT; +#endif +#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 WH_EZ_SETUP + if(IS_EZ_SETUP_ENABLED((&pApCliEntry->wdev)) + && pApCliEntry->MlmeAux.support_easy_setup){ +#ifdef NEW_CONNECTION_ALGO + if (ez_is_connection_allowed(&pApCliEntry->wdev) == FALSE) + Status = MLME_ASSOC_REJ_TEMPORARILY; +#endif + } +#endif /* WH_EZ_SETUP */ + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + DBGPRINT(RT_DEBUG_ERROR, ("(%s) Repeater Cli Receive ifIndex = %d, CliIdx = %d !!!\n", + __FUNCTION__, ifIndex, CliIdx)); + + pCurrState = &pApCliEntry->RepeaterCli[CliIdx].CtrlCurrState; +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + pAssocCurrState = &pApCliEntry->RepeaterCli[CliIdx].AssocCurrState; +#endif + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pCurrState = &pApCliEntry->CtrlCurrState; +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + pAssocCurrState = &pApCliEntry->AssocCurrState; +#endif + } + + + if(Status == MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Auth Rsp Success.\n", __FUNCTION__)); + *pCurrState = APCLI_CTRL_ASSOC; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pApCliEntry->RepeaterCli[CliIdx].AssocReqCnt = 0; + else +#endif /* MAC_REPEATER_SUPPORT */ + pApCliEntry->AssocReqCnt = 0; + +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + if (pApCliEntry->pre_mac_entry.AuthMode == Ndis802_11AuthModeWPA3PSK + || pApCliEntry->pre_mac_entry.AuthMode == Ndis802_11AuthModeOWE) { + pAssocCurrState = ASSOC_IDLE; + Timeout = 5000; + } +#endif + + + AssocParmFill(pAd, &AssocReq, pApCliEntry->MlmeAux.Bssid, pApCliEntry->MlmeAux.CapabilityInfo, +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + Timeout +#else + ASSOC_TIMEOUT +#endif + , 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->wdev.AuthMode == Ndis802_11AuthModeAutoSwitch) + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Auth Rsp Failure.\n", __FUNCTION__)); + + *pCurrState = APCLI_CTRL_AUTH_2; + + /* start Second Authentication Req. */ + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Start Second Auth Rep.\n", __FUNCTION__)); + COPY_MAC_ADDR(AuthReq.Addr, pApCliEntry->MlmeAux.Bssid); + AuthReq.Alg = Ndis802_11AuthModeOpen; + AuthReq.Timeout = AUTH_TIMEOUT; +#ifdef MAC_REPEATER_SUPPORT + AuthReq.BssIdx = ifIndex; + AuthReq.CliIdx = CliIdx; + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + MlmeEnqueue(pAd, APCLI_AUTH_STATE_MACHINE, APCLI_MT2_MLME_AUTH_REQ, + sizeof(MLME_AUTH_REQ_STRUCT), &AuthReq, ifIndex); + } + else + { +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + pApCliEntry->RepeaterCli[CliIdx].AuthReqCnt = 0; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + NdisZeroMemory(pApCliEntry->MlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pApCliEntry->MlmeAux.Ssid, MAX_LEN_OF_SSID); + pApCliEntry->AuthReqCnt = 0; + } + *pCurrState = APCLI_CTRL_DISCONNECTED; + +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if ((pAd->ApCfg.ApCliAutoConnectRunning == TRUE) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + ) + ApCliSwitchCandidateAP(pAd); +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev)){ + *pCurrState = APCLI_CTRL_AUTH; + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_JOIN_FAIL,0, NULL, ifIndex); + RTMP_MLME_HANDLER(pAd); + } +#endif /* WH_EZ_SETUP */ + + } + } + + 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; +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + PULONG pAssocCurrState = NULL; +#endif +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + if ((ifIndex >= MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + && (ifIndex < 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + } +#endif /* MAC_REPEATER_SUPPORT */ + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) { + pCurrState = &pApCliEntry->RepeaterCli[CliIdx].CtrlCurrState; +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + pAssocCurrState = &pApCliEntry->RepeaterCli[CliIdx].AssocCurrState; +#endif + } else +#endif /* MAC_REPEATER_SUPPORT */ + { + pCurrState = &pApCliEntry->CtrlCurrState; +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + pAssocCurrState = &pApCliEntry->AssocCurrState; +#endif + } + if(Status == MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Auth2 Rsp Success.\n", __FUNCTION__)); + *pCurrState = APCLI_CTRL_ASSOC; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pApCliEntry->RepeaterCli[CliIdx].AssocReqCnt = 0; + else +#endif /* MAC_REPEATER_SUPPORT */ + pApCliEntry->AssocReqCnt = 0; + + AssocParmFill(pAd, &AssocReq, pApCliEntry->MlmeAux.Bssid, pApCliEntry->MlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, 5); + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + MlmeEnqueue(pAd, APCLI_ASSOC_STATE_MACHINE, APCLI_MT2_MLME_ASSOC_REQ, + sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq, ifIndex); + } + else + { + 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; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Auth Req Timeout.\n", __FUNCTION__)); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + pApCliEntry->RepeaterCli[CliIdx].AuthReqCnt++; + + if (pApCliEntry->RepeaterCli[CliIdx].AuthReqCnt > 5) + { + *pCurrState = APCLI_CTRL_DISCONNECTED; + pApCliEntry->RepeaterCli[CliIdx].AuthReqCnt = 0; + /* allow other packet trigger auth request agian */ + RTMPRemoveRepeaterEntry(pAd, ifIndex, CliIdx); + + return; + } + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry->AuthReqCnt++; + +#ifdef WH_EZ_SETUP + if ((IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev)) && (pApCliEntry->AuthReqCnt > 2)) // allow two retries + { + *pCurrState = APCLI_CTRL_AUTH; // redundant?? + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_JOIN_FAIL,0, NULL, ifIndex); + RTMP_MLME_HANDLER(pAd); + return; + } + else +#endif /* WH_EZ_SETUP */ + + if (pApCliEntry->AuthReqCnt > 5) + { + *pCurrState = APCLI_CTRL_DISCONNECTED; + NdisZeroMemory(pApCliEntry->MlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pApCliEntry->MlmeAux.Ssid, MAX_LEN_OF_SSID); + pApCliEntry->AuthReqCnt = 0; +#ifdef APCLI_OWE_SUPPORT + apcli_reset_owe_parameters(pAd, ifIndex); +#endif + +#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, pApCliEntry->MlmeAux.Bssid); + AuthReq.Alg = pApCliEntry->MlmeAux.Alg; /*Ndis802_11AuthModeOpen; */ + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + && pApCliEntry->MlmeAux.support_easy_setup) { + AuthReq.Alg = AUTH_MODE_EZ; + } +#endif /* WH_EZ_SETUP */ + + 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]; + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev) + && pApCliEntry->MlmeAux.support_easy_setup) { +#ifdef NEW_CONNECTION_ALGO + if (ez_is_connection_allowed(&pApCliEntry->wdev) == FALSE) + Status = MLME_ASSOC_REJ_TEMPORARILY; +#endif + } +#endif /* WH_EZ_SETUP */ + + if(Status == MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) apCliIf = %d, Receive Assoc Rsp Success.\n", __FUNCTION__, ifIndex)); + + +#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_SAE_SUPPORT + if (Status == MLME_INVALID_PMKID) { + UCHAR if_addr[MAC_ADDR_LEN]; + INT CachedIdx; + UCHAR pmkid[80]; + UCHAR pmk[LEN_PMK]; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + NdisCopyMemory(if_addr, &pApCliEntry->RepeaterCli[CliIdx].CurrentAddress, MAC_ADDR_LEN); + else +#endif /* MAC_REPEATER_SUPPORT */ + NdisCopyMemory(if_addr, &pApCliEntry->wdev.if_addr, MAC_ADDR_LEN); + +/*Received PMK invalid status from AP delete entry from SavedPMK and delete SAE instance*/ + + + if (pApCliEntry->pre_mac_entry.AuthMode == Ndis802_11AuthModeWPA3PSK && + sae_get_pmk_cache(&pAd->SaeCfg, if_addr, pApCliEntry->MlmeAux.Bssid, pmkid, pmk) + ) { + + CachedIdx = apcli_search_pmkid_cache(pAd, pApCliEntry->MlmeAux.Bssid, ifIndex +#ifdef MAC_REPEATER_SUPPORT + , CliIdx +#endif + ); + + if (CachedIdx != INVALID_PMKID_IDX) { + SAE_INSTANCE *pSaeIns = + search_sae_instance(&pAd->SaeCfg, if_addr, pApCliEntry->MlmeAux.Bssid); + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("[SAE]Reconnection falied with pmkid ,delete cache entry and sae instance\n")); + if (pSaeIns != NULL) + delete_sae_instance(pSaeIns); + + apcli_delete_pmkid_cache(pAd, pApCliEntry->MlmeAux.Bssid, ifIndex +#ifdef MAC_REPEATER_SUPPORT + , CliIdx +#endif + ); + } + } + } +#endif/*APCLI_SAE_SUPPORT*/ + + +#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 */ + + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev)){ + *pCurrState = APCLI_CTRL_ASSOC; + if(Status == MLME_EZ_CONNECTION_LOOP) + ez_initiate_new_scan_hook(pApCliEntry->wdev.ez_driver_params.ez_ad); + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_JOIN_FAIL,0, NULL, ifIndex); + RTMP_MLME_HANDLER(pAd); + } +#endif + + } + + return; +} + +/* + ========================================================================== + Description: + APCLI MLME DeASSOC RSP state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlDeAssocRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PAPCLI_STRUCT pApCliEntry; + APCLI_CTRL_MSG_STRUCT *Info = (APCLI_CTRL_MSG_STRUCT *)(Elem->Msg); + USHORT Status = Info->Status; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; + BOOLEAN bValid = FALSE; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + if ((ifIndex >= MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + && (ifIndex < 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CtrlCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + if (Status == MLME_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Receive DeAssoc Rsp Success.\n", __FUNCTION__)); + } else + { + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Receive DeAssoc Rsp Failure.\n", __FUNCTION__)); + } + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + bValid = pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid; + else +#endif /* MAC_REPEATER_SUPPORT */ + bValid = pApCliEntry->Valid; + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + if (bValid) + ApCliLinkDown(pAd, ifIndex); + + *pCurrState = APCLI_CTRL_DISCONNECTED; + + return; +} + +/* + ========================================================================== + Description: + APCLI MLME Assoc Req timeout state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlAssocReqTimeoutAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_ASSOC_REQ_STRUCT AssocReq; + PAPCLI_STRUCT pApCliEntry; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Assoc Req Timeout.\n", __FUNCTION__)); + + if ((ifIndex >= MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + && (ifIndex < 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CtrlCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + /* give up to retry authentication req after retry it 5 times. */ +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx !=0xFF) + { + 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; + /* allow other packet trigger auth request agian */ + RTMPRemoveRepeaterEntry(pAd, ifIndex, CliIdx); + + return; + } + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry->AssocReqCnt++; + +#ifdef WH_EZ_SETUP + if ((IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev)) && (pApCliEntry->AssocReqCnt > 2)) // allow two assoc retries + { + *pCurrState = APCLI_CTRL_ASSOC; // redundant + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_JOIN_FAIL,0, NULL, ifIndex); + RTMP_MLME_HANDLER(pAd); + return; + } + else +#endif + { + if (pApCliEntry->AssocReqCnt > 5) + { + *pCurrState = APCLI_CTRL_DISCONNECTED; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Ssid, MAX_LEN_OF_SSID); + pApCliEntry->AssocReqCnt = 0; + +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if ((pAd->ApCfg.ApCliAutoConnectRunning == TRUE) +#ifdef MAC_REPEATER_SUPPORT + && (CliIdx == 0xFF) +#endif /* MAC_REPEATER_SUPPORT */ + ) + ApCliSwitchCandidateAP(pAd); +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + return; + } + } + } + + /* stay in same state. */ + *pCurrState = APCLI_CTRL_ASSOC; + + /* retry Association Req. */ + DBGPRINT(RT_DEBUG_TRACE, ("(%s) Retry Association Req.\n", __FUNCTION__)); + AssocParmFill(pAd, &AssocReq, pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.CapabilityInfo, + ASSOC_TIMEOUT, 5); + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + MlmeEnqueue(pAd, APCLI_ASSOC_STATE_MACHINE, APCLI_MT2_MLME_ASSOC_REQ, + sizeof(MLME_ASSOC_REQ_STRUCT), &AssocReq, ifIndex); + + return; +} + +/* + ========================================================================== + Description: + APCLI MLME Disconnect Rsp state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlDisconnectReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PAPCLI_STRUCT pApCliEntry; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + PULONG pAuthCurrState = NULL; +#endif + 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); +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + pAuthCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].AuthCurrState; +#endif + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CtrlCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + pAuthCurrState = &pAd->ApCfg.ApCliTab[ifIndex].AuthCurrState; +#endif + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + } + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + bValid = pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid; + else +#endif /* MAC_REPEATER_SUPPORT */ + bValid = pApCliEntry->Valid; + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + DBGPRINT(RT_DEBUG_ERROR, ("(%s) 2. Before do ApCliLinkDown.\n", __FUNCTION__)); + if (bValid) + ApCliLinkDown(pAd, ifIndex); + + /* set the apcli interface be invalid. */ +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + ifIndex = ((ifIndex - 64) / 16); + RTMPRemoveRepeaterEntry(pAd, ifIndex, CliIdx); + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry->Valid = FALSE; + + /* clear MlmeAux.Ssid and Bssid. */ + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, MAC_ADDR_LEN); + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.SsidLen = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Rssi = 0; + } + { +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + *pAuthCurrState = AUTH_REQ_IDLE; +#endif + *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)); + 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 */ + ) + { + STA_TR_ENTRY *tr_entry = &pAd->MacTab.tr_entry[pApCliEntry->MacTabWCID]; + if (tr_entry->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); + RTMPRemoveRepeaterEntry(pAd, ifIndex, CliIdx); + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry->Valid = FALSE; + + /* clear MlmeAux.Ssid and Bssid. */ + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, MAC_ADDR_LEN); + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.SsidLen = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Rssi = 0; +#ifdef APCLI_OWE_SUPPORT + apcli_reset_owe_parameters(pAd, ifIndex); +#endif + + } + +#ifdef WH_EZ_SETUP + if( (IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev)) && + ( (*pCurrState == APCLI_CTRL_AUTH) || (*pCurrState == APCLI_CTRL_AUTH_2) ||(*pCurrState == APCLI_CTRL_ASSOC) || + (pApCliEntry->MlmeAux.attempted_candidate_index != EZ_INDEX_NOT_FOUND) +#ifdef WSC_AP_SUPPORT + || ((pApCliEntry->WscControl.WscConfMode != WSC_DISABLE) && (pApCliEntry->WscControl.bWscTrigger == TRUE)) +#endif + || (pApCliEntry->wdev.ez_driver_params.ez_wps_reconnect) + ) + ) + { + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("(%s) Connection attempt failed by peer\n", __FUNCTION__)); + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_JOIN_FAIL,0, NULL, ifIndex); + RTMP_MLME_HANDLER(pAd); + }else +#endif + { + *pCurrState = APCLI_CTRL_DISCONNECTED; + } + return; +} + +/* + ========================================================================== + Description: + APCLI MLME Disconnect Req state machine procedure + ========================================================================== + */ +static VOID ApCliCtrlDeAssocAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PAPCLI_STRUCT pApCliEntry; + MLME_DISASSOC_REQ_STRUCT DisassocReq; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = NULL; + BOOLEAN bValid = FALSE; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) MLME Request Disconnect.\n", __FUNCTION__)); + + if ((ifIndex >= MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + && (ifIndex < 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CtrlCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + DisassocParmFill(pAd, &DisassocReq, pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, REASON_DISASSOC_STA_LEAVING); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + bValid = pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid; + else +#endif /* MAC_REPEATER_SUPPORT */ + bValid = pApCliEntry->Valid; + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + + MlmeEnqueue(pAd, APCLI_ASSOC_STATE_MACHINE, APCLI_MT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), &DisassocReq, ifIndex); + + if (bValid) + ApCliLinkDown(pAd, ifIndex); + + /* set the apcli interface be invalid. */ +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + ifIndex = ((ifIndex - 64) / 16); + RTMPRemoveRepeaterEntry(pAd, ifIndex, CliIdx); + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry->Valid = FALSE; + + /* clear MlmeAux.Ssid and Bssid. */ + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, MAC_ADDR_LEN); + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.SsidLen = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Rssi = 0; + } + + *pCurrState = APCLI_CTRL_DEASSOC; + + return; +} + + +/* + ========================================================================== + Description: + APCLI MLME Disconnect Req state machine procedure + ========================================================================== + */ +#ifndef WH_EZ_SETUP +static +#endif +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 WH_EZ_SETUP +#ifdef EZ_NETWORK_MERGE_SUPPORT + BOOLEAN deauth_in_same_context = FALSE; +#endif +#endif + +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) MLME Request Disconnect.\n", __FUNCTION__)); + +#ifdef WH_EZ_SETUP +#ifdef EZ_NETWORK_MERGE_SUPPORT + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd) && (ifIndex & IMM_DISCONNECT)) + { + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("ApCliCtrlDeAuthAction: Deauth In same context\n")); + ifIndex &= (!IMM_DISCONNECT); + Elem->Priv &= (!IMM_DISCONNECT); + deauth_in_same_context = TRUE; + } +#endif +#endif + + if ((ifIndex >= MAX_APCLI_NUM) +#ifdef MAC_REPEATER_SUPPORT + && (ifIndex < 64) +#endif /* MAC_REPEATER_SUPPORT */ + ) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + { + CliIdx = ((ifIndex - 64) % 16); + ifIndex = ((ifIndex - 64) / 16); + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CtrlCurrState; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + + /* Fill in the related information */ + DeAuthFrame.Reason = (USHORT)REASON_DEAUTH_STA_LEAVING; + COPY_MAC_ADDR(DeAuthFrame.Addr, pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid); + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + bValid = pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].CliValid; + else +#endif /* MAC_REPEATER_SUPPORT */ + bValid = pApCliEntry->Valid; + +#ifdef MAC_REPEATER_SUPPORT + ifIndex = (USHORT)(Elem->Priv); +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef WH_EZ_SETUP +#ifdef EZ_NETWORK_MERGE_SUPPORT + if (IS_EZ_SETUP_ENABLED((&pApCliEntry->wdev)) && deauth_in_same_context == TRUE) + { + MLME_QUEUE_ELEM *mlmeDeauth_Elem; + os_alloc_mem(pAd, (UCHAR **)&mlmeDeauth_Elem, sizeof(MLME_QUEUE_ELEM)); + + if(mlmeDeauth_Elem == NULL) + { + EZ_DEBUG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("Set::OID_802_11_DEAUTHENTICATION, Failed!!\n")); + return; + } + mlmeDeauth_Elem->Priv = Elem->Priv; + NdisCopyMemory(mlmeDeauth_Elem->Msg,&DeAuthFrame,sizeof(MLME_DEAUTH_REQ_STRUCT)); + mlmeDeauth_Elem->MsgLen = sizeof(MLME_DEAUTH_REQ_STRUCT); + ApCliMlmeDeauthReqAction( pAd,mlmeDeauth_Elem); + os_free_mem(NULL, mlmeDeauth_Elem); + } else +#endif +#endif + { + MlmeEnqueue(pAd, + APCLI_AUTH_STATE_MACHINE, + APCLI_MT2_MLME_DEAUTH_REQ, + sizeof(MLME_DEAUTH_REQ_STRUCT), + &DeAuthFrame, + ifIndex); + } +#ifdef APCLI_DOT11W_PMF_SUPPORT + /* speed up the de-auth is send out before mac entry is delete for */ + /*PMF 5.3.3.3 trasmit encrypt de-auth/ dis-asso req*/ + /*Still have chance to delete mac entry before de-auth is sent out.*/ + RTMP_MLME_HANDLER(pAd); +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + if (bValid) + ApCliLinkDown(pAd, ifIndex); + + /* set the apcli interface be invalid. */ +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + { + ifIndex = ((ifIndex - 64) / 16); + //RTMPDelRepeaterCliAsicEntry(pAd, CliIdx); + RTMPRemoveRepeaterEntry(pAd, ifIndex, CliIdx); + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + pApCliEntry->Valid = FALSE; + + /* clear MlmeAux.Ssid and Bssid. */ + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, MAC_ADDR_LEN); + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.SsidLen = 0; + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Ssid, MAX_LEN_OF_SSID); + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Rssi = 0; + } + + *pCurrState = APCLI_CTRL_DISCONNECTED; + + return; +} + +#endif /* APCLI_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_link_cover.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_link_cover.c new file mode 100644 index 000000000..ffc069a6f --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_link_cover.c @@ -0,0 +1,144 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-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 +#ifdef APCLI_LINK_COVER_SUPPORT +#include "rt_config.h" + +extern VOID* p5G_pAd; +extern VOID* p2G_pAd; + +INT ApcliLinkMonitorThread( + IN ULONG Context) +{ + RTMP_ADAPTER *pAd; + RTMP_ADAPTER *pAd_other_band; + RTMP_OS_TASK *pTask; + int status; + status = 0; + + pTask = (RTMP_OS_TASK *)Context; + pAd = (PRTMP_ADAPTER)RTMP_OS_TASK_DATA_GET(pTask); + + RtmpOSTaskCustomize(pTask); + + if (p2G_pAd == NULL) { + printk("##### no 2G pAd!!!\n"); + //RtmpOSTaskNotifyToExit(pTask); + // return 0; + } else if (p5G_pAd == NULL) { + printk("##### no 5G pAd!!!\n"); + //RtmpOSTaskNotifyToExit(pTask); + // return 0; + } + if (p5G_pAd == pAd) { + printk("we are 5G interface, wait 2G link update\n"); + pAd_other_band = p2G_pAd; + } + else { + printk("we are 2G interface, wait 5G link update\n"); + pAd_other_band = p5G_pAd; + } + + while (pTask && !RTMP_OS_TASK_IS_KILLED(pTask) && (pAd_other_band != NULL)) + { + if (RtmpOSTaskWait(pAd, pTask, &status) == FALSE) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + break; + } + if (status != 0) + break; + //TODO: wait_for_completion + } + + /* 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(). + */ + printk("<---ApcliLinkMonitorThread\n"); + + //if (pTask) + // RtmpOSTaskNotifyToExit(pTask); + + return 0; +} + +NDIS_STATUS RtmpApcliLinkTaskInit(IN PRTMP_ADAPTER pAd) +{ + RTMP_OS_TASK *pTask; + NDIS_STATUS status; + + printk("##### %s\n", __func__); + /* Creat ApCli Link Monitor Thread */ + pTask = &pAd->apcliLinkTask; + RTMP_OS_TASK_INIT(pTask, "LinkMonitorTask", pAd); + //status = RtmpOSTaskAttach(pTask, RTPCICmdThread, (ULONG)pTask); + status = RtmpOSTaskAttach(pTask, ApcliLinkMonitorThread, (ULONG)pTask); + if (status == NDIS_STATUS_FAILURE) + { +/* printk ("%s: unable to start RTPCICmdThread\n", RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev)); */ + printk ("%s: Unable to start ApcliLinkMonitorThread!\n", get_dev_name_prefix(pAd, INT_APCLI)); + return NDIS_STATUS_FAILURE; + } + + return NDIS_STATUS_SUCCESS; +} + +VOID RtmpApcliLinkTaskExit( + IN RTMP_ADAPTER *pAd) +{ + INT ret; + + printk("##### %s\n", __func__); + /* Terminate cmdQ thread */ + RTMP_OS_TASK_LEGALITY(&pAd->apcliLinkTask) + { + /*RTUSBCMDUp(&pAd->cmdQTask); */ + ret = RtmpOSTaskKill(&pAd->apcliLinkTask); + if (ret == NDIS_STATUS_FAILURE) + { + DBGPRINT(RT_DEBUG_ERROR, ("Kill command task fail!\n")); + } + } + return; +} + + +#endif /* APCLI_LINK_COVER_SUPPORT */ +#endif /* APCLI_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_sync.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_sync.c new file mode 100644 index 000000000..f875e7785 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/apcli_sync.c @@ -0,0 +1,1581 @@ +/* + *************************************************************************** + * 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" + +#ifdef WH_EZ_SETUP +#ifdef DUAL_CHIP +extern NDIS_SPIN_LOCK ez_conn_perm_lock; +#endif +#endif +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); + StateMachineSetAction(Sm, APCLI_JOIN_WAIT_PROBE_RSP, APCLI_MT2_PEER_BEACON, (STATE_MACHINE_FUNC)ApCliPeerProbeRspAtJoinAction); + + + for (i = 0; i < MAX_APCLI_NUM; i++) + { + /* timer init */ +#ifdef MULTI_APCLI_SUPPORT + pAd->ApCfg.ApCliTab[i].TimerInfo.pAd = pAd; + pAd->ApCfg.ApCliTab[i].TimerInfo.Ifindex= i; + RTMPInitTimer(pAd, &pAd->ApCfg.ApCliTab[i].MlmeAux.ProbeTimer, GET_TIMER_FUNCTION(ApCliProbeTimeout), &pAd->ApCfg.ApCliTab[i].TimerInfo, FALSE); +#else /* MULTI_APCLI_SUPPORT */ + RTMPInitTimer(pAd, &pAd->ApCfg.ApCliTab[i].MlmeAux.ProbeTimer, GET_TIMER_FUNCTION(ApCliProbeTimeout), pAd, FALSE); +#endif /* !MULTI_APCLI_SUPPORT */ + pAd->ApCfg.ApCliTab[i].SyncCurrState = APCLI_SYNC_IDLE; + } + + return; +} + +/* + ========================================================================== + Description: + Becaon timeout handler, executed in timer thread + ========================================================================== + */ +static VOID ApCliProbeTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + +#ifdef MULTI_APCLI_SUPPORT + PRTMP_ADAPTER pAd; + USHORT ifIndex = 0; + PTIMER_INFO TimerInfo = (PTIMER_INFO)FunctionContext; + pAd = TimerInfo->pAd; + ifIndex = TimerInfo->Ifindex; + DBGPRINT(RT_DEBUG_TRACE, ("ApCli_SYNC - ProbeReqTimeout, ifIndex=%u\n",ifIndex)); + MlmeEnqueue(pAd, APCLI_SYNC_STATE_MACHINE, APCLI_MT2_PROBE_TIMEOUT, 0, NULL, ifIndex); +#else /* MULTI_APCLI_SUPPORT */ + 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); +#endif /* !MULTI_APCLI_SUPPORT */ + + 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; +#ifdef WH_EZ_SETUP + PULONG pCurrStateCtrl = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + struct wifi_dev *wdev = &pAd->ApCfg.ApCliTab[ifIndex].wdev; +#ifdef WSC_AP_SUPPORT + PWSC_CTRL pWpsCtrl = &pAd->ApCfg.ApCliTab[ifIndex].WscControl; +#endif /* WSC_AP_SUPPORT */ +#endif + APCLI_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->MlmeAux.ProbeTimer), &Cancelled); + + pApCliEntry->MlmeAux.Rssi = -9999; + + pApCliEntry->MlmeAux.Channel = pAd->CommonCfg.Channel; + + pApCliEntry->MlmeAux.SupRateLen = pAd->CommonCfg.SupRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.SupRate, pAd->CommonCfg.SupRate, pAd->CommonCfg.SupRateLen); + + /* Prepare the default value for extended rate */ + pApCliEntry->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, pAd->CommonCfg.ExtRateLen); + + RTMPSetTimer(&(pApCliEntry->MlmeAux.ProbeTimer), PROBE_TIMEOUT); + +#ifdef APCLI_OWE_SUPPORT +/*OWE:clear previously selected ssid and bssid */ + if (pApCliEntry->wdev.AuthMode == Ndis802_11AuthModeOWE && (pApCliEntry->owe_trans_ssid_len > 0)) { + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.Ssid, MAX_LEN_OF_SSID); + } +#endif + + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev) +#ifdef EZ_NETWORK_MERGE_SUPPORT + //! if peer supports EZ setup, always go for EZ-connection + && pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.support_easy_setup) +#else + && wdev->ez_security.configured_status == EZ_UNCONFIGURED) + +#endif + { + ULONG bss_idx = BSS_NOT_FOUND; + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.support_easy_setup = FALSE; + bss_idx = BssTableSearchWithSSID(&pAd->ScanTab, (PCHAR)Info->Bssid, (PCHAR)Info->Ssid, Info->SsidLen, pApCliEntry->MlmeAux.Channel); + if (bss_idx != BSS_NOT_FOUND) { + if (pAd->ScanTab.BssEntry[bss_idx].support_easy_setup) + { + pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.support_easy_setup = TRUE; +#ifdef NEW_CONNECTION_ALGO + if (!ez_update_connection_permission(pAd,&pApCliEntry->wdev,EZ_DISALLOW_ALL_ALLOW_ME)) + { + BOOLEAN cancelled; + *pCurrStateCtrl = APCLI_CTRL_DISCONNECTED; + ASSERT(FALSE); + RTMPCancelTimer(&(pApCliEntry->MlmeAux.ProbeTimer), &cancelled); + return; + } +#endif + + } + } + else + { + BOOLEAN cancelled; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("BssEntry Not found in pAd->ScanTab\n")); + *pCurrStateCtrl = APCLI_CTRL_DISCONNECTED; + //ASSERT(FALSE); + RTMPCancelTimer(&(pApCliEntry->MlmeAux.ProbeTimer), &cancelled); + return; + + } + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("EasySetup Conn = %d\n",pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.support_easy_setup)); + + } + else if (IS_EZ_SETUP_ENABLED(wdev) && (pWpsCtrl->WscConfMode != WSC_DISABLE) && + (pWpsCtrl->bWscTrigger == TRUE)) + { + ULONG bss_idx = BSS_NOT_FOUND; + bss_idx = BssTableSearchWithSSID(&pAd->ScanTab, (PCHAR)Info->Bssid, (PCHAR)Info->Ssid, Info->SsidLen, pApCliEntry->MlmeAux.Channel); + + //! adjust APCLI's operating bandwidth to that of peer + if (bss_idx != BSS_NOT_FOUND) { + ez_ApCliAutoConnectBWAdjust(pAd, wdev, &pAd->ScanTab.BssEntry[bss_idx]); + + ez_ApCliAutoConnectBWAdjust(pAd, &pAd->ApCfg.MBSSID[wdev->func_idx].wdev , &pAd->ScanTab.BssEntry[bss_idx]); + } else { + } + } + +#endif /* WH_EZ_SETUP */ + + ApCliEnqueueProbeRequest(pAd, Info->SsidLen, (PCHAR) Info->Ssid, ifIndex); + + DBGPRINT(RT_DEBUG_TRACE, ("ApCli SYNC - Start Probe the SSID %s on channel =%d\n", pApCliEntry->MlmeAux.Ssid, pApCliEntry->MlmeAux.Channel)); + + *pCurrState = APCLI_JOIN_WAIT_PROBE_RSP; + + return; +} + + +/* + ========================================================================== + Description: + When waiting joining the (I)BSS, beacon received from external + ========================================================================== + */ +static VOID ApCliPeerProbeRspAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + USHORT LenVIE; + UCHAR *VarIE = NULL; + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + PAPCLI_STRUCT pApCliEntry = NULL; + struct wifi_dev *wdev; +#ifdef DBG +#ifdef DOT11_N_SUPPORT + UCHAR CentralChannel; +#endif /* DOT11_N_SUPPORT */ +#endif /* DBG */ + USHORT ifIndex = (USHORT)(Elem->Priv); + ULONG *pCurrState; + BCN_IE_LIST *ie_list = NULL; +#ifdef WH_EZ_SETUP + PFRAME_802_11 pFrame = NULL; +#ifdef DISCONNECT_ON_CONFIG_UPDATE + BOOLEAN error = FALSE; +#endif +#endif /* WH_EZ_SETUP */ +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + UCHAR Snr0 = Elem->Snr0; + UCHAR Snr1 = Elem->Snr1; + + Snr0 = ConvertToSnr(pAd, Snr0); + Snr1 = ConvertToSnr(pAd, Snr1); +#endif + + +#ifdef APCLI_OWE_SUPPORT + UCHAR tempBuf[20]; +#endif + + if (ifIndex >= MAX_APCLI_NUM) + return; + + /* Init Variable IE structure */ + os_alloc_mem(NULL, (UCHAR **)&VarIE, MAX_VIE_LEN); + if (VarIE == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + + os_alloc_mem(NULL, (UCHAR **)&ie_list, sizeof(BCN_IE_LIST)); + if (ie_list == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate ie_list fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + NdisZeroMemory(ie_list, sizeof(BCN_IE_LIST)); + + pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].SyncCurrState; + + if (PeerBeaconAndProbeRspSanity(pAd, + Elem->Msg, + Elem->MsgLen, + Elem->Channel, + ie_list, + &LenVIE, + pVIE, + TRUE, + FALSE)) + { + /* + 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; +#ifdef APCLI_OWE_SUPPORT + INT ssidEmptyFlag = FALSE; +#endif + INT bssidEqualFlag = FALSE; + INT bssidEmptyFlag = FALSE; + + INT matchFlag = FALSE; + +#ifdef APCLI_DOT11W_PMF_SUPPORT + ULONG Bssidx = BSS_NOT_FOUND; +#else + ULONG Bssidx; +#endif /* APCLI_DOT11W_PMF_SUPPORT */ +#ifdef WH_EZ_SETUP + CHAR Rssi = -127; +#endif +#if defined(RT_CFG80211_P2P_CONCURRENT_DEVICE) || defined(CFG80211_MULTI_STA) || defined (WH_EZ_SETUP) + CHAR Rssi0 = ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_0); + CHAR Rssi1 = ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_1); + CHAR Rssi2 = ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_2); + LONG RealRssi = (LONG)(RTMPMaxRssi(pAd, Rssi0, Rssi1, Rssi2)); +#endif /* RT_CFG80211_P2P_CONCURRENT_DEVICE || CFG80211_MULTI_STA */ + + + /* Update ScanTab */ +#if !defined(APCLI_SAE_SUPPORT) && !defined(APCLI_OWE_SUPPORT) + Bssidx = BssTableSearch(&pAd->ScanTab, ie_list->Bssid, ie_list->Channel); + if (Bssidx == BSS_NOT_FOUND) +#endif + { +#ifdef WH_EZ_SETUP + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) + Rssi = (CHAR)RealRssi; +#endif + /* discover new AP of this network, create BSS entry */ + Bssidx = BssTableSetEntry(pAd, &pAd->ScanTab, ie_list, -127, LenVIE, pVIE +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + , + Snr0, + Snr1 +#endif + ); + + + + if (Bssidx == BSS_NOT_FOUND) /* return if BSS table full */ + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: Driver ScanTable Full In Apcli ProbeRsp Join\n")); + goto LabelErr; + } + + NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].PTSF, &Elem->Msg[24], 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[0], &Elem->TimeStamp.u.LowPart, 4); + NdisMoveMemory(&pAd->ScanTab.BssEntry[Bssidx].TTSF[4], &Elem->TimeStamp.u.LowPart, 4); + pAd->ScanTab.BssEntry[Bssidx].MinSNR = Elem->Signal % 10; + if (pAd->ScanTab.BssEntry[Bssidx].MinSNR == 0) + pAd->ScanTab.BssEntry[Bssidx].MinSNR = -5; + + NdisMoveMemory(pAd->ScanTab.BssEntry[Bssidx].MacAddr, ie_list->Addr2, MAC_ADDR_LEN); + } + + + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + wdev = &pApCliEntry->wdev; + +#ifdef WH_EZ_SETUP + //wdev = &pApCliEntry->wdev; //Arvind same happen above + pFrame = (PFRAME_802_11)Elem->Msg; + if (IS_EZ_SETUP_ENABLED(wdev) && + pAd->ScanTab.BssEntry[Bssidx].support_easy_setup && + pApCliEntry->MlmeAux.support_easy_setup) { +#ifdef DISCONNECT_ON_CONFIG_UPDATE + error = ez_probe_rsp_join_action(pAd, wdev, ie_list, Bssidx); + if(error) + goto LabelErr; +#endif + if (pFrame->Hdr.FC.SubType == SUBTYPE_BEACON) { + /* + Ignore beacon here. + Only probe response has DH public key information. + */ + goto LabelErr; + } + else { + ez_process_beacon_probe_response(wdev, + Elem->Msg, Elem->MsgLen); + } + } +#endif /* WH_EZ_SETUP */ + +#if defined(APCLI_OWE_SUPPORT) || defined(APCLI_SAE_SUPPORT) + os_zero_mem((PVOID)&pApCliEntry->pre_mac_entry, sizeof(pApCliEntry->pre_mac_entry)); + pApCliEntry->pre_mac_entry.func_tb_idx = ifIndex + MIN_NET_DEVICE_FOR_APCLI; + pApCliEntry->pre_mac_entry.AuthMode = wdev->AuthMode; + pApCliEntry->pre_mac_entry.WepStatus = wdev->WepStatus; + pApCliEntry->pre_mac_entry.GroupKeyWepStatus = wdev->GroupKeyWepStatus; + SET_ENTRY_APCLI(&pApCliEntry->pre_mac_entry); +#endif + + +#ifdef APCLI_OWE_SUPPORT + if (pApCliEntry->wdev.AuthMode == Ndis802_11AuthModeOWE && (pApCliEntry->owe_trans_ssid_len > 0)) { + BSS_ENTRY *popen_bss_entry = NULL; + + popen_bss_entry = &pAd->ScanTab.BssEntry[Bssidx]; + + if (!MAC_ADDR_EQUAL(pApCliEntry->owe_trans_bssid, ie_list->Bssid)) { + + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: OWE Transition AP BSSID not equal\n")); + goto LabelErr; + } +/*Validate that we are connecting wth the same OWE BSS that was mentioned in the OPEN BSS Transition IE*/ + if (popen_bss_entry->owe_trans_ie_len > 0) { + UCHAR pair_ch = 0; + UCHAR pair_bssid[MAC_ADDR_LEN] = {0}; + UCHAR pair_ssid[MAX_LEN_OF_SSID] = {0}; + UCHAR pair_band = 0; + UCHAR pair_ssid_len = 0; + + extract_pair_owe_bss_info(popen_bss_entry->owe_trans_ie, + popen_bss_entry->owe_trans_ie_len, + pair_bssid, + pair_ssid, + &pair_ssid_len, + &pair_band, + &pair_ch); + + if (!MAC_ADDR_EQUAL(pApCliEntry->owe_trans_open_bssid, pair_bssid) + || !SSID_EQUAL(pApCliEntry->owe_trans_open_ssid, + pApCliEntry->owe_trans_open_ssid_len, pair_ssid, pair_ssid_len)) { + DBGPRINT(RT_DEBUG_ERROR, ("OWE:Transition AP Validation Failed\n")); + goto LabelErr; + } + } + + } +#endif + + /* Check the Probe-Rsp's Bssid. */ + if(!MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ZERO_MAC_ADDR)) + bssidEqualFlag = MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ie_list->Bssid); + else + bssidEmptyFlag = TRUE; + +#ifdef APCLI_OWE_SUPPORT + if (pApCliEntry->owe_trans_ssid_len > 0) { + ssidEqualFlag = SSID_EQUAL(pApCliEntry->owe_trans_ssid, + pApCliEntry->owe_trans_ssid_len, ie_list->Ssid, ie_list->SsidLen); + + bssidEqualFlag = MAC_ADDR_EQUAL(pApCliEntry->owe_trans_bssid, ie_list->Bssid); + + + if (ssidEqualFlag == TRUE) + ssidEmptyFlag = FALSE; + if (bssidEqualFlag == TRUE) + bssidEmptyFlag = FALSE; + + } else +#endif + /* Check the Probe-Rsp's Ssid. */ + if (pApCliEntry->CfgSsidLen != 0) + ssidEqualFlag = SSID_EQUAL(pApCliEntry->CfgSsid, pApCliEntry->CfgSsidLen, ie_list->Ssid, ie_list->SsidLen); + + + + /* bssid and ssid, Both match. */ + if (bssidEqualFlag && ssidEqualFlag) + matchFlag = TRUE; + +#ifdef WH_EZ_SETUP + if(!bssidEmptyFlag) + { + //! SSID will be empty on EZ interface in case of TRIband + if (IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev) && bssidEqualFlag && (pApCliEntry->CfgSsidLen == 0) + && ez_is_triband()) + matchFlag = TRUE; + } +#endif + + /* ssid match but bssid doesn't be indicate. */ + else if(ssidEqualFlag && bssidEmptyFlag) + matchFlag = TRUE; +#ifdef WH_EZ_SETUP + + if (IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev) && matchFlag == 0) + { + if (ssidEqualFlag == 0) + { + // Clear scan list if found to be stale. + BssTableInit(&pAd->ScanTab); + + } + if (bssidEqualFlag == 0) + { + hex_dump("Apclibssid", pApCliEntry->CfgApCliBssid,6); + hex_dump("IEbssid", ie_list->Bssid,6); + } + } +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - bssidEqualFlag=%d, ssidEqualFlag=%d, matchFlag=%d\n", + bssidEqualFlag, ssidEqualFlag, matchFlag)); + if (matchFlag) + { + /* Validate RSN IE if necessary, then copy store this information */ + if ((LenVIE > 0) +#ifdef WSC_AP_SUPPORT + && ((pApCliEntry->WscControl.WscConfMode == WSC_DISABLE) || + (pApCliEntry->WscControl.bWscTrigger == FALSE)) +#endif /* WSC_AP_SUPPORT */ + ) + { +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef DOT11W_PMF_SUPPORT + BSS_ENTRY *pInBss = NULL; + + pApCliEntry->MlmeAux.RsnCap.word = 0; + pApCliEntry->MlmeAux.IsSupportSHA256KeyDerivation = FALSE; + + pInBss = &pAd->ScanTab.BssEntry[Bssidx]; + if (pInBss) { + NdisMoveMemory(&pApCliEntry->MlmeAux.RsnCap, + &pInBss->WPA2.RsnCapability, sizeof(RSN_CAPABILITIES)); + pApCliEntry->MlmeAux.IsSupportSHA256KeyDerivation = + pInBss->IsSupportSHA256KeyDerivation; + } +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + if (ApCliValidateRSNIE(pAd, (PEID_STRUCT)pVIE, LenVIE, ifIndex +#ifdef APCLI_OWE_SUPPORT + , CAP_IS_PRIVACY_ON(ie_list->CapabilityInfo) +#endif + )) + { + pApCliEntry->MlmeAux.VarIELen = LenVIE; + NdisMoveMemory(pApCliEntry->MlmeAux.VarIEs, pVIE, pApCliEntry->MlmeAux.VarIELen); + } + else + { + /* ignore this response */ + pApCliEntry->MlmeAux.VarIELen = 0; + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The RSN IE of this received Probe-resp is dis-match !!!!!!!!!! \n")); + goto LabelErr; + } + } + else + { + if (pApCliEntry->wdev.AuthMode >= Ndis802_11AuthModeWPA +#ifdef WSC_AP_SUPPORT + && ((pApCliEntry->WscControl.WscConfMode == WSC_DISABLE) || + (pApCliEntry->WscControl.bWscTrigger == FALSE)) +#endif /* WSC_AP_SUPPORT */ +#ifdef APCLI_OWE_SUPPORT + && pApCliEntry->wdev.AuthMode != Ndis802_11AuthModeOWE +#endif + ) + { + /* ignore this response */ + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: The received Probe-resp has empty RSN IE !!!!!!!!!! \n")); + goto LabelErr; + } + +#ifdef APCLI_OWE_SUPPORT + else if (pApCliEntry->wdev.AuthMode == Ndis802_11AuthModeOWE + && (CAP_IS_PRIVACY_ON(ie_list->CapabilityInfo) == 0)) { + pApCliEntry->pre_mac_entry.AuthMode = Ndis802_11AuthModeOpen; + pApCliEntry->pre_mac_entry.WepStatus = Ndis802_11WEPDisabled; + pApCliEntry->pre_mac_entry.GroupKeyWepStatus = Ndis802_11WEPDisabled; + pApCliEntry->PairCipher = Ndis802_11WEPDisabled; + pApCliEntry->GroupCipher = Ndis802_11WEPDisabled; + pApCliEntry->RsnCapability = 0; + pApCliEntry->bMixCipher = FALSE; + } +#endif + + pApCliEntry->MlmeAux.VarIELen = 0; + } + +#ifdef MWDS + pApCliEntry->MlmeAux.bSupportMWDS = FALSE; + if(ie_list->vendor_ie.mtk_cap_found) + { + BOOLEAN bSupportMWDS = FALSE; + if(ie_list->vendor_ie.support_mwds) + bSupportMWDS = TRUE; + if(pAd->ScanTab.BssEntry[Bssidx].bSupportMWDS != bSupportMWDS) + pAd->ScanTab.BssEntry[Bssidx].bSupportMWDS = bSupportMWDS; + if(pAd->ScanTab.BssEntry[Bssidx].bSupportMWDS) + { + pApCliEntry->MlmeAux.bSupportMWDS = TRUE; + DBGPRINT(RT_DEBUG_OFF, ("AP supports MWDS\n")); + } + else{ + pApCliEntry->MlmeAux.bSupportMWDS = FALSE; + } + } +#endif /* MWDS */ + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - receive desired PROBE_RSP at JoinWaitProbeRsp... Channel = %d\n", + ie_list->Channel)); + + /* if the Bssid doesn't be indicated then you need to decide which AP to connect by most strong Rssi signal strength. */ + if (bssidEqualFlag == FALSE) + { + /* caculate real rssi value. */ + CHAR Rssi0 = ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_0); + CHAR Rssi1 = ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_1); + CHAR Rssi2 = ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_2); + LONG RealRssi = (LONG)(RTMPMaxRssi(pAd, Rssi0, Rssi1, Rssi2)); + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - previous Rssi = %ld current Rssi=%ld\n", pApCliEntry->MlmeAux.Rssi, (LONG)RealRssi)); + if (pApCliEntry->MlmeAux.Rssi > (LONG)RealRssi) + goto LabelErr; + else + pApCliEntry->MlmeAux.Rssi = RealRssi; + } + else + { + BOOLEAN Cancelled; + RTMPCancelTimer(&pApCliEntry->MlmeAux.ProbeTimer, &Cancelled); + } + + NdisMoveMemory(pApCliEntry->MlmeAux.Ssid, ie_list->Ssid, ie_list->SsidLen); + pApCliEntry->MlmeAux.SsidLen = ie_list->SsidLen; + + NdisMoveMemory(pApCliEntry->MlmeAux.Bssid, ie_list->Bssid, MAC_ADDR_LEN); + pApCliEntry->MlmeAux.CapabilityInfo = ie_list->CapabilityInfo & SUPPORTED_CAPABILITY_INFO; + pApCliEntry->MlmeAux.BssType = ie_list->BssType; + pApCliEntry->MlmeAux.BeaconPeriod = ie_list->BeaconPeriod; + pApCliEntry->MlmeAux.Channel = ie_list->Channel; + pApCliEntry->MlmeAux.AtimWin = ie_list->AtimWin; + pApCliEntry->MlmeAux.CfpPeriod = ie_list->CfParm.CfpPeriod; + pApCliEntry->MlmeAux.CfpMaxDuration = ie_list->CfParm.CfpMaxDuration; + pApCliEntry->MlmeAux.APRalinkIe = ie_list->RalinkIe; + + /* Copy AP's supported rate to MlmeAux for creating assoication request */ + /* Also filter out not supported rate */ + pApCliEntry->MlmeAux.SupRateLen = ie_list->SupRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.SupRate, ie_list->SupRate, ie_list->SupRateLen); + RTMPCheckRates(pAd, pApCliEntry->MlmeAux.SupRate, &pApCliEntry->MlmeAux.SupRateLen); + pApCliEntry->MlmeAux.ExtRateLen = ie_list->ExtRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.ExtRate, ie_list->ExtRate, ie_list->ExtRateLen); + RTMPCheckRates(pAd, pApCliEntry->MlmeAux.ExtRate, &pApCliEntry->MlmeAux.ExtRateLen); + +#ifdef DOT11_N_SUPPORT + NdisZeroMemory(pApCliEntry->RxMcsSet,sizeof(pApCliEntry->RxMcsSet)); + /* filter out un-supported ht rates */ + if ((ie_list->HtCapabilityLen > 0) && + (pApCliEntry->wdev.DesiredHtPhyInfo.bHtEnable) && + WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + /* For Dissallow TKIP rule on STA */ + !(pAd->CommonCfg.HT_DisallowTKIP && IS_INVALID_HT_SECURITY(wdev->WepStatus))) + { + RTMPZeroMemory(&pApCliEntry->MlmeAux.HtCapability, SIZE_HT_CAP_IE); + pApCliEntry->MlmeAux.NewExtChannelOffset = ie_list->NewExtChannelOffset; + pApCliEntry->MlmeAux.HtCapabilityLen = ie_list->HtCapabilityLen; + ApCliCheckHt(pAd, ifIndex, &ie_list->HtCapability, &ie_list->AddHtInfo); + +#ifdef DBG + if (ie_list->AddHtInfoLen > 0) + { + CentralChannel = ie_list->AddHtInfo.ControlChan; + /* Check again the Bandwidth capability of this AP. */ + CentralChannel = get_cent_ch_by_htinfo(pAd, &ie_list->AddHtInfo, + &ie_list->HtCapability); + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAtJoinAction HT===>CentralCh = %d, ControlCh = %d\n", + CentralChannel, ie_list->AddHtInfo.ControlChan)); + } +#endif /* DBG */ + } + else +#endif /* DOT11_N_SUPPORT */ + { + RTMPZeroMemory(&pApCliEntry->MlmeAux.HtCapability, SIZE_HT_CAP_IE); + RTMPZeroMemory(&pApCliEntry->MlmeAux.AddHtInfo, SIZE_ADD_HT_INFO_IE); + pApCliEntry->MlmeAux.HtCapabilityLen = 0; + } + ApCliUpdateMlmeRate(pAd, ifIndex); + +#ifdef DOT11_N_SUPPORT + /* copy QOS related information */ + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + NdisMoveMemory(&pApCliEntry->MlmeAux.APEdcaParm, &ie_list->EdcaParm, sizeof(EDCA_PARM)); + NdisMoveMemory(&pApCliEntry->MlmeAux.APQbssLoad, &ie_list->QbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisMoveMemory(&pApCliEntry->MlmeAux.APQosCapability, &ie_list->QosCapability, sizeof(QOS_CAPABILITY_PARM)); + } + else +#endif /* DOT11_N_SUPPORT */ + { + NdisZeroMemory(&pApCliEntry->MlmeAux.APEdcaParm, sizeof(EDCA_PARM)); + NdisZeroMemory(&pApCliEntry->MlmeAux.APQbssLoad, sizeof(QBSS_LOAD_PARM)); + NdisZeroMemory(&pApCliEntry->MlmeAux.APQosCapability, sizeof(QOS_CAPABILITY_PARM)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI SYNC - after JOIN, SupRateLen=%d, ExtRateLen=%d\n", + pApCliEntry->MlmeAux.SupRateLen, pApCliEntry->MlmeAux.ExtRateLen)); + + if (ie_list->AironetCellPowerLimit != 0xFF) + { + /* We need to change our TxPower for CCX 2.0 AP Control of Client Transmit Power */ + ChangeToCellPowerLimit(pAd, ie_list->AironetCellPowerLimit); + } + else /* Used the default TX Power Percentage. */ + pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + +#ifdef WSC_AP_SUPPORT +#ifdef DOT11_N_SUPPORT + if ((pApCliEntry->WscControl.WscConfMode != WSC_DISABLE) && + (pApCliEntry->WscControl.bWscTrigger == TRUE)) + { + ADD_HTINFO RootApHtInfo, ApHtInfo; + ApHtInfo = pAd->CommonCfg.AddHTInfo.AddHtInfo; + RootApHtInfo = ie_list->AddHtInfo.AddHtInfo; + if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (RootApHtInfo.RecomWidth) && + (RootApHtInfo.ExtChanOffset != ApHtInfo.ExtChanOffset)) + { + 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 */ +#ifdef APCLI_OWE_SUPPORT + if ((bssidEqualFlag == TRUE) + && pAd->ScanTab.BssEntry[Bssidx].owe_trans_ie_len > 0 + && pApCliEntry->wdev.AuthMode == Ndis802_11AuthModeOWE + && pApCliEntry->pre_mac_entry.AuthMode == Ndis802_11AuthModeOpen + && pApCliEntry->pre_mac_entry.WepStatus == Ndis802_11WEPDisabled) { + + BSS_ENTRY *popen_bss_entry = NULL; + BSS_TABLE *pscan_tab = NULL; + struct wifi_dev *papcli_wdev = NULL; + + + /*If bssidEqualFlag is set then the probe timer has been cancelled,*/ + /* so we need to perform OWE trans IE parsing here in the case of Configured BSSID*/ + + *pCurrState = APCLI_SYNC_IDLE; + + pscan_tab = &pAd->ScanTab; + papcli_wdev = (struct wifi_dev *)&pApCliEntry->wdev; + + /*If Trans IE found then extract BSSID ,SSID ,Band and Channel*/ + popen_bss_entry = &pscan_tab->BssEntry[Bssidx]; + + if (popen_bss_entry && (popen_bss_entry->owe_trans_ie_len > 0)) { + + + UCHAR pair_ch = 0; + UCHAR pair_bssid[MAC_ADDR_LEN] = {0}; + UCHAR pair_ssid[MAX_LEN_OF_SSID] = {0}; + UCHAR pair_band = 0; + UCHAR pair_ssid_len = 0; + + + + extract_pair_owe_bss_info(popen_bss_entry->owe_trans_ie, + popen_bss_entry->owe_trans_ie_len, + pair_bssid, + pair_ssid, + &pair_ssid_len, + &pair_band, + &pair_ch); + + + + if (pair_ch != 0) { + /*OWE Entry found ,update OweTransBssid and OweTranSsid*/ + + + /*OWE bss is on different channel*/ + + if (BOARD_IS_5G_ONLY(pAd)) { + + } else { + + /*Check if the OWE bss is on the same band as the CLI,then check if channel change required*/ + if ((WMODE_2G_ONLY(pApCliEntry->wdev.PhyMode) && (pair_ch <= 14)) + || (WMODE_5G_ONLY(pApCliEntry->wdev.PhyMode) && (pair_ch > 14))) { + + if (pair_ch != popen_bss_entry->Channel) { + /*OWE send EVENT to host for OWE indicating different channel*/ + wext_send_owe_trans_chan_event(papcli_wdev->if_dev, + OID_802_11_OWE_EVT_SAME_BAND_DIFF_CHANNEL, + pair_bssid, + pair_ssid, + &pair_ssid_len, + &pair_band, + &pair_ch); + + DBGPRINT(RT_DEBUG_TRACE, ("%s:%d Different channel same band\n", __func__, __LINE__)); + + NdisMoveMemory(&pApCliEntry->owe_trans_bssid, pair_bssid, MAC_ADDR_LEN); + NdisMoveMemory(&pApCliEntry->owe_trans_ssid, pair_ssid, pair_ssid_len); + pApCliEntry->owe_trans_ssid_len = pair_ssid_len; + + NdisMoveMemory(&pApCliEntry->owe_trans_open_bssid, popen_bss_entry->Bssid, MAC_ADDR_LEN); + NdisMoveMemory(&pApCliEntry->owe_trans_open_ssid, popen_bss_entry->Ssid, popen_bss_entry->SsidLen); + pApCliEntry->owe_trans_open_ssid_len = popen_bss_entry->SsidLen; + + pApCliEntry->pre_mac_entry.AuthMode = Ndis802_11AuthModeOpen; + pApCliEntry->pre_mac_entry.WepStatus = Ndis802_11WEPDisabled; + pApCliEntry->pre_mac_entry.GroupKeyWepStatus = Ndis802_11WEPDisabled; + pApCliEntry->PairCipher = Ndis802_11WEPDisabled; + pApCliEntry->GroupCipher = Ndis802_11WEPDisabled; + pApCliEntry->RsnCapability = 0; + pApCliEntry->bMixCipher = FALSE; + + /*Delete the Open Bss entry from Scan table because apcli does not ageout scan tab entries*/ + BssTableDeleteEntry(pscan_tab, pApCliEntry->MlmeAux.Bssid, pApCliEntry->MlmeAux.Channel); + + DBGPRINT(RT_DEBUG_TRACE, ("Switch to channel :%d\n", + pair_ch)); + + sprintf(tempBuf, "%d", pair_ch); + Set_Channel_Proc(pAd, tempBuf); + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_JOIN_REQ_TIMEOUT, 0, NULL, ifIndex); + return; + } else { + /*Same Channel send directed probe request to OWE BSS*/ + /*Update the Owe transtion Bssid and Ssid that will used for a directed probe request to OWE AP*/ + + NdisMoveMemory(&pApCliEntry->owe_trans_bssid, pair_bssid, MAC_ADDR_LEN); + NdisMoveMemory(&pApCliEntry->owe_trans_ssid, pair_ssid, pair_ssid_len); + pApCliEntry->owe_trans_ssid_len = pair_ssid_len; + + NdisMoveMemory(&pApCliEntry->owe_trans_open_bssid, popen_bss_entry->Bssid, MAC_ADDR_LEN); + NdisMoveMemory(&pApCliEntry->owe_trans_open_ssid, popen_bss_entry->Ssid, popen_bss_entry->SsidLen); + pApCliEntry->owe_trans_open_ssid_len = popen_bss_entry->SsidLen; + + pApCliEntry->pre_mac_entry.AuthMode = Ndis802_11AuthModeOpen; + pApCliEntry->pre_mac_entry.WepStatus = Ndis802_11WEPDisabled; + pApCliEntry->pre_mac_entry.GroupKeyWepStatus = Ndis802_11WEPDisabled; + pApCliEntry->PairCipher = Ndis802_11WEPDisabled; + pApCliEntry->GroupCipher = Ndis802_11WEPDisabled; + pApCliEntry->RsnCapability = 0; + pApCliEntry->bMixCipher = FALSE; + + + /*Delete the Open Bss entry from Scan table because apcli does not ageout scan tab entries*/ + BssTableDeleteEntry(pscan_tab, pApCliEntry->MlmeAux.Bssid, pApCliEntry->MlmeAux.Channel); + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_JOIN_REQ_TIMEOUT, 0, NULL, ifIndex); + return; + + } + } else { + /*Channel not in group of current band , but entry exists so send event to host to trigger connection on other band*/ + wext_send_owe_trans_chan_event(papcli_wdev->if_dev, + OID_802_11_OWE_EVT_DIFF_BAND, + pair_bssid, + pair_ssid, + &pair_ssid_len, + &pair_band, + &pair_ch); + + } + + } + } else { + /*Same Channel send directed probe request to OWE BSS*/ + /*Update the Owe transtion Bssid and Ssid that will used for a directed probe request to OWE AP*/ + + NdisMoveMemory(&pApCliEntry->owe_trans_bssid, pair_bssid, MAC_ADDR_LEN); + NdisMoveMemory(&pApCliEntry->owe_trans_ssid, pair_ssid, pair_ssid_len); + pApCliEntry->owe_trans_ssid_len = pair_ssid_len; + + NdisMoveMemory(&pApCliEntry->owe_trans_open_bssid, popen_bss_entry->Bssid, MAC_ADDR_LEN); + NdisMoveMemory(&pApCliEntry->owe_trans_open_ssid, popen_bss_entry->Ssid, popen_bss_entry->SsidLen); + pApCliEntry->owe_trans_open_ssid_len = popen_bss_entry->SsidLen; + + pApCliEntry->pre_mac_entry.AuthMode = Ndis802_11AuthModeOpen; + pApCliEntry->pre_mac_entry.WepStatus = Ndis802_11WEPDisabled; + pApCliEntry->pre_mac_entry.GroupKeyWepStatus = Ndis802_11WEPDisabled; + pApCliEntry->PairCipher = Ndis802_11WEPDisabled; + pApCliEntry->GroupCipher = Ndis802_11WEPDisabled; + pApCliEntry->RsnCapability = 0; + pApCliEntry->bMixCipher = FALSE; + + /*Delete the Open Bss entry from Scan table because apcli does not ageout scan tab entries*/ + BssTableDeleteEntry(pscan_tab, pApCliEntry->MlmeAux.Bssid, pApCliEntry->MlmeAux.Channel); + + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_JOIN_REQ_TIMEOUT, 0, NULL, ifIndex); + return; + + } + + + } + + } else + +#endif + + 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 */ + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev) + && pApCliEntry->MlmeAux.support_easy_setup) { + ez_prepare_security_key(wdev, ie_list->Addr2, FALSE); + } +#endif /* WH_EZ_SETUP */ + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_PROBE_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + } + } +#ifdef WH_EVENT_NOTIFIER + { + EventHdlr pEventHdlrHook = NULL; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_AP_PROBE_RSP); + if(pEventHdlrHook && pApCliEntry) + pEventHdlrHook(pAd, &pApCliEntry->wdev, ie_list, Elem); + } +#endif /* WH_EVENT_NOTIFIER */ + + } + +LabelErr: + if (VarIE != NULL) + os_free_mem(NULL, VarIE); + if (ie_list != NULL) + os_free_mem(NULL, ie_list); + + return; +} + +static VOID ApCliProbeTimeoutAtJoinAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].SyncCurrState; + APCLI_STRUCT *pApCliEntry = NULL; +#ifdef APCLI_OWE_SUPPORT + UCHAR entryIdx = 0; + BSS_TABLE *pscan_tab = NULL, *pssid_bss_tab = NULL; + struct wifi_dev *papcli_wdev = NULL; + UCHAR tempBuf[20]; +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_SYNC - ProbeTimeoutAtJoinAction\n")); + + if (ifIndex >= MAX_APCLI_NUM) + return; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + +#ifdef APCLI_OWE_SUPPORT + papcli_wdev = (struct wifi_dev *)&pApCliEntry->wdev; + pscan_tab = &pAd->ScanTab; + pssid_bss_tab = &pApCliEntry->MlmeAux.owe_bss_tab; + pssid_bss_tab->BssNr = 0; + + /*Find out APs with OWE transition IE and store them in the owe_bss_tab*/ + if (pApCliEntry->wdev.AuthMode == Ndis802_11AuthModeOWE) { + + for (entryIdx = 0; entryIdx < pscan_tab->BssNr; entryIdx++) { + BSS_ENTRY *pBssEntry = &pscan_tab->BssEntry[entryIdx]; + + if (pBssEntry->Channel == 0) + continue; + + if ((pBssEntry->owe_trans_ie_len > 0) && + (pssid_bss_tab->BssNr < MAX_LEN_OF_BSS_TABLE)) { + DBGPRINT(RT_DEBUG_INFO, + ("%s:OWE Table %d:Bssid=%02x:%02x:%02x:%02x:%02x:%02x\n" + , __func__, __LINE__, + PRINT_MAC(pBssEntry->Bssid))); + NdisMoveMemory(&pssid_bss_tab->BssEntry[pssid_bss_tab->BssNr++], + pBssEntry, sizeof(BSS_ENTRY)); + + } + } + } + if (pssid_bss_tab->BssNr < MAX_LEN_OF_BSS_TABLE) + NdisZeroMemory(&pssid_bss_tab->BssEntry[pssid_bss_tab->BssNr], sizeof(BSS_ENTRY)); + +#endif/* APCLI_OWE_SUPPORT */ + + *pCurrState = SYNC_IDLE; + + DBGPRINT(RT_DEBUG_TRACE, ("APCLI_SYNC - MlmeAux.Bssid=%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pApCliEntry->MlmeAux.Bssid))); + + if(!MAC_ADDR_EQUAL(pApCliEntry->MlmeAux.Bssid, ZERO_MAC_ADDR)) + { + ApCliCtrlMsg.Status = MLME_SUCCESS; +#ifdef MAC_REPEATER_SUPPORT + ApCliCtrlMsg.BssIdx = ifIndex; + ApCliCtrlMsg.CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef APCLI_OWE_SUPPORT + /*Find Open BSS with Trans IE*/ + if (papcli_wdev->AuthMode == Ndis802_11AuthModeOWE + && pApCliEntry->pre_mac_entry.AuthMode == Ndis802_11AuthModeOpen + && pApCliEntry->pre_mac_entry.WepStatus == Ndis802_11WEPDisabled) { + + ULONG bssidx = 0; + BSS_ENTRY *popen_bss_entry = NULL; + + /*Find BSS entry for Open bss from owe_bss_tab*/ + bssidx = BssTableSearch(pssid_bss_tab, pApCliEntry->MlmeAux.Bssid, pApCliEntry->MlmeAux.Channel); + + if (bssidx != BSS_NOT_FOUND) { + /*If Trans IE found then extract BSSID ,SSID ,Band and Channel*/ + popen_bss_entry = &pssid_bss_tab->BssEntry[bssidx]; + if (popen_bss_entry && (popen_bss_entry->owe_trans_ie_len > 0)) { + + + UCHAR pair_ch = 0; + UCHAR pair_bssid[MAC_ADDR_LEN] = {0}; + UCHAR pair_ssid[MAX_LEN_OF_SSID] = {0}; + UCHAR pair_band = 0; + UCHAR pair_ssid_len = 0; + + + + extract_pair_owe_bss_info(popen_bss_entry->owe_trans_ie, + popen_bss_entry->owe_trans_ie_len, + pair_bssid, + pair_ssid, + &pair_ssid_len, + &pair_band, + &pair_ch); + + + + if (pair_ch != 0) { + /*OWE Entry found ,update OweTransBssid and OweTranSsid*/ + + + /*OWE bss is on different channel*/ + + if (BOARD_IS_5G_ONLY(pAd)) { + + } else { + + /*Check if the OWE bss is on the same band as the CLI,then check if channel change required*/ + if ((WMODE_2G_ONLY(pApCliEntry->wdev.PhyMode) && (pair_ch <= 14)) + || (WMODE_5G_ONLY(pApCliEntry->wdev.PhyMode) && (pair_ch > 14))) { + + if (pair_ch != popen_bss_entry->Channel) { + /*OWE send EVENT to host for OWE indicating different channel*/ + wext_send_owe_trans_chan_event(papcli_wdev->if_dev, + OID_802_11_OWE_EVT_SAME_BAND_DIFF_CHANNEL, + pair_bssid, + pair_ssid, + &pair_ssid_len, + &pair_band, + &pair_ch); + + DBGPRINT(RT_DEBUG_TRACE, ("%s:%d Different channel same band\n", __func__, __LINE__)); + + NdisMoveMemory(&pApCliEntry->owe_trans_bssid, pair_bssid, MAC_ADDR_LEN); + NdisMoveMemory(&pApCliEntry->owe_trans_ssid, pair_ssid, pair_ssid_len); + pApCliEntry->owe_trans_ssid_len = pair_ssid_len; + + NdisMoveMemory(&pApCliEntry->owe_trans_open_bssid, popen_bss_entry->Bssid, MAC_ADDR_LEN); + NdisMoveMemory(&pApCliEntry->owe_trans_open_ssid, popen_bss_entry->Ssid, popen_bss_entry->SsidLen); + pApCliEntry->owe_trans_open_ssid_len = popen_bss_entry->SsidLen; + + + pApCliEntry->pre_mac_entry.AuthMode = Ndis802_11AuthModeOpen; + pApCliEntry->pre_mac_entry.WepStatus = Ndis802_11WEPDisabled; + pApCliEntry->pre_mac_entry.GroupKeyWepStatus = Ndis802_11WEPDisabled; + pApCliEntry->PairCipher = Ndis802_11WEPDisabled; + pApCliEntry->GroupCipher = Ndis802_11WEPDisabled; + pApCliEntry->RsnCapability = 0; + pApCliEntry->bMixCipher = FALSE; + + /*Delete the Open Bss entry from Scan table because apcli does not ageout scan tab entries*/ + BssTableDeleteEntry(pscan_tab, pApCliEntry->MlmeAux.Bssid, pApCliEntry->MlmeAux.Channel); + + DBGPRINT(RT_DEBUG_TRACE, ("Switch to channel :%d\n", + pair_ch)); + sprintf(tempBuf, "%d", pair_ch); + Set_Channel_Proc(pAd, tempBuf); + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_JOIN_REQ_TIMEOUT, 0, NULL, ifIndex); + return; + } else { + /*Same Channel send directed probe request to OWE BSS*/ + /*Update the Owe transtion Bssid and Ssid that will used for a directed probe request to OWE AP*/ + + NdisMoveMemory(&pApCliEntry->owe_trans_bssid, pair_bssid, MAC_ADDR_LEN); + NdisMoveMemory(&pApCliEntry->owe_trans_ssid, pair_ssid, pair_ssid_len); + pApCliEntry->owe_trans_ssid_len = pair_ssid_len; + + NdisMoveMemory(&pApCliEntry->owe_trans_open_bssid, popen_bss_entry->Bssid, MAC_ADDR_LEN); + NdisMoveMemory(&pApCliEntry->owe_trans_open_ssid, popen_bss_entry->Ssid, popen_bss_entry->SsidLen); + pApCliEntry->owe_trans_open_ssid_len = popen_bss_entry->SsidLen; + + + pApCliEntry->pre_mac_entry.AuthMode = Ndis802_11AuthModeOpen; + pApCliEntry->pre_mac_entry.WepStatus = Ndis802_11WEPDisabled; + pApCliEntry->pre_mac_entry.GroupKeyWepStatus = Ndis802_11WEPDisabled; + pApCliEntry->PairCipher = Ndis802_11WEPDisabled; + pApCliEntry->GroupCipher = Ndis802_11WEPDisabled; + pApCliEntry->RsnCapability = 0; + pApCliEntry->bMixCipher = FALSE; + + + /*Delete the Open Bss entry from Scan table because apcli does not ageout scan tab entries*/ + BssTableDeleteEntry(pscan_tab, pApCliEntry->MlmeAux.Bssid, pApCliEntry->MlmeAux.Channel); + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_JOIN_REQ_TIMEOUT, 0, NULL, ifIndex); + return; + + } + } else { + /*Channel not in group of current band , but entry exists so send event to host to trigger connection on other band*/ + wext_send_owe_trans_chan_event(papcli_wdev->if_dev, + OID_802_11_OWE_EVT_DIFF_BAND, + pair_bssid, + pair_ssid, + &pair_ssid_len, + &pair_band, + &pair_ch); + + } + + } + } else { + /*Same Channel send directed probe request to OWE BSS*/ + /*Update the Owe transtion Bssid and Ssid that will used for a directed probe request to OWE AP*/ + + NdisMoveMemory(&pApCliEntry->owe_trans_bssid, pair_bssid, MAC_ADDR_LEN); + NdisMoveMemory(&pApCliEntry->owe_trans_ssid, pair_ssid, pair_ssid_len); + pApCliEntry->owe_trans_ssid_len = pair_ssid_len; + + NdisMoveMemory(&pApCliEntry->owe_trans_open_bssid, popen_bss_entry->Bssid, MAC_ADDR_LEN); + NdisMoveMemory(&pApCliEntry->owe_trans_open_ssid, popen_bss_entry->Ssid, popen_bss_entry->SsidLen); + pApCliEntry->owe_trans_open_ssid_len = popen_bss_entry->SsidLen; + + pApCliEntry->pre_mac_entry.AuthMode = Ndis802_11AuthModeOpen; + pApCliEntry->pre_mac_entry.WepStatus = Ndis802_11WEPDisabled; + pApCliEntry->pre_mac_entry.GroupKeyWepStatus = Ndis802_11WEPDisabled; + pApCliEntry->PairCipher = Ndis802_11WEPDisabled; + pApCliEntry->GroupCipher = Ndis802_11WEPDisabled; + pApCliEntry->RsnCapability = 0; + pApCliEntry->bMixCipher = FALSE; + + /*Delete the Open Bss entry from Scan table because apcli does not ageout scan tab entries*/ + BssTableDeleteEntry(pscan_tab, pApCliEntry->MlmeAux.Bssid, pApCliEntry->MlmeAux.Channel); + + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_JOIN_REQ_TIMEOUT, 0, NULL, ifIndex); + return; + + } + + + } + + + } + } +#endif + + 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: + ========================================================================== + */ + +/* + ========================================================================== + Description: + ========================================================================== + */ +static VOID ApCliEnqueueProbeRequest_A3Bcast( + 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]; + APCLI_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, BROADCAST_ADDR, ifIndex); + + } + ssidLen = SsidLen; + NdisZeroMemory(ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(ssid, Ssid, ssidLen); + + /* this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr80211, + 1, &SsidIe, + 1, &ssidLen, + ssidLen, ssid, + 1, &SupRateIe, + 1, &pApCliEntry->MlmeAux.SupRateLen, + pApCliEntry->MlmeAux.SupRateLen, pApCliEntry->MlmeAux.SupRate, + END_OF_ARGS); + + /* Add the extended rate IE */ + if (pApCliEntry->MlmeAux.ExtRateLen != 0) + { + ULONG tmp; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pApCliEntry->MlmeAux.ExtRateLen, + pApCliEntry->MlmeAux.ExtRateLen, pApCliEntry->MlmeAux.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14)) + { + FrameLen += build_vht_cap_ie(pAd, (UCHAR *)&pApCliEntry->MlmeAux.vht_cap); + pApCliEntry->MlmeAux.vht_cap_len = sizeof(VHT_CAP_IE); + } +#endif /* DOT11_VHT_AC */ + +#ifdef WSC_AP_SUPPORT +/* Append WSC information in probe request if WSC state is running */ + if ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode != WSC_DISABLE) && + (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger)) + { + bHasWscIe = TRUE; + } +#ifdef WSC_V2_SUPPORT + else if (pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscV2Info.bEnableWpsV2) + { + bHasWscIe = TRUE; + } +#endif /* WSC_V2_SUPPORT */ + if (bHasWscIe) + { + UCHAR /* WscBuf[256], */ WscIeLen = 0; + UCHAR *WscBuf = NULL; + ULONG WscTmpLen = 0; + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&WscBuf, 512); + if (WscBuf != NULL) + { + NdisZeroMemory(WscBuf, 512); + WscBuildProbeReqIE(pAd, STA_MODE, &pApCliEntry->WscControl, WscBuf, &WscIeLen); + MakeOutgoingFrame(pOutBuffer + FrameLen, &WscTmpLen, + WscIeLen, WscBuf, + END_OF_ARGS); + FrameLen += WscTmpLen; + os_free_mem(NULL, WscBuf); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + } +#endif /*WSC_AP_SUPPORT*/ + + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev) && + pApCliEntry->MlmeAux.support_easy_setup) { + FrameLen += ez_build_probe_request_ie(&pApCliEntry->wdev, pOutBuffer + FrameLen); + } +#endif /* WH_EZ_SETUP */ + +#ifdef WH_EVENT_NOTIFIER + if(pApCliEntry->wdev.custom_vie.ie_hdr.len > 0) + { + ULONG custom_vie_len; + ULONG total_custom_vie_len = sizeof(struct Custom_IE_Header) + pApCliEntry->wdev.custom_vie.ie_hdr.len; + MakeOutgoingFrame((pOutBuffer + FrameLen),&custom_vie_len, + total_custom_vie_len, (UCHAR*)&pApCliEntry->wdev.custom_vie, END_OF_ARGS); + FrameLen += custom_vie_len; + } +#endif /* WH_EVENT_NOTIFIER */ + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + + 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]; + APCLI_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 + { +#ifdef APCLI_OWE_SUPPORT + if (pApCliEntry->wdev.AuthMode == Ndis802_11AuthModeOWE && (pApCliEntry->owe_trans_ssid_len > 0)) + ApCliMgtMacHeaderInit(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, + pAd->ApCfg.ApCliTab[ifIndex].owe_trans_bssid, + pAd->ApCfg.ApCliTab[ifIndex].owe_trans_bssid, ifIndex); + else +#endif + 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); + + ApCliEnqueueProbeRequest_A3Bcast( + pAd, + SsidLen, + Ssid, + ifIndex); + + } + ssidLen = SsidLen; + NdisZeroMemory(ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(ssid, Ssid, ssidLen); + + /* this ProbeRequest explicitly specify SSID to reduce unwanted ProbeResponse */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr80211, + 1, &SsidIe, + 1, &ssidLen, + ssidLen, ssid, + 1, &SupRateIe, + 1, &pApCliEntry->MlmeAux.SupRateLen, + pApCliEntry->MlmeAux.SupRateLen, pApCliEntry->MlmeAux.SupRate, + END_OF_ARGS); + + /* Add the extended rate IE */ + if (pApCliEntry->MlmeAux.ExtRateLen != 0) + { + ULONG tmp; + + MakeOutgoingFrame(pOutBuffer + FrameLen, &tmp, + 1, &ExtRateIe, + 1, &pApCliEntry->MlmeAux.ExtRateLen, + pApCliEntry->MlmeAux.ExtRateLen, pApCliEntry->MlmeAux.ExtRate, + END_OF_ARGS); + FrameLen += tmp; + } + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.Channel > 14)) + { + FrameLen += build_vht_cap_ie(pAd, (UCHAR *)&pApCliEntry->MlmeAux.vht_cap); + pApCliEntry->MlmeAux.vht_cap_len = sizeof(VHT_CAP_IE); + } +#endif /* DOT11_VHT_AC */ + +#ifdef WSC_AP_SUPPORT +/* Append WSC information in probe request if WSC state is running */ + if ((pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscConfMode != WSC_DISABLE) && + (pAd->ApCfg.ApCliTab[ifIndex].WscControl.bWscTrigger)) + { + bHasWscIe = TRUE; + } +#ifdef WSC_V2_SUPPORT + else if (pAd->ApCfg.ApCliTab[ifIndex].WscControl.WscV2Info.bEnableWpsV2) + { + bHasWscIe = TRUE; + } +#endif /* WSC_V2_SUPPORT */ + if (bHasWscIe) + { + UCHAR /* WscBuf[256], */ WscIeLen = 0; + UCHAR *WscBuf = NULL; + ULONG WscTmpLen = 0; + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&WscBuf, 512); + if (WscBuf != NULL) + { + NdisZeroMemory(WscBuf, 512); + WscBuildProbeReqIE(pAd, STA_MODE, &pApCliEntry->WscControl, WscBuf, &WscIeLen); + MakeOutgoingFrame(pOutBuffer + FrameLen, &WscTmpLen, + WscIeLen, WscBuf, + END_OF_ARGS); + FrameLen += WscTmpLen; + os_free_mem(NULL, WscBuf); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + } +#endif /*WSC_AP_SUPPORT*/ + + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev) && + pApCliEntry->MlmeAux.support_easy_setup) { + FrameLen += ez_build_probe_request_ie(&pApCliEntry->wdev, pOutBuffer + FrameLen); + } +#endif /* WH_EZ_SETUP */ +#ifdef WH_EVENT_NOTIFIER + if(pApCliEntry->wdev.custom_vie.ie_hdr.len > 0) + { + ULONG custom_vie_len; + ULONG total_custom_vie_len = sizeof(struct Custom_IE_Header) + pApCliEntry->wdev.custom_vie.ie_hdr.len; + MakeOutgoingFrame((pOutBuffer + FrameLen),&custom_vie_len, + total_custom_vie_len, (UCHAR*)&pApCliEntry->wdev.custom_vie, END_OF_ARGS); + FrameLen += custom_vie_len; + } +#endif /* WH_EVENT_NOTIFIER */ + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + } + + return; +} + +#endif /* APCLI_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/sniffer_mib.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/sniffer_mib.c new file mode 100644 index 000000000..37e41568e --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ap/sniffer_mib.c @@ -0,0 +1,551 @@ + +#ifdef SNIFFER_MIB_CMD + +#include "rt_config.h" + +VOID sniffer_timeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +BUILD_TIMER_FUNCTION(sniffer_timeout); + +INT sniffer_channel_restore(IN RTMP_ADAPTER *pAd) +{ + INT bw, ch; + pAd->hw_cfg.bbp_bw = pAd->ApCfg.sniffer_mib_ctrl.bbp_bw; +#ifdef DOT11_VHT_AC + pAd->CommonCfg.vht_cent_ch = pAd->ApCfg.sniffer_mib_ctrl.vht_cent_ch; +#endif /* DOT11_VHT_AC */ + pAd->CommonCfg.CentralChannel = pAd->ApCfg.sniffer_mib_ctrl.CentralChannel; + pAd->CommonCfg.Channel = pAd->ApCfg.sniffer_mib_ctrl.Channel; + + bbp_set_bw(pAd, pAd->hw_cfg.bbp_bw); + +#ifdef DOT11_VHT_AC + if (pAd->hw_cfg.bbp_bw == BW_80) + ch = pAd->CommonCfg.vht_cent_ch; + else +#endif /* DOT11_VHT_AC */ + if (pAd->hw_cfg.bbp_bw == BW_40) + ch = pAd->CommonCfg.CentralChannel; + else + ch = pAd->CommonCfg.Channel; + + DBGPRINT(RT_DEBUG_TRACE, ("ch_restore - End of Monitor, restore to %dMHz channel %d\n", + bw, ch)); + + ASSERT((ch != 0)); + AsicSwitchChannel(pAd, ch, FALSE); + AsicLockChannel(pAd, ch); + + return TRUE; + +} + +void sniffer_timeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PSNIFFER_MIB_CTRL psniffer_mib_ctrl = (SNIFFER_MIB_CTRL *)FunctionContext; + PRTMP_ADAPTER pAd = psniffer_mib_ctrl->pAd; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s: fRTMP_ADAPTER_HALT_IN_PROGRESS\n", __FUNCTION__)); + return; + } + + //set back the sniffer mode to off +#ifdef CONFIG_SNIFFER_SUPPORT + Set_MonitorMode_Proc(pAd,"0"); +#endif /* CONFIG_SNIFFER_SUPPORT */ + + //if (psniffer_mib_ctrl->scan_channel != 0) // restore to original channel + { + //sniffer_channel_restore(pAd); + RTEnqueueInternalCmd(pAd, CMDTHREAD_CHAN_RESTORE, NULL, 0); + } + +} + + +#ifdef CONFIG_SNIFFER_SUPPORT +#ifdef ALL_NET_EVENT +VOID vSnifferMacTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + INT32 i4AvgRssi = 0; + SNIFFER_MAC_CTRL *pMACEntry = (SNIFFER_MAC_CTRL *)FunctionContext; + PSNIFFER_MAC_NOTIFY_T pMACEntryNotify = NULL; + UCHAR bssid[MAC_ADDR_LEN] = {0}; //report zero bssid, to prevent too many check + + if(pMACEntry == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():%d: pMACEntry is NULL!\n", __FUNCTION__,__LINE__)); + return; + } + + pMACEntryNotify = &pMACEntry->rNotify; + if(pMACEntryNotify->i4RxPacketConut > 0) + { + i4AvgRssi = pMACEntryNotify->i4RssiAccum/pMACEntryNotify->i4RxPacketConut; + wext_send_event(pMACEntryNotify->pNetDev,pMACEntry->MACAddr,bssid,pMACEntryNotify->u4Channel,i4AvgRssi,FBT_LINK_STA_FOUND_NOTIFY); + + // Only clear data for next collection. + NdisZeroMemory(pMACEntryNotify,sizeof(*pMACEntryNotify)); + } +} +BUILD_TIMER_FUNCTION(vSnifferMacTimeout); +#endif /* ALL_NET_EVENT */ +#endif /* CONFIG_SNIFFER_SUPPORT */ + +VOID sniffer_mib_ctrlInit(IN PRTMP_ADAPTER pAd) +{ + PSNIFFER_MIB_CTRL psniffer_mib_ctrl = &pAd->ApCfg.sniffer_mib_ctrl; + NdisZeroMemory(psniffer_mib_ctrl, sizeof(SNIFFER_MIB_CTRL)); + psniffer_mib_ctrl->AgeOutTime = 100 ; //set default 100 ms + psniffer_mib_ctrl->pAd = pAd; + + RTMPInitTimer(pAd, &psniffer_mib_ctrl->AgeOutTimer, + GET_TIMER_FUNCTION(sniffer_timeout), psniffer_mib_ctrl, FALSE); + psniffer_mib_ctrl->AgeOutTimer_Running = FALSE; + + NdisAllocateSpinLock(pAd, &psniffer_mib_ctrl->MAC_ListLock); + + DlListInit(&psniffer_mib_ctrl->MAC_List); + + psniffer_mib_ctrl->MAC_ListNum = 0 ; // if we don't set MAC to listen, we expect to sniffer all +} + + +VOID sniffer_mib_ctrlExit(IN PRTMP_ADAPTER pAd) +{ + PSNIFFER_MIB_CTRL psniffer_mib_ctrl; + BOOLEAN Cancelled; + SNIFFER_MAC_CTRL *pMACEntry, *pMACEntryTmp; + psniffer_mib_ctrl = &pAd->ApCfg.sniffer_mib_ctrl; + + if(psniffer_mib_ctrl->AgeOutTimer_Running == TRUE) + { + RTMPCancelTimer(&psniffer_mib_ctrl->AgeOutTimer, &Cancelled); + psniffer_mib_ctrl->AgeOutTimer_Running = FALSE; + } + RTMPReleaseTimer(&psniffer_mib_ctrl->AgeOutTimer, &Cancelled); + + RTMP_SEM_LOCK(&psniffer_mib_ctrl->MAC_ListLock); + DlListForEachSafe(pMACEntry, pMACEntryTmp, &psniffer_mib_ctrl->MAC_List, SNIFFER_MAC_CTRL, List) + { +#ifdef CONFIG_SNIFFER_SUPPORT +#ifdef ALL_NET_EVENT + RTMPReleaseTimer(&pMACEntry->rNotifyTimer, &Cancelled); +#endif /* ALL_NET_EVENT */ +#endif /* CONFIG_SNIFFER_SUPPORT */ + DlListDel(&pMACEntry->List); + os_free_mem(NULL, pMACEntry); + } + DlListInit(&psniffer_mib_ctrl->MAC_List); + RTMP_SEM_UNLOCK(&psniffer_mib_ctrl->MAC_ListLock); + + NdisFreeSpinLock(&psniffer_mib_ctrl->MAC_ListLock); +} + +INT exsta_proc(IN RTMP_ADAPTER *pAd, IN RTMP_STRING *arg) +{ + BOOLEAN find_list = FALSE; + PSNIFFER_MIB_CTRL psniffer_mib_ctrl; + SNIFFER_MAC_CTRL *pMACEntry; + UCHAR macAddr[MAC_ADDR_LEN]; + RTMP_STRING *value; + INT i; + + BOOLEAN Cancelled; + + psniffer_mib_ctrl = &pAd->ApCfg.sniffer_mib_ctrl; + + DBGPRINT(RT_DEBUG_ERROR, ("%s: ==>\n",__FUNCTION__)); + + if (psniffer_mib_ctrl->MAC_ListNum >= (MAX_NUM_OF_SNIFFER_MAC - 1)) + { + DBGPRINT(RT_DEBUG_WARN, ("%s : sniffer mac table is full, and no more entry can join the list!\n",__FUNCTION__)); + return FALSE; + } + + if(strlen(arg) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + return FALSE; + + for (i=0, value = rstrtok(arg,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid */ + + AtoH(value, (UCHAR *)&macAddr[i++], 1); + } + + //need to cancel timer ? + if(psniffer_mib_ctrl->AgeOutTimer_Running == TRUE) + { + RTMPCancelTimer(&psniffer_mib_ctrl->AgeOutTimer, &Cancelled); + psniffer_mib_ctrl->AgeOutTimer_Running = FALSE; + } + + RTMP_SEM_LOCK(&psniffer_mib_ctrl->MAC_ListLock); + DlListForEach(pMACEntry, &psniffer_mib_ctrl->MAC_List, SNIFFER_MAC_CTRL, List) + { + if (MAC_ADDR_EQUAL(pMACEntry->MACAddr, macAddr)) + { + find_list = TRUE; + DBGPRINT(RT_DEBUG_ERROR, ("%s : duplicate mac =%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__,PRINT_MAC(macAddr))); + break; + } + } + RTMP_SEM_UNLOCK(&psniffer_mib_ctrl->MAC_ListLock); + + if (find_list == FALSE) + os_alloc_mem(NULL, (UCHAR **)&pMACEntry, sizeof(*pMACEntry)); + + if (!pMACEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return FALSE; + } + + if (find_list == FALSE) + { + RTMP_SEM_LOCK(&psniffer_mib_ctrl->MAC_ListLock); + NdisZeroMemory(pMACEntry,sizeof(*pMACEntry)); + NdisMoveMemory(pMACEntry->MACAddr, macAddr, MAC_ADDR_LEN); +#ifdef CONFIG_SNIFFER_SUPPORT +#ifdef ALL_NET_EVENT + RTMPInitTimer(pAd, &pMACEntry->rNotifyTimer, GET_TIMER_FUNCTION(vSnifferMacTimeout), pMACEntry, TRUE); +#endif /* ALL_NET_EVENT */ +#endif /* CONFIG_SNIFFER_SUPPORT */ + DlListAddTail(&psniffer_mib_ctrl->MAC_List, &pMACEntry->List); + psniffer_mib_ctrl->MAC_ListNum ++; + RTMP_SEM_UNLOCK(&psniffer_mib_ctrl->MAC_ListLock); + } + + return TRUE; +} + +INT exsta_list_proc(IN RTMP_ADAPTER *pAd, IN RTMP_STRING *arg) +{ + SNIFFER_MAC_CTRL *pMACEntry; + PSNIFFER_MIB_CTRL psniffer_mib_ctrl = &pAd->ApCfg.sniffer_mib_ctrl; + INT i=0; + DBGPRINT(RT_DEBUG_ERROR, ("%s: ==>\n",__FUNCTION__)); + + RTMP_SEM_LOCK(&psniffer_mib_ctrl->MAC_ListLock); + DlListForEach(pMACEntry, &psniffer_mib_ctrl->MAC_List, SNIFFER_MAC_CTRL, List) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:: MAC [%d]=%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__,i++, PRINT_MAC(pMACEntry->MACAddr))); + } + RTMP_SEM_UNLOCK(&psniffer_mib_ctrl->MAC_ListLock); + + DBGPRINT(RT_DEBUG_ERROR, ("%s:: MAC count=%d\n", __FUNCTION__,i)); + + return TRUE; +} + +INT exsta_clear_proc(IN RTMP_ADAPTER *pAd, IN RTMP_STRING *arg) +{ + PSNIFFER_MIB_CTRL psniffer_mib_ctrl; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_ERROR, ("%s: ==>\n",__FUNCTION__)); + + SNIFFER_MAC_CTRL *pMACEntry, *pMACEntryTmp; + psniffer_mib_ctrl = &pAd->ApCfg.sniffer_mib_ctrl; + + if(psniffer_mib_ctrl->AgeOutTimer_Running == TRUE) + { + RTMPCancelTimer(&psniffer_mib_ctrl->AgeOutTimer, &Cancelled); + psniffer_mib_ctrl->AgeOutTimer_Running = FALSE; + } + + RTMP_SEM_LOCK(&psniffer_mib_ctrl->MAC_ListLock); + DlListForEachSafe(pMACEntry, pMACEntryTmp, &psniffer_mib_ctrl->MAC_List, SNIFFER_MAC_CTRL, List) + { +#ifdef CONFIG_SNIFFER_SUPPORT +#ifdef ALL_NET_EVENT + RTMPReleaseTimer(&pMACEntry->rNotifyTimer, &Cancelled); +#endif /* ALL_NET_EVENT */ +#endif /* CONFIG_SNIFFER_SUPPORT */ + DlListDel(&pMACEntry->List); + os_free_mem(NULL, pMACEntry); + } + DlListInit(&psniffer_mib_ctrl->MAC_List); + + psniffer_mib_ctrl->MAC_ListNum = 0; + RTMP_SEM_UNLOCK(&psniffer_mib_ctrl->MAC_ListLock); + + return TRUE; +} + + +INT set_monitor_channel(IN RTMP_ADAPTER *ad, IN INT bw, IN INT channel, IN INT pri_idx) +{ + UINT8 ext_ch; + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): bw = %d, channel = %d, pri_idx = %d\n", __FUNCTION__, bw, channel, pri_idx)); + + ad->CommonCfg.Channel = channel; + if (bw == BW_40) { + if (pri_idx == 0) { + ad->CommonCfg.CentralChannel = ad->CommonCfg.Channel + 2; + ext_ch = EXTCHA_ABOVE; + } else if (pri_idx == 1) { + ext_ch = EXTCHA_BELOW; + if (channel == 14) { + ad->CommonCfg.CentralChannel = ad->CommonCfg.Channel - 1; + } else { + ad->CommonCfg.CentralChannel = ad->CommonCfg.Channel - 2; + } + } else { + DBGPRINT(RT_DEBUG_ERROR, ("pri_idx(%d) is invalid\n")); + return FALSE; + } + } + else if (bw == BW_20) { + ad->CommonCfg.CentralChannel = channel; + } else if ((bw == BW_80) && channel > 14) { +#ifdef DOT11_VHT_AC + ad->CommonCfg.vht_bw = VHT_BW_80; + ad->CommonCfg.vht_cent_ch = vht_cent_ch_freq(ad, ad->CommonCfg.Channel); +#endif + } else { + return FALSE; + } + + bbp_set_bw(ad, bw); + + /* TX/Rx : control channel setting */ +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (ad->chipCap.hif_type == HIF_RTMP || ad->chipCap.hif_type == HIF_RLT) + rtmp_mac_set_ctrlch(ad, ext_ch); +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + +#ifdef MT_MAC + if (ad->chipCap.hif_type == HIF_MT) + mt_mac_set_ctrlch(ad, ext_ch); +#endif /* MT_MAC */ + + bbp_set_ctrlch(ad, ext_ch); + +#ifdef DOT11_VHT_AC + if (ad->CommonCfg.BBPCurrentBW == BW_80) + ad->hw_cfg.cent_ch = ad->CommonCfg.vht_cent_ch; + else +#endif /* DOT11_VHT_AC */ + ad->hw_cfg.cent_ch = ad->CommonCfg.CentralChannel; + + AsicSwitchChannel(ad, ad->hw_cfg.cent_ch, FALSE); + AsicLockChannel(ad, ad->hw_cfg.cent_ch); + + return TRUE; +} + + +/* trigger sniffer timmer*/ +INT exsta_scan_proc(IN RTMP_ADAPTER *pAd, IN RTMP_STRING *arg) +{ + BOOLEAN Cancelled; + ULONG start = 0; + PSNIFFER_MIB_CTRL psniffer_mib_ctrl; + psniffer_mib_ctrl = &pAd->ApCfg.sniffer_mib_ctrl; +#ifdef CONFIG_SNIFFER_SUPPORT +#ifdef ALL_NET_EVENT + SNIFFER_MAC_CTRL *pMACEntry = NULL; + PSNIFFER_MAC_NOTIFY_T pMACEntryNotify = NULL; +#endif /* ALL_NET_EVENT */ +#endif /* CONFIG_SNIFFER_SUPPORT */ + + DBGPRINT(RT_DEBUG_ERROR, ("%s: ==>\n",__FUNCTION__)); + + start = simple_strtol(arg, 0, 10); + + if(psniffer_mib_ctrl->AgeOutTimer_Running == TRUE) + { + RTMPCancelTimer(&psniffer_mib_ctrl->AgeOutTimer, &Cancelled); + psniffer_mib_ctrl->AgeOutTimer_Running = FALSE; +#ifdef CONFIG_SNIFFER_SUPPORT +#ifdef ALL_NET_EVENT + RTMP_SEM_LOCK(&psniffer_mib_ctrl->MAC_ListLock); + DlListForEach(pMACEntry, &psniffer_mib_ctrl->MAC_List, SNIFFER_MAC_CTRL, List) + { + if(pMACEntry) + { + RTMPCancelTimer(&pMACEntry->rNotifyTimer, &Cancelled); + } + } + RTMP_SEM_UNLOCK(&psniffer_mib_ctrl->MAC_ListLock); +#endif /* ALL_NET_EVENT */ +#endif /* CONFIG_SNIFFER_SUPPORT */ + } + + if(start) + { + if (psniffer_mib_ctrl->AgeOutTime) + { + RTMPSetTimer(&psniffer_mib_ctrl->AgeOutTimer, psniffer_mib_ctrl->AgeOutTime); + psniffer_mib_ctrl->AgeOutTimer_Running = TRUE; + + psniffer_mib_ctrl->bbp_bw = pAd->CommonCfg.BBPCurrentBW;//pAd->hw_cfg.bbp_bw; +#ifdef DOT11_VHT_AC + psniffer_mib_ctrl->vht_cent_ch = pAd->CommonCfg.vht_cent_ch; +#endif /* DOT11_VHT_AC */ + psniffer_mib_ctrl->CentralChannel = pAd->CommonCfg.CentralChannel; + psniffer_mib_ctrl->Channel = pAd->CommonCfg.Channel; + +#ifdef DOT11_VHT_AC + DBGPRINT(RT_DEBUG_ERROR, ("%s: psniffer_mib_ctrl->bbp_bw=%d,psniffer_mib_ctrl->CentralChannel=%d,psniffer_mib_ctrl->Channel\n",__FUNCTION__, + psniffer_mib_ctrl->bbp_bw,psniffer_mib_ctrl->CentralChannel,psniffer_mib_ctrl->Channel)); +#else /* DOT11_VHT_AC */ + DBGPRINT(RT_DEBUG_ERROR, ("%s: psniffer_mib_ctrl->bbp_bw=%d, psniffer_mib_ctrl->vht_cent_ch=%d,psniffer_mib_ctrl->CentralChannel=%d,psniffer_mib_ctrl->Channel\n",__FUNCTION__, + psniffer_mib_ctrl->bbp_bw,psniffer_mib_ctrl->vht_cent_ch,psniffer_mib_ctrl->CentralChannel,psniffer_mib_ctrl->Channel)); +#endif /* !DOT11_VHT_AC */ + + // no cmd to set bw, keep the original bw + if (psniffer_mib_ctrl->scan_channel == 0) + { + ;// do nothing, don't switch channel + } + else + { + if (pAd->hw_cfg.bbp_bw !=BW_20 ) + { + if (psniffer_mib_ctrl->scan_channel <=7 ) //EXTCHA_ABOVE , ch 1~7 use EXTCHA_ABOVE + { + set_monitor_channel(pAd,psniffer_mib_ctrl->bbp_bw, psniffer_mib_ctrl->scan_channel, 0); + } + else // others use EXTCHA_BELOW + { + set_monitor_channel(pAd,psniffer_mib_ctrl->bbp_bw, psniffer_mib_ctrl->scan_channel, 1); + } + } + else //BW_20 case + { + set_monitor_channel(pAd,psniffer_mib_ctrl->bbp_bw, psniffer_mib_ctrl->scan_channel, 0); + } + } + +#ifdef CONFIG_SNIFFER_SUPPORT +#ifdef ALL_NET_EVENT + RTMP_SEM_LOCK(&psniffer_mib_ctrl->MAC_ListLock); + DlListForEach(pMACEntry, &psniffer_mib_ctrl->MAC_List, SNIFFER_MAC_CTRL, List) + { + if(pMACEntry) + { + pMACEntryNotify = &pMACEntry->rNotify; + NdisZeroMemory(pMACEntryNotify,sizeof(*pMACEntryNotify)); + RTMPSetTimer(&pMACEntry->rNotifyTimer, SNIFFER_MAC_TIMEOUT); + } + } + RTMP_SEM_UNLOCK(&psniffer_mib_ctrl->MAC_ListLock); +#endif /* ALL_NET_EVENT */ +#endif /* CONFIG_SNIFFER_SUPPORT */ + Set_MonitorMode_Proc(pAd,"2"); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: psniffer_mib_ctrl->AgeOutTime=%lu, not start timer!\n",__FUNCTION__,psniffer_mib_ctrl->AgeOutTime)); + } + } + return TRUE; +} + +INT set_mib_passive_scan_proc(IN RTMP_ADAPTER *pAd, IN RTMP_STRING *arg) +{ + PSNIFFER_MIB_CTRL psniffer_mib_ctrl; + psniffer_mib_ctrl = &pAd->ApCfg.sniffer_mib_ctrl; + + ULONG scan_type = (ULONG) simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_ERROR, ("%s: ==>\n",__FUNCTION__)); + + if (scan_type == PASSIVE_TYPE) + { + psniffer_mib_ctrl->scan_type = PASSIVE_TYPE; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: not implement yet !, force set to PASSIVE_TYPE\n",__FUNCTION__)); + psniffer_mib_ctrl->scan_type = PASSIVE_TYPE; + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s: psniffer_mib_ctrl->scan_type=%u\n",__FUNCTION__,psniffer_mib_ctrl->scan_type)); + + return TRUE; +} + +INT set_mib_scan_interval_proc(IN RTMP_ADAPTER *pAd, IN RTMP_STRING *arg) +{ + PSNIFFER_MIB_CTRL psniffer_mib_ctrl; + psniffer_mib_ctrl = &pAd->ApCfg.sniffer_mib_ctrl; + ULONG interval = (ULONG) simple_strtol(arg, 0, 10); + + psniffer_mib_ctrl->AgeOutTime = interval; + + DBGPRINT(RT_DEBUG_ERROR, ("%s: ==> psniffer_mib_ctrl->AgeOutTime=%u\n",__FUNCTION__,psniffer_mib_ctrl->AgeOutTime)); + + return TRUE; +} + +INT set_mib_scan_scope_proc(IN RTMP_ADAPTER *pAd, IN RTMP_STRING *arg) +{ + PSNIFFER_MIB_CTRL psniffer_mib_ctrl; + psniffer_mib_ctrl = &pAd->ApCfg.sniffer_mib_ctrl; + ULONG scope = (ULONG) simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_ERROR, ("%s: ==>\n",__FUNCTION__)); + + if (scope == SCAN_ONE) + { + psniffer_mib_ctrl->scan_scope = SCAN_ONE; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: not implement yet !, force set to SCAN_ONE\n",__FUNCTION__)); + psniffer_mib_ctrl->scan_scope = SCAN_ONE; + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s: psniffer_mib_ctrl->scan_scope=%u\n",__FUNCTION__,psniffer_mib_ctrl->scan_scope)); + + return TRUE; +} + +INT set_mib_scan_channel_proc(IN RTMP_ADAPTER *pAd, IN RTMP_STRING *arg) +{ + PSNIFFER_MIB_CTRL psniffer_mib_ctrl; + psniffer_mib_ctrl = &pAd->ApCfg.sniffer_mib_ctrl; + ULONG channel; + + DBGPRINT(RT_DEBUG_ERROR, ("%s: ==>\n",__FUNCTION__)); + + channel = (ULONG) simple_strtol(arg, 0, 10); + if ((channel>0) && (channel <=14)) + { + psniffer_mib_ctrl->scan_channel = channel; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: ==> error channel=%u, force set to channel 0\n",__FUNCTION__,channel)); + psniffer_mib_ctrl->scan_channel = 0; // 0 means current channel + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s: psniffer_mib_ctrl->scan_channel = %u\n",__FUNCTION__,psniffer_mib_ctrl->scan_channel)); + + return TRUE; +} + +#endif /* SNIFFER_MIB_CMD */ + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/ate_agent.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/ate_agent.c new file mode 100644 index 000000000..c41179916 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/ate_agent.c @@ -0,0 +1,1231 @@ +/* + *************************************************************************** + * 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: + ate_agent.c +*/ + +#include "rt_config.h" + +/* CCK Mode */ +static CHAR CCKRateTable[] = {0, 1, 2, 3, 8, 9, 10, 11, -1}; + +/* OFDM Mode */ +static CHAR OFDMRateTable[] = {0, 1, 2, 3, 4, 5, 6, 7, -1}; + +/* HT Mixed Mode */ +static CHAR HTMIXRateTable[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 32, -1}; + +static CHAR 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}; + + +INT32 SetTxStop(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + return TRUE; +} + + +INT32 SetRxStop(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + return TRUE; +} + + +VOID ATE_QA_Statistics(RTMP_ADAPTER *pAd, RXWI_STRUC *pRxWI, RXINFO_STRUC *pRxInfo, PHEADER_802_11 pHeader) +{ + +} + +#ifdef DBG +INT32 SetEERead(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + return TRUE; +} + + +INT32 SetEEWrite(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + return TRUE; +} + + +INT32 SetBBPRead(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + return TRUE; +} + + +INT32 SetBBPWrite(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + return TRUE; +} + + +INT32 SetRFWrite(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + return TRUE; +} +#endif /* DBG */ + + +VOID EEReadAll(PRTMP_ADAPTER pAd, UINT16 *Data) +{ + UINT16 Offset = 0; + UINT16 Value; + + for (Offset = 0; Offset < (EEPROM_SIZE >> 1);) + { + RT28xx_EEPROM_READ16(pAd, (Offset << 1), Value); + Data[Offset] = Value; + Offset++; + } +} + + +INT32 SetATEDa(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + //ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + INT32 Octet; + RTMP_STRING *Value; + + DBGPRINT(RT_DEBUG_OFF, ("%s: Da = %s\n", __FUNCTION__, Arg)); + + /* 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, &ATECtrl->Addr1[Octet++], 1); +#endif /* CONFIG_AP_SUPPORT */ + + } + + /* sanity check */ + if (Octet != MAC_ADDR_LEN) + { + return FALSE; + } + +#ifdef CONFIG_AP_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("%s: (DA = %02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, + ATECtrl->Addr1[0], ATECtrl->Addr1[1], ATECtrl->Addr1[2], ATECtrl->Addr1[3], + ATECtrl->Addr1[4], ATECtrl->Addr1[5])); + +#endif /* CONFIG_AP_SUPPORT */ + + + return TRUE; +} + + +INT32 SetATESa(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + RTMP_STRING *Value; + INT32 Octet; + + DBGPRINT(RT_DEBUG_OFF, ("%s: Sa = %s\n", __FUNCTION__, Arg)); + + /* 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, &ATECtrl->Addr3[Octet++], 1); +#endif /* CONFIG_AP_SUPPORT */ + + } + + /* sanity check */ + if (Octet != MAC_ADDR_LEN) + { + return FALSE; + } + +#ifdef CONFIG_AP_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("%s: (SA = %02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, + ATECtrl->Addr3[0], ATECtrl->Addr3[1], ATECtrl->Addr3[2], ATECtrl->Addr3[3], + ATECtrl->Addr3[4], ATECtrl->Addr3[5])); +#endif /* CONFIG_AP_SUPPORT */ + + + return TRUE; +} + + +INT32 SetATEBssid(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + RTMP_STRING *Value; + INT32 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, &ATECtrl->Addr2[Octet++], 1); +#endif /* CONFIG_AP_SUPPORT */ + + } + + /* sanity check */ + if (Octet != MAC_ADDR_LEN) + { + return FALSE; + } + +#ifdef CONFIG_AP_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("%s: (BSSID = %02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, + ATECtrl->Addr2[0], ATECtrl->Addr2[1], ATECtrl->Addr2[2], ATECtrl->Addr2[3], + ATECtrl->Addr2[4], ATECtrl->Addr2[5])); +#endif /* CONFIG_AP_SUPPORT */ + + + return TRUE; +} + + +INT32 SetATEInitChan(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + return TRUE; +} + + +INT32 SetADCDump(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + return TRUE; +} + + +INT32 SetATETxPower0(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + CHAR Power; + INT32 Ret = 0; + + DBGPRINT(RT_DEBUG_OFF, ("%s: Power0 = %s\n", __FUNCTION__, Arg)); + + Power = simple_strtol(Arg, 0, 10); + + ATECtrl->TxPower0 = Power; + + Ret = ATEOp->SetTxPower0(pAd, Power); + + if (!Ret) + return TRUE; + else + return FALSE; +} + + +INT32 SetATETxPower1(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + CHAR Power; + INT32 Ret = 0; + + DBGPRINT(RT_DEBUG_OFF, ("%s: Power1 = %s\n", __FUNCTION__, Arg)); + + Power = simple_strtol(Arg, 0, 10); + + ATECtrl->TxPower1 = Power; + + Ret = ATEOp->SetTxPower1(pAd, Power); + + if (!Ret) + return TRUE; + else + return FALSE; +} + + +INT32 SetATETxPowerEvaluation(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + return TRUE; +} + + +INT32 SetATETxAntenna(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + CHAR Ant; + + DBGPRINT(RT_DEBUG_OFF, ("%s: Ant = %s\n", __FUNCTION__, Arg)); + + Ant = simple_strtol(Arg, 0, 10); + + Ret = ATEOp->SetTxAntenna(pAd, Ant); + + if (!Ret) + return TRUE; + else + return FALSE; +} + + +INT32 SetATERxAntenna(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + CHAR Ant; + + DBGPRINT(RT_DEBUG_OFF, ("%s: Ant = %s\n", __FUNCTION__, Arg)); + + Ant = simple_strtol(Arg, 0, 10); + + Ret = ATEOp->SetRxAntenna(pAd, Ant); + + if (!Ret) + return TRUE; + else + return FALSE; +} + + +INT32 Default_Set_ATE_TX_FREQ_OFFSET_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + return TRUE; +} + + +INT32 SetATETxFreqOffset(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + INT32 Ret = 0; + UINT32 FreqOffset; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + + DBGPRINT(RT_DEBUG_OFF, ("%s: FreqOffset = %s\n", __FUNCTION__, Arg)); + + FreqOffset = simple_strtol(Arg, 0, 10); + + Ret = ATEOp->SetTxFreqOffset(pAd, FreqOffset); + + if (!Ret) + return TRUE; + else + return FALSE; +} + + +INT32 Default_Set_ATE_TX_BW_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + return TRUE; +} + + +INT32 SetATETxLength(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + UINT32 TxLength; + + DBGPRINT(RT_DEBUG_OFF, ("%s: TxLength = %s\n", __FUNCTION__, Arg)); + + TxLength = simple_strtol(Arg, 0, 10); + + if ((TxLength < 24) || (TxLength > (MAX_FRAME_SIZE - 34/* == 2312 */))) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Out of range (%d), \ + it should be in range of 24~%d.\n", __FUNCTION__, ATECtrl->TxLength, + (MAX_FRAME_SIZE - 34/* == 2312 */))); + return FALSE; + } + else + { + ATECtrl->TxLength = TxLength; + + } + + return TRUE; +} + + +INT32 SetATETxCount(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + + DBGPRINT(RT_DEBUG_OFF, ("%s: TxCount = %s\n", __FUNCTION__, Arg)); + + ATECtrl->TxCount = simple_strtol(Arg, 0, 10); + + if (ATECtrl->TxCount == 0) + { +#ifdef RTMP_PCI_SUPPORT + ATECtrl->TxCount = 0xFFFFFFFF; +#endif /* RTMP_MAC_PCI */ + } + + return TRUE; +} + + +INT32 CheckMCSValid(PRTMP_ADAPTER pAd, UCHAR PhyMode, UCHAR Mcs) +{ + int Index; + PCHAR pRateTab = NULL; + + switch (PhyMode) + { + case MODE_CCK: + pRateTab = CCKRateTable; + break; + case MODE_OFDM: + pRateTab = OFDMRateTable; + break; + case MODE_HTMIX: + case MODE_HTGREENFIELD: + pRateTab = HTMIXRateTable; + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unrecognizable Tx Mode %d\n", __FUNCTION__, PhyMode)); + return -1; + break; + } + + Index = 0; + + while (pRateTab[Index] != -1) + { + if (pRateTab[Index] == Mcs) + return 0; + Index++; + } + + return -1; +} + + +INT32 SetATETxMcs(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + UCHAR Mcs, PhyMode = 0; + INT32 Ret = 0; + + DBGPRINT(RT_DEBUG_OFF, ("%s: Mcs = %s\n", __FUNCTION__, Arg)); + + PhyMode = ATECtrl->PhyMode; + + Mcs = simple_strtol(Arg, 0, 10); + + Ret = CheckMCSValid(pAd, PhyMode, Mcs); + + if (Ret != -1) + { + ATECtrl->Mcs = Mcs; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Out of range, refer to rate table.\n", __FUNCTION__)); + return FALSE; + } + + return TRUE; +} + + +INT32 SetATETxStbc(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + UCHAR Stbc; + + DBGPRINT(RT_DEBUG_OFF, ("%s: Stbc = %s\n", __FUNCTION__, Arg)); + + Stbc = simple_strtol(Arg, 0, 10); + + if (Stbc > 1) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Out of range (%d)\n", __FUNCTION__, Stbc)); + return FALSE; + } + else + { + ATECtrl->Stbc = Stbc; + } + + return TRUE; +} + + +INT32 SetATETxMode(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + UCHAR PhyMode; + + DBGPRINT(RT_DEBUG_OFF, ("%s: TxMode = %s\n", __FUNCTION__, Arg)); + + PhyMode = simple_strtol(Arg, 0, 10); + + if (PhyMode > MODE_HTGREENFIELD) + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_ATE_TX_MODE_Proc::Out of range.\nIt should be in range of 0~3\n")); + DBGPRINT(RT_DEBUG_ERROR, ("0: CCK, 1: OFDM, 2: HT_MIX, 3: HT_GREEN_FIELD\n")); + return FALSE; + } + else + { + ATECtrl->PhyMode = PhyMode; + } + + return TRUE; +} + + +INT32 SetATETxGi(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + UCHAR Sgi; + + DBGPRINT(RT_DEBUG_OFF, ("%s: Sgi = %s\n", __FUNCTION__, Arg)); + + Sgi = simple_strtol(Arg, 0, 10); + + if (Sgi > 1) + { + DBGPRINT(RT_DEBUG_ERROR, (":%s: Out of range (%d)\n", __FUNCTION__, Sgi)); + return FALSE; + } + else + { + ATECtrl->Sgi = Sgi; + } + + return TRUE; +} + + +INT32 SetATERxFer(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + return TRUE; +} + + +INT32 SetATETempSensor(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + return TRUE; +} + + +INT32 SetATEReadRF(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + + INT32 Ret = 0; + + Ret = ShowAllRF(pAd); + + if (!Ret) + return TRUE; + else + return FALSE; + +} + + +INT32 SetATELoadE2p(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + BOOLEAN Ret = FALSE; + RTMP_STRING *Src = EEPROM_BIN_FILE_NAME; + RTMP_OS_FD Srcf; + INT32 Retval; + UINT32 u4MaxBufSize = EEPROM_SIZE >> 1; + USHORT WriteEEPROM[u4MaxBufSize]; + + //USHORT WriteEEPROM[(EEPROM_SIZE >> 1)]; + INT32 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, (RTMP_STRING *)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) + { + UINT16 Index=0; + UINT16 Value=0; + INT32 E2pSize = 512;/* == 0x200 for PCI interface */ + UINT16 TempData=0; + + for (Index = 0 ; Index < (E2pSize >> 1); Index++) + { + /* "value" is especially for some compilers... */ + TempData = le2cpu16(WriteEEPROM[Index]); + Value = TempData; + RT28xx_EEPROM_WRITE16(pAd, (Index << 1), Value); + } + } +#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; +} + + +#ifdef RTMP_EFUSE_SUPPORT +INT32 SetATELoadE2pFromBuf(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + BOOLEAN Ret = FALSE; + UINT32 Value = (UINT32)simple_strtol(Arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("===> %s (Value=%d)\n\n", __FUNCTION__, Value)); + + if (Value > 0) + { +#if defined(RTMP_MAC_PCI) && defined(RTMP_PCI_SUPPORT) + { + UINT16 Index = 0; + UINT16 Value = 0; + INT32 E2PSize = 512;/* == 0x200 for PCI interface */ + UINT16 TempData = 0; + + for (Index = 0; Index < (E2PSize >> 1); Index++) + { + /* "value" is especially for some compilers... */ + TempData = le2cpu16(pAd->EEPROMImage[Index]); + Value = TempData; + RT28xx_EEPROM_WRITE16(pAd, (Index << 1), Value); + } + } +#else + +// rt_ee_write_all(pAd, pAd->EEPROMImage); +#endif /* defined(RTMP_MAC_PCI) && defined(RTMP_PCI_SUPPORT) */ + Ret = TRUE; + + } + + DBGPRINT(RT_DEBUG_OFF, ("<=== %s (Ret=%d)\n", __FUNCTION__, Ret)); + + return Ret; + +} +#endif /* RTMP_EFUSE_SUPPORT */ + + +INT32 SetATEReadE2p(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + UINT16 Buffer[EEPROM_SIZE >> 1]; + UINT16 *p; + int i; + + EEReadAll(pAd, (UINT16 *)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; +} + + +INT32 SetATEAutoAlc(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + return TRUE; +} + + +INT32 SetATEIpg(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + return TRUE; +} + + +INT32 SetATEPayload(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + RTMP_STRING *Value; + + Value = Arg; + + /* only one octet acceptable */ + if (strlen(Value) != 2) + return FALSE; + + AtoH(Value, &(ATECtrl->Payload), 1); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_ATE_Payload_Proc (repeated pattern = 0x%2x)\n", ATECtrl->Payload)); + + return TRUE; +} + + +INT32 SetATEFixedPayload(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + RTMP_STRING *Value; + + Value = Arg; + + Value = (RTMP_STRING *)simple_strtol(Arg, 0, 10); + + if (Value == 0) + ATECtrl->bFixedPayload = FALSE; + else + ATECtrl->bFixedPayload = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: (Fixed Payload = %d)\n", __FUNCTION__, + ATECtrl->bFixedPayload)); + + return TRUE; +} + + +INT32 SetATETtr(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + return TRUE; +} + + +INT32 SetATEShow(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + RTMP_STRING *Mode_String = NULL; + RTMP_STRING *TxMode_String = NULL; + + switch (ATECtrl->Mode) + { + case (fATE_IDLE): + Mode_String = "ATESTART"; + break; + case (fATE_EXIT): + Mode_String = "ATESTOP"; + break; + 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)); + DBGPRINT(RT_DEBUG_OFF, ("TxPower0 = %d\n", ATECtrl->TxPower0)); + DBGPRINT(RT_DEBUG_OFF, ("TxPower1 = %d\n", ATECtrl->TxPower1)); + DBGPRINT(RT_DEBUG_OFF, ("TxAntennaSel = %d\n", ATECtrl->TxAntennaSel)); + DBGPRINT(RT_DEBUG_OFF, ("RxAntennaSel = %d\n", ATECtrl->RxAntennaSel)); + DBGPRINT(RT_DEBUG_OFF, ("BBPCurrentBW = %u\n", ATECtrl->BW)); + DBGPRINT(RT_DEBUG_OFF, ("GI = %u\n", ATECtrl->Sgi)); + DBGPRINT(RT_DEBUG_OFF, ("MCS = %u\n", ATECtrl->Mcs)); + + switch (ATECtrl->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", + ATECtrl->Addr1[0], ATECtrl->Addr1[1], ATECtrl->Addr1[2], ATECtrl->Addr1[3], ATECtrl->Addr1[4], ATECtrl->Addr1[5])); + DBGPRINT(RT_DEBUG_OFF, ("Addr2 = %02x:%02x:%02x:%02x:%02x:%02x\n", + ATECtrl->Addr2[0], ATECtrl->Addr2[1], ATECtrl->Addr2[2], ATECtrl->Addr2[3], ATECtrl->Addr2[4], ATECtrl->Addr2[5])); + DBGPRINT(RT_DEBUG_OFF, ("Addr3 = %02x:%02x:%02x:%02x:%02x:%02x\n", + ATECtrl->Addr3[0], ATECtrl->Addr3[1], ATECtrl->Addr3[2], ATECtrl->Addr3[3], ATECtrl->Addr3[4], ATECtrl->Addr3[5])); + DBGPRINT(RT_DEBUG_OFF, ("Channel = %u\n", ATECtrl->Channel)); + DBGPRINT(RT_DEBUG_OFF, ("TxLength = %u\n", ATECtrl->TxLength)); + DBGPRINT(RT_DEBUG_OFF, ("TxCount = %u\n", ATECtrl->TxCount)); + DBGPRINT(RT_DEBUG_OFF, ("RFFreqOffset = %u\n", ATECtrl->RFFreqOffset)); + DBGPRINT(RT_DEBUG_OFF, ("IPG=%u\n", ATECtrl->IPG)); + DBGPRINT(RT_DEBUG_OFF, ("Payload=0x%02x\n", ATECtrl->Payload)); + + return TRUE; +} + + +INT32 SetATEHelp(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + DBGPRINT(RT_DEBUG_OFF, ("ATE=ATESTART, ATESTOP, TXCONT, TXCARR, TXCARS, TXFRAME, RXFRAME\n")); + 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\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")); + DBGPRINT(RT_DEBUG_OFF, ("ATETXANT, set TX antenna. 0:all, 1:antenna one, 2:antenna two.\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATERXANT, set RX antenna.0:all, 1:antenna one, 2:antenna two, 3:antenna three.\n")); + 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, 4:VHT, 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")); + DBGPRINT(RT_DEBUG_OFF, ("ATELDE2P, load EEPROM from .bin file.\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATERE2P, display all EEPROM content.\n")); + 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")); + DBGPRINT(RT_DEBUG_OFF, ("ATESHOW, display all parameters of ATE.\n")); + DBGPRINT(RT_DEBUG_OFF, ("ATEHELP, online help.\n")); + + return TRUE; +} + + +VOID ATESampleRssi(PRTMP_ADAPTER pAd, RXWI_STRUC *pRxWI) +{ +} + + +#ifdef RTMP_PCI_SUPPORT +PNDIS_PACKET ATEPayloadInit(RTMP_ADAPTER *pAd, UINT32 TxIdx) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + RTMP_TX_RING *pTxRing = &pAd->TxRing[QID_AC_BE]; + PNDIS_PACKET pPacket = pTxRing->Cell[TxIdx].pNdisPacket; + PUCHAR pDest = (PUCHAR)ATECtrl->AteAllocVa[TxIdx]; + UINT32 Pos = 0; + + GET_OS_PKT_LEN(pPacket) = ATECtrl->TxLength - ATECtrl->HLen; + + DBGPRINT(RT_DEBUG_TRACE, ("%s, %d, %d, %d\n", __FUNCTION__, GET_OS_PKT_LEN(pPacket), + ATECtrl->TxLength, ATECtrl->HLen)); + + /* prepare frame payload */ + for (Pos = 0; Pos < GET_OS_PKT_LEN(pPacket); Pos++) + { + if (ATECtrl->bFixedPayload) + { + /* default payload is 0xA5 */ + pDest[Pos] = ATECtrl->Payload; + } + else + { + pDest[Pos] = RandomByte(pAd); + } + } + + return pPacket; +} +#endif /* RTMP_MAC_PCI */ + +#ifdef RTMP_PCI_SUPPORT +INT32 ATEPayloadAlloc(PRTMP_ADAPTER pAd, UINT32 Index) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + NDIS_PHYSICAL_ADDRESS AllocPa; + + ATECtrl->pAtePacket[Index] = RTMP_AllocateRxPacketBuffer(pAd, ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + ATECtrl->TxLength, FALSE, &ATECtrl->AteAllocVa[Index], &AllocPa); + + if (ATECtrl->pAtePacket[Index] == NULL) + { + ATECtrl->TxCount = 0; + DBGPRINT(RT_DEBUG_ERROR, ("%s : fail to alloc packet space.\n", + __FUNCTION__)); + return (NDIS_STATUS_RESOURCES); + } + + return (NDIS_STATUS_SUCCESS); +} +#endif /* RTMP_MAC_PCI */ + +//#ifdef RTMP_PCI_SUPPORT + +INT32 ATEInit(RTMP_ADAPTER *pAd) +{ + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + + NdisZeroMemory(ATECtrl, sizeof(*ATECtrl)); + + ATECtrl->Mode = ATE_STOP; + + ATECtrl->TxCount = 0xFFFFFFFF; + ATECtrl->Payload = 0xAA; + ATECtrl->bFixedPayload = 1; + ATECtrl->IPG = 200;/* 200 : sync with QA */ + ATECtrl->TxLength = 1058;/* 1058 : sync with QA */ + ATECtrl->BW = BW_20; + ATECtrl->PhyMode = MODE_OFDM; + ATECtrl->Mcs = 7; + ATECtrl->Sgi = 0;/* LONG GI : 800 ns*/ + ATECtrl->Channel = 1; + ATECtrl->TxAntennaSel = 1; + ATECtrl->RxAntennaSel = 0; + + ATECtrl->QID = QID_AC_BE; + ATECtrl->Addr1[0] = 0x00; + ATECtrl->Addr1[1] = 0x11; + ATECtrl->Addr1[2] = 0x22; + ATECtrl->Addr1[3] = 0xAA; + ATECtrl->Addr1[4] = 0xBB; + ATECtrl->Addr1[5] = 0xCC; + + NdisMoveMemory(ATECtrl->Addr2, ATECtrl->Addr1, MAC_ADDR_LEN); + NdisMoveMemory(ATECtrl->Addr3, ATECtrl->Addr1, MAC_ADDR_LEN); + ATECtrl->bQAEnabled = FALSE; + ATECtrl->bQATxStart = FALSE; + ATECtrl->bQARxStart = FALSE; + ATECtrl->TxDoneCount = 0; + + + ATECtrl->TemplateFrame = TemplateFrame; + +#ifdef MT_MAC + Ret = MT_ATEInit(pAd); +#endif + +#ifdef CONFIG_QA + ATECtrl->TxStatus = 0; +#endif + + return Ret; +} + + +INT32 ATEExit(RTMP_ADAPTER *pAd) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + + return Ret; +} + +VOID ATEPeriodicExec(PVOID SystemSpecific1, PVOID FunctionContext, + PVOID SystemSpecific2, PVOID SystemSpecific3) +{ + +} + + +INT32 SetATE( + PRTMP_ADAPTER pAd, + RTMP_STRING *Arg) +{ + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + + DBGPRINT(RT_DEBUG_OFF, ("%s: Arg = %s\n", __FUNCTION__, Arg)); + + if (!strcmp(Arg, "ATESTART") && (ATECtrl->Mode != ATE_START)) /* support restart w/o ATESTOP */ + { + Ret = ATEOp->ATEStart(pAd); + } + else if (!strcmp(Arg, "ATESTOP") && (ATECtrl->Mode & ATE_START)) + { + Ret = ATEOp->ATEStop(pAd); + } + else if (!strcmp(Arg, "APSTOP") && (ATECtrl->Mode == ATE_STOP)) + { + Ret = ATEOp->ATEStart(pAd); + } + else if (!strcmp(Arg, "APSTART") && (ATECtrl->Mode & ATE_START)) + { + Ret = ATEOp->ATEStop(pAd); + } + else if (!strcmp(Arg, "TXFRAME") && (ATECtrl->Mode & ATE_START)) + { + Ret = ATEOp->StartTx(pAd); + } + else if (!strcmp(Arg, "RXFRAME") && (ATECtrl->Mode & ATE_START)) + { + Ret = ATEOp->StartRx(pAd); + } + else if (!strcmp(Arg, "TXSTOP") && (ATECtrl->Mode & ATE_START)) + { + Ret = ATEOp->StopTx(pAd, ATECtrl->Mode); + } + else if (!strcmp(Arg, "RXSTOP") && (ATECtrl->Mode & ATE_START)) + { + Ret = ATEOp->StopRx(pAd); + } + else if (!strcmp(Arg, "TXCONT") && (ATECtrl->Mode & ATE_START)) + { + /* 0: All 1:TX0 2:TX1 */ + switch(ATECtrl->TxAntennaSel){ + case 0: + Ret = ATEOp->StartContinousTx(pAd, 2); + break; + case 1: + Ret = ATEOp->StartContinousTx(pAd, 0); + break; + case 2: + Ret = ATEOp->StartContinousTx(pAd, 1); + break; + } + ATECtrl->Mode |= ATE_TXCONT; + } + else if (!strcmp(Arg, "TXCARRSUPP") && (ATECtrl->Mode & ATE_START)) + { + INT32 pwr1 = 0xf; + INT32 pwr2 = 0; + /* 0: All 1:TX0 2:TX1 */ + switch(ATECtrl->TxAntennaSel){ + case 0: + DBGPRINT(RT_DEBUG_TRACE, ("%s: not support two 2 TXCARRSUPP\n",__FUNCTION__)); + break; + case 1: + if(ATECtrl->TxPower0>30) + pwr2 = (ATECtrl->TxPower0 - 30)<<1; + else{ + pwr1 = (ATECtrl->TxPower0 & 0x1e) >> 1; + pwr2 = (ATECtrl->TxPower0 & 0x01) << 1; + } + ATEOp->StartTxTone(pAd, WF0_TX_TWO_TONE_5M); + DBGPRINT(RT_DEBUG_TRACE, ("%s: TXCARRSUPP, TxPower0:0x%x, pwr1:0x%x, pwr2:0x%x\n",__FUNCTION__,ATECtrl->TxPower0, pwr1, pwr2)); + break; + case 2: + if(ATECtrl->TxPower1>30) + pwr2 = (ATECtrl->TxPower1 - 30)<<1; + else{ + pwr1 = (ATECtrl->TxPower1 & 0x1e) >> 1; + pwr2 = (ATECtrl->TxPower1 & 0x01) << 1; + } + ATEOp->StartTxTone(pAd, WF1_TX_TWO_TONE_5M); + DBGPRINT(RT_DEBUG_TRACE, ("%s: TXCARRSUPP, TxPower1:0x%x, pwr1:0x%x, pwr2:0x%x\n",__FUNCTION__,ATECtrl->TxPower1, pwr1, pwr2)); + break; + } + ATEOp->SetTxTonePower(pAd, pwr1, pwr2); + ATECtrl->Mode |= ATE_TXCARRSUPP; + } + else if (!strcmp(Arg, "TXTONEPWR") && (ATECtrl->Mode & ATE_START)) + { + ATEOp->SetTxTonePower(pAd, ATECtrl->TxPower0, ATECtrl->TxPower1); + } + else if (!strcmp(Arg, "TXCARR") && (ATECtrl->Mode & ATE_START)) + { + INT32 pwr1 = 0xf; + INT32 pwr2 = 0; + switch(ATECtrl->TxAntennaSel){ + case 0: + DBGPRINT(RT_DEBUG_OFF, ("%s: not support two 2 TXCARR\n",__FUNCTION__)); + break; + case 1: + if(ATECtrl->TxPower0>30) + pwr2 = (ATECtrl->TxPower0 - 30)<<1; + else{ + pwr1 = (ATECtrl->TxPower0 & 0x1e) >> 1; + pwr2 = (ATECtrl->TxPower0 & 0x01) << 1; + } + ATEOp->StartTxTone(pAd, WF0_TX_ONE_TONE_DC); + DBGPRINT(RT_DEBUG_TRACE, ("%s: TXCARR, TxPower0:0x%x, pwr1:0x%x, pwr2:0x%x\n",__FUNCTION__,ATECtrl->TxPower0, pwr1, pwr2)); + break; + case 2: + if(ATECtrl->TxPower1>30) + pwr2 = (ATECtrl->TxPower1 - 30)<<1; + else{ + pwr1 = (ATECtrl->TxPower1 & 0x1e) >> 1; + pwr2 = (ATECtrl->TxPower1 & 0x01) << 1; + } + ATEOp->StartTxTone(pAd, WF1_TX_ONE_TONE_DC); + DBGPRINT(RT_DEBUG_TRACE, ("%s: TXCARR, TxPower1:0x%x, pwr1:0x%x, pwr2:0x%x\n",__FUNCTION__,ATECtrl->TxPower1, pwr1, pwr2)); + break; + } + ATEOp->SetTxTonePower(pAd, pwr1, pwr2); + ATECtrl->Mode |= ATE_TXCARR; + } + else + { + DBGPRINT(RT_DEBUG_OFF, ("%s: do nothing(param = (%s), mode = (%d))\n", + __FUNCTION__, Arg, ATECtrl->Mode)); + } + + if (!Ret) + return TRUE; + else + return FALSE; +} + + +INT32 SetATEChannel( + PRTMP_ADAPTER pAd, + RTMP_STRING *Arg) +{ + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + INT16 Channel; + + DBGPRINT(RT_DEBUG_OFF, ("%s: Channel = %s\n", __FUNCTION__, Arg)); + + Channel = simple_strtol(Arg, 0, 10); + + ATECtrl->Channel = Channel; + + if (ATECtrl->BW == BW_20) + ATECtrl->ControlChl = ATECtrl->Channel; + else if (ATECtrl->BW == BW_40) + ATECtrl->ControlChl = ATECtrl->Channel - 2; + + Ret = ATEOp->SetChannel(pAd, Channel); + + if (!Ret) + return TRUE; + else + return FALSE; +} + + +INT32 SetATETxBw( + PRTMP_ADAPTER pAd, + RTMP_STRING *Arg) +{ + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + INT16 BW; + + DBGPRINT(RT_DEBUG_OFF, ("%s: Bw = %s\n", __FUNCTION__, Arg)); + + BW = simple_strtol(Arg, 0, 10); + + ATECtrl->BW = BW; + + if (ATECtrl->BW == BW_20) + ATECtrl->ControlChl = ATECtrl->Channel; + else if (ATECtrl->BW == BW_40){ + if(ATECtrl->Channel <= 2){ + ATECtrl->ControlChl = ATECtrl->Channel; + ATECtrl->Channel += 2; + }else if(ATECtrl->Channel > 12){ + ATECtrl->ControlChl = ATECtrl->Channel; + ATECtrl->Channel -= 2; + }else{ + ATECtrl->ControlChl = ATECtrl->Channel - 2; + } + } + + Ret = ATEOp->SetBW(pAd, BW); + + if (!Ret) + return TRUE; + else + return FALSE; +} diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/ate.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/ate.h new file mode 100644 index 000000000..699d4d342 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/ate.h @@ -0,0 +1,243 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of MediaTek. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + ate.h +*/ + +#ifndef __ATE_H__ +#define __ATE_H__ + +#define ATE_ON(_p) ((((_p)->ATECtrl.Mode) & ATE_START) == ATE_START) +INT32 ATEInit(struct _RTMP_ADAPTER *pAd); +INT32 ATEExit(struct _RTMP_ADAPTER *pAd); + +/* + Use bitmap to allow coexist of ATE_TXFRAME + and ATE_RXFRAME(i.e.,to support LoopBack mode). +*/ +#define fATE_IDLE (1 << 0) +#define fATE_TX_ENABLE (1 << 1) +#define fATE_RX_ENABLE (1 << 2) +#define fATE_TXCONT_ENABLE (1 << 3) +#define fATE_TXCARR_ENABLE (1 << 4) +#define fATE_TXCARRSUPP_ENABLE (1 << 5) +#define fATE_RESERVED_1 (1 << 6) +#define fATE_RFTEST_ENABLE (1 << 7) +#define fATE_EXIT (1 << 8) + +/* 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)) + + +/* 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) + + +#define ATE_RFTEST (fATE_RFTEST_ENABLE) + +#define BULK_OUT_LOCK(pLock, IrqFlags) \ + if(1 /*!(in_interrupt() & 0xffff0000)*/) \ + RTMP_IRQ_LOCK((pLock), IrqFlags); + +#define BULK_OUT_UNLOCK(pLock, IrqFlags) \ + if(1 /*!(in_interrupt() & 0xffff0000)*/) \ + RTMP_IRQ_UNLOCK((pLock), IrqFlags); + +/* ContiTxTone */ +#define WF0_TX_ONE_TONE_5M 0x0 +#define WF0_TX_TWO_TONE_5M 0x1 +#define WF1_TX_ONE_TONE_5M 0x2 +#define WF1_TX_TWO_TONE_5M 0x3 +#define WF0_TX_ONE_TONE_10M 0x4 +#define WF1_TX_ONE_TONE_10M 0x5 +#define WF0_TX_ONE_TONE_DC 0x6 +#define WF1_TX_ONE_TONE_DC 0x7 + +struct _RTMP_ADAPTER; +struct _RX_BLK; + +typedef struct _ATE_OPERATION { + INT32 (*ATEStart)(struct _RTMP_ADAPTER *pAd); + INT32 (*ATEStop)(struct _RTMP_ADAPTER *pAd); + INT32 (*StartTx)(struct _RTMP_ADAPTER *pAd); + INT32 (*StartRx)(struct _RTMP_ADAPTER *pAd); + INT32 (*StopTx)(struct _RTMP_ADAPTER *pAd, UINT32 Mode); + INT32 (*StopRx)(struct _RTMP_ADAPTER *pAd); + INT32 (*SetTxPath)(struct _RTMP_ADAPTER *pAd); + INT32 (*SetRxPath)(struct _RTMP_ADAPTER *pAd); + INT32 (*SetTxPower0)(struct _RTMP_ADAPTER *pAd, CHAR Value); + INT32 (*SetTxPower1)(struct _RTMP_ADAPTER *pAd, CHAR Value); + INT32 (*SetTxAntenna)(struct _RTMP_ADAPTER *pAd, CHAR Ant); + INT32 (*SetRxAntenna)(struct _RTMP_ADAPTER *pAd, CHAR Ant); + INT32 (*SetTxFreqOffset)(struct _RTMP_ADAPTER *pAd, UINT32 FreqOffset); + INT32 (*SetChannel)(struct _RTMP_ADAPTER *pAd, INT16 Value); + INT32 (*SetBW)(struct _RTMP_ADAPTER *pAd, INT16 Value); + INT32 (*SampleRssi)(struct _RTMP_ADAPTER *pAd, struct _RX_BLK *pRxBlk); + INT32 (*SetAIFS)(struct _RTMP_ADAPTER *pAd, CHAR Value); + INT32 (*SetTSSI)(struct _RTMP_ADAPTER *pAd, CHAR WFSel, CHAR Setting); + INT32 (*SetDPD)(struct _RTMP_ADAPTER *pAd, CHAR WFSel, CHAR Setting); + INT32 (*StartTxTone)(struct _RTMP_ADAPTER *pAd, UINT32 Mode); + INT32 (*SetTxTonePower)(struct _RTMP_ADAPTER *pAd, INT32 pwr1, INT pwr2); + INT32 (*StopTxTone)(struct _RTMP_ADAPTER *pAd); + INT32 (*StartContinousTx)(struct _RTMP_ADAPTER *pAd, CHAR WFSel); + INT32 (*RfRegWrite)(struct _RTMP_ADAPTER *pAd, UINT32 WFSel, UINT32 Offset, UINT32 Value); + INT32 (*RfRegRead)(struct _RTMP_ADAPTER *pAd, UINT32 WFSel, UINT32 Offset, UINT32 *Value); + INT32 (*GetFWInfo)(struct _RTMP_ADAPTER *pAd, UCHAR *FWInfo); +} ATE_OPERATION; + +typedef struct _ATE_CTRL { + ATE_OPERATION *ATEOp; +#ifdef RTMP_MAC_PCI + PVOID AteAllocVa[TX_RING_SIZE]; + PNDIS_PACKET pAtePacket[TX_RING_SIZE]; +#endif /* RTMP_MAC_PCI */ + UINT32 Mode; + BOOLEAN PassiveMode; + CHAR TxPower0; + CHAR TxPower1; + CHAR TxPower2; + 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; + USHORT TxInfoLen; + USHORT TxWILen; + USHORT QID; + UCHAR *TemplateFrame; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + UCHAR Addr3[MAC_ADDR_LEN]; + UCHAR Channel; + UCHAR ControlChl; + UCHAR BW; + UCHAR PhyMode; + UCHAR Stbc; + UCHAR Sgi; + UCHAR Mcs; + UCHAR Preamble; + UCHAR Payload; /* Payload pattern */ + BOOLEAN bFixedPayload; + 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 */ + /* Used when using QA Tool */ + 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 bAutoVcoCal; /* Set Auto VCO periodic calibration. */ + BOOLEAN bLowTemperature; /* Trigger Temperature Sensor */ + BOOLEAN bTestTimeReduction; /* Set ATE test time reduction. */ +#ifdef RTMP_MAC_PCI + BOOLEAN bFWLoading; /* Reload firmware when ATE is done. */ +#endif /* RTMP_MAC_PCI */ + UINT32 RxTotalCnt; + UINT32 RxCntPerSec; + + CHAR LastSNR0; /* last received SNR */ + CHAR LastSNR1; /* last received SNR for 2nd antenna */ + CHAR LastSNR2; + 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 CONFIG_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; + UINT32 SNR2; + INT32 BF_SNR[3]; /* Last RXWI BF SNR. Units=0.25 dB */ + /* TxStatus : 0 --> task is idle, 1 --> task is running */ + UCHAR TxStatus; + UINT32 RCPI0; + UINT32 RCPI1; + UINT32 RCPI2; + UINT32 FreqOffsetFromRx; + UINT32 RxMacFCSErrCount; + UINT32 RxMacMdrdyCount; + UINT32 thermal_val; +#endif + RTMP_OS_COMPLETION cmd_done; + ULONG cmd_expire; + RALINK_TIMER_STRUCT PeriodicTimer; + ULONG OneSecPeriodicRound; + ULONG PeriodicRound; + OS_NDIS_SPIN_LOCK TssiSemLock; + UINT32 tssi0_wf0_cr; + UINT32 tssi0_wf1_cr; + UINT32 tssi1_wf0_cr; + UINT32 tssi1_wf1_cr; + UINT32 phy_mux_27; + UINT32 rmac_pcr1; + UINT32 rmac_pcr; +} ATE_CTRL; +VOID RtmpDmaEnable(RTMP_ADAPTER *pAd, INT Enable); + + +VOID ATE_RTUSBBulkOutDataPacket( + IN PRTMP_ADAPTER pAd, + IN UCHAR BulkOutPipeId); + +VOID ATE_RTUSBCancelPendingBulkInIRP( + IN PRTMP_ADAPTER pAd); + + +#endif /* __ATE_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/ate_agent.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/ate_agent.h new file mode 100644 index 000000000..f6cec1df7 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/ate_agent.h @@ -0,0 +1,83 @@ +/* + *************************************************************************** + * 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: + ate_agent.h +*/ + +#ifndef __ATE_AGENT_H__ +#define __ATE_AGENT_H__ + +struct _RTMP_ADAPTER; + +INT32 SetTxStop(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetRxStop(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 RtmpDoAte(struct _RTMP_ADAPTER *pAd, RTMP_IOCTL_INPUT_STRUCT *wrq, RTMP_STRING *wrq_name); +VOID ATE_QA_Statistics(struct _RTMP_ADAPTER *pAd, RXWI_STRUC *pRxWI, RXINFO_STRUC *pRxInfo, PHEADER_802_11 pHeader); + +#ifdef DBG +INT32 SetEERead(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetEEWrite(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetBBPRead(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetBBPWrite(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetRFWrite(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +#endif /* DBG */ +VOID rt_ee_read_all(struct _RTMP_ADAPTER *pAd, UINT16 *Data); +VOID rt_ee_write_all(struct _RTMP_ADAPTER pAd, UINT16 *Data); +VOID rt_ee_write_bulk(struct _RTMP_ADAPTER pAd, UINT16 *Data, UINT16 offset, UINT16 length); +INT32 SetATEDa(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATESa(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATEBssid(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATEInitChan(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetADCDump(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATETxPower0(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATETxPower1(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATETxPowerEvaluation(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATETxAntenna(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATERxAntenna(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 Default_Set_ATE_TX_FREQ_OFFSET_Proc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATETxFreqOffset(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 Default_Set_ATE_TX_BW_Proc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATETxLength(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATETxCount(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATETxMcs(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATETxStbc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATETxMode(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATETxGi(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATERxFer(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATEReadRF(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATELoadE2p(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +#ifdef RTMP_EFUSE_SUPPORT +INT32 SetATELoadE2pFromBuf(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +#endif /* RTMP_EFUSE_SUPPORT */ +INT32 SetATEReadE2p(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATEAutoAlc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATETxGi(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATETempSensor(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATEIpg(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATEPayload(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATEFixedPayload(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATETtr(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATEShow(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATEHelp(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +VOID ATESampleRssi(struct _RTMP_ADAPTER *pAd, RXWI_STRUC *pRxWI); +VOID ATEPeriodicExec(PVOID SystemSpecific1, PVOID FunctionContext, + PVOID SystemSpecific2, PVOID SystemSpecific3); +INT32 SetATE(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATEChannel(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 SetATETxBw(struct _RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +INT32 MT_ATEInit(struct _RTMP_ADAPTER *pAd); +PNDIS_PACKET ATEPayloadInit(struct _RTMP_ADAPTER *pAd, UINT32 TxIdx); +INT32 ATEPayloadAlloc(struct _RTMP_ADAPTER *pAd, UINT32 Index); +VOID EEReadAll(struct _RTMP_ADAPTER *pAd, UINT16 *Data); +#endif + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/qa_agent.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/qa_agent.h new file mode 100644 index 000000000..cdf886c29 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/qa_agent.h @@ -0,0 +1,82 @@ +/* + *************************************************************************** + * 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: + qa_agent.h +*/ + +#ifndef __QA_AGENT_H__ +#define __QA_AGENT_H__ + +#define HQA_CMD_MAGIC_NO 0x18142880 + +/* RX STAT */ +#define HQA_RX_STAT_MACFCSERRCNT 0x1 +#define HQA_RX_STAT_MAC_MDRDYCNT 0x2 +#define HQA_RX_STAT_PHY_MDRDYCNT 0x3 +#define HQA_RX_STAT_PHY_FCSERRCNT 0x4 +#define HQA_RX_STAT_PD 0x5 +#define HQA_RX_STAT_CCK_SIG_SFD 0x6 +#define HQA_RX_STAT_OFDM_SIG_TAG 0x7 +#define HQA_RX_STAT_RSSI 0x8 +#define HQA_RX_RESET_PHY_COUNT 0x9 + +/* FW Event Callback */ +VOID HQA_GetThermalValue_CB(struct cmd_msg *msg, char *Data, UINT16 Len); + + +typedef struct _HQA_CMD_FRAME { + UINT32 MagicNo; + UINT16 Type; + UINT16 Id; + UINT16 Length; + UINT16 Sequence; + UCHAR Data[2048]; +} __attribute__((packed))HQA_CMD_FRAME; + +typedef INT32 (*HQA_CMD_HANDLER)( + struct _RTMP_ADAPTER *pAd, + RTMP_IOCTL_INPUT_STRUCT *wrq, + HQA_CMD_FRAME *HqaCmdFrame); + +typedef struct _HQA_CMD_TABLE{ + HQA_CMD_HANDLER *CmdSet; + UINT32 CmdSetSize; + UINT32 CmdOffset; +} HQA_CMD_TABLE; + +typedef struct _HQA_RX_STAT{ + UINT32 MacFCSErr; + UINT32 MacMdrdy; + UINT32 FCSErr_CCK; + UINT32 FCSErr_OFDM; + UINT32 CCK_PD; + UINT32 OFDM_PD; + UINT32 CCK_SIG_Err; + UINT32 CCK_SFD_Err; + UINT32 OFDM_SIG_Err; + UINT32 OFDM_TAG_Err; + UINT32 WB_RSSSI0; + UINT32 IB_RSSSI0; + UINT32 WB_RSSSI1; + UINT32 IB_RSSSI1; + UINT32 PhyMdrdyCCK; + UINT32 PhyMdrdyOFDM; + UINT32 DriverRxCount; + UINT32 RCPI0; + UINT32 RCPI1; + UINT32 FreqOffsetFromRX; + UINT32 RSSI0; + UINT32 RSSI1; +} __attribute__((packed))HQA_RX_STAT; + +#endif /* __QA_AGENT_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/rt_ate.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/rt_ate.h new file mode 100644 index 000000000..396bd6ad3 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/rt_ate.h @@ -0,0 +1,799 @@ +/* + *************************************************************************** + * 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 CONFIG_ATE +#ifndef STATS_COUNT_SUPPORT +#error "For ATE support, please set HAS_ATE=y and HAS_STATS_COUNT=y." +#endif /* !STATS_COUNT_SUPPORT */ +#endif /* CONFIG_ATE */ + +#if defined(RTMP_MAC) || defined(RLT_MAC) +#include "mac/mac_ral/rtmp_mac.h" +#elif defined(MT_MAC) +#include "mac/mac_mt/mt_mac.h" +#endif +#include "phy/phy.h" + +// TODO: shiang-6590, remove it after ATE code is re-organized!! +#define BBP_R1 1 +#define BBP_R3 3 +#define BBP_R4 4 +#define BBP_R21 21 +#define BBP_R22 22 +#define BBP_R24 24 +#define BBP_R27 27 +#define BBP_R50 50 +#define BBP_R51 51 +#define BBP_R52 52 +#define BBP_R60 60 +#define BBP_R66 66 +#define BBP_R69 69 +#define BBP_R70 70 +#define BBP_R174 174 +#define BBP_R182 182 +// TODO: ---End + +typedef struct _ATE_CHIP_STRUCT { + /* functions */ + VOID (*ChannelSwitch)(PRTMP_ADAPTER pAd); + INT (*TxPwrHandler)(PRTMP_ADAPTER pAd, char index); + INT (*TxPwrEvaluation)(PRTMP_ADAPTER pAd); + INT (*TssiCalibration)(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + INT (*ExtendedTssiCalibration)(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + VOID (*RxVGAInit)(PRTMP_ADAPTER pAd); + VOID (*AsicSetTxRxPath)(PRTMP_ADAPTER pAd); + VOID (*AdjustTxPower)(PRTMP_ADAPTER pAd); + VOID (*AsicExtraPowerOverMAC)(PRTMP_ADAPTER pAd); + VOID (*AsicCalibration)(PRTMP_ADAPTER pAd, UCHAR ate_mode); + VOID (*TemperCompensation)(RTMP_ADAPTER *pAd); + + /* command handlers */ + INT (*Set_BW_Proc)(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + INT (*Set_FREQ_OFFSET_Proc)(RTMP_ADAPTER *pAd, RTMP_STRING *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; +#ifdef RTMP_MAC_PCI + PVOID AteAllocVa[TX_RING_SIZE]; + PNDIS_PACKET pAtePacket[TX_RING_SIZE]; +#endif /* RTMP_MAC_PCI */ + 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; + USHORT TxInfoLen; + USHORT TxWILen; + TXINFO_STRUC TxInfo; /* TxInfo */ + 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 */ + BOOLEAN bFixedPayload; + 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 bAutoVcoCal; /* Set Auto VCO periodic calibration. */ + BOOLEAN bLowTemperature; /* Trigger Temperature Sensor */ + BOOLEAN bTestTimeReduction; /* Set ATE test time reduction. */ +#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 */ +#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 CONFIG_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; +#ifdef DOT11_VHT_AC + UCHAR vht_nss; +#endif /* DOT11_VHT_AC */ +#endif /* CONFIG_QA */ + 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_ASIC_CALIBRATION(__pAd, __ate_mode) \ +do { \ + if (__pAd->ate.pChipStruct->AsicCalibration != NULL) \ + __pAd->ate.pChipStruct->AsicCalibration(__pAd, __ate_mode); \ +} while (0) + + +#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. */ +#ifdef RTMP_BBP +#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))); \ +} +#endif /* RTMP_BBP */ + +/* 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) + +#define ATE_CHIP_SET_TX_RX_PATH(__pAd) \ + if (__pAd->ate.pChipStruct->AsicSetTxRxPath != NULL) \ + __pAd->ate.pChipStruct->AsicSetTxRxPath(__pAd) + + +#ifdef RTMP_MAC_PCI +#define ATEPCIReadBBPRegister(_A, _I, _pV) \ +{ \ + BBP_CSR_CFG_STRUC BbpCsr; \ + int j, k; \ + if (!IS_RT65XX(_A)) {\ + for (j=0; jBbpWriteLatch[_I]; \ + } \ + }\ +} + +#define ATEPCIWriteBBPRegister(_A, _I, _V) \ +{ \ + BBP_CSR_CFG_STRUC BbpCsr; \ + int BusyCnt; \ + if (!IS_RT65XX(_A)) {\ + for (BusyCnt=0; BusyCntBbpWriteLatch[_I] = _V; \ + break; \ + } \ + if (BusyCnt == MAX_BUSY_COUNT) \ + { \ + DBGPRINT_ERR(("BBP write R%d fail\n", _I)); \ + } \ + }\ +} + + +#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 /* RTMP_MAC_PCI */ + + +INT DefaultATETxPwrHandler( + IN PRTMP_ADAPTER pAd, + IN char index); + + + + + +#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 CONFIG_QA +VOID ATE_QA_Statistics( + IN RTMP_ADAPTER *pAd, + IN RXWI_STRUC *pRxWI, + IN RXINFO_STRUC *pRxInfo, + IN PHEADER_802_11 pHeader); + +INT RtmpDoAte( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN RTMP_STRING *wrq_name); + +INT Set_TxStop_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_RxStop_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef DBG +INT Set_EERead_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EEWrite_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_BBPRead_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_BBPWrite_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_RFWrite_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* DBG */ +#endif /* CONFIG_QA */ + +#ifdef RTMP_RF_RW_SUPPORT +#ifdef RLT_RF +#define ATE_RF_IO_READ8_BY_REG_ID(_A, _B, _I, _pV) rlt_rf_read(_A, _B, _I, _pV) +#define ATE_RF_IO_WRITE8_BY_REG_ID(_A, _B, _I, _V) rlt_rf_write(_A, _B, _I, _V) +#endif /* RLT_RF */ +#ifdef RTMP_RF +#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 /* RTMP_RF */ +#ifdef MT_RF +#define ATE_RF_IO_READ8_BY_REG_ID(_A, _I, _pV) +#define ATE_RF_IO_WRITE8_BY_REG_ID(_A, _I, _V) +#endif /* MT_RF */ +#endif /* RTMP_RF_RW_SUPPORT */ + +#ifdef CONFIG_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 /* CONFIG_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(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_DA_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_SA_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_BSSID_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + +INT Set_ATE_CHANNEL_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_INIT_CHAN_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ADCDump_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) +INT Set_ATE_TSSI_CALIBRATION_EX_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) */ + +#ifdef RTMP_INTERNAL_TX_ALC +INT Set_ATE_TSSI_CALIBRATION_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_TSSI_CALIBRATION_EX_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + +#if defined(RT3350) || defined(RT3352) +INT RT335x_Set_ATE_TSSI_CALIBRATION_ENABLE_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +CHAR InsertTssi( + IN UCHAR InChannel, + IN UCHAR Channel0, + IN UCHAR Channel1, + IN CHAR Tssi0, + IN CHAR Tssi1); + +INT RT335xATETssiCalibrationExtend(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_SHOW_TSSI_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#endif /* RTMP_TEMPERATURE_CALIBRATION */ + +#ifdef RTMP_TEMPERATURE_COMPENSATION + +INT Set_ATE_READ_EXTERNAL_TSSI_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + +INT Set_ATE_TX_POWER0_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_TX_POWER1_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef DOT11N_SS3_SUPPORT +INT Set_ATE_TX_POWER2_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* DOT11N_SS3_SUPPORT */ + +INT Set_ATE_TX_POWER_EVALUATION_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_TX_Antenna_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_RX_Antenna_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +VOID DefaultATEAsicExtraPowerOverMAC( + IN PRTMP_ADAPTER pAd); + +VOID ATEAsicExtraPowerOverMAC( + IN PRTMP_ADAPTER pAd); +#ifdef RT3350 +INT Set_ATE_PA_Bias_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* RT3350 */ + +INT Default_Set_ATE_TX_FREQ_OFFSET_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + + + + +#if defined(RT28xx) || defined(RT2880) +INT RT28xx_Set_ATE_TX_FREQ_OFFSET_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* defined(RT28xx) || defined(RT2880) */ + + +INT Set_ATE_TX_FREQ_OFFSET_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Default_Set_ATE_TX_BW_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + + + + +#if defined(RT28xx) || defined(RT2880) +INT RT28xx_Set_ATE_TX_BW_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* defined(RT28xx) || defined(RT2880) */ + + +INT Set_ATE_TX_BW_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_TX_LENGTH_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_TX_COUNT_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_TX_MCS_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_TX_STBC_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_TX_MODE_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_TX_GI_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + +INT Set_ATE_RX_FER_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_Read_RF_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#if (!defined(RTMP_RF_RW_SUPPORT)) && (!defined(RLT_RF)) +INT Set_ATE_Write_RF1_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_Write_RF2_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_Write_RF3_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_Write_RF4_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* (!defined(RTMP_RF_RW_SUPPORT)) && (!defined(RLT_RF)) */ + +INT Set_ATE_Load_E2P_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef RTMP_EFUSE_SUPPORT +INT Set_ATE_Load_E2P_From_Buf_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* RTMP_EFUSE_SUPPORT */ + +INT Set_ATE_Read_E2P_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef LED_CONTROL_SUPPORT +#endif /* LED_CONTROL_SUPPORT */ + +INT Set_ATE_AUTO_ALC_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_TEMP_SENSOR_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_IPG_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_Payload_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_Fixed_Payload_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + + +INT Set_ATE_TTR_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_Show_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ATE_Help_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +VOID DefaultATEAsicAdjustTxPower( + IN PRTMP_ADAPTER pAd); + + + + +VOID ATEAsicAdjustTxPower( + IN PRTMP_ADAPTER pAd); + + +VOID ATESampleRssi( + IN PRTMP_ADAPTER pAd, + IN RXWI_STRUC *pRxWI); + +#ifdef RTMP_MAC_PCI +NDIS_STATUS ATEPayloadAlloc( + IN PRTMP_ADAPTER pAd, + IN UINT32 idx); + +PNDIS_PACKET ATEPayloadInit( + IN PRTMP_ADAPTER pAd, + IN UINT32 TxIdx); + +NDIS_STATUS TxRingGetReady( + IN PRTMP_ADAPTER pAd); +#endif /* RTMP_MAC_PCI */ + + +INT TxDmaBusy(RTMP_ADAPTER *pAd); +INT RxDmaBusy(RTMP_ADAPTER *pAd); + +VOID RtmpDmaEnable(RTMP_ADAPTER *pAd, INT Enable); + +INT ATESetUpFrame(RTMP_ADAPTER *pAd, UINT32 TxIdx); + + + +NDIS_STATUS ChipStructAssign( + IN PRTMP_ADAPTER pAd); + +NDIS_STATUS ATEInit( + IN PRTMP_ADAPTER pAd); + +#ifdef CONFIG_QA +VOID ReadQATxTypeFromBBP( + IN PRTMP_ADAPTER pAd); +#endif /* CONFIG_QA */ + +#ifdef RTMP_BBP +NDIS_STATUS ATEBBPWriteWithRxChain( + IN RTMP_ADAPTER *pAd, + IN UCHAR bbpId, + IN CHAR bbpVal, + IN RX_CHAIN_IDX rx_ch_idx); +#endif /* RTMP_BBP */ + + + + + + +#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(RTMP_ADAPTER *pAd); + +VOID RtmpRfIoWrite(RTMP_ADAPTER *pAd); + +VOID ATEAsicSwitchChannel(RTMP_ADAPTER *pAd); + +VOID BbpSoftReset(RTMP_ADAPTER *pAd); + + +#endif /* __RT_ATE_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/rt_qa.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/rt_qa.h new file mode 100644 index 000000000..046bba014 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/include/rt_qa.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-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 CONFIG_QA +#ifndef CONFIG_ATE +#error "For supporting QA GUI, please set HAS_ATE=y and HAS_QA_SUPPORT=y." +#endif /* CONFIG_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 + +#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 +#define RACFG_CMD_ATE_RF_READ_BULK 0x0119 +#define RACFG_CMD_ATE_RF_WRITE_BULK 0x011a +#define RACFG_CMD_ATE_SET_TX_POWER2 0x011b +#ifdef RLT_RF +#define RACFG_CMD_ATE_RF_READ_BULK_BANK 0x0123 +#define RACFG_CMD_ATE_RF_WRITE_BULK_BANK 0x0124 +#endif /* RLT_RF */ +#define RACFG_CMD_TX_START_V2 0x0125 + + + +/* 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 /* CONFIG_QA */ + +#endif /* __RT_QA_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/inf/ate_pci.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/inf/ate_pci.c new file mode 100644 index 000000000..3c31fb618 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/inf/ate_pci.c @@ -0,0 +1,530 @@ +/* + *************************************************************************** + * 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; + +#if defined(RTMP_MAC) || defined(RLT_MAC) + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); /* disable DMA */ +#elif defined(MT_MAC) + RTMP_IO_READ32(pAd, MT_WPDMA_GLO_CFG, &GloCfg.word); /* disable DMA */ +#endif + result = (GloCfg.field.TxDMABusy) ? TRUE : FALSE; + + return result; +} + + +INT RxDmaBusy( + IN PRTMP_ADAPTER pAd) +{ + INT result; + WPDMA_GLO_CFG_STRUC GloCfg; + +#if defined(RTMP_MAC) || defined(RLT_MAC) + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); /* disable DMA */ +#elif defined(MT_MAC) + RTMP_IO_READ32(pAd, MT_WPDMA_GLO_CFG, &GloCfg.word); /* disable DMA */ +#endif + result = (GloCfg.field.RxDMABusy) ? TRUE : FALSE; + + return result; +} + + +VOID RtmpDmaEnable( + IN PRTMP_ADAPTER pAd, + IN INT Enable) +{ + ULONG WaitCnt = 0; + + /* check if DMA is in busy mode or not. */ + while (TxDmaBusy(pAd) || RxDmaBusy(pAd)) + { + RtmpusecDelay(10); + if (WaitCnt++ > 100) + break; + } + + AsicSetWPDMA(pAd, PDMA_TX_RX, (Enable > 0 ? TRUE : FALSE)); + + RtmpOsMsDelay(5); + + return; +} + + +/* +======================================================================== + Routine Description: + Write TxWI for ATE mode. + + Return Value: + None +======================================================================== +*/ +VOID ATEWriteTxWI( + IN PRTMP_ADAPTER pAd, + IN TXWI_STRUC *pOutTxWI, + IN BOOLEAN FRAG, + IN BOOLEAN CFACK, + IN BOOLEAN InsTimestamp, + IN BOOLEAN AMPDU, + IN BOOLEAN Ack, + IN BOOLEAN NSeq, /* HW new a sequence. */ + IN UCHAR BASize, + IN UCHAR WCID, + IN ULONG Length, + IN UCHAR PID, + IN UCHAR TID, + IN UCHAR TxRate, + IN UCHAR Txopmode, + IN BOOLEAN CfAck, + IN HTTRANSMIT_SETTING *pTransmit) +{ + TXWI_STRUC TxWI, *pTxWI; + UINT8 TXWISize = pAd->chipCap.TXWISize; + UCHAR bw; + + /* If CCK or OFDM, BW must be 20 */ + bw = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + NdisZeroMemory(&TxWI, TXWISize); + pTxWI = &TxWI; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + struct _TXWI_NMAC *txwi_n = (struct _TXWI_NMAC *)pTxWI; + + txwi_n->FRAG= FRAG; + txwi_n->CFACK = CFACK; + txwi_n->TS= InsTimestamp; + txwi_n->AMPDU = AMPDU; + txwi_n->ACK = Ack; + txwi_n->txop = Txopmode; + txwi_n->NSEQ= NSeq; + txwi_n->BAWinSize = BASize; + txwi_n->wcid = WCID; + txwi_n->MPDUtotalByteCnt = Length; + txwi_n->BW = bw; + txwi_n->ShortGI = pTransmit->field.ShortGI; + txwi_n->STBC = pTransmit->field.STBC; + txwi_n->MCS = pTransmit->field.MCS; + txwi_n->PHYMODE = pTransmit->field.MODE; + txwi_n->CFACK = CfAck; + txwi_n->MIMOps = 0; + txwi_n->MpduDensity = 0; + txwi_n->TxPktId = txwi_n->MCS; + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + struct _TXWI_OMAC *txwi_o = (struct _TXWI_OMAC *)pTxWI; + + txwi_o->FRAG= FRAG; + txwi_o->CFACK = CFACK; + txwi_o->TS= InsTimestamp; + txwi_o->AMPDU = AMPDU; + txwi_o->ACK = Ack; + txwi_o->txop = Txopmode; + txwi_o->NSEQ = NSeq; + txwi_o->BAWinSize = BASize; + txwi_o->wcid = WCID; + txwi_o->MPDUtotalByteCnt = Length; + txwi_o->BW = bw; + txwi_o->ShortGI = pTransmit->field.ShortGI; + txwi_o->STBC = pTransmit->field.STBC; + txwi_o->MCS = pTransmit->field.MCS; + txwi_o->PHYMODE = pTransmit->field.MODE; + txwi_o->CFACK = CfAck; + txwi_o->MIMOps = 0; + txwi_o->MpduDensity = 0; + txwi_o->PacketId = txwi_o->MCS; + } +#endif /* RTMP_MAC */ + + NdisMoveMemory(pOutTxWI, &TxWI, TXWISize); + + return; +} + + +/* +========================================================================== + Description: + Allocate Frame payload buffer. + NOTE: + This routine should only be used in ATE mode. +========================================================================== +*/ +NDIS_STATUS ATEPayloadAlloc( + IN PRTMP_ADAPTER pAd, + IN UINT32 idx) +{ + ATE_INFO *pATEInfo = &(pAd->ate); + NDIS_PHYSICAL_ADDRESS AllocPa; + + /* alloc buffer for payload */ +#ifdef CONFIG_QA + if ((pATEInfo->bQAEnabled == TRUE) && (pATEInfo->DLen != 0)) + { + pATEInfo->pAtePacket[idx] = RTMP_AllocateRxPacketBuffer(pAd, ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + pATEInfo->DLen + 0x100, FALSE, &pATEInfo->AteAllocVa[idx], &AllocPa); + } + else +#endif /* CONFIG_QA */ + { + pATEInfo->pAtePacket[idx] = RTMP_AllocateRxPacketBuffer(pAd, ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + pATEInfo->TxLength, FALSE, &pATEInfo->AteAllocVa[idx], &AllocPa); + } + + if (pATEInfo->pAtePacket[idx] == NULL) + { + pATEInfo->TxCount = 0; + DBGPRINT_ERR(("%s : fail to alloc packet space.\n", __FUNCTION__)); + return (NDIS_STATUS_RESOURCES); + } + + return (NDIS_STATUS_SUCCESS); +} + + +/* +========================================================================== + Description: + Initialize Frame payload. + NOTE: + This routine should only be used in ATE mode. +========================================================================== +*/ +PNDIS_PACKET ATEPayloadInit( + IN PRTMP_ADAPTER pAd, + IN UINT32 idx) +{ + ATE_INFO *pATEInfo = &(pAd->ate); + RTMP_TX_RING *pTxRing = &pAd->TxRing[QID_AC_BE]; + PNDIS_PACKET pPacket = pTxRing->Cell[idx].pNdisPacket; + PUCHAR pDest = (PUCHAR)pATEInfo->AteAllocVa[idx]; + UINT pos = 0; + +#ifdef CONFIG_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 /* CONFIG_QA */ + { + GET_OS_PKT_LEN(pPacket) = pATEInfo->TxLength - pATEInfo->HLen; +#ifndef LINUX + GET_OS_PKT_TOTAL_LEN(pPacket) = pATEInfo->TxLength - pATEInfo->HLen; +#endif /* LINUX */ + } + + /* prepare frame payload */ +#ifdef CONFIG_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 /* CONFIG_QA */ + { + for (pos = 0; pos < GET_OS_PKT_LEN(pPacket); pos++) + { + if ( pATEInfo->bFixedPayload ) + { + /* default payload is 0xA5 */ + pDest[pos] = pATEInfo->Payload; + } + else + { + pDest[pos] = RandomByte(pAd); + } + } + } + + return pPacket; +} + + +/* +========================================================================== + 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); + TXINFO_STRUC *pTxInfo; + TXD_STRUC *pTxD; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR tx_hw_info[TXD_SIZE]; +#endif /* RT_BIG_ENDIAN */ + PNDIS_PACKET pPacket=NULL; + PUCHAR pDest=NULL; + HTTRANSMIT_SETTING TxHTPhyMode; + + RTMP_TX_RING *pTxRing = &pAd->TxRing[QID_AC_BE]; + TXWI_STRUC *pTxWI = (TXWI_STRUC *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + PUCHAR pDMAHeaderBufVA = (PUCHAR) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + UINT8 TXWISize = pAd->chipCap.TXWISize; +#ifdef CONFIG_QA + PHEADER_802_11 pHeader80211; +#endif /* CONFIG_QA */ + UCHAR bw, sgi, stbc, mcs, phy_mode, frag, cfack, ts, ampdu, ack, nseq, bawinsize, pkt_id, txop; + USHORT byte_cnt; + + bw = sgi = stbc = mcs = phy_mode = frag = cfack = ts =0; + ampdu = ack = nseq = bawinsize = pkt_id = txop = 0; + byte_cnt = 0; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + bw = pATEInfo->TxWI.TXWI_N.BW; + sgi = pATEInfo->TxWI.TXWI_N.ShortGI; + stbc = pATEInfo->TxWI.TXWI_N.STBC; + mcs = pATEInfo->TxWI.TXWI_N.MCS; + phy_mode = pATEInfo->TxWI.TXWI_N.PHYMODE; + + frag = pATEInfo->TxWI.TXWI_N.FRAG; + cfack = pATEInfo->TxWI.TXWI_N.CFACK, + ts = pATEInfo->TxWI.TXWI_N.TS; + ampdu = pATEInfo->TxWI.TXWI_N.AMPDU; + ack = pATEInfo->TxWI.TXWI_N.ACK; + nseq = pATEInfo->TxWI.TXWI_N.NSEQ; + bawinsize =pATEInfo->TxWI.TXWI_N.BAWinSize; + byte_cnt = pATEInfo->TxWI.TXWI_N.MPDUtotalByteCnt; + pkt_id = pATEInfo->TxWI.TXWI_N.TxPktId; + txop = pATEInfo->TxWI.TXWI_N.txop; + cfack = pATEInfo->TxWI.TXWI_N.CFACK; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + bw = pATEInfo->TxWI.TXWI_O.BW; + sgi = pATEInfo->TxWI.TXWI_O.ShortGI; + stbc = pATEInfo->TxWI.TXWI_O.STBC; + mcs = pATEInfo->TxWI.TXWI_O.MCS; + phy_mode = pATEInfo->TxWI.TXWI_O.PHYMODE; + + frag = pATEInfo->TxWI.TXWI_O.FRAG; + cfack = pATEInfo->TxWI.TXWI_O.CFACK, + ts = pATEInfo->TxWI.TXWI_O.TS; + ampdu = pATEInfo->TxWI.TXWI_O.AMPDU; + ack = pATEInfo->TxWI.TXWI_O.ACK; + nseq = pATEInfo->TxWI.TXWI_O.NSEQ; + bawinsize =pATEInfo->TxWI.TXWI_O.BAWinSize; + byte_cnt = pATEInfo->TxWI.TXWI_O.MPDUtotalByteCnt; + pkt_id = pATEInfo->TxWI.TXWI_O.PacketId; + txop = pATEInfo->TxWI.TXWI_O.txop; + cfack = pATEInfo->TxWI.TXWI_O.CFACK; + } +#endif /* RTMP_MAC */ + + /* fill TxWI */ + TxHTPhyMode.field.BW = bw; + TxHTPhyMode.field.ShortGI = sgi; + TxHTPhyMode.field.STBC = stbc; + TxHTPhyMode.field.MCS = mcs; + TxHTPhyMode.field.MODE = phy_mode; + + if (pATEInfo->bQATxStart == TRUE) + { + /* always use QID_AC_BE and FIFO_EDCA */ + ATEWriteTxWI(pAd, pTxWI, frag, cfack, + ts, ampdu, ack, + nseq, bawinsize, 0, + byte_cnt, pkt_id, 0, 0, + txop, cfack, + &TxHTPhyMode); + + } + else + { + ATEWriteTxWI(pAd, pTxWI, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, + 4, 0, pATEInfo->TxLength, 0, 0, 0, IFS_HTTXOP, FALSE, &TxHTPhyMode); + + } + + /* fill 802.11 header */ +#ifdef CONFIG_QA + if (pATEInfo->bQATxStart == TRUE) + { + NdisMoveMemory(pDMAHeaderBufVA + TXWISize, pATEInfo->Header, pATEInfo->HLen); + } + else +#endif /* CONFIG_QA */ + { + pATEInfo->HLen = LENGTH_802_11; + NdisMoveMemory(pDMAHeaderBufVA + TXWISize, TemplateFrame, pATEInfo->HLen); + NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 4, pATEInfo->Addr1, MAC_ADDR_LEN); + NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 10, pATEInfo->Addr2, MAC_ADDR_LEN); + NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 16, pATEInfo->Addr3, MAC_ADDR_LEN); + } + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (((PUCHAR)pDMAHeaderBufVA) + TXWISize), DIR_READ, FALSE); +#endif /* RT_BIG_ENDIAN */ + + pPacket = ATEPayloadInit(pAd, TxIdx); + /* error check */ + if (pPacket == NULL) + { + pATEInfo->TxCount = 0; + DBGPRINT_ERR(("%s : fail to init frame payload.\n", __FUNCTION__)); + return -1; + } + pTxRing->Cell[TxIdx].pNdisPacket = pPacket; + + /* build Tx descriptor */ +#ifndef RT_BIG_ENDIAN + pTxD = (TXD_STRUC *) pTxRing->Cell[TxIdx].AllocVa; + pTxInfo = (TXINFO_STRUC *)(pTxRing->Cell[TxIdx].AllocVa + sizeof(TXD_STRUC)); +#else + pDestTxD = (TXD_STRUC *)pTxRing->Cell[TxIdx].AllocVa; + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + pTxInfo = (TXINFO_STRUC *)(&tx_hw_info[0] + sizeof(TXD_STRUC)); +#endif /* !RT_BIG_ENDIAN */ + { + /* prepare TxD */ + TX_BLK txblk; + txblk.SrcBufLen = GET_OS_PKT_LEN(pATEInfo->pAtePacket[TxIdx]); + txblk.pSrcBufData = (PUCHAR)pATEInfo->AteAllocVa[TxIdx]; + NdisZeroMemory(pTxD, TXD_SIZE); + /* build Tx descriptor */ + pTxD->SDPtr0 = RTMP_GetPhysicalAddressLow (pTxRing->Cell[TxIdx].DmaBuf.AllocPa); + pTxD->SDLen0 = TXWISize + pATEInfo->HLen; + pTxD->LastSec0 = 0; + pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, &txblk, 0, 1, RTMP_PCI_DMA_TODEVICE); + pTxD->SDLen1 = GET_OS_PKT_LEN(pATEInfo->pAtePacket[TxIdx]); + pTxD->LastSec1 = 1; + pTxD->Burst = 0; +#if defined(RTMP_MAC) || defined(RLT_MAC) + ral_write_txd(pAd, pTxD, pTxInfo, FALSE, FIFO_EDCA); +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ +#ifdef MT_MAC + mt_write_txd(pAd, pTxD); +#endif /* MT_MAC */ + } +#ifdef CONFIG_QA + if (pATEInfo->bQATxStart == TRUE) + { + 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; + } +#endif /* CONFIG_QA */ + +#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; +} + + +/* +========================================================================== + Description: + Tx ring skb hook and ring index setting. + NOTE: + This routine should only be used in ATE mode. +========================================================================== +*/ +NDIS_STATUS TxRingGetReady( + IN PRTMP_ADAPTER pAd) +{ + ATE_INFO *pATEInfo = &(pAd->ate); + RTMP_TX_RING *pTxRing = &pAd->TxRing[QID_AC_BE]; + UINT32 TxIdx = 0; + UINT32 ring_idx = 0; + RTMP_IO_READ32(pAd, pTxRing->hw_didx_addr, &pTxRing->TxDmaIdx); + pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; + pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; + RTMP_IO_WRITE32(pAd, pTxRing->hw_cidx_addr, pTxRing->TxCpuIdx); + + for (ring_idx = 0; (ring_idx < TX_RING_SIZE) && (ring_idx < pATEInfo->TxCount); ring_idx++) + { + TxIdx = pTxRing->TxCpuIdx; + + if (ATESetUpFrame(pAd, TxIdx) != 0) + { + return (NDIS_STATUS_FAILURE); + } + + if (((ring_idx + 1) < TX_RING_SIZE) && (ring_idx < pATEInfo->TxCount)) + { + INC_RING_INDEX(pTxRing->TxCpuIdx, TX_RING_SIZE); + } + } + + return (NDIS_STATUS_SUCCESS); +} + +#endif /* RTMP_MAC_PCI */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/inf/ate_usb.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/inf/ate_usb.c new file mode 100644 index 000000000..63afc4d4b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/inf/ate_usb.c @@ -0,0 +1,29 @@ +/* + *************************************************************************** + * 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_usb.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/mt_mac/mt_ate.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/mt_mac/mt_ate.c new file mode 100644 index 000000000..d8ed09f71 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/mt_mac/mt_ate.c @@ -0,0 +1,1183 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of MediaTek. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + mt_ate.c +*/ + +#include "rt_config.h" + +static INT32 MT_ATESetTxPower0(RTMP_ADAPTER *pAd, CHAR Value) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + //struct MT_TX_PWR_CAP *cap = &pAd->chipCap.MTTxPwrCap; + INT32 Ret = 0; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + ATECtrl->TxPower0 = Value; + ATECtrl->TxPower1 = pAd->EEPROMImage[TX1_G_BAND_TARGET_PWR]; + CmdSetTxPowerCtrl(pAd, ATECtrl->Channel); + return Ret; +} + +static INT32 MT_ATESetTxPower1(RTMP_ADAPTER *pAd, CHAR Value) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0; + // For TxTone Power + ATECtrl->TxPower1 = Value; + DBGPRINT(RT_DEBUG_OFF, ("%s, power1:0x%x\n", __FUNCTION__,ATECtrl->TxPower1)); + /* Same as Power0 */ + if ( ATECtrl->TxPower0 != ATECtrl->TxPower1) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: power1 do not same as power0\n", __FUNCTION__)); + Ret = -1; + } + + return Ret; +} + + +static INT32 MT_ATEStart(RTMP_ADAPTER *pAd) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0; + +#ifdef RTMP_PCI_SUPPORT + UINT32 Index; + TXD_STRUC *pTxD = NULL; + RTMP_TX_RING *pTxRing = &pAd->TxRing[QID_AC_BE]; +#endif + +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD = NULL; + UCHAR TxHwInfo[TXD_SIZE]; +#endif + +#ifdef CONFIG_AP_SUPPORT + INT32 IdBss, MaxNumBss = pAd->ApCfg.BssidNum; +#endif + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + /* Stop send TX packets */ + RTMP_OS_NETDEV_STOP_QUEUE(pAd->net_dev); +#ifdef SINGLE_SKU_V2 + pAd->SKUEn = 0; +#endif + /* Reset ATE TX/RX Counter */ + ATECtrl->TxDoneCount = 0; + ATECtrl->RxTotalCnt = 0; + ATECtrl->cmd_expire = RTMPMsecsToJiffies(3000); + RTMP_OS_INIT_COMPLETION(&ATECtrl->cmd_done); +#ifdef CONFIG_ATE + ATECtrl->TxPower0 = pAd->EEPROMImage[TX0_G_BAND_TARGET_PWR]; + ATECtrl->TxPower1 = pAd->EEPROMImage[TX1_G_BAND_TARGET_PWR]; + DBGPRINT(RT_DEBUG_INFO, ("%s, Init Txpower, Tx0:%x, Tx1:%x\n", __FUNCTION__, ATECtrl->TxPower0, ATECtrl->TxPower1)); +#ifdef CONFIG_QA + AsicGetRxStat(pAd, HQA_RX_RESET_PHY_COUNT); + ATECtrl->RxMacMdrdyCount = 0; + ATECtrl->RxMacFCSErrCount = 0; +#endif /* CONFIG_QA */ +#endif /* CONFIG_ATE */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (MaxNumBss > MAX_MBSSID_NUM(pAd)) + MaxNumBss = MAX_MBSSID_NUM(pAd); + + /* first IdBss must not be 0 (BSS0), must be 1 (BSS1) */ + for (IdBss = FIRST_MBSSID; IdBss < MAX_MBSSID_NUM(pAd); IdBss++) + { + if (pAd->ApCfg.MBSSID[IdBss].wdev.if_dev) + RTMP_OS_NETDEV_STOP_QUEUE(pAd->ApCfg.MBSSID[IdBss].wdev.if_dev); + } + } +#endif + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET); + + AsicSetMacTxRx(pAd, ASIC_MAC_RX, FALSE); + + /* Disable TX PDMA */ + AsicSetWPDMA(pAd, PDMA_TX, 0); + +#ifdef RTMP_MAC_PCI + /* Polling TX/RX path until packets empty */ + MTPciPollTxRxEmpty(pAd); + + + for (Index = 0; Index < TX_RING_SIZE; Index++) + { + PNDIS_PACKET pPacket; +#ifndef RT_BIG_ENDIAN + pTxD = (TXD_STRUC *)pAd->TxRing[QID_AC_BE].Cell[Index].AllocVa; +#else + pDestTxD = (TXD_STRUC *)pAd->TxRing[QID_AC_BE].Cell[Index].AllocVa; + NdisMoveMemory(&TxHwInfo[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&TxHwInfo[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + pTxD->DMADONE = 0; + pPacket = pTxRing->Cell[Index].pNdisPacket; + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + pTxRing->Cell[Index].pNdisPacket = NULL; + } + + /* prepare TX resource for ATE mode */ + pPacket = pTxRing->Cell[Index].pNextNdisPacket; + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + pTxRing->Cell[Index].pNextNdisPacket = NULL; + } + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif + } +#endif /* RTMP_MAC_PCI */ + + + + + + +#ifdef CONFIG_AP_SUPPORT +#ifdef RTMP_MAC_PCI + APStop(pAd); +#endif /* RTMP_MAC_PCI */ +#endif /* CONFIG_AP_SUPPORT */ + + AsicSetWPDMA(pAd, PDMA_TX_RX, 1); +#ifdef RTMP_MAC_PCI + RTMP_ASIC_INTERRUPT_ENABLE(pAd); +#endif /* RTMP_MAC_PCI */ + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + + if(ATECtrl->Mode & fATE_TXCONT_ENABLE){ + DBGPRINT(RT_DEBUG_OFF, ("%s ,Stop Continuous Tx\n",__FUNCTION__)); + AsicStopContinousTx(pAd); + } + + if((ATECtrl->Mode & fATE_TXCARRSUPP_ENABLE)|| + (ATECtrl->Mode & fATE_TXCARR_ENABLE)){ + DBGPRINT(RT_DEBUG_OFF, ("%s ,Stop Tx Carrier Test\n",__FUNCTION__)); + AsicSetTxToneTest(pAd, 0, 0); + } + ATECtrl->Mode = ATE_START; + { + UINT32 Value = 0; + ATECtrl->rmac_pcr1 = 0; + RTMP_IO_READ32(pAd, AGG_PCR1, &ATECtrl->rmac_pcr1); + Value = ATECtrl->rmac_pcr1; + Value &= 0x0FFFFFFF; + Value |= 0x10000000; + RTMP_IO_WRITE32(pAd, AGG_PCR1, Value); + } + + { + UINT32 Value = 0; + ATECtrl->rmac_pcr = 0; + RTMP_IO_READ32(pAd, AGG_PCR, &ATECtrl->rmac_pcr); + RTMP_IO_WRITE32(pAd, AGG_PCR, Value); + } + + return Ret; +} + + +static INT32 MT_ATEStop(RTMP_ADAPTER *pAd) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0; +#ifdef CONFIG_AP_SUPPORT + INT32 IdBss, MaxNumBss = pAd->ApCfg.BssidNum; +#endif +#ifdef RTMP_MAC_PCI + UINT32 Index, RingNum; + RXD_STRUC *pRxD = NULL; +#endif /* RTMP_MAC_PCI */ +#ifdef RT_BIG_ENDIAN + RXD_STRUC *pDestRxD; + UCHAR RxHwInfo[RXD_SIZE]; +#endif + + + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); +#ifdef SINGLE_SKU_V2 + pAd->SKUEn = 1; +#endif +#ifdef RTMP_MAC_PCI + /* Polling TX/RX path until packets empty */ + MTPciPollTxRxEmpty(pAd); +#endif + + AsicSetMacTxRx(pAd, ASIC_MAC_RXV, FALSE); + + NICInitializeAdapter(pAd, TRUE); + +#ifdef RTMP_MAC_PCI + + for (RingNum = 0; RingNum < NUM_OF_RX_RING; RingNum++) + { + for (Index = 0; Index < RX_RING_SIZE; Index++) + { +#ifdef RT_BIG_ENDIAN + pDestRxD = (RXD_STRUC *)pAd->RxRing[0].Cell[Index].AllocVa; + NdisMoveMemory(&RxHwInfo[0], pDestRxD, RXD_SIZE); + pRxD = (RXD_STRUC *)&RxHwInfo[0]; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + /* Point to Rx indexed rx ring descriptor */ + pRxD = (RXD_STRUC *)pAd->RxRing[0].Cell[Index].AllocVa; +#endif + pRxD->DDONE = 0; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); + WriteBackToDescriptor((PUCHAR)pDestRxD, (PUCHAR)pRxD, FALSE, TYPE_RXD); +#endif + } + } + +#endif /* RTMP_MAC_PCI */ + +/* if usb call this two function , FW will hang~~ */ +#ifdef RTMP_MAC_PCI + NICReadEEPROMParameters(pAd, NULL); + NICInitAsicFromEEPROM(pAd); +#endif /* RTMP_MAC_PCI */ + + AsicSetRxFilter(pAd); + + +#ifdef RTMP_MAC_PCI + RTMP_IRQ_ENABLE(pAd); +#endif /* RTMP_MAC_PCI */ + RTMPEnableRxTx(pAd); + + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + +#ifdef CONFIG_AP_SUPPORT +#ifdef RTMP_MAC_PCI + APStartUp(pAd); +#endif /* RTMP_MAC_PCI */ +#endif /* CONFIG_AP_SUPPORT */ + RTMP_OS_NETDEV_START_QUEUE(pAd->net_dev); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (MaxNumBss > MAX_MBSSID_NUM(pAd)) + MaxNumBss = MAX_MBSSID_NUM(pAd); + + /* first IdBss must not be 0 (BSS0), must be 1 (BSS1) */ + for (IdBss = FIRST_MBSSID; IdBss < MAX_MBSSID_NUM(pAd); IdBss++) + { + if (pAd->ApCfg.MBSSID[IdBss].wdev.if_dev) + RTMP_OS_NETDEV_START_QUEUE(pAd->ApCfg.MBSSID[IdBss].wdev.if_dev); + } + } +#endif + + RTMP_OS_EXIT_COMPLETION(&ATECtrl->cmd_done); + ATECtrl->Mode = ATE_STOP; + + if ((MTK_REV_GTE(pAd, MT7603, MT7603E1)) || + (MTK_REV_GTE(pAd, MT7628, MT7628E1))) + { + UINT32 Value; + RTMP_IO_READ32(pAd, CR_RFINTF_00, &Value); + Value &= ~CR_RFINTF_CAL_NSS_MASK; + Value |= CR_RFINTF_CAL_NSS(0x0); + RTMP_IO_WRITE32(pAd, CR_RFINTF_00, Value); + } + + RTMP_IO_WRITE32(pAd, AGG_PCR1, ATECtrl->rmac_pcr1); + RTMP_IO_WRITE32(pAd, AGG_PCR, ATECtrl->rmac_pcr); + return Ret; +} + + +#ifdef RTMP_PCI_SUPPORT +static INT32 MT_ATESetupFrame(RTMP_ADAPTER *pAd, UINT32 TxIdx) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + RTMP_TX_RING *pTxRing = &pAd->TxRing[QID_AC_BE]; + PUCHAR pDMAHeaderBufVA = (PUCHAR)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + TXD_STRUC *pTxD; + MAC_TX_INFO Info; + UINT8 TXWISize = pAd->chipCap.TXWISize; + PNDIS_PACKET pPacket = NULL; + HTTRANSMIT_SETTING Transmit; + TX_BLK TxBlk; + INT32 Ret = 0; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR TxHwInfo[TXD_SIZE]; +#endif /* RT_BIG_ENDIAN */ + + ATECtrl->HLen = LENGTH_802_11; + + NdisZeroMemory(&Transmit, sizeof(Transmit)); + NdisZeroMemory(&TxBlk, sizeof(TxBlk)); + + /* Fill Mac Tx info */ + NdisZeroMemory(&Info, sizeof(Info)); + + /* LMAC queue index (AC0) */ + Info.q_idx = 1; + + Info.WCID = 0; + Info.hdr_len = ATECtrl->HLen; + Info.hdr_pad = 0; + + Info.BM = IS_BM_MAC_ADDR(ATECtrl->Addr1); + + /* no ack */ + Info.Ack = 0; + + Info.bss_idx = 0; + + /* no frag */ + Info.FRAG = 0; + + /* no protection */ + Info.prot = 0; + + Info.Length = ATECtrl->TxLength; + + /* TX Path setting */ + Info.AntPri = 0; + Info.SpeEn = 0; + switch (ATECtrl->TxAntennaSel) { + case 0: /* Both */ + Info.AntPri = 0; + Info.SpeEn = 1; + break; + case 1: /* TX0 */ + Info.AntPri = 0; + Info.SpeEn = 0; + break; + case 2: /* TX1 */ + Info.AntPri = 2; //b'010 + Info.SpeEn = 0; + break; + } + + /* Fill Transmit setting */ + Transmit.field.MCS = ATECtrl->Mcs; + Transmit.field.BW = ATECtrl->BW; + Transmit.field.ShortGI = ATECtrl->Sgi; + Transmit.field.STBC = ATECtrl->Stbc; + Transmit.field.MODE = ATECtrl->PhyMode; + + if (ATECtrl->PhyMode == MODE_CCK) + { + Info.Preamble = LONG_PREAMBLE; + + /* + Short preamble mapping + UCHAR tmi_rate_map_cck_sp[]={ + TMI_TX_RATE_CCK_2M_SP, + TMI_TX_RATE_CCK_2M_SP, + TMI_TX_RATE_CCK_5M_SP, + TMI_TX_RATE_CCK_11M_SP, + }; + */ + if (ATECtrl->Mcs == 9) + { + Transmit.field.MCS = 1; + Info.Preamble = SHORT_PREAMBLE; + } + else if (ATECtrl->Mcs == 10) + { + Transmit.field.MCS = 2; + Info.Preamble = SHORT_PREAMBLE; + } + else if (ATECtrl->Mcs == 11) + { + Transmit.field.MCS = 3; + Info.Preamble = SHORT_PREAMBLE; + } + } + + write_tmac_info(pAd, pDMAHeaderBufVA, &Info, &Transmit); + + NdisMoveMemory(pDMAHeaderBufVA + TXWISize, ATECtrl->TemplateFrame, ATECtrl->HLen); + NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 4, ATECtrl->Addr1, MAC_ADDR_LEN); + NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 10, ATECtrl->Addr2, MAC_ADDR_LEN); + NdisMoveMemory(pDMAHeaderBufVA + TXWISize + 16, ATECtrl->Addr3, MAC_ADDR_LEN); + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (((PUCHAR)pDMAHeaderBufVA) + TXWISize), DIR_READ, FALSE); +#endif /* RT_BIG_ENDIAN */ + + pPacket = ATEPayloadInit(pAd, TxIdx); + + if (pPacket == NULL) + { + ATECtrl->TxCount = 0; + DBGPRINT_ERR(("%s : fail to init frame payload.\n", __FUNCTION__)); + return -1; + } + + pTxRing->Cell[TxIdx].pNdisPacket = pPacket; + + pTxD = (TXD_STRUC *)pTxRing->Cell[TxIdx].AllocVa; +#ifndef RT_BIG_ENDIAN + pTxD = (TXD_STRUC *)pTxRing->Cell[TxIdx].AllocVa; +#else + pDestTxD = (TXD_STRUC *)pTxRing->Cell[TxIdx].AllocVa; + NdisMoveMemory(&TxHwInfo[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&TxHwInfo[0]; +#endif + TxBlk.SrcBufLen = GET_OS_PKT_LEN(ATECtrl->pAtePacket[TxIdx]); + TxBlk.pSrcBufData = (PUCHAR)ATECtrl->AteAllocVa[TxIdx]; + + NdisZeroMemory(pTxD, TXD_SIZE); + /* build Tx descriptor */ + pTxD->SDPtr0 = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); + pTxD->SDLen0 = TXWISize + ATECtrl->HLen; + pTxD->LastSec0 = 0; + pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, &TxBlk, 0, 1, RTMP_PCI_DMA_TODEVICE); + pTxD->SDLen1 = GET_OS_PKT_LEN(ATECtrl->pAtePacket[TxIdx]); + pTxD->LastSec1 = 1; + pTxD->DMADONE = 0; + +#ifdef RT_BIG_ENDIAN + MTMacInfoEndianChange(pAd, pDMAHeaderBufVA, TYPE_TMACINFO, sizeof(TMAC_TXD_L)); + RTMPFrameEndianChange(pAd, (((PUCHAR)pDMAHeaderBufVA) + TXWISize), DIR_WRITE, FALSE); + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif + + return Ret; +} +#endif + + + + + + +static INT32 MT_ATEStartTx(RTMP_ADAPTER *pAd) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + UINT32 Value = 0; + INT32 Ret = 0; +#ifdef RTMP_PCI_SUPPORT + UINT32 Index; + UINT32 TxIdx = 0; + RTMP_TX_RING *pTxRing = &pAd->TxRing[QID_AC_BE]; +#endif /* RTMP_MAC_PCI */ +#ifdef CONFIG_AP_SUPPORT + INT32 IdBss, MaxNumBss = pAd->ApCfg.BssidNum; +#endif + + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + /* TxRx switch workaround */ + AsicSetRxPath(pAd, 0); + AsicSetMacTxRx(pAd, ASIC_MAC_RX, TRUE); + RtmpusecDelay(10000); + AsicSetMacTxRx(pAd, ASIC_MAC_RX, FALSE); + + CmdChannelSwitch(pAd, ATECtrl->ControlChl, ATECtrl->Channel, ATECtrl->BW, + pAd->CommonCfg.TxStream, pAd->CommonCfg.RxStream); + + + + + AsicSetMacTxRx(pAd, ASIC_MAC_RX_RXV, FALSE); + + /* Stop send TX packets */ + RTMP_OS_NETDEV_STOP_QUEUE(pAd->net_dev); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (MaxNumBss > MAX_MBSSID_NUM(pAd)) + MaxNumBss = MAX_MBSSID_NUM(pAd); + + /* first IdBss must not be 0 (BSS0), must be 1 (BSS1) */ + for (IdBss = FIRST_MBSSID; IdBss < MAX_MBSSID_NUM(pAd); IdBss++) + { + if (pAd->ApCfg.MBSSID[IdBss].wdev.if_dev) + RTMP_OS_NETDEV_STOP_QUEUE(pAd->ApCfg.MBSSID[IdBss].wdev.if_dev); + } + } +#endif + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET); + + /* Disable PDMA */ + AsicSetWPDMA(pAd, PDMA_TX, 0); + + /* Polling TX/RX path until packets empty */ +#ifdef RTMP_PCI_SUPPORT + MTPciPollTxRxEmpty(pAd); +#endif /* RTMP_MAC_PCI */ + + /* Turn on RX again if set before */ + if (ATECtrl->Mode & ATE_RXFRAME) + AsicSetMacTxRx(pAd, ASIC_MAC_RX_RXV, TRUE); + + RTMP_OS_NETDEV_START_QUEUE(pAd->net_dev); + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (MaxNumBss > MAX_MBSSID_NUM(pAd)) + MaxNumBss = MAX_MBSSID_NUM(pAd); + + /* first IdBss must not be 0 (BSS0), must be 1 (BSS1) */ + for (IdBss = FIRST_MBSSID; IdBss < MAX_MBSSID_NUM(pAd); IdBss++) + { + if (pAd->ApCfg.MBSSID[IdBss].wdev.if_dev) + RTMP_OS_NETDEV_START_QUEUE(pAd->ApCfg.MBSSID[IdBss].wdev.if_dev); + } + } +#endif + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET); + + +#ifdef RTMP_PCI_SUPPORT + RTMP_IO_READ32(pAd, pTxRing->hw_didx_addr, &pTxRing->TxDmaIdx); + pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; + pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; + RTMP_IO_WRITE32(pAd, pTxRing->hw_cidx_addr, pTxRing->TxCpuIdx); + + if (ATECtrl->bQAEnabled != TRUE) /* reset in start tx when iwpriv */ + ATECtrl->TxDoneCount = 0; + + for (Index = 0; Index < TX_RING_SIZE; Index++) + { + if (ATEPayloadAlloc(pAd, Index) != (NDIS_STATUS_SUCCESS)) + { + return (NDIS_STATUS_FAILURE); + } + + pTxRing->Cell[Index].pNdisPacket = ATECtrl->pAtePacket[Index]; + } + + for (Index = 0; (Index < TX_RING_SIZE) && (Index < ATECtrl->TxCount); Index++) + { + DBGPRINT(RT_DEBUG_OFF, ("Index = %d, ATECtrl->TxCount = %d\n", Index, ATECtrl->TxCount)); + TxIdx = pTxRing->TxCpuIdx; + + if (MT_ATESetupFrame(pAd, TxIdx) != 0) + { + return (NDIS_STATUS_FAILURE); + } + + if (((Index + 1) < TX_RING_SIZE) && (Index < ATECtrl->TxCount)) + { + INC_RING_INDEX(pTxRing->TxCpuIdx, TX_RING_SIZE); + } + } +#endif /* RTMP_MAC_PCI */ + /* Enable PDMA */ + AsicSetWPDMA(pAd, PDMA_TX_RX, 1); + + ATECtrl->Mode |= ATE_TXFRAME; +#ifdef RTMP_PCI_SUPPORT + RTMP_IO_WRITE32(pAd, pTxRing->hw_cidx_addr, pTxRing->TxCpuIdx); +#endif /* RTMP_MAC_PCI */ + + + + + /* Low temperature high rate EVM degrade Patch v2 */ + if ((MTK_REV_GTE(pAd, MT7603, MT7603E1)) || + (MTK_REV_GTE(pAd, MT7628, MT7628E1))) + { + if (ATECtrl->TxAntennaSel == 0) + { + RTMP_IO_READ32(pAd, CR_RFINTF_00, &Value); + Value &= ~CR_RFINTF_CAL_NSS_MASK; + Value |= CR_RFINTF_CAL_NSS(0x0); + RTMP_IO_WRITE32(pAd, CR_RFINTF_00, Value); + } + else if (ATECtrl->TxAntennaSel == 1) + { + RTMP_IO_READ32(pAd, CR_RFINTF_00, &Value); + Value &= ~CR_RFINTF_CAL_NSS_MASK; + Value |= CR_RFINTF_CAL_NSS(0x0); + RTMP_IO_WRITE32(pAd, CR_RFINTF_00, Value); + } + else if (ATECtrl->TxAntennaSel == 2) + { + RTMP_IO_READ32(pAd, CR_RFINTF_00, &Value); + Value &= ~CR_RFINTF_CAL_NSS_MASK; + Value |= CR_RFINTF_CAL_NSS(0x1); + RTMP_IO_WRITE32(pAd, CR_RFINTF_00, Value); + } + } + + return Ret; +} + + +static INT32 MT_ATEStartRx(RTMP_ADAPTER *pAd) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0, Value; +#ifdef CONFIG_AP_SUPPORT + INT32 IdBss, MaxNumBss = pAd->ApCfg.BssidNum; +#endif + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + +#ifdef RTMP_MAC_PCI + AsicSetMacTxRx(pAd, ASIC_MAC_RX_RXV, FALSE); +#endif /* RTMP_MAC_PCI */ + + + + /* Stop send TX packets */ + RTMP_OS_NETDEV_STOP_QUEUE(pAd->net_dev); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (MaxNumBss > MAX_MBSSID_NUM(pAd)) + MaxNumBss = MAX_MBSSID_NUM(pAd); + + /* first IdBss must not be 0 (BSS0), must be 1 (BSS1) */ + for (IdBss = FIRST_MBSSID; IdBss < MAX_MBSSID_NUM(pAd); IdBss++) + { + if (pAd->ApCfg.MBSSID[IdBss].wdev.if_dev) + RTMP_OS_NETDEV_STOP_QUEUE(pAd->ApCfg.MBSSID[IdBss].wdev.if_dev); + } + } +#endif + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET); + + AsicSetWPDMA(pAd, PDMA_TX, 0); + +#ifdef RTMP_MAC_PCI + /* Polling TX/RX path until packets empty */ + MTPciPollTxRxEmpty(pAd); +#endif + + RTMP_OS_NETDEV_START_QUEUE(pAd->net_dev); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (MaxNumBss > MAX_MBSSID_NUM(pAd)) + MaxNumBss = MAX_MBSSID_NUM(pAd); + + /* first IdBss must not be 0 (BSS0), must be 1 (BSS1) */ + for (IdBss = FIRST_MBSSID; IdBss < MAX_MBSSID_NUM(pAd); IdBss++) + { + if (pAd->ApCfg.MBSSID[IdBss].wdev.if_dev) + RTMP_OS_NETDEV_START_QUEUE(pAd->ApCfg.MBSSID[IdBss].wdev.if_dev); + } + } +#endif + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET); + + + /* Turn on TX again if set before */ + if (ATECtrl->Mode & ATE_TXFRAME) + { + AsicSetMacTxRx(pAd, ASIC_MAC_TX, TRUE); + } + /* reset counter when iwpriv only */ + if (ATECtrl->bQAEnabled != TRUE) + { + ATECtrl->RxTotalCnt = 0; + } + pAd->WlanCounters.FCSErrorCount.u.LowPart = 0; + + RTMP_IO_READ32(pAd, RMAC_RFCR, &Value); + Value |= RM_FRAME_REPORT_EN; + RTMP_IO_WRITE32(pAd, RMAC_RFCR, Value); + +#ifdef RTMP_MAC_PCI + AsicSetMacTxRx(pAd, ASIC_MAC_RX_RXV, TRUE); +#endif /* RTMP_MAC_PCI */ + + + + /* Enable PDMA */ + AsicSetWPDMA(pAd, PDMA_TX_RX, 1); + + + ATECtrl->Mode |= ATE_RXFRAME; + + +printk("<-----iverson MT_ATEStartRx \n "); + + return Ret; +} + + +static INT32 MT_ATEStopTx(RTMP_ADAPTER *pAd, UINT32 Mode) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0; +#ifdef RTMP_MAC_PCI + UINT32 Index; + TXD_STRUC *pTxD = NULL; + RTMP_TX_RING *pTxRing = &pAd->TxRing[QID_AC_BE]; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD = NULL; + UCHAR tx_hw_info[TXD_SIZE]; +#endif /* RT_BIG_ENDIAN */ +#endif /* RTMP_MAC_PCI */ + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + if (Mode == ATE_TXCARR) + { + + + + } + else if (Mode == ATE_TXCARRSUPP) + { + + + } + else if ((Mode & ATE_TXFRAME) || (Mode == ATE_STOP)) + { + if (Mode == ATE_TXCONT) + { + + + } + + /* Disable PDMA */ + AsicSetWPDMA(pAd, PDMA_TX_RX, 0); +#ifdef RTMP_MAC_PCI + + for (Index = 0; Index < TX_RING_SIZE; Index++) + { + PNDIS_PACKET pPacket; + +#ifndef RT_BIG_ENDIAN + pTxD = (TXD_STRUC *)pAd->TxRing[QID_AC_BE].Cell[Index].AllocVa; +#else + pDestTxD = (TXD_STRUC *)pAd->TxRing[QID_AC_BE].Cell[Index].AllocVa; + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif /* !RT_BIG_ENDIAN */ + pTxD->DMADONE = 0; + pPacket = pTxRing->Cell[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[Index].pNdisPacket = NULL; + + pPacket = pTxRing->Cell[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[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 */ + + + ATECtrl->Mode &= ~ATE_TXFRAME; + + /* Enable PDMA */ + AsicSetWPDMA(pAd, PDMA_TX_RX, 1); + } + + return Ret; +} + + +static INT32 MT_ATEStopRx(RTMP_ADAPTER *pAd) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0; + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + Ret = AsicSetMacTxRx(pAd, ASIC_MAC_RX_RXV, FALSE); + + ATECtrl->Mode &= ~ATE_RXFRAME; + + + return Ret; +} + + +static INT32 MT_ATESetTxAntenna(RTMP_ADAPTER *pAd, CHAR Ant) +{ + + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0; + UINT32 Value; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + /* 0: All 1:TX0 2:TX1 */ + ATECtrl->TxAntennaSel = Ant; + + if ((MTK_REV_GTE(pAd, MT7603, MT7603E1)) || + (MTK_REV_GTE(pAd, MT7628, MT7628E1))|| + (MTK_REV_GTE(pAd, MT7628, MT7603E2))) + { + if (ATECtrl->TxAntennaSel == 0) + { + RTMP_IO_READ32(pAd, CR_RFINTF_00, &Value); + Value &= ~CR_RFINTF_CAL_NSS_MASK; + Value |= CR_RFINTF_CAL_NSS(0x0); + RTMP_IO_WRITE32(pAd, CR_RFINTF_00, Value); + /* Tx both patch, ePA/eLNA/, iPA/eLNA, iPA/iLNA */ + { + + UINT32 RemapBase, RemapOffset; + UINT32 RestoreValue; + UINT32 value; + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + RemapBase = GET_REMAP_2_BASE(0x81060008) << 19; + RemapOffset = GET_REMAP_2_OFFSET(0x81060008); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + if ((MTK_REV_GTE(pAd, MT7603, MT7603E1))|| + (MTK_REV_GTE(pAd, MT7603, MT7603E2))){ + value = 0x04852390; + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, value); + }else if(MTK_REV_GTE(pAd, MT7628, MT7628E1)){ + value = 0x00489523; + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, value); + } + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); + + } + } + else if (ATECtrl->TxAntennaSel == 1) + { + RTMP_IO_READ32(pAd, CR_RFINTF_00, &Value); + Value &= ~CR_RFINTF_CAL_NSS_MASK; + Value |= CR_RFINTF_CAL_NSS(0x0); + RTMP_IO_WRITE32(pAd, CR_RFINTF_00, Value); + + /* Tx0 patch, ePA/eLNA/, iPA/eLNA, iPA/iLNA */ + { + UINT32 RemapBase, RemapOffset; + UINT32 RestoreValue; + UINT32 value; + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + RemapBase = GET_REMAP_2_BASE(0x81060008) << 19; + RemapOffset = GET_REMAP_2_OFFSET(0x81060008); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + if ((MTK_REV_GTE(pAd, MT7603, MT7603E1))|| + (MTK_REV_GTE(pAd, MT7603, MT7603E2))){ + value = 0x04852390; + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, value); + }else if(MTK_REV_GTE(pAd, MT7628, MT7628E1)){ + value = 0x00489523; + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, value); + } + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); + } + } + else if (ATECtrl->TxAntennaSel == 2) + { + RTMP_IO_READ32(pAd, CR_RFINTF_00, &Value); + Value &= ~CR_RFINTF_CAL_NSS_MASK; + Value |= CR_RFINTF_CAL_NSS(0x1); + RTMP_IO_WRITE32(pAd, CR_RFINTF_00, Value); + /* Tx1 patch, ePA/eLNA/, iPA/eLNA, iPA/iLNA */ + { + UINT32 RemapBase, RemapOffset; + UINT32 RestoreValue; + UINT32 value; + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + RemapBase = GET_REMAP_2_BASE(0x81060008) << 19; + RemapOffset = GET_REMAP_2_OFFSET(0x81060008); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + if ((MTK_REV_GTE(pAd, MT7603, MT7603E1))|| + (MTK_REV_GTE(pAd, MT7603, MT7603E2))){ + value = 0x04856790; + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, value); + }else if(MTK_REV_GTE(pAd, MT7628, MT7628E1)){ + value = 0x00489567; + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, value); + } + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); + } + } + } + + return Ret; +} + + +static INT32 MT_ATESetRxAntenna(RTMP_ADAPTER *pAd, CHAR Ant) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + ATECtrl->RxAntennaSel = Ant; + /* set RX path */ + AsicSetRxPath(pAd, (UINT32)ATECtrl->RxAntennaSel); + return Ret; +} + + +static INT32 MT_ATESetTxFreqOffset(RTMP_ADAPTER *pAd, UINT32 FreqOffset) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0; + ATECtrl->RFFreqOffset = FreqOffset; + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + AsicSetRfFreqOffset(pAd, ATECtrl->RFFreqOffset); + + return Ret; +} + +static INT32 MT_ATESetChannel(RTMP_ADAPTER *pAd, INT16 Value) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + CmdChannelSwitch(pAd, ATECtrl->ControlChl, ATECtrl->Channel, ATECtrl->BW, + pAd->CommonCfg.TxStream, pAd->CommonCfg.RxStream); + + return Ret; +} + + +static INT32 MT_ATESetBW(RTMP_ADAPTER *pAd, INT16 Value) +{ + //ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0; + UINT32 val = 0; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + RTMP_IO_READ32(pAd, AGG_BWCR, &val); + val &= (~0x0c); + switch (Value) + { + case BW_20: + val |= (0); + break; + case BW_40: + val |= (0x1 << 2); + break; + case BW_80: + val |= (0x2 << 2); + break; + } + RTMP_IO_WRITE32(pAd, AGG_BWCR, val); + /* TODO: check CMD_CH_PRIV_ACTION_BW_REQ */ + //CmdChPrivilege(pAd, CMD_CH_PRIV_ACTION_BW_REQ, ATECtrl->ControlChl, ATECtrl->Channel, + // ATECtrl->BW, pAd->CommonCfg.TxStream, pAd->CommonCfg.RxStream); + + + return Ret; +} + + +static INT32 MT_ATESampleRssi(RTMP_ADAPTER *pAd, RX_BLK *RxBlk) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0; + + if (RxBlk->rx_signal.raw_rssi[0] != 0) + { + ATECtrl->LastRssi0 = ConvertToRssi(pAd, + (struct raw_rssi_info *)(&RxBlk->rx_signal.raw_rssi[0]), RSSI_IDX_0); + + ATECtrl->AvgRssi0X8 = (ATECtrl->AvgRssi0X8 - ATECtrl->AvgRssi0) + + ATECtrl->LastRssi0; + ATECtrl->AvgRssi0 = ATECtrl->AvgRssi0X8 >> 3; + } + + if (RxBlk->rx_signal.raw_rssi[1] != 0) + { + ATECtrl->LastRssi1 = ConvertToRssi(pAd, + (struct raw_rssi_info *)(&RxBlk->rx_signal.raw_rssi[0]), RSSI_IDX_1); + + ATECtrl->AvgRssi1X8 = (ATECtrl->AvgRssi1X8 - ATECtrl->AvgRssi1) + + ATECtrl->LastRssi1; + ATECtrl->AvgRssi1 = ATECtrl->AvgRssi1X8 >> 3; + } + + ATECtrl->LastSNR0 = RxBlk->rx_signal.raw_snr[0];; + ATECtrl->LastSNR1 = RxBlk->rx_signal.raw_snr[1]; + + ATECtrl->NumOfAvgRssiSample++; + + return Ret; +} + +static INT32 MT_ATESetAIFS(RTMP_ADAPTER *pAd, CHAR Value) +{ + //ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0; + /* Test mode use AC0 for TX */ + AsicSetWmmParam(pAd, WMM_PARAM_AC_0, WMM_PARAM_AIFSN, Value); + return Ret; +} + +static INT32 MT_ATESetTSSI(RTMP_ADAPTER *pAd, CHAR WFSel, CHAR Setting) +{ + //ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0; + Ret = AsicSetTSSI(pAd, Setting, WFSel); + return Ret; +} + +static INT32 MT_ATESetDPD(RTMP_ADAPTER *pAd, CHAR WFSel, CHAR Setting) +{ + /* !!TEST MODE ONLY!! Normal Mode control by FW and Never disable */ + /* WF0 = 0, WF1 = 1, WF ALL = 2 */ + //ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0; + Ret = AsicSetDPD(pAd, Setting, WFSel); + return Ret; +} + +static INT32 MT_ATEStartTxTone(RTMP_ADAPTER *pAd, UINT32 Mode) +{ + //ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0; + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + AsicSetTxToneTest(pAd, 1, Mode); + return Ret; +} +static INT32 MT_ATESetTxTonePower(RTMP_ADAPTER *pAd, INT32 pwr1, INT32 pwr2) +{ + //ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0; + DBGPRINT(RT_DEBUG_OFF, ("%s, pwr1:%d, pwr2:%d\n", __FUNCTION__, pwr1, pwr2)); + AsicSetTxTonePower(pAd, pwr1, pwr2); + return Ret; +} + +static INT32 MT_ATEStopTxTone(RTMP_ADAPTER *pAd) +{ + //ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0; + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + AsicSetTxToneTest(pAd, 0, 0); + return Ret; +} + +static INT32 MT_ATEStartContinousTx(RTMP_ADAPTER *pAd, CHAR WFSel) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + INT32 Ret = 0; + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + AsicStartContinousTx(pAd, ATECtrl->PhyMode, ATECtrl->BW, ATECtrl->ControlChl, ATECtrl->Mcs, WFSel); + return Ret; +} + + +static INT32 MT_RfRegWrite(RTMP_ADAPTER *pAd, UINT32 WFSel, UINT32 Offset, UINT32 Value) +{ + INT32 Ret = 0; + + Ret = CmdRFRegAccessWrite(pAd, WFSel, Offset, Value); + + return Ret; +} + + +static INT32 MT_RfRegRead(RTMP_ADAPTER *pAd, UINT32 WFSel, UINT32 Offset, UINT32 *Value) +{ + INT32 Ret = 0; + + Ret = CmdRFRegAccessRead(pAd, WFSel, Offset, Value); + + return Ret; +} + + +static INT32 MT_GetFWInfo(RTMP_ADAPTER *pAd, UCHAR *FWInfo) +{ + + RTMP_CHIP_CAP *cap = &pAd->chipCap; + + memcpy(FWInfo, cap->FWImageName + cap->fw_len - 36, 36); + + return 0; +} + + +static ATE_OPERATION MT_ATEOp = { + .ATEStart = MT_ATEStart, + .ATEStop = MT_ATEStop, + .StartTx = MT_ATEStartTx, + .StartRx = MT_ATEStartRx, + .StopTx = MT_ATEStopTx, + .StopRx = MT_ATEStopRx, + .SetTxPower0 = MT_ATESetTxPower0, + .SetTxPower1 = MT_ATESetTxPower1, + .SetTxAntenna = MT_ATESetTxAntenna, + .SetRxAntenna = MT_ATESetRxAntenna, + .SetTxFreqOffset = MT_ATESetTxFreqOffset, + .SetChannel = MT_ATESetChannel, + .SetBW = MT_ATESetBW, + .SampleRssi = MT_ATESampleRssi, + .SetAIFS = MT_ATESetAIFS, + .SetTSSI = MT_ATESetTSSI, + .SetDPD = MT_ATESetDPD, + .StartTxTone = MT_ATEStartTxTone, + .SetTxTonePower = MT_ATESetTxTonePower, + .StopTxTone = MT_ATEStopTxTone, + .StartContinousTx = MT_ATEStartContinousTx, + .RfRegWrite = MT_RfRegWrite, + .RfRegRead = MT_RfRegRead, + .GetFWInfo = MT_GetFWInfo, +}; + + +INT32 MT_ATEInit(RTMP_ADAPTER *pAd) +{ + ATE_CTRL *ATECtrl = &pAd->ATECtrl; + + ATECtrl->ATEOp = &MT_ATEOp; + + return 0; +} diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/qa_agent.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/qa_agent.c new file mode 100644 index 000000000..15a988109 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/ate/qa_agent.c @@ -0,0 +1,2094 @@ +/* + *************************************************************************** + * 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: + qa_agent.c +*/ + +#include "rt_config.h" + +static INT ResponseToQA( + HQA_CMD_FRAME *HqaCmdFrame, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + INT32 Length, + INT32 Status) +{ + INT ret = 0; + + HqaCmdFrame->Length = OS_HTONS((Length)); + + Status = OS_HTONS((Status)); + memcpy(HqaCmdFrame->Data, &Status, 2); + + WRQ->u.data.length = sizeof((HqaCmdFrame)->MagicNo) + sizeof((HqaCmdFrame)->Type) + + sizeof((HqaCmdFrame)->Id) + sizeof((HqaCmdFrame)->Length) + + sizeof((HqaCmdFrame)->Sequence) + OS_NTOHS((HqaCmdFrame)->Length); + + DBGPRINT(RT_DEBUG_TRACE, ("WRQ->u.data.length = %d\n", WRQ->u.data.length)); + + if (copy_to_user(WRQ->u.data.pointer, (UCHAR *)(HqaCmdFrame), WRQ->u.data.length)) + { + + DBGPRINT_ERR(("copy_to_user() fail in %s\n", __FUNCTION__)); + return (-EFAULT); + } + else + { + } + + return ret; +} + + +static INT32 HQA_OpenAdapter( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ATECtrl->bQAEnabled = TRUE; + + /* Prepare feedback as soon as we can to avoid QA timeout. */ + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + Ret = ATEOp->ATEStart(pAd); + + return Ret; +} + + +static INT32 HQA_CloseAdapter( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ATECtrl->bQAEnabled = FALSE; + + /* Prepare feedback as soon as we can to avoid QA timeout. */ + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + Ret = ATEOp->ATEStop(pAd); + + return Ret; +} + + +static INT32 HQA_StartTx( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + UINT32 TxCount; + UINT16 TxLength; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy(&TxCount, HqaCmdFrame->Data, 4); + TxCount = OS_NTOHL(TxCount); + + memcpy(&TxLength, HqaCmdFrame->Data + 4, 2); + TxLength = OS_NTOHS(TxLength); + + if (TxCount == 0) + ATECtrl->TxCount = 0xFFFFFFFF; + else + ATECtrl->TxCount = TxCount; + + ATECtrl->TxLength = TxLength; + ATECtrl->bQATxStart = TRUE; + + Ret = ATEOp->StartTx(pAd); + + if (ATECtrl->bQATxStart == TRUE) + ATECtrl->TxStatus = 1; + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + return Ret; +} + + +static INT32 HQA_StartTxExt( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_StartTxContiTx( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_StartTxCarrier( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_StartRx( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ATECtrl->bQARxStart = TRUE; + + Ret = ATEOp->StartRx(pAd); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + return Ret; +} + + +static INT32 HQA_StopTx( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + UINT32 Mode; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + Mode = ATECtrl->Mode; + ATECtrl->Mode &= ATE_TXSTOP; + ATECtrl->bQATxStart = FALSE; + + Ret = ATEOp->StopTx(pAd, Mode); + + ATECtrl->TxStatus = 0; + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + return Ret; +} + + +static INT32 HQA_StopContiTx( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + AsicStopContinousTx(pAd); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_StopTxCarrier( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_StopRx( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ATECtrl->Mode &= ATE_RXSTOP; + ATECtrl->bQARxStart = FALSE; + + Ret = ATEOp->StopRx(pAd); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + return Ret; +} + + +static INT32 HQA_SetTxPath( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT16 Value = 0; + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy((PUCHAR)&Value, HqaCmdFrame->Data, 2); + Value = OS_NTOHS(Value); + + Ret = ATEOp->SetTxAntenna(pAd, (CHAR)Value); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + return Ret; +} + + +static INT32 HQA_SetRxPath( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT16 Value = 0; + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy((PUCHAR)&Value, HqaCmdFrame->Data, 2); + Value = OS_NTOHS(Value); + + Ret = ATEOp->SetRxAntenna(pAd, (CHAR)Value); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + return Ret; +} + + +static INT32 HQA_SetTxIPG( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Value = 0; + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy((PUCHAR)&Value, HqaCmdFrame->Data, 4); + Value = OS_NTOHL(Value); + + ATEOp->SetAIFS(pAd, (UINT32)Value); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + return Ret; + +} + + +static INT32 HQA_SetTxPower0( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + INT16 Value = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy((PUCHAR)&Value, HqaCmdFrame->Data, 2); + Value = OS_NTOHS(Value); + + Ret = ATEOp->SetTxPower0(pAd, Value); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + return Ret; +} + + +static INT32 HAQ_SetTxPower1( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + INT16 Value = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy((PUCHAR)&Value, HqaCmdFrame->Data, 2); + Value = OS_NTOHS(Value); + + Ret = ATEOp->SetTxPower1(pAd, Value); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + return Ret; +} + + +static HQA_CMD_HANDLER HQA_CMD_SET0[] = +{ + /* cmd id start from 0x1000 */ + HQA_OpenAdapter, /* 0x1000 */ + HQA_CloseAdapter, /* 0x1001 */ + HQA_StartTx, /* 0x1002 */ + HQA_StartTxExt, /* 0x1003 */ + HQA_StartTxContiTx, /* 0x1004 */ + HQA_StartTxCarrier, /* 0x1005 */ + HQA_StartRx, /* 0x1006 */ + HQA_StopTx, /* 0x1007 */ + HQA_StopContiTx, /* 0x1008 */ + HQA_StopTxCarrier, /* 0x1009 */ + HQA_StopRx, /* 0x100A */ + HQA_SetTxPath, /* 0x100B */ + HQA_SetRxPath, /* 0x100C */ + HQA_SetTxIPG, /* 0x100D */ + HQA_SetTxPower0, /* 0x100E */ + HAQ_SetTxPower1, /* 0x100F */ +}; + + +static INT32 HQA_SetChannel( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT32 Value; + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + + memcpy((PUCHAR)&Value, HqaCmdFrame->Data, 4); + Value = OS_NTOHL(Value); + + ATECtrl->Channel = Value; + + DBGPRINT(RT_DEBUG_OFF, ("%s: Channel = %d, BW = %d\n", __FUNCTION__, ATECtrl->Channel, ATECtrl->BW)); + + if (ATECtrl->BW == BW_20) + ATECtrl->ControlChl = ATECtrl->Channel; + else if (ATECtrl->BW == BW_40) + ATECtrl->ControlChl = ATECtrl->Channel - 2; + + Ret = ATEOp->SetChannel(pAd, Value); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + return Ret; +} + + +static INT32 HQA_SetPreamble( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Value = 0; + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy((PUCHAR)&Value, HqaCmdFrame->Data, 4); + Value = OS_NTOHL(Value); + ATECtrl->PhyMode = (UCHAR)Value; + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + return Ret; +} + + +static INT32 HQA_SetRate( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Value = 0; + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy((PUCHAR)&Value, HqaCmdFrame->Data, 4); + Value = OS_NTOHL(Value); + ATECtrl->Mcs = (UCHAR)Value; + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + return Ret; +} + + +static INT32 HQA_SetNss( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_SetSystemBW( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT32 Value; + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + + memcpy((PUCHAR)&Value, HqaCmdFrame->Data, 4); + Value = OS_NTOHL(Value); + + ATECtrl->BW = Value; + + DBGPRINT(RT_DEBUG_OFF, ("%s: Channel = %d, BW = %d\n", __FUNCTION__, ATECtrl->Channel, ATECtrl->BW)); + + if (ATECtrl->BW == BW_20) + ATECtrl->ControlChl = ATECtrl->Channel; + else if (ATECtrl->BW == BW_40) + ATECtrl->ControlChl = ATECtrl->Channel - 2; + + Ret = ATEOp->SetBW(pAd, Value); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + return Ret; +} + + +static INT32 HQA_SetPerPktBW( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_SetPrimaryBW( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_SetFreqOffset( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Value = 0; + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy((PUCHAR)&Value, HqaCmdFrame->Data, 4); + Value = OS_NTOHL(Value); + + ATEOp->SetTxFreqOffset(pAd, (UINT32)Value); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_SetAutoResponder( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + + + return Ret; +} + + +static INT32 HQA_SetTssiOnOff( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Value = 0, WFSel; + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + /* ON/OFF:4 WF Sel:4 */ + memcpy((PUCHAR)&Value, HqaCmdFrame->Data, 4); + Value = OS_NTOHL(Value); + + memcpy((PUCHAR)&WFSel, HqaCmdFrame->Data + 4, 4); + WFSel = OS_NTOHL(WFSel); + + ATEOp->SetTSSI(pAd, (CHAR)WFSel, (CHAR)Value); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + return Ret; +} + + +static INT32 HQA_SetRxHighLowTemperatureCompensation( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static HQA_CMD_HANDLER HQA_CMD_SET1[] = +{ + /* cmd id start from 0x1100 */ + HQA_SetChannel, /* 0x1100 */ + HQA_SetPreamble, /* 0x1101 */ + HQA_SetRate, /* 0x1102 */ + HQA_SetNss, /* 0x1103 */ + HQA_SetSystemBW, /* 0x1104 */ + HQA_SetPerPktBW, /* 0x1105 */ + HQA_SetPrimaryBW, /* 0x1106 */ + HQA_SetFreqOffset, /* 0x1107 */ + HQA_SetAutoResponder, /* 0x1108 */ + HQA_SetTssiOnOff, /* 0x1109 */ + HQA_SetRxHighLowTemperatureCompensation, /* 0x110A */ +}; + + +static INT32 HQA_ResetTxRxCounter( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + AsicGetRxStat(pAd, HQA_RX_RESET_PHY_COUNT); + ATECtrl->RxTotalCnt = 0; + ATECtrl->TxDoneCount = 0; + ATECtrl->RxMacFCSErrCount = 0; + ATECtrl->RxMacMdrdyCount = 0; + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_GetStatistics( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_GetRxOKData( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_GetRxOKOther( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_GetRxAllPktCount( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_GetTxTransmitted( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT32 Value = 0; + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + + Value = ATECtrl->TxDoneCount; + + DBGPRINT(RT_DEBUG_OFF, ("%s: TxDoneCount = %d\n", __FUNCTION__, ATECtrl->TxDoneCount)); + + Value = OS_HTONL(Value); + + memcpy(HqaCmdFrame->Data + 2, &Value, 4); + + ResponseToQA(HqaCmdFrame, WRQ, 6, Ret); + return Ret; +} + + +static INT32 HQA_GetHwCounter( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_CalibrationOperation( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static HQA_CMD_HANDLER HQA_CMD_SET2[] = +{ + /* cmd id start from 0x1200 */ + HQA_ResetTxRxCounter, /* 0x1200 */ + HQA_GetStatistics, /* 0x1201 */ + HQA_GetRxOKData, /* 0x1202 */ + HQA_GetRxOKOther, /* 0x1203 */ + HQA_GetRxAllPktCount, /* 0x1204 */ + HQA_GetTxTransmitted, /* 0x1205 */ + HQA_GetHwCounter, /* 0x1206 */ + HQA_CalibrationOperation, /* 0x1207 */ +}; + +/*Nobody uses it currently */ + +static VOID memcpy_exs(PRTMP_ADAPTER pAd, UCHAR *dst, UCHAR *src, ULONG len) +{ + ULONG i; + { + 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 INT32 HQA_MacBbpRegRead( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + INT32 Ret = 0; + UINT32 Offset, Value; + BOOLEAN IsFound; + + memcpy(&Offset, HqaCmdFrame->Data, 4); + Offset = OS_NTOHL(Offset); + + IsFound = mt_mac_cr_range_mapping(&Offset); + + if (!IsFound) + { + UINT32 RemapBase, RemapOffset; + UINT32 RestoreValue; + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + RemapBase = GET_REMAP_2_BASE(Offset) << 19; + RemapOffset = GET_REMAP_2_OFFSET(Offset); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); + } + else + { + RTMP_IO_READ32(pAd, Offset, &Value); + } + + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Offset = %x, Value = %x\n", __FUNCTION__, Offset, Value)); + + Value = OS_HTONL(Value); + memcpy(HqaCmdFrame->Data + 2, &Value, 4); + + ResponseToQA(HqaCmdFrame, WRQ, 6, Ret); + + return Ret; +} + + +static INT32 HQA_MacBbpRegWrite( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + INT32 Ret = 0; + UINT32 Offset, Value; + BOOLEAN IsFound; + + memcpy(&Offset, HqaCmdFrame->Data, 4); + memcpy(&Value, HqaCmdFrame->Data + 4, 4); + + Offset = OS_NTOHL(Offset); + Value = OS_NTOHL(Value); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Offset = %x, Value = %x\n", __FUNCTION__, Offset, Value)); + + IsFound = mt_mac_cr_range_mapping(&Offset); + + if (!IsFound) + { + UINT32 RemapBase, RemapOffset; + UINT32 RestoreValue; + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + RemapBase = GET_REMAP_2_BASE(Offset) << 19; + RemapOffset = GET_REMAP_2_OFFSET(Offset); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); + } + else + { + RTMP_IO_WRITE32(pAd, Offset, Value); + } + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + return Ret; +} + + +VOID RTMP_IO_READ_BULK(PRTMP_ADAPTER pAd, UCHAR *Dst, UINT32 Offset, UINT32 Len) +{ + UINT32 Index, Value = 0; + UCHAR *pDst; + BOOLEAN IsFound; + + DBGPRINT(RT_DEBUG_WARN, ("\n\n")); + + for (Index = 0 ; Index < (Len >> 2); Index++) + { + pDst = (Dst + (Index << 2)); + + IsFound = mt_mac_cr_range_mapping(&Offset); + + if (!IsFound) + { + UINT32 RemapBase, RemapOffset; + UINT32 RestoreValue; + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + RemapBase = GET_REMAP_2_BASE(Offset) << 19; + RemapOffset = GET_REMAP_2_OFFSET(Offset); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); + } + else + { + RTMP_IO_READ32(pAd, Offset, &Value); + } + + DBGPRINT(RT_DEBUG_TRACE,("%s: Offset = %x, Value = %x\n", __FUNCTION__, Offset, Value)); + + Value = OS_HTONL(Value); + memmove(pDst, &Value, 4); + Offset += 4; + } + + DBGPRINT(RT_DEBUG_WARN, ("\n\n")); + + return; +} + + +static INT32 HQA_MACBbpRegBulkRead( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + INT32 Ret = 0; + UINT32 Offset; + UINT16 Len, Tmp; + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + memcpy(&Offset, HqaCmdFrame->Data, 4); + Offset = OS_NTOHL(Offset); + + memcpy(&Len, HqaCmdFrame->Data + 4, 2); + Len = OS_NTOHS(Len); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Offset = %x, Len(unit: 4bytes) = %d\n", __FUNCTION__, Offset, Len)); + + if (Len > 371) + { + DBGPRINT_ERR(("%s : length requested is too large, make it smaller\n", __FUNCTION__)); + HqaCmdFrame->Length = OS_HTONS(2); + Tmp = OS_HTONS(1); + memcpy(HqaCmdFrame->Data, &Tmp, 2); + + return -EFAULT; + } + + RTMP_IO_READ_BULK(pAd, HqaCmdFrame->Data + 2, Offset, (Len << 2));/* unit in four bytes*/ + + ResponseToQA(HqaCmdFrame, WRQ, 2 + (Len << 2), Ret); + + return Ret; +} + + +static INT32 HQA_RfRegBulkRead( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0, Index; + UINT32 WfSel, Offset, Length, Value; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + + memcpy(&WfSel, HqaCmdFrame->Data, 4); + WfSel = OS_NTOHL(WfSel); + + memcpy(&Offset, HqaCmdFrame->Data + 4, 4); + Offset = OS_NTOHL(Offset); + + memcpy(&Length, HqaCmdFrame->Data + 8, 4); + Length = OS_NTOHL(Length); + + for (Index = 0; Index < Length; Index++) + { + Ret = ATEOp->RfRegRead(pAd, WfSel, Offset + Index * 4, &Value); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Wfsel = %d, Offset = %x, Value = %x\n", __FUNCTION__, WfSel, + Offset + Index * 4, Value)); + + if (Ret) + { + DBGPRINT(RT_DEBUG_ERROR, ("Wfsel = %d, Offset = %x, Value = %x fail\n", WfSel, + Offset + Index * 4, Value)); + break; + } + + Value = OS_HTONL(Value); + memcpy(HqaCmdFrame->Data + 2 + (Index * 4), &Value, 4); + } + + ResponseToQA(HqaCmdFrame, WRQ, 2 + (Length * 4), Ret); + + return Ret; +} + + +static INT32 HQA_RfRegBulkWrite( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0, Index; + UINT32 WfSel, Offset, Length, Value; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy(&WfSel, HqaCmdFrame->Data, 4); + WfSel = OS_NTOHL(WfSel); + + memcpy(&Offset, HqaCmdFrame->Data + 4, 4); + Offset = OS_NTOHL(Offset); + + memcpy(&Length, HqaCmdFrame->Data + 8, 4); + Length = OS_NTOHL(Length); + + for (Index = 0; Index < Length; Index++) + { + memcpy(&Value, HqaCmdFrame->Data + 12 + (Index * 4), 4); + Value = OS_NTOHL(Value); + DBGPRINT(RT_DEBUG_TRACE, ("%s: Wfsel = %d, Offset = %x, Value = %x\n", __FUNCTION__, + WfSel,Offset + Index * 4, Value)); + + Ret = ATEOp->RfRegWrite(pAd, WfSel, Offset + Index * 4, Value); + + if (Ret) + { + DBGPRINT(RT_DEBUG_ERROR, ("Wfsel = %d, Offset = %x, Value = %x fail\n", WfSel, + Offset + Index * 4, Value)); + break; + } + } + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + return Ret; +} + + +static INT32 HQA_ReadEEPROM( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + INT32 Ret = 0; + UINT16 Offset=0, Value=0; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy(&Offset, HqaCmdFrame->Data, 2); + Offset = OS_NTOHS(Offset); + + RT28xx_EEPROM_READ16(pAd, Offset, Value); + + 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(HqaCmdFrame->Data + 2, &Value, 2); + + ResponseToQA(HqaCmdFrame, WRQ, 4, Ret); + + return Ret; +} + + +static INT32 HQA_WriteEEPROM( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + INT32 Ret = 0; + UINT16 Offset=0, Value=0; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy(&Offset, HqaCmdFrame->Data, 2); + Offset = OS_NTOHS(Offset); + + memcpy(&Value, HqaCmdFrame->Data + 2, 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)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + + return Ret; +} + + +static INT32 HQA_ReadBulkEEPROM( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + INT32 Ret = 0; + UINT16 Offset; + UINT16 Len; + UINT32 u4MaxBufSize = EEPROM_SIZE >> 1; + UINT16 Buffer[u4MaxBufSize]; + + memcpy(&Offset, HqaCmdFrame->Data, 2); + Offset = OS_NTOHS(Offset); + + memcpy(&Len, HqaCmdFrame->Data + 2, 2); + Len = OS_NTOHS(Len); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Offset = %x, Length = %x\n", __FUNCTION__, Offset, Len)); + + EEReadAll(pAd, (UINT16 *)Buffer); + + if (Offset + Len <= EEPROM_SIZE) + memcpy_exs(pAd, HqaCmdFrame->Data + 2, (UCHAR *)Buffer+Offset, Len); + else + { + DBGPRINT_ERR(("%s : exceed EEPROM size\n", __FUNCTION__)); + Len = 0; + Ret = -1; + } + + ResponseToQA(HqaCmdFrame, WRQ, 2 + Len, Ret); + + return Ret; +} + + +static VOID EEWriteBulk(PRTMP_ADAPTER pAd, UINT16 *Data, UINT16 Offset, UINT16 Length) +{ + UINT16 Pos; + UINT16 Value; + UINT16 Len = Length; + + for (Pos = 0; Pos < (Len >> 1);) + { + Value = Data[Pos]; + RT28xx_EEPROM_WRITE16(pAd, Offset + (Pos * 2), Value); + Pos++; + } + + return; +} + + +static INT32 HQA_WriteBulkEEPROM( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + INT32 Ret = 0; + USHORT Offset; + USHORT Len; + UINT32 u4MaxBufSize = EEPROM_SIZE >> 1; + USHORT Buffer[u4MaxBufSize]; + + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy(&Offset, HqaCmdFrame->Data, 2); + Offset = OS_NTOHS(Offset); + + memcpy(&Len, HqaCmdFrame->Data + 2, 2); + Len = OS_NTOHS(Len); + + memcpy_exs(pAd, (UCHAR *)Buffer + Offset, (UCHAR *)HqaCmdFrame->Data + 4, Len); + +#if defined(RTMP_RBUS_SUPPORT) || defined(RTMP_FLASH_SUPPORT) + if (Len == 16) { + memcpy(pAd->eebuf + Offset, (UCHAR *)Buffer + Offset, Len); + } + if (Offset == 0x1f0) + rtmp_ee_flash_write_all(pAd, (PUSHORT)pAd->eebuf); + + if (Len != 16) +#endif + { + if ((Offset + Len) <= EEPROM_SIZE) + { + EEWriteBulk(pAd,(UINT16 *)(((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))); + } + } + + ResponseToQA(HqaCmdFrame, WRQ, 2 + Len, Ret); + + return Ret; +} + + +static INT32 HQA_CheckEfuseMode( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + UINT32 Value; + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + if (pAd->bUseEfuse) + Value = 1; + else + Value = 0; + + + Value = OS_HTONL(Value); + memcpy(HqaCmdFrame->Data + 2, &Value, 4); + + ResponseToQA(HqaCmdFrame, WRQ, 6, Ret); + return Ret; +} + + +static INT32 HQA_GetFreeEfuseBlock( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + UINT32 Value; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + eFuseGetFreeBlockCount(pAd, &Value); + + Value = OS_HTONL(Value); + memcpy(HqaCmdFrame->Data + 2, &Value, 4); + + ResponseToQA(HqaCmdFrame, WRQ, 6, Ret); + return Ret; +} + + +static INT32 HQA_GetEfuseBlockNr( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //UINT32 Value; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_WriteEFuseFromBuffer( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static HQA_CMD_HANDLER HQA_CMD_SET3[] = +{ + /* cmd id start from 0x1300 */ + HQA_MacBbpRegRead, /* 0x1300 */ + HQA_MacBbpRegWrite, /* 0x1301 */ + HQA_MACBbpRegBulkRead, /* 0x1302 */ + HQA_RfRegBulkRead, /* 0x1303 */ + HQA_RfRegBulkWrite, /* 0x1304 */ + HQA_ReadEEPROM, /* 0x1305 */ + HQA_WriteEEPROM, /* 0x1306 */ + HQA_ReadBulkEEPROM, /* 0x1307 */ + HQA_WriteBulkEEPROM, /* 0x1308 */ + HQA_CheckEfuseMode, /* 0x1309 */ + HQA_GetFreeEfuseBlock, /* 0x130A */ + HQA_GetEfuseBlockNr, /* 0x130B */ + HQA_WriteEFuseFromBuffer, /* 0x130C */ +}; + + +static INT32 HQA_ReadTempReferenceValue( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + +VOID HQA_GetThermalValue_CB(struct cmd_msg *msg, char *Data, UINT16 Len) +{ + struct _EXT_EVENT_GET_SENSOR_RESULT_T *EventExtCmdResult = (struct _EXT_EVENT_GET_SENSOR_RESULT_T *)Data; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + EventExtCmdResult->u4SensorResult = le2cpu32(EventExtCmdResult->u4SensorResult); + ATECtrl->thermal_val = EventExtCmdResult->u4SensorResult; + DBGPRINT(RT_DEBUG_OFF, ("ThemalSensor = 0x%x\n", EventExtCmdResult->u4SensorResult)); + DBGPRINT(RT_DEBUG_OFF, ("%s, value: 0x%x\n", __FUNCTION__, EventExtCmdResult->u4SensorResult)); + RTMP_OS_COMPLETE(&ATECtrl->cmd_done); +} + +static INT32 HQA_GetThermalValue( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + +#if defined(MT7603) || defined(MT7628) + UINT32 temperature=0; + temperature = MtAsicGetThemalSensor(pAd, 0); + temperature = OS_HTONL(temperature); + NdisMoveMemory(HqaCmdFrame->Data + 2, &temperature, 4); +#else + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + + CmdGetThemalSensorResult(pAd, 0); /* 0: get temperature; 1: get adc */ + Ret = RTMP_OS_WAIT_FOR_COMPLETION_TIMEOUT(&ATECtrl->cmd_done, ATECtrl->cmd_expire); + ATECtrl->thermal_val = OS_HTONL(ATECtrl->thermal_val); + NdisMoveMemory(HqaCmdFrame->Data + 2, &ATECtrl->thermal_val, 4); + + DBGPRINT(RT_DEBUG_OFF, ("%s--> val:0x%x\n", __FUNCTION__, ATECtrl->thermal_val)); +#endif /* MT7603 || MT7628 */ + + ResponseToQA(HqaCmdFrame, WRQ, 6, Ret); + + return Ret; +} + + +static INT32 HQA_SetSideBandOption( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static HQA_CMD_HANDLER HQA_CMD_SET4[] = +{ + /* cmd id start from 0x1400 */ + HQA_ReadTempReferenceValue, /* 0x1400 */ + HQA_GetThermalValue, /* 0x1401 */ + HQA_SetSideBandOption, /* 0x1402 */ +}; + + +static INT32 HQA_GetFWInfo( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + Ret = ATEOp->GetFWInfo(pAd, HqaCmdFrame->Data + 2); + + ResponseToQA(HqaCmdFrame, WRQ, 38, Ret); + return Ret; +} + + +static INT32 HQA_GetRxStatisticsAll( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + UINT32 value = 0; + UINT32 IBRssi0, IBRssi1, WBRssi0, WBRssi1; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + HQA_RX_STAT HqaRxStat; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + memset(&HqaRxStat, 0, sizeof(HQA_RX_STAT)); + /* Get latest FCSErr. sync iwpriv & HQA same FCSErr result */ + NICUpdateRawCounters(pAd); + HqaRxStat.MacFCSErr = OS_NTOHL(ATECtrl->RxMacFCSErrCount); + + value = AsicGetRxStat(pAd, HQA_RX_STAT_MAC_MDRDYCNT); + ATECtrl->RxMacMdrdyCount += value; + HqaRxStat.MacMdrdy= OS_NTOHL(ATECtrl->RxMacMdrdyCount); + + value = AsicGetRxStat(pAd, HQA_RX_STAT_PHY_FCSERRCNT); + HqaRxStat.FCSErr_OFDM = OS_NTOHL(value >> 16); + HqaRxStat.FCSErr_CCK = OS_NTOHL(value & 0xFFFF); + + value = AsicGetRxStat(pAd, HQA_RX_STAT_PD); + HqaRxStat.OFDM_PD = OS_NTOHL(value >> 16); + HqaRxStat.CCK_PD = OS_NTOHL(value & 0xFFFF); + + value = AsicGetRxStat(pAd, HQA_RX_STAT_CCK_SIG_SFD); + HqaRxStat.CCK_SIG_Err = OS_NTOHL(value >> 16); + HqaRxStat.CCK_SFD_Err = OS_NTOHL(value & 0xFFFF); + + value = AsicGetRxStat(pAd, HQA_RX_STAT_OFDM_SIG_TAG); + HqaRxStat.OFDM_SIG_Err = OS_NTOHL(value >> 16); + HqaRxStat.OFDM_TAG_Err = OS_NTOHL(value & 0xFFFF); + + value = AsicGetRxStat(pAd, HQA_RX_STAT_RSSI); + IBRssi0 = (value&0xFF000000) >> 24; + if (IBRssi0 > 128) + IBRssi0 -=256; + WBRssi0 = (value&0x00FF0000) >> 16; + if (WBRssi0 > 128) + WBRssi0 -=256; + IBRssi1 = (value&0x0000FF00) >> 8; + if (IBRssi1 > 128) + IBRssi1 -=256; + WBRssi1 = (value&0x000000FF); + if (WBRssi1 > 128) + WBRssi1 -=256; + HqaRxStat.IB_RSSSI0 = OS_NTOHL(IBRssi0); + HqaRxStat.WB_RSSSI0 = OS_NTOHL(WBRssi0); + HqaRxStat.IB_RSSSI1 = OS_NTOHL(IBRssi1); + HqaRxStat.WB_RSSSI1 = OS_NTOHL(WBRssi1); + + value = AsicGetRxStat(pAd, HQA_RX_STAT_PHY_MDRDYCNT); + HqaRxStat.PhyMdrdyOFDM = OS_NTOHL(value >>16); + HqaRxStat.PhyMdrdyCCK = OS_NTOHL(value & 0xFFFF); + + HqaRxStat.DriverRxCount = OS_NTOHL(ATECtrl->RxTotalCnt); + HqaRxStat.RCPI0 = OS_NTOHL(ATECtrl->RCPI0); + HqaRxStat.RCPI1 = OS_NTOHL(ATECtrl->RCPI1); + HqaRxStat.FreqOffsetFromRX = OS_NTOHL(ATECtrl->FreqOffsetFromRx); + HqaRxStat.RSSI0 = OS_NTOHL(ATECtrl->RSSI0); + HqaRxStat.RSSI1 = OS_NTOHL(ATECtrl->RSSI1); + + memcpy(HqaCmdFrame->Data + 2, &(HqaRxStat), sizeof(HQA_RX_STAT)); + + ResponseToQA(HqaCmdFrame, WRQ, (2+sizeof(HQA_RX_STAT)), Ret); + return Ret; +} + + +static INT32 HQA_StartContinousTx( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + INT32 Value = 0 , WFSel = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + /* Modulation:4 BW:4 PRI_CH:4 RATE:4 WFSel:4 */ + memcpy((PUCHAR)&Value, (PUCHAR)&HqaCmdFrame->Data, 4); + Value = OS_NTOHL(Value); + ATECtrl->PhyMode = (UCHAR)Value; + + memcpy((PUCHAR)&Value, (PUCHAR)&HqaCmdFrame->Data + 4, 4); + Value = OS_NTOHL(Value); + ATECtrl->BW = (UCHAR)Value; + + memcpy((PUCHAR)&Value, (PUCHAR)&HqaCmdFrame->Data + 8, 4); + Value = OS_NTOHL(Value); + //ATECtrl->ControlChl = (UCHAR)Value; //TODO QA Tool send this parameter with 0, which leads to error in channel switch, mask temperarily + + memcpy((PUCHAR)&Value, (PUCHAR)&HqaCmdFrame->Data + 12, 4); + Value = OS_NTOHL(Value); + ATECtrl->Mcs = (UCHAR)Value; + + memcpy((PUCHAR)&WFSel, (PUCHAR)&HqaCmdFrame->Data + 16, 4); + WFSel = OS_NTOHL(WFSel); + ATECtrl->TxAntennaSel = WFSel; + + ATEOp->StartContinousTx(pAd, (CHAR)WFSel); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_SetSTBC( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Value = 0; + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy((PUCHAR)&Value, (PUCHAR)&HqaCmdFrame->Data, 4); + Value = OS_NTOHL(Value); + + ATECtrl->Stbc = (UCHAR)Value; + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_SetShortGI( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Value = 0; + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy((PUCHAR)&Value, (PUCHAR)&HqaCmdFrame->Data, 4); + Value = OS_NTOHL(Value); + + ATECtrl->Sgi= (UCHAR)Value; + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_SetDPD( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Value = 0, WFSel; + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + /* ON/OFF:4 WF Sel:4 */ + memcpy((PUCHAR)&Value, (PUCHAR)&HqaCmdFrame->Data, 4); + Value = OS_NTOHL(Value); + + memcpy((PUCHAR)&WFSel, (PUCHAR)&HqaCmdFrame->Data + 4, 4); + WFSel = OS_NTOHL(WFSel); + + ATEOp->SetDPD(pAd, (CHAR)WFSel, (CHAR)Value); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + + +static INT32 HQA_StartContiTxTone( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Value = 0; + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy((PUCHAR)&Value, (PUCHAR)&HqaCmdFrame->Data, 4); + Value = OS_NTOHL(Value); + + ATEOp->StartTxTone(pAd, Value); + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + +static INT32 HQA_StopContiTxTone( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + ATEOp->StopTxTone(pAd); + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + +static INT32 HQA_CalibrationTestMode( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + INT32 Value = 0; + INT32 Ret = 0; + UINT8 Mode = 0; + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy((PUCHAR)&Value, (PUCHAR)&HqaCmdFrame->Data, 4); + Value = OS_NTOHL(Value); + if (Value == 0){ + ATECtrl->Mode &= ~ATE_RFTEST; + Mode = OPERATION_NORMAL_MODE; + }else if (Value == 1){ + ATECtrl->Mode |= ATE_RFTEST; + Mode = OPERATION_RFTEST_MODE; + }else + DBGPRINT(RT_DEBUG_WARN,("%s Mode = %d error!!!\n",__FUNCTION__, Value)); + + CmdRfTest(pAd, ACTION_SWITCH_TO_RFTEST, Mode, 0); + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + +static INT32 HQA_DoCalibrationTestItem( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Value = 0; + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy((PUCHAR)&Value, (PUCHAR)&HqaCmdFrame->Data, 4); + Value = OS_NTOHL(Value); + + CmdRfTest(pAd, ACTION_IN_RFTEST, 0, Value); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + +static INT32 HQA_eFusePhysicalWrite( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + /* ToDo */ + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + +static INT32 HQA_eFusePhysicalRead( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + /* ToDo */ + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + +static INT32 HQA_eFuseLogicalRead( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + /* ToDo */ + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + +static INT32 HQA_eFuseLogicalWrite( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + /* ToDo */ + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + +static INT32 HQA_TMRSetting( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + /* ToDo */ + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + +static INT32 HQA_GetRxSNR( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + INT32 Ret = 0, Value = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + Value = OS_NTOHL(ATECtrl->SNR0); + memcpy(HqaCmdFrame->Data + 2, &Value, 4); + + Value = OS_NTOHL(ATECtrl->SNR1); + memcpy(HqaCmdFrame->Data + 6, &Value, 4); + + ResponseToQA(HqaCmdFrame, WRQ, 10, Ret); + return Ret; +} + + +static INT32 HQA_WriteBufferDone( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + UINT32 Value = 0; + INT32 Ret = 0; + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + memcpy((PUCHAR)&Value, (PUCHAR)&HqaCmdFrame->Data, 4); + Value = OS_NTOHL(Value); + + switch (Value) + { + case E2P_EFUSE_MODE: + Set_EepromBufferWriteBack_Proc(pAd, "1"); + break; + case E2P_FLASH_MODE: + Set_EepromBufferWriteBack_Proc(pAd, "2"); + break; + case E2P_EEPROM_MODE: + Set_EepromBufferWriteBack_Proc(pAd, "3"); + break; + case E2P_BIN_MODE: + Set_EepromBufferWriteBack_Proc(pAd, "4"); + break; + default: + DBGPRINT(RT_DEBUG_OFF, ("%s: Unknow write back mode(%d)\n", __FUNCTION__, Value)); + } + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; + +} + + +static INT32 HQA_FFT( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + UINT32 Value = 0; + INT32 Ret = 0; + static UINT32 RFCR, OMA0R0, OMA0R1, OMA1R0, OMA1R1, OMA2R0, OMA2R1, OMA3R0, OMA3R1, OMA4R0, OMA4R1; + + memcpy((PUCHAR)&Value, (PUCHAR)&HqaCmdFrame->Data, 4); + Value = OS_NTOHL(Value); + + DBGPRINT(RT_DEBUG_OFF, ("%s: %d\n", __FUNCTION__, Value)); + + if (Value == 0) + { + RTMP_IO_WRITE32(pAd, RMAC_RFCR, RFCR); + RTMP_IO_WRITE32(pAd, RMAC_OMA0R0, OMA0R0); + RTMP_IO_WRITE32(pAd, RMAC_OMA0R1, OMA0R1); + + RTMP_IO_WRITE32(pAd, RMAC_OMA1R0, OMA1R0); + RTMP_IO_WRITE32(pAd, RMAC_OMA1R1, OMA1R1); + + RTMP_IO_WRITE32(pAd, RMAC_OMA2R0, OMA2R0); + RTMP_IO_WRITE32(pAd, RMAC_OMA2R1, OMA2R1); + + RTMP_IO_WRITE32(pAd, RMAC_OMA3R0, OMA3R0); + RTMP_IO_WRITE32(pAd, RMAC_OMA3R1, OMA3R1); + + RTMP_IO_WRITE32(pAd, RMAC_OMA4R0, OMA4R0); + RTMP_IO_WRITE32(pAd, RMAC_OMA4R1, OMA4R1); + + AsicSetWPDMA(pAd, PDMA_TX_RX, 1); + AsicSetMacTxRx(pAd, ASIC_MAC_RX_RXV, FALSE); + } + else + { + //backup CR value + RTMP_IO_READ32(pAd, RMAC_RFCR, &RFCR); + RTMP_IO_READ32(pAd, RMAC_OMA0R0, &OMA0R0); + RTMP_IO_READ32(pAd, RMAC_OMA0R1, &OMA0R1); + + RTMP_IO_READ32(pAd, RMAC_OMA1R0, &OMA1R0); + RTMP_IO_READ32(pAd, RMAC_OMA1R1, &OMA1R1); + + RTMP_IO_READ32(pAd, RMAC_OMA2R0, &OMA2R0); + RTMP_IO_READ32(pAd, RMAC_OMA2R1, &OMA2R1); + + RTMP_IO_READ32(pAd, RMAC_OMA3R0, &OMA3R0); + RTMP_IO_READ32(pAd, RMAC_OMA3R1, &OMA3R1); + + RTMP_IO_READ32(pAd, RMAC_OMA4R0, &OMA4R0); + RTMP_IO_READ32(pAd, RMAC_OMA4R1, &OMA4R1); + + RTMP_IO_READ32(pAd, RMAC_RFCR, &Value); + Value |= RM_FRAME_REPORT_EN; + RTMP_IO_WRITE32(pAd, RMAC_RFCR, Value); + + //set RMAC don't let packet go up + RTMP_IO_WRITE32(pAd, RMAC_RFCR, 0x001FEFFB); + RTMP_IO_WRITE32(pAd, RMAC_OMA0R0, 0x00000000); + RTMP_IO_WRITE32(pAd, RMAC_OMA0R1, 0x00000000); + + RTMP_IO_WRITE32(pAd, RMAC_OMA1R0, 0x00000000); + RTMP_IO_WRITE32(pAd, RMAC_OMA1R1, 0x00000000); + + RTMP_IO_WRITE32(pAd, RMAC_OMA2R0, 0x00000000); + RTMP_IO_WRITE32(pAd, RMAC_OMA2R1, 0x00000000); + + RTMP_IO_WRITE32(pAd, RMAC_OMA3R0, 0x00000000); + RTMP_IO_WRITE32(pAd, RMAC_OMA3R1, 0x00000000); + + RTMP_IO_WRITE32(pAd, RMAC_OMA4R0, 0x00000000); + RTMP_IO_WRITE32(pAd, RMAC_OMA4R1, 0x00000000); + if(!(ATECtrl->Mode&ATE_RFTEST)){ + if (IS_MT7603(pAd) || IS_MT7628(pAd)) + { + CmdIcapOverLap(pAd, 80); + } + if (IS_MT7636(pAd)) + { + CmdIcapOverLap(pAd, 120); + } + ATECtrl->Mode |= ATE_RFTEST; + } + AsicSetWPDMA(pAd, PDMA_TX_RX, 0); + + AsicSetMacTxRx(pAd, ASIC_MAC_RX_RXV, TRUE); + } + return Ret; +} +static INT32 HQA_SetTxTonePower(PRTMP_ADAPTER pAd, RTMP_IOCTL_INPUT_STRUCT *WRQ, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT32 Value = 0; + INT32 Ret = 0; + INT32 pwr1 = 0; + INT32 pwr2 = 0; + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + + memcpy((PUCHAR)&Value, (PUCHAR)&HqaCmdFrame->Data, 4); + pwr1 = OS_NTOHL(Value); + + memcpy((PUCHAR)&Value, (PUCHAR)&HqaCmdFrame->Data + 4, 4); + pwr2 = OS_NTOHL(Value); + + DBGPRINT(RT_DEBUG_OFF, ("%s, pwr1:%d, pwr2:%d \n", __FUNCTION__,pwr1,pwr2)); + + ATEOp->SetTxTonePower(pAd, pwr1, pwr2); + + ResponseToQA(HqaCmdFrame, WRQ, 2, Ret); + return Ret; +} + +static INT32 HQA_CheckEfuseModeType(PRTMP_ADAPTER pAd, RTMP_IOCTL_INPUT_STRUCT *WRQ, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT32 val = 0; + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + + DBGPRINT(RT_DEBUG_TRACE,("%s, %x\n", __FUNCTION__, pAd->e2pCurMode)); + val = OS_HTONL(pAd->e2pCurMode); + NdisMoveMemory(HqaCmdFrame->Data + 2, &(val), sizeof(val)); + ResponseToQA(HqaCmdFrame, WRQ, 2+sizeof(val), Ret); + return Ret; +} + +static INT32 HQA_CheckEfuseNativeModeType(PRTMP_ADAPTER pAd, RTMP_IOCTL_INPUT_STRUCT *WRQ, HQA_CMD_FRAME *HqaCmdFrame) +{ + UINT32 val = 0; + INT32 Ret = 0; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + + DBGPRINT(RT_DEBUG_TRACE,("%s, %x\n", __FUNCTION__, pAd->E2pAccessMode)); + val = OS_HTONL(pAd->E2pAccessMode); //Fix me::after Star update code, get backup one + NdisMoveMemory(HqaCmdFrame->Data + 2, &(val), sizeof(val)); + ResponseToQA(HqaCmdFrame, WRQ, 2+sizeof(val), Ret); + return Ret; +} + +static HQA_CMD_HANDLER HQA_CMD_SET5[] = +{ + /* cmd id start from 0x1500 */ + HQA_GetFWInfo, /* 0x1500 */ + HQA_StartContinousTx, /* 0x1501 */ + HQA_SetSTBC, /* 0x1502 */ + HQA_SetShortGI, /* 0x1503 */ + HQA_SetDPD, /* 0x1504 */ + HQA_SetTssiOnOff, /* 0x1505 */ + HQA_GetRxStatisticsAll, /* 0x1506 */ + HQA_StartContiTxTone, /* 0x1507 */ + HQA_StopContiTxTone, /* 0x1508 */ + HQA_CalibrationTestMode, /* 0x1509 */ + HQA_DoCalibrationTestItem, /* 0x150A */ + HQA_eFusePhysicalWrite, /* 0x150B */ + HQA_eFusePhysicalRead, /* 0x150C */ + HQA_eFuseLogicalRead, /* 0x150D */ + HQA_eFuseLogicalWrite, /* 0x150E */ + HQA_TMRSetting, /* 0x150F */ + HQA_GetRxSNR, /* 0x1510 */ + HQA_WriteBufferDone, /* 0x1511 */ + HQA_FFT, /* 0x1512 */ + HQA_SetTxTonePower, /* 0x1513 */ + NULL, + NULL, /* 0x1515 */ + NULL, /* 0x1516 */ + NULL, /* 0x1517 */ + NULL, /* 0x1518 */ + NULL, /* 0x1519 */ + NULL, /* 0x151A */ + NULL, /* 0x151B */ + NULL, /* 0x151C */ + NULL, /* 0x151D */ + NULL, /* 0x151E */ + NULL, /* 0x151F */ + NULL, /* 0x1520 */ + NULL, /* 0x1521 */ + HQA_CheckEfuseModeType, /* 0x1522 */ + HQA_CheckEfuseNativeModeType,/* 0x1523 */ +}; + + +static HQA_CMD_TABLE HQA_CMD_TABLES[] = { + { + HQA_CMD_SET0, + sizeof(HQA_CMD_SET0) / sizeof(HQA_CMD_HANDLER), + 0x1000, + }, + { + HQA_CMD_SET1, + sizeof(HQA_CMD_SET1) / sizeof(HQA_CMD_HANDLER), + 0x1100, + }, + { + HQA_CMD_SET2, + sizeof(HQA_CMD_SET2) / sizeof(HQA_CMD_HANDLER), + 0x1200, + }, + { + HQA_CMD_SET3, + sizeof(HQA_CMD_SET3) / sizeof(HQA_CMD_HANDLER), + 0x1300, + }, + { + HQA_CMD_SET4, + sizeof(HQA_CMD_SET4) / sizeof(HQA_CMD_HANDLER), + 0x1400, + }, + { + HQA_CMD_SET5, + sizeof(HQA_CMD_SET5) / sizeof(HQA_CMD_HANDLER), + 0x1500, + }, +}; + + +static INT32 HQA_CMDHandler( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + HQA_CMD_FRAME *HqaCmdFrame) +{ + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + INT32 Status = NDIS_STATUS_SUCCESS; + USHORT CmdId; + UINT32 TableIndex = 0; + CmdId = OS_NTOHS(HqaCmdFrame->Id); + DBGPRINT(RT_DEBUG_TRACE,("\n%s: Command_Id = 0x%04x !\n", __FUNCTION__, CmdId)); + + while (TableIndex < (sizeof(HQA_CMD_TABLES) / sizeof(HQA_CMD_TABLE))) + { + int CmdIndex = 0; + CmdIndex = CmdId - HQA_CMD_TABLES[TableIndex].CmdOffset; + if ((CmdIndex >= 0) && (CmdIndex < HQA_CMD_TABLES[TableIndex].CmdSetSize)) + { + HQA_CMD_HANDLER *pCmdSet; + + pCmdSet = HQA_CMD_TABLES[TableIndex].CmdSet; + + if (pCmdSet[CmdIndex] != NULL) + Status = (*pCmdSet[CmdIndex])(pAd, WRQ, HqaCmdFrame); + break; + } + TableIndex++; + } + + return Status; +} + + +INT32 RtmpDoAte( + PRTMP_ADAPTER pAd, + RTMP_IOCTL_INPUT_STRUCT *WRQ, + RTMP_STRING *wrq_name) +{ + INT32 Status = NDIS_STATUS_SUCCESS; + HQA_CMD_FRAME *HqaCmdFrame; + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + UINT32 ATEMagicNum; + + os_alloc_mem_suspend(pAd, (UCHAR **)&HqaCmdFrame, sizeof(*HqaCmdFrame)); + + if (!HqaCmdFrame) + { + Status = -ENOMEM; + goto ERROR0; + } + + NdisZeroMemory(HqaCmdFrame, sizeof(*HqaCmdFrame)); + + Status = copy_from_user((PUCHAR)HqaCmdFrame, WRQ->u.data.pointer, + WRQ->u.data.length); + + if (Status) + { + Status = -EFAULT; + goto ERROR1; + } + + ATEMagicNum = OS_NTOHL(HqaCmdFrame->MagicNo); + + switch(ATEMagicNum) + { + case HQA_CMD_MAGIC_NO: + Status = HQA_CMDHandler(pAd, WRQ, HqaCmdFrame); + break; + default: + Status = NDIS_STATUS_FAILURE; + DBGPRINT_ERR(("Unknown magic number of HQA command = %x\n", ATEMagicNum)); + break; + } + + ERROR1: + os_free_mem(NULL, HqaCmdFrame); + ERROR0: + return Status; +} diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/mt7603.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/mt7603.c new file mode 100644 index 000000000..ebc08c509 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/mt7603.c @@ -0,0 +1,1389 @@ +/* + *************************************************************************** + * 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: + mt7603.c +*/ + +#include "rt_config.h" +#ifdef MT7603_E1 +#include "mcu/mt7603_firmware.h" +#endif /* MT7603_E1 */ +#ifdef MT7603_E2 +#include "mcu/mt7603_e2_firmware.h" +#endif /* MT7603_E2 */ +#include "eeprom/mt7603_e2p.h" +#include "phy/wf_phy_back.h" + +static VOID mt7603_bbp_adjust(RTMP_ADAPTER *pAd) +{ + static char *ext_str[]={"extNone", "extAbove", "", "extBelow"}; + UCHAR rf_bw, ext_ch; + +#ifdef DOT11_N_SUPPORT + if (get_ht_cent_ch(pAd, &rf_bw, &ext_ch) == FALSE) +#endif /* DOT11_N_SUPPORT */ + { + rf_bw = BW_20; + ext_ch = EXTCHA_NONE; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + } + + bbp_set_bw(pAd, rf_bw); + +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("%s() : %s, ChannelWidth=%d, Channel=%d, ExtChanOffset=%d(%d) \n", + __FUNCTION__, ext_str[ext_ch], + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth, + pAd->CommonCfg.Channel, + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA, + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset)); +#endif /* DOT11_N_SUPPORT */ +} + +/*Nobody uses it currently*/ + +static void mt7603_switch_channel(RTMP_ADAPTER *pAd, UCHAR channel, BOOLEAN scan) +{ + + + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + { + CmdChannelSwitch(pAd, channel, channel, BW_20, + pAd->CommonCfg.TxStream, pAd->CommonCfg.RxStream); + + CmdSetTxPowerCtrl(pAd, channel); + } + else + { + CmdChannelSwitch(pAd, pAd->CommonCfg.Channel, channel, pAd->CommonCfg.BBPCurrentBW, + pAd->CommonCfg.TxStream, pAd->CommonCfg.RxStream); + + CmdSetTxPowerCtrl(pAd, channel); + } + + /* Channel latch */ + pAd->LatchRfRegs.Channel = channel; + + + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): Switch to Ch#%d(%dT%dR), BBP_BW=%d\n", + __FUNCTION__, + channel, + pAd->CommonCfg.TxStream, + pAd->CommonCfg.RxStream, + pAd->CommonCfg.BBPCurrentBW)); +} + + +/* + Init TxD short format template which will copy by PSE-Client to LMAC +*/ +static INT asic_set_tmac_info_template(RTMP_ADAPTER *pAd) +{ + UINT32 dw[5]; + TMAC_TXD_2 *dw2 = (TMAC_TXD_2 *)(&dw[0]); + TMAC_TXD_3 *dw3 = (TMAC_TXD_3 *)(&dw[1]); + //TMAC_TXD_4 *dw4 = (TMAC_TXD_4 *)(&dw[2]); + TMAC_TXD_5 *dw5 = (TMAC_TXD_5 *)(&dw[3]); + //TMAC_TXD_6 *dw6 = (TMAC_TXD_6 *)(&dw[4]); + + NdisZeroMemory((UCHAR *)(&dw[0]), sizeof(dw)); + + dw2->htc_vld = 0; + dw2->frag = 0; + dw2->max_tx_time = 0; + dw2->fix_rate = 0; + + dw3->remain_tx_cnt = MT_TX_SHORT_RETRY; + dw3->sn_vld = 0; + dw3->pn_vld = 0; + + dw5->pid = PID_DATA_AMPDU; + dw5->tx_status_fmt = 0; + dw5->tx_status_2_host = 0; // Disable TxS + dw5->bar_sn_ctrl = 0; //HW + dw5->pwr_mgmt= TMI_PM_BIT_CFG_BY_SW; + +#ifdef RTMP_PCI_SUPPORT +// TODO: shaing, for MT7628, may need to change this as RTMP_MAC_PCI + + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, 0x80080000); + + + /* For short format */ + RTMP_IO_WRITE32(pAd, 0xc0040, dw[0]); + RTMP_IO_WRITE32(pAd, 0xc0044, dw[1]); + RTMP_IO_WRITE32(pAd, 0xc0048, dw[2]); + RTMP_IO_WRITE32(pAd, 0xc004c, dw[3]); + RTMP_IO_WRITE32(pAd, 0xc0050, dw[4]); + + +// TODO: shaing, for MT7628, may need to change this as RTMP_MAC_PCI + // After change the Tx Padding CR of PCI-E Client, we need to re-map for PSE region + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, MT_PSE_BASE_ADDR); + +#endif /* RTMP_PCI_SUPPORT */ + + + return TRUE; +} + + +static VOID mt7603_init_mac_cr(RTMP_ADAPTER *pAd) +{ + UINT32 mac_val; + + DBGPRINT(RT_DEBUG_OFF, ("%s()-->\n", __FUNCTION__)); + + /* Preparation of TxD DW2~DW6 when we need run 3DW format */ + asic_set_tmac_info_template(pAd); + + /* A-MPDU BA WinSize control */ + RTMP_IO_READ32(pAd, AGG_AWSCR, &mac_val); + mac_val &= ~WINSIZE0_MASK; + mac_val |= WINSIZE0(4); + mac_val &= ~WINSIZE1_MASK; + mac_val |= WINSIZE1(5); + mac_val &= ~WINSIZE2_MASK; + mac_val |= WINSIZE2(8); + mac_val &= ~WINSIZE3_MASK; + mac_val |= WINSIZE3(10); + RTMP_IO_WRITE32(pAd, AGG_AWSCR, mac_val); + + RTMP_IO_READ32(pAd, AGG_AWSCR1, &mac_val); + mac_val &= ~WINSIZE4_MASK; + mac_val |= WINSIZE4(16); + mac_val &= ~WINSIZE5_MASK; + mac_val |= WINSIZE5(20); + mac_val &= ~WINSIZE6_MASK; + mac_val |= WINSIZE6(21); + mac_val &= ~WINSIZE7_MASK; + mac_val |= WINSIZE7(42); + RTMP_IO_WRITE32(pAd, AGG_AWSCR1, mac_val); + + /* A-MPDU Agg limit control */ + RTMP_IO_READ32(pAd, AGG_AALCR, &mac_val); + mac_val &= ~AC0_AGG_LIMIT_MASK; + mac_val |= AC0_AGG_LIMIT(24); //modify from 21, 20171207 + mac_val &= ~AC1_AGG_LIMIT_MASK; + mac_val |= AC1_AGG_LIMIT(24); + mac_val &= ~AC2_AGG_LIMIT_MASK; + mac_val |= AC2_AGG_LIMIT(24); + mac_val &= ~AC3_AGG_LIMIT_MASK; + mac_val |= AC3_AGG_LIMIT(24); + RTMP_IO_WRITE32(pAd, AGG_AALCR, mac_val); + + RTMP_IO_READ32(pAd, AGG_AALCR1, &mac_val); + mac_val &= ~AC10_AGG_LIMIT_MASK; + mac_val |= AC10_AGG_LIMIT(24); + mac_val &= ~AC11_AGG_LIMIT_MASK; + mac_val |= AC11_AGG_LIMIT(24); + mac_val &= ~AC12_AGG_LIMIT_MASK; + mac_val |= AC12_AGG_LIMIT(24); + mac_val &= ~AC13_AGG_LIMIT_MASK; + mac_val |= AC13_AGG_LIMIT(24); + RTMP_IO_WRITE32(pAd, AGG_AALCR1, mac_val); + + /* Vector report queue setting */ + RTMP_IO_READ32(pAd, DMA_VCFR0, &mac_val); + mac_val |= BIT13; + RTMP_IO_WRITE32(pAd, DMA_VCFR0, mac_val); + + /* TMR report queue setting */ + RTMP_IO_READ32(pAd, DMA_TMCFR0, &mac_val); + mac_val |= BIT13;//TMR report send to HIF q1. + mac_val = mac_val & ~(BIT0); + mac_val = mac_val & ~(BIT1); + RTMP_IO_WRITE32(pAd, DMA_TMCFR0, mac_val); + + RTMP_IO_READ32(pAd, RMAC_TMR_PA, &mac_val); + mac_val = mac_val & ~BIT31; + RTMP_IO_WRITE32(pAd, RMAC_TMR_PA, mac_val); + /* Configure all rx packets to HIF, except WOL2M packet */ + RTMP_IO_READ32(pAd, DMA_RCFR0, &mac_val); + mac_val = 0x00010000; // drop duplicate + mac_val |= 0xc0200000; // receive BA/CF_End/Ack/RTS/CTS/CTRL_RSVED + if (pAd->rx_pspoll_filter) + mac_val |= 0x00000008; //Non-BAR Control frame to MCU + RTMP_IO_WRITE32(pAd, DMA_RCFR0, mac_val); + + /* Configure Rx Vectors report to HIF */ + RTMP_IO_READ32(pAd, DMA_VCFR0, &mac_val); + mac_val &= (~0x1); // To HIF + mac_val |= 0x2000; // RxRing 1 + RTMP_IO_WRITE32(pAd, DMA_VCFR0, mac_val); + + /* RMAC dropping criteria for max/min recv. packet length */ + RTMP_IO_READ32(pAd, RMAC_RMACDR, &mac_val); + mac_val |= SELECT_RXMAXLEN_20BIT; + RTMP_IO_WRITE32(pAd, RMAC_RMACDR, mac_val); + RTMP_IO_READ32(pAd, RMAC_MAXMINLEN, &mac_val); + mac_val &= ~RMAC_DROP_MAX_LEN_MASK; + mac_val |= RMAC_DROP_MAX_LEN; + RTMP_IO_WRITE32(pAd, RMAC_MAXMINLEN, mac_val); + + + + /* Enable RX Group to HIF */ + AsicSetRxGroup(pAd, HIF_PORT, RXS_GROUP1|RXS_GROUP2|RXS_GROUP3, TRUE); + AsicSetRxGroup(pAd, MCU_PORT, RXS_GROUP1|RXS_GROUP2|RXS_GROUP3, TRUE); + + /* AMPDU BAR setting */ + /* Enable HW BAR feature */ + AsicSetBARTxCntLimit(pAd, TRUE, 1); + + /* RTS Retry setting */ + AsicSetRTSTxCntLimit(pAd, TRUE, MT_RTS_RETRY); + + /* Configure the BAR rate setting */ + RTMP_IO_READ32(pAd, AGG_ACR, &mac_val); + mac_val &= (~0xfff00000); + mac_val &= ~(AGG_ACR_AMPDU_NO_BA_AR_RULE_MASK|AMPDU_NO_BA_RULE); + mac_val |= AGG_ACR_AMPDU_NO_BA_AR_RULE_MASK; + RTMP_IO_WRITE32(pAd, AGG_ACR, mac_val); + + /* AMPDU Statistics Range Control setting + 0 < agg_cnt - 1 <= range_cr(0), => 1 + range_cr(0) < agg_cnt - 1 <= range_cr(4), => 2~5 + range_cr(4) < agg_cnt - 1 <= range_cr(14), => 6~15 + range_cr(14) < agg_cnt - 1, => 16~ + */ + RTMP_IO_READ32(pAd, AGG_ASRCR, &mac_val); + mac_val = (0 << 0) | (4 << 8) | (14 << 16); + RTMP_IO_WRITE32(pAd, AGG_ASRCR, mac_val); + + // Enable MIB counters + RTMP_IO_WRITE32(pAd, MIB_MSCR, 0x7fffffff); + RTMP_IO_WRITE32(pAd, MIB_MPBSCR, 0xffffffff); + + + /* Throughput patch */ + RTMP_IO_READ32(pAd, TMAC_TRCR, &mac_val); + mac_val &= 0x0fffffff; + mac_val |= 0x80000000; + RTMP_IO_WRITE32(pAd, TMAC_TRCR, mac_val); + + RTMP_IO_READ32(pAd, WTBL_OFF_RMVTCR, &mac_val); + /* RCPI include ACK and Data */ + mac_val |= RX_MV_MODE; + RTMP_IO_WRITE32(pAd, WTBL_OFF_RMVTCR, mac_val); + +#ifdef MT7603_FPGA + // enable MAC2MAC mode + RTMP_IO_READ32(pAd, RMAC_MISC, &mac_val); + mac_val |= BIT18; + RTMP_IO_WRITE32(pAd, RMAC_MISC, mac_val); +#endif /* MT7603_FPGA */ + + /* Turn on RX RIFS Mode */ + RTMP_IO_READ32(pAd, TMAC_TCR, &mac_val); + mac_val |= RX_RIFS_MODE; + RTMP_IO_WRITE32(pAd, TMAC_TCR, mac_val); + + /* IOT issue with Realtek at CCK mode */ + mac_val = 0x003000E7; + RTMP_IO_WRITE32(pAd, TMAC_CDTR, mac_val); + + /* IOT issue with Linksys WUSB6300. Cannot receive BA after TX finish */ + mac_val = 0x4; + RTMP_IO_WRITE32(pAd, TMAC_RRCR, mac_val); + + /* send RTS/CTS if agg size >= 2 */ + RTMP_IO_READ32(pAd, AGG_PCR1, &mac_val); + mac_val &= ~RTS_PKT_NUM_THRESHOLD_MASK; + mac_val |= RTS_PKT_NUM_THRESHOLD(3); + RTMP_IO_WRITE32(pAd, AGG_PCR1, mac_val); + + /* When WAPI + RDG, don't mask ORDER bit */ + RTMP_IO_READ32(pAd, SEC_SCR, &mac_val); + mac_val &= 0xfffbfffc; //zero bit [18] for ICV error issue. + RTMP_IO_WRITE32(pAd, SEC_SCR, mac_val); + + /* Enable Spatial Extension for RTS/CTS */ + RTMP_IO_READ32(pAd, TMAC_PCR, &mac_val); + mac_val |= PTEC_SPE_EN; + RTMP_IO_WRITE32(pAd, TMAC_PCR, mac_val); + + /* Enable Spatial Extension for ACK/BA/CTS */ + RTMP_IO_READ32(pAd, TMAC_B0BRR0, &mac_val); + mac_val |= BSSID00_RESP_SPE_EN; + RTMP_IO_WRITE32(pAd, TMAC_B0BRR0, mac_val); + + + AsicSetTxSClassifyFilter(pAd, TXS2HOST, TXS2H_QID1, TXS2HOST_AGGNUMS, 0x00); + AsicSetTxSClassifyFilter(pAd, TXS2MCU, TXS2M_QID0, TXS2MCU_AGGNUMS, 0x00); +} + + +static VOID MT7603BBPInit(RTMP_ADAPTER *pAd) +{ + return; +} + +static void mt7603_init_rf_cr(RTMP_ADAPTER *ad) +{ + return; +} + +static UINT8 mt7603_txpwr_chlist[] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +}; + + +int mt7603_read_chl_pwr(RTMP_ADAPTER *pAd) +{ + UINT32 i, choffset; + struct MT_TX_PWR_CAP *cap = &pAd->chipCap.MTTxPwrCap; + USHORT Value; + + mt7603_get_tx_pwr_info(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("%s()--->\n", __FUNCTION__)); + + for (i = 0; i < sizeof(mt7603_txpwr_chlist); i++) { + pAd->TxPower[i].Channel = mt7603_txpwr_chlist[i]; + pAd->TxPower[i].Power = TX_TARGET_PWR_DEFAULT_VALUE; + pAd->TxPower[i].Power2 = TX_TARGET_PWR_DEFAULT_VALUE; + } + + for (i = 0; i < 14; i++) { + pAd->TxPower[i].Power = cap->tx_0_target_pwr_g_band; + pAd->TxPower[i].Power2 = cap->tx_1_target_pwr_g_band; + } + + choffset = 14; + + /* 4. Print and Debug*/ + for (i = 0; i < choffset; i++) + { + DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: TxPower[%03d], Channel=%d, Power[Tx0:%d, Tx1:%d]\n", + i, pAd->TxPower[i].Channel, pAd->TxPower[i].Power, pAd->TxPower[i].Power2 )); + } + + /* check PA type combination */ + RT28xx_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET, Value); + cap->pa_type = GET_PA_TYPE(Value); + + return TRUE; +} + + +/* Read power per rate */ +void mt7603_get_tx_pwr_per_rate(RTMP_ADAPTER *pAd) +{ + BOOLEAN is_empty = 0; + UINT16 value = 0; + struct MT_TX_PWR_CAP *cap = &pAd->chipCap.MTTxPwrCap; + + /* G Band tx power for CCK 1M/2M, 5.5M/11M */ + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_CCK_1_2M, value); + if (is_empty) { + cap->tx_pwr_cck_1_2 = 0; + cap->tx_pwr_cck_5_11 = 0; + } else { + /* CCK 1M/2M */ + if (value & TX_PWR_CCK_1_2M_EN) { + if (value & TX_PWR_CCK_1_2M_SIGN) { + cap->tx_pwr_cck_1_2 = (value & TX_PWR_CCK_1_2M_MASK); + } else { + cap->tx_pwr_cck_1_2 = -(value & TX_PWR_CCK_1_2M_MASK); + } + } else { + cap->tx_pwr_cck_1_2 = 0; + } + + /* CCK 5.5M/11M */ + if (value & TX_PWR_CCK_5_11M_EN) { + if (value & TX_PWR_CCK_5_11M_SIGN) { + cap->tx_pwr_cck_5_11 = ((value & TX_PWR_CCK_5_11M_MASK) >> 8); + } else { + cap->tx_pwr_cck_5_11 = -((value & TX_PWR_CCK_5_11M_MASK) >> 8); + } + } else { + cap->tx_pwr_cck_5_11 = 0; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_cck_1_2 = %d\n", cap->tx_pwr_cck_1_2)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_cck_5_11 = %d\n", cap->tx_pwr_cck_5_11)); + + /* G Band tx power for OFDM 6M/9M, 12M/18M, 24M/36M, 48M/54M */ + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_G_BAND_OFDM_6_9M, value); + if (is_empty) { + cap->tx_pwr_g_band_ofdm_6_9 = 0; + cap->tx_pwr_g_band_ofdm_12_18 = 0; + } else { + /* OFDM 6M/9M */ + if (value & TX_PWR_G_BAND_OFDM_6_9M_EN) { + if (value & TX_PWR_G_BAND_OFDM_6_9M_SIGN) { + cap->tx_pwr_g_band_ofdm_6_9 = (value & TX_PWR_G_BAND_OFDM_6_9M_MASK); + } else { + cap->tx_pwr_g_band_ofdm_6_9 = -(value & TX_PWR_G_BAND_OFDM_6_9M_MASK); + } + } else { + cap->tx_pwr_g_band_ofdm_6_9 = 0; + } + + /* OFDM 12M/18M */ + if (value & TX_PWR_G_BAND_OFDM_12_18M_EN) { + if (value & TX_PWR_G_BAND_OFDM_12_18M_SIGN) { + cap->tx_pwr_g_band_ofdm_12_18 = ((value & TX_PWR_G_BAND_OFDM_12_18M_MASK) >> 8); + } else { + cap->tx_pwr_g_band_ofdm_12_18 = -((value & TX_PWR_G_BAND_OFDM_12_18M_MASK) >> 8); + } + } else { + cap->tx_pwr_g_band_ofdm_12_18 = 0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_g_band_ofdm_6_9 = %d\n", cap->tx_pwr_g_band_ofdm_6_9)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_g_band_ofdm_12_18 = %d\n", cap->tx_pwr_g_band_ofdm_12_18)); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_G_BAND_OFDM_24_36M, value); + if (is_empty) { + cap->tx_pwr_g_band_ofdm_24_36 = 0; + cap->tx_pwr_g_band_ofdm_48= 0; + } else { + /* OFDM 24M/36M */ + if (value & TX_PWR_G_BAND_OFDM_24_36M_EN) { + if (value & TX_PWR_G_BAND_OFDM_24_36M_SIGN) { + cap->tx_pwr_g_band_ofdm_24_36 = (value & TX_PWR_G_BAND_OFDM_24_36M_MASK); + } else { + cap->tx_pwr_g_band_ofdm_24_36 = -(value & TX_PWR_G_BAND_OFDM_24_36M_MASK); + } + } else { + cap->tx_pwr_g_band_ofdm_24_36 = 0; + } + + /* OFDM 48M */ + if (value & TX_PWR_G_BAND_OFDM_48M_EN) { + if (value & TX_PWR_G_BAND_OFDM_48M_SIGN) { + cap->tx_pwr_g_band_ofdm_48 = ((value & TX_PWR_G_BAND_OFDM_48M_MASK) >> 8); + } else { + cap->tx_pwr_g_band_ofdm_48 = -((value & TX_PWR_G_BAND_OFDM_48M_MASK) >> 8); + } + } else { + cap->tx_pwr_g_band_ofdm_48 = 0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_g_band_ofdm_24_36 = %d\n", cap->tx_pwr_g_band_ofdm_24_36)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_g_band_ofdm_48 = %d\n", cap->tx_pwr_g_band_ofdm_48)); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_G_BAND_OFDM_54M, value); + if (is_empty) { + cap->tx_pwr_g_band_ofdm_54 = 0; + cap->tx_pwr_ht_bpsk_mcs_0_8 = 0; + } else { + /* OFDM 54M */ + if (value & TX_PWR_G_BAND_OFDM_54M_EN) { + if (value & TX_PWR_G_BAND_OFDM_54M_SIGN) { + cap->tx_pwr_g_band_ofdm_54 = (value & TX_PWR_G_BAND_OFDM_54M_MASK); + } else { + cap->tx_pwr_g_band_ofdm_54 = -(value & TX_PWR_G_BAND_OFDM_54M_MASK); + } + } else { + cap->tx_pwr_g_band_ofdm_54 = 0; + } + + /* HT MCS_0, MCS_8 */ + if (value & TX_PWR_HT_BPSK_MCS_0_8_EN) { + if (value & TX_PWR_HT_BPSK_MCS_0_8_SIGN) { + cap->tx_pwr_ht_bpsk_mcs_0_8 = ((value & TX_PWR_HT_BPSK_MCS_0_8_MASK) >> 8); + } else { + cap->tx_pwr_ht_bpsk_mcs_0_8 = -((value & TX_PWR_HT_BPSK_MCS_0_8_MASK) >> 8); + } + } else { + cap->tx_pwr_ht_bpsk_mcs_0_8 = 0; + } } + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_g_band_ofdm_54 = %d\n", cap->tx_pwr_g_band_ofdm_54)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_bpsk_mcs_0_8 = %d\n", cap->tx_pwr_ht_bpsk_mcs_0_8)); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_HT_BPSK_MCS_32, value); + if (is_empty) { + cap->tx_pwr_ht_bpsk_mcs_32 = 0; + cap->tx_pwr_ht_qpsk_mcs_1_2_9_10 = 0; + } else { + /* HT MCS_0, MCS_8 */ + if (value & TX_PWR_HT_BPSK_MCS_32_EN) { + if (value & TX_PWR_HT_BPSK_MCS_32_SIGN) { + cap->tx_pwr_ht_bpsk_mcs_32 = (value & TX_PWR_HT_BPSK_MCS_32_MASK); + } else { + cap->tx_pwr_ht_bpsk_mcs_32 = -(value & TX_PWR_HT_BPSK_MCS_32_MASK); + } + } else { + cap->tx_pwr_ht_bpsk_mcs_32 = 0; + } + + /* HT MCS_1, MCS_2, MCS_9, MCS_10 */ + if (value & TX_PWR_HT_QPSK_MCS_1_2_9_10_EN) { + if (value & TX_PWR_HT_QPSK_MCS_1_2_9_10_SIGN) { + cap->tx_pwr_ht_qpsk_mcs_1_2_9_10 = ((value & TX_PWR_HT_QPSK_MCS_1_2_9_10_MASK) >> 8); + } else { + cap->tx_pwr_ht_qpsk_mcs_1_2_9_10 = -((value & TX_PWR_HT_QPSK_MCS_1_2_9_10_MASK) >> 8); + } + } else { + cap->tx_pwr_ht_qpsk_mcs_1_2_9_10 = 0; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_bpsk_mcs_32 = %d\n", cap->tx_pwr_ht_bpsk_mcs_32)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_qpsk_mcs_1_2_9_10 = %d\n", cap->tx_pwr_ht_qpsk_mcs_1_2_9_10)); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_HT_16QAM_MCS_3_4_11_12, value); + if (is_empty) { + cap->tx_pwr_ht_16qam_mcs_3_4_11_12 = 0; + cap->tx_pwr_ht_64qam_mcs_5_13 = 0; + } else { + /* HT MCS_3, MCS_4, MCS_11, MCS_12 */ + if (value & TX_PWR_HT_16QAM_MCS_3_4_11_12_EN) { + if (value & TX_PWR_HT_16QAM_MCS_3_4_11_12_SIGN) { + cap->tx_pwr_ht_16qam_mcs_3_4_11_12 = (value & TX_PWR_HT_16QAM_MCS_3_4_11_12_MASK); + } else { + cap->tx_pwr_ht_16qam_mcs_3_4_11_12 = -(value & TX_PWR_HT_16QAM_MCS_3_4_11_12_MASK); + } + } else { + cap->tx_pwr_ht_16qam_mcs_3_4_11_12 = 0; + } + + /* HT MCS_5, MCS_13 */ + if (value & TX_PWR_HT_64QAM_MCS_5_13_EN) { + if (value & TX_PWR_HT_64QAM_MCS_5_13_SIGN) { + cap->tx_pwr_ht_64qam_mcs_5_13 = ((value & TX_PWR_HT_64QAM_MCS_5_13_MASK) >> 8); + } else { + cap->tx_pwr_ht_64qam_mcs_5_13 = -((value & TX_PWR_HT_64QAM_MCS_5_13_MASK) >> 8); + } + } else { + cap->tx_pwr_ht_64qam_mcs_5_13 = 0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_16qam_mcs_3_4_11_12 = %d\n", cap->tx_pwr_ht_16qam_mcs_3_4_11_12)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_64qam_mcs_5_13 = %d\n", cap->tx_pwr_ht_64qam_mcs_5_13)); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_HT_64QAM_MCS_6_14, value); + if (is_empty) { + cap->tx_pwr_ht_64qam_mcs_6_14 = 0; + cap->tx_pwr_ht_64qam_mcs_7_15 = 0; + } else { + /* HT MCS_6, MCS_14 */ + if (value & TX_PWR_HT_64QAM_MCS_6_14_EN) { + if (value & TX_PWR_HT_64QAM_MCS_6_14_SIGN) { + cap->tx_pwr_ht_64qam_mcs_6_14 = (value & TX_PWR_HT_64QAM_MCS_6_14_MASK); + } else { + cap->tx_pwr_ht_64qam_mcs_6_14 = -(value & TX_PWR_HT_64QAM_MCS_6_14_MASK); + } + } else { + cap->tx_pwr_ht_64qam_mcs_6_14 = 0; + } + + /* HT MCS_7, MCS_15 */ + if (value & TX_PWR_HT_64QAM_MCS_7_15_EN) { + if (value & TX_PWR_HT_64QAM_MCS_7_15_SIGN) { + cap->tx_pwr_ht_64qam_mcs_7_15 = ((value & TX_PWR_HT_64QAM_MCS_7_15_MASK) >> 8); + } else { + cap->tx_pwr_ht_64qam_mcs_7_15 = -((value & TX_PWR_HT_64QAM_MCS_7_15_MASK) >> 8); + } + } else { + cap->tx_pwr_ht_64qam_mcs_7_15 = 0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_64qam_mcs_6_14 = %d\n", cap->tx_pwr_ht_64qam_mcs_6_14)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_64qam_mcs_7_15 = %d\n", cap->tx_pwr_ht_64qam_mcs_7_15)); + + return; +} + + +void mt7603_get_tx_pwr_info(RTMP_ADAPTER *pAd) +{ + bool is_empty = 0; + UINT16 value = 0; + struct MT_TX_PWR_CAP *cap = &pAd->chipCap.MTTxPwrCap; + + /* Read 20/40 BW delta */ + is_empty = RT28xx_EEPROM_READ16(pAd, G_BAND_20_40_BW_PWR_DELTA, value); + + if (is_empty) { + cap->delta_tx_pwr_bw40_g_band = 0x0; + } else { + /* G Band */ + if (value & G_BAND_20_40_BW_PWR_DELTA_EN) { + if (value & G_BAND_20_40_BW_PWR_DELTA_SIGN) { + /* bit[0..5] tx power delta value */ + cap->delta_tx_pwr_bw40_g_band = (value & G_BAND_20_40_BW_PWR_DELTA_MASK); + } else { + cap->delta_tx_pwr_bw40_g_band = -(value & G_BAND_20_40_BW_PWR_DELTA_MASK); + } + } else { + cap->delta_tx_pwr_bw40_g_band = 0x0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("delta_tx_pwr_bw40_g_band = %d\n", cap->delta_tx_pwr_bw40_g_band)); + + /////////////////// Tx0 ////////////////////////// + /* Read TSSI slope/offset for TSSI compensation */ + is_empty = RT28xx_EEPROM_READ16(pAd, TX0_G_BAND_TSSI_SLOPE, value); + + cap->tssi_0_slope_g_band = + (is_empty) ? TSSI_0_SLOPE_G_BAND_DEFAULT_VALUE : (value & TX0_G_BAND_TSSI_SLOPE_MASK); + + cap->tssi_0_offset_g_band = + (is_empty) ? TSSI_0_OFFSET_G_BAND_DEFAULT_VALUE : ((value & TX0_G_BAND_TSSI_OFFSET_MASK) >> 8); + + DBGPRINT(RT_DEBUG_TRACE, ("tssi_0_slope_g_band = %d\n", cap->tssi_0_slope_g_band)); + DBGPRINT(RT_DEBUG_TRACE, ("tssi_0_offset_g_band = %d\n", cap->tssi_0_offset_g_band)); + /* Read 54M target power */ + is_empty = RT28xx_EEPROM_READ16(pAd, TX0_G_BAND_TARGET_PWR, value); + + cap->tx_0_target_pwr_g_band = + (is_empty) ? TX_TARGET_PWR_DEFAULT_VALUE : (value & TX0_G_BAND_TARGET_PWR_MASK); + + DBGPRINT(RT_DEBUG_TRACE, ("tssi_0_target_pwr_g_band = %d\n", cap->tx_0_target_pwr_g_band)); + + /* Read power offset (channel delta) */ + if (is_empty) { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = 0x0; + } else { + /* tx power offset LOW */ + if (value & TX0_G_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & TX0_G_BAND_CHL_PWR_DELTA_LOW_SIGN) { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = ((value & TX0_G_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } else { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = -((value & TX0_G_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } + } else { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = 0x0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = %d\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW])); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX0_G_BAND_CHL_PWR_DELTA_MID, value); + + if (is_empty) { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID] = 0x0; + cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI] = 0x0; + } else { + /* tx power offset MID */ + if (value & TX0_G_BAND_CHL_PWR_DELTA_MID_EN) { + if (value & TX0_G_BAND_CHL_PWR_DELTA_MID_SIGN) + cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID] = (value & TX0_G_BAND_CHL_PWR_DELTA_MID_MASK); + else + cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID] = -(value & TX0_G_BAND_CHL_PWR_DELTA_MID_MASK); + } else { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID] = 0x0; + } + /* tx power offset HIGH */ + if (value & TX0_G_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & TX0_G_BAND_CHL_PWR_DELTA_HI_SIGN) + cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI] = ((value & TX0_G_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + else + cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI] = -((value & TX0_G_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + } else { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI] = 0x0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_0_chl_pwr_delta_g_band[G_BAND_MID] = %d\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID])); + DBGPRINT(RT_DEBUG_TRACE, ("tx_0_chl_pwr_delta_g_band[G_BAND_HI] = %d\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI])); + + /////////////////// Tx1 ////////////////////////// + /* Read TSSI slope/offset for TSSI compensation */ + is_empty = RT28xx_EEPROM_READ16(pAd, TX1_G_BAND_TSSI_SLOPE, value); + + cap->tssi_1_slope_g_band = (is_empty) ? TSSI_1_SLOPE_G_BAND_DEFAULT_VALUE : (value & TX1_G_BAND_TSSI_SLOPE_MASK); + + cap->tssi_1_offset_g_band = (is_empty) ? TSSI_1_OFFSET_G_BAND_DEFAULT_VALUE : ((value & TX1_G_BAND_TSSI_OFFSET_MASK) >> 8); + + DBGPRINT(RT_DEBUG_TRACE, ("tssi_1_slope_g_band = %d\n", cap->tssi_1_slope_g_band)); + DBGPRINT(RT_DEBUG_TRACE, ("tssi_1_offset_g_band = %d\n", cap->tssi_1_offset_g_band)); + + /* Read 54M target power */ + is_empty = RT28xx_EEPROM_READ16(pAd, TX1_G_BAND_TARGET_PWR, value); + + cap->tx_1_target_pwr_g_band = (is_empty) ? TX_TARGET_PWR_DEFAULT_VALUE : (value & TX1_G_BAND_TARGET_PWR_MASK); + + printk ("tssi_1_target_pwr_g_band = %d\n", cap->tx_1_target_pwr_g_band); + + /* Read power offset (channel delta) */ + if (is_empty) { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = 0; + } else { + /* tx power offset LOW */ + if (value & TX1_G_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & TX1_G_BAND_CHL_PWR_DELTA_LOW_SIGN) { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = ((value & TX1_G_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = -((value & TX1_G_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = 0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = %d\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW])); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX1_G_BAND_CHL_PWR_DELTA_MID, value); + if (is_empty) { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID] = 0; + cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI] = 0; + } else { + /* tx power offset MID */ + if (value & TX1_G_BAND_CHL_PWR_DELTA_MID_EN) { + if (value & TX1_G_BAND_CHL_PWR_DELTA_MID_SIGN) { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID] = (value & TX1_G_BAND_CHL_PWR_DELTA_MID_MASK); + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID] = -(value & TX1_G_BAND_CHL_PWR_DELTA_MID_MASK); + } + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID] = 0; + } + /* tx power offset HIGH */ + if (value & TX1_G_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & TX1_G_BAND_CHL_PWR_DELTA_HI_SIGN) { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI] = ((value & TX1_G_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI] = -((value & TX1_G_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + } + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI] = 0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_1_chl_pwr_delta_g_band[G_BAND_MID] = %d\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID])); + DBGPRINT(RT_DEBUG_TRACE, ("tx_1_chl_pwr_delta_g_band[G_BAND_HI] = %d\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI])); + + return ; +} + + +static VOID mt7603_show_pwr_info(RTMP_ADAPTER *pAd) +{ + struct MT_TX_PWR_CAP *cap = &pAd->chipCap.MTTxPwrCap; + UINT32 value; + + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("channel info related to power\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + + if (pAd->LatchRfRegs.Channel < 14) { + DBGPRINT(RT_DEBUG_OFF, ("central channel = %d, low_mid_hi = %d\n", pAd->LatchRfRegs.Channel, + get_low_mid_hi_index(pAd->LatchRfRegs.Channel))); + } + + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("channel power(unit: 0.5dbm)\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_target_pwr_g_band = 0x%x\n", cap->tx_0_target_pwr_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_target_pwr_g_band = 0x%x\n", cap->tx_1_target_pwr_g_band)); + + /* channel power delta */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("channel power delta(unit: 0.5db)\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = 0x%x\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_g_band[G_BAND_MID] = 0x%x\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_g_band[G_BAND_HI] = 0x%x\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = 0x%x\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_g_band[G_BAND_MID] = 0x%x\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_g_band[G_BAND_HI] = 0x%x\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI])); + + /* bw power delta */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("bw power delta(unit: 0.5db)\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("delta_tx_pwr_bw40_g_band = %d\n", cap->delta_tx_pwr_bw40_g_band)); + + /* per-rate power delta */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("per-rate power delta\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_cck_1_2 = %d\n", cap->tx_pwr_cck_1_2)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_cck_5_11 = %d\n", cap->tx_pwr_cck_5_11)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_6_9 = %d\n", cap->tx_pwr_g_band_ofdm_6_9)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_12_18 = %d\n", cap->tx_pwr_g_band_ofdm_12_18)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_24_36 = %d\n", cap->tx_pwr_g_band_ofdm_24_36)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_48 = %d\n", cap->tx_pwr_g_band_ofdm_48)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_54 = %d\n", cap->tx_pwr_g_band_ofdm_54)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_bpsk_mcs_32 = %d\n", cap->tx_pwr_ht_bpsk_mcs_32)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_bpsk_mcs_0_8 = %d\n", cap->tx_pwr_ht_bpsk_mcs_0_8)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_qpsk_mcs_1_2_9_10 = %d\n", cap->tx_pwr_ht_qpsk_mcs_1_2_9_10)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_16qam_mcs_3_4_11_12 = %d\n", cap->tx_pwr_ht_16qam_mcs_3_4_11_12)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_64qam_mcs_5_13 = %d\n", cap->tx_pwr_ht_64qam_mcs_5_13)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_64qam_mcs_6_14 = %d\n", cap->tx_pwr_ht_64qam_mcs_6_14)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_64qam_mcs_7_15 = %d\n", cap->tx_pwr_ht_64qam_mcs_7_15)); + + /* TMAC POWER INFO */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("per-rate power delta in MAC 0x60130020 ~ 0x60130030\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + RTMP_IO_READ32(pAd, TMAC_FP0R0, &value); + DBGPRINT(RT_DEBUG_OFF, ("TMAC_FP0R0 = 0x%x\n", value)); + RTMP_IO_READ32(pAd, TMAC_FP0R1, &value); + DBGPRINT(RT_DEBUG_OFF, ("TMAC_FP0R1 = 0x%x\n", value)); + RTMP_IO_READ32(pAd, TMAC_FP0R2, &value); + DBGPRINT(RT_DEBUG_OFF, ("TMAC_FP0R2 = 0x%x\n", value)); + RTMP_IO_READ32(pAd, TMAC_FP0R3, &value); + DBGPRINT(RT_DEBUG_OFF, ("TMAC_FP0R3 = 0x%x\n", value)); + RTMP_IO_READ32(pAd, TMAC_FP0R4, &value); + DBGPRINT(RT_DEBUG_OFF, ("TMAC_FP0R4 = 0x%x\n", value)); + + /* TSSI info */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("TSSI info\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("TSSI enable = %d\n", pAd->chipCap.tssi_enable)); + DBGPRINT(RT_DEBUG_OFF, ("tssi_0_slope_g_band = 0x%x\n", cap->tssi_0_slope_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("tssi_1_slope_g_band = 0x%x\n", cap->tssi_1_slope_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("tssi_0_offset_g_band = 0x%x\n", cap->tssi_0_offset_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("tssi_1_offset_g_band = 0x%x\n", cap->tssi_1_offset_g_band)); +} + + +#ifdef CAL_FREE_IC_SUPPORT +static BOOLEAN mt7603_is_cal_free_ic(RTMP_ADAPTER *pAd) +{ + UINT16 Value = 0; + BOOLEAN NotValid; + + NotValid = rtmp_ee_efuse_read16(pAd, 0x54, &Value); + + if (NotValid) + return FALSE; + + if (((Value >> 8) & 0xff) == 0x00) + return FALSE; + + NotValid = rtmp_ee_efuse_read16(pAd, 0x56, &Value); + + if (NotValid) + return FALSE; + + if (Value == 0x00) + return FALSE; + + NotValid = rtmp_ee_efuse_read16(pAd, 0x5c, &Value); + + if (NotValid) + return FALSE; + + if (Value == 0x00) + return FALSE; + + NotValid = rtmp_ee_efuse_read16(pAd, 0xf0, &Value); + + if (NotValid) + return FALSE; + + if ((Value & 0xff) == 0x00) + return FALSE; + + NotValid = rtmp_ee_efuse_read16(pAd, 0xf4, &Value); + + if (NotValid) + return FALSE; + + if ((Value & 0xff) == 0x00) + return FALSE; + + NotValid = rtmp_ee_efuse_read16(pAd, 0xf6, &Value); + + if (NotValid) + return FALSE; + + if (((Value >> 8) & 0xff) == 0x00) + return FALSE; + + return TRUE; +} + + + +static VOID mt7603_cal_free_data_get(RTMP_ADAPTER *ad) + +{ + + UINT16 value; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + + + /* 0x55 0x56 0x57 0x5C 0x5D */ + eFuseReadRegisters(ad, A_BAND_EXT_PA_SETTING, 2, &value); + /*0x55*/ + ad->EEPROMImage[A_BAND_EXT_PA_SETTING + 1] = (value >> 8) & 0xFF; + + eFuseReadRegisters(ad, TX0_G_BAND_TSSI_SLOPE, 2, &value); + /*0x56,0x57*/ + + *(UINT16 *)(&ad->EEPROMImage[TX0_G_BAND_TSSI_SLOPE]) = le2cpu16(value); + + + + eFuseReadRegisters(ad, TX1_G_BAND_TSSI_SLOPE, 2, &value); + + /*0x5c,0x5d*/ + *(UINT16 *)(&ad->EEPROMImage[TX1_G_BAND_TSSI_SLOPE]) = le2cpu16(value); + + eFuseReadRegisters(ad, TX1_G_BAND_TARGET_PWR, 2, &value); + + + /* 0xF0 0xF4 0xF7 */ + + eFuseReadRegisters(ad, CP_FT_VERSION, 2, &value); + + ad->EEPROMImage[CP_FT_VERSION] = value & 0xFF; + + eFuseReadRegisters(ad, XTAL_CALIB_FREQ_OFFSET, 2, &value); + + ad->EEPROMImage[XTAL_CALIB_FREQ_OFFSET] = value & 0xFF; + + eFuseReadRegisters(ad, XTAL_TRIM_3_COMP, 2, &value); + + ad->EEPROMImage[XTAL_TRIM_3_COMP+1] = (value >> 8) & 0xFF; + + +} + + +#endif /* CAL_FREE_IC_SUPPORT */ + + + + + +static void mt7603_antenna_default_reset( + struct _RTMP_ADAPTER *pAd, + EEPROM_ANTENNA_STRUC *pAntenna) +{ + pAntenna->word = 0; + pAd->RfIcType = RFIC_7603; + pAntenna->field.TxPath = 2; + pAntenna->field.RxPath = 2; +} + + + + +static const RTMP_CHIP_CAP MT7603_ChipCap = { + .max_nss = 2, + .TXWISize = sizeof(TMAC_TXD_L), /* 32 */ + .RXWISize = 28, +#ifdef RTMP_MAC_PCI + .WPDMABurstSIZE = 3, +#endif + .SnrFormula = SNR_FORMULA4, + .FlgIsHwWapiSup = TRUE, + .FlgIsHwAntennaDiversitySup = FALSE, +#ifdef STREAM_MODE_SUPPORT + .FlgHwStreamMode = FALSE, +#endif +#ifdef FIFO_EXT_SUPPORT + .FlgHwFifoExtCap = FALSE, +#endif + .asic_caps = (fASIC_CAP_PMF_ENC | fASIC_CAP_MCS_LUT), + .phy_caps = (fPHY_CAP_24G | fPHY_CAP_HT), + .MaxNumOfRfId = MAX_RF_ID, + .pRFRegTable = NULL, + .MaxNumOfBbpId = 200, + .pBBPRegTable = NULL, + .bbpRegTbSize = 0, + /* Force MT7603 use MBSSID_MODE2~ MBSSID_MODE6 of ENHANCE_NEW_MBSSID_MODE*/ + .MBSSIDMode = MBSSID_MODE4, +#ifdef RTMP_EFUSE_SUPPORT + .EFUSE_USAGE_MAP_START = 0x1e0, + .EFUSE_USAGE_MAP_END = 0x1fc, + .EFUSE_USAGE_MAP_SIZE = 29, + .EFUSE_RESERVED_SIZE = 22, // Cal-Free is 22 free block +#endif + .EEPROM_DEFAULT_BIN = MT7603_E2PImage, + .EEPROM_DEFAULT_BIN_SIZE = sizeof(MT7603_E2PImage), +#ifdef CONFIG_ANDES_SUPPORT + .CmdRspRxRing = RX_RING1, + .need_load_fw = TRUE, + .DownLoadType = DownLoadTypeA, +#endif + .MCUType = ANDES, + .cmd_header_len = sizeof(FW_TXD), +#ifdef RTMP_PCI_SUPPORT + .cmd_padding_len = 0, +#endif +#ifdef MT7603_E1 + .fw_header_image = MT7603_FirmwareImage, + .fw_len = sizeof(MT7603_FirmwareImage), +#endif /* MT7603_E1 */ + .fw_bin_file_name = "mtk/MT7603.bin", +#ifdef CARRIER_DETECTION_SUPPORT + .carrier_func = TONE_RADAR_V2, +#endif +#ifdef CONFIG_WIFI_TEST + .MemMapStart = 0x0000, + .MemMapEnd = 0xffff, + .MacMemMapOffset = 0x1000, + .MacStart = 0x0000, + .MacEnd = 0x0600, + .BBPMemMapOffset = 0x2000, + .BBPStart = 0x0000, + .BBPEnd = 0x0f00, + .RFIndexNum = 0, + .RFIndexOffset = 0, + .E2PStart = 0x0000, + .E2PEnd = 0x00fe, +#endif /* CONFIG_WIFI_TEST */ + .hif_type = HIF_MT, + .rf_type = RF_MT, + .RxBAWinSize = 64, + .AMPDUFactor = 3, + + .BiTxOpOn = 1, +}; + + +static const RTMP_CHIP_OP MT7603_ChipOp = { + .ChipBBPAdjust = mt7603_bbp_adjust, + .ChipSwitchChannel = mt7603_switch_channel, + .AsicMacInit = mt7603_init_mac_cr, + .AsicBbpInit = MT7603BBPInit, + .AsicRfInit = mt7603_init_rf_cr, + .AsicAntennaDefaultReset = mt7603_antenna_default_reset, + .ChipAGCInit = NULL, + .AsicRfTurnOn = NULL, + .AsicHaltAction = NULL, + .AsicRfTurnOff = NULL, + .AsicReverseRfFromSleepMode = NULL, +#ifdef CARRIER_DETECTION_SUPPORT + .ToneRadarProgram = ToneRadarProgram_v2, +#endif + .RxSensitivityTuning = NULL, + .DisableTxRx = NULL, +#ifdef RTMP_PCI_SUPPORT + //.AsicRadioOn = RT28xxPciAsicRadioOn, + //.AsicRadioOff = RT28xxPciAsicRadioOff, +#endif + +#ifdef CAL_FREE_IC_SUPPORT + .is_cal_free_ic = mt7603_is_cal_free_ic, + .cal_free_data_get = mt7603_cal_free_data_get, +#endif /* CAL_FREE_IC_SUPPORT */ + .show_pwr_info = mt7603_show_pwr_info, + +#ifdef MT_WOW_SUPPORT + .AsicWOWEnable = MT76xxAndesWOWEnable, + .AsicWOWDisable = MT76xxAndesWOWDisable, + .AsicWOWInit = MT76xxAndesWOWInit, +#endif /* MT_WOW_SUPPORT */ + .ChipSetEDCCA = mt7603_set_ed_cca, +#ifdef GREENAP_SUPPORT + .EnableAPMIMOPS = EnableAPMIMOPSv2, + .DisableAPMIMOPS = DisableAPMIMOPSv2, +#endif /* GREENAP_SUPPORT */ +}; + + +VOID mt7603_init(RTMP_ADAPTER *pAd) +{ + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + + DBGPRINT(RT_DEBUG_OFF, ("%s()-->\n", __FUNCTION__)); + + memcpy(&pAd->chipCap, &MT7603_ChipCap, sizeof(RTMP_CHIP_CAP)); + memcpy(&pAd->chipOps, &MT7603_ChipOp, sizeof(RTMP_CHIP_OP)); + + pAd->chipCap.hif_type = HIF_MT; + pAd->chipCap.mac_type = MAC_MT; + + mt_phy_probe(pAd); +#ifdef MT7603_E1 + if (MTK_REV_GTE(pAd, MT7603, MT7603E1) && MTK_REV_LT(pAd, MT7603, MT7603E2)) { + pChipCap->fw_header_image = MT7603_FirmwareImage; + pChipCap->fw_bin_file_name = "mtk/MT7603.bin"; + pChipCap->fw_len = sizeof(MT7603_FirmwareImage); + + } + else +#endif /* MT7603_E1 */ +#ifdef MT7603_E2 + if(MTK_REV_GTE(pAd, MT7603, MT7603E2)) + { + pChipCap->fw_header_image = MT7603_e2_FirmwareImage; + pChipCap->fw_bin_file_name = "mtk/MT7603_e2.bin"; + pChipCap->fw_len = sizeof(MT7603_e2_FirmwareImage); + } +#endif /* MT7603_E2 */ + +#ifdef RTMP_MAC_PCI + if (IS_PCI_INF(pAd)) { + pChipCap->tx_hw_hdr_len = pChipCap->TXWISize; + pChipCap->rx_hw_hdr_len = pChipCap->RXWISize; + } +#endif /* RTMP_MAC_PCI */ + + + + RTMP_DRS_ALG_INIT(pAd, RATE_ALG_GRP); + + /* + Following function configure beacon related parameters + in pChipCap + FlgIsSupSpecBcnBuf / BcnMaxHwNum / + WcidHwRsvNum / BcnMaxHwSize / BcnBase[] + */ + mt_bcn_buf_init(pAd); + +#ifdef DOT11W_PMF_SUPPORT + pChipCap->FlgPMFEncrtptMode = PMF_ENCRYPT_MODE_2; +#endif /* DOT11W_PMF_SUPPORT */ + + DBGPRINT(RT_DEBUG_OFF, ("<--%s()\n", __FUNCTION__)); +} + +#ifdef LED_CONTROL_SUPPORT +INT Set_MT7603LED_Proc( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *arg) +{ + UINT8 cmd = (UINT8)simple_strtol(arg, 0, 10); + /* + 0x2300[5] Default Antenna: + 0 for WIFI main antenna + 1 for WIFI aux antenna + + */ + + if (cmd < 33) + { + AndesLedOP(pAd, 0, cmd); + DBGPRINT(RT_DEBUG_TRACE, ("%s:cmd:0x%x\n", __FUNCTION__, cmd)); + } + return TRUE; +} + +INT Set_MT7603LED_Enhance_Proc( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *arg) +{ + UINT8 time = (UINT8)simple_strtol(arg, 0, 10); + /* + 0x2300[5] Default Antenna: + 0 for WIFI main antenna + 1 for WIFI aux antenna + + */ + + //if (cmd < 33) + { + AndesLedEnhanceOP(pAd, 0, time, time, 31); + DBGPRINT(RT_DEBUG_TRACE, ("%s:time:%d\n", __FUNCTION__, time)); + } + return TRUE; +} + +#define LED_BEHAVIOR_SOLID_ON 0 +#define LED_BEHAVIOR_SOLID_OFF 1 +#define LED_BEHAVIOR_GENERIC_FIX_BLINK 31 + +INT Set_MT7603LED_Behavor_Proc( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *arg) +{ + UINT8 behavior = (UINT8)simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("-->Set_MT7603LED_Behavor_Proc (%d)\n",behavior)); + switch (behavior) + { + case 0: + AndesLedEnhanceOP(pAd, 0, 0, 0, LED_BEHAVIOR_SOLID_OFF); + break; + + case 1: + AndesLedEnhanceOP(pAd, 0, 0, 0, LED_BEHAVIOR_SOLID_ON); + break; + + case 2: + AndesLedEnhanceOP(pAd, 0, 27, 27, LED_BEHAVIOR_GENERIC_FIX_BLINK); + break; + + case 3: + AndesLedEnhanceOP(pAd, 0, 200, 200, LED_BEHAVIOR_GENERIC_FIX_BLINK); + break; + + default: + { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("%s: Unknow LED behavior(%d)\n", + __FUNCTION__, behavior)); + } + break; + } + return TRUE; +} +#endif /*LED_CONTROL_SUPPORT*/ + +#ifdef USB_IOT_WORKAROUND2 +void usb_iot_add_padding(struct urb *urb, UINT8 *buf, ra_dma_addr_t dma) +{ + UCHAR pkt2drop[512] = { 0x00, 0x02, 0x00, 0x08, 0x00, 0xcd, 0x02, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x88, 0x01, 0x00, 0x00, 0x48, 0x02, 0x2a, 0x65, 0x44, 0x30, 0x00, 0x0c, 0x43, 0x26, 0x60, 0x40, + 0x01, 0x00, 0x5e, 0x00, 0x00, 0xfb, 0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x03, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x45, 0x00, 0x00, 0x43, 0x51, 0x0e, 0x40, 0x00, 0xff, 0x11, 0xc0, 0x7b, + 0xc0, 0xa8, 0xc8, 0x7b, 0xe0, 0x00, 0x00, 0xfb, 0x14, 0xe9, 0x14, 0xe9, 0x00, 0x2f, 0xc8, 0x6f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x5f, 0x73, 0x61, + 0x6e, 0x65, 0x2d, 0x70, 0x6f, 0x72, 0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f, 0x63, + 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + int padding = 0; + int sendlen = 0; + + if (!urb || !buf){ + printk("usb_iot_add_padding %x %x\n", urb, buf); + printk("\ntransfer_buffer_length=%d\n", urb->transfer_buffer_length); + return; + } + + padding = 512 - ((urb->transfer_buffer_length)%512); + + // copy data to new place + NdisCopyMemory(buf, urb->transfer_buffer, urb->transfer_buffer_length); + sendlen = urb->transfer_buffer_length; + + // add padding to 512 boundary + NdisZeroMemory(buf+sendlen, padding); + sendlen += padding; + + NdisCopyMemory(buf+sendlen, pkt2drop, 512); + sendlen += 512; + + // add final 4 bytes padding + NdisZeroMemory(buf+sendlen, 4); + sendlen += 4; + + // update URB + urb->transfer_buffer = buf; + if (dma) + urb->transfer_dma = dma; + + urb->transfer_buffer_length = sendlen; + +} +#endif + +void mt7603_set_ed_cca(RTMP_ADAPTER *pAd, BOOLEAN enable) +{ + + UINT32 macVal = 0, macVal2 = 0; + UINT32 NBIDmacVal = 0; + BOOLEAN bIsCERegion = FALSE; + UINT32 ed_th = 0; + bIsCERegion = GetEDCCASupport(pAd); + ed_th = pAd->ed_th; + + RTMP_IO_READ32(pAd, WF_PHY_BASE + 0x0634, &macVal2); + + if (enable) + { + macVal = 0xD7C87D0F; //EDCCA ON , TH - L, USER case //D7C87D0F + ed_th = pAd->ed_th; + pAd->ed_on = TRUE; + if((!bIsCERegion) && (ed_th < NON_CE_REGION_MAX_ED_TH)) { + macVal = macVal & (~(0x7F << 8)); /*NON-CE Region, ED_TH set to -40dBm~-50dBm;bit14~bit8 is for ED_TH, 0x00 means -62dBm*/ + macVal = macVal | (ed_th << 8); + pAd->ed_on = FALSE; + DBGPRINT(RT_DEBUG_OFF, ("%s: NON-CE Region,60200618=%x,ed_th=%x\n", __FUNCTION__, macVal,ed_th)); + } + RTMP_IO_WRITE32(pAd, WF_PHY_BASE + 0x0618, macVal); + + macVal2 |= 0x1; + RTMP_IO_WRITE32(pAd, WF_PHY_BASE + 0x0634, macVal2); + +#ifdef SMART_CARRIER_SENSE_SUPPORT + pAd->SCSCtrl.EDCCA_Status = 1; + DBGPRINT(RT_DEBUG_ERROR, ("%s: TURN ON EDCCA mac 0x10618 = 0x%x, EDCCA_Status=%d\n", __FUNCTION__, macVal, pAd->SCSCtrl.EDCCA_Status)); +#else + DBGPRINT(RT_DEBUG_ERROR, ("%s: TURN ON EDCCA mac 0x10618 = 0x%x\n", __FUNCTION__, macVal)); +#endif /* SMART_CARRIER_SENSE_SUPPORT */ + + } + else + { + + + /* After 7603 ACI issue task, the edcca could be always opened; + set ED threshold to -65dBm; + Disable PSE reset; + */ + macVal = 0xD7e87d10; + pAd->ed_on = TRUE; + RTMP_IO_WRITE32(pAd, WF_PHY_BASE + 0x0618, macVal); + + macVal2 &= 0xFFFFFFFE; + RTMP_IO_WRITE32(pAd, WF_PHY_BASE + 0x0634, macVal2); + + /*Adjust PD Threshold to -40dBm*/ + RTMP_IO_READ32(pAd, WF_PHY_BASE + 0x0620 , &macVal); + macVal &= ~0x3f; + macVal |= 0x3c; + RTMP_IO_WRITE32(pAd, WF_PHY_BASE + 0x0620, macVal); +#ifdef SMART_CARRIER_SENSE_SUPPORT + pAd->SCSCtrl.EDCCA_Status = 0; + DBGPRINT(RT_DEBUG_ERROR, ("%s: TURN OFF EDCCA mac 0x10618 = 0x%x, EDCCA_Status=%d\n", __FUNCTION__, macVal, pAd->SCSCtrl.EDCCA_Status)); +#else + DBGPRINT(RT_DEBUG_ERROR, ("%s: TURN OFF EDCCA mac 0x10618 = 0x%x\n", __FUNCTION__, macVal)); +#endif /* SMART_CARRIER_SENSE_SUPPORT */ + + } + + if (strncmp(pAd->CommonCfg.CountryCode, "JP", 2) == 0) + { + /* disable NBID for JAPAN carrier sense test mac, 0610[24]=0 [31]=0 */ + RTMP_IO_READ32(pAd, WF_PHY_BASE + 0x0610, &NBIDmacVal); + + DBGPRINT(RT_DEBUG_ERROR, ("%s: pAd->CommonCfg.CountryCode = %s \n", __FUNCTION__, pAd->CommonCfg.CountryCode)); + NBIDmacVal &= ~(1<<24); + NBIDmacVal &= ~(1<<31); + RTMP_IO_WRITE32(pAd, WF_PHY_BASE + 0x0610, NBIDmacVal); + DBGPRINT(RT_DEBUG_ERROR, ("%s: TURN OFF NBID mac 0x10610 = 0x%x\n", __FUNCTION__, NBIDmacVal)); + } + else + { + RTMP_IO_READ32(pAd, WF_PHY_BASE + 0x0610, &NBIDmacVal); + NBIDmacVal |= (1<<24); + NBIDmacVal |= (1<<31); + RTMP_IO_WRITE32(pAd, WF_PHY_BASE + 0x0610, NBIDmacVal); + } + /*Init Lower_signal_level to -65dBm*/ + RTMP_IO_READ32(pAd, WF_PHY_BASE + 0x0620, &macVal2); + macVal2 &= 0xFFFFFFC0; + macVal2 |= 0x00000023; + RTMP_IO_WRITE32(pAd, WF_PHY_BASE + 0x0620, macVal2); + +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/mt7628.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/mt7628.c new file mode 100644 index 000000000..62468c504 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/mt7628.c @@ -0,0 +1,1018 @@ +#include "rt_config.h" + +#include "mcu/mt7628_firmware.h" +#include "eeprom/mt7628_e2p.h" +#include "phy/wf_phy_back.h" + + +static VOID mt7628_bbp_adjust(RTMP_ADAPTER *pAd) +{ + static char *ext_str[]={"extNone", "extAbove", "", "extBelow"}; + UCHAR rf_bw, ext_ch; + +#ifdef DOT11_N_SUPPORT + if (get_ht_cent_ch(pAd, &rf_bw, &ext_ch) == FALSE) +#endif /* DOT11_N_SUPPORT */ + { + rf_bw = BW_20; + ext_ch = EXTCHA_NONE; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + } + + bbp_set_bw(pAd, rf_bw); + +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("%s() : %s, ChannelWidth=%d, Channel=%d, ExtChanOffset=%d(%d) \n", + __FUNCTION__, ext_str[ext_ch], + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth, + pAd->CommonCfg.Channel, + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA, + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset)); +#endif /* DOT11_N_SUPPORT */ +} + +static void mt7603_tx_pwr_gain(RTMP_ADAPTER *pAd, UINT8 channel) +{ + UINT32 value; + CHAR tx_0_pwr; + struct MT_TX_PWR_CAP *cap = &pAd->chipCap.MTTxPwrCap; + + + return;//Carter add for first day link. + + tx_0_pwr = cap->tx_0_target_pwr_g_band; + tx_0_pwr += cap->tx_0_chl_pwr_delta_g_band[get_low_mid_hi_index(channel)]; + + RTMP_IO_READ32(pAd, TMAC_FP0R0, &value); + + value &= ~LG_OFDM0_FRAME_POWER0_DBM_MASK; + value |= LG_OFDM0_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_g_band_ofdm_6_9); + + value &= ~LG_OFDM1_FRAME_POWER0_DBM_MASK; + value |= LG_OFDM1_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_g_band_ofdm_12_18); + + value &= ~LG_OFDM2_FRAME_POWER0_DBM_MASK; + value |= LG_OFDM2_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_g_band_ofdm_24_36); + + value &= ~LG_OFDM3_FRAME_POWER0_DBM_MASK; + value |= LG_OFDM3_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_g_band_ofdm_48); + + RTMP_IO_WRITE32(pAd, TMAC_FP0R0, value); + + RTMP_IO_READ32(pAd, TMAC_FP0R1, &value); + + value &= ~HT20_0_FRAME_POWER0_DBM_MASK; + value |= HT20_0_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_bpsk_mcs_0_8); + + value &= ~HT20_1_FRAME_POWER0_DBM_MASK; + value |= HT20_1_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_qpsk_mcs_1_2_9_10); + + value &= ~HT20_2_FRAME_POWER0_DBM_MASK; + value |= HT20_2_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_16qam_mcs_3_4_11_12); + + value &= ~HT20_3_FRAME_POWER0_DBM_MASK; + value |= HT20_3_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_64qam_mcs_5_13); + + RTMP_IO_WRITE32(pAd, TMAC_FP0R1, value); + + RTMP_IO_READ32(pAd, TMAC_FP0R2, &value); + + value &= ~HT40_0_FRAME_POWER0_DBM_MASK; + value |= HT40_0_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_bpsk_mcs_0_8 + + cap->delta_tx_pwr_bw40_g_band); + + value &= ~HT40_1_FRAME_POWER0_DBM_MASK; + value |= HT40_1_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_qpsk_mcs_1_2_9_10 + + cap->delta_tx_pwr_bw40_g_band); + + value &= ~HT40_2_FRAME_POWER0_DBM_MASK; + value |= HT40_2_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_16qam_mcs_3_4_11_12 + + cap->delta_tx_pwr_bw40_g_band); + + value &= ~HT40_3_FRAME_POWER0_DBM_MASK; + value |= HT40_3_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_64qam_mcs_5_13 + + cap->delta_tx_pwr_bw40_g_band); + + RTMP_IO_WRITE32(pAd, TMAC_FP0R2, value); + + RTMP_IO_READ32(pAd, TMAC_FP0R3, &value); + + value &= ~CCK0_FRAME_POWER0_DBM_MASK; + value |= CCK0_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_cck_1_2); + + value &= ~LG_OFDM4_FRAME_POWER0_DBM_MASK; + value |= LG_OFDM4_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_g_band_ofdm_54); + + value &= ~CCK1_FRAME_POWER0_DBM_MASK; + value |= CCK1_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_cck_5_11); + + value &= ~HT40_6_FRAME_POWER0_DBM_MASK; + value |= HT40_6_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_bpsk_mcs_32 + cap->delta_tx_pwr_bw40_g_band); + + RTMP_IO_WRITE32(pAd, TMAC_FP0R3, value); + + RTMP_IO_READ32(pAd, TMAC_FP0R4, &value); + + value &= ~HT20_4_FRAME_POWER0_DBM_MASK; + value |= HT20_4_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_64qam_mcs_6_14); + + value &= ~HT20_5_FRAME_POWER0_DBM_MASK; + value |= HT20_5_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_64qam_mcs_7_15); + + value &= ~HT40_4_FRAME_POWER0_DBM_MASK; + value |= HT40_4_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_64qam_mcs_6_14 + + cap->delta_tx_pwr_bw40_g_band); + + value &= ~HT40_5_FRAME_POWER0_DBM_MASK; + value |= HT40_5_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_64qam_mcs_7_15 + + cap->delta_tx_pwr_bw40_g_band); + + RTMP_IO_WRITE32(pAd, TMAC_FP0R4, value); +} + + +static void mt7628_switch_channel(RTMP_ADAPTER *pAd, UCHAR channel, BOOLEAN scan) +{ + + + /* tx pwr gain setting */ + mt7603_tx_pwr_gain(pAd, channel); + + if (pAd->CommonCfg.BBPCurrentBW == BW_20) + CmdChannelSwitch(pAd, channel, channel, BW_20, + pAd->CommonCfg.TxStream, pAd->CommonCfg.RxStream); + else + CmdChannelSwitch(pAd, pAd->CommonCfg.Channel, channel, pAd->CommonCfg.BBPCurrentBW, + pAd->CommonCfg.TxStream, pAd->CommonCfg.RxStream); + + /* Channel latch */ + pAd->LatchRfRegs.Channel = channel; + + + DBGPRINT(RT_DEBUG_OFF, + ("%s(): Switch to Ch#%d(%dT%dR), BBP_BW=%d\n", + __FUNCTION__, + channel, + pAd->CommonCfg.TxStream, + pAd->CommonCfg.RxStream, + pAd->CommonCfg.BBPCurrentBW)); +} + + +/* + Init TxD short format template which will copy by PSE-Client to LMAC +*/ +static INT asic_set_tmac_info_template(RTMP_ADAPTER *pAd) +{ + UINT32 dw[5]; + TMAC_TXD_2 *dw2 = (TMAC_TXD_2 *)(&dw[0]); + TMAC_TXD_3 *dw3 = (TMAC_TXD_3 *)(&dw[1]); + TMAC_TXD_4 *dw4 = (TMAC_TXD_4 *)(&dw[2]); + TMAC_TXD_5 *dw5 = (TMAC_TXD_5 *)(&dw[3]); + TMAC_TXD_6 *dw6 = (TMAC_TXD_6 *)(&dw[4]); + + NdisZeroMemory((UCHAR *)(&dw[0]), sizeof(dw)); + + dw2->htc_vld = 0; + dw2->frag = 0; + dw2->max_tx_time = 0; + dw2->fix_rate = 0; + + dw3->remain_tx_cnt = MT_TX_RETRY_CNT; + dw3->sn_vld = 0; + dw3->pn_vld = 0; + + dw5->pid = PID_DATA_AMPDU; + dw5->tx_status_fmt = 0; + dw5->tx_status_2_host = 0; // Disable TxS + dw5->bar_sn_ctrl = 0; //HW + dw5->pwr_mgmt = TMI_PM_BIT_CFG_BY_HW; // HW + +#ifdef RTMP_PCI_SUPPORT +// TODO: shaing, for MT7628, may need to change this as RTMP_MAC_PCI + + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, 0x80080000); + + + /* For short format */ + RTMP_IO_WRITE32(pAd, 0xc0040, dw[0]); + RTMP_IO_WRITE32(pAd, 0xc0044, dw[1]); + RTMP_IO_WRITE32(pAd, 0xc0048, dw[2]); + RTMP_IO_WRITE32(pAd, 0xc004c, dw[3]); + RTMP_IO_WRITE32(pAd, 0xc0050, dw[4]); + + +// TODO: shaing, for MT7628, may need to change this as RTMP_MAC_PCI + // After change the Tx Padding CR of PCI-E Client, we need to re-map for PSE region + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, MT_PSE_BASE_ADDR); + +#endif /* RTMP_PCI_SUPPORT */ + + + return TRUE; +} + + +static VOID mt7628_init_mac_cr(RTMP_ADAPTER *pAd) +{ + UINT32 mac_val; + + DBGPRINT(RT_DEBUG_OFF, ("%s()-->\n", __FUNCTION__)); + + /* Preparation of TxD DW2~DW6 when we need run 3DW format */ + asic_set_tmac_info_template(pAd); + + /* A-MPDU Agg limit control in range 1/2/4/8/10/12/14/16 */ + RTMP_IO_READ32(pAd, AGG_AWSCR, &mac_val); + mac_val = ((1 << 0) |(2<<8) | (4 << 16) | (8 << 24)); + RTMP_IO_WRITE32(pAd, AGG_AWSCR, mac_val); + + RTMP_IO_READ32(pAd, AGG_AWSCR1, &mac_val); + //mac_val = ((10 << 0) |(12<<8) | (14 << 16) | (16 << 24)); + mac_val &= 0x0; + mac_val = ((10 << 0) |(12<<8) | (14 << 16) | (0 << 24)); + RTMP_IO_WRITE32(pAd, AGG_AWSCR1, mac_val); + + RTMP_IO_WRITE32(pAd, AGG_AALCR, 0); + RTMP_IO_WRITE32(pAd, AGG_AALCR1, 0); + + /* Vector report queue setting */ + RTMP_IO_READ32(pAd, DMA_VCFR0, &mac_val); + mac_val |= BIT13; + RTMP_IO_WRITE32(pAd, DMA_VCFR0, mac_val); + + /* TxStatus report queue setting */ + RTMP_IO_READ32(pAd, DMA_TCFR1, &mac_val); + mac_val |= BIT14; + RTMP_IO_WRITE32(pAd, DMA_TCFR1, mac_val); + + /* TMR report queue setting */ + RTMP_IO_READ32(pAd, DMA_TMCFR0, &mac_val); + mac_val |= BIT13;//TMR report send to HIF q1. + mac_val = mac_val & ~(BIT0); + mac_val = mac_val & ~(BIT1); + RTMP_IO_WRITE32(pAd, DMA_TMCFR0, mac_val); + + RTMP_IO_READ32(pAd, RMAC_TMR_PA, &mac_val); + mac_val = mac_val & ~BIT31; + RTMP_IO_WRITE32(pAd, RMAC_TMR_PA, mac_val); + /* Configure all rx packets to HIF, except WOL2M packet */ + RTMP_IO_READ32(pAd, DMA_RCFR0, &mac_val); + mac_val = 0x00010000; // drop duplicate + // TODO: shiang-MT7603, remove me after FPGA verification done + mac_val |= 0xc0200000; // receive BA/CF_End/Ack/RTS/CTS/CTRL_RSVED + RTMP_IO_WRITE32(pAd, DMA_RCFR0, mac_val); + + /* Configure Rx Vectors report to HIF */ + RTMP_IO_READ32(pAd, DMA_VCFR0, &mac_val); + mac_val &= (~0x1); // To HIF + mac_val |= 0x2000; // RxRing 1 + RTMP_IO_WRITE32(pAd, DMA_VCFR0, mac_val); + + /* Enable RX Group to HIF */ + AsicSetRxGroup(pAd, HIF_PORT, RXS_GROUP3, TRUE); + AsicSetRxGroup(pAd, MCU_PORT, RXS_GROUP3, TRUE); + + /* AMPDU BAR setting */ + /* Enable HW BAR feature */ + AsicSetBARTxCntLimit(pAd, TRUE, 1); + + /* Configure the BAR rate setting */ + RTMP_IO_READ32(pAd, AGG_ACR, &mac_val); + mac_val &= (~0xfff00000); + mac_val &= ~(AGG_ACR_AMPDU_NO_BA_AR_RULE_MASK|AMPDU_NO_BA_RULE); + RTMP_IO_WRITE32(pAd, AGG_ACR, mac_val); + + /* AMPDU Statistics Range Control setting + 0 < agg_cnt - 1 <= range_cr(0), => 1 + range_cr(0) < agg_cnt - 1 <= range_cr(4), => 2~5 + range_cr(4) < agg_cnt - 1 <= range_cr(14), => 6~15 + range_cr(14) < agg_cnt - 1, => 16~ + */ + RTMP_IO_READ32(pAd, AGG_ASRCR, &mac_val); + mac_val = (0 << 0) | (4 << 8) | (14 << 16); + RTMP_IO_WRITE32(pAd, AGG_ASRCR, mac_val); + + // Enable MIB counters + RTMP_IO_WRITE32(pAd, MIB_MSCR, 0x7fffffff); + RTMP_IO_WRITE32(pAd, MIB_MPBSCR, 0xffffffff); + + + /* CCA Workaround */ + RTMP_IO_READ32(pAd, TMAC_TRCR, &mac_val); + mac_val &= ~CCA_SRC_SEL_MASK; + mac_val |= CCA_SRC_SEL(0x3); + mac_val &= ~CCA_SEC_SRC_SEL_MASK; + mac_val |= CCA_SEC_SRC_SEL(0x3); + RTMP_IO_WRITE32(pAd, TMAC_TRCR, mac_val); + + RTMP_IO_READ32(pAd, WTBL_OFF_RMVTCR, &mac_val); + /* RCPI include ACK and Data */ + mac_val |= RX_MV_MODE; + RTMP_IO_WRITE32(pAd, WTBL_OFF_RMVTCR, mac_val); + +#ifdef MT7628_FPGA + // enable MAC2MAC mode + RTMP_IO_READ32(pAd, RMAC_MISC, &mac_val); + mac_val |= BIT18; + RTMP_IO_WRITE32(pAd, RMAC_MISC, mac_val); + + mac_val = 0x00d700d7; + RTMP_IO_WRITE32(pAd, TMAC_CDTR, mac_val); + mac_val = 0x00d700d7; + RTMP_IO_WRITE32(pAd, TMAC_ODTR, mac_val); +#endif /* MT7628_FPGA */ + + + + /* Turn on RX RIFS Mode */ + RTMP_IO_READ32(pAd, TMAC_TCR, &mac_val); + mac_val |= RX_RIFS_MODE; + RTMP_IO_WRITE32(pAd, TMAC_TCR, mac_val); + /*enable RDG setting*/ + if(pAd->CommonCfg.bRdg) + { + RTMP_IO_READ32(pAd, TMAC_TCR, &mac_val); + mac_val |= (RDG_RA_MODE | RDG_RESP_EN); + RTMP_IO_WRITE32(pAd, TMAC_TCR, mac_val); + + /*enable long NAV*/ + RTMP_IO_READ32(pAd, AGG_PCR, &mac_val); + mac_val &= ~(PROTECTION_MODE); + RTMP_IO_WRITE32(pAd, TMAC_TCR, mac_val); + } +} + + +static VOID MT7628BBPInit(RTMP_ADAPTER *pAd) +{ + UINT32 Value; + + RTMP_IO_READ32(pAd, 0x106c8, &Value); + Value &= ~(1 << 30); + RTMP_IO_WRITE32(pAd, 0x106c8, Value); + + RTMP_IO_READ32(pAd, 0x106cc, &Value); + Value &= ~(1 << 0); + RTMP_IO_WRITE32(pAd, 0x106cc, Value); +} + +static void mt7628_init_rf_cr(RTMP_ADAPTER *ad) +{ + return; +} + +static UINT8 mt7628_txpwr_chlist[] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +}; + + +int mt7628_read_chl_pwr(RTMP_ADAPTER *pAd) +{ + UINT32 i, choffset; + struct MT_TX_PWR_CAP *cap = &pAd->chipCap.MTTxPwrCap; + + mt7628_get_tx_pwr_info(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("%s()--->\n", __FUNCTION__)); + + for (i = 0; i < sizeof(mt7628_txpwr_chlist); i++) { + pAd->TxPower[i].Channel = mt7628_txpwr_chlist[i]; + pAd->TxPower[i].Power = TX_TARGET_PWR_DEFAULT_VALUE; + pAd->TxPower[i].Power2 = TX_TARGET_PWR_DEFAULT_VALUE; + } + + for (i = 0; i < 14; i++) { + pAd->TxPower[i].Power = cap->tx_0_target_pwr_g_band; + pAd->TxPower[i].Power2 = cap->tx_1_target_pwr_g_band; + } + + choffset = 14; + + /* 4. Print and Debug*/ + for (i = 0; i < choffset; i++) + { + DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: TxPower[%03d], Channel=%d, Power[Tx0:%d, Tx1:%d]\n", + i, pAd->TxPower[i].Channel, pAd->TxPower[i].Power, pAd->TxPower[i].Power2 )); + } + + return TRUE; +} + + +/* Read power per rate */ +void mt7628_get_tx_pwr_per_rate(RTMP_ADAPTER *pAd) +{ + BOOLEAN is_empty = 0; + UINT16 value = 0; + struct MT_TX_PWR_CAP *cap = &pAd->chipCap.MTTxPwrCap; + + /* G Band tx power for CCK 1M/2M, 5.5M/11M */ + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_CCK_1_2M, value); + if (is_empty) { + cap->tx_pwr_cck_1_2 = 0; + cap->tx_pwr_cck_5_11 = 0; + } else { + /* CCK 1M/2M */ + if (value & TX_PWR_CCK_1_2M_EN) { + if (value & TX_PWR_CCK_1_2M_SIGN) { + cap->tx_pwr_cck_1_2 = (value & TX_PWR_CCK_1_2M_MASK); + } else { + cap->tx_pwr_cck_1_2 = -(value & TX_PWR_CCK_1_2M_MASK); + } + } else { + cap->tx_pwr_cck_1_2 = 0; + } + + /* CCK 5.5M/11M */ + if (value & TX_PWR_CCK_5_11M_EN) { + if (value & TX_PWR_CCK_5_11M_SIGN) { + cap->tx_pwr_cck_5_11 = ((value & TX_PWR_CCK_5_11M_MASK) >> 8); + } else { + cap->tx_pwr_cck_5_11 = -((value & TX_PWR_CCK_5_11M_MASK) >> 8); + } + } else { + cap->tx_pwr_cck_5_11 = 0; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_cck_1_2 = %d\n", cap->tx_pwr_cck_1_2)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_cck_5_11 = %d\n", cap->tx_pwr_cck_5_11)); + + /* G Band tx power for OFDM 6M/9M, 12M/18M, 24M/36M, 48M/54M */ + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_G_BAND_OFDM_6_9M, value); + if (is_empty) { + cap->tx_pwr_g_band_ofdm_6_9 = 0; + cap->tx_pwr_g_band_ofdm_12_18 = 0; + } else { + /* OFDM 6M/9M */ + if (value & TX_PWR_G_BAND_OFDM_6_9M_EN) { + if (value & TX_PWR_G_BAND_OFDM_6_9M_SIGN) { + cap->tx_pwr_g_band_ofdm_6_9 = (value & TX_PWR_G_BAND_OFDM_6_9M_MASK); + } else { + cap->tx_pwr_g_band_ofdm_6_9 = -(value & TX_PWR_G_BAND_OFDM_6_9M_MASK); + } + } else { + cap->tx_pwr_g_band_ofdm_6_9 = 0; + } + + /* OFDM 12M/18M */ + if (value & TX_PWR_G_BAND_OFDM_12_18M_EN) { + if (value & TX_PWR_G_BAND_OFDM_12_18M_SIGN) { + cap->tx_pwr_g_band_ofdm_12_18 = ((value & TX_PWR_G_BAND_OFDM_12_18M_MASK) >> 8); + } else { + cap->tx_pwr_g_band_ofdm_12_18 = -((value & TX_PWR_G_BAND_OFDM_12_18M_MASK) >> 8); + } + } else { + cap->tx_pwr_g_band_ofdm_12_18 = 0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_g_band_ofdm_6_9 = %d\n", cap->tx_pwr_g_band_ofdm_6_9)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_g_band_ofdm_12_18 = %d\n", cap->tx_pwr_g_band_ofdm_12_18)); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_G_BAND_OFDM_24_36M, value); + if (is_empty) { + cap->tx_pwr_g_band_ofdm_24_36 = 0; + cap->tx_pwr_g_band_ofdm_48= 0; + } else { + /* OFDM 24M/36M */ + if (value & TX_PWR_G_BAND_OFDM_24_36M_EN) { + if (value & TX_PWR_G_BAND_OFDM_24_36M_SIGN) { + cap->tx_pwr_g_band_ofdm_24_36 = (value & TX_PWR_G_BAND_OFDM_24_36M_MASK); + } else { + cap->tx_pwr_g_band_ofdm_24_36 = -(value & TX_PWR_G_BAND_OFDM_24_36M_MASK); + } + } else { + cap->tx_pwr_g_band_ofdm_24_36 = 0; + } + + /* OFDM 48M */ + if (value & TX_PWR_G_BAND_OFDM_48M_EN) { + if (value & TX_PWR_G_BAND_OFDM_48M_SIGN) { + cap->tx_pwr_g_band_ofdm_48 = ((value & TX_PWR_G_BAND_OFDM_48M_MASK) >> 8); + } else { + cap->tx_pwr_g_band_ofdm_48 = -((value & TX_PWR_G_BAND_OFDM_48M_MASK) >> 8); + } + } else { + cap->tx_pwr_g_band_ofdm_48 = 0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_g_band_ofdm_24_36 = %d\n", cap->tx_pwr_g_band_ofdm_24_36)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_g_band_ofdm_48 = %d\n", cap->tx_pwr_g_band_ofdm_48)); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_G_BAND_OFDM_54M, value); + if (is_empty) { + cap->tx_pwr_g_band_ofdm_54 = 0; + cap->tx_pwr_ht_bpsk_mcs_0_8 = 0; + } else { + /* OFDM 54M */ + if (value & TX_PWR_G_BAND_OFDM_54M_EN) { + if (value & TX_PWR_G_BAND_OFDM_54M_SIGN) { + cap->tx_pwr_g_band_ofdm_54 = (value & TX_PWR_G_BAND_OFDM_54M_MASK); + } else { + cap->tx_pwr_g_band_ofdm_54 = -(value & TX_PWR_G_BAND_OFDM_54M_MASK); + } + } else { + cap->tx_pwr_g_band_ofdm_54 = 0; + } + + /* HT MCS_0, MCS_8 */ + if (value & TX_PWR_HT_BPSK_MCS_0_8_EN) { + if (value & TX_PWR_HT_BPSK_MCS_0_8_SIGN) { + cap->tx_pwr_ht_bpsk_mcs_0_8 = ((value & TX_PWR_HT_BPSK_MCS_0_8_MASK) >> 8); + } else { + cap->tx_pwr_ht_bpsk_mcs_0_8 = -((value & TX_PWR_HT_BPSK_MCS_0_8_MASK) >> 8); + } + } else { + cap->tx_pwr_ht_bpsk_mcs_0_8 = 0; + } } + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_g_band_ofdm_54 = %d\n", cap->tx_pwr_g_band_ofdm_54)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_bpsk_mcs_0_8 = %d\n", cap->tx_pwr_ht_bpsk_mcs_0_8)); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_HT_BPSK_MCS_32, value); + if (is_empty) { + cap->tx_pwr_ht_bpsk_mcs_32 = 0; + cap->tx_pwr_ht_qpsk_mcs_1_2_9_10 = 0; + } else { + /* HT MCS_0, MCS_8 */ + if (value & TX_PWR_HT_BPSK_MCS_32_EN) { + if (value & TX_PWR_HT_BPSK_MCS_32_SIGN) { + cap->tx_pwr_ht_bpsk_mcs_32 = (value & TX_PWR_HT_BPSK_MCS_32_MASK); + } else { + cap->tx_pwr_ht_bpsk_mcs_32 = -(value & TX_PWR_HT_BPSK_MCS_32_MASK); + } + } else { + cap->tx_pwr_ht_bpsk_mcs_32 = 0; + } + + /* HT MCS_1, MCS_2, MCS_9, MCS_10 */ + if (value & TX_PWR_HT_QPSK_MCS_1_2_9_10_EN) { + if (value & TX_PWR_HT_QPSK_MCS_1_2_9_10_SIGN) { + cap->tx_pwr_ht_qpsk_mcs_1_2_9_10 = ((value & TX_PWR_HT_QPSK_MCS_1_2_9_10_MASK) >> 8); + } else { + cap->tx_pwr_ht_qpsk_mcs_1_2_9_10 = -((value & TX_PWR_HT_QPSK_MCS_1_2_9_10_MASK) >> 8); + } + } else { + cap->tx_pwr_ht_qpsk_mcs_1_2_9_10 = 0; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_bpsk_mcs_32 = %d\n", cap->tx_pwr_ht_bpsk_mcs_32)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_qpsk_mcs_1_2_9_10 = %d\n", cap->tx_pwr_ht_qpsk_mcs_1_2_9_10)); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_HT_16QAM_MCS_3_4_11_12, value); + if (is_empty) { + cap->tx_pwr_ht_16qam_mcs_3_4_11_12 = 0; + cap->tx_pwr_ht_64qam_mcs_5_13 = 0; + } else { + /* HT MCS_3, MCS_4, MCS_11, MCS_12 */ + if (value & TX_PWR_HT_16QAM_MCS_3_4_11_12_EN) { + if (value & TX_PWR_HT_16QAM_MCS_3_4_11_12_SIGN) { + cap->tx_pwr_ht_16qam_mcs_3_4_11_12 = (value & TX_PWR_HT_16QAM_MCS_3_4_11_12_MASK); + } else { + cap->tx_pwr_ht_16qam_mcs_3_4_11_12 = -(value & TX_PWR_HT_16QAM_MCS_3_4_11_12_MASK); + } + } else { + cap->tx_pwr_ht_16qam_mcs_3_4_11_12 = 0; + } + + /* HT MCS_5, MCS_13 */ + if (value & TX_PWR_HT_64QAM_MCS_5_13_EN) { + if (value & TX_PWR_HT_64QAM_MCS_5_13_SIGN) { + cap->tx_pwr_ht_64qam_mcs_5_13 = ((value & TX_PWR_HT_64QAM_MCS_5_13_MASK) >> 8); + } else { + cap->tx_pwr_ht_64qam_mcs_5_13 = -((value & TX_PWR_HT_64QAM_MCS_5_13_MASK) >> 8); + } + } else { + cap->tx_pwr_ht_64qam_mcs_5_13 = 0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_16qam_mcs_3_4_11_12 = %d\n", cap->tx_pwr_ht_16qam_mcs_3_4_11_12)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_64qam_mcs_5_13 = %d\n", cap->tx_pwr_ht_64qam_mcs_5_13)); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_HT_64QAM_MCS_6_14, value); + if (is_empty) { + cap->tx_pwr_ht_64qam_mcs_6_14 = 0; + cap->tx_pwr_ht_64qam_mcs_7_15 = 0; + } else { + /* HT MCS_6, MCS_14 */ + if (value & TX_PWR_HT_64QAM_MCS_6_14_EN) { + if (value & TX_PWR_HT_64QAM_MCS_6_14_SIGN) { + cap->tx_pwr_ht_64qam_mcs_6_14 = (value & TX_PWR_HT_64QAM_MCS_6_14_MASK); + } else { + cap->tx_pwr_ht_64qam_mcs_6_14 = -(value & TX_PWR_HT_64QAM_MCS_6_14_MASK); + } + } else { + cap->tx_pwr_ht_64qam_mcs_6_14 = 0; + } + + /* HT MCS_7, MCS_15 */ + if (value & TX_PWR_HT_64QAM_MCS_7_15_EN) { + if (value & TX_PWR_HT_64QAM_MCS_7_15_SIGN) { + cap->tx_pwr_ht_64qam_mcs_7_15 = ((value & TX_PWR_HT_64QAM_MCS_7_15_MASK) >> 8); + } else { + cap->tx_pwr_ht_64qam_mcs_7_15 = -((value & TX_PWR_HT_64QAM_MCS_7_15_MASK) >> 8); + } + } else { + cap->tx_pwr_ht_64qam_mcs_7_15 = 0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_64qam_mcs_6_14 = %d\n", cap->tx_pwr_ht_64qam_mcs_6_14)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_64qam_mcs_7_15 = %d\n", cap->tx_pwr_ht_64qam_mcs_7_15)); + + return; +} + + +void mt7628_get_tx_pwr_info(RTMP_ADAPTER *pAd) +{ + bool is_empty = 0; + UINT16 value = 0; + struct MT_TX_PWR_CAP *cap = &pAd->chipCap.MTTxPwrCap; + + /* Read 20/40 BW delta */ + is_empty = RT28xx_EEPROM_READ16(pAd, G_BAND_20_40_BW_PWR_DELTA, value); + + if (is_empty) { + cap->delta_tx_pwr_bw40_g_band = 0x0; + } else { + /* G Band */ + if (value & G_BAND_20_40_BW_PWR_DELTA_EN) { + if (value & G_BAND_20_40_BW_PWR_DELTA_SIGN) { + /* bit[0..5] tx power delta value */ + cap->delta_tx_pwr_bw40_g_band = (value & G_BAND_20_40_BW_PWR_DELTA_MASK); + } else { + cap->delta_tx_pwr_bw40_g_band = -(value & G_BAND_20_40_BW_PWR_DELTA_MASK); + } + } else { + cap->delta_tx_pwr_bw40_g_band = 0x0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("delta_tx_pwr_bw40_g_band = %d\n", cap->delta_tx_pwr_bw40_g_band)); + + /////////////////// Tx0 ////////////////////////// + /* Read TSSI slope/offset for TSSI compensation */ + is_empty = RT28xx_EEPROM_READ16(pAd, TX0_G_BAND_TSSI_SLOPE, value); + + cap->tssi_0_slope_g_band = + (is_empty) ? TSSI_0_SLOPE_G_BAND_DEFAULT_VALUE : (value & TX0_G_BAND_TSSI_SLOPE_MASK); + + cap->tssi_0_offset_g_band = + (is_empty) ? TSSI_0_OFFSET_G_BAND_DEFAULT_VALUE : ((value & TX0_G_BAND_TSSI_OFFSET_MASK) >> 8); + + DBGPRINT(RT_DEBUG_TRACE, ("tssi_0_slope_g_band = %d\n", cap->tssi_0_slope_g_band)); + DBGPRINT(RT_DEBUG_TRACE, ("tssi_0_offset_g_band = %d\n", cap->tssi_0_offset_g_band)); + /* Read 54M target power */ + is_empty = RT28xx_EEPROM_READ16(pAd, TX0_G_BAND_TARGET_PWR, value); + + cap->tx_0_target_pwr_g_band = + (is_empty) ? TX_TARGET_PWR_DEFAULT_VALUE : (value & TX0_G_BAND_TARGET_PWR_MASK); + + DBGPRINT(RT_DEBUG_TRACE, ("tssi_0_target_pwr_g_band = %d\n", cap->tx_0_target_pwr_g_band)); + + /* Read power offset (channel delta) */ + if (is_empty) { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = 0x0; + } else { + /* tx power offset LOW */ + if (value & TX0_G_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & TX0_G_BAND_CHL_PWR_DELTA_LOW_SIGN) { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = ((value & TX0_G_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } else { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = -((value & TX0_G_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } + } else { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = 0x0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = %d\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW])); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX0_G_BAND_CHL_PWR_DELTA_MID, value); + + if (is_empty) { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID] = 0x0; + cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI] = 0x0; + } else { + /* tx power offset MID */ + if (value & TX0_G_BAND_CHL_PWR_DELTA_MID_EN) { + if (value & TX0_G_BAND_CHL_PWR_DELTA_MID_SIGN) + cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID] = (value & TX0_G_BAND_CHL_PWR_DELTA_MID_MASK); + else + cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID] = -(value & TX0_G_BAND_CHL_PWR_DELTA_MID_MASK); + } else { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID] = 0x0; + } + /* tx power offset HIGH */ + if (value & TX0_G_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & TX0_G_BAND_CHL_PWR_DELTA_HI_SIGN) + cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI] = ((value & TX0_G_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + else + cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI] = -((value & TX0_G_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + } else { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI] = 0x0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_0_chl_pwr_delta_g_band[G_BAND_MID] = %d\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID])); + DBGPRINT(RT_DEBUG_TRACE, ("tx_0_chl_pwr_delta_g_band[G_BAND_HI] = %d\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI])); + + /////////////////// Tx1 ////////////////////////// + /* Read TSSI slope/offset for TSSI compensation */ + is_empty = RT28xx_EEPROM_READ16(pAd, TX1_G_BAND_TSSI_SLOPE, value); + + cap->tssi_1_slope_g_band = (is_empty) ? TSSI_1_SLOPE_G_BAND_DEFAULT_VALUE : (value & TX1_G_BAND_TSSI_SLOPE_MASK); + + cap->tssi_1_offset_g_band = (is_empty) ? TSSI_1_OFFSET_G_BAND_DEFAULT_VALUE : ((value & TX1_G_BAND_TSSI_OFFSET_MASK) >> 8); + + DBGPRINT(RT_DEBUG_TRACE, ("tssi_1_slope_g_band = %d\n", cap->tssi_1_slope_g_band)); + DBGPRINT(RT_DEBUG_TRACE, ("tssi_1_offset_g_band = %d\n", cap->tssi_1_offset_g_band)); + + /* Read 54M target power */ + is_empty = RT28xx_EEPROM_READ16(pAd, TX1_G_BAND_TARGET_PWR, value); + + cap->tx_1_target_pwr_g_band = (is_empty) ? TX_TARGET_PWR_DEFAULT_VALUE : (value & TX1_G_BAND_TARGET_PWR_MASK); + + printk ("tssi_1_target_pwr_g_band = %d\n", cap->tx_1_target_pwr_g_band); + + /* Read power offset (channel delta) */ + if (is_empty) { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = 0; + } else { + /* tx power offset LOW */ + if (value & TX1_G_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & TX1_G_BAND_CHL_PWR_DELTA_LOW_SIGN) { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = ((value & TX1_G_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = -((value & TX1_G_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = 0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = %d\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW])); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX1_G_BAND_CHL_PWR_DELTA_MID, value); + if (is_empty) { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID] = 0; + cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI] = 0; + } else { + /* tx power offset MID */ + if (value & TX1_G_BAND_CHL_PWR_DELTA_MID_EN) { + if (value & TX1_G_BAND_CHL_PWR_DELTA_MID_SIGN) { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID] = (value & TX1_G_BAND_CHL_PWR_DELTA_MID_MASK); + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID] = -(value & TX1_G_BAND_CHL_PWR_DELTA_MID_MASK); + } + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID] = 0; + } + /* tx power offset HIGH */ + if (value & TX1_G_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & TX1_G_BAND_CHL_PWR_DELTA_HI_SIGN) { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI] = ((value & TX1_G_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI] = -((value & TX1_G_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + } + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI] = 0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_1_chl_pwr_delta_g_band[G_BAND_MID] = %d\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID])); + DBGPRINT(RT_DEBUG_TRACE, ("tx_1_chl_pwr_delta_g_band[G_BAND_HI] = %d\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI])); + + return ; +} + + +static VOID mt7628_show_pwr_info(RTMP_ADAPTER *pAd) +{ + struct MT_TX_PWR_CAP *cap = &pAd->chipCap.MTTxPwrCap; + UINT32 value; + + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("channel info related to power\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + + if (pAd->LatchRfRegs.Channel < 14) { + DBGPRINT(RT_DEBUG_OFF, ("central channel = %d, low_mid_hi = %d\n", pAd->LatchRfRegs.Channel, + get_low_mid_hi_index(pAd->LatchRfRegs.Channel))); + } + + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("channel power(unit: 0.5dbm)\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_target_pwr_g_band = 0x%x\n", cap->tx_0_target_pwr_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_target_pwr_g_band = 0x%x\n", cap->tx_1_target_pwr_g_band)); + + /* channel power delta */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("channel power delta(unit: 0.5db)\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = 0x%x\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_g_band[G_BAND_MID] = 0x%x\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_g_band[G_BAND_HI] = 0x%x\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = 0x%x\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_g_band[G_BAND_MID] = 0x%x\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_g_band[G_BAND_HI] = 0x%x\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI])); + + /* bw power delta */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("bw power delta(unit: 0.5db)\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("delta_tx_pwr_bw40_g_band = %d\n", cap->delta_tx_pwr_bw40_g_band)); + + /* per-rate power delta */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("per-rate power delta\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_cck_1_2 = %d\n", cap->tx_pwr_cck_1_2)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_cck_5_11 = %d\n", cap->tx_pwr_cck_5_11)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_6_9 = %d\n", cap->tx_pwr_g_band_ofdm_6_9)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_12_18 = %d\n", cap->tx_pwr_g_band_ofdm_12_18)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_24_36 = %d\n", cap->tx_pwr_g_band_ofdm_24_36)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_48 = %d\n", cap->tx_pwr_g_band_ofdm_48)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_54 = %d\n", cap->tx_pwr_g_band_ofdm_54)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_bpsk_mcs_32 = %d\n", cap->tx_pwr_ht_bpsk_mcs_32)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_bpsk_mcs_0_8 = %d\n", cap->tx_pwr_ht_bpsk_mcs_0_8)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_qpsk_mcs_1_2_9_10 = %d\n", cap->tx_pwr_ht_qpsk_mcs_1_2_9_10)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_16qam_mcs_3_4_11_12 = %d\n", cap->tx_pwr_ht_16qam_mcs_3_4_11_12)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_64qam_mcs_5_13 = %d\n", cap->tx_pwr_ht_64qam_mcs_5_13)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_64qam_mcs_6_14 = %d\n", cap->tx_pwr_ht_64qam_mcs_6_14)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_64qam_mcs_7_15 = %d\n", cap->tx_pwr_ht_64qam_mcs_7_15)); + + /* TMAC POWER INFO */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("per-rate power delta in MAC 0x60130020 ~ 0x60130030\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + RTMP_IO_READ32(pAd, TMAC_FP0R0, &value); + DBGPRINT(RT_DEBUG_OFF, ("TMAC_FP0R0 = 0x%x\n", value)); + RTMP_IO_READ32(pAd, TMAC_FP0R1, &value); + DBGPRINT(RT_DEBUG_OFF, ("TMAC_FP0R1 = 0x%x\n", value)); + RTMP_IO_READ32(pAd, TMAC_FP0R2, &value); + DBGPRINT(RT_DEBUG_OFF, ("TMAC_FP0R2 = 0x%x\n", value)); + RTMP_IO_READ32(pAd, TMAC_FP0R3, &value); + DBGPRINT(RT_DEBUG_OFF, ("TMAC_FP0R3 = 0x%x\n", value)); + RTMP_IO_READ32(pAd, TMAC_FP0R4, &value); + DBGPRINT(RT_DEBUG_OFF, ("TMAC_FP0R4 = 0x%x\n", value)); + + /* TSSI info */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("TSSI info\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("TSSI enable = %d\n", pAd->chipCap.tssi_enable)); + DBGPRINT(RT_DEBUG_OFF, ("tssi_0_slope_g_band = 0x%x\n", cap->tssi_0_slope_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("tssi_1_slope_g_band = 0x%x\n", cap->tssi_1_slope_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("tssi_0_offset_g_band = 0x%x\n", cap->tssi_0_offset_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("tssi_1_offset_g_band = 0x%x\n", cap->tssi_1_offset_g_band)); +} + + +static void mt7628_antenna_default_reset( + struct _RTMP_ADAPTER *pAd, + EEPROM_ANTENNA_STRUC *pAntenna) +{ + pAntenna->word = 0; + pAd->RfIcType = RFIC_7628; + pAntenna->field.TxPath = 2; + pAntenna->field.RxPath = 2; +} + +static const RTMP_CHIP_CAP MT7628_ChipCap = { + .max_nss = 2, + .TXWISize = sizeof(TMAC_TXD_L), /* 32 */ + .RXWISize = 28, +#ifdef RTMP_MAC_PCI + .WPDMABurstSIZE = 3, +#endif + .SnrFormula = SNR_FORMULA4, + .FlgIsHwWapiSup = TRUE, + .FlgIsHwAntennaDiversitySup = FALSE, +#ifdef STREAM_MODE_SUPPORT + .FlgHwStreamMode = FALSE, +#endif +#ifdef FIFO_EXT_SUPPORT + .FlgHwFifoExtCap = FALSE, +#endif + .asic_caps = (fASIC_CAP_PMF_ENC | fASIC_CAP_MCS_LUT), + .phy_caps = (fPHY_CAP_24G | fPHY_CAP_HT), + .MaxNumOfRfId = MAX_RF_ID, + .pRFRegTable = NULL, + .MaxNumOfBbpId = 200, + .pBBPRegTable = NULL, + .bbpRegTbSize = 0, +#ifdef NEW_MBSSID_MODE +#ifdef ENHANCE_NEW_MBSSID_MODE + .MBSSIDMode = MBSSID_MODE4, +#else + .MBSSIDMode = MBSSID_MODE1, +#endif /* ENHANCE_NEW_MBSSID_MODE */ +#else + .MBSSIDMode = MBSSID_MODE0, +#endif /* NEW_MBSSID_MODE */ +#ifdef RTMP_EFUSE_SUPPORT + .EFUSE_USAGE_MAP_START = 0x1e0, + .EFUSE_USAGE_MAP_END = 0x1fc, + .EFUSE_USAGE_MAP_SIZE = 29, + .EFUSE_RESERVED_SIZE = 22, // Cal-Free is 22 free block +#endif + .EEPROM_DEFAULT_BIN = MT7628_E2PImage, + .EEPROM_DEFAULT_BIN_SIZE = sizeof(MT7628_E2PImage), +#ifdef CONFIG_ANDES_SUPPORT + .CmdRspRxRing = RX_RING1, + .need_load_fw = TRUE, +// .DownLoadType = DownLoadTypeA, +#endif + .MCUType = ANDES, + .cmd_header_len = 12, +#ifdef RTMP_PCI_SUPPORT + .cmd_padding_len = 0, +#endif + .fw_header_image = MT7628_FirmwareImage, + .fw_bin_file_name = "mtk/MT7628.bin", + .fw_len = sizeof(MT7628_FirmwareImage), +#ifdef CARRIER_DETECTION_SUPPORT + .carrier_func = TONE_RADAR_V2, +#endif +#ifdef CONFIG_WIFI_TEST + .MemMapStart = 0x0000, + .MemMapEnd = 0xffff, + .MacMemMapOffset = 0x1000, + .MacStart = 0x0000, + .MacEnd = 0x0600, + .BBPMemMapOffset = 0x2000, + .BBPStart = 0x0000, + .BBPEnd = 0x0f00, + .RFIndexNum = 0, + .RFIndexOffset = 0, + .E2PStart = 0x0000, + .E2PEnd = 0x00fe, +#endif /* CONFIG_WIFI_TEST */ + .hif_type = HIF_MT, + .rf_type = RF_MT, + .RxBAWinSize = 21, + .AMPDUFactor = 2, +}; + + +static const RTMP_CHIP_OP MT7628_ChipOp = { + .ChipBBPAdjust = mt7628_bbp_adjust, + .ChipSwitchChannel = mt7628_switch_channel, + .AsicMacInit = mt7628_init_mac_cr, + .AsicBbpInit = MT7628BBPInit, + .AsicRfInit = mt7628_init_rf_cr, + .AsicAntennaDefaultReset = mt7628_antenna_default_reset, + .ChipAGCInit = NULL, + .AsicRfTurnOn = NULL, + .AsicHaltAction = NULL, + .AsicRfTurnOff = NULL, + .AsicReverseRfFromSleepMode = NULL, +#ifdef CARRIER_DETECTION_SUPPORT + .ToneRadarProgram = ToneRadarProgram_v2, +#endif + .RxSensitivityTuning = NULL, + .DisableTxRx = NULL, + +#ifdef RTMP_PCI_SUPPORT + //.AsicRadioOn = RT28xxPciAsicRadioOn, + //.AsicRadioOff = RT28xxPciAsicRadioOff, +#endif + .show_pwr_info = mt7628_show_pwr_info, +}; + + +VOID mt7628_init(RTMP_ADAPTER *pAd) +{ + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + + DBGPRINT(RT_DEBUG_OFF, ("%s()-->\n", __FUNCTION__)); + + memcpy(&pAd->chipCap, &MT7628_ChipCap, sizeof(RTMP_CHIP_CAP)); + memcpy(&pAd->chipOps, &MT7628_ChipOp, sizeof(RTMP_CHIP_OP)); + + pAd->chipCap.hif_type = HIF_MT; + pAd->chipCap.mac_type = MAC_MT; + + mt_phy_probe(pAd); + + pChipCap->tx_hw_hdr_len = pChipCap->TXWISize; + pChipCap->rx_hw_hdr_len = pChipCap->RXWISize; + + + + + RTMP_DRS_ALG_INIT(pAd, RATE_ALG_GRP); + + /* + Following function configure beacon related parameters + in pChipCap + FlgIsSupSpecBcnBuf / BcnMaxHwNum / + WcidHwRsvNum / BcnMaxHwSize / BcnBase[] + */ + mt_bcn_buf_init(pAd); + +#ifdef DOT11W_PMF_SUPPORT + pChipCap->FlgPMFEncrtptMode = PMF_ENCRYPT_MODE_2; +#endif /* DOT11W_PMF_SUPPORT */ + + DBGPRINT(RT_DEBUG_OFF, ("<--%s()\n", __FUNCTION__)); +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/mt7636.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/mt7636.c new file mode 100644 index 000000000..0cadb8ba3 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/mt7636.c @@ -0,0 +1,1036 @@ +/* + *************************************************************************** + * 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: + mt7636.c +*/ + +#include "rt_config.h" +#include "mcu/mt7636_rom_patch.h" +#include "mcu/mt7636_firmware.h" +#include "phy/wf_phy_back.h" + +static VOID mt7636_bbp_adjust(RTMP_ADAPTER *pAd) +{ + static char *ext_str[]={"extNone", "extAbove", "", "extBelow"}; + UCHAR rf_bw, ext_ch; + + DBGPRINT(RT_DEBUG_ERROR, ("%s() todo \n", __FUNCTION__)); + return; + +#ifdef DOT11_N_SUPPORT + if (get_ht_cent_ch(pAd, &rf_bw, &ext_ch) == FALSE) +#endif /* DOT11_N_SUPPORT */ + { + rf_bw = BW_20; + ext_ch = EXTCHA_NONE; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + } + + bbp_set_bw(pAd, rf_bw); + +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("%s() : %s, ChannelWidth=%d, Channel=%d, ExtChanOffset=%d(%d) \n", + __FUNCTION__, ext_str[ext_ch], + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth, + pAd->CommonCfg.Channel, + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA, + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset)); +#endif /* DOT11_N_SUPPORT */ +} + +static void mt7636_tx_pwr_gain(RTMP_ADAPTER *pAd, UINT8 channel) +{ + UINT32 value; + CHAR tx_0_pwr; + struct MT_TX_PWR_CAP *cap = &pAd->chipCap.MTTxPwrCap; + + DBGPRINT(RT_DEBUG_ERROR, ("%s() todo \n", __FUNCTION__)); + return ; + + cap->tx_0_target_pwr_g_band = TX_TARGET_PWR_DEFAULT_VALUE; + cap->tx_0_chl_pwr_delta_g_band[get_low_mid_hi_index(channel)] = 0; + cap->tx_pwr_g_band_ofdm_6_9 = 0; + cap->tx_pwr_g_band_ofdm_12_18 = 0; + cap->tx_pwr_g_band_ofdm_24_36 = 0; + cap->tx_pwr_g_band_ofdm_48 = 0; + cap->tx_pwr_g_band_ofdm_54 = 0; + cap->tx_pwr_ht_bpsk_mcs_32 = 0; + cap->tx_pwr_ht_bpsk_mcs_0_8 = 0; + cap->tx_pwr_ht_qpsk_mcs_1_2_9_10 = 0; + cap->tx_pwr_ht_16qam_mcs_3_4_11_12 = 0; + cap->tx_pwr_ht_64qam_mcs_5_13 = 0; + cap->tx_pwr_ht_64qam_mcs_6_14 = 0; + cap->tx_pwr_ht_64qam_mcs_7_15 = 0; + cap->tx_pwr_cck_1_2 = 0; + cap->tx_pwr_cck_5_11 = 0; + cap->delta_tx_pwr_bw40_g_band = 0; + + tx_0_pwr = cap->tx_0_target_pwr_g_band; + tx_0_pwr += cap->tx_0_chl_pwr_delta_g_band[get_low_mid_hi_index(channel)]; + + RTMP_IO_READ32(pAd, TMAC_FP0R0, &value); + + value &= ~LG_OFDM0_FRAME_POWER0_DBM_MASK; + value |= LG_OFDM0_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_g_band_ofdm_6_9); + + value &= ~LG_OFDM1_FRAME_POWER0_DBM_MASK; + value |= LG_OFDM1_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_g_band_ofdm_12_18); + + value &= ~LG_OFDM2_FRAME_POWER0_DBM_MASK; + value |= LG_OFDM2_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_g_band_ofdm_24_36); + + value &= ~LG_OFDM3_FRAME_POWER0_DBM_MASK; + value |= LG_OFDM3_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_g_band_ofdm_48); + + RTMP_IO_WRITE32(pAd, TMAC_FP0R0, value); + + RTMP_IO_READ32(pAd, TMAC_FP0R1, &value); + + value &= ~HT20_0_FRAME_POWER0_DBM_MASK; + value |= HT20_0_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_bpsk_mcs_0_8); + + value &= ~HT20_1_FRAME_POWER0_DBM_MASK; + value |= HT20_1_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_qpsk_mcs_1_2_9_10); + + value &= ~HT20_2_FRAME_POWER0_DBM_MASK; + value |= HT20_2_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_16qam_mcs_3_4_11_12); + + value &= ~HT20_3_FRAME_POWER0_DBM_MASK; + value |= HT20_3_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_64qam_mcs_5_13); + + RTMP_IO_WRITE32(pAd, TMAC_FP0R1, value); + + RTMP_IO_READ32(pAd, TMAC_FP0R2, &value); + + value &= ~HT40_0_FRAME_POWER0_DBM_MASK; + value |= HT40_0_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_bpsk_mcs_0_8 + + cap->delta_tx_pwr_bw40_g_band); + + value &= ~HT40_1_FRAME_POWER0_DBM_MASK; + value |= HT40_1_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_qpsk_mcs_1_2_9_10 + + cap->delta_tx_pwr_bw40_g_band); + + value &= ~HT40_2_FRAME_POWER0_DBM_MASK; + value |= HT40_2_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_16qam_mcs_3_4_11_12 + + cap->delta_tx_pwr_bw40_g_band); + + value &= ~HT40_3_FRAME_POWER0_DBM_MASK; + value |= HT40_3_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_64qam_mcs_5_13 + + cap->delta_tx_pwr_bw40_g_band); + + RTMP_IO_WRITE32(pAd, TMAC_FP0R2, value); + + RTMP_IO_READ32(pAd, TMAC_FP0R3, &value); + + value &= ~CCK0_FRAME_POWER0_DBM_MASK; + value |= CCK0_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_cck_1_2); + + value &= ~LG_OFDM4_FRAME_POWER0_DBM_MASK; + value |= LG_OFDM4_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_g_band_ofdm_54); + + value &= ~CCK1_FRAME_POWER0_DBM_MASK; + value |= CCK1_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_cck_5_11); + + value &= ~HT40_6_FRAME_POWER0_DBM_MASK; + value |= HT40_6_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_bpsk_mcs_32 + cap->delta_tx_pwr_bw40_g_band); + + RTMP_IO_WRITE32(pAd, TMAC_FP0R3, value); + + RTMP_IO_READ32(pAd, TMAC_FP0R4, &value); + + value &= ~HT20_4_FRAME_POWER0_DBM_MASK; + value |= HT20_4_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_64qam_mcs_6_14); + + value &= ~HT20_5_FRAME_POWER0_DBM_MASK; + value |= HT20_5_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_64qam_mcs_7_15); + + value &= ~HT40_4_FRAME_POWER0_DBM_MASK; + value |= HT40_4_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_64qam_mcs_6_14 + + cap->delta_tx_pwr_bw40_g_band); + + value &= ~HT40_5_FRAME_POWER0_DBM_MASK; + value |= HT40_5_FRAME_POWER0_DBM(tx_0_pwr + cap->tx_pwr_ht_64qam_mcs_7_15 + + cap->delta_tx_pwr_bw40_g_band); + + RTMP_IO_WRITE32(pAd, TMAC_FP0R4, value); +} + + +static void mt7636_switch_channel(RTMP_ADAPTER *pAd, UCHAR channel, BOOLEAN scan) +{ + DBGPRINT(RT_DEBUG_ERROR, ("%s() todo \n", __FUNCTION__)); + return; + +} + + +static char *dma_sch_str[]={ + "LMAC", + "ByPass", + "HyBrid", + }; + + +/* + Init TxD short format template which will copy by PSE-Client to LMAC +*/ +static INT asic_set_tmac_info_template(RTMP_ADAPTER *pAd) +{ + UINT32 dw[5]; + TMAC_TXD_2 *dw2 = (TMAC_TXD_2 *)(&dw[0]); + TMAC_TXD_3 *dw3 = (TMAC_TXD_3 *)(&dw[1]); + TMAC_TXD_4 *dw4 = (TMAC_TXD_4 *)(&dw[2]); + TMAC_TXD_5 *dw5 = (TMAC_TXD_5 *)(&dw[3]); + TMAC_TXD_6 *dw6 = (TMAC_TXD_6 *)(&dw[4]); + + NdisZeroMemory((UCHAR *)(&dw[0]), sizeof(dw)); + + dw2->htc_vld = 0; + dw2->frag = 0; + dw2->max_tx_time = 0; + dw2->fix_rate = 0; + + dw3->remain_tx_cnt = 0xf; + dw3->sn_vld = 0; + dw3->pn_vld = 0; + + dw5->pid = PID_DATA_AMPDU; + dw5->tx_status_fmt = 0; + dw5->tx_status_2_host = 1; + dw5->bar_sn_ctrl = 0; //HW + dw5->pwr_mgmt = TMI_PM_BIT_CFG_BY_HW; // HW + +#ifdef RTMP_PCI_SUPPORT +// TODO: shaing, for MT7628, may need to change this as RTMP_MAC_PCI + + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, 0x80080000); + + + /* For short format */ + RTMP_IO_WRITE32(pAd, 0xc0040, dw[0]); + RTMP_IO_WRITE32(pAd, 0xc0044, dw[1]); + RTMP_IO_WRITE32(pAd, 0xc0048, dw[2]); + RTMP_IO_WRITE32(pAd, 0xc004c, dw[3]); + RTMP_IO_WRITE32(pAd, 0xc0050, dw[4]); + + +// TODO: shaing, for MT7628, may need to change this as RTMP_MAC_PCI + // After change the Tx Padding CR of PCI-E Client, we need to re-map for PSE region + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, MT_PSE_BASE_ADDR); + +#endif /* RTMP_PCI_SUPPORT */ + + + return TRUE; +} + + +static INT mt7636_init_mac_cr(RTMP_ADAPTER *pAd) +{ + UINT32 mac_val; + + DBGPRINT(RT_DEBUG_OFF, ("%s()-->\n", __FUNCTION__)); + + DBGPRINT(RT_DEBUG_OFF, ("%s(): DMA Scheduler Mode=%d(%s)\n", + __FUNCTION__, pAd->fpga_ctl.dma_mode, + dma_sch_str[pAd->fpga_ctl.dma_mode])); + + /* Preparation of TxD DW2~DW6 when we need run 3DW format */ + asic_set_tmac_info_template(pAd); + + /* A-MPDU Agg limit control in range 1/2/4/8/10/12/14/16 */ + RTMP_IO_READ32(pAd, AGG_AWSCR, &mac_val); + mac_val = ((1 << 0) |(2<<8) | (4 << 16) | (8 << 24)); + RTMP_IO_WRITE32(pAd, AGG_AWSCR, mac_val); + + RTMP_IO_READ32(pAd, AGG_AWSCR1, &mac_val); + //mac_val = ((10 << 0) |(12<<8) | (14 << 16) | (16 << 24)); + mac_val &= 0x0; + mac_val = ((10 << 0) |(12<<8) | (14 << 16) | (0 << 24)); + RTMP_IO_WRITE32(pAd, AGG_AWSCR1, mac_val); + + RTMP_IO_WRITE32(pAd, AGG_AALCR, 0); + RTMP_IO_WRITE32(pAd, AGG_AALCR1, 0); + + /* Vector report queue setting */ + RTMP_IO_READ32(pAd, DMA_VCFR0, &mac_val); + mac_val |= BIT13; + RTMP_IO_WRITE32(pAd, DMA_VCFR0, mac_val); + + /* TxStatus report queue setting */ + RTMP_IO_READ32(pAd, DMA_TCFR1, &mac_val); + mac_val |= BIT14; + RTMP_IO_WRITE32(pAd, DMA_TCFR1, mac_val); + + /* Configure all rx packets to HIF, except WOL2M packet */ + RTMP_IO_READ32(pAd, DMA_RCFR0, &mac_val); + mac_val = 0x00010000; // drop duplicate + // TODO: shiang-MT7603, remove me after FPGA verification done + mac_val |= 0x00200000; // receive BA/CF_End/Ack/RTS/CTS/CTRL_RSVED + RTMP_IO_WRITE32(pAd, DMA_RCFR0, mac_val); + + /* Configure Rx Vectors report to HIF */ + RTMP_IO_READ32(pAd, DMA_VCFR0, &mac_val); + mac_val &= (~0x1); // To HIF + mac_val |= 0x2000; // RxRing 1 + RTMP_IO_WRITE32(pAd, DMA_VCFR0, mac_val); + + /* AMPDU BAR setting */ + /* Disable BAR tx of HW */ + RTMP_IO_READ32(pAd, AGG_MRCR, &mac_val); + //mac_val &= (~0xf00); + mac_val |= (1 << 11); + RTMP_IO_WRITE32(pAd, AGG_MRCR, mac_val); + + /* Configure the BAR rate setting */ + RTMP_IO_READ32(pAd, AGG_ACR, &mac_val); + mac_val &= (~0xfff00000); + RTMP_IO_WRITE32(pAd, AGG_ACR, mac_val); + + /* AMPDU Statistics Range Control setting + 0 < agg_cnt - 1 <= range_cr(0), => 1 + range_cr(0) < agg_cnt - 1 <= range_cr(4), => 2~5 + range_cr(4) < agg_cnt - 1 <= range_cr(14), => 6~15 + range_cr(14) < agg_cnt - 1, => 16~ + */ + RTMP_IO_READ32(pAd, AGG_ASRCR, &mac_val); + mac_val = (0 << 0) | (4 << 8) | (14 << 16); + RTMP_IO_WRITE32(pAd, AGG_ASRCR, mac_val); + + // Enable MIB counters + RTMP_IO_WRITE32(pAd, MIB_MSCR, 0x7fffffff); + RTMP_IO_WRITE32(pAd, MIB_MPBSCR, 0xffffffff); + + + /* CCA Workaround */ + RTMP_IO_READ32(pAd, TMAC_TRCR, &mac_val); + mac_val &= ~CCA_SRC_SEL_MASK; + mac_val |= CCA_SRC_SEL(0x3); + mac_val &= ~CCA_SEC_SRC_SEL_MASK; + mac_val |= CCA_SEC_SRC_SEL(0x3); + RTMP_IO_WRITE32(pAd, TMAC_TRCR, mac_val); + + RTMP_IO_READ32(pAd, WTBL_OFF_RMVTCR, &mac_val); + /* RCPI include ACK and Data */ + mac_val |= RX_MV_MODE; + RTMP_IO_WRITE32(pAd, WTBL_OFF_RMVTCR, mac_val); + +#ifdef MT7603_FPGA + // enable MAC2MAC mode + RTMP_IO_READ32(pAd, RMAC_MISC, &mac_val); + mac_val |= BIT18; + RTMP_IO_WRITE32(pAd, RMAC_MISC, mac_val); +#endif /* MT7603_FPGA */ +} + + +static VOID MT7636BBPInit(RTMP_ADAPTER *pAd) +{ + UINT32 Value; + + DBGPRINT(RT_DEBUG_ERROR, ("%s() todo \n", __FUNCTION__)); + return; + + RTMP_IO_READ32(pAd, 0x106c8, &Value); + Value &= ~(1 << 30); + RTMP_IO_WRITE32(pAd, 0x106c8, Value); + + RTMP_IO_READ32(pAd, 0x106cc, &Value); + Value &= ~(1 << 0); + RTMP_IO_WRITE32(pAd, 0x106cc, Value); +} + +static void mt7636_init_rf_cr(RTMP_ADAPTER *ad) +{ + return; +} + +static UINT8 mt7603_txpwr_chlist[] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +}; + + +int mt7636_read_chl_pwr(RTMP_ADAPTER *pAd) +{ + UINT32 i, choffset; + struct MT_TX_PWR_CAP *cap = &pAd->chipCap.MTTxPwrCap; + + DBGPRINT(RT_DEBUG_ERROR, ("%s() todo \n", __FUNCTION__)); + return; + + mt7636_get_tx_pwr_info(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("%s()--->\n", __FUNCTION__)); + + for (i = 0; i < sizeof(mt7603_txpwr_chlist); i++) { + pAd->TxPower[i].Channel = mt7603_txpwr_chlist[i]; + pAd->TxPower[i].Power = TX_TARGET_PWR_DEFAULT_VALUE; + pAd->TxPower[i].Power2 = TX_TARGET_PWR_DEFAULT_VALUE; + } + + for (i = 0; i < 14; i++) { + pAd->TxPower[i].Power = cap->tx_0_target_pwr_g_band; + pAd->TxPower[i].Power2 = cap->tx_1_target_pwr_g_band; + } + + choffset = 14; + + /* 4. Print and Debug*/ + for (i = 0; i < choffset; i++) + { + DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: TxPower[%03d], Channel=%d, Power[Tx0:%d, Tx1:%d]\n", + i, pAd->TxPower[i].Channel, pAd->TxPower[i].Power, pAd->TxPower[i].Power2 )); + } + + return TRUE; +} + + +/* Read power per rate */ +void mt7636_get_tx_pwr_per_rate(RTMP_ADAPTER *pAd) +{ + BOOLEAN is_empty = 0; + u16 value = 0; + struct MT_TX_PWR_CAP *cap = &pAd->chipCap.MTTxPwrCap; + + DBGPRINT(RT_DEBUG_ERROR, ("%s() todo \n", __FUNCTION__)); + return; + + /* G Band tx power for CCK 1M/2M, 5.5M/11M */ + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_CCK_1_2M, value); + if (is_empty) { + cap->tx_pwr_cck_1_2 = 0; + cap->tx_pwr_cck_5_11 = 0; + } else { + /* CCK 1M/2M */ + if (value & TX_PWR_CCK_1_2M_EN) { + if (value & TX_PWR_CCK_1_2M_SIGN) { + cap->tx_pwr_cck_1_2 = (value & TX_PWR_CCK_1_2M_MASK); + } else { + cap->tx_pwr_cck_1_2 = -(value & TX_PWR_CCK_1_2M_MASK); + } + } else { + cap->tx_pwr_cck_1_2 = 0; + } + + /* CCK 5.5M/11M */ + if (value & TX_PWR_CCK_5_11M_EN) { + if (value & TX_PWR_CCK_5_11M_SIGN) { + cap->tx_pwr_cck_5_11 = ((value & TX_PWR_CCK_5_11M_MASK) >> 8); + } else { + cap->tx_pwr_cck_5_11 = -((value & TX_PWR_CCK_5_11M_MASK) >> 8); + } + } else { + cap->tx_pwr_cck_5_11 = 0; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_cck_1_2 = %d\n", cap->tx_pwr_cck_1_2)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_cck_5_11 = %d\n", cap->tx_pwr_cck_5_11)); + + /* G Band tx power for OFDM 6M/9M, 12M/18M, 24M/36M, 48M/54M */ + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_G_BAND_OFDM_6_9M, value); + if (is_empty) { + cap->tx_pwr_g_band_ofdm_6_9 = 0; + cap->tx_pwr_g_band_ofdm_12_18 = 0; + } else { + /* OFDM 6M/9M */ + if (value & TX_PWR_G_BAND_OFDM_6_9M_EN) { + if (value & TX_PWR_G_BAND_OFDM_6_9M_SIGN) { + cap->tx_pwr_g_band_ofdm_6_9 = (value & TX_PWR_G_BAND_OFDM_6_9M_MASK); + } else { + cap->tx_pwr_g_band_ofdm_6_9 = -(value & TX_PWR_G_BAND_OFDM_6_9M_MASK); + } + } else { + cap->tx_pwr_g_band_ofdm_6_9 = 0; + } + + /* OFDM 12M/18M */ + if (value & TX_PWR_G_BAND_OFDM_12_18M_EN) { + if (value & TX_PWR_G_BAND_OFDM_12_18M_SIGN) { + cap->tx_pwr_g_band_ofdm_12_18 = ((value & TX_PWR_G_BAND_OFDM_12_18M_MASK) >> 8); + } else { + cap->tx_pwr_g_band_ofdm_12_18 = -((value & TX_PWR_G_BAND_OFDM_12_18M_MASK) >> 8); + } + } else { + cap->tx_pwr_g_band_ofdm_12_18 = 0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_g_band_ofdm_6_9 = %d\n", cap->tx_pwr_g_band_ofdm_6_9)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_g_band_ofdm_12_18 = %d\n", cap->tx_pwr_g_band_ofdm_12_18)); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_G_BAND_OFDM_24_36M, value); + if (is_empty) { + cap->tx_pwr_g_band_ofdm_24_36 = 0; + cap->tx_pwr_g_band_ofdm_48= 0; + } else { + /* OFDM 24M/36M */ + if (value & TX_PWR_G_BAND_OFDM_24_36M_EN) { + if (value & TX_PWR_G_BAND_OFDM_24_36M_SIGN) { + cap->tx_pwr_g_band_ofdm_24_36 = (value & TX_PWR_G_BAND_OFDM_24_36M_MASK); + } else { + cap->tx_pwr_g_band_ofdm_24_36 = -(value & TX_PWR_G_BAND_OFDM_24_36M_MASK); + } + } else { + cap->tx_pwr_g_band_ofdm_24_36 = 0; + } + + /* OFDM 48M */ + if (value & TX_PWR_G_BAND_OFDM_48M_EN) { + if (value & TX_PWR_G_BAND_OFDM_48M_SIGN) { + cap->tx_pwr_g_band_ofdm_48 = ((value & TX_PWR_G_BAND_OFDM_48M_MASK) >> 8); + } else { + cap->tx_pwr_g_band_ofdm_48 = -((value & TX_PWR_G_BAND_OFDM_48M_MASK) >> 8); + } + } else { + cap->tx_pwr_g_band_ofdm_48 = 0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_g_band_ofdm_24_36 = %d\n", cap->tx_pwr_g_band_ofdm_24_36)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_g_band_ofdm_48 = %d\n", cap->tx_pwr_g_band_ofdm_48)); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_G_BAND_OFDM_54M, value); + if (is_empty) { + cap->tx_pwr_g_band_ofdm_54 = 0; + cap->tx_pwr_ht_bpsk_mcs_0_8 = 0; + } else { + /* OFDM 54M */ + if (value & TX_PWR_G_BAND_OFDM_54M_EN) { + if (value & TX_PWR_G_BAND_OFDM_54M_SIGN) { + cap->tx_pwr_g_band_ofdm_54 = (value & TX_PWR_G_BAND_OFDM_54M_MASK); + } else { + cap->tx_pwr_g_band_ofdm_54 = -(value & TX_PWR_G_BAND_OFDM_54M_MASK); + } + } else { + cap->tx_pwr_g_band_ofdm_54 = 0; + } + + /* HT MCS_0, MCS_8 */ + if (value & TX_PWR_HT_BPSK_MCS_0_8_EN) { + if (value & TX_PWR_HT_BPSK_MCS_0_8_SIGN) { + cap->tx_pwr_ht_bpsk_mcs_0_8 = ((value & TX_PWR_HT_BPSK_MCS_0_8_MASK) >> 8); + } else { + cap->tx_pwr_ht_bpsk_mcs_0_8 = -((value & TX_PWR_HT_BPSK_MCS_0_8_MASK) >> 8); + } + } else { + cap->tx_pwr_ht_bpsk_mcs_0_8 = 0; + } } + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_g_band_ofdm_54 = %d\n", cap->tx_pwr_g_band_ofdm_54)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_bpsk_mcs_0_8 = %d\n", cap->tx_pwr_ht_bpsk_mcs_0_8)); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_HT_BPSK_MCS_32, value); + if (is_empty) { + cap->tx_pwr_ht_bpsk_mcs_32 = 0; + cap->tx_pwr_ht_qpsk_mcs_1_2_9_10 = 0; + } else { + /* HT MCS_0, MCS_8 */ + if (value & TX_PWR_HT_BPSK_MCS_32_EN) { + if (value & TX_PWR_HT_BPSK_MCS_32_SIGN) { + cap->tx_pwr_ht_bpsk_mcs_32 = (value & TX_PWR_HT_BPSK_MCS_32_MASK); + } else { + cap->tx_pwr_ht_bpsk_mcs_32 = -(value & TX_PWR_HT_BPSK_MCS_32_MASK); + } + } else { + cap->tx_pwr_ht_bpsk_mcs_32 = 0; + } + + /* HT MCS_1, MCS_2, MCS_9, MCS_10 */ + if (value & TX_PWR_HT_QPSK_MCS_1_2_9_10_EN) { + if (value & TX_PWR_HT_QPSK_MCS_1_2_9_10_SIGN) { + cap->tx_pwr_ht_qpsk_mcs_1_2_9_10 = ((value & TX_PWR_HT_QPSK_MCS_1_2_9_10_MASK) >> 8); + } else { + cap->tx_pwr_ht_qpsk_mcs_1_2_9_10 = -((value & TX_PWR_HT_QPSK_MCS_1_2_9_10_MASK) >> 8); + } + } else { + cap->tx_pwr_ht_qpsk_mcs_1_2_9_10 = 0; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_bpsk_mcs_32 = %d\n", cap->tx_pwr_ht_bpsk_mcs_32)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_qpsk_mcs_1_2_9_10 = %d\n", cap->tx_pwr_ht_qpsk_mcs_1_2_9_10)); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_HT_16QAM_MCS_3_4_11_12, value); + if (is_empty) { + cap->tx_pwr_ht_16qam_mcs_3_4_11_12 = 0; + cap->tx_pwr_ht_64qam_mcs_5_13 = 0; + } else { + /* HT MCS_3, MCS_4, MCS_11, MCS_12 */ + if (value & TX_PWR_HT_16QAM_MCS_3_4_11_12_EN) { + if (value & TX_PWR_HT_16QAM_MCS_3_4_11_12_SIGN) { + cap->tx_pwr_ht_16qam_mcs_3_4_11_12 = (value & TX_PWR_HT_16QAM_MCS_3_4_11_12_MASK); + } else { + cap->tx_pwr_ht_16qam_mcs_3_4_11_12 = -(value & TX_PWR_HT_16QAM_MCS_3_4_11_12_MASK); + } + } else { + cap->tx_pwr_ht_16qam_mcs_3_4_11_12 = 0; + } + + /* HT MCS_5, MCS_13 */ + if (value & TX_PWR_HT_64QAM_MCS_5_13_EN) { + if (value & TX_PWR_HT_64QAM_MCS_5_13_SIGN) { + cap->tx_pwr_ht_64qam_mcs_5_13 = ((value & TX_PWR_HT_64QAM_MCS_5_13_MASK) >> 8); + } else { + cap->tx_pwr_ht_64qam_mcs_5_13 = -((value & TX_PWR_HT_64QAM_MCS_5_13_MASK) >> 8); + } + } else { + cap->tx_pwr_ht_64qam_mcs_5_13 = 0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_16qam_mcs_3_4_11_12 = %d\n", cap->tx_pwr_ht_16qam_mcs_3_4_11_12)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_64qam_mcs_5_13 = %d\n", cap->tx_pwr_ht_64qam_mcs_5_13)); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX_PWR_HT_64QAM_MCS_6_14, value); + if (is_empty) { + cap->tx_pwr_ht_64qam_mcs_6_14 = 0; + cap->tx_pwr_ht_64qam_mcs_7_15 = 0; + } else { + /* HT MCS_6, MCS_14 */ + if (value & TX_PWR_HT_64QAM_MCS_6_14_EN) { + if (value & TX_PWR_HT_64QAM_MCS_6_14_SIGN) { + cap->tx_pwr_ht_64qam_mcs_6_14 = (value & TX_PWR_HT_64QAM_MCS_6_14_MASK); + } else { + cap->tx_pwr_ht_64qam_mcs_6_14 = -(value & TX_PWR_HT_64QAM_MCS_6_14_MASK); + } + } else { + cap->tx_pwr_ht_64qam_mcs_6_14 = 0; + } + + /* HT MCS_7, MCS_15 */ + if (value & TX_PWR_HT_64QAM_MCS_7_15_EN) { + if (value & TX_PWR_HT_64QAM_MCS_7_15_SIGN) { + cap->tx_pwr_ht_64qam_mcs_7_15 = ((value & TX_PWR_HT_64QAM_MCS_7_15_MASK) >> 8); + } else { + cap->tx_pwr_ht_64qam_mcs_7_15 = -((value & TX_PWR_HT_64QAM_MCS_7_15_MASK) >> 8); + } + } else { + cap->tx_pwr_ht_64qam_mcs_7_15 = 0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_64qam_mcs_6_14 = %d\n", cap->tx_pwr_ht_64qam_mcs_6_14)); + DBGPRINT(RT_DEBUG_TRACE, ("tx_pwr_ht_64qam_mcs_7_15 = %d\n", cap->tx_pwr_ht_64qam_mcs_7_15)); + + return; +} + + +void mt7636_get_tx_pwr_info(RTMP_ADAPTER *pAd) +{ + bool is_empty = 0; + u16 value = 0; + struct MT_TX_PWR_CAP *cap = &pAd->chipCap.MTTxPwrCap; + + DBGPRINT(RT_DEBUG_ERROR, ("%s() todo \n", __FUNCTION__)); + return; + + /* Read 20/40 BW delta */ + is_empty = RT28xx_EEPROM_READ16(pAd, G_BAND_20_40_BW_PWR_DELTA, value); + + if (is_empty) { + cap->delta_tx_pwr_bw40_g_band = 0x0; + } else { + /* G Band */ + if (value & G_BAND_20_40_BW_PWR_DELTA_EN) { + if (value & G_BAND_20_40_BW_PWR_DELTA_SIGN) { + /* bit[0..5] tx power delta value */ + cap->delta_tx_pwr_bw40_g_band = (value & G_BAND_20_40_BW_PWR_DELTA_MASK); + } else { + cap->delta_tx_pwr_bw40_g_band = -(value & G_BAND_20_40_BW_PWR_DELTA_MASK); + } + } else { + cap->delta_tx_pwr_bw40_g_band = 0x0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("delta_tx_pwr_bw40_g_band = %d\n", cap->delta_tx_pwr_bw40_g_band)); + + /////////////////// Tx0 ////////////////////////// + /* Read TSSI slope/offset for TSSI compensation */ + is_empty = RT28xx_EEPROM_READ16(pAd, TX0_G_BAND_TSSI_SLOPE, value); + + cap->tssi_0_slope_g_band = + (is_empty) ? TSSI_0_SLOPE_G_BAND_DEFAULT_VALUE : (value & TX0_G_BAND_TSSI_SLOPE_MASK); + + cap->tssi_0_offset_g_band = + (is_empty) ? TSSI_0_OFFSET_G_BAND_DEFAULT_VALUE : ((value & TX0_G_BAND_TSSI_OFFSET_MASK) >> 8); + + DBGPRINT(RT_DEBUG_TRACE, ("tssi_0_slope_g_band = %d\n", cap->tssi_0_slope_g_band)); + DBGPRINT(RT_DEBUG_TRACE, ("tssi_0_offset_g_band = %d\n", cap->tssi_0_offset_g_band)); + /* Read 54M target power */ + is_empty = RT28xx_EEPROM_READ16(pAd, TX0_G_BAND_TARGET_PWR, value); + + cap->tx_0_target_pwr_g_band = + (is_empty) ? TX_TARGET_PWR_DEFAULT_VALUE : (value & TX0_G_BAND_TARGET_PWR_MASK); + + DBGPRINT(RT_DEBUG_TRACE, ("tssi_0_target_pwr_g_band = %d\n", cap->tx_0_target_pwr_g_band)); + + /* Read power offset (channel delta) */ + if (is_empty) { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = 0x0; + } else { + /* tx power offset LOW */ + if (value & TX0_G_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & TX0_G_BAND_CHL_PWR_DELTA_LOW_SIGN) { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = ((value & TX0_G_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } else { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = -((value & TX0_G_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } + } else { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = 0x0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = %d\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW])); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX0_G_BAND_CHL_PWR_DELTA_MID, value); + + if (is_empty) { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID] = 0x0; + cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI] = 0x0; + } else { + /* tx power offset MID */ + if (value & TX0_G_BAND_CHL_PWR_DELTA_MID_EN) { + if (value & TX0_G_BAND_CHL_PWR_DELTA_MID_SIGN) + cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID] = (value & TX0_G_BAND_CHL_PWR_DELTA_MID_MASK); + else + cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID] = -(value & TX0_G_BAND_CHL_PWR_DELTA_MID_MASK); + } else { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID] = 0x0; + } + /* tx power offset HIGH */ + if (value & TX0_G_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & TX0_G_BAND_CHL_PWR_DELTA_HI_SIGN) + cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI] = ((value & TX0_G_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + else + cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI] = -((value & TX0_G_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + } else { + cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI] = 0x0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_0_chl_pwr_delta_g_band[G_BAND_MID] = %d\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID])); + DBGPRINT(RT_DEBUG_TRACE, ("tx_0_chl_pwr_delta_g_band[G_BAND_HI] = %d\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI])); + + /////////////////// Tx1 ////////////////////////// + /* Read TSSI slope/offset for TSSI compensation */ + is_empty = RT28xx_EEPROM_READ16(pAd, TX1_G_BAND_TSSI_SLOPE, value); + + cap->tssi_1_slope_g_band = (is_empty) ? TSSI_1_SLOPE_G_BAND_DEFAULT_VALUE : (value & TX1_G_BAND_TSSI_SLOPE_MASK); + + cap->tssi_1_offset_g_band = (is_empty) ? TSSI_1_OFFSET_G_BAND_DEFAULT_VALUE : ((value & TX1_G_BAND_TSSI_OFFSET_MASK) >> 8); + + DBGPRINT(RT_DEBUG_TRACE, ("tssi_1_slope_g_band = %d\n", cap->tssi_1_slope_g_band)); + DBGPRINT(RT_DEBUG_TRACE, ("tssi_1_offset_g_band = %d\n", cap->tssi_1_offset_g_band)); + + /* Read 54M target power */ + is_empty = RT28xx_EEPROM_READ16(pAd, TX1_G_BAND_TARGET_PWR, value); + + cap->tx_1_target_pwr_g_band = (is_empty) ? TX_TARGET_PWR_DEFAULT_VALUE : (value & TX1_G_BAND_TARGET_PWR_MASK); + + printk ("tssi_1_target_pwr_g_band = %d\n", cap->tx_1_target_pwr_g_band); + + /* Read power offset (channel delta) */ + if (is_empty) { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = 0; + } else { + /* tx power offset LOW */ + if (value & TX1_G_BAND_CHL_PWR_DELTA_LOW_EN) { + if (value & TX1_G_BAND_CHL_PWR_DELTA_LOW_SIGN) { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = ((value & TX1_G_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = -((value & TX1_G_BAND_CHL_PWR_DELTA_LOW_MASK) >> 8); + } + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = 0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = %d\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW])); + + is_empty = RT28xx_EEPROM_READ16(pAd, TX1_G_BAND_CHL_PWR_DELTA_MID, value); + if (is_empty) { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID] = 0; + cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI] = 0; + } else { + /* tx power offset MID */ + if (value & TX1_G_BAND_CHL_PWR_DELTA_MID_EN) { + if (value & TX1_G_BAND_CHL_PWR_DELTA_MID_SIGN) { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID] = (value & TX1_G_BAND_CHL_PWR_DELTA_MID_MASK); + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID] = -(value & TX1_G_BAND_CHL_PWR_DELTA_MID_MASK); + } + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID] = 0; + } + /* tx power offset HIGH */ + if (value & TX1_G_BAND_CHL_PWR_DELTA_HI_EN) { + if (value & TX1_G_BAND_CHL_PWR_DELTA_HI_SIGN) { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI] = ((value & TX1_G_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI] = -((value & TX1_G_BAND_CHL_PWR_DELTA_HI_MASK) >> 8); + } + } else { + cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI] = 0; + } + } + DBGPRINT(RT_DEBUG_TRACE, ("tx_1_chl_pwr_delta_g_band[G_BAND_MID] = %d\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID])); + DBGPRINT(RT_DEBUG_TRACE, ("tx_1_chl_pwr_delta_g_band[G_BAND_HI] = %d\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI])); + + return ; +} + + +static VOID mt7636_show_pwr_info(RTMP_ADAPTER *pAd) +{ + struct MT_TX_PWR_CAP *cap = &pAd->chipCap.MTTxPwrCap; + UINT32 value; + + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("channel info related to power\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + + if (pAd->LatchRfRegs.Channel < 14) { + DBGPRINT(RT_DEBUG_OFF, ("central channel = %d, low_mid_hi = %d\n", pAd->LatchRfRegs.Channel, + get_low_mid_hi_index(pAd->LatchRfRegs.Channel))); + } + + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("channel power(unit: 0.5dbm)\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_target_pwr_g_band = 0x%x\n", cap->tx_0_target_pwr_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_target_pwr_g_band = 0x%x\n", cap->tx_1_target_pwr_g_band)); + + /* channel power delta */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("channel power delta(unit: 0.5db)\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_g_band[G_BAND_LOW] = 0x%x\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_g_band[G_BAND_MID] = 0x%x\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_MID])); + DBGPRINT(RT_DEBUG_OFF, ("tx_0_chl_pwr_delta_g_band[G_BAND_HI] = 0x%x\n", cap->tx_0_chl_pwr_delta_g_band[G_BAND_HI])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_g_band[G_BAND_LOW] = 0x%x\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_LOW])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_g_band[G_BAND_MID] = 0x%x\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_MID])); + DBGPRINT(RT_DEBUG_OFF, ("tx_1_chl_pwr_delta_g_band[G_BAND_HI] = 0x%x\n", cap->tx_1_chl_pwr_delta_g_band[G_BAND_HI])); + + /* bw power delta */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("bw power delta(unit: 0.5db)\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("delta_tx_pwr_bw40_g_band = %d\n", cap->delta_tx_pwr_bw40_g_band)); + + /* per-rate power delta */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("per-rate power delta\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_cck_1_2 = %d\n", cap->tx_pwr_cck_1_2)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_cck_5_11 = %d\n", cap->tx_pwr_cck_5_11)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_6_9 = %d\n", cap->tx_pwr_g_band_ofdm_6_9)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_12_18 = %d\n", cap->tx_pwr_g_band_ofdm_12_18)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_24_36 = %d\n", cap->tx_pwr_g_band_ofdm_24_36)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_48 = %d\n", cap->tx_pwr_g_band_ofdm_48)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_g_band_ofdm_54 = %d\n", cap->tx_pwr_g_band_ofdm_54)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_bpsk_mcs_32 = %d\n", cap->tx_pwr_ht_bpsk_mcs_32)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_bpsk_mcs_0_8 = %d\n", cap->tx_pwr_ht_bpsk_mcs_0_8)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_qpsk_mcs_1_2_9_10 = %d\n", cap->tx_pwr_ht_qpsk_mcs_1_2_9_10)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_16qam_mcs_3_4_11_12 = %d\n", cap->tx_pwr_ht_16qam_mcs_3_4_11_12)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_64qam_mcs_5_13 = %d\n", cap->tx_pwr_ht_64qam_mcs_5_13)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_64qam_mcs_6_14 = %d\n", cap->tx_pwr_ht_64qam_mcs_6_14)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pwr_ht_64qam_mcs_7_15 = %d\n", cap->tx_pwr_ht_64qam_mcs_7_15)); + + /* TMAC POWER INFO */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("per-rate power delta in MAC 0x60130020 ~ 0x60130030\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + RTMP_IO_READ32(pAd, TMAC_FP0R0, &value); + DBGPRINT(RT_DEBUG_OFF, ("TMAC_FP0R0 = 0x%x\n", value)); + RTMP_IO_READ32(pAd, TMAC_FP0R1, &value); + DBGPRINT(RT_DEBUG_OFF, ("TMAC_FP0R1 = 0x%x\n", value)); + RTMP_IO_READ32(pAd, TMAC_FP0R2, &value); + DBGPRINT(RT_DEBUG_OFF, ("TMAC_FP0R2 = 0x%x\n", value)); + RTMP_IO_READ32(pAd, TMAC_FP0R3, &value); + DBGPRINT(RT_DEBUG_OFF, ("TMAC_FP0R3 = 0x%x\n", value)); + RTMP_IO_READ32(pAd, TMAC_FP0R4, &value); + DBGPRINT(RT_DEBUG_OFF, ("TMAC_FP0R4 = 0x%x\n", value)); + + /* TSSI info */ + DBGPRINT(RT_DEBUG_OFF, ("\n===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("TSSI info\n")); + DBGPRINT(RT_DEBUG_OFF, ("===================================\n")); + DBGPRINT(RT_DEBUG_OFF, ("TSSI enable = %d\n", pAd->chipCap.tssi_enable)); + DBGPRINT(RT_DEBUG_OFF, ("tssi_0_slope_g_band = 0x%x\n", cap->tssi_0_slope_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("tssi_1_slope_g_band = 0x%x\n", cap->tssi_1_slope_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("tssi_0_offset_g_band = 0x%x\n", cap->tssi_0_offset_g_band)); + DBGPRINT(RT_DEBUG_OFF, ("tssi_1_offset_g_band = 0x%x\n", cap->tssi_1_offset_g_band)); +} + + +static void mt7636_antenna_default_reset( + struct _RTMP_ADAPTER *pAd, + EEPROM_ANTENNA_STRUC *pAntenna) +{ + DBGPRINT(RT_DEBUG_ERROR, ("%s() todo \n", __FUNCTION__)); + return; + + pAntenna->word = 0; + pAd->RfIcType = RFIC_7603; + pAntenna->field.TxPath = 2; + pAntenna->field.RxPath = 2; +} + + + + +static const RTMP_CHIP_CAP MT7636_ChipCap = { + .max_nss = 2, + .TXWISize = sizeof(TMAC_TXD_L), /* 32 */ + .RXWISize = 28, +#ifdef RTMP_MAC_PCI + .WPDMABurstSIZE = 3, +#endif + .SnrFormula = SNR_FORMULA4, + .FlgIsHwWapiSup = TRUE, + .FlgIsHwAntennaDiversitySup = FALSE, +#ifdef STREAM_MODE_SUPPORT + .FlgHwStreamMode = FALSE, +#endif +#ifdef FIFO_EXT_SUPPORT + .FlgHwFifoExtCap = FALSE, +#endif + .asic_caps = (fASIC_CAP_PMF_ENC | fASIC_CAP_MCS_LUT), + .phy_caps = (fPHY_CAP_24G | fPHY_CAP_HT), + .MaxNumOfRfId = MAX_RF_ID, + .pRFRegTable = NULL, + .MaxNumOfBbpId = 200, + .pBBPRegTable = NULL, + .bbpRegTbSize = 0, +#ifdef NEW_MBSSID_MODE +#ifdef ENHANCE_NEW_MBSSID_MODE + .MBSSIDMode = MBSSID_MODE4, +#else + .MBSSIDMode = MBSSID_MODE1, +#endif /* ENHANCE_NEW_MBSSID_MODE */ +#else + .MBSSIDMode = MBSSID_MODE0, +#endif /* NEW_MBSSID_MODE */ +#ifdef RTMP_EFUSE_SUPPORT + .EFUSE_USAGE_MAP_START = 0x1e0, + .EFUSE_USAGE_MAP_END = 0x1fc, + .EFUSE_USAGE_MAP_SIZE = 29, + .EFUSE_RESERVED_SIZE = 22, // Cal-Free is 22 free block +#endif + .EEPROM_DEFAULT_BIN = NULL, + .EEPROM_DEFAULT_BIN_SIZE = 0, +#ifdef CONFIG_ANDES_SUPPORT + .CmdRspRxRing = RX_RING1, + .need_load_fw = TRUE, + .DownLoadType = DownLoadTypeB, + .rom_patch_header_image = mt7636_rom_patch, + .rom_patch_len = sizeof(mt7636_rom_patch), + .load_code_method = HEADER_METHOD, + .need_load_rom_patch = TRUE, + .ram_code_protect = FALSE, + .rom_code_protect = TRUE, + .ilm_offset = 0x80000, + .dlm_offset = 0x110000, + .rom_patch_offset = 0x8C000, +#endif + .MCUType = ANDES, + .cmd_header_len = sizeof(FW_TXD), +#ifdef RTMP_PCI_SUPPORT + .cmd_padding_len = 0, +#endif + .fw_header_image = MT7636_FirmwareImage, + .fw_len = sizeof(MT7636_FirmwareImage), +#ifdef CARRIER_DETECTION_SUPPORT + .carrier_func = TONE_RADAR_V2, +#endif +#ifdef CONFIG_WIFI_TEST + .MemMapStart = 0x0000, + .MemMapEnd = 0xffff, + .MacMemMapOffset = 0x1000, + .MacStart = 0x0000, + .MacEnd = 0x0600, + .BBPMemMapOffset = 0x2000, + .BBPStart = 0x0000, + .BBPEnd = 0x0f00, + .RFIndexNum = 0, + .RFIndexOffset = 0, + .E2PStart = 0x0000, + .E2PEnd = 0x00fe, +#endif /* CONFIG_WIFI_TEST */ + .hif_type = HIF_MT, + .rf_type = RF_MT, + .RxBAWinSize = 21, + .AMPDUFactor = 2, +}; + + +static const RTMP_CHIP_OP MT7636_ChipOp = { + .ChipBBPAdjust = mt7636_bbp_adjust, + .ChipSwitchChannel = mt7636_switch_channel, + .AsicMacInit = mt7636_init_mac_cr, + .AsicBbpInit = MT7636BBPInit, + .AsicRfInit = mt7636_init_rf_cr, + .AsicAntennaDefaultReset = mt7636_antenna_default_reset, + .ChipAGCInit = NULL, + .AsicRfTurnOn = NULL, + .AsicHaltAction = NULL, + .AsicRfTurnOff = NULL, + .AsicReverseRfFromSleepMode = NULL, +#ifdef CARRIER_DETECTION_SUPPORT + .ToneRadarProgram = ToneRadarProgram_v2, +#endif + .RxSensitivityTuning = NULL, + .DisableTxRx = NULL, +#ifdef RTMP_PCI_SUPPORT + //.AsicRadioOn = RT28xxPciAsicRadioOn, + //.AsicRadioOff = RT28xxPciAsicRadioOff, +#endif + .show_pwr_info = mt7636_show_pwr_info, +}; + + +VOID mt7636_init(RTMP_ADAPTER *pAd) +{ + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + + DBGPRINT(RT_DEBUG_OFF, ("%s()-->\n", __FUNCTION__)); + + memcpy(&pAd->chipCap, &MT7636_ChipCap, sizeof(RTMP_CHIP_CAP)); + memcpy(&pAd->chipOps, &MT7636_ChipOp, sizeof(RTMP_CHIP_OP)); + + pAd->chipCap.hif_type = HIF_MT; + pAd->chipCap.mac_type = MAC_MT; + + mt_phy_probe(pAd); + +#ifdef RTMP_MAC_PCI + if (IS_PCI_INF(pAd)) { + pChipCap->tx_hw_hdr_len = pChipCap->TXWISize; + pChipCap->rx_hw_hdr_len = pChipCap->RXWISize; + } +#endif /* RTMP_MAC_PCI */ + + + + RTMP_DRS_ALG_INIT(pAd, RATE_ALG_GRP); + + /* + Following function configure beacon related parameters + in pChipCap + FlgIsSupSpecBcnBuf / BcnMaxHwNum / + WcidHwRsvNum / BcnMaxHwSize / BcnBase[] + */ + mt_bcn_buf_init(pAd); + +#ifdef DOT11W_PMF_SUPPORT + pChipCap->FlgPMFEncrtptMode = PMF_ENCRYPT_MODE_2; +#endif /* DOT11W_PMF_SUPPORT */ + + DBGPRINT(RT_DEBUG_OFF, ("<--%s()\n", __FUNCTION__)); +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/rt28xx.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/rt28xx.c new file mode 100644 index 000000000..a791247e9 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/rt28xx.c @@ -0,0 +1,400 @@ +/* + *************************************************************************** + * 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" + + +#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) */ + + +VOID RT28xx_ch_tunning(RTMP_ADAPTER *pAd, UINT8 bw) +{ + if (pAd->MACVersion != 0x28600100) + return; + + + if (bw == BW_20) + { + 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 if (bw == BW_40) + { + 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")); + +} + + +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 = 0; + UINT32 i = 0; + ULONG R2 = 0, R3 = DEFAULT_RF_TX_POWER, R4 = 0; + RTMP_RF_REGS *RFRegTable; + CHAR lan_gain; + + + /* 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)); + } + + 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, ("%s(): TxPwer=%d \n", __FUNCTION__, 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, ("%s(): TxPwer2=%d \n", __FUNCTION__, 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->hw_cfg.lan_gain = GET_LNA_GAIN(pAd); + 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*/ + lan_gain = pAd->hw_cfg.lan_gain; + if (Channel <= 14) + { + ULONG TxPinCfg = 0x00050F0A; /*Gary 2007/08/09 0x050A0A*/ + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - lan_gain)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - lan_gain)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - lan_gain)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0);/*(0x44 - lan_gain)); 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_mac_set_band(pAd, BAND_24G); + + /* Turn off unused PA or LNA when only 1T or 1R*/ + if (pAd->Antenna.field.TxPath == 1) + TxPinCfg &= 0xFFFFFFF3; + if (pAd->Antenna.field.RxPath == 1) + TxPinCfg &= 0xFFFFF3FF; + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + + filter_coefficient_ctrl(pAd, Channel); + } + else + { + ULONG TxPinCfg = 0x00050F05;/*Gary 2007/8/9 0x050505*/ + UINT8 bbpValue; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, (0x37 - lan_gain)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, (0x37 - lan_gain)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, (0x37 - lan_gain)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, 0); /*(0x44 - lan_gain)); According the Rory's suggestion to solve the middle range issue. */ + + /* Set the BBP_R82 value here */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R82, 0xF2); + + + /* 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_mac_set_band(pAd, BAND_5G); + + /* 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); + } + + /* + 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); +} + + +VOID RT28xx_chip_Init(RTMP_ADAPTER *pAd) +{ + rtmp_phy_probe(pAd); + pAd->ChipOps.ChipSwitchChannel = RT28xx_ChipSwitchChannel; +} + +#endif /*RT28xx */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/rt65xx.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/rt65xx.c new file mode 100644 index 000000000..ce00e319c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/rt65xx.c @@ -0,0 +1,29 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + rt65xx.c + + Abstract: + Specific funcitons and configurations for RT65xx + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/rtmp_chip.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/rtmp_chip.c new file mode 100644 index 000000000..26536f9bd --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/rtmp_chip.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-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" + + +BOOLEAN rt28xx_eeprom_read16(RTMP_ADAPTER *pAd, USHORT offset, USHORT *value) +{ + if (pAd->chipOps.eeread) { + return pAd->chipOps.eeread(pAd, offset, value); + } else { + return FALSE; + } +} + + +/* +======================================================================== +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 +#endif /* RTMP_MAC_PCI */ +} + + +/* +======================================================================== +Routine Description: + write memory + +Arguments: + pAd - WLAN control block pointer + Offset - Memory offsets + Value - Written value + Unit - Unit in "Byte" +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpChipWriteMemory( + IN RTMP_ADAPTER *pAd, + IN USHORT Offset, + IN UINT32 Value, + IN UINT8 Unit) +{ + switch(Unit) + { + case 1: + RTMP_IO_WRITE8(pAd, Offset, Value); + break; + case 2: + RTMP_IO_WRITE16(pAd, Offset, Value); + break; + case 4: + RTMP_IO_WRITE32(pAd, Offset, Value); + default: + break; + } +} + + +/* +======================================================================== +Routine Description: + Initialize specific beacon frame architecture. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpChipBcnSpecInit(RTMP_ADAPTER *pAd) +{ +} + + +/* +======================================================================== +Routine Description: + Initialize normal beacon frame architecture. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpChipBcnInit( + IN RTMP_ADAPTER *pAd) +{ + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + + + pChipCap->FlgIsSupSpecBcnBuf = FALSE; + pChipCap->BcnMaxHwNum = 8; + pChipCap->BcnMaxNum = (pChipCap->BcnMaxHwNum - MAX_MESH_NUM - MAX_APCLI_NUM); + pChipCap->BcnMaxHwSize = 0x1000; + + pChipCap->BcnBase[0] = 0x7800; + pChipCap->BcnBase[1] = 0x7A00; + pChipCap->BcnBase[2] = 0x7C00; + pChipCap->BcnBase[3] = 0x7E00; + pChipCap->BcnBase[4] = 0x7200; + pChipCap->BcnBase[5] = 0x7400; + pChipCap->BcnBase[6] = 0x5DC0; + pChipCap->BcnBase[7] = 0x5BC0; + + /* + If the MAX_MBSSID_NUM is larger than 6, + it shall reserve some WCID space(wcid 222~253) for beacon frames. + - these wcid 238~253 are reserved for beacon#6(ra6). + - these wcid 222~237 are reserved for beacon#7(ra7). + */ + if (pChipCap->BcnMaxNum == 8) + pChipCap->WcidHwRsvNum = 222; + else if (pChipCap->BcnMaxNum == 7) + pChipCap->WcidHwRsvNum = 238; + else + pChipCap->WcidHwRsvNum = 255; + + pAd->chipOps.BeaconUpdate = RtmpChipWriteMemory; +} + + +#ifdef MT_MAC +VOID mt_bcn_buf_init(RTMP_ADAPTER *pAd) +{ + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + + pChipCap->FlgIsSupSpecBcnBuf = FALSE; + pChipCap->BcnMaxHwNum = 16; + pChipCap->BcnMaxNum = 16; + +#if defined(MT7603_FPGA) || defined(MT7628_FPGA) || defined(MT7636_FPGA) + pChipCap->WcidHwRsvNum = 20; +#else + pChipCap->WcidHwRsvNum = 127; +#endif /* MT7603_FPGA */ + pChipCap->BcnMaxHwSize = 0x2000; // useless!! + + pChipCap->BcnBase[0] = 0; + pChipCap->BcnBase[1] = 0; + pChipCap->BcnBase[2] = 0; + pChipCap->BcnBase[3] = 0; + pChipCap->BcnBase[4] = 0; + pChipCap->BcnBase[5] = 0; + pChipCap->BcnBase[6] = 0; + pChipCap->BcnBase[7] = 0; + pChipCap->BcnBase[8] = 0; + pChipCap->BcnBase[9] = 0; + pChipCap->BcnBase[10] = 0; + pChipCap->BcnBase[11] = 0; + pChipCap->BcnBase[12] = 0; + pChipCap->BcnBase[13] = 0; + pChipCap->BcnBase[14] = 0; + pChipCap->BcnBase[15] = 0; + +#ifdef CONFIG_MULTI_CHANNEL + /* Record HW Null Frame offset */ + pAd->NullBufOffset[0] = 0; + pAd->NullBufOffset[1] = 0; +#endif /* CONFIG_MULTI_CHANNEL */ + + pAd->chipOps.BeaconUpdate = NULL; + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + } + +} +#endif /* MT_MAC */ + + +#ifdef RLT_MAC +/* +======================================================================== +Routine Description: + Initialize specific beacon frame architecture. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID rlt_bcn_buf_init(RTMP_ADAPTER *pAd) +{ + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + + pChipCap->FlgIsSupSpecBcnBuf = FALSE; + { + pChipCap->BcnMaxHwNum = 16; + pChipCap->WcidHwRsvNum = 255; + } + +/* + In 16-MBSS support mode, if AP-Client is enabled, + the last 8-MBSS would be occupied for AP-Client using. +*/ +#ifdef APCLI_SUPPORT + pChipCap->BcnMaxNum = (8 - MAX_MESH_NUM); +#else + pChipCap->BcnMaxNum = (pChipCap->BcnMaxHwNum - MAX_MESH_NUM); +#endif /* APCLI_SUPPORT */ + + pChipCap->BcnMaxHwSize = 0x2000; + + pChipCap->BcnBase[0] = 0xc000; + pChipCap->BcnBase[1] = 0xc200; + pChipCap->BcnBase[2] = 0xc400; + pChipCap->BcnBase[3] = 0xc600; + pChipCap->BcnBase[4] = 0xc800; + pChipCap->BcnBase[5] = 0xca00; + pChipCap->BcnBase[6] = 0xcc00; + pChipCap->BcnBase[7] = 0xce00; + pChipCap->BcnBase[8] = 0xd000; + pChipCap->BcnBase[9] = 0xd200; + pChipCap->BcnBase[10] = 0xd400; + pChipCap->BcnBase[11] = 0xd600; + pChipCap->BcnBase[12] = 0xd800; + pChipCap->BcnBase[13] = 0xda00; + pChipCap->BcnBase[14] = 0xdc00; + pChipCap->BcnBase[15] = 0xde00; + +#ifdef CONFIG_MULTI_CHANNEL + /* Record HW Null Frame offset */ + //pAd->NullBufOffset[0] = 0xd000; + pAd->NullBufOffset[0] = 0xd000; + pAd->NullBufOffset[1] = 0xd200; +#endif /* CONFIG_MULTI_CHANNEL */ + + pAd->chipOps.BeaconUpdate = RtmpChipWriteMemory; +} +#endif /* RLT_MAC */ + + + + +#ifdef HW_ANTENNA_DIVERSITY_SUPPORT +UINT32 SetHWAntennaDivsersity( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN Enable) +{ + if (Enable == TRUE) + { + UINT8 BBPValue = 0, RFValue = 0; + USHORT value; + + // RF_R29 bit7:6 + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_GAIN, value); + + RT30xxReadRFRegister(pAd, RF_R29, &RFValue); + RFValue &= 0x3f; // clear bit7:6 + RFValue |= (value << 6); + RT30xxWriteRFRegister(pAd, RF_R29, RFValue); + + // BBP_R47 bit7=1 + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &BBPValue); + BBPValue |= 0x80; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, BBPValue); + + BBPValue = 0xbe; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R150, BBPValue); + BBPValue = 0xb0; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R151, BBPValue); + BBPValue = 0x23; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R152, BBPValue); + BBPValue = 0x3a; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R153, BBPValue); + BBPValue = 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R154, BBPValue); + BBPValue = 0x3b; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R155, BBPValue); + BBPValue = 0x04; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R253, BBPValue); + + DBGPRINT(RT_DEBUG_TRACE, ("HwAnDi> Enable!\n")); + } + else + { + UINT8 BBPValue = 0; + + /* + main antenna: BBP_R152 bit7=1 + aux antenna: BBP_R152 bit7=0 + */ + if (pAd->FixDefaultAntenna == 0) + { + /* fix to main antenna */ + /* do not care BBP R153, R155, R253 */ + BBPValue = 0x3e; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R150, BBPValue); + BBPValue = 0x30; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R151, BBPValue); + BBPValue = 0x23; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R152, BBPValue); + BBPValue = 0x00; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R154, BBPValue); + } + else + { + /* fix to aux antenna */ + /* do not care BBP R153, R155, R253 */ + BBPValue = 0x3e; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R150, BBPValue); + BBPValue = 0x30; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R151, BBPValue); + BBPValue = 0xa3; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R152, BBPValue); + BBPValue = 0x00; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R154, BBPValue); + } + + DBGPRINT(RT_DEBUG_TRACE, ("HwAnDi> Disable!\n")); + } + + return 0; +} +#endif // HW_ANTENNA_DIVERSITY_SUPPORT // + + + + +UINT8 NICGetBandSupported(RTMP_ADAPTER *pAd) +{ + if (BOARD_IS_5G_ONLY(pAd)) + { + return RFIC_5GHZ; + } + else if (BOARD_IS_2G_ONLY(pAd)) + { + return RFIC_24GHZ; + } + else if (RFIC_IS_5G_BAND(pAd)) + { + return RFIC_DUAL_BAND; + } + else + return RFIC_24GHZ; +} + + +INT WaitForAsicReady(RTMP_ADAPTER *pAd) +{ + // TODO: shiang-7603 + return TRUE; +} + + +INT AsicGetMacVersion(RTMP_ADAPTER *pAd) +{ + UINT32 reg = 0; + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return FALSE; + } + +#if defined(RTMP_MAC) || defined(RLT_MAC) + reg = MAC_CSR0; + +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + if (WaitForAsicReady(pAd) == TRUE) + { + RTMP_IO_READ32(pAd, reg, &pAd->MACVersion); + DBGPRINT(RT_DEBUG_OFF, ("MACVersion[Ver:Rev]=0x%08x : 0x%08x\n", + pAd->MACVersion, pAd->ChipID)); + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s() failed!\n", __FUNCTION__)); + return FALSE; + } +} + + +/* +======================================================================== +Routine Description: + Initialize chip related information. + +Arguments: + pCB - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +int RtmpChipOpsHook(VOID *pCB) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pCB; + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; +#if defined(RTMP_MAC) || defined(RLT_MAC) || defined(RT65xx) + UINT32 MacValue; +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) || defined(RT65xx) */ + int ret = 0; +#ifdef GREENAP_SUPPORT + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; +#endif /* GREENAP_SUPPORT */ + + /* sanity check */ + if (WaitForAsicReady(pAd) == FALSE) + return -1; + + // TODO: shiang-7603 + if (IS_MT7603(pAd) || IS_MT7628(pAd)) { + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + } + else + { +#if defined(RTMP_MAC) || defined(RLT_MAC) + RTMP_IO_READ32(pAd, MAC_CSR0, &MacValue); + pAd->MACVersion = MacValue; +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + } + + if (pAd->MACVersion == 0xffffffff) + return -1; + + + /* default init */ + RTMP_DRS_ALG_INIT(pAd, RATE_ALG_LEGACY); + + + + + + + + + + +#ifdef MT7603 + if (IS_MT7603(pAd)) { + mt7603_init(pAd); + goto done; + } +#endif /* MT7603 */ + + + + +#ifdef GREENAP_SUPPORT +#if defined (MT7603) || defined (MT7628) + pChipOps->EnableAPMIMOPS = EnableAPMIMOPSv2; + pChipOps->DisableAPMIMOPS = DisableAPMIMOPSv2; +#else + pChipOps->EnableAPMIMOPS = EnableAPMIMOPSv1; + pChipOps->DisableAPMIMOPS = DisableAPMIMOPSv1; +#endif +#endif /* GREENAP_SUPPORT */ + +#ifdef RTMP_MAC + // TODO: default settings for rest of the chips!! change this to really default chip. + RTxx_default_Init(pAd); +#endif /* RTMP_MAC */ + + /* We depends on RfICType and MACVersion to assign the corresponding operation callbacks. */ + + + +done: + DBGPRINT(RT_DEBUG_TRACE, ("Chip specific bbpRegTbSize=%d!\n", pChipCap->bbpRegTbSize)); + DBGPRINT(RT_DEBUG_TRACE, ("Chip VCO calibration mode = %d!\n", pChipCap->FlgIsVcoReCalMode)); +#ifdef DOT11W_PMF_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("[PMF] Encryption mode = %d\n", pChipCap->FlgPMFEncrtptMode)); +#endif /* DOT11W_PMF_SUPPORT */ + + return ret; +} + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/rtxx_dft.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/rtxx_dft.c new file mode 100644 index 000000000..82e21e5af --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/chips/rtxx_dft.c @@ -0,0 +1,395 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + rtxx_dft.c + + Abstract: + Ralink Wireless driver chip default init functions + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#include "rt_config.h" + + + +FREQUENCY_ITEM RtmpFreqItems3020[] = +{ + /* ISM : 2.4 to 2.483 GHz, 11g */ + /*-CH---N-------R---K-----------*/ + {1, 241, 2, 2}, + {2, 241, 2, 7}, + {3, 242, 2, 2}, + {4, 242, 2, 7}, + {5, 243, 2, 2}, + {6, 243, 2, 7}, + {7, 244, 2, 2}, + {8, 244, 2, 7}, + {9, 245, 2, 2}, + {10, 245, 2, 7}, + {11, 246, 2, 2}, + {12, 246, 2, 7}, + {13, 247, 2, 2}, + {14, 248, 2, 4}, +}; + +FREQUENCY_ITEM FreqItems3020_Xtal20M[] = +{ + /* + * RF_R08: + * <7:0>: pll_N<7:0> + * + * RF_R09: + * <3:0>: pll_K<3:0> + * <4>: pll_N<8> + * <7:5>pll_N<11:9> + * + */ + /*-CH---N--------R---N[7:4]K[3:0]------*/ + {1, 0xE2, 2, 0x14}, + {2, 0xE3, 2, 0x14}, + {3, 0xE4, 2, 0x14}, + {4, 0xE5, 2, 0x14}, + {5, 0xE6, 2, 0x14}, + {6, 0xE7, 2, 0x14}, + {7, 0xE8, 2, 0x14}, + {8, 0xE9, 2, 0x14}, + {9, 0xEA, 2, 0x14}, + {10, 0xEB, 2, 0x14}, + {11, 0xEC, 2, 0x14}, + {12, 0xED, 2, 0x14}, + {13, 0xEE, 2, 0x14}, + {14, 0xF0, 2, 0x18}, +}; + +UCHAR NUM_OF_3020_CHNL = (sizeof(RtmpFreqItems3020) / sizeof(FREQUENCY_ITEM)); + +FREQUENCY_ITEM *FreqItems3020 = RtmpFreqItems3020; + + +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) + +/* The Tx power tuning entry*/ +const TX_POWER_TUNING_ENTRY_STRUCT TxPowerTuningTableOrg[] = +{ +/* idxTxPowerTable Tx power control over RF Tx power control over MAC*/ +/* (zero-based array) { RF R12[4:0]: Tx0 ALC}, {MAC 0x1314~0x1324}*/ +/* 0 */ {0x00, -15}, +/* 1 */ {0x01, -15}, +/* 2 */ {0x00, -14}, +/* 3 */ {0x01, -14}, +/* 4 */ {0x00, -13}, +/* 5 */ {0x01, -13}, +/* 6 */ {0x00, -12}, +/* 7 */ {0x01, -12}, +/* 8 */ {0x00, -11}, +/* 9 */ {0x01, -11}, +/* 10 */ {0x00, -10}, +/* 11 */ {0x01, -10}, +/* 12 */ {0x00, -9}, +/* 13 */ {0x01, -9}, +/* 14 */ {0x00, -8}, +/* 15 */ {0x01, -8}, +/* 16 */ {0x00, -7}, +/* 17 */ {0x01, -7}, +/* 18 */ {0x00, -6}, +/* 19 */ {0x01, -6}, +/* 20 */ {0x00, -5}, +/* 21 */ {0x01, -5}, +/* 22 */ {0x00, -4}, +/* 23 */ {0x01, -4}, +/* 24 */ {0x00, -3}, +/* 25 */ {0x01, -3}, +/* 26 */ {0x00, -2}, +/* 27 */ {0x01, -2}, +/* 28 */ {0x00, -1}, +/* 29 */ {0x01, -1}, +/* 30 */ {0x00, 0}, +/* 31 */ {0x01, 0}, +/* 32 */ {0x02, 0}, +/* 33 */ {0x03, 0}, +/* 34 */ {0x04, 0}, +/* 35 */ {0x05, 0}, +/* 36 */ {0x06, 0}, +/* 37 */ {0x07, 0}, +/* 38 */ {0x08, 0}, +/* 39 */ {0x09, 0}, +/* 40 */ {0x0A, 0}, +/* 41 */ {0x0B, 0}, +/* 42 */ {0x0C, 0}, +/* 43 */ {0x0D, 0}, +/* 44 */ {0x0E, 0}, +/* 45 */ {0x0F, 0}, +/* 46 */ {0x0F-1, 1}, +/* 47 */ {0x0F, 1}, +/* 48 */ {0x0F-1, 2}, +/* 49 */ {0x0F, 2}, +/* 50 */ {0x0F-1, 3}, +/* 51 */ {0x0F, 3}, +/* 52 */ {0x0F-1, 4}, +/* 53 */ {0x0F, 4}, +/* 54 */ {0x0F-1, 5}, +/* 55 */ {0x0F, 5}, +/* 56 */ {0x0F-1, 6}, +/* 57 */ {0x0F, 6}, +/* 58 */ {0x0F-1, 7}, +/* 59 */ {0x0F, 7}, +/* 60 */ {0x0F-1, 8}, +/* 61 */ {0x0F, 8}, +/* 62 */ {0x0F-1, 9}, +/* 63 */ {0x0F, 9}, +/* 64 */ {0x0F-1, 10}, +/* 65 */ {0x0F, 10}, +/* 66 */ {0x0F-1, 11}, +/* 67 */ {0x0F, 11}, +/* 68 */ {0x0F-1, 12}, +/* 69 */ {0x0F, 12}, +/* 70 */ {0x0F-1, 13}, +/* 71 */ {0x0F, 13}, +/* 72 */ {0x0F-1, 14}, +/* 73 */ {0x0F, 14}, +/* 74 */ {0x0F-1, 15}, +/* 75 */ {0x0F, 15}, +}; +#endif /* RTMP_INTERNAL_TX_ALC || RTMP_TEMPERATURE_COMPENSATION */ + + + + +static VOID RxSensitivityTuning(RTMP_ADAPTER *pAd) +{ + UCHAR R66 = 0x26 + pAd->hw_cfg.lan_gain; + +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + { + ATE_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R66, R66); + } + else +#endif /* CONFIG_ATE */ + { + bbp_set_agc(pAd, R66, RX_CHAIN_ALL); + } + DBGPRINT(RT_DEBUG_TRACE,("turn off R17 tuning, restore to 0x%02x\n", R66)); +} + + + + +static VOID ChipBBPAdjust(RTMP_ADAPTER *pAd) +{ + UCHAR bbp_val; + UINT8 rf_bw, ext_ch; + +#ifdef DOT11_N_SUPPORT + if (get_ht_cent_ch(pAd, &rf_bw, &ext_ch) == FALSE) +#endif /* DOT11_N_SUPPORT */ + { + rf_bw = BW_20; + ext_ch = EXTCHA_NONE; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + } + + bbp_set_bw(pAd, rf_bw); + + /* TX/RX : control channel setting */ + rtmp_mac_set_ctrlch(pAd, ext_ch); + bbp_set_ctrlch(pAd, ext_ch); + + /* request by Gary 20070208 for middle and long range G Band*/ +#ifdef DOT11_N_SUPPORT + if (rf_bw == BW_40) + bbp_val = (pAd->CommonCfg.Channel > 14) ? 0x48 : 0x38; + else +#endif /* DOT11_N_SUPPORT */ + bbp_val = (pAd->CommonCfg.Channel > 14) ? 0x40 : 0x38; + bbp_set_agc(pAd, bbp_val, RX_CHAIN_ALL); + + + if (pAd->MACVersion == 0x28600100) + { +#ifdef RT28xx + RT28xx_ch_tunning(pAd, BW_40); +#endif /* RT28xx */ + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R69, 0x12); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R70, 0x0A); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R73, 0x10); + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): BW_%s, ChannelWidth=%d, Channel=%d, ExtChanOffset=%d(%d) \n", + __FUNCTION__, (rf_bw == BW_40 ? "40" : "20"), + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth, + pAd->CommonCfg.Channel, + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA, + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset)); + + /* request by Gary 20070208 for middle and long range A Band*/ + if (pAd->CommonCfg.Channel > 14) + bbp_val = 0x1D; + else + bbp_val = 0x2D; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R62, bbp_val); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R63, bbp_val); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R64, bbp_val); + /*RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R86, bbp_val);*/ +} + + +static VOID Default_ChipSwitchChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel, + IN BOOLEAN bScan) +{ + DBGPRINT(RT_DEBUG_ERROR, ("%s(): dummy channel switch function!\n", __FUNCTION__)); + + pAd->LatchRfRegs.Channel = Channel; + pAd->hw_cfg.lan_gain = GET_LNA_GAIN(pAd); +} + + +static VOID Default_ChipAGCInit(RTMP_ADAPTER *pAd, UCHAR BandWidth) +{ + UCHAR R66 = 0x30, lan_gain; + + + lan_gain = pAd->hw_cfg.lan_gain; + if (pAd->LatchRfRegs.Channel <= 14) + { // BG band + { + R66 = 0x2E + lan_gain; + } + } + else + { //A band + { + if (BandWidth == BW_20) + R66 = (UCHAR)(0x32 + (lan_gain * 5) / 3); +#ifdef DOT11_N_SUPPORT + else + R66 = (UCHAR)(0x3A + (lan_gain * 5) / 3); +#endif // DOT11_N_SUPPORT // + } + } + bbp_set_agc(pAd, R66, RX_CHAIN_ALL); + +} + + +static VOID AsicAntennaDefaultReset( + IN PRTMP_ADAPTER pAd, + IN EEPROM_ANTENNA_STRUC *pAntenna) +{ + { + + pAntenna->word = 0; + pAntenna->field.RfIcType = RFIC_2820; + pAntenna->field.TxPath = 1; + pAntenna->field.RxPath = 2; + } + DBGPRINT(RT_DEBUG_WARN, ("E2PROM error, hard code as 0x%04x\n", pAntenna->word)); +} + + +VOID NetDevNickNameInit( + IN PRTMP_ADAPTER pAd) +{ +} + + +VOID RTxx_default_Init(RTMP_ADAPTER *pAd) +{ + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + + + /* init default value whatever chipsets */ + /* default pChipOps content will be 0x00 */ + pChipCap->bbpRegTbSize = 0; + pChipCap->MaxNumOfRfId = 31; + pChipCap->MaxNumOfBbpId = 136; + pChipCap->SnrFormula = SNR_FORMULA1; + pChipCap->RfReg17WtMethod = RF_REG_WT_METHOD_NONE; + pChipCap->TXWISize = 16; + pChipCap->RXWISize = 16; +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) + pChipCap->TxPowerTuningTable_2G = TxPowerTuningTableOrg; +#ifdef A_BAND_SUPPORT + pChipCap->TxPowerTuningTable_5G = TxPowerTuningTableOrg; +#endif /* A_BAND_SUPPORT */ +#endif /* defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) */ + pChipOps->AsicMacInit = NULL; + pChipOps->AsicBbpInit = NULL; + pChipOps->AsicRfInit = NULL; + +#ifdef RTMP_EFUSE_SUPPORT + pChipCap->EFUSE_USAGE_MAP_START = 0x2d0; + pChipCap->EFUSE_USAGE_MAP_END = 0x2fc; + pChipCap->EFUSE_USAGE_MAP_SIZE = 45; + pChipCap->EFUSE_RESERVED_SIZE = pChipCap->EFUSE_USAGE_MAP_SIZE - 5; +#endif /* RTMP_EFUSE_SUPPORT */ + + pChipCap->VcoPeriod = 10; + pChipCap->FlgIsVcoReCalMode = VCO_CAL_DISABLE; + pChipCap->WPDMABurstSIZE = 2; /* default 64B */ + pChipCap->MBSSIDMode = MBSSID_MODE0; + +#ifdef DOT11W_PMF_SUPPORT + pChipCap->FlgPMFEncrtptMode = PMF_ENCRYPT_MODE_0; +#endif /* DOT11W_PMF_SUPPORT */ + + RtmpChipBcnInit(pAd); + + pChipOps->RxSensitivityTuning = RxSensitivityTuning; + pChipOps->ChipBBPAdjust = ChipBBPAdjust; + pChipOps->ChipSwitchChannel = Default_ChipSwitchChannel; + + /* TX ALC */ + pChipCap->bTempCompTxALC = FALSE; + pChipOps->AsicGetTxPowerOffset = NULL; + pChipOps->InitDesiredTSSITable = NULL; + pChipOps->AsicTxAlcGetAutoAgcOffset = NULL; + pChipOps->AsicExtraPowerOverMAC = NULL; + pChipOps->AsicAdjustTxPower = AsicAdjustTxPower; + + pChipOps->ChipAGCInit = Default_ChipAGCInit; + pChipOps->AsicAntennaDefaultReset = AsicAntennaDefaultReset; + pChipOps->NetDevNickNameInit = NetDevNickNameInit; + /* Init value. If pChipOps->AsicResetBbpAgent==NULL, "AsicResetBbpAgent" as default. If your chipset has specific routine, please re-hook it at self init function */ + pChipOps->AsicResetBbpAgent = NULL; + + pChipOps->InitTemperCompensation = NULL; + pChipOps->TemperCompensation = NULL; + +#ifdef RT28xx + RT28xx_chip_Init(pAd); +#endif /* RT28xx */ +#ifdef CARRIER_DETECTION_SUPPORT + pChipCap->carrier_func = DISABLE_TONE_RADAR; + pChipOps->ToneRadarProgram = NULL; +#endif /* CARRIER_DETECTOIN_SUPPORT */ +#ifdef DFS_SUPPORT + pChipCap->DfsEngineNum = 4; +#endif /* DFS_SUPPORT */ + pChipOps->CckMrcStatusCtrl = NULL; + pChipOps->RadarGLRTCompensate = NULL; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/RT85592.bin b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/RT85592.bin new file mode 100644 index 0000000000000000000000000000000000000000..3e81b6c5276b25f6691736eb7b52cea3f8b6c464 GIT binary patch literal 25740 zcmbun4SZ8Y_BVd+%}ts#g{Cxx7FfB30_9E0i_n6~+%`=M6i6Y}RM@4ZML|&t1+6c; zos{$iEK(5>v_O%!qAcKA3c9R@7qKdHmim6^WC%JIHV zl@omC%85QxWtK0ja*|J9IoYSHoZ^$lM1H-$aF!w$F5D~^mXSPWe%i_U}py*dvS$_YAq1fd?ug*wt@v{7WPe+8i@gNu|J^lfliDr!8; zC%@#*vXuIRZw%s%32)ju-egig_evV;|9Ss~pBvNz-8O0-zI}XS-$uS&3SzFSsXN%9 zu3uYUmSthaINB{B*-X`!Ue|iMyxW zOM2H4-AUF!dtT*gnP=sqaJjDZMEIwCY`CJUOu?Nva#EA3^%&5!Ovy@rCQtxWZ~2(&T4J=acJi zclT>}$6f>6RxPQ?D)b*|*!oGhzJL^FRwd9!u50cPeGMV{*6g?Ep?(24Il`mXFKj%r z{gozTh!@m6w0?xo5PT9`9W#GTpj~iG>QdhU-ag~{@%5>wqjz27Cp$PFtg}(B{i6P0 z=AsbLf2&I9vqzD6XgpVntp%2i6|>`1VV@UwiF|Evn=wu3&Zt8C_GW zE!8JZT@1Zz_!T6htGL<{gd{os3#5i1B;Eu_Cf8K%6_9|}&AidM3OYC0h%7;^sW{r) z4^L6Sr}7ic{X7)9&&0hHy!UJl)QSr}xvkCpf_G&`w2j46U@XdnL`bw^QjL^5fU6Z0lgOnQnG}0c5^XH7 zTcD|yGGe`}6;H4FO;+OVQq&fNxdbB>9L+KFckKV}xZ_Q?k$c^#;J@Bg>^W{z$->R< zK5k`VOHYaS6VHxFcWmHk5S~=t3y>t&wemI1LwPToMWWzyg;PB9fqXol!%v0koNpfb z?O^l-&IaWI<&Z|t6CDz^7)Zf;Z@ zQI@Op+ViWHdK^EV2CZ6| z;~=R)o-&PYc}MRY#v>~%zOf#6Ru^V;M)Am1N7Ezyk-p)c7sb2J3~X4PF+H-)?;F5| z?KawaMf!b1-igRS9q~Tb80lxjyhcV$_VuaIvf`LI2T<(2+Wai}m{HgXUrfcUtT=C{ z9F0e2M56wfJY%4pXk)Tl{D9CFsL4o?8AT|Ka?ob&fZgHV26EPLe{f97703{5=Ms;{ zE=Iu{-e5q9u$eW%lBQg6)j(lO=6HLDB&bbZLWa%!jC?NcN!gv}X|dN~e7EQopSkXm z+?NxR>S$t1qO|S@@9oe15Q1kp6V`gsvoUL>ci6_iRPUxVGMyYGrBSRjg5tD+s!=m# zDK-Z^G)eZVj$-Nw-O{@}dWDDGjH4;BTU(M8;jH8S)Y%aU&Zo%_X-i8jtSWxa8>C8UTf5t%a)Vp%{D}OZ8J0)rh$kVd z$g6mCzHpB{YXMU{icjx(GHW5zdt{4_81q&cEr&>JmvL_3i9D;hKTRW6UXYdJ?d~{C zv5paBS#EK>O0knaA`@!pJeke?xtS04h4H~Ro)QD4;d}tM2W7cj3CID==Q5qExbADqxl}PzNF%tE zJ%Gzgr&e8ZZXv%^famEXYZL0}i$$$}_eFZ%${N9jbCpjF=(6DA@#djlC$#o42%gW~mKVyBgIuUIVjLulDxFUN7r={h)ot>9 zCdL*ry$X~cbneEO!jEvrTX*re5cHnSL$?jzTFi#4Mi%c;YF9aW@j`yDXMe$)Do>z|kq^A74Jh$- zvRTLys9%K^8-sN#V9U_2Q`B|nC_B^#>O+Eqa+ZWqp4TC-yZ58qM3v>gd>`&PQy%ZB zgN2{D>!RfuqFoDjj&K*aJ62$Q+xMT@QctmX(it*1CDPeu`ajT$EJkg< zRo14@P&{c-)5rk1@9gUgSu65}ZT;S*akgue4}D}UM*mw*nW4dk^eKL>4LGKFHb(U! z!>0ym8l-R_mv-&}min*Gv?{(%=&74jO#0jhxExhLdc3iCHhroC4E@%{F5;G*x1r47 z*@&`Dr=kKhjV}MUrneaH9>5hX#%g5sP2E|2W)I6IGJ>11cfwkEsxZF=c?rILb@rSd zl=TPPgrIFwj-zfA56m&bGU07B-dY?nT#U&uF*c$c*s<&&cFbo44hm}OeG#Y|&IhBW z<`J41l4?9>d(@j`K*-I;Pa_~N_7Gk*sEs+P>a3Uw$rR6%b@UydK6RG6;+K?GrcKjSDT9hfJSJ_$SI zEkLg(=t}$8>Ge_ zFxq<3u>}~5Vy^JPp2;`*gJs4n)Pu$5}NE;)vgWo2)^#8c<9N-7aN zx!y#Qg`}u1bi0K0Vw6lJQXc7Qm8e|7V4Y; z+0^Gw=ycsTRhw&gM2af)OA?KxYXkAE0$XIIWQT>4nT=BN7-?~JCe7qE zX~r2k=31p=<7;%F9L#$w63A{Gi|t47d4C;YM(yiJGWE#1h4P^ z?&MVuKeVU(O2yYTlP^m@V5YZZ<#UsbQEb*M(m$J28oKR#onSZiTqpMn*0^r3Lf zW=X5MWMAO%j+wl-V+!vR^8wdibXWB(OW?Elon<|@d8Ii-$_6fJkN4EYm5?Gak|YNw zZOk!U9CVJ3Vcfsq#NHmMi#>qn-K3KeIXQ@KXIq+dvGrV;r1+a_uWC}2(eV%|-&bB; z;7qy zjUrL26Lq7`Q5h5#HJXf;Pbu8;HW{M&lgYA|%$9AWw>(Em6zW(iDe|(;5=If0Zq%tv z&+p_tg`8yogWLy<*OUL6N&1;wirq~L)p1IGA(3KhxFSX2{z)6fxPjp#g&(`Z=*8mm=x8{I5i(I3Z@i zg_6TDC^?)`if!nL>r(DlC`DtGG7?uGNa-^QX}XiTWVe%Gh4s0QFS~9}0-Rw>uO~;L zy=0^0#}8A=g2TkdI&>Kp)QMesJ;nWMXNi(WCW@*xCBaiA*`Zy`2hm+#;Bx$+e zz_41pJE?06(uBz|v&K6N-N zezrKfxBvRIE<`!QxPR%%?1EB%S#3@%_m|Z}8b?BNZ-+N+gM`k2gl5_D$g<=ach9mX z+@tuVC98dtrGN3T74h1l5?$0|JPdg0VtR3X%uvK2#&HF+svI+u8$!4W@3}v)>fG^s z*?7ssm+?PiRn_nN=Yke%1uRyZfe*adJLFh#-Ta(wEA=~@{oy<8v{z+825jDc}^SOD+s=cfE$V*{u;T;(9o}qjA z_gK3W21m-1=Wvj*F|YmrFOMBgQaVXg`&m|U=}#Wc3$>_a-K12G5^a`)(h&hkDe@AV zID?*3HOxBMW4KWoz=iZlQR6vfCHq^O*L%2c=$^Xl5-#OT=l+zb$2(^)M7`;d;ymcu zgcFoAhWs%}xTh@2j)e|Ej-m$Pa=|`4ASAkm+Utor66!EllP)>C#<(t?*PSjqcMSb7 z-|zHAM72-DOGaPhPsu*sxq8kvmma1>8-9#(25^6jihD~YIUqHXOcW(?+Lg!iPHX2* z2iLLRop-+oxy<7SLJ~H^qq_50WEHuWxNYvfkUp=FuYfn1$9su;ZVWszaX;fSX|0i1 zfei}y1?~R$eC`!KVwu4gE~J2qHGzz1(siuOE>SGeUBpMl8WGpg`+szl^1Q$bOw?$A zR}8-g@rIr}4D*{8*r6v?g0u|bS;0H_k|G|3`kqzIL$|iw70>UF?E}4@?f)s@o&6S4 zuXad|`EC+00M&vub-w^S{B}S?L?&QaJ;%QucFq7F9G(|he2Tc^<0rO6NZ(q6YhMuu z`0jXse{=p9{vE%;zd8R8{1Y)d>u>qD41U;u<=>ok{w+gPH^@H|%0RV<_5C;gS%VZ; zIsPa9{R)!cUjP#LXASYs`k(w0&~D=2Z8!L5{T2TZD-6a_U?-nw^Hj&St#Hie>|&(A z^;ed~?ij~;?W(MJzpx4l>=n~L#$}~DY*8tfS&c`p59d1l!$iVPX=lB1!&P`Ya>kH{ zUt$F(iD6xyJ3uL6LrGz0GKp<761%O?%r<&Re}p9FOVryZS3j=ZyIE#cMa1?fvMV+0 zE^X{!MZ*?|mU)!eJr1)ryq>PPm4`{za*yimy;H-qe|cn9SWC=QFT3LDA6lRXK>sw8 zG{b%~JCQ|7BkACgb+%{qIH?_J(6gr!WzDjKw0n=Dm(Jg5HkZO&(D$jwh&^9#)|?Hb z7)Z&uaJTo`^4trNyVzsL^;(~!GRrF=Hn2fvXA((!$EaA}>Y7HKU#iH!p_U+f^|UNYDRE>YO768LV0 zXzeYhtn~r@7Y560=}6LUNmjIxHqz$qH)~@{C}Ya;x%zu4?CP@I33`cv3vA&InN4&M zTYFvBWG6A*W`)6fVto_A-z?JiBcuJ3HKy;Ex<08o!Dc7wwdfL=odfK*vSd~{n3xN* zrw#GndkW1Wa-}z5b-bow3Y*}-inekW>y3IP3BWBAYwv6(`(3X|`cV|2-BP4?O?CHXnW(pP6={D+ zkl9EFX{VivCS9j%6|4kQ=n(2RP$&D)&nj6x181dYm@h$ITc%|e$yzjMzU!F6s?gr) zFtcS|vQM~gmHsa3%#N#iSE}wQHU{`^ZIiXLOlGfa1~*F-HoJ=2%9-wVGs{yc!}bD0 zACb8ejPdMHtX_j}#O^}vXH=Obw-HO-tgu&V=u&64rQU46kbj!(i6z(9`dQkUk+OCm znY8penLSpbXtyxz~=+t$+RMwH8NtS zs}#0nA8B9CGiO*5H1=jJX*L!9u4fwi7+5?Cnbm{7XV7EjNQI3=+XE-f_TMkNg{?+! zePS_=6>jazDw(x_!p&=BEkh+O2K;!}M#?E}W`6?Klm9qQOWO=spfJ_k#1gzR8wFVJ zf3R{+74oKMk;HzvIF4r z?IVgZy1bh7A8@1Kc7`=)BP+v5Y%~gM|!alMP}GF_u38Y4R9~IM#r{5>sr_7SUDDer??@* z@YyHqtkaxplzOvDNRb^-o&l710eNJdj`fQm`_fGo$V7Qeut4ZyHdk#tQGwsu*06lifat8KfF(;9ROy%xY^$DxAW{zz--To z?b@Mz&0R1eew)0~W0FVc@@DH)Ztr z<|p>5*PI($UBnizA-3HnGz4&x38SymB2|Hx-k!R2FKZQebv~kn^$gD@Z^RDfR*_DPd33w}W>%UNYo5Y}o2 zyfCXI)alkf4+>58-I;DyEI77Y&kE{-6grat4YF_=J%0yT3d@+ZZW8-6!JIpRQrK6( zU&zo1@N3a-V)5XYt_pZP_!`?M@LKw%rU$RK1FySd0SUZ14cy-^A-nctfA)#MDdIXi z;w25S9JWUADi%2H)~)>6mV0qQlJgeN1CD|_ojzo4@OoFK!kp-3 z%M6{?rJlYwvNb!*8HOJ#HS2X^kDtUG+j$CmhLJX>7IXbk&|jj{?g1_nz{jDd-`A$X zHVrKiK1d6@r%7QPQax|fj2Yjq{2p& zKtDi@c8uEeT5n*P(Bfv}F&<-%i`jQ0cAZIEn5AgntkNyrtN@y8Tx5O~!E6y<_Py$@5H6j%$xyM-hx+M^!Q@&}vYZGw|0 zz{M;`vy=9IXhqh5HIvI$7j`k#wtz2fZ$s1|uzPw*@u=1)>U!Q2T>Farj0@KlmAX2L zC>FT^(wZ?g3vrLu(MHix*BNb;d@hWO)jlHoOJkdd)-BRUlU@@(gR9!O>OGd~Rj#-j zOZhlYrbEY*L+i-nftBJ-?XX4+tfWNwd1FT&#=iZY7W99>o$5G7u`ru~y$l=7kbO7$ z+_N;+*IyYyU0DWn=B{eelnCMpTt5Ti)fz5#7X+SFtxL&@Jv3hwPna6d8P^Bi^r5cS zL)3L@lvr1+{b6FuV2PDu1)G_*xb)MFBR4MQVIFl&-D$SwT-E&ghWe{x=I;x|aF9D= z0WOvm34t|e`;H{y9oT`04X%JYc;#UpM1!p8uYP3x;`ZE&&4>fJRky@Xx38Z&THL%& z#Y$?xjWsf&KX~pR$gT*ja7Dyoa|o}x{oi>VoYcTt$;%T1a6;>D#CT>R63qBa3=pNa z_$ebPvQ2v|&!pX-XVmT~ks+aq*1gUMxsjRCrm!xmi6tq@OCNszwPPrvLpt|J{jk!X zM0>qddR5U%FKcnfbSxJ3HVJcR_Rr?+)372_OTTOA2T71NF4Q9vtZroX2=3ror@16$ zq}TUHWOFS`KCIWK!z20^hs=6qZQ)^=Y4gl1(n8qN1U%S{%qlatl=Ys3+$ltL)A(lJ zDeMUhY&u|#y{=pP09RNtU?l}$ zl?jY|EskP0Lo~51!pNnJ8CwVE-sAp6%Y&6z;MG;F)=mSL-q824RXS!gnwNge(QZ;S za7p8T;d#CZ;=0tuq7Rk+pP(7_hwt7{>GNbu00i50b3ILzuJ=6 zkS&S*4_guoTN3*}*pg8jANiFnX{^8YUu?<9fGrWRm-a}Rj@19rmc-VNs(<7rTe9jV zTY^|p2nzO*+ii)6+1zYPmd^RLEfMhAj6OAvoKzk0kzRi?>ZXallxbdxvH3wDIr z?cSs!-fGXo-EISOtH^d#T?KNHYY#8wF{99h8?f zkQ=l)9%I%Z*2Q`jZ$9RAdyZ&vkbu}a2 z+3~_fk(td24W(D4tFnkY`^=%zIYEw#>^fiAa&39S8OOPbP?i&7f+G5V0efM{+>6&! z!;4ql$VeL}m2$l_4wOBx#-u$EYxLx4J)kcGs!ZAdqcIA4VL_Zb3Ndazt4(T@JtReP zgA1v+7R14?NR4HCHq}aqz)PasnMm?Mk)2g|;%b{jXqiejb7TH_oMWpV2MP}y+Nnsp}l20VCk>fcqhXnh>pYmjp>htSIo{2d3QE)8U_oN}`$TwR(-dV)MR`&kj z7DNk8z$p-2HlO!JH4w7^lSE*Gh_;AoHbpcbXRSeMG_3ovx@rB$)9228*OA30v?iF} zxcZ$nX&$z-3i5!R@TG`ZV^`s(oMe&T=hil7x>ZQCg$?54H$5Hni+%}n+LH1;MEkWSF=3fbnCfG%O&P98oQJebzszuAF}F z+<8GuM=pbatzah=V~CXra-KcMO#Fa5j}Hj7+UN98sTifu^HH8Co}i%?PfHf3$zMjb zMtQbpmGMDehPUcH^;u=!MZTV%mryd$^D>?u^bLhX_r$Z~%ipyc*V%A4c3lSE>T@-TFMK+R@#@E+9&L+m1p6$m}cvu=mYmdR&Pv_&DW4LUK z^#4nng-C21$+_9Qr}k)#NqfA;SV23BqKZiu1$fAAQ=)Xp5=kTBCzvRsLhnpLcEeT{ zRi!vhWZapwv-sxR{kr|OJc_mC(RxQ7CGwWQEE*f|GQ`{}sEH<`CD_-C^q*ihCOfe* za`om$R~Jy1hfJWZxVr7!y>kI<0`}w;n>~=jR_;fRjE)Z$79m&?$ePjd;i9DOQQ_N& zoLm)odVG}^ydVjA+AIn?P~e`FHlfA@I;3`gEod{i3jM&DjrMHtB_fydhSdnzsu@ZR z$-ISe9{pSm?-ih^u48l@Hs1Mtu?{iO=<=lZ6pWxBQYN0m%7=M%-0lmMdGfH6dZ{A6 zoOmzn*6O0h@pYJERyF#sxGh6@?Ugd?ihyLmcDbG4Q!l*4LibE6}YTLFDN@Bv(26Y@$#rjYPT zPI2S;%|Xwj>|GxwhP%2TTf-;~jG4tV2F;Bu|*w5__|3MGAWyDCx+_N(z(&WJW0oVs;}d zOhs1MRY#%ze%}ALd13S_G7G+N-G+6I?CA>l3WyF(!Pi=YSXVPxf4lWk(aL0Op%ES`PM`K zWym}-sIejr<$qSRXVPM)(yl_@;|-m+Io1tW-Lmu8`lsIu!`L7zuELPj$N#;J3}P2o zXlqYMNJ~?vz?>p^mqPIplRnom1 z>13p=R=pA1#yh)k-3+iR2uWl;3abzMb0cB4Oki8cJ5B4kmPNnMTS2c9xJj^ zO_tFWdfrb-fE5zs2%c7C0>;K;iHHp-RyWQso!*2?&C|3Bp@=- zAN&yGThlyr?QT^^)Fk+AvWD@cs2h#wkC+8TjfUo--Y``qI;eQ^Vv|UWZLpr9eKri) z(}0!cggj=URYD)GhqS66W*&o!aDFHNQ+Ogg%x4bhKq#(N5z#z!XHw8d5LWCrFk5~F z)7#Xk9b)@BJOI=1pD-K4ZicxVF-JQx=3Ga@uET@;BBU`z*!@>9+aMRZs=+r@a64$} zx!M#i&eSDH-VqJ`+ayL@M&@onbDGSdH~kv!yCgBGN@)zkihU5`Xi3odVeYdb91}XI z_K9;|u&~J7B5{fWStP;do=rzWa*4>K$PUM94zdROjni{d3s>EBA!yDHXboRYendKj z-Gu;G%hl$gwQfFy8EPpw19<{5&;~ndSOCXT2EQ1YG}LIwB%nP|jIWaWXsjSQkih4@GV9?E3yL$}W zEXo;Esj&k6*0*z@qYt;*q;qrMh(KR&^QDsy(hy_}-|8J8{)es5&Y8s>X94>xBxzoA zqOW^Eei--yi!Gf+Yay@jyFzsb|K<&>vwQ9hyBw%3q^_cmTg@`^g0o7i5te4iS-I8b zjRK}UahgV=4K4EI%jEWK&64>M&$cZ20P>mWQy$hlaI%c-&R)&8;!ol!*G(7o~=o=;QNH z%~PS4|Jbtur}HdVC9F)9#tn^|L-lJL#$A$7|6m2UaFbE2TAp;u!!K=y_(cs@uit-dTF%Fu;? zyY@wu5_5q|mR`s#4dQ?HqC`VM@uMEj!x}d<5A^;~WYJ|LDP6RW&$81(gmnf1vcI(0*f|bm9XBbp3^)u*n0@}b>FB!-P_xw z0JW&|Rell4g6FF>{Rai#yp{;lXbrUS_sCP4j5uiY0vo#oI_TX9`=;yce;i>p?9|j`ZE4U`3#f? zu#ul=?$4EhmCgh9V*-F>y|^DO_9+W1cgfX`67TB zcgB(b1}(4IjmS`kmB~%1BCCm)fUAKOU~_!CR~GbXY>b$v?y6gG6)P_VSD4^#Lq68F zbuNj^jS`nGNmi9FP>N_l>NC~mYi_qR`5FI@sl^`i2j64%R4{ucIHF7Q9DPb#9Ew!u znI&dU!F!Z)l(xFaw7a7;*rxJ0-qzu58{YDcw0lFTeS`hTXgg*yAAS4qG z$YVvG!YGXm$Ef4%EoX;jd)RX`-uitGR@gB_Y3aTEZ|hN`0{fkaE2L7Xwh+Gb^cuzL zpx^P$ddSJ11H$HK=OTI`c2_6b zjA7Jcxm%w{J)F}4HMP!oX63o>b251;A{a)kx7Uc+shm5V$7bL}u$I}RX!kcM;*_s8 zH4hjtS%b7|J&r3{@8e30O12marPn^~+5FLSEAxHph16LkDhb7Be@ipFiRK3aG#7+u zW+9r{|1-^r|KDhq;1lM!K=)k5q&-$=%$Z0!ZK~I(b)TW+nvqdC2Q(*w&P=D0`#^~P zT8gOvQ{J zMPWHc&Y@Y;8a8If^Mqu_gm8)Yddb2!=x|aDGcR`glM%;GHfG~=xHiVAV9lWuEwfc_ zNi(i7MM)I4_u#WV^+jCP@+=hdICX)1=r&Ky8S|!JQ}-e6o@^8|VRRJMWvIO^$C*r} zh2{%scv^i6GX*37fv+_9`fcllT>ySCIk}HPPJYG^&U@1^vc4z#^k^4Yw~O@_ zc3p$i7h_CyJPeZTWiFett5k`mLA55Ujt1!qa80AZ&c{j0K7;zDIO{s$gye|k{n&^Z z6oS_<#qNJw%s?Xc9DwV?77vC)BgOxkmTra;24e!0ae0@>M&rUPai5U zX;NHB_1IOq>kg$44XBL*J_E3SGywPv%y|s>h+W{vfzOy@!iNmd%{a*(S#I`Bb+u)$uVSlZmM$&}&6zSaBk?(zfnW8mZ`WykGaV17iIK}+~X za=Q0BMw0w&?Tx+~sQ2185cSU3_6SCpA5PUplg?THrho6u=G)y&Q!GX{!V9mfVcg^w zX=KWoopP66WZ-uy@!V{=KvpYqkwt7HdDBj;pFAq-Z^4==N!mJE*@75s5i!JF!*tU~ zx7V&sfJQ){a>p20G@=w1k9!|h@EaYkk>o6gX9*mAJK8;+-_YFff2G;`Uudoa%{y43 z#n?W|js{W#6i?kY+Bux~p-DQ#m7Lqh1t`|6DrIBu-OZRQ!no$&0lGH@zMLYYd4C5E zzF{4_s9XD6PI&ND0TGu8aN-fc37m9hJ4YifDEKfPT6fPrW9|gr6rC2}Lp`G0b&l6~ zJ0I$NFLv-j?29z2I6HEnF3r>8?&Fs6os``e*FByY?hIciv8T0luWcM84(p4ZqkC>9 ze21a>m>3U%1@@LM2w7_1!+|UX;Mt25iz3#-#Y=bd12zXWF-uR~vxBUN4Z90inWqOU zQ@Z0@4?)Rn2(EUQY}O8Vx@%sghdb3C@N1PBA>eL1t7ZZOpGdSN}y}7m`ygh>uyS6x{1Xdwj>n2EJ?csr6~i>#=WL zJzGX3%1Bas4<4<)%YwTOEHFz4A_|h9Z z4F#u{wCbKe>64#7lWw7SHtg_o8>3DaqU;RL_~zArn2`h@IHl~oJ|2-6+`~U_Yj|ew zp}G%G_i2sPvOQ7^&XCzFNCHN+a&Ub4D`alffd|g_@?hj4+B%HKT#r)DlF%~Y> z9kN?MpQY@4RuVH*@EC@bU*txm{)|44bowGvFtaL{Sqb^cO5LHxe4KFKRBzjkap|DI zc!PrW`O;?5wR$vL5={o>LVrV%1F5)&p&Ck(Cd@?l2}7v{o_U~7G5{$b8!MG8u}a+Gu}=5M9Bc3l*hz&K!lu< z0-ubk%G5F{^On_>@v^*%mR$G}(7YJW65x3aUR_m8i90o>L`sW!T$*IP$34M1K}xr# zxNV9`#?&Zg1P0g*2R!J4lH|^C#&h-H&sK74&Fg`Sq#xks0^_Lum4>ot#U;7LljZKp zFpj-dWw=y^*u|2ZeD2RF;{NuSs;Cp4vEDoR%=FP&)EhKcLnUB5Kue)pP~ zOip_*Ha@-g!@az*t}(BXHL5(pq4Ido_S*4{?6aSEO!Yi#lISV$osiqhwLt&dD)q=O zk(4FUCNb`=MI>2^rA^8!e1*H8Yfl-u4g9OJugZ>;Z7r)PySL0<*00RKw_5QYSS?+@ z)K*8H+V=uDkK~YsY@o0IMuj!!j$v=MZ^-z%tKWy?UfqL}jtouEvg*vkw^$ zhTE~w;eJ;e9BSjPz z5x?bU+t=_*R$&cqga+cPZYxT}PLM}@BLew|6@`I)p+F?TzyjZ-(&5W*KL_f_!4}K+ z2kHb`Kbh%?2s}Y=z@rxQ1g}Y~(l8&o5f?zLL8-ANAxc4bBP?{V#uLCL&|{UuBkZ|o zC3aW>TB{S17xKPv2TE7u0ivJ@o?81}1=@@KENe2A$<1oJ9tZo>Syvrg)4fq`UN7qZ z|G9vXpiJazimwnIZd5b_T%_fA?NjR4|T!$jx4XALzuKcGErTFfs;o(E8i*B+?@$E%rSStq-;l}!SkJDi%gs+hO9)39ETs9%7yp1s{l{lef_ z3Yl=+R?1mIHMwkbwW`$cymZ*^yiSbya*tPJ{kUd(!tkNG;SH4I*C zCw!6W#RFY^T|ApmI?l5hPm#WC;NJI`0huyGmdB%w$$>L_s)0n*yzhxH-mjd3Z|Fx@ zgCSXZe5Ff=D3FdWx{A3}t|5AQ0d%MO8hra`cbF*UDW?w8YD*kXhYAk96ybn#a1ANN5 z`#j8R$I2l?LRtHgE|$`;n>ByIY)4r zG3D+RnnR3q+iM=JCT zyI|p2dCce$yE7s>il}p7PwmEi&{73`3c=?f%}a{JPX4d_4Hb4SULj9jNK3G*)?NcL z-fPwE0T|b@s~d4q%<94_?n51;fO6j2Zihl|5cBQG`UvW^5+%K{MzTuM8$rFX2klrJ zS_GoTLYF*w$Z8Htc2v`bc)vV!S@7y)Oi)-8%ZC*QmA0%FwOl6#)<$7#kji$aj0v23w;?_p581Q$df~n0 z^PcfVL3ooEdb@2s&;ctV2uq(GrsYwNIZq)mU6B z@$z^F`X7Un{h8I|xW|7C5gA*~K&(H)NtrU7I>GXo9NGRBV4z#wio17Czj*HS0TI82 zH_<*Xs(_LX{joDhOR7EzUwt#yN)uZwlF(?MPTY0KnB4)}Keg<7a+g5dJ@D(9oxW8suP(gZLlqZVTYpiSrjX zqPA#dsgAh0W+;CT<7_X2WZ)Z9=v{bVuyKlx5A_ZT#Ge9dA(1ge2*GmiJCPjoC2C^l z?5X|u`c^ESzyTy^H25(4eirgUE2>~A+uv+P{ZJl`P4pM+2YE1J^)K=SoO2(Xtxj3I zNKMP1H*a=fIK-ER3>l(^<8G?yeqYk4Ey-`PP3zs4KmF;6Gbv>+4E0xzd@9X$_@C$A zb3VRm_|}7c?)Wb2S##=-hb9|u-FR=}X9<6Kc>0UuAAIt|z6-B^Usy3`P1oa_XB_?g z?8cSziZUJl{`R%c{}5xpd)xALo|+RcQ}zCj!>^rn>G!>wZa6mhmKE=giaKI!+xTx&s2e8eBAbI&fxqY?%d z{b}B;OuO@*mhXPPbmEi4@7AoZF00?#@cKV|Z@+WqTmQwEx9olGnRP4NV{hv}K-Z~P z)Wr0=bBq5tKmX60UU~D`7nW8we|+GBFTeTW+N8AXnTsEvd*2-+;)m+Zaorv+xxa8S zn>xc_>~6g?srTU3YnFL-*8OGwSFJx@`RB2NN3|)xpZ4e@vmY2XZb%QB$Fs;GK##~ZujU9gbt?K#H zZND7w7Ii(8<9{lvP z_ujhj#pQo*+y2)*8=hXWoXlN+H@N?pVXkSD(-)P_n!Ee2TmM}9+%k9TnP09R{@|m} z9xr!BJSAc1@`@K~HomlXzwe)intr%+;p`ow2B}fq!y;xsR9rGX zb*A&$&tLrOAIJWFWY^}`{<5U%+4UJ&+4nq<_s55OSxxeYGpAI@=2Ni`|ax7?A`f8Z#ZOgSE_rCt; zx+PDoU3KcCx0=5B>f+D$-T%j;X@3}Rik$hY4p@nn*RP6Zugp89P z9(k|z%S---*LH5=%b$M^k%=A&Lq?6u)b5!!Z}y)asaae0WW(RK?mF?|yN79yH`}KTXp7N7q7qlzVGD2rG*bpozBMJIeKv4?$Ji+ zs|#2Deek_wpY7bXf6uZdYo4BDn|asVyvG;nBf8xZpEzPn^YIUk{LuEz>1S&zpL%8A zrkBot`OCGY1D}7q`OnC3Si16sCl)_+pDTMp+Q>Wl4YkC{=1>3m*3rv9e$l#N^>WW& z|FXRhi)9n?D|>G@}>+;8mNvE`$Gc;ETnfA-sOU2N2?{cpc5b)qBp z-ua9ExUv4#*UPJ)TYs+Qr%Qi7eCm^7$$bXK^bG6#Xwd_+e(#(D;~Myr@IQ8sF*Re| zhs%OX#l>)OTs?4&DtO|N$1goF|E(nHzCpiy`trl?mc8@GA9FL>{(St!UA3DRdiVbO znSP_jT{}8*%a<1yoER3Pyxr$e>}vh^-oi%KqIx>p%Zs{zuF3G2!D42{R6UykpkW&z^ns z>!#5UF858|KJTt8|C;^SPUGt(eQ)i#wc$u>^P*l8|MujvqC5B8o2mQ0bN+32zgBVJ zck92nz9wq!XHTtq;g-sC@8=|*s@}M?)0Ssqi^A0b=so*MT?7Z8&2aNdN_aH+(I=_ z@4>?HwmXta`j&)KeqrIl*~P``9jbUDnzi`eduK0H`xb^uG`w$rY0F=f-+rG47!Tb$ z|JJFq?`toj_A>k2+4Bl-#nVjZqeZjD>)_m%^Uwni&41(}wP5~(59U8qD5gPDO<1Mn zFD#z>(0%Icg$w5|R3Dn1zi^D&w>X@%$u@#VL+MkePMI370-!qHme{v&z!?7;=yYE!u#$J?TQN)&MjJ`7A>4#0Mdf6#-gvpzQt&YT8kf?{m>$H(fs-9 zy!q%?fE2jgJ$1Y@eb^{)BFK!u^N8U$o~Nd3wwcb%^vN?rZxV+MXn*;i@1VdTK&hz? zHP9lty#({W{XdFO1`GGAE|L>FpoI7^MqM0YV~EUx2Mfoj7|b98zz8+*Zf)x1F>3Jx zbBokPb7rd;;JJm1^XI9-7R9&TdTW4Q!4GwANHE&j5@c694+BFYcyq^Z{}P7`_-)Z0 zcMye#+vhHP@R9t5v(>w1V_4@ugrQV}|BJDCc-XB;>a5{ppFK+*cAGjpY1nWYHf+rB zHL(b6e)DnBK zD0kvll&1@MjfY_7KlIT2MJk-U`33olW~-@-?^SKHiwo5F_y8Q|+=2&&Wi%W56zw@8mKq{n}913*I-;pxJKei#&tU`hRcR46IT{4 z2QDWr7p@t&cH{chU*rxFhW4eGbb;c)?{%W8r-DY;ANa$4`(L8?Yk%nYt+V|4Pr30I xD%S#k(tr62R!9x}$^Yd~ychQWfBpMy|Dj%Q{QQ@GMUf>`{$IKc6j|C|{2!4@FgpMM literal 0 HcmV?d00001 diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/a4_conn.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/a4_conn.c new file mode 100644 index 000000000..f78350bf9 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/a4_conn.c @@ -0,0 +1,731 @@ +/* + *************************************************************************** + * 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: + a4_conn.c + + Abstract: + This is A4 connection function used to process those 4-addr of connected APClient or STA. + Used by MWDS and MAP feature + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ +#ifdef A4_CONN +#include "rt_config.h" + +#define ETH_TYPE_VLAN 0x8100 +#define ETH_TYPE_IPv4 0x0800 +#define ETH_TYPE_IPv6 0x86dd +#define ETH_TYPE_ARP 0x0806 +#define ETH_TYPE_EAPOL 0x888e +#define ETH_TYPE_WAI 0x88b4 + +BOOLEAN a4_interface_init( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN BOOLEAN is_ap, + IN UCHAR a4_type +) +{ + BSS_STRUCT *mbss = NULL; + BOOLEAN add_inf = FALSE; + + if (is_ap) { + if (if_index >= HW_BEACON_MAX_NUM) + return FALSE; + + mbss = &adapter->ApCfg.MBSSID[if_index]; + if (mbss->a4_init == 0) { + NdisAllocateSpinLock(adapter, &mbss->a4_entry_lock); + DlListInit(&mbss->a4_entry_list); + RoutingTabInit(adapter, if_index, ROUTING_ENTRY_A4); + add_inf = TRUE; + } + mbss->a4_init |= (1 << a4_type); + } +#ifdef APCLI_SUPPORT + else { + PAPCLI_STRUCT apcli_entry; + + if (if_index >= MAX_APCLI_NUM) + return FALSE; + apcli_entry = &adapter->ApCfg.ApCliTab[if_index]; + if (apcli_entry->a4_init == 0) + add_inf = TRUE; + apcli_entry->a4_init |= (1 << a4_type); + } +#else + else + return FALSE; +#endif + + if (add_inf) + adapter->a4_interface_count++; + + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_WARN, ("a4_interface_init a4_interface_count: %d\n", + adapter->a4_interface_count)); + return TRUE; +} + + +BOOLEAN a4_interface_deinit( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN BOOLEAN is_ap, + IN UCHAR a4_type +) +{ + BSS_STRUCT *mbss = NULL; + PA4_CONNECT_ENTRY a4_entry = NULL, pConnEntryTmp = NULL; + PDL_LIST a4_entry_list = NULL; + PMAC_TABLE_ENTRY entry = NULL; + BOOLEAN delete_inf = FALSE; + + if (is_ap) { + if (if_index >= HW_BEACON_MAX_NUM) + return FALSE; + + mbss = &adapter->ApCfg.MBSSID[if_index]; + if (mbss->a4_init) { + a4_entry_list = &mbss->a4_entry_list; + DlListForEachSafe(a4_entry, pConnEntryTmp, a4_entry_list, A4_CONNECT_ENTRY, List) { + if (a4_entry) { + entry = &adapter->MacTab.Content[a4_entry->wcid]; + a4_ap_peer_disable(adapter, entry, a4_type); + } + } + + mbss->a4_init &= ~(1 << a4_type); + if (!mbss->a4_init) { + NdisFreeSpinLock(&mbss->a4_entry_lock); + RoutingTabDestory(adapter, if_index, ROUTING_ENTRY_A4); + delete_inf = TRUE; + } + } + } +#ifdef APCLI_SUPPORT + else { + PAPCLI_STRUCT apcli_entry; + + if (if_index >= MAX_APCLI_NUM) + return FALSE; + apcli_entry = &adapter->ApCfg.ApCliTab[if_index]; + if (apcli_entry->a4_init) { + apcli_entry->a4_init &= ~(1 << a4_type); + if (!apcli_entry->a4_init) + delete_inf = TRUE; + } + } +#else + else + return FALSE; +#endif + + if (delete_inf) + adapter->a4_interface_count--; + + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_WARN, ("a4_interface_init a4_interface_count: %d\n", + adapter->a4_interface_count)); + return TRUE; +} + + +INT a4_get_entry_count( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index +) +{ + int count = 0; + BSS_STRUCT *mbss = NULL; + + if (if_index >= HW_BEACON_MAX_NUM) + return 0; + + mbss = &adapter->ApCfg.MBSSID[if_index]; + + if (!mbss->a4_init) + return 0; + + count = DlListLen(&mbss->a4_entry_list); + return count; +} + + +BOOLEAN a4_lookup_entry_by_wcid( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN UCHAR wcid +) +{ + BSS_STRUCT *mbss = NULL; + PDL_LIST a4_entry_list = NULL; + PA4_CONNECT_ENTRY a4_entry = NULL; + BOOLEAN found = FALSE; + + if (a4_get_entry_count(adapter, if_index) == 0) + return FALSE; + + mbss = &adapter->ApCfg.MBSSID[if_index]; + a4_entry_list = &mbss->a4_entry_list; + DlListForEach(a4_entry, a4_entry_list, A4_CONNECT_ENTRY, List) { + if (a4_entry && + a4_entry->valid && + (a4_entry->wcid == wcid)) { + found = TRUE; + break; + } + } + return found; +} + + +BOOLEAN a4_lookup_entry_by_addr( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN PUCHAR mac_addr +) +{ + BSS_STRUCT *mbss = NULL; + PDL_LIST a4_entry_list = NULL; + PA4_CONNECT_ENTRY a4_entry = NULL; + PMAC_TABLE_ENTRY entry = NULL; + BOOLEAN found = FALSE; + + if ((a4_get_entry_count(adapter, if_index) == 0) || + (mac_addr == NULL)) + return FALSE; + + mbss = &adapter->ApCfg.MBSSID[if_index]; + a4_entry_list = &mbss->a4_entry_list; + DlListForEach(a4_entry, a4_entry_list, A4_CONNECT_ENTRY, List) { + if (a4_entry && a4_entry->valid && VALID_WCID(a4_entry->wcid)) { + entry = &adapter->MacTab.Content[a4_entry->wcid]; + + if (MAC_ADDR_EQUAL(mac_addr, entry->Addr)) { + found = TRUE; + break; + } + } + } + return found; +} + + +VOID a4_add_entry( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN UCHAR wcid +) +{ + BSS_STRUCT *mbss = NULL; + PA4_CONNECT_ENTRY a4_entry = NULL; + + if (a4_lookup_entry_by_wcid(adapter, if_index, wcid)) + return; + + mbss = &adapter->ApCfg.MBSSID[if_index]; + os_alloc_mem(adapter, (UCHAR **)&a4_entry, sizeof(A4_CONNECT_ENTRY)); + + if (a4_entry) { + NdisZeroMemory(a4_entry, sizeof(A4_CONNECT_ENTRY)); + a4_entry->valid = 1; + a4_entry->wcid = wcid; + RTMP_SEM_LOCK(&mbss->a4_entry_lock); + DlListAddTail(&mbss->a4_entry_list, &a4_entry->List); + RTMP_SEM_UNLOCK(&mbss->a4_entry_lock); + } else + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s: Fail to alloc memory for pNewConnEntry\n", __func__)); +} + + +VOID a4_delete_entry( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN UCHAR wcid +) +{ + BSS_STRUCT *mbss = NULL; + PA4_CONNECT_ENTRY a4_entry = NULL; + PDL_LIST a4_entry_list = NULL; + + if (a4_get_entry_count(adapter, if_index) == 0) + return; + + mbss = &adapter->ApCfg.MBSSID[if_index]; + a4_entry_list = &mbss->a4_entry_list; + RTMP_SEM_LOCK(&mbss->a4_entry_lock); + DlListForEach(a4_entry, a4_entry_list, A4_CONNECT_ENTRY, List) { + if (a4_entry && + a4_entry->valid && + (a4_entry->wcid == wcid)) { + DlListDel(&a4_entry->List); + os_free_mem(adapter, a4_entry); + break; + } + } + RTMP_SEM_UNLOCK(&mbss->a4_entry_lock); +} + + +VOID a4_proxy_delete( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN PUCHAR mac_addr +) +{ + if (a4_get_entry_count(adapter, if_index) == 0) + return; + + RoutingTabSetOneFree(adapter, if_index, mac_addr, ROUTING_ENTRY_A4); +} + +BOOLEAN a4_get_dst_ip(void *pkt, unsigned char *ip) +{ + UCHAR *pSrcBuf; + UINT16 TypeLen; + UINT32 type_len_idx = 12; + UCHAR *ip_header = NULL; + + pSrcBuf = pkt; + TypeLen = (pSrcBuf[type_len_idx] << 8) | pSrcBuf[type_len_idx + 1]; + while (TypeLen == ETH_TYPE_VLAN) { + type_len_idx += 2; + TypeLen = (pSrcBuf[type_len_idx] << 8) | pSrcBuf[type_len_idx + 1]; + } + if (TypeLen == ETH_TYPE_IPv4) { + ip_header = &pSrcBuf[type_len_idx + 2]; + NdisCopyMemory(ip, ip_header + 16, 4); + return TRUE; + } + return FALSE; +} + +BOOLEAN a4_proxy_lookup( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN PUCHAR mac_addr, + IN BOOLEAN update_alive_time, + IN BOOLEAN is_rx, + OUT UCHAR *wcid +) +{ +#ifdef WAPP_SUPPORT + UINT8 ip[4] = {0}; +#endif + + *wcid = 0; + + if (a4_get_entry_count(adapter, if_index) == 0) { +#ifdef WAPP_SUPPORT + if (!is_rx && a4_get_dst_ip(mac_addr, ip)) + wapp_send_a4_entry_missing(adapter, if_index, ip); +#endif + return FALSE; + } + + if (RoutingTabLookup(adapter, if_index, mac_addr, update_alive_time, wcid) != NULL) + return TRUE; + else { +#ifdef WAPP_SUPPORT + if (!is_rx && a4_get_dst_ip(mac_addr, ip)) + wapp_send_a4_entry_missing(adapter, if_index, ip); +#endif + return FALSE; + } +} + + +VOID a4_proxy_update( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN UCHAR wcid, + IN PUCHAR mac_addr, + IN UINT32 ip /* ARP Sender IP*/ +) +{ + UCHAR proxy_wcid = 0; + BOOLEAN found = FALSE; + PROUTING_ENTRY routing_entry = NULL; + + if (a4_get_entry_count(adapter, if_index) == 0) + return; + + if (!VALID_WCID(wcid) || !mac_addr) + return; + + routing_entry = RoutingTabLookup(adapter, if_index, mac_addr, TRUE, &proxy_wcid); + found = (routing_entry != NULL) ? TRUE : FALSE; + + if (found) { + if (ROUTING_ENTRY_TEST_FLAG(routing_entry, ROUTING_ENTRY_A4)) { + /* Mean the target change to other ProxyAP */ + if (proxy_wcid != wcid) { + RoutingTabSetOneFree(adapter, if_index, mac_addr, ROUTING_ENTRY_A4); + routing_entry = NULL; + found = FALSE; + } + } else { + /* Assign A4 falg to this one if found. */ + SET_ROUTING_ENTRY(routing_entry, ROUTING_ENTRY_A4); + } + } + + if (!found) { + /* Allocate a new one if not found. */ + routing_entry = RoutingTabGetFree(adapter, if_index); + + if (routing_entry) { + SET_ROUTING_ENTRY(routing_entry, ROUTING_ENTRY_A4); + RoutingEntrySet(adapter, if_index, wcid, mac_addr, routing_entry); + } + } + + if (routing_entry != NULL && (ip != 0)) /* ARP Sender IP Update*/ + RoutingTabARPLookupUpdate(adapter, if_index, routing_entry, ip); +} + + +VOID a4_proxy_maintain( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index +) +{ + if (a4_get_entry_count(adapter, if_index) == 0) + return; + + RoutingTabMaintain(adapter, if_index); +} + + +INT a4_hard_transmit( + IN PRTMP_ADAPTER adapter, + IN struct wifi_dev *wdev, + IN PNDIS_PACKET pkt +) +{ + INT ret = NDIS_STATUS_SUCCESS; + + if (wdev->tx_pkt_handle) + ret = wdev->tx_pkt_handle(adapter, pkt); + + return ret; +} + +PNDIS_PACKET a4_clone_packet( + IN PRTMP_ADAPTER adapter, + IN PNET_DEV if_dev, + IN PNDIS_PACKET pkt +) +{ + struct sk_buff *skb = NULL; + PNDIS_PACKET pkt_clone = NULL; + + skb = skb_copy(RTPKT_TO_OSPKT(pkt), GFP_ATOMIC); + + if (skb) { + skb->dev = if_dev; + pkt_clone = OSPKT_TO_RTPKT(skb); + } + + return pkt_clone; +} + +void a4_send_clone_pkt( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN PNDIS_PACKET pkt, + IN PUCHAR exclude_mac_addr +) +{ + struct wifi_dev *wdev = NULL; + PNDIS_PACKET pkt_clone = NULL; + PDL_LIST a4_entry_list = NULL; + PA4_CONNECT_ENTRY a4_entry = NULL; + PROUTING_ENTRY routing_entry = NULL; + PMAC_TABLE_ENTRY entry = NULL; + BOOLEAN found = FALSE; + UCHAR wcid = 0; +#if (defined(WH_EZ_SETUP) && defined(EZ_DUAL_BAND_SUPPORT)) + struct wifi_dev *ap_wdev = NULL; + BOOLEAN drop_pkt_to_dup_ez_apcli = FALSE; +#endif + + if (!pkt) + return; + + if ((a4_get_entry_count(adapter, if_index) > 0)) { +#if (defined(WH_EZ_SETUP) && defined(EZ_DUAL_BAND_SUPPORT)) + ap_wdev = &adapter->ApCfg.MBSSID[if_index].wdev; + +#endif + + if (exclude_mac_addr) { + routing_entry = RoutingTabLookup(adapter, if_index, exclude_mac_addr, FALSE, &wcid); + + if (routing_entry && ROUTING_ENTRY_TEST_FLAG(routing_entry, ROUTING_ENTRY_A4)) + found = TRUE; + else + found = FALSE; + } + + a4_entry_list = &adapter->ApCfg.MBSSID[if_index].a4_entry_list; + DlListForEach(a4_entry, a4_entry_list, A4_CONNECT_ENTRY, List) { + if (a4_entry && a4_entry->valid && VALID_WCID(a4_entry->wcid)) { + if (found && (wcid == a4_entry->wcid)) + continue; + + entry = &adapter->MacTab.Content[a4_entry->wcid]; + wdev = entry->wdev; + +#if (defined(WH_EZ_SETUP) && defined(EZ_DUAL_BAND_SUPPORT)) + + if ((wdev->enable_easy_setup) +#ifdef EZ_API_SUPPORT + && (wdev->ez_security.ez_api_mode != CONNECTION_OFFLOAD) +#endif + ) { + /* todo: fill it based on ez_peer_securtity cli_duplicate info */ + if (drop_pkt_to_dup_ez_apcli && entry->link_duplicate) { + continue; + } + } + +#endif + pkt_clone = a4_clone_packet(adapter, wdev->if_dev, pkt); + if (pkt_clone == NULL) { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s: Fail to alloc memory for pPacketClone\n", __func__)); + return; + } + + RTMP_SET_PACKET_WCID(pkt_clone, entry->wcid); + RTMP_SET_PACKET_WDEV(pkt_clone, wdev->wdev_idx); + RTMP_SET_PACKET_MOREDATA(pkt_clone, FALSE); + /*RTMP_SET_PACKET_QUEIDX(pPacketClone, QID_AC_BE);*/ + a4_hard_transmit(adapter, wdev, pkt_clone); + } + } + } +} + + +BOOLEAN a4_ap_peer_enable( + IN PRTMP_ADAPTER adapter, + IN PMAC_TABLE_ENTRY entry, + IN UCHAR type +) +{ + BSS_STRUCT *mbss = NULL; + UCHAR if_index; + + if (!entry || !IS_ENTRY_CLIENT(entry)) + return FALSE; + + if_index = entry->func_tb_idx; + if (if_index >= HW_BEACON_MAX_NUM) + return FALSE; + + mbss = &adapter->ApCfg.MBSSID[if_index]; +#ifdef WSC_AP_SUPPORT + if (mbss && + (mbss->WscControl.WscConfMode != WSC_DISABLE) && + (mbss->WscControl.bWscTrigger == TRUE)) { + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s fail due to wps\n", __func__)); + return FALSE; + } +#endif /* WSC_AP_SUPPORT */ + + if (IS_ENTRY_A4(entry) == FALSE) { + /* To check and remove entry which is created from another side. */ + a4_proxy_delete(adapter, if_index, entry->Addr); + a4_add_entry(adapter, if_index, entry->wcid); + } + + if (type > GET_ENTRY_A4(entry)) { + SET_ENTRY_A4(entry, type); + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("SET_A4_ENTRY type:%d OK!\n", type)); + } + + return TRUE; +} + + +BOOLEAN a4_ap_peer_disable( + IN PRTMP_ADAPTER adapter, + IN PMAC_TABLE_ENTRY entry, + IN UCHAR type +) +{ + UCHAR if_index; + + if (!entry || !IS_ENTRY_CLIENT(entry)) + return FALSE; + + if_index = entry->func_tb_idx; + if (if_index >= HW_BEACON_MAX_NUM) + return FALSE; + + if (type == GET_ENTRY_A4(entry)) { + SET_ENTRY_A4(entry, A4_TYPE_NONE); + a4_delete_entry(adapter, if_index, entry->wcid); + RoutingTabSetAllFree(adapter, if_index, entry->wcid, ROUTING_ENTRY_A4); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_WARN, + ("a4_ap_peer_disable: Disable A4 for entry : %02x-%02x-%02x-%02x-%02x-%02x\n", + PRINT_MAC(entry->Addr))); + } + + return TRUE; +} + + +#ifdef APCLI_SUPPORT +BOOLEAN a4_apcli_peer_enable( + IN PRTMP_ADAPTER adapter, + IN PAPCLI_STRUCT apcli_entry, + IN PMAC_TABLE_ENTRY entry, + IN UCHAR type +) +{ + if (!apcli_entry || !entry || !IS_ENTRY_APCLI(entry)) + return FALSE; + +#ifdef WSC_AP_SUPPORT + if (((apcli_entry->WscControl.WscConfMode != WSC_DISABLE) && + (apcli_entry->WscControl.bWscTrigger == TRUE))) + return FALSE; +#endif /* WSC_AP_SUPPORT */ + + if (IS_ENTRY_A4(entry) == FALSE) + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_WARN, + ("%s entry:%02x-%02x-%02x-%02x-%02x-%02x\n", + __func__, PRINT_MAC(entry->Addr))); + + if (type > GET_ENTRY_A4(entry)) { + SET_APCLI_A4(apcli_entry, type); + SET_ENTRY_A4(entry, type); + } + return TRUE; +} + + +BOOLEAN a4_apcli_peer_disable( + IN PRTMP_ADAPTER adapter, + IN PAPCLI_STRUCT apcli_entry, + IN PMAC_TABLE_ENTRY entry, + IN UCHAR type +) +{ + + if (!apcli_entry || !entry) + return FALSE; + + if (type == GET_ENTRY_A4(entry)) { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_WARN, + ("a4_apcli_peer_disable, Disable A4 for entry:%02x-%02x-%02x-%02x-%02x-%02x\n", + PRINT_MAC(entry->Addr))); + SET_APCLI_A4(apcli_entry, A4_TYPE_NONE); + SET_ENTRY_A4(entry, A4_TYPE_NONE); + } + + return TRUE; +} +#endif /* APCLI_SUPPORT */ + + +INT Set_APProxy_Status_Show_Proc( + IN PRTMP_ADAPTER adapter, + IN RTMP_STRING *arg) +{ + POS_COOKIE obj; + UCHAR if_index; + INT32 i, count = 0; + UINT32 ip_addr = 0; + ULONG now = 0, AliveTime = 0; + PDL_LIST a4_entry_list = NULL; + PA4_CONNECT_ENTRY a4_entry = NULL; + PROUTING_ENTRY routing_entry = NULL, *routing_entry_list[ROUTING_POOL_SIZE]; + UCHAR *proxy_mac_addr = NULL, proxy_ip[64]; + + obj = (POS_COOKIE) adapter->OS_Cookie; + if_index = obj->ioctl_if; + + if ((obj->ioctl_if_type != INT_MBSSID) && (obj->ioctl_if_type != INT_MAIN)) + return FALSE; + + if (a4_get_entry_count(adapter, if_index) == 0) + return TRUE; + + a4_entry_list = &adapter->ApCfg.MBSSID[if_index].a4_entry_list; + NdisGetSystemUpTime(&now); + DlListForEach(a4_entry, a4_entry_list, A4_CONNECT_ENTRY, List) { + if (a4_entry && a4_entry->valid && VALID_WCID(a4_entry->wcid)) { + count = 0; + proxy_mac_addr = adapter->MacTab.Content[a4_entry->wcid].Addr; + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("Proxy Mac: %02X:%02X:%02X:%02X:%02X:%02X\n", + PRINT_MAC(proxy_mac_addr))); + + if (GetRoutingEntryAll(adapter, if_index, a4_entry->wcid, ROUTING_ENTRY_A4, + ROUTING_POOL_SIZE, (ROUTING_ENTRY **)&routing_entry_list, &count)) { + for (i = 0; i < count; i++) { + routing_entry = (PROUTING_ENTRY)routing_entry_list[i]; + + if (!routing_entry) + continue; + + if (routing_entry->KeepAliveTime >= now) + AliveTime = ((routing_entry->KeepAliveTime - now) / OS_HZ); + else + AliveTime = 0; + + if (routing_entry->IPAddr != 0) { + ip_addr = routing_entry->IPAddr; + sprintf(proxy_ip, "%d.%d.%d.%d", + (ip_addr & 0xff), + ((ip_addr & (0xff << 8)) >> 8), + ((ip_addr & (0xff << 16)) >> 16), + ((ip_addr & (0xff << 24)) >> 24)); + } else + strcpy(proxy_ip, "0.0.0.0"); + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("MAC:%02X:%02X:%02X:%02X:%02X:%02X, IP:%s, AgeOut:%lus, Retry:(%d,%d)\n", + PRINT_MAC(routing_entry->Mac), proxy_ip, AliveTime, + routing_entry->Retry, ROUTING_ENTRY_MAX_RETRY)); + } + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("Total Count = %d\n\n", count)); + } + } + } + return TRUE; +} + +INT Set_APProxy_Refresh_Proc( + IN PRTMP_ADAPTER adapter, + IN RTMP_STRING * arg) +{ + adapter->a4_need_refresh = TRUE; + return TRUE; +} + +#endif /* A4_CONN */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/action.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/action.c new file mode 100644 index 000000000..1651e3e20 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/action.c @@ -0,0 +1,1185 @@ +/**************************************************************************** + * 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 WH_EZ_SETUP +extern UCHAR mtk_oui[]; +#endif + +static VOID ReservedAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + + + +/* + ========================================================================== + Description: + association state machine init, including state transition and timer init + Parameters: + S - pointer to the association state machine + Note: + The state machine looks like the following + + ASSOC_IDLE + MT2_MLME_DISASSOC_REQ mlme_disassoc_req_action + MT2_PEER_DISASSOC_REQ peer_disassoc_action + MT2_PEER_ASSOC_REQ drop + MT2_PEER_REASSOC_REQ drop + MT2_CLS3ERR cls3err_action + ========================================================================== + */ +VOID ActionStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_ACT_STATE, MAX_ACT_MSG, (STATE_MACHINE_FUNC)Drop, ACT_IDLE, ACT_MACHINE_BASE); + + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_SPECTRUM_CATE, (STATE_MACHINE_FUNC)PeerSpectrumAction); + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_QOS_CATE, (STATE_MACHINE_FUNC)PeerQOSAction); + + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_DLS_CATE, (STATE_MACHINE_FUNC)ReservedAction); + +#ifdef DOT11_N_SUPPORT + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_BA_CATE, (STATE_MACHINE_FUNC)PeerBAAction); + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_HT_CATE, (STATE_MACHINE_FUNC)PeerHTAction); +#ifdef DOT11_VHT_AC + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_VHT_CATE, (STATE_MACHINE_FUNC)PeerVHTAction); +#endif /* DOT11_VHT_AC */ + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ADD_BA_CATE, (STATE_MACHINE_FUNC)MlmeADDBAAction); + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_ORI_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction); + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_REC_DELBA_CATE, (STATE_MACHINE_FUNC)MlmeDELBAAction); +#endif /* DOT11_N_SUPPORT */ + + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_PUBLIC_CATE, (STATE_MACHINE_FUNC)PeerPublicAction); + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_RM_CATE, (STATE_MACHINE_FUNC)PeerRMAction); + + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_QOS_CATE, (STATE_MACHINE_FUNC)MlmeQOSAction); + StateMachineSetAction(S, ACT_IDLE, MT2_MLME_DLS_CATE, (STATE_MACHINE_FUNC)MlmeDLSAction); + StateMachineSetAction(S, ACT_IDLE, MT2_ACT_INVALID, (STATE_MACHINE_FUNC)MlmeInvalidAction); + + +#ifdef CONFIG_AP_SUPPORT +#ifdef DOT11R_FT_SUPPORT + StateMachineSetAction(S, ACT_IDLE, FT_CATEGORY_BSS_TRANSITION, (STATE_MACHINE_FUNC)FT_FtAction); +#endif /* DOT11R_FT_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT + StateMachineSetAction(S, ACT_IDLE, MT2_PEER_PMF_CATE, (STATE_MACHINE_FUNC)PMF_PeerAction); +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + StateMachineSetAction(S, ACT_IDLE, WNM_CATEGORY_BSS_TRANSITION, (STATE_MACHINE_FUNC)WNM_Action); +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef CONFIG_DOT11V_WNM + StateMachineSetAction(S, ACT_IDLE, CATEGORY_WNM, (STATE_MACHINE_FUNC)PeerWNMAction); +#endif /* CONFIG_DOT11V_WNM */ +} + + +#ifdef DOT11_N_SUPPORT +VOID MlmeADDBAAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + MLME_ADDBA_REQ_STRUCT *pInfo; + UCHAR Addr[6]; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG Idx; + FRAME_ADDBA_REQ Frame; + ULONG FrameLen; + //BA_ORI_ENTRY *pBAEntry = NULL; + MAC_TABLE_ENTRY *pEntry = NULL; + //STA_TR_ENTRY *tr_entry; + struct wifi_dev *wdev; + + pInfo = (MLME_ADDBA_REQ_STRUCT *)Elem->Msg; + NdisZeroMemory(&Frame, sizeof(FRAME_ADDBA_REQ)); + + if(MlmeAddBAReqSanity(pAd, Elem->Msg, Elem->MsgLen, Addr) && + VALID_WCID(pInfo->Wcid)) + { + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory*/ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeADDBAAction() allocate memory failed \n")); + return; + } + /* 1. find entry */ + pEntry = &pAd->MacTab.Content[pInfo->Wcid]; + //tr_entry = &pAd->MacTab.tr_entry[pInfo->Wcid]; + ASSERT((pEntry->wdev != NULL)); + wdev = pEntry->wdev; + + Idx = pEntry->BAOriWcidArray[pInfo->TID]; + if (Idx == 0) + { + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() can't find BAOriEntry \n")); + return; + } + else + { + //pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + } + +#ifdef APCLI_SUPPORT +#ifdef MAC_REPEATER_SUPPORT + if (IS_ENTRY_APCLI(pEntry) && (pEntry->bReptCli == TRUE)) { + INT idx = pEntry->func_tb_idx; + ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, + pAd->ApCfg.ApCliTab[idx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress, + pInfo->pAddr); + } + else +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* APCLI_SUPPORT */ + ActHeaderInit(pAd, &Frame.Hdr, pInfo->pAddr, wdev->if_addr, wdev->bssid); + + Frame.Category = CATEGORY_BA; + Frame.Action = ADDBA_REQ; + Frame.BaParm.AMSDUSupported = 0; +#ifdef WFA_VHT_PF + if (IS_VHT_STA(pEntry) && pAd->CommonCfg.DesiredHtPhy.AmsduEnable) + Frame.BaParm.AMSDUSupported = 1; +#endif /* WFA_VHT_PF */ + Frame.BaParm.BAPolicy = IMMED_BA; + Frame.BaParm.TID = pInfo->TID; + Frame.BaParm.BufSize = pInfo->BaBufSize; + Frame.Token = pInfo->Token; + Frame.TimeOutValue = pInfo->TimeOutValue; + Frame.BaStartSeq.field.FragNum = 0; + Frame.BaStartSeq.field.StartSeq = AsicGetTidSn(pAd, pInfo->Wcid, pInfo->TID); + +#ifdef UNALIGNMENT_SUPPORT + { + BA_PARM tmpBaParm; + + NdisMoveMemory((PUCHAR)(&tmpBaParm), (PUCHAR)(&Frame.BaParm), sizeof(BA_PARM)); + *(USHORT *)(&tmpBaParm) = cpu2le16(*(USHORT *)(&tmpBaParm)); + NdisMoveMemory((PUCHAR)(&Frame.BaParm), (PUCHAR)(&tmpBaParm), sizeof(BA_PARM)); + } +#else + *(USHORT *)(&(Frame.BaParm)) = cpu2le16((*(USHORT *)(&(Frame.BaParm)))); +#endif /* UNALIGNMENT_SUPPORT */ + + Frame.TimeOutValue = cpu2le16(Frame.TimeOutValue); + Frame.BaStartSeq.word = cpu2le16(Frame.BaStartSeq.word); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ADDBA_REQ), &Frame, + END_OF_ARGS); + + MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | WMM_UP2AC_MAP[pInfo->TID]), pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, + ("BA - Send ADDBA request. StartSeq = %x, FrameLen = %ld. BufSize = %d\n", + Frame.BaStartSeq.field.StartSeq, FrameLen, Frame.BaParm.BufSize)); + } +} + + +/* + ========================================================================== + Description: + send DELBA and delete BaEntry if any + Parametrs: + Elem - MLME message MLME_DELBA_REQ_STRUCT + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeDELBAAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + MLME_DELBA_REQ_STRUCT *pInfo; + PUCHAR pOutBuffer = NULL, pOutBuffer2 = NULL; + //ULONG Idx; + FRAME_DELBA_REQ Frame; + ULONG FrameLen; +#if defined(RTMP_MAC) || defined(RTL_MAC) + FRAME_BAR FrameBar; +#endif + MAC_TABLE_ENTRY *pEntry = NULL; + struct wifi_dev *wdev; + UCHAR *src_addr = NULL; + + pInfo = (MLME_DELBA_REQ_STRUCT *)Elem->Msg; + /* must send back DELBA */ + NdisZeroMemory(&Frame, sizeof(FRAME_DELBA_REQ)); + DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeDELBAAction(), Initiator(%d) \n", pInfo->Initiator)); + + if(MlmeDelBAReqSanity(pAd, Elem->Msg, Elem->MsgLen) && + VALID_WCID(pInfo->Wcid)) + { + if(MlmeAllocateMemory(pAd, &pOutBuffer) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeDELBAAction() allocate memory failed 1. \n")); + return; + } + + if(MlmeAllocateMemory(pAd, &pOutBuffer2) != NDIS_STATUS_SUCCESS) + { + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_ERROR, ("BA - MlmeDELBAAction() allocate memory failed 2. \n")); + return; + } + + /* SEND BAR (Send BAR to refresh peer reordering buffer.) */ + pEntry = &pAd->MacTab.Content[pInfo->Wcid]; + if (!pEntry->wdev) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():No binding wdev for wcid(%d)\n", __FUNCTION__, pInfo->Wcid)); + MlmeFreeMemory(pAd, pOutBuffer); + MlmeFreeMemory(pAd, pOutBuffer2); + return; + } + + wdev = pEntry->wdev; + //Idx = pEntry->BAOriWcidArray[pInfo->TID]; +#ifdef APCLI_SUPPORT +#ifdef MAC_REPEATER_SUPPORT + if (IS_ENTRY_APCLI(pEntry) && pEntry->bReptCli) + { + UINT apidx = pEntry->func_tb_idx; + src_addr = &pAd->ApCfg.ApCliTab[apidx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress[0]; + } + else +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* APCLI_SUPPORT */ + src_addr = wdev->if_addr; + +#if defined(RTMP_MAC) || defined(RTL_MAC) + if ((pAd->chipCap.hif_type == HIF_RTMP) || (pAd->chipCap.hif_type == HIF_RLT)) + { + BarHeaderInit(pAd, &FrameBar, pEntry->Addr, src_addr); + + FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL funciton.*/ + FrameBar.StartingSeq.field.StartSeq = pAd->MacTab.tr_entry[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, (MGMT_USE_QUEUE_FLAG & QID_AC_BE), pOutBuffer2, FrameLen); + DBGPRINT(RT_DEBUG_TRACE,("BA - MlmeDELBAAction() . Send BAR to refresh peer reordering buffer \n")); + } +#endif + + /* SEND DELBA FRAME*/ + FrameLen = 0; + + ActHeaderInit(pAd, &Frame.Hdr, pEntry->Addr, src_addr, pEntry->wdev->bssid); + + 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); + MlmeFreeMemory(pAd, pOutBuffer2); + DBGPRINT(RT_DEBUG_TRACE, ("BA - MlmeDELBAAction() . 3 DELBA sent. Initiator(%d)\n", pInfo->Initiator)); + } +} +#endif /* DOT11_N_SUPPORT */ + + +VOID MlmeQOSAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ +#if defined(CONFIG_AP_SUPPORT) && defined(CONFIG_HOTSPOT_R2) + MLME_QOS_ACTION_STRUCT *pInfo; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + NDIS_STATUS NStatus; + FRAME_ACTION_HDR Frame; + pInfo = (MLME_QOS_ACTION_STRUCT *)Elem->Msg; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ACT - MlmeQOSAction() allocate memory failed \n")); + return; + } + + if (pInfo->ActionField == ACTION_QOSMAP_CONFIG) + { + UCHAR OosMapIE = IE_QOS_MAP_SET; + QOSMAP_SET *pQosMapBuf = &pInfo->QOSMap; + BSS_STRUCT *mbss = &pAd->ApCfg.MBSSID[pInfo->apidx]; + UCHAR ielen = 0; + + ActHeaderInit(pAd, &Frame.Hdr, pInfo->Addr, mbss->wdev.bssid, mbss->wdev.bssid); + + Frame.Category = CATEGORY_QOS; + Frame.Action = ACTION_QOSMAP_CONFIG; + + ielen = pQosMapBuf->DSCP_Field_Len; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ACTION_HDR), &Frame, + 1, &OosMapIE, + 1, &ielen, + ielen, pQosMapBuf->DSCP_Field, + END_OF_ARGS); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + } + + MlmeFreeMemory(pAd, pOutBuffer); +#endif /* defined(CONFIG_AP_SUPPORT) && defined(CONFIG_HOTSPOT_R2) */ +} + + +VOID MlmeDLSAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ +} + + +VOID MlmeInvalidAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + /*PUCHAR pOutBuffer = NULL;*/ + /*Return the receiving frame except the MSB of category filed set to 1. 7.3.1.11*/ +} + + +VOID PeerQOSAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ +} + + + + + + +#ifdef DOT11_N_SUPPORT +VOID PeerBAAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + switch(Action) + { + case ADDBA_REQ: + PeerAddBAReqAction(pAd,Elem); + break; + case ADDBA_RESP: + PeerAddBARspAction(pAd,Elem); + break; + case DELBA: + PeerDelBAAction(pAd,Elem); + break; + } +} + + +#ifdef DOT11N_DRAFT3 +#ifdef CONFIG_AP_SUPPORT +extern UCHAR get_regulatory_class(PRTMP_ADAPTER pAd, UCHAR Channel); + +VOID ApPublicAction(RTMP_ADAPTER *pAd, 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 RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR apidx, + IN UCHAR InfoReq) +{ + UCHAR *pOutBuffer = NULL; + NDIS_STATUS NStatus; + FRAME_ACTION_HDR Frame; + ULONG FrameLen; + BSS_2040_COEXIST_ELEMENT BssCoexistInfo; + BSS_2040_INTOLERANT_CH_REPORT BssIntolerantInfo; + UCHAR *pAddr1; + struct wifi_dev *wdev; + + DBGPRINT(RT_DEBUG_TRACE, ("SendBSS2040CoexistMgmtAction(): Wcid=%d, apidx=%d, InfoReq=%d!\n", Wcid, apidx, InfoReq)); + + NdisZeroMemory((PUCHAR)&BssCoexistInfo, sizeof(BSS_2040_COEXIST_ELEMENT)); + NdisZeroMemory((PUCHAR)&BssIntolerantInfo, sizeof(BSS_2040_INTOLERANT_CH_REPORT)); + + BssCoexistInfo.ElementID = IE_2040_BSS_COEXIST; + BssCoexistInfo.Len = 1; + BssCoexistInfo.BssCoexistIe.word = pAd->CommonCfg.LastBSSCoexist2040.word; + BssCoexistInfo.BssCoexistIe.field.InfoReq = InfoReq; + BssIntolerantInfo.ElementID = IE_2040_BSS_INTOLERANT_REPORT; + BssIntolerantInfo.Len = 1; + BssIntolerantInfo.RegulatoryClass = get_regulatory_class(pAd, 0); + + 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; + } + + pAddr1 = pAd->MacTab.Content[Wcid].Addr; + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + ActHeaderInit(pAd, &Frame.Hdr, pAddr1, wdev->if_addr, wdev->bssid); + + Frame.Category = CATEGORY_PUBLIC; + Frame.Action = ACTION_BSS_2040_COEXIST; + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ACTION_HDR), &Frame, + sizeof(BSS_2040_COEXIST_ELEMENT), &BssCoexistInfo, + sizeof(BSS_2040_INTOLERANT_CH_REPORT), &BssIntolerantInfo, + END_OF_ARGS); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_ERROR,("ACT - SendBSS2040CoexistMgmtAction(BSSCoexist2040=0x%x)\n", BssCoexistInfo.BssCoexistIe.word)); + +} +#endif /* CONFIG_AP_SUPPORT */ + + + + +BOOLEAN ChannelSwitchSanityCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR NewChannel, + IN UCHAR Secondary) +{ + UCHAR i; + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + + if ((NewChannel > 7) && (Secondary == 1)) + return FALSE; + + if ((NewChannel < 5) && (Secondary == 3)) + return FALSE; + + /* 0. Check if new channel is in the channellist.*/ + for (i = 0;i < pAd->ChannelListNum;i++) + { + if (pAd->ChannelList[i].Channel == NewChannel) + { + break; + } + } + + if (i == pAd->ChannelListNum) + return FALSE; + + return TRUE; +} + + +VOID ChannelSwitchAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR NewChannel, + IN UCHAR Secondary) +{ + UCHAR rf_channel = 0, rf_bw; + + DBGPRINT(RT_DEBUG_TRACE,("%s(): NewChannel=%d, Secondary=%d\n", + __FUNCTION__, NewChannel, Secondary)); + + if (ChannelSwitchSanityCheck(pAd, Wcid, NewChannel, Secondary) == FALSE) + return; + + pAd->CommonCfg.Channel = NewChannel; + if (Secondary == EXTCHA_NONE) + { + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 0; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = 0; + + rf_bw = BW_20; + rf_channel = pAd->CommonCfg.Channel; + } + /* 1. Switch to BW = 40 And Station supports BW = 40.*/ + else if (((Secondary == EXTCHA_ABOVE) || (Secondary == EXTCHA_BELOW)) && + (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == 1) + ) + { + rf_bw = BW_40; +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == 1) + { + rf_bw = BW_20; + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + } + else +#endif /* GREENAP_SUPPORT */ + if (Secondary == EXTCHA_ABOVE) + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; + else + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; + + rf_channel = pAd->CommonCfg.CentralChannel; + pAd->MacTab.Content[Wcid].HTPhyMode.field.BW = 1; + } + + if (rf_channel != 0) { + AsicSetChannel(pAd, rf_channel, rf_bw, Secondary, FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): %dMHz LINK UP, CtrlChannel=%d, CentralChannel= %d \n", + __FUNCTION__, (rf_bw == BW_40 ? 40 : 20), + pAd->CommonCfg.Channel, + pAd->CommonCfg.CentralChannel)); + } +} +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + +VOID PeerPublicAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + +#if defined(WAPP_SUPPORT) && defined(CONFIG_AP_SUPPORT) && defined(DOT11U_INTERWORKING) + if (!GasEnable(pAd, Elem)) +#endif + if ((Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + ) + return; + + + switch(Action) + { +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + case ACTION_BSS_2040_COEXIST: /* Format defined in IEEE 7.4.7a.1 in 11n Draf3.03*/ + { + /*UCHAR BssCoexist;*/ + BSS_2040_COEXIST_ELEMENT *pCoexistInfo; + BSS_2040_COEXIST_IE *pBssCoexistIe; + BSS_2040_INTOLERANT_CH_REPORT *pIntolerantReport = NULL; + + if (Elem->MsgLen <= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT)) ) + { + DBGPRINT(RT_DEBUG_ERROR, ("ACTION - 20/40 BSS Coexistence Management Frame length too short! len = %ld!\n", Elem->MsgLen)); + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("ACTION - 20/40 BSS Coexistence Management action----> \n")); + hex_dump("CoexistenceMgmtFrame", Elem->Msg, Elem->MsgLen); + + + pCoexistInfo = (BSS_2040_COEXIST_ELEMENT *) &Elem->Msg[LENGTH_802_11+2]; + /*hex_dump("CoexistInfo", (PUCHAR)pCoexistInfo, sizeof(BSS_2040_COEXIST_ELEMENT));*/ + if (Elem->MsgLen >= (LENGTH_802_11 + sizeof(BSS_2040_COEXIST_ELEMENT) + sizeof(BSS_2040_INTOLERANT_CH_REPORT))) + { + pIntolerantReport = (BSS_2040_INTOLERANT_CH_REPORT *)((PUCHAR)pCoexistInfo + sizeof(BSS_2040_COEXIST_ELEMENT)); + } + /*hex_dump("IntolerantReport ", (PUCHAR)pIntolerantReport, sizeof(BSS_2040_INTOLERANT_CH_REPORT));*/ + + if(pAd->CommonCfg.bBssCoexEnable == FALSE || (pAd->CommonCfg.bForty_Mhz_Intolerant == TRUE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("20/40 BSS CoexMgmt=%d, bForty_Mhz_Intolerant=%d, ignore this action!!\n", + pAd->CommonCfg.bBssCoexEnable, + pAd->CommonCfg.bForty_Mhz_Intolerant)); + break; + } + + pBssCoexistIe = (BSS_2040_COEXIST_IE *)(&pCoexistInfo->BssCoexistIe); +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + BOOLEAN bNeedFallBack = FALSE; + + /*ApPublicAction(pAd, Elem);*/ + if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_20) + { + DBGPRINT(RT_DEBUG_TRACE, ("BSS_2040_COEXIST: BW=%d, bBssCoexEnable=%d!\n", pAd->CommonCfg.RegTransmitSetting.field.BW, pAd->CommonCfg.bBssCoexEnable)); + } + else 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; +#ifdef NEW_BW2040_COEXIST_SUPPORT + /* radio fall back */ + bbp_set_bw(pAd, BW_20); +#endif /* NEW_BW2040_COEXIST_SUPPORT */ + 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].func_tb_idx; + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + SendBSS2040CoexistMgmtAction(pAd, MCAST_WCID, apidx, 0); + } + + } +#endif /* CONFIG_AP_SUPPORT */ + + } + break; +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +#if (defined(CONFIG_HOTSPOT) || defined(WAPP_SUPPORT))\ + && defined(DOT11U_INTERWORKING) && defined(CONFIG_AP_SUPPORT) + case ACTION_GAS_INIT_REQ: + if (GasEnable(pAd, Elem)) + ReceiveGASInitReq(pAd, Elem); + + break; + + case ACTION_GAS_CB_REQ: + if (GasEnable(pAd, Elem)) + ReceiveGASCBReq(pAd, Elem); + + break; +#endif + + case ACTION_WIFI_DIRECT: +#ifdef WH_EZ_SETUP + { + //struct wifi_dev *wdev = NULL; + if (IS_ADPTR_EZ_SETUP_ENABLED(pAd)) { + if (/*!VALID_UCAST_ENTRY_WCID(pAd, Elem->Wcid)*/(Elem->Wcid >= MAX_LEN_OF_MAC_TABLE)) + { + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s, Wrong Wcid:%d !!! need to check the root cause!!!!", + __FUNCTION__, Elem->Wcid)); + return; + } + //wdev = pAd->MacTab.Content[Elem->Wcid].wdev; + //if (IS_EZ_SETUP_ENABLED(wdev)) + if (NdisEqualMemory(&(Elem->Msg[LENGTH_802_11+2]), mtk_oui, MTK_OUI_LEN)) + { + ez_process_action_frame(pAd, Elem); + break; + } + } + } +#endif /* WH_EZ_SETUP */ + + + break; + + +#ifdef WH_EZ_SETUP + case ACTION_VENDOR_USAGE: + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) + EZ_DEBUG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("ERROR !!! ACTION - 221 is Reserved\n")); + break; +#endif + + default: + break; + } + +} + + +static VOID ReservedAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ +#ifdef DBG + UCHAR Category; +#endif /* DBG */ + if (Elem->MsgLen <= LENGTH_802_11) + { + return; + } + +#ifdef DBG + 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); +#endif /* DBG */ +} + + +VOID PeerRMAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ +#ifdef CONFIG_AP_SUPPORT +#ifdef DOT11K_RRM_SUPPORT + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + MAC_TABLE_ENTRY *pEntry = NULL; + + if (VALID_WCID(Elem->Wcid)) + pEntry = &pAd->MacTab.Content[Elem->Wcid]; + else + return; + + if (!(pEntry->wdev)) + return; + + if (!IS_RRM_ENABLE(pAd, pEntry->func_tb_idx)) + return; + + switch(Action) + { + case RRM_MEASURE_REP: + DBGPRINT(RT_DEBUG_TRACE, ("%s: Get RRM Measure report.\n", + __FUNCTION__)); + + RRM_PeerMeasureRepAction(pAd, Elem); + break; + + case RRM_NEIGHTBOR_REQ: + RRM_PeerNeighborReqAction(pAd, Elem); + break; + } +#endif /* DOT11K_RRM_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + return; +} + + +#ifdef DOT11_N_SUPPORT + +#ifdef CONFIG_AP_SUPPORT +#ifdef DOT11N_DRAFT3 +VOID SendNotifyBWActionFrame(RTMP_ADAPTER *pAd, UCHAR Wcid, UCHAR apidx) +{ + UCHAR *pOutBuffer = NULL, *pAddr1; + NDIS_STATUS NStatus; + FRAME_ACTION_HDR Frame; + ULONG FrameLen; + struct wifi_dev *wdev; + + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /* Get an unused nonpaged memory */ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("ACT - SendNotifyBWAction() allocate memory failed \n")); + return; + } + + pAddr1 = pAd->MacTab.Content[Wcid].Addr; + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + ActHeaderInit(pAd, &Frame.Hdr, pAddr1, wdev->if_addr, wdev->bssid); + Frame.Category = CATEGORY_HT; + Frame.Action = NOTIFY_BW_ACTION; + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ACTION_HDR), &Frame, + END_OF_ARGS); + + *(pOutBuffer + FrameLen) = pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; + FrameLen++; + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_TRACE,("ACT - SendNotifyBWAction(NotifyBW= %d)!\n", pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth)); + +} +#endif /* DOT11N_DRAFT3 */ +#endif /* CONFIG_AP_SUPPORT */ + + +VOID PeerHTAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + MAC_TABLE_ENTRY *pEntry; + UCHAR oldMmpsMode; + + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + + pEntry = &pAd->MacTab.Content[Elem->Wcid]; + + switch(Action) + { + case NOTIFY_BW_ACTION: + DBGPRINT(RT_DEBUG_INFO,("ACTION - HT Notify Channel bandwidth action----> \n")); + + if (Elem->Msg[LENGTH_802_11+2] == 0) /* 7.4.8.2. if value is 1, keep the same as supported channel bandwidth. */ + pEntry->HTPhyMode.field.BW = 0; + else + { + pEntry->HTPhyMode.field.BW = pEntry->MaxHTPhyMode.field.BW & + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth; + } + break; + + case SMPS_ACTION: + /* 7.3.1.25*/ + DBGPRINT(RT_DEBUG_TRACE,("ACTION - SMPS action----> \n")); + oldMmpsMode = pEntry->MmpsMode; + if (((Elem->Msg[LENGTH_802_11+2] & 0x1) == 0)) + pEntry->MmpsMode = MMPS_DISABLE; + else if (((Elem->Msg[LENGTH_802_11+2] & 0x2) == 0)) + pEntry->MmpsMode = MMPS_STATIC; + else + pEntry->MmpsMode = MMPS_DYNAMIC; + + if (oldMmpsMode != pEntry->MmpsMode) + { + if ( /* (oldMmpsMode == MMPS_DYNAMIC) || */(pEntry->MmpsMode == MMPS_DYNAMIC)) { + AsicSetSMPS(pAd, pEntry->wcid, 1); + } else { +#ifdef CONFIG_AP_SUPPORT + AsicSetSMPS(pAd, pEntry->wcid, 0); + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + APMlmeDynamicTxRateSwitching(pAd); + + +#endif /* CONFIG_AP_SUPPORT */ + + } + } + DBGPRINT(RT_DEBUG_TRACE,("Wcid(%d) MIMO PS = %d\n", Elem->Wcid, pEntry->MmpsMode)); + /* rt2860c : add something for smps change.*/ + break; + + case SETPCO_ACTION: + break; + + case MIMO_CHA_MEASURE_ACTION: + break; + + default: + DBGPRINT(RT_DEBUG_WARN,("%s(): Unknown HT Action:%d\n", __FUNCTION__, Action)); + break; + } + +} + + +#ifdef DOT11_VHT_AC +VOID PeerVHTAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + + switch(Action) + { + case ACT_VHT_OPMODE_NOTIFY: + { + OPERATING_MODE *op_mode = (OPERATING_MODE *)&Elem->Msg[LENGTH_802_11+2]; + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[Elem->Wcid]; + + DBGPRINT(RT_DEBUG_TRACE,("ACTION - Operating Mode Notification action---->\n")); + hex_dump("OperatingModeNotify", &Elem->Msg[0], Elem->MsgLen); + DBGPRINT(RT_DEBUG_TRACE, ("\t RxNssType=%d, RxNss=%d, ChBW=%d\n", + op_mode->rx_nss_type, op_mode->rx_nss, op_mode->ch_width)); + + if (op_mode->rx_nss_type == 0) { + pEntry->force_op_mode = TRUE; + NdisMoveMemory(&pEntry->operating_mode, op_mode, 1); + } + } + break; +#ifdef VHT_TXBF_SUPPORT + case ACT_VHT_COMPRESS_BF: + { + DBGPRINT(RT_DEBUG_OFF,("ACTION - VHT Compressed Beamforming action---->\n")); + hex_dump("VHT Compressed BF", &Elem->Msg[0], Elem->MsgLen); + break; + } +#endif /* VHT_TXBF_SUPPORT */ + default: + break; + } +} +#endif /* DOT11_VHT_AC */ + + +/* + ========================================================================== + 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(RTMP_ADAPTER *pAd) +{ + //MAC_TABLE_ENTRY *pEntry; + INT i, total; + //UCHAR TID; + +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + return; +#endif /* CONFIG_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 < MAX_LEN_OF_MAC_TABLE); + } + total --; + } +} + + +VOID SendRefreshBAR(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + FRAME_BAR FrameBar; + ULONG FrameLen; + NDIS_STATUS NStatus; + UCHAR *pOutBuffer = NULL, i, TID; + USHORT Sequence, idx; + BA_ORI_ENTRY *pBAEntry; + + for (i = 0; i BAOriWcidArray[i]; + if (idx == 0) + continue; + + pBAEntry = &pAd->BATable.BAOriEntry[idx]; + + if (pBAEntry->ORI_BA_Status == Originator_Done) + { + TID = pBAEntry->TID; + + ASSERT(pBAEntry->Wcid < MAX_LEN_OF_MAC_TABLE); + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n")); + return; + } + + Sequence = pAd->MacTab.tr_entry[pEntry->wcid].TxSeq[TID]; +#ifdef APCLI_SUPPORT +#ifdef MAC_REPEATER_SUPPORT + if (IS_ENTRY_APCLI(pEntry) && pEntry->bReptCli) + BarHeaderInit(pAd, &FrameBar, pEntry->Addr, + pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress); + else +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* APCLI_SUPPORT */ + BarHeaderInit(pAd, &FrameBar, pEntry->Addr, pEntry->wdev->if_addr); + + FrameBar.StartingSeq.field.FragNum = 0; /* make sure sequence not clear in DEL function.*/ + FrameBar.StartingSeq.field.StartSeq = Sequence; /* make sure sequence not clear in DEL funciton.*/ + FrameBar.BarControl.TID = TID; /* make sure sequence not clear in DEL funciton.*/ + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_BAR), &FrameBar, + END_OF_ARGS); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + + MlmeFreeMemory(pAd, pOutBuffer); + } + } +} +#endif /* DOT11_N_SUPPORT */ + + +UCHAR get_channel_set_num(UCHAR *ChannelSet) +{ + int index = 0; + + if (ChannelSet == NULL) + return 0; + + while (ChannelSet[index] != 0)index++; + + return index; +} + + +VOID ActHeaderInit( + IN RTMP_ADAPTER *pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR *da, + IN UCHAR *sa, + IN UCHAR *bssid) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + pHdr80211->FC.Type = FC_TYPE_MGMT; + pHdr80211->FC.SubType = SUBTYPE_ACTION; + + COPY_MAC_ADDR(pHdr80211->Addr1, da); + COPY_MAC_ADDR(pHdr80211->Addr2, sa); + COPY_MAC_ADDR(pHdr80211->Addr3, bssid); +} + + +VOID BarHeaderInit( + IN RTMP_ADAPTER *pAd, + IN OUT PFRAME_BAR pCntlBar, + IN PUCHAR pDA, + IN PUCHAR pSA) +{ +/* USHORT Duration;*/ + + NdisZeroMemory(pCntlBar, sizeof(FRAME_BAR)); + pCntlBar->FC.Type = FC_TYPE_CNTL; + pCntlBar->FC.SubType = SUBTYPE_BLOCK_ACK_REQ; + pCntlBar->BarControl.MTID = 0; + pCntlBar->BarControl.Compressed = 1; + pCntlBar->BarControl.ACKPolicy = 0; + + + pCntlBar->Duration = 16 + RTMPCalcDuration(pAd, RATE_1, sizeof(FRAME_BA)); + + COPY_MAC_ADDR(pCntlBar->Addr1, pDA); + COPY_MAC_ADDR(pCntlBar->Addr2, pSA); +} + + +/* + ========================================================================== + Description: + Insert Category and action code into the action frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. category code of the frame. + 4. action code of the frame. + + Return : None. + ========================================================================== + */ +VOID InsertActField( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Category, + IN UINT8 ActCode) +{ + ULONG TempLen; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &Category, + 1, &ActCode, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/all_net_event.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/all_net_event.c new file mode 100644 index 000000000..2a0fdb375 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/all_net_event.c @@ -0,0 +1,20 @@ +#ifdef ALL_NET_EVENT +#include "rt_config.h" + +void wext_send_event(PNET_DEV net_dev, const char *peer_mac_addr, + const char *bssid, UINT32 channel, INT32 rssi, FBT_NOTIFY_E event_type) +{ + FBT_NOTIFY_ST event_data; + + memcpy(&event_data.FbtNotifyExtApMac, bssid, 6); + event_data.FbtChannel = channel; + event_data.FbtRSSI = rssi; + + event_data.FbtNotifyType = event_type; + memcpy(&event_data.FbtNotifyMac, peer_mac_addr, 6); + + RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM, + IW_ALL_NET_EVENT, NULL, (PUCHAR)&event_data, sizeof(event_data)); + +} +#endif /* ALL_NET_EVENT */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ba_action.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ba_action.c new file mode 100644 index 000000000..a9d6af04b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ba_action.c @@ -0,0 +1,2320 @@ +#ifdef DOT11_N_SUPPORT + +#include "rt_config.h" + + + +#define BA_ORI_INIT_SEQ (tr_entry->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 MULTI_CLIENT_REORDERING_PACKET_TIMEOUT ((200 * OS_HZ)/1000) /* system ticks -- 200 ms*/ +#define MAX_REORDERING_PACKET_TIMEOUT ((3000 * OS_HZ)/1000) /* system ticks -- 100 ms*/ + +#if defined(MAX_CONTINUOUS_TX_CNT) || defined(NEW_IXIA_METHOD) +#undef MULTI_CLIENT_REORDERING_PACKET_TIMEOUT +#define MULTI_CLIENT_REORDERING_PACKET_TIMEOUT ((500 * OS_HZ)/1000) /* system ticks -- 200 ms*/ +#endif +#define RESET_RCV_SEQ (0xFFFF) + +static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk); + +#ifdef PEER_DELBA_TX_ADAPT +static VOID Peer_DelBA_Tx_Adapt_Enable( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry); + +static VOID Peer_DelBA_Tx_Adapt_Disable( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry); +#endif /* PEER_DELBA_TX_ADAPT */ + +BA_ORI_ENTRY *BATableAllocOriEntry(RTMP_ADAPTER *pAd, USHORT *Idx); +BA_REC_ENTRY *BATableAllocRecEntry(RTMP_ADAPTER *pAd, USHORT *Idx); + +VOID BAOriSessionSetupTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID BARecSessionIdleTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + + +BUILD_TIMER_FUNCTION(BAOriSessionSetupTimeout); +BUILD_TIMER_FUNCTION(BARecSessionIdleTimeout); + +#define ANNOUNCE_REORDERING_PACKET(_pAd, _mpdu_blk) \ + Announce_Reordering_Packet(_pAd, _mpdu_blk); + +VOID BA_MaxWinSizeReasign( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntryPeer, + OUT UCHAR *pWinSize) +{ + UCHAR MaxSize; + UCHAR MaxPeerRxSize; + + + if (CLIENT_STATUS_TEST_FLAG(pEntryPeer, fCLIENT_STATUS_RALINK_CHIPSET)) + MaxPeerRxSize = (1 << (pEntryPeer->MaxRAmpduFactor + 3)); /* (2^(13 + exp)) / 2048 bytes */ + else + MaxPeerRxSize = (((1 << (pEntryPeer->MaxRAmpduFactor + 3)) * 10) / 16) -1; + + if (pAd->Antenna.field.TxPath == 3 && + (pEntryPeer->HTCapability.MCSSet[2] != 0)) + MaxSize = 31; /* for 3x3, MaxSize use ((48KB/1.5KB) -1) = 31 */ + else + MaxSize = 20; /* for not 3x3, MaxSize use ((32KB/1.5KB) -1) ~= 20 */ + + DBGPRINT(RT_DEBUG_TRACE, ("ba>WinSize=%d, MaxSize=%d, MaxPeerRxSize=%d\n", + *pWinSize, MaxSize, MaxPeerRxSize)); + + 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; + } +} + + +UINT BA_Reorder_AMSDU_Annnounce(RTMP_ADAPTER *pAd, PNDIS_PACKET pPacket, 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 Announce_Reordering_Packet(RTMP_ADAPTER *pAd, struct reordering_mpdu *mpdu) +{ + PNDIS_PACKET pPacket; + BOOLEAN opmode = pAd->OpMode; + + pPacket = mpdu->pPacket; + if (mpdu->bAMSDU) + { + BA_Reorder_AMSDU_Annnounce(pAd, pPacket, mpdu->OpMode); + } + else + { + /* pass this 802.3 packet to upper layer or forward this packet to WM directly */ + Announce_or_Forward_802_3_Packet(pAd, pPacket, RTMP_GET_PACKET_WDEV(pPacket), opmode); + } +} + + +/* Insert a reordering mpdu into sorted linked list by sequence no. */ +BOOLEAN ba_reordering_mpdu_insertsorted(struct reordering_list *list, struct reordering_mpdu *mpdu) +{ + + struct reordering_mpdu **ppScan = &list->next; + + while (*ppScan != NULL) + { + if (SEQ_SMALLER((*ppScan)->Sequence, mpdu->Sequence, MAXSEQ)) + { + ppScan = &(*ppScan)->next; + } + else if ((*ppScan)->Sequence == mpdu->Sequence) + { + /* give up this duplicated frame */ + return(FALSE); + } + else + { + /* find position */ + break; + } + } + + mpdu->next = *ppScan; + *ppScan = mpdu; + list->qlen++; + return TRUE; +} + + +/* Caller lock critical section if necessary */ +static inline void ba_enqueue(struct reordering_list *list, struct reordering_mpdu *mpdu_blk) +{ + list->qlen++; + mpdu_blk->next = list->next; + list->next = mpdu_blk; +} + + +/* caller lock critical section if necessary */ +static inline struct reordering_mpdu * ba_dequeue(struct reordering_list *list) +{ + struct reordering_mpdu *mpdu_blk = NULL; + + ASSERT(list); + + if (list->qlen) + { + list->qlen--; + mpdu_blk = list->next; + if (mpdu_blk) + { + list->next = mpdu_blk->next; + mpdu_blk->next = NULL; + } + } + return mpdu_blk; +} + + +static inline struct reordering_mpdu *ba_reordering_mpdu_dequeue(struct reordering_list *list) +{ + return(ba_dequeue(list)); +} + + +static inline struct reordering_mpdu *ba_reordering_mpdu_probe(struct reordering_list *list) +{ + ASSERT(list); + + return(list->next); +} + + +/* free all resource for reordering mechanism */ +void ba_reordering_resource_release(RTMP_ADAPTER *pAd) +{ + BA_TABLE *Tab; + BA_REC_ENTRY *pBAEntry; + struct reordering_mpdu *mpdu_blk; + int i; + + Tab = &pAd->BATable; + + /* I. release all pending reordering packet */ + NdisAcquireSpinLock(&pAd->BATabLock); + for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) + { + pBAEntry = &Tab->BARecEntry[i]; + if (pBAEntry->REC_BA_Status != Recipient_NONE) + { + while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) + { + ASSERT(mpdu_blk->pPacket); + RELEASE_NDIS_PACKET(pAd, mpdu_blk->pPacket, NDIS_STATUS_FAILURE); + ba_mpdu_blk_free(pAd, mpdu_blk); + } + } + } + NdisReleaseSpinLock(&pAd->BATabLock); + + ASSERT(pBAEntry->list.qlen == 0); + /* II. free memory of reordering mpdu table */ + NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); + os_free_mem(pAd, pAd->mpdu_blk_pool.mem); + NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); +} + + +/* + * Allocate all resource for reordering mechanism + */ +BOOLEAN ba_reordering_resource_init(RTMP_ADAPTER *pAd, int num) +{ + int i; + PUCHAR mem; + struct reordering_mpdu *mpdu_blk; + struct reordering_list *freelist; + + /* allocate spinlock */ + NdisAllocateSpinLock(pAd, &pAd->mpdu_blk_pool.lock); + + /* initialize freelist */ + freelist = &pAd->mpdu_blk_pool.freelist; + freelist->next = NULL; + freelist->qlen = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("Allocate %d memory for BA reordering\n", (UINT32)(num*sizeof(struct reordering_mpdu)))); + + /* allocate number of mpdu_blk memory */ + os_alloc_mem(pAd, (PUCHAR *)&mem, (num*sizeof(struct reordering_mpdu))); + + pAd->mpdu_blk_pool.mem = mem; + + if (mem == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("Can't Allocate Memory for BA Reordering\n")); + return(FALSE); + } + + /* build mpdu_blk free list */ + for (i=0; impdu_blk_pool.lock); + mpdu_blk = ba_dequeue(&pAd->mpdu_blk_pool.freelist); + if (mpdu_blk) + { + /* reset mpdu_blk */ + NdisZeroMemory(mpdu_blk, sizeof(struct reordering_mpdu)); + } + NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); + return mpdu_blk; +} + +static void ba_mpdu_blk_free(PRTMP_ADAPTER pAd, struct reordering_mpdu *mpdu_blk) +{ + ASSERT(mpdu_blk); + + NdisAcquireSpinLock(&pAd->mpdu_blk_pool.lock); + ba_enqueue(&pAd->mpdu_blk_pool.freelist, mpdu_blk); + NdisReleaseSpinLock(&pAd->mpdu_blk_pool.lock); +} + + +static USHORT ba_indicate_reordering_mpdus_in_order( + IN PRTMP_ADAPTER pAd, + IN PBA_REC_ENTRY pBAEntry, + IN USHORT StartSeq) +{ + struct reordering_mpdu *mpdu_blk; + USHORT LastIndSeq = RESET_RCV_SEQ; + + NdisAcquireSpinLock(&pBAEntry->RxReRingLock); + + while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) + { + /* find in-order frame */ + if (!SEQ_STEPONE(mpdu_blk->Sequence, StartSeq, MAXSEQ)) + break; + + /* dequeue in-order frame from reodering list */ + mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); + if(mpdu_blk == NULL) + { + break; + } + /* pass this frame up */ + ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); + /* move to next sequence */ + StartSeq = mpdu_blk->Sequence; + LastIndSeq = StartSeq; + /* free mpdu_blk */ + ba_mpdu_blk_free(pAd, mpdu_blk); + } + + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); + + /* update last indicated sequence */ + return LastIndSeq; +} + +static void ba_indicate_reordering_mpdus_le_seq( + IN PRTMP_ADAPTER pAd, + IN PBA_REC_ENTRY pBAEntry, + IN USHORT Sequence) +{ + struct reordering_mpdu *mpdu_blk; + + NdisAcquireSpinLock(&pBAEntry->RxReRingLock); + while ((mpdu_blk = ba_reordering_mpdu_probe(&pBAEntry->list))) + { + /* find in-order frame */ + if ((mpdu_blk->Sequence == Sequence) || SEQ_SMALLER(mpdu_blk->Sequence, Sequence, MAXSEQ)) + { + /* dequeue in-order frame from reodering list */ + mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list); + if(mpdu_blk == NULL) + { + break; + } + /* pass this frame up */ + ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); + /* free mpdu_blk */ + ba_mpdu_blk_free(pAd, mpdu_blk); + } + else + { + break; + } + } + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); +} + + +static void ba_refresh_reordering_mpdus(RTMP_ADAPTER *pAd, BA_REC_ENTRY *pBAEntry) +{ + struct reordering_mpdu *mpdu_blk; + + NdisAcquireSpinLock(&pBAEntry->RxReRingLock); + + /* dequeue in-order frame from reodering list */ + while ((mpdu_blk = ba_reordering_mpdu_dequeue(&pBAEntry->list))) + { + /* pass this frame up */ + ANNOUNCE_REORDERING_PACKET(pAd, mpdu_blk); + + pBAEntry->LastIndSeq = mpdu_blk->Sequence; + ba_mpdu_blk_free(pAd, mpdu_blk); + + /* update last indicated sequence */ + } + ASSERT(pBAEntry->list.qlen == 0); + pBAEntry->LastIndSeq = RESET_RCV_SEQ; + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); +} + + +/* static */ +void ba_flush_reordering_timeout_mpdus( + IN PRTMP_ADAPTER pAd, + IN PBA_REC_ENTRY pBAEntry, + IN ULONG Now32) + +{ + USHORT Sequence; + + if ((pBAEntry == NULL) || (pBAEntry->list.qlen <= 0)) + return; + +/* if ((RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+REORDERING_PACKET_TIMEOUT)) &&*/ +/* (pBAEntry->list.qlen > ((pBAEntry->BAWinSize*7)/8))) ||*/ +/* (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(10*REORDERING_PACKET_TIMEOUT))) &&*/ +/* (pBAEntry->list.qlen > (pBAEntry->BAWinSize/8)))*/ + if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(MAX_REORDERING_PACKET_TIMEOUT/6))) + &&(pBAEntry->list.qlen > 0/*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 +#ifdef CONFIG_BA_REORDER_MONITOR + if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(pAd->BATable.ba_reordering_packet_timeout))) + && (pBAEntry->list.qlen > 0) + ) +#else + if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer+(REORDERING_PACKET_TIMEOUT))) + && (pBAEntry->list.qlen > 0) + ) +#endif + { +/* + 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_TRACE, ("%x, flush one!\n", pBAEntry->LastIndSeq)); + + } +} + + +/* + * generate ADDBA request to + * set up BA agreement + */ +VOID BAOriSessionSetUp( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR TID, + IN USHORT TimeOut, + IN ULONG DelayTime, + IN BOOLEAN isForced) +{ + BA_ORI_ENTRY *pBAEntry = NULL; + USHORT Idx; + BOOLEAN Cancelled; + STA_TR_ENTRY *tr_entry; + UCHAR BAWinSize = 0; + + ASSERT(TID < NUM_OF_TID); + if (TID >= NUM_OF_TID) + { + DBGPRINT(RT_DEBUG_TRACE, ("Wrong TID %d!\n", TID)); + return; + } + + if ((pAd->CommonCfg.BACapability.field.AutoBA != TRUE) && (isForced == FALSE)) + return; + + /* if this entry is limited to use legacy tx mode, it doesn't generate BA. */ + if (RTMPStaFixedTxMode(pAd, pEntry) != FIXED_TXMODE_HT) + return; + + if ((pEntry->BADeclineBitmap & (1<BAOriWcidArray[TID]; + if (Idx == 0) + { + /* allocate a BA session*/ + pBAEntry = BATableAllocOriEntry(pAd, &Idx); + if (pBAEntry == NULL) + { + DBGPRINT(RT_DEBUG_TRACE,("%s(): alloc BA session failed\n", + __FUNCTION__)); + return; + } + } + else + { + pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + } + + if (pBAEntry->ORI_BA_Status >= Originator_WaitRes) + return; + + pEntry->BAOriWcidArray[TID] = Idx; + + + BAWinSize = pAd->CommonCfg.BACapability.field.TxBAWinLimit; + + + /* Initialize BA session */ + pBAEntry->ORI_BA_Status = Originator_WaitRes; + pBAEntry->Wcid = pEntry->wcid; + pBAEntry->BAWinSize = BAWinSize; + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + pBAEntry->Sequence = BA_ORI_INIT_SEQ; + pBAEntry->Token = 1; /* (2008-01-21) Jan Lee recommends it - this token can't be 0*/ + pBAEntry->TID = TID; + pBAEntry->TimeOutValue = TimeOut; + pBAEntry->pAdapter = pAd; + + if (!(pEntry->TXBAbitmap & (1<ORIBATimer, GET_TIMER_FUNCTION(BAOriSessionSetupTimeout), pBAEntry, FALSE); + } + else + RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); + + /* set timer to send ADDBA request */ + RTMPSetTimer(&pBAEntry->ORIBATimer, DelayTime); +} + + +VOID BAOriSessionAdd( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN FRAME_ADDBA_RSP *pFrame) +{ + BA_ORI_ENTRY *pBAEntry = NULL; + BOOLEAN Cancelled; + UCHAR TID; + USHORT Idx; + + UCHAR MaxPeerBufSize; + STA_TR_ENTRY *tr_entry; + + TID = pFrame->BaParm.TID; + Idx = pEntry->BAOriWcidArray[TID]; + pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + + MaxPeerBufSize = 0; + + /* Start fill in parameters.*/ + if ((Idx !=0) && (pBAEntry->TID == TID) && (pBAEntry->ORI_BA_Status == Originator_WaitRes)) + { + MaxPeerBufSize = (UCHAR)pFrame->BaParm.BufSize; + + { + if (pAd->chipCap.hif_type == HIF_MT) + { + pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, MaxPeerBufSize); + } + else + { + if (MaxPeerBufSize > 0) + MaxPeerBufSize -= 1; + else + MaxPeerBufSize = 0; + pBAEntry->BAWinSize = min(pBAEntry->BAWinSize, MaxPeerBufSize); + BA_MaxWinSizeReasign(pAd, pEntry, &pBAEntry->BAWinSize); + } + } + + pBAEntry->TimeOutValue = pFrame->TimeOutValue; + pBAEntry->amsdu_cap = pFrame->BaParm.AMSDUSupported; + pBAEntry->ORI_BA_Status = Originator_Done; + pAd->BATable.numDoneOriginator ++; + + /* reset sequence number */ + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + pBAEntry->Sequence = BA_ORI_INIT_SEQ; + + /* Set Bitmap flag.*/ + pEntry->TXBAbitmap |= (1<ORIBATimer, &Cancelled); + + pBAEntry->ORIBATimer.TimerValue = 0; /*pFrame->TimeOutValue;*/ + + RTMP_ADD_BA_SESSION_TO_ASIC(pAd, pEntry->wcid, TID, pBAEntry->Sequence, + pBAEntry->BAWinSize, BA_SESSION_ORI); + + DBGPRINT(RT_DEBUG_TRACE, ("%s():TXBAbitmap=%x, AMSDUCap=%d, BAWinSize=%d, TimeOut=%ld\n", + __FUNCTION__, pEntry->TXBAbitmap, pBAEntry->amsdu_cap, + pBAEntry->BAWinSize, pBAEntry->ORIBATimer.TimerValue)); + + /* Send BAR after BA session is build up */ + SendRefreshBAR(pAd, pEntry); + + if (pBAEntry->ORIBATimer.TimerValue) + RTMPSetTimer(&pBAEntry->ORIBATimer, pBAEntry->ORIBATimer.TimerValue); /* in mSec */ + } + +} + + +BOOLEAN BARecSessionAdd( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN FRAME_ADDBA_REQ *pFrame) +{ + BA_REC_ENTRY *pBAEntry = NULL; + BOOLEAN Status = TRUE, Cancelled; + USHORT Idx; + UCHAR TID, BAWinSize; + + + ASSERT(pEntry); + + /* find TID*/ + TID = pFrame->BaParm.TID; + + BAWinSize = min(((UCHAR)pFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit); + + if (BAWinSize == 0) { + BAWinSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit; + } + + NdisAcquireSpinLock(&pAd->BATabLock); + /* 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*/ + NdisReleaseSpinLock(&pAd->BATabLock); + ba_refresh_reordering_mpdus(pAd, pBAEntry); + NdisAcquireSpinLock(&pAd->BATabLock); + } + + DBGPRINT(RT_DEBUG_TRACE,("%s(%ld): Idx = %d, BAWinSize(req %d) = %d\n", + __FUNCTION__, pAd->BATable.numAsRecipient, Idx, + pFrame->BaParm.BufSize, BAWinSize)); + + /* Start fill in parameters.*/ + if (pBAEntry != NULL) + { + ASSERT(pBAEntry->list.qlen == 0); + + pBAEntry->REC_BA_Status = Recipient_HandleRes; + pBAEntry->BAWinSize = BAWinSize; + pBAEntry->Wcid = pEntry->wcid; + pBAEntry->TID = TID; + pBAEntry->TimeOutValue = pFrame->TimeOutValue; + pBAEntry->REC_BA_Status = Recipient_Accept; + /* initial sequence number */ + /* initial LastIndSeq = SSN - 1*/ + pBAEntry->LastIndSeq = (pFrame->BaStartSeq.field.StartSeq - 1) & MAXSEQ; + + DBGPRINT(RT_DEBUG_TRACE, ("Start Seq = %08x\n", pFrame->BaStartSeq.field.StartSeq)); + + if (pEntry->RXBAbitmap & (1<RECBATimer, &Cancelled); + else + RTMPInitTimer(pAd, &pBAEntry->RECBATimer, GET_TIMER_FUNCTION(BARecSessionIdleTimeout), pBAEntry, TRUE); + + /* Set Bitmap flag.*/ + pEntry->RXBAbitmap |= (1<BARecWcidArray[TID] = Idx; + pEntry->BADeclineBitmap &= ~(1<wcid, TID, pBAEntry->LastIndSeq, + pBAEntry->BAWinSize, BA_SESSION_RECP); + + DBGPRINT(RT_DEBUG_TRACE, ("MACEntry[%d]RXBAbitmap = 0x%x. BARecWcidArray=%d\n", + pEntry->wcid, pEntry->RXBAbitmap, pEntry->BARecWcidArray[TID])); + } + else + { + Status = FALSE; + DBGPRINT(RT_DEBUG_TRACE,("Can't Accept ADDBA for %02x:%02x:%02x:%02x:%02x:%02x TID = %d\n", + PRINT_MAC(pEntry->Addr), TID)); + } + NdisReleaseSpinLock(&pAd->BATabLock); + return(Status); +} + + +BA_REC_ENTRY *BATableAllocRecEntry(RTMP_ADAPTER *pAd, USHORT *Idx) +{ + int i; + BA_REC_ENTRY *pBAEntry = NULL; + + + //NdisAcquireSpinLock(&pAd->BATabLock); + + if (pAd->BATable.numAsRecipient >= (MAX_LEN_OF_BA_REC_TABLE - 1)) + { + DBGPRINT(RT_DEBUG_TRACE, ("BA Recipeint Session (%ld) > %d\n", + pAd->BATable.numAsRecipient, (MAX_LEN_OF_BA_REC_TABLE - 1))); + goto done; + } + + /* reserve idx 0 to identify BAWcidArray[TID] as empty*/ + for (i=1; i < MAX_LEN_OF_BA_REC_TABLE; i++) + { + pBAEntry =&pAd->BATable.BARecEntry[i]; + if ((pBAEntry->REC_BA_Status == Recipient_NONE)) + { + /* get one */ + pAd->BATable.numAsRecipient++; + pBAEntry->REC_BA_Status = Recipient_USED; + *Idx = i; + break; + } + } + +done: + //NdisReleaseSpinLock(&pAd->BATabLock); + return pBAEntry; +} + + +BA_ORI_ENTRY *BATableAllocOriEntry(RTMP_ADAPTER *pAd, USHORT *Idx) +{ + int i; + BA_ORI_ENTRY *pBAEntry = NULL; + + NdisAcquireSpinLock(&pAd->BATabLock); + if (pAd->BATable.numAsOriginator >= (MAX_LEN_OF_BA_ORI_TABLE - 1)) + goto done; + + /* reserve idx 0 to identify BAWcidArray[TID] as empty*/ + for (i=1; iBATable.BAOriEntry[i]; + if ((pBAEntry->ORI_BA_Status == Originator_NONE)) + { + /* get one */ + pAd->BATable.numAsOriginator++; + pBAEntry->ORI_BA_Status = Originator_USED; + pBAEntry->pAdapter = pAd; + *Idx = i; + break; + } + } + +done: + NdisReleaseSpinLock(&pAd->BATabLock); + return pBAEntry; +} + + +VOID BATableFreeOriEntry(RTMP_ADAPTER *pAd, ULONG Idx) +{ + BA_ORI_ENTRY *pBAEntry = NULL; + MAC_TABLE_ENTRY *pEntry; + + if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) + return; + + pBAEntry =&pAd->BATable.BAOriEntry[Idx]; + + NdisAcquireSpinLock(&pAd->BATabLock); + if (pBAEntry->ORI_BA_Status != Originator_NONE) + { + pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; + pEntry->BAOriWcidArray[pBAEntry->TID] = 0; + DBGPRINT(RT_DEBUG_TRACE, ("%s: Wcid = %d, TID = %d\n", __FUNCTION__, pBAEntry->Wcid, pBAEntry->TID)); + + if (pBAEntry->ORI_BA_Status == Originator_Done) + { + pAd->BATable.numDoneOriginator -= 1; + pEntry->TXBAbitmap &= (~(1<<(pBAEntry->TID) )); + DBGPRINT(RT_DEBUG_TRACE, ("BATableFreeOriEntry numAsOriginator= %ld\n", pAd->BATable.numAsRecipient)); + /* Erase Bitmap flag.*/ + } + + ASSERT(pAd->BATable.numAsOriginator != 0); + + pAd->BATable.numAsOriginator -= 1; + + pBAEntry->ORI_BA_Status = Originator_NONE; + pBAEntry->Token = 0; + } + NdisReleaseSpinLock(&pAd->BATabLock); + +} + + +VOID BATableFreeRecEntry(RTMP_ADAPTER *pAd, ULONG Idx) +{ + BA_REC_ENTRY *pBAEntry = NULL; + MAC_TABLE_ENTRY *pEntry; + + + if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_REC_TABLE)) + return; + + pBAEntry =&pAd->BATable.BARecEntry[Idx]; + + NdisAcquireSpinLock(&pAd->BATabLock); + if (pBAEntry->REC_BA_Status != Recipient_NONE) + { + pEntry = &pAd->MacTab.Content[pBAEntry->Wcid]; + pEntry->BARecWcidArray[pBAEntry->TID] = 0; + + ASSERT(pAd->BATable.numAsRecipient != 0); + + pAd->BATable.numAsRecipient -= 1; + + pBAEntry->REC_BA_Status = Recipient_NONE; + } + NdisReleaseSpinLock(&pAd->BATabLock); +} + + +VOID BAOriSessionTearDown( + INOUT RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive, + IN BOOLEAN bForceSend) +{ + UINT Idx = 0; + BA_ORI_ENTRY *pBAEntry; + BOOLEAN Cancelled; + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + + /* Clear WTBL2.dw15 when BA is deleted */ + RTMP_DEL_BA_SESSION_FROM_ASIC(pAd, Wcid, TID, BA_SESSION_ORI); + + /* Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).*/ + Idx = pAd->MacTab.Content[Wcid].BAOriWcidArray[TID]; + if ((Idx == 0) || (Idx >= MAX_LEN_OF_BA_ORI_TABLE)) + { + if (bForceSend == TRUE) + { + /* force send specified TID DelBA*/ + MLME_DELBA_REQ_STRUCT DelbaReq; + MLME_QUEUE_ELEM *Elem; + os_alloc_mem(NULL, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + if (Elem != NULL) + { + NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); + NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); + + COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); + DelbaReq.Wcid = Wcid; + DelbaReq.TID = TID; + DelbaReq.Initiator = ORIGINATOR; + Elem->MsgLen = sizeof(DelbaReq); + NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); + MlmeDELBAAction(pAd, Elem); + os_free_mem(NULL, Elem); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(bForceSend):alloc memory failed!\n", __FUNCTION__)); + } + } + + return; + } + + DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID)); + + pBAEntry = &pAd->BATable.BAOriEntry[Idx]; + DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %d, Wcid=%d.TID=%d, ORI_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->ORI_BA_Status)); + + /* Prepare DelBA action frame and send to the peer.*/ + if ((bPassive == FALSE) && (TID == pBAEntry->TID) && (pBAEntry->ORI_BA_Status == Originator_Done)) + { + MLME_DELBA_REQ_STRUCT DelbaReq; + MLME_QUEUE_ELEM *Elem; + os_alloc_mem(NULL, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + if (Elem != NULL) + { + NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); + NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); + + COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); + DelbaReq.Wcid = Wcid; + DelbaReq.TID = pBAEntry->TID; + DelbaReq.Initiator = ORIGINATOR; + Elem->MsgLen = sizeof(DelbaReq); + NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); + MlmeDELBAAction(pAd, Elem); + os_free_mem(NULL, Elem); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__)); + return; + } + } + RTMPCancelTimer(&pBAEntry->ORIBATimer, &Cancelled); + BATableFreeOriEntry(pAd, Idx); + + if (bPassive) + { + /*BAOriSessionSetUp(pAd, &pAd->MacTab.Content[Wcid], TID, 0, 10000, TRUE);*/ + } +} + +VOID BARecSessionTearDown( + IN OUT PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive) +{ + ULONG Idx = 0; + BA_REC_ENTRY *pBAEntry; + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + + NdisAcquireSpinLock(&pAd->BATabLock); + /* Locate corresponding BA Originator Entry in BA Table with the (pAddr,TID).*/ + Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; + if (Idx == 0) { + NdisReleaseSpinLock(&pAd->BATabLock); + return; + } + + DBGPRINT(RT_DEBUG_TRACE,("%s===>Wcid=%d.TID=%d \n", __FUNCTION__, Wcid, TID)); + + + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + DBGPRINT(RT_DEBUG_TRACE,("\t===>Idx = %ld, Wcid=%d.TID=%d, REC_BA_Status = %d \n", Idx, Wcid, TID, pBAEntry->REC_BA_Status)); + + /* Prepare DelBA action frame and send to the peer.*/ + if ((TID == pBAEntry->TID) && (pBAEntry->REC_BA_Status == Recipient_Accept)) + { + MLME_DELBA_REQ_STRUCT DelbaReq; + BOOLEAN Cancelled; + + RTMPCancelTimer(&pBAEntry->RECBATimer, &Cancelled); + + + /* 1. Send DELBA Action Frame*/ + if (bPassive == FALSE) + { + MLME_QUEUE_ELEM *Elem; + os_alloc_mem(NULL, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + if (Elem != NULL) + { + NdisZeroMemory(&DelbaReq, sizeof(DelbaReq)); + NdisZeroMemory(Elem, sizeof(MLME_QUEUE_ELEM)); + + COPY_MAC_ADDR(DelbaReq.Addr, pAd->MacTab.Content[Wcid].Addr); + DelbaReq.Wcid = Wcid; + DelbaReq.TID = TID; + DelbaReq.Initiator = RECIPIENT; + Elem->MsgLen = sizeof(DelbaReq); + NdisMoveMemory(Elem->Msg, &DelbaReq, sizeof(DelbaReq)); + MlmeDELBAAction(pAd, Elem); + os_free_mem(NULL, Elem); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():alloc memory failed!\n", __FUNCTION__)); + NdisReleaseSpinLock(&pAd->BATabLock); + return; + } + } + + + + /* 2. Free resource of BA session*/ + /* flush all pending reordering mpdus */ + NdisReleaseSpinLock(&pAd->BATabLock); + ba_refresh_reordering_mpdus(pAd, pBAEntry); + NdisAcquireSpinLock(&pAd->BATabLock); + + //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, BA_SESSION_RECP); + + //NdisReleaseSpinLock(&pAd->BATabLock); + + } + NdisReleaseSpinLock(&pAd->BATabLock); + BATableFreeRecEntry(pAd, Idx); +} + + +VOID BASessionTearDownALL(RTMP_ADAPTER *pAd, UCHAR Wcid) +{ + int i; + + for (i=0; ipAdapter; + + +#ifdef CONFIG_ATE + /* Nothing to do in ATE mode. */ + if (ATE_ON(pAd)) + return; +#endif /* CONFIG_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; + + + NdisZeroMemory(&AddbaReq, sizeof(AddbaReq)); + COPY_MAC_ADDR(AddbaReq.pAddr, pEntry->Addr); + AddbaReq.Wcid = pEntry->wcid; + AddbaReq.TID = pBAEntry->TID; + AddbaReq.BaBufSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit; + AddbaReq.TimeOutValue = 0; + AddbaReq.Token = pBAEntry->Token; + MlmeEnqueue(pAd, ACTION_STATE_MACHINE, MT2_MLME_ADD_BA_CATE, sizeof(MLME_ADDBA_REQ_STRUCT), (PVOID)&AddbaReq, 0); + RTMP_MLME_HANDLER(pAd); + DBGPRINT(RT_DEBUG_TRACE,("BA Ori Session Timeout(%d) : Send ADD BA again\n", pBAEntry->Token)); + + pBAEntry->Token++; + RTMPSetTimer(&pBAEntry->ORIBATimer, ORI_BA_SESSION_TIMEOUT); + } + else + { + BATableFreeOriEntry(pAd, pEntry->BAOriWcidArray[pBAEntry->TID]); + } +} + + +/* + ========================================================================== + Description: + Retry sending ADDBA Reqest. + + IRQL = DISPATCH_LEVEL + + Parametrs: + p8023Header: if this is already 802.3 format, p8023Header is NULL + + Return : TRUE if put into rx reordering buffer, shouldn't indicaterxhere. + FALSE , then continue indicaterx at this moment. + ========================================================================== + */ +VOID BARecSessionIdleTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + + BA_REC_ENTRY *pBAEntry = (BA_REC_ENTRY *)FunctionContext; + PRTMP_ADAPTER pAd; + ULONG Now32; + + if (pBAEntry == NULL) + return; + + if ((pBAEntry->REC_BA_Status == Recipient_Accept)) + { + NdisGetSystemUpTime(&Now32); + + if (RTMP_TIME_AFTER((unsigned long)Now32, (unsigned long)(pBAEntry->LastIndSeqAtTimer + REC_BA_SESSION_IDLE_TIMEOUT))) + { + pAd = pBAEntry->pAdapter; + /* flush all pending reordering mpdus */ + ba_refresh_reordering_mpdus(pAd, pBAEntry); + DBGPRINT(RT_DEBUG_TRACE, ("%ld: REC BA session Timeout\n", Now32)); + } + } +} + + +VOID PeerAddBAReqAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + UCHAR Status = 1; + UCHAR pAddr[6]; + FRAME_ADDBA_RSP ADDframe; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + PFRAME_ADDBA_REQ pAddreqFrame = (PFRAME_ADDBA_REQ)(&Elem->Msg[0]); + ULONG FrameLen/*, *ptemp*/; + MAC_TABLE_ENTRY *pMacEntry; +#ifdef CONFIG_AP_SUPPORT + INT apidx; +#endif /* CONFIG_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> (Wcid = %d)\n", __FUNCTION__, Elem->Wcid)); + + /*ADDBA Request from unknown peer, ignore this.*/ + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + + pMacEntry = &pAd->MacTab.Content[Elem->Wcid]; + DBGPRINT(RT_DEBUG_TRACE,("BA - PeerAddBAReqAction----> \n")); + if ((pMacEntry == NULL) || (pMacEntry->wdev == NULL)) + { + DBGPRINT(RT_DEBUG_ERROR,(" %s: HIT the pMacEntry or pMacEntry->wdev NULL check\n", __FUNCTION__)); + return; + } + + //ptemp = (PULONG)Elem->Msg; + + if (PeerAddBAReqActionSanity(pAd, Elem->Msg, Elem->MsgLen, pAddr)) + { + if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Rcv Wcid(%d) AddBAReq\n", Elem->Wcid)); + if (BARecSessionAdd(pAd, &pAd->MacTab.Content[Elem->Wcid], pAddreqFrame)) + { +#ifdef PEER_DELBA_TX_ADAPT + Peer_DelBA_Tx_Adapt_Disable(pAd, &pAd->MacTab.Content[Elem->Wcid]); +#endif /* PEER_DELBA_TX_ADAPT */ + Status = 0; + } + else + Status = 38; /* more parameters have invalid values*/ + } + else + { + Status = 37; /* the request has been declined.*/ + } + } + + if (IS_ENTRY_CLIENT(pMacEntry)) + ASSERT(pMacEntry->Sst == SST_ASSOC); + + /* 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 CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pMacEntry)) + { + apidx = pMacEntry->func_tb_idx; +#ifdef MAC_REPEATER_SUPPORT + if (pMacEntry && pMacEntry->bReptCli) + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->ApCfg.ApCliTab[apidx].RepeaterCli[pMacEntry->MatchReptCliIdx].CurrentAddress, pAddr); + else +#endif /* MAC_REPEATER_SUPPORT */ + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, pAddr); + } + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (IS_ENTRY_WDS(pMacEntry)) + { + apidx = pMacEntry->func_tb_idx; + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.if_addr, pAddr); + } + else +#endif /* WDS_SUPPORT */ + { + apidx = pMacEntry->func_tb_idx; + ActHeaderInit(pAd, &ADDframe.Hdr, pAddr, pAd->ApCfg.MBSSID[apidx].wdev.if_addr, pAd->ApCfg.MBSSID[apidx].wdev.bssid); + } + } +#endif /* CONFIG_AP_SUPPORT */ + ADDframe.Category = CATEGORY_BA; + ADDframe.Action = ADDBA_RESP; + ADDframe.Token = pAddreqFrame->Token; + /* What is the Status code?? need to check.*/ + ADDframe.StatusCode = Status; + ADDframe.BaParm.BAPolicy = IMMED_BA; +#ifdef DOT11_VHT_AC + if (pMacEntry && IS_VHT_STA(pMacEntry) && (Status == 0)) + ADDframe.BaParm.AMSDUSupported = pAddreqFrame->BaParm.AMSDUSupported; + else +#endif /* DOT11_VHT_AC */ + ADDframe.BaParm.AMSDUSupported = 0; + +#ifdef WFA_VHT_PF + if (pAd->CommonCfg.DesiredHtPhy.AmsduEnable) + ADDframe.BaParm.AMSDUSupported = 1; +#endif /* WFA_VHT_PF */ + ADDframe.BaParm.TID = pAddreqFrame->BaParm.TID; + ADDframe.BaParm.BufSize = min(((UCHAR)pAddreqFrame->BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit); + if (ADDframe.BaParm.BufSize == 0) { + //ADDframe.BaParm.BufSize = 64; + ADDframe.BaParm.BufSize = pAd->CommonCfg.BACapability.field.RxBAWinLimit; + } + ADDframe.TimeOutValue = 0; /* pAddreqFrame->TimeOutValue; */ + +#ifdef UNALIGNMENT_SUPPORT + { + BA_PARM tmpBaParm; + + NdisMoveMemory((PUCHAR)(&tmpBaParm), (PUCHAR)(&ADDframe.BaParm), sizeof(BA_PARM)); + *(USHORT *)(&tmpBaParm) = cpu2le16(*(USHORT *)(&tmpBaParm)); + NdisMoveMemory((PUCHAR)(&ADDframe.BaParm), (PUCHAR)(&tmpBaParm), sizeof(BA_PARM)); + } +#else + *(USHORT *)(&ADDframe.BaParm) = cpu2le16(*(USHORT *)(&ADDframe.BaParm)); +#endif /* UNALIGNMENT_SUPPORT */ + + ADDframe.StatusCode = cpu2le16(ADDframe.StatusCode); + ADDframe.TimeOutValue = cpu2le16(ADDframe.TimeOutValue); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_ADDBA_RSP), &ADDframe, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): TID(%d), BufSize(%d) <== \n", __FUNCTION__, Elem->Wcid, ADDframe.BaParm.TID, + ADDframe.BaParm.BufSize)); +} + + +VOID PeerAddBARspAction(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + PFRAME_ADDBA_RSP pFrame = NULL; + + /*ADDBA Response from unknown peer, ignore this.*/ + if (Elem->Wcid >= MAX_LEN_OF_MAC_TABLE) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("%s ==> Wcid(%d)\n", __FUNCTION__, Elem->Wcid)); + + /*hex_dump("PeerAddBARspAction()", Elem->Msg, Elem->MsgLen);*/ + + if (PeerAddBARspActionSanity(pAd, Elem->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) + ) + { + pAd->MacTab.Content[Elem->Wcid].BADeclineBitmap |= 1<BaParm.TID; + } + } +} + +VOID PeerDelBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) + +{ + PFRAME_DELBA_REQ pDelFrame = NULL; + + DBGPRINT(RT_DEBUG_TRACE,("%s ==>\n", __FUNCTION__)); + /*DELBA Request from unknown peer, ignore this.*/ + if (PeerDelBAActionSanity(pAd, Elem->Wcid, Elem->Msg, Elem->MsgLen)) + { + pDelFrame = (PFRAME_DELBA_REQ)(&Elem->Msg[0]); + +#ifdef PEER_DELBA_TX_ADAPT + if (pDelFrame->DelbaParm.TID == 0) + Peer_DelBA_Tx_Adapt_Enable(pAd, &pAd->MacTab.Content[Elem->Wcid]); +#endif /* PEER_DELBA_TX_ADAPT */ + + if (pDelFrame->DelbaParm.Initiator == ORIGINATOR) + { + DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> ORIGINATOR\n")); + BARecSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE); + } + else + { + DBGPRINT(RT_DEBUG_TRACE,("BA - PeerDelBAAction----> RECIPIENT, Reason = %d\n", pDelFrame->ReasonCode)); + /*hex_dump("DelBA Frame", pDelFrame, Elem->MsgLen);*/ + BAOriSessionTearDown(pAd, Elem->Wcid, pDelFrame->DelbaParm.TID, TRUE, FALSE); + } + } +} + + +BOOLEAN CntlEnqueueForRecv( + IN RTMP_ADAPTER *pAd, + IN ULONG Wcid, + IN ULONG MsgLen, + IN PFRAME_BA_REQ pMsg) +{ + PFRAME_BA_REQ pFrame = pMsg; + PBA_REC_ENTRY pBAEntry; + ULONG Idx; + UCHAR TID; + ULONG Now32; + + TID = (UCHAR)pFrame->BARControl.TID; + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): BAR-Wcid(%ld), Tid (%d)\n", __FUNCTION__, Wcid, TID)); + /*hex_dump("BAR", (PCHAR) pFrame, MsgLen);*/ + /* Do nothing if the driver is starting halt state.*/ + /* This might happen when timer already been fired before cancel timer with mlmehalt*/ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return FALSE; + + /* First check the size, it MUST not exceed the mlme queue size*/ + if (MsgLen > MGMT_DMA_BUFFER_SIZE) /* 1600B */ + { + DBGPRINT_ERR(("CntlEnqueueForRecv: frame too large, size = %ld \n", MsgLen)); + return FALSE; + } + else if (MsgLen != sizeof(FRAME_BA_REQ)) + { + DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen)); + return FALSE; + } + else if (MsgLen != sizeof(FRAME_BA_REQ)) + { + DBGPRINT_ERR(("CntlEnqueueForRecv: BlockAck Request frame length size = %ld incorrect\n", MsgLen)); + return FALSE; + } + + if ((Wcid < MAX_LEN_OF_MAC_TABLE) && (TID < 8)) + { + /* if this receiving packet is from SA that is in our OriEntry. Since WCID <9 has direct mapping. no need search.*/ + Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + } + else + { + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("BAR(%ld) : Tid (%d) - %04x:%04x\n", Wcid, TID, pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq )); + NdisGetSystemUpTime(&Now32); + if (SEQ_SMALLER(pBAEntry->LastIndSeq, pFrame->BAStartingSeq.field.StartSeq, MAXSEQ)) + { + LONG TmpSeq, seq; + /*MTWF_LOG(DBG_CAT_PROTO, CATPROTO_BA, DBG_LVL_TRACE, ("BAR Seq = %x, LastIndSeq = %x\n", pFrame->BAStartingSeq.field.StartSeq, pBAEntry->LastIndSeq));*/ + + seq = (pFrame->BAStartingSeq.field.StartSeq == 0) ? MAXSEQ :(pFrame->BAStartingSeq.field.StartSeq -1); + ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, seq); + pBAEntry->LastIndSeq = seq; + pBAEntry->LastIndSeqAtTimer = Now32; + + TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); + + if (TmpSeq != RESET_RCV_SEQ) { + pBAEntry->LastIndSeq = TmpSeq; + } + } + + return TRUE; +} + + +/* Description : Send SMPS Action frame If SMPS mode switches. */ +VOID SendSMPSAction(RTMP_ADAPTER *pAd, UCHAR Wcid, UCHAR smps) +{ + struct wifi_dev *wdev; + MAC_TABLE_ENTRY *pEntry; + UCHAR *pOutBuffer = NULL; + NDIS_STATUS NStatus; + FRAME_SMPS_ACTION Frame; + ULONG FrameLen; + + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("BA - MlmeADDBAAction() allocate memory failed \n")); + return; + } + + if (!VALID_WCID(Wcid)) + { + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_ERROR,("BA - Invalid WCID(%d)\n", Wcid)); + return; + } + + pEntry = &pAd->MacTab.Content[Wcid]; + wdev = pEntry->wdev; + if (!wdev) + { + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_ERROR, ("BA - wdev is null\n")); + return; + } + +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { +#ifdef MAC_REPEATER_SUPPORT + if (pEntry->bReptCli) + ActHeaderInit(pAd, &Frame.Hdr, pEntry->Addr, pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].RepeaterCli[pEntry->MatchReptCliIdx].CurrentAddress, wdev->bssid); + else +#endif /* MAC_REPEATER_SUPPORT */ + ActHeaderInit(pAd, &Frame.Hdr, pEntry->Addr, wdev->if_addr, wdev->bssid); + } + else +#endif /* APCLI_SUPPORT */ + ActHeaderInit(pAd, &Frame.Hdr, pEntry->Addr, wdev->if_addr, wdev->bssid); + Frame.Category = CATEGORY_HT; + Frame.Action = SMPS_ACTION; + switch (smps) + { + case MMPS_DISABLE: + Frame.smps = 0; + break; + case MMPS_DYNAMIC: + Frame.smps = 3; + break; + case MMPS_STATIC: + Frame.smps = 1; + break; + } + + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(FRAME_SMPS_ACTION), &Frame, + END_OF_ARGS); + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + DBGPRINT(RT_DEBUG_ERROR,("HT - %s( %d ) \n", __FUNCTION__, Frame.smps)); +} + + +#define RADIO_MEASUREMENT_REQUEST_ACTION 0 + +typedef struct GNU_PACKED _BEACON_REQUEST { + UCHAR RegulatoryClass; + UCHAR ChannelNumber; + USHORT RandomInterval; + USHORT MeasurementDuration; + UCHAR MeasurementMode; + UCHAR BSSID[MAC_ADDR_LEN]; + UCHAR ReportingCondition; + UCHAR Threshold; + UCHAR SSIDIE[2]; /* 2 byte*/ +} BEACON_REQUEST; + +typedef struct GNU_PACKED _MEASUREMENT_REQ +{ + UCHAR ID; + UCHAR Length; + UCHAR Token; + UCHAR RequestMode; + UCHAR Type; +} MEASUREMENT_REQ; + + +#ifdef CONFIG_AP_SUPPORT +VOID SendBeaconRequest(RTMP_ADAPTER *pAd, UCHAR Wcid) +{ + UCHAR *pOutBuffer = NULL; + NDIS_STATUS NStatus; + FRAME_RM_REQ_ACTION Frame; + ULONG FrameLen; + BEACON_REQUEST BeaconReq; + MEASUREMENT_REQ MeasureReg; + UCHAR apidx; + + if (IS_ENTRY_APCLI(&pAd->MacTab.Content[Wcid])) + return; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); /*Get an unused nonpaged memory*/ + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("Radio - SendBeaconRequest() allocate memory failed \n")); + return; + } + apidx = pAd->MacTab.Content[Wcid].func_tb_idx; + ActHeaderInit(pAd, &Frame.Hdr, pAd->MacTab.Content[Wcid].Addr, pAd->ApCfg.MBSSID[apidx].wdev.if_addr, pAd->ApCfg.MBSSID[apidx].wdev.bssid); + + Frame.Category = CATEGORY_RM; + Frame.Action = RADIO_MEASUREMENT_REQUEST_ACTION; + 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 RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk, + IN UCHAR wdev_idx) +{ + PNDIS_PACKET pRxPkt; + UCHAR Header802_3[LENGTH_802_3]; + struct wifi_dev *wdev; + + ASSERT(wdev_idx < WDEV_NUM_MAX); + if (wdev_idx >= WDEV_NUM_MAX) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid wdev_idx(%d)\n", __FUNCTION__, wdev_idx)); + return; + } + wdev = pAd->wdev_list[wdev_idx]; + +/* + 1. get 802.3 Header + 2. remove LLC + a. pointer pRxBlk->pData to payload + b. modify pRxBlk->DataSize +*/ + RTMP_802_11_REMOVE_LLC_AND_CONVERT_TO_802_3(pRxBlk, Header802_3); + ASSERT(pRxBlk->pRxPacket); + + pRxPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket); + + RTMP_OS_PKT_INIT(pRxBlk->pRxPacket, + get_netdev_from_bssid(pAd, wdev_idx), + pRxBlk->pData, pRxBlk->DataSize); + + /* copy 802.3 header, if necessary */ + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU)) + { + UCHAR VLAN_Size = 0; + UCHAR *data_p; + USHORT VLAN_VID = 0, VLAN_Priority = 0; + + // TODO: shiang-usw, fix me!! +#ifdef CONFIG_AP_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_STA) || RX_BLK_TEST_FLAG(pRxBlk, fRX_WDS)) { + /* Check if need to insert VLAN tag to the received packet */ + WDEV_VLAN_INFO_GET(pAd, VLAN_VID, VLAN_Priority, wdev); + if (VLAN_VID) + VLAN_Size = LENGTH_802_1Q; + } +#endif /* CONFIG_AP_SUPPORT */ + + { + 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, TPID); + } + } +} + + +#define INDICATE_LEGACY_OR_AMSDU(_pAd, _pRxBlk, _wdev_idx) \ + do \ + { \ + if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_AMSDU)) \ + { \ + Indicate_AMSDU_Packet(_pAd, _pRxBlk, _wdev_idx); \ + } \ + else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_EAP)) \ + { \ + Indicate_EAPOL_Packet(_pAd, _pRxBlk, _wdev_idx); \ + } \ + else \ + { \ + Indicate_Legacy_Packet(_pAd, _pRxBlk, _wdev_idx); \ + } \ + } while (0); + + +static VOID ba_enqueue_reordering_packet( + IN RTMP_ADAPTER *pAd, + IN BA_REC_ENTRY *pBAEntry, + IN RX_BLK *pRxBlk, + IN UCHAR wdev_idx) +{ + 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, wdev_idx); + +#ifdef HDR_TRANS_SUPPORT + if (pRxBlk->bHdrRxTrans) { + RTMP_OS_PKT_INIT(pRxBlk->pRxPacket, + get_netdev_from_bssid(pAd, wdev_idx), + pRxBlk->pTransData, pRxBlk->TransDataSize); + } + else +#endif + { + /* it is necessary for reordering packet to record + which BSS it come from + */ + RTMP_SET_PACKET_WDEV(pRxBlk->pRxPacket, wdev_idx); + } + + STATS_INC_RX_PACKETS(pAd, wdev_idx); + + 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); + #ifdef NEW_IXIA_METHOD + pAd->tr_ststic.rx[ALREADY_IN_ORDER]++; + #endif + } + + ASSERT((0<= pBAEntry->list.qlen) && (pBAEntry->list.qlen <= pBAEntry->BAWinSize)); + NdisReleaseSpinLock(&pBAEntry->RxReRingLock); + } + else + { + ULONG Now32; + + if (mpdu_blk) + ba_mpdu_blk_free(pAd, mpdu_blk); + 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, wdev_idx); + + Sequence = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); + + if (Sequence != RESET_RCV_SEQ) { + pBAEntry->LastIndSeq = Sequence; + } + + NdisGetSystemUpTime(&Now32); + pBAEntry->LastIndSeqAtTimer = Now32; + } +} + + +#ifdef MAC_REPEATER_SUPPORT +VOID Rtmp_Chk_Reset_Ba_Sequence(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + HEADER_802_11 *pHeader = pRxBlk->pHeader; + FRAME_CONTROL *pFmeCtrl = &pHeader->FC; + UCHAR wcid = pRxBlk->wcid; + MAC_TABLE_ENTRY *pEntry = NULL; + + UINT32 value; + + if (!pAd->ApCfg.bMACRepeaterEn) + return; + + pEntry = &pAd->MacTab.Content[wcid]; + + if (!pEntry) + return; + + if ((pFmeCtrl->FrDs == 1) && (pFmeCtrl->ToDs == 0)) + { + if (IS_ENTRY_APCLI(pEntry) && (pEntry->bReptCli == TRUE)) + { + value = (pEntry->Addr[0] | (pEntry->Addr[1] << 8) | + (pEntry->Addr[2] << 16) | (pEntry->Addr[3] << 24)); + RTMP_IO_WRITE32(pAd, BSCR0, value); + + RTMP_IO_READ32(pAd, BSCR1, &value); + value &= ~(BA_MAC_ADDR_47_32_MASK | RST_BA_TID_MASK | RST_BA_SEL_MASK); + value |= BA_MAC_ADDR_47_32((pEntry->Addr[4] | (pEntry->Addr[5] << 8))); + value |= (RST_BA_SEL(RST_BA_MAC_TID_MATCH) | RST_BA_TID(pRxBlk->TID) | START_RST_BA_SB); + RTMP_IO_WRITE32(pAd, BSCR1, value); + pAd->RalinkCounters.BaSnResetCnt++; + } + } + +} +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef CONFIG_BA_REORDER_MONITOR +void ba_timeout_flush(PRTMP_ADAPTER pAd) +{ + ULONG now; + UINT32 idx0 = 0; + UINT32 idx1 = 0; + PBA_REC_ENTRY pBAEntry = NULL; + + NdisGetSystemUpTime(&now); + + for (idx0 = 0; idx0 < 16; idx0++) { + idx1 = 0; + while ((pAd->BATable.ba_timeout_bitmap[idx0] != 0) && (idx1 < 32)) { + + if (pAd->BATable.ba_timeout_bitmap[idx0] & 0x1) { + pBAEntry = &pAd->BATable.BARecEntry[(idx0 << 5) + idx1]; + ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, now); + //pBAEntry->check_amsdu_miss = FALSE; + } + + pAd->BATable.ba_timeout_bitmap[idx0] >>= 1; + idx1++; + } + } + + pAd->BATable.ba_timeout_check = FALSE; +} + +void ba_timeout_monitor(PRTMP_ADAPTER pAd) +{ + UINT32 idx = 0; + PBA_REC_ENTRY pBAEntry = NULL; + ULONG now; + POS_COOKIE obj = (POS_COOKIE) pAd->OS_Cookie; + BOOLEAN need_check = FALSE; + static int NeedFallBack=0; + + if ( pAd->MacTab.Size >= 20 ) + { + pAd->BATable.ba_reordering_packet_timeout = MULTI_CLIENT_REORDERING_PACKET_TIMEOUT; + NeedFallBack = 0; + } + else + { + NeedFallBack ++; + if (NeedFallBack >= 5) + pAd->BATable.ba_reordering_packet_timeout = REORDERING_PACKET_TIMEOUT; + } + + if (!pAd->BATable.ba_timeout_check) { + NdisGetSystemUpTime(&now); + for (idx = 0; idx < MAX_LEN_OF_BA_REC_TABLE; idx++) { + pBAEntry = &pAd->BATable.BARecEntry[idx]; + + if ((pBAEntry->REC_BA_Status == Recipient_Accept) + && (pBAEntry->list.qlen > 0)) { + + if (RTMP_TIME_AFTER((unsigned long)now, + (unsigned long)(pBAEntry->LastIndSeqAtTimer + pAd->BATable.ba_reordering_packet_timeout ))) { + need_check = TRUE; + pAd->BATable.ba_timeout_bitmap[(idx >> 5)] |= (1 << (idx % 32)); + } + } + } + + if (need_check) { + pAd->BATable.ba_timeout_check = need_check; + RTMP_OS_TASKLET_SCHE(&obj->rx_done_task); + } + } +} +#endif + + + +/* + ========================================================================== + Description: + Indicate this packet to upper layer or put it into reordering buffer + + Parametrs: + pRxBlk : carry necessary packet info 802.11 format + wdev_idx : the packet received from which wdev + + Return : + none + + Note : + the packet queued into reordering buffer need to cover to 802.3 format + or pre_AMSDU format + ========================================================================== +*/ +VOID Indicate_AMPDU_Packet(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk, UCHAR wdev_idx) +{ + USHORT Idx; + PBA_REC_ENTRY pBAEntry = NULL; + UINT16 Sequence = pRxBlk->pHeader->Sequence; + ULONG Now32; + INT max_pkt_len, data_len; + +#ifdef HDR_TRANS_SUPPORT + if (pRxBlk->bHdrRxTrans) { + max_pkt_len = 1514; + data_len = pRxBlk->TransDataSize; + } + else +#endif /* HDR_TRANS_SUPPORT */ + { + max_pkt_len = MAX_RX_PKT_LEN; + data_len = pRxBlk->DataSize; + } + + if (!data_len) { + /* release packet*/ + /* avoid processing with null paiload packets - QCA61X4A bug */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + + if (!RX_BLK_TEST_FLAG(pRxBlk, fRX_AMSDU) && (data_len > max_pkt_len)) + { + static int err_size; + + err_size++; + if (err_size > 20) { + DBGPRINT(RT_DEBUG_TRACE, ("AMPDU DataSize = %d\n", pRxBlk->DataSize)); + hex_dump("802.11 Header", (UCHAR *)pRxBlk->pHeader, 24); + hex_dump("Payload", pRxBlk->pData, 64); + err_size = 0; + } + + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + if (pRxBlk->wcid < MAX_LEN_OF_MAC_TABLE) + { + Idx = pAd->MacTab.Content[pRxBlk->wcid].BARecWcidArray[pRxBlk->TID]; + if (Idx == 0) + { + /* Rec BA Session had been torn down */ + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, wdev_idx); + return; + } + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + } + else + { + /* impossible !!! release packet*/ + ASSERT(0); + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return; + } + + ASSERT(pBAEntry); + + /* update last rx time*/ + NdisGetSystemUpTime(&Now32); + + pBAEntry->rcvSeq = Sequence; + + ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32); + //pBAEntry->LastIndSeqAtTimer = Now32; + + + /* Reset Last Indicate Sequence*/ + if (pBAEntry->LastIndSeq == RESET_RCV_SEQ) + { + ASSERT((pBAEntry->list.qlen == 0) && (pBAEntry->list.next == NULL)); + + /* reset rcv sequence of BA session */ + pBAEntry->LastIndSeq = Sequence; + pBAEntry->LastIndSeqAtTimer = Now32; + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, wdev_idx); + return; + } + + + /* I. Check if in order. */ + if (SEQ_STEPONE(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) + { + USHORT LastIndSeq; + + pBAEntry->LastIndSeq = Sequence; + INDICATE_LEGACY_OR_AMSDU(pAd, pRxBlk, wdev_idx); + 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) + { +#ifdef NEW_IXIA_METHOD + pAd->tr_ststic.rx[DUP_SEQ_PKT]++; +#endif + pBAEntry->nDropPacket++; +#ifdef MAC_REPEATER_SUPPORT + Rtmp_Chk_Reset_Ba_Sequence(pAd, pRxBlk); +#endif /* MAC_REPEATER_SUPPORT */ + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + } + /* III. Drop Old Received Packet*/ + else if (SEQ_SMALLER(Sequence, pBAEntry->LastIndSeq, MAXSEQ)) + { +#ifdef NEW_IXIA_METHOD + pAd->tr_ststic.rx[DUP_SEQ_PKT]++; +#endif + pBAEntry->nDropPacket++; +#ifdef MAC_REPEATER_SUPPORT + Rtmp_Chk_Reset_Ba_Sequence(pAd, pRxBlk); +#endif /* MAC_REPEATER_SUPPORT */ + 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, wdev_idx); + } + /* 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; + ba_indicate_reordering_mpdus_le_seq(pAd, pBAEntry, (WinStartSeq - 1) & MAXSEQ); + pBAEntry->LastIndSeq = (WinStartSeq - 1) & MAXSEQ; /* TmpSeq; */ + + pBAEntry->LastIndSeqAtTimer = Now32; + + ba_enqueue_reordering_packet(pAd, pBAEntry, pRxBlk, wdev_idx); + + TmpSeq = ba_indicate_reordering_mpdus_in_order(pAd, pBAEntry, pBAEntry->LastIndSeq); + if (TmpSeq != RESET_RCV_SEQ) + pBAEntry->LastIndSeq = TmpSeq; + } +} + + +VOID BaReOrderingBufferMaintain(RTMP_ADAPTER *pAd) +{ + ULONG Now32; + UCHAR Wcid; + USHORT Idx; + UCHAR TID; + PBA_REC_ENTRY pBAEntry = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + + /* update last rx time*/ + NdisGetSystemUpTime(&Now32); + + for (Wcid = 1; Wcid < MAX_LEN_OF_MAC_TABLE; Wcid++) + { + pEntry = &pAd->MacTab.Content[Wcid]; + if (IS_ENTRY_NONE(pEntry)) + continue; + + for (TID= 0; TID < NUM_OF_TID; TID++) + { + Idx = pAd->MacTab.Content[Wcid].BARecWcidArray[TID]; + pBAEntry = &pAd->BATable.BARecEntry[Idx]; + ba_flush_reordering_timeout_mpdus(pAd, pBAEntry, Now32); + } + } +} + + +#ifdef PEER_DELBA_TX_ADAPT +static VOID Peer_DelBA_Tx_Adapt_Enable( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry) +{ +#ifdef MCS_LUT_SUPPORT + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(): No need this for HIF_MT!\n", __FUNCTION__)); + return; + } +#endif /* MT_MAC */ + + if ((pAd->CommonCfg.bBADecline == TRUE) || + (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET))) + { + /* we should not do this if bBADecline is TRUE or RGD is ON */ + return; + } + + if(!RTMP_TEST_MORE_FLAG(pAd, fASIC_CAP_MCS_LUT) || !(pEntry->wcid < 128)) + { + DBGPRINT(RT_DEBUG_WARN, + ("%s(): Warning! This chip does not support HW Tx rate lookup.\n", + __FUNCTION__)); + return; + } + + if (pEntry) + { + USHORT RegId = 0; + UINT32 MacReg = 0, BitLUT; + pEntry->bPeerDelBaTxAdaptEn = 1; + /* 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 */ + 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 +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(): No need this for HIF_MT!\n", __FUNCTION__)); + return; + } +#endif /* MT_MAC */ + + if(!RTMP_TEST_MORE_FLAG(pAd, fASIC_CAP_MCS_LUT) || !(pEntry->wcid < 128)) + { + DBGPRINT(RT_DEBUG_WARN, + ("%s(): Warning! This chip does not support HW Tx rate lookup.\n", + __FUNCTION__)); + return; + } + + if (pEntry && pEntry->bPeerDelBaTxAdaptEn) + { + UINT32 BitLUT; + 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; + DBGPRINT(RT_DEBUG_TRACE, + ("%s():bPeerDelBaTxAdaptEn = 0x%x\n", + __FUNCTION__, pEntry->bPeerDelBaTxAdaptEn)); + } +#endif /* MCS_LUT_SUPPORT */ +} +#endif /* PEER_DELBA_TX_ADAPT */ + + +#ifdef MAC_REPEATER_SUPPORT +VOID RxTrackingInit(struct wifi_dev *wdev) +{ + UCHAR j; + RX_TRACKING_T *pTracking = NULL; + RX_TA_TID_SEQ_MAPPING *pTaTidSeqMapEntry = NULL; + + pTracking = &wdev->rx_tracking; + pTaTidSeqMapEntry = &pTracking->LastRxWlanIdx; + + pTracking->TriggerNum = 0; + + pTaTidSeqMapEntry->RxDWlanIdx = 0xff; + pTaTidSeqMapEntry->MuarIdx = 0xff; + for (j = 0; j < 8; j++) + { + pTaTidSeqMapEntry->TID_SEQ[j] = 0xffff; + } + pTaTidSeqMapEntry->LatestTID = 0xff; + NdisZeroMemory(pTaTidSeqMapEntry->LatestTA, MAC_ADDR_LEN); + + return; +} + +VOID TaTidRecAndCmp( + struct _RTMP_ADAPTER *pAd, + struct rxd_base_struct *rx_base, + UINT16 SN, + BOOLEAN isBAR, + HEADER_802_11 *pHeader) +{ + struct wifi_dev *wdev = NULL; + RX_TRACKING_T *pTracking = NULL; + RX_TA_TID_SEQ_MAPPING *pTaTidSeqMapEntry = NULL; + UCHAR Widx = rx_base->rxd_2.wlan_idx; + UCHAR Tid = rx_base->rxd_2.tid; + UCHAR MuarIdx = rx_base->rxd_1.bssid; + UINT32 value = 0; + MAC_TABLE_ENTRY *pEntry = NULL; + struct _STA_TR_ENTRY *tr_entry = NULL; + UINT32 i; + UCHAR Zero[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + if ( pAd->ApCfg.bBaSnResetDis) + return; + if (!pAd->ApCfg.bMACRepeaterEn) + return; + if (isBAR) { + PFRAME_BA_REQ pFrame = (PFRAME_BA_REQ)(&(pHeader->FC)); + + Tid = pFrame->BARControl.TID; + + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) { + if (!IS_ENTRY_NONE(&pAd->MacTab.Content[i])) { + pEntry = &pAd->MacTab.Content[i]; + tr_entry = &pAd->MacTab.tr_entry[i]; + if (tr_entry) + wdev = tr_entry->wdev; + + if (NdisEqualMemory(pFrame->Addr1, pEntry->ReptCliAddr, MAC_ADDR_LEN) && + NdisEqualMemory(pFrame->Addr2, pEntry->Addr, MAC_ADDR_LEN)) { + Widx = pEntry->wcid; + break; + } else if (wdev && NdisEqualMemory(pEntry->ReptCliAddr, Zero, MAC_ADDR_LEN) && + NdisEqualMemory(pFrame->Addr2, pEntry->Addr, MAC_ADDR_LEN) && + NdisEqualMemory(pFrame->Addr1, wdev->if_addr, MAC_ADDR_LEN)) { + Widx = pEntry->wcid; + break; + } + } + } + } + + if (Widx >= MAX_LEN_OF_MAC_TABLE) + return; + + tr_entry = &pAd->MacTab.tr_entry[Widx]; + + if (tr_entry) { + wdev = tr_entry->wdev; + } + + if (wdev == NULL) + return; + + if ((wdev->wdev_type != WDEV_TYPE_STA)) + { + return; + } + + pTracking = &wdev->rx_tracking; + pTaTidSeqMapEntry = &pTracking->LastRxWlanIdx; + if (isBAR) { + if (NdisEqualMemory(pTaTidSeqMapEntry->LatestTA, pHeader->Addr2, MAC_ADDR_LEN)) + MuarIdx = pTaTidSeqMapEntry->MuarIdx; + } + if (pTaTidSeqMapEntry->RxDWlanIdx == 0xff) + {/*first Rx pkt, just record it.*/ + pTaTidSeqMapEntry->RxDWlanIdx = Widx; + pTaTidSeqMapEntry->MuarIdx = MuarIdx; + pTaTidSeqMapEntry->TID_SEQ[Tid] = SN; + pTaTidSeqMapEntry->LatestTID = Tid; + NdisCopyMemory(pTaTidSeqMapEntry->LatestTA, pHeader->Addr2, MAC_ADDR_LEN); + } + else + { + /* compare*/ + if ((pTaTidSeqMapEntry->MuarIdx == MuarIdx) && + (pTaTidSeqMapEntry->RxDWlanIdx != Widx) && + pTaTidSeqMapEntry->LatestTID == Tid) + { + /*condition match, trigger scoreboard update*/ + + DBGPRINT(RT_DEBUG_INFO, + ("last Widx = %d, muar_idx = %x, last TID = %d\n", + pTaTidSeqMapEntry->RxDWlanIdx, + pTaTidSeqMapEntry->MuarIdx, + pTaTidSeqMapEntry->LatestTID)); + + DBGPRINT(RT_DEBUG_INFO, + ("new Widx = %d, muar_idx = %x, last TID = %d\n", + Widx, + MuarIdx, + Tid)); + + + + pEntry=&pAd->MacTab.Content[Widx]; + + if (!pEntry) + return; + else { + value = (pEntry->Addr[0] | (pEntry->Addr[1] << 8) | + (pEntry->Addr[2] << 16) | (pEntry->Addr[3] << 24)); + RTMP_IO_WRITE32(pAd, BSCR0, value); + + RTMP_IO_READ32(pAd, BSCR1, &value); + value &= ~(BA_MAC_ADDR_47_32_MASK | RST_BA_TID_MASK | RST_BA_SEL_MASK); + value |= BA_MAC_ADDR_47_32((pEntry->Addr[4] | (pEntry->Addr[5] << 8))); + value |= (RST_BA_SEL(RST_BA_MAC_TID_MATCH) | RST_BA_TID(Tid) | START_RST_BA_SB); + RTMP_IO_WRITE32(pAd, BSCR1, value); + pAd->RalinkCounters.BaSnResetCnt++; + pTracking->TriggerNum++; + } + } + + /*update lastest rx information.*/ + pTaTidSeqMapEntry->RxDWlanIdx = Widx; + pTaTidSeqMapEntry->MuarIdx = MuarIdx; + pTaTidSeqMapEntry->TID_SEQ[Tid] = SN; + pTaTidSeqMapEntry->LatestTID = Tid; + NdisCopyMemory(pTaTidSeqMapEntry->LatestTA, pHeader->Addr2, MAC_ADDR_LEN); + } +} +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/bn_lib.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/bn_lib.c new file mode 100644 index 000000000..1cabc7f97 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/bn_lib.c @@ -0,0 +1,6977 @@ +/* ==================================================================== + * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgment: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ +#ifdef DOT11_SAE_OPENSSL_BN + +#include "bn.h" + +static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *ctx); + + +void OPENSSL_cleanse(void *ptr, ULONG len) +{ + memset(ptr, 0, len); +} + +const BIGNUM *BN_value_one(void) +{ + static const BN_ULONG data_one = 1L; + static const BIGNUM const_one = {(BN_ULONG *)&data_one, 1, 1, 0, BN_FLG_STATIC_DATA}; + return &const_one; +} + +int BN_num_bits_word(BN_ULONG l) +{ + static const char bits[256] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + }; + { + if (l & 0xffff0000L) { + if (l & 0xff000000L) + return (bits[(int)(l >> 24L)] + 24); + else + return (bits[(int)(l >> 16L)] + 16); + } else { + if (l & 0xff00L) + return (bits[(int)(l >> 8)] + 8); + else + return bits[(int)(l)]; + } + } +} + +int BN_num_bits(const BIGNUM *a) +{ + int i = a->top - 1; + bn_check_top(a); + + if (BN_is_zero(a)) + return 0; + + return ((i * BN_BITS2) + BN_num_bits_word(a->d[i])); +} + +static void bn_free_d(BIGNUM *a) +{ + if (a->d) + os_free_mem(NULL, a->d); +} + + +void BN_clear_free(BIGNUM *a) +{ + int i; + + if (a == NULL) + return; + + bn_check_top(a); + + if (a->d != NULL) { + memset(a->d, 0, a->dmax * sizeof(a->d[0])); + + if (!BN_get_flags(a, BN_FLG_STATIC_DATA)) + bn_free_d(a); + } + + i = BN_get_flags(a, BN_FLG_MALLOCED); + memset(a, 0, sizeof(*a)); + + if (i) + os_free_mem(NULL, a); +} + +void BN_free(BIGNUM *a) +{ + if (a == NULL) + return; + + bn_check_top(a); + + if (!BN_get_flags(a, BN_FLG_STATIC_DATA)) + bn_free_d(a); + + if (a->flags & BN_FLG_MALLOCED) + os_free_mem(NULL, a); + else { + a->d = NULL; + } +} + +void bn_init(BIGNUM *a) +{ + static BIGNUM nilbn; + *a = nilbn; + bn_check_top(a); +} + +BIGNUM *BN_new(void) +{ + BIGNUM *ret; + os_alloc_mem(NULL, (UCHAR **)&ret, sizeof(struct bignum_st)); + + if (ret == NULL) + return NULL; + + ret->flags = BN_FLG_MALLOCED; + /* ellis */ + ret->top = 0; + ret->dmax = 0; + ret->d = NULL; + ret->neg = 0; + bn_check_top(ret); + return ret; +} + +BIGNUM *BN_secure_new(void) +{ + BIGNUM *ret = BN_new(); + + if (ret != NULL) + ret->flags |= BN_FLG_SECURE; + + return ret; +} + +/* This is used by bn_expand2() */ +/* The caller MUST check that words > b->dmax before calling this */ +static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words) +{ + BN_ULONG *A, *a = NULL; + const BN_ULONG *B; + int i; + bn_check_top(b); + + if (words > (INT_MAX / (4 * BN_BITS2))) { + BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_BIGNUM_TOO_LONG); + return NULL; + } + + if (BN_get_flags(b, BN_FLG_STATIC_DATA)) { + BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA); + return NULL; + } + + os_alloc_mem(NULL, (UCHAR **)&A, sizeof(BN_ULONG)*words); + memset(A, 0, sizeof(BN_ULONG)*words); + a = A; + + if (A == NULL) { + BNerr(BN_F_BN_EXPAND_INTERNAL, ERR_R_MALLOC_FAILURE); + return NULL; + } + + B = b->d; + + /* Check if the previous number needs to be copied */ + if (B != NULL) { + for (i = b->top >> 2; i > 0; i--, A += 4, B += 4) { + /* + * The fact that the loop is unrolled + * 4-wise is a tribute to Intel. It's + * the one that doesn't have enough + * registers to accommodate more data. + * I'd unroll it 8-wise otherwise:-) + * + * + */ + BN_ULONG a0, a1, a2, a3; + a0 = B[0]; + a1 = B[1]; + a2 = B[2]; + a3 = B[3]; + A[0] = a0; + A[1] = a1; + A[2] = a2; + A[3] = a3; + } + + switch (b->top & 3) { + case 3: + A[2] = B[2]; + + /* fall thru */ + case 2: + A[1] = B[1]; + + /* fall thru */ + case 1: + A[0] = B[0]; + + /* fall thru */ + case 0: + /* Without the "case 0" some old optimizers got this wrong. */ + ; + } + } + + return a; +} + + +/* + * This is an internal function that should not be used in applications. It + * ensures that 'b' has enough room for a 'words' word number and initialises + * any unused part of b->d with leading zeros. It is mostly used by the + * various BIGNUM routines. If there is an error, NULL is returned. If not, + * 'b' is returned. + */ + +BIGNUM *bn_expand2(BIGNUM *b, int words) +{ + bn_check_top(b); + + if (words > b->dmax) { + BN_ULONG *a = bn_expand_internal(b, words); + + if (!a) + return NULL; + + if (b->d) { + memset(b->d, 0, b->dmax * sizeof(b->d[0])); + bn_free_d(b); + } + + b->d = a; + b->dmax = words; + } + + bn_check_top(b); + return b; +} + +static inline BIGNUM *bn_expand(BIGNUM *a, int bits) +{ + if (bits > (INT_MAX - BN_BITS2 + 1)) + return NULL; + + if (((bits + BN_BITS2 - 1) / BN_BITS2) <= (a)->dmax) + return a; + + return bn_expand2((a), (bits + BN_BITS2 - 1) / BN_BITS2); +} + + +BIGNUM *BN_dup(const BIGNUM *a) +{ + BIGNUM *t; + + if (a == NULL) + return NULL; + + bn_check_top(a); + t = BN_get_flags(a, BN_FLG_SECURE) ? BN_secure_new() : BN_new(); + + if (t == NULL) + return NULL; + + if (!BN_copy(t, a)) { + BN_free(t); + return NULL; + } + + bn_check_top(t); + return t; +} + +BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b) +{ + int i; + BN_ULONG *A; + const BN_ULONG *B; + bn_check_top(b); + + if (a == b) + return a; + + if (bn_wexpand(a, b->top) == NULL) + return NULL; + + A = a->d; + B = b->d; + + for (i = b->top >> 2; i > 0; i--, A += 4, B += 4) { + BN_ULONG a0, a1, a2, a3; + a0 = B[0]; + a1 = B[1]; + a2 = B[2]; + a3 = B[3]; + A[0] = a0; + A[1] = a1; + A[2] = a2; + A[3] = a3; + } + + /* ultrix cc workaround, see comments in bn_expand_internal */ + switch (b->top & 3) { + case 3: + A[2] = B[2]; + + /* fall thru */ + case 2: + A[1] = B[1]; + + /* fall thru */ + case 1: + A[0] = B[0]; + + /* fall thru */ + case 0: + ; + } + + + if (BN_get_flags(b, BN_FLG_CONSTTIME) != 0) + BN_set_flags(a, BN_FLG_CONSTTIME); + + a->top = b->top; + a->neg = b->neg; + bn_check_top(a); + return a; +} + +void BN_swap(BIGNUM *a, BIGNUM *b) +{ + int flags_old_a, flags_old_b; + BN_ULONG *tmp_d; + int tmp_top, tmp_dmax, tmp_neg; + bn_check_top(a); + bn_check_top(b); + flags_old_a = a->flags; + flags_old_b = b->flags; + tmp_d = a->d; + tmp_top = a->top; + tmp_dmax = a->dmax; + tmp_neg = a->neg; + a->d = b->d; + a->top = b->top; + a->dmax = b->dmax; + a->neg = b->neg; + b->d = tmp_d; + b->top = tmp_top; + b->dmax = tmp_dmax; + b->neg = tmp_neg; + a->flags = + (flags_old_a & BN_FLG_MALLOCED) | (flags_old_b & BN_FLG_STATIC_DATA); + b->flags = + (flags_old_b & BN_FLG_MALLOCED) | (flags_old_a & BN_FLG_STATIC_DATA); + bn_check_top(a); + bn_check_top(b); +} + +void BN_clear(BIGNUM *a) +{ + bn_check_top(a); + + if (a->d != NULL) + memset(a->d, 0, sizeof(*a->d) * a->dmax); + + a->top = 0; + a->neg = 0; +} + +BN_ULONG BN_get_word(const BIGNUM *a) +{ + if (a->top > 1) + return BN_MASK2; + else if (a->top == 1) + return a->d[0]; + + /* a->top == 0 */ + return 0; +} + +int BN_set_word(BIGNUM *a, BN_ULONG w) +{ + bn_check_top(a); + + if (bn_expand(a, (int)sizeof(BN_ULONG) * 8) == NULL) + return 0; + + a->neg = 0; + a->d[0] = w; + a->top = (w ? 1 : 0); + bn_check_top(a); + return 1; +} + +BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) +{ + unsigned int i, m; + unsigned int n; + BN_ULONG l; + BIGNUM *bn = NULL; + + if (ret == NULL) + ret = bn = BN_new(); + + if (ret == NULL) + return NULL; + + bn_check_top(ret); + + /* Skip leading zero's. */ + for ( ; len > 0 && *s == 0; s++, len--) + continue; + + n = len; + + if (n == 0) { + ret->top = 0; + return ret; + } + + i = ((n - 1) / BN_BYTES) + 1; + m = ((n - 1) % (BN_BYTES)); + + if (bn_wexpand(ret, (int)i) == NULL) { + BN_free(bn); + return NULL; + } + + ret->top = i; + ret->neg = 0; + l = 0; + + while (n--) { + l = (l << 8L) | *(s++); + + if (m-- == 0) { + ret->d[--i] = l; + l = 0; + m = BN_BYTES - 1; + } + } + + /* + * need to call this due to clear byte at top if avoiding having the top + * bit set (-ve number) + */ + bn_correct_top(ret); + return ret; +} + +/* ignore negative */ +static int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) +{ + int i; + BN_ULONG l; + bn_check_top(a); + i = BN_num_bytes(a); + + if (tolen == -1) + tolen = i; + else if (tolen < i) + return -1; + + /* Add leading zeroes if necessary */ + if (tolen > i) { + memset(to, 0, tolen - i); + to += tolen - i; + } + + while (i--) { + l = a->d[i / BN_BYTES]; + *(to++) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff; + } + + return tolen; +} + +int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) +{ + if (tolen < 0) + return -1; + + return bn2binpad(a, to, tolen); +} + +int BN_bn2bin(const BIGNUM *a, unsigned char *to) +{ + return bn2binpad(a, to, -1); +} + +BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret) +{ + unsigned int i, m; + unsigned int n; + BN_ULONG l; + BIGNUM *bn = NULL; + + if (ret == NULL) + ret = bn = BN_new(); + + if (ret == NULL) + return NULL; + + bn_check_top(ret); + s += len; + + /* Skip trailing zeroes. */ + for ( ; len > 0 && s[-1] == 0; s--, len--) + continue; + + n = len; + + if (n == 0) { + ret->top = 0; + return ret; + } + + i = ((n - 1) / BN_BYTES) + 1; + m = ((n - 1) % (BN_BYTES)); + + if (bn_wexpand(ret, (int)i) == NULL) { + BN_free(bn); + return NULL; + } + + ret->top = i; + ret->neg = 0; + l = 0; + + while (n--) { + s--; + l = (l << 8L) | *s; + + if (m-- == 0) { + ret->d[--i] = l; + l = 0; + m = BN_BYTES - 1; + } + } + + /* + * need to call this due to clear byte at top if avoiding having the top + * bit set (-ve number) + */ + bn_correct_top(ret); + return ret; +} + +int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen) +{ + int i; + BN_ULONG l; + bn_check_top(a); + i = BN_num_bytes(a); + + if (tolen < i) + return -1; + + /* Add trailing zeroes if necessary */ + if (tolen > i) + memset(to + i, 0, tolen - i); + + to += i; + + while (i--) { + l = a->d[i / BN_BYTES]; + to--; + *to = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff; + } + + return tolen; +} + +int BN_ucmp(const BIGNUM *a, const BIGNUM *b) +{ + int i; + BN_ULONG t1, t2, *ap, *bp; + bn_check_top(a); + bn_check_top(b); + i = a->top - b->top; + + if (i != 0) + return i; + + ap = a->d; + bp = b->d; + + for (i = a->top - 1; i >= 0; i--) { + t1 = ap[i]; + t2 = bp[i]; + + if (t1 != t2) + return ((t1 > t2) ? 1 : -1); + } + + return 0; +} + +int BN_cmp(const BIGNUM *a, const BIGNUM *b) +{ + int i; + int gt, lt; + BN_ULONG t1, t2; + + if ((a == NULL) || (b == NULL)) { + if (a != NULL) + return -1; + else if (b != NULL) + return 1; + else + return 0; + } + + bn_check_top(a); + bn_check_top(b); + + if (a->neg != b->neg) { + if (a->neg) + return -1; + else + return 1; + } + + if (a->neg == 0) { + gt = 1; + lt = -1; + } else { + gt = -1; + lt = 1; + } + + if (a->top > b->top) + return gt; + + if (a->top < b->top) + return lt; + + for (i = a->top - 1; i >= 0; i--) { + t1 = a->d[i]; + t2 = b->d[i]; + + if (t1 > t2) + return gt; + + if (t1 < t2) + return lt; + } + + return 0; +} + +int BN_set_bit(BIGNUM *a, int n) +{ + int i, j, k; + + if (n < 0) + return 0; + + i = n / BN_BITS2; + j = n % BN_BITS2; + + if (a->top <= i) { + if (bn_wexpand(a, i + 1) == NULL) + return 0; + + for (k = a->top; k < i + 1; k++) + a->d[k] = 0; + + a->top = i + 1; + } + + a->d[i] |= (((BN_ULONG)1) << j); + bn_check_top(a); + return 1; +} + +int BN_clear_bit(BIGNUM *a, int n) +{ + int i, j; + bn_check_top(a); + + if (n < 0) + return 0; + + i = n / BN_BITS2; + j = n % BN_BITS2; + + if (a->top <= i) + return 0; + + a->d[i] &= (~(((BN_ULONG)1) << j)); + bn_correct_top(a); + return 1; +} + +int BN_is_bit_set(const BIGNUM *a, int n) +{ + int i, j; + bn_check_top(a); + + if (n < 0) + return 0; + + i = n / BN_BITS2; + j = n % BN_BITS2; + + if (a->top <= i) + return 0; + + return (int)(((a->d[i]) >> j) & ((BN_ULONG)1)); +} + +int BN_mask_bits(BIGNUM *a, int n) +{ + int b, w; + bn_check_top(a); + + if (n < 0) + return 0; + + w = n / BN_BITS2; + b = n % BN_BITS2; + + if (w >= a->top) + return 0; + + if (b == 0) + a->top = w; + else { + a->top = w + 1; + a->d[w] &= ~(BN_MASK2 << b); + } + + bn_correct_top(a); + return 1; +} + +void BN_set_negative(BIGNUM *a, int b) +{ + if (b && !BN_is_zero(a)) + a->neg = 1; + else + a->neg = 0; +} + +int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n) +{ + int i; + BN_ULONG aa, bb; + aa = a[n - 1]; + bb = b[n - 1]; + + if (aa != bb) + return ((aa > bb) ? 1 : -1); + + for (i = n - 2; i >= 0; i--) { + aa = a[i]; + bb = b[i]; + + if (aa != bb) + return ((aa > bb) ? 1 : -1); + } + + return 0; +} + +/* + * Here follows a specialised variants of bn_cmp_words(). It has the + * capability of performing the operation on arrays of different sizes. The + * sizes of those arrays is expressed through cl, which is the common length + * ( basically, min(len(a),len(b)) ), and dl, which is the delta between the + * two lengths, calculated as len(a)-len(b). All lengths are the number of + * BN_ULONGs... + */ + +int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl) +{ + int n, i; + n = cl - 1; + + if (dl < 0) { + for (i = dl; i < 0; i++) { + if (b[n - i] != 0) + return -1; /* a < b */ + } + } + + if (dl > 0) { + for (i = dl; i > 0; i--) { + if (a[n + i] != 0) + return 1; /* a > b */ + } + } + + return bn_cmp_words(a, b, cl); +} + +/* + * Constant-time conditional swap of a and b. + * a and b are swapped if condition is not 0. The code assumes that at most one bit of condition is set. + * nwords is the number of words to swap. The code assumes that at least nwords are allocated in both a and b, + * and that no more than nwords are used by either a or b. + * a and b cannot be the same number + */ +void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords) +{ + BN_ULONG t; + int i; + bn_wcheck_size(a, nwords); + bn_wcheck_size(b, nwords); + ASSERT(a != b); + ASSERT((condition & (condition - 1)) == 0); + ASSERT(sizeof(BN_ULONG) >= sizeof(int)); + condition = ((condition - 1) >> (BN_BITS2 - 1)) - 1; + t = (a->top ^ b->top) & condition; + a->top ^= t; + b->top ^= t; +#define BN_CONSTTIME_SWAP(ind) \ + do { \ + t = (a->d[ind] ^ b->d[ind]) & condition; \ + a->d[ind] ^= t; \ + b->d[ind] ^= t; \ + } while (0) + + switch (nwords) { + default: + for (i = 10; i < nwords; i++) + BN_CONSTTIME_SWAP(i); + + /* Fallthrough */ + case 10: + BN_CONSTTIME_SWAP(9); /* Fallthrough */ + + case 9: + BN_CONSTTIME_SWAP(8); /* Fallthrough */ + + case 8: + BN_CONSTTIME_SWAP(7); /* Fallthrough */ + + case 7: + BN_CONSTTIME_SWAP(6); /* Fallthrough */ + + case 6: + BN_CONSTTIME_SWAP(5); /* Fallthrough */ + + case 5: + BN_CONSTTIME_SWAP(4); /* Fallthrough */ + + case 4: + BN_CONSTTIME_SWAP(3); /* Fallthrough */ + + case 3: + BN_CONSTTIME_SWAP(2); /* Fallthrough */ + + case 2: + BN_CONSTTIME_SWAP(1); /* Fallthrough */ + + case 1: + BN_CONSTTIME_SWAP(0); + } + +#undef BN_CONSTTIME_SWAP +} + +/* Bits of security, see SP800-57 */ + +int BN_security_bits(int L, int N) +{ + int secbits, bits; + + if (L >= 15360) + secbits = 256; + else if (L >= 7680) + secbits = 192; + else if (L >= 3072) + secbits = 128; + else if (L >= 2048) + secbits = 112; + else if (L >= 1024) + secbits = 80; + else + return 0; + + if (N == -1) + return secbits; + + bits = N / 2; + + if (bits < 80) + return 0; + + return bits >= secbits ? secbits : bits; +} + +void BN_zero_ex(BIGNUM *a) +{ + a->top = 0; + a->neg = 0; +} + +int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w) +{ + return ((a->top == 1) && (a->d[0] == w)) || ((w == 0) && (a->top == 0)); +} + +int BN_is_zero(const BIGNUM *a) +{ + return a->top == 0; +} + +int BN_is_one(const BIGNUM *a) +{ + return BN_abs_is_word(a, 1) && !a->neg; +} + +int BN_is_word(const BIGNUM *a, const BN_ULONG w) +{ + return BN_abs_is_word(a, w) && (!w || !a->neg); +} + +int BN_is_odd(const BIGNUM *a) +{ + return (a->top > 0) && (a->d[0] & 1); +} + +int BN_is_negative(const BIGNUM *a) +{ + return (a->neg != 0); +} + +int BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx) +{ + return BN_mod_mul_montgomery(r, a, &(mont->RR), mont, ctx); +} + +void BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags) +{ + dest->d = b->d; + dest->top = b->top; + dest->dmax = b->dmax; + dest->neg = b->neg; + dest->flags = ((dest->flags & BN_FLG_MALLOCED) + | (b->flags & ~BN_FLG_MALLOCED) + | BN_FLG_STATIC_DATA | flags); +} + +BN_GENCB *BN_GENCB_new(void) +{ + BN_GENCB *ret; + os_alloc_mem(NULL, (UCHAR **)&ret, sizeof(BN_GENCB)); + + if (ret == NULL) + return NULL; + + return ret; +} + +void BN_GENCB_free(BN_GENCB *cb) +{ + if (cb == NULL) + return; + + os_free_mem(NULL, cb); +} + +void BN_set_flags(BIGNUM *b, int n) +{ + b->flags |= n; +} + +int BN_get_flags(const BIGNUM *b, int n) +{ + return b->flags & n; +} + +/* Populate a BN_GENCB structure with an "old"-style callback */ +void BN_GENCB_set_old(BN_GENCB *gencb, void (*callback) (int, int, void *), + void *cb_arg) +{ + BN_GENCB *tmp_gencb = gencb; + tmp_gencb->ver = 1; + tmp_gencb->arg = cb_arg; + tmp_gencb->cb.cb_1 = callback; +} + +/* Populate a BN_GENCB structure with a "new"-style callback */ +void BN_GENCB_set(BN_GENCB *gencb, int (*callback) (int, int, BN_GENCB *), + void *cb_arg) +{ + BN_GENCB *tmp_gencb = gencb; + tmp_gencb->ver = 2; + tmp_gencb->arg = cb_arg; + tmp_gencb->cb.cb_2 = callback; +} + +void *BN_GENCB_get_arg(BN_GENCB *cb) +{ + return cb->arg; +} + +BIGNUM *bn_wexpand(BIGNUM *a, int words) +{ + return (words <= a->dmax) ? a : bn_expand2(a, words); +} + +void bn_correct_top(BIGNUM *a) +{ + BN_ULONG *ftl; + int tmp_top = a->top; + + if (tmp_top > 0) { + for (ftl = &(a->d[tmp_top]); tmp_top > 0; tmp_top--) { + ftl--; + + if (*ftl != 0) + break; + } + + a->top = tmp_top; + } + + if (a->top == 0) + a->neg = 0; + + bn_pollute(a); +} + +#define LBITS(a) ((a)&BN_MASK2l) +#define HBITS(a) (((a)>>BN_BITS4)&BN_MASK2l) +#define L2HBITS(a) (((a)<>(BN_BITS4-1); \ + m = (m&BN_MASK2l)<<(BN_BITS4+1); \ + l = (l+m)&BN_MASK2; \ + if (l < m) \ + h++; \ + (lo) = l; \ + (ho) = h; \ + } + +#define mul_add(r, a, bl, bh, c) { \ + BN_ULONG l, h; \ + \ + h = (a); \ + l = LBITS(h); \ + h = HBITS(h); \ + mul64(l, h, (bl), (bh)); \ + \ + /* non-multiply part */ \ + l = (l+(c))&BN_MASK2; \ + if (l < (c)) \ + h++; \ + (c) = (r); \ + l = (l+(c))&BN_MASK2; \ + if (l < (c)) \ + h++; \ + (c) = h&BN_MASK2; \ + (r) = l; \ + } + +#define mul(r, a, bl, bh, c) { \ + BN_ULONG l, h; \ + \ + h = (a); \ + l = LBITS(h); \ + h = HBITS(h); \ + mul64(l, h, (bl), (bh)); \ + \ + /* non-multiply part */ \ + l += (c); \ + if ((l&BN_MASK2) < (c)) \ + h++; \ + (c) = h&BN_MASK2; \ + (r) = l&BN_MASK2; \ + } + + + +static BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) +{ + BN_ULONG c = 0; + BN_ULONG bl, bh; + + if (num <= 0) + return ((BN_ULONG)0); + + bl = LBITS(w); + bh = HBITS(w); + + for (;;) { + mul_add(rp[0], ap[0], bl, bh, c); + + if (--num == 0) + break; + + mul_add(rp[1], ap[1], bl, bh, c); + + if (--num == 0) + break; + + mul_add(rp[2], ap[2], bl, bh, c); + + if (--num == 0) + break; + + mul_add(rp[3], ap[3], bl, bh, c); + + if (--num == 0) + break; + + ap += 4; + rp += 4; + } + + return c; +} + +static BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) +{ + BN_ULONG carry = 0; + BN_ULONG bl, bh; + + if (num <= 0) + return ((BN_ULONG)0); + + bl = LBITS(w); + bh = HBITS(w); + + for (;;) { + mul(rp[0], ap[0], bl, bh, carry); + + if (--num == 0) + break; + + mul(rp[1], ap[1], bl, bh, carry); + + if (--num == 0) + break; + + mul(rp[2], ap[2], bl, bh, carry); + + if (--num == 0) + break; + + mul(rp[3], ap[3], bl, bh, carry); + + if (--num == 0) + break; + + ap += 4; + rp += 4; + } + + return carry; +} + +static void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) +{ + if (n <= 0) + return; + + for (;;) { + sqr64(r[0], r[1], a[0]); + + if (--n == 0) + break; + + sqr64(r[2], r[3], a[1]); + + if (--n == 0) + break; + + sqr64(r[4], r[5], a[2]); + + if (--n == 0) + break; + + sqr64(r[6], r[7], a[3]); + + if (--n == 0) + break; + + a += 4; + r += 8; + } +} + +static BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n) +{ + BN_ULONG c, l, t; + + if (n <= 0) + return ((BN_ULONG)0); + + c = 0; + + for (;;) { + t = a[0]; + t = (t + c)&BN_MASK2; + c = (t < c); + l = (t + b[0])&BN_MASK2; + c += (l < t); + r[0] = l; + + if (--n <= 0) + break; + + t = a[1]; + t = (t + c)&BN_MASK2; + c = (t < c); + l = (t + b[1])&BN_MASK2; + c += (l < t); + r[1] = l; + + if (--n <= 0) + break; + + t = a[2]; + t = (t + c)&BN_MASK2; + c = (t < c); + l = (t + b[2])&BN_MASK2; + c += (l < t); + r[2] = l; + + if (--n <= 0) + break; + + t = a[3]; + t = (t + c)&BN_MASK2; + c = (t < c); + l = (t + b[3])&BN_MASK2; + c += (l < t); + r[3] = l; + + if (--n <= 0) + break; + + a += 4; + b += 4; + r += 4; + } + + return ((BN_ULONG)c); +} + +static BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n) +{ + BN_ULONG t1, t2; + int c = 0; + + if (n <= 0) + return ((BN_ULONG)0); + + for (;;) { + t1 = a[0]; + t2 = b[0]; + r[0] = (t1 - t2 - c)&BN_MASK2; + + if (t1 != t2) + c = (t1 < t2); + + if (--n <= 0) + break; + + t1 = a[1]; + t2 = b[1]; + r[1] = (t1 - t2 - c)&BN_MASK2; + + if (t1 != t2) + c = (t1 < t2); + + if (--n <= 0) + break; + + t1 = a[2]; + t2 = b[2]; + r[2] = (t1 - t2 - c)&BN_MASK2; + + if (t1 != t2) + c = (t1 < t2); + + if (--n <= 0) + break; + + t1 = a[3]; + t2 = b[3]; + r[3] = (t1 - t2 - c)&BN_MASK2; + + if (t1 != t2) + c = (t1 < t2); + + if (--n <= 0) + break; + + a += 4; + b += 4; + r += 4; + } + + return c; +} + +/* Divide h,l by d and return the result. */ +/* I need to test this some more :-( */ +BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) +{ + BN_ULONG dh, dl, q, ret = 0, th, tl, t; + int i, count = 2; + + if (d == 0) + return BN_MASK2; + + i = BN_num_bits_word(d); + /* ASSERT((i == BN_BITS2) || (h <= (BN_ULONG)1 << i)); check point */ + i = BN_BITS2 - i; + + if (h >= d) + h -= d; + + if (i) { + d <<= i; + h = (h << i) | (l >> (BN_BITS2 - i)); + l <<= i; + } + + dh = (d & BN_MASK2h) >> BN_BITS4; + dl = (d & BN_MASK2l); + + for (;;) { + if ((h >> BN_BITS4) == dh) + q = BN_MASK2l; + else + q = h / dh; + + th = q * dh; + tl = dl * q; + + for (;;) { + t = h - th; + + if ((t & BN_MASK2h) || + ((tl) <= ((t << BN_BITS4) | ((l & BN_MASK2h) >> BN_BITS4)))) + break; + + q--; + th -= dh; + tl -= dl; + } + + t = (tl >> BN_BITS4); + tl = (tl << BN_BITS4) & BN_MASK2h; + th += t; + + if (l < tl) + th++; + + l -= tl; + + if (h < th) { + h += d; + q--; + } + + h -= th; + + if (--count == 0) + break; + + ret = q << BN_BITS4; + h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2; + l = (l & BN_MASK2l) << BN_BITS4; + } + + ret |= q; + return ret; +} + +#define BN_MUL_COMBA +#define BN_SQR_COMBA + +#ifdef BN_MUL_COMBA + +#undef bn_mul_comba8 +#undef bn_mul_comba4 +#undef bn_sqr_comba8 +#undef bn_sqr_comba4 + +/* mul_add_c(a,b,c0,c1,c2) -- c+=a*b for three word number c=(c2,c1,c0) */ +/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */ +/* sqr_add_c(a,i,c0,c1,c2) -- c+=a[i]^2 for three word number c=(c2,c1,c0) */ +/* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number c=(c2,c1,c0) */ + +#define mul_add_c(a, b, c0, c1, c2) \ + do { \ + t1 = LBITS(a); t2 = HBITS(a); \ + bl = LBITS(b); bh = HBITS(b); \ + mul64(t1, t2, bl, bh); \ + c0 = (c0+t1) & BN_MASK2; \ + if ((c0) < t1) \ + t2++; \ + c1 = (c1+t2) & BN_MASK2;\ + if ((c1) < t2) \ + c2++; \ + } while (0) + +#define mul_add_c2(a, b, c0, c1, c2) \ + do { \ + t1 = LBITS(a); t2 = HBITS(a); \ + bl = LBITS(b); bh = HBITS(b); \ + mul64(t1, t2, bl, bh); \ + if (t2 & BN_TBIT) \ + c2++; \ + t2 = (t2+t2)&BN_MASK2; \ + if (t1 & BN_TBIT) \ + t2++; \ + t1 = (t1+t1)&BN_MASK2; \ + c0 = (c0+t1)&BN_MASK2; \ + if ((c0 < t1) && (((++t2)&BN_MASK2) == 0)) \ + c2++; \ + c1 = (c1+t2)&BN_MASK2; \ + if ((c1) < t2) \ + c2++; \ + } while (0) + +#define sqr_add_c(a, i, c0, c1, c2) \ + do { \ + sqr64(t1, t2, (a)[i]); \ + c0 = (c0+t1)&BN_MASK2; \ + if ((c0) < t1) \ + t2++; \ + c1 = (c1+t2)&BN_MASK2; \ + if ((c1) < t2) \ + c2++; \ + } while (0) + +#define sqr_add_c2(a, i, j, c0, c1, c2) \ + mul_add_c2((a)[i], (a)[j], c0, c1, c2) + +static void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) +{ + BN_ULONG bl, bh; + BN_ULONG t1, t2; + BN_ULONG c1, c2, c3; + c1 = 0; + c2 = 0; + c3 = 0; + mul_add_c(a[0], b[0], c1, c2, c3); + r[0] = c1; + c1 = 0; + mul_add_c(a[0], b[1], c2, c3, c1); + mul_add_c(a[1], b[0], c2, c3, c1); + r[1] = c2; + c2 = 0; + mul_add_c(a[2], b[0], c3, c1, c2); + mul_add_c(a[1], b[1], c3, c1, c2); + mul_add_c(a[0], b[2], c3, c1, c2); + r[2] = c3; + c3 = 0; + mul_add_c(a[0], b[3], c1, c2, c3); + mul_add_c(a[1], b[2], c1, c2, c3); + mul_add_c(a[2], b[1], c1, c2, c3); + mul_add_c(a[3], b[0], c1, c2, c3); + r[3] = c1; + c1 = 0; + mul_add_c(a[4], b[0], c2, c3, c1); + mul_add_c(a[3], b[1], c2, c3, c1); + mul_add_c(a[2], b[2], c2, c3, c1); + mul_add_c(a[1], b[3], c2, c3, c1); + mul_add_c(a[0], b[4], c2, c3, c1); + r[4] = c2; + c2 = 0; + mul_add_c(a[0], b[5], c3, c1, c2); + mul_add_c(a[1], b[4], c3, c1, c2); + mul_add_c(a[2], b[3], c3, c1, c2); + mul_add_c(a[3], b[2], c3, c1, c2); + mul_add_c(a[4], b[1], c3, c1, c2); + mul_add_c(a[5], b[0], c3, c1, c2); + r[5] = c3; + c3 = 0; + mul_add_c(a[6], b[0], c1, c2, c3); + mul_add_c(a[5], b[1], c1, c2, c3); + mul_add_c(a[4], b[2], c1, c2, c3); + mul_add_c(a[3], b[3], c1, c2, c3); + mul_add_c(a[2], b[4], c1, c2, c3); + mul_add_c(a[1], b[5], c1, c2, c3); + mul_add_c(a[0], b[6], c1, c2, c3); + r[6] = c1; + c1 = 0; + mul_add_c(a[0], b[7], c2, c3, c1); + mul_add_c(a[1], b[6], c2, c3, c1); + mul_add_c(a[2], b[5], c2, c3, c1); + mul_add_c(a[3], b[4], c2, c3, c1); + mul_add_c(a[4], b[3], c2, c3, c1); + mul_add_c(a[5], b[2], c2, c3, c1); + mul_add_c(a[6], b[1], c2, c3, c1); + mul_add_c(a[7], b[0], c2, c3, c1); + r[7] = c2; + c2 = 0; + mul_add_c(a[7], b[1], c3, c1, c2); + mul_add_c(a[6], b[2], c3, c1, c2); + mul_add_c(a[5], b[3], c3, c1, c2); + mul_add_c(a[4], b[4], c3, c1, c2); + mul_add_c(a[3], b[5], c3, c1, c2); + mul_add_c(a[2], b[6], c3, c1, c2); + mul_add_c(a[1], b[7], c3, c1, c2); + r[8] = c3; + c3 = 0; + mul_add_c(a[2], b[7], c1, c2, c3); + mul_add_c(a[3], b[6], c1, c2, c3); + mul_add_c(a[4], b[5], c1, c2, c3); + mul_add_c(a[5], b[4], c1, c2, c3); + mul_add_c(a[6], b[3], c1, c2, c3); + mul_add_c(a[7], b[2], c1, c2, c3); + r[9] = c1; + c1 = 0; + mul_add_c(a[7], b[3], c2, c3, c1); + mul_add_c(a[6], b[4], c2, c3, c1); + mul_add_c(a[5], b[5], c2, c3, c1); + mul_add_c(a[4], b[6], c2, c3, c1); + mul_add_c(a[3], b[7], c2, c3, c1); + r[10] = c2; + c2 = 0; + mul_add_c(a[4], b[7], c3, c1, c2); + mul_add_c(a[5], b[6], c3, c1, c2); + mul_add_c(a[6], b[5], c3, c1, c2); + mul_add_c(a[7], b[4], c3, c1, c2); + r[11] = c3; + c3 = 0; + mul_add_c(a[7], b[5], c1, c2, c3); + mul_add_c(a[6], b[6], c1, c2, c3); + mul_add_c(a[5], b[7], c1, c2, c3); + r[12] = c1; + c1 = 0; + mul_add_c(a[6], b[7], c2, c3, c1); + mul_add_c(a[7], b[6], c2, c3, c1); + r[13] = c2; + c2 = 0; + mul_add_c(a[7], b[7], c3, c1, c2); + r[14] = c3; + r[15] = c1; +} +#ifdef BN_RECURSION +static void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) +{ + BN_ULONG bl, bh; + BN_ULONG t1, t2; + BN_ULONG c1, c2, c3; + c1 = 0; + c2 = 0; + c3 = 0; + mul_add_c(a[0], b[0], c1, c2, c3); + r[0] = c1; + c1 = 0; + mul_add_c(a[0], b[1], c2, c3, c1); + mul_add_c(a[1], b[0], c2, c3, c1); + r[1] = c2; + c2 = 0; + mul_add_c(a[2], b[0], c3, c1, c2); + mul_add_c(a[1], b[1], c3, c1, c2); + mul_add_c(a[0], b[2], c3, c1, c2); + r[2] = c3; + c3 = 0; + mul_add_c(a[0], b[3], c1, c2, c3); + mul_add_c(a[1], b[2], c1, c2, c3); + mul_add_c(a[2], b[1], c1, c2, c3); + mul_add_c(a[3], b[0], c1, c2, c3); + r[3] = c1; + c1 = 0; + mul_add_c(a[3], b[1], c2, c3, c1); + mul_add_c(a[2], b[2], c2, c3, c1); + mul_add_c(a[1], b[3], c2, c3, c1); + r[4] = c2; + c2 = 0; + mul_add_c(a[2], b[3], c3, c1, c2); + mul_add_c(a[3], b[2], c3, c1, c2); + r[5] = c3; + c3 = 0; + mul_add_c(a[3], b[3], c1, c2, c3); + r[6] = c1; + r[7] = c2; +} +#endif /*BN_RECURSION */ +static void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) +{ + BN_ULONG bl, bh; + BN_ULONG t1, t2; + BN_ULONG c1, c2, c3; + c1 = 0; + c2 = 0; + c3 = 0; + sqr_add_c(a, 0, c1, c2, c3); + r[0] = c1; + c1 = 0; + sqr_add_c2(a, 1, 0, c2, c3, c1); + r[1] = c2; + c2 = 0; + sqr_add_c(a, 1, c3, c1, c2); + sqr_add_c2(a, 2, 0, c3, c1, c2); + r[2] = c3; + c3 = 0; + sqr_add_c2(a, 3, 0, c1, c2, c3); + sqr_add_c2(a, 2, 1, c1, c2, c3); + r[3] = c1; + c1 = 0; + sqr_add_c(a, 2, c2, c3, c1); + sqr_add_c2(a, 3, 1, c2, c3, c1); + sqr_add_c2(a, 4, 0, c2, c3, c1); + r[4] = c2; + c2 = 0; + sqr_add_c2(a, 5, 0, c3, c1, c2); + sqr_add_c2(a, 4, 1, c3, c1, c2); + sqr_add_c2(a, 3, 2, c3, c1, c2); + r[5] = c3; + c3 = 0; + sqr_add_c(a, 3, c1, c2, c3); + sqr_add_c2(a, 4, 2, c1, c2, c3); + sqr_add_c2(a, 5, 1, c1, c2, c3); + sqr_add_c2(a, 6, 0, c1, c2, c3); + r[6] = c1; + c1 = 0; + sqr_add_c2(a, 7, 0, c2, c3, c1); + sqr_add_c2(a, 6, 1, c2, c3, c1); + sqr_add_c2(a, 5, 2, c2, c3, c1); + sqr_add_c2(a, 4, 3, c2, c3, c1); + r[7] = c2; + c2 = 0; + sqr_add_c(a, 4, c3, c1, c2); + sqr_add_c2(a, 5, 3, c3, c1, c2); + sqr_add_c2(a, 6, 2, c3, c1, c2); + sqr_add_c2(a, 7, 1, c3, c1, c2); + r[8] = c3; + c3 = 0; + sqr_add_c2(a, 7, 2, c1, c2, c3); + sqr_add_c2(a, 6, 3, c1, c2, c3); + sqr_add_c2(a, 5, 4, c1, c2, c3); + r[9] = c1; + c1 = 0; + sqr_add_c(a, 5, c2, c3, c1); + sqr_add_c2(a, 6, 4, c2, c3, c1); + sqr_add_c2(a, 7, 3, c2, c3, c1); + r[10] = c2; + c2 = 0; + sqr_add_c2(a, 7, 4, c3, c1, c2); + sqr_add_c2(a, 6, 5, c3, c1, c2); + r[11] = c3; + c3 = 0; + sqr_add_c(a, 6, c1, c2, c3); + sqr_add_c2(a, 7, 5, c1, c2, c3); + r[12] = c1; + c1 = 0; + sqr_add_c2(a, 7, 6, c2, c3, c1); + r[13] = c2; + c2 = 0; + sqr_add_c(a, 7, c3, c1, c2); + r[14] = c3; + r[15] = c1; +} + +static void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) +{ + BN_ULONG bl, bh; + BN_ULONG t1, t2; + BN_ULONG c1, c2, c3; + c1 = 0; + c2 = 0; + c3 = 0; + sqr_add_c(a, 0, c1, c2, c3); + r[0] = c1; + c1 = 0; + sqr_add_c2(a, 1, 0, c2, c3, c1); + r[1] = c2; + c2 = 0; + sqr_add_c(a, 1, c3, c1, c2); + sqr_add_c2(a, 2, 0, c3, c1, c2); + r[2] = c3; + c3 = 0; + sqr_add_c2(a, 3, 0, c1, c2, c3); + sqr_add_c2(a, 2, 1, c1, c2, c3); + r[3] = c1; + c1 = 0; + sqr_add_c(a, 2, c2, c3, c1); + sqr_add_c2(a, 3, 1, c2, c3, c1); + r[4] = c2; + c2 = 0; + sqr_add_c2(a, 3, 2, c3, c1, c2); + r[5] = c3; + c3 = 0; + sqr_add_c(a, 3, c1, c2, c3); + r[6] = c1; + r[7] = c2; +} +#endif /* !BN_MUL_COMBA */ + + +#define MONT_WORD /* use the faster word-based algorithm */ + +#ifdef MONT_WORD +static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont); +#endif + + +int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + BN_MONT_CTX *mont, BN_CTX *ctx) +{ + BIGNUM *tmp; + int ret = 0; +#if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD) + int num = mont->N.top; + + if (num > 1 && a->top == num && b->top == num) { + if (bn_wexpand(r, num) == NULL) + return 0; + + if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) { + r->neg = a->neg ^ b->neg; + r->top = num; + bn_correct_top(r); + return 1; + } + } + +#endif + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + + if (tmp == NULL) + goto err; + + bn_check_top(tmp); + + if (a == b) { + if (!BN_sqr(tmp, a, ctx)) + goto err; + } else { + if (!BN_mul(tmp, a, b, ctx)) + goto err; + } + + /* reduce from aRR to aR */ +#ifdef MONT_WORD + + if (!BN_from_montgomery_word(r, tmp, mont)) + goto err; + +#else + + if (!BN_from_montgomery(r, tmp, mont, ctx)) + goto err; + +#endif + bn_check_top(r); + ret = 1; +err: + BN_CTX_end(ctx); + return ret; +} + +#ifdef MONT_WORD +static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) +{ + BIGNUM *n; + BN_ULONG *ap, *np, *rp, n0, v, carry; + int nl, max, i; + n = &(mont->N); + nl = n->top; + + if (nl == 0) { + ret->top = 0; + return 1; + } + + max = (2 * nl); /* carry is stored separately */ + + if (bn_wexpand(r, max) == NULL) + return 0; + + r->neg ^= n->neg; + np = n->d; + rp = r->d; + /* clear the top words of T */ + i = max - r->top; + + if (i) + memset(&rp[r->top], 0, sizeof(*rp) * i); + + r->top = max; + n0 = mont->n0[0]; + + for (carry = 0, i = 0; i < nl; i++, rp++) { + v = bn_mul_add_words(rp, np, nl, (rp[0] * n0) & BN_MASK2); + v = (v + carry + rp[nl]) & BN_MASK2; + carry |= (v != rp[nl]); + carry &= (v <= rp[nl]); + rp[nl] = v; + } + + if (bn_wexpand(ret, nl) == NULL) + return 0; + + ret->top = nl; + ret->neg = r->neg; + rp = ret->d; + ap = &(r->d[nl]); +# define BRANCH_FREE 0 +# if BRANCH_FREE + { + BN_ULONG *nrp; + size_t m; + v = bn_sub_words(rp, ap, np, nl) - carry; + /* + * if subtraction result is real, then trick unconditional memcpy + * below to perform in-place "refresh" instead of actual copy. + */ + m = (0 - (size_t)v); + nrp = + (BN_ULONG *)(((PTR_SIZE_INT) rp & ~m) | ((PTR_SIZE_INT) ap & m)); + + for (i = 0, nl -= 4; i < nl; i += 4) { + BN_ULONG t1, t2, t3, t4; + t1 = nrp[i + 0]; + t2 = nrp[i + 1]; + t3 = nrp[i + 2]; + ap[i + 0] = 0; + t4 = nrp[i + 3]; + ap[i + 1] = 0; + rp[i + 0] = t1; + ap[i + 2] = 0; + rp[i + 1] = t2; + ap[i + 3] = 0; + rp[i + 2] = t3; + rp[i + 3] = t4; + } + + for (nl += 4; i < nl; i++) + rp[i] = nrp[i], ap[i] = 0; + } +# else + + if (bn_sub_words(rp, ap, np, nl) - carry) + memcpy(rp, ap, nl * sizeof(BN_ULONG)); + +# endif + bn_correct_top(r); + bn_correct_top(ret); + bn_check_top(ret); + return 1; +} +#endif /* MONT_WORD */ + +int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx) +{ + int retn = 0; +#ifdef MONT_WORD + BIGNUM *t; + BN_CTX_start(ctx); + + t = BN_CTX_get(ctx); + if (t && BN_copy(t, a)) + retn = BN_from_montgomery_word(ret, t, mont); + + BN_CTX_end(ctx); +#else /* !MONT_WORD */ + BIGNUM *t1, *t2; + BN_CTX_start(ctx); + t1 = BN_CTX_get(ctx); + t2 = BN_CTX_get(ctx); + + if (t1 == NULL || t2 == NULL) + goto err; + + if (!BN_copy(t1, a)) + goto err; + + BN_mask_bits(t1, mont->ri); + + if (!BN_mul(t2, t1, &mont->Ni, ctx)) + goto err; + + BN_mask_bits(t2, mont->ri); + + if (!BN_mul(t1, t2, &mont->N, ctx)) + goto err; + + if (!BN_add(t2, a, t1)) + goto err; + + if (!BN_rshift(ret, t2, mont->ri)) + goto err; + + if (BN_ucmp(ret, &(mont->N)) >= 0) { + if (!BN_usub(ret, ret, &(mont->N))) + goto err; + } + + retn = 1; + bn_check_top(ret); +err: + BN_CTX_end(ctx); +#endif /* MONT_WORD */ + return retn; +} + +BN_MONT_CTX *BN_MONT_CTX_new(void) +{ + BN_MONT_CTX *ret; + os_alloc_mem(NULL, (UCHAR **)&ret, sizeof(BN_MONT_CTX)); + + if (ret == NULL) + return NULL; + + BN_MONT_CTX_init(ret); + ret->flags = BN_FLG_MALLOCED; + return ret; +} + +void BN_MONT_CTX_init(BN_MONT_CTX *ctx) +{ + ctx->ri = 0; + bn_init(&(ctx->RR)); + bn_init(&(ctx->N)); + bn_init(&(ctx->Ni)); + ctx->n0[0] = ctx->n0[1] = 0; + ctx->flags = 0; +} + +void BN_MONT_CTX_free(BN_MONT_CTX *mont) +{ + if (mont == NULL) + return; + + BN_clear_free(&(mont->RR)); + BN_clear_free(&(mont->N)); + BN_clear_free(&(mont->Ni)); + + if (mont->flags & BN_FLG_MALLOCED) + os_free_mem(NULL, mont); +} + +int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) +{ + int ret = 0; + BIGNUM *Ri, *R; + + if (BN_is_zero(mod)) + return 0; + + BN_CTX_start(ctx); + + Ri = BN_CTX_get(ctx); + if (Ri == NULL) + goto err; + + R = &(mont->RR); /* grab RR as a temp */ + + if (!BN_copy(&(mont->N), mod)) + goto err; /* Set N */ + + mont->N.neg = 0; +#ifdef MONT_WORD + { + BIGNUM tmod; + BN_ULONG buf[2]; + bn_init(&tmod); + tmod.d = buf; + tmod.dmax = 2; + tmod.neg = 0; + + if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0) + BN_set_flags(&tmod, BN_FLG_CONSTTIME); + + mont->ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2; +# if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2 <= 32) + /* + * Only certain BN_BITS2<=32 platforms actually make use of n0[1], + * and we could use the #else case (with a shorter R value) for the + * others. However, currently only the assembler files do know which + * is which. + */ + BN_zero(R); + + if (!(BN_set_bit(R, 2 * BN_BITS2))) + goto err; + + tmod.top = 0; + + buf[0] = mod->d[0]; + if (buf[0]) + tmod.top = 1; + + buf[1] = mod->top > 1 ? mod->d[1] : 0; + if (buf[1]) + tmod.top = 2; + + if ((BN_mod_inverse(Ri, R, &tmod, ctx)) == NULL) + goto err; + + if (!BN_lshift(Ri, Ri, 2 * BN_BITS2)) + goto err; /* R*Ri */ + + if (!BN_is_zero(Ri)) { + if (!BN_sub_word(Ri, 1)) + goto err; + } else { /* if N mod word size == 1 */ + if (bn_expand(Ri, (int)sizeof(BN_ULONG) * 2) == NULL) + goto err; + + /* Ri-- (mod double word size) */ + Ri->neg = 0; + Ri->d[0] = BN_MASK2; + Ri->d[1] = BN_MASK2; + Ri->top = 2; + } + + if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) + goto err; + + /* + * Ni = (R*Ri-1)/N, keep only couple of least significant words: + */ + mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0; + mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0; +# else + BN_zero(R); + + if (!(BN_set_bit(R, BN_BITS2))) + goto err; /* R */ + + buf[0] = mod->d[0]; /* tmod = N mod word size */ + buf[1] = 0; + tmod.top = buf[0] != 0 ? 1 : 0; + + /* Ri = R^-1 mod N */ + if ((BN_mod_inverse(Ri, R, &tmod, ctx)) == NULL) + goto err; + + if (!BN_lshift(Ri, Ri, BN_BITS2)) + goto err; /* R*Ri */ + + if (!BN_is_zero(Ri)) { + if (!BN_sub_word(Ri, 1)) + goto err; + } else { /* if N mod word size == 1 */ + if (!BN_set_word(Ri, BN_MASK2)) + goto err; /* Ri-- (mod word size) */ + } + + if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) + goto err; + + /* + * Ni = (R*Ri-1)/N, keep only least significant word: + */ + mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0; + mont->n0[1] = 0; +# endif + } +#else /* !MONT_WORD */ + { /* bignum version */ + mont->ri = BN_num_bits(&mont->N); + BN_zero(R); + + if (!BN_set_bit(R, mont->ri)) + goto err; /* R = 2^ri */ + + /* Ri = R^-1 mod N */ + if ((BN_mod_inverse(Ri, R, &mont->N, ctx)) == NULL) + goto err; + + if (!BN_lshift(Ri, Ri, mont->ri)) + goto err; /* R*Ri */ + + if (!BN_sub_word(Ri, 1)) + goto err; + + /* + * Ni = (R*Ri-1) / N + */ + if (!BN_div(&(mont->Ni), NULL, Ri, &mont->N, ctx)) + goto err; + } +#endif + /* setup RR for conversions */ + BN_zero(&(mont->RR)); + + if (!BN_set_bit(&(mont->RR), mont->ri * 2)) + goto err; + + if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx)) + goto err; + + ret = 1; +err: + BN_CTX_end(ctx); + return ret; +} + +BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from) +{ + if (to == from) + return to; + + if (!BN_copy(&(to->RR), &(from->RR))) + return NULL; + + if (!BN_copy(&(to->N), &(from->N))) + return NULL; + + if (!BN_copy(&(to->Ni), &(from->Ni))) + return NULL; + + to->ri = from->ri; + to->n0[0] = from->n0[0]; + to->n0[1] = from->n0[1]; + return to; +} + +void BN_STACK_init(BN_STACK *st) +{ + st->indexes = NULL; + st->depth = st->size = 0; +} + +void BN_STACK_finish(BN_STACK *st) +{ + if (st->indexes) + os_free_mem(NULL, st->indexes); + + st->indexes = NULL; +} + + +int BN_STACK_push(BN_STACK *st, unsigned int idx) +{ + if (st->depth == st->size) { + /* Need to expand */ + unsigned int newsize = + st->size ? (st->size * 3 / 2) : BN_CTX_START_FRAMES; + unsigned int *newitems; + os_alloc_mem(NULL, (UCHAR **)&newitems, sizeof(*newitems) * newsize); + + if (newitems == NULL) + return 0; + + if (st->depth) + memcpy(newitems, st->indexes, sizeof(*newitems) * st->depth); + + if (st->indexes) + os_free_mem(NULL, st->indexes); + + st->indexes = newitems; + st->size = newsize; + } + + st->indexes[(st->depth)++] = idx; + return 1; +} + +unsigned int BN_STACK_pop(BN_STACK *st) +{ + return st->indexes[--(st->depth)]; +} + +void BN_POOL_init(BN_POOL *p) +{ + p->head = NULL; + p->curr = NULL; + p->tail = NULL; + p->used = 0; + p->size = 0; +} + +void BN_POOL_finish(BN_POOL *p) +{ + unsigned int loop; + BIGNUM *bn; + + while (p->head) { + for (loop = 0, bn = p->head->vals; loop++ < BN_CTX_POOL_SIZE; bn++) + if (bn->d) + BN_clear_free(bn); + + p->curr = p->head->next; + + if (p->head) + os_free_mem(NULL, p->head); + + p->head = p->curr; + } +} + + +BIGNUM *BN_POOL_get(BN_POOL *p, int flag) +{ + BIGNUM *bn; + unsigned int loop; + + /* Full; allocate a new pool item and link it in. */ + if (p->used == p->size) { + BN_POOL_ITEM *item; + os_alloc_mem(NULL, (UCHAR **)&item, sizeof(BN_POOL_ITEM)); + + if (item == NULL) + return NULL; + + for (loop = 0, bn = item->vals; loop++ < BN_CTX_POOL_SIZE; bn++) { + bn_init(bn); + + if ((flag & BN_FLG_SECURE) != 0) + BN_set_flags(bn, BN_FLG_SECURE); + } + + item->prev = p->tail; + item->next = NULL; + + if (p->head == NULL) + p->head = p->curr = p->tail = item; + else { + p->tail->next = item; + p->tail = item; + p->curr = item; + } + + p->size += BN_CTX_POOL_SIZE; + p->used++; + /* Return the first bignum from the new pool */ + return item->vals; + } + + if (!p->used) + p->curr = p->head; + else if ((p->used % BN_CTX_POOL_SIZE) == 0) + p->curr = p->curr->next; + + return p->curr->vals + ((p->used++) % BN_CTX_POOL_SIZE); +} + +void BN_POOL_release(BN_POOL *p, unsigned int num) +{ + unsigned int offset = (p->used - 1) % BN_CTX_POOL_SIZE; + p->used -= num; + + while (num--) { + bn_check_top(p->curr->vals + offset); + + if (offset == 0) { + offset = BN_CTX_POOL_SIZE - 1; + p->curr = p->curr->prev; + } else + offset--; + } +} + + +BN_CTX *BN_CTX_new(void) +{ + BN_CTX *ret; + os_alloc_mem(NULL, (UCHAR **)&ret, sizeof(BN_CTX)); + memset(ret, 0, sizeof(BN_CTX)); + + if (ret == NULL) + return NULL; + + /* Initialise the structure */ + BN_POOL_init(&ret->pool); + BN_STACK_init(&ret->stack); + return ret; +} + +BN_CTX *BN_CTX_secure_new(void) +{ + BN_CTX *ret = BN_CTX_new(); + + if (ret != NULL) + ret->flags = BN_FLG_SECURE; + + return ret; +} + +void BN_CTX_free(BN_CTX *ctx) +{ + if (ctx == NULL) + return; + + BN_STACK_finish(&ctx->stack); + BN_POOL_finish(&ctx->pool); + + if (ctx) + os_free_mem(NULL, ctx); +} + +void BN_CTX_start(BN_CTX *ctx) +{ + /* If we're already overflowing ... */ + if (ctx->err_stack || ctx->too_many) + ctx->err_stack++; + /* (Try to) get a new frame pointer */ + else if (!BN_STACK_push(&ctx->stack, ctx->used)) { + BNerr(BN_F_BN_CTX_START, BN_R_TOO_MANY_TEMPORARY_VARIABLES); + ctx->err_stack++; + } +} + +void BN_CTX_end(BN_CTX *ctx) +{ + if (ctx->err_stack) + ctx->err_stack--; + else { + unsigned int fp = BN_STACK_pop(&ctx->stack); + + /* Does this stack frame have anything to release? */ + if (fp < ctx->used) + BN_POOL_release(&ctx->pool, ctx->used - fp); + + ctx->used = fp; + /* Unjam "too_many" in case "get" had failed */ + ctx->too_many = 0; + } +} + +BIGNUM *BN_CTX_get(BN_CTX *ctx) +{ + BIGNUM *ret; + + if (ctx->err_stack || ctx->too_many) + return NULL; + + ret = BN_POOL_get(&ctx->pool, ctx->flags); + if (ret == NULL) { + /* + * Setting too_many prevents repeated "get" attempts from cluttering + * the error stack. + */ + ctx->too_many = 1; + BNerr(BN_F_BN_CTX_GET, BN_R_TOO_MANY_TEMPORARY_VARIABLES); + return NULL; + } + + /* OK, make sure the returned bignum is "zero" */ + BN_zero(ret); + ctx->used++; + return ret; +} + +void BN_RECP_CTX_init(BN_RECP_CTX *recp) +{ + memset(recp, 0, sizeof(*recp)); + bn_init(&(recp->N)); + bn_init(&(recp->Nr)); +} + +BN_RECP_CTX *BN_RECP_CTX_new(void) +{ + BN_RECP_CTX *ret; + os_alloc_mem(NULL, (UCHAR **)&ret, sizeof(BN_RECP_CTX)); + + if (ret == NULL) + return NULL; + + bn_init(&(ret->N)); + bn_init(&(ret->Nr)); + ret->flags = BN_FLG_MALLOCED; + return ret; +} + +void BN_RECP_CTX_free(BN_RECP_CTX *recp) +{ + if (recp == NULL) + return; + + BN_free(&(recp->N)); + BN_free(&(recp->Nr)); + + if (recp->flags & BN_FLG_MALLOCED) + os_free_mem(NULL, recp); +} + +int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *d, BN_CTX *ctx) +{ + if (!BN_copy(&(recp->N), d)) + return 0; + + BN_zero(&(recp->Nr)); + recp->num_bits = BN_num_bits(d); + recp->shift = 0; + return 1; +} + +int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y, + BN_RECP_CTX *recp, BN_CTX *ctx) +{ + int ret = 0; + BIGNUM *a; + const BIGNUM *ca; + BN_CTX_start(ctx); + + a = BN_CTX_get(ctx); + if (a == NULL) + goto err; + + if (y != NULL) { + if (x == y) { + if (!BN_sqr(a, x, ctx)) + goto err; + } else { + if (!BN_mul(a, x, y, ctx)) + goto err; + } + + ca = a; + } else + ca = x; /* Just do the mod */ + + ret = BN_div_recp(NULL, r, ca, recp, ctx); +err: + BN_CTX_end(ctx); + bn_check_top(r); + return ret; +} + +int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, + BN_RECP_CTX *recp, BN_CTX *ctx) +{ + int i, j, ret = 0; + BIGNUM *a, *b, *d, *r; + BN_CTX_start(ctx); + a = BN_CTX_get(ctx); + b = BN_CTX_get(ctx); + + if (dv != NULL) + d = dv; + else + d = BN_CTX_get(ctx); + + if (rem != NULL) + r = rem; + else + r = BN_CTX_get(ctx); + + if (a == NULL || b == NULL || d == NULL || r == NULL) + goto err; + + if (BN_ucmp(m, &(recp->N)) < 0) { + BN_zero(d); + + if (!BN_copy(r, m)) { + BN_CTX_end(ctx); + return 0; + } + + BN_CTX_end(ctx); + return 1; + } + + /* + * We want the remainder Given input of ABCDEF / ab we need multiply + * ABCDEF by 3 digests of the reciprocal of ab + */ + /* i := max(BN_num_bits(m), 2*BN_num_bits(N)) */ + i = BN_num_bits(m); + j = recp->num_bits << 1; + + if (j > i) + i = j; + + /* Nr := round(2^i / N) */ + if (i != recp->shift) + recp->shift = BN_reciprocal(&(recp->Nr), &(recp->N), i, ctx); + + /* BN_reciprocal could have returned -1 for an error */ + if (recp->shift == -1) + goto err; + + /*- + * d := |round(round(m / 2^BN_num_bits(N)) * recp->Nr / 2^(i - BN_num_bits(N)))| + * = |round(round(m / 2^BN_num_bits(N)) * round(2^i / N) / 2^(i - BN_num_bits(N)))| + * <= |(m / 2^BN_num_bits(N)) * (2^i / N) * (2^BN_num_bits(N) / 2^i)| + * = |m/N| + */ + if (!BN_rshift(a, m, recp->num_bits)) + goto err; + + if (!BN_mul(b, a, &(recp->Nr), ctx)) + goto err; + + if (!BN_rshift(d, b, i - recp->num_bits)) + goto err; + + d->neg = 0; + + if (!BN_mul(b, &(recp->N), d, ctx)) + goto err; + + if (!BN_usub(r, m, b)) + goto err; + + r->neg = 0; + j = 0; + + while (BN_ucmp(r, &(recp->N)) >= 0) { + if (j++ > 2) { + BNerr(BN_F_BN_DIV_RECP, BN_R_BAD_RECIPROCAL); + goto err; + } + + if (!BN_usub(r, r, &(recp->N))) + goto err; + + if (!BN_add_word(d, 1)) + goto err; + } + + r->neg = BN_is_zero(r) ? 0 : m->neg; + d->neg = m->neg ^ recp->N.neg; + ret = 1; +err: + BN_CTX_end(ctx); + bn_check_top(dv); + bn_check_top(rem); + return ret; +} + +/* + * len is the expected size of the result We actually calculate with an extra + * word of precision, so we can do faster division if the remainder is not + * required. + */ +/* r := 2^len / m */ +int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx) +{ + int ret = -1; + BIGNUM *t; + BN_CTX_start(ctx); + + t = BN_CTX_get(ctx); + if (t == NULL) + goto err; + + if (!BN_set_bit(t, len)) + goto err; + + if (!BN_div(r, NULL, t, m, ctx)) + goto err; + + ret = len; +err: + bn_check_top(r); + BN_CTX_end(ctx); + return ret; +} + +int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) +{ + int max, al; + int ret = 0; + BIGNUM *tmp, *rr; + bn_check_top(a); + al = a->top; + + if (al <= 0) { + r->top = 0; + r->neg = 0; + return 1; + } + + BN_CTX_start(ctx); + rr = (a != r) ? r : BN_CTX_get(ctx); + tmp = BN_CTX_get(ctx); + + if (!rr || !tmp) + goto err; + + max = 2 * al; /* Non-zero (from above) */ + + if (bn_wexpand(rr, max) == NULL) + goto err; + + if (al == 4) { +#ifndef BN_SQR_COMBA + BN_ULONG t[8]; + bn_sqr_normal(rr->d, a->d, 4, t); +#else + bn_sqr_comba4(rr->d, a->d); +#endif + } else if (al == 8) { +#ifndef BN_SQR_COMBA + BN_ULONG t[16]; + bn_sqr_normal(rr->d, a->d, 8, t); +#else + bn_sqr_comba8(rr->d, a->d); +#endif + } else { +#if defined(BN_RECURSION) + + if (al < BN_SQR_RECURSIVE_SIZE_NORMAL) { + BN_ULONG t[BN_SQR_RECURSIVE_SIZE_NORMAL * 2]; + bn_sqr_normal(rr->d, a->d, al, t); + } else { + int j, k; + j = BN_num_bits_word((BN_ULONG)al); + j = 1 << (j - 1); + k = j + j; + + if (al == j) { + if (bn_wexpand(tmp, k * 2) == NULL) + goto err; + + bn_sqr_recursive(rr->d, a->d, al, tmp->d); + } else { + if (bn_wexpand(tmp, max) == NULL) + goto err; + + bn_sqr_normal(rr->d, a->d, al, tmp->d); + } + } + +#else + + if (bn_wexpand(tmp, max) == NULL) + goto err; + + bn_sqr_normal(rr->d, a->d, al, tmp->d); +#endif + } + + rr->neg = 0; + + /* + * If the most-significant half of the top word of 'a' is zero, then the + * square of 'a' will max-1 words. + */ + if (a->d[al - 1] == (a->d[al - 1] & BN_MASK2l)) + rr->top = max - 1; + else + rr->top = max; + + if (r != rr && BN_copy(r, rr) == NULL) + goto err; + + ret = 1; +err: + bn_check_top(rr); + bn_check_top(tmp); + BN_CTX_end(ctx); + return ret; +} + +/* tmp must have 2*n words */ +void bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, int n, BN_ULONG *tmp) +{ + int i, j, max; + const BN_ULONG *ap; + BN_ULONG *rp; + max = n * 2; + ap = a; + rp = r; + rp[0] = rp[max - 1] = 0; + rp++; + j = n; + + if (--j > 0) { + ap++; + rp[j] = bn_mul_words(rp, ap, j, ap[-1]); + rp += 2; + } + + for (i = n - 2; i > 0; i--) { + j--; + ap++; + rp[j] = bn_mul_add_words(rp, ap, j, ap[-1]); + rp += 2; + } + + bn_add_words(r, r, r, max); + /* There will not be a carry */ + bn_sqr_words(tmp, a, n); + bn_add_words(r, r, tmp, max); +} + +#ifdef BN_RECURSION +/*- + * r is 2*n words in size, + * a and b are both n words in size. (There's not actually a 'b' here ...) + * n must be a power of 2. + * We multiply and return the result. + * t must be 2*n words in size + * We calculate + * a[0]*b[0] + * a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0]) + * a[1]*b[1] + */ +void bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, int n2, BN_ULONG *t) +{ + int n = n2 / 2; + int zero, c1; + BN_ULONG ln, lo, *p; + + if (n2 == 4) { +# ifndef BN_SQR_COMBA + bn_sqr_normal(r, a, 4, t); +# else + bn_sqr_comba4(r, a); +# endif + return; + } else if (n2 == 8) { +# ifndef BN_SQR_COMBA + bn_sqr_normal(r, a, 8, t); +# else + bn_sqr_comba8(r, a); +# endif + return; + } + + if (n2 < BN_SQR_RECURSIVE_SIZE_NORMAL) { + bn_sqr_normal(r, a, n2, t); + return; + } + + /* r=(a[0]-a[1])*(a[1]-a[0]) */ + c1 = bn_cmp_words(a, &(a[n]), n); + zero = 0; + + if (c1 > 0) + bn_sub_words(t, a, &(a[n]), n); + else if (c1 < 0) + bn_sub_words(t, &(a[n]), a, n); + else + zero = 1; + + /* The result will always be negative unless it is zero */ + p = &(t[n2 * 2]); + + if (!zero) + bn_sqr_recursive(&(t[n2]), t, n, p); + else + memset(&t[n2], 0, sizeof(*t) * n2); + + bn_sqr_recursive(r, a, n, p); + bn_sqr_recursive(&(r[n2]), &(a[n]), n, p); + /*- + * t[32] holds (a[0]-a[1])*(a[1]-a[0]), it is negative or zero + * r[10] holds (a[0]*b[0]) + * r[32] holds (b[1]*b[1]) + */ + c1 = (int)(bn_add_words(t, r, &(r[n2]), n2)); + /* t[32] is negative */ + c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2)); + /*- + * t[32] holds (a[0]-a[1])*(a[1]-a[0])+(a[0]*a[0])+(a[1]*a[1]) + * r[10] holds (a[0]*a[0]) + * r[32] holds (a[1]*a[1]) + * c1 holds the carry bits + */ + c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2)); + + if (c1) { + p = &(r[n + n2]); + lo = *p; + ln = (lo + c1) & BN_MASK2; + *p = ln; + + /* + * The overflow will stop before we over write words we should not + * overwrite + */ + if (ln < (BN_ULONG)c1) { + do { + p++; + lo = *p; + ln = (lo + 1) & BN_MASK2; + *p = ln; + } while (ln == 0); + } + } +} +#endif + +/* + * BN_mod_inverse_no_branch is a special version of BN_mod_inverse. It does + * not contain branches that may leak sensitive information. + */ +static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in, + const BIGNUM *a, const BIGNUM *n, + BN_CTX *ctx) +{ + BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL; + BIGNUM *ret = NULL; + int sign; + bn_check_top(a); + bn_check_top(n); + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + B = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + D = BN_CTX_get(ctx); + M = BN_CTX_get(ctx); + Y = BN_CTX_get(ctx); + T = BN_CTX_get(ctx); + + if (T == NULL) + goto err; + + if (in == NULL) + R = BN_new(); + else + R = in; + + if (R == NULL) + goto err; + + BN_one(X); + BN_zero(Y); + + if (BN_copy(B, a) == NULL) + goto err; + + if (BN_copy(A, n) == NULL) + goto err; + + A->neg = 0; + + if (B->neg || (BN_ucmp(B, A) >= 0)) { + /* + * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, + * BN_div_no_branch will be called eventually. + */ + { + BIGNUM local_B; + bn_init(&local_B); + BN_with_flags(&local_B, B, BN_FLG_CONSTTIME); + + if (!BN_nnmod(B, &local_B, A, ctx)) + goto err; + + /* Ensure local_B goes out of scope before any further use of B */ + } + } + + sign = -1; + /*- + * From B = a mod |n|, A = |n| it follows that + * + * 0 <= B < A, + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + */ + + while (!BN_is_zero(B)) { + BIGNUM *tmp; + /*- + * 0 < B < A, + * (*) -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|) + */ + /* + * Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked, + * BN_div_no_branch will be called eventually. + */ + { + BIGNUM local_A; + bn_init(&local_A); + BN_with_flags(&local_A, A, BN_FLG_CONSTTIME); + + /* (D, M) := (A/B, A%B) ... */ + if (!BN_div(D, M, &local_A, B, ctx)) + goto err; + + /* Ensure local_A goes out of scope before any further use of A */ + } + /*- + * Now + * A = D*B + M; + * thus we have + * (**) sign*Y*a == D*B + M (mod |n|). + */ + tmp = A; /* keep the BIGNUM object, the value does not matter */ + /* (A, B) := (B, A mod B) ... */ + A = B; + B = M; + /* ... so we have 0 <= B < A again */ + + /*- + * Since the former M is now B and the former B is now A, + * (**) translates into + * sign*Y*a == D*A + B (mod |n|), + * i.e. + * sign*Y*a - D*A == B (mod |n|). + * Similarly, (*) translates into + * -sign*X*a == A (mod |n|). + * + * Thus, + * sign*Y*a + D*sign*X*a == B (mod |n|), + * i.e. + * sign*(Y + D*X)*a == B (mod |n|). + * + * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + * Note that X and Y stay non-negative all the time. + */ + + if (!BN_mul(tmp, D, X, ctx)) + goto err; + + if (!BN_add(tmp, tmp, Y)) + goto err; + + M = Y; /* keep the BIGNUM object, the value does not matter */ + Y = X; + X = tmp; + sign = -sign; + } + + /*- + * The while loop (Euclid's algorithm) ends when + * A == gcd(a,n); + * we have + * sign*Y*a == A (mod |n|), + * where Y is non-negative. + */ + + if (sign < 0) { + if (!BN_sub(Y, n, Y)) + goto err; + } + + /* Now Y*a == A (mod |n|). */ + + if (BN_is_one(A)) { + /* Y*a == 1 (mod |n|) */ + if (!Y->neg && BN_ucmp(Y, n) < 0) { + if (!BN_copy(R, Y)) + goto err; + } else { + if (!BN_nnmod(R, Y, n, ctx)) + goto err; + } + } else { + BNerr(BN_F_BN_MOD_INVERSE_NO_BRANCH, BN_R_NO_INVERSE); + goto err; + } + + ret = R; +err: + + if ((ret == NULL) && (in == NULL)) + BN_free(R); + + BN_CTX_end(ctx); + bn_check_top(ret); + return ret; +} + + +BIGNUM *int_bn_mod_inverse(BIGNUM *in, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx, + int *pnoinv) +{ + BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL; + BIGNUM *ret = NULL; + int sign; + + if (pnoinv) + *pnoinv = 0; + + if ((BN_get_flags(a, BN_FLG_CONSTTIME) != 0) + || (BN_get_flags(n, BN_FLG_CONSTTIME) != 0)) + return BN_mod_inverse_no_branch(in, a, n, ctx); + + bn_check_top(a); + bn_check_top(n); + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + B = BN_CTX_get(ctx); + X = BN_CTX_get(ctx); + D = BN_CTX_get(ctx); + M = BN_CTX_get(ctx); + Y = BN_CTX_get(ctx); + T = BN_CTX_get(ctx); + + if (T == NULL) + goto err; + + if (in == NULL) + R = BN_new(); + else + R = in; + + if (R == NULL) + goto err; + + BN_one(X); + BN_zero(Y); + + if (BN_copy(B, a) == NULL) + goto err; + + if (BN_copy(A, n) == NULL) + goto err; + + A->neg = 0; + + if (B->neg || (BN_ucmp(B, A) >= 0)) { + if (!BN_nnmod(B, B, A, ctx)) + goto err; + } + + sign = -1; + /*- + * From B = a mod |n|, A = |n| it follows that + * + * 0 <= B < A, + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + */ + + if (BN_is_odd(n) && (BN_num_bits(n) <= 2048)) { + /* + * Binary inversion algorithm; requires odd modulus. This is faster + * than the general algorithm if the modulus is sufficiently small + * (about 400 .. 500 bits on 32-bit systems, but much more on 64-bit + * systems) + */ + int shift; + + while (!BN_is_zero(B)) { + /*- + * 0 < B < |n|, + * 0 < A <= |n|, + * (1) -sign*X*a == B (mod |n|), + * (2) sign*Y*a == A (mod |n|) + */ + /* + * Now divide B by the maximum possible power of two in the + * integers, and divide X by the same value mod |n|. When we're + * done, (1) still holds. + */ + shift = 0; + + while (!BN_is_bit_set(B, shift)) { /* note that 0 < B */ + shift++; + + if (BN_is_odd(X)) { + if (!BN_uadd(X, X, n)) + goto err; + } + + /* + * now X is even, so we can easily divide it by two + */ + if (!BN_rshift1(X, X)) + goto err; + } + + if (shift > 0) { + if (!BN_rshift(B, B, shift)) + goto err; + } + + /* + * Same for A and Y. Afterwards, (2) still holds. + */ + shift = 0; + + while (!BN_is_bit_set(A, shift)) { /* note that 0 < A */ + shift++; + + if (BN_is_odd(Y)) { + if (!BN_uadd(Y, Y, n)) + goto err; + } + + /* now Y is even */ + if (!BN_rshift1(Y, Y)) + goto err; + } + + if (shift > 0) { + if (!BN_rshift(A, A, shift)) + goto err; + } + + /*- + * We still have (1) and (2). + * Both A and B are odd. + * The following computations ensure that + * + * 0 <= B < |n|, + * 0 < A < |n|, + * (1) -sign*X*a == B (mod |n|), + * (2) sign*Y*a == A (mod |n|), + * + * and that either A or B is even in the next iteration. + */ + if (BN_ucmp(B, A) >= 0) { + /* -sign*(X + Y)*a == B - A (mod |n|) */ + if (!BN_uadd(X, X, Y)) + goto err; + + /* + * NB: we could use BN_mod_add_quick(X, X, Y, n), but that + * actually makes the algorithm slower + */ + if (!BN_usub(B, B, A)) + goto err; + } else { + /* sign*(X + Y)*a == A - B (mod |n|) */ + if (!BN_uadd(Y, Y, X)) + goto err; + + /* + * as above, BN_mod_add_quick(Y, Y, X, n) would slow things down + */ + if (!BN_usub(A, A, B)) + goto err; + } + } + } else { + /* general inversion algorithm */ + while (!BN_is_zero(B)) { + BIGNUM *tmp; + + /*- + * 0 < B < A, + * (*) -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|) + */ + + /* (D, M) := (A/B, A%B) ... */ + if (BN_num_bits(A) == BN_num_bits(B)) { + if (!BN_one(D)) + goto err; + + if (!BN_sub(M, A, B)) + goto err; + } else if (BN_num_bits(A) == BN_num_bits(B) + 1) { + /* A/B is 1, 2, or 3 */ + if (!BN_lshift1(T, B)) + goto err; + + if (BN_ucmp(A, T) < 0) { + /* A < 2*B, so D=1 */ + if (!BN_one(D)) + goto err; + + if (!BN_sub(M, A, B)) + goto err; + } else { + /* A >= 2*B, so D=2 or D=3 */ + if (!BN_sub(M, A, T)) + goto err; + + if (!BN_add(D, T, B)) + goto err; /* use D (:= 3*B) as temp */ + + if (BN_ucmp(A, D) < 0) { + /* A < 3*B, so D=2 */ + if (!BN_set_word(D, 2)) + goto err; + + /* + * M (= A - 2*B) already has the correct value + */ + } else { + /* only D=3 remains */ + if (!BN_set_word(D, 3)) + goto err; + + /* + * currently M = A - 2*B, but we need M = A - 3*B + */ + if (!BN_sub(M, M, B)) + goto err; + } + } + } else { + if (!BN_div(D, M, A, B, ctx)) + goto err; + } + + /*- + * Now + * A = D*B + M; + * thus we have + * (**) sign*Y*a == D*B + M (mod |n|). + */ + tmp = A; /* keep the BIGNUM object, the value does not matter */ + /* (A, B) := (B, A mod B) ... */ + A = B; + B = M; + /* ... so we have 0 <= B < A again */ + + /*- + * Since the former M is now B and the former B is now A, + * (**) translates into + * sign*Y*a == D*A + B (mod |n|), + * i.e. + * sign*Y*a - D*A == B (mod |n|). + * Similarly, (*) translates into + * -sign*X*a == A (mod |n|). + * + * Thus, + * sign*Y*a + D*sign*X*a == B (mod |n|), + * i.e. + * sign*(Y + D*X)*a == B (mod |n|). + * + * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at + * -sign*X*a == B (mod |n|), + * sign*Y*a == A (mod |n|). + * Note that X and Y stay non-negative all the time. + */ + + /* + * most of the time D is very small, so we can optimize tmp := D*X+Y + */ + if (BN_is_one(D)) { + if (!BN_add(tmp, X, Y)) + goto err; + } else { + if (BN_is_word(D, 2)) { + if (!BN_lshift1(tmp, X)) + goto err; + } else if (BN_is_word(D, 4)) { + if (!BN_lshift(tmp, X, 2)) + goto err; + } else if (D->top == 1) { + if (!BN_copy(tmp, X)) + goto err; + + if (!BN_mul_word(tmp, D->d[0])) + goto err; + } else { + if (!BN_mul(tmp, D, X, ctx)) + goto err; + } + + if (!BN_add(tmp, tmp, Y)) + goto err; + } + + M = Y; /* keep the BIGNUM object, the value does not matter */ + Y = X; + X = tmp; + sign = -sign; + } + } + + /*- + * The while loop (Euclid's algorithm) ends when + * A == gcd(a,n); + * we have + * sign*Y*a == A (mod |n|), + * where Y is non-negative. + */ + + if (sign < 0) { + if (!BN_sub(Y, n, Y)) + goto err; + } + + /* Now Y*a == A (mod |n|). */ + + if (BN_is_one(A)) { + /* Y*a == 1 (mod |n|) */ + if (!Y->neg && BN_ucmp(Y, n) < 0) { + if (!BN_copy(R, Y)) + goto err; + } else { + if (!BN_nnmod(R, Y, n, ctx)) + goto err; + } + } else { + if (pnoinv) + *pnoinv = 1; + + goto err; + } + + ret = R; +err: + + if ((ret == NULL) && (in == NULL)) + BN_free(R); + + BN_CTX_end(ctx); + bn_check_top(ret); + return ret; +} + +BIGNUM *BN_mod_inverse(BIGNUM *in, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) +{ + BIGNUM *rv; + int noinv; + rv = int_bn_mod_inverse(in, a, n, ctx, &noinv); + + if (noinv) + BNerr(BN_F_BN_MOD_INVERSE, BN_R_NO_INVERSE); + + return rv; +} + +int BN_lshift1(BIGNUM *r, const BIGNUM *a) +{ + register BN_ULONG *ap, *rp, t, c; + int i; + bn_check_top(r); + bn_check_top(a); + + if (r != a) { + r->neg = a->neg; + + if (bn_wexpand(r, a->top + 1) == NULL) + return 0; + + r->top = a->top; + } else { + if (bn_wexpand(r, a->top + 1) == NULL) + return 0; + } + + ap = a->d; + rp = r->d; + c = 0; + + for (i = 0; i < a->top; i++) { + t = *(ap++); + *(rp++) = ((t << 1) | c) & BN_MASK2; + c = (t & BN_TBIT) ? 1 : 0; + } + + if (c) { + *rp = 1; + r->top++; + } + + bn_check_top(r); + return 1; +} + +int BN_rshift1(BIGNUM *r, const BIGNUM *a) +{ + BN_ULONG *ap, *rp, t, c; + int i, j; + bn_check_top(r); + bn_check_top(a); + + if (BN_is_zero(a)) { + BN_zero(r); + return 1; + } + + i = a->top; + ap = a->d; + j = i - (ap[i - 1] == 1); + + if (a != r) { + if (bn_wexpand(r, j) == NULL) + return 0; + + r->neg = a->neg; + } + + rp = r->d; + t = ap[--i]; + c = (t & 1) ? BN_TBIT : 0; + + if (t >>= 1) + rp[i] = t; + + while (i > 0) { + t = ap[--i]; + rp[i] = ((t >> 1) & BN_MASK2) | c; + c = (t & 1) ? BN_TBIT : 0; + } + + r->top = j; + + if (!r->top) + r->neg = 0; /* don't allow negative zero */ + + bn_check_top(r); + return 1; +} + +int BN_lshift(BIGNUM *r, const BIGNUM *a, int n) +{ + int i, nw, lb, rb; + BN_ULONG *t, *f; + BN_ULONG l; + bn_check_top(r); + bn_check_top(a); + + if (n < 0) { + BNerr(BN_F_BN_LSHIFT, BN_R_INVALID_SHIFT); + return 0; + } + + nw = n / BN_BITS2; + + if (bn_wexpand(r, a->top + nw + 1) == NULL) + return 0; + + r->neg = a->neg; + lb = n % BN_BITS2; + rb = BN_BITS2 - lb; + f = a->d; + t = r->d; + t[a->top + nw] = 0; + + if (lb == 0) + for (i = a->top - 1; i >= 0; i--) + t[nw + i] = f[i]; + else + for (i = a->top - 1; i >= 0; i--) { + l = f[i]; + t[nw + i + 1] |= (l >> rb) & BN_MASK2; + t[nw + i] = (l << lb) & BN_MASK2; + } + + memset(t, 0, sizeof(*t) * nw); + r->top = a->top + nw + 1; + bn_correct_top(r); + bn_check_top(r); + return 1; +} + +int BN_rshift(BIGNUM *r, const BIGNUM *a, int n) +{ + int i, j, nw, lb, rb; + BN_ULONG *t, *f; + BN_ULONG l, tmp; + bn_check_top(r); + bn_check_top(a); + + if (n < 0) { + BNerr(BN_F_BN_RSHIFT, BN_R_INVALID_SHIFT); + return 0; + } + + nw = n / BN_BITS2; + rb = n % BN_BITS2; + lb = BN_BITS2 - rb; + + if (nw >= a->top || a->top == 0) { + BN_zero(r); + return 1; + } + + i = (BN_num_bits(a) - n + (BN_BITS2 - 1)) / BN_BITS2; + + if (r != a) { + if (bn_wexpand(r, i) == NULL) + return 0; + + r->neg = a->neg; + } else { + if (n == 0) + return 1; /* or the copying loop will go berserk */ + } + + f = &(a->d[nw]); + t = r->d; + j = a->top - nw; + r->top = i; + + if (rb == 0) { + for (i = j; i != 0; i--) + *(t++) = *(f++); + } else { + l = *(f++); + + for (i = j - 1; i != 0; i--) { + tmp = (l >> rb) & BN_MASK2; + l = *(f++); + *(t++) = (tmp | (l << lb)) & BN_MASK2; + } + l = (l >> rb); + if ((l & BN_MASK2)) + *(t) = l; + } + + if (!r->top) + r->neg = 0; /* don't allow negative zero */ + + bn_check_top(r); + return 1; +} + +int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx) +{ + /* + * like BN_mod, but returns non-negative remainder (i.e., 0 <= r < |d| + * always holds) + */ + if (!(BN_mod(r, m, d, ctx))) + return 0; + + if (!r->neg) + return 1; + + /* now -|d| < r < 0, so we have to set r := r + |d| */ + return (d->neg ? BN_sub : BN_add) (r, r, d); +} + +int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx) +{ + if (!BN_add(r, a, b)) + return 0; + + return BN_nnmod(r, r, m, ctx); +} + +/* + * BN_mod_add variant that may be used if both a and b are non-negative and + * less than m + */ +int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m) +{ + if (!BN_uadd(r, a, b)) + return 0; + + if (BN_ucmp(r, m) >= 0) + return BN_usub(r, r, m); + + return 1; +} + +int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx) +{ + if (!BN_sub(r, a, b)) + return 0; + + return BN_nnmod(r, r, m, ctx); +} + +/* + * BN_mod_sub variant that may be used if both a and b are non-negative and + * less than m + */ +int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m) +{ + if (!BN_sub(r, a, b)) + return 0; + + if (r->neg) + return BN_add(r, r, m); + + return 1; +} + +/* slow but works */ +int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx) +{ + BIGNUM *t; + int ret = 0; + bn_check_top(a); + bn_check_top(b); + bn_check_top(m); + BN_CTX_start(ctx); + + t = BN_CTX_get(ctx); + if (t == NULL) + goto err; + + if (a == b) { + if (!BN_sqr(t, a, ctx)) + goto err; + } else { + if (!BN_mul(t, a, b, ctx)) + goto err; + } + + if (!BN_nnmod(r, t, m, ctx)) + goto err; + + bn_check_top(r); + ret = 1; +err: + BN_CTX_end(ctx); + return ret; +} + +int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) +{ + if (!BN_sqr(r, a, ctx)) + return 0; + + /* r->neg == 0, thus we don't need BN_nnmod */ + return BN_mod(r, r, m, ctx); +} + +int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx) +{ + if (!BN_lshift1(r, a)) + return 0; + + bn_check_top(r); + return BN_nnmod(r, r, m, ctx); +} + +/* + * BN_mod_lshift1 variant that may be used if a is non-negative and less than + * m + */ +int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m) +{ + if (!BN_lshift1(r, a)) + return 0; + + bn_check_top(r); + + if (BN_cmp(r, m) >= 0) + return BN_sub(r, r, m); + + return 1; +} + +int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, + BN_CTX *ctx) +{ + BIGNUM *abs_m = NULL; + int ret; + + if (!BN_nnmod(r, a, m, ctx)) + return 0; + + if (m->neg) { + abs_m = BN_dup(m); + + if (abs_m == NULL) + return 0; + + abs_m->neg = 0; + } + + ret = BN_mod_lshift_quick(r, r, n, (abs_m ? abs_m : m)); + bn_check_top(r); + BN_free(abs_m); + return ret; +} + +/* + * BN_mod_lshift variant that may be used if a is non-negative and less than + * m + */ +int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m) +{ + if (r != a) { + if (BN_copy(r, a) == NULL) + return 0; + } + + while (n > 0) { + int max_shift; + /* 0 < r < m */ + max_shift = BN_num_bits(m) - BN_num_bits(r); + /* max_shift >= 0 */ + + if (max_shift < 0) { + BNerr(BN_F_BN_MOD_LSHIFT_QUICK, BN_R_INPUT_NOT_REDUCED); + return 0; + } + + if (max_shift > n) + max_shift = n; + + if (max_shift) { + if (!BN_lshift(r, r, max_shift)) + return 0; + + n -= max_shift; + } else { + if (!BN_lshift1(r, r)) + return 0; + + --n; + } + + /* BN_num_bits(r) <= BN_num_bits(m) */ + + if (BN_cmp(r, m) >= 0) { + if (!BN_sub(r, r, m)) + return 0; + } + } + + bn_check_top(r); + return 1; +} + +/* r can == a or b */ +int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) +{ + int a_neg = a->neg, ret; + bn_check_top(a); + bn_check_top(b); + + /*- + * a + b a+b + * a + -b a-b + * -a + b b-a + * -a + -b -(a+b) + */ + if (a_neg ^ b->neg) { + /* only one is negative */ + if (a_neg) { + const BIGNUM *tmp; + tmp = a; + a = b; + b = tmp; + } + + /* we are now a - b */ + + if (BN_ucmp(a, b) < 0) { + if (!BN_usub(r, b, a)) + return 0; + + r->neg = 1; + } else { + if (!BN_usub(r, a, b)) + return 0; + + r->neg = 0; + } + + return 1; + } + + ret = BN_uadd(r, a, b); + r->neg = a_neg; + bn_check_top(r); + return ret; +} + +/* unsigned add of b to a */ +int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) +{ + int max, min, dif; + const BN_ULONG *ap, *bp; + BN_ULONG *rp, carry, t1, t2; + bn_check_top(a); + bn_check_top(b); + + if (a->top < b->top) { + const BIGNUM *tmp; + tmp = a; + a = b; + b = tmp; + } + + max = a->top; + min = b->top; + dif = max - min; + + if (bn_wexpand(r, max + 1) == NULL) + return 0; + + r->top = max; + ap = a->d; + bp = b->d; + rp = r->d; + carry = bn_add_words(rp, ap, bp, min); + rp += min; + ap += min; + + while (dif) { + dif--; + t1 = *(ap++); + t2 = (t1 + carry) & BN_MASK2; + *(rp++) = t2; + carry &= (t2 == 0); + } + + *rp = carry; + r->top += carry; + r->neg = 0; + bn_check_top(r); + return 1; +} + +/* unsigned subtraction of b from a, a must be larger than b. */ +int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) +{ + int max, min, dif; + BN_ULONG t1, t2, borrow, *rp; + const BN_ULONG *ap, *bp; + bn_check_top(a); + bn_check_top(b); + max = a->top; + min = b->top; + dif = max - min; + + if (dif < 0) { /* hmm... should not be happening */ + BNerr(BN_F_BN_USUB, BN_R_ARG2_LT_ARG3); + return 0; + } + + if (bn_wexpand(r, max) == NULL) + return 0; + + ap = a->d; + bp = b->d; + rp = r->d; + borrow = bn_sub_words(rp, ap, bp, min); + ap += min; + rp += min; + + while (dif) { + dif--; + t1 = *(ap++); + t2 = (t1 - borrow) & BN_MASK2; + *(rp++) = t2; + borrow &= (t1 == 0); + } + + r->top = max; + r->neg = 0; + bn_correct_top(r); + return 1; +} + +int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) +{ + int max; + int add = 0, neg = 0; + bn_check_top(a); + bn_check_top(b); + + /*- + * a - b a-b + * a - -b a+b + * -a - b -(a+b) + * -a - -b b-a + */ + if (a->neg) { + if (b->neg) { + const BIGNUM *tmp; + tmp = a; + a = b; + b = tmp; + } else { + add = 1; + neg = 1; + } + } else { + if (b->neg) { + add = 1; + neg = 0; + } + } + + if (add) { + if (!BN_uadd(r, a, b)) + return 0; + + r->neg = neg; + return 1; + } + + /* We are actually doing a - b :-) */ + max = (a->top > b->top) ? a->top : b->top; + + if (bn_wexpand(r, max) == NULL) + return 0; + + if (BN_ucmp(a, b) < 0) { + if (!BN_usub(r, b, a)) + return 0; + + r->neg = 1; + } else { + if (!BN_usub(r, a, b)) + return 0; + + r->neg = 0; + } + + bn_check_top(r); + return 1; +} + +BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w) +{ +#ifndef BN_LLONG + BN_ULONG ret = 0; +#else + BN_ULLONG ret = 0; +#endif + int i; + + if (w == 0) + return (BN_ULONG)-1; + +#ifndef BN_LLONG + + /* + * If |w| is too long and we don't have BN_ULLONG then we need to fall + * back to using BN_div_word + */ + if (w > ((BN_ULONG)1 << BN_BITS4)) { + BIGNUM *tmp = BN_dup(a); + + if (tmp == NULL) + return (BN_ULONG)-1; + + ret = BN_div_word(tmp, w); + BN_free(tmp); + return ret; + } + +#endif + bn_check_top(a); + w &= BN_MASK2; + + for (i = a->top - 1; i >= 0; i--) { +#ifndef BN_LLONG + /* + * We can assume here that | w <= ((BN_ULONG)1 << BN_BITS4) | and so + * | ret < ((BN_ULONG)1 << BN_BITS4) | and therefore the shifts here are + * safe and will not overflow + */ + ret = ((ret << BN_BITS4) | ((a->d[i] >> BN_BITS4) & BN_MASK2l)) % w; + ret = ((ret << BN_BITS4) | (a->d[i] & BN_MASK2l)) % w; +#else + ret = (BN_ULLONG) (((ret << (BN_ULLONG) BN_BITS2) | a->d[i]) % + (BN_ULLONG) w); +#endif + } + + return ((BN_ULONG)ret); +} + +BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w) +{ + BN_ULONG ret = 0; + int i, j; + bn_check_top(a); + w &= BN_MASK2; + + if (!w) + /* actually this an error (division by zero) */ + return (BN_ULONG)-1; + + if (a->top == 0) + return 0; + + /* normalize input (so bn_div_words doesn't complain) */ + j = BN_BITS2 - BN_num_bits_word(w); + w <<= j; + + if (!BN_lshift(a, a, j)) + return (BN_ULONG)-1; + + for (i = a->top - 1; i >= 0; i--) { + BN_ULONG l, d; + l = a->d[i]; + d = bn_div_words(ret, l, w); + ret = (l - ((d * w) & BN_MASK2)) & BN_MASK2; + a->d[i] = d; + } + + if ((a->top > 0) && (a->d[a->top - 1] == 0)) + a->top--; + + ret >>= j; + + if (!a->top) + a->neg = 0; /* don't allow negative zero */ + + bn_check_top(a); + return ret; +} + +int BN_add_word(BIGNUM *a, BN_ULONG w) +{ + BN_ULONG l; + int i; + bn_check_top(a); + w &= BN_MASK2; + + /* degenerate case: w is zero */ + if (!w) + return 1; + + /* degenerate case: a is zero */ + if (BN_is_zero(a)) + return BN_set_word(a, w); + + /* handle 'a' when negative */ + if (a->neg) { + a->neg = 0; + i = BN_sub_word(a, w); + + if (!BN_is_zero(a)) + a->neg = !(a->neg); + + return i; + } + + for (i = 0; w != 0 && i < a->top; i++) { + a->d[i] = l = (a->d[i] + w) & BN_MASK2; + w = (w > l) ? 1 : 0; + } + + if (w && i == a->top) { + if (bn_wexpand(a, a->top + 1) == NULL) + return 0; + + a->top++; + a->d[i] = w; + } + + bn_check_top(a); + return 1; +} + +int BN_sub_word(BIGNUM *a, BN_ULONG w) +{ + int i; + bn_check_top(a); + w &= BN_MASK2; + + /* degenerate case: w is zero */ + if (!w) + return 1; + + /* degenerate case: a is zero */ + if (BN_is_zero(a)) { + i = BN_set_word(a, w); + + if (i != 0) + BN_set_negative(a, 1); + + return i; + } + + /* handle 'a' when negative */ + if (a->neg) { + a->neg = 0; + i = BN_add_word(a, w); + a->neg = 1; + return i; + } + + if ((a->top == 1) && (a->d[0] < w)) { + a->d[0] = w - a->d[0]; + a->neg = 1; + return 1; + } + + i = 0; + + for (;;) { + if (a->d[i] >= w) { + a->d[i] -= w; + break; + } else { + a->d[i] = (a->d[i] - w) & BN_MASK2; + i++; + w = 1; + } + } + + if ((a->d[i] == 0) && (i == (a->top - 1))) + a->top--; + + bn_check_top(a); + return 1; +} + +int BN_mul_word(BIGNUM *a, BN_ULONG w) +{ + BN_ULONG ll; + bn_check_top(a); + w &= BN_MASK2; + + if (a->top) { + if (w == 0) + BN_zero(a); + else { + ll = bn_mul_words(a->d, a->d, a->top, w); + + if (ll) { + if (bn_wexpand(a, a->top + 1) == NULL) + return 0; + + a->d[a->top++] = ll; + } + } + } + + bn_check_top(a); + return 1; +} + +/*- + * BN_div computes dv := num / divisor, rounding towards + * zero, and sets up rm such that dv*divisor + rm = num holds. + * Thus: + * dv->neg == num->neg ^ divisor->neg (unless the result is zero) + * rm->neg == num->neg (unless the remainder is zero) + * If 'dv' or 'rm' is NULL, the respective value is not returned. + */ +int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, + BN_CTX *ctx) +{ + int norm_shift, i, loop; + BIGNUM *tmp, wnum, *snum, *sdiv, *res; + BN_ULONG *resp, *wnump; + BN_ULONG d0, d1; + int num_n, div_n; + int no_branch = 0; + + /* + * Invalid zero-padding would have particularly bad consequences so don't + * just rely on bn_check_top() here (bn_check_top() works only for + * BN_DEBUG builds) + */ + if ((num->top > 0 && num->d[num->top - 1] == 0) || + (divisor->top > 0 && divisor->d[divisor->top - 1] == 0)) { + BNerr(BN_F_BN_DIV, BN_R_NOT_INITIALIZED); + return 0; + } + + bn_check_top(num); + bn_check_top(divisor); + + if ((BN_get_flags(num, BN_FLG_CONSTTIME) != 0) + || (BN_get_flags(divisor, BN_FLG_CONSTTIME) != 0)) + no_branch = 1; + + bn_check_top(dv); + bn_check_top(rm); + /*- bn_check_top(num); *//* + * 'num' has been checked already + */ + /*- bn_check_top(divisor); *//* + * 'divisor' has been checked already + */ + + if (BN_is_zero(divisor)) { + BNerr(BN_F_BN_DIV, BN_R_DIV_BY_ZERO); + return 0; + } + + if (!no_branch && BN_ucmp(num, divisor) < 0) { + if (rm != NULL) { + if (BN_copy(rm, num) == NULL) + return 0; + } + + if (dv != NULL) + BN_zero(dv); + + return 1; + } + + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + snum = BN_CTX_get(ctx); + sdiv = BN_CTX_get(ctx); + + if (dv == NULL) + res = BN_CTX_get(ctx); + else + res = dv; + + if (sdiv == NULL || res == NULL || tmp == NULL || snum == NULL) + goto err; + + /* First we normalise the numbers */ + norm_shift = BN_BITS2 - ((BN_num_bits(divisor)) % BN_BITS2); + + if (!(BN_lshift(sdiv, divisor, norm_shift))) + goto err; + + sdiv->neg = 0; + norm_shift += BN_BITS2; + + if (!(BN_lshift(snum, num, norm_shift))) + goto err; + + snum->neg = 0; + + if (no_branch) { + /* + * Since we don't know whether snum is larger than sdiv, we pad snum + * with enough zeroes without changing its value. + */ + if (snum->top <= sdiv->top + 1) { + if (bn_wexpand(snum, sdiv->top + 2) == NULL) + goto err; + + for (i = snum->top; i < sdiv->top + 2; i++) + snum->d[i] = 0; + + snum->top = sdiv->top + 2; + } else { + if (bn_wexpand(snum, snum->top + 1) == NULL) + goto err; + + snum->d[snum->top] = 0; + snum->top++; + } + } + + div_n = sdiv->top; + num_n = snum->top; + loop = num_n - div_n; + /* + * Lets setup a 'window' into snum This is the part that corresponds to + * the current 'area' being divided + */ + wnum.neg = 0; + wnum.d = &(snum->d[loop]); + wnum.top = div_n; + /* + * only needed when BN_ucmp messes up the values between top and max + */ + wnum.dmax = snum->dmax - loop; /* so we don't step out of bounds */ + /* Get the top 2 words of sdiv */ + /* div_n=sdiv->top; */ + d0 = sdiv->d[div_n - 1]; + d1 = (div_n == 1) ? 0 : sdiv->d[div_n - 2]; + /* pointer to the 'top' of snum */ + wnump = &(snum->d[num_n - 1]); + + /* Setup to 'res' */ + if (!bn_wexpand(res, (loop + 1))) + goto err; + + res->neg = (num->neg ^ divisor->neg); + res->top = loop - no_branch; + resp = &(res->d[loop - 1]); + + /* space for temp */ + if (!bn_wexpand(tmp, (div_n + 1))) + goto err; + + if (!no_branch) { + if (BN_ucmp(&wnum, sdiv) >= 0) { + /* + * If BN_DEBUG_RAND is defined BN_ucmp changes (via bn_pollute) + * the const bignum arguments => clean the values between top and + * max again + */ + bn_sub_words(wnum.d, wnum.d, sdiv->d, div_n); + *resp = 1; + } else + res->top--; + } + + /* Increase the resp pointer so that we never create an invalid pointer. */ + resp++; + + /* + * if res->top == 0 then clear the neg value otherwise decrease the resp + * pointer + */ + if (res->top == 0) + res->neg = 0; + else + resp--; + + for (i = 0; i < loop - 1; i++, wnump--) { + BN_ULONG q, l0; + /* + * the first part of the loop uses the top two words of snum and sdiv + * to calculate a BN_ULONG q such that | wnum - sdiv * q | < sdiv + */ +# if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM) + BN_ULONG bn_div_3_words(BN_ULONG *, BN_ULONG, BN_ULONG); + q = bn_div_3_words(wnump, d1, d0); +# else + BN_ULONG n0, n1, rem = 0; + n0 = wnump[0]; + n1 = wnump[-1]; + + if (n0 == d0) + q = BN_MASK2; + else { /* n0 < d0 */ +# ifdef BN_LLONG + BN_ULLONG t2; +# if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words) + q = (BN_ULONG)(((((BN_ULLONG) n0) << BN_BITS2) | n1) / d0); +# else + q = bn_div_words(n0, n1, d0); +# endif +# ifndef REMAINDER_IS_ALREADY_CALCULATED + /* + * rem doesn't have to be BN_ULLONG. The least we + * know it's less that d0, isn't it? + */ + rem = (n1 - q * d0) & BN_MASK2; +# endif + t2 = (BN_ULLONG) d1 * q; + + for (;;) { + if (t2 <= ((((BN_ULLONG) rem) << BN_BITS2) | wnump[-2])) + break; + + q--; + rem += d0; + + if (rem < d0) + break; /* don't let rem overflow */ + + t2 -= d1; + } + +# else /* !BN_LLONG */ + BN_ULONG t2l, t2h; + q = bn_div_words(n0, n1, d0); +# ifndef REMAINDER_IS_ALREADY_CALCULATED + rem = (n1 - q * d0) & BN_MASK2; +# endif +# if defined(BN_UMULT_LOHI) + BN_UMULT_LOHI(t2l, t2h, d1, q); +# elif defined(BN_UMULT_HIGH) + t2l = d1 * q; + t2h = BN_UMULT_HIGH(d1, q); +# else + { + BN_ULONG ql, qh; + t2l = LBITS(d1); + t2h = HBITS(d1); + ql = LBITS(q); + qh = HBITS(q); + mul64(t2l, t2h, ql, qh); /* t2=(BN_ULLONG)d1*q; */ + } +# endif + + for (;;) { + if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2]))) + break; + + q--; + rem += d0; + + if (rem < d0) + break; /* don't let rem overflow */ + + if (t2l < d1) + t2h--; + + t2l -= d1; + } + +# endif /* !BN_LLONG */ + } + +# endif /* !BN_DIV3W */ + l0 = bn_mul_words(tmp->d, sdiv->d, div_n, q); + tmp->d[div_n] = l0; + wnum.d--; + + /* + * ingore top values of the bignums just sub the two BN_ULONG arrays + * with bn_sub_words + */ + if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n + 1)) { + /* + * Note: As we have considered only the leading two BN_ULONGs in + * the calculation of q, sdiv * q might be greater than wnum (but + * then (q-1) * sdiv is less or equal than wnum) + */ + q--; + + if (bn_add_words(wnum.d, wnum.d, sdiv->d, div_n)) + /* + * we can't have an overflow here (assuming that q != 0, but + * if q == 0 then tmp is zero anyway) + */ + (*wnump)++; + } + + /* store part of the result */ + resp--; + *resp = q; + } + + bn_correct_top(snum); + + if (rm != NULL) { + /* + * Keep a copy of the neg flag in num because if rm==num BN_rshift() + * will overwrite it. + */ + int neg = num->neg; + BN_rshift(rm, snum, norm_shift); + + if (!BN_is_zero(rm)) + rm->neg = neg; + + bn_check_top(rm); + } + + if (no_branch) + bn_correct_top(res); + + BN_CTX_end(ctx); + return 1; +err: + bn_check_top(rm); + BN_CTX_end(ctx); + return 0; +} + +static inline unsigned int constant_time_msb(unsigned int a) +{ + return 0 - (a >> (sizeof(a) * 8 - 1)); +} + + +static inline unsigned int constant_time_is_zero(unsigned int a) +{ + return constant_time_msb(~a & (a - 1)); +} + + +static inline unsigned int constant_time_eq(unsigned int a, + unsigned int b) +{ + return constant_time_is_zero(a ^ b); +} + +static inline unsigned int constant_time_eq_int(int a, int b) +{ + return constant_time_eq((unsigned)(a), (unsigned)(b)); +} + + +/* maximum precomputation table size for *variable* sliding windows */ +#define TABLESIZE 32 + +/* this one works - simple but works */ +int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) +{ + int i, bits, ret = 0; + BIGNUM *v, *rr; + + if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0 + || BN_get_flags(a, BN_FLG_CONSTTIME) != 0) { + /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ + BNerr(BN_F_BN_EXP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + BN_CTX_start(ctx); + + if ((r == a) || (r == p)) + rr = BN_CTX_get(ctx); + else + rr = r; + + v = BN_CTX_get(ctx); + + if (rr == NULL || v == NULL) + goto err; + + if (BN_copy(v, a) == NULL) + goto err; + + bits = BN_num_bits(p); + + if (BN_is_odd(p)) { + if (BN_copy(rr, a) == NULL) + goto err; + } else { + if (!BN_one(rr)) + goto err; + } + + for (i = 1; i < bits; i++) { + if (!BN_sqr(v, v, ctx)) + goto err; + + if (BN_is_bit_set(p, i)) { + if (!BN_mul(rr, rr, v, ctx)) + goto err; + } + } + + if (r != rr && BN_copy(r, rr) == NULL) + goto err; + + ret = 1; +err: + BN_CTX_end(ctx); + bn_check_top(r); + return ret; +} + +int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, + BN_CTX *ctx) +{ + int ret; + bn_check_top(a); + bn_check_top(p); + bn_check_top(m); + /*- + * For even modulus m = 2^k*m_odd, it might make sense to compute + * a^p mod m_odd and a^p mod 2^k separately (with Montgomery + * exponentiation for the odd part), using appropriate exponent + * reductions, and combine the results using the CRT. + * + * For now, we use Montgomery only if the modulus is odd; otherwise, + * exponentiation using the reciprocal-based quick remaindering + * algorithm is used. + * + * (Timing obtained with expspeed.c [computations a^p mod m + * where a, p, m are of the same length: 256, 512, 1024, 2048, + * 4096, 8192 bits], compared to the running time of the + * standard algorithm: + * + * BN_mod_exp_mont 33 .. 40 % [AMD K6-2, Linux, debug configuration] + * 55 .. 77 % [UltraSparc processor, but + * debug-solaris-sparcv8-gcc conf.] + * + * BN_mod_exp_recp 50 .. 70 % [AMD K6-2, Linux, debug configuration] + * 62 .. 118 % [UltraSparc, debug-solaris-sparcv8-gcc] + * + * On the Sparc, BN_mod_exp_recp was faster than BN_mod_exp_mont + * at 2048 and more bits, but at 512 and 1024 bits, it was + * slower even than the standard algorithm! + * + * "Real" timings [linux-elf, solaris-sparcv9-gcc configurations] + * should be obtained when the new Montgomery reduction code + * has been integrated into OpenSSL.) + */ +#define MONT_MUL_MOD +#define MONT_EXP_WORD +#define RECP_MUL_MOD +#ifdef MONT_MUL_MOD + /* + * I have finally been able to take out this pre-condition of the top bit + * being set. It was caused by an error in BN_div with negatives. There + * was also another problem when for a^b%m a >= m. eay 07-May-97 + */ + /* if ((m->d[m->top-1]&BN_TBIT) && BN_is_odd(m)) */ + + if (BN_is_odd(m)) { +# ifdef MONT_EXP_WORD + + if (a->top == 1 && !a->neg + && (BN_get_flags(p, BN_FLG_CONSTTIME) == 0) + && (BN_get_flags(a, BN_FLG_CONSTTIME) == 0) + && (BN_get_flags(m, BN_FLG_CONSTTIME) == 0)) { + BN_ULONG A = a->d[0]; + ret = BN_mod_exp_mont_word(r, A, p, m, ctx, NULL); + } else +# endif + ret = BN_mod_exp_mont(r, a, p, m, ctx, NULL); + } else +#endif +#ifdef RECP_MUL_MOD + { + ret = BN_mod_exp_recp(r, a, p, m, ctx); + } + +#else + { + ret = BN_mod_exp_simple(r, a, p, m, ctx); + } +#endif + bn_check_top(r); + return ret; +} + +int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx) +{ + int i, j, bits, ret = 0, wstart, wend, window, wvalue; + int start = 1; + BIGNUM *aa; + /* Table of variables obtained from 'ctx' */ + BIGNUM *val[TABLESIZE]; + BN_RECP_CTX recp; + + if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0 + || BN_get_flags(a, BN_FLG_CONSTTIME) != 0 + || BN_get_flags(m, BN_FLG_CONSTTIME) != 0) { + /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ + BNerr(BN_F_BN_MOD_EXP_RECP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + bits = BN_num_bits(p); + + if (bits == 0) { + /* x**0 mod 1 is still zero. */ + if (BN_is_one(m)) { + ret = 1; + BN_zero(r); + } else + ret = BN_one(r); + + return ret; + } + + BN_CTX_start(ctx); + aa = BN_CTX_get(ctx); + val[0] = BN_CTX_get(ctx); + + if (!aa || !val[0]) + goto err; + + BN_RECP_CTX_init(&recp); + + if (m->neg) { + /* ignore sign of 'm' */ + if (!BN_copy(aa, m)) + goto err; + + aa->neg = 0; + + if (BN_RECP_CTX_set(&recp, aa, ctx) <= 0) + goto err; + } else { + if (BN_RECP_CTX_set(&recp, m, ctx) <= 0) + goto err; + } + + if (!BN_nnmod(val[0], a, m, ctx)) + goto err; /* 1 */ + + if (BN_is_zero(val[0])) { + BN_zero(r); + ret = 1; + goto err; + } + + window = BN_window_bits_for_exponent_size(bits); + + if (window > 1) { + if (!BN_mod_mul_reciprocal(aa, val[0], val[0], &recp, ctx)) + goto err; /* 2 */ + + j = 1 << (window - 1); + + for (i = 1; i < j; i++) { + val[i] = BN_CTX_get(ctx); + if ((val[i] == NULL) || + !BN_mod_mul_reciprocal(val[i], val[i - 1], aa, &recp, ctx)) + goto err; + } + } + + start = 1; /* This is used to avoid multiplication etc when there is only the value '1' in the buffer. */ + wvalue = 0; /* The 'value' of the window */ + wstart = bits - 1; /* The top bit of the window */ + wend = 0; /* The bottom bit of the window */ + + if (!BN_one(r)) + goto err; + + for (;;) { + if (BN_is_bit_set(p, wstart) == 0) { + if (!start) + if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx)) + goto err; + + if (wstart == 0) + break; + + wstart--; + continue; + } + + /* + * We now have wstart on a 'set' bit, we now need to work out how bit + * a window to do. To do this we need to scan forward until the last + * set bit before the end of the window + */ + j = wstart; + wvalue = 1; + wend = 0; + + for (i = 1; i < window; i++) { + if (wstart - i < 0) + break; + + if (BN_is_bit_set(p, wstart - i)) { + wvalue <<= (i - wend); + wvalue |= 1; + wend = i; + } + } + + /* wend is the size of the current window */ + j = wend + 1; + + /* add the 'bytes above' */ + if (!start) + for (i = 0; i < j; i++) { + if (!BN_mod_mul_reciprocal(r, r, r, &recp, ctx)) + goto err; + } + + /* wvalue will be an odd number < 2^window */ + if (!BN_mod_mul_reciprocal(r, r, val[wvalue >> 1], &recp, ctx)) + goto err; + + /* move the 'window' down further */ + wstart -= wend + 1; + wvalue = 0; + start = 0; + + if (wstart < 0) + break; + } + + ret = 1; +err: + BN_CTX_end(ctx); + BN_RECP_CTX_free(&recp); + bn_check_top(r); + return ret; +} + +int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont) +{ + int i, j, bits, ret = 0, wstart, wend, window, wvalue; + int start = 1; + BIGNUM *d, *r; + const BIGNUM *aa; + /* Table of variables obtained from 'ctx' */ + BIGNUM *val[TABLESIZE]; + BN_MONT_CTX *mont = NULL; + + if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0 + || BN_get_flags(a, BN_FLG_CONSTTIME) != 0 + || BN_get_flags(m, BN_FLG_CONSTTIME) != 0) + return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, in_mont); + + bn_check_top(a); + bn_check_top(p); + bn_check_top(m); + + if (!BN_is_odd(m)) { + BNerr(BN_F_BN_MOD_EXP_MONT, BN_R_CALLED_WITH_EVEN_MODULUS); + return 0; + } + + bits = BN_num_bits(p); + + if (bits == 0) { + /* x**0 mod 1 is still zero. */ + if (BN_is_one(m)) { + ret = 1; + BN_zero(rr); + } else + ret = BN_one(rr); + + return ret; + } + + BN_CTX_start(ctx); + d = BN_CTX_get(ctx); + r = BN_CTX_get(ctx); + val[0] = BN_CTX_get(ctx); + + if (!d || !r || !val[0]) + goto err; + + /* + * If this is not done, things will break in the montgomery part + */ + + if (in_mont != NULL) + mont = in_mont; + else { + mont = BN_MONT_CTX_new(); + if (mont == NULL) + goto err; + + if (!BN_MONT_CTX_set(mont, m, ctx)) + goto err; + } + + if (a->neg || BN_ucmp(a, m) >= 0) { + if (!BN_nnmod(val[0], a, m, ctx)) + goto err; + + aa = val[0]; + } else + aa = a; + + if (BN_is_zero(aa)) { + BN_zero(rr); + ret = 1; + goto err; + } + + if (!BN_to_montgomery(val[0], aa, mont, ctx)) + goto err; /* 1 */ + + window = BN_window_bits_for_exponent_size(bits); + + if (window > 1) { + if (!BN_mod_mul_montgomery(d, val[0], val[0], mont, ctx)) + goto err; /* 2 */ + + j = 1 << (window - 1); + + for (i = 1; i < j; i++) { + val[i] = BN_CTX_get(ctx); + if ((val[i] == NULL) || + !BN_mod_mul_montgomery(val[i], val[i - 1], d, mont, ctx)) + goto err; + } + } + + start = 1; /* This is used to avoid multiplication etc when there is only the value '1' in the buffer. */ + wvalue = 0; /* The 'value' of the window */ + wstart = bits - 1; /* The top bit of the window */ + wend = 0; /* The bottom bit of the window */ + j = m->top; /* borrow j */ + + if (m->d[j - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) { + if (bn_wexpand(r, j) == NULL) + goto err; + + /* 2^(top*BN_BITS2) - m */ + r->d[0] = (0 - m->d[0]) & BN_MASK2; + + for (i = 1; i < j; i++) + r->d[i] = (~m->d[i]) & BN_MASK2; + + r->top = j; + /* + * Upper words will be zero if the corresponding words of 'm' were + * 0xfff[...], so decrement r->top accordingly. + */ + bn_correct_top(r); + } else + if (!BN_to_montgomery(r, BN_value_one(), mont, ctx)) + goto err; + + for (;;) { + if (BN_is_bit_set(p, wstart) == 0) { + if (!start) { + if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) + goto err; + } + + if (wstart == 0) + break; + + wstart--; + continue; + } + + /* + * We now have wstart on a 'set' bit, we now need to work out how bit + * a window to do. To do this we need to scan forward until the last + * set bit before the end of the window + */ + j = wstart; + wvalue = 1; + wend = 0; + + for (i = 1; i < window; i++) { + if (wstart - i < 0) + break; + + if (BN_is_bit_set(p, wstart - i)) { + wvalue <<= (i - wend); + wvalue |= 1; + wend = i; + } + } + + /* wend is the size of the current window */ + j = wend + 1; + + /* add the 'bytes above' */ + if (!start) + for (i = 0; i < j; i++) { + if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) + goto err; + } + + /* wvalue will be an odd number < 2^window */ + if (!BN_mod_mul_montgomery(r, r, val[wvalue >> 1], mont, ctx)) + goto err; + + /* move the 'window' down further */ + wstart -= wend + 1; + wvalue = 0; + start = 0; + + if (wstart < 0) + break; + } + +#if defined(SPARC_T4_MONT) + + if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) { + j = mont->N.top; /* borrow j */ + val[0]->d[0] = 1; /* borrow val[0] */ + + for (i = 1; i < j; i++) + val[0]->d[i] = 0; + + val[0]->top = j; + + if (!BN_mod_mul_montgomery(rr, r, val[0], mont, ctx)) + goto err; + } else +#endif + if (!BN_from_montgomery(rr, r, mont, ctx)) + goto err; + + ret = 1; +err: + + if (in_mont == NULL) + BN_MONT_CTX_free(mont); + + BN_CTX_end(ctx); + bn_check_top(rr); + return ret; +} + +#if defined(SPARC_T4_MONT) +static BN_ULONG bn_get_bits(const BIGNUM *a, int bitpos) +{ + BN_ULONG ret = 0; + int wordpos; + wordpos = bitpos / BN_BITS2; + bitpos %= BN_BITS2; + + if (wordpos >= 0 && wordpos < a->top) { + ret = a->d[wordpos] & BN_MASK2; + + if (bitpos) { + ret >>= bitpos; + + if (++wordpos < a->top) + ret |= a->d[wordpos] << (BN_BITS2 - bitpos); + } + } + + return ret & BN_MASK2; +} +#endif + +/* + * BN_mod_exp_mont_consttime() stores the precomputed powers in a specific + * layout so that accessing any of these table values shows the same access + * pattern as far as cache lines are concerned. The following functions are + * used to transfer a BIGNUM from/to that table. + */ + +static int MOD_EXP_CTIME_COPY_TO_PREBUF(const BIGNUM *b, int top, + unsigned char *buf, int idx, + int window) +{ + int i, j; + int width = 1 << window; + BN_ULONG *table = (BN_ULONG *)buf; + + if (top > b->top) + top = b->top; /* this works because 'buf' is explicitly zeroed */ + + for (i = 0, j = idx; i < top; i++, j += width) + table[j] = b->d[i]; + + return 1; +} + +static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top, + unsigned char *buf, int idx, + int window) +{ + int i, j; + int width = 1 << window; + /* + * We declare table 'volatile' in order to discourage compiler + * from reordering loads from the table. Concern is that if + * reordered in specific manner loads might give away the + * information we are trying to conceal. Some would argue that + * compiler can reorder them anyway, but it can as well be + * argued that doing so would be violation of standard... + */ + volatile BN_ULONG *table = (volatile BN_ULONG *)buf; + + if (bn_wexpand(b, top) == NULL) + return 0; + + if (window <= 3) { + for (i = 0; i < top; i++, table += width) { + BN_ULONG acc = 0; + + for (j = 0; j < width; j++) { + acc |= table[j] & + ((BN_ULONG)0 - (constant_time_eq_int(j, idx) & 1)); + } + + b->d[i] = acc; + } + } else { + int xstride = 1 << (window - 2); + BN_ULONG y0, y1, y2, y3; + i = idx >> (window - 2); /* equivalent of idx / xstride */ + idx &= xstride - 1; /* equivalent of idx % xstride */ + y0 = (BN_ULONG)0 - (constant_time_eq_int(i, 0) & 1); + y1 = (BN_ULONG)0 - (constant_time_eq_int(i, 1) & 1); + y2 = (BN_ULONG)0 - (constant_time_eq_int(i, 2) & 1); + y3 = (BN_ULONG)0 - (constant_time_eq_int(i, 3) & 1); + + for (i = 0; i < top; i++, table += width) { + BN_ULONG acc = 0; + + for (j = 0; j < xstride; j++) { + acc |= ((table[j + 0 * xstride] & y0) | + (table[j + 1 * xstride] & y1) | + (table[j + 2 * xstride] & y2) | + (table[j + 3 * xstride] & y3)) + & ((BN_ULONG)0 - (constant_time_eq_int(j, idx) & 1)); + } + + b->d[i] = acc; + } + } + + b->top = top; + bn_correct_top(b); + return 1; +} + +/* + * Given a pointer value, compute the next address that is a cache line + * multiple. + */ +#define MOD_EXP_CTIME_ALIGN(x_) \ + ((unsigned char *)(x_) + (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - (((size_t)(x_)) & (MOD_EXP_CTIME_MIN_CACHE_LINE_MASK)))) + +/* + * This variant of BN_mod_exp_mont() uses fixed windows and the special + * precomputation memory layout to limit data-dependency to a minimum to + * protect secret exponents (cf. the hyper-threading timing attacks pointed + * out by Colin Percival, + * http://www.daemonology.net/hyperthreading-considered-harmful/) + */ +int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *in_mont) +{ + int i, bits, ret = 0, window, wvalue; + int top; + BN_MONT_CTX *mont = NULL; + int numPowers; + unsigned char *powerbufFree = NULL; + int powerbufLen = 0; + unsigned char *powerbuf = NULL; + BIGNUM tmp, am; +#if defined(SPARC_T4_MONT) + unsigned int t4 = 0; +#endif + bn_check_top(a); + bn_check_top(p); + bn_check_top(m); + + if (!BN_is_odd(m)) { + BNerr(BN_F_BN_MOD_EXP_MONT_CONSTTIME, BN_R_CALLED_WITH_EVEN_MODULUS); + return 0; + } + + top = m->top; + bits = BN_num_bits(p); + + if (bits == 0) { + /* x**0 mod 1 is still zero. */ + if (BN_is_one(m)) { + ret = 1; + BN_zero(rr); + } else + ret = BN_one(rr); + + return ret; + } + + BN_CTX_start(ctx); + + /* + * Allocate a montgomery context if it was not supplied by the caller. If + * this is not done, things will break in the montgomery part. + */ + if (in_mont != NULL) + mont = in_mont; + else { + mont = BN_MONT_CTX_new(); + if (mont == NULL) + goto err; + + if (!BN_MONT_CTX_set(mont, m, ctx)) + goto err; + } + +#ifdef RSAZ_ENABLED + + /* + * If the size of the operands allow it, perform the optimized + * RSAZ exponentiation. For further information see + * crypto/bn/rsaz_exp.c and accompanying assembly modules. + */ + if ((16 == a->top) && (16 == p->top) && (BN_num_bits(m) == 1024) + && rsaz_avx2_eligible()) { + if (NULL == bn_wexpand(rr, 16)) + goto err; + + RSAZ_1024_mod_exp_avx2(rr->d, a->d, p->d, m->d, mont->RR.d, + mont->n0[0]); + rr->top = 16; + rr->neg = 0; + bn_correct_top(rr); + ret = 1; + goto err; + } else if ((8 == a->top) && (8 == p->top) && (BN_num_bits(m) == 512)) { + if (NULL == bn_wexpand(rr, 8)) + goto err; + + RSAZ_512_mod_exp(rr->d, a->d, p->d, m->d, mont->n0[0], mont->RR.d); + rr->top = 8; + rr->neg = 0; + bn_correct_top(rr); + ret = 1; + goto err; + } + +#endif + /* Get the window size to use with size of p. */ + window = BN_window_bits_for_ctime_exponent_size(bits); +#if defined(SPARC_T4_MONT) + + if (window >= 5 && (top & 15) == 0 && top <= 64 && + (OPENSSL_sparcv9cap_P[1] & (CFR_MONTMUL | CFR_MONTSQR)) == + (CFR_MONTMUL | CFR_MONTSQR) && (OPENSSL_sparcv9cap_P[0])) { + t4 = OPENSSL_sparcv9cap_P[0]; + window = 5; + } else +#endif +#if defined(OPENSSL_BN_ASM_MONT5) + if (window >= 5) { + window = 5; /* ~5% improvement for RSA2048 sign, and even for RSA4096 */ + /* reserve space for mont->N.d[] copy */ + powerbufLen += top * sizeof(mont->N.d[0]); + } + +#endif + (void)0; + /* + * Allocate a buffer large enough to hold all of the pre-computed powers + * of am, am itself and tmp. + */ + numPowers = 1 << window; + powerbufLen += sizeof(m->d[0]) * (top * numPowers + + ((2 * top) > + numPowers ? (2 * top) : numPowers)); +#ifdef alloca + + if (powerbufLen < 3072) + powerbufFree = + alloca(powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH); + else +#endif + os_alloc_mem(NULL, (UCHAR **) &powerbufFree, powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH); + + if (powerbufFree == NULL) + goto err; + + powerbuf = MOD_EXP_CTIME_ALIGN(powerbufFree); + memset(powerbuf, 0, powerbufLen); +#ifdef alloca + + if (powerbufLen < 3072) + powerbufFree = NULL; + +#endif + /* lay down tmp and am right after powers table */ + tmp.d = (BN_ULONG *)(powerbuf + sizeof(m->d[0]) * top * numPowers); + am.d = tmp.d + top; + tmp.top = am.top = 0; + tmp.dmax = am.dmax = top; + tmp.neg = am.neg = 0; + tmp.flags = am.flags = BN_FLG_STATIC_DATA; + /* prepare a^0 in Montgomery domain */ + + if (m->d[top - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) { + /* 2^(top*BN_BITS2) - m */ + tmp.d[0] = (0 - m->d[0]) & BN_MASK2; + + for (i = 1; i < top; i++) + tmp.d[i] = (~m->d[i]) & BN_MASK2; + + tmp.top = top; + } else + if (!BN_to_montgomery(&tmp, BN_value_one(), mont, ctx)) + goto err; + + /* prepare a^1 in Montgomery domain */ + if (a->neg || BN_ucmp(a, m) >= 0) { + if (!BN_mod(&am, a, m, ctx)) + goto err; + + if (!BN_to_montgomery(&am, &am, mont, ctx)) + goto err; + } else if (!BN_to_montgomery(&am, a, mont, ctx)) + goto err; + +#if defined(SPARC_T4_MONT) + + if (t4) { + typedef int (*bn_pwr5_mont_f) (BN_ULONG *tp, const BN_ULONG *np, + const BN_ULONG *n0, const void *table, + int power, int bits); + int bn_pwr5_mont_t4_8(BN_ULONG *tp, const BN_ULONG *np, + const BN_ULONG *n0, const void *table, + int power, int bits); + int bn_pwr5_mont_t4_16(BN_ULONG *tp, const BN_ULONG *np, + const BN_ULONG *n0, const void *table, + int power, int bits); + int bn_pwr5_mont_t4_24(BN_ULONG *tp, const BN_ULONG *np, + const BN_ULONG *n0, const void *table, + int power, int bits); + int bn_pwr5_mont_t4_32(BN_ULONG *tp, const BN_ULONG *np, + const BN_ULONG *n0, const void *table, + int power, int bits); + static const bn_pwr5_mont_f pwr5_funcs[4] = { + bn_pwr5_mont_t4_8, bn_pwr5_mont_t4_16, + bn_pwr5_mont_t4_24, bn_pwr5_mont_t4_32 + }; + bn_pwr5_mont_f pwr5_worker = pwr5_funcs[top / 16 - 1]; + typedef int (*bn_mul_mont_f) (BN_ULONG *rp, const BN_ULONG *ap, + const void *bp, const BN_ULONG *np, + const BN_ULONG *n0); + int bn_mul_mont_t4_8(BN_ULONG *rp, const BN_ULONG *ap, const void *bp, + const BN_ULONG *np, const BN_ULONG *n0); + int bn_mul_mont_t4_16(BN_ULONG *rp, const BN_ULONG *ap, + const void *bp, const BN_ULONG *np, + const BN_ULONG *n0); + int bn_mul_mont_t4_24(BN_ULONG *rp, const BN_ULONG *ap, + const void *bp, const BN_ULONG *np, + const BN_ULONG *n0); + int bn_mul_mont_t4_32(BN_ULONG *rp, const BN_ULONG *ap, + const void *bp, const BN_ULONG *np, + const BN_ULONG *n0); + static const bn_mul_mont_f mul_funcs[4] = { + bn_mul_mont_t4_8, bn_mul_mont_t4_16, + bn_mul_mont_t4_24, bn_mul_mont_t4_32 + }; + bn_mul_mont_f mul_worker = mul_funcs[top / 16 - 1]; + void bn_mul_mont_vis3(BN_ULONG *rp, const BN_ULONG *ap, + const void *bp, const BN_ULONG *np, + const BN_ULONG *n0, int num); + void bn_mul_mont_t4(BN_ULONG *rp, const BN_ULONG *ap, + const void *bp, const BN_ULONG *np, + const BN_ULONG *n0, int num); + void bn_mul_mont_gather5_t4(BN_ULONG *rp, const BN_ULONG *ap, + const void *table, const BN_ULONG *np, + const BN_ULONG *n0, int num, int power); + void bn_flip_n_scatter5_t4(const BN_ULONG *inp, size_t num, + void *table, size_t power); + void bn_gather5_t4(BN_ULONG *out, size_t num, + void *table, size_t power); + void bn_flip_t4(BN_ULONG *dst, BN_ULONG *src, size_t num); + BN_ULONG *np = mont->N.d, *n0 = mont->n0; + int stride = 5 * (6 - (top / 16 - 1)); /* multiple of 5, but less than 32 */ + + /* + * BN_to_montgomery can contaminate words above .top [in + * BN_DEBUG[_DEBUG] build]... + */ + for (i = am.top; i < top; i++) + am.d[i] = 0; + + for (i = tmp.top; i < top; i++) + tmp.d[i] = 0; + + bn_flip_n_scatter5_t4(tmp.d, top, powerbuf, 0); + bn_flip_n_scatter5_t4(am.d, top, powerbuf, 1); + + if (!(*mul_worker) (tmp.d, am.d, am.d, np, n0) && + !(*mul_worker) (tmp.d, am.d, am.d, np, n0)) + bn_mul_mont_vis3(tmp.d, am.d, am.d, np, n0, top); + + bn_flip_n_scatter5_t4(tmp.d, top, powerbuf, 2); + + for (i = 3; i < 32; i++) { + /* Calculate a^i = a^(i-1) * a */ + if (!(*mul_worker) (tmp.d, tmp.d, am.d, np, n0) && + !(*mul_worker) (tmp.d, tmp.d, am.d, np, n0)) + bn_mul_mont_vis3(tmp.d, tmp.d, am.d, np, n0, top); + + bn_flip_n_scatter5_t4(tmp.d, top, powerbuf, i); + } + + /* switch to 64-bit domain */ + np = alloca(top * sizeof(BN_ULONG)); + top /= 2; + bn_flip_t4(np, mont->N.d, top); + bits--; + + for (wvalue = 0, i = bits % 5; i >= 0; i--, bits--) + wvalue = (wvalue << 1) + BN_is_bit_set(p, bits); + + bn_gather5_t4(tmp.d, top, powerbuf, wvalue); + + /* + * Scan the exponent one window at a time starting from the most + * significant bits. + */ + while (bits >= 0) { + if (bits < stride) + stride = bits + 1; + + bits -= stride; + wvalue = bn_get_bits(p, bits + 1); + + if ((*pwr5_worker) (tmp.d, np, n0, powerbuf, wvalue, stride)) + continue; + + /* retry once and fall back */ + if ((*pwr5_worker) (tmp.d, np, n0, powerbuf, wvalue, stride)) + continue; + + bits += stride - 5; + wvalue >>= stride - 5; + wvalue &= 31; + bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_t4(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_gather5_t4(tmp.d, tmp.d, powerbuf, np, n0, top, + wvalue); + } + + bn_flip_t4(tmp.d, tmp.d, top); + top *= 2; + /* back to 32-bit domain */ + tmp.top = top; + bn_correct_top(&tmp); + memset(np, 0, top * sizeof(BN_ULONG)); + } else +#endif +#if defined(OPENSSL_BN_ASM_MONT5) + if (window == 5 && top > 1) { + /* + * This optimization uses ideas from http://eprint.iacr.org/2011/239, + * specifically optimization of cache-timing attack countermeasures + * and pre-computation optimization. + */ + /* + * Dedicated window==4 case improves 512-bit RSA sign by ~15%, but as + * 512-bit RSA is hardly relevant, we omit it to spare size... + */ + void bn_mul_mont_gather5(BN_ULONG *rp, const BN_ULONG *ap, + const void *table, const BN_ULONG *np, + const BN_ULONG *n0, int num, int power); + void bn_scatter5(const BN_ULONG *inp, size_t num, + void *table, size_t power); + void bn_gather5(BN_ULONG *out, size_t num, void *table, size_t power); + void bn_power5(BN_ULONG *rp, const BN_ULONG *ap, + const void *table, const BN_ULONG *np, + const BN_ULONG *n0, int num, int power); + int bn_get_bits5(const BN_ULONG *ap, int off); + int bn_from_montgomery(BN_ULONG *rp, const BN_ULONG *ap, + const BN_ULONG *not_used, const BN_ULONG *np, + const BN_ULONG *n0, int num); + BN_ULONG *n0 = mont->n0, *np; + + /* + * BN_to_montgomery can contaminate words above .top [in + * BN_DEBUG[_DEBUG] build]... + */ + for (i = am.top; i < top; i++) + am.d[i] = 0; + + for (i = tmp.top; i < top; i++) + tmp.d[i] = 0; + + /* + * copy mont->N.d[] to improve cache locality + */ + for (np = am.d + top, i = 0; i < top; i++) + np[i] = mont->N.d[i]; + + bn_scatter5(tmp.d, top, powerbuf, 0); + bn_scatter5(am.d, am.top, powerbuf, 1); + bn_mul_mont(tmp.d, am.d, am.d, np, n0, top); + bn_scatter5(tmp.d, top, powerbuf, 2); +# if 0 + + for (i = 3; i < 32; i++) { + /* Calculate a^i = a^(i-1) * a */ + bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1); + bn_scatter5(tmp.d, top, powerbuf, i); + } + +# else + + /* same as above, but uses squaring for 1/2 of operations */ + for (i = 4; i < 32; i *= 2) { + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_scatter5(tmp.d, top, powerbuf, i); + } + + for (i = 3; i < 8; i += 2) { + int j; + bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1); + bn_scatter5(tmp.d, top, powerbuf, i); + + for (j = 2 * i; j < 32; j *= 2) { + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_scatter5(tmp.d, top, powerbuf, j); + } + } + + for (; i < 16; i += 2) { + bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1); + bn_scatter5(tmp.d, top, powerbuf, i); + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_scatter5(tmp.d, top, powerbuf, 2 * i); + } + + for (; i < 32; i += 2) { + bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1); + bn_scatter5(tmp.d, top, powerbuf, i); + } + +# endif + bits--; + + for (wvalue = 0, i = bits % 5; i >= 0; i--, bits--) + wvalue = (wvalue << 1) + BN_is_bit_set(p, bits); + + bn_gather5(tmp.d, top, powerbuf, wvalue); + + /* + * Scan the exponent one window at a time starting from the most + * significant bits. + */ + if (top & 7) + while (bits >= 0) { + for (wvalue = 0, i = 0; i < 5; i++, bits--) + wvalue = (wvalue << 1) + BN_is_bit_set(p, bits); + + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top); + bn_mul_mont_gather5(tmp.d, tmp.d, powerbuf, np, n0, top, + wvalue); + } + else { + while (bits >= 0) { + wvalue = bn_get_bits5(p->d, bits - 4); + bits -= 5; + bn_power5(tmp.d, tmp.d, powerbuf, np, n0, top, wvalue); + } + } + + ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np, n0, top); + tmp.top = top; + bn_correct_top(&tmp); + + if (ret) { + if (!BN_copy(rr, &tmp)) + ret = 0; + + goto err; /* non-zero ret means it's not error */ + } + } else +#endif + { + if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 0, window)) + goto err; + + if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&am, top, powerbuf, 1, window)) + goto err; + + /* + * If the window size is greater than 1, then calculate + * val[i=2..2^winsize-1]. Powers are computed as a*a^(i-1) (even + * powers could instead be computed as (a^(i/2))^2 to use the slight + * performance advantage of sqr over mul). + */ + if (window > 1) { + if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx)) + goto err; + + if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 2, + window)) + goto err; + + for (i = 3; i < numPowers; i++) { + /* Calculate a^i = a^(i-1) * a */ + if (!BN_mod_mul_montgomery(&tmp, &am, &tmp, mont, ctx)) + goto err; + + if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, i, + window)) + goto err; + } + } + + bits--; + + for (wvalue = 0, i = bits % window; i >= 0; i--, bits--) + wvalue = (wvalue << 1) + BN_is_bit_set(p, bits); + + if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(&tmp, top, powerbuf, wvalue, + window)) + goto err; + + /* + * Scan the exponent one window at a time starting from the most + * significant bits. + */ + while (bits >= 0) { + wvalue = 0; /* The 'value' of the window */ + + /* Scan the window, squaring the result as we go */ + for (i = 0; i < window; i++, bits--) { + if (!BN_mod_mul_montgomery(&tmp, &tmp, &tmp, mont, ctx)) + goto err; + + wvalue = (wvalue << 1) + BN_is_bit_set(p, bits); + } + + /* + * Fetch the appropriate pre-computed value from the pre-buf + */ + if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(&am, top, powerbuf, wvalue, + window)) + goto err; + + /* Multiply the result into the intermediate result */ + if (!BN_mod_mul_montgomery(&tmp, &tmp, &am, mont, ctx)) + goto err; + } + } + + /* Convert the final result from montgomery to standard format */ +#if defined(SPARC_T4_MONT) + + if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) { + am.d[0] = 1; /* borrow am */ + + for (i = 1; i < top; i++) + am.d[i] = 0; + + if (!BN_mod_mul_montgomery(rr, &tmp, &am, mont, ctx)) + goto err; + } else +#endif + if (!BN_from_montgomery(rr, &tmp, mont, ctx)) + goto err; + + ret = 1; +err: + + if (in_mont == NULL) + BN_MONT_CTX_free(mont); + + if (powerbuf != NULL) { + memset(powerbuf, 0, powerbufLen); + os_free_mem(NULL, powerbufFree); + } + + BN_CTX_end(ctx); + return ret; +} + +int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont) +{ + BN_MONT_CTX *mont = NULL; + int b, bits, ret = 0; + int r_is_one; + BN_ULONG w, next_w; + BIGNUM *d, *r, *t; + BIGNUM *swap_tmp; +#define BN_MOD_MUL_WORD(r, w, m) \ + (BN_mul_word(r, (w)) && \ + (/* BN_ucmp(r, (m)) < 0 ? 1 :*/ \ + (BN_mod(t, r, m, ctx) && (swap_tmp = r, r = t, t = swap_tmp, 1)))) + /* + * BN_MOD_MUL_WORD is only used with 'w' large, so the BN_ucmp test is + * probably more overhead than always using BN_mod (which uses BN_copy if + * a similar test returns true). + */ + /* + * We can use BN_mod and do not need BN_nnmod because our accumulator is + * never negative (the result of BN_mod does not depend on the sign of + * the modulus). + */ +#define BN_TO_MONTGOMERY_WORD(r, w, mont) \ + (BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx)) + + if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0 + || BN_get_flags(m, BN_FLG_CONSTTIME) != 0) { + /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ + BNerr(BN_F_BN_MOD_EXP_MONT_WORD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + bn_check_top(p); + bn_check_top(m); + + if (!BN_is_odd(m)) { + BNerr(BN_F_BN_MOD_EXP_MONT_WORD, BN_R_CALLED_WITH_EVEN_MODULUS); + return 0; + } + + if (m->top == 1) + a %= m->d[0]; /* make sure that 'a' is reduced */ + + bits = BN_num_bits(p); + + if (bits == 0) { + /* x**0 mod 1 is still zero. */ + if (BN_is_one(m)) { + ret = 1; + BN_zero(rr); + } else + ret = BN_one(rr); + + return ret; + } + + if (a == 0) { + BN_zero(rr); + ret = 1; + return ret; + } + + BN_CTX_start(ctx); + d = BN_CTX_get(ctx); + r = BN_CTX_get(ctx); + t = BN_CTX_get(ctx); + + if (d == NULL || r == NULL || t == NULL) + goto err; + + if (in_mont != NULL) + mont = in_mont; + else { + mont = BN_MONT_CTX_new(); + if (mont == NULL) + goto err; + + if (!BN_MONT_CTX_set(mont, m, ctx)) + goto err; + } + + r_is_one = 1; /* except for Montgomery factor */ + /* bits-1 >= 0 */ + /* The result is accumulated in the product r*w. */ + w = a; /* bit 'bits-1' of 'p' is always set */ + + for (b = bits - 2; b >= 0; b--) { + /* First, square r*w. */ + next_w = w * w; + + if ((next_w / w) != w) { /* overflow */ + if (r_is_one) { + if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) + goto err; + + r_is_one = 0; + } else { + if (!BN_MOD_MUL_WORD(r, w, m)) + goto err; + } + + next_w = 1; + } + + w = next_w; + + if (!r_is_one) { + if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) + goto err; + } + + /* Second, multiply r*w by 'a' if exponent bit is set. */ + if (BN_is_bit_set(p, b)) { + next_w = w * a; + + if ((next_w / a) != w) { /* overflow */ + if (r_is_one) { + if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) + goto err; + + r_is_one = 0; + } else { + if (!BN_MOD_MUL_WORD(r, w, m)) + goto err; + } + + next_w = a; + } + + w = next_w; + } + } + + /* Finally, set r:=r*w. */ + if (w != 1) { + if (r_is_one) { + if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) + goto err; + + r_is_one = 0; + } else { + if (!BN_MOD_MUL_WORD(r, w, m)) + goto err; + } + } + + if (r_is_one) { /* can happen only if a == 1 */ + if (!BN_one(rr)) + goto err; + } else { + if (!BN_from_montgomery(rr, r, mont, ctx)) + goto err; + } + + ret = 1; +err: + + if (in_mont == NULL) + BN_MONT_CTX_free(mont); + + BN_CTX_end(ctx); + bn_check_top(rr); + return ret; +} + +/* The old fallback, simple version :-) */ +int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx) +{ + int i, j, bits, ret = 0, wstart, wend, window, wvalue; + int start = 1; + BIGNUM *d; + /* Table of variables obtained from 'ctx' */ + BIGNUM *val[TABLESIZE]; + + if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0 + || BN_get_flags(a, BN_FLG_CONSTTIME) != 0 + || BN_get_flags(m, BN_FLG_CONSTTIME) != 0) { + /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */ + BNerr(BN_F_BN_MOD_EXP_SIMPLE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return 0; + } + + bits = BN_num_bits(p); + + if (bits == 0) { + /* x**0 mod 1 is still zero. */ + if (BN_is_one(m)) { + ret = 1; + BN_zero(r); + } else + ret = BN_one(r); + + return ret; + } + + BN_CTX_start(ctx); + d = BN_CTX_get(ctx); + val[0] = BN_CTX_get(ctx); + + if (!d || !val[0]) + goto err; + + if (!BN_nnmod(val[0], a, m, ctx)) + goto err; /* 1 */ + + if (BN_is_zero(val[0])) { + BN_zero(r); + ret = 1; + goto err; + } + + window = BN_window_bits_for_exponent_size(bits); + + if (window > 1) { + if (!BN_mod_mul(d, val[0], val[0], m, ctx)) + goto err; /* 2 */ + + j = 1 << (window - 1); + + for (i = 1; i < j; i++) { + val[i] = BN_CTX_get(ctx); + if ((val[i] == NULL) || + !BN_mod_mul(val[i], val[i - 1], d, m, ctx)) + goto err; + } + } + + start = 1; /* This is used to avoid multiplication etc when there is only the value '1' in the buffer. */ + wvalue = 0; /* The 'value' of the window */ + wstart = bits - 1; /* The top bit of the window */ + wend = 0; /* The bottom bit of the window */ + + if (!BN_one(r)) + goto err; + + for (;;) { + if (BN_is_bit_set(p, wstart) == 0) { + if (!start) + if (!BN_mod_mul(r, r, r, m, ctx)) + goto err; + + if (wstart == 0) + break; + + wstart--; + continue; + } + + /* + * We now have wstart on a 'set' bit, we now need to work out how bit + * a window to do. To do this we need to scan forward until the last + * set bit before the end of the window + */ + j = wstart; + wvalue = 1; + wend = 0; + + for (i = 1; i < window; i++) { + if (wstart - i < 0) + break; + + if (BN_is_bit_set(p, wstart - i)) { + wvalue <<= (i - wend); + wvalue |= 1; + wend = i; + } + } + + /* wend is the size of the current window */ + j = wend + 1; + + /* add the 'bytes above' */ + if (!start) + for (i = 0; i < j; i++) { + if (!BN_mod_mul(r, r, r, m, ctx)) + goto err; + } + + /* wvalue will be an odd number < 2^window */ + if (!BN_mod_mul(r, r, val[wvalue >> 1], m, ctx)) + goto err; + + /* move the 'window' down further */ + wstart -= wend + 1; + wvalue = 0; + start = 0; + + if (wstart < 0) + break; + } + + ret = 1; +err: + BN_CTX_end(ctx); + bn_check_top(r); + return ret; +} + +void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb) +{ + BN_ULONG *rr; + + if (na < nb) { + int itmp; + BN_ULONG *ltmp; + itmp = na; + na = nb; + nb = itmp; + ltmp = a; + a = b; + b = ltmp; + } + + rr = &(r[na]); + + if (nb <= 0) { + (void)bn_mul_words(r, a, na, 0); + return; + } else + rr[0] = bn_mul_words(r, a, na, b[0]); + + for (;;) { + if (--nb <= 0) + return; + + rr[1] = bn_mul_add_words(&(r[1]), a, na, b[1]); + + if (--nb <= 0) + return; + + rr[2] = bn_mul_add_words(&(r[2]), a, na, b[2]); + + if (--nb <= 0) + return; + + rr[3] = bn_mul_add_words(&(r[3]), a, na, b[3]); + + if (--nb <= 0) + return; + + rr[4] = bn_mul_add_words(&(r[4]), a, na, b[4]); + rr += 4; + r += 4; + b += 4; + } +} + + + +int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +{ + int ret = 0; + int top, al, bl; + BIGNUM *rr; +#if defined(BN_MUL_COMBA) || defined(BN_RECURSION) + int i; +#endif +#ifdef BN_RECURSION + BIGNUM *t = NULL; + int j = 0, k; +#endif + bn_check_top(a); + bn_check_top(b); + bn_check_top(r); + al = a->top; + bl = b->top; + + if ((al == 0) || (bl == 0)) { + BN_zero(r); + return 1; + } + + top = al + bl; + BN_CTX_start(ctx); + + if ((r == a) || (r == b)) { + rr = BN_CTX_get(ctx); + if (rr == NULL) + goto err; + } else + rr = r; + +#if defined(BN_MUL_COMBA) || defined(BN_RECURSION) + i = al - bl; +#endif +#ifdef BN_MUL_COMBA + + if (i == 0) { +# if 0 + + if (al == 4) { + if (bn_wexpand(rr, 8) == NULL) + goto err; + + rr->top = 8; + bn_mul_comba4(rr->d, a->d, b->d); + goto end; + } + +# endif + + if (al == 8) { + if (bn_wexpand(rr, 16) == NULL) + goto err; + + rr->top = 16; + bn_mul_comba8(rr->d, a->d, b->d); + goto end; + } + } + +#endif /* BN_MUL_COMBA */ +#ifdef BN_RECURSION + + if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) { + if (i >= -1 && i <= 1) { + /* + * Find out the power of two lower or equal to the longest of the + * two numbers + */ + if (i >= 0) + j = BN_num_bits_word((BN_ULONG)al); + + if (i == -1) + j = BN_num_bits_word((BN_ULONG)bl); + + j = 1 << (j - 1); + assert(j <= al || j <= bl); + k = j + j; + t = BN_CTX_get(ctx); + + if (t == NULL) + goto err; + + if (al > j || bl > j) { + if (bn_wexpand(t, k * 4) == NULL) + goto err; + + if (bn_wexpand(rr, k * 4) == NULL) + goto err; + + bn_mul_part_recursive(rr->d, a->d, b->d, + j, al - j, bl - j, t->d); + } else { /* al <= j || bl <= j */ + if (bn_wexpand(t, k * 2) == NULL) + goto err; + + if (bn_wexpand(rr, k * 2) == NULL) + goto err; + + bn_mul_recursive(rr->d, a->d, b->d, j, al - j, bl - j, t->d); + } + + rr->top = top; + goto end; + } + } + +#endif /* BN_RECURSION */ + + if (bn_wexpand(rr, top) == NULL) + goto err; + + rr->top = top; + bn_mul_normal(rr->d, a->d, al, b->d, bl); +#if defined(BN_MUL_COMBA) || defined(BN_RECURSION) +end: +#endif + rr->neg = a->neg ^ b->neg; + bn_correct_top(rr); + + if (r != rr && BN_copy(r, rr) == NULL) + goto err; + + ret = 1; +err: + bn_check_top(r); + BN_CTX_end(ctx); + return ret; +} + +/* least significant word */ +#define BN_lsw(n) (((n)->top == 0) ? (BN_ULONG) 0 : (n)->d[0]) + +/* Returns -2 for errors because both -1 and 0 are valid results. */ +int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) +{ + int i; + int ret = -2; /* avoid 'uninitialized' warning */ + int err = 0; + BIGNUM *A, *B, *tmp; + /*- + * In 'tab', only odd-indexed entries are relevant: + * For any odd BIGNUM n, + * tab[BN_lsw(n) & 7] + * is $(-1)^{(n^2-1)/8}$ (using TeX notation). + * Note that the sign of n does not matter. + */ + static const int tab[8] = { 0, 1, 0, -1, 0, -1, 0, 1 }; + bn_check_top(a); + bn_check_top(b); + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + B = BN_CTX_get(ctx); + + if (B == NULL) + goto end; + + err = !BN_copy(A, a); + + if (err) + goto end; + + err = !BN_copy(B, b); + + if (err) + goto end; + + /* + * Kronecker symbol, implemented according to Henri Cohen, + * "A Course in Computational Algebraic Number Theory" + * (algorithm 1.4.10). + */ + + /* Cohen's step 1: */ + + if (BN_is_zero(B)) { + ret = BN_abs_is_word(A, 1); + goto end; + } + + /* Cohen's step 2: */ + + if (!BN_is_odd(A) && !BN_is_odd(B)) { + ret = 0; + goto end; + } + + /* now B is non-zero */ + i = 0; + + while (!BN_is_bit_set(B, i)) + i++; + + err = !BN_rshift(B, B, i); + + if (err) + goto end; + + if (i & 1) { + /* i is odd */ + /* (thus B was even, thus A must be odd!) */ + /* set 'ret' to $(-1)^{(A^2-1)/8}$ */ + ret = tab[BN_lsw(A) & 7]; + } else { + /* i is even */ + ret = 1; + } + + if (B->neg) { + B->neg = 0; + + if (A->neg) + ret = -ret; + } + + /* + * now B is positive and odd, so what remains to be done is to compute + * the Jacobi symbol (A/B) and multiply it by 'ret' + */ + + while (1) { + /* Cohen's step 3: */ + + /* B is positive and odd */ + if (BN_is_zero(A)) { + ret = BN_is_one(B) ? ret : 0; + goto end; + } + + /* now A is non-zero */ + i = 0; + + while (!BN_is_bit_set(A, i)) + i++; + + err = !BN_rshift(A, A, i); + + if (err) + goto end; + + if (i & 1) { + /* i is odd */ + /* multiply 'ret' by $(-1)^{(B^2-1)/8}$ */ + ret = ret * tab[BN_lsw(B) & 7]; + } + + /* Cohen's step 4: */ + /* multiply 'ret' by $(-1)^{(A-1)(B-1)/4}$ */ + if ((A->neg ? ~BN_lsw(A) : BN_lsw(A)) & BN_lsw(B) & 2) + ret = -ret; + + /* (A, B) := (B mod |A|, |A|) */ + err = !BN_nnmod(B, B, A, ctx); + + if (err) + goto end; + + tmp = A; + A = B; + B = tmp; + tmp->neg = 0; + } + +end: + BN_CTX_end(ctx); + + if (err) + return -2; + else + return ret; +} + +static UCHAR randombyte(void) +{ + ULONG i; + UCHAR R, Result; + static ULONG ShiftReg; + R = 0; + + if (ShiftReg == 0) + NdisGetSystemUpTime((ULONG *)&ShiftReg); + + for (i = 0; i < 8; i++) { + if (ShiftReg & 0x00000001) { + ShiftReg = ((ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000; + Result = 1; + } else { + ShiftReg = ShiftReg >> 1; + Result = 0; + } + + R = (R << 1) | Result; + } + + return R; +} + +static int bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom) +{ + unsigned char *buf = NULL; + int ret = 0, bit, bytes, mask; + time_t tim; + UINT32 i; + + if (bits == 0) { + if (top != BN_RAND_TOP_ANY || bottom != BN_RAND_BOTTOM_ANY) + goto toosmall; + + BN_zero(rnd); + return 1; + } + + if (bits < 0 || (bits == 1 && top > 0)) + goto toosmall; + + bytes = (bits + 7) / 8; + bit = (bits - 1) % 8; + mask = 0xff << (bit + 1); + os_alloc_mem(NULL, (UCHAR **) &buf, bytes); + + if (buf == NULL) { + BNerr(BN_F_BNRAND, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* make a random number and set the top and bottom bits */ + NdisGetSystemUpTime((ULONG *)(&tim)); + + for (i = 0; i < bytes; i++) + buf[i] = randombyte(); + + if (pseudorand == 2) { + /* + * generate patterns that are more likely to trigger BN library bugs + */ + int i; + unsigned char c; + + for (i = 0; i < bytes; i++) { + c = randombyte(); + + if (c >= 128 && i > 0) + buf[i] = buf[i - 1]; + else if (c < 42) + buf[i] = 0; + else if (c < 84) + buf[i] = 255; + } + } + + if (top >= 0) { + if (top) { + if (bit == 0) { + buf[0] = 1; + buf[1] |= 0x80; + } else + buf[0] |= (3 << (bit - 1)); + } else + buf[0] |= (1 << bit); + } + + buf[0] &= ~mask; + + if (bottom) /* set bottom bit if requested */ + buf[bytes - 1] |= 1; + + if (!BN_bin2bn(buf, bytes, rnd)) + goto err; + + ret = 1; +err: + os_free_mem(NULL, buf); + bn_check_top(rnd); + return ret; +toosmall: + BNerr(BN_F_BNRAND, BN_R_BITS_TOO_SMALL); + return 0; +} + +/* random number r: 0 <= r < range */ +static int bn_rand_range(int pseudo, BIGNUM *r, const BIGNUM *range) +{ + int (*bn_rand)(BIGNUM *, int, int, int) = pseudo ? BN_pseudo_rand : BN_rand; + int n; + int count = 100; + + if (range->neg || BN_is_zero(range)) + return 0; + + n = BN_num_bits(range); /* n > 0 */ + + /* BN_is_bit_set(range, n - 1) always holds */ + + if (n == 1) + BN_zero(r); + else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) { + /* + * range = 100..._2, so 3*range (= 11..._2) is exactly one bit longer + * than range + */ + do { + if (!bn_rand(r, n + 1, -1, 0)) + return 0; + /* + * If r < 3*range, use r := r MOD range (which is either r, r - + * range, or r - 2*range). Otherwise, iterate once more. Since + * 3*range = 11..._2, each iteration succeeds with probability >= + * .75. + */ + if (BN_cmp(r, range) >= 0) { + if (!BN_sub(r, r, range)) + return 0; + if (BN_cmp(r, range) >= 0) + if (!BN_sub(r, r, range)) + return 0; + } + + if (!--count) + return 0; + } while (BN_cmp(r, range) >= 0); + } else { + do { + /* range = 11..._2 or range = 101..._2 */ + if (!bn_rand(r, n, -1, 0)) + return 0; + + if (!--count) + return 0; + } while (BN_cmp(r, range) >= 0); + } + + bn_check_top(r); + return 1; +} + +int BN_rand(BIGNUM *rnd, int bits, int top, int bottom) +{ + return bnrand(0, rnd, bits, top, bottom); +} + +int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom) +{ + return bnrand(1, rnd, bits, top, bottom); +} + +int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom) +{ + return bnrand(2, rnd, bits, top, bottom); +} + +int BN_rand_range(BIGNUM *r, const BIGNUM *range) +{ + return bn_rand_range(0, r, range); +} + +BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) +/* + * Returns 'ret' such that ret^2 == a (mod p), using the Tonelli/Shanks + * algorithm (cf. Henri Cohen, "A Course in Algebraic Computational Number + * Theory", algorithm 1.5.1). 'p' must be prime! + */ +{ + BIGNUM *ret = in; + int err = 1; + int r; + BIGNUM *A, *b, *q, *t, *x, *y; + int e, i, j; + + if (!BN_is_odd(p) || BN_abs_is_word(p, 1)) { + if (BN_abs_is_word(p, 2)) { + if (ret == NULL) + ret = BN_new(); + + if (ret == NULL) + goto end; + + if (!BN_set_word(ret, BN_is_bit_set(a, 0))) { + if (ret != in) + BN_free(ret); + + return NULL; + } + + bn_check_top(ret); + return ret; + } + + BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); + return NULL; + } + + if (BN_is_zero(a) || BN_is_one(a)) { + if (ret == NULL) + ret = BN_new(); + + if (ret == NULL) + goto end; + + if (!BN_set_word(ret, BN_is_one(a))) { + if (ret != in) + BN_free(ret); + + return NULL; + } + + bn_check_top(ret); + return ret; + } + + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + b = BN_CTX_get(ctx); + q = BN_CTX_get(ctx); + t = BN_CTX_get(ctx); + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + + if (y == NULL) + goto end; + + if (ret == NULL) + ret = BN_new(); + + if (ret == NULL) + goto end; + + /* A = a mod p */ + if (!BN_nnmod(A, a, p, ctx)) + goto end; + + /* now write |p| - 1 as 2^e*q where q is odd */ + e = 1; + + while (!BN_is_bit_set(p, e)) + e++; + + /* we'll set q later (if needed) */ + + if (e == 1) { + /*- + * The easy case: (|p|-1)/2 is odd, so 2 has an inverse + * modulo (|p|-1)/2, and square roots can be computed + * directly by modular exponentiation. + * We have + * 2 * (|p|+1)/4 == 1 (mod (|p|-1)/2), + * so we can use exponent (|p|+1)/4, i.e. (|p|-3)/4 + 1. + */ + if (!BN_rshift(q, p, 2)) + goto end; + + q->neg = 0; + + if (!BN_add_word(q, 1)) + goto end; + + if (!BN_mod_exp(ret, A, q, p, ctx)) + goto end; + + err = 0; + goto vrfy; + } + + if (e == 2) { + /*- + * |p| == 5 (mod 8) + * + * In this case 2 is always a non-square since + * Legendre(2,p) = (-1)^((p^2-1)/8) for any odd prime. + * So if a really is a square, then 2*a is a non-square. + * Thus for + * b := (2*a)^((|p|-5)/8), + * i := (2*a)*b^2 + * we have + * i^2 = (2*a)^((1 + (|p|-5)/4)*2) + * = (2*a)^((p-1)/2) + * = -1; + * so if we set + * x := a*b*(i-1), + * then + * x^2 = a^2 * b^2 * (i^2 - 2*i + 1) + * = a^2 * b^2 * (-2*i) + * = a*(-i)*(2*a*b^2) + * = a*(-i)*i + * = a. + * + * (This is due to A.O.L. Atkin, + * , + * November 1992.) + */ + + /* t := 2*a */ + if (!BN_mod_lshift1_quick(t, A, p)) + goto end; + + /* b := (2*a)^((|p|-5)/8) */ + if (!BN_rshift(q, p, 3)) + goto end; + + q->neg = 0; + + if (!BN_mod_exp(b, t, q, p, ctx)) + goto end; + + /* y := b^2 */ + if (!BN_mod_sqr(y, b, p, ctx)) + goto end; + + /* t := (2*a)*b^2 - 1 */ + if (!BN_mod_mul(t, t, y, p, ctx)) + goto end; + + if (!BN_sub_word(t, 1)) + goto end; + + /* x = a*b*t */ + if (!BN_mod_mul(x, A, b, p, ctx)) + goto end; + + if (!BN_mod_mul(x, x, t, p, ctx)) + goto end; + + if (!BN_copy(ret, x)) + goto end; + + err = 0; + goto vrfy; + } + + /* + * e > 2, so we really have to use the Tonelli/Shanks algorithm. First, + * find some y that is not a square. + */ + if (!BN_copy(q, p)) + goto end; /* use 'q' as temp */ + + q->neg = 0; + i = 2; + + do { + /* + * For efficiency, try small numbers first; if this fails, try random + * numbers. + */ + if (i < 22) { + if (!BN_set_word(y, i)) + goto end; + } else { + if (!BN_pseudo_rand(y, BN_num_bits(p), 0, 0)) + goto end; + + if (BN_ucmp(y, p) >= 0) { + if (!(p->neg ? BN_add : BN_sub) (y, y, p)) + goto end; + } + + /* now 0 <= y < |p| */ + if (BN_is_zero(y)) + if (!BN_set_word(y, i)) + goto end; + } + + r = BN_kronecker(y, q, ctx); /* here 'q' is |p| */ + + if (r < -1) + goto end; + + if (r == 0) { + /* m divides p */ + BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); + goto end; + } + } while (r == 1 && ++i < 82); + + if (r != -1) { + /* + * Many rounds and still no non-square -- this is more likely a bug + * than just bad luck. Even if p is not prime, we should have found + * some y such that r == -1. + */ + BNerr(BN_F_BN_MOD_SQRT, BN_R_TOO_MANY_ITERATIONS); + goto end; + } + + /* Here's our actual 'q': */ + if (!BN_rshift(q, q, e)) + goto end; + + /* + * Now that we have some non-square, we can find an element of order 2^e + * by computing its q'th power. + */ + if (!BN_mod_exp(y, y, q, p, ctx)) + goto end; + + if (BN_is_one(y)) { + BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); + goto end; + } + + /*- + * Now we know that (if p is indeed prime) there is an integer + * k, 0 <= k < 2^e, such that + * + * a^q * y^k == 1 (mod p). + * + * As a^q is a square and y is not, k must be even. + * q+1 is even, too, so there is an element + * + * X := a^((q+1)/2) * y^(k/2), + * + * and it satisfies + * + * X^2 = a^q * a * y^k + * = a, + * + * so it is the square root that we are looking for. + */ + + /* t := (q-1)/2 (note that q is odd) */ + if (!BN_rshift1(t, q)) + goto end; + + /* x := a^((q-1)/2) */ + if (BN_is_zero(t)) { /* special case: p = 2^e + 1 */ + if (!BN_nnmod(t, A, p, ctx)) + goto end; + + if (BN_is_zero(t)) { + /* special case: a == 0 (mod p) */ + BN_zero(ret); + err = 0; + goto end; + } else if (!BN_one(x)) + goto end; + } else { + if (!BN_mod_exp(x, A, t, p, ctx)) + goto end; + + if (BN_is_zero(x)) { + /* special case: a == 0 (mod p) */ + BN_zero(ret); + err = 0; + goto end; + } + } + + /* b := a*x^2 (= a^q) */ + if (!BN_mod_sqr(b, x, p, ctx)) + goto end; + + if (!BN_mod_mul(b, b, A, p, ctx)) + goto end; + + /* x := a*x (= a^((q+1)/2)) */ + if (!BN_mod_mul(x, x, A, p, ctx)) + goto end; + + while (1) { + /*- + * Now b is a^q * y^k for some even k (0 <= k < 2^E + * where E refers to the original value of e, which we + * don't keep in a variable), and x is a^((q+1)/2) * y^(k/2). + * + * We have a*b = x^2, + * y^2^(e-1) = -1, + * b^2^(e-1) = 1. + */ + if (BN_is_one(b)) { + if (!BN_copy(ret, x)) + goto end; + + err = 0; + goto vrfy; + } + + /* find smallest i such that b^(2^i) = 1 */ + i = 1; + + if (!BN_mod_sqr(t, b, p, ctx)) + goto end; + + while (!BN_is_one(t)) { + i++; + + if (i == e) { + BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE); + goto end; + } + + if (!BN_mod_mul(t, t, t, p, ctx)) + goto end; + } + + /* t := y^2^(e - i - 1) */ + if (!BN_copy(t, y)) + goto end; + + for (j = e - i - 1; j > 0; j--) { + if (!BN_mod_sqr(t, t, p, ctx)) + goto end; + } + + if (!BN_mod_mul(y, t, t, p, ctx)) + goto end; + + if (!BN_mod_mul(x, x, t, p, ctx)) + goto end; + + if (!BN_mod_mul(b, b, y, p, ctx)) + goto end; + + e = i; + } + +vrfy: + + if (!err) { + /* + * verify the result -- the input might have been not a square (test + * added in 0.9.8) + */ + if (!BN_mod_sqr(x, ret, p, ctx)) + err = 1; + + if (!err && 0 != BN_cmp(x, A)) { + BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE); + err = 1; + } + } + +end: + + if (err) { + if (ret != in) + BN_clear_free(ret); + + ret = NULL; + } + + BN_CTX_end(ctx); + bn_check_top(ret); + return ret; +} + +static const char Hex[] = "0123456789ABCDEF"; + +char *BN_bn2hex(const BIGNUM *a) +{ + int i, j, v, z = 0; + char *buf; + char *p; + + if (BN_is_zero(a)) + return NULL; + + os_alloc_mem(NULL, (UCHAR **) &buf, a->top * BN_BYTES * 2 + 2); + + if (buf == NULL) + goto err +; + p = buf; + if (a->neg) + *(p++) = '-'; + for (i = a->top - 1; i >= 0; i--) { + for (j = BN_BITS2 - 8; j >= 0; j -= 8) { + /* strip leading zeros */ + v = ((int)(a->d[i] >> (long)j)) & 0xff; + if (z || (v != 0)) { + *(p++) = Hex[v >> 4]; + *(p++) = Hex[v & 0x0f]; + z = 1; + } + } + } + *p = '\0'; +err: + return buf; +} +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/client_wds.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/client_wds.c new file mode 100644 index 000000000..27260400a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/client_wds.c @@ -0,0 +1,192 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering 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); + + 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, (RT_LIST_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.CliWdsProxyTb[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.CliWdsProxyTb[idx].pHead; + while(pCliWdsEntry) + { + PCLIWDS_PROXY_ENTRY pCliWdsEntryNext = pCliWdsEntry->pNext; + CliWdsEntyFree(pAd, pCliWdsEntry); + pCliWdsEntry = pCliWdsEntryNext; + } + } + + if (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, (RT_LIST_ENTRY *)pCliWdsEntry); + + RTMP_SEM_UNLOCK(&pAd->ApCfg.CliWdsTabLock); + + return; +} + + +UCHAR *CliWds_ProxyLookup(RTMP_ADAPTER *pAd, UCHAR *pMac) +{ + UINT8 HashId = (*(pMac + 5) & (CLIWDS_HASH_TAB_SIZE - 1)); + PCLIWDS_PROXY_ENTRY pCliWdsEntry; + + pCliWdsEntry = (PCLIWDS_PROXY_ENTRY)pAd->ApCfg.CliWdsProxyTb[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.CliWdsProxyTb[HashId], (RT_LIST_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.CliWdsProxyTb[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.CliWdsProxyTb[idx], (RT_LIST_ENTRY *)pCliWdsEntry); + CliWdsEntyFree(pAd, pCliWdsEntry); + } + pCliWdsEntry = pCliWdsEntryNext; + } + } + return; +} + +#endif /* CLIENT_WDS */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_aes.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_aes.c new file mode 100644 index 000000000..2ec9fa311 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_aes.c @@ -0,0 +1,1153 @@ +/* + *************************************************************************** + * 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); + 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; + +#ifdef DOT11W_PMF_SUPPORT + /* When Management Frame Protection is negotiated, the Management + field of the Nonce Flags field shall be set to 1 if the Type + field of the Frame Control field is 00 (Management frame); otherwise it + is set to 0. */ + if (isMgmtFrame) + nonce_hdr[0] = nonce_hdr[0] | 0x10; +#endif /* DOT11W_PMF_SUPPORT */ + n_offset += 1; + + /* Fill in MPDU Address A2 field */ + NdisMoveMemory(&nonce_hdr[n_offset], pHdr + 10, MAC_ADDR_LEN); + n_offset += MAC_ADDR_LEN; + + /* Fill in the PN. The PN field occupies octets 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 == FC_TYPE_DATA) + { + qc_exists = ((frame_subtype == SUBTYPE_QDATA) || + (frame_subtype == SUBTYPE_QDATA_CFACK) || + (frame_subtype == SUBTYPE_QDATA_CFPOLL) || + (frame_subtype == SUBTYPE_QDATA_CFACK_CFPOLL)); + } + + /* Construct AAD header */ + RTMPConstructCCMPAAD(pHdr, + (frame_type == FC_TYPE_DATA), + a4_exists, + qc_exists, + aad_hdr, + &aad_len); + + /* Construct NONCE header */ + RTMPConstructCCMPNonce(pHdr, + a4_exists, + qc_exists, + (frame_type == FC_TYPE_MGMT), + pIV, + nonce_hdr, + &nonce_hdr_len); + + /* CCM originator processing - + Use the temporal key, AAD, nonce, and MPDU data to + form the cipher text and MIC. */ + if (AES_CCM_Encrypt(pData, DataLen, + pKey, 16, + nonce_hdr, nonce_hdr_len, + aad_hdr, aad_len, LEN_CCMP_MIC, + pData, &out_len)) + return FALSE; + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHdr, DIR_READ, FALSE); +#endif + + return TRUE; +} + +/* + ======================================================================== + + Routine Description: + Decrypt data with CCMP. + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +BOOLEAN RTMPSoftDecryptCCMP( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHdr, + IN PCIPHER_KEY pKey, + INOUT PUCHAR pData, + INOUT UINT16 *DataLen) +{ + UINT8 frame_type, frame_subtype; + UINT8 from_ds, to_ds; + UINT8 a4_exists, qc_exists; + UINT8 aad_hdr[30]; + UINT aad_len = 0; + UINT8 pn[LEN_PN]; + PUCHAR cipherData_ptr; + UINT32 cipherData_len; + UINT8 nonce_hdr[13]; + UINT32 nonce_hdr_len = 0; + UINT32 out_len = *DataLen; + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHdr, DIR_READ, FALSE); +#endif + + /* Check the key is valid */ + if (pKey->KeyLen == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The key is not available !\n", __FUNCTION__)); + return FALSE; + } + + /* Initial variable */ + NdisZeroMemory(aad_hdr, 30); + NdisZeroMemory(nonce_hdr, 13); + + /* Indicate type and subtype of Frame Control field */ + frame_type = (((*pHdr) >> 2) & 0x03); + frame_subtype = (((*pHdr) >> 4) & 0x0f); + + /* Indicate the fromDS and ToDS */ + from_ds = ((*(pHdr + 1)) & 0x2) >> 1; + to_ds = ((*(pHdr + 1)) & 0x1); + + /* decide if the Address 4 exist or QoS exist */ + a4_exists = (from_ds & to_ds); + qc_exists = 0; + if (frame_type == FC_TYPE_DATA) + { + qc_exists = ((frame_subtype == SUBTYPE_QDATA) || + (frame_subtype == SUBTYPE_QDATA_CFACK) || + (frame_subtype == SUBTYPE_QDATA_CFPOLL) || + (frame_subtype == SUBTYPE_QDATA_CFACK_CFPOLL)); + } + + /* Extract PN and from CCMP header */ + pn[0] = pData[0]; + pn[1] = pData[1]; + pn[2] = pData[4]; + pn[3] = pData[5]; + pn[4] = pData[6]; + pn[5] = pData[7]; + + /* skip ccmp header */ + cipherData_ptr = pData + LEN_CCMP_HDR; + cipherData_len = *DataLen - LEN_CCMP_HDR; + + /*skip payload length is zero*/ + if ((*DataLen ) <= LEN_CCMP_HDR) + return FALSE; + + /* Construct AAD header */ + RTMPConstructCCMPAAD(pHdr, + (frame_type == FC_TYPE_DATA), + a4_exists, + qc_exists, + aad_hdr, + &aad_len); + + /* Construct NONCE header */ + RTMPConstructCCMPNonce(pHdr, + a4_exists, + qc_exists, + (frame_type == FC_TYPE_MGMT), + pn, + nonce_hdr, + &nonce_hdr_len); + + /* CCM recipient processing - + uses the temporal key, AAD, nonce, MIC, + and MPDU cipher text data */ + if (AES_CCM_Decrypt(cipherData_ptr, cipherData_len, + pKey->Key, 16, + nonce_hdr, nonce_hdr_len, + aad_hdr, aad_len, LEN_CCMP_MIC, + pData, &out_len)) + return FALSE; + + *DataLen = out_len; + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHdr, DIR_READ, FALSE); +#endif + + return TRUE; +} + +/* + ======================================================================== + + 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/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_cfg.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_cfg.c new file mode 100644 index 000000000..cb3e96073 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_cfg.c @@ -0,0 +1,2771 @@ +/**************************************************************************** + * 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(RTMP_STRING *SetCmd); + + +INT ComputeChecksum(UINT PIN) +{ + INT digit_s; + UINT accum = 0; + + PIN *= 10; + accum += 3 * ((PIN / 10000000) % 10); + accum += 1 * ((PIN / 1000000) % 10); + accum += 3 * ((PIN / 100000) % 10); + accum += 1 * ((PIN / 10000) % 10); + accum += 3 * ((PIN / 1000) % 10); + accum += 1 * ((PIN / 100) % 10); + accum += 3 * ((PIN / 10) % 10); + + digit_s = (accum % 10); + return ((10 - digit_s) % 10); +} /* ComputeChecksum*/ + +UINT GenerateWpsPinCode( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromApcli, + IN UCHAR apidx) +{ + UCHAR macAddr[MAC_ADDR_LEN]; + UINT iPin; + UINT checksum; + + NdisZeroMemory(macAddr, MAC_ADDR_LEN); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (bFromApcli) + NdisMoveMemory(&macAddr[0], pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, MAC_ADDR_LEN); + else +#endif /* APCLI_SUPPORT */ + NdisMoveMemory(&macAddr[0], pAd->ApCfg.MBSSID[apidx].wdev.if_addr, MAC_ADDR_LEN); + } +#endif /* CONFIG_AP_SUPPORT */ + + iPin = macAddr[3] * 256 * 256 + macAddr[4] * 256 + macAddr[5]; + + iPin = iPin % 10000000; + + + checksum = ComputeChecksum( iPin ); + iPin = iPin*10 + checksum; + + return iPin; +} + + +static char *phy_mode_str[]={"CCK", "OFDM", "HTMIX", "GF", "VHT"}; +char* get_phymode_str(int Mode) +{ + if (Mode >= MODE_CCK && Mode <= MODE_VHT) + return phy_mode_str[Mode]; + else + return "N/A"; +} + + +static UCHAR *phy_bw_str[] = {"20M", "40M", "80M", "BOTH", "10M"}; +char* get_bw_str(int bandwidth) +{ + if (bandwidth >= BW_20 && bandwidth <= BW_10) + return phy_bw_str[bandwidth]; + else + return "N/A"; +} + + +/* + ========================================================================== + Description: + Set Country Region to pAd->CommonCfg.CountryRegion. + This command will not work, if the field of CountryRegion in eeprom is programmed. + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT RT_CfgSetCountryRegion(RTMP_ADAPTER *pAd, RTMP_STRING *arg, INT band) +{ + LONG region; + UCHAR *pCountryRegion; + + region = simple_strtol(arg, 0, 10); + + if (band == BAND_24G) + pCountryRegion = &pAd->CommonCfg.CountryRegion; + else + pCountryRegion = &pAd->CommonCfg.CountryRegionForABand; + + /* + 1. If this value is set before interface up, do not reject this value. + 2. Country can be set only when EEPROM not programmed + */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE) && (*pCountryRegion & EEPROM_IS_PROGRAMMED)) + { + DBGPRINT(RT_DEBUG_ERROR, ("CfgSetCountryRegion():CountryRegion in eeprom was programmed\n")); + return FALSE; + } + + if((region >= 0) && + (((band == BAND_24G) &&((region <= REGION_MAXIMUM_BG_BAND) || + (region == REGION_31_BG_BAND) || (region == REGION_32_BG_BAND) || (region == REGION_33_BG_BAND) )) || + ((band == BAND_5G) && (region <= REGION_MAXIMUM_A_BAND) )) + ) + { + *pCountryRegion= (UCHAR) region; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("CfgSetCountryRegion():region(%ld) out of range!\n", region)); + return FALSE; + } + + return TRUE; + +} + + +static UCHAR CFG_WMODE_MAP[]={ + PHY_11BG_MIXED, (WMODE_B | WMODE_G), /* 0 => B/G mixed */ + PHY_11B, (WMODE_B), /* 1 => B only */ + PHY_11A, (WMODE_A), /* 2 => A only */ + PHY_11ABG_MIXED, (WMODE_A | WMODE_B | WMODE_G), /* 3 => A/B/G mixed */ + PHY_11G, WMODE_G, /* 4 => G only */ + PHY_11ABGN_MIXED, (WMODE_B | WMODE_G | WMODE_GN | WMODE_A | WMODE_AN), /* 5 => A/B/G/GN/AN mixed */ + PHY_11N_2_4G, (WMODE_GN), /* 6 => N in 2.4G band only */ + PHY_11GN_MIXED, (WMODE_G | WMODE_GN), /* 7 => G/GN, i.e., no CCK mode */ + PHY_11AN_MIXED, (WMODE_A | WMODE_AN), /* 8 => A/N in 5 band */ + PHY_11BGN_MIXED, (WMODE_B | WMODE_G | WMODE_GN), /* 9 => B/G/GN mode*/ + PHY_11AGN_MIXED, (WMODE_G | WMODE_GN | WMODE_A | WMODE_AN), /* 10 => A/AN/G/GN mode, not support B mode */ + PHY_11N_5G, (WMODE_AN), /* 11 => only N in 5G band */ +#ifdef DOT11_VHT_AC + PHY_11VHT_N_ABG_MIXED, (WMODE_B | WMODE_G | WMODE_GN |WMODE_A | WMODE_AN | WMODE_AC), /* 12 => B/G/GN/A/AN/AC mixed*/ + PHY_11VHT_N_AG_MIXED, (WMODE_G | WMODE_GN |WMODE_A | WMODE_AN | WMODE_AC), /* 13 => G/GN/A/AN/AC mixed , no B mode */ + PHY_11VHT_N_A_MIXED, (WMODE_A | WMODE_AN | WMODE_AC), /* 14 => A/AC/AN mixed */ + PHY_11VHT_N_MIXED, (WMODE_AN | WMODE_AC), /* 15 => AC/AN mixed, but no A mode */ +#endif /* DOT11_VHT_AC */ + PHY_MODE_MAX, WMODE_INVALID /* default phy mode if not match */ +}; + +#ifdef DBG +static RTMP_STRING *BAND_STR[] = {"Invalid", "2.4G", "5G", "2.4G/5G"}; +#endif /* DBG */ +static RTMP_STRING *WMODE_STR[]= {"", "A", "B", "G", "gN", "aN", "AC"}; + +UCHAR *wmode_2_str(UCHAR wmode) +{ + UCHAR *str; + INT idx, pos, max_len; + + max_len = WMODE_COMP * 3; + if (os_alloc_mem(NULL, &str, max_len) == NDIS_STATUS_SUCCESS) + { + NdisZeroMemory(str, max_len); + pos = 0; + for (idx = 0; idx < WMODE_COMP; idx++) + { + if (wmode & (1 << idx)) { + if ((strlen(str) + strlen(WMODE_STR[idx + 1])) >= (max_len - 1)) + break; + if (strlen(str)) { + NdisMoveMemory(&str[pos], "/", 1); + pos++; + } + NdisMoveMemory(&str[pos], WMODE_STR[idx + 1], strlen(WMODE_STR[idx + 1])); + pos += strlen(WMODE_STR[idx + 1]); + } + if (strlen(str) >= max_len) + break; + } + + return str; + } + else + return NULL; +} + + +RT_802_11_PHY_MODE wmode_2_cfgmode(UCHAR wmode) +{ + INT i, mode_cnt = sizeof(CFG_WMODE_MAP) / (sizeof(UCHAR) * 2); + + for (i = 0; i < mode_cnt; i++) + { + if (CFG_WMODE_MAP[i*2+1] == wmode) + return CFG_WMODE_MAP[i*2]; + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Cannot get cfgmode by wmode(%x)\n", + __FUNCTION__, wmode)); + + return 0; +} + + +UCHAR cfgmode_2_wmode(UCHAR cfg_mode) +{ + DBGPRINT(RT_DEBUG_OFF, ("cfg_mode=%d\n", cfg_mode)); + if (cfg_mode >= PHY_MODE_MAX) + cfg_mode = PHY_MODE_MAX; + + return CFG_WMODE_MAP[cfg_mode * 2 + 1]; +} + +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT +static BOOLEAN wmode_valid(RTMP_ADAPTER *pAd, enum WIFI_MODE wmode) +{ + if ((WMODE_CAP_5G(wmode) && (!PHY_CAP_5G(pAd->chipCap.phy_caps))) || + (WMODE_CAP_2G(wmode) && (!PHY_CAP_2G(pAd->chipCap.phy_caps))) || + (WMODE_CAP_N(wmode) && RTMP_TEST_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DOT_11N)) + ) + return FALSE; + else + return TRUE; +} +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +static BOOLEAN wmode_valid_and_correct(RTMP_ADAPTER *pAd, UCHAR* wmode) +{ + BOOLEAN ret = TRUE; + + if (*wmode == WMODE_INVALID) + *wmode = (WMODE_B | WMODE_G | WMODE_GN |WMODE_A | WMODE_AN | WMODE_AC); + + while(1) + { + if (WMODE_CAP_5G(*wmode) && (!PHY_CAP_5G(pAd->chipCap.phy_caps))) + { + *wmode = *wmode & ~(WMODE_A | WMODE_AN | WMODE_AC); + } + else if (WMODE_CAP_2G(*wmode) && (!PHY_CAP_2G(pAd->chipCap.phy_caps))) + { + *wmode = *wmode & ~(WMODE_B | WMODE_G | WMODE_GN); + } + else if (WMODE_CAP_N(*wmode) && ((!PHY_CAP_N(pAd->chipCap.phy_caps)) || RTMP_TEST_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DOT_11N))) + { + *wmode = *wmode & ~(WMODE_GN | WMODE_AN); + } + else if (WMODE_CAP_AC(*wmode) && (!PHY_CAP_AC(pAd->chipCap.phy_caps))) + { + *wmode = *wmode & ~(WMODE_AC); + } + + if ( *wmode == 0 ) + { + *wmode = (WMODE_B | WMODE_G | WMODE_GN |WMODE_A | WMODE_AN | WMODE_AC); + break; + } + else + break; + } + + return ret; +} + + +BOOLEAN wmode_band_equal(UCHAR smode, UCHAR tmode) +{ + BOOLEAN eq = FALSE; + UCHAR *str1, *str2; + + if ((WMODE_CAP_5G(smode) == WMODE_CAP_5G(tmode)) && + (WMODE_CAP_2G(smode) == WMODE_CAP_2G(tmode))) + eq = TRUE; + + str1 = wmode_2_str(smode); + str2 = wmode_2_str(tmode); + if (str1 && str2) + { + DBGPRINT(RT_DEBUG_TRACE, + ("Old WirelessMode:%s(0x%x), " + "New WirelessMode:%s(0x%x)!\n", + str1, smode, str2, tmode)); + } + if (str1) + os_free_mem(NULL, str1); + if (str2) + os_free_mem(NULL, str2); + + return eq; +} + + +/* + ========================================================================== + Description: + Set Wireless Mode + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT RT_CfgSetWirelessMode(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + LONG cfg_mode; + UCHAR wmode, *mode_str; + + + cfg_mode = simple_strtol(arg, 0, 10); + + /* check if chip support 5G band when WirelessMode is 5G band */ + wmode = cfgmode_2_wmode((UCHAR)cfg_mode); + if (!wmode_valid_and_correct(pAd, &wmode)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s(): Invalid wireless mode(%ld, wmode=0x%x), ChipCap(%s)\n", + __FUNCTION__, cfg_mode, wmode, + BAND_STR[pAd->chipCap.phy_caps & 0x3])); + return FALSE; + } + + if (wmode_band_equal(pAd->CommonCfg.PhyMode, wmode) == TRUE) + DBGPRINT(RT_DEBUG_OFF, ("wmode_band_equal(): Band Equal!\n")); + else + DBGPRINT(RT_DEBUG_OFF, ("wmode_band_equal(): Band Not Equal!\n")); + + pAd->CommonCfg.PhyMode = wmode; + pAd->CommonCfg.cfg_wmode = wmode; + + mode_str = wmode_2_str(wmode); + if (mode_str) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Set WMODE=%s(0x%x)\n", + __FUNCTION__, mode_str, wmode)); + os_free_mem(NULL, mode_str); + } + + return TRUE; +} + + +/* maybe can be moved to GPL code, ap_mbss.c, but the code will be open */ +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT +static UCHAR RT_CfgMbssWirelessModeMaxGet(RTMP_ADAPTER *pAd) +{ + UCHAR wmode = 0, *mode_str; + INT idx; + struct wifi_dev *wdev; + + for(idx = 0; idx < pAd->ApCfg.BssidNum; idx++) { + wdev = &pAd->ApCfg.MBSSID[idx].wdev; + mode_str = wmode_2_str(wdev->PhyMode); + if (mode_str) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(BSS%d): wmode=%s(0x%x)\n", + __FUNCTION__, idx, mode_str, wdev->PhyMode)); + os_free_mem(pAd, mode_str); + } + wmode |= wdev->PhyMode; + } + + mode_str = wmode_2_str(wmode); + if (mode_str) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Combined WirelessMode = %s(0x%x)\n", + __FUNCTION__, mode_str, wmode)); + os_free_mem(pAd, mode_str); + } + return wmode; +} + + +/* + ========================================================================== + Description: + Set Wireless Mode for MBSS + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT RT_CfgSetMbssWirelessMode(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT cfg_mode; + UCHAR wmode; + + + cfg_mode = simple_strtol(arg, 0, 10); + + wmode = cfgmode_2_wmode((UCHAR)cfg_mode); + if ((wmode == WMODE_INVALID) || (!wmode_valid(pAd, wmode))) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s(): Invalid wireless mode(%d, wmode=0x%x), ChipCap(%s)\n", + __FUNCTION__, cfg_mode, wmode, + BAND_STR[pAd->chipCap.phy_caps & 0x3])); + return FALSE; + } + + if (WMODE_CAP_5G(wmode) && WMODE_CAP_2G(wmode)) + { + DBGPRINT(RT_DEBUG_ERROR, ("AP cannot support 2.4G/5G band mxied mode!\n")); + return FALSE; + } + + + if (pAd->ApCfg.BssidNum > 1) + { + /* pAd->CommonCfg.PhyMode = maximum capability of all MBSS */ + if (wmode_band_equal(pAd->CommonCfg.PhyMode, wmode) == TRUE) + { + wmode = RT_CfgMbssWirelessModeMaxGet(pAd); + + DBGPRINT(RT_DEBUG_TRACE, + ("mbss> Maximum phy mode = %d!\n", wmode)); + } + else + { + UINT32 IdBss; + + /* replace all phy mode with the one with different band */ + DBGPRINT(RT_DEBUG_TRACE, + ("mbss> Different band with the current one!\n")); + DBGPRINT(RT_DEBUG_TRACE, + ("mbss> Reset band of all BSS to the new one!\n")); + + for(IdBss=0; IdBssApCfg.BssidNum; IdBss++) + pAd->ApCfg.MBSSID[IdBss].wdev.PhyMode = wmode; + } + } + + pAd->CommonCfg.PhyMode = wmode; + pAd->CommonCfg.cfg_wmode = wmode; + return TRUE; +} +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +static BOOLEAN RT_isLegalCmdBeforeInfUp(RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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 RTMP_STRING *keyString, + IN CIPHER_KEY *pSharedKey, + IN INT keyIdx) +{ + INT KeyLen; + INT i; + /*UCHAR CipherAlg = CIPHER_NONE;*/ +#ifdef DBG + BOOLEAN bKeyIsHex = FALSE; +#endif /* DBG */ + + /* 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*/ +#ifdef MT_MAC + case 16: /*wep 128 Ascii type*/ +#endif +#ifdef DBG + bKeyIsHex = FALSE; +#endif /* DBG */ + pSharedKey->KeyLen = KeyLen; + NdisMoveMemory(pSharedKey->Key, keyString, KeyLen); + break; + + case 10: /*wep 40 Hex type*/ + case 26: /*wep 104 Hex type*/ +#ifdef MT_MAC + case 32: /*wep 128 Hex type*/ +#endif + for(i=0; i < KeyLen; i++) + { + if( !isxdigit(*(keyString+i)) ) + return FALSE; /*Not Hex value;*/ + } +#ifdef DBG + bKeyIsHex = TRUE; +#endif /* DBG */ + 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); +#ifdef MT_MAC + if (KeyLen == 32) + pSharedKey->CipherAlg = CIPHER_WEP152; +#endif + 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 RTMP_STRING *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(RTMP_STRING *arg) +{ + INT fix_tx_mode = FIXED_TXMODE_HT; + ULONG value; + + + if (rtstrcasecmp(arg, "OFDM") == TRUE) + fix_tx_mode = FIXED_TXMODE_OFDM; + else if (rtstrcasecmp(arg, "CCK") == TRUE) + fix_tx_mode = FIXED_TXMODE_CCK; + else if (rtstrcasecmp(arg, "HT") == TRUE) + fix_tx_mode = FIXED_TXMODE_HT; + else if (rtstrcasecmp(arg, "VHT") == TRUE) + fix_tx_mode = FIXED_TXMODE_VHT; + else + { + value = simple_strtol(arg, 0, 10); + switch (value) + { + case FIXED_TXMODE_CCK: + case FIXED_TXMODE_OFDM: + case FIXED_TXMODE_HT: + case FIXED_TXMODE_VHT: + fix_tx_mode = value; + break; + default: + fix_tx_mode = FIXED_TXMODE_HT; + break; + } + } + + return fix_tx_mode; + +} + + +INT RT_CfgSetMacAddress(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_STRING *arg, BOOLEAN *pAutoRate) +{ + INT Value = simple_strtol(arg, 0, 10); + INT TxMcs; + + if ((Value >= 0 && Value <= 23) || (Value == 32)) /* 3*3*/ + { + TxMcs = Value; + *pAutoRate = FALSE; + } + else + { + TxMcs = MCS_AUTO; + *pAutoRate = TRUE; + } + + return TxMcs; + +} + + +INT RT_CfgSetAutoFallBack(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR AutoFallBack = (UCHAR)simple_strtol(arg, 0, 10); + + if (AutoFallBack) + AutoFallBack = TRUE; + else + AutoFallBack = FALSE; + + AsicSetAutoFallBack(pAd, (AutoFallBack) ? TRUE : FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("RT_CfgSetAutoFallBack::(AutoFallBack=%d)\n", AutoFallBack)); + return TRUE; +} + + +#ifdef WSC_INCLUDED +INT RT_CfgSetWscPinCode( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *pPinCodeStr, + OUT PWSC_CTRL pWscControl) +{ + UINT pinCode; + + pinCode = (UINT) simple_strtol(pPinCodeStr, 0, 10); /* When PinCode is 03571361, return value is 3571361.*/ + if (strlen(pPinCodeStr) == 4) + { + pWscControl->WscEnrolleePinCode = pinCode; + pWscControl->WscEnrolleePinCodeLen = 4; + } + else if ( ValidateChecksum(pinCode) ) + { + pWscControl->WscEnrolleePinCode = pinCode; + pWscControl->WscEnrolleePinCodeLen = 8; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("RT_CfgSetWscPinCode(): invalid Wsc PinCode (%d)\n", pinCode)); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("RT_CfgSetWscPinCode():Wsc PinCode=%d\n", pinCode)); + + return TRUE; + +} +#endif /* WSC_INCLUDED */ + +/* +======================================================================== +Routine Description: + Handler for CMD_RTPRIV_IOCTL_STA_SIOCGIWNAME. + +Arguments: + pAd - WLAN control block pointer + *pData - the communication data pointer + Data - the communication data + +Return Value: + NDIS_STATUS_SUCCESS or NDIS_STATUS_FAILURE + +Note: +======================================================================== +*/ +INT RtmpIoctl_rt_ioctl_giwname( + IN RTMP_ADAPTER *pAd, + IN VOID *pData, + IN ULONG Data) +{ + UCHAR CurOpMode = OPMODE_AP; + + if (CurOpMode == OPMODE_AP) + { + strcpy(pData, "RTWIFI SoftAP"); + } + + return NDIS_STATUS_SUCCESS; +} + + +INT RTMP_COM_IoctlHandle( + IN VOID *pAdSrc, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + INT Status = NDIS_STATUS_SUCCESS, i; + + + pObj = pObj; /* avoid compile warning */ + + switch(cmd) + { + case CMD_RTPRIV_IOCTL_NETDEV_GET: + /* get main net_dev */ + { + VOID **ppNetDev = (VOID **)pData; + *ppNetDev = (VOID *)(pAd->net_dev); + } + break; + + case CMD_RTPRIV_IOCTL_NETDEV_SET: + { + struct wifi_dev *wdev = NULL; + /* set main net_dev */ + pAd->net_dev = pData; + +#ifdef CONFIG_AP_SUPPORT + if (pAd->OpMode == OPMODE_AP) { + pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.if_dev = (void *)pData; + pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.func_dev = (void *)&pAd->ApCfg.MBSSID[MAIN_MBSSID]; + pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.func_idx = MAIN_MBSSID; + pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.sys_handle = (void *)pAd; + RTMP_OS_NETDEV_SET_WDEV(pData, &pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev); + wdev = &pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev; + } +#endif /* CONFIG_AP_SUPPORT */ + if (wdev) { + if (rtmp_wdev_idx_reg(pAd, wdev) < 0) { + DBGPRINT(RT_DEBUG_ERROR, ("Assign wdev idx for %s failed, free net device!\n", + RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev))); + RtmpOSNetDevFree(pAd->net_dev); + } + } + break; + } + case CMD_RTPRIV_IOCTL_OPMODE_GET: + /* get Operation Mode */ + *(ULONG *)pData = pAd->OpMode; + break; + + + case CMD_RTPRIV_IOCTL_TASK_LIST_GET: + /* get all Tasks */ + { + RT_CMD_WAIT_QUEUE_LIST *pList = (RT_CMD_WAIT_QUEUE_LIST *)pData; + + pList->pMlmeTask = &pAd->mlmeTask; +#ifdef RTMP_TIMER_TASK_SUPPORT + pList->pTimerTask = &pAd->timerTask; +#endif /* RTMP_TIMER_TASK_SUPPORT */ + pList->pCmdQTask = &pAd->cmdQTask; +#ifdef WSC_INCLUDED + pList->pWscTask = &pAd->wscTask; +#endif /* WSC_INCLUDED */ + } + break; + +#ifdef RTMP_MAC_PCI + case CMD_RTPRIV_IOCTL_IRQ_INIT: + /* init IRQ */ + rtmp_irq_init(pAd); + break; +#endif /* RTMP_MAC_PCI */ + + case CMD_RTPRIV_IOCTL_IRQ_RELEASE: + /* release IRQ */ + RTMP_OS_IRQ_RELEASE(pAd, pAd->net_dev); + break; + +#ifdef RTMP_MAC_PCI + case CMD_RTPRIV_IOCTL_MSI_ENABLE: + /* enable MSI */ + RTMP_MSI_ENABLE(pAd); + *(ULONG **)pData = (ULONG *)(pObj->pci_dev); + break; +#endif /* RTMP_MAC_PCI */ + + case CMD_RTPRIV_IOCTL_NIC_NOT_EXIST: + /* set driver state to fRTMP_ADAPTER_NIC_NOT_EXIST */ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); + break; + + case CMD_RTPRIV_IOCTL_MCU_SLEEP_CLEAR: + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_MCU_SLEEP); + break; + + + 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((RTMP_STRING *) pData) == FALSE) + return NDIS_STATUS_FAILURE; + } + break; + + case CMD_RTPRIV_IOCTL_SIOCGIWFREQ: + /* get channel number */ + *(ULONG *)pData = pAd->CommonCfg.Channel; + break; +#ifdef CONFIG_SNIFFER_SUPPORT + case CMD_RTPRIV_IOCTL_SNIFF_INIT: + Monitor_Init(pAd, pData); + break; + + case CMD_RTPRIV_IOCTL_SNIFF_OPEN: + if (Monitor_Open(pAd, pData) != TRUE) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_SNIFF_CLOSE: + if (Monitor_Close(pAd, pData) != TRUE) + return NDIS_STATUS_FAILURE; + break; + + case CMD_RTPRIV_IOCTL_SNIFF_REMOVE: + Monitor_Remove(pAd); + break; +#endif /*CONFIG_SNIFFER_SUPPORT*/ + + + + case CMD_RTPRIV_IOCTL_BEACON_UPDATE: + /* update all beacon contents */ +#ifdef CONFIG_AP_SUPPORT + //CFG_TODO + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); +#endif /* CONFIG_AP_SUPPORT */ + break; + + case CMD_RTPRIV_IOCTL_RXPATH_GET: + /* get the number of rx path */ + *(ULONG *)pData = pAd->Antenna.field.RxPath; + break; + + case CMD_RTPRIV_IOCTL_CHAN_LIST_NUM_GET: + *(ULONG *)pData = pAd->ChannelListNum; + break; + + case CMD_RTPRIV_IOCTL_CHAN_LIST_GET: + { + UINT32 i; + UCHAR *pChannel = (UCHAR *)pData; + + for (i = 1; i <= pAd->ChannelListNum; i++) + { + *pChannel = pAd->ChannelList[i-1].Channel; + pChannel ++; + } + } + break; + + case CMD_RTPRIV_IOCTL_FREQ_LIST_GET: + { + UINT32 i; + UINT32 *pFreq = (UINT32 *)pData; + UINT32 m; + + for (i = 1; i <= pAd->ChannelListNum; i++) + { + m = 2412000; + MAP_CHANNEL_ID_TO_KHZ(pAd->ChannelList[i-1].Channel, m); + (*pFreq) = m; + pFreq ++; + } + } + break; + +#ifdef EXT_BUILD_CHANNEL_LIST + case CMD_RTPRIV_SET_PRECONFIG_VALUE: + /* Set some preconfigured value before interface up*/ + pAd->CommonCfg.DfsType = MAX_RD_REGION; + break; +#endif /* EXT_BUILD_CHANNEL_LIST */ + + + +#ifdef RTMP_PCI_SUPPORT + case CMD_RTPRIV_IOCTL_PCI_SUSPEND: + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + break; + + case CMD_RTPRIV_IOCTL_PCI_RESUME: + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + break; + + case CMD_RTPRIV_IOCTL_PCI_CSR_SET: + pAd->CSRBaseAddress = (PUCHAR)Data; + DBGPRINT(RT_DEBUG_ERROR, ("pAd->CSRBaseAddress =0x%lx, csr_addr=0x%lx!\n", (ULONG)pAd->CSRBaseAddress, (ULONG)Data)); + break; + + case CMD_RTPRIV_IOCTL_PCIE_INIT: + RTMPInitPCIeDevice(pData, pAd); + break; +#endif /* RTMP_PCI_SUPPORT */ + +#ifdef RTMP_SDIO_SUPPORT + case CMD_RTPRIV_IOCTL_SDIO_INIT: + InitSDIODevice(pAd); + break; +#endif + +#ifdef INF_PPA_SUPPORT + case CMD_RTPRIV_IOCTL_INF_PPA_INIT: + os_alloc_mem(NULL, (UCHAR **)&(pAd->pDirectpathCb), sizeof(PPA_DIRECTPATH_CB)); + break; + + case CMD_RTPRIV_IOCTL_INF_PPA_EXIT: + if (ppa_hook_directpath_register_dev_fn && (pAd->PPAEnable == TRUE)) + { + UINT status; + status = ppa_hook_directpath_register_dev_fn(&pAd->g_if_id, pAd->net_dev, NULL, 0); + DBGPRINT(RT_DEBUG_TRACE, ("Unregister PPA::status=%d, if_id=%d\n", status, pAd->g_if_id)); + } + os_free_mem(NULL, pAd->pDirectpathCb); + break; +#endif /* INF_PPA_SUPPORT*/ + + case CMD_RTPRIV_IOCTL_VIRTUAL_INF_UP: + /* interface up */ + { + RT_CMD_INF_UP_DOWN *pInfConf = (RT_CMD_INF_UP_DOWN *)pData; + // TODO: Shiang-usw, this function looks have some problem, need to revise! + if (VIRTUAL_IF_NUM(pAd) == 0) + { +#ifdef DBG + ULONG start, end, diff_ms; + /* Get the current time for calculating startup time */ + NdisGetSystemUpTime(&start); +#endif /* DBG */ + VIRTUAL_IF_INC(pAd); + if (pInfConf->rt28xx_open(pAd->net_dev) != 0) + { + VIRTUAL_IF_DEC(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("rt28xx_open return fail!\n")); + return NDIS_STATUS_FAILURE; + } + +#ifdef DBG + /* Get the current time for calculating startup time */ + NdisGetSystemUpTime(&end); diff_ms = (end-start)*1000/OS_HZ; + DBGPRINT(RT_DEBUG_ERROR, ("WiFi Startup Cost (%s): %lu.%03lus\n", + RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev),diff_ms/1000,diff_ms%1000)); +#endif /* DBG */ + } + else + { + VIRTUAL_IF_INC(pAd); +#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 */ + } + } + 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 = 0; /* Collision packets*/ + pStats->rx_over_errors = pAd->Counters8023.RxNoBuffer; /* receiver ring buff overflow*/ + pStats->rx_crc_errors = 0;/*pAd->WlanCounters.FCSErrorCount; recved pkt with crc error*/ + pStats->rx_frame_errors = 0; /* recv'd frame alignment error*/ + pStats->rx_fifo_errors = pAd->Counters8023.RxNoBuffer; /* recv'r fifo overrun*/ + } +#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].wdev.if_dev == (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; + + + /*check if the interface is down*/ + if(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + return NDIS_STATUS_FAILURE; + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == OPMODE_AP) + { +#ifdef APCLI_SUPPORT + if ((pStats->priv_flags == INT_APCLI) + ) + { + INT ApCliIdx = ApCliIfLookUp(pAd, (PUCHAR)pStats->dev_addr); + if ((ApCliIdx >= 0) && VALID_WCID(pAd->ApCfg.ApCliTab[ApCliIdx].MacTabWCID)) + pMacEntry = &pAd->MacTab.Content[pAd->ApCfg.ApCliTab[ApCliIdx].MacTabWCID]; + } + else +#endif /* APCLI_SUPPORT */ + { + /* + only AP client support wireless stats function. + return NULL pointer for all other cases. + */ + pMacEntry = NULL; + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_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_AP_SUPPORT + if (CurOpMode == OPMODE_AP) + { + if (pMacEntry != NULL) + pStats->level = + RTMPMaxRssi(pAd, pMacEntry->RssiSample.AvgRssi[0], + pMacEntry->RssiSample.AvgRssi[1], + pMacEntry->RssiSample.AvgRssi[2]); + else + pStats->level = RTMPMaxRssi(pAd, pAd->ApCfg.RssiSample.AvgRssi[0], + pAd->ApCfg.RssiSample.AvgRssi[1], + pAd->ApCfg.RssiSample.AvgRssi[2]); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + pStats->noise = RTMPMaxRssi(pAd, pAd->ApCfg.RssiSample.AvgRssi[0], + pAd->ApCfg.RssiSample.AvgRssi[1], + pAd->ApCfg.RssiSample.AvgRssi[2]) - + RTMPMinSnr(pAd, pAd->ApCfg.RssiSample.AvgSnr[0], + pAd->ApCfg.RssiSample.AvgSnr[1]); +#endif /* CONFIG_AP_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 CONFIG_ATE +#ifdef CONFIG_QA + case CMD_RTPRIV_IOCTL_ATE: + RtmpDoAte(pAd, wrq, pData); + break; +#endif /* CONFIG_QA */ +#endif /* CONFIG_ATE */ + + case CMD_RTPRIV_IOCTL_MAC_ADDR_GET: + { + UCHAR mac_addr[MAC_ADDR_LEN]; + USHORT Addr01, Addr23, Addr45; + + RT28xx_EEPROM_READ16(pAd, 0x04, Addr01); + RT28xx_EEPROM_READ16(pAd, 0x06, Addr23); + RT28xx_EEPROM_READ16(pAd, 0x08, Addr45); + + mac_addr[0] = (UCHAR)(Addr01 & 0xff); + mac_addr[1] = (UCHAR)(Addr01 >> 8); + mac_addr[2] = (UCHAR)(Addr23 & 0xff); + mac_addr[3] = (UCHAR)(Addr23 >> 8); + mac_addr[4] = (UCHAR)(Addr45 & 0xff); + mac_addr[5] = (UCHAR)(Addr45 >> 8); + + for(i=0; i<6; i++) + *(UCHAR *)(pData+i) = mac_addr[i]; + break; + } +#ifdef CONFIG_AP_SUPPORT + case CMD_RTPRIV_IOCTL_AP_SIOCGIWRATEQ: + /* handle for SIOCGIWRATEQ */ + { + RT_CMD_IOCTL_RATE *pRate = (RT_CMD_IOCTL_RATE *)pData; + HTTRANSMIT_SETTING HtPhyMode; + +#ifdef APCLI_SUPPORT + if (pRate->priv_flags == INT_APCLI) + HtPhyMode = pAd->ApCfg.ApCliTab[pObj->ioctl_if].wdev.HTPhyMode; + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (pRate->priv_flags == INT_WDS) + HtPhyMode = pAd->WdsTab.WdsEntry[pObj->ioctl_if].wdev.HTPhyMode; + else +#endif /* WDS_SUPPORT */ + HtPhyMode = pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.HTPhyMode; + + 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; + + } + + + 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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + NDIS_802_11_SSID Ssid; + +#ifdef CONFIG_AP_SUPPORT +#ifdef AP_SCAN_SUPPORT +#endif /* AP_SCAN_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + struct wifi_dev *wdev = NULL; + UCHAR ifIndex; + POS_COOKIE pObjt = (POS_COOKIE) pAd->OS_Cookie; +#endif + +#ifdef CONFIG_AP_SUPPORT + ifIndex = pObjt->ioctl_if; +#ifdef APCLI_SUPPORT + if (pObjt->ioctl_if_type == INT_APCLI) + wdev = &pAd->ApCfg.ApCliTab[pObjt->ioctl_if].wdev; + else +#endif + if (pObjt->ioctl_if_type == INT_MBSSID) + wdev = &pAd->ApCfg.MBSSID[pObjt->ioctl_if].wdev; + else + wdev = &pAd->ApCfg.MBSSID[0].wdev; +#endif + + //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; + } + + + NdisZeroMemory(&Ssid, sizeof(NDIS_802_11_SSID)); + +#ifdef CONFIG_AP_SUPPORT +#ifdef AP_SCAN_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if ((strlen(arg) != 0) && (strlen(arg) <= MAX_LEN_OF_SSID)) + { + NdisMoveMemory(Ssid.Ssid, arg, strlen(arg)); + Ssid.SsidLength = strlen(arg); + } + + if (Ssid.SsidLength == 0) + ApSiteSurvey(pAd, &Ssid, SCAN_PASSIVE, FALSE, wdev); + else + ApSiteSurvey(pAd, &Ssid, SCAN_ACTIVE, FALSE, wdev); + + return TRUE; + } +#endif /* AP_SCAN_SUPPORT */ +#endif // CONFIG_AP_SUPPORT // + + + DBGPRINT(RT_DEBUG_TRACE, ("Set_SiteSurvey_Proc\n")); + + return TRUE; +} + +INT Set_Antenna_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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 HW_TX_RATE_LOOKUP_SUPPORT +INT Set_HwTxRateLookUp_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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 /* HW_TX_RATE_LOOKUP_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT +#ifdef MULTI_MAC_ADDR_EXT_SUPPORT +INT Set_EnMultiMacAddrExt_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR Enable = simple_strtol(arg, 0, 10); + + pAd->bUseMultiMacAddrExt = (Enable ? TRUE : FALSE); + AsicSetMacAddrExt(pAd, pAd->bUseMultiMacAddrExt); + + DBGPRINT(RT_DEBUG_WARN, ("UseMultiMacAddrExt = %d, UseMultiMacAddrExt(%s)\n", + pAd->bUseMultiMacAddrExt, (Enable ? "ON" : "OFF"))); + + return TRUE; +} + +INT Set_MultiMacAddrExt_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR tempMAC[6], idx; + RTMP_STRING *token; + RTMP_STRING sepValue[] = ":", DASH = '-'; + ULONG offset, Addr; + INT i; + + if(strlen(arg) < 19) /*Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format.*/ + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + idx = (UCHAR) simple_strtol((token+1), 0, 10); + + if (idx > 15) + return FALSE; + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (&tempMAC[i]), 1); + } + + if(i != 6) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x\n", + tempMAC[0], tempMAC[1], tempMAC[2], tempMAC[3], tempMAC[4], tempMAC[5], idx)); + + offset = 0x1480 + (HW_WCID_ENTRY_SIZE * idx); + Addr = tempMAC[0] + (tempMAC[1] << 8) +(tempMAC[2] << 16) +(tempMAC[3] << 24); + RTMP_IO_WRITE32(pAd, offset, Addr); + Addr = tempMAC[4] + (tempMAC[5] << 8); + RTMP_IO_WRITE32(pAd, offset + 4, Addr); + + return TRUE; + } + + return FALSE; +} +#endif /* MULTI_MAC_ADDR_EXT_SUPPORT */ +#endif /* MAC_REPEATER_SUPPORT */ + +INT set_tssi_enable(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT8 tssi_enable = 0; + + tssi_enable = simple_strtol(arg, 0, 10); + + if (tssi_enable == 1) { + pAd->chipCap.tssi_enable = TRUE; + DBGPRINT(RT_DEBUG_OFF, ("turn on TSSI mechanism\n")); + } else if (tssi_enable == 0) { + pAd->chipCap.tssi_enable = FALSE; + DBGPRINT(RT_DEBUG_OFF, ("turn off TSS mechanism\n")); + } else { + DBGPRINT(RT_DEBUG_OFF, ("illegal param(%u)\n", tssi_enable)); + return FALSE; + } + return TRUE; +} + +#ifdef RLT_MAC +#ifdef CONFIG_WIFI_TEST +INT set_pbf_loopback(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT8 enable = 0; + UINT32 value; + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(): Not support for HIF_MT yet!\n", + __FUNCTION__)); + return FALSE; + } + + enable = simple_strtol(arg, 0, 10); + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &value); + + if (enable == 1) { + pAd->chipCap.pbf_loopback = TRUE; + value |= PBF_LOOP_EN; + DBGPRINT(RT_DEBUG_OFF, ("turn on pbf loopback\n")); + } else if(enable == 0) { + pAd->chipCap.pbf_loopback = FALSE; + value &= ~PBF_LOOP_EN; + DBGPRINT(RT_DEBUG_OFF, ("turn off pbf loopback\n")); + } else { + DBGPRINT(RT_DEBUG_OFF, ("illegal param(%d)\n")); + return FALSE; + } + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, value); + + return TRUE; +} + +INT set_pbf_rx_drop(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT8 enable = 0; + UINT32 value; + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(): Not support for HIF_MT yet!\n", + __FUNCTION__)); + return FALSE; + } + + enable = simple_strtol(arg, 0, 10); + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + RTMP_IO_READ32(pAd, RLT_PBF_CFG, &value); +#endif + + if (enable == 1) { + pAd->chipCap.pbf_rx_drop = TRUE; + value |= RX_DROP_MODE; + DBGPRINT(RT_DEBUG_OFF, ("turn on pbf loopback\n")); + } else if (enable == 0) { + pAd->chipCap.pbf_rx_drop = FALSE; + value &= ~RX_DROP_MODE; + DBGPRINT(RT_DEBUG_OFF, ("turn off pbf loopback\n")); + } else { + DBGPRINT(RT_DEBUG_OFF, ("illegal param(%d)\n")); + return FALSE; + } + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + RTMP_IO_WRITE32(pAd, RLT_PBF_CFG, value); +#endif + + return TRUE; +} +#endif + +INT set_fw_debug(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT8 fw_debug_param; + + fw_debug_param = simple_strtol(arg, 0, 10); + +#ifdef RLT_MAC + AndesRltFunSet(pAd, LOG_FW_DEBUG_MSG, fw_debug_param); +#endif /* RLT_MAC */ + + return TRUE; +} +#endif + +#ifdef MT_MAC +INT set_get_fid(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + //TODO: Carter, at present, only can read pkt in Port2(LMAC port) + volatile UCHAR q_idx = 0, loop = 0, dw_idx = 0; + UINT32 head_fid_addr = 0, dw_content, next_fid_addr = 0; + volatile UINT32 value = 0x00000000L; + q_idx = simple_strtol(arg, 0, 10); + + value = 0x00400000 | (q_idx << 16);//port2. queue by input value. + RTMP_IO_WRITE32(pAd, 0x8024, value); + RTMP_IO_READ32(pAd, 0x8024, &head_fid_addr);//get head FID. + head_fid_addr = head_fid_addr & 0xfff; + + if (head_fid_addr == 0xfff) { + DBGPRINT(RT_DEBUG_ERROR, ("%s, q_idx:%d empty!!\n", __func__, q_idx)); + return TRUE; + } + + value = (0 | (head_fid_addr << 16)); + while (1) { + for (dw_idx = 0; dw_idx < 8; dw_idx++) { + RTMP_IO_READ32(pAd, ((MT_PCI_REMAP_ADDR_1 + (((value & 0x0fff0000) >> 16) * 128)) + (dw_idx * 4)), &dw_content);//get head FID. + DBGPRINT(RT_DEBUG_ERROR, ("pkt:%d, fid:%x, dw_idx = %d, dw_content = 0x%x\n", loop, ((value & 0x0fff0000) >> 16), dw_idx, dw_content)); + } + RTMP_IO_WRITE32(pAd, 0x8028, value); + RTMP_IO_READ32(pAd, 0x8028, &next_fid_addr);//get next FID. + if ((next_fid_addr & 0xfff) == 0xfff) { + return TRUE; + } + + value = (0 | ((next_fid_addr & 0xffff) << 16)); + loop++; + if (loop > 5) { + return TRUE; + } + } + return TRUE; +} + + +#ifdef RTMP_MAC_PCI +INT Set_PDMAWatchDog_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 Dbg; + + Dbg = simple_strtol(arg, 0, 10); + + if (Dbg == 1) + { + pAd->PDMAWatchDogEn = 1; + } + else if (Dbg == 0) + { + pAd->PDMAWatchDogEn = 0; + } + else if (Dbg == 2) + { + PDMAResetAndRecovery(pAd); + } + else if (Dbg == 3) + { + pAd->PDMAWatchDogDbg = 0; + } + else if (Dbg == 4) + { + pAd->PDMAWatchDogDbg = 1; + } + + return TRUE; +} +#endif /* RTMP_MAC_PCI */ + +INT SetPSEWatchDog_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 Dbg; + + Dbg = simple_strtol(arg, 0, 10); + + if (Dbg == 1) + { + pAd->PSEWatchDogEn = 1; + } + else if (Dbg == 0) + { + pAd->PSEWatchDogEn = 0; + } +#ifdef RTMP_MAC_PCI + + else if (Dbg == 2) + { + PSEResetAndRecovery(pAd); + } + else if (Dbg == 3) + { + DumpPseInfo(pAd); + + } +#endif /* RTMP_MAC_PCI */ + +#ifdef DMA_RESET_SUPPORT + else if (Dbg == 4) + { + pAd->bcn_reset_en=TRUE; + } + else if (Dbg == 5) + { + pAd->bcn_reset_en=FALSE; + } +#endif /* DMA_RESET_SUPPORT */ + + return TRUE; +} + +#ifdef TXRXCR_DEBUG_SUPPORT +INT SetTxRxCr_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 Dbg; + UINT32 mac_val; + UINT32 idx; + Dbg = simple_strtol(arg, 0, 10); + + if (Dbg == 0) + { + RTMP_IO_WRITE32(pAd, 0x14108, 0x80); + RTMP_IO_WRITE32(pAd, 0x14108, 0xc0); + RTMP_IO_WRITE32(pAd, 0x14108, 0x80); + + RTMP_IO_READ32(pAd, 0x2c030, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x60330030=0x%x\n",mac_val)); + + RTMP_IO_READ32(pAd, 0x2c01c, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x6033001C=0x%x\n",mac_val)); + } + else if (Dbg == 1) + { + + DBGPRINT(RT_DEBUG_ERROR, ("=============================================\n")); + DBGPRINT(RT_DEBUG_ERROR, ("RX Status Counter\n")); + RTMP_IO_READ32(pAd, 0x1410c, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x6020410C=0x%x\n",mac_val)); + + RTMP_IO_READ32(pAd, 0x14110, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x60204110=0x%x\n",mac_val)); + + RTMP_IO_READ32(pAd, 0x14114, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x60204114=0x%x\n",mac_val)); + + RTMP_IO_READ32(pAd, 0x1411c, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x6020411C=0x%x\n",mac_val)); + + RTMP_IO_READ32(pAd, 0x14120, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x60204120=0x%x\n",mac_val)); + + RTMP_IO_READ32(pAd, 0x2c030, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x60330030=0x%x\n",mac_val)); + + RTMP_IO_READ32(pAd, 0x2c01c, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x6033001C=0x%x\n",mac_val)); + + DBGPRINT(RT_DEBUG_ERROR, ("=============================================\n")); + DBGPRINT(RT_DEBUG_ERROR, ("CCA Status\n")); + RTMP_IO_WRITE32(pAd, 0x20014, 0x1F); + RTMP_IO_WRITE32(pAd, 0x20018, 0x07070707); + RTMP_IO_WRITE32(pAd, 0x2004c, 0x02021919); + + RTMP_IO_READ32(pAd, 0x20024, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x60000024=0x%x\n",mac_val)); + DBGPRINT(RT_DEBUG_ERROR, ("=============================================\n")); + + for (idx=0;idx<10;idx++) + { + RTMP_IO_READ32(pAd, 0x21518, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x60120118[%d]=0x%08x ",idx, mac_val)); + if (idx==4) + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + } + + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + + RTMP_IO_WRITE32(pAd, 0x20014, 0x1f); + RTMP_IO_WRITE32(pAd, 0x20014, 0x07070707); + + RTMP_IO_WRITE32(pAd, 0x2004c, 0x00000101); + DBGPRINT(RT_DEBUG_ERROR, ("write 0x6000004c=0x00000101\n")); + + for (idx=0;idx<10;idx++) + { + RTMP_IO_READ32(pAd, 0x20024, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x60000024[%d]=0x%08x ",idx, mac_val)); + if (idx==4) + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + } + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + + RTMP_IO_WRITE32(pAd, 0x2004c, 0x02021919); + DBGPRINT(RT_DEBUG_ERROR, ("write 0x6000004c=0x02021919\n")); + for (idx=0;idx<10;idx++) + { + RTMP_IO_READ32(pAd, 0x20024, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x60000024[%d]=0x%08x ",idx, mac_val)); + if (idx==4) + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + } + + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + + RTMP_IO_WRITE32(pAd, 0x2004c, 0x10101212); + + DBGPRINT(RT_DEBUG_ERROR, ("write 0x6000004c=0x10101212\n")); + for (idx=0;idx<10;idx++) + { + RTMP_IO_READ32(pAd, 0x20024, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x60000024[%d]=0x%08x ",idx, mac_val)); + if (idx==4) + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + } + + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + + RTMP_IO_WRITE32(pAd, 0x2004c, 0x00000B0B); + + DBGPRINT(RT_DEBUG_ERROR, ("write 0x6000004c=0x00000B0B\n")); + for (idx=0;idx<10;idx++) + { + RTMP_IO_READ32(pAd, 0x20024, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x60000024[%d]=0x%08x ",idx, mac_val)); + if (idx==4) + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + } + + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + DBGPRINT(RT_DEBUG_ERROR, ("=============================================\n")); + + RTMP_IO_WRITE32(pAd, 0x2004c, 0x13131414); + RTMP_IO_READ32(pAd, 0x20024, &mac_val); + + DBGPRINT(RT_DEBUG_ERROR, ("0x6000004c[0x13131414]=0x%08x ", mac_val)); + RTMP_IO_WRITE32(pAd, 0x2004c, 0x1A1A1B1B); + RTMP_IO_READ32(pAd, 0x20024, &mac_val); + + DBGPRINT(RT_DEBUG_ERROR, ("0x6000004c[0x1A1A1B1B]=0x%08x ", mac_val)); + RTMP_IO_WRITE32(pAd, 0x2004c, 0x16161D1D); + RTMP_IO_READ32(pAd, 0x20024, &mac_val); + + DBGPRINT(RT_DEBUG_ERROR, ("0x6000004c[0x16161D1D]=0x%08x ", mac_val)); + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + + RTMP_IO_WRITE32(pAd, 0x2004c, 0x26262727); + RTMP_IO_READ32(pAd, 0x20024, &mac_val); + + DBGPRINT(RT_DEBUG_ERROR, ("0x6000004c[0x26262727]=0x%08x ", mac_val)); + RTMP_IO_WRITE32(pAd, 0x2004c, 0x28282929); + RTMP_IO_READ32(pAd, 0x20024, &mac_val); + + DBGPRINT(RT_DEBUG_ERROR, ("0x6000004c[0x28282929]=0x%08x ", mac_val)); + RTMP_IO_WRITE32(pAd, 0x2004c, 0x2A2A2B2B); + RTMP_IO_READ32(pAd, 0x20024, &mac_val); + + DBGPRINT(RT_DEBUG_ERROR, ("0x6000004c[0x2A2A2B2B]=0x%08x ", mac_val)); + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + DBGPRINT(RT_DEBUG_ERROR, ("=============================================\n")); + + RTMP_IO_READ32(pAd, 0x21710, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x60130110=0x%08x ", mac_val)); + + RTMP_IO_READ32(pAd, 0x21714, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x60130114=0x%08x ", mac_val)); + + RTMP_IO_READ32(pAd, 0x21718, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x60130118=0x%08x ", mac_val)); + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + + RTMP_IO_READ32(pAd, 0x2171c, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x60130118=0x%08x ", mac_val)); + + RTMP_IO_READ32(pAd, 0x21720, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x60130120=0x%08x ", mac_val)); + + RTMP_IO_READ32(pAd, 0x21724, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x60130124=0x%08x ", mac_val)); + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + + RTMP_IO_READ32(pAd, 0x21728, &mac_val); + DBGPRINT(RT_DEBUG_ERROR, ("0x60130128=0x%08x ", mac_val)); + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + DBGPRINT(RT_DEBUG_ERROR, ("=============================================\n")); + + RTMP_IO_WRITE32(pAd, 0x20014, 0x1f); + RTMP_IO_WRITE32(pAd, 0x20018, 0x05050505); + + RTMP_IO_WRITE32(pAd, 0x2004c, 0x85858686); + RTMP_IO_READ32(pAd, 0x20024, &mac_val); + + DBGPRINT(RT_DEBUG_ERROR, ("0x6000004c[0x85858686]=0x%08x\n", mac_val)); + + RTMP_IO_WRITE32(pAd, 0x20018, 0x05050404); + RTMP_IO_WRITE32(pAd, 0x2004c, 0x81812A2A); + RTMP_IO_READ32(pAd, 0x20024, &mac_val); + + DBGPRINT(RT_DEBUG_ERROR, ("0x6000004c[0x81812A2A]=0x%08x\n", mac_val)); + DBGPRINT(RT_DEBUG_ERROR, ("\n\n\n\n\n\n\n\n\n\n")); + DBGPRINT(RT_DEBUG_ERROR, ("=============================================\n")); + } + + return TRUE; +} +#endif /* TXRXCR_DEBUG_SUPPORT */ + + + +INT set_fw_log(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 LogType; + LogType = simple_strtol(arg, 0, 10); + + if (LogType < 3) + CmdFwLog2Host(pAd, LogType); + else + DBGPRINT(RT_DEBUG_OFF, (":%s: Unknown Log Type = %d\n", __FUNCTION__, LogType)); + + return TRUE; +} + +#ifdef THERMAL_PROTECT_SUPPORT +INT set_thermal_protection_criteria_proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + UINT8 HighEn; + CHAR HighTempTh; + UINT8 LowEn; + CHAR LowTempTh; + CHAR *Param; + + Param = rstrtok(arg, ","); + + if (Param != NULL) + { + HighEn = simple_strtol(Param, 0, 10); + } + else + { + goto error; + } + + Param = rstrtok(NULL, ","); + + if (Param != NULL) + { + HighTempTh = simple_strtol(Param, 0, 10); + } + else + { + goto error; + } + + Param = rstrtok(NULL, ","); + + if (Param != NULL) + { + LowEn = simple_strtol(Param, 0, 10); + } + else + { + goto error; + } + + Param = rstrtok(NULL, ","); + + if (Param != NULL) + { + LowTempTh = simple_strtol(Param, 0, 10); + } + else + { + goto error; + } + + + CmdThermalProtect(pAd, HighEn, HighTempTh, LowEn, LowTempTh); + + DBGPRINT(RT_DEBUG_OFF, ("%s: high_en=%d, high_thd = %d, low_en = %d, low_thd = %d\n", __FUNCTION__, HighEn, HighTempTh, LowEn, LowTempTh)); + + return TRUE; + +error: + DBGPRINT(RT_DEBUG_OFF, ("iwpriv ra0 set tpc=high_en,high_thd,low_en,low_thd\n")); + return TRUE; + +} +#endif /* THERMAL_PROTECT_SUPPORT */ + +VOID StatRateToString(RTMP_ADAPTER *pAd, CHAR *Output, UCHAR TxRx, UINT32 RawData) +{ + extern UCHAR tmi_rate_map_ofdm[]; + extern UCHAR tmi_rate_map_cck_lp[]; + extern UCHAR tmi_rate_map_cck_sp[]; + UCHAR phy_mode, rate, preamble; + CHAR *phyMode[5] = {"CCK", "OFDM", "MM", "GF", "VHT"}; + + phy_mode = RawData>>13; + rate = RawData & 0x3F; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED)) + preamble = SHORT_PREAMBLE; + else + preamble = LONG_PREAMBLE; + + if ( TxRx == 0 ) + sprintf(Output+strlen(Output), "Last TX Rate = "); + else + sprintf(Output+strlen(Output), "Last RX Rate = "); + + if ( phy_mode == MODE_CCK ) { + + if ( TxRx == 0 ) + { + if (preamble) + rate = tmi_rate_map_cck_lp[rate]; + else + rate = tmi_rate_map_cck_sp[rate]; + } + + if ( rate == TMI_TX_RATE_CCK_1M_LP ) + sprintf(Output+strlen(Output), "1M, "); + else if ( rate == TMI_TX_RATE_CCK_2M_LP ) + sprintf(Output+strlen(Output), "2M, "); + else if ( rate == TMI_TX_RATE_CCK_5M_LP ) + sprintf(Output+strlen(Output), "5M, "); + else if ( rate == TMI_TX_RATE_CCK_11M_LP ) + sprintf(Output+strlen(Output), "11M, "); + else if ( rate == TMI_TX_RATE_CCK_2M_SP ) + sprintf(Output+strlen(Output), "2M, "); + else if ( rate == TMI_TX_RATE_CCK_5M_SP ) + sprintf(Output+strlen(Output), "5M, "); + else if ( rate == TMI_TX_RATE_CCK_11M_SP ) + sprintf(Output+strlen(Output), "11M, "); + else + sprintf(Output+strlen(Output), "unkonw, "); + + } else if ( phy_mode == MODE_OFDM ) { + + if ( TxRx == 0 ) + { + rate = tmi_rate_map_ofdm[rate]; + } + + if ( rate == TMI_TX_RATE_OFDM_6M ) + sprintf(Output+strlen(Output), "6M, "); + else if ( rate == TMI_TX_RATE_OFDM_9M ) + sprintf(Output+strlen(Output), "9M, "); + else if ( rate == TMI_TX_RATE_OFDM_12M ) + sprintf(Output+strlen(Output), "12M, "); + else if ( rate == TMI_TX_RATE_OFDM_18M ) + sprintf(Output+strlen(Output), "18M, "); + else if ( rate == TMI_TX_RATE_OFDM_24M ) + sprintf(Output+strlen(Output), "24M, "); + else if ( rate == TMI_TX_RATE_OFDM_36M ) + sprintf(Output+strlen(Output), "36M, "); + else if ( rate == TMI_TX_RATE_OFDM_48M ) + sprintf(Output+strlen(Output), "48M, "); + else if ( rate == TMI_TX_RATE_OFDM_54M ) + sprintf(Output+strlen(Output), "54M, "); + else + sprintf(Output+strlen(Output), "unkonw, "); + } else { + sprintf(Output+strlen(Output), "MCS%d, ", rate); + } + sprintf(Output+strlen(Output), "%2dM, ", ((RawData>>7) & 0x1)? 40: 20); + sprintf(Output+strlen(Output), "%cGI, ", ((RawData>>9) & 0x1)? 'S': 'L'); + sprintf(Output+strlen(Output), "%s%s\n", phyMode[(phy_mode) & 0x3], ((RawData>>10) & 0x3)? ", STBC": " "); + +} + + +INT Set_themal_sensor(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + /* 0: get temperature; 1: get adc */ + UINT32 value; + value = simple_strtol(arg, 0, 10); + + if ((value == 0) || (value == 1)) { +#if defined(MT7603) || defined(MT7628) +#ifdef DBG + UINT32 temperature=0; + temperature = MtAsicGetThemalSensor(pAd, value); + DBGPRINT(RT_DEBUG_OFF, ("%s: ThemalSensor = 0x%x\n", __FUNCTION__, temperature)); +#endif /* DBG */ +#else + CmdGetThemalSensorResult(pAd, value); +#endif /* MT7603 ||MT7628 */ + } else + DBGPRINT(RT_DEBUG_OFF, (":%s: 0: get temperature; 1: get adc\n", __FUNCTION__)); + + return TRUE; +} + + +INT Set_rx_pspoll_filter_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 value; + value = simple_strtol(arg, 0, 10); + + pAd->rx_pspoll_filter = value; + MtAsicSetRxPspollFilter(pAd, pAd->rx_pspoll_filter); + + DBGPRINT(RT_DEBUG_OFF, (":%s: rx_pspoll_filter=%d\n", __FUNCTION__, pAd->rx_pspoll_filter)); + return TRUE; +} + +#ifdef SMART_CARRIER_SENSE_SUPPORT +INT SetSCSEnable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 value; + + value = simple_strtol(arg, 0, 10); + + + if (value == 1) + { + pAd->SCSCtrl.SCSEnable= SCS_ENABLE; + DBGPRINT(RT_DEBUG_OFF, ("==>%s (ON)\n", __FUNCTION__)); + } + else if (value == 0) + { + pAd->SCSCtrl.SCSEnable= SCS_DISABLE; + DBGPRINT(RT_DEBUG_OFF, ("==>%s (OFF)\n", __FUNCTION__)); + /* Restore to default */ + RTMP_IO_WRITE32(pAd, CR_AGC_0, pAd->SCSCtrl.CR_AGC_0_default); + RTMP_IO_WRITE32(pAd, CR_AGC_0_RX1, pAd->SCSCtrl.CR_AGC_0_default); + RTMP_IO_WRITE32(pAd, CR_AGC_3, pAd->SCSCtrl.CR_AGC_3_default); + RTMP_IO_WRITE32(pAd, CR_AGC_3_RX1, pAd->SCSCtrl.CR_AGC_3_default); + pAd->SCSCtrl.SCSStatus = SCS_STATUS_DEFAULT; + } + else + DBGPRINT(RT_DEBUG_OFF, ("==>%s (Unknow value = %d)\n", __FUNCTION__, value)); + + return TRUE; +} + +INT SetSCSCfg_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT32 Recv=0; + INT SCSMinRssiTolerance = 0, SCSTrafficThreshold = 0, FalseCcaUpBond = 0, FalseCcaLowBond = 0, FixedBond = 0, ForceMode = 0; + + Recv = sscanf(arg, "%d-%d-%d-%d-%d-%d", &(SCSMinRssiTolerance), &(SCSTrafficThreshold), &(FalseCcaUpBond), &(FalseCcaLowBond), &(FixedBond), &(ForceMode)); + if (Recv != 6){ + DBGPRINT(RT_DEBUG_OFF, ("Format Error!\n")); + DBGPRINT(RT_DEBUG_OFF, ("iwpriv ra0 set SCSCfg=[MinRssiTolerance]-[TrafficThreshold]-[FalseCcaUpBoundary]-[FalseCcaLowBoundary]-[FixedBoundary]-[ForceMode]\n")); + DBGPRINT(RT_DEBUG_OFF, ("PS: FiexedBond is Negative number. Ex:70 means -70dBm")); + } else { + pAd->SCSCtrl.SCSMinRssiTolerance = (UINT8)SCSMinRssiTolerance; + pAd->SCSCtrl.SCSTrafficThreshold = SCSTrafficThreshold; + pAd->SCSCtrl.FalseCcaUpBond = (UINT16)FalseCcaUpBond; + pAd->SCSCtrl.FalseCcaLowBond = (UINT16)FalseCcaLowBond; + pAd->SCSCtrl.FixedRssiBond = (0 -(CHAR)FixedBond); + pAd->SCSCtrl.ForceMode = (BOOLEAN)ForceMode; + } + return TRUE; +} +#endif /* SMART_CARRIER_SENSE_SUPPORT */ + +#endif /* MT_MAC */ +#ifdef SW_ATF_SUPPORT +/*Set badNodeEntry max and min enq threshold. Default set enq_badNodeMaxThr = 4,enq_badNodeMinThr = 3*/ +INT SetBadNodePara_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT32 Recv = 0; + INT minEnqThr, maxEnqThr; + + Recv = sscanf(arg, "%d-%d", &(minEnqThr), &(maxEnqThr)); + if (Recv != 2) { + DBGPRINT(RT_DEBUG_OFF, ("Format Error!\n")); + DBGPRINT(RT_DEBUG_OFF, ("iwpriv ra0 set badNodePara=[minEnqThr]-[maxEnqThr]\n")); + } else { + pAd->AtfParaSet.enq_badNodeMaxThr = maxEnqThr; + pAd->AtfParaSet.enq_badNodeMinThr = minEnqThr; + DBGPRINT(RT_DEBUG_OFF, ("minEnqThr = %d,maxEnqThr = %d\n", + pAd->AtfParaSet.enq_badNodeMinThr, pAd->AtfParaSet.enq_badNodeMaxThr)); + } + return TRUE; +} +/*Set goodNodeEntry max and min deq threshold. Default set deq_goodNodeMaxThr = 468,deq_goodNodeMinThr = 390*/ +INT SetGoodNodePara_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT32 Recv = 0; + + INT minDeqThr, maxDeqThr; + + Recv = sscanf(arg, "%d-%d", &(minDeqThr), &(maxDeqThr)); + if (Recv != 2) { + DBGPRINT(RT_DEBUG_OFF, ("Format Error!\n")); + DBGPRINT(RT_DEBUG_OFF, ("iwpriv ra0 set goodNodePara=[minDeqThr]-[maxDeqThr]\n")); + } else { + pAd->AtfParaSet.deq_goodNodeMaxThr = maxDeqThr; + pAd->AtfParaSet.deq_goodNodeMinThr = minDeqThr; + DBGPRINT(RT_DEBUG_OFF, ("minDeqThr = %d,maxDeqThr = %d\n", + pAd->AtfParaSet.deq_goodNodeMinThr, pAd->AtfParaSet.deq_goodNodeMaxThr)); + } + return TRUE; +} +INT SetFixAtfPara_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT32 value; + + value = simple_strtol(arg, 0, 10); + pAd->AtfParaSet.flagOnce = value; + pAd->AtfParaSet.enq_badNodeCurrent = 4; + DBGPRINT(RT_DEBUG_OFF, ("fixAtfPara:%d\n", pAd->AtfParaSet.flagOnce)); + return TRUE; +} +/*Set txThreshold,Default set wcidTxThr = 43*/ +INT SetTxThr_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT32 value; + + value = simple_strtol(arg, 0, 10); + pAd->AtfParaSet.wcidTxThr = value; + DBGPRINT(RT_DEBUG_OFF, ("wcidTxThr:%d\n", pAd->AtfParaSet.wcidTxThr)); + return TRUE; + +} +/*Set badNodeEntry min deq Threshold. Default set deq_badNodeMinThr = 43*/ +INT SetBadNodeMinDeq_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT32 value; + + value = simple_strtol(arg, 0, 10); + pAd->AtfParaSet.deq_badNodeMinThr = value; + DBGPRINT(RT_DEBUG_OFF, ("badNodeMinDeqCnt:%d\n", pAd->AtfParaSet.deq_badNodeMinThr)); + return TRUE; +} +/*Set enq period time. Default set dropDelta = 2,periodTimer = 75um(75um = (1+2)*25um)*/ +INT SetAtfDropDelta_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT32 value; + + value = simple_strtol(arg, 0, 10); + pAd->AtfParaSet.dropDelta = value; + DBGPRINT(RT_DEBUG_OFF, ("dropDelta:%d\n", pAd->AtfParaSet.dropDelta)); + return TRUE; + +} +/*set atf false cca*/ +INT SetAtfFalseCCAThr_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT32 value; + + value = simple_strtol(arg, 0, 10); + pAd->AtfParaSet.atfFalseCCAThr = value; + DBGPRINT(RT_DEBUG_OFF, ("atfFalseCCAThr:%d\n", pAd->AtfParaSet.atfFalseCCAThr)); + return TRUE; + +} +#endif + +#ifdef SINGLE_SKU_V2 +INT SetSKUEnable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR value; + + value = simple_strtol(arg, 0, 10); + + if (value) + { + pAd->SKUEn = 1; + DBGPRINT(RT_DEBUG_ERROR, ("==>SetSKUEnable_Proc (ON)\n")); + } + else + { + pAd->SKUEn = 0; + DBGPRINT(RT_DEBUG_ERROR, ("==>SetSKUEnable_Proc (OFF)\n")); + } + + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + + return TRUE; +} +#endif /* SINGLE_SKU_V2 */ + +/* run-time turn EDCCA on/off */ +INT Set_ed_chk_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT ed_chk = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s()::ed_chk=%d\n", + __FUNCTION__, ed_chk)); + + pAd->ed_chk = ed_chk; + if (ed_chk != 0) + RTMP_CHIP_ASIC_SET_EDCCA(pAd, TRUE); + else + RTMP_CHIP_ASIC_SET_EDCCA(pAd, FALSE); + + return TRUE; +} +INT ed_status_read(RTMP_ADAPTER *pAd) +{ + UINT32 period_us = pAd->ed_chk_period * 1000; + ULONG irqflag=0; + INT percent; + BOOLEAN bIsCERegion = FALSE; + UINT32 ed_th = 0; + + UINT32 ch_idle_stat=0, ch_busy_stat=0, ed_stat=0, rssi_stat=0; + INT32 WBRssi0, WBRssi1, RefWBRssi; + + RTMP_IO_READ32(pAd, 0x2c050, &ed_stat); + + RTMP_IRQ_LOCK(&pAd->irq_lock, irqflag); + + pAd->ch_idle_stat[pAd->ed_stat_lidx] = ch_idle_stat; + pAd->ch_busy_stat[pAd->ed_stat_lidx] = ch_busy_stat; + pAd->ed_stat[pAd->ed_stat_lidx] = ed_stat; + NdisGetSystemUpTime(&pAd->chk_time[pAd->ed_stat_lidx]); + + RTMP_IO_READ32(pAd,RO_AGC_DEBUG_2,&rssi_stat); + + //IBRssi0 = (rssi_stat&0xFF000000)>>24; + WBRssi0 = (rssi_stat&0x00FF0000)>>16; + //IBRssi1 = (rssi_stat&0x0000FF00)>>8; + WBRssi1 = (rssi_stat&0x000000FF); + + if(WBRssi0>=128) + WBRssi0-=256; + + if(WBRssi1>=128) + WBRssi1-=256; + + RefWBRssi = max(WBRssi0,WBRssi1); + pAd->rssi_stat[pAd->ed_stat_lidx] = RefWBRssi; + if(RefWBRssi >= -40 && pAd->ed_big_rssi_count < pAd->ed_block_tx_threshold) + pAd->ed_big_rssi_count++; + else if(pAd->ed_big_rssi_count > 0) + pAd->ed_big_rssi_count--; + + pAd->ed_big_rssi_stat[pAd->ed_stat_lidx] = pAd->ed_big_rssi_count * 100 / pAd->ed_block_tx_threshold; + + if ((pAd->ed_threshold > 0) && (period_us > 0) && (pAd->ed_block_tx_threshold > 0)) { + percent = (pAd->ed_stat[pAd->ed_stat_lidx] * 100 ) / period_us; + if (percent > 100) + percent = 100; + + if (percent > pAd->ed_threshold) + { + pAd->ed_trigger_cnt++; + pAd->ed_silent_cnt = 0; + } + else + { + pAd->ed_trigger_cnt = 0; + pAd->ed_silent_cnt++; + } + + if(pAd->ed_debug) + { + DBGPRINT(RT_DEBUG_ERROR, ("@@@ %s: pAd->ed_trigger_cnt=%d, pAd->ed_silent_cnt=%u, percent=%d !!\n", + __FUNCTION__, pAd->ed_trigger_cnt, pAd->ed_silent_cnt + , percent)); + } + } + pAd->ed_trigger_stat[pAd->ed_stat_lidx] = pAd->ed_trigger_cnt; + pAd->ed_silent_stat[pAd->ed_stat_lidx] = pAd->ed_silent_cnt; + + if(pAd->ed_chk != FALSE) + { + UINT32 macVal = 0, macVal2 = 0; + bIsCERegion = GetEDCCASupport(pAd); + ed_th = pAd->ed_th; + + RTMP_IO_READ32(pAd, WF_PHY_BASE + 0x0634, &macVal2); + if (pAd->ed_trigger_cnt > pAd->ed_block_tx_threshold || pAd->ed_big_rssi_stat[pAd->ed_stat_lidx] < 50) { + //EDCCA CERT + if(pAd->ed_threshold_strict != TRUE) + { + pAd->ed_threshold_strict = TRUE; + macVal = 0xD7C87D10; + if((!bIsCERegion) && (ed_th < NON_CE_REGION_MAX_ED_TH)) { + macVal = macVal & (~(0x7F << 8)); + macVal = macVal | (ed_th << 8); + } + RTMP_IO_WRITE32(pAd, WF_PHY_BASE + 0x0618, macVal); + + macVal2 &= 0xFFFFFFFE; + RTMP_IO_WRITE32(pAd, WF_PHY_BASE + 0x0634, macVal2); + + DBGPRINT(RT_DEBUG_WARN, ("\n====\n@@@ %s: EDCCA TH - H\npAd->ed_trigger_cnt : %d > %d || pAd->ed_big_rssi_stat : %d < 50\n====\n" + ,__FUNCTION__,pAd->ed_trigger_cnt,pAd->ed_block_tx_threshold,pAd->ed_big_rssi_stat[pAd->ed_stat_lidx])); + + } + } + + if (pAd->ed_silent_cnt > pAd->ed_block_tx_threshold && pAd->ed_big_rssi_stat[pAd->ed_stat_lidx] >= 50) { + //EDCCA USER + if(pAd->ed_threshold_strict != FALSE) + { + pAd->ed_threshold_strict = FALSE; + macVal = 0xD7C87D0F; + if((!bIsCERegion) && (ed_th < NON_CE_REGION_MAX_ED_TH)) { + macVal = macVal & (~(0x7F << 8)); + macVal = macVal | (ed_th << 8); + } + RTMP_IO_WRITE32(pAd, WF_PHY_BASE + 0x0618, macVal); + + macVal2 |= 0x1; + RTMP_IO_WRITE32(pAd, WF_PHY_BASE + 0x0634, macVal2); + + DBGPRINT(RT_DEBUG_WARN, ("\n====\n@@@ %s: EDCCA TH - L\npAd->ed_silent_cnt : %d > %d && pAd->ed_big_rssi_stat : %d >= 50\n====\n" + ,__FUNCTION__,pAd->ed_silent_cnt,pAd->ed_block_tx_threshold,pAd->ed_big_rssi_stat[pAd->ed_stat_lidx])); + + } + } + } + + INC_RING_INDEX(pAd->ed_stat_lidx, ED_STAT_CNT); + //pAd->false_cca_stat[pAd->ed_stat_lidx] = 0; + if (pAd->ed_stat_sidx == pAd->ed_stat_lidx) { + INC_RING_INDEX(pAd->ed_stat_sidx, ED_STAT_CNT); + } + + RTMP_IRQ_UNLOCK(&pAd->irq_lock, irqflag); + + if (pAd->ed_trigger_cnt > pAd->ed_block_tx_threshold) { + if (pAd->ed_tx_stoped == FALSE) { + pAd->ed_tx_stoped = TRUE; + DBGPRINT(RT_DEBUG_WARN, ("\n====\n### %s: EDCCA ed_tx_stoped is set to TRUE\n====\n", __FUNCTION__)); + } + } + + if (pAd->ed_silent_cnt > pAd->ed_block_tx_threshold) { + if (pAd->ed_tx_stoped == TRUE) { + pAd->ed_tx_stoped = FALSE; + DBGPRINT(RT_DEBUG_WARN, ("\n====\n### %s: EDCCA ed_tx_stoped is set to FALSE\n====\n", __FUNCTION__)); + } + } + + return TRUE; +} + +//this function will be called in multi entry +INT ed_monitor_exit(RTMP_ADAPTER *pAd) +{ + ULONG irqflag=0; + + RTMP_IRQ_LOCK(&pAd->irq_lock, irqflag); + DBGPRINT(RT_DEBUG_OFF, ("@@@ %s : ===>\n", __FUNCTION__)); + + NdisZeroMemory(&pAd->ed_stat[0], sizeof(pAd->ed_stat)); + NdisZeroMemory(&pAd->ch_idle_stat[0], sizeof(pAd->ch_idle_stat)); + NdisZeroMemory(&pAd->ch_busy_stat[0], sizeof(pAd->ch_busy_stat)); + NdisZeroMemory(&pAd->chk_time[0], sizeof(pAd->chk_time)); + NdisZeroMemory(&pAd->ed_trigger_stat[0], sizeof(pAd->ed_trigger_stat)); + NdisZeroMemory(&pAd->ed_silent_stat[0], sizeof(pAd->ed_silent_stat)); + NdisZeroMemory(&pAd->rssi_stat[0], sizeof(pAd->rssi_stat)); + + + pAd->ed_stat_lidx = pAd->ed_stat_sidx = 0; + pAd->ed_trigger_cnt = 0; + pAd->ed_silent_cnt = 0; + //ignore fisrt time's incorrect false cca + pAd->ed_false_cca_cnt = 0; + + pAd->ed_tx_stoped = FALSE; + pAd->ed_threshold_strict = FALSE; + //also clear top level flags + pAd->ed_chk = FALSE; + DBGPRINT(RT_DEBUG_OFF, ("@@@ %s : <===\n", __FUNCTION__)); + RTMP_IRQ_UNLOCK(&pAd->irq_lock, irqflag); + + RTMP_CHIP_ASIC_SET_EDCCA(pAd,FALSE); + + return TRUE; +} + + +// open & muanl cmd will call +INT ed_monitor_init(RTMP_ADAPTER *pAd) +{ + ULONG irqflag=0; + + RTMP_IRQ_LOCK(&pAd->irq_lock, irqflag); + DBGPRINT(RT_DEBUG_OFF, ("@@@ %s : ===>\n", __FUNCTION__)); + NdisZeroMemory(&pAd->ed_stat[0], sizeof(pAd->ed_stat)); + NdisZeroMemory(&pAd->ch_idle_stat[0], sizeof(pAd->ch_idle_stat)); + NdisZeroMemory(&pAd->ch_busy_stat[0], sizeof(pAd->ch_busy_stat)); + NdisZeroMemory(&pAd->chk_time[0], sizeof(pAd->chk_time)); + NdisZeroMemory(&pAd->ed_trigger_stat[0], sizeof(pAd->ed_trigger_stat)); + NdisZeroMemory(&pAd->ed_silent_stat[0], sizeof(pAd->ed_silent_stat)); + NdisZeroMemory(&pAd->rssi_stat[0], sizeof(pAd->rssi_stat)); + + + pAd->ed_stat_lidx = pAd->ed_stat_sidx = 0; + pAd->ed_trigger_cnt = 0; + pAd->ed_silent_cnt = 0; + + // ignore fisrt time's incorrect false cca + pAd->ed_false_cca_cnt = 0; + + pAd->ed_tx_stoped = FALSE; + pAd->ed_threshold_strict = FALSE; + //also set top level flags + if(pAd->ed_chk == 0) //turn on if disabled , otherwise decide by profile + pAd->ed_chk = 1; + + DBGPRINT(RT_DEBUG_OFF, ("@@@ %s : <===\n", __FUNCTION__)); + RTMP_IRQ_UNLOCK(&pAd->irq_lock, irqflag); + + RTMP_CHIP_ASIC_SET_EDCCA(pAd,TRUE); + return TRUE; +} + +#ifdef DBG +INT show_ed_stat_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + unsigned long irqflags=0; + UINT32 ed_stat[ED_STAT_CNT], ed_big_rssi_stat[ED_STAT_CNT], rssi_stat[ED_STAT_CNT]; + UINT32 silent_stat[ED_STAT_CNT], trigger_stat[ED_STAT_CNT]; + UINT32 busy_stat[ED_STAT_CNT], idle_stat[ED_STAT_CNT]; + ULONG chk_time[ED_STAT_CNT]; + INT period_us; + UCHAR start, end, idx; + + RTMP_IRQ_LOCK(&pAd->irq_lock, irqflags); + start = pAd->ed_stat_sidx; + end = pAd->ed_stat_lidx; + NdisMoveMemory(&ed_stat[0], &pAd->ed_stat[0], sizeof(ed_stat)); + NdisMoveMemory(&ed_big_rssi_stat[0], &pAd->ed_big_rssi_stat[0], sizeof(ed_big_rssi_stat)); + NdisMoveMemory(&busy_stat[0], &pAd->ch_busy_stat[0], sizeof(busy_stat)); + NdisMoveMemory(&idle_stat[0], &pAd->ch_idle_stat[0], sizeof(idle_stat)); + NdisMoveMemory(&chk_time[0], &pAd->chk_time[0], sizeof(chk_time)); + NdisMoveMemory(&trigger_stat[0], &pAd->ed_trigger_stat[0], sizeof( +trigger_stat)); + NdisMoveMemory(&silent_stat[0], &pAd->ed_silent_stat[0], sizeof(silent_stat)); + NdisMoveMemory(&rssi_stat[0], &pAd->rssi_stat[0], sizeof( +rssi_stat)); + RTMP_IRQ_UNLOCK(&pAd->irq_lock, irqflags); + +#ifdef CONFIG_AP_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("Dump ChannelBusy Counts, ed_chk=%u, false_cca_threshold=%u, ChkPeriod=%dms, ED_Threshold=%d%%, HitCntForBlockTx=%d\n", + pAd->ed_chk, pAd->ed_false_cca_threshold, pAd->ed_chk_period, pAd->ed_threshold, pAd->ed_block_tx_threshold)); +#endif + period_us = pAd->ed_chk_period * 1000; + DBGPRINT(RT_DEBUG_OFF, ("TimeSlot:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("%ld ", chk_time[idx])); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("Dump ED_STAT\n")); + DBGPRINT(RT_DEBUG_OFF, ("RawCnt:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("%d ", ed_stat[idx])); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("Percent:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("\t%d", (ed_stat[idx] * 100) / period_us)); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("RSSI:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("\t%d", rssi_stat[idx])); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("TriggerCnt:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("\t%d", trigger_stat[idx])); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + + DBGPRINT(RT_DEBUG_OFF, ("SilentCnt:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("\t%d", silent_stat[idx])); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n==========================\n")); + + + DBGPRINT(RT_DEBUG_OFF, ("BIG WBRSSI %% - Over -40dBm \n")); + /*DBGPRINT(RT_DEBUG_OFF, ("RawCnt:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("%d ", ed_2nd_stat[idx])); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + */ + DBGPRINT(RT_DEBUG_OFF, ("Percent:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("\t%d", ed_big_rssi_stat[idx])); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + DBGPRINT(RT_DEBUG_OFF, ("\n==========================\n")); + + + DBGPRINT(RT_DEBUG_OFF, ("Dump CH_IDLE_STAT\n")); + DBGPRINT(RT_DEBUG_OFF, ("RawCnt:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("%d ", idle_stat[idx])); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("Percent:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("\t%d", (idle_stat[idx] *100)/ period_us)); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + DBGPRINT(RT_DEBUG_OFF, ("\n==========================\n")); + + DBGPRINT(RT_DEBUG_OFF, ("Dump CH_BUSY_STAT\n")); + DBGPRINT(RT_DEBUG_OFF, ("RawCnt:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("%d ", busy_stat[idx])); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("Percent:")); + idx = start; + do { + DBGPRINT(RT_DEBUG_OFF, ("\t%d", (busy_stat[idx] *100 )/ period_us)); + INC_RING_INDEX(idx, ED_STAT_CNT); + } while (idx != end); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + DBGPRINT(RT_DEBUG_OFF, ("\n==========================\n")); + + return TRUE; +} +#endif /* DBG */ + +INT Set_RadioOn_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + UCHAR radio; + + radio = simple_strtol(arg, 0, 10); + + pAd->iwpriv_command = FALSE; +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + pAd->iwpriv_command = TRUE; + } +#endif /* MT_MAC */ + + if (radio) + { + MlmeRadioOn(pAd); +#ifdef FT_R1KH_KEEP + pAd->ApCfg.FtTab.FT_RadioOff = FALSE; +#endif/* FT_R1KH_KEEP */ + DBGPRINT(RT_DEBUG_OFF, ("==>Set_RadioOn_Proc (ON)\n")); + } + else + { + MlmeRadioOff(pAd); +#ifdef FT_R1KH_KEEP + pAd->ApCfg.FtTab.FT_RadioOff = TRUE; +#endif/* FT_R1KH_KEEP */ + DBGPRINT(RT_DEBUG_OFF, ("==>Set_RadioOn_Proc (OFF)\n")); + } + + return TRUE; +} + +#if defined(CUSTOMER_DCC_FEATURE) || defined(BAND_STEERING) +VOID EnableRadioChstats( + IN PRTMP_ADAPTER pAd) +{ + UINT32 mac_val; + + /* Clear previous status */ + RTMP_IO_READ32(pAd, MIB_MSCR, &mac_val); + DBGPRINT(RT_DEBUG_OFF, ("MIB Status Control=0x%x\n", mac_val)); + /*mt7603_set_ed_cca(pAd, 1);*/ + RTMP_IO_READ32(pAd, MIB_MSDR9, &mac_val); // Ch Busy Time + RTMP_IO_READ32(pAd, MIB_MSDR18, &mac_val); // p_ED Time + AsicGetRxStat(pAd, HQA_RX_RESET_PHY_COUNT); + +} +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_cmd.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_cmd.c new file mode 100644 index 000000000..c053649a0 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_cmd.c @@ -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-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; + ULONG flag; + + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + DBGPRINT(RT_DEBUG_TRACE, ("--->RTEnqueueInternalCmd - NIC is not exist!!\n")); + return NDIS_STATUS_FAILURE; + } + + 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); + RTMP_SPIN_LOCK_IRQSAVE(&pAd->CmdQLock,&flag); + 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); + RTMP_SPIN_UNLOCK_IRQRESTORE(&pAd->CmdQLock,&flag); + + if (status == NDIS_STATUS_FAILURE) + { + if (cmdqelmt->buffer) + os_free_mem(pAd, cmdqelmt->buffer); + os_free_mem(pAd, cmdqelmt); + } + else + RTCMDUp(&pAd->cmdQTask); + } + return(NDIS_STATUS_SUCCESS); +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_cs.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_cs.c new file mode 100644 index 000000000..174b1f1f2 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_cs.c @@ -0,0 +1,880 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + cmm_cs.c + + Abstract: + Carrier Sensing related functions + + Revision History: + Who When What + --------------------------------------------------------------------- +*/ +#include "rt_config.h" + +#ifdef CARRIER_DETECTION_SUPPORT +static ULONG time[20]; +static ULONG idle[20]; +static ULONG busy[20]; +static ULONG cd_idx=0; + +static void ToneRadarProgram(PRTMP_ADAPTER pAd); + +#ifdef CONFIG_AP_SUPPORT +static inline VOID CarrierDetectionResetStatus(PRTMP_ADAPTER pAd) +{ + if(pAd->chipCap.carrier_func == TONE_RADAR_V3) + { + RTMP_BBP_IO_WRITE32(pAd, TR_R1, 0x3); + } + else + { + RTMP_CARRIER_IO_WRITE8(pAd, 1, 1); + } +} + +static inline VOID CarrierDetectionStatusGet(PRTMP_ADAPTER pAd, + PUINT8 pStatus) +{ + *pStatus = 0; + + if(pAd->chipCap.carrier_func == TONE_RADAR_V3) + { + UINT32 mac_value = 0; + RTMP_BBP_IO_READ32(pAd, TR_R1, &mac_value); + *pStatus = (UINT8) mac_value; + } + else + { + RTMP_CARRIER_IO_READ8(pAd, 1, pStatus); + } +} + +static inline VOID CarrierDetectionEnable(PRTMP_ADAPTER pAd, + BOOLEAN bEnable) +{ + if(pAd->chipCap.carrier_func == TONE_RADAR_V3) + { + RTMP_BBP_IO_WRITE32(pAd, TR_R0, bEnable); + } + else + { + RTMP_CARRIER_IO_WRITE8(pAd, 0, bEnable); + } +} + + +/* + ========================================================================== + 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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + UINT Enable; + + if (apidx != MAIN_MBSSID) + return FALSE; + + Enable = (UINT) simple_strtol(arg, 0, 10); + + pAd->CommonCfg.CarrierDetect.Enable = (BOOLEAN)(Enable == 0 ? FALSE : TRUE); + + RTMP_CHIP_RADAR_GLRT_COMPENSATE(pAd); + RTMP_CHIP_CCK_MRC_STATUS_CTRL(pAd); + + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + CarrierDetectionStart(pAd); + else + CarrierDetectionStop(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: %s\n", __FUNCTION__, + pAd->CommonCfg.CarrierDetect.Enable == TRUE ? "Enable Carrier Detection":"Disable Carrier Detection")); + + return TRUE; +} +#endif /* CONFIG_AP_SUPPORT */ + + +/* + ========================================================================== + Description: + When h/w interrupt is not available for CS, this function monitor necessary parameters that determine the CS + state periodically. (every 100ms) + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + ========================================================================== +*/ +VOID CarrierDetectionPeriodicStateCtrl( + IN PRTMP_ADAPTER pAd) +{ + PCARRIER_DETECTION_STRUCT pCarrierDetect = &pAd->CommonCfg.CarrierDetect; + CD_STATE *pCD_State = &pCarrierDetect->CD_State; + ULONG *pOneSecIntCount = &pCarrierDetect->OneSecIntCount; + +#ifdef CONFIG_ATE + /* Nothing to do in ATE mode */ + if (ATE_ON(pAd)) + return; +#endif /* CONFIG_ATE */ + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return; + } + + if (pCarrierDetect->bCsInit == FALSE) + return; + + if (pAd->chipCap.carrier_func == TONE_RADAR_V3) + { + UINT8 TrStatus = 0; + + CarrierDetectionStatusGet(pAd, &TrStatus); + if (TrStatus) + { + if (*pCD_State == CD_NORMAL) + { + DBGPRINT(RT_DEBUG_OFF, + ("Carrier Detected ! (TrStatus = 0x%x)\n", TrStatus)); + *pCD_State = CD_SILENCE; + /* stop all TX actions including Beacon sending.*/ + AsicDisableSync(pAd); + } + *pOneSecIntCount = pCarrierDetect->CarrierGoneThreshold; + CarrierDetectionResetStatus(pAd); + + } + else + *pOneSecIntCount = 0; + + /*CarrierDetectionResetStatus(pAd);*/ + } + +#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT + + if (pAd->chipCap.carrier_func == TONE_RADAR_V2) + { + CARRIER_DETECT_PARAM CarrDetectParam; + + /* tell firmware to prepare Recheck and RadarToneCount */ + AsicSendCommandToMcu(pAd, CD_CHECKOUT_MCU_CMD, 0xff, 0x00, 0x00, FALSE); + /* Debug */ + if (pAd->CommonCfg.CarrierDetect.Debug == RT_DEBUG_TRACE) + { + CARRIER_DETECT_DEBUG CarrDetectDebug; + RTUSBMultiRead(pAd, 0x4CB0, (PUCHAR) &CarrDetectDebug, sizeof(CarrDetectDebug)); + printk("delta_div = 0x%02X, rRadarToneCount = %u, Recheck = %u, Criteria = %u, Threshold = 0x%08X, VGA_Mask = 0x%04X\n", + CarrDetectDebug.delta_div, + CarrDetectDebug.RadarToneCount, + CarrDetectDebug.ReCheck, + CarrDetectDebug.Criteria << 6, /* ms -> 16us*/ + CarrDetectDebug.Threshold, + CarrDetectDebug.VGA_Mask); + } + + RTUSBMultiRead(pAd, RADAR_TONE_COUNT, (PUCHAR) &CarrDetectParam, sizeof(CarrDetectParam)); + switch(*pCD_State) + { + case CD_NORMAL: + if (CarrDetectParam.ReCheck == 0) + { + *pCD_State = CD_SILENCE; + if (pAd->CommonCfg.CarrierDetect.Debug != RT_DEBUG_TRACE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Carrier Detected\n")); + + /* stop all TX actions including Beacon sending.*/ + AsicDisableSync(pAd); + } + else + printk("Carrier Detected\n"); + } + break; + + case CD_SILENCE: + *pOneSecIntCount += CarrDetectParam.RadarToneCount; + break; + + default: + break; + } +} +#endif /* CARRIER_DETECTION_FIRMWARE_SUPPORT */ + +} + + +/* + ========================================================================== + Description: + When there is no f/w taking care of CS operation, this function depends on h/w interrupts for every possible carrier + tone to judge the CS state + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + ========================================================================== +*/ +VOID RTMPHandleRadarInterrupt(PRTMP_ADAPTER pAd) +{ + UINT32 value, delta; + UCHAR bbp=0; + PCARRIER_DETECTION_STRUCT pCarrierDetect = &pAd->CommonCfg.CarrierDetect; + + if (pAd->chipCap.carrier_func > TONE_RADAR_V2) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("RTMPHandleRadarInterrupt()\n")); + RTMP_IO_READ32(pAd, PBF_LIFE_TIMER, &value); + RTMP_IO_READ32(pAd, CH_IDLE_STA, &pCarrierDetect->idle_time); + pCarrierDetect->busy_time = AsicGetChBusyCnt(pAd, 0); + delta = (value >> 4) - pCarrierDetect->TimeStamp; + pCarrierDetect->TimeStamp = value >> 4; + pCarrierDetect->OneSecIntCount++; + + if(pAd->chipCap.carrier_func==TONE_RADAR_V2) + { +#ifdef RTMP_BBP + CarrierDetectionStatusGet(pAd, &bbp); + if (!(bbp & 0x1)) + return; + else +#endif /* RTMP_BBP */ + { + UINT32 RadarInt = 0; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + RadarInt = RLT_RadarInt; +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + RadarInt = RTMP_RadarInt; +#endif /* RTMP_MAC */ + /* Disable carrier detection and clear the status bit*/ + CarrierDetectionEnable(pAd, 0); + CarrierDetectionResetStatus(pAd); + /* Clear interrupt */ + RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, RadarInt); + } + } + + if (pCarrierDetect->Debug) + { + if (cd_idx < 20) + { + time[cd_idx] = delta; + idle[cd_idx] = pCarrierDetect->idle_time; + busy[cd_idx] = pCarrierDetect->busy_time; + cd_idx++; + } + else + { + int i; + pCarrierDetect->Debug = 0; + for (i = 0; i < 20; i++) + { + printk("%3d %4ld %ld %ld\n", i, time[i], idle[i], busy[i]); + } + cd_idx = 0; + + } + } + + if (pCarrierDetect->CD_State == CD_NORMAL) + { + if ((delta < pCarrierDetect->criteria) && (pCarrierDetect->recheck)) + pCarrierDetect->recheck --; + else + pCarrierDetect->recheck = pCarrierDetect->recheck1; + + if (pCarrierDetect->recheck == 0) + { + /* declare carrier sense*/ + pCarrierDetect->CD_State = CD_SILENCE; + + if (pCarrierDetect->Debug != RT_DEBUG_TRACE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Carrier Detected\n")); + + /* stop all TX actions including Beacon sending.*/ + AsicDisableSync(pAd); + } + else + { + printk("Carrier Detected\n"); + } + } + } + + if(pAd->chipCap.carrier_func == TONE_RADAR_V2) + { + CarrierDetectionStatusGet(pAd, &bbp); + + if (bbp & 0x1) + { + DBGPRINT(RT_DEBUG_ERROR, ("CS bit not cleared!!!\n")); + CarrierDetectionResetStatus(pAd); + } + /* re-enable carrier detection */ + CarrierDetectionEnable(pAd, 1); + } + else if(pAd->chipCap.carrier_func == TONE_RADAR_V1 && + pCarrierDetect->Enable) + { + ToneRadarProgram(pAd); + } +} + +/* + ========================================================================== + Description: + Reset CS state to NORMAL state. + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + ========================================================================== +*/ +INT CarrierDetectReset( + IN PRTMP_ADAPTER pAd) +{ + pAd->CommonCfg.CarrierDetect.CD_State = CD_NORMAL; + return 0; +} + +/* + ========================================================================== + Description: + Criteria in CS is a timing difference threshold for a pair of carrier tones. This function is a ioctl uesed to adjust the + Criteria. (unit: 16us) + + Arguments: + pAd Pointer to our adapter + arg Pointer to the ioctl argument + + Return Value: + None + + Note: + ========================================================================== +*/ +INT Set_CarrierCriteria_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->CommonCfg.CarrierDetect.VGA_Mask = simple_strtol(arg, 0, 10); + pAd->CommonCfg.CarrierDetect.Packet_End_Mask = simple_strtol(arg, 0, 10); + pAd->CommonCfg.CarrierDetect.Rx_PE_Mask = simple_strtol(arg, 0, 10); + printk("CarrMask = %u(%x)\n", pAd->CommonCfg.CarrierDetect.VGA_Mask, pAd->CommonCfg.CarrierDetect.VGA_Mask); + CarrierDetectionStart(pAd); + + return TRUE; +} + +/* + ========================================================================== + Description: + Initialize CS parameters. + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + ========================================================================== +*/ +VOID CSInit( + IN PRTMP_ADAPTER pAd) +{ + PCARRIER_DETECTION_STRUCT pCarrierDetect = &pAd->CommonCfg.CarrierDetect; + + pCarrierDetect->TimeStamp = 0; + pCarrierDetect->recheck = pCarrierDetect->recheck1; + pCarrierDetect->OneSecIntCount = 0; + pCarrierDetect->bCsInit = FALSE; +} + +/* + ========================================================================== + Description: + To trigger CS start + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + ========================================================================== +*/ +VOID CarrierDetectionStart(PRTMP_ADAPTER pAd) +{ + /*ULONG Value;*/ + /* Enable Bandwidth usage monitor*/ + DBGPRINT(RT_DEBUG_TRACE, ("CarrierDetectionStart\n")); + /*RTMP_IO_READ32(pAd, CH_TIME_CFG, &Value);*/ + /*RTMP_IO_WRITE32(pAd, CH_TIME_CFG, Value | 0x1f); */ + + /* Init Carrier Detect*/ + if (pAd->CommonCfg.CarrierDetect.Enable) + { + CSInit(pAd); + ToneRadarProgram(pAd); +#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT + { + USHORT criteria = (USHORT) (pAd->CommonCfg.CarrierDetect.criteria >> 6); /* convert unit from 16us to 1ms:(2^4 /2^10) */ + RTUSBMultiWrite(pAd, CD_CRITERIA, (PUCHAR) &criteria, 2, FALSE); + RTMP_IO_WRITE8(pAd, CD_CHECK_COUNT, pAd->CommonCfg.CarrierDetect.recheck1); + AsicSendCommandToMcu(pAd, CD_ONOFF_MCU_CMD, 0xff, 0x01, 0x00, FALSE); + } +#else +#ifndef MT760x + /* 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 /* MT760x */ +#endif /* CARRIER_DETECTION_FIRMWARE_SUPPORT */ + pAd->CommonCfg.CarrierDetect.bCsInit = TRUE; + } +} + +/* + ========================================================================== + Description: + To stop CS + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + ========================================================================== +*/ +VOID CarrierDetectionStop(IN PRTMP_ADAPTER pAd) +{ + CarrierDetectReset(pAd); + CarrierDetectionEnable(pAd, 0); +#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT + /* Stop firmware CS action */ + AsicSendCommandToMcu(pAd, CD_ONOFF_MCU_CMD, 0xff, 0x00, 0x00, FALSE); +#endif /* CARRIER_DETECTION_FIRMWARE_SUPPORT */ + 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 */ + CarrierDetectionEnable(pAd, 1); +} + +/* + ========================================================================== + Description: + To program CS v3 related BBP registers (CS initialization) + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + ========================================================================== +*/ +VOID ToneRadarProgram_v3(PRTMP_ADAPTER pAd, ULONG threshold) +{ + /* + Carrier Sense (Tone Radar) BBP initialization + (MT7650 Carrier sense programming guide_v1_20120824.docx) + */ + DBGPRINT(RT_DEBUG_TRACE, ("ToneRadarProgram v3\n")); + CarrierDetectionEnable(pAd, 0); + RTMP_BBP_IO_WRITE32(pAd, TR_R2, 0x002d002d); + RTMP_BBP_IO_WRITE32(pAd, TR_R3, 0x0003002d); + RTMP_BBP_IO_WRITE32(pAd, TR_R5, 0x80000000); + RTMP_BBP_IO_WRITE32(pAd, TR_R6, 0x80100000); + CarrierDetectionEnable(pAd, 1); +} + + +#endif /* CARRIER_DETECTION_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_data.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_data.c new file mode 100644 index 000000000..629010890 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_data.c @@ -0,0 +1,5293 @@ +/**************************************************************************** + * 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}; + + +// UserPriority To AccessCategory mapping +UCHAR WMM_UP2AC_MAP[8] = {QID_AC_BE, QID_AC_BK, + QID_AC_BK, QID_AC_BE, + QID_AC_VI, QID_AC_VI, + QID_AC_VO, QID_AC_VO}; + +struct WCID_TABLE{ + DL_LIST list; + UCHAR wcid; +}; +static struct WCID_TABLE wcid_table[MAX_LEN_OF_TR_TABLE]; + +#ifdef SW_ATF_SUPPORT +#define atfFreeTimer 0xbe000508 +#define freeTimerMaxCnt 65535 +#endif + +#ifdef DBG_DIAGNOSE +VOID dbg_diag_deque_log(RTMP_ADAPTER *pAd) +{ + struct dbg_diag_info *diag_info; + UCHAR QueIdx = 0; + + diag_info = &pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx]; + +#ifdef RTMP_MAC_PCI +#ifdef DBG_TX_RING_DEPTH + if ((pAd->DiagStruct.diag_cond & DIAG_COND_TX_RING_DEPTH) != DIAG_COND_TX_RING_DEPTH) + { + for (QueIdx = 0; QueIdx < 4 /* 4 */; QueIdx++) + { + UINT free_cnt, desc_num; + UINT32 dma_id, cpu_id, hw_cnt; + + free_cnt = GET_TXRING_FREENO(pAd, QueIdx); + RTMP_IO_READ32(pAd, pAd->TxRing[QueIdx].hw_didx_addr, &dma_id); + RTMP_IO_READ32(pAd, pAd->TxRing[QueIdx].hw_cidx_addr, &cpu_id); + if (dma_id > cpu_id) + hw_cnt = TX_RING_SIZE - dma_id + cpu_id; + else if (cpu_id > dma_id) + hw_cnt = cpu_id - dma_id; + else + hw_cnt = ((free_cnt > 0) ? 0 : TX_RING_SIZE); + + hw_cnt = ((hw_cnt <=15) ? hw_cnt : 15); + diag_info->TxDescCnt[QueIdx][hw_cnt]++; + } + } +#endif /* DBG_TX_RING_DEPTH */ + +#ifdef MT_MAC +#ifdef DBG_PSE_DEPTH + if ((pAd->DiagStruct.diag_cond & DIAG_COND_PSE_DEPTH) != DIAG_COND_PSE_DEPTH) + { + UINT32 mac_val; + RTMP_IO_READ32(pAd, 0x8148, &mac_val); + mac_val = ((mac_val & 0xfff) / 13); + if (mac_val > 48) + mac_val = 49; + diag_info->pse_pg_cnt[mac_val]++; + } +#endif /* DBG_PSE_DEPTH */ +#endif /* MT_MAC */ +#endif /* RTMP_MAC_PCI */ + +#ifdef DBG_TXQ_DEPTH + if ((pAd->DiagStruct.diag_cond & DIAG_COND_TXQ_DEPTH) != DIAG_COND_TXQ_DEPTH) + { + if ((pAd->DiagStruct.wcid > 0) && (pAd->DiagStruct.wcid < MAX_LEN_OF_TR_TABLE)) { + STA_TR_ENTRY *tr_entry = &pAd->MacTab.tr_entry[pAd->DiagStruct.wcid]; + UCHAR swq_cnt; + + for (QueIdx = 0; QueIdx < 4; QueIdx++) + { + if (tr_entry->tx_queue[QueIdx].Number <= 7) + swq_cnt = tr_entry->tx_queue[QueIdx].Number; + else + swq_cnt = 8; + diag_info->TxSWQueCnt[QueIdx][swq_cnt]++; + } + } + } +#endif /* DBG_TXQ_DEPTH */ +} +#endif /* DBG_DIAGNOSE */ + +/*Nobody uses it currently*/ + +VOID dump_rxblk(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + DBGPRINT(RT_DEBUG_TRACE,("Dump RX_BLK Structure:\n")); + + DBGPRINT(RT_DEBUG_TRACE,("\tHW rx info:\n")); + hex_dump("RawData", &pRxBlk->hw_rx_info[0], RXD_SIZE); + + DBGPRINT(RT_DEBUG_TRACE,("\tData Pointer info:\n")); + +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (pAd->chipCap.hif_type == HIF_RTMP || pAd->chipCap.hif_type == HIF_RLT) { + DBGPRINT(RT_DEBUG_TRACE,("\t\tpRxInfo=0x%p\n", pRxBlk->pRxInfo)); + dump_rxinfo(pAd, pRxBlk->pRxInfo); +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + DBGPRINT(RT_DEBUG_TRACE,("\t\tpRxFceInfo=0x%p\n", pRxBlk->pRxFceInfo)); + dumpRxFCEInfo(pAd, pRxBlk->pRxFceInfo); + } +#endif /* RLT_MAC */ + DBGPRINT(RT_DEBUG_TRACE,("\t\tpRxWI=0x%p\n", pRxBlk->pRxWI)); + dump_rmac_info(pAd, (UCHAR *)pRxBlk->pRxWI); + } +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + +#ifdef MT_MAC +#ifdef DBG + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_TRACE,("\t\trmac_info=0x%p\n", pRxBlk->rmac_info)); + dump_rmac_info(pAd, pRxBlk->rmac_info); + } +#endif /* DBG */ +#endif /* MT_MAC */ + + DBGPRINT(RT_DEBUG_TRACE,("\t\tpRxPacket=0x%p, MPDUtotalByteCnt=%d\n", pRxBlk->pRxPacket, pRxBlk->MPDUtotalByteCnt)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tpHeader=0x%p\n", pRxBlk->pHeader)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tpData=0x%p\n", pRxBlk->pData)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tDataSize=%d\n", pRxBlk->DataSize)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tFlags=0x%x\n", pRxBlk->Flags)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tUserPriority=%d\n", pRxBlk->UserPriority)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tOpMode=%d\n", pRxBlk->OpMode)); + + DBGPRINT(RT_DEBUG_TRACE,("\tMirror Info from RMAC Info:\n")); + DBGPRINT(RT_DEBUG_TRACE,("\t\tWCID=%d\n", pRxBlk->wcid)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tTID=%d\n", pRxBlk->TID)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tKey_idx=%d\n", pRxBlk->key_idx)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tBSS_IDX=%d\n", pRxBlk->bss_idx)); +#if defined(RLT_MAC) || defined(RTMP_MAC) + if (pAd->chipCap.hif_type == HIF_RTMP || pAd->chipCap.hif_type == HIF_RLT) { + DBGPRINT(RT_DEBUG_TRACE,("\t\tPhyMode=%d(%s)\n", + pRxBlk->rx_rate.field.MODE, + get_phymode_str(pRxBlk->rx_rate.field.MODE))); + DBGPRINT(RT_DEBUG_TRACE,("\t\tMCS=%d\n", pRxBlk->rx_rate.field.MCS)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tBW=%d\n", pRxBlk->rx_rate.field.BW)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tSGI=%d\n", pRxBlk->rx_rate.field.ShortGI)); + DBGPRINT(RT_DEBUG_TRACE,("\t\tSTBC=%d\n", pRxBlk->rx_rate.field.STBC)); +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + DBGPRINT(RT_DEBUG_TRACE,("\t\tLDPC=%d\n", pRxBlk->rx_rate.field.ldpc)); +#endif /* RLT_MAC */ + DBGPRINT(RT_DEBUG_TRACE,("\t\tRSSI=%d:%d:%d\n", + pRxBlk->rx_signal.raw_rssi[0], pRxBlk->rx_signal.raw_rssi[1], + pRxBlk->rx_signal.raw_rssi[2])); + DBGPRINT(RT_DEBUG_TRACE,("\t\tSNR=%d:%d:%d\n", + pRxBlk->rx_signal.raw_snr[0], pRxBlk->rx_signal.raw_snr[1], + pRxBlk->rx_signal.raw_snr[2])); + DBGPRINT(RT_DEBUG_TRACE,("\t\tFreqOffset=%d\n", + pRxBlk->rx_signal.freq_offset)); + } +#endif /* defined(RLT_MAC) || defined(RTMP_MAC) */ + + //hex_dump("Dump RxPacket in dump_rxblk", (UCHAR *)pRxBlk->pHeader, pRxBlk->MPDUtotalByteCnt > 512 ? 512 : pRxBlk->MPDUtotalByteCnt); +} + + +#ifdef MT_MAC +/* + 1'b0: the related GROUP is not present + 1'b1: the related GROUP is present + + bit[0]: indicates GROUP1 (DW8~DW11) + bit[1]: indicates GROUP2 (DW12~DW13) + bit[2]: indicates GROUP3 (DW14~DW19) + bit[3]: indicates GROUP4 (DW4~DW7) +*/ +//#define RMAC_INFO_GRP_1_SIZE 16 +//#define RMAC_INFO_GRP_2_SIZE 8 +//#define RMAC_INFO_GRP_3_SIZE 24 +//#define RMAC_INFO_GRP_4_SIZE 16 + +static INT32 RMACInfoGrpToLen[]={ + /* 0: base only */ + RMAC_INFO_BASE_SIZE, + /* 1: [bit 0] base + group 1 */ + RMAC_INFO_BASE_SIZE + RMAC_INFO_GRP_1_SIZE, + /* 2: [bit 1] base + group 2 */ + RMAC_INFO_BASE_SIZE + RMAC_INFO_GRP_2_SIZE, + /* 3: [bit 0 + bit 1] base + group 1 + group 2 */ + RMAC_INFO_BASE_SIZE + RMAC_INFO_GRP_1_SIZE + RMAC_INFO_GRP_2_SIZE, + /* 4: [bit 2] base + group 3 */ + RMAC_INFO_BASE_SIZE + RMAC_INFO_GRP_3_SIZE, + /* 5: [bit 0 + bit 2] base + group 1 + group 3 */ + RMAC_INFO_BASE_SIZE + RMAC_INFO_GRP_1_SIZE + RMAC_INFO_GRP_3_SIZE, + /* 6: [bit 1 + bit 2] base + group 2 + group 3 */ + RMAC_INFO_BASE_SIZE + RMAC_INFO_GRP_2_SIZE + RMAC_INFO_GRP_3_SIZE, + /* 7: [bit 0 + bit 1 + bit 2] base + group 1 + group 2 + group 3 */ + RMAC_INFO_BASE_SIZE + RMAC_INFO_GRP_1_SIZE + RMAC_INFO_GRP_2_SIZE + RMAC_INFO_GRP_3_SIZE, + /* 8: [bit 3 ] base + group 4 */ + RMAC_INFO_BASE_SIZE + RMAC_INFO_GRP_4_SIZE, + /* 9: [bit 0 + bit 3 ] base + group 1 + group 4 */ + RMAC_INFO_BASE_SIZE + RMAC_INFO_GRP_1_SIZE + RMAC_INFO_GRP_4_SIZE, + /* 10: [bit 1 + bit 3 ] base + group 2 + group 4 */ + RMAC_INFO_BASE_SIZE + RMAC_INFO_GRP_2_SIZE + RMAC_INFO_GRP_4_SIZE, + /* 11: [bit 0 + bit 1 + bit 3 ] base + group 1 + group 2 + group 4 */ + RMAC_INFO_BASE_SIZE + RMAC_INFO_GRP_1_SIZE + RMAC_INFO_GRP_2_SIZE + RMAC_INFO_GRP_4_SIZE, + /* 12: [bit 2 + bit 3 ] base + group 3 + group 4 */ + RMAC_INFO_BASE_SIZE + RMAC_INFO_GRP_3_SIZE + RMAC_INFO_GRP_4_SIZE, + /* 13: [bit 0 + bit 2 + bit 3 ] base + group 1 + group 3 + group 4 */ + RMAC_INFO_BASE_SIZE + RMAC_INFO_GRP_1_SIZE + RMAC_INFO_GRP_3_SIZE + RMAC_INFO_GRP_4_SIZE, + /* 14: [bit 1 + bit 2 + bit 3 ] base + group 2 + group 3 + group 4 */ + RMAC_INFO_BASE_SIZE + RMAC_INFO_GRP_2_SIZE + RMAC_INFO_GRP_3_SIZE + RMAC_INFO_GRP_4_SIZE, + /* 15: [bit 0 + bit 1 + bit 2 + bit 3 ] base + group 1 + group 2 + group 3 + group 4 */ + RMAC_INFO_BASE_SIZE + RMAC_INFO_GRP_1_SIZE + RMAC_INFO_GRP_2_SIZE + RMAC_INFO_GRP_3_SIZE + RMAC_INFO_GRP_4_SIZE, +}; + + +#ifdef MT_MAC +VOID ParseRxVPacket(RTMP_ADAPTER *pAd, UINT32 Type, RX_BLK *RxBlk, UCHAR *Data) +{ + //RXV_DWORD0 *DW0 = NULL; + RXV_DWORD1 *DW1 = NULL; + RX_VECTOR1_1ST_CYCLE *RXV1_1ST_CYCLE = NULL; + //RX_VECTOR1_2ND_CYCLE *RXV1_2ND_CYCLE = NULL; +#ifdef CONFIG_QA + RX_VECTOR1_3TH_CYCLE *RXV1_3TH_CYCLE = NULL; +#endif /* CONFIG_QA */ + RX_VECTOR1_4TH_CYCLE *RXV1_4TH_CYCLE = NULL; +//#ifdef CONFIG_QA + RX_VECTOR1_5TH_CYCLE *RXV1_5TH_CYCLE = NULL; +//#endif /* CONFIG_QA */ + + //RX_VECTOR1_6TH_CYCLE *RXV1_6TH_CYCLE = NULL; + RX_VECTOR2_1ST_CYCLE *RXV2_1ST_CYCLE = NULL; + RX_VECTOR2_2ND_CYCLE *RXV2_2ND_CYCLE = NULL; + RX_VECTOR2_3TH_CYCLE *RXV2_3TH_CYCLE = NULL; + + if (Type == RMAC_RX_PKT_TYPE_RX_NORMAL) + { + RXV1_1ST_CYCLE = (RX_VECTOR1_1ST_CYCLE *)Data; + //RXV1_2ND_CYCLE = (RX_VECTOR1_2ND_CYCLE *)(Data + 4); +#ifdef CONFIG_QA + RXV1_3TH_CYCLE = (RX_VECTOR1_3TH_CYCLE *)(Data + 8); +#endif /* CONFIG_QA */ + RXV1_4TH_CYCLE = (RX_VECTOR1_4TH_CYCLE *)(Data + 12); +//#ifdef CONFIG_QA + RXV1_5TH_CYCLE = (RX_VECTOR1_5TH_CYCLE *)(Data + 16); +//#endif /* CONFIG_QA */ + + //RXV1_6TH_CYCLE = (RX_VECTOR1_6TH_CYCLE *)(Data + 20); + RXV2_2ND_CYCLE = (RX_VECTOR2_2ND_CYCLE *)(Data + 28); + } + else if (Type == RMAC_RX_PKT_TYPE_RX_TXRXV) + { + //DW0 = (RXV_DWORD0 *)Data; + DW1 = (RXV_DWORD1 *)(Data + 4); + RXV1_1ST_CYCLE = (RX_VECTOR1_1ST_CYCLE *)(Data + 8); + //RXV1_2ND_CYCLE = (RX_VECTOR1_2ND_CYCLE *)(Data + 12); +#ifdef CONFIG_QA + RXV1_3TH_CYCLE = (RX_VECTOR1_3TH_CYCLE *)(Data + 16); +#endif /* CONFIG_QA */ + RXV1_4TH_CYCLE = (RX_VECTOR1_4TH_CYCLE *)(Data + 20); +//#ifdef CONFIG_QA + RXV1_5TH_CYCLE = (RX_VECTOR1_5TH_CYCLE *)(Data + 24); +//#endif /* CONFIG_QA */ + + //RXV1_6TH_CYCLE = (RX_VECTOR1_6TH_CYCLE *)(Data + 28); + RXV2_1ST_CYCLE = (RX_VECTOR2_1ST_CYCLE *)(Data + 32); + RXV2_2ND_CYCLE = (RX_VECTOR2_2ND_CYCLE *)(Data + 36); + RXV2_3TH_CYCLE = (RX_VECTOR2_3TH_CYCLE *)(Data + 40); + + RxBlk->rxv2_cyc1 = *(UINT32 *)RXV2_1ST_CYCLE; + RxBlk->rxv2_cyc2 = *(UINT32 *)RXV2_2ND_CYCLE; + RxBlk->rxv2_cyc3 = *(UINT32 *)RXV2_3TH_CYCLE; + pAd->rxv2_cyc3[(DW1->RxvSn % 10)] = RxBlk->rxv2_cyc3; + { + MAC_TABLE_ENTRY *pEntry = MacTableLookup(pAd, Data); + if (pEntry != NULL) + pEntry->rxv2_cyc3[(DW1->RxvSn % 10)] = RxBlk->rxv2_cyc3; + } +#ifdef CONFIG_QA + pAd->ATECtrl.RCPI0 = RXV1_3TH_CYCLE->Rcpi0; + pAd->ATECtrl.RCPI1 = RXV1_3TH_CYCLE->Rcpi1; + if(RXV1_5TH_CYCLE) { + pAd->ATECtrl.FreqOffsetFromRx = RXV1_5TH_CYCLE->FoE; + pAd->ATECtrl.SNR0 = RXV1_5TH_CYCLE->LTF_SNR0; + } + if(RXV2_2ND_CYCLE) + pAd->ATECtrl.SNR1 = RXV2_2ND_CYCLE->OfdmLtfSNR1; + pAd->ATECtrl.RSSI0 = RXV1_3TH_CYCLE->Rcpi0/2 - 110; + pAd->ATECtrl.RSSI1 = RXV1_3TH_CYCLE->Rcpi1/2 - 110; +#endif /* CONFIG_QA */ + } + else + { + DBGPRINT(RT_DEBUG_ERROR,("%s(): invalid Type %u\n",__FUNCTION__,Type)); + return; /* return here to avoid dereferencing NULL pointer below */ + } + + //RxBlk->rx_signal.raw_rssi[0] = (RXV1_3TH_CYCLE->Rcpi0 - 220) / 2; + //RxBlk->rx_signal.raw_rssi[1] = (RXV1_3TH_CYCLE->Rcpi1 - 220) / 2; + RxBlk->rx_signal.raw_rssi[0] = (CHAR)RXV1_4TH_CYCLE->IBRssi0; + RxBlk->rx_signal.raw_rssi[1] = (CHAR)RXV1_4TH_CYCLE->IBRssi1; +//#ifdef CUSTOMER_DCC_FEATURE + if(RXV1_5TH_CYCLE) + RxBlk->rx_signal.raw_snr[0] = RXV1_5TH_CYCLE->LTF_SNR0; + if(RXV2_2ND_CYCLE) + RxBlk->rx_signal.raw_snr[1] = RXV2_2ND_CYCLE->OfdmLtfSNR1; +//#endif + //RxBlk->rx_signal.raw_snr[0] = rxwi_n->bbp_rxinfo[0]; + //RxBlk->rx_signal.raw_snr[1] = rxwi_n->bbp_rxinfo[1]; + //RxBlk->rx_signal.freq_offset = rxwi_n->bbp_rxinfo[4]; + + RxBlk->rx_rate.field.MODE = RXV1_1ST_CYCLE->TxMode; + RxBlk->rx_rate.field.MCS = RXV1_1ST_CYCLE->TxRate; + RxBlk->rx_rate.field.ldpc = RXV1_1ST_CYCLE->HtAdCode; + RxBlk->rx_rate.field.BW = RXV1_1ST_CYCLE->FrMode; + RxBlk->rx_rate.field.STBC = RXV1_1ST_CYCLE->HtStbc; + RxBlk->rx_rate.field.ShortGI = RXV1_1ST_CYCLE->HtShortGi; +} + + +static inline INT32 mt_rx_info_2_blk( + RTMP_ADAPTER *pAd, + RX_BLK *pRxBlk, + PNDIS_PACKET pRxPacket, + INT32 pkt_type) +{ + UCHAR *RMACInfo, *Pos; + INT32 RMACInfoLen; + struct rxd_base_struct *rx_base; + //RXD_GRP4_STRUCT *RxdGrp4 = NULL; + RXD_GRP1_STRUCT *RxdGrp1 = NULL; + RXD_GRP2_STRUCT *RxdGrp2 = NULL; + RXD_GRP3_STRUCT *RxdGrp3 = NULL; + + pRxBlk->pRxInfo = (RXINFO_STRUC *)(&pRxBlk->hw_rx_info[RXINFO_OFFSET]); + RMACInfo = (UCHAR *)(GET_OS_PKT_DATAPTR(pRxPacket)); + Pos = RMACInfo; + pRxBlk->rmac_info = RMACInfo; + rx_base = (struct rxd_base_struct *)RMACInfo; + + Pos += RMAC_INFO_BASE_SIZE; + + if (rx_base->rxd_0.grp_vld & RXS_GROUP4) + { + //RxdGrp4 = (RXD_GRP4_STRUCT *)Pos; + Pos += RMAC_INFO_GRP_4_SIZE; + } + + if (rx_base->rxd_0.grp_vld & RXS_GROUP1) + { + RxdGrp1 = (RXD_GRP1_STRUCT *)Pos; + Pos += RMAC_INFO_GRP_1_SIZE; + } + + if (rx_base->rxd_0.grp_vld & RXS_GROUP2) + { + RxdGrp2 = (RXD_GRP2_STRUCT *)Pos; + Pos += RMAC_INFO_GRP_2_SIZE; + } + + if (rx_base->rxd_0.grp_vld & RXS_GROUP3) + { + RxdGrp3 = (RXD_GRP3_STRUCT *)Pos; + Pos += RMAC_INFO_GRP_3_SIZE; + } + + RMACInfoLen = RMACInfoGrpToLen[rx_base->rxd_0.grp_vld]; + +#ifdef RT_BIG_ENDIAN + if ((RMACInfoLen - 4) > 0) + { + MTMacInfoEndianChange(pAd, RMACInfo, TYPE_RMACINFO, RMACInfoLen); + } +#endif /* RT_BIG_ENDIAN */ + + //dump_rmac_info(pAd, RMACInfo); + + pRxBlk->MPDUtotalByteCnt = rx_base->rxd_0.rx_byte_cnt - RMACInfoLen; + + if (rx_base->rxd_1.hdr_offset == 1) { + pRxBlk->MPDUtotalByteCnt -= 2; + RMACInfoLen += 2; + } + + if (RxdGrp1 != NULL) + { + UINT64 pn_low = RxdGrp1->sec_pn_32; + UINT64 pn_high = RxdGrp1->sec_pn_48; + + pRxBlk->CCMP_PN = pn_low + (pn_high << 32); + } + + pRxBlk->DataSize = pRxBlk->MPDUtotalByteCnt; + pRxBlk->wcid = rx_base->rxd_2.wlan_idx; + pRxBlk->bss_idx = rx_base->rxd_1.bssid; + pRxBlk->key_idx = rx_base->rxd_1.key_id; + pRxBlk->TID = rx_base->rxd_2.tid; + + if (RxdGrp2 != NULL) + pRxBlk->TimeStamp = RxdGrp2->timestamp; + + pRxBlk->pRxInfo->U2M = rx_base->rxd_1.u2m; + pRxBlk->pRxInfo->Mcast = rx_base->rxd_1.mcast; + pRxBlk->pRxInfo->Bcast = rx_base->rxd_1.bcast; + pRxBlk->pRxInfo->FRAG = rx_base->rxd_2.frag; + pRxBlk->pRxInfo->NULLDATA = rx_base->rxd_2.null_frm; + pRxBlk->pRxInfo->DATA = !(rx_base->rxd_2.ndata); + pRxBlk->pRxInfo->HTC = rx_base->rxd_1.htc_vld; + pRxBlk->pRxInfo->AMPDU = !(rx_base->rxd_2.non_ampdu); + pRxBlk->pRxInfo->L2PAD = 0; + pRxBlk->pRxInfo->AMSDU = 0; // TODO: + pRxBlk->pRxInfo->CipherErr = rx_base->rxd_2.icv_err | (rx_base->rxd_2.tkip_mic_err << 1);/* 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid */ + pRxBlk->pRxInfo->Crc = rx_base->rxd_2.fcs_err; + pRxBlk->pRxInfo->MyBss = ((rx_base->rxd_1.bssid == 0xf) ? 0 : 1); + pRxBlk->pRxInfo->BA = !(rx_base->rxd_2.non_ampdu); + pRxBlk->pRxInfo->Decrypted = 0; // TODO: + + if (rx_base->rxd_0.grp_vld & RXS_GROUP3) + ParseRxVPacket(pAd, RMAC_RX_PKT_TYPE_RX_NORMAL, pRxBlk, (UCHAR *)RxdGrp3); + + SET_OS_PKT_DATAPTR(pRxPacket, GET_OS_PKT_DATAPTR(pRxPacket) + RMACInfoLen); + SET_OS_PKT_LEN(pRxPacket, pRxBlk->MPDUtotalByteCnt); + +//+++Add by shiang for work-around +//---Add by shiang for work-around +#ifdef DOT11_N_SUPPORT +#ifdef MAC_REPEATER_SUPPORT + if (IS_MT7603(pAd)) { + if (pRxBlk->pRxInfo->U2M == 1) + { + UCHAR *pData; + UINT16 SN; + HEADER_802_11 *pHeader; + + pData = (UCHAR *)GET_OS_PKT_DATAPTR(pRxPacket); + SN = (*((UINT16 *)(pData + 22)) & 0xfff0) >> 4; + + pHeader = (HEADER_802_11 *)pData; + if (pHeader->FC.Type == FC_TYPE_DATA && pHeader->FC.SubType == SUBTYPE_QDATA) { + TaTidRecAndCmp(pAd, rx_base, SN, FALSE, pHeader); + } else if (pHeader->FC.Type == FC_TYPE_CNTL && pHeader->FC.SubType == SUBTYPE_BLOCK_ACK_REQ) { + PFRAME_BA_REQ pFrame = (PFRAME_BA_REQ)(&(pHeader->FC)); + + TaTidRecAndCmp(pAd, rx_base, pFrame->BAStartingSeq.field.StartSeq, TRUE, pHeader); + } + } + } +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + return RMACInfoLen; +} +#endif /* MT_MAC */ + + +#define NUM_TYPE_STRING 8 +UCHAR *rx_pkt_type_string [NUM_TYPE_STRING] = { + "RMAC_RX_PKT_TYPE_RX_TXS", "RMAC_RX_PKT_TYPE_RX_TXRXV", "RMAC_RX_PKT_TYPE_RX_NORMAL", + "RMAC_RX_PKT_TYPE_RX_DUP_RFB", "RMAC_RX_PKT_TYPE_RX_TMR", "Undefine Type 0x5", + "Undefine Type 0x6", "RMAC_RX_PKT_TYPE_RX_EVENT" +}; + + +UINT32 parse_rx_packet_type(RTMP_ADAPTER *ad, RX_BLK *rx_blk, VOID *rx_packet) +{ + UINT32 rx_hw_hdr_len = 0; + UINT32 rx_pkt_type; + union rmac_rxd_0 *rxd_0; + + if (!rx_blk) { + DBGPRINT(RT_DEBUG_ERROR, ("%s() has NULL parameter: rx_blk\n", __func__)); + return rx_hw_hdr_len; + } + + rxd_0 = (union rmac_rxd_0 *)(GET_OS_PKT_DATAPTR(rx_packet)); + +#ifdef RT_BIG_ENDIAN + mt_rmac_d0_endian_change(&rxd_0->word); +#endif /* RT_BIG_ENDIAN */ + +#ifdef RTMP_PCI_SUPPORT + + if (rx_blk->PDMALen != RMAC_RX_PKT_RX_BYTE_COUNT(rxd_0->word)) + { + + DBGPRINT(RT_DEBUG_ERROR, ("drop rx length = 0x%x, pdma length = 0x%x packet\n", + RMAC_RX_PKT_RX_BYTE_COUNT(rxd_0->word), rx_blk->PDMALen)); + return 0; + + } + + if (RMAC_RX_PKT_RX_BYTE_COUNT(rxd_0->word) > RX_BUFFER_AGGRESIZE) + { + DBGPRINT(RT_DEBUG_ERROR, ("drop rx length = 0x%x packet\n", + RMAC_RX_PKT_RX_BYTE_COUNT(rxd_0->word))); + return 0; + } +#endif + + rx_pkt_type = RMAC_RX_PKT_TYPE(rxd_0->word); + + switch (rx_pkt_type) { + case RMAC_RX_PKT_TYPE_RX_NORMAL: + case RMAC_RX_PKT_TYPE_RX_DUP_RFB: +#ifdef MT_MAC + rx_hw_hdr_len = mt_rx_info_2_blk(ad, rx_blk, rx_packet, rx_pkt_type); +#endif /* MT_MAC */ + break; + + case RMAC_RX_PKT_TYPE_RX_TXRXV: + { + RMAC_RXD_0_TXRXV *rxv = (RMAC_RXD_0_TXRXV *)(GET_OS_PKT_DATAPTR(rx_packet)); + UCHAR *ptr; + INT idx; + + DBGPRINT(RT_DEBUG_LOUD, ("RxV Report: Number=%d, ByteCnt=%d\n", + rxv->rxv_cnt, rxv->rx_byte_cnt)); + + if (rxv->rx_byte_cnt != (rxv->rxv_cnt * 44 + 4)) + { + DBGPRINT(RT_DEBUG_ERROR, ("ReceivedByteCnt not equal rxv_entry required!\n")); + } + else + { + ptr = (UCHAR *)(GET_OS_PKT_DATAPTR(rx_packet) + 4); + +#ifdef RT_BIG_ENDIAN + if ((rxv->rx_byte_cnt - 4) > 0) + { + MTMacInfoEndianChange(ad, ptr, + TYPE_RMACINFO, rxv->rx_byte_cnt); + } +#endif /* RT_BIG_ENDIAN */ + + for (idx = 0; idx < rxv->rxv_cnt; idx++) + { + ParseRxVPacket(ad, RMAC_RX_PKT_TYPE_RX_TXRXV, rx_blk, ptr); + ptr += 44; + } + } + } + break; + + case RMAC_RX_PKT_TYPE_RX_TXS: + { + RMAC_RXD_0_TXS *txs = (RMAC_RXD_0_TXS *)(GET_OS_PKT_DATAPTR(rx_packet)); + UCHAR *ptr; + INT idx; + + DBGPRINT(RT_DEBUG_INFO, ("TxS Report: Number=%d, ByteCnt=%d\n", + txs->txs_cnt, txs->rx_byte_cnt)); + if (txs->rx_byte_cnt != (txs->txs_cnt * 20 + 4)) + { + DBGPRINT(RT_DEBUG_ERROR, ("ReceivedByteCnt not equal txs_entry required!\n")); + } + else + { + ptr = (UCHAR *)(GET_OS_PKT_DATAPTR(rx_packet) + 4); + for (idx = 0; idx < txs->txs_cnt; idx++) + { + TXS_STRUC *txs_entry = (TXS_STRUC *)ptr; + TXS_D_0 *txs_d0 = &txs_entry->txs_d0; +#ifdef RT_BIG_ENDIAN + TXS_D_1 *txs_d1 = &txs_entry->txs_d1; + TXS_D_2 *txs_d2 = &txs_entry->txs_d2; + TXS_D_3 *txs_d3 = &txs_entry->txs_d3; +#endif + TXS_D_4 *txs_d4 = &txs_entry->txs_d4; +#ifdef RT_BIG_ENDIAN + *(((UINT32 *)txs_d0)) = SWAP32(*(((UINT32 *)txs_d0))); + *(((UINT32 *)txs_d1)) = SWAP32(*(((UINT32 *)txs_d1))); + *(((UINT32 *)txs_d2)) = SWAP32(*(((UINT32 *)txs_d2))); + *(((UINT32 *)txs_d3)) = SWAP32(*(((UINT32 *)txs_d3))); + *(((UINT32 *)txs_d4)) = SWAP32(*(((UINT32 *)txs_d4))); +#endif + ParseTxSPacket(ad, txs_d4->pid, txs_d0->txsfm, ptr); + + ptr += 20; + } + } + } + break; + + case RMAC_RX_PKT_TYPE_RX_EVENT: + { + if (ad->chipOps.rx_event_handler != NULL) + ad->chipOps.rx_event_handler(ad, GET_OS_PKT_DATAPTR(rx_packet)); + + if (rx_blk) + RX_BLK_SET_FLAG(rx_blk, fRX_CMD_RSP); + } + break; +#ifdef MT_PS + case RMAC_RX_PKT_TYPE_RETRIEVE: + { + struct rxd_base_struct *rx_base; + TMAC_TXD_L *txd_l = (TMAC_TXD_L *)(GET_OS_PKT_DATAPTR(rx_packet)); + TMAC_TXD_1 *txd_1 = &txd_l->txd_1; +#ifdef RT_BIG_ENDIAN + *(((UINT32 *)txd_1)) = SWAP32(*(((UINT32 *)txd_1))); +#endif /* RT_BIG_ENDIAN */ + + UCHAR padding = txd_1->hdr_pad & 0x03; + UCHAR hdr_info = txd_1->hdr_info*2; + UCHAR *da, *sa; + STA_TR_ENTRY *tr_entry; + MAC_TABLE_ENTRY *pEntry; + unsigned long IrqFlags = 0; + UINT32 q_idx = QID_AC_BE; + HEADER_802_11 *pWifi_hdr; + UCHAR *qos_p; +#ifdef UAPSD_SUPPORT + UCHAR ac_idx = 0; +#endif /* UAPSD_SUPPORT */ + + tr_entry = &ad->MacTab.tr_entry[txd_1->wlan_idx]; + pEntry = &ad->MacTab.Content[txd_1->wlan_idx]; + rx_base = (struct rxd_base_struct *)rxd_0; + pWifi_hdr = (HEADER_802_11 *)(GET_OS_PKT_DATAPTR(rx_packet) + sizeof(TMAC_TXD_L)); + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(ad, (PUCHAR)pWifi_hdr, DIR_READ, FALSE); +#endif + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("parse_rx_packet_type wlan_idx=%d,%d,%d,0x%x\n", txd_1->wlan_idx,hdr_info,padding,tr_entry->EntryType)); + + if ((pWifi_hdr->FC.Type == FC_TYPE_CNTL) || + (pWifi_hdr->FC.Type == FC_TYPE_MGMT)) + { + return 0; + } + + da = pWifi_hdr->Addr1; + sa = pWifi_hdr->Addr2; + qos_p = ((UCHAR *)pWifi_hdr) + sizeof(HEADER_802_11); + +#ifdef UAPSD_SUPPORT + /* + Sanity Check for UAPSD condition for correct QoS index. + */ + if (qos_p[0] >= 8) + qos_p[0] = 1; /* shout not be here */ + + /* get the AC ID of incoming packet */ + ac_idx = WMM_UP2AC_MAP[qos_p[0]]; +#endif /* UAPSD_SUPPORT */ + + if ((tr_entry->ps_state == APPS_RETRIEVE_GOING) + || (tr_entry->ps_state == APPS_RETRIEVE_START_PS)) + { + if (qos_p[1] == PS_RETRIEVE_TOKEN) //retrive_token : 0x76 + { + rx_blk->DataSize = 0; + rx_blk->MPDUtotalByteCnt = rx_base->rxd_0.rx_byte_cnt; + tr_entry->ps_qbitmap &= (~(1 << qos_p[0])) ; + //DBGPRINT(RT_DEBUG_ERROR, ("txd_1->wlan_idx=%d, got token:%d, tr_entry->ps_qbitmap=%x\n", txd_1->wlan_idx, qos_p[0], tr_entry->ps_qbitmap)); + if (tr_entry->ps_qbitmap == 0x0) + { + //QUEUE_ENTRY *pQEntry; + UINT32 wlan_idx = 0; + int for_qid; + + if (tr_entry->ps_queue.Number) + { + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("(wcid=%d) put ps_queue packets(Number=%d) to tx_queue.\n", txd_1->wlan_idx, tr_entry->ps_queue.Number)); + MtEnqTxSwqFromPsQueue(ad, q_idx, tr_entry); + } + + for (for_qid = 0; for_qid < WMM_QUE_NUM; for_qid++) + { + tr_entry->TokenCount[for_qid] = tr_entry->tx_queue[for_qid].Number; + } + tr_entry->ps_state = APPS_RETRIEVE_WAIT_EVENT; + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("(ps_state = %d)Receives all RMAC_RX_PKT_TYPE_RETRIEVE packets and send CMDTHREAD_PS_CLEAR cmd.\n", + tr_entry->ps_state)); + wlan_idx = pEntry->wcid; + RTEnqueueInternalCmd(ad, CMDTHREAD_PS_CLEAR, (VOID *)&wlan_idx, sizeof(UINT32)); + } + } + else + { + INT packet_length = 0; + + if ((pWifi_hdr->FC.SubType == SUBTYPE_DATA_NULL) || (pWifi_hdr->FC.SubType == SUBTYPE_QOS_NULL)) + return 0; + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("da=(%02x:%02x:%02x:%02x:%02x:%02x), sa=(%02x:%02x:%02x:%02x:%02x:%02x), qos_p->ac%d, qos_p->value=%d, Sequence=%d txd_1->wlan_idx=%d\n" + , PRINT_MAC(da), PRINT_MAC(sa), qos_p[0], qos_p[1], pWifi_hdr->Sequence,txd_1->wlan_idx)); + + packet_length = rx_base->rxd_0.rx_byte_cnt-sizeof(TMAC_TXD_L) - padding - hdr_info - sizeof(SNAP_802_1H); + if (packet_length <= 0) + return 0; + + rx_hw_hdr_len = sizeof(TMAC_TXD_L); + SET_OS_PKT_DATAPTR(rx_packet, GET_OS_PKT_DATAPTR(rx_packet) + sizeof(TMAC_TXD_L) + padding + hdr_info + sizeof(SNAP_802_1H)); + SET_OS_PKT_LEN(rx_packet, packet_length); + + OS_PKT_HEAD_BUF_EXTEND(rx_packet, MAC_ADDR_LEN + MAC_ADDR_LEN); + NdisCopyMemory(GET_OS_PKT_DATAPTR(rx_packet) + MAC_ADDR_LEN, sa, MAC_ADDR_LEN); + NdisCopyMemory(GET_OS_PKT_DATAPTR(rx_packet), da, MAC_ADDR_LEN); + + RTMP_SET_PACKET_WCID(rx_packet, txd_1->wlan_idx); + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("parse_rx_packet_type not token txd_1->wlan_idx: %x, rx_packet addr: %x rx_wcid: %x\n",txd_1->wlan_idx,(u32)rx_packet,RTMP_GET_PACKET_WCID(rx_packet))); + RTMP_SET_PACKET_WDEV(rx_packet, tr_entry->wdev->wdev_idx); + + RTMP_IRQ_LOCK(&ad->irq_lock, IrqFlags); + if (tr_entry->ps_queue.Number >= MAX_PACKETS_IN_PS_QUEUE) + { + // drop the ps retrive pks due to limit ps queue max length + RELEASE_NDIS_PACKET(ad, rx_packet, NDIS_STATUS_FAILURE); + } + else + { + InsertTailQueue(&tr_entry->ps_queue, PACKET_TO_QUEUE_ENTRY(rx_packet)); + } + RTMP_IRQ_UNLOCK(&ad->irq_lock, IrqFlags); + +#ifdef UAPSD_SUPPORT + if (UAPSD_MR_IS_NOT_TIM_BIT_NEEDED_HANDLED(&ad->MacTab.Content[tr_entry->wcid], ac_idx)) + { + /* + 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 */ + { +#ifdef CONFIG_AP_SUPPORT + WLAN_MR_TIM_BIT_SET(ad, tr_entry->func_tb_idx, tr_entry->wcid); +#endif /* CONFIG_AP_SUPPORT */ + } + + RX_BLK_SET_FLAG(rx_blk, fRX_RETRIEVE); + + } + } + else + { + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("da=(%02x:%02x:%02x:%02x:%02x:%02x), sa=(%02x:%02x:%02x:%02x:%02x:%02x), qos_p->ac%d, qos_p->value=%d, Sequence=%d txd_1->wlan_idx=%d, ps_state = %d\n" + , PRINT_MAC(da), PRINT_MAC(sa), qos_p[0], qos_p[1], pWifi_hdr->Sequence,txd_1->wlan_idx, tr_entry->ps_state)); + } + break; + } +#endif /* MT_PS */ + + case RMAC_RX_PKT_TYPE_RX_TMR: + { +#ifdef DBG + TMR_FRM_STRUC *tmr = (TMR_FRM_STRUC *)(GET_OS_PKT_DATAPTR(rx_packet)); + struct rmac_rxd_0_tmr *ptmr_d0 = &tmr->tmr_d0; + //TMR_D_1 *ptmr_d1 = &tmr->tmr_d1; + UINT32 *ptod_0 = &tmr->tod_0; + UINT32 *ptoa_0 = &tmr->toa_0; + TMR_D_6 *tmr_d6 = &tmr->tmr_d6; + hex_dump("TMR", (UCHAR *)tmr, 20); +#endif /* DBG */ + return 0; + +#ifdef DBG + hex_dump("TMR", (UCHAR *)tmr, ptmr_d0->rx_byte_cnt); + DBGPRINT(RT_DEBUG_OFF, ("TMR Report: ir = %d\n", ptmr_d0->ir)); + DBGPRINT(RT_DEBUG_OFF, ("DWORD_0: ByteCnt=%d, NC=%d, TMF=%d, " + "toa_vld=%d, tod_vld=%d\n", + ptmr_d0->rx_byte_cnt, ptmr_d0->nc, ptmr_d0->tmf, + ptmr_d0->toa_vld, ptmr_d0->tod_vld)); + if (ptmr_d0->ir == 1) //responder case! + { + TMR_D_2 *ptmr_d2 = &tmr->tmr_d2; + UINT32 *pta_16 = &tmr->ta_16; + + DBGPRINT(RT_DEBUG_OFF, ("TYPE=%x,SUB_TYPE=%x\n", + ptmr_d0->type, ptmr_d0->sub_type)); + DBGPRINT(RT_DEBUG_OFF, ("DWORD_2: TA[0:15]=%x, SN=%x\n", ptmr_d2->field.ta_0, ptmr_d2->field.sn)); + DBGPRINT(RT_DEBUG_OFF, ("DWORD_3: TA[16:47]=%x\n", *pta_16)); + } + + DBGPRINT(RT_DEBUG_OFF, ("DWORD_4: TOD[0:31]=0x%x\n", *ptod_0)); + DBGPRINT(RT_DEBUG_OFF, ("DWORD_6: TOD[32:47]=0x%x\n", tmr_d6->field.tod_32)); + + DBGPRINT(RT_DEBUG_OFF, ("DWORD_5: TOA[0:31]=0x%x\n", *ptoa_0)); + DBGPRINT(RT_DEBUG_OFF, ("DWORD_6: TOA[32:47]=0x%x\n", tmr_d6->field.toa_32)); +#endif /* DBG */ + + } + break; + + default: + DBGPRINT(RT_DEBUG_OFF, ("%s():Invalid PktType:%d\n", __FUNCTION__, rx_pkt_type)); + //rx_hw_hdr_len = pRxD->SDL0; + //rx_blk->MPDUtotalByteCnt = 0; + //rx_blk->DataSize = 0; + break; + } + + return rx_hw_hdr_len; +} +#endif /* MT_MAC */ + +#ifdef DOT11_N_SUPPORT +VOID RTMP_BASetup(RTMP_ADAPTER *pAd, STA_TR_ENTRY *tr_entry, UINT8 UPriority) +{ + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[tr_entry->wcid]; + + if (pAd->CommonCfg.BACapability.field.AutoBA == FALSE) + return; + + // TODO: shiang-usw, fix me for pEntry, we should replace this paramter as tr_entry! + if ((tr_entry && tr_entry->EntryType != ENTRY_CAT_MCAST && tr_entry->wcid < MAX_LEN_OF_MAC_TABLE) && + (pEntry->NoBADataCountDown == 0) && IS_HT_STA(pEntry)) + { + BOOLEAN isRalink = CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET); + + + if (((pEntry->TXBAbitmap & (1<BADeclineBitmap & (1 << UPriority)) == 0) */ + && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED) + && (!(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS))) + && ((isRalink || IS_ENTRY_MESH(pEntry) || IS_ENTRY_WDS(pEntry)) + || (pEntry->WepStatus == Ndis802_11WEPDisabled || pEntry->WepStatus == Ndis802_11AESEnable +#ifdef WAPI_SUPPORT + || pEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled +#endif /* WAPI_SUPPORT */ + )) + ) + { + BAOriSessionSetUp(pAd, pEntry, UPriority, 0, 10, FALSE); + } + } +} +#endif /* DOT11_N_SUPPORT */ + + +/* + ======================================================================== + + Routine Description: + API for MLME to transmit management frame to AP (BSS Mode) + or station (IBSS Mode) + + Arguments: + pAd Pointer to our adapter + pData Pointer to the outgoing 802.11 frame + Length Size of outgoing management frame + + Return Value: + NDIS_STATUS_FAILURE + NDIS_STATUS_PENDING + NDIS_STATUS_SUCCESS + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +#define MAX_DATAMM_RETRY 3 + +NDIS_STATUS MiniportMMRequest(RTMP_ADAPTER *pAd, UCHAR QueIdx, UCHAR *pData, UINT Length) +{ + PNDIS_PACKET pPacket; + NDIS_STATUS Status = NDIS_STATUS_FAILURE; + ULONG FreeNum; +#ifdef RTMP_MAC_PCI + unsigned long IrqFlags = 0; + BOOLEAN bUseDataQ = FALSE; +#endif /* RTMP_MAC_PCI */ + BOOLEAN FlgDataQForce = FALSE, FlgIsLocked = FALSE; + int retryCnt = 0; + BOOLEAN FlgIsCheckPS = FALSE; + +#ifdef WH_EZ_SETUP + HEADER_802_11 *pHead = (HEADER_802_11*)pData; + struct wifi_dev *wdev; +#endif /* WH_EZ_SETUP */ + +#ifdef WH_EZ_SETUP +#ifdef DUAL_CHIP + wdev = WdevSearchByAddress(pAd,pHead->Addr2); + if(!IS_SINGLE_CHIP_DBDC(pAd)) { + if ((wdev != NULL) && IS_EZ_SETUP_ENABLED(wdev)) + RTMP_SEM_LOCK(&pAd->ez_miniport_lock); + } +#endif +#endif + + ASSERT(Length <= MGMT_DMA_BUFFER_SIZE); + + if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG) + { +#ifdef RTMP_MAC_PCI + bUseDataQ = TRUE; +#endif /* RTMP_MAC_PCI */ + QueIdx &= (~MGMT_USE_QUEUE_FLAG); + } + +#ifndef MT_PS +#ifdef CONFIG_FPGA_MODE + if (pAd->fpga_ctl.fpga_on & 0x1) { + if (pAd->fpga_ctl.tx_kick_cnt > 0) { + if (pAd->fpga_ctl.tx_kick_cnt < 0xffff) + pAd->fpga_ctl.tx_kick_cnt--; + } + else + return NDIS_STATUS_FAILURE; + + QueIdx = 0; + //bUseDataQ = TRUE; + } +#endif /* CONFIG_FPGA_MODE */ +#endif /* MT_PS */ + + if ((QueIdx & MGMT_USE_PS_FLAG) == MGMT_USE_PS_FLAG) + { + FlgIsCheckPS = TRUE; + QueIdx &= (~MGMT_USE_PS_FLAG); + } +#ifdef RTMP_MAC_PCI + if (pAd->MACVersion == 0x28600100) + { + /* do not care about the version */ + QueIdx = (bUseDataQ ==TRUE ? QueIdx : 3); + bUseDataQ = TRUE; + } + + + if (bUseDataQ) + { + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + FlgIsLocked = TRUE; + retryCnt = MAX_DATAMM_RETRY; + } +#endif /* RTMP_MAC_PCI */ + + do + { + /* Reset is in progress, stop immediately*/ + if (RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS | + fRTMP_ADAPTER_NIC_NOT_EXIST | + fRTMP_ADAPTER_RADIO_OFF)) || + !RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP) + ) + { + Status = NDIS_STATUS_FAILURE; + break; + } + + + /* 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)) + { + INT hw_len; + UCHAR rtmpHwHdr[40]; + + // TODO: shiang-7603 + hw_len = pAd->chipCap.tx_hw_hdr_len; + ASSERT((sizeof(rtmpHwHdr) > hw_len)); + + /* We need to reserve space for rtmp hardware header. i.e., TxWI for RT2860 and TxInfo+TxWI for RT2870*/ + NdisZeroMemory(&rtmpHwHdr, hw_len); + Status = RTMPAllocateNdisPacket(pAd, &pPacket, (UCHAR *)&rtmpHwHdr[0], hw_len, pData, Length); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_WARN, ("MiniportMMRequest (error:: can't allocate NDIS PACKET)\n")); + break; + } + +#ifdef DOT11W_PMF_SUPPORT + if (pAd->chipCap.hif_type != HIF_MT) + PMF_PerformTxFrameAction(pAd, pPacket); +#endif /* DOT11W_PMF_SUPPORT */ + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) +#ifdef UAPSD_SUPPORT + UAPSD_MR_QOS_NULL_HANDLE(pAd, pData, pPacket); +#endif /* UAPSD_SUPPORT */ +#else +#ifdef CONFIG_AP_SUPPORT +#ifdef UAPSD_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + UAPSD_MR_QOS_NULL_HANDLE(pAd, pData, pPacket); + } +#endif /* UAPSD_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + +#ifdef RTMP_MAC_PCI + if (bUseDataQ) + { + FlgDataQForce = TRUE; + retryCnt--; + } +#endif /* RTMP_MAC_PCI */ +#ifdef WIFI_DIAG + DiagMiniportMMRequest(pAd, pData, Length); +#endif + Status = MlmeHardTransmit(pAd, QueIdx, pPacket, FlgDataQForce, FlgIsLocked, FlgIsCheckPS); + if (Status == NDIS_STATUS_SUCCESS) + retryCnt = 0; + else + RELEASE_NDIS_PACKET(pAd, pPacket, Status); + } + else + { + pAd->RalinkCounters.MgmtRingFullCount++; +#ifdef RTMP_MAC_PCI + if (bUseDataQ) + { + retryCnt--; + DBGPRINT(RT_DEBUG_TRACE, ("retryCnt %d\n", retryCnt)); + if (retryCnt == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("Qidx(%d), not enough space in DataRing, MgmtRingFullCount=%ld!\n", + QueIdx, pAd->RalinkCounters.MgmtRingFullCount)); + } + } + else +#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 */ + +#ifdef WH_EZ_SETUP +#ifdef DUAL_CHIP + if(!IS_SINGLE_CHIP_DBDC(pAd)) { + if ((wdev != NULL) && IS_EZ_SETUP_ENABLED(wdev)) + RTMP_SEM_UNLOCK(&pAd->ez_miniport_lock); + } +#endif +#endif + + 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 RTMP_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 */ + STA_TR_ENTRY *tr_entry = &pAd->MacTab.tr_entry[pMacEntry->wcid]; + + /* 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 = DuplicatePacket(wdev->if_dev, pPacket); + } + else +#endif /* UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY */ + { + RTMP_SET_PACKET_UAPSD(pPacket, 1, MgmtQid); + } + + UAPSD_PacketEnqueue(pAd, pMacEntry, pPacket, MgmtQid, FALSE); + + if (pMacEntry->bAPSDAllAC) + { + /* mark corresponding TIM bit in outgoing BEACON frame*/ + WLAN_MR_TIM_BIT_SET(pAd, pMacEntry->func_tb_idx, 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 */ + { +#ifdef UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY +Label_Legacy_PS: +#endif /* UAPSD_CC_FUNC_PS_MGMT_TO_LEGACY */ + DBGPRINT(RT_DEBUG_TRACE, + ("ps> mgmt to legacy ps queue... (%d)\n", FlgIsDeltsFrame)); + + if (tr_entry->ps_queue.Number >= MAX_PACKETS_IN_PS_QUEUE || + rtmp_enq_req(pAd, pPacket, MgmtQid, tr_entry, FlgIsLocked, NULL) == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s(%d): WLAN_TX_DROP, pPacket=%p, QueIdx=%d, ps_queue_num=%d, wcid=%d\n", + __FUNCTION__, __LINE__, pPacket, MgmtQid, tr_entry->ps_queue.Number, tr_entry->wcid)); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_RESOURCES); + return; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ps> mgmt to legacy ps queue... (%d)\n", FlgIsDeltsFrame)); + /* mark corresponding TIM bit in outgoing BEACON frame*/ + WLAN_MR_TIM_BIT_SET(pAd, pMacEntry->func_tb_idx, pMacEntry->Aid); + } + + } +} +#endif /* CONFIG_AP_SUPPORT */ + + +/* + ======================================================================== + + Routine Description: + Copy frame from waiting queue into relative ring buffer and set + appropriate ASIC register to kick hardware transmit function + + Arguments: + pAd Pointer to our adapter + pBuffer Pointer to memory of outgoing frame + Length Size of outgoing management frame + + Return Value: + NDIS_STATUS_FAILURE + NDIS_STATUS_PENDING + NDIS_STATUS_SUCCESS + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS MlmeHardTransmit( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket, + IN BOOLEAN FlgDataQForce, + IN BOOLEAN FlgIsLocked, + IN BOOLEAN FlgIsCheckPS) +{ +#ifdef CONFIG_AP_SUPPORT + MAC_TABLE_ENTRY *pEntry = NULL; + HEADER_802_11 *pHeader_802_11; + //UINT8 TXWISize = pAd->chipCap.TXWISize; + UINT8 tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len; +#endif /* CONFIG_AP_SUPPORT */ + PACKET_INFO PacketInfo; + UCHAR *pSrcBufVA; + UINT SrcBufLen; + + if ((pAd->Dot11_H.RDMode != RD_NORMAL_MODE) +#ifdef CARRIER_DETECTION_SUPPORT +#ifdef CONFIG_AP_SUPPORT + ||(isCarrierDetectExist(pAd) == TRUE) +#endif /* CONFIG_AP_SUPPORT */ +#endif /* CARRIER_DETECTION_SUPPORT */ + ) + { + return NDIS_STATUS_FAILURE; + } + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + if (pSrcBufVA == NULL) + return NDIS_STATUS_FAILURE; + +#ifdef CONFIG_AP_SUPPORT + // TODO: shiang-7603 + pHeader_802_11 = (HEADER_802_11 *) (pSrcBufVA + tx_hw_hdr_len); + + /* + Section 11.2.1.1 STA Power Management modes of IEEE802.11-2007: + The Power Managment bit shall not be set in any management frame, + except an Action frame. + + So in the 'baseline' test plan + (Wi-Fi 802.11 WPA2, WPA, WEP Interoperability Test Plan), + Section 2.2.6, the following Requirement: + APs shall ignore the power save bit in any received Authenticate and + (Re) Associate, and shall assume that the station is awake for the + response. + */ + + /* + IEEE802.11, 11.2.1.4 AP operation during the contention period f) + A single buffered MSDU or management frame for a STA in the PS mode shall + be forwarded to the STA after a PS-Poll has been received from that STA. + The More Data field shall be set to indicate the presence of further + buffered MSDUs or "management frames" for the polling STA. + */ + + /* + IEEE802.11e, 11.2.1.4 Power management with APSD, + An unscheduled SP ends after the QAP has attempted to transmit at least + one MSDU or MMPDU associated with a delivery-enabled AC and destined for + the non-AP QSTA, but no more than the number indicated in the Max SP + Length field if the field has a nonzero value. + */ + + if ((pHeader_802_11->FC.Type == FC_TYPE_DATA) || + (pHeader_802_11->FC.Type == FC_TYPE_MGMT)) + { + if ((pHeader_802_11->FC.Type == FC_TYPE_MGMT) || (pHeader_802_11->FC.SubType != SUBTYPE_QOS_NULL)) + pEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); +#ifdef MAC_REPEATER_SUPPORT + if (pEntry != NULL && pAd->ApCfg.bMACRepeaterEn && IS_ENTRY_APCLI(pEntry)) + { + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + UCHAR MacTabWCID=0; + UCHAR isLinkValid; + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, FALSE, pHeader_802_11->Addr2, TRUE, &isLinkValid); + if (pReptEntry && pReptEntry->CliValid) + { + MacTabWCID = pReptEntry->MacTabWCID; + pEntry = &pAd->MacTab.Content[MacTabWCID]; + } + } +#endif + } + +#ifdef DOT11K_RRM_SUPPORT +#ifdef QUIET_SUPPORT + if ((pEntry != NULL) + && (pEntry->func_tb_idx < pAd->ApCfg.BssidNum) + && IS_RRM_QUIET(pAd, pEntry->func_tb_idx)) + { + return NDIS_STATUS_FAILURE; + } +#endif /* QUIET_SUPPORT */ +#endif /* DOT11K_RRM_SUPPORT */ + + +#ifdef CONFIG_FPGA_MODE + if (pAd->fpga_ctl.fpga_on & 0x1) { + if (pAd->fpga_ctl.tx_kick_cnt > 0) { + if (pAd->fpga_ctl.tx_kick_cnt < 0xffff) { + pAd->fpga_ctl.tx_kick_cnt--; + } + } else { + return NDIS_STATUS_FAILURE; + } + } +#endif /* CONFIG_FPGA_MODE */ + + if ((pEntry != NULL) && + (pEntry->PsMode == PWR_SAVE) && + (((pHeader_802_11->FC.Type == FC_TYPE_DATA) && + (pHeader_802_11->FC.SubType != SUBTYPE_DATA_NULL) && + (pHeader_802_11->FC.SubType != SUBTYPE_QOS_NULL)) || + ((pHeader_802_11->FC.Type == FC_TYPE_MGMT) && + (pHeader_802_11->FC.SubType == SUBTYPE_ACTION)) || + ((pHeader_802_11->FC.Type == FC_TYPE_MGMT) && + (pHeader_802_11->FC.SubType == SUBTYPE_ACTION_NO_ACK)) || + (FlgIsCheckPS == 1))) + { + /* the peer is in PS mode, we need to queue the management frame */ + UINT8 FlgIsDeltsFrame = 0, MgmtQid = QID_AC_VO; + + /* + 1. Data & Not QoS Null, or + 2. Management & Action, or + 3. Management & Action No ACK; + */ + DBGPRINT(RT_DEBUG_TRACE, ("STA in ps mode, queue the mgmt frame\n")); + RTMP_SET_PACKET_WCID(pPacket, pEntry->wcid); + RTMP_SET_PACKET_MGMT_PKT(pPacket, 1); /* is management frame */ + RTMP_SET_PACKET_MGMT_PKT_DATA_QUE(pPacket, 0); /* default to management queue */ + + + + if (FlgDataQForce == TRUE) + RTMP_SET_PACKET_MGMT_PKT_DATA_QUE(pPacket, 1); /* force to data queue */ + + if ((pHeader_802_11->FC.Type == FC_TYPE_MGMT) && + (pHeader_802_11->FC.SubType == SUBTYPE_ACTION)) + { + FRAME_ADDBA_REQ *pFrameBa = (FRAME_ADDBA_REQ *)pHeader_802_11; + if (pFrameBa->Category == CATEGORY_BA) + MgmtQid = QueIdx; + } + + +#ifdef CONFIG_HOTSPOT_R2 + if (((pHeader_802_11->FC.Type == FC_TYPE_MGMT) && + (pHeader_802_11->FC.SubType == SUBTYPE_DISASSOC)) || + ((pHeader_802_11->FC.Type == FC_TYPE_MGMT) && + (pHeader_802_11->FC.SubType == SUBTYPE_DEAUTH))) + { + RTMP_SET_PACKET_DISASSOC(pPacket, 1); + pEntry->IsKeep = 1; + } +#endif /* CONFIG_HOTSPOT_R2 */ + + AP_QueuePsActionPacket(pAd, pEntry, pPacket, FlgIsDeltsFrame, + FlgIsLocked, MgmtQid); + return NDIS_STATUS_SUCCESS; + } + else +#endif /* CONFIG_AP_SUPPORT */ + { +#ifdef RTMP_MAC_PCI + if (FlgDataQForce == TRUE) + return MlmeHardTransmitTxRing(pAd,QueIdx,pPacket); + else +#endif /* RTMP_MAC_PCI */ + return MlmeHardTransmitMgmtRing(pAd,QueIdx,pPacket); + } +} + +#ifdef WH_EZ_SETUP +extern UCHAR dmac_wmm_aci_2_hw_ac_que[4][4]; +#endif + +NDIS_STATUS MlmeHardTransmitMgmtRing(RTMP_ADAPTER *pAd, UCHAR QueIdx, PNDIS_PACKET pPacket) +{ + PACKET_INFO PacketInfo; + UCHAR *pSrcBufVA, *tmac_info; + UINT SrcBufLen; + HEADER_802_11 *pHeader_802_11; + BOOLEAN bAckRequired, bInsertTimestamp; +#ifdef GN_ONLY_AP_SUPPORT + BOOLEAN BMode=TRUE, bExcludeBRate=FALSE; +#endif + PFRAME_BAR pBar = NULL; + UCHAR MlmeRate; + MAC_TABLE_ENTRY *pMacEntry = NULL; + UCHAR PID, wcid, tx_rate; + HTTRANSMIT_SETTING *transmit = NULL, TransmitSetting; + //UINT8 TXWISize = pAd->chipCap.TXWISize; + UINT8 tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len; + MAC_TX_INFO mac_info; +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +#ifdef WH_EZ_SETUP + struct wifi_dev *wdev = NULL; +#endif +#endif +#endif +#ifdef CONFIG_AP_SUPPORT +#ifdef SPECIFIC_TX_POWER_SUPPORT + UCHAR TxPwrAdj = 0; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + UCHAR prot = 0; + UCHAR apidx = 0; + ULONG Flags = 0; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + /* Make sure MGMT ring resource won't be used by other threads*/ + RTMP_IRQ_LOCK(&pAd->MgmtRingLock, Flags); + + NdisZeroMemory((UCHAR *)&mac_info, sizeof(mac_info)); + + if (pSrcBufVA == NULL) + { + /* The buffer shouldn't be NULL*/ + RTMP_IRQ_UNLOCK(&pAd->MgmtRingLock, Flags); + return NDIS_STATUS_FAILURE; + } + + +#if defined(MT7603) || defined(MT7628) + // TODO: shiang-7603 + tmac_info = pSrcBufVA; +#else + tmac_info = pSrcBufVA + TXINFO_SIZE; +#endif /* MT7603 */ + pHeader_802_11 = (HEADER_802_11 *) (pSrcBufVA + tx_hw_hdr_len); +#ifdef GN_ONLY_AP_SUPPORT + if((pAd->OpMode == OPMODE_STA) || (pAd->OpMode == OPMODE_AP)) + { + UCHAR BssIdx,i,CCK_rate; + BSS_ENTRY *pEntry01; + bExcludeBRate = pAd->CommonCfg.bExcludeBRate; + if(pHeader_802_11->FC.Type == FC_TYPE_MGMT) { + BssIdx = BssTableSearch(&pAd->ScanTab, pHeader_802_11->Addr3, pAd->LatchRfRegs.Channel); + pEntry01 = &pAd->ScanTab.BssEntry[BssIdx]; + if(BssIdx < 0xFF) { + BMode = FALSE; + for(i=0 ; i < MAX_LEN_OF_SUPPORTED_RATES;i++) { + CCK_rate = pEntry01->SupRate[i] & 0x7f; + if (CCK_rate == 2 || CCK_rate == 4 || CCK_rate == 11 || CCK_rate == 22) { + BMode = TRUE; + break; + } + } + } //if(BssIdx < 0xFF) + } //if(pHeader_802_11->FC.Type == FC_TYPE_MGMT) + } // if((pAd->OpMode == OPMODE_STA) || (pAd->OpMode == OPMODE_AP)) +#endif +//DBGPRINT(RT_DEBUG_OFF, ("%s(): pSrcBufVA=0x%p, pHeader_802_11=0x%p, tmac_info=%p, tx_hw_hdr_len=%d\n", +// __FUNCTION__, pSrcBufVA, pHeader_802_11, tmac_info, tx_hw_hdr_len)); + 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; +#ifdef GN_ONLY_AP_SUPPORT + if((pAd->OpMode == OPMODE_STA) || (pAd->OpMode == OPMODE_AP)) { +// printk("====[%s] pAd->OpMode = %d BMode = %d bExcludeBRate = %d \n", __FUNCTION__,pAd->OpMode, BMode, bExcludeBRate); + if(!BMode || bExcludeBRate) + MlmeRate= RATE_6; + } +#endif + if (((pHeader_802_11->FC.Type == FC_TYPE_DATA) && (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) || + ((pHeader_802_11->FC.Type == FC_TYPE_CNTL) && (pHeader_802_11->FC.SubType == SUBTYPE_BLOCK_ACK_REQ))) + { + pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); +#ifdef GN_ONLY_AP_SUPPORT + if((pAd->OpMode == OPMODE_STA) || (pAd->OpMode == OPMODE_AP)) + { + if(!(pMacEntry->SupportRateMode & 0x01)) { + BMode=FALSE; + } + } +#endif +#ifdef MAC_REPEATER_SUPPORT + if (pMacEntry != NULL && pAd->ApCfg.bMACRepeaterEn && IS_ENTRY_APCLI(pMacEntry)) + { + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + UCHAR MacTabWCID=0; + UCHAR isLinkValid; + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, FALSE, pHeader_802_11->Addr2, TRUE, &isLinkValid); + if (pReptEntry && pReptEntry->CliValid) + { + MacTabWCID = pReptEntry->MacTabWCID; + pMacEntry = &pAd->MacTab.Content[MacTabWCID]; + } + } +#endif + } + +#ifdef DOT11W_PMF_SUPPORT + if (pAd->chipCap.hif_type == HIF_MT) + { + UINT32 ret = 0; + MAC_TABLE_ENTRY *pEntry = NULL; + + pEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); +#ifdef MAC_REPEATER_SUPPORT + if (pEntry != NULL && pAd->ApCfg.bMACRepeaterEn && IS_ENTRY_APCLI(pEntry)) + { + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + UCHAR MacTabWCID=0; + UCHAR isLinkValid; + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, FALSE, pHeader_802_11->Addr2, TRUE, &isLinkValid); + if (pReptEntry && pReptEntry->CliValid) + { + MacTabWCID = pReptEntry->MacTabWCID; + pEntry = &pAd->MacTab.Content[MacTabWCID]; + } + } +#endif + ret = PMF_RobustFrameClassify( + (PHEADER_802_11)pHeader_802_11, + (PUCHAR)(((PUCHAR)pHeader_802_11)+LENGTH_802_11), + (SrcBufLen - LENGTH_802_11 - tx_hw_hdr_len), + (PUCHAR) pEntry, + FALSE); + + if (pEntry) + apidx = pEntry->func_tb_idx; + + if (ret == UNICAST_ROBUST_FRAME) + { + prot = 1; + pHeader_802_11->FC.Wep = 1; + } + else if (ret == GROUP_ROBUST_FRAME) + { + ret = PMF_EncapBIPAction(pAd, + (PUCHAR)pHeader_802_11, + (SrcBufLen - tx_hw_hdr_len)); + if (ret == PMF_STATUS_SUCCESS) + prot = 2; + else + DBGPRINT(RT_DEBUG_OFF, ("%s, PMF GROUP ROBUST Encap fail, ret=%d\n", + __FUNCTION__, ret)); + } + } +#endif + + + +#ifdef GN_ONLY_AP_SUPPORT + if((pAd->OpMode == OPMODE_STA) || (pAd->OpMode == OPMODE_AP)) { + if(!BMode || bExcludeBRate) { + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = MCS_RATE_6; + } + } +#endif + /* + 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. + */ + + pHeader_802_11->FC.PwrMgmt = PWR_ACTIVE; + + + +#ifdef CONFIG_AP_SUPPORT + pHeader_802_11->FC.MoreData = RTMP_GET_PACKET_MOREDATA(pPacket); +#endif /* CONFIG_AP_SUPPORT */ + + + bInsertTimestamp = FALSE; + if (pHeader_802_11->FC.Type == FC_TYPE_CNTL) /* must be PS-POLL*/ + { + bAckRequired = FALSE; + + if (pHeader_802_11->FC.SubType == SUBTYPE_BLOCK_ACK_REQ) + { + pBar = (PFRAME_BAR)(pSrcBufVA + tx_hw_hdr_len); + bAckRequired = TRUE; + } + +#ifdef VHT_TXBF_SUPPORT + if (pHeader_802_11->FC.SubType == SUBTYPE_VHT_NDPA) + { + pHeader_802_11->Duration = 100; + //DBGPRINT(RT_DEBUG_OFF, ("%s(): VHT_NDPA frame, rate=%d, len=%d, duration=%d\n", + // __FUNCTION__, MlmeRate, SrcBufLen, pHeader_802_11->Duration)); + //hex_dump("VHT_NDPA after update Duration", (UCHAR *)pHeader_802_11, SrcBufLen); + } +#endif /* VHT_TXBF_SUPPORT */ + } + else /* FC_TYPE_MGMT or FC_TYPE_DATA(must be NULL frame)*/ + { + if (pHeader_802_11->Addr1[0] & 0x01) /* MULTICAST, BROADCAST*/ + { + bAckRequired = FALSE; + pHeader_802_11->Duration = 0; + } + else + { +#ifdef SOFT_SOUNDING + if (((pHeader_802_11->FC.Type == FC_TYPE_DATA) && (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) + && pMacEntry && (pMacEntry->snd_reqired == TRUE)) + { + bAckRequired = FALSE; + pHeader_802_11->Duration = 0; + } + else +#endif /* SOFT_SOUNDING */ + { + bAckRequired = TRUE; + pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14); + if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) && (pHeader_802_11->FC.Type == FC_TYPE_MGMT)) + { + bInsertTimestamp = TRUE; + bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Response*/ +#ifdef CONFIG_AP_SUPPORT +#ifdef SPECIFIC_TX_POWER_SUPPORT + /* Find which MBSSID to be send this probeRsp */ + UINT32 apidx = get_apidx_by_addr(pAd, pHeader_802_11->Addr2); + + if ( !(apidx >= pAd->ApCfg.BssidNum) && + (pAd->ApCfg.MBSSID[apidx].TxPwrAdj != -1) && + (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_CCK) && + (pAd->CommonCfg.MlmeTransmit.field.MCS == RATE_1)) + { + TxPwrAdj = pAd->ApCfg.MBSSID[apidx].TxPwrAdj; + } +#endif /* SPECIFIC_TX_POWER_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + } + else if ((pHeader_802_11->FC.SubType == SUBTYPE_PROBE_REQ) && (pHeader_802_11->FC.Type == FC_TYPE_MGMT)) + { + bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Probe Request*/ + } + else if ((pHeader_802_11->FC.SubType == SUBTYPE_DEAUTH) && + (MacTableLookup(pAd, pHeader_802_11->Addr1) == NULL)) + { + bAckRequired = FALSE; /* Disable ACK to prevent retry 0x1f for Deauth */ + } + } + } + } + + pHeader_802_11->Sequence = pAd->Sequence++; + if (pAd->Sequence >0xfff) + pAd->Sequence = 0; + + /* + Before radar detection done, mgmt frame can not be sent but probe req + Because we need to use probe req to trigger driver to send probe req in passive scan + */ + if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) + && (pAd->CommonCfg.bIEEE80211H == 1) + && (pAd->Dot11_H.RDMode != RD_NORMAL_MODE)) + { + RTMP_IRQ_UNLOCK(&pAd->MgmtRingLock, Flags); + return NDIS_STATUS_FAILURE; + } + + /* + 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 + + management frame doesn't need encryption. + so use RESERVED_WCID no matter u are sending to specific wcid or not + */ + PID = PID_MGMT; + + + if (pMacEntry == NULL) + { + wcid = RESERVED_WCID; + // TODO: shiang-7603 + if (IS_MT7603(pAd) || IS_MT7628(pAd)) + { + wcid = 0; + if(prot) + { + MAC_TABLE_ENTRY *pEntry = NULL; + + pEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); +#ifdef MAC_REPEATER_SUPPORT + if (pEntry != NULL && pAd->ApCfg.bMACRepeaterEn && IS_ENTRY_APCLI(pEntry)) + { + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + UCHAR MacTabWCID=0; + UCHAR isLinkValid; + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, FALSE, pHeader_802_11->Addr2, TRUE, &isLinkValid); + if (pReptEntry && pReptEntry->CliValid) + { + MacTabWCID = pReptEntry->MacTabWCID; + pEntry = &pAd->MacTab.Content[MacTabWCID]; + } + } +#endif + + if (pEntry) + wcid = pEntry->Aid; + } + } + tx_rate = (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS; + transmit = &pAd->CommonCfg.MlmeTransmit; +#ifdef VHT_TXBF_SUPPORT + if (pAd->NDPA_Request) + { + transmit->field.MODE = MODE_VHT; + transmit->field.MCS = MCS_RATE_6; + } +#endif + } + else + { + + wcid = pMacEntry->wcid; + tx_rate = (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS; + transmit = &pMacEntry->MaxHTPhyMode; + /* dont use low rate to send QoS Null data frame */ + } + + if(prot) + mac_info.prot = prot; + + if (prot == 2) + mac_info.bss_idx = apidx; + + mac_info.FRAG = FALSE; + + mac_info.CFACK = FALSE; + mac_info.InsTimestamp = bInsertTimestamp; + mac_info.AMPDU = FALSE; + + mac_info.Ack = bAckRequired; + mac_info.BM = IS_BM_MAC_ADDR(pHeader_802_11->Addr1); + mac_info.NSeq = FALSE; + mac_info.BASize = 0; + + mac_info.WCID = wcid; + mac_info.TID = 0; +#if defined(MT7603) || defined(MT7628) + // TODO: shiang-MT7603 + mac_info.Length = (SrcBufLen - tx_hw_hdr_len); + if (pHeader_802_11->FC.Type == FC_TYPE_MGMT) { + mac_info.hdr_len = 24; + if (pHeader_802_11->FC.Order == 1) + mac_info.hdr_len += 4; + if((pHeader_802_11->FC.SubType == SUBTYPE_ASSOC_RSP) || (pHeader_802_11->FC.SubType == SUBTYPE_REASSOC_RSP)) { + MAC_TABLE_ENTRY *pEntry = NULL; + PID = PID_MGMT_ASSOC_RSP; + DBGPRINT(RT_DEBUG_TRACE,("===[%s] ASSOC_RSP:addr1 %02x:%02x:%02x:%02x:%02x:%02x addr2 %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, PRINT_MAC(pHeader_802_11->Addr1), PRINT_MAC(pHeader_802_11->Addr2))); + pEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); + if(pEntry) { + DBGPRINT(RT_DEBUG_TRACE,("===[%s] pEntry->wcid = %d \n", __FUNCTION__, pEntry->wcid)); + mac_info.WCID = pEntry->wcid; + } else { + DBGPRINT(RT_DEBUG_TRACE,("===[%s] ERROR: pEntry == NULL \n", __FUNCTION__)); + } + } + } else if (pHeader_802_11->FC.Type == FC_TYPE_DATA) { + switch (pHeader_802_11->FC.SubType) { + case SUBTYPE_DATA_NULL: + mac_info.hdr_len = 24; + tx_rate = (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS; + transmit = &pAd->CommonCfg.MlmeTransmit; + break; + case SUBTYPE_QOS_NULL: + mac_info.hdr_len = 26; + /*Fill the PID to check TxS of QOS NULL FRAME*/ + PID = PID_QOS_NULL_FRAME; + tx_rate = (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS; + transmit = &pAd->CommonCfg.MlmeTransmit; + break; + default: + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): FIXME!!!Unexpected frame(Type=%d, SubType=%d) send to MgmtRing, need to assign the length!\n", + __FUNCTION__, pHeader_802_11->FC.Type, pHeader_802_11->FC.SubType)); + hex_dump("DataFrame", (char *)pHeader_802_11, 24); + } + break; + } + + if (pMacEntry && pAd->MacTab.tr_entry[wcid].PsDeQWaitCnt) + PID = PID_PS_DATA; + + mac_info.WCID = wcid; + } + else if (pHeader_802_11->FC.Type == FC_TYPE_CNTL) + { + switch (pHeader_802_11->FC.SubType) + { + case SUBTYPE_BLOCK_ACK_REQ: + PID = PID_CTL_BAR; + mac_info.hdr_len = 16; + mac_info.SpeEn = 0; + mac_info.TID = pBar->BarControl.TID; + if (pAd->CommonCfg.Channel > 14) + { /* 2.4G */ + TransmitSetting.field.MODE = MODE_OFDM; + } + else + { /* 5G */ +#ifdef GN_ONLY_AP_SUPPORT + if((pAd->OpMode == OPMODE_STA) || (pAd->OpMode == OPMODE_AP)) { + if(!BMode || bExcludeBRate) + TransmitSetting.field.MODE = MODE_OFDM; + else + TransmitSetting.field.MODE = MODE_CCK; + } + else +#endif + TransmitSetting.field.MODE = MODE_CCK; + } + TransmitSetting.field.BW = BW_20; + TransmitSetting.field.STBC = 0; + TransmitSetting.field.ShortGI = 0; + TransmitSetting.field.MCS = 0; + TransmitSetting.field.ldpc = 0; + transmit = &TransmitSetting; + break; + case SUBTYPE_PS_POLL: + mac_info.hdr_len = sizeof (PSPOLL_FRAME); + tx_rate = (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS; + transmit = &pAd->CommonCfg.MlmeTransmit; + break; + + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s(): FIXME!!!Unexpected frame(Type=%d, SubType=%d) send to MgmtRing, need to assign the length!\n", + __FUNCTION__, pHeader_802_11->FC.Type, pHeader_802_11->FC.SubType)); + break; + } + } + else { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): FIXME!!!Unexpected frame send to MgmtRing, need to assign the length!\n", + __FUNCTION__)); + } +#else + mac_info.Length = (SrcBufLen - TXINFO_SIZE - pAd->chipCap.TXWISize - TSO_SIZE); +#endif /* MT7603 */ + mac_info.PID = PID; + mac_info.TxRate = tx_rate; + mac_info.SpeEn = 1; + mac_info.Preamble = LONG_PREAMBLE; + +#ifdef MT_MAC + // TODO: shiang-MT7603 + mac_info.q_idx = Q_IDX_AC4; + +#endif /* MT_MAC */ + + /* PCI use Miniport to send NULL frame and need to add NULL frame TxS control here to enter PSM */ + DBGPRINT(RT_DEBUG_INFO, ("%s(line=%d), mac_info.PsmBySw(%d)\n", __FUNCTION__, __LINE__, mac_info.PsmBySw)); + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +#ifdef WH_EZ_SETUP + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)) { + pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); + wdev = WdevSearchByAddress(pAd, pHeader_802_11->Addr2); + + if (!wdev) { + RTMP_IRQ_UNLOCK(&pAd->MgmtRingLock, Flags); + return NDIS_STATUS_FAILURE; + } + + if (pMacEntry && IS_EZ_SETUP_ENABLED(wdev) + && wdev->ez_driver_params.need_tx_satus + && (pHeader_802_11->FC.Type == FC_TYPE_MGMT) + && (pHeader_802_11->FC.SubType == SUBTYPE_ACTION) + && ((pHeader_802_11->Octet[0] == CATEGORY_PUBLIC))){ + + wdev->ez_driver_params.need_tx_satus = FALSE; + mac_info.PID = PID_EZ_ACTION; + mac_info.WCID = pMacEntry->wcid; + //TxSTypeCtlPerPkt(pAd, mac_info.PID, TXS_FORMAT0, FALSE, TRUE, FALSE, TXS_DUMP_REPEAT); + } + } +#endif +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef SOFT_SOUNDING + if (((pHeader_802_11->FC.Type == FC_TYPE_DATA) && (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) + && pMacEntry && (pMacEntry->snd_reqired == TRUE)) + { + wcid = RESERVED_WCID; + tx_rate = (UCHAR)pMacEntry->snd_rate.field.MCS; + transmit = &pMacEntry->snd_rate; + + mac_info.Txopmode = IFS_PIFS; + + write_tmac_info(pAd, tmac_info, &mac_info, transmit); + + pMacEntry->snd_reqired = FALSE; + DBGPRINT(RT_DEBUG_OFF, ("%s():Kick Sounding to %02x:%02x:%02x:%02x:%02x:%02x, dataRate(PhyMode:%s, BW:%sHz, %dSS, MCS%d)\n", + __FUNCTION__, PRINT_MAC(pMacEntry->Addr), + get_phymode_str(transmit->field.MODE), + get_bw_str(transmit->field.BW), + (transmit->field.MCS>>4) + 1, (transmit->field.MCS & 0xf))); + } + else +#endif /* SOFT_SOUNDING */ + { + mac_info.Txopmode = IFS_BACKOFF; + + write_tmac_info(pAd, tmac_info, &mac_info, transmit); + +#ifdef SPECIFIC_TX_POWER_SUPPORT +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (pMacEntry == NULL) { + TXWI_STRUC *pFirstTxWI = (TXWI_STRUC *)tmac_info; + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + pFirstTxWI->TXWI_O.TxPwrAdj = TxPwrAdj; +#endif /* RTMP_MAC */ +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + pFirstTxWI->TXWI_N.TxPwrAdj = TxPwrAdj; +#endif /* RLT_MAC */ + } +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + } + +//+++Add by shiang for debug + +//---Add by shiang for debug +//+++Add by shiang for debug +#ifdef DBG +if ((pHeader_802_11->FC.Type == FC_TYPE_CNTL) && (pHeader_802_11->FC.SubType == SUBTYPE_VHT_NDPA)) +{ + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Send VhtNDPA to peer(wcid=%d, pMacEntry=%p) with Mode=%d, txRate=%d, BW=%d\n", + __FUNCTION__, wcid, pMacEntry, transmit->field.MODE, tx_rate, transmit->field.BW)); + hex_dump("VHT_NDPA raw data", pSrcBufVA, SrcBufLen); + dump_tmac_info(pAd, tmac_info); +} +#endif /* DBG */ +//---Add by shiang for debug + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE); +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + MTMacInfoEndianChange(pAd, tmac_info, TYPE_TMACINFO, sizeof(TMAC_TXD_L)); + } +#endif +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (pAd->chipCap.hif_type == HIF_RTMP || pAd->chipCap.hif_type == HIF_RLT) + { + RTMPWIEndianChange(pAd, tmac_info, TYPE_TXWI); + } +#endif +#endif + + + /* Now do hardware-depened kick out.*/ + HAL_KickOutMgmtTx(pAd, mac_info.q_idx, pPacket, pSrcBufVA, SrcBufLen); + +#ifdef CONFIG_HOTSPOT_R2 + if (RTMP_GET_PACKET_DISASSOC(pPacket)) + { + if (((pHeader_802_11->FC.Type == FC_TYPE_MGMT) && + (pHeader_802_11->FC.SubType == SUBTYPE_DISASSOC)) || + ((pHeader_802_11->FC.Type == FC_TYPE_MGMT) && + (pHeader_802_11->FC.SubType == SUBTYPE_DEAUTH))) + { + pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); + } + if ((pMacEntry) && (pMacEntry->IsKeep == 1)) + MacTableDeleteEntry(pAd, pMacEntry->Aid, pMacEntry->Addr); + } +#endif /* CONFIG_HOTSPOT_R2 */ + + /* Make sure to release MGMT ring resource*/ +/* if (!IrqState)*/ + RTMP_IRQ_UNLOCK(&pAd->MgmtRingLock, Flags); + 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(RTMP_ADAPTER *pAd, PNDIS_PACKET pPacket, TX_BLK *pTxBlk) +{ + UCHAR TxFrameType = TX_LEGACY_FRAME; + UCHAR Wcid; + MAC_TABLE_ENTRY *pMacEntry = NULL; + STA_TR_ENTRY *tr_entry = NULL; + + if (RTMP_GET_PACKET_TXTYPE(pPacket) == TX_MCAST_FRAME) + return TX_MCAST_FRAME; + + /* Handle for unicast packets */ + Wcid = RTMP_GET_PACKET_WCID(pPacket); + tr_entry = &pAd->MacTab.tr_entry[Wcid]; + if (Wcid < MAX_LEN_OF_MAC_TABLE) + pMacEntry = &pAd->MacTab.Content[Wcid]; + else + pMacEntry = &pAd->MacTab.Content[MCAST_WCID]; + + pTxBlk->wdev = tr_entry->wdev; + + /* It's a specific packet need to force low rate, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame*/ + if ((RTMP_GET_PACKET_TXTYPE(pPacket) == TX_LEGACY_FRAME) || (pMacEntry->PsMode == PWR_SAVE)) + TxFrameType = TX_LEGACY_FRAME; +#ifdef DOT11_N_SUPPORT + else if (IS_HT_RATE(pMacEntry)) + { + +#ifdef VHT_TXBF_SUPPORT + // TODO: shiang-usw, we should use cb here instead of mark the data type! + if (pMacEntry->TxSndgType == SNDG_TYPE_NDP && IS_VHT_RATE(pMacEntry)) + { +#error + TxFrameType = TX_NDPA_FRAME; + DBGPRINT(RT_DEBUG_OFF, ("%s():Err!! fix me for this!!\n", __FUNCTION__)); + } +#endif + + if (RTMP_GET_PACKET_MOREDATA(pPacket) || (pMacEntry->PsMode == PWR_SAVE)) + TxFrameType = TX_LEGACY_FRAME; + else +#ifdef UAPSD_SUPPORT + if (RTMP_GET_PACKET_EOSP(pPacket)) + TxFrameType = TX_LEGACY_FRAME; + else +#endif /* UAPSD_SUPPORT */ +#ifdef WFA_VHT_PF + if (pAd->force_amsdu == TRUE) + return TX_AMSDU_FRAME; + else +#endif /* WFA_VHT_PF */ + 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; + } +#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))) + ) + { + TxFrameType = TX_RALINK_FRAME; + } + } + + 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(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk) +{ + PACKET_INFO PacketInfo; + PNDIS_PACKET pPacket; + MAC_TABLE_ENTRY *pMacEntry = NULL; + + pPacket = pTxBlk->pPacket; + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); +#ifdef TX_PKT_SG + NdisMoveMemory( &pTxBlk->pkt_info, &PacketInfo, sizeof(PacketInfo)); +#endif /* TX_PKT_SG */ + pTxBlk->Wcid = RTMP_GET_PACKET_WCID(pPacket); + pTxBlk->wdev_idx = RTMP_GET_PACKET_WDEV(pPacket); + + pTxBlk->UserPriority = RTMP_GET_PACKET_UP(pPacket); + pTxBlk->FrameGap = IFS_HTTXOP; +#ifdef CONFIG_AP_SUPPORT + pTxBlk->pMbss = NULL; +#endif /* CONFIG_AP_SUPPORT */ + + if (RTMP_GET_PACKET_CLEAR_EAP_FRAME(pTxBlk->pPacket)) + TX_BLK_SET_FLAG(pTxBlk, fTX_bClearEAPFrame); + else + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bClearEAPFrame); + +#ifdef WAPI_SUPPORT + /* Check if this is an WPI data frame*/ + if ((RTMPIsWapiCipher(pAd, pTxBlk->wdev_idx) == 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->tr_entry->EntryType == ENTRY_CAT_MCAST) + { + pTxBlk->pMacEntry = NULL; + TX_BLK_SET_FLAG(pTxBlk, fTX_ForceRate); + { +#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; + } + + /* AckRequired = FALSE, when broadcast packet in Adhoc mode.*/ + TX_BLK_CLEAR_FLAG(pTxBlk, (fTX_bAckRequired | fTX_bAllowFrag | fTX_bWMM)); + if (RTMP_GET_PACKET_MOREDATA(pPacket)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bMoreData); + } + } + 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 */ + +//YF MCC +#ifdef MULTI_WMM_SUPPORT + if (IS_ENTRY_APCLI(pMacEntry)) + { + pTxBlk->QueIdx = EDCA_WMM1_AC0_PIPE; + printk("%s(): QIdx %d\n", __FUNCTION__, pTxBlk->QueIdx); + } +#endif /* MULTI_WMM_SUPPORT */ + + /* For all unicast packets, need Ack unless the Ack Policy is not set as NORMAL_ACK.*/ +#ifdef MULTI_WMM_SUPPORT + if (pTxBlk->QueIdx >= EDCA_WMM1_AC0_PIPE) + { + if (pAd->CommonCfg.AckPolicy[pTxBlk->QueIdx - EDCA_WMM1_AC0_PIPE] != NORMAL_ACK) + TX_BLK_CLEAR_FLAG(pTxBlk, fTX_bAckRequired); + else + TX_BLK_SET_FLAG(pTxBlk, fTX_bAckRequired); + } + else +#endif /* MULTI_WMM_SUPPORT */ + { + 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_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef WDS_SUPPORT + if(IS_ENTRY_WDS(pMacEntry)) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bWDSEntry); + } + else +#endif /* WDS_SUPPORT */ +#ifdef A4_CONN + if (IS_ENTRY_A4(pMacEntry)) { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pMacEntry)) { + TX_BLK_SET_FLAG(pTxBlk, fTX_bApCliPacket); + if (pMacEntry->func_tb_idx < MAX_APCLI_NUM) + pTxBlk->pApCliEntry = + &pAd->ApCfg.ApCliTab[pMacEntry->func_tb_idx]; + } +#endif /* APCLI_SUPPORT */ + if (!RTMP_GET_PACKET_EAPOL(pTxBlk->pPacket)) + TX_BLK_SET_FLAG(pTxBlk, fTX_bA4Frame); + } else +#endif /* A4_CONN */ +#ifdef APCLI_SUPPORT + if(IS_ENTRY_APCLI(pMacEntry)) + { +#ifdef MAT_SUPPORT + PNDIS_PACKET apCliPkt = NULL; + +#ifdef MAC_REPEATER_SUPPORT + if ((pMacEntry->bReptCli) && (pAd->ApCfg.bMACRepeaterEn)) + { + UCHAR tmpIdx; + + pAd->MatCfg.bMACRepeaterEn = pAd->ApCfg.bMACRepeaterEn; + if(pAd->ApCfg.MACRepeaterOuiMode != 1) + { + tmpIdx = (64 + (MAX_EXT_MAC_ADDR_SIZE * pMacEntry->func_tb_idx) + pMacEntry->MatchReptCliIdx); + // TODO: shiang-lock, fix ME! + apCliPkt = (PNDIS_PACKET)MATEngineTxHandle(pAd, pPacket, tmpIdx, pTxBlk->OpMode); + } + } + else +#endif /* MAC_REPEATER_SUPPORT */ + { + /* For each tx packet, update our MAT convert engine databases.*/ + /* CFG_TODO */ + apCliPkt = (PNDIS_PACKET)MATEngineTxHandle(pAd, pPacket, pMacEntry->func_tb_idx, pTxBlk->OpMode); + } + + if(apCliPkt) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + pPacket = apCliPkt; + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); + pTxBlk->pPacket = apCliPkt; + } +#endif /* MAT_SUPPORT */ + pTxBlk->pApCliEntry = &pAd->ApCfg.ApCliTab[pMacEntry->func_tb_idx]; + TX_BLK_SET_FLAG(pTxBlk, fTX_bApCliPacket); + + } + else +#endif /* APCLI_SUPPORT */ +#ifdef CLIENT_WDS + if (IS_ENTRY_CLIWDS(pMacEntry)) + { + PUCHAR pDA = GET_OS_PKT_DATAPTR(pPacket); + PUCHAR pSA = GET_OS_PKT_DATAPTR(pPacket) + MAC_ADDR_LEN; + if (((pMacEntry->func_tb_idx < MAX_MBSSID_NUM(pAd)) + && !MAC_ADDR_EQUAL(pSA, pAd->ApCfg.MBSSID[pMacEntry->func_tb_idx].Bssid)) + || !MAC_ADDR_EQUAL(pDA, pMacEntry->Addr) + ) + { + TX_BLK_SET_FLAG(pTxBlk, fTX_bClientWDSFrame); + } + } + else +#endif /* CLIENT_WDS */ + if (IS_ENTRY_CLIENT(pMacEntry)) + { } + else + return FALSE; + + /* If both of peer and us support WMM, enable it.*/ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_WMM_INUSED) && CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)) + TX_BLK_SET_FLAG(pTxBlk, fTX_bWMM); + } +#endif /* CONFIG_AP_SUPPORT */ + + } + + if (pTxBlk->TxFrameType == TX_LEGACY_FRAME) + { + if ( ((RTMP_GET_PACKET_LOWRATE(pPacket)) +#ifdef UAPSD_SUPPORT + && (!(pMacEntry && (pMacEntry->bAPSDFlagSPStart))) +#endif /* UAPSD_SUPPORT */ + ) || + ((pAd->OpMode == OPMODE_AP) && (pMacEntry->MaxHTPhyMode.field.MODE == MODE_CCK) && (pMacEntry->MaxHTPhyMode.field.MCS == RATE_1)) + || (RTMP_GET_PACKET_ICMP(pTxBlk->pPacket) && PingFixRate) + ) + { /* Specific packet, i.e., bDHCPFrame, bEAPOLFrame, bWAIFrame, need force low rate. */ + pTxBlk->pTransmit = &pAd->MacTab.Content[MCAST_WCID].HTPhyMode; + TX_BLK_SET_FLAG(pTxBlk, fTX_ForceRate); + +#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); + } +#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); + } +#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(RTMP_ADAPTER *pAd, NDIS_PACKET *pPacket, 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_AP_SUPPORT + /* CFG_TODO */ + if ((MAC_ADDR_EQUAL(GET_OS_PKT_DATAPTR(pTxBlk->pPacket), GET_OS_PKT_DATAPTR(pPacket))) + && (pAd->OpMode == OPMODE_AP)) /* unicast to same STA*/ + return TRUE; + else +#endif /* CONFIG_AP_SUPPORT */ + return FALSE; + +} + + +#ifdef DBG +VOID rtmp_sta_txq_dump(RTMP_ADAPTER *pAd, STA_TR_ENTRY *tr_entry, INT qidx) +{ + ULONG IrqFlags = 0; + QUEUE_ENTRY *entry; + + RTMP_IRQ_LOCK(&pAd->irq_lock /*&tr_entry->txq_lock[qidx]*/, IrqFlags); + + entry = tr_entry->tx_queue[qidx].Head; + DBGPRINT(RT_DEBUG_OFF, ("\nDump TxQ[%d] of TR_ENTRY(ID:%d, MAC:%02x:%02x:%02x:%02x:%02x:%02x): %s, enq_cap=%d\n", + qidx, tr_entry->wcid, PRINT_MAC(tr_entry->Addr), + entry == NULL ? "Empty" : "HasEntry", tr_entry->enq_cap)); + while(entry != NULL) { + DBGPRINT(RT_DEBUG_OFF, (" 0x%p ", entry)); + entry = entry->Next; + if (entry == NULL) { + DBGPRINT(RT_DEBUG_OFF, ("\n")); + } + }; + + RTMP_IRQ_UNLOCK(&pAd->irq_lock /* &tr_entry->txq_lock[qidx]*/, IrqFlags); +} + + +VOID rtmp_tx_swq_dump(RTMP_ADAPTER *pAd, INT qidx) +{ + ULONG IrqFlags = 0; + INT deq_id, enq_id; +#ifdef NEW_IXIA_METHOD + UINT32 mac_val = 0; +#endif +#ifdef DATA_QUEUE_RESERVE + UINT capCount; +#endif /* DATA_QUEUE_RESERVE */ + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + deq_id = pAd->tx_swq[qidx].deqIdx; + enq_id = pAd->tx_swq[qidx].enqIdx; +#ifdef DATA_QUEUE_RESERVE + capCount = (enq_id >=deq_id) ? (TX_SWQ_FIFO_LEN-enq_id+deq_id) : (deq_id-enq_id); + DBGPRINT(RT_DEBUG_OFF, ("\nDump TxSwQ[%d]: DeqIdx=%d, EnqIdx=%d, %s, capCount=%u\n", + qidx, deq_id, enq_id, + (pAd->tx_swq[qidx].swq[deq_id] == 0 ? "Empty" : "HasEntry"), capCount)); +#else /* DATA_QUEUE_RESERVE */ + DBGPRINT(RT_DEBUG_OFF, ("\nDump TxSwQ[%d]: DeqIdx=%d, EnqIdx=%d, %s\n", + qidx, deq_id, enq_id, + (pAd->tx_swq[qidx].swq[deq_id] == 0 ? "Empty" : "HasEntry"))); +#endif /* !DATA_QUEUE_RESERVE */ + + for (; deq_id != enq_id; (deq_id = (deq_id == /*511*/ (TX_SWQ_FIFO_LEN-1) ? 0 : deq_id+1))) + { + DBGPRINT(RT_DEBUG_OFF, (" %d ", pAd->tx_swq[qidx].swq[deq_id])); + } + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + DBGPRINT(RT_DEBUG_OFF, ("\n")); +#ifdef NEW_IXIA_METHOD + RTMP_IO_READ32(pAd, AGG_AALCR, &mac_val); + DBGPRINT(RT_DEBUG_OFF, ("###### * AGGCR = 0x%x * ######\n", mac_val)); + DBGPRINT(RT_DEBUG_OFF, ("###### * Per-Q = %d * ######\n", SQ_ENQ_NORMAL_MAX)); + DBGPRINT(RT_DEBUG_OFF, ("###### * FIFO-Q = %d * ######\n", TX_SWQ_FIFO_LEN)); + DBGPRINT(RT_DEBUG_OFF, ("###### * TX-RingSize = %d * ######\n", TX_RING_SIZE)); + DBGPRINT(RT_DEBUG_OFF, ("###### * RX-RingSize = %d * ######\n", RX_RING_SIZE)); + DBGPRINT(RT_DEBUG_OFF, ("###### * MAX_RX_CNT = %d * ######\n", MAX_RX_PROCESS_CNT)); + DBGPRINT(RT_DEBUG_OFF, ("###### * MAX_REORDERING_MPDU_NUM = %d * ######\n", MAX_REORDERING_MPDU_NUM)); + DBGPRINT(RT_DEBUG_OFF, ("###### * RX_BUFFER_AGGRESIZE = %d * ######\n", RX_BUFFER_AGGRESIZE)); + DBGPRINT(RT_DEBUG_OFF, ("###### * detcect length:%d - %d - %d * ######\n", dectlen_l, dectlen_m, dectlen_h)); +#endif +} +#endif /* DBG */ + + +VOID rtmp_ps_init(RTMP_ADAPTER *pAd) +{ + UINT32 i= 0; + /*initial PS Token Queue*/ + DlListInit(&pAd->psTokenQueue); + + for(i=0;ipsTokenQueue,struct WCID_TABLE,list) + { + DBGPRINT(RT_DEBUG_LOUD,("%d\t",pEntry->wcid)); + } + DBGPRINT(RT_DEBUG_LOUD,("\n")); +} + +INT rtmp_ps_enq(RTMP_ADAPTER *pAd, STA_TR_ENTRY *tr_entry) +{ + struct WCID_TABLE *pEntry; + + if(tr_entry->wcid >= MAX_LEN_OF_TR_TABLE ) + { + return TRUE; + } + + pEntry = &wcid_table[tr_entry->wcid]; + + if( tr_entry->PsTokenFlag != PS_TOKEN_STAT_WCID_PKT) + { + tr_entry->PsTokenFlag = PS_TOKEN_STAT_WCID_PKT; + DlListAdd(&pAd->psTokenQueue,&pEntry->list); + DBGPRINT(RT_DEBUG_LOUD, ("enqueue PS fifo token to Token Queue, WCID: %d,%d.\n", tr_entry->wcid,pEntry->wcid)); + + }else + { + DBGPRINT(RT_DEBUG_LOUD, ("not need enqueue WCID: %d.\n", tr_entry->wcid)); + } + /*rtmp_ps_listforAll(pAd);*/ + return TRUE; +} + +INT rtmp_psDeq_req(RTMP_ADAPTER *pAd) +{ + + STA_TR_ENTRY *tr_entry = NULL; + struct WCID_TABLE *psEntry = NULL, *tmp; + struct tx_swq_fifo *fifo_swq; + + UCHAR cnt=0,i=0; + INT32 capCount=0; + /*remove first psToken now, should check WCID requeue when report*/ + + DlListForEachSafe(psEntry,tmp,&pAd->psTokenQueue,struct WCID_TABLE,list){ + DlListDel(&psEntry->list); + if( psEntry->wcid >= MAX_LEN_OF_TR_TABLE) + { + DBGPRINT(RT_DEBUG_ERROR,("%s(): wcid >MAX_LEN_OF_TR_TABLE \n",__FUNCTION__)); + continue; + } + tr_entry = &pAd->MacTab.tr_entry[psEntry->wcid]; + + if(!tr_entry) + { + DBGPRINT(RT_DEBUG_ERROR,("%s(): tr_entry is NULL \n",__FUNCTION__)); + continue; + } + + if(tr_entry->enqCount <=0) + { + tr_entry->PsTokenFlag = PS_TOKEN_STAT_IDLE; + DBGPRINT(RT_DEBUG_LOUD,("%s(): ps token flag =%d,wcid =%d\n",__FUNCTION__,tr_entry->PsTokenFlag,psEntry->wcid)); + continue; + } + tr_entry->PsTokenFlag = PS_TOKEN_STAT_PKT; + + /*enqueue wcid to sw fifo queue*/ + fifo_swq = &pAd->tx_swq[QID_AC_BE]; + cnt = tr_entry->tx_queue[QID_AC_BE].Number ; + capCount = (fifo_swq->enqIdx >=fifo_swq->deqIdx) ? (TX_SWQ_FIFO_LEN-fifo_swq->enqIdx+fifo_swq->deqIdx) : (fifo_swq->deqIdx-fifo_swq->enqIdx); + cnt = cnt > capCount ? capCount : cnt; + for(i=0;iswq[fifo_swq->enqIdx] != 0) || !(tr_entry->enq_cap)) + { + rtmp_ps_enq(pAd,tr_entry); + DBGPRINT(RT_DEBUG_LOUD,("%s(): fifo is full,flag:%d,enqId:%d,deqId:%d, cap: %d \n",__FUNCTION__,tr_entry->PsTokenFlag,fifo_swq->enqIdx,fifo_swq->deqIdx,tr_entry->enq_cap)); + break; + } + + fifo_swq->swq[fifo_swq->enqIdx] = tr_entry->wcid; + INC_RING_INDEX(fifo_swq->enqIdx, TX_SWQ_FIFO_LEN); + } + + DBGPRINT(RT_DEBUG_LOUD,("%s(): deq for PS retrieve and PSM change. WCID: %d,stat: %d\n",__FUNCTION__,tr_entry->wcid,tr_entry->PsTokenFlag)); + return TRUE; + } + + return TRUE; +} + +INT rtmp_psDeq_report(RTMP_ADAPTER *pAd,struct dequeue_info *info) +{ + STA_TR_ENTRY *tr_entry = NULL; + + tr_entry = &pAd->MacTab.tr_entry[info->cur_wcid]; + if(tr_entry->enqCount > 0 && tr_entry->PsTokenFlag == PS_TOKEN_STAT_PKT) + { + rtmp_ps_enq(pAd,tr_entry); + DBGPRINT(RT_DEBUG_LOUD,("%s(): After DeqReport, re-enq PsToken, WCID: %d,STAT: %d\n",__FUNCTION__,info->target_wcid,tr_entry->PsTokenFlag)); + }else + if(tr_entry->enqCount <= 0 && tr_entry->PsTokenFlag != PS_TOKEN_STAT_IDLE) + { + tr_entry->PsTokenFlag = PS_TOKEN_STAT_IDLE; + DBGPRINT(RT_DEBUG_LOUD,("%s(): After DeqReport, Abort PsToken, WCID: %d,STAT: %d\n",__FUNCTION__,info->target_wcid,tr_entry->PsTokenFlag)); + } + return TRUE; +} + + + +INT rtmp_tx_swq_init(RTMP_ADAPTER *pAd) +{ + ULONG IrqFlags = 0; + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + NdisZeroMemory(pAd->tx_swq, sizeof(pAd->tx_swq)); + rtmp_ps_init(pAd); + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + + return TRUE; +} + + +INT rtmp_tx_swq_exit(RTMP_ADAPTER *pAd, UCHAR wcid) +{ + UCHAR ring_idx, wcid_start, wcid_end; + STA_TR_ENTRY *tr_entry; + ULONG IrqFlags = 0; + PNDIS_PACKET pPacket; + QUEUE_ENTRY *pEntry; + QUEUE_HEADER *pQueue; + + if (wcid == WCID_ALL) { + wcid_start = 0; + wcid_end = MAX_LEN_OF_TR_TABLE - 1; + } else { + if (wcid < MAX_LEN_OF_TR_TABLE) + wcid_start = wcid_end = wcid; + else + { + DBGPRINT(RT_DEBUG_OFF, ("%s():Invalid WCID[%d]\n", + __FUNCTION__, wcid)); + return FALSE; + } + } + + for (wcid = wcid_start; wcid <= wcid_end; wcid++) { + tr_entry = &pAd->MacTab.tr_entry[wcid]; + + if (IS_ENTRY_NONE(tr_entry)) + continue; + + // TODO: shiang-usw, protect "tr_entry->enq_cap" here !! + for (ring_idx = 0; ring_idx < WMM_QUE_NUM; ring_idx++) + { + RTMP_IRQ_LOCK(&pAd->irq_lock /* &tr_entry->txq_lock[ring_idx] */, IrqFlags); + pQueue = &tr_entry->tx_queue[ring_idx]; + while (pQueue->Head) + { + pEntry = RemoveHeadQueue(pQueue); +#ifdef LIMIT_GLOBAL_SW_QUEUE + TR_ENQ_COUNT_DEC(tr_entry, &pAd->TxSwQueue[ring_idx]); +#else /* LIMIT_GLOBAL_SW_QUEUE */ + TR_ENQ_COUNT_DEC(tr_entry); +#endif /*! LIMIT_GLOBAL_SW_QUEUE */ + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + if (pPacket) + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + RTMP_IRQ_UNLOCK(&pAd->irq_lock /* &tr_entry->txq_lock[ring_idx] */, IrqFlags); + } + + RTMP_IRQ_LOCK(&pAd->irq_lock /* &tr_entry->ps_queue_lock */, IrqFlags); + pQueue = &tr_entry->ps_queue; + while (pQueue->Head) + { + pEntry = RemoveHeadQueue(pQueue); + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + if (pPacket) + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + RTMP_IRQ_UNLOCK(&pAd->irq_lock /*&tr_entry->ps_queue_lock*/, IrqFlags); + } + + return TRUE; +} +#ifdef MAX_CONTINUOUS_TX_CNT +BOOLEAN Rtmp_Set_Packet_EnqIdx(PNDIS_PACKET pkt,INT enq_idx) +{ + BOOLEAN retval = FALSE; + USHORT SQIdx; + UCHAR SLowPart,SHighPart; + if((pkt == NULL) || (enq_idx > TX_SWQ_FIFO_LEN) || (enq_idx < 0)) + return retval; + SQIdx = (USHORT)(enq_idx); + SLowPart = (UCHAR)(SQIdx & 0xFF); + SHighPart = (UCHAR)((SQIdx & 0xFF00) >> 8); + RTMP_SET_PACKET_SWQINDEX_LOW(pkt,SLowPart); + RTMP_SET_PACKET_SWQINDEX_HIGH(pkt,SHighPart); + retval = TRUE; + return retval; +} +USHORT Rtmp_Get_Packet_EnqIdx(PNDIS_PACKET pkt) +{ + USHORT GQIdx = 0; + UCHAR GLowPart,GHighPart; + if(pkt == NULL) + return AP_MAX_SWQIDX; + GLowPart = (UCHAR)RTMP_GET_PACKET_SWQINDEX_LOW(pkt); + GHighPart = (UCHAR)RTMP_GET_PACKET_SWQINDEX_HIGH(pkt); + GQIdx = (((USHORT)GHighPart << 8) | GLowPart); + return GQIdx; +} +#endif +#ifdef SW_ATF_SUPPORT +/* +*timer CR:0xbe000508 +*periodCnt:65535 +*1 = 25us +*/ +static UINT32 timerCnt(RTMP_ADAPTER *pAd) +{ + UINT32 cnt; + + cnt = readl((void *)atfFreeTimer); + return cnt; +} +/*65535 is the timer max count */ +static UINT32 timerCntAdjust(INT32 lastTimerCnt, INT32 currentTimerCnt) +{ + if (currentTimerCnt < lastTimerCnt) + currentTimerCnt = freeTimerMaxCnt + currentTimerCnt; + return currentTimerCnt; +} + +#endif +INT rtmp_enq_req(RTMP_ADAPTER *pAd, PNDIS_PACKET pkt, UCHAR qidx, STA_TR_ENTRY *tr_entry, BOOLEAN FlgIsLocked,QUEUE_HEADER *pPktQueue) +{ + ULONG IrqFlags = 0; + BOOLEAN enq_done = FALSE; + INT enq_idx = 0; + struct tx_swq_fifo *fifo_swq; +#ifdef DBG + UCHAR occupied_wcid = 0; +#endif /* DBG */ + QUEUE_ENTRY *pEntry; + UINT capCount = 0; + PNDIS_PACKET tmpPkt; +#ifdef SW_ATF_SUPPORT + UINT32 temp_time; + UINT32 tmp; + UINT32 temp_cnt; + PMAC_TABLE_ENTRY pEntry_tmp = NULL; +#endif + ASSERT(qidx < WMM_QUE_NUM); + ASSERT((tr_entry->wcid != 0)); + + fifo_swq = &pAd->tx_swq[qidx]; + if (FlgIsLocked == FALSE) + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + +#ifdef LIMIT_GLOBAL_SW_QUEUE + if (pAd->MacTab.Size == 1) + { + /* Only check one STA's for WMM unlimit bandwidth test case, + Ex: + Tx BK at begin; Tx BE (start after BK run 10 seconds) + Lower AC (BK) may enqueue much and reach SQ_ENQ_NORMAL_MAX, then let BE drops. + This test case is not WMM standard test case. All test are limited bandwidh. + */ + if ((tr_entry->enqCount > SQ_ENQ_NORMAL_MAX) + && (tr_entry->tx_queue[qidx].Number > SQ_ENQ_RESERVE_PERAC)) + { +#ifdef DBG + occupied_wcid = fifo_swq->swq[enq_idx]; +#endif /* DBG */ + enq_done = FALSE; +#ifdef NEW_IXIA_METHOD + if (IS_EXPECTED_LENGTH(RTPKT_TO_OSPKT(pkt)->len)) + pAd->tr_ststic.txfl[0]++; +#endif + goto enq_end; + } + } + else +#endif /* LIMIT_GLOBAL_SW_QUEUE */ + { + if ((tr_entry->enqCount > SQ_ENQ_NORMAL_MAX)) + { +#ifdef DBG + occupied_wcid = fifo_swq->swq[enq_idx]; +#endif /* DBG */ + enq_done = FALSE; +#ifdef NEW_IXIA_METHOD + if (IS_EXPECTED_LENGTH(RTPKT_TO_OSPKT(pkt)->len)) + pAd->tr_ststic.txfl[0]++; +#endif + goto enq_end; + } + } + + + if(pkt) + { + enq_idx = fifo_swq->enqIdx; +#ifdef DATA_QUEUE_RESERVE + if (RTMP_GET_PACKET_DHCP(pkt) || RTMP_GET_PACKET_EAPOL(pkt) + || RTMP_GET_PACKET_ICMP(pkt)) + { + tr_entry->high_pkt_cnt ++; + } +#endif /* DATA_QUEUE_RESERVE */ + +#ifdef DATA_QUEUE_RESERVE + if (pAd->bQueueRsv) + { + capCount = (fifo_swq->enqIdx >=fifo_swq->deqIdx) ? (TX_SWQ_FIFO_LEN-fifo_swq->enqIdx+fifo_swq->deqIdx) : (fifo_swq->deqIdx-fifo_swq->enqIdx); + if (!(RTMP_GET_PACKET_DHCP(pkt) || RTMP_GET_PACKET_EAPOL(pkt) + || RTMP_GET_PACKET_ICMP(pkt))) + { + if (capCount < FIFO_RSV_FOR_HIGH_PRIORITY) { +#ifdef NEW_IXIA_METHOD + if (IS_EXPECTED_LENGTH(RTPKT_TO_OSPKT(pkt)->len)) + pAd->tr_ststic.txfl[1]++; +#endif + goto enq_end; + } + } + } +#endif /* DATA_QUEUE_RESERVE */ + + if ((fifo_swq->swq[enq_idx] == 0) && (tr_entry->enq_cap)) + { +#ifdef SW_ATF_SUPPORT + /*Only handle low prior data pkt*/ + if ((pAd->AtfParaSet.flagATF == TRUE) && (tr_entry->wcid != MAX_LEN_OF_MAC_TABLE) && + !(RTMP_GET_PACKET_DHCP(pkt) || RTMP_GET_PACKET_EAPOL(pkt) || RTMP_GET_PACKET_ICMP(pkt))) { + pAd->AtfParaSet.currentTimerCnt = timerCnt(pAd); + temp_time = pAd->AtfParaSet.currentTimerCnt; + tmp = timerCntAdjust(pAd->AtfParaSet.lastTimerCnt, pAd->AtfParaSet.currentTimerCnt); + pAd->AtfParaSet.currentTimerCnt = tmp; + pEntry_tmp = &(pAd->MacTab.Content[tr_entry->wcid]); + if ((pEntry_tmp != NULL) && (pEntry_tmp->atfPara.isBadNode == TRUE) + && (pEntry_tmp->atfPara.inTxFlow == TRUE)) { + temp_cnt = pAd->AtfParaSet.lastTimerCnt + pAd->AtfParaSet.dropDelta; + if (pAd->AtfParaSet.currentTimerCnt <= temp_cnt) { + pEntry_tmp->atfPara.enqCount_us++; + if (pEntry_tmp->atfPara.enqCount_us > pEntry_tmp->atfThr.enqCurrentThr) { + enq_done = FALSE; + goto enq_end; + } + } else { + pAd->AtfParaSet.lastTimerCnt = temp_time; + pEntry_tmp->atfPara.enqCount_us = 1; + } + } + } + +#endif + InsertTailQueueAc(pAd, tr_entry, &tr_entry->tx_queue[qidx], + PACKET_TO_QUEUE_ENTRY(pkt)); + fifo_swq->swq[enq_idx] = tr_entry->wcid; + +#ifdef MAX_CONTINUOUS_TX_CNT + Rtmp_Set_Packet_EnqIdx(pkt,enq_idx); + if(pAd->TxSwqCtrl == 1) + { + DBGPRINT(RT_DEBUG_OFF,("%s(%d)enqIdx = %d,tr_entry->wcid = %d\n",__FUNCTION__,__LINE__,fifo_swq->enqIdx,tr_entry->wcid)); + } +#endif + INC_RING_INDEX(fifo_swq->enqIdx, TX_SWQ_FIFO_LEN); +#ifdef LIMIT_GLOBAL_SW_QUEUE + TR_ENQ_COUNT_INC(tr_entry,&pAd->TxSwQueue[qidx]); +#else /* LIMIT_GLOBAL_SW_QUEUE */ + TR_ENQ_COUNT_INC(tr_entry); +#endif /*! LIMIT_GLOBAL_SW_QUEUE */ + enq_done = TRUE; + } else + { +#ifdef DBG + occupied_wcid = fifo_swq->swq[enq_idx]; + enq_done = FALSE; +#endif /* DBG */ +#ifdef DATA_QUEUE_RESERVE + if (RTMP_GET_PACKET_DHCP(pkt) || RTMP_GET_PACKET_EAPOL(pkt) + || RTMP_GET_PACKET_ICMP(pkt)) + { + tr_entry->high_pkt_drop_cnt ++; + } +#endif /* DATA_QUEUE_RESERVE */ +#ifdef NEW_IXIA_METHOD + if (IS_EXPECTED_LENGTH(RTPKT_TO_OSPKT(pkt)->len)) + pAd->tr_ststic.txfl[1]++; +#endif + goto enq_end; + } + } + /*check soft queue is enough*/ + capCount = (fifo_swq->enqIdx >=fifo_swq->deqIdx) ? (TX_SWQ_FIFO_LEN-fifo_swq->enqIdx+fifo_swq->deqIdx) : (fifo_swq->deqIdx-fifo_swq->enqIdx); + /*insert full queue to soft queue*/ + if(pPktQueue && pPktQueue->Number <= capCount) + { + while(pPktQueue->Head) + { + pEntry = RemoveHeadQueue(pPktQueue); + tmpPkt = QUEUE_ENTRY_TO_PACKET(pEntry); + + enq_idx = fifo_swq->enqIdx; + if ((fifo_swq->swq[enq_idx] == 0) && (tr_entry->enq_cap)) { + InsertTailQueueAc(pAd, tr_entry, &tr_entry->tx_queue[qidx],tmpPkt); + fifo_swq->swq[enq_idx] = tr_entry->wcid; + +#ifdef MAX_CONTINUOUS_TX_CNT + Rtmp_Set_Packet_EnqIdx(pkt,enq_idx); +#endif + INC_RING_INDEX(fifo_swq->enqIdx, TX_SWQ_FIFO_LEN); +#ifdef LIMIT_GLOBAL_SW_QUEUE + TR_ENQ_COUNT_INC(tr_entry,&pAd->TxSwQueue[qidx]); +#else /* LIMIT_GLOBAL_SW_QUEUE */ + TR_ENQ_COUNT_INC(tr_entry); +#endif /*! LIMIT_GLOBAL_SW_QUEUE */ + enq_done = TRUE; + } else { +#ifdef DBG + occupied_wcid = fifo_swq->swq[enq_idx]; +#endif /* DBG */ + enq_done = FALSE; + goto enq_end; + } + } + } +enq_end: + if (FlgIsLocked == FALSE) + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_TXQ, + ("%s():EnqPkt(%p) for WCID(%d) to tx_swq[%d].swq[%d] %s\n", + __FUNCTION__, pkt, tr_entry->wcid, qidx, enq_idx, + (enq_done ? "success" : "fail"))); + if (enq_done == FALSE) { +#ifdef DBG_DIAGNOSE + if ((pAd->DiagStruct.inited) && (pAd->DiagStruct.wcid == tr_entry->wcid)) + pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx].enq_fall_cnt[qidx]++; +#endif /* DBG_DIAGNOSE */ + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_TXQ, + ("\t FailedCause =>OccupiedWCID:%d,EnqCap:%d\n", + occupied_wcid, tr_entry->enq_cap)); + } + + if (0 /*(RTDebugFunc & DBG_FUNC_TXQ) == DBG_FUNC_TXQ*/) { + DBGPRINT(RT_DEBUG_OFF, ("%s():EnqSuccess!\n", __FUNCTION__)); + rtmp_tx_swq_dump(pAd, qidx); + rtmp_sta_txq_dump(pAd, tr_entry, qidx); + } + /*add hook point for enqueue progress*/ + RTMP_OS_TXRXHOOK_CALL(WLAN_TX_ENQUEUE_PROGRESS,NULL,qidx,fifo_swq); + + return enq_done; +} + +INT rtmp_deq_req(RTMP_ADAPTER *pAd, INT cnt, struct dequeue_info *info) +{ + CHAR deq_qid = 0, start_q, end_q; + UCHAR deq_wcid; + struct tx_swq_fifo *fifo_swq; + STA_TR_ENTRY *tr_entry = NULL; + + if (!info->inited) { + if (info->target_que < WMM_QUE_NUM) { + info->start_q = info->target_que; + info->end_q = info->target_que; + } + else + { + info->start_q = (WMM_QUE_NUM - 1); + info->end_q = 0; + } + info->cur_q = info->start_q; + + if (info->target_wcid < MAX_LEN_OF_TR_TABLE) { + info->pkt_cnt = cnt; + info->full_qid[0] = FALSE; + info->full_qid[1] = FALSE; + info->full_qid[2] = FALSE; + info->full_qid[3] = FALSE; + } else { + info->q_max_cnt[0] = cnt; + info->q_max_cnt[1] = cnt; + info->q_max_cnt[2] = cnt; + info->q_max_cnt[3] = cnt; + } + info->inited = 1; + } + + start_q = info->cur_q; + end_q = info->end_q; + + /* wcid first */ + if (info->target_wcid < MAX_LEN_OF_TR_TABLE) { + if (info->pkt_cnt <= 0) { + info->status = NDIS_STATUS_FAILURE; +#ifdef DATA_QUEUE_RESERVE + info->status_2 = 1; +#endif /* DATA_QUEUE_RESERVE */ + goto done; + } + + deq_wcid = info->target_wcid; + if (info->target_que >= WMM_QUE_NUM) { + tr_entry = &pAd->MacTab.tr_entry[deq_wcid]; + for (deq_qid = start_q; deq_qid >= end_q; deq_qid--) { + if (info->full_qid[deq_qid] == FALSE && tr_entry->tx_queue[deq_qid].Number) + break; + } + } else if (info->full_qid[info->target_que] == FALSE) { + deq_qid = info->target_que; + } else { + info->status = NDIS_STATUS_FAILURE; +#ifdef DATA_QUEUE_RESERVE + info->status_2 = 2; +#endif /* DATA_QUEUE_RESERVE */ + goto done; + } + + if (deq_qid >= 0) { + info->cur_q = deq_qid; + info->cur_wcid = deq_wcid; + } else { + info->status = NDIS_STATUS_FAILURE; +#ifdef DATA_QUEUE_RESERVE + info->status_2 = 3; +#endif /* DATA_QUEUE_RESERVE */ + } + + goto done; + } + + /* + Start from high queue, + Don't need get "pAd->irq_lock" here becuse already get it by caller + */ + for (deq_qid = start_q; deq_qid >= end_q; deq_qid--) + { + fifo_swq = &pAd->tx_swq[deq_qid]; + deq_wcid = fifo_swq->swq[fifo_swq->deqIdx]; +#ifdef MAX_CONTINUOUS_TX_CNT + while(deq_wcid == 0) + { + if((fifo_swq->enqIdx == fifo_swq->deqIdx) && (fifo_swq->swq[fifo_swq->enqIdx] == 0))/*swq empty*/ + { + break; + } + INC_RING_INDEX(fifo_swq->deqIdx, TX_SWQ_FIFO_LEN); + deq_wcid = fifo_swq->swq[fifo_swq->deqIdx]; + } +#endif + if (deq_wcid == 0) { + DBGPRINT(RT_DEBUG_LOUD | DBG_FUNC_TXQ, + ("%s():tx_swq[%d] emtpy!\n", __FUNCTION__, deq_qid)); + info->q_max_cnt[deq_qid] = 0; + continue; + } + + tr_entry = &pAd->MacTab.tr_entry[deq_wcid]; + + /* If any stations are in Psm, AP will skip this swq and increase deqIdx */ + if (tr_entry->EntryType == ENTRY_CAT_MCAST) + { /* Broadcast/Multicast */ + if (pAd->MacTab.fAnyStationInPsm) + { + DBGPRINT(RT_DEBUG_LOUD | DBG_FUNC_TXQ, + ("!!!B/MCast entry and AP in PSM\n")); + + fifo_swq->swq[fifo_swq->deqIdx] = 0; + INC_RING_INDEX(fifo_swq->deqIdx, TX_SWQ_FIFO_LEN); + continue; + } + } + else + { /* unicast */ + if ((tr_entry->PsMode == PWR_SAVE) +#ifdef MT_PS + ||((tr_entry->ps_state != APPS_RETRIEVE_IDLE) && (tr_entry->ps_state != APPS_RETRIEVE_DONE)) +#endif /* MT_PS */ + ) + { + DBGPRINT(RT_DEBUG_LOUD | DBG_FUNC_TXQ, ("!!!STA in PSM\n")); + + fifo_swq->swq[fifo_swq->deqIdx] = 0; + INC_RING_INDEX(fifo_swq->deqIdx, TX_SWQ_FIFO_LEN); + if (tr_entry->tx_queue[deq_qid].Number > 0) + TR_TOKEN_COUNT_INC(tr_entry, deq_qid); + continue; + } + } + + if (info->q_max_cnt[deq_qid] > 0) { + info->cur_q = deq_qid; + info->cur_wcid = deq_wcid; + info->pkt_cnt = info->q_max_cnt[deq_qid]; + break; + } else { + /* Queue Quota full, go next! */ + } + } + + if (deq_qid < end_q) { + info->cur_q = deq_qid; + info->status = NDIS_STATUS_FAILURE; +#ifdef DATA_QUEUE_RESERVE + info->status_2 = 4; +#endif /* DATA_QUEUE_RESERVE */ + } + +done: + rtmp_psDeq_req(pAd); + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_TXQ, + ("%s(): DeqReq %s, Start/End/Cur Queue=%d/%d/%d\n", + __FUNCTION__, + (info->status == NDIS_STATUS_SUCCESS ? "success" : "fail"), + info->start_q, info->end_q, info->cur_q)); + + if (info->status == NDIS_STATUS_SUCCESS) { + tr_entry = &pAd->MacTab.tr_entry[info->cur_wcid]; + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_TXQ, + ("\tdeq_info=>wcid:%d, qidx:%d, pkt_cnt:%d, q_max_cnt=%d, QueuedNum=%d\n", + info->cur_wcid, info->cur_q, info->pkt_cnt, info->q_max_cnt[deq_qid], + tr_entry->tx_queue[info->cur_q].Number)); + } else { + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_TXQ, + ("\tdeq_info=>wcid:%d, qidx:%d, pkt_cnt:%d\n", + info->cur_wcid, info->cur_q, info->pkt_cnt)); + } + +#ifdef DBG + if (0){ // RTDebugFunc & DBG_FUNC_TXQ) { + if (deq_qid >= 0) { + // cannot call this here because we already get lock but this function will try lock again! + rtmp_tx_swq_dump(pAd, deq_qid); + + if (deq_wcid < MAX_LEN_OF_TR_TABLE) + rtmp_sta_txq_dump(pAd, &pAd->MacTab.tr_entry[deq_wcid], deq_qid); + } + } +#endif /* DBG */ + + return TRUE; +} + + +INT rtmp_deq_report(RTMP_ADAPTER *pAd, struct dequeue_info *info) +{ + UINT tx_cnt = info->deq_pkt_cnt, qidx = info->cur_q; + struct tx_swq_fifo *fifo_swq; +#ifdef MAX_CONTINUOUS_TX_CNT + STA_TR_ENTRY *tr_entry = NULL; + PQUEUE_HEADER pQueue = NULL; +#endif + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_TXQ, + ("%s():Success DeQ(QId=%d) for WCID(%d), PktCnt=%d, TxSWQDeQ/EnQ ID=%d/%d\n", + __FUNCTION__, info->cur_q, info->cur_wcid, info->deq_pkt_cnt, + pAd->tx_swq[qidx].deqIdx, pAd->tx_swq[qidx].enqIdx)); + + if ((qidx < 4) && (tx_cnt > 0)) { + fifo_swq = &pAd->tx_swq[qidx]; + do { + if (fifo_swq->swq[fifo_swq->deqIdx] == info->cur_wcid) { +#ifdef MAX_CONTINUOUS_TX_CNT + tr_entry = &pAd->MacTab.tr_entry[info->cur_wcid]; + tr_entry->tx_queue[info->cur_q].AlreadyDeqCnt++; + if (tr_entry->tx_queue[info->cur_q].AlreadyDeqCnt > 1)//not first packet + { + + if(fifo_swq->swq[info->CurSwqIdx] == info->cur_wcid) + fifo_swq->swq[info->CurSwqIdx] = 0; + if((pAd->TxSwqCtrl == 3) && (tr_entry->tx_queue[info->cur_q].AlreadyDeqCnt %5 ==0)) + DBGPRINT(RT_DEBUG_OFF,("%s(%d)deqidx(%d),curswq(%d),deqcnt(%d),wcid(%d).\n",__FUNCTION__,__LINE__,fifo_swq->deqIdx,info->CurSwqIdx,tr_entry->tx_queue[info->cur_q].AlreadyDeqCnt,info->cur_wcid)); + } + pQueue = &tr_entry->tx_queue[qidx]; + if ((pQueue->Head == NULL) || (tr_entry->tx_queue[info->cur_q].AlreadyDeqCnt >= pAd->ContinousTxCnt))//already TX 21 PKTS, stop and go to next WCID. + { + tr_entry->tx_queue[info->cur_q].AlreadyDeqCnt = 0;//clear current swq[deq_idx] and deq_idx move. + fifo_swq->swq[fifo_swq->deqIdx] = 0; + INC_RING_INDEX(fifo_swq->deqIdx, TX_SWQ_FIFO_LEN); + + if((pAd->TxSwqCtrl == 3)&&(tr_entry->tx_queue[info->cur_q].AlreadyDeqCnt == pAd->ContinousTxCnt)) + DBGPRINT(RT_DEBUG_OFF,("%s(%d)AlreadyDeqCnt = %d DataQueue %s.\n",__FUNCTION__,__LINE__,tr_entry->tx_queue[info->cur_q].AlreadyDeqCnt,(pQueue->Head == NULL?"NULL":"MORE"))); + } +#else + fifo_swq->swq[fifo_swq->deqIdx] = 0; + INC_RING_INDEX(fifo_swq->deqIdx, TX_SWQ_FIFO_LEN); +#endif + tx_cnt--; + } else + break; + }while (tx_cnt != 0); + + if (info->q_max_cnt[qidx] > 0) + info->q_max_cnt[qidx] -= info->deq_pkt_cnt; + + if (info->target_wcid < MAX_LEN_OF_TR_TABLE) + info->pkt_cnt -= info->deq_pkt_cnt; + + //rtmp_tx_swq_dump(pAd, qidx); + //rtmp_sta_txq_dump(pAd, &pAd->MacTab.tr_entry[info->wcid], qidx); + } + + rtmp_psDeq_report(pAd,info); + + if (qidx<4) { + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_TXQ, + ("After DeqReport, tx_swq D/EQIdx=%d/%d, deq_info.q_max_cnt/pkt_cnt=%d/%d\n", + pAd->tx_swq[qidx].deqIdx, pAd->tx_swq[qidx].enqIdx, + info->q_max_cnt[qidx] , info->pkt_cnt)); + } + + + return TRUE; +} + + +#ifdef CONFIG_AP_SUPPORT +INT deq_mgmt_frame(RTMP_ADAPTER *pAd, PNDIS_PACKET pkt, UCHAR qIdx, BOOLEAN bLocked) +{ + NDIS_STATUS Status; + //unsigned long IrqFlags; + +#ifdef RTMP_MAC_PCI + if (RTMP_GET_PACKET_MGMT_PKT_DATA_QUE(pkt) == 1) + { + //DEQUEUE_LOCK(&pAd->irq_lock, bLocked, IrqFlags); + Status = MlmeHardTransmitTxRing(pAd,qIdx,pkt); + //DEQUEUE_UNLOCK(&pAd->irq_lock, bLocked, IrqFlags); + } + else +#endif /* RTMP_MAC_PCI */ + Status = MlmeHardTransmitMgmtRing(pAd,qIdx,pkt); + + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR, ("tx queued mgmt frame error!\n")); + RELEASE_NDIS_PACKET(pAd, pkt, NDIS_STATUS_FAILURE); + } + + return TRUE; +} +#endif /* CONFIG_AP_SUPPORT */ + + +#define TX_FLAG_STOP_DEQUEUE (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |\ + fRTMP_ADAPTER_RADIO_OFF |\ + fRTMP_ADAPTER_RESET_IN_PROGRESS |\ + fRTMP_ADAPTER_HALT_IN_PROGRESS |\ + fRTMP_ADAPTER_NIC_NOT_EXIST |\ + fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET) + +#define ENTRY_RETRY_INTERVAL (100 * OS_HZ / 1000) +static inline BOOLEAN traffic_jam_chk(RTMP_ADAPTER *pAd, STA_TR_ENTRY *tr_entry) +{ + BOOLEAN drop_it = FALSE; + + if (!IS_ENTRY_NONE(tr_entry)) + { + ULONG Now32; + + NdisGetSystemUpTime(&Now32); + +#ifdef CONFIG_AP_SUPPORT +#ifdef WDS_SUPPORT + if (IS_ENTRY_WDS(tr_entry)) + { + if (tr_entry->LockEntryTx && + RTMP_TIME_BEFORE(Now32, tr_entry->TimeStamp_toTxRing + WDS_ENTRY_RETRY_INTERVAL)) + drop_it = TRUE; + } + else +#endif /* WDS_SUPPORT */ + if (tr_entry->ContinueTxFailCnt >= pAd->ApCfg.EntryLifeCheck) + { + if(RTMP_TIME_BEFORE(Now32, tr_entry->TimeStamp_toTxRing + ENTRY_RETRY_INTERVAL)) + drop_it = TRUE; + } + else +#endif /* CONFIG_AP_SUPPORT */ + { + tr_entry->TimeStamp_toTxRing = Now32; + } + } + + return drop_it; +} + + +INT deq_packet_gatter(RTMP_ADAPTER *pAd, struct dequeue_info *deq_info, TX_BLK *pTxBlk, BOOLEAN in_hwIRQ) +{ + STA_TR_ENTRY *tr_entry; + MAC_TABLE_ENTRY *pMacEntry = NULL; + ULONG hwd_cnt = 0; + PQUEUE_ENTRY qEntry = NULL; + PNDIS_PACKET pPacket; + PQUEUE_HEADER pQueue; + //unsigned long IrqFlags; + UCHAR QueIdx = deq_info->cur_q; + UCHAR wcid = deq_info->cur_wcid; +#ifdef MAX_CONTINUOUS_TX_CNT + USHORT SwqIdx = AP_MAX_SWQIDX; +#endif + tr_entry = &pAd->MacTab.tr_entry[wcid]; + if (wcid < MAX_LEN_OF_MAC_TABLE) + pMacEntry = &pAd->MacTab.Content[wcid]; + else + pMacEntry = &pAd->MacTab.Content[MCAST_WCID]; + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_TXQ, ("-->%s(): deq_info->wcid=%d, qidx=%d! hwd_cnt=%lu!\n", + __FUNCTION__, wcid, QueIdx, hwd_cnt)); + + deq_info->deq_pkt_cnt = 0; + + do { + hwd_cnt = GET_TXRING_FREENO(pAd, QueIdx); + pQueue = &tr_entry->tx_queue[QueIdx]; + +dequeue: + if ((qEntry = pQueue->Head) != NULL) + { + qEntry = RemoveHeadQueue(pQueue); +#ifdef LIMIT_GLOBAL_SW_QUEUE + TR_ENQ_COUNT_DEC(tr_entry, &pAd->TxSwQueue[QueIdx]); +#else /* LIMIT_GLOBAL_SW_QUEUE */ + TR_ENQ_COUNT_DEC(tr_entry); +#endif /*! LIMIT_GLOBAL_SW_QUEUE */ + pPacket = QUEUE_ENTRY_TO_PACKET(qEntry); +#ifdef SW_ATF_SUPPORT + if (wcid < MAX_LEN_OF_MAC_TABLE) + pMacEntry->atfPara.deqCount_100ms++; +#endif + ASSERT(RTMP_GET_PACKET_WCID(pPacket) == wcid); +#ifdef MAX_CONTINUOUS_TX_CNT + SwqIdx = Rtmp_Get_Packet_EnqIdx(pPacket); + if(SwqIdx != AP_MAX_SWQIDX){ + deq_info->CurSwqIdx = SwqIdx; + } + if(pAd->TxSwqCtrl == 1) + DBGPRINT(RT_DEBUG_OFF,("%s(%d)deq_info->CurSwqIdx = %d\n",__FUNCTION__,__LINE__,deq_info->CurSwqIdx)); +#endif + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_TXQ, + ("-->%s(): GetPacket, wcid=%d, deq_pkt_cnt=%d, TotalFrameNum=%d\n", + __FUNCTION__, wcid, deq_info->deq_pkt_cnt, pTxBlk->TotalFrameNum)); + +#ifdef CONFIG_AP_SUPPORT + // TODO: shiang-usw, for mgmt frame enqueue to a dataQ but still go through mgmtRing here, is that good?? + if (RTMP_GET_PACKET_MGMT_PKT(pPacket)) { + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_TXQ, ("%s(): Call deq_mgmt_frame()!\n", __FUNCTION__)); + deq_mgmt_frame(pAd, pPacket, QueIdx, in_hwIRQ); + deq_info->deq_pkt_cnt++; + + goto dequeue; + } +#endif /* CONFIG_AP_SUPPORT */ + + // TODO: shiang-usw, remove this check to other place!! + if (traffic_jam_chk(pAd, tr_entry) == TRUE) { + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_TXQ, ("%s(): traffic jam detected! free pkt!\n", __FUNCTION__)); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + + deq_info->deq_pkt_cnt++; +#ifdef NEW_IXIA_METHOD + if (IS_EXPECTED_LENGTH(RTPKT_TO_OSPKT(pPacket)->len)) + pAd->tr_ststic.tx[DROP_TX_JAM]++; +#endif + goto dequeue; + } + + pTxBlk->TxFrameType = TxPktClassification(pAd, pPacket, pTxBlk); + +#ifdef DATA_QUEUE_RESERVE + if (pAd->bQueueRsv) + { + if (pTxBlk->TxFrameType & TX_LEGACY_FRAME) + { + //reserved Tx Ring + if (!(RTMP_GET_PACKET_DHCP(pPacket) || RTMP_GET_PACKET_EAPOL(pPacket) + || RTMP_GET_PACKET_ICMP(pPacket))) + { + hwd_cnt = (hwd_cnt < TX_RING_SIZE_RSV) ? 0 : (hwd_cnt-TX_RING_SIZE_RSV); + } + } + } +#endif /* DATA_QUEUE_RESERVE */ + + if (pTxBlk->TxFrameType & (TX_RALINK_FRAME | TX_AMSDU_FRAME)) { + if (pTxBlk->TotalFrameNum == 0) { + struct tx_swq_fifo *tx_swq = &pAd->tx_swq[QueIdx]; + BOOLEAN tx_swq_empty = FALSE; + UINT diff = 0; + + if (tx_swq->enqIdx > tx_swq->deqIdx) + diff = tx_swq->enqIdx - tx_swq->deqIdx; + else if (tx_swq->enqIdx < tx_swq->deqIdx) + diff = TX_SWQ_FIFO_LEN - tx_swq->deqIdx + tx_swq->enqIdx; + + if (diff == 1) + tx_swq_empty = TRUE; + + if ((tx_swq_empty == TRUE) && + (NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, + hwd_cnt, pTxBlk->TxFrameType))) + { + InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); + #ifdef LIMIT_GLOBAL_SW_QUEUE + TR_ENQ_COUNT_INC(tr_entry, &pAd->TxSwQueue[QueIdx]); + #else /* LIMIT_GLOBAL_SW_QUEUE */ + TR_ENQ_COUNT_INC(tr_entry); + #endif /* ! LIMIT_GLOBAL_SW_QUEUE */ + deq_info->q_max_cnt[QueIdx] = 0; + break; + } + } + else + { + if (CanDoAggregateTransmit(pAd, pPacket, pTxBlk) == FALSE) { + InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); + #ifdef LIMIT_GLOBAL_SW_QUEUE + TR_ENQ_COUNT_INC(tr_entry, &pAd->TxSwQueue[QueIdx]); + #else /* LIMIT_GLOBAL_SW_QUEUE */ + TR_ENQ_COUNT_INC(tr_entry); + #endif /*! LIMIT_GLOBAL_SW_QUEUE */ + goto start_kick; + } + } + } + + + /*Need located here, since RTMP_HAS_ENOUGH_FREE_DESC will use it when USB mode*/ + pTxBlk->QueIdx = QueIdx; +#ifdef MT_MAC +#ifdef USE_BMC + if ((pAd->chipCap.hif_type == HIF_MT) && (pAd->MacTab.fAnyStationInPsm == 1) && (tr_entry->EntryType == ENTRY_CAT_MCAST)) + { + pTxBlk->QueIdx = QID_BMC; + //DATA_QUEUE_RESERVE + hwd_cnt = GET_BMCRING_FREENO(pAd); + } +#endif /* USE_BMC */ +#endif + + /* Early check to make sure we have enoguh Tx Resource. */ + if (!RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, hwd_cnt, pPacket)) + { + pAd->PrivateInfo.TxRingFullCnt++; + InsertHeadQueue(pQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); + #ifdef LIMIT_GLOBAL_SW_QUEUE + TR_ENQ_COUNT_INC(tr_entry, &pAd->TxSwQueue[QueIdx]); + #else /* LIMIT_GLOBAL_SW_QUEUE */ + TR_ENQ_COUNT_INC(tr_entry); + #endif /*! LIMIT_GLOBAL_SW_QUEUE */ + + if (deq_info->target_wcid < MAX_LEN_OF_TR_TABLE) { + deq_info->full_qid[QueIdx] = TRUE; + } else { + deq_info->q_max_cnt[QueIdx] = 0; + } +#ifdef DBG_DIAGNOSE + if (pAd->DiagStruct.inited && pAd->DiagStruct.wcid == pTxBlk->Wcid) { + struct dbg_diag_info *diag_info; + + diag_info = &pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx]; + diag_info->deq_fail_no_resource_cnt[QueIdx]++; + } +#endif /* DBG_DIAGNOSE */ + +#ifdef RTMP_MAC_PCI + DBGPRINT(RT_DEBUG_INFO, ("%s(): No free TxD(hwd_cnt=%ld, SWIDx=%d, CIDX=%d)\n", + __FUNCTION__, hwd_cnt, pAd->TxRing[QueIdx].TxSwFreeIdx, + pAd->TxRing[QueIdx].TxCpuIdx)); +#else + DBGPRINT(RT_DEBUG_INFO, ("%s(): deque break beacuse no free txResource\n", __FUNCTION__)); +#endif /* RTMP_MAC_PCI */ + + break; + } + + pTxBlk->TotalFrameNum++; + /* The real fragment number maybe vary*/ + pTxBlk->TotalFragNum += RTMP_GET_PACKET_FRAGMENTS(pPacket); + pTxBlk->TotalFrameLen += GET_OS_PKT_LEN(pPacket); + + if (pTxBlk->TotalFrameNum == 1) { + + pTxBlk->pPacket = pPacket; + pTxBlk->wdev = tr_entry->wdev; + pTxBlk->tr_entry = tr_entry; + pTxBlk->pMacEntry = pMacEntry; +#ifdef VENDOR_FEATURE1_SUPPORT + pTxBlk->HeaderBuf = (UCHAR *)pTxBlk->HeaderBuffer; +#endif /* VENDOR_FEATURE1_SUPPORT */ + } + + InsertTailQueue(&pTxBlk->TxPacketList, PACKET_TO_QUEUE_ENTRY(pPacket)); + } + else + { + if (pTxBlk->TxPacketList.Number == 0) + { + deq_info->deq_pkt_cnt++; + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_TXQ, ("<--%s():Try deQ a empty Q. pTxBlk.TxPktList.Num=%d, deq_info.pkt_cnt=%d\n", + __FUNCTION__, pTxBlk->TxPacketList.Number, deq_info->pkt_cnt)); + break; + } + } + + if ((pTxBlk->TxFrameType & (TX_RALINK_FRAME | TX_AMSDU_FRAME)) && + (pTxBlk->TotalFrameNum == 1) && (pQueue->Head != NULL)) { + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_TXQ, + ("%s(): ForAMSDU/ARalink, try dequeue more pkt!\n", + __FUNCTION__)); + goto dequeue; + } + +start_kick: + if (pTxBlk->TxFrameType & (TX_RALINK_FRAME | TX_AMSDU_FRAME)) + { + if (pTxBlk->TxPacketList.Number == 1) + pTxBlk->TxFrameType = TX_LEGACY_FRAME; + } + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_TXQ, ("<--%s():pTxBlk.TxPktList.Num=%d, deq_info.pkt_cnt=%d\n", + __FUNCTION__, pTxBlk->TxPacketList.Number, deq_info->pkt_cnt)); + break; + } while(pTxBlk->TxPacketList.Number < deq_info->pkt_cnt); + + if (pTxBlk->TxPacketList.Number > 0) { + deq_info->deq_pkt_cnt += pTxBlk->TxPacketList.Number; + return TRUE; + } + else + 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 RTMP_ADAPTER *pAd, + IN BOOLEAN in_hwIRQ, + IN UCHAR QIdx, + IN INT wcid, + IN INT max_cnt) +{ + //NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + INT Count = 0, round = 0; + TX_BLK TxBlk, *pTxBlk = &TxBlk; + UCHAR QueIdx = 0; + unsigned long IrqFlags = 0; + struct dequeue_info deq_info = {0}; + +#ifdef DATA_QUEUE_RESERVE + INT real_tx = 0; +#endif /* DATA_QUEUE_RESERVE */ + + +#ifdef DBG_DIAGNOSE + if (pAd->DiagStruct.inited) + dbg_diag_deque_log(pAd); +#endif /* DBG_DIAGNOSE */ + + //NdisZeroMemory((UCHAR *)&deq_info, sizeof(deq_info)); + + deq_info.target_wcid = ((wcid == WCID_ALL) ? MAX_LEN_OF_TR_TABLE : wcid); + deq_info.target_que = QIdx; + + do + { + // TODO: shiang-usw, for another two options "IS_P2P_ABSENCE(pAd)" and RTMP_TEST_MORE_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUE) + // TODO: we need to take care that for per-entry based control "tr_entry->deq_cap" + if (RTMP_TEST_FLAG(pAd, TX_FLAG_STOP_DEQUEUE)) + break; + + round++; + + DEQUEUE_LOCK(&pAd->irq_lock, in_hwIRQ, IrqFlags); + + rtmp_deq_req(pAd, max_cnt, &deq_info); + if (deq_info.status == NDIS_STATUS_FAILURE) { + DEQUEUE_UNLOCK(&pAd->irq_lock, in_hwIRQ, IrqFlags); + break; + } + + QueIdx = deq_info.cur_q; + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_TXQ, ("%s(): deq_info:cur_wcid=%d, cur_qidx=%d, pkt_cnt=%d, pkt_bytes=%d\n", + __FUNCTION__, deq_info.cur_wcid, QueIdx, deq_info.pkt_cnt, deq_info.pkt_bytes)); + + NdisZeroMemory((UCHAR *)pTxBlk, sizeof(TX_BLK)); + + RTMP_START_DEQUEUE(pAd, QueIdx, IrqFlags); + + deq_packet_gatter(pAd, &deq_info, pTxBlk, in_hwIRQ); + if (pTxBlk->TotalFrameNum) { +#ifdef DATA_QUEUE_RESERVE + real_tx += pTxBlk->TotalFrameNum; +#endif /* DATA_QUEUE_RESERVE */ + ASSERT(pTxBlk->wdev); + + ASSERT(pTxBlk->wdev->wdev_hard_tx); + if (pTxBlk->wdev && pTxBlk->wdev->wdev_hard_tx) { + pTxBlk->wdev->wdev_hard_tx(pAd, pTxBlk); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():ERR! pTxBlk->wdev=%p, wdev_hard_tx=%p\n", + __FUNCTION__, pTxBlk->wdev, + pTxBlk->wdev ? pTxBlk->wdev->wdev_hard_tx : NULL)); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + /*Status =*/ APHardTransmit(pAd, pTxBlk); +#endif /* CONFIG_AP_SUPPORT */ + } + + Count += pTxBlk->TotalFrameNum; + } + + RTMP_STOP_DEQUEUE(pAd, QueIdx, IrqFlags); + + rtmp_deq_report(pAd, &deq_info); + + DEQUEUE_UNLOCK(&pAd->irq_lock, in_hwIRQ, IrqFlags); + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_TXQ, ("%s(): deq_packet_gatter %s, TotalFrmNum=%d\n", + __FUNCTION__, (pTxBlk->TotalFrameNum > 0 ? "success" : "fail"), + pTxBlk->TotalFrameNum)); + +#ifdef RTMP_MAC_PCI + if (++pAd->FifoUpdateDone >= FIFO_STAT_READ_PERIOD) + { + // TODO: shiang-usw, check this because of REG access here!! + NICUpdateFifoStaCounters(pAd); + pAd->FifoUpdateDone = 0; + } +#endif /* RTMP_MAC_PCI */ + + if (round >= 1024) { + DBGPRINT(RT_DEBUG_OFF, ("%s():ForceToBreak!!Buggy here?\n", __FUNCTION__)); + break; + } + + }while(1); + + +#ifdef DATA_QUEUE_RESERVE + if(pAd->bDump) + { + //(TBTT's) de-queue BE bcast pkt check point + if ((wcid == MAX_LEN_OF_MAC_TABLE) && (max_cnt !=0) && (QIdx ==0)) + { + if (real_tx!= max_cnt) + { + pAd->dequeu_fail_cnt++; + + } + } + } +#endif /* DATA_QUEUE_RESERVE */ + + +#ifdef DBG_DEQUE + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_TXQ, + ("--->%s():DeQueueRule:WCID[%d], Que[%d]\n", + __FUNCTION__, deq_info.target_wcid, deq_info.target_que)); +#endif /* DBG_DEQUE */ + +#ifdef DBG_DIAGNOSE + if (pAd->DiagStruct.inited) { + struct dbg_diag_info *diag_info; + + diag_info = &pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx]; + diag_info->deq_called++; + diag_info->deq_round += round; + if (Count < 8) + diag_info->deq_cnt[Count]++; + else + diag_info->deq_cnt[8]++; + } +#endif /* DBG_DIAGNOSE */ + + +#ifdef BLOCK_NET_IF + ASSERT((QueIdx < NUM_OF_TX_RING)); + if ((pAd->blockQueueTab[QueIdx].SwTxQueueBlockFlag == TRUE) + && /* (pAd->TxSwQueue[QueIdx].Number < 1)*/ + (pAd->tx_swq[QueIdx].enqIdx == pAd->tx_swq[QueIdx].deqIdx) + ) + { + 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(RTMP_ADAPTER *pAd, UCHAR Rate, 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; +} + + +/* + NOTE: we do have an assumption here, that Byte0 and Byte1 + always reasid at the same scatter gather buffer + */ +static inline VOID Sniff2BytesFromNdisBuffer( + IN PNDIS_BUFFER buf, + IN UCHAR offset, + OUT UCHAR *p0, + OUT UCHAR *p1) +{ + UCHAR *ptr = (UCHAR *)(buf + offset); + *p0 = *ptr; + *p1 = *(ptr + 1); +} + + +#define ETH_TYPE_VLAN 0x8100 +#define ETH_TYPE_IPv4 0x0800 +#define ETH_TYPE_IPv6 0x86dd +#define ETH_TYPE_ARP 0x0806 +#define ETH_TYPE_EAPOL 0x888e +#define ETH_TYPE_WAI 0x88b4 + +#define IP_VER_CODE_V4 0x40 +#define IP_VER_CODE_V6 0x60 +#define IP_PROTO_UDP 0x11 +#define IP_HDR_LEN 20 +#define ETH_HDR_LEN 14 + +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) +BOOLEAN is_gratuitous_arp(UCHAR *pData) +{ + UCHAR *Pos = pData; + UINT16 ProtoType; + UCHAR *SenderIP; + UCHAR *TargetIP; + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_ARP) + { + /* + * Check if Gratuitous ARP, Sender IP equal Target IP + */ + SenderIP = Pos + 14; + TargetIP = Pos + 24; + if (NdisCmpMemory(SenderIP, TargetIP, 4) == 0) { + DBGPRINT(RT_DEBUG_TRACE, ("The Packet is GratuitousARP\n")); + return TRUE; + } + } + + return FALSE; +} + +BOOLEAN is_dad_packet(RTMP_ADAPTER *pAd, UCHAR *pData) +{ + UCHAR *pSenderIP = pData + 16; +#ifdef MAC_REPEATER_SUPPORT + UCHAR *pSourceMac = pData + 10; + UCHAR isLinkValid; +#endif + UCHAR *pDestMac = pData + 20; + UCHAR ZERO_IP_ADDR[4] = {0x00, 0x00, 0x00, 0x00}; + UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + /* + * Check if DAD packet + */ + if ( +#ifdef MAC_REPEATER_SUPPORT + (RTMPLookupRepeaterCliEntry(pAd, FALSE, pSourceMac, TRUE, &isLinkValid) != NULL) && +#endif + ((MAC_ADDR_EQUAL(pDestMac, BROADCAST_ADDR) == TRUE) || + (MAC_ADDR_EQUAL(pDestMac, ZERO_MAC_ADDR) == TRUE)) && + (RTMPEqualMemory(pSenderIP, ZERO_IP_ADDR, 4) == TRUE)) { + DBGPRINT(RT_DEBUG_TRACE, ("DAD found, and do not send this packet\n")); + return TRUE; + } + + return FALSE; +} +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +BOOLEAN is_looping_packet(RTMP_ADAPTER *pAd, NDIS_PACKET *pPacket) +{ + UCHAR *pSrcBuf; + UINT16 TypeLen; + UCHAR Byte0, Byte1; + if (!pAd) + return FALSE; + pSrcBuf = GET_OS_PKT_DATAPTR(pPacket); + ASSERT(pSrcBuf); + /* get Ethernet protocol field and skip the Ethernet Header */ + TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13]; + + pSrcBuf += LENGTH_802_3; + + if (TypeLen <= 1500) + { + /* + 802.3, 802.3 LLC: + DestMAC(6) + SrcMAC(6) + Lenght(2) + + DSAP(1) + SSAP(1) + Control(1) + + if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header. + => + SNAP (5, OriginationID(3) + etherType(2)) + else + => It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it + */ + if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03) + { + Sniff2BytesFromNdisBuffer((PNDIS_BUFFER)pSrcBuf, 6, &Byte0, &Byte1); + TypeLen = (USHORT)((Byte0 << 8) + Byte1); + pSrcBuf += LENGTH_802_1_H; /* Skip this LLC/SNAP header*/ + } + else + { + return FALSE;; + } + } + + if (TypeLen == ETH_TYPE_ARP) + { + /* AP's tx shall check DAD.*/ + if (is_dad_packet(pAd, pSrcBuf - 2) || is_gratuitous_arp(pSrcBuf - 2)) + return TRUE; + } + + return FALSE; +} + +void set_wf_fwd_cb(RTMP_ADAPTER *pAd, PNDIS_PACKET pPacket, struct wifi_dev *wdev) +{ + struct sk_buff *pOsRxPkt = RTPKT_TO_OSPKT(pPacket); + RTMP_CLEAN_PACKET_BAND(pOsRxPkt); + RTMP_CLEAN_PACKET_RECV_FROM(pOsRxPkt); + + if (pAd->CommonCfg.Channel >= H_CHANNEL_BIGGER_THAN) + { + RTMP_SET_PACKET_BAND(pOsRxPkt, RTMP_PACKET_SPECIFIC_5G_H); + if (wdev->wdev_type == WDEV_TYPE_AP) + { + RTMP_SET_PACKET_RECV_FROM(pOsRxPkt, RTMP_PACKET_RECV_FROM_5G_H_AP); + } + else if ((wdev->wdev_type == WDEV_TYPE_STA) )//|| (wdev->wdev_type == WDEV_TYPE_REPEATER)) + { + RTMP_SET_PACKET_RECV_FROM(pOsRxPkt, RTMP_PACKET_RECV_FROM_5G_H_CLIENT); + } + else + { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("No Setting RTMP_SET_PACKET_RECV_FROM(5G_H) wdev->channel(%d) wdev->wdev_type(%d)\n", pAd->CommonCfg.Channel, wdev->wdev_type)); + } + + + } + else if (pAd->CommonCfg.Channel > 14) + { + RTMP_SET_PACKET_BAND(pOsRxPkt, RTMP_PACKET_SPECIFIC_5G); + if (wdev->wdev_type == WDEV_TYPE_AP) + { + RTMP_SET_PACKET_RECV_FROM(pOsRxPkt, RTMP_PACKET_RECV_FROM_5G_AP); + } + else if ((wdev->wdev_type == WDEV_TYPE_STA)) //|| (wdev->wdev_type == WDEV_TYPE_REPEATER)) + { + RTMP_SET_PACKET_RECV_FROM(pOsRxPkt, RTMP_PACKET_RECV_FROM_5G_CLIENT); + } + else + { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("No Setting RTMP_SET_PACKET_RECV_FROM(5G) wdev->channel(%d) wdev->wdev_type(%d)\n", pAd->CommonCfg.Channel, wdev->wdev_type)); + } + + } + else + { + RTMP_SET_PACKET_BAND(pOsRxPkt, RTMP_PACKET_SPECIFIC_2G); + + if (wdev->wdev_type == WDEV_TYPE_AP) + { + RTMP_SET_PACKET_RECV_FROM(pOsRxPkt, RTMP_PACKET_RECV_FROM_2G_AP); + } + else if ((wdev->wdev_type == WDEV_TYPE_STA)) //|| (wdev->wdev_type == WDEV_TYPE_REPEATER)) + { + RTMP_SET_PACKET_RECV_FROM(pOsRxPkt, RTMP_PACKET_RECV_FROM_2G_CLIENT); + } + else + { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("No Setting RTMP_SET_PACKET_RECV_FROM(2G) wdev->channel(%d) wdev->wdev_type(%d)\n", pAd->CommonCfg.Channel, wdev->wdev_type)); + } + } + + //MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_WARN,("set_wf_fwd_cb: wdev_idx=0x%x, wdev_type=0x%x, func_idx=0x%x=> BandFrom:0x%x, RecvdFrom: 0x%x\n", + // wdev->wdev_idx,wdev->wdev_type,wdev->func_idx, + // RTMP_GET_PACKET_BAND(pOsRxPkt),RTMP_GET_PACKET_RECV_FROM(pOsRxPkt))); + +} +#endif +#endif /* CONFIG_WIFI_PKT_FWD */ + +VOID CheckQosMapUP(PMAC_TABLE_ENTRY pEntry, UCHAR DSCP, PUCHAR pUserPriority) +{ +#if defined(CONFIG_AP_SUPPORT) && defined(CONFIG_HOTSPOT_R2) + UCHAR i = 0, find_up = 0, dscpL = 0, dscpH = 0; + BSS_STRUCT *pMbss = NULL; + STA_TR_ENTRY *tr_entry = NULL; + RTMP_ADAPTER *pAd = NULL; + + if (pEntry == NULL || pEntry->wdev == NULL) + { + return; + } + else + { + pAd = (RTMP_ADAPTER *)pEntry->pAd; + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + } + + if (IS_ENTRY_CLIENT(tr_entry)) + pMbss = (BSS_STRUCT *)pEntry->wdev->func_dev; + else + return; + + if (pEntry->QosMapSupport && pMbss->HotSpotCtrl.QosMapEnable) { + for (i=0;i<(pEntry->DscpExceptionCount/2);i++) { + if ((pEntry->DscpException[i] & 0xff) == DSCP) { + *pUserPriority = (pEntry->DscpException[i]>>8) & 0xff; + find_up = 1; + break; + } + } + + if (!find_up) { + for (i=0;i<8;i++) { + dscpL = pEntry->DscpRange[i] & 0xff; + dscpH = (pEntry->DscpRange[i]>>8) & 0xff; + if ((DSCP <= dscpH) && (DSCP >= dscpL)) { + *pUserPriority = i; + break; + } + } + } + } +#endif /* defined(CONFIG_AP_SUPPORT) && defined(CONFIG_HOTSPOT_R2) */ +} + + +/* + Check the Ethernet Frame type, and set RTMP_SET_PACKET_SPECIFIC flags + Here we set the PACKET_SPECIFIC flags(LLC, VLAN, DHCP/ARP, EAPOL). +*/ +#ifdef MULTI_CLIENT_SUPPORT +extern INT FarDropRssi; +#endif +BOOLEAN RTMPCheckEtherType( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN STA_TR_ENTRY *tr_entry, + IN struct wifi_dev *wdev, + OUT UCHAR *pUserPriority, + OUT UCHAR *pQueIdx, + OUT UCHAR *pWcid) +{ + UINT16 TypeLen; + UCHAR Byte0, Byte1, *pSrcBuf, up = 0; + MAC_TABLE_ENTRY *pMacEntry = &pAd->MacTab.Content[tr_entry->wcid]; +#ifdef MULTI_CLIENT_SUPPORT + CHAR Rssi = -127; +#endif +#ifdef DATA_QUEUE_RESERVE + UCHAR *pUdpHdr, *bootpHdr, *dhcp_msg_type, *pCliHwAddr; +#endif /* DATA_QUEUE_RESERVE */ + + if(pAd->bPingLog) + { + pSrcBuf = GET_OS_PKT_DATAPTR(pPacket); + CheckICMPPacket(pAd, pSrcBuf, 0); + } + pSrcBuf = GET_OS_PKT_DATAPTR(pPacket); + ASSERT(pSrcBuf); + + RTMP_SET_PACKET_SPECIFIC(pPacket, 0); + + /* get Ethernet protocol field and skip the Ethernet Header */ + TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13]; + pSrcBuf += LENGTH_802_3; + if (TypeLen <= 1500) + { + /* + 802.3, 802.3 LLC: + DestMAC(6) + SrcMAC(6) + Lenght(2) + + DSAP(1) + SSAP(1) + Control(1) + + if the DSAP = 0xAA, SSAP=0xAA, Contorl = 0x03, it has a 5-bytes SNAP header. + => + SNAP (5, OriginationID(3) + etherType(2)) + else + => It just has 3-byte LLC header, maybe a legacy ether type frame. we didn't handle it + */ + if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03) + { + Sniff2BytesFromNdisBuffer((PNDIS_BUFFER)pSrcBuf, 6, &Byte0, &Byte1); + RTMP_SET_PACKET_LLCSNAP(pPacket, 1); + TypeLen = (USHORT)((Byte0 << 8) + Byte1); + pSrcBuf += LENGTH_802_1_H; /* Skip this LLC/SNAP header*/ + } else { + return FALSE; + } + } + + /* If it's a VLAN packet, get the real Type/Length field.*/ + if (TypeLen == ETH_TYPE_VLAN) + { +#ifdef CONFIG_AP_SUPPORT + /* + 802.3 VLAN packets format: + + DstMAC(6B) + SrcMAC(6B) + + 802.1Q Tag Type (2B = 0x8100) + Tag Control Information (2-bytes) + + Length/Type(2B) + + data payload (42-1500 bytes) + + FCS(4B) + + VLAN tag: 3-bit UP + 1-bit CFI + 12-bit VLAN ID + */ + + /* No matter unicast or multicast, discard it if not my VLAN packet. */ + if (wdev->VLAN_VID != 0) + { + USHORT vlan_id = *(USHORT *)pSrcBuf; + + vlan_id = cpu2be16(vlan_id); + vlan_id = vlan_id & 0x0FFF; /* 12 bit */ + if (vlan_id != wdev->VLAN_VID) { +DBGPRINT(RT_DEBUG_OFF, ("%s():failed for VLAN_ID(vlan_id=%d, VLAN_VID=%d)\n", + __FUNCTION__, vlan_id, wdev->VLAN_VID)); + return FALSE; + } + } +#endif /* CONFIG_AP_SUPPORT */ + + RTMP_SET_PACKET_VLAN(pPacket, 1); + Sniff2BytesFromNdisBuffer((PNDIS_BUFFER)pSrcBuf, 2, &Byte0, &Byte1); + TypeLen = (USHORT)((Byte0 << 8) + Byte1); + + /* only use VLAN tag as UserPriority setting */ + up = (*pSrcBuf & 0xe0) >> 5; + CheckQosMapUP(pMacEntry, (*pSrcBuf & 0xfc) >> 2, &up); + + + + pSrcBuf += LENGTH_802_1Q; /* Skip the VLAN Header.*/ + } + else if (TypeLen == ETH_TYPE_IPv4) + { + /* + 0 4 8 14 15 31(Bits) + +---+----+-----+----+---------------+ + |Ver | IHL |DSCP |ECN | TotalLen | + +---+----+-----+----+---------------+ + Ver - 4bit Internet Protocol version number. + IHL - 4bit Internet Header Length + DSCP - 6bit Differentiated Services Code Point(TOS) + ECN - 2bit Explicit Congestion Notification + TotalLen - 16bit IP entire packet length(include IP hdr) + */ + up = (*(pSrcBuf + 1) & 0xe0) >> 5; + CheckQosMapUP(pMacEntry, (*(pSrcBuf+1) & 0xfc) >> 2, &up); + } + else if (TypeLen == ETH_TYPE_IPv6) + { + /* + 0 4 8 12 16 31(Bits) + +---+----+----+----+---------------+ + |Ver | TrafficClas | Flow Label | + +---+----+----+--------------------+ + Ver - 4bit Internet Protocol version number. + TrafficClas - 8bit traffic class field, the 6 most-significant bits used for DSCP + */ + up = ((*pSrcBuf) & 0x0e) >> 1; + CheckQosMapUP(pMacEntry, ((*pSrcBuf & 0x0f) << 2)|((*(pSrcBuf+1)) & 0xc0) >> 6, &up); + } + + + switch (TypeLen) + { + case ETH_TYPE_IPv4: + { +#ifdef DBG + UINT32 pktLen = GET_OS_PKT_LEN(pPacket); + ASSERT((pktLen > (ETH_HDR_LEN + IP_HDR_LEN))); /* 14 for ethernet header, 20 for IP header*/ +#endif /* DBG */ + RTMP_SET_PACKET_IPV4(pPacket, 1); + if (*(pSrcBuf + 9) == IP_PROTO_UDP) + { + UINT16 srcPort, dstPort; + +#ifdef DATA_QUEUE_RESERVE + pUdpHdr = (pSrcBuf + IP_HDR_LEN); + bootpHdr = pUdpHdr + 8; +#endif /* DATA_QUEUE_RESERVE */ + + pSrcBuf += IP_HDR_LEN; + srcPort = OS_NTOHS(get_unaligned((PUINT16)(pSrcBuf))); + dstPort = OS_NTOHS(get_unaligned((PUINT16)(pSrcBuf+2))); + + if ((srcPort==0x44 && dstPort==0x43) || (srcPort==0x43 && dstPort==0x44)) + { /*It's a BOOTP/DHCP packet*/ + RTMP_SET_PACKET_DHCP(pPacket, 1); + RTMP_SET_PACKET_TXTYPE(pPacket, TX_LEGACY_FRAME); + +#ifdef DATA_QUEUE_RESERVE + if(pAd->bDump) + { + dhcp_msg_type = (bootpHdr+ (28 + 6 + 10 + 64+ 128 + 4)); + dhcp_msg_type += 2; + pCliHwAddr = (bootpHdr+28); + + if (*(dhcp_msg_type) == 2) + DBGPRINT(RT_DEBUG_ERROR, ("@@@ %s() DHCP OFFER to rept mac=%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, PRINT_MAC(pCliHwAddr))); + + if (*(dhcp_msg_type) == 5) + DBGPRINT(RT_DEBUG_ERROR, ("@@@ %s() DHCP ACK to rept mac=%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, PRINT_MAC(pCliHwAddr))); + + if (*(dhcp_msg_type) == 6) + DBGPRINT(RT_DEBUG_ERROR, ("@@@ %s() DHCP NACK to rept mac=%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, PRINT_MAC(pCliHwAddr))); + + if (*(dhcp_msg_type) == 8) + DBGPRINT(RT_DEBUG_ERROR, ("@@@ %s() DHCP INFORM to rept mac=%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, PRINT_MAC(pCliHwAddr))); + } +#endif /* DATA_QUEUE_RESERVE */ + + } +#ifdef AIRPLAY_SUPPORT + if ((srcPort==5353 && dstPort==5353)) + { + DBGPRINT(RT_DEBUG_TRACE, ("this is mDns packet from upper layer ..... on V4\n")); + RTMP_SET_PACKET_EAPOL(pPacket, 1); + RTMP_SET_PACKET_TXTYPE(pPacket, TX_LEGACY_FRAME); + } +#endif /* AIRPLAY_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef CONFIG_DOT11V_WNM + WNMIPv4ProxyARPCheck(pAd, pPacket, srcPort, dstPort, pSrcBuf); +#endif +#ifdef CONFIG_HOTSPOT + { + USHORT Wcid = RTMP_GET_PACKET_WCID(pPacket); + if (!HSIPv4Check(pAd, &Wcid, pPacket, pSrcBuf, srcPort, dstPort)) + return FALSE; + } +#endif +#endif + } + else if (*(pSrcBuf + 9) == 0x01) + { + pSrcBuf += IP_HDR_LEN; + + if ((*pSrcBuf == 0x08) || + (*pSrcBuf == 0x00)) + { + RTMP_SET_PACKET_ICMP(pPacket, 1); + RTMP_SET_PACKET_TXTYPE(pPacket, TX_LEGACY_FRAME); + DBGPRINT(RT_DEBUG_TRACE, ("%s,%-3d/%-3d,RTMP_SET_PACKET_ICMP\n", + __FUNCTION__,pMacEntry->RssiSample.AvgRssi[0],pMacEntry->RssiSample.AvgRssi[1])); + } + } + +#ifdef MULTI_CLIENT_SUPPORT + //BY_MC_ON + if (is_multiclient_mode_on(pAd) > 0) + { + Rssi = RTMPAvgRssi(pAd, &pMacEntry->RssiSample); + + if (Rssi < FarDropRssi) + { + if ((!RTMP_GET_PACKET_DHCP(pPacket)) //dhcp + && (*(pSrcBuf + 9) != 0x01)) //icmp + { printk("WCID:%d,Rssi:%d,Drop data packet:\n", RTMP_GET_PACKET_WCID(pPacket),Rssi); + return FALSE; + } + } + } +#endif + } + break; + case ETH_TYPE_ARP: + { +#ifdef CONFIG_AP_SUPPORT +#ifdef CONFIG_DOT11V_WNM + BSS_STRUCT *pMbss = (BSS_STRUCT *)wdev->func_dev; + if (pMbss->WNMCtrl.ProxyARPEnable) + { + /* Check if IPv4 Proxy ARP Candidate from DS */ + if (IsIPv4ProxyARPCandidate(pAd, pSrcBuf - 2)) + { + BOOLEAN FoundProxyARPEntry; + FoundProxyARPEntry = IPv4ProxyARP(pAd, pMbss, pSrcBuf - 2, TRUE); + if (!FoundProxyARPEntry) + DBGPRINT(RT_DEBUG_TRACE, ("Can not find proxy entry\n")); + + return FALSE; + } + } +#endif +#ifdef CONFIG_HOTSPOT + if (pMbss->HotSpotCtrl.HotSpotEnable) + { + if (!pMbss->HotSpotCtrl.DGAFDisable) + { + if (IsGratuitousARP(pAd, pSrcBuf - 2, pSrcBuf-14, pMbss)) + return FALSE; + } + } + +#endif +#endif +#if defined (CONFIG_WIFI_PKT_FWD) + if (wdev->wdev_type == WDEV_TYPE_AP) { + /* AP's tx shall check DAD.*/ + if (is_dad_packet(pAd, pSrcBuf - 2) || is_gratuitous_arp(pSrcBuf - 2)) + return FALSE; + } +#endif /* CONFIG_WIFI_PKT_FWD */ + RTMP_SET_PACKET_DHCP(pPacket, 1); + RTMP_SET_PACKET_TXTYPE(pPacket, TX_LEGACY_FRAME); + } + break; + case ETH_P_IPV6: + { +#ifdef CONFIG_AP_SUPPORT +#ifdef CONFIG_DOT11V_WNM + BSS_STRUCT *pMbss = (BSS_STRUCT *)wdev->func_dev; + WNMIPv6ProxyARPCheck(pAd, pPacket, pSrcBuf); + if (pMbss->WNMCtrl.ProxyARPEnable) + { + /* Check if IPv6 Proxy ARP Candidate from DS */ + if (IsIPv6ProxyARPCandidate(pAd, pSrcBuf - 2)) + { + BOOLEAN FoundProxyARPEntry; + FoundProxyARPEntry = IPv6ProxyARP(pAd, pMbss, pSrcBuf - 2, TRUE); + if (!FoundProxyARPEntry) + DBGPRINT(RT_DEBUG_TRACE, ("Can not find IPv6 proxy entry\n")); + + return FALSE; + } + } +#endif +#ifdef CONFIG_HOTSPOT + if (pMbss->HotSpotCtrl.HotSpotEnable) + { + if (!pMbss->HotSpotCtrl.DGAFDisable) + { + if (IsUnsolicitedNeighborAdver(pAd, pSrcBuf - 2)) + return FALSE; + } + } +#endif + /* + Check if DHCPv6 Packet, and Convert group-address DHCP + packets to individually-addressed 802.11 frames + */ +#endif + /* return AC_BE if packet is not IPv6 */ + if ((*pSrcBuf & 0xf0) != 0x60) + up = 0; + +#ifdef AIRPLAY_SUPPORT + /* point to the Next Header */ + if (*(pSrcBuf + 6) == IP_PROTO_UDP) + { + UINT16 srcPort = 0, dstPort = 0; + + pSrcBuf += 40; /* IPV6 Header */ + srcPort = OS_NTOHS(get_unaligned((PUINT16)(pSrcBuf))); + dstPort = OS_NTOHS(get_unaligned((PUINT16)(pSrcBuf+2))); + + if ((srcPort==5353 && dstPort==5353)) + { + DBGPRINT(RT_DEBUG_TRACE, ("this is mDns packet from upper layer ..... on V6\n")); + RTMP_SET_PACKET_EAPOL(pPacket, 1); + RTMP_SET_PACKET_TXTYPE(pPacket, TX_LEGACY_FRAME); + } + } +#endif /* AIRPLAY_SUPPORT */ + } + break; + case ETH_TYPE_EAPOL: + RTMP_SET_PACKET_EAPOL(pPacket, 1); + RTMP_SET_PACKET_TXTYPE(pPacket, TX_LEGACY_FRAME); + break; +#ifdef WAPI_SUPPORT + case ETH_TYPE_WAI: + RTMP_SET_PACKET_WAI(pPacket, 1); + RTMP_SET_PACKET_TXTYPE(pPacket, TX_LEGACY_FRAME); + break; +#endif /* WAPI_SUPPORT */ + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + case 0x890d: + { + RTMP_SET_PACKET_TDLS_MMPDU(pPacket, 1); + RTMP_SET_PACKET_TXTYPE(pPacket, TX_LEGACY_FRAME); + up = 5; + } + 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[WMM_UP2AC_MAP[up]]) + up = 0; + + + /* + Set WMM when + 1. wdev->bWmmCapable == TRUE + 2. Receiver's capability + a). bc/mc packets + ->Need to get UP for IGMP use + b). unicast packets + -> CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE) + 3. has VLAN tag or DSCP fields in IPv4/IPv6 hdr + */ +#ifdef NEW_IXIA_METHOD + if (up == 0 || up == 3)/*BE force VO*/ + up = 7; +#endif + if ((wdev->bWmmCapable == TRUE) && (up <= 7)) + { + *pUserPriority = up; + *pQueIdx = WMM_UP2AC_MAP[up]; + } + + return TRUE; +} + +VOID RTMP_RxPacketClassify( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk, + IN MAC_TABLE_ENTRY *pEntry) +{ + PUCHAR pData = NdisEqualMemory(SNAP_802_1H, pRxBlk->pData, 6) ? (pRxBlk->pData + 6) : pRxBlk->pData; + UINT16 protoType = OS_NTOHS(*((UINT16 *)(pData))); + + RTMP_SET_PACKET_ETHTYPE(pRxBlk->pRxPacket, 0); + + if (protoType == ETH_P_ARP) + { + UINT16 ArpOp; + + pData = pData + 8; + ArpOp = OS_NTOHS(*((UINT16 *)(pData))); + + DBGPRINT(RT_DEBUG_WARN, ("rx path ARP #(aid=%d,wcid=%d,arp op = %d, ampdu = %d)\n", + pEntry->Aid, pRxBlk->wcid, ArpOp, RX_BLK_TEST_FLAG(pRxBlk, fRX_AMPDU))); + + + RTMP_SET_PACKET_ETHTYPE(pRxBlk->pRxPacket, 0x1); + } + else if (protoType == ETH_P_IP) + { + UINT8 protocol = *(pData + 11); + + if (protocol == 0x1) + { + RTMP_SET_PACKET_ETHTYPE(pRxBlk->pRxPacket, 0x2); + } + } +} + +BOOLEAN CheckICMPPacket(RTMP_ADAPTER *pAd, UCHAR *pSrcBuf, UINT8 Direction) +{ + UINT16 TypeLen; + UCHAR Byte0, Byte1; + UINT32 sequence=0; + + if (Direction == 0) /* TX */ + { + TypeLen = (pSrcBuf[12] << 8) | pSrcBuf[13]; + pSrcBuf += LENGTH_802_3; + + if (TypeLen <= 1500) + { + if (pSrcBuf[0] == 0xAA && pSrcBuf[1] == 0xAA && pSrcBuf[2] == 0x03) + { + Sniff2BytesFromNdisBuffer((PNDIS_BUFFER)pSrcBuf, 6, &Byte0, &Byte1); + TypeLen = (USHORT)((Byte0 << 8) + Byte1); + pSrcBuf += LENGTH_802_1_H; /* Skip this LLC/SNAP header*/ + } else { + return FALSE; + } + } + + if (TypeLen == ETH_TYPE_IPv4) + { + pSrcBuf += 9; + + if (*pSrcBuf == 0x01) + { + pSrcBuf += 11; + + if (*pSrcBuf == 0x00) + { + pSrcBuf++; + if (*pSrcBuf == 0x00) + { + sequence = (pSrcBuf[5] << 8) | pSrcBuf[6]; + //DBGPRINT(RT_DEBUG_OFF, ("ping reply packet seq:%d\n",sequence)); + printk("\033[1;32m ping reply packet seq:%d \033[0m\n",sequence); + return TRUE; + } + } + else if (*pSrcBuf == 0x08) + { + pSrcBuf++; + if (*pSrcBuf == 0x00) + { + sequence = (pSrcBuf[5] << 8) | pSrcBuf[6]; + //DBGPRINT(RT_DEBUG_OFF, ("ping req packet seq:%d\n",sequence)); + printk("\033[1;32m ping req packet seq:%d \033[0m\n",sequence); + return TRUE; + } + } + } + } + } + else if (Direction == 1) /* RX */ + { + pSrcBuf = NdisEqualMemory(SNAP_802_1H, pSrcBuf, 6) ? (pSrcBuf + 6) : pSrcBuf; + + TypeLen = (*pSrcBuf << 8) + (*(pSrcBuf + 1)); + + if (TypeLen == ETH_TYPE_IPv4) + { + pSrcBuf += 11; + + if (*pSrcBuf == 0x01) + { + pSrcBuf += 11; + + if (*pSrcBuf == 0x00) + { + pSrcBuf++; + if (*pSrcBuf == 0x00) + { + sequence = (pSrcBuf[5] << 8) | pSrcBuf[6]; + //DBGPRINT(RT_DEBUG_OFF, ("ping reply packet seq:%d\n",sequence)); + printk("\033[1;32m ping reply packet seq:%d \033[0m\n",sequence); + return TRUE; + } + } + else if (*pSrcBuf == 0x08) + { + pSrcBuf++; + if (*pSrcBuf == 0x00) + { + sequence = (pSrcBuf[5] << 8) | pSrcBuf[6]; + //DBGPRINT(RT_DEBUG_OFF, ("ping req packet seq:%d\n",sequence)); + printk("\033[1;32m ping req packet seq:%d \033[0m\n",sequence); + return TRUE; + } + } + + + } + } + } + + return FALSE; +} + + +#ifdef SOFT_ENCRYPT +BOOLEAN RTMPExpandPacketForSwEncrypt( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk) +{ + PACKET_INFO PacketInfo; + UINT32 ex_head = 0, ex_tail = 0; + UCHAR NumberOfFrag = RTMP_GET_PACKET_FRAGMENTS(pTxBlk->pPacket); + +#ifdef WAPI_SUPPORT + if (pTxBlk->CipherAlg == CIPHER_SMS4) + ex_tail = LEN_WPI_MIC; + else +#endif /* WAPI_SUPPORT */ + if (pTxBlk->CipherAlg == CIPHER_AES) + ex_tail = LEN_CCMP_MIC; + + ex_tail = (NumberOfFrag * ex_tail); + + pTxBlk->pPacket = ExpandPacket(pAd, pTxBlk->pPacket, ex_head, ex_tail); + if (pTxBlk->pPacket == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: out of resource.\n", __FUNCTION__)); + return FALSE; + } + RTMP_QueryPacketInfo(pTxBlk->pPacket, &PacketInfo, &pTxBlk->pSrcBufHeader, &pTxBlk->SrcBufLen); + + return TRUE; +} + + +VOID RTMPUpdateSwCacheCipherInfo( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN UCHAR *pHdr) +{ + HEADER_802_11 *pHeader_802_11; + MAC_TABLE_ENTRY *pMacEntry; + + pHeader_802_11 = (HEADER_802_11 *) pHdr; + pMacEntry = pTxBlk->pMacEntry; + + if (pMacEntry && pHeader_802_11->FC.Wep && + CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT)) + { + PCIPHER_KEY pKey = &pMacEntry->PairwiseKey; + + TX_BLK_SET_FLAG(pTxBlk, fTX_bSwEncrypt); + + pTxBlk->CipherAlg = pKey->CipherAlg; + pTxBlk->pKey = pKey; +#ifdef WAPI_SUPPORT + pTxBlk->KeyIdx = pMacEntry->usk_id; + + /* TSC increment pre encryption transmittion */ + if (pKey->CipherAlg == CIPHER_SMS4) + inc_iv_byte(pKey->TxTsc, LEN_WAPI_TSC, 2); + else +#endif /* WAPI_SUPPORT */ + if ((pKey->CipherAlg == CIPHER_WEP64) || (pKey->CipherAlg == CIPHER_WEP128)) + inc_iv_byte(pKey->TxTsc, LEN_WEP_TSC, 1); + else if ((pKey->CipherAlg == CIPHER_TKIP) || (pKey->CipherAlg == CIPHER_AES)) + inc_iv_byte(pKey->TxTsc, LEN_WPA_TSC, 1); + + } + +} + + +INT tx_sw_encrypt(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk, UCHAR *pHeaderBufPtr, HEADER_802_11 *wifi_hdr) +{ + 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; + // TODO: shiang-MT7603, for header Len, shall we take care that?? + pTxBlk->MpduHeaderLen += iv_offset; + + /* Encrypt the MPDU data by software */ + RTMPSoftEncryptionAction(pAd, + pTxBlk->CipherAlg, + (UCHAR *)wifi_hdr, + pTxBlk->pSrcBufData, + pTxBlk->SrcBufLen, + pTxBlk->KeyIdx, + pTxBlk->pKey, &ext_offset); + pTxBlk->SrcBufLen += ext_offset; + pTxBlk->TotalFrameLen += ext_offset; + + return TRUE; +} +#endif /* SOFT_ENCRYPT */ + +#ifdef IP_ASSEMBLY + +/*for cache usage to improve throughput*/ +static IP_ASSEMBLE_DATA *pCurIpAsmData[NUM_OF_TX_RING]; + + static INT rtmp_IpAssembleDataCreate(RTMP_ADAPTER *pAd,UCHAR queId,IP_ASSEMBLE_DATA **ppIpAsmbData,UINT id,UINT fragSize) +{ + ULONG now = 0; + IP_ASSEMBLE_DATA *pIpAsmbData = NULL; + DL_LIST *pAssHead = &pAd->assebQueue[queId]; + + os_alloc_mem(NULL,(UCHAR**)&pIpAsmbData,sizeof(IP_ASSEMBLE_DATA)); + + *ppIpAsmbData = pIpAsmbData; + + if(pIpAsmbData==NULL) + { + return NDIS_STATUS_FAILURE; + } + + InitializeQueueHeader(&pIpAsmbData->queue); + NdisGetSystemUpTime(&now); + pIpAsmbData->identify = id; + pIpAsmbData->fragSize = fragSize; + pIpAsmbData->createTime = now; + + DlListAdd(pAssHead,&pIpAsmbData->list); + + return NDIS_STATUS_SUCCESS; +} + + +static VOID rtmp_IpAssembleDataDestory(RTMP_ADAPTER *pAd,IP_ASSEMBLE_DATA *pIpAsmbData) +{ + PQUEUE_ENTRY pPktEntry; + PNDIS_PACKET pPkt; + + /*free queue packet*/ + while (1) + { + pPktEntry = RemoveHeadQueue(&pIpAsmbData->queue); + if (pPktEntry == NULL) + { + break; + } + pPkt = QUEUE_ENTRY_TO_PACKET(pPktEntry); + RELEASE_NDIS_PACKET(pAd, pPkt, NDIS_STATUS_FAILURE); + } + /*remove from list*/ + DlListDel(&pIpAsmbData->list); + /*free data*/ + os_free_mem(NULL,pIpAsmbData); +} + + +static IP_ASSEMBLE_DATA* rtmp_IpAssembleDataSearch(RTMP_ADAPTER *pAd, UCHAR queIdx, UINT identify) +{ + DL_LIST *pAssHead = &pAd->assebQueue[queIdx]; + IP_ASSEMBLE_DATA *pAssData = NULL; + + DlListForEach(pAssData,pAssHead,struct ip_assemble_data,list) + { + if(pAssData->identify == identify) + { + return pAssData; + } + } + return NULL; +} + + +static VOID rtmp_IpAssembleDataUpdate(RTMP_ADAPTER *pAd) +{ + DL_LIST *pAssHead = NULL; + IP_ASSEMBLE_DATA *pAssData = NULL,*pNextAssData=NULL; + INT i=0; + ULONG now = 0; + QUEUE_HEADER *pAcQueue = NULL; + + NdisGetSystemUpTime(&now); + for(i=0;iassebQueue[i]; + DlListForEachSafe(pAssData,pNextAssData,pAssHead,struct ip_assemble_data,list) + { + pAcQueue = &pAssData->queue; + if ((pAcQueue->Number != 0) && (RTMP_TIME_AFTER(now, (pAssData->createTime) + (1000 * OS_HZ)))) + { + if(pCurIpAsmData[i] == pAssData) + { + pCurIpAsmData[i] = NULL; + } + rtmp_IpAssembleDataDestory(pAd,pAssData); + } + } + } +} + + +INT rtmp_IpAssembleHandle(RTMP_ADAPTER *pAd,STA_TR_ENTRY *pTrEntry , PNDIS_PACKET pPacket,UCHAR queIdx,PACKET_INFO packetInfo) +{ + IP_ASSEMBLE_DATA *pIpAsmData = NULL; + /*define local variable*/ + IP_V4_HDR *pIpv4Hdr, Ipv4Hdr; + IP_FLAGS_FRAG_OFFSET *pFlagsFragOffset, flagsFragOffset; + UINT fragSize = 0; + QUEUE_HEADER *pAcQueue = NULL; + UINT32 fragCount = 0; + + + /*check all timer of assemble for ageout */ + rtmp_IpAssembleDataUpdate(pAd); + + /*is not ipv4 packet*/ + if (!RTMP_GET_PACKET_IPV4(pPacket)) + { + /*continue to do normal path*/ + return NDIS_STATUS_INVALID_DATA; + } + + pFlagsFragOffset = (IP_FLAGS_FRAG_OFFSET *) (packetInfo.pFirstBuffer + LENGTH_802_3 + 6); + flagsFragOffset.word = ntohs(pFlagsFragOffset->word); + + + /*is not fragment packet*/ + if(flagsFragOffset.field.flags_more_frag == 0 && flagsFragOffset.field.frag_offset == 0) + { + /*continue to do normal path*/ + return NDIS_STATUS_INVALID_DATA; + } + + /*get ipv4 */ + pIpv4Hdr = (IP_V4_HDR *) (packetInfo.pFirstBuffer + LENGTH_802_3); + Ipv4Hdr.identifier = ntohs(pIpv4Hdr->identifier); + Ipv4Hdr.tot_len = ntohs(pIpv4Hdr->tot_len); + Ipv4Hdr.ihl = pIpv4Hdr->ihl; + fragSize = Ipv4Hdr.tot_len - (Ipv4Hdr.ihl * 4); + + /* check if 1st fragment */ + if ((flagsFragOffset.field.flags_more_frag == 1) && (flagsFragOffset.field.frag_offset == 0)) + { + /*check current queue is exist this id packet or not*/ + pIpAsmData = rtmp_IpAssembleDataSearch(pAd,queIdx,Ipv4Hdr.identifier); + /*if not exist, create it*/ + if(!pIpAsmData) + { + rtmp_IpAssembleDataCreate(pAd,queIdx,&pIpAsmData,Ipv4Hdr.identifier,fragSize); + if(!pIpAsmData) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + } + + /*store to cache */ + pCurIpAsmData[queIdx] = pIpAsmData; + /*insert packet*/ + pAcQueue = &pIpAsmData->queue; + InsertTailQueue(pAcQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); + + } else + { + /*search assemble data from identify and cache first*/ + if(pCurIpAsmData[queIdx] && (pCurIpAsmData[queIdx]->identify == Ipv4Hdr.identifier)) + { + pIpAsmData = pCurIpAsmData[queIdx]; + }else + { + pIpAsmData = rtmp_IpAssembleDataSearch(pAd,queIdx,Ipv4Hdr.identifier); + + /*not create assemble, should drop*/ + if(!pIpAsmData) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + /*update cache*/ + pCurIpAsmData[queIdx] = pIpAsmData; + } + pAcQueue = &pIpAsmData->queue; + InsertTailQueue(pAcQueue, PACKET_TO_QUEUE_ENTRY(pPacket)); + /* check if last fragment */ + if (pIpAsmData && (flagsFragOffset.field.flags_more_frag == 0) && (flagsFragOffset.field.frag_offset != 0)) + { + /*fragment packets gatter and check*/ + fragCount = ((flagsFragOffset.field.frag_offset * 8) / (pIpAsmData->fragSize)) + 1; + + if (pAcQueue->Number != fragCount) + { + rtmp_IpAssembleDataDestory(pAd,pIpAsmData); + pCurIpAsmData[queIdx] = NULL; + return NDIS_STATUS_FAILURE; + } + + /* move backup fragments to software queue */ + if (rtmp_enq_req(pAd, NULL, queIdx, pTrEntry,FALSE,pAcQueue) == FALSE) + { + rtmp_IpAssembleDataDestory(pAd,pIpAsmData); + pCurIpAsmData[queIdx] = NULL; + return NDIS_STATUS_FAILURE; + } + rtmp_IpAssembleDataDestory(pAd,pIpAsmData); + pCurIpAsmData[queIdx] = NULL; + } + + } + return NDIS_STATUS_SUCCESS; +} +#endif + + +INT rtmp_tx_burst_set(RTMP_ADAPTER *pAd) +{ + +#ifdef DOT11_N_SUPPORT +#ifdef MT_MAC + +#ifdef RTMP_SDIO_SUPPORT + if(pAd->MCUCtrl.Stage == FW_RUN_TIME){ +#endif + if (pAd->chipCap.hif_type == HIF_MT) + { + /* Not RDG, update the TxOP else keep the default RDG's TxOP */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE) == FALSE) + { + if ((pAd->MacTab.Size == 1) && (pAd->CommonCfg.bEnableTxBurst)) + { /* Only update TxOP for racing */ + AsicUpdateTxOP(pAd, WMM_PARAM_AC_1, 0x60); + } + else + { + AsicUpdateTxOP(pAd, WMM_PARAM_AC_1, 0x0); + } + } + } +#ifdef RTMP_SDIO_SUPPORT + } +#endif + +#endif /* MT_MAC */ +#endif /* DOT11_N_SUPPORT */ + + return NDIS_STATUS_SUCCESS; +} + + + +INT TxOPUpdatingAlgo(RTMP_ADAPTER *pAd) +{ + UCHAR UpdateTxOP = 0xFF; + ULONG TxTotalByteCnt = pAd->TxTotalByteCnt; + ULONG RxTotalByteCnt = pAd->RxTotalByteCnt; + BOOLEAN TxopEnabled = ((pAd->CommonCfg.ManualTxop == 0) && (pAd->CommonCfg.bEnableTxBurst) /*&& (pAd->chipCap.TxOPScenario == 1)*/); +#ifdef APCLI_SUPPORT + UINT apcliNum = 0, ifIndex = 0; +#endif /* APCLI_SUPPORT */ + //DBGPRINT(RT_DEBUG_TRACE, ("lala_1: [Tx Total Byte Count] = %lu\n", pAd->TxTotalByteCnt)); + //DBGPRINT(RT_DEBUG_TRACE, ("lala_1: [Rx Total Byte Count] = %lu\n", pAd->RxTotalByteCnt)); + + if ((TxTotalByteCnt == 0) || (RxTotalByteCnt == 0)) + { + /* Avoid to divide 0, when doing the traffic calculating */ + // DBGPRINT(RT_DEBUG_TRACE, ("Not expected one of them is 0, TxTotalByteCnt = %lu, RxTotalByteCnt = %lu\n", TxTotalByteCnt, RxTotalByteCnt)); + UpdateTxOP = 0x0; + + } + else if ((pAd->MacTab.Size == 1) && TxopEnabled) + { + if ((((TxTotalByteCnt + RxTotalByteCnt) << 3) >> 20) > pAd->CommonCfg.ManualTxopThreshold) + { /* TxopThreshold unit is Mbps */ + if (TxTotalByteCnt > RxTotalByteCnt) + { + if ((TxTotalByteCnt/RxTotalByteCnt) >= pAd->CommonCfg.ManualTxopUpBound) + { /* Boundary unit is Ratio */ + DBGPRINT(RT_DEBUG_TRACE, ("(Ratio: %lu >= %d) Should be enable TxOP to 0x60\n", + TxTotalByteCnt/RxTotalByteCnt, pAd->CommonCfg.ManualTxopUpBound)); + UpdateTxOP = 0x60; // Tx + } + else if ((TxTotalByteCnt/RxTotalByteCnt) <= pAd->CommonCfg.ManualTxopLowBound) + { + if (pAd->chipCap.BiTxOpOn) + { + UpdateTxOP = 0x60; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("(Ratio: %lu <= %d) Should be disable TxOP to 0x0\n", + TxTotalByteCnt/RxTotalByteCnt, pAd->CommonCfg.ManualTxopLowBound)); + UpdateTxOP = 0x0; + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("(Ratio: %d < %lu < %d) Keep the last TxOP setting\n", + pAd->CommonCfg.ManualTxopLowBound, TxTotalByteCnt/RxTotalByteCnt, pAd->CommonCfg.ManualTxopUpBound)); + } + } + else + { + if ((RxTotalByteCnt/TxTotalByteCnt) >= pAd->CommonCfg.ManualTxopUpBound) + { /* Boundary unit is Ratio */ + DBGPRINT(RT_DEBUG_TRACE, ("(Ratio: %lu >= %d) Should be enable TxOP to 0x60\n", + RxTotalByteCnt/TxTotalByteCnt, pAd->CommonCfg.ManualTxopUpBound)); + UpdateTxOP = 0x60; + } + else if ((RxTotalByteCnt/TxTotalByteCnt) <= pAd->CommonCfg.ManualTxopLowBound) + { + if (pAd->chipCap.BiTxOpOn) + { + UpdateTxOP = 0x60; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("(Ratio: %lu <= %d) Should be disable TxOP to 0x0\n", + RxTotalByteCnt/TxTotalByteCnt, pAd->CommonCfg.ManualTxopLowBound)); + UpdateTxOP = 0x0; + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("(Ratio: %d < %lu < %d) Keep the last TxOP setting\n", pAd->CommonCfg.ManualTxopLowBound, RxTotalByteCnt/TxTotalByteCnt, pAd->CommonCfg.ManualTxopUpBound)); + } + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Current TP=%lu < Threshold(%lu), turn-off TxOP\n", + (((TxTotalByteCnt + RxTotalByteCnt) << 3) >> 20), pAd->CommonCfg.ManualTxopThreshold)); + + UpdateTxOP = 0x0; + } + } + else if (pAd->MacTab.Size > 1) + { + UpdateTxOP = 0x0; + } + + +#ifdef APCLI_SUPPORT + if (TxopEnabled) + { + for (ifIndex = 0; ifIndex < MAX_APCLI_NUM; ifIndex++) + { + APCLI_STRUCT *apcli_entry; + PMAC_TABLE_ENTRY pEntry; + STA_TR_ENTRY *tr_entry; + UINT Wcid = 0; + + apcli_entry = &pAd->ApCfg.ApCliTab[ifIndex]; + Wcid = apcli_entry->MacTabWCID; + + if (!VALID_WCID(Wcid)) + continue; + + pEntry = &pAd->MacTab.Content[Wcid]; + tr_entry = &pAd->MacTab.tr_entry[Wcid]; + + if (IS_ENTRY_APCLI(pEntry) + && (pEntry->Sst == SST_ASSOC) + && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + apcliNum++; + } + } + + if (apcliNum == 1) + { + if (pAd->MacTab.Size == 1) + { + DBGPRINT(RT_DEBUG_TRACE,("Hit only one apcli tune TxOP to 80\n")); + UpdateTxOP = 0x80; + + } +#ifdef MAC_REPEATER_SUPPORT + else if ((pAd->ApCfg.RepeaterCliSize == 1) && + ((pAd->ApCfg.RepeaterCliSize + apcliNum) == pAd->MacTab.Size)) + { + DBGPRINT(RT_DEBUG_TRACE,("Hit only one rept tune TxOP to 80\n")); + UpdateTxOP = 0x80; + } +#endif /* MAC_REPEATER_SUPPORT */ + } + +#ifdef TRAFFIC_BASED_TXOP + DBGPRINT(RT_DEBUG_INFO, ("INFO: %d the traffic rule with cnt ApClient[%d],STA[%d]\n", + UpdateTxOP, pAd->ApClientTxopAbledCnt, pAd->StaTxopAbledCnt)); + /* Traffic Base Txop Rule */ + if (((UpdateTxOP == 0) || (UpdateTxOP == 0xFF)) && + ((pAd->StaTxopAbledCnt == 1) || (pAd->ApClientTxopAbledCnt == 1))) + { + DBGPRINT(RT_DEBUG_TRACE, ("Hit the traffic rule with cnt ApClient[%d],STA[%d]\n", + pAd->ApClientTxopAbledCnt, pAd->StaTxopAbledCnt)); + UpdateTxOP = 0x60; + } + +#endif /* TRAFFIC_BASED_TXOP */ + } +#endif /* APCLI_SUPPORT */ + + + if ((pAd->MacTab.Size >= 30) +#ifdef APCLI_SUPPORT + && (apcliNum == 0) +#endif /* APCLI_SUPPORT */ + ) + { + ULONG txCount = 0; + ULONG per = 0; + + txCount = pAd->WlanCounters.TransmittedFragmentCount.u.LowPart; + per = txCount==0? 0: 1000*(pAd->WlanCounters.FailedCount.u.LowPart)/(pAd->WlanCounters.FailedCount.u.LowPart+txCount); + per = (per / 10); + + if (per < 2) + UpdateTxOP = 0x40; + } + + if (UpdateTxOP != 0xFF && + UpdateTxOP != pAd->CurrEdcaParam[WMM_PARAM_AC_1].u2Txop) + { + AsicUpdateTxOP(pAd, WMM_PARAM_AC_1, UpdateTxOP); + } + + pAd->TxTotalByteCnt = 0; + pAd->RxTotalByteCnt = 0; + + return TRUE; +} + +#ifdef DYNAMIC_WMM +INT DynamicWMMDetectAction(RTMP_ADAPTER *pAd) +{ + UCHAR UpdateTxOP = 0x0; + ULONG PrioTxTotalByteCnt = pAd->TxTotalByteCnt_Dyn[QID_AC_BK] + pAd->TxTotalByteCnt_Dyn[QID_AC_VI] + pAd->TxTotalByteCnt_Dyn[QID_AC_VO]; + //BOOLEAN TxopEnabled = ((pAd->CommonCfg.ManualTxop == 0) && (pAd->CommonCfg.bEnableTxBurst)); + + if (pAd->MacTab.Size > 1) + UpdateTxOP = 0x0; + else if (pAd->CommonCfg.bEnableTxBurst) + UpdateTxOP = 0x60; + else + UpdateTxOP = 0x0; + + //DBGPRINT(RT_DEBUG_WARN, ("%s: PrioTxTotalByteCnt %lu, TxOP 0x%2x\n",__FUNCTION__, PrioTxTotalByteCnt, UpdateTxOP)); + DBGPRINT(RT_DEBUG_WARN, ("%s: PrioTxTotalByteCnt %lu, bk=%lu vi=%lu vo=%lu\n",__FUNCTION__, PrioTxTotalByteCnt, pAd->TxTotalByteCnt_Dyn[QID_AC_BK], pAd->TxTotalByteCnt_Dyn[QID_AC_VI], pAd->TxTotalByteCnt_Dyn[QID_AC_VO])); + + if (PrioTxTotalByteCnt == 0 && pAd->CommonCfg.DynamicWmm == 1) + { + if (pAd->CurrEdcaParam[WMM_PARAM_AC_1].u2WinMax != 0xf) // avoid re-writing + { + DBGPRINT(RT_DEBUG_OFF, ("%s: aggression mode\n",__FUNCTION__)); + AsicSetWmmParam(pAd, WMM_PARAM_AC_1, WMM_PARAM_TXOP, UpdateTxOP); + AsicSetWmmParam(pAd, WMM_PARAM_AC_1, WMM_PARAM_AIFSN, 0x2); + AsicSetWmmParam(pAd, WMM_PARAM_AC_1, WMM_PARAM_CWMIN, 0x3); + AsicSetWmmParam(pAd, WMM_PARAM_AC_1, WMM_PARAM_CWMAX, 0xf); + } + } + else // change to default WMM BE paramaters + { + if (pAd->CurrEdcaParam[WMM_PARAM_AC_1].u2WinMax != 0x3f) // avoid re-writing + { + DBGPRINT(RT_DEBUG_OFF, ("%s: default wmm\n",__FUNCTION__)); + AsicSetWmmParam(pAd, WMM_PARAM_AC_1, WMM_PARAM_TXOP, UpdateTxOP); + AsicSetWmmParam(pAd, WMM_PARAM_AC_1, WMM_PARAM_AIFSN, 0x3); + AsicSetWmmParam(pAd, WMM_PARAM_AC_1, WMM_PARAM_CWMIN, 0xf); + AsicSetWmmParam(pAd, WMM_PARAM_AC_1, WMM_PARAM_CWMAX, 0x3f); + } + } + + pAd->TxTotalByteCnt = 0; + pAd->RxTotalByteCnt = 0; + pAd->TxTotalByteCnt_Dyn[QID_AC_BK] = 0; + pAd->TxTotalByteCnt_Dyn[QID_AC_BE] = 0; + pAd->TxTotalByteCnt_Dyn[QID_AC_VI] = 0; + pAd->TxTotalByteCnt_Dyn[QID_AC_VO] = 0; + + //pAd->TxTotalByteCnt_Dyn[QID_AC_VI] = pAd->CommonCfg.ManualTxopThreshold; + + return TRUE; +} +#endif /* DYNAMIC_WMM */ +#ifdef NEW_IXIA_METHOD +void wifi_txrx_parmtrs_dump(RTMP_ADAPTER *pAd) +{ + UINT8 idx = 0; + + if (tx_pkt_from_os >= 500) { + DBGPRINT(RT_DEBUG_OFF, ("************ TX ************\n")); + DBGPRINT(RT_DEBUG_OFF, ("tx_pkt_len : %d .\n", tx_pkt_len)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pkt_from_os: %d .\n", tx_pkt_from_os)); + DBGPRINT(RT_DEBUG_OFF, ("tx_pkt_to_hw : %d .\n", tx_pkt_to_hw)); + for (idx = 1; idx < MAX_TDROP_RESON; idx++) { + if (pAd->tr_ststic.tx[idx] == 0) + continue; + DBGPRINT(RT_DEBUG_OFF, ("TX Drop Reason:%s,Drop Cnt:%d\n", + tdrop_reason[idx], pAd->tr_ststic.tx[idx])); + if (idx == DROP_TXQ_ENQ_FAIL) { + DBGPRINT(RT_DEBUG_OFF, ("perQ-drop = %d,fifoQ-drop = %d\n", + pAd->tr_ststic.txfl[0], pAd->tr_ststic.txfl[1])); + } + } + tx_pkt_len = 0; + tx_pkt_from_os = 0; + tx_pkt_to_hw = 0; + } + if (rx_pkt_from_hw >= 500) { + DBGPRINT(RT_DEBUG_OFF, ("************ RX ************\n")); + DBGPRINT(RT_DEBUG_OFF, ("rx_pkt_len : %d .\n", rx_pkt_len)); + DBGPRINT(RT_DEBUG_OFF, ("rx_pkt_from_hw: %d .\n", rx_pkt_from_hw)); + DBGPRINT(RT_DEBUG_OFF, ("rx_pkt_to_os : %d .\n", rx_pkt_to_os)); + for (idx = 1; idx < MAX_RDROP_RESON; idx++) { + if (pAd->tr_ststic.rx[idx] == 0) + continue; + DBGPRINT(RT_DEBUG_OFF, ("RX Drop Reason:%s,Drop Cnt:%d\n", + rdrop_reason[idx], pAd->tr_ststic.rx[idx])); + } + rx_pkt_len = 0; + rx_pkt_from_hw = 0; + rx_pkt_to_os = 0; + } + NdisZeroMemory(&pAd->tr_ststic, sizeof(WTRC)); + /*DBGPRINT(RT_DEBUG_OFF, ("txpktdetect2s: %d, rxpktdetect2s: %d .\n", txpktdetect2s, rxpktdetect2s));*/ +} +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_data_pci.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_data_pci.c new file mode 100644 index 000000000..646beb40b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_data_pci.c @@ -0,0 +1,2765 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + cmm_data_pci.c + + Abstract: + + Note: + All functions in this file must be PCI-depended, or you should move + your functions to other files. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- +*/ + + +#include "rt_config.h" + + +VOID dump_txd(RTMP_ADAPTER *pAd, TXD_STRUC *pTxD) +{ + DBGPRINT(RT_DEBUG_OFF, ("TxD:\n")); + + DBGPRINT(RT_DEBUG_OFF, ("\tSDPtr0=0x%x\n", pTxD->SDPtr0)); + DBGPRINT(RT_DEBUG_OFF, ("\tSDLen0=0x%x\n", pTxD->SDLen0)); + DBGPRINT(RT_DEBUG_OFF, ("\tLastSec0=0x%x\n", pTxD->LastSec0)); + DBGPRINT(RT_DEBUG_OFF, ("\tSDPtr1=0x%x\n", pTxD->SDPtr1)); + DBGPRINT(RT_DEBUG_OFF, ("\tSDLen1=0x%x\n", pTxD->SDLen1)); + DBGPRINT(RT_DEBUG_OFF, ("\tLastSec1=0x%x\n", pTxD->LastSec1)); + DBGPRINT(RT_DEBUG_OFF, ("\tDMADONE=0x%x\n", pTxD->DMADONE)); + DBGPRINT(RT_DEBUG_OFF, ("\tBurst=0x%x\n", pTxD->Burst)); +} + + +VOID dump_rxd(RTMP_ADAPTER *pAd, RXD_STRUC *pRxD) +{ + DBGPRINT(RT_DEBUG_OFF, ("RxD:\n")); + + DBGPRINT(RT_DEBUG_OFF, ("\tSDPtr0/SDLen0/LastSec0=0x%x/0x%x/0x%x\n", + pRxD->SDP0, pRxD->SDL0, pRxD->LS0)); + DBGPRINT(RT_DEBUG_OFF, ("\tSDPtr1/SDLen1/LastSec1=0x%x/0x%x/0x%x\n", + pRxD->SDP1, pRxD->SDL1, pRxD->LS1)); + DBGPRINT(RT_DEBUG_OFF, ("\tDDONE=0x%x\n", pRxD->DDONE)); +} + + +VOID dumpTxRing(RTMP_ADAPTER *pAd, INT ring_idx) +{ + //RTMP_DMABUF *pDescRing; + RTMP_TX_RING *pTxRing; + TXD_STRUC *pTxD; + int index; + + ASSERT(ring_idx < NUM_OF_TX_RING); + //pDescRing = (RTMP_DMABUF *)pAd->TxDescRing[ring_idx].AllocVa; + + pTxRing = &pAd->TxRing[ring_idx]; + for (index = 0; index < TX_RING_SIZE; index++) + { + pTxD = (TXD_STRUC *)pTxRing->Cell[index].AllocVa; + hex_dump("Dump TxDesc", (UCHAR *)pTxD, sizeof(TXD_STRUC)); + dump_txd(pAd, pTxD); +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (pAd->chipCap.hif_type == HIF_RTMP || pAd->chipCap.hif_type == HIF_RLT) { + TXINFO_STRUC *pTxInfo; + + pTxInfo = (TXINFO_STRUC *)(pTxRing->Cell[index].AllocVa + sizeof(TXD_STRUC)); + hex_dump("Dump TxInfo", (UCHAR *)pTxInfo, sizeof(TXINFO_STRUC)); + dump_txinfo(pAd, pTxInfo); + } +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + } +} + + +BOOLEAN MonitorTxRing(RTMP_ADAPTER *pAd) +{ + UINT32 Value; + + if (pAd->TxDMACheckTimes < 10) + { + /* Check if TX DMA busy */ + RTMP_IO_READ32(pAd, MT_WPDMA_GLO_CFG, &Value); + + if ((Value & TX_DMA_BUSY) == TX_DMA_BUSY) + { + /* Check TX FIFO if have space */ + RTMP_IO_WRITE32(pAd, 0x4244, 0x98000000); + RTMP_IO_READ32(pAd, 0x4244, &Value); + if ((Value & (1 << 8)) == 0) + { + pAd->TxDMACheckTimes = 0; + return FALSE; + } + else + { + pAd->TxDMACheckTimes++; + return FALSE; + } + } + else + { + pAd->TxDMACheckTimes = 0; + return FALSE; + } + } + else + { + pAd->TxDMACheckTimes = 0; + return TRUE; + } +} + + +BOOLEAN MonitorRxRing(RTMP_ADAPTER *pAd) +{ + UINT32 Value; + + if (pAd->RxDMACheckTimes < 10) + { + /* Check if RX DMA busy */ + RTMP_IO_READ32(pAd, MT_WPDMA_GLO_CFG, &Value); + + if ((Value & RX_DMA_BUSY) == RX_DMA_BUSY) + { + /* Check RX FIFO if have data */ + RTMP_IO_WRITE32(pAd, 0x4244, 0x28000000); + RTMP_IO_READ32(pAd, 0x4244, &Value); + if ((Value & (1 << 8)) == 0) + { + pAd->RxDMACheckTimes = 0; + return FALSE; + } + else + { + pAd->RxDMACheckTimes++; + return FALSE; + } + } + else + { + pAd->RxDMACheckTimes = 0; + return FALSE; + } + } + else + { + pAd->RxDMACheckTimes = 0; + return TRUE; + } +} + + +BOOLEAN MonitorRxPse(RTMP_ADAPTER *pAd) +{ + UINT32 RemapBase, RemapOffset; + UINT32 Value; + UINT32 RestoreValue; + + if (pAd->RxPseCheckTimes < 10) + { + /* Check RX FIFO if not ready */ + RTMP_IO_WRITE32(pAd, 0x4244, 0x28000000); + RTMP_IO_READ32(pAd, 0x4244, &Value); + if ((Value & (1 << 8)) != 0) + { + pAd->RxPseCheckTimes = 0; + return FALSE; + } + else + { + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + RemapBase = GET_REMAP_2_BASE(0x800c006c) << 19; + RemapOffset = GET_REMAP_2_OFFSET(0x800c006c); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, 3); + + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + + if(((Value & (0x8001 << 16)) == (0x8001 << 16)) || + ((Value & (0xe001 << 16)) == (0xe001 << 16))) + { + pAd->RxPseCheckTimes++; + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); + return FALSE; + } + else + { + pAd->RxPseCheckTimes = 0; + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); + return FALSE; + } + } + } + else + { + pAd->RxPseCheckTimes = 0; + return TRUE; + } +} + + +VOID dumpRxRing(RTMP_ADAPTER *pAd, INT ring_idx) +{ + //RTMP_DMABUF *pDescRing; + RTMP_RX_RING *pRxRing; + RXD_STRUC *pRxD; + int index; + + + //pDescRing = (RTMP_DMABUF *)pAd->RxDescRing[0].AllocVa; + + pRxRing = &pAd->RxRing[0]; + for (index = 0; index < RX_RING_SIZE; index++) + { + pRxD = (RXD_STRUC *)pRxRing->Cell[index].AllocVa; + hex_dump("Dump RxDesc", (UCHAR *)pRxD, sizeof(RXD_STRUC)); + dump_rxd(pAd, pRxD); + } +} + + +#if defined(RTMP_MAC) || defined(RLT_MAC) +static VOID ral_write_txinfo( + IN RTMP_ADAPTER *pAd, + IN TXINFO_STRUC *pTxInfo, + IN BOOLEAN bWiv, + IN UCHAR QueueSel) +{ +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + struct _TXINFO_NMAC_PKT *nmac_info = (struct _TXINFO_NMAC_PKT *)pTxInfo; + +#ifdef HDR_TRANS_SUPPORT + if (pTxBlk && pTxBlk->NeedTrans) + nmac_info->pkt_80211 = 0; /* 802.3 MAC header */ + else +#endif /* HDR_TRANS_SUPPORT */ + nmac_info->pkt_80211 = 1; + nmac_info->info_type = 0; + nmac_info->d_port = 0; + nmac_info->cso = 0; + nmac_info->tso = 0; + nmac_info->wiv = (bWiv) ? 1: 0; + nmac_info->QSEL = (pAd->bGenOneHCCA == TRUE) ? FIFO_HCCA : QueueSel; + + } +#endif /* RLT_MAC */ + + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + struct _TXINFO_OMAC *omac_info = (struct _TXINFO_OMAC *)pTxInfo; + + omac_info->WIV = (bWiv) ? 1: 0; + omac_info->QSEL = (pAd->bGenOneHCCA == TRUE) ? FIFO_HCCA : QueueSel; + + } +#endif /* RTMP_MAC */ +} + + +#ifdef RLT_MAC +static VOID rlt_update_txinfo( + IN RTMP_ADAPTER *pAd, + IN TXINFO_STRUC *pTxInfo, + IN TX_BLK *pTxBlk) +{ +} +#endif /* RLT_MAC */ + + +VOID ral_write_txd( + IN RTMP_ADAPTER *pAd, + IN TXD_STRUC *pTxD, + IN TX_BLK *txblk, + IN BOOLEAN bWIV, + IN UCHAR QueueSEL) +{ + TXINFO_STRUC *pTxInfo = (TXINFO_STRUC *)(pTxD + 1); + + + /* Always use Long preamble before verifiation short preamble functionality works well.*/ + /* Todo: remove the following line if short preamble functionality works*/ + + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + + ral_write_txinfo(pAd, pTxInfo, bWIV, QueueSEL); + + pTxD->DMADONE = 0; +} + +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + +#ifdef MT_MAC +VOID mt_write_txd(RTMP_ADAPTER *pAd, TXD_STRUC *pTxD) +{ + + pTxD->DMADONE = 0; +} +#endif /* MT_MAC */ + + + + + +/* IRQL = DISPATCH_LEVEL */ +VOID ComposeNullFrame(RTMP_ADAPTER *pAd) +{ + NdisZeroMemory(&pAd->NullFrame, sizeof (HEADER_802_11)); + pAd->NullFrame.FC.Type = FC_TYPE_DATA; + pAd->NullFrame.FC.SubType = SUBTYPE_DATA_NULL; + pAd->NullFrame.FC.ToDs = 1; + COPY_MAC_ADDR(pAd->NullFrame.Addr1, pAd->CommonCfg.Bssid); + COPY_MAC_ADDR(pAd->NullFrame.Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pAd->NullFrame.Addr3, pAd->CommonCfg.Bssid); +} + + +USHORT write_first_buf(RTMP_ADAPTER *pAd, TX_BLK *txblk, UCHAR *dma_buf) +{ + UINT tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len; // TXWISize + TSO_SIZE + USHORT first_buf_len; + + first_buf_len = tx_hw_hdr_len + txblk->MpduHeaderLen + txblk->HdrPadLen - txblk->hw_rsv_len; + + + NdisMoveMemory(dma_buf, + (UCHAR *)(txblk->HeaderBuf + txblk->hw_rsv_len), + first_buf_len); + + return first_buf_len; +} + + +USHORT RtmpPCI_WriteSingleTxResource( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN BOOLEAN bIsLast, + OUT USHORT *FreeNumber) +{ + UCHAR *pDMAHeaderBufVA; + USHORT TxIdx, RetTxIdx; + TXD_STRUC *pTxD; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR tx_hw_info[TXD_SIZE]; + UINT8 *temp; +#if defined(RTMP_MAC) || defined(RLT_MAC) + UINT tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len; // TXWISize + TSO_SIZE +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ +#endif + UINT32 BufBasePaLow; + RTMP_TX_RING *pTxRing; +#ifdef MT_MAC +#ifdef USE_BMC + if (pTxBlk->QueIdx == QID_BMC) + { + pTxRing = &pAd->TxBmcRing; + TxIdx = pAd->TxBmcRing.TxCpuIdx; + } + else +#endif /* USE_BMC */ +#endif + { + /* get Tx Ring Resource*/ + pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; + TxIdx = pAd->TxRing[pTxBlk->QueIdx].TxCpuIdx; + } + + pDMAHeaderBufVA = (UCHAR *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + BufBasePaLow = RTMP_GetPhysicalAddressLow(pTxRing->Cell[TxIdx].DmaBuf.AllocPa); + + pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + pTxRing->Cell[TxIdx].PacketPa = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, RTMP_PCI_DMA_TODEVICE); + + /* build Tx Descriptor*/ +#ifndef RT_BIG_ENDIAN + pTxD = (TXD_STRUC *)pTxRing->Cell[TxIdx].AllocVa; +#else + pDestTxD = (TXD_STRUC *)pTxRing->Cell[TxIdx].AllocVa; + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; +#endif + + pTxD->SDPtr0 = BufBasePaLow; + pTxD->SDLen0 = write_first_buf(pAd, pTxBlk, pDMAHeaderBufVA); + pTxD->SDPtr1 = pTxRing->Cell[TxIdx].PacketPa; + pTxD->SDLen1 = pTxBlk->SrcBufLen; + pTxD->LastSec0 = !(pTxD->SDLen1); + pTxD->LastSec1 = (bIsLast && pTxD->SDLen1) ? 1 : 0; + pTxD->Burst = 0; + +#if defined(RTMP_MAC) || defined(RLT_MAC) + ral_write_txd(pAd, pTxD, pTxBlk, FALSE, FIFO_EDCA); +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ +#ifdef MT_MAC + mt_write_txd(pAd, pTxD); +#endif /* MT_MAC */ + +#ifdef RT_BIG_ENDIAN +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + UINT16 TmacLen = (pAd->chipCap.tx_hw_hdr_len - pTxBlk->hw_rsv_len); + MTMacInfoEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA), TYPE_TMACINFO, TmacLen); + RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TmacLen), DIR_WRITE, FALSE); + } + +#endif +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (pAd->chipCap.hif_type == HIF_RTMP || pAd->chipCap.hif_type == HIF_RLT) + { + RTMPWIEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA), TYPE_TXWI); + RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + tx_hw_hdr_len), DIR_WRITE, FALSE); + } +#endif + 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; + +#ifdef CONFIG_WIFI_TEST + pTxRing->Cell[TxIdx].DataOut = 1; + pTxRing->Cell[TxIdx].TimePeriod = 0; +#endif + + *FreeNumber -= 1; + + return RetTxIdx; +} + + +USHORT RtmpPCI_WriteMultiTxResource( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN UCHAR frameNum, + OUT USHORT *FreeNumber) +{ + BOOLEAN bIsLast; + UCHAR *pDMAHeaderBufVA; + USHORT TxIdx, RetTxIdx; + TXD_STRUC *pTxD; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR tx_hw_info[TXD_SIZE]; + //TXD_STRUC TxD; +#endif + UINT32 BufBasePaLow; + RTMP_TX_RING *pTxRing; +#if !defined(MT7603) && !defined(MT7628) + USHORT hwHdrLen; +#endif /* !defined(MT7603) && !defined(MT7628) */ + UINT32 firstDMALen = 0; + //UINT8 TXWISize = pAd->chipCap.TXWISize; + UINT tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len; // TXWISize + TSO_SIZE + + ASSERT((pTxBlk->TxFrameType == TX_AMSDU_FRAME || pTxBlk->TxFrameType == TX_RALINK_FRAME)); + 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 defined(MT7603) || defined(MT7628) + if (frameNum == 0) + { + /* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */ + firstDMALen = tx_hw_hdr_len - pTxBlk->hw_rsv_len + pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + + NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf + pTxBlk->hw_rsv_len, firstDMALen); + } + else + { + firstDMALen = pTxBlk->MpduHeaderLen; + NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf, firstDMALen); + } + +#else + + if (frameNum == 0) + { + /* copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer */ + if (pTxBlk->TxFrameType == TX_AMSDU_FRAME) + hwHdrLen = pTxBlk->MpduHeaderLen - AMSDU_SUBHEAD_LEN + pTxBlk->HdrPadLen + AMSDU_SUBHEAD_LEN; + else if (pTxBlk->TxFrameType == TX_RALINK_FRAME) + hwHdrLen = pTxBlk->MpduHeaderLen - ARALINK_HEADER_LEN + pTxBlk->HdrPadLen + ARALINK_HEADER_LEN; + + hwHdrLen = pTxBlk->MpduHeaderLen + pTxBlk->HdrPadLen; + + firstDMALen = pAd->chipCap.TXWISize + hwHdrLen; + } + else + { + firstDMALen = pTxBlk->MpduHeaderLen; + } + + NdisMoveMemory(pDMAHeaderBufVA, pTxBlk->HeaderBuf + TXINFO_SIZE, firstDMALen); +#endif /* defined(MT7603) || defined(MT7628) */ + + pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + pTxRing->Cell[TxIdx].PacketPa = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, RTMP_PCI_DMA_TODEVICE); + + /* build Tx Descriptor */ +#ifndef RT_BIG_ENDIAN + pTxD = (TXD_STRUC *) pTxRing->Cell[TxIdx].AllocVa; +#else + pDestTxD = (TXD_STRUC *) pTxRing->Cell[TxIdx].AllocVa; + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; +#endif + + pTxD->SDPtr0 = BufBasePaLow; + pTxD->SDLen0 = firstDMALen; /* include padding*/ + pTxD->SDPtr1 = pTxRing->Cell[TxIdx].PacketPa; + pTxD->SDLen1 = pTxBlk->SrcBufLen; + pTxD->LastSec0 = !(pTxD->SDLen1); + pTxD->LastSec1 = (bIsLast && pTxD->SDLen1) ? 1 : 0; + pTxD->Burst = 0; + +#if defined(RTMP_MAC) || defined(RLT_MAC) + ral_write_txd(pAd, pTxD, pTxBlk, FALSE, FIFO_EDCA); +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ +#ifdef MT_MAC + mt_write_txd(pAd, pTxD); +#endif /* MT_MAC */ + +#ifdef RT_BIG_ENDIAN +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + UINT16 TmacLen = (pAd->chipCap.tx_hw_hdr_len - pTxBlk->hw_rsv_len); + if (frameNum == 0) + RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TmacLen), DIR_WRITE, FALSE); + if (frameNum != 0) + MTMacInfoEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA), TYPE_TMACINFO, TmacLen); + } +#endif +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (pAd->chipCap.hif_type == HIF_RTMP || pAd->chipCap.hif_type == HIF_RLT) + { + if (frameNum == 0) + RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + pAd->chipCap.TXWISize), DIR_WRITE, FALSE); + if (frameNum != 0) + RTMPWIEndianChange(pAd, (PUCHAR)pDMAHeaderBufVA, TYPE_TXWI); + } +#endif + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + + RetTxIdx = TxIdx; + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxRing->Cell[TxIdx].DmaBuf.AllocPa, pTxD->SDLen0); + RTMP_DCACHE_FLUSH(pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); + RTMP_DCACHE_FLUSH(pTxRing->Cell[TxIdx].AllocPa, RXD_SIZE); + + /* Update Tx index*/ + INC_RING_INDEX(TxIdx, TX_RING_SIZE); + pTxRing->TxCpuIdx = TxIdx; + + *FreeNumber -= 1; + + return RetTxIdx; +} + + +VOID RtmpPCI_FinalWriteTxResource( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN USHORT totalMPDUSize, + IN USHORT FirstTxIdx) +{ + RTMP_TX_RING *pTxRing; + UCHAR *tmac_info; + + /* get Tx Ring Resource*/ + pTxRing = &pAd->TxRing[pTxBlk->QueIdx]; + tmac_info = (UCHAR *)pTxRing->Cell[FirstTxIdx].DmaBuf.AllocVa; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + TXWI_STRUC *pTxWI = (TXWI_STRUC *)tmac_info; + + pTxWI->TXWI_N.MPDUtotalByteCnt = totalMPDUSize; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + TXWI_STRUC *pTxWI = (TXWI_STRUC *)tmac_info; + + pTxWI->TXWI_O.MPDUtotalByteCnt = totalMPDUSize; + } +#endif /* RTMP_MAC */ + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + TMAC_TXD_S *txd_s = (TMAC_TXD_S *)tmac_info; + + txd_s->txd_0.tx_byte_cnt = totalMPDUSize; + } +#endif /* MT_MAC */ + +#ifdef RT_BIG_ENDIAN +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + UINT16 TmacLen = (pAd->chipCap.tx_hw_hdr_len - pTxBlk->hw_rsv_len); + MTMacInfoEndianChange(pAd, tmac_info, TYPE_TMACINFO, TmacLen); + } +#endif +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (pAd->chipCap.hif_type == HIF_RTMP || pAd->chipCap.hif_type == HIF_RLT) + { + RTMPWIEndianChange(pAd, tmac_info, TYPE_TXWI); + } +#endif +#endif /* RT_BIG_ENDIAN */ +} + + +USHORT RtmpPCI_WriteFragTxResource( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk, + IN UCHAR fragNum, + OUT USHORT *FreeNumber) +{ + UCHAR *pDMAHeaderBufVA; + USHORT TxIdx, RetTxIdx; + TXD_STRUC *pTxD; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR tx_hw_info[TXD_SIZE]; + //TXD_STRUC TxD; +#endif + UINT32 BufBasePaLow; + RTMP_TX_RING *pTxRing; + //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); + + /* Build Tx Descriptor*/ +#ifndef RT_BIG_ENDIAN + pTxD = (TXD_STRUC *) pTxRing->Cell[TxIdx].AllocVa; +#else + pDestTxD = (TXD_STRUC *) pTxRing->Cell[TxIdx].AllocVa; + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; +#endif + + if (fragNum == pTxBlk->TotalFragNum) + { + pTxRing->Cell[TxIdx].pNdisPacket = pTxBlk->pPacket; + pTxRing->Cell[TxIdx].pNextNdisPacket = NULL; + } + + pTxD->SDPtr0 = BufBasePaLow; + /* Copy TXINFO + TXWI + WLAN Header + LLC into DMA Header Buffer, including padding */ + pTxD->SDLen0 = write_first_buf(pAd, pTxBlk, pDMAHeaderBufVA); + pTxD->SDPtr1 = PCI_MAP_SINGLE(pAd, pTxBlk, 0, 1, RTMP_PCI_DMA_TODEVICE); + pTxD->SDLen1 = pTxBlk->SrcBufLen; + pTxD->LastSec0 = !(pTxD->SDLen1); + pTxD->LastSec1 = (pTxD->SDLen1 ? 1 : 0); + pTxD->Burst = 0; + +#if defined(RTMP_MAC) || defined(RLT_MAC) + ral_write_txd(pAd, pTxD, pTxBlk, FALSE, FIFO_EDCA); +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ +#ifdef MT_MAC + mt_write_txd(pAd, pTxD); +#endif /* MT_MAC */ + +#ifdef RT_BIG_ENDIAN +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + UINT16 TmacLen = (pAd->chipCap.tx_hw_hdr_len - pTxBlk->hw_rsv_len); + MTMacInfoEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA), TYPE_TMACINFO, TmacLen); + RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + TmacLen), DIR_WRITE, FALSE); + } + +#endif +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (pAd->chipCap.hif_type == HIF_RTMP || pAd->chipCap.hif_type == HIF_RLT) + { + RTMPWIEndianChange(pAd, pDMAHeaderBufVA, TYPE_TXWI); + RTMPFrameEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA + pAd->chipCap.TXWISize), DIR_WRITE, FALSE); + } +#endif + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + + RetTxIdx = TxIdx; + pTxBlk->Priv += pTxBlk->SrcBufLen; + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxRing->Cell[TxIdx].DmaBuf.AllocPa, pTxD->SDLen0); + RTMP_DCACHE_FLUSH(pTxBlk->pSrcBufData, pTxBlk->SrcBufLen); + RTMP_DCACHE_FLUSH(pTxRing->Cell[TxIdx].AllocPa, RXD_SIZE); + + /* Update Tx index */ + INC_RING_INDEX(TxIdx, TX_RING_SIZE); + pTxRing->TxCpuIdx = TxIdx; + + *FreeNumber -= 1; + + return RetTxIdx; +} + + +/* + Must be run in Interrupt context + This function handle PCI specific TxDesc and cpu index update and kick the packet out. + */ +int RtmpPCIMgmtKickOut( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket, + IN UCHAR *pSrcBufVA, + IN UINT SrcBufLen) +{ + TXD_STRUC *pTxD; +#ifdef RT_BIG_ENDIAN + UCHAR tx_hw_info[TXD_SIZE]; + TXD_STRUC *pDestTxD; +#endif + UCHAR *frm_buf; + UINT32 SwIdx; + INT pkt_len; + RTMP_DMACB *dma_buf; + +#if defined(MT7603) || defined(MT7628) + if (IS_MT7603(pAd) || (IS_MT7628(pAd))) + { + frm_buf = pSrcBufVA; + pkt_len = SrcBufLen; + if (QueIdx == Q_IDX_BCN) { + SwIdx = pAd->BcnRing.TxCpuIdx; + dma_buf = &pAd->BcnRing.Cell[SwIdx]; + } else { + SwIdx = pAd->MgmtRing.TxCpuIdx; + dma_buf = &pAd->MgmtRing.Cell[SwIdx]; + } + } + else +#endif /* MT7603 */ + { + frm_buf = pSrcBufVA + TXINFO_SIZE; + pkt_len = SrcBufLen - TXINFO_SIZE; + SwIdx = pAd->MgmtRing.TxCpuIdx; + dma_buf = &pAd->MgmtRing.Cell[SwIdx]; + } + +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *)dma_buf->AllocVa; + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_STRUC *)dma_buf->AllocVa; +#endif + + dma_buf->pNdisPacket = pPacket; + dma_buf->pNextNdisPacket = NULL; + dma_buf->PacketPa = PCI_MAP_SINGLE(pAd, frm_buf, pkt_len, 0, RTMP_PCI_DMA_TODEVICE); + + pTxD->SDPtr0 = dma_buf->PacketPa; + pTxD->SDLen0 = pkt_len; + pTxD->LastSec0 = 1; + pTxD->SDPtr1 = 0; + pTxD->LastSec1 = 0; + pTxD->SDLen1 = 0; + pTxD->Burst = 0; + +#if defined(RTMP_MAC) || defined(RLT_MAC) + ral_write_txd(pAd, pTxD, NULL, TRUE, FIFO_MGMT); +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ +#ifdef MT_MAC + mt_write_txd(pAd, pTxD); +#endif /* MT_MAC */ + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((UCHAR *)pTxD, TYPE_TXD); + WriteBackToDescriptor((UCHAR *)pDestTxD, (UCHAR *)pTxD, FALSE, TYPE_TXD); +#endif + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pSrcBufVA, SrcBufLen); + RTMP_DCACHE_FLUSH(dma_buf->AllocPa, TXD_SIZE); + +#if defined(MT7603) || defined(MT7628) + if ((IS_MT7603(pAd) || (IS_MT7628(pAd))) && (QueIdx == Q_IDX_BCN)) + { + INC_RING_INDEX(pAd->BcnRing.TxCpuIdx, BCN_RING_SIZE); + RTMP_IO_WRITE32(pAd, pAd->BcnRing.hw_cidx_addr, pAd->BcnRing.TxCpuIdx); + } + else +#endif /* MT7603 */ + { + /* Increase TX_CTX_IDX, but write to register later.*/ + INC_RING_INDEX(pAd->MgmtRing.TxCpuIdx, MGMT_RING_SIZE); + RTMP_IO_WRITE32(pAd, pAd->MgmtRing.hw_cidx_addr, pAd->MgmtRing.TxCpuIdx); + } + + return 0; +} + +#ifdef CONFIG_AP_SUPPORT + +static VOID trPsTokenUpdate(RTMP_ADAPTER *pAd,UINT QueIdx,PNDIS_PACKET pPacket) +{ + struct tx_swq_fifo *fifo_swq; + STA_TR_ENTRY *tr_entry; + INT enq_idx; + UCHAR wcid; + + wcid = RTMP_GET_PACKET_WCID(pPacket); + + if(wcid < MAX_LEN_OF_TR_TABLE) + { + + tr_entry = &pAd->MacTab.tr_entry[wcid]; + + if (tr_entry->tx_queue[QueIdx].Number == 0) + { + tr_entry->TokenCount[QueIdx] = 0; + } else + if ((tr_entry->ps_state == APPS_RETRIEVE_IDLE) && (tr_entry->TokenCount[QueIdx] > 0)) + { + fifo_swq = &pAd->tx_swq[QueIdx]; + enq_idx = fifo_swq->enqIdx; + + if ((fifo_swq->swq[enq_idx] == 0) && (tr_entry->enq_cap)) + { + fifo_swq->swq[enq_idx] = tr_entry->wcid; + INC_RING_INDEX(fifo_swq->enqIdx, TX_SWQ_FIFO_LEN); + TR_TOKEN_COUNT_DEC(tr_entry, QueIdx); + } + } + } +} + +#endif + +BOOLEAN RTMPFreeTXDUponTxDmaDone( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx) +{ + RTMP_TX_RING *pTxRing; + TXD_STRUC *pTxD; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR tx_hw_info[TXD_SIZE]; +#endif + PNDIS_PACKET pPacket; + UCHAR FREE = 0; + TXD_STRUC TxD, *pOriTxD; + BOOLEAN bReschedule = FALSE; + //UINT8 TXWISize = pAd->chipCap.TXWISize; + +#ifdef MT_MAC + if (QueIdx == QID_BMC) + pTxRing = &pAd->TxBmcRing; + else +#endif /* MT_MAC */ + { + ASSERT(QueIdx < NUM_OF_TX_RING); + if (QueIdx >= NUM_OF_TX_RING) + return FALSE; + + pTxRing = &pAd->TxRing[QueIdx]; + } + + RTMP_IO_READ32(pAd, pTxRing->hw_didx_addr, &pTxRing->TxDmaIdx); + while (pTxRing->TxSwFreeIdx != pTxRing->TxDmaIdx) + { +#ifdef CONFIG_ATE +#ifdef CONFIG_QA + if ((ATE_ON(pAd)) && (pAd->ATECtrl.bQATxStart == TRUE) && (pAd->ATECtrl.QID == QueIdx)) + { + HEADER_802_11 *pHeader80211; + + pAd->ATECtrl.TxDoneCount++; + pAd->RalinkCounters.KickTxCount++; + + /* always use QID_AC_BE and FIFO_EDCA */ + ASSERT(pAd->ATECtrl.QID == 0); + pAd->ATECtrl.TxAc0++; + + FREE++; +#ifndef RT_BIG_ENDIAN + pTxD = (TXD_STRUC *) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); + pOriTxD = pTxD; + NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); + pTxD = &TxD; +#else + pDestTxD = (TXD_STRUC *) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); + pOriTxD = pDestTxD ; + //TxD = *pDestTxD; + //pTxD = &TxD; + NdisMoveMemory(&tx_hw_info[0], pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif +/* pTxD->DMADONE = 0; */ + + pHeader80211 = (PHEADER_802_11)((UCHAR *)(pTxRing->Cell[pTxRing->TxSwFreeIdx].DmaBuf.AllocVa) + pAd->chipCap.TXWISize); +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_READ, FALSE); +#endif + pHeader80211->Sequence = ++pAd->ATECtrl.seq; +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHeader80211, DIR_WRITE, FALSE); +#endif + + if ((pAd->ATECtrl.bQATxStart == TRUE) && (pAd->ATECtrl.Mode & ATE_TXFRAME) && (pAd->ATECtrl.TxDoneCount < pAd->ATECtrl.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, pTxRing->hw_didx_addr, &pTxRing->TxDmaIdx); + goto kick_out; + } + else if ((pAd->ATECtrl.TxStatus == 1)/* or (pAd->ate.bQATxStart == TRUE) ??? */ && (pAd->ATECtrl.TxDoneCount == pAd->ATECtrl.TxCount)) + { + DBGPRINT(RT_DEBUG_TRACE,("all Tx is done\n")); + + /* Tx status enters idle mode.*/ + pAd->ATECtrl.TxStatus = 0; + } + else if (!(pAd->ATECtrl.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->ATECtrl.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; + NdisMoveMemory(pDestTxD, pTxD, TXD_SIZE); +#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 /* CONFIG_QA */ +#endif /* CONFIG_ATE */ + + /* + Note: + + Can not take off the NICUpdateFifoStaCounters(); Or the + FIFO overflow rate will be high, i.e. > 3% + (see the rate by "iwpriv ra0 show stainfo") + + Based on different platform, try to find the best value to + replace '4' here (overflow rate target is about 0%). + */ + if (++pAd->FifoUpdateRx >= FIFO_STAT_READ_PERIOD) + { + NICUpdateFifoStaCounters(pAd); + pAd->FifoUpdateRx = 0; + } + + /* Note : If (pAd->ate.bQATxStart == TRUE), we will never reach here. */ + FREE++; +#ifndef RT_BIG_ENDIAN + pTxD = (TXD_STRUC *) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); + pOriTxD = pTxD; + NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); + pTxD = &TxD; +#else + pDestTxD = (TXD_STRUC *) (pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocVa); + pOriTxD = pDestTxD ; + //TxD = *pDestTxD; + //pTxD = &TxD; + NdisMoveMemory(&tx_hw_info[0], pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif +/* pTxD->DMADONE = 0; */ + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) +#ifdef UAPSD_SUPPORT + UAPSD_SP_PacketCheck(pAd, + pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket, + ((UCHAR *)pTxRing->Cell[\ + pTxRing->TxSwFreeIdx].DmaBuf.AllocVa) + pAd->chipCap.TXWISize); +#endif /* UAPSD_SUPPORT */ +#else +#ifdef CONFIG_AP_SUPPORT +#ifdef UAPSD_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + UAPSD_SP_PacketCheck(pAd, + pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket, + ((UCHAR *)pTxRing->Cell[pTxRing->TxSwFreeIdx].DmaBuf.AllocVa) + pAd->chipCap.TXWISize); + } +#endif /* UAPSD_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + +#ifdef CONFIG_ATE + /* Execution of this block is not allowed when ATE is running. */ + if (!(ATE_ON(pAd))) +#endif /* CONFIG_ATE */ + { + pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket; + if (pPacket) + { +#ifndef DMA_CACHE_OPTIMIZE +#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); +#endif /* DMA_CACHE_OPTIMIZE */ + +#ifdef CONFIG_AP_SUPPORT + if (QueIdx < WMM_QUE_NUM) + { + trPsTokenUpdate(pAd,QueIdx,pPacket); + } +#endif /* CONFIG_AP_SUPPORT */ + + + +#ifdef WLAN_SKB_RECYCLE + if (skb_queue_len(&pAd->rx0_recycle) < NUM_RX_DESC && + skb_recycle_check(RTPKT_TO_OSPKT(pPacket), RX_BUFFER_NORMSIZE)) + __skb_queue_head(&pAd->rx0_recycle, RTPKT_TO_OSPKT(pPacket)); + else +#endif /* WLAN_SKB_RECYCLE */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + + pTxRing->Cell[pTxRing->TxSwFreeIdx].pNdisPacket = NULL; + } + + pPacket = pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket; + if (pPacket) + { +#ifndef DMA_CACHE_OPTIMIZE +#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); +#endif /* DMA_CACHE_OPTIMIZE */ + +#ifdef WLAN_SKB_RECYCLE + if (skb_queue_len(&pAd->rx0_recycle) < NUM_RX_DESC && + skb_recycle_check(RTPKT_TO_OSPKT(pPacket), RX_BUFFER_NORMSIZE )) + __skb_queue_head(&pAd->rx0_recycle, RTPKT_TO_OSPKT(pPacket)); + else +#endif /* WLAN_SKB_RECYCLE */ + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + + pTxRing->Cell[pTxRing->TxSwFreeIdx].pNextNdisPacket = NULL; + } + } + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxRing->Cell[pTxRing->TxSwFreeIdx].AllocPa, TXD_SIZE); + + pAd->RalinkCounters.TransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); + pAd->RalinkCounters.OneSecTransmittedByteCount += (pTxD->SDLen1 + pTxD->SDLen0); + +#ifdef MT_MAC + if (QueIdx == QID_BMC) + pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE]++; + else +#endif /* MT_MAC */ + pAd->RalinkCounters.OneSecDmaDoneCount[QueIdx]++; + + INC_RING_INDEX(pTxRing->TxSwFreeIdx, TX_RING_SIZE); + +#ifdef CONFIG_WIFI_TEST + pTxRing->Cell[pTxRing->TxSwFreeIdx].DataOut = 0; + pTxRing->Cell[pTxRing->TxSwFreeIdx].TimePeriod = 0; +#endif + + /* get tx_tdx_idx again */ + RTMP_IO_READ32(pAd, pTxRing->hw_didx_addr, &pTxRing->TxDmaIdx); + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + //*pDestTxD = TxD; + NdisMoveMemory(pDestTxD, pTxD, TXD_SIZE); +#else + NdisMoveMemory(pOriTxD, pTxD, sizeof(TXD_STRUC)); +#endif + +#ifdef CONFIG_ATE +#ifdef CONFIG_QA +kick_out: +#endif /* CONFIG_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->ATECtrl.Mode & ATE_TXFRAME) && (QueIdx == pAd->ATECtrl.QID) && + (QueIdx < NUM_OF_TX_RING)) { + /* TxDoneCount++ has been done if QA is used.*/ + if (pAd->ATECtrl.bQATxStart == FALSE) + pAd->ATECtrl.TxDoneCount++; + + if (((pAd->ATECtrl.TxCount - pAd->ATECtrl.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 = (TXD_STRUC *) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa); + pOriTxD = pTxD; + NdisMoveMemory(&TxD, pTxD, sizeof(TXD_STRUC)); + pTxD = &TxD; +#else + pDestTxD = (TXD_STRUC *) (pTxRing->Cell[pAd->TxRing[QueIdx].TxCpuIdx].AllocVa); + pOriTxD = pDestTxD ; + NdisMoveMemory(&tx_hw_info[0], pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + 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); + NdisMoveMemory(pDestTxD, pTxD, TXD_SIZE); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxRing->Cell[pTxRing->TxCpuIdx].AllocPa, RXD_SIZE); + + /* kick Tx-Ring*/ + RTMP_IO_WRITE32(pAd, pTxRing->hw_cidx_addr, pTxRing->TxCpuIdx); + + pAd->RalinkCounters.KickTxCount++; + } + } +#endif /* CONFIG_ATE */ + } + + + return bReschedule; + +} + + +/* + ======================================================================== + + Routine Description: + Process TX Rings DMA Done interrupt, running in DPC level + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +BOOLEAN RTMPHandleTxRingDmaDoneInterrupt( + IN RTMP_ADAPTER *pAd, + IN RTMP_TX_DONE_MASK tx_mask) +{ + ULONG IrqFlags = 0; + BOOLEAN bReschedule = FALSE; + + + /* Make sure Tx ring resource won't be used by other threads*/ + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + if (tx_mask & TX_AC0_DONE) + bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK); + + if (tx_mask & TX_AC1_DONE) + bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE); + } +#endif /* MT_MAC */ + +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (pAd->chipCap.hif_type == HIF_RTMP || pAd->chipCap.hif_type == HIF_RLT) + { + if (tx_mask & TX_AC0_DONE) + bReschedule = RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BE); + + if (tx_mask & TX_AC1_DONE) + bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_BK); + } +#endif /* #if defined(RTMP_MAC) || defined(RLT_MAC) */ + + if (tx_mask & TX_HCCA_DONE) + bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_HCCA); + + if (tx_mask & TX_AC3_DONE) + bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VO); + + if (tx_mask & TX_AC2_DONE) + bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_AC_VI); +#ifdef MT_MAC + if (tx_mask & TX_BMC_DONE) + bReschedule |= RTMPFreeTXDUponTxDmaDone(pAd, QID_BMC); +#endif /* MT_MAC */ + + /* Make sure to release Tx ring resource*/ + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, WCID_ALL, MAX_TX_PROCESS); + + return bReschedule; +} + + +/* + ======================================================================== + + Routine Description: + Process MGMT ring DMA done interrupt, running in DPC level + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPHandleMgmtRingDmaDoneInterrupt(RTMP_ADAPTER *pAd) +{ + TXD_STRUC *pTxD; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR tx_hw_info[TXD_SIZE]; +#endif + PNDIS_PACKET pPacket; +/* int i;*/ + UCHAR FREE = 0; + RTMP_MGMT_RING *pMgmtRing = &pAd->MgmtRing; + //UINT8 TXWISize = pAd->chipCap.TXWISize; + + + NdisAcquireSpinLock(&pAd->MgmtRingLock); + + RTMP_IO_READ32(pAd, pMgmtRing->hw_didx_addr, &pMgmtRing->TxDmaIdx); + while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx) + { + FREE++; +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa); + //TxD = *pDestTxD; + //pTxD = &TxD; + NdisMoveMemory(&tx_hw_info[0], pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_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) + pAd->chipCap.TXWISize) + +#ifdef UAPSD_SUPPORT +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + UAPSD_QoSNullTxMgmtTxDoneHandle(pAd, + pPacket, + LMR_FRAME_GET(), FALSE); +#else +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + UAPSD_QoSNullTxMgmtTxDoneHandle(pAd, + pPacket, LMR_FRAME_GET(), FALSE); + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_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, TXD_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(RTMP_ADAPTER *pAd) +{ +//+++Add by Carter +#ifdef MT_MAC + volatile UINT32 en_cr, stat_cr; + + stat_cr = 0x00000000L; + en_cr = 0x00000000L; + + printk("%s\n", __func__); + + RTMP_IO_READ32(pAd, HWISR3, &stat_cr); + RTMP_IO_READ32(pAd, HWIER3, &en_cr); + + /* disable the interrupt source */ + RTMP_IO_WRITE32(pAd, HWIER3, (~stat_cr & en_cr)); + + /* write 1 to clear */ + RTMP_IO_WRITE32(pAd, HWISR3, stat_cr); + RTMP_IO_WRITE32(pAd, HWIER3, en_cr); +#endif /* MT_MAC */ +//---Add by Carter + +#ifdef CONFIG_AP_SUPPORT + if (pAd->OpMode == OPMODE_AP) + { + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (pAd->chipCap.hif_type != HIF_MT) + ReSyncBeaconTime(pAd); +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + /* disable mask */ + + } +#endif /*MT_MAC */ + + RTMP_OS_TASKLET_SCHE(&pObj->tbtt_task); + + 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)) + { + } + } +} + + +VOID RTMPHandleTTTTInterrupt(RTMP_ADAPTER *pAd) +{ +//+++Add by Carter +#ifdef MT_MAC + //volatile UINT32 en_cr, stat_cr; + printk("%s\n", __func__); + + //stat_cr = 0x00000000L; + //en_cr = 0x00000000L; +#endif +} + +/* + ======================================================================== + + Routine Description: + Arguments: + pAd Pointer to our adapter. Rewrite beacon content before next send-out. + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID RTMPHandlePreTBTTInterrupt(RTMP_ADAPTER *pAd) +{ +#ifdef CONFIG_AP_SUPPORT + + if (pAd->OpMode == OPMODE_AP + ) + { + APUpdateAllBeaconFrame(pAd); + } + else +#endif /* CONFIG_AP_SUPPORT */ + { + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s()...\n", __FUNCTION__)); + } + } + +#ifdef MT_MAC + /* use pretbtt to check DTIM and dequeue bmc packets */ +//#ifdef USE_BMC + if (pAd->chipCap.hif_type == HIF_MT) { + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + RTMP_OS_TASKLET_SCHE(&pObj->tbtt_task); + } +//#endif +#endif /*MT_MAC */ + +} + +#if defined (MT_MAC) && defined (CONFIG_AP_SUPPORT) +VOID RTMPHandlePreTTTTInterrupt(RTMP_ADAPTER *pAd) +{ + printk("%s\n", __func__); + /* only AP MODE support TTTT now, p2p go don't take care of this. */ + if (pAd->OpMode == OPMODE_AP) + { + APMakeAllTimFrame(pAd); + } +} +#endif + +VOID RTMPHandleRxCoherentInterrupt(RTMP_ADAPTER *pAd) +{ + if (pAd == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("====> pAd is NULL, return.\n")); + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPHandleRxCoherentInterrupt \n")); + +#if defined(MT7603) || defined(MT7628) + // TODO: shiang-MT7603, fix me for upper crash case!! + if (IS_MT7603(pAd) || IS_MT7628(pAd)) { + return; + } +#endif /* MT7603*/ + + AsicSetWPDMA(pAd, PDMA_TX_RX, FALSE); + + RTMPRingCleanUp(pAd, QID_AC_BE); + RTMPRingCleanUp(pAd, QID_AC_BK); + RTMPRingCleanUp(pAd, QID_AC_VI); + RTMPRingCleanUp(pAd, QID_AC_VO); + RTMPRingCleanUp(pAd, QID_CTRL); + RTMPRingCleanUp(pAd, QID_MGMT); + RTMPRingCleanUp(pAd, QID_RX); + + RTMPEnableRxTx(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPHandleRxCoherentInterrupt \n")); +} + + +#ifdef CONFIG_AP_SUPPORT +VOID RTMPHandleMcuInterrupt(RTMP_ADAPTER *pAd) +{ + UINT32 McuIntSrc = 0; + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(): Not support for HIF_MT yet!\n", + __FUNCTION__)); + return; + } + + 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 */ + + +#ifdef RLT_MAC + + +static inline INT rlt_rx_info_2_blk(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk, PNDIS_PACKET pRxPacket) +{ + struct _RXWI_NMAC *rxwi_n; + UCHAR *buf_ptr; +#ifdef RT_BIG_ENDIAN + RXINFO_STRUC *pRxInfo; + RXINFO_STRUC RxInfo; +#endif /* RT_BIG_ENDIAN */ + + pRxBlk->pRxFceInfo = (RXFCE_INFO *)&pRxBlk->hw_rx_info[RXINFO_OFFSET]; + pRxBlk->pRxInfo = (RXINFO_STRUC *)GET_OS_PKT_DATAPTR(pRxPacket); +#ifdef RT_BIG_ENDIAN + NdisMoveMemory(&RxInfo, pRxBlk->pRxInfo, RAL_RXINFO_SIZE); + pRxInfo = &RxInfo; + (*(UINT32*)pRxInfo) = le2cpu32(*(UINT32*)pRxInfo); + NdisMoveMemory(pRxBlk->pRxInfo, pRxInfo, RAL_RXINFO_SIZE); +#endif /* RT_BIG_ENDIAN */ + + rxwi_n = (struct _RXWI_NMAC *)(GET_OS_PKT_DATAPTR(pRxPacket) + RAL_RXINFO_SIZE); + pRxBlk->pRxWI = (RXWI_STRUC *)(rxwi_n); +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd , (UCHAR *)pRxBlk->pRxWI, TYPE_RXWI); +#endif /* RT_BIG_ENDIAN */ + + pRxBlk->MPDUtotalByteCnt = rxwi_n->MPDUtotalByteCnt; + pRxBlk->wcid = rxwi_n->wcid; + pRxBlk->key_idx = rxwi_n->key_idx; + pRxBlk->bss_idx = rxwi_n->bss_idx; + pRxBlk->TID = rxwi_n->tid; + pRxBlk->DataSize = rxwi_n->MPDUtotalByteCnt; + + pRxBlk->rx_rate.field.MODE = rxwi_n->phy_mode; + pRxBlk->rx_rate.field.MCS = rxwi_n->mcs; + pRxBlk->rx_rate.field.ldpc = rxwi_n->ldpc; + pRxBlk->rx_rate.field.BW = rxwi_n->bw; + pRxBlk->rx_rate.field.STBC = rxwi_n->stbc; + pRxBlk->rx_rate.field.ShortGI = rxwi_n->sgi; + pRxBlk->rx_signal.raw_rssi[0] = rxwi_n->rssi[0]; + pRxBlk->rx_signal.raw_rssi[1] = rxwi_n->rssi[1]; + pRxBlk->rx_signal.raw_rssi[2] = rxwi_n->rssi[2]; + { + pRxBlk->rx_signal.raw_snr[0] = rxwi_n->bbp_rxinfo[0]; + pRxBlk->rx_signal.raw_snr[1] = rxwi_n->bbp_rxinfo[1]; + pRxBlk->rx_signal.raw_snr[2] = rxwi_n->bbp_rxinfo[2]; + } + pRxBlk->rx_signal.freq_offset = rxwi_n->bbp_rxinfo[4]; + pRxBlk->ldpc_ex_sym = rxwi_n->ldpc_ex_sym; + + SET_OS_PKT_DATAPTR(pRxPacket, GET_OS_PKT_DATAPTR(pRxPacket) + RAL_RXINFO_SIZE + pAd->chipCap.RXWISize); + SET_OS_PKT_LEN(pRxPacket, GET_OS_PKT_LEN(pRxPacket) - RAL_RXINFO_SIZE - pAd->chipCap.RXWISize); + + return TRUE; +} +#endif /* RLT_MAC */ + + +#ifdef RTMP_MAC +static inline INT rtmp_rx_info_2_blk(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk, PNDIS_PACKET pRxPacket) +{ + struct _RXWI_OMAC *rxwi_o = (struct _RXWI_OMAC *)(GET_OS_PKT_DATAPTR(pRxPacket)); + + pRxBlk->pRxInfo = (RXINFO_STRUC *)(&pRxBlk->hw_rx_info[RXINFO_OFFSET]); + pRxBlk->pRxWI = (RXWI_STRUC *)rxwi_o; +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd , (UCHAR *)pRxBlk->pRxWI, TYPE_RXWI); +#endif /* RT_BIG_ENDIAN */ + + pRxBlk->MPDUtotalByteCnt = rxwi_o->MPDUtotalByteCnt; + pRxBlk->wcid = rxwi_o->wcid; + pRxBlk->key_idx = rxwi_o->key_idx; + pRxBlk->bss_idx = rxwi_o->bss_idx; + pRxBlk->TID = rxwi_o->tid; + pRxBlk->DataSize = rxwi_o->MPDUtotalByteCnt; + + pRxBlk->rx_rate.field.MODE = rxwi_o->phy_mode; + pRxBlk->rx_rate.field.MCS = rxwi_o->mcs; + pRxBlk->rx_rate.field.BW = rxwi_o->bw; + pRxBlk->rx_rate.field.STBC = rxwi_o->stbc; + pRxBlk->rx_rate.field.ShortGI = rxwi_o->sgi; + pRxBlk->rx_signal.raw_rssi[0] = rxwi_o->RSSI0; + pRxBlk->rx_signal.raw_rssi[1] = rxwi_o->RSSI1; + pRxBlk->rx_signal.raw_rssi[2] = rxwi_o->RSSI2; + pRxBlk->rx_signal.raw_snr[0] = rxwi_o->SNR0; + pRxBlk->rx_signal.raw_snr[1] = rxwi_o->SNR1; + pRxBlk->rx_signal.raw_snr[2] = rxwi_o->SNR2; + pRxBlk->rx_signal.freq_offset = rxwi_o->FOFFSET; + + SET_OS_PKT_DATAPTR(pRxPacket, GET_OS_PKT_DATAPTR(pRxPacket) + pAd->chipCap.RXWISize); + SET_OS_PKT_LEN(pRxPacket, GET_OS_PKT_LEN(pRxPacket) - pAd->chipCap.RXWISize); + + return TRUE; +} +#endif /* RTMP_MAC */ + + +PNDIS_PACKET GetPacketFromRxRing( + IN RTMP_ADAPTER *pAd, + OUT RX_BLK *pRxBlk, + OUT BOOLEAN *pbReschedule, + INOUT UINT32 *pRxPending, + UCHAR RxRingNo) +{ + RXD_STRUC *pRxD; +#ifdef RT_BIG_ENDIAN + RXD_STRUC *pDestRxD; + UCHAR rx_hw_info[RXD_SIZE]; +#endif + RTMP_RX_RING *pRxRing; + NDIS_SPIN_LOCK *pRxRingLock; + PNDIS_PACKET pRxPacket = NULL, pNewPacket; + VOID *AllocVa; + NDIS_PHYSICAL_ADDRESS AllocPa; + BOOLEAN bReschedule = FALSE; + RTMP_DMACB *pRxCell; + //UINT8 RXWISize = pAd->chipCap.RXWISize; + UINT8 rx_hw_hdr_len = pAd->chipCap.RXWISize; + + pRxRing = &pAd->RxRing[RxRingNo]; + pRxRingLock = &pAd->RxRingLock[RxRingNo]; + RTMP_SEM_LOCK(pRxRingLock); + + if (*pRxPending == 0) + { + /* Get how may packets had been received */ + RTMP_IO_READ32(pAd, pRxRing->hw_didx_addr, &pRxRing->RxDmaIdx); + if (pRxRing->RxSwReadIdx == pRxRing->RxDmaIdx) + { + bReschedule = FALSE; + goto done; + } + + /* get rx pending count */ + if (pRxRing->RxDmaIdx > pRxRing->RxSwReadIdx) + *pRxPending = pRxRing->RxDmaIdx - pRxRing->RxSwReadIdx; + else + *pRxPending = pRxRing->RxDmaIdx + RX_RING_SIZE - pRxRing->RxSwReadIdx; + } + + pRxCell = &pRxRing->Cell[pRxRing->RxSwReadIdx]; + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pRxCell->AllocPa, RXD_SIZE); + +#ifdef RT_BIG_ENDIAN + pDestRxD = (RXD_STRUC *)pRxCell->AllocVa; + /* RxD = *pDestRxD; */ + NdisMoveMemory(&rx_hw_info[0], pDestRxD, RXD_SIZE); + pRxD = (RXD_STRUC *)&rx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + /* Point to Rx indexed rx ring descriptor */ + pRxD = (RXD_STRUC *) pRxCell->AllocVa; +#endif + + if (pRxD->DDONE == 0) + { + *pRxPending = 0; + DBGPRINT(RT_DEBUG_INFO, ("DDONE=0!\n")); + /* DMAIndx had done but DDONE bit not ready */ + bReschedule = TRUE; + goto done; + } + + if ((pRxD->LS0 == 0) || ((pRxD->LS0 == 1) && (pAd->DropInvalidPacket >= 1))) + { + if (pRxD->LS0 == 0) + pAd->DropInvalidPacket++; + else + pAd->DropInvalidPacket = 0; + + if (pAd->DropInvalidPacket >= 1) + { + /* 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; + + DBGPRINT(RT_DEBUG_OFF, ("Ring No = %d\n", RxRingNo)); + hex_dump("Invalid Pkt content", GET_OS_PKT_DATAPTR(pRxPacket), 32); + } + + pRxD->SDL0 = RX_BUFFER_AGGRESIZE; + pRxD->LS0 = 0; + pRxD->DDONE = 0; + bReschedule = TRUE; + *pRxPending = 0; + pRxPacket = NULL; + + /* update rx descriptor and kick rx */ +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); + WriteBackToDescriptor((PUCHAR)pDestRxD, (PUCHAR)pRxD, FALSE, TYPE_RXD); +#endif + + INC_RING_INDEX(pRxRing->RxSwReadIdx, RX_RING_SIZE); + + pRxRing->RxCpuIdx = (pRxRing->RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pRxRing->RxSwReadIdx-1); + RTMP_IO_WRITE32(pAd, pRxRing->hw_cidx_addr, pRxRing->RxCpuIdx); + + goto done; + } + +#ifndef RT_BIG_ENDIAN + /* return rx descriptor */ + NdisMoveMemory(&pRxBlk->hw_rx_info[0], pRxD, RXD_SIZE); +#endif /* RT_BIG_ENDIAN */ + +#ifdef WLAN_SKB_RECYCLE + { + struct sk_buff *skb = __skb_dequeue_tail(&pAd->rx0_recycle); + + if (unlikely(skb==NULL)) + pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa); + else + { + pNewPacket = OSPKT_TO_RTPKT(skb); + AllocVa = GET_OS_PKT_DATAPTR(pNewPacket); + AllocPa = PCI_MAP_SINGLE_DEV(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, AllocVa, RX_BUFFER_AGGRESIZE, -1, RTMP_PCI_DMA_FROMDEVICE); + } + } +#else + pNewPacket = RTMP_AllocateRxPacketBuffer(pAd, ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, RX_BUFFER_AGGRESIZE, FALSE, &AllocVa, &AllocPa); +#endif /* WLAN_SKB_RECYCLE */ + + if (pNewPacket && !pAd->RxReset) + { +#ifndef DMA_CACHE_OPTIMIZE + /* unmap the rx buffer*/ + PCI_UNMAP_SINGLE(pAd, pRxCell->DmaBuf.AllocPa, + pRxCell->DmaBuf.AllocSize, RTMP_PCI_DMA_FROMDEVICE); +#endif /* DMA_CACHE_OPTIMIZE */ + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pRxCell->DmaBuf.AllocPa, pRxCell->DmaBuf.AllocSize); + + pRxPacket = pRxCell->pNdisPacket; + + pRxBlk->Flags = 0; + pRxBlk->PDMALen = pRxD->SDL0; +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + rx_hw_hdr_len = parse_rx_packet_type(pAd, pRxBlk, pRxPacket); + if (rx_hw_hdr_len == 0) + {pRxBlk->DataSize = 0;} + } +#endif /* MT_MAC */ + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + rlt_rx_info_2_blk(pAd, pRxBlk, pRxPacket); + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + rtmp_rx_info_2_blk(pAd, pRxBlk, pRxPacket); +#endif /* RTMP_MAC */ + + if (pRxPacket) + { + pRxBlk->pRxPacket = pRxPacket; + pRxBlk->pData = (UCHAR *)GET_OS_PKT_DATAPTR(pRxPacket); + pRxBlk->pHeader = (HEADER_802_11 *)(pRxBlk->pData); + } + + 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; + pRxD->SDL0 = RX_BUFFER_AGGRESIZE; + } + else + { + if (pNewPacket) + { + RELEASE_NDIS_PACKET(pAd, pNewPacket, NDIS_STATUS_SUCCESS); +#ifdef NEW_IXIA_METHOD + /*RX Drop*/ + pAd->tr_ststic.rx[DROP_NO_BUF]++; +#endif + } + + pAd->RxResetDropCount++; + + if (pAd->RxResetDropCount > 10) + { + pAd->RxReset = 0; + pAd->RxResetDropCount = 0; +#ifdef MT_PS + MtPsRecovery(pAd); +#endif /* MT_PS */ + } + + pRxD->SDL0 = RX_BUFFER_AGGRESIZE; + pRxPacket = NULL; + bReschedule = TRUE; + } + + *pRxPending = *pRxPending - 1; + +#ifndef CACHE_LINE_32B + pRxD->DDONE = 0; + + /* update rx descriptor and kick rx */ +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); + WriteBackToDescriptor((PUCHAR)pDestRxD, (PUCHAR)pRxD, FALSE, TYPE_RXD); +#endif + + INC_RING_INDEX(pRxRing->RxSwReadIdx, RX_RING_SIZE); + + pRxRing->RxCpuIdx = (pRxRing->RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pRxRing->RxSwReadIdx-1); + RTMP_IO_WRITE32(pAd, pRxRing->hw_cidx_addr, pRxRing->RxCpuIdx); + +#else /* CACHE_LINE_32B */ + /* + Because our RXD_SIZE is 16B, but if the cache line size is 32B, we + will suffer a problem as below: + + 1. We flush RXD 0, start address of RXD 0 is 32B-align. + Nothing occurs. + 2. We flush RXD 1, start address of RXD 1 is 16B-align. + Because cache line size is 32B, cache must flush 32B, cannot flush + 16B only, so RXD0 and RXD1 will be flushed. + But when traffic is busy, maybe RXD0 is updated by MAC, i.e. + DDONE bit is 1, so when the cache flushs RXD0, the DDONE bit will + be cleared to 0. + 3. Then when we handle RXD0 in the future, we will find the DDONE bit + is 0 and we will wait for MAC to set it to 1 forever. + */ + if (pRxRing->RxSwReadIdx & 0x01) + { + RTMP_DMACB *pRxCellLast; +#ifdef RT_BIG_ENDIAN + RXD_STRUC *pDestRxDLast; +#endif + /* 16B-align */ + + /* update last BD 32B-align, DMA Done bit = 0 */ + pRxCell->LastBDInfo.DDONE = 0; +#ifdef RT_BIG_ENDIAN + pRxCellLast = &pRxRing->Cell[pRxRing->RxSwReadIdx - 1]; + pDestRxDLast = (RXD_STRUC *) pRxCellLast->AllocVa; + RTMPDescriptorEndianChange((PUCHAR)&pRxCell->LastBDInfo, TYPE_RXD); + WriteBackToDescriptor((UCHAR *)pDestRxDLast, (UCHAR *)&pRxCell->LastBDInfo, FALSE, TYPE_RXD); +#endif + + /* update current BD 16B-align, DMA Done bit = 0 */ + pRxD->DDONE = 0; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); + WriteBackToDescriptor((PUCHAR)pDestRxD, (PUCHAR)pRxD, FALSE, TYPE_RXD); +#endif + + /* flush cache from last BD */ + RTMP_DCACHE_FLUSH(pRxCellLast->AllocPa, 32); /* use RXD_SIZE should be OK */ + + /* update SW read and CPU index */ + INC_RING_INDEX(pRxRing->RxSwReadIdx, RX_RING_SIZE); + pRxRing->RxCpuIdx = (pRxRing->RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pRxRing->RxSwReadIdx-1); + RTMP_IO_WRITE32(pAd, pRxRing->hw_cidx_addr, pRxRing->RxCpuIdx); + } + else + { + /* 32B-align */ + /* do not set DDONE bit and backup it */ + if (pRxRing->RxSwReadIdx >= (RX_RING_SIZE-1)) + { + DBGPRINT(RT_DEBUG_ERROR, + ("Please change RX_RING_SIZE to mutiple of 2!\n")); + + /* flush cache from current BD */ + RTMP_DCACHE_FLUSH(pRxCell->AllocPa, RXD_SIZE); + + /* update SW read and CPU index */ + INC_RING_INDEX(pRxRing->RxSwReadIdx, RX_RING_SIZE); + pRxRing->RxCpuIdx = (pRxRing->RxSwReadIdx == 0) ? (RX_RING_SIZE-1) : (pRxRing->RxSwReadIdx-1); + RTMP_IO_WRITE32(pAd, pRxRing->hw_cidx_addr, pRxRing->RxCpuIdx); + } + else + { + /* backup current BD */ + pRxCell = &pRxRing->Cell[pRxRing->RxSwReadIdx + 1]; + pRxCell->LastBDInfo = *pRxD; + + /* update CPU index */ + INC_RING_INDEX(pRxRing->RxSwReadIdx, RX_RING_SIZE); + } + } +#endif /* CACHE_LINE_32B */ + +done: + RTMP_SEM_UNLOCK(pRxRingLock); + *pbReschedule = bReschedule; + return pRxPacket; +} + + +NDIS_STATUS MlmeHardTransmitTxRing(RTMP_ADAPTER *pAd, UCHAR QueIdx, PNDIS_PACKET pPacket) +{ + PACKET_INFO PacketInfo; + UCHAR *pSrcBufVA, *tmac_info, *frm_buf; + UINT SrcBufLen, frm_len; + TXD_STRUC *pTxD; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR hw_hdr_info[TXD_SIZE]; +#endif + PHEADER_802_11 pHeader_802_11; + PFRAME_BAR pBar = NULL; + BOOLEAN bAckRequired, bInsertTimestamp; + #ifdef GN_ONLY_AP_SUPPORT + BOOLEAN BMode = TRUE, bExcludeBRate=FALSE; +#endif + UCHAR MlmeRate, wcid, tx_rate; + UINT32 SwIdx; + ULONG FreeNum; + MAC_TABLE_ENTRY *pMacEntry = NULL; +#if defined(VHT_TXBF_SUPPORT) || (!defined(MT7603) && !defined(MT7628)) + UINT8 TXWISize = pAd->chipCap.TXWISize; +#endif /* defined(VHT_TXBF_SUPPORT) || (!defined(MT7603) && !defined(MT7628)) */ + UINT8 tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len; + HTTRANSMIT_SETTING *transmit, TransmitSetting; + MAC_TX_INFO mac_info; +#ifdef CONFIG_AP_SUPPORT +#ifdef SPECIFIC_TX_POWER_SUPPORT + UCHAR TxPwrAdj = 0; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + UCHAR prot = 0; + UCHAR apidx = 0; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + if (pSrcBufVA == NULL) + return NDIS_STATUS_FAILURE; + + FreeNum = GET_TXRING_FREENO(pAd, QueIdx); + if (FreeNum == 0) + return NDIS_STATUS_FAILURE; + + SwIdx = pAd->TxRing[QueIdx].TxCpuIdx; +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *)pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; + NdisMoveMemory(&hw_hdr_info[0], pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&hw_hdr_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_STRUC *) pAd->TxRing[QueIdx].Cell[SwIdx].AllocVa; +#endif + + if (pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket) + { + DBGPRINT(RT_DEBUG_OFF, ("MlmeHardTransmit Error\n")); + return NDIS_STATUS_FAILURE; + } + + +#if defined(MT7603) || defined(MT7628) + // TODO: shiang-7603 + frm_buf = pSrcBufVA; + frm_len = SrcBufLen; + tmac_info = pSrcBufVA; +//DBGPRINT(RT_DEBUG_OFF, ("%s(): pSrcBufVA=0x%p, pHeader_802_11=0x%p, tmac_info=%p, tx_hw_hdr_len=%d\n", +// __FUNCTION__, pSrcBufVA, pHeader_802_11, tmac_info, tx_hw_hdr_len)); +#else + frm_buf = (UCHAR *)(pSrcBufVA + TXINFO_SIZE); + frm_len = SrcBufLen - TXINFO_SIZE; + tmac_info =(UCHAR *)(pSrcBufVA + TXINFO_SIZE); +#endif /* MT7603 */ + pHeader_802_11 = (HEADER_802_11 *)(pSrcBufVA + tx_hw_hdr_len); +#ifdef GN_ONLY_AP_SUPPORT + if((pAd->OpMode == OPMODE_STA) || (pAd->OpMode == OPMODE_AP)) { + UCHAR BssIdx,i,CCK_rate; + BSS_ENTRY *pEntry01; + bExcludeBRate = pAd->CommonCfg.bExcludeBRate; + + if(pHeader_802_11->FC.Type == FC_TYPE_MGMT) { + BssIdx = BssTableSearch(&pAd->ScanTab, pHeader_802_11->Addr3, pAd->LatchRfRegs.Channel); + pEntry01 = &pAd->ScanTab.BssEntry[BssIdx]; + if(BssIdx < 0xFF) { + BMode = FALSE; + for(i=0 ; i < MAX_LEN_OF_SUPPORTED_RATES;i++) { + CCK_rate = pEntry01->SupRate[i] & 0x7f; + if (CCK_rate == 2 || CCK_rate == 4 || CCK_rate == 11 || CCK_rate == 22) { + BMode = TRUE; + break; + } + } + } + } + if(!BMode || bExcludeBRate){ + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = MCS_RATE_6; + } + } +#endif + if (pHeader_802_11->Addr1[0] & 0x01) + MlmeRate = pAd->CommonCfg.BasicMlmeRate; + else + MlmeRate = pAd->CommonCfg.MlmeRate; + + if (((pHeader_802_11->FC.Type == FC_TYPE_DATA) && + (pHeader_802_11->FC.SubType == SUBTYPE_QOS_NULL)) || + ((pHeader_802_11->FC.Type == FC_TYPE_CNTL) && + (pHeader_802_11->FC.SubType == SUBTYPE_BLOCK_ACK_REQ))) + { + pMacEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); +#ifdef GN_ONLY_AP_SUPPORT + if((pAd->OpMode == OPMODE_STA) || (pAd->OpMode == OPMODE_AP)) { + if(!(pMacEntry->SupportRateMode & 0x01)) + BMode=FALSE; + } +#endif +#ifdef MAC_REPEATER_SUPPORT + if (pMacEntry != NULL && pAd->ApCfg.bMACRepeaterEn && IS_ENTRY_APCLI(pMacEntry)) + { + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + UCHAR MacTabWCID=0; + UCHAR isLinkValid; + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, FALSE, pHeader_802_11->Addr2, TRUE, &isLinkValid); + if (pReptEntry && pReptEntry->CliValid) + { + MacTabWCID = pReptEntry->MacTabWCID; + pMacEntry = &pAd->MacTab.Content[MacTabWCID]; + } + + } +#endif + } + +#ifdef DOT11W_PMF_SUPPORT + if (pAd->chipCap.hif_type == HIF_MT) + { + UINT32 ret = 0; + MAC_TABLE_ENTRY *pEntry = NULL; + + pEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); +#ifdef MAC_REPEATER_SUPPORT + if (pEntry != NULL && pAd->ApCfg.bMACRepeaterEn && IS_ENTRY_APCLI(pEntry)) + { + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + UCHAR MacTabWCID=0; + UCHAR isLinkValid; + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, FALSE, pHeader_802_11->Addr2, TRUE, &isLinkValid); + if (pReptEntry && pReptEntry->CliValid) + { + MacTabWCID = pReptEntry->MacTabWCID; + pEntry = &pAd->MacTab.Content[MacTabWCID]; + } + } +#endif + ret = PMF_RobustFrameClassify( + (PHEADER_802_11)pHeader_802_11, + (PUCHAR)(((PUCHAR)pHeader_802_11)+LENGTH_802_11), + (SrcBufLen - LENGTH_802_11 - tx_hw_hdr_len), + (PUCHAR) pEntry, + FALSE); + + if (pEntry) + apidx = pEntry->func_tb_idx; + + if (ret == UNICAST_ROBUST_FRAME) + { + prot = 1; + pHeader_802_11->FC.Wep = 1; + } + else if (ret == GROUP_ROBUST_FRAME) + { + ret = PMF_EncapBIPAction(pAd, + (PUCHAR)pHeader_802_11, + (SrcBufLen - tx_hw_hdr_len)); + if (ret == PMF_STATUS_SUCCESS) + prot = 2; + else + DBGPRINT(RT_DEBUG_OFF, ("%s, PMF GROUP ROBUST Encap fail, ret=%d\n", + __FUNCTION__, ret)); + } + } +#endif + + /* Verify Mlme rate for a/g bands.*/ + if ((pAd->LatchRfRegs.Channel > 14) && (MlmeRate < RATE_6)) /* 11A band*/ + MlmeRate = RATE_6; +#ifdef GN_ONLY_AP_SUPPORT + if((pAd->OpMode == OPMODE_STA) || (pAd->OpMode == OPMODE_AP)) { + if(!BMode) + MlmeRate= RATE_6; + } +#endif + /* + 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 */ + + bInsertTimestamp = FALSE; + + if (pHeader_802_11->FC.Type == FC_TYPE_CNTL) + { + if (pHeader_802_11->FC.SubType == SUBTYPE_BLOCK_ACK_REQ) + { + pBar = (PFRAME_BAR)(pSrcBufVA + tx_hw_hdr_len); + bAckRequired = TRUE; + } + else + { + bAckRequired = FALSE; + } +#ifdef VHT_TXBF_SUPPORT + if (pHeader_802_11->FC.SubType == SUBTYPE_VHT_NDPA) + pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, (SrcBufLen - TXINFO_SIZE - TXWISize - TSO_SIZE)); +#endif /* VHT_TXBF_SUPPORT*/ + } + else /* FC_TYPE_MGMT or FC_TYPE_DATA(must be NULL frame)*/ + { + if (pHeader_802_11->Addr1[0] & 0x01) /* MULTICAST, BROADCAST */ + { + bAckRequired = FALSE; + pHeader_802_11->Duration = 0; + } + else + { + bAckRequired = TRUE; + pHeader_802_11->Duration = RTMPCalcDuration(pAd, MlmeRate, 14); + if (pHeader_802_11->FC.SubType == SUBTYPE_PROBE_RSP) + { + bInsertTimestamp = TRUE; +#ifdef CONFIG_AP_SUPPORT +#ifdef SPECIFIC_TX_POWER_SUPPORT + /* Find which MBSSID to be send this probeRsp */ + UINT32 apidx = get_apidx_by_addr(pAd, pHeader_802_11->Addr2); + + if (!(apidx >= pAd->ApCfg.BssidNum) && + (pAd->ApCfg.MBSSID[apidx].TxPwrAdj != -1) && + (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_CCK) && + (pAd->CommonCfg.MlmeTransmit.field.MCS == RATE_1)) + { + TxPwrAdj = pAd->ApCfg.MBSSID[apidx].TxPwrAdj; + } +#endif /* SPECIFIC_TX_POWER_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + } + } + } + + pHeader_802_11->Sequence = pAd->Sequence++; + if (pAd->Sequence > 0xfff) + pAd->Sequence = 0; + + /* Before radar detection done, mgmt frame can not be sent but probe req*/ + /* Because we need to use probe req to trigger driver to send probe req in passive scan*/ + if ((pHeader_802_11->FC.SubType != SUBTYPE_PROBE_REQ) + && (pAd->CommonCfg.bIEEE80211H == 1) + && (pAd->Dot11_H.RDMode != RD_NORMAL_MODE)) + { + DBGPRINT(RT_DEBUG_ERROR,("MlmeHardTransmit --> radar detect not in normal mode !!!\n")); + return (NDIS_STATUS_FAILURE); + } + + /* + 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 + */ + +/* management frame doesn't need encryption. so use RESERVED_WCID no matter u are sending to specific wcid or not */ + /* Only beacon use Nseq=TRUE. So here we use Nseq=FALSE.*/ + if (pMacEntry == NULL) + { + wcid = RESERVED_WCID; + if (IS_MT7603(pAd) || IS_MT7628(pAd)) + { + wcid = 0; + if(prot) + { + MAC_TABLE_ENTRY *pEntry = NULL; + + pEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); +#ifdef MAC_REPEATER_SUPPORT + if (pEntry != NULL && pAd->ApCfg.bMACRepeaterEn && IS_ENTRY_APCLI(pEntry)) + { + REPEATER_CLIENT_ENTRY *pReptEntry = NULL; + UCHAR MacTabWCID=0; + UCHAR isLinkValid; + + pReptEntry = RTMPLookupRepeaterCliEntry(pAd, FALSE, pHeader_802_11->Addr2, TRUE, &isLinkValid); + if (pReptEntry && pReptEntry->CliValid) + { + MacTabWCID = pReptEntry->MacTabWCID; + pEntry = &pAd->MacTab.Content[MacTabWCID]; + } + + } +#endif + + if (pEntry) + wcid = pEntry->Aid; + } + } + tx_rate = (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS; + transmit = &pAd->CommonCfg.MlmeTransmit; + } + else + { + wcid = pMacEntry->Aid; + tx_rate = (UCHAR)pMacEntry->MaxHTPhyMode.field.MCS; + transmit = &pMacEntry->MaxHTPhyMode; + } + + NdisZeroMemory((UCHAR *)&mac_info, sizeof(mac_info)); + + if(prot) + mac_info.prot = prot; + + if (prot == 2) + mac_info.bss_idx = apidx; + + mac_info.FRAG = FALSE; + + mac_info.CFACK = FALSE; + mac_info.InsTimestamp = bInsertTimestamp; + mac_info.AMPDU = FALSE; + + mac_info.BM = IS_BM_MAC_ADDR(pHeader_802_11->Addr1); + mac_info.Ack = bAckRequired; + mac_info.NSeq = FALSE; + mac_info.BASize = 0; + mac_info.WCID = wcid; + mac_info.TID = 0; +#ifdef MT_MAC + mac_info.q_idx = QueIdx; +#endif /* MT_MAC */ + +#if defined(MT7603) || defined(MT7628) + mac_info.Length = (SrcBufLen - tx_hw_hdr_len); + if (pHeader_802_11->FC.Type == FC_TYPE_MGMT) { + mac_info.hdr_len = 24; + if (pHeader_802_11->FC.Order == 1) + mac_info.hdr_len += 4; + if (pHeader_802_11->FC.SubType == SUBTYPE_BEACON) + mac_info.q_idx = Q_IDX_BCN; + mac_info.PID = PID_MGMT; + } else if (pHeader_802_11->FC.Type == FC_TYPE_DATA) { + switch (pHeader_802_11->FC.SubType) { + case SUBTYPE_DATA_NULL: + mac_info.hdr_len = 24; + tx_rate = (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS; + transmit = &pAd->CommonCfg.MlmeTransmit; + break; + case SUBTYPE_QOS_NULL: + mac_info.hdr_len = 26; + tx_rate = (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS; + transmit = &pAd->CommonCfg.MlmeTransmit; + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s(): FIXME!!!Unexpected frame(Type=%d, SubType=%d) send to MgmtRing, need to assign the length!\n", + __FUNCTION__, pHeader_802_11->FC.Type, pHeader_802_11->FC.SubType)); + hex_dump("DataFrame", frm_buf, frm_len); + break; + } + mac_info.WCID = wcid; + if (pMacEntry && pAd->MacTab.tr_entry[wcid].PsDeQWaitCnt) + mac_info.PID = PID_PS_DATA; + else + mac_info.PID = PID_MGMT; + } else if (pHeader_802_11->FC.Type == FC_TYPE_CNTL) { + switch (pHeader_802_11->FC.SubType) { + case SUBTYPE_BLOCK_ACK_REQ: + mac_info.PID = PID_CTL_BAR; + mac_info.hdr_len = 16; + mac_info.SpeEn = 0; + mac_info.TID = pBar->BarControl.TID; + if (pAd->CommonCfg.Channel > 14) + { /* 2.4G */ + TransmitSetting.field.MODE = MODE_OFDM; + } + else + { /* 5G */ +#ifdef GN_ONLY_AP_SUPPORT + if((pAd->OpMode == OPMODE_STA) || (pAd->OpMode == OPMODE_AP)) { + if(BMode || !bExcludeBRate) + TransmitSetting.field.MODE = MODE_CCK; + else + TransmitSetting.field.MODE = MODE_OFDM; + } + else +#endif + TransmitSetting.field.MODE = MODE_CCK; + } + TransmitSetting.field.BW = BW_20; + TransmitSetting.field.STBC = 0; + TransmitSetting.field.ShortGI = 0; + TransmitSetting.field.MCS = 0; + TransmitSetting.field.ldpc = 0; + transmit = &TransmitSetting; + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s(): FIXME!!!Unexpected frame(Type=%d, SubType=%d) send to MgmtRing, need to assign the length!\n", + __FUNCTION__, pHeader_802_11->FC.Type, pHeader_802_11->FC.SubType)); + hex_dump("Control Frame", frm_buf, frm_len); + break; + } + } +#else + mac_info.Length = (SrcBufLen - TXINFO_SIZE - TXWISize - TSO_SIZE); + mac_info.PID = PID_MGMT; +#endif /* defined(MT7603) || defined(MT7628) */ + + mac_info.TxRate = tx_rate; + mac_info.Txopmode = IFS_BACKOFF; + mac_info.SpeEn = 1; + mac_info.Preamble = LONG_PREAMBLE; + + /* PCI use Miniport to send NULL frame and need to add NULL frame TxS control here to enter PSM */ + if ((pHeader_802_11->FC.Type == FC_TYPE_MGMT) && + ((pHeader_802_11->FC.SubType == SUBTYPE_ASSOC_RSP) || (pHeader_802_11->FC.SubType == SUBTYPE_REASSOC_RSP))) { + MAC_TABLE_ENTRY *pEntry = NULL; + mac_info.PID = PID_MGMT_ASSOC_RSP; + DBGPRINT(RT_DEBUG_TRACE,("===[%s] ASSOC_RSP(pci):addr1 %02x:%02x:%02x:%02x:%02x:%02x addr2 %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, PRINT_MAC(pHeader_802_11->Addr1), PRINT_MAC(pHeader_802_11->Addr2))); + pEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); + if(pEntry) { + DBGPRINT(RT_DEBUG_TRACE,("===[%s] pEntry->wcid = %d \n", __FUNCTION__, pEntry->wcid)); + mac_info.WCID = pEntry->wcid; + } else { + DBGPRINT(RT_DEBUG_TRACE,("===[%s] ERROR: pEntry == NULL \n", __FUNCTION__)); + } + } + + write_tmac_info(pAd, tmac_info, &mac_info, transmit); + +#ifdef SPECIFIC_TX_POWER_SUPPORT + if (IS_RT6352(pAd) && (pMacEntry == NULL)) { + TXWI_STRUC *pFirstTxWI = (TXWI_STRUC *)tmac_info; + + pFirstTxWI->TxPwrAdj = TxPwrAdj; + } +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + + pAd->TxRing[QueIdx].Cell[SwIdx].pNdisPacket = pPacket; + pAd->TxRing[QueIdx].Cell[SwIdx].pNextNdisPacket = NULL; + +#ifdef RT_BIG_ENDIAN +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + MTMacInfoEndianChange(pAd, tmac_info, TYPE_TMACINFO, sizeof(TMAC_TXD_L)); +#endif + +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (pAd->chipCap.hif_type == HIF_RTMP || pAd->chipCap.hif_type == HIF_RLT) + RTMPWIEndianChange(pAd, tmac_info, TYPE_TXWI); +#endif +#endif + +#ifdef VHT_TXBF_SUPPORT + if (pHeader_802_11->FC.Type == FC_TYPE_CNTL && pHeader_802_11->FC.SubType == SUBTYPE_VHT_NDPA) + { + DBGPRINT(RT_DEBUG_OFF, ("%s(): Send VhtNDPA to peer(wcid=%d, pMacEntry=%p) with dataRate(PhyMode:%s, BW:%sHz, %dSS, MCS%d)\n", + __FUNCTION__, wcid, pMacEntry, get_phymode_str(transmit->field.MODE), + get_bw_str(transmit->field.BW), + (transmit->field.MCS>>4) + 1, (transmit->field.MCS & 0xf))); + + hex_dump("VHT NDPA frame raw data", pSrcBufVA, SrcBufLen); + } +#endif /* VHT_TXBF_SUPPORT */ + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, (PUCHAR)pHeader_802_11, DIR_WRITE, FALSE); +#endif + + pAd->TxRing[QueIdx].Cell[SwIdx].PacketPa = PCI_MAP_SINGLE(pAd, frm_buf, frm_len, 0, RTMP_PCI_DMA_TODEVICE); + + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 0; + pTxD->SDLen0 = frm_len; + pTxD->SDLen1 = 0; + pTxD->SDPtr0 = pAd->TxRing[QueIdx].Cell[SwIdx].PacketPa; + pTxD->Burst = 0; + +#if defined(RTMP_MAC) || defined(RLT_MAC) + ral_write_txd(pAd, pTxD, NULL, TRUE, FIFO_EDCA); +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + +#ifdef MT_MAC + mt_write_txd(pAd, pTxD); +#endif /* MT_MAC */ + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif + + pAd->RalinkCounters.KickTxCount++; + pAd->RalinkCounters.OneSecTxDoneCount++; + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(SrcBufPA, SrcBufLen); + RTMP_DCACHE_FLUSH(pAd->TxRing[QueIdx].Cell[SwIdx].AllocPa, TXD_SIZE); + + /* Increase TX_CTX_IDX, but write to register later.*/ + INC_RING_INDEX(pAd->TxRing[QueIdx].TxCpuIdx, TX_RING_SIZE); + + RTMP_IO_WRITE32(pAd, pAd->TxRing[QueIdx].hw_cidx_addr, pAd->TxRing[QueIdx].TxCpuIdx); + + return NDIS_STATUS_SUCCESS; +} + + +#ifdef CONFIG_ANDES_SUPPORT +BOOLEAN RxRing1DoneInterruptHandle(RTMP_ADAPTER *pAd) +{ + UINT32 RxProcessed, RxPending; + BOOLEAN bReschedule = FALSE; + //RXD_STRUC *pRxD = NULL; + //RXINFO_STRUC *pRxInfo = NULL; + //UCHAR *pData = NULL; + PNDIS_PACKET pRxPacket = NULL; + //PHEADER_802_11 pHeader = NULL; + RX_BLK rxblk, *pRxBlk = NULL; + //UINT8 RXWISize = pAd->chipCap.RXWISize; +#ifdef RLT_MAC + RXFCE_INFO *pFceInfo; +#endif /* RLT_MAC */ + + 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)//Carter commented. otherwise TXS might be droped. + )) || + !RTMP_TEST_FLAG(pAd,fRTMP_ADAPTER_START_UP)) + { + break; + } + +#ifdef RTMP_MAC_PCI + //if (RxProcessed++ > MAX_RX_PROCESS_CNT) + if (RxProcessed++ > 32) + { + bReschedule = TRUE; + break; + } +#endif /* RTMP_MAC_PCI */ + + /* + 1. allocate a new data packet into rx ring to replace received packet + then processing the received packet + 2. the callee must take charge of release of packet + 3. As far as driver is concerned, the rx packet must + a. be indicated to upper layer or + b. be released if it is discarded + */ + + pRxBlk = &rxblk; + + pRxPacket = GetPacketFromRxRing(pAd, pRxBlk, &bReschedule, &RxPending, 1); + if (pRxPacket == NULL) + break; + + /* get rx descriptor and data buffer */ + //pRxD = (RXD_STRUC *)&pRxBlk->hw_rx_info[0]; + //pRxInfo = rxblk.pRxInfo; + //pData = GET_OS_PKT_DATAPTR(pRxPacket); + //pHeader = (PHEADER_802_11)(pData + RXWISize); + +#ifdef RLT_MAC + pFceInfo = rxblk.pRxFceInfo; + if (pFceInfo->info_type == CMD_PACKET) + { + DBGPRINT(RT_DEBUG_INFO, ("%s: Receive command packet.\n", __FUNCTION__)); + pci_rx_cmd_msg_complete(pAd, pFceInfo); + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + continue; + } +#endif /* RLT_MAC */ + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + if ((rxblk.DataSize == 0) && (pRxPacket)) { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + continue; + } + } +#endif /* MT_MAC */ + } + return bReschedule; +} + + +VOID RTMPHandleTxRing8DmaDoneInterrupt(RTMP_ADAPTER *pAd) +{ + TXD_STRUC *pTxD; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR hw_hdr_info[TXD_SIZE]; +#endif + PNDIS_PACKET pPacket; +/* int i;*/ + UCHAR FREE = 0; + RTMP_CTRL_RING *pCtrlRing = &pAd->CtrlRing; + //UINT8 TXWISize = pAd->chipCap.TXWISize; + + NdisAcquireSpinLock(&pAd->CtrlRingLock); + + RTMP_IO_READ32(pAd, pCtrlRing->hw_didx_addr, &pCtrlRing->TxDmaIdx); + while (pCtrlRing->TxSwFreeIdx!= pCtrlRing->TxDmaIdx) + { + FREE++; +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *) (pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx].AllocVa); + NdisMoveMemory(&hw_hdr_info[0], pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&hw_hdr_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_STRUC *) (pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx].AllocVa); +#endif + + pPacket = pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx].pNdisPacket; + + if (pPacket == NULL) + { + INC_RING_INDEX(pCtrlRing->TxSwFreeIdx, MGMT_RING_SIZE); + continue; + } + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RTMPFreeNdisPacket(pAd, pPacket); + } + + pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx].pNdisPacket = NULL; + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx].AllocPa, TXD_SIZE); + + INC_RING_INDEX(pCtrlRing->TxSwFreeIdx, MGMT_RING_SIZE); + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD); +#endif + } + + NdisReleaseSpinLock(&pAd->CtrlRingLock); +} +#endif /* CONFIG_ANDES_SUPPORT */ + + +#ifdef MT_MAC +VOID RTMPHandleBcnDmaDoneInterrupt(RTMP_ADAPTER *pAd) +{ + TXD_STRUC *pTxD; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR hw_hdr_info[TXD_SIZE]; +#endif + PNDIS_PACKET pPacket; + RTMP_BCN_RING *pBcnRing = &pAd->BcnRing; + UCHAR *tmac_info = NULL; + +#ifdef CONFIG_AP_SUPPORT + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[0]; + UCHAR bss_idx = 0; + UINT32 Lowpart, Highpart; +DBGPRINT(RT_DEBUG_FPGA, ("-->%s():bcn_state=%d\n", __FUNCTION__, pAd->ApCfg.MBSSID[0].bcn_buf.bcn_state)); +#endif /* CONFIG_AP_SUPPORT */ + + RTMP_SEM_LOCK(&pAd->BcnRingLock); + + RTMP_IO_READ32(pAd, pBcnRing->hw_didx_addr, &pBcnRing->TxDmaIdx); + while (pBcnRing->TxSwFreeIdx!= pBcnRing->TxDmaIdx) + { +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *) (pBcnRing->Cell[pBcnRing->TxSwFreeIdx].AllocVa); + NdisMoveMemory(&hw_hdr_info[0], pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&hw_hdr_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_STRUC *) (pBcnRing->Cell[pBcnRing->TxSwFreeIdx].AllocVa); +#endif + + pPacket = pBcnRing->Cell[pBcnRing->TxSwFreeIdx].pNdisPacket; + if (pPacket == NULL) + { + INC_RING_INDEX(pBcnRing->TxSwFreeIdx, BCN_RING_SIZE); + continue; + } + + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + tmac_info = GET_OS_PKT_DATAPTR(pPacket); + pBcnRing->Cell[pBcnRing->TxSwFreeIdx].pNdisPacket = NULL; + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pBcnRing->Cell[pBcnRing->TxSwFreeIdx].AllocPa, TXD_SIZE); + +#ifdef CONFIG_AP_SUPPORT//Carter commented for update beacon by TxS, instead of dma_done + // TODO: shiang-MT7603, big endian!! + if (tmac_info) { +//+++Add by Carter for MT7603 + TMAC_TXD_1 *txd_1; +#ifdef RT_BIG_ENDIAN + TMAC_TXD_1 temp_txd1; +#endif + +//---Add by Carter for MT7603 + //BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[0]; + +//+++Add by Carter for MT7603 + txd_1 = (TMAC_TXD_1 *)(tmac_info + sizeof(TMAC_TXD_0)); +#ifdef RT_BIG_ENDIAN + NdisCopyMemory(&temp_txd1, txd_1, sizeof(TMAC_TXD_1)); + *(((UINT32 *)&temp_txd1)) = SWAP32(*(((UINT32 *)&temp_txd1))); + txd_1 = &temp_txd1; +#endif /* RT_BIG_ENDIAN */ + + if (txd_1->own_mac > 0x10 && txd_1->own_mac <= 0x1f) + bss_idx = txd_1->own_mac & 0x0f; + else if (txd_1->own_mac == 0) + bss_idx = txd_1->own_mac; + + pMbss = &pAd->ApCfg.MBSSID[bss_idx]; +//---Add by Carter for MT7603 + + if (pMbss->bcn_buf.bcn_state == BCN_TX_WRITE_TO_DMA) + pMbss->bcn_buf.bcn_state = BCN_TX_DMA_DONE; + + AsicGetTsfTime(pAd, &Highpart, &Lowpart); + pMbss->BcnDmaDoneTime[pMbss->timer_loop] = Lowpart;//update TSF time to corresponding field. + + DBGPRINT(RT_DEBUG_INFO, ("%s():change state as idle\n", __FUNCTION__)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Err, cannot found tmac_info!\n", __FUNCTION__)); + } +#endif /* CONFIG_AP_SUPPORT */ + + INC_RING_INDEX(pBcnRing->TxSwFreeIdx, BCN_RING_SIZE); + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD); +#endif + + } + + RTMP_SEM_UNLOCK(&pAd->BcnRingLock); + + +} +#endif /* MT_MAC */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_data_sdio.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_data_sdio.c new file mode 100644 index 000000000..c4d8a2717 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_data_sdio.c @@ -0,0 +1,147 @@ +/* + *************************************************************************** + * 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: + cmm_data_sdio.c +*/ + + +#include "rt_config.h" +#include "rtmp.h" + + + +USHORT MtSDIO_WriteSubTxResource(struct _RTMP_ADAPTER *pAd, struct _TX_BLK *pTxBlk, BOOLEAN bIsLast, USHORT *freeCnt) +{ + + return 0; + +} + +USHORT MtSDIO_WriteFragTxResource( + RTMP_ADAPTER *pAd, + struct _TX_BLK *pTxBlk, + UCHAR fragNum, + USHORT *freeCnt) +{ + return(0); +} + + +USHORT MtSDIO_WriteSingleTxResource( + RTMP_ADAPTER *pAd, + struct _TX_BLK *pTxBlk, + BOOLEAN bIsLast, + USHORT *freeCnt) +{ + +} + + +USHORT MtSDIO_WriteMultiTxResource( + RTMP_ADAPTER *pAd, + struct _TX_BLK *pTxBlk, + UCHAR frmNum, + USHORT *freeCnt) +{ + NDIS_STATUS Status = 0; + + return(Status); +} + + +VOID MtSDIO_FinalWriteTxResource( + RTMP_ADAPTER *pAd, + struct _TX_BLK *pTxBlk, + USHORT totalMPDUSize, + USHORT TxIdx) +{ + +} + + +VOID MtSDIODataLastTxIdx( + RTMP_ADAPTER *pAd, + UCHAR QueIdx, + USHORT TxIdx) +{ + /* DO nothing for USB.*/ +} + + +VOID MtSDIODataKickOut( + RTMP_ADAPTER *pAd, + struct _TX_BLK *pTxBlk, + UCHAR QueIdx) +{ +} + + +int MtSDIOMgmtKickOut( + RTMP_ADAPTER *pAd, + UCHAR QueIdx, + PNDIS_PACKET pPacket, + UCHAR *pSrcBufVA, + UINT SrcBufLen) +{ + return 0; +} + + +PNDIS_PACKET GetPacketFromRxRing( + RTMP_ADAPTER *pAd, + RX_BLK *pRxBlk, + BOOLEAN *pbReschedule, + UINT32 *pRxPending, + UCHAR RxRingNo) + +{ + UINT8 RXWISize = pAd->chipCap.RXWISize; + UINT8 rx_hw_hdr_len = pAd->chipCap.RXWISize; + PNDIS_PACKET pRxPacket = pAd->SDIORxPacket; + PUCHAR buf = GET_OS_PKT_DATAPTR(pRxPacket); + UINT32 len=GET_OS_PKT_LEN(pRxPacket); + UINT32 i; + + pRxBlk->Flags = 0; + DBGPRINT(RT_DEBUG_TRACE, ("%s===========start\n",__FUNCTION__)); + if(!pRxPacket){ + DBGPRINT(RT_DEBUG_OFF, ("%s=====return NULL !!!!!\n",__FUNCTION__)); + return NULL; + } + + for(i=0;iDataSize = 0; + } + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_CMD_RSP)) + { + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + return NULL; + } + + pRxBlk->pRxPacket = pRxPacket; + pRxBlk->pData = (UCHAR *)GET_OS_PKT_DATAPTR(pRxPacket); + pRxBlk->pHeader = (HEADER_802_11 *)(pRxBlk->pData); + + return pRxPacket; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_dfs.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_dfs.c new file mode 100644 index 000000000..c51c802d9 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_dfs.c @@ -0,0 +1,2677 @@ +/* + *************************************************************************** + * 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 + +NewDFSValidRadar NewDFSValidTable[] = +{ + /* FCC-1 && (Japan W53 Radar 1 / W56 Radar 2)*/ + { + (NEW_DFS_FCC | NEW_DFS_JAP | NEW_DFS_JAP_W53), + 7, + 10, 1000, + 0, + 4, + 0, 0, + 28570 - 70, + 150 + }, + /* FCC-2*/ + { + (NEW_DFS_FCC | NEW_DFS_JAP), + 7, + 13, 1000, + 0, + 1, + 3000, 4600 - 20, + 0, + 25 + }, + /* FCC-3 & FCC-4*/ + { + (NEW_DFS_FCC | NEW_DFS_JAP), + 7, + /*120, 200, FCC-3 */ + /*220, 400, FCC-4*/ + 100, 1500, + 0, + 1, + 4000, 10000 - 40, + 0, + 60 + }, + /* FCC-6*/ + { + (NEW_DFS_FCC | NEW_DFS_JAP), + 7, + 12, 1000, + 0, + 1, + 0, 0, + 6660-10, + 35 + }, + /* Japan W53 Radar 2*/ + { + NEW_DFS_JAP_W53, + 7, + 40, 1000, + 0, + 1, + 0, 0, + 76923 - 30, + 180 + }, + /* Japan W56 Radar 1*/ + { + NEW_DFS_JAP, + 7, + 5, 500, + 0, + 2, + 0, 0, + 27777 - 30, + 70 + }, + /* Japan W56 Radar 3*/ + { + NEW_DFS_JAP, + 7, + 30, 1000, + 0, + 1, + 0, 0, + 80000 - 50, + 200 + }, + +/* CE Staggered radar*/ + + { + /* EN-1*/ + /* width 0.8 - 5 us*/ + /* PRF 200 - 1000 Hz*/ + /* PRI 5000 - 1000 us (T: 20000 - 100000)*/ + /* */ + NEW_DFS_EU, + 0xf, + 10, 1000, + 0, + 1, + 20000-15, 100000-70, + 0, + 120 + }, + /* EN-2*/ + /* width 0.8 - 15 us*/ + /* PRF 200 - 1600 Hz*/ + /* PRI 5000 - 625 us (T: 12500 - 100000)*/ + { + NEW_DFS_EU, + 0xf, + 10, 2000, + 0, + 1, + 12500 - 10, 100000 - 70, + 0, + 120 + }, + + /* EN-3*/ + /* width 0.8 - 15 us*/ + /* PRF 2300 - 4000 Hz*/ + /* PRI 434 - 250 us (T: 5000 - 8695)*/ + { + NEW_DFS_EU, + 0xf, + 21, 2000, + 0, + 1, + 5000 - 4, 8695 - 7, + 0, + 50 + }, + /* EN-4*/ + /* width 20 - 30 us*/ + /* PRF 2000 - 4000 Hz*/ + /* PRI 500 - 250 us (T: 5000 - 10000)*/ + /* Note : with Chirp Modulation +- 2,5Mhz*/ + { + NEW_DFS_EU, + 0xf, + 380, 3000, + 0, + 4, + 5000 - 4, 10000 - 8, + 0, + 60 + }, + /* EN-5*/ + /* width 0.8 - 2 us*/ + /* PRF 300 - 400 Hz*/ + /* PRI 3333 - 2500 us (T: 50000 - 66666)*/ + /* Staggered PRF, 20 - 50 pps*/ + { + NEW_DFS_EU, + 0xf, + 10, 800, + 0, + 1, + 50000 - 35, 66666 + 50, + 0, + 30 + }, + /* EN-6*/ + /* width 0.8 - 2 us*/ + /* PRF 400 - 1200 Hz*/ + /* PRI 2500 - 833 us (T: 16666 - 50000)*/ + /* Staggered PRF, 80 - 400 pps*/ + { + NEW_DFS_EU, + 0xf, + 10, 800, + 0, + 1, + 16666 - 13, 50000 + 35, + 0, + 30 + }, + + { + NEW_DFS_END, + 0, + 0, 0, + 0, + 0, + 0, 0, + 0, + 0, + }, +}; + +static NewDFSTable NewDFSTable1[] = +{ + { + /* ch, mode(0~7), M(~511), el, eh(~4095), wl, wh(~4095), err_w, tl, th, err_t, bl, bh, ee, pj*/ + NEW_DFS_FCC, + { + {0, 0, 10, 8, 16, 6, 2000, 5, 2900, 29000, 5, 0, 0, 0x1000000, 0}, + {1, 0, 70, 42, 126, 20, 5000, 5, 2900, 29000, 10, 0, 0, 0x1000000, 0}, + {2, 0, 100, 42, 160, 20, 5000, 25, 2900, 10100, 20, 0, 0, 0x1000000, 0}, + {3, 2, 200, 20, 150, 900, 2200, 50, 1000, 999999999, 200, 0, 999999999, 0x10000000, 0}, + } + }, + + { + NEW_DFS_EU, + { + {0, 0, 10, 10, 18, 4, 4095, 5, 7800, 101000, 5, 0, 0, 0x1000000, 0}, + {1, 0, 70, 42, 90, 20, 4095, 3, 4900, 101000, 10, 0, 0, 0x1000000, 0}, + {2, 0, 100, 42, 160, 20, 4095, 5, 4900, 101000, 20, 0, 0, 0x1000000, 0}, + {3, 3, 200, 20, 150, 200, 4095, 100, 4900, 11000, 200, 0, 0, 0x1000000, 0}, + {4, 8, 0, 8, 17, 7, 70, 2, 32500, 200500, 10, 0, 0, 0x1000000, 0}, + /*{5, 1, 0, 12, 16, 8, 700, 5, 33000, 135000, 100, 0, 0, 0x1000000, 0},*/ + } + }, + + { + NEW_DFS_JAP, + { + {0, 0, 10, 8, 16, 4, 2000, 5, 2900, 85000, 5, 0, 0, 0x1000000, 0}, + {1, 0, 70, 48, 126, 20, 5000, 5, 2900, 85000, 10, 0, 0, 0x1000000, 0}, + {2, 0, 100, 48, 160, 20, 5000, 25, 2900, 85000, 20, 0, 0, 0x1000000, 0}, + {3, 2, 200, 20, 150, 900, 2200, 50, 1000, 999999999, 200, 0, 999999999, 0x10000000, 0}, + } + }, + + { + NEW_DFS_JAP_W53, + { + {0, 0, 10, 8, 16, 8, 2000, 5, 28000, 85000, 10, 0x1000000, 0}, + {1, 0, 32, 24, 64, 20, 2000, 5, 28000, 85000, 10, 0x1000000, 0}, + {2, 0, 100, 42, 160, 20, 2000, 25, 28000, 85000, 10, 0x1000000, 0}, + /*{3, 2, 200, 20, 150, 300, 2000, 50, 15000, 45000, 200},*/ + } + }, +}; + +/* for MT76x0 */ +static NewDFSTable NewDFSTable2[] = +{ + { + /* (0~9) (~511) (~4095) (~4095) */ + /* ch, mode M EL, EH WL WH ErrW TL TH Err_T BL BH EE PJ*/ + NEW_DFS_FCC, + { + {0, 0, 8, 2, 7, 106, 420, 30, 2900, 100096, 30, 0, 2147483647, 0x1400000, 0x12ee}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 3, 20, 2, 18, 106, 420, 32, 2900, 100096, 32, 0, 2147483647, 0xe4e1c00, 0x12ee}, + {3, 2, 60, 15, 48, 900, 2048, 32, 2900, 100096, 32, 0, 2147483647, 0x0e4e1c00, 0x12ee}, + } + }, + + { + /* (0~9) (~511) (~4095) (~4095) */ + /* ch, mode M EL, EH WL WH ErrW TL TH Err_T BL BH EE PJ*/ + NEW_DFS_EU, + { + {0, 0, 8, 2, 7, 106, 420, 30, 2900, 100096, 30, 0, 2147483647, 0x1400000, 0x12ee}, + {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {2, 3, 20, 2, 18, 106, 2048, 32, 2900, 100096, 32, 0, 2147483647, 0xe4e1c00, 0x12ee}, + {3, 8, 8, 2, 7, 106, 200, 32, 2900, 296704, 32, 0, 2147483647, 0x1400000, 0x15ee}, + } + }, +}; + +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 PRADAR_DETECT_STRUCT pRadarDetect, + 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); +} + + +static inline VOID DfsHwDetectionStatusGet(PRTMP_ADAPTER pAd, + PUINT8 pDetectedChannels) +{ + RTMP_BBP_IO_READ32(pAd, DFS_R1, pDetectedChannels); +} + +static inline VOID DfsResetHwDetectionStatus(PRTMP_ADAPTER pAd) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + + RTMP_BBP_IO_WRITE32(pAd, DFS_R1, pRadarDetect->EnabledChMask); +} + +static inline VOID DfsCaptureModeControl(PRTMP_ADAPTER pAd, + BOOLEAN bEnable, + BOOLEAN bPowerUp, + BOOLEAN bCapLastEvents) +{ + UINT8 bbp_val = 0; + + bbp_val = (bEnable == TRUE) | + ((bPowerUp == TRUE) <<1) | + ((bCapLastEvents == TRUE) << 2); + + RTMP_BBP_IO_WRITE32(pAd, DFS_R36, (UINT32) bbp_val); +} + +static inline VOID DfsDetectionEnable(PRTMP_ADAPTER pAd) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + + RTMP_BBP_IO_WRITE32(pAd, DFS_R0, (pRadarDetect->EnabledChMask << 16)); +} + +static inline VOID DfsDetectionDisable(PRTMP_ADAPTER pAd) +{ + RTMP_BBP_IO_WRITE32(pAd, DFS_R0, 0); +} + +static inline VOID StagerRadarGetPRIs(PRTMP_ADAPTER pAd, + UINT8 dfs_channel, + PUINT32 pT1, + PUINT32 pT2, + PUINT32 pT3) +{ + UINT32 T_all = 0; + UINT32 bbp_val = 0; + PDFS_PROGRAM_PARAM pDfsProgramParam = \ + &pAd->CommonCfg.RadarDetect.DfsProgramParam; + + /* select channel */ + bbp_val = (pDfsProgramParam->ChEnable << 16) | dfs_channel; + RTMP_BBP_IO_WRITE32(pAd, DFS_R0, bbp_val); + + RTMP_BBP_IO_READ32(pAd, DFS_R19, &T_all); + RTMP_BBP_IO_READ32(pAd, DFS_R22, pT1); + RTMP_BBP_IO_READ32(pAd, DFS_R25, pT2); + + *pT3 = T_all - *pT1 -*pT2; +} + +static inline VOID DfsHwDetectionGetPulseInfo(PRTMP_ADAPTER pAd, + UINT8 ChannelIndex, + PUINT32 pPeriod, + PUINT32 pWidth1, + PUINT32 pWidth2, + PUINT32 pBurst) +{ + UINT32 bbp_val = 0; + PDFS_PROGRAM_PARAM pDfsProgramParam = \ + &pAd->CommonCfg.RadarDetect.DfsProgramParam; + + *pPeriod = *pWidth1 = *pWidth2 = *pBurst = 0; + + /* select channel */ + bbp_val = (pDfsProgramParam->ChEnable << 16) | ChannelIndex; + RTMP_BBP_IO_WRITE32(pAd, DFS_R0, bbp_val); + + /* Read reports - Period */ + RTMP_BBP_IO_READ32(pAd, DFS_R19, pPeriod); + + /* Read reports - Width */ + RTMP_BBP_IO_READ32(pAd, DFS_R20, pWidth1); + RTMP_BBP_IO_READ32(pAd, DFS_R23, pWidth2); + + /* Read reports - Burst Number */ + RTMP_BBP_IO_READ32(pAd, DFS_R22, pBurst); +} + +static inline VOID DfsProgramBbpValues(PRTMP_ADAPTER pAd, + pNewDFSTable pDfsTable) +{ + UINT8 idx, DfsInputControl; + UINT8 DfsEngineNum = pAd->chipCap.DfsEngineNum; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam; + + DfsInputControl = pDfsProgramParam->Symmetric_Round << 4; + + /* Full 40Mhz*/ + if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + { + /* BW 40*/ + DfsInputControl |= 0x80; + } + + /* Delta Delay*/ + DfsInputControl |= (pDfsProgramParam->DeltaDelay & 0xf); + RTMP_DFS_IO_WRITE8(pAd, 0x3, DfsInputControl); + DBGPRINT(RT_DEBUG_TRACE,("R3 = 0x%x\n", DfsInputControl)); + + /* VGA Mask*/ + RTMP_DFS_IO_WRITE8(pAd, 0x4, pDfsProgramParam->VGA_Mask); + DBGPRINT(RT_DEBUG_TRACE,("VGA_Mask = 0x%x\n", pDfsProgramParam->VGA_Mask)); + + /* packet end Mask*/ + RTMP_DFS_IO_WRITE8(pAd, 0x5, pDfsProgramParam->Packet_End_Mask); + DBGPRINT(RT_DEBUG_TRACE,("Packet_End_Mask = 0x%x\n", pDfsProgramParam->Packet_End_Mask)); + + /* Rx PE Mask*/ + RTMP_DFS_IO_WRITE8(pAd, 0x6, pDfsProgramParam->Rx_PE_Mask); + DBGPRINT(RT_DEBUG_TRACE,("Rx_PE_Mask = 0x%x\n", pDfsProgramParam->Rx_PE_Mask)); + + /* program each channel*/ + for (idx = 0; idx < DfsEngineNum; idx++) + { + /* select channel*/ + RTMP_DFS_IO_WRITE8(pAd, 0x0, idx); + + DBGPRINT(RT_DEBUG_TRACE, ("write DFS Channle[%d] configuration \n",idx)); + /* start programing*/ + + /* reg 0x10, Detection Mode[2:0]*/ + RTMP_DFS_IO_WRITE8(pAd, 0x10, (pDfsTable->entry[idx].mode & 0xf)); + + /* reg 0x11~0x12, M[7:0] & M[8]*/ + + if (pAd->chipCap.DfsEngineNum > 4 && + (idx==4 || idx==5)) + { + /* Ch 4 and Ch5 use indirect M which taking the M value of another channel (one of 0~3) */ + RTMP_DFS_IO_WRITE8(pAd, 0x12, ((pDfsTable->entry[idx].avgLen << 4) & 0x30)); + } + else + { + RTMP_DFS_IO_WRITE8(pAd, 0x11, (pDfsTable->entry[idx].avgLen & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x12, ((pDfsTable->entry[idx].avgLen >> 8) & 0x1)); + } + + /* reg 0x13~0x14, Energy Low[7:0] & Energy Low[11:8]*/ + RTMP_DFS_IO_WRITE8(pAd, 0x13, (pDfsTable->entry[idx].ELow & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x14, ((pDfsTable->entry[idx].ELow >> 8) & 0xf)); + + + /* reg 0x15~0x16, Energy High[7:0] & Energy High[11:8]*/ + RTMP_DFS_IO_WRITE8(pAd, 0x15, (pDfsTable->entry[idx].EHigh & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x16, ((pDfsTable->entry[idx].EHigh >> 8) & 0xf)); + + + /* reg 0x28~0x29, Width Low[7:0] & Width Low[11:8]*/ + RTMP_DFS_IO_WRITE8(pAd, 0x28, (pDfsTable->entry[idx].WLow & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x29, ((pDfsTable->entry[idx].WLow >> 8) & 0xf)); + + /* reg 0x2a~0x2b, Width High[7:0] & Width High[11:8]*/ + RTMP_DFS_IO_WRITE8(pAd, 0x2a, (pDfsTable->entry[idx].WHigh & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x2b, ((pDfsTable->entry[idx].WHigh >> 8) & 0xf)); + + /* reg 0x2c, Width Delta[7:0], (Width Measurement Uncertainty)*/ + RTMP_DFS_IO_WRITE8(pAd, 0x2c, (pDfsTable->entry[idx].EpsilonW & 0xff)); + + /* reg 0x17~0x1a, Period Low[7:0] & Period Low[15:8] & Period Low[23:16] & Period Low[31:24]*/ + RTMP_DFS_IO_WRITE8(pAd, 0x17, (pDfsTable->entry[idx].TLow & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x18, ((pDfsTable->entry[idx].TLow >> 8) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x19, ((pDfsTable->entry[idx].TLow >> 16) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x1a, ((pDfsTable->entry[idx].TLow >> 24) & 0xff)); + + /* reg 0x1b~0x1e, Period High[7:0] & Period High[15:8] & Period High[23:16] & Period High[31:24]*/ + RTMP_DFS_IO_WRITE8(pAd, 0x1b, (pDfsTable->entry[idx].THigh & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x1c, ((pDfsTable->entry[idx].THigh >> 8) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x1d, ((pDfsTable->entry[idx].THigh >> 16) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd, 0x1e, ((pDfsTable->entry[idx].THigh >> 24) & 0xff)); + + /* reg 0x27, Period Delt[7:0], (Period Measurement Uncertainty)*/ + RTMP_DFS_IO_WRITE8(pAd, 0x27, (pDfsTable->entry[idx].EpsilonT & 0xff)); + + if (pDfsProgramParam->RadarEventExpire[idx] != 0) + { + RTMP_DFS_IO_WRITE8(pAd,0x39, (pDfsTable->entry[idx].EventExpiration & 0xff)); + RTMP_DFS_IO_WRITE8(pAd,0x3a, ((pDfsTable->entry[idx].EventExpiration >> 8) & 0xff) ); + RTMP_DFS_IO_WRITE8(pAd,0x3b, ((pDfsTable->entry[idx].EventExpiration >> 16) & 0xff)); + RTMP_DFS_IO_WRITE8(pAd,0x3c, ((pDfsTable->entry[idx].EventExpiration >> 24) & 0xff)); + } + + } + + /* reset status */ + RTMP_DFS_IO_WRITE8(pAd, 0x2, pRadarDetect->EnabledChMask); + /* Enable detection*/ + RTMP_DFS_IO_WRITE8(pAd, 0x1, (pDfsProgramParam->ChEnable)); +} + +#ifdef RTMP_MAC_PCI +static VOID SwCheckDfsEvent( + IN PRTMP_ADAPTER pAd); +#endif /* RTMP_MAC_PCI */ + + +/* + ======================================================================== + Routine Description: + Radar wave detection. The API should be invoke each second. + + Arguments: + pAd - Adapter pointer + + Return Value: + None + + ======================================================================== +*/ +VOID ApRadarDetectPeriodic( + IN PRTMP_ADAPTER pAd) +{ + INT i; + + if (pAd->Dot11_H.RDMode == RD_NORMAL_MODE) + pAd->Dot11_H.InServiceMonitorCount++; + + for (i=0; iChannelListNum; i++) + { + if (pAd->ChannelList[i].RemainingTimeForUse > 0) + { + pAd->ChannelList[i].RemainingTimeForUse --; + if ((pAd->Mlme.PeriodicRound%5) == 0) + { + DBGPRINT(RT_DEBUG_INFO, ("RadarDetectPeriodic - ch=%d, RemainingTimeForUse=%d\n", + pAd->ChannelList[i].Channel, pAd->ChannelList[i].RemainingTimeForUse)); + } + } + } + /*radar detect*/ + if ((pAd->CommonCfg.Channel > 14) + && (pAd->CommonCfg.bIEEE80211H == 1) + && RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) + { + RadarDetectPeriodic(pAd); + } + return; +} + + +/* 0 = Switch Channel when Radar Hit (Normal mode) + 1 = Don't Switch Channel when Radar Hit */ +INT Set_RadarDebug_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + + pRadarDetect->McuRadarDebug = simple_strtol(arg, 0, 16); + + if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_SHOW_RAW_EVENT) + printk("Show raw data of the event buffer.\n"); + + if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_EVENT) + { + if (pRadarDetect->bDfsSwDisable == 1) + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Warning!! DfsSwDisable is 1\n", __FUNCTION__)); + printk("Show effective event\n"); + } + + if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_SILENCE) + printk("Silence\n"); + + if (pRadarDetect->McuRadarDebug & RADAR_DONT_SWITCH) + printk("Dont Switch Channel\n"); + + if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_DONT_CHECK_BUSY) + printk("Dont Check Channel Busy\n"); + + if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_DONT_CHECK_RSSI) + printk("Dont Check RSSI\n"); + + if (pRadarDetect->McuRadarDebug & RADAR_SIMULATE) + printk("Simulate a radar detection\n"); + + return TRUE; +} + +INT Set_ResetRadarHwDetect_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + DfsResetHwDetectionStatus(pAd); + return TRUE; +} + +INT Set_DfsSwDisable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + NewRadarDetectionStop(pAd); + return TRUE; +} + + +INT Set_RadarSetTbl1_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + PUCHAR p2 = arg; + ULONG idx, value; + PDFS_PROGRAM_PARAM pDfsProgramParam = &pAd->CommonCfg.RadarDetect.DfsProgramParam; + + while((*p2 != ':') && (*p2 != '\0')) + { + p2++; + } + + if (*p2 == ':') + { + A2Dec(idx, arg); + A2Dec(value, p2+ 1); + if (idx == 0) + { + pDfsProgramParam->DeltaDelay = value; + printk("Delta_Delay = %d\n", pDfsProgramParam->DeltaDelay); + } + else + modify_table1(pAd, idx, value); + + if (pAd->CommonCfg.RadarDetect.pDFSTable) + NewRadarDetectionProgram(pAd, pAd->CommonCfg.RadarDetect.pDFSTable); + else + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Table not initialized.\n", __FUNCTION__)); + } + else + printk("please enter iwpriv ra0 set RadarT1=xxx:yyy\n"); + + return TRUE; +} + +INT Set_RadarSetTbl2_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + PUCHAR p2 = arg; + ULONG idx, value; + + while((*p2 != ':') && (*p2 != '\0')) + { + p2++; + } + + if (*p2 == ':') + { + A2Dec(idx, arg); + A2Dec(value, p2+ 1); + modify_table2(pAd, idx, value); + } + else + printk("please enter iwpriv ra0 set RadarT2=xxx:yyy\n"); + + return TRUE; +} + +INT Set_PollTime_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + pRadarDetect->PollTime = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Set_PrintBusyIdle_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + pRadarDetect->print_ch_busy_sta = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Set_BusyIdleRatio_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + pRadarDetect->ch_busy_idle_ratio = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Set_DfsRssiHigh_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + pRadarDetect->DfsRssiHigh = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Set_DfsRssiLow_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + pRadarDetect->DfsRssiLow = simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Show_BlockCh_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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->use_tasklet = 1; + pRadarDetect->McuRadarDebug = 0; + pRadarDetect->radarDeclared = 0; + pDfsProgramParam->ChEnable = pRadarDetect->EnabledChMask; + + { + pDfsProgramParam->VGA_Mask = 45; + pDfsProgramParam->Packet_End_Mask = 45; + pDfsProgramParam->Rx_PE_Mask = 45; + pDfsProgramParam->DeltaDelay = 0x3; + pDfsProgramParam->Symmetric_Round = 1; + } + /* + s/w detection needs event buffer. + */ + if (pAd->chipCap.DfsEngineNum > 4) + pRadarDetect->bDfsSwDisable = TRUE; /* Default close s/w detection for new DFS*/ + + dfs_sw_init(pAd); +} + +void NewRadarDetectionStart(PRTMP_ADAPTER pAd) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + pNewDFSTable *ppDFSTable = &pRadarDetect->pDFSTable; + + pRadarDetect->bDfsInit = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("--->NewRadarDetectionStart()\n")); + + DFSInit(pAd); + + + RTMP_CHIP_RADAR_GLRT_COMPENSATE(pAd); + + if ((pAd->CommonCfg.RDDurRegion == CE) && RESTRICTION_BAND_1(pAd)) + pAd->Dot11_H.ChMovingTime = 605; + else + pAd->Dot11_H.ChMovingTime = 65; + + if (pAd->CommonCfg.RDDurRegion == FCC) + { + if (pRadarDetect->ch_busy_idle_ratio == 0) + pRadarDetect->ch_busy_idle_ratio = 2; + + *ppDFSTable = &NewDFSTable1[0]; + DBGPRINT(RT_DEBUG_TRACE,("DFS start, use FCC table\n")); + } + else if (pAd->CommonCfg.RDDurRegion == CE) + { + if (pRadarDetect->ch_busy_idle_ratio == 0) + pRadarDetect->ch_busy_idle_ratio = 3; + + *ppDFSTable = &NewDFSTable1[1]; + DBGPRINT(RT_DEBUG_TRACE,("DFS start, use CE table\n")); + } + else /* JAP*/ + { + if ((pAd->CommonCfg.Channel >= 52) && (pAd->CommonCfg.Channel <= 64)) + { + *ppDFSTable = &NewDFSTable1[3]; + + if (pRadarDetect->ch_busy_idle_ratio == 0) + pRadarDetect->ch_busy_idle_ratio = 3; + } + else + { + *ppDFSTable = &NewDFSTable1[2]; + + if (pRadarDetect->ch_busy_idle_ratio == 0) + pRadarDetect->ch_busy_idle_ratio = 2; + } + DBGPRINT(RT_DEBUG_TRACE,("DFS start, use JAP table\n")); + } + + + NewRadarDetectionProgram(pAd, (*ppDFSTable)); + +#ifdef RTMP_MAC_PCI + /* enable debug mode*/ + DfsCaptureModeControl(pAd, TRUE, TRUE, FALSE); + + RTMP_HW_TIMER_INT_SET(pAd, HW_TIMER_INTERVAL); /* 1ms Timer interrupt */ + RTMP_HW_TIMER_INT_ENABLE(pAd); +#endif /* RTMP_MAC_PCI */ + pRadarDetect->bDfsInit = TRUE; + DBGPRINT(RT_DEBUG_TRACE,("Poll Time=%d\n", pRadarDetect->PollTime)); +} + + +VOID NewRadarDetectionStop( + IN PRTMP_ADAPTER pAd) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + + DBGPRINT(RT_DEBUG_TRACE, ("NewRadarDetectionStop\n")); + + /* set init bit = false to prevent dfs rotines */ + pRadarDetect->bDfsInit = FALSE; + pRadarDetect->radarDeclared = 0; + + /* Disable detection*/ + DfsDetectionDisable(pAd); + + /* Clear status */ + DfsResetHwDetectionStatus(pAd); + +#ifdef RTMP_MAC_PCI + RTMP_HW_TIMER_INT_SET(pAd, 0); + RTMP_HW_TIMER_INT_DISABLE(pAd); +#endif /* RTMP_MAC_PCI */ + +} + + +/* 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]; + + if (start_idx > end_idx) + end_idx += NEW_DFS_DBG_PORT_ENT_NUM; + + + pDfsSwParam->sw_idx[id] = pDfsSwParam->pr_idx[id]; + + /* FCC && Japan*/ + + if (pAd->CommonCfg.RDDurRegion != CE) + { + ULONG minPeriod = (3000 << 1); + /* Calculate how many counters to check*/ + /* if pRadarDetect->PollTime is 1ms, a round of timestamp is 107 for 20Mhz, 53 for 40Mhz*/ + /* if pRadarDetect->PollTime is 2ms, a round of timestamp is 71 for 20Mhz, 35 for 40Mhz*/ + /* if pRadarDetect->PollTime is 3ms, a round of timestamp is 53 for 20Mhz, 27 for 40Mhz*/ + /* if pRadarDetect->PollTime is 4ms, a round of timestamp is 43 for 20Mhz, 21 for 40Mhz*/ + /* the max period to check for 40Mhz for FCC is 28650 * 2*/ + /* the max period to check for 40Mhz for Japan is 80000 * 2*/ + /* 0x40000 = 4194304 / 57129 = 73.xxx*/ + /* 0x40000 = 4194304 / 160000 = 26.2144*/ + /* 53/73 < 1 (1+1)*/ + /* 53/26.2144 = 2.02... (2+1)*/ + /* 27/26.2144 = 1.02... (1+1)*/ + /* 20M should use the same value as 40Mhz mode*/ + + if (pRadarDetect->MCURadarRegion == NEW_DFS_JAP_W53) + { + minPeriod = 28500 << 1; + } + + if (pAd->CommonCfg.RDDurRegion == FCC) + { + CounterToCheck = 1+1; + } + else /* if (pAd->CommonCfg.RDDurRegion == JAP)*/ + { + if (pRadarDetect->PollTime <= 2) + CounterToCheck = 2+1; + else + CounterToCheck = 1+1; + } + + /* First Loop for FCC/JAP*/ + for (i = end_idx; i > start_idx; i--) + { + pCurrent = &pDfsSwParam->DFS_W[id][i & NEW_DFS_DBG_PORT_MASK]; + + /* we only handle entries has same counter with the last one*/ + if (pCurrent->counter != pEnd->counter) + break; + + pCurrent->start_idx = 0xffff; + + /* calculate if any two pulse become a valid period, add it in period table,*/ + for (j = i - 1; j > start_idx; j--) + { + p1 = &pDfsSwParam->DFS_W[id][j & NEW_DFS_DBG_PORT_MASK]; + + /* check period, must within max period*/ + if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + { + if (p1->counter + CounterToCheck < pCurrent->counter) + break; + + widthsum = p1->width + pCurrent->width; + if (id == 0) + { + if (widthsum < 600) + pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_L; + else + pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift; + } + else if (id == 1) + pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch1_Shift; + else if (id == 2) + pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift; + + if ( (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) || + (PERIOD_MATCH(p1->width, pCurrent->width, pDfsSwParam->dfs_width_diff)) ) + { + if (p1->timestamp >= pCurrent->timestamp) + period = 0x400000 + pCurrent->timestamp - p1->timestamp; + else + period = pCurrent->timestamp - p1->timestamp; + + if ((period >= (minPeriod - 2)) && (period <= pDfsSwParam->dfs_max_period)) + { + /* add in period table*/ + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx = (i & NEW_DFS_DBG_PORT_MASK); + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width = pCurrent->width; + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx2 = (j & NEW_DFS_DBG_PORT_MASK); + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width2 = p1->width; + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].period = period; + + if (pCurrent->start_idx == 0xffff) + pCurrent->start_idx = pDfsSwParam->dfs_t_idx[id]; + pCurrent->end_idx = pDfsSwParam->dfs_t_idx[id]; + + pDfsSwParam->dfs_t_idx[id]++; + if (pDfsSwParam->dfs_t_idx[id] >= NEW_DFS_MPERIOD_ENT_NUM) + pDfsSwParam->dfs_t_idx[id] = 0; + } + else if (period > pDfsSwParam->dfs_max_period) + break; + } + } + else + { + if (p1->counter + CounterToCheck < pCurrent->counter) + break; + + widthsum = p1->width + pCurrent->width; + if (id == 0) + { + if (widthsum < 600) + pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_L; + else + pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift; + } + else if (id == 1) + pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch1_Shift; + else if (id == 2) + pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift; + + + if ( (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) || + (PERIOD_MATCH(p1->width, pCurrent->width, pDfsSwParam->dfs_width_diff)) ) + + { + if (p1->timestamp >= pCurrent->timestamp) + period = 0x400000 + pCurrent->timestamp - p1->timestamp; + else + period = pCurrent->timestamp - p1->timestamp; + + if ((period >= ((minPeriod >> 1) - 2)) && (period <= (pDfsSwParam->dfs_max_period >> 1))) + { + /* add in period table*/ + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx = (i & NEW_DFS_DBG_PORT_MASK); + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width = pCurrent->width; + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx2 = (j & NEW_DFS_DBG_PORT_MASK); + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width2 = p1->width; + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].period = period; + + if (pCurrent->start_idx == 0xffff) + pCurrent->start_idx = pDfsSwParam->dfs_t_idx[id]; + pCurrent->end_idx = pDfsSwParam->dfs_t_idx[id]; + + pDfsSwParam->dfs_t_idx[id]++; + if (pDfsSwParam->dfs_t_idx[id] >= NEW_DFS_MPERIOD_ENT_NUM) + pDfsSwParam->dfs_t_idx[id] = 0; + } + else if (period > (pDfsSwParam->dfs_max_period >> 1)) + break; + } + } + } /* for (j = i - 1; j > start_idx; j--)*/ + } /* for (i = end_idx; i > start_idx; i--)*/ + + /* Second Loop for FCC/JAP*/ + for (i = end_idx; i > start_idx; i--) + { + pCurrent = &pDfsSwParam->DFS_W[id][i & NEW_DFS_DBG_PORT_MASK]; + + /* we only handle entries has same counter with the last one*/ + if (pCurrent->counter != pEnd->counter) + break; + if (pCurrent->start_idx != 0xffff) + { + /*pNewDFSDebugPort p2, p3, p4, p5, p6;*/ + pNewDFSDebugPort p2, p3; + pNewDFSMPeriod pCE_T; + ULONG idx[10], T[10]; + + for (idx[0] = pCurrent->start_idx; idx[0] <= pCurrent->end_idx; idx[0]++) + { + pCE_T = &pDfsSwParam->DFS_T[id][idx[0]]; + + p2 = &pDfsSwParam->DFS_W[id][pCE_T->idx2]; + + if (p2->start_idx == 0xffff) + continue; + + T[0] = pCE_T->period; + + for (idx[1] = p2->start_idx; idx[1] <= p2->end_idx; idx[1]++) + { + + pCE_T = &pDfsSwParam->DFS_T[id][idx[1]]; + + p3 = &pDfsSwParam->DFS_W[id][pCE_T->idx2]; + + if (idx[0] == idx[1]) + continue; + + if (p3->start_idx == 0xffff) + continue; + + T[1] = pCE_T->period; + + if ( PERIOD_MATCH(T[0], T[1], pDfsSwParam->dfs_period_err)) + { + if (id <= 2) /* && (id >= 0)*/ + { + /*if (((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && (T[1] > minPeriod)) ||*/ + /* ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_20) && (T[1] > (minPeriod >> 1))) )*/ + { + unsigned int loop, PeriodMatched = 0, idx1; + for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++) + { + idx1 = (idx[1] >= loop)? (idx[1] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[1] - loop); + if (PERIOD_MATCH(pDfsSwParam->DFS_T[id][idx1].period, T[1], pDfsSwParam->dfs_period_err)) + PeriodMatched++; + } + + if (PeriodMatched > pDfsSwParam->dfs_declare_thres) + { + { + pNewDFSValidRadar pDFSValidRadar; + ULONG T1 = (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)? (T[1]>>1) : T[1]; + + pDFSValidRadar = &NewDFSValidTable[0]; + + while (pDFSValidRadar->type != NEW_DFS_END) + { + if ((pDFSValidRadar->type & pRadarDetect->MCURadarRegion) == 0) + { + pDFSValidRadar++; + continue; + } + + if (pDFSValidRadar->TLow) + { + if ( (T1 > (pDFSValidRadar->TLow - pDFSValidRadar->TMargin)) && + (T1 < (pDFSValidRadar->THigh + pDFSValidRadar->TMargin)) ) + { + radar_detected = 1; + } + } + else + { + if ( (T1 > (pDFSValidRadar->T - pDFSValidRadar->TMargin)) && + (T1 < (pDFSValidRadar->T + pDFSValidRadar->TMargin)) ) + { + radar_detected = 1; + break; + } + } + + pDFSValidRadar++; + } + if (radar_detected == 1) + { + DBGPRINT(RT_DEBUG_TRACE, ("W=%d, T=%d (%d), period matched=%d\n", (unsigned int)pCE_T->width, (unsigned int)T1, (unsigned int)id, PeriodMatched)); + printk("SWRadarCheck: Radar Detected\n"); + return radar_detected; + } + else if (pRadarDetect->MCURadarRegion != NEW_DFS_JAP_W53) + DBGPRINT(RT_DEBUG_TRACE, ("W=%d, T=%d (%d), period matched=%d\n", (unsigned int)pCE_T->width, (unsigned int)T1, (unsigned int)id, PeriodMatched)); + } + } + } + } /* if (id <= 2) && (id >= 0)*/ + } + } /* for (idx[1] = p2->start_idx; idx[1] <= p2->end_idx; idx[1]++)*/ + + /* increase FCC-1 detection*/ + if (id <= 2) + { + if (IS_FCC_RADAR_1((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), T[0])) + { + int loop, idx1, PeriodMatched_fcc1 = 0; + for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++) + { + idx1 = (idx[0] >= loop)? (idx[0] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[0] - loop); + if ( IS_FCC_RADAR_1((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), pDfsSwParam->DFS_T[id][idx1].period) ) + { + /*printk("%d %d %d\n", PeriodMatched_fcc1, pDfsSwParam->DFS_T[id][idx1].period, loop);*/ + PeriodMatched_fcc1++; + } + } + + if (PeriodMatched_fcc1 > 3) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeriodMatched_fcc1 = %d (%d)\n", PeriodMatched_fcc1, id)); + radar_detected = 1; + return radar_detected; + } + } + } + + + /* increase W56-3 detection*/ + if ((pRadarDetect->MCURadarRegion == NEW_DFS_JAP) && (id <= 2)) + { + if (IS_W56_RADAR_3((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), T[0])) + { + int loop, idx1, PeriodMatched_w56_3 = 0; + for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++) + { + idx1 = (idx[0] >= loop)? (idx[0] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[0] - loop); + if ( IS_W56_RADAR_3((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), pDfsSwParam->DFS_T[id][idx1].period) ) + { + /*printk("%d %d %d\n", PeriodMatched_w56_3, pDfsSwParam->DFS_T[id][idx1].period, loop);*/ + PeriodMatched_w56_3++; + } + } + + if (PeriodMatched_w56_3 > 3) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeriodMatched_w56_3 = %d (%d)\n", PeriodMatched_w56_3, id)); + radar_detected = 1; + return radar_detected; + } + } + } + + if ((pRadarDetect->MCURadarRegion == NEW_DFS_JAP_W53) && (id <= 2) && IS_W53_RADAR_2((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), T[0])) + { + int loop, idx1, PeriodMatched_W56_2 = 0; + + for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++) + { + idx1 = (idx[0] >= loop)? (idx[0] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[0] - loop); + if ( IS_W53_RADAR_2((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40), pDfsSwParam->DFS_T[id][idx1].period) ) + { + /*printk("%d %d %d\n", PeriodMatched_W56_2, pDfsSwParam->DFS_T[id][idx1].period, loop);*/ + PeriodMatched_W56_2++; + } + } + + if (PeriodMatched_W56_2 >= 3) + { + DBGPRINT(RT_DEBUG_TRACE, ("PeriodMatched_W56_2 = %d(%d)\n", PeriodMatched_W56_2, id)); + radar_detected = 1; + return radar_detected; + } + } + } /* for (idx[0] = pCurrent->start_idx; idx[0] <= pCurrent->end_idx; idx[0]++)*/ + } /* if (pCurrent->start_idx != 0xffff)*/ + } /* for (i = end_idx; i > start_idx; i--)*/ + + return radar_detected; + } + + /* CE have staggered radar */ + + /* Calculate how many counters to check*/ + /* if pRadarDetect->PollTime is 1ms, a round of timestamp is 107 for 20Mhz, 53 for 40Mhz*/ + /* if pRadarDetect->PollTime is 2ms, a round of timestamp is 71 for 20Mhz, 35 for 40Mhz*/ + /* if pRadarDetect->PollTime is 3ms, a round of timestamp is 53 for 20Mhz, 27 for 40Mhz*/ + /* if pRadarDetect->PollTime is 4ms, a round of timestamp is 43 for 20Mhz, 21 for 40Mhz*/ + /* if pRadarDetect->PollTime is 8ms, a round of timestamp is ?? for 20Mhz, 12 for 40Mhz*/ + /* the max period to check for 40Mhz is 133333 + 125000 + 117647 = 375980*/ + /* 0x40000 = 4194304 / 375980 = 11.1556*/ + /* 53/11.1556 = 4.75...*/ + /* 35/11.1556 = 3.1374, (4+1) is safe, (3+1) to save CPU power, but may lost some data*/ + /* 27/11.1556 = 2.42, (3+1) is OK*/ + /* 21/11.1556 = 1.88, (2+1) is OK*/ + /* 20M should use the same value as 40Mhz mode*/ + if (pRadarDetect->PollTime == 1) + CounterToCheck = 5+1; + else if (pRadarDetect->PollTime == 2) + CounterToCheck = 4+1; + else if (pRadarDetect->PollTime == 3) + CounterToCheck = 3+1; + else if (pRadarDetect->PollTime <= 8) + CounterToCheck = 2+1; + else + CounterToCheck = 1+1; + + /* First Loop for CE*/ + for (i = end_idx; i > start_idx; i--) + { + pCurrent = &pDfsSwParam->DFS_W[id][i & NEW_DFS_DBG_PORT_MASK]; + + /* we only handle entries has same counter with the last one*/ + if (pCurrent->counter != pEnd->counter) + break; + + pCurrent->start_idx = 0xffff; + + /* calculate if any two pulse become a valid period, add it in period table,*/ + for (j = i - 1; j > start_idx; j--) + { + p1 = &pDfsSwParam->DFS_W[id][j & NEW_DFS_DBG_PORT_MASK]; + + + /* check period, must within 16666 ~ 66666*/ + if (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + { + if (p1->counter + CounterToCheck < pCurrent->counter) + break; + + widthsum = p1->width + pCurrent->width; + if (id == 0) + { + if (((p1->width > 310) && (pCurrent->width < 300)) || ((pCurrent->width > 310) && ((p1->width < 300))) ) + continue; + if (widthsum < 620) + pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_H; + else + pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_L; + + } + else if (id == 1) + pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch1_Shift; + else if (id == 2) + pDfsSwParam->dfs_width_diff = widthsum >> pDfsSwParam->dfs_width_diff_ch2_Shift; + + if ( (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) || + (PERIOD_MATCH(p1->width, pCurrent->width, pDfsSwParam->dfs_width_diff)) ) + { + if (p1->timestamp >= pCurrent->timestamp) + period = 0x400000 + pCurrent->timestamp - p1->timestamp; + else + period = pCurrent->timestamp - p1->timestamp; + + /*if ((period >= (33333 - 20)) && (period <= (133333 + 20)))*/ + if ((period >= (33333 - 20)) && (period <= pDfsSwParam->dfs_max_period)) + //if ((period >= (10000 - 2)) && (period <= pDfsSwParam->dfs_max_period)) + { + /* add in period table*/ + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx = (i & NEW_DFS_DBG_PORT_MASK); + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width = pCurrent->width; + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx2 = (j & NEW_DFS_DBG_PORT_MASK); + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width2 = p1->width; + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].period = period; + + if (pCurrent->start_idx == 0xffff) + pCurrent->start_idx = pDfsSwParam->dfs_t_idx[id]; + pCurrent->end_idx = pDfsSwParam->dfs_t_idx[id]; + + pDfsSwParam->dfs_t_idx[id]++; + if (pDfsSwParam->dfs_t_idx[id] >= NEW_DFS_MPERIOD_ENT_NUM) + pDfsSwParam->dfs_t_idx[id] = 0; + } + else if (period > pDfsSwParam->dfs_max_period) /* to allow miss a pulse*/ + break; + } + + } + else + { + if (p1->counter + CounterToCheck < pCurrent->counter) + break; + + widthsum = p1->width + pCurrent->width; + if (id == 0) + { + if (((p1->width > 300) && (pCurrent->width < 300)) || ((pCurrent->width > 300) && ((p1->width < 300))) ) + continue; + if (widthsum < 620) + pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_H; + else + pDfsSwParam->dfs_width_diff = pDfsSwParam->dfs_width_ch0_err_L; + } + else if (id == 1) + { + pDfsSwParam->dfs_width_diff = widthsum >> 3; /* for 20M verified */ + //printk("dfs_width_diff = %u\n",pDfsSwParam->dfs_width_diff); + } + else if (id == 2) + pDfsSwParam->dfs_width_diff = widthsum >> 6; + + if ( (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) || + (PERIOD_MATCH(p1->width, pCurrent->width, pDfsSwParam->dfs_width_diff)) ) + + { + if (p1->timestamp >= pCurrent->timestamp) + period = 0x400000 + pCurrent->timestamp - p1->timestamp; + else + period = pCurrent->timestamp - p1->timestamp; + + //if ((period >= (5000 - 2)) && (period <= (pDfsSwParam->dfs_max_period >> 1))) + if ((period >= (16666 - 20)) && (period <= (pDfsSwParam->dfs_max_period >> 1)))//neil modify for ce 5-1 + { + /* add in period table*/ + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx = (i & NEW_DFS_DBG_PORT_MASK); + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width = pCurrent->width; + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].idx2 = (j & NEW_DFS_DBG_PORT_MASK); + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].width2 = p1->width; + pDfsSwParam->DFS_T[id][pDfsSwParam->dfs_t_idx[id]].period = period; + + if (pCurrent->start_idx == 0xffff) + pCurrent->start_idx = pDfsSwParam->dfs_t_idx[id]; + pCurrent->end_idx = pDfsSwParam->dfs_t_idx[id]; + + pDfsSwParam->dfs_t_idx[id]++; + if (pDfsSwParam->dfs_t_idx[id] >= NEW_DFS_MPERIOD_ENT_NUM) + pDfsSwParam->dfs_t_idx[id] = 0; + } + else if (period > (pDfsSwParam->dfs_max_period >> 1)) + break; + } + } + } /* for (j = i - 1; j > start_idx; j--)*/ + } + + /* Second Loop for CE*/ + for (i = end_idx; i > start_idx; i--) + { + pCurrent = &pDfsSwParam->DFS_W[id][i & NEW_DFS_DBG_PORT_MASK]; + + /* we only handle entries has same counter with the last one*/ + if (pCurrent->counter != pEnd->counter) + break; + + /* Check Staggered radar*/ + if (pCurrent->start_idx != 0xffff) + { + pNewDFSDebugPort p2, p3; + pNewDFSMPeriod pCE_T; + ULONG idx[10], T[10]; + + /*printk("pCurrent=%d, idx=%d~%d\n", pCurrent->timestamp, pCurrent->start_idx, pCurrent->end_idx);*/ + + for (idx[0] = pCurrent->start_idx; idx[0] <= pCurrent->end_idx; idx[0]++) + { + pCE_T = &pDfsSwParam->DFS_T[id][idx[0]]; + + p2 = &pDfsSwParam->DFS_W[id][pCE_T->idx2]; + + /*printk("idx[0]= %d, idx=%d p2=%d, idx=%d~%d\n", idx[0], pCE_T->idx2, p2->timestamp, p2->start_idx, p2->end_idx);*/ + + if (p2->start_idx == 0xffff) + continue; + + T[0] = pCE_T->period; + + + for (idx[1] = p2->start_idx; idx[1] <= p2->end_idx; idx[1]++) + { + + pCE_T = &pDfsSwParam->DFS_T[id][idx[1]]; + + p3 = &pDfsSwParam->DFS_W[id][pCE_T->idx2]; + + /*printk("p3=%d, idx=%d~%d\n", p3->timestamp, p3->start_idx, p3->end_idx);*/ + + if (idx[0] == idx[1]) + continue; + + if (p3->start_idx == 0xffff) + continue; + + + + T[1] = pCE_T->period; + + + if (PERIOD_MATCH(T[0], T[1], pDfsSwParam->dfs_period_err)) + { + if (id <= 2) /* && (id >= 0)*/ + { + + + if (((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && (T[1] > 66666)) || + ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_20) && (T[1] > 33333)) ) + { + unsigned int loop, PeriodMatched = 0, idx1; + + for (loop = 1; loop < pDfsSwParam->dfs_check_loop; loop++) + { + idx1 = (idx[1] >= loop)? (idx[1] - loop): (NEW_DFS_MPERIOD_ENT_NUM + idx[1] - loop); + if (PERIOD_MATCH(pDfsSwParam->DFS_T[id][idx1].period, T[1], pDfsSwParam->dfs_period_err)) + { + /*printk("%d %d\n", loop, pDfsSwParam->DFS_T[id][idx[1]-loop].period);*/ + PeriodMatched++; + } + } + + if (PeriodMatched > pDfsSwParam->dfs_declare_thres) + { + printk("Radar Detected(CE), W=%d, T=%d (%d), period matched=%d\n", (unsigned int)pCE_T->width, (unsigned int)T[1], (unsigned int)id, PeriodMatched); + + if (PeriodMatched > (pDfsSwParam->dfs_declare_thres + 1)) + radar_detected = 1; + return radar_detected; + } + } + } + } + } /* for (idx[1] = p2->start_idx; idx[1] <= p2->end_idx; idx[1]++)*/ + } /* for (idx[0] = pCurrent->start_idx; idx[0] <= pCurrent->end_idx; idx[0]++)*/ + } + } /* for (i = end_idx; i < start_idx; i--)*/ + + return radar_detected; +} + +/* + ========================================================================== + Description: + Recheck DFS radar of stager type. + Arguments: + pAdapter Pointer to our adapter + dfs_channel DFS detect channel + Return Value: + "TRUE" if check pass, "FALSE" otherwise. + Note: + ========================================================================== + */ +static BOOLEAN StagerRadarCheck(IN PRTMP_ADAPTER pAd, UINT8 dfs_channel) +{ + UINT T1=0, T2=0, T3=0, F1, F2, F3 = 0, Fmax = 0, freq_diff_min, freq_diff_max; + UINT8 dfs_stg2=0, dfs_typ5=0; + UINT F_MAX, F_MID, F_MIN; + + DBGPRINT(RT_DEBUG_TRACE, ("--->StagerRadarCheck()\n")); + StagerRadarGetPRIs(pAd, dfs_channel, &T1, &T2, &T3); + + if (T3 < 5) + T3 = 0; + + /*1. Check radar stagger2 or stagger3*/ + if (T3 == 0 || ((T3 > (T1 + T2) ? (T3 - T1 - T2) : (T1 + T2 - T3)) < 25)) + { + DBGPRINT(RT_DEBUG_TRACE, ("stg2 confirmed\n")); + dfs_stg2 =1; + F1 = 20000000/T1; /*hz*/ + F2 = 20000000/T2; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("stg3 confirmed\n")); + F1 = 20000000/T1; /*hz*/ + F2 = 20000000/T2; + F3 = 20000000/T3; + } + + F_MAX = (F1 > F2) ? ( (F1 > F3) ? F1 : F3 ) : ( (F2 > F3) ? F2 : F3 ); + F_MIN = (F1 < F2) ? ( (F1 < F3) ? F1 : F3 ) : ( (F2 < F3) ? F2 : F3 ); + F_MID = (F1 > F2) ? ((F1 < F3) ? F1 : ( (F2 > F3) ? F2 : F3 )) : ( F2 < F3 ? F2 : ((F1 > F3) ? F1 :F3) ); + + DBGPRINT(RT_DEBUG_TRACE, ("F_MAX=%d F_MID=%d F_MIN=%d\n", F_MAX, F_MID, F_MIN)); + + F1 = F_MAX; + F2 = F_MID; + F3 = F_MIN; + + Fmax = F1; + + /*2. Check radar type 5 or type6*/ + if (Fmax>295 && Fmax<=405) + { + 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); + pRadarDetect->busy_time = AsicGetChBusyCnt(pAd, 0); + + /*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.AvgRssi[0]) && (pAd->ApCfg.RssiSample.AvgRssi[0] > pRadarDetect->DfsRssiHigh)) + pRadarDetect->ch_busy = 2; + else if ((pAd->ApCfg.RssiSample.AvgRssi[0]) && (pAd->ApCfg.RssiSample.AvgRssi[0] < 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.AvgRssi[0], pRadarDetect->ch_busy)); + +} + +static BOOLEAN DfsChannelCheck( + IN PRTMP_ADAPTER pAd, + IN UINT8 DfsChannel) +{ + pNewDFSTable pDFSTable; + UINT8 i; + UINT32 T, W, W2, B; + BOOLEAN radarDeclared = 0; + + T = W = W2 = B = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("DFS HW check channel = 0x%x\n", DfsChannel)); + /*Select the DFS table based on radar country region*/ + if (pAd->CommonCfg.RDDurRegion == FCC) + pDFSTable = &NewDFSTable1[0]; + else if (pAd->CommonCfg.RDDurRegion == CE) + { + pDFSTable = &NewDFSTable1[1]; + } + else /* Japan*/ + { + if ((pAd->CommonCfg.Channel >= 52) && (pAd->CommonCfg.Channel <= 64)) + { + pDFSTable = &NewDFSTable1[3]; + } + else + { + pDFSTable = &NewDFSTable1[2]; + } + } + /*check which channe(0~3) is detecting radar signals*/ + for (i = 0; i < pAd->chipCap.DfsEngineNum; i++) + { + + if (DfsChannel & (0x1 << i)) + { + DfsHwDetectionGetPulseInfo(pAd, i, &T, &W, &W2, &B); + + if (DfsSwCheckOnHwDetection(pAd, pDFSTable, i, T, W) == FALSE) + continue; + + DBGPRINT(RT_DEBUG_OFF, ("T = %u, W= %u detected by ch %d\n", T, W, i)); + + /*set this variable to 1 for announcing that we find the radar signals.*/ + radarDeclared = 1; + + if ( ((i == 3) || (i == 2)) && (pDFSTable->entry[i].mode != 0) ) + { + DBGPRINT(RT_DEBUG_TRACE, ("Burst = %u(0x%x)\n", B, B)); + DBGPRINT(RT_DEBUG_TRACE, ("The second Width = %u(0x%x)\n", W2, W2)); + } + } + } + return radarDeclared; +} + + +static BOOLEAN DfsEventDataFetch( + IN PRTMP_ADAPTER pAd, + IN PRADAR_DETECT_STRUCT pRadarDetect, + OUT PDFS_EVENT pDfsEvent) +{ + UINT8 idx; + UINT8 EventBuff[DFS_EVENT_SIZE] = {0}; + UINT32 bbp_val; + + /* Read a event from event buffer */ + for (idx = 0; idx < DFS_EVENT_SIZE; idx++) + { + RTMP_BBP_IO_READ32(pAd, BBP_R127, &bbp_val); + EventBuff[idx] = bbp_val; + } + + if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_SHOW_RAW_EVENT) + { + DFS_EVENT_BUFF_PRINT(0, EventBuff, DFS_EVENT_SIZE); + } + + pDfsEvent->EngineId = EventBuff[0]; + if (pDfsEvent->EngineId == 0xff) /* end of event */ + return FALSE; + + pDfsEvent->TimeStamp = EventBuff[1]; + pDfsEvent->TimeStamp |= (EventBuff[2] << 8); + pDfsEvent->TimeStamp |= (EventBuff[3] << 16); + + pDfsEvent->Width = EventBuff[4]; + pDfsEvent->Width |= (EventBuff[5] << 8); + + /* Check if event is valid */ + if (!DFS_EVENT_SANITY_CHECK(pAd, *pDfsEvent)) + return FALSE; + + return TRUE; +} + +VOID NewRadarDetectionProgram(PRTMP_ADAPTER pAd, pNewDFSTable pDFSTable) +{ + UINT8 idx, TalbeIdx; + UINT8 DfsEngineNum = pAd->chipCap.DfsEngineNum; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam; + + pRadarDetect->bDfsInit = FALSE; + + /* Get Table index*/ + for (TalbeIdx = 0; !((1<type); TalbeIdx++) + { + if (TalbeIdx > MAX_RD_REGION) + { + DBGPRINT(RT_DEBUG_ERROR, ("Table index out of range.\n")); + return; + } + } + + for(idx = 0; idxDFSParamFromConfig & (0x1<NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].valid) + { + pDFSTable->entry[idx].mode = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].mode; + pDFSTable->entry[idx].avgLen = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].avgLen; + pDFSTable->entry[idx].ELow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].ELow; + pDFSTable->entry[idx].EHigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].EHigh; + pDFSTable->entry[idx].WLow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].WLow; + pDFSTable->entry[idx].WHigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].WHigh; + pDFSTable->entry[idx].EpsilonW = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].EpsilonW; + pDFSTable->entry[idx].TLow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].TLow; + pDFSTable->entry[idx].THigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].THigh; + pDFSTable->entry[idx].EpsilonT = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].EpsilonT; + pDFSTable->entry[idx].BLow = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].BLow; + pDFSTable->entry[idx].BHigh = pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].BHigh; + pDFSTable->entry[idx].EventExpiration= pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].EventExpiration; + pDFSTable->entry[idx].PwrJump= pDfsProgramParam->NewDFSTableEntry[(TalbeIdx*DfsEngineNum)+idx].PwrJump; + + DBGPRINT(RT_DEBUG_TRACE, ("TalbeIdx = %d; idx = %d; DFSParam = %2d; %3d; %3d; %3d; %3d; %4d; %3d; %6lu; %7lu; %4d; %2lu; %2lu, %d, 0x%04x\n", TalbeIdx, idx, + pDFSTable->entry[idx].mode, pDFSTable->entry[idx].avgLen, pDFSTable->entry[idx].ELow, + pDFSTable->entry[idx].EHigh, pDFSTable->entry[idx].WLow, pDFSTable->entry[idx].WHigh, + pDFSTable->entry[idx].EpsilonW, pDFSTable->entry[idx].TLow, pDFSTable->entry[idx].THigh, + pDFSTable->entry[idx].EpsilonT, pDFSTable->entry[idx].BLow, pDFSTable->entry[idx].BHigh, + pDFSTable->entry[idx].EventExpiration, pDFSTable->entry[idx].PwrJump)); + } + } + + /* Symmetric round*/ + if(pRadarDetect->SymRoundFromCfg != 0) + { + pDfsProgramParam->Symmetric_Round = pRadarDetect->SymRoundFromCfg; + DBGPRINT(RT_DEBUG_TRACE, ("Symmetric_Round = %d\n", pDfsProgramParam->Symmetric_Round)); + } + + /* BusyIdleRatio*/ + if(pRadarDetect->BusyIdleFromCfg != 0) + { + pRadarDetect->ch_busy_idle_ratio = pRadarDetect->BusyIdleFromCfg; + DBGPRINT(RT_DEBUG_TRACE, ("ch_busy_idle_ratio = %d\n", pRadarDetect->ch_busy_idle_ratio)); + } + /* DfsRssiHigh*/ + if(pRadarDetect->DfsRssiHighFromCfg != 0) + { + pRadarDetect->DfsRssiHigh = pRadarDetect->DfsRssiHighFromCfg; + DBGPRINT(RT_DEBUG_TRACE, ("DfsRssiHigh = %d\n", pRadarDetect->DfsRssiHigh)); + } + /* DfsRssiLow*/ + if(pRadarDetect->DfsRssiLowFromCfg != 0) + { + pRadarDetect->DfsRssiLow = pRadarDetect->DfsRssiLowFromCfg; + DBGPRINT(RT_DEBUG_TRACE, ("DfsRssiLow = %d\n", pRadarDetect->DfsRssiLow)); + } + + /*pRadarDetect->MCURadarRegion = pAd->CommonCfg.RDDurRegion;*/ + pRadarDetect->MCURadarRegion = pDFSTable->type; + + DfsProgramBbpValues(pAd, pDFSTable); + + pRadarDetect->bDfsInit = TRUE; + +} + +BOOLEAN DfsSwCheckOnHwDetection( + IN PRTMP_ADAPTER pAd, + IN pNewDFSTable pDFSTable, + IN UINT8 DfsChannel, + IN ULONG RadarPeriod, + IN ULONG RadarWidth) +{ + BOOLEAN bRadarCheck = TRUE; + if (!RadarPeriod || !RadarWidth) + { + DBGPRINT(RT_DEBUG_TRACE, ("Block eception on zero RadarPeriod or RadarWidth\n")); + return FALSE; + } + + if (pDFSTable->type == NEW_DFS_JAP) + { + /* Double check on pusle Width and Period*/ + if (DfsChannel < 3) + { + /*check short pulse*/ + if (RadarWidth < 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 (pDFSTable->type == NEW_DFS_EU) + { + /* Double check on pusle Width and Period*/ + if (DfsChannel < 3) + { + + /* block the illegal period */ + if ((RadarPeriod < 4900) || + (RadarPeriod > 8800 && RadarPeriod < 12400) || + (RadarPeriod > 14000 && RadarPeriod < 15800) || + (RadarPeriod > 100100)) + { + /*(0~245), (440~620us), (5005us~) according to the spec*/ + DBGPRINT(RT_DEBUG_TRACE, + ("Radar check: ch=%u, T=%lu, W=%lu, blocked\n", DfsChannel, RadarPeriod, RadarWidth)); + bRadarCheck = FALSE; + } + } + else if (DfsChannel == 4) /* to do: check dfs mode 8or9*/ + { + if (StagerRadarCheck(pAd, DfsChannel) == FALSE) + bRadarCheck = FALSE; + } + } + else if (pDFSTable->type == FCC) + { + /* Double check on pusle Width and Period*/ + if (DfsChannel < 3) + { + if (RadarWidth < 950) + { + /* block the illegal period */ + if ((RadarPeriod < 2800) || + (RadarPeriod > 10100 && RadarPeriod < 28360) || (RadarPeriod > 28700)) + { + /*(0~140), (505~1418), (1435us~) 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 ((RadarPeriod<2800) || + (RadarPeriod > 10200 && RadarPeriod < 19800) || + (RadarPeriod>40200)) + { + /* block the illegal period */ + /*(0~140) and (510us~990), (2010us~) 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); + } + } + + return bRadarCheck; +} + +static VOID ChannelSelectOnRadarDetection( + IN PRTMP_ADAPTER pAd) +{ + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + UINT i; + + if (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE) + return; + +#ifdef DOT11_VHT_AC + if (pAd->CommonCfg.BBPCurrentBW == BW_80) + { + for (i=0; iChannelListNum; i++) + { + if ((pAd->CommonCfg.Channel >= 52 && pAd->CommonCfg.Channel <= 64) && + (pAd->ChannelList[i].Channel >= 52 && pAd->ChannelList[i].Channel <= 64)) + { + pAd->ChannelList[i].RemainingTimeForUse = 1800; + } + else if ((pAd->CommonCfg.Channel >= 100 && pAd->CommonCfg.Channel <= 112) && + (pAd->ChannelList[i].Channel >= 100 && pAd->ChannelList[i].Channel <= 112)) + { + pAd->ChannelList[i].RemainingTimeForUse = 1800; + } + else if ((pAd->CommonCfg.Channel >= 116 && pAd->CommonCfg.Channel <= 128) && + (pAd->ChannelList[i].Channel >= 116 && pAd->ChannelList[i].Channel <= 128)) + { + pAd->ChannelList[i].RemainingTimeForUse = 1800; + } + } + } +#endif /* DOT11_VHT_AC */ + + for (i=0; iChannelListNum; i++) + { + if (pAd->CommonCfg.Channel == pAd->ChannelList[i].Channel) + { + if (pAd->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->dfs_check_loop = DFS_SW_RADAR_CHECK_LOOP; + pDfsSwParam->dfs_width_diff_ch1_Shift = DFS_SW_RADAR_CH1_SHIFT; + pDfsSwParam->dfs_width_diff_ch2_Shift = DFS_SW_RADAR_CH2_SHIFT; + pDfsSwParam->PreDfsEvent.EngineId = 0xff; + pDfsSwParam->EvtDropAdjTime = 2000; + + pDfsSwParam->dfs_width_ch0_err_L = DFS_SW_RADAR_CH0_ERR; + if (pAd->CommonCfg.RDDurRegion == CE) + pDfsSwParam->dfs_period_err = (DFS_SW_RADAR_PERIOD_ERR << 2); + 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 + { + 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 + { + if (pAd->CommonCfg.RDDurRegion == FCC) + pDfsSwParam->dfs_max_period = FCC_RADAR_PERIOD_MAX; + else if (pAd->CommonCfg.RDDurRegion == JAP) + pDfsSwParam->dfs_max_period = JAP_RADAR_PERIOD_MAX; + } + + if (pRadarDetect->use_tasklet) + pRadarDetect->PollTime = NEW_DFS_CHECK_TIME_TASKLET; + else + pRadarDetect->PollTime = NEW_DFS_CHECK_TIME; + + for (k = 0; k < pAd->chipCap.DfsEngineNum; k++) + { + for (j = 0; j < NEW_DFS_DBG_PORT_ENT_NUM; j++) + { + pDfsSwParam->DFS_W[k][j].start_idx = 0xffff; + } + } + + for (k = 0; k < pAd->chipCap.DfsEngineNum; k++) + { + pDfsSwParam->sw_idx[k] = NEW_DFS_DBG_PORT_ENT_NUM - 1; + pDfsSwParam->hw_idx[k] = 0; + } + + NdisZeroMemory(pDfsSwParam->DFS_T, sizeof(pDfsSwParam->DFS_T)); + NdisZeroMemory(pDfsSwParam->DFS_W, sizeof(pDfsSwParam->DFS_W)); +} + +void modify_table1(PRTMP_ADAPTER pAd, ULONG idx, ULONG value) +{ + pNewDFSTable pDFSTable; + ULONG x, y; + UINT8 DfsEngineNum = pAd->chipCap.DfsEngineNum; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam; + + if (pAd->CommonCfg.RDDurRegion == FCC) + pDFSTable = &NewDFSTable1[0]; + else if (pAd->CommonCfg.RDDurRegion == CE) + { + pDFSTable = &NewDFSTable1[1]; + } + else /* Japan*/ + { + if ((pAd->CommonCfg.Channel >= 52) && (pAd->CommonCfg.Channel <= 64)) + { + pDFSTable = &NewDFSTable1[3]; + } + else + { + pDFSTable = &NewDFSTable1[2]; + } + } + + + if (idx == 0) + { + pDfsProgramParam->DeltaDelay = value; + } + else if (idx <= (DfsEngineNum*16)) + { + x = idx / 16; + y = idx % 16; + pRadarDetect->DFSParamFromConfig = 0; /* to prevent table be loaded from config file again */ + switch (y) + { + case 1: + pDFSTable->entry[x].mode = (UCHAR)value; + break; + case 2: + pDFSTable->entry[x].avgLen = (USHORT)value; + break; + case 3: + pDFSTable->entry[x].ELow = (USHORT)value; + break; + + case 4: + pDFSTable->entry[x].EHigh = (USHORT)value; + break; + + case 5: + pDFSTable->entry[x].WLow = (USHORT)value; + break; + + case 6: + pDFSTable->entry[x].WHigh = (USHORT)value; + break; + + case 7: + pDFSTable->entry[x].EpsilonW = (UCHAR)value; + break; + + case 8: + pDFSTable->entry[x].TLow = (ULONG)value; + break; + + case 9: + pDFSTable->entry[x].THigh = (ULONG)value; + break; + + case 0xa: + pDFSTable->entry[x].EpsilonT = (UCHAR)value; + break; + + case 0xb: + pDFSTable->entry[x].BLow= (ULONG)value; + break; + + case 0xc: + pDFSTable->entry[x].BHigh = (ULONG)value; + break; + + case 0xd: + pDFSTable->entry[x].EventExpiration= (UINT32)value; + break; + + case 0xe: + pDFSTable->entry[x].PwrJump= (UINT16)value; + break; + + default: + break; + } + + } + else if (idx == (DfsEngineNum*16 +1)) + { + pDfsProgramParam->Symmetric_Round = (UCHAR)value; + } + else if (idx == (DfsEngineNum*16 +2)) + { + pDfsProgramParam->VGA_Mask = (UCHAR)value; + } + else if (idx == (DfsEngineNum*16 +3)) + { + pDfsProgramParam->Packet_End_Mask = (UCHAR)value; + } + else if (idx == (DfsEngineNum*16 +4)) + { + pDfsProgramParam->Rx_PE_Mask = (UCHAR)value; + } + + printk("Delta_Delay(0) = %d\n", pDfsProgramParam->DeltaDelay); + + for (x = 0; x < DfsEngineNum; x++) + { + printk("Channel %lu\n", x); + printk("\t\tmode(%02lu)=%d, M(%02lu)=%03d, EL(%02lu)=%03d EH(%02lu)=%03d, WL(%02lu)=%03d WH(%02lu)=%04d, eW(%02lu)=%02d\n" + "\t\tTL(%02lu)=%05u TH(%02lu)=%06u, eT(%02lu)=%03d, BL(%02lu)=%u, BH(%02lu)=%u\n" + "\t\tEE(%02lu) = %06u, PJ(%02lu) = 0x%02x\n", + (x*16+0x1), (unsigned int)pDFSTable->entry[x].mode, + (x*16+0x2), (unsigned int)pDFSTable->entry[x].avgLen, + (x*16+0x3), (unsigned int)pDFSTable->entry[x].ELow, + (x*16+0x4), (unsigned int)pDFSTable->entry[x].EHigh, + (x*16+0x5), (unsigned int)pDFSTable->entry[x].WLow, + (x*16+0x6), (unsigned int)pDFSTable->entry[x].WHigh, + (x*16+0x7), (unsigned int)pDFSTable->entry[x].EpsilonW, + (x*16+0x8), (unsigned int)pDFSTable->entry[x].TLow, + (x*16+0x9), (unsigned int)pDFSTable->entry[x].THigh, + (x*16+0xa), (unsigned int)pDFSTable->entry[x].EpsilonT, + (x*16+0xb), (unsigned int)pDFSTable->entry[x].BLow, + (x*16+0xc), (unsigned int)pDFSTable->entry[x].BHigh, + (x*16+0xd), (unsigned int)pDFSTable->entry[x].EventExpiration, + (x*16+0xe), (unsigned int)pDFSTable->entry[x].PwrJump ); + } + + printk("Symmetric_Round(%02d) = %d\n", (DfsEngineNum*16 +1), pDfsProgramParam->Symmetric_Round); + printk("VGA_Mask(%02d) = %d\n", (DfsEngineNum*16 +2), pDfsProgramParam->VGA_Mask); + printk("Packet_End_Mask(%02d) = %d\n", (DfsEngineNum*16 +3), pDfsProgramParam->Packet_End_Mask); + printk("Rx_PE_Mask(%02d) = %d\n", (DfsEngineNum*16 +4), pDfsProgramParam->Rx_PE_Mask); + +} + + +void modify_table2(PRTMP_ADAPTER pAd, ULONG idx, ULONG value) +{ + pNewDFSValidRadar pDFSValidRadar; + ULONG x, y; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + + idx--; + + x = idx / 17; + y = idx % 17; + + pDFSValidRadar = &NewDFSValidTable[0]; + + while (pDFSValidRadar->type != NEW_DFS_END) + { + if (pDFSValidRadar->type & pRadarDetect->MCURadarRegion) + { + if (x == 0) + break; + else + { + x--; + pDFSValidRadar++; + } + } + else + pDFSValidRadar++; + } + + if (pDFSValidRadar->type == NEW_DFS_END) + { + printk("idx=%d exceed max number\n", (unsigned int)idx); + return; + } + switch(y) + { + case 0: + pDFSValidRadar->channel = value; + break; + case 1: + pDFSValidRadar->WLow = value; + break; + case 2: + pDFSValidRadar->WHigh = value; + break; + case 3: + pDFSValidRadar->W = value; + break; + case 8: + pDFSValidRadar->WMargin = value; + break; + case 9: + pDFSValidRadar->TLow = value; + break; + case 10: + pDFSValidRadar->THigh = value; + break; + case 11: + pDFSValidRadar->T = value; + break; + case 16: + pDFSValidRadar->TMargin = value; + break; + } + + pDFSValidRadar = &NewDFSValidTable[0]; + while (pDFSValidRadar->type != NEW_DFS_END) + { + if (pDFSValidRadar->type & pRadarDetect->MCURadarRegion) + { + printk("ch = %x --- ", pDFSValidRadar->channel); + printk("wl:wh = %d:%d ", pDFSValidRadar->WLow, pDFSValidRadar->WHigh); + printk("W = %u --- ", pDFSValidRadar->W); + printk("W Margin = %d\n", pDFSValidRadar->WMargin); + printk("Tl:Th = %d:%d ", (unsigned int)pDFSValidRadar->TLow, (unsigned int)pDFSValidRadar->THigh); + printk("T = %lu --- ", pDFSValidRadar->T); + printk("T Margin = %d\n", pDFSValidRadar->TMargin); + } + pDFSValidRadar++; + } + +} + +#ifdef RTMP_MAC_PCI +VOID NewTimerCB_Radar( + IN PRTMP_ADAPTER pAd) +{ + UCHAR channel=0; + UCHAR radarDeclared = 0; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + + if (!DFS_CHECK_FLAGS(pAd, pRadarDetect) || + (pRadarDetect->PollTime == 0)) + return; + + /* to prevent possible re-entries*/ + pRadarDetect->bDfsInit = FALSE; + + pRadarDetect->RadarTimeStampLow++; + + /*511ms*/ + if ((pRadarDetect->RadarTimeStampLow & 0x3f) == 0) + DfsCheckBusyIdle(pAd); + /*if ((pRadarDetect->McuRadarTick++ >= pRadarDetect->PollTime) &&*/ + if ((pRadarDetect->McuRadarTick++ >= 3) && /* 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 + */ + DfsHwDetectionStatusGet(pAd, &channel); + + /*Check if any interrupt trigger by Radar Global Status(Radar Signals)*/ + if ((channel & pRadarDetect->EnabledChMask) && (!pRadarDetect->ch_busy)) + { + radarDeclared = DfsChannelCheck(pAd, channel); + } + + /*reset the radar channel for new counting (Write clear) */ + if (channel & pRadarDetect->EnabledChMask) + DfsResetHwDetectionStatus(pAd); + + if (pRadarDetect->McuRadarDebug & RADAR_SIMULATE) + { + radarDeclared = 1; + pRadarDetect->McuRadarDebug &= ~RADAR_SIMULATE; + } + + if ((radarDeclared || pRadarDetect->radarDeclared) && (pRadarDetect->ch_busy_countdown == -1)) + pRadarDetect->ch_busy_countdown = 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; + } + pRadarDetect->bDfsInit = TRUE; +} + +#define DFS_EVENT_DATA_FETCH(__pAd, __pRadarDetect, __DfsEvent) \ + DfsEventDataFetch(__pAd, __pRadarDetect, &__DfsEvent) + +static VOID SwCheckDfsEvent( + IN PRTMP_ADAPTER pAd) +{ + INT k, limit = 64; + UCHAR id = 0; + DFS_EVENT DfsEvent; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam; + + pRadarDetect->McuRadarTick = 0; + + /* disable debug mode to read debug port */ + DfsCaptureModeControl(pAd, FALSE, TRUE, FALSE); + + pDfsSwParam->dfs_w_counter++; + + for (k = 0; k < limit; k++) + { + /* fetch event data */ + if (DFS_EVENT_DATA_FETCH(pAd, pRadarDetect, DfsEvent) == FALSE) + break; + + if (DfsEventDrop(pAd, &DfsEvent) == TRUE) + continue; + + if (pRadarDetect->use_tasklet) + { + id = DfsEvent.EngineId; + + if (id < pAd->chipCap.DfsEngineNum) + { + pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].counter = pDfsSwParam->dfs_w_counter; + pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].timestamp = DfsEvent.TimeStamp; + pDfsSwParam->DFS_W[id][pDfsSwParam->dfs_w_idx[id]].width = DfsEvent.Width; + + if (pRadarDetect->McuRadarDebug & RADAR_DEBUG_EVENT) + { + printk("counter = %lu ", pDfsSwParam->dfs_w_counter); + DFS_EVENT_PRINT(DfsEvent); + } + + pDfsSwParam->dfs_w_last_idx[id] = pDfsSwParam->dfs_w_idx[id]; + pDfsSwParam->dfs_w_idx[id]++; + if (pDfsSwParam->dfs_w_idx[id] >= NEW_DFS_DBG_PORT_ENT_NUM) + pDfsSwParam->dfs_w_idx[id] = 0; + } + } + } + + if (pRadarDetect->use_tasklet) + { + /* set hw_idx*/ + pDfsSwParam->hw_idx[0] = pDfsSwParam->dfs_w_idx[0]; + pDfsSwParam->hw_idx[1] = pDfsSwParam->dfs_w_idx[1]; + pDfsSwParam->hw_idx[2] = pDfsSwParam->dfs_w_idx[2]; + pDfsSwParam->hw_idx[3] = pDfsSwParam->dfs_w_idx[3]; + /*dfs tasklet will call SWRadarCheck*/ + schedule_dfs_task(pAd); + } + + /* enable debug mode*/ + DfsCaptureModeControl(pAd, TRUE, TRUE, FALSE); +} +#endif /* RTMP_MAC_PCI */ + +#endif /*CONFIG_AP_SUPPORT*/ +#endif /* DFS_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_info.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_info.c new file mode 100644 index 000000000..415c3bff1 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_info.c @@ -0,0 +1,9797 @@ +/**************************************************************************** + * 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" +#include "ap.h" +#ifdef NEW_IXIA_METHOD +char *tdrop_reason[MAX_TDROP_RESON] = { + "NULL", + "INVALID_PKT_LEN", + "INVALID_TR_WCID", + "INVALID_TR_ENTRY", + "INVALID_WDEV", + "INVALID_ETH_TYPE", + "DROP_PORT_SECURE", + "DROP_PSQ_FULL", + "DROP_TXQ_FULL", + "DROP_TX_JAM", + "DROP_TXQ_ENQ_FAIL", + "DROP_TXQ_ENQ_PS ", + "DROP_HW_RESET", + "DROP_80211H_MODE", + "DROP_BLK_INFO_ERROR", +}; +char *rdrop_reason[MAX_RDROP_RESON] = { + "RPKT_SUCCESS", + "ALREADY_IN_ORDER", + "DUP_SEQ_PKT", + "DROP_OLD_PKT", + "DROP_NO_BUF", + "DROP_DUP_FRAME", + "DROP_NOT_ALLOW", + "DROP_RING_FULL", + "DROP_DATA_SIZE", + "DROP_INFO_NULL", + "DROP_RXD_ERROR", +}; +#endif + +#ifdef APCLI_OWE_SUPPORT +#define OWETRANSIE_LINE_LEN (10) /*OWETranIe*/ +#endif + +#ifdef DYNAMIC_WMM +INT SetDynamicWMM(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->CommonCfg.DynamicWmm = (UCHAR) simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("CURRENT: Set DynamicWMM = %d \n", pAd->CommonCfg.DynamicWmm)); + + return TRUE; +} +#endif + +#ifdef INTERFERENCE_RA_SUPPORT +INT SetInterfRA(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->CommonCfg.Interfra = (UCHAR) simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("CURRENT: Set InterfRA = %d \n", pAd->CommonCfg.Interfra)); + + return TRUE; +} +#endif /* DYNAMIC_WMM */ + + +#ifdef MT_MAC +INT SetManualTxOP(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->CommonCfg.ManualTxop = (UCHAR) simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("CURRENT: Set ManualTxOP = %d \n", pAd->CommonCfg.ManualTxop)); + + return TRUE; +} + + +INT SetManualTxOPThreshold(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->CommonCfg.ManualTxopThreshold = (UCHAR) simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("CURRENT: Set ManualTxOP TP Threshold = %lu (Mbps)\n", pAd->CommonCfg.ManualTxopThreshold)); + + return TRUE; +} + + +INT SetManualTxOPUpBound(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->CommonCfg.ManualTxopUpBound = (UCHAR) simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("CURRENT: Set ManualTxOP Traffic Upper Bound = %d (Ratio)\n", pAd->CommonCfg.ManualTxopUpBound)); + + return TRUE; +} + + +INT SetManualTxOPLowBound(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->CommonCfg.ManualTxopLowBound = (UCHAR) simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("CURRENT: Set ManualTxOP Traffic Low Bound = %d (Ratio)\n", pAd->CommonCfg.ManualTxopLowBound)); + + return TRUE; +} +#endif /* MT_MAC */ + +/* + ========================================================================== + Description: + Get Driver version. + + Return: + ========================================================================== +*/ +INT Set_DriverVersion_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + DBGPRINT(RT_DEBUG_OFF, ("Driver Patch\n")); + DBGPRINT(RT_DEBUG_OFF, ("001 : 4AC + MGMT PSE queue pkt stuck detect & AP tr_entry is memory currupted\n")); + DBGPRINT(RT_DEBUG_OFF, ("002 : wifi_forward support\n")); + DBGPRINT(RT_DEBUG_OFF, ("\n")); +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef DBG +#ifdef CONFIG_ANDES_SUPPORT + if (pAd->chipCap.MCUType == ANDES) { + UINT32 loop = 0; + RTMP_CHIP_CAP *cap = &pAd->chipCap; + + if (pAd->chipCap.need_load_fw) { + USHORT fw_ver, build_ver; + fw_ver = (*(cap->FWImageName + 11) << 8) | (*(cap->FWImageName + 10)); + build_ver = (*(cap->FWImageName + 9) << 8) | (*(cap->FWImageName + 8)); + + DBGPRINT(RT_DEBUG_OFF, ("fw version:%d.%d.%02d ", (fw_ver & 0xf000) >> 8, + (fw_ver & 0x0f00) >> 8, fw_ver & 0x00ff)); + DBGPRINT(RT_DEBUG_OFF, ("build:%x\n", build_ver)); + DBGPRINT(RT_DEBUG_OFF, ("build time:")); + + for (loop = 0; loop < 16; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->FWImageName + 16 + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + } + + if (pAd->chipCap.need_load_rom_patch) { + DBGPRINT(RT_DEBUG_OFF, ("rom patch version = \n")); + + for (loop = 0; loop < 4; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->rom_patch + 24 + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("build time = \n")); + + for (loop = 0; loop < 16; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->rom_patch + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + } + } +#endif /* CONFIG_ANDES_SUPPORT */ +#endif /* DBG */ + 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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + int retval; + +#ifdef EXT_BUILD_CHANNEL_LIST + return -EOPNOTSUPP; +#endif /* EXT_BUILD_CHANNEL_LIST */ + + retval = RT_CfgSetCountryRegion(pAd, arg, BAND_5G); + if (retval == FALSE) + return FALSE; + + /* if set country region, driver needs to be reset*/ + BuildChannelList(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_CountryRegionABand_Proc::(CountryRegion=%d)\n", pAd->CommonCfg.CountryRegionForABand)); + + return TRUE; +} + + +INT Set_Cmm_WirelessMode_Proc( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *arg, + IN BOOLEAN FlgIsDiffMbssModeUsed) +{ + INT success = TRUE; +#ifdef CONFIG_AP_SUPPORT + UINT32 i = 0; +#ifdef MBSS_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (FlgIsDiffMbssModeUsed) { + LONG cfg_mode = simple_strtol(arg, 0, 10); + + /* assign wireless mode for the BSS */ + pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.PhyMode = + cfgmode_2_wmode((UCHAR)cfg_mode); + + /* + If the band is different with other BSS, we will correct it in + RT_CfgSetMbssWirelessMode() + */ + success = RT_CfgSetMbssWirelessMode(pAd, arg); + } + else +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + success = RT_CfgSetWirelessMode(pAd, arg); + + if (success) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* recover Wmm Capable for "each" BSS */ + /* all phy mode of MBSS are the same */ + for(i=0; iApCfg.BssidNum; i++) + { + pAd->ApCfg.MBSSID[i].wdev.bWmmCapable = \ + pAd->ApCfg.MBSSID[i].bWmmCapableOrg; + +#ifdef MBSS_SUPPORT + /* In Same-MBSS Mode, all phy modes are the same */ + if (FlgIsDiffMbssModeUsed == 0) + pAd->ApCfg.MBSSID[i].wdev.PhyMode = pAd->CommonCfg.PhyMode; +#endif /* MBSS_SUPPORT */ + } + + RTMPSetPhyMode(pAd, pAd->CommonCfg.PhyMode); + } +#endif /* CONFIG_AP_SUPPORT */ + + + +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("Set_Cmm_WirelessMode_Proc::(=%d)\n", pAd->CommonCfg.PhyMode)); + DBGPRINT(RT_DEBUG_TRACE, ("Set_Cmm_WirelessMode_Proc::(BSS%d=%d)\n", + pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.PhyMode)); + + for(i=0; iApCfg.BssidNum; i++) + { + /* + When last mode is not 11B-only, new mode is 11B, we need to re-make + beacon frame content. + + Because we put support rate/extend support rate element in + APMakeBssBeacon(), not APUpdateBeaconFrame(). + */ + APMakeBssBeacon(pAd, i); + } +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("Set_WirelessMode_Proc::parameters out of range\n")); + } + + return success; +} + + +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT +/* + ========================================================================== + Description: + Set Wireless Mode for MBSS + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_MBSS_WirelessMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + return Set_Cmm_WirelessMode_Proc(pAd, arg, 1); +} +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +/* + ========================================================================== + Description: + Set Wireless Mode + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_WirelessMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + return Set_Cmm_WirelessMode_Proc(pAd, arg, 0); +} + +#ifdef MULTI_CLIENT_SUPPORT +INT Set_ManualMultiClientOn_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG dbg; + + DBGPRINT_S(("==>%s()\n", __FUNCTION__)); + + dbg = simple_strtol(arg, 0, 10); + + pAd->bManualMultiClientOn = dbg; + + DBGPRINT_S(("<==%s(ManualMultiClientOn = %d)\n", __FUNCTION__, pAd->bManualMultiClientOn)); + + return TRUE; +} + +INT Set_MultiClientOnMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG dbg; + + DBGPRINT_S(("==>%s()\n", __FUNCTION__)); + + dbg = simple_strtol(arg, 0, 10); + + pAd->MultiClientOnMode = dbg; + + DBGPRINT_S(("<==%s(MultiClientOnMode = %d)\n", __FUNCTION__, pAd->MultiClientOnMode)); + + return TRUE; +} + +UINT RtsRetryCnt = 7; + +INT Set_RtsRetryCnt_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG dbg; + + DBGPRINT_S(("==>%s()\n", __FUNCTION__)); + + dbg = simple_strtol(arg, 0, 10); + if( dbg <= 0xf) + RtsRetryCnt = dbg; + + DBGPRINT_S(("<==%s(RtsRetryCnt = %d)\n", __FUNCTION__, RtsRetryCnt)); + + return TRUE; +} + +INT MidRateRssi = -76; + +INT Set_MidRate_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT dbg; + + DBGPRINT_S(("==>%s()\n", __FUNCTION__)); + + dbg = simple_strtol(arg, 0, 10); + MidRateRssi = 0 - dbg; + + DBGPRINT_S(("<==%s(MidRateRssi = %d)\n", __FUNCTION__, MidRateRssi)); + + return TRUE; +} + +INT FarRateRssi = -82; + +INT Set_FarRate_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT dbg; + + DBGPRINT_S(("==>%s()\n", __FUNCTION__)); + + dbg = simple_strtol(arg, 0, 10); + FarRateRssi = 0 - dbg; + + DBGPRINT_S(("<==%s(FarRateRssi = %d)\n", __FUNCTION__, FarRateRssi)); + + return TRUE; +} + +INT FarDropRssi = -127; + +INT Set_FarDropRssi_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT dbg; + + DBGPRINT_S(("==>%s()\n", __FUNCTION__)); + + dbg = simple_strtol(arg, 0, 10); + FarDropRssi = 0 - dbg; + + DBGPRINT_S(("<==%s(FarRateRssi = %d)\n", __FUNCTION__, FarDropRssi)); + + return TRUE; +} + +extern int TX_IDLE_TIME; +INT Set_TIMIdle_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT dbg; + + DBGPRINT_S(("==>%s()\n", __FUNCTION__)); + + dbg = simple_strtol(arg, 0, 10); + TX_IDLE_TIME = dbg; + + DBGPRINT_S(("<==%s(TX_IDLE_TIME = %d)\n", __FUNCTION__, TX_IDLE_TIME)); + + return TRUE; +} + +INT Set_TxSwQMaxLen_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT dbg; + + DBGPRINT_S(("==>%s()\n", __FUNCTION__)); + + dbg = simple_strtol(arg, 0, 10); + pAd->TxSwQMaxLen = dbg; + + DBGPRINT_S(("<==%s(pAd->TxSwQMaxLen = %d)\n", __FUNCTION__, pAd->TxSwQMaxLen)); + + return TRUE; + +} + +INT FalseCCAthSelRaTable = 1500; +INT Set_FalseCCARateTable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT dbg; + + DBGPRINT_S(("==>%s()\n", __FUNCTION__)); + + dbg = simple_strtol(arg, 0, 10); + FalseCCAthSelRaTable = dbg; + + DBGPRINT_S(("<==%s(FalseCCAThreshold = %d)\n", __FUNCTION__, FalseCCAthSelRaTable)); + + return TRUE; + +} +#endif + +INT PingFixRate = 1; +INT Set_PingFixRate_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT dbg; + + DBGPRINT_S(("==>%s()\n", __FUNCTION__)); + + dbg = simple_strtol(arg, 0, 10); + PingFixRate = dbg; + + DBGPRINT_S(("<==%s(PingFixRate = %d)\n", __FUNCTION__, PingFixRate)); + + return TRUE; + +} + + +#ifdef WH_EZ_SETUP +INT ap_phy_rrm_init_byRf(RTMP_ADAPTER *pAd, UCHAR RfIC); +#endif + +/* + ========================================================================== + Description: + Set Channel + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Channel_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ +#ifdef CONFIG_AP_SUPPORT + INT32 i; +#endif /* CONFIG_AP_SUPPORT */ + INT32 Success = TRUE; + UCHAR Channel; + UCHAR RFChannel; + + Channel = (UCHAR) simple_strtol(arg, 0, 10); + + pAd->CommonCfg.Channel = Channel; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if (pAd->ApCfg.ApCliAutoConnectChannelSwitching == FALSE) + pAd->ApCfg.ApCliAutoConnectChannelSwitching = TRUE; +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + /* check if this channel is valid*/ + if (ChannelSanity(pAd, Channel) == TRUE) + { + 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_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if ((WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + && (pAd->CommonCfg.bIEEE80211H == TRUE)) + { + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (pAd->ChannelList[i].Channel == Channel) + { + if (pAd->ChannelList[i].RemainingTimeForUse > 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: previous detection of a radar on this channel(Channel=%d)\n", Channel)); + Success = FALSE; + break; + } + else + { + DBGPRINT(RT_DEBUG_INFO, ("RemainingTimeForUse %d ,Channel %d\n", + pAd->ChannelList[i].RemainingTimeForUse, Channel)); + } + } + } + } + + if (Success == TRUE) + { + if ((pAd->CommonCfg.Channel > 14 ) + && (pAd->CommonCfg.bIEEE80211H == TRUE)) + { + pAd->Dot11_H.org_ch = pAd->CommonCfg.Channel; + } + + pAd->CommonCfg.Channel = Channel; //lk added + +#ifdef DOT11_N_SUPPORT + N_ChannelCheck(pAd); + + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + RFChannel = N_SetCenCh(pAd, pAd->CommonCfg.Channel); + else +#endif /* DOT11_N_SUPPORT */ + RFChannel = pAd->CommonCfg.Channel; + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): CtrlChannel(%d), CentralChannel(%d) \n", + __FUNCTION__, pAd->CommonCfg.Channel, + pAd->CommonCfg.CentralChannel)); + + if ((pAd->CommonCfg.Channel > 14 ) + && (pAd->CommonCfg.bIEEE80211H == TRUE)) + { + if (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) + { + AsicSwitchChannel(pAd, RFChannel, FALSE); +#ifdef CONFIG_MAP_SUPPORT + if (!IS_MAP_ENABLE(pAd) || !pAd->bMAPQuickChChangeEn) { +#endif + APStop(pAd); + APStartUp(pAd); +#ifdef CONFIG_MAP_SUPPORT + } else { +for (i = 0; i < WDEV_NUM_MAX; i++) { + if (pAd->wdev_list[i] != NULL && + pAd->wdev_list[i]->wdev_type == WDEV_TYPE_AP) { + MacTableResetWdev(pAd, pAd->wdev_list[i]); + } +} +ap_phy_rrm_init(pAd); + } +#endif + } + else + { + NotifyChSwAnnToPeerAPs(pAd, ZERO_MAC_ADDR, pAd->CurrentAddress, 1, pAd->CommonCfg.Channel); + pAd->Dot11_H.RDMode = RD_SWITCHING_MODE; + pAd->Dot11_H.CSCount = 0; + pAd->Dot11_H.new_channel = Channel; + } + } + else + { +#ifdef CONFIG_MAP_SUPPORT + if (!IS_MAP_ENABLE(pAd) || !pAd->bMAPQuickChChangeEn) { +#endif + AsicSwitchChannel(pAd, RFChannel, FALSE); + APStop(pAd); + APStartUp(pAd); +#ifdef CONFIG_MAP_SUPPORT + } else { +for (i = 0; i < WDEV_NUM_MAX; i++) { + if (pAd->wdev_list[i] != NULL && pAd->wdev_list[i]->wdev_type == WDEV_TYPE_AP) + MacTableResetWdev(pAd, pAd->wdev_list[i]); +} +ap_phy_rrm_init(pAd); + } +#endif + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + + if (Success == TRUE) + DBGPRINT(RT_DEBUG_TRACE, ("Set_Channel_Proc::(Channel=%d)\n", pAd->CommonCfg.Channel)); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_AUTO_CONNECT_SUPPORT + pAd->ApCfg.ApCliAutoConnectChannelSwitching = FALSE; +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + return Success; +} + +#ifdef CONFIG_MAP_SUPPORT +/* +* ========================================================================== +* Description: +* Enable/disable quick Channel change feature +* Return: +* TRUE if all parameters are OK, FALSE otherwise +* ========================================================================== +*/ +INT Set_Map_Channel_En_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR MapChannelEn = (UCHAR) simple_strtol(arg, 0, 10); + + pAd->bMAPQuickChChangeEn = MapChannelEn; + return TRUE; +} + + +/* +* ========================================================================== +* Description: +* Set Channel quickly without AP start/stop +* Return: +* TRUE if all parameters are OK, FALSE otherwise +* ========================================================================== +*/ +INT Set_Map_Channel_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + if (pAd->bMAPQuickChChangeEn == FALSE) + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("MAPQuickChChange feaure not enabled!!")); + + return Set_Channel_Proc(pAd, arg); +} +#endif + + +INT Set_SendBMToAir_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT32 Success = TRUE; + BOOLEAN Send; + + Send = (UCHAR) simple_strtol(arg, 0, 10); + + pAd->BSendBMToAir = Send; + if(pAd->BSendBMToAir) + DBGPRINT(RT_DEBUG_OFF, ("Set_SendBMToAir_Proc Enable B/M Pkts to air\n")); + else + DBGPRINT(RT_DEBUG_OFF, ("Set_SendBMToAir_Proc Disable B/M Pkts to air\n")); + + return Success; +} + + +/* + ========================================================================== + Description: + Set Short Slot Time Enable or Disable + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ShortSlot_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + LONG TxPower; + INT success = FALSE; +#ifdef NEW_IXIA_METHOD + UINT32 valo = 0, valn = 0; +#endif + 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 */ + + success = TRUE; + } + else + success = FALSE; +#ifdef NEW_IXIA_METHOD + if ((pAd->protectpara & 0x2) == 0x2) {/*Don't drop CCK power*/ + RTMP_IO_READ32(pAd, TMAC_FP0R3, &valo); + valo &= ~LG_OFDM4_FRAME_POWER0_DBM_MASK; + valo &= ~HT40_6_FRAME_POWER0_DBM_MASK; + DBGPRINT(RT_DEBUG_OFF, ("Percentage Before TMAC_FP0R3 = 0x%x\n", valo)); + } +#endif +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + CmdSetTxPowerCtrl(pAd, pAd->hw_cfg.cent_ch); + } +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("Set_TxPower_Proc::(TxPowerPercentage=%ld)\n", pAd->CommonCfg.TxPowerPercentage)); +#ifdef NEW_IXIA_METHOD + if ((TxPower != 100) && ((pAd->protectpara & 0x2) == 0x2)) { /*Don't drop CCK power*/ + RTMP_IO_READ32(pAd, TMAC_FP0R3, &valn); + valn &= ~CCK0_FRAME_POWER0_DBM_MASK; + valn &= ~CCK1_FRAME_POWER0_DBM_MASK; + valn |= valo; + RTMP_IO_WRITE32(pAd, TMAC_FP0R3, valn); + DBGPRINT(RT_DEBUG_OFF, ("Percentage Before TMAC_FP0R3 = 0x%x\n", valn)); + } +#endif + return success; +} + +INT Set_MaxTxPwr_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR MaxTxPwr = 0; + + MaxTxPwr = (UCHAR) simple_strtol(arg, 0, 10); + + if ((MaxTxPwr > 0) && (MaxTxPwr < 0xff)) { + pAd->MaxTxPwr = MaxTxPwr; + BuildChannelList(pAd); + DBGPRINT(RT_DEBUG_OFF, ("Set MaxTxPwr = %d\n", MaxTxPwr)); + return TRUE; + } + + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: wrong power announced(MaxTxPwr=%d)\n", MaxTxPwr)); + return FALSE; + +} + +/* + ========================================================================== + Description: + Set 11B/11G Protection + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_BGProtection_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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; + break; + case Rt802_11PreambleLong: + pAd->CommonCfg.TxPreamble = Preamble; + 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(RTMP_ADAPTER *pAd, RTMP_STRING *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; + 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(RTMP_ADAPTER *pAd, RTMP_STRING *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; + } + + + 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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + LONG aggre; + + aggre = simple_strtol(arg, 0, 10); + + if (aggre == 1) + pAd->CommonCfg.bAggregationCapable = TRUE; + else if (aggre == 0) + pAd->CommonCfg.bAggregationCapable = FALSE; + else + return FALSE; /*Invalid argument */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef PIGGYBACK_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + pAd->CommonCfg.bPiggyBackCapable = pAd->CommonCfg.bAggregationCapable; + RTMPSetPiggyBack(pAd, pAd->CommonCfg.bPiggyBackCapable); + } +#endif /* PIGGYBACK_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_PktAggregate_Proc::(AGGRE=%d)\n", pAd->CommonCfg.bAggregationCapable)); + + return TRUE; +} +#endif + + +#ifdef INF_PPA_SUPPORT +INT Set_INF_AMAZON_SE_PPA_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + UINT status; + UCHAR aggre; + UINT32 g_if_id; + NDIS_STATUS re_val; + + aggre = simple_strtol(arg, 0, 10); + + if (ppa_hook_directpath_register_dev_fn == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s::There is no PPA module\n", __FUNCTION__)); + return FALSE; + } + + if (aggre == 1) + { + if (pAd->PPAEnable == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("PPA already enabled\n")); + } + else + { + if (pAd->pDirectpathCb == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("Allocate memory for pDirectpathCb\n")); + re_val = os_alloc_mem(NULL, (UCHAR **)&(pAd->pDirectpathCb), sizeof(PPA_DIRECTPATH_CB)); + + if (re_val != NDIS_STATUS_SUCCESS) + return FALSE; + } + + /* Register callback */ + pAd->pDirectpathCb->rx_fn = ifx_ra_start_xmit; + pAd->pDirectpathCb->stop_tx_fn = NULL; + pAd->pDirectpathCb->start_tx_fn = NULL; + + status = ppa_hook_directpath_register_dev_fn( + &g_if_id, pAd->net_dev, pAd->pDirectpathCb, PPA_F_DIRECTPATH_REGISTER|PPA_F_DIRECTPATH_ETH_IF); + + if (status == IFX_SUCCESS) + { + pAd->g_if_id = g_if_id; + pAd->PPAEnable = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("Register PPA success::ret=%d, id=%d\n", status, pAd->g_if_id)); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Register PPA fail::ret=%d\n", status)); + } + } + else if (aggre == 0) + { + if (pAd->PPAEnable == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("PPA already disabled\n")); + } + else + { + g_if_id = pAd->g_if_id; + status = ppa_hook_directpath_register_dev_fn(&g_if_id, pAd->net_dev, NULL, 0 /*PPA_F_DIRECTPATH_REGISTER*/); + + if (status == IFX_SUCCESS) + { + pAd->g_if_id = 0; + pAd->PPAEnable = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("Unregister PPA success::ret=%d, if_id=%d\n", status, pAd->g_if_id)); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("Unregister PPA fail::ret=%d\n", status)); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s::Invalid argument=%d\n", __FUNCTION__, aggre)); + return FALSE; + } + + return TRUE; +} +#endif /* INF_PPA_SUPPORT */ + + +/* + ========================================================================== + Description: + Set IEEE80211H. + This parameter is 1 when needs radar detection, otherwise 0 + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_IEEE80211H_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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, sizeof(pAd->CommonCfg.CountryCode)); + 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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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((RTMP_STRING *) ChRegion[loop].CountReg, "") != 0) + { + if (strncmp((RTMP_STRING *) 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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + PCH_REGION pChRegion = NULL; + UCHAR EntryIdx, CountryCode[3]={0}; + + /* Get Channel Region (CountryCode)*/ + { + INT loop = 0; + + while (strcmp((RTMP_STRING *) ChRegion[loop].CountReg, "") != 0) + { + if (strncmp((RTMP_STRING *) 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(RTMP_ADAPTER *pAd, RTMP_STRING *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((RTMP_STRING *) ChRegion[loop].CountReg, "") != 0) + { + if (strncmp((RTMP_STRING *) 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(RTMP_ADAPTER *pAd, RTMP_STRING *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 */ + + + + 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); + } + + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscGenPinCode_Proc:: Enrollee PinCode\t\t%08u\n", pWscControl->WscEnrolleePinCode)); + + return TRUE; +} + +#ifdef BB_SOC +INT Set_WscResetPinCode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + PWSC_CTRL pWscControl = NULL; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + { + pWscControl = &pAd->ApCfg.MBSSID[apidx].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) Set_WscResetPinCode_Proc:: This command is from ra interface now.\n", apidx)); + } + + pWscControl->WscEnrolleePinCode = GenerateWpsPinCode(pAd, 0, apidx); + } +#endif // CONFIG_AP_SUPPORT // + + DBGPRINT(RT_DEBUG_TRACE, ("Set_WscResetPinCode_Proc:: Enrollee PinCode\t\t%08u\n", pWscControl->WscEnrolleePinCode)); + + return TRUE; +} +#endif + +INT Set_WscVendorPinCode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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 */ + + + + if (!pWscControl) + return FALSE; + else + return RT_CfgSetWscPinCode(pAd, arg, pWscControl); +} +#endif /* WSC_INCLUDED */ + + +#ifdef DBG +INT rx_temp_dbg = 0; + +/* + ========================================================================== + Description: + For Debug information + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_Debug_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG dbg; + + DBGPRINT_S(("==>%s()\n", __FUNCTION__)); + + dbg = simple_strtol(arg, 0, 10); + if( dbg <= RT_DEBUG_MAX) + RTDebugLevel = dbg; + + DBGPRINT_S(("<==%s(RTDebugLevel = %ld)\n", __FUNCTION__, RTDebugLevel)); + + return TRUE; +} + +INT Set_Ap_Probe_Rsp_Times(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + INT input; + + input = simple_strtol(arg, 0, 10); + + if ((input >= 1) && (input <= 10)) + pAd->ApCfg.MBSSID[apidx].ProbeRspTimes = input; + else{ + DBGPRINT(RT_DEBUG_ERROR, ("AP[%d]->ProbeRspTimes: Out of Range\n", apidx)); + return FALSE; + } + DBGPRINT(RT_DEBUG_TRACE, ("AP[%d]->ProbeRspTimes: %d\n", apidx, pAd->ApCfg.MBSSID[apidx].ProbeRspTimes)); + + return TRUE; +} + +/* + ========================================================================== + Description: + For DebugFunc information + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_DebugFunc_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG func; + DBGPRINT_S(("==>%s()\n", __FUNCTION__)); + + func = simple_strtol(arg, 0, 10); + if (func <= 0xffffff) + func <<= 8; + RTDebugFunc = func; + DBGPRINT_S(("Set RTDebugFunc = 0x%lx\n", RTDebugFunc)); + + return TRUE; +} + + +static BOOLEAN ascii2hex(RTMP_STRING *in, UINT32 *out) +{ + UINT32 hex_val, val; + CHAR *p, asc_val; + + hex_val = 0; + p = (char *)in; + while((*p) != 0) + { + val = 0; + asc_val = *p; + if ((asc_val >= 'a') && (asc_val <= 'f')) + val = asc_val - 87; + else if ((*p >= 'A') && (asc_val <= 'F')) + val = asc_val - 55; + else if ((asc_val >= '0') && (asc_val <= '9')) + val = asc_val - 48; + else + return FALSE; + + hex_val = (hex_val << 4) + val; + p++; + } + *out = hex_val; + + return TRUE; +} + + +/* + ========================================================================== + 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(RTMP_ADAPTER *pAd, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + RTMP_STRING *seg_str, *addr_str, *val_str, *range_str; + RTMP_STRING *mpool, *msg; + RTMP_STRING *arg, *ptr; + UINT32 macAddr, macVal = 0; + UINT32 macValue; + BOOLEAN bIsPrintAllMAC = FALSE, bFromUI, is_write, is_range; + UINT32 IdMac, mac_s = 0x1000, mac_e = 0x1700, mac_range = 0xffff; + + + os_alloc_mem(NULL, (UCHAR **)&mpool, sizeof(CHAR)*(4096+256+12)); + if (!mpool) + return; + + +#if defined(MT7603) || defined(MT7628) || defined(MT7636) + if (IS_MT7603(pAd) || IS_MT7628(pAd) || IS_MT7636(pAd)) + mac_range = 0xcffff; +#endif /* MT7603 */ + + bFromUI = ((wrq->u.data.flags & RTPRIV_IOCTL_FLAG_UI) == RTPRIV_IOCTL_FLAG_UI) ? TRUE : FALSE; + + msg = (RTMP_STRING *)((ULONG)(mpool+3) & (ULONG)~0x03); + arg = (RTMP_STRING *)((ULONG)(msg+4096+3) & (ULONG)~0x03); + + memset(msg, 0x00, 4096); + memset(arg, 0x00, 256); + + if (wrq->u.data.length > 1) { +#ifdef LINUX + copy_from_user(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length); +#else + NdisMoveMemory(arg, wrq->u.data.pointer, (wrq->u.data.length > 255) ? 255 : wrq->u.data.length); +#endif /* LINUX */ + arg[255] = 0x00; + } + + ptr = arg; + if ((ptr!= NULL) && (strlen(ptr) > 0)) { + while ((*ptr != 0) && (*ptr == 0x20)) // remove space + ptr++; + } + + + DBGPRINT(RT_DEBUG_TRACE, ("%s():wrq->u.data.length=%d, pointer(%p)=%s!\n", + __FUNCTION__, wrq->u.data.length, + wrq->u.data.pointer, wrq->u.data.pointer)); + if ((ptr == NULL) || strlen(ptr) == 0) { + bIsPrintAllMAC = TRUE; + goto print_all; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s():after trim space, ptr len=%d, pointer(%p)=%s!\n", + __FUNCTION__, strlen(ptr), ptr, ptr)); + + + + { + while ((seg_str = strsep((char **)&ptr, ",")) != NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("seg_str[%d]=%s\n", strlen(seg_str), seg_str)); + is_write = FALSE; + addr_str = seg_str; + val_str = NULL; + if ((val_str = strchr(seg_str, '=')) != NULL) { + *val_str++ = 0; + is_write = 1; + } else { + is_write = 0; + } + + if (addr_str) { + if ((range_str = strchr(addr_str, '-')) != NULL) { + *range_str++ = 0; + is_range = 1; + } else { + is_range = 0; + } + + if ((ascii2hex(addr_str, &mac_s) == FALSE)) { + DBGPRINT(RT_DEBUG_ERROR, ("Invalid MAC CR Addr, str=%s\n", addr_str)); + break; + } + +#if defined(MT7603) || defined(MT7628) || defined(MT7636) + if (IS_MT7603(pAd) || IS_MT7628(pAd) || IS_MT7636(pAd)) + mt_mac_cr_range_mapping(&mac_s); +#endif + if (mac_s >= mac_range) { + DBGPRINT(RT_DEBUG_ERROR, ("MAC CR Addr[0x%x] out of range[0x%x], str=%s\n", + mac_s, mac_range, addr_str)); + break; + } + + if (is_range) { + if (ascii2hex(range_str, &mac_e) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, ("Invalid Range End MAC CR Addr[0x%x], str=%s\n", + mac_e, range_str)); + break; + } + +#if defined(MT7603) || defined(MT7628) || defined(MT7636) + if (IS_MT7603(pAd) || IS_MT7628(pAd) || IS_MT7636(pAd)) + mt_mac_cr_range_mapping(&mac_e); +#endif + if (mac_e >= mac_range) { + DBGPRINT(RT_DEBUG_ERROR, ("MAC CR Addr[0x%x] out of range[0x%x], str=%s\n", + mac_e, mac_range, range_str)); + break; + } + + if (mac_e < mac_s) { + DBGPRINT(RT_DEBUG_ERROR, ("Invalid Range MAC Addr[%s - %s] => [0x%x - 0x%x]\n", + addr_str, range_str, mac_s, mac_e)); + break; + } + } else { + mac_e = mac_s; + } + } + + if (val_str) { + if ((strlen(val_str) == 0) || ascii2hex(val_str, &macVal) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, ("Invalid MAC value[0x%s]\n", val_str)); + break; + } + } + + if (is_write) { + RTMP_IO_WRITE32(pAd, mac_s, macVal); + sprintf(msg+strlen(msg), "[0x%04x]:%08x ", mac_s, macVal); + if (!bFromUI) + DBGPRINT(RT_DEBUG_INFO, ("MacAddr=0x%x, MacValue=0x%x\n", mac_s, macVal)); + } else { + for(IdMac = mac_s; IdMac <= mac_e; IdMac += 4) + { + RTMP_IO_READ32(pAd, IdMac, &macVal); + sprintf(msg+strlen(msg), "[0x%04x]:%08x ", IdMac , macVal); + if (!bFromUI) + DBGPRINT(RT_DEBUG_TRACE, ("MacAddr=0x%x, MacValue=0x%x\n", IdMac, macVal)); + } + } + + + if (ptr) + DBGPRINT(RT_DEBUG_TRACE, ("NextRound: ptr[%d]=%s\n", strlen(ptr), ptr)); + } + + } + +print_all: + if (bIsPrintAllMAC) + { + int mac_idx = 0; + + mac_s = 0x1000; + mac_e = 0x1700; + +#if defined(MT7603) || defined(MT7628) || defined(MT7636) + if (IS_MT7603(pAd) || IS_MT7628(pAd) || IS_MT7636(pAd)) { + static UINT32 mac_range_7603[]={ + 0x20000, 0x201ff, /* WF_CFG: 0x6000_0000 ~ 0x6000_01FF */ + WF_TRB_BASE, 0x211ff, /* WF_TRB: 0x6010_0000 ~ 0x6010_01FF */ + WF_AGG_BASE, 0x213ff, /* WF_AGG: 0x6011_0000 ~ 0x6011_01FF */ + WF_ARB_BASE, 0x214ff, /* WF_ARB: 0x6012_0000 ~ 0x6012_01FF */ + WF_TMAC_BASE, 0x216ff, /* WF_TMAC: 0x6013_0000 ~ 0x6013_01FF */ + WF_RMAC_BASE, 0x21908, /* WF_RMAC: 0x6014_0000 ~ 0x6014_01FF */ + WF_SEC_BASE, 0x21A04, /* WF_SEC: 0x6015_0000 ~ 0x6015_01FF */ + WF_DMA_BASE, 0x21C88, /* WF_DMA: 0x6016_0000 ~ 0x6016_0088 */ + //0x21E00, 0x1740, /* WF_CFGOFF: 0x6015_0000 ~ 0x6015_01FF */ + //0x22000, 0x1740, /* WF_PF: 0x6015_0000 ~ 0x6015_01FF */ + //0x23000, 0x1740, /* WF_WTBLOFF: 0x6015_0000 ~ 0x6015_01FF */ + //0x23200, 0x1740, /* WF_ETBF: 0x6015_0000 ~ 0x6015_01FF */ + //0x24000, 0x1740, /* WF_LPON: 0x6015_0000 ~ 0x6015_01FF */ + //0x24400, 0x244FF, /* WF_INT: 0x6015_0000 ~ 0x6015_01FF */ + //0x28000, 0x280ff, /* WF_WTBLON: 0x6015_0000 ~ 0x6015_01FF */ + 0x2C000, 0x2C1FF, /* WF_MIB: 0x6015_0000 ~ 0x6015_01FF */ + 0x2D000, 0x2D1FF, /* WF_AON: 0x6015_0000 ~ 0x6015_01FF */ + 0,0 + }; + + sprintf(msg, "\n"); + mac_idx = 0; + while (mac_range_7603[mac_idx] != 0) + { + mac_s = mac_range_7603[mac_idx]; + mac_e = mac_range_7603[mac_idx + 1]; + for (macAddr = mac_s; macAddr <= mac_e; macAddr += 4) { + RTMP_IO_READ32(pAd, macAddr, &macValue); + DBGPRINT(RT_DEBUG_TRACE, ("[%08x] = %08x\n", macAddr, macValue)); + } + mac_idx += 2; + } + } + else +#endif /* MT7603 */ + { + for(IdMac = mac_s; IdMac < mac_e; IdMac += 4) + { + RTMP_IO_READ32(pAd, IdMac, &macValue); + DBGPRINT(RT_DEBUG_TRACE, ("%08x = %08x\n", IdMac, macValue)); + } + } + } + + + 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 */ + + + + os_free_mem(NULL, mpool); + if (!bFromUI) + DBGPRINT(RT_DEBUG_INFO, ("<==%s()\n", __FUNCTION__)); +} + + +INT Show_DescInfo_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ +#ifdef RTMP_MAC_PCI + INT32 i, QueIdx; + RXD_STRUC *pRxD; + TXD_STRUC *pTxD; +#ifdef RT_BIG_ENDIAN + RXD_STRUC *pDestRxD, RxD; + TXD_STRUC *pDestTxD, TxD; +#endif /* RT_BIG_ENDIAN */ + RTMP_TX_RING *pTxRing; + RTMP_MGMT_RING *pMgmtRing = &pAd->MgmtRing; + RTMP_RX_RING *pRxRing; + RTMP_BCN_RING *pBcnRing = &pAd->BcnRing; + RTMP_TX_RING *pTxBmcRing = &pAd->TxBmcRing; + RTMP_CTRL_RING *pCtrlRing = &pAd->CtrlRing; + PUCHAR pDMAHeaderBufVA; + + for (QueIdx = 0; QueIdx < NUM_OF_TX_RING; QueIdx++) + { + pTxRing = &pAd->TxRing[QueIdx]; + + DBGPRINT(RT_DEBUG_OFF, ("Tx Ring %d ---------------------------------\n", QueIdx)); + for(i = 0; i < TX_RING_SIZE; i++) + { + pDMAHeaderBufVA = (UCHAR *)pTxRing->Cell[i].DmaBuf.AllocVa; +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *)pTxRing->Cell[i].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + MTMacInfoEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA), TYPE_TMACINFO, 32); +#else + pTxD = (TXD_STRUC *)pTxRing->Cell[i].AllocVa; +#endif /* RT_BIG_ENDIAN */ + DBGPRINT(RT_DEBUG_OFF, ("Desc #%d\n",i)); + dump_txd(pAd, pTxD); + dump_tmac_info(pAd, pDMAHeaderBufVA); + DBGPRINT(RT_DEBUG_OFF, ("pkt physical address = %lx\n", + (ULONG)pTxRing->Cell[i].PacketPa)); +#ifdef RT_BIG_ENDIAN + MTMacInfoEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA), TYPE_TMACINFO, 32); +#endif + } + } + + DBGPRINT(RT_DEBUG_OFF, ("Mgmt Ring ------------------------------------------\n")); + for(i = 0; i < MGMT_RING_SIZE; i++) + { + pDMAHeaderBufVA = (UCHAR *)pMgmtRing->Cell[i].DmaBuf.AllocVa; +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *)pMgmtRing->Cell[i].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + MTMacInfoEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA), TYPE_TMACINFO, 32); +#else + pTxD = (TXD_STRUC *)pMgmtRing->Cell[i].AllocVa; +#endif /* RT_BIG_ENDIAN */ + DBGPRINT(RT_DEBUG_OFF, ("Desc #%d\n",i)); + dump_txd(pAd, pTxD); + dump_tmac_info(pAd, pDMAHeaderBufVA); + DBGPRINT(RT_DEBUG_OFF, ("pkt physical address = %lx\n", + (ULONG)pMgmtRing->Cell[i].PacketPa)); +#ifdef RT_BIG_ENDIAN + MTMacInfoEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA), TYPE_TMACINFO, 32); +#endif + } + + DBGPRINT(RT_DEBUG_OFF, ("BCN ring---------------------------------------------\n")); + for (i = 0; i < BCN_RING_SIZE; i++) + { + pDMAHeaderBufVA = (UCHAR *)pBcnRing->Cell[i].DmaBuf.AllocVa; +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *)pBcnRing->Cell[i].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + MTMacInfoEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA), TYPE_TMACINFO, 32); +#else + pTxD = (TXD_STRUC *)pBcnRing->Cell[i].AllocVa; +#endif /* RT_BIG_ENDIAN */ + DBGPRINT(RT_DEBUG_OFF, ("Desc #%d\n",i)); + dump_txd(pAd, pTxD); + dump_tmac_info(pAd, pDMAHeaderBufVA); + DBGPRINT(RT_DEBUG_OFF, ("pkt physical address = %lx\n", + (ULONG)pBcnRing->Cell[i].PacketPa)); +#ifdef RT_BIG_ENDIAN + MTMacInfoEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA), TYPE_TMACINFO, 32); +#endif + } + + DBGPRINT(RT_DEBUG_OFF, ("BMC ring---------------------------------------------\n")); + for (i = 0; i < TX_RING_SIZE; i++) + { + pDMAHeaderBufVA = (UCHAR *)pTxBmcRing->Cell[i].DmaBuf.AllocVa; +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *)pTxBmcRing->Cell[i].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + MTMacInfoEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA), TYPE_TMACINFO, 32); +#else + pTxD = (TXD_STRUC *)pTxBmcRing->Cell[i].AllocVa; +#endif /* RT_BIG_ENDIAN */ + DBGPRINT(RT_DEBUG_OFF, ("Desc #%d\n",i)); + dump_txd(pAd, pTxD); + dump_tmac_info(pAd, pDMAHeaderBufVA); + DBGPRINT(RT_DEBUG_OFF, ("pkt physical address = %lx\n", + (ULONG)pTxBmcRing->Cell[i].PacketPa)); +#ifdef RT_BIG_ENDIAN + MTMacInfoEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA), TYPE_TMACINFO, 32); +#endif + } + + DBGPRINT(RT_DEBUG_OFF, ("Control ring---------------------------------------------\n")); + for(i = 0; i < MGMT_RING_SIZE; i++) + { + pDMAHeaderBufVA = (UCHAR *)pCtrlRing->Cell[i].DmaBuf.AllocVa; +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *)pCtrlRing->Cell[i].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + MTMacInfoEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA), TYPE_TMACINFO, 32); +#else + pTxD = (TXD_STRUC *)pCtrlRing->Cell[i].AllocVa; +#endif /* RT_BIG_ENDIAN */ + DBGPRINT(RT_DEBUG_OFF, ("Desc #%d\n",i)); + dump_txd(pAd, pTxD); + dump_tmac_info(pAd, pDMAHeaderBufVA); + DBGPRINT(RT_DEBUG_OFF, ("pkt physical address = %lx\n", + (ULONG)pCtrlRing->Cell[i].PacketPa)); +#ifdef RT_BIG_ENDIAN + MTMacInfoEndianChange(pAd, (PUCHAR)(pDMAHeaderBufVA), TYPE_TMACINFO, 32); +#endif + } + + + for (QueIdx = 0; QueIdx < NUM_OF_RX_RING; QueIdx++) + { + pRxRing = &pAd->RxRing[QueIdx]; + + DBGPRINT(RT_DEBUG_OFF, ("Rx Ring %d ---------------------------------\n", QueIdx)); + for(i = 0;i < RX_RING_SIZE; i++) + { +#ifdef RT_BIG_ENDIAN + pDestRxD = (RXD_STRUC *)pRxRing->Cell[i].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + pRxD = (RXD_STRUC *)pRxRing->Cell[i].AllocVa; +#endif /* RT_BIG_ENDIAN */ + DBGPRINT(RT_DEBUG_OFF, ("Desc #%d\n",i)); + dump_rxd(pAd, pRxD); + DBGPRINT(RT_DEBUG_OFF, ("pRxD->DDONE = %x\n", pRxD->DDONE)); + } + } +#endif /* RTMP_MAC_PCI */ + + return TRUE; +} +#endif /* DBG */ + +#ifdef FAST_DETECT_STA_OFF +int Flag_fast_detect_sta_off; +INT Set_FlagFastDetectStaOff_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + Flag_fast_detect_sta_off = simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("%s (Flag_fast_detect_sta_off = %d)\n", __func__, Flag_fast_detect_sta_off)); + + return TRUE; +} +#endif + +#if defined(MAX_CONTINUOUS_TX_CNT) || defined(NEW_IXIA_METHOD) +INT Set_Rssi_Threshold_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT rssithval; + rssithval = simple_strtol(arg, 0, 10); + pAd->DeltaRssiTh = rssithval; + DBGPRINT_S(("==>%s(): pAd->DeltaRssiTh = %d\n", __FUNCTION__, pAd->DeltaRssiTh)); + return TRUE; +} +INT Set_ContinousTxCnt_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT txcnt; + txcnt = simple_strtol(arg, 0, 10); + pAd->ContinousTxCnt = txcnt; + pAd->MonitorFlag = FALSE; + DBGPRINT_S(("==>%s(): pAd->ContinousTxCnt = %d\n", __FUNCTION__, pAd->ContinousTxCnt)); + return TRUE; +} +INT Set_Rate_Threshold_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT ratethval; + ratethval = simple_strtol(arg, 0, 10); + pAd->RateTh = ratethval; + DBGPRINT_S(("==>%s(): pAd->RateTh = %d\n", __FUNCTION__, pAd->RateTh)); + return TRUE; +} +#endif +/* + ========================================================================== + Description: + Reset statistics counter + + Arguments: + pAd Pointer to our adapter + arg + + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_ResetStatCounter_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + DBGPRINT(RT_DEBUG_TRACE, ("==>Set_ResetStatCounter_Proc\n")); + + /* add the most up-to-date h/w raw counters into software counters*/ + NICUpdateRawCounters(pAd); + + NdisZeroMemory(&pAd->WlanCounters, sizeof(COUNTER_802_11)); + NdisZeroMemory(&pAd->Counters8023, sizeof(COUNTER_802_3)); + NdisZeroMemory(&pAd->RalinkCounters, sizeof(COUNTER_RALINK)); + +#ifdef CONFIG_ATE +#ifdef CONFIG_QA + pAd->ATECtrl.U2M = 0; + pAd->ATECtrl.OtherCount = 0; + pAd->ATECtrl.OtherData = 0; +#endif /* CONFIG_QA */ +#endif /* CONFIG_ATE */ + +#ifdef CONFIG_AP_SUPPORT +#endif /* CONFIG_AP_SUPPORT */ + + + return TRUE; +} + + +BOOLEAN RTMPCheckStrPrintAble( + IN CHAR *pInPutStr, + IN UCHAR strLen) +{ + UCHAR i=0; + + for (i=0; i 0x7E)) + return FALSE; + } + + return TRUE; +} + + +/* + ======================================================================== + + Routine Description: + Remove WPA Key process + + Arguments: + pAd Pointer to our adapter + pBuf Pointer to the where the key stored + + Return Value: + NDIS_SUCCESS Add key successfully + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ + + + + + + +/* + ======================================================================== + Routine Description: + Change NIC PHY mode. Re-association may be necessary + + Arguments: + pAd - Pointer to our adapter + phymode - + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID RTMPSetPhyMode(RTMP_ADAPTER *pAd, ULONG phymode) +{ + INT i; + //COMMON_CONFIG *cmm_cfg = &pAd->CommonCfg; + + /* the selected phymode must be supported by the RF IC encoded in E2PROM*/ + + pAd->CommonCfg.PhyMode = (UCHAR)phymode; + + DBGPRINT(RT_DEBUG_TRACE,("%s(): PhyMode=%d, channel=%d \n", + __FUNCTION__, pAd->CommonCfg.PhyMode, + pAd->CommonCfg.Channel)); + +#ifdef EXT_BUILD_CHANNEL_LIST + BuildChannelListEx(pAd); +#else + BuildChannelList(pAd); +#endif /* EXT_BUILD_CHANNEL_LIST */ + +#ifdef P2P_CHANNEL_LIST_SEPARATE + P2PBuildChannelList(pAd); +#endif /* P2P_CHANNEL_LIST_SEPARATE */ + + + /* 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 */ + DBGPRINT(RT_DEBUG_ERROR, ("%s(): channel out of range, use first ch=%d\n", + __FUNCTION__, pAd->CommonCfg.Channel)); + } + + NdisZeroMemory(pAd->CommonCfg.SupRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisZeroMemory(pAd->CommonCfg.ExtRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisZeroMemory(pAd->CommonCfg.DesireRate, MAX_LEN_OF_SUPPORTED_RATES); + switch (phymode) { + case (WMODE_B): + pAd->CommonCfg.SupRate[0] = 0x82; /* 1 mbps, in units of 0.5 Mbps, basic rate */ + pAd->CommonCfg.SupRate[1] = 0x84; /* 2 mbps, in units of 0.5 Mbps, basic rate */ + pAd->CommonCfg.SupRate[2] = 0x8B; /* 5.5 mbps, in units of 0.5 Mbps, basic rate */ + pAd->CommonCfg.SupRate[3] = 0x96; /* 11 mbps, in units of 0.5 Mbps, basic rate */ + pAd->CommonCfg.SupRateLen = 4; + pAd->CommonCfg.ExtRateLen = 0; + pAd->CommonCfg.DesireRate[0] = 2; /* 1 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[1] = 4; /* 2 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[2] = 11; /* 5.5 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[3] = 22; /* 11 mbps, in units of 0.5 Mbps*/ + /*pAd->CommonCfg.HTPhyMode.field.MODE = MODE_CCK; This MODE is only FYI. not use*/ + break; + + /* + In current design, we will put supported/extended rate element in + beacon even we are 11n-only mode. + Or some 11n stations will not connect to us if we do not put + supported/extended rate element in beacon. + */ +#ifdef GN_ONLY_AP_SUPPORT + case (WMODE_G): +#ifdef DOT11_N_SUPPORT + case (WMODE_G | WMODE_GN): + case (WMODE_GN): +#endif + pAd->CommonCfg.SupRate[0] = 0x0C; /* 6 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRate[1] = 0x12; /* 9 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRate[2] = 0x18; /* 12 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRate[3] = 0x24; /* 18 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRate[4] = 0x30; /* 24 mbps, in units of 0.5 Mbps*/ + 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*/ + + break; +#endif //#ifdef GN_ONLY_AP_SUPPORT + case (WMODE_B | WMODE_G): + case (WMODE_A | WMODE_B | WMODE_G): +#ifdef DOT11_N_SUPPORT + case (WMODE_A | WMODE_B | WMODE_G | WMODE_GN | WMODE_AN): + case (WMODE_B | WMODE_G | WMODE_GN): +#endif /* DOT11_N_SUPPORT */ +#ifdef DOT11_VHT_AC + case (WMODE_A | WMODE_B | WMODE_G | WMODE_GN | WMODE_AN | WMODE_AC): +#endif /* DOT11_VHT_AC */ + pAd->CommonCfg.SupRate[0] = 0x82; /* 1 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->CommonCfg.SupRate[1] = 0x84; /* 2 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->CommonCfg.SupRate[2] = 0x8B; /* 5.5 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->CommonCfg.SupRate[3] = 0x96; /* 11 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->CommonCfg.SupRate[4] = 0x12; /* 9 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRate[5] = 0x24; /* 18 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRate[6] = 0x48; /* 36 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRateLen = 8; + pAd->CommonCfg.ExtRate[0] = 0x0C; /* 6 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.ExtRate[1] = 0x18; /* 12 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.ExtRate[2] = 0x30; /* 24 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.ExtRate[3] = 0x60; /* 48 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.ExtRateLen = 4; + pAd->CommonCfg.DesireRate[0] = 2; /* 1 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[1] = 4; /* 2 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[2] = 11; /* 5.5 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[3] = 22; /* 11 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[4] = 12; /* 6 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[5] = 18; /* 9 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[6] = 24; /* 12 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[7] = 36; /* 18 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[8] = 48; /* 24 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[9] = 72; /* 36 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[10] = 96; /* 48 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[11] = 108; /* 54 mbps, in units of 0.5 Mbps*/ + break; + + case (WMODE_A): +#ifndef GN_ONLY_AP_SUPPORT + case (WMODE_G): +#endif +#ifdef DOT11_N_SUPPORT + case (WMODE_A | WMODE_AN): + case (WMODE_A | WMODE_G | WMODE_GN | WMODE_AN): +#ifndef GN_ONLY_AP_SUPPORT + case (WMODE_G | WMODE_GN): + case (WMODE_GN): +#endif + case (WMODE_AN): +#endif /* DOT11_N_SUPPORT */ +#ifdef DOT11_VHT_AC + case (WMODE_A | WMODE_AN | WMODE_AC): + case (WMODE_AN | WMODE_AC): + case (WMODE_G | WMODE_GN |WMODE_A | WMODE_AN | WMODE_AC): +#endif /* DOT11_VHT_AC */ + pAd->CommonCfg.SupRate[0] = 0x8C; /* 6 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->CommonCfg.SupRate[1] = 0x12; /* 9 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRate[2] = 0x98; /* 12 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->CommonCfg.SupRate[3] = 0x24; /* 18 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRate[4] = 0xb0; /* 24 mbps, in units of 0.5 Mbps, basic rate*/ + pAd->CommonCfg.SupRate[5] = 0x48; /* 36 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRate[6] = 0x60; /* 48 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRate[7] = 0x6c; /* 54 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.SupRateLen = 8; + pAd->CommonCfg.ExtRateLen = 0; + pAd->CommonCfg.DesireRate[0] = 12; /* 6 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[1] = 18; /* 9 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[2] = 24; /* 12 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[3] = 36; /* 18 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[4] = 48; /* 24 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[5] = 72; /* 36 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[6] = 96; /* 48 mbps, in units of 0.5 Mbps*/ + pAd->CommonCfg.DesireRate[7] = 108; /* 54 mbps, in units of 0.5 Mbps*/ + /*pAd->CommonCfg.HTPhyMode.field.MODE = MODE_OFDM; This MODE is only FYI. not use*/ + break; + + default: + break; + } + +#ifdef DYNAMIC_RX_RATE_ADJ + UpdateSuppRateBitmap(pAd); +#endif /* DYNAMIC_RX_RATE_ADJ */ +#ifdef GN_ONLY_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if(phymode & WMODE_B) + pAd->CommonCfg.bExcludeBRate = FALSE; + else + pAd->CommonCfg.bExcludeBRate = TRUE; + } +#endif +#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 */ + + + +//CFG_TODO + +#ifdef DOT11_N_SUPPORT + SetCommonHT(pAd); +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + SetCommonVHT(pAd); +#endif /* DOT11_VHT_AC */ +} + + +/* + ======================================================================== + Description: + Add Client security information into ASIC WCID table and IVEIV table. + Return: + ======================================================================== +*/ +VOID RTMPAddWcidAttributeEntry( + IN RTMP_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 */ + + + // TODO: shiang-7603!! fix me + if (IS_MT7603(pAd) || IS_MT7628(pAd) || IS_MT7636(pAd)) { + DBGPRINT(RT_DEBUG_OFF, ("%s(): MT7603 Not support yet!\n", __FUNCTION__)); + return; + } + + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (BssIdx >= MIN_NET_DEVICE_FOR_APCLI) + { + if (pEntry) + BssIdx -= MIN_NET_DEVICE_FOR_APCLI; + else + { + DBGPRINT(RT_DEBUG_WARN, ("RTMPAddWcidAttributeEntry: AP-Client link doesn't need to set Group WCID Attribute. \n")); + return; + } + } + else +#endif /* APCLI_SUPPORT */ +#ifdef WDS_SUPPORT + if (BssIdx >= MIN_NET_DEVICE_FOR_WDS) + { + if (pEntry) + BssIdx = BSS0; + else + { + DBGPRINT(RT_DEBUG_WARN, ("RTMPAddWcidAttributeEntry: WDS link doesn't need to set Group WCID Attribute. \n")); + return; + } + } + else +#endif /* WDS_SUPPORT */ + { + if (BssIdx >= pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPAddWcidAttributeEntry: The BSS-index(%d) is out of range for MBSSID link. \n", BssIdx)); + return; + } + } + + /* choose wcid number*/ + if (pEntry) + Wcid = pEntry->wcid; + else + GET_GroupKey_WCID(pAd, Wcid, BssIdx); + +#ifdef DOT1X_SUPPORT + if ((BssIdx < pAd->ApCfg.BssidNum) && (BssIdx < MAX_MBSSID_NUM(pAd)) && (BssIdx < HW_BEACON_MAX_NUM)) + IEEE8021X = pAd->ApCfg.MBSSID[BssIdx].wdev.IEEE8021X; +#endif /* DOT1X_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + } + + /* Update WCID attribute table*/ + { + UINT32 wcid_attr_base = 0, wcid_attr_size = 0; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + wcid_attr_base = RLT_MAC_WCID_ATTRIBUTE_BASE; + wcid_attr_size = RLT_HW_WCID_ATTRI_SIZE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + wcid_attr_base = MAC_WCID_ATTRIBUTE_BASE; + wcid_attr_size = HW_WCID_ATTRI_SIZE; + } +#endif /* RTMP_MAC */ + + offset = wcid_attr_base + (Wcid * wcid_attr_size); +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* + 1. Wds-links and Mesh-links always use Pair-wise key table. + 2. When the CipherAlg is TKIP, AES or the dynamic WEP is enabled, + it needs to set key into Pair-wise Key Table. + 3. The pair-wise key security mode is set NONE, it means as no security. + */ + if (pEntry && (IS_ENTRY_WDS(pEntry) || IS_ENTRY_MESH(pEntry))) + WCIDAttri = (BssIdx<<4) | (CipherAlg<<1) | PAIRWISEKEYTABLE; + else if ((pEntry) && + ((CipherAlg == CIPHER_TKIP) || + (CipherAlg == CIPHER_AES) || + (CipherAlg == CIPHER_NONE) || + (IEEE8021X == TRUE))) + WCIDAttri = (BssIdx<<4) | (CipherAlg<<1) | PAIRWISEKEYTABLE; + else + WCIDAttri = (BssIdx<<4) | (CipherAlg<<1) | SHAREDKEYTABLE; + } +#endif /* CONFIG_AP_SUPPORT */ + + + RTMP_IO_WRITE32(pAd, offset, WCIDAttri); + } + + /* Update IV/EIV table*/ + { + UINT32 iveiv_tb_base = 0, iveiv_tb_size = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + iveiv_tb_base = RLT_MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = RLT_HW_IVEIV_ENTRY_SIZE; + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + iveiv_tb_base = MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = HW_IVEIV_ENTRY_SIZE; + } +#endif /* RTMP_MAC */ + + offset = iveiv_tb_base + (Wcid * iveiv_tb_size); + + /* WPA mode*/ + if ((CipherAlg == CIPHER_TKIP) || (CipherAlg == CIPHER_AES)) + { + /* Eiv bit on. keyid always is 0 for pairwise key */ + IVEIV = (KeyIdx <<6) | 0x20; + } + else + { + /* WEP KeyIdx is default tx key. */ + IVEIV = (KeyIdx << 6); + } + + /* For key index and ext IV bit, so only need to update the position(offset+3).*/ +#ifdef RTMP_MAC_PCI + RTMP_IO_WRITE8(pAd, offset+3, IVEIV); +#endif /* RTMP_MAC_PCI */ + } + DBGPRINT(RT_DEBUG_TRACE,("RTMPAddWcidAttributeEntry: WCID #%d, KeyIndex #%d, Alg=%s\n",Wcid, KeyIdx, CipherName[CipherAlg])); + DBGPRINT(RT_DEBUG_TRACE,(" WCIDAttri = 0x%x \n", WCIDAttri)); + +} + +/* + ========================================================================== + Description: + Parse encryption type +Arguments: + pAdapter Pointer to our adapter + wrq Pointer to the ioctl argument + + Return Value: + None + + Note: + ========================================================================== +*/ +RTMP_STRING *GetEncryptType(CHAR enc) +{ + if(enc == Ndis802_11WEPDisabled) + return "NONE"; + if(enc == Ndis802_11WEPEnabled) + return "WEP"; + if(enc == Ndis802_11TKIPEnable) + return "TKIP"; + if(enc == Ndis802_11AESEnable) + return "AES"; + if(enc == Ndis802_11TKIPAESMix) + return "TKIPAES"; +#ifdef WAPI_SUPPORT + if(enc == Ndis802_11EncryptionSMS4Enabled) + return "SMS4"; +#endif /* WAPI_SUPPORT */ + else + return "UNKNOW"; +} + +RTMP_STRING *GetAuthMode(CHAR auth) +{ + if(auth == Ndis802_11AuthModeOpen) + return "OPEN"; + if(auth == Ndis802_11AuthModeShared) + return "SHARED"; + if(auth == Ndis802_11AuthModeAutoSwitch) + return "WEPAUTO"; + 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 "WPAPSKWPA2PSK"; +#ifdef WAPI_SUPPORT + if(auth == Ndis802_11AuthModeWAICERT) + return "WAI-CERT"; + if(auth == Ndis802_11AuthModeWAIPSK) + return "WAI-PSK"; +#endif /* WAPI_SUPPORT */ +#ifdef DOT11_SAE_SUPPORT + if (auth == Ndis802_11AuthModeWPA3PSK) + return "WPA3PSK"; + if (auth == Ndis802_11AuthModeWPA2PSKWPA3PSK) + return "WPA2PSKWPA3PSK"; +#endif +#ifdef CONFIG_OWE_SUPPORT + if (auth == Ndis802_11AuthModeOWE) + return "OWE"; +#endif + + 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 + ========================================================================== +*/ +#ifndef WH_EZ_SETUP +#define LINE_LEN (4+33+20+23+9+9+7+3) /* Channel+SSID(2*32+1)+Bssid+Security+Signal+WiressMode+ExtCh+NetworkType*/ +#endif + +#ifdef AIRPLAY_SUPPORT +#define IS_UNICODE_SSID_LEN (4) +#endif /* AIRPLAY_SUPPORT */ + +#ifdef WSC_INCLUDED +#define WPS_LINE_LEN (4+5) +#endif /* WSC_INCLUDED */ +#ifdef MWDS +#define MWDS_LINE_LEN (8) +#endif /* MWDS */ +#ifdef DOT11K_RRM_SUPPORT +#define BCNREPT_LINE_LEN (10) +#endif /* DOT11K_RRM_SUPPORT */ + +VOID RTMPCommSiteSurveyData( + IN RTMP_STRING *msg, + IN BSS_ENTRY *pBss, + IN UINT32 MsgLen) +{ + INT Rssi = 0; + UINT Rssi_Quality = 0; + NDIS_802_11_NETWORK_TYPE wireless_mode; + CHAR Ssid[MAX_LEN_OF_SSID +1]; + RTMP_STRING SecurityStr[32] = {0}; + NDIS_802_11_ENCRYPTION_STATUS ap_cipher = Ndis802_11EncryptionDisabled; + NDIS_802_11_AUTHENTICATION_MODE ap_auth_mode = Ndis802_11AuthModeOpen; +#ifdef AIRPLAY_SUPPORT + BOOLEAN isUniCodeSsid = FALSE; +#endif /* AIRPLAY_SUPPORT */ + + /*Channel*/ + sprintf(msg+strlen(msg),"%-4d", pBss->Channel); + + + /*SSID*/ + NdisZeroMemory(Ssid, (MAX_LEN_OF_SSID +1)); + if (RTMPCheckStrPrintAble((PCHAR)pBss->Ssid, pBss->SsidLen)) + NdisMoveMemory(Ssid, pBss->Ssid, pBss->SsidLen); + else + { + INT idx = 0; + +#ifdef AIRPLAY_SUPPORT + isUniCodeSsid = TRUE; +#endif /* AIRPLAY_SUPPORT */ + + sprintf(Ssid, "0x"); + for (idx = 0; (idx < 15) && (idx < pBss->SsidLen); idx++) + sprintf(Ssid + 2 + (idx*2), "%02X", (UCHAR)pBss->Ssid[idx]); + } + sprintf(msg+strlen(msg), "%-33s", Ssid); +#ifdef AIRPLAY_SUPPORT + /* IsUniCode SSID */ + if (isUniCodeSsid == TRUE) + sprintf(msg+strlen(msg),"%-4s", "Y"); + else + sprintf(msg+strlen(msg),"%-4s", "N"); +#endif /* AIRPLAY_SUPPORT */ + + /*BSSID*/ + sprintf(msg+strlen(msg),"%02x:%02x:%02x:%02x:%02x:%02x ", + pBss->Bssid[0], + pBss->Bssid[1], + pBss->Bssid[2], + pBss->Bssid[3], + pBss->Bssid[4], + pBss->Bssid[5]); + + /*Security*/ + RTMPZeroMemory(SecurityStr, 32); + if ((Ndis802_11AuthModeWPA <= pBss->AuthMode) && + (pBss->AuthMode <= Ndis802_11AuthModeWPA1PSKWPA2PSK)) + { + if (pBss->AuthMode == Ndis802_11AuthModeWPANone) + { + ap_auth_mode = pBss->AuthMode; + ap_cipher = pBss->WPA.PairCipher; + } + else if (pBss->AuthModeAux == Ndis802_11AuthModeOpen) + { + ap_auth_mode = pBss->AuthMode; + if ((ap_auth_mode == Ndis802_11AuthModeWPA) || + (ap_auth_mode == Ndis802_11AuthModeWPAPSK)) + { + if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled) + ap_cipher = pBss->WPA.PairCipher; + else + ap_cipher = Ndis802_11TKIPAESMix; + } + else if ((ap_auth_mode == Ndis802_11AuthModeWPA2) || + (ap_auth_mode == Ndis802_11AuthModeWPA2PSK)) + { + if (pBss->WPA2.PairCipherAux == Ndis802_11WEPDisabled) + ap_cipher = pBss->WPA2.PairCipher; + else + ap_cipher = Ndis802_11TKIPAESMix; + } + } + else if ((pBss->AuthMode == Ndis802_11AuthModeWPAPSK) || + (pBss->AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + if ((pBss->AuthModeAux == Ndis802_11AuthModeWPAPSK) || + (pBss->AuthModeAux == Ndis802_11AuthModeWPA2PSK)) + ap_auth_mode = Ndis802_11AuthModeWPA1PSKWPA2PSK; + else + ap_auth_mode = pBss->AuthMode; + + if (pBss->WPA.PairCipher != pBss->WPA2.PairCipher) + ap_cipher = Ndis802_11TKIPAESMix; + else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && + (pBss->WPA.PairCipherAux != pBss->WPA2.PairCipherAux)) + ap_cipher = Ndis802_11TKIPAESMix; + else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && + (pBss->WPA.PairCipherAux == pBss->WPA2.PairCipherAux) && + (pBss->WPA.PairCipherAux != Ndis802_11WEPDisabled)) + ap_cipher = Ndis802_11TKIPAESMix; + else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && + (pBss->WPA.PairCipherAux == pBss->WPA2.PairCipherAux) && + (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)) + ap_cipher = pBss->WPA.PairCipher; + } + else if ((pBss->AuthMode == Ndis802_11AuthModeWPA) || + (pBss->AuthMode == Ndis802_11AuthModeWPA2)) + { + if ((pBss->AuthModeAux == Ndis802_11AuthModeWPA) || + (pBss->AuthModeAux == Ndis802_11AuthModeWPA2)) + ap_auth_mode = Ndis802_11AuthModeWPA1WPA2; + else + ap_auth_mode = pBss->AuthMode; + + if (pBss->WPA.PairCipher != pBss->WPA2.PairCipher) + ap_cipher = Ndis802_11TKIPAESMix; + else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && + (pBss->WPA.PairCipherAux != pBss->WPA2.PairCipherAux)) + ap_cipher = Ndis802_11TKIPAESMix; + else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && + (pBss->WPA.PairCipherAux == pBss->WPA2.PairCipherAux) && + (pBss->WPA.PairCipherAux != Ndis802_11WEPDisabled)) + ap_cipher = Ndis802_11TKIPAESMix; + else if ((pBss->WPA.PairCipher == pBss->WPA2.PairCipher) && + (pBss->WPA.PairCipherAux == pBss->WPA2.PairCipherAux) && + (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled)) + ap_cipher = pBss->WPA.PairCipher; + } + + snprintf(SecurityStr, sizeof(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");*/ + snprintf(SecurityStr, sizeof(SecurityStr), "%s/%s", + GetAuthMode((CHAR)ap_auth_mode), GetEncryptType((CHAR)ap_cipher)); + else if (ap_cipher == Ndis802_11WEPEnabled) + /*sprintf(SecurityStr, "WEP");*/ + snprintf(SecurityStr, sizeof(SecurityStr), "%s/%s", + GetAuthMode((CHAR)ap_auth_mode), GetEncryptType((CHAR)ap_cipher)); + else + snprintf(SecurityStr, sizeof(SecurityStr), "%s/%s", + GetAuthMode((CHAR)ap_auth_mode), GetEncryptType((CHAR)ap_cipher)); + } + + sprintf(msg+strlen(msg), "%-23s", SecurityStr); + + /* Rssi*/ + Rssi = (INT)pBss->Rssi; + if (Rssi >= -50) + Rssi_Quality = 100; + else if (Rssi >= -80) /* between -50 ~ -80dbm*/ + Rssi_Quality = (UINT)(24 + ((Rssi + 80) * 26)/10); + else if (Rssi >= -90) /* between -80 ~ -90dbm*/ + Rssi_Quality = (UINT)(((Rssi + 90) * 26)/10); + else /* < -84 dbm*/ + Rssi_Quality = 0; + sprintf(msg+strlen(msg),"%-9d", Rssi_Quality); + + /* Wireless Mode*/ + wireless_mode = NetworkTypeInUseSanity(pBss); + if (wireless_mode == Ndis802_11FH || + wireless_mode == Ndis802_11DS) + sprintf(msg+strlen(msg),"%-9s", "11b"); + else if (wireless_mode == Ndis802_11OFDM5) + sprintf(msg+strlen(msg),"%-9s", "11a"); + else if (wireless_mode == Ndis802_11OFDM5_N) + sprintf(msg+strlen(msg),"%-9s", "11a/n"); + else if (wireless_mode == Ndis802_11OFDM24) + sprintf(msg+strlen(msg),"%-9s", "11b/g"); + else if (wireless_mode == Ndis802_11OFDM24_N) + sprintf(msg+strlen(msg),"%-9s", "11b/g/n"); + else + sprintf(msg+strlen(msg),"%-9s", "unknow"); + + /* Ext Channel*/ + if (pBss->AddHtInfoLen > 0) + { + if (pBss->AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_ABOVE) + sprintf(msg+strlen(msg),"%-7s", " ABOVE"); + else if (pBss->AddHtInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW) + sprintf(msg+strlen(msg),"%-7s", " BELOW"); + else + sprintf(msg+strlen(msg),"%-7s", " NONE"); + } + else + { + sprintf(msg+strlen(msg),"%-7s", " NONE"); + } + + /*Network Type */ + if (pBss->BssType == BSS_ADHOC) + sprintf(msg+strlen(msg),"%-3s", " Ad"); + else + sprintf(msg+strlen(msg),"%-3s", " In"); + /* SSID Length */ + //sprintf(msg + strlen(msg), " %-8d", pBss->SsidLen); + sprintf(msg+strlen(msg),"\n"); + + return; +} + +static BOOLEAN ui_ascii2int(RTMP_STRING *in, UINT32 *out) +{ + UINT32 decimal_val, val; + CHAR *p, asc_val; + + decimal_val = 0; + p = (char *)in; + while ((*p) != 0) { + val = 0; + asc_val = *p; + if ((asc_val >= '0') && (asc_val <= '9')) + val = asc_val - 48; + else + return FALSE; + decimal_val = (decimal_val * 10) + val; + p++; + } + *out = decimal_val; + return TRUE; +} + +#if defined (AP_SCAN_SUPPORT) || defined (CONFIG_STA_SUPPORT) +VOID RTMPIoctlGetSiteSurvey( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + RTMP_STRING *msg; + INT i=0; + INT WaitCnt; + INT Status = 0; + INT max_len = LINE_LEN; + BSS_ENTRY *pBss; + RTMP_STRING *this_char; + UINT32 bss_start_idx; + UINT32 TotalLen, BufLen = IW_SCAN_MAX_DATA; + INT last_msg_len = 0; + BSS_TABLE *pScanTab; +#ifdef AIRPLAY_SUPPORT + UCHAR TargetSsid[MAX_LEN_OF_SSID+1]; + UCHAR TargetSsidLen = 0; +#endif /* AIRPLAY_SUPPORT */ + +#ifdef WSC_INCLUDED + max_len += WPS_LINE_LEN; +#endif /* WSC_INCLUDED */ +#ifdef MWDS + max_len += MWDS_LINE_LEN; +#endif /* MWDS */ +#ifdef DOT11K_RRM_SUPPORT + max_len += BCNREPT_LINE_LEN; +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef AIRPLAY_SUPPORT + max_len += IS_UNICODE_SSID_LEN; +#endif /* AIRPLAY_SUPPORT */ + + TotalLen = sizeof(CHAR)*((MAX_LEN_OF_BSS_TABLE + 1)*max_len) + 100; + +#ifdef AIRPLAY_SUPPORT + if (wrq->u.data.length > MAX_LEN_OF_SSID) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPIoctlGetSiteSurvey - INPUT SSID LEN NOT CORRECT\n")); + return; + } + + if (wrq->u.data.length > 0) + { + NdisZeroMemory(TargetSsid, sizeof(TargetSsid)); + copy_from_user(TargetSsid, wrq->u.data.pointer, wrq->u.data.length); + TargetSsidLen = strlen(TargetSsid); + DBGPRINT(RT_DEBUG_TRACE, ("Filter the ScanRes by SSID --> %s (%d)\n", TargetSsid, TargetSsidLen)); + } + +#else + if (wrq->u.data.length == 0) + BufLen = IW_SCAN_MAX_DATA; + else + /*BufLen = wrq->u.data.length;*/ + BufLen = IW_SCAN_MAX_DATA; +#endif /* AIRPLAY_SUPPORT */ +#ifdef APCLI_OWE_SUPPORT + max_len += OWETRANSIE_LINE_LEN; +#endif + os_alloc_mem(NULL, (UCHAR **)&this_char, wrq->u.data.length + 1); + if (!this_char) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s: Allocate memory fail!!!\n", __func__)); + return; + } + + if (copy_from_user(this_char, wrq->u.data.pointer, wrq->u.data.length)) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s: copy_from_user() fail!!!\n", __func__)); + os_free_mem(NULL, this_char); + return; + } + this_char[wrq->u.data.length] = 0; + + if (ui_ascii2int(this_char, &bss_start_idx) == FALSE) + bss_start_idx = 0; + + 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); + + if (pAdapter->ScanTab.BssNr == 0) { + sprintf(msg, "No BssInfo\n"); + wrq->u.data.length = strlen(msg); + Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("RTMPIoctlGetSiteSurvey - wrq->u.data.length = %d\n", + wrq->u.data.length)); + os_free_mem(NULL, (PUCHAR)msg); + os_free_mem(NULL, this_char); + return; + } + + if (bss_start_idx > (pAdapter->ScanTab.BssNr - 1)) { + sprintf(msg, "BssInfo Idx(%d) is out of range(0~%d)\n", + bss_start_idx, (pAdapter->ScanTab.BssNr - 1)); + wrq->u.data.length = strlen(msg); + Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("RTMPIoctlGetSiteSurvey - wrq->u.data.length = %d\n", + wrq->u.data.length)); + os_free_mem(NULL, (PUCHAR)msg); + os_free_mem(NULL, this_char); + return; + } + + //snprintf(msg, TotalLen, "%s", "\n"); + sprintf(msg, "%s", "\n"); + //sprintf(msg + strlen(msg), "Total=%-4d", pAdapter->ScanTab.BssNr); + //sprintf(msg + strlen(msg), "%s", "\n"); +#ifdef AIRPLAY_SUPPORT + sprintf(msg+strlen(msg),"%-4s%-33s%-4s%-20s%-23s%-9s%-7s%-7s%-3s\n", + "Ch", "SSID", "UN", "BSSID", "Security", "Siganl(%)", "W-Mode", " ExtCH"," NT"); +#else + sprintf(msg + strlen(msg), "%-4s%-33s%-20s%-23s%-9s%-9s%-7s%-3s\n", + "Ch", "SSID", "BSSID", "Security", "Signal(%)", "W-Mode", " ExtCH", " NT"); +#endif /* AIRPLAY_SUPPORT */ + + +#ifdef WSC_INCLUDED + sprintf(msg+strlen(msg)-1,"%-4s%-5s\n", " WPS", " DPID"); +#endif /* WSC_INCLUDED */ + +#ifdef DOT11K_RRM_SUPPORT + sprintf(msg+strlen(msg)-1, "%-10s\n", " BcnRept"); +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef MWDS + sprintf(msg+strlen(msg)-1,"%-8s\n", " MWDSCap"); +#endif /* MWDS */ +#ifdef APCLI_OWE_SUPPORT + sprintf(msg + strlen(msg) - 1, "%-10s\n", " OWETranIe"); +#endif /* APCLI_OWE_SUPPORT */ + + WaitCnt = 0; + + while ((ScanRunning(pAdapter) == TRUE) && (WaitCnt++ < 200)) + OS_WAIT(500); + + pScanTab = &pAdapter->ScanTab; + BssTableSortByRssi(pScanTab,FALSE); + + for (i = bss_start_idx; i < pAdapter->ScanTab.BssNr; i++) + { + pBss = &pAdapter->ScanTab.BssEntry[i]; + + if( pBss->Channel==0) + break; + +#ifdef APCLI_OWE_SUPPORT + if (pBss->hide_owe_bss == TRUE) + continue; +#endif + if(last_msg_len < IW_SCAN_MAX_DATA) { + last_msg_len = strlen(msg); + } else { + DBGPRINT(RT_DEBUG_TRACE,("===[%s] *** last_msg_len = %d ***\n", __FUNCTION__, last_msg_len)); + } + + DBGPRINT(RT_DEBUG_TRACE,("===[%s] i:%d last_msg_len = %d strlen(msg) = %d \n", __FUNCTION__, i, last_msg_len, strlen(msg))); + if((strlen(msg)+max_len ) >= BufLen) + break; + +#ifdef AIRPLAY_SUPPORT + if (TargetSsidLen > 0) + { + if (strcmp(pBss->Ssid, TargetSsid) != 0) + continue; + } +#endif /* AIRPLAY_SUPPORT */ + //sprintf(msg + strlen(msg), "%-4d", i); + 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 DOT11K_RRM_SUPPORT + sprintf(msg+strlen(msg)-1, "%-7s\n", pBss->FromBcnReport ? " YES" : " NO"); +#endif /* DOT11K_RRM_SUPPORT */ +#ifndef MWDS + /*sprintf(msg+strlen(msg), "%-7s\n", pBss->FromBcnReport ? " YES" : " NO");*/ +#else + /*sprintf(msg+strlen(msg), "%-7s", pBss->FromBcnReport ? " YES" : " NO");*/ + + if (pBss->bSupportMWDS) + sprintf(msg+strlen(msg)-1, "%-4s\n", " YES"); + else + sprintf(msg+strlen(msg)-1, "%-4s\n", " NO"); +#endif /* MWDS */ +#ifdef APCLI_OWE_SUPPORT + if (pBss->bhas_owe_trans_ie) + sprintf(msg + strlen(msg), "%-10s\n", " YES"); + else + sprintf(msg + strlen(msg), "%-10s\n", " NO"); +#endif + + } + + if(strlen(msg) < IW_SCAN_MAX_DATA) + wrq->u.data.length = strlen(msg); + else + wrq->u.data.length = last_msg_len; + /*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 + + +static VOID +copy_mac_table_entry(RT_802_11_MAC_ENTRY *pDst, MAC_TABLE_ENTRY *pEntry) +{ + pDst->ApIdx = (UCHAR)pEntry->func_tb_idx; + 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.AvgRssi[0]; + pDst->AvgRssi1 = pEntry->RssiSample.AvgRssi[1]; + pDst->AvgRssi2 = pEntry->RssiSample.AvgRssi[2]; + + /* the connected time per entry*/ + pDst->ConnectedTime = pEntry->StaConnectTime; + + pDst->TxRate.word = pEntry->HTPhyMode.word; + pDst->LastRxRate = pEntry->LastRxRate; +} + + +VOID RTMPIoctlGetMacTableStaInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + INT i, MacTabWCID; + RT_802_11_MAC_TABLE *pMacTab = NULL; + UINT16 wrq_len = wrq->u.data.length; + PRT_802_11_MAC_ENTRY pDst; + MAC_TABLE_ENTRY *pEntry; + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + + wrq->u.data.length = 0; +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + STA_TR_ENTRY *tr_entry; + + if (wrq_len < sizeof(RT_802_11_MAC_ENTRY)) + return; + if (pObj->ioctl_if >= MAX_APCLI_NUM) + return; + if (pAd->ApCfg.ApCliTab[pObj->ioctl_if].CtrlCurrState != APCLI_CTRL_CONNECTED) + return; + MacTabWCID = pAd->ApCfg.ApCliTab[pObj->ioctl_if].MacTabWCID; + if (!VALID_WCID(MacTabWCID)) + return; + if (!VALID_TR_WCID(MacTabWCID)) + return; + pEntry = &pAd->MacTab.Content[MacTabWCID]; + tr_entry = &pAd->MacTab.tr_entry[MacTabWCID]; + if (IS_ENTRY_APCLI(pEntry) && (pEntry->Sst == SST_ASSOC) && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + RT_802_11_MAC_ENTRY MacEntry; + + pDst = &MacEntry; + copy_mac_table_entry(pDst, pEntry); + + wrq->u.data.length = sizeof(RT_802_11_MAC_ENTRY); + copy_to_user(wrq->u.data.pointer, pDst, wrq->u.data.length); + } + + return; + } +#endif + + /* 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->func_tb_idx; + 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.AvgRssi[0]; + pDst->AvgRssi1 = pEntry->RssiSample.AvgRssi[1]; + pDst->AvgRssi2 = pEntry->RssiSample.AvgRssi[2]; + + /* the connected time per entry*/ + pDst->ConnectedTime = pEntry->StaConnectTime; + pDst->TxRate.word = pEntry->HTPhyMode.word; + + pDst->LastRxRate = pEntry->LastRxRate; + + 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); +} + +VOID RTMPIoctlGetDriverInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT * wrq) +{ + RTMP_STRING *msg; + UINT32 TotalLen = 4096; + + os_alloc_mem(NULL, (PUCHAR *)&msg, TotalLen); + + if (msg == NULL) { + DBGPRINT(RT_DEBUG_OFF, ("RTMPIoctlGetDriverInfo - msg memory alloc fail.\n")); + return; + } + + NdisZeroMemory(msg, TotalLen); + + sprintf(msg, "Driver version: %s \n", AP_DRIVER_VERSION); +#ifdef CONFIG_ANDES_SUPPORT + if (pAd->chipCap.MCUType == ANDES) { + UINT32 loop = 0; + RTMP_CHIP_CAP *cap = &pAd->chipCap; + + if (pAd->chipCap.need_load_fw) { + USHORT fw_ver, build_ver; + + fw_ver = (*(cap->FWImageName + 11) << 8) | (*(cap->FWImageName + 10)); + build_ver = (*(cap->FWImageName + 9) << 8) | (*(cap->FWImageName + 8)); + + sprintf(msg+strlen(msg), "fw version:%d.%d.%02d ", (fw_ver & 0xf000) >> 8, + (fw_ver & 0x0f00) >> 8, fw_ver & 0x00ff); + sprintf(msg+strlen(msg), "build:%x\n", build_ver); + sprintf(msg+strlen(msg), "%s", "build time:"); + + for (loop = 0; loop < 16; loop++) + sprintf(msg+strlen(msg), "%c", *(cap->FWImageName + 16 + loop)); + + sprintf(msg+strlen(msg), "%s", "\n"); + } + + if (pAd->chipCap.need_load_rom_patch) { + sprintf(msg+strlen(msg), "%s", "rom patch version = \n"); + + for (loop = 0; loop < 4; loop++) + sprintf(msg+strlen(msg), "%c", *(cap->rom_patch + 24 + loop)); + + sprintf(msg+strlen(msg), "%s", "\n"); + + sprintf(msg+strlen(msg), "%s", "build time:"); + + for (loop = 0; loop < 16; loop++) + sprintf(msg+strlen(msg), "%c", *(cap->rom_patch + loop)); + + sprintf(msg+strlen(msg), "%s", "\n"); + } + } +#endif + +#if defined(MT7603_FPGA) || defined(MT7628_FPGA) + if ((IS_MT7603(pAd) || IS_MT7628(pAd)) && pAd->chipCap.hif_type == HIF_MT) { + UINT32 mac_val, ver, date_code, rev; + + RTMP_IO_READ32(pAd, 0x2700, &ver); + RTMP_IO_READ32(pAd, 0x2704, &rev); + RTMP_IO_READ32(pAd, 0x2708, &date_code); + RTMP_IO_READ32(pAd, 0x21f8, &mac_val); + sprintf(msg+strlen(msg), "%s", "MT7603 FPGA Version:\n"); + + sprintf(msg+strlen(msg), "\tFGPA1: Code[0x700]:0x%x, [0x704]:0x%x, [0x708]:0x%x\n", + ver, rev, date_code); + + sprintf(msg+strlen(msg), "\tFPGA2: Version[0x21f8]:0x%x\n", mac_val); + } +#endif /* MT7603_FPGA */ + + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + DBGPRINT(RT_DEBUG_OFF, ("%s: copy_to_user() fail\n", __func__)); + os_free_mem(NULL, (PUCHAR)msg); +} + + +#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; + + /* 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]); + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) + { + pDst = &pMacTab->Entry[pMacTab->Num]; + + + pDst->ApIdx = (UCHAR)pEntry->func_tb_idx; + 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.AvgRssi[0]; + pDst->AvgRssi1 = pEntry->RssiSample.AvgRssi[1]; + pDst->AvgRssi2 = pEntry->RssiSample.AvgRssi[2]; + + /* the connected time per entry*/ + pDst->ConnectedTime = pEntry->StaConnectTime; + pDst->TxRate.word = pEntry->HTPhyMode.word; + + + pMacTab->Num += 1; + } + } + + wrq->u.data.length = sizeof(RT_802_11_MAC_TABLE); + if (copy_to_user(wrq->u.data.pointer, pMacTab, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: copy_to_user() fail\n", __FUNCTION__)); + } + + os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN)); + if (msg == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + goto LabelOK; + } + memset(msg, 0 ,MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN ); + sprintf(msg,"%s","\n"); + sprintf(msg+strlen(msg),"%-14s%-4s%-4s%-4s%-4s%-6s%-6s%-10s%-10s%-10s\n", + "MAC", "AP", "AID", "PSM", "AUTH", "CTxR", "LTxR","LDT", "RxB", "TxB"); + + for (i=0; iMacTab.Content[i]; + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) + { + if((strlen(msg)+MAC_LINE_LEN ) >= (MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN) ) + break; + sprintf(msg+strlen(msg),"%02x%02x%02x%02x%02x%02x ", PRINT_MAC(pEntry->Addr)); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->func_tb_idx); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->Aid); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->PsMode); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->AuthState); + sprintf(msg+strlen(msg),"%-6d",RateIdToMbps[pAd->MacTab.Content[i].CurrTxRate]); + sprintf(msg+strlen(msg),"%-6d",0/*RateIdToMbps[pAd->MacTab.Content[i].HTPhyMode.word]*/); /* ToDo*/ + sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.LastDataPacketTime*/); /* ToDo*/ + sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.TotalRxByteCount*/); /* ToDo*/ + sprintf(msg+strlen(msg),"%-10d\n",0/*pAd->MacTab.Content[i].HSCounter.TotalTxByteCount*/); /* ToDo*/ + + } + } + /* for compatible with old API just do the printk to console*/ + + DBGPRINT(RT_DEBUG_TRACE, ("%s", msg)); + os_free_mem(NULL, msg); + +LabelOK: + if (pMacTab != NULL) + os_free_mem(NULL, pMacTab); +} + +#if defined(INF_AR9) || defined(BB_SOC) +#if defined(AR9_MAPI_SUPPORT) || defined(BB_SOC) +#ifdef CONFIG_AP_SUPPORT +VOID RTMPAR9IoctlGetMacTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + INT i; + char *msg; + + os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN)); + if (msg == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + return; + } + memset(msg, 0 ,MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN ); + sprintf(msg,"%s","\n"); + sprintf(msg+strlen(msg),"%-14s%-4s%-4s%-4s%-4s%-6s%-6s%-10s%-10s%-10s\n", + "MAC", "AP", "AID", "PSM", "AUTH", "CTxR", "LTxR","LDT", "RxB", "TxB"); + + for (i=0; iMacTab.Content[i]; + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst == SST_ASSOC)) + { + if((strlen(msg)+MAC_LINE_LEN ) >= (MAX_LEN_OF_MAC_TABLE*MAC_LINE_LEN) ) + break; + sprintf(msg+strlen(msg),"%02x%02x%02x%02x%02x%02x ", + pEntry->Addr[0], pEntry->Addr[1], pEntry->Addr[2], + pEntry->Addr[3], pEntry->Addr[4], pEntry->Addr[5]); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->func_tb_idx); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->Aid); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->PsMode); + sprintf(msg+strlen(msg),"%-4d", (int)pEntry->AuthState); + sprintf(msg+strlen(msg),"%-6d",RateIdToMbps[pAd->MacTab.Content[i].CurrTxRate]); + sprintf(msg+strlen(msg),"%-6d",0/*RateIdToMbps[pAd->MacTab.Content[i].HTPhyMode.word]*/); /* ToDo*/ + sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.LastDataPacketTime*/); /* ToDo*/ + sprintf(msg+strlen(msg),"%-10d",0/*pAd->MacTab.Content[i].HSCounter.TotalRxByteCount*/); /* ToDo*/ + sprintf(msg+strlen(msg),"%-10d\n",0/*pAd->MacTab.Content[i].HSCounter.TotalTxByteCount*/); /* ToDo*/ + + } + } + /* for compatible with old API just do the printk to console*/ + wrq->u.data.length = strlen(msg); + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s", msg)); + } + + os_free_mem(NULL, msg); +} + +VOID RTMPIoctlGetSTAT2( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + char *msg; + BSS_STRUCT *pMbss; + INT apidx; + + os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(pAd->ApCfg.BssidNum*(14*128))); + if (msg == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + return; + } + memset(msg, 0 ,pAd->ApCfg.BssidNum*(14*128)); + sprintf(msg,"%s","\n"); + + for (apidx=0; apidxApCfg.BssidNum; apidx++) + { + pMbss=&pAd->ApCfg.MBSSID[apidx]; + + sprintf(msg+strlen(msg),"ra%d\n",apidx); + sprintf(msg+strlen(msg),"bytesTx = %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)); + } + + os_free_mem(NULL, msg); +} + + +VOID RTMPIoctlGetRadioDynInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + char *msg; + BSS_STRUCT *pMbss; + INT status,bandwidth,ShortGI; + struct wifi_dev *wdev; + + os_alloc_mem(NULL, (UCHAR **)&msg, sizeof(CHAR)*(4096)); + if (msg == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Alloc memory failed\n", __FUNCTION__)); + return; + } + memset(msg, 0 ,4096); + sprintf(msg,"%s","\n"); + + + pMbss=&pAd->ApCfg.MBSSID[0]; + wdev = &pMbss->wdev; + if(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + status = 0; + else + status = 1; + + if(pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) + bandwidth = 1; + else + bandwidth = 0; + + if(pAd->CommonCfg.RegTransmitSetting.field.ShortGI == GI_800) + ShortGI = 1; + else + ShortGI = 0; + + + sprintf(msg+strlen(msg),"status = %d\n",status); + sprintf(msg+strlen(msg),"channelsInUse = %d\n",pAd->ChannelListNum); + sprintf(msg+strlen(msg),"channel = %d\n",pAd->CommonCfg.Channel); + sprintf(msg+strlen(msg),"chanWidth = %d\n",bandwidth); + sprintf(msg+strlen(msg),"guardIntvl = %d\n",ShortGI); + sprintf(msg+strlen(msg),"MCS = %d\n",wdev->DesiredTransmitSetting.field.MCS); + + wrq->u.data.length = strlen(msg); + + if (copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s", msg)); + } + + os_free_mem(NULL, msg); +} +#endif/*CONFIG_AP_SUPPORT*/ +#endif/*AR9_MAPI_SUPPORT*/ +#endif/* INF_AR9 */ + +#ifdef DOT11_N_SUPPORT +INT Set_BASetup_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR mac[6], tid; + RTMP_STRING *token; + RTMP_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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR mac[6], tid; + RTMP_STRING *token; + RTMP_STRING sepValue[] = ":", DASH = '-'; + INT i; + MAC_TABLE_ENTRY *pEntry; + + /*DBGPRINT(RT_DEBUG_TRACE,("\n%s\n", arg));*/ +/* + The BAOriTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d, + =>The six 2 digit hex-decimal number previous are the Mac address, + =>The seventh decimal number is the tid value. +*/ + if(strlen(arg) < 19) /*Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format.*/ + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + tid = simple_strtol((token+1), 0, 10); + /* tid will be 0 ~ 7; Or kernel will crash in BAOriSessionTearDown() */ + if (tid > (NUM_OF_TID-1)) + return FALSE; + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (&mac[i]), 1); + } + if(i != 6) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", + PRINT_MAC(mac), tid)); + + pEntry = MacTableLookup(pAd, (PUCHAR) mac); + + if (pEntry) { + DBGPRINT(RT_DEBUG_OFF, ("\nTear down Ori BA Session: Tid = %d\n", tid)); + BAOriSessionTearDown(pAd, pEntry->wcid, tid, FALSE, TRUE); + } + + return TRUE; + } + + return FALSE; + +} + +INT Set_BARecTearDown_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR mac[6], tid; + RTMP_STRING *token; + RTMP_STRING sepValue[] = ":", DASH = '-'; + INT i; + MAC_TABLE_ENTRY *pEntry; + + /*DBGPRINT(RT_DEBUG_TRACE,("\n%s\n", arg));*/ +/* + The BARecTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d, + =>The six 2 digit hex-decimal number previous are the Mac address, + =>The seventh decimal number is the tid value. +*/ + if(strlen(arg) < 19) /*Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and tid value in decimal format.*/ + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + tid = simple_strtol((token+1), 0, 10); + /* tid will be 0 ~ 7; Or kernel will crash in BARecSessionTearDown() */ + if (tid > (NUM_OF_TID-1)) + return FALSE; + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (&mac[i]), 1); + } + if(i != 6) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", + PRINT_MAC(mac), tid)); + + pEntry = MacTableLookup(pAd, (PUCHAR) mac); + + if (pEntry) { + DBGPRINT(RT_DEBUG_OFF, ("\nTear down Rec BA Session: Tid = %d\n", tid)); + BARecSessionTearDown(pAd, pEntry->wcid, tid, FALSE); + } + + return TRUE; + } + + return FALSE; + +} + +INT Set_HtBw_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; +#endif /* CONFIG_AP_SUPPORT */ + UCHAR HtMcs = MCS_AUTO, Mcs_tmp, ValidMcs = 15; +#ifdef DOT11_VHT_AC + RTMP_STRING *mcs_str, *ss_str; + UCHAR ss = 0, mcs = 0; +#endif /* DOT11_VHT_AC */ + struct wifi_dev *wdev; + +#ifdef DOT11_VHT_AC + ss_str = arg; + if ((mcs_str = rtstrchr(arg, ':'))!= NULL) + { + *mcs_str = 0; + mcs_str++; + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): ss_str=%s, mcs_str=%s\n", + __FUNCTION__, ss_str, mcs_str)); + + if (strlen(ss_str) && strlen(mcs_str)) { + mcs = simple_strtol(mcs_str, 0, 10); + ss = simple_strtol(ss_str, 0, 10); + + if ((ss <= pAd->CommonCfg.TxStream) && (mcs <= 7)) + HtMcs = ((ss - 1) <<4) | mcs; + else { + HtMcs = MCS_AUTO; + ss = 0; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s(): %dSS-MCS%d, Auto=%s\n", + __FUNCTION__, ss, mcs, + (HtMcs == MCS_AUTO && ss == 0) ? "TRUE" : "FALSE")); + Set_FixedTxMode_Proc(pAd, "VHT"); + } + } + else +#endif /* DOT11_VHT_AC */ + { +#ifdef DOT11N_SS3_SUPPORT + if (pAd->CommonCfg.TxStream >= 3) + ValidMcs = 23; +#endif /* DOT11N_SS3_SUPPORT */ + + Mcs_tmp = simple_strtol(arg, 0, 10); + if (Mcs_tmp <= ValidMcs || Mcs_tmp == 32) + HtMcs = Mcs_tmp; + else + HtMcs = MCS_AUTO; + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; + + wdev->DesiredTransmitSetting.field.MCS = HtMcs; + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtMcs_Proc::(HtMcs=%d) for ra%d\n", + wdev->DesiredTransmitSetting.field.MCS, pObj->ioctl_if)); + } +#endif /* CONFIG_AP_SUPPORT */ + + SetCommonHT(pAd); + +#ifdef WFA_VHT_PF +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + INT idx; + + NdisAcquireSpinLock(&pAd->MacTabLock); + for (idx = 1; idx < MAX_LEN_OF_MAC_TABLE; idx++) + { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[idx]; + + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->func_tb_idx == pObj->ioctl_if)) { + if ((HtMcs == MCS_AUTO) && ss == 0) { + UCHAR TableSize = 0; + + pEntry->bAutoTxRateSwitch = TRUE; + + MlmeSelectTxRateTable(pAd, pEntry, &pEntry->pTable, &TableSize, &pEntry->CurrTxRateIndex); + MlmeNewTxRate(pAd, pEntry); + +#ifdef NEW_RATE_ADAPT_SUPPORT + if (! ADAPT_RATE_TABLE(pEntry->pTable)) +#endif /* NEW_RATE_ADAPT_SUPPORT */ + pEntry->HTPhyMode.field.ShortGI = GI_800; + } + else + { + pEntry->HTPhyMode.field.MCS = pMbss->HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((UCHAR)pMbss->DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + } + } + NdisReleaseSpinLock(&pAd->MacTabLock); + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* WFA_VHT_PF */ + + return TRUE; +} + +INT Set_HtGi_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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_HtExtcha_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value == 0) + pAd->CommonCfg.bRdg = FALSE; + else if (Value ==1) + pAd->CommonCfg.bRdg = TRUE; + else + return FALSE; /*Invalid argument*/ + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + pAd->CommonCfg.bRdg = FALSE; +#endif + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtRdg_Proc::(HtRdg=%d)\n",pAd->CommonCfg.bRdg)); + + return TRUE; +} + +INT Set_HtLinkAdapt_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->bLinkAdapt = FALSE; + else if ( Value ==1 ) + 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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + pAd->CommonCfg.BACapability.field.AmsduEnable = (Value == 0) ? FALSE : TRUE; + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtAmsdu_Proc::(HtAmsdu=%d)\n",pAd->CommonCfg.BACapability.field.AmsduEnable)); + + return TRUE; +} + + +INT Set_HtAutoBa_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + if (Value == 0) + pAd->CommonCfg.bHTProtect = FALSE; + else if (Value == 1) + pAd->CommonCfg.bHTProtect = TRUE; + else + return FALSE; /*Invalid argument*/ + + DBGPRINT(RT_DEBUG_TRACE, ("Set_HtProtect_Proc::(HtProtect=%d)\n",pAd->CommonCfg.bHTProtect)); + + return TRUE; +} + +INT Set_SendSMPSAction_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR mac[6], mode; + RTMP_STRING *token; + RTMP_STRING sepValue[] = ":", DASH = '-'; + INT i; + MAC_TABLE_ENTRY *pEntry; + + /*DBGPRINT(RT_DEBUG_TRACE,("\n%s\n", arg));*/ +/* + The BARecTearDown inupt string format should be xx:xx:xx:xx:xx:xx-d, + =>The six 2 digit hex-decimal number previous are the Mac address, + =>The seventh decimal number is the mode value. +*/ + if(strlen(arg) < 19) /*Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and mode value in decimal format.*/ + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + mode = simple_strtol((token+1), 0, 10); + if (mode > MMPS_DISABLE) + return FALSE; + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (&mac[i]), 1); + } + if(i != 6) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x", + PRINT_MAC(mac), mode)); + + pEntry = MacTableLookup(pAd, mac); + + if (pEntry) { + DBGPRINT(RT_DEBUG_OFF, ("\nSendSMPSAction SMPS mode = %d\n", mode)); + SendSMPSAction(pAd, pEntry->wcid, mode); + } + + return TRUE; + } + + return FALSE; + + +} + +INT Set_HtMIMOPSmode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *pParam) +{ + UCHAR bBssCoexEnable = simple_strtol(pParam, 0, 10); +#ifdef WH_EZ_SETUP + POS_COOKIE pObj; + UCHAR apidx; + struct wifi_dev *wdev; + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + wdev = &pAd->ApCfg.ApCliTab[apidx].wdev; + else +#endif /* APCLI_SUPPORT */ + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; +#endif + pAd->CommonCfg.bBssCoexEnable = ((bBssCoexEnable == 1) ? TRUE: FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("Set bBssCoexEnable=%d!\n", pAd->CommonCfg.bBssCoexEnable)); + + if ((pAd->CommonCfg.bBssCoexEnable == FALSE) + && pAd->CommonCfg.bRcvBSSWidthTriggerEvents) + { + /* switch back 20/40 */ + DBGPRINT(RT_DEBUG_TRACE, ("Set bBssCoexEnable: Switch back 20/40. \n")); + pAd->CommonCfg.bRcvBSSWidthTriggerEvents = FALSE; + if ((pAd->CommonCfg.Channel <=14) && (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = 1; + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; + } +#if (defined(WH_EZ_SETUP) && defined(EZ_NETWORK_MERGE_SUPPORT)) + if ((wdev != NULL) && IS_EZ_SETUP_ENABLED(wdev)){ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("\nSet_HT_BssCoex_Proc: Coex support disabled ****\n")); + ez_set_ap_fallback_context(wdev,FALSE,0); + } +#endif /* WH_EZ_SETUP */ + + } + + return TRUE; +} + + +INT Set_HT_BssCoexApCntThr_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *pParam) +{ + pAd->CommonCfg.BssCoexApCntThr = simple_strtol(pParam, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("Set BssCoexApCntThr=%d!\n", pAd->CommonCfg.BssCoexApCntThr)); + + return TRUE; +} +#endif /* DOT11N_DRAFT3 */ + +#endif /* DOT11_N_SUPPORT */ + + +#ifdef DOT11_VHT_AC +INT Set_VhtBw_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG vht_cw; + UCHAR cent_ch; + vht_cw = simple_strtol(arg, 0, 10); + + + if (vht_cw == VHT_BW_80) + pAd->CommonCfg.vht_bw = VHT_BW_80; + else + pAd->CommonCfg.vht_bw = VHT_BW_2040; + + if (!WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) + goto direct_done; + + SetCommonHT(pAd); + if(pAd->CommonCfg.BBPCurrentBW == BW_80) + cent_ch = pAd->CommonCfg.vht_cent_ch; + else + cent_ch = pAd->CommonCfg.CentralChannel; + + AsicSwitchChannel(pAd, cent_ch, FALSE); + AsicLockChannel(pAd, cent_ch); + + DBGPRINT(RT_DEBUG_TRACE, ("BW_%s, PrimaryChannel(%d), %s CentralChannel = %d, apply it immediately\n", + (pAd->CommonCfg.BBPCurrentBW == BW_80 ? "80": + (pAd->CommonCfg.BBPCurrentBW == BW_40 ? "40" : + "20")), + pAd->CommonCfg.Channel, + (pAd->CommonCfg.BBPCurrentBW == BW_80 ? "VHT" : "HT"), cent_ch)); + +direct_done: + + DBGPRINT(RT_DEBUG_TRACE, ("Set_VhtBw_Proc::(VHT_BW=%d)\n", pAd->CommonCfg.vht_bw)); + + return TRUE; +} + + +INT set_VhtBwSignal_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG bw_signal = simple_strtol(arg, 0, 10); + + if (bw_signal <= 2) + pAd->CommonCfg.vht_bw_signal = bw_signal; + else + pAd->CommonCfg.vht_bw_signal = BW_SIGNALING_DISABLE; + DBGPRINT(RT_DEBUG_TRACE, ("%s(): vht_bw_signal=%d(%s)\n", + __FUNCTION__, pAd->CommonCfg.vht_bw_signal, + (pAd->CommonCfg.vht_bw_signal == BW_SIGNALING_DYNAMIC ? "Dynamic" : + (pAd->CommonCfg.vht_bw_signal == BW_SIGNALING_STATIC ? "Static" : "Disable")))); + + return TRUE; +} + + +INT Set_VhtStbc_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value == STBC_USE) + pAd->CommonCfg.vht_stbc = STBC_USE; + else if ( Value == STBC_NONE ) + pAd->CommonCfg.vht_stbc = STBC_NONE; + else + return FALSE; /*Invalid argument */ + + SetCommonHT(pAd); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_VhtStbc_Proc::(VhtStbc=%d)\n", pAd->CommonCfg.vht_stbc)); + + return TRUE; +} + +INT Set_VhtDisallowNonVHT_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + + if (Value == 0) + pAd->CommonCfg.bNonVhtDisallow = FALSE; + else + pAd->CommonCfg.bNonVhtDisallow = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("Set_VhtDisallowNonVHT_Proc::(bNonVhtDisallow=%d)\n", pAd->CommonCfg.bNonVhtDisallow)); + + return TRUE; +} +#endif /* DOT11_VHT_AC */ + + + +INT Set_FixedTxMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + struct wifi_dev *wdev = NULL; +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; +#endif /* CONFIG_AP_SUPPORT */ + INT fix_tx_mode = RT_CfgSetFixedTxPhyMode(arg); + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; +#endif /* CONFIG_AP_SUPPORT */ + + if (wdev) + wdev->DesiredTransmitSetting.field.FixedTxMode = fix_tx_mode; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():(FixedTxMode=%d)\n", + __FUNCTION__, fix_tx_mode)); + + return TRUE; +} + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +INT Set_OpMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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) { + struct raw_rssi_info rssi_info; + + rssi_info.raw_rssi[0] = (CHAR)oldTail->data[0]; + rssi_info.raw_rssi[1] = (CHAR)oldTail->data[1]; + rssi_info.raw_rssi[2] = (CHAR)oldTail->data[2]; + DBGPRINT(RT_DEBUG_OFF, ("Rx2 %2d %2d %2d S:%d %d %d ", + ConvertToRssi(pAd, &rssi_info, RSSI_IDX_0), + ConvertToRssi(pAd, &rssi_info, RSSI_IDX_1), + ConvertToRssi(pAd, &rssi_info, RSSI_IDX_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; + + + 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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 streamWord, reg, regAddr; + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(): Not support for HIF_MT yet!\n", + __FUNCTION__)); + return FALSE; + } + + 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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + return FALSE; +} + + +INT Set_StreamModeMCS_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->CommonCfg.PreAntSwitchTimeout = simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s():(PreAntSwitchTimeout=%d)\n", + __FUNCTION__, pAd->CommonCfg.PreAntSwitchTimeout)); + return TRUE; +} +#endif /* PRE_ANT_SWITCH */ + + + +#ifdef MT_MAC +#ifdef DBG +UINT8 +raStbcSettingCheck( + UINT8 ucOrigStbc, + UINT8 ucMode, + UINT8 ucMcs, + UINT8 ucVhtNss, + BOOLEAN fgBFOn, + BOOLEAN fgForceOneTx) +{ + UINT8 ucStbc = 0; + + if (fgForceOneTx == TRUE) + return ucStbc; + + if (fgBFOn == TRUE) + return ucStbc; + + switch (ucMode) { + case MODE_VHT: + if (ucVhtNss == 1) + ucStbc = ucOrigStbc; + else + ucStbc = 0; + break; + case MODE_HTMIX: + case MODE_HTGREENFIELD: + if (ucMcs < MCS_8) + ucStbc = ucOrigStbc; + else + ucStbc = 0; + break; + case MODE_CCK: + case MODE_OFDM: + default: + ucStbc = 0; + break; + } + + return ucStbc; +} + +INT Set_Fixed_Rate_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + BOOLEAN fgStatus = TRUE; + UINT32 ret; + INT32 i4Recv = 0; + UINT32 u4WCID = 0; + UINT32 u4Mode = 0, u4Bw = 0, u4Mcs = 0, u4VhtNss = 0; + UINT32 u4SGI = 0, u4Preamble = 0, u4STBC = 0, u4LDPC = 0, u4SpeEn = 0; + MAC_TABLE_ENTRY *pEntry = NULL; + + if (arg) { + do { + i4Recv = sscanf(arg, "%d-%d-%d-%d-%d-%d-%d-%d-%d-%d", &(u4WCID), + &(u4Mode), &(u4Bw), &(u4Mcs), &(u4VhtNss), + &(u4SGI), &(u4Preamble), &(u4STBC), &(u4LDPC), &(u4SpeEn)); + DBGPRINT(RT_DEBUG_TRACE, ("%s():WCID = %d, Mode = %d, BW = %d, MCS = %d, VhtNss = %d\n" + "\t\t\t\tSGI = %d, Preamble = %d, STBC = %d, LDPC = %d, SpeEn = %d\n", + __func__, u4WCID, u4Mode, u4Bw, u4Mcs, u4VhtNss, + u4SGI, u4Preamble, u4STBC, u4LDPC, u4SpeEn)); + + if (i4Recv != 10) { + DBGPRINT(RT_DEBUG_ERROR, ("Format Error!\n")); + fgStatus = FALSE; + break; + } + + if (!VALID_UCAST_ENTRY_WCID(u4WCID)) { + DBGPRINT(RT_DEBUG_ERROR, ("WCID exceed pAd->MaxUcastEntryNum!\n")); + fgStatus = FALSE; + break; + } + + if (u4Mode > MODE_VHT) { + DBGPRINT(RT_DEBUG_ERROR, ("Unknown Mode!\n")); + fgStatus = FALSE; + break; + } + + if (u4Bw > 4) { + DBGPRINT(RT_DEBUG_ERROR, ("Unknown BW!\n")); + fgStatus = FALSE; + break; + } + + if (((u4Mode == MODE_CCK) && (u4Mcs > 3)) || + ((u4Mode == MODE_OFDM) && (u4Mcs > 7)) || + ((u4Mode == MODE_HTMIX) && (u4Mcs > 32)) || + ((u4Mode == MODE_VHT) && (u4Mcs > 9))) { + DBGPRINT(RT_DEBUG_ERROR, ("Unknown MCS!\n")); + fgStatus = FALSE; + break; + } + + if ((u4Mode == MODE_VHT) && (u4VhtNss > 4)) { + DBGPRINT(RT_DEBUG_ERROR, ("Unknown VhtNss!\n")); + fgStatus = FALSE; + break; + } + + RTMP_SEM_EVENT_WAIT(&pAd->AutoRateLock, ret); + + pEntry = &pAd->MacTab.Content[u4WCID]; + + if (IS_ENTRY_NONE(pEntry)) { + RTMP_SEM_EVENT_UP(&pAd->AutoRateLock); + break; + } + + u4STBC = raStbcSettingCheck(u4STBC, u4Mode, u4Mcs, u4VhtNss, 0, 0); + + pEntry->HTPhyMode.field.MODE = u4Mode; + pEntry->HTPhyMode.field.iTxBF = 0; + pEntry->HTPhyMode.field.eTxBF = 0; + pEntry->HTPhyMode.field.STBC = u4STBC?1:0; + pEntry->HTPhyMode.field.ShortGI = u4SGI?1:0; + pEntry->HTPhyMode.field.BW = u4Bw; + pEntry->HTPhyMode.field.ldpc = u4LDPC?1:0; + pEntry->HTPhyMode.field.MCS = u4Mcs; + + pEntry->LastTxRate = pEntry->HTPhyMode.word; + pAd->LastTxRate = pEntry->HTPhyMode.word; + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + pEntry->wdev->bAutoTxRateSwitch = FALSE; + } +#endif /* CONFIG_AP_SUPPORT */ + + pEntry->bAutoTxRateSwitch = FALSE; + +#ifdef MCS_LUT_SUPPORT + asic_mcs_lut_update(pAd, pEntry); + pEntry->LastTxRate = (USHORT) (pEntry->HTPhyMode.word); +#endif /* MCS_LUT_SUPPORT */ + + RTMP_SEM_EVENT_UP(&pAd->AutoRateLock); + } while (0); + } + + if (fgStatus == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, + ("iwpriv ra0 set FixedRate=[WCID]-[Mode]-[BW]-[MCS]-[VhtNss]-[SGI]-[Preamble]-[STBC]-[LDPC]-[SPE_EN]\n")); + DBGPRINT(RT_DEBUG_ERROR, ("[WCID]Wireless Client ID\n")); + DBGPRINT(RT_DEBUG_ERROR, ("[Mode]CCK=0, OFDM=1, HT=2, GF=3, VHT=4\n")); + DBGPRINT(RT_DEBUG_ERROR, ("[BW]BW20=0, BW40=1, BW80=2,BW160=3\n")); + DBGPRINT(RT_DEBUG_ERROR, ("[MCS]CCK=0~4, OFDM=0~7, HT=0~32, VHT=0~9\n")); + DBGPRINT(RT_DEBUG_ERROR, ("[VhtNss]VHT=1~4, Other=ignore\n")); + DBGPRINT(RT_DEBUG_ERROR, ("[Preamble]Long=0, Other=Short\n")); + } else + dump_wtbl_info(pAd, u4WCID); + + return fgStatus; +} + +#endif /* DBG */ + +#ifdef ANTI_INTERFERENCE_SUPPORT +INT Set_DynamicRaInterval(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG irqFlags = 0; + ULONG bDynamicRaInterval; + + bDynamicRaInterval = simple_strtol(arg, 0, 10); + + if (bDynamicRaInterval == 0) { + pAd->bDynamicRaInterval = FALSE; + RTMP_IRQ_LOCK(&pAd->irq_lock, irqFlags); + pAd->ra_interval = DEF_RA_TIME_INTRVAL; + pAd->ra_fast_interval = DEF_QUICK_RA_TIME_INTERVAL; + +#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); + } else + pAd->bDynamicRaInterval = TRUE; + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("%s()::bDynamicRaInterval=%d\n", + __FUNCTION__, pAd->bDynamicRaInterval)); + + return TRUE; +} + +INT Set_SwiftTrainThrd(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + BOOLEAN fgStatus = TRUE; + INT32 i4Recv = 0; + UINT32 u4WCID = 0, u4SwiftTrainThrd = 0; + MAC_TABLE_ENTRY *pEntry = NULL; + + if (arg) { + i4Recv = sscanf(arg, "%d-%d", &(u4WCID), &(u4SwiftTrainThrd)); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s():WCID = %d, SwiftTrainThrd = %d\n", __FUNCTION__, u4WCID, u4SwiftTrainThrd)); + + if (i4Recv != 2) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("Format Error!\n")); + fgStatus = FALSE; + return fgStatus; + } + pEntry = &pAd->MacTab.Content[u4WCID]; + + if (!IS_ENTRY_NONE(pEntry)) + pEntry->SwiftTrainThrd = u4SwiftTrainThrd; + } + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("%s()::SwiftTrainThrd=%d\n", + __FUNCTION__, pEntry->SwiftTrainThrd)); + + return fgStatus; +} +#endif /* ANTI_INTERFERENCE_SUPPORT */ + +#endif /* MT_MAC */ + +#ifdef CFO_TRACK +/* + Set_CFOTrack_Proc - enable/disable CFOTrack + usage: iwpriv ra0 set CFOTrack=[0..8] +*/ +INT Set_CFOTrack_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->CommonCfg.DebugFlags = simple_strtol(arg, 0, 16); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_DebugFlags_Proc::(DebugFlags=%02lX)\n", pAd->CommonCfg.DebugFlags)); + return TRUE; +} +#endif /* DBG_CTRL_SUPPORT */ + + + + + + +INT Set_LongRetryLimit_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR LongRetryLimit = (UCHAR)simple_strtol(arg, 0, 10); + + AsicSetRetryLimit(pAd, TX_RTY_CFG_RTY_LIMIT_LONG, LongRetryLimit); + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_LongRetryLimit_Proc::(LongRetryLimit=0x%x)\n", LongRetryLimit)); + return TRUE; +} + + +INT Set_ShortRetryLimit_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR ShortRetryLimit = (UCHAR)simple_strtol(arg, 0, 10); + +#ifdef MT_MAC + pAd->shortretry = ShortRetryLimit; +#else/* !MT_MAC */ + AsicSetRetryLimit(pAd, TX_RTY_CFG_RTY_LIMIT_SHORT, ShortRetryLimit); +#endif /* MT_MAC */ + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_ShortRetryLimit_Proc::(ShortRetryLimit=0x%x)\n", ShortRetryLimit)); + return TRUE; +} + + +INT Set_AutoFallBack_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + return RT_CfgSetAutoFallBack(pAd, arg); +} + + + +RTMP_STRING *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"; + } +} + +RTMP_STRING *RTMPGetRalinkEncryModeStr( + IN USHORT encryMode) +{ + switch(encryMode) + { + case Ndis802_11WEPDisabled: + return "NONE"; + case Ndis802_11WEPEnabled: + return "WEP"; + case Ndis802_11TKIPEnable: + return "TKIP"; + case Ndis802_11AESEnable: + return "AES"; + case Ndis802_11TKIPAESMix: + return "TKIPAES"; + default: + return "UNKNOW"; + } +} + +#ifdef DBG +INT Show_SSID_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *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 */ + + + snprintf(pBuf, BufLen, "\t%s", ssid_str); + return 0; +} + +INT Show_WirelessMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + + switch(pAd->CommonCfg.PhyMode) + { + case (WMODE_B | WMODE_G): + snprintf(pBuf, BufLen, "\t11B/G"); + break; + case (WMODE_B): + snprintf(pBuf, BufLen, "\t11B"); + break; + case (WMODE_A): + snprintf(pBuf, BufLen, "\t11A"); + break; + case (WMODE_A | WMODE_B | WMODE_G): + snprintf(pBuf, BufLen, "\t11A/B/G"); + break; + case (WMODE_G): + snprintf(pBuf, BufLen, "\t11G"); + break; +#ifdef DOT11_N_SUPPORT + case (WMODE_A | WMODE_B | WMODE_G | WMODE_GN | WMODE_AN): + snprintf(pBuf, BufLen, "\t11A/B/G/N"); + break; + case (WMODE_GN): + snprintf(pBuf, BufLen, "\t11N only with 2.4G"); + break; + case (WMODE_G | WMODE_GN): + snprintf(pBuf, BufLen, "\t11G/N"); + break; + case (WMODE_A | WMODE_AN): + snprintf(pBuf, BufLen, "\t11A/N"); + break; + case (WMODE_B | WMODE_G | WMODE_GN): + snprintf(pBuf, BufLen, "\t11B/G/N"); + break; + case (WMODE_A | WMODE_G | WMODE_GN | WMODE_AN): + snprintf(pBuf, BufLen, "\t11A/G/N"); + break; + case (WMODE_AN): + snprintf(pBuf, BufLen, "\t11N only with 5G"); + break; +#endif /* DOT11_N_SUPPORT */ + default: + snprintf(pBuf, BufLen, "\tUnknow Value(%d)", pAd->CommonCfg.PhyMode); + break; + } + + return 0; +} + + +INT Show_TxBurst_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%lu", pAd->CommonCfg.TxPowerPercentage); + return 0; +} + +INT Show_Channel_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%d", pAd->CommonCfg.Channel); + return 0; +} + +INT Show_BGProtection_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *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 RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%u", pAd->CommonCfg.RtsThreshold); + return 0; +} + +INT Show_FragThreshold_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + struct wifi_dev *wdev = NULL; +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; +#endif /* CONFIG_AP_SUPPORT */ + + if (wdev) + snprintf(pBuf, BufLen, "\t%u", wdev->DesiredTransmitSetting.field.MCS); + return 0; +} + +INT Show_HtGi_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%d", pAd->CommonCfg.CountryRegion); + return 0; +} + +INT Show_CountryRegionABand_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%d", pAd->CommonCfg.CountryRegionForABand); + return 0; +} + +INT Show_CountryCode_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *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 RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%s", pAd->CommonCfg.bAggregationCapable ? "TRUE":"FALSE"); + return 0; +} +#endif /* AGGREGATION_SUPPORT */ + +INT Show_WmmCapable_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *pBuf, + IN ULONG BufLen) +{ +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + snprintf(pBuf, BufLen, "\t%s", pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev.bWmmCapable ? "TRUE":"FALSE"); +#endif /* CONFIG_AP_SUPPORT */ + + + return 0; +} + + +INT Show_IEEE80211H_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\t%s", pAd->CommonCfg.bIEEE80211H ? "TRUE":"FALSE"); + return 0; +} + + +INT Show_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + NDIS_802_11_AUTHENTICATION_MODE AuthMode = Ndis802_11AuthModeOpen; + struct wifi_dev *wdev = NULL; +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; +#endif /* CONFIG_AP_SUPPORT */ + + + if (!wdev) + return -1; + + AuthMode = wdev->AuthMode; + if ((AuthMode >= Ndis802_11AuthModeOpen) && + (AuthMode <= Ndis802_11AuthModeWPA1PSKWPA2PSK)) + snprintf(pBuf, BufLen, "\t%s", RTMPGetRalinkAuthModeStr(AuthMode)); +#ifdef WAPI_SUPPORT + else if (AuthMode == Ndis802_11AuthModeWAICERT) + snprintf(pBuf, BufLen, "\t%s", "WAI_CERT"); + else if (AuthMode == Ndis802_11AuthModeWAIPSK) + snprintf(pBuf, BufLen, "\t%s", "WAI_PSK"); +#endif /* WAPI_SUPPORT */ +#ifdef DOT11_SAE_SUPPORT + else if (AuthMode == Ndis802_11AuthModeWPA3PSK) + snprintf(pBuf, BufLen, "\t%s", "WPA3PSK"); + else if (AuthMode == Ndis802_11AuthModeWPA2PSKWPA3PSK) + snprintf(pBuf, BufLen, "\t%s", "WPA2PSKWPA3PSK"); +#endif +#ifdef CONFIG_OWE_SUPPORT + else if (AuthMode == Ndis802_11AuthModeOWE) + snprintf(pBuf, BufLen, "\t%s", "OWE"); +#endif + else + snprintf(pBuf, BufLen, "\tUnknow Value(%d)", AuthMode); + + return 0; +} + +INT Show_EncrypType_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + struct wifi_dev *wdev = NULL; + NDIS_802_11_WEP_STATUS WepStatus = Ndis802_11WEPDisabled; +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; +#endif /* CONFIG_AP_SUPPORT */ + + + if (!wdev) + return -1; + + WepStatus = wdev->WepStatus; + if ((WepStatus >= Ndis802_11WEPEnabled) && + (WepStatus <= Ndis802_11Encryption4KeyAbsent)) + snprintf(pBuf, BufLen, "\t%s", RTMPGetRalinkEncryModeStr(WepStatus)); +#ifdef WAPI_SUPPORT + else if (WepStatus == Ndis802_11EncryptionSMS4Enabled) + snprintf(pBuf, BufLen, "\t%s", "WPI_SMS4"); +#endif /* WAPI_SUPPORT */ + else + snprintf(pBuf, BufLen, "\tUnknow Value(%d)", WepStatus); + + return 0; +} + +INT Show_DefaultKeyID_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + struct wifi_dev *wdev = NULL; +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + wdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev; +#endif /* CONFIG_AP_SUPPORT */ + + + if (!wdev) + return -1; + + snprintf(pBuf, BufLen, "\t%d", wdev->DefaultKeyId); + + return 0; +} + + +INT Show_WepKey_Proc( + IN PRTMP_ADAPTER pAd, + IN INT KeyIdx, + OUT RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + UCHAR Key[16] = {0}, KeyLength = 0; + INT index = BSS0, idx = 0, len = 0, ucMaxKeySize = 0; +#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 + { + len = strlen(pBuf); + ucMaxKeySize = sizeof(Key)/sizeof(Key[0]); + sprintf(pBuf, "\t"); + for (idx = 0; idx < KeyLength; idx++) + { + if(idx < ucMaxKeySize) + len += sprintf(pBuf+len, "%02X", Key[idx]); + } + } + return 0; +} + +INT Show_Key1_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + Show_WepKey_Proc(pAd, 0, pBuf, BufLen); + return 0; +} + +INT Show_Key2_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + Show_WepKey_Proc(pAd, 1, pBuf, BufLen); + return 0; +} + +INT Show_Key3_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + Show_WepKey_Proc(pAd, 2, pBuf, BufLen); + return 0; +} + +INT Show_Key4_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + Show_WepKey_Proc(pAd, 3, pBuf, BufLen); + return 0; +} + +INT Show_PMK_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *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 */ + + + sprintf(pBuf, "\tPMK = "); + for (idx = 0; idx < 32; idx++) + sprintf(pBuf+strlen(pBuf), "%02X", PMK[idx]); + + return 0; +} +#endif /* DBG */ + + +INT Show_STA_RAInfo_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + sprintf(pBuf, "\n"); +#ifdef PRE_ANT_SWITCH + sprintf(pBuf+strlen(pBuf), "PreAntSwitch: %d\n", pAd->CommonCfg.PreAntSwitch); + sprintf(pBuf+strlen(pBuf), "PreAntSwitchRSSI: %d\n", pAd->CommonCfg.PreAntSwitchRSSI); +#endif /* PRE_ANT_SWITCH */ + + +#ifdef NEW_RATE_ADAPT_SUPPORT + sprintf(pBuf+strlen(pBuf), "LowTrafficThrd: %d\n", pAd->CommonCfg.lowTrafficThrd); + sprintf(pBuf+strlen(pBuf), "TrainUpRule: %d\n", pAd->CommonCfg.TrainUpRule); + sprintf(pBuf+strlen(pBuf), "TrainUpRuleRSSI: %d\n", pAd->CommonCfg.TrainUpRuleRSSI); + sprintf(pBuf+strlen(pBuf), "TrainUpLowThrd: %d\n", pAd->CommonCfg.TrainUpLowThrd); + sprintf(pBuf+strlen(pBuf), "TrainUpHighThrd: %d\n", pAd->CommonCfg.TrainUpHighThrd); +#endif // NEW_RATE_ADAPT_SUPPORT // + +#ifdef STREAM_MODE_SUPPORT + sprintf(pBuf+strlen(pBuf), "StreamMode: %d\n", pAd->CommonCfg.StreamMode); + sprintf(pBuf+strlen(pBuf), "StreamModeMCS: 0x%04x\n", pAd->CommonCfg.StreamModeMCS); +#endif // STREAM_MODE_SUPPORT // + +#ifdef DBG_CTRL_SUPPORT + sprintf(pBuf+strlen(pBuf), "DebugFlags: 0x%lx\n", pAd->CommonCfg.DebugFlags); +#endif /* DBG_CTRL_SUPPORT */ + return 0; +} + + +#ifdef DBG +static INT dump_mac_table(RTMP_ADAPTER *pAd, UINT32 ent_type, BOOLEAN bReptCli) +{ + INT i; + ULONG DataRate=0; + + + printk("\n"); + +#ifdef DOT11_N_SUPPORT + printk("HT Operating Mode : %d\n", pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode); + printk("\n"); +#endif /* DOT11_N_SUPPORT */ + + printk("\n%-19s%-5s%-5s%-4s%-4s%-4s%-7s%-10s%-6s%-4s%-6s%-6s%-6s%-7s%-7s%-7s\n", + "MAC", "MODE", "AID", "BSS", "PSM", "WMM", "MIMOPS", "RSSI0/1/2", "PhMd", "BW", "MCS", "SGI", "STBC", "Idle", "Rate", "QosMap"); +#ifdef MWDS + printk("%-8s","MWDSCap"); +#endif /* MWDS */ + + for (i=0; iMacTab.Content[i]; + + if ((ent_type == ENTRY_NONE)) + { + /* dump all MacTable entries */ + if (pEntry->EntryType == ENTRY_NONE) + continue; + } else { + /* dump MacTable entries which match the EntryType */ + if (pEntry->EntryType != ent_type) + continue; + + if ((IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry)) + && (pEntry->Sst != SST_ASSOC)) + continue; + +#ifdef MAC_REPEATER_SUPPORT + if (bReptCli == FALSE) + { + /* only dump the apcli entry which not a RepeaterCli */ + if (IS_ENTRY_APCLI(pEntry) && (pEntry->bReptCli == TRUE)) + continue; + } +#endif /* MAC_REPEATER_SUPPORT */ + } + + DataRate=0; + getRate(pEntry->HTPhyMode, &DataRate); + printk("%02X:%02X:%02X:%02X:%02X:%02X ", PRINT_MAC(pEntry->Addr)); + printk("%-5x", pEntry->EntryType); + printk("%-5d", (int)pEntry->Aid); + printk("%-4d", (int)pEntry->func_tb_idx); + printk("%-4d", (int)pEntry->PsMode); + printk("%-4d", (int)CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_WMM_CAPABLE)); +#ifdef DOT11_N_SUPPORT + printk("%-7d", (int)pEntry->MmpsMode); +#endif /* DOT11_N_SUPPORT */ + printk("%-3d/%-3d/%-3d", pEntry->RssiSample.AvgRssi[0], + pEntry->RssiSample.AvgRssi[1], + pEntry->RssiSample.AvgRssi[2]); + printk("%-6s", get_phymode_str(pEntry->HTPhyMode.field.MODE)); + printk("%-4s", get_bw_str(pEntry->HTPhyMode.field.BW)); +#ifdef DOT11_VHT_AC + if (pEntry->HTPhyMode.field.MODE == MODE_VHT) + printk("%dS-M%d", ((pEntry->HTPhyMode.field.MCS>>4) + 1), (pEntry->HTPhyMode.field.MCS & 0xf)); + else +#endif /* DOT11_VHT_AC */ + printk("%-6d", pEntry->HTPhyMode.field.MCS); + printk("%-4d", pEntry->HTPhyMode.field.ShortGI); + printk("%-5d", pEntry->HTPhyMode.field.STBC); + printk("%-7d", (int)(pEntry->StaIdleTimeout - pEntry->NoDataIdleCount)); + printk("%-7d", (int)DataRate); +#ifdef CONFIG_HOTSPOT_R2 + printk("%-7d", (int)pEntry->QosMapSupport); +#endif + printk("%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount, + (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0); +#ifdef CONFIG_HOTSPOT_R2 + if (pEntry->QosMapSupport) + { + int k =0; + printk("DSCP Exception:\n"); + for(k=0;kDscpExceptionCount/2;k++) + { + printk("[Value: %4d] [UP: %4d]\n", pEntry->DscpException[k] & 0xff, (pEntry->DscpException[k] >> 8) & 0xff); + } + printk("DSCP Range:\n"); + for(k=0;k<8;k++) + { + printk("[UP :%3d][Low Value: %4d] [High Value: %4d]\n", k, pEntry->DscpRange[k] & 0xff, (pEntry->DscpRange[k] >> 8) & 0xff); + } + } +#endif +#ifdef MWDS +#ifdef APCLI_SUPPORT + if(IS_ENTRY_APCLI(pEntry)) + { + if(pEntry->func_tb_idx < MAX_APCLI_NUM) + { + if (pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].MlmeAux.bSupportMWDS) + printk("%-8s", "YES"); + else + printk("%-8s", "NO"); + } + } + else +#endif + { + if (pEntry->bSupportMWDS) + printk("%-8s", "YES"); + else + printk("%-8s", "NO"); + } +#endif +//+++Add by shiang for debug + printk("\t\t\t\t\t\t\tMaxCap:%-10s", get_phymode_str(pEntry->MaxHTPhyMode.field.MODE)); + printk("%-6s", get_bw_str(pEntry->MaxHTPhyMode.field.BW)); +#ifdef DOT11_VHT_AC + if (pEntry->MaxHTPhyMode.field.MODE == MODE_VHT) + printk("%dS-M%d", ((pEntry->MaxHTPhyMode.field.MCS>>4) + 1), (pEntry->MaxHTPhyMode.field.MCS & 0xf)); + else +#endif /* DOT11_VHT_AC */ + printk("%-6d", pEntry->MaxHTPhyMode.field.MCS); + printk("%-4d", pEntry->MaxHTPhyMode.field.ShortGI); + printk("%-5d\n", pEntry->MaxHTPhyMode.field.STBC); +//---Add by shiang for debug + printk("\n"); + } + + return TRUE; +} +#ifdef ACL_BLK_COUNT_SUPPORT +INT Show_ACLRejectCount_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) + { + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + DBGPRINT(RT_DEBUG_TRACE, ("%s(): arg=%s\n", __FUNCTION__, (arg == NULL ? "" : arg))); + if (arg && strlen(arg)) { + if (rtstrcasecmp(arg, "1") == TRUE) { + int count; + DBGPRINT(RT_DEBUG_TRACE, + (" ACL sizeof=%d, ACL: Policy=%lu,ACL: Num=%lu\n", + sizeof(RT_802_11_ACL), + pAd->ApCfg.MBSSID[apidx].AccessControlList.Policy, + pAd->ApCfg.MBSSID[apidx].AccessControlList.Num)); + if (pAd->ApCfg.MBSSID[apidx].AccessControlList.Policy == 2) { + DBGPRINT(RT_DEBUG_OFF, + ("ACL: Policy=%lu(0:Dis,1:WL,2:Blk),ACL: Num=%lu\n", + pAd->ApCfg.MBSSID[apidx].AccessControlList.Policy, + pAd->ApCfg.MBSSID[apidx].AccessControlList.Num)); + for (count = 0; count < pAd->ApCfg.MBSSID[apidx].AccessControlList.Num; count++) { + DBGPRINT(RT_DEBUG_OFF, + ("MAC:%02x:%02x:%02x:%02x:%02x:%02x,RejCount:%lu\n", + PRINT_MAC(pAd->ApCfg.MBSSID[apidx].AccessControlList.Entry[count].Addr), + pAd->ApCfg.MBSSID[apidx].AccessControlList.Entry[count].Reject_Count)); + } + } else { + DBGPRINT(RT_DEBUG_ERROR, + ("ERROR:Now Policy=%lu(0:Dis,1:WL,2:Blk)\n", + pAd->ApCfg.MBSSID[apidx].AccessControlList.Policy)); + } + } + } + return TRUE; + } +#endif/*ACL_BLK_COUNT_SUPPORT*/ +INT Show_MacTable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 ent_type = ENTRY_CLIENT; + + DBGPRINT(RT_DEBUG_OFF, ("%s(): arg=%s\n", __FUNCTION__, (arg == NULL ? "" : arg))); + if (arg && strlen(arg)) { + if (rtstrcasecmp(arg, "sta") == TRUE) + ent_type = ENTRY_CLIENT; + else if (rtstrcasecmp(arg, "ap") == TRUE) + ent_type = ENTRY_AP; + else + ent_type = ENTRY_NONE; + } + + DBGPRINT(RT_DEBUG_OFF, ("Dump MacTable entries info, EntType=0x%x\n", ent_type)); + + return dump_mac_table(pAd, ent_type, FALSE); +} + +#ifdef CONFIG_AP_SUPPORT +INT Show_StationKeepAliveTime_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT i; + + for(i = BSS0; i < pAd->ApCfg.BssidNum; i++) + { + BSS_STRUCT *mbss = &pAd->ApCfg.MBSSID[i]; + + DBGPRINT(RT_DEBUG_OFF, ("[%d] : StationKeepAliveTime=%d\n", i, mbss->StationKeepAliveTime)); + } + + return TRUE; +} +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef MT_MAC +static INT dump_ps_table(RTMP_ADAPTER *pAd, UINT32 ent_type, BOOLEAN bReptCli) +{ + INT i,j; + struct wtbl_entry tb_entry; + union WTBL_1_DW3 *dw3 = (union WTBL_1_DW3 *)&tb_entry.wtbl_1.wtbl_1_d3.word; + UINT32 rPseRdTabAccessReg; + BOOLEAN pfgForce; + UCHAR pucPort, pucQueue; + INT Total_Packet_Number = 0 ; + + printk("\n"); + +#ifdef DOT11_N_SUPPORT + printk("HT Operating Mode : %d\n", pAd->CommonCfg.AddHTInfo.AddHtInfo2.OperaionMode); + printk("\n"); +#endif /* DOT11_N_SUPPORT */ + +#ifdef DATA_QUEUE_RESERVE + printk("pAd->MacTab.fAnyStationInPsm : %d\n", pAd->MacTab.fAnyStationInPsm); + printk("pAd->dequeu_fail_cnt : %u\n", pAd->dequeu_fail_cnt); +#endif /* DATA_QUEUE_RESERVE */ + +#ifdef LIMIT_GLOBAL_SW_QUEUE + for (i = 0; i < WMM_QUE_NUM; i++) + { + printk("AC[%d] Length : %d\n", i, pAd->TxSwQueue[i].Number); + } + printk("\n\n\n"); +#endif /* LIMIT_GLOBAL_SW_QUEUE */ + + printk("\n%-19s\t%-10s\t%-5s\t%-5s\t%-5s\t%-5s\t%-5s\t%-5s\t%-5s\t%-5s\t%-5s\t%-5s\t%-6s\t%-6s\t%-6s", + "MAC", "EntryType", "AID", "BSS", "PSM", "psm", "ipsm", "iips", "sktx", "redt", "port", "queu", "pktnum","psnum","TXOK/PER"); +#ifdef UAPSD_SUPPORT + printk("\t%-7s", "APSD"); +#endif /* UAPSD_SUPPORT */ + printk("\n"); + + if( ent_type!= ENTRY_CAT_MCAST ) + { + for (i=0; iMacTab.Content[i]; + STA_TR_ENTRY *tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + Total_Packet_Number = 0 ; + + if ((ent_type == ENTRY_NONE)) + { + /* dump all MacTable entries */ + if (pEntry->EntryType == ENTRY_NONE) + continue; + } + else + { + /* dump MacTable entries which match the EntryType */ + if (pEntry->EntryType != ent_type) + continue; + + if ((IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry)) + && (pEntry->Sst != SST_ASSOC)) + continue; + +#ifdef MAC_REPEATER_SUPPORT + if (bReptCli == FALSE) + { + /* only dump the apcli entry which not a RepeaterCli */ + if (IS_ENTRY_APCLI(pEntry) && (pEntry->bReptCli == TRUE)) + continue; + } +#endif /* MAC_REPEATER_SUPPORT */ + } + + NdisZeroMemory(&tb_entry, sizeof(tb_entry)); + if (mt_wtbl_get_entry234(pAd, pEntry->wcid, &tb_entry) == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Cannot found WTBL2/3/4\n",__FUNCTION__)); + return FALSE; + } + RTMP_IO_READ32(pAd, tb_entry.wtbl_addr[0]+12, &dw3->word); + + //get PSE register + + // rPseRdTabAccessReg.field.rd_kick_busy=1; + // rPseRdTabAccessReg.field.rd_tag=pEntry->wcid; + rPseRdTabAccessReg = PSE_RTA_RD_KICK_BUSY |PSE_RTA_TAG(pEntry->wcid); + RTMP_IO_WRITE32(pAd, PSE_RTA,rPseRdTabAccessReg); + + do + { + RTMP_IO_READ32(pAd,PSE_RTA,&rPseRdTabAccessReg); + + pfgForce = ( BOOLEAN ) GET_PSE_RTA_RD_RULE_F(rPseRdTabAccessReg); + pucPort = ( UCHAR ) GET_PSE_RTA_RD_RULE_PID(rPseRdTabAccessReg); + pucQueue = ( UCHAR ) GET_PSE_RTA_RD_RULE_QID(rPseRdTabAccessReg); + } + while ( GET_PSE_RTA_RD_KICK_BUSY(rPseRdTabAccessReg) == 1 ); + + Total_Packet_Number = Total_Packet_Number + tr_entry->ps_queue.Number; + for (j = 0; j < WMM_QUE_NUM; j++) + Total_Packet_Number = Total_Packet_Number + tr_entry->tx_queue[j].Number; + + printk("%02X:%02X:%02X:%02X:%02X:%02X", PRINT_MAC(pEntry->Addr)); + printk("\t%-10x", pEntry->EntryType); + printk("\t%-5d", (int)pEntry->Aid); + printk("\t%-5d", (int)pEntry->func_tb_idx); + printk("\t%-5d", (int)pEntry->PsMode); + printk("\t%-5d", (int)dw3->field.psm); + printk("\t%-5d", (int)dw3->field.i_psm); + printk("\t%-5d", (int)dw3->field.du_i_psm); + printk("\t%-5d", (int)dw3->field.skip_tx); + printk("\t%-5d", (int)pfgForce); + printk("\t%-5d", (int)pucPort); + printk("\t%-5d", (int)pucQueue); + printk("\t%-6d", (int)Total_Packet_Number); + printk("\t%-6d", (int)tr_entry->ps_queue.Number); + +#ifdef DATA_QUEUE_RESERVE + printk("\t%-6u", tr_entry->high_pkt_cnt); + printk("\t%-6u", tr_entry->high_pkt_drop_cnt); +#else /* DATA_QUEUE_RESERVE */ + printk("\t%-6u", 0); + printk("\t%-6u", 0); +#endif /* !DATA_QUEUE_RESERVE */ + + printk("\t%-6d/%d", (int)pEntry->LastTxOkCount,(int)pEntry->LastTxPER); +#ifdef UAPSD_SUPPORT + printk("\t%d,%d,%d,%d", + (int)pEntry->bAPSDCapablePerAC[QID_AC_BE], pEntry->bAPSDCapablePerAC[QID_AC_BK], pEntry->bAPSDCapablePerAC[QID_AC_VI], pEntry->bAPSDCapablePerAC[QID_AC_VO]); +#endif /* UAPSD_SUPPORT */ + printk("\n"); + } + } + else + { + + for (i=MAX_LEN_OF_MAC_TABLE; iMacTab.tr_entry[i]; + Total_Packet_Number = 0 ; + + NdisZeroMemory(&tb_entry, sizeof(tb_entry)); + if (mt_wtbl_get_entry234(pAd, tr_entry->wcid, &tb_entry) == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Cannot found WTBL2/3/4\n",__FUNCTION__)); + return FALSE; + } + RTMP_IO_READ32(pAd, tb_entry.wtbl_addr[0]+12, &dw3->word); + + //get PSE register + + // rPseRdTabAccessReg.field.rd_kick_busy=1; + // rPseRdTabAccessReg.field.rd_tag=pEntry->wcid; + rPseRdTabAccessReg = PSE_RTA_RD_KICK_BUSY |PSE_RTA_TAG(i); + RTMP_IO_WRITE32(pAd, PSE_RTA,rPseRdTabAccessReg); + + do + { + RTMP_IO_READ32(pAd,PSE_RTA,&rPseRdTabAccessReg); + + pfgForce = ( BOOLEAN ) GET_PSE_RTA_RD_RULE_F(rPseRdTabAccessReg); + pucPort = ( UCHAR ) GET_PSE_RTA_RD_RULE_PID(rPseRdTabAccessReg); + pucQueue = ( UCHAR ) GET_PSE_RTA_RD_RULE_QID(rPseRdTabAccessReg); + } + while ( GET_PSE_RTA_RD_KICK_BUSY(rPseRdTabAccessReg) == 1 ); + + Total_Packet_Number = Total_Packet_Number + tr_entry->ps_queue.Number; + for (j = 0; j < WMM_QUE_NUM; j++) + Total_Packet_Number = Total_Packet_Number + tr_entry->tx_queue[j].Number; + + printk("%02X:%02X:%02X:%02X:%02X:%02X", PRINT_MAC(tr_entry->Addr)); + printk("\t%-10x", tr_entry->EntryType); + printk("\t%-5d", (int)tr_entry->wcid); + printk("\t%-5d", (int)tr_entry->func_tb_idx); + printk("\t%-5d", (int)tr_entry->PsMode); + printk("\t%-5d", (int)dw3->field.psm); + printk("\t%-5d", (int)dw3->field.i_psm); + printk("\t%-5d", (int)dw3->field.du_i_psm); + printk("\t%-5d", (int)dw3->field.skip_tx); + printk("\t%-5d", (int)pfgForce); + printk("\t%-5d", (int)pucPort); + printk("\t%-5d", (int)pucQueue); + printk("\t%-6d", (int)Total_Packet_Number); + printk("\t%-6d", (int)tr_entry->ps_queue.Number); + +#ifdef DATA_QUEUE_RESERVE + printk("\t%-6u", tr_entry->high_pkt_cnt); + printk("\t%-6u", tr_entry->high_pkt_drop_cnt); +#else /* DATA_QUEUE_RESERVE */ + printk("\t%-6u", 0); + printk("\t%-6u", 0); +#endif /* !DATA_QUEUE_RESERVE */ + +#ifdef UAPSD_SUPPORT + printk("\t%d,%d,%d,%d", + (int)0, 0, 0, 0); +#endif /* UAPSD_SUPPORT */ + printk("\n"); + } + + } + + return TRUE; +} + + +INT Show_PSTable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 ent_type = ENTRY_CLIENT; + + DBGPRINT(RT_DEBUG_ERROR, ("%s(): arg=%s\n", __FUNCTION__, (arg == NULL ? "" : arg))); + if (arg && strlen(arg)) { + if (rtstrcasecmp(arg, "sta") == TRUE) + ent_type = ENTRY_CLIENT; + else if (rtstrcasecmp(arg, "ap") == TRUE) + ent_type = ENTRY_AP; + else if (rtstrcasecmp(arg, "mcast") == TRUE) + ent_type = ENTRY_CAT_MCAST; + else + ent_type = ENTRY_NONE; + } + + DBGPRINT(RT_DEBUG_OFF, ("Dump MacTable entries info, EntType=0x%x\n", ent_type)); + + return dump_ps_table(pAd, ent_type, FALSE); +} +#endif /* MT_MAC */ + + +#ifdef DOT11_N_SUPPORT +INT Show_BaTable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT i, j; + BA_ORI_ENTRY *pOriBAEntry; + BA_REC_ENTRY *pRecBAEntry; + RTMP_STRING tmpBuf[6]; + + for (i=0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i]; + if (IS_ENTRY_NONE(pEntry)) + continue; + + if ((IS_ENTRY_CLIENT(pEntry) || IS_ENTRY_APCLI(pEntry)) + && (pEntry->Sst != SST_ASSOC)) + continue; + + if (IS_ENTRY_APCLI(pEntry)) + strcpy(tmpBuf, "ApCli"); + else if (IS_ENTRY_WDS(pEntry)) + strcpy(tmpBuf, "WDS"); + else if (IS_ENTRY_MESH(pEntry)) + strcpy(tmpBuf, "Mesh"); + else if (IS_ENTRY_AP(pEntry)) + strcpy(tmpBuf, "AP"); + else + strcpy(tmpBuf, "STA"); + + printk("%02X:%02X:%02X:%02X:%02X:%02X (Aid = %d) (%s) -\n", + PRINT_MAC(pEntry->Addr), pEntry->Aid, tmpBuf); + + printk("[Recipient]\n"); + for (j=0; j < NUM_OF_TID; j++) + { + if (pEntry->BARecWcidArray[j] != 0) + { + pRecBAEntry =&pAd->BATable.BARecEntry[pEntry->BARecWcidArray[j]]; + printk("TID=%d, BAWinSize=%d, LastIndSeq=%d, ReorderingPkts=%d\n", j, pRecBAEntry->BAWinSize, pRecBAEntry->LastIndSeq, pRecBAEntry->list.qlen); + } + } + printk("\n"); + + printk("[Originator]\n"); + for (j=0; j < NUM_OF_TID; j++) + { + if (pEntry->BAOriWcidArray[j] != 0) + { + pOriBAEntry =&pAd->BATable.BAOriEntry[pEntry->BAOriWcidArray[j]]; + printk("TID=%d, BAWinSize=%d, StartSeq=%d, CurTxSeq=%d\n", + j, pOriBAEntry->BAWinSize, pOriBAEntry->Sequence, + pAd->MacTab.tr_entry[pEntry->wcid].TxSeq[j]); + } + } + printk("\n\n"); + } + + return TRUE; +} +#endif /* DOT11_N_SUPPORT */ + + +#ifdef MT_MAC +INT show_wtbl_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT i, start, end, idx = -1; + //WTBL_ENTRY wtbl_entry; + + DBGPRINT(RT_DEBUG_OFF, ("%s(): arg=%s\n", __FUNCTION__, (arg == NULL ? "" : arg))); + if (arg!=NULL && strlen(arg)) { + idx = simple_strtoul(arg, NULL, 10); + start = end = idx; + } else { + start = 0; + end = pAd->mac_ctrl.wtbl_entry_cnt[0] - 1; + } + + DBGPRINT(RT_DEBUG_OFF, ("Dump WTBL entries info, start=%d, end=%d, idx=%d\n", + start, end, idx)); + + dump_wtbl_base_info(pAd); + for (i = start; i <= end; i++) + { + dump_wtbl_info(pAd, i); + } + return TRUE; +} + + +INT show_temp_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT32 temp; + temp = MtAsicGetThemalSensor(pAd, 0); + + DBGPRINT(RT_DEBUG_OFF, ("Temperture: %d\n", temp)); + return TRUE; +} + +INT show_mib_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 mac_val, idx, ampdu_cnt[5]; + UINT32 msdr6, msdr7, msdr8, msdr9, msdr10, msdr16, msdr17, msdr18; + UINT32 mbxsdr[4][3]; + UINT32 mbtcr[16], mbtbcr[16], mbrcr[16], mbrbcr[16]; + UINT32 btcr[4], btbcr[4], brcr[4], brbcr[4]; + + RTMP_IO_READ32(pAd, MIB_MSCR, &mac_val); + DBGPRINT(RT_DEBUG_OFF, ("MIB Status Control=0x%x\n", mac_val)); + RTMP_IO_READ32(pAd, MIB_MPBSCR, &mac_val); + DBGPRINT(RT_DEBUG_OFF, ("MIB Per-BSS Status Control=0x%x\n", mac_val)); + + RTMP_IO_READ32(pAd, MIB_MSDR6, &msdr6); + RTMP_IO_READ32(pAd, MIB_MSDR7, &msdr7); + RTMP_IO_READ32(pAd, MIB_MSDR8, &msdr8); + RTMP_IO_READ32(pAd, MIB_MSDR9, &msdr9); + RTMP_IO_READ32(pAd, MIB_MSDR10, &msdr10); + RTMP_IO_READ32(pAd, MIB_MSDR16, &msdr16); + RTMP_IO_READ32(pAd, MIB_MSDR17, &msdr17); + RTMP_IO_READ32(pAd, MIB_MSDR18, &msdr18); + DBGPRINT(RT_DEBUG_OFF, ("===Phy/Timing Related Counters===\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tChannelIdleCnt=0x%x\n", msdr6 & 0xffff)); + DBGPRINT(RT_DEBUG_OFF, ("\tCCA_NAV_Tx_Time=0x%x\n", msdr9 & 0xffffff)); + DBGPRINT(RT_DEBUG_OFF, ("\tRx_MDRDY_CNT=0x%x\n", msdr10 & 0x3ffffff)); + DBGPRINT(RT_DEBUG_OFF, ("\tPrim CCA Time=0x%x\n", msdr16 & 0xffffff)); + DBGPRINT(RT_DEBUG_OFF, ("\tSec CCA Time=0x%x\n", msdr17 & 0xffffff)); + DBGPRINT(RT_DEBUG_OFF, ("\tPrim ED Time=0x%x\n", msdr18 & 0xffffff)); + + DBGPRINT(RT_DEBUG_OFF, ("===Tx Related Counters(Generic)===\n")); + RTMP_IO_READ32(pAd, MIB_MSDR0, &mac_val); + DBGPRINT(RT_DEBUG_OFF, ("\tBeaconTxCnt=0x%x\n", mac_val)); + RTMP_IO_READ32(pAd, MIB_MDR0, &mac_val); + DBGPRINT(RT_DEBUG_OFF, ("\tTx 40MHz Cnt=0x%x\n", (mac_val >> 16) & 0xffff)); + RTMP_IO_READ32(pAd, MIB_MDR1, &mac_val); + DBGPRINT(RT_DEBUG_OFF, ("\tTx 80MHz Cnt=0x%x\n", mac_val& 0xffff)); + DBGPRINT(RT_DEBUG_OFF, ("\tTx 160MHz Cnt=0x%x\n", (mac_val >> 16) & 0xffff)); + + DBGPRINT(RT_DEBUG_OFF, ("===AMPDU Related Counters===\n")); + RTMP_IO_READ32(pAd, MIB_MSDR12, &du_cnt[0]); + RTMP_IO_READ32(pAd, MIB_MSDR14, &du_cnt[1]); + RTMP_IO_READ32(pAd, MIB_MSDR15, &du_cnt[2]); + RTMP_IO_READ32(pAd, MIB_MDR2, &du_cnt[3]); + RTMP_IO_READ32(pAd, MIB_MDR3, &du_cnt[4]); + DBGPRINT(RT_DEBUG_OFF, ("\tRx BA_Cnt=0x%x\n", ampdu_cnt[0] & 0xffff)); + DBGPRINT(RT_DEBUG_OFF, ("\tTx AMPDU_Burst_Cnt=0x%x\n", (ampdu_cnt[0] >> 16 ) & 0xffff)); + DBGPRINT(RT_DEBUG_OFF, ("\tTx AMPDU_Pkt_Cnt=0x%x\n", ampdu_cnt[1] & 0xffffff)); + DBGPRINT(RT_DEBUG_OFF, ("\tAMPDU SuccessCnt=0x%x\n", ampdu_cnt[2] & 0xffffff)); + DBGPRINT(RT_DEBUG_OFF, ("\tTx Agg Range: \t1 \t2~5 \t6~15 \t16~\n")); + DBGPRINT(RT_DEBUG_OFF, ("\t\t\t0x%x \t0x%x \t0x%x \t0x%x \n", + (ampdu_cnt[3]) & 0xffff, (ampdu_cnt[3] >> 16) & 0xffff, + (ampdu_cnt[4]) & 0xffff, (ampdu_cnt[4] >> 16) & 0xfff)); + + DBGPRINT(RT_DEBUG_OFF, ("===Rx Related Counters(Generic)===\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tVector Overflow Drop Cnt=0x%x\n", (msdr6 >> 16 ) & 0xffff)); + DBGPRINT(RT_DEBUG_OFF, ("\tVector Missmacth Cnt=0x%x\n", (msdr7 >> 16 ) & 0xffff)); + DBGPRINT(RT_DEBUG_OFF, ("\tDelimiter Fail Cnt=0x%x\n", msdr8& 0xffff)); + RTMP_IO_READ32(pAd, MIB_MSDR4, &mac_val); + DBGPRINT(RT_DEBUG_OFF, ("\tRxFifoFullCnt=0x%x\n", mac_val & 0xffff)); + DBGPRINT(RT_DEBUG_OFF, ("\tRxFCSErrCnt=0x%x\n", (mac_val >> 16 ) & 0xffff)); + RTMP_IO_READ32(pAd, MIB_MSDR5, &mac_val); + DBGPRINT(RT_DEBUG_OFF, ("\tRxMPDUCnt=0x%x\n", mac_val & 0xffff)); + DBGPRINT(RT_DEBUG_OFF, ("\tPFDropCnt=0x%x\n", (mac_val >> 16 ) & 0x00ff)); + RTMP_IO_READ32(pAd, MIB_MSDR22, &mac_val); + DBGPRINT(RT_DEBUG_OFF, ("\tRx AMPDU Cnt=0x%x\n", mac_val & 0xffff)); + RTMP_IO_READ32(pAd, MIB_MSDR23, &mac_val); + DBGPRINT(RT_DEBUG_OFF, ("\tRx Total ByteCnt=0x%x\n", mac_val)); + + for (idx = 0; idx < 4; idx++) { + RTMP_IO_READ32(pAd, WTBL_BTCRn + idx * 4, &btcr[idx]); + RTMP_IO_READ32(pAd, WTBL_BTBCRn + idx * 4, &btbcr[idx]); + RTMP_IO_READ32(pAd, WTBL_BRCRn + idx * 4, &brcr[idx]); + RTMP_IO_READ32(pAd, WTBL_BRBCRn + idx * 4, &brbcr[idx]); + } + DBGPRINT(RT_DEBUG_OFF, ("===Per-BSS Related Tx/Rx Counters===\n")); + DBGPRINT(RT_DEBUG_OFF, ("BSS Idx TxCnt/DataCnt TxByteCnt RxCnt/DataCnt RxByteCnt\n")); + for (idx = 0; idx < 4; idx++) { + DBGPRINT(RT_DEBUG_OFF, ("%d\t 0x%x/0x%x\t 0x%x \t 0x%x/0x%x \t 0x%x\n", + idx, (btcr[idx] >> 16) & 0xffff, btcr[idx] & 0xffff, btbcr[idx], + (brcr[idx] >> 16) & 0xffff, brcr[idx] & 0xffff, brbcr[idx])); + } + + + for (idx = 0; idx < 4; idx++) + { + RTMP_IO_READ32(pAd, MIB_MB0SDR0 + idx * 0x10, &mbxsdr[idx][0]); + RTMP_IO_READ32(pAd, MIB_MB0SDR1 + idx * 0x10, &mbxsdr[idx][1]); + RTMP_IO_READ32(pAd, MIB_MB0SDR2 + idx * 0x10, &mbxsdr[idx][2]); + } + DBGPRINT(RT_DEBUG_OFF, ("===Per-MBSS Related MIB Counters===\n")); + DBGPRINT(RT_DEBUG_OFF, ("BSS Idx RTSTx/RetryCnt BAMissCnt AckFailCnt FrmRetry1/2Cnt\n")); + for (idx = 0; idx < 4; idx++) { + DBGPRINT(RT_DEBUG_OFF, ("%d:\t0x%x/0x%x 0x%x \t 0x%x \t 0x%x/0x%x\n", + idx, mbxsdr[idx][0], (mbxsdr[idx][0] >> 16) & 0xffff, + mbxsdr[idx][1], (mbxsdr[idx][1] >> 16) & 0xffff, + mbxsdr[idx][2], (mbxsdr[idx][2] >> 16) & 0xffff)); + } + + + for (idx = 0; idx < 8; idx++) { + RTMP_IO_READ32(pAd, WTBL_MBTCRn + idx * 4, &mbtcr[idx]); + RTMP_IO_READ32(pAd, WTBL_MBRCRn + idx * 4, &mbrcr[idx]); + } + + for (idx = 0; idx < 16; idx++) { + RTMP_IO_READ32(pAd, WTBL_MBTBCRn + idx * 4, &mbtbcr[idx]); + RTMP_IO_READ32(pAd, WTBL_MBRBCRn + idx * 4, &mbrbcr[idx]); + } + DBGPRINT(RT_DEBUG_OFF, ("===Per-MBSS Related Tx/Rx Counters===\n")); + DBGPRINT(RT_DEBUG_OFF, ("MBSSIdx TxDataCnt TxByteCnt RxDataCnt RxByteCnt\n")); + for (idx = 0; idx < 16; idx++) { + DBGPRINT(RT_DEBUG_OFF, ("%d\t 0x%x\t 0x%x \t 0x%x \t 0x%x\n", + idx, + ((idx % 2 == 1) ? (mbtcr[idx/2] >> 16) & 0xffff : mbtcr[idx/2] & 0xffff), + mbtbcr[idx], + ((idx % 2 == 1) ? (mbrcr[idx/2] >> 16) & 0xffff : mbrcr[idx/2] & 0xffff), + mbrbcr[idx])); + } + + return TRUE; +} + + +INT32 ShowTmacInfo(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 Value; + + RTMP_IO_READ32(pAd, TMAC_TCR, &Value); + DBGPRINT(RT_DEBUG_OFF, ("TX Stream = %d\n", GET_TMAC_TCR_TX_STREAM_NUM(Value) + 1)); + DBGPRINT(RT_DEBUG_OFF, ("TX RIFS Enable = %d\n", GET_TX_RIFS_EN(Value))); + DBGPRINT(RT_DEBUG_OFF, ("RX RIFS Mode = %d\n", GET_RX_RIFS_MODE(Value))); + DBGPRINT(RT_DEBUG_OFF, ("TXOP TBTT Control = %d\n", GET_TXOP_TBTT_CONTROL(Value))); + DBGPRINT(RT_DEBUG_OFF, ("TXOP TBTT Stop Control = %d\n", GET_TBTT_TX_STOP_CONTROL(Value))); + DBGPRINT(RT_DEBUG_OFF, ("TXOP Burst Stop = %d\n", GET_TXOP_BURST_STOP(Value))); + DBGPRINT(RT_DEBUG_OFF, ("RDG Mode = %d\n", GET_RDG_RA_MODE(Value))); + DBGPRINT(RT_DEBUG_OFF, ("RDG Responser Enable = %d\n", GET_RDG_RESP_EN(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Smoothing = %d\n", GET_SMOOTHING(Value))); + + RTMP_IO_READ32(pAd, TMAC_PSCR, &Value); + DBGPRINT(RT_DEBUG_OFF, ("AP Power Save RXPE Off Time(unit 2us) = %d\n", GET_APS_OFF_TIME(Value))); + DBGPRINT(RT_DEBUG_OFF, ("AP Power Save RXPE On Time(unit 2us) = %d\n", APS_ON_TIME(Value))); + DBGPRINT(RT_DEBUG_OFF, ("AP Power Save Halt Time (unit 32us) = %d\n", GET_APS_HALT_TIME(Value))); + DBGPRINT(RT_DEBUG_OFF, ("AP Power Enable = %d\n", GET_APS_EN(Value))); + + RTMP_IO_READ32(pAd, TMAC_ACTXOPLR1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("AC0 TXOP = 0x%x (unit: 32us)\n", GET_AC0LIMIT(Value))); + DBGPRINT(RT_DEBUG_OFF, ("AC1 TXOP = 0x%x (unit: 32us)\n", GET_AC1LIMIT(Value))); + + RTMP_IO_READ32(pAd, TMAC_ACTXOPLR0, &Value); + DBGPRINT(RT_DEBUG_OFF, ("AC2 TXOP = 0x%x (unit: 32us)\n", GET_AC2LIMIT(Value))); + DBGPRINT(RT_DEBUG_OFF, ("AC3 TXOP = 0x%x (unit: 32us)\n", GET_AC3LIMIT(Value))); + + RTMP_IO_READ32(pAd, TMAC_ACTXOPLR3, &Value); + DBGPRINT(RT_DEBUG_OFF, ("AC10 TXOP = 0x%x (unit: 32us)\n", GET_AC10LIMIT(Value))); + DBGPRINT(RT_DEBUG_OFF, ("AC11 TXOP = 0x%x (unit: 32us)\n", GET_AC11LIMIT(Value))); + + RTMP_IO_READ32(pAd, TMAC_ACTXOPLR2, &Value); + DBGPRINT(RT_DEBUG_OFF, ("AC12 TXOP = 0x%x (unit: 32us)\n", GET_AC12LIMIT(Value))); + DBGPRINT(RT_DEBUG_OFF, ("AC13 TXOP = 0x%x (unit: 32us)\n", GET_AC13LIMIT(Value))); + + RTMP_IO_READ32(pAd, TMAC_ICR, &Value); + DBGPRINT(RT_DEBUG_OFF, ("EIFS Time (unit: 1us) = %d\n", GET_ICR_EIFS_TIME(Value))); + DBGPRINT(RT_DEBUG_OFF, ("RIFS Time (unit: 1us) = %d\n", GET_ICR_RIFS_TIME(Value))); + DBGPRINT(RT_DEBUG_OFF, ("SIFS Time (unit: 1us) = %d\n", GET_ICR_SIFS_TIME(Value))); + DBGPRINT(RT_DEBUG_OFF, ("SLOT Time (unit: 1us) = %d\n", GET_ICR_SLOT_TIME(Value))); + + RTMP_IO_READ32(pAd, ATCR, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Aggregation Timeout (unit: 50ns) = 0x%x\n", GET_AGG_TOUT(Value))); + + return 0; +} + + +INT32 ShowAggInfo(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 Value; + + RTMP_IO_READ32(pAd, AGG_PCR, &Value); + DBGPRINT(RT_DEBUG_OFF, ("MM Protection = %d\n", GET_MM_PROTECTION(Value))); + DBGPRINT(RT_DEBUG_OFF, ("GF Protection = %d\n", GET_GF_PROTECTION(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Protection Mode = %d\n", GET_PROTECTION_MODE(Value))); + DBGPRINT(RT_DEBUG_OFF, ("BW40 Protection = %d\n", GET_BW40_PROTECTION(Value))); + DBGPRINT(RT_DEBUG_OFF, ("RIFS Protection = %d\n", GET_RIFS_PROTECTION(Value))); + DBGPRINT(RT_DEBUG_OFF, ("BW80 Protection = %d\n", GET_BW80_PROTECTION(Value))); + DBGPRINT(RT_DEBUG_OFF, ("BW160 Protection = %d\n", GET_BW160_PROTECTION(Value))); + DBGPRINT(RT_DEBUG_OFF, ("ERP Protection = 0x%x\n", GET_ERP_PROTECTION(Value))); + + RTMP_IO_READ32(pAd, AGG_PCR1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("RTS Threshold(packet length) = 0x%x\n", GET_RTS_THRESHOLD(Value))); + DBGPRINT(RT_DEBUG_OFF, ("RTS PKT Nums Threshold = %d\n", GET_RTS_PKT_NUM_THRESHOLD(Value))); + RTMP_IO_READ32(pAd, AGG_MRCR, &Value); + DBGPRINT(RT_DEBUG_OFF, ("RTS Retry Count Limit = %d\n", GET_RTS_RTY_CNT_LIMIT(Value))); + DBGPRINT(RT_DEBUG_OFF, ("BAR Frame Tx Count Limit = %d\n", GET_BAR_TX_CNT_LIMIT(Value))); + RTMP_IO_READ32(pAd, AGG_ACR, &Value); + DBGPRINT(RT_DEBUG_OFF, ("AMPDU No BA Rule = %d\n", GET_AMPDU_NO_BA_RULE(Value))); + DBGPRINT(RT_DEBUG_OFF, ("AMPDU No BA AR Rule = %d\n", GET_AGG_ACR_AMPDU_NO_BA_AR_RULE(Value))); + DBGPRINT(RT_DEBUG_OFF, ("BAR Tx Rate = 0x%x\n", GET_BAR_RATE_TX_RATE(Value))); + DBGPRINT(RT_DEBUG_OFF, ("BAR Tx Mode = 0x%x\n", GET_BAR_RATE_TX_MODE(Value))); + DBGPRINT(RT_DEBUG_OFF, ("BAR Nsts = %d\n", GET_BAR_RATE_NSTS(Value))); + DBGPRINT(RT_DEBUG_OFF, ("BAR STBC = %d\n", GET_BAR_RATE_STBC(Value))); + + RTMP_IO_READ32(pAd, AGG_AALCR, &Value); + DBGPRINT(RT_DEBUG_OFF, ("AC0 Agg limit = %d\n", GET_AC0_AGG_LIMIT(Value))); + DBGPRINT(RT_DEBUG_OFF, ("AC1 Agg limit = %d\n", GET_AC1_AGG_LIMIT(Value))); + DBGPRINT(RT_DEBUG_OFF, ("AC2 Agg limit = %d\n", GET_AC2_AGG_LIMIT(Value))); + DBGPRINT(RT_DEBUG_OFF, ("AC3 Agg limit = %d\n", GET_AC3_AGG_LIMIT(Value))); + + RTMP_IO_READ32(pAd, AGG_AALCR1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("AC10 Agg limit = %d\n", GET_AC10_AGG_LIMIT(Value))); + DBGPRINT(RT_DEBUG_OFF, ("AC11 Agg limit = %d\n", GET_AC11_AGG_LIMIT(Value))); + DBGPRINT(RT_DEBUG_OFF, ("AC12 Agg limit = %d\n", GET_AC12_AGG_LIMIT(Value))); + DBGPRINT(RT_DEBUG_OFF, ("AC13 Agg limit = %d\n", GET_AC13_AGG_LIMIT(Value))); + + RTMP_IO_READ32(pAd, AGG_AWSCR, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Winsize0 limit = %d\n", GET_WINSIZE0(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Winsize1 limit = %d\n", GET_WINSIZE1(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Winsize2 limit = %d\n", GET_WINSIZE2(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Winsize3 limit = %d\n", GET_WINSIZE3(Value))); + + RTMP_IO_READ32(pAd, AGG_AWSCR1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Winsize4 limit = %d\n", GET_WINSIZE4(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Winsize5 limit = %d\n", GET_WINSIZE5(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Winsize6 limit = %d\n", GET_WINSIZE6(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Winsize7 limit = %d\n", GET_WINSIZE7(Value))); + + return 0; +} + + +INT ShowManualTxOP(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 txop; + + DBGPRINT(RT_DEBUG_OFF, ("CURRENT: ManualTxOP = %d\n", pAd->CommonCfg.ManualTxop)); + DBGPRINT(RT_DEBUG_OFF, (" : bEnableTxBurst = %d\n", pAd->CommonCfg.bEnableTxBurst)); + DBGPRINT(RT_DEBUG_OFF, (" : MacTab.Size = %d\n", pAd->MacTab.Size)); + DBGPRINT(RT_DEBUG_OFF, (" : RDG_ACTIVE = %d\n", RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE))); + RTMP_IO_READ32(pAd, TMAC_ACTXOPLR1, &txop); + DBGPRINT(RT_DEBUG_OFF, (" : AC0 TxOP = 0x%x\n", GET_AC0LIMIT(txop))); + DBGPRINT(RT_DEBUG_OFF, (" : AC1 TxOP = 0x%x\n", GET_AC1LIMIT(txop))); + + return TRUE; +} +static VOID DumpPseFrameInfo(RTMP_ADAPTER *pAd, UINT8 PID, UINT8 QID) +{ + UINT32 FirstFID, CurFID, NextFID, FrameNums = 0; + UINT32 Value; + + DBGPRINT(RT_DEBUG_OFF, ("PID = %d, QID = %d\n", PID, QID)); + + RTMP_IO_READ32(pAd, C_GFF, &Value); + Value &= ~GET_QID_MASK; + Value |= SET_GET_QID(QID); + Value &= ~GET_PID_MASK; + Value |= SET_GET_PID(PID); + RTMP_IO_WRITE32(pAd, C_GFF, Value); + + RTMP_IO_READ32(pAd, C_GFF, &Value); + FirstFID = GET_FIRST_FID(Value); + + if (FirstFID == 0xfff) + { + DBGPRINT(RT_DEBUG_OFF, ("FrameNums = %d\n", FrameNums)); + return; + } + + CurFID = FirstFID; + FrameNums++; + + DBGPRINT(RT_DEBUG_OFF, ("FID = %d", CurFID)); + + while (1) + { + RTMP_IO_READ32(pAd, C_GF, &Value); + Value &= ~CURR_FID_MASK; + Value |= SET_CURR_FID(CurFID); + RTMP_IO_WRITE32(pAd, C_GF, Value); + RTMP_IO_READ32(pAd, C_GF, &Value); + NextFID = GET_RETURN_FID(Value); + + if (NextFID == 0xfff) + { + DBGPRINT(RT_DEBUG_OFF, ("\nFrameNums = %d\n", FrameNums)); + return; + } + else + { + CurFID = NextFID; + DBGPRINT(RT_DEBUG_OFF, (", FID = %d\n", CurFID)); + FrameNums++; + } + + } + + DBGPRINT(RT_DEBUG_OFF, ("\nFrameNums = %d\n", FrameNums)); +} + + +INT32 ShowPseInfo(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 Value; + + RTMP_IO_READ32(pAd, BC, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Total Page Nums = 0x%x, Page Size = %d\n", GET_TOTAL_PAGE_NUM(Value), GET_PAGE_SIZE_CFG(Value))); + + RTMP_IO_READ32(pAd, FC_FFC, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Free page counter status = 0x%x\n", GET_FREE_PAGE_CNT(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Free for all(FFA) counter status = 0x%x\n", GET_FFA_CNT(Value))); + + RTMP_IO_READ32(pAd, FC_FRP, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Reserve priority:\n")); + DBGPRINT(RT_DEBUG_OFF, ("P0(HIF) = 0x%x, ", GET_RSRV_PRI_P0(Value))); + DBGPRINT(RT_DEBUG_OFF, ("P1(MCU) = 0x%x\n", GET_RSRV_PRI_P1(Value))); + DBGPRINT(RT_DEBUG_OFF, ("P2 RQ0(Rx Data) = 0x%x, ", GET_RSRV_PRI_P2_RQ0(Value))); + DBGPRINT(RT_DEBUG_OFF, ("P2 RQ1(RxV) = 0x%x, ", GET_RSRV_PRI_P2_RQ1(Value))); + DBGPRINT(RT_DEBUG_OFF, ("P2 RQ2(TxS) = 0x%x\n", GET_RSRV_PRI_P2_RQ2(Value))); + + RTMP_IO_READ32(pAd, FC_P0, &Value); + DBGPRINT(RT_DEBUG_OFF, ("P0(HIF):\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tmin reserve setting = 0x%x\n", GET_MIN_RSRV_P0(Value))); + DBGPRINT(RT_DEBUG_OFF, ("\tmax quota setting = 0x%x\n", GET_MAX_QUOTA_P0(Value))); + RTMP_IO_READ32(pAd, FC_RP0P1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("\treserve pages = 0x%x\n", GET_RSRV_CNT_P0(Value))); + RTMP_IO_READ32(pAd, FC_SP0P1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("\tused pages = 0x%x\n", GET_SRC_CNT_P0(Value))); + + RTMP_IO_READ32(pAd, FC_P1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("P1(MCU):\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tmin reserve setting = 0x%x\n", GET_MIN_RSRV_P1(Value))); + DBGPRINT(RT_DEBUG_OFF, ("\tmax quota setting = 0x%x\n", GET_MAX_QUOTA_P1(Value))); + RTMP_IO_READ32(pAd, FC_RP0P1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("\treserve pages = 0x%x\n", GET_RSRV_CNT_P1(Value))); + RTMP_IO_READ32(pAd, FC_SP0P1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("\tused pages = 0x%x\n", GET_SRC_CNT_P1(Value))); + + RTMP_IO_READ32(pAd, FC_P2Q0, &Value); + DBGPRINT(RT_DEBUG_OFF, ("P2 RQ0(Rx Data):\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tmin reserve setting = 0x%x\n", GET_MIN_RSRV_P2_RQ0(Value))); + DBGPRINT(RT_DEBUG_OFF, ("\tmax quota setting = 0x%x\n", GET_MAX_QUOTA_P2_RQ0(Value))); + RTMP_IO_READ32(pAd, FC_RP2Q0Q1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("\treserve pages = 0x%x\n", GET_RSRV_CNT_P2_RQ0(Value))); + RTMP_IO_READ32(pAd, FC_SP2Q0Q1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("\tused pages = 0x%x\n", GET_SRC_CNT_P2_RQ0(Value))); + + + RTMP_IO_READ32(pAd, FC_P2Q1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("P2 RQ1(RxV):\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tmin reserve setting = 0x%x\n", GET_MIN_RSRV_P2_RQ1(Value))); + DBGPRINT(RT_DEBUG_OFF, ("\tmax quota setting = 0x%x\n", GET_MAX_QUOTA_P2_RQ1(Value))); + RTMP_IO_READ32(pAd, FC_RP2Q0Q1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("\treserve pages = 0x%x\n", GET_RSRV_CNT_P2_RQ1(Value))); + RTMP_IO_READ32(pAd, FC_SP2Q0Q1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("\tused pages = 0x%x\n", GET_SRC_CNT_P2_RQ1(Value))); + + + RTMP_IO_READ32(pAd, FC_P2Q2, &Value); + DBGPRINT(RT_DEBUG_OFF, ("P2 RQ2(TxS):\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tmin reserve setting = 0x%x\n", GET_MIN_RSRV_P2_RQ2(Value))); + DBGPRINT(RT_DEBUG_OFF, ("\tmax quota setting = 0x%x\n", GET_MAX_QUOTA_P2_RQ2(Value))); + RTMP_IO_READ32(pAd, FC_RP2Q2, &Value); + DBGPRINT(RT_DEBUG_OFF, ("\treserve pages = 0x%x\n", GET_RSRV_CNT_P2_RQ2(Value))); + RTMP_IO_READ32(pAd, FC_SP2Q2, &Value); + DBGPRINT(RT_DEBUG_OFF, ("\tused pages = 0x%x\n", GET_SRC_CNT_P2_RQ2(Value))); + + /* HIF port frame information */ + DBGPRINT(RT_DEBUG_OFF, ("HIF HTX_L0 frame information\n")); + DumpPseFrameInfo(pAd, 0, 0); + + DBGPRINT(RT_DEBUG_OFF, ("HIF HTX_HI frame information\n")); + DumpPseFrameInfo(pAd, 0, 1); + + DBGPRINT(RT_DEBUG_OFF, ("HIF HRX frame information\n")); + DumpPseFrameInfo(pAd, 0, 2); + + /* MCU port frame information */ + DBGPRINT(RT_DEBUG_OFF, ("MCU CTX_Q0 frame information\n")); + DumpPseFrameInfo(pAd, 1, 0); + + DBGPRINT(RT_DEBUG_OFF, ("MCU CTX_Q1 frame information\n")); + DumpPseFrameInfo(pAd, 1, 1); + + DBGPRINT(RT_DEBUG_OFF, ("MCU CTX_Q2 frame information\n")); + DumpPseFrameInfo(pAd, 1, 2); + + DBGPRINT(RT_DEBUG_OFF, ("MCU CTX_Q3 frame information\n")); + DumpPseFrameInfo(pAd, 1, 3); + + /* WLAN port frame information */ + DBGPRINT(RT_DEBUG_OFF, ("WLAN AC0 frame information\n")); + DumpPseFrameInfo(pAd, 2, 0); + + DBGPRINT(RT_DEBUG_OFF, ("WLAN AC1 frame information\n")); + DumpPseFrameInfo(pAd, 2, 1); + + DBGPRINT(RT_DEBUG_OFF, ("WLAN AC2 frame information\n")); + DumpPseFrameInfo(pAd, 2, 2); + + DBGPRINT(RT_DEBUG_OFF, ("WLAN AC3 frame information\n")); + DumpPseFrameInfo(pAd, 2, 3); + + DBGPRINT(RT_DEBUG_OFF, ("WLAN AC4 frame information\n")); + DumpPseFrameInfo(pAd, 2, 4); + + DBGPRINT(RT_DEBUG_OFF, ("WLAN AC5 frame information\n")); + DumpPseFrameInfo(pAd, 2, 5); + + DBGPRINT(RT_DEBUG_OFF, ("WLAN AC6 frame information\n")); + DumpPseFrameInfo(pAd, 2, 6); + + DBGPRINT(RT_DEBUG_OFF, ("WLAN BC/MC frame information\n")); + DumpPseFrameInfo(pAd, 2, 7); + + DBGPRINT(RT_DEBUG_OFF, ("WLAN Beacon frame information\n")); + DumpPseFrameInfo(pAd, 2, 8); + + DBGPRINT(RT_DEBUG_OFF, ("WLAN AC10 frame information\n")); + DumpPseFrameInfo(pAd, 2, 9); + + DBGPRINT(RT_DEBUG_OFF, ("WLAN AC11 frame information\n")); + DumpPseFrameInfo(pAd, 2, 10); + + DBGPRINT(RT_DEBUG_OFF, ("WLAN AC12 frame information\n")); + DumpPseFrameInfo(pAd, 2, 11); + + DBGPRINT(RT_DEBUG_OFF, ("WLAN AC13 frame information\n")); + DumpPseFrameInfo(pAd, 2, 12); + + DBGPRINT(RT_DEBUG_OFF, ("WLAN AC14 frame information\n")); + DumpPseFrameInfo(pAd, 2, 13); + + return 0; +} + + +INT32 ShowPseData(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + CHAR *Param; + UINT16 StartFID, CurFID, FrameNums, Index, DwIndex; + UINT32 Value; + UINT32 PseData[4 * 8]; + + Param = rstrtok(arg, ","); + + if (Param != NULL) + { + StartFID = simple_strtol(Param, 0, 10); + } + else + { + goto error; + } + + Param = rstrtok(NULL, ","); + + if (Param != NULL) + { + FrameNums = simple_strtol(Param, 0, 10); + } + else + { + goto error; + } + + CurFID = StartFID; + + for (Index = 0; Index < FrameNums; Index++) + { + for (DwIndex = 0; DwIndex < 8; DwIndex++) + { + RTMP_IO_READ32(pAd, (MT_PCI_REMAP_ADDR_1 + (((CurFID) * 128)) + (DwIndex * 4)), + &PseData[DwIndex * 4]); + } + + DBGPRINT(RT_DEBUG_OFF, ("FID:0x%x\n", CurFID)); + +#ifdef RT_BIG_ENDIAN + MTMacInfoEndianChange(pAd, (PUCHAR)(PseData), TYPE_TMACINFO, 32); +#endif + dump_tmac_info(pAd, (PUCHAR)PseData); + +#ifdef RT_BIG_ENDIAN + MTMacInfoEndianChange(pAd, (PUCHAR)(PseData), TYPE_TMACINFO, 32); +#endif + RTMP_IO_READ32(pAd, C_GF, &Value); + Value &= ~CURR_FID_MASK; + Value |= SET_CURR_FID(CurFID); + RTMP_IO_WRITE32(pAd, C_GF, Value); + RTMP_IO_READ32(pAd, C_GF, &Value); + CurFID = GET_RETURN_FID(Value); + + if (CurFID == 0xfff) + break; + } + +error: + DBGPRINT(RT_DEBUG_OFF, ("%s: param = %s not correct\n", __FUNCTION__, arg)); + DBGPRINT(RT_DEBUG_OFF, ("%s: iwpriv ra0 show psedata=startfid,framenums\n", __FUNCTION__)); + return 0; +} + + +#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT) +INT32 ShowDMASchInfo(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 Value; + RTMP_IO_READ32(pAd, MT_PAGE_CNT_0, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue0 reservation page thd = 0x%x\n", GET_PAGE_CNT_0(Value))); + RTMP_IO_READ32(pAd, MT_PAGE_CNT_1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue1 reservation page thd = 0x%x\n", GET_PAGE_CNT_1(Value))); + RTMP_IO_READ32(pAd, MT_PAGE_CNT_2, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue2 reservation page thd = 0x%x\n", GET_PAGE_CNT_2(Value))); + RTMP_IO_READ32(pAd, MT_PAGE_CNT_3, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue3 reservation page thd = 0x%x\n", GET_PAGE_CNT_3(Value))); + RTMP_IO_READ32(pAd, MT_PAGE_CNT_4, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue4 reservation page thd = 0x%x\n", GET_PAGE_CNT_4(Value))); + RTMP_IO_READ32(pAd, MT_PAGE_CNT_5, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue5 reservation page thd = 0x%x\n", GET_PAGE_CNT_5(Value))); + RTMP_IO_READ32(pAd, MT_PAGE_CNT_6, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue6 reservation page thd = 0x%x\n", GET_PAGE_CNT_6(Value))); + RTMP_IO_READ32(pAd, MT_PAGE_CNT_7, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue7 reservation page thd = 0x%x\n", GET_PAGE_CNT_7(Value))); + RTMP_IO_READ32(pAd, MT_PAGE_CNT_8, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue8 reservation page thd = 0x%x\n", GET_PAGE_CNT_8(Value))); + RTMP_IO_READ32(pAd, MT_PAGE_CNT_9, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue9 reservation page thd = 0x%x\n", GET_PAGE_CNT_9(Value))); + RTMP_IO_READ32(pAd, MT_PAGE_CNT_10, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue10 reservation page thd = 0x%x\n", GET_PAGE_CNT_10(Value))); + RTMP_IO_READ32(pAd, MT_PAGE_CNT_11, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue11 reservation page thd = 0x%x\n", GET_PAGE_CNT_11(Value))); + RTMP_IO_READ32(pAd, MT_PAGE_CNT_12, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue12 reservation page thd = 0x%x\n", GET_PAGE_CNT_12(Value))); + RTMP_IO_READ32(pAd, MT_PAGE_CNT_13, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue13 reservation page thd = 0x%x\n", GET_PAGE_CNT_13(Value))); + RTMP_IO_READ32(pAd, MT_PAGE_CNT_14, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue14 reservation page thd = 0x%x\n", GET_PAGE_CNT_14(Value))); + RTMP_IO_READ32(pAd, MT_PAGE_CNT_15, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue15 reservation page thd = 0x%x\n", GET_PAGE_CNT_15(Value))); + + RTMP_IO_READ32(pAd, MT_QUEUE_PRIORITY_1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue0 priority = 0x%x\n", GET_RG_QUEUE_PRIORITY_0(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue1 priority = 0x%x\n", GET_RG_QUEUE_PRIORITY_1(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue2 priority = 0x%x\n", GET_RG_QUEUE_PRIORITY_2(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue3 priority = 0x%x\n", GET_RG_QUEUE_PRIORITY_3(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue4 priority = 0x%x\n", GET_RG_QUEUE_PRIORITY_4(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue5 priority = 0x%x\n", GET_RG_QUEUE_PRIORITY_5(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue6 priority = 0x%x\n", GET_RG_QUEUE_PRIORITY_6(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue7 priority = 0x%x\n", GET_RG_QUEUE_PRIORITY_7(Value))); + + RTMP_IO_READ32(pAd, MT_QUEUE_PRIORITY_2, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue8 priority = 0x%x\n", GET_RG_QUEUE_PRIORITY_8(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue9 priority = 0x%x\n", GET_RG_QUEUE_PRIORITY_9(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue10 priority = 0x%x\n", GET_RG_QUEUE_PRIORITY_10(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue11 priority = 0x%x\n", GET_RG_QUEUE_PRIORITY_11(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue12 priority = 0x%x\n", GET_RG_QUEUE_PRIORITY_12(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue13 priority = 0x%x\n", GET_RG_QUEUE_PRIORITY_13(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue14 priority = 0x%x\n", GET_RG_QUEUE_PRIORITY_14(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue15 priority = 0x%x\n", GET_RG_QUEUE_PRIORITY_15(Value))); + + RTMP_IO_READ32(pAd, MT_SCH_REG_1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Free for all buffer thd = 0x%x\n", GET_RG_FFA_THD(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Packet bytes per page = %d\n", GET_RG_PAGE_SIZE(Value))); + + RTMP_IO_READ32(pAd, MT_SCH_REG_2, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Max packet size in one packet = 0x%x\n", GET_RG_MAX_PKT_SIZE(Value))); + + RTMP_IO_READ32(pAd, MT_SCH_REG_4, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Force qid = %d\n", GET_FORCE_QID(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Force mode = %d\n", GET_FORCE_MODE(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Bypass mode = %d\n", GET_BYPASS_MODE(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Hybird mode = %d\n", GET_HYBIRD_MODE(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Force in predict mode = %d\n", GET_RG_PREDICT_NO_MASK(Value))); + DBGPRINT(RT_DEBUG_OFF, ("SW mode = %d\n", GET_SW_MODE(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Rate map(0x%x) when sw mode = 1\n", GET_RG_RATE_MAP(Value))); + + RTMP_IO_READ32(pAd, MT_GROUP_THD_0, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Group 0 page thd = 0x%x\n", GET_GROUP_THD_0(Value))); + RTMP_IO_READ32(pAd, MT_GROUP_THD_1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Group 1 page thd = 0x%x\n", GET_GROUP_THD_1(Value))); + RTMP_IO_READ32(pAd, MT_GROUP_THD_2, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Group 2 page thd = 0x%x\n", GET_GROUP_THD_2(Value))); + RTMP_IO_READ32(pAd, MT_GROUP_THD_3, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Group 3 page thd = 0x%x\n", GET_GROUP_THD_3(Value))); + RTMP_IO_READ32(pAd, MT_GROUP_THD_4, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Group 4 page thd = 0x%x\n", GET_GROUP_THD_4(Value))); + RTMP_IO_READ32(pAd, MT_GROUP_THD_5, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Group 5 page thd = 0x%x\n", GET_GROUP_THD_5(Value))); + + RTMP_IO_READ32(pAd, MT_BMAP_0, &Value); + DBGPRINT(RT_DEBUG_OFF, ("One queue on bit mapping(0x%x) for group 0\n", GET_RG_BMAP_0(Value))); + DBGPRINT(RT_DEBUG_OFF, ("One queue on bit mapping(0x%x) for group 1\n", GET_RG_BMAP_1(Value))); + + RTMP_IO_READ32(pAd, MT_BMAP_1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("One queue on bit mapping(0x%x) for group 2\n", GET_RG_BMAP_2(Value))); + DBGPRINT(RT_DEBUG_OFF, ("One queue on bit mapping(0x%x) for group 3\n", GET_RG_BMAP_3(Value))); + + RTMP_IO_READ32(pAd, MT_BMAP_2, &Value); + DBGPRINT(RT_DEBUG_OFF, ("One queue on bit mapping(0x%x) for group 4\n", GET_RG_BMAP_4(Value))); + DBGPRINT(RT_DEBUG_OFF, ("One queue on bit mapping(0x%x) for group 5\n", GET_RG_BMAP_5(Value))); + + RTMP_IO_READ32(pAd, MT_HIGH_PRIORITY_1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue0 high priority = 0x%x\n", GET_RG_HIGH_PRIORITY_0(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue1 high priority = 0x%x\n", GET_RG_HIGH_PRIORITY_1(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue2 high priority = 0x%x\n", GET_RG_HIGH_PRIORITY_2(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue3 high priority = 0x%x\n", GET_RG_HIGH_PRIORITY_3(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue4 high priority = 0x%x\n", GET_RG_HIGH_PRIORITY_4(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue5 high priority = 0x%x\n", GET_RG_HIGH_PRIORITY_5(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue6 high priority = 0x%x\n", GET_RG_HIGH_PRIORITY_6(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue7 high priority = 0x%x\n", GET_RG_HIGH_PRIORITY_7(Value))); + + RTMP_IO_READ32(pAd, MT_HIGH_PRIORITY_2, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue8 high priority = 0x%x\n", GET_RG_HIGH_PRIORITY_8(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue9 high priority = 0x%x\n", GET_RG_HIGH_PRIORITY_9(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue10 high priority = 0x%x\n", GET_RG_HIGH_PRIORITY_10(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue11 high priority = 0x%x\n", GET_RG_HIGH_PRIORITY_11(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue12 high priority = 0x%x\n", GET_RG_HIGH_PRIORITY_12(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue13 high priority = 0x%x\n", GET_RG_HIGH_PRIORITY_13(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue14 high priority = 0x%x\n", GET_RG_HIGH_PRIORITY_14(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue15 high priority = 0x%x\n", GET_RG_HIGH_PRIORITY_15(Value))); + + RTMP_IO_READ32(pAd, MT_PRIORITY_MASK, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Mask for queue priority = 0x%x\n", GET_RG_QUEUE_PRIORITY(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Mask for high priority = 0x%x\n", GET_RG_HIGH_PRIORITY(Value))); + + RTMP_IO_READ32(pAd, MT_RSV_MAX_THD, &Value); + DBGPRINT(RT_DEBUG_OFF, ("FFA1 max thd = 0x%x\n", GET_RG_RSV_MAX_THD(Value))); + + RTMP_IO_READ32(pAd, RSV_AC_CNT_0, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue 0 rsv paged used count = 0x%x\n", GET_RSV_AC_CNT_0(Value))); + RTMP_IO_READ32(pAd, RSV_AC_CNT_1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue 1 rsv paged used count = 0x%x\n", GET_RSV_AC_CNT_1(Value))); + RTMP_IO_READ32(pAd, RSV_AC_CNT_2, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue 2 rsv paged used count = 0x%x\n", GET_RSV_AC_CNT_2(Value))); + RTMP_IO_READ32(pAd, RSV_AC_CNT_3, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue 3 rsv paged used count = 0x%x\n", GET_RSV_AC_CNT_3(Value))); + RTMP_IO_READ32(pAd, RSV_AC_CNT_4, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue 4 rsv paged used count = 0x%x\n", GET_RSV_AC_CNT_4(Value))); + RTMP_IO_READ32(pAd, RSV_AC_CNT_5, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue 5 rsv paged used count = 0x%x\n", GET_RSV_AC_CNT_5(Value))); + RTMP_IO_READ32(pAd, RSV_AC_CNT_6, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue 6 rsv paged used count = 0x%x\n", GET_RSV_AC_CNT_6(Value))); + RTMP_IO_READ32(pAd, RSV_AC_CNT_7, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue 7 rsv paged used count = 0x%x\n", GET_RSV_AC_CNT_7(Value))); + RTMP_IO_READ32(pAd, RSV_AC_CNT_8, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue 8 rsv paged used count = 0x%x\n", GET_RSV_AC_CNT_8(Value))); + RTMP_IO_READ32(pAd, RSV_AC_CNT_9, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue 9 rsv paged used count = 0x%x\n", GET_RSV_AC_CNT_9(Value))); + RTMP_IO_READ32(pAd, RSV_AC_CNT_10, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue 10 rsv paged used count = 0x%x\n", GET_RSV_AC_CNT_10(Value))); + RTMP_IO_READ32(pAd, RSV_AC_CNT_11, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue 11 rsv paged used count = 0x%x\n", GET_RSV_AC_CNT_11(Value))); + RTMP_IO_READ32(pAd, RSV_AC_CNT_12, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue 12 rsv paged used count = 0x%x\n", GET_RSV_AC_CNT_12(Value))); + RTMP_IO_READ32(pAd, RSV_AC_CNT_13, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue 13 rsv paged used count = 0x%x\n", GET_RSV_AC_CNT_13(Value))); + RTMP_IO_READ32(pAd, RSV_AC_CNT_14, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue 14 rsv paged used count = 0x%x\n", GET_RSV_AC_CNT_14(Value))); + RTMP_IO_READ32(pAd, RSV_AC_CNT_15, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Queue 15 rsv paged used count = 0x%x\n", GET_RSV_AC_CNT_15(Value))); + + RTMP_IO_READ32(pAd, SCH_DBG0_0, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Each queue rsv space if enough(0x%x)\n", GET_RSV_ENOUGH(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Group remain page great than max pkt page = %d\n", GET_GROUP_ENOUGH(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Queue remain page great than max pkt pagew = %d\n", GET_QUEUE_ENOUGH(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Pedict mode = %d\n", GET_PREDICT_MODE(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Use queue reservation = %d\n", GET_REST_QUEUE_EN(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Current queue tx op time if enough = %d\n", GET_ENOUGH_TXTIME(Value))); + DBGPRINT(RT_DEBUG_OFF, ("Current queue pse page space if enough = %d\n", GET_ENOUGH_BUF(Value))); + + RTMP_IO_READ32(pAd, SCH_DBG_1, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Free for all buffer used counter = 0x%x\n", GET_FFA_PAGE_CNT(Value))); + RTMP_IO_READ32(pAd, SCH_DBG_2, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Current packet tx op time = 0x%x\n", GET_PKT_TX_TIME(Value))); + RTMP_IO_READ32(pAd, SCH_DBG_3, &Value); + DBGPRINT(RT_DEBUG_OFF, ("tx op time period per byte = 0x%x\n", GET_TX_TIME_PER_BYTE(Value))); + RTMP_IO_READ32(pAd, SCH_DBG_4, &Value); + DBGPRINT(RT_DEBUG_OFF, ("PSE poer resrvation latched by dma scheduler = 0x%x\n", GET_PSE_RSV_SPACE(Value))); + DBGPRINT(RT_DEBUG_OFF, ("PSE port reservation space = 0x%x\n", GET_HIF_RSV_PCNT(Value))); + DBGPRINT(RT_DEBUG_OFF, ("PSE poer resrvation space update = %d\n", GET_HIF_RSV_PCNT_UPDT(Value))); + RTMP_IO_READ32(pAd, SCH_DBG_5, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Per-Queue group is enough page space for en-queue = 0x%x\n", GET_GROUP_EN(Value))); + RTMP_IO_READ32(pAd, SCH_DBG_6, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Group 0 used page count = 0x%x\n", GET_USED_GROUP_0(Value))); + RTMP_IO_READ32(pAd, SCH_DBG_7, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Group 1 used page count = 0x%x\n", GET_USED_GROUP_1(Value))); + RTMP_IO_READ32(pAd, SCH_DBG_8, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Group 2 used page count = 0x%x\n", GET_USED_GROUP_2(Value))); + RTMP_IO_READ32(pAd, SCH_DBG_9, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Group 3 used page count = 0x%x\n", GET_USED_GROUP_3(Value))); + RTMP_IO_READ32(pAd, SCH_DBG_10, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Group 4 used page count = 0x%x\n", GET_USED_GROUP_4(Value))); + RTMP_IO_READ32(pAd, SCH_DBG_11, &Value); + DBGPRINT(RT_DEBUG_OFF, ("Group 5 used page count = 0x%x\n", GET_USED_GROUP_5(Value))); + + return TRUE; +} +#endif +#endif + +#ifdef MIXMODE_SUPPORT +INT32 ShowMixModeProc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + MixModeDebugInfo(pAd, 0); + return TRUE; +} + + +INT32 GetMacTableStaInfo_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT i; + RT_802_11_MAC_TABLE *pMacTab = NULL; + PRT_802_11_MAC_ENTRY pDst; + MAC_TABLE_ENTRY *pEntry; + + DBGPRINT(RT_DEBUG_OFF, ("%s()\n", __FUNCTION__)); + + /* 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 FALSE; + } + + 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->func_tb_idx; + 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.AvgRssi[0]; + pDst->AvgRssi1 = pEntry->RssiSample.AvgRssi[1]; + pDst->AvgRssi2 = pEntry->RssiSample.AvgRssi[2]; + + /* the connected time per entry*/ + pDst->ConnectedTime = pEntry->StaConnectTime; + pDst->TxRate.word = pEntry->HTPhyMode.word; + + pDst->LastRxRate = pEntry->LastRxRate; + + pMacTab->Num += 1; + + DBGPRINT(RT_DEBUG_OFF, ("ApIdx = %d\n", pDst->ApIdx)); + DBGPRINT(RT_DEBUG_OFF, ("STA Mac = %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(pDst->Addr))); + DBGPRINT(RT_DEBUG_OFF, ("Aid = %d\nPsm = %d\n", pDst->ApIdx, pDst->Psm)); +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("MimoPs%d\n", pDst->MimoPs)); +#endif /* DOT11_N_SUPPORT */ + DBGPRINT(RT_DEBUG_OFF, ("AvgRssi[0] = %d\nAvgRssi[1] = %d\nAvgRssi[2] = %d\n", pDst->AvgRssi0, pDst->AvgRssi1, pDst->AvgRssi2)); + DBGPRINT(RT_DEBUG_OFF, ("ConnectedTime = %d\n", pDst->ConnectedTime)); + DBGPRINT(RT_DEBUG_OFF, ("LastRxRate = %d\n", pDst->LastRxRate)); + } + } + + if (pMacTab != NULL) + os_free_mem(NULL, pMacTab); + + return TRUE; +} + + +INT32 SetMixMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT ret; + struct mix_peer_parameter *sta_info; + INT Status = NDIS_STATUS_SUCCESS; + UINT ArgIdx; + RTMP_STRING *thisChar; + INT Loop; + + DBGPRINT(RT_DEBUG_OFF, ("%s()\n", __FUNCTION__)); + + ArgIdx = 0; + + ret = os_alloc_mem(pAd, + (UCHAR **)&sta_info, + sizeof(struct mix_peer_parameter)); + if (ret == NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_OFF, + ("Set::OID_SET_MIXMODE\n")); + + while ((thisChar = strsep((char **)&arg, "-")) != NULL) + { + switch(ArgIdx) + { + case 0: /* channel. */ + sta_info->channel = (UINT8) simple_strtol(thisChar, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("channel = %d\n", sta_info->channel)); + break; + + case 1: /* center_channel. */ + sta_info->center_channel = (UINT8) simple_strtol(thisChar, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("center_channel = %d\n", sta_info->center_channel)); + break; + + case 2: /* bw. */ + sta_info->bw = (UINT8) simple_strtol(thisChar, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("bw = %d\n", sta_info->bw)); + break; + + case 3: /* ch_offset. */ + sta_info->ch_offset = (UINT8) simple_strtol(thisChar, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("ch_offset = %d\n", sta_info->ch_offset)); + break; + + case 4: /* mac_addr. */ + if(strlen(thisChar) != 17) + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: invalid value mac_addr.\n", __FUNCTION__)); + return FALSE; + } + + if(strlen(thisChar) == 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + { + RTMP_STRING *value; + for (Loop=0, value = rstrtok(thisChar,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid */ + + AtoH(value, &sta_info->mac_addr[Loop++], 1); + } + + if(Loop != 6) + return FALSE; + } + DBGPRINT(RT_DEBUG_OFF, ("mac_addr = %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(sta_info->mac_addr))); + break; + + case 5: /* duration. */ + sta_info->duration= (UINT32) simple_strtol(thisChar, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("duration = %d\n", sta_info->duration)); + break; + } + ArgIdx++; + } + + Status = MixModeSet(pAd, sta_info, 0); + os_free_mem(NULL, sta_info); + } else { + Status = -EFAULT; + DBGPRINT(RT_DEBUG_OFF, + ("%s()::alloc memory fail\n", __func__)); + } + + return TRUE; +} + +INT32 MixModeCancel_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_OFF, ("%s()\n", __FUNCTION__)); + + if(pAd == NULL) + return FALSE; + + RTMPCancelTimer(&pAd->MixModeCtrl.MixModeTimer,&Cancelled); + + MlmeEnqueue(pAd, MIX_MODE_STATE_MACHINE, MIX_MODE_MSG_CANCLE, 0, NULL, 0); + RTMP_MLME_HANDLER(pAd); + + return TRUE; +} + +INT32 GetMixModeRssi_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR mnt_idx = 0; + LONG avgRssi = -127; + struct peer_info *sta = &pAd->MixModeCtrl.sta_info[mnt_idx]; + LONG mgmt_rssi; + LONG data_rssi; + LONG cntl_rssi; + LONG total; + + DBGPRINT(RT_DEBUG_OFF, ("%s()\n", __FUNCTION__)); + + if (MixMode_On(pAd)) { + DBGPRINT(RT_DEBUG_ERROR, + ("\n\n\nQuery::!!!Mix Mode runnning, CANNOT GET RESULT NOW!!!\n\n\n")); + return FALSE; + } + + mgmt_rssi = sta->mnt_sta.frm[FC_TYPE_MGMT].rssi; + data_rssi = sta->mnt_sta.frm[FC_TYPE_DATA].rssi; + cntl_rssi = sta->mnt_sta.frm[FC_TYPE_CNTL].rssi; + total = sta->mnt_sta.Count; + + /* + * weight * rssi + * But need to check vaule + * it cannot overflow + */ + if (total) + avgRssi = (mgmt_rssi + data_rssi + cntl_rssi) / total; + + DBGPRINT(RT_DEBUG_OFF, + ("%s:: %02x:%02x:%02x:%02x:%02x:%02x, avgRssi=%ld\n", __FUNCTION__, PRINT_MAC(sta->mac_addr), avgRssi)); + + return TRUE; +} +#endif + +INT Show_sta_tr_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT idx; + STA_TR_ENTRY *tr_entry; + + for (idx = 0; idx < MAX_LEN_OF_TR_TABLE; idx++) + { + tr_entry = &pAd->MacTab.tr_entry[idx]; + if (IS_VALID_ENTRY(tr_entry)) + dump_tr_entry(pAd, idx, (RTMP_STRING *)__FUNCTION__, __LINE__); + } + + return TRUE; +} +#if defined(MAX_CONTINUOUS_TX_CNT) || defined(NEW_IXIA_METHOD) +INT Show_TxSwqInfo_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR Qindex; + + Qindex = (UCHAR)simple_strtol(arg, 0, 10); + if(Qindex < 0 || Qindex >=4 ){ + DBGPRINT(RT_DEBUG_OFF, ("Invlaid Qindex,should be 0-3!\n")); + return FALSE; + } + rtmp_tx_swq_dump(pAd,Qindex); + DBGPRINT(RT_DEBUG_OFF, ("Dump tx_swq[%d] infor success!\n",Qindex)); + return TRUE; +} +INT Set_TxSwqCtrl_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR Ctrl; + Ctrl = (UCHAR)simple_strtol(arg, 0, 10); + pAd->TxSwqCtrl = Ctrl; + DBGPRINT(RT_DEBUG_OFF, ("1:enq/deq swqidx check.2:deq_req() queue NULL check.3:deq_report() status check.4: drop and ps event statistic.\n")); + DBGPRINT(RT_DEBUG_OFF, ("pAd->TxSwqCtrl = %d!\n",pAd->TxSwqCtrl )); + return TRUE; +} + +#endif +INT show_stainfo_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT i; + ULONG DataRate=0, irqflags = 0; + UCHAR mac_addr[MAC_ADDR_LEN]; + RTMP_STRING *token; + CHAR sep[1] = {':'}; + MAC_TABLE_ENTRY *pEntry; + STA_TR_ENTRY *tr_entry; + + DBGPRINT(RT_DEBUG_OFF, ("%s(): Input string=%s\n", + __FUNCTION__, arg)); + for (i = 0, token = rstrtok(arg, &sep[0]); token; token = rstrtok(NULL, &sep[0]), i++) + { + DBGPRINT(RT_DEBUG_OFF, ("%s(): token(len=%d) =%s\n", + __FUNCTION__, strlen(token), token)); + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (&mac_addr[i]), 1); + } + + DBGPRINT(RT_DEBUG_OFF, ("%s(): i= %d\n", __FUNCTION__, i)); + if(i != 6) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("\nAddr %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(mac_addr))); + + pEntry = MacTableLookup(pAd, (UCHAR *)mac_addr); + if (!pEntry) + return FALSE; + + if (IS_ENTRY_NONE(pEntry)) { + DBGPRINT(RT_DEBUG_OFF, ("Invalid MAC address!\n")); + return FALSE; + } + + printk("\n"); + + printk("EntryType : %d\n", pEntry->EntryType); + printk("Entry Capability:\n"); + printk("\tPhyMode:%-10s\n", get_phymode_str(pEntry->MaxHTPhyMode.field.MODE)); + printk("\tBW:%-6s\n", get_bw_str(pEntry->MaxHTPhyMode.field.BW)); + printk("\tDataRate: \n"); +#ifdef DOT11_VHT_AC + if (pEntry->MaxHTPhyMode.field.MODE == MODE_VHT) + printk("%dS-M%d", ((pEntry->MaxHTPhyMode.field.MCS>>4) + 1), (pEntry->MaxHTPhyMode.field.MCS & 0xf)); + else +#endif /* DOT11_VHT_AC */ + printk(" %-6d", pEntry->MaxHTPhyMode.field.MCS); + printk(" %-6d", pEntry->MaxHTPhyMode.field.ShortGI); + printk(" %-6d\n", pEntry->MaxHTPhyMode.field.STBC); + + printk("Entry Operation Features\n"); + printk("\t%-4s%-4s%-4s%-4s%-8s%-7s%-7s%-7s%-10s%-6s%-6s%-6s%-6s%-7s%-7s\n", + "AID", "BSS", "PSM", "WMM", "MIMOPS", "RSSI0", "RSSI1", + "RSSI2", "PhMd", "BW", "MCS", "SGI", "STBC", "Idle", "Rate"); + + DataRate=0; + getRate(pEntry->HTPhyMode, &DataRate); + printk("\t%-4d", (int)pEntry->Aid); + printk("%-4d", (int)pEntry->func_tb_idx); + 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.AvgRssi[0]); + printk("%-7d", pEntry->RssiSample.AvgRssi[1]); + printk("%-7d", pEntry->RssiSample.AvgRssi[2]); + printk("%-10s", get_phymode_str(pEntry->HTPhyMode.field.MODE)); + printk("%-6s", get_bw_str(pEntry->HTPhyMode.field.BW)); +#ifdef DOT11_VHT_AC + if (pEntry->HTPhyMode.field.MODE == MODE_VHT) + printk("%dS-M%d", ((pEntry->HTPhyMode.field.MCS>>4) + 1), (pEntry->HTPhyMode.field.MCS & 0xf)); + else +#endif /* DOT11_VHT_AC */ + printk("%-6d", pEntry->HTPhyMode.field.MCS); + printk("%-6d", pEntry->HTPhyMode.field.ShortGI); + printk("%-6d", pEntry->HTPhyMode.field.STBC); + printk("%-7d", (int)(pEntry->StaIdleTimeout - pEntry->NoDataIdleCount)); + printk("%-7d", (int)DataRate); + printk("%-10d, %d, %d%%\n", pEntry->DebugFIFOCount, pEntry->DebugTxCount, + (pEntry->DebugTxCount) ? ((pEntry->DebugTxCount-pEntry->DebugFIFOCount)*100/pEntry->DebugTxCount) : 0); + + printk("\n"); + + ASSERT(pEntry->wcid <= MAX_LEN_OF_MAC_TABLE); + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + printk("Entry TxRx Info\n"); + printk("\tEntryType : %d\n", tr_entry->EntryType); + printk("\tHookingWdev : %p\n", tr_entry->wdev); + printk("\tIndexing : FuncTd=%d, WCID=%d\n", tr_entry->func_tb_idx, tr_entry->wcid); + printk("Entry TxRx Features\n"); + printk("\tIsCached, PortSecured, PsMode, LockTx, VndAth\n"); + printk("\t%d\t%d\t%d\t%d\t%d\n", tr_entry->isCached, tr_entry->PortSecured, + tr_entry->PsMode, tr_entry->LockEntryTx, + tr_entry->bIAmBadAtheros); + + printk("\t%-6s%-6s%-6s%-6s%-6s%-6s%-6s\n", "TxQId", "PktNum", "QHead", "QTail", "EnQCap", "DeQCap", "PktSeq"); + for (i = 0; i < WMM_QUE_NUM; i++){ + RTMP_IRQ_LOCK(&pAd->irq_lock /* &tr_entry->txq_lock[i] */, irqflags); + printk("\t%d %6d %p %6p %d %d %d\n", + i, + tr_entry->tx_queue[i].Number, + tr_entry->tx_queue[i].Head, + tr_entry->tx_queue[i].Tail, + tr_entry->enq_cap, tr_entry->deq_cap, + tr_entry->TxSeq[i]); + RTMP_IRQ_UNLOCK(&pAd->irq_lock /* &tr_entry->txq_lock[i] */, irqflags); + } + RTMP_IRQ_LOCK(&pAd->irq_lock /* &tr_entry->ps_queue_lock */, irqflags); + printk("\tpsQ %6d %p %p %d %d NoQ:%d\n", + tr_entry->ps_queue.Number, + tr_entry->ps_queue.Head, + tr_entry->ps_queue.Tail, + tr_entry->enq_cap, tr_entry->deq_cap, + tr_entry->NonQosDataSeq); + RTMP_IRQ_UNLOCK(&pAd->irq_lock /* &tr_entry->ps_queue_lock */, irqflags); + + printk("\n"); + return TRUE; +} + + +INT show_devinfo_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR *pstr; +#if defined(RTMP_MAC) || defined(RLT_MAC) + UINT32 mac_val; +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + DBGPRINT(RT_DEBUG_OFF, ("Device MAC\n")); + if (pAd->OpMode == OPMODE_AP) + pstr = "AP"; + else if (pAd->OpMode == OPMODE_STA) + pstr = "STA"; + else + pstr = "Unknown"; + DBGPRINT(RT_DEBUG_OFF, ("Operation Mode: %s\n", pstr)); + + pstr = wmode_2_str(pAd->CommonCfg.PhyMode); + if (pstr) { + DBGPRINT(RT_DEBUG_OFF, ("WirelessMode: %s(%d)\n", pstr, pAd->CommonCfg.PhyMode)); + os_free_mem(pAd, pstr); + } + + DBGPRINT(RT_DEBUG_OFF, ("Channel: %d\n", pAd->CommonCfg.Channel)); + DBGPRINT(RT_DEBUG_OFF, ("\tCentralChannel: %d\n", pAd->CommonCfg.CentralChannel)); +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) + DBGPRINT(RT_DEBUG_OFF, ("\tVHT CentralChannel: %d\n", pAd->CommonCfg.vht_cent_ch)); +#endif /* DOT11_VHT_AC */ + DBGPRINT(RT_DEBUG_OFF, ("\tRF Channel: %d\n", pAd->LatchRfRegs.Channel)); + + DBGPRINT(RT_DEBUG_OFF, ("Bandwidth\n")); + pstr = (pAd->CommonCfg.RegTransmitSetting.field.BW) ? "20/40" : "20"; + DBGPRINT(RT_DEBUG_OFF, ("\tHT-BW: %s\n", pstr)); +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) + { + if (pAd->CommonCfg.vht_bw) + pstr = "80"; + DBGPRINT(RT_DEBUG_OFF, ("\tVHT-BW: %s\n", pstr)); + } +#endif /* DOT11_VHT_AC */ + +#if defined(RTMP_MAC) || defined(RLT_MAC) + // TODO: shiang-7603 + if (pAd->chipCap.hif_type != HIF_MT) { + RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &mac_val); + printk("BackOff Slot : %s slot time, BKOFF_SLOT_CFG(0x1104) = 0x%08x\n", + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_SLOT_INUSED) ? "short" : "long", + mac_val); + } +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + + DBGPRINT(RT_DEBUG_OFF, ("Security\n")); + + return TRUE; +} + + +INT show_wdev_info(RTMP_ADAPTER *pAd, struct wifi_dev *wdev) +{ + INT idx; + + for (idx = 0 ; idx < WDEV_NUM_MAX; idx++) + { + if (pAd->wdev_list[idx] == wdev) { + break; + } + } + + if (idx >= WDEV_NUM_MAX) + { + DBGPRINT(RT_DEBUG_OFF, ("ERR! Cannot found required wdev(%p)!\n", wdev)); + return FALSE; + } + + DBGPRINT(RT_DEBUG_OFF, ("WDEV Instance(%d) Info:\n", idx)); + + return TRUE; +} + + +CHAR *wdev_type_str[]={"AP", "STA", "ADHOC", "WDS", "MESH", "Unknown"}; + +RTMP_STRING *wdev_type2str(int type) +{ + switch (type) + { + case WDEV_TYPE_AP: + return wdev_type_str[0]; + case WDEV_TYPE_STA: + return wdev_type_str[1]; + case WDEV_TYPE_ADHOC: + return wdev_type_str[2]; + case WDEV_TYPE_WDS: + return wdev_type_str[3]; + case WDEV_TYPE_MESH: + return wdev_type_str[4]; + default: + return wdev_type_str[5]; + } +} + + +INT show_sysinfo_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT idx; + UINT32 total_size = 0, cntr_size; + struct wifi_dev *wdev; + + + DBGPRINT(RT_DEBUG_OFF, ("Device Instance\n")); + for (idx = 0; idx < WDEV_NUM_MAX; idx++) { + DBGPRINT(RT_DEBUG_OFF, ("\tWDEV %02d:", idx)); + if (pAd->wdev_list[idx]) + { + UCHAR *str = NULL; + + wdev = pAd->wdev_list[idx]; + DBGPRINT(RT_DEBUG_OFF, ("\n\t\tName/Type:%s/%s\n", + RTMP_OS_NETDEV_GET_DEVNAME(wdev->if_dev), + wdev_type2str(wdev->wdev_type))); + DBGPRINT(RT_DEBUG_OFF, ("\t\tWdev(list) Idx:%d\n", wdev->wdev_idx)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tMacAddr:%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(wdev->if_addr))); + DBGPRINT(RT_DEBUG_OFF, ("\t\tBSSID:%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(wdev->bssid))); + str = wmode_2_str(wdev->PhyMode); + if (str) { + DBGPRINT(RT_DEBUG_OFF, ("\t\tPhyMode:%s\n", str)); + os_free_mem(pAd, str); + } + DBGPRINT(RT_DEBUG_OFF, ("\t\tChannel:%d\n", wdev->channel)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tPortSecured/AllowTx: %d(%sSecured):%d\n", + wdev->PortSecured, + (wdev->PortSecured == WPA_802_1X_PORT_SECURED ? "" : "Not"), + wdev->allow_data_tx)); + DBGPRINT(RT_DEBUG_OFF, ("\t\ttx_pkt_checker:%p\n", wdev->tx_pkt_allowed)); + DBGPRINT(RT_DEBUG_OFF, ("\t\ttx_pkt_handlerer:%p\n", wdev->tx_pkt_handle)); + DBGPRINT(RT_DEBUG_OFF, ("\t\ttx_pkt_hardTransmit:%p\n", wdev->wdev_hard_tx)); + + DBGPRINT(RT_DEBUG_OFF, ("\t\tif_dev:0x%p\tfunc_dev:[%d]0x%p\tsys_handle:0x%p\n", + wdev->if_dev, wdev->func_idx, wdev->func_dev, wdev->sys_handle)); + } + else + { + DBGPRINT(RT_DEBUG_OFF, ("\n")); + } + + } + + DBGPRINT(RT_DEBUG_OFF, ("Memory Statistics:\n")); + + DBGPRINT(RT_DEBUG_OFF, ("\tsize>\n")); + DBGPRINT(RT_DEBUG_OFF, ("\t\tpAd = \t\t%d bytes\n\n", sizeof(*pAd))); + + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tCommonCfg = \t%d bytes\n", sizeof(pAd->CommonCfg))); + total_size += sizeof(pAd->CommonCfg); +#ifdef CONFIG_AP_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tApCfg = \t%d bytes\n", sizeof(pAd->ApCfg))); + total_size += sizeof(pAd->ApCfg); + DBGPRINT(RT_DEBUG_OFF, ("\t\t\t\tMBSSID = \t%d B (PerMBSS =%d B, Total MBSS Num= %d)\n", + sizeof(pAd->ApCfg.MBSSID), sizeof(struct _BSS_STRUCT), HW_BEACON_MAX_NUM)); +#ifdef APCLI_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("\t\t\t\t\tAPCLI = \t%d bytes (PerAPCLI =%d bytes, Total APCLI Num= %d)\n", + sizeof(pAd->ApCfg.ApCliTab), sizeof(struct _APCLI_STRUCT), MAX_APCLI_NUM)); +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef RTMP_MAC_PCI + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tTxRing = \t%d bytes\n", sizeof(pAd->TxRing))); + total_size += sizeof(pAd->TxRing); + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tRxRing = \t%d bytes\n", sizeof(pAd->RxRing))); + total_size += sizeof(pAd->RxRing); +#ifdef CONFIG_ANDES_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tCtrlRing = \t%d bytes\n", sizeof(pAd->CtrlRing))); + total_size += sizeof(pAd->CtrlRing); +#endif /* CONFIG_ANDES_SUPPORT */ + +#ifdef MT_MAC + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tBcnRing = \t%d bytes\n", sizeof(pAd->BcnRing))); + total_size += sizeof(pAd->BcnRing); +#endif /* MT_MAC */ +#endif /* RTMP_MAC_PCI */ + + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tMgmtRing = \t%d bytes\n", sizeof(pAd->MgmtRing))); + total_size += sizeof(pAd->MgmtRing); + + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tMlme = \t%d bytes\n", sizeof(pAd->Mlme))); + total_size += sizeof(pAd->Mlme); + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tMacTab = \t%d bytes\n", sizeof(pAd->MacTab))); + total_size += sizeof(pAd->MacTab); + +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tBATable = \t%d bytes\n", sizeof(pAd->BATable))); + total_size += sizeof(pAd->BATable); +#endif /* DOT11_N_SUPPORT */ + + cntr_size = sizeof(pAd->Counters8023) + sizeof(pAd->WlanCounters) + + sizeof(pAd->RalinkCounters) + /* sizeof(pAd->DrsCounters) */+ + sizeof(pAd->PrivateInfo); + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tCounter** = \t%d bytes\n", cntr_size)); + total_size += cntr_size; + +#if defined (AP_SCAN_SUPPORT) || defined (CONFIG_STA_SUPPORT) + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tScanTab = \t%d bytes\n", sizeof(pAd->ScanTab))); + total_size += sizeof(pAd->ScanTab); +#endif + DBGPRINT(RT_DEBUG_OFF, ("\tsize> Total = \t\t%d bytes, Others = %d bytes\n\n", + total_size, sizeof(*pAd)-total_size)); + + return TRUE; +} + +#ifdef MULTI_CLIENT_SUPPORT +INT show_configinfo_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + printk("\n=================>\n"); + DBGPRINT(RT_DEBUG_OFF, ("config para :\n")); + DBGPRINT(RT_DEBUG_OFF, ("\n\tRtsRetryCnt: \t%d", RtsRetryCnt)); + DBGPRINT(RT_DEBUG_OFF, ("\n\tMidRate: \t%d", MidRateRssi)); + DBGPRINT(RT_DEBUG_OFF, ("\n\tFarRate: \t%d", FarRateRssi)); + DBGPRINT(RT_DEBUG_OFF, ("\n\tFarDropRssi: \t%d", FarDropRssi)); + DBGPRINT(RT_DEBUG_OFF, ("\n\tTIMIdle: \t%d", TX_IDLE_TIME)); + DBGPRINT(RT_DEBUG_OFF, ("\n\tTxSwQMaxLen: \t%d", pAd->TxSwQMaxLen)); + DBGPRINT(RT_DEBUG_OFF, ("\n\tFalseCCAThreshold: \t%d", FalseCCAthSelRaTable)); + printk("\n<=================\n"); + DBGPRINT(RT_DEBUG_OFF, ("\n\tis_multiclient_mode_on: \t%d", is_multiclient_mode_on(pAd))); + DBGPRINT(RT_DEBUG_OFF, ("\n\tManual multiclient_mode_on: \t%d", pAd->bManualMultiClientOn)); +#ifdef TRAFFIC_BASED_TXOP + DBGPRINT(RT_DEBUG_OFF, ("\n\tmulticlient_mode_check: \t%d, [%d][%d]", + pAd->MultiClientOnMode, pAd->MacTab.Size, pAd->StaTxopAbledCnt)); +#endif + printk("\n"); + + return TRUE; +} +#endif + +INT show_trinfo_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ +#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_RBUS_SUPPORT) + if (IS_RBUS_INF(pAd) || IS_PCI_INF(pAd)) + { + ULONG irq_flags = 0; + UINT32 tbase[NUM_OF_TX_RING], tcnt[NUM_OF_TX_RING]; + UINT32 tcidx[NUM_OF_TX_RING], tdidx[NUM_OF_TX_RING]; + UINT32 rbase[NUM_OF_RX_RING], rcnt[NUM_OF_RX_RING]; + UINT32 rcidx[NUM_OF_RX_RING], rdidx[NUM_OF_RX_RING]; + UINT32 mbase[4] = {0}, mcnt[4] = {0}, mcidx[4] = {0}, mdidx[4] = {0}; + UINT32 sys_ctrl[4]; + UINT32 cr_int_src = 0, cr_int_mask = 0, cr_delay_int = 0, cr_wpdma_glo_cfg = 0; +#ifdef RLT_MAC + UINT32 pbf_val, pcnt[5]; +#endif /* RLT_MAC */ + INT idx; + + RTMP_IRQ_LOCK(&pAd->irq_lock, irq_flags); + for (idx = 0; idx < NUM_OF_TX_RING; idx++) + { + RTMP_IO_READ32(pAd, pAd->TxRing[idx].hw_desc_base, &tbase[idx]); + RTMP_IO_READ32(pAd, pAd->TxRing[idx].hw_cnt_addr, &tcnt[idx]); + RTMP_IO_READ32(pAd, pAd->TxRing[idx].hw_cidx_addr, &tcidx[idx]); + RTMP_IO_READ32(pAd, pAd->TxRing[idx].hw_didx_addr, &tdidx[idx]); + } + + for (idx = 0; idx < NUM_OF_RX_RING; idx++) + { + RTMP_IO_READ32(pAd, pAd->RxRing[idx].hw_desc_base, &rbase[idx]); + RTMP_IO_READ32(pAd, pAd->RxRing[idx].hw_cnt_addr, &rcnt[idx]); + RTMP_IO_READ32(pAd, pAd->RxRing[idx].hw_cidx_addr, &rcidx[idx]); + RTMP_IO_READ32(pAd, pAd->RxRing[idx].hw_didx_addr, &rdidx[idx]); + } + + RTMP_IO_READ32(pAd, pAd->MgmtRing.hw_desc_base, &mbase[0]); + RTMP_IO_READ32(pAd, pAd->MgmtRing.hw_cnt_addr, &mcnt[0]); + RTMP_IO_READ32(pAd, pAd->MgmtRing.hw_cidx_addr, &mcidx[0]); + RTMP_IO_READ32(pAd, pAd->MgmtRing.hw_didx_addr, &mdidx[0]); + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { +#ifdef CONFIG_ANDES_SUPPORT + RTMP_IO_READ32(pAd, pAd->CtrlRing.hw_desc_base, &mbase[1]); + RTMP_IO_READ32(pAd, pAd->CtrlRing.hw_cnt_addr, &mcnt[1]); + RTMP_IO_READ32(pAd, pAd->CtrlRing.hw_cidx_addr, &mcidx[1]); + RTMP_IO_READ32(pAd, pAd->CtrlRing.hw_didx_addr, &mdidx[1]); +#endif /* CONFIG_ANDES_SUPPORT */ + + RTMP_IO_READ32(pAd, RLT_PBF_CFG, &pbf_val); + RTMP_IO_READ32(pAd, TX_MAX_PCNT, &pcnt[0]); + RTMP_IO_READ32(pAd, RX_MAX_PCNT, &pcnt[1]); + RTMP_IO_READ32(pAd, TXQ_STA, &pcnt[2]); + RTMP_IO_READ32(pAd, RXQ_STA, &pcnt[3]); + RTMP_IO_READ32(pAd, TXRXQ_PCNT, &pcnt[4]); + RTMP_IO_READ32(pAd, PBF_DBG, &pcnt[5]); + } +#endif /* RLT_MAC */ + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { +#ifdef CONFIG_ANDES_SUPPORT + RTMP_IO_READ32(pAd, pAd->CtrlRing.hw_desc_base, &mbase[1]); + RTMP_IO_READ32(pAd, pAd->CtrlRing.hw_cnt_addr, &mcnt[1]); + RTMP_IO_READ32(pAd, pAd->CtrlRing.hw_cidx_addr, &mcidx[1]); + RTMP_IO_READ32(pAd, pAd->CtrlRing.hw_didx_addr, &mdidx[1]); +#endif /* CONFIG_ANDES_SUPPORT */ + + RTMP_IO_READ32(pAd, pAd->BcnRing.hw_desc_base, &mbase[2]); + RTMP_IO_READ32(pAd, pAd->BcnRing.hw_cnt_addr, &mcnt[2]); + RTMP_IO_READ32(pAd, pAd->BcnRing.hw_cidx_addr, &mcidx[2]); + RTMP_IO_READ32(pAd, pAd->BcnRing.hw_didx_addr, &mdidx[2]); + + RTMP_IO_READ32(pAd, pAd->TxBmcRing.hw_desc_base, &mbase[3]); + RTMP_IO_READ32(pAd, pAd->TxBmcRing.hw_cnt_addr, &mcnt[3]); + RTMP_IO_READ32(pAd, pAd->TxBmcRing.hw_cidx_addr, &mcidx[3]); + RTMP_IO_READ32(pAd, pAd->TxBmcRing.hw_didx_addr, &mdidx[3]); + } +#endif /* MT_MAC */ + +#ifdef MT_MAC + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + cr_int_src = MT_INT_SOURCE_CSR; + cr_int_mask = MT_INT_MASK_CSR; + cr_delay_int = MT_DELAY_INT_CFG; + cr_wpdma_glo_cfg = MT_WPDMA_GLO_CFG; + } +#endif /* MT_MAC */ + +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (pAd->chipCap.hif_type == HIF_RLT || pAd->chipCap.hif_type == HIF_RTMP) { + cr_int_src = INT_SOURCE_CSR; + cr_int_mask = INT_MASK_CSR; + cr_delay_int = DELAY_INT_CFG; + cr_wpdma_glo_cfg = WPDMA_GLO_CFG; + } +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + RTMP_IO_READ32(pAd, cr_int_src, &sys_ctrl[0]); + RTMP_IO_READ32(pAd, cr_int_mask, &sys_ctrl[1]); + RTMP_IO_READ32(pAd, cr_delay_int, &sys_ctrl[2]); + RTMP_IO_READ32(pAd, cr_wpdma_glo_cfg, &sys_ctrl[3]); + + RTMP_IRQ_UNLOCK(&pAd->irq_lock, irq_flags); + + DBGPRINT(RT_DEBUG_OFF, ("TxRing Configuration\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tRingIdx Reg \tBase \t\tCnt \tCIDX \tDIDX \tSWIDX\n")); + for (idx = 0; idx < NUM_OF_TX_RING; idx++) { + DBGPRINT(RT_DEBUG_OFF, ("\t%d \t0x%04x \t0x%08x \t0x%x \t0x%x \t0x%x \t0x%x\n", + idx, pAd->TxRing[idx].hw_desc_base, tbase[idx], tcnt[idx], tcidx[idx], tdidx[idx],pAd->TxRing[idx].TxSwFreeIdx)); + } + + DBGPRINT(RT_DEBUG_OFF, ("\nRxRing Configuration\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tRingIdx Reg \tBase \t\tCnt \tCIDX \tDIDX\tSWIDX\n")); + for (idx = 0; idx < NUM_OF_RX_RING; idx++) { + DBGPRINT(RT_DEBUG_OFF, ("\t%d \t0x%04x \t0x%08x \t0x%x \t0x%x \t0x%x \t0x%x\n", + idx, pAd->RxRing[idx].hw_desc_base, rbase[idx], rcnt[idx], rcidx[idx], rdidx[idx],pAd->RxRing[idx].RxSwReadIdx)); + } + + DBGPRINT(RT_DEBUG_OFF, ("\nMgmtRing Configuration\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tRingIdx Reg \tBase \t\tCnt \tCIDX \tDIDX\tSWIDX\n")); + DBGPRINT(RT_DEBUG_OFF, ("\t%d \t0x%04x \t0x%08x \t0x%x \t0x%x \t0x%x \t0x%x\n", + 0, pAd->MgmtRing.hw_desc_base, mbase[0], mcnt[0], mcidx[0], mdidx[0],pAd->MgmtRing.TxSwFreeIdx)); + +#ifdef CONFIG_ANDES_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("\nCtrlRing Configuration\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tRingIdx Reg \tBase \t\tCnt \tCIDX \tDIDX\tSWIDX\n")); + DBGPRINT(RT_DEBUG_OFF, ("\t%d \t0x%04x \t0x%08x \t0x%x \t0x%x \t0x%x \t0x%x\n", + 0, pAd->CtrlRing.hw_desc_base, mbase[1], mcnt[1], mcidx[1], mdidx[1],pAd->CtrlRing.TxSwFreeIdx)); +#endif /* CONFIG_ANDES_SUPPORT */ + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("\nBcnRing Configuration\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tRingIdx Reg \tBase \t\tCnt \tCIDX \tDIDX \tSWIDX\n")); + DBGPRINT(RT_DEBUG_OFF, ("\t%d \t0x%04x \t0x%08x \t0x%x \t0x%x \t0x%x \t0x%x\n", + 0, pAd->BcnRing.hw_desc_base, mbase[2], mcnt[2], mcidx[2], mdidx[2],pAd->BcnRing.TxSwFreeIdx)); + } + + DBGPRINT(RT_DEBUG_OFF, ("\nBMCRing Configuration\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tRingIdx Reg \tBase \t\tCnt \tCIDX \tDIDX \tSWIDX\n")); + DBGPRINT(RT_DEBUG_OFF, ("\t%d \t0x%04x \t0x%08x \t0x%x \t0x%x \t0x%x \t0x%x\n", + 0, pAd->TxBmcRing.hw_desc_base, mbase[3], mcnt[3], mcidx[3], mdidx[3],pAd->TxBmcRing.TxSwFreeIdx)); +#endif /* MT_MAC */ + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + DBGPRINT(RT_DEBUG_OFF, ("\nPBF Configuration\n" + "\tRLT_PBF_CFG: 0x%08x\n", pbf_val)); + DBGPRINT(RT_DEBUG_OFF, ("\tPCNT_CFG:\n" + "\t\tTxMax[0x%04x] -0x%08x\n", TX_MAX_PCNT, pcnt[0])); + DBGPRINT(RT_DEBUG_OFF, ("\t\tTxStat[0x%04x] -0x%08x\n", RX_MAX_PCNT, pcnt[2])); + DBGPRINT(RT_DEBUG_OFF, ("\t\tTxUsed[0x%04x] -0x%08x\n", TXRXQ_PCNT, pcnt[4])); + DBGPRINT(RT_DEBUG_OFF, ("\t\tRxMax[0x%04x] -0x%08x\n", RX_MAX_PCNT, pcnt[1])); + DBGPRINT(RT_DEBUG_OFF, ("\t\tRxStat[0x%04x] -0x%08x\n", RXQ_STA, pcnt[3])); + DBGPRINT(RT_DEBUG_OFF, ("\t\tFreCNT[0x%04x] -0x%08x\n", PBF_DBG, pcnt[5])); + } +#endif /* RLT_MAC */ + + DBGPRINT(RT_DEBUG_OFF, ("Interrupt Configuration\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tIntCSR \tIntMask \tDelayINT\n")); + DBGPRINT(RT_DEBUG_OFF, ("\t0x%x \t0x%x \t0x%x\n", sys_ctrl[0], sys_ctrl[1], sys_ctrl[2])); + DBGPRINT(RT_DEBUG_OFF, ("DMA Configuration(0x%x)\n", sys_ctrl[3])); + DBGPRINT(RT_DEBUG_OFF, ("\tTx/RxDMAEn=%d/%d, \tTx/RxDMABusy=%d/%d\n", + sys_ctrl[3] & 0x1, sys_ctrl[3] & 0x4, + sys_ctrl[3] & 0x2, sys_ctrl[3] & 0x8)); + + DBGPRINT(RT_DEBUG_OFF, ("PDMA Info\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tPDMAMonitorEn=%d, TxRCounter = %lu, TxDMACheckTimes = %d, RxRCounter = %lu, RxDMACheckTimes = %d, PDMARFailCount = %lu\n", pAd->PDMAWatchDogEn, pAd->TxDMAResetCount, pAd->TxDMACheckTimes, pAd->RxDMAResetCount, pAd->RxDMACheckTimes, pAd->PDMAResetFailCount)); + DBGPRINT(RT_DEBUG_OFF, ("PSE Info\n")); +#ifdef DMA_RESET_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("\tPSEMonitorEn=%d, bcn_reset_en=%d, RCounter = %lu, RxPseCheckTimes = %u, PSETriggerType1Count = %lu, PSETriggerType2Count = %lu, PSERFailCount = %lu, PSEResetFailRecover=%d, PSEResetFailRetryQuota=%lu\n", pAd->PSEWatchDogEn, pAd->bcn_reset_en, pAd->PSEResetCount, pAd->RxPseCheckTimes, pAd->PSETriggerType1Count, pAd->PSETriggerType2Count, pAd->PSEResetFailCount, pAd->PSEResetFailRecover, pAd->PSEResetFailRetryQuota)); + DBGPRINT(RT_DEBUG_OFF, ("\tAC0HitCount=%lu, AC1HitCount=%lu,AC2HitCount=%lu,AC3HitCount=%lu,MgtHitCount=%lu\n", pAd->AC0HitCount, pAd->AC1HitCount, pAd->AC2HitCount, pAd->AC3HitCount,pAd->MgtHitCount)); +#else /* DMA_RESET_SUPPORT */ + DBGPRINT(RT_DEBUG_OFF, ("\tPSEMonitorEn=%d, RCounter = %lu, RxPseCheckTimes = %u, PSETriggerType1Count = %lu, PSETriggerType2Count = %lu, PSERFailCount = %lu\n", pAd->PSEWatchDogEn, pAd->PSEResetCount, pAd->RxPseCheckTimes, pAd->PSETriggerType1Count, pAd->PSETriggerType2Count, pAd->PSEResetFailCount)); +#endif /* !DMA_RESET_SUPPORT */ + DBGPRINT(RT_DEBUG_OFF, ("\n")); + DBGPRINT(RT_DEBUG_OFF, ("SkipTxRcount=%lu\n", pAd->SkipTxRCount)); + } +#endif /* defined(RTMP_PCI_SUPPORT) || defined(RTMP_RBUS_SUPPORT) */ + + + return TRUE; +} + + +INT show_txqinfo_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT qidx; + ULONG irqflag = 0; + UCHAR *TxSwQ = NULL; + struct tx_swq_fifo *fifo_swq; + + os_alloc_mem(NULL, &TxSwQ, 512 * 4); + if (TxSwQ == NULL) + { + DBGPRINT(RT_DEBUG_OFF, ("%s():mem alloc failed!\n", __FUNCTION__)); + return FALSE; + } + + DBGPRINT(RT_DEBUG_OFF, ("%s():Dump TxQ Info\n", __FUNCTION__)); + for (qidx = 0; qidx < 4; qidx++) + { + fifo_swq = &pAd->tx_swq[qidx]; + + RTMP_IRQ_LOCK(&pAd->irq_lock, irqflag); + NdisMoveMemory(&TxSwQ[qidx * 512], fifo_swq->swq, 512); + RTMP_IRQ_UNLOCK(&pAd->irq_lock, irqflag); + } + + os_free_mem(NULL, TxSwQ); + + rtmp_tx_swq_dump(pAd, 0); + rtmp_sta_txq_dump(pAd, &pAd->MacTab.tr_entry[1], 0); + + return TRUE; +} +#endif /* DBG */ + +#ifdef WSC_STA_SUPPORT +INT Show_WpsManufacturer_Proc( + IN PRTMP_ADAPTER pAd, + OUT RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *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 RTMP_STRING *pBuf, + IN ULONG BufLen) +{ + snprintf(pBuf, BufLen, "\tModuleTxpower = %d", pAd->CommonCfg.ModuleTxpower); + return 0; +} +#endif /* SINGLE_SKU */ + +#ifdef APCLI_SUPPORT + INT RTMPIoctlConnStatus(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + + INT i=0; + POS_COOKIE pObj; + UCHAR ifIndex; + BOOLEAN bConnect=FALSE; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + DBGPRINT(RT_DEBUG_TRACE, ("==>RTMPIoctlConnStatus\n")); + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + + DBGPRINT(RT_DEBUG_OFF, ("=============================================================\n")); + if((pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState == APCLI_CTRL_CONNECTED) + && (pAd->ApCfg.ApCliTab[ifIndex].SsidLen != 0)) + { + for (i=0; iMacTab.Content[i]; + STA_TR_ENTRY *tr_entry = &pAd->MacTab.tr_entry[i]; + + if ( IS_ENTRY_APCLI(pEntry) + && (pEntry->Sst == SST_ASSOC) + && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + DBGPRINT(RT_DEBUG_OFF, ("ApCli%d Connected AP : %02X:%02X:%02X:%02X:%02X:%02X SSID:%s\n", + ifIndex, PRINT_MAC(pEntry->Addr), pAd->ApCfg.ApCliTab[ifIndex].Ssid)); + bConnect=TRUE; +#ifdef MWDS + if(pAd->ApCfg.ApCliTab[ifIndex].MlmeAux.bSupportMWDS) + DBGPRINT(RT_DEBUG_OFF, ("MWDSCap : YES\n")); + else + DBGPRINT(RT_DEBUG_OFF, ("MWDSCap : NO\n")); +#endif /* MWDS */ + } + } + + 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, + 13, 26, 39, 52, 78, 104, 117, 130, 156, /* 11ac: 20Mhz, 800ns GI, MCS: 0~8 */ + 27, 54, 81, 108, 162, 216, 243, 270, 324, 360, /*11ac: 40Mhz, 800ns GI, MCS: 0~9 */ + 59, 117, 176, 234, 351, 468, 527, 585, 702, 780, /*11ac: 80Mhz, 800ns GI, MCS: 0~9 */ + 14, 29, 43, 57, 87, 115, 130, 144, 173, /* 11ac: 20Mhz, 400ns GI, MCS: 0~8 */ + 30, 60, 90, 120, 180, 240, 270, 300, 360, 400, /*11ac: 40Mhz, 400ns GI, MCS: 0~9 */ + 65, 130, 195, 260, 390, 520, 585, 650, 780, 867 /*11ac: 80Mhz, 400ns GI, MCS: 0~9 */ + }; + + int rate_count = sizeof(MCSMappingRateTable)/sizeof(int); + int rate_index = 0; + int value = 0; + +#ifdef DOT11_VHT_AC + if (HTSetting.field.MODE >= MODE_VHT) + { + if (HTSetting.field.BW == BW_20) { + rate_index = 108 + + ((UCHAR)HTSetting.field.ShortGI * 29) + + ((UCHAR)HTSetting.field.MCS); + } + else if (HTSetting.field.BW == BW_40) { + rate_index = 117 + + ((UCHAR)HTSetting.field.ShortGI * 29) + + ((UCHAR)HTSetting.field.MCS); + } + else if (HTSetting.field.BW == BW_80) { + rate_index = 127 + + ((UCHAR)HTSetting.field.ShortGI * 29) + + ((UCHAR)HTSetting.field.MCS); + } + } + else +#endif /* DOT11_VHT_AC */ +#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; +} + +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) +INT Set_WifiFwd_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + int active = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s::active=%d\n", __FUNCTION__, active)); + + if (active == 0) { + if (wf_fwd_pro_halt_hook) + wf_fwd_pro_halt_hook(); + } else { + if (wf_fwd_pro_active_hook) + wf_fwd_pro_active_hook(); + } + + return TRUE; +} + +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +INT WifiFwdSet( + IN int disabled) +{ + if (disabled != 0) { + if (wf_fwd_pro_disabled_hook) + wf_fwd_pro_disabled_hook(); + } + + DBGPRINT(RT_DEBUG_OFF, ("%s::disabled=%d\n", __FUNCTION__, disabled)); + + return TRUE; +} +INT Set_WifiFwd_Down( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + int disable = simple_strtol(arg, 0, 10); + + WifiFwdSet(disable); + return TRUE; +} + + +INT Set_WifiFwdBpdu_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + int active = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s::active=%d\n", __FUNCTION__, active)); + + if (active == 0) { + if (wf_fwd_bpdu_halt_hook) + wf_fwd_bpdu_halt_hook(); + } else { + if (wf_fwd_bpdu_active_hook) + wf_fwd_bpdu_active_hook(); + } + + return TRUE; +} + +#endif + +INT Set_WifiFwdAccessSchedule_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + int active = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s::active=%d\n", __FUNCTION__, active)); + + if (active == 0) { + if (wf_fwd_access_schedule_halt_hook) + wf_fwd_access_schedule_halt_hook(); + } else { + if (wf_fwd_access_schedule_active_hook) + wf_fwd_access_schedule_active_hook(); + } + + return TRUE; +} + +INT Set_WifiFwdHijack_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + int active = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s::active=%d\n", __FUNCTION__, active)); + + if (active == 0) { + if (wf_fwd_hijack_halt_hook) + wf_fwd_hijack_halt_hook(); + } else { + if (wf_fwd_hijack_active_hook) + wf_fwd_hijack_active_hook(); + } + + return TRUE; +} + +INT Set_WifiFwdRepDevice( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + int rep = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s::rep=%d\n", __FUNCTION__, rep)); + + if (wf_fwd_get_rep_hook) + wf_fwd_get_rep_hook(rep); + + return TRUE; +} + +INT Set_WifiFwdShowEntry( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + if (wf_fwd_show_entry_hook) + wf_fwd_show_entry_hook(); + + return TRUE; +} + +INT Set_WifiFwdDeleteEntry( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + int idx = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s::idx=%d\n", __FUNCTION__, idx)); + + if (wf_fwd_delete_entry_hook) + wf_fwd_delete_entry_hook(idx); + + return TRUE; +} + +INT Set_PacketSourceShowEntry( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + if (packet_source_show_entry_hook) + packet_source_show_entry_hook(); + + return TRUE; +} + +INT Set_PacketSourceDeleteEntry( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + int idx = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("%s::idx=%d\n", __FUNCTION__, idx)); + + if (packet_source_delete_entry_hook) + packet_source_delete_entry_hook(idx); + + return TRUE; +} +#endif /* CONFIG_WIFI_PKT_FWD */ + + + +#ifdef VHT_TXBF_SUPPORT +/* + The VhtNDPA sounding inupt string format should be xx:xx:xx:xx:xx:xx-d, + =>The six 2 digit hex-decimal number previous are the Mac address, + =>The seventh decimal number is the MCS value. +*/ +INT Set_VhtNDPA_Sounding_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR mac[6]; + UINT mcs; + RTMP_STRING *token; + RTMP_STRING sepValue[] = ":", DASH = '-'; + INT i; + MAC_TABLE_ENTRY *pEntry = NULL; + + DBGPRINT(RT_DEBUG_TRACE,("\n%s\n", arg)); + + /*Mac address acceptable format 01:02:03:04:05:06 length 17 plus the "-" and MCS value in decimal format.*/ + if(strlen(arg) < 19) + return FALSE; + + token = strchr(arg, DASH); + if ((token != NULL) && (strlen(token)>1)) + { + mcs = (UINT)simple_strtol((token+1), 0, 10); + + *token = '\0'; + for (i = 0, token = rstrtok(arg, &sepValue[0]); token; token = rstrtok(NULL, &sepValue[0]), i++) + { + if((strlen(token) != 2) || (!isxdigit(*token)) || (!isxdigit(*(token+1)))) + return FALSE; + AtoH(token, (&mac[i]), 1); + } + if (i != 6) + return FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x\n", + PRINT_MAC(mac), mcs)); + + pEntry = MacTableLookup(pAd, (PUCHAR) mac); + if (pEntry) { +#ifdef SOFT_SOUNDING + pEntry->snd_rate.field.MODE = MODE_VHT; + pEntry->snd_rate.field.BW = (mcs / 100) > BW_80 ? BW_80 : (mcs / 100); + mcs %= 100; + pEntry->snd_rate.field.MCS = ((mcs / 10) << 4 | (mcs % 10)); + + DBGPRINT(RT_DEBUG_OFF, ("%s():Trigger VHT NDPA Sounding=%02x:%02x:%02x:%02x:%02x:%02x, snding rate=VHT-%sHz, %dSS-MCS%d\n", + __FUNCTION__, PRINT_MAC(mac), + get_bw_str(pEntry->snd_rate.field.BW), + (pEntry->snd_rate.field.MCS >> 4) + 1, + pEntry->snd_rate.field.MCS & 0xf)); +#endif + trigger_vht_ndpa(pAd, pEntry); + } + + return TRUE; + } + + return FALSE; +} +#endif /* VHT_TXBF_SUPPORT */ + + +#ifdef DOT11_N_SUPPORT + +#ifdef DBG +void assoc_ht_info_debugshow( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR ht_cap_len, + IN HT_CAPABILITY_IE *pHTCapability) +{ + HT_CAP_INFO *pHTCap; + HT_CAP_PARM *pHTCapParm; + EXT_HT_CAP_INFO *pExtHT; + + + if (pHTCapability && (ht_cap_len > 0)) + { + pHTCap = &pHTCapability->HtCapInfo; + pHTCapParm = &pHTCapability->HtCapParm; + pExtHT = &pHTCapability->ExtHtCapInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("Peer - 11n HT Info\n")); + DBGPRINT(RT_DEBUG_TRACE, ("\tHT Cap Info: \n")); + DBGPRINT(RT_DEBUG_TRACE, ("\t\t HT_RX_LDPC(%d), BW(%d), MIMOPS(%d), GF(%d), ShortGI_20(%d), ShortGI_40(%d)\n", + pHTCap->ht_rx_ldpc, pHTCap->ChannelWidth, pHTCap->MimoPs, pHTCap->GF, + pHTCap->ShortGIfor20, pHTCap->ShortGIfor40)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\t TxSTBC(%d), RxSTBC(%d), DelayedBA(%d), A-MSDU(%d), CCK_40(%d)\n", + pHTCap->TxSTBC, pHTCap->RxSTBC, pHTCap->DelayedBA, pHTCap->AMsduSize, pHTCap->CCKmodein40)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\t PSMP(%d), Forty_Mhz_Intolerant(%d), L-SIG(%d)\n", + pHTCap->PSMP, pHTCap->Forty_Mhz_Intolerant, pHTCap->LSIGTxopProSup)); + + DBGPRINT(RT_DEBUG_TRACE, ("\tHT Parm Info: \n")); + DBGPRINT(RT_DEBUG_TRACE, ("\t\t MaxRx A-MPDU Factor(%d), MPDU Density(%d)\n", + pHTCapParm->MaxRAmpduFactor, pHTCapParm->MpduDensity)); + + DBGPRINT(RT_DEBUG_TRACE, ("\tHT MCS set: \n")); + DBGPRINT(RT_DEBUG_TRACE, ("\t\t RxMCS(%02x %02x %02x %02x %02x) MaxRxMbps(%d) TxMCSSetDef(%02x)\n", + pHTCapability->MCSSet[0], pHTCapability->MCSSet[1], pHTCapability->MCSSet[2], + pHTCapability->MCSSet[3], pHTCapability->MCSSet[4], + (pHTCapability->MCSSet[11]<<8) + pHTCapability->MCSSet[10], + pHTCapability->MCSSet[12])); + + DBGPRINT(RT_DEBUG_TRACE, ("\tExt HT Cap Info: \n")); + DBGPRINT(RT_DEBUG_TRACE, ("\t\t PCO(%d), TransTime(%d), MCSFeedback(%d), +HTC(%d), RDG(%d)\n", + pExtHT->Pco, pExtHT->TranTime, pExtHT->MCSFeedback, pExtHT->PlusHTC, pExtHT->RDGSupport)); + + + 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 */ + } +} +#endif /* DBG */ + +INT Set_BurstMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG Value; + + Value = simple_strtol(arg, 0, 10); + pAd->CommonCfg.bRalinkBurstMode = ((Value == 1) ? TRUE : FALSE); + + AsicSetRalinkBurstMode(pAd, pAd->CommonCfg.bRalinkBurstMode); + + DBGPRINT(RT_DEBUG_TRACE, ("Set_BurstMode_Proc ::%s\n", + (pAd->CommonCfg.bRalinkBurstMode == TRUE) ? "enabled" : "disabled")); + + return TRUE; +} +#endif /* DOT11_N_SUPPORT */ + + +#ifdef DOT11_VHT_AC +VOID assoc_vht_info_debugshow( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN VHT_CAP_IE *vht_cap, + IN VHT_OP_IE *vht_op) +{ + VHT_CAP_INFO *cap_info; + VHT_MCS_SET *mcs_set; + VHT_OP_INFO *op_info; + VHT_MCS_MAP *mcs_map; + + + if (!WMODE_CAP_AC(pAd->CommonCfg.PhyMode)) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("Peer - 11AC VHT Info\n")); + if (vht_cap) + { + cap_info = &vht_cap->vht_cap; + mcs_set = &vht_cap->mcs_set; + + hex_dump("peer vht_cap raw data", (UCHAR *)cap_info, sizeof(VHT_CAP_INFO)); + hex_dump("peer vht_mcs raw data", (UCHAR *)mcs_set, sizeof(VHT_MCS_SET)); + + DBGPRINT(RT_DEBUG_TRACE, ("\tVHT Cap Info: \n")); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tMaxMpduLen(%d), BW(%d), SGI_80M(%d), RxLDPC(%d), TxSTBC(%d), RxSTBC(%d), +HTC-VHT(%d)\n", + cap_info->max_mpdu_len, cap_info->ch_width, cap_info->sgi_80M, cap_info->rx_ldpc, cap_info->tx_stbc, + cap_info->rx_stbc, cap_info->htc_vht_cap)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tMaxAmpduExp(%d), VhtLinkAdapt(%d), RxAntConsist(%d), TxAntConsist(%d)\n", + cap_info->max_ampdu_exp, cap_info->vht_link_adapt, cap_info->rx_ant_consistency, cap_info->tx_ant_consistency)); + mcs_map = &mcs_set->rx_mcs_map; + DBGPRINT(RT_DEBUG_TRACE, ("\t\tRxMcsSet: HighRate(%d), RxMCSMap(%d,%d,%d,%d,%d,%d,%d)\n", + mcs_set->rx_high_rate, mcs_map->mcs_ss1, mcs_map->mcs_ss2, mcs_map->mcs_ss3, + mcs_map->mcs_ss4, mcs_map->mcs_ss5, mcs_map->mcs_ss6, mcs_map->mcs_ss7)); + mcs_map = &mcs_set->tx_mcs_map; + DBGPRINT(RT_DEBUG_TRACE, ("\t\tTxMcsSet: HighRate(%d), TxMcsMap(%d,%d,%d,%d,%d,%d,%d)\n", + mcs_set->tx_high_rate, mcs_map->mcs_ss1, mcs_map->mcs_ss2, mcs_map->mcs_ss3, + mcs_map->mcs_ss4, mcs_map->mcs_ss5, mcs_map->mcs_ss6, mcs_map->mcs_ss7)); +#ifdef VHT_TXBF_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("\t\tETxBfCap: Bfer(%d), Bfee(%d), SndDim(%d)\n", + cap_info->bfer_cap_su, cap_info->bfee_cap_su, cap_info->num_snd_dimension)); +#endif + } + + if (vht_op) + { + op_info = &vht_op->vht_op_info; + mcs_map = &vht_op->basic_mcs_set; + DBGPRINT(RT_DEBUG_TRACE, ("\tVHT OP Info: \n")); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tChannel Width(%d), CenteralFreq1(%d), CenteralFreq2(%d)\n", + op_info->ch_width, op_info->center_freq_1, op_info->center_freq_2)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tBasicMCSSet(SS1:%d, SS2:%d, SS3:%d, SS4:%d, SS5:%d, SS6:%d, SS7:%d)\n", + mcs_map->mcs_ss1, mcs_map->mcs_ss2, mcs_map->mcs_ss3, + mcs_map->mcs_ss4, mcs_map->mcs_ss5, mcs_map->mcs_ss6, + mcs_map->mcs_ss7)); + } + + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + +} +#endif /* DOT11_VHT_AC */ + + +INT Set_RateAdaptInterval(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 ra_time, ra_qtime; + RTMP_STRING *token; + char sep = ':'; + ULONG irqFlags = 0; + +/* + The ra_interval inupt string format should be d:d, in units of ms. + =>The first decimal number indicates the rate adaptation checking period, + =>The second decimal number indicates the rate adaptation quick response checking period. +*/ + DBGPRINT(RT_DEBUG_TRACE,("%s():%s\n", __FUNCTION__, arg)); + + token = strchr(arg, sep); + if (token != NULL) + { + *token = '\0'; + + if (strlen(arg) && strlen(token+1)) + { + ra_time = simple_strtol(arg, 0, 10); + ra_qtime = simple_strtol(token+1, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("%s():Set RateAdaptation TimeInterval as(%d:%d) ms\n", + __FUNCTION__, ra_time, ra_qtime)); + + RTMP_IRQ_LOCK(&pAd->irq_lock, irqFlags); + pAd->ra_interval = ra_time; + pAd->ra_fast_interval = ra_qtime; +#ifdef CONFIG_AP_SUPPORT + if (pAd->ApCfg.ApQuickResponeForRateUpTimerRunning == TRUE) + { + BOOLEAN Cancelled; + + RTMPCancelTimer(&pAd->ApCfg.ApQuickResponeForRateUpTimer, &Cancelled); + pAd->ApCfg.ApQuickResponeForRateUpTimerRunning = FALSE; + } +#endif /* CONFIG_AP_SUPPORT */ + RTMP_IRQ_UNLOCK(&pAd->irq_lock, irqFlags); + return TRUE; + } + } + + return FALSE; + +} + +#ifdef CONFIG_SNIFFER_SUPPORT +INT Set_MonitorMode_Proc( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *arg) +{ + //UINT32 Value = 0; + + pAd->monitor_ctrl.current_monitor_mode = simple_strtol(arg, 0, 10); + if(pAd->monitor_ctrl.current_monitor_mode > MONITOR_MODE_FULL || pAd->monitor_ctrl.current_monitor_mode < MONITOR_MODE_OFF) + pAd->monitor_ctrl.current_monitor_mode = MONITOR_MODE_OFF; + + DBGPRINT(RT_DEBUG_ERROR, + ("set Current Monitor Mode = %d , range(%d ~ %d)\n" + , pAd->monitor_ctrl.current_monitor_mode,MONITOR_MODE_OFF,MONITOR_MODE_FULL)); + + switch(pAd->monitor_ctrl.current_monitor_mode) + { + case MONITOR_MODE_OFF: //reset to normal + pAd->ApCfg.BssType = BSS_INFRA; + AsicClearRxFilter(pAd); + AsicSetRxFilter(pAd); + + break; + case MONITOR_MODE_REGULAR_RX: //report probe_request only , normal rx filter + pAd->ApCfg.BssType = BSS_MONITOR; + + /* ASIC supporsts sniffer function with replacing RSSI with timestamp. + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (0x80); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); */ + break; + + case MONITOR_MODE_FULL: //fully report, Enable Rx with promiscuous reception + pAd->ApCfg.BssType = BSS_MONITOR; + AsicSetRxFilter(pAd); + + /*RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &Value); + Value |= (0x80); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, Value); */ + break; + } + return TRUE; +} +#endif /* CONFIG_SNIFFER_SUPPORT */ + + +INT Set_VcoPeriod_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT16 Value; + + if(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Do NOT accept this command after interface is up.\n")); + return FALSE; + } + + Value = (UINT16)simple_strtol(arg, 0, 10); + pAd->CommonCfg.ModuleTxpower = Value; + DBGPRINT(RT_DEBUG_TRACE, ("IF Set_ModuleTxpower_Proc::(ModuleTxpower=%d)\n", pAd->CommonCfg.ModuleTxpower)); + return TRUE; +} +#endif /* SINGLE_SKU */ + + +#ifdef CONFIG_FPGA_MODE + +#ifdef CAPTURE_MODE +INT set_cap_dump(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG seg = simple_strtol(arg, 0, 10);; + CHAR *buf1, *buf2; + UINT32 offset = 0; + + seg = ((seg > 0 && seg <= 4) ? seg : 1); + if (pAd->fpga_ctl.cap_done == TRUE && (pAd->fpga_ctl.cap_buf != NULL)) { + switch (seg) + { + case 1: + offset = 0; + break; + case 2: + offset = 0x2000; + break; + case 3: + offset = 0x4000; + break; + case 4: + offset = 0x6000; + break; + } + cap_dump(pAd, + (pAd->fpga_ctl.cap_buf + offset), + (pAd->fpga_ctl.cap_buf + 0x8000 + offset), + 0x2000); + } + + return TRUE; +} + + +INT set_cap_start(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG cap_start; + BOOLEAN do_cap; + BOOLEAN cap_done; /* 1: capture done, 0: capture not finish yet */ + + + cap_start = simple_strtol(arg, 0, 10); + do_cap = cap_start == 1 ? TRUE : FALSE; + + if (!pAd->fpga_ctl.cap_support) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): cap mode is not support yet!\n", __FUNCTION__)); + return FALSE; + } + + if (do_cap) + { + /* + start to do cap, + if auto =>will triggered depends on trigger condition, + if manual =>start immediately + */ + if (pAd->fpga_ctl.do_cap == FALSE) + asic_cap_start(pAd); + else + { + DBGPRINT(RT_DEBUG_OFF, ("%s(): alreay in captureing\n", __FUNCTION__)); + } + } + else + { + + if (pAd->fpga_ctl.do_cap == TRUE) { + DBGPRINT(RT_DEBUG_OFF, ("%s(): force stop captureing\n", __FUNCTION__)); + // TODO: force stop capture! + asic_cap_stop(pAd); + } + else + { + + } + pAd->fpga_ctl.do_cap = FALSE; + } + return TRUE; +} + + +INT set_cap_trigger_offset(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG trigger_offset; /* in unit of us */ + + trigger_offset = simple_strtol(arg, 0, 10); + + pAd->fpga_ctl.trigger_offset = (UINT32)trigger_offset; + DBGPRINT(RT_DEBUG_OFF, ("%s():set trigger_offset=%d\n", + __FUNCTION__, pAd->fpga_ctl.trigger_offset)); + + return TRUE; +} + + + +INT set_cap_trigger(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG trigger; /* 1: manual trigger, 2: auto trigger */ + + + trigger = simple_strtol(arg, 0, 10); + pAd->fpga_ctl.cap_trigger = trigger <= 2 ? trigger : 0; + DBGPRINT(RT_DEBUG_OFF, ("%s():set cap_trigger=%s trigger\n", __FUNCTION__, + (pAd->fpga_ctl.cap_trigger == 0 ? "Invalid" : + (pAd->fpga_ctl.cap_trigger == 1 ? "Manual" : "Auto")))); + + return TRUE; +} + + +INT set_cap_type(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG cap_type; /* 1: ADC6, 2: ADC8, 3: FEQ */ + + cap_type = simple_strtol(arg, 0, 10); + + pAd->fpga_ctl.cap_type = cap_type <= 3 ? cap_type : 0; + DBGPRINT(RT_DEBUG_OFF, ("%s():set cap_type=%s\n", + __FUNCTION__, + pAd->fpga_ctl.cap_type == 1 ? "ADC6" :\ + (pAd->fpga_ctl.cap_type == 2 ? "ADC8" : "FEQ"))); + + return TRUE; +} + + +INT set_cap_support(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR cap_support; /* 0: no cap mode; 1: cap mode enable */ + + cap_support = simple_strtol(arg, 0, 10); + pAd->fpga_ctl.cap_support = (cap_support == 1 ? TRUE : FALSE); + + DBGPRINT(RT_DEBUG_OFF, ("%s():set cap_support=%s\n", + __FUNCTION__, + (pAd->fpga_ctl.cap_support == TRUE ? "TRUE" : "FALSE"))); + + return TRUE; +} +#endif /* CAPTURE_MODE */ + + +INT set_vco_cal(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR vco_cal; + + vco_cal = simple_strtol(arg, 0, 10); + pAd->fpga_ctl.vco_cal = vco_cal ? TRUE : FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("%s(): vco_cal=%s\n", + __FUNCTION__, (pAd->fpga_ctl.vco_cal ? "Enabled" : "Stopped"))); + + return TRUE; + +} + +INT set_tr_stop(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR stop; + + stop = simple_strtol(arg, 0, 10); + pAd->fpga_ctl.fpga_tr_stop = (stop <= 4 ? stop : 0); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): fpga_tr_stop=0x%x\n", __FUNCTION__, pAd->fpga_ctl.fpga_tr_stop)); + + return TRUE; +} + + +INT set_tx_kickcnt(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->fpga_ctl.tx_kick_cnt = (INT)simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s():tx_kick_cnt=%d\n", __FUNCTION__, pAd->fpga_ctl.tx_kick_cnt)); + + return TRUE; +} + + +INT set_data_phy_mode(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->fpga_ctl.tx_data_phy = (INT)simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): tx_data_phy=%d\n", __FUNCTION__, pAd->fpga_ctl.tx_data_phy)); + + return TRUE; +} + + +INT set_data_bw(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->fpga_ctl.tx_data_bw = (UCHAR)simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): tx_data_bw=%d\n", __FUNCTION__, pAd->fpga_ctl.tx_data_bw)); + + return TRUE; +} + + +INT set_data_mcs(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR mcs = (UCHAR)simple_strtol(arg, 0, 10); + + pAd->fpga_ctl.tx_data_mcs = mcs; + DBGPRINT(RT_DEBUG_TRACE, ("%s(): tx_data_mcs=%d\n", __FUNCTION__, pAd->fpga_ctl.tx_data_mcs)); + + return TRUE; +} + +INT set_data_ldpc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->fpga_ctl.tx_data_ldpc = (UCHAR)simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): tx_data_ldpc=%d\n", __FUNCTION__, pAd->fpga_ctl.tx_data_ldpc)); + + return TRUE; +} + +INT set_data_gi(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->fpga_ctl.tx_data_gi = (UCHAR)simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): tx_data_gi=%d\n", __FUNCTION__, pAd->fpga_ctl.tx_data_gi)); + + return TRUE; +} + + +INT set_data_basize(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->fpga_ctl.data_basize = (UCHAR)simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): data_basize=%d\n", __FUNCTION__, pAd->fpga_ctl.data_basize)); + + return TRUE; +} + + +#ifdef MT_MAC +INT set_txs_report_type(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + MT_MAC_TXS_TYPE txs_mode = TXS_NONE; + + if (arg && strlen(arg)) { + if (strstr(arg, "data") != NULL) + txs_mode |= TXS_DATA; + + if (strstr(arg, "qdata") != NULL) + txs_mode |= TXS_QDATA; + + if (strstr(arg, "noqdata") != NULL) + txs_mode |= TXS_NON_QDATA; + + if (strstr(arg, "mgmt") != NULL) + txs_mode |= TXS_MGMT; + if (strstr(arg, "bcn") != NULL) + txs_mode |= TXS_BCN; + + if (strstr(arg, "mgmt_other") != NULL) + txs_mode |= TXS_MGMT_OTHER; + + if (strstr(arg, "ctrl") != NULL) + txs_mode |= TXS_CTRL; + + if (strstr(arg, "all") != NULL) + txs_mode |= TXS_ALL; + } + + pAd->fpga_ctl.txs_type = txs_mode; + DBGPRINT(RT_DEBUG_OFF, ("%s(): Set TXS Report type as: 0x%x\n", + __FUNCTION__, pAd->fpga_ctl.txs_type)); + + return TRUE; +} + + +INT set_no_bcn(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG no_bcn; + + no_bcn = simple_strtol(arg, 0, 10); + pAd->fpga_ctl.no_bcn = (no_bcn ? 1 : 0); + DBGPRINT(RT_DEBUG_OFF, ("%s(): Set no beacon as:%d\n", + __FUNCTION__, pAd->fpga_ctl.no_bcn)); + + return TRUE; +} +#endif /* MT_MAC */ + + +INT set_fpga_mode(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG fpga_on; +#ifdef CONFIG_AP_SUPPORT + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[0].wdev; +#endif /* CONFIG_AP_SUPPORT */ + + fpga_on = simple_strtol(arg, 0, 10); + + if (fpga_on & 2) + pAd->fpga_ctl.tx_data_mcs = 7; + + if (fpga_on & 4) + pAd->fpga_ctl.tx_data_mcs = (1 << 4) | 7; + +#ifdef CONFIG_AP_SUPPORT + if (fpga_on & 0x6) { + pAd->fpga_ctl.tx_data_phy = MODE_VHT; + pAd->fpga_ctl.tx_data_ldpc = 0; + pAd->fpga_ctl.tx_data_bw = BW_80; + pAd->fpga_ctl.tx_data_gi = 1; + pAd->fpga_ctl.data_basize = 31; + wdev->bAutoTxRateSwitch = FALSE; + } + else + { + wdev->bAutoTxRateSwitch = TRUE; + } +#endif /* CONFIG_AP_SUPPORT */ + + pAd->fpga_ctl.fpga_on = fpga_on; + DBGPRINT(RT_DEBUG_TRACE, ("%s(): fpga_on=%d\n", __FUNCTION__, pAd->fpga_ctl.fpga_on)); + DBGPRINT(RT_DEBUG_TRACE, ("\tdata_phy=%d\n", pAd->fpga_ctl.tx_data_phy)); + DBGPRINT(RT_DEBUG_TRACE, ("\tdata_bw=%d\n", pAd->fpga_ctl.tx_data_bw)); + DBGPRINT(RT_DEBUG_TRACE, ("\tdata_mcs=%d\n", pAd->fpga_ctl.tx_data_mcs)); + DBGPRINT(RT_DEBUG_TRACE, ("\tdata_gi=%d\n", pAd->fpga_ctl.tx_data_gi)); + DBGPRINT(RT_DEBUG_TRACE, ("\tdata_basize=%d\n", pAd->fpga_ctl.data_basize)); + +#ifdef CONFIG_AP_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("\tbAutoTxRateSwitch=%d\n", + wdev->bAutoTxRateSwitch)); +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} +#endif /* CONFIG_FPGA_MODE */ + + +#if defined(WFA_VHT_PF) || defined(MT7603_FPGA) || defined(MT7628_FPGA) +INT set_force_amsdu(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->force_amsdu = (simple_strtol(arg, 0, 10) > 0 ? TRUE : FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): force_amsdu=%d\n", + __FUNCTION__, pAd->force_amsdu)); + return TRUE; +} +#endif /* defined(WFA_VHT_PF) || defined(MT7603_FPGA) */ + + +#ifdef WFA_VHT_PF +INT set_vht_nss_mcs_cap(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + CHAR *token, sep[2] = {':', '-'}; + UCHAR val[3] = {0}, ss, mcs_l, mcs_h, mcs_cap, status = FALSE; + INT idx = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():intput string=%s\n", __FUNCTION__, arg)); + ss = mcs_l = mcs_h = 0; + + while (arg) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s():intput string[len=%d]=%s\n", __FUNCTION__, strlen(arg), arg)); + if (idx < 2) { + token = rtstrchr(arg, sep[idx]); + if (!token) { + DBGPRINT(RT_DEBUG_TRACE, ("cannot found token '%c' in string \"%s\"!\n", sep[idx], arg)); + return FALSE; + } + *token++ = 0; + } else + token = NULL; + + if (strlen(arg)) { + val[idx] = (UCHAR)simple_strtoul(arg, NULL, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s():token string[len=%d]=%s, val[%d]=%d\n", + __FUNCTION__, strlen(arg), arg, idx, val[idx])); + idx++; + } + arg = token; + if (idx == 3) + break; + } + + if (idx <3) + return FALSE; + + ss = val[0]; + mcs_l = val[1]; + mcs_h = val[2]; + DBGPRINT(RT_DEBUG_TRACE, ("ss=%d, mcs_l=%d, mcs_h=%d\n", ss, mcs_l, mcs_h)); + if (ss && mcs_h) + { + if (ss <= pAd->chipCap.max_nss) + pAd->CommonCfg.vht_nss_cap = ss; + else + pAd->CommonCfg.vht_nss_cap = pAd->chipCap.max_nss; + + switch (mcs_h) + { + case 7: + mcs_cap = VHT_MCS_CAP_7; + break; + case 8: + mcs_cap = VHT_MCS_CAP_8; + break; + case 9: + mcs_cap = VHT_MCS_CAP_9; + break; + default: + mcs_cap = VHT_MCS_CAP_9; + break; + } + + if (mcs_h <= pAd->chipCap.max_vht_mcs) + pAd->CommonCfg.vht_mcs_cap = mcs_cap; + else + pAd->CommonCfg.vht_mcs_cap = pAd->chipCap.max_vht_mcs; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():ss=%d, mcs_cap=%d, vht_nss_cap=%d, vht_mcs_cap=%d\n", + __FUNCTION__, ss, mcs_cap, + pAd->CommonCfg.vht_nss_cap, + pAd->CommonCfg.vht_mcs_cap)); + status = TRUE; + } + + return status; +} + + +INT set_vht_nss_mcs_opt(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + + + DBGPRINT(RT_DEBUG_TRACE, ("%s():intput string=%s\n", __FUNCTION__, arg)); + + return Set_HtMcs_Proc(pAd, arg); +} + + +INT set_vht_opmode_notify_ie(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + CHAR *token; + UINT ss, bw; + BOOLEAN status = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():intput string=%s\n", __FUNCTION__, arg)); + token = rtstrchr(arg, ':'); + if (!token) + return FALSE; + + *token = 0; + token++; + if (strlen(arg) && strlen(token)) + { + ss = simple_strtoul(arg, NULL, 10); + bw = simple_strtoul(token, NULL, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("%s():ss=%d, bw=%d\n", __FUNCTION__, ss, bw)); + if (ss > 0 && ss <= 2) + pAd->vht_pf_op_ss = ss; + else + pAd->vht_pf_op_ss = pAd->Antenna.field.RxPath; + + switch (bw) { + case 20: + pAd->vht_pf_op_bw = BAND_WIDTH_20; + break; + case 40: + pAd->vht_pf_op_bw = BAND_WIDTH_40; + break; + case 80: + default: + pAd->vht_pf_op_bw = BAND_WIDTH_80; + break; + } + status = TRUE; + } + + pAd->force_vht_op_mode = status; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():force_vht_op_mode=%d, vht_pf_op_ss=%d, vht_pf_op_bw=%d\n", + __FUNCTION__, pAd->force_vht_op_mode, pAd->vht_pf_op_ss, pAd->vht_pf_op_bw)); + + return status; +} + + +INT set_force_operating_mode(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->force_vht_op_mode = (simple_strtol(arg, 0, 10) > 0 ? TRUE : FALSE); + + if (pAd->force_vht_op_mode == TRUE) { + pAd->vht_pf_op_ss = 1; // 1SS + pAd->vht_pf_op_bw = BAND_WIDTH_20; // 20M + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): force_operating_mode=%d\n", + __FUNCTION__, pAd->force_vht_op_mode)); + if (pAd->force_vht_op_mode == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("\tforce_operating_mode as %dSS in 20MHz BW\n", + pAd->vht_pf_op_ss)); + } + + return TRUE; +} + + +INT set_force_noack(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->force_noack = (simple_strtol(arg, 0, 10) > 0 ? TRUE : FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): force_noack=%d\n", + __FUNCTION__, pAd->force_noack)); + + return TRUE; +} + + +INT set_force_vht_sgi(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->vht_force_sgi = (simple_strtol(arg, 0, 10) > 0 ? TRUE : FALSE); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): vht_force_sgi=%d\n", + __FUNCTION__, pAd->vht_force_sgi)); + + return TRUE; +} + + +INT set_force_vht_tx_stbc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + pAd->vht_force_tx_stbc = (simple_strtol(arg, 0, 10) > 0 ? TRUE : FALSE); + if (pAd->CommonCfg.TxStream < 2) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): TxStream=%d is not enough for TxSTBC!\n", + __FUNCTION__, pAd->CommonCfg.TxStream)); + pAd->vht_force_tx_stbc = 0; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s(): vht_force_tx_stbc=%d\n", + __FUNCTION__, pAd->vht_force_tx_stbc)); + + return TRUE; +} + + +INT set_force_ext_cca(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG cca_cfg; + UINT32 mac_val; + + cca_cfg = (simple_strtol(arg, 0, 10) > 0 ? TRUE : FALSE); + if (cca_cfg) + mac_val = 0x04101b3f; + else + mac_val = 0x583f; + RTMP_IO_WRITE32(pAd, TXOP_CTRL_CFG, mac_val); + + return TRUE; +} +#endif /* WFA_VHT_PF */ + + +#ifdef DOT11_N_SUPPORT + +#define MAX_AGG_CNT 8 + +/* DisplayTxAgg - display Aggregation statistics from MAC */ +void DisplayTxAgg (RTMP_ADAPTER *pAd) +{ + ULONG totalCount; + ULONG aggCnt[MAX_AGG_CNT + 2]; + int i; + + AsicReadAggCnt(pAd, aggCnt, sizeof(aggCnt) / sizeof(ULONG)); + totalCount = aggCnt[0] + aggCnt[1]; + if (totalCount > 0) + for (i=0; ichipCap.rf_type == RF_RLT) + Ret = SetRltRF(pAd, Arg); +#endif + + +#ifdef MT_MAC + if (pAd->chipCap.rf_type == RF_MT) + Ret = SetMTRF(pAd, Arg); +#endif + + return Ret; +} + + +static struct { + RTMP_STRING *name; + INT (*show_proc)(RTMP_ADAPTER *pAd, RTMP_STRING *arg, ULONG BufLen); +} *PRTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC, RTMP_PRIVATE_STA_SHOW_CFG_VALUE_PROC[] = { +#ifdef DBG + {"SSID", Show_SSID_Proc}, + {"WirelessMode", Show_WirelessMode_Proc}, + {"TxBurst", Show_TxBurst_Proc}, + {"TxPreamble", Show_TxPreamble_Proc}, + {"TxPower", Show_TxPower_Proc}, + {"Channel", Show_Channel_Proc}, + {"BGProtection", Show_BGProtection_Proc}, + {"RTSThreshold", Show_RTSThreshold_Proc}, + {"FragThreshold", Show_FragThreshold_Proc}, +#ifdef DOT11_N_SUPPORT + {"HtBw", Show_HtBw_Proc}, + {"HtMcs", Show_HtMcs_Proc}, + {"HtGi", Show_HtGi_Proc}, + {"HtOpMode", Show_HtOpMode_Proc}, + {"HtExtcha", Show_HtExtcha_Proc}, + {"HtMpduDensity", Show_HtMpduDensity_Proc}, + {"HtBaWinSize", Show_HtBaWinSize_Proc}, + {"HtRdg", Show_HtRdg_Proc}, + {"HtAmsdu", Show_HtAmsdu_Proc}, + {"HtAutoBa", Show_HtAutoBa_Proc}, +#endif /* DOT11_N_SUPPORT */ + {"CountryRegion", Show_CountryRegion_Proc}, + {"CountryRegionABand", Show_CountryRegionABand_Proc}, + {"CountryCode", Show_CountryCode_Proc}, +#ifdef AGGREGATION_SUPPORT + {"PktAggregate", Show_PktAggregate_Proc}, +#endif + + {"WmmCapable", Show_WmmCapable_Proc}, + + {"IEEE80211H", Show_IEEE80211H_Proc}, + {"AuthMode", Show_AuthMode_Proc}, + {"EncrypType", Show_EncrypType_Proc}, + {"DefaultKeyID", Show_DefaultKeyID_Proc}, + {"Key1", Show_Key1_Proc}, + {"Key2", Show_Key2_Proc}, + {"Key3", Show_Key3_Proc}, + {"Key4", Show_Key4_Proc}, + {"PMK", Show_PMK_Proc}, +#ifdef SINGLE_SKU + {"ModuleTxpower", Show_ModuleTxpower_Proc}, +#endif /* SINGLE_SKU */ +#endif /* DBG */ + {"rainfo", Show_STA_RAInfo_Proc}, + {NULL, NULL} +}; + + +INT RTMPShowCfgValue( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *pName, + IN RTMP_STRING *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; +} + + + +#ifdef DBG +INT show_pwr_info(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + if (pAd->chipOps.show_pwr_info) { + pAd->chipOps.show_pwr_info(pAd); + } + + return 0; +} + + +INT32 ShowBBPInfo(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + ShowAllBBP(pAd); + + return TRUE; +} + + +INT32 ShowRFInfo(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + + ShowAllRF(pAd); + + return 0; +} +#endif /* DBG */ + +#ifdef SMART_CARRIER_SENSE_SUPPORT +INT32 ShowSCSInfo(RTMP_ADAPTER *pAd, RTMP_STRING *Arg) +{ + printk("========Configuration==========\n"); + printk("SCS enable =%d \n", pAd->SCSCtrl.SCSEnable); + printk("MinRssi Tolerance=%d \n", pAd->SCSCtrl.SCSMinRssiTolerance); + printk("FixedRssiBoundary=%d \n", pAd->SCSCtrl.FixedRssiBond); + printk("False CCA up boundayr =%d \n", pAd->SCSCtrl.FalseCcaUpBond); + printk("False CCA low boundayr =%d \n", pAd->SCSCtrl.FalseCcaLowBond); + printk("Traffic threshold =%d \n", pAd->SCSCtrl.SCSTrafficThreshold); + printk("ForceMode = %d \n", pAd->SCSCtrl.ForceMode); + printk("========Statistic /Status==========\n"); + printk("Min RSSI=%d \n", pAd->SCSCtrl.SCSMinRssi); + printk("PD count=%x \n", pAd->SCSCtrl.PdCount); + printk("MDRDY count=%x \n", pAd->SCSCtrl.MdrdyCount); + printk("FalseCCA count=%d \n", pAd->SCSCtrl.FalseCCA); + printk("Current RSSI boundary =%d \n", pAd->SCSCtrl.RSSIBoundary); + printk("RTS count =%d \n", pAd->SCSCtrl.RtsCount); + printk("RTS retry count =%d \n", pAd->SCSCtrl.RtsRtyCount); + printk("Tx Traffic = %d \n", pAd->RalinkCounters.OneSecTransmittedByteCount); + printk("Rx Traffic = %d \n", pAd->RalinkCounters.OneSecReceivedByteCount); + printk("Current Sensitivity = %d \n", pAd->SCSCtrl.CurrSensitivity); + printk("Adjust Sensitivity = %d \n", pAd->SCSCtrl.AdjustSensitivity); + + return TRUE; +} +#endif /* SMART_CARRIER_SENSE_SUPPORT */ + +#ifdef NEW_IXIA_METHOD +UCHAR force_connect = 0xF; +INT force_connect_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + int dbg; + + dbg = (int)simple_strtol(arg, 0, 10); + force_connect = (UCHAR)dbg; + DBGPRINT_S(("<==%s(force_connect = %d)\n", __func__, force_connect)); + return TRUE; +} + +INT Set_chkT_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + int dbg; + + DBGPRINT_S(("==>%s()\n", __func__)); + dbg = (int)simple_strtol(arg, 0, 10); + pAd->chkTmr = dbg; + DBGPRINT_S(("<==%s(pAd->chkTmr = %d)\n", __func__, pAd->chkTmr)); + return TRUE; +} +INT Set_pkt_threshld_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + int dbg; + + DBGPRINT_S(("==>%s()\n", __func__)); + dbg = (int)simple_strtol(arg, 0, 10); + pAd->pktthld = dbg; + if (dbg == 0) { + dectlen_l = 8; + dectlen_m = 8; + dectlen_h = 8; + } else { + dectlen_l = 88; + dectlen_m = 512; + dectlen_h = 1518; + } + DBGPRINT_S(("<==%s(pAd->pktthld = %d)\n", __func__, pAd->pktthld)); + return TRUE; +} + +unsigned short dectlen_l = 88; +unsigned short dectlen_m = 512; +unsigned short dectlen_h = 1518; +INT Set_statistic_pktlen_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + int d1, d2, d3; + + DBGPRINT_S(("==>%s Before(dectlen_l: %d, dectlen_m: %d, dectlen_h: %d)\n", + __func__, dectlen_l, dectlen_m, dectlen_h)); + sscanf(arg, "%d-%d-%d", &d1, &d2, &d3); + dectlen_l = (unsigned short)d1; + dectlen_m = (unsigned short)d2; + dectlen_h = (unsigned short)d3; + DBGPRINT_S(("<==%s After(dectlen_l: %d, dectlen_m: %d, dectlen_h: %d)\n", + __func__, dectlen_l, dectlen_m, dectlen_h)); + return TRUE; +} + + +INT set_Protection_Parameter_Set_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 valrts, valcts, value; + UINT32 command; + + command = (UINT32)simple_strtol(arg, 0, 10); + pAd->CommonCfg.bHTProtect = FALSE; /*disable Protect detect*/ + /*RTS CR*/ + RTMP_IO_READ32(pAd, AGG_PCR1, &valrts); + /*CTS2SELF CR*/ + RTMP_IO_READ32(pAd, AGG_PCR, &valcts); + /*RTS&&CTS FixRate CR*/ + RTMP_IO_READ32(pAd, TMAC_PCR, &value); + switch (command) { + case 1:/*disable RTS && CTS2CELF*/ + { + valrts &= ~RTS_THRESHOLD_MASK; + valrts &= ~RTS_PKT_NUM_THRESHOLD_MASK; + valrts |= RTS_THRESHOLD(0xFFFFF); + valrts |= RTS_PKT_NUM_THRESHOLD(0x7F); + valcts &= ~ERP_PROTECTION_MASK; + valcts &= (0x00080000); + pAd->protectpara |= 0x1; + break; + } + case 2:/*disable RTS , enable CTS2SELF*/ + { + valrts &= ~RTS_THRESHOLD_MASK; + valrts &= ~RTS_PKT_NUM_THRESHOLD_MASK; + valrts |= RTS_THRESHOLD(0xFFFFF); + valrts |= RTS_PKT_NUM_THRESHOLD(0x7F); + valcts &= ~ERP_PROTECTION_MASK; + valcts |= ERP_PROTECTION_MASK; + valcts |= (0x001b0000); + pAd->protectpara |= 0x1; + break; + } + case 3:/*enable RTS , disable CTS2SELF*/ + { + valrts &= ~RTS_THRESHOLD_MASK; + valrts &= ~RTS_PKT_NUM_THRESHOLD_MASK; + valrts |= RTS_THRESHOLD(pAd->CommonCfg.RtsThreshold); + valrts |= RTS_PKT_NUM_THRESHOLD(1); + valcts &= ~ERP_PROTECTION_MASK; + valcts &= (0x00080000); + pAd->protectpara &= ~0x1; + break; + } + case 4:/*keep CCK rate always 100Percentage*/ + pAd->protectpara |= 0x2; + break; + case 5:/*Fix RTS/CTS CCK 1M rate.*/ + value &= ~PTEC_FIX_RATE_MASK; + value &= ~PTEC_RATE_SEL; + break; + case 6: + value |= PTEC_RATE_SEL;/*Protect auto rate*/ + break; + default: + { + pAd->CommonCfg.bHTProtect = TRUE;/*Auto Protect detect*/ + pAd->protectpara = 0; + break; + } + } + RTMP_IO_WRITE32(pAd, AGG_PCR1, valrts); + RTMP_IO_WRITE32(pAd, AGG_PCR, valcts); + RTMP_IO_WRITE32(pAd, TMAC_PCR, value); + DBGPRINT(RT_DEBUG_OFF, ("[%d]:para(0x%x), HtProt(%d), 21254(0x%x), 21250(0x%x), 212b4(0x%x)\n", + command, pAd->protectpara, pAd->CommonCfg.bHTProtect, valrts, valcts, value)); + return TRUE; +} +#endif + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_loft_cal.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_loft_cal.c new file mode 100644 index 000000000..a948dca7d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_loft_cal.c @@ -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: + cmm_loft_cal.c + + Abstract: + Tx LOFT calibration and profile related functions + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + +*/ + +#include "rt_config.h" + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mac_pci.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mac_pci.c new file mode 100644 index 000000000..82db49fa1 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mac_pci.c @@ -0,0 +1,3274 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + + + +#ifdef RTMP_MAC_PCI +#include "rt_config.h" + + +static INT desc_ring_alloc(RTMP_ADAPTER *pAd, RTMP_DMABUF *pDescRing, INT size) +{ + VOID *pci_dev = ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev; + + pDescRing->AllocSize = size; + RtmpAllocDescBuf(pci_dev, + 0, + pDescRing->AllocSize, + FALSE, + &pDescRing->AllocVa, + &pDescRing->AllocPa); + + if (pDescRing->AllocVa == NULL) + { + DBGPRINT_ERR(("Failed to allocate a big buffer\n")); + return ERRLOG_OUT_OF_SHARED_MEMORY; + } + + /* Zero init this memory block*/ + NdisZeroMemory(pDescRing->AllocVa, size); + + return 0; +} + + +static INT desc_ring_free(RTMP_ADAPTER *pAd, RTMP_DMABUF *pDescRing) +{ + VOID *pci_dev = ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev; + + if (pDescRing->AllocVa) + { + RtmpFreeDescBuf(pci_dev, + pDescRing->AllocSize, + pDescRing->AllocVa, + pDescRing->AllocPa); + } + NdisZeroMemory(pDescRing, sizeof(RTMP_DMABUF)); + + return TRUE; +} + + +#ifdef RESOURCE_PRE_ALLOC +VOID RTMPResetTxRxRingMemory(RTMP_ADAPTER *pAd) +{ + int index, j; + RTMP_TX_RING *pTxRing; + TXD_STRUC *pTxD; + RTMP_DMACB *dma_cb; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR tx_hw_info[TXD_SIZE]; +#endif /* RT_BIG_ENDIAN */ + PNDIS_PACKET pPacket; + + rtmp_tx_swq_exit(pAd, WCID_ALL); + + /* Free Tx Ring Packet*/ + for (index=0;index< NUM_OF_TX_RING;index++) + { + pTxRing = &pAd->TxRing[index]; + for (j=0; j< TX_RING_SIZE; j++) + { + dma_cb = &pTxRing->Cell[j]; +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *)(dma_cb->AllocVa); + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_STRUC *) (dma_cb->AllocVa); +#endif /* RT_BIG_ENDIAN */ + pPacket = dma_cb->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*/ + dma_cb->pNdisPacket = NULL; + + pPacket = dma_cb->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*/ + dma_cb->pNextNdisPacket = NULL; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + } + } + +#ifdef CONFIG_ANDES_SUPPORT + { + RTMP_CTRL_RING *pCtrlRing = &pAd->CtrlRing; + + RTMP_IO_READ32(pAd, pCtrlRing->hw_didx_addr, &pCtrlRing->TxDmaIdx); + + while (pCtrlRing->TxSwFreeIdx!= pCtrlRing->TxCpuIdx) + { +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *) (pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx].AllocVa); + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_STRUC *) (pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx].AllocVa); +#endif + pTxD->DMADONE = 0; + pPacket = pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx].pNdisPacket; + + if (pPacket == NULL) + { + INC_RING_INDEX(pCtrlRing->TxSwFreeIdx, MGMT_RING_SIZE); + continue; + } + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx].pNdisPacket = NULL; + + pPacket = pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx].pNextNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx].pNextNdisPacket = NULL; + INC_RING_INDEX(pCtrlRing->TxSwFreeIdx, MGMT_RING_SIZE); + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD); +#endif + } + } +#endif /* CONFIG_ANDES_SUPPORT */ + +#ifdef MT_MAC + if (1 /*pAd->chipCap.hif_type == HIF_MT*/) + { + RTMP_BCN_RING *pBcnRing = &pAd->BcnRing; + + RTMP_IO_READ32(pAd, pBcnRing->hw_didx_addr, &pBcnRing->TxDmaIdx); + + while (pBcnRing->TxSwFreeIdx!= pBcnRing->TxDmaIdx) + { +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *) (pBcnRing->Cell[pBcnRing->TxSwFreeIdx].AllocVa); + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_STRUC *) (pBcnRing->Cell[pBcnRing->TxSwFreeIdx].AllocVa); +#endif + pTxD->DMADONE = 0; + pPacket = pBcnRing->Cell[pBcnRing->TxSwFreeIdx].pNdisPacket; + + if (pPacket == NULL) + { + INC_RING_INDEX(pBcnRing->TxSwFreeIdx, BCN_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); + } + pBcnRing->Cell[pBcnRing->TxSwFreeIdx].pNdisPacket = NULL; + + pPacket = pBcnRing->Cell[pBcnRing->TxSwFreeIdx].pNextNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + pBcnRing->Cell[pBcnRing->TxSwFreeIdx].pNextNdisPacket = NULL; + INC_RING_INDEX(pBcnRing->TxSwFreeIdx, BCN_RING_SIZE); + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD); +#endif + } + } +#endif /* MT_MAC */ + + for (index=0;index< NUM_OF_RX_RING;index++) + { + for (j = RX_RING_SIZE - 1 ; j >= 0; j--) + { + dma_cb = &pAd->RxRing[index].Cell[j]; + if ((dma_cb->DmaBuf.AllocVa) && (dma_cb->pNdisPacket)) + { + PCI_UNMAP_SINGLE(pAd, dma_cb->DmaBuf.AllocPa, dma_cb->DmaBuf.AllocSize, RTMP_PCI_DMA_FROMDEVICE); + RELEASE_NDIS_PACKET(pAd, dma_cb->pNdisPacket, NDIS_STATUS_SUCCESS); + } + } + NdisZeroMemory(pAd->RxRing[index].Cell, RX_RING_SIZE * sizeof(RTMP_DMACB)); + } + + if (pAd->FragFrame.pFragPacket) + { + RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS); + pAd->FragFrame.pFragPacket = NULL; + } + + NdisFreeSpinLock(&pAd->CmdQLock); +} + + +VOID RTMPFreeTxRxRingMemory(RTMP_ADAPTER *pAd) +{ + INT num; + VOID *pci_dev = ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev; + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n")); + + + /* Free Rx/Mgmt Desc buffer*/ + for (num = 0; num < NUM_OF_RX_RING; num++) + desc_ring_free(pAd, &pAd->RxDescRing[num]); + + desc_ring_free(pAd, &pAd->MgmtDescRing); +#ifdef CONFIG_ANDES_SUPPORT + desc_ring_free(pAd, &pAd->CtrlDescRing); +#endif /* CONFIG_ANDES_SUPPORT */ + +#ifdef MT_MAC + desc_ring_free(pAd, &pAd->BcnDescRing); + + if (pAd->TxBmcBufSpace.AllocVa) + { + RTMP_FreeFirstTxBuffer(pci_dev, + pAd->TxBmcBufSpace.AllocSize, + FALSE, pAd->TxBmcBufSpace.AllocVa, + pAd->TxBmcBufSpace.AllocPa); + } + NdisZeroMemory(&pAd->TxBmcBufSpace, sizeof(RTMP_DMABUF)); + + desc_ring_free(pAd, &pAd->TxBmcDescRing); +#endif /* MT_MAC */ + + /* Free 1st TxBufSpace and TxDesc buffer*/ + for (num = 0; num < NUM_OF_TX_RING; num++) + { + if (pAd->TxBufSpace[num].AllocVa) + { + RTMP_FreeFirstTxBuffer(pci_dev, + pAd->TxBufSpace[num].AllocSize, + FALSE, pAd->TxBufSpace[num].AllocVa, + pAd->TxBufSpace[num].AllocPa); + } + NdisZeroMemory(&pAd->TxBufSpace[num], sizeof(RTMP_DMABUF)); + + desc_ring_free(pAd, &pAd->TxDescRing[num]); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n")); +} + + +NDIS_STATUS RTMPInitTxRxRingMemory(RTMP_ADAPTER *pAd) +{ + INT num, index; + ULONG /*RingBasePaHigh,*/ RingBasePaLow; + VOID *RingBaseVa; + RTMP_TX_RING *pTxRing; + RTMP_RX_RING *pRxRing; + RTMP_DMABUF *pDmaBuf, *pDescRing; + RTMP_DMACB *dma_cb; + PNDIS_PACKET pPacket; + TXD_STRUC *pTxD; + RXD_STRUC *pRxD; + //ULONG ErrorValue = 0; + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + + /* Init the CmdQ and CmdQLock*/ + NdisAllocateSpinLock(pAd, &pAd->CmdQLock); + NdisAcquireSpinLock(&pAd->CmdQLock); + RTInitializeCmdQ(&pAd->CmdQ); + NdisReleaseSpinLock(&pAd->CmdQLock); + + /* Initialize All Tx Ring Descriptors and associated buffer memory*/ + /* (5 TX rings = 4 ACs + 1 HCCA)*/ + for (num = 0; num < NUM_OF_TX_RING; num++) + { + ULONG /*BufBasePaHigh,*/ BufBasePaLow; + VOID *BufBaseVa; + + /* memory zero the Tx ring descriptor's memory */ + pDescRing = &pAd->TxDescRing[num]; + NdisZeroMemory(pDescRing->AllocVa, pDescRing->AllocSize); + /* Save PA & VA for further operation*/ + //RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pDescRing->AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pDescRing->AllocPa); + RingBaseVa = pDescRing->AllocVa; + + /* Zero init all 1st TXBuf's memory for this TxRing*/ + NdisZeroMemory(pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocSize); + /* Save PA & VA for further operation */ + //BufBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxBufSpace[num].AllocPa); + BufBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxBufSpace[num].AllocPa); + BufBaseVa = pAd->TxBufSpace[num].AllocVa; + + /* linking Tx Ring Descriptor and associated buffer memory */ + pTxRing = &pAd->TxRing[num]; + for (index = 0; index < TX_RING_SIZE; index++) + { + dma_cb = &pTxRing->Cell[index]; + dma_cb->pNdisPacket = NULL; + dma_cb->pNextNdisPacket = NULL; + /* Init Tx Ring Size, Va, Pa variables*/ + dma_cb->AllocSize = TXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, 0/*RingBasePaHigh*/); + RTMP_SetPhysicalAddressLow (dma_cb->AllocPa, RingBasePaLow); + + /* Setup Tx Buffer size & address. only 802.11 header will store in this space */ + pDmaBuf = &dma_cb->DmaBuf; + pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE; + pDmaBuf->AllocVa = BufBaseVa; + RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa,0 /*BufBasePaHigh*/); + RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, BufBasePaLow); + + /* link the pre-allocated TxBuf to TXD */ + pTxD = (TXD_STRUC *)dma_cb->AllocVa; + pTxD->SDPtr0 = BufBasePaLow; + /* advance to next ring descriptor address */ + pTxD->DMADONE = 1; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxD, dma_cb->AllocSize); + + RingBasePaLow += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + /* advance to next TxBuf address */ + BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE; + BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE; + } + DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d entry initialized\n", num, index)); + } + + /* Initialize MGMT Ring and associated buffer memory */ + pDescRing = &pAd->MgmtDescRing; + //RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pDescRing->AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pDescRing->AllocPa); + RingBaseVa = pDescRing->AllocVa; + NdisZeroMemory(pDescRing->AllocVa, pDescRing->AllocSize); + for (index = 0; index < MGMT_RING_SIZE; index++) + { + dma_cb = &pAd->MgmtRing.Cell[index]; + dma_cb->pNdisPacket = NULL; + dma_cb->pNextNdisPacket = NULL; + /* Init MGMT Ring Size, Va, Pa variables */ + dma_cb->AllocSize = TXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, 0/*RingBasePaHigh*/); + RTMP_SetPhysicalAddressLow (dma_cb->AllocPa, RingBasePaLow); + + /* Offset to next ring descriptor address */ + RingBasePaLow += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + /* link the pre-allocated TxBuf to TXD */ + pTxD = (TXD_STRUC *)dma_cb->AllocVa; + pTxD->DMADONE = 1; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxD, dma_cb->AllocSize); + + /* no pre-allocated buffer required in MgmtRing for scatter-gather case */ + } + +#ifdef CONFIG_ANDES_SUPPORT + /* Initialize CTRL Ring and associated buffer memory */ + pDescRing = &pAd->CtrlDescRing; + //RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pDescRing->AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pDescRing->AllocPa); + RingBaseVa = pDescRing->AllocVa; + NdisZeroMemory(pDescRing->AllocVa, pDescRing->AllocSize); + for (index = 0; index < MGMT_RING_SIZE; index++) + { + dma_cb = &pAd->CtrlRing.Cell[index]; + dma_cb->pNdisPacket = NULL; + dma_cb->pNextNdisPacket = NULL; + /* Init Ctrl Ring Size, Va, Pa variables */ + dma_cb->AllocSize = TXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, 0/*RingBasePaHigh*/); + RTMP_SetPhysicalAddressLow (dma_cb->AllocPa, RingBasePaLow); + + /* Offset to next ring descriptor address */ + RingBasePaLow += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + /* link the pre-allocated TxBuf to TXD */ + pTxD = (TXD_STRUC *)dma_cb->AllocVa; + pTxD->DMADONE = 1; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxD, dma_cb->AllocSize); + + /* no pre-allocated buffer required in CtrlRing for scatter-gather case */ + } +#endif /* CONFIG_ANDES_SUPPORT */ + + +#ifdef MT_MAC + if (1 /*pAd->chipCap.hif_type == HIF_MT*/) { + /* Initialize CTRL Ring and associated buffer memory */ + ULONG /*BufBasePaHigh,*/ BufBasePaLow; + VOID *BufBaseVa; + + pDescRing = &pAd->BcnDescRing; + //RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pDescRing->AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pDescRing->AllocPa); + RingBaseVa = pDescRing->AllocVa; + NdisZeroMemory(pDescRing->AllocVa, pDescRing->AllocSize); + DBGPRINT(RT_DEBUG_OFF, ("TX_BCN DESC %p size = %ld\n", + pDescRing->AllocVa, pDescRing->AllocSize)); + for (index = 0; index < BCN_RING_SIZE; index++) + { + dma_cb = &pAd->BcnRing.Cell[index]; + dma_cb->pNdisPacket = NULL; + dma_cb->pNextNdisPacket = NULL; + /* Init Ctrl Ring Size, Va, Pa variables */ + dma_cb->AllocSize = TXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, 0/*RingBasePaHigh*/); + RTMP_SetPhysicalAddressLow (dma_cb->AllocPa, RingBasePaLow); + + /* Offset to next ring descriptor address */ + RingBasePaLow += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + /* link the pre-allocated TxBuf to TXD */ + pTxD = (TXD_STRUC *)dma_cb->AllocVa; + pTxD->DMADONE = 1; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxD, dma_cb->AllocSize); + + /* no pre-allocated buffer required in CtrlRing for scatter-gather case */ + } + + /* memory zero the Tx BMC ring descriptor's memory */ + pDescRing = &pAd->TxBmcDescRing; + NdisZeroMemory(pDescRing->AllocVa, pDescRing->AllocSize); + /* Save PA & VA for further operation*/ + //RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pDescRing->AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pDescRing->AllocPa); + RingBaseVa = pDescRing->AllocVa; + + /* Zero init all 1st TXBuf's memory for this TxRing*/ + NdisZeroMemory(pAd->TxBmcBufSpace.AllocVa, pAd->TxBmcBufSpace.AllocSize); + /* Save PA & VA for further operation */ + //BufBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxBmcBufSpace.AllocPa); + BufBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxBmcBufSpace.AllocPa); + BufBaseVa = pAd->TxBmcBufSpace.AllocVa; + + /* linking Tx Ring Descriptor and associated buffer memory */ + pTxRing = &pAd->TxBmcRing; + for (index = 0; index < TX_RING_SIZE; index++) + { + dma_cb = &pTxRing->Cell[index]; + dma_cb->pNdisPacket = NULL; + dma_cb->pNextNdisPacket = NULL; + /* Init Tx Ring Size, Va, Pa variables*/ + dma_cb->AllocSize = TXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, 0/*RingBasePaHigh*/); + RTMP_SetPhysicalAddressLow (dma_cb->AllocPa, RingBasePaLow); + + /* Setup Tx Buffer size & address. only 802.11 header will store in this space */ + pDmaBuf = &dma_cb->DmaBuf; + pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE; + pDmaBuf->AllocVa = BufBaseVa; + RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa,0 /*BufBasePaHigh*/); + RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, BufBasePaLow); + + /* link the pre-allocated TxBuf to TXD */ + pTxD = (TXD_STRUC *)dma_cb->AllocVa; + pTxD->SDPtr0 = BufBasePaLow; + /* advance to next ring descriptor address */ + pTxD->DMADONE = 1; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxD, dma_cb->AllocSize); + + RingBasePaLow += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + /* advance to next TxBuf address */ + BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE; + BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE; + } + } +#endif /* MT_MAC */ + + /* Initialize Rx Ring and associated buffer memory */ + for (num = 0; num < NUM_OF_RX_RING; num++) + { + pDescRing = &pAd->RxDescRing[num]; + pRxRing = &pAd->RxRing[num]; + + NdisZeroMemory(pDescRing->AllocVa, pDescRing->AllocSize); + DBGPRINT(RT_DEBUG_OFF, ("RX[%d] DESC %p size = %ld\n", + num, pDescRing->AllocVa, pDescRing->AllocSize)); + + /* Save PA & VA for further operation */ + //RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pDescRing->AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pDescRing->AllocPa); + RingBaseVa = pDescRing->AllocVa; + + /* Linking Rx Ring and associated buffer memory */ + for (index = 0; index < RX_RING_SIZE; index++) + { + dma_cb = &pRxRing->Cell[index]; + /* Init RX Ring Size, Va, Pa variables*/ + dma_cb->AllocSize = RXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, 0/*RingBasePaHigh*/); + RTMP_SetPhysicalAddressLow (dma_cb->AllocPa, RingBasePaLow);; + + /* Offset to next ring descriptor address */ + RingBasePaLow += RXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + RXD_SIZE; + + /* Setup Rx associated Buffer size & allocate share memory */ + pDmaBuf = &dma_cb->DmaBuf; + pDmaBuf->AllocSize = RX_BUFFER_AGGRESIZE; + pPacket = RTMP_AllocateRxPacketBuffer( + pAd, + ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + pDmaBuf->AllocSize, + FALSE, + &pDmaBuf->AllocVa, + &pDmaBuf->AllocPa); + + /* keep allocated rx packet */ + dma_cb->pNdisPacket = pPacket; + + /* Error handling*/ + if (pDmaBuf->AllocVa == NULL) + { + //ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate RxRing's 1st buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + + /* Zero init this memory block */ + //NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize); + + /* Write RxD buffer address & allocated buffer length */ + pRxD = (RXD_STRUC *)dma_cb->AllocVa; + pRxD->SDP0 = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa); + pRxD->DDONE = 0; + pRxD->SDL0 = pDmaBuf->AllocSize; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pRxD, dma_cb->AllocSize); + } + } + + NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME)); + pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); + if (pAd->FragFrame.pFragPacket == NULL) + Status = NDIS_STATUS_RESOURCES; + + /* Initialize all transmit related software queues */ + rtmp_tx_swq_init(pAd); + for(index = 0; index < NUM_OF_TX_RING; index++) + { + /* Init TX rings index pointer */ + pAd->TxRing[index].TxSwFreeIdx = 0; + pAd->TxRing[index].TxCpuIdx = 0; + } + + /* Init RX Ring index pointer */ + for (index = 0; index < NUM_OF_RX_RING; index++) { + pAd->RxRing[index].RxSwReadIdx = 0; + pAd->RxRing[index].RxCpuIdx = RX_RING_SIZE - 1; + } + + /* init MGMT ring index pointer */ + pAd->MgmtRing.TxSwFreeIdx = 0; + pAd->MgmtRing.TxCpuIdx = 0; + +#ifdef CONFIG_ANDES_SUPPORT + /* init CTRL ring index pointer */ + pAd->CtrlRing.TxSwFreeIdx = 0; + pAd->CtrlRing.TxCpuIdx = 0; +#endif /* CONFIG_ANDES_SUPPORT */ + + pAd->PrivateInfo.TxRingFullCnt = 0; + + return Status; + +} + + +/* + ======================================================================== + + Routine Description: + Allocate DMA memory blocks for send, receive + + Arguments: + Adapter Pointer to our adapter + + Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + NDIS_STATUS_RESOURCES + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS RTMPAllocTxRxRingMemory(RTMP_ADAPTER *pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + INT num; + ULONG ErrorValue = 0; + VOID *pci_dev = ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev; + + DBGPRINT(RT_DEBUG_TRACE, ("-->RTMPAllocTxRxRingMemory\n")); + do + { + /* + Allocate all ring descriptors, include TxD, RxD, MgmtD. + Although each size is different, to prevent cacheline and alignment + issue, I intentional set them all to 64 bytes. + */ + for (num = 0; num < NUM_OF_TX_RING; num++) + { + /* Allocate Tx ring descriptor's memory (5 TX rings = 4 ACs + 1 HCCA)*/ + desc_ring_alloc(pAd, &pAd->TxDescRing[num], TX_RING_SIZE * TXD_SIZE); + if (pAd->TxDescRing[num].AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d bytes allocated\n", + num, (INT)pAd->TxDescRing[num].AllocSize)); + + /* Allocate all 1st TXBuf's memory for this TxRing */ + pAd->TxBufSpace[num].AllocSize = TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE; + RTMP_AllocateFirstTxBuffer( + pci_dev, + num, + pAd->TxBufSpace[num].AllocSize, + FALSE, + &pAd->TxBufSpace[num].AllocVa, + &pAd->TxBufSpace[num].AllocPa); + + if (pAd->TxBufSpace[num].AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + } + if (Status == NDIS_STATUS_RESOURCES) + break; + + + /* Alloc MGMT ring desc buffer except Tx ring allocated eariler */ + desc_ring_alloc(pAd, &pAd->MgmtDescRing, MGMT_RING_SIZE * TXD_SIZE); + if (pAd->MgmtDescRing.AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d bytes allocated\n", + (INT)pAd->MgmtDescRing.AllocSize)); + +#ifdef CONFIG_ANDES_SUPPORT + /* Alloc CTRL ring desc buffer except Tx ring allocated eariler */ + desc_ring_alloc(pAd, &pAd->CtrlDescRing, MGMT_RING_SIZE * TXD_SIZE); + if (pAd->CtrlDescRing.AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("CTRL Ring: total %d bytes allocated\n", + (INT)pAd->CtrlDescRing.AllocSize)); +#endif /* CONFIG_ANDES_SUPPORT */ + +#ifdef MT_MAC + if (1 /*pAd->chipCap.hif_type == HIF_MT*/) { + /* Alloc Beacon ring desc buffer */ + desc_ring_alloc(pAd, &pAd->BcnDescRing, BCN_RING_SIZE * TXD_SIZE); + if (pAd->BcnDescRing.AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("Beacon Ring: total %d bytes allocated\n", + (INT)pAd->BcnDescRing.AllocSize)); + + /* Allocate Tx ring descriptor's memory (BMC)*/ + desc_ring_alloc(pAd, &pAd->TxBmcDescRing, TX_RING_SIZE * TXD_SIZE); + if (pAd->TxBmcDescRing.AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("TxBmcRing: total %d bytes allocated\n", + (INT)pAd->TxBmcDescRing.AllocSize)); + + /* Allocate all 1st TXBuf's memory for this TxRing */ + pAd->TxBmcBufSpace.AllocSize = TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE; + RTMP_AllocateFirstTxBuffer( + pci_dev, + 0, + pAd->TxBmcBufSpace.AllocSize, + FALSE, + &pAd->TxBmcBufSpace.AllocVa, + &pAd->TxBmcBufSpace.AllocPa); + + if (pAd->TxBmcBufSpace.AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + + if (Status == NDIS_STATUS_RESOURCES) + break; + } +#endif /* MT_MAC */ + + /* Alloc RX ring desc memory except Tx ring allocated eariler */ + for (num = 0; num < NUM_OF_RX_RING; num++) { + desc_ring_alloc(pAd, &pAd->RxDescRing[num], + RX_RING_SIZE * RXD_SIZE); + if (pAd->RxDescRing[num].AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("Rx[%d] Ring: total %d bytes allocated\n", + num, (INT)pAd->RxDescRing[num].AllocSize)); + } + } while (FALSE); + + + if (Status != NDIS_STATUS_SUCCESS) + { + /* Log error inforamtion*/ + NdisWriteErrorLogEntry( + pAd->AdapterHandle, + NDIS_ERROR_CODE_OUT_OF_RESOURCES, + 1, + ErrorValue); + } + + DBGPRINT_S(("<-- RTMPAllocTxRxRingMemory, Status=%x, ErrorValue=%lux\n", Status,ErrorValue)); + + return Status; +} + +#else +/* + ======================================================================== + + Routine Description: + Allocate DMA memory blocks for send, receive + + Arguments: + Adapter Pointer to our adapter + + Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + NDIS_STATUS_RESOURCES + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS RTMPAllocTxRxRingMemory(RTMP_ADAPTER *pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + ULONG RingBasePaHigh, RingBasePaLow; + PVOID RingBaseVa; + INT index, num; + TXD_STRUC *pTxD; + RXD_STRUC *pRxD; + ULONG ErrorValue = 0; + RTMP_TX_RING *pTxRing; + RTMP_DMABUF *pDmaBuf; + RTMP_DMACB *dma_cb; + PNDIS_PACKET pPacket; + + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPAllocTxRxRingMemory\n")); + + /* Init the CmdQ and CmdQLock*/ + NdisAllocateSpinLock(pAd, &pAd->CmdQLock); + NdisAcquireSpinLock(&pAd->CmdQLock); + RTInitializeCmdQ(&pAd->CmdQ); + NdisReleaseSpinLock(&pAd->CmdQLock); + + do + { + /* + Allocate all ring descriptors, include TxD, RxD, MgmtD. + Although each size is different, to prevent cacheline and alignment + issue, I intentional set them all to 64 bytes + */ + for (num=0; numTxDescRing[num], TX_RING_SIZE * TXD_SIZE); + if (pAd->TxDescRing[num].AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + + pDmaBuf = &pAd->TxDescRing[num]; + DBGPRINT(RT_DEBUG_TRACE, ("TxDescRing[%p]: total %d bytes allocated\n", + pDmaBuf->AllocVa, (INT)pDmaBuf->AllocSize)); + + /* Save PA & VA for further operation*/ + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pDmaBuf->AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa); + RingBaseVa = pDmaBuf->AllocVa; + + /* + Allocate all 1st TXBuf's memory for this TxRing + */ + pAd->TxBufSpace[num].AllocSize = TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE; + RTMP_AllocateFirstTxBuffer( + ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + num, + pAd->TxBufSpace[num].AllocSize, + FALSE, + &pAd->TxBufSpace[num].AllocVa, + &pAd->TxBufSpace[num].AllocPa); + + if (pAd->TxBufSpace[num].AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate a big buffer\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++) + { + dma_cb = &pTxRing->Cell[index]; + dma_cb->pNdisPacket = NULL; + dma_cb->pNextNdisPacket = NULL; + /* Init Tx Ring Size, Va, Pa variables */ + dma_cb->AllocSize = TXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (dma_cb->AllocPa, RingBasePaLow); + + /* Setup Tx Buffer size & address. only 802.11 header will store in this space*/ + pDmaBuf = &dma_cb->DmaBuf; + pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE; + pDmaBuf->AllocVa = BufBaseVa; + RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa, BufBasePaHigh); + RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, BufBasePaLow); + + /* link the pre-allocated TxBuf to TXD */ + pTxD = (TXD_STRUC *)dma_cb->AllocVa; + pTxD->SDPtr0 = BufBasePaLow; + /* advance to next ring descriptor address */ + pTxD->DMADONE = 1; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxD, dma_cb->AllocSize); + + RingBasePaLow += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + /* advance to next TxBuf address */ + BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE; + BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE; + } + DBGPRINT(RT_DEBUG_TRACE, ("TxRing[%d]: total %d entry allocated\n", num, index)); + } + if (Status == NDIS_STATUS_RESOURCES) + break; + + /* + Allocate MGMT ring descriptor's memory except Tx ring which allocated eariler + */ + desc_ring_alloc(pAd, &pAd->MgmtDescRing, MGMT_RING_SIZE * TXD_SIZE); + if (pAd->MgmtDescRing.AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("MgmtDescRing[%p]: total %d bytes allocated\n", + pAd->MgmtDescRing.AllocVa, (INT)pAd->MgmtDescRing.AllocSize)); + + /* Save PA & VA for further operation*/ + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->MgmtDescRing.AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow(pAd->MgmtDescRing.AllocPa); + RingBaseVa = pAd->MgmtDescRing.AllocVa; + + /* + Initialize MGMT Ring and associated buffer memory + */ + for (index = 0; index < MGMT_RING_SIZE; index++) + { + dma_cb = &pAd->MgmtRing.Cell[index]; + dma_cb->pNdisPacket = NULL; + dma_cb->pNextNdisPacket = NULL; + /* Init MGMT Ring Size, Va, Pa variables*/ + dma_cb->AllocSize = TXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (dma_cb->AllocPa, RingBasePaLow); + + /* Offset to next ring descriptor address*/ + RingBasePaLow += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + /* link the pre-allocated TxBuf to TXD*/ + pTxD = (TXD_STRUC *)dma_cb->AllocVa; + pTxD->DMADONE = 1; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxD, dma_cb->AllocSize); + + /* no pre-allocated buffer required in MgmtRing for scatter-gather case*/ + } + DBGPRINT(RT_DEBUG_TRACE, ("MGMT Ring: total %d entry allocated\n", index)); + +#ifdef CONFIG_ANDES_SUPPORT + /* + Allocate CTRL ring descriptor's memory except Tx ring which allocated eariler + */ + desc_ring_alloc(pAd, &pAd->CtrlDescRing, MGMT_RING_SIZE * TXD_SIZE); + if (pAd->CtrlDescRing.AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("CtrlDescRing[%p]: total %d bytes allocated\n", + pAd->CtrlDescRing.AllocVa, (INT)pAd->CtrlDescRing.AllocSize)); + + /* Save PA & VA for further operation*/ + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->CtrlDescRing.AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->CtrlDescRing.AllocPa); + RingBaseVa = pAd->CtrlDescRing.AllocVa; + + /* + Initialize CTRL Ring and associated buffer memory + */ + for (index = 0; index < MGMT_RING_SIZE; index++) + { + dma_cb = &pAd->CtrlRing.Cell[index]; + dma_cb->pNdisPacket = NULL; + dma_cb->pNextNdisPacket = NULL; + /* Init CTRL Ring Size, Va, Pa variables*/ + dma_cb->AllocSize = TXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow(dma_cb->AllocPa, RingBasePaLow); + + /* Offset to next ring descriptor address*/ + RingBasePaLow += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + /* link the pre-allocated TxBuf to TXD*/ + pTxD = (TXD_STRUC *)dma_cb->AllocVa; + pTxD->DMADONE = 1; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxD, dma_cb->AllocSize); + + /* no pre-allocated buffer required in CtrlRing for scatter-gather case*/ + } + DBGPRINT(RT_DEBUG_TRACE, ("CTRL Ring: total %d entry allocated\n", index)); +#endif /* CONFIG_ANDES_SUPPORT */ + + +#ifdef MT_MAC + if (1/* pAd->chipCap.hif_type == HIF_MT */) { + /* Allocate Beacon ring descriptor's memory */ + ULONG BufBasePaHigh; + ULONG BufBasePaLow; + PVOID BufBaseVa; + + desc_ring_alloc(pAd, &pAd->BcnDescRing, BCN_RING_SIZE * TXD_SIZE); + if (pAd->BcnDescRing.AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("BcnDescRing[%p]: total %d bytes allocated\n", + pAd->BcnDescRing.AllocVa, (INT)pAd->BcnDescRing.AllocSize)); + + /* Save PA & VA for further operation*/ + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->BcnDescRing.AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->BcnDescRing.AllocPa); + RingBaseVa = pAd->BcnDescRing.AllocVa; + + /* Initialize Beacon Ring and associated buffer memory */ + for (index = 0; index < BCN_RING_SIZE; index++) + { + dma_cb = &pAd->BcnRing.Cell[index]; + dma_cb->pNdisPacket = NULL; + dma_cb->pNextNdisPacket = NULL; + /* Init CTRL Ring Size, Va, Pa variables*/ + dma_cb->AllocSize = TXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow(dma_cb->AllocPa, RingBasePaLow); + + /* Offset to next ring descriptor address*/ + RingBasePaLow += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + /* link the pre-allocated TxBuf to TXD*/ + pTxD = (TXD_STRUC *)dma_cb->AllocVa; + pTxD->DMADONE = 1; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxD, dma_cb->AllocSize); + + /* no pre-allocated buffer required in CtrlRing for scatter-gather case*/ + } + DBGPRINT(RT_DEBUG_TRACE, ("Bcn Ring: total %d entry allocated\n", index)); + + /* + Allocate Tx ring descriptor's memory (BMC) + */ + desc_ring_alloc(pAd, &pAd->TxBmcDescRing, TX_RING_SIZE * TXD_SIZE); + if (pAd->TxBmcDescRing.AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + + pDmaBuf = &pAd->TxBmcDescRing; + DBGPRINT(RT_DEBUG_TRACE, ("TxBmcDescRing[%p]: total %d bytes allocated\n", + pDmaBuf->AllocVa, (INT)pDmaBuf->AllocSize)); + + /* Save PA & VA for further operation*/ + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pDmaBuf->AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa); + RingBaseVa = pDmaBuf->AllocVa; + + /* + Allocate all 1st TXBuf's memory for this TxRing + */ + pAd->TxBmcBufSpace.AllocSize = TX_RING_SIZE * TX_DMA_1ST_BUFFER_SIZE; + RTMP_AllocateFirstTxBuffer( + ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + 0, + pAd->TxBmcBufSpace.AllocSize, + FALSE, + &pAd->TxBmcBufSpace.AllocVa, + &pAd->TxBmcBufSpace.AllocPa); + + if (pAd->TxBmcBufSpace.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->TxBmcBufSpace.AllocVa, pAd->TxBmcBufSpace.AllocSize); + + /* Save PA & VA for further operation*/ + BufBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->TxBmcBufSpace.AllocPa); + BufBasePaLow = RTMP_GetPhysicalAddressLow (pAd->TxBmcBufSpace.AllocPa); + BufBaseVa = pAd->TxBmcBufSpace.AllocVa; + + /* + Initialize Tx Ring Descriptor and associated buffer memory + */ + pTxRing = &pAd->TxBmcRing; + for (index = 0; index < TX_RING_SIZE; index++) + { + dma_cb = &pTxRing->Cell[index]; + dma_cb->pNdisPacket = NULL; + dma_cb->pNextNdisPacket = NULL; + /* Init Tx Ring Size, Va, Pa variables */ + dma_cb->AllocSize = TXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (dma_cb->AllocPa, RingBasePaLow); + + /* Setup Tx Buffer size & address. only 802.11 header will store in this space*/ + pDmaBuf = &dma_cb->DmaBuf; + pDmaBuf->AllocSize = TX_DMA_1ST_BUFFER_SIZE; + pDmaBuf->AllocVa = BufBaseVa; + RTMP_SetPhysicalAddressHigh(pDmaBuf->AllocPa, BufBasePaHigh); + RTMP_SetPhysicalAddressLow(pDmaBuf->AllocPa, BufBasePaLow); + + /* link the pre-allocated TxBuf to TXD */ + pTxD = (TXD_STRUC *)dma_cb->AllocVa; + pTxD->SDPtr0 = BufBasePaLow; + /* advance to next ring descriptor address */ + pTxD->DMADONE = 1; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pTxD, dma_cb->AllocSize); + + RingBasePaLow += TXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + TXD_SIZE; + + /* advance to next TxBuf address */ + BufBasePaLow += TX_DMA_1ST_BUFFER_SIZE; + BufBaseVa = (PUCHAR) BufBaseVa + TX_DMA_1ST_BUFFER_SIZE; + } + + if (Status == NDIS_STATUS_RESOURCES) + break; + } +#endif /* MT_MAC */ + + for (num = 0; num < NUM_OF_RX_RING; num++) + { + /* Alloc RxRingDesc memory except Tx ring allocated eariler */ + desc_ring_alloc(pAd, &pAd->RxDescRing[num], RX_RING_SIZE * RXD_SIZE); + if (pAd->RxDescRing[num].AllocVa == NULL) { + Status = NDIS_STATUS_RESOURCES; + break; + } + DBGPRINT(RT_DEBUG_OFF, ("RxDescRing[%p]: total %d bytes allocated\n", + pAd->RxDescRing[num].AllocVa, (INT)pAd->RxDescRing[num].AllocSize)); + + /* Initialize Rx Ring and associated buffer memory */ + RingBasePaHigh = RTMP_GetPhysicalAddressHigh(pAd->RxDescRing[num].AllocPa); + RingBasePaLow = RTMP_GetPhysicalAddressLow (pAd->RxDescRing[num].AllocPa); + RingBaseVa = pAd->RxDescRing[num].AllocVa; + for (index = 0; index < RX_RING_SIZE; index++) + { + dma_cb = &pAd->RxRing[num].Cell[index]; + /* Init RX Ring Size, Va, Pa variables*/ + dma_cb->AllocSize = RXD_SIZE; + dma_cb->AllocVa = RingBaseVa; + RTMP_SetPhysicalAddressHigh(dma_cb->AllocPa, RingBasePaHigh); + RTMP_SetPhysicalAddressLow (dma_cb->AllocPa, RingBasePaLow); + + /* Offset to next ring descriptor address */ + RingBasePaLow += RXD_SIZE; + RingBaseVa = (PUCHAR) RingBaseVa + RXD_SIZE; + + /* Setup Rx associated Buffer size & allocate share memory*/ + pDmaBuf = &dma_cb->DmaBuf; + pDmaBuf->AllocSize = RX_BUFFER_AGGRESIZE; + pPacket = RTMP_AllocateRxPacketBuffer( + pAd, + ((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + pDmaBuf->AllocSize, + FALSE, + &pDmaBuf->AllocVa, + &pDmaBuf->AllocPa); + + /* keep allocated rx packet */ + dma_cb->pNdisPacket = pPacket; + if (pDmaBuf->AllocVa == NULL) + { + ErrorValue = ERRLOG_OUT_OF_SHARED_MEMORY; + DBGPRINT_ERR(("Failed to allocate RxRing's 1st buffer\n")); + Status = NDIS_STATUS_RESOURCES; + break; + } + + /* Zero init this memory block*/ + NdisZeroMemory(pDmaBuf->AllocVa, pDmaBuf->AllocSize); + + /* Write RxD buffer address & allocated buffer length*/ + pRxD = (RXD_STRUC *)dma_cb->AllocVa; + pRxD->SDP0 = RTMP_GetPhysicalAddressLow(pDmaBuf->AllocPa); + pRxD->SDL0 = pDmaBuf->AllocSize; + pRxD->DDONE = 0; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#endif + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(pRxD, dma_cb->AllocSize); + } + + DBGPRINT(RT_DEBUG_TRACE, ("Rx[%d] Ring: total %d entry allocated\n", num, index)); + } + } while (FALSE); + + NdisZeroMemory(&pAd->FragFrame, sizeof(FRAGMENT_FRAME)); + pAd->FragFrame.pFragPacket = RTMP_AllocateFragPacketBuffer(pAd, RX_BUFFER_NORMSIZE); + if (pAd->FragFrame.pFragPacket == NULL) + Status = NDIS_STATUS_RESOURCES; + + if (Status != NDIS_STATUS_SUCCESS) + { + /* Log error inforamtion*/ + NdisWriteErrorLogEntry( + pAd->AdapterHandle, + NDIS_ERROR_CODE_OUT_OF_RESOURCES, + 1, + ErrorValue); + } + + /* + Initialize all transmit related software queues + */ + + /* Init TX rings index pointer*/ + rtmp_tx_swq_init(pAd); + for(index = 0; index < NUM_OF_TX_RING; index++) + { + pAd->TxRing[index].TxSwFreeIdx = 0; + pAd->TxRing[index].TxCpuIdx = 0; + } + + /* init MGMT ring index pointer*/ + pAd->MgmtRing.TxSwFreeIdx = 0; + pAd->MgmtRing.TxCpuIdx = 0; + +#ifdef CONFIG_ANDES_SUPPORT + /* init CTRL ring index pointer*/ + pAd->CtrlRing.TxSwFreeIdx = 0; + pAd->CtrlRing.TxCpuIdx = 0; +#endif /* CONFIG_ANDES_SUPPORT */ + + /* Init RX Ring index pointer*/ + for(index = 0; index < NUM_OF_RX_RING; index++) { + pAd->RxRing[index].RxSwReadIdx = 0; + pAd->RxRing[index].RxCpuIdx = RX_RING_SIZE - 1; + } + + pAd->PrivateInfo.TxRingFullCnt = 0; + + DBGPRINT_S(("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status)); + return Status; +} + + +VOID RTMPFreeTxRxRingMemory(RTMP_ADAPTER *pAd) +{ + int index, num , j; + RTMP_TX_RING *pTxRing; + TXD_STRUC *pTxD; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR tx_hw_info[TXD_SIZE]; +#endif /* RT_BIG_ENDIAN */ + PNDIS_PACKET pPacket; + RTMP_DMACB *dma_cb; + + DBGPRINT(RT_DEBUG_TRACE, ("--> RTMPFreeTxRxRingMemory\n")); + + rtmp_tx_swq_exit(pAd, WCID_ALL); + + /* 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 = (TXD_STRUC *) (pTxRing->Cell[j].AllocVa); + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_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 */ + } + } + + { + RTMP_MGMT_RING *pMgmtRing = &pAd->MgmtRing; + NdisAcquireSpinLock(&pAd->MgmtRingLock); + + RTMP_IO_READ32(pAd, pMgmtRing->hw_didx_addr, &pMgmtRing->TxDmaIdx); + while (pMgmtRing->TxSwFreeIdx!= pMgmtRing->TxDmaIdx) + { +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *) (pMgmtRing->Cell[pAd->MgmtRing.TxSwFreeIdx].AllocVa); + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_STRUC *) (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); + } + +#ifdef CONFIG_ANDES_SUPPORT + { + RTMP_CTRL_RING *pCtrlRing = &pAd->CtrlRing; + + NdisAcquireSpinLock(&pAd->CtrlRingLock); + RTMP_IO_READ32(pAd, pCtrlRing->hw_didx_addr, &pCtrlRing->TxDmaIdx); + + while (pCtrlRing->TxSwFreeIdx!= pCtrlRing->TxDmaIdx) + { +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *) (pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx].AllocVa); + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_STRUC *) (pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx].AllocVa); +#endif + pTxD->DMADONE = 0; + pPacket = pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx].pNdisPacket; + + if (pPacket == NULL) + { + INC_RING_INDEX(pCtrlRing->TxSwFreeIdx, MGMT_RING_SIZE); + continue; + } + + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx].pNdisPacket = NULL; + + pPacket = pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx].pNextNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + pCtrlRing->Cell[pCtrlRing->TxSwFreeIdx].pNextNdisPacket = NULL; + INC_RING_INDEX(pCtrlRing->TxSwFreeIdx, MGMT_RING_SIZE); + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD); +#endif + } + NdisReleaseSpinLock(&pAd->CtrlRingLock); + } +#endif /* CONFIG_ANDES_SUPPORT */ + + +#ifdef MT_MAC + if (1 /*pAd->chipCap.hif_type == HIF_MT*/) + { + RTMP_BCN_RING *pBcnRing = &pAd->BcnRing; + RTMP_DMACB *dma_cell = &pAd->BcnRing.Cell[0]; + + RTMP_SEM_LOCK(&pAd->BcnRingLock); + //NdisAcquireSpinLock(&pAd->BcnRingLock); + RTMP_IO_READ32(pAd, pBcnRing->hw_didx_addr, &pBcnRing->TxDmaIdx); + + while (pBcnRing->TxSwFreeIdx!= pBcnRing->TxDmaIdx) + { +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *) (dma_cell[pBcnRing->TxSwFreeIdx].AllocVa); + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_STRUC *) (dma_cell[pBcnRing->TxSwFreeIdx].AllocVa); +#endif + pTxD->DMADONE = 0; + pPacket = dma_cell[pBcnRing->TxSwFreeIdx].pNdisPacket; + + if (pPacket == NULL) + { + INC_RING_INDEX(pBcnRing->TxSwFreeIdx, BCN_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); + } + dma_cell[pBcnRing->TxSwFreeIdx].pNdisPacket = NULL; + + pPacket = dma_cell[pBcnRing->TxSwFreeIdx].pNextNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_SUCCESS); + } + dma_cell[pBcnRing->TxSwFreeIdx].pNextNdisPacket = NULL; + INC_RING_INDEX(pBcnRing->TxSwFreeIdx, BCN_RING_SIZE); + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, TRUE, TYPE_TXD); +#endif + } + RTMP_SEM_UNLOCK(&pAd->BcnRingLock); + //NdisReleaseSpinLock(&pAd->BcnRingLock); + + /* Free Tx BMC Ring Packet*/ + pTxRing = &pAd->TxBmcRing; + + for (j=0; j< TX_RING_SIZE; j++) + { +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *) (pTxRing->Cell[j].AllocVa); + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_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 */ + } + + if (pAd->TxBmcBufSpace.AllocVa) + { + RTMP_FreeFirstTxBuffer(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, pAd->TxBmcBufSpace.AllocSize, FALSE, pAd->TxBmcBufSpace.AllocVa, pAd->TxBmcBufSpace.AllocPa); + } + NdisZeroMemory(&pAd->TxBmcBufSpace, sizeof(RTMP_DMABUF)); + + if (pAd->TxBmcDescRing.AllocVa) + { + RtmpFreeDescBuf(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, pAd->TxBmcDescRing.AllocSize, pAd->TxBmcDescRing.AllocVa, pAd->TxBmcDescRing.AllocPa); + } + NdisZeroMemory(&pAd->TxBmcDescRing, sizeof(RTMP_DMABUF)); + } +#endif /* MT_MAC */ + + for (j = 0; j < NUM_OF_RX_RING; j++) + { + for (index = RX_RING_SIZE - 1 ; index >= 0; index--) + { + dma_cb = &pAd->RxRing[j].Cell[index]; + if ((dma_cb->DmaBuf.AllocVa) && (dma_cb->pNdisPacket)) + { + PCI_UNMAP_SINGLE(pAd, dma_cb->DmaBuf.AllocPa, + dma_cb->DmaBuf.AllocSize, + RTMP_PCI_DMA_FROMDEVICE); + RELEASE_NDIS_PACKET(pAd, dma_cb->pNdisPacket, NDIS_STATUS_SUCCESS); + } + } + NdisZeroMemory(pAd->RxRing[j].Cell, RX_RING_SIZE * sizeof(RTMP_DMACB)); + + if (pAd->RxDescRing[j].AllocVa) + RtmpFreeDescBuf(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + pAd->RxDescRing[j].AllocSize, + pAd->RxDescRing[j].AllocVa, + pAd->RxDescRing[j].AllocPa); + + NdisZeroMemory(&pAd->RxDescRing[j], sizeof(RTMP_DMABUF)); + } + + if (pAd->MgmtDescRing.AllocVa) + { + RtmpFreeDescBuf(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, pAd->MgmtDescRing.AllocSize, pAd->MgmtDescRing.AllocVa, pAd->MgmtDescRing.AllocPa); + } + NdisZeroMemory(&pAd->MgmtDescRing, sizeof(RTMP_DMABUF)); + +#ifdef CONFIG_ANDES_SUPPORT + if (pAd->CtrlDescRing.AllocVa) + { + RtmpFreeDescBuf(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, pAd->CtrlDescRing.AllocSize, pAd->CtrlDescRing.AllocVa, pAd->CtrlDescRing.AllocPa); + } + NdisZeroMemory(&pAd->CtrlDescRing, sizeof(RTMP_DMABUF)); +#endif /* CONFIG_ANDES_SUPPORT */ + + for (num = 0; num < NUM_OF_TX_RING; num++) + { + if (pAd->TxBufSpace[num].AllocVa) + { + RTMP_FreeFirstTxBuffer(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, pAd->TxBufSpace[num].AllocSize, FALSE, pAd->TxBufSpace[num].AllocVa, pAd->TxBufSpace[num].AllocPa); + } + NdisZeroMemory(&pAd->TxBufSpace[num], sizeof(RTMP_DMABUF)); + + if (pAd->TxDescRing[num].AllocVa) + { + RtmpFreeDescBuf(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, pAd->TxDescRing[num].AllocSize, pAd->TxDescRing[num].AllocVa, pAd->TxDescRing[num].AllocPa); + } + NdisZeroMemory(&pAd->TxDescRing[num], sizeof(RTMP_DMABUF)); + } + + if (pAd->FragFrame.pFragPacket) + { + RELEASE_NDIS_PACKET(pAd, pAd->FragFrame.pFragPacket, NDIS_STATUS_SUCCESS); + pAd->FragFrame.pFragPacket = NULL; + } + + NdisFreeSpinLock(&pAd->CmdQLock); + + DBGPRINT(RT_DEBUG_TRACE, ("<-- RTMPFreeTxRxRingMemory\n")); +} + +#endif /* RESOURCE_PRE_ALLOC */ + + +VOID AsicInitTxRxRing(RTMP_ADAPTER *pAd) +{ +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + rlt_asic_init_txrx_ring(pAd); +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + rtmp_asic_init_txrx_ring(pAd); +#endif /* RTMP_MAC */ + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + mt_asic_init_txrx_ring(pAd); +#endif /* MT_MAC */ +} + + +/* + ======================================================================== + + Routine Description: + Reset NIC Asics. Call after rest DMA. So reset TX_CTX_IDX to zero. + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + Reset NIC to initial state AS IS system boot up time. + + ======================================================================== +*/ +VOID RTMPRingCleanUp(RTMP_ADAPTER *pAd, UCHAR RingType) +{ + TXD_STRUC *pTxD; + RXD_STRUC *pRxD; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD, TxD; + RXD_STRUC *pDestRxD, RxD; +#endif /* RT_BIG_ENDIAN */ + //QUEUE_ENTRY *pEntry; + PNDIS_PACKET pPacket; + RTMP_TX_RING *pTxRing; + ULONG IrqFlags = 0; + int i, ring_id; + + + /* + We have to clean all descriptors in case some error happened with reset + */ + DBGPRINT(RT_DEBUG_OFF,("RTMPRingCleanUp(RingIdx=%d, Pending-NDIS=%ld)\n", RingType, pAd->RalinkCounters.PendingNdisPacketCount)); + switch (RingType) + { + case QID_AC_BK: + case QID_AC_BE: + case QID_AC_VI: + case QID_AC_VO: + case QID_HCCA: + + pTxRing = &pAd->TxRing[RingType]; + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + for (i=0; iCell[i].AllocVa; + + pPacket = (PNDIS_PACKET) pTxRing->Cell[i].pNdisPacket; + /* release scatter-and-gather NDIS_PACKET*/ + if (pPacket) + { + 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, pTxRing->hw_didx_addr, &pTxRing->TxDmaIdx); + pTxRing->TxSwFreeIdx = pTxRing->TxDmaIdx; + pTxRing->TxCpuIdx = pTxRing->TxDmaIdx; + RTMP_IO_WRITE32(pAd, pTxRing->hw_cidx_addr, pTxRing->TxCpuIdx); + + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + + //rtmp_tx_swq_exit(pAd, WCID_ALL); + break; + + case QID_MGMT: + RTMP_IRQ_LOCK(&pAd->MgmtRingLock, IrqFlags); + for (i=0; iMgmtRing.Cell[i].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_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, pAd->MgmtRing.hw_didx_addr, &pAd->MgmtRing.TxDmaIdx); + pAd->MgmtRing.TxSwFreeIdx = pAd->MgmtRing.TxDmaIdx; + pAd->MgmtRing.TxCpuIdx = pAd->MgmtRing.TxDmaIdx; + RTMP_IO_WRITE32(pAd, pAd->MgmtRing.hw_cidx_addr, pAd->MgmtRing.TxCpuIdx); + + RTMP_IRQ_UNLOCK(&pAd->MgmtRingLock, IrqFlags); + pAd->RalinkCounters.MgmtRingFullCount = 0; + break; + + case QID_RX: + for (ring_id =0; ring_id < NUM_OF_RX_RING; ring_id++) + { + RTMP_RX_RING *pRxRing; + NDIS_SPIN_LOCK *lock; + + pRxRing = &pAd->RxRing[ring_id]; + lock = &pAd->RxRingLock[ring_id]; + + RTMP_IRQ_LOCK(lock, IrqFlags); + for (i=0; iCell[i].AllocVa; + RxD = *pDestRxD; + pRxD = &RxD; + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); +#else + /* Point to Rx indexed rx ring descriptor*/ + pRxD = (RXD_STRUC *)pRxRing->Cell[i].AllocVa; +#endif /* RT_BIG_ENDIAN */ + + pRxD->DDONE = 0; + pRxD->SDL0 = RX_BUFFER_AGGRESIZE; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pRxD, TYPE_RXD); + WriteBackToDescriptor((PUCHAR)pDestRxD, (PUCHAR)pRxD, FALSE, TYPE_RXD); +#endif /* RT_BIG_ENDIAN */ + } + + RTMP_IO_READ32(pAd, pRxRing->hw_didx_addr, &pRxRing->RxDmaIdx); + pRxRing->RxSwReadIdx = pRxRing->RxDmaIdx; + pRxRing->RxCpuIdx = ((pRxRing->RxDmaIdx == 0) ? (RX_RING_SIZE-1) : (pRxRing->RxDmaIdx-1)); + RTMP_IO_WRITE32(pAd, pRxRing->hw_cidx_addr, pRxRing->RxCpuIdx); + + RTMP_IRQ_UNLOCK(lock, IrqFlags); + } + break; + +#ifdef CONFIG_ANDES_SUPPORT + case QID_CTRL: + RTMP_IRQ_LOCK(&pAd->CtrlRingLock, IrqFlags); + + for (i=0; iCtrlRing.Cell[i].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_STRUC *) pAd->CtrlRing.Cell[i].AllocVa; +#endif /* RT_BIG_ENDIAN */ + + pPacket = (PNDIS_PACKET) pAd->CtrlRing.Cell[i].pNdisPacket; + /* rlease scatter-and-gather NDIS_PACKET*/ + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + pAd->CtrlRing.Cell[i].pNdisPacket = NULL; + + pPacket = (PNDIS_PACKET) pAd->CtrlRing.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->CtrlRing.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, pAd->CtrlRing.hw_didx_addr, &pAd->CtrlRing.TxDmaIdx); + pAd->CtrlRing.TxSwFreeIdx = pAd->CtrlRing.TxDmaIdx; + pAd->CtrlRing.TxCpuIdx = pAd->CtrlRing.TxDmaIdx; + RTMP_IO_WRITE32(pAd, pAd->CtrlRing.hw_cidx_addr, pAd->CtrlRing.TxCpuIdx); + + RTMP_IRQ_UNLOCK(&pAd->CtrlRingLock, IrqFlags); + break; +#endif /* CONFIG_ANDES_SUPPORT */ + +#ifdef MT_MAC + case QID_BCN: + RTMP_IRQ_LOCK(&pAd->BcnRingLock, IrqFlags); + + for (i = 0; i < BCN_RING_SIZE; i++) + { +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *)pAd->BcnRing.Cell[i].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_STRUC *) pAd->BcnRing.Cell[i].AllocVa; +#endif /* RT_BIG_ENDIAN */ + + pPacket = (PNDIS_PACKET) pAd->BcnRing.Cell[i].pNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + //RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + pAd->BcnRing.Cell[i].pNdisPacket = NULL; + + pPacket = (PNDIS_PACKET) pAd->BcnRing.Cell[i].pNextNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + //RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + pAd->BcnRing.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, pAd->BcnRing.hw_didx_addr, &pAd->BcnRing.TxDmaIdx); + pAd->BcnRing.TxSwFreeIdx = pAd->BcnRing.TxDmaIdx; + pAd->BcnRing.TxCpuIdx = pAd->BcnRing.TxDmaIdx; + RTMP_IO_WRITE32(pAd, pAd->BcnRing.hw_cidx_addr, pAd->BcnRing.TxCpuIdx); + + RTMP_IRQ_UNLOCK(&pAd->BcnRingLock, IrqFlags); + + break; + case QID_BMC: + + for (i = 0; i < TX_RING_SIZE; i++) + { +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *)pAd->TxBmcRing.Cell[i].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_STRUC *) pAd->TxBmcRing.Cell[i].AllocVa; +#endif /* RT_BIG_ENDIAN */ + + pPacket = (PNDIS_PACKET) pAd->TxBmcRing.Cell[i].pNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr0, pTxD->SDLen0, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + pAd->TxBmcRing.Cell[i].pNdisPacket = NULL; + + pPacket = (PNDIS_PACKET) pAd->TxBmcRing.Cell[i].pNextNdisPacket; + if (pPacket) + { + PCI_UNMAP_SINGLE(pAd, pTxD->SDPtr1, pTxD->SDLen1, RTMP_PCI_DMA_TODEVICE); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + pAd->TxBmcRing.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, pAd->TxBmcRing.hw_didx_addr, &pAd->TxBmcRing.TxDmaIdx); + pAd->TxBmcRing.TxSwFreeIdx = pAd->TxBmcRing.TxDmaIdx; + pAd->TxBmcRing.TxCpuIdx = pAd->TxBmcRing.TxDmaIdx; + RTMP_IO_WRITE32(pAd, pAd->TxBmcRing.hw_cidx_addr, pAd->TxBmcRing.TxCpuIdx); + + break; +#endif /* MT_MAC */ + + default: + break; + } +} + + +VOID PDMAResetAndRecovery(RTMP_ADAPTER *pAd) +{ + UINT32 RemapBase, RemapOffset; + UINT32 Value; + UINT32 RestoreValue; + UINT32 Loop = 0; + ULONG IrqFlags = 0; + + /* Stop SW Dequeue */ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET); + + RTMP_ASIC_INTERRUPT_DISABLE(pAd); + + /* Disable PDMA */ + RT28XXDMADisable(pAd); + + RtmpOsMsDelay(1); + + pAd->RxReset = 1; + + /* Assert csr_force_tx_eof */ + RTMP_IO_READ32(pAd, MT_WPDMA_GLO_CFG , &Value); + Value |= FORCE_TX_EOF; + RTMP_IO_WRITE32(pAd, MT_WPDMA_GLO_CFG, Value); + + /* Infor PSE client of TX abort */ + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + RemapBase = GET_REMAP_2_BASE(RST) << 19; + RemapOffset = GET_REMAP_2_OFFSET(RST); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value |= TX_R_E_1; + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + + do + { + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + + if((Value & TX_R_E_1_S) == TX_R_E_1_S) + break; + RtmpOsMsDelay(1); + Loop++; + } while (Loop <= 500); + + if (Loop > 500) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Tx state is not idle(CLIET RST = %x)\n", __FUNCTION__, Value)); + pAd->PDMAResetFailCount++; + } + + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value |= TX_R_E_2; + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + + /* Reset PDMA */ + RTMP_IO_READ32(pAd, MT_WPDMA_GLO_CFG , &Value); + Value |= SW_RST; + RTMP_IO_WRITE32(pAd, MT_WPDMA_GLO_CFG, Value); + + Loop = 0; + /* Polling for PSE client to clear TX FIFO */ + do + { + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + + if((Value & TX_R_E_2_S) == TX_R_E_2_S) + break; + RtmpOsMsDelay(1); + Loop++; + } while (Loop <= 500); + + if (Loop > 500) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Tx FIFO is not empty(CLIET RST = %x)\n", __FUNCTION__, Value)); + pAd->PDMAResetFailCount++; + } + + /* De-assert PSE client TX abort */ + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~TX_R_E_1; + Value &= ~TX_R_E_2; + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); + + AsicDisableSync(pAd); + + RTMP_IRQ_LOCK(&pAd->BcnRingLock, IrqFlags); + +#ifdef CONFIG_AP_SUPPORT + if (pAd->OpMode == OPMODE_AP) + { + UCHAR idx; + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) + { + BSS_STRUCT *pMbss; + pMbss = &pAd->ApCfg.MBSSID[idx]; + ASSERT(pMbss); + if (pMbss) + { + pMbss->bcn_buf.bcn_state = BCN_TX_IDLE; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():func_dev is NULL!\n", __FUNCTION__)); + RTMP_IRQ_UNLOCK(&pAd->BcnRingLock, IrqFlags); + return ; + } + } + } +#endif + + + RTMP_IRQ_UNLOCK(&pAd->BcnRingLock, IrqFlags); + + RTMPRingCleanUp(pAd, QID_AC_BE); + RTMPRingCleanUp(pAd, QID_AC_BK); + RTMPRingCleanUp(pAd, QID_AC_VI); + RTMPRingCleanUp(pAd, QID_AC_VO); + RTMPRingCleanUp(pAd, QID_MGMT); + RTMPRingCleanUp(pAd, QID_CTRL); + RTMPRingCleanUp(pAd, QID_BCN); + RTMPRingCleanUp(pAd, QID_BMC); + RTMPRingCleanUp(pAd, QID_RX); + + AsicEnableBssSync(pAd, pAd->CommonCfg.BeaconPeriod); + + /* Enable PDMA */ + RT28XXDMAEnable(pAd); + + RTMP_ASIC_INTERRUPT_ENABLE(pAd); + + /* Enable SW Dequeue */ + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET); +} + + +VOID PDMAWatchDog(RTMP_ADAPTER *pAd) +{ + BOOLEAN NoDataOut = FALSE, NoDataIn = FALSE; + + /* Tx DMA unchaged detect */ + NoDataOut = MonitorTxRing(pAd); + + if (NoDataOut) + { + DBGPRINT(RT_DEBUG_OFF, ("TXDMA Reset\n")); + pAd->TxDMAResetCount++; + goto reset; + } + + /* Rx DMA unchanged detect */ + NoDataIn = MonitorRxRing(pAd); + + if (NoDataIn) + { + DBGPRINT(RT_DEBUG_OFF, ("RXDMA Reset\n")); + pAd->RxDMAResetCount++; + goto reset; + } + + return; + +reset: + +#ifdef DMA_RESET_SUPPORT + //replace with PSE reset instead of PMDA reset. + pAd->pse_reset_flag=TRUE; +#else /* DMA_RESET_SUPPORT */ + PDMAResetAndRecovery(pAd); +#endif /* !DMA_RESET_SUPPORT */ + +} + +VOID DumpPseInfo(RTMP_ADAPTER *pAd) +{ + UINT32 RemapBase, RemapOffset; + UINT32 Value; + UINT32 RestoreValue; + UINT32 Index; + + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + + /* PSE Infomation */ + for (Index = 0; Index < 30720; Index++) + { + RemapBase = GET_REMAP_2_BASE(0xa5000000 + Index * 4) << 19; + RemapOffset = GET_REMAP_2_OFFSET(0xa5000000 + Index * 4); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + + DBGPRINT(RT_DEBUG_OFF, ("Offset[0x%x] = 0x%x\n", 0xa5000000 + Index * 4, Value)); + } + + /* Frame linker */ + for (Index = 0; Index < 1280; Index++) + { + RemapBase = GET_REMAP_2_BASE(0xa00001b0) << 19; + RemapOffset = GET_REMAP_2_OFFSET(0xa00001b0); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~0xfff; + Value |= (Index & 0xfff); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + + RemapBase = GET_REMAP_2_BASE(0xa00001b4) << 19; + RemapOffset = GET_REMAP_2_OFFSET(0xa00001b4); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + + DBGPRINT(RT_DEBUG_OFF, ("Frame Linker(0x%x) = 0x%x\n", Index, Value )); + + } + + /* Page linker */ + for (Index = 0; Index < 1280; Index++) + { + RemapBase = GET_REMAP_2_BASE(0xa00001b8) << 19; + RemapOffset = GET_REMAP_2_OFFSET(0xa00001b8); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~(0xfff << 16); + Value |= ((Index & 0xfff) << 16); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + + RemapBase = GET_REMAP_2_BASE(0xa00001b8) << 19; + RemapOffset = GET_REMAP_2_OFFSET(0xa00001b8); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + + DBGPRINT(RT_DEBUG_OFF, ("Page Linker(0x%x) = 0x%x\n", Index, (Value & 0xfff))); + } + + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); +} + + +VOID PSEResetAndRecovery(RTMP_ADAPTER *pAd) +{ + UINT32 Loop = 0; + UINT32 Value; + + +#ifdef RTMP_PCI_SUPPORT + NdisAcquireSpinLock(&pAd->IndirectUpdateLock); +#endif + + RTMP_IO_READ32(pAd, 0x816c, &Value); + if((Value & (1 << 1)) == (1 << 1)) + { + Value &= ~(1 << 1); + DBGPRINT(RT_DEBUG_ERROR, ("@@@ %s: This Reset Result may be old! force clean result first! \n", __FUNCTION__)); + RTMP_IO_WRITE32(pAd, 0x816c, Value); + } + + RTMP_IO_READ32(pAd, 0x816c, &Value); + Value |= (1 << 0); + RTMP_IO_WRITE32(pAd, 0x816c, Value); + + do + { + RTMP_IO_READ32(pAd, 0x816c, &Value); + + if((Value & (1 << 1)) == (1 << 1)) + { + Value &= ~(1 << 1); + RTMP_IO_WRITE32(pAd, 0x816c, Value); + break; + } + RtmpOsMsDelay(1); + Loop++; + } while (Loop <= 500); + + if (Loop > 500) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: PSE Reset Fail(%x)\n", __FUNCTION__, Value)); + +#ifdef RTMP_PCI_SUPPORT + /*Dump the PSE CRs*/ + { + UINT32 RemapBase, RemapOffset; + UINT32 Value; + UINT32 RestoreValue; + + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: START ============== PSE CR dump ===================\n", __FUNCTION__)); + + RTMP_IO_READ32(pAd, 0x816c, &Value); + DBGPRINT(RT_DEBUG_ERROR, ("mac [0x816c] = 0x%08x\n", Value)); + RTMP_IO_READ32(pAd, 0x8170, &Value); + DBGPRINT(RT_DEBUG_ERROR, ("mac [0x8170] = 0x%08x\n", Value)); + + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + RemapBase = GET_REMAP_2_BASE(0x800c0070) << 19; + RemapOffset = GET_REMAP_2_OFFSET(0x800c0070); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + DBGPRINT(RT_DEBUG_ERROR, ("rw 3 : mac [0x800c0070] = 0x%08x\n", Value)); + + //RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + RemapBase = GET_REMAP_2_BASE(0x800c006c) << 19; + RemapOffset = GET_REMAP_2_OFFSET(0x800c006c); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + + // write 3 + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, 3); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + DBGPRINT(RT_DEBUG_ERROR, ("rw 3 : mac [0x800c006c] = 0x%08x\n", Value)); + + // write 4 + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, 4); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + DBGPRINT(RT_DEBUG_ERROR, ("rw 4 : mac [0x800c006c] = 0x%08x\n", Value)); + + // write 5 + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, 5); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + DBGPRINT(RT_DEBUG_ERROR, ("rw 5 : mac [0x800c006c] = 0x%08x\n", Value)); + + // write 6 + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, 6); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + DBGPRINT(RT_DEBUG_ERROR, ("rw 6 :mac [0x800c006c] = 0x%08x\n", Value)); + + // write 7 + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, 7); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + DBGPRINT(RT_DEBUG_ERROR, ("rw 7 :mac [0x800c006c] = 0x%08x\n", Value)); + + // write 8 + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, 8); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + DBGPRINT(RT_DEBUG_ERROR, ("rw 8 :mac [0x800c006c] = 0x%08x\n", Value)); + + // write 9 + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, 9); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + DBGPRINT(RT_DEBUG_ERROR, ("rw 9 :mac [0x800c006c] = 0x%08x\n", Value)); + + // write a + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, 0xa); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + DBGPRINT(RT_DEBUG_ERROR, ("rw a :mac [0x800c006c] = 0x%08x\n", Value)); + + // write b + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, 0xb); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + DBGPRINT(RT_DEBUG_ERROR, ("rw b :mac [0x800c006c] = 0x%08x\n", Value)); + + // write c + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, 0xc); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + DBGPRINT(RT_DEBUG_ERROR, ("rw c :mac [0x800c006c] = 0x%08x\n", Value)); + + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); + DBGPRINT(RT_DEBUG_ERROR, ("%s: END ============== PSE CR dump ===================\n", __FUNCTION__)); + + } + } +#endif /* RTMP_PCI_SUPPORT */ + +#ifdef DMA_RESET_SUPPORT + + RTMP_IO_READ32(pAd, 0x816c, &Value); + if ((Value & (1 << 0)) == (1 << 0)) + { + DBGPRINT(RT_DEBUG_ERROR, ("@@@ %s: Host Poll Fail !! Try to abort this PSE reset to F/W!! \n", __FUNCTION__)); + Value &= ~(1 << 0); + RTMP_IO_WRITE32(pAd, 0x816c, Value); + } + + if (pAd->PSEResetFailRecover == FALSE) + { + pAd->PSEResetFailRecover = TRUE; + pAd->PSEResetFailRetryQuota = 3; // start to count down + } + else + { + if (pAd->PSEResetFailRetryQuota) + pAd->PSEResetFailRetryQuota --; + + if (pAd->PSEResetFailRetryQuota == 0) // reach the quota + { + pAd->PSEResetFailRecover = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s: PSE Reset Retry Reach Quota!!\n", __FUNCTION__)); + } + } +#endif /* DMA_RESET_SUPPORT */ + + pAd->PSEResetFailCount++; + + +#ifdef RTMP_PCI_SUPPORT + NdisReleaseSpinLock(&pAd->IndirectUpdateLock); +#endif + + return; + + } +#ifdef DMA_RESET_SUPPORT + else //Reset Success + { + if (pAd->PSEResetFailRecover) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: PSE Reset Recover Back!!\n", __FUNCTION__)); + } + + pAd->PSEResetFailRecover = FALSE; + pAd->PSEResetFailRetryQuota = 0; + } + + //clear the AC / Mgmt Hit event. + RTMP_IO_READ32(pAd, 0x816c, &Value); + if((Value & (1 << 2)) == (1 << 2)) + { + Value &= ~(1 << 2); + RTMP_IO_WRITE32(pAd, 0x816c, Value); + } + + if((Value & (1 << 3)) == (1 << 3)) + { + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, 0x816c, Value); + } + if((Value & (1 << 4)) == (1 << 4)) + { + Value &= ~(1 << 4); + RTMP_IO_WRITE32(pAd, 0x816c, Value); + } + + if((Value & (1 << 5)) == (1 << 5)) + { + Value &= ~(1 << 5); + RTMP_IO_WRITE32(pAd, 0x816c, Value); + } + + if((Value & (1 << 6)) == (1 << 6)) + { + Value &= ~(1 << 6); + RTMP_IO_WRITE32(pAd, 0x816c, Value); + } +#endif /* DMA_RESET_SUPPORT */ + + +#ifdef RTMP_PCI_SUPPORT + NdisReleaseSpinLock(&pAd->IndirectUpdateLock); +#endif + + PDMAResetAndRecovery(pAd); +} + + + +#ifdef DMA_RESET_SUPPORT +VOID PSEACStuckWatchDog(RTMP_ADAPTER *pAd) +{ + UINT32 Value; + + RTMP_IO_READ32(pAd, 0x816c, &Value); + + //AC + if((Value & (1 << 2)) == (1 << 2)) + { + //clear after reset + //Value &= ~(1 << 2); + //RTMP_IO_WRITE32(pAd, 0x816c, Value); + if ( +#ifdef MAX_CONTINOUS_TX_CNT + pAd->ContinousTxCnt != 1 || +#endif + pAd->ed_on == TRUE) { + pAd->pse_reset_flag = FALSE; + Value &= ~(1 << 2); + RTMP_IO_WRITE32(pAd, 0x816c, Value); + DBGPRINT(RT_DEBUG_OFF, ("Ignore HIT AC0 ! pAd->ed_on = %d\n", pAd->ed_on)); +#ifdef MAX_CONTINOUS_TX_CNT + DBGPRINT(RT_DEBUG_OFF, ("pAd->ContinousTxCnt = %d\n", pAd->ContinousTxCnt)); +#endif + } else { + DBGPRINT(RT_DEBUG_OFF, ("HIT AC0 !\n")); + + pAd->AC0HitCount++; + pAd->pse_reset_flag = TRUE; + } + } + + + if((Value & (1 << 3)) == (1 << 3)) + { + //clear after reset + //Value &= ~(1 << 3); + //RTMP_IO_WRITE32(pAd, 0x816c, Value); + if ( +#ifdef MAX_CONTINOUS_TX_CNT + pAd->ContinousTxCnt != 1 || +#endif + pAd->ed_on == TRUE) { + pAd->pse_reset_flag = FALSE; + Value &= ~(1 << 3); + RTMP_IO_WRITE32(pAd, 0x816c, Value); + DBGPRINT(RT_DEBUG_OFF, ("Ignore HIT AC1 ! pAd->ed_on = %d\n", pAd->ed_on)); +#ifdef MAX_CONTINOUS_TX_CNT + DBGPRINT(RT_DEBUG_OFF, ("pAd->ContinousTxCnt = %d\n", pAd->ContinousTxCnt)); +#endif + } else { + DBGPRINT(RT_DEBUG_OFF, ("HIT AC1 !\n")); + + pAd->AC1HitCount++; + pAd->pse_reset_flag = TRUE; + } + } + + if((Value & (1 << 4)) == (1 << 4)) + { + //clear after reset + //Value &= ~(1 << 4); + //RTMP_IO_WRITE32(pAd, 0x816c, Value); + if ( +#ifdef MAX_CONTINOUS_TX_CNT + pAd->ContinousTxCnt != 1 || +#endif + pAd->ed_on == TRUE) { + pAd->pse_reset_flag = FALSE; + Value &= ~(1 << 4); + RTMP_IO_WRITE32(pAd, 0x816c, Value); + DBGPRINT(RT_DEBUG_OFF, ("Ignore HIT AC2 ! pAd->ed_on = %d\n", pAd->ed_on)); +#ifdef MAX_CONTINOUS_TX_CNT + DBGPRINT(RT_DEBUG_OFF, ("pAd->ContinousTxCnt = %d\n", pAd->ContinousTxCnt)); +#endif + } else { + DBGPRINT(RT_DEBUG_OFF, ("HIT AC2 !\n")); + + pAd->AC2HitCount++; + pAd->pse_reset_flag = TRUE; + } + } + + + if((Value & (1 << 5)) == (1 << 5)) + { + //clear after reset + //Value &= ~(1 << 5); + //RTMP_IO_WRITE32(pAd, 0x816c, Value); + if ( +#ifdef MAX_CONTINOUS_TX_CNT + pAd->ContinousTxCnt != 1 || +#endif + pAd->ed_on == TRUE) { + pAd->pse_reset_flag = FALSE; + Value &= ~(1 << 5); + RTMP_IO_WRITE32(pAd, 0x816c, Value); + DBGPRINT(RT_DEBUG_OFF, ("Ignore HIT AC3 ! pAd->ed_on = %d\n", pAd->ed_on)); +#ifdef MAX_CONTINOUS_TX_CNT + DBGPRINT(RT_DEBUG_OFF, ("pAd->ContinousTxCnt = %d\n", pAd->ContinousTxCnt)); +#endif + } else { + DBGPRINT(RT_DEBUG_OFF, ("HIT AC3 !\n")); + + pAd->AC3HitCount++; + pAd->pse_reset_flag = TRUE; + } + //return TRUE; + } + + + if((Value & (1 << 6)) == (1 << 6)) + { + //clear after reset + //Value &= ~(1 << 6); + //RTMP_IO_WRITE32(pAd, 0x816c, Value); + + if (RTDebugLevel >= RT_DEBUG_OFF) + printk("HIT MGMT !\n"); + + pAd->MgtHitCount ++; + pAd->pse_reset_flag = TRUE; + //return TRUE; + } + +} +#endif /* DMA_RESET_SUPPORT */ + +VOID PSEWatchDog(RTMP_ADAPTER *pAd) +{ + BOOLEAN NoDataIn = FALSE; + + NoDataIn = MonitorRxPse(pAd); + + if (((NoDataIn) +#ifdef DMA_RESET_SUPPORT + || ((pAd->bcn_reset_en) && (pAd->pse_reset_flag)) + || ((pAd->PSEResetFailRecover) && (pAd->PSEResetFailRetryQuota)) +#endif + ) + && (pAd->pse_reset_exclude_flag == FALSE)) + { + DBGPRINT(RT_DEBUG_OFF, ("PSE Reset: MonitorRxPse\n")); + DBGPRINT(RT_DEBUG_OFF, ("NoDataIn = %d, bcn_reset_en = %d, pse_reset_flag = %d\n", + NoDataIn, pAd->bcn_reset_en, pAd->pse_reset_flag)); + DBGPRINT(RT_DEBUG_OFF, ("PSEResetFailRecover = %d, PSEResetFailRetryQuota = %ld\n", + pAd->PSEResetFailRecover, pAd->PSEResetFailRetryQuota)); + pAd->PSEResetCount++; + goto reset; + } + +/*MT7628's case may not apply to MT7603 */ + + return; + +reset: +#ifdef DMA_RESET_SUPPORT + pAd->pse_reset_flag=TRUE; +#endif + pAd->pse_reset_exclude_flag = TRUE; + PSEResetAndRecovery(pAd); + pAd->pse_reset_exclude_flag = FALSE; + +#ifdef DMA_RESET_SUPPORT + pAd->pse_reset_flag=FALSE; +#endif +} + + +/*************************************************************************** + * + * register related procedures. + * + **************************************************************************/ +/* +======================================================================== +Routine Description: + Disable DMA. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT28XXDMADisable(RTMP_ADAPTER *pAd) +{ + AsicSetWPDMA(pAd, PDMA_TX_RX, FALSE); +} + + +/* +======================================================================== +Routine Description: + Enable DMA. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT28XXDMAEnable(RTMP_ADAPTER *pAd) +{ + AsicSetMacTxRx(pAd, ASIC_MAC_TX, TRUE); + AsicWaitPDMAIdle(pAd, 200, 1000); + + RtmpusecDelay(50); + + AsicSetWPDMA(pAd, PDMA_TX_RX, TRUE); + + DBGPRINT(RT_DEBUG_TRACE, ("<== %s(): WPDMABurstSIZE = %d\n", __FUNCTION__, pAd->chipCap.WPDMABurstSIZE)); +} + + +BOOLEAN AsicCheckCommanOk(RTMP_ADAPTER *pAd, UCHAR Command) +{ + BOOLEAN status = FALSE; + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return TRUE; + } + + + + + return status; +} + + +#ifdef MT_MAC +VOID RT28xx_UpdateBeaconToAsic( + IN RTMP_ADAPTER *pAd, + IN INT apidx, + IN ULONG FrameLen, + IN ULONG UpdatePos) +{ + BCN_BUF_STRUC *bcn_buf = NULL; + UCHAR *buf/*, *hdr*/; + INT len; + PNDIS_PACKET *pkt = NULL; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { + bcn_buf = &pAd->ApCfg.MBSSID[apidx].bcn_buf; + } +#endif /* CONFIG_AP_SUPPORT */ + + + if (!bcn_buf) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): bcn_buf is NULL!\n", __FUNCTION__)); + return; + } + + pkt = bcn_buf->BeaconPkt; + if (pkt) { + buf = (UCHAR *)GET_OS_PKT_DATAPTR(pkt); + len = FrameLen + pAd->chipCap.tx_hw_hdr_len; + SET_OS_PKT_LEN(pkt, len); +#ifdef RT_BIG_ENDIAN + MTMacInfoEndianChange(pAd, buf, TYPE_TMACINFO, sizeof(TMAC_TXD_L)); +#endif /* RT_BIG_ENDIAN */ + /* Now do hardware-depened kick out.*/ + RTMP_SEM_LOCK(&pAd->BcnRingLock); + HAL_KickOutMgmtTx(pAd, Q_IDX_BCN, pkt, buf, len); + bcn_buf->bcn_state = BCN_TX_WRITE_TO_DMA; + RTMP_SEM_UNLOCK(&pAd->BcnRingLock); + } else { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): BeaconPkt is NULL!\n", __FUNCTION__)); + } +} +#endif /* MT_MAC */ + + +#if defined(RTMP_MAC) || defined(RLT_MAC) +/* +======================================================================== +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; + INT wr_bytes = 1; + UCHAR *pBeaconFrame, *tmac_info; + UCHAR tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len; + + if (IS_MT76x2(pAd)) + wr_bytes = 4; + +#ifdef CONFIG_AP_SUPPORT + if (apidx < pAd->ApCfg.BssidNum && + apidx < HW_BEACON_MAX_NUM && + (pAd->OpMode == OPMODE_AP) + ) + { + BSS_STRUCT *pMbss; + + pMbss = &pAd->ApCfg.MBSSID[apidx]; + bcn_idx = pMbss->bcn_buf.BcnBufIdx; + CapInfoPos = pMbss->bcn_buf.cap_ie_pos; + bBcnReq = BeaconTransmitRequired(pAd, apidx, pMbss); + + if (wr_bytes > 1) { + CapInfoPos = (CapInfoPos & (~(wr_bytes - 1))); + UpdatePos = (UpdatePos & (~(wr_bytes - 1))); + } + + tmac_info = (UCHAR *)GET_OS_PKT_DATAPTR(pMbss->bcn_buf.BeaconPkt); + pBeaconFrame = (UCHAR *)(tmac_info + TXWISize); + + ptr_capinfo = (PUCHAR)(pBeaconFrame + CapInfoPos); + ptr_update = (PUCHAR)(pBeaconFrame + UpdatePos); + } + else +#endif /* CONFIG_AP_SUPPORT */ + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Invalid Interface\n", __FUNCTION__)); + return; + } + + if (pAd->BeaconOffset[bcn_idx] == 0) { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Invalid BcnOffset[%d]\n", + __FUNCTION__, bcn_idx)); + 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 = tmac_info; + +#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 += wr_bytes) + { + RTMP_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[bcn_idx] + TXWISize + i, *((UINT32 *)ptr_capinfo), wr_bytes); + ptr_capinfo += wr_bytes; + } + + if (FrameLen > UpdatePos) + { + for (i = UpdatePos; i < (FrameLen); i += wr_bytes) + { + UINT32 longptr = *ptr_update + (*(ptr_update+1)<<8) + (*(ptr_update+2)<<16) + (*(ptr_update+3)<<24); + RTMP_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[bcn_idx] + TXWISize + i, longptr, wr_bytes); + ptr_update += wr_bytes; + } + } + } +} +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + + + +/* + ========================================================================== + Description: + This routine sends command to firmware and turn our chip to wake up mode from power save mode. + Both RadioOn and .11 power save function needs to call this routine. + Input: + Level = GUIRADIO_OFF : call this function is from Radio Off to Radio On. Need to restore PCI host value. + Level = other value : normal wake up function. + + ========================================================================== + */ +BOOLEAN RT28xxPciAsicRadioOn(RTMP_ADAPTER *pAd, UCHAR Level) +{ + + if (pAd->OpMode == OPMODE_AP && Level==DOT11POWERSAVE) + return FALSE; + + + /* 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*/ + /* 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); + + } + else + { + /* In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.*/ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + AsicSwitchChannel(pAd, pAd->CommonCfg.CentralChannel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.CentralChannel); + } +#endif /* CONFIG_AP_SUPPORT */ + } + } + return TRUE; + +} + + +/* + ========================================================================== + Description: + This routine sends command to firmware and turn our chip to power save mode. + Both RadioOff and .11 power save function needs to call this routine. + Input: + Level = GUIRADIO_OFF : GUI Radio Off mode + Level = DOT11POWERSAVE : 802.11 power save mode + Level = RTMP_HALT : When Disable device. + + ========================================================================== + */ +BOOLEAN RT28xxPciAsicRadioOff( + IN RTMP_ADAPTER *pAd, + IN UCHAR Level, + IN USHORT TbttNumToNextWakeUp) +{ +#if defined(RTMP_MAC) || defined(RLT_MAC) + UINT32 RxDmaIdx, RxCpuIdx; +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(): Not support for HIF_MT yet!\n", + __FUNCTION__)); + return FALSE; + } + +#if defined(RTMP_MAC) || defined(RLT_MAC) + DBGPRINT(RT_DEBUG_TRACE, ("%s ===> Lv= %d, TxCpuIdx = %d, TxDmaIdx = %d. RxCpuIdx = %d, RxDmaIdx = %d.\n", + __FUNCTION__, Level,pAd->TxRing[0].TxCpuIdx, pAd->TxRing[0].TxDmaIdx, + pAd->RxRing[0].RxCpuIdx, pAd->RxRing[0].RxDmaIdx)); + + if (pAd->OpMode == OPMODE_AP && Level==DOT11POWERSAVE) + return FALSE; + + if (Level == DOT11POWERSAVE) + { + /* Check Rx DMA busy status, if more than half is occupied, give up this radio off.*/ + RTMP_IO_READ32(pAd, pAd->RxRing[0].hw_didx_addr, &RxDmaIdx); + RTMP_IO_READ32(pAd, pAd->RxRing[0].hw_cidx_addr, &RxCpuIdx); + if ((RxDmaIdx > RxCpuIdx) && ((RxDmaIdx - RxCpuIdx) > RX_RING_SIZE/3)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): return1. RxDmaIdx=%d, RxCpuIdx=%d\n", + __FUNCTION__, RxDmaIdx, RxCpuIdx)); + return FALSE; + } + else if ((RxCpuIdx >= RxDmaIdx) && ((RxCpuIdx - RxDmaIdx) < RX_RING_SIZE/3)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): return2. RxDmaIdx=%d, RxCpuIdx=%d\n", + __FUNCTION__, RxDmaIdx, RxCpuIdx)); + return FALSE; + } + } + + + /* Once go into this function, disable tx because don't want too many packets in queue to prevent HW stops.*/ + /*pAd->bPCIclkOffDisableTx = TRUE;*/ + /*pAd->bPCIclkOffDisableTx = FALSE;*/ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); + + + /* In Radio Off, we turn off RF clk, So now need to call ASICSwitchChannel again.*/ + AsicTurnOffRFClk(pAd, pAd->CommonCfg.Channel); + + if (Level != RTMP_HALT) + { + UINT32 AutoWakeupInt = 0; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + AutoWakeupInt = RLT_AutoWakeupInt; +#endif /* RLT_MAC*/ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + AutoWakeupInt = RTMP_AutoWakeupInt; +#endif /* RTMP_MAC */ + /* + Change Interrupt bitmask. + When PCI clock is off, don't want to service interrupt. + */ + RTMP_IO_WRITE32(pAd, INT_MASK_CSR, AutoWakeupInt); + } + else + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) + RTMP_ASIC_INTERRUPT_DISABLE(pAd); + } + + RTMP_IO_WRITE32(pAd, pAd->RxRing[0].hw_cidx_addr, pAd->RxRing[0].RxCpuIdx); + /* 2. Send Sleep command */ + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_STATUS, 0xffffffff); + RTMP_IO_WRITE32(pAd, H2M_MAILBOX_CID, 0xffffffff); + /* send POWER-SAVE command to MCU. high-byte = 1 save power as much as possible. high byte = 0 save less power*/ + AsicSendCommandToMcu(pAd, SLEEP_MCU_CMD, PowerSafeCID, 0xff, 0x1, FALSE); + + + +/* 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);*/ + + 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); + } + + + /*pAd->bPCIclkOffDisableTx = FALSE;*/ + +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + return TRUE; +} + + +VOID PciMlmeRadioOn(RTMP_ADAPTER *pAd) +{ +#ifdef LOAD_FW_ONE_TIME + { + UINT32 value; + RTMP_IO_READ32(pAd, AGG_TEMP, &value); + value &= 0x0000ffff; + RTMP_IO_WRITE32(pAd, AGG_TEMP, value); + } +#endif /* LOAD_FW_ONE_TIME */ + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + + DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __FUNCTION__)); + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + MTPciMlmeRadioOn(pAd); + return; + } +#endif /* MT_MAC */ + +#if defined(RTMP_MAC) || defined(RLT_MAC) + + + if ((pAd->OpMode == OPMODE_AP) || + ((pAd->OpMode == OPMODE_STA) + )) + { + 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_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 + 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 */ + } + + +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ +} + + +VOID PciMlmeRadioOFF(RTMP_ADAPTER *pAd) +{ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + + DBGPRINT(RT_DEBUG_TRACE,("%s===>\n", __FUNCTION__)); + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + MTPciMlmeRadioOff(pAd); + return; + } +#endif /* MT_MAC */ + +#if defined(RTMP_MAC) || defined(RLT_MAC) + + + /* Set Radio off flag*/ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + + +#ifdef CONFIG_AP_SUPPORT +#ifdef AP_SCAN_SUPPORT + { + BOOLEAN Cancelled; + RTMPCancelTimer(&pAd->ScanCtrl.APScanTimer, &Cancelled); + } +#endif /* AP_SCAN_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef LED_CONTROL_SUPPORT + RTMPSetLED(pAd, LED_RADIO_OFF); +#endif /* LED_CONTROL_SUPPORT */ + +#ifdef RTMP_PCI_SUPPORT + if (pAd->infType == RTMP_DEV_INF_PCI || pAd->infType == RTMP_DEV_INF_PCIE) + { + { + if (RT28xxPciAsicRadioOff(pAd, GUIRADIO_OFF, 0) ==FALSE) + { + DBGPRINT(RT_DEBUG_ERROR,("%s call RT28xxPciAsicRadioOff fail !!\n", __FUNCTION__)); + } + } + } +#endif /* RTMP_PCI_SUPPORT */ + + +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + +} + + +/* +======================================================================== +Routine Description: + Get a pci map buffer. + +Arguments: + pAd - WLAN control block pointer + *ptr - Virtual address or TX control block + size - buffer size + sd_idx - 1: the ptr is TX control block + direction - RTMP_PCI_DMA_TODEVICE or RTMP_PCI_DMA_FROMDEVICE + +Return Value: + the PCI map buffer + +Note: +======================================================================== +*/ +ra_dma_addr_t RtmpDrvPciMapSingle( + IN RTMP_ADAPTER *pAd, + IN VOID *ptr, + IN size_t size, + IN INT sd_idx, + IN INT direction) +{ + ra_dma_addr_t SrcBufPA; + + if (sd_idx == 1) + { + TX_BLK *pTxBlk = (TX_BLK *)(ptr); + + if (pTxBlk->SrcBufLen) + { + SrcBufPA = linux_pci_map_single(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev,pTxBlk->pSrcBufData, pTxBlk->SrcBufLen, 0, direction); + } + else + { + return 0; + } + + } + else + { + SrcBufPA = linux_pci_map_single(((POS_COOKIE)(pAd->OS_Cookie))->pci_dev, + ptr, size, 0, direction); + } + + + if (dma_mapping_error(&((POS_COOKIE)(pAd->OS_Cookie))->pci_dev->dev, SrcBufPA)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s: dma mapping error\n", __FUNCTION__)); + return 0; + } + else + { + return SrcBufPA; + } +} + + +int write_reg(RTMP_ADAPTER *ad, UINT32 base, UINT16 offset, UINT32 value) +{ + // TODO: shiang-7603 + if (ad->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(): Not support for HIF_MT yet!\n", + __FUNCTION__)); + return FALSE; + } + + if (base == 0x40) + RTMP_IO_WRITE32(ad, 0x10000 + offset, value); + else if (base == 0x41) + RTMP_IO_WRITE32(ad, offset, value); + else + DBGPRINT(RT_DEBUG_OFF, ("illegal base = %x\n", base)); + + return 0; +} + + +int read_reg(RTMP_ADAPTER *ad, UINT32 base, UINT16 offset, UINT32 *value) +{ + // TODO: shiang-7603 + if (ad->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(): Not support for HIF_MT yet!\n", + __FUNCTION__)); + return FALSE; + } + + if (base == 0x40) { + RTMP_IO_READ32(ad, 0x10000 + offset, value); + } else if (base == 0x41) { + RTMP_IO_READ32(ad, offset, value); + } else { + DBGPRINT(RT_DEBUG_OFF, ("illegal base = %x\n", base)); + } + return 0; +} + + +INT rtmp_irq_init(RTMP_ADAPTER *pAd) +{ + unsigned long irqFlags; + UINT32 reg_mask = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + reg_mask = (RLT_DELAYINTMASK) |(RLT_RxINT|RLT_TxDataInt|RLT_TxMgmtInt); +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + reg_mask = ((RTMP_DELAYINTMASK) |(RTMP_RxINT|RTMP_TxDataInt|RTMP_TxMgmtInt)) & ~(0x03); +#endif /* RTMP_MAC */ + +#ifdef MT_MAC + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) + reg_mask = ((MT_DELAYINTMASK) |(MT_RxINT|MT_TxDataInt|MT_TxMgmtInt)|MT_INT_BMC_DLY); +#endif /* MT_MAC */ + + RTMP_INT_LOCK(&pAd->irq_lock, irqFlags); + pAd->int_enable_reg = reg_mask; + pAd->int_disable_mask = 0; + pAd->int_pending = 0; + RTMP_INT_UNLOCK(&pAd->irq_lock, irqFlags); + + return 0; +} + +#endif /* RTMP_MAC_PCI */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mac_sdio.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mac_sdio.c new file mode 100644 index 000000000..5915647d2 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mac_sdio.c @@ -0,0 +1,170 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +#include "rt_config.h" + +VOID RT28xx_UpdateBeaconToAsic( + RTMP_ADAPTER *pAd, + INT apidx, + ULONG FrameLen, + ULONG UpdatePos) +{ + +} + + +VOID RTMPResetTxRxRingMemory(RTMP_ADAPTER *pAd) +{ +} + + +VOID RTMPFreeTxRxRingMemory(RTMP_ADAPTER *pAd) +{ + UINT32 Index; + + for (Index = 0; Index < NUM_OF_TX_RING; Index++) + { + NdisFreeSpinLock(&SDIOTxPacketListLock[Index]); + } +} + + +NDIS_STATUS RTMPAllocTxRxRingMemory(RTMP_ADAPTER *pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + INT32 Index; + ULONG ErrorValue = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("-->RTMPAllocTxRxRingMemory\n")); + + + for (Index = 0; Index < NUM_OF_TX_RING; Index++) + { + NdisAllocateSpinLock(pAd, &pAd->SDIOTxPacketListLock[Index]); + } + + /* Alloc MGMT ring desc buffer except Tx ring allocated eariler */ + + + /* Alloc Beacon ring desc buffer */ + + /* Allocate Tx ring descriptor's memory (BMC)*/ + + /* Alloc RX ring desc memory except Tx ring allocated eariler */ + + + + DBGPRINT_S(("<-- RTMPAllocTxRxRingMemory, Status=%x\n", Status)); + + return Status; +} + + +NDIS_STATUS RTMPInitTxRxRingMemory(RTMP_ADAPTER *pAd) +{ + NDIS_STATUS Status; + UINT32 Index; + unsigned long Flags; + + for (Index = 0; Index < NUM_OF_TX_RING; Index++) + { + /* + * (5 TX rings = 4 ACs + 1 HCCA) + */ + RTMP_SPIN_LOCK_IRQSAVE(&pAd->SDIOTxPacketListLock[Index], &Flags); + DlListInit(&pAd->SDIOTxPacketList[Index]); + RTMP_SPIN_UNLOCK_IRQRESTORE(&pAd->SDIOTxPacketListLock[Index], &Flags); + } + + return Status; +} + + +/* +======================================================================== +Routine Description: + Disable DMA. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT28XXDMADisable( + IN RTMP_ADAPTER *pAd) +{ + /* no use*/ +} + + +/* +======================================================================== +Routine Description: + Enable DMA. + +Arguments: + *pAd the raxx interface data pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RT28XXDMAEnable(RTMP_ADAPTER *pAd) +{ + +} + + +/******************************************************************** + * + * SDIO Radio on/off Related functions. + * + ********************************************************************/ +VOID RT28xxSdioMlmeRadioOn( + IN PRTMP_ADAPTER pAd) +{ +} + + +VOID RT28xxSdioMlmeRadioOFF( + IN PRTMP_ADAPTER pAd) +{ +} + + +VOID RT28xxSdioAsicRadioOff(RTMP_ADAPTER *pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("--> %s\n", __FUNCTION__)); + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); + + DBGPRINT(RT_DEBUG_TRACE, ("<== %s\n", __FUNCTION__)); + +} + + +VOID RT28xxSdioAsicRadioOn(RTMP_ADAPTER *pAd) +{ + /* make some traffic to invoke EvtDeviceD0Entry callback function*/ + + DBGPRINT(RT_DEBUG_TRACE, ("<== %s\n", __FUNCTION__)); +} + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mat.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mat.c new file mode 100644 index 000000000..54aca4ab0 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mat.c @@ -0,0 +1,474 @@ +/* + *************************************************************************** + * 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; + + if (pMatStruct->nodeCount >= 128) + { + return NULL; + } + else + { + os_alloc_mem(NULL, (PUCHAR *)&pPtr, size); + } + +#endif + + return (PUCHAR)pPtr; +} + + +VOID dumpPkt(PUCHAR pHeader, int len) +{ + +#ifdef DBG + int i; + RTMP_STRING *tmp; + + tmp = (RTMP_STRING *)pHeader; + + DBGPRINT(RT_DEBUG_OFF, ("--StartDump\n")); + for(i=0;iPointer to our adapter + pPkt =>pointer to the 802.11 header of outgoing packet + ifIdx =>Interface Index want to dispatch to. + + Return Value: + Success => + TRUE + Mapped mac address if found, else return specific default mac address + depends on the upper layer protocol type. + Error => + FALSE. + + Note: + 1.the pPktHdr must be a 802.3 packet. + 2.Maybe we need a TxD arguments? + 3.We check every packet here including group mac address becasue we need to + handle DHCP packet. + ======================================================================== + */ +PUCHAR MATEngineTxHandle( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPkt, + IN UINT ifIdx, + IN UCHAR OpMode) +{ + PUCHAR pLayerHdr = NULL, pPktHdr = NULL, pMacAddr = NULL; + UINT16 protoType, protoType_ori; + INT i; + struct _MATProtoOps *pHandle = NULL; + PUCHAR retSkb = NULL; + BOOLEAN bVLANPkt = FALSE; + + + if(pAd->MatCfg.status != MAT_ENGINE_STAT_INITED) + return NULL; + + pPktHdr = GET_OS_PKT_DATAPTR(pPkt); + if (!pPktHdr) + return NULL; + + protoType_ori = get_unaligned((PUINT16)(pPktHdr + 12)); + + /* Get the upper layer protocol type of this 802.3 pkt. */ + protoType = OS_NTOHS(protoType_ori); + + /* handle 802.1q enabled packet. Skip the VLAN tag field to get the protocol type. */ + if (protoType == 0x8100) + { + protoType_ori = get_unaligned((PUINT16)(pPktHdr + 12 + 4)); + protoType = OS_NTOHS(protoType_ori); + bVLANPkt = TRUE; + } + + + /* For differnet protocol, dispatch to specific handler */ + for (i=0; i < MAX_MAT_SUPPORT_PROTO_NUM; i++) + { + if (protoType == MATProtoTb[i].protocol) + { + pHandle = MATProtoTb[i].pHandle; /* the pHandle must not be null! */ + pLayerHdr = bVLANPkt ? (pPktHdr + MAT_VLAN_ETH_HDR_LEN) : (pPktHdr + MAT_ETHER_HDR_LEN); +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef MAC_REPEATER_SUPPORT + UCHAR tempIdx = ifIdx; + UCHAR CliIdx = 0xFF; + + if (tempIdx >= 64) + { + CliIdx = ((tempIdx - 64) % 16); + tempIdx = ((tempIdx - 64) / 16); + + pMacAddr = &pAd->ApCfg.ApCliTab[tempIdx].RepeaterCli[CliIdx].CurrentAddress[0]; + } + else +#endif /* MAC_REPEATER_SUPPORT */ + pMacAddr = &pAd->ApCfg.ApCliTab[ifIdx].wdev.if_addr[0]; + } +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + + if (pHandle->tx!=NULL) + retSkb = pHandle->tx((PVOID)&pAd->MatCfg, RTPKT_TO_OSPKT(pPkt), pLayerHdr, pMacAddr); + + return retSkb; + } + } + return retSkb; +} + + +/* + ======================================================================== + Routine Description: + Depends on the Received packet, check the upper layer protocol type + and search for specific mapping table to find out the real destination + MAC address. + + Arguments: + pAd =>Pointer to our adapter + pPkt =>pointer to the 802.11 header of receviced packet + infIdx =>Interface Index want to dispatch to. + + Return Value: + Success => + Mapped mac address if found, else return specific default mac address + depends on the upper layer protocol type. + Error => + NULL + + Note: + ======================================================================== + */ +PUCHAR MATEngineRxHandle( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPkt, + IN UINT infIdx) +{ + PUCHAR pMacAddr = NULL; + PUCHAR pLayerHdr = NULL, pPktHdr = NULL; + UINT16 protoType; + INT i =0; + struct _MATProtoOps *pHandle = NULL; + + + if(pAd->MatCfg.status != MAT_ENGINE_STAT_INITED) + return NULL; + + pPktHdr = GET_OS_PKT_DATAPTR(pPkt); + if (!pPktHdr) + return NULL; + + /* If it's a multicast/broadcast packet, we do nothing. */ + if (IS_GROUP_MAC(pPktHdr)) + return NULL; + + /* Get the upper layer protocol type of this 802.3 pkt and dispatch to specific handler */ + protoType = OS_NTOHS(get_unaligned((PUINT16)(pPktHdr + 12))); + + for (i=0; irx!=NULL) + pMacAddr = pHandle->rx((PVOID)&pAd->MatCfg, RTPKT_TO_OSPKT(pPkt), pLayerHdr, NULL); +/* RTMP_SEM_UNLOCK(&MATDBLock); */ + break; + } + } + + if (pMacAddr) + NdisMoveMemory(pPktHdr, pMacAddr, MAC_ADDR_LEN); + + return NULL; + +} + + +BOOLEAN MATPktRxNeedConvert( + IN PRTMP_ADAPTER pAd, + IN PNET_DEV net_dev) +{ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + int i = 0; + + /* Check if the packet will be send to apcli interface. */ + while(iApCfg.ApCliTab[i].Valid == TRUE) + && (net_dev == pAd->ApCfg.ApCliTab[i].wdev.if_dev) +#ifdef A4_CONN + && (IS_APCLI_A4(&pAd->ApCfg.ApCliTab[i]) == FALSE) +#endif /* A4_CONN */ + ){ + return TRUE; + } + i++; + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_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. */ + os_alloc_mem_suspend(NULL, (UCHAR **)&(pAd->MatCfg.pMATNodeEntryPoll), sizeof(MATNodeEntry) * MAX_MAT_NODE_ENTRY_NUM); + if (pAd->MatCfg.pMATNodeEntryPoll != NULL) + { + MATNodeEntry *pPtr=NULL; + + NdisZeroMemory(pAd->MatCfg.pMATNodeEntryPoll, sizeof(MATNodeEntry) * MAX_MAT_NODE_ENTRY_NUM); + pPtr = pAd->MatCfg.pMATNodeEntryPoll; + for (i = 0; i < (MAX_MAT_NODE_ENTRY_NUM -1); i++) + { + pPtr->next = (MATNodeEntry *)(pPtr+1); + pPtr = pPtr->next; + } + pPtr->next = NULL; + } else { + return FALSE; + } +#endif + + /* For each specific protocol, call it's init function. */ + for (i = 0; i < MAX_MAT_SUPPORT_PROTO_NUM; i++) + { + pHandle = MATProtoTb[i].pHandle; + ASSERT(pHandle); + if (pHandle->init != NULL) + { + status = pHandle->init(&pAd->MatCfg); + if (status == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, ("MATEngine Init Protocol (0x%x) failed, Stop the MAT Funciton initialization failed!\n", MATProtoTb[i].protocol)); + goto init_failed; + } + DBGPRINT(RT_DEBUG_TRACE, ("MATEngine Init Protocol (0x%04x) success!\n", MATProtoTb[i].protocol)); + } + } + + NdisAllocateSpinLock(pAd, &pAd->MatCfg.MATDBLock); +#ifdef MAC_REPEATER_SUPPORT + pAd->MatCfg.bMACRepeaterEn = FALSE; +#endif /* MAC_REPEATER_SUPPORT */ + pAd->MatCfg.pPriv = (VOID *)pAd; + pAd->MatCfg.status = MAT_ENGINE_STAT_INITED; + + return TRUE; + +init_failed: + /* For each specific protocol, call it's exit function. */ + for (i = 0; i < MAX_MAT_SUPPORT_PROTO_NUM; i++) + { + if ((pHandle = MATProtoTb[i].pHandle) != NULL) + { + if (pHandle->exit != NULL) + { + status = pHandle->exit(&pAd->MatCfg); + if (status == FALSE) + goto init_failed; + } + } + } + +#ifdef KMALLOC_BATCH + if (pAd->MatCfg.pMATNodeEntryPoll) + os_free_mem(pAd, pAd->MatCfg.pMATNodeEntryPoll); + pAd->MatCfg.status = MAT_ENGINE_STAT_EXITED; +#endif /* KMALLOC_BATCH */ + + return FALSE; + +} + +#endif /* MAT_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mat_iparp.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mat_iparp.c new file mode 100644 index 000000000..1c5422a34 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mat_iparp.c @@ -0,0 +1,807 @@ +/* + *************************************************************************** + * 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; + } + } + } + + + /* 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); + } + } + } + DBGPRINT(RT_DEBUG_TRACE, ("%s() Set nodeCount to 0,nodeCount = %d\n", __FUNCTION__, pMatCfg->nodeCount)); + pMatCfg->nodeCount = 0; + 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 + { + 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; + } + + 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; + USHORT wcid = 0xFF; + PMAC_TABLE_ENTRY pEntry = NULL; + PREPEATER_CLIENT_ENTRY pReptEntry = NULL; +#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; + } + + wcid = RTMP_GET_PACKET_WCID(pSkb); + + pEntry = &pAd->MacTab.Content[wcid]; + pReptEntry = &pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].RepeaterCli[pEntry->MatchReptCliIdx]; + + if (pAd->ApCfg.bMACRepeaterEn) + { + if (pEntry->bReptCli) + { + UINT ip; + + ip = ntohl(dstIP); + + /* avoid duplicate packet in IGMP case */ + if (IS_MULTICAST_IP(ip)) + return pReptEntry->OriginalAddress; + } + + + if ((pAd->ApCfg.MACRepeaterOuiMode != 1)) + { + 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; + 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->func_tb_idx)); + } + bHdrChanged = TRUE; + } + + if (bHdrChanged == TRUE) + NdisZeroMemory((pUdpHdr+6), 2); /*modify the UDP chksum as zero */ + } + } + } + } +#endif /* MAC_REPEATER_SUPPORT */ + + return pMacAddr; +} + +static UCHAR DHCP_MAGIC[]= {0x63, 0x82, 0x53, 0x63}; +static PUCHAR MATProto_IP_Tx( + IN MAT_STRUCT *pMatCfg, + IN PNDIS_PACKET pSkb, + IN PUCHAR pLayerHdr, + IN PUCHAR pDevMacAdr) +{ + PUCHAR pSrcMac; + PUCHAR pSrcIP; + BOOLEAN needUpdate; + PUCHAR pPktHdr; + + 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) + { + UCHAR isLinkValid; + + if (RTMPLookupRepeaterCliEntry(pMatCfg->pPriv, FALSE, pDevMacAdr, TRUE, &isLinkValid) != NULL) + { + NdisMoveMemory((bootpHdr+28), pDevMacAdr, MAC_ADDR_LEN); + + if (NdisEqualMemory(dhcpHdr, DHCP_MAGIC, 4)) + { + PUCHAR pOptCode, pOptLen; + UINT16 udpLen; + + udpLen = OS_NTOHS(get_unaligned((PUINT16)(udpHdr+4))); + pOptCode = (dhcpHdr + 4); + do + { + pOptLen = pOptCode + 1; + if (*pOptCode == 61) /* Client Identifier */ + { + DBGPRINT(RT_DEBUG_TRACE, + ("Client Identifier found, change Hardware Address to " + "%02x:%02x:%02x:%02x:%02x:%02x\n", + pDevMacAdr[0], pDevMacAdr[1], pDevMacAdr[2], + pDevMacAdr[3], pDevMacAdr[4], pDevMacAdr[5])); + /* Change Hardware Address */ + NdisMoveMemory((pOptCode+3), pDevMacAdr, MAC_ADDR_LEN); + break; + } + pOptCode += (2+*pOptLen); + }while ((*pOptCode != 0xFF) && ((pOptCode - udpHdr) <= udpLen)); + } + bHdrChanged = TRUE; + } + } +#endif /* MAC_REPEATER_SUPPORT */ + } + + if (bHdrChanged == TRUE) + NdisZeroMemory((udpHdr+6), 2); /* Modify the UDP chksum as zero */ + } + + return 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/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mat_ipv6.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mat_ipv6.c new file mode 100644 index 000000000..5a7076d80 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mat_ipv6.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-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; + } + } + } + + + /* 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); + } + } + } + + 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 + { + os_alloc_mem_suspend(NULL, (UCHAR **)&(pMatCfg->MatTableSet.IPv6MacTable), sizeof(IPv6MacMappingTable)); + if (pMatCfg->MatTableSet.IPv6MacTable) + { + pIPv6MacTable = (IPv6MacMappingTable *)pMatCfg->MatTableSet.IPv6MacTable; + NdisZeroMemory(pIPv6MacTable, sizeof(IPv6MacMappingTable)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("IPMacTable_init(): Allocate memory for IPv6MacTable failed!\n")); + return FALSE; + } + } + + if (pIPv6MacTable->valid == FALSE) + { + /*Set the last hash entry (hash[64]) as our default broadcast Mac address */ + pEntry = (IPv6MacMappingEntry *)MATDBEntryAlloc(pMatCfg, sizeof(IPv6MacMappingEntry)); + if (!pEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("IPMacTable_init(): Allocate memory for IPMacTable broadcast entry failed!\n")); + return FALSE; + } + NdisZeroMemory(pEntry, sizeof(IPv6MacMappingEntry)); + NdisMoveMemory(pEntry->macAddr, BROADCAST_ADDR, MAC_ADDR_LEN); + pEntry->pNext = NULL; + pIPv6MacTable->hash[IPV6MAC_TB_HASH_INDEX_OF_BCAST] = pEntry; + + pIPv6MacTable->valid = TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): IPv6MacTable already inited!\n", __FUNCTION__)); + } + + return TRUE; + +} + + +static NDIS_STATUS MATProto_IPv6_Exit( + IN MAT_STRUCT *pMatCfg) +{ + INT status; + + status = IPv6MacTable_RemoveAll(pMatCfg); + + return status; +} + + +static NDIS_STATUS MATProto_IPv6_Init( + IN MAT_STRUCT *pMatCfg) +{ + + BOOLEAN status = FALSE; + + status = IPv6MacTable_init(pMatCfg); + + return status; +} + + + +VOID getIPv6MacTbInfo( + IN MAT_STRUCT *pMatCfg, + IN char *pOutBuf, + IN ULONG BufLen) +{ + IPv6MacMappingTable *pIPv6MacTable; + IPv6MacMappingEntry *pHead; + int startIdx, endIdx; + char Ipv6str[40] = {0}; + + + pIPv6MacTable = (IPv6MacMappingTable *)pMatCfg->MatTableSet.IPv6MacTable; + if ((!pIPv6MacTable) || (!pIPv6MacTable->valid)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s():IPv6MacTable not init yet!\n", __FUNCTION__)); + return; + } + + + /* dump all. */ + startIdx = 0; + endIdx = MAT_MAX_HASH_ENTRY_SUPPORT; + + sprintf(pOutBuf, "\n"); + sprintf(pOutBuf+strlen(pOutBuf), "%-40s%-20s\n", "IP", "MAC"); + for(; startIdx< endIdx; startIdx++) + { + pHead = pIPv6MacTable->hash[startIdx]; + + while(pHead) + { +/* if (strlen(pOutBuf) > (IW_PRIV_SIZE_MASK - 30)) */ + if (RtmpOsCmdDisplayLenCheck(strlen(pOutBuf), 30) == FALSE) + break; + NdisZeroMemory(Ipv6str, 40); + sprintf(Ipv6str, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", PRINT_IPV6_ADDR(*((RT_IPV6_ADDR *)(&pHead->ipv6Addr[0])))); + sprintf(pOutBuf+strlen(pOutBuf), "%-40s%02x:%02x:%02x:%02x:%02x:%02x\n", + Ipv6str, pHead->macAddr[0],pHead->macAddr[1],pHead->macAddr[2], + pHead->macAddr[3],pHead->macAddr[4],pHead->macAddr[5]); + pHead = pHead->pNext; + } + } +} + +#endif /* MAT_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mat_pppoe.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mat_pppoe.c new file mode 100644 index 000000000..0a4ac82dd --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_mat_pppoe.c @@ -0,0 +1,1058 @@ +/* + *************************************************************************** + * 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); + } + } + } + + 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); + } + } + } + + 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; + } + } + } + } + + + /* 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; + } + } + } + + + /* 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) + { + 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) + { + os_alloc_mem_suspend(NULL, (UCHAR **)&(pMatCfg->MatTableSet.SesMacTable), sizeof(SesMacMappingTable)); + if (pMatCfg->MatTableSet.SesMacTable) + { + pSesMacTable = (SesMacMappingTable *)pMatCfg->MatTableSet.SesMacTable; + NdisZeroMemory(pSesMacTable, sizeof(SesMacMappingTable)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("MATProto_PPPoEDis_Init(): Allocate memory for SesMacTable failed!\n")); + return FALSE; + } + + } + pSesMacTable->valid = TRUE; + + return TRUE; +} + + +/* PPPoE discovery stage exit function */ +static NDIS_STATUS MATProto_PPPoEDis_Exit( + IN MAT_STRUCT *pMatCfg) +{ + UidMacTable_RemoveAll(pMatCfg); + SesMacTable_RemoveAll(pMatCfg); + + return TRUE; +} + + +/* PPPoE Session stage Rx handler + When we receive a ppp pakcet, first check if the srcMac is a PPPoE server or not. + if it's a server, check the session ID of specific PPPoEServeryEntry and find out the + correct dstMac Address. + if it's not a server, check the session ID and find out the cor + + */ +static PUCHAR MATProto_PPPoESes_Rx( + IN MAT_STRUCT *pMatCfg, + IN PNDIS_PACKET pSkb, + IN PUCHAR pLayerHdr, + IN PUCHAR pDevMacAdr) +{ + PUCHAR srcMac, dstMac = NULL, pData; + UINT16 sesID; + + srcMac = (GET_OS_PKT_DATAPTR(pSkb) + 6); + pData = pLayerHdr; + + /*skip the first two bytes.(version/Type/Code) */ + pData += 2; + + /*get the session ID */ + sesID = OS_NTOHS(get_unaligned((PUINT16)(pData))); + + /* Try to find the dstMac from SesMacHash table. */ + dstMac = getInMacByOutMacFromSesMacTb(pMatCfg, srcMac, sesID); + + return dstMac; +} + +/* PPPoE Session stage Tx handler */ +static PUCHAR MATProto_PPPoESes_Tx( + IN MAT_STRUCT *pMatStruct, + IN PNDIS_PACKET pSkb, + IN PUCHAR pLayerHdr, + IN PUCHAR pDevMacAdr) +{ + + /* + For transmit packet, we do nothing. + */ + return NULL; +} + + +/* PPPoE session stage init function */ +static NDIS_STATUS MATProto_PPPoESes_Init( + IN MAT_STRUCT *pMatStruct) +{ + return TRUE; +} + +/* PPPoE session stage exit function */ +static NDIS_STATUS MATProto_PPPoESes_Exit( + IN MAT_STRUCT *pMatStruct) +{ + + return TRUE; +} + +#endif /* MAT_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_profile.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_profile.c new file mode 100644 index 000000000..9db37955c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_profile.c @@ -0,0 +1,5440 @@ +/**************************************************************************** + * 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(RTMP_STRING *s1, RTMP_STRING *s2) +{ + int i = 0; + RTMP_STRING *ptokS = s1, *ptokE = s1; + + if (strlen(s1) != ETH_MAC_ADDR_STR_LEN) + return FALSE; + + while((*ptokS) != '\0') + { + if((ptokE = strchr(ptokS, ':')) != NULL) + *ptokE++ = '\0'; + if ((strlen(ptokS) != 2) || (!isxdigit(*ptokS)) || (!isxdigit(*(ptokS+1)))) + break; /* fail*/ + AtoH(ptokS, (PUCHAR)&s2[i++], 1); + ptokS = ptokE; + if (ptokS == NULL) + break; + if (i == 6) + break; /* parsing finished*/ + } + + return ( i == 6 ? TRUE : FALSE); + +} + + +#define ASC_LOWER(_x) ((((_x) >= 0x41) && ((_x) <= 0x5a)) ? (_x) + 0x20 : (_x)) +/* we assume the s1 and s2 both are strings.*/ +BOOLEAN rtstrcasecmp(RTMP_STRING *s1, RTMP_STRING *s2) +{ + RTMP_STRING *p1 = s1, *p2 = s2; + CHAR c1, c2; + + if (strlen(s1) != strlen(s2)) + return FALSE; + + while(*p1 != '\0') + { + c1 = ASC_LOWER(*p1); + c2 = ASC_LOWER(*p2); + if(c1 != c2) + return FALSE; + p1++; + p2++; + } + + return TRUE; +} + + +/* we assume the s1 (buffer) and s2 (key) both are strings.*/ +RTMP_STRING *rtstrstruncasecmp(RTMP_STRING *s1, RTMP_STRING *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 (RTMP_STRING *)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. + */ +RTMP_STRING *__rstrtok; +RTMP_STRING *rstrtok(RTMP_STRING *s,const RTMP_STRING *ct) +{ + RTMP_STRING *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(RTMP_STRING *s,RTMP_STRING *ct) +{ + INT count = 0; + /* point to the beginning of the line */ + RTMP_STRING *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(const RTMP_STRING *cp, unsigned int *addr) +{ + unsigned int val; + int base, n; + RTMP_STRING c; + unsigned int parts[4]={0}; + 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 + ======================================================================== +*/ +RTMP_STRING *RTMPFindSection(RTMP_STRING *buffer) +{ + RTMP_STRING temp_buf[32]; + RTMP_STRING *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 RTMP_STRING *key, + OUT RTMP_STRING *dest, + IN INT destsize, + IN RTMP_STRING *buffer, + IN BOOLEAN bTrimSpace) +{ + RTMP_STRING *pMemBuf, *temp_buf1 = NULL, *temp_buf2 = NULL; + RTMP_STRING *start_ptr, *end_ptr; + RTMP_STRING *ptr; + RTMP_STRING *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 = (RTMP_STRING *)(pMemBuf + MAX_PARAM_BUFFER_SIZE); + + + /*find section*/ + if((offset = RTMPFindSection(buffer)) == NULL) + { + os_free_mem(NULL, (PUCHAR)pMemBuf); + return (FALSE); + } + + strcpy(temp_buf1, "\n"); + strcat(temp_buf1, key); + strcat(temp_buf1, "="); + + /*search key*/ + if((start_ptr=rtstrstr(offset, temp_buf1)) == NULL) + { + os_free_mem(NULL, (PUCHAR)pMemBuf); + return (FALSE); + } + + start_ptr += strlen("\n"); + if((end_ptr = rtstrstr(start_ptr, "\n"))==NULL) + end_ptr = start_ptr+strlen(start_ptr); + + if (end_ptr= pAd->ApCfg.BssidNum) + break; + + KeyIdx = simple_strtol(macptr, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + pAd->ApCfg.MBSSID[i].wdev.DefaultKeyId = (UCHAR) (KeyIdx - 1 ); + else + pAd->ApCfg.MBSSID[i].wdev.DefaultKeyId = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) DefaultKeyID(0~3)=%d\n", i, pAd->ApCfg.MBSSID[i].wdev.DefaultKeyId)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + + } + + + for (idx = 0; idx < 4; idx++) + { + snprintf(tok_str, sizeof(tok_str), "Key%dType", idx + 1); + /*Key1Type*/ + if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + /* + do sanity check for KeyType length; + or in station mode, the KeyType length > 1, + the code will overwrite the stack of caller + (RTMPSetProfileParameters) and cause srcbuf = NULL + */ + if (i < MAX_MBSSID_NUM(pAd)) + KeyType[i] = simple_strtol(macptr, 0, 10); + } +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (TRUE) + { + BOOLEAN bKeyxStryIsUsed = FALSE; + + //GPRINT(RT_DEBUG_TRACE, ("pAd->ApCfg.BssidNum=%d\n", pAd->ApCfg.BssidNum)); + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + snprintf(tok_str, sizeof(tok_str), "Key%dStr%d", idx + 1, i + 1); + if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, FALSE)) + { + rtmp_parse_key_buffer_from_file(pAd, tmpbuf, KeyType[i], i, idx); + + if (bKeyxStryIsUsed == FALSE) + bKeyxStryIsUsed = TRUE; + } + } + + if (bKeyxStryIsUsed == FALSE) + { + snprintf(tok_str, sizeof(tok_str), "Key%dStr", idx + 1); + if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, FALSE)) + { + if (pAd->ApCfg.BssidNum == 1) + { + rtmp_parse_key_buffer_from_file(pAd, tmpbuf, KeyType[BSS0], BSS0, idx); + } + else + { + /* Anyway, we still do the legacy dissection of the whole KeyxStr string.*/ + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + rtmp_parse_key_buffer_from_file(pAd, macptr, KeyType[i], i, idx); + } + } + } + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + + } + } +} + +#ifdef CONFIG_AP_SUPPORT + +#ifdef APCLI_SUPPORT +static void rtmp_read_ap_client_from_file( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *tmpbuf, + IN RTMP_STRING *buffer) +{ + RTMP_STRING *macptr = NULL; + INT i=0, j=0, idx; + UCHAR macAddress[MAC_ADDR_LEN]; + PAPCLI_STRUCT pApCliEntry = NULL; + ULONG KeyIdx; + RTMP_STRING tok_str[16]; + ULONG KeyType[MAX_APCLI_NUM]; + ULONG KeyLen; + struct wifi_dev *wdev; +#ifdef APCLI_SAE_SUPPORT + INT boundary = 65; +#endif + + NdisZeroMemory(KeyType, sizeof(KeyType)); + +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef DOT11W_PMF_SUPPORT + for (i = 0; i < MAX_APCLI_NUM; i++) { + pAd->ApCfg.ApCliTab[i].PmfCfg.Desired_MFPC = FALSE; + pAd->ApCfg.ApCliTab[i].PmfCfg.Desired_MFPR = FALSE; + pAd->ApCfg.ApCliTab[i].PmfCfg.Desired_PMFSHA256 = FALSE; + } +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + + /*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; + + DBGPRINT(RT_DEBUG_TRACE, ("ApCliEntry[%d].Enable=%d\n", i, pApCliEntry->Enable)); + } + } + + /*ApCliSsid*/ + if(RTMPGetKeyParameter("ApCliSsid", tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, FALSE)) + { + for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + + /*Ssid acceptable strlen must be less than 32 and bigger than 0.*/ + pApCliEntry->CfgSsidLen = (UCHAR)strlen(macptr); + if (pApCliEntry->CfgSsidLen > 32) + { + pApCliEntry->CfgSsidLen = 0; + continue; + } + if(pApCliEntry->CfgSsidLen > 0) + { + memcpy(&pApCliEntry->CfgSsid, macptr, pApCliEntry->CfgSsidLen); + pApCliEntry->Valid = FALSE;/* it should be set when successfuley association*/ + } else + { + NdisZeroMemory(&(pApCliEntry->CfgSsid), MAX_LEN_OF_SSID); + continue; + } + DBGPRINT(RT_DEBUG_TRACE, ("ApCliEntry[%d].CfgSsidLen=%d, CfgSsid=%s\n", i, pApCliEntry->CfgSsidLen, pApCliEntry->CfgSsid)); + } + } + +#ifdef WH_EZ_SETUP + /*ApCliHideSSID*/ + if(RTMPGetKeyParameter("ApCliHideSSID", 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->CfgHideSsidLen = (UCHAR)strlen(macptr); + if (pApCliEntry->CfgHideSsidLen > 32) + { + pApCliEntry->CfgHideSsidLen = 0; + continue; + } + if(pApCliEntry->CfgHideSsidLen > 0) + { + memcpy(&pApCliEntry->CfgHideSsid, macptr, pApCliEntry->CfgHideSsidLen); + pApCliEntry->Valid = FALSE;/* it should be set when successfuley association*/ + } else + { + NdisZeroMemory(&(pApCliEntry->CfgHideSsid), MAX_LEN_OF_SSID); + continue; + } + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("ApCliEntry[%d].CfgHideSsidLen=%d, CfgSsid=%s\n", i, pApCliEntry->CfgHideSsidLen, pApCliEntry->CfgHideSsid)); + } + } +#endif + + /*ApCliBssid*/ + if(RTMPGetKeyParameter("ApCliBssid", tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, TRUE)) + { + for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + + NdisZeroMemory(&(pApCliEntry->CfgApCliBssid), MAC_ADDR_LEN); + + if(strlen(macptr) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17*/ + continue; + if(strcmp(macptr,"00:00:00:00:00:00") == 0) + continue; + for (j=0; jCfgApCliBssid, &macAddress, MAC_ADDR_LEN); + pApCliEntry->Valid = FALSE;/* it should be set when successfuley association*/ + } + } + + /*ApCliAuthMode*/ + if (RTMPGetKeyParameter("ApCliAuthMode", tmpbuf, 255, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + wdev = &pApCliEntry->wdev; + + if (rtstrcasecmp(macptr, "WEPAUTO") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeAutoSwitch; + else if (rtstrcasecmp(macptr, "SHARED") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeShared; + else if (rtstrcasecmp(macptr, "WPAPSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPAPSK; + else if (rtstrcasecmp(macptr, "WPA2PSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA2PSK; +#ifdef APCLI_SAE_SUPPORT + else if (rtstrcasecmp(macptr, "WPA3PSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA3PSK; + else if (rtstrcasecmp(macptr, "WPA2PSKWPA3PSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA3PSK; + /* WPA3PSK has transition function in station mode */ +#endif /* APCLI_SAE_SUPPORT */ +#ifdef APCLI_OWE_SUPPORT + else if (rtstrcasecmp(macptr, "OWE") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeOWE; +#endif + else + wdev->AuthMode = Ndis802_11AuthModeOpen; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) ApCli_AuthMode=%d \n", i, wdev->AuthMode)); + RTMPMakeRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, (i + MIN_NET_DEVICE_FOR_APCLI)); + } + + } + + /*ApCliEncrypType*/ + if (RTMPGetKeyParameter("ApCliEncrypType", tmpbuf, 255, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + wdev = &pApCliEntry->wdev; + + wdev->WepStatus = Ndis802_11WEPDisabled; + if (rtstrcasecmp(macptr, "WEP") == TRUE) + { + if (wdev->AuthMode < Ndis802_11AuthModeWPA) + wdev->WepStatus = Ndis802_11WEPEnabled; + } + else if (rtstrcasecmp(macptr, "TKIP") == TRUE) + { + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + wdev->WepStatus = Ndis802_11TKIPEnable; + } + else if (rtstrcasecmp(macptr, "AES") == TRUE) + { + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + wdev->WepStatus = Ndis802_11AESEnable; + } +#ifdef APCLI_OWE_SUPPORT + else if (rtstrcasecmp(macptr, "CCMP128") == TRUE) + wdev->WepStatus = Ndis802_11CCMP128Enable; + else if (rtstrcasecmp(macptr, "CCMP256") == TRUE) + wdev->WepStatus = Ndis802_11CCMP256Enable; +#endif + else + { + wdev->WepStatus = Ndis802_11WEPDisabled; + } + + pApCliEntry->PairCipher = wdev->WepStatus; + pApCliEntry->GroupCipher = wdev->WepStatus; + pApCliEntry->bMixCipher = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) APCli_EncrypType = %d \n", i, wdev->WepStatus)); + RTMPMakeRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, (i + MIN_NET_DEVICE_FOR_APCLI)); + } + + } + + /*ApCliWPAPSK*/ + 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; + } +#ifdef APCLI_SAE_SUPPORT + + if (pApCliEntry->wdev.AuthMode == Ndis802_11AuthModeWPA3PSK) + boundary = LEN_MAX_WPA3PSK_PSD + 1; + else + boundary = LEN_MAX_WPA2PSK_PSD + 1; + + if (strlen(macptr) >= boundary) { + DBGPRINT(RT_DEBUG_ERROR, + ("APCli_WPAPSK_KEY, key string required <64 characters for SAE!!!\n")); + continue; + } + +#endif + + 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->wdev.AuthMode != Ndis802_11AuthModeWPAPSK) && + (pApCliEntry->wdev.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 + } + } + +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef DOT11W_PMF_SUPPORT + /* Protection Management Frame Capable */ + if (RTMPGetKeyParameter("ApCliPMFMFPC", tmpbuf, 32, buffer, TRUE)) { + for (i = 0, macptr = rstrtok(tmpbuf, ";"); + (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL, ";"), + i++) { + Set_ApCliPMFMFPC_Proc(pAd, macptr); + } + } + + /* Protection Management Frame Required */ + if (RTMPGetKeyParameter("ApCliPMFMFPR", tmpbuf, 32, buffer, TRUE)) { + for (i = 0, macptr = rstrtok(tmpbuf, ";"); + (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL, ";"), + i++) { + Set_ApCliPMFMFPR_Proc(pAd, macptr); + } + } + + if (RTMPGetKeyParameter("ApCliPMFSHA256", tmpbuf, 32, buffer, TRUE)) { + for (i = 0, macptr = rstrtok(tmpbuf, ";"); + (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL, ";"), + i++) { + Set_ApCliPMFSHA256_Proc(pAd, macptr); + } + } +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + + /*ApCliDefaultKeyID*/ + if (RTMPGetKeyParameter("ApCliDefaultKeyID", tmpbuf, 255, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + wdev = &pAd->ApCfg.ApCliTab[i].wdev; + + KeyIdx = simple_strtol(macptr, 0, 10); + if((KeyIdx >= 1 ) && (KeyIdx <= 4)) + wdev->DefaultKeyId = (UCHAR) (KeyIdx - 1); + else + wdev->DefaultKeyId = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) DefaultKeyID(0~3)=%d\n", i, wdev->DefaultKeyId)); + } + } + + /*ApCliKeyXType, ApCliKeyXStr*/ + for (idx=0; idx<4; idx++) + { + snprintf(tok_str, sizeof(tok_str), "ApCliKey%dType", idx+1); + /*ApCliKey1Type*/ + if(RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + KeyType[i] = simple_strtol(macptr, 0, 10); + } + + snprintf(tok_str, sizeof(tok_str), "ApCliKey%dStr", idx+1); + /*ApCliKey1Str*/ + if(RTMPGetKeyParameter(tok_str, tmpbuf, 512, buffer, FALSE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + KeyLen = strlen(macptr); + if(((KeyType[i] == 0) && (KeyLen != 10) && (KeyLen != 26)) || + ((KeyType[i] != 0) && (KeyLen != 5) && (KeyLen != 13))) + { + DBGPRINT(RT_DEBUG_ERROR, ("I/F(apcli%d) Key%dStr is Invalid key length!\n", i, idx+1)); + } + else + { + if (RT_CfgSetWepKey(pAd, macptr, &pApCliEntry->SharedKey[idx], idx) != TRUE) + DBGPRINT(RT_DEBUG_ERROR, ("RT_CfgSetWepKey fail!\n")); + } + } + } + } + } + + /* ApCliTxMode*/ + if (RTMPGetKeyParameter("ApCliTxMode", tmpbuf, 25, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + wdev = &pAd->ApCfg.ApCliTab[i].wdev; + + wdev->DesiredTransmitSetting.field.FixedTxMode = + RT_CfgSetFixedTxPhyMode(macptr); + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Tx Mode = %d\n", i, + wdev->DesiredTransmitSetting.field.FixedTxMode)); + } + } + + /* ApCliTxMcs*/ + if (RTMPGetKeyParameter("ApCliTxMcs", tmpbuf, 50, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_APCLI_NUM); macptr = rstrtok(NULL,";"), i++) + { + wdev = &pAd->ApCfg.ApCliTab[i].wdev; + + wdev->DesiredTransmitSetting.field.MCS = + RT_CfgSetTxMCSProc(macptr, &wdev->bAutoTxRateSwitch); + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) Tx MCS = %s(%d)\n", i, + (wdev->DesiredTransmitSetting.field.MCS == MCS_AUTO ? "AUTO" : ""), + wdev->DesiredTransmitSetting.field.MCS)); + } + } + + +#ifdef WSC_AP_SUPPORT + /* Wsc4digitPinCode = TRUE use 4-digit Pin code, otherwise 8-digit Pin code */ + if (RTMPGetKeyParameter("ApCli_Wsc4digitPinCode", tmpbuf, 32, buffer, TRUE)) + { + if (simple_strtol(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)); + } + +#ifdef APCLI_SUPPORT + /* ApCliWscScanMode */ + if (RTMPGetKeyParameter("ApCliWscScanMode", tmpbuf, 32, buffer, TRUE)) { + UCHAR Mode; + + Mode = simple_strtol(tmpbuf, 0, 10); + if (Mode != TRIGGER_PARTIAL_SCAN) + Mode = TRIGGER_FULL_SCAN; + + pAd->ApCfg.ApCliTab[i].WscControl.WscApCliScanMode = Mode; + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli%d) WscApCliScanMode=%d\n", i, Mode)); + } +#endif /* APCLI_SUPPORT */ +#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->wdev.UapsdInfo.bAPSDCapable = \ + (UCHAR) simple_strtol(macptr, 0, 10); + DBGPRINT(RT_DEBUG_ERROR, ("ApCliAPSDCapable[%d]=%d\n", i, + pApCliEntry->wdev.UapsdInfo.bAPSDCapable)); + } + } +#endif /* UAPSD_SUPPORT */ + + /* ApCliNum */ + if(RTMPGetKeyParameter("ApCliNum", tmpbuf, 10, buffer, TRUE)) + { + if (simple_strtol(tmpbuf, 0, 10) <= MAX_APCLI_NUM) + { + pAd->ApCfg.ApCliNum = simple_strtol(tmpbuf, 0, 10); + } + DBGPRINT(RT_DEBUG_TRACE, ("I/F(apcli) ApCliNum=%d\n", pAd->ApCfg.ApCliNum)); + } + + +} +#endif /* APCLI_SUPPORT */ + + +static void rtmp_read_acl_parms_from_file(RTMP_ADAPTER *pAd, RTMP_STRING *tmpbuf, RTMP_STRING *buffer) +{ + RTMP_STRING tok_str[32], *macptr; + INT i=0, j=0, idx; + UCHAR macAddress[MAC_ADDR_LEN]; + + + memset(macAddress, 0, MAC_ADDR_LEN); + for (idx=0; idxApCfg.MBSSID[idx].AccessControlList, 0, sizeof(RT_802_11_ACL)); + /* AccessPolicyX*/ + snprintf(tok_str, sizeof(tok_str), "AccessPolicy%d", idx); + if (RTMPGetKeyParameter(tok_str, tmpbuf, 10, buffer, TRUE)) + { + switch (simple_strtol(tmpbuf, 0, 10)) + { + case 1: /* Allow All, and the AccessControlList is positive now.*/ + pAd->ApCfg.MBSSID[idx].AccessControlList.Policy = 1; + break; + case 2: /* Reject All, and the AccessControlList is negative now.*/ + pAd->ApCfg.MBSSID[idx].AccessControlList.Policy = 2; + break; + case 0: /* Disable, don't care the AccessControlList.*/ + default: + pAd->ApCfg.MBSSID[idx].AccessControlList.Policy = 0; + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s=%ld\n", tok_str, pAd->ApCfg.MBSSID[idx].AccessControlList.Policy)); + } + /* AccessControlListX*/ + snprintf(tok_str, sizeof(tok_str), "AccessControlList%d", idx); + if (RTMPGetKeyParameter(tok_str, tmpbuf, MAX_PARAM_BUFFER_SIZE, buffer, TRUE)) + { + for (i=0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (strlen(macptr) != 17) /* Mac address acceptable format 01:02:03:04:05:06 length 17*/ + continue; + + ASSERT(pAd->ApCfg.MBSSID[idx].AccessControlList.Num <= MAX_NUM_OF_ACL_LIST); + + for (j=0; jApCfg.MBSSID[idx].AccessControlList.Num == MAX_NUM_OF_ACL_LIST) + { + DBGPRINT(RT_DEBUG_WARN, ("The AccessControlList is full, and no more entry can join the list!\n")); + DBGPRINT(RT_DEBUG_WARN, ("The last entry of ACL is %02x:%02x:%02x:%02x:%02x:%02x\n", + macAddress[0],macAddress[1],macAddress[2],macAddress[3],macAddress[4],macAddress[5])); + + break; + } + + pAd->ApCfg.MBSSID[idx].AccessControlList.Num++; + NdisMoveMemory(pAd->ApCfg.MBSSID[idx].AccessControlList.Entry[(pAd->ApCfg.MBSSID[idx].AccessControlList.Num - 1)].Addr, macAddress, MAC_ADDR_LEN); + } + DBGPRINT(RT_DEBUG_TRACE, ("%s=Get %ld Mac Address\n", tok_str, pAd->ApCfg.MBSSID[idx].AccessControlList.Num)); + } + } +} + +/* + ======================================================================== + + Routine Description: + In kernel mode read parameters from file + + Arguments: + src the location of the file. + dest put the parameters to the destination. + Length size to read. + + Return Value: + None + + Note: + + ======================================================================== +*/ +static void rtmp_read_ap_wmm_parms_from_file(RTMP_ADAPTER *pAd, RTMP_STRING *tmpbuf, RTMP_STRING *buffer) +{ + RTMP_STRING *macptr; + INT i=0; + + /*WmmCapable*/ + if(RTMPGetKeyParameter("WmmCapable", tmpbuf, 32, buffer, TRUE)) + { + BOOLEAN bEnableWmm = FALSE; + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i >= pAd->ApCfg.BssidNum) + { + break; + } + + if(simple_strtol(macptr, 0, 10) != 0) + { + pAd->ApCfg.MBSSID[i].wdev.bWmmCapable = TRUE; + bEnableWmm = TRUE; + } + else + { + pAd->ApCfg.MBSSID[i].wdev.bWmmCapable = FALSE; + } + + if (bEnableWmm) + { + pAd->CommonCfg.APEdcaParm.bValid = TRUE; + pAd->ApCfg.BssEdcaParm.bValid = TRUE; + } + else + { + pAd->CommonCfg.APEdcaParm.bValid = FALSE; + pAd->ApCfg.BssEdcaParm.bValid = FALSE; + } + + pAd->ApCfg.MBSSID[i].bWmmCapableOrg = \ + pAd->ApCfg.MBSSID[i].wdev.bWmmCapable; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WmmCapable=%d\n", i, pAd->ApCfg.MBSSID[i].wdev.bWmmCapable)); + } + } + /*DLSCapable*/ + if(RTMPGetKeyParameter("DLSCapable", tmpbuf, 32, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i >= pAd->ApCfg.BssidNum) + { + break; + } + + if(simple_strtol(macptr, 0, 10) != 0) /*Enable*/ + { + pAd->ApCfg.MBSSID[i].bDLSCapable = TRUE; + } + else /*Disable*/ + { + pAd->ApCfg.MBSSID[i].bDLSCapable = FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) DLSCapable=%d\n", i, pAd->ApCfg.MBSSID[i].bDLSCapable)); + } + } + /*APAifsn*/ + if(RTMPGetKeyParameter("APAifsn", tmpbuf, 32, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->CommonCfg.APEdcaParm.Aifsn[i] = (UCHAR) simple_strtol(macptr, 0, 10);; + + DBGPRINT(RT_DEBUG_TRACE, ("APAifsn[%d]=%d\n", i, pAd->CommonCfg.APEdcaParm.Aifsn[i])); + } + } + /*APCwmin*/ + if(RTMPGetKeyParameter("APCwmin", tmpbuf, 32, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->CommonCfg.APEdcaParm.Cwmin[i] = (UCHAR) simple_strtol(macptr, 0, 10);; + + 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].wdev.UapsdInfo.bAPSDCapable = \ + (UCHAR) simple_strtol(macptr, 0, 10); + DBGPRINT(RT_DEBUG_ERROR, ("APSDCapable[%d]=%d\n", i, + pAd->ApCfg.MBSSID[i].wdev.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].wdev.UapsdInfo.bAPSDCapable = + pAd->ApCfg.MBSSID[0].wdev.UapsdInfo.bAPSDCapable; + DBGPRINT(RT_DEBUG_ERROR, ("APSDCapable[%d]=%d\n", i, + pAd->ApCfg.MBSSID[i].wdev.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].wdev.UapsdInfo.bAPSDCapable = \ + pAd->ApCfg.MBSSID[0].wdev.UapsdInfo.bAPSDCapable; + DBGPRINT(RT_DEBUG_ERROR, ("default ApCliAPSDCapable[%d]=%d\n", + i, pAd->ApCfg.ApCliTab[i].wdev.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(RTMP_ADAPTER *pAd, RTMP_STRING *tmpbuf, RTMP_STRING *buffer) +{ + RTMP_STRING tok_str[16], *macptr; + UINT32 ip_addr; + INT i=0; + BOOLEAN bUsePrevFormat = FALSE; + USHORT offset; + INT count[HW_BEACON_MAX_NUM]; + + /* own_ip_addr*/ + if (RTMPGetKeyParameter("own_ip_addr", tmpbuf, 32, buffer, TRUE)) + { + Set_OwnIPAddr_Proc(pAd, tmpbuf); + } + + + /* session_timeout_interval*/ + if (RTMPGetKeyParameter("session_timeout_interval", tmpbuf, 32, buffer, TRUE)) + { + pAd->ApCfg.session_timeout_interval = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("session_timeout_interval=%d\n", pAd->ApCfg.session_timeout_interval)); + } + + /* quiet_interval*/ + if (RTMPGetKeyParameter("quiet_interval", tmpbuf, 32, buffer, TRUE)) + { + pAd->ApCfg.quiet_interval = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("quiet_interval=%d\n", pAd->ApCfg.quiet_interval)); + } + + /* EAPifname*/ + if (RTMPGetKeyParameter("EAPifname", tmpbuf, 256, buffer, TRUE)) + { + Set_EAPIfName_Proc(pAd, tmpbuf); + } + + /* PreAuthifname*/ + if (RTMPGetKeyParameter("PreAuthifname", tmpbuf, 256, buffer, TRUE)) + { + Set_PreAuthIfName_Proc(pAd, tmpbuf); + } + + /*PreAuth*/ + if(RTMPGetKeyParameter("PreAuth", tmpbuf, 10, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i >= pAd->ApCfg.BssidNum) + break; + + if(simple_strtol(macptr, 0, 10) != 0) /*Enable*/ + pAd->ApCfg.MBSSID[i].PreAuth = TRUE; + else /*Disable*/ + pAd->ApCfg.MBSSID[i].PreAuth = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) PreAuth=%d\n", i, pAd->ApCfg.MBSSID[i].PreAuth)); + } + } + + /*IEEE8021X*/ + if(RTMPGetKeyParameter("IEEE8021X", tmpbuf, 32, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i >= pAd->ApCfg.BssidNum) + break; + + if(simple_strtol(macptr, 0, 10) != 0) /*Enable*/ + pAd->ApCfg.MBSSID[i].wdev.IEEE8021X = TRUE; + else /*Disable*/ + pAd->ApCfg.MBSSID[i].wdev.IEEE8021X = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d), IEEE8021X=%d\n", i, pAd->ApCfg.MBSSID[i].wdev.IEEE8021X)); + } + } + + /* RADIUS_Server*/ + offset = 0; + /*if (RTMPGetKeyParameter("RADIUS_Server", tmpbuf, 256, buffer, TRUE))*/ + while (RTMPGetKeyParameterWithOffset("RADIUS_Server", tmpbuf, &offset, 256, buffer, TRUE)) + { + for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_MBSSID_NUM(pAd)); macptr = rstrtok(NULL,";"), i++) + { + if (rtinet_aton(macptr, &ip_addr) && pAd->ApCfg.MBSSID[i].radius_srv_num < MAX_RADIUS_SRV_NUM) + { + INT srv_idx = pAd->ApCfg.MBSSID[i].radius_srv_num; + + pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_ip = ip_addr; + pAd->ApCfg.MBSSID[i].radius_srv_num++; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d), radius_ip(seq-%d)=%s(%x)\n", i, pAd->ApCfg.MBSSID[i].radius_srv_num, macptr, pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_ip)); + } + } + } + /* RADIUS_Port*/ + /*if (RTMPGetKeyParameter("RADIUS_Port", tmpbuf, 128, buffer, TRUE))*/ + offset = 0; + memset(&count[0], 0, sizeof(count)); + while (RTMPGetKeyParameterWithOffset("RADIUS_Port", tmpbuf, &offset, 128, buffer, TRUE)) + { + for (i=0, macptr = rstrtok(tmpbuf,";"); (macptr && i < MAX_MBSSID_NUM(pAd)); macptr = rstrtok(NULL,";"), i++) + { + if (count[i] < pAd->ApCfg.MBSSID[i].radius_srv_num) + { + INT srv_idx = count[i]; + + pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_port = (UINT32) simple_strtol(macptr, 0, 10); + count[i] ++; + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d), radius_port(seq-%d)=%d\n", i, count[i], pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_port)); + } + } + } + /* RADIUS_Key*/ + /*if (RTMPGetKeyParameter("RADIUS_Key", tmpbuf, 640, buffer, FALSE))*/ + offset = 0; + memset(&count[0], 0, sizeof(count)); + while (RTMPGetKeyParameterWithOffset("RADIUS_Key1", 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, sizeof(pAd->ApCfg.MBSSID[i].radius_srv_info[srv_idx].radius_key)); + 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, sizeof(pAd->ApCfg.MBSSID[i].NasId)); + 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(RTMP_ADAPTER *pAd, RTMP_STRING *buffer, INT BSSIdx) +{ + RTMP_STRING *tmpbuf = buffer; + INT i = BSSIdx; + /*UCHAR keyMaterial[40];*/ + ULONG len = strlen(tmpbuf); + int ret = 0; +#if defined(DOT11_SAE_SUPPORT) + INT boundary = 65; +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WPAPSK_KEY=%s\n", i, tmpbuf)); + +#if defined(DOT11_SAE_SUPPORT) + + if (pAd->ApCfg.MBSSID[i].wdev.AuthMode == Ndis802_11AuthModeWPA3PSK + || pAd->ApCfg.MBSSID[i].wdev.AuthMode == Ndis802_11AuthModeWPA2PSKWPA3PSK) + boundary = LEN_MAX_WPA3PSK_PSD + 1; + else + boundary = LEN_MAX_WPA2PSK_PSD + 1; + + if (strlen(tmpbuf) < boundary) { + NdisMoveMemory(pAd->ApCfg.MBSSID[i].PSK, tmpbuf, strlen(tmpbuf)); + pAd->ApCfg.MBSSID[i].PSK[strlen(tmpbuf)] = '\0'; + } else { + pAd->ApCfg.MBSSID[i].PSK[0] = '\0'; + DBGPRINT(RT_DEBUG_ERROR, ("WPAPSK%dStr is Invalid key length! %d\n", i+1, strlen(tmpbuf))); + return FALSE; + } +#endif + + 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; + strcpy(pAd->ApCfg.MBSSID[i].WPAKeyString, tmpbuf); + +#ifdef WSC_AP_SUPPORT + NdisZeroMemory(pAd->ApCfg.MBSSID[i].WscControl.WpaPsk, 64); + pAd->ApCfg.MBSSID[i].WscControl.WpaPskLen = 0; + if ((len >= 8) && (len <= 64)) + { + NdisMoveMemory(pAd->ApCfg.MBSSID[i].WscControl.WpaPsk, tmpbuf, len); + pAd->ApCfg.MBSSID[i].WscControl.WpaPskLen = len; + } +#endif /* WSC_AP_SUPPORT */ + return ret; +} +#endif /* CONFIG_AP_SUPPORT */ + + + + +#ifdef DOT11_VHT_AC +static void VHTParametersHook( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *pValueStr, + IN RTMP_STRING *pInput) +{ + long Value; + + /* Channel Width */ + if (RTMPGetKeyParameter("VHT_BW", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == VHT_BW_80) + pAd->CommonCfg.vht_bw = VHT_BW_80; + else + pAd->CommonCfg.vht_bw = VHT_BW_2040; + + DBGPRINT(RT_DEBUG_TRACE, ("VHT: Channel Width = %s\n", + (pAd->CommonCfg.vht_bw == VHT_BW_80) ? "80 MHz" : "20/40 MHz" )); + } + + /* VHT GI setting */ + if (RTMPGetKeyParameter("VHT_SGI", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == GI_800) + pAd->CommonCfg.vht_sgi_80 = GI_800; + else + pAd->CommonCfg.vht_sgi_80 = GI_400; + + DBGPRINT(RT_DEBUG_TRACE, ("VHT: Short GI for 80Mhz = %s\n", + (pAd->CommonCfg.vht_sgi_80==GI_800) ? "Disabled" : "Enable" )); + } + + /* VHT STBC */ + if (RTMPGetKeyParameter("VHT_STBC", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + pAd->CommonCfg.vht_stbc = (Value == 1 ? STBC_USE : STBC_NONE); + DBGPRINT(RT_DEBUG_TRACE, ("VHT: STBC = %d\n", + pAd->CommonCfg.vht_stbc)); + } + + /* bandwidth signaling */ + if (RTMPGetKeyParameter("VHT_BW_SIGNAL", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value >= 0 && Value <= 2) + pAd->CommonCfg.vht_bw_signal = Value; + else + pAd->CommonCfg.vht_bw_signal = BW_SIGNALING_DISABLE; + DBGPRINT(RT_DEBUG_TRACE, ("VHT: BW SIGNALING = %d\n", pAd->CommonCfg.vht_bw_signal)); + } + + /* Disallow non-VHT connection */ + if (RTMPGetKeyParameter("VHT_DisallowNonVHT", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == 0) + pAd->CommonCfg.bNonVhtDisallow = FALSE; + else + pAd->CommonCfg.bNonVhtDisallow = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("VHT: VHT_DisallowNonVHT = %d\n", pAd->CommonCfg.bNonVhtDisallow)); + } + + /* VHT LDPC */ + if (RTMPGetKeyParameter("VHT_LDPC", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == 0) + pAd->CommonCfg.vht_ldpc = FALSE; + else + pAd->CommonCfg.vht_ldpc = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("VHT: VHT_LDPC = %d\n", pAd->CommonCfg.vht_ldpc)); + } + +#ifdef WFA_VHT_PF + /* VHT highest Tx Rate with LGI */ + if (RTMPGetKeyParameter("VHT_TX_HRATE", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value >= 0 && Value <= 2) + pAd->CommonCfg.vht_tx_hrate = Value; + else + pAd->CommonCfg.vht_tx_hrate = 0; + DBGPRINT(RT_DEBUG_TRACE, ("VHT: TX HighestRate = %d\n", pAd->CommonCfg.vht_tx_hrate)); + } + + if (RTMPGetKeyParameter("VHT_RX_HRATE", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value >= 0 && Value <= 2) + pAd->CommonCfg.vht_rx_hrate = Value; + else + pAd->CommonCfg.vht_rx_hrate = 0; + DBGPRINT(RT_DEBUG_TRACE, ("VHT: RX HighestRate = %d\n", pAd->CommonCfg.vht_rx_hrate)); + } + + if (RTMPGetKeyParameter("VHT_MCS_CAP", pValueStr, 25, pInput, TRUE)) + set_vht_nss_mcs_cap(pAd, pValueStr); +#endif /* WFA_VHT_PF */ + +} + +#endif /* DOT11_VHT_AC */ + + +#ifdef DOT11_N_SUPPORT +static void HTParametersHook( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *pValueStr, + IN RTMP_STRING *pInput) +{ + long Value; +#ifdef CONFIG_AP_SUPPORT + INT i=0; + RTMP_STRING *Bufptr; +#endif /* CONFIG_AP_SUPPORT */ + + if (RTMPGetKeyParameter("HT_PROTECT", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.bHTProtect = FALSE; + } + else + { + pAd->CommonCfg.bHTProtect = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: Protection = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + + if (RTMPGetKeyParameter("HT_MIMOPSMode", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value > MMPS_DISABLE) + { + pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_DISABLE; + } + else + { + /*TODO: add mimo power saving mechanism*/ + pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_DISABLE; + /*pAd->CommonCfg.BACapability.field.MMPSmode = Value;*/ + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: MIMOPS Mode = %d\n", (INT) Value)); + } + + if (RTMPGetKeyParameter("HT_BADecline", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.bBADecline = FALSE; + } + else + { + pAd->CommonCfg.bBADecline = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Decline = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + + if (RTMPGetKeyParameter("HT_AutoBA", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == 0) + { + pAd->CommonCfg.BACapability.field.AutoBA = FALSE; + pAd->CommonCfg.BACapability.field.Policy = BA_NOTUSE; + } + else + { + pAd->CommonCfg.BACapability.field.AutoBA = TRUE; + pAd->CommonCfg.BACapability.field.Policy = IMMED_BA; + } + pAd->CommonCfg.REGBACapability.field.AutoBA = pAd->CommonCfg.BACapability.field.AutoBA; + pAd->CommonCfg.REGBACapability.field.Policy = pAd->CommonCfg.BACapability.field.Policy; + DBGPRINT(RT_DEBUG_TRACE, ("HT: Auto BA = %s\n", (Value==0) ? "Disable" : "Enable")); + } + + + /* 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->CommonCfg.bRdg = TRUE; + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + pAd->CommonCfg.bRdg = FALSE; +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("HT: RDG = %s\n", (Value==0) ? "Disable" : "Enable(+HTC)")); + } + + + + + /* Tx A-MSUD ?*/ + if (RTMPGetKeyParameter("HT_AMSDU", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + pAd->CommonCfg.BACapability.field.AmsduEnable = (Value == 0) ? FALSE : TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("HT: Tx A-MSDU = %s\n", (Value==0) ? "Disable" : "Enable")); + } + +#ifdef WFA_VHT_PF + if (RTMPGetKeyParameter("FORCE_AMSDU", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + pAd->force_amsdu = (Value == 0) ? FALSE : TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("HT: FORCE A-MSDU = %s\n", (Value==0) ? "Disable" : "Enable")); + } +#endif /* WFA_VHT_PF */ + + /* MPDU Density*/ + if (RTMPGetKeyParameter("HT_MpduDensity", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value <=7 && Value >= 0) + { + pAd->CommonCfg.BACapability.field.MpduDensity = Value; + DBGPRINT(RT_DEBUG_TRACE, ("HT: MPDU Density = %d\n", (INT) Value)); + } + else + { + pAd->CommonCfg.BACapability.field.MpduDensity = 4; + DBGPRINT(RT_DEBUG_TRACE, ("HT: MPDU Density = %d (Default)\n", 4)); + } + } + + /* Max Rx BA Window Size*/ + if (RTMPGetKeyParameter("HT_BAWinSize", pValueStr, 25, pInput, TRUE)) + { + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + Value = simple_strtol(pValueStr, 0, 10); + + if (Value >= 1 && Value <= 64) + { + pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = min((UINT8)Value, (UINT8)pChipCap->RxBAWinSize); + pAd->CommonCfg.BACapability.field.RxBAWinLimit = min((UINT8)Value, (UINT8)pChipCap->RxBAWinSize); + DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Windw Size = %d\n", min((UINT8)Value, (UINT8)pChipCap->RxBAWinSize))); + } + else + { + pAd->CommonCfg.REGBACapability.field.RxBAWinLimit = min((UINT8)64, (UINT8)pChipCap->RxBAWinSize); + pAd->CommonCfg.BACapability.field.RxBAWinLimit = min((UINT8)64, (UINT8)pChipCap->RxBAWinSize); + DBGPRINT(RT_DEBUG_TRACE, ("HT: BA Windw Size = %d\n", min((UINT8)64, (UINT8)pChipCap->RxBAWinSize))); + } + + } + + /* Guard Interval*/ + if (RTMPGetKeyParameter("HT_GI", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == GI_400) + { + pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_400; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.ShortGI = GI_800; + } + + DBGPRINT(RT_DEBUG_TRACE, ("HT: Guard Interval = %s\n", (Value==GI_400) ? "400" : "800" )); + } + + /* HT LDPC */ + if (RTMPGetKeyParameter("HT_LDPC", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == 0) + pAd->CommonCfg.ht_ldpc = FALSE; + else + pAd->CommonCfg.ht_ldpc = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("HT: HT_LDPC = %d\n", pAd->CommonCfg.ht_ldpc)); + } + + /* HT Operation Mode : Mixed Mode , Green Field*/ + if (RTMPGetKeyParameter("HT_OpMode", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == HTMODE_GF) + { + + pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_GF; + } + else + { + pAd->CommonCfg.RegTransmitSetting.field.HTMODE = HTMODE_MM; + } + + DBGPRINT(RT_DEBUG_TRACE, ("HT: Operate Mode = %s\n", (Value==HTMODE_GF) ? "Green Field" : "Mixed Mode" )); + } + + /* Fixed Tx mode : CCK, OFDM*/ + if (RTMPGetKeyParameter("FixedTxMode", pValueStr, 25, pInput, TRUE)) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + for (i = 0, Bufptr = rstrtok(pValueStr,";"); (Bufptr && i < MAX_MBSSID_NUM(pAd)); Bufptr = rstrtok(NULL,";"), i++) + { + pAd->ApCfg.MBSSID[i].wdev.DesiredTransmitSetting.field.FixedTxMode = + RT_CfgSetFixedTxPhyMode(Bufptr); + DBGPRINT(RT_DEBUG_TRACE, ("(IF-ra%d) Fixed Tx Mode = %d\n", i, + pAd->ApCfg.MBSSID[i].wdev.DesiredTransmitSetting.field.FixedTxMode)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + } + + + /* Channel Width */ + if (RTMPGetKeyParameter("HT_BW", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + if (Value == BW_40) + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_40; + else + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + +#ifdef DOT11N_DRAFT3 + if (Value == BW_40) + pAd->CommonCfg.ori_bw_before_2040_coex = BW_40; + else + pAd->CommonCfg.ori_bw_before_2040_coex = BW_20; +#endif /* DOT11N_DRAFT3 */ + +#ifdef MCAST_RATE_SPECIFIC + pAd->CommonCfg.MCastPhyMode.field.BW = pAd->CommonCfg.RegTransmitSetting.field.BW; +#endif /* MCAST_RATE_SPECIFIC */ + + DBGPRINT(RT_DEBUG_TRACE, ("HT: Channel Width = %s\n", (Value==BW_40) ? "40 MHz" : "20 MHz" )); + } + + if (RTMPGetKeyParameter("HT_EXTCHA", pValueStr, 25, pInput, TRUE)) + { + Value = simple_strtol(pValueStr, 0, 10); + + if (Value == 0) + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_BELOW; + else + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_ABOVE; + +#ifdef DOT11N_DRAFT3 + if (Value == 0) + pAd->CommonCfg.ori_ext_channel_before_2040_coex = EXTCHA_BELOW; + else + pAd->CommonCfg.ori_ext_channel_before_2040_coex = EXTCHA_ABOVE; +#endif /* DOT11N_DRAFT3 */ + + if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_20) + { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_NONE; +#ifdef DOT11N_DRAFT3 + pAd->CommonCfg.ori_ext_channel_before_2040_coex = EXTCHA_NONE; +#endif /* DOT11N_DRAFT3 */ + DBGPRINT(RT_DEBUG_TRACE, ("HT: Ext Channel = %s\n", "NONE" )); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("HT: Ext Channel = %s\n", (Value==0) ? "BELOW" : "ABOVE" )); + } + } + + /* MSC*/ + if (RTMPGetKeyParameter("HT_MCS", pValueStr, 50, pInput, TRUE)) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + for (i = 0, Bufptr = rstrtok(pValueStr,";"); (Bufptr && i < MAX_MBSSID_NUM(pAd)); Bufptr = rstrtok(NULL,";"), i++) + { + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[i].wdev; + Value = simple_strtol(Bufptr, 0, 10); + if ((Value >= 0 && Value <= 23) || (Value == 32)) + wdev->DesiredTransmitSetting.field.MCS = Value; + else + wdev->DesiredTransmitSetting.field.MCS = MCS_AUTO; + DBGPRINT(RT_DEBUG_TRACE, ("(IF-ra%d) HT: MCS = %s(%d)\n", i, + (wdev->DesiredTransmitSetting.field.MCS == MCS_AUTO ? "AUTO" : "Fixed"), + wdev->DesiredTransmitSetting.field.MCS)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + + } + + /* 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; + RTMP_STRING *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 */ + + if (RTMPGetKeyParameter("TXRX_RXV_ON", pValueStr, 25, pInput, TRUE)) { + + Value = simple_strtol(pValueStr, 0, 10); + pAd->CommonCfg.bTXRX_RXV_ON = Value; + + DBGPRINT(RT_DEBUG_TRACE, ("TXRX_RXV_ON = %s\n", (Value == 1) ? "ON" : "OFF" )); + } +} +#endif /* DOT11_N_SUPPORT */ + + + + +void RTMPSetCountryCode(RTMP_ADAPTER *pAd, RTMP_STRING *CountryCode) +{ + NdisMoveMemory(pAd->CommonCfg.CountryCode, CountryCode , 2); + pAd->CommonCfg.CountryCode[2] = ' '; + if (strlen((RTMP_STRING *) 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 RTMP_STRING *pBuffer) +{ + RTMP_STRING *tmpbuf; + ULONG RtsThresh; + ULONG FragThresh; + RTMP_STRING *macptr; + INT i = 0, retval; + + os_alloc_mem(NULL, (UCHAR **)&tmpbuf, MAX_PARAM_BUFFER_SIZE); + if(tmpbuf == NULL) + return NDIS_STATUS_FAILURE; + + do + { + /* set file parameter to portcfg*/ + if (RTMPGetKeyParameter("MacAddress", tmpbuf, 25, pBuffer, TRUE)) + { + retval = RT_CfgSetMacAddress(pAd, tmpbuf); + if (retval) + DBGPRINT(RT_DEBUG_TRACE, ("MacAddress = %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pAd->CurrentAddress))); + } + /*CountryRegion*/ + if(RTMPGetKeyParameter("CountryRegion", tmpbuf, 25, pBuffer, TRUE)) + { + retval = RT_CfgSetCountryRegion(pAd, tmpbuf, BAND_24G); + DBGPRINT(RT_DEBUG_TRACE, ("CountryRegion=%d\n", pAd->CommonCfg.CountryRegion)); + } +#ifdef P2P_CHANNEL_LIST_SEPARATE + /*P2PCountryRegion*/ + if(RTMPGetKeyParameter("P2PCountryRegion", tmpbuf, 25, pBuffer, TRUE)) + { + UCHAR region = (UCHAR) simple_strtol(tmpbuf, 0, 10); + PCFG80211_CTRL pCfg80211_Ctrl = &pAd->cfg80211_ctrl; + + pCfg80211_Ctrl->CountryRegion = region; + DBGPRINT(RT_DEBUG_ERROR, ("%s::(P2PCountryRegion=%d)\n", __FUNCTION__, pCfg80211_Ctrl->CountryRegion)); + } +#endif /* P2P_CHANNEL_LIST_SEPARATE */ + + /*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 BB_SOC +#ifdef RTMP_EFUSE_SUPPORT + /*EfuseBufferMode*/ + if(RTMPGetKeyParameter("EfuseBufferMode", tmpbuf, 25, pBuffer, TRUE)) + { + pAd->E2pAccessMode = ((UCHAR) simple_strtol(tmpbuf, 0, 10) == 1)? 4: (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("EfuseBufferMode=%d\n", pAd->E2pAccessMode)); + } +#endif /* RTMP_EFUSE_SUPPORT */ +#endif /* BB_SOC */ + + /* E2pAccessMode */ + if (RTMPGetKeyParameter("E2pAccessMode", tmpbuf, 25, pBuffer, TRUE)) + { + pAd->E2pAccessMode = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("E2pAccessMode=%d\n", pAd->E2pAccessMode)); + } + + /*CountryCode*/ + if (pAd->CommonCfg.bCountryFlag == 0) + { + if(RTMPGetKeyParameter("CountryCode", tmpbuf, 25, pBuffer, TRUE)) + RTMPSetCountryCode(pAd, tmpbuf); + } + +#ifdef EXT_BUILD_CHANNEL_LIST + /*ChannelGeography*/ + if(RTMPGetKeyParameter("ChannelGeography", tmpbuf, 25, pBuffer, TRUE)) + { + UCHAR Geography = (UCHAR) simple_strtol(tmpbuf, 0, 10); + if (Geography <= BOTH) + { + pAd->CommonCfg.Geography = Geography; + pAd->CommonCfg.CountryCode[2] = + (pAd->CommonCfg.Geography == BOTH) ? ' ' : ((pAd->CommonCfg.Geography == IDOR) ? 'I' : 'O'); + 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 (pAd->ApCfg.BssidNum != 0) + { + if (HW_BEACON_OFFSET > (HW_BEACON_MAX_SIZE(pAd) / pAd->ApCfg.BssidNum)) + { + DBGPRINT(RT_DEBUG_OFF, ("mbss> fatal error! beacon offset is error in driver! " + "Please re-assign HW_BEACON_OFFSET!\n")); + } + } +#else + pAd->ApCfg.BssidNum = 1; +#endif /* MBSS_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* SSID*/ + if (TRUE) + { + RTMP_STRING tok_str[16]; + UCHAR BssidCountSupposed = 0; + BOOLEAN bSSIDxIsUsed = FALSE; + + //PRINT(RT_DEBUG_TRACE, ("pAd->ApCfg.BssidNum=%d\n", pAd->ApCfg.BssidNum)); + for (i = 0; i < pAd->ApCfg.BssidNum; i++) + { + snprintf(tok_str, sizeof(tok_str), "SSID%d", i + 1); + if(RTMPGetKeyParameter(tok_str, tmpbuf, 33, pBuffer, FALSE)) + { + NdisMoveMemory(pAd->ApCfg.MBSSID[i].Ssid, tmpbuf , strlen(tmpbuf)); + pAd->ApCfg.MBSSID[i].Ssid[strlen(tmpbuf)] = '\0'; + pAd->ApCfg.MBSSID[i].SsidLen = strlen((RTMP_STRING *) 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((RTMP_STRING *)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((RTMP_STRING *) pAd->ApCfg.MBSSID[BSS0].Ssid); + DBGPRINT(RT_DEBUG_TRACE, ("SSID=%s\n", pAd->ApCfg.MBSSID[BSS0].Ssid)); + } + } + } + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + + + /*Channel*/ + if(RTMPGetKeyParameter("Channel", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->CommonCfg.Channel = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("Channel=%d\n", pAd->CommonCfg.Channel)); + if (pAd->CommonCfg.Channel > 14) + pAd->Dot11_H.org_ch = pAd->CommonCfg.Channel; + } + + /* EtherTrafficBand */ + if (RTMPGetKeyParameter("EtherTrafficBand", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->CommonCfg.EtherTrafficBand = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("EtherTrafficBand=%d\n", pAd->CommonCfg.EtherTrafficBand)); + + if (pAd->CommonCfg.EtherTrafficBand > EtherTrafficBand5G) + pAd->CommonCfg.EtherTrafficBand = EtherTrafficBand5G; + } + + /*WirelessMode*/ + /*Note: BssidNum must be put before WirelessMode in dat file*/ + if(RTMPGetKeyParameter("WirelessMode", tmpbuf, 32, pBuffer, TRUE)) + { + UCHAR cfg_mode; + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + cfg_mode = simple_strtol(macptr, 0, 10); +#ifdef CONFIG_AP_SUPPORT + if (i >= pAd->ApCfg.BssidNum) + break; + + pAd->ApCfg.MBSSID[i].wdev.PhyMode = cfgmode_2_wmode(cfg_mode); + DBGPRINT(RT_DEBUG_TRACE, ("BSS%d PhyMode=%d\n", i, pAd->ApCfg.MBSSID[i].wdev.PhyMode)); +#endif /* CONFIG_AP_SUPPORT */ + + if (i == 0) + { +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT + /* for first time, update all phy mode is same as ra0 */ + { + UINT32 IdBss; + for(IdBss=1; IdBssApCfg.BssidNum; IdBss++) + pAd->ApCfg.MBSSID[IdBss].wdev.PhyMode = pAd->ApCfg.MBSSID[0].wdev.PhyMode; + } +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + /* set mode for 1st time */ + RT_CfgSetWirelessMode(pAd, macptr); + } +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT + else + RT_CfgSetMbssWirelessMode(pAd, macptr); +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + } + + DBGPRINT(RT_DEBUG_TRACE, ("PhyMode=%d\n", pAd->CommonCfg.PhyMode)); + } +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) + if (RTMPGetKeyParameter("WfFwdDisabled", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->CommonCfg.WfFwdDisabled = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("WfFwdDisabled=%d\n", pAd->CommonCfg.WfFwdDisabled)); + } +#endif +#endif + /*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)); + } + +#ifdef CONFIG_AP_SUPPORT +#ifdef DYNAMIC_RX_RATE_ADJ + /* 1,2,5.5,11,6,9,12,18,24,36,48,54 */ + if(RTMPGetKeyParameter("SupportRate", tmpbuf, 64, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i >= pAd->ApCfg.BssidNum) + break; + + pAd->ApCfg.MBSSID[i].SuppRateBitmap = (ULONG) simple_strtol(macptr, 0, 16); + DBGPRINT(RT_DEBUG_TRACE, ("BSS%d SupportRate=%lx\n", i, pAd->ApCfg.MBSSID[i].SuppRateBitmap)); + + if (i == 0) + { +#ifdef MBSS_SUPPORT + /* for fist time, update all phy mode is same as ra0 */ + UINT32 IdBss; + + for(IdBss = 1; IdBss < pAd->ApCfg.BssidNum; IdBss++) + pAd->ApCfg.MBSSID[IdBss].SuppRateBitmap = pAd->ApCfg.MBSSID[0].SuppRateBitmap; +#endif /* MBSS_SUPPORT */ + } + } + } + + /* MCS0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15*/ + if(RTMPGetKeyParameter("SupportHTRate", tmpbuf, 64, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if (i >= pAd->ApCfg.BssidNum) + break; + + pAd->ApCfg.MBSSID[i].SuppHTRateBitmap = (ULONG) simple_strtol(macptr, 0, 16); + DBGPRINT(RT_DEBUG_TRACE, ("BSS%d SupportHTRate=%lx\n", i, pAd->ApCfg.MBSSID[i].SuppHTRateBitmap)); + + if (i == 0) + { +#ifdef MBSS_SUPPORT + /* for fist time, update all phy mode is same as ra0 */ + UINT32 IdBss; + + for(IdBss = 1; IdBss < pAd->ApCfg.BssidNum; IdBss++) + pAd->ApCfg.MBSSID[IdBss].SuppHTRateBitmap = pAd->ApCfg.MBSSID[0].SuppHTRateBitmap; +#endif /* MBSS_SUPPORT */ + } + } + } +#endif /* DYNAMIC_RX_RATE_ADJ */ +#endif /* CONFIG_AP_SUPPORT */ + + /*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)); + } + + +#if defined(DOT11V_WNM_SUPPORT) || defined(CONFIG_DOT11V_WNM) + WNM_ReadParametersFromFile(pAd, tmpbuf, pBuffer); +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef DFS_SUPPORT + /*DFSIndoor*/ + { + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam; + + if (RTMPGetKeyParameter("DfsIndoor", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->Dot11_H.bDFSIndoor = (USHORT) (simple_strtol(tmpbuf, 0, 10) != 0); + DBGPRINT(RT_DEBUG_TRACE, ("DfsIndoor=%d\n", pAd->Dot11_H.bDFSIndoor)); + } + { + INT k=0; + /*SymRoundFromCfg*/ + if (RTMPGetKeyParameter("SymRoundFromCfg", tmpbuf, 10, pBuffer, TRUE)) + { + pRadarDetect->SymRoundFromCfg = (UCHAR) simple_strtol(tmpbuf, 0, 10); + pRadarDetect->SymRoundCfgValid = 1; + DBGPRINT(RT_DEBUG_TRACE, ("SymRoundFromCfg=%d\n", pRadarDetect->SymRoundFromCfg)); + } + + /*BusyIdleFromCfg*/ + if (RTMPGetKeyParameter("BusyIdleFromCfg", tmpbuf, 10, pBuffer, TRUE)) + { + pRadarDetect->BusyIdleFromCfg = (UCHAR) simple_strtol(tmpbuf, 0, 10); + pRadarDetect->BusyIdleCfgValid = 1; + DBGPRINT(RT_DEBUG_TRACE, ("BusyIdleFromCfg=%d\n", pRadarDetect->BusyIdleFromCfg)); + } + /*DfsRssiHighFromCfg*/ + if (RTMPGetKeyParameter("DfsRssiHighFromCfg", tmpbuf, 10, pBuffer, TRUE)) + { + pRadarDetect->DfsRssiHighFromCfg = simple_strtol(tmpbuf, 0, 10); + pRadarDetect->DfsRssiHighCfgValid = 1; + DBGPRINT(RT_DEBUG_TRACE, ("DfsRssiHighFromCfg=%d\n", pRadarDetect->DfsRssiHighFromCfg)); + } + + /*DfsRssiLowFromCfg*/ + if (RTMPGetKeyParameter("DfsRssiLowFromCfg", tmpbuf, 10, pBuffer, TRUE)) + { + pRadarDetect->DfsRssiLowFromCfg = simple_strtol(tmpbuf, 0, 10); + pRadarDetect->DfsRssiLowCfgValid = 1; + DBGPRINT(RT_DEBUG_TRACE, ("DfsRssiLowFromCfg=%d\n", pRadarDetect->DfsRssiLowFromCfg)); + } + + /*DFSParamFromConfig*/ + if (RTMPGetKeyParameter("DFSParamFromConfig", tmpbuf, 10, pBuffer, TRUE)) + { + pRadarDetect->DFSParamFromConfig = (UCHAR) simple_strtol(tmpbuf, 0, 10); + + DBGPRINT(RT_DEBUG_TRACE, ("DFSParamFromConfig=%d\n", pRadarDetect->DFSParamFromConfig)); + } + + /* DFSParam*/ + for(k = 0; k < 4*pAd->chipCap.DfsEngineNum; k++) + { + RTMP_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 + // Read BandSteering profile parameters + BndStrgSetProfileParam(pAd,tmpbuf,pBuffer); +#endif /* BAND_STEERING */ + } +#endif /* CONFIG_AP_SUPPORT */ + /*TxPower*/ + if(RTMPGetKeyParameter("TxPower", tmpbuf, 10, pBuffer, TRUE)) + { + pAd->CommonCfg.TxPowerPercentage = (ULONG) simple_strtol(tmpbuf, 0, 10); + 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_11PreambleAuto: + pAd->CommonCfg.TxPreamble = Rt802_11PreambleAuto; + 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_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 > 3 || 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, 128, 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)) + { + UINT32 Time = simple_strtol(tmpbuf, 0, 10); +#ifndef ACS_CTCC_SUPPORT + Time = Time * 3600; /* second */ +#endif + pAd->ApCfg.ACSCheckTime = Time; + DBGPRINT(RT_DEBUG_TRACE, ("ACSCheckTime = %u (Sec) \n", Time)); + } +#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 PRE_ANT_SWITCH + /*PreAntSwitch*/ + if(RTMPGetKeyParameter("PreAntSwitch", tmpbuf, 32, pBuffer, TRUE)) + { + pAd->CommonCfg.PreAntSwitch = (simple_strtol(tmpbuf, 0, 10) != 0); + DBGPRINT(RT_DEBUG_TRACE, ("PreAntSwitch = %d\n", pAd->CommonCfg.PreAntSwitch)); + } +#endif /* PRE_ANT_SWITCH */ + + + +#ifdef STREAM_MODE_SUPPORT + /* StreamMode*/ + if (pAd->chipCap.FlgHwStreamMode) + { + if(RTMPGetKeyParameter("StreamMode", tmpbuf, 32, pBuffer, TRUE)) + { + pAd->CommonCfg.StreamMode = (simple_strtol(tmpbuf, 0, 10) & 0x03); + DBGPRINT(RT_DEBUG_TRACE, ("StreamMode= %d\n", pAd->CommonCfg.StreamMode)); + } + + /* StreamModeMac*/ + for (i = 0; i < STREAM_MODE_STA_NUM; i++) + { + RTMP_STRING tok_str[32]; + + sprintf(tok_str, "StreamModeMac%d", i); + + if (RTMPGetKeyParameter(tok_str, tmpbuf, MAX_PARAM_BUFFER_SIZE, pBuffer, TRUE)) + { + int j; + if(strlen(tmpbuf) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17*/ + continue; + + for (j=0; jCommonCfg.StreamModeMac[i][j], 1); + tmpbuf=tmpbuf+3; + } + } + } + + if (NdisEqualMemory(ZERO_MAC_ADDR, &pAd->CommonCfg.StreamModeMac[0][0], MAC_ADDR_LEN)) + { + /* set default broadcast mac to entry 0 if user not set it */ + NdisMoveMemory(&pAd->CommonCfg.StreamModeMac[0][0], BROADCAST_ADDR, MAC_ADDR_LEN); + } + } +#endif /* STREAM_MODE_SUPPORT */ + +#ifdef DBG_CTRL_SUPPORT + /*DebugFlags*/ + if(RTMPGetKeyParameter("DebugFlags", tmpbuf, 32, pBuffer, TRUE)) + { + pAd->CommonCfg.DebugFlags = simple_strtol(tmpbuf, 0, 16); + DBGPRINT(RT_DEBUG_TRACE, ("DebugFlags = 0x%02lx\n", pAd->CommonCfg.DebugFlags)); + } +#endif /* DBG_CTRL_SUPPORT */ + + /*IEEE80211H*/ + if(RTMPGetKeyParameter("IEEE80211H", tmpbuf, 10, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + if(simple_strtol(macptr, 0, 10) != 0) /*Enable*/ + pAd->CommonCfg.bIEEE80211H = TRUE; + else /*Disable*/ + pAd->CommonCfg.bIEEE80211H = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("IEEE80211H=%d\n", pAd->CommonCfg.bIEEE80211H)); + } + } + +#ifdef DFS_SUPPORT + { + /*CSPeriod*/ + if(RTMPGetKeyParameter("CSPeriod", tmpbuf, 10, pBuffer, TRUE)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) + pAd->Dot11_H.CSPeriod = simple_strtol(tmpbuf, 0, 10); + else + pAd->Dot11_H.CSPeriod = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("CSPeriod=%d\n", pAd->Dot11_H.CSPeriod)); + } + + } +#endif /* DFS_SUPPORT */ + + /*RDRegion*/ + if(RTMPGetKeyParameter("RDRegion", tmpbuf, 128, pBuffer, TRUE)) + { + if ((strncmp(tmpbuf, "JAP_W53", 7) == 0) || (strncmp(tmpbuf, "jap_w53", 7) == 0)) + { + pAd->CommonCfg.RDDurRegion = JAP_W53; + /*pRadarDetect->DfsSessionTime = 15;*/ + } + else if ((strncmp(tmpbuf, "JAP_W56", 7) == 0) || (strncmp(tmpbuf, "jap_w56", 7) == 0)) + { + pAd->CommonCfg.RDDurRegion = JAP_W56; + /*pRadarDetect->DfsSessionTime = 13;*/ + } + else if ((strncmp(tmpbuf, "JAP", 3) == 0) || (strncmp(tmpbuf, "jap", 3) == 0)) + { + pAd->CommonCfg.RDDurRegion = JAP; + /*pRadarDetect->DfsSessionTime = 5;*/ + } + else if ((strncmp(tmpbuf, "FCC", 3) == 0) || (strncmp(tmpbuf, "fcc", 3) == 0)) + { + pAd->CommonCfg.RDDurRegion = FCC; + /*pRadarDetect->DfsSessionTime = 5;*/ + } + else if ((strncmp(tmpbuf, "CE", 2) == 0) || (strncmp(tmpbuf, "ce", 2) == 0)) + { + pAd->CommonCfg.RDDurRegion = CE; + /*pRadarDetect->DfsSessionTime = 13;*/ + } + else + { + pAd->CommonCfg.RDDurRegion = CE; + /*pRadarDetect->DfsSessionTime = 13;*/ + } + + DBGPRINT(RT_DEBUG_TRACE, ("RDRegion=%d\n", pAd->CommonCfg.RDDurRegion)); + } + else + { + pAd->CommonCfg.RDDurRegion = CE; + /*pRadarDetect->DfsSessionTime = 13;*/ + } + +#ifdef SYSTEM_LOG_SUPPORT + /*WirelessEvent*/ + if(RTMPGetKeyParameter("WirelessEvent", tmpbuf, 10, pBuffer, TRUE)) + { + BOOLEAN FlgIsWEntSup = FALSE; + + if(simple_strtol(tmpbuf, 0, 10) != 0) + FlgIsWEntSup = TRUE; + + RtmpOsWlanEventSet(pAd, &pAd->CommonCfg.bWirelessEvent, FlgIsWEntSup); + DBGPRINT(RT_DEBUG_TRACE, ("WirelessEvent=%d\n", pAd->CommonCfg.bWirelessEvent)); + } +#endif /* SYSTEM_LOG_SUPPORT */ + +#ifdef MBO_SUPPORT + ReadMboParameterFromFile(pAd, tmpbuf, pBuffer); +#endif/* MBO_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 */ + } + /*EncrypType*/ + if(RTMPGetKeyParameter("EncrypType", tmpbuf, 128, pBuffer, TRUE)) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* + We need to reset the WepStatus of all interfaces as 1 (Ndis802_11WEPDisabled) first. + Or it may have problem when some interface enabled but didn't configure it. + */ + for ( i= 0; iApCfg.BssidNum; i++) + pAd->ApCfg.MBSSID[i].wdev.WepStatus = Ndis802_11WEPDisabled; + + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + int apidx; + struct wifi_dev *wdev; + if (i < HW_BEACON_MAX_NUM) + apidx = i; + else + break; + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + if (rtstrcasecmp(macptr, "NONE") == TRUE) + wdev->WepStatus = Ndis802_11WEPDisabled; + else if (rtstrcasecmp(macptr, "WEP") == TRUE) + wdev->WepStatus = Ndis802_11WEPEnabled; + else if (rtstrcasecmp(macptr, "TKIPAES") == TRUE) + wdev->WepStatus = Ndis802_11TKIPAESMix; + else if (rtstrcasecmp(macptr, "TKIP") == TRUE) + wdev->WepStatus = Ndis802_11TKIPEnable; + else if (rtstrcasecmp(macptr, "AES") == TRUE) + wdev->WepStatus = Ndis802_11AESEnable; +#ifdef WAPI_SUPPORT + else if (rtstrcasecmp(macptr, "SMS4") == TRUE) + wdev->WepStatus = Ndis802_11EncryptionSMS4Enabled; +#endif /* WAPI_SUPPORT */ +#ifdef CONFIG_OWE_SUPPORT + else if (rtstrcasecmp(macptr, "CCMP128") == TRUE) + wdev->WepStatus = Ndis802_11CCMP128Enable; + else if (rtstrcasecmp(macptr, "CCMP256") == TRUE) + wdev->WepStatus = Ndis802_11CCMP256Enable; +#endif + else + wdev->WepStatus = Ndis802_11WEPDisabled; + + /* decide the group key encryption type*/ + if (wdev->WepStatus == Ndis802_11TKIPAESMix) + wdev->GroupKeyWepStatus = Ndis802_11TKIPEnable; + else + wdev->GroupKeyWepStatus = wdev->WepStatus; + + /* move to ap.c::APStartUp to process*/ + /*RTMPMakeRSNIE(pAd, pAd->ApCfg.MBSSID[apidx].AuthMode, wdev->WepStatus, apidx);*/ + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) EncrypType=%d\n", i, wdev->WepStatus)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* WpaMixPairCipher*/ + if(RTMPGetKeyParameter("WpaMixPairCipher", tmpbuf, 256, pBuffer, TRUE)) + { + /* + In WPA-WPA2 mix mode, it provides a more flexible cipher combination. + - WPA-AES and WPA2-TKIP + - WPA-AES and WPA2-TKIPAES + - WPA-TKIP and WPA2-AES + - WPA-TKIP and WPA2-TKIPAES + - WPA-TKIPAES and WPA2-AES + - WPA-TKIPAES and WPA2-TKIP + - WPA-TKIPAES and WPA2-TKIPAES (default) + */ + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + struct wifi_dev *wdev; + + // TODO: shiang, check about the sequence of this paramter and BssNum!! + if (i >= HW_BEACON_MAX_NUM) + break; + + wdev = &pAd->ApCfg.MBSSID[i].wdev; + if (wdev->AuthMode != Ndis802_11AuthModeWPA1WPA2 && + wdev->AuthMode != Ndis802_11AuthModeWPA1PSKWPA2PSK) + continue; + + if (wdev->WepStatus != Ndis802_11TKIPAESMix) + continue; + + if ((strncmp(macptr, "WPA_AES_WPA2_TKIPAES", 20) == 0) || (strncmp(macptr, "wpa_aes_wpa2_tkipaes", 20) == 0)) + wdev->WpaMixPairCipher = WPA_AES_WPA2_TKIPAES; + else if ((strncmp(macptr, "WPA_AES_WPA2_TKIP", 17) == 0) || (strncmp(macptr, "wpa_aes_wpa2_tkip", 17) == 0)) + wdev->WpaMixPairCipher = WPA_AES_WPA2_TKIP; + else if ((strncmp(macptr, "WPA_TKIP_WPA2_AES", 17) == 0) || (strncmp(macptr, "wpa_tkip_wpa2_aes", 17) == 0)) + wdev->WpaMixPairCipher = WPA_TKIP_WPA2_AES; + else if ((strncmp(macptr, "WPA_TKIP_WPA2_TKIPAES", 21) == 0) || (strncmp(macptr, "wpa_tkip_wpa2_tkipaes", 21) == 0)) + wdev->WpaMixPairCipher = WPA_TKIP_WPA2_TKIPAES; + else if ((strncmp(macptr, "WPA_TKIPAES_WPA2_AES", 20) == 0) || (strncmp(macptr, "wpa_tkipaes_wpa2_aes", 20) == 0)) + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_AES; + else if ((strncmp(macptr, "WPA_TKIPAES_WPA2_TKIPAES", 24) == 0) || (strncmp(macptr, "wpa_tkipaes_wpa2_tkipaes", 24) == 0)) + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIPAES; + else if ((strncmp(macptr, "WPA_TKIPAES_WPA2_TKIP", 21) == 0) || (strncmp(macptr, "wpa_tkipaes_wpa2_tkip", 21) == 0)) + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIP; + else /*Default*/ + wdev->WpaMixPairCipher = WPA_TKIPAES_WPA2_TKIPAES; + + DBGPRINT(RT_DEBUG_OFF, ("I/F(ra%d) MixWPACipher=0x%02x\n", i, wdev->WpaMixPairCipher)); + } + } + + /*RekeyMethod*/ + if(RTMPGetKeyParameter("RekeyMethod", tmpbuf, 128, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + PRT_WPA_REKEY pRekeyInfo = &pAd->ApCfg.MBSSID[i].WPAREKEY; + + if ((strcmp(macptr, "TIME") == 0) || (strcmp(macptr, "time") == 0)) + pRekeyInfo->ReKeyMethod = TIME_REKEY; + else if ((strcmp(macptr, "PKT") == 0) || (strcmp(macptr, "pkt") == 0)) + pRekeyInfo->ReKeyMethod = PKT_REKEY; + else if ((strcmp(macptr, "DISABLE") == 0) || (strcmp(macptr, "disable") == 0)) + pRekeyInfo->ReKeyMethod = DISABLE_REKEY; + else + pRekeyInfo->ReKeyMethod = DISABLE_REKEY; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) ReKeyMethod=%ld\n", i, pRekeyInfo->ReKeyMethod)); + } + + /* Apply to remaining MBSS*/ + if (i == 1) + { + for (i = 1; i < pAd->ApCfg.BssidNum; i++) + { + pAd->ApCfg.MBSSID[i].WPAREKEY.ReKeyMethod = + pAd->ApCfg.MBSSID[0].WPAREKEY.ReKeyMethod; + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) ReKeyMethod=%ld\n", + i, pAd->ApCfg.MBSSID[i].WPAREKEY.ReKeyMethod)); + } + } + } + /*RekeyInterval*/ + if(RTMPGetKeyParameter("RekeyInterval", tmpbuf, 255, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + ULONG value_interval; + PRT_WPA_REKEY pRekeyInfo = &pAd->ApCfg.MBSSID[i].WPAREKEY; + + value_interval = simple_strtol(macptr, 0, 10); + + if((value_interval >= 10) && (value_interval < MAX_REKEY_INTER)) + pRekeyInfo->ReKeyInterval = value_interval; + else /*Default*/ + pRekeyInfo->ReKeyInterval = 3600; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) ReKeyInterval=%ld\n", + i, pRekeyInfo->ReKeyInterval)); + } + + /* Apply to remaining MBSS*/ + if (i == 1) + { + for (i = 1; i < pAd->ApCfg.BssidNum; i++) + { + pAd->ApCfg.MBSSID[i].WPAREKEY.ReKeyInterval = + pAd->ApCfg.MBSSID[0].WPAREKEY.ReKeyInterval; + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) ReKeyInterval=%ld\n", + i, pAd->ApCfg.MBSSID[i].WPAREKEY.ReKeyInterval)); + } + } + + } + /*PMKCachePeriod*/ + if(RTMPGetKeyParameter("PMKCachePeriod", tmpbuf, 255, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->ApCfg.MBSSID[i].PMKCachePeriod = + simple_strtol(macptr, 0, 10) * 60 * OS_HZ; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) PMKCachePeriod=%ld\n", + i, pAd->ApCfg.MBSSID[i].PMKCachePeriod)); + } + + /* Apply to remaining MBSS*/ + if (i == 1) + { + for (i = 1; i < pAd->ApCfg.BssidNum; i++) + { + pAd->ApCfg.MBSSID[i].PMKCachePeriod = + pAd->ApCfg.MBSSID[0].PMKCachePeriod; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) PMKCachePeriod=%ld\n", + i, pAd->ApCfg.MBSSID[i].PMKCachePeriod)); + } + } + } + + /*WPAPSK_KEY*/ + if(TRUE) + { + RTMP_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 + } + } +#ifdef APCLI_SUPPORT +#ifdef ROAMING_ENHANCE_SUPPORT + if (RTMPGetKeyParameter("RoamingEnhance", tmpbuf, 32, pBuffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + pAd->ApCfg.bRoamingEnhance = (simple_strtol(tmpbuf, 0, 10) > 0)?TRUE:FALSE; + } + } +#endif /* ROAMING_ENHANCE_SUPPORT */ +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef MT_MAC + /* Non-BAR Control frame to MCU */ + if (RTMPGetKeyParameter("rx_pspoll_filter", tmpbuf, 25, pBuffer, TRUE)) + { + pAd->rx_pspoll_filter = (UCHAR) simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("rx_pspoll_filter=%d\n", pAd->rx_pspoll_filter)); + } +#endif /* MT_MAC */ + + + /*DefaultKeyID, KeyType, KeyStr*/ + rtmp_read_key_parms_from_file(pAd, tmpbuf, pBuffer); + +#ifdef WAPI_SUPPORT + rtmp_read_wapi_parms_from_file(pAd, tmpbuf, pBuffer); +#endif /* WAPI_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /*Access Control List*/ + rtmp_read_acl_parms_from_file(pAd, tmpbuf, pBuffer); + +#ifdef APCLI_SUPPORT + rtmp_read_ap_client_from_file(pAd, tmpbuf, pBuffer); +#endif /* APCLI_SUPPORT */ + +#ifdef IGMP_SNOOP_SUPPORT + /* Igmp Snooping information*/ + rtmp_read_igmp_snoop_from_file(pAd, tmpbuf, pBuffer); +#endif /* IGMP_SNOOP_SUPPORT */ + +#ifdef PREVENT_ARP_SPOOFING + if (RTMPGetKeyParameter("ARPSpoofChk", tmpbuf, 128, pBuffer, TRUE)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) + pAd->ApCfg.ARPSpoofChk = TRUE; + else + pAd->ApCfg.ARPSpoofChk = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("ARPSpoofChk=%d\n", pAd->ApCfg.ARPSpoofChk)); + } +#endif /* PREVENT_ARP_SPOOFING */ + +#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 MWDS + rtmp_read_MWDS_from_file(pAd, tmpbuf, pBuffer); +#endif /* MWDS */ + +#ifdef MAC_REPEATER_SUPPORT + if (RTMPGetKeyParameter("MACRepeaterEn", tmpbuf, 10, pBuffer, FALSE)) + { + if(simple_strtol(tmpbuf, 0, 10) != 0) + pAd->ApCfg.bMACRepeaterEn = TRUE; + else + pAd->ApCfg.bMACRepeaterEn = FALSE; + + 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)); + + } + + //replace all real mac + if (RTMPGetKeyParameter("MACRepeaterMACList", tmpbuf, MAX_PARAM_BUFFER_SIZE, pBuffer, FALSE)) + { + UCHAR macAddress[MAC_ADDR_LEN]; + INT j; + + 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.ReptMacList.Num <= MAX_NUMBER_OF_MAC_LIST); + + for (j=0; jApCfg.ReptMacList.Num == MAX_NUMBER_OF_MAC_LIST) + { + DBGPRINT(RT_DEBUG_ERROR, ("The ReptMacList is full, and no more entry can join the list!\n")); + DBGPRINT(RT_DEBUG_ERROR, ("The last entry of MAC is %02x:%02x:%02x:%02x:%02x:%02x\n", + macAddress[0],macAddress[1],macAddress[2],macAddress[3],macAddress[4],macAddress[5])); + + break; + } + + pAd->ApCfg.ReptMacList.Num ++; + NdisMoveMemory(pAd->ApCfg.ReptMacList.Entry[(pAd->ApCfg.ReptMacList.Num -1)].Addr, macAddress, MAC_ADDR_LEN); + } + DBGPRINT(RT_DEBUG_TRACE, ("MACRepeaterMACList.Num = %ld\n", pAd->ApCfg.ReptMacList.Num)); + } + + +#endif /* MAC_REPEATER_SUPPORT */ + } + +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + HTParametersHook(pAd, tmpbuf, pBuffer); +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + VHTParametersHook(pAd, tmpbuf, pBuffer); +#endif /* DOT11_VHT_AC */ + +#ifdef CONFIG_FPGA_MODE + if(RTMPGetKeyParameter("FPGA_ON", tmpbuf, 25, pBuffer, TRUE)) + { + ULONG fpga_on = simple_strtol(tmpbuf, 0, 10); + + pAd->fpga_ctl.fpga_on = fpga_on > 0 ? fpga_on : 0; + DBGPRINT(RT_DEBUG_OFF, ("%s(): FPGA_ON=%d\n", + __FUNCTION__, pAd->fpga_ctl.fpga_on)); + } + +#if defined(MT7603) || defined(MT7628) || defined(MT7636) + if(RTMPGetKeyParameter("DMA_SCH", tmpbuf, 25, pBuffer, TRUE)) + { + ULONG dma_sch = simple_strtol(tmpbuf, 0, 10); + + pAd->fpga_ctl.dma_mode = dma_sch > 0 ? dma_sch : 0; + DBGPRINT(RT_DEBUG_OFF, ("%s(): DMA Scheduler=%d\n", + __FUNCTION__, pAd->fpga_ctl.dma_mode)); + } +#endif /* MT7603 */ +#ifdef CAPTURE_MODE + if(RTMPGetKeyParameter("cap_support", tmpbuf, 25, pBuffer, TRUE)) + { + ULONG cap_support = simple_strtol(tmpbuf, 0, 10); + + pAd->fpga_ctl.cap_support = cap_support > 0 ? TRUE : FALSE; + DBGPRINT(RT_DEBUG_OFF, ("%s(): CaptureMode=%d\n", + __FUNCTION__, pAd->fpga_ctl.cap_support)); + } +#endif /* CAPTURE_MODE */ +#endif /* CONFIG_FPGA_MODE */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef WSC_AP_SUPPORT + RTMP_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)); + } +#ifdef STA_FORCE_ROAM_SUPPORT + if(RTMPGetKeyParameter("ForceRoamSupport", tmpbuf, 10, pBuffer, TRUE)) // use as global OR in multi-profile?? + { + if((strlen(tmpbuf) > 0) && (strlen(tmpbuf) <= 3)){ + + macptr = rstrtok(tmpbuf,";"); + + if( macptr!= NULL){ + + if(strlen(macptr) == 1){ + INT Value = 0; + + Value = simple_strtol(macptr, 0, 10); + + if((Value == 0) || (Value == 1)) + pAd->en_force_roam_supp = Value; + + DBGPRINT(RT_DEBUG_OFF, ("I/F(ra0) ForceRoamSupport=%d\n",pAd->en_force_roam_supp)); + } + } + } + } +#endif + + /*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 WH_EZ_SETUP + ez_read_parms_from_file(pAd, tmpbuf, pBuffer); +#endif /* WH_EZ_SETUP */ + +#ifdef STA_FORCE_ROAM_SUPPORT + if(RTMPGetKeyParameter("ForceRoamSupport", tmpbuf, 10, pBuffer, TRUE)) // use as global OR in multi-profile?? + { + if((strlen(tmpbuf) > 0) && (strlen(tmpbuf) <= 3)){ + + macptr = rstrtok(tmpbuf,";"); + + if( macptr!= NULL){ + + if(strlen(macptr) == 1){ + INT Value = 0; + + Value = simple_strtol(macptr, 0, 10); + + if((Value == 0) || (Value == 1)) + pAd->en_force_roam_supp = Value; + + DBGPRINT(RT_DEBUG_OFF, ("I/F(ra0) ForceRoamSupport=%d\n",pAd->en_force_roam_supp)); + } + } + } + } +#endif + } +#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_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 // + } + + 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 */ + 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 */ + } +#endif /* WSC_V2_SUPPORT */ + + +#endif /* WSC_INCLUDED */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef DOT11R_FT_SUPPORT + FT_rtmp_read_parameters_from_file(pAd, tmpbuf, pBuffer); +#endif /* DOT11R_FT_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT + rtmp_read_pmf_parameters_from_file(pAd, tmpbuf, pBuffer); +#endif /* DOT11W_PMF_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT + /* EntryLifeCheck is used to check */ + if (RTMPGetKeyParameter("EntryLifeCheck", tmpbuf, 256, pBuffer, TRUE)) + { + long LifeCheckCnt = simple_strtol(tmpbuf, 0, 10); + if ((LifeCheckCnt <= 65535) && (LifeCheckCnt != 0)) + pAd->ApCfg.EntryLifeCheck = LifeCheckCnt; + else + pAd->ApCfg.EntryLifeCheck = MAC_ENTRY_LIFE_CHECK_CNT; + + DBGPRINT(RT_DEBUG_ERROR, ("EntryLifeCheck=%ld\n", pAd->ApCfg.EntryLifeCheck)); + } + +#ifdef DOT11K_RRM_SUPPORT + RRM_ReadParametersFromFile(pAd, tmpbuf, pBuffer); +#endif /* DOT11K_RRM_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef SINGLE_SKU + if(RTMPGetKeyParameter("AntGain", tmpbuf, 10, pBuffer, TRUE)) + { + UCHAR AntGain = simple_strtol(tmpbuf, 0, 10); + pAd->CommonCfg.AntGain= AntGain; + + DBGPRINT(RT_DEBUG_TRACE, ("AntGain=%d\n", pAd->CommonCfg.AntGain)); + } + if(RTMPGetKeyParameter("BandedgeDelta", tmpbuf, 10, pBuffer, TRUE)) + { + UCHAR Bandedge = simple_strtol(tmpbuf, 0, 10); + pAd->CommonCfg.BandedgeDelta = Bandedge; + + DBGPRINT(RT_DEBUG_TRACE, ("BandedgeDelta=%d\n", pAd->CommonCfg.BandedgeDelta)); + } +#endif /* SINGLE_SKU */ + + + + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) || defined(MT_WOW_SUPPORT) + /* set GPIO pin for wake-up signal */ + if (RTMPGetKeyParameter("WOW_GPIO", tmpbuf, 10, pBuffer, TRUE)) + Set_WOW_GPIO(pAd, tmpbuf); + + /* set WOW enable/disable */ + if (RTMPGetKeyParameter("WOW_Enable", tmpbuf, 10, pBuffer, TRUE)) + Set_WOW_Enable(pAd, tmpbuf); + + /* set delay time for WOW really enable */ + if (RTMPGetKeyParameter("WOW_Delay", tmpbuf, 10, pBuffer, TRUE)) + Set_WOW_Delay(pAd, tmpbuf); + + /* set GPIO pulse hold time */ + if (RTMPGetKeyParameter("WOW_Hold", tmpbuf, 10, pBuffer, TRUE)) + Set_WOW_Hold(pAd, tmpbuf); + + /* set wakeup signal type */ + if (RTMPGetKeyParameter("WOW_InBand", tmpbuf, 10, pBuffer, TRUE)) + Set_WOW_InBand(pAd, tmpbuf); + + /* set wakeup interface */ + if (RTMPGetKeyParameter("WOW_Interface", tmpbuf, 10, pBuffer, TRUE)) + Set_WOW_Interface(pAd, tmpbuf); + + /* set GPIO High Low */ + if (RTMPGetKeyParameter("WOW_GPIOHighLow", tmpbuf, 10, pBuffer, TRUE)) + Set_WOW_GPIOHighLow(pAd, tmpbuf); + +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) || defined(MT_WOW_SUPPORT)*/ + +#ifdef MICROWAVE_OVEN_SUPPORT + if (RTMPGetKeyParameter("MO_FalseCCATh", tmpbuf, 10, pBuffer, TRUE)) + Set_MO_FalseCCATh_Proc(pAd, tmpbuf); +#endif /* MICROWAVE_OVEN_SUPPORT */ + + +#ifdef CONFIG_SNIFFER_SUPPORT + if (RTMPGetKeyParameter("SnifferType", tmpbuf, 10, pBuffer, TRUE)) { + pAd->sniffer_ctl.sniffer_type = simple_strtol(tmpbuf, 0, 10); +#ifdef CONFIG_AP_SUPPORT + if(pAd->ApCfg.MBSSID[0].wdev.if_dev) + set_sniffer_mode(pAd->ApCfg.MBSSID[0].wdev.if_dev, pAd->sniffer_ctl.sniffer_type); +#endif /* CONFIG_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_OFF, ("SnifferType = %d\n", pAd->sniffer_ctl.sniffer_type)); + } +#endif /* CONFIG_SNIFFER_SUPPORT */ + + if (RTMPGetKeyParameter("PS_RETRIEVE", tmpbuf, 10, pBuffer, TRUE)) + { + long PS_RETRIEVE; + PS_RETRIEVE = simple_strtol(tmpbuf, 0, 10); + pAd->bPS_Retrieve = PS_RETRIEVE; + DBGPRINT(RT_DEBUG_OFF, ("PS_RETRIEVE = %lx\n",PS_RETRIEVE)); + } + +#ifdef SMART_CARRIER_SENSE_SUPPORT + if (RTMPGetKeyParameter("SCSEnable", tmpbuf, 10, pBuffer, TRUE)) + { + long SCSEnable; + SCSEnable = simple_strtol(tmpbuf, 0, 10); + pAd->SCSCtrl.SCSEnable = SCSEnable; + DBGPRINT(RT_DEBUG_OFF, ("Smart Carrier Sense = %lx\n",SCSEnable)); + } +#endif /* SMART_CARRIER_SENSE_SUPPORT */ + +#ifdef FAST_DETECT_STA_OFF + if (RTMPGetKeyParameter("Flag_fast_detect_sta_off", tmpbuf, 10, pBuffer, TRUE)) { + Flag_fast_detect_sta_off = simple_strtol(tmpbuf, 0, 10); + DBGPRINT(RT_DEBUG_OFF, ("Flag_fast_detect_sta_off = %d\n", Flag_fast_detect_sta_off)); + } +#endif + + if (RTMPGetKeyParameter("ed_th_nonCE", tmpbuf, 10, pBuffer, TRUE)) + { + UINT32 ed_th = 0; + ed_th = simple_strtol(tmpbuf, 0, 10); + pAd->ed_th = ed_th; + DBGPRINT(RT_DEBUG_OFF, ("ed_th_nonCE = %x\n",ed_th)); + } + if (RTMPGetKeyParameter("Cts2SelfTh", tmpbuf, 10, pBuffer, TRUE)) { + UINT32 FalseCCATh = 0; + + FalseCCATh = simple_strtol(tmpbuf, 0, 10); + pAd->Cts2SelfTh = FalseCCATh; + DBGPRINT(RT_DEBUG_OFF, ("FalseCCATh = %d\n",FalseCCATh)); + } + }while(0); + + os_free_mem(NULL, tmpbuf); + + return NDIS_STATUS_SUCCESS; +} + +#ifdef MULTIPLE_CARD_SUPPORT +/* record whether the card in the card list is used in the card file*/ +UINT8 MC_CardUsed[MAX_NUM_OF_MULTIPLE_CARD] = {0}; +/* record used card mac address in the card list*/ +static UINT8 MC_CardMac[MAX_NUM_OF_MULTIPLE_CARD][6]; + +BOOLEAN get_mac_from_eeprom(RTMP_ADAPTER *pAd, UCHAR *mac) +{ + USHORT addr, ee_addr; + INT idx; + + for (ee_addr = 0x04, idx = 0; ee_addr <= 0x08; ee_addr += 2, idx +=2) { + RT28xx_EEPROM_READ16(pAd, ee_addr, addr); + mac[idx] = (UCHAR)(addr & 0xff); + mac[idx + 1] = (UCHAR)(addr >> 8); + } + + return TRUE; +} + + +#ifdef RTMP_FLASH_SUPPORT +#define EEPROM_SEG_IN_NVM 2 /* segments for EEPROM in flash */ +#endif /* RTMP_FLASH_SUPPORT */ + +/* +======================================================================== +Routine Description: + Get card profile path. + +Arguments: + pAd + +Return Value: + TRUE - Find a card profile + FALSE - use default profile + +Note: +======================================================================== +*/ +BOOLEAN RTMP_CardInfoRead( + IN PRTMP_ADAPTER pAd) +{ +#define MC_SELECT_CARDID 0 /* use CARD ID (0 ~ 31) to identify different cards */ +#define MC_SELECT_MAC 1 /* use CARD MAC to identify different cards */ +#define MC_SELECT_CARDTYPE 2 /* use CARD type (abgn or bgn) to identify different cards */ + +#define LETTER_CASE_TRANSLATE(txt_p, card_id) \ + { UINT32 _len; char _char; \ + for(_len=0; _len Error opening %s\n", CARD_INFO_PATH)); + goto free_resource; + } + + /* card information file exists so reading the card information */ + memset(buffer, 0x00, MAX_INI_BUFFER_SIZE); + retval = RtmpOSFileRead(srcf, buffer, MAX_INI_BUFFER_SIZE); + if (retval < 0) + { + /* read fail */ + DBGPRINT(RT_DEBUG_TRACE, + ("--> Read %s error %d\n", CARD_INFO_PATH, -retval)); + } + else + { + /* get card selection method */ + memset(tmpbuf, 0x00, MAX_PARAM_BUFFER_SIZE); + card_select_method = MC_SELECT_CARDTYPE; /* default*/ + + if (RTMPGetKeyParameter("SELECT", tmpbuf, 256, buffer, TRUE)) + { + if (strcmp(tmpbuf, "CARDID") == 0) + card_select_method = MC_SELECT_CARDID; + else if (strcmp(tmpbuf, "MAC") == 0) + card_select_method = MC_SELECT_MAC; + else if (strcmp(tmpbuf, "CARDTYPE") == 0) + card_select_method = MC_SELECT_CARDTYPE; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("MC> Card Selection = %d\n", card_select_method)); + + /* init*/ + card_free_id = -1; + card_nouse_id = -1; + card_same_mac_id = -1; + card_match_id = -1; + + /* search current card information records*/ + for (card_index=0; card_index Free = %d, Same = %d, NOUSE = %d\n", + card_free_id, card_same_mac_id, card_nouse_id)); + + if ((card_same_mac_id >= 0) && + ((card_select_method == MC_SELECT_CARDID) || + (card_select_method == MC_SELECT_CARDTYPE))) + { + /* same MAC entry is found*/ + card_match_id = card_same_mac_id; + + if (card_select_method == MC_SELECT_CARDTYPE) + { + /* for CARDTYPE*/ + snprintf(card_id_buf, sizeof(card_id_buf), "%02dCARDTYPE%s", + card_match_id, RFIC_word); + + if ((start_ptr = (PUCHAR)rtstrstruncasecmp(buffer, card_id_buf)) != NULL) + { + /* we found the card ID*/ + LETTER_CASE_TRANSLATE(start_ptr, card_id_buf); + } + } + } + else + { + /* the card is 1st plug-in, try to find the match card profile*/ + switch(card_select_method) + { + case MC_SELECT_CARDID: /* CARDID*/ + default: + if (card_free_id >= 0) + card_match_id = card_free_id; + else + card_match_id = card_nouse_id; + break; + + case MC_SELECT_MAC: /* MAC*/ +#ifdef RTMP_FLASH_SUPPORT + memcpy(&mac[0], &mac_maybe[segment][0], MAC_ADDR_LEN); +#endif /* RTMP_FLASH_SUPPORT */ + snprintf(card_id_buf, sizeof(card_id_buf), "MAC%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5]); + + /* try to find the key word in the card file */ + if ((start_ptr = (PUCHAR)rtstrstruncasecmp(buffer, card_id_buf)) != NULL) + { + LETTER_CASE_TRANSLATE(start_ptr, card_id_buf); + + /* get the row ID (2 ASCII characters) */ + start_ptr -= 2; + card_id_buf[0] = *(start_ptr); + card_id_buf[1] = *(start_ptr+1); + card_id_buf[2] = 0x00; + card_match_id = simple_strtol(card_id_buf, 0, 10); +#ifdef RTMP_FLASH_SUPPORT + if (MC_CardUsed[card_match_id] == 1) + { + /* try again to find the key word in the card file by the other MAC address */ + segment += 1; + memcpy(&mac[0], &mac_maybe[segment][0], MAC_ADDR_LEN); + snprintf(card_id_buf, sizeof(card_id_buf), "MAC%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5]); + + if ((start_ptr = (PUCHAR)rtstrstruncasecmp(buffer, card_id_buf)) != NULL) + { + LETTER_CASE_TRANSLATE(start_ptr, card_id_buf); + + /* get the row ID (2 ASCII characters) */ + start_ptr -= 2; + card_id_buf[0] = *(start_ptr); + card_id_buf[1] = *(start_ptr+1); + card_id_buf[2] = 0x00; + card_match_id = simple_strtol(card_id_buf, 0, 10); + } + } +#endif /* RTMP_FLASH_SUPPORT */ + } + break; + + case MC_SELECT_CARDTYPE: /* CARDTYPE*/ + card_nouse_id = -1; + + for(card_index=0; + card_index= 0) + { + /* make up search keyword*/ + switch(card_select_method) + { + case MC_SELECT_CARDID: /* CARDID*/ + snprintf(card_id_buf, sizeof(card_id_buf), "%02dCARDID", card_match_id); + break; + + case MC_SELECT_MAC: /* MAC*/ + snprintf(card_id_buf, sizeof(card_id_buf), + "%02dmac%02x:%02x:%02x:%02x:%02x:%02x", + card_match_id, + mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5]); + break; + + case MC_SELECT_CARDTYPE: /* CARDTYPE*/ + default: + snprintf(card_id_buf, sizeof(card_id_buf), "%02dcardtype%s", + card_match_id, RFIC_word); + break; + } + + DBGPRINT(RT_DEBUG_TRACE, ("Search Keyword = %s\n", card_id_buf)); + + /* read card file path*/ + if (RTMPGetKeyParameter(card_id_buf, tmpbuf, 256, buffer, TRUE)) + { + if (strlen(tmpbuf) < sizeof(pAd->MC_FileName)) + { + /* backup card information*/ + pAd->MC_RowID = card_match_id; /* base 0 */ + /* + If we are run in Multicard mode, the eeinit shall execute + here instead of NICReadEEPROMParameters() + */ + if (pAd->chipOps.eeinit) + pAd->chipOps.eeinit(pAd); + + get_mac_from_eeprom(pAd, &mac[0]); + MC_CardUsed[card_match_id] = 1; + memcpy(MC_CardMac[card_match_id], mac, sizeof(mac)); + + /* backup card file path*/ + NdisMoveMemory(pAd->MC_FileName, tmpbuf , strlen(tmpbuf)); + pAd->MC_FileName[strlen(tmpbuf)] = '\0'; + flg_match_ok = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, + ("Card Profile Name = %s\n", pAd->MC_FileName)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, + ("Card Profile Name length too large!\n")); + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, + ("Can not find search key word in card.dat!\n")); + } + + if ((flg_match_ok != TRUE) && + (card_match_id < MAX_NUM_OF_MULTIPLE_CARD)) + { + MC_CardUsed[card_match_id] = 0; + memset(MC_CardMac[card_match_id], 0, sizeof(mac)); + } + } /* if (card_match_id >= 0)*/ + } + + +/* close file*/ +retval = RtmpOSFileClose(srcf); + +free_resource: +RtmpOSFSInfoChange(&osFSInfo, FALSE); +os_free_mem(NULL, buffer); +os_free_mem(NULL, tmpbuf); + +return flg_match_ok; +} +#endif /* MULTIPLE_CARD_SUPPORT */ + + +#ifdef WSC_INCLUDED +void rtmp_read_wsc_user_parms( + PWSC_CTRL pWscControl, + RTMP_STRING *tmpbuf, + RTMP_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 +// TODO: shiang-usw, for MT76x0 series, currently cannot use this function! +NDIS_STATUS RTMPSetSingleSKUParameters( + IN RTMP_ADAPTER *pAd) +{ + RTMP_STRING *buffer; + RTMP_STRING *readline, *token; + RTMP_OS_FD srcf; + INT retval; + RTMP_STRING *ptr; + int index, i; + CH_POWER *StartCh = NULL; + UCHAR channel, *temp; + RTMP_OS_FS_INFO osFSInfo; + + DlListInit(&pAd->SingleSkuPwrList); + + /* init*/ + os_alloc_mem(NULL, (UCHAR **)&buffer, MAX_INI_BUFFER_SIZE); + if (buffer == NULL) + return FALSE; + + RtmpOSFSInfoChange(&osFSInfo, TRUE); + /* open card information file*/ + srcf = RtmpOSFileOpen(get_single_sku_path(), O_RDONLY, 0); + if (IS_FILE_OPEN_ERR(srcf)) + { + /* card information file does not exist */ + DBGPRINT(RT_DEBUG_TRACE, + ("--> Error opening %s\n", get_single_sku_path())); + goto free_resource; + } + + +#ifdef RTMP_INTERNAL_TX_ALC + if (pAd->TxPowerCtrl.bInternalTxALC != TRUE) +#endif /* RTMP_INTERNAL_TX_ALC */ + { + } + + /* card information file exists so reading the card information */ + NdisZeroMemory(buffer, MAX_INI_BUFFER_SIZE); + retval = RtmpOSFileRead(srcf, buffer, MAX_INI_BUFFER_SIZE); + if (retval < 0) + { + /* read fail */ + DBGPRINT(RT_DEBUG_TRACE, ("--> Read %s error %d\n", get_single_sku_path(), -retval)); + } + else + { + for ( readline = ptr = buffer, index=0; (ptr = strchr(readline, '\n')) != NULL; readline = ptr + 1, index++ ) + { + *ptr = '\0'; + + if ( readline[0] == '#' ) + continue; + + if ( !strncmp(readline, "ch", 2) ) + { + + CH_POWER *pwr = NULL; + + os_alloc_mem(NULL, (UCHAR **)&pwr, sizeof(*pwr)); + NdisZeroMemory(pwr, sizeof(*pwr)); + + token= rstrtok(readline +2 ," "); + channel = simple_strtol(token, 0, 10); + pwr->StartChannel = channel; + + if (pwr->StartChannel <= 14) + { + for ( i= 0 ; i < SINGLE_SKU_TABLE_CCK_LENGTH ; i++ ) + { + token = rstrtok(NULL ," "); + if ( token == NULL ) + break; + pwr->PwrCCK[i] = simple_strtol(token, 0, 10) * 2; + } + } + + for ( i= 0 ; i < SINGLE_SKU_TABLE_OFDM_LENGTH ; i++ ) + { + token = rstrtok(NULL ," "); + if ( token == NULL ) + break; + pwr->PwrOFDM[i] = simple_strtol(token, 0, 10) *2; + } + + for ( i= 0 ; i < SINGLE_SKU_TABLE_HT_LENGTH ; i++ ) + { + token = rstrtok(NULL ," "); + if ( token == NULL ) + break; + pwr->PwrHT20[i] = simple_strtol(token, 0, 10) *2; + } + + for ( i= 0 ; i < SINGLE_SKU_TABLE_HT_LENGTH ; i++ ) + { + token = rstrtok(NULL ," "); + if ( token == NULL ) + break; + pwr->PwrHT40[i] = simple_strtol(token, 0, 10) *2; + } +#ifdef DOT11_VHT_AC + if (pwr->StartChannel > 14) + { + for ( i= 0 ; i < SINGLE_SKU_TABLE_VHT_LENGTH ; i++ ) + { + token = rstrtok(NULL ," "); + if ( token == NULL ) + break; + pwr->PwrVHT80[i] = simple_strtol(token, 0, 10) *2; + } + } +#endif /* DOT11_VHT_AC */ + if ( StartCh == NULL ) + { + StartCh = pwr; + DlListAddTail(&pAd->SingleSkuPwrList, &pwr->List); + } + else + { + BOOLEAN isSame = TRUE; + + if (pwr->StartChannel <= 14) + { + 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 ) + { + for ( i= 0 ; i < SINGLE_SKU_TABLE_VHT_LENGTH ; i++ ) + { + if ( StartCh->PwrVHT80[i] != pwr->PwrVHT80[i] ) + { + isSame = FALSE; + break; + } + } + } + + if ( isSame == TRUE ) + { + os_free_mem(NULL, pwr); + } + else + { + StartCh = pwr; + DlListAddTail(&pAd->SingleSkuPwrList, &StartCh->List); + pwr = NULL; + } + + } + StartCh->num ++; + os_alloc_mem(pAd, (PUCHAR *)&temp, StartCh->num); + if ( StartCh->Channel != NULL ) + { + NdisMoveMemory(temp, StartCh->Channel, StartCh->num-1); + os_free_mem(pAd, StartCh->Channel); + } + StartCh->Channel = temp; + StartCh->Channel[StartCh->num-1] = channel; + } + } + } + + { + CH_POWER *ch, *ch_temp; + DlListForEachSafe(ch, ch_temp, &pAd->SingleSkuPwrList, CH_POWER, List) + { + int i; + DBGPRINT(RT_DEBUG_TRACE,("start ch = %d, ch->num = %d\n", ch->StartChannel, ch->num)); + + DBGPRINT(RT_DEBUG_TRACE, ("Channel: ")); + for ( i = 0 ; i < ch->num ; i++ ) + DBGPRINT(RT_DEBUG_TRACE,("%d ", ch->Channel[i])); + DBGPRINT(RT_DEBUG_TRACE,("\n")); + + DBGPRINT(RT_DEBUG_TRACE, ("CCK: ")); + for ( i= 0 ; i < SINGLE_SKU_TABLE_CCK_LENGTH ; i++ ) + { + DBGPRINT(RT_DEBUG_TRACE,("%d ", ch->PwrCCK[i])); + } + DBGPRINT(RT_DEBUG_TRACE,("\n")); + + DBGPRINT(RT_DEBUG_TRACE, ("OFDM: ")); + for ( i= 0 ; i < SINGLE_SKU_TABLE_OFDM_LENGTH ; i++ ) + { + DBGPRINT(RT_DEBUG_TRACE,("%d ", ch->PwrOFDM[i])); + } + DBGPRINT(RT_DEBUG_TRACE,("\n")); + + DBGPRINT(RT_DEBUG_TRACE, ("HT20: ")); + for ( i= 0 ; i < SINGLE_SKU_TABLE_HT_LENGTH ; i++ ) + { + DBGPRINT(RT_DEBUG_TRACE, ("%d ", ch->PwrHT20[i])); + } + DBGPRINT(RT_DEBUG_TRACE,("\n")); + + DBGPRINT(RT_DEBUG_TRACE, ("HT40: ")); + for ( i= 0 ; i < SINGLE_SKU_TABLE_HT_LENGTH ; i++ ) + { + DBGPRINT(RT_DEBUG_TRACE,("%d ", ch->PwrHT40[i])); + } + DBGPRINT(RT_DEBUG_TRACE,("\n")); + + DBGPRINT(RT_DEBUG_TRACE, ("VHT80: ")); + for ( i= 0 ; i < SINGLE_SKU_TABLE_VHT_LENGTH ; i++ ) + { + DBGPRINT(RT_DEBUG_TRACE,("%d ", ch->PwrVHT80[i])); + } + DBGPRINT(RT_DEBUG_TRACE,("\n")); + } + } + + /* close file*/ + retval = RtmpOSFileClose(srcf); + +free_resource: + RtmpOSFSInfoChange(&osFSInfo, FALSE); + + os_free_mem(NULL, buffer); + return TRUE; +} + + +UCHAR GetSkuChannelBasePwr( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel) +{ + CH_POWER *ch, *ch_temp; + UCHAR start_ch; + UCHAR base_pwr = pAd->DefaultTargetPwr; + UINT8 i, j; + + DlListForEachSafe(ch, ch_temp, &pAd->SingleSkuPwrList, CH_POWER, List) + { + start_ch = ch->StartChannel; + + if ( channel >= start_ch ) + { + for ( j = 0; j < ch->num; j++ ) + { + if ( channel == ch->Channel[j] ) + { + for ( i= 0 ; i < SINGLE_SKU_TABLE_CCK_LENGTH ; i++ ) + { + if ( base_pwr > ch->PwrCCK[i] ) + base_pwr = ch->PwrCCK[i]; + } + + for ( i= 0 ; i < SINGLE_SKU_TABLE_OFDM_LENGTH ; i++ ) + { + if ( base_pwr > ch->PwrOFDM[i] ) + base_pwr = ch->PwrOFDM[i]; + } + + for ( i= 0 ; i < SINGLE_SKU_TABLE_HT_LENGTH ; i++ ) + { + if ( base_pwr > ch->PwrHT20[i] ) + base_pwr = ch->PwrHT20[i]; + } + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + for ( i= 0 ; i < SINGLE_SKU_TABLE_HT_LENGTH ; i++ ) + { + if ( ch->PwrHT40[i] == 0 ) + break; + + if ( base_pwr > ch->PwrHT40[i] ) + base_pwr = ch->PwrHT40[i]; + } + } + break; + } + } + } + } + + return base_pwr; + +} + +#define SKU_PHYMODE_CCK_1M_2M 0 +#define SKU_PHYMODE_CCK_5M_11M 1 +#define SKU_PHYMODE_OFDM_6M_9M 2 +#define SKU_PHYMODE_OFDM_12M_18M 3 +#define SKU_PHYMODE_OFDM_24M_36M 4 +#define SKU_PHYMODE_OFDM_48M_54M 5 +#define SKU_PHYMODE_HT_MCS0_MCS1 6 +#define SKU_PHYMODE_HT_MCS2_MCS3 7 +#define SKU_PHYMODE_HT_MCS4_MCS5 8 +#define SKU_PHYMODE_HT_MCS6_MCS7 9 +#define SKU_PHYMODE_HT_MCS8_MCS9 10 +#define SKU_PHYMODE_HT_MCS10_MCS11 11 +#define SKU_PHYMODE_HT_MCS12_MCS13 12 +#define SKU_PHYMODE_HT_MCS14_MCS15 13 +#define SKU_PHYMODE_STBC_MCS0_MCS1 14 +#define SKU_PHYMODE_STBC_MCS2_MCS3 15 +#define SKU_PHYMODE_STBC_MCS4_MCS5 16 +#define SKU_PHYMODE_STBC_MCS6_MCS7 17 + + +VOID 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; + } +} + + +#ifdef RLT_MAC +INT32 GetSkuPAModePwr( + IN PRTMP_ADAPTER pAd, + IN UCHAR PAMode) +{ + INT32 pa_mode_pwr = 0; + + switch ( PAMode ) + { + case SKU_PHYMODE_CCK_1M_2M: + pa_mode_pwr = RF_PA_MODE_CCK_1M; + break; + case SKU_PHYMODE_CCK_5M_11M: + pa_mode_pwr = RF_PA_MODE_CCK_5M; + break; + case SKU_PHYMODE_OFDM_6M_9M: + pa_mode_pwr = RF_PA_MODE_OFDM_6M; + break; + case SKU_PHYMODE_OFDM_12M_18M: + pa_mode_pwr = RF_PA_MODE_OFDM_12M; + break; + case SKU_PHYMODE_OFDM_24M_36M: + pa_mode_pwr = RF_PA_MODE_OFDM_24M; + break; + case SKU_PHYMODE_OFDM_48M_54M: + pa_mode_pwr = RF_PA_MODE_OFDM_48M; + break; + case SKU_PHYMODE_HT_MCS0_MCS1: + case SKU_PHYMODE_STBC_MCS0_MCS1: + pa_mode_pwr = RF_PA_MODE_HT_MCS0; + break; + case SKU_PHYMODE_HT_MCS2_MCS3: + case SKU_PHYMODE_STBC_MCS2_MCS3: + pa_mode_pwr = RF_PA_MODE_HT_MCS2; + break; + case SKU_PHYMODE_HT_MCS4_MCS5: + case SKU_PHYMODE_STBC_MCS4_MCS5: + pa_mode_pwr = RF_PA_MODE_HT_MCS4; + break; + case SKU_PHYMODE_HT_MCS6_MCS7: + case SKU_PHYMODE_STBC_MCS6_MCS7: + pa_mode_pwr = RF_PA_MODE_HT_MCS6; + break; + case SKU_PHYMODE_HT_MCS8_MCS9: + pa_mode_pwr = RF_PA_MODE_HT_MCS8; + break; + case SKU_PHYMODE_HT_MCS10_MCS11: + pa_mode_pwr = RF_PA_MODE_HT_MCS10; + break; + case SKU_PHYMODE_HT_MCS12_MCS13: + pa_mode_pwr = RF_PA_MODE_HT_MCS12; + break; + case SKU_PHYMODE_HT_MCS14_MCS15: + pa_mode_pwr = RF_PA_MODE_HT_MCS14; + break; + default: + break; + } + + return pa_mode_pwr; +} + + +UCHAR GetSkuRatePwr( + IN PRTMP_ADAPTER pAd, + IN CHAR phymode, + IN UCHAR channel, + IN UCHAR bw) +{ + UINT8 i; + CH_POWER *ch, *ch_temp; + UCHAR start_ch; + UCHAR rate_pwr = pAd->DefaultTargetPwr; + UCHAR max_pwr; + INT32 pwr_diff; + + DlListForEachSafe(ch, ch_temp, &pAd->SingleSkuPwrList, CH_POWER, List) + { + start_ch = ch->StartChannel; + + if ( channel >= start_ch ) + { + for ( i = 0; i < ch->num; i++ ) + { + if ( channel == ch->Channel[i] ) + { + 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 = GetSkuPAModePwr(pAd, phymode) + (pAd->SingleSkuRatePwrDiff[phymode] << 12) + 2048; + pwr_diff = pwr_diff >> 12; + max_pwr = pAd->DefaultTargetPwr + pwr_diff; + + if ( rate_pwr > max_pwr ) + rate_pwr = max_pwr; + + return rate_pwr; + +} + + +VOID UpdateSkuRatePwr( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel, + IN UCHAR bw, + IN CHAR base_pwr) +{ + INT32 sku_rate_pwr; + INT32 rate_pwr; + INT32 mcs_digital_pwr, pa_mode_pwr, diff_pwr; + UINT32 data, Adata, Gdata; + UCHAR BBPR4, BBPR178; + UCHAR i; + CHAR rate_table[18]; + + DBGPRINT(RT_DEBUG_TRACE, ("channel = %d, bw = %d\n", channel, bw)); + + for ( i = 0 ; i < 18; i++ ) + { + sku_rate_pwr = GetSkuRatePwr(pAd, i, channel, bw); + DBGPRINT(RT_DEBUG_TRACE, ("sku_rate_pwr = %d", sku_rate_pwr)); + sku_rate_pwr = sku_rate_pwr << 12; // sku_rate_power * 4096 + DBGPRINT(RT_DEBUG_TRACE, ("\tsku_rate_pwr = %d\n", sku_rate_pwr)); + + if ( i < SKU_PHYMODE_CCK_5M_11M ) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBPR4); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R178, &BBPR178); + if ( BBPR4 & 0x20 ) + { + if ( BBPR178 == 0 ) + { + mcs_digital_pwr = 9830; // 8192 * 1.2 + } + else + { + mcs_digital_pwr = 18022; // 8192 * 2.2 + } + } + else + { + if ( BBPR178 == 0 ) + { + mcs_digital_pwr = 24576; // 8192 * 3 + } + else + { + mcs_digital_pwr = 819; /// 8192 * 0.1 + } + + } + } + else + { + mcs_digital_pwr = 0; + } + + pa_mode_pwr = GetSkuPAModePwr(pAd, i); + + DBGPRINT(RT_DEBUG_TRACE, ("base_pwr = %d", base_pwr)); + rate_pwr = base_pwr << 12; + DBGPRINT(RT_DEBUG_TRACE, ("\t base_pwr = %d\n", rate_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("mcs_digital_pwr = %d\n", mcs_digital_pwr)); + DBGPRINT(RT_DEBUG_TRACE, ("pa_mode_pwr = %d\n", pa_mode_pwr)); + rate_pwr = rate_pwr + mcs_digital_pwr + pa_mode_pwr; + DBGPRINT(RT_DEBUG_TRACE, ("rate_pwr = %d\n", rate_pwr)); + diff_pwr = sku_rate_pwr - rate_pwr; + DBGPRINT(RT_DEBUG_TRACE, ("diff_pwr = %d", diff_pwr)); + diff_pwr = diff_pwr >> 12; + DBGPRINT(RT_DEBUG_TRACE, ("\tdiff_pwr = %d\n", diff_pwr)); + + rate_table[i] = diff_pwr -1; + } + + for ( i = 0 ; i < 5; i++ ) + { + data = 0; + Adata = 0; + Gdata = 0; + + data = (rate_table[i*4] & 0x3F )+ ((rate_table[i*4 + 1] &0x3F) << 8); + Adata = ((rate_table[i*4] + pAd->chipCap.Apwrdelta ) & 0x3F )+ ( ((rate_table[i*4 + 1] + pAd->chipCap.Apwrdelta) & 0x3F) << 8); + Gdata = ((rate_table[i*4] + pAd->chipCap.Gpwrdelta ) & 0x3F ) + ( ((rate_table[i*4 + 1] + pAd->chipCap.Gpwrdelta) & 0x3F) << 8); + + if ( i != 4 ) + { + data |= ((rate_table[i*4 + 2] &0x3F) << 16 )+ ((rate_table[i*4 + 3] & 0x3F) << 24); + Adata |= ( ((rate_table[i*4 + 2] + pAd->chipCap.Apwrdelta ) & 0x3F) << 16) + ( ((rate_table[i*4 + 3] + pAd->chipCap.Apwrdelta) & 0x3F) << 24); + Gdata |= ( ((rate_table[i*4 + 2] + pAd->chipCap.Gpwrdelta ) & 0x3F) << 16) + ( ((rate_table[i*4 + 3] + pAd->chipCap.Gpwrdelta) & 0x3F) << 24); + } + + /* For 20M/40M Power Delta issue */ + pAd->Tx20MPwrCfgABand[i] = data; + pAd->Tx20MPwrCfgGBand[i] = data; + pAd->Tx40MPwrCfgABand[i] = Adata; + pAd->Tx40MPwrCfgGBand[i] = Gdata; + + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_0 + i*4, data); + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("20MHz BW, 2.4G band-%08x, Adata = %08x, Gdata = %08x \n", data, Adata, Gdata)); + } + + /* Extra set MAC registers to compensate Tx power if any */ + RTMP_CHIP_ASIC_EXTRA_POWER_OVER_MAC(pAd); + +} + +#endif /*RTL_MAC*/ + +#endif /* SINGLE_SKU_V2 */ + + +INT32 ralinkrate[] = { +/* CCK */ +2, 4, 11, 22, +/* OFDM */ +12, 18, 24, 36, 48, 72, 96, 108, +/* 20MHz, 800ns GI, MCS: 0 ~ 15 */ +13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260, +/* 20MHz, 800ns GI, MCS: 16 ~ 23 */ +39, 78, 117, 156, 234, 312, 351, 390, +/* 40MHz, 800ns GI, MCS: 0 ~ 15 */ +27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, +/* 40MHz, 800ns GI, MCS: 16 ~ 23 */ +81, 162, 243, 324, 486, 648, 729, 810, +/* 20MHz, 400ns GI, MCS: 0 ~ 15 */ +14, 29, 43, 57, 87, 115, 130, 144, 29, 59, 87, 115, 173, 230, 260, 288, +/* 20MHz, 400ns GI, MCS: 16 ~ 23 */ +43, 87, 130, 173, 260, 317, 390, 433, +/* 40MHz, 400ns GI, MCS: 0 ~ 15 */ +30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, +/* 40MHz, 400ns GI, MCS: 16 ~ 23 */ +90, 180, 270, 360, 540, 720, 810, 900}; + +UINT32 RT_RateSize = sizeof(ralinkrate); diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_radar.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_radar.c new file mode 100644 index 000000000..885edb066 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_radar.c @@ -0,0 +1,428 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + cmm_radar.c + + Abstract: + CS/DFS common functions. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#include "rt_config.h" + +/*----- 802.11H -----*/ + +/* Periodic Radar detection, switch channel will occur in RTMPHandleTBTTInterrupt()*/ +/* Before switch channel, driver needs doing channel switch announcement.*/ +VOID RadarDetectPeriodic( + IN PRTMP_ADAPTER pAd) +{ + INT i, ChIdx = 0, bAnyUnavailableChannel = FALSE; + + /* + 1. APStart(), CalBufTime = 0; + 2. if bAnyUnavailableChannel, CalBufTime = DEFAULT_CAL_BUF_TIME; + 3. if Calibrated, CalBufTime = DEFAULT_CAL_BUF_TIME_MAX; + */ + for (i=0; iChannelListNum; i++) + { + if (pAd->ChannelList[i].RemainingTimeForUse != 0) + { + bAnyUnavailableChannel = TRUE; + } + + if (pAd->CommonCfg.Channel == pAd->ChannelList[i].Channel) + { + ChIdx = i; + } + } + + if (bAnyUnavailableChannel) + pAd->Dot11_H.CalBufTime = DEFAULT_CAL_BUF_TIME; + + if (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) + { + /* In Silent Mode, RDCount is use to check with the CAC Time */ + if (pAd->Dot11_H.RDCount++ > pAd->Dot11_H.ChMovingTime && + pAd->ChannelList[ChIdx].RemainingTimeForUse == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("Not found radar signal, start send beacon and radar detection in service monitor\n\n")); + pAd->Dot11_H.RDMode = RD_NORMAL_MODE; + AsicEnableBssSync(pAd, pAd->CommonCfg.BeaconPeriod); + pAd->Dot11_H.RDCount = 0; + } + } + else if (pAd->Dot11_H.RDMode == RD_NORMAL_MODE) + { + if (!bAnyUnavailableChannel) + { + pAd->Dot11_H.RDCount++; + /* In Normal Mode, RDCount is use to check with the CalBufTime */ + if ((pAd->Dot11_H.RDCount >= pAd->Dot11_H.CalBufTime)) + { + pAd->Dot11_H.CalBufTime = DEFAULT_CAL_BUF_TIME_MAX; + } + } + } +} + +/* + ======================================================================== + + Routine Description: + Radar channel check routine + + Arguments: + pAd Pointer to our adapter + + Return Value: + TRUE need to do radar detect + FALSE need not to do radar detect + + ======================================================================== +*/ +BOOLEAN RadarChannelCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Ch) +{ + INT i; + BOOLEAN result = FALSE; + + for (i=0; iChannelListNum; i++) + { + if (Ch == pAd->ChannelList[i].Channel) + { + result = pAd->ChannelList[i].DfsReq; + break; + } + } + + return result; +} + + +/* + ======================================================================== + + Routine Description: + Determine the current radar state + + Arguments: + pAd Pointer to our adapter + + Return Value: + + ======================================================================== +*/ +VOID RadarStateCheck( + IN PRTMP_ADAPTER pAd) +{ + pAd->Dot11_H.CalBufTime = 0; + + if ((pAd->CommonCfg.Channel > 14) && + (pAd->CommonCfg.bIEEE80211H == 1) && + RadarChannelCheck(pAd, pAd->CommonCfg.Channel)) + { + pAd->Dot11_H.RDMode = RD_SILENCE_MODE; + pAd->Dot11_H.RDCount = 0; + pAd->Dot11_H.InServiceMonitorCount = 0; + } + else + pAd->Dot11_H.RDMode = RD_NORMAL_MODE; + +#ifdef CARRIER_DETECTION_SUPPORT + if ((pAd->CommonCfg.RDDurRegion == JAP) + || (pAd->CommonCfg.RDDurRegion == JAP_W53) + || (pAd->CommonCfg.RDDurRegion == JAP_W56)) + { + + if ((pAd->CommonCfg.Channel > 14) || + (pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40)) + { + pAd->CommonCfg.CarrierDetect.Enable = TRUE; + } + } +#endif /* CARRIER_DETECTION_SUPPORT */ +} + + +ULONG JapRadarType( + IN PRTMP_ADAPTER pAd) +{ + ULONG i; + const UCHAR Channel[15]={52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}; + + if (pAd->CommonCfg.RDDurRegion != JAP) + { + return pAd->CommonCfg.RDDurRegion; + } + + for (i=0; i<15; i++) + { + if (pAd->CommonCfg.Channel == Channel[i]) + { + break; + } + } + + if (i < 4) + return JAP_W53; + else if (i < 15) + return JAP_W56; + else + return JAP; /* W52*/ + +} + + +UCHAR get_channel_by_reference( + IN PRTMP_ADAPTER pAd, + IN UINT8 mode) +{ + UCHAR ch = 0; + INT ch_idx; + + switch (mode) + { + case 1: + { + USHORT min_time = 0xFFFF; + /* select channel with least RemainingTimeForUse */ + for ( ch_idx = 0; ch_idx < pAd->ChannelListNum; ch_idx++) + { + if (pAd->ChannelList[ch_idx].RemainingTimeForUse < min_time) + { + min_time = pAd->ChannelList[ch_idx].RemainingTimeForUse; + ch = pAd->ChannelList[ch_idx].Channel; + } + } + break; + } + + default: + { + ch = FirstChannel(pAd); + break; + } + } + + DBGPRINT(RT_DEBUG_TRACE,("%s(): mode = %u, ch = %u\n", + __FUNCTION__, mode, ch)); + return ch; +} + + +#ifdef CONFIG_AP_SUPPORT +/* + ======================================================================== + + Routine Description: + Channel switching count down process upon radar detection + + Arguments: + pAd Pointer to our adapter + + ======================================================================== +*/ +VOID ChannelSwitchingCountDownProc( + IN PRTMP_ADAPTER pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("%s():Channel Switching...(%d/%d)\n", + __FUNCTION__, pAd->Dot11_H.CSCount, pAd->Dot11_H.CSPeriod)); + + pAd->Dot11_H.CSCount++; + if (pAd->Dot11_H.CSCount >= pAd->Dot11_H.CSPeriod) + { +#ifdef DFS_SUPPORT + pAd->CommonCfg.RadarDetect.DFSAPRestart = 1; + schedule_dfs_task(pAd); +#else + APStop(pAd); + APStartUp(pAd); +#endif /* !DFS_SUPPORT */ + } +} +#endif /* CONFIG_AP_SUPPORT */ + +/* + ========================================================================== + Description: + Set channel switch Period + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_CSPeriod_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *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 RTMP_STRING *arg) +{ + USHORT Value; + + Value = (USHORT) simple_strtol(arg, 0, 10); + + pAd->Dot11_H.ChMovingTime = Value; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: %d\n", __FUNCTION__, + pAd->Dot11_H.ChMovingTime)); + + return TRUE; +} + + +/* + ========================================================================== + Description: + Reset channel block status. + Arguments: + pAd Pointer to our adapter + arg Not used + + Return Value: + None + + Note: + Usage: + 1.) iwpriv ra0 set ChMovTime=[value] + ========================================================================== +*/ +INT Set_BlockChReset_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *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 RTMP_STRING *arg) +{ +#ifdef DFS_SUPPORT + UINT8 idx; + PRADAR_DETECT_STRUCT pRadarDetect = &pAd->CommonCfg.RadarDetect; + PDFS_PROGRAM_PARAM pDfsProgramParam = &pRadarDetect->DfsProgramParam; + PDFS_SW_DETECT_PARAM pDfsSwParam = &pRadarDetect->DfsSwParam; + PCHAR RDMode[]= {"Normal State", "Switching State", "Silent State"}; + + printk("DFSUseTasklet = %d\n", pRadarDetect->use_tasklet); + printk("McuRadarDebug = %x\n", (unsigned int)pRadarDetect->McuRadarDebug); + printk("PollTime = %d\n", pRadarDetect->PollTime); + printk("ChEnable = %d (0x%x)\n", pDfsProgramParam->ChEnable, pDfsProgramParam->ChEnable); + printk("DeltaDelay = %d\n", pDfsProgramParam->DeltaDelay); + printk("PeriodErr = %d\n", pDfsSwParam->dfs_period_err); + printk("MaxPeriod = %d\n", (unsigned int)pDfsSwParam->dfs_max_period); + printk("Ch0LErr = %d\n", pDfsSwParam->dfs_width_ch0_err_L); + printk("Ch0HErr = %d\n", pDfsSwParam->dfs_width_ch0_err_H); + printk("Ch1Shift = %d\n", pDfsSwParam->dfs_width_diff_ch1_Shift); + printk("Ch2Shift = %d\n", pDfsSwParam->dfs_width_diff_ch2_Shift); + printk("DfsRssiHigh = %d\n", pRadarDetect->DfsRssiHigh); + printk("DfsRssiLow = %d\n", pRadarDetect->DfsRssiLow); + printk("DfsSwDisable = %u\n", pRadarDetect->bDfsSwDisable); + printk("CheckLoop = %d\n", pDfsSwParam->dfs_check_loop); + printk("DeclareThres = %d\n", pDfsSwParam->dfs_declare_thres); + for (idx=0; idx < pAd->chipCap.DfsEngineNum; idx++) + printk("sw_idx[%u] = %u\n", idx, pDfsSwParam->sw_idx[idx]); + for (idx=0; idx < pAd->chipCap.DfsEngineNum; idx++) + printk("hw_idx[%u] = %u\n", idx, pDfsSwParam->hw_idx[idx]); + + printk("pAd->Dot11_H.ChMovingTime = %d\n", pAd->Dot11_H.ChMovingTime); + printk("pAd->Dot11_H.RDMode = %s\n", RDMode[pAd->Dot11_H.RDMode]); + printk("pAd->Dot11_H.RDCount = %d\n", pAd->Dot11_H.RDCount); + printk("pAd->Dot11_H.CalBufTime = %d\n", pAd->Dot11_H.CalBufTime); +#endif /* DFS_SUPPORT */ + +#ifdef CARRIER_DETECTION_SUPPORT + printk("pAd->CommonCfg.CarrierDetect.CD_State = %d\n", pAd->CommonCfg.CarrierDetect.CD_State); + printk("pAd->CommonCfg.CarrierDetect.criteria = %d\n", pAd->CommonCfg.CarrierDetect.criteria); + printk("pAd->CommonCfg.CarrierDetect.Delta = %d\n", pAd->CommonCfg.CarrierDetect.delta); + printk("pAd->CommonCfg.CarrierDetect.DivFlag = %d\n", pAd->CommonCfg.CarrierDetect.div_flag); + printk("pAd->CommonCfg.CarrierDetect.Threshold = %d(0x%x)\n", pAd->CommonCfg.CarrierDetect.threshold, pAd->CommonCfg.CarrierDetect.threshold); +#endif /* CARRIER_DETECTION_SUPPORT */ + + return TRUE; +} + +/* + ======================================================================== + Routine Description: + Control CCK_MRC Status + Arguments: + pAd Pointer to our adapter + Return Value: + + ======================================================================== +*/ +VOID CckMrcStatusCtrl(IN PRTMP_ADAPTER pAd) +{ +} + + +/* + ======================================================================== + Routine Description: + Enhance DFS/CS when using GLRT. + Arguments: + pAd Pointer to our adapter + Return Value: + + ======================================================================== +*/ +VOID RadarGLRTCompensate(IN PRTMP_ADAPTER pAd) +{ +} +#endif /*defined(DFS_SUPPORT) || defined(CARRIER_DETECTION_SUPPORT) */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_rf_cal.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_rf_cal.c new file mode 100644 index 000000000..0c3d58517 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_rf_cal.c @@ -0,0 +1,2996 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2009, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + cmm_rf_cal.c + + Abstract: + RF calibration and profile related functions + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Arvin Tai 2012/05/02 +*/ + +#include "rt_config.h" + +REG_PAIR RT6352_VGA_TABLE[] = +{/* Gain(dB), BBP_R66 */ + {0, 0x10}, + {2, 0x14}, + {4, 0x18}, + {6, 0x1C}, + {8, 0x20}, + {10, 0x30}, + {12, 0x34}, + {14, 0x38}, + {16, 0x3C}, + {18, 0x40}, + {20, 0x44}, + {22, 0x60}, + {24, 0x64}, + {26, 0x68}, + {28, 0x6C}, + {30, 0x70}, + {32, 0x74}, + {34, 0x78}, + {36, 0x7C}, +}; + +REG_PAIR RT6352_RFR3R4_TABLE[] = +{/* Gain(dB), RF_R3R4 */ + { 0, 0x4 }, + { 2, 0x5 }, + { 4, 0x6 }, + { 6, 0x7 }, + { 8, 0x8 }, + {10, 0xc }, + {12, 0xd }, + {14, 0xe }, + {16, 0xf }, + {18, 0x10}, + {20, 0x11}, + {22, 0x18}, + {24, 0x19}, + {26, 0x1a}, + {28, 0x1b}, + {30, 0x1c}, + {32, 0x1d}, + {34, 0x1e}, + {36, 0x1f}, +}; + + +UCHAR RT6352_VGA_TABLE_PARMS = (sizeof(RT6352_VGA_TABLE) / sizeof(REG_PAIR)); + +INT32 CalcRCalibrationCode( + IN PRTMP_ADAPTER pAd, + IN INT32 D1, + IN INT32 D2) +{ + INT32 CalCode; + + CalCode = ((D2 - D1) * 1000) / 43; + if((CalCode%10) >= 5) + CalCode += 10; + + CalCode = (CalCode / 10); + + return CalCode; +} + +/**************************************************************************** + * + * VOID R Calibraton + * + ****************************************************************************/ + +VOID R_Calibration( + IN PRTMP_ADAPTER pAd) +{ + UINT32 saveMacSysCtrl; + UCHAR saveRfB0R1, saveRfB0R34, saveRfB0R35; + UCHAR saveRfB5R4, saveRfB5R17, saveRfB5R18; + UCHAR saveRfB5R19, saveRfB5R20; + UCHAR saveBBPR22, saveBBPR47, saveBBPR49; + UCHAR byteValue = 0; + INT32 RCalCode; + UCHAR R_Cal_Code = 0; + CHAR D1 = 0, D2 = 0; + UCHAR RFValue; + UINT32 MAC_RF_BYPASS0, MAC_RF_CONTROL0, MAC_PWR_PIN_CFG; + + /* Save RF Register */ + RT635xReadRFRegister(pAd, RF_BANK0, RF_R01, &saveRfB0R1); + RT635xReadRFRegister(pAd, RF_BANK0, RF_R34, &saveRfB0R34); + RT635xReadRFRegister(pAd, RF_BANK0, RF_R35, &saveRfB0R35); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R04, &saveRfB5R4); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R17, &saveRfB5R17); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R18, &saveRfB5R18); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R19, &saveRfB5R19); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R20, &saveRfB5R20); + + /* save BBP registers */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R22, &saveBBPR22); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R47, &saveBBPR47); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &saveBBPR49); + + /* Save MAC registers */ + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &saveMacSysCtrl); + RTMP_IO_READ32(pAd, RTMP_RF_BYPASS0, &MAC_RF_BYPASS0); + RTMP_IO_READ32(pAd, RF_CONTROL0, &MAC_RF_CONTROL0); + RTMP_IO_READ32(pAd, PWR_PIN_CFG, &MAC_PWR_PIN_CFG); + + { + UINT32 macCfg, macStatus; + UINT32 MTxCycle, MRxCycle; + ULONG stTime, mt_time, mr_time; + + /* Disable MAC Tx and MAC Rx and wait MAC Tx/Rx status in idle state */ + /* MAC Tx */ + NdisGetSystemUpTime(&stTime); + AsicSetMacTxRx(pAd, ASIC_MAC_TX, FALSE); + 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); + AsicSetMacTxRx(pAd, ASIC_MAC_RX, FALSE); + for (MRxCycle = 0; MRxCycle < 10000; MRxCycle++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &macStatus); + if (macStatus & 0x2) + RtmpusecDelay(50); + else + break; + } + NdisGetSystemUpTime(&mr_time); + mr_time -= stTime; + if (MRxCycle == 10000) + { + DBGPRINT(RT_DEBUG_WARN, ("%s(cnt=%d,time=0x%lx):stop MRx, macStatus=%d!\n", + __FUNCTION__, MRxCycle, mr_time, macStatus)); + } + } + + /* RF bypass MAC */ + RFValue = (MAC_RF_BYPASS0 | 0x3004); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0, RFValue); + RFValue = (MAC_RF_CONTROL0 & (~0x3002)); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, RFValue); + + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, 0x27); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R17, 0x80); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, 0x83); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, 0x20); + + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, 0x00); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R34, 0x13); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R35, 0x00); + + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, 0x1); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, 0x04); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, 0x80); + RtmpusecDelay(100); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &byteValue); + if (byteValue > 128) + D1= byteValue - 256; + else + D1 = (CHAR)byteValue; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, 0x0); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R35, 0x01); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, 0x80); + RtmpusecDelay(100); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R49, &byteValue); + if (byteValue > 128) + D2= byteValue - 256; + else + D2 = (CHAR)byteValue; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, 0x0); + + RCalCode = CalcRCalibrationCode(pAd, D1, D2); + if (RCalCode < 0) + R_Cal_Code = 256 + RCalCode; + else + R_Cal_Code = (UCHAR)RCalCode; + + DBGPRINT(RT_DEBUG_ERROR, ("D1 = %d, D2 = %d, CalCode = %d !!!\n", D1, D2, RCalCode)); + + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R07, R_Cal_Code); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, 0x00); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &byteValue); + byteValue |= 0x1; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, byteValue); + RtmpOsMsDelay(1); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &byteValue); + byteValue &= (~0x1); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, byteValue); + + /* Restore RF Register */ + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, saveRfB0R1); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R34, saveRfB0R34); + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R35, saveRfB0R35); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, saveRfB5R4); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R17, saveRfB5R17); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, saveRfB5R18); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, saveRfB5R19); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, saveRfB5R20); + + /* Restore BBP registers */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R22, saveBBPR22); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R47, saveBBPR47); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R49, saveBBPR49); + + /* Restore registers */ + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0, MAC_RF_BYPASS0); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, MAC_RF_CONTROL0); + + /* Return to normal mode */ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, saveMacSysCtrl); + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, MAC_PWR_PIN_CFG); +} + +INT Set_TestRxIQCalibration_Proc( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *arg) +{ + DBGPRINT(RT_DEBUG_OFF, ("TestRxIQCalibration !!!\n")); + RXIQ_Calibration(pAd); + + return TRUE; +} + +INT Set_TestLoftTxIQCalibration_Proc( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *arg) +{ + UINT32 Value; + + Value = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_OFF, ("TestLOFTTxIQCalibration !!!\n")); + pAd->bCalibrationDone = FALSE; + //LOFT_IQ_Calibration_v2(pAd, TRUE, Value); + LOFT_IQ_Calibration(pAd); + pAd->bCalibrationDone = TRUE; + + return TRUE; +} + +VOID RtmpKickOutHwNullFrame( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bPrepareContent, + IN BOOLEAN bTransmit) +{ + UINT8 TXWISize = pAd->chipCap.TXWISize; + TXWI_STRUC NullTxWI, *pTxWI = NULL; + PUCHAR pNullFrame; + NDIS_STATUS NState; + PHEADER_802_11 pNullFr; + ULONG Length; + UCHAR *ptr; + UINT i; + UINT32 longValue, macStatus; + USHORT k_count = 0; + HTTRANSMIT_SETTING MlmeTransmit; + MAC_TX_INFO mac_info; + + if (bPrepareContent) + { + NState = MlmeAllocateMemory(pAd, (PUCHAR *)&pNullFrame); + + NdisZeroMemory(pNullFrame, 48); + + if (NState == NDIS_STATUS_SUCCESS) + { + pTxWI = &NullTxWI; + NdisZeroMemory(pTxWI, TXWISize); + + pNullFr = (PHEADER_802_11) pNullFrame; + Length = sizeof(HEADER_802_11); + + pNullFr->FC.Type = FC_TYPE_DATA; + pNullFr->FC.SubType = SUBTYPE_DATA_NULL; + pNullFr->FC.ToDs = 0; + pNullFr->FC.FrDs = 1; + + COPY_MAC_ADDR(pNullFr->Addr1, BROADCAST_ADDR); + COPY_MAC_ADDR(pNullFr->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pNullFr->Addr3, pAd->CurrentAddress); + + pNullFr->FC.PwrMgmt = 0; + + pNullFr->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, pAd->CommonCfg.TxRate, 14); + + /* sequence is increased in MlmeHardTx */ + pNullFr->Sequence = pAd->Sequence; + pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; /* next sequence */ + + MlmeTransmit.word = 0; + MlmeTransmit.field.MCS = 15; + MlmeTransmit.field.MODE = MODE_HTMIX; + MlmeTransmit.field.BW = 0; + + NdisZeroMemory((UCHAR *)&mac_info, sizeof(mac_info)); + mac_info.FRAG = FALSE; + + mac_info.CFACK = FALSE; + mac_info.InsTimestamp = FALSE; + mac_info.AMPDU = FALSE; + + mac_info.BM = IS_BM_MAC_ADDR(pNullFr->Addr1); + mac_info.Ack = FALSE; + mac_info.NSeq = TRUE; + mac_info.BASize = 0; + + mac_info.WCID = 1; + mac_info.Length = Length; + mac_info.PID = 15; + + mac_info.TID = 0; + mac_info.TxRate = 15; + mac_info.Txopmode = IFS_HTTXOP; + mac_info.Preamble = LONG_PREAMBLE; + mac_info.SpeEn = 1; + + write_tmac_info(pAd, (UCHAR *)pTxWI, &mac_info, &MlmeTransmit); + + pTxWI->TXWI_O.MCS = 15; + pTxWI->TXWI_O.PHYMODE = MODE_HTMIX; + pTxWI->TXWI_O.BW = 0; + + ptr = (PUCHAR)&NullTxWI; + +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, ptr, TYPE_TXWI); +#endif + for (i=0; i < TXWISize; i+=4) + { + longValue = *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + (*(ptr + 3) << 24); + + RTMP_IO_WRITE32(pAd, HW_CS_CTS_BASE + i, longValue); + + ptr += 4; + } + + ptr = pNullFrame; + +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); +#endif + for (i= 0; i< Length; i+=4) + { + longValue = *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + (*(ptr + 3) << 24); + + RTMP_IO_WRITE32(pAd, HW_CS_CTS_BASE + TXWISize+ i, longValue); + + ptr += 4; + } + } + + if (pNullFrame) + MlmeFreeMemory(pAd, pNullFrame); + } + + if (bTransmit) + { + /* kick NULL frame #0 */ + RTMP_IO_WRITE32(pAd, PBF_CTRL, 0x80); + + /* Check MAC Tx/Rx idle */ + for (k_count = 0; k_count < 200; k_count++) + { + RTMP_IO_READ32(pAd, PBF_CTRL, &macStatus); + if (macStatus & 0x80) + { + RtmpusecDelay(100); + } + else + { + break; + } + } + + if (k_count == 200) + { + DBGPRINT(RT_DEBUG_TRACE, ("Wait Null Frame SendOut to MAX !!!\n")); + } + } + + return; +} + +/**************************************************************************** + * + * VOID DPD Calibraton + * + ****************************************************************************/ + +/* (Workaround for IQ swap introduced AM-PM inversion) + Multiply the AM-PM in LUTs by -1 +*/ +VOID DPD_IQ_Swap_AM_PM_Inversion( + IN PRTMP_ADAPTER pAd, + IN UCHAR AntIdx) +{ + USHORT k_count = 0, PM_inv_upper = 0, PM_inv_lower = 0; + SHORT PM = 0, PM_inv = 0; + UCHAR PM_upper = 0, PM_lower = 0; + + if (AntIdx == 0) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x02); + else + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x04); + + /* Read out AM-PM one by one, multiply by (-1) and write it back */ + for (k_count = 0; k_count < 64; k_count++) + { + /* Read out the AM-PM value through BBP registers */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, ((4 * k_count) + 1)); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R188, &PM_upper); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, ((4 * k_count) + 2)); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R188, &PM_lower); + PM = (PM_upper * 256) + PM_lower; + + /* unsigned to signed conversion */ + if (PM > 512) + PM -= 1024; + + /* Invert the AM-PM value */ + PM_inv = PM * (-1); + + /* Signed to unsigned conversion */ + if(PM_inv < 0) + PM_inv += 1024; + + DBGPRINT(RT_DEBUG_WARN, ("PM (%d), PM_inv (%d)\n", PM, PM_inv)); + + /* Write back the AM-PM value through BBP registers */ + PM_inv_upper = (PM_inv / 256); + PM_inv_lower = (PM_inv % 256); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, ((4 * k_count) + 1)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, PM_inv_upper); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, ((4 * k_count) + 2)); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, PM_inv_lower); + + } + + return; +} + +VOID DPD_AM_AM_LUT_Scaling( + IN PRTMP_ADAPTER pAd, + IN UCHAR AntIdx) +{ + USHORT k_count = 0; + UCHAR AM_temp = 0, AM_scaling = 0; + SHORT AM_Dealta = 0; + UINT32 check_loop = 0; + UCHAR scaling_vector[] = {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 5, 5, 5, 5, 5, 5, 5, 5, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10}; + + for (check_loop = 0; check_loop < 2; check_loop++) + { + if (AntIdx == 0) + { + DBGPRINT(RT_DEBUG_INFO, ("DPD Scaling for TX0 !!!\n")); + if (check_loop == 0) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x02); + else + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x03); + } + else + { + DBGPRINT(RT_DEBUG_INFO, ("DPD Scaling for TX1 !!!\n")); + if (check_loop == 0) + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x04); + else + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x05); + } + + /* Read out AM-PM one by one, multiply by (-1) and write it back */ + for (k_count = 0; k_count < 64; k_count++) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, ((4 * k_count) + 3)); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R188, &AM_temp); + AM_Dealta = AM_temp - 128; + if (scaling_vector[k_count] > 0) + { + if (AM_Dealta > 0) + AM_scaling = 128 + ((AM_Dealta * scaling_vector[k_count]) / 10); + else + AM_scaling = 128; + } + else + AM_scaling = 128; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, AM_scaling); + RtmpusecDelay(100); + + DBGPRINT(RT_DEBUG_INFO, ("(%d). AM_temp (%d), AM_Dealta (%d), AM_scaling (%d)\n", k_count, AM_temp, AM_Dealta, AM_scaling)); + } + } +} + +UCHAR DPD_Calibration( + IN PRTMP_ADAPTER pAd, + IN UCHAR AntIdx) +{ + UCHAR index, Max_Retry = 0, Pass_Thres = 0,byteValue = 0; + UINT32 macStatus, macValue; + UINT32 saveMacSysCtrl, saveTxPinCfg, saveTxAlgCfg0; + USHORT AM_SUM =0, AM_10 = 0, k_count = 0; + BOOLEAN DPD_Cal_success = FALSE, bNeedDoDPD = TRUE; + UCHAR saveBbpR27, saveBbpR65; + UCHAR saveBbpR241, saveBbpR242, saveBbpR244; + UCHAR saveRfB0R1, saveRfB5R1, saveRfB7R1; + UCHAR saveRfB4R11, saveRfB4R13; + UCHAR saveRfB6R11, saveRfB6R13; + UCHAR saveRfB4R19, saveRfB4R21, saveRfB4R22; + UCHAR saveRfB5R17, saveRfB5R18, saveRfB5R19, saveRfB5R20; + UCHAR saveRfB6R19, saveRfB6R21, saveRfB6R22; + UCHAR saveRfB7R17, saveRfB7R18, saveRfB7R19, saveRfB7R20; + UCHAR saveRfB5R3, saveRfB5R4; + UCHAR saveRfB7R3, saveRfB7R4; + UCHAR VGA_Upper_Bound, VGA_Lower_Bound, AM_63 = 0, VGA_code = 0; + UCHAR saveBbpR159;//, BBPValue; + CHAR VGA_code_idx = 0, target_power, delta_power; + INT32 txALC_init = 0, txALC_limit = 0; + INT32 temp_comp, tx_alc_txwi = 0; + INT32 txvga2, txvga3, mac_gain_atten; + INT32 gain_atten_bb = 0, gain_atten_rf = 0, txALC_req = 0; + INT32 txALC_req_at, txALC_req_skip2, txALC_req_skip3; + INT32 txALC_req_sat = 0; + UINT32 macValue_Tx_Cfg0 = 0,macValue_2nd, check_loop = 0; + BOOLEAN bInternalTxALC = FALSE; + + /* init base power by e2p target power */ + target_power = ((pAd->E2p_D0_Value & 0xFF) == 0xFF) ? 0x1E : (pAd->E2p_D0_Value & 0x3F); + + switch (AntIdx) + { + case 0: + /* Compute the corresponding signal values + Do exactly what TXALC does: + */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &macValue); + txALC_init = (macValue & 0x0000003F); + txALC_limit = (macValue & 0x003F0000) >> 16; + + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &macValue); + temp_comp = (macValue & 0x0000003F); + if ((temp_comp & 0x20) == 0x20) + temp_comp -= 64; + + tx_alc_txwi = 0; + + RTMP_IO_READ32(pAd, TX_ALC_VGA3, &macValue); + txvga2 = (macValue & 0x001F0000) >> 16; + txvga3 = (macValue & 0x0000001F); + + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &macValue); + mac_gain_atten = (macValue & 0x00300000) >> 20; + + if(mac_gain_atten == 1) + { + RTMP_IO_READ32(pAd, TX0_BB_GAIN_ATTEN, &macValue); + gain_atten_bb = (macValue & 0x00001F00) >> 8; + if ((gain_atten_bb & 0x10) == 0x10) + gain_atten_bb -= 32; + + RTMP_IO_READ32(pAd, TX0_RF_GAIN_ATTEN, &macValue); + gain_atten_rf = (macValue & 0x00007F00) >> 8; + if ((gain_atten_rf & 0x40) == 0x40) + gain_atten_rf -= 128; + } + else if(mac_gain_atten == 2) + { + RTMP_IO_READ32(pAd, TX0_BB_GAIN_ATTEN, &macValue); + gain_atten_bb = (macValue & 0x001F0000) >> 16; + if ((gain_atten_bb & 0x10) == 0x10) + gain_atten_bb -= 32; + + RTMP_IO_READ32(pAd, TX0_RF_GAIN_ATTEN, &macValue); + gain_atten_rf = (macValue & 0x007F0000) >> 16; + if ((gain_atten_rf & 0x40) == 0x40) + gain_atten_rf -= 128; + } + else if(mac_gain_atten == 3) + { + RTMP_IO_READ32(pAd, TX0_BB_GAIN_ATTEN, &macValue); + gain_atten_bb = (macValue & 0x1F000000) >> 24; + if ((gain_atten_bb & 0x10) == 0x10) + gain_atten_bb -= 32; + + RTMP_IO_READ32(pAd, TX0_RF_GAIN_ATTEN, &macValue); + gain_atten_rf = (macValue & 0x7F000000) >> 24; + if ((gain_atten_rf & 0x40) == 0x40) + gain_atten_rf -= 128; + } + + txALC_req = txALC_init + temp_comp + tx_alc_txwi; + + if(txALC_req >= txALC_limit) + txALC_req = txALC_limit; + + if(txALC_req < 0) + txALC_req_at = txALC_req - gain_atten_bb - gain_atten_rf; + else + txALC_req_at = txALC_req; + + if(txALC_req_at > 23) + txALC_req_skip2 = txALC_req_at + txvga2; + else + txALC_req_skip2 = txALC_req_at; + + if(txALC_req_skip2 > 35) + txALC_req_skip3 = txALC_req_skip2 + txvga3; + else + txALC_req_skip3 = txALC_req_skip2; + + if(txALC_req_skip3 < 0) + txALC_req_sat = 0; + else if(txALC_req_skip3 > 47) + txALC_req_sat = 47; + else + txALC_req_sat = txALC_req_skip3; + + + // no dpd when power is less 15 dBm or greater 20 dBm + bInternalTxALC = FALSE; +#ifdef RTMP_INTERNAL_TX_ALC +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + { + PATE_INFO pATEInfo = &(pAd->ate); + + if (pATEInfo->bAutoTxAlc == TRUE) + bInternalTxALC = TRUE; + } + else +#endif /* CONFIG_ATE */ + { + if(pAd->TxPowerCtrl.bInternalTxALC == TRUE) + bInternalTxALC = TRUE; + } +#endif /* RTMP_INTERNAL_TX_ALC */ + +#ifdef RTMP_INTERNAL_TX_ALC + if(bInternalTxALC == TRUE) + { + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &macValue); + target_power = (macValue & 0x3F); + +#ifdef ADJUST_POWER_CONSUMPTION_SUPPORT + if ((target_power < 12) || (target_power > 30)) +#else + if ((target_power < 30) || (target_power > 40)) +#endif /* ADJUST_POWER_CONSUMPTION_SUPPORT */ + { + bNeedDoDPD = FALSE; + break; + } + } + else +#endif /* RTMP_INTERNAL_TX_ALC */ + { +#ifdef CONFIG_ATE + if (!ATE_ON(pAd)) +#endif /* CONFIG_ATE */ + { + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &macValue); + delta_power = (macValue & 0x3F); + delta_power = (delta_power & 0x20) ? delta_power - 0x40 : delta_power; + + target_power += delta_power; + +#ifdef ADJUST_POWER_CONSUMPTION_SUPPORT + if ((target_power < 12) || (target_power > 30)) +#else + if ((target_power < 30) || (target_power > 40)) +#endif /* ADJUST_POWER_CONSUMPTION_SUPPORT */ + { + bNeedDoDPD = FALSE; + break; + } + } + } + break; + + case 1: + /* Compute the corresponding signal values + Do exactly what TXALC does: + */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &macValue); + txALC_init = (macValue & 0x00003F00) >> 8; + txALC_limit = (macValue & 0x3F000000) >> 24; + + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &macValue); + temp_comp = (macValue & 0x0000003F); + if ((temp_comp & 0x20) == 0x20) + temp_comp -= 64; + + tx_alc_txwi = 0; + + RTMP_IO_READ32(pAd, TX_ALC_VGA3, &macValue); + txvga2 = (macValue & 0x1F000000) >> 24; + txvga3 = (macValue & 0x00001F00) >> 8; + + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &macValue); + mac_gain_atten = (macValue & 0x00C00000) >> 22; + + if(mac_gain_atten == 1) + { + RTMP_IO_READ32(pAd, TX1_BB_GAIN_ATTEN, &macValue); + gain_atten_bb = (macValue & 0x00001F00) >> 8; + if ((gain_atten_bb & 0x10) == 0x10) + gain_atten_bb -= 32; + + RTMP_IO_READ32(pAd, TX1_RF_GAIN_ATTEN, &macValue); + gain_atten_rf = (macValue & 0x00007F00) >> 8; + if ((gain_atten_rf & 0x40) == 0x40) + gain_atten_rf -= 128; + } + else if(mac_gain_atten == 2) + { + RTMP_IO_READ32(pAd, TX1_BB_GAIN_ATTEN, &macValue); + gain_atten_bb = (macValue & 0x001F0000) >> 16; + if ((gain_atten_bb & 0x10) == 0x10) + gain_atten_bb -= 32; + + RTMP_IO_READ32(pAd, TX1_RF_GAIN_ATTEN, &macValue); + gain_atten_rf = (macValue & 0x007F0000) >> 16; + if ((gain_atten_rf & 0x40) == 0x40) + gain_atten_rf -= 128; + } + else if(mac_gain_atten == 3) + { + RTMP_IO_READ32(pAd, TX1_BB_GAIN_ATTEN, &macValue); + gain_atten_bb = (macValue & 0x1F000000) >> 24; + if ((gain_atten_bb & 0x10) == 0x10) + gain_atten_bb -= 32; + + RTMP_IO_READ32(pAd, TX1_RF_GAIN_ATTEN, &macValue); + gain_atten_rf = (macValue & 0x7F000000) >> 24; + if ((gain_atten_rf & 0x40) == 0x40) + gain_atten_rf -= 128; + } + + txALC_req = txALC_init + temp_comp + tx_alc_txwi; + + if(txALC_req >= txALC_limit) + txALC_req = txALC_limit; + + if(txALC_req < 0) + txALC_req_at = txALC_req - gain_atten_bb - gain_atten_rf; + else + txALC_req_at = txALC_req; + + if(txALC_req_at > 23) + txALC_req_skip2 = txALC_req_at + txvga2; + else + txALC_req_skip2 = txALC_req_at; + + if(txALC_req_skip2 > 35) + txALC_req_skip3 = txALC_req_skip2 + txvga3; + else + txALC_req_skip3 = txALC_req_skip2; + + if(txALC_req_skip3 < 0) + txALC_req_sat = 0; + else if(txALC_req_skip3 > 47) + txALC_req_sat = 47; + else + txALC_req_sat = txALC_req_skip3; + + // no dpd when power is less 15 dBm or greater 20 dBm + bInternalTxALC = FALSE; +#ifdef RTMP_INTERNAL_TX_ALC +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + { + PATE_INFO pATEInfo = &(pAd->ate); + + if (pATEInfo->bAutoTxAlc == TRUE) + bInternalTxALC = TRUE; + } + else +#endif /* CONFIG_ATE */ + { + if(pAd->TxPowerCtrl.bInternalTxALC == TRUE) + bInternalTxALC = TRUE; + } +#endif /* RTMP_INTERNAL_TX_ALC */ + +#ifdef RTMP_INTERNAL_TX_ALC + if(bInternalTxALC == TRUE) + { + RTMP_IO_READ32(pAd, TX_ALG_CFG_0, &macValue); + target_power = (macValue & 0x3F); + +#ifdef ADJUST_POWER_CONSUMPTION_SUPPORT + if ((target_power < 12) || (target_power > 30)) +#else + if ((target_power < 30) || (target_power > 40)) +#endif /* ADJUST_POWER_CONSUMPTION_SUPPORT */ + { + bNeedDoDPD = FALSE; + break; + } + } + else +#endif /* RTMP_INTERNAL_TX_ALC */ + { +#ifdef CONFIG_ATE + if (!ATE_ON(pAd)) +#endif /* CONFIG_ATE */ + { + /* for single sku */ + RTMP_IO_READ32(pAd, TX_ALG_CFG_1, &macValue); + delta_power = (macValue & 0x3F); + delta_power = (delta_power & 0x20) ? delta_power - 0x40 : delta_power; + + target_power += delta_power; + +#ifdef ADJUST_POWER_CONSUMPTION_SUPPORT + if ((target_power < 12) || (target_power > 30)) +#else + if ((target_power < 30) || (target_power > 40)) +#endif /* ADJUST_POWER_CONSUMPTION_SUPPORT */ + { + bNeedDoDPD = FALSE; + break; + } + } + } + break; + + default: + break; + } + + if (bNeedDoDPD == FALSE) + { + DPD_Cal_success = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("Don't need do DPD Calibration !!!\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_INFO, ("RF Gain(%d), RF R3/4(%x)\n", RT6352_RFR3R4_TABLE[VGA_code_idx].Register, VGA_code)); + if (AntIdx == 0) + { + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, (0x20 | VGA_code)); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, (0x20 | VGA_code)); + } + else + { + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, (0x20 | VGA_code)); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, (0x20 | VGA_code)); + } + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x08); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x00); + + /* Check MAC Tx/Rx idle */ + for (k_count = 0; k_count < 10000; k_count++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &macStatus); + if (macStatus & 0x3) + RtmpusecDelay(50); + else + break; + } + + if (k_count == 10000) + { + DBGPRINT(RT_DEBUG_ERROR, ("2. Wait MAC Status to MAX !!!\n")); + } + + /* Turn on debug tone and start DPD calibration through MAC registers */ + if (pAd->CommonCfg.Chip_VerID > 1) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, 0x11); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, 0x2A); + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x01); + if (AntIdx == 0) + { + if (check_loop == 0) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x80); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x81); + } + } + else + { + if (check_loop == 0) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x82); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R188, 0x83); + } + } + + /* Wait up to 1ms for capture buffer to fill */ + for (k_count = 0; k_count < 1000; k_count++) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R188, &byteValue); + if ((byteValue & 0x80) == 0) + break; + RtmpusecDelay(50); + } + + if (k_count == 1000) + DBGPRINT(RT_DEBUG_ERROR, ("Wait capture buffer to MAX !!!\n")); + + /* Turn off debug tone */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, 0x00); + + /* Check if VGA is appropriate (signal has large swing but not clipped in ADC) */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x01); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0xFF); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R188, &byteValue); + AM_63 = byteValue; + DBGPRINT(RT_DEBUG_INFO, ("AM_63 (%d)\n", AM_63)); + + if (AM_63 < VGA_Lower_Bound) + VGA_code_idx++; + else if (AM_63 > VGA_Upper_Bound) + VGA_code_idx--; + else + { + DBGPRINT(RT_DEBUG_INFO, ("Appropriate VGA Gain(%d), R66(%x)\n", RT6352_VGA_TABLE[VGA_code_idx].Register, VGA_code)); + DBGPRINT(RT_DEBUG_INFO, ("AM_63 (%d)\n", AM_63)); + break; + } + } + + /* VGA_code cannot be found, report error and stop DPD calibration */ + if ((VGA_code_idx < 0) || (VGA_code_idx > 18)) + { + DBGPRINT(RT_DEBUG_ERROR, (" VGA Code idx overflow(%d), AM_63(%d) !!!\n", VGA_code_idx, AM_63)); + DPD_Cal_success = FALSE; + break; + } + + AM_SUM = 0; + AM_10 = 0; + + /* DPD calibration protection mechanism */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R186, 0x01); + + for (k_count = 0; k_count < 11; k_count++) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, ((4 * k_count) + 3)); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R188, &byteValue); + AM_SUM += byteValue; + } + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R187, 0x2B); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R188, &byteValue); + AM_10 = byteValue; + + DBGPRINT(RT_DEBUG_INFO, ("AM_SUM = %d, AM_10 = %d !!!\n", AM_SUM, AM_10)); + DBGPRINT(RT_DEBUG_INFO, ("(AM_SUM - 5.5*AM_10) = (%d) @@\n", (AM_SUM - ((11 * AM_10) / 2)))); + + if (AntIdx == 0) + { + if (((AM_SUM - ((11 * AM_10) / 2)) >= -3) && ((AM_SUM - ((11 * AM_10) / 2)) <= Pass_Thres)) + { + DBGPRINT(RT_DEBUG_TRACE, ("DPD Calibration Pass for TX0 !!!\n")); + + if (check_loop == 0) + pAd->Tx0_DPD_ALC_tag0_flag = 0x1; + else if (check_loop == 1) + pAd->Tx0_DPD_ALC_tag1_flag = 0x1; + + DPD_Cal_success = TRUE; + break; + } + + if (index == 3) + { + Pass_Thres += 3; + } + } + else + { + if (index == 4) + { + if (((AM_SUM - ((11 * AM_10) / 2)) >= -9) && ((AM_SUM - ((11 * AM_10) / 2)) <= 12)) + { + DBGPRINT(RT_DEBUG_TRACE, ("DPD Calibration Pass for TX1 !!!\n")); + + if (check_loop == 0) + pAd->Tx1_DPD_ALC_tag0_flag = 0x1; + else if (check_loop == 1) + pAd->Tx1_DPD_ALC_tag1_flag = 0x1; + + DPD_Cal_success = TRUE; + break; + } + } + else + { + if (((AM_SUM - ((11 * AM_10) / 2)) >= -5) && ((AM_SUM - ((11 * AM_10) / 2)) <= 5)) + { + DBGPRINT(RT_DEBUG_TRACE, ("DPD Calibration Pass for TX1 !!!\n")); + + if (check_loop == 0) + pAd->Tx1_DPD_ALC_tag0_flag = 0x1; + else if (check_loop == 1) + pAd->Tx1_DPD_ALC_tag1_flag = 0x1; + + DPD_Cal_success = TRUE; + break; + } + } + } + } + + } + + /* Restore RF registers */ + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, saveRfB0R1); + if (AntIdx == 0) + { + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R01, saveRfB5R1); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R17, saveRfB5R17); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, saveRfB5R18); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, saveRfB5R19); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, saveRfB5R20); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R11, saveRfB4R11); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R13, saveRfB4R13); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R19, saveRfB4R19); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R21, saveRfB4R21); + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R22, saveRfB4R22); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, saveRfB5R3); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, saveRfB5R4); + } + else + { + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R01, saveRfB7R1); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R17, saveRfB7R17); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R18, saveRfB7R18); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R19, saveRfB7R19); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R20, saveRfB7R20); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R11, saveRfB6R11); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R13, saveRfB6R13); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R19, saveRfB6R19); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R21, saveRfB6R21); + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R22, saveRfB6R22); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, saveRfB7R3); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, saveRfB7R4); + } + + /* Restore BBP registers */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &byteValue); + byteValue &= (~0x18); + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + byteValue |= 0x10; + +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + { + PATE_INFO pATEInfo = &(pAd->ate); + + byteValue &= (~0x18); + if (pATEInfo->TxWI.TXWI_O.BW == BW_40) + byteValue |= 0x10; + } +#endif /* CONFIG_ATE */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, byteValue); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, 0x1); + RtmpusecDelay(2); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, 0x0); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R27, saveBbpR27); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R65, saveBbpR65); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBP_R140); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, saveBbpR159); + if (pAd->CommonCfg.Chip_VerID > 1) + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R241, saveBbpR241); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R242, saveBbpR242); + } + else + { + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R242, saveBbpR242); + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, saveBbpR244); + + /* Restore MAC registers */ + RTMP_IO_WRITE32(pAd, TX_ALG_CFG_0, saveTxAlgCfg0); + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, saveTxPinCfg); + 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 CONFIG_ATE + UCHAR saveBbpR1 = 0, saveRfB0R2 = 0, BBPValue = 0, RFValue = 0; +#endif /* CONFIG_ATE */ + + DBGPRINT(RT_DEBUG_INFO, (" Do DPD Calibration !!!\n")); + +#ifdef CONFIG_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 /* CONFIG_ATE */ + + Ant0 = DPD_Calibration(pAd, 0); + if (pAd->Antenna.field.TxPath > 1) + Ant1 = DPD_Calibration(pAd, 1); + +#ifdef CONFIG_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 /* CONFIG_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 CONFIG_ATE + if (ATE_ON(pAd)) + { + PATE_INFO pATEInfo = &(pAd->ate); + + byteValue &= (~0x18); + if (pATEInfo->TxWI.TXWI_O.BW == BW_40) + byteValue |= 0x10; + } +#endif /* CONFIG_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 RTMP_STRING *arg) +{ +#ifdef CONFIG_ATE + PATE_INFO pATEInfo = &(pAd->ate); +#endif /* CONFIG_ATE */ + INT bDPDCalibrationEnable = 0; + + DBGPRINT(RT_DEBUG_WARN, (" TestDPDCalibration !!!\n")); + + pAd->bCalibrationDone = FALSE; + + bDPDCalibrationEnable = simple_strtol(arg, 0, 10); + + if (bDPDCalibrationEnable == 0) + { +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + { + pATEInfo->bDPDEnable = FALSE; + } +#endif /* CONFIG_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 CONFIG_ATE + if (ATE_ON(pAd)) + { + pATEInfo->bDPDEnable = TRUE; + } +#endif /* CONFIG_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 RTMP_STRING *arg) +{ + UCHAR Ant0 = 0; + UCHAR byteValue = 0; +#ifdef CONFIG_ATE + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR saveBbpR1 = 0, saveRfB0R2 = 0, BBPValue = 0, RFValue = 0; +#endif /* CONFIG_ATE */ + INT bDPDCalibrationEnable = 0; + + DBGPRINT(RT_DEBUG_WARN, (" TestDPDCalibrationTX0 !!!\n")); + + pAd->bCalibrationDone = FALSE; + + bDPDCalibrationEnable = simple_strtol(arg, 0, 10); + + if (bDPDCalibrationEnable == 0) + { +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + { + pATEInfo->bDPDEnable = FALSE; + } +#endif /* CONFIG_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 CONFIG_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 /* CONFIG_ATE */ + + if (bDPDCalibrationEnable == 1) + { +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + { + pATEInfo->bDPDEnable = TRUE; + } +#endif /* CONFIG_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 CONFIG_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 /* CONFIG_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 CONFIG_ATE + if (ATE_ON(pAd)) + { + byteValue &= (~0x18); + if (pATEInfo->TxWI.TXWI_O.BW == BW_40) + byteValue |= 0x10; + } +#endif /* CONFIG_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 RTMP_STRING *arg) +{ + UCHAR Ant1 = 0; + UCHAR byteValue = 0; +#ifdef CONFIG_ATE + PATE_INFO pATEInfo = &(pAd->ate); + UCHAR saveBbpR1 = 0, saveRfB0R2 = 0, BBPValue = 0, RFValue = 0; +#endif /* CONFIG_ATE */ + INT bDPDCalibrationEnable = 0; + + DBGPRINT(RT_DEBUG_WARN, (" TestDPDCalibrationTX1 !!!\n")); + + pAd->bCalibrationDone = FALSE; + + bDPDCalibrationEnable = simple_strtol(arg, 0, 10); + + if (bDPDCalibrationEnable == 0) + { +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + { + pATEInfo->bDPDEnable = FALSE; + } +#endif /* CONFIG_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 CONFIG_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 /* CONFIG_ATE */ + + if (bDPDCalibrationEnable == 1) + { +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + { + pATEInfo->bDPDEnable = TRUE; + } +#endif /* CONFIG_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 CONFIG_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 /* CONFIG_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 CONFIG_ATE + if (ATE_ON(pAd)) + { + byteValue &= (~0x18); + if (pATEInfo->TxWI.TXWI_O.BW == BW_40) + byteValue |= 0x10; + } +#endif /* CONFIG_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 RTMP_STRING *arg) +{ + pAd->chipCap.DPDCalPassThres = simple_strtol(arg, 0, 10); + + DBGPRINT(RT_DEBUG_INFO, + ("DPD Pass Threshold = %d \n", pAd->chipCap.DPDCalPassThres)); + + return TRUE; +} + +/**************************************************************************** + * + * VOID TX Filter BandWidth Calibraton + * + ****************************************************************************/ +static INT BBP_Core_Soft_Reset( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN set_bw, + IN INT bw) +{ + UINT8 bbp_val; + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &bbp_val); + bbp_val |= 0x1; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, bbp_val); + RtmpusecDelay(100); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &bbp_val); + if (set_bw == TRUE) { + bbp_val &= (~0x18); + switch (bw) + { + case BW_40: + bbp_val |= 0x10; + break; + case BW_20: + default: + break; + } + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, bbp_val); + RtmpusecDelay(100); + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &bbp_val); + bbp_val &= (~0x1); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, bbp_val); + RtmpusecDelay(100); + + return 0; +} + +static INT RF_lp_Config( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bTxCal) +{ + UCHAR rf_val; + + if (bTxCal) + { + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x04); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0, 0x06); + } + else + { + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x02); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0, 0x06); + + } + + RT635xReadRFRegister(pAd, RF_BANK5, RF_R17, &rf_val); + rf_val |= 0x80; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R17, rf_val); + + if (bTxCal) + { + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, 0xC1); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, 0x20); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, 0x02); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R03, &rf_val); + rf_val &= (~0x3F); + rf_val |= 0x3F; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, rf_val); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R04, &rf_val); + rf_val &= (~0x3F); + rf_val |= 0x3F; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, rf_val); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R05, 0x31); + } + else + { + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, 0xF1); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, 0x18); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, 0x02); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R03, &rf_val); + rf_val &= (~0x3F); + rf_val |= 0x34; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, rf_val); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R04, &rf_val); + rf_val &= (~0x3F); + rf_val |= 0x34; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, rf_val); + } + + return 0; +} + +static CHAR lp_Tx_Filter_BW_Cal( + IN PRTMP_ADAPTER pAd) +{ + INT cnt; + UINT8 bbp_val; + CHAR cal_val; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x82); + + cnt = 0; + do { + RtmpusecDelay(500); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &bbp_val); + if (bbp_val == 0x02 || cnt == 20) + break; + cnt++; + }while(cnt < 20); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x39); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &bbp_val); + cal_val = bbp_val & 0x7F; + if (cal_val >= 0x40) + cal_val -= 128; + + return cal_val; +} + + +/* RF Bandwidth calibration */ +BOOLEAN BW_Filter_Calibration( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bTxCal) +{ + UINT8 tx_agc_fc = 0, rx_agc_fc = 0, cmm_agc_fc; + UINT8 filter_target; + UINT8 tx_filter_target_20m = 0x09, tx_filter_target_40m = 0x02; + UINT8 rx_filter_target_20m = 0x27, rx_filter_target_40m = 0x31; + INT loop = 0, bw, cnt; + UINT8 bbp_val, rf_val; + CHAR cal_r32_init, cal_r32_val, cal_diff; + UINT8 saveRfB5R00, saveRfB5R01, saveRfB5R03, saveRfB5R04, saveRfB5R05; + UINT8 saveRfB5R06, saveRfB5R07; + UINT8 saveRfB5R08, saveRfB5R17, saveRfB5R18, saveRfB5R19, saveRfB5R20; + UINT8 saveRfB5R37, saveRfB5R38, saveRfB5R39, saveRfB5R40, saveRfB5R41; + UINT8 saveRfB5R42, saveRfB5R43, saveRfB5R44, saveRfB5R45, saveRfB5R46; + UINT8 saveRfB5R58, saveRfB5R59; + UINT8 saveBBP159R0, saveBBP159R2, saveBBPR23; + UINT32 MAC_RF_CONTROL0, MAC_RF_BYPASS0; + + DBGPRINT(RT_DEBUG_ERROR, (" %s BW Filter Calibration !!!\n", (bTxCal == TRUE ? "TX" : "RX"))); + + /* Save MAC registers */ + RTMP_IO_READ32(pAd, RF_CONTROL0, &MAC_RF_CONTROL0); + RTMP_IO_READ32(pAd, RTMP_RF_BYPASS0 , &MAC_RF_BYPASS0); + + /* save BBP registers */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R23, &saveBBPR23); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x0); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &saveBBP159R0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x02); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &saveBBP159R2); + + /* Save RF registers */ + RT635xReadRFRegister(pAd, RF_BANK5, RF_R00, &saveRfB5R00); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R01, &saveRfB5R01); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R03, &saveRfB5R03); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R04, &saveRfB5R04); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R05, &saveRfB5R05); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R06, &saveRfB5R06); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R07, &saveRfB5R07); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R08, &saveRfB5R08); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R17, &saveRfB5R17); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R18, &saveRfB5R18); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R19, &saveRfB5R19); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R20, &saveRfB5R20); + + RT635xReadRFRegister(pAd, RF_BANK5, RF_R37, &saveRfB5R37); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R38, &saveRfB5R38); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R39, &saveRfB5R39); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R40, &saveRfB5R40); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R41, &saveRfB5R41); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R42, &saveRfB5R42); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R43, &saveRfB5R43); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R44, &saveRfB5R44); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R45, &saveRfB5R45); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R46, &saveRfB5R46); + + RT635xReadRFRegister(pAd, RF_BANK5, RF_R58, &saveRfB5R58); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R59, &saveRfB5R59); + + RT635xReadRFRegister(pAd, RF_BANK5, RF_R00, &rf_val); + rf_val |= 0x3; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R00, rf_val); + + RT635xReadRFRegister(pAd, RF_BANK5, RF_R01, &rf_val); + rf_val |= 0x1; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R01, rf_val); + + cnt = 0; + do { + RtmpusecDelay(500); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R01, &rf_val); + DBGPRINT(RT_DEBUG_INFO, ("ABB.R1 = %d, Cnt = %d \n", rf_val, cnt)); + if (((rf_val & 0x1) == 0x00) || (cnt == 40)) + break; + cnt++; + } while(cnt < 40); + + RT635xReadRFRegister(pAd, RF_BANK5, RF_R00, &rf_val); + rf_val &= (~0x3); + rf_val |= 0x1; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R00, rf_val); + + /* I-3 */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R23, &bbp_val); + bbp_val &= (~0x1F); + bbp_val |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, bbp_val); + + do { + /* I-4,5,6,7,8,9 */ + if (loop == 0) { + bw = BW_20; + + if (bTxCal) + filter_target = tx_filter_target_20m; + else + filter_target = rx_filter_target_20m; + } + else + { + bw = BW_40; + + if (bTxCal) + filter_target = tx_filter_target_40m; + else + filter_target = rx_filter_target_40m; + } + DBGPRINT(RT_DEBUG_INFO, ("%s():Start BW Cal for %dMHz\n", + __FUNCTION__, (bw == BW_20 ? 20 : 40))); + + RT635xReadRFRegister(pAd, RF_BANK5, RF_R08, &rf_val); + rf_val &= (~0x04); + if (loop == 1) + rf_val |= 0x4; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R08, rf_val); + + BBP_Core_Soft_Reset(pAd, TRUE, bw); + + RF_lp_Config(pAd, bTxCal); + + if (bTxCal) + { + tx_agc_fc = 0; + RT635xReadRFRegister(pAd, RF_BANK5, RF_R58, &rf_val); + rf_val &= (~0x7F); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R58, rf_val); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R59, &rf_val); + rf_val &= (~0x7F); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R59, rf_val); + } + else + { + rx_agc_fc = 0; + RT635xReadRFRegister(pAd, RF_BANK5, RF_R06, &rf_val); + rf_val &= (~0x7F); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R06, rf_val); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R07, &rf_val); + rf_val &= (~0x7F); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R07, rf_val); + } + + RtmpusecDelay(1000); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x2); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &bbp_val); + bbp_val &= (~0x6); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, bbp_val); + + BBP_Core_Soft_Reset(pAd, FALSE, bw); + + cal_r32_init = lp_Tx_Filter_BW_Cal(pAd); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x2); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &bbp_val); + bbp_val |= 0x6; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, bbp_val); + + +do_cal: + + if (bTxCal) + { + RT635xReadRFRegister(pAd, RF_BANK5, RF_R58, &rf_val); + rf_val &= (~0x7F); + rf_val |= tx_agc_fc; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R58, rf_val); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R59, &rf_val); + rf_val &= (~0x7F); + rf_val |= tx_agc_fc; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R59, rf_val); + } + else + { + RT635xReadRFRegister(pAd, RF_BANK5, RF_R06, &rf_val); + rf_val &= (~0x7F); + rf_val |= rx_agc_fc; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R06, rf_val); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R07, &rf_val); + rf_val &= (~0x7F); + rf_val |= rx_agc_fc; + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R07, rf_val); + } + + RtmpusecDelay(500); + + BBP_Core_Soft_Reset(pAd, FALSE, bw); + + cal_r32_val = lp_Tx_Filter_BW_Cal(pAd); + + cal_diff = cal_r32_init - cal_r32_val; + + + if (bTxCal) + cmm_agc_fc = tx_agc_fc; + else + cmm_agc_fc = rx_agc_fc; + + if (((cal_diff > filter_target) && (cmm_agc_fc == 0)) || + ((cal_diff < filter_target) && (cmm_agc_fc == 0x3f))) + { + if (bTxCal) + tx_agc_fc = 0; + else + rx_agc_fc = 0; + } + else if ((cal_diff <= filter_target) && (cmm_agc_fc < 0x3f)) + { + if (bTxCal) + tx_agc_fc++; + else + rx_agc_fc++; + goto do_cal; + } + else + { + /* do nothing */ + } + + + if (bTxCal) + { + if (loop == 0) + pAd->tx_bw_cal[0] = tx_agc_fc; + else + pAd->tx_bw_cal[1] = tx_agc_fc; + } + else + { + if (loop == 0) + pAd->rx_bw_cal[0] = rx_agc_fc; + else + pAd->rx_bw_cal[1] = rx_agc_fc; + } + + loop++; + } while(loop <= 1); + + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R00, saveRfB5R00); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R01, saveRfB5R01); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, saveRfB5R03); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, saveRfB5R04); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R05, saveRfB5R05); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R06, saveRfB5R06); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R07, saveRfB5R07); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R08, saveRfB5R08); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R17, saveRfB5R17); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, saveRfB5R18); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, saveRfB5R19); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, saveRfB5R20); + + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R37, saveRfB5R37); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R38, saveRfB5R38); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R39, saveRfB5R39); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R40, saveRfB5R40); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R41, saveRfB5R41); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R42, saveRfB5R42); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R43, saveRfB5R43); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R44, saveRfB5R44); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R45, saveRfB5R45); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R46, saveRfB5R46); + + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R58, saveRfB5R58); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R59, saveRfB5R59); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, saveBBPR23); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, saveBBP159R0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x2); + //RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &bbp_val); + //bbp_val &= (~0x6); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, saveBBP159R2); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &bbp_val); + bbp_val &= (~0x18); + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + bbp_val |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, bbp_val); + + RTMP_IO_WRITE32(pAd, RF_CONTROL0, MAC_RF_CONTROL0); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0, MAC_RF_BYPASS0); + + return TRUE; +} + +/* Rx DCOC Calibration */ +VOID RxDCOC_Calibration( + IN PRTMP_ADAPTER pAd) +{ + UCHAR BbpReg = 0; + UINT32 MacValue = 0, MacValue1 = 0; + USHORT k_count = 0; + UINT8 saveRfB0R2, saveRfB5R4, saveRfB7R4, RFValue; + + DBGPRINT(RT_DEBUG_WARN, (" RxDCOC_Calibration !!!\n")); + + RT635xReadRFRegister(pAd, RF_BANK0, RF_R02, &saveRfB0R2); + RFValue = saveRfB0R2; + RFValue |= 0x03; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R02, RFValue); + + /* Write BBP CAL R141 bit[4] = 1. (Enable calibrate MID-GAIN) */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBP_R141); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &BbpReg); + BbpReg |= 0x10; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BbpReg); + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &MacValue); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x8); + + for (k_count = 0; k_count < 10000; k_count++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &MacValue1); + if (MacValue1 & 0x1) + RtmpusecDelay(50); + else + break; + } + RT635xReadRFRegister(pAd, RF_BANK5, RF_R04, &saveRfB5R4); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R04, &saveRfB7R4); + saveRfB5R4 = saveRfB5R4 & (~0x40); + saveRfB7R4 = saveRfB7R4 & (~0x40); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, 0x64); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, 0x64); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, saveRfB5R4); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, saveRfB7R4); + + /* Write BBP CAL R140 bit [6],[3] to 1 (Start Full,Gainfreeze calibration) */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBP_R140); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &BbpReg); + BbpReg = BbpReg & (~0x40); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BbpReg); + BbpReg |= 0x48; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BbpReg); + + /* Polling CAL R140 bit[6] = 0 (Cal done) */ + for (k_count = 0; k_count < 10000; k_count++) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &BbpReg); + if ((BbpReg & 0x40)==0) + break; + RtmpusecDelay(50); + } + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &BbpReg); + BbpReg = BbpReg & (~0x40); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BbpReg); + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, MacValue); + + /* Write CAL R141 bit[4] = 0 (Disable calibrate MID-GAIN) */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, BBP_R141); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &BbpReg); + BbpReg &= (~0x10); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, BbpReg); + + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R02, saveRfB0R2); +} + +/**************************************************************************** + * + * VOID RXIQCalibraton(VOID) + * + ****************************************************************************/ +static UINT32 do_sqrt_accumulation(UINT32 si) +{ + UINT32 root,root_pre,bit; + CHAR i; + bit = 1 << 15; + root = 0; + for (i=15; i>=0; i=i-1) + { + root_pre = root + bit; + if((root_pre*root_pre) <= si) + root = root_pre; + bit = bit >> 1; + } + + return root; +} + +VOID RXIQ_Calibration( + IN PRTMP_ADAPTER pAd) +{ + UINT8 RFB0R1,RFB0R2,RFB0R42; + UINT8 RFB4R0, RFB4R19; + UINT8 RFB5R3, RFB5R4, RFB5R17, RFB5R18, RFB5R19, RFB5R20; + UINT8 RFB6R0, RFB6R19; + UINT8 RFB7R3, RFB7R4, RFB7R17, RFB7R18, RFB7R19, RFB7R20; + + UINT8 BBP1, BBP4; + UINT8 BBPR241, BBPR242; + UINT32 i; + UINT8 ch_idx; + UINT8 bbpval; + UINT8 rfval, vga_idx=0; + INT32 mi = 0, mq = 0, si = 0, sq = 0, riq = 0; + INT32 Sigma_i, Sigma_q, R_iq, G_rx; + INT32 G_imb; + INT32 Ph_rx; + UINT32 saveMacSysCtrl = 0; + UINT32 orig_RF_CONTROL0 = 0; // 0x0518 + UINT32 orig_RF_BYPASS0 = 0; // 0x051c + UINT32 orig_RF_CONTROL1 = 0; // 0x0520 + UINT32 orig_RF_BYPASS1 = 0; // 0x0524 + UINT32 orig_RF_CONTROL3 = 0; // 0x0530 + UINT32 orig_RF_BYPASS3 = 0; // 0x0534 + UINT32 macStatus, k_count, bbpval1 = 0; + UCHAR rf_vga_table[]={0x20, 0x21, 0x22, + 0x38, 0x39, 0x3a, + 0x3b, 0x3c, 0x3d, + 0x3e, 0x3f}; + + DBGPRINT(RT_DEBUG_INFO, (" RxIQ Calibration !!!\n")); + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &saveMacSysCtrl); + RTMP_IO_READ32(pAd, RF_CONTROL0 , &orig_RF_CONTROL0); + RTMP_IO_READ32(pAd, RTMP_RF_BYPASS0 , &orig_RF_BYPASS0 ); + RTMP_IO_READ32(pAd, RF_CONTROL1 , &orig_RF_CONTROL1); + RTMP_IO_READ32(pAd, RF_BYPASS1 , &orig_RF_BYPASS1 ); + RTMP_IO_READ32(pAd, RF_CONTROL3 , &orig_RF_CONTROL3); + RTMP_IO_READ32(pAd, RF_BYPASS3 , &orig_RF_BYPASS3 ); + + // BBP store + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BBP1); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R4, &BBP4); + + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); + /* Check MAC Tx/Rx idle */ + for (k_count = 0; k_count < 10000; k_count++) + { + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &macStatus); + if (macStatus & 0x3) + RtmpusecDelay(50); + else + break; + } + + if (k_count == 10000) + { + DBGPRINT(RT_DEBUG_ERROR, ("Wait MAC Status to MAX !!!\n")); + } + + bbpval = BBP4 & (~0x18); + bbpval = BBP4 | 0x00; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R4, bbpval); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R21, &bbpval); + bbpval = bbpval | 1; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, bbpval); + bbpval = bbpval & 0xFE; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R21, bbpval); + + + RTMP_IO_WRITE32(pAd, RF_CONTROL1, 0x00000202); // 0x0520 + RTMP_IO_WRITE32(pAd, RF_BYPASS1 , 0x00000303); // 0x0524 +#ifdef RT6352_EP_SUPPORT + RTMP_IO_WRITE32(pAd, RF_CONTROL3, 0x0101); // 0x0530 +#else + RTMP_IO_WRITE32(pAd, RF_CONTROL3, 0x0000); // 0x0530 +#endif /* RT6352_EP_SUPPORT */ + RTMP_IO_WRITE32(pAd, RF_BYPASS3 , 0xF1F1); // 0x0534 + + /* B) Store RF Original Setting */ + RT635xReadRFRegister(pAd, RF_BANK0, RF_R01, &RFB0R1); + RT635xReadRFRegister(pAd, RF_BANK0, RF_R02, &RFB0R2); + RT635xReadRFRegister(pAd, RF_BANK0, RF_R42, &RFB0R42); + + RT635xReadRFRegister(pAd, RF_BANK4, RF_R00, &RFB4R0); + RT635xReadRFRegister(pAd, RF_BANK4, RF_R19, &RFB4R19); + /* RF TRx0 VGA gain store */ + RT635xReadRFRegister(pAd, RF_BANK5, RF_R03, &RFB5R3); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R04, &RFB5R4); + /* RF TRx0 Loopback path force */ + RT635xReadRFRegister(pAd, RF_BANK5, RF_R17, &RFB5R17); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R18, &RFB5R18); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R19, &RFB5R19); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R20, &RFB5R20); + + RT635xReadRFRegister(pAd, RF_BANK6, RF_R00, &RFB6R0); + RT635xReadRFRegister(pAd, RF_BANK6, RF_R19, &RFB6R19); + /* RF TRx1 VGA gain store */ + RT635xReadRFRegister(pAd, RF_BANK7, RF_R03, &RFB7R3); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R04, &RFB7R4); + /* RF TRx1 Loopback path force */ + RT635xReadRFRegister(pAd, RF_BANK7, RF_R17, &RFB7R17); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R18, &RFB7R18); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R19, &RFB7R19); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R20, &RFB7R20); + + /* ) RF Loopback Setting*/ + /* RF common setting */ + + /* TRx 0 loopback setting */ + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R00, 0x87); // force TR switch + RT635xWriteRFRegister(pAd, RF_BANK4, RF_R19, 0x27); // force TR switch + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, 0x38); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, 0x38); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R17, 0x80); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R18, 0xC1); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R19, 0x60); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R20, 0x00); + + /* TRx 1 loopback setting */ + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R00, 0x87); // force TR switch + RT635xWriteRFRegister(pAd, RF_BANK6, RF_R19, 0x27); // force TR switch + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, 0x38); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, 0x38); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R17, 0x80); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R18, 0xC1); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R19, 0x60); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R20, 0x00); + + + /* BBP Tx power control */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x0); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x0); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x5); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x0); + + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R241, &BBPR241); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R242, &BBPR242); + + + /* C) Set Debug Tone (need to be disable after calibration) */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R241, 0x10); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R242, 0x84); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R244, 0x31); + + /* Disable rx iq compensation */ + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x3); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &bbpval); + bbpval = bbpval & (~0x7); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, bbpval ); + + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00000004); // 0x0518 + RtmpusecDelay(1); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00000006); // 0x0518 + RtmpusecDelay(1); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0 , 0x00003376); // 0x051c + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00001006); // 0x0518 + RtmpusecDelay(1); +#ifdef RT6352_EP_SUPPORT + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x06); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x06); +#else + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R23, 0x02); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R24, 0x02); +#endif /* RT6352_EP_SUPPORT */ + //BBP Rf Rx gain control + for(ch_idx = 0; ch_idx < 2; ch_idx = ch_idx + 1) + { /* Path control */ + if(ch_idx == 0) + { /* only on Tx0 */ + /* RF only Tx0 */ + rfval = RFB0R1 & (~0x3); + rfval = RFB0R1 | 0x1; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, rfval); + rfval = RFB0R2 & (~0x33); + rfval = RFB0R2 | 0x11; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R02, rfval); + rfval = RFB0R42 & (~0x50); + rfval = RFB0R42 | 0x10; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, rfval); + + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00001006); // 0x0518 + RtmpusecDelay(1); + + // BBP only Tx0 + bbpval = BBP1 & (~ 0x18); + bbpval = bbpval | 0x00; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, bbpval); + + // BBP only Rx0 + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x01); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x00); + } + else + { + // RF only Tx1 + rfval = RFB0R1 & (~0x3); + rfval = RFB0R1 | 0x2; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R01, rfval); + rfval = RFB0R2 & (~0x33); + rfval = RFB0R2 | 0x22; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R02, rfval); + rfval = RFB0R42 & (~0x50); + rfval = RFB0R42 | 0x40; + RT635xWriteRFRegister(pAd, RF_BANK0, RF_R42, rfval); + + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0x00002006); // 0x0518 + RtmpusecDelay(1); + + // BBP only Tx1 + bbpval = BBP1 & (~ 0x18); + bbpval = bbpval | 0x08; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, bbpval); + + // BBP only Rx1 + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x01); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x01); + } + RtmpusecDelay(500); + + /* e) Read mi, mq, si, sq, riq */ + vga_idx = 0; + + while( vga_idx < 11) + { + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R03, rf_vga_table[vga_idx]); + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R04, rf_vga_table[vga_idx]); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R03, rf_vga_table[vga_idx]); + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R04, rf_vga_table[vga_idx]); + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x00); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, 0x93); + + for (i = 0; i < 10000; i++) + { + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &bbpval); + if ((bbpval & 0xff)== 0x93) + RtmpusecDelay(50); + else + break; + } + + if ((bbpval & 0xff)== 0x93) + { + DBGPRINT(RT_DEBUG_ERROR, ("Fatal Error: Calibration doesn't finish")); + goto Restore_Value; + } + + for (i = 0; i < 5; i++) // 0 mi, 1 mq, 2 si, 3 sq, 4 riq + { + UINT32 BBPtemp = 0; + UINT8 value = 0; + INT32 result = 0; + + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x1E); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R159, i); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x22); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &value); + BBPtemp = BBPtemp + (value<<24); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x21); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &value); + BBPtemp = BBPtemp + (value<<16); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x20); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &value); + BBPtemp = BBPtemp + (value<<8); + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R158, 0x1F); + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R159, &value); + BBPtemp = BBPtemp + value; + + if ((i<2) && (BBPtemp & 0x800000)) // 23:0 + result = (BBPtemp & 0xFFFFFF) - 0x1000000; + else if(i==4) + result = BBPtemp; + else + result = BBPtemp; + + if (i == 0) + mi = result/4096; + else if (i==1) + mq = result/4096; + else if (i==2) + si = BBPtemp/4096; + else if (i==3) + sq = BBPtemp/4096; + else + riq = result/4096; + } + + /* Software AGC */ + bbpval1 = si - mi*mi; + DBGPRINT(RT_DEBUG_TRACE, ("RXIQ si=%d, sq=%d, riq=%d, bbpval %d, vga_idx %d\n", + si, sq, riq, bbpval1, vga_idx)); + + if(bbpval1 >= (100*100)) + break; + + if(bbpval1 <= 100) + vga_idx = vga_idx + 9; + else if(bbpval1 <= 158) + vga_idx = vga_idx + 8; + else if(bbpval1 <= 251) + vga_idx = vga_idx + 7; + else if(bbpval1 <= 398) + vga_idx = vga_idx + 6; + else if(bbpval1 <= 630) + vga_idx = vga_idx + 5; + else if(bbpval1 <= 1000) + vga_idx = vga_idx + 4; + else if(bbpval1 <= 1584) + vga_idx = vga_idx + 3; + else if(bbpval1 <= 2511) + vga_idx = vga_idx + 2; + else + vga_idx = vga_idx + 1; + } + + /* F) Calculate Sigma_i, Sigma_q, R_iq */ + Sigma_i = do_sqrt_accumulation(100*(si - mi*mi)); + Sigma_q = do_sqrt_accumulation(100*(sq - mq*mq)); + R_iq = 10*(riq-(mi*mq)); + + DBGPRINT(RT_DEBUG_TRACE, ("Sigma_i=%d, Sigma_q=%d, R_iq=%d\n", Sigma_i, Sigma_q, R_iq)); + + if(((Sigma_i <= 1400 ) && (Sigma_i >= 1000)) + && ((Sigma_i - Sigma_q) <= 112) + && ((Sigma_i - Sigma_q) >= -112) + && ((mi <= 32) && (mi >= -32)) + && ((mq <= 32) && (mq >= -32))) + { + R_iq = 10*(riq-(mi*mq)); + DBGPRINT(RT_DEBUG_TRACE, ("RXIQ Sigma_i=%d, Sigma_q=%d, R_iq=%d\n", Sigma_i, Sigma_q, R_iq)); + + /* G) Calculate Gain/ Phase imbalance */ + G_rx = (1000 * Sigma_q) / Sigma_i; + G_imb = ((-2) * 128 * (1000 - G_rx)) / (1000 + G_rx); + Ph_rx = (R_iq * 2292 ) / (Sigma_i * Sigma_q); + DBGPRINT(RT_DEBUG_TRACE, ("RXIQ G_imb=%d, Ph_rx=%d\n", G_imb, Ph_rx)); + + if((Ph_rx > 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, RTMP_RF_BYPASS0 , orig_RF_BYPASS0); + RTMP_IO_WRITE32(pAd, RF_CONTROL1 , orig_RF_CONTROL1); + RTMP_IO_WRITE32(pAd, RF_BYPASS1 , orig_RF_BYPASS1); + RTMP_IO_WRITE32(pAd, RF_CONTROL3 , orig_RF_CONTROL3); + RTMP_IO_WRITE32(pAd, RF_BYPASS3 , orig_RF_BYPASS3); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL , saveMacSysCtrl); +} + +VOID RF_SELF_TXDC_CAL( + IN PRTMP_ADAPTER pAd) +{ + // RF_CONTROL0: 0x0518 + // RTMP_RF_BYPASS0 : 0x051c + // RF_CONTROL2: 0x0528 + // RF_BYPASS2 : 0x052c + UCHAR RfB5R1_Org, RfB7R1_Org, RFValue; + UINT32 mac0518, mac051c,mac0528,mac052c; + CHAR i; + + DBGPRINT(RT_DEBUG_INFO, ("RF Tx_0 self calibration start\n")); + RTMP_IO_READ32(pAd, RF_CONTROL0, &mac0518); + RTMP_IO_READ32(pAd, RTMP_RF_BYPASS0 , &mac051c); + RTMP_IO_READ32(pAd, RF_CONTROL2, &mac0528); + RTMP_IO_READ32(pAd, RF_BYPASS2 , &mac052c); + + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0 , 0x0); + RTMP_IO_WRITE32(pAd, RF_BYPASS2 , 0x0); + + RTMP_IO_WRITE32(pAd, RF_CONTROL0, 0xC); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0 , 0x3306); + RTMP_IO_WRITE32(pAd, RF_CONTROL2, 0x3330); + RTMP_IO_WRITE32(pAd, RF_BYPASS2 , 0xfffff); + RT635xReadRFRegister(pAd, RF_BANK5, RF_R01, &RfB5R1_Org); + RT635xReadRFRegister(pAd, RF_BANK7, RF_R01, &RfB7R1_Org); + + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R01, 0x4); + for( i=0; i < 100; i = i + 1){ + RtmpusecDelay(50); /* wait 1 usec */ + RT635xReadRFRegister(pAd, RF_BANK5, RF_R01, &RFValue); + if((RFValue&0x04)!=0x4) + break; + } + RT635xWriteRFRegister(pAd, RF_BANK5, RF_R01, RfB5R1_Org); + + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R01, 0x4); + for( i=0; i < 100; i = i + 1){ + RtmpusecDelay(50); /* wait 1 usec */ + RT635xReadRFRegister(pAd, RF_BANK7, RF_R01, &RFValue); + if((RFValue&0x04)!=0x4) + break; + } + RT635xWriteRFRegister(pAd, RF_BANK7, RF_R01, RfB7R1_Org); + + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0 , 0x0); + RTMP_IO_WRITE32(pAd, RF_BYPASS2 , 0x0); + RTMP_IO_WRITE32(pAd, RF_CONTROL0, mac0518); + RTMP_IO_WRITE32(pAd, RTMP_RF_BYPASS0 , mac051c); + RTMP_IO_WRITE32(pAd, RF_CONTROL2, mac0528); + RTMP_IO_WRITE32(pAd, RF_BYPASS2 , mac052c); + + DBGPRINT(RT_DEBUG_INFO, ("RF Tx self calibration end\n")); + +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_sanity.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_sanity.c new file mode 100644 index 000000000..34493576b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_sanity.c @@ -0,0 +1,2262 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + sanity.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2004-09-01 add WMM support +*/ +#include "rt_config.h" +#ifdef DOT11R_FT_SUPPORT +#include "ft.h" +#include "ft_cmm.h" +#endif /* DOT11R_FT_SUPPORT */ + +extern UCHAR CISCO_OUI[]; +extern UCHAR APPLE_OUI[]; /* For IOS immediately connect */ +extern UCHAR WPA_OUI[]; +extern UCHAR RSN_OUI[]; +extern UCHAR WME_INFO_ELEM[]; +extern UCHAR WME_PARM_ELEM[]; +extern UCHAR RALINK_OUI[]; +#if (defined(WH_EZ_SETUP) || defined(MWDS)) +extern UCHAR MTK_OUI[]; +#endif +extern UCHAR BROADCOM_OUI[]; +extern UCHAR WPS_OUI[]; + + + +typedef struct wsc_ie_probreq_data +{ + UCHAR ssid[32]; + UCHAR macAddr[6]; + UCHAR data[2]; +} WSC_IE_PROBREQ_DATA; + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN MlmeAddBAReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2) +{ + PMLME_ADDBA_REQ_STRUCT pInfo; + + pInfo = (MLME_ADDBA_REQ_STRUCT *)Msg; + + if ((MsgLen != sizeof(MLME_ADDBA_REQ_STRUCT))) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - message lenght not correct.\n")); + return FALSE; + } + + if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - The peer Mac is not associated yet.\n")); + return FALSE; + } + + /* + if ((pInfo->BaBufSize > MAX_RX_REORDERBUF) || (pInfo->BaBufSize < 2)) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - Rx Reordering buffer too big or too small\n")); + return FALSE; + } + */ + + if ((pInfo->pAddr[0]&0x01) == 0x01) + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAddBAReqSanity fail - broadcast address not support BA\n")); + return FALSE; + } + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN MlmeDelBAReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen) +{ + MLME_DELBA_REQ_STRUCT *pInfo; + pInfo = (MLME_DELBA_REQ_STRUCT *)Msg; + + if ((MsgLen != sizeof(MLME_DELBA_REQ_STRUCT))) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - message lenght not correct.\n")); + return FALSE; + } + + if ((pInfo->Wcid >= MAX_LEN_OF_MAC_TABLE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - The peer Mac is not associated yet.\n")); + return FALSE; + } + + if ((pInfo->TID & 0xf0)) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - The peer TID is incorrect.\n")); + return FALSE; + } + + if (NdisEqualMemory(pAd->MacTab.Content[pInfo->Wcid].Addr, pInfo->Addr, MAC_ADDR_LEN) == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("MlmeDelBAReqSanity fail - the peer addr dosen't exist.\n")); + return FALSE; + } + + return TRUE; +} + + +BOOLEAN PeerAddBAReqActionSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2) +{ + PFRAME_802_11 pFrame = (PFRAME_802_11)pMsg; + PFRAME_ADDBA_REQ pAddFrame; + pAddFrame = (PFRAME_ADDBA_REQ)(pMsg); + if (MsgLen < (sizeof(FRAME_ADDBA_REQ))) + { + DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request frame length size = %ld incorrect\n", MsgLen)); + return FALSE; + } + /* we support immediate BA.*/ +#ifdef UNALIGNMENT_SUPPORT + { + BA_PARM tmpBaParm; + + NdisMoveMemory((PUCHAR)(&tmpBaParm), (PUCHAR)(&pAddFrame->BaParm), sizeof(BA_PARM)); + *(USHORT *)(&tmpBaParm) = cpu2le16(*(USHORT *)(&tmpBaParm)); + NdisMoveMemory((PUCHAR)(&pAddFrame->BaParm), (PUCHAR)(&tmpBaParm), sizeof(BA_PARM)); + } +#else + *(USHORT *)(&pAddFrame->BaParm) = cpu2le16(*(USHORT *)(&pAddFrame->BaParm)); +#endif + pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue); + pAddFrame->BaStartSeq.word = cpu2le16(pAddFrame->BaStartSeq.word); + + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + + if (pAddFrame->BaParm.BAPolicy != IMMED_BA) + { + DBGPRINT(RT_DEBUG_ERROR,("PeerAddBAReqActionSanity: ADDBA Request Ba Policy[%d] not support\n", pAddFrame->BaParm.BAPolicy)); + DBGPRINT(RT_DEBUG_ERROR,("ADDBA Request. tid=%x, Bufsize=%x, AMSDUSupported=%x \n", pAddFrame->BaParm.TID, pAddFrame->BaParm.BufSize, pAddFrame->BaParm.AMSDUSupported)); + return FALSE; + } + + return TRUE; +} + +BOOLEAN PeerAddBARspActionSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen) +{ + PFRAME_ADDBA_RSP pAddFrame; + + pAddFrame = (PFRAME_ADDBA_RSP)(pMsg); + if (MsgLen < (sizeof(FRAME_ADDBA_RSP))) + { + DBGPRINT(RT_DEBUG_ERROR,("%s(): ADDBA Resp frame length incorrect(len=%ld)\n", __FUNCTION__, MsgLen)); + return FALSE; + } + /* we support immediate BA.*/ +#ifdef UNALIGNMENT_SUPPORT + { + BA_PARM tmpBaParm; + + NdisMoveMemory((PUCHAR)(&tmpBaParm), (PUCHAR)(&pAddFrame->BaParm), sizeof(BA_PARM)); + *(USHORT *)(&tmpBaParm) = cpu2le16(*(USHORT *)(&tmpBaParm)); + NdisMoveMemory((PUCHAR)(&pAddFrame->BaParm), (PUCHAR)(&tmpBaParm), sizeof(BA_PARM)); + } +#else + *(USHORT *)(&pAddFrame->BaParm) = cpu2le16(*(USHORT *)(&pAddFrame->BaParm)); +#endif + pAddFrame->StatusCode = cpu2le16(pAddFrame->StatusCode); + pAddFrame->TimeOutValue = cpu2le16(pAddFrame->TimeOutValue); + + if (pAddFrame->BaParm.BAPolicy != IMMED_BA) + { + DBGPRINT(RT_DEBUG_ERROR,("%s(): ADDBA Resp Ba Policy[%d] not support\n", __FUNCTION__, pAddFrame->BaParm.BAPolicy)); + return FALSE; + } + + return TRUE; + +} + +BOOLEAN PeerDelBAActionSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN VOID *pMsg, + IN ULONG MsgLen ) +{ + PFRAME_DELBA_REQ pDelFrame; + + if (MsgLen != (sizeof(FRAME_DELBA_REQ))) + return FALSE; + + if (Wcid >= MAX_LEN_OF_MAC_TABLE) + return FALSE; + + pDelFrame = (PFRAME_DELBA_REQ)(pMsg); + + *(USHORT *)(&pDelFrame->DelbaParm) = cpu2le16(*(USHORT *)(&pDelFrame->DelbaParm)); + pDelFrame->ReasonCode = cpu2le16(pDelFrame->ReasonCode); + + return TRUE; +} + + +BOOLEAN PeerBeaconAndProbeRspSanity_Old( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN UCHAR MsgChannel, + OUT PUCHAR pAddr2, + OUT PUCHAR pBssid, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT UCHAR *pBssType, + OUT USHORT *pBeaconPeriod, + OUT UCHAR *pChannel, + OUT UCHAR *pNewChannel, + OUT LARGE_INTEGER *pTimestamp, + OUT CF_PARM *pCfParm, + OUT USHORT *pAtimWin, + OUT USHORT *pCapabilityInfo, + OUT UCHAR *pErp, + OUT UCHAR *pDtimCount, + OUT UCHAR *pDtimPeriod, + OUT UCHAR *pBcastFlag, + OUT UCHAR *pMessageToMe, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT UCHAR *pCkipFlag, + OUT UCHAR *pAironetCellPowerLimit, + OUT PEDCA_PARM pEdcaParm, + OUT PQBSS_LOAD_PARM pQbssLoad, + OUT PQOS_CAPABILITY_PARM pQosCapability, + OUT ULONG *pRalinkIe, + OUT UCHAR *pHtCapabilityLen, + 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; + PFRAME_802_11 pFrame; + PEID_STRUCT pEid; + UCHAR Sanity; + /*UCHAR ECWMin, ECWMax;*/ + /*MAC_CSR9_STRUC Csr9;*/ + ULONG Length = 0; + UCHAR *pPeerWscIe = NULL; + INT PeerWscIeLen = 0; + BOOLEAN bWscCheck = TRUE; + UCHAR LatchRfChannel = 0; + + + /* + For some 11a AP which didn't have DS_IE, we use two conditions to decide the channel + 1. If the AP is 11n enabled, then check the control channel. + 2. If the AP didn't have any info about channel, use the channel we received this + frame as the channel. (May inaccuracy!!) + */ + UCHAR CtrlChannel = 0; + + + os_alloc_mem(NULL, &pPeerWscIe, 512); + /* Add for 3 necessary EID field check*/ + Sanity = 0; + + *pAtimWin = 0; + *pErp = 0; + *pDtimCount = 0; + *pDtimPeriod = 0; + *pBcastFlag = 0; + *pMessageToMe = 0; + *pExtRateLen = 0; + *pCkipFlag = 0; /* Default of CkipFlag is 0*/ + *pAironetCellPowerLimit = 0xFF; /* Default of AironetCellPowerLimit is 0xFF*/ + *LengthVIE = 0; /* Set the length of VIE to init value 0*/ + *pHtCapabilityLen = 0; /* Set the length of VIE to init value 0*/ + *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 Addr2 and BSSID from header*/ + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + COPY_MAC_ADDR(pBssid, pFrame->Hdr.Addr3); + +/* hex_dump("Beacon", Msg, MsgLen);*/ + + Ptr = pFrame->Octet; + Length += LENGTH_802_11; + + /* get timestamp from payload and advance the pointer*/ + NdisMoveMemory(pTimestamp, Ptr, TIMESTAMP_LEN); + + pTimestamp->u.LowPart = cpu2le32(pTimestamp->u.LowPart); + pTimestamp->u.HighPart = cpu2le32(pTimestamp->u.HighPart); + + Ptr += TIMESTAMP_LEN; + Length += TIMESTAMP_LEN; + + /* get beacon interval from payload and advance the pointer*/ + NdisMoveMemory(pBeaconPeriod, Ptr, 2); + Ptr += 2; + Length += 2; + + /* get capability info from payload and advance the pointer*/ + NdisMoveMemory(pCapabilityInfo, Ptr, 2); + Ptr += 2; + Length += 2; + + if (CAP_IS_ESS_ON(*pCapabilityInfo)) + *pBssType = BSS_INFRA; + else + *pBssType = BSS_ADHOC; + + pEid = (PEID_STRUCT) Ptr; + + /* get variable fields from payload and advance the pointer*/ + while ((Length + 2 + pEid->Len) <= MsgLen) + { + + /* Secure copy VIE to VarIE[MAX_VIE_LEN] didn't overflow.*/ + if ((*LengthVIE + pEid->Len + 2) >= MAX_VIE_LEN) + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n", + __FUNCTION__, (*LengthVIE + pEid->Len + 2), MAX_VIE_LEN)); + break; + } + + switch(pEid->Eid) + { + case IE_SSID: + /* Already has one SSID EID in this beacon, ignore the second one*/ + if (Sanity & 0x1) + break; + if(pEid->Len <= MAX_LEN_OF_SSID) + { + NdisMoveMemory(Ssid, pEid->Octet, pEid->Len); + *pSsidLen = pEid->Len; + Sanity |= 0x1; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_SSID (len=%d)\n", __FUNCTION__, 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, ("%s() - wrong IE_SUPP_RATES (len=%d)\n",__FUNCTION__, pEid->Len)); + goto SanityCheck; + } + break; + + case IE_HT_CAP: + if (pEid->Len >= SIZE_HT_CAP_IE) /*Note: allow extension.!!*/ + { + NdisMoveMemory(pHtCapability, pEid->Octet, sizeof(HT_CAPABILITY_IE)); + *pHtCapabilityLen = SIZE_HT_CAP_IE; /* Nnow we only support 26 bytes.*/ + + *(USHORT *)(&pHtCapability->HtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->HtCapInfo)); +#ifdef UNALIGNMENT_SUPPORT + { + EXT_HT_CAP_INFO extHtCapInfo; + NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&pHtCapability->ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); + NdisMoveMemory((PUCHAR)(&pHtCapability->ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + } +#else + *(USHORT *)(&pHtCapability->ExtHtCapInfo) = cpu2le16(*(USHORT *)(&pHtCapability->ExtHtCapInfo)); +#endif /* UNALIGNMENT_SUPPORT */ +#ifdef RT_BIG_ENDIAN + *(UINT32 *)(&pHtCapability.TxBFCap) = + le2cpu32(*(UINT32 *)(&pHtCapability.TxBFCap)); +#endif + + + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - wrong IE_HT_CAP. pEid->Len = %d\n", __FUNCTION__, pEid->Len)); + } + + break; + case IE_ADD_HT: + if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) + { + /* + This IE allows extension, but we can ignore extra bytes beyond our + knowledge , so only copy first sizeof(ADD_HT_INFO_IE) + */ + NdisMoveMemory(AddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); + *AddHtInfoLen = SIZE_ADD_HT_INFO_IE; + + CtrlChannel = AddHtInfo->ControlChan; + + *(USHORT *)(&AddHtInfo->AddHtInfo2) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo2)); + *(USHORT *)(&AddHtInfo->AddHtInfo3) = cpu2le16(*(USHORT *)(&AddHtInfo->AddHtInfo3)); + + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - wrong IE_ADD_HT. \n", __FUNCTION__)); + } + + break; + case IE_SECONDARY_CH_OFFSET: + if (pEid->Len == 1) + { + *NewExtChannelOffset = pEid->Octet[0]; + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - wrong IE_SECONDARY_CH_OFFSET. \n", __FUNCTION__)); + } + + break; + case IE_FH_PARM: + DBGPRINT(RT_DEBUG_TRACE, ("%s(IE_FH_PARM) \n", __FUNCTION__)); + break; + + case IE_DS_PARM: + if(pEid->Len == 1) + { + *pChannel = *pEid->Octet; + Sanity |= 0x4; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_DS_PARM (len=%d)\n",__FUNCTION__,pEid->Len)); + goto SanityCheck; + } + break; + + case IE_CF_PARM: + if(pEid->Len == 6) + { + pCfParm->bValid = TRUE; + pCfParm->CfpCount = pEid->Octet[0]; + pCfParm->CfpPeriod = pEid->Octet[1]; + pCfParm->CfpMaxDuration = pEid->Octet[2] + 256 * pEid->Octet[3]; + pCfParm->CfpDurRemaining = pEid->Octet[4] + 256 * pEid->Octet[5]; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_CF_PARM\n", __FUNCTION__)); + if (pPeerWscIe) + os_free_mem(NULL, pPeerWscIe); + return FALSE; + } + break; + + case IE_IBSS_PARM: + if(pEid->Len == 2) + { + NdisMoveMemory(pAtimWin, pEid->Octet, pEid->Len); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_IBSS_PARM\n", __FUNCTION__)); + if (pPeerWscIe) + os_free_mem(NULL, pPeerWscIe); + return FALSE; + } + break; + + case IE_CHANNEL_SWITCH_ANNOUNCEMENT: + if(pEid->Len == 3) + { + *pNewChannel = pEid->Octet[1]; /*extract new channel number*/ + } + break; + + /* + New for WPA + CCX v2 has the same IE, we need to parse that too + Wifi WMM use the same IE vale, need to parse that too + */ + /* case IE_WPA:*/ + case IE_VENDOR_SPECIFIC: + /* Check the OUI version, filter out non-standard usage*/ + if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3) && (pEid->Len == 7)) + { + if (pEid->Octet[3] != 0) + *pRalinkIe = pEid->Octet[3]; + else + *pRalinkIe = 0xf0000000; /* Set to non-zero value (can't set bit0-2) to represent this is Ralink Chip. So at linkup, we will set ralinkchip flag.*/ + } + else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4)) + { + /* Copy to pVIE which will report to bssid list.*/ + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } + else if (NdisEqualMemory(pEid->Octet, WME_PARM_ELEM, 6) && (pEid->Len == 24)) + { + PUCHAR ptr; + int i; + + /* parsing EDCA parameters*/ + pEdcaParm->bValid = TRUE; + pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10;*/ + pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20;*/ + pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40;*/ + pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; + pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; + ptr = &pEid->Octet[8]; + for (i=0; i<4; i++) + { + UCHAR aci = (*ptr & 0x60) >> 5; /* b5~6 is AC INDEX*/ + pEdcaParm->bACM[aci] = (((*ptr) & 0x10) == 0x10); /* b5 is ACM*/ + pEdcaParm->Aifsn[aci] = (*ptr) & 0x0f; /* b0~3 is AIFSN*/ + pEdcaParm->Cwmin[aci] = *(ptr+1) & 0x0f; /* b0~4 is Cwmin*/ + pEdcaParm->Cwmax[aci] = *(ptr+1) >> 4; /* b5~8 is Cwmax*/ + pEdcaParm->Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); /* in unit of 32-us*/ + ptr += 4; /* point to next AC*/ + } + } + else if (NdisEqualMemory(pEid->Octet, WME_INFO_ELEM, 6) && (pEid->Len == 7)) + { + /* parsing EDCA parameters*/ + pEdcaParm->bValid = TRUE; + pEdcaParm->bQAck = FALSE; /* pEid->Octet[0] & 0x10;*/ + pEdcaParm->bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20;*/ + pEdcaParm->bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40;*/ + pEdcaParm->EdcaUpdateCount = pEid->Octet[6] & 0x0f; + pEdcaParm->bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; + + /* use default EDCA parameter*/ + pEdcaParm->bACM[QID_AC_BE] = 0; + pEdcaParm->Aifsn[QID_AC_BE] = 3; + pEdcaParm->Cwmin[QID_AC_BE] = pAd->wmm_cw_min; + pEdcaParm->Cwmax[QID_AC_BE] = pAd->wmm_cw_max; + pEdcaParm->Txop[QID_AC_BE] = 0; + + pEdcaParm->bACM[QID_AC_BK] = 0; + pEdcaParm->Aifsn[QID_AC_BK] = 7; + pEdcaParm->Cwmin[QID_AC_BK] = pAd->wmm_cw_min; + pEdcaParm->Cwmax[QID_AC_BK] = pAd->wmm_cw_max; + pEdcaParm->Txop[QID_AC_BK] = 0; + + pEdcaParm->bACM[QID_AC_VI] = 0; + pEdcaParm->Aifsn[QID_AC_VI] = 2; + pEdcaParm->Cwmin[QID_AC_VI] = pAd->wmm_cw_min - 1; + pEdcaParm->Cwmax[QID_AC_VI] = pAd->wmm_cw_max; + pEdcaParm->Txop[QID_AC_VI] = 96; /* AC_VI: 96*32us ~= 3ms*/ + + pEdcaParm->bACM[QID_AC_VO] = 0; + pEdcaParm->Aifsn[QID_AC_VO] = 2; + pEdcaParm->Cwmin[QID_AC_VO] = pAd->wmm_cw_min - 2; + pEdcaParm->Cwmax[QID_AC_VO] = pAd->wmm_cw_max - 1; + pEdcaParm->Txop[QID_AC_VO] = 48; /* AC_VO: 48*32us ~= 1.5ms*/ + } + else if (NdisEqualMemory(pEid->Octet, WPS_OUI, 4) + ) + { + if (pPeerWscIe) + { + /* Ignore old WPS IE fragments, if we get the version 0x10 */ + if (pEid->Octet[4] == 0x10) //First WPS IE will have version 0x10 + { + NdisMoveMemory(pPeerWscIe, pEid->Octet+4, pEid->Len - 4); + PeerWscIeLen = (pEid->Len - 4); + } + else // reassembly remanning, other IE fragmentations will not have version 0x10 + { + if ((PeerWscIeLen +(pEid->Len - 4)) <= 512) + { + NdisMoveMemory(pPeerWscIe+PeerWscIeLen, pEid->Octet+4, pEid->Len - 4); + PeerWscIeLen += (pEid->Len - 4); + } + else /* ((PeerWscIeLen +(pEid->Len - 4)) > 512) */ + { + bWscCheck = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s: Error!!! Sum of All PeerWscIeLen = %d (> 512)\n", __FUNCTION__, (PeerWscIeLen +(pEid->Len - 4)))); + } + } + } + else + { + bWscCheck = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s: Error!!! pPeerWscIe is empty!\n", __FUNCTION__)); + } + + + + + } + + + 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 */ + + + case IE_QBSS_LOAD: + if (pEid->Len == 5) + { + pQbssLoad->bValid = TRUE; + pQbssLoad->StaNum = pEid->Octet[0] + pEid->Octet[1] * 256; + pQbssLoad->ChannelUtilization = pEid->Octet[2]; + pQbssLoad->RemainingAdmissionControl = pEid->Octet[3] + pEid->Octet[4] * 256; + + /* Copy to pVIE*/ + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } + break; + + +#ifdef DOT11R_FT_SUPPORT + case IE_FT_MDIE: + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + break; +#endif /* DOT11R_FT_SUPPORT */ + + case IE_EXT_CAPABILITY: + if (pEid->Len >= 1) + { + UCHAR MaxSize; + UCHAR MySize = sizeof(EXT_CAP_INFO_ELEMENT); + + MaxSize = min(pEid->Len, MySize); + + NdisMoveMemory(pExtCapInfo,&pEid->Octet[0], MaxSize); +#ifdef RT_BIG_ENDIAN + (*(UINT32 *)(&(pExtCapInfo))) = + le2cpu32(*(UINT32 *)(&(pExtCapInfo))); + (*(UINT32 *)(&(pExtCapInfo)+4)) = + le2cpu32(*(UINT32 *)(&(pExtCapInfo)+4)); +#endif + } + break; + default: + break; + } + + Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len]*/ + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + LatchRfChannel = MsgChannel; + + if ((pAd->LatchRfRegs.Channel > 14) && ((Sanity & 0x4) == 0)) + { + if (CtrlChannel != 0) + *pChannel = CtrlChannel; + else + *pChannel = LatchRfChannel; + Sanity |= 0x4; + } + + + if (pPeerWscIe && (PeerWscIeLen > 0) && (PeerWscIeLen <= 512) && ( bWscCheck == TRUE)) + { + UCHAR WscIe[] = {0xdd, 0x00, 0x00, 0x50, 0xF2, 0x04}; + Ptr = (PUCHAR) pVIE; + WscIe[1] = PeerWscIeLen + 4; + NdisMoveMemory(Ptr + *LengthVIE, WscIe, 6); + NdisMoveMemory(Ptr + *LengthVIE + 6, pPeerWscIe, PeerWscIeLen); + *LengthVIE += (PeerWscIeLen + 6); + } + + +SanityCheck: + if (pPeerWscIe) + os_free_mem(NULL, pPeerWscIe); + + if ((Sanity != 0x7) || ( bWscCheck == FALSE)) + { + DBGPRINT(RT_DEBUG_LOUD, ("%s() - missing field, Sanity=0x%02x\n", __FUNCTION__, Sanity)); + return FALSE; + } + else + { + return TRUE; + } + +} + + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerBeaconAndProbeRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN UCHAR MsgChannel, + OUT BCN_IE_LIST *ie_list, + OUT USHORT *LengthVIE, + OUT PNDIS_802_11_VARIABLE_IEs pVIE, + IN BOOLEAN bGetDtim, + IN BOOLEAN bFromBeaconReport) +{ + UCHAR *Ptr; + PFRAME_802_11 pFrame; + PEID_STRUCT pEid; + UCHAR Sanity; + ULONG Length = 0; + UCHAR *pPeerWscIe = NULL; + INT PeerWscIeLen = 0; + BOOLEAN bWscCheck = TRUE; + UCHAR LatchRfChannel = 0; + + + /* + For some 11a AP which didn't have DS_IE, we use two conditions to decide the channel + 1. If the AP is 11n enabled, then check the control channel. + 2. If the AP didn't have any info about channel, use the channel we received this + frame as the channel. (May inaccuracy!!) + */ + UCHAR CtrlChannel = 0; + + + os_alloc_mem(NULL, &pPeerWscIe, 512); + Sanity = 0; /* Add for 3 necessary EID field check*/ + + ie_list->AironetCellPowerLimit = 0xFF; /* Default of AironetCellPowerLimit is 0xFF*/ + ie_list->NewExtChannelOffset = 0xff; /*Default 0xff means no such IE*/ + *LengthVIE = 0; /* Set the length of VIE to init value 0*/ + + if (bFromBeaconReport == FALSE) { + pFrame = (PFRAME_802_11)Msg; + + + /* get Addr2 and BSSID from header*/ + COPY_MAC_ADDR(&ie_list->Addr2[0], pFrame->Hdr.Addr2); + COPY_MAC_ADDR(&ie_list->Bssid[0], pFrame->Hdr.Addr3); + + Ptr = pFrame->Octet; + Length += LENGTH_802_11; + } else { + /* beacon report response's body have no 802.11 header part! */ + Ptr = (UINT8 *)Msg; + pFrame = NULL; /* init. */ + } + + /* get timestamp from payload and advance the pointer*/ + NdisMoveMemory(&ie_list->TimeStamp, Ptr, TIMESTAMP_LEN); + + ie_list->TimeStamp.u.LowPart = cpu2le32(ie_list->TimeStamp.u.LowPart); + ie_list->TimeStamp.u.HighPart = cpu2le32(ie_list->TimeStamp.u.HighPart); + + Ptr += TIMESTAMP_LEN; + Length += TIMESTAMP_LEN; + + /* get beacon interval from payload and advance the pointer*/ + NdisMoveMemory(&ie_list->BeaconPeriod, Ptr, 2); + Ptr += 2; + Length += 2; + + /* get capability info from payload and advance the pointer*/ + NdisMoveMemory(&ie_list->CapabilityInfo, Ptr, 2); + Ptr += 2; + Length += 2; + + if (CAP_IS_ESS_ON(ie_list->CapabilityInfo)) + ie_list->BssType = BSS_INFRA; + else + ie_list->BssType = BSS_ADHOC; + + pEid = (PEID_STRUCT) Ptr; + + /* get variable fields from payload and advance the pointer*/ + while ((Length + 2 + pEid->Len) <= MsgLen) + { + + /* Secure copy VIE to VarIE[MAX_VIE_LEN] didn't overflow.*/ + if ((*LengthVIE + pEid->Len + 2) >= MAX_VIE_LEN) + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - Variable IEs out of resource [len(=%d) > MAX_VIE_LEN(=%d)]\n", + __FUNCTION__, (*LengthVIE + pEid->Len + 2), MAX_VIE_LEN)); + break; + } + + switch(pEid->Eid) + { + case IE_SSID: + /* Already has one SSID EID in this beacon, ignore the second one*/ + if (Sanity & 0x1) + break; + if(pEid->Len <= MAX_LEN_OF_SSID) + { + NdisMoveMemory(&ie_list->Ssid[0], pEid->Octet, pEid->Len); + ie_list->SsidLen = pEid->Len; + Sanity |= 0x1; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_SSID (len=%d)\n",__FUNCTION__,pEid->Len)); + goto SanityCheck; + } + break; + + case IE_SUPP_RATES: + if(pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + Sanity |= 0x2; + NdisMoveMemory(&ie_list->SupRate[0], pEid->Octet, pEid->Len); + ie_list->SupRateLen = pEid->Len; + + /* + TODO: 2004-09-14 not a good design here, cause it exclude extra + rates from ScanTab. We should report as is. And filter out + unsupported rates in MlmeAux + */ + /* Check against the supported rates*/ + /* RTMPCheckRates(pAd, SupRate, pSupRateLen);*/ + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_SUPP_RATES (len=%d)\n",__FUNCTION__,pEid->Len)); + goto SanityCheck; + } + break; + +#ifdef NEIGHBORING_AP_STAT + case IE_TIM: + if (pEid->Len == 4) { + ie_list->DtimPeriod = pEid->Octet[1]; + } + break; +#endif + + case IE_HT_CAP: + if (pEid->Len >= SIZE_HT_CAP_IE) /*Note: allow extension.!!*/ + { + NdisMoveMemory(&ie_list->HtCapability, pEid->Octet, sizeof(HT_CAPABILITY_IE)); + ie_list->HtCapabilityLen = SIZE_HT_CAP_IE; /* Nnow we only support 26 bytes.*/ + + *(USHORT *)(&ie_list->HtCapability.HtCapInfo) = cpu2le16(*(USHORT *)(&ie_list->HtCapability.HtCapInfo)); +#ifdef UNALIGNMENT_SUPPORT + { + EXT_HT_CAP_INFO extHtCapInfo; + NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&ie_list->HtCapability.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); + NdisMoveMemory((PUCHAR)(&ie_list->HtCapability.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + } +#else + *(USHORT *)(&ie_list->HtCapability.ExtHtCapInfo) = + cpu2le16(*(USHORT *)(&ie_list->HtCapability.ExtHtCapInfo)); +#endif /* UNALIGNMENT_SUPPORT */ +#ifdef RT_BIG_ENDIAN + *(USHORT *)(&ie_list->HtCapability.TxBFCap) = + le2cpu32(*(USHORT *)(&ie_list->HtCapability.TxBFCap)); +#endif + + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - wrong IE_HT_CAP. pEid->Len = %d\n", __FUNCTION__, pEid->Len)); + } + + break; + case IE_ADD_HT: + if (pEid->Len >= sizeof(ADD_HT_INFO_IE)) + { + /* + This IE allows extension, but we can ignore extra bytes beyond our + knowledge , so only copy first sizeof(ADD_HT_INFO_IE) + */ + NdisMoveMemory(&ie_list->AddHtInfo, pEid->Octet, sizeof(ADD_HT_INFO_IE)); + ie_list->AddHtInfoLen = SIZE_ADD_HT_INFO_IE; + + CtrlChannel = ie_list->AddHtInfo.ControlChan; + + *(USHORT *)(&ie_list->AddHtInfo.AddHtInfo2) = cpu2le16(*(USHORT *)(&ie_list->AddHtInfo.AddHtInfo2)); + *(USHORT *)(&ie_list->AddHtInfo.AddHtInfo3) = cpu2le16(*(USHORT *)(&ie_list->AddHtInfo.AddHtInfo3)); + + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - wrong IE_ADD_HT. \n", __FUNCTION__)); + } + + break; + case IE_SECONDARY_CH_OFFSET: + if (pEid->Len == 1) + ie_list->NewExtChannelOffset = pEid->Octet[0]; + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s() - wrong IE_SECONDARY_CH_OFFSET. \n", __FUNCTION__)); + } + break; + + case IE_FH_PARM: + DBGPRINT(RT_DEBUG_TRACE, ("%s(IE_FH_PARM) \n", __FUNCTION__)); + break; + + case IE_DS_PARM: + if(pEid->Len == 1) + { + ie_list->Channel = *pEid->Octet; + Sanity |= 0x4; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_DS_PARM (len=%d)\n",__FUNCTION__,pEid->Len)); + goto SanityCheck; + } + break; + + case IE_CF_PARM: + if(pEid->Len == 6) + { + ie_list->CfParm.bValid = TRUE; + ie_list->CfParm.CfpCount = pEid->Octet[0]; + ie_list->CfParm.CfpPeriod = pEid->Octet[1]; + ie_list->CfParm.CfpMaxDuration = pEid->Octet[2] + 256 * pEid->Octet[3]; + ie_list->CfParm.CfpDurRemaining = pEid->Octet[4] + 256 * pEid->Octet[5]; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_CF_PARM\n", __FUNCTION__)); + if (pPeerWscIe) + os_free_mem(NULL, pPeerWscIe); + return FALSE; + } + break; + + case IE_IBSS_PARM: + if(pEid->Len == 2) + { + NdisMoveMemory(&ie_list->AtimWin, pEid->Octet, pEid->Len); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() - wrong IE_IBSS_PARM\n", __FUNCTION__)); + if (pPeerWscIe) + os_free_mem(NULL, pPeerWscIe); + return FALSE; + } + break; + + case IE_CHANNEL_SWITCH_ANNOUNCEMENT: + if(pEid->Len == 3) + ie_list->NewChannel = pEid->Octet[1]; /*extract new channel number*/ + break; + + /* + New for WPA + CCX v2 has the same IE, we need to parse that too + Wifi WMM use the same IE vale, need to parse that too + */ + /* case IE_WPA:*/ + case IE_VENDOR_SPECIFIC: +#if defined(MWDS) || defined(MAP_SUPPORT) + /* Check the OUI version, filter out non-standard usage*/ + check_vendor_ie(pAd, (UCHAR *)pEid, &(ie_list->vendor_ie)); +#endif + /* Check the OUI version, filter out non-standard usage*/ + if (NdisEqualMemory(pEid->Octet, RALINK_OUI, 3) && (pEid->Len == 7)) + { + if (pEid->Octet[3] != 0) + ie_list->RalinkIe = pEid->Octet[3]; + else + ie_list->RalinkIe = 0xf0000000; /* Set to non-zero value (can't set bit0-2) to represent this is Ralink Chip. So at linkup, we will set ralinkchip flag.*/ + } + +#ifdef APCLI_OWE_SUPPORT + else if (NdisEqualMemory(pEid->Octet, OWE_TRANS_OUI, 4)) { + UCHAR pair_ch = 0; + UCHAR pair_bssid[MAC_ADDR_LEN] = {0}; + UCHAR pair_ssid[MAX_LEN_OF_SSID] = {0}; + UCHAR pair_band = 0; + UCHAR pair_ssid_len = 0; + UCHAR ch = 0; + /* Copy to pVIE which will report to bssid list.*/ + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, (UCHAR *)pEid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + extract_pair_owe_bss_info(pEid->Octet + 4, + pEid->Len - 4, + pair_bssid, + pair_ssid, + &pair_ssid_len, + &pair_band, + &pair_ch); + if (pair_ch != 0) + ch = pair_ch; + else + ch = ie_list->Channel; + + if (ChannelSanity(pAd, ch) == FALSE) { + if (pPeerWscIe) + os_free_mem(NULL, pPeerWscIe); + return FALSE; + } + + } +#endif /*APCLI_OWE_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*/ + ie_list->EdcaParm.bValid = TRUE; + ie_list->EdcaParm.bQAck = FALSE; /* pEid->Octet[0] & 0x10;*/ + ie_list->EdcaParm.bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20;*/ + ie_list->EdcaParm.bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40;*/ + ie_list->EdcaParm.EdcaUpdateCount = pEid->Octet[6] & 0x0f; + ie_list->EdcaParm.bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; + ptr = &pEid->Octet[8]; + for (i=0; i<4; i++) + { + UCHAR aci = (*ptr & 0x60) >> 5; /* b5~6 is AC INDEX*/ + ie_list->EdcaParm.bACM[aci] = (((*ptr) & 0x10) == 0x10); /* b5 is ACM*/ + ie_list->EdcaParm.Aifsn[aci] = (*ptr) & 0x0f; /* b0~3 is AIFSN*/ + ie_list->EdcaParm.Cwmin[aci] = *(ptr+1) & 0x0f; /* b0~4 is Cwmin*/ + ie_list->EdcaParm.Cwmax[aci] = *(ptr+1) >> 4; /* b5~8 is Cwmax*/ + ie_list->EdcaParm.Txop[aci] = *(ptr+2) + 256 * (*(ptr+3)); /* in unit of 32-us*/ + ptr += 4; /* point to next AC*/ + } + } + else if (NdisEqualMemory(pEid->Octet, WME_INFO_ELEM, 6) && (pEid->Len == 7)) + { + /* parsing EDCA parameters*/ + ie_list->EdcaParm.bValid = TRUE; + ie_list->EdcaParm.bQAck = FALSE; /* pEid->Octet[0] & 0x10;*/ + ie_list->EdcaParm.bQueueRequest = FALSE; /* pEid->Octet[0] & 0x20;*/ + ie_list->EdcaParm.bTxopRequest = FALSE; /* pEid->Octet[0] & 0x40;*/ + ie_list->EdcaParm.EdcaUpdateCount = pEid->Octet[6] & 0x0f; + ie_list->EdcaParm.bAPSDCapable = (pEid->Octet[6] & 0x80) ? 1 : 0; + + /* use default EDCA parameter*/ + ie_list->EdcaParm.bACM[QID_AC_BE] = 0; + ie_list->EdcaParm.Aifsn[QID_AC_BE] = 3; + ie_list->EdcaParm.Cwmin[QID_AC_BE] = pAd->wmm_cw_min; + ie_list->EdcaParm.Cwmax[QID_AC_BE] = pAd->wmm_cw_max; + ie_list->EdcaParm.Txop[QID_AC_BE] = 0; + + ie_list->EdcaParm.bACM[QID_AC_BK] = 0; + ie_list->EdcaParm.Aifsn[QID_AC_BK] = 7; + ie_list->EdcaParm.Cwmin[QID_AC_BK] = pAd->wmm_cw_min; + ie_list->EdcaParm.Cwmax[QID_AC_BK] = pAd->wmm_cw_max; + ie_list->EdcaParm.Txop[QID_AC_BK] = 0; + + ie_list->EdcaParm.bACM[QID_AC_VI] = 0; + ie_list->EdcaParm.Aifsn[QID_AC_VI] = 2; + ie_list->EdcaParm.Cwmin[QID_AC_VI] = pAd->wmm_cw_min - 1; + ie_list->EdcaParm.Cwmax[QID_AC_VI] = pAd->wmm_cw_max; + ie_list->EdcaParm.Txop[QID_AC_VI] = 96; /* AC_VI: 96*32us ~= 3ms*/ + + ie_list->EdcaParm.bACM[QID_AC_VO] = 0; + ie_list->EdcaParm.Aifsn[QID_AC_VO] = 2; + ie_list->EdcaParm.Cwmin[QID_AC_VO] = pAd->wmm_cw_min - 2; + ie_list->EdcaParm.Cwmax[QID_AC_VO] = pAd->wmm_cw_max - 1; + ie_list->EdcaParm.Txop[QID_AC_VO] = 48; /* AC_VO: 48*32us ~= 1.5ms*/ + } + else if (NdisEqualMemory(pEid->Octet, WPS_OUI, 4) + ) + { + /* + 1. WSC 2.0 IE also has 0x104a000110. (WSC 1.0 version) + + 2. Some developing devices would broadcast incorrect IE content. + To prevent system crashed by those developing devices, we shall check length. + + @20140123 + */ + if (pPeerWscIe && (pEid->Len > 4)) + { + if ((PeerWscIeLen + (pEid->Len - 4)) <= 512) + { + NdisMoveMemory(pPeerWscIe+PeerWscIeLen, pEid->Octet+4, pEid->Len - 4); + PeerWscIeLen += (pEid->Len - 4); + } + else /* ((PeerWscIeLen +(pEid->Len - 4)) > 512) */ + { + bWscCheck = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s: Error!!! Sum of All PeerWscIeLen = %d (> 512)\n", __FUNCTION__, (PeerWscIeLen +(pEid->Len - 4)))); + } + } + else + { + bWscCheck = FALSE; + if (pEid->Len <= 4) + DBGPRINT(RT_DEBUG_TRACE, ("%s: Error!!! Incorrect WPS IE!\n", __FUNCTION__)); + if (pPeerWscIe == NULL) + DBGPRINT(RT_DEBUG_TRACE, ("%s: Error!!! pPeerWscIe is null!\n", __FUNCTION__)); + } + + + + } + + + break; + + case IE_EXT_SUPP_RATES: + if (pEid->Len <= MAX_LEN_OF_SUPPORTED_RATES) + { + NdisMoveMemory(&ie_list->ExtRate[0], pEid->Octet, pEid->Len); + ie_list->ExtRateLen = pEid->Len; + + /* + TODO: 2004-09-14 not a good design here, cause it exclude extra rates + from ScanTab. We should report as is. And filter out unsupported + rates in MlmeAux + */ + /* Check against the supported rates*/ + /* RTMPCheckRates(pAd, ExtRate, pExtRateLen);*/ + } + break; + + case IE_ERP: + if (pEid->Len == 1) + ie_list->Erp = (UCHAR)pEid->Octet[0]; + break; + + case IE_AIRONET_CKIP: + /* + 0. Check Aironet IE length, it must be larger or equal to 28 + Cisco AP350 used length as 28 + Cisco AP12XX used length as 30 + */ + if (pEid->Len < (CKIP_NEGOTIATION_LENGTH - 2)) + break; + + /* 1. Copy CKIP flag byte to buffer for process*/ + ie_list->CkipFlag = *(pEid->Octet + 8); + break; + + case IE_AP_TX_POWER: + /* AP Control of Client Transmit Power*/ + /*0. Check Aironet IE length, it must be 6*/ + if (pEid->Len != 0x06) + break; + + /* Get cell power limit in dBm*/ + if (NdisEqualMemory(pEid->Octet, CISCO_OUI, 3) == 1) + ie_list->AironetCellPowerLimit = *(pEid->Octet + 4); + break; + + /* WPA2 & 802.11i RSN*/ + case IE_RSN: + /* There is no OUI for version anymore, check the group cipher OUI before copying*/ + if (RTMPEqualMemory(pEid->Octet + 2, RSN_OUI, 3) || pEid->Len != 0) + { + /* 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 */ + + + case IE_QBSS_LOAD: + if (pEid->Len == 5) + { + ie_list->QbssLoad.bValid = TRUE; + ie_list->QbssLoad.StaNum = pEid->Octet[0] + pEid->Octet[1] * 256; + ie_list->QbssLoad.ChannelUtilization = pEid->Octet[2]; + ie_list->QbssLoad.RemainingAdmissionControl = pEid->Octet[3] + pEid->Octet[4] * 256; + + /* Copy to pVIE*/ + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + } + break; + + +#ifdef DOT11R_FT_SUPPORT + case IE_FT_MDIE: + Ptr = (PUCHAR) pVIE; + NdisMoveMemory(Ptr + *LengthVIE, &pEid->Eid, pEid->Len + 2); + *LengthVIE += (pEid->Len + 2); + break; +#endif /* DOT11R_FT_SUPPORT */ + + case IE_EXT_CAPABILITY: + if (pEid->Len >= 1) + { + UCHAR cp_len, buf_space = sizeof(EXT_CAP_INFO_ELEMENT); + + cp_len = min(pEid->Len, buf_space); + NdisMoveMemory(&ie_list->ExtCapInfo,&pEid->Octet[0], cp_len); +#ifdef RT_BIG_ENDIAN + (*(UINT32 *)(&(ie_list->ExtCapInfo))) = le2cpu32(*(UINT32 *)(&(ie_list->ExtCapInfo))); + (*(UINT32 *)(&(ie_list->ExtCapInfo)+4)) = + le2cpu32(*(UINT32 *)(&(ie_list->ExtCapInfo)+4)); +#endif + } + break; + +#ifdef DOT11_VHT_AC + case IE_VHT_CAP: + if (pEid->Len == sizeof(VHT_CAP_IE)) { +#ifdef RT_BIG_ENDIAN + UINT32 tmp_1; + UINT64 tmp_2; +#endif + NdisMoveMemory(&ie_list->vht_cap_ie, &pEid->Octet[0], sizeof(VHT_CAP_IE)); + ie_list->vht_cap_len = pEid->Len; +#ifdef RT_BIG_ENDIAN + NdisCopyMemory(&tmp_1, &ie_list->vht_cap_ie.vht_cap, 4); + tmp_1 = le2cpu32(tmp_1); + NdisCopyMemory(&ie_list->vht_cap_ie.vht_cap, &tmp_1, 4); + + NdisCopyMemory(&tmp_2, &(ie_list->vht_cap_ie.mcs_set), 8); + tmp_2 = le2cpu64(tmp_2); + NdisCopyMemory(&(ie_list->vht_cap_ie.mcs_set), &tmp_2, 8); +#endif + } + break; + case IE_VHT_OP: + if (pEid->Len == sizeof(VHT_OP_IE)) { +#ifdef RT_BIG_ENDIAN + UINT16 tmp; +#endif + NdisMoveMemory(&ie_list->vht_op_ie, &pEid->Octet[0], sizeof(VHT_OP_IE)); + ie_list->vht_op_len = pEid->Len; +#ifdef RT_BIG_ENDIAN + NdisCopyMemory(&tmp, &ie_list->vht_op_ie.basic_mcs_set, sizeof(VHT_MCS_MAP)); + tmp = le2cpu16(tmp); + NdisCopyMemory(&ie_list->vht_op_ie.basic_mcs_set, &tmp, sizeof(VHT_MCS_MAP)); +#endif + } + break; + case IE_OPERATING_MODE_NOTIFY: + if (pEid->Len == sizeof(OPERATING_MODE) && (bFromBeaconReport == FALSE)) { + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[BSSID_WCID]; + OPERATING_MODE op_mode; + + NdisMoveMemory(&op_mode, &pEid->Octet[0], sizeof(OPERATING_MODE)); + if (op_mode.rx_nss_type == 0) { + pEntry->force_op_mode = TRUE; + NdisMoveMemory(&pEntry->operating_mode, &op_mode, 1); + } + DBGPRINT(RT_DEBUG_TRACE, ("%s() - IE_OPERATING_MODE_NOTIFY(=%d)\n", __FUNCTION__, pEid->Eid)); + } +#endif /* DOT11_VHT_AC */ + + default: + break; + } + + Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len]*/ + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + LatchRfChannel = MsgChannel; + if ((pAd->LatchRfRegs.Channel > 14) && ((Sanity & 0x4) == 0)) + { + if (CtrlChannel != 0) + ie_list->Channel = CtrlChannel; + else { + if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40 +#ifdef DOT11_VHT_AC + || pAd->CommonCfg.RegTransmitSetting.field.BW == BW_80 +#endif /* DOT11_VHT_AC */ + ) { + ie_list->Channel = pAd->CommonCfg.Channel; + } + else + ie_list->Channel = LatchRfChannel; + } + Sanity |= 0x4; + } + + if (pPeerWscIe && (PeerWscIeLen > 0) && (PeerWscIeLen <= 512) && ( bWscCheck == TRUE)) + { + UCHAR WscIe[] = {0xdd, 0x00, 0x00, 0x50, 0xF2, 0x04}; + Ptr = (PUCHAR) pVIE; + WscIe[1] = PeerWscIeLen + 4; + NdisMoveMemory(Ptr + *LengthVIE, WscIe, 6); + NdisMoveMemory(Ptr + *LengthVIE + 6, pPeerWscIe, PeerWscIeLen); + *LengthVIE += (PeerWscIeLen + 6); + } + + +SanityCheck: + if (pPeerWscIe) + os_free_mem(NULL, pPeerWscIe); + + if ((Sanity != 0x7) || ( bWscCheck == FALSE)) + { + if (((bFromBeaconReport == FALSE) && (Sanity != 0x7)) || + ((bFromBeaconReport == TRUE) && (!(Sanity & 0x1))) || (bWscCheck == FALSE)) { + DBGPRINT(RT_DEBUG_LOUD, ("%s() - missing field, Sanity=0x%02x\n", __func__, Sanity)); + return FALSE; + } + } + else + { + } + return TRUE; +} + + +#ifdef DOT11N_DRAFT3 +/* + ========================================================================== + Description: + MLME message sanity check for some IE addressed in 802.11n d3.03. + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerBeaconAndProbeRspSanity2( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN OVERLAP_BSS_SCAN_IE *BssScan, + OUT UCHAR *RegClass) +{ + CHAR *Ptr; + PFRAME_802_11 pFrame; + PEID_STRUCT pEid; + ULONG Length = 0; + BOOLEAN brc; + + pFrame = (PFRAME_802_11)Msg; + + *RegClass = 0; + Ptr = pFrame->Octet; + Length += LENGTH_802_11; + + /* get timestamp from payload and advance the pointer*/ + Ptr += TIMESTAMP_LEN; + Length += TIMESTAMP_LEN; + + /* get beacon interval from payload and advance the pointer*/ + Ptr += 2; + Length += 2; + + /* get capability info from payload and advance the pointer*/ + Ptr += 2; + Length += 2; + + pEid = (PEID_STRUCT) Ptr; + brc = FALSE; + + RTMPZeroMemory(BssScan, sizeof(OVERLAP_BSS_SCAN_IE)); + /* get variable fields from payload and advance the pointer*/ + while ((Length + 2 + pEid->Len) <= MsgLen) + { + switch(pEid->Eid) + { + case IE_SUPP_REG_CLASS: + if(pEid->Len > 0) + { + *RegClass = *pEid->Octet; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_SUPP_REG_CLASS (len=%d)\n",pEid->Len)); + } + break; + case IE_OVERLAPBSS_SCAN_PARM: + if (pEid->Len == sizeof(OVERLAP_BSS_SCAN_IE)) + { + brc = TRUE; + RTMPMoveMemory(BssScan, pEid->Octet, sizeof(OVERLAP_BSS_SCAN_IE)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - wrong IE_OVERLAPBSS_SCAN_PARM (len=%d)\n",pEid->Len)); + } + break; + + case IE_EXT_CHANNEL_SWITCH_ANNOUNCEMENT: + DBGPRINT(RT_DEBUG_TRACE, ("PeerBeaconAndProbeRspSanity - IE_EXT_CHANNEL_SWITCH_ANNOUNCEMENT\n")); + break; + + } + + Length = Length + 2 + pEid->Len; /* Eid[1] + Len[1]+ content[Len] */ + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + return brc; + +} +#endif /* DOT11N_DRAFT3 */ + +#if defined(AP_SCAN_SUPPORT) || defined(CONFIG_STA_SUPPORT) +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ +BOOLEAN MlmeScanReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *pBssType, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT UCHAR *pScanType +#ifdef CONFIG_AP_SUPPORT +#endif + ) +{ + MLME_SCAN_REQ_STRUCT *Info; + + Info = (MLME_SCAN_REQ_STRUCT *)(Msg); + *pBssType = Info->BssType; + *pSsidLen = Info->SsidLen; + NdisMoveMemory(Ssid, Info->Ssid, *pSsidLen); + *pScanType = Info->ScanType; +#ifdef CONFIG_AP_SUPPORT +#endif + + if ((*pBssType == BSS_INFRA || *pBssType == BSS_ADHOC || *pBssType == BSS_ANY) + && (SCAN_MODE_VALID(*pScanType)) + ) + { + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeScanReqSanity fail - wrong BssType or ScanType\n")); + return FALSE; + } +} +#endif + +/* IRQL = DISPATCH_LEVEL*/ +UCHAR ChannelSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel) +{ + int i; + + for (i = 0; i < pAd->ChannelListNum; i ++) + { + if (channel == pAd->ChannelList[i].Channel) + return 1; + } + return 0; +} + +#ifdef P2P_CHANNEL_LIST_SEPARATE +/* IRQL = DISPATCH_LEVEL*/ +UCHAR P2PChannelSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel) +{ + int i; + PCFG80211_CTRL pCfg80211_Ctrl = &pAd->cfg80211_ctrl; + + for (i = 0; i < pCfg80211_Ctrl->ChannelListNum; i ++) + { + if (channel == pCfg80211_Ctrl->ChannelList[i].Channel) + return 1; + } + return 0; +} +#endif /* P2P_CHANNEL_LIST_SEPARATE */ + + + +/* + ========================================================================== + 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); +#ifdef WH_EZ_SETUP + if (IS_ADPTR_EZ_SETUP_ENABLED(pAd) && (*pReason == MLME_EZ_DISCONNECT_NON_EZ)) + { + return FALSE; + } +#endif + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerAuthSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT USHORT *pAlg, + OUT USHORT *pSeq, + OUT USHORT *pStatus, + CHAR *pChlgText) +{ + PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + + COPY_MAC_ADDR(pAddr, pFrame->Hdr.Addr2); + NdisMoveMemory(pAlg, &pFrame->Octet[0], 2); + NdisMoveMemory(pSeq, &pFrame->Octet[2], 2); + NdisMoveMemory(pStatus, &pFrame->Octet[4], 2); + + if (*pAlg == AUTH_MODE_OPEN) + { + if (*pSeq == 1 || *pSeq == 2) + { + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong Seg#\n")); + return FALSE; + } + } + else if (*pAlg == AUTH_MODE_KEY) + { + if (*pSeq == 1 || *pSeq == 4) + { + return TRUE; + } + else if (*pSeq == 2 || *pSeq == 3) + { + NdisMoveMemory(pChlgText, &pFrame->Octet[8], CIPHER_TEXT_LEN); + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong Seg#\n")); + return FALSE; + } + } +#ifdef DOT11R_FT_SUPPORT + else if (*pAlg == AUTH_MODE_FT) + { + return TRUE; + } +#endif /* DOT11R_FT_SUPPORT */ +#ifdef WH_EZ_SETUP + else if (IS_ADPTR_EZ_SETUP_ENABLED(pAd) && (*pAlg == AUTH_MODE_EZ)) + { + return TRUE; + } +#endif /* WH_EZ_SETUP */ + else + { + DBGPRINT(RT_DEBUG_TRACE, ("PeerAuthSanity fail - wrong algorithm\n")); + return FALSE; + } +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ +BOOLEAN MlmeAuthReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT ULONG *pTimeout, + OUT USHORT *pAlg) +{ + MLME_AUTH_REQ_STRUCT *pInfo; + + pInfo = (MLME_AUTH_REQ_STRUCT *)Msg; + COPY_MAC_ADDR(pAddr, pInfo->Addr); + *pTimeout = pInfo->Timeout; + *pAlg = pInfo->Alg; + + if (((*pAlg == AUTH_MODE_KEY) ||(*pAlg == AUTH_MODE_OPEN) +#ifdef DOT11R_FT_SUPPORT + || (*pAlg == AUTH_MODE_FT) +#endif /* DOT11R_FT_SUPPORT */ +#ifdef WH_EZ_SETUP + || (IS_ADPTR_EZ_SETUP_ENABLED(pAd) && (*pAlg == AUTH_MODE_EZ)) +#endif /* WH_EZ_SETUP */ + ) && + ((*pAddr & 0x01) == 0)) + { + return TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("MlmeAuthReqSanity fail - wrong algorithm\n")); + return FALSE; + } +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN MlmeAssocReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pApAddr, + OUT USHORT *pCapabilityInfo, + OUT ULONG *pTimeout, + OUT USHORT *pListenIntv) +{ + MLME_ASSOC_REQ_STRUCT *pInfo; + + pInfo = (MLME_ASSOC_REQ_STRUCT *)Msg; + *pTimeout = pInfo->Timeout; /* timeout*/ + COPY_MAC_ADDR(pApAddr, pInfo->Addr); /* AP address*/ + *pCapabilityInfo = pInfo->CapabilityInfo; /* capability info*/ + *pListenIntv = pInfo->ListenIntv; + + return TRUE; +} + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +BOOLEAN PeerDisassocSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pReason) +{ + PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + + COPY_MAC_ADDR(pAddr2, pFrame->Hdr.Addr2); + NdisMoveMemory(pReason, &pFrame->Octet[0], 2); + + return TRUE; +} + +/* + ======================================================================== + Routine Description: + Sanity check NetworkType (11b, 11g or 11a) + + Arguments: + pBss - Pointer to BSS table. + + Return Value: + Ndis802_11DS .......(11b) + Ndis802_11OFDM24....(11g) + Ndis802_11OFDM5.....(11a) + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity(BSS_ENTRY *pBss) +{ + NDIS_802_11_NETWORK_TYPE NetWorkType; + UCHAR rate, i; + + NetWorkType = Ndis802_11DS; + + if (pBss->Channel <= 14) + { + + /* First check support Rate.*/ + for (i = 0; i < pBss->SupRateLen; i++) + { + rate = pBss->SupRate[i] & 0x7f; /* Mask out basic rate set bit*/ + if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22)) + { + continue; + } + else + { + + /* Otherwise (even rate > 108) means Ndis802_11OFDM24*/ + NetWorkType = Ndis802_11OFDM24; + break; + } + } + + + /* Second check Extend Rate.*/ + if (NetWorkType != Ndis802_11OFDM24) + { + for (i = 0; i < pBss->ExtRateLen; i++) + { + rate = pBss->SupRate[i] & 0x7f; /* Mask out basic rate set bit*/ + if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22)) + { + continue; + } + else + { + + /* Otherwise (even rate > 108) means Ndis802_11OFDM24*/ + NetWorkType = Ndis802_11OFDM24; + break; + } + } + } + } + else + { + NetWorkType = Ndis802_11OFDM5; + } + + if (pBss->HtCapabilityLen != 0) + { + if (NetWorkType == Ndis802_11OFDM5) + NetWorkType = Ndis802_11OFDM5_N; + else + NetWorkType = Ndis802_11OFDM24_N; + } + + return NetWorkType; +} + + + + +/* + ========================================================================== + Description: + MLME message sanity check + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== + */ +BOOLEAN PeerProbeReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PEER_PROBE_REQ_PARAM *ProbeReqParam) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)Msg; + UCHAR *Ptr; + UCHAR eid =0, eid_len = 0, *eid_data; +#ifdef CONFIG_AP_SUPPORT +#if defined(WSC_INCLUDED) || defined(EASY_CONFIG_SETUP) || defined(WAPP_SUPPORT) + UCHAR apidx = MAIN_MBSSID; +#endif + UCHAR Addr1[MAC_ADDR_LEN]; +#ifdef WSC_INCLUDED + UCHAR *pPeerWscIe = NULL; + UINT PeerWscIeLen = 0; + BOOLEAN bWscCheck = TRUE; +#endif /* WSC_INCLUDED */ +#endif /* CONFIG_AP_SUPPORT */ + UINT total_ie_len = 0; +#ifdef WH_EVENT_NOTIFIER + IE_LISTS *ie_lists = &ProbeReqParam->ie_list; +#endif /* WH_EVENT_NOTIFIER */ + + NdisZeroMemory(ProbeReqParam, sizeof(*ProbeReqParam)); + COPY_MAC_ADDR(ProbeReqParam->Addr2, &Fr->Hdr.Addr2); + + if (Fr->Octet[0] != IE_SSID || Fr->Octet[1] > MAX_LEN_OF_SSID) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(): sanity fail - wrong SSID IE\n", __FUNCTION__)); + return FALSE; + } + /* + * MAP-R1 4.8.5 workaround + * Test case expect auth/assoc reject after probe response therefore + * dropping it here will cause test case to fail. + * Impact on band steering: Client will be able to see blocked bss as + * well, however connection will be rejected in auth phase. + * TODO: Define a separate ioctl for probe withholding and do not + * call that in certification case. Correct apidex passed in below API. + */ + + ProbeReqParam->SsidLen = Fr->Octet[1]; + NdisMoveMemory(ProbeReqParam->Ssid, &Fr->Octet[2], ProbeReqParam->SsidLen); + +#ifdef CONFIG_AP_SUPPORT + COPY_MAC_ADDR(Addr1, &Fr->Hdr.Addr1); +#ifdef WSC_AP_SUPPORT + os_alloc_mem(NULL, &pPeerWscIe, 512); +#endif /* WSC_AP_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + 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; + + /* For IOS immediately connect */ + if (!ProbeReqParam->IsFromIos && NdisEqualMemory(eid_data, APPLE_OUI, 3)) { + ProbeReqParam->IsFromIos = TRUE; + } + +#ifdef RSSI_FEEDBACK + if (ProbeReqParam->bRssiRequested && + NdisEqualMemory(eid_data, RALINK_OUI, 3) && (eid_len == 7)) + { + if (*(eid_data + 3/* skip RALINK_OUI */) & 0x8) + ProbeReqParam->bRssiRequested = TRUE; + break; + } +#endif /* RSSI_FEEDBACK */ + +#ifdef WH_EVENT_NOTIFIER + if(pAd->ApCfg.EventNotifyCfg.CustomOUILen && + (eid_len >= pAd->ApCfg.EventNotifyCfg.CustomOUILen) && + NdisEqualMemory(eid_data, pAd->ApCfg.EventNotifyCfg.CustomOUI, pAd->ApCfg.EventNotifyCfg.CustomOUILen)) + { + ie_lists->vendor_ie.custom_ie_len = eid_len; + NdisMoveMemory(ie_lists->vendor_ie.custom_ie, eid_data, eid_len); + break; + } +#endif /* WH_EVENT_NOTIFIER */ + + if (NdisEqualMemory(eid_data, WPS_OUI, 4) + ) + { +#ifdef CONFIG_AP_SUPPORT +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef WSC_INCLUDED + + + WscCheckPeerDPID(pAd, Fr, eid_data, eid_len); + +#ifdef CONFIG_AP_SUPPORT + if (pPeerWscIe) + { + /* Ignore old WPS IE fragments, if we get the version 0x10 */ + if (*(eid_data+4) == 0x10) //First WPS IE will have version 0x10 + { + NdisMoveMemory(pPeerWscIe, eid_data+4, eid_len-4); + PeerWscIeLen = (eid_len-4); + } + else // reassembly remanning, other IE fragmentations will not have version 0x10 + { + if ((PeerWscIeLen +(eid_len-4)) <= 512) + { + NdisMoveMemory(pPeerWscIe+PeerWscIeLen, eid_data+4, eid_len-4); + PeerWscIeLen += (eid_len-4); + } + else /* ((PeerWscIeLen +(eid_len-4)) > 512) */ + { + bWscCheck = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s: Error!Sum of All PeerWscIeLen = %d (> 512)\n", + __FUNCTION__, (PeerWscIeLen +(eid_len-4)))); + } + } + } + else + { + bWscCheck = FALSE; + DBGPRINT(RT_DEBUG_ERROR, ("%s: Error!!! pPeerWscIe is empty!\n", __FUNCTION__)); + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* WSC_INCLUDED */ + } + break; + +#ifdef CONFIG_HOTSPOT + case IE_INTERWORKING: + ProbeReqParam->AccessNetWorkType = (*eid_data) & 0x0F; + + if (eid_len > 3) + { + if (eid_len == 7) + NdisMoveMemory(ProbeReqParam->Hessid, eid_data + 1, MAC_ADDR_LEN); + else + NdisMoveMemory(ProbeReqParam->Hessid, eid_data + 3 , MAC_ADDR_LEN); + + ProbeReqParam->IsHessid = TRUE; + } + + ProbeReqParam->IsIWIE = TRUE; + break; +#endif + case IE_EXT_CAPABILITY: +#ifdef CONFIG_HOTSPOT + if (eid_len >= 4) + { + if (((*(eid_data + 3)) & 0x80) == 0x80) + ProbeReqParam->IsIWCapability = TRUE; + } +#endif + break; + + +#if (defined(BAND_STEERING) || defined(WH_EVENT_NOTIFIER)) + case IE_HT_CAP: +#ifdef BAND_STEERING + if (pAd->ApCfg.BandSteering != TRUE) + break; +#endif + if (eid_len >= SIZE_HT_CAP_IE) + { +#ifdef BAND_STEERING + ProbeReqParam->IsHtSupport = TRUE; + ProbeReqParam->RxMCSBitmask = *(UINT32 *)(eid_data + 3); +#endif +#ifdef WH_EVENT_NOTIFIER + NdisMoveMemory(&ie_lists->HTCapability, eid_data, SIZE_HT_CAP_IE); + *(USHORT *)(&ie_lists->HTCapability.HtCapInfo) = cpu2le16(*(USHORT *)(&ie_lists->HTCapability.HtCapInfo)); + *(USHORT *)(&ie_lists->HTCapability.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&ie_lists->HTCapability.ExtHtCapInfo)); + ie_lists->ht_cap_len = SIZE_HT_CAP_IE; +#endif /* WH_EVENT_NOTIFIER */ + + } + else + MTWF_LOG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_WARN, ("%s() - wrong IE_HT_CAP. eid_len = %d\n", __FUNCTION__, eid_len)); + break; + +#ifdef DOT11_VHT_AC + case IE_VHT_CAP: + if (pAd->ApCfg.BandSteering != TRUE) + break; + if (eid_len >= SIZE_OF_VHT_CAP_IE) { + ProbeReqParam->IsVhtSupport = TRUE; +#ifdef WH_EVENT_NOTIFIER + NdisMoveMemory(&ie_lists->vht_cap, eid_data, eid_len); + ie_lists->vht_cap_len = eid_len; +#endif /* WH_EVENT_NOTIFIER */ + } + else + MTWF_LOG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_WARN, ("%s() - wrong IE_VHT_CAP. eid_len = %d\n", __FUNCTION__, eid_len)); + break; +#endif /* DOT11_VHT_AC */ +#endif + default: + break; + } + eid = Ptr[total_ie_len]; + eid_len = Ptr[total_ie_len + 1]; + eid_data = Ptr + total_ie_len + 2; + total_ie_len += (eid_len + 2); + } + +#ifdef CONFIG_AP_SUPPORT +#ifdef WSC_INCLUDED + if (pPeerWscIe && (PeerWscIeLen > 0) && (bWscCheck == TRUE)) + { + /* WPS_BandSteering Support */ +#ifdef BAND_STEERING + ProbeReqParam->bWpsCapable = TRUE; +#endif + + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + if (NdisEqualMemory(Addr1, pAd->ApCfg.MBSSID[apidx].wdev.bssid, MAC_ADDR_LEN)) + break; + } + + /* + Due to Addr1 in Probe Request may be FF:FF:FF:FF:FF:FF + and we need to send out this information to external registrar. + Therefore we choose ra0 to send this probe req when we couldn't find apidx by Addr1. + */ + if (apidx >= pAd->ApCfg.BssidNum) + { + apidx = MAIN_MBSSID; + } + + if ((pAd->ApCfg.MBSSID[apidx].WscControl.WscConfMode & WSC_PROXY) != WSC_DISABLE) + { + int bufLen = 0; + PUCHAR pBuf = NULL; + WSC_IE_PROBREQ_DATA *pprobreq = NULL; + + /* + PeerWscIeLen: Len of WSC IE without WSC OUI + */ + bufLen = sizeof(WSC_IE_PROBREQ_DATA) + PeerWscIeLen; + os_alloc_mem(NULL, &pBuf, bufLen); + if(pBuf) + { + /*Send WSC probe req to UPnP*/ + NdisZeroMemory(pBuf, bufLen); + pprobreq = (WSC_IE_PROBREQ_DATA*)pBuf; + if (32 >= ProbeReqParam->SsidLen) /*Well, I think that it must be TRUE!*/ + { + NdisMoveMemory(pprobreq->ssid, ProbeReqParam->Ssid, ProbeReqParam->SsidLen); /* SSID*/ + NdisMoveMemory(pprobreq->macAddr, Fr->Hdr.Addr2, 6); /* Mac address*/ + pprobreq->data[0] = PeerWscIeLen>>8; /* element ID*/ + pprobreq->data[1] = PeerWscIeLen & 0xff; /* element Length */ + NdisMoveMemory((pBuf+sizeof(WSC_IE_PROBREQ_DATA)), pPeerWscIe, PeerWscIeLen); /* (WscProbeReqData)*/ + WscSendUPnPMessage(pAd, apidx, + WSC_OPCODE_UPNP_MGMT, WSC_UPNP_MGMT_SUB_PROBE_REQ, + pBuf, bufLen, 0, 0, &Fr->Hdr.Addr2[0], AP_MODE); + } + os_free_mem(NULL, pBuf); + } + } + } + if (pPeerWscIe) + os_free_mem(NULL, pPeerWscIe); +#endif /* WSC_INCLUDED */ +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + +/* =========================================================== +Routine Description: + Check a packet is Action frame or not + +Arguments: + pAd - WLAN control block pointer + pbuf - packet buffer + +Return Value: + TRUE - yes + FALSE - no + +============================================================*/ +BOOLEAN +IsPublicActionFrame( + IN PRTMP_ADAPTER pAd, + IN VOID *pbuf +) +{ + HEADER_802_11 *pHeader = pbuf; + UINT8 *ptr = pbuf; + + if (pHeader->FC.Type != FC_TYPE_MGMT) + return FALSE; + + if (pHeader->FC.SubType != SUBTYPE_ACTION) + return FALSE; + + ptr += sizeof(HEADER_802_11); + + if (*ptr == CATEGORY_PUBLIC) + return TRUE; + else + return FALSE; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_sync.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_sync.c new file mode 100644 index 000000000..87b16e8d1 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_sync.c @@ -0,0 +1,635 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + cmm_sync.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2004-09-01 modified for rt2561/2661 +*/ +#include "rt_config.h" + +/*BaSizeArray follows the 802.11n definition as MaxRxFactor. 2^(13+factor) bytes. When factor =0, it's about Ba buffer size =8.*/ +UCHAR BaSizeArray[4] = {8,16,32,64}; + +extern COUNTRY_REGION_CH_DESC Country_Region_ChDesc_2GHZ[]; +extern UINT16 const Country_Region_GroupNum_2GHZ; +extern COUNTRY_REGION_CH_DESC Country_Region_ChDesc_5GHZ[]; +extern UINT16 const Country_Region_GroupNum_5GHZ; + +/* + ========================================================================== + Description: + Update StaCfg->ChannelList[] according to 1) Country Region 2) RF IC type, + and 3) PHY-mode user selected. + The outcome is used by driver when doing site survey. + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID BuildChannelList(RTMP_ADAPTER *pAd) +{ + UCHAR i, j, index=0, num=0; + PCH_DESC pChDesc = NULL; + BOOLEAN bRegionFound = FALSE; + PUCHAR pChannelList = NULL; + PUCHAR pChannelListFlag = NULL; + + + + NdisZeroMemory(pAd->ChannelList, MAX_NUM_OF_CHANNELS * sizeof(CHANNEL_TX_POWER)); + + /* if not 11a-only mode, channel list starts from 2.4Ghz band*/ + if (WMODE_CAP_2G(pAd->CommonCfg.PhyMode)) + { + for (i = 0; i < Country_Region_GroupNum_2GHZ; i++) + { + if ((pAd->CommonCfg.CountryRegion & 0x7f) == + Country_Region_ChDesc_2GHZ[i].RegionIndex) + { + pChDesc = Country_Region_ChDesc_2GHZ[i].pChDesc; + num = TotalChNum(pChDesc); + bRegionFound = TRUE; + + break; + } + } + + if (!bRegionFound) + { + DBGPRINT(RT_DEBUG_ERROR,("CountryRegion=%d not support", pAd->CommonCfg.CountryRegion)); + return; + } + + if (num > 0) + { + os_alloc_mem(NULL, (UCHAR **)&pChannelList, num * sizeof(UCHAR)); + + if (!pChannelList) + { + DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelList failed\n", __FUNCTION__)); + return; + } + + os_alloc_mem(NULL, (UCHAR **)&pChannelListFlag, num * sizeof(UCHAR)); + + if (!pChannelListFlag) + { + DBGPRINT(RT_DEBUG_ERROR,("%s:Allocate memory for ChannelListFlag failed\n", __FUNCTION__)); + os_free_mem(NULL, pChannelList); + return; + } + + for (i = 0; i < num; i++) + { + pChannelList[i] = GetChannel_2GHZ(pChDesc, i); + pChannelListFlag[i] = GetChannelFlag(pChDesc, i); + } + + for (i = 0; i < num; i++) + { + for (j = 0; j < MAX_NUM_OF_CHANNELS; j++) + { + if (pChannelList[i] == pAd->TxPower[j].Channel) + NdisMoveMemory(&pAd->ChannelList[index+i], &pAd->TxPower[j], sizeof(CHANNEL_TX_POWER)); + } + + pAd->ChannelList[index + i].Flags = pChannelListFlag[i]; + /* TODO: shiang-7603, NdisMoveMemory may replace the + * pAd->ChannelList[index+i].Channel as other values! + */ + pAd->ChannelList[index+i].Channel = pChannelList[i]; + + +#ifdef DOT11_N_SUPPORT + if (N_ChannelGroupCheck(pAd, pAd->ChannelList[index + i].Channel)) + pAd->ChannelList[index + i].Flags |= CHANNEL_40M_CAP; +#ifdef DOT11_VHT_AC + if (vht80_channel_group(pAd, pAd->ChannelList[index + i].Channel)) + pAd->ChannelList[index + i].Flags |= CHANNEL_80M_CAP; +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + if (!strncmp((RTMP_STRING *) pAd->CommonCfg.CountryCode, "CN", 2)) + pAd->ChannelList[index+i].MaxTxPwr = pAd->MaxTxPwr;/*for CN CountryCode*/ + else + pAd->ChannelList[index+i].MaxTxPwr = 20; + } + + index += num; + + os_free_mem(NULL, pChannelList); + os_free_mem(NULL, pChannelListFlag); + } + bRegionFound = FALSE; + num = 0; + } + + if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + { + for (i = 0; i < Country_Region_GroupNum_5GHZ; i++) + { + if ((pAd->CommonCfg.CountryRegionForABand & 0x7f) == + Country_Region_ChDesc_5GHZ[i].RegionIndex) + { + pChDesc = Country_Region_ChDesc_5GHZ[i].pChDesc; + num = TotalChNum(pChDesc); + bRegionFound = TRUE; + + break; + } + } + + if (!bRegionFound) + { + DBGPRINT(RT_DEBUG_ERROR,("CountryRegionABand=%d not support", pAd->CommonCfg.CountryRegionForABand)); + return; + } + + if (num > 0) + { + UCHAR RadarCh[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]; + /* TODO: shiang-7603, NdisMoveMemory may replace the + * pAd->ChannelList[index+i].Channel as other values! + */ + pAd->ChannelList[index+i].Channel = pChannelList[i]; + +#ifdef DOT11_N_SUPPORT + if (N_ChannelGroupCheck(pAd, pAd->ChannelList[index + i].Channel)) + pAd->ChannelList[index + i].Flags |= CHANNEL_40M_CAP; +#ifdef DOT11_VHT_AC + if (vht80_channel_group(pAd, pAd->ChannelList[index + i].Channel)) + pAd->ChannelList[index + i].Flags |= CHANNEL_80M_CAP; +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + + for (j=0; j<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,("CountryCode(2.4G/5G)=%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 DBG + DBGPRINT(RT_DEBUG_TRACE, ("SupportedChannelList:\n")); + for (i=0; iChannelListNum; i++) + { + DBGPRINT_RAW(RT_DEBUG_TRACE,("\tChannel # %d: Pwr0/1 = %d/%d, Flags = %x\n ", + pAd->ChannelList[i].Channel, + pAd->ChannelList[i].Power, + pAd->ChannelList[i].Power2, + pAd->ChannelList[i].Flags)); + } +#endif +} + + +#ifdef P2P_CHANNEL_LIST_SEPARATE +VOID P2PBuildChannelList( + IN PRTMP_ADAPTER pAd) +{ + UCHAR i, index=0, num=0; + PCH_DESC pChDesc = NULL; + BOOLEAN bRegionFound = FALSE; + PCFG80211_CTRL pCfg80211_Ctrl = &pAd->cfg80211_ctrl; + + NdisZeroMemory(pCfg80211_Ctrl->ChannelList, MAX_NUM_OF_CHANNELS * sizeof(CHANNEL_TX_POWER)); + + /* if not 11a-only mode, channel list starts from 2.4Ghz band*/ + if (WMODE_CAP_2G(pAd->CommonCfg.PhyMode)) + { + for (i = 0; i < Country_Region_GroupNum_2GHZ; i++) + { + if ((pCfg80211_Ctrl->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,("%s::P2PCountryRegion=%d not support", __FUNCTION__, pCfg80211_Ctrl->CountryRegion)); + return; + } + + if (num > 0) + { + for (i = 0; i < num; i++) + { + pCfg80211_Ctrl->ChannelList[i].Channel = GetChannel_2GHZ(pChDesc, i); + pCfg80211_Ctrl->ChannelList[i].Flags = GetChannelFlag(pChDesc, i); + } + + index += num; + } + num = 0; + } + + if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + { + for (i = 0; i < Country_Region_GroupNum_5GHZ; i++) + { + if ((pCfg80211_Ctrl->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,("%s::P2PCountryRegionForABand=%d not support", __FUNCTION__, pCfg80211_Ctrl->CountryRegionForABand)); + return; + } + + if (num > 0) + { + for (i = 0; i < num; i++) + { + pCfg80211_Ctrl->ChannelList[index + i].Channel = GetChannel_5GHZ(pChDesc, i); + pCfg80211_Ctrl->ChannelList[index + i].Flags = GetChannelFlag(pChDesc, i); + } + + index += num; + } + } + + pCfg80211_Ctrl->ChannelListNum = index; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::Channel list nubmer = %d\n", __FUNCTION__, pCfg80211_Ctrl->ChannelListNum)); +} +#endif /* P2P_CHANNEL_LIST_SEPARATE */ + + + +/* + ========================================================================== + Description: + This routine return the first channel number according to the country + code selection and RF IC selection (signal band or dual band). It is called + whenever driver need to start a site survey of all supported channels. + Return: + ch - the first channel number of current country code setting + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +UCHAR FirstChannel(RTMP_ADAPTER *pAd) +{ + return pAd->ChannelList[0].Channel; +} + + +/* + ========================================================================== + Description: + This routine returns the next channel number. This routine is called + during driver need to start a site survey of all supported channels. + Return: + next_channel - the next channel number valid in current country code setting. + Note: + return 0 if no more next channel + ========================================================================== + */ +UCHAR NextChannel(RTMP_ADAPTER *pAd, UCHAR channel) +{ + int i; + UCHAR next_channel = 0; + +#ifdef P2P_CHANNEL_LIST_SEPARATE + PCFG80211_CTRL pCfg80211_Ctrl = &pAd->cfg80211_ctrl; +#endif /* P2P_CHANNEL_LIST_SEPARATE */ + +#ifdef P2P_CHANNEL_LIST_SEPARATE + if ((pAd->ScanCtrl.ScanType == SCAN_P2P)) + { + for (i = 0; i < (pCfg80211_Ctrl->ChannelListNum - 1); i++) + { + if (channel == pCfg80211_Ctrl->ChannelList[i].Channel) + { + next_channel = pCfg80211_Ctrl->ChannelList[i+1].Channel; + return next_channel; + } + } + } +#endif /* P2P_CHANNEL_LIST_SEPARATE */ + + + + + 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->ScanCtrl.ScanType == SCAN_2040_BSS_COEXIST) && (pAd->ChannelList[i+1].Channel >14)) + { + channel = pAd->ChannelList[i+1].Channel; + continue; + } + else +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + { + /* Record this channel's idx in ChannelList array.*/ + next_channel = pAd->ChannelList[i+1].Channel; + break; + } + } + } + return next_channel; +} + +/* + ========================================================================== + Description: + + Return: + scan_channel - channel to scan. + Note: + return 0 if no more next channel + ========================================================================== + */ +UCHAR RTMPFindScanChannel( + IN PRTMP_ADAPTER pAd, + UINT8 LastScanChannel) +{ + UCHAR scan_channel = 0; +#ifdef CONFIG_AP_SUPPORT +#ifdef AP_PARTIAL_SCAN_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (pAd->ApCfg.bPartialScanning == TRUE) + { + scan_channel = FindPartialScanChannel(pAd); + return scan_channel; + } + } +#endif /* AP_PARTIAL_SCAN_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + if (LastScanChannel == 0) + scan_channel = FirstChannel(pAd); + else + scan_channel = NextChannel(pAd, LastScanChannel); + + return scan_channel; +} + +/* + ========================================================================== + Description: + This routine is for Cisco Compatible Extensions 2.X + Spec31. AP Control of Client Transmit Power + Return: + None + Note: + Required by Aironet dBm(mW) + 0dBm(1mW), 1dBm(5mW), 13dBm(20mW), 15dBm(30mW), + 17dBm(50mw), 20dBm(100mW) + + We supported + 3dBm(Lowest), 6dBm(10%), 9dBm(25%), 12dBm(50%), + 14dBm(75%), 15dBm(100%) + + The client station's actual transmit power shall be within +/- 5dB of + the minimum value or next lower value. + ========================================================================== + */ +VOID ChangeToCellPowerLimit(RTMP_ADAPTER *pAd, UCHAR AironetCellPowerLimit) +{ + /* + valud 0xFF means that hasn't found power limit information + from the AP's Beacon/Probe response + */ + if (AironetCellPowerLimit == 0xFF) + return; + + if (AironetCellPowerLimit < 6) /*Used Lowest Power Percentage.*/ + pAd->CommonCfg.TxPowerPercentage = 6; + else if (AironetCellPowerLimit < 9) + pAd->CommonCfg.TxPowerPercentage = 10; + else if (AironetCellPowerLimit < 12) + pAd->CommonCfg.TxPowerPercentage = 25; + else if (AironetCellPowerLimit < 14) + pAd->CommonCfg.TxPowerPercentage = 50; + else if (AironetCellPowerLimit < 15) + pAd->CommonCfg.TxPowerPercentage = 75; + else + pAd->CommonCfg.TxPowerPercentage = 100; /*else used maximum*/ + + if (pAd->CommonCfg.TxPowerPercentage > pAd->CommonCfg.TxPowerDefault) + pAd->CommonCfg.TxPowerPercentage = pAd->CommonCfg.TxPowerDefault; + +} + + +CHAR ConvertToRssi(RTMP_ADAPTER *pAd, struct raw_rssi_info *rssi_info, UCHAR rssi_idx) +{ + UCHAR RssiOffset, LNAGain; + CHAR BaseVal; + CHAR rssi; + + /* Rssi equals to zero or rssi_idx larger than 3 should be an invalid value*/ + if (rssi_idx >= 3) + return -99; + + rssi = rssi_info->raw_rssi[rssi_idx]; + + if (rssi == 0) + return -99; + + LNAGain = pAd->hw_cfg.lan_gain; + + if (pAd->LatchRfRegs.Channel > 14) + RssiOffset = pAd->ARssiOffset[rssi_idx]; + else + RssiOffset = pAd->BGRssiOffset[rssi_idx]; + + BaseVal = -12; + +#if defined (MT7603) || defined (MT7628) + if (IS_MT7603(pAd) || IS_MT7628(pAd)) + return (rssi + (CHAR)RssiOffset - (CHAR)LNAGain); +#endif + + + return (BaseVal - RssiOffset - LNAGain - rssi); +} + + +CHAR ConvertToSnr(RTMP_ADAPTER *pAd, UCHAR Snr) +{ + if (pAd->chipCap.SnrFormula == SNR_FORMULA2) + return (Snr * 3 + 8) >> 4; + else if (pAd->chipCap.SnrFormula == SNR_FORMULA3) + return (Snr * 3 / 16 ); /* * 0.1881 */ + else + return ((0xeb - Snr) * 3) / 16 ; +} + + + + +#ifdef CONFIG_AP_SUPPORT +#ifdef DOT11_N_SUPPORT +extern int DetectOverlappingPeriodicRound; + +VOID Handle_BSS_Width_Trigger_Events(RTMP_ADAPTER *pAd) +{ + ULONG Now32; +#ifdef WH_EZ_SETUP + UCHAR i; +#endif +#ifdef DOT11N_DRAFT3 + if (pAd->CommonCfg.bBssCoexEnable == FALSE) + return; +#endif /* DOT11N_DRAFT3 */ + + 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; +#ifdef WH_EZ_SETUP + for(i=0;iwdev_list[i]; + if(!wdev /*|| (wdev->channel != pAd->CommonCfg.Channel)*/) // Arvind : assume only one wdev + continue; + +#if defined(EZ_NETWORK_MERGE_SUPPORT) + if (IS_EZ_SETUP_ENABLED(wdev) && (wdev->wdev_type == WDEV_TYPE_AP)){ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("\nHandle_BSS_Width_Trigger_Events: do fallback ****\n")); + ez_set_ap_fallback_context(wdev,TRUE, pAd->CommonCfg.Channel); + } +#endif /* WH_EZ_SETUP */ + + } +#endif /* WH_EZ_SETUP */ + + DetectOverlappingPeriodicRound = 31; + } +} +#endif /* DOT11_N_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_tkip.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_tkip.c new file mode 100644 index 000000000..243a67dbf --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_tkip.c @@ -0,0 +1,929 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + cmm_tkip.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Wu 02-25-02 Initial +*/ + +#include "rt_config.h" + +/* Rotation functions on 32 bit values */ +#define ROL32( A, n ) \ + ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) ) +#define ROR32( A, n ) ROL32( (A), 32-(n) ) + +UINT Tkip_Sbox_Lower[256] = +{ + 0xA5,0x84,0x99,0x8D,0x0D,0xBD,0xB1,0x54, + 0x50,0x03,0xA9,0x7D,0x19,0x62,0xE6,0x9A, + 0x45,0x9D,0x40,0x87,0x15,0xEB,0xC9,0x0B, + 0xEC,0x67,0xFD,0xEA,0xBF,0xF7,0x96,0x5B, + 0xC2,0x1C,0xAE,0x6A,0x5A,0x41,0x02,0x4F, + 0x5C,0xF4,0x34,0x08,0x93,0x73,0x53,0x3F, + 0x0C,0x52,0x65,0x5E,0x28,0xA1,0x0F,0xB5, + 0x09,0x36,0x9B,0x3D,0x26,0x69,0xCD,0x9F, + 0x1B,0x9E,0x74,0x2E,0x2D,0xB2,0xEE,0xFB, + 0xF6,0x4D,0x61,0xCE,0x7B,0x3E,0x71,0x97, + 0xF5,0x68,0x00,0x2C,0x60,0x1F,0xC8,0xED, + 0xBE,0x46,0xD9,0x4B,0xDE,0xD4,0xE8,0x4A, + 0x6B,0x2A,0xE5,0x16,0xC5,0xD7,0x55,0x94, + 0xCF,0x10,0x06,0x81,0xF0,0x44,0xBA,0xE3, + 0xF3,0xFE,0xC0,0x8A,0xAD,0xBC,0x48,0x04, + 0xDF,0xC1,0x75,0x63,0x30,0x1A,0x0E,0x6D, + 0x4C,0x14,0x35,0x2F,0xE1,0xA2,0xCC,0x39, + 0x57,0xF2,0x82,0x47,0xAC,0xE7,0x2B,0x95, + 0xA0,0x98,0xD1,0x7F,0x66,0x7E,0xAB,0x83, + 0xCA,0x29,0xD3,0x3C,0x79,0xE2,0x1D,0x76, + 0x3B,0x56,0x4E,0x1E,0xDB,0x0A,0x6C,0xE4, + 0x5D,0x6E,0xEF,0xA6,0xA8,0xA4,0x37,0x8B, + 0x32,0x43,0x59,0xB7,0x8C,0x64,0xD2,0xE0, + 0xB4,0xFA,0x07,0x25,0xAF,0x8E,0xE9,0x18, + 0xD5,0x88,0x6F,0x72,0x24,0xF1,0xC7,0x51, + 0x23,0x7C,0x9C,0x21,0xDD,0xDC,0x86,0x85, + 0x90,0x42,0xC4,0xAA,0xD8,0x05,0x01,0x12, + 0xA3,0x5F,0xF9,0xD0,0x91,0x58,0x27,0xB9, + 0x38,0x13,0xB3,0x33,0xBB,0x70,0x89,0xA7, + 0xB6,0x22,0x92,0x20,0x49,0xFF,0x78,0x7A, + 0x8F,0xF8,0x80,0x17,0xDA,0x31,0xC6,0xB8, + 0xC3,0xB0,0x77,0x11,0xCB,0xFC,0xD6,0x3A +}; + +UINT Tkip_Sbox_Upper[256] = +{ + 0xC6,0xF8,0xEE,0xF6,0xFF,0xD6,0xDE,0x91, + 0x60,0x02,0xCE,0x56,0xE7,0xB5,0x4D,0xEC, + 0x8F,0x1F,0x89,0xFA,0xEF,0xB2,0x8E,0xFB, + 0x41,0xB3,0x5F,0x45,0x23,0x53,0xE4,0x9B, + 0x75,0xE1,0x3D,0x4C,0x6C,0x7E,0xF5,0x83, + 0x68,0x51,0xD1,0xF9,0xE2,0xAB,0x62,0x2A, + 0x08,0x95,0x46,0x9D,0x30,0x37,0x0A,0x2F, + 0x0E,0x24,0x1B,0xDF,0xCD,0x4E,0x7F,0xEA, + 0x12,0x1D,0x58,0x34,0x36,0xDC,0xB4,0x5B, + 0xA4,0x76,0xB7,0x7D,0x52,0xDD,0x5E,0x13, + 0xA6,0xB9,0x00,0xC1,0x40,0xE3,0x79,0xB6, + 0xD4,0x8D,0x67,0x72,0x94,0x98,0xB0,0x85, + 0xBB,0xC5,0x4F,0xED,0x86,0x9A,0x66,0x11, + 0x8A,0xE9,0x04,0xFE,0xA0,0x78,0x25,0x4B, + 0xA2,0x5D,0x80,0x05,0x3F,0x21,0x70,0xF1, + 0x63,0x77,0xAF,0x42,0x20,0xE5,0xFD,0xBF, + 0x81,0x18,0x26,0xC3,0xBE,0x35,0x88,0x2E, + 0x93,0x55,0xFC,0x7A,0xC8,0xBA,0x32,0xE6, + 0xC0,0x19,0x9E,0xA3,0x44,0x54,0x3B,0x0B, + 0x8C,0xC7,0x6B,0x28,0xA7,0xBC,0x16,0xAD, + 0xDB,0x64,0x74,0x14,0x92,0x0C,0x48,0xB8, + 0x9F,0xBD,0x43,0xC4,0x39,0x31,0xD3,0xF2, + 0xD5,0x8B,0x6E,0xDA,0x01,0xB1,0x9C,0x49, + 0xD8,0xAC,0xF3,0xCF,0xCA,0xF4,0x47,0x10, + 0x6F,0xF0,0x4A,0x5C,0x38,0x57,0x73,0x97, + 0xCB,0xA1,0xE8,0x3E,0x96,0x61,0x0D,0x0F, + 0xE0,0x7C,0x71,0xCC,0x90,0x06,0xF7,0x1C, + 0xC2,0x6A,0xAE,0x69,0x17,0x99,0x3A,0x27, + 0xD9,0xEB,0x2B,0x22,0xD2,0xA9,0x07,0x33, + 0x2D,0x3C,0x15,0xC9,0x87,0xAA,0x50,0xA5, + 0x03,0x59,0x09,0x1A,0x65,0xD7,0x84,0xD0, + 0x82,0x29,0x5A,0x1E,0x7B,0xA8,0x6D,0x2C +}; + + +/* Expanded IV for TKIP function.*/ + +typedef struct GNU_PACKED _IV_CONTROL_ +{ + union GNU_PACKED + { + struct GNU_PACKED + { + UCHAR rc0; + UCHAR rc1; + UCHAR rc2; + + union GNU_PACKED + { + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UCHAR KeyID:2; + UCHAR ExtIV:1; + UCHAR Rsvd:5; +#else + UCHAR Rsvd:5; + UCHAR ExtIV:1; + UCHAR KeyID:2; +#endif + } field; + UCHAR Byte; + } CONTROL; + } field; + + ULONG word; + } IV16; + + ULONG IV32; +} TKIP_IV, *PTKIP_IV; + + +/* + ======================================================================== + + Routine Description: + Convert from UCHAR[] to ULONG in a portable way + + Arguments: + pMICKey pointer to MIC Key + + Return Value: + None + + Note: + + ======================================================================== +*/ +ULONG RTMPTkipGetUInt32( + IN PUCHAR pMICKey) +{ + ULONG res = 0; + INT i; + + for (i = 0; i < 4; i++) + { + res |= (*pMICKey++) << (8 * i); + } + + return res; +} + +/* + ======================================================================== + + Routine Description: + Convert from ULONG to UCHAR[] in a portable way + + Arguments: + pDst pointer to destination for convert ULONG to UCHAR[] + val the value for convert + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPTkipPutUInt32( + IN OUT PUCHAR pDst, + IN ULONG val) +{ + INT i; + + for(i = 0; i < 4; i++) + { + *pDst++ = (UCHAR) (val & 0xff); + val >>= 8; + } +} + +/* + ======================================================================== + + Routine Description: + Set the MIC Key. + + Arguments: + pAd Pointer to our adapter + pMICKey pointer to MIC Key + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPTkipSetMICKey( + IN PTKIP_KEY_INFO pTkip, + IN PUCHAR pMICKey) +{ + /* Set the key */ + pTkip->K0 = RTMPTkipGetUInt32(pMICKey); + pTkip->K1 = RTMPTkipGetUInt32(pMICKey + 4); + /* and reset the message */ + pTkip->L = pTkip->K0; + pTkip->R = pTkip->K1; + pTkip->nBytesInM = 0; + pTkip->M = 0; +} + +/* + ======================================================================== + + Routine Description: + Calculate the MIC Value. + + Arguments: + pAd Pointer to our adapter + uChar Append this uChar + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPTkipAppendByte( + IN PTKIP_KEY_INFO pTkip, + IN UCHAR uChar) +{ + /* Append the byte to our word-sized buffer */ + pTkip->M |= (uChar << (8* pTkip->nBytesInM)); + pTkip->nBytesInM++; + /* Process the word if it is full. */ + if( pTkip->nBytesInM >= 4 ) + { + pTkip->L ^= pTkip->M; + pTkip->R ^= ROL32( pTkip->L, 17 ); + pTkip->L += pTkip->R; + pTkip->R ^= ((pTkip->L & 0xff00ff00) >> 8) | ((pTkip->L & 0x00ff00ff) << 8); + pTkip->L += pTkip->R; + pTkip->R ^= ROL32( pTkip->L, 3 ); + pTkip->L += pTkip->R; + pTkip->R ^= ROR32( pTkip->L, 2 ); + pTkip->L += pTkip->R; + /* Clear the buffer */ + pTkip->M = 0; + pTkip->nBytesInM = 0; + } +} + +/* + ======================================================================== + + Routine Description: + Calculate the MIC Value. + + Arguments: + pAd Pointer to our adapter + pSrc Pointer to source data for Calculate MIC Value + Len Indicate the length of the source data + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPTkipAppend( + IN PTKIP_KEY_INFO pTkip, + IN PUCHAR pSrc, + IN UINT nBytes) +{ + /* This is simple */ + while(nBytes > 0) + { + RTMPTkipAppendByte(pTkip, *pSrc++); + nBytes--; + } +} + +/* + ======================================================================== + + Routine Description: + Get the MIC Value. + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + the MIC Value is store in pAd->PrivateInfo.MIC + ======================================================================== +*/ +VOID RTMPTkipGetMIC( + IN PTKIP_KEY_INFO pTkip) +{ + /* Append the minimum padding*/ + RTMPTkipAppendByte(pTkip, 0x5a ); + RTMPTkipAppendByte(pTkip, 0 ); + RTMPTkipAppendByte(pTkip, 0 ); + RTMPTkipAppendByte(pTkip, 0 ); + RTMPTkipAppendByte(pTkip, 0 ); + /* and then zeroes until the length is a multiple of 4 */ + while( pTkip->nBytesInM != 0 ) + { + RTMPTkipAppendByte(pTkip, 0 ); + } + /* The appendByte function has already computed the result. */ + RTMPTkipPutUInt32(pTkip->MIC, pTkip->L); + RTMPTkipPutUInt32(pTkip->MIC + 4, pTkip->R); +} + + +/* + ======================================================================== + + Routine Description: + Init MIC Value calculation function which include set MIC key & + calculate first 16 bytes (DA + SA + priority + 0) + + Arguments: + pAd Pointer to our adapter + pTKey Pointer to the Temporal Key (TK), TK shall be 128bits. + pDA Pointer to DA address + pSA Pointer to SA address + pMICKey pointer to MIC Key + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID RTMPInitMICEngine( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKey, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN UCHAR UserPriority, + IN PUCHAR pMICKey) +{ + ULONG Priority = UserPriority; + + /* Init MIC value calculation*/ + RTMPTkipSetMICKey(&pAd->PrivateInfo.Tx, pMICKey); + /* DA*/ + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pDA, MAC_ADDR_LEN); + /* SA*/ + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSA, MAC_ADDR_LEN); + /* Priority + 3 bytes of 0*/ + RTMPTkipAppend(&pAd->PrivateInfo.Tx, (PUCHAR)&Priority, 4); +} + +/* + ======================================================================== + + Routine Description: + Compare MIC value of received MSDU + + Arguments: + pAd Pointer to our adapter + pSrc Pointer to the received Plain text data + pDA Pointer to DA address + pSA Pointer to SA address + pMICKey pointer to MIC Key + Len the length of the received plain text data exclude MIC value + + Return Value: + TRUE MIC value matched + FALSE MIC value mismatched + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +BOOLEAN RTMPTkipCompareMICValue( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSrc, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN PUCHAR pMICKey, + IN UCHAR UserPriority, + IN UINT Len) +{ + UCHAR OldMic[8]; + ULONG Priority = UserPriority; + + /* Init MIC value calculation*/ + RTMPTkipSetMICKey(&pAd->PrivateInfo.Rx, pMICKey); + /* DA*/ + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pDA, MAC_ADDR_LEN); + /* SA*/ + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSA, MAC_ADDR_LEN); + /* Priority + 3 bytes of 0*/ + RTMPTkipAppend(&pAd->PrivateInfo.Rx, (PUCHAR)&Priority, 4); + + /* Calculate MIC value from plain text data*/ + RTMPTkipAppend(&pAd->PrivateInfo.Rx, pSrc, Len); + + /* Get MIC valude from received frame*/ + NdisMoveMemory(OldMic, pSrc + Len, 8); + + /* Get MIC value from decrypted plain data*/ + RTMPTkipGetMIC(&pAd->PrivateInfo.Rx); + + /* Move MIC value from MSDU, this steps should move to data path.*/ + /* Since the MIC value might cross MPDUs.*/ + if(!NdisEqualMemory(pAd->PrivateInfo.Rx.MIC, OldMic, 8)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("RTMPTkipCompareMICValue(): TKIP MIC Error !\n")); /*MIC error.*/ + + + return (FALSE); + } + return (TRUE); +} + +/* + ======================================================================== + + Routine Description: + Copy frame from waiting queue into relative ring buffer and set + appropriate ASIC register to kick hardware transmit function + + Arguments: + pAd Pointer to our adapter + PNDIS_PACKET Pointer to Ndis Packet for MIC calculation + pEncap Pointer to LLC encap data + LenEncap Total encap length, might be 0 which indicates no encap + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPCalculateMICValue( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR pEncap, + IN PCIPHER_KEY pKey, + IN UCHAR apidx) +{ + PACKET_INFO PacketInfo; + PUCHAR pSrcBufVA; + UINT SrcBufLen; + PUCHAR pSrc; + UCHAR UserPriority; + UCHAR vlan_offset = 0; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + UserPriority = RTMP_GET_PACKET_UP(pPacket); + pSrc = pSrcBufVA; + + /* determine if this is a vlan packet */ + if (((*(pSrc + 12) << 8) + *(pSrc + 13)) == 0x8100) + vlan_offset = 4; + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + /* Start Calculate MIC Value*/ + if (apidx >= MIN_NET_DEVICE_FOR_APCLI && ((apidx - MIN_NET_DEVICE_FOR_APCLI) < MAX_APCLI_NUM) && (pAd->OpMode == OPMODE_AP)) + { /* For packet which need to do MATConvert, we need to use the CurrentAddress of specific ApCli interface.*/ + RTMPInitMICEngine( + pAd, + pKey->Key, + pSrc, + pAd->ApCfg.ApCliTab[apidx-MIN_NET_DEVICE_FOR_APCLI].wdev.if_addr, + UserPriority, + pKey->TxMic); + } + else +#endif /* APCLI_SUPPORT */ +#ifdef IGMP_SNOOP_SUPPORT + if ((RTMP_GET_PACKET_WCID(pPacket) != MCAST_WCID) && (*pSrc & 0x01) && (pAd->OpMode == OPMODE_AP)) + { + UCHAR wcid = RTMP_GET_PACKET_WCID(pPacket); + RTMPInitMICEngine( + pAd, + pKey->Key, + pAd->MacTab.Content[wcid].Addr, + pSrc + 6, + UserPriority, + pKey->TxMic); + } + else +#endif /* IGMP_SNOOP_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + { + RTMPInitMICEngine( + pAd, + pKey->Key, + pSrc, + pSrc + 6, + UserPriority, + pKey->TxMic); + } + + + if (pEncap != NULL) + { + /* LLC encapsulation*/ + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pEncap, 6); + /* Protocol Type*/ + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc + 12 + vlan_offset, 2); + } + SrcBufLen -= (14 + vlan_offset); + pSrc += (14 + vlan_offset); + do + { + if (SrcBufLen > 0) + { + RTMPTkipAppend(&pAd->PrivateInfo.Tx, pSrc, SrcBufLen); + } + + break; /* No need handle next packet */ + + } while (TRUE); + + /* Compute the final MIC Value*/ + RTMPTkipGetMIC(&pAd->PrivateInfo.Tx); +} + + +/************************************************************/ +/* tkip_sbox() */ +/* Returns a 16 bit value from a 64K entry table. The Table */ +/* is synthesized from two 256 entry byte wide tables. */ +/************************************************************/ + +UINT tkip_sbox(UINT index) +{ + UINT index_low; + UINT index_high; + UINT left, right; + + index_low = (index % 256); + index_high = ((index >> 8) % 256); + + left = Tkip_Sbox_Lower[index_low] + (Tkip_Sbox_Upper[index_low] * 256); + right = Tkip_Sbox_Upper[index_high] + (Tkip_Sbox_Lower[index_high] * 256); + + return (left ^ right); +} + +UINT rotr1(UINT a) +{ + unsigned int b; + + if ((a & 0x01) == 0x01) + { + b = (a >> 1) | 0x8000; + } + else + { + b = (a >> 1) & 0x7fff; + } + b = b % 65536; + return b; +} + +VOID RTMPTkipMixKey( + UCHAR *key, + UCHAR *ta, + ULONG pnl, /* Least significant 16 bits of PN */ + ULONG pnh, /* Most significant 32 bits of PN */ + UCHAR *rc4key, + UINT *p1k) +{ + + UINT tsc0; + UINT tsc1; + UINT tsc2; + + UINT ppk0; + UINT ppk1; + UINT ppk2; + UINT ppk3; + UINT ppk4; + UINT ppk5; + + INT i; + INT j; + + tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */ + tsc1 = (unsigned int)(pnh % 65536); + tsc2 = (unsigned int)(pnl % 65536); /* lsb */ + + /* Phase 1, step 1 */ + p1k[0] = tsc1; + p1k[1] = tsc0; + p1k[2] = (UINT)(ta[0] + (ta[1]*256)); + p1k[3] = (UINT)(ta[2] + (ta[3]*256)); + p1k[4] = (UINT)(ta[4] + (ta[5]*256)); + + /* Phase 1, step 2 */ + for (i=0; i<8; i++) + { + j = 2*(i & 1); + p1k[0] = (p1k[0] + tkip_sbox( (p1k[4] ^ ((256*key[1+j]) + key[j])) % 65536 )) % 65536; + p1k[1] = (p1k[1] + tkip_sbox( (p1k[0] ^ ((256*key[5+j]) + key[4+j])) % 65536 )) % 65536; + p1k[2] = (p1k[2] + tkip_sbox( (p1k[1] ^ ((256*key[9+j]) + key[8+j])) % 65536 )) % 65536; + p1k[3] = (p1k[3] + tkip_sbox( (p1k[2] ^ ((256*key[13+j]) + key[12+j])) % 65536 )) % 65536; + p1k[4] = (p1k[4] + tkip_sbox( (p1k[3] ^ (((256*key[1+j]) + key[j]))) % 65536 )) % 65536; + p1k[4] = (p1k[4] + i) % 65536; + } + + /* Phase 2, Step 1 */ + ppk0 = p1k[0]; + ppk1 = p1k[1]; + ppk2 = p1k[2]; + ppk3 = p1k[3]; + ppk4 = p1k[4]; + ppk5 = (p1k[4] + tsc2) % 65536; + + /* Phase2, Step 2 */ + ppk0 = ppk0 + tkip_sbox( (ppk5 ^ ((256*key[1]) + key[0])) % 65536); + ppk1 = ppk1 + tkip_sbox( (ppk0 ^ ((256*key[3]) + key[2])) % 65536); + ppk2 = ppk2 + tkip_sbox( (ppk1 ^ ((256*key[5]) + key[4])) % 65536); + ppk3 = ppk3 + tkip_sbox( (ppk2 ^ ((256*key[7]) + key[6])) % 65536); + ppk4 = ppk4 + tkip_sbox( (ppk3 ^ ((256*key[9]) + key[8])) % 65536); + ppk5 = ppk5 + tkip_sbox( (ppk4 ^ ((256*key[11]) + key[10])) % 65536); + + ppk0 = ppk0 + rotr1(ppk5 ^ ((256*key[13]) + key[12])); + ppk1 = ppk1 + rotr1(ppk0 ^ ((256*key[15]) + key[14])); + ppk2 = ppk2 + rotr1(ppk1); + ppk3 = ppk3 + rotr1(ppk2); + ppk4 = ppk4 + rotr1(ppk3); + ppk5 = ppk5 + rotr1(ppk4); + + /* Phase 2, Step 3 */ + /* Phase 2, Step 3 */ + + tsc0 = (unsigned int)((pnh >> 16) % 65536); /* msb */ + tsc1 = (unsigned int)(pnh % 65536); + tsc2 = (unsigned int)(pnl % 65536); /* lsb */ + + rc4key[0] = (tsc2 >> 8) % 256; + rc4key[1] = (((tsc2 >> 8) % 256) | 0x20) & 0x7f; + rc4key[2] = tsc2 % 256; + rc4key[3] = ((ppk5 ^ ((256*key[1]) + key[0])) >> 1) % 256; + + rc4key[4] = ppk0 % 256; + rc4key[5] = (ppk0 >> 8) % 256; + + rc4key[6] = ppk1 % 256; + rc4key[7] = (ppk1 >> 8) % 256; + + rc4key[8] = ppk2 % 256; + rc4key[9] = (ppk2 >> 8) % 256; + + rc4key[10] = ppk3 % 256; + rc4key[11] = (ppk3 >> 8) % 256; + + rc4key[12] = ppk4 % 256; + rc4key[13] = (ppk4 >> 8) % 256; + + rc4key[14] = ppk5 % 256; + rc4key[15] = (ppk5 >> 8) % 256; +} + + +/* + TRUE: Success! + FALSE: Decrypt Error! +*/ +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; + + /* skip payload length is zero*/ + if ((*DataByteCnt) <= LEN_TKIP_IV_HDR) + return FALSE; + + /* 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.*/ + 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/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_usb_io.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_usb_io.c new file mode 100644 index 000000000..cef63ea4d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_usb_io.c @@ -0,0 +1,1197 @@ +/* + *************************************************************************** + * 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: + cmm_usb_io.c +*/ +#include "rt_config.h" + +NTSTATUS RTUSBReadEEPROM(RTMP_ADAPTER *pAd, USHORT adr, UCHAR *buf, USHORT len) +{ + return RTUSB_VendorRequest(pAd, (USBD_TRANSFER_DIRECTION_IN | + USBD_SHORT_TRANSFER_OK), + DEVICE_VENDOR_REQUEST_IN, + 0x9, 0, adr, buf, len); +} + + +NTSTATUS RTUSBWriteEEPROM(RTMP_ADAPTER *pAd, USHORT adr, UCHAR *buf, USHORT len) +{ + return RTUSB_VendorRequest(pAd, USBD_TRANSFER_DIRECTION_OUT, + DEVICE_VENDOR_REQUEST_OUT, + 0x8, 0, adr, buf, len); +} + + +BOOLEAN RTUSBReadEEPROM16(RTMP_ADAPTER *pAd, USHORT offset, USHORT *pData) +{ + NTSTATUS status; + UINT16 localData; + BOOLEAN IsEmpty = 0; + + status = RTUSBReadEEPROM(pAd, offset, (PUCHAR)(&localData), 2); + if (status == STATUS_SUCCESS) + *pData = le2cpu16(localData); + + if ((*pData == 0xffff) || (*pData == 0x0000)) + IsEmpty = 1; + + return IsEmpty; +} + + +NTSTATUS RTUSBWriteEEPROM16(RTMP_ADAPTER *pAd, USHORT offset, USHORT value) +{ + USHORT tmpVal; + + tmpVal = cpu2le16(value); + return RTUSBWriteEEPROM(pAd, offset, (PUCHAR)&(tmpVal), 2); +} + +#define MAX_VENDOR_REQ_RETRY_COUNT 10 + +/* + ======================================================================== + Routine Description: + RTUSB_VendorRequest - Builds a ralink specific request, sends it off to USB endpoint zero and waits for completion + + Arguments: + @pAd: + @TransferFlags: + @RequestType: USB message request type value + @Request: USB message request value + @Value: USB message value + @Index: USB message index value + @TransferBuffer: USB data to be sent + @TransferBufferLength: Lengths in bytes of the data to be sent + + Context: ! in atomic context + + Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + + Note: + This function sends a simple control message to endpoint zero + and waits for the message to complete, or CONTROL_TIMEOUT_JIFFIES timeout. + Because it is synchronous transfer, so don't use this function within an atomic context, + otherwise system will hang, do be careful. + + TransferBuffer may located in stack region which may not in DMA'able region in some embedded platforms, + so need to copy TransferBuffer to UsbVendorReqBuf allocated by kmalloc to do DMA transfer. + Use UsbVendorReq_semaphore to protect this region which may be accessed by multi task. + Normally, coherent issue is resloved by low-level HC driver, so do not flush this zone by RTUSB_VendorRequest. + + ======================================================================== +*/ +NTSTATUS RTUSB_VendorRequest( + IN PRTMP_ADAPTER pAd, + IN UINT32 TransferFlags, + IN UCHAR RequestType, + IN UCHAR Request, + IN USHORT Value, + IN USHORT Index, + IN PVOID TransferBuffer, + IN UINT32 TransferBufferLength) +{ + int RET = 0; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + + if(in_interrupt()) + { + DBGPRINT(RT_DEBUG_ERROR, ("BUG: RTUSB_VendorRequest is called from invalid context ==> %d,%d,%d\n", Request, Value, Index)); + return NDIS_STATUS_FAILURE; + } + + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + /*DBGPRINT(RT_DEBUG_ERROR, ("WIFI device has been disconnected\n"));*/ + return NDIS_STATUS_FAILURE; + } + else if (RTMP_TEST_PSFLAG(pAd, fRTMP_PS_MCU_SLEEP)) + { + DBGPRINT(RT_DEBUG_ERROR, ("MCU has entered sleep mode\n")); + return NDIS_STATUS_FAILURE; + } + else + { + int RetryCount = 0; /* RTUSB_CONTROL_MSG retry counts*/ + ASSERT(TransferBufferLength UsbVendorReq_semaphore), RET); + if (RET != 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("UsbVendorReq_semaphore get failed\n")); + return NDIS_STATUS_FAILURE; + } + + if ((TransferBufferLength > 0) && ((RequestType == DEVICE_VENDOR_REQUEST_OUT) || (RequestType == DEVICE_CLASS_REQUEST_OUT))) + NdisMoveMemory(pAd->UsbVendorReqBuf, TransferBuffer, TransferBufferLength); + + do { + RTUSB_CONTROL_MSG(pObj->pUsb_Dev, 0, Request, RequestType, Value, + Index, pAd->UsbVendorReqBuf, TransferBufferLength, + CONTROL_TIMEOUT_JIFFIES, RET); + + if (RET < 0) { + DBGPRINT(RT_DEBUG_OFF, ("#\n")); + if (RET == RTMP_USB_CONTROL_MSG_ENODEV) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); + break; + } + RetryCount++; + RtmpusecDelay(5000); /* wait for 5ms*/ + } + } while((RET < 0) && (RetryCount < MAX_VENDOR_REQ_RETRY_COUNT)); + + if ( (!(RET < 0)) && (TransferBufferLength > 0) && (RequestType == DEVICE_VENDOR_REQUEST_IN)) + NdisMoveMemory(TransferBuffer, pAd->UsbVendorReqBuf, TransferBufferLength); + + RTMP_SEM_EVENT_UP(&(pAd->UsbVendorReq_semaphore)); + + if (RET < 0) { + DBGPRINT(RT_DEBUG_ERROR, ("RTUSB_VendorRequest failed(%d),TxFlags=0x%x, ReqType=%s, Req=0x%x, Idx=0x%x,pAd->Flags=0x%lx\n", + RET, TransferFlags, (RequestType == DEVICE_VENDOR_REQUEST_OUT ? "OUT" : "IN"), Request, Index, pAd->Flags)); + if (Request == 0x2) + DBGPRINT(RT_DEBUG_ERROR, ("\tRequest Value=0x%04x!\n", Value)); + + if ((!TransferBuffer) && (TransferBufferLength > 0)) + hex_dump("Failed TransferBuffer value", TransferBuffer, TransferBufferLength); + + if (RET == RTMP_USB_CONTROL_MSG_ENODEV) + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); + + } + + } + + if (RET < 0) + return NDIS_STATUS_FAILURE; + else + return NDIS_STATUS_SUCCESS; +} + +NDIS_STATUS RTUSBEnqueueCmdFromNdis( + IN PRTMP_ADAPTER pAd, + IN NDIS_OID Oid, + IN BOOLEAN SetInformation, + IN PVOID pInformationBuffer, + IN UINT32 InformationBufferLength) +{ + NDIS_STATUS status; + PCmdQElmt cmdqelmt = NULL; + RTMP_OS_TASK *pTask = &pAd->cmdQTask; + + + RTMP_OS_TASK_LEGALITY(pTask) + ; + else + return (NDIS_STATUS_RESOURCES); + + status = os_alloc_mem(pAd, (PUCHAR *)(&cmdqelmt), sizeof(CmdQElmt)); + if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt == NULL)) + return (NDIS_STATUS_RESOURCES); + + cmdqelmt->buffer = NULL; + if (pInformationBuffer != NULL) + { + status = os_alloc_mem(pAd, (PUCHAR *)&cmdqelmt->buffer, InformationBufferLength); + if ((status != NDIS_STATUS_SUCCESS) || (cmdqelmt->buffer == NULL)) + { + os_free_mem(NULL, cmdqelmt); + return (NDIS_STATUS_RESOURCES); + } + else + { + NdisMoveMemory(cmdqelmt->buffer, pInformationBuffer, InformationBufferLength); + cmdqelmt->bufferlength = InformationBufferLength; + } + } + else + cmdqelmt->bufferlength = 0; + + cmdqelmt->command = Oid; + cmdqelmt->CmdFromNdis = TRUE; + if (SetInformation == TRUE) + cmdqelmt->SetOperation = TRUE; + else + cmdqelmt->SetOperation = FALSE; + + 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); +} + +NTSTATUS CheckGPIOHdlr(RTMP_ADAPTER *pAd, PCmdQElmt CMDQelmt) +{ +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("The driver is in ATE mode now\n")); + return NDIS_STATUS_SUCCESS; + } +#endif /* CONFIG_ATE */ + + + return NDIS_STATUS_SUCCESS; +} + + +static NTSTATUS ResetBulkOutHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ +#ifndef MT_MAC + INT32 MACValue = 0; + UCHAR Index = 0; + int ret=0; + PHT_TX_CONTEXT pHTTXContext; + unsigned long IrqFlags; + + DBGPRINT(RT_DEBUG_TRACE, ("CMDTHREAD_RESET_BULK_OUT(ResetPipeid=0x%0x)===>\n", pAd->bulkResetPipeid)); + + /* All transfers must be aborted or cancelled before attempting to reset the pipe. */ + /*RTUSBCancelPendingBulkOutIRP(pAd);*/ + /* Wait 10ms to let previous packet that are already in HW FIFO to clear. by MAXLEE 12-25-2007*/ + do + { + if(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + break; + + RTMP_IO_READ32(pAd, TXRXQ_PCNT, &MACValue); + if ((MACValue & 0xf00000/*0x800000*/) == 0) + break; + + Index++; + RtmpusecDelay(10000); + }while(Index < 100); + + USB_CFG_READ(pAd, &MACValue); + + /* 2nd, to prevent Read Register error, we check the validity.*/ + if ((MACValue & 0xc00000) == 0) + USB_CFG_READ(pAd, &MACValue); + + /* 3rd, to prevent Read Register error, we check the validity.*/ + if ((MACValue & 0xc00000) == 0) + USB_CFG_READ(pAd, &MACValue); + + MACValue |= 0x80000; + USB_CFG_WRITE(pAd, MACValue); + + /* Wait 1ms to prevent next URB to bulkout before HW reset. by MAXLEE 12-25-2007*/ + RtmpusecDelay(1000); + + MACValue &= (~0x80000); + USB_CFG_WRITE(pAd, MACValue); + DBGPRINT(RT_DEBUG_TRACE, ("\tSet 0x2a0 bit19. Clear USB DMA TX path\n")); + + /* Wait 5ms to prevent next URB to bulkout before HW reset. by MAXLEE 12-25-2007*/ + /*RtmpusecDelay(5000);*/ + + if ((pAd->bulkResetPipeid & BULKOUT_MGMT_RESET_FLAG) == BULKOUT_MGMT_RESET_FLAG) + { + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); + + if (pAd->MgmtRing.TxSwFreeIdx < MGMT_RING_SIZE /* pMLMEContext->bWaitingBulkOut == TRUE */) + RTUSB_SET_BULK_FLAG(pAd, fRTUSB_BULK_OUT_MLME); + + RTUSBKickBulkOut(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("\tTX MGMT RECOVER Done!\n")); + } + else + { + pHTTXContext = &(pAd->TxContext[pAd->bulkResetPipeid]); + + /*NdisAcquireSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]);*/ + RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); + if ( pAd->BulkOutPending[pAd->bulkResetPipeid] == FALSE) + { + pAd->BulkOutPending[pAd->bulkResetPipeid] = TRUE; + pHTTXContext->IRPPending = TRUE; + pAd->watchDogTxPendingCnt[pAd->bulkResetPipeid] = 1; + + /* no matter what, clean the flag*/ + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); + + /*NdisReleaseSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]);*/ + RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); + +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + ret = ATEResetBulkOut(pAd); + else +#endif /* CONFIG_ATE */ + { + RTUSBInitHTTxDesc(pAd, pHTTXContext, pAd->bulkResetPipeid, + pHTTXContext->BulkOutSize, + RtmpUsbBulkOutDataPacketComplete); + + if ((ret = RTUSB_SUBMIT_URB(pHTTXContext->pUrb))!=0) + { + RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); + pAd->BulkOutPending[pAd->bulkResetPipeid] = FALSE; + pHTTXContext->IRPPending = FALSE; + pAd->watchDogTxPendingCnt[pAd->bulkResetPipeid] = 0; + RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); + + DBGPRINT(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_OUT:Submit Tx URB failed %d\n", ret)); + } + else + { + RTMP_INT_LOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); + + DBGPRINT(RT_DEBUG_TRACE,("\tCMDTHREAD_RESET_BULK_OUT: TxContext[%d]:CWPos=%ld, NBPos=%ld, ENBPos=%ld, bCopy=%d, pending=%d!\n", + pAd->bulkResetPipeid, pHTTXContext->CurWritePosition, pHTTXContext->NextBulkOutPosition, + pHTTXContext->ENextBulkOutPosition, pHTTXContext->bCopySavePad, + pAd->BulkOutPending[pAd->bulkResetPipeid])); + DBGPRINT(RT_DEBUG_TRACE,("\t\tBulkOut Req=0x%lx, Complete=0x%lx, Other=0x%lx\n", + pAd->BulkOutReq, pAd->BulkOutComplete, pAd->BulkOutCompleteOther)); + + RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); + + DBGPRINT(RT_DEBUG_TRACE, ("\tCMDTHREAD_RESET_BULK_OUT: Submit Tx DATA URB for failed BulkReq(0x%lx) Done, status=%d!\n", + pAd->bulkResetReq[pAd->bulkResetPipeid], + RTMP_USB_URB_STATUS_GET(pHTTXContext->pUrb))); + } + } + } + else + { + /*NdisReleaseSpinLock(&pAd->BulkOutLock[pAd->bulkResetPipeid]);*/ + /*RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags);*/ + + DBGPRINT(RT_DEBUG_ERROR, ("CmdThread : TX DATA RECOVER FAIL for BulkReq(0x%lx) because BulkOutPending[%d] is TRUE!\n", + pAd->bulkResetReq[pAd->bulkResetPipeid], pAd->bulkResetPipeid)); + + if (pAd->bulkResetPipeid == 0) + { + UCHAR pendingContext = 0; + PHT_TX_CONTEXT pHTTXContext = (PHT_TX_CONTEXT)(&pAd->TxContext[pAd->bulkResetPipeid ]); + PTX_CONTEXT pMLMEContext = (PTX_CONTEXT)(pAd->MgmtRing.Cell[pAd->MgmtRing.TxDmaIdx].AllocVa); + PTX_CONTEXT pNULLContext = (PTX_CONTEXT)(&pAd->PsPollContext); + PTX_CONTEXT pPsPollContext = (PTX_CONTEXT)(&pAd->NullContext); + + if (pHTTXContext->IRPPending) + pendingContext |= 1; + else if (pMLMEContext->IRPPending) + pendingContext |= 2; + else if (pNULLContext->IRPPending) + pendingContext |= 4; + else if (pPsPollContext->IRPPending) + pendingContext |= 8; + else + pendingContext = 0; + + DBGPRINT(RT_DEBUG_ERROR, ("\tTX Occupied by %d!\n", pendingContext)); + } + + /* no matter what, clean the flag*/ + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET); + + RTMP_INT_UNLOCK(&pAd->BulkOutLock[pAd->bulkResetPipeid], IrqFlags); + + RTUSB_SET_BULK_FLAG(pAd, (fRTUSB_BULK_OUT_DATA_NORMAL << pAd->bulkResetPipeid)); + } + + if (!(RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)))) + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, WCID_ALL, MAX_TX_PROCESS); + /*RTUSBKickBulkOut(pAd);*/ + } + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_OUT<===\n")); +#endif + + return NDIS_STATUS_SUCCESS; + + +} + + +/* All transfers must be aborted or cancelled before attempting to reset the pipe.*/ +static NTSTATUS ResetBulkInHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ +#ifndef MT_MAC + UINT32 MACValue; + NTSTATUS ntStatus; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_IN === >\n")); + + +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + ATEResetBulkIn(pAd); + else +#endif /* CONFIG_ATE */ + { + /*while ((atomic_read(&pAd->PendingRx) > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) */ + if((pAd->PendingRx > 0) && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("BulkIn IRP Pending!!!\n")); + RTUSBCancelPendingBulkInIRP(pAd); + RtmpusecDelay(100000); + pAd->PendingRx = 0; + } + } + + /* Wait 10ms before reading register.*/ + RtmpusecDelay(10000); + ntStatus = RTMP_IO_READ32(pAd, MAC_CSR0, &MACValue); + + /* It must be removed. Or ATE will have no RX success. */ + if ((NT_SUCCESS(ntStatus) == TRUE) && + (!(RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))))) + { + UCHAR i; + + if (RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_RADIO_OFF | + fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST))) + return NDIS_STATUS_SUCCESS; + + pAd->NextRxBulkInPosition = pAd->RxContext[pAd->NextRxBulkInIndex].BulkInOffset; + + DBGPRINT(RT_DEBUG_TRACE, ("BULK_IN_RESET: NBIIdx=0x%x,NBIRIdx=0x%x, BIRPos=0x%lx. BIReq=x%lx, BIComplete=0x%lx, BICFail0x%lx\n", + pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex, pAd->NextRxBulkInPosition, pAd->BulkInReq, pAd->BulkInComplete, pAd->BulkInCompleteFail)); + + for (i = 0; i < RX_RING_SIZE; i++) + { + DBGPRINT(RT_DEBUG_TRACE, ("\tRxContext[%d]: IRPPending=%d, InUse=%d, Readable=%d!\n" + , i, pAd->RxContext[i].IRPPending, pAd->RxContext[i].InUse, pAd->RxContext[i].Readable)); + } + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BULKIN_RESET); + + for (i = 0; i < pAd->CommonCfg.NumOfBulkInIRP; i++) + { + /*RTUSBBulkReceive(pAd);*/ + PRX_CONTEXT pRxContext; + PURB pUrb; + int ret = 0; + unsigned long IrqFlags; + + RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); + pRxContext = &(pAd->RxContext[pAd->NextRxBulkInIndex]); + + if ((pAd->PendingRx > 0) || (pRxContext->Readable == TRUE) || (pRxContext->InUse == TRUE)) + { + RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); + return NDIS_STATUS_SUCCESS; + } + + pRxContext->InUse = TRUE; + pRxContext->IRPPending = TRUE; + pAd->PendingRx++; + pAd->BulkInReq++; + RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); + + /* Init Rx context descriptor*/ + RTUSBInitRxDesc(pAd, pRxContext); + pUrb = pRxContext->pUrb; + if ((ret = RTUSB_SUBMIT_URB(pUrb))!=0) + { /* fail*/ + RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags); + pRxContext->InUse = FALSE; + pRxContext->IRPPending = FALSE; + pAd->PendingRx--; + pAd->BulkInReq--; + RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags); + DBGPRINT(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Submit Rx URB failed(%d), status=%d\n", ret, RTMP_USB_URB_STATUS_GET(pUrb))); + } + else + { /* success*/ + /*DBGPRINT(RT_DEBUG_TRACE, ("BIDone, Pend=%d,BIIdx=%d,BIRIdx=%d!\n", */ + /* pAd->PendingRx, pAd->NextRxBulkInIndex, pAd->NextRxBulkInReadIndex));*/ + DBGPRINT_RAW(RT_DEBUG_TRACE, ("CMDTHREAD_RESET_BULK_IN: Submit Rx URB Done, status=%d!\n", RTMP_USB_URB_STATUS_GET(pUrb))); + ASSERT((pRxContext->InUse == pRxContext->IRPPending)); + } + } + + } + else + { + /* Card must be removed*/ + if (NT_SUCCESS(ntStatus) != TRUE) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); + DBGPRINT_RAW(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Read Register Failed!Card must be removed!!\n\n")); + } + else + DBGPRINT_RAW(RT_DEBUG_ERROR, ("CMDTHREAD_RESET_BULK_IN: Cannot do bulk in because flags(0x%lx) on !\n", pAd->Flags)); + } + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_IN <===\n")); +#endif + + return NDIS_STATUS_SUCCESS; + +} + + +static NTSTATUS SetAsicWcidHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + RT_SET_ASIC_WCID SetAsicWcid; +#ifndef MT_MAC + USHORT offset; + UINT32 MACValue, MACRValue = 0; +#endif + + SetAsicWcid = *((PRT_SET_ASIC_WCID)(CMDQelmt->buffer)); + + if (SetAsicWcid.WCID >= MAX_LEN_OF_MAC_TABLE) + return NDIS_STATUS_FAILURE; + +#ifndef MT_MAC + if (pAd->chipCap.hif_type != HIF_MT) { + offset = MAC_WCID_BASE + ((UCHAR)SetAsicWcid.WCID)*HW_WCID_ENTRY_SIZE; + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_SET_ASIC_WCID : WCID = %ld, SetTid = %lx, DeleteTid = %lx.\n", + SetAsicWcid.WCID, SetAsicWcid.SetTid, SetAsicWcid.DeleteTid)); + + MACValue = (pAd->MacTab.Content[SetAsicWcid.WCID].Addr[3]<<24)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[2]<<16)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[1]<<8)+(pAd->MacTab.Content[SetAsicWcid.WCID].Addr[0]); + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("1-MACValue= %x,\n", MACValue)); + RTMP_IO_WRITE32(pAd, offset, MACValue); + /* Read bitmask*/ + RTMP_IO_READ32(pAd, offset+4, &MACRValue); + if ( SetAsicWcid.DeleteTid != 0xffffffff) + MACRValue &= (~SetAsicWcid.DeleteTid); + if (SetAsicWcid.SetTid != 0xffffffff) + MACRValue |= (SetAsicWcid.SetTid); + + MACRValue &= 0xffff0000; + MACValue = (pAd->MacTab.Content[SetAsicWcid.WCID].Addr[5]<<8)+pAd->MacTab.Content[SetAsicWcid.WCID].Addr[4]; + MACValue |= MACRValue; + RTMP_IO_WRITE32(pAd, offset+4, MACValue); + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("2-MACValue= %x,\n", MACValue)); + } else +#endif /* MT_MAC */ + { + DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_SET_ASIC_WCID : WCID = %ld, Tid = %x, SN = %d, BaSize = %d, IsAdd = %d, Ses_type = %d.\n", + SetAsicWcid.WCID, SetAsicWcid.Tid, SetAsicWcid.SN, SetAsicWcid.Basize, SetAsicWcid.IsAdd, SetAsicWcid.Ses_type)); + + AsicUpdateBASession(pAd, SetAsicWcid.WCID, SetAsicWcid.Tid, SetAsicWcid.SN, SetAsicWcid.Basize, SetAsicWcid.IsAdd, SetAsicWcid.Ses_type); + } + + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS DelAsicWcidHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + RT_SET_ASIC_WCID SetAsicWcid; + SetAsicWcid = *((PRT_SET_ASIC_WCID)(CMDQelmt->buffer)); + + if (SetAsicWcid.WCID >= MAX_LEN_OF_MAC_TABLE) + return NDIS_STATUS_FAILURE; + + AsicDelWcidTab(pAd, (UCHAR)SetAsicWcid.WCID); + + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS SetWcidSecInfoHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + PRT_ASIC_WCID_SEC_INFO pInfo; + + pInfo = (PRT_ASIC_WCID_SEC_INFO)CMDQelmt->buffer; + RTMPSetWcidSecurityInfo(pAd, + pInfo->BssIdx, + pInfo->KeyIdx, + pInfo->CipherAlg, + pInfo->Wcid, + pInfo->KeyTabFlag); + + return NDIS_STATUS_SUCCESS; +} + + +static NTSTATUS SetAsicWcidIVEIVHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + PRT_ASIC_WCID_IVEIV_ENTRY pInfo; + + pInfo = (PRT_ASIC_WCID_IVEIV_ENTRY)CMDQelmt->buffer; + AsicUpdateWCIDIVEIV(pAd, + pInfo->Wcid, + pInfo->Iv, + pInfo->Eiv); + + return NDIS_STATUS_SUCCESS; +} + + +static NTSTATUS SetAsicWcidAttrHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + PRT_ASIC_WCID_ATTR_ENTRY pInfo; + + pInfo = (PRT_ASIC_WCID_ATTR_ENTRY)CMDQelmt->buffer; + AsicUpdateWcidAttributeEntry(pAd, + pInfo->BssIdx, + pInfo->KeyIdx, + pInfo->CipherAlg, + pInfo->Wcid, + pInfo->KeyTabFlag); + + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS SETAsicSharedKeyHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + PRT_ASIC_SHARED_KEY pInfo; + + pInfo = (PRT_ASIC_SHARED_KEY)CMDQelmt->buffer; + AsicAddSharedKeyEntry(pAd, + pInfo->BssIndex, + pInfo->KeyIdx, + &pInfo->CipherKey); + + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS SetAsicPairwiseKeyHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + PRT_ASIC_PAIRWISE_KEY pInfo; + + pInfo = (PRT_ASIC_PAIRWISE_KEY)CMDQelmt->buffer; + AsicAddPairwiseKeyEntry(pAd, + pInfo->WCID, + &pInfo->CipherKey); + + return NDIS_STATUS_SUCCESS; +} + + + +static NTSTATUS RemovePairwiseKeyHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + UCHAR Wcid = *((PUCHAR)(CMDQelmt->buffer)); + + AsicRemovePairwiseKeyEntry(pAd, Wcid); + return NDIS_STATUS_SUCCESS; +} + + +static NTSTATUS SetClientMACEntryHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + PRT_SET_ASIC_WCID pInfo; + + pInfo = (PRT_SET_ASIC_WCID)CMDQelmt->buffer; + AsicUpdateRxWCIDTable(pAd, pInfo->WCID, pInfo->Addr); + return NDIS_STATUS_SUCCESS; +} + + +static NTSTATUS UpdateProtectHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + PRT_ASIC_PROTECT_INFO pAsicProtectInfo; + + pAsicProtectInfo = (PRT_ASIC_PROTECT_INFO)CMDQelmt->buffer; + AsicUpdateProtect(pAd, pAsicProtectInfo->OperationMode, pAsicProtectInfo->SetMask, + pAsicProtectInfo->bDisableBGProtect, pAsicProtectInfo->bNonGFExist); + + return NDIS_STATUS_SUCCESS; +} + + +#ifdef CONFIG_AP_SUPPORT +static NTSTATUS APUpdateCapabilityAndErpieHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + APUpdateCapabilityAndErpIe(pAd); + return NDIS_STATUS_SUCCESS; +} +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +static NTSTATUS _802_11_CounterMeasureHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + MAC_TABLE_ENTRY *pEntry; + + pEntry = (MAC_TABLE_ENTRY *)CMDQelmt->buffer; + HandleCounterMeasure(pAd, pEntry); + } + + return NDIS_STATUS_SUCCESS; +} +#endif /* CONFIG_AP_SUPPORT */ + + + + +#ifdef CONFIG_AP_SUPPORT +static NTSTATUS APEnableTXBurstHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::CMDTHREAD_AP_ENABLE_TX_BURST \n")); + + AsicSetWmmParam(pAd, WMM_PARAM_AC_0, WMM_PARAM_TXOP, 0x20); + } + + return NDIS_STATUS_SUCCESS; +} + + +static NTSTATUS APDisableTXBurstHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::CMDTHREAD_AP_DISABLE_TX_BURST \n")); + + AsicSetWmmParam(pAd, WMM_PARAM_AC_0, WMM_PARAM_TXOP, 0x00); + } + + return NDIS_STATUS_SUCCESS; +} + + +static NTSTATUS APAdjustEXPAckTimeHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::CMDTHREAD_AP_ADJUST_EXP_ACK_TIME \n")); + RTMP_IO_WRITE32(pAd, EXP_ACK_TIME, 0x005400ca); + } + + return NDIS_STATUS_SUCCESS; +} + + +static NTSTATUS APRecoverEXPAckTimeHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::CMDTHREAD_AP_RECOVER_EXP_ACK_TIME \n")); + RTMP_IO_WRITE32(pAd, EXP_ACK_TIME, 0x002400ca); + } + + return NDIS_STATUS_SUCCESS; +} +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef LED_CONTROL_SUPPORT +static NTSTATUS SetLEDStatusHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + UCHAR LEDStatus = *((PUCHAR)(CMDQelmt->buffer)); + + RTMPSetLEDStatus(pAd, LEDStatus); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: CMDTHREAD_SET_LED_STATUS (LEDStatus = %d)\n", + __FUNCTION__, LEDStatus)); + + return NDIS_STATUS_SUCCESS; +} +#endif /* LED_CONTROL_SUPPORT */ + +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT +/*WPS LED MODE 10*/ +static NTSTATUS LEDWPSMode10Hdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + UINT WPSLedMode10 = *((PUINT)(CMDQelmt->buffer)); + + DBGPRINT(RT_DEBUG_INFO, ("WPS LED mode 10::ON or Flash or OFF : %x\n", WPSLedMode10)); + + switch(WPSLedMode10) + { + case LINK_STATUS_WPS_MODE10_TURN_ON: + RTMPSetLEDStatus(pAd, LED_WPS_MODE10_TURN_ON); + break; + case LINK_STATUS_WPS_MODE10_FLASH: + RTMPSetLEDStatus(pAd,LED_WPS_MODE10_FLASH); + break; + case LINK_STATUS_WPS_MODE10_TURN_OFF: + RTMPSetLEDStatus(pAd, LED_WPS_MODE10_TURN_OFF); + break; + default: + DBGPRINT(RT_DEBUG_INFO, ("WPS LED mode 10:: No this status %d!!!\n", WPSLedMode10)); + break; + } + + return NDIS_STATUS_SUCCESS; +} +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ + + +#ifdef CONFIG_AP_SUPPORT +static NTSTATUS ChannelRescanHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + DBGPRINT(RT_DEBUG_TRACE, ("cmd> Re-scan channel! \n")); + + pAd->CommonCfg.Channel = AP_AUTO_CH_SEL(pAd, TRUE); +#ifdef DOT11_N_SUPPORT + /* If WMODE_CAP_N(phymode) and BW=40 check extension channel, after select channel */ + N_ChannelCheck(pAd); +#endif /* DOT11_N_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("cmd> Switch to %d! \n", pAd->CommonCfg.Channel)); + APStop(pAd); + APStartUp(pAd); + +#ifdef AP_QLOAD_SUPPORT + QBSS_LoadAlarmResume(pAd); +#endif /* AP_QLOAD_SUPPORT */ + + return NDIS_STATUS_SUCCESS; +} +#endif /* CONFIG_AP_SUPPORT*/ + + +#ifdef LINUX +#endif /* LINUX */ + + + +#ifdef STREAM_MODE_SUPPORT +static NTSTATUS UpdateTXChainAddress(RTMP_ADAPTER *pAd, IN PCmdQElmt CMDQelmt) +{ + AsicUpdateTxChainAddress(pAd, CMDQelmt->buffer); + return NDIS_STATUS_SUCCESS; +} +#endif /* STREAM_MODE_SUPPORT */ + + +#ifdef MT_MAC +static NTSTATUS AddRemoveKeyHdlr(RTMP_ADAPTER *pAd, IN PCmdQElmt CMDQelmt) +{ + PMT_ASIC_SEC_INFO pInfo; + + pInfo = (PMT_ASIC_SEC_INFO)CMDQelmt->buffer; + + CmdProcAddRemoveKey(pAd, pInfo->AddRemove, pInfo->BssIdx, pInfo->KeyIdx, pInfo->Wcid, pInfo->KeyTabFlag, &pInfo->CipherKey, pInfo->Addr); + return NDIS_STATUS_SUCCESS; +} +#endif /* MT_MAC */ + +#ifdef MT_PS +static NTSTATUS MtCmdPsClearReqHdlr(RTMP_ADAPTER *pAd, IN PCmdQElmt CMDQelmt) +{ + UINT32 wlanidx = 0; + + NdisMoveMemory(&wlanidx , CMDQelmt->buffer, sizeof(UINT32)); + DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("wcid=0x%x, Send Ps Clear CMD to MCU\n", wlanidx)); + CmdPsClearReq(pAd, wlanidx, TRUE); + + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS MtCmdPsRetrieveStartReqHdlr(RTMP_ADAPTER *pAd, IN PCmdQElmt CMDQelmt) +{ + MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY *)(CMDQelmt->buffer); + + DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("wcid=%d CmdPsRetrieveStartReq CMD to MCU\n", pEntry->wcid)); + CmdPsRetrieveStartReq(pAd, pEntry->wcid); + + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS MtCmdPsRetrieveRspHdlr(RTMP_ADAPTER *pAd, IN PCmdQElmt CMDQelmt) +{ + AndesPsRetrieveStartRsp(pAd, CMDQelmt->buffer, CMDQelmt->bufferlength); + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS MtCmdPsSetIgnorePsm(RTMP_ADAPTER *pAd, IN PCmdQElmt CMDQelmt) +{ + UCHAR bVal; + MAC_TABLE_ENTRY *pEntry = NULL; + + os_alloc_mem(NULL, (UCHAR **) &pEntry, sizeof(MAC_TABLE_ENTRY)); + if (pEntry) + { + NdisMoveMemory(&bVal , CMDQelmt->buffer, sizeof(UCHAR)); + NdisMoveMemory(pEntry , CMDQelmt->buffer+1, sizeof(MAC_TABLE_ENTRY)); + MtSetIgnorePsm(pAd, pEntry, bVal); + os_free_mem(NULL, pEntry); + } + return NDIS_STATUS_SUCCESS; +} +#endif /* MT_PS */ +#ifdef CFG_TDLS_SUPPORT + +static NTSTATUS CFGTdlsSendCHSWSetupHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS CFGTdlsAutoTeardownHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY *)(CMDQelmt->buffer); + cfg_tdls_auto_teardown(pAd, pEntry->Addr); + return NDIS_STATUS_SUCCESS; +} + +#endif /* CFG_TDLS_SUPPORT */ + +#ifdef BCN_OFFLOAD_SUPPORT +static NTSTATUS HwCtrlBcnUpdate(RTMP_ADAPTER *pAd, PCmdQElmt CMDQelmt) +{ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + ULONG UpTime; + + /* update channel utilization */ + NdisGetSystemUpTime(&UpTime); + +#ifdef AP_QLOAD_SUPPORT + QBSS_LoadUpdate(pAd, UpTime); +#endif /* AP_QLOAD_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT + RRM_QuietUpdata(pAd); +#endif /* DOT11K_RRM_SUPPORT */ + + APUpdateAllBeaconFrame(pAd); + } +#endif /* CONFIG_AP_SUPPORT */ + + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS HwCtrlBmcCntUpdate(RTMP_ADAPTER *pAd, PCmdQElmt CMDQelmt) +{ + CHAR *pfunc_idx, idx = 0; + pfunc_idx = (CHAR *)CMDQelmt->buffer; + + idx = *pfunc_idx; + + /* BMC start */ + if (AsicSetBmcQCR(pAd, BMC_CNT_UPDATE, CR_WRITE, idx, NULL) + == FALSE) + { + return NDIS_STATUS_FAILURE; + } + return NDIS_STATUS_SUCCESS; +} +#endif /* BCN_OFFLOAD_SUPPORT */ + + +typedef NTSTATUS (*CMDHdlr)(RTMP_ADAPTER *pAd, IN PCmdQElmt CMDQelmt); + +static CMDHdlr CMDHdlrTable[] = { + ResetBulkOutHdlr, /* CMDTHREAD_RESET_BULK_OUT*/ + ResetBulkInHdlr, /* CMDTHREAD_RESET_BULK_IN*/ + CheckGPIOHdlr, /* CMDTHREAD_CHECK_GPIO */ + SetAsicWcidHdlr, /* CMDTHREAD_SET_ASIC_WCID*/ + DelAsicWcidHdlr, /* CMDTHREAD_DEL_ASIC_WCID*/ + SetClientMACEntryHdlr, /* CMDTHREAD_SET_CLIENT_MAC_ENTRY*/ + + NULL, + NULL, + NULL, + NULL, + +#ifdef CONFIG_AP_SUPPORT + APUpdateCapabilityAndErpieHdlr, /* CMDTHREAD_AP_UPDATE_CAPABILITY_AND_ERPIE*/ + APEnableTXBurstHdlr, /* CMDTHREAD_AP_ENABLE_TX_BURST*/ + APDisableTXBurstHdlr, /* CMDTHREAD_AP_DISABLE_TX_BURST*/ + APAdjustEXPAckTimeHdlr, /* CMDTHREAD_AP_ADJUST_EXP_ACK_TIME*/ + APRecoverEXPAckTimeHdlr, /* CMDTHREAD_AP_RECOVER_EXP_ACK_TIME*/ + ChannelRescanHdlr, /* CMDTHREAD_CHAN_RESCAN*/ +#else + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef LED_CONTROL_SUPPORT + SetLEDStatusHdlr, /* CMDTHREAD_SET_LED_STATUS*/ +#else + NULL, +#endif /* LED_CONTROL_SUPPORT */ + +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT + LEDWPSMode10Hdlr, /* CMDTHREAD_LED_WPS_MODE10*/ +#else + NULL, +#endif /* WSC_LED_SUPPORT */ + +#else + NULL, +#endif /* WSC_INCLUDED */ + + /* Security related */ + SetWcidSecInfoHdlr, /* CMDTHREAD_SET_WCID_SEC_INFO*/ + SetAsicWcidIVEIVHdlr, /* CMDTHREAD_SET_ASIC_WCID_IVEIV*/ + SetAsicWcidAttrHdlr, /* CMDTHREAD_SET_ASIC_WCID_ATTR*/ + SETAsicSharedKeyHdlr, /* CMDTHREAD_SET_ASIC_SHARED_KEY*/ + SetAsicPairwiseKeyHdlr, /* CMDTHREAD_SET_ASIC_PAIRWISE_KEY*/ + RemovePairwiseKeyHdlr, /* CMDTHREAD_REMOVE_PAIRWISE_KEY*/ + + NULL, + +#ifdef CONFIG_AP_SUPPORT + _802_11_CounterMeasureHdlr, /* CMDTHREAD_802_11_COUNTER_MEASURE*/ +#else + NULL, +#endif /* CONFIG_AP_SUPPORT */ + + UpdateProtectHdlr, /* CMDTHREAD_UPDATE_PROTECT*/ + + +#ifdef LINUX + NULL, + NULL, + NULL, + NULL, + +#else + NULL, + NULL, + NULL, + NULL, +#endif /* LINUX */ + + NULL, + + NULL, + +#ifdef STREAM_MODE_SUPPORT + UpdateTXChainAddress, /* CMDTHREAD_UPDATE_TX_CHAIN_ADDRESS */ +#else + NULL, +#endif + + NULL, +#ifdef MT_MAC + AddRemoveKeyHdlr, /* CMDTHREAD_ADDREMOVE_ASIC_KEY */ +#else + NULL, +#endif /* MT_MAC */ + +#ifdef MT_PS + MtCmdPsClearReqHdlr, /* CMDTHREAD_PS_CLEAR */ + MtCmdPsRetrieveStartReqHdlr, /* CMDTHREAD_PS_RETRIEVE_START */ + MtCmdPsRetrieveRspHdlr, /* CMDTHREAD_PS_RETRIEVE_RSP */ + MtCmdPsSetIgnorePsm, /* CMDTHREAD_PS_IGNORE_PSM_SET */ +#else /* MT_PS */ + NULL, + NULL, + NULL, + NULL, +#endif /* !MT_PS */ +#ifdef CFG_TDLS_SUPPORT + CFGTdlsSendCHSWSetupHdlr, /* CMDTHREAD_TDLS_SEND_CH_SW_SETUP */ + CFGTdlsAutoTeardownHdlr, /* CMDTHREAD_TDLS_AUTO_TEARDOWN */ +#else + NULL, + NULL, +#endif /* CFG_TDLS_SUPPORT */ +#ifdef BCN_OFFLOAD_SUPPORT + HwCtrlBcnUpdate, /*HWCMD_ID_BCN_UPDATE*/ + HwCtrlBmcCntUpdate, /*HWCMD_ID_BMC_CNT_UPDATE*/ +#else + NULL, + NULL, +#endif /* BCN_OFFLOAD_SUPPORT */ + MtCmdAsicUpdateProtect, /*CMDTHREAD_PERODIC_CR_ACCESS_ASIC_UPDATE_PROTECT*/ + NULL, + MtCmdNICUpdateRawCounters, /*CMDTHREAD_PERODIC_CR_ACCESS_NIC_UPDATE_RAW_COUNTERS*/ + MtCmdWtbl2RateTableUpdate, /*CMDTHREAD_PERODIC_CR_ACCESS_WTBL_RATE_TABLE_UPDATE*/ + MlmePeriodicExec, /*CMDTHREAD_MLME_PERIOIDC_EXEC*/ + MtCmdWtblTxpsUpdate /*CMDTHREAD_PWR_MGT_BIT*/ +}; + + +static inline BOOLEAN ValidCMD(IN PCmdQElmt CMDQelmt) +{ + SHORT CMDIndex = CMDQelmt->command - CMDTHREAD_FIRST_CMD_ID; + USHORT CMDHdlrTableLength= sizeof(CMDHdlrTable) / sizeof(CMDHdlr); + + if ( (CMDIndex >= 0) && (CMDIndex < CMDHdlrTableLength)) + { + if (CMDHdlrTable[CMDIndex] > 0) + return TRUE; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("No corresponding CMDHdlr for this CMD(%x)\n", CMDQelmt->command)); + return FALSE; + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("CMD(%x) is out of boundary\n", CMDQelmt->command)); + return FALSE; + } +} + + +VOID CMDHandler(RTMP_ADAPTER *pAd) +{ + PCmdQElmt cmdqelmt; + //NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS; + //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; + + + if(!(RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) + { + if(ValidCMD(cmdqelmt)) + /*ntStatus =*/ (*CMDHdlrTable[cmdqelmt->command - CMDTHREAD_FIRST_CMD_ID])(pAd, cmdqelmt); + } + + 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 */ +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_video.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_video.c new file mode 100644 index 000000000..1e4ec06ac --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_video.c @@ -0,0 +1,168 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + cmm_video.c + + Abstract: + Ralink WiFi Driver video mode related subroutines + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + +*/ + +#include "rt_config.h" + + +#ifdef VIDEO_TURBINE_SUPPORT + + + +BOOLEAN UpdateFromGlobal = FALSE; + +void VideoTurbineUpdate( + IN PRTMP_ADAPTER pAd) +{ + if (UpdateFromGlobal == TRUE) + { + pAd->VideoTurbine.Enable = GLOBAL_AP_VIDEO_CONFIG.Enable; + pAd->VideoTurbine.ClassifierEnable = GLOBAL_AP_VIDEO_CONFIG.ClassifierEnable; + pAd->VideoTurbine.HighTxMode = GLOBAL_AP_VIDEO_CONFIG.HighTxMode; + pAd->VideoTurbine.TxPwr = GLOBAL_AP_VIDEO_CONFIG.TxPwr; + pAd->VideoTurbine.VideoMCSEnable = GLOBAL_AP_VIDEO_CONFIG.VideoMCSEnable; + pAd->VideoTurbine.VideoMCS = GLOBAL_AP_VIDEO_CONFIG.VideoMCS; + pAd->VideoTurbine.TxBASize = GLOBAL_AP_VIDEO_CONFIG.TxBASize; + pAd->VideoTurbine.TxLifeTimeMode = GLOBAL_AP_VIDEO_CONFIG.TxLifeTimeMode; + pAd->VideoTurbine.TxLifeTime = GLOBAL_AP_VIDEO_CONFIG.TxLifeTime; + pAd->VideoTurbine.TxRetryLimit = GLOBAL_AP_VIDEO_CONFIG.TxRetryLimit; + } +} + + +VOID TxSwQDepthAdjust(IN RTMP_ADAPTER *pAd, IN UINT32 qLen) +{ + ULONG IrqFlags; + INT qIdx; + QUEUE_HEADER *pTxQ, *pEntry; + PNDIS_PACKET pPacket; + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + pAd->TxSwQMaxLen = qLen; + for (qIdx = 0; qIdx < NUM_OF_TX_RING; qIdx++) + { + pTxQ = &pAd->TxSwQueue[qIdx]; + while(pTxQ->Number >= pAd->TxSwQMaxLen) + { + pEntry = RemoveHeadQueue(pTxQ); + if (pEntry) + { + pPacket = QUEUE_ENTRY_TO_PACKET(pEntry); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + else + break; + } + } + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + + DBGPRINT(RT_DEBUG_OFF, ("%s():Set TxSwQMaxLen as %d\n", + __FUNCTION__, pAd->TxSwQMaxLen)); +} + + +VOID VideoTurbineDynamicTune( + IN PRTMP_ADAPTER pAd) +{ + if (pAd->VideoTurbine.Enable == TRUE) + { + UINT32 MacReg = 0; + + { + /* Tx retry limit = 2F,1F */ + RTMP_IO_READ32(pAd, TX_RTY_CFG, &MacReg); + MacReg &= 0xFFFF0000; + MacReg |= GetAsicVideoRetry(pAd); + RTMP_IO_WRITE32(pAd, TX_RTY_CFG, MacReg); + } + + pAd->VideoTurbine.TxBASize = GetAsicVideoTxBA(pAd); + + Set_RateAdaptInterval(pAd, "100:50"); + TxSwQDepthAdjust(pAd, 1024); + + } + else + { + UINT32 MacReg = 0; + + + /* Default Tx retry limit = 1F,0F */ + RTMP_IO_READ32(pAd, TX_RTY_CFG, &MacReg); + MacReg &= 0xFFFF0000; + MacReg |= GetAsicDefaultRetry(pAd); + RTMP_IO_WRITE32(pAd, TX_RTY_CFG, MacReg); + + pAd->VideoTurbine.TxBASize = GetAsicDefaultTxBA(pAd); + + /* reset to default rate adaptation simping interval */ + if ((pAd->ra_interval != DEF_RA_TIME_INTRVAL) || + (pAd->ra_fast_interval != DEF_QUICK_RA_TIME_INTERVAL)) + Set_RateAdaptInterval(pAd, "500:100"); + + TxSwQDepthAdjust(pAd, MAX_PACKETS_IN_QUEUE); + } +} + +UINT32 GetAsicDefaultRetry( + IN PRTMP_ADAPTER pAd) +{ + UINT32 RetryLimit; + + RetryLimit = 0x1F0F; + + return RetryLimit; +} + +UCHAR GetAsicDefaultTxBA( + IN PRTMP_ADAPTER pAd) +{ + return pAd->CommonCfg.TxBASize; +} + +UINT32 GetAsicVideoRetry( + IN PRTMP_ADAPTER pAd) +{ + return pAd->VideoTurbine.TxRetryLimit; +} + +UCHAR GetAsicVideoTxBA( + IN PRTMP_ADAPTER pAd) +{ + return pAd->VideoTurbine.TxBASize; +} + +VOID VideoConfigInit( + IN PRTMP_ADAPTER pAd) +{ + pAd->VideoTurbine.Enable = FALSE; + pAd->VideoTurbine.TxRetryLimit = 0x2F1F; + pAd->VideoTurbine.TxBASize = pAd->CommonCfg.TxBASize; +} + +#endif /* VIDEO_TURBINE_SUPPORT */ + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_wep.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_wep.c new file mode 100644 index 000000000..13ea69822 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_wep.c @@ -0,0 +1,370 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + rtmp_wep.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Paul Wu 10-28-02 Initial +*/ + +#include "rt_config.h" + +UINT FCSTAB_32[256] = +{ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +/* + ======================================================================== + + Routine Description: + Calculate a new FCS given the current FCS and the new data. + + Arguments: + Fcs the original FCS value + Cp pointer to the data which will be calculate the FCS + Len the length of the data + + Return Value: + UINT - FCS 32 bits + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +UINT RTMP_CALC_FCS32( + IN UINT Fcs, + IN PUCHAR Cp, + IN INT Len) +{ + while (Len--) + Fcs = (((Fcs) >> 8) ^ FCSTAB_32[((Fcs) ^ (*Cp++)) & 0xff]); + + return (Fcs); +} + +/* + ======================================================================== + + Routine Description: + Init WEP function. + + Arguments: + pAd Pointer to our adapter + pKey Pointer to the WEP KEY + KeyId WEP Key ID + KeyLen the length of WEP KEY + pDest Pointer to the destination which Encryption data will store in. + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPInitWepEngine( + IN PUCHAR pIv, + IN PUCHAR pKey, + IN UCHAR KeyLen, + OUT ARC4_CTX_STRUC *pARC4_CTX) +{ + PUCHAR seed = NULL; + UINT8 seed_len; + + os_alloc_mem(NULL, (UCHAR **)&seed, sizeof(UCHAR)*16); + if (seed == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: seed Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + /* WEP seed construction */ + NdisZeroMemory(seed, 16); + NdisMoveMemory(seed, pIv, 3); + NdisMoveMemory(&seed[3], pKey, KeyLen); + seed_len = 3 + KeyLen; + + /* RC4 uses a pseudo-random number generator (PRNG) + to generate a key stream */ + ARC4_INIT(pARC4_CTX, &seed[0], seed_len); + + os_free_mem(NULL, seed); +} + +/* + ======================================================================== + + Routine Description: + Construct WEP IV header. + + Arguments: + + Return Value: + + Note: + It's a 4-octets header. + + ======================================================================== +*/ +VOID RTMPConstructWEPIVHdr( + IN UINT8 key_idx, + IN UCHAR *pn, + OUT UCHAR *iv_hdr) +{ + NdisZeroMemory(iv_hdr, LEN_WEP_IV_HDR); + + NdisMoveMemory(iv_hdr, pn, LEN_WEP_TSC); + + /* Append key index */ + iv_hdr[3] = (key_idx << 6); +} + +/* + ======================================================================== + + Routine Description: + WEP MPDU cryptographic encapsulation + + Arguments: + pAdapter Pointer to our adapter + pSrc Pointer to the received data + Len the length of the received data + + Return Value: + + Note: + + ======================================================================== +*/ +BOOLEAN RTMPSoftEncryptWEP( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pIvHdr, + IN PCIPHER_KEY pKey, + INOUT PUCHAR pData, + IN ULONG DataByteCnt) +{ + ARC4_CTX_STRUC *ARC4_CTX = NULL; + UINT FCSCRC32; + + os_alloc_mem(NULL, (UCHAR **)&ARC4_CTX, sizeof(ARC4_CTX_STRUC)); + if (ARC4_CTX == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: ARC4_CTX Allocate memory fail!!!\n", __FUNCTION__)); + return FALSE; + } + + if (pKey->KeyLen == 0) + { + os_free_mem(NULL, ARC4_CTX); + DBGPRINT(RT_DEBUG_ERROR, ("%s : The key is empty !\n", __FUNCTION__)); + return FALSE; + } + + /* Initialize WEP key stream */ + RTMPInitWepEngine(pIvHdr, + pKey->Key, + pKey->KeyLen, + ARC4_CTX); + + /* WEP computes the ICV over the plaintext data */ + FCSCRC32 = RTMP_CALC_FCS32(PPPINITFCS32, pData, DataByteCnt); + FCSCRC32 ^= 0xffffffff; /* complement */ + FCSCRC32 = cpu2le32(FCSCRC32); + + /* Append 4-bytes ICV after the MPDU data */ + NdisMoveMemory(pData + DataByteCnt, (PUCHAR)&FCSCRC32, LEN_ICV); + + /* Encrypt the MPDU plaintext data and ICV using ARC4 with a seed */ + ARC4_Compute(ARC4_CTX, pData, DataByteCnt + LEN_ICV, pData); + + os_free_mem(NULL, ARC4_CTX); + + return TRUE; +} + + +/* + ======================================================================== + + Routine Description: + Decrypt received WEP data + + Arguments: + pAdapter Pointer to our adapter + pSrc Pointer to the received data + Len the length of the received data + + Return Value: + TRUE Decrypt WEP data success + FALSE Decrypt WEP data failed + + Note: + + ======================================================================== +*/ +BOOLEAN RTMPSoftDecryptWEP( + IN PRTMP_ADAPTER pAd, + IN PCIPHER_KEY pKey, + INOUT PUCHAR pData, + INOUT UINT16 *DataByteCnt) +{ + /*ARC4_CTX_STRUC ARC4_CTX;*/ + ARC4_CTX_STRUC *ARC4_CTX = NULL; + PUCHAR plaintext_ptr; + UINT16 plaintext_len; + PUCHAR ciphertext_ptr; + UINT16 ciphertext_len; + UINT trailfcs; + UINT crc32; + + os_alloc_mem(NULL, (UCHAR **)&ARC4_CTX, sizeof(ARC4_CTX_STRUC)); + if (ARC4_CTX == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: ARC4_CTX Allocate memory fail!!!\n", __FUNCTION__)); + return FALSE; + } + + if (pKey->KeyLen == 0) + { + os_free_mem(NULL, ARC4_CTX); + DBGPRINT(RT_DEBUG_ERROR, ("%s : The key is not available !\n", __FUNCTION__)); + return FALSE; + } + + /* Initialize WEP key stream */ + RTMPInitWepEngine(pData, + pKey->Key, + pKey->KeyLen, + ARC4_CTX); + + /* Skip the WEP IV header (4-bytes) */ + ciphertext_ptr = pData + LEN_WEP_IV_HDR; + ciphertext_len = *DataByteCnt - LEN_WEP_IV_HDR; + + /*skip payload length is zero*/ + if ((*DataByteCnt) <= LEN_WEP_IV_HDR) { + os_free_mem(NULL, ARC4_CTX); + return FALSE; + } + + /* Decrypt the WEP MPDU. It shall include plaintext and ICV. + The result output would overwrite the original WEP IV header position */ + ARC4_Compute(ARC4_CTX, + ciphertext_ptr, + ciphertext_len, + pData); + + /* Point to the decrypted data frame and its length shall exclude ICV length */ + plaintext_ptr = pData; + plaintext_len = ciphertext_len - LEN_ICV; + + /* Extract peer's the ICV */ + NdisMoveMemory(&trailfcs, plaintext_ptr + plaintext_len, LEN_ICV); + + /* WEP recomputes the ICV and + bit-wise compares it with the decrypted ICV from the MPDU. */ + crc32 = RTMP_CALC_FCS32(PPPINITFCS32, plaintext_ptr, plaintext_len); + crc32 ^= 0xffffffff; /* complement */ + + if(crc32 != cpu2le32(trailfcs)) + { + os_free_mem(NULL, ARC4_CTX); + DBGPRINT(RT_DEBUG_ERROR, ("! WEP Data CRC Error !\n")); /*CRC error.*/ + return FALSE; + } + + /* Update the total data length */ + *DataByteCnt = plaintext_len; + + os_free_mem(NULL, ARC4_CTX); + + return TRUE; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_wpa.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_wpa.c new file mode 100644 index 000000000..6e5919cc2 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/cmm_wpa.c @@ -0,0 +1,7025 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + wpa.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Jan Lee 03-07-22 Initial + Paul Lin 03-11-28 Modify for supplicant +*/ +#include "rt_config.h" + +/* WPA OUI*/ +UCHAR OUI_WPA[3] = {0x00, 0x50, 0xF2}; +UCHAR OUI_WPA_NONE_AKM[4] = {0x00, 0x50, 0xF2, 0x00}; +UCHAR OUI_WPA_VERSION[4] = {0x00, 0x50, 0xF2, 0x01}; +UCHAR OUI_WPA_WEP40[4] = {0x00, 0x50, 0xF2, 0x01}; +UCHAR OUI_WPA_TKIP[4] = {0x00, 0x50, 0xF2, 0x02}; +UCHAR OUI_WPA_CCMP[4] = {0x00, 0x50, 0xF2, 0x04}; +UCHAR OUI_WPA_WEP104[4] = {0x00, 0x50, 0xF2, 0x05}; +UCHAR OUI_WPA_8021X_AKM[4] = {0x00, 0x50, 0xF2, 0x01}; +UCHAR OUI_WPA_PSK_AKM[4] = {0x00, 0x50, 0xF2, 0x02}; +/* WPA2 OUI*/ +UCHAR OUI_WPA2[3] = {0x00, 0x0F, 0xAC}; +UCHAR OUI_WPA2_WEP40[4] = {0x00, 0x0F, 0xAC, 0x01}; +UCHAR OUI_WPA2_TKIP[4] = {0x00, 0x0F, 0xAC, 0x02}; +UCHAR OUI_WPA2_CCMP[4] = {0x00, 0x0F, 0xAC, 0x04}; +UCHAR OUI_WPA2_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x01}; +UCHAR OUI_WPA2_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x02}; +UCHAR OUI_WPA2_WEP104[4] = {0x00, 0x0F, 0xAC, 0x05}; +UCHAR OUI_WPA2_1X_SHA256[4] = {0x00, 0x0F, 0xAC, 0x05}; +UCHAR OUI_WPA2_PSK_SHA256[4] = {0x00, 0x0F, 0xAC, 0x06}; + +#ifdef CONFIG_OWE_SUPPORT +UCHAR OUI_WPA2_CIPHER_CCMP128[4] = {0x00, 0x0F, 0xAC, 0x04}; +UCHAR OUI_WPA2_CIPHER_CCMP256[4] = {0x00, 0x0F, 0xAC, 0x0A}; +#endif + +#ifdef DOT11_SAE_SUPPORT +UCHAR OUI_WPA2_AKM_SAE_SHA256[4] = {0x00, 0x0F, 0xAC, 0x08}; +#endif +#ifdef CONFIG_OWE_SUPPORT +UCHAR OUI_WPA2_AKM_OWE[4] = {0x00, 0x0F, 0xAC, 0x12/*d'18*/}; +#endif + + +#ifdef DOT11R_FT_SUPPORT +UCHAR OUI_FT_8021X_AKM[4] = {0x00, 0x0F, 0xAC, 0x03}; +UCHAR OUI_FT_PSK_AKM[4] = {0x00, 0x0F, 0xAC, 0x04}; +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef CONFIG_HOTSPOT_R2 +UCHAR OSEN_IE[] = {0x50,0x6f,0x9a,0x12,0x00,0x0f,0xac,0x07,0x01,0x00,0x00,0x0f,0xac,0x04,0x01,0x00,0x50,0x6f,0x9a,0x01,0x00,0x00}; +UCHAR OSEN_IELEN = sizeof(OSEN_IE); +#endif + +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); + +static VOID WpaEAPOLTimeout( + 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); + StateMachineSetAction(S, WPA_PTK, MT2_EAPOLTIMEOUT, (STATE_MACHINE_FUNC)WpaEAPOLTimeout); +} + +/* + ========================================================================== + 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; + STA_TR_ENTRY *tr_entry; + PHEADER_802_11 pHeader; + + + 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->func_tb_idx == MAIN_MBSSID) && + (pAd->ApCfg.MBSSID[pEntry->func_tb_idx].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) + { + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + DBGPRINT(RT_DEBUG_TRACE, (" PortSecured(%d), WpaState(%d), AuthMode(%d), PMKID_CacheIdx(%d) \n", + tr_entry->PortSecured, pEntry->WpaState, pEntry->AuthMode, pEntry->PMKID_CacheIdx)); + + if ((tr_entry->PortSecured == WPA_802_1X_PORT_NOT_SECURED) + && (pEntry->WpaState < AS_PTKSTART) + && ((pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) || (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef DOT11_SAE_SUPPORT + || (pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK) +#endif +#ifdef CONFIG_OWE_SUPPORT + || (pEntry->AuthMode == Ndis802_11AuthModeOWE) +#endif + || ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) && (pEntry->PMKID_CacheIdx != ENTRY_NOT_FOUND)))) + { + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pEntry->WpaState = AS_INITPSK; + tr_entry->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 WpaEAPOLTimeout( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + + pEntry = MacTableLookup(pAd, Elem->Msg); + if ((pEntry) && IS_ENTRY_CLIENT(pEntry)) { + PRTMP_ADAPTER pAd = NULL; + + pAd = (PRTMP_ADAPTER)pEntry->pAd; + pEntry->ReTryCounter++; + + DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec---> ReTryCounter=%d, WpaState=%d\n", + pEntry->ReTryCounter, pEntry->WpaState)); + switch (pEntry->AuthMode) { + case Ndis802_11AuthModeWPA: + case Ndis802_11AuthModeWPAPSK: + case Ndis802_11AuthModeWPA2: + case Ndis802_11AuthModeWPA2PSK: + /* 1. GTK already retried, give up and disconnect client. */ + if (pEntry->ReTryCounter > (GROUP_MSG1_RETRY_TIMER_CTR + 3)) { + /* send wireless event - for group key handshaking timeout */ + RTMPSendWirelessEvent(pAd, IW_GROUP_HS_TIMEOUT_EVENT_FLAG, + pEntry->Addr, pEntry->wdev->wdev_idx, 0); + + DBGPRINT(RT_DEBUG_TRACE, + ("WPARetryExec::Group Key HS exceed retry count,Disassociate client, pEntry->ReTryCounter %d\n", + pEntry->ReTryCounter)); + MlmeDeAuthAction(pAd, pEntry, REASON_GROUP_KEY_HS_TIMEOUT, FALSE); + } + /* 2. Retry GTK. */ + else if (pEntry->ReTryCounter > GROUP_MSG1_RETRY_TIMER_CTR) { + + DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec::ReTry 2-way group-key Handshake\n")); + if (pEntry->GTKState == REKEY_NEGOTIATING) + WPAStart2WayGroupHS(pAd, pEntry); + } + /* 3. 4-way message 3 retried more than three times. Disconnect client */ + else if (pEntry->ReTryCounter > (PEER_MSG3_RETRY_TIMER_CTR + 3)) { + /* send wireless event - for pairwise key handshaking timeout */ + RTMPSendWirelessEvent(pAd, IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG, pEntry->Addr, + pEntry->wdev->wdev_idx, 0); + + DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec::MSG3 timeout, pEntry->ReTryCounter = %d\n", + pEntry->ReTryCounter)); + MlmeDeAuthAction(pAd, pEntry, REASON_4_WAY_TIMEOUT, FALSE); + + } + /* 4. Retry 4 way message 3 */ + else if (pEntry->ReTryCounter >= PEER_MSG3_RETRY_TIMER_CTR) { + DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec::ReTry MSG3 of 4-way Handshake\n")); + WPAPairMsg3Retry(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV); + } + /* 5. 4-way message 1 retried more than three times. Disconnect client */ + else if (pEntry->ReTryCounter > (PEER_MSG1_RETRY_TIMER_CTR + 3)) { + /* send wireless event - for pairwise key handshaking timeout */ + RTMPSendWirelessEvent(pAd, IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG, pEntry->Addr, + pEntry->wdev->wdev_idx, 0); + + DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec::MSG1 timeout, pEntry->ReTryCounter = %d\n", + pEntry->ReTryCounter)); + MlmeDeAuthAction(pAd, pEntry, REASON_4_WAY_TIMEOUT, FALSE); + } + /* 6. Retry 4 way message 1, the last try, the timeout is 3 sec for EAPOL-Start */ + else if (pEntry->ReTryCounter == (PEER_MSG1_RETRY_TIMER_CTR + 3)) { + DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec::Retry MSG1, the last try\n")); + WPAStart4WayHS(pAd, pEntry, PEER_MSG3_RETRY_EXEC_INTV); + } + /* 7. Retry 4 way message 1 */ + else if (pEntry->ReTryCounter < (PEER_MSG1_RETRY_TIMER_CTR + 3)) { + if ((pEntry->WpaState == AS_PTKSTART) || (pEntry->WpaState == AS_INITPSK) || + (pEntry->WpaState == AS_INITPMK)) { + DBGPRINT(RT_DEBUG_TRACE, ("WPARetryExec::ReTry MSG1 of 4-way Handshake\n")); + WPAStart4WayHS(pAd, pEntry, PEER_MSG1_RETRY_EXEC_INTV); + } + } + break; + + default: + break; + + } + } +#ifdef APCLI_SUPPORT + else if ((pEntry) && IS_ENTRY_APCLI(pEntry)) { + if (pEntry->AuthMode == Ndis802_11AuthModeWPA || pEntry->AuthMode == Ndis802_11AuthModeWPAPSK) { + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pEntry->pAd; + + if (pEntry->func_tb_idx < MAX_APCLI_NUM) { + UCHAR ifIndex = pEntry->func_tb_idx; + + DBGPRINT(RT_DEBUG_TRACE, ("(%s) ApCli interface[%d] startdown.\n", + __func__, ifIndex)); +#ifdef MAC_REPEATER_SUPPORT + if ((pEntry->bReptCli) && (pAd->ApCfg.bMACRepeaterEn == TRUE)) + 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); +#endif /* MAC_REPEATER_SUPPORT */ + } + } + } +#endif /* APCLI_SUPPORT */ +} + +VOID WpaEAPOLKeyAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MAC_TABLE_ENTRY *pEntry; + STA_TR_ENTRY *tr_entry; + 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 */ + unsigned char hdr_len = LENGTH_802_11; + + + DBGPRINT(RT_DEBUG_INFO, ("WpaEAPOLKeyAction ===>\n")); + + pHeader = (PHEADER_802_11)Elem->Msg; +#ifdef A4_CONN + if (pHeader->FC.FrDs == 1 && pHeader->FC.ToDs == 1) + hdr_len = LENGTH_802_11_WITH_ADDR4; +#endif + pEapol_packet = (PEAPOL_PACKET)&Elem->Msg[hdr_len + 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) { + if(!VALID_WCID(pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].MacTabWCID)) { + DBGPRINT(RT_DEBUG_ERROR, ("Error: Invalid WCID=%d\n", + pAd->ApCfg.ApCliTab[ifIndex].RepeaterCli[CliIdx].MacTabWCID)); + break; + } + 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; + + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + + 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 - hdr_len - LENGTH_802_1_H) + { + DBGPRINT(RT_DEBUG_ERROR, ("The length of EAPoL packet is invalid \n")); + break; + } + + if (((pEapol_packet->ProVer != EAPOL_VER) && (pEapol_packet->ProVer != EAPOL_VER2)) || + ((pEapol_packet->KeyDesc.Type != WPA1_KEY_DESC) && (pEapol_packet->KeyDesc.Type != WPA2_KEY_DESC))) + { + DBGPRINT(RT_DEBUG_ERROR, ("Key descripter does not match with WPA rule\n")); + break; + } + +#ifdef DOT11R_FT_SUPPORT + /* The value 3 shall be used for all EAPOL-Key frames to and from a STA when the negotiated */ + /* AKM is 00-0F-AC:3 or 00-0F-AC:4. It is a FT STA. */ + if (IS_FT_RSN_STA(pEntry)) + { + if (peerKeyInfo.KeyDescVer != KEY_DESC_EXT) + { + DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version(%d) not match(FT) \n", peerKeyInfo.KeyDescVer)); + break; + } + } + else +#endif /* DOT11R_FT_SUPPORT */ + /* The value 1 shall be used for all EAPOL-Key frames to and from a STA when */ + /* neither the group nor pairwise ciphers are CCMP for Key Descriptor 1.*/ + if ((pEntry->WepStatus == Ndis802_11TKIPEnable) && (peerKeyInfo.KeyDescVer != KEY_DESC_TKIP)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version not match(TKIP) \n")); + break; + } +#ifdef DOT11W_PMF_SUPPORT + else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_USE_SHA256) && + (peerKeyInfo.KeyDescVer != KEY_DESC_EXT +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + && peerKeyInfo.KeyDescVer != KEY_DESC_NOT_DEFINED +#endif + )) { + DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version not match(AES-128/NOT_DEFINED)\n")); + } +#endif /* DOT11W_PMF_SUPPORT */ + /* The value 2 shall be used for all EAPOL-Key frames to and from a STA when */ + /* either the pairwise or the group cipher is AES-CCMP for Key Descriptor 2 or 3.*/ + else if ((pEntry->WepStatus == Ndis802_11AESEnable) + && (peerKeyInfo.KeyDescVer != KEY_DESC_AES) + && (peerKeyInfo.KeyDescVer != KEY_DESC_EXT) +#ifdef CONFIG_HOTSPOT_R2 + && (peerKeyInfo.KeyDescVer != KEY_DESC_OSEN) +#endif +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + && (peerKeyInfo.KeyDescVer != KEY_DESC_NOT_DEFINED) +#endif + ) + { + DBGPRINT(RT_DEBUG_ERROR, ("Key descripter version not match(AES) pEntry->WepStatus=%d, peerKeyInfo.KeyDescVer=%d\n", pEntry->WepStatus, peerKeyInfo.KeyDescVer)); + break; + } + + /* Check if this STA is in class 3 state and the WPA state is started */ + if ((pEntry->Sst == SST_ASSOC) && (pEntry->WpaState >= AS_INITPSK)) + { + /* Check the Key Ack (bit 7) of the Key Information to determine the Authenticator */ + /* or not.*/ + /* An EAPOL-Key frame that is sent by the Supplicant in response to an EAPOL-*/ + /* Key frame from the Authenticator must not have the Ack bit set.*/ + if (peerKeyInfo.KeyAck == 1) + { + /* The frame is snet by Authenticator. */ + /* So the Supplicant side shall handle this.*/ + + if ((peerKeyInfo.Secure == 0) && (peerKeyInfo.Request == 0) && + (peerKeyInfo.Error == 0) && (peerKeyInfo.KeyType == PAIRWISEKEY)) + { + /* + Process + 1. the message 1 of 4-way HS in WPA or WPA2 + EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) + 2. the message 3 of 4-way HS in WPA + EAPOL-Key(0,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) + */ + if (peerKeyInfo.KeyMic == 0) + PeerPairMsg1Action(pAd, pEntry, Elem); + else + PeerPairMsg3Action(pAd, pEntry, Elem); + } + else if ((peerKeyInfo.Secure == 1) && + (peerKeyInfo.KeyMic == 1) && + (peerKeyInfo.Request == 0) && + (peerKeyInfo.Error == 0)) + { + /* + Process + 1. the message 3 of 4-way HS in WPA2 + EAPOL-Key(1,1,1,1,P,0,KeyRSC,ANonce,MIC,DataKD_M3) + 2. the message 1 of group KS in WPA or WPA2 + EAPOL-Key(1,1,1,0,G,0,Key RSC,0, MIC,GTK[N]) + */ + if (peerKeyInfo.KeyType == PAIRWISEKEY) + PeerPairMsg3Action(pAd, pEntry, Elem); + else + PeerGroupMsg1Action(pAd, pEntry, Elem); + } + } + else + { + /* + The frame is snet by Supplicant.So the Authenticator + side shall handle this. + */ +#ifdef CONFIG_AP_SUPPORT + 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[hdr_len], + (Elem->MsgLen - hdr_len)); + } + } +#ifdef CONFIG_AP_SUPPORT + else if ((peerKeyInfo.Request == 1) && (peerKeyInfo.Error == 0)) + { + INT i; + UCHAR apidx = pEntry->func_tb_idx; + + /* Need to check KeyType for groupkey or pairwise key update, refer to 8021i P.114, */ + if (peerKeyInfo.KeyType == GROUPKEY) + { + UINT8 Wcid; + BSS_STRUCT *mbss; + struct wifi_dev *wdev; + DBGPRINT(RT_DEBUG_TRACE, ("REQUEST=1, ERROR=0, update group key\n")); + + mbss = &pAd->ApCfg.MBSSID[apidx]; + wdev = &mbss->wdev; + + GenRandom(pAd, wdev->bssid, mbss->GNonce); + wdev->DefaultKeyId = (wdev->DefaultKeyId == 1) ? 2 : 1; + WpaDeriveGTK(mbss->GMK, mbss->GNonce, + wdev->bssid, mbss->GTK, LEN_TKIP_GTK); + + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + if (IS_ENTRY_CLIENT(&pAd->MacTab.Content[i]) + && (pAd->MacTab.Content[i].WpaState == AS_PTKINITDONE) + && (pAd->MacTab.Content[i].func_tb_idx== apidx)) + { + pAd->MacTab.Content[i].GTKState = REKEY_NEGOTIATING; + WPAStart2WayGroupHS(pAd, &pAd->MacTab.Content[i]); + pAd->MacTab.Content[i].ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR; + /* retry timer is set inside WPAStart2WayGroupHS */ + //RTMPModTimer(&pAd->MacTab.Content[i].RetryTimer, PEER_MSG3_RETRY_EXEC_INTV); + + } + } + + /* Get a specific WCID to record this MBSS key attribute */ + GET_GroupKey_WCID(pAd, Wcid, apidx); + + WPAInstallSharedKey(pAd, wdev->GroupKeyWepStatus, + apidx, wdev->DefaultKeyId, Wcid, + TRUE, mbss->GTK, LEN_TKIP_GTK); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("REQUEST=1, ERROR= 0, update pairwise key\n")); + + NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY)); + + /* clear this entry as no-security mode*/ + AsicRemovePairwiseKeyEntry(pAd, pEntry->wcid); + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + CmdProcAddRemoveKey(pAd, 1, pEntry->func_tb_idx, 0, pEntry->wcid, PAIRWISEKEYTABLE, &pEntry->PairwiseKey, pEntry->Addr); +#endif + + 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 +#ifdef DOT11_SAE_SUPPORT + || (pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK) +#endif +#ifdef CONFIG_OWE_SUPPORT + || (pEntry->AuthMode == Ndis802_11AuthModeOWE) +#endif + ) + pEntry->WpaState = AS_INITPSK; + + pEntry->GTKState = REKEY_NEGOTIATING; + pEntry->PrivacyFilter = Ndis802_11PrivFilter8021xWEP; + pEntry->ReTryCounter = PEER_MSG1_RETRY_TIMER_CTR; + tr_entry->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; + struct wifi_dev *wdev; + + if ((!pEntry) || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry) +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + && (!IS_ENTRY_TDLS(pEntry)) +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + + )) + return; + + + Status = RTMPAllocateNdisPacket(pAd, &pPacket, pHeader802_3, HdrLen, pData, DataLen); + if (Status != NDIS_STATUS_SUCCESS) + return; + + +#if defined(MT_MAC) && defined(WSC_INCLUDED) && defined(CONFIG_AP_SUPPORT) + if (bClearFrame == 0x80) + RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, bClearFrame); + else +#endif /* defined(MT_MAC) && defined(WSC_INCLUDED) && defined(CONFIG_AP_SUPPORT) */ + RTMP_SET_PACKET_CLEAR_EAP_FRAME(pPacket, (bClearFrame ? 1 : 0)); + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + } + else +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + { + } + + RTMP_SET_PACKET_WCID(pPacket, (UCHAR)pEntry->wcid); + // TODO: shiang-usw, fix this! + RTMP_SET_PACKET_WDEV(pPacket, pEntry->wdev->wdev_idx); + RTMP_SET_PACKET_MOREDATA(pPacket, FALSE); + + /* send out the packet */ + wdev = pEntry->wdev; + if (wdev && wdev->tx_pkt_handle) + wdev->tx_pkt_handle(pAd, pPacket); + else { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Invalid wdev(%p) or tx_pkt_handle(%p)!\n", + __FUNCTION__, wdev, (wdev ? wdev->tx_pkt_handle : NULL))); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + } + + if (!RTMP_TEST_FLAG(pAd, (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS | + fRTMP_ADAPTER_RESET_IN_PROGRESS))) + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, WCID_ALL, MAX_TX_PROCESS); + +} + +/* + ========================================================================== + 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) +#ifdef DOT11_SAE_SUPPORT + || (pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK) +#endif +#ifdef CONFIG_OWE_SUPPORT + || (pEntry->AuthMode == Ndis802_11AuthModeOWE) +#endif + ) + 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->wdev->wdev_idx, 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); + } +#ifdef CONFIG_OWE_SUPPORT + else if ((pEntry->AuthMode == Ndis802_11AuthModeOWE) && + (pEntry->key_deri_alg == SEC_KEY_DERI_SHA256)) { + RT_HMAC_SHA256(pEntry->PTK, LEN_PTK_KEK, + (PUCHAR)pMsg, eapol_len, mic, LEN_KEY_DESC_MIC); + } else if ((pEntry->AuthMode == Ndis802_11AuthModeOWE) && + (pEntry->key_deri_alg == SEC_KEY_DERI_SHA384)) { + RT_HMAC_SHA384(pEntry->PTK, + LEN_PTK_KCK_SHA384, + (PUCHAR)pMsg, + eapol_len, + mic, + LEN_KEY_DESC_MIC_SHA384); + } +#endif + else if (EapolKeyInfo.KeyDescVer == KEY_DESC_OSEN +#ifdef DOT11_SAE_SUPPORT + || EapolKeyInfo.KeyDescVer == KEY_DESC_NOT_DEFINED +#endif + ) {/* AES-128 */ + + UINT mlen = AES_KEY128_LENGTH; + + AES_CMAC((PUCHAR)pMsg, eapol_len, pEntry->PTK, LEN_PTK_KCK, mic, &mlen); + + { + unsigned char *tmp = (unsigned char *)pEntry->PTK; + int k=0; + printk("PTK=>"); + for(k=0;k<32;k++) + printk("%02x", *(tmp+k)); + printk("\n"); + } + } + 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->wdev->wdev_idx, 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) +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + || (EapolKeyInfo.KeyDescVer == KEY_DESC_NOT_DEFINED) +#endif + ) { + 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; + STA_TR_ENTRY *tr_entry; + //struct wifi_dev *wdev; +#ifdef CONFIG_AP_SUPPORT + BSS_STRUCT *pMbss; +#endif /* CONFIG_AP_SUPPORT */ +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + UINT8 pmk_len; +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart4WayHS\n")); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS | + fRTMP_ADAPTER_HALT_IN_PROGRESS)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : The interface is closed...\n")); + return; + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : The entry doesn't exist.\n")); + return; + } + + pMbss = (BSS_STRUCT *)pEntry->wdev->func_dev; + //wdev = pEntry->wdev; + if (pEntry->wdev != &pMbss->wdev) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : cannot get binding wdev(%p).\n", pEntry->wdev)); + return; + } + + /* pointer to the corresponding position*/ + pBssid = pMbss->wdev.bssid; + group_cipher = pMbss->wdev.GroupKeyWepStatus; + } +#endif /* CONFIG_AP_SUPPORT */ + + if(pEntry) { + if(!pEntry->AuthAssocNotInProgressFlag) { + DBGPRINT(RT_DEBUG_TRACE,("===[%s] in if pEntry->AuthAssocNotInProgressFlag = %u as auth/assoc in progress thus not initiating 4way HS \n", + __FUNCTION__, pEntry->AuthAssocNotInProgressFlag)); + return; + } else { + DBGPRINT(RT_DEBUG_TRACE,("===[%s] in else pEntry->AuthAssocNotInProgressFlag = %u \n", + __FUNCTION__, pEntry->AuthAssocNotInProgressFlag)); + } + } + + if (pBssid == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : No corresponding Authenticator.\n")); + return; + } + + /* Check the status*/ + if ((pEntry->WpaState > AS_PTKSTART) || (pEntry->WpaState < AS_INITPMK)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[ERROR]WPAStart4WayHS : Not expect calling\n")); + return; + } + +#ifdef WSC_AP_SUPPORT + if (MAC_ADDR_EQUAL(pEntry->Addr, pMbss->WscControl.EntryAddr) && + pMbss->WscControl.EapMsgRunning) + { + pEntry->WpaState = AS_NOTUSE; + DBGPRINT(RT_DEBUG_ERROR, ("This is a WSC-Enrollee. Not expect calling WPAStart4WayHS here \n")); + return; + } +#endif /* WSC_AP_SUPPORT */ + + /* Increment replay counter by 1*/ + ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); + + /* Randomly generate ANonce */ + GenRandom(pAd, (UCHAR *)pBssid, pEntry->ANonce); + + /* Allocate memory for output*/ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + /* Construct EAPoL message - Pairwise Msg 1*/ + /* EAPOL-Key(0,0,1,0,P,0,0,ANonce,0,DataKD_M1) */ + ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_PAIR_MSG_1, + 0, /* Default key index*/ + pEntry->ANonce, + NULL, /* TxRSC*/ + NULL, /* GTK*/ + NULL, /* RSNIE*/ + 0, /* RSNIE length */ + pEapolFrame); + +#ifdef CONFIG_AP_SUPPORT + /* If PMKID match in WPA2-enterprise mode, fill PMKID into Key data field and update PMK here */ + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2 +#ifdef DOT11_SAE_SUPPORT + || pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK +#endif +#ifdef CONFIG_OWE_SUPPORT + || pEntry->AuthMode == Ndis802_11AuthModeOWE +#endif + ) && (pEntry->PMKID_CacheIdx != ENTRY_NOT_FOUND)) + { + /* Fill in value for KDE */ + pEapolFrame->KeyDesc.KeyData[0] = 0xDD; + pEapolFrame->KeyDesc.KeyData[2] = 0x00; + pEapolFrame->KeyDesc.KeyData[3] = 0x0F; + pEapolFrame->KeyDesc.KeyData[4] = 0xAC; + pEapolFrame->KeyDesc.KeyData[5] = 0x04; + + NdisMoveMemory(&pEapolFrame->KeyDesc.KeyData[6], &pMbss->PMKIDCache.BSSIDInfo[pEntry->PMKID_CacheIdx].PMKID, LEN_PMKID); +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + pmk_len = LEN_PMK; +#ifdef CONFIG_OWE_SUPPORT + if (pEntry->key_deri_alg == SEC_KEY_DERI_SHA384) + pmk_len = LEN_PMK_SHA384; +#endif + NdisMoveMemory(&pEntry->PMK, &pMbss->PMKIDCache.BSSIDInfo[pEntry->PMKID_CacheIdx].PMK, pmk_len); +#else + NdisMoveMemory(&pMbss->PMK, &pMbss->PMKIDCache.BSSIDInfo[pEntry->PMKID_CacheIdx].PMK, PMK_LEN); +#endif + pEapolFrame->KeyDesc.KeyData[1] = 0x14;/* 4+LEN_PMKID*/ + INC_UINT16_TO_ARRARY(pEapolFrame->KeyDesc.KeyDataLen, 6 + LEN_PMKID); + INC_UINT16_TO_ARRARY(pEapolFrame->Body_Len, 6 + LEN_PMKID); + } +#ifdef DOT11W_PMF_SUPPORT + else if ((NULL +#ifdef DOT11_SAE_SUPPORT + || pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK +#endif +#ifdef CONFIG_OWE_SUPPORT + || pEntry->AuthMode == Ndis802_11AuthModeOWE +#endif + ) + && (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE))) + { + UCHAR digest[80], PMK_key[20]; + PKEY_DESCRIPTER pKeyDesc = &pEapolFrame->KeyDesc; + + pKeyDesc->KeyData[0] = 0xDD; + pKeyDesc->KeyData[2] = 0x00; + pKeyDesc->KeyData[3] = 0x0F; + pKeyDesc->KeyData[4] = 0xAC; + pKeyDesc->KeyData[5] = 0x04; + + NdisMoveMemory(&PMK_key[0], "PMK Name", 8); + NdisMoveMemory(&PMK_key[8], pMbss->wdev.bssid, MAC_ADDR_LEN); + NdisMoveMemory(&PMK_key[14], pEntry->Addr, MAC_ADDR_LEN); +#ifdef DOT11_SAE_SUPPORT + if (pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, ("%s:[SAE]pmkid not found\n", __func__)); + if (!sae_get_pmk_cache(&pAd->SaeCfg, pMbss->wdev.bssid, pEntry->Addr, digest, NULL)) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, ("%s: derive pmkid fail\n", __func__)); + return; + } + } +#endif + +#ifdef CONFIG_OWE_SUPPORT + if (pEntry->AuthMode == Ndis802_11AuthModeOWE) { + OWE_INFO *owe = &pEntry->owe; + NdisMoveMemory(&pKeyDesc->KeyData[6], owe->pmkid, LEN_PMKID); + } else +#endif /*CONFIG_OWE_SUPPORT*/ + NdisMoveMemory(&pKeyDesc->KeyData[6], digest, LEN_PMKID); + + pKeyDesc->KeyData[1] = 0x14;// 4+LEN_PMKID + INC_UINT16_TO_ARRARY(pKeyDesc->KeyDataLen, 6 + LEN_PMKID); + INC_UINT16_TO_ARRARY(pEapolFrame->Body_Len, 6 + LEN_PMKID); + } +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + /* Make outgoing frame*/ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + RTMPToWirelessSta(pAd, pEntry, Header802_3, + LENGTH_802_3, (PUCHAR)pEapolFrame, + CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, + (tr_entry->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 */ + unsigned char hdr_len = LENGTH_802_11; +#ifdef A4_CONN + PHEADER_802_11 pHeader; +#endif +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) || \ + (defined(DOT11R_FT_SUPPORT) && defined(CONFIG_STA_SUPPORT)) + UINT8 ptk_len = LEN_AES_PTK; +#endif + DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg1Action \n")); + + if ((!pEntry) || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry))) + return; + +#ifdef A4_CONN + pHeader = (PHEADER_802_11)Elem->Msg; + if (pHeader->FC.FrDs == 1 && pHeader->FC.ToDs == 1) + hdr_len = LENGTH_802_11_WITH_ADDR4; +#endif + + if (Elem->MsgLen < (hdr_len + 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->func_tb_idx; +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + CliIdx = ((ifIndex - 64) % 16); +#endif /* MAC_REPEATER_SUPPORT */ + + if (IfIndex >= MAX_APCLI_NUM) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pCurrentAddr = pAd->ApCfg.ApCliTab[IfIndex].RepeaterCli[CliIdx].CurrentAddress; + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrentAddr = pAd->ApCfg.ApCliTab[IfIndex].wdev.if_addr; + + +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + if (is_pmkid_cache_in_entry(pEntry)) { + + if (pEntry->AuthMode == Ndis802_11AuthModeOWE + && pEntry->key_deri_alg == SEC_KEY_DERI_SHA256) { + if (pEntry->owe.last_try_group == pEntry->owe.curr_group) + NdisMoveMemory(pEntry->PMK, pEntry->pmk_cache, LEN_PMK); + else { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("===> %s:PMK Cache not valid as owe group changed from %d to %d\n", + __func__, pEntry->owe.last_try_group, + pEntry->owe.curr_group)); + return; + } + } else if (pEntry->AuthMode == Ndis802_11AuthModeOWE + && pEntry->key_deri_alg == SEC_KEY_DERI_SHA384) { + if (pEntry->owe.last_try_group == pEntry->owe.curr_group) + NdisMoveMemory(pEntry->PMK, pEntry->pmk_cache, LEN_PMK_SHA384); + else { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("===> %s:PMK Cache not valid as owe group changed from %d to %d\n", + __func__, pEntry->owe.last_try_group, + pEntry->owe.curr_group)); + return; + } + } else { + NdisMoveMemory(pEntry->PMK, pEntry->pmk_cache, LEN_PMK); + } + } +#endif +#ifdef APCLI_OWE_SUPPORT + else if (pEntry->need_process_ecdh_ie == TRUE) { + process_ecdh_element(pAd, + pEntry, + (EXT_ECDH_PARAMETER_IE *)&pEntry->ecdh_ie, + pEntry->ecdh_ie.length, + SUBTYPE_ASSOC_RSP, FALSE); + } +#endif + + + +#ifdef APCLI_OWE_SUPPORT + if (pEntry->AuthMode == Ndis802_11AuthModeOWE + && pEntry->key_deri_alg == SEC_KEY_DERI_SHA384) + ptk_len = LEN_OWE_PTK_SHA384; +#endif + +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + if (pEntry->AuthMode == Ndis802_11AuthModeOWE + || pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK) + pmk_ptr = pEntry->PMK; + else +#endif + 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 */ + + if (pCurrentAddr == NULL) + return; + + /* Store the received frame*/ + pMsg1 = (PEAPOL_PACKET)&Elem->Msg[hdr_len + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - hdr_len - LENGTH_802_1_H; + + /* Sanity Check peer Pairwise message 1 - Replay Counter*/ + if (PeerWpaMessageSanity(pAd, pMsg1, MsgLen, EAPOL_PAIR_MSG_1, pEntry) == FALSE) + return; + + /* Store Replay counter, it will use to verify message 3 and construct message 2*/ + NdisMoveMemory(pEntry->R_Counter, pMsg1->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + /* Store ANonce*/ + NdisMoveMemory(pEntry->ANonce, pMsg1->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE); + + /* Generate random SNonce*/ + GenRandom(pAd, (UCHAR *)pCurrentAddr, pEntry->SNonce); + pEntry->AllowInsPTK = TRUE; + pEntry->AllowUpdateRSC = FALSE; + pEntry->LastGroupKeyId = 0; + NdisZeroMemory(pEntry->LastGTK, MAX_LEN_GTK); + +#ifdef DOT11R_FT_SUPPORT + if (IS_FT_RSN_STA(pEntry)) + { + } + else +#endif /* DOT11R_FT_SUPPORT */ + +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + + if (pEntry->AuthMode == Ndis802_11AuthModeOWE) { + PMF_DerivePTK(pAd, + (UCHAR *)pmk_ptr, + pEntry->ANonce, + pEntry->Addr, + pEntry->SNonce, + pCurrentAddr, + PTK, + ptk_len); + NdisMoveMemory(pEntry->PTK, PTK, ptk_len); + hex_dump("PTK", PTK, ptk_len); + } else if (pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK) { + PMF_DerivePTK(pAd, + (UCHAR *)pmk_ptr, + pEntry->ANonce, + pEntry->Addr, + pEntry->SNonce, + pCurrentAddr, + PTK, + LEN_AES_PTK); + NdisMoveMemory(pEntry->PTK, PTK, LEN_AES_PTK); + } else +#endif + +#ifdef DOT11W_PMF_SUPPORT + if ((CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_USE_SHA256))) + { + PMF_DerivePTK(pAd, + (UCHAR *)pmk_ptr, + pEntry->ANonce, + pEntry->Addr, + pEntry->SNonce, + pCurrentAddr, + PTK, + LEN_AES_PTK); /* Must is 48 bytes */ + + NdisMoveMemory(pEntry->PTK, PTK, LEN_AES_PTK); + hex_dump("PTK", PTK, LEN_AES_PTK); + } + else +#endif /* DOT11W_PMF_SUPPORT */ + { + /* Calculate PTK(ANonce, SNonce)*/ + WpaDerivePTK(pAd, + pmk_ptr, + pEntry->ANonce, + pEntry->Addr, + pEntry->SNonce, + pCurrentAddr, + PTK, + LEN_PTK); + + /* Save key to PTK entry*/ + NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK); + } + + /* Update WpaState*/ + pEntry->WpaState = AS_PTKINIT_NEGOTIATING; + + /* Allocate memory for output*/ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + /* Construct EAPoL message - Pairwise Msg 2*/ + /* EAPOL-Key(0,1,0,0,P,0,0,SNonce,MIC,DataKD_M2)*/ + ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_PAIR_MSG_2, + 0, /* DefaultKeyIdx*/ + pEntry->SNonce, + NULL, /* TxRsc*/ + NULL, /* GTK*/ + (UCHAR *)rsnie_ptr, + rsnie_len, + pEapolFrame); + + /* Make outgoing frame*/ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pCurrentAddr, EAPOL); + + RTMPToWirelessSta(pAd, pEntry, + Header802_3, sizeof(Header802_3), (PUCHAR)pEapolFrame, + CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, TRUE); + + os_free_mem(NULL, mpool); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg1Action: send Msg2 of 4-way \n")); +} + + +/* + ========================================================================== + Description: + When receiving the second packet of 4-way pairwisekey handshake. + Return: + ========================================================================== +*/ +VOID PeerPairMsg2Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR PTK[80]; + BOOLEAN Cancelled; + //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 */ + STA_TR_ENTRY *tr_entry; +#ifdef CONFIG_OWE_SUPPORT + UINT8 len_ptk = LEN_AES_PTK; +#endif + unsigned char hdr_len = LENGTH_802_11; +#ifdef A4_CONN + PHEADER_802_11 pHeader; +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg2Action \n")); + + if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry)) + return; + +#ifdef A4_CONN + /* pointer to 802.11 header*/ + pHeader = (PHEADER_802_11)Elem->Msg; + + if (pHeader->FC.FrDs == 1 && pHeader->FC.ToDs == 1) + hdr_len = LENGTH_802_11_WITH_ADDR4; +#endif + + if (Elem->MsgLen < (hdr_len + LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG)) + return; + + /* check Entry in valid State*/ + if (pEntry->WpaState < AS_PTKSTART) + return; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + struct wifi_dev *wdev; + if (pEntry->func_tb_idx >= pAd->ApCfg.BssidNum) + return; + else + apidx = pEntry->func_tb_idx; + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + pBssid = wdev->bssid; + +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + if ( (pEntry->AuthMode == Ndis802_11AuthModeOWE) || (pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK) ) + pmk_ptr = pEntry->PMK; + else + pmk_ptr = pAd->ApCfg.MBSSID[apidx].PMK; +#else + pmk_ptr = pAd->ApCfg.MBSSID[apidx].PMK; +#endif + gtk_ptr = pAd->ApCfg.MBSSID[apidx].GTK; + group_cipher = wdev->GroupKeyWepStatus; + default_key = wdev->DefaultKeyId; + + /* Get Group TxTsc form Asic*/ + RTMPGetTxTscFromAsic(pAd, apidx, TxTsc); + + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || (pEntry->AuthMode == Ndis802_11AuthModeWPAPSK)) + { + rsnie_len = pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0]; + rsnie_ptr = &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][0]; + } + else + { + if ((wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2)) + { + rsnie_len = pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1]; + rsnie_ptr = &pAd->ApCfg.MBSSID[apidx].RSN_IE[1][0]; + } + else + { +#ifdef CONFIG_HOTSPOT_R2 + if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.bASANEnable == 1) + { + printk("choose OSEN\n"); + rsnie_len = OSEN_IELEN; + rsnie_ptr = OSEN_IE; + } + else +#endif + { + rsnie_len = pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0]; + rsnie_ptr = &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][0]; + } + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + + + /* 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[hdr_len + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - hdr_len - LENGTH_802_1_H; + + /* Store SNonce*/ + NdisMoveMemory(pEntry->SNonce, pMsg2->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE); + +#ifdef CONFIG_OWE_SUPPORT + if ((pEntry->AuthMode == Ndis802_11AuthModeOWE) && (pEntry->key_deri_alg == SEC_KEY_DERI_SHA384)) + len_ptk = LEN_OWE_PTK_SHA384; +#endif +#ifdef DOT11R_FT_SUPPORT + if (IS_FT_RSN_STA(pEntry)) + { +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + UINT8 ptk_len; + + FT_DerivePMKR0(pmk_ptr, LEN_PMK, + (PUINT8)pAd->ApCfg.MBSSID[apidx].Ssid, + pAd->ApCfg.MBSSID[apidx].SsidLen, + pAd->ApCfg.MBSSID[apidx].FtCfg.FtMdId, + pAd->ApCfg.MBSSID[apidx].FtCfg.FtR0khId, + pAd->ApCfg.MBSSID[apidx].FtCfg.FtR0khIdLen, + pEntry->Addr, + pEntry->FT_PMK_R0, + pEntry->FT_PMK_R0_NAME); + + FT_DerivePMKR1(pEntry->FT_PMK_R0, + pEntry->FT_PMK_R0_NAME, + pBssid, /* R1KHID*/ + pEntry->Addr, /* S1KHID*/ + pEntry->FT_PMK_R1, + pEntry->FT_PMK_R1_NAME); + + if (pEntry->WepStatus == Ndis802_11TKIPEnable) + ptk_len = 32+32; + else + ptk_len = 32+16; + + FT_DerivePTK(pEntry->FT_PMK_R1, + pEntry->FT_PMK_R1_NAME, + pEntry->ANonce, + pEntry->SNonce, + pBssid, /* Bssid*/ + pEntry->Addr, /* sta mac*/ + ptk_len, + pEntry->PTK, + pEntry->PTK_NAME); + + } +#endif /* CONFIG_AP_SUPPORT */ + } + else +#endif /* DOT11R_FT_SUPPORT */ +#ifdef DOT11_SAE_SUPPORT + if (pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK) { + PMF_DerivePTK(pAd, + (UCHAR *)pmk_ptr, + pEntry->ANonce, + (UCHAR *)pBssid, + pEntry->SNonce, + pEntry->Addr, + PTK, + LEN_AES_PTK); + + NdisMoveMemory(pEntry->PTK, PTK, LEN_AES_PTK); + hex_dump("PTK", PTK, LEN_AES_PTK); + } else +#endif +#ifdef CONFIG_OWE_SUPPORT + if (pEntry->AuthMode == Ndis802_11AuthModeOWE) { + PMF_DerivePTK(pAd, + (UCHAR *)pmk_ptr, + pEntry->ANonce, + (UCHAR *)pBssid, + pEntry->SNonce, + pEntry->Addr, + PTK, + len_ptk); + + NdisMoveMemory(pEntry->PTK, PTK, LEN_AES_PTK); + hex_dump("OWE PTK", PTK, LEN_AES_PTK); + } else +#endif + +#ifdef DOT11W_PMF_SUPPORT + if ((CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_USE_SHA256))) + { + PMF_DerivePTK(pAd, + (UCHAR *)pmk_ptr, + pEntry->ANonce, + (UCHAR *)pBssid, + pEntry->SNonce, + pEntry->Addr, + PTK, + LEN_AES_PTK); /* Must is 48 bytes */ + + NdisMoveMemory(pEntry->PTK, PTK, LEN_AES_PTK); + hex_dump("PTK", PTK, LEN_AES_PTK); + } + else +#endif /* DOT11W_PMF_SUPPORT */ +#ifdef CONFIG_HOTSPOT_R2 + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_OSEN_CAPABLE)) + { + printk("got msg2 derivePTK\n"); + PMF_DerivePTK(pAd, + (UCHAR *)pmk_ptr, + pEntry->ANonce, + (UCHAR *)pBssid, + pEntry->SNonce, + pEntry->Addr, + PTK, + LEN_AES_PTK); /* Must is 48 bytes */ + + NdisMoveMemory(pEntry->PTK, PTK, LEN_AES_PTK); + hex_dump("PTK", PTK, LEN_AES_PTK); + } + else +#endif /* CONFIG_HOTSPOT_R2 */ + { + /* Derive PTK*/ + if ((pmk_ptr == NULL) || (pBssid == NULL)) + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: pmk_ptr or pBssid == NULL!\n", __FUNCTION__)); + return; + } + + WpaDerivePTK(pAd, + (UCHAR *)pmk_ptr, + pEntry->ANonce, /* ANONCE*/ + (UCHAR *)pBssid, + pEntry->SNonce, /* SNONCE*/ + pEntry->Addr, + PTK, + LEN_PTK); + + NdisMoveMemory(pEntry->PTK, PTK, LEN_PTK); + } + + /* Sanity Check peer Pairwise message 2 - Replay Counter, MIC, RSNIE*/ + if (PeerWpaMessageSanity(pAd, pMsg2, MsgLen, EAPOL_PAIR_MSG_2, pEntry) == FALSE) { +#ifdef WIFI_DIAG + if (IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_AUTH_FAIL, REASON_4WAY_HS_MSG2_FAIL); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + REASON_MIC_FAILURE); +#endif + return; + } + + do + { +#if defined(CONFIG_HOTSPOT) && defined(CONFIG_AP_SUPPORT) + UCHAR HSClientGTK[32]; +#endif + + /* Allocate memory for input*/ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + /* delete retry timer*/ + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + + /* Change state*/ + pEntry->WpaState = AS_PTKINIT_NEGOTIATING; + + /* Increment replay counter by 1*/ + ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); + +#if defined(CONFIG_HOTSPOT) && defined(CONFIG_AP_SUPPORT) + if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.HotSpotEnable && + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.DGAFDisable) + { + // Radom GTK for hotspot sation client */ + GenRandom(pAd, pEntry->Addr, HSClientGTK); + gtk_ptr = HSClientGTK; + + DBGPRINT(RT_DEBUG_OFF, ("%s:Random unique GTK for each mobile device when dgaf disable\n", __FUNCTION__)); + hex_dump("GTK", gtk_ptr, 32); + } +#endif + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + WPAInstallPairwiseKey(pAd, pEntry->func_tb_idx, pEntry, TRUE); +#endif + /* Construct EAPoL message - Pairwise Msg 3*/ + ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_PAIR_MSG_3, + default_key, + pEntry->ANonce, + TxTsc, + (UCHAR *)gtk_ptr, + (UCHAR *)rsnie_ptr, + rsnie_len, + pEapolFrame); + + /* Make outgoing frame*/ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3, + (PUCHAR)pEapolFrame, + CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, + (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE); + + pEntry->ReTryCounter = PEER_MSG3_RETRY_TIMER_CTR; + RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG1_RETRY_EXEC_INTV); + + + /* Update State*/ + pEntry->WpaState = AS_PTKINIT_NEGOTIATING; + + os_free_mem(NULL, mpool); + + }while(FALSE); + + DBGPRINT(RT_DEBUG_TRACE, ("<=== PeerPairMsg2Action: send Msg3 of 4-way \n")); +} + +VOID WPAPairMsg3Retry( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN ULONG TimeInterval +) +{ + BOOLEAN Cancelled; + PEAPOL_PACKET pEapolFrame; + UCHAR *mpool; + PUINT8 pBssid = NULL; + PUINT8 gtk_ptr = NULL; + UCHAR default_key = 0; + UCHAR group_cipher = Ndis802_11WEPDisabled; + PUINT8 rsnie_ptr = NULL; + //PUINT8 pmk_ptr = NULL; + UCHAR rsnie_len = 0; + UCHAR TxTsc[6]; + UCHAR Header802_3[LENGTH_802_3]; +#ifdef CONFIG_AP_SUPPORT + UCHAR apidx = 0; +#endif /* CONFIG_AP_SUPPORT */ +#if defined(CONFIG_HOTSPOT) && defined(CONFIG_AP_SUPPORT) + UCHAR HSClientGTK[32]; +#endif + STA_TR_ENTRY *tr_entry; + + DBGPRINT(RT_DEBUG_TRACE, ("===> %s \n",__FUNCTION__)); +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + struct wifi_dev *wdev; + if (pEntry->func_tb_idx>= pAd->ApCfg.BssidNum) + return; + else + apidx = pEntry->func_tb_idx; + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + pBssid = wdev->bssid; + //pmk_ptr = pAd->ApCfg.MBSSID[apidx].PMK; + gtk_ptr = pAd->ApCfg.MBSSID[apidx].GTK; + group_cipher = wdev->GroupKeyWepStatus; + default_key = wdev->DefaultKeyId; + + /* Get Group TxTsc form Asic*/ + RTMPGetTxTscFromAsic(pAd, apidx, TxTsc); + + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA) || (pEntry->AuthMode == Ndis802_11AuthModeWPAPSK)) + { + rsnie_len = pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0]; + rsnie_ptr = &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][0]; + } + else + { + if ((wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2)) + { + rsnie_len = pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1]; + rsnie_ptr = &pAd->ApCfg.MBSSID[apidx].RSN_IE[1][0]; + } + else + { + rsnie_len = pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0]; + rsnie_ptr = &pAd->ApCfg.MBSSID[apidx].RSN_IE[0][0]; + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + + /* Allocate memory for input*/ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + /* delete retry timer*/ + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + + /* Change state*/ + pEntry->WpaState = AS_PTKINIT_NEGOTIATING; + + /* Increment replay counter by 1*/ + ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); + +#if defined(CONFIG_HOTSPOT) && defined(CONFIG_AP_SUPPORT) + if (pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.HotSpotEnable && + pAd->ApCfg.MBSSID[apidx].HotSpotCtrl.DGAFDisable) + { + // Radom GTK for hotspot sation client */ + GenRandom(pAd, pEntry->Addr, HSClientGTK); + gtk_ptr = HSClientGTK; + + DBGPRINT(RT_DEBUG_OFF, ("%s:Random unique GTK for each mobile device when dgaf disable\n", __FUNCTION__)); + hex_dump("GTK", gtk_ptr, 32); + } +#endif + /* Construct EAPoL message - Pairwise Msg 3*/ + ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_PAIR_MSG_3, + default_key, + pEntry->ANonce, + TxTsc, + (UCHAR *)gtk_ptr, + (UCHAR *)rsnie_ptr, + rsnie_len, + pEapolFrame); + + /* Make outgoing frame*/ + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + RTMPToWirelessSta(pAd, pEntry, Header802_3, LENGTH_802_3, + (PUCHAR)pEapolFrame, + CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, + (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED) ? FALSE : TRUE); + + RTMPSetTimer(&pEntry->RetryTimer, TimeInterval); + + /* Update State*/ + pEntry->WpaState = AS_PTKINIT_NEGOTIATING; + + os_free_mem(NULL, mpool); + +} + +/* + ======================================================================== + + Routine Description: + Process Pairwise key Msg 3 of 4-way handshaking and send Msg 4 + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID PeerPairMsg3Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem) +{ + //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 MAC_REPEATER_SUPPORT + USHORT ifIndex = (USHORT)(Elem->Priv); + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + STA_TR_ENTRY *tr_entry; + UCHAR idx = 0; + BOOLEAN bWPA2 = FALSE; +#if (defined(MAP_SUPPORT) && defined(WAPP_SUPPORT)) || defined(MWDS) + PAPCLI_STRUCT pApCliEntry; +#endif + unsigned char hdr_len = LENGTH_802_11; +#ifdef A4_CONN + PHEADER_802_11 pHeader; +#endif + /* Choose WPA2 or not*/ + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + || (pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK) + || (pEntry->AuthMode == Ndis802_11AuthModeOWE) +#endif + ) + bWPA2 = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg3Action \n")); + + if ((!pEntry) || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry))) + return; + +#ifdef A4_CONN + pHeader = (PHEADER_802_11) Elem->Msg; + + if (pHeader->FC.FrDs == 1 && pHeader->FC.ToDs == 1) + hdr_len = LENGTH_802_11_WITH_ADDR4; +#endif + + if (Elem->MsgLen < (hdr_len + 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->func_tb_idx; +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + CliIdx = ((ifIndex - 64) % 16); +#endif /* MAC_REPEATER_SUPPORT */ + + if (IfIndex >= MAX_APCLI_NUM) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pCurrentAddr = pAd->ApCfg.ApCliTab[IfIndex].RepeaterCli[CliIdx].CurrentAddress; + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrentAddr = pAd->ApCfg.ApCliTab[IfIndex].wdev.if_addr; + group_cipher = pAd->ApCfg.ApCliTab[IfIndex].GroupCipher; + + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + if (pCurrentAddr == NULL) + return; + + /* Record 802.11 header & the received EAPOL packet Msg3*/ + //pHeader = (PHEADER_802_11) Elem->Msg; + pMsg3 = (PEAPOL_PACKET)&Elem->Msg[hdr_len + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - hdr_len - LENGTH_802_1_H; + + /* Sanity Check peer Pairwise message 3 - Replay Counter, MIC, RSNIE*/ + if (PeerWpaMessageSanity(pAd, pMsg3, MsgLen, EAPOL_PAIR_MSG_3, pEntry) == FALSE) + return; + + if ((pEntry->AllowInsPTK == TRUE) && bWPA2) { + UCHAR kid = pEntry->LastGroupKeyId; + + if (unlikely(kid >= ARRAY_SIZE(pEntry->CCMP_BC_PN))) { + DBGPRINT(RT_DEBUG_TRACE, ("%s invalid key id %u\n", __func__, kid)); + return; + } + + pEntry->CCMP_BC_PN[kid] = 0; + for (idx = 0; idx < (LEN_KEY_DESC_RSC - 2); idx++) + pEntry->CCMP_BC_PN[kid] += ((UINT64)pMsg3->KeyDesc.KeyRsc[idx] << (idx*8)); + pEntry->AllowUpdateRSC = FALSE; + pEntry->Init_CCMP_BC_PN_Passed[kid] = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d)-%d: update CCMP_BC_PN to %llu\n", + __func__, pEntry->wcid, kid, pEntry->CCMP_BC_PN[kid])); + } + + /* Save Replay counter, it will use construct message 4*/ + NdisMoveMemory(pEntry->R_Counter, pMsg3->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + /* Double check ANonce*/ + if (!NdisEqualMemory(pEntry->ANonce, pMsg3->KeyDesc.KeyNonce, LEN_KEY_DESC_NONCE)) + { + return; + } + + /* Allocate memory for output*/ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + /* Construct EAPoL message - Pairwise Msg 4*/ + ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_PAIR_MSG_4, + 0, /* group key index not used in message 4*/ + NULL, /* Nonce not used in message 4*/ + NULL, /* TxRSC not used in message 4*/ + NULL, /* GTK not used in message 4*/ + NULL, /* RSN IE not used in message 4*/ + 0, + pEapolFrame); + + /* Update WpaState*/ + pEntry->WpaState = AS_PTKINITDONE; + /* Update pairwise key */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) { + if(pEntry->AllowInsPTK == TRUE) { + APCliInstallPairwiseKey(pAd, pEntry); + pEntry->AllowInsPTK = FALSE; + pEntry->AllowUpdateRSC = TRUE; + } else { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : the M3 reinstall attack, skip install key\n", + __func__)); + } + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + /* open 802.1x port control and privacy filter*/ + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + if (tr_entry && (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK || + pEntry->AuthMode == Ndis802_11AuthModeWPA2 +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + || pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK + || pEntry->AuthMode == Ndis802_11AuthModeOWE +#endif + )) + { + tr_entry->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 */ +#if (defined(MAP_SUPPORT) && defined(WAPP_SUPPORT)) || defined(MWDS) + pApCliEntry = &pAd->ApCfg.ApCliTab[pEntry->func_tb_idx]; +#endif +#if defined(MAP_SUPPORT) && defined(WAPP_SUPPORT) + if (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)/*For security AES case*/ + wapp_send_apcli_association_change(WAPP_APCLI_ASSOCIATED, pAd, pApCliEntry); +#endif /*WAPP_SUPPORT*/ +#if defined(MWDS) || defined(MAP_SUPPORT) + if (pEntry && (pEntry->func_tb_idx < MAX_APCLI_NUM) && tr_entry) { + if (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED) { +#ifdef MWDS + MWDSAPCliPeerEnable(pAd, pApCliEntry, pEntry); +#endif + } + } +#endif /* defined(MWDS) || defined(MAP_SUPPORT) */ +#ifdef WH_EVENT_NOTIFIER + if (pEntry && tr_entry && + (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + EventHdlr pEventHdlrHook = NULL; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_EXT_UPLINK_STAT); + if(pEventHdlrHook && pEntry->wdev) + pEventHdlrHook(pAd, pEntry, (UINT32)WHC_UPLINK_STAT_CONNECTED); + } +#endif /* WH_EVENT_NOTIFIER */ +#endif /* APLCI_SUPPORT */ + } +#endif /* CONFIG_AP_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); + + +#ifdef WH_EZ_SETUP + if( (IS_EZ_SETUP_ENABLED(pEntry->wdev)) && (IS_ENTRY_APCLI(pEntry)) ){ + //! Should be done in handle pair four + // EZ_UPDATE_CAPABILITY_INFO(pAd, EZ_SET_ACTION, CONNECTED, pEntry->func_tb_idx); + // ez_apclient_info_action_frame(pAd, pEntry->wdev); +#ifdef NEW_CONNECTION_ALGO + /*APCLI has connected to a non-easy setup AP, allocate itself a new node number according to the MAC address of the root AP and its own aid.*/ + ez_handle_pairmsg4(pAd, pEntry); +#endif + } +#endif /* WIDI_SUPPORT */ + + +#ifdef APCLI_OWE_SUPPORT + if (IS_ENTRY_APCLI(pEntry) && pEntry->AuthMode == Ndis802_11AuthModeOWE) { + OWE_INFO *owe = &pEntry->owe; + UINT pmk_len = LEN_PMK; + UCHAR intf_idx = pEntry->func_tb_idx; + UCHAR CliIdx = 0xff; + + if (pEntry->key_deri_alg == SEC_KEY_DERI_SHA384) + pmk_len = LEN_PMK_SHA384; + +#ifdef MAC_REPEATER_SUPPORT + if (pEntry->bReptCli == TRUE) { + intf_idx = pEntry->MatchReptCliIdx; + CliIdx = pEntry->MatchReptCliIdx; + } +#endif + + if (owe->pmkid) { + apcli_add_pmkid_cache(pAd, pEntry->Addr, owe->pmkid, + pEntry->PMK, pmk_len, intf_idx +#ifdef MAC_REPEATER_SUPPORT + , CliIdx +#endif + ); + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_ERROR, + ("Store PMKID for MAC=>0x%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pEntry->Addr))); + hex_dump("PMK cache ID", owe->pmkid, LEN_PMKID); + hex_dump("PMK key", pEntry->PMK, pmk_len); + } + + } +#endif + +#ifdef APCLI_OWE_SUPPORT + if (pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK) + set_sae_instance_removable(&pAd->SaeCfg, pAd->CurrentAddress, pEntry->Addr); +#endif + + + 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; +#ifdef DBG + UCHAR group_cipher = Ndis802_11WEPDisabled; +#endif /* DBG */ + STA_TR_ENTRY *tr_entry; + unsigned char hdr_len = LENGTH_802_11; +#ifdef A4_CONN + PHEADER_802_11 pHeader; +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("===> PeerPairMsg4Action\n")); + + do + { + if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry)) + break; + +#ifdef A4_CONN + pHeader = (PHEADER_802_11)Elem->Msg; + if (pHeader->FC.FrDs == 1 && pHeader->FC.ToDs == 1) + hdr_len = LENGTH_802_11_WITH_ADDR4; +#endif + + if (Elem->MsgLen < (hdr_len + LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG)) + break; + + if (pEntry->WpaState < AS_PTKINIT_NEGOTIATING) + break; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef DBG + UCHAR apidx = 0; +#endif /* DBG */ + if (pEntry->func_tb_idx >= pAd->ApCfg.BssidNum) + break; + else + { +#ifdef DBG + apidx = pEntry->func_tb_idx; + group_cipher = pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus; +#endif /* DBG */ + } + + + } +#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[hdr_len + LENGTH_802_1_H]; + MsgLen = Elem->MsgLen - hdr_len - LENGTH_802_1_H; + + /* Sanity Check peer Pairwise message 4 - Replay Counter, MIC*/ + if (PeerWpaMessageSanity(pAd, pMsg4, MsgLen, EAPOL_PAIR_MSG_4, pEntry) == FALSE) { +#ifdef WIFI_DIAG + if (IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_AUTH_FAIL, REASON_4WAY_HS_MSG4_FAIL); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + REASON_MIC_FAILURE); +#endif + break; + } + + /* 3. Install pairwise key */ +#ifdef MT_MAC + if (pAd->chipCap.hif_type != HIF_MT) +#endif + WPAInstallPairwiseKey(pAd, pEntry->func_tb_idx, pEntry, TRUE); + + /* 4. upgrade state */ + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + pEntry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + pEntry->WpaState = AS_PTKINITDONE; + tr_entry->PortSecured = WPA_802_1X_PORT_SECURED; + +#ifdef WSC_AP_SUPPORT + if (pAd->ApCfg.MBSSID[pEntry->func_tb_idx].WscControl.WscConfMode != WSC_DISABLE) + WscInformFromWPA(pEntry); +#endif /* WSC_AP_SUPPORT */ + + if (pEntry->AuthMode == Ndis802_11AuthModeWPA2 || + pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK +#ifdef DOT11_SAE_SUPPORT + || pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK +#endif +#ifdef CONFIG_OWE_SUPPORT + || pEntry->AuthMode == Ndis802_11AuthModeOWE +#endif + ) { + pEntry->GTKState = REKEY_ESTABLISHED; + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + +#ifdef CONFIG_AP_SUPPORT +#ifdef DOT11R_FT_SUPPORT + if (IS_FT_RSN_STA(pEntry)) + { + PFT_R1HK_ENTRY pR1khEntry; + PUINT8 pUCipher = NULL; + PUINT8 pAkm = NULL; + UINT8 count; + + pUCipher = WPA_ExtractSuiteFromRSNIE(pEntry->RSN_IE, pEntry->RSNIE_Len, PAIRWISE_SUITE, &count); + pAkm = WPA_ExtractSuiteFromRSNIE(pEntry->RSN_IE, pEntry->RSNIE_Len, AKM_SUITE, &count); + + /* Record the PMK-R0 related information */ + RTMPAddPMKIDCache(pAd, + pEntry->func_tb_idx, + pEntry->Addr, + pEntry->FT_PMK_R0_NAME, + pEntry->FT_PMK_R0 +#ifdef CONFIG_OWE_SUPPORT + , LEN_PMK +#endif + ); + + /* Delete previous entry */ + pR1khEntry = FT_R1khEntryTabLookup(pAd, pEntry->FT_PMK_R1_NAME); + if (pR1khEntry != NULL) + { + FT_R1khEntryDelete(pAd, pR1khEntry); + } + /* Update R1KH table */ + if (pUCipher != NULL) + NdisMoveMemory(pEntry->FT_UCipher, pUCipher, 4); + if (pAkm != NULL) + NdisMoveMemory(pEntry->FT_Akm, pAkm, 4); + + FT_R1khEntryInsert(pAd, + pEntry->FT_PMK_R0_NAME, + pEntry->FT_PMK_R1_NAME, + pEntry->FT_PMK_R1, + pUCipher, + pAkm, + (pAd->ApCfg.MBSSID[pEntry->func_tb_idx].PMKCachePeriod/OS_HZ), + FT_REASSOC_DEADLINE, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].FtCfg.FtR0khId, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].FtCfg.FtR0khIdLen, + pEntry->Addr); + +#ifdef IAPP_SUPPORT + { + FT_KDP_EVT_ASSOC EvtAssoc; + + EvtAssoc.SeqNum = 0; + NdisMoveMemory(EvtAssoc.MacAddr, pEntry->Addr, MAC_ADDR_LEN); +#ifdef WH_EZ_SETUP + if (!IS_EZ_SETUP_ENABLED(&pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev) /*&& !ez_is_triband()*/) +#endif + { + FT_KDP_EVENT_INFORM(pAd, + pEntry->func_tb_idx, + FT_KDP_SIG_FT_ASSOCIATION, + &EvtAssoc, + sizeof(EvtAssoc), + NULL); + } + } +#endif /* IAPP_SUPPORT */ + + pR1khEntry = FT_R1khEntryTabLookup(pAd, pEntry->FT_PMK_R1_NAME); + if (pR1khEntry != NULL) + { + hex_dump("R1KHTab-R0KHID", pR1khEntry->R0khId, pR1khEntry->R0khIdLen); + hex_dump("R1KHTab-PairwiseCipher", pR1khEntry->PairwisChipher, 4); + hex_dump("R1KHTab-AKM", pR1khEntry->AkmSuite, 4); + hex_dump("R1KHTab-PMKR0Name", pR1khEntry->PmkR0Name, 16); + hex_dump("R1KHTab-PMKR1Name", pR1khEntry->PmkR1Name, 16); + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("The entry in R1KH table doesn't exist\n")); + } + } + else +#endif /* DOT11R_FT_SUPPORT */ +#ifdef DOT1X_SUPPORT + if (pEntry->AuthMode == Ndis802_11AuthModeWPA2) + { + UCHAR PMK_key[20]; + UCHAR digest[80]; + + /* Calculate PMKID, refer to IEEE 802.11i-2004 8.5.1.2*/ + NdisMoveMemory(&PMK_key[0], "PMK Name", 8); + NdisMoveMemory(&PMK_key[8], pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid, MAC_ADDR_LEN); + NdisMoveMemory(&PMK_key[14], pEntry->Addr, MAC_ADDR_LEN); + RT_HMAC_SHA1(pAd->ApCfg.MBSSID[pEntry->func_tb_idx].PMK, PMK_LEN, PMK_key, 20, digest, SHA1_DIGEST_SIZE); + RTMPAddPMKIDCache(pAd, pEntry->func_tb_idx, pEntry->Addr, + digest, pAd->ApCfg.MBSSID[pEntry->func_tb_idx].PMK +#ifdef CONFIG_OWE_SUPPORT + , LEN_PMK +#endif + ); + DBGPRINT(RT_DEBUG_TRACE, ("Calc PMKID=%02x:%02x:%02x:%02x:%02x:%02x\n", digest[0],digest[1],digest[2],digest[3],digest[4],digest[5])); + } +#endif /* DOT1X_SUPPORT */ +#ifdef DOT11_SAE_SUPPORT + else if (pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK) + set_sae_instance_removable(&pAd->SaeCfg, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid, + pEntry->Addr); +#endif + +#ifdef CONFIG_OWE_SUPPORT + else if (pEntry->AuthMode == Ndis802_11AuthModeOWE) { + INT CacheIdx;/* Key cache */ + + if (pEntry->owe.pmkid) { + UINT8 pmk_len = LEN_PMK; + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx]; + + if (pEntry->key_deri_alg == SEC_KEY_DERI_SHA384) + pmk_len = LEN_PMK_SHA384; + + CacheIdx = RTMPSearchPMKIDCache(pAd, pEntry->func_tb_idx, pEntry->Addr); + if ((CacheIdx == -1) || + ((RTMPEqualMemory(pEntry->owe.pmkid, + &pMbss->PMKIDCache.BSSIDInfo[CacheIdx].PMKID, + pmk_len)) == 0)) { + CacheIdx = -1; + } + hex_dump("store pmkid:", pEntry->owe.pmkid, LEN_PMKID); + RTMPAddPMKIDCache(pAd, + pEntry->func_tb_idx, + pEntry->Addr, + pEntry->owe.pmkid, + pEntry->PMK, + pmk_len); + /* store_pmkid_cache_in_sec_config(pAd, pEntry, CacheIdx); */ + } + } +#endif /*CONFIG_OWE_SUPPORT*/ + + +#endif /* CONFIG_AP_SUPPORT */ +#if defined(MWDS) || defined(MAP_SUPPORT) || defined(WAPP_SUPPORT) + if (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED) { +#ifdef MWDS + MWDSAPPeerEnable(pAd, pEntry); +#endif + +#ifdef WAPP_SUPPORT + wapp_send_cli_join_event(pAd, pEntry); +#endif + } +#endif + +#ifdef WH_EVENT_NOTIFIER + if (pEntry && tr_entry && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + EventHdlr pEventHdlrHook = NULL; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_STA_JOIN); + if(pEventHdlrHook && pEntry->wdev) + pEventHdlrHook(pAd, pEntry, Elem); + } +#endif /* WH_EVENT_NOTIFIER */ + + /* send wireless event - for set key done WPA2*/ + RTMPSendWirelessEvent(pAd, IW_SET_KEY_DONE_WPA2_EVENT_FLAG, pEntry->Addr, pEntry->wdev->wdev_idx, 0); + +#ifdef CONFIG_HOTSPOT_R2 + if (pEntry->IsWNMReqValid == TRUE) + { + struct wnm_req_data *req_data = pEntry->ReqData; + Send_WNM_Notify_Req(pAd, + req_data->peer_mac_addr, + req_data->wnm_req, + req_data->wnm_req_len, + req_data->type); + + pEntry->IsWNMReqValid = FALSE; + os_free_mem(NULL, req_data); + printk("!!!!msg 4 send wnm req\n"); + } + if (pEntry->IsBTMReqValid == TRUE) + { + struct btm_req_data *req_data = pEntry->ReqbtmData; + Send_BTM_Req(pAd, + req_data->peer_mac_addr, + req_data->btm_req, + req_data->btm_req_len); + + pEntry->IsBTMReqValid = FALSE; + os_free_mem(NULL, req_data); + printk("!!!!msg 4 send btm req\n"); + } +#endif + +#ifdef MBO_SUPPORT + /* update STA bssid & security info to daemon */ + MboIndicateStaBssidInfo(pAd, &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev, pEntry->Addr); +#endif/* MBO_SUPPORT */ + DBGPRINT(RT_DEBUG_TRACE, ("AP SETKEYS DONE - WPA2, AuthMode(%d)=%s, WepStatus(%d)=%s, GroupWepStatus(%d)=%s\n\n", + pEntry->AuthMode, GetAuthMode(pEntry->AuthMode), + pEntry->WepStatus, GetEncryptType(pEntry->WepStatus), + group_cipher, + GetEncryptType(group_cipher))); + } + else + { + /* 5. init Group 2-way handshake if necessary.*/ + WPAStart2WayGroupHS(pAd, pEntry); + + pEntry->ReTryCounter = GROUP_MSG1_RETRY_TIMER_CTR; + + /* retry timer is set inside WPAStart2WayGroupHS */ + //RTMPModTimer(&pEntry->RetryTimer, PEER_MSG3_RETRY_EXEC_INTV); + + } + }while(FALSE); + +} + +/* + ========================================================================== + Description: + This is a function to send the first packet of 2-way groupkey handshake + Return: + + ========================================================================== +*/ +VOID WPAStart2WayGroupHS( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + UCHAR Header802_3[14]; + UCHAR TxTsc[6]; + UCHAR *mpool; + PEAPOL_PACKET pEapolFrame; + UCHAR group_cipher = Ndis802_11WEPDisabled; + UCHAR default_key = 0; + PUINT8 gnonce_ptr = NULL; + PUINT8 gtk_ptr = NULL; + PUINT8 pBssid = NULL; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("===> WPAStart2WayGroupHS\n")); + + if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry)) + return; + + /* delete retry timer*/ + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + UCHAR apidx = 0; + + if (pEntry->func_tb_idx >= pAd->ApCfg.BssidNum) + return; + else + apidx = pEntry->func_tb_idx; + + group_cipher = pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus; + default_key = pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId; + gnonce_ptr = pAd->ApCfg.MBSSID[apidx].GNonce; + gtk_ptr = pAd->ApCfg.MBSSID[apidx].GTK; + pBssid = pAd->ApCfg.MBSSID[apidx].wdev.bssid; + + /* Get Group TxTsc form Asic*/ + RTMPGetTxTscFromAsic(pAd, apidx, TxTsc); + } +#endif /* CONFIG_AP_SUPPORT */ + + /* Allocate memory for output*/ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + /* Increment replay counter by 1*/ + ADD_ONE_To_64BIT_VAR(pEntry->R_Counter); + + /* Construct EAPoL message - Group Msg 1*/ + ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_GROUP_MSG_1, + default_key, + (UCHAR *)gnonce_ptr, + TxTsc, + (UCHAR *)gtk_ptr, + NULL, + 0, + pEapolFrame); + + /* Make outgoing frame*/ + if (pBssid == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pBssid == NULL!\n", __FUNCTION__)); + return; + } + + MAKE_802_3_HEADER(Header802_3, pEntry->Addr, pBssid, EAPOL); + RTMPToWirelessSta(pAd, pEntry, + Header802_3, LENGTH_802_3, + (PUCHAR)pEapolFrame, + CONV_ARRARY_TO_UINT16(pEapolFrame->Body_Len) + 4, FALSE); + + os_free_mem(NULL, mpool); + + RTMPSetTimer(&pEntry->RetryTimer, PEER_MSG1_RETRY_EXEC_INTV); + DBGPRINT(RT_DEBUG_TRACE, ("<=== WPAStart2WayGroupHS : send out Group Message 1 \n")); + + return; +} + +/* + ======================================================================== + + Routine Description: + Process Group key 2-way handshaking + + Arguments: + pAd Pointer to our adapter + Elem Message body + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID PeerGroupMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Header802_3[14]; + UCHAR *mpool; + PEAPOL_PACKET pEapolFrame; + PEAPOL_PACKET pGroup; + UINT MsgLen; + UCHAR default_key = 0; + UCHAR group_cipher = Ndis802_11WEPDisabled; + PUINT8 pCurrentAddr = NULL; +#ifdef APCLI_SUPPORT + BOOLEAN Cancelled; +#endif /* APCLI_SUPPORT */ +#ifdef MAC_REPEATER_SUPPORT + USHORT ifIndex = (USHORT)(Elem->Priv); + UCHAR CliIdx = 0xFF; +#endif /* MAC_REPEATER_SUPPORT */ + STA_TR_ENTRY *tr_entry; + UCHAR idx = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg1Action \n")); + + if ((!pEntry) || (!IS_ENTRY_CLIENT(pEntry) && !IS_ENTRY_APCLI(pEntry))) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (ifIndex >= 64) + CliIdx = ((ifIndex - 64) % 16); +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + { + UINT IfIndex = 0; + + IfIndex = pEntry->func_tb_idx; + if (IfIndex >= MAX_APCLI_NUM) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (CliIdx != 0xFF) + pCurrentAddr = pAd->ApCfg.ApCliTab[IfIndex].RepeaterCli[CliIdx].CurrentAddress; + else +#endif /* MAC_REPEATER_SUPPORT */ + pCurrentAddr = pAd->ApCfg.ApCliTab[IfIndex].wdev.if_addr; + group_cipher = pAd->ApCfg.ApCliTab[IfIndex].GroupCipher; + default_key = pAd->ApCfg.ApCliTab[IfIndex].wdev.DefaultKeyId; + + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + 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) { +#ifdef WIFI_DIAG + if (IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_AUTH_FAIL, REASON_2WAY_HS_MSG1_FAIL); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + REASON_MIC_FAILURE); +#endif + return; + } + + if (pEntry->AllowUpdateRSC == TRUE) { + UCHAR kid = pEntry->LastGroupKeyId; + + if (unlikely(kid >= ARRAY_SIZE(pEntry->CCMP_BC_PN))) { + DBGPRINT(RT_DEBUG_TRACE, ("%s invalid key id %u\n", __func__, kid)); + return; + } + + pEntry->CCMP_BC_PN[kid] = 0; + for (idx = 0; idx < (LEN_KEY_DESC_RSC - 2); idx++) + pEntry->CCMP_BC_PN[kid] += ((UINT64)pGroup->KeyDesc.KeyRsc[idx] << (idx*8)); + pEntry->AllowUpdateRSC = FALSE; + pEntry->Init_CCMP_BC_PN_Passed[kid] = FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d)-%d: update CCMP_BC_PN to %llu\n", + __func__, pEntry->wcid, kid, pEntry->CCMP_BC_PN[kid])); + } + + /* delete retry timer*/ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + /* Patch issue with gateway AP*/ + /* In WPA mode, AP doesn't send out message 1 of group-key HS.*/ + /* So, Supplicant shall maintain a timeout action to disconnect */ + /* this link.*/ + /* Todo - Does it need to apply to STA ?*/ + if (IS_ENTRY_APCLI(pEntry)) + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + /* Save Replay counter, it will use to construct message 2*/ + NdisMoveMemory(pEntry->R_Counter, pGroup->KeyDesc.ReplayCounter, LEN_KEY_DESC_REPLAY); + + /* Allocate memory for output*/ + os_alloc_mem(NULL, (PUCHAR *)&mpool, TX_EAPOL_BUFFER); + if (mpool == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : no memory!!!\n", __FUNCTION__)); + return; + } + + pEapolFrame = (PEAPOL_PACKET)mpool; + NdisZeroMemory(pEapolFrame, TX_EAPOL_BUFFER); + + + /* Construct EAPoL message - Group Msg 2*/ + ConstructEapolMsg(pEntry, + group_cipher, + EAPOL_GROUP_MSG_2, + default_key, + NULL, /* Nonce not used*/ + NULL, /* TxRSC not used*/ + NULL, /* GTK not used*/ + NULL, /* RSN IE not used*/ + 0, + pEapolFrame); + + /* open 802.1x port control and privacy filter*/ + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + tr_entry->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 */ +#ifdef APCLI_SUPPORT +#ifdef WH_EVENT_NOTIFIER + if(pEntry && + IS_ENTRY_APCLI(pEntry)) + { + STA_TR_ENTRY *tr_entry = NULL; + EventHdlr pEventHdlrHook = NULL; + if(VALID_TR_WCID(pEntry->wcid)) + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + if(tr_entry && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_EXT_UPLINK_STAT); + if(pEventHdlrHook && pEntry->wdev) + pEventHdlrHook(pAd, pEntry, (UINT32)WHC_UPLINK_STAT_CONNECTED); + } + } +#endif /* WH_EVENT_NOTIFIER */ +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_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); + + + 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 == NULL) + return; + + if ((pEntry) && IS_ENTRY_CLIENT(pEntry) && (pEntry->WpaState < AS_PTKSTART)) + { + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pEntry->pAd; + + switch (pEntry->EnqueueEapolStartTimerRunning) + { + case EAPOL_START_PSK: + DBGPRINT(RT_DEBUG_TRACE, ("Enqueue EAPoL-Start-PSK for sta(%02x:%02x:%02x:%02x:%02x:%02x) \n", PRINT_MAC(pEntry->Addr))); + +#ifdef EAPOL_QUEUE_SUPPORT + EAPMlmeEnqueue(pAd, WPA_STATE_MACHINE, MT2_EAPOLStart, 6, &pEntry->Addr, 0); +#else /* EAPOL_QUEUE_SUPPORT */ + MlmeEnqueue(pAd, WPA_STATE_MACHINE, MT2_EAPOLStart, 6, &pEntry->Addr, 0); +#endif /* !EAPOL_QUEUE_SUPPORT */ + + RTMP_MLME_HANDLER(pAd); + break; +#ifdef CONFIG_AP_SUPPORT +#ifdef DOT1X_SUPPORT + case EAPOL_START_1X: + DBGPRINT(RT_DEBUG_TRACE, ("Enqueue EAPoL-Start-1X for sta(%02x:%02x:%02x:%02x:%02x:%02x) \n", PRINT_MAC(pEntry->Addr))); + + DOT1X_EapTriggerAction(pAd, pEntry); + break; +#endif /* DOT1X_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + default: + break; + + } + } + pEntry->EnqueueEapolStartTimerRunning = EAPOL_START_DISABLE; + +} + + +VOID MlmeDeAuthAction( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN USHORT Reason, + IN BOOLEAN bDataFrameFirst) +{ + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + HEADER_802_11 DeAuthHdr; + NDIS_STATUS NStatus; + + if (pEntry) + { + /* Send out a Deauthentication request frame*/ + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + /* send wireless event - for send disassication */ + RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pEntry->Addr, pEntry->wdev->wdev_idx, 0); + +#ifdef ALL_NET_EVENT + wext_send_event(pEntry->wdev->if_dev, + pEntry->Addr, + pEntry->bssid, + pAd->CommonCfg.Channel, + RTMPAvgRssi(pAd, &pEntry->RssiSample), + FBT_LINK_OFFLINE_NOTIFY); +#endif /* ALL_NET_EVENT */ + + DBGPRINT(RT_DEBUG_TRACE, + ("Send DEAUTH frame with ReasonCode(%d) to %02x:%02x:%02x:%02x:%02x:%02x \n", + Reason, PRINT_MAC(pEntry->Addr))); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + MgtMacHeaderInit(pAd, &DeAuthHdr, SUBTYPE_DEAUTH, 0, pEntry->Addr, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.if_addr, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid); + } +#endif /* CONFIG_AP_SUPPORT */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &DeAuthHdr, + 2, &Reason, + END_OF_ARGS); + +#ifdef DOT11W_PMF_SUPPORT + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE)) + { + ULONG TmpLen; + UINT res_len = LEN_CCMP_HDR + LEN_CCMP_MIC; + UCHAR res_buf[res_len]; + + /* reserve a buffer for PMF CCMP calculation later */ + MakeOutgoingFrame(pOutBuffer + FrameLen, &TmpLen, + res_len, res_buf, + END_OF_ARGS); + FrameLen += TmpLen; + + /* Indicate this is a unicast Robust management frame */ + DeAuthHdr.FC.Wep = 1; + } +#endif /* DOT11_PMF_SUPPORT */ + + + if (bDataFrameFirst) + MiniportMMRequest(pAd, MGMT_USE_QUEUE_FLAG, pOutBuffer, FrameLen); + else + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + +#ifdef WIFI_DIAG + if (IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_ERROR_MAX, Reason); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + Reason); +#endif + + /* ApLogEvent(pAd, pEntry->Addr, EVENT_DISASSOCIATED);*/ +#ifdef CONFIG_HOTSPOT_R2 + if (!pEntry->IsKeep) +#endif /* CONFIG_HOTSPOT_R2 */ + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + } +} + + +/* + ========================================================================== + Description: + When receiving the last packet of 2-way groupkey handshake. + Return: + ========================================================================== +*/ +VOID PeerGroupMsg2Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN VOID *Msg, + IN UINT MsgLen) +{ + UINT Len; + PUCHAR pData; + BOOLEAN Cancelled; + PEAPOL_PACKET pMsg2; +#ifdef DBG + UCHAR group_cipher = Ndis802_11WEPDisabled; +#endif /* DBG */ + + DBGPRINT(RT_DEBUG_TRACE, ("===> PeerGroupMsg2Action \n")); + + if ((!pEntry) || !IS_ENTRY_CLIENT(pEntry)) + return; + + if (MsgLen < (LENGTH_802_1_H + LENGTH_EAPOL_H + MIN_LEN_OF_EAPOL_KEY_MSG)) + return; + + if (pEntry->WpaState != AS_PTKINITDONE) + return; + + + do + { + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef DBG + UCHAR apidx = 0; +#endif /* DBG */ + if (pEntry->func_tb_idx >= pAd->ApCfg.BssidNum) + return; + else + { +#ifdef DBG + apidx = pEntry->func_tb_idx; + group_cipher = pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus; +#endif /* DBG */ + } + } +#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) { +#ifdef WIFI_DIAG + if (IS_ENTRY_CLIENT(pEntry)) + DiagConnError(pAd, pEntry->func_tb_idx, pEntry->Addr, + DIAG_CONN_AUTH_FAIL, REASON_2WAY_HS_MSG2_FAIL); +#endif +#ifdef CONN_FAIL_EVENT + if (IS_ENTRY_CLIENT(pEntry)) + ApSendConnFailMsg(pAd, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pEntry->Addr, + REASON_MIC_FAILURE); +#endif + break; + } + + /* 3. upgrade state*/ + + RTMPCancelTimer(&pEntry->RetryTimer, &Cancelled); + pEntry->GTKState = REKEY_ESTABLISHED; +#ifdef CONFIG_PUSH_SUPPORT + if (VALID_TR_WCID(pEntry->wcid)) + { + EventHdlr pEventHdlrHook = NULL; + STA_TR_ENTRY *tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + if(tr_entry && (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_STA_JOIN); + if(pEventHdlrHook && pEntry->wdev) + pEventHdlrHook(pAd, pEntry, pAd->CommonCfg.Channel); + } + } +#endif /* CONFIG_PUSH_SUPPORT */ + + 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->wdev->wdev_idx, 0); + + DBGPRINT(RT_DEBUG_TRACE, ("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->wdev->wdev_idx, 0); + + DBGPRINT(RT_DEBUG_TRACE, ("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(RTMP_STRING *password, PUCHAR ssid, INT ssidlength, PUCHAR output) +{ + if ((strlen(password) > 63) || (ssidlength > 32)) + return 0; + + F(password, ssid, ssidlength, 4096, 1, output); + F(password, ssid, ssidlength, 4096, 2, &output[SHA1_DIGEST_SIZE]); + return 1; +} + +/* + ======================================================================== + + Routine Description: + The key derivation function(KDF) is defined in IEEE 802.11r/D9.0, 8.5.1.5.2 + + Arguments: + + Return Value: + + Note: + Output - KDF-Length (K, label, Context) where + Input: K, a 256-bit key derivation key + label, a string identifying the purpose of the keys derived using this KDF + Context, a bit string that provides context to identify the derived key + Length, the length of the derived key in bits + Output: a Length-bit derived key + + result - "" + iterations - (Length+255)/256 + do i = 1 to iterations + result - result || HMAC-SHA256(K, i || label || Context || Length) + od + return first Length bits of result, and securely delete all unused bits + + In this algorithm, i and Length are encoded as 16-bit unsigned integers. + + ======================================================================== +*/ +VOID KDF( + IN PUINT8 key, + IN INT key_len, + IN PUINT8 label, + IN INT label_len, + IN PUINT8 data, + IN INT data_len, + OUT PUINT8 output, + IN USHORT len) +{ + USHORT i; + UCHAR *input; + INT currentindex = 0; + INT total_len; + UINT len_in_bits = (len << 3); + + os_alloc_mem(NULL, (PUCHAR *)&input, 1024); + + if (input == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!KDF: no memory!!!\n")); + return; + } + + NdisZeroMemory(input, 1024); + + /* Initial concatenated value (i || label || Context || Length)*/ + /* concatenate 16-bit unsigned integer, its initial value is 1. */ + input[0] = 1; + input[1] = 0; + total_len = 2; + + /* concatenate a prefix string*/ + NdisMoveMemory(&input[total_len], label, label_len); + total_len += label_len; + + /* concatenate the context*/ + NdisMoveMemory(&input[total_len], data, data_len); + total_len += data_len; + + /* concatenate the length in bits (16-bit unsigned integer)*/ + input[total_len] = (len_in_bits & 0xFF); + input[total_len + 1] = (len_in_bits & 0xFF00) >> 8; + total_len += 2; + + for (i = 1; i <= ((len_in_bits + 255) / 256); i++) + { + /* HMAC-SHA256 derives output */ + RT_HMAC_SHA256((UCHAR *)key, key_len, input, total_len, (UCHAR *)&output[currentindex], 32); + + currentindex += 32; /* next concatenation location*/ + input[0]++; /* increment octet count*/ + + } + os_free_mem(NULL, input); +} + + +/* + ======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +VOID RTMPDerivePMKID( + IN PUINT8 pAaddr, + IN PUINT8 pSpaddr, + IN PUINT8 pKey, + IN PUINT8 pAkm_oui, + OUT PUINT8 pPMKID) +{ + UCHAR digest[80], text_buf[20]; + UINT8 text_len; + + /* Concatenate the text for PMKID calculation*/ + NdisMoveMemory(&text_buf[0], "PMK Name", 8); + NdisMoveMemory(&text_buf[8], pAaddr, MAC_ADDR_LEN); + NdisMoveMemory(&text_buf[14], pSpaddr, MAC_ADDR_LEN); + text_len = 20; + +#ifdef DOT11W_PMF_SUPPORT +/* todo pmf*/ + /* When the negotiated AKM is 00-0F-AC:5 or 00-0F-AC:6, + HMAC-SHA-256 is used to calculate the PMKID */ + if (NdisEqualMemory(pAkm_oui, OUI_PMF_8021X_AKM, 4) || + NdisEqualMemory(pAkm_oui, OUI_PMF_PSK_AKM, 4)) + { + RT_HMAC_SHA256(pKey, PMK_LEN, text_buf, text_len, digest, SHA256_DIGEST_SIZE); + } + else +#endif /* DOT11W_PMF_SUPPPORT */ + { + RT_HMAC_SHA1(pKey, PMK_LEN, text_buf, text_len, digest, SHA1_DIGEST_SIZE); + } + + /* Truncate the first 128-bit of output result */ + NdisMoveMemory(pPMKID, digest, LEN_PMKID); + +} + + + +/* + ======================================================================== + + Routine Description: + It utilizes PRF-384 or PRF-512 to derive session-specific keys from a PMK. + It shall be called by 4-way handshake processing. + + Arguments: + pAd - pointer to our pAdapter context + PMK - pointer to PMK + ANonce - pointer to ANonce + AA - pointer to Authenticator Address + SNonce - pointer to SNonce + SA - pointer to Supplicant Address + len - indicate the length of PTK (octet) + + Return Value: + Output pointer to the PTK + + Note: + Refer to IEEE 802.11i-2004 8.5.1.2 + + ======================================================================== +*/ +VOID WpaDerivePTK( + IN PRTMP_ADAPTER pAd, + IN UCHAR *PMK, + IN UCHAR *ANonce, + IN UCHAR *AA, + IN UCHAR *SNonce, + IN UCHAR *SA, + OUT UCHAR *output, + IN UINT len) +{ + UCHAR concatenation[76]; + UINT CurrPos = 0; + UCHAR temp[32]; + UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ', + 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'}; + + /* initiate the concatenation input*/ + NdisZeroMemory(temp, sizeof(temp)); + NdisZeroMemory(concatenation, 76); + + /* Get smaller address*/ + if (RTMPCompareMemory(SA, AA, 6) == 1) + NdisMoveMemory(concatenation, AA, 6); + else + NdisMoveMemory(concatenation, SA, 6); + CurrPos += 6; + + /* Get larger address*/ + if (RTMPCompareMemory(SA, AA, 6) == 1) + NdisMoveMemory(&concatenation[CurrPos], SA, 6); + else + NdisMoveMemory(&concatenation[CurrPos], AA, 6); + + /* store the larger mac address for backward compatible of */ + /* ralink proprietary STA-key issue */ + NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN); + CurrPos += 6; + + /* Get smaller Nonce*/ + if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) + NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue*/ + else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) + NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); + else + NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); + CurrPos += 32; + + /* Get larger Nonce*/ + if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) + NdisMoveMemory(&concatenation[CurrPos], temp, 32); /* patch for ralink proprietary STA-key issue*/ + else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) + NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); + else + NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); + CurrPos += 32; + + + /* 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, +#ifdef DOT11_SAE_SUPPORT + IN NDIS_802_11_AUTHENTICATION_MODE AuthMode, +#endif + 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; + +#ifdef DOT11_SAE_SUPPORT + if (WepStatus == Ndis802_11TKIPEnable || WepStatus == Ndis802_11TKIPAESMix) { + if (AuthMode == Ndis802_11AuthModeWPA3PSK || + AuthMode == Ndis802_11AuthModeWPA2PSKWPA3PSK) { + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("==> %s not support group cipher on SAE\n", __func__)); + return; + } + } +#endif + + switch (WepStatus) + { + /* TKIP mode*/ + case Ndis802_11TKIPEnable: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4); + *rsn_len = sizeof(RSNIE2); + break; + + /* AES mode*/ + case Ndis802_11AESEnable: + if (bMixCipher) + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); + else + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CCMP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4); + *rsn_len = sizeof(RSNIE2); + break; +#ifdef CONFIG_OWE_SUPPORT + case Ndis802_11CCMP128Enable: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CIPHER_CCMP128, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CIPHER_CCMP128, 4); + *rsn_len = sizeof(RSNIE2);/* mixed TBD */ + break; + case Ndis802_11CCMP256Enable: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_CIPHER_CCMP256, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CIPHER_CCMP256, 4); + *rsn_len = sizeof(RSNIE2); + break; +#endif + /* TKIP-AES mix mode*/ + case Ndis802_11TKIPAESMix: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA2_TKIP, 4); + + PairwiseCnt = 1; + /* Insert WPA2 TKIP as the first pairwise cipher */ + if (MIX_CIPHER_WPA2_TKIP_ON(FlexibleCipher)) + { + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_TKIP, 4); + /* Insert WPA2 AES as the secondary pairwise cipher*/ + if (MIX_CIPHER_WPA2_AES_ON(FlexibleCipher)) + { + NdisMoveMemory(pRsnIe + sizeof(RSNIE2), OUI_WPA2_CCMP, 4); + PairwiseCnt = 2; + } + } + else + { + /* Insert WPA2 AES as the first pairwise cipher */ + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA2_CCMP, 4); + } + + pRsnie_cipher->ucount = PairwiseCnt; + *rsn_len = sizeof(RSNIE2) + (4 * (PairwiseCnt - 1)); + break; + } + + + /* swap for big-endian platform*/ + pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); + pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); + } + else + { + RSNIE *pRsnie_cipher = (RSNIE*)pRsnIe; + + /* Assign OUI and version*/ + NdisMoveMemory(pRsnie_cipher->oui, OUI_WPA_VERSION, 4); + pRsnie_cipher->version = 1; + + switch (WepStatus) + { + /* TKIP mode*/ + case Ndis802_11TKIPEnable: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4); + *rsn_len = sizeof(RSNIE); + break; + + /* AES mode*/ + case Ndis802_11AESEnable: + if (bMixCipher) + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); + else + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_CCMP, 4); + pRsnie_cipher->ucount = 1; + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4); + *rsn_len = sizeof(RSNIE); + break; + + /* TKIP-AES mix mode*/ + case Ndis802_11TKIPAESMix: + NdisMoveMemory(pRsnie_cipher->mcast, OUI_WPA_TKIP, 4); + + PairwiseCnt = 1; + /* Insert WPA TKIP as the first pairwise cipher */ + if (MIX_CIPHER_WPA_TKIP_ON(FlexibleCipher)) + { + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_TKIP, 4); + /* Insert WPA AES as the secondary pairwise cipher*/ + if (MIX_CIPHER_WPA_AES_ON(FlexibleCipher)) + { + NdisMoveMemory(pRsnIe + sizeof(RSNIE), OUI_WPA_CCMP, 4); + PairwiseCnt = 2; + } + } + else + { + /* Insert WPA AES as the first pairwise cipher */ + NdisMoveMemory(pRsnie_cipher->ucast[0].oui, OUI_WPA_CCMP, 4); + } + + pRsnie_cipher->ucount = PairwiseCnt; + *rsn_len = sizeof(RSNIE) + (4 * (PairwiseCnt - 1)); + break; + } + + + /* swap for big-endian platform*/ + pRsnie_cipher->version = cpu2le16(pRsnie_cipher->version); + pRsnie_cipher->ucount = cpu2le16(pRsnie_cipher->ucount); + } +} + +/* + ======================================================================== + + Routine Description: + Build AKM suite in RSN-IE. + It only shall be called by RTMPMakeRSNIE. + + Arguments: + pAd - pointer to our pAdapter context + ElementID - indicate the WPA1 or WPA2 + AuthMode - indicate the authentication mode + apidx - indicate the interface index + + Return Value: + + Note: + + ======================================================================== +*/ +static VOID RTMPMakeRsnIeAKM( + IN PRTMP_ADAPTER pAd, + IN UCHAR ElementID, + IN UINT AuthMode, + IN UCHAR apidx, + OUT PUCHAR pRsnIe, + OUT UCHAR *rsn_len) +{ + RSNIE_AUTH *pRsnie_auth; + UCHAR AkmCnt = 1; /* default as 1*/ +#ifdef DOT11R_FT_SUPPORT + BOOLEAN bFtEnabled = FALSE; + UINT8 FtAkmOui[8]; +#endif /* DOT11R_FT_SUPPORT */ + + pRsnie_auth = (RSNIE_AUTH*)(pRsnIe + (*rsn_len)); + + /* decide WPA2 or WPA1 */ + if (ElementID == Wpa2Ie) + { +#ifdef DOT11R_FT_SUPPORT +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (apidx < pAd->ApCfg.BssidNum) + { + /* Indicate the FT is enabld*/ + if (pAd->ApCfg.MBSSID[apidx].FtCfg.FtCapFlag.Dot11rFtEnable) + { + bFtEnabled = TRUE; + AkmCnt = 2; + if (AuthMode == Ndis802_11AuthModeWPA2 || + AuthMode == Ndis802_11AuthModeWPA1WPA2) + { + NdisMoveMemory(FtAkmOui, OUI_WPA2_8021X_AKM, 4); + NdisMoveMemory(&FtAkmOui[4], OUI_FT_8021X_AKM, 4); + } + else if (AuthMode == Ndis802_11AuthModeWPA2PSK || + AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) + { + NdisMoveMemory(FtAkmOui, OUI_WPA2_PSK_AKM, 4); + NdisMoveMemory(&FtAkmOui[4], OUI_FT_PSK_AKM, 4); + } + else + AkmCnt = 0; + } + } + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* DOT11R_FT_SUPPORT */ + + switch (AuthMode) + { + case Ndis802_11AuthModeWPA2: + case Ndis802_11AuthModeWPA1WPA2: +#ifdef DOT11R_FT_SUPPORT + if (bFtEnabled && (AkmCnt > 0)) + { + /* append the primary AKM suite */ + NdisMoveMemory(pRsnie_auth->auth[0].oui, FtAkmOui, 4); + + /* Append the secondary AKM suite if it exists */ + if (AkmCnt == 2) + { + /* Get the offset of the end of 1st AKM suite */ + UCHAR ext_akm_offset = (*rsn_len) + sizeof(RSNIE_AUTH); + + NdisMoveMemory(pRsnIe + ext_akm_offset, &FtAkmOui[4] , 4); + } + } + else +#endif /* DOT11R_FT_SUPPORT */ + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_8021X_AKM, 4); + +#ifdef DOT11W_PMF_SUPPORT +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (pAd->ApCfg.MBSSID[apidx].PmfCfg.MFPR) { + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_1X_SHA256, 4); + DBGPRINT(RT_DEBUG_WARN, ("[PMF]%s: Insert 1X-SHA256 to AKM of RSNIE\n", __FUNCTION__)); + } else if ((pAd->ApCfg.MBSSID[apidx].PmfCfg.MFPC) && (pAd->ApCfg.MBSSID[apidx].PmfCfg.PMFSHA256)) { + NdisMoveMemory(pRsnie_auth->auth[0].oui + (4*AkmCnt), OUI_WPA2_1X_SHA256, 4); + AkmCnt++; + DBGPRINT(RT_DEBUG_WARN, ("[PMF]%s: Insert 1X-SHA256 to AKM of RSNIE\n", __FUNCTION__)); + } + } +#endif /* CONFIG_AP_SUPPORT */ +#endif /* DOT11W_PMF_SUPPORT */ + break; +#ifdef DOT11_SAE_SUPPORT + case Ndis802_11AuthModeWPA3PSK: + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_AKM_SAE_SHA256, 4); + AkmCnt = 1;/* FT WPA3 PSK is TBD */ + break; +#endif +#ifdef CONFIG_OWE_SUPPORT + case Ndis802_11AuthModeOWE: + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_AKM_OWE, 4); + AkmCnt = 1;/* FT WPA3 PSK is TBD */ + break; +#endif +#ifdef DOT11_SAE_SUPPORT + case Ndis802_11AuthModeWPA2PSKWPA3PSK: + AkmCnt = 0; + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4); + AkmCnt++; + NdisMoveMemory(pRsnie_auth->auth[0].oui + (4*AkmCnt), OUI_WPA2_AKM_SAE_SHA256, 4); + AkmCnt++; + break; +#endif + case Ndis802_11AuthModeWPA2PSK: + case Ndis802_11AuthModeWPA1PSKWPA2PSK: + +#ifdef DOT11R_FT_SUPPORT + if (bFtEnabled && (AkmCnt > 0)) + { + /* append the primary AKM suite */ + NdisMoveMemory(pRsnie_auth->auth[0].oui, FtAkmOui, 4); + + /* Append the secondary AKM suite if it exists */ + if (AkmCnt == 2) + { + /* Get the offset of the end of 1st AKM suite */ + UCHAR ext_akm_offset = (*rsn_len) + sizeof(RSNIE_AUTH); + + NdisMoveMemory(pRsnIe + ext_akm_offset, &FtAkmOui[4] , 4); + } + } + else +#endif /* DOT11R_FT_SUPPORT */ + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_AKM, 4); + +#ifdef DOT11W_PMF_SUPPORT +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef APCLI_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) { + PAPCLI_STRUCT pApCliEntry = &pAd->ApCfg.ApCliTab[apidx - MIN_NET_DEVICE_FOR_APCLI]; + + if (pApCliEntry) { + DBGPRINT(RT_DEBUG_WARN, + ("[PMF]%s: IsSupportSHA256KeyDerivation = %d, MFPR = %d\n", + __func__, pApCliEntry->MlmeAux.IsSupportSHA256KeyDerivation, + pApCliEntry->MlmeAux.RsnCap.field.MFPR)); + + if ((pApCliEntry->PmfCfg.PMFSHA256 && + pApCliEntry->MlmeAux.IsSupportSHA256KeyDerivation) + || (pApCliEntry->PmfCfg.MFPC && + pApCliEntry->MlmeAux.RsnCap.field.MFPR) + || (pApCliEntry->PmfCfg.MFPC && + pApCliEntry->MlmeAux.IsSupportSHA256KeyDerivation)) { + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_SHA256, 4); + DBGPRINT(RT_DEBUG_WARN, + ("[PMF]%s: Insert PSK-SHA256 to AKM of RSNIE\n", __func__)); + } + } + } else +#endif /* APCLI_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + { + if (pAd->ApCfg.MBSSID[apidx].PmfCfg.MFPR) { + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA2_PSK_SHA256, 4); + DBGPRINT(RT_DEBUG_WARN, + ("[PMF]%s: Insert PSK-SHA256 to AKM of RSNIE\n", __func__)); + } else if ((pAd->ApCfg.MBSSID[apidx].PmfCfg.MFPC) && + (pAd->ApCfg.MBSSID[apidx].PmfCfg.PMFSHA256)) { + NdisMoveMemory(pRsnie_auth->auth[0].oui + (4*AkmCnt), OUI_WPA2_PSK_SHA256, 4); + AkmCnt++; + DBGPRINT(RT_DEBUG_WARN, + ("[PMF]%s: Insert PSK-SHA256 to AKM of RSNIE\n", __func__)); + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + +#endif /* DOT11W_PMF_SUPPORT */ + break; + default: + AkmCnt = 0; + break; + + } + } + else + { + switch (AuthMode) + { + case Ndis802_11AuthModeWPA: + case Ndis802_11AuthModeWPA1WPA2: + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_8021X_AKM, 4); + break; + + case Ndis802_11AuthModeWPAPSK: + case Ndis802_11AuthModeWPA1PSKWPA2PSK: + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_PSK_AKM, 4); + break; + + case Ndis802_11AuthModeWPANone: + NdisMoveMemory(pRsnie_auth->auth[0].oui, OUI_WPA_NONE_AKM, 4); + break; + default: + AkmCnt = 0; + break; + } + } + + pRsnie_auth->acount = AkmCnt; + pRsnie_auth->acount = cpu2le16(pRsnie_auth->acount); + + /* update current RSNIE length*/ + (*rsn_len) += (sizeof(RSNIE_AUTH) + (4 * (AkmCnt - 1))); + +} + +/* + ======================================================================== + + Routine Description: + Build capability in RSN-IE. + It only shall be called by RTMPMakeRSNIE. + + Arguments: + pAd - pointer to our pAdapter context + ElementID - indicate the WPA1 or WPA2 + apidx - indicate the interface index + + Return Value: + + Note: + + ======================================================================== +*/ +static VOID RTMPMakeRsnIeCap( + IN PRTMP_ADAPTER pAd, + IN UCHAR ElementID, + IN UCHAR apidx, + OUT PUCHAR pRsnIe, + OUT UCHAR *rsn_len) +{ + RSN_CAPABILITIES *pRSN_Cap; + + /* it could be ignored in WPA1 mode*/ + if (ElementID == WpaIe) + return; + + pRSN_Cap = (RSN_CAPABILITIES*)(pRsnIe + (*rsn_len)); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef DOT11W_PMF_SUPPORT +#ifdef APCLI_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) { + PAPCLI_STRUCT pApCliEntry = &pAd->ApCfg.ApCliTab[apidx - MIN_NET_DEVICE_FOR_APCLI]; + + pRSN_Cap->field.MFPC = (pApCliEntry->PmfCfg.MFPC) ? 1 : 0; + pRSN_Cap->field.MFPR = (pApCliEntry->PmfCfg.MFPR) ? 1 : 0; + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: RSNIE Capability MFPC=%d, MFPR=%d\n", + __func__, pRSN_Cap->field.MFPC, pRSN_Cap->field.MFPR)); + } else +#endif /* APCLI_SUPPORT */ +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + if (apidx < pAd->ApCfg.BssidNum) + { + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; + +#ifdef DOT1X_SUPPORT + pRSN_Cap->field.PreAuth = (pMbss->PreAuth == TRUE) ? 1 : 0; +#endif /* DOT1X_SUPPORT */ +#ifdef DOT11W_PMF_SUPPORT + pRSN_Cap->field.MFPC = (pMbss->PmfCfg.MFPC) ? 1 : 0; + pRSN_Cap->field.MFPR = (pMbss->PmfCfg.MFPR) ? 1 : 0; + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: RSNIE Capability MFPC=%d, MFPR=%d\n", __FUNCTION__, pRSN_Cap->field.MFPC, pRSN_Cap->field.MFPR)); +#endif /* DOT11W_PMF_SUPPORT */ + } + } +#endif /* CONFIG_AP_SUPPORT */ + + + pRSN_Cap->word = cpu2le16(pRSN_Cap->word); + + (*rsn_len) += sizeof(RSN_CAPABILITIES); /* update current RSNIE length*/ + +} + +/* + ======================================================================== + + Routine Description: + Build PMKID in RSN-IE. + It only shall be called by RTMPMakeRSNIE. + + Arguments: + pAd - pointer to our pAdapter context + ElementID - indicate the WPA1 or WPA2 + apidx - indicate the interface index + + Return Value: + + Note: + + ======================================================================== +*/ +#ifdef DOT11W_PMF_SUPPORT +static VOID RTMPInsertRsnIeZeroPMKID( + IN PRTMP_ADAPTER pAd, + IN UCHAR ElementID, + IN UCHAR apidx, + OUT PUCHAR pRsnIe, + OUT UCHAR *rsn_len) +{ + PUINT8 pBuf; + UCHAR ZeroPmkID[2] = {0x00, 0x00}; + + /* it could be ignored in WPA1 mode*/ + if (ElementID == WpaIe) + return; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef APCLI_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) { + PAPCLI_STRUCT pApCliEntry = &pAd->ApCfg.ApCliTab[apidx - MIN_NET_DEVICE_FOR_APCLI]; + + if (pApCliEntry->PmfCfg.MFPC) + goto InsertPMKIDCount; + } else +#endif /* APCLI_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + if (apidx < pAd->ApCfg.BssidNum) + { + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; + if (pMbss->PmfCfg.MFPC) + goto InsertPMKIDCount; + } + } +#endif /* CONFIG_AP_SUPPORT */ + return; + +InsertPMKIDCount: + pBuf = (pRsnIe + (*rsn_len)); + + NdisMoveMemory(pBuf, ZeroPmkID, 2); + (*rsn_len) += 2; /* update current RSNIE length */ +} +#endif /* DOT11W_PMF_SUPPORT */ + +#if defined(CONFIG_OWE_SUPPORT) || defined(DOT11_SAE_SUPPORT) +static VOID RTMPInsertRsnIePMKID( + IN PRTMP_ADAPTER pAd, + IN UCHAR ElementID, + IN UINT AuthMode, + IN UCHAR apidx, + IN MAC_TABLE_ENTRY * pEntry, + OUT PUCHAR pRsnIe, + OUT UCHAR *rsn_len) +{ + + PUINT8 pBuf; +#ifdef DOT11W_PMF_SUPPORT + UCHAR ZeroPmkID[2] = {0x00, 0x00}; + BOOLEAN MFP_Enabled = FALSE; +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef APCLI_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) { + PAPCLI_STRUCT pApCliEntry = &pAd->ApCfg.ApCliTab[apidx - MIN_NET_DEVICE_FOR_APCLI]; + + MFP_Enabled = pApCliEntry->PmfCfg.MFPC; + } else +#endif /* APCLI_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + if (apidx < pAd->ApCfg.BssidNum) { + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; + + MFP_Enabled = pMbss->PmfCfg.MFPC; + } +#endif + + if (ElementID == Wpa2Ie) { + +#ifdef CONFIG_AP_SUPPORT + pBuf = pRsnIe + (*rsn_len); +#ifdef DOT11_SAE_SUPPORT + if ((AuthMode == Ndis802_11AuthModeWPA3PSK || AuthMode == Ndis802_11AuthModeWPA2PSKWPA3PSK) + && pEntry && (IS_ENTRY_CLIENT(pEntry) +#ifdef APCLI_SAE_SUPPORT + || IS_ENTRY_APCLI(pEntry) +#endif + ) && is_pmkid_cache_in_entry(pEntry)) { + + UINT16 pmk_count = 1; + + pmk_count = cpu2le16(pmk_count); + NdisMoveMemory(pBuf, &pmk_count, sizeof(pmk_count)); + NdisMoveMemory(pBuf+sizeof(pmk_count), pEntry->pmkid, LEN_PMKID); + (*rsn_len) += sizeof(pmk_count) + LEN_PMKID; + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s: (SAE) including the PMKID.\n", __func__)); + } +#endif +#ifdef CONFIG_OWE_SUPPORT + else if (AuthMode == Ndis802_11AuthModeOWE + && pEntry && (IS_ENTRY_CLIENT(pEntry) +#ifdef APCLI_OWE_SUPPORT + || IS_ENTRY_APCLI(pEntry) +#endif + ) && is_pmkid_cache_in_entry(pEntry)) { + UINT16 pmk_count = 1; + + pmk_count = cpu2le16(pmk_count); + NdisMoveMemory(pBuf, &pmk_count, sizeof(pmk_count)); + NdisMoveMemory(pBuf+sizeof(pmk_count), pEntry->pmkid, LEN_PMKID); + hex_dump("pmkid = ", pEntry->pmkid, LEN_PMKID); + (*rsn_len) += sizeof(pmk_count) + LEN_PMKID; + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s: (OWE) including the PMKID.\n", __func__)); + } +#endif +#ifdef DOT11W_PMF_SUPPORT + else if (MFP_Enabled) { + NdisMoveMemory(pBuf, ZeroPmkID, 2); + (*rsn_len) += 2; + } +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + } +} +#endif + +/* + ======================================================================== + + Routine Description: + Build RSN IE context. It is not included element-ID and length. + + Arguments: + pAd - pointer to our pAdapter context + AuthMode - indicate the authentication mode + WepStatus - indicate the encryption type + apidx - indicate the interface index + + Return Value: + + Note: + + ======================================================================== +*/ +VOID RTMPMakeRSNIE(RTMP_ADAPTER *pAd, UINT AuthMode, UINT WepStatus, UCHAR apidx) +{ + PUCHAR pRsnIe = NULL; /* primary RSNIE*/ + UCHAR *rsnielen_cur_p = 0; /* the length of the primary RSNIE */ +#ifdef CONFIG_AP_SUPPORT + PUCHAR pRsnIe_ex = NULL; /* secondary RSNIE, it's ONLY used in WPA-mix mode */ + BOOLEAN bMixRsnIe = FALSE; /* indicate WPA-mix mode is on or off*/ + UCHAR s_offset; +#endif /* CONFIG_AP_SUPPORT */ + UCHAR *rsnielen_ex_cur_p = 0; /* the length of the secondary RSNIE */ + UCHAR PrimaryRsnie; + BOOLEAN bMixCipher = FALSE; /* indicate the pairwise and group cipher are different*/ + UCHAR p_offset; + WPA_MIX_PAIR_CIPHER FlexibleCipher = MIX_CIPHER_NOTUSE; /* it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode*/ + + rsnielen_cur_p = NULL; + rsnielen_ex_cur_p = NULL; + + do + { + +#ifdef APCLI_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) + { + UINT apcliIfidx = 0; + + /* Only support WPAPSK or WPA2PSK for AP-Client mode */ + { + 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 */ +#ifdef DOT11_SAE_SUPPORT + && (AuthMode != Ndis802_11AuthModeWPA3PSK) + && (AuthMode != Ndis802_11AuthModeWPA2PSKWPA3PSK) +#endif /* DOT11_SAE_SUPPORT */ +#ifdef CONFIG_OWE_SUPPORT + && (AuthMode != Ndis802_11AuthModeOWE) +#endif /* DOT11_SAE_SUPPORT */ + ) + return; + + DBGPRINT(RT_DEBUG_TRACE,("==> RTMPMakeRSNIE(AP-ra%d)\n", apidx)); + + /* decide the group key encryption type */ + if (WepStatus == Ndis802_11TKIPAESMix) + { + pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus = Ndis802_11TKIPEnable; + FlexibleCipher = pAd->ApCfg.MBSSID[apidx].wdev.WpaMixPairCipher; + } + else + pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus = WepStatus; + + /* Initiate some related information */ + pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0] = 0; + pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1] = 0; + NdisZeroMemory(pAd->ApCfg.MBSSID[apidx].RSN_IE[0], MAX_LEN_OF_RSNIE); + NdisZeroMemory(pAd->ApCfg.MBSSID[apidx].RSN_IE[1], MAX_LEN_OF_RSNIE); + + /* Pointer to the first RSNIE context */ + rsnielen_cur_p = &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[0]; + pRsnIe = pAd->ApCfg.MBSSID[apidx].RSN_IE[0]; + + /* Pointer to the secondary RSNIE context */ + rsnielen_ex_cur_p = &pAd->ApCfg.MBSSID[apidx].RSNIE_Len[1]; + pRsnIe_ex = pAd->ApCfg.MBSSID[apidx].RSN_IE[1]; + + /* Decide whether the authentication mode is WPA1-WPA2 mixed mode */ + if ((AuthMode == Ndis802_11AuthModeWPA1WPA2) || + (AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) + { + bMixRsnIe = TRUE; + } + break; + } +#endif /* CONFIG_AP_SUPPORT */ + + } 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, +#ifdef DOT11_SAE_SUPPORT + AuthMode, +#endif + apidx, bMixCipher, FlexibleCipher, pRsnIe, &p_offset); + + /* 2. insert AKM*/ + RTMPMakeRsnIeAKM(pAd, PrimaryRsnie, AuthMode, apidx, pRsnIe, &p_offset); + + /* 3. insert capability*/ + RTMPMakeRsnIeCap(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset); + +#ifdef DOT11W_PMF_SUPPORT + /* 4. Insert PMKID */ + RTMPInsertRsnIeZeroPMKID(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset); + + /* 5. Insert Group Management Cipher*/ + PMF_MakeRsnIeGMgmtCipher(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset); +#endif /* DOT11W_PMF_SUPPORT */ + } + + /* 4. update the RSNIE length*/ + if (rsnielen_cur_p == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: rsnielen_cur_p == NULL!\n", __FUNCTION__)); + return; + } + + *rsnielen_cur_p = p_offset; + + hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p)); + +#ifdef CONFIG_AP_SUPPORT + if ((pAd->OpMode == OPMODE_AP) + ) + { + /* if necessary, build the secondary RSNIE*/ + if (bMixRsnIe) + { + /* 1. insert cipher suite*/ + RTMPMakeRsnIeCipher(pAd, Wpa2Ie, WepStatus, +#ifdef DOT11_SAE_SUPPORT + AuthMode, +#endif + apidx, bMixCipher, FlexibleCipher, + pRsnIe_ex, &s_offset); + + /* 2. insert AKM*/ + RTMPMakeRsnIeAKM(pAd, Wpa2Ie, AuthMode, apidx, pRsnIe_ex, &s_offset); + + /* 3. insert capability*/ + RTMPMakeRsnIeCap(pAd, Wpa2Ie, apidx, pRsnIe_ex, &s_offset); + +#ifdef DOT11W_PMF_SUPPORT + /* 4. Insert PMKID */ + RTMPInsertRsnIeZeroPMKID(pAd, Wpa2Ie, apidx, pRsnIe_ex, &s_offset); + + /* 5. Insert Group Management Cipher*/ + PMF_MakeRsnIeGMgmtCipher(pAd, Wpa2Ie, apidx, pRsnIe_ex, &s_offset); +#endif /* DOT11W_PMF_SUPPORT */ + + /* Update the RSNIE length*/ + *rsnielen_ex_cur_p = s_offset; + + hex_dump("The secondary RSNIE", pRsnIe_ex, (*rsnielen_ex_cur_p)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + +} + + +/* For OWE, make RSNIE.*/ +#if defined(CONFIG_OWE_SUPPORT) || defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) +VOID WPAMakeEntryRSNIE( + IN PRTMP_ADAPTER pAd, + IN UINT AuthMode, + IN UINT WepStatus, + IN MAC_TABLE_ENTRY * pEntry) +{ + 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; + /* it provide the more flexible cipher combination in WPA-WPA2 and TKIPAES mode*/ + WPA_MIX_PAIR_CIPHER FlexibleCipher = MIX_CIPHER_NOTUSE; + + rsnielen_cur_p = NULL; + rsnielen_ex_cur_p = NULL; + apidx = pEntry->func_tb_idx; + + do { + +#ifdef APCLI_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) { + UINT apcliIfidx = 0; + + /* Only support WPAPSK or WPA2PSK for AP-Client mode */ + { + if ((AuthMode != Ndis802_11AuthModeWPAPSK) && + (AuthMode != Ndis802_11AuthModeWPA2PSK) +#ifdef APCLI_SAE_SUPPORT + && (AuthMode != Ndis802_11AuthModeWPA3PSK) +#endif +#ifdef APCLI_OWE_SUPPORT + && (AuthMode != Ndis802_11AuthModeOWE) +#endif + ) + 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 */ +#ifdef DOT11_SAE_SUPPORT + && (AuthMode != Ndis802_11AuthModeWPA3PSK) + && (AuthMode != Ndis802_11AuthModeWPA2PSKWPA3PSK) +#endif /* DOT11_SAE_SUPPORT */ +#ifdef CONFIG_OWE_SUPPORT + && (AuthMode != Ndis802_11AuthModeOWE) +#endif /* DOT11_SAE_SUPPORT */ + ) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPMakeRSNIE(AP-ra%d)\n", apidx)); + + /* decide the group key encryption type */ + if (WepStatus == Ndis802_11TKIPAESMix) { + pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus = Ndis802_11TKIPEnable; + FlexibleCipher = pAd->ApCfg.MBSSID[apidx].wdev.WpaMixPairCipher; + } else + pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus = WepStatus; + + /* Initiate some related information */ + pEntry->RSNE_Len[0] = 0; + pEntry->RSNE_Len[1] = 0; + NdisZeroMemory(pEntry->RSNE_Content[0], MAX_LEN_OF_RSNIE); + NdisZeroMemory(pEntry->RSNE_Content[1], MAX_LEN_OF_RSNIE); + + /* Pointer to the first RSNIE context */ + rsnielen_cur_p = &pEntry->RSNE_Len[0]; + pRsnIe = pEntry->RSNE_Content[0]; + + /* Pointer to the secondary RSNIE context */ + rsnielen_ex_cur_p = &pEntry->RSNE_Len[1]; + pRsnIe_ex = pEntry->RSNE_Content[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 */ + + } 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, +#ifdef DOT11_SAE_SUPPORT + AuthMode, +#endif + 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. Insert PMKID */ + RTMPInsertRsnIePMKID(pAd, PrimaryRsnie, AuthMode, apidx, pEntry, pRsnIe, &p_offset); +#ifdef DOT11W_PMF_SUPPORT + /* 5. Insert Group Management Cipher*/ + PMF_MakeRsnIeGMgmtCipher(pAd, PrimaryRsnie, apidx, pRsnIe, &p_offset); +#endif /* DOT11W_PMF_SUPPORT */ + } + + /* 4. update the RSNIE length*/ + if (rsnielen_cur_p == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: rsnielen_cur_p == NULL!\n", __func__)); + return; + } + + *rsnielen_cur_p = p_offset; + + hex_dump("The primary RSNIE", pRsnIe, (*rsnielen_cur_p)); + +#ifdef CONFIG_AP_SUPPORT + if ((pAd->OpMode == OPMODE_AP) + ) { + /* if necessary, build the secondary RSNIE*/ + if (bMixRsnIe) { + /* 1. insert cipher suite*/ + RTMPMakeRsnIeCipher(pAd, Wpa2Ie, WepStatus, +#ifdef DOT11_SAE_SUPPORT + AuthMode, +#endif + apidx, bMixCipher, FlexibleCipher, + pRsnIe_ex, &s_offset); + + /* 2. insert AKM*/ + RTMPMakeRsnIeAKM(pAd, Wpa2Ie, AuthMode, apidx, pRsnIe_ex, &s_offset); + + /* 3. insert capability*/ + RTMPMakeRsnIeCap(pAd, Wpa2Ie, apidx, pRsnIe_ex, &s_offset); + +#ifdef DOT11W_PMF_SUPPORT + /* 4. Insert PMKID */ + RTMPInsertRsnIeZeroPMKID(pAd, Wpa2Ie, apidx, pRsnIe_ex, &s_offset); + + /* 5. Insert Group Management Cipher*/ + PMF_MakeRsnIeGMgmtCipher(pAd, Wpa2Ie, apidx, pRsnIe_ex, &s_offset); +#endif /* DOT11W_PMF_SUPPORT */ + + /* Update the RSNIE length*/ + *rsnielen_ex_cur_p = s_offset; + hex_dump("The secondary RSNIE", pRsnIe_ex, (*rsnielen_ex_cur_p)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + + } +#endif + +/* + ========================================================================== + 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 + wdev_idx - indicate the interface index + + Return: + TRUE - This frame is EAP frame + FALSE - otherwise + ========================================================================== +*/ +BOOLEAN RTMPCheckWPAframe( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR *pData, + IN ULONG DataByteCount, + IN UCHAR wdev_idx, + IN BOOLEAN eth_frame) +{ + ULONG min_len = (LENGTH_802_1_H + LENGTH_EAPOL_H); +#ifdef DBG + ULONG Body_len; +#endif /* DBG */ + + BOOLEAN Cancelled; + + ASSERT(wdev_idx <= WDEV_NUM_MAX); + if (wdev_idx >= WDEV_NUM_MAX) + return FALSE; + do + { + if (eth_frame) { + min_len = (LENGTH_802_3 + LENGTH_EAPOL_H); + break; + } + + } while (FALSE); + + if(DataByteCount < min_len) + return FALSE; + + /* Skip LLC or ETH header */ + if (eth_frame == TRUE) { + pData += LENGTH_802_3; + } else { + /* Cisco 1200 AP may send packet with SNAP_BRIDGE_TUNNEL*/ + if (NdisEqualMemory(SNAP_802_1H, pData, 6) || + NdisEqualMemory(SNAP_BRIDGE_TUNNEL, pData, 6)) + { + pData += 6; + } + } + + /* Skip 2-bytes EAPoL type */ + if (NdisEqualMemory(EAPOL, pData, 2)) + pData += 2; + else + return FALSE; + + switch (*(pData+1)) + { + case EAPPacket: +#ifdef DBG + Body_len = (*(pData+2)<<8) | (*(pData+3)); +#endif /* DBG */ +#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: +#ifdef DBG + Body_len = (*(pData+2)<<8) | (*(pData+3)); + DBGPRINT(RT_DEBUG_TRACE, ("Receive EAPOL-Key frame, TYPE = 3, Length = %ld\n", Body_len)); +#endif /* DBG */ + 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 + + ========================================================================== +*/ +RTMP_STRING *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: + + + ======================================================================== +*/ + +/* + ======================================================================== + + Routine Description: + Parse KEYDATA field. KEYDATA[] May contain 2 RSN IE and optionally GTK. + GTK is encaptulated in KDE format at p.83 802.11i D10 + + Arguments: + + Return Value: + + Note: + 802.11i D10 + + ======================================================================== +*/ +BOOLEAN RTMPParseEapolKeyData( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKeyData, + IN UCHAR KeyDataLen, + IN UCHAR GroupKeyIndex, + IN UCHAR MsgType, + IN BOOLEAN bWPA2, + IN MAC_TABLE_ENTRY *pEntry) +{ + PUCHAR pMyKeyData = pKeyData; + UCHAR KeyDataLength = KeyDataLen; + UCHAR GTK[MAX_LEN_GTK]; + UCHAR GTKLEN = 0; + UCHAR DefaultIdx = 0; + UCHAR skip_offset = 0; + + + NdisZeroMemory(GTK, MAX_LEN_GTK); + + /* Verify The RSN IE contained in pairewise_msg_2 && pairewise_msg_3 and skip it*/ + if (MsgType == EAPOL_PAIR_MSG_2 || MsgType == EAPOL_PAIR_MSG_3) + { + { + if (bWPA2 && MsgType == EAPOL_PAIR_MSG_3) + { + /*WpaShowAllsuite(pMyKeyData, skip_offset);*/ + + /* skip RSN IE*/ + pMyKeyData += skip_offset; + KeyDataLength -= skip_offset; + DBGPRINT(RT_DEBUG_TRACE, ("RTMPParseEapolKeyData ==> WPA2/WPA2PSK RSN IE matched in Msg 3, Length(%d) \n", skip_offset)); + } + else + return TRUE; + } + } + + DBGPRINT(RT_DEBUG_TRACE,("RTMPParseEapolKeyData ==> KeyDataLength %d without RSN_IE \n", KeyDataLength)); + /*hex_dump("remain data", pMyKeyData, KeyDataLength);*/ + +#ifdef DOT11R_FT_SUPPORT + if (IS_FT_RSN_STA(pEntry)) + { + PEID_STRUCT pEid; + + pEid = (PEID_STRUCT)pMyKeyData; + if (pEid->Eid == IE_FT_MDIE) + { + /* Skip MDIE of FT*/ + /* todo - verify it*/ + pMyKeyData += (pEid->Len + 2); + KeyDataLength -= (pEid->Len + 2); + } + } +#endif /* DOT11R_FT_SUPPORT */ + + /* Parse KDE format in pairwise_msg_3_WPA2 && group_msg_1_WPA2*/ + if (bWPA2 && (MsgType == EAPOL_PAIR_MSG_3 || MsgType == EAPOL_GROUP_MSG_1)) + { + PEID_STRUCT pEid; + + pEid = (PEID_STRUCT) pMyKeyData; + skip_offset = 0; + while ((skip_offset + 2 + pEid->Len) <= KeyDataLength) + { + switch(pEid->Eid) + { + case WPA_KDE_TYPE: + { + PKDE_HDR pKDE; + + pKDE = (PKDE_HDR)pEid; + if (NdisEqualMemory(pKDE->OUI, OUI_WPA2, 3)) + { + if (pKDE->DataType == KDE_GTK) + { + PGTK_KDE pKdeGtk; + + pKdeGtk = (PGTK_KDE) &pKDE->octet[0]; + DefaultIdx = pKdeGtk->Kid; + + /* Get GTK length - refer to IEEE 802.11i-2004 p.82 */ + GTKLEN = pKDE->Len -6; + if (GTKLEN < LEN_WEP64) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key length is too short (%d) \n", GTKLEN)); + return FALSE; + } + NdisMoveMemory(GTK, pKdeGtk->GTK, GTKLEN); + DBGPRINT(RT_DEBUG_TRACE, ("GTK in KDE format ,DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN)); + } +#ifdef DOT11W_PMF_SUPPORT + else if (pKDE->DataType == KDE_IGTK + && (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE))) + { + if (PMF_ExtractIGTKKDE( + pAd, &pKDE->octet[0], pKDE->Len - 4 +#ifdef APCLI_DOT11W_PMF_SUPPORT + , pEntry +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + ) == FALSE) + return FALSE; + } +#endif /* DOT11W_PMF_SUPPORT */ + } + } + break; + } + skip_offset = skip_offset + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + + /* skip KDE Info*/ + pMyKeyData += skip_offset; + KeyDataLength -= skip_offset; + } + else if (!bWPA2 && MsgType == EAPOL_GROUP_MSG_1) + { + DefaultIdx = GroupKeyIndex; + GTKLEN = KeyDataLength; + NdisMoveMemory(GTK, pMyKeyData, KeyDataLength); + DBGPRINT(RT_DEBUG_TRACE, ("GTK without KDE, DefaultKeyID=%d, KeyLen=%d \n", DefaultIdx, GTKLEN)); + } + + /* Sanity check - shared key index must be 0 ~ 3*/ + if (DefaultIdx > 3) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: GTK Key index(%d) is invalid in %s %s \n", DefaultIdx, ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType))); + return FALSE; + } + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if ((pAd->chipCap.hif_type == HIF_RLT || pAd->chipCap.hif_type == HIF_RTMP) && IS_ENTRY_APCLI(pEntry)) + { + /* Prevent the GTK reinstall key attack */ + if (pEntry->LastGroupKeyId != DefaultIdx || + !NdisEqualMemory(pEntry->LastGTK, GTK, MAX_LEN_GTK)) { + /* Set Group key material, TxMic and RxMic for AP-Client*/ + if (!APCliInstallSharedKey(pAd, GTK, GTKLEN, DefaultIdx, pEntry)) + { + return FALSE; + } + pEntry->LastGroupKeyId = DefaultIdx; + NdisMoveMemory(pEntry->LastGTK, GTK, MAX_LEN_GTK); + pEntry->AllowUpdateRSC = TRUE; + } else { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : the Group reinstall attack, skip install key\n", + __func__)); + } + } +#ifdef MT_MAC + else if ((pAd->chipCap.hif_type == HIF_MT) && IS_ENTRY_APCLI(pEntry)) + { + UCHAR IfIdx; + APCLI_STRUCT *pApcli_entry; + + IfIdx = pEntry->func_tb_idx; + ASSERT((IfIdx < MAX_APCLI_NUM)); + + pApcli_entry = &pAd->ApCfg.ApCliTab[IfIdx]; + + /* Prevent the GTK reinstall key attack */ + if (pEntry->LastGroupKeyId != DefaultIdx || + !NdisEqualMemory(pEntry->LastGTK, GTK, MAX_LEN_GTK)) { + /* Set Group key material, TxMic and RxMic for AP-Client*/ + WPAInstallSharedKey(pAd, + pApcli_entry->GroupCipher, +#ifdef MULTI_APCLI_SUPPORT + pEntry->func_tb_idx, +#else /* MULTI_APCLI_SUPPORT */ + BSS0, +#endif /* !MULTI_APCLI_SUPPORT */ + DefaultIdx, +#ifdef MULTI_APCLI_SUPPORT + APCLI_MCAST_WCID(IfIdx), +#else /* MULTI_APCLI_SUPPORT */ + APCLI_MCAST_WCID, +#endif /* !MULTI_APCLI_SUPPORT */ + FALSE, + GTK, + GTKLEN); + pEntry->LastGroupKeyId = DefaultIdx; + NdisMoveMemory(pEntry->LastGTK, GTK, MAX_LEN_GTK); + pEntry->AllowUpdateRSC = TRUE; + } else { + DBGPRINT(RT_DEBUG_ERROR, ("!!!%s : the Group reinstall attack, skip install key\n", + __func__)); + } + } +#endif /* MT_MAC */ +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_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) +#ifdef DOT11_SAE_SUPPORT + || (pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK) +#endif +#ifdef CONFIG_OWE_SUPPORT + || (pEntry->AuthMode == Ndis802_11AuthModeOWE) +#endif + ) + 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; + +#ifdef DOT11_SAE_SUPPORT + if (pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK) + KeyDescVer = KEY_DESC_NOT_DEFINED; + else +#endif +#ifdef CONFIG_OWE_SUPPORT + if (pEntry->AuthMode == Ndis802_11AuthModeOWE) + KeyDescVer = KEY_DESC_NOT_DEFINED; + else +#endif + /* Key Descriptor Version (bits 0-2) specifies the key descriptor version type*/ +#ifdef DOT11R_FT_SUPPORT + if (IS_FT_RSN_STA(pEntry)) + { + /* Todo-AlbertY : use AKM to detemine which Descriptor version is used */ + + /* All EAPOL-Key frames to and from a STA when the negotiated */ + /* AKM is 00-0F-AC:3 or 00-0F-AC:4.*/ + KeyDescVer = KEY_DESC_EXT; + } + else +#endif /* DOT11R_FT_SUPPORT */ +#ifdef DOT11W_PMF_SUPPORT + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_USE_SHA256)) + { + /* All EAPOL-Key frames to and from a STA when the negotiated */ + /* AKM is 00-0F-AC:3 or 00-0F-AC:4.*/ + KeyDescVer = KEY_DESC_EXT; + } + else +#endif /* DOT11W_PMF_SUPPORT */ +#ifdef CONFIG_HOTSPOT_R2 + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_OSEN_CAPABLE)) + { + printk ("OSEN use sha256\n"); + //KeyDescVer = KEY_DESC_EXT; + KeyDescVer = KEY_DESC_OSEN; + } + else +#endif /* CONFIG_HOTSPOT_R2 */ + { + /* Fill in Key information, refer to IEEE Std 802.11i-2004 page 78 */ + /* When either the pairwise or the group cipher is AES, the KEY_DESC_AES shall be used.*/ + KeyDescVer = (((pEntry->WepStatus == Ndis802_11AESEnable) || + (GroupKeyWepStatus == Ndis802_11AESEnable)) ? (KEY_DESC_AES) : (KEY_DESC_TKIP)); + } + + pMsg->KeyDesc.KeyInfo.KeyDescVer = KeyDescVer; + + /* Specify Key Type as Group(0) or Pairwise(1)*/ + if (MsgType >= EAPOL_GROUP_MSG_1) + pMsg->KeyDesc.KeyInfo.KeyType = GROUPKEY; + else + pMsg->KeyDesc.KeyInfo.KeyType = PAIRWISEKEY; + + /* Specify Key Index, only group_msg1_WPA1*/ + if (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1)) + pMsg->KeyDesc.KeyInfo.KeyIndex = DefaultKeyIdx; + + if (MsgType == EAPOL_PAIR_MSG_3) + pMsg->KeyDesc.KeyInfo.Install = 1; + + if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3) || (MsgType == EAPOL_GROUP_MSG_1)) + pMsg->KeyDesc.KeyInfo.KeyAck = 1; + + if (MsgType != EAPOL_PAIR_MSG_1) + pMsg->KeyDesc.KeyInfo.KeyMic = 1; + + if ((bWPA2 && (MsgType >= EAPOL_PAIR_MSG_3)) || + (!bWPA2 && (MsgType >= EAPOL_GROUP_MSG_1))) + { + pMsg->KeyDesc.KeyInfo.Secure = 1; + } + + /* This subfield shall be set, and the Key Data field shall be encrypted, if + any key material (e.g., GTK or SMK) is included in the frame. */ + if (bWPA2 && ((MsgType == EAPOL_PAIR_MSG_3) || + (MsgType == EAPOL_GROUP_MSG_1))) + { + pMsg->KeyDesc.KeyInfo.EKD_DL = 1; + } + + /* key Information element has done. */ + *(USHORT *)(&pMsg->KeyDesc.KeyInfo) = cpu2le16(*(USHORT *)(&pMsg->KeyDesc.KeyInfo)); + + /* Fill in Key Length*/ + if (bWPA2) + { + /* In WPA2 mode, the field indicates the length of pairwise key cipher, */ + /* so only pairwise_msg_1 and pairwise_msg_3 need to fill. */ + if ((MsgType == EAPOL_PAIR_MSG_1) || (MsgType == EAPOL_PAIR_MSG_3)) + pMsg->KeyDesc.KeyLength[1] = ((pEntry->WepStatus == Ndis802_11TKIPEnable) ? LEN_TKIP_TK : LEN_AES_TK); + } + else if (!bWPA2) + { + if (MsgType >= EAPOL_GROUP_MSG_1) + { + /* the length of group key cipher*/ + pMsg->KeyDesc.KeyLength[1] = ((GroupKeyWepStatus == Ndis802_11TKIPEnable) ? LEN_TKIP_GTK : LEN_AES_GTK); + } + else + { + /* the length of pairwise key cipher*/ + pMsg->KeyDesc.KeyLength[1] = ((pEntry->WepStatus == Ndis802_11TKIPEnable) ? LEN_TKIP_TK : LEN_AES_TK); + } + } + + /* Fill in replay counter */ + NdisMoveMemory(pMsg->KeyDesc.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY); + + /* Fill Key Nonce field */ + /* ANonce : pairwise_msg1 & pairwise_msg3*/ + /* SNonce : pairwise_msg2*/ + /* GNonce : group_msg1_wpa1 */ + if ((MsgType <= EAPOL_PAIR_MSG_3) || ((!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)))) + NdisMoveMemory(pMsg->KeyDesc.KeyNonce, KeyNonce, LEN_KEY_DESC_NONCE); + + /* Fill key IV - WPA2 as 0, WPA1 as random*/ + if (!bWPA2 && (MsgType == EAPOL_GROUP_MSG_1)) + { + /* Suggest IV be random number plus some number,*/ + NdisMoveMemory(pMsg->KeyDesc.KeyIv, &KeyNonce[16], LEN_KEY_DESC_IV); + pMsg->KeyDesc.KeyIv[15] += 2; + } + + /* Fill Key RSC field */ + /* It contains the RSC for the GTK being installed.*/ + if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2) || (MsgType == EAPOL_GROUP_MSG_1)) + { + NdisMoveMemory(pMsg->KeyDesc.KeyRsc, TxRSC, 6); + } + + /* Clear Key MIC field for MIC calculation later */ + NdisZeroMemory(pMsg->KeyDesc.KeyMic, LEN_KEY_DESC_MIC); + + ConstructEapolKeyData(pEntry, + GroupKeyWepStatus, + KeyDescVer, + MsgType, + DefaultKeyIdx, + GTK, + RSNIE, + RSNIE_Len, + pMsg); + + /* Calculate MIC and fill in KeyMic Field except Pairwise Msg 1.*/ + if (MsgType != EAPOL_PAIR_MSG_1) + { + CalculateMIC(KeyDescVer, pEntry->PTK, +#ifdef CONFIG_OWE_SUPPORT + pEntry->AuthMode, pEntry->key_deri_alg, +#endif + pMsg); + } + + DBGPRINT(RT_DEBUG_INFO, ("===> ConstructEapolMsg for %s %s\n", ((bWPA2) ? "WPA2" : "WPA"), GetEapolMsgType(MsgType))); + DBGPRINT(RT_DEBUG_INFO, (" Body length = %d \n", CONV_ARRARY_TO_UINT16(pMsg->Body_Len))); + DBGPRINT(RT_DEBUG_INFO, (" 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 = NULL, *Key_Data, *eGTK; + ULONG data_offset; + BOOLEAN bWPA2Capable = FALSE; + BOOLEAN GTK_Included = FALSE; +#ifdef DOT11R_FT_SUPPORT + PRTMP_ADAPTER pAd = pEntry->pAd; +#endif /* DOT11R_FT_SUPPORT */ + + /* Choose WPA2 or not*/ + if ((pEntry->AuthMode == Ndis802_11AuthModeWPA2) || + (pEntry->AuthMode == Ndis802_11AuthModeWPA2PSK) +#ifdef DOT11_SAE_SUPPORT + || (pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK) +#endif +#ifdef CONFIG_OWE_SUPPORT + || (pEntry->AuthMode == Ndis802_11AuthModeOWE) +#endif + ) + bWPA2Capable = TRUE; + + if (MsgType == EAPOL_PAIR_MSG_1 || + MsgType == EAPOL_PAIR_MSG_4 || + MsgType == EAPOL_GROUP_MSG_2) + return; + + /* allocate memory pool*/ + os_alloc_mem(NULL, (PUCHAR *)&mpool, 1500); + + if (mpool == NULL) + return; + + /* eGTK Len = 512 */ + eGTK = (UCHAR *) ROUND_UP(mpool, 4); + /* Key_Data Len = 512 */ + Key_Data = (UCHAR *) ROUND_UP(eGTK + 512, 4); + + NdisZeroMemory(Key_Data, 512); + SET_UINT16_TO_ARRARY(pMsg->KeyDesc.KeyDataLen, 0); + data_offset = 0; + + /* Encapsulate RSNIE in pairwise_msg2 & pairwise_msg3 */ + if (RSNIE_LEN && ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3))) + { + PUINT8 pmkid_ptr = NULL; + UINT8 pmkid_len = 0; + +#ifdef DOT11R_FT_SUPPORT + if (IS_FT_RSN_STA(pEntry)) + { + pmkid_ptr = pEntry->FT_PMK_R1_NAME; + pmkid_len = LEN_PMK_NAME; + } +#endif /* DOT11R_FT_SUPPORT */ + + RTMPInsertRSNIE(&Key_Data[data_offset], + &data_offset, + RSNIE, + RSNIE_LEN, + pmkid_ptr, + pmkid_len); + } + +#ifdef DOT11R_FT_SUPPORT + /* Encapsulate MDIE if FT is enabled*/ + if (IS_FT_RSN_STA(pEntry) && bWPA2Capable && + ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3))) + { + /* The MDIE shall be the same as those provided in + the AP's (Re)association Response frame. */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + NdisMoveMemory(&Key_Data[data_offset], pEntry->InitialMDIE, 5); + data_offset += 5; + } +#endif /* CONFIG_AP_SUPPORT */ + } +#endif /* DOT11R_FT_SUPPORT */ + + /* Encapsulate GTK */ + /* Only for pairwise_msg3_WPA2 and group_msg1*/ + if ((MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) || (MsgType == EAPOL_GROUP_MSG_1)) + { + UINT8 gtk_len; + + /* Decide the GTK length */ + if (GroupKeyWepStatus == Ndis802_11AESEnable) + gtk_len = LEN_AES_GTK; + else + gtk_len = LEN_TKIP_GTK; + + /* Insert GTK KDE format in WAP2 mode */ + if (bWPA2Capable) + { + /* Construct the common KDE format */ + WPA_ConstructKdeHdr(KDE_GTK, 2 + gtk_len, &Key_Data[data_offset]); + data_offset += sizeof(KDE_HDR); + + /* GTK KDE format - 802.11i-2004 Figure-43x*/ + Key_Data[data_offset] = (DefaultKeyIdx & 0x03); + Key_Data[data_offset + 1] = 0x00; /* Reserved Byte*/ + data_offset += 2; + } + + /* Fill in GTK */ + NdisMoveMemory(&Key_Data[data_offset], GTK, gtk_len); + data_offset += gtk_len; + +#ifdef DOT11W_PMF_SUPPORT + /* Insert IGTK KDE to Key_Data field */ + if ((bWPA2Capable) + && (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE))) + { + DBGPRINT(RT_DEBUG_WARN, ("[PMF]:%s - Insert IGTK\n", __FUNCTION__)); + PMF_InsertIGTKKDE(pEntry->pAd, pEntry->func_tb_idx, &Key_Data[data_offset], &data_offset); + } +#endif /* DOT11W_PMF_SUPPORT */ + + GTK_Included = TRUE; + } + +#ifdef DOT11R_FT_SUPPORT + /* Encapsulate the related IE of FT when FT is enabled */ + if (IS_FT_RSN_STA(pEntry) && bWPA2Capable && + ((MsgType == EAPOL_PAIR_MSG_2) || (MsgType == EAPOL_PAIR_MSG_3))) + { + /* Encapsulate FTIE. The MDIE shall be the same + as those provided in the AP's (Re)association Response frame. */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + NdisMoveMemory(&Key_Data[data_offset], pEntry->InitialFTIE, pEntry->InitialFTIE_Len); + data_offset += pEntry->InitialFTIE_Len; + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (MsgType == EAPOL_PAIR_MSG_3 && bWPA2Capable) + { + /* Encapsulate TIE[ReassociationDeadline] */ + FT_InsertTimeoutIntervalIE(pAd, + &Key_Data[data_offset], + (PULONG)&data_offset, + REASSOC_DEADLINE_INTERVAL, + FT_REASSOC_DEADLINE); + + /* Encapsulate TIM[KeyLifetime] */ + FT_InsertTimeoutIntervalIE(pAd, + &Key_Data[data_offset], + (PULONG)&data_offset, + KEY_LIFETIME_INTERVAL, + (pAd->ApCfg.MBSSID[pEntry->func_tb_idx].PMKCachePeriod/OS_HZ)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + } +#endif /* DOT11R_FT_SUPPORT */ + + + /* If the Encrypted Key Data subfield (of the Key Information field) + is set, the entire Key Data field shall be encrypted. */ + /* This whole key-data field shall be encrypted if a GTK is included.*/ + /* Encrypt the data material in key data field with KEK*/ + if (GTK_Included) + { + /*hex_dump("GTK_Included", Key_Data, data_offset);*/ + + if ( +#ifdef DOT11R_FT_SUPPORT + (keyDescVer == KEY_DESC_EXT) || +#endif /* DOT11R_FT_SUPPORT */ +#ifdef DOT11W_PMF_SUPPORT + (keyDescVer == KEY_DESC_EXT) || +#endif /* DOT11W_PMF_SUPPORT */ +#ifdef CONFIG_HOTSPOT_R2 + (keyDescVer == KEY_DESC_OSEN) || +#endif /* CONFIG_HOTSPOT_R2 */ +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + (keyDescVer == KEY_DESC_NOT_DEFINED) || +#endif + (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, +#ifdef CONFIG_OWE_SUPPORT + IN NDIS_802_11_AUTHENTICATION_MODE StaAuthMode, + IN UINT8 key_deri_alg, +#endif + OUT PEAPOL_PACKET pMsg) +{ + UCHAR *OutBuffer; + ULONG FrameLen = 0; + UCHAR mic[LEN_KEY_DESC_MIC]; + UCHAR digest[80]; +#ifdef CONFIG_OWE_SUPPORT + UINT8 mic_len = LEN_KEY_DESC_MIC; +#endif + + /* 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); + } +#ifdef CONFIG_OWE_SUPPORT + else if ((KeyDescVer == KEY_DESC_NOT_DEFINED) && + (StaAuthMode == Ndis802_11AuthModeOWE) && + (key_deri_alg == SEC_KEY_DERI_SHA256)) { + RT_HMAC_SHA256(PTK, LEN_PTK_KCK, OutBuffer, FrameLen, mic, LEN_KEY_DESC_MIC); + mic_len = LEN_KEY_DESC_MIC; + } else if ((KeyDescVer == KEY_DESC_NOT_DEFINED) && + (StaAuthMode == Ndis802_11AuthModeOWE) && + (key_deri_alg == SEC_KEY_DERI_SHA384)) { + /*TODO: OWE SHA521*/ + RT_HMAC_SHA384(PTK, LEN_PTK_KCK_SHA384, OutBuffer, FrameLen, mic, LEN_KEY_DESC_MIC_SHA384); + mic_len = LEN_KEY_DESC_MIC_SHA384; + } +#endif + else if ((KeyDescVer == KEY_DESC_EXT) || (KeyDescVer == KEY_DESC_OSEN) +#ifdef DOT11_SAE_SUPPORT + || (KeyDescVer == KEY_DESC_NOT_DEFINED) +#endif + ) { + UINT mlen = AES_KEY128_LENGTH; + AES_CMAC(OutBuffer, FrameLen, PTK, LEN_PTK_KCK, mic, &mlen); + } + + /* store the calculated MIC*/ +#ifndef CONFIG_OWE_SUPPORT + NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, LEN_KEY_DESC_MIC); +#else + NdisMoveMemory(pMsg->KeyDesc.KeyMic, mic, mic_len); +#endif + + os_free_mem(NULL, OutBuffer); +} + + +/* For TKIP frame, calculate the MIC value */ +BOOLEAN rtmp_chk_tkip_mic(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, RX_BLK *pRxBlk) +{ + HEADER_802_11 *pHeader = pRxBlk->pHeader; + UCHAR *pData = pRxBlk->pData; + USHORT DataSize = pRxBlk->DataSize; + UCHAR UserPriority = pRxBlk->UserPriority; + PCIPHER_KEY pWpaKey; + UCHAR *pDA, *pSA; + + if ((pHeader->FC.FrDs == 1) && (pHeader->FC.ToDs == 1)) { + pDA = pHeader->Addr3; + pSA = (PUCHAR)pHeader + sizeof(HEADER_802_11); + } + else if ((pHeader->FC.FrDs == 1) && (pHeader->FC.ToDs == 0)) { + pDA = pHeader->Addr1; + pSA = pHeader->Addr3; + } else if ((pHeader->FC.FrDs == 0) && (pHeader->FC.ToDs == 1)) { + pDA = pHeader->Addr3; + pSA = pHeader->Addr2; + } else { + /* FrDS = 0; ToDS = 0 => IBSS, Non-AP to Non-AP in BSS */ + pDA = pHeader->Addr1; + pSA = pHeader->Addr2; + } + + pWpaKey = &pEntry->PairwiseKey; + if (RTMPTkipCompareMICValue(pAd, + pData, + pDA, + pSA, + pWpaKey->RxMic, + UserPriority, + DataSize) == FALSE) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, ("Rx MIC Value error 2\n")); + + +#ifdef CONFIG_AP_SUPPORT + if (RX_BLK_TEST_FLAG(pRxBlk, fRX_STA)) + { + RTMP_HANDLE_COUNTER_MEASURE(pAd, pEntry); + } +#endif /* CONFIG_AP_SUPPORT */ + + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + return FALSE; + } + + return TRUE; +} + + +UCHAR RTMPExtractKeyIdxFromIVHdr(UCHAR *pIV, UINT8 CipherAlg) +{ + UCHAR keyIdx = 0xFF; + + /* extract the key index from IV header */ + switch (CipherAlg) + { + case Ndis802_11WEPEnabled: + case Ndis802_11TKIPEnable: + case Ndis802_11AESEnable: + case Ndis802_11GroupWEP40Enabled: + case Ndis802_11GroupWEP104Enabled: + keyIdx = (*(pIV + 3) & 0xc0) >> 6; + break; + +#ifdef WAPI_SUPPORT + case Ndis802_11EncryptionSMS4Enabled: + keyIdx = *(pIV) & 0xFF; + break; +#endif /* WAPI_SUPPORT */ + } + + return keyIdx; + +} + +CIPHER_KEY *RTMPSwCipherKeySelection( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pIV, + IN RX_BLK *pRxBlk, + IN MAC_TABLE_ENTRY *pEntry) +{ + PCIPHER_KEY pKey = NULL; + UCHAR keyIdx = 0; + UINT8 CipherAlg = Ndis802_11EncryptionDisabled; + + if ((pEntry == NULL) || + (RX_BLK_TEST_FLAG(pRxBlk, fRX_STA)) || + (RX_BLK_TEST_FLAG(pRxBlk, fRX_WDS)) || + (RX_BLK_TEST_FLAG(pRxBlk, fRX_MESH))) + return NULL; + + if (pRxBlk->pRxInfo->U2M) + { + CipherAlg = pEntry->WepStatus; + } + else + { + } + + if ((keyIdx = RTMPExtractKeyIdxFromIVHdr(pIV, CipherAlg)) > 3) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : Invalid key index(%d) !!!\n", + __FUNCTION__, keyIdx)); + return NULL; + } + + if ((CipherAlg == Ndis802_11WEPEnabled) + || (CipherAlg == Ndis802_11GroupWEP40Enabled) + || (CipherAlg == Ndis802_11GroupWEP104Enabled)) + { + pKey = &pAd->SharedKey[pEntry->func_tb_idx][keyIdx]; + } + else if ((CipherAlg == Ndis802_11TKIPEnable) || + (CipherAlg == Ndis802_11AESEnable)) + { + if (pRxBlk->pRxInfo->U2M) + pKey = &pEntry->PairwiseKey; + else { + pKey = &pAd->SharedKey[pEntry->func_tb_idx][keyIdx]; + } + } +#ifdef WAPI_SUPPORT + else if (CipherAlg == Ndis802_11EncryptionSMS4Enabled) + { + if (pRxBlk->pRxInfo->U2M) + pKey = &pEntry->PairwiseKey; + else + pKey = &pAd->SharedKey[pEntry->func_tb_idx][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; + + } + +#ifdef DOT11W_PMF_SUPPORT + /* Get group mamagement cipher */ + if (len < LEN_OUI_SUITE) + { + DBGPRINT(RT_DEBUG_TRACE, ("[PMF]%s : The peer RSNIE doesn't include Group_mgmt_cipher_suite\n", __FUNCTION__)); + goto out; + } + else + { + offset = LEN_OUI_SUITE; + + /* Get Group-Mgmt-Cipher_Suite information */ + if (type == G_MGMT_SUITE) + { + *count = 1; + return pBuf; + } + else + { + /* skip the Group-Mgmt-Cipher_Suite field */ + pBuf += offset; + len -= offset; + } + } +#endif /* DOT11W_PMF_SUPPORT */ + +out: + *count = 0; + return NULL; + +} + +VOID WpaShowAllsuite( + IN PUINT8 rsnie, + IN UINT rsnie_len) +{ + PUINT8 pSuite = NULL; + UINT8 count; + + hex_dump("RSNIE", rsnie, rsnie_len); + + /* group cipher*/ + if ((pSuite = WPA_ExtractSuiteFromRSNIE(rsnie, rsnie_len, GROUP_SUITE, &count)) != NULL) + { + hex_dump("group cipher", pSuite, 4*count); + } + + /* pairwise cipher*/ + if ((pSuite = WPA_ExtractSuiteFromRSNIE(rsnie, rsnie_len, PAIRWISE_SUITE, &count)) != NULL) + { + hex_dump("pairwise cipher", pSuite, 4*count); + } + + /* AKM*/ + if ((pSuite = WPA_ExtractSuiteFromRSNIE(rsnie, rsnie_len, AKM_SUITE, &count)) != NULL) + { + hex_dump("AKM suite", pSuite, 4*count); + } + + /* PMKID*/ + if ((pSuite = WPA_ExtractSuiteFromRSNIE(rsnie, rsnie_len, PMKID_LIST, &count)) != NULL) + { + hex_dump("PMKID", pSuite, LEN_PMKID); + } + +} + +VOID RTMPInsertRSNIE( + IN PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUINT8 rsnie_ptr, + IN UINT8 rsnie_len, + IN PUINT8 pmkid_ptr, + IN UINT8 pmkid_len) +{ + PUCHAR pTmpBuf; + ULONG TempLen = 0; + UINT8 extra_len = 0; + UINT16 pmk_count = 0; + UCHAR ie_num; + UINT8 total_len = 0; + UCHAR WPA2_OUI[3]={0x00,0x0F,0xAC}; + + pTmpBuf = pFrameBuf; + + /* PMKID-List Must larger than 0 and the multiple of 16. */ + if (pmkid_len > 0 && ((pmkid_len & 0x0f) == 0)) + { + extra_len = sizeof(UINT16) + pmkid_len; + + pmk_count = (pmkid_len >> 4); + pmk_count = cpu2le16(pmk_count); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s : no PMKID-List included(%d).\n", __FUNCTION__, pmkid_len)); + } + + if (rsnie_len != 0) + { + ie_num = IE_WPA; + total_len = rsnie_len; + + if (NdisEqualMemory(rsnie_ptr + 2, WPA2_OUI, sizeof(WPA2_OUI))) + { + ie_num = IE_RSN; + total_len += extra_len; + } + + /* construct RSNIE body */ + MakeOutgoingFrame(pTmpBuf, &TempLen, + 1, &ie_num, + 1, &total_len, + rsnie_len, rsnie_ptr, + END_OF_ARGS); + + pTmpBuf += TempLen; + *pFrameLen = *pFrameLen + TempLen; + + if (ie_num == IE_RSN) + { + /* Insert PMKID-List field */ + if (extra_len > 0) + { + MakeOutgoingFrame(pTmpBuf, &TempLen, + 2, &pmk_count, + pmkid_len, pmkid_ptr, + END_OF_ARGS); + + pTmpBuf += TempLen; + *pFrameLen = *pFrameLen + TempLen; + } + } + } + + return; +} + + +VOID WPAInstallPairwiseKey( + PRTMP_ADAPTER pAd, + UINT8 BssIdx, + PMAC_TABLE_ENTRY pEntry, + BOOLEAN bAE) +{ + NdisZeroMemory(&pEntry->PairwiseKey, sizeof(CIPHER_KEY)); + + /* Assign the pairwise cipher algorithm */ + if (pEntry->WepStatus == Ndis802_11TKIPEnable) + pEntry->PairwiseKey.CipherAlg = CIPHER_TKIP; + else if (pEntry->WepStatus == Ndis802_11AESEnable) + pEntry->PairwiseKey.CipherAlg = CIPHER_AES; +#ifdef CONFIG_OWE_SUPPORT + else if (pEntry->AuthMode == Ndis802_11AuthModeOWE && pEntry->key_deri_alg == SEC_KEY_DERI_SHA256) + pEntry->PairwiseKey.CipherAlg = CIPHER_AES; +#endif + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : fails (wcid-%d)\n", + __FUNCTION__, pEntry->wcid)); + return; + } + + /* Assign key material and its length */ + pEntry->PairwiseKey.KeyLen = LEN_TK; + NdisMoveMemory(pEntry->PairwiseKey.Key, &pEntry->PTK[OFFSET_OF_PTK_TK], LEN_TK); + if (pEntry->PairwiseKey.CipherAlg == CIPHER_TKIP) + { + if (bAE) + { + NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pEntry->PTK[OFFSET_OF_AP_TKIP_TX_MIC], LEN_TKIP_MIC); + NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pEntry->PTK[OFFSET_OF_AP_TKIP_RX_MIC], LEN_TKIP_MIC); + } + else + { + NdisMoveMemory(pEntry->PairwiseKey.TxMic, &pEntry->PTK[OFFSET_OF_STA_TKIP_TX_MIC], LEN_TKIP_MIC); + NdisMoveMemory(pEntry->PairwiseKey.RxMic, &pEntry->PTK[OFFSET_OF_STA_TKIP_RX_MIC], LEN_TKIP_MIC); + } + } + +#ifdef SOFT_ENCRYPT + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_SOFTWARE_ENCRYPT)) + { + DBGPRINT(RT_DEBUG_TRACE, ("===> SW_ENC ON(wcid=%d) \n", pEntry->wcid)); + NdisZeroMemory(pEntry->PairwiseKey.TxTsc, LEN_WPA_TSC); + NdisZeroMemory(pEntry->PairwiseKey.RxTsc, LEN_WPA_TSC); + } + else +#endif /* SOFT_ENCRYPT */ + { + /* Add Pair-wise key to Asic */ + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->wcid, + &pEntry->PairwiseKey); + + RTMPSetWcidSecurityInfo(pAd, + BssIdx, + 0, + pEntry->PairwiseKey.CipherAlg, + (UCHAR)pEntry->wcid, + PAIRWISEKEYTABLE); + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + CmdProcAddRemoveKey(pAd, 0, BssIdx, 0, pEntry->wcid, PAIRWISEKEYTABLE, &pEntry->PairwiseKey, pEntry->Addr); +#endif + } + +} + +VOID WPAInstallSharedKey( + PRTMP_ADAPTER pAd, + UINT8 GroupCipher, + UINT8 BssIdx, + UINT8 KeyIdx, + UINT8 Wcid, + BOOLEAN bAE, + PUINT8 pGtk, + UINT8 GtkLen) +{ + PCIPHER_KEY pSharedKey = NULL; + + 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; + } + +#if (defined(MT_MAC) && defined(APCLI_SUPPORT)) +#ifdef MULTI_APCLI_SUPPORT + if (Wcid == APCLI_MCAST_WCID(BssIdx)) + { + PAPCLI_STRUCT pApCliEntry = NULL; + pApCliEntry = &pAd->ApCfg.ApCliTab[BssIdx]; + if (KeyIdx < SHARE_KEY_NUM ) + pSharedKey = &pApCliEntry->SharedKey[KeyIdx]; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():%d Over buffer size!\n", __FUNCTION__,__LINE__)); + } + } +#else /* MULTI_APCLI_SUPPORT */ + if (Wcid == APCLI_MCAST_WCID) + { + PAPCLI_STRUCT pApCliEntry = NULL; + pApCliEntry = &pAd->ApCfg.ApCliTab[0];//TODO: Carter, find a better way to know index. + if (KeyIdx < SHARE_KEY_NUM ) + pSharedKey = &pApCliEntry->SharedKey[KeyIdx]; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():%d Over buffer size!\n", __FUNCTION__,__LINE__)); + } + } +#endif /* !MULTI_APCLI_SUPPORT */ + else +#endif + { + UINT32 u4MaxSharedKeySize = 0; + UINT32 u4MaxSharedKeyLen = 0; + u4MaxSharedKeySize = sizeof(pAd->SharedKey)/sizeof(pAd->SharedKey[0]); + u4MaxSharedKeyLen = sizeof(pAd->SharedKey[0])/sizeof(pAd->SharedKey[0][0]); + + if((BssIdx >= u4MaxSharedKeySize) || (KeyIdx >= u4MaxSharedKeyLen)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():%d Over buffer size!\n", __FUNCTION__,__LINE__)); + } + else + pSharedKey = &pAd->SharedKey[BssIdx][KeyIdx]; + } + + if(pSharedKey) + NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY)); + + /* Set the group cipher */ + if (!pSharedKey) + return; + + if (GroupCipher == Ndis802_11GroupWEP40Enabled) + pSharedKey->CipherAlg = CIPHER_WEP64; + else if (GroupCipher == Ndis802_11GroupWEP104Enabled) + pSharedKey->CipherAlg = CIPHER_WEP128; + else if (GroupCipher == Ndis802_11TKIPEnable) + pSharedKey->CipherAlg = CIPHER_TKIP; + else if (GroupCipher == Ndis802_11AESEnable) + pSharedKey->CipherAlg = CIPHER_AES; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : fails (IF/ra%d) \n", + __FUNCTION__, BssIdx)); + return; + } + + /* Set the key material and its length */ + if (GroupCipher == Ndis802_11GroupWEP40Enabled || + GroupCipher == Ndis802_11GroupWEP104Enabled) + { + /* Sanity check the length */ + if ((GtkLen != LEN_WEP64) && (GtkLen != LEN_WEP128)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : (IF/ra%d) WEP key invlaid(%d) \n", + __FUNCTION__, BssIdx, GtkLen)); + return; + } + + pSharedKey->KeyLen = GtkLen; + NdisMoveMemory(pSharedKey->Key, pGtk, GtkLen); + } + else + { + /* Sanity check the length */ + if (GtkLen < LEN_TK) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : (IF/ra%d) WPA key invlaid(%d) \n", + __FUNCTION__, BssIdx, GtkLen)); + return; + } + + pSharedKey->KeyLen = LEN_TK; + NdisMoveMemory(pSharedKey->Key, pGtk, LEN_TK); + if (pSharedKey->CipherAlg == CIPHER_TKIP) + { + if (bAE) + { + NdisMoveMemory(pSharedKey->TxMic, pGtk + 16, LEN_TKIP_MIC); + NdisMoveMemory(pSharedKey->RxMic, pGtk + 24, LEN_TKIP_MIC); + } + else + { + NdisMoveMemory(pSharedKey->TxMic, pGtk + 24, LEN_TKIP_MIC); + NdisMoveMemory(pSharedKey->RxMic, pGtk + 16, LEN_TKIP_MIC); + } + } + } + + /* Update group key table(0x6C00) and group key mode(0x7000) */ + AsicAddSharedKeyEntry( + pAd, + BssIdx, + KeyIdx, + pSharedKey); + + /* When Wcid isn't zero, it means that this is a Authenticator Role. + Only Authenticator entity needs to set HW IE/EIV table (0x6000) + and WCID attribute table (0x6800) for group key. */ + if (Wcid != 0) + { + RTMPSetWcidSecurityInfo(pAd, + BssIdx, + KeyIdx, + pSharedKey->CipherAlg, + Wcid, + SHAREDKEYTABLE); + } +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + CmdProcAddRemoveKey(pAd, 0, BssIdx, KeyIdx, Wcid, SHAREDKEYTABLE, pSharedKey, BROADCAST_ADDR); +#endif +} + +VOID RTMPSetWcidSecurityInfo( + PRTMP_ADAPTER pAd, + UINT8 BssIdx, + UINT8 KeyIdx, + UINT8 CipherAlg, + UINT8 Wcid, + UINT8 KeyTabFlag) +{ + UINT32 IV = 0; + UINT8 IV_KEYID = 0; + + /* Prepare initial IV value */ + if (CipherAlg == CIPHER_WEP64 || CipherAlg == CIPHER_WEP128) + { + INT i; + UCHAR TxTsc[LEN_WEP_TSC]; + + /* Generate 3-bytes IV randomly for encryption using */ + for(i = 0; i < LEN_WEP_TSC; i++) + TxTsc[i] = RandomByte(pAd); + + /* Update HW IVEIV table */ + IV_KEYID = (KeyIdx << 6); + IV = (IV_KEYID << 24) | + (TxTsc[2] << 16) | + (TxTsc[1] << 8) | + (TxTsc[0]); + } + else if (CipherAlg == CIPHER_TKIP || CipherAlg == CIPHER_AES) + { + /* Set IVEIV as 1 in Asic - + In IEEE 802.11-2007 8.3.3.4.3 described : + The PN shall be implemented as a 48-bit monotonically incrementing + non-negative integer, initialized to 1 when the corresponding + temporal key is initialized or refreshed. */ + IV_KEYID = (KeyIdx << 6) | 0x20; + IV = (IV_KEYID << 24) | 1; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : Unsupport cipher Alg (%d) for Wcid-%d \n", + __FUNCTION__, CipherAlg, Wcid)); + return; + } + /* Update WCID IV/EIV table */ + AsicUpdateWCIDIVEIV(pAd, Wcid, IV, 0); + + /* Update WCID attribute entry */ + AsicUpdateWcidAttributeEntry(pAd, + BssIdx, + KeyIdx, + CipherAlg, + Wcid, + KeyTabFlag); + +} + + +#ifdef CONFIG_OWE_SUPPORT + + +VOID HKDF_expand_sha384(IN UCHAR *secret, + IN INT secret_len, + IN UCHAR *info, + IN INT info_len, + OUT UCHAR *output, + INT output_Len) +{ + UCHAR T[SHA384_DIGEST_SIZE]; + UCHAR iter = 1; + const unsigned char *addr[3]; + UINT len[3]; + UINT pos, clen; + + addr[0] = T; + len[0] = SHA384_DIGEST_SIZE; + addr[1] = info; + len[1] = info_len; + addr[2] = &iter; + len[2] = 1; + + RT_HMAC_SHA384_VECTOR(secret, secret_len, 2, &addr[1], &len[1], T, SHA384_DIGEST_SIZE); + + pos = 0; + for (;;) { + clen = output_Len - pos; + if (clen > SHA384_DIGEST_SIZE) + clen = SHA384_DIGEST_SIZE; + memcpy(output + pos, T, clen); + pos += clen; + + if (pos == output_Len) + break; + + if (iter == 255) { + os_zero_mem(output, output_Len); + os_zero_mem(T, SHA384_DIGEST_SIZE); + return; + } + iter++; + + RT_HMAC_SHA384_VECTOR(secret, secret_len, 3, addr, len, T, SHA384_DIGEST_SIZE); + } + + os_zero_mem(T, SHA384_DIGEST_SIZE); +} + +VOID HKDF_expand_sha256(IN UCHAR *secret, + IN INT secret_len, + IN UCHAR *info, + IN INT info_len, + OUT UCHAR *output, + INT output_Len) +{ + UCHAR T[SHA256_DIGEST_SIZE]; + UCHAR iter = 1; + const unsigned char *addr[3]; + UINT len[3]; + UINT pos, clen; + + addr[0] = T; + len[0] = SHA256_DIGEST_SIZE; + addr[1] = info; + len[1] = info_len; + addr[2] = &iter; + len[2] = 1; + + RT_HMAC_SHA256_VECTOR(secret, secret_len, 2, &addr[1], &len[1], T, SHA256_DIGEST_SIZE); + + pos = 0; + for (;;) { + clen = output_Len - pos; + if (clen > SHA256_DIGEST_SIZE) + clen = SHA256_DIGEST_SIZE; + memcpy(output + pos, T, clen); + pos += clen; + + if (pos == output_Len) + break; + + if (iter == 255) { + os_zero_mem(output, output_Len); + os_zero_mem(T, SHA256_DIGEST_SIZE); + return; + } + iter++; + + RT_HMAC_SHA256_VECTOR(secret, secret_len, 3, addr, len, T, SHA256_DIGEST_SIZE); + } + + os_zero_mem(T, SHA256_DIGEST_SIZE); +} + +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_aes.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_aes.c new file mode 100644 index 000000000..a2d8f6a93 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_aes.c @@ -0,0 +1,1599 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + Module Name: + AES + + Abstract: + RFC 3394: Advanced Encryption Standard (AES) Key Wrap Algorithm + RFC 3601: Counter with CBC-MAC (CCM) + RFC 4493: The AES-CMAC Algorithm + FIPS PUBS 197: ADVANCED ENCRYPTION STANDARD (AES) + NIST 800-38A: Recommendation for Block Cipher Modes of Operation + NIST 800-38C: The CCM Mode for Authentication and Confidentiality + + Revision History: + Who When What + -------- ---------- ------------------------------------------ + Eddy 2009/05/19 Create AES-Key Wrap + Eddy 2009/04/20 Create AES-CMAC, AES-CCM + Eddy 2009/01/19 Create AES-128, AES-192, AES-256, AES-CBC +***************************************************************************/ + +#include "crypt_aes.h" + + +/* The value given by [x^(i-1),{00},{00},{00}], with x^(i-1) being powers of x in the field GF(2^8). */ +static const UINT32 aes_rcon[] = { + 0x00000000, 0x01000000, 0x02000000, 0x04000000, + 0x08000000, 0x10000000, 0x20000000, 0x40000000, + 0x80000000, 0x1B000000, 0x36000000}; + +static const UINT8 aes_sbox_enc[] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7 ,0xab, 0x76, /* 0 */ + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4 ,0x72, 0xc0, /* 1 */ + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8 ,0x31, 0x15, /* 2 */ + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27 ,0xb2, 0x75, /* 3 */ + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3 ,0x2f, 0x84, /* 4 */ + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c ,0x58, 0xcf, /* 5 */ + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c ,0x9f, 0xa8, /* 6 */ + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff ,0xf3, 0xd2, /* 7 */ + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d ,0x19, 0x73, /* 8 */ + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e ,0x0b, 0xdb, /* 9 */ + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95 ,0xe4, 0x79, /* a */ + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a ,0xae, 0x08, /* b */ + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd ,0x8b, 0x8a, /* c */ + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1 ,0x1d, 0x9e, /* d */ + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55 ,0x28, 0xdf, /* e */ + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54 ,0xbb, 0x16, /* f */ +}; + +static const UINT8 aes_sbox_dec[] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, /* 0 */ + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, /* 1 */ + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, /* 2 */ + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, /* 3 */ + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, /* 4 */ + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, /* 5 */ + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, /* 6 */ + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, /* 7 */ + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, /* 8 */ + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, /* 9 */ + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, /* a */ + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, /* b */ + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, /* c */ + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, /* d */ + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, /* e */ + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, /* f */ +}; + +/* ArrayIndex*{02} */ +static const UINT8 aes_mul_2[] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, /* 0 */ + 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, /* 1 */ + 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, /* 2 */ + 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, /* 3 */ + 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, /* 4 */ + 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, /* 5 */ + 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, /* 6 */ + 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, /* 7 */ + 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, /* 8 */ + 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, /* 9 */ + 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, /* a */ + 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, /* b */ + 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, /* c */ + 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, /* d */ + 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, /* e */ + 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5, /* f */ +}; + +/* ArrayIndex*{03} */ +static const UINT8 aes_mul_3[] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11, /* 0 */ + 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, /* 1 */ + 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, /* 2 */ + 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41, /* 3 */ + 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, /* 4 */ + 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1, /* 5 */ + 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1, /* 6 */ + 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, /* 7 */ + 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a, /* 8 */ + 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba, /* 9 */ + 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea, /* a */ + 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda, /* b */ + 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a, /* c */ + 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a, /* d */ + 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a, /* e */ + 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a, /* f */ +}; + +/* ArrayIndex*{09} */ +static const UINT8 aes_mul_9[] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, /* 0 */ + 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, /* 1 */ + 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, /* 2 */ + 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc, /* 3 */ + 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, /* 4 */ + 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, /* 5 */ + 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a, /* 6 */ + 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, /* 7 */ + 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, /* 8 */ + 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b, /* 9 */ + 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, /* a */ + 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, /* b */ + 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed, /* c */ + 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, /* d */ + 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, /* e */ + 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46, /* f */ +}; + +/* ArrayIndex*{0b} */ +static const UINT8 aes_mul_b[] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, /* 0 */ + 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, /* 1 */ + 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, /* 2 */ + 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2, /* 3 */ + 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, /* 4 */ + 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, /* 5 */ + 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4, /* 6 */ + 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, /* 7 */ + 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, /* 8 */ + 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e, /* 9 */ + 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, /* a */ + 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, /* b */ + 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, /* c */ + 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, /* d */ + 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, /* e */ + 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3, /* f */ +}; + +/* ArrayIndex*{0d} */ +static const UINT8 aes_mul_d[] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, /* 0 */ + 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, /* 1 */ + 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, /* 2 */ + 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20, /* 3 */ + 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, /* 4 */ + 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, /* 5 */ + 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d, /* 6 */ + 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, /* 7 */ + 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, /* 8 */ + 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, /* 9 */ + 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, /* a */ + 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, /* b */ + 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, /* c */ + 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, /* d */ + 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, /* e */ + 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97, /* f */ +}; + +/* ArrayIndex*{0e} */ +static const UINT8 aes_mul_e[] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, /* 0 */ + 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, /* 1 */ + 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, /* 2 */ + 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61, /* 3 */ + 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, /* 4 */ + 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, /* 5 */ + 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c, /* 6 */ + 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, /* 7 */ + 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, /* 8 */ + 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, /* 9 */ + 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, /* a */ + 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, /* b */ + 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, /* c */ + 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, /* d */ + 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, /* e */ + 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d, /* f */ +}; + +/* For AES_CMAC */ +#define AES_MAC_LENGTH 16 /* 128-bit string */ +static UINT8 Const_Zero[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static UINT8 Const_Rb[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87}; + +/* +======================================================================== +Routine Description: + AES key expansion (key schedule) + +Arguments: + Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) + KeyLength The length of cipher key in bytes + paes_ctx Pointer to AES_CTX_STRUC + +Return Value: + paes_ctx Retrun the KeyWordExpansion of AES_CTX_STRUC + +Note: + Pseudo code for key expansion + ------------------------------------------ + Nk = (key length/4); + + while (i < Nk) + KeyWordExpansion[i] = word(key[4*i], key[4*i + 1], key[4*i + 2], key[4*i + 3]); + i++; + end while + + while (i < ((key length/4 + 6 + 1)*4) ) + temp = KeyWordExpansion[i - 1]; + if (i % Nk ==0) + temp = SubWord(RotWord(temp)) ^ Rcon[i/Nk]; + else if ((Nk > 6) && (i % 4 == 4)) + temp = SubWord(temp); + end if + + KeyWordExpansion[i] = KeyWordExpansion[i - Nk]^ temp; + i++; + end while +======================================================================== +*/ +VOID RT_AES_KeyExpansion ( + IN UINT8 Key[], + IN UINT KeyLength, + INOUT AES_CTX_STRUC *paes_ctx) +{ + UINT KeyIndex = 0; + UINT NumberOfWordOfKey, NumberOfWordOfKeyExpansion; + UINT8 TempWord[AES_KEY_ROWS], Temp; + UINT32 Temprcon; + + NumberOfWordOfKey = KeyLength >> 2; + while (KeyIndex < NumberOfWordOfKey) + { + paes_ctx->KeyWordExpansion[0][KeyIndex] = Key[4*KeyIndex]; + paes_ctx->KeyWordExpansion[1][KeyIndex] = Key[4*KeyIndex + 1]; + paes_ctx->KeyWordExpansion[2][KeyIndex] = Key[4*KeyIndex + 2]; + paes_ctx->KeyWordExpansion[3][KeyIndex] = Key[4*KeyIndex + 3]; + KeyIndex++; + } + + NumberOfWordOfKeyExpansion = ((UINT) AES_KEY_ROWS) * ((KeyLength >> 2) + 6 + 1); + while (KeyIndex < NumberOfWordOfKeyExpansion) + { + TempWord[0] = paes_ctx->KeyWordExpansion[0][KeyIndex - 1]; + TempWord[1] = paes_ctx->KeyWordExpansion[1][KeyIndex - 1]; + TempWord[2] = paes_ctx->KeyWordExpansion[2][KeyIndex - 1]; + TempWord[3] = paes_ctx->KeyWordExpansion[3][KeyIndex - 1]; + if ((KeyIndex % NumberOfWordOfKey) == 0) { + Temprcon = aes_rcon[KeyIndex/NumberOfWordOfKey]; + Temp = aes_sbox_enc[TempWord[1]]^((Temprcon >> 24) & 0xff); + TempWord[1] = aes_sbox_enc[TempWord[2]]^((Temprcon >> 16) & 0xff); + TempWord[2] = aes_sbox_enc[TempWord[3]]^((Temprcon >> 8) & 0xff); + TempWord[3] = aes_sbox_enc[TempWord[0]]^((Temprcon ) & 0xff); + TempWord[0] = Temp; + } else if ((NumberOfWordOfKey > 6) && ((KeyIndex % NumberOfWordOfKey) == 4)) { + Temp = aes_sbox_enc[TempWord[0]]; + TempWord[1] = aes_sbox_enc[TempWord[1]]; + TempWord[2] = aes_sbox_enc[TempWord[2]]; + TempWord[3] = aes_sbox_enc[TempWord[3]]; + TempWord[0] = Temp; + } + paes_ctx->KeyWordExpansion[0][KeyIndex] = paes_ctx->KeyWordExpansion[0][KeyIndex - NumberOfWordOfKey]^TempWord[0]; + paes_ctx->KeyWordExpansion[1][KeyIndex] = paes_ctx->KeyWordExpansion[1][KeyIndex - NumberOfWordOfKey]^TempWord[1]; + paes_ctx->KeyWordExpansion[2][KeyIndex] = paes_ctx->KeyWordExpansion[2][KeyIndex - NumberOfWordOfKey]^TempWord[2]; + paes_ctx->KeyWordExpansion[3][KeyIndex] = paes_ctx->KeyWordExpansion[3][KeyIndex - NumberOfWordOfKey]^TempWord[3]; + KeyIndex++; + } +} + + +/* +======================================================================== +Routine Description: + AES encryption + +Arguments: + PlainBlock The block of plain text, 16 bytes(128 bits) each block + PlainBlockSize The length of block of plain text in bytes + Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) + KeyLength The length of cipher key in bytes + CipherBlockSize The length of allocated cipher block in bytes + +Return Value: + CipherBlock Return cipher text + CipherBlockSize Return the length of real used cipher block in bytes + +Note: + Reference to FIPS-PUB 197 + 1. Check if block size is 16 bytes(128 bits) and if key length is 16, 24, or 32 bytes(128, 192, or 256 bits) + 2. Transfer the plain block to state block + 3. Main encryption rounds + 4. Transfer the state block to cipher block + ------------------------------------------ + NumberOfRound = (key length / 4) + 6; + state block = plain block; + + AddRoundKey(state block, key); + for round = 1 to NumberOfRound + SubBytes(state block) + ShiftRows(state block) + MixColumns(state block) + AddRoundKey(state block, key); + end for + + SubBytes(state block) + ShiftRows(state block) + AddRoundKey(state block, key); + + cipher block = state block; +======================================================================== +*/ +VOID RT_AES_Encrypt ( + IN UINT8 PlainBlock[], + IN UINT PlainBlockSize, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 CipherBlock[], + INOUT UINT *CipherBlockSize) +{ +/* AES_CTX_STRUC aes_ctx; +*/ + AES_CTX_STRUC *paes_ctx = NULL; + UINT RowIndex, ColumnIndex; + UINT RoundIndex, NumberOfRound = 0; + UINT8 Temp, Row0, Row1, Row2, Row3; + + /* + * 1. Check if block size is 16 bytes(128 bits) and if key length is 16, 24, or 32 bytes(128, 192, or 256 bits) + */ + if (PlainBlockSize != AES_BLOCK_SIZES) { + DBGPRINT(RT_DEBUG_ERROR, ("RT_AES_Encrypt: plain block size is %d bytes, it must be %d bytes(128 bits).\n", + PlainBlockSize, AES_BLOCK_SIZES)); + return; + } + if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) { + DBGPRINT(RT_DEBUG_ERROR, ("RT_AES_Encrypt: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n", + KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH)); + return; + } + if (*CipherBlockSize < AES_BLOCK_SIZES) { + DBGPRINT(RT_DEBUG_ERROR, ("RT_AES_Encrypt: cipher block size is %d bytes, it must be %d bytes(128 bits).\n", + *CipherBlockSize, AES_BLOCK_SIZES)); + return; + } + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&paes_ctx, sizeof(AES_CTX_STRUC)); + if (paes_ctx == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + /* + * 2. Transfer the plain block to state block + */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] = PlainBlock[RowIndex + 4*ColumnIndex]; + + /* + * 3. Main encryption rounds + */ + RT_AES_KeyExpansion(Key, KeyLength, paes_ctx); + NumberOfRound = (KeyLength >> 2) + 6; + + /* AES_AddRoundKey */ + RoundIndex = 0; + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] ^= paes_ctx->KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex]; + + for (RoundIndex = 1; RoundIndex < NumberOfRound;RoundIndex++) + { + /* AES_SubBytes */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] = aes_sbox_enc[paes_ctx->State[RowIndex][ColumnIndex]]; + + /* AES_ShiftRows */ + Temp = paes_ctx->State[1][0]; + paes_ctx->State[1][0] = paes_ctx->State[1][1]; + paes_ctx->State[1][1] = paes_ctx->State[1][2]; + paes_ctx->State[1][2] = paes_ctx->State[1][3]; + paes_ctx->State[1][3] = Temp; + Temp = paes_ctx->State[2][0]; + paes_ctx->State[2][0] = paes_ctx->State[2][2]; + paes_ctx->State[2][2] = Temp; + Temp = paes_ctx->State[2][1]; + paes_ctx->State[2][1] = paes_ctx->State[2][3]; + paes_ctx->State[2][3] = Temp; + Temp = paes_ctx->State[3][3]; + paes_ctx->State[3][3] = paes_ctx->State[3][2]; + paes_ctx->State[3][2] = paes_ctx->State[3][1]; + paes_ctx->State[3][1] = paes_ctx->State[3][0]; + paes_ctx->State[3][0] = Temp; + + /* AES_MixColumns */ + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + { + Row0 = paes_ctx->State[0][ColumnIndex]; + Row1 = paes_ctx->State[1][ColumnIndex]; + Row2 = paes_ctx->State[2][ColumnIndex]; + Row3 = paes_ctx->State[3][ColumnIndex]; + paes_ctx->State[0][ColumnIndex] = aes_mul_2[Row0]^aes_mul_3[Row1]^Row2^Row3; + paes_ctx->State[1][ColumnIndex] = Row0^aes_mul_2[Row1]^aes_mul_3[Row2]^Row3; + paes_ctx->State[2][ColumnIndex] = Row0^Row1^aes_mul_2[Row2]^aes_mul_3[Row3]; + paes_ctx->State[3][ColumnIndex] = aes_mul_3[Row0]^Row1^Row2^aes_mul_2[Row3]; + } + + /* AES_AddRoundKey */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] ^= paes_ctx->KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex]; + } + + /* AES_SubBytes */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] = aes_sbox_enc[paes_ctx->State[RowIndex][ColumnIndex]]; + /* AES_ShiftRows */ + Temp = paes_ctx->State[1][0]; + paes_ctx->State[1][0] = paes_ctx->State[1][1]; + paes_ctx->State[1][1] = paes_ctx->State[1][2]; + paes_ctx->State[1][2] = paes_ctx->State[1][3]; + paes_ctx->State[1][3] = Temp; + Temp = paes_ctx->State[2][0]; + paes_ctx->State[2][0] = paes_ctx->State[2][2]; + paes_ctx->State[2][2] = Temp; + Temp = paes_ctx->State[2][1]; + paes_ctx->State[2][1] = paes_ctx->State[2][3]; + paes_ctx->State[2][3] = Temp; + Temp = paes_ctx->State[3][3]; + paes_ctx->State[3][3] = paes_ctx->State[3][2]; + paes_ctx->State[3][2] = paes_ctx->State[3][1]; + paes_ctx->State[3][1] = paes_ctx->State[3][0]; + paes_ctx->State[3][0] = Temp; + /* AES_AddRoundKey */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] ^= paes_ctx->KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex]; + + /* + * 4. Transfer the state block to cipher block + */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + CipherBlock[RowIndex + 4*ColumnIndex] = paes_ctx->State[RowIndex][ColumnIndex]; + + *CipherBlockSize = ((UINT) AES_STATE_ROWS)*((UINT) AES_STATE_COLUMNS); + + if (paes_ctx != NULL) + os_free_mem(NULL, paes_ctx); +} + + +/* +======================================================================== +Routine Description: + AES decryption + +Arguments: + CipherBlock The block of cipher text, 16 bytes(128 bits) each block + CipherBlockSize The length of block of cipher text in bytes + Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) + KeyLength The length of cipher key in bytes + PlainBlockSize The length of allocated plain block in bytes + +Return Value: + PlainBlock Return plain text + PlainBlockSize Return the length of real used plain block in bytes + +Note: + Reference to FIPS-PUB 197 + 1. Check if block size is 16 bytes(128 bits) and if key length is 16, 24, or 32 bytes(128, 192, or 256 bits) + 2. Transfer the cipher block to state block + 3. Main decryption rounds + 4. Transfer the state block to plain block + ------------------------------------------ + NumberOfRound = (key length / 4) + 6; + state block = cipher block; + + AddRoundKey(state block, key); + for round = NumberOfRound to 1 + InvSubBytes(state block) + InvShiftRows(state block) + InvMixColumns(state block) + AddRoundKey(state block, key); + end for + + InvSubBytes(state block) + InvShiftRows(state block) + AddRoundKey(state block, key); + + plain block = state block; +======================================================================== +*/ +VOID RT_AES_Decrypt ( + IN UINT8 CipherBlock[], + IN UINT CipherBlockSize, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 PlainBlock[], + INOUT UINT *PlainBlockSize) +{ +/* AES_CTX_STRUC aes_ctx; +*/ + AES_CTX_STRUC *paes_ctx = NULL; + UINT RowIndex, ColumnIndex; + UINT RoundIndex, NumberOfRound = 0; + UINT8 Temp, Row0, Row1, Row2, Row3; + + /* + * 1. Check if block size is 16 bytes(128 bits) and if key length is 16, 24, or 32 bytes(128, 192, or 256 bits) + */ + if (*PlainBlockSize < AES_BLOCK_SIZES) { + DBGPRINT(RT_DEBUG_ERROR, ("RT_AES_Decrypt: plain block size is %d bytes, it must be %d bytes(128 bits).\n", + *PlainBlockSize, AES_BLOCK_SIZES)); + return; + } + if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) { + DBGPRINT(RT_DEBUG_ERROR, ("RT_AES_Decrypt: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n", + KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH)); + return; + } + if (CipherBlockSize != AES_BLOCK_SIZES) { + DBGPRINT(RT_DEBUG_ERROR, ("RT_AES_Decrypt: cipher block size is %d bytes, it must be %d bytes(128 bits).\n", + CipherBlockSize, AES_BLOCK_SIZES)); + return; + } + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&paes_ctx, sizeof(AES_CTX_STRUC)); + if (paes_ctx == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + /* + * 2. Transfer the cipher block to state block + */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] = CipherBlock[RowIndex + 4*ColumnIndex]; + + /* + * 3. Main decryption rounds + */ + RT_AES_KeyExpansion(Key, KeyLength, paes_ctx); + NumberOfRound = (KeyLength >> 2) + 6; + + /* AES_AddRoundKey */ + RoundIndex = NumberOfRound; + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] ^= paes_ctx->KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex]; + + for (RoundIndex = (NumberOfRound - 1); RoundIndex > 0 ;RoundIndex--) + { + /* AES_InvShiftRows */ + Temp = paes_ctx->State[1][3]; + paes_ctx->State[1][3] = paes_ctx->State[1][2]; + paes_ctx->State[1][2] = paes_ctx->State[1][1]; + paes_ctx->State[1][1] = paes_ctx->State[1][0]; + paes_ctx->State[1][0] = Temp; + Temp = paes_ctx->State[2][0]; + paes_ctx->State[2][0] = paes_ctx->State[2][2]; + paes_ctx->State[2][2] = Temp; + Temp = paes_ctx->State[2][1]; + paes_ctx->State[2][1] = paes_ctx->State[2][3]; + paes_ctx->State[2][3] = Temp; + Temp = paes_ctx->State[3][0]; + paes_ctx->State[3][0] = paes_ctx->State[3][1]; + paes_ctx->State[3][1] = paes_ctx->State[3][2]; + paes_ctx->State[3][2] = paes_ctx->State[3][3]; + paes_ctx->State[3][3] = Temp; + + /* AES_InvSubBytes */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] = aes_sbox_dec[paes_ctx->State[RowIndex][ColumnIndex]]; + + /* AES_AddRoundKey */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] ^= paes_ctx->KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex]; + + /* AES_InvMixColumns */ + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + { + Row0 = paes_ctx->State[0][ColumnIndex]; + Row1 = paes_ctx->State[1][ColumnIndex]; + Row2 = paes_ctx->State[2][ColumnIndex]; + Row3 = paes_ctx->State[3][ColumnIndex]; + paes_ctx->State[0][ColumnIndex] = aes_mul_e[Row0]^aes_mul_b[Row1]^aes_mul_d[Row2]^aes_mul_9[Row3]; + paes_ctx->State[1][ColumnIndex] = aes_mul_9[Row0]^aes_mul_e[Row1]^aes_mul_b[Row2]^aes_mul_d[Row3]; + paes_ctx->State[2][ColumnIndex] = aes_mul_d[Row0]^aes_mul_9[Row1]^aes_mul_e[Row2]^aes_mul_b[Row3]; + paes_ctx->State[3][ColumnIndex] = aes_mul_b[Row0]^aes_mul_d[Row1]^aes_mul_9[Row2]^aes_mul_e[Row3]; + } + } + + /* AES_InvShiftRows */ + Temp = paes_ctx->State[1][3]; + paes_ctx->State[1][3] = paes_ctx->State[1][2]; + paes_ctx->State[1][2] = paes_ctx->State[1][1]; + paes_ctx->State[1][1] = paes_ctx->State[1][0]; + paes_ctx->State[1][0] = Temp; + Temp = paes_ctx->State[2][0]; + paes_ctx->State[2][0] = paes_ctx->State[2][2]; + paes_ctx->State[2][2] = Temp; + Temp = paes_ctx->State[2][1]; + paes_ctx->State[2][1] = paes_ctx->State[2][3]; + paes_ctx->State[2][3] = Temp; + Temp = paes_ctx->State[3][0]; + paes_ctx->State[3][0] = paes_ctx->State[3][1]; + paes_ctx->State[3][1] = paes_ctx->State[3][2]; + paes_ctx->State[3][2] = paes_ctx->State[3][3]; + paes_ctx->State[3][3] = Temp; + /* AES_InvSubBytes */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] = aes_sbox_dec[paes_ctx->State[RowIndex][ColumnIndex]]; + /* AES_AddRoundKey */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + paes_ctx->State[RowIndex][ColumnIndex] ^= paes_ctx->KeyWordExpansion[RowIndex][(RoundIndex*((UINT) AES_STATE_COLUMNS)) + ColumnIndex]; + + /* + * 4. Transfer the state block to plain block + */ + for (RowIndex = 0; RowIndex < AES_STATE_ROWS;RowIndex++) + for (ColumnIndex = 0; ColumnIndex < AES_STATE_COLUMNS;ColumnIndex++) + PlainBlock[RowIndex + 4*ColumnIndex] = paes_ctx->State[RowIndex][ColumnIndex]; + + *PlainBlockSize = ((UINT) AES_STATE_ROWS)*((UINT) AES_STATE_COLUMNS); + + if (paes_ctx != NULL) + os_free_mem(NULL, paes_ctx); +} + + + +/* +======================================================================== +Routine Description: + AES-CBCMAC + +Arguments: + Payload Data + PayloadLength The length of data in bytes + Key Cipher key + KeyLength The length of cipher key in bytes depend on block cipher (16, 24, or 32 bytes) + Nonce Nonce + NonceLength The length of nonce in bytes + AAD Additional authenticated data + AADLength The length of AAD in bytes + MACLength The length of MAC in bytes + +Return Value: + MACText The mac + +Note: + Reference to RFC 3601, and NIST 800-38C. +======================================================================== +*/ +VOID AES_CCM_MAC ( + IN UINT8 Payload[], + IN UINT PayloadLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 Nonce[], + IN UINT NonceLength, + IN UINT8 AAD[], + IN UINT AADLength, + IN UINT MACLength, + OUT UINT8 MACText[]) +{ + UINT8 Block[AES_BLOCK_SIZES], Block_MAC[AES_BLOCK_SIZES]; + UINT Block_Index = 0, ADD_Index = 0, Payload_Index = 0; + UINT Temp_Value = 0, Temp_Index = 0, Temp_Length = 0, Copy_Length = 0; + + /* + * 1. Formatting of the Control Information and the Nonce + */ + NdisZeroMemory(Block, AES_BLOCK_SIZES); + if (AADLength > 0) + Block[0] |= 0x40; /* Set bit 6 to 1 */ + Temp_Value = ((MACLength - 2) >> 1) << 3; /* Set bit 3-5 to (t-2)/2 */ + Block[0] |= Temp_Value; + Temp_Value = (15 - NonceLength) - 1; /* Set bit 0-2 to (q-1), q = 15 - Nonce Length */ + Block[0] |= Temp_Value; + for (Temp_Index = 0; Temp_Index < NonceLength; Temp_Index++) + Block[Temp_Index + 1] = Nonce[Temp_Index]; + if (NonceLength < 12) + Block[12] = (PayloadLength >> 24) & 0xff; + if (NonceLength < 13) + Block[13] = (PayloadLength >> 16) & 0xff; + Block[14] = (PayloadLength >> 8) & 0xff; + Block[15] = PayloadLength & 0xff; + + NdisZeroMemory(Block_MAC, AES_BLOCK_SIZES); + Temp_Length = sizeof(Block_MAC); + RT_AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, Block_MAC, &Temp_Length); + + /* + * 2. Formatting of the Associated Data + * If 0 < AADLength < (2^16 - 2^8), AData_Length = 2 + * If (2^16 - 2^8) < AADLength < 2^32, AData_Length = 6 + * If 2^32 < AADLength < 2^64, AData_Length = 10 (not implement) + */ + NdisZeroMemory(Block, AES_BLOCK_SIZES); + if ((AADLength > 0) && (AADLength < 0xFF00)) { + Block_Index = 2; + Block[0] = (AADLength >> 8) & 0xff; + Block[1] = AADLength & 0xff; + } else { + Block_Index = 6; + Block[2] = (AADLength >> 24) & 0xff; + Block[3] = (AADLength >> 16) & 0xff; + Block[4] = (AADLength >> 8) & 0xff; + Block[5] = AADLength & 0xff; + } + + while (ADD_Index < AADLength) + { + Copy_Length = AADLength - ADD_Index; + if (Copy_Length > AES_BLOCK_SIZES) + Copy_Length = AES_BLOCK_SIZES; + if ((Copy_Length + Block_Index) > AES_BLOCK_SIZES) { + Copy_Length = AES_BLOCK_SIZES - Block_Index; + } + for (Temp_Index = 0; Temp_Index < Copy_Length; Temp_Index++) + { + if((Temp_Index + Block_Index) < AES_BLOCK_SIZES) + Block[Temp_Index + Block_Index] = AAD[ADD_Index + Temp_Index]; + } + for (Temp_Index = 0; Temp_Index < AES_BLOCK_SIZES; Temp_Index++) + Block[Temp_Index] ^= Block_MAC[Temp_Index]; + NdisZeroMemory(Block_MAC, AES_BLOCK_SIZES); + Temp_Length = sizeof(Block_MAC); + RT_AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, Block_MAC, &Temp_Length); + ADD_Index += Copy_Length; + Block_Index = 0; + NdisZeroMemory(Block, AES_BLOCK_SIZES); + } + + /* + * 3. Calculate the MAC (MIC) + */ + while (Payload_Index < PayloadLength) + { + NdisZeroMemory(Block, AES_BLOCK_SIZES); + Copy_Length = PayloadLength - Payload_Index; + if (Copy_Length > AES_BLOCK_SIZES) + Copy_Length = AES_BLOCK_SIZES; + for (Temp_Index = 0; Temp_Index < Copy_Length; Temp_Index++) + Block[Temp_Index] = Payload[Payload_Index + Temp_Index]; + for (Temp_Index = 0; Temp_Index < AES_BLOCK_SIZES; Temp_Index++) + Block[Temp_Index] ^= Block_MAC[Temp_Index]; + NdisZeroMemory(Block_MAC, AES_BLOCK_SIZES); + Temp_Length = sizeof(Block_MAC); + RT_AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, Block_MAC, &Temp_Length); + Payload_Index += Copy_Length; + } + for (Temp_Index = 0; Temp_Index < MACLength; Temp_Index++) + MACText[Temp_Index] = Block_MAC[Temp_Index]; +} + + +/* +======================================================================== +Routine Description: + AES-CBCMAC Encryption + +Arguments: + PlainText Plain text + PlainTextLength The length of plain text in bytes + Key Cipher key + KeyLength The length of cipher key in bytes depend on block cipher (16, 24, or 32 bytes) + Nonce Nonce + NonceLength The length of nonce in bytes + AAD Additional authenticated data + AADLength The length of AAD in bytes + MACLength The length of MAC in bytes + CipherTextLength The length of allocated memory spaces in bytes + +Return Value: + CipherText The ciphertext + CipherTextLength Return the length of the ciphertext in bytes + +Function Value: + 0: Success + -1: The key length must be 16 bytes. + -2: A valid nonce length is 7-13 bytes. + -3: The MAC length must be 4, 6, 8, 10, 12, 14, or 16 bytes. + -4: The CipherTextLength is not enough. + +Note: + Reference to RFC 3601, and NIST 800-38C. + Here, the implement of AES_CCM is suitable for WI_FI. +======================================================================== +*/ +INT AES_CCM_Encrypt ( + IN UINT8 PlainText[], + IN UINT PlainTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 Nonce[], + IN UINT NonceLength, + IN UINT8 AAD[], + IN UINT AADLength, + IN UINT MACLength, + OUT UINT8 CipherText[], + INOUT UINT *CipherTextLength) +{ + UINT8 Block_MAC[AES_BLOCK_SIZES]; + UINT8 Block_CTR[AES_BLOCK_SIZES], Block_CTR_Cipher[AES_BLOCK_SIZES]; + UINT Cipher_Index = 0; + UINT Temp_Value = 0, Temp_Index = 0, Temp_Length = 0, Copy_Length = 0; + + /* + * 1. Check Input Values + * - Key length must be 16 bytes + * - Nonce length range is form 7 to 13 bytes + * - MAC length must be 4, 6, 8, 10, 12, 14, or 16 bytes + * - CipherTextLength > PlainTextLength + MACLength + */ + if (KeyLength != AES_KEY128_LENGTH) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Encrypt: The key length must be %d bytes\n", AES_KEY128_LENGTH)); + return -1; + } + + if ((NonceLength < 7) || (NonceLength > 13)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Encrypt: A valid nonce length is 7-13 bytes\n")); + return -2; + } + + if ((MACLength != 4) && (MACLength != 6) && (MACLength != 8) && (MACLength != 10) + && (MACLength != 12) && (MACLength != 14) && (MACLength != 16)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Encrypt: The MAC length must be 4, 6, 8, 10, 12, 14, or 16 bytes\n")); + return -3; + } + + if (*CipherTextLength < (PlainTextLength + MACLength)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Encrypt: The CipherTextLength is not enough.\n")); + return -4; + } + + + /* + * 1. Formatting of the Counter Block + */ + NdisZeroMemory(Block_CTR, AES_BLOCK_SIZES); + Temp_Value = (15 - NonceLength) - 1; /* Set bit 0-2 to (q-1), q = 15 - Nonce Length */ + Block_CTR[0] |= Temp_Value; + for (Temp_Index = 0; Temp_Index < NonceLength; Temp_Index++) + Block_CTR[Temp_Index + 1] = Nonce[Temp_Index]; + + /* + * 2. Calculate the MAC (MIC) + */ + AES_CCM_MAC(PlainText, PlainTextLength, Key, KeyLength, Nonce, NonceLength, AAD, AADLength, MACLength, Block_MAC); + Temp_Length = sizeof(Block_CTR_Cipher); + RT_AES_Encrypt(Block_CTR, AES_BLOCK_SIZES , Key, KeyLength, Block_CTR_Cipher, &Temp_Length); + for (Temp_Index = 0; Temp_Index < MACLength; Temp_Index++) + Block_MAC[Temp_Index] ^= Block_CTR_Cipher[Temp_Index]; + + /* + * 3. Cipher Payload + */ + while (Cipher_Index < PlainTextLength) + { + Block_CTR[15] += 1; + Temp_Length = sizeof(Block_CTR_Cipher); + RT_AES_Encrypt(Block_CTR, AES_BLOCK_SIZES , Key, KeyLength, Block_CTR_Cipher, &Temp_Length); + + Copy_Length = PlainTextLength - Cipher_Index; + if (Copy_Length > AES_BLOCK_SIZES) + Copy_Length = AES_BLOCK_SIZES; + for (Temp_Index = 0; Temp_Index < Copy_Length; Temp_Index++) + CipherText[Cipher_Index + Temp_Index] = PlainText[Cipher_Index + Temp_Index]^Block_CTR_Cipher[Temp_Index]; + + Cipher_Index += Copy_Length; + } + for (Temp_Index = 0; Temp_Index < MACLength; Temp_Index++) + CipherText[PlainTextLength + Temp_Index] = Block_MAC[Temp_Index]; + *CipherTextLength = PlainTextLength + MACLength; + + return 0; +} + + +/* +======================================================================== +Routine Description: + AES-CBCMAC Decryption + +Arguments: + CipherText The ciphertext + CipherTextLength The length of cipher text in bytes + Key Cipher key + KeyLength The length of cipher key in bytes depend on block cipher (16, 24, or 32 bytes) + Nonce Nonce + NonceLength The length of nonce in bytes + AAD Additional authenticated data + AADLength The length of AAD in bytes + CipherTextLength The length of allocated memory spaces in bytes + +Return Value: + PlainText Plain text + PlainTextLength Return the length of the plain text in bytes + +Function Value: + 0: Success + -1: The key length must be 16 bytes. + -2: A valid nonce length is 7-13 bytes. + -3: The MAC length must be 4, 6, 8, 10, 12, 14, or 16 bytes. + -4: The PlainTextLength is not enough. + -5: The MIC does not match. + +Note: + Reference to RFC 3601, and NIST 800-38C. + Here, the implement of AES_CCM is suitable for WI_FI. +======================================================================== +*/ +INT AES_CCM_Decrypt ( + IN UINT8 CipherText[], + IN UINT CipherTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 Nonce[], + IN UINT NonceLength, + IN UINT8 AAD[], + IN UINT AADLength, + IN UINT MACLength, + OUT UINT8 PlainText[], + INOUT UINT *PlainTextLength) +{ + UINT8 Block_MAC[AES_BLOCK_SIZES], Block_MAC_From_Cipher[AES_BLOCK_SIZES]; + UINT8 Block_CTR[AES_BLOCK_SIZES], Block_CTR_Cipher[AES_BLOCK_SIZES]; + UINT Block_Index = 0, Cipher_Index = 0; + UINT Temp_Value = 0, Temp_Index = 0, Temp_Length = 0, Copy_Length = 0; + + + /* + * 1. Check Input Values + * - Key length must be 16 bytes + * - Nonce length range is form 7 to 13 bytes + */ + if (KeyLength != AES_KEY128_LENGTH) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Decrypt: The key length must be %d bytes\n", AES_KEY128_LENGTH)); + return -1; + } + + if ((NonceLength < 7) || (NonceLength > 13)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Decrypt: A valid nonce length is 7-13 bytes\n")); + return -2; + } + + if ((MACLength != 4) && (MACLength != 6) && (MACLength != 8) && (MACLength != 10) + && (MACLength != 12) && (MACLength != 14) && (MACLength != 16)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Decrypt: The MAC length must be 4, 6, 8, 10, 12, 14, or 16 bytes\n")); + return -3; + } + + if (*PlainTextLength < (CipherTextLength - MACLength)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Decrypt: The PlainTextLength is not enough.\n")); + return -4; + } + + /* + * 2. Formatting of the Counter Block + */ + NdisZeroMemory(Block_CTR, AES_BLOCK_SIZES); + Temp_Value = (15 - NonceLength) - 1; /* Set bit 0-2 to (q-1), q = 15 - Nonce Length */ + Block_CTR[0] |= Temp_Value; + for (Temp_Index = 0; Temp_Index < NonceLength; Temp_Index++) + Block_CTR[Temp_Index + 1] = Nonce[Temp_Index]; + Temp_Length = sizeof(Block_CTR_Cipher); + RT_AES_Encrypt(Block_CTR, AES_BLOCK_SIZES , Key, KeyLength, Block_CTR_Cipher, &Temp_Length); + + /* + * 3. Catch the MAC (MIC) from CipherText + */ + Block_Index = 0; + for (Temp_Index = (CipherTextLength - MACLength); Temp_Index < CipherTextLength; Temp_Index++, Block_Index++) + Block_MAC_From_Cipher[Block_Index] = CipherText[Temp_Index]^Block_CTR_Cipher[Block_Index]; + + /* + * 4. Decryption the Payload + */ + while (Cipher_Index < (CipherTextLength - MACLength)) + { + Block_CTR[15] += 1; + Temp_Length = sizeof(Block_CTR_Cipher); + RT_AES_Encrypt(Block_CTR, AES_BLOCK_SIZES , Key, KeyLength, Block_CTR_Cipher, &Temp_Length); + + Copy_Length = (CipherTextLength - MACLength) - Cipher_Index; + if (Copy_Length > AES_BLOCK_SIZES) + Copy_Length = AES_BLOCK_SIZES; + for (Temp_Index = 0; Temp_Index < Copy_Length; Temp_Index++) + PlainText[Cipher_Index + Temp_Index] = CipherText[Cipher_Index + Temp_Index]^Block_CTR_Cipher[Temp_Index]; + Cipher_Index += Copy_Length; + } + *PlainTextLength = CipherTextLength - MACLength; + + /* + * 5. Calculate the MAC (MIC) from Payload + */ + AES_CCM_MAC(PlainText, *PlainTextLength, Key, KeyLength, Nonce, NonceLength, AAD, AADLength, MACLength, Block_MAC); + + /* + * 6. Check the MIC + */ + if (NdisCmpMemory(Block_MAC_From_Cipher, Block_MAC, MACLength) != 0) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CCM_Decrypt: The MIC does not match.\n")); + return -5; + } + + return 0; +} + + +/* +======================================================================== +Routine Description: + AES-CMAC generate subkey + +Arguments: + Key Cipher key 128 bits + KeyLength The length of Cipher key in bytes + +Return Value: + SubKey1 SubKey 1 128 bits + SubKey2 SubKey 2 128 bits + +Note: + Reference to RFC 4493 + + Step 1. L := AES-128(K, const_Zero); + Step 2. if MSB(L) is equal to 0 + then K1 := L << 1; + else K1 := (L << 1) XOR const_Rb; + Step 3. if MSB(K1) is equal to 0 + then K2 := K1 << 1; + else K2 := (K1 << 1) XOR const_Rb; + Step 4. return K1, K2; +======================================================================== +*/ +VOID AES_CMAC_GenerateSubKey ( + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 SubKey1[], + OUT UINT8 SubKey2[]) +{ + UINT8 MSB_L = 0, MSB_K1 = 0, Top_Bit = 0; + UINT SubKey1_Length = 0; + INT Index = 0; + + if (KeyLength != AES_KEY128_LENGTH) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CMAC_GenerateSubKey: key length is %d bytes, it must be %d bytes(128 bits).\n", + KeyLength, AES_KEY128_LENGTH)); + return; + } + + /* Step 1: L := AES-128(K, const_Zero); */ + SubKey1_Length = 16; + RT_AES_Encrypt(Const_Zero, sizeof(Const_Zero), Key, KeyLength, SubKey1, &SubKey1_Length); + + /* + * Step 2. if MSB(L) is equal to 0 + * then K1 := L << 1; + * else K1 := (L << 1) XOR const_Rb; + */ + MSB_L = SubKey1[0] & 0x80; + for(Index = 0; Index < 15; Index++) { + Top_Bit = (SubKey1[Index + 1] & 0x80)?1:0; + SubKey1[Index] <<= 1; + SubKey1[Index] |= Top_Bit; + } + SubKey1[15] <<= 1; + if (MSB_L > 0) { + for(Index = 0; Index < 16; Index++) + SubKey1[Index] ^= Const_Rb[Index]; + } + + /* + * Step 3. if MSB(K1) is equal to 0 + * then K2 := K1 << 1; + * else K2 := (K1 << 1) XOR const_Rb; + */ + MSB_K1 = SubKey1[0] & 0x80; + for(Index = 0; Index < 15; Index++) { + Top_Bit = (SubKey1[Index + 1] & 0x80)?1:0; + SubKey2[Index] = SubKey1[Index] << 1; + SubKey2[Index] |= Top_Bit; + } + SubKey2[15] = SubKey1[15] << 1; + if (MSB_K1 > 0) { + for(Index = 0; Index < 16; Index++) + SubKey2[Index] ^= Const_Rb[Index]; + } +} + + +/* +======================================================================== +Routine Description: + AES-CMAC + +Arguments: + PlainText Plain text + PlainTextLength The length of plain text in bytes + Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) + KeyLength The length of cipher key in bytes + MACTextLength The length of allocated memory spaces in bytes + +Return Value: + MACText Message authentication code (128-bit string) + MACTextLength Return the length of Message authentication code in bytes + +Note: + Reference to RFC 4493 +======================================================================== +*/ +VOID AES_CMAC ( + IN UINT8 PlainText[], + IN UINT PlainTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 MACText[], + INOUT UINT *MACTextLength) +{ + UINT PlainBlockStart; + UINT8 X[AES_BLOCK_SIZES], Y[AES_BLOCK_SIZES]; + UINT8 SubKey1[16]; + UINT8 SubKey2[16]; + INT Index; + UINT X_Length; + + if (*MACTextLength < AES_MAC_LENGTH) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CMAC: MAC text length is less than %d bytes).\n", + AES_MAC_LENGTH)); + return; + } + if (KeyLength != AES_KEY128_LENGTH) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CMAC: key length is %d bytes, it must be %d bytes(128 bits).\n", + KeyLength, AES_KEY128_LENGTH)); + return; + } + + /* Step 1. (K1,K2) := Generate_Subkey(K); */ + NdisZeroMemory(SubKey1, 16); + NdisZeroMemory(SubKey2, 16); + AES_CMAC_GenerateSubKey(Key, KeyLength, SubKey1, SubKey2); + + /* + * 2. Main algorithm + * - Plain text divide into serveral blocks (16 bytes/block) + * - If plain text is not divided with no remainder by block, padding size = (block - remainder plain text) + * - Execute RT_AES_Encrypt procedure. + */ + PlainBlockStart = 0; + NdisMoveMemory(X, Const_Zero, AES_BLOCK_SIZES); + while ((PlainTextLength - PlainBlockStart) > AES_BLOCK_SIZES) + { + for (Index = 0; Index < AES_BLOCK_SIZES; Index++) + Y[Index] = PlainText[PlainBlockStart + Index]^X[Index]; + + X_Length = sizeof(X); + RT_AES_Encrypt(Y, sizeof(Y) , Key, KeyLength, X, &X_Length); + PlainBlockStart += ((UINT) AES_BLOCK_SIZES); + } + if ((PlainTextLength - PlainBlockStart) == AES_BLOCK_SIZES) { + for (Index = 0; Index < AES_BLOCK_SIZES; Index++) + Y[Index] = PlainText[PlainBlockStart + Index]^X[Index]^SubKey1[Index]; + } else { + NdisZeroMemory(Y, AES_BLOCK_SIZES); + NdisMoveMemory(Y, &PlainText[PlainBlockStart], (PlainTextLength - PlainBlockStart)); + Y[(PlainTextLength - PlainBlockStart)] = 0x80; + for (Index = 0; Index < AES_BLOCK_SIZES; Index++) + Y[Index] = Y[Index]^X[Index]^SubKey2[Index]; + } + RT_AES_Encrypt(Y, sizeof(Y) , Key, KeyLength, MACText, MACTextLength); +} + + +/* For AES_Key_Wrap */ +#define AES_KEY_WRAP_IV_LENGTH 8 /* 64-bit */ +#define AES_KEY_WRAP_BLOCK_SIZE 8 /* 64-bit */ +static UINT8 Default_IV[8] = { + 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6}; + +/* +======================================================================== +Routine Description: + AES-CBC encryption + +Arguments: + PlainText Plain text + PlainTextLength The length of plain text in bytes + Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) + KeyLength The length of cipher key in bytes + IV Initialization vector, it may be 16 bytes (128 bits) + IVLength The length of initialization vector in bytes + CipherTextLength The length of allocated cipher text in bytes + +Return Value: + CipherText Return cipher text + CipherTextLength Return the length of real used cipher text in bytes + +Note: + Reference to RFC 3602 and NIST 800-38A +======================================================================== +*/ +VOID AES_CBC_Encrypt ( + IN UINT8 PlainText[], + IN UINT PlainTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 IV[], + IN UINT IVLength, + OUT UINT8 CipherText[], + INOUT UINT *CipherTextLength) +{ + UINT PaddingSize, PlainBlockStart, CipherBlockStart, CipherBlockSize; + UINT Index; + UINT8 Block[AES_BLOCK_SIZES]; + + /* + * 1. Check the input parameters + * - CipherTextLength > (PlainTextLength + Padding size), Padding size = block size - (PlainTextLength % block size) + * - Key length must be 16, 24, or 32 bytes(128, 192, or 256 bits) + * - IV length must be 16 bytes(128 bits) + */ + PaddingSize = ((UINT) AES_BLOCK_SIZES) - (PlainTextLength % ((UINT)AES_BLOCK_SIZES)); + if (*CipherTextLength < (PlainTextLength + PaddingSize)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Encrypt: cipher text length is %d bytes < (plain text length %d bytes + padding size %d bytes).\n", + *CipherTextLength, PlainTextLength, PaddingSize)); + return; + } + if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Encrypt: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n", + KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH)); + return; + } + if (IVLength != AES_CBC_IV_LENGTH) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Encrypt: IV length is %d bytes, it must be %d bytes(128bits).\n", + IVLength, AES_CBC_IV_LENGTH)); + return; + } + + + /* + * 2. Main algorithm + * - Plain text divide into serveral blocks (16 bytes/block) + * - If plain text is divided with no remainder by block, add a new block and padding size = block(16 bytes) + * - If plain text is not divided with no remainder by block, padding size = (block - remainder plain text) + * - Execute RT_AES_Encrypt procedure. + * + * - Padding method: The remainder bytes will be filled with padding size (1 byte) + */ + PlainBlockStart = 0; + CipherBlockStart = 0; + while ((PlainTextLength - PlainBlockStart) >= AES_BLOCK_SIZES) + { + if (CipherBlockStart == 0) { + for (Index = 0; Index < AES_BLOCK_SIZES; Index++) + Block[Index] = PlainText[PlainBlockStart + Index]^IV[Index]; + } else { + for (Index = 0; Index < AES_BLOCK_SIZES; Index++) + Block[Index] = PlainText[PlainBlockStart + Index]^CipherText[CipherBlockStart - ((UINT) AES_BLOCK_SIZES) + Index]; + } + + CipherBlockSize = *CipherTextLength - CipherBlockStart; + RT_AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, CipherText + CipherBlockStart, &CipherBlockSize); + + PlainBlockStart += ((UINT) AES_BLOCK_SIZES); + CipherBlockStart += CipherBlockSize; + } + + NdisMoveMemory(Block, (&PlainText[0] + PlainBlockStart), (PlainTextLength - PlainBlockStart)); + NdisFillMemory((Block + (((UINT) AES_BLOCK_SIZES) -PaddingSize)), PaddingSize, (UINT8) PaddingSize); + if (CipherBlockStart == 0) { + for (Index = 0; Index < AES_BLOCK_SIZES; Index++) + Block[Index] ^= IV[Index]; + } else { + for (Index = 0; Index < AES_BLOCK_SIZES; Index++) + Block[Index] ^= CipherText[CipherBlockStart - ((UINT) AES_BLOCK_SIZES) + Index]; + } + CipherBlockSize = *CipherTextLength - CipherBlockStart; + RT_AES_Encrypt(Block, AES_BLOCK_SIZES , Key, KeyLength, CipherText + CipherBlockStart, &CipherBlockSize); + CipherBlockStart += CipherBlockSize; + *CipherTextLength = CipherBlockStart; +} + + +/* +======================================================================== +Routine Description: + AES-CBC decryption + +Arguments: + CipherText Cipher text + CipherTextLength The length of cipher text in bytes + Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) + KeyLength The length of cipher key in bytes + IV Initialization vector, it may be 16 bytes (128 bits) + IVLength The length of initialization vector in bytes + PlainTextLength The length of allocated plain text in bytes + +Return Value: + PlainText Return plain text + PlainTextLength Return the length of real used plain text in bytes + +Note: + Reference to RFC 3602 and NIST 800-38A +======================================================================== +*/ +VOID AES_CBC_Decrypt ( + IN UINT8 CipherText[], + IN UINT CipherTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 IV[], + IN UINT IVLength, + OUT UINT8 PlainText[], + INOUT UINT *PlainTextLength) +{ + UINT PaddingSize, PlainBlockStart, CipherBlockStart, PlainBlockSize; + UINT Index; + + /* + * 1. Check the input parameters + * - CipherTextLength must be divided with no remainder by block + * - Key length must be 16, 24, or 32 bytes(128, 192, or 256 bits) + * - IV length must be 16 bytes(128 bits) + */ + if ((CipherTextLength % AES_BLOCK_SIZES) != 0) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Decrypt: cipher text length is %d bytes, it can't be divided with no remainder by block size(%d).\n", + CipherTextLength, AES_BLOCK_SIZES)); + return; + } + if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Decrypt: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n", + KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH)); + return; + } + if (IVLength != AES_CBC_IV_LENGTH) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_CBC_Decrypt: IV length is %d bytes, it must be %d bytes(128bits).\n", + IVLength, AES_CBC_IV_LENGTH)); + return; + } + + + /* + * 2. Main algorithm + * - Cypher text divide into serveral blocks (16 bytes/block) + * - Execute RT_AES_Decrypt procedure. + * - Remove padding bytes, padding size is the last byte of plain text + */ + CipherBlockStart = 0; + PlainBlockStart = 0; + while ((CipherTextLength - CipherBlockStart) >= AES_BLOCK_SIZES) + { + PlainBlockSize = *PlainTextLength - PlainBlockStart; + RT_AES_Decrypt(CipherText + CipherBlockStart, AES_BLOCK_SIZES , Key, KeyLength, PlainText + PlainBlockStart, &PlainBlockSize); + + if (PlainBlockStart == 0) { + for (Index = 0; Index < AES_BLOCK_SIZES; Index++) + PlainText[PlainBlockStart + Index] ^= IV[Index]; + } else { + for (Index = 0; Index < AES_BLOCK_SIZES; Index++) + PlainText[PlainBlockStart + Index] ^= CipherText[CipherBlockStart + Index - ((UINT) AES_BLOCK_SIZES)]; + } + + CipherBlockStart += AES_BLOCK_SIZES; + PlainBlockStart += PlainBlockSize; + } + + PaddingSize = (UINT8) PlainText[PlainBlockStart -1]; + *PlainTextLength = PlainBlockStart - PaddingSize; + +} + + +/* +======================================================================== +Routine Description: + AES key wrap algorithm + +Arguments: + PlainText Plain text + PlainTextLength The length of plain text in bytes + Key Cipher key + KeyLength The length of cipher key in bytes depend on block cipher (16, 24, or 32 bytes) + +Return Value: + CipherText The ciphertext + CipherTextLength Return the length of the ciphertext in bytes + +Function Value: + 0: Success + -1: The key length must be 16, 24, or 32 bytes + -2: Not enough memory + +Note: + Reference to RFC 3394 +======================================================================== +*/ +INT AES_Key_Wrap ( + IN UINT8 PlainText[], + IN UINT PlainTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 CipherText[], + OUT UINT *CipherTextLength) +{ + UINT8 IV[8], Block_B[16], Block_Input[16]; + UINT8 *pResult; + UINT Temp_Length = 0, Number_Of_Block = 0; + INT Index_i = 0, Index_j = 0; + + /* + * 0. Check input parameter + */ + if ((KeyLength != AES_KEY128_LENGTH) && (KeyLength != AES_KEY192_LENGTH) && (KeyLength != AES_KEY256_LENGTH)) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_Key_Wrap: key length is %d bytes, it must be %d, %d, or %d bytes(128, 192, or 256 bits).\n", + KeyLength, AES_KEY128_LENGTH, AES_KEY192_LENGTH, AES_KEY256_LENGTH)); + return -1; + } + + os_alloc_mem(NULL, (UCHAR **)&pResult, sizeof(UINT8)*PlainTextLength); + if (pResult == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_Key_Wrap: allocate %d bytes memory failure.\n", sizeof(UINT8)*PlainTextLength)); + return -2; + } + + + /* + * 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); + } + } + + + /* + * 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); + + os_free_mem(NULL, pResult); + return 0; +} + + +/* +======================================================================== +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; + } + os_alloc_mem(NULL, (UCHAR **)&pResult, sizeof(UINT8)*PlainLength); + if (pResult == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("AES_Key_Unwrap: allocate %d bytes memory failure.\n", sizeof(UINT8)*PlainLength)); + return -2; + } + + + /* + * 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); + } + } + + /* + * 3. Output the results + */ + *PlainTextLength = PlainLength; + NdisMoveMemory(PlainText, pResult, PlainLength); + + os_free_mem(NULL, pResult); + return 0; +} + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_arc4.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_arc4.c new file mode 100644 index 000000000..382b89631 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_arc4.c @@ -0,0 +1,139 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + + +/**************************************************************************** + Module Name: + RC4 + + Abstract: + + Revision History: + Who When What + -------- ---------- ------------------------------------------ + Eddy 2009/05/13 ARC4 +***************************************************************************/ + +#include "crypt_arc4.h" + + +/* +======================================================================== +Routine Description: + ARC4 initialize the key block + +Arguments: + pARC4_CTX Pointer to ARC4 CONTEXT + Key Cipher key, it may be 16, 24, or 32 bytes (128, 192, or 256 bits) + KeyLength The length of cipher key in bytes + +======================================================================== +*/ +VOID ARC4_INIT ( + IN ARC4_CTX_STRUC *pARC4_CTX, + IN PUCHAR pKey, + IN UINT KeyLength) +{ + UINT BlockIndex = 0, SWAPIndex = 0, KeyIndex = 0; + UINT8 TempValue = 0; + + /*Initialize the block value*/ + pARC4_CTX->BlockIndex1 = 0; + pARC4_CTX->BlockIndex2 = 0; + for (BlockIndex = 0; BlockIndex < ARC4_KEY_BLOCK_SIZE; BlockIndex++) + pARC4_CTX->KeyBlock[BlockIndex] = (UINT8) BlockIndex; + + /*Key schedule*/ + for (BlockIndex = 0; BlockIndex < ARC4_KEY_BLOCK_SIZE; BlockIndex++) + { + TempValue = pARC4_CTX->KeyBlock[BlockIndex]; + KeyIndex = BlockIndex % KeyLength; + SWAPIndex = (SWAPIndex + TempValue + pKey[KeyIndex]) & 0xff; + pARC4_CTX->KeyBlock[BlockIndex] = pARC4_CTX->KeyBlock[SWAPIndex]; + pARC4_CTX->KeyBlock[SWAPIndex] = TempValue; + } /* End of for */ + +} /* End of ARC4_INIT */ + + +/* +======================================================================== +Routine Description: + ARC4 encryption/decryption + +Arguments: + pARC4_CTX Pointer to ARC4 CONTEXT + InputText Input text + InputTextLength The length of input text in bytes + +Return Value: + OutputBlock Return output text + ======================================================================== +*/ +VOID ARC4_Compute ( + IN ARC4_CTX_STRUC *pARC4_CTX, + IN UINT8 InputBlock[], + IN UINT InputBlockSize, + OUT UINT8 OutputBlock[]) +{ + UINT InputIndex = 0; + UINT8 TempValue = 0; + + for (InputIndex = 0; InputIndex < InputBlockSize; InputIndex++) + { + pARC4_CTX->BlockIndex1 = (pARC4_CTX->BlockIndex1 + 1) & 0xff; + TempValue = pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex1]; + pARC4_CTX->BlockIndex2 = (pARC4_CTX->BlockIndex2 + TempValue) & 0xff; + + pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex1] = pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex2]; + pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex2] = TempValue; + + TempValue = (TempValue + pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex1]) & 0xff; + OutputBlock[InputIndex] = InputBlock[InputIndex]^pARC4_CTX->KeyBlock[TempValue]; + + } /* End of for */ +} /* End of ARC4_Compute */ + + +/* +======================================================================== +Routine Description: + Discard the key length + +Arguments: + pARC4_CTX Pointer to ARC4 CONTEXT + Length Discard the key length + +======================================================================== +*/ +VOID ARC4_Discard_KeyLength ( + IN ARC4_CTX_STRUC *pARC4_CTX, + IN UINT Length) +{ + UINT Index = 0; + UINT8 TempValue = 0; + + for (Index = 0; Index < Length; Index++) + { + pARC4_CTX->BlockIndex1 = (pARC4_CTX->BlockIndex1 + 1) & 0xff; + TempValue = pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex1]; + pARC4_CTX->BlockIndex2 = (pARC4_CTX->BlockIndex2 + TempValue) & 0xff; + + pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex1] = pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex2]; + pARC4_CTX->KeyBlock[pARC4_CTX->BlockIndex2] = TempValue; + } /* End of for */ + +} /* End of ARC4_Discard_KeyLength */ + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_biginteger.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_biginteger.c new file mode 100644 index 000000000..f17003f6b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_biginteger.c @@ -0,0 +1,4448 @@ +/**************************************************************************** + * 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. + ***************************************************************************/ +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + +#include "crypt_biginteger.h" +#include "rt_config.h" +#include + + + +#ifdef __KERNEL__ +#define DEBUGPRINT(fmt, args...) printk(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) +#ifdef WSC_INCLUDED +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, +}; +#endif + +static UINT8 Value_0[1] = {0x00}; +static UINT8 Value_1[1] = {0x01}; +static PBIG_INTEGER pBI_S = NULL, pBI_O; + +BI_OP_TIME_RECORD bi_op_ti_rec; +UCHAR is_time_rec = FALSE; +ULONG alloc_cnt = 0; +UCHAR is_add_alloc_rec = FALSE; +UCHAR is_sub_alloc_rec = FALSE; +UCHAR is_mul_alloc_rec = FALSE; +UCHAR is_div_alloc_rec = FALSE; +UCHAR is_mod_alloc_rec = FALSE; +ULONG alloc_cnt_add = 0; +ULONG alloc_cnt_sub = 0; +ULONG alloc_cnt_mul = 0; +ULONG alloc_cnt_div = 0; +ULONG alloc_cnt_mod = 0; +#ifdef BI_POOL_DBG +UINT32 expected_cnt[25]; /* 0~21 is used */ +#endif + +#ifdef BI_POOL +#define TEMP_USAGE_POOL_SIZE 500 +BIG_INTEGER *temp_usage_pool[TEMP_USAGE_POOL_SIZE] = {NULL}; +static UINT16 pool_cur_index; +static UCHAR pool_is_small = FALSE; +#endif +NDIS_SPIN_LOCK bi_pool_lock; + + +#ifdef BI_POOL +VOID big_integer_pool_init( + VOID) +{ + UINT16 i = 0; + NdisAcquireSpinLock(&bi_pool_lock); + + for (i = 0; i < TEMP_USAGE_POOL_SIZE; i++) { + BigInteger_Init(&temp_usage_pool[i]); + BigInteger_AllocSize(&temp_usage_pool[i], 300); + } + + NdisReleaseSpinLock(&bi_pool_lock); +} + +VOID big_integer_pool_deinit( + VOID) +{ + UINT16 i = 0; + NdisAcquireSpinLock(&bi_pool_lock); + + for (i = 0; i < TEMP_USAGE_POOL_SIZE; i++) + BigInteger_Free(&temp_usage_pool[i]); + + NdisReleaseSpinLock(&bi_pool_lock); +} + +BIG_INTEGER *get_temporal_usage_big_interger( + VOID) +{ + UINT16 i = 0; + NdisAcquireSpinLock(&bi_pool_lock); + + for (i = 0; i < TEMP_USAGE_POOL_SIZE; i++) { + BIG_INTEGER *tmp = temp_usage_pool[(i + pool_cur_index) % TEMP_USAGE_POOL_SIZE]; + + if (tmp->invalid == FALSE) { + tmp->invalid = TRUE; + tmp->Signed = 1; + pool_cur_index = (i + pool_cur_index + 1) % TEMP_USAGE_POOL_SIZE; + NdisReleaseSpinLock(&bi_pool_lock); + return tmp; + } + } + + if (pool_is_small == FALSE) + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("\x1b[35m%s :pool is too small\x1b[m\n", __func__)); + + pool_is_small = TRUE; + NdisReleaseSpinLock(&bi_pool_lock); + return NULL; +} + +UINT32 sae_dump_pool_info_check( + INT32 expect_cnt, + UCHAR is_check, + UCHAR is_print) +{ + UINT32 cnt = 0; + UINT i = 0; + + for (i = 0; i < TEMP_USAGE_POOL_SIZE; i++) + if (temp_usage_pool[i]->invalid) + cnt++; + + if (is_check + && expect_cnt != cnt) + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("\x1b[31mError: invalid pool cnt = %d, Expected Cnt = %d, caller = %pS\x1b[m\n", + cnt, expect_cnt, OS_TRACE)); + + if (is_print && cnt != 0) + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("\x1b[31m")); + + if (is_print) + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("invalid pool cnt = %d, pool idx = %d, pool_is_small = %d\x1b[m\n", cnt, pool_cur_index, pool_is_small)); + + return cnt; +} +#endif + +VOID release_temporal_usage_big_interger( + IN BIG_INTEGER **pBI) +{ + if (*pBI && (*pBI)->invalid == TRUE) { + NdisAcquireSpinLock(&bi_pool_lock); + (*pBI)->invalid = FALSE; + *pBI = NULL; + NdisReleaseSpinLock(&bi_pool_lock); + } else { + /*MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("%s :pool is too small\n", __func__));*/ + BigInteger_Free(pBI); + } +} + + +static inline ULONG show_float( + ULONG a, + ULONG b, + INT32 x) +{ + ULONG c = a / b; + UCHAR i = 0; + ULONG d = 1; + ULONG e = 0; + + for (i = 0; i < x; i++) + d *= 10; + + e = d * a / b; + return e - c * d; +} + +VOID BigInteger_record_time_begin( + BI_OP_TIME_INTERVAL * time_rec) +{ + NdisGetSystemUpTime(&time_rec->time_interval); +} + +VOID BigInteger_record_time_end( + BI_OP_TIME_INTERVAL * time_rec) +{ + ULONG temp; + NdisGetSystemUpTime(&temp); + time_rec->time_interval = temp - time_rec->time_interval; + + if (time_rec->exe_times + 1 == 0) + return; + + time_rec->avg_time_interval = ((time_rec->avg_time_interval * time_rec->exe_times) + + time_rec->time_interval) / (time_rec->exe_times + 1); + time_rec->exe_times++; +} + +VOID BigInteger_record_time_ns( + BI_OP_TIME_INTERVAL * time_rec, + ULONG time_interval) +{ + time_rec->time_interval += time_interval; + + if (time_rec->exe_times + 1 == 0) + return; + + time_rec->avg_time_interval = time_rec->time_interval / (time_rec->exe_times + 1); + time_rec->exe_times++; +} + + + +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); + + for (i = (pBI->ArrayLength - 1), j = 0; i >= 0; i--, j++) { + DEBUGPRINT("%08x, ", pBI->pIntegerArray[i]); + + if ((j % 8) == 7) + DEBUGPRINT("\n"); + } + + DEBUGPRINT("\n\n"); +} + +static UCHAR randombyte(void) +{ + ULONG i; + UCHAR R = 0, Result; + static ULONG ShiftReg; + + if (ShiftReg == 0) + NdisGetSystemUpTime((ULONG *)&ShiftReg); + + for (i = 0; i < 8; i++) { + if (ShiftReg & 0x00000001) { + ShiftReg = ((ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000; + Result = 1; + } else { + ShiftReg = ShiftReg >> 1; + Result = 0; + } + + R = (R << 1) | Result; + } + + return R; +} + +INT BigInteger_rand_range(IN BIG_INTEGER * range, INOUT BIG_INTEGER * r) +{ + UINT8 *rand = NULL; + UINT32 i; + UINT32 iter = 0; + UINT32 range_len; + BIG_INTEGER *rand_bi = NULL; + + if (!range) + return 0; + + range_len = BigInteger_getlen(range); + os_alloc_mem(NULL, (UCHAR **)&rand, range_len); + if (!rand) { + DEBUGPRINT("==> %s(), fail\n", __func__); + return 0; + } + + for (iter = 0; iter < 100; iter++) { + for (i = 0; i < range_len; i++) + rand[i] = randombyte(); + + hex_dump_with_lvl("rand:", (char *)rand, range_len, DBG_LVL_INFO); + BigInteger_Bin2BI(rand, range_len, &rand_bi); + if (BigInteger_is_zero(rand_bi) + || BigInteger_is_one(rand_bi) + || BigInteger_UnsignedCompare(rand_bi, range) >= 0) { + continue; + } else { + BigInteger_Copy(rand_bi, &r); + BigInteger_Free(&rand_bi); + os_free_mem(NULL, rand); + return 1; + } + } + + BigInteger_Free(&rand_bi); + os_free_mem(NULL, rand); + return 0; + +} + +VOID BigInteger_Init( + INOUT PBIG_INTEGER *pBI) +{ + if (*pBI != NULL) { + if ((*pBI)->invalid == FALSE) + BigInteger_Free_AllocSize(pBI); + + return; + } else { + if (is_time_rec) + alloc_cnt++; + + if (is_add_alloc_rec) + alloc_cnt_add++; + + if (is_sub_alloc_rec) + alloc_cnt_sub++; + + if (is_mul_alloc_rec) + alloc_cnt_mul++; + + if (is_div_alloc_rec) + alloc_cnt_div++; + + if (is_mod_alloc_rec) + alloc_cnt_mod++; + + os_alloc_mem(NULL, (UCHAR **)pBI, sizeof(BIG_INTEGER)); + } + + if (*pBI == NULL) { + DEBUGPRINT("BigInteger_Init: allocate %zu bytes memory failure.\n", sizeof(BIG_INTEGER)); + return; + } + + NdisZeroMemory(*pBI, sizeof(BIG_INTEGER)); + (*pBI)->pIntegerArray = NULL; + (*pBI)->Signed = 1; +} + + +VOID BigInteger_Free_AllocSize( + IN PBIG_INTEGER *pBI) +{ + if ((*pBI != NULL) && ((*pBI)->pIntegerArray != NULL)) { + UCHAR invalid = (*pBI)->invalid; + os_free_mem(NULL, (*pBI)->pIntegerArray); + NdisZeroMemory(*pBI, sizeof(BIG_INTEGER)); + (*pBI)->pIntegerArray = NULL; + (*pBI)->Signed = 1; + (*pBI)->invalid = invalid; + } +} + + +VOID BigInteger_Free( + IN PBIG_INTEGER *pBI) +{ + if (*pBI != NULL) { + BigInteger_Free_AllocSize(pBI); + os_free_mem(NULL, *pBI); + } + + *pBI = NULL; +} + + +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) { + if (is_time_rec) + alloc_cnt++; + + if (is_add_alloc_rec) + alloc_cnt_add++; + + if (is_sub_alloc_rec) + alloc_cnt_sub++; + + if (is_mul_alloc_rec) + alloc_cnt_mul++; + + if (is_div_alloc_rec) + alloc_cnt_div++; + + if (is_mod_alloc_rec) + alloc_cnt_mod++; + + os_alloc_mem(NULL, (UCHAR **) &((*pBI)->pIntegerArray), sizeof(UINT32)*ArrayLength); + + if ((*pBI)->pIntegerArray == NULL) { + DEBUGPRINT("BigInteger_AllocSize: allocate %zu bytes memory failure.\n", sizeof(UINT32)*ArrayLength); + return; + } + + (*pBI)->AllocSize = sizeof(UINT32) * ArrayLength; + } + + NdisZeroMemory((*pBI)->pIntegerArray, (*pBI)->AllocSize); + (*pBI)->ArrayLength = ArrayLength; + (*pBI)->IntegerLength = Length; +} + + +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 */ + +UINT32 BigInteger_getlen( + IN BIG_INTEGER * pBI) +{ + return pBI->IntegerLength; +} + + + +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 */ + + /* for OWE. + * It already guarantee the length of its corresponding pointer is big enough. + * And would like to this function help it to transfer bn to binary, + * then return the length of this function transferred. + * + * The length checking here is not necessary, + * the caller of others should guarantee the length of its corresponding pointer is big enough, too. + * if (*Length < (sizeof(UINT8) * pBI->IntegerLength)) { + * DEBUGPRINT("BigInteger_BI2Bin: length(%d) is not enough.\n", *Length); + * *Length = 0; + * return; + * } + */ + + if (pBI->pIntegerArray == NULL) { + *Length = 0; + return; + } /* End of if */ + + BigInteger_ClearHighBits(pBI); + ShiftIndex = pBI->IntegerLength & 0x3; + + if (ShiftIndex == 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_BI2Bin_with_pad( + IN PBIG_INTEGER pBI, + OUT UINT8 *pValue, + OUT UINT *Length, + IN UINT32 PadLen) +{ + UINT32 offset; + + if (!pBI) + return; + + offset = (pBI->IntegerLength > PadLen) ? 0 : PadLen - pBI->IntegerLength; + NdisZeroMemory(pValue, offset); + BigInteger_BI2Bin(pBI, pValue + offset, Length); + *Length += offset; +} + + + +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; + ShiftIndex = Length & 0x3; + + if (ShiftIndex == 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 */ + + BigInteger_ClearHighBits(*pBI); +} /* 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 * 32) - 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); +} /* 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; + BigInteger_ClearHighBits(pFirstOperand); + BigInteger_ClearHighBits(pSecondOperand); + + 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 */ + + if (pFirstOperand->IntegerLength > pSecondOperand->IntegerLength) + return 1; + + if (pFirstOperand->IntegerLength < pSecondOperand->IntegerLength) + return -1; + + 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; +#ifdef BI_TIME_REC + struct timeval t1; + struct timeval t2; +#endif + + 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 */ + +#ifdef BI_TIME_REC + + if (is_time_rec) { + do_gettimeofday(&t1); + is_add_alloc_rec = TRUE; + } + +#endif + + 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 */ + + POOL_COUNTER_CHECK_BEGIN(expected_cnt[0]); + GET_BI_INS_FROM_POOL(pTempBI); + + /* + * 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 */ + + release_temporal_usage_big_interger(&pTempBI); + POOL_COUNTER_CHECK_END(expected_cnt[0]); +#ifdef BI_TIME_REC + + if (is_time_rec) { + ULONG time_interval = 0; + do_gettimeofday(&t2); + + if (t1.tv_usec > t2.tv_usec) + time_interval = (t2.tv_sec - t1.tv_sec) * 1000000 - t1.tv_usec + t2.tv_usec; + else + time_interval = t2.tv_usec - t1.tv_usec; + + BigInteger_record_time_ns(&bi_op_ti_rec.add_op, time_interval); + is_add_alloc_rec = FALSE; + } + +#endif +} /* 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 pTempBI2 = NULL; +#ifdef BI_TIME_REC + struct timeval t1; + struct timeval t2; +#endif + + 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 */ + +#ifdef BI_TIME_REC + + if (is_time_rec) { + do_gettimeofday(&t1); + is_sub_alloc_rec = TRUE; + } + +#endif + + 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) { + UINT32 *pResultArray = NULL; + UINT32 *pTempArray = NULL; + + if (CompareResult == 1) { + BigInteger_Copy(pFirstOperand, pBI_Result); + pTempBI2 = pSecondOperand; + } else if (CompareResult == -1) { + BigInteger_Copy(pSecondOperand, pBI_Result); + pTempBI2 = pFirstOperand; + } /* End of if */ + + pResultArray = (*pBI_Result)->pIntegerArray; + pTempArray = pTempBI2->pIntegerArray; + Carry = 0; + + for (BIArrayIndex = 0; BIArrayIndex < (*pBI_Result)->ArrayLength; BIArrayIndex++) { + if (BIArrayIndex < pTempBI2->ArrayLength) { + if (((pResultArray[BIArrayIndex] - Carry) < pTempArray[BIArrayIndex]) + || ((pResultArray[BIArrayIndex] == 0) && (Carry == 1))) { + pResultArray[BIArrayIndex] = 0xffffffffUL - pTempArray[BIArrayIndex] - Carry + pResultArray[BIArrayIndex] + 1; + Carry = 1; + } else { + pResultArray[BIArrayIndex] = pResultArray[BIArrayIndex] - pTempArray[BIArrayIndex] - Carry; + Carry = 0; + } /* End of if */ + } else { + if (pResultArray[BIArrayIndex] >= Carry) { + pResultArray[BIArrayIndex] -= Carry; + Carry = 0; + break; + } else { + pResultArray[BIArrayIndex] = 0xffffffffUL; + 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 { + PBIG_INTEGER pTempBI = NULL; + POOL_COUNTER_CHECK_BEGIN(expected_cnt[7]); + GET_BI_INS_FROM_POOL(pTempBI); + BigInteger_Init(&pTempBI); + + 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 */ + + release_temporal_usage_big_interger(&pTempBI); + POOL_COUNTER_CHECK_END(expected_cnt[7]); + } /* End of if */ + +#ifdef BI_TIME_REC + + if (is_time_rec) { + ULONG time_interval = 0; + do_gettimeofday(&t2); + + if (t1.tv_usec > t2.tv_usec) + time_interval = (t2.tv_sec - t1.tv_sec) * 1000000 - t1.tv_usec + t2.tv_usec; + else + time_interval = t2.tv_usec - t1.tv_usec; + + BigInteger_record_time_ns(&bi_op_ti_rec.sub_op, time_interval); + is_sub_alloc_rec = FALSE; + } + +#endif +} /* 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; +#ifdef BI_TIME_REC + struct timeval t1; + struct timeval t2; +#endif + + 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 */ + +#ifdef BI_TIME_REC + if (is_time_rec) { + do_gettimeofday(&t1); + is_mul_alloc_rec = TRUE; + } +#endif + + /* 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); +#ifdef BI_TIME_REC + + if (is_time_rec) { + ULONG time_interval = 0; + do_gettimeofday(&t2); + + if (t1.tv_usec > t2.tv_usec) + time_interval = (t2.tv_sec - t1.tv_sec) * 1000000 - t1.tv_usec + t2.tv_usec; + else + time_interval = t2.tv_usec - t1.tv_usec; + + BigInteger_record_time_ns(&bi_op_ti_rec.mul_op, time_interval); + is_mul_alloc_rec = FALSE; + } + +#endif +} /* 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; +#ifdef BI_TIME_REC + struct timeval t1; + struct timeval t2; +#endif + + if ((pBI == NULL) || (pBI->pIntegerArray == NULL)) { + DEBUGPRINT("\tBigInteger_Square: the operand is NULL.\n"); + return; + } /* End of if */ + +#ifdef BI_TIME_REC + + if (is_time_rec) + do_gettimeofday(&t1); + +#endif + + /* 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); + BigInteger_Free(&pBI_O); + BigInteger_Free(&pBI_S); +#ifdef BI_TIME_REC + + if (is_time_rec) { + ULONG time_interval = 0; + do_gettimeofday(&t2); + + if (t1.tv_usec > t2.tv_usec) + time_interval = (t2.tv_sec - t1.tv_sec) * 1000000 - t1.tv_usec + t2.tv_usec; + else + time_interval = t2.tv_usec - t1.tv_usec; + + BigInteger_record_time_ns(&bi_op_ti_rec.square_op, time_interval); + } + +#endif +} /* 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 MulLoopStart, MulLoopEnd; + UINT AllocLength, ArrayIndex, ShiftIndex; + UINT8 SecondHighByte; +#ifdef BI_TIME_REC + struct timeval t1; + struct timeval t2; +#endif + PBIG_INTEGER pTempBI = NULL; + PBIG_INTEGER pTempBI2 = NULL; + PBIG_INTEGER pMulBI = NULL; +#ifdef BI_TIME_REC + + if (is_time_rec) { + do_gettimeofday(&t1); + is_div_alloc_rec = TRUE; + } + +#endif + + 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 */ + + POOL_COUNTER_CHECK_BEGIN(expected_cnt[16]); + GET_BI_INS_FROM_POOL(pTempBI); + GET_BI_INS_FROM_POOL(pTempBI2); + GET_BI_INS_FROM_POOL(pMulBI); + + 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_Copy(pFirstOperand, pBI_Remainder); + SecondHighByte = (BigInteger_GetByteValue(pSecondOperand, pSecondOperand->IntegerLength) & 0xFF); + 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--; + MulLoopStart = (BigInteger_GetByteValue((*pBI_Remainder), pFirstOperand->IntegerLength + Index - ComputeSize + 1) & 0xFF) << 8; + MulLoopStart = MulLoopStart | (BigInteger_GetByteValue((*pBI_Remainder), pFirstOperand->IntegerLength + Index - ComputeSize) & 0xFF); + + if (MulLoopStart < (UINT32) SecondHighByte) + continue; + + if (SecondHighByte) + MulLoopEnd = (MulLoopStart / (UINT32) SecondHighByte) + 1; + else + MulLoopEnd = 1; + MulLoopStart = MulLoopStart / (UINT32) (SecondHighByte + 1); + + for (MulIndex = (INT) MulLoopStart; MulIndex <= MulLoopEnd; MulIndex++) { /* 0xFFFF / 0x01 = 0xFFFF */ + NdisZeroMemory(pMulBI->pIntegerArray, pMulBI->AllocSize); + + if ((MulIndex > 0xff) && (ShiftIndex == 3)) { + pMulBI->pIntegerArray[ArrayIndex] = ((UINT) (MulIndex & 0xff) << (8 * ShiftIndex)); + pMulBI->pIntegerArray[ArrayIndex + 1] = (UINT) (MulIndex >> 8) & 0xff; + } else + pMulBI->pIntegerArray[ArrayIndex] = ((UINT) (MulIndex) << (8 * ShiftIndex)); + + /* BigInteger_ClearHighBits(pMulBI); */ + BigInteger_Mul(pSecondOperand, pMulBI, &pTempBI); + CompareResult = BigInteger_UnsignedCompare(*pBI_Remainder, pTempBI); + + if (CompareResult < 1) { + if (CompareResult == -1) { + MulIndex = MulIndex - 1; + BigInteger_AllocSize(&pMulBI, Index + 1); + NdisZeroMemory(pMulBI->pIntegerArray, pMulBI->AllocSize); + + if ((MulIndex > 0xff) && (ShiftIndex == 3)) { + pMulBI->pIntegerArray[ArrayIndex] = ((UINT) (MulIndex & 0xff) << (8 * ShiftIndex)); + pMulBI->pIntegerArray[ArrayIndex + 1] = (UINT) (MulIndex >> 8) & 0xff; + } else + pMulBI->pIntegerArray[ArrayIndex] = ((UINT) (MulIndex) << (8 * ShiftIndex)); + + 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); + break; + } /* End of if */ + } /* End of for */ + } /* End of if */ + } /* End of for */ + +output: + (*pBI_Result)->Signed = pFirstOperand->Signed * pSecondOperand->Signed; + (*pBI_Remainder)->Signed = pFirstOperand->Signed * pSecondOperand->Signed; + BigInteger_ClearHighBits(*pBI_Result); + BigInteger_ClearHighBits(*pBI_Remainder); + release_temporal_usage_big_interger(&pTempBI); + release_temporal_usage_big_interger(&pTempBI2); + release_temporal_usage_big_interger(&pMulBI); + POOL_COUNTER_CHECK_END(expected_cnt[16]); +#ifdef BI_TIME_REC + + if (is_time_rec) { + ULONG time_interval = 0; + do_gettimeofday(&t2); + + if (t1.tv_usec > t2.tv_usec) + time_interval = (t2.tv_sec - t1.tv_sec) * 1000000 - t1.tv_usec + t2.tv_usec; + else + time_interval = t2.tv_usec - t1.tv_usec; + + BigInteger_record_time_ns(&bi_op_ti_rec.div_op, time_interval); + is_div_alloc_rec = FALSE; + } + +#endif +} /* End of BigInteger_Div */ + +#ifdef WSC_INCLUDED +static UINT8 WPS_DH_PInverse_VALUE[192] = { + 0xd9, 0xc7, 0xd8, 0x95, 0xed, 0x5a, 0xa0, 0xac, + 0xa4, 0xb4, 0xbc, 0x87, 0x43, 0x7d, 0x88, 0x13, + 0x0f, 0xce, 0xd9, 0xcc, 0x8f, 0x13, 0x84, 0x81, + 0xf5, 0x32, 0x2b, 0x5c, 0xfd, 0x0b, 0x7b, 0xd7, + 0x22, 0x57, 0x31, 0xdb, 0xb9, 0x2e, 0x86, 0x4c, + 0xab, 0xa2, 0x74, 0xbb, 0x68, 0x04, 0xd4, 0x4f, + 0x32, 0x46, 0xbb, 0xae, 0x44, 0x6d, 0xfb, 0xdf, + 0x7b, 0x2c, 0xaa, 0x2f, 0x7f, 0xfb, 0xa3, 0x2d, + 0xa3, 0x88, 0x05, 0x0d, 0xbc, 0xd5, 0xe5, 0xac, + 0xcb, 0x79, 0xe6, 0xa5, 0xa5, 0x0f, 0x3e, 0xd6, + 0x01, 0xe2, 0x38, 0x7b, 0xfb, 0x98, 0x61, 0x69, + 0x01, 0xaa, 0x42, 0xec, 0xcd, 0x35, 0xc5, 0x13, + 0x0d, 0x4d, 0xd6, 0x0b, 0x30, 0x93, 0x4a, 0xd4, + 0x7b, 0xb1, 0x12, 0xfa, 0xe1, 0x78, 0x10, 0xca, + 0x67, 0x6e, 0xc3, 0xcc, 0x40, 0xb6, 0xa9, 0x05, + 0x74, 0x5e, 0xf2, 0x05, 0xa8, 0xf0, 0x90, 0x88, + 0x5f, 0xee, 0x48, 0xe1, 0xfb, 0x0a, 0xae, 0x62, + 0xcf, 0x9d, 0xe9, 0x4f, 0x4d, 0x2f, 0x59, 0x54, + 0x7f, 0x2e, 0xaf, 0x68, 0xe7, 0xe8, 0x23, 0xa3, + 0x21, 0x21, 0x56, 0x15, 0x96, 0x31, 0x09, 0xb9, + 0x1a, 0xf2, 0x5b, 0x38, 0x6a, 0x3c, 0x43, 0x7a, + 0x3e, 0x49, 0x1e, 0x72, 0x1b, 0x79, 0x8e, 0x44, + 0xf1, 0x74, 0x6c, 0x08, 0xca, 0x23, 0x73, 0x28, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +}; +#endif + + +static VOID BigInteger_Inverse( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + OUT PBIG_INTEGER *pFirstInverse, + OUT PBIG_INTEGER *pSecondInverse) +{ + PBIG_INTEGER pBI_A = NULL, pBI_B = NULL; + PBIG_INTEGER pBI_X = NULL, pBI_X1 = NULL, pBI_X2 = NULL; + PBIG_INTEGER pBI_Y = NULL, pBI_Y1 = NULL, pBI_Y2 = NULL; + PBIG_INTEGER pBI_Q = NULL, pBI_R = NULL; + PBIG_INTEGER pBI_Temp = NULL; + POOL_COUNTER_CHECK_BEGIN(expected_cnt[15]); + GET_BI_INS_FROM_POOL(pBI_A); + GET_BI_INS_FROM_POOL(pBI_B); + GET_BI_INS_FROM_POOL(pBI_X); + GET_BI_INS_FROM_POOL(pBI_X1); + GET_BI_INS_FROM_POOL(pBI_X2); + GET_BI_INS_FROM_POOL(pBI_Y); + GET_BI_INS_FROM_POOL(pBI_Y1); + GET_BI_INS_FROM_POOL(pBI_Y2); + GET_BI_INS_FROM_POOL(pBI_Q); + GET_BI_INS_FROM_POOL(pBI_R); + GET_BI_INS_FROM_POOL(pBI_Temp); + BigInteger_Init(&pBI_A); + BigInteger_Init(&pBI_B); + BigInteger_Init(&pBI_X); + BigInteger_Init(&pBI_X1); + BigInteger_Init(&pBI_X2); + BigInteger_Init(&pBI_Y); + BigInteger_Init(&pBI_Y1); + BigInteger_Init(&pBI_Y2); + BigInteger_Init(&pBI_Q); + BigInteger_Init(&pBI_R); + BigInteger_Init(&pBI_Temp); + BigInteger_Copy(pFirstOperand, &pBI_A); + BigInteger_Copy(pSecondOperand, &pBI_B); + BigInteger_AllocSize(&pBI_Q, 1); + BigInteger_AllocSize(&pBI_R, 1); + BigInteger_AllocSize(&pBI_X, 1); + BigInteger_AllocSize(&pBI_Y, 1); + BigInteger_AllocSize(&pBI_X2, 1); + BigInteger_AllocSize(&pBI_X1, 1); + BigInteger_AllocSize(&pBI_Y2, 1); + BigInteger_AllocSize(&pBI_Y1, 1); + pBI_X2->pIntegerArray[0] = 0x1; + pBI_Y1->pIntegerArray[0] = 0x1; + + while (((pBI_B->IntegerLength > 1) || ((pBI_B->IntegerLength == 1) && (pBI_B->pIntegerArray[0] > 0))) && (pBI_B->Signed == 1)) { + BigInteger_Div(pBI_A, pBI_B, &pBI_Q, &pBI_R); + BigInteger_Mul(pBI_Q, pBI_X1, &pBI_Temp); + BigInteger_Sub(pBI_X2, pBI_Temp, &pBI_X); + BigInteger_Mul(pBI_Q, pBI_Y1, &pBI_Temp); + BigInteger_Sub(pBI_Y2, pBI_Temp, &pBI_Y); + BigInteger_Copy(pBI_B, &pBI_A); + BigInteger_Copy(pBI_R, &pBI_B); + BigInteger_Copy(pBI_X1, &pBI_X2); + BigInteger_Copy(pBI_X, &pBI_X1); + BigInteger_Copy(pBI_Y1, &pBI_Y2); + BigInteger_Copy(pBI_Y, &pBI_Y1); + } /* End of while */ + + if (((pBI_X2->IntegerLength > 1) || ((pBI_X2->IntegerLength == 1) && (pBI_X2->pIntegerArray[0] > 0))) && (pBI_X2->Signed == -1)) { + BigInteger_Add(pSecondOperand, pBI_X2, &pBI_Temp); + BigInteger_Copy(pBI_Temp, &pBI_X2); + BigInteger_Sub(pFirstOperand, pBI_Y2, &pBI_Temp); + BigInteger_Copy(pBI_Temp, &pBI_Y2); + } /* End of if */ + + if (((pBI_Y2->IntegerLength > 1) || ((pBI_Y2->IntegerLength == 1) && (pBI_Y2->pIntegerArray[0] > 0))) && (pBI_Y2->Signed == -1)) + pBI_Y2->Signed = 1; /* End of if */ + + BigInteger_Copy(pBI_X2, pFirstInverse); + BigInteger_Copy(pBI_Y2, pSecondInverse); + release_temporal_usage_big_interger(&pBI_A); + release_temporal_usage_big_interger(&pBI_B); + release_temporal_usage_big_interger(&pBI_X); + release_temporal_usage_big_interger(&pBI_X1); + release_temporal_usage_big_interger(&pBI_X2); + release_temporal_usage_big_interger(&pBI_Y); + release_temporal_usage_big_interger(&pBI_Y1); + release_temporal_usage_big_interger(&pBI_Y2); + release_temporal_usage_big_interger(&pBI_Q); + release_temporal_usage_big_interger(&pBI_R); + release_temporal_usage_big_interger(&pBI_Temp); + POOL_COUNTER_CHECK_END(expected_cnt[15]); +} /* End of BigInteger_Inverse */ + + + + +static VOID BigInteger_Div2Exponent( + IN PBIG_INTEGER pBI, + IN UINT Exponent, + OUT PBIG_INTEGER *pBI_Result, + OUT PBIG_INTEGER *pBI_Remainder) +{ + UINT Bites_Of_BI, Bits_Of_Result, Bits_Of_Remainder; + UINT ResultLength, ResultArrayIndex, ResultShiftIndex; + UINT RemainderLength, RemainderArrayIndex, RemainderShiftIndex; + UINT BIArrayIndex, ShiftIndex; + UINT ReadShift = 0, WriteShift = 0, ReadBits = 0; + UINT32 Value, TempValue; + + if (pBI == NULL) { + DEBUGPRINT("BigInteger_Div2Exponent: pBI is NUll\n"); + (*pBI_Result) = NULL; + return; + } /* End of if */ + + BigInteger_BitsOfBI(pBI, &Bites_Of_BI); + + if (Bites_Of_BI < Exponent) { + BigInteger_Bin2BI(Value_0, 1, pBI_Result); + BigInteger_Copy(pBI, pBI_Remainder); + return; + } /* End of if */ + + Bits_Of_Result = Bites_Of_BI - Exponent + 1; + ResultLength = Bits_Of_Result >> 0x3L; + + if ((Bits_Of_Result & 0x7) > 0) + ResultLength++; + + BigInteger_AllocSize(pBI_Result, ResultLength); + + ResultShiftIndex = Bits_Of_Result & 0x1FL; + if (ResultShiftIndex == 0) + ResultShiftIndex = 32; + + ResultArrayIndex = (*pBI_Result)->ArrayLength - 1; + Bits_Of_Remainder = Exponent - 1; + RemainderLength = Bits_Of_Remainder >> 0x3L; + + if ((Bits_Of_Remainder & 0x7) > 0) + RemainderLength++; + + BigInteger_AllocSize(pBI_Remainder, RemainderLength); + + RemainderShiftIndex = Bits_Of_Remainder & 0x1FL; + if (RemainderShiftIndex == 0) + RemainderShiftIndex = 32; + + RemainderArrayIndex = (*pBI_Remainder)->ArrayLength - 1; + + ShiftIndex = Bites_Of_BI & 0x1FL; + if (ShiftIndex == 0) + ShiftIndex = 32; + + BIArrayIndex = pBI->ArrayLength - 1; + Value = 0; + + while (Bits_Of_Result > 0) { + if ((ResultShiftIndex >= ShiftIndex) && (ShiftIndex <= Bits_Of_Result)) { + ReadShift = 0; + WriteShift = ResultShiftIndex - ShiftIndex; + ReadBits = ShiftIndex; + } else if ((ResultShiftIndex < ShiftIndex) && (ResultShiftIndex <= Bits_Of_Result)) { + ReadShift = ShiftIndex - ResultShiftIndex; + WriteShift = 0; + ReadBits = ResultShiftIndex; + } else if ((ResultShiftIndex > Bits_Of_Result) && (ShiftIndex > Bits_Of_Result)) { + ReadShift = ShiftIndex - Bits_Of_Result; + WriteShift = ResultShiftIndex - Bits_Of_Result; + ReadBits = Bits_Of_Result; + } /* End of if */ + + TempValue = (UINT32) ((pBI->pIntegerArray[BIArrayIndex] & (0xFFFFFFFFL >> (32 - ShiftIndex))) >> ReadShift); + Value = Value | (TempValue << WriteShift); + ResultShiftIndex -= ReadBits; + ShiftIndex -= ReadBits; + Bits_Of_Result -= ReadBits; + + if (ResultShiftIndex == 0) { + (*pBI_Result)->pIntegerArray[ResultArrayIndex] = Value; + ResultShiftIndex = 32; + ResultArrayIndex--; + Value = 0; + } /* End of if */ + + if (ShiftIndex == 0) { + ShiftIndex = 32; + BIArrayIndex--; + } /* End of if */ + } /* End of while */ + + if (ResultShiftIndex != 32) + (*pBI_Result)->pIntegerArray[ResultArrayIndex] = Value; + + Value = 0; + + while (Bits_Of_Remainder > 0) { + if ((RemainderShiftIndex >= ShiftIndex) && (ShiftIndex <= Bits_Of_Remainder)) { + ReadShift = 0; + WriteShift = RemainderShiftIndex - ShiftIndex; + ReadBits = ShiftIndex; + } else if ((RemainderShiftIndex < ShiftIndex) && (RemainderShiftIndex <= Bits_Of_Remainder)) { + ReadShift = ShiftIndex - RemainderShiftIndex; + WriteShift = 0; + ReadBits = RemainderShiftIndex; + } else if ((RemainderShiftIndex > Bits_Of_Remainder) && (ShiftIndex > Bits_Of_Remainder)) { + ReadShift = ShiftIndex - Bits_Of_Remainder; + WriteShift = RemainderShiftIndex - Bits_Of_Remainder; + ReadBits = Bits_Of_Remainder; + } /* End of if */ + + TempValue = (UINT32) ((pBI->pIntegerArray[BIArrayIndex] & (0xFFFFFFFFL >> (32 - ShiftIndex))) >> ReadShift); + Value = Value | (TempValue << WriteShift); + RemainderShiftIndex -= ReadBits; + ShiftIndex -= ReadBits; + Bits_Of_Remainder -= ReadBits; + + if (RemainderShiftIndex == 0) { + (*pBI_Remainder)->pIntegerArray[RemainderArrayIndex] = Value; + RemainderShiftIndex = 32; + RemainderArrayIndex--; + Value = 0; + } /* End of if */ + + if (ShiftIndex == 0) { + ShiftIndex = 32; + BIArrayIndex--; + } /* End of if */ + } /* End of while */ + + if (RemainderShiftIndex != 32) + (*pBI_Remainder)->pIntegerArray[RemainderArrayIndex] = Value; + + (*pBI_Result)->Signed = pBI->Signed; + (*pBI_Remainder)->Signed = pBI->Signed; + BigInteger_ClearHighBits(*pBI_Result); + BigInteger_ClearHighBits(*pBI_Remainder); +} /* End of BigInteger_Div2Exponent */ + + +static VOID BigInteger_Square2( + 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; + PBIG_INTEGER pBI_Square_1 = NULL; + PBIG_INTEGER pBI_Square_2 = NULL; + + 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 */ + + POOL_COUNTER_CHECK_BEGIN(expected_cnt[19]); + GET_BI_INS_FROM_POOL(pBI_Square_1); + GET_BI_INS_FROM_POOL(pBI_Square_2); + BigInteger_AllocSize(pBI_Result, (pBI->IntegerLength * 2) + 20); + BigInteger_AllocSize(&pBI_Square_1, (pBI->IntegerLength * 2) + 20); + BigInteger_AllocSize(&pBI_Square_2, (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_Square_2->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_Square_1); + Carry32 = 0; + + for (BIFirstIndex = 0; BIFirstIndex < pBI_Square_1->ArrayLength; BIFirstIndex++) { + pBI_Square_1->pIntegerArray[BIFirstIndex] = (pBI_Square_1->pIntegerArray[BIFirstIndex] << 1) | Carry32; + + if (pBI_Square_1->pIntegerArray[BIFirstIndex] < (*pBI_Result)->pIntegerArray[BIFirstIndex]) + Carry32 = 1; + else + Carry32 = 0; + } /* End of for */ + + pBI_Square_1->pIntegerArray[BIFirstIndex] = Carry32; + pBI_Square_1->IntegerLength++; + pBI_Square_1->ArrayLength++; + BigInteger_ClearHighBits(pBI_Square_1); + BigInteger_Add(pBI_Square_1, pBI_Square_2, pBI_Result); + release_temporal_usage_big_interger(&pBI_Square_1); + release_temporal_usage_big_interger(&pBI_Square_2); + POOL_COUNTER_CHECK_END(expected_cnt[19]); +output: + (*pBI_Result)->Signed = 1; + BigInteger_ClearHighBits(*pBI_Result); +} /* End of BigInteger_Square */ + + +VOID BigInteger_Montgomery_MulMod( + IN PBIG_INTEGER pBI_A, + IN PBIG_INTEGER pBI_B, + IN PBIG_INTEGER pBI_P, + IN PBIG_INTEGER pBI_PInverse, + IN UINT Bits_Of_R, + OUT PBIG_INTEGER *pBI_Result) +{ + PBIG_INTEGER pBI_MulMod_1 = NULL; + PBIG_INTEGER pBI_MulMod_2 = NULL; + PBIG_INTEGER pBI_MulMod_3 = NULL; + + if (*pBI_Result == NULL) + BigInteger_Init(pBI_Result); + + POOL_COUNTER_CHECK_BEGIN(expected_cnt[1]); + GET_BI_INS_FROM_POOL(pBI_MulMod_1); + GET_BI_INS_FROM_POOL(pBI_MulMod_2); + GET_BI_INS_FROM_POOL(pBI_MulMod_3); + BigInteger_Mul(pBI_A, pBI_B, &pBI_MulMod_1); + BigInteger_Mul(pBI_MulMod_1, pBI_PInverse, &pBI_MulMod_2); + BigInteger_Div2Exponent(pBI_MulMod_2, Bits_Of_R, pBI_Result, &pBI_MulMod_3); + BigInteger_Mul(pBI_MulMod_3, pBI_P, pBI_Result); + BigInteger_Add(pBI_MulMod_1, *pBI_Result, &pBI_MulMod_3); + BigInteger_Div2Exponent(pBI_MulMod_3, Bits_Of_R, &pBI_MulMod_2, pBI_Result); + + if (BigInteger_UnsignedCompare(pBI_MulMod_2, pBI_P) >= 0) + BigInteger_Sub(pBI_MulMod_2, pBI_P, pBI_Result); + else + BigInteger_Copy(pBI_MulMod_2, pBI_Result); + + release_temporal_usage_big_interger(&pBI_MulMod_1); + release_temporal_usage_big_interger(&pBI_MulMod_2); + release_temporal_usage_big_interger(&pBI_MulMod_3); + POOL_COUNTER_CHECK_END(expected_cnt[1]); +} /* End of BigInteger_Montgomery_MulMod */ + +#ifdef WSC_INCLUDED +extern UINT8 WPS_DH_P_VALUE[192]; +#endif + +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, Bits_Of_E, Bits_Of_R; + UINT32 Index, AllocLength; + PBIG_INTEGER pBI_Temp1 = NULL, pBI_Temp2 = NULL; + PBIG_INTEGER pBI_A = NULL, pBI_X = NULL, pBI_R = NULL, pBI_1 = NULL, pBI_PInverse = NULL; + /* For workaround */ + /*if (pBI_P->IntegerLength == 32) { + BigInteger_Montgomery_ExpMod32(pBI_G, pBI_E, pBI_P, pBI_Result); + return; + }*/ + BigInteger_record_time_begin(&bi_op_ti_rec.exp_mod_op); + POOL_COUNTER_CHECK_BEGIN(expected_cnt[18]); + GET_BI_INS_FROM_POOL(pBI_Temp1); + GET_BI_INS_FROM_POOL(pBI_Temp2); + AllocLength = (pBI_G->IntegerLength + pBI_E->IntegerLength + pBI_P->IntegerLength) + 50; + BigInteger_AllocSize(&pBI_Temp1, AllocLength); + BigInteger_AllocSize(&pBI_Temp2, AllocLength); + + /* -- For spicial case --- */ + if ((pBI_G->IntegerLength == 1) && (pBI_G->pIntegerArray[0] == 0)) { + BigInteger_Bin2BI(Value_0, 1, pBI_Result); + goto memory_free; + } + + if ((pBI_G->IntegerLength == 1) && (pBI_G->pIntegerArray[0] == 1)) { + BigInteger_Div(pBI_G, pBI_P, &pBI_Temp1, pBI_Result); + goto memory_free; + } + + if ((pBI_E->IntegerLength == 1) && (pBI_E->pIntegerArray[0] == 1)) { + BigInteger_Div(pBI_G, pBI_P, &pBI_Temp1, pBI_Result); + goto memory_free; + } + + if ((pBI_E->IntegerLength == 1) && (pBI_E->pIntegerArray[0] == 2)) { + BigInteger_Square2(pBI_G, &pBI_Temp1); + BigInteger_Div(pBI_Temp1, pBI_P, &pBI_Temp2, pBI_Result); + goto memory_free; + } + + GET_BI_INS_FROM_POOL(pBI_A); + GET_BI_INS_FROM_POOL(pBI_X); + GET_BI_INS_FROM_POOL(pBI_R); + GET_BI_INS_FROM_POOL(pBI_PInverse); + GET_BI_INS_FROM_POOL(pBI_1); + /* ---Main algorithm --- */ + BigInteger_Init(&pBI_A); + BigInteger_Init(&pBI_X); + BigInteger_Init(&pBI_R); + BigInteger_Init(&pBI_PInverse); + BigInteger_Bin2BI(Value_1, 1, &pBI_1); + BigInteger_AllocSize(&pBI_X, AllocLength); +#ifdef WSC_INCLUDED + 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_PInverse_VALUE, 192, &pBI_PInverse); + } else +#endif + { + UINT8 *pRValue = NULL; + BigInteger_BitsOfBI(pBI_P, &Bits_Of_P); + + if ((Bits_Of_P % 8) == 0) + AllocLength = pBI_P->IntegerLength + 1; + else + AllocLength = pBI_P->IntegerLength; + + os_alloc_mem(NULL, (UCHAR **)&pRValue, sizeof(UINT8)*AllocLength); + NdisZeroMemory(pRValue, sizeof(UINT8)*AllocLength); + pRValue[0] = (UINT8) (1 << (Bits_Of_P & 0x7)); + BigInteger_Bin2BI(pRValue, AllocLength, &pBI_R); + os_free_mem(NULL, pRValue); + BigInteger_Inverse(pBI_R, pBI_P, &pBI_Temp1, &pBI_PInverse); /* Calculate the inverse of P */ + BigInteger_Div(pBI_R, pBI_P, &pBI_Temp2, &pBI_X); /* X = 1*R (mod P) */ + } /* End of if */ + + /* A = G*R (mod P) */ + BigInteger_Mul(pBI_G, pBI_R, &pBI_Temp1); + BigInteger_Div(pBI_Temp1, pBI_P, &pBI_Temp2, &pBI_A); + /* Calculate (G^E) * R mod P */ + BigInteger_BitsOfBI(pBI_E, &Bits_Of_E); /* Calculate the bits of E */ + BigInteger_BitsOfBI(pBI_R, &Bits_Of_R); /* Calculate the bits of R */ + + for (Index = Bits_Of_E; Index > 0; Index--) { + BigInteger_Montgomery_MulMod(pBI_X, pBI_X, pBI_P, pBI_PInverse, Bits_Of_R, &pBI_Temp1); + + if (BigInteger_GetBitValue(pBI_E, Index)) + BigInteger_Montgomery_MulMod(pBI_A, pBI_Temp1, pBI_P, pBI_PInverse, Bits_Of_R, &pBI_X); + else + BigInteger_Copy(pBI_Temp1, &pBI_X); /* End of if */ + } /* End of for */ + + BigInteger_Montgomery_MulMod(pBI_X, pBI_1, pBI_P, pBI_PInverse, Bits_Of_R, pBI_Result); + release_temporal_usage_big_interger(&pBI_A); + release_temporal_usage_big_interger(&pBI_X); + release_temporal_usage_big_interger(&pBI_R); + release_temporal_usage_big_interger(&pBI_PInverse); + release_temporal_usage_big_interger(&pBI_1); +memory_free: + release_temporal_usage_big_interger(&pBI_Temp1); + release_temporal_usage_big_interger(&pBI_Temp2); + POOL_COUNTER_CHECK_END(expected_cnt[18]); + BigInteger_record_time_end(&bi_op_ti_rec.exp_mod_op); +} /* End of BigInteger_Montgomery_ExpMod */ + + +VOID BigInteger_Montgomery_MulMod_with_mont( + IN PBIG_INTEGER pBI_A, + IN PBIG_INTEGER pBI_B, + IN PBIG_INTEGER pBI_P, + IN MONT_STRUC * mont, + OUT PBIG_INTEGER *pBI_Result) +{ + PBIG_INTEGER pBI_MulMod_1 = NULL; + PBIG_INTEGER pBI_MulMod_2 = NULL; + PBIG_INTEGER pBI_MulMod_3 = NULL; + + if (*pBI_Result == NULL) + BigInteger_Init(pBI_Result); + + POOL_COUNTER_CHECK_BEGIN(expected_cnt[20]); + GET_BI_INS_FROM_POOL(pBI_MulMod_1); + GET_BI_INS_FROM_POOL(pBI_MulMod_2); + GET_BI_INS_FROM_POOL(pBI_MulMod_3); + BigInteger_Mul(pBI_A, pBI_B, &pBI_MulMod_1); + BigInteger_Mul(pBI_MulMod_1, mont->pBI_PInverse, &pBI_MulMod_2); + BigInteger_Div2Exponent(pBI_MulMod_2, mont->Bits_Of_R, pBI_Result, &pBI_MulMod_3); + BigInteger_Mul(pBI_MulMod_3, pBI_P, pBI_Result); + BigInteger_Add(pBI_MulMod_1, *pBI_Result, &pBI_MulMod_3); + BigInteger_Div2Exponent(pBI_MulMod_3, mont->Bits_Of_R, &pBI_MulMod_2, pBI_Result); + + if (BigInteger_UnsignedCompare(pBI_MulMod_2, pBI_P) >= 0) + BigInteger_Sub(pBI_MulMod_2, pBI_P, pBI_Result); + else + BigInteger_Copy(pBI_MulMod_2, pBI_Result); + + release_temporal_usage_big_interger(&pBI_MulMod_1); + release_temporal_usage_big_interger(&pBI_MulMod_2); + release_temporal_usage_big_interger(&pBI_MulMod_3); + POOL_COUNTER_CHECK_END(expected_cnt[20]); +} /* End of BigInteger_Montgomery_MulMod */ + + +VOID BigInteger_Montgomery_ExpMod_with_mont( + IN PBIG_INTEGER pBI_G, + IN PBIG_INTEGER pBI_E, + IN PBIG_INTEGER pBI_P, + IN MONT_STRUC * mont, + OUT PBIG_INTEGER *pBI_Result) +{ + UINT Bits_Of_P, Bits_Of_E, Bits_Of_R; + UINT32 Index, AllocLength; + PBIG_INTEGER pBI_Temp1 = NULL, pBI_Temp2 = NULL; + PBIG_INTEGER pBI_A = NULL, pBI_X = NULL, pBI_R = NULL, pBI_1 = NULL, pBI_PInverse = NULL; + /* For workaround */ + /*if (pBI_P->IntegerLength == 32) { + BigInteger_Montgomery_ExpMod32(pBI_G, pBI_E, pBI_P, pBI_Result); + return; + }*/ + BigInteger_record_time_begin(&bi_op_ti_rec.exp_mod_op); + POOL_COUNTER_CHECK_BEGIN(expected_cnt[21]); + GET_BI_INS_FROM_POOL(pBI_Temp1); + GET_BI_INS_FROM_POOL(pBI_Temp2); + AllocLength = (pBI_G->IntegerLength + pBI_E->IntegerLength + pBI_P->IntegerLength) + 50; + BigInteger_AllocSize(&pBI_Temp1, AllocLength); + BigInteger_AllocSize(&pBI_Temp2, AllocLength); + + /* -- For spicial case --- */ + if ((pBI_G->IntegerLength == 1) && (pBI_G->pIntegerArray[0] == 0)) { + BigInteger_Bin2BI(Value_0, 1, pBI_Result); + goto memory_free; + } + + if ((pBI_G->IntegerLength == 1) && (pBI_G->pIntegerArray[0] == 1)) { + BigInteger_Div(pBI_G, pBI_P, &pBI_Temp1, pBI_Result); + goto memory_free; + } + + if ((pBI_E->IntegerLength == 1) && (pBI_E->pIntegerArray[0] == 1)) { + BigInteger_Div(pBI_G, pBI_P, &pBI_Temp1, pBI_Result); + goto memory_free; + } + + if ((pBI_E->IntegerLength == 1) && (pBI_E->pIntegerArray[0] == 2)) { + BigInteger_Square2(pBI_G, &pBI_Temp1); + BigInteger_Div(pBI_Temp1, pBI_P, &pBI_Temp2, pBI_Result); + goto memory_free; + } + + GET_BI_INS_FROM_POOL(pBI_A); + GET_BI_INS_FROM_POOL(pBI_X); + GET_BI_INS_FROM_POOL(pBI_R); + GET_BI_INS_FROM_POOL(pBI_PInverse); + GET_BI_INS_FROM_POOL(pBI_1); + /* ---Main algorithm --- */ + BigInteger_Init(&pBI_A); + BigInteger_Init(&pBI_X); + BigInteger_Init(&pBI_R); + BigInteger_Init(&pBI_PInverse); + BigInteger_Bin2BI(Value_1, 1, &pBI_1); + BigInteger_AllocSize(&pBI_X, AllocLength); +#ifdef WSC_INCLUDED + BigInteger_Bin2BI(WPS_DH_P_VALUE, 192, &pBI_Temp1); +#endif + if (mont != NULL) { + BigInteger_Copy(mont->pBI_X, &pBI_X); + BigInteger_Copy(mont->pBI_R, &pBI_R); + BigInteger_Copy(mont->pBI_PInverse, &pBI_PInverse); + Bits_Of_R = mont->Bits_Of_R; + } + +#ifdef WSC_INCLUDED + 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_PInverse_VALUE, 192, &pBI_PInverse); + BigInteger_BitsOfBI(pBI_R, &Bits_Of_R); /* Calculate the bits of R */ + } else +#endif + { + UINT8 *pRValue = NULL; + BigInteger_BitsOfBI(pBI_P, &Bits_Of_P); + + if ((Bits_Of_P % 8) == 0) + AllocLength = pBI_P->IntegerLength + 1; + else + AllocLength = pBI_P->IntegerLength; + + os_alloc_mem(NULL, (UCHAR **)&pRValue, sizeof(UINT8)*AllocLength); + NdisZeroMemory(pRValue, sizeof(UINT8)*AllocLength); + pRValue[0] = (UINT8) (1 << (Bits_Of_P & 0x7)); + BigInteger_Bin2BI(pRValue, AllocLength, &pBI_R); + os_free_mem(NULL, pRValue); + BigInteger_Inverse(pBI_R, pBI_P, &pBI_Temp1, &pBI_PInverse); /* Calculate the inverse of P */ + BigInteger_Div(pBI_R, pBI_P, &pBI_Temp2, &pBI_X); /* X = 1*R (mod P) */ + BigInteger_BitsOfBI(pBI_R, &Bits_Of_R); /* Calculate the bits of R */ + } /* End of if */ + + /* A = G*R (mod P) */ + BigInteger_Mul(pBI_G, pBI_R, &pBI_Temp1); + BigInteger_Div(pBI_Temp1, pBI_P, &pBI_Temp2, &pBI_A); + /* Calculate (G^E) * R mod P */ + BigInteger_BitsOfBI(pBI_E, &Bits_Of_E); /* Calculate the bits of E */ + + for (Index = Bits_Of_E; Index > 0; Index--) { + BigInteger_Montgomery_MulMod_with_mont(pBI_X, pBI_X, pBI_P, mont, &pBI_Temp1); + + if (BigInteger_GetBitValue(pBI_E, Index)) + BigInteger_Montgomery_MulMod_with_mont(pBI_A, pBI_Temp1, pBI_P, mont, &pBI_X); + else + BigInteger_Copy(pBI_Temp1, &pBI_X); /* End of if */ + } /* End of for */ + + BigInteger_Montgomery_MulMod_with_mont(pBI_X, pBI_1, pBI_P, mont, pBI_Result); + release_temporal_usage_big_interger(&pBI_A); + release_temporal_usage_big_interger(&pBI_X); + release_temporal_usage_big_interger(&pBI_R); + release_temporal_usage_big_interger(&pBI_PInverse); + release_temporal_usage_big_interger(&pBI_1); +memory_free: + release_temporal_usage_big_interger(&pBI_Temp1); + release_temporal_usage_big_interger(&pBI_Temp2); + POOL_COUNTER_CHECK_END(expected_cnt[21]); + BigInteger_record_time_end(&bi_op_ti_rec.exp_mod_op); +} /* End of BigInteger_Montgomery_ExpMod */ + + + +VOID BigInteger_Mod( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + OUT PBIG_INTEGER *pBI_Remainder) +{ + INT CompareResult; + INT Index, MulIndex, ComputeSize; + UINT32 MulLoopStart, MulLoopEnd; + UINT AllocLength, ArrayIndex, ShiftIndex; + UINT8 SecondHighByte; + PBIG_INTEGER pTempBI = NULL; + PBIG_INTEGER pTempBI2 = NULL; + PBIG_INTEGER pMulBI = NULL; +#ifdef BI_TIME_REC + struct timeval t1; + struct timeval t2; + + if (is_time_rec) { + do_gettimeofday(&t1); + is_mod_alloc_rec = TRUE; + } + +#endif + + 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 */ + + POOL_COUNTER_CHECK_BEGIN(expected_cnt[17]); + GET_BI_INS_FROM_POOL(pTempBI); + GET_BI_INS_FROM_POOL(pTempBI2); + GET_BI_INS_FROM_POOL(pMulBI); + + if (*pBI_Remainder == NULL) + BigInteger_Init(pBI_Remainder); + + /* The second operand is one */ + if ((pSecondOperand->IntegerLength == 1) && (pSecondOperand->pIntegerArray[0] == 1)) { + BigInteger_Bin2BI(Value_0, 1, pBI_Remainder); + goto output; + } /* End of if */ + + CompareResult = BigInteger_UnsignedCompare(pFirstOperand, pSecondOperand); + + if (CompareResult == 0) { + BigInteger_Bin2BI(Value_0, 1, pBI_Remainder); + goto output; + } else if (CompareResult == -1) { + BigInteger_Copy(pFirstOperand, pBI_Remainder); + goto output; + } /* End of if */ + + 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) & 0xFF); + 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--; + MulLoopStart = (BigInteger_GetByteValue((*pBI_Remainder), pFirstOperand->IntegerLength + Index - ComputeSize + 1) & 0xFF) << 8; + MulLoopStart = MulLoopStart | (BigInteger_GetByteValue((*pBI_Remainder), pFirstOperand->IntegerLength + Index - ComputeSize) & 0xFF); + + if (MulLoopStart < (UINT32) SecondHighByte) + continue; + + if (SecondHighByte != 0) + MulLoopEnd = (MulLoopStart / (UINT32) SecondHighByte) + 1; + else { + MulLoopEnd = MulLoopStart; + MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("MulLoopStart division by zero!!\n")); + } + MulLoopStart = MulLoopStart / (UINT32) (SecondHighByte + 1); + + for (MulIndex = (INT) MulLoopStart; MulIndex <= MulLoopEnd; MulIndex++) { /* 0xFFFF / 0x01 = 0xFFFF */ + NdisZeroMemory(pMulBI->pIntegerArray, pMulBI->AllocSize); + + if ((MulIndex > 0xff) && (ShiftIndex == 3)) { + pMulBI->pIntegerArray[ArrayIndex] = ((UINT) (MulIndex & 0xff) << (8 * ShiftIndex)); + pMulBI->pIntegerArray[ArrayIndex + 1] = (UINT) (MulIndex >> 8) & 0xff; + } else + pMulBI->pIntegerArray[ArrayIndex] = ((UINT) (MulIndex) << (8 * ShiftIndex)); + + BigInteger_Mul(pSecondOperand, pMulBI, &pTempBI); + CompareResult = BigInteger_UnsignedCompare(*pBI_Remainder, pTempBI); + + if (CompareResult < 1) { + if (CompareResult == -1) { + MulIndex = MulIndex - 1; + NdisZeroMemory(pMulBI->pIntegerArray, pMulBI->AllocSize); + + if ((MulIndex > 0xff) && (ShiftIndex == 3)) { + pMulBI->pIntegerArray[ArrayIndex] = ((UINT) (MulIndex & 0xff) << (8 * ShiftIndex)); + pMulBI->pIntegerArray[ArrayIndex + 1] = (UINT) (MulIndex >> 8) & 0xff; + } else + pMulBI->pIntegerArray[ArrayIndex] = ((UINT) (MulIndex) << (8 * ShiftIndex)); + + BigInteger_Mul(pSecondOperand, pMulBI, &pTempBI); + } + + BigInteger_Sub(*pBI_Remainder, pTempBI, &pTempBI2); + BigInteger_Copy(pTempBI2, pBI_Remainder); + break; + } /* End of if */ + } /* End of for */ + } /* End of if */ + } /* End of for */ + +output: + (*pBI_Remainder)->Signed = pFirstOperand->Signed * pSecondOperand->Signed; + BigInteger_ClearHighBits(*pBI_Remainder); + release_temporal_usage_big_interger(&pTempBI); + release_temporal_usage_big_interger(&pTempBI2); + release_temporal_usage_big_interger(&pMulBI); + POOL_COUNTER_CHECK_END(expected_cnt[17]); +#ifdef BI_TIME_REC + + if (is_time_rec) { + ULONG time_interval = 0; + do_gettimeofday(&t2); + + if (t1.tv_usec > t2.tv_usec) + time_interval = (t2.tv_sec - t1.tv_sec) * 1000000 - t1.tv_usec + t2.tv_usec; + else + time_interval = t2.tv_usec - t1.tv_usec; + + BigInteger_record_time_ns(&bi_op_ti_rec.mod_op, time_interval); + is_mod_alloc_rec = FALSE; + } + +#endif +} + +VOID BigInteger_Mod_Mul( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER *pBI_Result) +{ + BIG_INTEGER *tmp = NULL; + POOL_COUNTER_CHECK_BEGIN(expected_cnt[8]); + GET_BI_INS_FROM_POOL(tmp); + BigInteger_Init(&tmp); + BigInteger_Mul(pFirstOperand, pSecondOperand, &tmp); + BigInteger_Mod(tmp, pBI_P, pBI_Result); + release_temporal_usage_big_interger(&tmp); + POOL_COUNTER_CHECK_END(expected_cnt[8]); +} + +UCHAR BigInteger_is_zero( + IN PBIG_INTEGER pBI) +{ + BigInteger_ClearHighBits(pBI); + + if (pBI->IntegerLength == 1 + && pBI->Signed == 1 + && pBI->pIntegerArray[0] == 0) + return TRUE; + else + return FALSE; +} + +UCHAR BigInteger_is_one( + IN PBIG_INTEGER pBI) +{ + BigInteger_ClearHighBits(pBI); + + if (pBI->IntegerLength == 1 + && pBI->Signed == 1 + && pBI->pIntegerArray[0] == 1) + return TRUE; + else + return FALSE; +} + +UCHAR BigInteger_is_odd( + IN PBIG_INTEGER pBI) +{ + if (!pBI) + return FALSE; + + if (pBI->IntegerLength == 0) + return FALSE; + + if (pBI->pIntegerArray[0] & BIT0) + return TRUE; + else + return FALSE; +} + + +VOID BigInteger_Mod_Square( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER *pBI_Result) +{ + BigInteger_Mod_Mul(pFirstOperand, pFirstOperand, pBI_P, pBI_Result); +} + +VOID BigInteger_Mod_Add( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER *pBI_Result) +{ + BIG_INTEGER *tmp = NULL; + POOL_COUNTER_CHECK_BEGIN(expected_cnt[2]); + GET_BI_INS_FROM_POOL(tmp); + BigInteger_Add(pFirstOperand, pSecondOperand, &tmp); + BigInteger_Mod(tmp, pBI_P, pBI_Result); + release_temporal_usage_big_interger(&tmp); + POOL_COUNTER_CHECK_END(expected_cnt[2]); +} + + +VOID BigInteger_Mod_Sub( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER *pBI_Result) +{ + BIG_INTEGER *tmp = NULL; + BIG_INTEGER *res = NULL; + POOL_COUNTER_CHECK_BEGIN(expected_cnt[3]); + GET_BI_INS_FROM_POOL(tmp); + GET_BI_INS_FROM_POOL(res); + BigInteger_Sub(pFirstOperand, pSecondOperand, &tmp); + + if (tmp->Signed == 1) + BigInteger_Mod(tmp, pBI_P, &res); + else { + BIG_INTEGER *tmp2 = NULL; + GET_BI_INS_FROM_POOL(tmp2); + tmp->Signed = 1; + BigInteger_Mod(tmp, pBI_P, &tmp2); + BigInteger_Sub(pBI_P, tmp2, &res); + release_temporal_usage_big_interger(&tmp2); + } + + BigInteger_Copy(res, pBI_Result); + release_temporal_usage_big_interger(&tmp); + release_temporal_usage_big_interger(&res); + POOL_COUNTER_CHECK_END(expected_cnt[3]); +} + + +VOID BigInteger_Mod_Add_quick( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER *pBI_Result) +{ + BIG_INTEGER *tmp = NULL; + POOL_COUNTER_CHECK_BEGIN(expected_cnt[4]); + GET_BI_INS_FROM_POOL(tmp); + BigInteger_Add(pFirstOperand, pSecondOperand, &tmp); + + if (BigInteger_UnsignedCompare(tmp, pBI_P) >= 0) + BigInteger_Sub(tmp, pBI_P, pBI_Result); + else + BigInteger_Copy(tmp, pBI_Result); + + release_temporal_usage_big_interger(&tmp); + POOL_COUNTER_CHECK_END(expected_cnt[4]); +} + + +VOID BigInteger_Mod_Sub_quick( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER *pBI_Result) +{ + BIG_INTEGER *tmp = NULL; + POOL_COUNTER_CHECK_BEGIN(expected_cnt[5]); + GET_BI_INS_FROM_POOL(tmp); + BigInteger_Sub(pFirstOperand, pSecondOperand, &tmp); + + if (tmp->Signed == -1) + BigInteger_Add(tmp, pBI_P, pBI_Result); + else + BigInteger_Copy(tmp, pBI_Result); + + release_temporal_usage_big_interger(&tmp); + POOL_COUNTER_CHECK_END(expected_cnt[5]); +} + + +VOID BigInteger_Mod_Div( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER *pBI_Result) +{ + BIG_INTEGER *tmp = NULL; + POOL_COUNTER_CHECK_BEGIN(expected_cnt[6]); + GET_BI_INS_FROM_POOL(tmp); + BigInteger_record_time_begin(&bi_op_ti_rec.div_mod_op); + BigInteger_Mod_Mul_Inverse(pSecondOperand, pBI_P, &tmp); + + if (tmp == NULL) { + release_temporal_usage_big_interger(pBI_Result); + DEBUGPRINT("BigInteger_Mod_Mul_Inverse fail!!\n"); + return; + } + + BigInteger_Mod_Mul(pFirstOperand, tmp, pBI_P, &tmp); + BigInteger_Copy(tmp, pBI_Result); + release_temporal_usage_big_interger(&tmp); + POOL_COUNTER_CHECK_END(expected_cnt[6]); + BigInteger_record_time_end(&bi_op_ti_rec.div_mod_op); +} + + + +/* Tonelli¡VShanks algorithm*/ +/* reference: https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm */ +/* pBI_P must be prime */ +VOID BigInteger_Mod_Sqrt( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pBI_P, + IN MONT_STRUC * mont, + OUT PBIG_INTEGER *pBI_Result) +{ + BIG_INTEGER *p = NULL; + BIG_INTEGER *Q = NULL; + BIG_INTEGER *R = NULL; + BIG_INTEGER *t = NULL; + BIG_INTEGER *c = NULL; + BIG_INTEGER *z = NULL; + UINT32 S = 0; + UINT32 M = 0; + UINT32 i; + BIG_INTEGER *pone = NULL; + BIG_INTEGER *tmp = NULL; + BIG_INTEGER *b = NULL; + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("==> %s()\n", __func__)); + BigInteger_record_time_begin(&bi_op_ti_rec.sqrt_mod_op); + + if (BigInteger_is_quadratic_residue(pFirstOperand, pBI_P, mont) == FALSE) { + /* MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("%s: is_not_quadratic_residue\n", __FUNCTION__)); */ + release_temporal_usage_big_interger(pBI_Result); + return; + } + + POOL_COUNTER_CHECK_BEGIN(expected_cnt[9]); + GET_BI_INS_FROM_POOL(p); + GET_BI_INS_FROM_POOL(Q); + GET_BI_INS_FROM_POOL(R); + GET_BI_INS_FROM_POOL(t); + GET_BI_INS_FROM_POOL(c); + GET_BI_INS_FROM_POOL(z); + GET_BI_INS_FROM_POOL(tmp); + GET_BI_INS_FROM_POOL(b); + /* fix me */ + GET_BI_INS_FROM_POOL(pone); + /* MTWF_LOG(DBG_CAT_SEC, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("\x1b[31m%s: is_quadratic_residue\x1b[m\n", __FUNCTION__)); */ + /*DEBUGPRINT("pFirstOperand\n"); + BigInteger_Print(pFirstOperand);*/ + BigInteger_Copy(pBI_P, &p); + BigInteger_minus_one(p); + + /* p - 1 = Q * 2^S */ + while (BigInteger_is_odd(p) == FALSE) { + S++; + BigInteger_Shift_Right1(p, &p); + } + + BigInteger_Copy(p, &Q); + /* R = n^((Q+1)/2) (mod P) */ + BigInteger_Init(&R); + BigInteger_Copy(Q, &p); + BigInteger_plus_one(p); + BigInteger_Shift_Right1(p, &p); + BigInteger_Montgomery_ExpMod_with_mont(pFirstOperand, p, pBI_P, mont, &R); + /*BigInteger_Mod_Mul(R, R, pBI_P, &tmp); + DEBUGPRINT("R:\n"); + BigInteger_Print(R); + DEBUGPRINT("R^2:\n"); + BigInteger_Print(tmp);*/ + /* t = n^Q (mod P) */ + BigInteger_Init(&t); + BigInteger_Montgomery_ExpMod_with_mont(pFirstOperand, Q, pBI_P, mont, &t); /* ellis */ + /*DEBUGPRINT("pFirstOperand:\n"); + BigInteger_Print(pFirstOperand); + DEBUGPRINT("Q:\n"); + BigInteger_Print(Q); + DEBUGPRINT("t:\n"); + BigInteger_Print(t); + BigInteger_Mod_Mul(t, pFirstOperand, pBI_P, &tmp); + DEBUGPRINT("t*n:\n"); + BigInteger_Print(tmp);*/ + /* M = S */ + M = S; + + if (BigInteger_is_one(t)) + goto Find; + + /* Find the first quadratic non-residue z by brute-force search */ + BigInteger_Init(&c); + BigInteger_Init(&z); + BigInteger_DWtoBI(1, &z); + BigInteger_Copy(pBI_P, &p); + BigInteger_minus_one(p); + BigInteger_Shift_Right1(p, &p); + + do { + BigInteger_plus_one(z); + BigInteger_Montgomery_ExpMod_with_mont(z, p, pBI_P, mont, &tmp); + BigInteger_plus_one(tmp); + } while (BigInteger_UnsignedCompare(tmp, pBI_P) != 0); + + BigInteger_Montgomery_ExpMod_with_mont(z, Q, pBI_P, mont, &c); + BigInteger_DWtoBI(1, &pone); + + while (BigInteger_is_one(t) == FALSE) { + BigInteger_Copy(t, &tmp); + + /* find the lowest i, 0 < i < M, such that t^(2^i) = 1 (mod P) */ + for (i = 1; i < M; i++) { + BigInteger_Mod_Mul(tmp, tmp, pBI_P, &tmp); + + if (BigInteger_is_one(tmp)) + break; + } + + if (i == M) { + DEBUGPRINT("\x1b[33msearch fail\x1b[m\n"); + BigInteger_Free(pBI_Result); + goto Free; + } + + /* b = c^2^(M-i-1) (mod P)*/ + BigInteger_Shift_Left(pone, M - i - 1, &tmp); + BigInteger_Montgomery_ExpMod_with_mont(c, tmp, pBI_P, mont, &b); + /* R = R*b (mod P)*/ + BigInteger_Mod_Mul(R, b, pBI_P, &R); + /* t = t*b^2 (mod P), c = b^2 (mod P) */ + BigInteger_Mod_Mul(b, b, pBI_P, &c); + BigInteger_Mod_Mul(t, c, pBI_P, &t); + /* M = i */ + M = i; + } + +Find: + BigInteger_Copy(pFirstOperand, &p); + BigInteger_Copy(R, pBI_Result); +Free: + release_temporal_usage_big_interger(&p); + release_temporal_usage_big_interger(&Q); + release_temporal_usage_big_interger(&R); + release_temporal_usage_big_interger(&t); + release_temporal_usage_big_interger(&pone); + release_temporal_usage_big_interger(&tmp); + release_temporal_usage_big_interger(&b); + release_temporal_usage_big_interger(&c); + release_temporal_usage_big_interger(&z); + POOL_COUNTER_CHECK_END(expected_cnt[9]); + BigInteger_record_time_end(&bi_op_ti_rec.sqrt_mod_op); +} + +VOID BigInteger_Euclidean_Div( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + IN PBIG_INTEGER prev_u, + IN PBIG_INTEGER prev_v, + INOUT PBIG_INTEGER curr_u, + INOUT PBIG_INTEGER curr_v) +{ + PBIG_INTEGER div_result = NULL; + PBIG_INTEGER div_Remainder = NULL; + PBIG_INTEGER tmp2 = NULL; + PBIG_INTEGER tmp = NULL; + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("==> %s()\n", __func__)); + POOL_COUNTER_CHECK_BEGIN(expected_cnt[13]); + GET_BI_INS_FROM_POOL(div_result); + GET_BI_INS_FROM_POOL(div_Remainder); + GET_BI_INS_FROM_POOL(tmp); + GET_BI_INS_FROM_POOL(tmp2); + + while (!BigInteger_is_one(pSecondOperand) + && !BigInteger_is_zero(pSecondOperand)) { + BigInteger_Div(pFirstOperand, pSecondOperand, &div_result, &div_Remainder); /* pFirstOperand = pSecondOperand * div_result + div_Remainder */ + /* new_u = prev_u - curr_u * div_result */ + BigInteger_Mul(curr_u, div_result, &tmp); + BigInteger_Sub(prev_u, tmp, &tmp2); + BigInteger_Copy(curr_u, &prev_u); + BigInteger_Copy(tmp2, &curr_u); + /* new_v = prev_v - curr_v * div_result */ + BigInteger_Mul(curr_v, div_result, &tmp); + BigInteger_Sub(prev_v, tmp, &tmp2); + BigInteger_Copy(curr_v, &prev_v); + BigInteger_Copy(tmp2, &curr_v); + BigInteger_Copy(pSecondOperand, &pFirstOperand); + BigInteger_Copy(div_Remainder, &pSecondOperand); + }; + + release_temporal_usage_big_interger(&div_result); + + release_temporal_usage_big_interger(&div_Remainder); + + release_temporal_usage_big_interger(&tmp2); + + release_temporal_usage_big_interger(&tmp); + + POOL_COUNTER_CHECK_END(expected_cnt[13]); +} + +/* +UCHAR test[7] = { + 0x72, 0xf8, 0x45, 0x05, 0x69, 0xb0, 0x4d +};*/ + +UCHAR test[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 +}; + + +UCHAR test2[] = {0x72, 0xf8, 0x45, 0x03, 0x69, 0xb0, 0x45, 0xff, 0xfa, 0xc3, 0x21}; + + +VOID BigInteger_Mod_Mul_Inverse( + IN PBIG_INTEGER pBI, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER *pBI_Result) +{ + PBIG_INTEGER pFirstOperand = NULL; + PBIG_INTEGER pSecondOperand = NULL; + PBIG_INTEGER res = NULL; + PBIG_INTEGER prev_u = NULL; + PBIG_INTEGER prev_v = NULL; + PBIG_INTEGER curr_u = NULL; + PBIG_INTEGER curr_v = NULL; + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("==> %s()\n", __func__)); + BigInteger_record_time_begin(&bi_op_ti_rec.mod_mul_inv_op); + POOL_COUNTER_CHECK_BEGIN(expected_cnt[14]); + GET_BI_INS_FROM_POOL(pFirstOperand); + GET_BI_INS_FROM_POOL(pSecondOperand); + GET_BI_INS_FROM_POOL(res); + GET_BI_INS_FROM_POOL(prev_u); + GET_BI_INS_FROM_POOL(prev_v); + GET_BI_INS_FROM_POOL(curr_u); + GET_BI_INS_FROM_POOL(curr_v); + BigInteger_Init(&pFirstOperand); + BigInteger_Init(&pSecondOperand); + + if (pBI == NULL) + BigInteger_Bin2BI(test, sizeof(test), &pFirstOperand); + else + BigInteger_Copy(pBI_P, &pFirstOperand); + + if (pBI_P == NULL) + BigInteger_Bin2BI(test2, sizeof(test2), &pSecondOperand); + else + BigInteger_Mod(pBI, pBI_P, &pSecondOperand); + + /*DEBUGPRINT("P:"); + BigInteger_Print(ptest);*/ + /*DEBUGPRINT("INPUT:"); + BigInteger_Print(ptest2);*/ + BigInteger_DWtoBI(1, &prev_u); + BigInteger_DWtoBI(0, &curr_u); + BigInteger_DWtoBI(0, &prev_v); + BigInteger_DWtoBI(1, &curr_v); + BigInteger_Euclidean_Div(pFirstOperand, pSecondOperand, prev_u, prev_v, curr_u, curr_v); + + if (BigInteger_is_one(pSecondOperand) == FALSE) { + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("\x1b[31mpSecondOperand is not one!!!!!!\x1b[m\n")); + release_temporal_usage_big_interger(pBI_Result); + goto Free; + } + + + if (curr_v->Signed == -1) { + BigInteger_Add(curr_v, pBI_P, &res); + BigInteger_Copy(res, pBI_Result); + } else + BigInteger_Copy(curr_v, pBI_Result); + + /*DEBUGPRINT("BigInteger_Modular_Mul_Inverse result:"); + BigInteger_Print(*pBI_Result);*/ +Free: + release_temporal_usage_big_interger(&pFirstOperand); + release_temporal_usage_big_interger(&pSecondOperand); + release_temporal_usage_big_interger(&res); + release_temporal_usage_big_interger(&prev_u); + release_temporal_usage_big_interger(&prev_v); + release_temporal_usage_big_interger(&curr_u); + release_temporal_usage_big_interger(&curr_v); + POOL_COUNTER_CHECK_END(expected_cnt[14]); + BigInteger_record_time_end(&bi_op_ti_rec.mod_mul_inv_op); +} + +VOID BigInteger_Mod_Mul_Inverse2( + IN PBIG_INTEGER pBI, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER *pBI_Result) +{ + BIG_INTEGER *tmp = NULL; + BigInteger_record_time_begin(&bi_op_ti_rec.mod_mul_inv_op); + BigInteger_Inverse(pBI, pBI_P, pBI_Result, &tmp); + release_temporal_usage_big_interger(&tmp); + BigInteger_record_time_end(&bi_op_ti_rec.mod_mul_inv_op); +} + + + +UCHAR testa[] = {0x38, 0xa0, 0x39, 0xeb, 0x50, 0x4f, 0x4f, 0x50}; + + +UCHAR BigInteger_Sqrt( + IN PBIG_INTEGER pBI, + OUT PBIG_INTEGER *pBI_Result) +{ + PBIG_INTEGER x = NULL; + UINT32 x_len; + UCHAR *x_buf = NULL; + PBIG_INTEGER ptest = NULL; + UINT8 first_byte; + UINT8 x_first_byte; + UCHAR res; + UINT32 i = 0; + BigInteger_record_time_begin(&bi_op_ti_rec.sqrt_op); + + /* + * Let S = a * 0x10^2n, where 0x1 <= a <= 0xff + * X ={ 0x2 * 0x10^n, where 0x1 <= a <= 0x10 ,note: sqrt(sqrt(0x1)*sqrt(0x10)) = 0x2 + * { 0x7 * 0x20^n, where 0x10 < a <= 0xff ,note: sqrt(sqrt(0x10)*sqrt(0x100)) ~= 0x7 + */ + if (pBI == NULL) + BigInteger_Bin2BI(testa, sizeof(testa), &ptest); + else + BigInteger_Copy(pBI, &ptest); + + /*DEBUGPRINT("input:"); + BigInteger_Print(ptest);*/ + x_len = (ptest->IntegerLength + 1) / 2; + os_alloc_mem(NULL, &x_buf, x_len); + + if (x_buf == NULL) { + res = FALSE; + goto Free; + } + + NdisZeroMemory(x_buf, x_len); + first_byte = BigInteger_GetByteValue(ptest, ptest->IntegerLength); + + if (first_byte > 0x10) + x_first_byte = 0x7; + else + x_first_byte = 0x2; + + if (ptest->IntegerLength % 2 == 0) + x_first_byte <<= 4; + + x_buf[0] = x_first_byte; + BigInteger_Bin2BI(x_buf, x_len, &x); + BigInteger_is_one(x); + + /* S is input, use Xi+1 = 1/2 * (Xi + S/Xi), if Xn+1 == Xn, sqrt(S) ~= Xn */ + do { + PBIG_INTEGER div_res = NULL; + PBIG_INTEGER div_rem = NULL; + PBIG_INTEGER tmp = NULL; + i++; + /*DEBUGPRINT("x:"); + BigInteger_Print(x);*/ + BigInteger_Div(ptest, x, &div_res, &div_rem); + + /*DEBUGPRINT("div_res:"); + BigInteger_Print(div_res); + DEBUGPRINT("div_rem:"); + BigInteger_Print(div_rem);*/ + if (BigInteger_UnsignedCompare(x, div_res) == 0) { + if (BigInteger_is_zero(div_rem)) { + DEBUGPRINT("\x1b[33m%s: found!!!\x1b[m\n", __func__); + res = TRUE; + } else + res = FALSE; + + BigInteger_Free(&div_res); + BigInteger_Free(&div_rem); + break; + } + + if (BigInteger_UnsignedCompare(x, div_rem) != 1) { /* ellis: if BigInteger_Div work, remove it */ + res = FALSE; + BigInteger_Free(&div_res); + BigInteger_Free(&div_rem); + DEBUGPRINT("%s: div fail!!!\n", __func__); + break; + } + + BigInteger_Add(x, div_res, &tmp); + BigInteger_Shift_Right1(tmp, &div_res); + + if (BigInteger_UnsignedCompare(x, div_res) == 0) { + DEBUGPRINT("diff == 1\n"); + res = FALSE; + BigInteger_Free(&div_res); + BigInteger_Free(&div_rem); + BigInteger_Free(&tmp); + break; + } + + BigInteger_Copy(div_res, &x); + /*DEBUGPRINT("new x:"); + BigInteger_Print(x);*/ + BigInteger_Free(&div_res); + BigInteger_Free(&div_rem); + BigInteger_Free(&tmp); + } while (1); + + DEBUGPRINT("%s: total loop %d\n", __func__, i); + + if (res) { + if (*pBI_Result == NULL) + BigInteger_Init(pBI_Result); + + BigInteger_Copy(x, pBI_Result); + } else + BigInteger_Free(pBI_Result); + + os_free_mem(NULL, x_buf); +Free: + BigInteger_Free(&ptest); + BigInteger_Free(&x); + BigInteger_record_time_end(&bi_op_ti_rec.sqrt_op); + return res; +} + +VOID BigInteger_Shift_Right1( + IN PBIG_INTEGER pBI, + OUT PBIG_INTEGER *pBI_Result) +{ + BIG_INTEGER *res = NULL; + UINT32 len; + UINT32 shift_bit = 1; + INT16 i; + UINT32 shift_tmp; + BIG_INTEGER *ptest = NULL; + + POOL_COUNTER_CHECK_BEGIN(expected_cnt[10]); + GET_BI_INS_FROM_POOL(res); + GET_BI_INS_FROM_POOL(ptest); + + if (pBI == NULL) + BigInteger_Bin2BI(test, sizeof(test), &ptest); /* debug usage */ + else + BigInteger_Copy(pBI, &ptest); + + len = ptest->IntegerLength; + BigInteger_AllocSize(&res, len); + NdisCopyMemory(res->pIntegerArray, ptest->pIntegerArray, len); + res->Signed = ptest->Signed; + + /* i = res->ArrayLength - 1 */ + shift_tmp = res->pIntegerArray[res->ArrayLength - 1] & ((1 << shift_bit) - 1); + res->pIntegerArray[res->ArrayLength - 1] >>= shift_bit; + + for (i = res->ArrayLength - 2; i >= 0; i--) { + UINT32 shift_tmp2 = res->pIntegerArray[i] & ((1 << shift_bit) - 1); + res->pIntegerArray[i] = (shift_tmp << (32 - shift_bit)) + | (res->pIntegerArray[i] >> shift_bit); + shift_tmp = shift_tmp2; + } + + BigInteger_ClearHighBits(res); + BigInteger_Copy(res, pBI_Result); + release_temporal_usage_big_interger(&ptest); + release_temporal_usage_big_interger(&res); + POOL_COUNTER_CHECK_END(expected_cnt[10]); +} + +VOID BigInteger_Mod_Shift_Left( + IN PBIG_INTEGER pBI, + IN UCHAR bit, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER *pBI_Result) +{ + BIG_INTEGER *res = NULL; + BIG_INTEGER *tmp = NULL; + UCHAR two[] = {0x1}; + + two[0] <<= bit; + + GET_BI_INS_FROM_POOL(res); + GET_BI_INS_FROM_POOL(tmp); + + BigInteger_Bin2BI(two, sizeof(two), &tmp); + BigInteger_Mod_Mul(pBI, tmp, pBI_P, &res); + + BigInteger_Copy(res, pBI_Result); + release_temporal_usage_big_interger(&tmp); + release_temporal_usage_big_interger(&res); +} + +/* do not use this api(unknown bug) */ +VOID BigInteger_Shift_Left( + IN PBIG_INTEGER pBI, + IN UINT32 bit, + OUT PBIG_INTEGER *pBI_Result) +{ + BIG_INTEGER *res = NULL; + UINT32 len; + UINT32 shift_bit = bit % 32; + UINT32 shift_dword = bit / 32; + UINT32 shift_byte = (shift_bit + 7) / 8; + INT16 i; + UINT32 shift_tmp = 0; + BIG_INTEGER *ptest = NULL; + + if (bit == 0) { + BigInteger_Copy(pBI, pBI_Result); + return; + } + + POOL_COUNTER_CHECK_BEGIN(expected_cnt[11]); + GET_BI_INS_FROM_POOL(res); + GET_BI_INS_FROM_POOL(ptest); + + if (pBI == NULL) + BigInteger_Bin2BI(test, sizeof(test), &ptest); /* debug usage */ + else + BigInteger_Copy(pBI, &ptest); + + len = ptest->IntegerLength + shift_dword * 4; + + if (shift_bit) + len += shift_byte; + + BigInteger_AllocSize(&res, len); + res->Signed = ptest->Signed; + + if (shift_bit) { + /* i = 0 */ + shift_tmp = ptest->pIntegerArray[0] >> (32 - shift_bit); + res->pIntegerArray[shift_dword] = ptest->pIntegerArray[0] << shift_bit; + + for (i = 1; i < ptest->ArrayLength; i++) { + UINT32 shift_tmp2 = ptest->pIntegerArray[i] >> (32 - shift_bit); + res->pIntegerArray[i + shift_dword] = shift_tmp | (ptest->pIntegerArray[i] << shift_bit); + shift_tmp = shift_tmp2; + } + + if (shift_bit) + res->pIntegerArray[ptest->ArrayLength + shift_dword] = shift_tmp; + } + + BigInteger_Copy(res, pBI_Result); + release_temporal_usage_big_interger(&ptest); + release_temporal_usage_big_interger(&res); + POOL_COUNTER_CHECK_END(expected_cnt[11]); +} + +/* treat pBi is positve and non-zero */ +VOID BigInteger_minus_one( + INOUT PBIG_INTEGER pBI) +{ + INT16 i; + + if (pBI == NULL) + return; + + for (i = 0; i < pBI->ArrayLength; i++) { + if (pBI->pIntegerArray[i]) { + pBI->pIntegerArray[i]--; + return; + } else + pBI->pIntegerArray[i] = ~0; + } +} + +/* treat pBi is positve and non-zero */ +VOID BigInteger_plus_one( + INOUT PBIG_INTEGER pBI) +{ + INT16 i; + + if (pBI == NULL) + return; + + for (i = 0; i < pBI->ArrayLength; i++) { + if (pBI->pIntegerArray[i] != ~0) { + pBI->pIntegerArray[i]++; + return; + } else + pBI->pIntegerArray[i] = 0; + } + + /* todo: length update */ + panic("BigInteger_plus_one: todo: length update"); +} + + +/* an integer q is called a quadratic residue modulo n if it is congruent to a perfect square modulo n */ +UCHAR BigInteger_is_quadratic_residue( + IN BIG_INTEGER *q, + IN BIG_INTEGER *prime, + IN MONT_STRUC * mont) +{ + BIG_INTEGER *p = NULL; + BIG_INTEGER *res = NULL; + UCHAR ret; + POOL_COUNTER_CHECK_BEGIN(expected_cnt[12]); + GET_BI_INS_FROM_POOL(p); + GET_BI_INS_FROM_POOL(res); + BigInteger_Init(&res); + BigInteger_Copy(prime, &p); + BigInteger_minus_one(p); + BigInteger_Shift_Right1(p, &p); + BigInteger_Montgomery_ExpMod_with_mont(q, p, prime, mont, &res); + ret = BigInteger_is_one(res); + release_temporal_usage_big_interger(&p); + release_temporal_usage_big_interger(&res); + POOL_COUNTER_CHECK_END(expected_cnt[12]); + /* if (ret == TRUE) DEBUGPRINT("\x1b[33mgot it\x1b[m\n"); */ + return ret; +} + +VOID BigInteger_Montgomery_ExpMod32( + IN PBIG_INTEGER pBI_G, + IN PBIG_INTEGER pBI_E, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER *pBI_Result) +{ + BIG_INTEGER *g = NULL; + BIG_INTEGER *e = NULL; + BIG_INTEGER *res = NULL; + UINT i = 0; + UINT j = 0; + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("==> %s()\n", __func__)); + BigInteger_record_time_begin(&bi_op_ti_rec.simple_exp_mod_op); + BigInteger_Copy(pBI_G, &g); + BigInteger_Copy(pBI_E, &e); + BigInteger_Bin2BI(Value_1, 1, &res); + + while (BigInteger_is_zero(e) == FALSE) { + if (BigInteger_is_odd(e)) { + BigInteger_Mod_Mul(res, g, pBI_P, &res); + BigInteger_minus_one(e); + } else { + BigInteger_Mod_Mul(g, g, pBI_P, &g); + BigInteger_Shift_Right1(e, &e); + j++; + } + + i++; + } + + BigInteger_Copy(res, pBI_Result); + BigInteger_Free(&g); + BigInteger_Free(&e); + BigInteger_Free(&res); + BigInteger_record_time_end(&bi_op_ti_rec.simple_exp_mod_op); +} + +VOID BigInteger_DWtoBI( + IN UINT32 value, + OUT PBIG_INTEGER *pBI) +{ + BigInteger_AllocSize(pBI, 4); + (*pBI)->pIntegerArray[0] = value; + BigInteger_ClearHighBits(*pBI); +} + +VOID BigInteger_Add_DW( + INOUT PBIG_INTEGER pBI, + IN UINT32 value) +{ + UINT32 copy = pBI->pIntegerArray[0]; + UINT8 i; + pBI->pIntegerArray[0] += value; + + if (pBI->pIntegerArray[0] < copy) { + for (i = 1; i < pBI->ArrayLength; i++) { + if (pBI->pIntegerArray[i] != ~0) { + pBI->pIntegerArray[i]++; + BigInteger_ClearHighBits(pBI); + return; + } else + pBI->pIntegerArray[i] = 0; + } + } + + /* todo: length update */ + panic("BigInteger_Add_DW: todo: length update"); +} + + +VOID BigInteger_Mod_DW( + INOUT PBIG_INTEGER pBI, + IN UINT32 value, + OUT UINT32 *rem) +{ + *rem = pBI->pIntegerArray[0] % value; + pBI->pIntegerArray[0] -= *rem; +} + + + +VOID BigInteger_DtoH( + INOUT PBIG_INTEGER pBI) +{ + BIG_INTEGER *res = NULL; + BIG_INTEGER *tmp = NULL; + BIG_INTEGER *tmp2 = NULL; + BIG_INTEGER *tmp3 = NULL; + BIG_INTEGER *hundred = NULL; + UINT i; + UINT8 byte_value; + BigInteger_DWtoBI(100, &hundred); + BigInteger_DWtoBI((UINT32)1, &tmp2); + BigInteger_DWtoBI((UINT32)0, &res); + + for (i = 1; i <= pBI->IntegerLength; i++) { + byte_value = BigInteger_GetByteValue(pBI, i); + BigInteger_DWtoBI((UINT32)byte_value, &tmp); + BigInteger_Mul(tmp, tmp2, &tmp3); + BigInteger_Copy(tmp3, &tmp); + BigInteger_Add(res, tmp, &tmp3); + BigInteger_Copy(tmp3, &res); + BigInteger_Mul(tmp2, hundred, &tmp); + BigInteger_Copy(tmp, &tmp2); + } + + BigInteger_Copy(res, &pBI); + BigInteger_Free(&res); + BigInteger_Free(&tmp); + BigInteger_Free(&tmp2); + BigInteger_Free(&tmp3); + BigInteger_Free(&hundred); +} + +VOID BigInteger_dump_time( + VOID) +{ + if (DebugLevel < DBG_LVL_TRACE) + return; + + DEBUGPRINT("BigInteger time record: (allocated cnt = %lu)\n", alloc_cnt); + DEBUGPRINT("add allocated cnt = %lu\n", alloc_cnt_add); + DEBUGPRINT("sub allocated cnt = %lu\n", alloc_cnt_sub); + DEBUGPRINT("mul allocated cnt = %lu\n", alloc_cnt_mul); + DEBUGPRINT("div allocated cnt = %lu\n", alloc_cnt_div); + DEBUGPRINT("mod allocated cnt = %lu\n", alloc_cnt_mod); + + if (bi_op_ti_rec.add_op.exe_times) { + DEBUGPRINT("add_op time record:\n"); + DEBUGPRINT("\tavg_time=%lu.%03lu nsec", (bi_op_ti_rec.add_op.time_interval / bi_op_ti_rec.add_op.exe_times), + show_float(bi_op_ti_rec.add_op.time_interval, bi_op_ti_rec.add_op.exe_times, 3)); + DEBUGPRINT(", %lu nsec", bi_op_ti_rec.add_op.time_interval); + DEBUGPRINT("\n\texe_times=%u\n", bi_op_ti_rec.add_op.exe_times); + bi_op_ti_rec.add_op.time_interval = 0; + bi_op_ti_rec.add_op.exe_times = 0; + bi_op_ti_rec.add_op.avg_time_interval = 0; + } + + if (bi_op_ti_rec.sub_op.exe_times) { + DEBUGPRINT("sub_op time record:\n"); + DEBUGPRINT("\tavg_time=%lu.%03lu nsec", (bi_op_ti_rec.sub_op.time_interval / bi_op_ti_rec.sub_op.exe_times), + show_float(bi_op_ti_rec.sub_op.time_interval, bi_op_ti_rec.sub_op.exe_times, 3)); + DEBUGPRINT(", %lu nsec", bi_op_ti_rec.sub_op.time_interval); + DEBUGPRINT(", add:sub = 1:%lu.%02lu", (bi_op_ti_rec.sub_op.time_interval / bi_op_ti_rec.add_op.time_interval), + show_float(bi_op_ti_rec.sub_op.time_interval, bi_op_ti_rec.add_op.time_interval, 2)); + DEBUGPRINT("\n\texe_times=%u\n", bi_op_ti_rec.sub_op.exe_times); + bi_op_ti_rec.sub_op.time_interval = 0; + bi_op_ti_rec.sub_op.exe_times = 0; + bi_op_ti_rec.sub_op.avg_time_interval = 0; + } + + if (bi_op_ti_rec.mul_op.exe_times) { + DEBUGPRINT("mul_op time record:\n"); + DEBUGPRINT("\tavg_time=%lu.%03lu nsec", (bi_op_ti_rec.mul_op.time_interval / bi_op_ti_rec.mul_op.exe_times), + show_float(bi_op_ti_rec.mul_op.time_interval, bi_op_ti_rec.mul_op.exe_times, 3)); + DEBUGPRINT(", %lu nsec", bi_op_ti_rec.mul_op.time_interval); + DEBUGPRINT(", add:mul = 1:%lu.%02lu", (bi_op_ti_rec.mul_op.time_interval / bi_op_ti_rec.add_op.time_interval), + show_float(bi_op_ti_rec.mul_op.time_interval, bi_op_ti_rec.add_op.time_interval, 2)); + DEBUGPRINT("\n\texe_times=%u\n", bi_op_ti_rec.mul_op.exe_times); + bi_op_ti_rec.mul_op.time_interval = 0; + bi_op_ti_rec.mul_op.exe_times = 0; + bi_op_ti_rec.mul_op.avg_time_interval = 0; + } + + if (bi_op_ti_rec.div_op.exe_times) { + DEBUGPRINT("div_op time record:\n"); + DEBUGPRINT("\tavg_time=%lu.%03lu nsec", (bi_op_ti_rec.div_op.time_interval / bi_op_ti_rec.div_op.exe_times), + show_float(bi_op_ti_rec.div_op.time_interval, bi_op_ti_rec.div_op.exe_times, 3)); + DEBUGPRINT(", %lu nsec", bi_op_ti_rec.div_op.time_interval); + DEBUGPRINT(", add:div = 1:%lu.%02lu", (bi_op_ti_rec.div_op.time_interval / bi_op_ti_rec.add_op.time_interval), + show_float(bi_op_ti_rec.div_op.time_interval, bi_op_ti_rec.add_op.time_interval, 2)); + DEBUGPRINT("\n\texe_times=%u\n", bi_op_ti_rec.div_op.exe_times); + bi_op_ti_rec.div_op.avg_time_interval = 0; + bi_op_ti_rec.div_op.time_interval = 0; + bi_op_ti_rec.div_op.exe_times = 0; + } + + if (bi_op_ti_rec.mod_op.exe_times) { + DEBUGPRINT("mod_op time record:\n"); + DEBUGPRINT("\tavg_time=%lu.%03lu nsec", (bi_op_ti_rec.mod_op.time_interval / bi_op_ti_rec.mod_op.exe_times), + show_float(bi_op_ti_rec.mod_op.time_interval, bi_op_ti_rec.mod_op.exe_times, 3)); + DEBUGPRINT(", %lu nsec", bi_op_ti_rec.mod_op.time_interval); + if (bi_op_ti_rec.add_op.time_interval) + DEBUGPRINT(", add:mod = 1:%lu.%02lu", (bi_op_ti_rec.mod_op.time_interval / bi_op_ti_rec.add_op.time_interval), + show_float(bi_op_ti_rec.mod_op.time_interval, bi_op_ti_rec.add_op.time_interval, 2)); + DEBUGPRINT("\n\texe_times=%u\n", bi_op_ti_rec.mod_op.exe_times); + bi_op_ti_rec.mod_op.avg_time_interval = 0; + bi_op_ti_rec.mod_op.time_interval = 0; + bi_op_ti_rec.mod_op.exe_times = 0; + } + + if (bi_op_ti_rec.square_op.exe_times) { + DEBUGPRINT("square_op time record:\n"); + DEBUGPRINT("\tavg_time=%lu.%03lu nsec", (bi_op_ti_rec.square_op.time_interval / bi_op_ti_rec.square_op.exe_times), + show_float(bi_op_ti_rec.square_op.time_interval, bi_op_ti_rec.square_op.exe_times, 3)); + DEBUGPRINT(", %lu nsec", bi_op_ti_rec.square_op.time_interval); + DEBUGPRINT("\n\texe_times=%u\n", bi_op_ti_rec.square_op.exe_times); + bi_op_ti_rec.square_op.avg_time_interval = 0; + bi_op_ti_rec.square_op.time_interval = 0; + bi_op_ti_rec.square_op.exe_times = 0; + } + + alloc_cnt = 0; + alloc_cnt_add = 0; + alloc_cnt_sub = 0; + alloc_cnt_mul = 0; + alloc_cnt_div = 0; + alloc_cnt_mod = 0; + + if (bi_op_ti_rec.sqrt_op.exe_times) { + DEBUGPRINT("sqrt_op time record:\n"); + DEBUGPRINT("\tavg_time=%lu jiffies", bi_op_ti_rec.sqrt_op.avg_time_interval); +#ifdef LINUX + DEBUGPRINT(", %u msec", jiffies_to_msecs(bi_op_ti_rec.sqrt_op.avg_time_interval)); +#endif + DEBUGPRINT("\n\texe_times=%u\n", bi_op_ti_rec.sqrt_op.exe_times); + bi_op_ti_rec.sqrt_op.avg_time_interval = 0; + bi_op_ti_rec.sqrt_op.time_interval = 0; + bi_op_ti_rec.sqrt_op.exe_times = 0; + } + + if (bi_op_ti_rec.exp_mod_op.exe_times) { + DEBUGPRINT("exp_mod_op time record:\n"); + DEBUGPRINT("\tavg_time=%lu jiffies", bi_op_ti_rec.exp_mod_op.avg_time_interval); +#ifdef LINUX + DEBUGPRINT(", %u msec", jiffies_to_msecs(bi_op_ti_rec.exp_mod_op.avg_time_interval)); +#endif + DEBUGPRINT("\n\texe_times=%u\n", bi_op_ti_rec.exp_mod_op.exe_times); + bi_op_ti_rec.exp_mod_op.avg_time_interval = 0; + bi_op_ti_rec.exp_mod_op.time_interval = 0; + bi_op_ti_rec.exp_mod_op.exe_times = 0; + } + + if (bi_op_ti_rec.div_mod_op.exe_times) { + DEBUGPRINT("div_mod_op time record:\n"); + DEBUGPRINT("\tavg_time=%lu jiffies", bi_op_ti_rec.div_mod_op.avg_time_interval); +#ifdef LINUX + DEBUGPRINT(", %u msec", jiffies_to_msecs(bi_op_ti_rec.div_mod_op.avg_time_interval)); +#endif + DEBUGPRINT("\n\texe_times=%u\n", bi_op_ti_rec.div_mod_op.exe_times); + bi_op_ti_rec.div_mod_op.avg_time_interval = 0; + bi_op_ti_rec.div_mod_op.time_interval = 0; + bi_op_ti_rec.div_mod_op.exe_times = 0; + } + + if (bi_op_ti_rec.sqrt_mod_op.exe_times) { + DEBUGPRINT("sqrt_mod_op time record:\n"); + DEBUGPRINT("\tavg_time=%lu jiffies", bi_op_ti_rec.sqrt_mod_op.avg_time_interval); +#ifdef LINUX + DEBUGPRINT(", %u msec", jiffies_to_msecs(bi_op_ti_rec.sqrt_mod_op.avg_time_interval)); +#endif + DEBUGPRINT("\n\texe_times=%u\n", bi_op_ti_rec.sqrt_mod_op.exe_times); + bi_op_ti_rec.sqrt_mod_op.avg_time_interval = 0; + bi_op_ti_rec.sqrt_mod_op.time_interval = 0; + bi_op_ti_rec.sqrt_mod_op.exe_times = 0; + } + + if (bi_op_ti_rec.mod_mul_inv_op.exe_times) { + DEBUGPRINT("mod_mul_inv_op time record:\n"); + DEBUGPRINT("\tavg_time=%lu jiffies", bi_op_ti_rec.mod_mul_inv_op.avg_time_interval); +#ifdef LINUX + DEBUGPRINT(", %u msec", jiffies_to_msecs(bi_op_ti_rec.mod_mul_inv_op.avg_time_interval)); +#endif + DEBUGPRINT("\n\texe_times=%u\n", bi_op_ti_rec.mod_mul_inv_op.exe_times); + bi_op_ti_rec.mod_mul_inv_op.avg_time_interval = 0; + bi_op_ti_rec.mod_mul_inv_op.time_interval = 0; + bi_op_ti_rec.mod_mul_inv_op.exe_times = 0; + } + + if (bi_op_ti_rec.simple_exp_mod_op.exe_times) { + DEBUGPRINT("simple_exp_mod_op time record:\n"); + DEBUGPRINT("\tavg_time=%lu jiffies", bi_op_ti_rec.simple_exp_mod_op.avg_time_interval); +#ifdef LINUX + DEBUGPRINT(", %u msec", jiffies_to_msecs(bi_op_ti_rec.simple_exp_mod_op.avg_time_interval)); +#endif + DEBUGPRINT("\n\texe_times=%u\n", bi_op_ti_rec.simple_exp_mod_op.exe_times); + bi_op_ti_rec.simple_exp_mod_op.avg_time_interval = 0; + bi_op_ti_rec.simple_exp_mod_op.time_interval = 0; + bi_op_ti_rec.simple_exp_mod_op.exe_times = 0; + } +} +/* End of crypt_biginteger.c */ + +#else +#include "crypt_biginteger.h" + + +#ifdef __KERNEL__ +#define DEBUGPRINT(fmt, args...) printk(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"); + } + DEBUGPRINT("\n\n"); +} + + +VOID BigInteger_Init ( + INOUT PBIG_INTEGER *pBI) +{ + if (*pBI != NULL) + BigInteger_Free(pBI); + + os_alloc_mem(NULL, (UCHAR **)pBI, sizeof(BIG_INTEGER)); + if (*pBI == NULL) { + DEBUGPRINT("BigInteger_Init: allocate %d bytes memory failure.\n", (sizeof(BIG_INTEGER))); + return; + } + + NdisZeroMemory(*pBI, sizeof(BIG_INTEGER)); + (*pBI)->pIntegerArray = NULL; + (*pBI)->Signed = 1; +} + + +VOID BigInteger_Free_AllocSize ( + IN PBIG_INTEGER *pBI) +{ + if ((*pBI != NULL) && ((*pBI)->pIntegerArray != NULL)) { + os_free_mem(NULL, (*pBI)->pIntegerArray); + NdisZeroMemory(*pBI, sizeof(BIG_INTEGER)); + (*pBI)->pIntegerArray = NULL; + (*pBI)->Signed = 1; + } +} + + +VOID BigInteger_Free ( + IN PBIG_INTEGER *pBI) +{ + if (*pBI != NULL) { + BigInteger_Free_AllocSize(pBI); + os_free_mem(NULL, *pBI); + } + + *pBI = NULL; +} + + +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 == NULL) { + DEBUGPRINT("BigInteger_AllocSize: allocate %d bytes memory failure.\n", (sizeof(UINT32)*ArrayLength)); + return; + } + (*pBI)->AllocSize = sizeof(UINT32)*ArrayLength; + } + + NdisZeroMemory((*pBI)->pIntegerArray, (*pBI)->AllocSize); + (*pBI)->ArrayLength = ArrayLength; + (*pBI)->IntegerLength = Length; +} + + +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; + + if (SecondHighByte == 0) + break; + + 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; + } + + 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) + 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 */ + + +#endif /* defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_bignum.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_bignum.c new file mode 100644 index 000000000..f9309de12 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_bignum.c @@ -0,0 +1,551 @@ + +/* ==================================================================== + * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgment: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/**************************************************************************** +* Mediatek Inc. +* 5F., No.5, Taiyuan 1st St., Zhubei City, +* Hsinchu County 302, Taiwan, R.O.C. +* (c) Copyright 2014, Mediatek, Inc. +* +* All rights reserved. Mediatek's source code 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: + crypt_bignum.c + + Abstract: + BN wrepper for reference OPENSSL funcitons + + Revision History: + Who When What + -------- ---------- --------------------------------------------- + Ellis 2018.3.1 Initial version +*/ +#ifdef DOT11_SAE_OPENSSL_BN +#include "crypt_bignum.h" +#include "rt_config.h" +#include + + + +#ifdef __KERNEL__ +#define DEBUGPRINT(fmt, args...) printk(fmt, ## args) +#else +#define DEBUGPRINT(fmt, args...) printf(fmt, ## args) +#endif /* __KERNEL__ */ + +VOID Bignum_Print ( + IN BIGNUM *pBI) +{ + UINT32 i, j = 0; + + DEBUGPRINT("dmax = %d, top = %d\n", pBI->dmax, pBI->top); + + for (i = pBI->dmax - 1; j < pBI->dmax; i--, j++) { + if (j/4 > 0 && j % 4 == 0) + DEBUGPRINT("\n"); + DEBUGPRINT("%02x %02x %02x %02x ", (pBI->d[i] & 0xff000000) >> 24, + (pBI->d[i] & 0xff0000) >> 16, (pBI->d[i] & 0xff00) >> 8, (pBI->d[i] & 0xff)) ; + } + + DEBUGPRINT("\n"); + return; +} + + + +VOID Bignum_Init( + INOUT BIGNUM **pBI) +{ + if (*pBI == NULL) { + *pBI = BN_new(); + } +} + +VOID Bignum_Free( + IN BIGNUM **pBI) +{ + if (*pBI != NULL) + BN_free(*pBI); + *pBI = NULL; +} + +UINT32 Bignum_getlen( + IN BIGNUM *pBI) +{ + return pBI->top * 4; +} + +INT Bignum_Get_rand_range(IN BIGNUM * range, INOUT BIGNUM * r) +{ + return BN_rand_range(r, (const BIGNUM *)range); +} + +VOID Bignum_BI2Bin( + IN BIGNUM *pBI, + OUT UINT8 *pValue, + OUT UINT *Length) +{ + *Length = BN_num_bytes(pBI); + BN_bn2bin(pBI, pValue); +} /* End of Bignum_BI2Bin */ + + +VOID Bignum_BI2Bin_with_pad( + IN BIGNUM *pBI, + OUT UINT8 *pValue, + IN UINT *Length, + IN UINT32 PadLen) +{ + UINT32 num_bytes, offset; + + num_bytes = BN_num_bytes((const BIGNUM *) pBI); + + if (PadLen > num_bytes) + offset = PadLen - num_bytes; + else + offset = 0; + + NdisZeroMemory(pValue, offset); + Bignum_BI2Bin(pBI, pValue + offset, Length); + *Length += offset; +} + + +VOID Bignum_Bin2BI( + IN UINT8 *pValue, + IN UINT Length, + OUT BIGNUM **pBI) +{ + if (*pBI) + BN_free(*pBI); + *pBI = BN_bin2bn(pValue, Length, NULL); +} /* End of Bignum_Bin2BI */ + + +VOID Bignum_Copy( + IN BIGNUM *pBI_Copied, + OUT BIGNUM **pBI_Result) +{ + if (*pBI_Result) + BN_free(*pBI_Result); + *pBI_Result = BN_dup(pBI_Copied); +} /* End of Bignum_Copy */ + + +INT Bignum_UnsignedCompare( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand) +{ + return BN_ucmp(pFirstOperand, pSecondOperand); +} /* End of Bignum_Compare */ + + +VOID Bignum_Add( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand, + OUT BIGNUM **pBI_Result) +{ + if (*pBI_Result == NULL) + *pBI_Result = BN_new(); + BN_add(*pBI_Result, pFirstOperand, pSecondOperand); +} /* End of Bignum_Add */ + + +VOID Bignum_Sub( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand, + OUT BIGNUM **pBI_Result) +{ + if (*pBI_Result == NULL) + *pBI_Result = BN_new(); + BN_sub(*pBI_Result, pFirstOperand, pSecondOperand); +} /* End of Bignum_Sub */ + +VOID Bignum_Mod( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand, + OUT BIGNUM **pBI_Remainder) +{ + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + if (*pBI_Remainder == NULL) + *pBI_Remainder = BN_new(); + + BN_mod(*pBI_Remainder, pFirstOperand, pSecondOperand, bnctx); + + BN_CTX_free(bnctx); +} + +VOID Bignum_Mod_Mul( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result) +{ + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + if (*pBI_Result == NULL) + *pBI_Result = BN_new(); + + BN_mod_mul(*pBI_Result, pFirstOperand, pSecondOperand, pBI_P, bnctx); + + BN_CTX_free(bnctx); +} + + +UCHAR Bignum_is_zero( + IN BIGNUM *pBI) +{ + return (UCHAR)BN_is_zero(pBI); +} + +UCHAR Bignum_is_one( + IN BIGNUM *pBI) +{ + return (UCHAR)BN_is_one(pBI); +} + +UCHAR Bignum_is_odd( + IN BIGNUM *pBI) +{ + return (UCHAR)BN_is_odd(pBI); +} + + +VOID Bignum_Mod_Square( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result) +{ + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + if (*pBI_Result == NULL) + *pBI_Result = BN_new(); + + BN_mod_sqr(*pBI_Result, pFirstOperand, pBI_P, bnctx); + BN_CTX_free(bnctx); +} + +VOID Bignum_Mod_Add( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result) +{ + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + if (*pBI_Result == NULL) + *pBI_Result = BN_new(); + + BN_mod_add(*pBI_Result, pFirstOperand, pSecondOperand, pBI_P, bnctx); + BN_CTX_free(bnctx); +} + + +VOID Bignum_Mod_Sub( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result) +{ + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + if (*pBI_Result == NULL) + *pBI_Result = BN_new(); + + BN_mod_sub(*pBI_Result, pFirstOperand, pSecondOperand, pBI_P, bnctx); + BN_CTX_free(bnctx); +} + +VOID Bignum_Mod_Add_quick( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result) +{ + if (*pBI_Result == NULL) + *pBI_Result = BN_new(); + + BN_mod_add_quick(*pBI_Result, pFirstOperand, pSecondOperand, pBI_P); +} + + +VOID Bignum_Mod_Sub_quick( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result) +{ + if (*pBI_Result == NULL) + *pBI_Result = BN_new(); + + BN_mod_sub_quick(*pBI_Result, pFirstOperand, pSecondOperand, pBI_P); +} + + +VOID Bignum_Mod_Div( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result) +{ + BIGNUM *tmp = NULL; + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + + tmp = BN_CTX_get(bnctx); + + BN_mod_inverse(tmp, pSecondOperand, pBI_P, bnctx); + + Bignum_Mod_Mul(pFirstOperand, tmp, pBI_P, pBI_Result); + + BN_CTX_free(bnctx); +} + + + +/* Tonelli¡VShanks algorithm*/ +/* reference: https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm */ +/* pBI_P must be prime */ +VOID Bignum_Mod_Sqrt( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result) +{ + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + if (*pBI_Result == NULL) + *pBI_Result = BN_new(); + + BN_mod_sqrt(*pBI_Result, pFirstOperand, pBI_P, bnctx); + BN_CTX_free(bnctx); +} + +VOID Bignum_Shift_Right1( + IN BIGNUM *pBI, + OUT BIGNUM **pBI_Result) +{ + BN_copy(*pBI_Result, pBI); + BN_div_word(*pBI_Result, 2); +} + +VOID Bignum_Mod_Shift_Left1( + IN BIGNUM *pBI, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result) +{ + BN_mod_lshift1_quick(*pBI_Result, pBI, pBI_P); +} + +VOID Bignum_Mod_Shift_Left( + IN BIGNUM *pBI, + IN UCHAR bit, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result) +{ + BN_mod_lshift_quick(*pBI_Result, pBI, bit, pBI_P); +} + + +/* an integer q is called a quadratic residue modulo n if it is congruent to a perfect square modulo n */ +UCHAR Bignum_is_quadratic_residue( + IN BIGNUM *q, + IN BIGNUM *prime) +{ + BIGNUM *p = NULL; + BIGNUM *res = NULL; + UCHAR ret; + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + res = BN_CTX_get(bnctx); + + Bignum_Copy(prime, &p); + BN_sub_word(p, 1); + Bignum_Shift_Right1(p, &p); + BN_mod_exp_mont(res, q, p, prime, bnctx, NULL); + ret = Bignum_is_one(res); + + BN_CTX_free(bnctx); + BN_free(p); + return ret; +} + +VOID Bignum_Add_DW( + INOUT BIGNUM *pBI, + IN UINT32 value) +{ + return; +} + +VOID Bignum_Mod_DW( + INOUT BIGNUM *pBI, + IN UINT32 value, + OUT UINT32 *rem) +{ + *rem = pBI->d[0] & (value - 1); + pBI->d[0] &= ~(value - 1); +} + +VOID Bignum_Montgomery_ExpMod( + IN BIGNUM *pBI_G, + IN BIGNUM *pBI_E, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result) +{ + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + + if (*pBI_Result == NULL) + *pBI_Result = BN_new(); + + BN_mod_exp_mont(*pBI_Result, pBI_G, pBI_E, pBI_P, bnctx, NULL); + + BN_CTX_free(bnctx); +} + +VOID Bignum_Mod_Mul_Inverse( + IN BIGNUM *pBI, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result) +{ + BN_CTX *bnctx; + + bnctx = BN_CTX_new(); + + if (*pBI_Result == NULL) + *pBI_Result = BN_new(); + + BN_mod_inverse(*pBI_Result, pBI, pBI_P, bnctx); + + BN_CTX_free(bnctx); +} + + + +/* End of crypt_Bignum.c */ + +#endif /* DOT11_SAE_OPENSSL_BN */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_dh.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_dh.c new file mode 100644 index 000000000..0939143fe --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_dh.c @@ -0,0 +1,227 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + Module Name: + DH + + Abstract: + RFC 2631: Diffie-Hellman Key Agreement Method + + Revision History: + Who When What + -------- ---------- ------------------------------------------ + Eddy 2009/01/21 Create Diffie-Hellman +***************************************************************************/ + + +#include "crypt_dh.h" +#include "crypt_biginteger.h" + + +/* +======================================================================== +Routine Description: + Diffie-Hellman public key generation + +Arguments: + GValue Array in UINT8 + GValueLength The length of G in bytes + PValue Array in UINT8 + PValueLength The length of P in bytes + PrivateKey Private key + PrivateKeyLength The length of Private key in bytes + +Return Value: + PublicKey Public key + PublicKeyLength The length of public key in bytes + +Note: + Reference to RFC2631 + PublicKey = G^PrivateKey (mod P) +======================================================================== +*/ +void DH_PublicKey_Generate ( + IN UINT8 GValue[], + IN UINT GValueLength, + IN UINT8 PValue[], + IN UINT PValueLength, + IN UINT8 PrivateKey[], + IN UINT PrivateKeyLength, + OUT UINT8 PublicKey[], + INOUT UINT *PublicKeyLength) +{ + PBIG_INTEGER pBI_G = NULL; + PBIG_INTEGER pBI_P = NULL; + PBIG_INTEGER pBI_PrivateKey = NULL; + PBIG_INTEGER pBI_PublicKey = NULL; + + /* + * 1. Check the input parameters + * - GValueLength, PValueLength and PrivateLength must be large than zero + * - PublicKeyLength must be large or equal than PValueLength + * - PValue must be odd + * + * - PValue must be prime number (no implement) + * - GValue must be greater than 0 but less than the PValue (no implement) + */ + if (GValueLength == 0) { + DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: G length is (%d)\n", GValueLength)); + return; + } /* End of if */ + if (PValueLength == 0) { + DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: P length is (%d)\n", PValueLength)); + return; + } /* End of if */ + if (PrivateKeyLength == 0) { + DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: private key length is (%d)\n", PrivateKeyLength)); + return; + } /* End of if */ + if (*PublicKeyLength < PValueLength) { + DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: public key length(%d) must be large or equal than P length(%d)\n", + *PublicKeyLength, PValueLength)); + return; + } /* End of if */ + if (!(PValue[PValueLength - 1] & 0x1)) { + DBGPRINT(RT_DEBUG_ERROR, ("DH_PublicKey_Generate: P value must be odd\n")); + return; + } /* End of if */ + + /* + * 2. Transfer parameters to BigInteger structure + */ + BigInteger_Init(&pBI_G); + BigInteger_Init(&pBI_P); + BigInteger_Init(&pBI_PrivateKey); + BigInteger_Init(&pBI_PublicKey); + BigInteger_Bin2BI(GValue, GValueLength, &pBI_G); + BigInteger_Bin2BI(PValue, PValueLength, &pBI_P); + BigInteger_Bin2BI(PrivateKey, PrivateKeyLength, &pBI_PrivateKey); + + /* + * 3. Calculate PublicKey = G^PrivateKey (mod P) + * - BigInteger Operation + * - Montgomery reduction + */ + BigInteger_Montgomery_ExpMod(pBI_G, pBI_PrivateKey, pBI_P, &pBI_PublicKey); + + /* + * 4. Transfer BigInteger structure to char array + */ + BigInteger_BI2Bin(pBI_PublicKey, PublicKey, PublicKeyLength); + + BigInteger_Free(&pBI_G); + BigInteger_Free(&pBI_P); + BigInteger_Free(&pBI_PrivateKey); + BigInteger_Free(&pBI_PublicKey); +} /* End of DH_PublicKey_Generate */ + + +/* +======================================================================== +Routine Description: + Diffie-Hellman secret key generation + +Arguments: + PublicKey Public key + PublicKeyLength The length of Public key in bytes + PValue Array in UINT8 + PValueLength The length of P in bytes + PrivateKey Private key + PrivateKeyLength The length of Private key in bytes + +Return Value: + SecretKey Secret key + SecretKeyLength The length of secret key in bytes + +Note: + Reference to RFC2631 + SecretKey = PublicKey^PrivateKey (mod P) +======================================================================== +*/ +void DH_SecretKey_Generate ( + IN UINT8 PublicKey[], + IN UINT PublicKeyLength, + IN UINT8 PValue[], + IN UINT PValueLength, + IN UINT8 PrivateKey[], + IN UINT PrivateKeyLength, + OUT UINT8 SecretKey[], + INOUT UINT *SecretKeyLength) +{ + PBIG_INTEGER pBI_P = NULL; + PBIG_INTEGER pBI_SecretKey = NULL; + PBIG_INTEGER pBI_PrivateKey = NULL; + PBIG_INTEGER pBI_PublicKey = NULL; + + /* + * 1. Check the input parameters + * - PublicKeyLength, PValueLength and PrivateLength must be large than zero + * - SecretKeyLength must be large or equal than PValueLength + * - PValue must be odd + * + * - PValue must be prime number (no implement) + */ + if (PublicKeyLength == 0) { + DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: public key length is (%d)\n", PublicKeyLength)); + return; + } /* End of if */ + if (PValueLength == 0) { + DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: P length is (%d)\n", PValueLength)); + return; + } /* End of if */ + if (PrivateKeyLength == 0) { + DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: private key length is (%d)\n", PrivateKeyLength)); + return; + } /* End of if */ + if (*SecretKeyLength < PValueLength) { + DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: secret key length(%d) must be large or equal than P length(%d)\n", + *SecretKeyLength, PValueLength)); + return; + } /* End of if */ + if (!(PValue[PValueLength - 1] & 0x1)) { + DBGPRINT(RT_DEBUG_ERROR, ("DH_SecretKey_Generate: P value must be odd\n")); + return; + } /* End of if */ + + /* + * 2. Transfer parameters to BigInteger structure + */ + BigInteger_Init(&pBI_P); + BigInteger_Init(&pBI_PrivateKey); + BigInteger_Init(&pBI_PublicKey); + BigInteger_Init(&pBI_SecretKey); + + BigInteger_Bin2BI(PublicKey, PublicKeyLength, &pBI_PublicKey); + BigInteger_Bin2BI(PValue, PValueLength, &pBI_P); + BigInteger_Bin2BI(PrivateKey, PrivateKeyLength, &pBI_PrivateKey); + + /* + * 3. Calculate SecretKey = PublicKey^PrivateKey (mod P) + * - BigInteger Operation + * - Montgomery reduction + */ + BigInteger_Montgomery_ExpMod(pBI_PublicKey, pBI_PrivateKey, pBI_P, &pBI_SecretKey); + + /* + * 4. Transfer BigInteger structure to char array + */ + BigInteger_BI2Bin(pBI_SecretKey, SecretKey, SecretKeyLength); + + BigInteger_Free(&pBI_P); + BigInteger_Free(&pBI_PrivateKey); + BigInteger_Free(&pBI_PublicKey); + BigInteger_Free(&pBI_SecretKey); +} /* End of DH_SecretKey_Generate */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_hmac.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_hmac.c new file mode 100644 index 000000000..3f0ddc34d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_hmac.c @@ -0,0 +1,505 @@ +/**************************************************************************** + * 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 */ +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +VOID RT_HMAC_SHA256_VECTOR( + const UINT8 key[], + IN UINT key_len, + IN UCHAR element_num, + IN const UINT8 *message[], + IN UINT *message_len, + OUT UINT8 mac[], + IN UINT mac_len) +{ + SHA256_CTX_STRUC sha_ctx1; + SHA256_CTX_STRUC sha_ctx2; + UINT8 K0[SHA256_BLOCK_SIZE]; + UINT8 Digest[SHA256_DIGEST_SIZE]; + UINT index; + const UCHAR *_addr[6]; + INT _len[6], i; + + 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 (key_len <= SHA256_BLOCK_SIZE) + NdisMoveMemory(K0, key, key_len); + else + RT_SHA256(key, key_len, 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) */ + + _addr[0] = K0; + _len[0] = sizeof(K0); + + for (i = 0; i < element_num; i++) { + _addr[i + 1] = message[i]; + _len[i + 1] = message_len[i]; + } + + rt_sha256_vector(element_num + 1, _addr, _len, 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 (mac_len > SHA256_DIGEST_SIZE) + NdisMoveMemory(mac, Digest, SHA256_DIGEST_SIZE); + else + NdisMoveMemory(mac, Digest, mac_len); +} +#endif /* defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) */ +#endif /* HMAC_SHA256_SUPPORT */ + +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +#ifdef SHA384_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_SHA384( + IN const UINT8 Key[], + IN UINT KeyLen, + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 MAC[], + IN UINT MACLen) +{ + SHA384_CTX_STRUC sha_ctx1; + SHA384_CTX_STRUC sha_ctx2; + UINT8 K0[SHA384_BLOCK_SIZE]; + UINT8 Digest[SHA384_DIGEST_SIZE]; + UINT index; + + NdisZeroMemory(&sha_ctx1, sizeof(SHA384_CTX_STRUC)); + NdisZeroMemory(&sha_ctx2, sizeof(SHA384_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, SHA384_BLOCK_SIZE); + + if (KeyLen <= SHA384_BLOCK_SIZE) + NdisMoveMemory(K0, Key, KeyLen); + else + RT_SHA384(Key, KeyLen, K0); + + /* Exclusive-Or K0 with ipad */ + /* ipad: Inner pad; the byte x 36 repeated B times. */ + for (index = 0; index < SHA384_BLOCK_SIZE; index++) + K0[index] ^= 0x36; + + /* End of for */ + RT_SHA384_Init(&sha_ctx1); + /* H(K0^ipad) */ + RT_SHA384_Append(&sha_ctx1, K0, sizeof(K0)); + /* H((K0^ipad)||text) */ + RT_SHA384_Append(&sha_ctx1, Message, MessageLen); + RT_SHA384_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 < SHA384_BLOCK_SIZE; index++) + K0[index] ^= 0x36^0x5c; + + /* End of for */ + RT_SHA384_Init(&sha_ctx2); + /* H(K0^opad) */ + RT_SHA384_Append(&sha_ctx2, K0, sizeof(K0)); + /* H( (K0^opad) || H((K0^ipad)||text) ) */ + RT_SHA384_Append(&sha_ctx2, Digest, SHA384_DIGEST_SIZE); + RT_SHA384_End(&sha_ctx2, Digest); + + if (MACLen > SHA384_DIGEST_SIZE) + NdisMoveMemory(MAC, Digest, SHA384_DIGEST_SIZE); + else + NdisMoveMemory(MAC, Digest, MACLen); +} /* End of RT_HMAC_SHA384 */ + +VOID RT_HMAC_SHA384_VECTOR( + const UINT8 key[], + IN UINT key_len, + IN UCHAR element_num, + IN const UINT8 *message[], + IN UINT *message_len, + OUT UINT8 mac[], + IN UINT mac_len) +{ + SHA384_CTX_STRUC sha_ctx1; + SHA384_CTX_STRUC sha_ctx2; + UINT8 K0[SHA384_BLOCK_SIZE]; + UINT8 Digest[SHA384_DIGEST_SIZE]; + UINT index; + const UCHAR *_addr[6]; + INT _len[6], i; + + NdisZeroMemory(&sha_ctx1, sizeof(SHA384_CTX_STRUC)); + NdisZeroMemory(&sha_ctx2, sizeof(SHA384_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, SHA384_BLOCK_SIZE); + + if (key_len <= SHA384_BLOCK_SIZE) + NdisMoveMemory(K0, key, key_len); + else + RT_SHA384(key, key_len, K0); + + /* Exclusive-Or K0 with ipad */ + /* ipad: Inner pad; the byte x??36?? repeated B times. */ + for (index = 0; index < SHA384_BLOCK_SIZE; index++) + K0[index] ^= 0x36; + + /* End of for */ + RT_SHA384_Init(&sha_ctx1); + /* H(K0^ipad) */ + + _addr[0] = K0; + _len[0] = sizeof(K0); + + for (i = 0; i < element_num; i++) { + _addr[i + 1] = message[i]; + _len[i + 1] = message_len[i]; + } + + rt_sha384_vector(element_num + 1, _addr, _len, Digest); + /* Exclusive-Or K0 with opad and remove ipad */ + /* opad: Outer pad; the byte x??5c?? repeated B times. */ + for (index = 0; index < SHA384_BLOCK_SIZE; index++) + K0[index] ^= 0x36^0x5c; + + /* End of for */ + RT_SHA384_Init(&sha_ctx2); + /* H(K0^opad) */ + RT_SHA384_Append(&sha_ctx2, K0, sizeof(K0)); + /* H( (K0^opad) || H((K0^ipad)||text) ) */ + RT_SHA384_Append(&sha_ctx2, Digest, SHA384_DIGEST_SIZE); + RT_SHA384_End(&sha_ctx2, Digest); + + if (mac_len > SHA384_DIGEST_SIZE) + NdisMoveMemory(mac, Digest, SHA384_DIGEST_SIZE); + else + NdisMoveMemory(mac, Digest, mac_len); +} + +#endif /* SHA384_SUPPORT */ +#endif /* defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_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/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_md5.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_md5.c new file mode 100644 index 000000000..a49c1113d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_md5.c @@ -0,0 +1,356 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + Module Name: + MD5 + + Abstract: + RFC1321: The MD5 Message-Digest Algorithm + + Revision History: + Who When What + -------- ---------- ------------------------------------------ + Eddy 2008/11/24 Create md5 +***************************************************************************/ + +#include "rt_config.h" + + +#ifdef MD5_SUPPORT +/* + * F, G, H and I are basic MD5 functions. + */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +#define ROTL(x,n,w) ((x << n) | (x >> (w - n))) +#define ROTL32(x,n) ROTL(x,n,32) /* 32 bits word */ + +#define ROUND1(a, b, c, d, x, s, ac) { \ + (a) += F((b),(c),(d)) + (x) + (UINT32)(ac); \ + (a) = ROTL32((a),(s)); \ + (a) += (b); \ +} +#define ROUND2(a, b, c, d, x, s, ac) { \ + (a) += G((b),(c),(d)) + (x) + (UINT32)(ac); \ + (a) = ROTL32((a),(s)); \ + (a) += (b); \ +} +#define ROUND3(a, b, c, d, x, s, ac) { \ + (a) += H((b),(c),(d)) + (x) + (UINT32)(ac); \ + (a) = ROTL32((a),(s)); \ + (a) += (b); \ +} +#define ROUND4(a, b, c, d, x, s, ac) { \ + (a) += I((b),(c),(d)) + (x) + (UINT32)(ac); \ + (a) = ROTL32((a),(s)); \ + (a) += (b); \ +} +static const UINT32 MD5_DefaultHashValue[4] = { + 0x67452301UL, 0xefcdab89UL, 0x98badcfeUL, 0x10325476UL +}; +#endif /* MD5_SUPPORT */ + + +#ifdef MD5_SUPPORT +/* +======================================================================== +Routine Description: + Initial Md5_CTX_STRUC + +Arguments: + pMD5_CTX Pointer to Md5_CTX_STRUC + +Return Value: + None + +Note: + None +======================================================================== +*/ +VOID RT_MD5_Init ( + IN MD5_CTX_STRUC *pMD5_CTX) +{ + NdisMoveMemory(pMD5_CTX->HashValue, MD5_DefaultHashValue, + sizeof(MD5_DefaultHashValue)); + NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE); + pMD5_CTX->BlockLen = 0; + pMD5_CTX->MessageLen = 0; +} /* End of RT_MD5_Init */ + + +/* +======================================================================== +Routine Description: + MD5 computation for one block (512 bits) + +Arguments: + pMD5_CTX Pointer to Md5_CTX_STRUC + +Return Value: + None + +Note: + T[i] := floor(abs(sin(i + 1)) * (2 pow 32)), i is number of round +======================================================================== +*/ +VOID RT_MD5_Hash ( + IN MD5_CTX_STRUC *pMD5_CTX) +{ + UINT32 X_i; + UINT32 X[16]; + UINT32 a,b,c,d; + + /* Prepare the message schedule, {X_i} */ + NdisMoveMemory(X, pMD5_CTX->Block, MD5_BLOCK_SIZE); + for (X_i = 0; X_i < 16; X_i++) + X[X_i] = cpu2le32(X[X_i]); /* Endian Swap */ + /* End of for */ + + /* MD5 hash computation */ + /* Initialize the working variables */ + a = pMD5_CTX->HashValue[0]; + b = pMD5_CTX->HashValue[1]; + c = pMD5_CTX->HashValue[2]; + d = pMD5_CTX->HashValue[3]; + + /* + * Round 1 + * Let [abcd k s i] denote the operation + * a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s) + */ + ROUND1(a, b, c, d, X[ 0], 7, 0xd76aa478); /* 1 */ + ROUND1(d, a, b, c, X[ 1], 12, 0xe8c7b756); /* 2 */ + ROUND1(c, d, a, b, X[ 2], 17, 0x242070db); /* 3 */ + ROUND1(b, c, d, a, X[ 3], 22, 0xc1bdceee); /* 4 */ + ROUND1(a, b, c, d, X[ 4], 7, 0xf57c0faf); /* 5 */ + ROUND1(d, a, b, c, X[ 5], 12, 0x4787c62a); /* 6 */ + ROUND1(c, d, a, b, X[ 6], 17, 0xa8304613); /* 7 */ + ROUND1(b, c, d, a, X[ 7], 22, 0xfd469501); /* 8 */ + ROUND1(a, b, c, d, X[ 8], 7, 0x698098d8); /* 9 */ + ROUND1(d, a, b, c, X[ 9], 12, 0x8b44f7af); /* 10 */ + ROUND1(c, d, a, b, X[10], 17, 0xffff5bb1); /* 11 */ + ROUND1(b, c, d, a, X[11], 22, 0x895cd7be); /* 12 */ + ROUND1(a, b, c, d, X[12], 7, 0x6b901122); /* 13 */ + ROUND1(d, a, b, c, X[13], 12, 0xfd987193); /* 14 */ + ROUND1(c, d, a, b, X[14], 17, 0xa679438e); /* 15 */ + ROUND1(b, c, d, a, X[15], 22, 0x49b40821); /* 16 */ + + /* + * Round 2 + * Let [abcd k s i] denote the operation + * a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s) + */ + ROUND2(a, b, c, d, X[ 1], 5, 0xf61e2562); /* 17 */ + ROUND2(d, a, b, c, X[ 6], 9, 0xc040b340); /* 18 */ + ROUND2(c, d, a, b, X[11], 14, 0x265e5a51); /* 19 */ + ROUND2(b, c, d, a, X[ 0], 20, 0xe9b6c7aa); /* 20 */ + ROUND2(a, b, c, d, X[ 5], 5, 0xd62f105d); /* 21 */ + ROUND2(d, a, b, c, X[10], 9, 0x2441453); /* 22 */ + ROUND2(c, d, a, b, X[15], 14, 0xd8a1e681); /* 23 */ + ROUND2(b, c, d, a, X[ 4], 20, 0xe7d3fbc8); /* 24 */ + ROUND2(a, b, c, d, X[ 9], 5, 0x21e1cde6); /* 25 */ + ROUND2(d, a, b, c, X[14], 9, 0xc33707d6); /* 26 */ + ROUND2(c, d, a, b, X[ 3], 14, 0xf4d50d87); /* 27 */ + ROUND2(b, c, d, a, X[ 8], 20, 0x455a14ed); /* 28 */ + ROUND2(a, b, c, d, X[13], 5, 0xa9e3e905); /* 29 */ + ROUND2(d, a, b, c, X[ 2], 9, 0xfcefa3f8); /* 30 */ + ROUND2(c, d, a, b, X[ 7], 14, 0x676f02d9); /* 31 */ + ROUND2(b, c, d, a, X[12], 20, 0x8d2a4c8a); /* 32 */ + + /* + * Round 3 + * Let [abcd k s t] denote the operation + * a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s) + */ + ROUND3(a, b, c, d, X[ 5], 4, 0xfffa3942); /* 33 */ + ROUND3(d, a, b, c, X[ 8], 11, 0x8771f681); /* 34 */ + ROUND3(c, d, a, b, X[11], 16, 0x6d9d6122); /* 35 */ + ROUND3(b, c, d, a, X[14], 23, 0xfde5380c); /* 36 */ + ROUND3(a, b, c, d, X[ 1], 4, 0xa4beea44); /* 37 */ + ROUND3(d, a, b, c, X[ 4], 11, 0x4bdecfa9); /* 38 */ + ROUND3(c, d, a, b, X[ 7], 16, 0xf6bb4b60); /* 39 */ + ROUND3(b, c, d, a, X[10], 23, 0xbebfbc70); /* 40 */ + ROUND3(a, b, c, d, X[13], 4, 0x289b7ec6); /* 41 */ + ROUND3(d, a, b, c, X[ 0], 11, 0xeaa127fa); /* 42 */ + ROUND3(c, d, a, b, X[ 3], 16, 0xd4ef3085); /* 43 */ + ROUND3(b, c, d, a, X[ 6], 23, 0x4881d05); /* 44 */ + ROUND3(a, b, c, d, X[ 9], 4, 0xd9d4d039); /* 45 */ + ROUND3(d, a, b, c, X[12], 11, 0xe6db99e5); /* 46 */ + ROUND3(c, d, a, b, X[15], 16, 0x1fa27cf8); /* 47 */ + ROUND3(b, c, d, a, X[ 2], 23, 0xc4ac5665); /* 48 */ + + /* + * Round 4 + * Let [abcd k s t] denote the operation + * a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s) + */ + ROUND4(a, b, c, d, X[ 0], 6, 0xf4292244); /* 49 */ + ROUND4(d, a, b, c, X[ 7], 10, 0x432aff97); /* 50 */ + ROUND4(c, d, a, b, X[14], 15, 0xab9423a7); /* 51 */ + ROUND4(b, c, d, a, X[ 5], 21, 0xfc93a039); /* 52 */ + ROUND4(a, b, c, d, X[12], 6, 0x655b59c3); /* 53 */ + ROUND4(d, a, b, c, X[ 3], 10, 0x8f0ccc92); /* 54 */ + ROUND4(c, d, a, b, X[10], 15, 0xffeff47d); /* 55 */ + ROUND4(b, c, d, a, X[ 1], 21, 0x85845dd1); /* 56 */ + ROUND4(a, b, c, d, X[ 8], 6, 0x6fa87e4f); /* 57 */ + ROUND4(d, a, b, c, X[15], 10, 0xfe2ce6e0); /* 58 */ + ROUND4(c, d, a, b, X[ 6], 15, 0xa3014314); /* 59 */ + ROUND4(b, c, d, a, X[13], 21, 0x4e0811a1); /* 60 */ + ROUND4(a, b, c, d, X[ 4], 6, 0xf7537e82); /* 61 */ + ROUND4(d, a, b, c, X[11], 10, 0xbd3af235); /* 62 */ + ROUND4(c, d, a, b, X[ 2], 15, 0x2ad7d2bb); /* 63 */ + ROUND4(b, c, d, a, X[ 9], 21, 0xeb86d391); /* 64 */ + + /* Compute the i^th intermediate hash value H^(i) */ + pMD5_CTX->HashValue[0] += a; + pMD5_CTX->HashValue[1] += b; + pMD5_CTX->HashValue[2] += c; + pMD5_CTX->HashValue[3] += d; + + NdisZeroMemory(pMD5_CTX->Block, MD5_BLOCK_SIZE); + pMD5_CTX->BlockLen = 0; +} /* End of RT_MD5_Hash */ + + +/* +======================================================================== +Routine Description: + The message is appended to block. If block size > 64 bytes, the MD5_Hash +will be called. + +Arguments: + pMD5_CTX Pointer to MD5_CTX_STRUC + message Message context + messageLen The length of message in bytes + +Return Value: + None + +Note: + None +======================================================================== +*/ +VOID RT_MD5_Append ( + IN MD5_CTX_STRUC *pMD5_CTX, + IN const UINT8 Message[], + IN UINT MessageLen) +{ + UINT appendLen = 0; + UINT diffLen = 0; + + while (appendLen != MessageLen) { + diffLen = MessageLen - appendLen; + if ((pMD5_CTX->BlockLen + diffLen) < MD5_BLOCK_SIZE) { + NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen, + Message + appendLen, diffLen); + pMD5_CTX->BlockLen += diffLen; + appendLen += diffLen; + } + else + { + NdisMoveMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen, + Message + appendLen, MD5_BLOCK_SIZE - pMD5_CTX->BlockLen); + appendLen += (MD5_BLOCK_SIZE - pMD5_CTX->BlockLen); + pMD5_CTX->BlockLen = MD5_BLOCK_SIZE; + RT_MD5_Hash(pMD5_CTX); + } /* End of if */ + } /* End of while */ + pMD5_CTX->MessageLen += MessageLen; +} /* End of RT_MD5_Append */ + + +/* +======================================================================== +Routine Description: + 1. Append bit 1 to end of the message + 2. Append the length of message in rightmost 64 bits + 3. Transform the Hash Value to digest message + +Arguments: + pMD5_CTX Pointer to MD5_CTX_STRUC + +Return Value: + digestMessage Digest message + +Note: + None +======================================================================== +*/ +VOID RT_MD5_End ( + IN MD5_CTX_STRUC *pMD5_CTX, + OUT UINT8 DigestMessage[]) +{ + UINT index; + UINT64 message_length_bits; + + /* append 1 bits to end of the message */ + NdisFillMemory(pMD5_CTX->Block + pMD5_CTX->BlockLen, 1, 0x80); + + /* 55 = 64 - 8 - 1: append 1 bit(1 byte) and message length (8 bytes) */ + if (pMD5_CTX->BlockLen > 55) + RT_MD5_Hash(pMD5_CTX); + /* End of if */ + + /* Append the length of message in rightmost 64 bits */ + message_length_bits = pMD5_CTX->MessageLen*8; + message_length_bits = cpu2le64(message_length_bits); + NdisMoveMemory(&pMD5_CTX->Block[56], &message_length_bits, 8); + RT_MD5_Hash(pMD5_CTX); + + /* Return message digest, transform the UINT32 hash value to bytes */ + for (index = 0; index < 4;index++) + pMD5_CTX->HashValue[index] = cpu2le32(pMD5_CTX->HashValue[index]); + /* End of for */ + NdisMoveMemory(DigestMessage, pMD5_CTX->HashValue, MD5_DIGEST_SIZE); +} /* End of RT_MD5_End */ + + +/* +======================================================================== +Routine Description: + MD5 algorithm + +Arguments: + message Message context + messageLen The length of message in bytes + +Return Value: + digestMessage Digest message + +Note: + None +======================================================================== +*/ +VOID RT_MD5 ( + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 DigestMessage[]) +{ + MD5_CTX_STRUC md5_ctx; + + NdisZeroMemory(&md5_ctx, sizeof(MD5_CTX_STRUC)); + RT_MD5_Init(&md5_ctx); + RT_MD5_Append(&md5_ctx, Message, MessageLen); + RT_MD5_End(&md5_ctx, DigestMessage); +} /* End of RT_MD5 */ + +#endif /* MD5_SUPPORT */ + + +/* End of crypt_md5.c */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_sha2.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_sha2.c new file mode 100644 index 000000000..c7933f6a4 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/crypt_sha2.c @@ -0,0 +1,849 @@ +/**************************************************************************** + * 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 */ +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +#define ROTR64(x, n) ROTR(x, n, 64) /* 64 bits word */ +#define ROTL64(x, n) ROTL(x, n, 64) /* 64 bits word */ +#endif + +/* 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 */ + +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +#ifdef SHA384_SUPPORT +/* SHA384 functions */ +#define Zsigma_512_0(x) (ROTR64(x, 28) ^ ROTR64(x, 34) ^ ROTR64(x, 39)) +#define Zsigma_512_1(x) (ROTR64(x, 14) ^ ROTR64(x, 18) ^ ROTR64(x, 41)) +#define Sigma_512_0(x) (ROTR64(x, 1) ^ ROTR64(x, 8) ^ SHR(x, 7)) +#define Sigma_512_1(x) (ROTR64(x, 19) ^ ROTR64(x, 61) ^ SHR(x, 6)) +/* SHA384 constants */ +static const UINT64 SHA384_K[80] = { + 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, + 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, + 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, + 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, + 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, + 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, + 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, + 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, + 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, + 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, + 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, + 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, + 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, + 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, + 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, + 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, + 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, + 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, + 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, + 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 +}; +static const UINT64 SHA384_DefaultHashValue[8] = { + 0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939, + 0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4 +}; +#endif /* SHA384_SUPPORT */ +#endif + +#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 */ +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +VOID rt_sha256_vector( + IN UCHAR num, + IN const unsigned char **message, + IN UINT *messageLen, + OUT UINT8 *digestmessage) +{ + SHA256_CTX_STRUC sha_ctx; + UCHAR i; + + NdisZeroMemory(&sha_ctx, sizeof(SHA256_CTX_STRUC)); + RT_SHA256_Init(&sha_ctx); + for (i = 0; i < num; i++) + RT_SHA256_Append(&sha_ctx, message[i], messageLen[i]); + RT_SHA256_End(&sha_ctx, digestmessage); +} +#endif /* defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) */ +#endif /* SHA256_SUPPORT */ + +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +#ifdef SHA384_SUPPORT +/* +======================================================================== +Routine Description: + Initial SHA384_CTX_STRUC + +Arguments: + pSHA_CTX Pointer to SHA384_CTX_STRUC + +Return Value: + None + +Note: + None +======================================================================== +*/ +VOID RT_SHA384_Init( + IN SHA384_CTX_STRUC * pSHA_CTX) +{ + NdisMoveMemory(pSHA_CTX->HashValue, SHA384_DefaultHashValue, sizeof(SHA384_DefaultHashValue)); + NdisZeroMemory(pSHA_CTX->Block, SHA384_BLOCK_SIZE); + pSHA_CTX->MessageLen = 0; + pSHA_CTX->BlockLen = 0; +} /* End of RT_SHA384_Init */ + + +/* +======================================================================== +Routine Description: + SHA384 computation for one block (1024 bits) + +Arguments: + pSHA_CTX Pointer to SHA384_CTX_STRUC + +Return Value: + None + +Note: + None +======================================================================== +*/ +VOID RT_SHA384_Hash( + IN SHA384_CTX_STRUC * pSHA_CTX) +{ + UINT32 W_i, t; + UINT64 W[80]; + UINT64 a, b, c, d, e, f, g, h, T1, T2; + /* Prepare the message schedule, {W_i}, 0 < t < 15 */ + NdisMoveMemory(W, pSHA_CTX->Block, SHA384_BLOCK_SIZE); + + for (W_i = 0; W_i < 16; W_i++) + W[W_i] = cpu2be64(W[W_i]); /* Endian Swap */ + + /* End of for */ + /* SHA384 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 < 80; t++) { + if (t > 15) /* Prepare the message schedule, {W_i}, 16 < t < 79 */ + W[t] = Sigma_512_1(W[t-2]) + W[t-7] + Sigma_512_0(W[t-15]) + W[t-16]; + + T1 = h + Zsigma_512_1(e) + Ch(e, f, g) + SHA384_K[t] + W[t]; + T2 = Zsigma_512_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, SHA384_BLOCK_SIZE); + pSHA_CTX->BlockLen = 0; +} /* End of RT_SHA384_Hash */ + + +/* +======================================================================== +Routine Description: + The message is appended to block. If block size > 128 bytes, the SHA384_Hash +will be called. + +Arguments: + pSHA_CTX Pointer to SHA384_CTX_STRUC + message Message context + messageLen The length of message in bytes + +Return Value: + None + +Note: + None +======================================================================== +*/ +VOID RT_SHA384_Append( + IN SHA384_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) < SHA384_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, SHA384_BLOCK_SIZE - pSHA_CTX->BlockLen); + appendLen += (SHA384_BLOCK_SIZE - pSHA_CTX->BlockLen); + pSHA_CTX->BlockLen = SHA384_BLOCK_SIZE; + RT_SHA384_Hash(pSHA_CTX); + } /* End of if */ + } /* End of while */ + + pSHA_CTX->MessageLen += MessageLen; +} /* End of RT_SHA384_Append */ + + +/* +======================================================================== +Routine Description: + 1. Append bit 1 to end of the message + 2. Append the length of message in rightmost 128 bits + 3. Transform the Hash Value to digest message + +Arguments: + pSHA_CTX Pointer to SHA384_CTX_STRUC + +Return Value: + digestMessage Digest message + +Note: + None +======================================================================== +*/ +VOID RT_SHA384_End( + IN SHA384_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); + + /* 119 = 128(SHA256_BLOCK_SIZE) - 16 - 1: append 1 bit(1 byte) and message length (16 bytes) */ + if (pSHA_CTX->BlockLen > 119) + RT_SHA384_Hash(pSHA_CTX); + + /* End of if */ + /* Append the length of message in rightmost 128 bits */ + message_length_bits = pSHA_CTX->MessageLen*8; + message_length_bits = cpu2be64(message_length_bits); + NdisMoveMemory(&pSHA_CTX->Block[120], &message_length_bits, 8); + RT_SHA384_Hash(pSHA_CTX); + + /* Return message digest, transform the UINT64 hash value to bytes */ + for (index = 0; index < 8; index++) + pSHA_CTX->HashValue[index] = cpu2be64(pSHA_CTX->HashValue[index]); + + /* End of for */ + NdisMoveMemory(DigestMessage, pSHA_CTX->HashValue, SHA384_DIGEST_SIZE); +} /* End of RT_SHA384_End */ + + +/* +======================================================================== +Routine Description: + SHA384 algorithm + +Arguments: + message Message context + messageLen The length of message in bytes + +Return Value: + digestMessage Digest message + +Note: + None +======================================================================== +*/ +VOID RT_SHA384( + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 DigestMessage[]) +{ + SHA384_CTX_STRUC sha_ctx; + + NdisZeroMemory(&sha_ctx, sizeof(SHA384_CTX_STRUC)); + RT_SHA384_Init(&sha_ctx); + RT_SHA384_Append(&sha_ctx, Message, MessageLen); + RT_SHA384_End(&sha_ctx, DigestMessage); +} /* End of RT_SHA384 */ + +VOID rt_sha384_vector( + IN UCHAR num, + IN const unsigned char **message, + IN UINT *messageLen, + OUT UINT8 *digestmessage) +{ + SHA384_CTX_STRUC sha_ctx; + UCHAR i; + + NdisZeroMemory(&sha_ctx, sizeof(SHA384_CTX_STRUC)); + RT_SHA384_Init(&sha_ctx); + for (i = 0; i < num; i++) + RT_SHA384_Append(&sha_ctx, message[i], messageLen[i]); + RT_SHA384_End(&sha_ctx, digestmessage); +} + +#endif /* SHA384_SUPPORT */ +#endif /* defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) */ + +/* End of crypt_sha2.c */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ecc.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ecc.c new file mode 100644 index 000000000..90a8c36a0 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ecc.c @@ -0,0 +1,1178 @@ +#include "rt_config.h" +#include "sae_cmm.h" +#include "ecc.h" + +EC_POINT_OP_TIME_RECORD ec_op_ti_rec; + +static EC_GROUP_INFO ec_groups[] = { + EC_GROUP(19, EC_GROUP19_BITS_OF_R), + EC_GROUP(20, EC_GROUP20_BITS_OF_R), + EC_GROUP(21, EC_GROUP21_BITS_OF_R), + EC_GROUP(25, EC_GROUP25_BITS_OF_R), + EC_GROUP(26, EC_GROUP26_BITS_OF_R), + EC_GROUP(27, EC_GROUP27_BITS_OF_R), + EC_GROUP(28, EC_GROUP28_BITS_OF_R), + EC_GROUP(29, EC_GROUP29_BITS_OF_R), + EC_GROUP(30, EC_GROUP30_BITS_OF_R), +}; + +static EC_GROUP_INFO_BI ec_groups_bi[] = { + EC_GROUP_BI(19), + EC_GROUP_BI(20), + EC_GROUP_BI(21), + EC_GROUP_BI(25), + EC_GROUP_BI(26), + EC_GROUP_BI(27), + EC_GROUP_BI(28), + EC_GROUP_BI(29), + EC_GROUP_BI(30), +}; + +int ECC_COST_TIME_DBG_LVL = DBG_LVL_INFO; + + +EC_GROUP_INFO *get_ecc_group_info( + IN INT32 group) +{ + UINT32 i; + EC_GROUP_INFO *ec_group = NULL; + + for (i = 0; i < EC_GROUP_NUM; i++) + if (ec_groups[i].group_id == group) + ec_group = &ec_groups[i]; + return ec_group; +} + +EC_GROUP_INFO_BI *get_ecc_group_info_bi( + IN INT32 group) +{ + UINT32 i; + EC_GROUP_INFO_BI *ec_group_bi = NULL; + EC_GROUP_INFO *ec_group = NULL; + const UCHAR *gx = NULL; + const UCHAR *gy = NULL; + UINT32 gx_len; + UINT32 gy_len; + + for (i = 0; i < EC_GROUP_NUM; i++) + if (ec_groups[i].group_id == group) { + ec_group = &ec_groups[i]; + ec_group_bi = &ec_groups_bi[i]; + } + + if (ec_group == NULL + || ec_group_bi == NULL) + return NULL; + + if (ec_group_bi->is_init == FALSE) { + SAE_BN *tmp = NULL; + SAE_BN *pthree = NULL; + UCHAR three[] = {0x3}; + + SAE_BN_BIN2BI((UINT8 *)ec_group->prime, + ec_group->prime_len, + &ec_group_bi->prime); + SAE_BN_BIN2BI((UINT8 *)ec_group->order, + ec_group->order_len, + &ec_group_bi->order); + SAE_BN_BIN2BI((UINT8 *)ec_group->a, + ec_group->a_len, + &ec_group_bi->a); + SAE_BN_BIN2BI((UINT8 *)ec_group->b, + ec_group->b_len, + &ec_group_bi->b); + + if (group == 19) { + gx = ec_group19_gx; + gy = ec_group19_gy; + gx_len = sizeof(ec_group19_gx); + gy_len = sizeof(ec_group19_gy); + } else if (group == 20) { + gx = ec_group20_gx; + gy = ec_group20_gy; + gx_len = sizeof(ec_group20_gx); + gy_len = sizeof(ec_group20_gy); + } else if (group == 21) { + gx = ec_group21_gx; + gy = ec_group21_gy; + gx_len = sizeof(ec_group21_gx); + gy_len = sizeof(ec_group21_gy); + } + + if ((gx != NULL) && (gy != NULL)) { + SAE_BN_BIN2BI((UINT8 *)gx, gx_len, &ec_group_bi->gx); + SAE_BN_BIN2BI((UINT8 *)gy, gy_len, &ec_group_bi->gy); + } + + ec_group_bi->is_init = TRUE; + + SAE_BN_BIN2BI(three, sizeof(three), &pthree); + SAE_BN_INIT(&tmp); + SAE_BN_ADD(ec_group_bi->a, pthree, &tmp); + if (!SAE_BN_UCMP(tmp, ec_group_bi->prime)) + ec_group_bi->is_minus_3 = TRUE; + + SAE_BN_FREE(&tmp); + SAE_BN_FREE(&pthree); + + /* mont structure init */ + os_alloc_mem(NULL, (UCHAR **) &ec_group_bi->mont, sizeof(MONT_STRUC)); + if (ec_group_bi->mont == NULL) + return NULL; + + ec_group_bi->mont->Bits_Of_R = ec_group->bits_of_R; + ec_group_bi->mont->pBI_X = NULL; + ec_group_bi->mont->pBI_R = NULL; + ec_group_bi->mont->pBI_PInverse = NULL; +#ifndef DOT11_SAE_OPENSSL_BN + SAE_BN_BIN2BI((UINT8 *)ec_group->X, + ec_group->X_len, + &ec_group_bi->mont->pBI_X); + SAE_BN_BIN2BI((UINT8 *)ec_group->R, + ec_group->R_len, + &ec_group_bi->mont->pBI_R); + SAE_BN_BIN2BI((UINT8 *)ec_group->PInverse, + ec_group->PInverse_len, + &ec_group_bi->mont->pBI_PInverse); +#endif + } + + return ec_group_bi; +} + +VOID group_info_bi_deinit( + VOID) +{ + UINT32 i; + EC_GROUP_INFO_BI *ec_group_bi = NULL; + + for (i = 0; i < EC_GROUP_NUM; i++) + if (ec_groups_bi[i].is_init == TRUE) { + ec_group_bi = &ec_groups_bi[i]; + + SAE_BN_FREE(&ec_group_bi->prime); + SAE_BN_FREE(&ec_group_bi->order); + SAE_BN_FREE(&ec_group_bi->a); + SAE_BN_FREE(&ec_group_bi->b); + SAE_BN_FREE(&ec_group_bi->gx); + SAE_BN_FREE(&ec_group_bi->gy); + ec_group_bi->cofactor = NULL; + + if (ec_group_bi->mont != NULL) { +#ifndef DOT11_SAE_OPENSSL_BN + SAE_BN_FREE(&ec_group_bi->mont->pBI_X); + SAE_BN_FREE(&ec_group_bi->mont->pBI_R); + SAE_BN_FREE(&ec_group_bi->mont->pBI_PInverse); +#endif + os_free_mem(NULL, ec_group_bi->mont); + ec_group_bi->mont = NULL; + } + + ec_group_bi->is_init = FALSE; + } +} + +BIG_INTEGER_EC_POINT *ecc_point_add_cmm( + IN BIG_INTEGER_EC_POINT *point, + IN BIG_INTEGER_EC_POINT *point2, + IN SAE_BN *lamda, + IN EC_GROUP_INFO_BI *ec_group_bi) +{ + BIG_INTEGER_EC_POINT *res = NULL; + SAE_BN *tmp = NULL; + SAE_BN *tmp2 = NULL; + SAE_BN *prime = ec_group_bi->prime; + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("==> %s()\n", __func__)); + ecc_point_init(&res); + + if (res == NULL) + return NULL; + + POOL_COUNTER_CHECK_BEGIN(sae_expected_cnt[7]); + GET_BI_INS_FROM_POOL(tmp); + GET_BI_INS_FROM_POOL(tmp2); + + /* + * Xr = lamda ^ 2 - Xp - Xq + * Yr = lamda * (Xp - Xr) - Yp + */ + SAE_BN_MOD_MUL(lamda, lamda, prime, &tmp); + SAE_BN_MOD_ADD_QUICK(point->x, point2->x, prime, &tmp2); + SAE_BN_MOD_SUB(tmp, tmp2, prime, &res->x); + SAE_BN_MOD_SUB_QUICK(point->x, res->x, prime, &tmp); + SAE_BN_MOD_MUL(lamda, tmp, prime, &tmp2); + SAE_BN_MOD_SUB(tmp2, point->y, prime, &res->y); + SAE_BN_RELEASE_BACK_TO_POOL(&tmp); + SAE_BN_RELEASE_BACK_TO_POOL(&tmp2); + POOL_COUNTER_CHECK_END(sae_expected_cnt[7]); + return res; +} + +VOID ecc_point_init( + IN BIG_INTEGER_EC_POINT **ec_point_res) +{ + if (*ec_point_res == NULL) { + os_alloc_mem(NULL, (UCHAR **)ec_point_res, sizeof(BIG_INTEGER_EC_POINT)); + + if (*ec_point_res == NULL) { + panic("ecc_point_init alloc fail\n"); + return; + } + + (*ec_point_res)->x = NULL; + (*ec_point_res)->y = NULL; + (*ec_point_res)->z = NULL; + (*ec_point_res)->z_is_one = 0; + } +} + + +VOID ecc_point_free( + IN BIG_INTEGER_EC_POINT **ec_point_res) +{ + if (*ec_point_res == NULL) + return; + + SAE_BN_FREE(&(*ec_point_res)->x); + SAE_BN_FREE(&(*ec_point_res)->y); + SAE_BN_FREE(&(*ec_point_res)->z); + os_free_mem(NULL, *ec_point_res); + *ec_point_res = NULL; +} + +VOID ecc_point_copy( + IN BIG_INTEGER_EC_POINT *point, + OUT BIG_INTEGER_EC_POINT **ec_point_res) +{ + if (point == NULL) + return; + + if (*ec_point_res == NULL) { + ecc_point_init(ec_point_res); + + if (*ec_point_res == NULL) { + panic("ecc_point_init alloc fail\n"); + return; + } + } + + if (point->x) + SAE_BN_COPY(point->x, &(*ec_point_res)->x); + if (point->y) + SAE_BN_COPY(point->y, &(*ec_point_res)->y); + if (point->z) + SAE_BN_COPY(point->z, &(*ec_point_res)->z); + (*ec_point_res)->z_is_one = point->z_is_one; +} + +/* if (x1, y2) != (x2, y2), but x1 = x2 => result is infinity */ +/* if point1 + point2 and point1 is infinity => result is point2 */ +VOID ecc_point_add( + IN BIG_INTEGER_EC_POINT *point, + IN BIG_INTEGER_EC_POINT *point2, + IN EC_GROUP_INFO_BI *ec_group_bi, + OUT BIG_INTEGER_EC_POINT **ec_point_res) +{ + BIG_INTEGER_EC_POINT *res = NULL; + SAE_BN *tmp = NULL; + SAE_BN *tmp2 = NULL; + SAE_BN *lamda = NULL; + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_INFO, + ("==> %s()\n", __func__)); + SAE_LOG_TIME_BEGIN(&ec_op_ti_rec.add_op); + + /* if point1 + point2 and point1 is infinity => result is point2 */ + if (point == NULL && point2 != NULL) { + ecc_point_copy(point2, ec_point_res); + return; + } + + /* if point1 + point2 and point2 is infinity => result is point1 */ + if (point != NULL && point2 == NULL) { + ecc_point_copy(point, ec_point_res); + return; + } + + /* if point1 + point2 and point1 & point2 is infinity => result is infinity */ + if (point == NULL && point2 == NULL) { + ecc_point_free(ec_point_res); + return; + } + + if (point->z && point2->z) { + ecc_point_add_3d(point, point2, ec_group_bi, ec_point_res); + return; + } + + if (SAE_BN_UCMP(point->x, point2->x) == 0) { + if (SAE_BN_UCMP(point->y, point2->y) == 0) + ecc_point_double(point, ec_group_bi, ec_point_res); + else + /* if (x1, y2) != (x2, y2), but x1 = x2 => result is infinity */ + ecc_point_free(ec_point_res); + return; + } + + POOL_COUNTER_CHECK_BEGIN(sae_expected_cnt[8]); + GET_BI_INS_FROM_POOL(tmp); + GET_BI_INS_FROM_POOL(tmp2); + GET_BI_INS_FROM_POOL(lamda); + SAE_BN_INIT(&tmp); + SAE_BN_INIT(&tmp2); + SAE_BN_INIT(&lamda); + + /* lamda = (Yp - Yq) / (Xp - Xq) */ + SAE_BN_MOD_SUB_QUICK(point->x, point2->x, ec_group_bi->prime, &tmp); + SAE_BN_MOD_SUB_QUICK(point->y, point2->y, ec_group_bi->prime, &tmp2); + SAE_BN_MOD_DIV(tmp2, tmp, ec_group_bi->prime, &lamda); + res = ecc_point_add_cmm(point, point2, lamda, ec_group_bi); + ecc_point_copy(res, ec_point_res); + SAE_BN_RELEASE_BACK_TO_POOL(&tmp); + SAE_BN_RELEASE_BACK_TO_POOL(&tmp2); + SAE_BN_RELEASE_BACK_TO_POOL(&lamda); + POOL_COUNTER_CHECK_END(sae_expected_cnt[8]); + ecc_point_free(&res); + SAE_LOG_TIME_END(&ec_op_ti_rec.add_op); +} + +/* if point is infinity, result is infinity */ +VOID ecc_point_double( + IN BIG_INTEGER_EC_POINT *point, + IN EC_GROUP_INFO_BI *ec_group_bi, + OUT BIG_INTEGER_EC_POINT **ec_point_res) +{ + BIG_INTEGER_EC_POINT *res = NULL; + SAE_BN *tmp = NULL; + SAE_BN *tmp2 = NULL; + SAE_BN *lamda = NULL; + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_INFO, + ("==> %s()\n", __func__)); + SAE_LOG_TIME_BEGIN(&ec_op_ti_rec.dbl_op); + + if (point == NULL) { + /* if point is infinity, result is infinity */ + ecc_point_free(ec_point_res); + return; + } + + if (point->z) { + ecc_point_double_3d(point, ec_group_bi, ec_point_res); + return; + } + + POOL_COUNTER_CHECK_BEGIN(sae_expected_cnt[9]); + GET_BI_INS_FROM_POOL(tmp); + GET_BI_INS_FROM_POOL(tmp2); + GET_BI_INS_FROM_POOL(lamda); + SAE_BN_INIT(&tmp); + SAE_BN_INIT(&tmp2); + SAE_BN_INIT(&lamda); + + /* lamda = (3Xp^2 + a) / 2Yp */ + SAE_BN_MOD_SQR(point->x, ec_group_bi->prime, &tmp); + SAE_BN_MOD_ADD_QUICK(tmp, tmp, ec_group_bi->prime, &tmp2); + SAE_BN_MOD_ADD_QUICK(tmp, tmp2, ec_group_bi->prime, &tmp2); + SAE_BN_MOD_ADD(tmp2, ec_group_bi->a, ec_group_bi->prime, &tmp); + SAE_BN_MOD_ADD_QUICK(point->y, point->y, ec_group_bi->prime, &tmp2); + SAE_BN_MOD_DIV(tmp, tmp2, ec_group_bi->prime, &lamda); + res = ecc_point_add_cmm(point, point, lamda, ec_group_bi); + ecc_point_copy(res, ec_point_res); + SAE_BN_RELEASE_BACK_TO_POOL(&tmp); + SAE_BN_RELEASE_BACK_TO_POOL(&tmp2); + SAE_BN_RELEASE_BACK_TO_POOL(&lamda); + POOL_COUNTER_CHECK_END(sae_expected_cnt[9]); + ecc_point_free(&res); + SAE_LOG_TIME_END(&ec_op_ti_rec.dbl_op); +} + +VOID ecc_point_add_3d( + IN BIG_INTEGER_EC_POINT *point, + IN BIG_INTEGER_EC_POINT *point2, + IN EC_GROUP_INFO_BI *ec_group_bi, + OUT BIG_INTEGER_EC_POINT **ec_point_res) +{ + SAE_BN *n0 = NULL; + SAE_BN *n1 = NULL; + SAE_BN *n2 = NULL; + SAE_BN *n3 = NULL; + SAE_BN *n4 = NULL; + SAE_BN *n5 = NULL; + SAE_BN *n6 = NULL; + BIG_INTEGER_EC_POINT *res = NULL; + + /* if point1 + point2 and point1 is infinity => result is point2 */ + if (point == NULL && point2 != NULL) { + ecc_point_copy(point2, ec_point_res); + return; + } + + /* if point1 + point2 and point2 is infinity => result is point1 */ + if (point != NULL && point2 == NULL) { + ecc_point_copy(point, ec_point_res); + return; + } + + /* if point1 + point2 and point1 & point2 is infinity => result is infinity */ + if (point == NULL && point2 == NULL) { + ecc_point_free(ec_point_res); + return; + } + + SAE_BN_INIT(&n0); + SAE_BN_INIT(&n1); + SAE_BN_INIT(&n2); + SAE_BN_INIT(&n3); + SAE_BN_INIT(&n4); + SAE_BN_INIT(&n5); + SAE_BN_INIT(&n6); + + if (n6 == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("%s: allocate fail\n", __func__)); + ecc_point_free(ec_point_res); + return; + } + + /* n1, n2 */ + if (point2->z_is_one) { + SAE_BN_COPY(point->x, &n1); + SAE_BN_COPY(point->y, &n2); + /* n1 = X_a */ + /* n2 = Y_a */ + } else { + SAE_BN_MOD_SQR(point2->z, ec_group_bi->prime, &n0); + SAE_BN_MOD_MUL(point->x, n0, ec_group_bi->prime, &n1); + /* n1 = X_a * Z_b^2 */ + SAE_BN_MOD_MUL(n0, point2->z, ec_group_bi->prime, &n0); + SAE_BN_MOD_MUL(point->y, n0, ec_group_bi->prime, &n2); + /* n2 = Y_a * Z_b^3 */ + } + + /* n3, n4 */ + if (point->z_is_one) { + SAE_BN_COPY(point2->x, &n3); + SAE_BN_COPY(point2->y, &n4); + /* n3 = X_b */ + /* n4 = Y_b */ + } else { + SAE_BN_MOD_SQR(point->z, ec_group_bi->prime, &n0); + SAE_BN_MOD_MUL(point2->x, n0, ec_group_bi->prime, &n3); + /* n3 = X_b * Z_a^2 */ + SAE_BN_MOD_MUL(n0, point->z, ec_group_bi->prime, &n0); + SAE_BN_MOD_MUL(point2->y, n0, ec_group_bi->prime, &n4); + /* n4 = Y_b * Z_a^3 */ + } + + /* n5, n6 */ + SAE_BN_MOD_SUB_QUICK(n1, n3, ec_group_bi->prime, &n5); + SAE_BN_MOD_SUB_QUICK(n2, n4, ec_group_bi->prime, &n6); + /* n5 = n1 - n3 */ + /* n6 = n2 - n4 */ + + if (SAE_BN_IS_ZERO(n5)) { + if (SAE_BN_IS_ZERO(n6)) { + /* a is the same point as b */ + ecc_point_double_3d(point, ec_group_bi, ec_point_res); + } else { + /* a is the inverse of b */ + ecc_point_free(ec_point_res); + } + return; + } + /* 'n7', 'n8' */ + SAE_BN_MOD_ADD_QUICK(n1, n3, ec_group_bi->prime, &n1); + SAE_BN_MOD_ADD_QUICK(n2, n4, ec_group_bi->prime, &n2); + /* 'n7' = n1 + n3 */ + /* 'n8' = n2 + n4 */ + + ecc_point_init(&res); + + if (res == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s: ecc allocate fail\n", __func__)); + ecc_point_free(ec_point_res); + return; + } + + SAE_BN_INIT(&res->x); + SAE_BN_INIT(&res->y); + SAE_BN_INIT(&res->z); + + /* Z_r */ + if (point->z_is_one && point2->z_is_one) + SAE_BN_COPY(n5, &res->z); + else { + if (point->z_is_one) + SAE_BN_COPY(point2->z, &n0); + else if (point2->z_is_one) + SAE_BN_COPY(point->z, &n0); + else + SAE_BN_MOD_MUL(point->z, point2->z, ec_group_bi->prime, &n0); + SAE_BN_MOD_MUL(n0, n5, ec_group_bi->prime, &res->z); + } + res->z_is_one = 0; + /* Z_r = Z_a * Z_b * n5 */ + + /* X_r */ + SAE_BN_MOD_SQR(n6, ec_group_bi->prime, &n0); + SAE_BN_MOD_SQR(n5, ec_group_bi->prime, &n4); + SAE_BN_MOD_MUL(n1, n4, ec_group_bi->prime, &n3); + SAE_BN_MOD_SUB_QUICK(n0, n3, ec_group_bi->prime, &res->x); + /* X_r = n6^2 - n5^2 * 'n7' */ + + /* 'n9' */ + SAE_BN_MOD_LSHIFT1(res->x, ec_group_bi->prime, &n0); + SAE_BN_MOD_SUB_QUICK(n3, n0, ec_group_bi->prime, &n0); + /* n9 = n5^2 * 'n7' - 2 * X_r */ + + /* Y_r */ + SAE_BN_MOD_MUL(n0, n6, ec_group_bi->prime, &n0); + SAE_BN_MOD_MUL(n4, n5, ec_group_bi->prime, &n5); /* now n5 is n5^3 */ + SAE_BN_MOD_MUL(n2, n5, ec_group_bi->prime, &n1); + SAE_BN_MOD_SUB_QUICK(n0, n1, ec_group_bi->prime, &n0); + if (SAE_BN_IS_ODD(n0)) { + SAE_BN_ADD(n0, ec_group_bi->prime, &n3); /* BI: input can not equal to output */ + SAE_BN_COPY(n3, &n0); + } + /* now 0 <= n0 < 2*p, and n0 is even */ + SAE_BN_RSHIFT1(n0, &res->y); + /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */ + + SAE_BN_FREE(&n0); + SAE_BN_FREE(&n1); + SAE_BN_FREE(&n2); + SAE_BN_FREE(&n3); + SAE_BN_FREE(&n4); + SAE_BN_FREE(&n5); + SAE_BN_FREE(&n6); + + ecc_point_copy(res, ec_point_res); + + ecc_point_free(&res); +} + +VOID ecc_point_double_3d( + IN BIG_INTEGER_EC_POINT *point, + IN EC_GROUP_INFO_BI *ec_group_bi, + OUT BIG_INTEGER_EC_POINT **ec_point_res) +{ + SAE_BN *n0 = NULL; + SAE_BN *n1 = NULL; + SAE_BN *n2 = NULL; + SAE_BN *n3 = NULL; + BIG_INTEGER_EC_POINT *res = NULL; + + if (point == NULL) { + /* if point is infinity, result is infinity */ + ecc_point_free(ec_point_res); + return; + } + + SAE_BN_INIT(&n0); + SAE_BN_INIT(&n1); + SAE_BN_INIT(&n2); + SAE_BN_INIT(&n3); + + if (n3 == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("%s: allocate fail\n", __func__)); + ecc_point_free(ec_point_res); + return; + } + + ecc_point_init(&res); + + if (res == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s: ecc allocate fail\n", __func__)); + ecc_point_free(ec_point_res); + return; + } + + SAE_BN_INIT(&res->x); + SAE_BN_INIT(&res->y); + SAE_BN_INIT(&res->z); + + /* n1 */ + if (point->z_is_one) { + SAE_BN_MOD_SQR(point->x, ec_group_bi->prime, &n0); + SAE_BN_MOD_LSHIFT1(n0, ec_group_bi->prime, &n1); + SAE_BN_MOD_ADD_QUICK(n0, n1, ec_group_bi->prime, &n0); + SAE_BN_MOD_ADD_QUICK(n0, ec_group_bi->a, ec_group_bi->prime, &n1); + /* n1 = 3 * X_a^2 + a_curve */ + } else if (ec_group_bi->is_minus_3) { + SAE_BN_MOD_SQR(point->z, ec_group_bi->prime, &n1); + SAE_BN_MOD_ADD_QUICK(point->x, n1, ec_group_bi->prime, &n0); + SAE_BN_MOD_SUB_QUICK(point->x, n1, ec_group_bi->prime, &n2); + SAE_BN_MOD_MUL(n0, n2, ec_group_bi->prime, &n1); + SAE_BN_MOD_LSHIFT1(n1, ec_group_bi->prime, &n0); + SAE_BN_MOD_ADD_QUICK(n0, n1, ec_group_bi->prime, &n1); + /*- + * n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2) + * = 3 * X_a^2 - 3 * Z_a^4 + */ + } else { + SAE_BN_MOD_SQR(point->x, ec_group_bi->prime, &n0); + SAE_BN_MOD_LSHIFT1(n0, ec_group_bi->prime, &n1); + SAE_BN_MOD_ADD_QUICK(n0, n1, ec_group_bi->prime, &n0); + SAE_BN_MOD_SQR(point->z, ec_group_bi->prime, &n1); + SAE_BN_MOD_SQR(n1, ec_group_bi->prime, &n1); + SAE_BN_MOD_MUL(n1, ec_group_bi->a, ec_group_bi->prime, &n1); + SAE_BN_MOD_ADD_QUICK(n1, n0, ec_group_bi->prime, &n1); + /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */ + } + + /* Z_r */ + if (point->z_is_one) + SAE_BN_COPY(point->y, &n0); + else + SAE_BN_MOD_MUL(point->y, point->z, ec_group_bi->prime, &n0); + SAE_BN_MOD_LSHIFT1(n0, ec_group_bi->prime, &res->z); + res->z_is_one = 0; + /* Z_r = 2 * Y_a * Z_a */ + + /* n2 */ + SAE_BN_MOD_SQR(point->y, ec_group_bi->prime, &n3); + SAE_BN_MOD_MUL(point->x, n3, ec_group_bi->prime, &n2); + SAE_BN_MOD_LSHIFT(n2, 2, ec_group_bi->prime, &n2); + /* n2 = 4 * X_a * Y_a^2 */ + + /* X_r */ + SAE_BN_MOD_LSHIFT1(n2, ec_group_bi->prime, &n0); + SAE_BN_MOD_SQR(n1, ec_group_bi->prime, &res->x); + SAE_BN_MOD_SUB_QUICK(res->x, n0, ec_group_bi->prime, &res->x); + /* X_r = n1^2 - 2 * n2 */ + + /* n3 */ + SAE_BN_MOD_SQR(n3, ec_group_bi->prime, &n0); + SAE_BN_MOD_LSHIFT(n0, 3, ec_group_bi->prime, &n3); + /* n3 = 8 * Y_a^4 */ + + /* Y_r */ + SAE_BN_MOD_SUB_QUICK(n2, res->x, ec_group_bi->prime, &n0); + SAE_BN_MOD_MUL(n1, n0, ec_group_bi->prime, &n0); + SAE_BN_MOD_SUB_QUICK(n0, n3, ec_group_bi->prime, &res->y); + /* Y_r = n1 * (n2 - X_r) - n3 */ + + SAE_BN_FREE(&n0); + SAE_BN_FREE(&n1); + SAE_BN_FREE(&n2); + SAE_BN_FREE(&n3); + + ecc_point_copy(res, ec_point_res); + + ecc_point_free(&res); +} + + +VOID ecc_point_3d_to_2d( + IN EC_GROUP_INFO_BI *ec_group_bi, + INOUT BIG_INTEGER_EC_POINT *ec_point_res) +{ + SAE_BN *Z_1 = NULL; + SAE_BN *Z_2 = NULL; + SAE_BN *Z_3 = NULL; + SAE_BN *Z = ec_point_res->z; + SAE_BN *res_x = NULL; + SAE_BN *res_y = NULL; + SAE_BN *res_z = NULL; + UCHAR one[] = {1}; + + if (ec_point_res == NULL) + return; + if (ec_point_res->z_is_one) + return; + + if (ec_point_res->z == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("%s: z is null\n", __func__)); + return; + } + + SAE_BN_INIT(&Z_1); + SAE_BN_INIT(&Z_2); + SAE_BN_INIT(&Z_3); + SAE_BN_INIT(&res_x); + SAE_BN_INIT(&res_y); + SAE_BN_INIT(&res_z); + + /*- + * We have a curve defined by a Weierstrass equation + * y^2 = x^3 + a*x + b. + * The point to consider is given in Jacobian projective coordinates + * where (X, Y, Z) represents (x, y) = (X/Z^2, Y/Z^3). + * Substituting this and multiplying by Z^6 transforms the above equation into + * Y^2 = X^3 + a*X*Z^4 + b*Z^6. + * To test this, we add up the right-hand side in 'rh'. + */ + SAE_BN_MOD_MUL_INV(Z, ec_group_bi->prime, &Z_1); + SAE_BN_MOD_SQR(Z_1, ec_group_bi->prime, &Z_2); + SAE_BN_MOD_MUL(ec_point_res->x, Z_2, ec_group_bi->prime, &res_x); + SAE_BN_MOD_MUL(Z_2, Z_1, ec_group_bi->prime, &Z_3); + SAE_BN_MOD_MUL(ec_point_res->y, Z_3, ec_group_bi->prime, &res_y); + + SAE_BN_BIN2BI(one, sizeof(one), &res_z); + + SAE_BN_COPY(res_x, &ec_point_res->x); + SAE_BN_COPY(res_y, &ec_point_res->y); + SAE_BN_COPY(res_z, &ec_point_res->z); + ec_point_res->z_is_one = 1; + + SAE_BN_FREE(&Z_1); + SAE_BN_FREE(&Z_2); + SAE_BN_FREE(&Z_3); + SAE_BN_FREE(&res_x); + SAE_BN_FREE(&res_y); + SAE_BN_FREE(&res_z); +} + +VOID ecc_point_set_z_to_one( + INOUT BIG_INTEGER_EC_POINT *ec_point_res) +{ + UCHAR one[] = {1}; + + SAE_BN_BIN2BI(one, sizeof(one), &ec_point_res->z); + ec_point_res->z_is_one = 1; +} + + +#define W_POW 16 + +/* https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication */ +/* w-ary non-adjacent form (wNAF) method */ +VOID ecc_point_mul_wNAF( + IN BIG_INTEGER_EC_POINT *point, + IN SAE_BN *scalar, + IN EC_GROUP_INFO_BI *ec_group_bi, + OUT BIG_INTEGER_EC_POINT **ec_point_res) +{ + BIG_INTEGER_EC_POINT *p[W_POW / 2] = {NULL}; + BIG_INTEGER_EC_POINT *res = NULL; + SAE_BN *scalar_copy = NULL; + UINT32 i; + UINT32 *d; + UINT32 record = 0; + + SAE_LOG_TIME_BEGIN(&ec_op_ti_rec.mul_op); + + /* pre-compute {1, 3, ..., 2^(w-1) -1}P */ + ecc_point_copy(point, &p[0]); + ecc_point_double(p[0], ec_group_bi, &p[W_POW / 2 - 1]); + for (i = 0; i < W_POW / 4 - 1; i++) + ecc_point_add(p[i], p[W_POW / 2 - 1], ec_group_bi, &p[i + 1]); + for (i = 0; i < W_POW / 4; i++) { + ecc_point_copy(p[i], &p[W_POW / 2 - i - 1]); + ecc_point_inverse(p[W_POW / 2 - i - 1], ec_group_bi->prime, &p[W_POW / 2 - i - 1]); + } + os_alloc_mem(NULL, (UCHAR **)&d, sizeof(UINT32) * SAE_BN_GET_LEN(scalar) * 8); + NdisZeroMemory(d, sizeof(UINT32) * SAE_BN_GET_LEN(scalar) * 8); + SAE_BN_COPY(scalar, &scalar_copy); + + i = 0; + while (SAE_BN_IS_ZERO(scalar_copy) == FALSE) { + if (SAE_BN_IS_ODD(scalar_copy)) { + SAE_BN_MOD_DW(scalar_copy, W_POW, &d[i]); + if (d[i] >= W_POW / 2) + SAE_BN_ADD_DW(scalar_copy, W_POW); /* fix me */ + } else + d[i] = 0; + SAE_BN_RSHIFT1(scalar_copy, &scalar_copy); + i++; + } + i = SAE_BN_GET_LEN(scalar) * 8 - 1; + ecc_point_copy(point, &res); + do { + + ecc_point_double(res, ec_group_bi, &res); + if (d[i]) { + ecc_point_add(res, p[d[i]], ec_group_bi, &res); + record++; + } + i--; + } while (i != 0); + + ecc_point_copy(res, ec_point_res); + + os_free_mem(NULL, d); + + for (i = 0; i < W_POW / 2; i++) + ecc_point_free(&p[i]); + ecc_point_free(&res); + SAE_LOG_TIME_END(&ec_op_ti_rec.mul_op); + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_OFF, ("total cnt = %d!!!!!!\n", record + W_POW / 2)); +} + +/* https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication */ +/* windowed method */ +VOID ecc_point_mul_windowed( + IN BIG_INTEGER_EC_POINT *point, + IN SAE_BN *scalar, + IN EC_GROUP_INFO_BI *ec_group_bi, + OUT BIG_INTEGER_EC_POINT **ec_point_res) +{ + BIG_INTEGER_EC_POINT *p[W_POW / 2] = {NULL}; + BIG_INTEGER_EC_POINT *res = NULL; + SAE_BN *scalar_copy = NULL; + INT16 i; + UINT32 *d; + + SAE_LOG_TIME_BEGIN(&ec_op_ti_rec.mul_op); + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_INFO, + ("==> %s()\n", __func__)); + + POOL_COUNTER_CHECK_BEGIN(sae_expected_cnt[11]); + GET_BI_INS_FROM_POOL(scalar_copy); + + /* pre-compute {1, 3, ..., 2^(w-1) -1}P */ + ecc_point_copy(point, &p[0]); + ecc_point_double(p[0], ec_group_bi, &p[W_POW / 2 - 1]); + + for (i = 0; i < W_POW / 2 - 1; i++) + ecc_point_add(p[i], p[W_POW / 2 - 1], ec_group_bi, &p[i + 1]); + + os_alloc_mem(NULL, (UCHAR **)&d, sizeof(UINT32) * SAE_BN_GET_LEN(scalar) * 8); + NdisZeroMemory(d, sizeof(UINT32) * SAE_BN_GET_LEN(scalar) * 8); + SAE_BN_COPY(scalar, &scalar_copy); + + i = 0; + while (SAE_BN_IS_ZERO(scalar_copy) == FALSE) { + if (SAE_BN_IS_ODD(scalar_copy)) + SAE_BN_MOD_DW(scalar_copy, W_POW, &d[i]); + else + d[i] = 0; + SAE_BN_RSHIFT1(scalar_copy, &scalar_copy); + i++; + } + + i = SAE_BN_GET_LEN(scalar) * 8 - 1; + + do { + + ecc_point_double(res, ec_group_bi, &res); + if (d[i]) + ecc_point_add(res, p[(d[i] - 1) / 2], ec_group_bi, &res); + i--; + } while (i >= 0); + + ecc_point_copy(res, ec_point_res); + + os_free_mem(NULL, d); + + for (i = 0; i < W_POW / 2; i++) + ecc_point_free(&p[i]); + ecc_point_free(&res); + SAE_BN_RELEASE_BACK_TO_POOL(&scalar_copy); + POOL_COUNTER_CHECK_END(sae_expected_cnt[11]); + SAE_LOG_TIME_END(&ec_op_ti_rec.mul_op); +} + + + +/* (x,y) => (x, p-y) */ +VOID ecc_point_inverse( + IN BIG_INTEGER_EC_POINT *point, + IN SAE_BN *prime, + OUT BIG_INTEGER_EC_POINT **point_res) +{ + BIG_INTEGER_EC_POINT *res = NULL; + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("==> %s()\n", __func__)); + + if (point == NULL) { + ecc_point_free(point_res); + return; + } + + ecc_point_copy(point, &res); + SAE_BN_SUB(prime, point->y, &res->y); + ecc_point_copy(res, point_res); + ecc_point_free(&res); +} + +/* y^2 = x^3 + ax + b */ +UCHAR ecc_point_is_on_curve( + IN EC_GROUP_INFO_BI *ec_group_bi, + IN BIG_INTEGER_EC_POINT *point) +{ + SAE_BN *right = NULL; + SAE_BN *left = NULL; + SAE_BN *left2 = NULL; + UCHAR res; + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("==> %s()\n", __func__)); + + POOL_COUNTER_CHECK_BEGIN(sae_expected_cnt[12]); + GET_BI_INS_FROM_POOL(right); + GET_BI_INS_FROM_POOL(left); + GET_BI_INS_FROM_POOL(left2); + SAE_BN_INIT(&right); + SAE_BN_INIT(&left); + SAE_BN_INIT(&left2); + + SAE_LOG_TIME_BEGIN(&ec_op_ti_rec.on_curve_check_op); + SAE_BN_MOD_SQR(point->x, ec_group_bi->prime, &right); /* x^2 */ + SAE_BN_MOD_ADD(right, ec_group_bi->a, ec_group_bi->prime, &right); /* X^2+a */ + SAE_BN_MOD_MUL(point->x, right, ec_group_bi->prime, &right); /* x^3+ax */ + SAE_BN_MOD_ADD(right, ec_group_bi->b, ec_group_bi->prime, &right); /* x^3+ax+b */ + SAE_BN_MOD_SQR(point->y, ec_group_bi->prime, &left); /* y^2 */ + SAE_BN_SUB(ec_group_bi->prime, point->y, &left2); + SAE_BN_MOD_SQR(left2, ec_group_bi->prime, &left2); /* (p - y)^2 */ + + if (SAE_BN_UCMP(left, right) == 0 + || SAE_BN_UCMP(left2, right) == 0) + res = TRUE; + else + res = FALSE; + + SAE_BN_RELEASE_BACK_TO_POOL(&right); + SAE_BN_RELEASE_BACK_TO_POOL(&left); + SAE_BN_RELEASE_BACK_TO_POOL(&left2); + POOL_COUNTER_CHECK_END(sae_expected_cnt[12]); + SAE_LOG_TIME_END(&ec_op_ti_rec.on_curve_check_op); + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("%s(): res = %d\n", __func__, res)); + return res; +} + +/* Y^2 = X^3 + a*X*Z^4 + b*Z^6 */ +UCHAR ecc_point_is_on_curve_3d( + IN EC_GROUP_INFO_BI *ec_group_bi, + IN BIG_INTEGER_EC_POINT *point) +{ + SAE_BN *right = NULL; + SAE_BN *left = NULL; + SAE_BN *left2 = NULL; + SAE_BN *tmp = NULL; + SAE_BN *Z4 = NULL; + UCHAR res; + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("==> %s()\n", __func__)); + + if (point->z == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("ecc_point_is_on_curve_3d: z is NULL\n")); + return FALSE; + } + + GET_BI_INS_FROM_POOL(right); + GET_BI_INS_FROM_POOL(left); + GET_BI_INS_FROM_POOL(left2); + GET_BI_INS_FROM_POOL(tmp); + GET_BI_INS_FROM_POOL(Z4); + SAE_BN_INIT(&right); + SAE_BN_INIT(&left); + SAE_BN_INIT(&left2); + SAE_BN_INIT(&tmp); + SAE_BN_INIT(&Z4); + + SAE_BN_MOD_SQR(point->x, ec_group_bi->prime, &right); /* x^2 */ + SAE_BN_MOD_SQR(point->z, ec_group_bi->prime, &tmp); /* z^2 */ + SAE_BN_MOD_SQR(tmp, ec_group_bi->prime, &Z4); /* z^4 */ + SAE_BN_MOD_MUL(Z4, tmp, ec_group_bi->prime, &tmp); /* z^6 */ + SAE_BN_MOD_MUL(ec_group_bi->a, Z4, ec_group_bi->prime, &Z4); /* az^4 */ + SAE_BN_MOD_ADD(right, Z4, ec_group_bi->prime, &right); /* X^2+az^4 */ + SAE_BN_MOD_MUL(point->x, right, ec_group_bi->prime, &right); /* X^3+axz^4 */ + SAE_BN_MOD_MUL(ec_group_bi->b, tmp, ec_group_bi->prime, &tmp); /* bz^6 */ + SAE_BN_MOD_ADD(right, tmp, ec_group_bi->prime, &right); /* X^3+axz^4 + bz^6 */ + + SAE_BN_MOD_SQR(point->y, ec_group_bi->prime, &left); /* y^2 */ + SAE_BN_SUB(ec_group_bi->prime, point->y, &left2); + SAE_BN_MOD_SQR(left2, ec_group_bi->prime, &left2); /* (p - y)^2 */ + + + if (SAE_BN_UCMP(left, right) == 0 + || SAE_BN_UCMP(left2, right) == 0) + res = TRUE; + else + res = FALSE; + + SAE_BN_RELEASE_BACK_TO_POOL(&right); + SAE_BN_RELEASE_BACK_TO_POOL(&left); + SAE_BN_RELEASE_BACK_TO_POOL(&left2); + SAE_BN_RELEASE_BACK_TO_POOL(&tmp); + SAE_BN_RELEASE_BACK_TO_POOL(&Z4); + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("%s(): res = %d\n", __func__, res)); + return res; +} +#ifdef DOT11_SAE_OPENSSL_BN +#endif + + +/* ec_GFp_simple_set_compressed_coordinates */ +/* y^2 = x^3 + ax + b */ +UCHAR ecc_point_find_by_x( + IN EC_GROUP_INFO_BI *ec_group_bi, + IN SAE_BN *x, + IN SAE_BN **res_y, + IN UCHAR need_res_y) +{ + SAE_BN *res = NULL; + UCHAR has_y; + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_INFO, + ("==> %s()\n", __func__)); + + SAE_LOG_TIME_BEGIN(&ec_op_ti_rec.find_y_op); + SAE_BN_MOD_SQR(x, ec_group_bi->prime, &res); /* x^2 */ + SAE_BN_MOD_ADD(res, ec_group_bi->a, ec_group_bi->prime, &res); /* X^2+a */ + SAE_BN_MOD_MUL(x, res, ec_group_bi->prime, &res); /* x^3+ax */ + SAE_BN_MOD_ADD(res, ec_group_bi->b, ec_group_bi->prime, &res); /* x^3+ax+b */ + + if (SAE_BN_IS_QUADRATIC_RESIDE(res, ec_group_bi->prime, ec_group_bi->mont)) + has_y = TRUE; + else + has_y = FALSE; + + if (need_res_y && has_y) { + SAE_BN_MOD_SQRT(res, ec_group_bi->prime, ec_group_bi->mont, &res); + if (res) { + SAE_BN_COPY(res, res_y); + has_y = TRUE; + } else { + SAE_BN_FREE(res_y); + has_y = FALSE; + } + } + + SAE_BN_FREE(&res); + SAE_LOG_TIME_END(&ec_op_ti_rec.find_y_op); + return has_y; +} + + +VOID ecc_point_dump_time( + VOID) +{ + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, ECC_COST_TIME_DBG_LVL, ("ecc_point time record:\n")); + + if (ec_op_ti_rec.add_op.exe_times) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, ("add_op time record:\n")); + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, + ("\tavg_time=%lu jiffies", ec_op_ti_rec.add_op.avg_time_interval)); +#ifdef LINUX + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, + (", %u msec", jiffies_to_msecs(ec_op_ti_rec.add_op.avg_time_interval))); +#endif + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, ("\n\texe_times=%u\n", ec_op_ti_rec.add_op.exe_times)); + ec_op_ti_rec.add_op.avg_time_interval = 0; + ec_op_ti_rec.add_op.time_interval = 0; + ec_op_ti_rec.add_op.exe_times = 0; + } + + if (ec_op_ti_rec.dbl_op.exe_times) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, ("dbl_op time record:\n")); + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, + ("\tavg_time=%lu jiffies", ec_op_ti_rec.dbl_op.avg_time_interval)); +#ifdef LINUX + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, + (", %u msec", jiffies_to_msecs(ec_op_ti_rec.dbl_op.avg_time_interval))); +#endif + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, ("\n\texe_times=%u\n", ec_op_ti_rec.dbl_op.exe_times)); + ec_op_ti_rec.dbl_op.avg_time_interval = 0; + ec_op_ti_rec.dbl_op.time_interval = 0; + ec_op_ti_rec.dbl_op.exe_times = 0; + } + + if (ec_op_ti_rec.mul_op.exe_times) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, ("mul_op time record:\n")); + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, + ("\tavg_time=%lu jiffies", ec_op_ti_rec.mul_op.avg_time_interval)); +#ifdef LINUX + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, + (", %u msec", jiffies_to_msecs(ec_op_ti_rec.mul_op.avg_time_interval))); +#endif + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, ("\n\texe_times=%u\n", ec_op_ti_rec.mul_op.exe_times)); + ec_op_ti_rec.mul_op.avg_time_interval = 0; + ec_op_ti_rec.mul_op.time_interval = 0; + ec_op_ti_rec.mul_op.exe_times = 0; + } + + if (ec_op_ti_rec.find_y_op.exe_times) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, ("find_y_op time record:\n")); + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, + ("\tavg_time=%lu jiffies", ec_op_ti_rec.find_y_op.avg_time_interval)); +#ifdef LINUX + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, + (", %u msec", jiffies_to_msecs(ec_op_ti_rec.find_y_op.avg_time_interval))); +#endif + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, + ("\n\texe_times=%u\n", ec_op_ti_rec.find_y_op.exe_times)); + ec_op_ti_rec.find_y_op.avg_time_interval = 0; + ec_op_ti_rec.find_y_op.time_interval = 0; + ec_op_ti_rec.find_y_op.exe_times = 0; + } + + if (ec_op_ti_rec.on_curve_check_op.exe_times) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, ("on_curve_check_op time record:\n")); + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, + ("\tavg_time=%lu jiffies", + ec_op_ti_rec.on_curve_check_op.avg_time_interval)); +#ifdef LINUX + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, ECC_COST_TIME_DBG_LVL, + (", %u msec", + jiffies_to_msecs(ec_op_ti_rec.on_curve_check_op.avg_time_interval))); +#endif + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, ECC_COST_TIME_DBG_LVL, + ("\n\texe_times=%u\n", + ec_op_ti_rec.on_curve_check_op.exe_times)); + ec_op_ti_rec.on_curve_check_op.avg_time_interval = 0; + ec_op_ti_rec.on_curve_check_op.time_interval = 0; + ec_op_ti_rec.on_curve_check_op.exe_times = 0; + } +} + + +INT ecc_gen_key(EC_GROUP_INFO *ec_group, + EC_GROUP_INFO_BI *ec_group_bi, + INOUT SAE_BN **priv_key, + BIG_INTEGER_EC_POINT *generator, + INOUT VOID **pub_key) +{ + SAE_BN *priv = NULL; + BIG_INTEGER_EC_POINT *pub = NULL; + + if (*priv_key == NULL) { + SAE_BN_INIT(&priv); + if (priv == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, DBG_LVL_OFF, + ("%s, cannot alloc BN for priv\n", __func__)); + return 0; + } + *priv_key = priv; + } else + priv = *priv_key; + + do { + if (!SAE_GET_RAND_RANGE(priv, ec_group_bi->order)) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, DBG_LVL_OFF, + ("%s, derive priv_key failed\n", __func__)); + return 0; + } + } while (SAE_BN_IS_ZERO(priv)); + + if (*pub_key == NULL) { + ecc_point_init(&pub); + if (pub == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_ECC, DBG_LVL_OFF, + ("%s, cannot alloc POINT for pub\n", __func__)); + return 0; + } + *pub_key = pub; + } else + pub = *pub_key; + + ECC_POINT_MUL(generator, priv, ec_group_bi, &pub); + SAE_ECC_3D_to_2D(ec_group_bi, pub); + + return 1; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ee_efuse.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ee_efuse.c new file mode 100644 index 000000000..ffea30f4f --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ee_efuse.c @@ -0,0 +1,1404 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + ee_efuse.c + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef RTMP_EFUSE_SUPPORT + +#include "rt_config.h" + +static VOID eFuseWritePhysical( + IN PRTMP_ADAPTER pAd, + PUSHORT lpInBuffer, + ULONG nInBufferSize, + PUCHAR lpOutBuffer, + ULONG nOutBufferSize); + + +static VOID EFUSE_IO_READ32(PRTMP_ADAPTER pAd, UINT32 reg, UINT32 *value) +{ +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { +#ifdef RTMP_MAC_PCI + UINT32 RestoreValue; + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, MT_EEF_BASE - 0x70000); + RTMP_IO_READ32(pAd, 0x80000 + (reg - MT_EEF_BASE) + 0x70000, value); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); +#endif + + } + else +#endif /* MT_MAC */ + RTMP_IO_READ32(pAd, reg, value); +} + + +static VOID EFUSE_IO_WRITE32(PRTMP_ADAPTER pAd, UINT32 reg, UINT32 value) +{ +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { +#ifdef RTMP_MAC_PCI + UINT32 RestoreValue; + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, MT_EEF_BASE - 0x70000); + RTMP_IO_WRITE32(pAd, 0x80000 + (reg - MT_EEF_BASE) + 0x70000, value); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); +#endif + + } + else +#endif /* MT_MAC */ + RTMP_IO_WRITE32(pAd, reg, value); +} + + +/* +======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + +======================================================================== +*/ +UCHAR eFuseReadRegisters(PRTMP_ADAPTER pAd, UINT16 Offset, UINT16 Length, UINT16* pData) +{ + EFUSE_CTRL_STRUC eFuseCtrlStruc; + INT32 i; + UINT32 efuseDataOffset; + UINT32 data=0; + UINT32 efuse_ctrl_reg = EFUSE_CTRL; + int ret; + RTMP_SEM_EVENT_WAIT(&(pAd->e2p_read_lock), ret); + + if(ret != 0) + DBGPRINT(RT_DEBUG_ERROR, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,ret)); + + + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + efuse_ctrl_reg = MT_EFUSE_CTRL; +#endif /* MT_MAC */ + + EFUSE_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word); + + /* Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.*/ + /*Use the eeprom logical address and covert to address to block number*/ + eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; + + /* Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 0.*/ + eFuseCtrlStruc.field.EFSROM_MODE = 0; + + /* Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure.*/ + eFuseCtrlStruc.field.EFSROM_KICK = 1; + + NdisMoveMemory(&data, &eFuseCtrlStruc, 4); + EFUSE_IO_WRITE32(pAd, efuse_ctrl_reg, data); + + + /* Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again.*/ + i = 0; + while(i < 500) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + RTMP_SEM_EVENT_UP(&(pAd->e2p_read_lock)); + return 0x3f; + } + /*rtmp.HwMemoryReadDword(EFUSE_CTRL, (DWORD *) &eFuseCtrlStruc, 4);*/ + EFUSE_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word); + + if(eFuseCtrlStruc.field.EFSROM_KICK == 0) + { + RtmpusecDelay(2); + break; + } + RtmpusecDelay(2); + i++; + } + + /*if EFSROM_AOUT is not found in physical address, write 0xffff*/ + if (eFuseCtrlStruc.field.EFSROM_AOUT == 0x3f) + { + for(i = 0; i < Length / 2; i++) { + *(pData +2 * i) = 0xffff; + } + + RTMP_SEM_EVENT_UP(&(pAd->e2p_read_lock)); + return 0x3f; + } else { +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + if (!eFuseCtrlStruc.field.EFSROM_DOUT_VLD) { + + for(i = 0; i < Length / 2; i++){ + *(pData +2 * i) = 0xffff; + } + + RTMP_SEM_EVENT_UP(&(pAd->e2p_read_lock)); + return 0x3f; + } + } +#endif /* MT_MAC */ + + /*Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x590-0x59C)*/ +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + efuseDataOffset = MT_EFUSE_RDATA0 + (Offset & 0xC); + else +#endif /* MT_MAC */ + efuseDataOffset = EFUSE_DATA3 - (Offset & 0xC); + + + /*data hold 4 bytes data.*/ + /*In EFUSE_IO_READ32 will automatically execute 32-bytes swapping*/ + + EFUSE_IO_READ32(pAd, efuseDataOffset, &data); + + /*Decide the upper 2 bytes or the bottom 2 bytes.*/ + /* Little-endian S | S Big-endian*/ + /* addr 3 2 1 0 | 0 1 2 3*/ + /* Ori-V D C B A | A B C D*/ + /*After swapping*/ + /* D C B A | D C B A*/ + /*Return 2-bytes*/ + /*The return byte statrs from S. Therefore, the little-endian will return BA, the Big-endian will return DC.*/ + /*For returning the bottom 2 bytes, the Big-endian should shift right 2-bytes.*/ +#ifdef RT_BIG_ENDIAN + data = data << (8*((Offset & 0x3)^0x2)); +#else + data = data >> (8*(Offset & 0x3)); +#endif /* RT_BIG_ENDIAN */ + + NdisMoveMemory(pData, &data, Length); + + } + + RTMP_SEM_EVENT_UP(&(pAd->e2p_read_lock)); + return eFuseCtrlStruc.field.EFSROM_AOUT; +} + + +VOID EfusePhysicalReadRegisters(PRTMP_ADAPTER pAd, UINT16 Offset, + UINT16 Length, UINT16* pData) +{ + EFUSE_CTRL_STRUC EfuseCtrlStruc; + INT32 Index; + UINT32 EfuseDataOffset; + UINT32 Data; + UINT32 EfuseCtrlReg = EFUSE_CTRL; + + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + EfuseCtrlReg = MT_EFUSE_CTRL; +#endif /* MT_MAC */ + + EFUSE_IO_READ32(pAd, EfuseCtrlReg, &EfuseCtrlStruc.word); + + /*Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.*/ + EfuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; + + /*Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 1.*/ + /*Read in physical view*/ + EfuseCtrlStruc.field.EFSROM_MODE = 1; + + /*Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure.*/ + EfuseCtrlStruc.field.EFSROM_KICK = 1; + + NdisMoveMemory(&Data, &EfuseCtrlStruc, 4); + EFUSE_IO_WRITE32(pAd, EfuseCtrlReg, Data); + + /*Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again.*/ + Index = 0; + + while (Index < 500) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + EFUSE_IO_READ32(pAd, EfuseCtrlReg, &EfuseCtrlStruc.word); + + if(EfuseCtrlStruc.field.EFSROM_KICK == 0) + { + RtmpusecDelay(2); + break; + } + + RtmpusecDelay(2); + Index++; + } + + DBGPRINT(RT_DEBUG_INFO, ("EfuseCtrlStruc.field.EFSROM_AOUT = %x\n", EfuseCtrlStruc.field.EFSROM_AOUT)); + + DBGPRINT(RT_DEBUG_INFO, ("EfuseCtrlStruc.field.EFSROM_DOUT_VLD = %x\n", EfuseCtrlStruc.field.EFSROM_DOUT_VLD)); + + /*if EFSROM_AOUT is not found in physical address, write 0xffff*/ + if (EfuseCtrlStruc.field.EFSROM_AOUT == 0x3f) + { + for(Index = 0; Index < Length / 2; Index++) + { + *(pData + 2 * Index) = 0xffff; + } + DBGPRINT(RT_DEBUG_ERROR, ("EfuseCtrlStruc.field.EFSROM_AOUT = %x\n", EfuseCtrlStruc.field.EFSROM_AOUT)); + return; + } + else + { + if (pAd->chipCap.hif_type == HIF_MT) + { + if (!EfuseCtrlStruc.field.EFSROM_DOUT_VLD) { + + for(Index = 0; Index < Length / 2; Index++) + { + *(pData + 2 * Index) = 0xffff; + } + + DBGPRINT(RT_DEBUG_OFF, ("EfuseCtrlStruc.field.EFSROM_DOUT_VLD = %x\n", EfuseCtrlStruc.field.EFSROM_DOUT_VLD)); + return; + } + } + } + + + /*Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590)*/ + /*Because the size of each EFUSE_DATA is 4 Bytes, the size of address of each is 2 bits.*/ + /*The previous 2 bits is the EFUSE_DATA number, the last 2 bits is used to decide which bytes*/ + /*Decide which EFUSE_DATA to read*/ + /*590:F E D C */ + /*594:B A 9 8 */ + /*598:7 6 5 4*/ + /*59C:3 2 1 0*/ +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + EfuseDataOffset = MT_EFUSE_RDATA0 + (Offset & 0xC); + else +#endif /* MT_MAC */ + EfuseDataOffset = EFUSE_DATA3 - (Offset & 0xC) ; + + EFUSE_IO_READ32(pAd, EfuseDataOffset , &Data); + +#ifdef RT_BIG_ENDIAN + Data = Data << (8 *((Offset & 0x3)^0x2)); +#else + Data = Data >> (8 * (Offset & 0x3)); +#endif /* RT_BIG_ENDIAN */ + + NdisMoveMemory(pData, &Data, Length); +} + + +/* +======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + +======================================================================== +*/ +VOID eFuseReadPhysical( + IN PRTMP_ADAPTER pAd, + IN PUSHORT lpInBuffer, + IN ULONG nInBufferSize, + OUT PUSHORT lpOutBuffer, + IN ULONG nOutBufferSize +) +{ + USHORT* pInBuf = (USHORT*)lpInBuffer; + USHORT* pOutBuf = (USHORT*)lpOutBuffer; + + USHORT Offset = pInBuf[0]; /*addr*/ + USHORT Length = pInBuf[1]; /*length*/ + INT32 i; + + for(i = 0; i < Length; i+=2) + { + EfusePhysicalReadRegisters(pAd, Offset + i, 2, &pOutBuf[i/2]); + } +} + + +/* +======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + +======================================================================== +*/ +NTSTATUS eFuseRead( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + OUT PUSHORT pData, + IN USHORT Length) +{ + NTSTATUS Status = STATUS_SUCCESS; + int i; + + for(i = 0; i < Length; i+=2) + { + eFuseReadRegisters(pAd, Offset+i, 2, &pData[i/2]); + } + return Status; +} + + +/* +======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + +======================================================================== +*/ +static VOID eFusePhysicalWriteRegisters( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Length, + OUT USHORT* pData) +{ + EFUSE_CTRL_STRUC eFuseCtrlStruc; + int i; + UINT32 efuseDataOffset; + UINT32 efuse_rdata = EFUSE_DATA3, efuse_wdata = EFUSE_DATA3; + UINT32 data, eFuseDataBuffer[4]; + UINT32 efuse_ctrl_reg = EFUSE_CTRL; + + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + efuse_ctrl_reg = MT_EFUSE_CTRL; + efuse_rdata = MT_EFUSE_RDATA0; + efuse_wdata = MT_EFUSE_WDATA0; + } +#endif /* MT_MAC */ + + /*Step0. Write 16-byte of data to EFUSE_DATA0-3 (0x590-0x59C), where EFUSE_DATA0 is the LSB DW, EFUSE_DATA3 is the MSB DW.*/ + + /*read current values of 16-byte block */ + EFUSE_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word); + + /*Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.*/ + eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; + + /*Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 1.*/ + eFuseCtrlStruc.field.EFSROM_MODE = 1; + + /*Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure.*/ + eFuseCtrlStruc.field.EFSROM_KICK = 1; + + NdisMoveMemory(&data, &eFuseCtrlStruc, 4); + EFUSE_IO_WRITE32(pAd, efuse_ctrl_reg, data); + + /*Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again.*/ + i = 0; + while(i < 500) + { + EFUSE_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word); + + if(eFuseCtrlStruc.field.EFSROM_KICK == 0) + { + RtmpusecDelay(2); + break; + } + RtmpusecDelay(2); + i++; + } + + /*Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590)*/ + efuseDataOffset = efuse_rdata; + + for (i = 0; i < 4; i++) + { + EFUSE_IO_READ32(pAd, efuseDataOffset, (PUINT32) &eFuseDataBuffer[i]); +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + efuseDataOffset += 4; + else +#endif /* MT_MAC */ + efuseDataOffset -= 4; + } + + /*Update the value, the offset is multiple of 2, length is 2*/ + efuseDataOffset = (Offset & 0xc) >> 2; + data = pData[0] & 0xffff; + /*The offset should be 0x***10 or 0x***00*/ + if((Offset % 4) != 0) + { + eFuseDataBuffer[efuseDataOffset] = (eFuseDataBuffer[efuseDataOffset] & 0xffff) | (data << 16); + } + else + { + eFuseDataBuffer[efuseDataOffset] = (eFuseDataBuffer[efuseDataOffset] & 0xffff0000) | data; + } + + efuseDataOffset = efuse_wdata; + + for(i = 0; i < 4; i++) + { + EFUSE_IO_WRITE32(pAd, efuseDataOffset, eFuseDataBuffer[i]); +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + efuseDataOffset += 4; + else +#endif /* MT_MAC */ + efuseDataOffset -= 4; + } + + /*Step1. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment.*/ + // TODO: shiang, for below line, windows driver didn't have this read, why we have ?? + EFUSE_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word); + + eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; + + /*Step2. Write EFSROM_MODE (0x580, bit7:bit6) to 3.*/ + eFuseCtrlStruc.field.EFSROM_MODE = 3; + + /*Step3. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical write procedure.*/ + eFuseCtrlStruc.field.EFSROM_KICK = 1; + + NdisMoveMemory(&data, &eFuseCtrlStruc, 4); + EFUSE_IO_WRITE32(pAd, efuse_ctrl_reg, data); + + /*Step4. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. It's done.*/ + i = 0; + + while (i < 500) + { + EFUSE_IO_READ32(pAd, efuse_ctrl_reg, &eFuseCtrlStruc.word); + + if(eFuseCtrlStruc.field.EFSROM_KICK == 0) + { + RtmpusecDelay(2); + break; + } + + RtmpusecDelay(2); + i++; + } +} + +/* +======================================================================== + + Routine Description: + + Arguments: + + Return Value: + + Note: + +======================================================================== +*/ +static NTSTATUS eFuseWriteRegisters( + IN PRTMP_ADAPTER pAd, + IN USHORT Offset, + IN USHORT Length, + IN USHORT* pData) +{ + USHORT i,Loop=0, StartBlock=0, EndBlock=0; + USHORT eFuseData[2]; + USHORT LogicalAddress, BlkNum = 0xffff; + UCHAR EFSROM_AOUT; + + USHORT addr,tmpaddr, InBuf[3], tmpOffset; + USHORT buffer[8]; + BOOLEAN bWriteSuccess = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters Offset=%x, pData=%x\n", Offset, *pData)); + /*set start block and end block number, start from tail of mapping table*/ + if( (pAd->chipCap.EFUSE_USAGE_MAP_END % 2) != 0) + { + StartBlock = pAd->chipCap.EFUSE_USAGE_MAP_END-1; + } + else + { + StartBlock = pAd->chipCap.EFUSE_USAGE_MAP_END; + } + + if( (pAd->chipCap.EFUSE_USAGE_MAP_START % 2) != 0) + { + EndBlock = pAd->chipCap.EFUSE_USAGE_MAP_START-1; + } + else + { + EndBlock = pAd->chipCap.EFUSE_USAGE_MAP_START; + } + /*Step 0. find the entry in the mapping table*/ + /*The address of EEPROM is 2-bytes alignment.*/ + /*The last bit is used for alignment, so it must be 0.*/ + tmpOffset = Offset & 0xfffe; + EFSROM_AOUT = eFuseReadRegisters(pAd, tmpOffset, 2, &eFuseData[0]); + if (EFSROM_AOUT == 0x3f) + { /*find available logical address pointer */ + /*the logical address does not exist, find an empty one*/ + /*from the first address of block 45=16*45=0x2d0 to the last address of block 47*/ + /*==>48*16-3(reserved)=2FC*/ + for (i=StartBlock; i >= EndBlock; i-=2) + { + /*Retrive the logical block nubmer form each logical address pointer*/ + /*It will access two logical address pointer each time.*/ + EfusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); + /*To avoid the odd byte problem, ex. We read the 21|20 bytes and if 21 is the */ + /* end byte. Then, the EFUSE_USAGE_MAP_END which is 21 is not equal to*/ + /* i which is 20. Therefore, this 21th byte could be used.*/ + /*Otherwise, if 20 is the stop byte, i which is 20 is equal EFUSE_USAGE_MAP_END.*/ + /* It means the 21th byte could not be used.*/ + if(( (LogicalAddress >> 8) & 0xff) == 0) + {/*Not used logical address pointer*/ + if (i != pAd->chipCap.EFUSE_USAGE_MAP_END) + { + BlkNum = i-pAd->chipCap.EFUSE_USAGE_MAP_START+1; + break; + } + + } + + if( (LogicalAddress & 0xff) == 0) + {/*Not used logical address pointer*/ + if (i != (pAd->chipCap.EFUSE_USAGE_MAP_START-1)) + { + BlkNum = i-pAd->chipCap.EFUSE_USAGE_MAP_START; + break; + } + } + + } + } + else + { + BlkNum = EFSROM_AOUT; + } + + DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters BlkNum = %d \n", BlkNum)); + + if(BlkNum == 0xffff) + { + DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n")); + return FALSE; + } + + /*Step 1. Save data of this block which is pointed by the avaible logical address pointer*/ + /* read and save the original block data*/ + for(i =0; i<8; i++) + { + addr = BlkNum * 0x10 ; + + InBuf[0] = addr+2*i; + InBuf[1] = 2; + InBuf[2] = 0x0; + + eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); + + buffer[i] = InBuf[2]; + } + + /*Step 2. Update the data in buffer, and write the data to Efuse*/ + buffer[ (Offset >> 1) % 8] = pData[0]; + + do + { Loop++; + /*Step 3. Write the data to Efuse*/ + if(!bWriteSuccess) + { + for(i =0; i<8; i++) + { + addr = BlkNum * 0x10 ; + + InBuf[0] = addr+2*i; + InBuf[1] = 2; + InBuf[2] = buffer[i]; + + eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2); + } + } + else + { + addr = BlkNum * 0x10 ; + + InBuf[0] = addr+(Offset % 16); + InBuf[1] = 2; + InBuf[2] = pData[0]; + + eFuseWritePhysical(pAd, &InBuf[0], 6, NULL, 2); + } + + /*Step 4. Write mapping table*/ + addr = pAd->chipCap.EFUSE_USAGE_MAP_START+BlkNum; + + tmpaddr = addr; + + if(addr % 2 != 0) + addr = addr -1; + InBuf[0] = addr; + InBuf[1] = 2; + + /*convert the address from 10 to 8 bit ( bit7, 6 = parity and bit5 ~ 0 = bit9~4), and write to logical map entry*/ + tmpOffset = Offset; + tmpOffset >>= 4; + tmpOffset |= ((~((tmpOffset & 0x01) ^ ( tmpOffset >> 1 & 0x01) ^ (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01))) << 6) & 0x40; + tmpOffset |= ((~( (tmpOffset >> 2 & 0x01) ^ (tmpOffset >> 3 & 0x01) ^ (tmpOffset >> 4 & 0x01) ^ ( tmpOffset >> 5 & 0x01))) << 7) & 0x80; + + /* write the logical address*/ + if(tmpaddr%2 != 0) + InBuf[2] = tmpOffset<<8; + else + InBuf[2] = tmpOffset; + + eFuseWritePhysical(pAd,&InBuf[0], 6, NULL, 0); + + /*Step 5. Compare data if not the same, invalidate the mapping entry, then re-write the data until E-fuse is exhausted*/ + bWriteSuccess = TRUE; + for(i =0; i<8; i++) + { + addr = BlkNum * 0x10 ; + + InBuf[0] = addr+2*i; + InBuf[1] = 2; + InBuf[2] = 0x0; + + eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); + + if(buffer[i] != InBuf[2]) + { + bWriteSuccess = FALSE; + break; + } + } + + /*Step 6. invlidate mapping entry and find a free mapping entry if not succeed*/ + if (!bWriteSuccess) + { + DBGPRINT(RT_DEBUG_TRACE, ("Not bWriteSuccess BlkNum = %d\n", BlkNum)); + + /* the offset of current mapping entry*/ + addr = pAd->chipCap.EFUSE_USAGE_MAP_START+BlkNum; + + /*find a new mapping entry*/ + BlkNum = 0xffff; + for (i=StartBlock; i >= EndBlock; i-=2) + { + EfusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); + if(( (LogicalAddress >> 8) & 0xff) == 0) + { + if(i != pAd->chipCap.EFUSE_USAGE_MAP_END) + { + BlkNum = i+1-pAd->chipCap.EFUSE_USAGE_MAP_START; + break; + } + } + + if( (LogicalAddress & 0xff) == 0) + { + if(i != (pAd->chipCap.EFUSE_USAGE_MAP_START-1)) + { + BlkNum = i-pAd->chipCap.EFUSE_USAGE_MAP_START; + break; + } + } + } + DBGPRINT(RT_DEBUG_TRACE, ("Not bWriteSuccess and allocate new BlkNum = %d\n", BlkNum)); + if(BlkNum == 0xffff) + { + DBGPRINT(RT_DEBUG_TRACE, ("eFuseWriteRegisters: out of free E-fuse space!!!\n")); + return FALSE; + } + + /*invalidate the original mapping entry if new entry is not found*/ + tmpaddr = addr; + + if(addr % 2 != 0) + addr = addr -1; + InBuf[0] = addr; + InBuf[1] = 2; + + eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); + + /* write the logical address*/ + if(tmpaddr%2 != 0) + { + /* Invalidate the high byte*/ + for (i=8; i<15; i++) + { + if( ( (InBuf[2] >> i) & 0x01) == 0) + { + InBuf[2] |= (0x1 <> i) & 0x01) == 0) + { + InBuf[2] |= (0x1 <>8; + pValueX=OddWriteByteBuf; + + } + + for(i=0; ibUseEfuse == FALSE) + return FALSE; + + eFuseGetFreeBlockCount(pAd, &free_num); + DBGPRINT(RT_DEBUG_OFF, ("efuseFreeNumber = %d\n", free_num)); + return TRUE; +} + + +INT set_eFusedump_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + USHORT InBuf[3]; + INT i = 0; + + if (pAd->bUseEfuse == FALSE) + return FALSE; + + for (i = 0; i < pAd->chipCap.EFUSE_USAGE_MAP_END/2; i++) + { + InBuf[0] = 2*i; + InBuf[1] = 2; + InBuf[2] = 0x0; + + eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); + + if (i%4 == 0) + DBGPRINT(RT_DEBUG_OFF, ("\nBlock %x:", i/8)); + DBGPRINT(RT_DEBUG_OFF, ("%04x ", InBuf[2])); + } + return TRUE; +} + + +INT set_eFuseLoadFromBin_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + RTMP_STRING *src; + RTMP_OS_FD srcf; + RTMP_OS_FS_INFO osfsInfo; + INT retval, memSize; + RTMP_STRING *buffer, *memPtr; + INT TotalByte= 0; + //USHORT *PDATA; + UCHAR all_ff[16] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + UCHAR *ptr; + UCHAR index; + USHORT offset = 0; + USHORT value; + + memSize = 128 + MAX_EEPROM_BIN_FILE_SIZE + sizeof(USHORT) * 8; +/* memPtr = kmalloc(memSize, MEM_ALLOC_FLAG);*/ + os_alloc_mem(NULL, (UCHAR **)&memPtr, memSize); + if (memPtr == NULL) + return FALSE; + + NdisZeroMemory(memPtr, memSize); + src = memPtr; /* kmalloc(128, MEM_ALLOC_FLAG);*/ + buffer = src + 128; /* kmalloc(MAX_EEPROM_BIN_FILE_SIZE, MEM_ALLOC_FLAG);*/ + //PDATA = (USHORT*)(buffer + MAX_EEPROM_BIN_FILE_SIZE); /* kmalloc(sizeof(USHORT)*8,MEM_ALLOC_FLAG);*/ + ptr = buffer; + + if(strlen(arg)>0) + NdisMoveMemory(src, arg, strlen(arg)); + else + NdisMoveMemory(src, EEPROM_DEFULT_BIN_FILE, strlen(EEPROM_DEFULT_BIN_FILE)); + DBGPRINT(RT_DEBUG_OFF, ("FileName=%s\n",src)); + + RtmpOSFSInfoChange(&osfsInfo, TRUE); + + srcf = RtmpOSFileOpen(src, O_RDONLY, 0); + if (IS_FILE_OPEN_ERR(srcf)) + { + DBGPRINT_ERR(("--> Error opening file %s\n", src)); + retval = FALSE; + goto recoverFS; + } + else + { + /* The object must have a read method*/ + while(RtmpOSFileRead(srcf, &buffer[TotalByte], 1)==1) + { + TotalByte++; + if(TotalByte>MAX_EEPROM_BIN_FILE_SIZE) + { + DBGPRINT(RT_DEBUG_ERROR, ("--> Error reading file %s, file size too large[>%d]\n", src, MAX_EEPROM_BIN_FILE_SIZE)); + retval = FALSE; + goto closeFile; + } + } + + retval = RtmpOSFileClose(srcf); + if (retval) + DBGPRINT(RT_DEBUG_TRACE, ("--> Error closing file %s\n", src)); + } + + + RtmpOSFSInfoChange(&osfsInfo, FALSE); + + for ( offset = 0 ; offset < TotalByte ; offset += 16 ) + { + if ( memcmp( ptr, all_ff, 16 ) ) + { + DBGPRINT(RT_DEBUG_TRACE, ("offset 0x%04x: ", offset)); + for ( index = 0 ; index < 16 ; index += 2 ) + { + value = *(USHORT *)(ptr + index); + //eFuseWrite(pAd, offset + index ,&value, 2); + DBGPRINT(RT_DEBUG_TRACE, ("0x%04x ", value)); + } + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + } + + ptr += 16; + } + + return TRUE; + +closeFile: + if (srcf) + if (RtmpOSFileClose(srcf) != 0) + retval = FALSE; + +recoverFS: + RtmpOSFSInfoChange(&osfsInfo, FALSE); + + + if (memPtr) +/* kfree(memPtr);*/ + os_free_mem(NULL, memPtr); + + return retval; +} + + + +BOOLEAN rtmp_ee_efuse_read16(RTMP_ADAPTER *pAd, UINT16 Offset, UINT16 *pValue) +{ + UCHAR Value; + + Value = eFuseReadRegisters(pAd, Offset, 2, pValue); + + if (Value == 0x3F) + { + DBGPRINT(RT_DEBUG_INFO, ("%s: Not found valid block for this offset (%x)\n", __FUNCTION__, Offset)); + + return TRUE; + } + else + { + return FALSE; + } +} + + +int rtmp_ee_efuse_write16( + IN RTMP_ADAPTER *pAd, + IN USHORT Offset, + IN USHORT data) +{ + eFuseWrite(pAd,Offset ,&data, 2); + return 0; +} + +int RtmpEfuseSupportCheck( + IN RTMP_ADAPTER *pAd) +{ + USHORT value; + + if (IS_RT30xx(pAd) || IS_RT3593(pAd)) + { + EfusePhysicalReadRegisters(pAd, EFUSE_TAG, 2, &value); + pAd->EFuseTag = (value & 0xff); + } + return 0; +} + +INT rtmp_ee_write_to_efuse( + IN PRTMP_ADAPTER pAd) +{ + USHORT length = pAd->chipCap.EEPROM_DEFAULT_BIN_SIZE; + UCHAR *ptr = pAd->EEPROMImage; + UCHAR index; + UCHAR all_ff[16] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + USHORT offset = 0; + USHORT value; + + for ( offset = 0 ; offset < length ; offset += 16 ) + { + if ( memcmp( ptr, all_ff, 16 ) ) + { + DBGPRINT(RT_DEBUG_TRACE, ("offset 0x%04x: ", offset)); + for ( index = 0 ; index < 16 ; index += 2 ) + { + value = le2cpu16(*(USHORT *)(ptr + index)); + eFuseWrite(pAd, offset + index ,&value, 2); + DBGPRINT(RT_DEBUG_TRACE, ("0x%04x ", value)); + } + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + } + + ptr += 16; + } + + return TRUE; + +} + + +VOID eFuseGetFreeBlockCount(IN PRTMP_ADAPTER pAd, + PUINT EfuseFreeBlock) +{ + + USHORT i=0, StartBlock=0, EndBlock=0; + USHORT LogicalAddress; + USHORT FirstFreeBlock = 0xffff, LastFreeBlock = 0xffff; + +#ifndef CAL_FREE_IC_SUPPORT + if(!pAd->bUseEfuse) + { + DBGPRINT(RT_DEBUG_TRACE,("eFuseGetFreeBlockCount Only supports efuse Mode\n")); + return ; + } +#endif /* CAL_FREE_IC_SUPPORT */ + *EfuseFreeBlock = 0; + + + /* find first free block*/ + if( (pAd->chipCap.EFUSE_USAGE_MAP_START % 2) != 0) + { + StartBlock = pAd->chipCap.EFUSE_USAGE_MAP_START-1; + } + else + { + StartBlock = pAd->chipCap.EFUSE_USAGE_MAP_START; + } + + if( (pAd->chipCap.EFUSE_USAGE_MAP_END % 2) != 0) + { + EndBlock = pAd->chipCap.EFUSE_USAGE_MAP_END-1; + } + else + { + EndBlock = pAd->chipCap.EFUSE_USAGE_MAP_END; + } + + for (i = StartBlock; i <= EndBlock; i+=2) + { + EfusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); + + if( (LogicalAddress & 0xff) == 0) + { + if(i != (pAd->chipCap.EFUSE_USAGE_MAP_START-1)) + { + FirstFreeBlock = i; + break; + } + } + + if(( (LogicalAddress >> 8) & 0xff) == 0) + { + if(i != pAd->chipCap.EFUSE_USAGE_MAP_END) + { + FirstFreeBlock = i+1; + break; + } + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("eFuseGetFreeBlockCount, FirstFreeBlock= 0x%x\n", FirstFreeBlock)); + + /*if not find, return free block number = 0*/ + if(FirstFreeBlock == 0xffff) + { + *EfuseFreeBlock = 0; + return; + } + for (i = EndBlock; i >= StartBlock; i-=2) + { + EfusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); + + if(( (LogicalAddress >> 8) & 0xff) == 0) + { + if(i != pAd->chipCap.EFUSE_USAGE_MAP_END) + { + LastFreeBlock = i+1; + break; + } + } + + if( (LogicalAddress & 0xff) == 0) + { + if(i != (pAd->chipCap.EFUSE_USAGE_MAP_START-1)) + { + LastFreeBlock = i; + break; + } + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("eFuseGetFreeBlockCount, LastFreeBlock= 0x%x\n", LastFreeBlock)); + + /*if not find last free block, return free block number = 0, this should not happen since we have checked first free block number previously*/ + if(LastFreeBlock == 0xffff) + { + *EfuseFreeBlock = 0; + return; + } + + /* return total free block number, last free block number must >= first free block number*/ + if(LastFreeBlock < FirstFreeBlock) + { + *EfuseFreeBlock = 0; + } + else + { + *EfuseFreeBlock = LastFreeBlock - FirstFreeBlock + 1; + } + + DBGPRINT(RT_DEBUG_TRACE,("eFuseGetFreeBlockCount is %d\n",*EfuseFreeBlock)); +} + + +INT eFuse_init(RTMP_ADAPTER *pAd) +{ + UINT EfuseFreeBlock=0; + BOOLEAN bCalFree; + + /*RT3572 means 3062/3562/3572*/ + /*3593 means 3593*/ + DBGPRINT(RT_DEBUG_ERROR, ("NVM is Efuse and its size =%x[%x-%x] \n",pAd->chipCap.EFUSE_USAGE_MAP_SIZE,pAd->chipCap.EFUSE_USAGE_MAP_START,pAd->chipCap.EFUSE_USAGE_MAP_END)); + eFuseGetFreeBlockCount(pAd, &EfuseFreeBlock); + /*If the used block of efuse is less than 5. We assume the default value*/ + /* of this efuse is empty and change to the buffer mode in odrder to */ + /*bring up interfaces successfully.*/ + + + if (EfuseFreeBlock >= pAd->chipCap.EFUSE_RESERVED_SIZE) + { + + + DBGPRINT(RT_DEBUG_OFF, ("NVM is efuse and the information is too less to bring up the interface\n")); + DBGPRINT(RT_DEBUG_OFF, ("Load EEPROM buffer from BIN, and force to use BIN buffer mode\n")); + + pAd->bUseEfuse = FALSE; + rtmp_ee_load_from_bin(pAd); + + /* Forse to use BIN eeprom buffer mode */ + RtmpChipOpsEepromHook(pAd, pAd->infType,E2P_BIN_MODE); + +#ifdef CAL_FREE_IC_SUPPORT + RTMP_CAL_FREE_IC_CHECK(pAd,bCalFree); + if (bCalFree) + { + DBGPRINT(RT_DEBUG_OFF, ("Cal Free IC!!\n")); + RTMP_CAL_FREE_DATA_GET(pAd); + } + else + { + DBGPRINT(RT_DEBUG_OFF, ("Non Cal Free IC!!\n")); + } +#endif /* CAL_FREE_IC_SUPPORT */ + + } + else + { + rtmp_ee_load_from_efuse(pAd); + } + + return 0; +} + + +INT efuse_probe(RTMP_ADAPTER *pAd) +{ + UINT32 eFuseCtrl, ctrl_reg; + + if (WaitForAsicReady(pAd) == FALSE) + return -1; + + pAd->bUseEfuse=FALSE; + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + ctrl_reg = MT_EE_CTRL; + else +#endif /* MT_MAC */ + ctrl_reg = EFUSE_CTRL; + + EFUSE_IO_READ32(pAd, ctrl_reg, &eFuseCtrl); + + printk("%s: efuse = %x\n", __FUNCTION__, eFuseCtrl); + + if (pAd->chipCap.hif_type == HIF_MT) + { + if ((eFuseCtrl & 0x40000000) == 0x40000000) + pAd->bUseEfuse = 0; + else + pAd->bUseEfuse = 1; + } + else + { + pAd->bUseEfuse = ( (eFuseCtrl & 0x80000000) == 0x80000000) ? 1 : 0; + } + + return 0; +} + + +VOID rtmp_ee_load_from_efuse(RTMP_ADAPTER *pAd) +{ + UINT16 efuse_val=0; + UINT free_blk = 0; + UINT i; + + DBGPRINT(RT_DEBUG_OFF,("Load EEPROM buffer from efuse, and change to BIN buffer mode\n")); + + /* If the number of the used block is less than 5, assume the efuse is not well-calibrated, and force to use buffer mode */ + eFuseGetFreeBlockCount(pAd, &free_blk); + if (free_blk > (pAd->chipCap.EFUSE_USAGE_MAP_SIZE - 5)) + return ; + + NdisZeroMemory(pAd->EEPROMImage, MAX_EEPROM_BIN_FILE_SIZE); + for(i=0; iEEPROMImage[i],&efuse_val,2); + } + + /* Change to BIN eeprom buffer mode */ + RtmpChipOpsEepromHook(pAd, pAd->infType,E2P_BIN_MODE); +} + + +#ifdef CONFIG_ATE +INT Set_LoadEepromBufferFromEfuse_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT bEnable = simple_strtol(arg, 0, 10); + + + if (bEnable < 0) + return FALSE; + else + { + rtmp_ee_load_from_efuse(pAd); + return TRUE; + } +} + + +INT set_eFuseBufferModeWriteBack_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT bEnable = simple_strtol(arg, 0, 10); + + if (bEnable < 0) + return FALSE; + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s::Write EEPROM buffer back to eFuse\n", __FUNCTION__)); + Set_EepromBufferWriteBack_Proc(pAd, "1"); + return TRUE; + } +} + + +INT set_BinModeWriteBack_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT bEnable = simple_strtol(arg, 0, 10); + + if (bEnable < 0) + return FALSE; + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s::Write EEPROM buffer back to BIN\n", __FUNCTION__)); + Set_EepromBufferWriteBack_Proc(pAd, "4"); + + return TRUE; + } +} + +#endif /* CONFIG_ATE */ +#endif /* RTMP_EFUSE_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ee_flash.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ee_flash.c new file mode 100644 index 000000000..1efc83587 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ee_flash.c @@ -0,0 +1,531 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + ee_flash.c + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef RTMP_FLASH_SUPPORT + +#include "rt_config.h" +#include +#include +#ifdef MT7603 +#define EEPROM_FILE_NAME "MT7603E1E2_EEPROM_layout_2014011_ePAeLNA.bin" +#endif /* RT3090 */ + +MODULE_LICENSE("GPL"); + + + +#define EEPROM_DFT_FILE_DIR "/etc_ro/wlan/" +#ifdef EEPROM_1ST_FILE_DIR +#undef EEPROM_1ST_FILE_DIR +#define EEPROM_1ST_FILE_DIR "/etc_ro/Wireless/RT2860/" +#endif +#define EEPROM_2ND_FILE_DIR "/etc_ro/Wireless/iNIC/" + +#if defined(RTMP_RBUS_SUPPORT) || defined(RTMP_FLASH_SUPPORT) +/* The flag "CONFIG_RALINK_FLASH_API" is used for APSoC Linux SDK */ +#ifdef CONFIG_PROPRIETARY_DRIVER +static void flash_bin_read(RTMP_ADAPTER *ad, UCHAR *p, ULONG a, ULONG b) +{ + UCHAR *buffer = NULL; + UINT32 len; + UCHAR *name = get_dev_eeprom_binary(ad); + /*load from request firmware*/ + os_load_code_from_bin(ad, &buffer, name, &len); + + if (len > 0 && buffer != NULL) { + os_move_mem(p, buffer + a, b); + os_free_mem(NULL, buffer); + } +} +static void flash_bin_write(UCHAR *p, ULONG a, ULONG b) +{ + DBGPRINT(RT_DEBUG_ERROR, + ("proprietary driver not support flash write, will write on ated.\n")); +} +#define flash_read(_ad, _ptr, _offset, _len) flash_bin_read(_ad, _ptr, _offset, _len) +#define flash_write(_ptr, _offset, _len) flash_bin_write(_ptr, _offset, _len) + +#else +#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 flash_read(_ad, _ptr, _offset, _len) FlashRead((uint16_t *)_ptr, (uint16_t *)_offset, (uint32_t)_len) +#define flash_write(_ptr, _offset, _len) FlashWrite(_ptr, _offset, _len) + +#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); +#define flash_read(_ad, _ptr, _offset, _len) ra_mtd_read(MTD_NUM_FACTORY, 0, (size_t)_len, _ptr) +#define flash_write(_ptr, _offset, _len) ra_mtd_write(MTD_NUM_FACTORY, 0, (size_t)_len, _ptr) + +#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); +#define flash_read(_ad, _ptr, _offset, _len) ra_mtd_read_nm("Factory", _offset&0xFFFF, (size_t)_len, _ptr) +#define flash_write(_ptr, _offset, _len) ra_mtd_write_nm("Factory", _offset&0xFFFF, (size_t)_len, _ptr) + +#endif + +#endif /* CONFIG_RALINK_FLASH_API */ +#endif /*CONFIG_PROPRIETERY_DRIVER*/ + +void RtmpFlashRead( + RTMP_ADAPTER *ad, + UCHAR *p, + ULONG a, + ULONG b) +{ + size_t retlen; + struct mtd_info *mtd_info = get_mtd_device_nm("factory"); + if (IS_ERR(mtd_info) || mtd_info == NULL) { + printk("ERROR: failed to find 'Factory' mtd partiton\n"); + return; + } + mtd_read(mtd_info, a, b, &retlen, p); + put_mtd_device(mtd_info); +} + +void RtmpFlashWrite( + UCHAR *p, + ULONG a, + ULONG b) +{ + size_t retlen; + struct mtd_info *mtd_info = get_mtd_device_nm("factory"); + if (IS_ERR(mtd_info) || mtd_info == NULL) { + printk("ERROR: failed to find 'Factory' mtd partiton\n"); + return; + } + mtd_write(mtd_info, a, b, &retlen, p); + put_mtd_device(mtd_info); +} + + + +#endif /* defined(RTMP_RBUS_SUPPORT) || defined(RTMP_FLASH_SUPPORT) */ + + +static NDIS_STATUS rtmp_ee_flash_init(PRTMP_ADAPTER pAd, PUCHAR start); + +static USHORT EE_FLASH_ID_LIST[]={ + + + + + +#ifdef MT7603 + 0x7603, +#endif +}; + +#ifndef EE_FLASH_ID_NUM +#define EE_FLASH_ID_NUM (sizeof(EE_FLASH_ID_LIST) / sizeof(USHORT)) +#endif + + +/******************************************************************************* + * + * 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. + * + ******************************************************************************/ +BOOLEAN rtmp_ee_flash_read(PRTMP_ADAPTER pAd, UINT16 Offset, UINT16 *pValue) +{ + BOOLEAN IsEmpty = 0; + + if (!pAd->chipCap.ee_inited) + { + *pValue = 0xffff; + } + else + { + memcpy(pValue, pAd->eebuf + Offset, 2); + } + + if ((*pValue == 0xffff) || (*pValue == 0x0000)) + IsEmpty = 1; + + return IsEmpty; +} + + +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], get_dev_eeprom_size(pAd)); +#else + RtmpFlashWrite(pAd->eebuf, pAd->flash_offset, get_dev_eeprom_size(pAd)); +#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, get_dev_eeprom_size(pAd)); +} + + +VOID rtmp_ee_flash_write_all(PRTMP_ADAPTER pAd, USHORT *Data) +{ + if (!pAd->chipCap.ee_inited) + return; + memcpy(pAd->eebuf, Data, get_dev_eeprom_size(pAd)); +#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], get_dev_eeprom_size(pAd)); +#else + RtmpFlashWrite(pAd->eebuf, pAd->flash_offset, get_dev_eeprom_size(pAd)); +#endif /* MULTIPLE_CARD_SUPPORT */ +} + + +static NDIS_STATUS rtmp_ee_flash_reset(RTMP_ADAPTER *pAd, UCHAR *start) +{ + PUCHAR src; + RTMP_OS_FS_INFO osFsInfo; + RTMP_OS_FD srcf; + INT retval; + +#ifdef RT_SOC_SUPPORT +#ifdef MULTIPLE_CARD_SUPPORT + RTMP_STRING BinFilePath[128]; + RTMP_STRING *pBinFileName = NULL; + UINT32 ChipVerion = (pAd->MACVersion >> 16); + + if (rtmp_get_default_bin_file_by_chip(pAd, ChipVerion, &pBinFileName) == TRUE) + { + if (pAd->MC_RowID > 0) + sprintf(BinFilePath, "%s%s", EEPROM_2ND_FILE_DIR, pBinFileName); + else + sprintf(BinFilePath, "%s%s", EEPROM_1ST_FILE_DIR, pBinFileName); + + src = BinFilePath; + DBGPRINT(RT_DEBUG_TRACE, ("%s(): src = %s\n", __FUNCTION__, src)); + } + else +#endif /* MULTIPLE_CARD_SUPPORT */ +#endif /* RT_SOC_SUPPORT */ + { +#ifdef MT7603 + if (IS_MT7603(pAd)) + { + src = EEPROM_DEFAULT_7603_FILE_PATH; + } + else +#endif /* MT_MAC */ + { + 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)); + if ( pAd->chipCap.EEPROM_DEFAULT_BIN != NULL ) + { + NdisMoveMemory(start, pAd->chipCap.EEPROM_DEFAULT_BIN, + pAd->chipCap.EEPROM_DEFAULT_BIN_SIZE > MAX_EEPROM_BUFFER_SIZE?MAX_EEPROM_BUFFER_SIZE:pAd->chipCap.EEPROM_DEFAULT_BIN_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("Load EEPROM Buffer from default BIN.\n")); + return NDIS_STATUS_SUCCESS; + } + else + return NDIS_STATUS_FAILURE; + } + else + { + /* The object must have a read method*/ + NdisZeroMemory(start, get_dev_eeprom_size(pAd)); + + retval = RtmpOSFileRead(srcf, start, get_dev_eeprom_size(pAd)); + if (retval < 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("--> Read %s error %d\n", src, -retval)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("--> rtmp_ee_flash_reset copy %s to eeprom buffer\n", src)); + } + + retval = RtmpOSFileClose(srcf); + if (retval) + { + DBGPRINT(RT_DEBUG_TRACE, ("--> Error %d closing %s\n", -retval, src)); + } + } + } + + RtmpOSFSInfoChange(&osFsInfo, FALSE); + + return NDIS_STATUS_SUCCESS; +} + +#ifdef LINUX +/* 0 -- Show ee buffer */ +/* 1 -- force reset to default */ +/* 2 -- Change ee settings */ +int Set_EECMD_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR arg) +{ + USHORT i; + + i = simple_strtol(arg, 0, 10); + switch(i) + { + case 0: + { + USHORT value, k; + for (k = 0; k < get_dev_eeprom_size(pAd); 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); + } + + rtmp_ee_flash_read(pAd, 0, &i); + + if ((i != 0x2880) && (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]) + { +#ifdef MT7603 + if (IS_MT7603(pAd)) + { + if (eeFlashId != 0x7603) + return FALSE; + } +#endif /* MT7603 */ + return TRUE; + } + } + return FALSE; +} + + +static NDIS_STATUS rtmp_ee_flash_init(PRTMP_ADAPTER pAd, PUCHAR start) +{ +#ifdef CAL_FREE_IC_SUPPORT + BOOLEAN bCalFree=0; +#endif /* CAL_FREE_IC_SUPPORT */ + + pAd->chipCap.ee_inited = 1; + + if (validFlashEepromID(pAd) == FALSE) + { + if (rtmp_ee_flash_reset(pAd, start) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR, ("rtmp_ee_init(): rtmp_ee_flash_init() failed\n")); + return NDIS_STATUS_FAILURE; + } + +#ifdef CAL_FREE_IC_SUPPORT + RTMP_CAL_FREE_IC_CHECK(pAd,bCalFree); + if (bCalFree) + { + //MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("Cal Free IC!!\n")); + DBGPRINT(RT_DEBUG_OFF, ("rtmp_ee_flash_init() Cal Free IC!!\n")); + RTMP_CAL_FREE_DATA_GET(pAd); + } + else + { + DBGPRINT(RT_DEBUG_OFF, ("rtmp_ee_flash_init() Non Cal Free IC!!\n")); + } + +#endif /* CAL_FREE_IC_SUPPORT */ + + + /* 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; + *(UINT16 *)(&pAd->EEPROMImage[0x08]) = le2cpu16(Addr45); + DBGPRINT(RT_DEBUG_ERROR, ("The EEPROM in Flash is wrong, use default\n")); + } + + /*write back all to flash*/ + rtmp_ee_flash_write_all(pAd,(USHORT *)pAd->EEPROMImage); + + if (validFlashEepromID(pAd) == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, ("rtmp_ee_flash_init(): invalid eeprom\n")); + return NDIS_STATUS_FAILURE; + } + } + + return NDIS_STATUS_SUCCESS; +} + + +NDIS_STATUS rtmp_nv_init(RTMP_ADAPTER *pAd) +{ +#ifdef MULTIPLE_CARD_SUPPORT + UCHAR *eepromBuf; +#endif /* MULTIPLE_CARD_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("--> rtmp_nv_init\n")); + + +/* + if (pAd->chipCap.EEPROMImage == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("pAd->chipCap.EEPROMImage == NULL!!!\n")); + return NDIS_STATUS_FAILURE; + } +*/ + +/* ASSERT((pAd->eebuf == NULL)); */ + pAd->eebuf = pAd->EEPROMImage; +#ifdef MULTIPLE_CARD_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("rtmp_nv_init:pAd->MC_RowID = %d\n", pAd->MC_RowID)); + os_alloc_mem(pAd, &eepromBuf, get_dev_eeprom_size(pAd)); + if (eepromBuf) + { + pAd->eebuf = eepromBuf; + NdisMoveMemory(pAd->eebuf, pAd->chipCap.EEPROM_DEFAULT_BIN, get_dev_eeprom_size(pAd)); + } + 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, pAd->eebuf, pAd->E2P_OFFSET_IN_FLASH[pAd->MC_RowID], get_dev_eeprom_size(pAd)); +#else + RtmpFlashRead(pAd, pAd->eebuf, pAd->flash_offset, get_dev_eeprom_size(pAd)); +#endif /* MULTIPLE_CARD_SUPPORT */ + + return rtmp_ee_flash_init(pAd, pAd->eebuf); +} + +#endif /* RTMP_FLASH_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ee_prom.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ee_prom.c new file mode 100644 index 000000000..043c1a994 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ee_prom.c @@ -0,0 +1,269 @@ +/* + *************************************************************************** + * 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(RTMP_ADAPTER *pAd, 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(RTMP_ADAPTER *pAd, UINT32 *x) +{ + *x = *x & ~EESK; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x); + RtmpusecDelay(1); +} + + +/* IRQL = PASSIVE_LEVEL*/ +static inline USHORT ShiftInBits(RTMP_ADAPTER *pAd) +{ + UINT32 x,i; + UINT16 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(RTMP_ADAPTER *pAd, USHORT data, 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(RTMP_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(RTMP_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(RTMP_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*/ +BOOLEAN rtmp_ee_prom_read16(RTMP_ADAPTER *pAd, UINT16 Offset, UINT16 *pValue) +{ + UINT32 x; + UINT16 data; + BOOLEAN IsEmpty = 0; + + + 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; + + if ( IsEmpty == 0x0000 ) + IsEmpty = 1; + + return IsEmpty; +} + + +int rtmp_ee_prom_write16(RTMP_ADAPTER *pAd, USHORT Offset, UINT16 Data) +{ + UINT32 x; + + + + Offset /= 2; + + EWEN(pAd); + + /* reset bits and set EECS*/ + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + x &= ~(EEDI | EEDO | EESK); + x |= EECS; + RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); + + /* patch can not access e-Fuse issue*/ + if (IS_RT2860(pAd)) + { + /* kick a pulse*/ + RaiseClock(pAd, &x); + LowerClock(pAd, &x); + } + + /* output the read_opcode ,register number and data in that order */ + ShiftOutBits(pAd, EEPROM_WRITE_OPCODE, 3); + ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum); + ShiftOutBits(pAd, Data, 16); /* 16-bit access*/ + + /* read DO status*/ + RTMP_IO_READ32(pAd, E2PROM_CSR, &x); + + EEpromCleanup(pAd); + + RtmpusecDelay(10000); /*delay for twp(MAX)=10ms*/ + + EWDS(pAd); + + EEpromCleanup(pAd); + + + return NDIS_STATUS_SUCCESS; + +} + + +INT rtmp_ee_write_to_prom(RTMP_ADAPTER *pAd) +{ + USHORT value, offset = 0; + + { + for (offset = 0; offset < (EEPROM_SIZE >> 1);) + { + value = ((PUSHORT)pAd->EEPROMImage)[offset]; + RT28xx_EEPROM_WRITE16(pAd, (offset << 1), value); + offset++; + } + } + + return TRUE; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/eeprom.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/eeprom.c new file mode 100644 index 000000000..3909c506b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/eeprom.c @@ -0,0 +1,1134 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + eeprom.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ +#include "rt_config.h" + +struct chip_map{ + UINT32 ChipVersion; + RTMP_STRING *name; +}; + +struct chip_map RTMP_CHIP_E2P_FILE_TABLE[] = { + {0x3071, "RT3092_PCIe_LNA_2T2R_ALC_V1_2.bin"}, + {0x3090, "RT3092_PCIe_LNA_2T2R_ALC_V1_2.bin"}, + {0x3593, "HMC_RT3593_PCIe_3T3R_V1_3.bin"}, + {0x5392, "RT5392_PCIe_2T2R_ALC_V1_4.bin"}, + {0x5592, "RT5592_PCIe_2T2R_V1_7.bin"}, + {0,} +}; + + +struct chip_map chip_card_id_map[] ={ + {7620, ""}, +}; + + +INT rtmp_read_txmixer_gain_from_eeprom(RTMP_ADAPTER *pAd) +{ + UINT16 value; + + /* + Get TX mixer gain setting + 0xff are invalid value + Note: + RT30xx default value is 0x00 and will program to RF_R17 + only when this value is not zero + RT359x default value is 0x02 + */ + if (IS_RT30xx(pAd) || IS_RT3572(pAd) || IS_RT3593(pAd) + || IS_RT5390(pAd) || IS_RT5392(pAd) || IS_RT5592(pAd) + || IS_RT3290(pAd) || IS_RT65XX(pAd) || IS_MT7601(pAd)) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXMIXER_GAIN_2_4G, value); + pAd->TxMixerGain24G = 0; + value &= 0x00ff; + if (value != 0xff) + { + value &= 0x07; + pAd->TxMixerGain24G = (UCHAR)value; + } + + } + + + return TRUE; +} + + +INT rtmp_read_rssi_langain_from_eeprom(RTMP_ADAPTER *pAd) +{ + INT i; + UINT16 value; + + /* Get RSSI Offset on EEPROM 0x9Ah & 0x9Ch.*/ + /* The valid value are (-10 ~ 10) */ + /* */ + { + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET, value); + pAd->BGRssiOffset[0] = value & 0x00ff; + pAd->BGRssiOffset[1] = (value >> 8); + } + + { + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_BG_OFFSET+2, value); + { +/* if (IS_RT2860(pAd)) RT2860 supports 3 Rx and the 2.4 GHz RSSI #2 offset is in the EEPROM 0x48*/ + pAd->BGRssiOffset[2] = value & 0x00ff; + pAd->ALNAGain1 = (value >> 8); + } + } + + { + RT28xx_EEPROM_READ16(pAd, EEPROM_LNA_OFFSET, value); + pAd->BLNAGain = value & 0x00ff; + /* External LNA gain for 5GHz Band(CH36~CH64) */ + pAd->ALNAGain0 = (value >> 8); + } + + + { + RT28xx_EEPROM_READ16(pAd, EEPROM_RSSI_A_OFFSET, value); + pAd->ARssiOffset[0] = value & 0x00ff; + pAd->ARssiOffset[1] = (value >> 8); + } + + { + RT28xx_EEPROM_READ16(pAd, (EEPROM_RSSI_A_OFFSET+2), value); + { + pAd->ARssiOffset[2] = value & 0x00ff; + pAd->ALNAGain2 = (value >> 8); + } + } + + + if (((UCHAR)pAd->ALNAGain1 == 0xFF) || (pAd->ALNAGain1 == 0x00)) + pAd->ALNAGain1 = pAd->ALNAGain0; + if (((UCHAR)pAd->ALNAGain2 == 0xFF) || (pAd->ALNAGain2 == 0x00)) + pAd->ALNAGain2 = pAd->ALNAGain0; + + DBGPRINT(RT_DEBUG_TRACE, ("ALNAGain0 = %d, ALNAGain1 = %d, ALNAGain2 = %d\n", + pAd->ALNAGain0, pAd->ALNAGain1, pAd->ALNAGain2)); + + /* Validate 11a/b/g RSSI 0/1/2 offset.*/ + for (i =0 ; i < 3; i++) + { + if ((pAd->BGRssiOffset[i] < -10) || (pAd->BGRssiOffset[i] > 10)) + pAd->BGRssiOffset[i] = 0; + + if ((pAd->ARssiOffset[i] < -10) || (pAd->ARssiOffset[i] > 10)) + pAd->ARssiOffset[i] = 0; + } + + return TRUE; +} + + +/* + CountryRegion byte offset (38h) +*/ +INT rtmp_read_country_region_from_eeporm(RTMP_ADAPTER *pAd) +{ + UINT16 value, value2; + + { + value = pAd->EEPROMDefaultValue[EEPROM_COUNTRY_REG_OFFSET] >> 8; /* 2.4G band*/ + value2 = pAd->EEPROMDefaultValue[EEPROM_COUNTRY_REG_OFFSET] & 0x00FF; /* 5G band*/ + } + + if ((value <= REGION_MAXIMUM_BG_BAND) || (value == REGION_31_BG_BAND) || (value == REGION_32_BG_BAND) || (value == REGION_33_BG_BAND) ) + pAd->CommonCfg.CountryRegion = ((UCHAR) value) | EEPROM_IS_PROGRAMMED; + + if (value2 <= REGION_MAXIMUM_A_BAND) + pAd->CommonCfg.CountryRegionForABand = ((UCHAR) value2) | EEPROM_IS_PROGRAMMED; + + return TRUE; +} + + +/* + Read frequency offset setting from EEPROM which used for RF +*/ +INT rtmp_read_freq_offset_from_eeprom(RTMP_ADAPTER *pAd) +{ + UINT16 value; + + RT28xx_EEPROM_READ16(pAd, EEPROM_FREQ_OFFSET, value); + + { + if ((value & 0x00FF) != 0x00FF) + pAd->RfFreqOffset = (ULONG) (value & 0x00FF); + else + pAd->RfFreqOffset = 0; + } + + + + DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: RF FreqOffset=0x%x \n", pAd->RfFreqOffset)); + + return TRUE; +} + + +INT rtmp_read_txpwr_from_eeprom(RTMP_ADAPTER *pAd) +{ + /* if not return early. cause fail at emulation.*/ + /* Init the channel number for TX channel power*/ +#ifdef MT7603 + if (IS_MT7603(pAd)) + mt7603_read_chl_pwr(pAd); + else +#endif + RTMPReadChannelPwr(pAd); + + RTMPReadTxPwrPerRate(pAd); + + + +#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 */ + + return TRUE; +} + + +/* + ======================================================================== + + Routine Description: + Read initial parameters from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +INT NICReadEEPROMParameters(RTMP_ADAPTER *pAd, RTMP_STRING *mac_addr) +{ + USHORT i, value; + EEPROM_VERSION_STRUC Version; + EEPROM_ANTENNA_STRUC Antenna; + EEPROM_NIC_CONFIG2_STRUC NicConfig2; + USHORT Addr01,Addr23,Addr45 ; + + DBGPRINT(RT_DEBUG_TRACE, ("%s()-->\n", __FUNCTION__)); + + + 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 */ + + } + + /*Send EEprom parameter to FW*/ + #ifdef CONFIG_ATE + if(!ATE_ON(pAd)) + #endif + { +#ifdef LOAD_FW_ONE_TIME + DBGPRINT(RT_DEBUG_ERROR, ("@@@ NICReadEEPROMParameters : pAd->FWLoad=%u \n",pAd->FWLoad)); + if (pAd->FWLoad == 0) +#endif /* LOAD_FW_ONE_TIME */ + CmdEfusBufferModeSet(pAd); + } + + /* 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")); +#if defined(BB_SOC)&&!defined(NEW_MBSSID_MODE) + //BBUPrepareMAC(pAd, pAd->CurrentAddress); + COPY_MAC_ADDR(pAd->PermanentAddress, pAd->CurrentAddress); + printk("now bb MainSsid mac %02x:%02x:%02x:%02x:%02x:%02x\n",PRINT_MAC(pAd->CurrentAddress)); +#endif + } + else if (mac_addr && + strlen((RTMP_STRING *)mac_addr) == 17 && + (strcmp(mac_addr, "00:00:00:00:00:00") != 0)) + { + INT j; + RTMP_STRING *macptr; + + macptr = (RTMP_STRING *) 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")); + } + + /* if E2PROM version mismatch with driver's expectation, then skip*/ + /* all subsequent E2RPOM retieval and set a system error bit to notify GUI*/ + RT28xx_EEPROM_READ16(pAd, EEPROM_VERSION_OFFSET, Version.word); + pAd->EepromVersion = Version.field.Version + Version.field.FaeReleaseNumber * 256; + DBGPRINT(RT_DEBUG_TRACE, ("E2PROM: Version = %d, FAE release #%d\n", Version.field.Version, Version.field.FaeReleaseNumber)); + + /* Read BBP default value from EEPROM and store to array(EEPROMDefaultValue) in pAd */ + RT28xx_EEPROM_READ16(pAd, EEPROM_NIC1_OFFSET, value); + pAd->EEPROMDefaultValue[EEPROM_NIC_CFG1_OFFSET] = value; + + /* EEPROM offset 0x36 - NIC Configuration 1 */ + RT28xx_EEPROM_READ16(pAd, EEPROM_NIC2_OFFSET, value); + pAd->EEPROMDefaultValue[EEPROM_NIC_CFG2_OFFSET] = value; + NicConfig2.word = pAd->EEPROMDefaultValue[EEPROM_NIC_CFG2_OFFSET]; + + + { + RT28xx_EEPROM_READ16(pAd, EEPROM_COUNTRY_REGION, value); /* Country Region*/ + pAd->EEPROMDefaultValue[EEPROM_COUNTRY_REG_OFFSET] = value; + DBGPRINT(RT_DEBUG_OFF, ("Country Region from e2p = %x\n", value)); + } + + for(i = 0; i < 8; i++) + { +#if defined(RT65xx) || defined(MT7601) || defined(MT7603) || defined(MT7628)/* MT7650 EEPROM doesn't have those BBP setting @20121001 */ + if (IS_RT65XX(pAd) || IS_MT7601(pAd) || IS_MT7603(pAd) || IS_MT7628(pAd)) + break; +#endif /* defined(RT65xx) || defined(MT7601) || defined(MT7603) */ + + 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]; + + + + + + // TODO: shiang, why we only check oxff00?? + if (((Antenna.word & 0xFF00) == 0xFF00) || IS_MT76x2(pAd)) +/* if (Antenna.word == 0xFFFF)*/ + RTMP_CHIP_ANTENNA_INFO_DEFAULT_RESET(pAd, &Antenna); + +// TODO: shiang-7603 + if (IS_MT7603(pAd) || IS_MT7628(pAd)) + RTMP_CHIP_ANTENNA_INFO_DEFAULT_RESET(pAd, &Antenna); + + /* Choose the desired Tx&Rx stream.*/ + if ((pAd->CommonCfg.TxStream == 0) || (pAd->CommonCfg.TxStream > Antenna.field.TxPath)) + pAd->CommonCfg.TxStream = Antenna.field.TxPath; + + if ((pAd->CommonCfg.RxStream == 0) || (pAd->CommonCfg.RxStream > Antenna.field.RxPath)) + { + pAd->CommonCfg.RxStream = Antenna.field.RxPath; + + if ((pAd->MACVersion != RALINK_3883_VERSION) && + (pAd->MACVersion != RALINK_2883_VERSION) && + (pAd->CommonCfg.RxStream > 2)) + { + /* only 2 Rx streams for RT2860 series*/ + pAd->CommonCfg.RxStream = 2; + } + } + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("%s(): AfterAdjust, RxPath = %d, TxPath = %d\n", + __FUNCTION__, Antenna.field.RxPath, Antenna.field.TxPath)); + +#ifdef WSC_INCLUDED + /* WSC hardware push button function 0811 */ + if ((pAd->MACVersion == 0x28600100) || (pAd->MACVersion == 0x28700100)) + WSC_HDR_BTN_MR_HDR_SUPPORT_SET(pAd, NicConfig2.field.EnableWPSPBC); +#endif /* WSC_INCLUDED */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (NicConfig2.word == 0xffff) + NicConfig2.word = 0; + } +#endif /* CONFIG_AP_SUPPORT */ + + + 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, ("%s(): RxPath = %d, TxPath = %d, RfIcType = %d\n", + __FUNCTION__, Antenna.field.RxPath, Antenna.field.TxPath, + Antenna.field.RfIcType)); + + /* Save the antenna for future use*/ + pAd->Antenna.word = Antenna.word; + + /* Set the RfICType here, then we can initialize RFIC related operation callbacks*/ + pAd->Mlme.RealRxPath = (UCHAR) Antenna.field.RxPath; + pAd->RfIcType = (UCHAR) Antenna.field.RfIcType; + + + + +#ifdef MT7603 + if (IS_MT7603(pAd)) + pAd->RfIcType = RFIC_7603; +#endif /* MT7603 */ + + + pAd->phy_ctrl.rf_band_cap = NICGetBandSupported(pAd); + + /* check if the chip supports 5G band */ + if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + { + if (!RFIC_IS_5G_BAND(pAd)) + { + DBGPRINT_RAW(RT_DEBUG_ERROR, + ("%s():Err! chip not support 5G band %d!\n", + __FUNCTION__, pAd->RfIcType)); +#ifdef DOT11_N_SUPPORT + /* change to bgn mode */ + Set_WirelessMode_Proc(pAd, "9"); +#else + /* change to bg mode */ + Set_WirelessMode_Proc(pAd, "0"); +#endif /* DOT11_N_SUPPORT */ + pAd->phy_ctrl.rf_band_cap = RFIC_24GHZ; + } + pAd->phy_ctrl.rf_band_cap = RFIC_24GHZ | RFIC_5GHZ; + } + else + { + pAd->phy_ctrl.rf_band_cap = RFIC_24GHZ; + } + + + LoadTssiInfoFromEEPROM(pAd); + + pAd->BbpRssiToDbmDelta = 0x0; + + rtmp_read_freq_offset_from_eeprom(pAd); + + rtmp_read_country_region_from_eeporm(pAd); + + rtmp_read_rssi_langain_from_eeprom(pAd); + + rtmp_read_txmixer_gain_from_eeprom(pAd); + +#ifdef LED_CONTROL_SUPPORT + rtmp_read_led_setting_from_eeprom(pAd); +#endif /* LED_CONTROL_SUPPORT */ + + rtmp_read_txpwr_from_eeprom(pAd); + +#ifdef RTMP_EFUSE_SUPPORT + RtmpEfuseSupportCheck(pAd); +#endif /* RTMP_EFUSE_SUPPORT */ + +#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. + */ + value = pAd->EEPROMDefaultValue[EEPROM_NIC_CFG2_OFFSET]; + if (value == 0xFFFF) /*EEPROM is empty*/ + pAd->TxPowerCtrl.bInternalTxALC = FALSE; + else if (value & 1<<13) + pAd->TxPowerCtrl.bInternalTxALC = TRUE; + else + pAd->TxPowerCtrl.bInternalTxALC = FALSE; + } + DBGPRINT(RT_DEBUG_TRACE, ("TXALC> bInternalTxALC = %d\n", pAd->TxPowerCtrl.bInternalTxALC)); +#endif /* RTMP_INTERNAL_TX_ALC */ + + + + + + + DBGPRINT(RT_DEBUG_TRACE, ("%s: pAd->Antenna.field.BoardType = %d, IS_MINI_CARD(pAd) = %d, IS_RT5390U(pAd) = %d\n", + __FUNCTION__, + pAd->Antenna.field.BoardType, + IS_MINI_CARD(pAd), + IS_RT5390U(pAd))); + + DBGPRINT(RT_DEBUG_TRACE, ("<--%s()\n", __FUNCTION__)); + + return TRUE; +} + + +void rtmp_eeprom_of_platform(RTMP_ADAPTER *pAd) +{ +#if defined(CONFIG_RT_FIRST_CARD_EEPROM) || defined(CONFIG_RT_SECOND_CARD_EEPROM) + UCHAR e2p_dafault = 0; +#endif /* defined(CONFIG_RT_FIRST_CARD_EEPROM) || defined(CONFIG_RT_SECOND_CARD_EEPROM) */ +#ifdef CONFIG_RT_FIRST_CARD_EEPROM + if ( pAd->dev_idx == 0 ) + { + if ( RTMPEqualMemory("efuse", CONFIG_RT_FIRST_CARD_EEPROM, 5) ) + e2p_dafault = E2P_EFUSE_MODE; + if ( RTMPEqualMemory("prom", CONFIG_RT_FIRST_CARD_EEPROM, 4) ) + e2p_dafault = E2P_EEPROM_MODE; + if ( RTMPEqualMemory("flash", CONFIG_RT_FIRST_CARD_EEPROM, 5) ) + e2p_dafault = E2P_FLASH_MODE; + + pAd->E2pAccessMode = e2p_dafault; + } +#endif /* CONFIG_RT_FIRST_CARD_EEPROM */ + +#ifdef CONFIG_RT_SECOND_CARD_EEPROM + if ( pAd->dev_idx == 1 ) + { + if ( RTMPEqualMemory("efuse", CONFIG_RT_SECOND_CARD_EEPROM, 5) ) + e2p_dafault = E2P_EFUSE_MODE; + if ( RTMPEqualMemory("prom", CONFIG_RT_SECOND_CARD_EEPROM, 4) ) + e2p_dafault = E2P_EEPROM_MODE; + if ( RTMPEqualMemory("flash", CONFIG_RT_SECOND_CARD_EEPROM, 5) ) + e2p_dafault = E2P_FLASH_MODE; + + pAd->E2pAccessMode = e2p_dafault; + } +#endif /* CONFIG_RT_SECOND_CARD_EEPROM */ +} + +UCHAR RtmpEepromGetDefault(RTMP_ADAPTER *pAd) +{ + UCHAR e2p_dafault = 0; + +#ifdef RTMP_FLASH_SUPPORT + if (pAd->infType == RTMP_DEV_INF_RBUS) + e2p_dafault = E2P_FLASH_MODE; + else +#endif /* RTMP_FLASH_SUPPORT */ + { +#ifdef RTMP_EFUSE_SUPPORT + if (pAd->bUseEfuse) + e2p_dafault = E2P_EFUSE_MODE; + else +#endif /* RTMP_EFUSE_SUPPORT */ + e2p_dafault = E2P_EEPROM_MODE; + } + + DBGPRINT(RT_DEBUG_OFF, ("%s::e2p_dafault=%d\n", __FUNCTION__, e2p_dafault)); + return e2p_dafault; +} + + +#if defined(RTMP_EFUSE_SUPPORT) && defined(RTMP_FLASH_SUPPORT) +static USHORT EE_FLASH_ID_LIST[]={ + + + + + +#ifdef MT7603 + 0x7603, +#endif +}; + +#define EE_FLASH_ID_NUM (sizeof(EE_FLASH_ID_LIST) / sizeof(USHORT)) +#endif /* defined(RTMP_EFUSE_SUPPORT) && defined(RTMP_FLASH_SUPPORT) */ + + + + +static NDIS_STATUS rtmp_ee_bin_init(PRTMP_ADAPTER pAd) +{ +#ifdef CAL_FREE_IC_SUPPORT + BOOLEAN bCalFree=0; +#endif /* CAL_FREE_IC_SUPPORT */ + + rtmp_ee_load_from_bin(pAd); + +#ifdef CAL_FREE_IC_SUPPORT + RTMP_CAL_FREE_IC_CHECK(pAd,bCalFree); + if (bCalFree) + { + DBGPRINT(RT_DEBUG_OFF, ("Cal Free IC!!\n")); + RTMP_CAL_FREE_DATA_GET(pAd); + } + else + { + DBGPRINT(RT_DEBUG_OFF, ("Non Cal Free IC!!\n")); + } +#endif /* CAL_FREE_IC_SUPPORT */ + + return NDIS_STATUS_SUCCESS; +} + +#if defined(RTMP_EFUSE_SUPPORT) && defined(RTMP_FLASH_SUPPORT) +static VOID RtmpEepromTypeAdjust(RTMP_ADAPTER *pAd, UCHAR *pE2pType) +{ + UINT EfuseFreeBlock=0; + + eFuseGetFreeBlockCount(pAd, &EfuseFreeBlock); + + if (EfuseFreeBlock >= pAd->chipCap.EFUSE_RESERVED_SIZE) + { + DBGPRINT(RT_DEBUG_OFF, ("NVM is efuse and the information is too less to bring up the interface\n")); + DBGPRINT(RT_DEBUG_OFF, ("Force to use Flash mode\n")); + *pE2pType = E2P_FLASH_MODE; + } + else + { + USHORT eeFlashId = 0; + int listIdx; + BOOLEAN bFound = FALSE; + + rtmp_ee_efuse_read16(pAd, 0, &eeFlashId); + DBGPRINT(RT_DEBUG_OFF, ("%s:: eeFlashId = 0x%x.\n", __FUNCTION__, eeFlashId)); + for(listIdx =0 ; listIdx < EE_FLASH_ID_NUM; listIdx++) + { + if (eeFlashId == EE_FLASH_ID_LIST[listIdx]) + { + bFound = TRUE; + break; + } + } + + if (bFound == FALSE) + { + *pE2pType = E2P_FLASH_MODE; + } + } +} +#endif /* defined(RTMP_EFUSE_SUPPORT) && defined(RTMP_FLASH_SUPPORT) */ + +INT RtmpChipOpsEepromHook(RTMP_ADAPTER *pAd, INT infType,INT forceMode) +{ + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + UCHAR e2p_type; +#ifdef RTMP_PCI_SUPPORT + UINT32 val; +#endif /* RTMP_PCI_SUPPORT */ + UCHAR e2p_default = 0; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return -1; + +#ifdef RTMP_EFUSE_SUPPORT + efuse_probe(pAd); +#endif /* RTMP_EFUSE_SUPPORT */ + + rtmp_eeprom_of_platform(pAd); + + if(forceMode != E2P_NONE && forceMode < NUM_OF_E2P_MODE) + { + e2p_type = forceMode; + DBGPRINT(RT_DEBUG_OFF, ("%s::forceMode: %d , infType: %d\n", + __FUNCTION__, e2p_type, infType)); + } + else + { + e2p_type = pAd->E2pAccessMode; + + DBGPRINT(RT_DEBUG_OFF, ("%s::e2p_type=%d, inf_Type=%d\n", + __FUNCTION__, e2p_type, infType)); + + e2p_default = RtmpEepromGetDefault(pAd); + /* If e2p_type is out of range, get the default mode */ + e2p_type = ((e2p_type != 0) && (e2p_type < NUM_OF_E2P_MODE)) ? e2p_type : e2p_default; + + if (infType == RTMP_DEV_INF_RBUS) + { + e2p_type = E2P_FLASH_MODE; + pChipOps->loadFirmware = NULL; + } +#if defined(RTMP_EFUSE_SUPPORT) && defined(RTMP_FLASH_SUPPORT) + else if (pAd->E2pAccessMode == E2P_NONE) + { + /* + User doesn't set E2pAccessMode in profile, adjust access mode automatically here. + */ + RtmpEepromTypeAdjust(pAd, &e2p_type); + } +#endif /* defined(RTMP_EFUSE_SUPPORT) && defined(RTMP_FLASH_SUPPORT) */ + +#ifdef RTMP_EFUSE_SUPPORT + if (e2p_type != E2P_EFUSE_MODE) + pAd->bUseEfuse = FALSE; +#endif /* RTMP_EFUSE_SUPPORT */ + + DBGPRINT(RT_DEBUG_OFF, ("%s: E2P type(%d), E2pAccessMode = %d, E2P default = %d\n", __FUNCTION__, e2p_type, pAd->E2pAccessMode, e2p_default)); + pAd->eeprom_type = (e2p_type==E2P_EFUSE_MODE) ? EEPROM_EFUSE: EEPROM_FLASH; + } + + pAd->e2pCurMode = e2p_type; + + switch (e2p_type) + { + case E2P_EEPROM_MODE: + break; + case E2P_BIN_MODE: + { + pChipOps->eeinit = rtmp_ee_bin_init; + pChipOps->eeread = rtmp_ee_bin_read16; + pChipOps->eewrite = rtmp_ee_bin_write16; + DBGPRINT(RT_DEBUG_OFF, ("NVM is BIN mode\n")); + return 0; + } + +#ifdef RTMP_FLASH_SUPPORT + case E2P_FLASH_MODE: + { + pChipOps->eeinit = rtmp_nv_init; + pChipOps->eeread = rtmp_ee_flash_read; + pChipOps->eewrite = rtmp_ee_flash_write; + pAd->flash_offset = get_dev_eeprom_offset(pAd); +#ifdef CONFIG_RT_FIRST_CARD + if ( pAd->dev_idx == 0 ) + pAd->flash_offset = CONFIG_RT_FIRST_IF_RF_OFFSET; +#endif /* CONFIG_RT_FIRST_CARD */ +#ifdef CONFIG_RT_SECOND_CARD + if ( pAd->dev_idx == 1 ) + pAd->flash_offset = CONFIG_RT_SECOND_IF_RF_OFFSET; +#endif /* CONFIG_RT_FIRST_CARD */ + DBGPRINT(RT_DEBUG_OFF, ("NVM is FLASH mode, flash_offset = 0x%x\n", pAd->flash_offset)); + return 0; + } +#endif /* RTMP_FLASH_SUPPORT */ + +#ifdef RTMP_EFUSE_SUPPORT + case E2P_EFUSE_MODE: + if (pAd->bUseEfuse) + { + pChipOps->eeinit = eFuse_init; + pChipOps->eeread = rtmp_ee_efuse_read16; + pChipOps->eewrite = rtmp_ee_efuse_write16; + DBGPRINT(RT_DEBUG_OFF, ("NVM is EFUSE mode\n")); + return 0; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s::hook efuse mode failed\n", __FUNCTION__)); + break; + } +#endif /* RTMP_EFUSE_SUPPORT */ + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Do not support E2P type(%d), change to BIN mode\n", __FUNCTION__, e2p_type)); + + pChipOps->eeinit = rtmp_ee_bin_init; + pChipOps->eeread = rtmp_ee_bin_read16; + pChipOps->eewrite = rtmp_ee_bin_write16; + DBGPRINT(RT_DEBUG_OFF, ("NVM is BIN mode\n")); + return 0; + } + + /* Hook functions based on interface types for EEPROM */ + switch (infType) + { +#ifdef RTMP_PCI_SUPPORT + case RTMP_DEV_INF_PCI: + case RTMP_DEV_INF_PCIE: + RTMP_IO_READ32(pAd, E2PROM_CSR, &val); + if (((val & 0x30) == 0) && (!IS_RT3290(pAd))) + pAd->EEPROMAddressNum = 6; /* 93C46 */ + else + pAd->EEPROMAddressNum = 8; /* 93C66 or 93C86 */ + + pChipOps->eeinit = NULL; + pChipOps->eeread = rtmp_ee_prom_read16; + pChipOps->eewrite = rtmp_ee_prom_write16; + break; +#endif /* RTMP_PCI_SUPPORT */ + + + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s::hook failed\n", __FUNCTION__)); + break; + } + + DBGPRINT(RT_DEBUG_OFF, ("NVM is EEPROM mode\n")); + return 0; +} + + +BOOLEAN rtmp_get_default_bin_file_by_chip( + IN PRTMP_ADAPTER pAd, + IN UINT32 ChipVersion, + OUT RTMP_STRING **pBinFileName) +{ + BOOLEAN found = FALSE; + INT i; + for (i = 0; RTMP_CHIP_E2P_FILE_TABLE[i].ChipVersion != 0; i++ ) + { + if (RTMP_CHIP_E2P_FILE_TABLE[i].ChipVersion == ChipVersion) + { + *pBinFileName = RTMP_CHIP_E2P_FILE_TABLE[i].name; + DBGPRINT(RT_DEBUG_OFF, + ("%s(): Found E2P bin file name:%s\n", + __FUNCTION__, *pBinFileName)); + found = TRUE; + break; + } + } + + if (found == TRUE) + DBGPRINT(RT_DEBUG_OFF, ("%s::Found E2P bin file name=%s\n", __FUNCTION__, *pBinFileName)); + else + DBGPRINT(RT_DEBUG_ERROR, ("%s::E2P bin file name not found\n", __FUNCTION__)); + + return found; +} + + +BOOLEAN rtmp_ee_bin_read16(RTMP_ADAPTER *pAd, UINT16 Offset, UINT16 *pValue) +{ + BOOLEAN IsEmpty = 0; + + DBGPRINT(RT_DEBUG_INFO, ("%s::Read from EEPROM buffer\n", __FUNCTION__)); + NdisMoveMemory(pValue, &(pAd->EEPROMImage[Offset]), 2); + *pValue = le2cpu16(*pValue); + + if ((*pValue == 0xffff) || (*pValue == 0x0000)) + IsEmpty = 1; + + return IsEmpty; +} + + +INT rtmp_ee_bin_write16( + IN RTMP_ADAPTER *pAd, + IN USHORT Offset, + IN USHORT data) +{ + DBGPRINT(RT_DEBUG_INFO, ("%s::Write to EEPROM buffer\n", __FUNCTION__)); + data = le2cpu16(data); + NdisMoveMemory(&(pAd->EEPROMImage[Offset]), &data, 2); + + return 0; +} + + +INT rtmp_ee_load_from_bin( + IN PRTMP_ADAPTER pAd) +{ + RTMP_STRING *src = NULL; + INT ret_val; + RTMP_OS_FD srcf; + RTMP_OS_FS_INFO osFSInfo; + +#ifdef RT_SOC_SUPPORT +#ifdef MULTIPLE_CARD_SUPPORT + RTMP_STRING bin_file_path[128]; + RTMP_STRING *bin_file_name = NULL; + UINT32 chip_ver = (pAd->MACVersion >> 16); + + if (rtmp_get_default_bin_file_by_chip(pAd, chip_ver, &bin_file_name) == TRUE) + { + if (pAd->MC_RowID > 0) + sprintf(bin_file_path, "%s%s", EEPROM_2ND_FILE_DIR, bin_file_name); + else + sprintf(bin_file_path, "%s%s", EEPROM_1ST_FILE_DIR, bin_file_name); + + src = bin_file_path; + } + else +#endif /* MULTIPLE_CARD_SUPPORT */ +#endif /* RT_SOC_SUPPORT */ + src = BIN_FILE_PATH; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::FileName=%s\n", __FUNCTION__, src)); + + RtmpOSFSInfoChange(&osFSInfo, TRUE); + + if (src && *src) + { + srcf = RtmpOSFileOpen(src, O_RDONLY, 0); + if (IS_FILE_OPEN_ERR(srcf)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s::Error opening %s\n", __FUNCTION__, src)); + goto error; + } + else + { + NdisZeroMemory(pAd->EEPROMImage, MAX_EEPROM_BIN_FILE_SIZE); + ret_val = RtmpOSFileRead(srcf, (RTMP_STRING *)pAd->EEPROMImage, MAX_EEPROM_BIN_FILE_SIZE); + + if (ret_val > 0) + ret_val = NDIS_STATUS_SUCCESS; + else + DBGPRINT(RT_DEBUG_ERROR, ("%s::Read file \"%s\" failed(errCode=%d)!\n", __FUNCTION__, src, ret_val)); + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s::Error src or srcf is null\n", __FUNCTION__)); + goto error; + } + + ret_val = RtmpOSFileClose(srcf); + + if (ret_val) + DBGPRINT(RT_DEBUG_ERROR, ("%s::Error %d closing %s\n", __FUNCTION__, -ret_val, src)); + + RtmpOSFSInfoChange(&osFSInfo, FALSE); + return TRUE; + +error: + if (pAd->chipCap.EEPROM_DEFAULT_BIN != NULL) + { + NdisMoveMemory(pAd->EEPROMImage, pAd->chipCap.EEPROM_DEFAULT_BIN, + pAd->chipCap.EEPROM_DEFAULT_BIN_SIZE > MAX_EEPROM_BUFFER_SIZE?MAX_EEPROM_BUFFER_SIZE:pAd->chipCap.EEPROM_DEFAULT_BIN_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("Load EEPROM Buffer from default BIN.\n")); + } + + return FALSE; +} + + +INT rtmp_ee_write_to_bin( + IN PRTMP_ADAPTER pAd) +{ + RTMP_STRING *src = NULL; + INT ret_val; + RTMP_OS_FD srcf; + RTMP_OS_FS_INFO osFSInfo; + const INT PCI_EFUSE_SIZE = 10; + UCHAR pci_pm[PCI_EFUSE_SIZE]; + UCHAR pci_efuse[PCI_EFUSE_SIZE]; + INT i = 0; + +#ifdef RT_SOC_SUPPORT +#ifdef MULTIPLE_CARD_SUPPORT + RTMP_STRING bin_file_path[128]; + RTMP_STRING *bin_file_name = NULL; + UINT32 chip_ver = (pAd->MACVersion >> 16); + + if (rtmp_get_default_bin_file_by_chip(pAd, chip_ver, &bin_file_name) == TRUE) + { + if (pAd->MC_RowID > 0) + sprintf(bin_file_path, "%s%s", EEPROM_2ND_FILE_DIR, bin_file_name); + else + sprintf(bin_file_path, "%s%s", EEPROM_1ST_FILE_DIR, bin_file_name); + + src = bin_file_path; + } + else +#endif /* MULTIPLE_CARD_SUPPORT */ +#endif /* RT_SOC_SUPPORT */ + src = BIN_FILE_PATH; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::FileName=%s\n", __FUNCTION__, src)); + + RtmpOSFSInfoChange(&osFSInfo, TRUE); + + if (src && *src) + { + srcf = RtmpOSFileOpen(src, O_WRONLY|O_CREAT, 0); + + if (IS_FILE_OPEN_ERR(srcf)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s::Error opening %s\n", __FUNCTION__, src)); + return FALSE; + } + else + RtmpOSFileWrite(srcf, (RTMP_STRING *)pAd->EEPROMImage, MAX_EEPROM_BIN_FILE_SIZE); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s::Error src or srcf is null\n", __FUNCTION__)); + return FALSE; + } + + ret_val = RtmpOSFileClose(srcf); + + if (ret_val) + DBGPRINT(RT_DEBUG_ERROR, ("%s::Error %d closing %s\n", __FUNCTION__, -ret_val, src)); + + RtmpOSFSInfoChange(&osFSInfo, FALSE); +#ifdef RTMP_MAC_PCI +#ifdef MT7603 + NdisZeroMemory(pci_pm, PCI_EFUSE_SIZE); + NdisZeroMemory(pci_efuse, PCI_EFUSE_SIZE); + /* 0x26 ~ 0x2F */ + for(i=0;iEEPROMImage[0x26+i+1]; + buf_reg <<= 8; + buf_reg |= pAd->EEPROMImage[0x26+i]; + buf_reg = le2cpu16 (buf_reg); + NdisMoveMemory(&pci_pm[i], &buf_reg, 2); + } + eFuseRead(pAd, 0x26, (USHORT *)pci_efuse, PCI_EFUSE_SIZE); + + DBGPRINT(RT_DEBUG_TRACE, ("PCIE_PM: ")); + for(i=0;ichipCap.EEPROM_DEFAULT_BIN != NULL ) + { + NdisMoveMemory(pAd->EEPROMImage, pAd->chipCap.EEPROM_DEFAULT_BIN, + pAd->chipCap.EEPROM_DEFAULT_BIN_SIZE > MAX_EEPROM_BUFFER_SIZE?MAX_EEPROM_BUFFER_SIZE:pAd->chipCap.EEPROM_DEFAULT_BIN_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("Load EEPROM Buffer from default BIN.\n")); + } + + } + + /* Change to BIN eeprom buffer mode */ + RtmpChipOpsEepromHook(pAd, pAd->infType,E2P_BIN_MODE); + return TRUE; + } +} + + +INT Set_EepromBufferWriteBack_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT e2p_mode = simple_strtol(arg, 0, 10); + + if (e2p_mode >= NUM_OF_E2P_MODE) + return FALSE; + + switch (e2p_mode) + { +#ifdef RTMP_EFUSE_SUPPORT + case E2P_EFUSE_MODE: + DBGPRINT(RT_DEBUG_OFF, ("Write EEPROM buffer back to eFuse\n")); + rtmp_ee_write_to_efuse(pAd); + break; +#endif /* RTMP_EFUSE_SUPPORT */ + +#ifdef RTMP_FLASH_SUPPORT + case E2P_FLASH_MODE: + DBGPRINT(RT_DEBUG_OFF, ("Write EEPROM buffer back to Flash\n")); + rtmp_ee_flash_write_all(pAd, (PUSHORT)pAd->EEPROMImage); + break; +#endif /* RTMP_FLASH_SUPPORT */ + + case E2P_EEPROM_MODE: + DBGPRINT(RT_DEBUG_OFF, ("Write EEPROM buffer back to EEPROM\n")); + rtmp_ee_write_to_prom(pAd); + break; + + case E2P_BIN_MODE: + DBGPRINT(RT_DEBUG_OFF, ("Write EEPROM buffer back to BIN\n")); + rtmp_ee_write_to_bin(pAd); + break; + + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s::do not support this EEPROM access mode\n", __FUNCTION__)); + return FALSE; + } + + return TRUE; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/event_notifier.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/event_notifier.c new file mode 100644 index 000000000..3b7369d9e --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/event_notifier.c @@ -0,0 +1,694 @@ +/* + *************************************************************************** + * 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: + event_notifier.c + + Abstract: + This is event notify feature used to send wireless event to upper layer. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifdef WH_EVENT_NOTIFIER +#include "rt_config.h" +//#include "hdev/hdev.h" + +static NTSTATUS WHCStaProbeReq(IN PRTMP_ADAPTER pAd, ...) +{ + va_list Args; + struct wifi_dev *wdev = NULL; + PEER_PROBE_REQ_PARAM *pProbeReqParam = NULL; + MLME_QUEUE_ELEM *Elem = NULL; + PFRAME_802_11 pFrame = NULL; + struct drvevnt_type_buf drvevnt; + struct drvevnt_sta_probe_req *pProbeReq = &drvevnt.data.probereq; + HTTRANSMIT_SETTING HTSetting; + + NdisZeroMemory(pProbeReq, sizeof(*pProbeReq)); + va_start(Args, pAd); + wdev = va_arg(Args, struct wifi_dev *); + pProbeReqParam = va_arg(Args, PEER_PROBE_REQ_PARAM *); + Elem = va_arg(Args, MLME_QUEUE_ELEM *); + va_end(Args); + pFrame = (PFRAME_802_11)Elem->Msg; + + pProbeReq->type = WHC_DRVEVNT_STA_PROBE_REQ; + COPY_MAC_ADDR(pProbeReq->sta_mac, pProbeReqParam->Addr2); + pProbeReq->is_ucast = IS_BROADCAST_MAC_ADDR(pFrame->Hdr.Addr1)?FALSE:TRUE; + pProbeReq->rx_info.channel = Elem->Channel; + pProbeReq->rx_info.rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_0), + ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_1), + ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_2)); + if(Elem->Channel > 14) + { + HTSetting.field.MODE = MODE_OFDM; + HTSetting.field.BW = BW_20; + HTSetting.field.MCS = MCS_RATE_6; + } + else + { + HTSetting.field.MODE = MODE_CCK; + HTSetting.field.BW = BW_20; + HTSetting.field.MCS = RATE_1; + } + getRate(HTSetting, &pProbeReq->rx_info.rate); + + pProbeReq->cap = 0; + if(pProbeReqParam->ie_list.ht_cap_len > 0) + { + pProbeReq->cap |= WHC_WLCAP_80211_N; + if(pProbeReqParam->ie_list.HTCapability.HtCapInfo.ChannelWidth == BW_40) + pProbeReq->cap |= WHC_WLCAP_HT40; + } + +#ifdef DOT11_VHT_AC + if (pProbeReqParam->ie_list.vht_cap_len > 0) + { + VHT_CAP_IE *vht_cap_ie = &pProbeReqParam->ie_list.vht_cap; + pProbeReq->cap |= WHC_WLCAP_80211_AC; + + if(vht_cap_ie->vht_cap.ch_width == VHT_BW_80) + pProbeReq->cap |= WHC_WLCAP_HT80; + else if(vht_cap_ie->vht_cap.ch_width == VHT_BW_160) + pProbeReq->cap |= WHC_WLCAP_HT160; + else if(vht_cap_ie->vht_cap.ch_width == VHT_BW_8080) + pProbeReq->cap |= (WHC_WLCAP_HT80|WHC_WLCAP_HT160); + else + pProbeReq->cap |= WHC_WLCAP_HT40; + } +#endif /* DOT11_VHT_AC */ + + pProbeReq->cap |= \ + (pProbeReqParam->ie_list.HTCapability.MCSSet[3] != 0x00) ? (WHC_WLCAP_RX_4_STREAMS|WHC_WLCAP_TX_4_STREAMS) :\ + (pProbeReqParam->ie_list.HTCapability.MCSSet[2] != 0x00) ? (WHC_WLCAP_RX_3_STREAMS|WHC_WLCAP_TX_3_STREAMS) :\ + (pProbeReqParam->ie_list.HTCapability.MCSSet[1] != 0x00) ? (WHC_WLCAP_RX_2_STREAMS|WHC_WLCAP_TX_2_STREAMS) : 0; + + if(pProbeReqParam->ie_list.vendor_ie.custom_ie_len > 0) + { + pProbeReq->custom_ie_len = pProbeReqParam->ie_list.vendor_ie.custom_ie_len; + NdisMoveMemory(pProbeReq->custom_ie, pProbeReqParam->ie_list.vendor_ie.custom_ie, + pProbeReqParam->ie_list.vendor_ie.custom_ie_len); + } + + RtmpOSWrielessEventSend(wdev->if_dev, RT_WLAN_EVENT_CUSTOM, WHC_DRVEVNT_STA_PROBE_REQ, + NULL, (PUCHAR)pProbeReq, sizeof(*pProbeReq)); + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS WHCApProbeRsp(IN PRTMP_ADAPTER pAd, ...) +{ + va_list Args; + struct wifi_dev *wdev = NULL; + BCN_IE_LIST *ie_list = NULL; + MLME_QUEUE_ELEM *Elem = NULL; + PFRAME_802_11 pFrame = NULL; + struct drvevnt_type_buf drvevnt; + struct drvevnt_ap_probe_rsp *pProbeRsp = &drvevnt.data.probersp; + HTTRANSMIT_SETTING HTSetting; + + NdisZeroMemory(pProbeRsp, sizeof(*pProbeRsp)); + + va_start(Args, pAd); + wdev = va_arg(Args, struct wifi_dev *); + ie_list = va_arg(Args, BCN_IE_LIST *); + Elem = va_arg(Args, MLME_QUEUE_ELEM *); + va_end(Args); + pFrame = (PFRAME_802_11)Elem->Msg; + + pProbeRsp->type = WHC_DRVEVNT_AP_PROBE_RSP; + COPY_MAC_ADDR(pProbeRsp->ap_mac, pFrame->Hdr.Addr2); + pProbeRsp->rx_info.channel = Elem->Channel; + pProbeRsp->rx_info.rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_0), + ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_1), + ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_2)); + if(Elem->Channel > 14) + { + HTSetting.field.MODE = MODE_OFDM; + HTSetting.field.BW = BW_20; + HTSetting.field.MCS = MCS_RATE_6; + } + else + { + HTSetting.field.MODE = MODE_CCK; + HTSetting.field.BW = BW_20; + HTSetting.field.MCS = RATE_1; + } + getRate(HTSetting, &pProbeRsp->rx_info.rate); + + pProbeRsp->cap = 0; + if(ie_list->HtCapabilityLen > 0) + { + pProbeRsp->cap |= WHC_WLCAP_80211_N; + if(ie_list->HtCapability.HtCapInfo.ChannelWidth == BW_40) + pProbeRsp->cap |= WHC_WLCAP_HT40; + } + +#ifdef DOT11_VHT_AC + if (ie_list->vht_cap_len > 0) + { + VHT_CAP_IE *vht_cap_ie = &ie_list->vht_cap_ie; + pProbeRsp->cap |= WHC_WLCAP_80211_AC; + + if(vht_cap_ie->vht_cap.ch_width == VHT_BW_80) + pProbeRsp->cap |= WHC_WLCAP_HT80; + else if(vht_cap_ie->vht_cap.ch_width == VHT_BW_160) + pProbeRsp->cap |= WHC_WLCAP_HT160; + else if(vht_cap_ie->vht_cap.ch_width == VHT_BW_8080) + pProbeRsp->cap |= (WHC_WLCAP_HT80|WHC_WLCAP_HT160); + else + pProbeRsp->cap |= WHC_WLCAP_HT40; + } +#endif /* DOT11_VHT_AC */ + pProbeRsp->cap |= \ + (ie_list->HtCapability.MCSSet[3] != 0x00) ? (WHC_WLCAP_RX_4_STREAMS|WHC_WLCAP_TX_4_STREAMS) :\ + (ie_list->HtCapability.MCSSet[2] != 0x00) ? (WHC_WLCAP_RX_3_STREAMS|WHC_WLCAP_TX_3_STREAMS) :\ + (ie_list->HtCapability.MCSSet[1] != 0x00) ? (WHC_WLCAP_RX_2_STREAMS|WHC_WLCAP_TX_2_STREAMS) : 0; + + if(ie_list->vendor_ie.custom_ie_len > 0) + { + pProbeRsp->custom_ie_len = ie_list->vendor_ie.custom_ie_len; + NdisMoveMemory(pProbeRsp->custom_ie, ie_list->vendor_ie.custom_ie, ie_list->vendor_ie.custom_ie_len); + } + + RtmpOSWrielessEventSend(wdev->if_dev, RT_WLAN_EVENT_CUSTOM, WHC_DRVEVNT_AP_PROBE_RSP, + NULL, (PUCHAR)pProbeRsp, sizeof(*pProbeRsp)); + + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS WHCStaJoin(IN PRTMP_ADAPTER pAd, ...) +{ + va_list Args; + struct wifi_dev *wdev = NULL; + MAC_TABLE_ENTRY *pEntry = NULL; + MLME_QUEUE_ELEM *Elem = NULL; + struct drvevnt_type_buf drvevnt; + struct drvevnt_sta_join *pStaJoin = &drvevnt.data.join; + + NdisZeroMemory(pStaJoin, sizeof(*pStaJoin)); + + va_start(Args, pAd); + pEntry = va_arg(Args, MAC_TABLE_ENTRY *); + Elem = va_arg(Args, MLME_QUEUE_ELEM *); + va_end(Args); + + wdev = pEntry->wdev; + pStaJoin->type = WHC_DRVEVNT_STA_JOIN; + pStaJoin->channel = Elem->Channel; + COPY_MAC_ADDR(pStaJoin->sta_mac, pEntry->Addr); + pStaJoin->aid = pEntry->Aid; + +#ifdef DOT11K_RRM_SUPPORT + pStaJoin->capability |= (pEntry->CapabilityInfo & RRM_CAP_BIT) >> 12; /* Radio Measurement Enable or Disable */ +#endif +#ifdef DOT11V_WNM_SUPPORT + pStaJoin->capability |= (pEntry->BssTransitionManmtSupport) << 1; /* BSS Transition Management Enable or Disable */ +#endif + if(pEntry->custom_ie_len > 0) + { + pStaJoin->custom_ie_len = pEntry->custom_ie_len; + NdisMoveMemory(pStaJoin->custom_ie, pEntry->custom_ie, pEntry->custom_ie_len); + } + + RtmpOSWrielessEventSend(wdev->if_dev, RT_WLAN_EVENT_CUSTOM, WHC_DRVEVNT_STA_JOIN, + NULL, (PUCHAR)pStaJoin, sizeof(*pStaJoin)); + + DBGPRINT(RT_DEBUG_TRACE, ("%s WHC_DRVEVNT_STA_JOIN send ....\n", __FUNCTION__)); + + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS WHCStaLeave(IN PRTMP_ADAPTER pAd, ...) +{ + va_list Args; + struct wifi_dev *wdev = NULL; + UCHAR *pStaMac = NULL; + UCHAR Channel; + struct drvevnt_type_buf drvevnt; + struct drvevnt_sta_leave *pStaLeave = &drvevnt.data.leave; + + NdisZeroMemory(pStaLeave, sizeof(*pStaLeave)); + + va_start(Args, pAd); + wdev = va_arg(Args, struct wifi_dev *); + pStaMac = va_arg(Args, UCHAR *); + Channel = (UCHAR)va_arg(Args, UINT32); + va_end(Args); + + pStaLeave->type = WHC_DRVEVNT_STA_LEAVE; + COPY_MAC_ADDR(pStaLeave->sta_mac, pStaMac); + pStaLeave->channel = Channel; + + RtmpOSWrielessEventSend(wdev->if_dev, RT_WLAN_EVENT_CUSTOM, WHC_DRVEVNT_STA_LEAVE, + NULL, (PUCHAR)pStaLeave, sizeof(*pStaLeave)); + + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS WHCExtUpLinkStatus(IN PRTMP_ADAPTER pAd, ...) +{ + va_list Args; + MAC_TABLE_ENTRY *pEntry = NULL; + UINT32 link_state; + struct wifi_dev *wdev = NULL; + struct drvevnt_type_buf drvevnt; + struct drvevnt_ext_uplink_stat *pExtUplink = &drvevnt.data.link_state; + + NdisZeroMemory(pExtUplink, sizeof(*pExtUplink)); + + va_start(Args, pAd); + pEntry = va_arg(Args, MAC_TABLE_ENTRY *); + link_state = va_arg(Args, UINT32); + va_end(Args); + wdev = pEntry->wdev; + + pExtUplink->type = WHC_DRVEVNT_EXT_UPLINK_STAT; + COPY_MAC_ADDR(pExtUplink->ap_mac, pEntry->Addr); + pExtUplink->channel = pAd->CommonCfg.Channel; + pExtUplink->link_state = link_state; + + RtmpOSWrielessEventSend(wdev->if_dev, RT_WLAN_EVENT_CUSTOM, WHC_DRVEVNT_EXT_UPLINK_STAT, + NULL, (PUCHAR)pExtUplink, sizeof(*pExtUplink)); + + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS WHCStaTimeout(IN PRTMP_ADAPTER pAd, ...) +{ + va_list Args; + MAC_TABLE_ENTRY *pEntry = NULL; + struct wifi_dev *wdev = NULL; + struct drvevnt_type_buf drvevnt; + struct drvevnt_sta_timeout *pStaTimeout = &drvevnt.data.timeout; + + NdisZeroMemory(pStaTimeout, sizeof(*pStaTimeout)); + + va_start(Args, pAd); + pEntry = va_arg(Args, MAC_TABLE_ENTRY *); + va_end(Args); + wdev = pEntry->wdev; + + pStaTimeout->type = WHC_DRVEVNT_STA_TIMEOUT; + COPY_MAC_ADDR(pStaTimeout->sta_mac, pEntry->Addr); + pStaTimeout->channel = pAd->CommonCfg.Channel; + + RtmpOSWrielessEventSend(wdev->if_dev, RT_WLAN_EVENT_CUSTOM, WHC_DRVEVNT_STA_TIMEOUT, + NULL, (PUCHAR)pStaTimeout, sizeof(*pStaTimeout)); + + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS WHCStaAuthReject(IN PRTMP_ADAPTER pAd, ...) +{ + va_list Args; + struct wifi_dev *wdev = NULL; + UCHAR *pStaMac = NULL; + MLME_QUEUE_ELEM *Elem = NULL; + struct drvevnt_type_buf drvevnt; + struct drvevnt_sta_auth_reject *pStaAuthReject = &drvevnt.data.auth_reject; + HTTRANSMIT_SETTING HTSetting; + + NdisZeroMemory(pStaAuthReject, sizeof(*pStaAuthReject)); + va_start(Args, pAd); + wdev = va_arg(Args, struct wifi_dev *); + pStaMac = va_arg(Args, UCHAR *); + Elem = va_arg(Args, MLME_QUEUE_ELEM *); + va_end(Args); + + pStaAuthReject->type = WHC_DRVEVNT_STA_AUTH_REJECT; + pStaAuthReject->rx_info.channel = Elem->Channel; + COPY_MAC_ADDR(pStaAuthReject->sta_mac, pStaMac); + pStaAuthReject->rx_info.rssi = RTMPMaxRssi(pAd, ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_0), + ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_1), + ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_2)); + if(Elem->Channel > 14) + { + HTSetting.field.MODE = MODE_OFDM; + HTSetting.field.BW = BW_20; + HTSetting.field.MCS = MCS_RATE_6; + } + else + { + HTSetting.field.MODE = MODE_CCK; + HTSetting.field.BW = BW_20; + HTSetting.field.MCS = RATE_1; + } + getRate(HTSetting, &pStaAuthReject->rx_info.rate); + + RtmpOSWrielessEventSend(wdev->if_dev, RT_WLAN_EVENT_CUSTOM, WHC_DRVEVNT_STA_AUTH_REJECT, + NULL, (PUCHAR)pStaAuthReject, sizeof(*pStaAuthReject)); + + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS WHCStaRssiTooLow(IN PRTMP_ADAPTER pAd, ...) +{ + va_list Args; + struct wifi_dev *wdev = NULL; + CHAR Rssi; + UCHAR *pStaMac = NULL; + struct drvevnt_type_buf drvevnt; + struct drvevnt_sta_rssi_too_low *pStaRssi = &drvevnt.data.sta_rssi; + + NdisZeroMemory(pStaRssi, sizeof(*pStaRssi)); + + va_start(Args, pAd); + wdev = va_arg(Args, struct wifi_dev *); + pStaMac = va_arg(Args, UCHAR *); + Rssi = (CHAR)va_arg(Args, INT); + va_end(Args); + + pStaRssi->type = WHC_DRVEVNT_STA_AUTH_REJECT; + pStaRssi->rssi = Rssi; + COPY_MAC_ADDR(pStaRssi->sta_mac, pStaMac); + + RtmpOSWrielessEventSend(wdev->if_dev, RT_WLAN_EVENT_CUSTOM, WHC_DRVEVNT_STA_RSSI_TOO_LOW, + NULL, (PUCHAR)pStaRssi, sizeof(*pStaRssi)); + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS WHCStaActivityState(IN PRTMP_ADAPTER pAd, ...) +{ + va_list Args; + BOOLEAN bTx; + MAC_TABLE_ENTRY *pEntry = NULL; + StaActivityItem *pStaActivity = NULL; + struct wifi_dev *wdev = NULL; + struct drvevnt_type_buf drvevnt; + struct drvevnt_sta_activity_stat *pStaStat = &drvevnt.data.sta_activity_stat; + + NdisZeroMemory(pStaStat, sizeof(*pStaStat)); + + va_start(Args, pAd); + pEntry = va_arg(Args, MAC_TABLE_ENTRY *); + bTx = (BOOLEAN)va_arg(Args, INT); + va_end(Args); + wdev = pEntry->wdev; + if(bTx) + pStaActivity = &pEntry->tx_state; + else + pStaActivity = &pEntry->rx_state; + + pStaStat->type = WHC_DRVEVNT_STA_ACTIVITY_STATE; + pStaStat->bTx = bTx; + NdisMoveMemory(&pStaStat->sta_state, pStaActivity, sizeof(*pStaActivity)); + COPY_MAC_ADDR(pStaStat->sta_mac, pEntry->Addr); + + RtmpOSWrielessEventSend(wdev->if_dev, RT_WLAN_EVENT_CUSTOM, WHC_DRVEVNT_STA_ACTIVITY_STATE, + NULL, (PUCHAR)pStaStat, sizeof(*pStaStat)); + + return NDIS_STATUS_SUCCESS; +} + +static EVENT_TABLE_T EventHdlrTable[] = { + {WHC_DRVEVNT_STA_PROBE_REQ, WHCStaProbeReq}, + {WHC_DRVEVNT_AP_PROBE_RSP, WHCApProbeRsp}, + {WHC_DRVEVNT_STA_JOIN, WHCStaJoin}, + {WHC_DRVEVNT_STA_LEAVE, WHCStaLeave}, + {WHC_DRVEVNT_EXT_UPLINK_STAT, WHCExtUpLinkStatus}, + {WHC_DRVEVNT_STA_TIMEOUT, WHCStaTimeout}, + {WHC_DRVEVNT_STA_AUTH_REJECT, WHCStaAuthReject}, + {WHC_DRVEVNT_STA_RSSI_TOO_LOW, WHCStaRssiTooLow}, + {WHC_DRVEVNT_STA_ACTIVITY_STATE, WHCStaActivityState}, + {DRVEVNT_END_ID, NULL} +}; + +EventHdlr GetEventNotiferHook(IN UINT32 EventID) +{ + UINT32 CurIndex = 0; + UINT32 EventHdlrTableLength= sizeof(EventHdlrTable) / sizeof(EVENT_TABLE_T); + EventHdlr Handler = NULL; + + if(EventID > DRVEVNT_END_ID) + { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("Event ID(%d) is out of boundary.\n", EventID)); + return NULL; + } + + for(CurIndex=0; CurIndex < EventHdlrTableLength; CurIndex++) + { + if (EventHdlrTable[CurIndex].EventID == EventID) + { + Handler = EventHdlrTable[CurIndex].EventHandler; + break; + } + } + + if(Handler == NULL) + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("No corresponding EventHdlr for this Event ID(%d).\n", EventID)); + + return Handler; +} + +INT SetCustomOUIProc(PRTMP_ADAPTER pAd, PSTRING arg) +{ + UCHAR tmp[256] = {0}; + INT len = 0; + + pAd->ApCfg.EventNotifyCfg.CustomOUILen = 0; + NdisZeroMemory(pAd->ApCfg.EventNotifyCfg.CustomOUI, sizeof(pAd->ApCfg.EventNotifyCfg.CustomOUI)); + + strncpy(tmp, arg, sizeof(tmp)); + len = strlen(tmp); + if(len > 0) + { + if(len%2 != 0) + { + tmp[len]='0'; + len++; + } + + AtoH(tmp, pAd->ApCfg.EventNotifyCfg.CustomOUI, len); + pAd->ApCfg.EventNotifyCfg.CustomOUILen = len/2; + } + + return TRUE; +} + +INT SetCustomVIEProc(PRTMP_ADAPTER pAd, PSTRING arg) +{ + POS_COOKIE pObj = NULL; + UCHAR ifIndex = 0, tmp[256] = {0}; + INT len = 0; + struct wifi_dev *wdev = NULL; + BOOLEAN bAP = FALSE; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + switch (pObj->ioctl_if_type) + { + case INT_MAIN: + case INT_MBSSID: + if(ifIndex < HW_BEACON_MAX_NUM) + { + wdev = &pAd->ApCfg.MBSSID[ifIndex].wdev; + bAP = TRUE; + } + break; +#ifdef APCLI_SUPPORT + case INT_APCLI: + if(ifIndex < MAX_APCLI_NUM) + wdev = &pAd->ApCfg.ApCliTab[ifIndex].wdev; + break; +#endif /* APCLI_SUPPORT */ + default: + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s(): Invalid interface type(%u).\n", __FUNCTION__, pObj->ioctl_if_type)); + return FALSE; + break; + } + + if(!wdev) + { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("%s(): wdev is NULL!\n", __FUNCTION__)); + return FALSE; + } + wdev->custom_vie.ie_hdr.eid = IE_VENDOR_SPECIFIC; + wdev->custom_vie.ie_hdr.len = 0; + NdisZeroMemory(wdev->custom_vie.custom_ie, CUSTOM_IE_TOTAL_LEN); + + strncpy(tmp, arg, sizeof(tmp)); + len = strlen(tmp); + if(len > 0) + { + if(len%2 != 0) + { + tmp[len]='0'; + len++; + } + + AtoH(tmp, wdev->custom_vie.custom_ie, len); + wdev->custom_vie.ie_hdr.len = len/2; + if(bAP) + UpdateBeaconHandler(pAd, wdev, IE_CHANGE); + } + + return TRUE; +} + +INT SetChannelLoadDetectPeriodProc(PRTMP_ADAPTER pAd, PSTRING arg) +{ + struct EventNotifierCfg *pEventNotifyCfg = &pAd->ApCfg.EventNotifyCfg; + + pEventNotifyCfg->ChLoadDetectPeriod = simple_strtol(arg, 0, 10); + if(pEventNotifyCfg->ChLoadDetectPeriod > 0) + { + pEventNotifyCfg->bChLoadDetect = TRUE; + pEventNotifyCfg->ChLoadRound = 0; + } + else + { + pEventNotifyCfg->bChLoadDetect = FALSE; + } + return TRUE; +} + +INT SetStaRssiDetectThresholdProc(PRTMP_ADAPTER pAd, PSTRING arg) +{ + POS_COOKIE pObj = NULL; + UCHAR ifIndex = 0; + struct EventNotifierCfg *pEventNotifyCfg = NULL; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + if((pObj->ioctl_if_type != INT_MAIN) && (pObj->ioctl_if_type != INT_MBSSID)) + { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s(): Invalid interface type(%u).\n", __FUNCTION__, pObj->ioctl_if_type)); + return FALSE; + } + + pEventNotifyCfg = &pAd->ApCfg.EventNotifyCfg; + pEventNotifyCfg->StaRssiDetectThreshold = simple_strtol(arg, 0, 10); + if(pEventNotifyCfg->StaRssiDetectThreshold >= 0) + pEventNotifyCfg->bStaRssiDetect = FALSE; + else + pEventNotifyCfg->bStaRssiDetect = TRUE; + + return TRUE; +} + +INT SetStaTxPktDetectPeriodProc(PRTMP_ADAPTER pAd, PSTRING arg) +{ + POS_COOKIE pObj = NULL; + UCHAR ifIndex = 0; + struct EventNotifierCfg *pEventNotifyCfg = NULL; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + if((pObj->ioctl_if_type != INT_MAIN) && (pObj->ioctl_if_type != INT_MBSSID)) + { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s(): Invalid interface type(%u).\n", __FUNCTION__, pObj->ioctl_if_type)); + return FALSE; + } + + pEventNotifyCfg = &pAd->ApCfg.EventNotifyCfg; + pEventNotifyCfg->StaTxPktDetectPeriod = simple_strtol(arg, 0, 10); + pEventNotifyCfg->StaTxPktDetectRound = 0; + + return TRUE; +} + +INT SetStaTxPacketDetectThresholdProc(PRTMP_ADAPTER pAd, PSTRING arg) +{ + POS_COOKIE pObj = NULL; + UCHAR ifIndex = 0; + struct EventNotifierCfg *pEventNotifyCfg = NULL; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + if((pObj->ioctl_if_type != INT_MAIN) && (pObj->ioctl_if_type != INT_MBSSID)) + { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s(): Invalid interface type(%u).\n", __FUNCTION__, pObj->ioctl_if_type)); + return FALSE; + } + + pEventNotifyCfg = &pAd->ApCfg.EventNotifyCfg; + pEventNotifyCfg->StaStateTxThreshold = simple_strtol(arg, 0, 10); + if(pEventNotifyCfg->StaStateTxThreshold > 0) + { + pEventNotifyCfg->bStaStateTxDetect = TRUE; + pEventNotifyCfg->StaTxPktDetectRound = 0; + } + else + pEventNotifyCfg->bStaStateTxDetect = FALSE; + + return TRUE; +} + +INT SetStaRxPktDetectPeriodProc(PRTMP_ADAPTER pAd, PSTRING arg) +{ + POS_COOKIE pObj = NULL; + UCHAR ifIndex = 0; + struct EventNotifierCfg *pEventNotifyCfg = NULL; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + if((pObj->ioctl_if_type != INT_MAIN) && (pObj->ioctl_if_type != INT_MBSSID)) + { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s(): Invalid interface type(%u).\n", __FUNCTION__, pObj->ioctl_if_type)); + return FALSE; + } + + pEventNotifyCfg = &pAd->ApCfg.EventNotifyCfg; + pEventNotifyCfg->StaRxPktDetectPeriod = simple_strtol(arg, 0, 10); + pEventNotifyCfg->StaRxPktDetectRound = 0; + + return TRUE; +} + +INT SetStaRxPacketDetectThresholdProc(PRTMP_ADAPTER pAd, PSTRING arg) +{ + POS_COOKIE pObj = NULL; + UCHAR ifIndex = 0; + struct EventNotifierCfg *pEventNotifyCfg = NULL; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + if((pObj->ioctl_if_type != INT_MAIN) && (pObj->ioctl_if_type != INT_MBSSID)) + { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s(): Invalid interface type(%u).\n", __FUNCTION__, pObj->ioctl_if_type)); + return FALSE; + } + + pEventNotifyCfg = &pAd->ApCfg.EventNotifyCfg; + pEventNotifyCfg->StaStateRxThreshold = simple_strtol(arg, 0, 10); + if(pEventNotifyCfg->StaStateRxThreshold > 0) + { + pEventNotifyCfg->bStaStateRxDetect = TRUE; + pEventNotifyCfg->StaRxPktDetectRound = 0 ; + } + else + pEventNotifyCfg->bStaStateRxDetect = FALSE; + + return TRUE; +} +#endif /* WH_EVENT_NOTIFIER */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/event_notifier_old.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/event_notifier_old.c new file mode 100644 index 000000000..ac0b7656b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/event_notifier_old.c @@ -0,0 +1,125 @@ +/* + *************************************************************************** + * 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: + event_notifier.c + + Abstract: + This is event notify feature used to send wireless event to upper layer. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifdef CONFIG_PUSH_SUPPORT +#include "rt_config.h" +//#include "hdev/hdev.h" + +static NTSTATUS WHCStaJoin(IN PRTMP_ADAPTER pAd, ...) +{ + va_list Args; + struct wifi_dev *wdev = NULL; + MAC_TABLE_ENTRY *pEntry = NULL; + UCHAR Channel; + struct drvevnt_type_buf drvevnt; + struct drvevnt_sta_join *pStaJoin = &drvevnt.data.join; + + NdisZeroMemory(pStaJoin, sizeof(*pStaJoin)); + + va_start(Args, pAd); + pEntry = va_arg(Args, MAC_TABLE_ENTRY *); + Channel = va_arg(Args, UINT32); + va_end(Args); + + wdev = pEntry->wdev; + pStaJoin->type = WHC_DRVEVNT_STA_JOIN; + pStaJoin->channel = Channel; + COPY_MAC_ADDR(pStaJoin->sta_mac, pEntry->Addr); + pStaJoin->aid = pEntry->Aid; + + RtmpOSWrielessEventSend(wdev->if_dev, RT_WLAN_EVENT_CUSTOM, WHC_DRVEVNT_STA_JOIN, + NULL, (PUCHAR)pStaJoin, sizeof(*pStaJoin)); + + DBGPRINT(RT_DEBUG_TRACE, ("%s WHC_DRVEVNT_STA_JOIN send ....\n", __FUNCTION__)); + + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS WHCStaLeave(IN PRTMP_ADAPTER pAd, ...) +{ + va_list Args; + struct wifi_dev *wdev = NULL; + UCHAR *pStaMac = NULL; + UCHAR Channel; + struct drvevnt_type_buf drvevnt; + struct drvevnt_sta_leave *pStaLeave = &drvevnt.data.leave; + + NdisZeroMemory(pStaLeave, sizeof(*pStaLeave)); + + va_start(Args, pAd); + wdev = va_arg(Args, struct wifi_dev *); + pStaMac = va_arg(Args, UCHAR *); + Channel = (UCHAR)va_arg(Args, UINT32); + va_end(Args); + + pStaLeave->type = WHC_DRVEVNT_STA_LEAVE; + COPY_MAC_ADDR(pStaLeave->sta_mac, pStaMac); + pStaLeave->channel = Channel; + + RtmpOSWrielessEventSend(wdev->if_dev, RT_WLAN_EVENT_CUSTOM, WHC_DRVEVNT_STA_LEAVE, + NULL, (PUCHAR)pStaLeave, sizeof(*pStaLeave)); + + DBGPRINT(RT_DEBUG_TRACE, ("%s WHC_DRVEVNT_STA_LEAVE send ....\n", __FUNCTION__)); + return NDIS_STATUS_SUCCESS; +} + +static EVENT_TABLE_T EventHdlrTable[] = { + {WHC_DRVEVNT_STA_JOIN, WHCStaJoin}, + {WHC_DRVEVNT_STA_LEAVE, WHCStaLeave}, + {DRVEVNT_END_ID, NULL} +}; + +EventHdlr GetEventNotiferHook(IN UINT32 EventID) +{ + UINT32 CurIndex = 0; + UINT32 EventHdlrTableLength= sizeof(EventHdlrTable) / sizeof(EVENT_TABLE_T); + EventHdlr Handler = NULL; + + if(EventID > DRVEVNT_END_ID) + { + DBGPRINT(RT_DEBUG_ERROR, ("Event ID(%d) is out of boundary.\n", EventID)); + return NULL; + } + + for(CurIndex=0; CurIndex < EventHdlrTableLength; CurIndex++) + { + if (EventHdlrTable[CurIndex].EventID == EventID) + { + Handler = EventHdlrTable[CurIndex].EventHandler; + break; + } + } + + if(Handler == NULL) + DBGPRINT(RT_DEBUG_ERROR, ("No corresponding EventHdlr for this Event ID(%d).\n", EventID)); + + return Handler; +} + +#endif /* CONFIG_PUSH_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/frq_cal.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/frq_cal.c new file mode 100644 index 000000000..ac05d3905 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/frq_cal.c @@ -0,0 +1,28 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + frq_cal.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ft.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ft.c new file mode 100644 index 000000000..2d5076378 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ft.c @@ -0,0 +1,3055 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + ft.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Fonchi Wu 12-19-2008 + */ +#ifdef DOT11R_FT_SUPPORT + +#include "rt_config.h" +#include "ft.h" + +#ifdef CONFIG_AP_SUPPORT + +static VOID FT_RrbEnqueue( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN PFT_ACTION pFtAction, + IN UINT16 FtActLen, + IN UINT32 ApIdx); + +static VOID FT_ReqActionParse( + IN PRTMP_ADAPTER pAd, + IN UINT16 Len, + IN PUCHAR Ptr, + OUT PFT_INFO pFtInfo); + +VOID FT_ConstructGTKSubIe( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + OUT PFT_FTIE_INFO pFtInfo); + +UINT16 FT_AuthReqRsnValidation( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_CFG pFtCfg, + IN PFT_INFO pFtInfo_in, + OUT PFT_INFO pFtInfo_out); + +UINT16 FT_AuthConfirmRsnValidation( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pFtInfo_in); + +UINT16 FT_AssocReqRsnValidation( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pFtInfo_in, + OUT PFT_INFO pFtInfo_out); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_EnqueueAuthReply( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pHdr, + IN USHORT Alg, + IN USHORT Seq, + IN USHORT StatusCode, + IN PFT_MDIE_INFO pMdIeInfo, + IN PFT_FTIE_INFO pFtIeInfo, + IN PFT_RIC_INFO pRicInfo, + IN PUCHAR pRsnIe, + IN UCHAR RsnIeLen) +{ + HEADER_802_11 AuthHdr; + ULONG FrameLen = 0; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + PUINT8 ftie_ptr = NULL; + UINT8 ftie_len = 0; + PUINT8 mdie_ptr = NULL; + UINT8 mdie_len = 0; + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("AUTH_RSP - Send FT-AUTH response (%d)...\n", StatusCode)); + MgtMacHeaderInit(pAd, &AuthHdr, SUBTYPE_AUTH, 0, pHdr->Addr2, + pHdr->Addr1, + pHdr->Addr1); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &AuthHdr, + 2, &Alg, + 2, &Seq, + 2, &StatusCode, + END_OF_ARGS); + + /* Insert MDIE. */ + if((pMdIeInfo != NULL) && (pMdIeInfo->Len > 0)) + { + mdie_ptr = pOutBuffer + FrameLen; + mdie_len = 5; + FT_InsertMdIE(pAd, pOutBuffer + FrameLen, &FrameLen, + pMdIeInfo->MdId, pMdIeInfo->FtCapPlc); + } + + /* Insert FTIE. */ + if ((pFtIeInfo != NULL) && (pFtIeInfo->Len != 0)) + { + ftie_ptr = pOutBuffer+FrameLen; + ftie_len = (2 + pFtIeInfo->Len); + FT_InsertFTIE(pAd, pOutBuffer+FrameLen, &FrameLen, + pFtIeInfo->Len, pFtIeInfo->MICCtr, + pFtIeInfo->MIC, pFtIeInfo->ANonce, + pFtIeInfo->SNonce); + + /* Insert R1KH IE into FTIE. */ + if (pFtIeInfo->R1khIdLen!= 0) + FT_FTIE_InsertKhIdSubIE(pAd, pOutBuffer+FrameLen, &FrameLen, + FT_R1KH_ID, pFtIeInfo->R1khId, + pFtIeInfo->R1khIdLen); + + /* Insert R0KH IE into FTIE. */ + if (pFtIeInfo->R0khIdLen!= 0) + FT_FTIE_InsertKhIdSubIE(pAd, pOutBuffer+FrameLen, &FrameLen, + FT_R0KH_ID, pFtIeInfo->R0khId, + pFtIeInfo->R0khIdLen); + + } + + /* Insert RSNIE. */ + if ((RsnIeLen != 0) && (pRsnIe != NULL)) + { + ULONG TmpLen; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + RsnIeLen, pRsnIe, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* Insert RIC. */ + if ((pRicInfo != NULL) && (pRicInfo->Len != 0)) + { + ULONG TmpLen; + MakeOutgoingFrame(pOutBuffer+FrameLen, &TmpLen, + pRicInfo->Len, pRicInfo->pRicInfo, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* Calculate MIC in authentication-ACK frame */ + if ((pFtIeInfo != NULL) && (pFtIeInfo->MICCtr.field.IECnt)) + { + PMAC_TABLE_ENTRY pEntry; + + if ((pEntry = MacTableLookup(pAd, pHdr->Addr2)) != NULL) + { + UINT8 ft_mic[16]; + PFT_FTIE pFtIe; + + NdisZeroMemory(ft_mic, sizeof(ft_mic)); + FT_CalculateMIC(pHdr->Addr2, + pHdr->Addr1, + pEntry->PTK, + 4, + pRsnIe, + RsnIeLen, + mdie_ptr, + mdie_len, + ftie_ptr, + ftie_len, + pRicInfo->pRicInfo, + pRicInfo->Len, + ft_mic); + + /* Update the MIC field of FTIE */ + pFtIe = (PFT_FTIE)(ftie_ptr + 2); + NdisMoveMemory(pFtIe->MIC, ft_mic, FT_MIC_LEN); + } + } + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +static VOID FT_ReqActionParse( + IN PRTMP_ADAPTER pAd, + IN UINT16 Len, + IN PUCHAR Ptr, + OUT PFT_INFO pFtInfo) +{ + PEID_STRUCT eid_ptr; + UCHAR WPA1_OUI[4]={0x00,0x50,0xF2,0x01}; + UCHAR WPA2_OUI[3]={0x00,0x0F,0xAC}; + + eid_ptr = (PEID_STRUCT) Ptr; + + NdisZeroMemory(pFtInfo, sizeof(FT_INFO)); + + /* get variable fields from payload and advance the pointer */ + while(((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)Ptr + Len)) + { + switch(eid_ptr->Eid) + { + case IE_FT_MDIE: + FT_FillMdIeInfo(eid_ptr, &pFtInfo->MdIeInfo); + break; + + case IE_FT_FTIE: + FT_FillFtIeInfo(eid_ptr, &pFtInfo->FtIeInfo); + break; + + case IE_FT_RIC_DATA: + /* record the pointer of first RDIE. */ + if (pFtInfo->RicInfo.pRicInfo == NULL) + { + pFtInfo->RicInfo.pRicInfo = &eid_ptr->Eid; + pFtInfo->RicInfo.Len = ((UCHAR*)Ptr + Len) + - (UCHAR*)eid_ptr + 1; + } + case IE_FT_RIC_DESCRIPTOR: + if ((pFtInfo->RicInfo.RicIEsLen + eid_ptr->Len + 2) < MAX_RICIES_LEN) + { + NdisMoveMemory(&pFtInfo->RicInfo.RicIEs[pFtInfo->RicInfo.RicIEsLen], + &eid_ptr->Eid, eid_ptr->Len + 2); + pFtInfo->RicInfo.RicIEsLen += eid_ptr->Len + 2; + } + break; + + case IE_RSN: + case IE_WPA: + + if (NdisEqualMemory(eid_ptr->Octet, WPA1_OUI, sizeof(WPA1_OUI)) + || NdisEqualMemory(&eid_ptr->Octet[2], WPA2_OUI, sizeof(WPA2_OUI))) + { + NdisMoveMemory(pFtInfo->RSN_IE, eid_ptr, eid_ptr->Len + 2); + pFtInfo->RSNIE_Len = eid_ptr->Len + 2; + } + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_MakeFtActFrame( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 ActType, + IN PUCHAR pStaMac, + IN PUCHAR pTargetApMac, + IN UINT16 StatusCode, + IN PFT_INFO pFtInfo) +{ + ULONG TmpLen = 0; + UCHAR Category = FT_CATEGORY_BSS_TRANSITION; + + if (pFrameBuf == NULL) + return; + + /* Build basic frame first */ + MakeOutgoingFrame((pFrameBuf + *pFrameLen), &TmpLen, + 1, &Category, + 1, &ActType, + 6, pStaMac, + 6, pTargetApMac, + END_OF_ARGS); + + *pFrameLen += TmpLen; + + if ((ActType == FT_ACTION_BT_RSP) + || (ActType == FT_ACTION_BT_ACK)) + { + UINT16 StatusCodeBuf; + + TmpLen = 0; + StatusCodeBuf = cpu2le16(StatusCode); + MakeOutgoingFrame((pFrameBuf + *pFrameLen), &TmpLen, + 2, &StatusCodeBuf, + END_OF_ARGS); + *pFrameLen += TmpLen; + } + + /* Insert MD IE into packet. */ + if (pFtInfo->MdIeInfo.Len != 0) + FT_InsertMdIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + pFtInfo->MdIeInfo.MdId, pFtInfo->MdIeInfo.FtCapPlc); + + /* Insert FT IE into packet. */ + if (pFtInfo->FtIeInfo.Len != 0) + FT_InsertFTIE(pAd, (pFrameBuf + *pFrameLen), pFrameLen, + pFtInfo->FtIeInfo.Len, pFtInfo->FtIeInfo.MICCtr, + pFtInfo->FtIeInfo.MIC, pFtInfo->FtIeInfo.ANonce, + pFtInfo->FtIeInfo.SNonce); + + if (pFtInfo->FtIeInfo.R0khIdLen!= 0) + FT_FTIE_InsertKhIdSubIE(pAd, (pFrameBuf + *pFrameLen), + pFrameLen, FT_R0KH_ID, pFtInfo->FtIeInfo.R0khId, + pFtInfo->FtIeInfo.R0khIdLen); + + if (pFtInfo->FtIeInfo.R1khIdLen!= 0) + FT_FTIE_InsertKhIdSubIE(pAd, (pFrameBuf + *pFrameLen), + pFrameLen, FT_R1KH_ID, pFtInfo->FtIeInfo.R1khId, + pFtInfo->FtIeInfo.R1khIdLen); + + if (pFtInfo->FtIeInfo.GtkLen!= 0) + FT_FTIE_InsertGTKSubIE(pAd, (pFrameBuf + *pFrameLen), + pFrameLen, pFtInfo->FtIeInfo.GtkSubIE, + pFtInfo->FtIeInfo.GtkLen); + + + /* Insert Ric IE into packet .*/ + if ((ActType == FT_ACTION_BT_CONFIRM) + || (ActType == FT_ACTION_BT_ACK)) + { + TmpLen = 0; + MakeOutgoingFrame((pFrameBuf + *pFrameLen), &TmpLen, + pFtInfo->RicInfo.Len, (PUCHAR)pFtInfo->RicInfo.pRicInfo, + END_OF_ARGS); + *pFrameLen += TmpLen; + } + + return; +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ + VOID FT_CfgInitial( + IN PRTMP_ADAPTER pAd) +{ + INT apidx; + PFT_CFG pFtCfg; + RTMP_STRING R0khIdBuf[50]; + + NdisZeroMemory(R0khIdBuf, 50); + for (apidx = 0; apidx < MAX_MBSSID_NUM(pAd); apidx++) + { + pFtCfg = &pAd->ApCfg.MBSSID[apidx].FtCfg; + pFtCfg->FtCapFlag.Dot11rFtEnable = TRUE; +#if defined(WH_EZ_SETUP) || defined(MBO_SUPPORT) + // Keep false by default as applicable for MAN, + // if required for other project, can be enabled by command/dat file. + pFtCfg->FtCapFlag.FtOverDs = FALSE; + pFtCfg->FtCapFlag.RsrReqCap = FALSE; +#else + + pFtCfg->FtCapFlag.FtOverDs = TRUE; + pFtCfg->FtCapFlag.RsrReqCap = TRUE; +#endif + FT_SET_MDID(pFtCfg->FtMdId, FT_DEFAULT_MDID); + + snprintf(R0khIdBuf, sizeof(R0khIdBuf), "Ralink:%02x:%02x:%02x:%02x:%02x:%02x", + RandomByte(pAd), RandomByte(pAd), RandomByte(pAd), + RandomByte(pAd), RandomByte(pAd), RandomByte(pAd)); + NdisZeroMemory(pFtCfg->FtR0khId, sizeof(pFtCfg->FtR0khId)); + NdisMoveMemory(pFtCfg->FtR0khId, R0khIdBuf, strlen(R0khIdBuf)); + pFtCfg->FtR0khIdLen = strlen(R0khIdBuf); + } +} + +VOID FT_Init( + IN PRTMP_ADAPTER pAd) +{ +#ifdef FT_R1KH_KEEP + if (pAd->ApCfg.FtTab.FT_RadioOff != TRUE) { +#endif/* FT_R1KH_KEEP */ + FT_KDP_Init(pAd); + FT_RIC_Init(pAd); + FT_R1khEntryTabInit(pAd); +#ifdef FT_R1KH_KEEP + } +#endif/* FT_R1KH_KEEP */ +} + +VOID FT_Release( + IN PRTMP_ADAPTER pAd) +{ +#ifdef FT_R1KH_KEEP + if (pAd->ApCfg.FtTab.FT_RadioOff != TRUE) { +#endif /* FT_R1KH_KEEP */ + FT_KDP_Release(pAd); + FT_RIC_Release(pAd); + FT_R1khEntryTabDestroy(pAd); +#ifdef FT_R1KH_KEEP + } +#endif/* FT_R1KH_KEEP */ +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +USHORT FT_AuthReqHandler( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pFtInfo, + OUT PFT_INFO pFtInfoBuf) +{ + USHORT result = MLME_SUCCESS; + UCHAR ApIdx = pEntry->func_tb_idx; + PFT_CFG pFtCfg; + FT_CAP_AND_POLICY FtCapPlc; + + DBGPRINT(RT_DEBUG_TRACE, ("---> %s \n", __FUNCTION__)); + + if (ApIdx >= pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: invalid apidx (%d)\n", \ + __FUNCTION__, ApIdx)); + return MLME_UNSPECIFY_FAIL; + } + + pFtCfg = &pAd->ApCfg.MBSSID[ApIdx].FtCfg; + NdisZeroMemory(pFtInfoBuf, sizeof(FT_INFO)); + + do + { + if ((pFtInfo->MdIeInfo.Len == 0) + || (!FT_MDID_EQU(pFtInfo->MdIeInfo.MdId, pFtCfg->FtMdId))) + { + DBGPRINT_ERR(("%s : The MDIE is invalid\n", __FUNCTION__)); + result = FT_STATUS_CODE_INVALID_MDIE; + break; + } + + /* FT auth-req in an RSN */ + if (pFtInfo->RSNIE_Len != 0) + { + /* Sanity check */ + result = FT_AuthReqRsnValidation(pAd, + pEntry, + pFtCfg, + pFtInfo, + pFtInfoBuf); + if (result != MLME_SUCCESS) + break; + } + else + { + /* FT auth-req with no RSN Ie (OPEN mode). + reply auth-rsp with success. */ + ; + } + NdisMoveMemory(&pEntry->MdIeInfo, &pFtInfo->MdIeInfo, + pFtInfo->MdIeInfo.Len); + + /* prepare Ft IEs for association response. */ + FT_SET_MDID(pFtInfoBuf->MdIeInfo.MdId, pFtCfg->FtMdId); + FtCapPlc.field.FtOverDs = pFtCfg->FtCapFlag.FtOverDs; + FtCapPlc.field.RsrReqCap = pFtCfg->FtCapFlag.RsrReqCap; + pFtInfoBuf->MdIeInfo.FtCapPlc.word = + pFtInfo->MdIeInfo.FtCapPlc.word & FtCapPlc.word; + pFtInfoBuf->MdIeInfo.Len = 3; + + result = MLME_SUCCESS; + break; + } while(0); + + DBGPRINT(RT_DEBUG_TRACE, ("<--- %s done. StatusCode(%d)\n", __FUNCTION__, result)); + + return result; +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +USHORT FT_AuthConfirmHandler( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pFtInfo, + OUT PFT_INFO pFtInfoBuf) +{ + USHORT result = MLME_SUCCESS; + UCHAR ApIdx = pEntry->func_tb_idx; + PFT_CFG pFtCfg; + FT_CAP_AND_POLICY FtCapPlc; + struct wifi_dev *wdev; + ULONG temp_len = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s:\n", __FUNCTION__)); + + if (ApIdx >= pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: invalid apidx (%d)\n", __FUNCTION__, ApIdx)); + return MLME_UNSPECIFY_FAIL; + } + + wdev = &pAd->ApCfg.MBSSID[ApIdx].wdev; + pFtCfg = &pAd->ApCfg.MBSSID[ApIdx].FtCfg; + NdisZeroMemory(pFtInfoBuf, sizeof(FT_INFO)); + + do + { + if ((pFtInfo->MdIeInfo.Len == 0) + || (!FT_MDID_EQU(pFtInfo->MdIeInfo.MdId, pFtCfg->FtMdId))) + { + /* invalid MDID. reject it. */ + result = FT_STATUS_CODE_INVALID_MDIE; + break; + } + + if (pFtInfo->RSNIE_Len != 0) + { + UINT16 result; + UINT8 rsnie_len = 0; + PUINT8 rsnie_ptr = NULL; + UINT8 ft_len = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Fast BSS transition in a RSN \n", __FUNCTION__)); + result = FT_AuthConfirmRsnValidation(pAd, + pEntry, + pFtInfo); + if (result != MLME_SUCCESS) + break; + + /* Prepare RSNIE for outgoing frame */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2)) + { + rsnie_len = pAd->ApCfg.MBSSID[pEntry->func_tb_idx].RSNIE_Len[1]; + rsnie_ptr = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].RSN_IE[1][0]; + } + else + { + rsnie_len = pAd->ApCfg.MBSSID[pEntry->func_tb_idx].RSNIE_Len[0]; + rsnie_ptr = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].RSN_IE[0][0]; + } + + pFtInfoBuf->RSNIE_Len = 0; + RTMPInsertRSNIE(pFtInfoBuf->RSN_IE, + &temp_len, + rsnie_ptr, + rsnie_len, + pEntry->FT_PMK_R1_NAME, + LEN_PMK_NAME); + + pFtInfoBuf->RSNIE_Len = (UCHAR)temp_len; + + ft_len = sizeof(FT_FTIE); + + /* Prepare MIC-control and MIC field of FTIE for outgoing frame. */ + pFtInfoBuf->FtIeInfo.MICCtr.field.IECnt = 3; + NdisZeroMemory(pFtInfoBuf->FtIeInfo.MIC, 16); + + /* Prepare ANonce and Snonce field of FTIE for outgoing frame */ + NdisMoveMemory(pFtInfoBuf->FtIeInfo.ANonce, pEntry->ANonce, LEN_NONCE); + NdisMoveMemory(pFtInfoBuf->FtIeInfo.SNonce, pEntry->SNonce, LEN_NONCE); + + /* Prepare in the R0KHID and its length */ + pFtInfoBuf->FtIeInfo.R0khIdLen = pFtCfg->FtR0khIdLen; + NdisMoveMemory(pFtInfoBuf->FtIeInfo.R0khId, + pFtCfg->FtR0khId, pFtCfg->FtR0khIdLen); + ft_len += (2 + pFtInfoBuf->FtIeInfo.R0khIdLen); + + /* Prepare in the R1KHID and its length */ + pFtInfoBuf->FtIeInfo.R1khIdLen = MAC_ADDR_LEN; + NdisMoveMemory(pFtInfoBuf->FtIeInfo.R1khId, + wdev->bssid, MAC_ADDR_LEN); + ft_len += (2 + MAC_ADDR_LEN); + + /* Update the length of FTIE */ + pFtInfoBuf->FtIeInfo.Len = ft_len; + + } + + /* + FT auth-req with no RSN Ie (OPEN mode). + reply auth-rsp with success. + */ + FT_RIC_ResourceRequestHandle(pAd, pEntry, + (PUCHAR)pFtInfo->RicInfo.pRicInfo, + pFtInfo->RicInfo.Len, + (PUCHAR)pFtInfoBuf->RicInfo.pRicInfo, + (PUINT32)&pFtInfoBuf->RicInfo.Len); + + /* In an RSN, The IE count need to include RIC for + MIC calculation */ + if (pFtInfoBuf->FtIeInfo.MICCtr.field.IECnt > 0 && + pFtInfoBuf->RicInfo.Len > 0) + pFtInfoBuf->FtIeInfo.MICCtr.field.IECnt += 1; + + /* prepare Ft IEs for association response. */ + FT_SET_MDID(pFtInfoBuf->MdIeInfo.MdId, pFtCfg->FtMdId); + FtCapPlc.field.FtOverDs = pFtCfg->FtCapFlag.FtOverDs; + FtCapPlc.field.RsrReqCap = pFtCfg->FtCapFlag.RsrReqCap; + pFtInfoBuf->MdIeInfo.FtCapPlc.word = + pFtInfo->MdIeInfo.FtCapPlc.word & FtCapPlc.word; + pFtInfoBuf->MdIeInfo.Len = 3; + + result = MLME_SUCCESS; + + break; + } while(0); + + return result; +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +USHORT FT_AssocReqHandler( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN isReassoc, + IN PFT_CFG pFtCfg, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pPeer_FtInfo, + OUT PFT_INFO pFtInfoBuf) +{ + USHORT statusCode = MLME_SUCCESS; + FT_CAP_AND_POLICY FtCapPlc; + + DBGPRINT(RT_DEBUG_TRACE, ("%s:\n", __FUNCTION__)); + + NdisZeroMemory(pFtInfoBuf, sizeof(FT_INFO)); + + if ((pFtCfg->FtCapFlag.Dot11rFtEnable) + && (pPeer_FtInfo != NULL) && (pPeer_FtInfo->MdIeInfo.Len != 0)) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: it's FT client \n", __FUNCTION__)); + + /* If the contents of the MDIE received by the AP do not match the + ** contents advertised in the Beacon and Probe Response frames, the + ** AP shall reject the (Re)association Request with status code 54 + ** ("Invalid MDIE"). */ + if (!FT_MDID_EQU(pPeer_FtInfo->MdIeInfo.MdId, pFtCfg->FtMdId)) + statusCode = FT_STATUS_CODE_INVALID_MDIE; + else + { + UINT8 ft_len = 0; + + ft_len = sizeof(FT_FTIE); + + /* Indicate this is a FT Initial Mobility Domain Association procedure */ + if (!IS_FT_STA(pEntry)) + { + NdisMoveMemory(&pEntry->MdIeInfo, &pPeer_FtInfo->MdIeInfo, + sizeof(pPeer_FtInfo->MdIeInfo)); + } + + if (pPeer_FtInfo->RSNIE_Len != 0) + { + + /* This is Fast BSS transition procedure with RSN */ + if (pPeer_FtInfo->FtIeInfo.Len > 0) + { + UINT16 result; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Fast BSS transition in a RSN \n", __FUNCTION__)); + result = FT_AssocReqRsnValidation(pAd, + pEntry, + pPeer_FtInfo, + pFtInfoBuf); + if (result != MLME_SUCCESS) + return result; + + /* Update the length of GTK in FTIE*/ + if (pFtInfoBuf->FtIeInfo.GtkLen) + ft_len += (2 + pFtInfoBuf->FtIeInfo.GtkLen); + } + + /* Prepare in the R0KHID and its length */ + if (isReassoc) + { + pFtInfoBuf->FtIeInfo.R0khIdLen = pPeer_FtInfo->FtIeInfo.R0khIdLen; + NdisMoveMemory(pFtInfoBuf->FtIeInfo.R0khId, + pPeer_FtInfo->FtIeInfo.R0khId, pFtInfoBuf->FtIeInfo.R0khIdLen); + } + else + { + pFtInfoBuf->FtIeInfo.R0khIdLen = pFtCfg->FtR0khIdLen; + NdisMoveMemory(pFtInfoBuf->FtIeInfo.R0khId, + pFtCfg->FtR0khId, pFtCfg->FtR0khIdLen); + } + ft_len += (2 + pFtInfoBuf->FtIeInfo.R0khIdLen); + + /* Prepare in the R1KHID and its length */ + pFtInfoBuf->FtIeInfo.R1khIdLen = MAC_ADDR_LEN; + NdisMoveMemory(pFtInfoBuf->FtIeInfo.R1khId, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid, MAC_ADDR_LEN); + ft_len += (2 + MAC_ADDR_LEN); + + /* Update the length of FTIE */ + pFtInfoBuf->FtIeInfo.Len = ft_len; + } + + /* prepare MDIE for association response. */ + FT_SET_MDID(pFtInfoBuf->MdIeInfo.MdId, pFtCfg->FtMdId); + FtCapPlc.field.FtOverDs = pFtCfg->FtCapFlag.FtOverDs; + FtCapPlc.field.RsrReqCap = pFtCfg->FtCapFlag.RsrReqCap; + pFtInfoBuf->MdIeInfo.FtCapPlc.word = + pPeer_FtInfo->MdIeInfo.FtCapPlc.word & FtCapPlc.word; + pFtInfoBuf->MdIeInfo.Len = 3; + + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: it isn't FT client \n", __FUNCTION__)); + } + + return statusCode; +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_R1khEntryTabInit( + IN PRTMP_ADAPTER pAd) +{ + INT idx; + + /* init spin lock */ + NdisAllocateSpinLock(pAd, &(pAd->ApCfg.FtTab.FT_R1khEntryTabLock)); + + pAd->ApCfg.FtTab.FT_R1khEntryTabSize = 0; + for (idx = 0; idx < FT_R1KH_ENTRY_HASH_TABLE_SIZE; idx++) + { + /* init event list */ + initList(&(pAd->ApCfg.FtTab.FT_R1khEntryTab[idx])); + } + pAd->ApCfg.FtTab.FT_R1khEntryTabReady = TRUE; +} /* End of FT_R1khEntryTabInit */ + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +INT FT_R1khEntryInsert( + IN PRTMP_ADAPTER pAd, + IN PUINT8 pPmkR0Name, + IN PUINT8 pPmkR1Name, + IN PUINT8 pPmkR1Key, + IN PUINT8 pPairwisChipher, + IN PUINT8 pAkmSuite, + IN UINT32 KeyLifeTime, + IN UINT32 RassocDeadline, + IN PUINT8 pR0khId, + IN UINT8 R0khIdLen, + IN PUINT8 pStaMac) +{ + UINT8 HashId; + PFT_R1HK_ENTRY pEntry; + + if (pAd->ApCfg.FtTab.FT_R1khEntryTabSize >= FT_R1KH_ENTRY_TABLE_SIZE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: FT_R1khEntryTab full.\n", __FUNCTION__)); + return -1; + } + + if(os_alloc_mem(pAd, (PUCHAR *)&pEntry, sizeof(FT_R1HK_ENTRY)) == + NDIS_STATUS_FAILURE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unable to alloc memory.\n", __FUNCTION__)); + return -1; + } + + pEntry->pNext = NULL; + if (pStaMac != NULL) + NdisMoveMemory(pEntry->StaMac, pStaMac, MAC_ADDR_LEN); + if (pR0khId != NULL && R0khIdLen > 0) + { + pEntry->R0khIdLen = R0khIdLen; + NdisMoveMemory(pEntry->R0khId, pR0khId, R0khIdLen); + } + if (pPairwisChipher != NULL) + NdisMoveMemory(pEntry->PairwisChipher, pPairwisChipher, 4); + if (pAkmSuite != NULL) + NdisMoveMemory(pEntry->AkmSuite, pAkmSuite, 4); + if (pPmkR0Name != NULL) + NdisMoveMemory(pEntry->PmkR0Name, pPmkR0Name, 16); + if (pPmkR1Name != NULL) + NdisMoveMemory(pEntry->PmkR1Name, pPmkR1Name, 16); + if (pPmkR1Key != NULL) + NdisMoveMemory(pEntry->PmkR1Key, pPmkR1Key, 32); + pEntry->KeyLifeTime = KeyLifeTime; + pEntry->RassocDeadline = RassocDeadline; + HashId = FT_R1KH_HASH_INDEX(pEntry->PmkR1Name); + + RTMP_SEM_LOCK(&(pAd->ApCfg.FtTab.FT_R1khEntryTabLock)); + + insertTailList(&pAd->ApCfg.FtTab.FT_R1khEntryTab[HashId], + (RT_LIST_ENTRY *)pEntry); + + pAd->ApCfg.FtTab.FT_R1khEntryTabSize++; + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_R1khEntryTabLock)); + + return 0; +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_R1khEntryDelete( + IN PRTMP_ADAPTER pAd, + IN PFT_R1HK_ENTRY pEntry) +{ + UINT8 HashId; + PFT_TAB pFtTab; + + pFtTab = &pAd->ApCfg.FtTab; + HashId = FT_R1KH_HASH_INDEX(pEntry->PmkR1Name); + + RTMP_SEM_LOCK(&(pFtTab->FT_R1khEntryTabLock)); + + delEntryList(&pFtTab->FT_R1khEntryTab[HashId], + (RT_LIST_ENTRY *)pEntry); + + os_free_mem(pAd, pEntry); + + pFtTab->FT_R1khEntryTabSize--; + RTMP_SEM_UNLOCK(&(pFtTab->FT_R1khEntryTabLock)); +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_R1khEntryTabDestroy( + IN PRTMP_ADAPTER pAd) +{ + INT idx; + PFT_R1HK_ENTRY pEntry; + PFT_TAB pFtTab; + + pFtTab = &pAd->ApCfg.FtTab; + pFtTab->FT_R1khEntryTabReady = FALSE; + + RTMP_SEM_LOCK(&(pFtTab->FT_R1khEntryTabLock)); + + for (idx = 0; idx < FT_R1KH_ENTRY_HASH_TABLE_SIZE; idx ++) + { + do + { + pEntry = (PFT_R1HK_ENTRY)removeHeadList( + &(pFtTab->FT_R1khEntryTab[idx])); + if (pEntry != NULL) + os_free_mem(pAd, (PUCHAR)pEntry); + } while (pEntry != NULL); + } + + RTMP_SEM_UNLOCK(&(pFtTab->FT_R1khEntryTabLock)); + NdisFreeSpinLock(&(pFtTab->FT_R1khEntryTabLock)); +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +PFT_R1HK_ENTRY FT_R1khEntryTabLookup( + IN PRTMP_ADAPTER pAd, + IN PUINT8 pPMKR1Name) +{ + UINT8 HashId; + PFT_R1HK_ENTRY pEntry; + + HashId = FT_R1KH_HASH_INDEX(pPMKR1Name); + RTMP_SEM_LOCK(&(pAd->ApCfg.FtTab.FT_R1khEntryTabLock)); + + pEntry = (PFT_R1HK_ENTRY)pAd->ApCfg.FtTab.FT_R1khEntryTab[HashId].pHead; + while(pEntry != NULL) + { + if (RTMPEqualMemory(pPMKR1Name, pEntry->PmkR1Name, FT_KDP_WPA_NAME_MAX_SIZE)) + break; + pEntry = pEntry->pNext; + } + + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_R1khEntryTabLock)); + + return pEntry; +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_FtAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PMAC_TABLE_ENTRY pEntry; + PHEADER_802_11 pHdr; + PFT_ACTION pFtAction; + UINT16 FtActLen; + BOOLEAN IsTerminate; + PFT_INFO pFtInfo = NULL; + PFT_INFO pFtInfoBuf = NULL; + USHORT result; + NDIS_STATUS NStatus; + PUCHAR pFtActFrame = NULL; + ULONG FtActFrameLen = 0; + INT apidx; + PFT_CFG pFtCfg; + + os_alloc_mem(pAd, (UCHAR **)&pFtInfo, sizeof(FT_INFO)); + if (pFtInfo == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d):: pFtInfo alloc failed.\n", __FUNCTION__, __LINE__)); + return; + } + + os_alloc_mem(pAd, (UCHAR **)&pFtInfoBuf, sizeof(FT_INFO)); + if (pFtInfoBuf == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d):: pFtInfoBuf alloc failed.\n", __FUNCTION__, __LINE__)); + goto out; + } + + pHdr = (PHEADER_802_11)Elem->Msg; + pFtAction = (PFT_ACTION)(&Elem->Msg[LENGTH_802_11]); + FtActLen = (Elem->MsgLen - LENGTH_802_11); + + /* Find which MBSSID to be authenticate */ + apidx = get_apidx_by_addr(pAd, pHdr->Addr1); + if (apidx >= pAd->ApCfg.BssidNum) + goto out; + + pFtCfg = &pAd->ApCfg.MBSSID[apidx].FtCfg; + + /* decide self is terminate or not. */ + IsTerminate = (MAC_ADDR_EQUAL(pFtAction->TargetApAddr, + pAd->ApCfg.MBSSID[apidx].wdev.bssid)) ? TRUE : FALSE; + + switch(pFtAction->Action) + { + case FT_ACTION_BT_REQ: + + DBGPRINT(RT_DEBUG_TRACE, + ("Get FT_ACTION_BT_REQ IsTerminate=%d\n", IsTerminate)); + + if (IsTerminate) + { + NStatus = MlmeAllocateMemory(pAd, &pFtActFrame); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("%s: allocate memory failed.\n", + __FUNCTION__)); + goto out; + } + + if (!pFtCfg->FtCapFlag.Dot11rFtEnable) + goto out; + + pEntry = MacTableLookup(pAd, pHdr->Addr2); + if (!pEntry) + pEntry = MacTableInsertEntry(pAd, pHdr->Addr2, + &pAd->ApCfg.MBSSID[apidx].wdev, ENTRY_CLIENT, OPMODE_AP, TRUE); + + /* Parse FT-Request action frame. */ + FT_ReqActionParse(pAd, (FtActLen - sizeof(PFT_ACTION)), + pFtAction->Oct, pFtInfo); + + /* FT-Request frame Handler. */ + NdisZeroMemory(pFtInfoBuf, sizeof(FT_INFO)); + result = FT_AuthReqHandler(pAd, pEntry, pFtInfo, pFtInfoBuf); + + if (result == MLME_SUCCESS) + { + NdisMoveMemory(&pEntry->MdIeInfo, &pFtInfo->MdIeInfo, sizeof(FT_MDIE_INFO)); + + pEntry->AuthState = AS_AUTH_OPEN; + pEntry->Sst = SST_AUTH; + } + + /* Build Ft-Rsp action frame. */ + FtActFrameLen = 0; + FT_MakeFtActFrame(pAd, pFtActFrame, &FtActFrameLen, + FT_ACTION_BT_RSP, pEntry->Addr, pFtAction->TargetApAddr, + result, pFtInfoBuf); + + /* send FT-Rsp action frame to corresponding STA. */ + FT_RrbEnqueue(pAd, pHdr->Addr3, (PFT_ACTION)pFtActFrame, + FtActFrameLen, pEntry->func_tb_idx); + } + else + { + FT_RrbEnqueue(pAd, pFtAction->TargetApAddr, + (PFT_ACTION)pFtAction, FtActLen, apidx); + } + break; + + case FT_ACTION_BT_CONFIRM: + + DBGPRINT(RT_DEBUG_TRACE, + ("Get FT_ACTION_BT_CONFIRM IsTerminate=%d\n", IsTerminate)); + + if (IsTerminate) + { + NDIS_STATUS NStatus = MlmeAllocateMemory(pAd, &pFtActFrame); + + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("%s: allocate memory failed.\n", + __FUNCTION__)); + goto out; + } + + if (Elem->Wcid < MAX_LEN_OF_MAC_TABLE) + pEntry = &pAd->MacTab.Content[Elem->Wcid]; + else + { + DBGPRINT(RT_DEBUG_OFF, ("%s: invalid STA.\n", __FUNCTION__)); + goto out; + } + + if (pEntry->func_tb_idx > pAd->ApCfg.BssidNum) + goto out; + + if (!pFtCfg->FtCapFlag.Dot11rFtEnable) + goto out; + + /* Parse FT-Request action frame. */ + FT_ReqActionParse(pAd, (FtActLen - sizeof(PFT_ACTION)), + pFtAction->Oct, pFtInfo); + + /* FT-Request frame Handler. */ + NdisZeroMemory(pFtInfoBuf, sizeof(FT_INFO)); + os_alloc_mem(pAd, (UCHAR **)&(pFtInfoBuf->RicInfo.pRicInfo), 512); + if (pFtInfoBuf->RicInfo.pRicInfo != NULL) + { + result = FT_AuthConfirmHandler(pAd, pEntry, pFtInfo, pFtInfoBuf); + + /* Build Ft-Ack action frame. */ + FtActFrameLen = 0; + FT_MakeFtActFrame(pAd, pFtActFrame, &FtActFrameLen, + FT_ACTION_BT_ACK, pEntry->Addr, pHdr->Addr3, result, + pFtInfoBuf); + + /* reply FT-Ack action frame to corresponding STA. */ + FT_RrbEnqueue(pAd, pHdr->Addr3, (PFT_ACTION)pFtActFrame, + FtActFrameLen, pEntry->func_tb_idx); + os_free_mem(NULL, pFtInfoBuf->RicInfo.pRicInfo); + } + else + { + goto out; + } + } + else + FT_RrbEnqueue(pAd, pFtAction->TargetApAddr, + pFtAction, FtActLen, apidx); + break; + + case FT_ACTION_BT_RSP: + case FT_ACTION_BT_ACK: + + DBGPRINT(RT_DEBUG_TRACE, + ("Get FT_ACTION_BT_RSP or FT_ACTION_BT_ACK \ + IsTerminate=%d\n", IsTerminate)); + + /* forward it to corrspondign STA. */ + NStatus = MlmeAllocateMemory(pAd, &pFtActFrame); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("%s: allocate memory failed.\n", + __FUNCTION__)); + goto out; + } + + COPY_MAC_ADDR(pHdr->Addr1, pFtAction->StaMac); + COPY_MAC_ADDR(pHdr->Addr2, pAd->ApCfg.MBSSID[apidx].wdev.bssid); + COPY_MAC_ADDR(pHdr->Addr3, pAd->ApCfg.MBSSID[apidx].wdev.bssid); + pHdr->FC.ToDs = 0; + pHdr->FC.FrDs = 1; + + FtActFrameLen = 0; + MakeOutgoingFrame(pFtActFrame, &FtActFrameLen, + Elem->MsgLen, pHdr, + END_OF_ARGS); + + MiniportMMRequest(pAd, 0, pFtActFrame, FtActFrameLen); + break; + + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow action type (%d).\n", \ + __FUNCTION__, pFtAction->Action)); + break; + } +out: + if (pFtInfo) + os_free_mem(NULL, pFtInfo); + + if (pFtInfoBuf) + os_free_mem(NULL, pFtInfoBuf); + + if (pFtActFrame) + MlmeFreeMemory(pAd, pFtActFrame); +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +static VOID FT_RrbEnqueue( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pDA, + IN PFT_ACTION pFtAction, + IN UINT16 FtActLen, + IN UINT32 ApIdx) +{ + FT_KDP_EVT_ACTION FtKdpEvtAction; + + COPY_MAC_ADDR(FtKdpEvtAction.MacDa, pDA); + + switch(pFtAction->Action) + { + case FT_ACTION_BT_REQ: + case FT_ACTION_BT_CONFIRM: + FtKdpEvtAction.RequestType = 0; + COPY_MAC_ADDR(FtKdpEvtAction.MacSa, pFtAction->StaMac); + COPY_MAC_ADDR(FtKdpEvtAction.MacAp, + pAd->ApCfg.MBSSID[ApIdx].wdev.bssid); + break; + + case FT_ACTION_BT_RSP: + case FT_ACTION_BT_ACK: + FtKdpEvtAction.RequestType = 1; + COPY_MAC_ADDR(FtKdpEvtAction.MacSa, pFtAction->TargetApAddr); + COPY_MAC_ADDR(FtKdpEvtAction.MacAp, + pAd->ApCfg.MBSSID[ApIdx].wdev.bssid); + break; + } + + FT_KDP_EVENT_INFORM(pAd, ApIdx, FT_KDP_SIG_ACTION, pFtAction, + FtActLen, &FtKdpEvtAction); + +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_RrbHandler( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPktSrc, + IN INT32 PktLen) +{ + PMAC_TABLE_ENTRY pEntry; + NDIS_STATUS Status; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen; + HEADER_802_11 Hdr; + PFT_RRB pRrb = (PFT_RRB)(pPktSrc + LENGTH_802_3); + PUCHAR pDA; + PUCHAR pSA; + PFT_ACTION pFtAction; + ULONG Wcid; + + + Status = MlmeAllocateMemory(pAd, &pOutBuffer); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_OFF, ("%s: allocate auth buffer fail!\n", + __FUNCTION__)); + return; + } /* End of if */ + + pFtAction = (PFT_ACTION)pRrb->Oct; + + pDA = pPktSrc; + pSA = pFtAction->StaMac; + + pEntry = MacTableLookup(pAd, pSA); + if (pEntry) + Wcid = pEntry->wcid; + else + Wcid = RESERVED_WCID; + + /* Make 802.11 header. */ + ActHeaderInit(pAd, &Hdr, pDA, pSA, pRrb->APAdr); + + /* Make ft action frame. */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr, + pRrb->FTActLen, (PUCHAR)pRrb->Oct, + END_OF_ARGS); + + /* enqueue it into FT action state machine. */ + REPORT_MGMT_FRAME_TO_MLME(pAd, Wcid, pOutBuffer, FrameLen, 0, 0, 0, 0, 0); + + if (pOutBuffer) + os_free_mem(pAd, pOutBuffer); +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_R1KHInfoMaintenance( + IN PRTMP_ADAPTER pAd) +{ + INT HashIdx; + PFT_R1HK_ENTRY pEntry; + PMAC_TABLE_ENTRY pMacEntry; + PFT_TAB pFtTab; + + pFtTab = &pAd->ApCfg.FtTab; + if (pFtTab->FT_R1khEntryTabReady != TRUE) + return; + + RTMP_SEM_LOCK(&pFtTab->FT_R1khEntryTabLock); + for (HashIdx = 0; HashIdx < FT_R1KH_ENTRY_HASH_TABLE_SIZE; HashIdx++) + { + pEntry = (PFT_R1HK_ENTRY)\ + (pFtTab->FT_R1khEntryTab[HashIdx].pHead); + + while (pEntry != NULL) + { + if((pEntry->KeyLifeTime--) == 0) + { + PFT_R1HK_ENTRY pEntryTmp; + MLME_DISASSOC_REQ_STRUCT DisassocReq; + + /* + Kick out the station. + and Info KDP daemon to delete the key. + */ + pMacEntry = MacTableLookup(pAd, pEntry->StaMac); + + DBGPRINT(RT_DEBUG_ERROR, + ("%s:PMKCache timeout.Kick out wcid(%d),delete FT_R1khEntry!\n", + __func__, pMacEntry->wcid)); + + if (pMacEntry) + { + DisassocParmFill(pAd, &DisassocReq, pEntry->StaMac, + MLME_UNSPECIFY_FAIL); + MlmeEnqueue(pAd, AP_ASSOC_STATE_MACHINE, APMT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), (PVOID)&DisassocReq, 0); + } + + /* + Indicate IAPP daemon to delete R0KH-SA + relative to the STA + */ + FT_KDP_EVENT_INFORM(pAd, 0, FT_KDP_SIG_KEY_TIMEOUT, + pEntry->StaMac, MAC_ADDR_LEN, NULL); + + pEntryTmp = pEntry->pNext; + delEntryList(&pFtTab->FT_R1khEntryTab[HashIdx], + (RT_LIST_ENTRY *)pEntry); + os_free_mem(pAd, pEntry); + pFtTab->FT_R1khEntryTabSize--; + pEntry = pEntryTmp; + } + else + pEntry = pEntry->pNext; + } + } + RTMP_SEM_UNLOCK(&pFtTab->FT_R1khEntryTabLock); +} + +VOID FT_ConstructGTKSubIe( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + OUT PFT_FTIE_INFO pFtInfo) +{ + UINT8 gtk_len = 0; + UINT8 pad_len = 0; + UINT8 key_buf[32]; + UINT8 e_key_buf[40]; + UINT8 key_len; + UINT e_key_len; + UCHAR apidx; + UCHAR key_idx; + UCHAR cipher_alg; + PUINT8 gtk; + ULONG TmpLen = 0; + UINT8 remainder; + FT_GTK_KEY_INFO KeyInfo; + UCHAR rsc[8]; + + apidx = pEntry->func_tb_idx; + gtk = pAd->ApCfg.MBSSID[apidx].GTK; + key_idx = pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.DefaultKeyId; + cipher_alg = pAd->SharedKey[pEntry->func_tb_idx][key_idx].CipherAlg; + + DBGPRINT(RT_DEBUG_TRACE, ("%s : key idx(%d) \n", __FUNCTION__, key_idx)); + + switch (cipher_alg) + { + case CIPHER_WEP64: + gtk_len = 5; + break; + case CIPHER_WEP128: + gtk_len = 13; + break; + case CIPHER_TKIP: + gtk_len = 32; + break; + case CIPHER_AES: + gtk_len = 16; + break; + } + + /* The Key field shall be padded before encrypting if the key length + is less than 16 octets or if it is not a multiple of 8. */ + NdisMoveMemory(key_buf, gtk, gtk_len); + key_len = gtk_len; + if ((remainder = gtk_len & 0x07) != 0) + { + INT i; + + pad_len = (8 - remainder); + key_buf[gtk_len] = 0xDD; + for (i = 1; i < pad_len; i++) + key_buf[gtk_len + i] = 0; + + key_len += pad_len; + } + if (key_len < 16) + { + INT i; + + pad_len = 16 - key_len; + for (i = 0; i < pad_len; i++) + key_buf[key_len + i] = 0; + + key_len += pad_len; + } + + NdisZeroMemory(&KeyInfo, sizeof(FT_GTK_KEY_INFO)); + KeyInfo.field.KeyId = key_idx; + KeyInfo.word = cpu2le16(KeyInfo.word); + + /* Get Group RSC form Asic */ + NdisZeroMemory(rsc, 8); + RTMPGetTxTscFromAsic(pAd, apidx, rsc); + + e_key_len = key_len; + AES_Key_Wrap(key_buf, key_len, + &pEntry->PTK[LEN_PTK_KCK], LEN_PTK_KEK, + e_key_buf, &e_key_len); + + /* Construct FT GTK-IE*/ + + MakeOutgoingFrame(pFtInfo->GtkSubIE, &TmpLen, + sizeof(FT_GTK_KEY_INFO), &KeyInfo, + 1, >k_len, + 8, rsc, + e_key_len, e_key_buf, + END_OF_ARGS); + + pFtInfo->GtkLen = TmpLen; + +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +BOOLEAN FT_QueryKeyInfoForKDP( + IN PRTMP_ADAPTER pAd, + IN UINT32 ApIdx, + OUT FT_KDP_EVT_KEY_ELM *pEvtKeyReq) +{ + INT CacheIdx; + ULONG Now; + UINT32 alive_tick; + INT remain_time = 0; + PAP_BSSID_INFO pkeyInfo; + PFT_R1HK_ENTRY pR1khEntry; + UCHAR OriPMKR1Name[FT_KDP_WPA_NAME_MAX_SIZE]; + + /* Search PMK Cache */ + CacheIdx = RTMPSearchPMKIDCache(pAd, ApIdx, pEvtKeyReq->MacAddr); + + if (CacheIdx == -1) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The PMKR0 doesn't exist for %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, PRINT_MAC(pEvtKeyReq->MacAddr))); + return FALSE; + } + + pkeyInfo = &pAd->ApCfg.MBSSID[ApIdx].PMKIDCache.BSSIDInfo[CacheIdx]; + + /* Derive the PMK-R1 and PMK-R1-Name for this R1KH */ + FT_DerivePMKR1(pkeyInfo->PMK, + pkeyInfo->PMKID, + /*pEvtKeyReq->KeyInfo.R1KHID, */ /* peer R1KH-ID */ + pAd->ApCfg.MBSSID[ApIdx].wdev.bssid, + pEvtKeyReq->MacAddr, + pEvtKeyReq->PMKR1, + OriPMKR1Name); + + pR1khEntry = FT_R1khEntryTabLookup(pAd, OriPMKR1Name); + + if (pR1khEntry == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : No initial association information 2 for %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, PRINT_MAC(pEvtKeyReq->MacAddr))); + return FALSE; + } + + FT_DerivePMKR1(pkeyInfo->PMK, + pkeyInfo->PMKID, + pEvtKeyReq->KeyInfo.R1KHID, /* peer R1KH-ID */ + pEvtKeyReq->MacAddr, + pEvtKeyReq->PMKR1, + pEvtKeyReq->PMKR1Name); + + /* calculate the remaine time of PMKR0-Key */ + NdisGetSystemUpTime(&Now); + alive_tick = Now - pkeyInfo->RefreshTime; + if (alive_tick < pAd->ApCfg.MBSSID[ApIdx].PMKCachePeriod) + remain_time = (pAd->ApCfg.MBSSID[ApIdx].PMKCachePeriod - alive_tick)/OS_HZ; + + /* Assign KeyLifeTime and Reassociation Deadline */ + pEvtKeyReq->KeyLifeTime = remain_time; + pEvtKeyReq->ReassocDeadline = FT_REASSOC_DEADLINE; + + /* Assign R0KH-ID */ + pEvtKeyReq->KeyInfo.R0KHIDLen = pAd->ApCfg.MBSSID[ApIdx].FtCfg.FtR0khIdLen; + NdisMoveMemory(pEvtKeyReq->KeyInfo.R0KHID, + pAd->ApCfg.MBSSID[ApIdx].FtCfg.FtR0khId, + pAd->ApCfg.MBSSID[ApIdx].FtCfg.FtR0khIdLen); + + /* Assign PMK-R0-Name */ + NdisMoveMemory(pEvtKeyReq->KeyInfo.PMKR0Name, pkeyInfo->PMKID, LEN_PMK_NAME); + + /* Assign cipher and AKM */ + NdisMoveMemory(pEvtKeyReq->PairwisChipher, pR1khEntry->PairwisChipher, 4); + NdisMoveMemory(pEvtKeyReq->AkmSuite, pR1khEntry->AkmSuite, 4); + + /* Assign R0KH MAC */ + NdisMoveMemory(pEvtKeyReq->R0KH_MAC, pEvtKeyReq->MacAddr, 6); + + return TRUE; + +} + +UINT16 FT_AuthReqRsnValidation( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_CFG pFtCfg, + IN PFT_INFO pFtInfo_in, + OUT PFT_INFO pFtInfo_out) +{ + UINT8 count = 0, ap_idx = 0; + PUINT8 pAkmSuite = NULL; + PUINT8 pPmkR0Name = NULL; + PUINT8 pCipher = NULL; + PFT_R1HK_ENTRY pR1hkEntry = NULL; + UINT8 ft_len = 0; + UINT8 ptk_len; + UINT8 rsnie_len = 0; + PUINT8 rsnie_ptr = NULL; + UINT16 result = MLME_SUCCESS; + struct wifi_dev *wdev; + ULONG temp_len = 0; + +#ifdef R1KH_HARD_RETRY + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_FT, DBG_LVL_OFF, ("%s: (%ld)=>\n", __func__, (jiffies * 1000) / OS_HZ)); +#endif/* R1KH_HARD_RETRY */ + /* Check the validity of the received RSNIE */ + if ((result = APValidateRSNIE(pAd, pEntry, pFtInfo_in->RSN_IE, pFtInfo_in->RSNIE_Len)) != MLME_SUCCESS) + { + return result; + } + + ap_idx = pEntry->func_tb_idx; + wdev = &pAd->ApCfg.MBSSID[ap_idx].wdev; + + /* Extract the PMK-R0-Name from the received RSNIE */ + pPmkR0Name = WPA_ExtractSuiteFromRSNIE(pFtInfo_in->RSN_IE, pFtInfo_in->RSNIE_Len, PMKID_LIST, &count); + +#ifdef WH_EZ_SETUP + if(!pPmkR0Name) + { + /* reject the Authentication Request with status code 53 ("Invalid PMKID") */ + DBGPRINT_ERR(("%s : The peer PMKID is emtpy\n", __FUNCTION__)); + return FT_STATUS_CODE_INVALID_PMKID; + } +#endif + +#ifdef FT_RSN_DEBUG + hex_dump("FT PMK-R0-NAME", pPmkR0Name, count * LEN_PMK_NAME); +#endif /* FT_RSN_DEBUG */ + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(&pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev) || ez_is_triband()){ + + FT_DerivePMKR0(pAd->ApCfg.MBSSID[pEntry->func_tb_idx].PMK, LEN_PMK, + (PUINT8)pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen, + pFtCfg->FtMdId, + pFtInfo_in->FtIeInfo.R0khId, // use rokhid passed by sta + pFtInfo_in->FtIeInfo.R0khIdLen, + pEntry->Addr, + pEntry->FT_PMK_R0, + pEntry->FT_PMK_R0_NAME); + + FT_DerivePMKR1(pEntry->FT_PMK_R0, + pEntry->FT_PMK_R0_NAME, + wdev->bssid, /* R1KHID*/ + pEntry->Addr, /* S1KHID*/ + pEntry->FT_PMK_R1, + pEntry->FT_PMK_R1_NAME); + + + /* Extract the AKM suite from the received RSNIE */ + pAkmSuite = WPA_ExtractSuiteFromRSNIE(pFtInfo_in->RSN_IE, + pFtInfo_in->RSNIE_Len, AKM_SUITE, &count); + if(pAkmSuite == NULL){ // add check for expected value + /* + It doesn't a negotiated AKM of Fast BSS Transition, + the AP shall reject the Authentication Request with + status code 43 ("Invalid AKMP"). + */ + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_FT, DBG_LVL_ERROR, + ("%s : The AKM is invalid\n", __FUNCTION__)); + return MLME_INVALID_AKMP; + } + + /* Extract the pairwise cipher suite from the received RSNIE */ + pCipher = WPA_ExtractSuiteFromRSNIE(pFtInfo_in->RSN_IE, + pFtInfo_in->RSNIE_Len, PAIRWISE_SUITE, &count); + if(pCipher == NULL){ // add check for expected value + /* + If the non-AP STA selects a pairwise cipher suite in the RSNIE + that is different than the ones used in the Initial Mobility + Domain association, then the AP shall reject the Authentication + Request with status code 19 ("Invalid Pair-wise Cipher"). + */ + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_FT, DBG_LVL_ERROR, + ("%s : The pairwise-cipher is invalid\n", __FUNCTION__)); + return MLME_INVALID_PAIRWISE_CIPHER; + } + + /* Delete previous entry */ + pR1hkEntry = FT_R1khEntryTabLookup(pAd, pEntry->FT_PMK_R1_NAME); + if (pR1hkEntry != NULL) + { + FT_R1khEntryDelete(pAd, pR1hkEntry); + } + /* Update R1KH table */ + if (pCipher != NULL) + NdisMoveMemory(pEntry->FT_UCipher, pCipher, 4); + + if (pAkmSuite != NULL) + NdisMoveMemory(pEntry->FT_Akm, pAkmSuite, 4); + + FT_R1khEntryInsert(pAd, + pEntry->FT_PMK_R0_NAME, + pEntry->FT_PMK_R1_NAME, + pEntry->FT_PMK_R1, + pCipher, + pAkmSuite, + (pAd->ApCfg.MBSSID[pEntry->func_tb_idx].PMKCachePeriod/OS_HZ), + 20, + pFtInfo_in->FtIeInfo.R0khId, + pFtInfo_in->FtIeInfo.R0khIdLen, + pEntry->Addr); + + + pR1hkEntry = FT_R1khEntryTabLookup(pAd, pEntry->FT_PMK_R1_NAME); + + } + else +#endif + if (pPmkR0Name){ + + /* The R1KH of the target AP uses the value of PMKR0Name and other + information in the frame to calculate PMKR1Name. */ + FT_DerivePMKR1Name(pPmkR0Name, + wdev->bssid, + pEntry->Addr, + pEntry->FT_PMK_R1_NAME); + + hex_dump("pPmkR0Name=", pPmkR0Name, LEN_PMK_NAME); + hex_dump("pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Bssid=", wdev->bssid, 6); + hex_dump("pEntry->Addr=", pEntry->Addr, 6); + hex_dump("pEntry->FT_PMK_R1_NAME=", pEntry->FT_PMK_R1_NAME, sizeof(pEntry->FT_PMK_R1_NAME)); +#ifdef R1KH_HARD_RETRY +R1KH_QUERY: +#endif/* R1KH_HARD_RETRY */ + + /* Look up the R1KH Table */ + pR1hkEntry = FT_R1khEntryTabLookup(pAd, pEntry->FT_PMK_R1_NAME); + + /* If the target AP does not have the key identified by PMKR1Name, + it may retrieve that key from the R0KH identified by the STA. */ + if ((pR1hkEntry == NULL) || + (RTMPEqualMemory(pEntry->FT_PMK_R1_NAME, pR1hkEntry->PmkR1Name, LEN_PMK_NAME) == FALSE)) + { + if (pEntry->FT_R1kh_CacheMiss_Times <= FT_R1KH_CACHE_MISS_THRESHOLD) { + FT_KDP_EVT_KEY_ELM EvtKeyReq; + + NdisZeroMemory(&EvtKeyReq, sizeof(FT_KDP_EVT_KEY_ELM)); +#ifndef R1KH_HARD_RETRY + /* sw retry */ + pEntry->FT_R1kh_CacheMiss_Times++; +#endif /* R1KH_HARD_RETRY */ + /* make up request content */ + EvtKeyReq.ElmId = FT_KDP_ELM_ID_PRI; + EvtKeyReq.ElmLen = FT_KDP_ELM_PRI_LEN; + EvtKeyReq.OUI[0] = FT_KDP_ELM_PRI_OUI_0; + EvtKeyReq.OUI[1] = FT_KDP_ELM_PRI_OUI_1; + EvtKeyReq.OUI[2] = FT_KDP_ELM_PRI_OUI_2; + NdisMoveMemory(EvtKeyReq.MacAddr, pEntry->Addr, ETH_ALEN); + NdisMoveMemory(EvtKeyReq.KeyInfo.S1KHID, pEntry->Addr, FT_KDP_S1KHID_MAX_SIZE); + NdisMoveMemory(EvtKeyReq.KeyInfo.R1KHID, wdev->bssid, FT_KDP_R1KHID_MAX_SIZE); + + /* Issue an event to query PMKR1 information from R0KH */ + FT_KDP_EVENT_INFORM(pAd, pEntry->func_tb_idx, FT_KDP_SIG_KEY_REQ_AUTO, + &EvtKeyReq, sizeof(FT_KDP_EVT_KEY_ELM), NULL); +#ifdef R1KH_HARD_RETRY + +/*spec defines auth rsp should happen within 30 ms*/ + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_FT, DBG_LVL_OFF, ("@(%ld)snd iapp!\n", + (jiffies * 1000) / OS_HZ)); + /* msleep(20); */ + if (!RTMP_OS_WAIT_FOR_COMPLETION_TIMEOUT(&pEntry->ack_r1kh, RTMPMsecsToJiffies(30))) + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_FT, DBG_LVL_OFF, + ("@(%ld)snd timeout!\n", (jiffies * 1000) / OS_HZ)); + + /* only hard retry one time! */ + if ((pEntry->FT_R1kh_CacheMiss_Hard++) < FT_R1KH_CACHE_MISS_HARD_RETRY_THRESHOLD) + goto R1KH_QUERY; + else { + pEntry->FT_R1kh_CacheMiss_Hard = 0;/* reset the hard retry */ + + /* sw retry++ */ + pEntry->FT_R1kh_CacheMiss_Times++; + return MLME_FAIL_NO_RESOURCE; + } +#endif /* R1KH_HARD_RETRY */ + } else { + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_FT, DBG_LVL_ERROR, + ("%s : R0KH unreachable!!! \n", __func__)); + /* If the requested R0KH is not reachable, the AP shall respond + to the Authentication Request with status code 28 ("R0KH unreachable"). */ + return FT_STATUS_CODE_R0KH_UNREACHABLE; + } + } + + /* If the RSNIE in the Authentication Request frame contains an invalid + PMKR0Name, and the AP has determined that it is an invalid PMKR0Name, + the AP shall reject the Authentication Request with status code 53 + ("Invalid PMKID"). */ + if ((pR1hkEntry == NULL) || + (RTMPEqualMemory(pPmkR0Name, pR1hkEntry->PmkR0Name, LEN_PMK_NAME) == FALSE)) + { + DBGPRINT_ERR(("%s : The PMKID is invalid\n", __FUNCTION__)); + hex_dump("Peer PMKR0Name", pPmkR0Name, LEN_PMK_NAME); + hex_dump("Own PMKR0Name", pR1hkEntry->PmkR0Name, LEN_PMK_NAME); + return FT_STATUS_CODE_INVALID_PMKID; + } + } +#ifndef WH_EZ_SETUP + else + { + /* reject the Authentication Request with status code 53 ("Invalid PMKID") */ + DBGPRINT_ERR(("%s : The peer PMKID is emtpy\n", __FUNCTION__)); + return FT_STATUS_CODE_INVALID_PMKID; + } +#endif + if (pR1hkEntry == NULL) + { + DBGPRINT_ERR(("%s : The R1KH table doesn't exist\n", __FUNCTION__)); + return FT_STATUS_CODE_R0KH_UNREACHABLE; + } + + /* Update the Reassocation Deadline */ + pEntry->AssocDeadLine = pR1hkEntry->RassocDeadline; + + /* Extract the AKM suite from the received RSNIE */ + pAkmSuite = WPA_ExtractSuiteFromRSNIE(pFtInfo_in->RSN_IE, pFtInfo_in->RSNIE_Len, AKM_SUITE, &count); + if ((pAkmSuite == NULL) || + (RTMPEqualMemory(pAkmSuite, pR1hkEntry->AkmSuite, 4) == FALSE)) + { + /* It doesn't a negotiated AKM of Fast BSS Transition, the AP + shall reject the Authentication Request with status code 43 ("Invalid AKMP"). */ + DBGPRINT_ERR(("%s : The AKM is invalid\n", __FUNCTION__)); + return MLME_INVALID_AKMP; + } + + /* Extract the pairwise cipher suite from the received RSNIE */ + pCipher = WPA_ExtractSuiteFromRSNIE(pFtInfo_in->RSN_IE, pFtInfo_in->RSNIE_Len, PAIRWISE_SUITE, &count); + if ((pCipher == NULL) || + (RTMPEqualMemory(pCipher, pR1hkEntry->PairwisChipher, 4) == FALSE)) + { + /* If the non-AP STA selects a pairwise cipher suite in the RSNIE + that is different than the ones used in the Initial Mobility + Domain association, then the AP shall reject the Authentication + Request with status code 19 ("Invalid Pair-wise Cipher"). */ + DBGPRINT_ERR(("%s : The pairwise-cipher is invalid\n", __FUNCTION__)); + return MLME_INVALID_PAIRWISE_CIPHER; + } + + /* Check the validity of R0KHID */ + if ((pFtInfo_in->FtIeInfo.R0khIdLen != pR1hkEntry->R0khIdLen) || + (RTMPEqualMemory(pFtInfo_in->FtIeInfo.R0khId, + pR1hkEntry->R0khId, + pR1hkEntry->R0khIdLen) == FALSE)) + { + /* If the FTIE in the FT Request frame contains an invalid R0KH-ID, + the AP shall reject the FT Request with status code 55 ("Invalid FTIE"). */ + DBGPRINT_ERR(("%s : The FTIE is invalid\n", __FUNCTION__)); + return FT_STATUS_CODE_INVALID_FTIE; + } + + /* Get PMK-R1 from R1KH Table */ + NdisMoveMemory(pEntry->FT_PMK_R1, pR1hkEntry->PmkR1Key, LEN_PMK); + + /* Get SNonce from Auth-req */ + NdisMoveMemory(pEntry->SNonce, pFtInfo_in->FtIeInfo.SNonce, LEN_NONCE); + + /* Generate ANonce randomly */ + GenRandom(pAd, wdev->bssid, pEntry->ANonce); + + hex_dump("anonce", pEntry->ANonce, 32); + hex_dump("snonce", pEntry->SNonce, 32); + + if (pEntry->WepStatus == Ndis802_11TKIPEnable) + ptk_len = 32+32; + else + ptk_len = 32+16; + + /* Derive FT PTK and PTK-NAME */ + FT_DerivePTK(pEntry->FT_PMK_R1, + pEntry->FT_PMK_R1_NAME, + pEntry->ANonce, + pEntry->SNonce, + wdev->bssid, + pEntry->Addr, + ptk_len, + pEntry->PTK, + pEntry->PTK_NAME); + + ft_len = sizeof(FT_FTIE); + + /* Prepare some information for authentication response using */ + NdisMoveMemory(pFtInfo_out->FtIeInfo.ANonce, pEntry->ANonce, LEN_NONCE); + NdisMoveMemory(pFtInfo_out->FtIeInfo.SNonce, pEntry->SNonce, LEN_NONCE); + + pFtInfo_out->FtIeInfo.R0khIdLen = pR1hkEntry->R0khIdLen; + NdisMoveMemory(pFtInfo_out->FtIeInfo.R0khId, + pR1hkEntry->R0khId, + pR1hkEntry->R0khIdLen); + ft_len += (2 + pR1hkEntry->R0khIdLen); + + pFtInfo_out->FtIeInfo.R1khIdLen = MAC_ADDR_LEN; + NdisMoveMemory(pFtInfo_out->FtIeInfo.R1khId, + wdev->bssid, + MAC_ADDR_LEN); + ft_len += (2 + MAC_ADDR_LEN); + + /* Update the total length for FTIE */ + pFtInfo_out->FtIeInfo.Len = ft_len; + + /* Prepare RSNIE for authentication response */ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) || + (wdev->AuthMode == Ndis802_11AuthModeWPA1WPA2)) + { + rsnie_len = pAd->ApCfg.MBSSID[ap_idx].RSNIE_Len[1]; + rsnie_ptr = &pAd->ApCfg.MBSSID[ap_idx].RSN_IE[1][0]; + } + else + { + rsnie_len = pAd->ApCfg.MBSSID[ap_idx].RSNIE_Len[0]; + rsnie_ptr = &pAd->ApCfg.MBSSID[ap_idx].RSN_IE[0][0]; + } + + pFtInfo_out->RSNIE_Len = 0; + RTMPInsertRSNIE(pFtInfo_out->RSN_IE, + &temp_len, + rsnie_ptr, + rsnie_len, + pPmkR0Name, + LEN_PMK_NAME); + + pFtInfo_out->RSNIE_Len = (UCHAR)temp_len; +#ifdef R1KH_HARD_RETRY + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_FT, DBG_LVL_OFF, ("%s:<=(%ld)\n", __func__, (jiffies * 1000) / OS_HZ)); +#endif/* R1KH_HARD_RETRY */ + return MLME_SUCCESS; +} + +UINT16 FT_AuthConfirmRsnValidation( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pFtInfo_in) +{ + PFT_FTIE_INFO pPeerFtIe; + PUINT8 pmkid_ptr = NULL; + UINT8 pmkid_count = 0; + UINT8 ft_mic[16]; + PFT_R1HK_ENTRY pR1hkEntry = NULL; + PUINT8 pAkmSuite = NULL; + UINT8 count = 0; + + + NdisZeroMemory(ft_mic, sizeof(ft_mic)); + /* The R1KH of the target AP verifies the MIC in the FTIE in + the Reassociation Request frame, and shall discard the + request if the MIC is incorrect. */ + FT_CalculateMIC(pEntry->Addr, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid, + pEntry->PTK, + 3, + pFtInfo_in->RSN_IE, + pFtInfo_in->RSNIE_Len, + pFtInfo_in->MdIeInfo.pMdIe, + pFtInfo_in->MdIeInfo.Len + 2, + pFtInfo_in->FtIeInfo.pFtIe, + pFtInfo_in->FtIeInfo.Len + 2, + pFtInfo_in->RicInfo.RicIEs, + pFtInfo_in->RicInfo.RicIEsLen, + ft_mic); + + if (!RTMPEqualMemory(ft_mic, pFtInfo_in->FtIeInfo.MIC, FT_MIC_LEN)) + { + DBGPRINT_ERR(("%s : MIC is different\n", __FUNCTION__)); + hex_dump("received MIC", pFtInfo_in->FtIeInfo.MIC, FT_MIC_LEN); + hex_dump("desired MIC", ft_mic, FT_MIC_LEN); + return 0xFFFF; + } + + pPeerFtIe = &pFtInfo_in->FtIeInfo; + + /* Look up the R1KH Table */ + pR1hkEntry = FT_R1khEntryTabLookup(pAd, pEntry->FT_PMK_R1_NAME); + if (pR1hkEntry == NULL) + { + DBGPRINT_ERR(("%s : Invalid R1KH table in target AP\n", __FUNCTION__)); + return FT_STATUS_CODE_RESERVED; + } + + /* Extract the AKM suite from the received RSNIE */ + pAkmSuite = WPA_ExtractSuiteFromRSNIE(pFtInfo_in->RSN_IE, + pFtInfo_in->RSNIE_Len, + AKM_SUITE, &count); + + if ((pAkmSuite == NULL) || + (RTMPEqualMemory(pAkmSuite, pR1hkEntry->AkmSuite, 4) == FALSE)) + { + /* It doesn't a negotiated AKM of Fast BSS Transition, the AP + shall reject the Authentication Request with status code 43 + ("Invalid AKMP"). */ + DBGPRINT_ERR(("%s : Invalid AKMP\n", __FUNCTION__)); + return MLME_INVALID_AKMP; + } + + /* If the FTIE in the Reassociation Request frame contains + a different R0KH-ID, R1KH-ID, ANonce, or SNonce, the AP + shall reject the Reassociation Request with status code + 55 ("Invalid FTIE"). */ + if ((RTMPEqualMemory(pPeerFtIe->R0khId, pR1hkEntry->R0khId, pR1hkEntry->R0khIdLen) == FALSE) || + (RTMPEqualMemory(pPeerFtIe->R1khId, pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid, MAC_ADDR_LEN) == FALSE) || + (RTMPEqualMemory(pPeerFtIe->ANonce, pEntry->ANonce, 32) == FALSE) || + (RTMPEqualMemory(pPeerFtIe->SNonce, pEntry->SNonce, 32) == FALSE)) + { + DBGPRINT_ERR(("%s : Invalid FTIE\n", __FUNCTION__)); + return FT_STATUS_CODE_INVALID_FTIE; + } + + /* If the RSNIE in the Reassociation Request frame contains an invalid + PMKR1Name, the AP shall reject the Reassociation Request with status + code 53 ("Invalid PMKID"). */ + pmkid_ptr = WPA_ExtractSuiteFromRSNIE(pFtInfo_in->RSN_IE, pFtInfo_in->RSNIE_Len, PMKID_LIST, &pmkid_count); + if ((pmkid_ptr == NULL) || + (RTMPEqualMemory(pmkid_ptr, pEntry->FT_PMK_R1_NAME, LEN_PMK_NAME) == FALSE)) + { + DBGPRINT_ERR(("%s : Invalid PMKID\n", __FUNCTION__)); + return FT_STATUS_CODE_INVALID_PMKID; + } + + return MLME_SUCCESS; + +} + +UINT16 FT_AssocReqRsnValidation( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pFtInfo_in, + OUT PFT_INFO pFtInfo_out) +{ + PFT_FTIE_INFO pPeerFtIe; + PUINT8 pmkid_ptr = NULL; + UINT8 pmkid_count = 0; + UINT8 ft_mic[16]; + UINT8 rsnie_len = 0; + PUINT8 rsnie_ptr = NULL; + PFT_R1HK_ENTRY pR1hkEntry = NULL; + PUINT8 pAkmSuite = NULL; + UINT8 count = 0; + ULONG temp_len = 0; + + NdisZeroMemory(ft_mic, sizeof(ft_mic)); + /* The R1KH of the target AP verifies the MIC in the FTIE in + the Reassociation Request frame, and shall discard the + request if the MIC is incorrect. */ + FT_CalculateMIC(pEntry->Addr, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid, + pEntry->PTK, + 5, + pFtInfo_in->RSN_IE, + pFtInfo_in->RSNIE_Len, + pFtInfo_in->MdIeInfo.pMdIe, + pFtInfo_in->MdIeInfo.Len + 2, + pFtInfo_in->FtIeInfo.pFtIe, + pFtInfo_in->FtIeInfo.Len + 2, + pFtInfo_in->RicInfo.RicIEs, + pFtInfo_in->RicInfo.RicIEsLen, + ft_mic); + + if (!RTMPEqualMemory(ft_mic, pFtInfo_in->FtIeInfo.MIC, 16)) + { + DBGPRINT_ERR(("%s : MIC is different\n", __FUNCTION__)); + hex_dump("received MIC", pFtInfo_in->FtIeInfo.MIC, 16); + hex_dump("desired MIC", ft_mic, 16); + return 0xFFFF; + } + + pPeerFtIe = &pFtInfo_in->FtIeInfo; + + /* Look up the R1KH Table */ + pR1hkEntry = FT_R1khEntryTabLookup(pAd, pEntry->FT_PMK_R1_NAME); + if (pR1hkEntry == NULL) + { + DBGPRINT_ERR(("%s : Invalid R1KH table in target AP\n", __FUNCTION__)); + return FT_STATUS_CODE_RESERVED; + } + + /* Extract the AKM suite from the received RSNIE */ + pAkmSuite = WPA_ExtractSuiteFromRSNIE(pFtInfo_in->RSN_IE, + pFtInfo_in->RSNIE_Len, + AKM_SUITE, &count); + + if ((pAkmSuite == NULL) || + (RTMPEqualMemory(pAkmSuite, pR1hkEntry->AkmSuite, 4) == FALSE)) + { + /* It doesn't a negotiated AKM of Fast BSS Transition, the AP + shall reject the Authentication Request with status code 43 + ("Invalid AKMP"). */ + DBGPRINT_ERR(("%s : Invalid AKMP\n", __FUNCTION__)); + return MLME_INVALID_AKMP; + } + + /* If the FTIE in the Reassociation Request frame contains + a different R0KH-ID, R1KH-ID, ANonce, or SNonce, the AP + shall reject the Reassociation Request with status code + 55 ("Invalid FTIE"). */ + if ((RTMPEqualMemory(pPeerFtIe->R0khId, pR1hkEntry->R0khId, pR1hkEntry->R0khIdLen) == FALSE) || + (RTMPEqualMemory(pPeerFtIe->R1khId, pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid, MAC_ADDR_LEN) == FALSE) || + (RTMPEqualMemory(pPeerFtIe->ANonce, pEntry->ANonce, 32) == FALSE) || + (RTMPEqualMemory(pPeerFtIe->SNonce, pEntry->SNonce, 32) == FALSE)) + { + DBGPRINT_ERR(("%s : Invalid FTIE\n", __FUNCTION__)); + return FT_STATUS_CODE_INVALID_FTIE; + } + + /* If the RSNIE in the Reassociation Request frame contains an invalid + PMKR1Name, the AP shall reject the Reassociation Request with status + code 53 ("Invalid PMKID"). */ + pmkid_ptr = WPA_ExtractSuiteFromRSNIE(pFtInfo_in->RSN_IE, pFtInfo_in->RSNIE_Len, PMKID_LIST, &pmkid_count); + if ((pmkid_ptr == NULL) || + (RTMPEqualMemory(pmkid_ptr, pEntry->FT_PMK_R1_NAME, LEN_PMK_NAME) == FALSE)) + { + DBGPRINT_ERR(("%s : Invalid PMKID\n", __FUNCTION__)); + return FT_STATUS_CODE_INVALID_PMKID; + } + + /* Prepare RSNIE for outgoing frame */ + if ((pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK) || + (pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.AuthMode == Ndis802_11AuthModeWPA1WPA2)) + { + rsnie_len = pAd->ApCfg.MBSSID[pEntry->func_tb_idx].RSNIE_Len[1]; + rsnie_ptr = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].RSN_IE[1][0]; + } + else + { + rsnie_len = pAd->ApCfg.MBSSID[pEntry->func_tb_idx].RSNIE_Len[0]; + rsnie_ptr = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].RSN_IE[0][0]; + } + + pFtInfo_out->RSNIE_Len = 0; + RTMPInsertRSNIE(pFtInfo_out->RSN_IE, + &temp_len, + rsnie_ptr, + rsnie_len, + pEntry->FT_PMK_R1_NAME, + LEN_PMK_NAME); + + pFtInfo_out->RSNIE_Len = (UCHAR)temp_len; + + /* Prepare MIC-control and MIC field of FTIE for outgoing frame. */ + pFtInfo_out->FtIeInfo.MICCtr.field.IECnt = 3; + NdisZeroMemory(pFtInfo_out->FtIeInfo.MIC, 16); + + /* Prepare ANonce and Snonce field of FTIE for outgoing frame */ + NdisMoveMemory(pFtInfo_out->FtIeInfo.ANonce, pEntry->ANonce, LEN_NONCE); + NdisMoveMemory(pFtInfo_out->FtIeInfo.SNonce, pEntry->SNonce, LEN_NONCE); + + /* Prepare GTK related information of FTIE for outgoing frame */ + FT_ConstructGTKSubIe(pAd, pEntry, &pFtInfo_out->FtIeInfo); + /*ft_len += (2 + pFtInfo_out->FtIeInfo.GtkLen); */ + + /* Prepare RIC-Response */ + + return MLME_SUCCESS; + +} +#endif /* CONFIG_AP_SUPPORT */ + + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_FillMdIeInfo( + PEID_STRUCT eid_ptr, + PFT_MDIE_INFO pMdIeInfo) +{ + PFT_MDIE pMdIe; + + pMdIeInfo->Len = 3; + pMdIeInfo->pMdIe = eid_ptr; /* store the pointer of the original MD-IE for MIC calculating */ + + pMdIe = (PFT_MDIE)(eid_ptr->Octet); + FT_SET_MDID(pMdIeInfo->MdId, pMdIe->MdId); + + NdisMoveMemory(&(pMdIeInfo->FtCapPlc.word), &pMdIe->FtCapPlc.word, + sizeof(FT_CAP_AND_POLICY)); +} + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_FillFtIeInfo( + PEID_STRUCT eid_ptr, + PFT_FTIE_INFO pFtIeInfo) +{ + PFT_FTIE pFtIe; + PFT_OPTION_FIELD subEidPtr; + UINT16 MicCtrBuf; + INT RemainLen; + PUINT8 ptr; + + RemainLen = eid_ptr->Len; + pFtIeInfo->Len = eid_ptr->Len; + pFtIeInfo->pFtIe = eid_ptr; /* store the pointer of the original FT-IE for MIC calculating */ + + pFtIe = (PFT_FTIE)eid_ptr->Octet; + NdisMoveMemory(&MicCtrBuf, &(pFtIe->MICCtr.word), + sizeof(FT_MIC_CTR_FIELD)); + pFtIeInfo->MICCtr.word = le2cpu16(MicCtrBuf); + RemainLen -= 2; + + NdisMoveMemory(pFtIeInfo->MIC, pFtIe->MIC, 16); + RemainLen -= 16; + + NdisMoveMemory(pFtIeInfo->ANonce, pFtIe->ANonce, 32); + RemainLen -= 32; + + NdisMoveMemory(pFtIeInfo->SNonce, pFtIe->SNonce, 32); + RemainLen -= 32; + + /* Pare sub-element field. */ + /*subEidPtr = (PFT_OPTION_FIELD)(pFtIe->Option); */ + ptr = pFtIe->Option; + while (RemainLen > 0) + { + subEidPtr = (PFT_OPTION_FIELD)ptr; + + switch(subEidPtr->SubElementId) + { + case FT_R0KH_ID: + if ((subEidPtr->Len > 0) && (subEidPtr->Len <=FT_ROKH_ID_LEN)) + { + pFtIeInfo->R0khIdLen = subEidPtr->Len; + NdisMoveMemory(pFtIeInfo->R0khId, subEidPtr->Oct, + pFtIeInfo->R0khIdLen); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s Invalid R0KHID Length (%d)\n", + __FUNCTION__, subEidPtr->Len)); + break; + + case FT_R1KH_ID: + if (subEidPtr->Len == FT_R1KH_ID_LEN) + { + pFtIeInfo->R1khIdLen = subEidPtr->Len; + NdisMoveMemory(pFtIeInfo->R1khId, subEidPtr->Oct, + pFtIeInfo->R1khIdLen); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s Invalid R1KHID Length (%d)\n", + __FUNCTION__, subEidPtr->Len)); + break; + + case FT_GTK: + if (subEidPtr->Len > 0) + { + pFtIeInfo->GtkLen = subEidPtr->Len; + NdisMoveMemory(pFtIeInfo->GtkSubIE, &subEidPtr->Oct[0], subEidPtr->Len); + } + break; + + default: + break; + } + + ptr += (subEidPtr->Len + 2); + RemainLen -= (subEidPtr->Len + 2); + + /* avoid infinite loop. */ + if (subEidPtr->Len == 0) + break; + } +} + + +/* + ======================================================================== + + Routine Description: + It is used to derive the first level FT Key Hierarchy key, PMK-R0, + and its identifier PMKR0Name. + (IEEE 802.11r/D9.0, 8.5.1.5.3) + + Arguments: + + Return Value: + + Note: + R0-Key-Data = + KDF-384(XXKey, "FT-R0", + SSIDlength || SSID || MDID || + R0KHlength || R0KH-ID || S0KH-ID) + PMK-R0 = L(R0-Key-Data, 0, 256) + PMK-R0Name-Salt = L(R0-Key-Data, 256, 128) + + PMKR0Name = Truncate-128(SHA-256("FT-R0N" || PMK-R0Name-Salt)) + + ======================================================================== +*/ +VOID FT_DerivePMKR0( + IN PUINT8 xxkey, + IN INT xxkey_len, + IN PUINT8 ssid, + IN INT ssid_len, + IN PUINT8 mdid, + IN PUINT8 r0khid, + IN INT r0khid_len, + IN PUINT8 s0khid, + OUT PUINT8 pmkr0, + OUT PUINT8 pmkr0_name) +{ + const char label_name[] = "FT-R0N"; + UCHAR R0KeyData[96]; + UCHAR PmkR0NameSalt[20]; + UCHAR temp_result[64]; + UCHAR context[128]; + UINT c_len=0; + + /* =========================== */ + /* PMK-R0 derivation */ + /* =========================== */ + + /* construct the concatenated context for PMK-R0 */ + /* SSIDlength(1 byte) */ + /* SSID(0~32 bytes) */ + /* MDID(2 bytes) */ + /* R0KHlength(1 byte) */ + /* R0KH-ID(5~48 bytes) */ + /* S0KH-ID(6 bytes) */ + + hex_dump("xxkey", (PUCHAR)xxkey, xxkey_len); + hex_dump("label", (PUCHAR)label_name, sizeof(label_name)); + hex_dump("ssid", (PUCHAR)ssid, ssid_len); + hex_dump("mdis", (PUCHAR)mdid, 2); + hex_dump("r0khid", (PUCHAR)r0khid, r0khid_len); + hex_dump("s0khid", (PUCHAR)s0khid, MAC_ADDR_LEN); + + /* Initial the related context */ + NdisZeroMemory(temp_result, 64); + NdisZeroMemory(context, 128); + c_len = 0; + + /* concatenate the SSIDlength with a single octet */ + context[0] = ssid_len; + c_len += 1; + + /* concatenate the SSID with its length */ + NdisMoveMemory(&context[c_len], ssid, ssid_len); + c_len += ssid_len; + + /* concatenate the MDID with 2-octets */ + NdisMoveMemory(&context[c_len], mdid, 2); + c_len += 2; + + /* concatenate the R0KHlength with a single octet */ + context[c_len] = r0khid_len; + c_len += 1; + + /* concatenate the R0KH-ID with its length */ + NdisMoveMemory(&context[c_len], r0khid, r0khid_len); + c_len += r0khid_len; + + /* concatenate the S0KH-ID with its length */ + NdisMoveMemory(&context[c_len], s0khid, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* Calculate a 48-bytes key material through FT-KDF */ + KDF(xxkey, xxkey_len, (PUINT8)"FT-R0", 5, context, c_len, R0KeyData, 48); + + /* PMK-R0 key shall be computed as the first 256 bits (bits 0-255) */ + /* of the R0-Key-Data. The latter 128 bits of R0-Key-Data shall */ + /* be used as the PMK-R0Name-Salt to generate the PMKR0Name. */ + NdisMoveMemory(pmkr0, R0KeyData, LEN_PMK); + NdisMoveMemory(PmkR0NameSalt, &R0KeyData[32], LEN_PMK_NAME); + + /* =============================== */ + /* PMK-R0-Name derivation */ + /* =============================== */ + + /* Initial the related parameter for PMK-R0-Name derivation */ + NdisZeroMemory(temp_result, 64); + NdisZeroMemory(context, 128); + c_len = 0; + + /* concatenate the label with its length */ + NdisMoveMemory(context, label_name, strlen(label_name)); + c_len += strlen(label_name); + + /* concatenate the PMK-R0Name-Salt with its length */ + NdisMoveMemory(&context[c_len], PmkR0NameSalt, LEN_PMK_NAME); + c_len += LEN_PMK_NAME; + + RT_SHA256(context, c_len, temp_result); + NdisMoveMemory(pmkr0_name, temp_result, LEN_PMK_NAME); + + hex_dump("PMK-R0", (UCHAR *)pmkr0, LEN_PMK); + hex_dump("PMK-R0-Name", (UCHAR *)pmkr0_name, LEN_PMK_NAME); + +} + +/* + ======================================================================== + + Routine Description: + It is used to derive the second level FT Key Hierarchy key + identifier, PMK-R1-NAME. + (IEEE 802.11r/D9.0, 8.5.1.5.4) + + Arguments: + + Return Value: + + Note: + PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name || R1KH-ID || S1KH-ID)) + + ======================================================================== +*/ +VOID FT_DerivePMKR1Name( + IN PUINT8 pmkr0_name, + IN PUINT8 r1khid, + IN PUINT8 s1khid, + OUT PUINT8 pmkr1_name) +{ + const char label_name[] = "FT-R1N"; + UCHAR temp_result[64]; + UCHAR context[128]; + UINT c_len = 0; + + /* =============================== */ + /* PMK-R1-Name derivation */ + /* =============================== */ + + /* Initial the related parameter for PMK-R1-Name derivation */ + NdisZeroMemory(temp_result, 64); + NdisZeroMemory(context, 128); + c_len = 0; + + /* concatenate the label with its length */ + NdisMoveMemory(context, label_name, strlen(label_name)); + c_len += strlen(label_name); + + /* concatenate the PMK-R1-Name with 16-octets */ + NdisMoveMemory(&context[c_len], pmkr0_name, LEN_PMK_NAME); + c_len += LEN_PMK_NAME; + + /* concatenate the R1KH-ID with 6-octets */ + NdisMoveMemory(&context[c_len], r1khid, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* concatenate the S1KH-ID with 6-octets */ + NdisMoveMemory(&context[c_len], s1khid, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* derive PMK-R1-Name */ + RT_SHA256(context, c_len, temp_result); + NdisMoveMemory(pmkr1_name, temp_result, LEN_PMK_NAME); + + hex_dump("PMK-R1-Name", (UCHAR *)pmkr1_name, LEN_PMK_NAME); + +} + +/* + ======================================================================== + + Routine Description: + It is used to derive the second level FT Key Hierarchy key, PMK-R1, + and its identifier PMKR1Name. + (IEEE 802.11r/D9.0, 8.5.1.5.4) + + Arguments: + + Return Value: + + Note: + PMK-R1 = KDF-256(PMK-R0, "FT-R1", R1KH-ID || S1KH-ID) + PMKR1Name = Truncate-128(SHA-256("FT-R1N" || PMKR0Name || R1KH-ID || S1KH-ID)) + + ======================================================================== +*/ +VOID FT_DerivePMKR1( + IN PUINT8 pmkr0, + IN PUINT8 pmkr0_name, + IN PUINT8 r1khid, + IN PUINT8 s1khid, + OUT PUINT8 pmkr1, + OUT PUINT8 pmkr1_name) +{ + /*const char label_name[] = "FT-R1N"; */ + UCHAR temp_result[64]; + UCHAR context[128]; + UINT c_len=0; + + /* =========================== */ + /* PMK-R1 derivation */ + /* =========================== */ + + DBGPRINT(RT_DEBUG_TRACE, ("%s:\n", __FUNCTION__)); + hex_dump("pmkr0", pmkr0, 32); + hex_dump("pmkr0_name", pmkr0_name, LEN_PMK_NAME); + hex_dump("r1khid", r1khid, MAC_ADDR_LEN); + hex_dump("s1khid", s1khid, MAC_ADDR_LEN); + hex_dump("pmkr1", pmkr1, 32); + hex_dump("pmkr1_name", pmkr1_name, 16); + + /* construct the concatenated context for PMK-R1 */ + /* R1KH-ID(6 bytes) */ + /* S1KH-ID(6 bytes) */ + + /* Initial the related parameter */ + NdisZeroMemory(temp_result, 64); + NdisZeroMemory(context, 128); + c_len = 0; + + /* concatenate the R1KH-ID with 6-octets */ + NdisMoveMemory(&context[c_len], r1khid, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* concatenate the S1KH-ID with 6-octets */ + NdisMoveMemory(&context[c_len], s1khid, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* Calculate a 32-bytes key material through FT-KDF */ + KDF(pmkr0, LEN_PMK, (PUINT8)"FT-R1", 5, context, c_len, temp_result, 32); + NdisMoveMemory(pmkr1, temp_result, LEN_PMK); + + /* =============================== */ + /* PMK-R1-Name derivation */ + /* =============================== */ + FT_DerivePMKR1Name(pmkr0_name, + r1khid, + s1khid, + pmkr1_name); + + hex_dump("PMK-R1", (UCHAR *)pmkr1, LEN_PMK); + hex_dump("PMK-R1-Name", (UCHAR *)pmkr1_name, LEN_PMK_NAME); + +} + +/* + ======================================================================== + + Routine Description: + It is used to derive the third level FT Key Hierarchy key, PTK, + and its identifier PTKName. + (IEEE 802.11r/D9.0, 8.5.1.5.4) + + Arguments: + + Return Value: + + Note: + PTK = KDF-PTKLen(PMK-R1, "FT-PTK", SNonce || ANonce || BSSID || STA-ADDR) + PTKName = + Truncate-128(SHA-256(PMKR1Name || "FT-PTKN" || SNonce || ANonce || BSSID || + STA-ADDR)) + + ======================================================================== +*/ +VOID FT_DerivePTK( + IN PUINT8 pmkr1, + IN PUINT8 pmkr1_name, + IN PUINT8 a_nonce, + IN PUINT8 s_nonce, + IN PUINT8 bssid, + IN PUINT8 sta_mac, + IN UINT key_len, + OUT PUINT8 ptk, + OUT PUINT8 ptk_name) +{ + const char label_name[] = "FT-PTKN"; + UCHAR temp_result[64]; + UCHAR context[128]; + UINT c_len=0; + + /* =============================== */ + /* PTK derivation */ + /* =============================== */ + + /* construct the concatenated context for PTK */ + /* SNonce (32 bytes) */ + /* ANonce (32 bytes) */ + /* BSSID (6 bytes) */ + /* STA-ADDR (6-bytes) */ + + /* Initial the related parameter */ + NdisZeroMemory(temp_result, 64); + NdisZeroMemory(context, 128); + c_len = 0; + + /* concatenate the SNonce with 32-octets */ + NdisMoveMemory(&context[c_len], s_nonce, LEN_NONCE); + c_len += LEN_NONCE; + + /* concatenate the ANonce with 32-octets */ + NdisMoveMemory(&context[c_len], a_nonce, LEN_NONCE); + c_len += LEN_NONCE; + + /* concatenate the BSSID with 6-octets */ + NdisMoveMemory(&context[c_len], bssid, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* concatenate the STA-ADDR with 6-octets */ + NdisMoveMemory(&context[c_len], sta_mac, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* Calculate a key material through FT-KDF */ + KDF(pmkr1, + LEN_PMK, + (PUINT8)"FT-PTK", + 6, + context, + c_len, + temp_result, + key_len); + NdisMoveMemory(ptk, temp_result, key_len); + + /* =============================== */ + /* PTK-Name derivation */ + /* =============================== */ + + /* Initial the related parameter for PTK-Name derivation */ + NdisZeroMemory(temp_result, 64); + NdisZeroMemory(context, 128); + c_len = 0; + + /* concatenate the PMK-R1-Name with 16-octets */ + NdisMoveMemory(&context[c_len], pmkr1_name, LEN_PMK_NAME); + c_len += LEN_PMK_NAME; + + /* concatenate the label with its length */ + NdisMoveMemory(&context[c_len], label_name, strlen(label_name)); + c_len += strlen(label_name); + + /* concatenate the SNonce with 32-octets */ + NdisMoveMemory(&context[c_len], s_nonce, LEN_NONCE); + c_len += LEN_NONCE; + + /* concatenate the ANonce with 32-octets */ + NdisMoveMemory(&context[c_len], a_nonce, LEN_NONCE); + c_len += LEN_NONCE; + + /* concatenate the BSSID with 6-octets */ + NdisMoveMemory(&context[c_len], bssid, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* concatenate the STA-ADDR with 6-octets */ + NdisMoveMemory(&context[c_len], sta_mac, MAC_ADDR_LEN); + c_len += MAC_ADDR_LEN; + + /* Derive PTKName */ + RT_SHA256(context, c_len, temp_result); + NdisMoveMemory(ptk_name, temp_result, LEN_PMK_NAME); + + /*hex_dump("ANonce", (UCHAR *)a_nonce, LEN_NONCE); */ + /*hex_dump("SNonce", (UCHAR *)s_nonce, LEN_NONCE); */ + + hex_dump("PTK", (UCHAR *)ptk, key_len); + hex_dump("PTK-Name", (UCHAR *)ptk_name, LEN_PMK_NAME); + +} + + +/* + ======================================================================== + + Routine Description: + Calcaulate FT MIC. It is used during Fast BSS transition. + + Arguments: + + Return Value: + + Note: + It's defined in IEEE 802.11r D9.0 11A.8.4/8.5 + The MIC shall be calculated using the KCK and the AES-128-CMAC + algorithm. The output of the AES-128-CMAC shall be 128 bits. + + The MIC shall be calculated on the concatenation, in the + following order, of: + - non-AP STA MAC address (6 octets) + - Target AP MAC address (6 octets) + - Transaction sequence number (1 octet) + - Contents of the RSN information element. + - Contents of the MDIE. + - Contents of the FTIE, with the MIC field of the FTIE set to 0. + - Contents of the RIC-Request (if present) + + ======================================================================== +*/ +VOID FT_CalculateMIC( + IN PUINT8 sta_addr, + IN PUINT8 ap_addr, + IN PUINT8 kck, + IN UINT8 seq, + IN PUINT8 rsnie, + IN UINT8 rsnie_len, + IN PUINT8 mdie, + IN UINT8 mdie_len, + IN PUINT8 ftie, + IN UINT8 ftie_len, + IN PUINT8 ric, + IN UINT8 ric_len, + OUT PUINT8 mic) +{ + UCHAR *OutBuffer; + ULONG FrameLen = 0; + ULONG TmpLen = 0; + UINT mlen = AES_KEY128_LENGTH; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + /* allocate memory for MIC calculation */ + os_alloc_mem(NULL, (PUCHAR *)&OutBuffer, 512); + if (OutBuffer == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("!!!FT_CalculateMIC: no memory!!!\n")); + return; + } + + /* make a header frame for calculating MIC. */ + MakeOutgoingFrame(OutBuffer, &TmpLen, + MAC_ADDR_LEN, sta_addr, + MAC_ADDR_LEN, ap_addr, + 1, &seq, + END_OF_ARGS); + FrameLen += TmpLen; + + /* concatenate RSNIE */ + if (rsnie_len != 0) + { + MakeOutgoingFrame(OutBuffer + FrameLen, &TmpLen, + rsnie_len, rsnie, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* concatenate MDIE */ + if (mdie_len != 0) + { + MakeOutgoingFrame(OutBuffer + FrameLen, &TmpLen, + mdie_len, mdie, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* concatenate FTIE */ + if (ftie != 0) + { + /* The MIC field of the FTIE set to 0 */ + NdisZeroMemory(ftie + 4, 16); + + MakeOutgoingFrame(OutBuffer + FrameLen, &TmpLen, + ftie_len, ftie, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* concatenate RIC-Request/Response if present */ + if (ric != 0) + { + MakeOutgoingFrame(OutBuffer + FrameLen, &TmpLen, + ric_len, ric, + END_OF_ARGS); + FrameLen += TmpLen; + } + + /* Calculate MIC */ + AES_CMAC(OutBuffer, FrameLen, kck, LEN_PTK_KCK, mic, &mlen); + + os_free_mem(NULL, OutBuffer); +} + +#ifdef CONFIG_AP_SUPPORT +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +void FT_rtmp_read_parameters_from_file( + IN PRTMP_ADAPTER pAd, + RTMP_STRING *tmpbuf, + RTMP_STRING *pBuffer) +{ + INT Loop; + + /* FtSupport */ + if(RTMPGetKeyParameter("FtSupport", tmpbuf, 32, pBuffer, TRUE)) + { + RTMP_STRING *macptr; + for (Loop = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), Loop++) + { + if (Loop >= MAX_MBSSID_NUM(pAd)) + break; + + if(simple_strtol(macptr, 0, 10) != 0) /*Enable */ + pAd->ApCfg.MBSSID[Loop].FtCfg.FtCapFlag.Dot11rFtEnable = TRUE; + else /*Disable */ + pAd->ApCfg.MBSSID[Loop].FtCfg.FtCapFlag.Dot11rFtEnable = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Dot11rFtEnable=%d\n", + Loop, pAd->ApCfg.MBSSID[Loop].FtCfg.FtCapFlag.Dot11rFtEnable)); + } + } + + /* FtRic */ + if(RTMPGetKeyParameter("FtRic", tmpbuf, 32, pBuffer, TRUE)) + { + RTMP_STRING *macptr; + for (Loop = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), Loop++) + { + if (Loop >= MAX_MBSSID_NUM(pAd)) + break; + + if(simple_strtol(macptr, 0, 10) != 0) /*Enable */ + pAd->ApCfg.MBSSID[Loop].FtCfg.FtCapFlag.RsrReqCap = TRUE; + else /*Disable */ + pAd->ApCfg.MBSSID[Loop].FtCfg.FtCapFlag.RsrReqCap = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Dot11rFtRic=%d\n", + Loop, pAd->ApCfg.MBSSID[Loop].FtCfg.FtCapFlag.RsrReqCap)); + } + } + + /* FtOtd */ + if(RTMPGetKeyParameter("FtOtd", tmpbuf, 32, pBuffer, TRUE)) + { + RTMP_STRING *macptr; + for (Loop = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), Loop++) + { + if (Loop >= MAX_MBSSID_NUM(pAd)) + break; + + if(simple_strtol(macptr, 0, 10) != 0) /*Enable */ + pAd->ApCfg.MBSSID[Loop].FtCfg.FtCapFlag.FtOverDs = TRUE; + else /*Disable */ + pAd->ApCfg.MBSSID[Loop].FtCfg.FtCapFlag.FtOverDs = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) Dot11rFtOtd=%d\n", + Loop, pAd->ApCfg.MBSSID[Loop].FtCfg.FtCapFlag.FtOverDs)); + } + } + + for (Loop = 0; Loop < MAX_MBSSID_NUM(pAd); Loop++) + { + RTMP_STRING tok_str[16]; + + /* + FtMdId: + FtMdId shall be a value of two octets. + */ + NdisZeroMemory(tok_str, sizeof(tok_str)); + snprintf(tok_str, sizeof(tok_str), "FtMdId%d", Loop + 1); + if(RTMPGetKeyParameter(tok_str, tmpbuf, FT_MDID_LEN + 1, pBuffer, FALSE)) + { + if (strlen(tmpbuf) == FT_MDID_LEN) + { + NdisMoveMemory(pAd->ApCfg.MBSSID[Loop].FtCfg.FtMdId, tmpbuf, FT_MDID_LEN); + DBGPRINT(RT_DEBUG_TRACE, ("%s::FtMdid(%d)=%c%c\n", __FUNCTION__, Loop, + pAd->ApCfg.MBSSID[Loop].FtCfg.FtMdId[0], + pAd->ApCfg.MBSSID[Loop].FtCfg.FtMdId[1])); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: Invalid MdId=%s\n", __FUNCTION__,tmpbuf)); + } + } + + /* + FtR0khId: + FtR0khId shall be in string of 1 ~ 48 octets. + */ + NdisZeroMemory(tok_str, sizeof(tok_str)); + snprintf(tok_str, sizeof(tok_str), "FtR0khId%d", Loop + 1); + if(RTMPGetKeyParameter(tok_str, tmpbuf, FT_ROKH_ID_LEN + 1, pBuffer, FALSE)) + { + if (strlen(tmpbuf) <= FT_ROKH_ID_LEN) + { + NdisMoveMemory(pAd->ApCfg.MBSSID[Loop].FtCfg.FtR0khId, tmpbuf, strlen(tmpbuf)); + pAd->ApCfg.MBSSID[Loop].FtCfg.FtR0khId[strlen(tmpbuf)] = '\0'; + DBGPRINT(RT_DEBUG_TRACE, ("%s::FtR0khId(%d)=%s\n", __FUNCTION__, Loop, + pAd->ApCfg.MBSSID[Loop].FtCfg.FtR0khId)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: Invalid R0khId(%d)=%s Len=%d\n", + __FUNCTION__, Loop, tmpbuf, strlen(tmpbuf))); + } + } + } +} + +INT Set_FT_Enable(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + INT apidx = pObj->ioctl_if; + PFT_CFG pFtCfg; + ULONG Value; + + Value = (UINT) simple_strtol(arg, 0, 10); + + if (apidx > pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid interface number (%d).\n", + __FUNCTION__, apidx)); + return TRUE; + } + + + pFtCfg = &pAd->ApCfg.MBSSID[pObj->ioctl_if].FtCfg; + pFtCfg->FtCapFlag.Dot11rFtEnable = (Value == 0 ? FALSE : TRUE); + + return TRUE; +} + +INT Set_FT_Mdid(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + INT apidx = pObj->ioctl_if; + PFT_CFG pFtCfg; + + if (apidx > pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid interface number (%d).\n", + __FUNCTION__, apidx)); + return TRUE; + } + + pFtCfg = &pAd->ApCfg.MBSSID[pObj->ioctl_if].FtCfg; + NdisMoveMemory(pFtCfg->FtMdId, arg, FT_MDID_LEN); + + return TRUE; +} + +INT Set_FT_R0khid(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + INT apidx = pObj->ioctl_if; + PFT_CFG pFtCfg; + + if (apidx > pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid interface number (%d).\n", + __FUNCTION__, apidx)); + return TRUE; + } + + if (strlen(arg) > FT_ROKH_ID_LEN) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid R0KHID Length (%d).\n", + __FUNCTION__, strlen(arg))); + DBGPRINT(RT_DEBUG_ERROR, ("%s: The length shall be in range from 1 to 48 octects.\n", + __FUNCTION__)); + return TRUE; + } + + pFtCfg = &pAd->ApCfg.MBSSID[pObj->ioctl_if].FtCfg; + NdisMoveMemory(pFtCfg->FtR0khId, arg, strlen(arg)); + pFtCfg->FtR0khIdLen = strlen(arg); + + return TRUE; +} + +INT Set_FT_RIC(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + INT apidx = pObj->ioctl_if; + PFT_CFG pFtCfg; + ULONG Value; + + Value = (UINT) simple_strtol(arg, 0, 10); + + if (apidx > pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid interface number (%d).\n", + __FUNCTION__, apidx)); + return TRUE; + } + + pFtCfg = &pAd->ApCfg.MBSSID[pObj->ioctl_if].FtCfg; + pFtCfg->FtCapFlag.RsrReqCap = (Value == 0 ? FALSE : TRUE); + + return TRUE; +} + +INT Set_FT_OTD(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + INT apidx = pObj->ioctl_if; + PFT_CFG pFtCfg; + ULONG Value; + + Value = (UINT) simple_strtol(arg, 0, 10); + + if (apidx > pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid interface number (%d).\n", + __FUNCTION__, apidx)); + return TRUE; + } + + pFtCfg = &pAd->ApCfg.MBSSID[pObj->ioctl_if].FtCfg; + pFtCfg->FtCapFlag.FtOverDs = (Value == 0 ? FALSE : TRUE); + + return TRUE; +} + +INT Show_FTConfig_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + INT apidx = pObj->ioctl_if; + PFT_CFG pFtCfg; + + if (apidx >= pAd->ApCfg.BssidNum) + return -1; + + pFtCfg = &pAd->ApCfg.MBSSID[pObj->ioctl_if].FtCfg; + + DBGPRINT(RT_DEBUG_OFF, ("MDID=%c%c\n", pFtCfg->FtMdId[0], pFtCfg->FtMdId[1])); + DBGPRINT(RT_DEBUG_OFF, ("R0KHID=%s, Len=%d\n", pFtCfg->FtR0khId, pFtCfg->FtR0khIdLen)); + DBGPRINT(RT_DEBUG_OFF, ("FT Enable=%d\n", pFtCfg->FtCapFlag.Dot11rFtEnable)); + DBGPRINT(RT_DEBUG_OFF, ("FT RIC=%d\n", pFtCfg->FtCapFlag.RsrReqCap)); + DBGPRINT(RT_DEBUG_OFF, ("FT OTD=%d\n", pFtCfg->FtCapFlag.FtOverDs)); + + return TRUE; +} +#endif /* CONFIG_AP_SUPPORT */ + +#endif /* DOT11R_FT_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ft_iocl.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ft_iocl.c new file mode 100644 index 000000000..d06698684 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ft_iocl.c @@ -0,0 +1,1093 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + + Abstract: + + All related IEEE802.11r IOCTL function body. + +***************************************************************************/ + +#ifdef DOT11R_FT_SUPPORT + + + +#include "rt_config.h" + +#define TYPE_FUNC +#define FT_FUNC_SIMULATION + +#ifdef FT_FUNC_SIMULATION +#endif /* FT_FUNC_SIMULATION */ + +/* ----- Private Variable ----- */ +#ifdef FT_FUNC_SIMULATION +static UCHAR gFT_MAC_STA[ETH_ALEN] = { 0x00, 0x0e, 0x2e, 0x82, 0xe7, 0x6d }; +UCHAR gFT_MAC_OldAP[ETH_ALEN] = { 0x00, 0x0e, 0x2e, 0x12, 0x34, 0x56 }; + + +#endif /* FT_FUNC_SIMULATION */ + + +/* ----- Extern Function ----- */ +#ifdef CONFIG_AP_SUPPORT +extern BOOLEAN FT_KDP_R0KH_InfoAdd( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pR0KHID, + IN UCHAR *pMAC, + IN UINT32 IP); +#endif /* CONFIG_AP_SUPPORT */ + + +/* ----- Private Function ----- */ +#define FT_CMD_INPUT_PARAM_DECLARATION \ + PRTMP_ADAPTER pAd, INT32 Argc, CHAR *pArgv + +#ifdef CONFIG_AP_SUPPORT +#ifndef FT_KDP_FUNC_SOCK_COMM +static VOID FT_KDP_CMD_EventList(FT_CMD_INPUT_PARAM_DECLARATION); +#endif /* FT_KDP_FUNC_SOCK_COMM */ + +static VOID FT_KDP_CMD_DbgFlagCtrl(FT_CMD_INPUT_PARAM_DECLARATION); + +#ifdef FT_FUNC_SIMULATION +static VOID FT_KDP_CMD_SimEvtFtAssoc(FT_CMD_INPUT_PARAM_DECLARATION); +static VOID FT_KDP_CMD_SimEvtFtReAssoc(FT_CMD_INPUT_PARAM_DECLARATION); +static VOID FT_KDP_CMD_SimKeyReq(FT_CMD_INPUT_PARAM_DECLARATION); + +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD +static VOID FT_KDP_CMD_SimR0KH_InfoCreate(FT_CMD_INPUT_PARAM_DECLARATION); +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + +static VOID FT_RIC_CMD_SimRscReqHdlTspec(FT_CMD_INPUT_PARAM_DECLARATION); +static VOID FT_RIC_CMD_SimRscReqHandle(FT_CMD_INPUT_PARAM_DECLARATION); +static VOID FT_RRB_CMD_SimSend(FT_CMD_INPUT_PARAM_DECLARATION); +static VOID FT_11K_CMD_SimInfoReq(FT_CMD_INPUT_PARAM_DECLARATION); +static VOID FT_11K_CMD_SimKeyShow(FT_CMD_INPUT_PARAM_DECLARATION); +#endif /* FT_FUNC_SIMULATION */ +#endif /* CONFIG_AP_SUPPORT */ + + +static UINT32 FT_CMD_UtilHexGet(CHAR **ppArgv); +static UINT32 FT_CMD_UtilNumGet(CHAR **ppArgv); +static VOID FT_CMD_UtilMacGet(CHAR **ppArgv, UCHAR *pDevMac); + + + +#ifdef CONFIG_AP_SUPPORT +void test11r(PRTMP_ADAPTER pAd) +{ + FT_KDP_CMD_SimEvtFtAssoc(pAd, 0, NULL); +} +#endif /* CONFIG_AP_SUPPORT */ + +/* +======================================================================== +Routine Description: + Get argument number value. + +Arguments: + **ppArgv - input parameters + +Return Value: + decimal number + +Note: +======================================================================== +*/ +static UINT32 TYPE_FUNC FT_CMD_UtilHexGet( + IN CHAR **ppArgv) +{ + CHAR buf[3], *pNum; + UINT32 ID; + UCHAR Value; + + + pNum = (*ppArgv); + + buf[0] = 0x30; + buf[1] = 0x30; + buf[2] = 0; + + for(ID=0; ID= 2) + memcpy(buf, (*ppArgv), 2); + else + buf[1] = (**ppArgv); + /* End of if */ + + (*ppArgv) += ID; + if ((**ppArgv) == '_') + (*ppArgv) ++; /* skip _ */ + /* End of if */ + + FT_ARG_ATOH(buf, &Value); + return (UINT32)Value; +} /* End of FT_CMD_UtilHexGet */ + + +/* +======================================================================== +Routine Description: + Get argument number value. + +Arguments: + *pArgv - input parameters + +Return Value: + decimal number + +Note: +======================================================================== +*/ +static UINT32 TYPE_FUNC FT_CMD_UtilNumGet( + IN CHAR **ppArgv) +{ + CHAR buf[20], *pNum; + UINT32 ID; + + + pNum = (*ppArgv); + + for(ID=0; IDApCfg.FtTab.FT_KdpLock)); + + pInfo = FT_KDP_CB->R0KH_InfoHead; + IdInfo = 1; + + while(pInfo != NULL) + { + DBGPRINT_RAW(RT_DEBUG_OFF, ("\n%03d. R0KHID = 0x", IdInfo)); + + for(IdArray=0; IdArrayR0KHID); IdArray++) + { + if (IdArray == (sizeof(pInfo->R0KHID)>>1)) + DBGPRINT_RAW(RT_DEBUG_OFF, ("\n ")); + /* End of if */ + + DBGPRINT_RAW(RT_DEBUG_OFF, (" %02x", pInfo->R0KHID[IdArray])); + } /* End of for */ + + DBGPRINT_RAW(RT_DEBUG_OFF, + ("\n%03d. MAC = 0x%02x:%02x:%02x:%02x:%02x:%02x\n", + IdInfo, pInfo->MAC[0], pInfo->MAC[1], pInfo->MAC[2], + pInfo->MAC[3], pInfo->MAC[4], pInfo->MAC[5])); + + DBGPRINT_RAW(RT_DEBUG_OFF, + ("%03d. IP = %d.%d.%d.%d\n", IdInfo, + (pInfo->IP & 0x000000FF) >> 0, + (pInfo->IP & 0x0000FF00) >> 8, + (pInfo->IP & 0x00FF0000) >> 16, + (pInfo->IP & 0xFF000000) >> 24)); + + pInfo = pInfo->pNext; + IdInfo ++; + } /* End of while */ + + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\n")); + return TRUE; +} /* End of FT_KDP_CMD_R0KH_InfoShow */ +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + + +#ifndef FT_KDP_FUNC_SOCK_COMM +/* +======================================================================== +Routine Description: + List all queued events. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID TYPE_FUNC FT_KDP_CMD_EventList( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + FT_KDP_SIGNAL *pFtKdp; + ULONG SplFlags; + + + pFtKdp = (FT_KDP_SIGNAL *)FT_KDP_CB->EventList.pHead; + if (pFtKdp == NULL) + { + DBGPRINT_RAW(RT_DEBUG_OFF, ("ft_kdp> No any event!\n")); + return; + } /* End of if */ + + DBGPRINT_RAW(RT_DEBUG_OFF, ("\nEvent\n")); + DBGPRINT_RAW(RT_DEBUG_OFF, ("----------------------------------------------------\n")); + + RTMP_SEM_LOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + + while(pFtKdp != NULL) + { + switch(pFtKdp->Sig) + { + case FT_KDP_SIG_KEY_TIMEOUT: + DBGPRINT_RAW(RT_DEBUG_OFF, ("KEY TIMEOUT\n")); + break; + + case FT_KDP_SIG_KEY_REQ: + DBGPRINT_RAW(RT_DEBUG_OFF, ("KEY REQUEST\n")); + break; + + case FT_KDP_SIG_FT_ASSOCIATION: + DBGPRINT_RAW(RT_DEBUG_OFF, ("STATION FT ASSOCIATION\n")); + break; + + case FT_KDP_SIG_TERMINATE: + DBGPRINT_RAW(RT_DEBUG_OFF, ("TERMINATE\n")); + break; + + default: + DBGPRINT_RAW(RT_DEBUG_OFF, ("UNKNOWN\n")); + break; + } /* End of switch */ + + pFtKdp = (FT_KDP_SIGNAL *)pFtKdp->pNext; + } /* End of while */ + + RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\n")); +} /* End of FT_KDP_CMD_EventList */ +#endif /* FT_KDP_FUNC_SOCK_COMM */ + + +/* +======================================================================== +Routine Description: + Change the debug flag of IAPP daemon. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID FT_KDP_CMD_DbgFlagCtrl( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + INT32 DebugLevel; + + + DebugLevel = FT_CMD_UtilNumGet(&pArgv); + + FT_KDP_EVENT_INFORM(pAd, BSS0, FT_KSP_SIG_DEBUG_TRACE, + &DebugLevel, sizeof(DebugLevel), NULL); +} /* End of FT_KDP_CMD_DbgFlagCtrl */ + + +#ifdef FT_FUNC_SIMULATION +/* +======================================================================== +Routine Description: + List all queued events. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID TYPE_FUNC FT_KDP_CMD_SimEvtFtAssoc( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + FT_KDP_EVT_ASSOC EvtAssoc; + + + /* fill the station information */ + EvtAssoc.SeqNum = 0x1234; + NdisMoveMemory(EvtAssoc.MacAddr, gFT_MAC_STA, MAC_ADDR_LEN); + + /* inform other APs a station associated to us */ + FT_KDP_EVENT_INFORM(pAd, BSS0, FT_KDP_SIG_FT_ASSOCIATION, + &EvtAssoc, sizeof(FT_KDP_EVT_ASSOC), NULL); +} /* End of FT_KDP_CMD_SimEvtFtAssoc */ + + +/* +======================================================================== +Routine Description: + List all queued events. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID TYPE_FUNC FT_KDP_CMD_SimEvtFtReAssoc( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + FT_KDP_EVT_REASSOC EvtReAssoc; + + + /* fill the station information */ + EvtReAssoc.SeqNum = 0x1234; + NdisMoveMemory(EvtReAssoc.MacAddr, gFT_MAC_STA, MAC_ADDR_LEN); + NdisMoveMemory(EvtReAssoc.OldApMacAddr, gFT_MAC_OldAP, MAC_ADDR_LEN); + + /* inform other APs a station associated to us */ + FT_KDP_EVENT_INFORM(pAd, BSS0, FT_KDP_SIG_FT_REASSOCIATION, + &EvtReAssoc, sizeof(FT_KDP_EVT_REASSOC), NULL); +} /* End of FT_KDP_CMD_SimEvtFtReAssoc */ + + +/* +======================================================================== +Routine Description: + Request PMK-R1 Key from R0KH. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + 1. Command Format: + [R0KHID 1st byte (HEX)] [R1KHID 1st byte (HEX)] +======================================================================== +*/ +static VOID TYPE_FUNC FT_KDP_CMD_SimKeyReq( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + FT_KDP_EVT_KEY_ELM EvtKeyReq, *pEvtKeyReq; + UCHAR R0KHID_Byte, R1KHID_Byte; + + + /* init */ + memset(&EvtKeyReq, 0, sizeof(FT_KDP_EVT_KEY_ELM)); + pEvtKeyReq = &EvtKeyReq; + + /* fill request content */ + pEvtKeyReq->ElmId = FT_KDP_ELM_ID_PRI; + pEvtKeyReq->ElmLen = FT_KDP_ELM_PRI_LEN; + pEvtKeyReq->OUI[0] = FT_KDP_ELM_PRI_OUI_0; + pEvtKeyReq->OUI[1] = FT_KDP_ELM_PRI_OUI_1; + pEvtKeyReq->OUI[2] = FT_KDP_ELM_PRI_OUI_2; + + memcpy(pEvtKeyReq->MacAddr, gFT_MAC_STA, ETH_ALEN); + + R0KHID_Byte = FT_CMD_UtilHexGet(&pArgv); + memset(pEvtKeyReq->KeyInfo.R0KHID, R0KHID_Byte, FT_KDP_R0KHID_MAX_SIZE); + + R1KHID_Byte = FT_CMD_UtilHexGet(&pArgv); + memset(pEvtKeyReq->KeyInfo.R1KHID, R1KHID_Byte, FT_KDP_R1KHID_MAX_SIZE); + + memcpy(pEvtKeyReq->KeyInfo.S1KHID, gFT_MAC_STA, FT_KDP_S1KHID_MAX_SIZE); + memset(pEvtKeyReq->KeyInfo.RSV, 0x00, sizeof(pEvtKeyReq->KeyInfo.RSV)); + + /* request PMK-R1 Key (our R1KH vs. the station) from the R0KH */ + FT_KDP_EVENT_INFORM(pAd, BSS0, FT_KDP_SIG_KEY_REQ, + pEvtKeyReq, sizeof(FT_KDP_EVT_KEY_ELM), NULL); +} /* End of FT_KDP_CMD_SimKeyReq */ + + +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD +/* +======================================================================== +Routine Description: + Create a R0KH information. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + 1. Command Format: + [R0KHID 1st byte (HEX)] [IP1] [IP2] [IP3] [IP4] +======================================================================== +*/ +static VOID TYPE_FUNC FT_KDP_CMD_SimR0KH_InfoCreate( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + UCHAR R0KHID[FT_KDP_R0KHID_MAX_SIZE]; + UCHAR MAC[ETH_ALEN]; + UCHAR ByteFirst; + UCHAR IP[4]; + + + ByteFirst = FT_CMD_UtilHexGet(&pArgv); + IP[0] = FT_CMD_UtilNumGet(&pArgv); + IP[1] = FT_CMD_UtilNumGet(&pArgv); + IP[2] = FT_CMD_UtilNumGet(&pArgv); + IP[3] = FT_CMD_UtilNumGet(&pArgv); + + memset(R0KHID, ByteFirst, sizeof(R0KHID)); + memset(MAC, ByteFirst, sizeof(MAC)); + MAC[0] = 0x00; + + FT_KDP_R0KH_InfoAdd(pAd, R0KHID, MAC, *(UINT32 *)IP); +} /* End of FT_KDP_CMD_SimR0KH_InfoCreate */ +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + + +/* +======================================================================== +Routine Description: + Simulate to make a resource request. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + 1. Command Format: + [1-WME] [TID:0~7] [dir:0~3] [access:1~3] [UP:0~7] [ack:0~1] + [nom size:byte] [inact:sec] [mean data rate:bps] [min phy rate:bps] + [surp factor:>=1] [tclas processing:0~1] + 2. dir: 0 - uplink, 1 - dnlink, 2 - bidirectional link, 3 - direct link + access: 1 - EDCA, 2 - HCCA, 3 - EDCA + HCCA + ack: 0 - normal ACK, 1 - no ACK +======================================================================== +*/ +static VOID FT_RIC_CMD_SimRscReqHdlTspec( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ +} /* End of FT_RIC_CMD_SimRscReqHdlTspec */ + + +/* +======================================================================== +Routine Description: + Simulate to handle resource requests. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + Test example: + + iwpriv ra0 set acm=50 + iwpriv ra0 set acm=10_0_0_1_1 + + 1. OK case + iwpriv ra0 set ft=512_1_7_0_1_7_0_500_3000_200000_11000000_10_0 + iwpriv ra0 set ft=512_1_6_1_1_6_0_500_3000_200000_11000000_10_0 + iwpriv ra0 set ft=512_1_5_0_1_5_0_500_3000_200000_11000000_10_0 + iwpriv ra0 set ft=512_1_4_1_1_4_0_500_3000_200000_11000000_10_0 + + 2. Fail case + iwpriv ra0 set ft=512_1_7_0_1_7_0_500_3000_200000_11000000_10_0 + iwpriv ra0 set ft=512_1_5_0_1_5_0_500_3000_200000_11000000_10_0 + iwpriv ra0 set ft=512_1_6_1_1_6_0_500_3000_11000000_11000000_10_0 + iwpriv ra0 set ft=512_1_4_1_1_4_0_500_3000_11000000_11000000_10_0 + + iwpriv ra0 set ft=510 +======================================================================== +*/ +static VOID TYPE_FUNC FT_RIC_CMD_SimRscReqHandle( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) + { +} + + +/* +======================================================================== +Routine Description: + Simulate to send a RRB frame. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + 1. Command Format: + [0(REQ)/1(RSP)] [PeerMAC] +======================================================================== +*/ +static VOID TYPE_FUNC FT_RRB_CMD_SimSend( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + FT_KDP_EVT_ACTION ActionCB, *pActionCB; + UCHAR MacPeer[6]; + + + pActionCB = &ActionCB; + + pActionCB->RequestType = FT_CMD_UtilNumGet(&pArgv); + FT_CMD_UtilMacGet(&pArgv, MacPeer); + + memcpy(pActionCB->MacDa, MacPeer, ETH_ALEN); + memset(pActionCB->MacSa, 0x22, ETH_ALEN); + memset(pActionCB->MacAp, 0x33, ETH_ALEN); + + pActionCB->MacDa[0] = 0x00; + pActionCB->MacSa[0] = 0x00; + pActionCB->MacAp[0] = 0x00; + + FT_KDP_EventInform(pAd, BSS0, FT_KDP_SIG_ACTION, + "testtesttesttesttest", 19, 0, (VOID *)pActionCB); +} /* End of FT_RRB_CMD_SimSend */ + + +/* +======================================================================== +Routine Description: + Simulate to send a 11k neighbor request. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + 1. Command Format: + PeerSSID +======================================================================== +*/ +static VOID TYPE_FUNC FT_11K_CMD_SimInfoReq( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + if (strlen((RTMP_STRING *) pArgv) <= MAX_LEN_OF_SSID) + { + FT_KDP_EVENT_INFORM(pAd, BSS0, FT_KDP_SIG_AP_INFO_REQ, + pArgv, strlen((RTMP_STRING *) pArgv), NULL); + } /* End of if */ +} /* End of FT_11K_CMD_SimInfoReq */ + + +/* +======================================================================== +Routine Description: + Show encryption/decryption key information. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: +======================================================================== +*/ +static VOID TYPE_FUNC FT_11K_CMD_SimKeyShow( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + hex_dump("Key=", FT_KDP_CB->CryptKey, sizeof(FT_KDP_CB->CryptKey)); +} /* End of FT_11K_CMD_SimInfoReq */ +#endif /* FT_FUNC_SIMULATION */ + + +/* +======================================================================== +Routine Description: + Display a R0KH information. + +Arguments: + pAd - WLAN control block pointer + Argc - the number of input parameters + *pArgv - input parameters + +Return Value: + None + +Note: + +======================================================================== +*/ +static VOID TYPE_FUNC FT_R1KH_InfoShow( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + INT i; + INT HashIdx; + PFT_R1HK_ENTRY pEntry; + + RTMP_SEM_LOCK(&pAd->ApCfg.FtTab.FT_R1khEntryTabLock); + for (HashIdx = 0; HashIdx < FT_R1KH_ENTRY_HASH_TABLE_SIZE; HashIdx++) + { + pEntry = (PFT_R1HK_ENTRY)\ + (pAd->ApCfg.FtTab.FT_R1khEntryTab[HashIdx].pHead); + + while (pEntry != NULL) + { + DBGPRINT_RAW(RT_DEBUG_OFF, ("StaMac=%02x:%02x:%02x:%02x:%02x:%02x, ", + pEntry->StaMac[0], pEntry->StaMac[1], pEntry->StaMac[2], + pEntry->StaMac[3], pEntry->StaMac[4], pEntry->StaMac[5])); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\nKeyLifeTime=%d, ", pEntry->KeyLifeTime)); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\nRassocDeadline=%d\n", + pEntry->RassocDeadline)); + DBGPRINT_RAW(RT_DEBUG_OFF, ("PairwisChipher=")); + for (i=0; i<4; i++) + DBGPRINT_RAW(RT_DEBUG_OFF, ("%02x:", pEntry->PairwisChipher[i])); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\nAkmSuite=")); + for (i=0; i<4; i++) + DBGPRINT_RAW(RT_DEBUG_OFF, ("%02x:", pEntry->AkmSuite[i])); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\nPmkR0Name=")); + for (i=0; i<16; i++) + DBGPRINT_RAW(RT_DEBUG_OFF, ("%02x:", pEntry->PmkR0Name[i])); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\nPmkR1Key=")); + for (i=0; i<32; i++) + DBGPRINT_RAW(RT_DEBUG_OFF, ("%02x:", pEntry->PmkR1Key[i])); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\nPmkR1Name=")); + for (i=0; i<16; i++) + DBGPRINT_RAW(RT_DEBUG_OFF, ("%02x:", pEntry->PmkR1Name[i])); + DBGPRINT_RAW(RT_DEBUG_OFF, ("\n")); + pEntry = pEntry->pNext; + } + } + RTMP_SEM_UNLOCK(&pAd->ApCfg.FtTab.FT_R1khEntryTabLock); +} /* End of FT_R1KH_InfoShow */ + + +static PMAC_TABLE_ENTRY FtEntry = NULL; +static VOID FT_OverDs_SimReq( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ + PUCHAR pOutBuffer = NULL; + ULONG FrameLen; + HEADER_802_11 Hdr; + FT_INFO FtInfoBuf; + NDIS_STATUS NStatus; + + UCHAR StaAddr[MAC_ADDR_LEN] = {0x00,0x0c,0x43,0x00,0x00,0x00}; + UCHAR TargetAddr[MAC_ADDR_LEN] = {0x00,0x0c,0x43,0x28,0x60,0x10}; + + if (FtEntry == NULL) + { + FtEntry = MacTableInsertEntry(pAd, StaAddr, &pAd->ApCfg.MBSSID[0].wdev, ENTRY_CLIENT, OPMODE_AP, TRUE); + FtEntry->Sst = SST_ASSOC; + } + + NdisZeroMemory(&FtInfoBuf, sizeof(FT_INFO)); + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("%s: allocate memory failed.\n", + __FUNCTION__)); + return; + } + + /* Make 802.11 header. */ + ActHeaderInit(pAd, &Hdr, pAd->ApCfg.MBSSID[FtEntry->func_tb_idx].wdev.bssid, + FtEntry->Addr, pAd->ApCfg.MBSSID[FtEntry->func_tb_idx].wdev.bssid); + + FrameLen = 0; + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr, + END_OF_ARGS); + + FtInfoBuf.MdIeInfo.Len = 3; + FT_SET_MDID(FtInfoBuf.MdIeInfo.MdId, FT_DEFAULT_MDID); + FtInfoBuf.MdIeInfo.FtCapPlc.field.FtOverDs = 1; + FtInfoBuf.MdIeInfo.FtCapPlc.field.RsrReqCap = 1; + FT_MakeFtActFrame(pAd, pOutBuffer, &FrameLen, + FT_ACTION_BT_REQ, FtEntry->Addr, TargetAddr, 0, + &FtInfoBuf); + + /* enqueue it into FT action state machine. */ + REPORT_MGMT_FRAME_TO_MLME(pAd, FtEntry->Aid, pOutBuffer, FrameLen, 0, 0, 0, 0,0); + + if (pOutBuffer) + os_free_mem(pAd, pOutBuffer); + +} + +static VOID FT_OverDs_SimConfirm( + IN PRTMP_ADAPTER pAd, + IN INT32 Argc, + IN CHAR *pArgv) +{ +} +#endif /* CONFIG_AP_SUPPORT */ + + + + + + +#define FT_KDP_CMD_DAEMON_KILL 0 +#define FT_KDP_CMD_EVENT_LIST 1 +#define FT_KDP_CMD_DEBUG_FLAG_CTRL 2 + +#define FT_KDP_CMD_SM_EVT_FT_ASSOC 500 +#define FT_KDP_CMD_SM_EVT_FT_REASSOC 501 +#define FT_KDP_CMD_SM_EVT_KEY_REQ 502 +#define FT_KDP_CMD_SM_R0KH_INFO_SHOW 503 +#define FT_KDP_CMD_SM_R0KH_INFO_CREATE 504 +#define FT_R1KH_INFO_SHOW 505 +#define FT_RIC_CMD_SM_REQ_START 506 +#define FT_RIC_CMD_SM_REQ 507 +#define FT_RIC_CMD_SM_REQ_END 508 +#define FT_RIC_CMD_SM_REQ_RSP_LIST 509 +#define FT_RIC_CMD_SM_REQ_HANDLE 510 +#define FT_RIC_CMD_SM_RRB_SEND 511 +#define FT_RIC_CMD_SM_REQ_HDL_TSPEC 512 +#define FT_11K_CMD_INFO_REQ 513 +#define FT_KDP_KEY_SHOW 514 + +#define FT_REQ_ACT 600 +#define FT_CONFIRM_ACT 601 +#define FT_ROAMING_ACT 602 + +/* +======================================================================== +Routine Description: + IO control handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + pArgvIn - the data flow information + +Return Value: + None + +Note: + All test commands are listed as follows: + iwpriv ra0 set ft=[cmd id]_[arg1]_[arg2]_......_[argn] + [cmd id] = xx, such as 000, 001, 002, 003, ... +======================================================================== +*/ +INT TYPE_FUNC FT_Ioctl(RTMP_ADAPTER *pAd, RTMP_STRING *pArgvIn) +{ + CHAR BufCmd[4] = { 0, 0, 0, 0 }; + CHAR *pArgv, *pParam; + UINT32 Command, /*CmdEndOffset,*/ IdCmd; + INT32 Argc; + + + /* init */ + pArgv = (CHAR *)pArgvIn; + + /* get command type */ + /* command format is iwpriv ra0 set acm=[cmd id]_[arg1]_......_[argn] */ + for(IdCmd=0; IdCmd<=3; IdCmd++) + { + if ((pArgv[IdCmd] == 0x00) || (pArgv[IdCmd] == '_')) + { + /*CmdEndOffset = IdCmd;*/ + break; + } /* End of if */ + } /* End of for */ + + memcpy(BufCmd, pArgv, IdCmd); + Command = FT_ARG_ATOI(BufCmd); + pArgv += IdCmd; /* 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) + { +#ifdef CONFIG_AP_SUPPORT + /* normal commands */ + case FT_KDP_CMD_DAEMON_KILL: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> kill daemon!\n")); + FT_KDP_EventInform(pAd, BSS0, FT_KDP_SIG_TERMINATE, NULL, 0, 0, NULL); + break; + +#ifndef FT_KDP_FUNC_SOCK_COMM + case FT_KDP_CMD_EVENT_LIST: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> event list!\n")); + FT_KDP_CMD_EventList(pAd, Argc, pArgv); + break; +#endif /* FT_KDP_FUNC_SOCK_COMM */ + + case FT_KDP_CMD_DEBUG_FLAG_CTRL: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> IAPP daemon debug flag control!\n")); + FT_KDP_CMD_DbgFlagCtrl(pAd, Argc, pArgv); + break; + +#ifdef FT_FUNC_SIMULATION + /* simulation commands */ + case FT_KDP_CMD_SM_EVT_FT_ASSOC: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) ft assoc!\n")); + FT_KDP_CMD_SimEvtFtAssoc(pAd, Argc, pArgv); + break; + + case FT_KDP_CMD_SM_EVT_FT_REASSOC: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) ft reassoc!\n")); + FT_KDP_CMD_SimEvtFtReAssoc(pAd, Argc, pArgv); + break; + + case FT_KDP_CMD_SM_EVT_KEY_REQ: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) key req!\n")); + FT_KDP_CMD_SimKeyReq(pAd, Argc, pArgv); + break; + +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD + case FT_KDP_CMD_SM_R0KH_INFO_CREATE: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) R0KH INFO create!\n")); + FT_KDP_CMD_SimR0KH_InfoCreate(pAd, Argc, pArgv); + break; +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + + case FT_RIC_CMD_SM_REQ_HANDLE: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) handle a resource request!\n")); + FT_RIC_CMD_SimRscReqHandle(pAd, Argc, pArgv); + break; + + case FT_RIC_CMD_SM_REQ_HDL_TSPEC: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) make a resource request TSPEC!\n")); + FT_RIC_CMD_SimRscReqHdlTspec(pAd, Argc, pArgv); + break; + + case FT_RIC_CMD_SM_RRB_SEND: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) send a RRB frame!\n")); + FT_RRB_CMD_SimSend(pAd, Argc, pArgv); + break; + + case FT_11K_CMD_INFO_REQ: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) send a info request frame!\n")); + FT_11K_CMD_SimInfoReq(pAd, Argc, pArgv); + break; + + case FT_KDP_KEY_SHOW: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) show key information!\n")); + FT_11K_CMD_SimKeyShow(pAd, Argc, pArgv); + break; +#endif /* FT_FUNC_SIMULATION */ + +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD + case FT_KDP_CMD_SM_R0KH_INFO_SHOW: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) R0KH INFO show!\n")); + FT_KDP_CMD_R0KH_InfoShow(pAd, (RTMP_STRING *)pArgv); + break; +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + + case FT_R1KH_INFO_SHOW: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> (sm) R1KH INFO show!\n")); + FT_R1KH_InfoShow(pAd, Argc, pArgv); + break; + + case FT_REQ_ACT: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> FT_REQ_ACT!\n")); + FT_OverDs_SimReq(pAd, Argc, pArgv); + break; + + case FT_CONFIRM_ACT: + DBGPRINT(RT_DEBUG_TRACE, ("ft_iocl> FT_CONFIRM_ACT!\n")); + FT_OverDs_SimConfirm(pAd, Argc, pArgv); + break; +#endif /* CONFIG_AP_SUPPORT */ + + + default: /* error command type */ + DBGPRINT(RT_DEBUG_TRACE, + ("ft_iocl> ERROR! No such command %d!\n", Command)); + return -EINVAL; /* input error */ + } /* End of switch */ + + return TRUE; +} /* End of FT_Ioctl */ + +#endif /* DOT11R_FT_SUPPORT */ + +/* End of ft_iocl.c */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ft_rc.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ft_rc.c new file mode 100644 index 000000000..746e16f33 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ft_rc.c @@ -0,0 +1,383 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + + Abstract: + + All related IEEE802.11r Resource Information Container body. + +***************************************************************************/ + +#ifdef DOT11R_FT_SUPPORT + + +#include "rt_config.h" + + +#define TYPE_FUNC + + + + + +/* +======================================================================== +Routine Description: + Initialize FT RIC Module. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_RIC_Init( + IN PRTMP_ADAPTER pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("ap_ftrc> Initialize FT RIC Module...\n")); + +} /* End of FT_RIC_Init */ + + +/* +======================================================================== +Routine Description: + Release FT RIC Module. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_RIC_Release( + IN PRTMP_ADAPTER pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("ap_ftrc> Release FT RIC Module...\n")); + +} /* End of FT_KDP_Release */ + + + + +#ifdef CONFIG_AP_SUPPORT +/* +======================================================================== +Routine Description: + Handle the resource request. + +Arguments: + pAd - WLAN control block pointer + *pCdb - the source QSTA + *pBufReq - the request packet buffer + ReqLen - the length of request packet buffer + *pBufRsp - the response packet buffer + *pRspLen - the length of response content + +Return Value: + non-zero - the frame length we handled + zero - no request is found + +Note: + 1. The start octet of the buffer is the element ID of RIC request or response. + 2. Same resource type for all resource descriptors in the RDIE. + 3. Suppose RDIEs are continual. +======================================================================== +*/ +UINT32 TYPE_FUNC FT_RIC_ResourceRequestHandle( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pCdb, + IN UCHAR *pBufReq, + IN UINT32 ReqLen, + OUT UCHAR *pBufRsp, + OUT UINT32 *pRspLen) +{ + FT_ELM_RIC_DATA_INFO *pElmDataInfoReq, *pElmDataInfoRsp; + UCHAR *pBufReqElm, *pElmReqDescp; + UCHAR *pBufRspElm; + ULONG ElmLen, RspLen; + UINT32 DescpCnt; + UINT32 HandledSize; + BOOLEAN FlgIsTspecAccepted; + + + /* init */ + pBufReqElm = pBufReq; + pBufRspElm = pBufRsp; + if (pRspLen == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ft_ric> (ResourceRequestHandle) Error! NULL pointer!\n")); + return 0; + } + *pRspLen = 0; + HandledSize = 0; + + /* sanity check */ + if ((pCdb == NULL) || + (pBufReq == NULL) || + (pBufRsp == NULL) + ) + { + DBGPRINT(RT_DEBUG_ERROR, + ("ft_ric> (ResourceRequestHandle) Error! NULL pointer!\n")); + return 0; + } /* End of if */ + + /* handle all RDIEs */ + /* + The non-AP STA shall construct the RIC with a number of + Resource Requests, each delineated by an RDIE. + */ + while(HandledSize < ReqLen) + { + /* sanity check the RDIE */ + pElmDataInfoReq = (FT_ELM_RIC_DATA_INFO *)pBufReqElm; + + if (pElmDataInfoReq->ElmID != FT_ELM_ID_RIC_DATA_INFO) + break; + /* End of if */ + + /* make up reponse */ + /* + The RIC Response shall comprise one RDIE for each RDIE in the + RIC Request. + */ + pElmDataInfoRsp = (FT_ELM_RIC_DATA_INFO *)pBufRspElm; + pElmDataInfoRsp->ElmID = FT_ELM_ID_RIC_DATA_INFO; + pElmDataInfoRsp->ElmLen = FT_ELM_LEN_RIC_DATA_INFO; + + /* + The RDIE Identifier in the RDIE shall be an arbitrary value + chosen by the non-AP STA that uniquely identifies the RDIE + within the RIC. + */ + pElmDataInfoRsp->RDIE_Identifier = pElmDataInfoReq->RDIE_Identifier; + + pBufRspElm += sizeof(FT_ELM_RIC_DATA_INFO); + *pRspLen += sizeof(FT_ELM_RIC_DATA_INFO); + + + /* parsing the RIC descriptors */ + /* + The Resource Count shall be set to the number of alternative + Resource Descriptors that follow. + */ + DescpCnt = pElmDataInfoReq->RD_Count; + FlgIsTspecAccepted = FALSE; + + pElmReqDescp = ((UCHAR *)pElmDataInfoReq); + pElmReqDescp += FT_ELM_HDR_LEN + pElmDataInfoReq->ElmLen; + HandledSize += FT_ELM_HDR_LEN + pElmDataInfoReq->ElmLen; + + while(DescpCnt > 0) + { + if (FlgIsTspecAccepted == FALSE) + { + /* only one resource descriptor is accepted is enough */ + /* + If there are multiple Resource Descriptors then these + are treated as "choices" by the target AP. + */ + switch(*pElmReqDescp) + { + case IE_FT_RIC_DESCRIPTOR: + /* BLOCK ACK */ + /* reject the resource */ + DBGPRINT(RT_DEBUG_TRACE, + ("ft_ric> Handle a resource request BLOCK ACK...\n")); + + if (BA_ResourceAllocate(pAd, + pCdb, + pElmReqDescp, + pBufRspElm, + &RspLen) == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("ft_ric> Accept BA.\n")); + FlgIsTspecAccepted = TRUE; + } + break; + + default: + break; + } /* End of switch */ + } /* End of if */ + + /* find the next RD Descriptor element */ + ElmLen = *(pElmReqDescp+1); + pElmReqDescp += FT_ELM_HDR_LEN + ElmLen; + HandledSize += FT_ELM_HDR_LEN + ElmLen; + + DescpCnt --; + } /* End of while */ + + + /* re-assign the reponse RD Count/status code of RDIE */ + if (FlgIsTspecAccepted == TRUE) + { + /* + A resource request is considered successful by a non-AP STA + if the Status Code 0 is returned in each RDIE. + */ + pElmDataInfoRsp->RD_Count = 1; + pElmDataInfoRsp->StatusCode = 0; + + pBufRspElm += RspLen; + *pRspLen += RspLen; + + DBGPRINT(RT_DEBUG_TRACE, + ("ft_ric> Accept a resource request (RspLen: %d).\n", *pRspLen)); + } + else + { + /* + Status Code non-zero indicates that the resources could not + be accepted. + + In this case the AP may include a single Resource Descriptor + following the RDIE indicating a suggested resource that could + have been accepted. + + The Resource Count field shall be set to '0' or '1' depending + whether the suggested Resource Descriptor is attached. + + A non-zero Status Code in an RDIE shall not cause a non-zero + Status Code in the auth/assoc frame containing the RIC. + */ + + /* we do NOT support suggested Resource Descriptor */ + + pElmDataInfoRsp->RD_Count = 0; /* 0 or 1, we only support 0 */ + pElmDataInfoRsp->StatusCode = FT_STATUS_CODE_RESERVED; + + DBGPRINT(RT_DEBUG_TRACE, ("ft_ric> Resource request fails!\n")); + } /* End of if */ + + + /* check next RDIE */ + pBufReqElm = pElmReqDescp; + } /* End of while */ + + return HandledSize; +} /* End of FT_RIC_ResourceRequestHandle */ + + +/* +======================================================================== +Routine Description: + Handle the resource request. + +Arguments: + pAd - WLAN control block pointer + *pMacEntry - the source QSTA + *pBufReq - the request packet buffer + ReqLen - the length of request packet buffer + *pBufRsp - the response packet buffer + *pRspLen - the length of response content + +Return Value: + non-zero - the frame length we handled + zero - no request is found + +Note: + 1. The start octet of the buffer is the element ID of RIC request or response. + 2. Same resource type for all resource descriptors in the RDIE. + 3. Suppose RDIEs are continual. +======================================================================== +*/ +UINT32 BA_ResourceAllocate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pMacEntry, + IN UCHAR *pBufRscReq, + OUT UCHAR *pBufRscRsp, + OUT ULONG *pBufRspLen) +{ +extern BOOLEAN BARecSessionAdd( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN PFRAME_ADDBA_REQ pFrame); + + UINT8 IEId = IE_FT_RIC_DESCRIPTOR; + UINT8 RicType = FT_RIC_TYPE_BA; + UINT8 Len = 7; + UINT16 Status = 1; + BA_PARM BaParm; /*0 - 2 */ + USHORT TimeOutValue; + + FRAME_ADDBA_REQ AddreqFrame; + FT_ELM_RIC_DESCP_INFO *pRicDesInfo; + FT_RIC_DESCP_BLOCK_ACK *pRicBaInfo; + + if ((pAd->CommonCfg.bBADecline == FALSE) && IS_HT_STA(pMacEntry)) + { + UINT16 Value; + pRicDesInfo = (FT_ELM_RIC_DESCP_INFO *)pBufRscReq; + pRicBaInfo = (FT_RIC_DESCP_BLOCK_ACK *)pRicDesInfo->Container; + Value = le2cpu16(*(UINT16 *)(&pRicBaInfo->BaParm)); + NdisMoveMemory((PUCHAR)&AddreqFrame.BaParm, &Value, sizeof(UINT16)); + AddreqFrame.TimeOutValue = le2cpu16(pRicBaInfo->TimeOutValue); + AddreqFrame.BaStartSeq.word = le2cpu16(pRicBaInfo->BaStartSeq); + + DBGPRINT(RT_DEBUG_OFF, ("Rcv Wcid(%d) AddBAReq\n", pMacEntry->Aid)); + if (BARecSessionAdd(pAd, pMacEntry, &AddreqFrame)) + Status = 0; + else + Status = 38; /* more parameters have invalid values */ + } + else + { + Status = 37; /* the request has been declined. */ + } + + if (Status != 0) + return Status; + + BaParm.BAPolicy = IMMED_BA; + BaParm.AMSDUSupported = 0; + BaParm.TID = AddreqFrame.BaParm.TID; + BaParm.BufSize = min(((UCHAR)AddreqFrame.BaParm.BufSize), (UCHAR)pAd->CommonCfg.BACapability.field.RxBAWinLimit); + if (BaParm.BufSize == 0) + { + BaParm.BufSize = 64; + } + TimeOutValue = 0; + + *(UINT16 *)(&BaParm) = cpu2le16(*(USHORT *)(&BaParm)); + Status = cpu2le16(Status); + TimeOutValue = cpu2le16(TimeOutValue); + + MakeOutgoingFrame( pBufRscRsp, pBufRspLen, + 1, &IEId, + 1, &Len, + 1, &RicType, + 2, &Status, + 2, (UCHAR *)&BaParm, + 2, &TimeOutValue, + END_OF_ARGS); + + return Status; +} + +#endif /* CONFIG_AP_SUPPORT */ + +#endif /* DOT11R_FT_SUPPORT */ + +/* End of ap_ftrc.c */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ft_tlv.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ft_tlv.c new file mode 100644 index 000000000..03249bdb9 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ft_tlv.c @@ -0,0 +1,206 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + ft_tlv.c + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Fonchi Wu 12-02-2008 created for 11r soft-AP + */ + +#ifdef DOT11R_FT_SUPPORT + + +#include "rt_config.h" +#include "dot11r_ft.h" + + +VOID FT_InsertMdIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUINT8 pMdId, + IN FT_CAP_AND_POLICY FtCapPlc) +{ + + ULONG TempLen; + UINT8 Length; + UCHAR MDIE = IE_FT_MDIE; + + Length = 3; + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &MDIE, + 1, &Length, + 2, (PUCHAR)pMdId, + 1, (PUCHAR)&FtCapPlc.word, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +VOID FT_InsertFTIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Length, + IN FT_MIC_CTR_FIELD MICCtr, + IN PUINT8 pMic, + IN PUINT8 pANonce, + IN PUINT8 pSNonce) +{ + ULONG TempLen; + UINT16 MICCtrBuf; + UCHAR FTIE = IE_FT_FTIE; + + MICCtrBuf = cpu2le16(MICCtr.word); + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &FTIE, + 1, &Length, + 2, (PUCHAR)&MICCtrBuf, + 16, (PUCHAR)pMic, + 32, (PUCHAR)pANonce, + 32, (PUCHAR)pSNonce, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; +} + +VOID FT_FTIE_InsertKhIdSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN FT_SUB_ELEMENT_ID SubId, + IN PUINT8 pKhId, + IN UINT8 KhIdLen) +{ + ULONG TempLen; + UCHAR TempSubID; + + if (SubId != FT_R0KH_ID && SubId != FT_R1KH_ID) + { + DBGPRINT(RT_DEBUG_ERROR,("(%s): unknow SubId (%d)\n", + __FUNCTION__, SubId)); + return; + } + + /* The lenght of R1KHID must only be 6 octects. */ + if ((SubId == FT_R1KH_ID) && (KhIdLen != 6)) + { + DBGPRINT(RT_DEBUG_ERROR,("(%s): Invalid R1KHID length (%d)\n", + __FUNCTION__, KhIdLen)); + return; + } + + /* The length of R0KHID must in range of 1 to 48 octects.*/ + if ((SubId == FT_R0KH_ID) && ((KhIdLen > 48) && (KhIdLen < 1))) + { + DBGPRINT(RT_DEBUG_ERROR,("(%s): Invalid R0KHID length (%d)\n", + __FUNCTION__, KhIdLen)); + } + + TempSubID = (UCHAR)SubId; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &TempSubID, + 1, &KhIdLen, + KhIdLen, (PUCHAR)pKhId, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; +} + +VOID FT_FTIE_InsertGTKSubIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUINT8 pGtkSubIe, + IN UINT8 GtkSubIe_len) +{ + ULONG TempLen; + UINT8 Length; + UINT8 SubId; + + SubId = FT_GTK; + Length = GtkSubIe_len; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &SubId, + 1, &Length, + Length, pGtkSubIe, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; +} + +VOID FT_FTIE_InsertIGTKSubIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUINT8 pGtkSubIe, + IN UINT8 GtkSubIe_len) +{ + ULONG TempLen; + UINT8 Length; + UINT8 SubId; + + SubId = FT_IGTK_ID; + Length = GtkSubIe_len; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &SubId, + 1, &Length, + Length, pGtkSubIe, + END_OF_ARGS); + *pFrameLen = *pFrameLen + TempLen; +} + +VOID FT_InsertTimeoutIntervalIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN FT_TIMEOUT_INTERVAL_TYPE Type, + IN UINT32 TimeOutValue) +{ + ULONG TempLen; + UINT8 Length; + UINT8 TimeOutIntervalIE; + UINT8 TimeoutType; + UINT32 TimeoutValueBuf; + + Length = 5; + TimeOutIntervalIE = IE_FT_TIMEOUT_INTERVAL; + TimeoutType = Type; + TimeoutValueBuf = cpu2le32(TimeOutValue); + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &TimeOutIntervalIE, + 1, &Length, + 1, (PUCHAR)&TimeoutType, + 4, (PUCHAR)&TimeoutValueBuf, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; +} + + + +#endif /* DOT11R_FT_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/gas.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/gas.c new file mode 100644 index 000000000..faaf0ca6f --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/gas.c @@ -0,0 +1,1320 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2011, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + gas.c + + Abstract: + generic advertisement service(GAS) + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + +enum DOT11U_ADVERTISMENT_PROTOCOL_ID dot11GASAdvertisementID[] = +{ + ACCESS_NETWORK_QUERY_PROTOCOL, +}; + +static VOID SendGASIndication( + IN PRTMP_ADAPTER pAd, + GAS_EVENT_DATA *Event); + + +enum GAS_STATE GASPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PGAS_CTRL pGASCtrl; + PGAS_PEER_ENTRY GASPeerEntry; + PGAS_EVENT_DATA Event = (PGAS_EVENT_DATA)Elem->Msg; + +#ifdef CONFIG_AP_SUPPORT + pGASCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].GASCtrl; +#endif /* CONFIG_AP_SUPPORT */ + + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + return GASPeerEntry->CurrentState; + } + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + return GAS_UNKNOWN; +} + + +VOID GASSetPeerCurrentState( + IN PRTMP_ADAPTER pAd, + //IN MLME_QUEUE_ELEM *Elem, + PGAS_EVENT_DATA Event, + IN enum GAS_STATE State) +{ + + PGAS_CTRL pGASCtrl; + PGAS_PEER_ENTRY GASPeerEntry; + //PGAS_EVENT_DATA Event = (PGAS_EVENT_DATA)Elem->Msg; + +#ifdef CONFIG_AP_SUPPORT + pGASCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].GASCtrl; +#endif /* CONFIG_AP_SUPPORT */ + + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + GASPeerEntry->CurrentState = State; + break; + } + + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); +} + +BOOLEAN GasEnable(IN PRTMP_ADAPTER pAd, IN MLME_QUEUE_ELEM *Elem) +{ +#ifdef CONFIG_AP_SUPPORT + UCHAR APIndex; + GAS_FRAME *GASFrame; + PGAS_CTRL pGASCtrl = NULL; + + GASFrame = (GAS_FRAME *)Elem->Msg; + + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) { + /* according to 802.11-2012, public action frame may have Wildcard BSSID in addr3, + use addr1(DA) for searching instead. + */ + if (MAC_ADDR_EQUAL(GASFrame->Hdr.Addr1, pAd->ApCfg.MBSSID[APIndex].wdev.bssid)) { + pGASCtrl = &pAd->ApCfg.MBSSID[APIndex].GASCtrl; + break; + } + } + + if (!pGASCtrl) { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s Can not find Peer Control DA=%02X:%02X:%02X:%02X:%02X:%02X\n", + __func__, PRINT_MAC(GASFrame->Hdr.Addr1))); + return FALSE; + } + + return pGASCtrl->b11U_enable; +#endif /* CONFIG_AP_SUPPORT */ +} + +#ifdef CONFIG_AP_SUPPORT +void wext_send_anqp_req_event(PNET_DEV net_dev, const char *peer_mac_addr, + const char *anqp_req, UINT16 anqp_req_len) +{ + struct anqp_req_data *req_data; + UINT16 buflen = 0; + char *buf; + + buflen = sizeof(*req_data) + anqp_req_len; + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + req_data = (struct anqp_req_data *)buf; + req_data->ifindex = RtmpOsGetNetIfIndex(net_dev); + memcpy(req_data->peer_mac_addr, peer_mac_addr, 6); + req_data->anqp_req_len = anqp_req_len; + memcpy(req_data->anqp_req, anqp_req, anqp_req_len); + + RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_HS_ANQP_REQ, NULL, (PUCHAR)buf, buflen); + + os_free_mem(NULL, buf); + +} + + +void SendAnqpReqEvent(PNET_DEV net_dev, const char *peer_mac_addr, + const char *anqp_req, UINT16 anqp_req_len) +{ + wext_send_anqp_req_event(net_dev, + peer_mac_addr, + anqp_req, + anqp_req_len); +} + + +//static VOID SendGASRsp( +// IN PRTMP_ADAPTER pAd, +// IN MLME_QUEUE_ELEM *Elem) +VOID SendGASRsp( + IN PRTMP_ADAPTER pAd, + GAS_EVENT_DATA *Event) +{ + + //GAS_EVENT_DATA *Event = (GAS_EVENT_DATA *)Elem->Msg; + UCHAR *Buf, *Pos; + GAS_FRAME *GASFrame; + ULONG FrameLen = 0, VarLen = 0, tmpValue = 0; + PGAS_CTRL pGASCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].GASCtrl; + GAS_PEER_ENTRY *GASPeerEntry; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + break; + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + if (Event->u.GAS_RSP_DATA.AdvertisementProID == ACCESS_NETWORK_QUERY_PROTOCOL) + { + /* Advertisement protocol element + Query response length field */ + VarLen += 6; + } + + if (Event->EventType == GAS_RSP) + { + /* Query response field*/ + VarLen += Event->u.GAS_RSP_DATA.QueryRspLen; + } + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*GASFrame) + VarLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + //GASSetPeerCurrentState(pAd, Elem, WAIT_PEER_GAS_REQ); + GASSetPeerCurrentState(pAd, Event, WAIT_PEER_GAS_REQ); + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListDel(&GASPeerEntry->List); + DlListInit(&GASPeerEntry->GASQueryRspFragList); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + if (GASPeerEntry->PostReplyTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->PostReplyTimerRunning = FALSE; + } + RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + + if (GASPeerEntry->GASRspBufferingTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + GASPeerEntry->GASRspBufferingTimerRunning = FALSE; + } + RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + os_free_mem(NULL, GASPeerEntry); + return; + } + + NdisZeroMemory(Buf, sizeof(*GASFrame) + VarLen); + + GASFrame = (GAS_FRAME *)Buf; + + ActHeaderInit(pAd, &GASFrame->Hdr, Event->PeerMACAddr ,pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid); + + FrameLen += sizeof(HEADER_802_11); + + GASFrame->Category = CATEGORY_PUBLIC; + FrameLen += 1; + GASFrame->u.GAS_INIT_RSP.Action = ACTION_GAS_INIT_RSP; + FrameLen += 1; + + if (Event->EventType == GAS_RSP) + { + GASFrame->u.GAS_INIT_RSP.DialogToken = Event->u.GAS_RSP_DATA.DialogToken; + FrameLen += 1; + + GASFrame->u.GAS_INIT_RSP.StatusCode = cpu2le16(Event->u.GAS_RSP_DATA.StatusCode); + FrameLen += 2; + + GASFrame->u.GAS_INIT_RSP.GASComebackDelay = Event->u.GAS_RSP_DATA.GASComebackDelay; + FrameLen += 2; + + Pos = GASFrame->u.GAS_INIT_RSP.Variable; + *Pos++ = IE_ADVERTISEMENT_PROTO; + *Pos++ = 2; /* Length field */ + *Pos++ = 0; /* Query response info field */ + + *Pos++ = Event->u.GAS_RSP_DATA.AdvertisementProID; /* Advertisement Protocol ID field */ + + tmpValue = cpu2le16(Event->u.GAS_RSP_DATA.QueryRspLen); + NdisMoveMemory(Pos, &tmpValue, 2); + Pos += 2; + FrameLen += 6; + + if (Event->u.GAS_RSP_DATA.QueryRspLen > 0) + NdisMoveMemory(Pos, Event->u.GAS_RSP_DATA.QueryRsp, Event->u.GAS_RSP_DATA.QueryRspLen); + + FrameLen += Event->u.GAS_RSP_DATA.QueryRspLen; + + //GASSetPeerCurrentState(pAd, Elem, WAIT_PEER_GAS_REQ); + GASSetPeerCurrentState(pAd, Event, WAIT_PEER_GAS_REQ); + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListDel(&GASPeerEntry->List); + DlListInit(&GASPeerEntry->GASQueryRspFragList); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + if (GASPeerEntry->PostReplyTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->PostReplyTimerRunning = FALSE; + } + RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->FreeResource++; + + if (GASPeerEntry->GASRspBufferingTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + GASPeerEntry->GASRspBufferingTimerRunning = FALSE; + } + RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + GASPeerEntry->FreeResource++; + + GASPeerEntry->FreeResource++; + os_free_mem(NULL, GASPeerEntry); + + } + else if (Event->EventType == GAS_RSP_MORE) + { + + GASFrame->u.GAS_INIT_RSP.DialogToken = Event->u.GAS_RSP_MORE_DATA.DialogToken; + FrameLen += 1; + + GASFrame->u.GAS_INIT_RSP.StatusCode = cpu2le16(Event->u.GAS_RSP_MORE_DATA.StatusCode); + FrameLen += 2; + + GASFrame->u.GAS_INIT_RSP.GASComebackDelay = Event->u.GAS_RSP_MORE_DATA.GASComebackDelay; + FrameLen += 2; + + Pos = GASFrame->u.GAS_INIT_RSP.Variable; + *Pos++ = IE_ADVERTISEMENT_PROTO; + *Pos++ = 2; /* Length field */ + *Pos++ = 0; /* Query response info field */ + + *Pos++ = Event->u.GAS_RSP_MORE_DATA.AdvertisementProID; /* Advertisement Protocol ID field */ + + tmpValue = 0; + NdisMoveMemory(Pos, &tmpValue, 2); + + Pos += 2; + FrameLen += 6; + + //GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_CB_REQ); + GASSetPeerCurrentState(pAd, Event, WAIT_GAS_CB_REQ); + + /* + * Buffer the query response for a minimun of dotGASResponseBufferingTime + * after the expiry of the GAS comeback delay + */ + if (!GASPeerEntry->GASRspBufferingTimerRunning) + { + RTMPSetTimer(&GASPeerEntry->GASRspBufferingTimer, dotGASResponseBufferingTime + + GASFrame->u.GAS_INIT_RSP.GASComebackDelay); + GASPeerEntry->GASRspBufferingTimerRunning = TRUE; + } + + } + + MiniportMMRequest(pAd, 0, Buf, FrameLen); + + os_free_mem(NULL, Buf); +} + + +VOID ReceiveGASInitReq( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + GAS_EVENT_DATA *Event; + GAS_FRAME *GASFrame = (GAS_FRAME *)Elem->Msg; + GAS_PEER_ENTRY *GASPeerEntry, *GASPeerEntryTmp; + PGAS_CTRL pGASCtrl = NULL; + UCHAR APIndex, *Pos, *Buf; + UINT16 VarLen; + UINT32 Len = 0; + BOOLEAN IsFound = FALSE, Cancelled;; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + if (MAC_ADDR_EQUAL(GASFrame->Hdr.Addr3, pAd->ApCfg.MBSSID[APIndex].wdev.bssid)) + { + pGASCtrl = &pAd->ApCfg.MBSSID[APIndex].GASCtrl; + break; + } + } + + if (!pGASCtrl) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Can not find Peer Control\n", __FUNCTION__)); + return; + } + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, GASFrame->Hdr.Addr2)) + { + IsFound = TRUE; + GASPeerEntry->QueryNum++; + break; + } + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + if (IsFound) { + + //if (GASPeerEntry->QueryNum++ >= 15) + { + /* Query too many times, remove the peer address from list */ + DBGPRINT(RT_DEBUG_OFF, ("%s Q %d, old 0x%x, 0x%x, %02x:%02x:%02x:%02x:%02x:%02x remove peer\n", __FUNCTION__, GASPeerEntry->QueryNum, GASPeerEntry->DialogToken, GASFrame->u.GAS_INIT_REQ.DialogToken, GASPeerEntry->PeerMACAddr[0], GASPeerEntry->PeerMACAddr[1], GASPeerEntry->PeerMACAddr[2], GASPeerEntry->PeerMACAddr[3], GASPeerEntry->PeerMACAddr[4], GASPeerEntry->PeerMACAddr[5])); + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEachSafe(GASPeerEntry, GASPeerEntryTmp, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, GASFrame->Hdr.Addr2)) + { + DlListDel(&GASPeerEntry->List); + DlListInit(&GASPeerEntry->GASQueryRspFragList); + + if (GASPeerEntry->PostReplyTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->PostReplyTimerRunning = FALSE; + } + RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + + if (GASPeerEntry->GASRspBufferingTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + GASPeerEntry->GASRspBufferingTimerRunning = FALSE; + } + RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + GASPeerEntry->FreeResource++; + + os_free_mem(NULL, GASPeerEntry); + } + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + } + //return; + } + + os_alloc_mem(NULL, (UCHAR **)&GASPeerEntry, sizeof(*GASPeerEntry)); + + if (!GASPeerEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(GASPeerEntry, sizeof(*GASPeerEntry)); + GASPeerEntry->AllocResource++; + + GASPeerEntry->CurrentState = WAIT_PEER_GAS_REQ; + GASPeerEntry->QueryNum++; + NdisMoveMemory(GASPeerEntry->PeerMACAddr, GASFrame->Hdr.Addr2, MAC_ADDR_LEN); + GASPeerEntry->DialogToken = GASFrame->u.GAS_INIT_REQ.DialogToken; + GASPeerEntry->Priv = pAd; + RTMPInitTimer(pAd, &GASPeerEntry->PostReplyTimer, + GET_TIMER_FUNCTION(PostReplyTimeout), GASPeerEntry, FALSE); + GASPeerEntry->AllocResource++; + RTMPInitTimer(pAd, &GASPeerEntry->GASRspBufferingTimer, + GET_TIMER_FUNCTION(GASRspBufferingTimeout), GASPeerEntry, FALSE); + GASPeerEntry->AllocResource++; + + DlListInit(&GASPeerEntry->GASQueryRspFragList); + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListAddTail(&pGASCtrl->GASPeerList, &GASPeerEntry->List); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + NdisMoveMemory(&VarLen, GASFrame->u.GAS_INIT_REQ.Variable + 4, 2); + VarLen = le2cpu16(VarLen); + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + VarLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + goto error; + } + + NdisZeroMemory(Buf, sizeof(*Event) + VarLen); + + Event = (GAS_EVENT_DATA *)Buf; + + Event->ControlIndex = APIndex; + Len += 1; + + NdisMoveMemory(Event->PeerMACAddr, GASFrame->Hdr.Addr2, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + Event->EventType = PEER_GAS_REQ; + Len += 2; + + Event->u.PEER_GAS_REQ_DATA.DialogToken = GASFrame->u.GAS_INIT_REQ.DialogToken; + Len += 1; + + Pos = GASFrame->u.GAS_INIT_REQ.Variable + 3; + Event->u.PEER_GAS_REQ_DATA.AdvertisementProID = *Pos; + GASPeerEntry->AdvertisementProID = *Pos; + Len += 1; + Pos++; + + NdisMoveMemory(&Event->u.PEER_GAS_REQ_DATA.QueryReqLen, Pos, 2); + Event->u.PEER_GAS_REQ_DATA.QueryReqLen = le2cpu16(Event->u.PEER_GAS_REQ_DATA.QueryReqLen); + Len += 2; + Pos += 2; + + NdisMoveMemory(Event->u.PEER_GAS_REQ_DATA.QueryReq, Pos, Event->u.PEER_GAS_REQ_DATA.QueryReqLen); + Len += Event->u.PEER_GAS_REQ_DATA.QueryReqLen; + + SendGASIndication(pAd, (GAS_EVENT_DATA *)Buf); + //MlmeEnqueue(pAd, GAS_STATE_MACHINE, PEER_GAS_REQ, Len, Buf,0); + + //RTMP_MLME_HANDLER(pAd); + + os_free_mem(NULL, Buf); + + return; + +error: + DlListDel(&GASPeerEntry->List); + os_free_mem(NULL, GASPeerEntry); +} + + +static VOID SendGASCBRsp( + IN PRTMP_ADAPTER pAd, + //IN MLME_QUEUE_ELEM *Elem) + GAS_EVENT_DATA *Event) +{ + //GAS_EVENT_DATA *Event = (GAS_EVENT_DATA *)Elem->Msg; + UCHAR *Buf, *Pos; + GAS_FRAME *GASFrame; + ULONG FrameLen = 0, VarLen = 0, tmpLen = 0; + GAS_PEER_ENTRY *GASPeerEntry; + GAS_QUERY_RSP_FRAGMENT *GASQueryRspFrag = NULL, *GASQueryRspFragTmp; + PGAS_CTRL pGASCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].GASCtrl; + BOOLEAN bGASQueryRspFragFound = FALSE; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + if (GASPeerEntry->AdvertisementProID == ACCESS_NETWORK_QUERY_PROTOCOL) + { + /* Advertisement protocol element + Query response length field */ + VarLen += 6; + } + + DlListForEach(GASQueryRspFrag, &GASPeerEntry->GASQueryRspFragList, + GAS_QUERY_RSP_FRAGMENT, List) + { + if (GASPeerEntry->CurrentGASFragNum == + GASQueryRspFrag->GASRspFragID) + { + GASPeerEntry->CurrentGASFragNum++; + VarLen += GASQueryRspFrag->FragQueryRspLen; + bGASQueryRspFragFound = TRUE; + break; + } + } + break; + } + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*GASFrame) + VarLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*GASFrame) + VarLen); + + GASFrame = (GAS_FRAME *)Buf; + + ActHeaderInit(pAd, &GASFrame->Hdr, Event->PeerMACAddr ,pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid); + + FrameLen += sizeof(HEADER_802_11); + + GASFrame->Category = CATEGORY_PUBLIC; + FrameLen += 1; + + GASFrame->u.GAS_CB_RSP.Action = ACTION_GAS_CB_RSP; + FrameLen += 1; + + if (Event->EventType == GAS_CB_REQ) + { + GASFrame->u.GAS_CB_RSP.DialogToken = Event->u.GAS_CB_REQ_DATA.DialogToken; + FrameLen += 1; + + GASFrame->u.GAS_CB_RSP.StatusCode = cpu2le16(Event->u.GAS_CB_REQ_DATA.StatusCode); + FrameLen += 2; + + if (bGASQueryRspFragFound) + GASFrame->u.GAS_CB_RSP.GASRspFragID = (GASQueryRspFrag->GASRspFragID & 0x7F); + else + GASFrame->u.GAS_CB_RSP.GASRspFragID = 0; + + DBGPRINT(RT_DEBUG_OFF, ("GASRspFragID = %d\n", GASFrame->u.GAS_CB_RSP.GASRspFragID)); + + FrameLen += 1; + + GASFrame->u.GAS_CB_RSP.GASComebackDelay = 0; + FrameLen += 2; + + Pos = GASFrame->u.GAS_CB_RSP.Variable; + *Pos++ = IE_ADVERTISEMENT_PROTO; + *Pos++ = 2; /* Length field */ + *Pos++ = 0; /* Query response info field */ + + *Pos++ = Event->u.GAS_CB_REQ_DATA.AdvertisementProID; /* Advertisement Protocol ID field */ + + if (Event->u.GAS_CB_REQ_DATA.StatusCode == 0) + { + + tmpLen = cpu2le16(GASQueryRspFrag->FragQueryRspLen); + + NdisMoveMemory(Pos, &tmpLen, 2); + Pos += 2; + FrameLen += 6; + + NdisMoveMemory(Pos, GASQueryRspFrag->FragQueryRsp, + GASQueryRspFrag->FragQueryRspLen); + + FrameLen += GASQueryRspFrag->FragQueryRspLen; + } + else + { + tmpLen = 0; + + NdisMoveMemory(Pos, &tmpLen, 2); + Pos += 2; + FrameLen += 6; + } + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListDel(&GASPeerEntry->List); + + DlListForEachSafe(GASQueryRspFrag, GASQueryRspFragTmp, + &GASPeerEntry->GASQueryRspFragList, GAS_QUERY_RSP_FRAGMENT, List) + { + DlListDel(&GASQueryRspFrag->List); + os_free_mem(NULL, GASQueryRspFrag->FragQueryRsp); + os_free_mem(NULL, GASQueryRspFrag); + GASPeerEntry->FreeResource += 2; + } + + DlListInit(&GASPeerEntry->GASQueryRspFragList); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + if (GASPeerEntry->PostReplyTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->PostReplyTimerRunning = FALSE; + } + + if (GASPeerEntry->GASRspBufferingTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + GASPeerEntry->GASRspBufferingTimerRunning = FALSE; + } + RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->FreeResource += 1; + + RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, & Cancelled); + + os_free_mem(NULL, GASPeerEntry); + } + else if (Event->EventType == GAS_CB_REQ_MORE) + { + + GASFrame->u.GAS_CB_RSP.DialogToken = Event->u.GAS_CB_REQ_MORE_DATA.DialogToken; + FrameLen += 1; + + GASFrame->u.GAS_CB_RSP.StatusCode = cpu2le16(Event->u.GAS_CB_REQ_MORE_DATA.StatusCode); + FrameLen += 2; + + GASFrame->u.GAS_CB_RSP.GASRspFragID = (0x80 | (GASQueryRspFrag->GASRspFragID & 0x7F)); + DBGPRINT(RT_DEBUG_OFF, ("GASRspFragID = %d\n", GASFrame->u.GAS_CB_RSP.GASRspFragID)); + FrameLen += 1; + + GASFrame->u.GAS_CB_RSP.GASComebackDelay = 0; + FrameLen += 2; + + Pos = GASFrame->u.GAS_CB_RSP.Variable; + *Pos++ = IE_ADVERTISEMENT_PROTO; + *Pos++ = 2; /* Length field */ + *Pos++ = 0; /* Query response info field */ + + *Pos++ = Event->u.GAS_CB_REQ_MORE_DATA.AdvertisementProID; /* Advertisement Protocol ID field */ + + tmpLen = cpu2le16(GASQueryRspFrag->FragQueryRspLen); + + NdisMoveMemory(Pos, &tmpLen, 2); + Pos += 2; + FrameLen += 6; + + NdisMoveMemory(Pos, GASQueryRspFrag->FragQueryRsp, + GASQueryRspFrag->FragQueryRspLen); + + FrameLen += GASQueryRspFrag->FragQueryRspLen; + + //GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_CB_REQ); + GASSetPeerCurrentState(pAd, Event, WAIT_GAS_CB_REQ); + } + + MiniportMMRequest(pAd, 0, Buf, FrameLen); + + os_free_mem(NULL, Buf); +} + + +VOID ReceiveGASCBReq( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + GAS_EVENT_DATA *Event; + GAS_FRAME *GASFrame = (GAS_FRAME *)Elem->Msg; + GAS_PEER_ENTRY *GASPeerEntry; + PGAS_CTRL pGASCtrl = NULL; + UCHAR APIndex, *Buf; + UINT32 Len = 0; + BOOLEAN IsGASCBReqMore = FALSE; + BOOLEAN IsFound = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + if (MAC_ADDR_EQUAL(GASFrame->Hdr.Addr3, pAd->ApCfg.MBSSID[APIndex].wdev.bssid)) + { + pGASCtrl = &pAd->ApCfg.MBSSID[APIndex].GASCtrl; + break; + } + } + + if (!pGASCtrl) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Can not find Peer Control\n", __FUNCTION__)); + return; + } + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event)); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*Event)); + + Event = (GAS_EVENT_DATA *)Buf; + + Event->ControlIndex = APIndex; + Len += 1; + + NdisMoveMemory(Event->PeerMACAddr, GASFrame->Hdr.Addr2, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + if ((GASPeerEntry->CurrentGASFragNum + 1) < + GASPeerEntry->GASRspFragNum) + IsGASCBReqMore = TRUE; + + IsFound = TRUE; + break; + } + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + if (!IsGASCBReqMore) + { + if(IsFound) + { + Event->EventType = GAS_CB_REQ; + Len += 2; + + Event->u.GAS_CB_REQ_DATA.DialogToken = GASFrame->u.GAS_CB_REQ.DialogToken; + Len += 1; + + Event->u.GAS_CB_REQ_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID; + Len += 1; + + if (pGASCtrl->ExternalANQPServerTest == 2) + Event->u.GAS_CB_REQ_DATA.StatusCode = SERVER_UNREACHABLE; + else + Event->u.GAS_CB_REQ_DATA.StatusCode = 0; + + Len += 2; + + SendGASCBRsp(pAd, (GAS_EVENT_DATA *)Buf); + //MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_CB_REQ, Len, Buf, 0); + + //RTMP_MLME_HANDLER(pAd); + } + else + { + os_alloc_mem(NULL, (UCHAR **)&GASPeerEntry, sizeof(*GASPeerEntry)); + + if (!GASPeerEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + goto error; + } + + NdisZeroMemory(GASPeerEntry, sizeof(*GASPeerEntry)); + + GASPeerEntry->CurrentState = WAIT_GAS_CB_REQ; + GASPeerEntry->ControlIndex = Event->ControlIndex; + NdisMoveMemory(GASPeerEntry->PeerMACAddr, GASFrame->Hdr.Addr2, MAC_ADDR_LEN); + GASPeerEntry->DialogToken = GASFrame->u.GAS_CB_REQ.DialogToken; + GASPeerEntry->AdvertisementProID = ACCESS_NETWORK_QUERY_PROTOCOL; // FIXME + GASPeerEntry->Priv = pAd; + DlListInit(&GASPeerEntry->GASQueryRspFragList); + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListAddTail(&pGASCtrl->GASPeerList, &GASPeerEntry->List); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + Event->EventType = GAS_CB_REQ; + Len += 2; + + Event->u.GAS_CB_REQ_DATA.DialogToken = GASFrame->u.GAS_CB_REQ.DialogToken; + Len += 1; + + Event->u.GAS_CB_REQ_DATA.AdvertisementProID = ACCESS_NETWORK_QUERY_PROTOCOL; + Len += 1; + + Event->u.GAS_CB_REQ_DATA.StatusCode = UNSPECIFIED_FAILURE; + Len += 2; + + SendGASCBRsp(pAd, (GAS_EVENT_DATA *)Buf); + //MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_CB_REQ, Len, Buf, 0); + + //RTMP_MLME_HANDLER(pAd); + } + } + else + { + Event->EventType = GAS_CB_REQ_MORE; + Len += 2; + + Event->u.GAS_CB_REQ_MORE_DATA.DialogToken = GASFrame->u.GAS_CB_REQ.DialogToken; + Len += 1; + + Event->u.GAS_CB_REQ_MORE_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID; + Len += 1; + + Event->u.GAS_CB_REQ_MORE_DATA.StatusCode = 0; + Len += 2; + + SendGASCBRsp(pAd, (GAS_EVENT_DATA *)Buf); + //MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_CB_REQ_MORE, Len, Buf,0); + + //RTMP_MLME_HANDLER(pAd); + } + + +error: + os_free_mem(NULL, Buf); +} + + +static BOOLEAN IsAdvertisementProIDValid( + IN PRTMP_ADAPTER pAd, + IN enum DOT11U_ADVERTISMENT_PROTOCOL_ID AdvertisementProtoID) +{ + INT32 i; + + for (i = 0; i < sizeof(dot11GASAdvertisementID) + / sizeof(enum DOT11U_ADVERTISMENT_PROTOCOL_ID); i++) + { + if (AdvertisementProtoID == dot11GASAdvertisementID[i]) + return TRUE; + } + + return FALSE; +} + + +void PostReplyTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + GAS_PEER_ENTRY *GASPeerEntry = (GAS_PEER_ENTRY *)FunctionContext; + PGAS_CTRL pGASCtrl; + PRTMP_ADAPTER pAd; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + if (!GASPeerEntry) + { + DBGPRINT(RT_DEBUG_OFF, ("%s: GASPeerEntry is NULL\n", __FUNCTION__)); + return; + } + + pAd = GASPeerEntry->Priv; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s: fRTMP_ADAPTER_HALT_IN_PROGRESS\n", __FUNCTION__)); + return; + } + + pGASCtrl = &pAd->ApCfg.MBSSID[GASPeerEntry->ControlIndex].GASCtrl; + + GASPeerEntry->PostReplyTimerRunning = FALSE; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListDel(&GASPeerEntry->List); + + DlListInit(&GASPeerEntry->GASQueryRspFragList); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->FreeResource += 1; + + RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, & Cancelled); + GASPeerEntry->FreeResource += 1; + + GASPeerEntry->FreeResource += 1; + + os_free_mem(NULL, GASPeerEntry); + +} +BUILD_TIMER_FUNCTION(PostReplyTimeout); + + +VOID GASRspBufferingTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + GAS_PEER_ENTRY *GASPeerEntry = (GAS_PEER_ENTRY *)FunctionContext; + PRTMP_ADAPTER pAd; + PGAS_CTRL pGASCtrl; + GAS_QUERY_RSP_FRAGMENT *GASQueryRspFrag = NULL, *GASQueryRspFragTmp; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + if (!GASPeerEntry) + { + DBGPRINT(RT_DEBUG_OFF, ("%s: GASPeerEntry is NULL\n", __FUNCTION__)); + return; + } + + pAd = GASPeerEntry->Priv; + + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS + | fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s: fRTMP_ADAPTER_HALT_IN_PROGRESS\n", __FUNCTION__)); + return; + } + + pGASCtrl = &pAd->ApCfg.MBSSID[GASPeerEntry->ControlIndex].GASCtrl; + + if (GASPeerEntry->GASRspBufferingTimerRunning) + { + GASPeerEntry->GASRspBufferingTimerRunning = FALSE; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListDel(&GASPeerEntry->List); + + DlListForEachSafe(GASQueryRspFrag, GASQueryRspFragTmp, + &GASPeerEntry->GASQueryRspFragList, GAS_QUERY_RSP_FRAGMENT, List) + { + DlListDel(&GASQueryRspFrag->List); + os_free_mem(NULL, GASQueryRspFrag->FragQueryRsp); + os_free_mem(NULL, GASQueryRspFrag); + GASPeerEntry->FreeResource += 2; + } + + DlListInit(&GASPeerEntry->GASQueryRspFragList); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->FreeResource += 1; + + RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, & Cancelled); + GASPeerEntry->FreeResource += 1; + + GASPeerEntry->FreeResource += 1; + + os_free_mem(NULL, GASPeerEntry); + } +} +BUILD_TIMER_FUNCTION(GASRspBufferingTimeout); + + +static VOID SendGASIndication( + IN PRTMP_ADAPTER pAd, + //IN MLME_QUEUE_ELEM *Elem) + GAS_EVENT_DATA *Event) +{ + PGAS_PEER_ENTRY GASPeerEntry; + //GAS_EVENT_DATA *Event = (GAS_EVENT_DATA *)Elem->Msg; + GAS_EVENT_DATA *GASRspEvent; + PGAS_CTRL pGASCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].GASCtrl; + PNET_DEV NetDev = pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.if_dev; + UCHAR *Buf; + UINT32 Len = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + /* + * If advertisement protocol ID equals to the value + * contained in any dot11GASAdvertisementID MID objects + */ + if (IsAdvertisementProIDValid(pAd, Event->u.PEER_GAS_REQ_DATA.AdvertisementProID) && + !pGASCtrl->ExternalANQPServerTest) + { + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + /* Init PostReply timer */ + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + if (!GASPeerEntry->PostReplyTimerRunning) + { + RTMPSetTimer(&GASPeerEntry->PostReplyTimer, dot11GASResponseTimeout); + GASPeerEntry->PostReplyTimerRunning = TRUE; + } + + break; + } + } + + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + //GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_RSP); + GASSetPeerCurrentState(pAd, Event, WAIT_GAS_RSP); + + if (Event->u.PEER_GAS_REQ_DATA.AdvertisementProID == ACCESS_NETWORK_QUERY_PROTOCOL) + { + /* Send anqp request indication to daemon */ + SendAnqpReqEvent(NetDev, + Event->PeerMACAddr, + Event->u.PEER_GAS_REQ_DATA.QueryReq, + Event->u.PEER_GAS_REQ_DATA.QueryReqLen); + } + } + else if (IsAdvertisementProIDValid(pAd, Event->u.PEER_GAS_REQ_DATA.AdvertisementProID) && + pGASCtrl->ExternalANQPServerTest == 1) /* server not reachable for 2F test */ + { + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*GASRspEvent)); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*GASRspEvent)); + + GASRspEvent = (GAS_EVENT_DATA *)Buf; + + GASRspEvent->ControlIndex = Event->ControlIndex; + Len += 1; + NdisMoveMemory(GASRspEvent->PeerMACAddr, Event->PeerMACAddr, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + GASRspEvent->EventType = GAS_RSP; + Len += 2; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + GASRspEvent->u.GAS_RSP_DATA.DialogToken = GASPeerEntry->DialogToken; + Len += 1; + break; + } + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + GASRspEvent->u.GAS_RSP_DATA.StatusCode = SERVER_UNREACHABLE; + Len += 2; + + GASRspEvent->u.GAS_RSP_DATA.GASComebackDelay = 0; + Len += 2; + + GASRspEvent->u.GAS_RSP_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID; + Len += 1; + + GASRspEvent->u.GAS_RSP_DATA.QueryRspLen = 0; + Len += 2; + + //GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_RSP); + GASSetPeerCurrentState(pAd, Event, WAIT_GAS_RSP); + + SendGASRsp(pAd, (GAS_EVENT_DATA *)Buf); + //MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_RSP, Len, Buf, 0); + + //RTMP_MLME_HANDLER(pAd); + + os_free_mem(NULL, Buf); + } + else if (IsAdvertisementProIDValid(pAd, Event->u.PEER_GAS_REQ_DATA.AdvertisementProID) && + pGASCtrl->ExternalANQPServerTest == 2) /* server not reachable for 4F test */ + { + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*GASRspEvent)); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*GASRspEvent)); + + GASRspEvent = (GAS_EVENT_DATA *)Buf; + + GASRspEvent->ControlIndex = Event->ControlIndex; + Len += 1; + NdisMoveMemory(GASRspEvent->PeerMACAddr, Event->PeerMACAddr, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + GASRspEvent->EventType = GAS_RSP_MORE; + Len += 2; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + GASRspEvent->u.GAS_RSP_MORE_DATA.DialogToken = GASPeerEntry->DialogToken; + Len += 1; + break; + } + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + GASRspEvent->u.GAS_RSP_MORE_DATA.StatusCode = 0; + Len += 2; + + GASRspEvent->u.GAS_RSP_MORE_DATA.GASComebackDelay = 1; + Len += 2; + + GASRspEvent->u.GAS_RSP_MORE_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID; + Len += 1; + + //GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_RSP); + GASSetPeerCurrentState(pAd, Event, WAIT_GAS_RSP); + + SendGASRsp(pAd, (GAS_EVENT_DATA *)Buf); + //MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_RSP_MORE, Len, Buf, 0); + + //RTMP_MLME_HANDLER(pAd); + + os_free_mem(NULL, Buf); + } + else if (!IsAdvertisementProIDValid(pAd, Event->u.PEER_GAS_REQ_DATA.AdvertisementProID)) + { + /* Do not support this advertisement protocol, such as MIH */ + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*GASRspEvent)); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*GASRspEvent)); + + GASRspEvent = (GAS_EVENT_DATA *)Buf; + + GASRspEvent->ControlIndex = Event->ControlIndex; + Len += 1; + NdisMoveMemory(GASRspEvent->PeerMACAddr, Event->PeerMACAddr, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + GASRspEvent->EventType = GAS_RSP; + Len += 2; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + DlListForEach(GASPeerEntry, &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(GASPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + GASRspEvent->u.GAS_RSP_DATA.DialogToken = GASPeerEntry->DialogToken; + Len += 1; + break; + } + } + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + + GASRspEvent->u.GAS_RSP_DATA.StatusCode = ADVERTISEMENT_PROTOCOL_NOT_SUPPORTED; + Len += 2; + + GASRspEvent->u.GAS_RSP_DATA.GASComebackDelay = 0; + Len += 2; + + GASRspEvent->u.GAS_RSP_DATA.AdvertisementProID = GASPeerEntry->AdvertisementProID; + Len += 1; + + GASRspEvent->u.GAS_RSP_DATA.QueryRspLen = 0; + Len += 2; + + //GASSetPeerCurrentState(pAd, Elem, WAIT_GAS_RSP); + GASSetPeerCurrentState(pAd, Event, WAIT_GAS_RSP); + + MlmeEnqueue(pAd, GAS_STATE_MACHINE, GAS_RSP, Len, Buf, 0); + RTMP_MLME_HANDLER(pAd); + + os_free_mem(NULL, Buf); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s: should not in this case\n", __FUNCTION__)); +} +#endif /* CONFIG_AP_SUPPORT */ + +static VOID GASCtrlInit(IN PRTMP_ADAPTER pAd) +{ + PGAS_CTRL pGASCtrl; +#ifdef CONFIG_AP_SUPPORT + UCHAR APIndex; +#endif + + +#ifdef CONFIG_AP_SUPPORT + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + pGASCtrl = &pAd->ApCfg.MBSSID[APIndex].GASCtrl; + NdisZeroMemory(pGASCtrl, sizeof(*pGASCtrl)); + NdisAllocateSpinLock(pAd, &pGASCtrl->GASPeerListLock); + DlListInit(&pGASCtrl->GASPeerList); + } +#endif +} + +VOID GASCtrlExit(IN PRTMP_ADAPTER pAd) +{ + PGAS_CTRL pGASCtrl; + GAS_PEER_ENTRY *GASPeerEntry, *GASPeerEntryTmp; + GAS_QUERY_RSP_FRAGMENT *GASQueryRspFrag, *GASQueryRspFragTmp; + BOOLEAN Cancelled; +#ifdef CONFIG_AP_SUPPORT + UCHAR APIndex; +#endif + + +#ifdef CONFIG_AP_SUPPORT + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + pGASCtrl = &pAd->ApCfg.MBSSID[APIndex].GASCtrl; + + RTMP_SEM_LOCK(&pGASCtrl->GASPeerListLock); + /* Remove all GAS peer entry */ + DlListForEachSafe(GASPeerEntry, GASPeerEntryTmp, + &pGASCtrl->GASPeerList, GAS_PEER_ENTRY, List) + { + + DlListDel(&GASPeerEntry->List); + + DlListForEachSafe(GASQueryRspFrag, GASQueryRspFragTmp, + &GASPeerEntry->GASQueryRspFragList, GAS_QUERY_RSP_FRAGMENT, List) + { + DlListDel(&GASQueryRspFrag->List); + os_free_mem(NULL, GASQueryRspFrag->FragQueryRsp); + os_free_mem(NULL, GASQueryRspFrag); + } + + DlListInit(&GASPeerEntry->GASQueryRspFragList); + + if (GASPeerEntry->PostReplyTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + GASPeerEntry->PostReplyTimerRunning = FALSE; + } + + if (GASPeerEntry->GASRspBufferingTimerRunning) + { + RTMPCancelTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + GASPeerEntry->GASRspBufferingTimerRunning = FALSE; + } + + RTMPReleaseTimer(&GASPeerEntry->PostReplyTimer, &Cancelled); + RTMPReleaseTimer(&GASPeerEntry->GASRspBufferingTimer, &Cancelled); + os_free_mem(NULL, GASPeerEntry); + } + + DlListInit(&pGASCtrl->GASPeerList); + RTMP_SEM_UNLOCK(&pGASCtrl->GASPeerListLock); + NdisFreeSpinLock(&pGASCtrl->GASPeerListLock); + } +#endif /* CONFIG_AP_SUPPORT */ +} + + +VOID GASStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + GASCtrlInit(pAd); + + StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, MAX_GAS_STATE, MAX_GAS_MSG, (STATE_MACHINE_FUNC)Drop, GAS_UNKNOWN, GAS_MACHINE_BASE); + + +#ifdef CONFIG_AP_SUPPORT + StateMachineSetAction(S, WAIT_PEER_GAS_REQ, PEER_GAS_REQ, (STATE_MACHINE_FUNC)SendGASIndication); + StateMachineSetAction(S, WAIT_GAS_RSP, GAS_RSP, (STATE_MACHINE_FUNC)SendGASRsp); + StateMachineSetAction(S, WAIT_GAS_RSP, GAS_RSP_MORE, (STATE_MACHINE_FUNC)SendGASRsp); + StateMachineSetAction(S, WAIT_GAS_RSP, GAS_CB_REQ, (STATE_MACHINE_FUNC)SendGASCBRsp); + StateMachineSetAction(S, WAIT_GAS_CB_REQ, GAS_CB_REQ, (STATE_MACHINE_FUNC)SendGASCBRsp); + StateMachineSetAction(S, WAIT_GAS_CB_REQ, GAS_CB_REQ_MORE, (STATE_MACHINE_FUNC)SendGASCBRsp); +#endif /* CONFIG_AP_SUPPORT */ +} diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/hotspot.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/hotspot.c new file mode 100644 index 000000000..c256cc79c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/hotspot.c @@ -0,0 +1,841 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2011, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + hotspot.c + + Abstract: + hotspot2.0 features + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + +extern UCHAR BROADCAST_ADDR[MAC_ADDR_LEN]; + +void wext_hotspot_onoff_event(PNET_DEV net_dev, int onoff) +{ + struct hs_onoff *hotspot_onoff; + UINT16 buflen = 0; + char *buf; + + buflen = sizeof(*hotspot_onoff); + + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + hotspot_onoff = (struct hs_onoff *)buf; + hotspot_onoff->ifindex = RtmpOsGetNetIfIndex(net_dev); + hotspot_onoff->hs_onoff = onoff; + + RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_HS_ONOFF, NULL, (PUCHAR)buf, buflen); + os_free_mem(NULL, buf); +} + + +void HotspotOnOffEvent(PNET_DEV net_dev, int onoff) +{ + + wext_hotspot_onoff_event(net_dev, onoff); +} + + +static void wext_hotspot_ap_reload_event(PNET_DEV net_dev) +{ + struct hs_onoff *hotspot_onoff; + UINT16 buflen = 0; + char *buf; + + buflen = sizeof(*hotspot_onoff); + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + hotspot_onoff = (struct hs_onoff *)buf; + hotspot_onoff->ifindex = RtmpOsGetNetIfIndex(net_dev); + + RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_HS_AP_RELOAD, NULL, (PUCHAR)buf, buflen); + os_free_mem(NULL, buf); +} + + +void HotspotAPReload(PNET_DEV net_dev) +{ + wext_hotspot_ap_reload_event(net_dev); +} + + +#ifdef CONFIG_AP_SUPPORT +BOOLEAN HSIPv4Check( + IN PRTMP_ADAPTER pAd, + PUSHORT pWcid, + PNDIS_PACKET pPacket, + PUCHAR pSrcBuf, + UINT16 srcPort, + UINT16 dstPort) +{ + struct wifi_dev *wdev; + BSS_STRUCT *pMbss; + UCHAR wdev_idx = RTMP_GET_PACKET_WDEV(pPacket); + + ASSERT(wdev_idx < WDEV_NUM_MAX); + if (wdev_idx >= WDEV_NUM_MAX) + return FALSE; + + wdev = pAd->wdev_list[wdev_idx]; + ASSERT(wdev->func_idx < pAd->ApCfg.BssidNum); + + pMbss = &pAd->ApCfg.MBSSID[wdev->func_idx]; + if ((pMbss->HotSpotCtrl.HotSpotEnable) +#ifdef CONFIG_HOTSPOT_R2 + || (pMbss->HotSpotCtrl.bASANEnable) +#endif + ) + { + if (srcPort == 0x43 && dstPort == 0x44) + { + //UCHAR *pTargetIPAddr = pSrcBuf + 24; + /* Client hardware address */ + UCHAR *pTargetMACAddr = pSrcBuf + 36; + + /* Convert group-address DHCP packets to individually-addressed 802.11 frames */ + if (*pWcid == pMbss->wdev.tr_tb_idx && pMbss->HotSpotCtrl.DGAFDisable) /* MCAST_WCID Fix */ + { + UCHAR Index; + PUCHAR pSrcBufOriginal = GET_OS_PKT_DATAPTR(pPacket); + for (Index = 0; Index < MAC_ADDR_LEN; Index++) + { + DBGPRINT(RT_DEBUG_OFF, ("Original source address(%d) = %02x\n",Index, pSrcBufOriginal[Index])); + pSrcBufOriginal[Index] = pTargetMACAddr[Index]; + DBGPRINT(RT_DEBUG_OFF, ("Source address(%d) = %02x\n", Index, pSrcBuf[Index])); + } + + DBGPRINT(RT_DEBUG_OFF, ("Convert broadcast dhcp to unicat frame when dgaf disable\n")); + + if (!ApAllowToSendPacket(pAd, &pAd->ApCfg.MBSSID[wdev_idx].wdev, pPacket, (UCHAR *)pWcid)) + return FALSE; + + RTMP_SET_PACKET_WCID(pPacket, *pWcid); + } + } + } + return TRUE; +} + + +static BOOLEAN IsICMPv4EchoPacket( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData) +{ + UINT16 ProtoType; + UCHAR *Pos = pData; + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_IP) + { + Pos += 9; + + if (*Pos == 0x01) + { + Pos += 11; + if (*Pos == 0x08) + { + Pos++; + if (*Pos == 0x00) + { + DBGPRINT(RT_DEBUG_OFF, ("ICMPv4Echp Packet\n")); + return TRUE; + } + } + } + + } + + return FALSE; +} + +BOOLEAN L2FilterInspection( + IN PRTMP_ADAPTER pAd, + IN PHOTSPOT_CTRL pHSCtrl, + IN PUCHAR pData) +{ + if (IsICMPv4EchoPacket(pAd, pData)) + { + if (pHSCtrl->ICMPv4Deny) + return TRUE; + else + return FALSE; + } + + return FALSE; +} + +BOOLEAN ProbeReqforHSAP( + IN PRTMP_ADAPTER pAd, + IN UCHAR APIndex, + IN struct _PEER_PROBE_REQ_PARAM *ProbeReqParam) +{ + + PHOTSPOT_CTRL pHSCtrl; + pHSCtrl = &pAd->ApCfg.MBSSID[APIndex].HotSpotCtrl; + + if (pHSCtrl->HotSpotEnable && ProbeReqParam->IsIWIE) + { + if (ProbeReqParam->IsHessid && pHSCtrl->IsHessid) + { + if(NdisEqualMemory(ProbeReqParam->Hessid, pHSCtrl->Hessid, MAC_ADDR_LEN) || + NdisEqualMemory(ProbeReqParam->Hessid, BROADCAST_ADDR, MAC_ADDR_LEN)) + ; + else + return FALSE; + } + + if ((ProbeReqParam->AccessNetWorkType == pHSCtrl->AccessNetWorkType) || + (ProbeReqParam->AccessNetWorkType == 0x0f)) + return TRUE; + else + return FALSE; + } + else + return TRUE; +} + +inline INT Set_HotSpot_DGAF( + IN PRTMP_ADAPTER pAd, + UCHAR Disable) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UCHAR APIndex = pObj->ioctl_if; + PHOTSPOT_CTRL pHSCtrl; + + pHSCtrl = &pAd->ApCfg.MBSSID[APIndex].HotSpotCtrl; + + pHSCtrl->DGAFDisable = Disable; + + return 0; +} + +INT Set_HotSpot_Param( + IN PRTMP_ADAPTER pAd, + UINT32 Param, + UINT32 Value) +{ + + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UCHAR APIndex = pObj->ioctl_if; + PHOTSPOT_CTRL pHSCtrl; + PWNM_CTRL pWNMCtrl; + PGAS_CTRL pGASCtrl; + + pHSCtrl = &pAd->ApCfg.MBSSID[APIndex].HotSpotCtrl; + pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; + pGASCtrl = &pAd->ApCfg.MBSSID[APIndex].GASCtrl; + + switch (Param) { + case PARAM_DGAF_DISABLED: + pHSCtrl->DGAFDisable = Value; + break; + case PARAM_PROXY_ARP: + pWNMCtrl->ProxyARPEnable = Value; + break; + case PARAM_L2_FILTER: + pHSCtrl->L2Filter = Value; + break; + case PARAM_ICMPV4_DENY: + pHSCtrl->ICMPv4Deny = Value; + break; + case PARAM_MMPDU_SIZE: + pHSCtrl->MMPDUSize = Value; + break; + case PARAM_EXTERNAL_ANQP_SERVER_TEST: + pGASCtrl->ExternalANQPServerTest = Value; + break; + case PARAM_GAS_COME_BACK_DELAY: + pGASCtrl->cb_delay = Value; + break; +#ifdef CONFIG_HOTSPOT_R2 + case PARAM_WNM_NOTIFICATION: + pWNMCtrl->WNMNotifyEnable = Value; + break; + case PARAM_QOSMAP: + pHSCtrl->QosMapEnable = Value; + break; +#endif + default: + DBGPRINT(RT_DEBUG_ERROR, ("Unknow Parameter:%d\n", Param)); + break; + } + + return 0; +} +#endif /* CONFIG_AP_SUPPORT */ + +VOID HSCtrlRemoveAllIE(PHOTSPOT_CTRL pHSCtrl) +{ + + /* Remove all IE from daemon */ + if (pHSCtrl->P2PIELen) + { + pHSCtrl->P2PIELen = 0; + os_free_mem(NULL, pHSCtrl->P2PIE); + } + + if (pHSCtrl->HSIndicationIELen) + { + pHSCtrl->HSIndicationIELen = 0; + os_free_mem(NULL, pHSCtrl->HSIndicationIE); + } + + /*if (pHSCtrl->InterWorkingIELen) + { + pHSCtrl->InterWorkingIELen = 0; + os_free_mem(NULL, pHSCtrl->InterWorkingIE); + } + + if (pHSCtrl->AdvertisementProtoIELen) + { + pHSCtrl->AdvertisementProtoIELen = 0; + os_free_mem(NULL, pHSCtrl->AdvertisementProtoIE); + } + */ + + if (pHSCtrl->QosMapSetIELen) + { + /*pHSCtrl->AdvertisementProtoIELen = 0;*/ + os_free_mem(NULL, pHSCtrl->QosMapSetIE); + } + + if (pHSCtrl->RoamingConsortiumIELen) + { + pHSCtrl->RoamingConsortiumIELen = 0; + os_free_mem(NULL, pHSCtrl->RoamingConsortiumIE); + } +} + +VOID GASCtrlRemoveAllIE(PGAS_CTRL pGasCtrl) +{ + if (pGasCtrl->InterWorkingIELen && pGasCtrl->InterWorkingIE) { + os_free_mem(NULL, pGasCtrl->InterWorkingIE); + pGasCtrl->InterWorkingIE = NULL; + pGasCtrl->InterWorkingIELen = 0; + } + + if (pGasCtrl->AdvertisementProtoIELen && pGasCtrl->AdvertisementProtoIE) { + os_free_mem(NULL, pGasCtrl->AdvertisementProtoIE); + pGasCtrl->AdvertisementProtoIE = NULL; + pGasCtrl->AdvertisementProtoIELen = 0; + } +} + +#ifdef CONFIG_AP_SUPPORT +VOID Clear_Hotspot_All_IE( + IN PRTMP_ADAPTER pAd) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UCHAR APIndex = pObj->ioctl_if; + PHOTSPOT_CTRL pHSCtrl; + PGAS_CTRL pGasCtrl; + + pHSCtrl = &pAd->ApCfg.MBSSID[APIndex].HotSpotCtrl; + pGasCtrl = &pAd->ApCfg.MBSSID[APIndex].GASCtrl; + HSCtrlRemoveAllIE(pHSCtrl); + GASCtrlRemoveAllIE(pGasCtrl); +} +#endif + +INT Set_HotSpot_OnOff( + IN PRTMP_ADAPTER pAd, + IN UINT8 OnOff, + IN UINT8 EventTrigger, + IN UINT8 EventType) +{ + UCHAR *Buf; + HSCTRL_EVENT_DATA *Event; + UINT32 Len = 0; +#ifdef CONFIG_AP_SUPPORT + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UCHAR APIndex = pObj->ioctl_if; +#endif /* CONFIG_AP_SUPPORT */ + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event)); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return FALSE; + } + + NdisZeroMemory(Buf, sizeof(*Event)); + + Event = (HSCTRL_EVENT_DATA *)Buf; +#ifdef CONFIG_AP_SUPPORT + Event->ControlIndex = APIndex; +#endif /* CONFIG_STA_SUPPORT */ + Len += 1; + + Event->EventTrigger = EventTrigger; + Len += 1; + + Event->EventType = EventType; + Len += 1; + + if (OnOff) + MlmeEnqueue(pAd, HSCTRL_STATE_MACHINE, HSCTRL_ON, Len, Buf, 0); + else + MlmeEnqueue(pAd, HSCTRL_STATE_MACHINE, HSCTRL_OFF, Len, Buf, 0); + + os_free_mem(NULL, Buf); + + return TRUE; +} + + +enum HSCTRL_STATE HSCtrlCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PHOTSPOT_CTRL pHSCtrl; +#ifdef CONFIG_AP_SUPPORT + PHSCTRL_EVENT_DATA Event = (PHSCTRL_EVENT_DATA)Elem->Msg; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + pHSCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].HotSpotCtrl; +#endif /* CONFIG_AP_SUPPORT */ + + + return pHSCtrl->HSCtrlState; +} + + +VOID HSCtrlSetCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem, + IN enum HSCTRL_STATE State) +{ + + PHOTSPOT_CTRL pHSCtrl; +#ifdef CONFIG_AP_SUPPORT + PHSCTRL_EVENT_DATA Event = (PHSCTRL_EVENT_DATA)Elem->Msg; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + pHSCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].HotSpotCtrl; +#endif /* CONFIG_AP_SUPPORT */ + + + pHSCtrl->HSCtrlState = State; +} + + +static VOID HSCtrlOn( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PHOTSPOT_CTRL pHSCtrl; + PGAS_CTRL pGASCtrl; + PNET_DEV NetDev; + HSCTRL_EVENT_DATA *Event = (HSCTRL_EVENT_DATA *)Elem->Msg; + + printk("%s\n", __FUNCTION__); + + +#ifdef CONFIG_AP_SUPPORT + NetDev = pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.if_dev; + pHSCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].HotSpotCtrl; + pGASCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].GASCtrl; +#endif /* CONFIG_AP_SUPPORT */ + + pGASCtrl->b11U_enable = 1; + pHSCtrl->HotSpotEnable = 1; + pHSCtrl->HSDaemonReady = 1; +#ifdef CONFIG_AP_SUPPORT + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); +#endif /* CONFIG_AP_SUPPORT */ + + HSCtrlSetCurrentState(pAd, Elem, HSCTRL_IDLE); + + /* Send indication to daemon */ + if (Event->EventTrigger) { + switch (Event->EventType) { + case HS_ON_OFF_BASE: + HotspotOnOffEvent(NetDev, 1); + break; + case HS_AP_RELOAD: + HotspotAPReload(NetDev); + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow event type(%d)\n", __FUNCTION__, Event->EventType)); + break; + } + } +} + + +static VOID HSCtrlInit( + IN PRTMP_ADAPTER pAd) +{ + PHOTSPOT_CTRL pHSCtrl; +#ifdef CONFIG_AP_SUPPORT + UCHAR APIndex; +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + pHSCtrl = &pAd->ApCfg.MBSSID[APIndex].HotSpotCtrl; + NdisZeroMemory(pHSCtrl, sizeof(*pHSCtrl)); + pHSCtrl->HotSpotEnable = 0; + pHSCtrl->HSCtrlState = HSCTRL_IDLE; + } +#endif /* CONFIG_AP_SUPPORT */ +} + + +VOID HSCtrlExit( + IN PRTMP_ADAPTER pAd) +{ + PHOTSPOT_CTRL pHSCtrl; +#ifdef CONFIG_AP_SUPPORT + UCHAR APIndex; +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + pHSCtrl = &pAd->ApCfg.MBSSID[APIndex].HotSpotCtrl; + + /* Remove all IE */ + HSCtrlRemoveAllIE(pHSCtrl); + GASCtrlRemoveAllIE(&pAd->ApCfg.MBSSID[APIndex].GASCtrl); + } +#endif /* CONFIG_AP_SUPPORT */ +} + + +VOID HSCtrlHalt( + IN PRTMP_ADAPTER pAd) +{ + + PHOTSPOT_CTRL pHSCtrl; +#ifdef CONFIG_AP_SUPPORT + UCHAR APIndex; +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + pHSCtrl = &pAd->ApCfg.MBSSID[APIndex].HotSpotCtrl; + pHSCtrl->HotSpotEnable = 0; + + } +#endif /* CONFIG_AP_SUPPORT */ +} + +static VOID HSCtrlOff( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PHOTSPOT_CTRL pHSCtrl; + PNET_DEV NetDev; + HSCTRL_EVENT_DATA *Event = (HSCTRL_EVENT_DATA *)Elem->Msg; +#ifdef CONFIG_DOT11V_WNM + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; +#endif + UCHAR tmp; + + printk("%s\n", __FUNCTION__); + +#ifdef CONFIG_AP_SUPPORT + NetDev = pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.if_dev; + pHSCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].HotSpotCtrl; + +#ifdef CONFIG_HOTSPOT_R2 + pHSCtrl->bASANEnable = 0; + pHSCtrl->QLoadTestEnable = 0; +#endif +#endif /* CONFIG_AP_SUPPORT */ + + pHSCtrl->HotSpotEnable = 0; + pHSCtrl->HSDaemonReady = 0; + pHSCtrl->DGAFDisable = 0; + pHSCtrl->L2Filter = 0; + pHSCtrl->ICMPv4Deny = 0; + +#ifdef CONFIG_DOT11V_WNM + pWNMCtrl->ProxyARPEnable = 0; +#ifdef CONFIG_HOTSPOT_R2 + pWNMCtrl->WNMNotifyEnable = 0; + pHSCtrl->QosMapEnable = 0; + for(tmp = 0;tmp<21;tmp++) + { + pHSCtrl->DscpException[tmp] = 0xff; + pHSCtrl->DscpException[tmp] |= (0xff << 8); + } + for(tmp = 0;tmp<8;tmp++) + { + pHSCtrl->DscpRange[tmp] = 0xff; + pHSCtrl->DscpRange[tmp] |= (0xff << 8); + } +#endif +#endif + +#ifdef CONFIG_AP_SUPPORT + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); +#endif /* CONFIG_AP_SUPPORT */ + + HSCtrlSetCurrentState(pAd, Elem, HSCTRL_IDLE); + + if (Event->EventTrigger) { + switch (Event->EventType) { + case HS_ON_OFF_BASE: + HotspotOnOffEvent(NetDev, 0); + break; + case HS_AP_RELOAD: + HotspotAPReload(NetDev); + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow event type(%d)\n", __FUNCTION__, Event->EventType)); + break; + } + } +} + +BOOLEAN HotSpotEnable( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem, + IN INT Type) +{ + PHOTSPOT_CTRL pHSCtrl = NULL; + +#ifdef CONFIG_AP_SUPPORT + UCHAR APIndex; + PGAS_EVENT_DATA Event; + GAS_FRAME *GASFrame; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + if (Type == GAS_STATE_MESSAGES) + { + Event = (PGAS_EVENT_DATA)Elem->Msg; + pHSCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].HotSpotCtrl; + } + else if (Type == ACTION_STATE_MESSAGES) + { + GASFrame = (GAS_FRAME *)Elem->Msg; + + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + if (MAC_ADDR_EQUAL(GASFrame->Hdr.Addr3, pAd->ApCfg.MBSSID[APIndex].wdev.bssid)) + { + pHSCtrl = &pAd->ApCfg.MBSSID[APIndex].HotSpotCtrl; + break; + } + } + + if (!pHSCtrl) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Can not find Peer Control\n", __FUNCTION__)); + return FALSE; + } + } +#endif /* CONFIG_AP_SUPPORT */ + + + return pHSCtrl->HotSpotEnable; +} + + +VOID HSCtrlStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + HSCtrlInit(pAd); + + StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, MAX_HSCTRL_STATE, MAX_HSCTRL_MSG, (STATE_MACHINE_FUNC)Drop, HSCTRL_IDLE, HSCTRL_MACHINE_BASE); + + StateMachineSetAction(S, HSCTRL_IDLE, HSCTRL_ON, (STATE_MACHINE_FUNC)HSCtrlOn); + StateMachineSetAction(S, HSCTRL_IDLE, HSCTRL_OFF, (STATE_MACHINE_FUNC)HSCtrlOff); +} + + +BOOLEAN hotspot_rx_snoop(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, RX_BLK *pRxBlk) +{ + BOOLEAN drop = FALSE; + BOOLEAN FoundProxyARPEntry; + BSS_STRUCT *pMbss = pEntry->pMbss; + PUCHAR pData = NdisEqualMemory(SNAP_802_1H, pRxBlk->pData, 6) ? (pRxBlk->pData + 6) : pRxBlk->pData; + UCHAR Offset = 0; + + /* Check if Proxy ARP Candidate for IPv4 */ + if (IsIPv4ProxyARPCandidate(pAd, pData)) + { + FoundProxyARPEntry = IPv4ProxyARP(pAd, pMbss, pData, FALSE); + if (FoundProxyARPEntry) { + DBGPRINT(RT_DEBUG_TRACE, ("Find proxy entry for IPv4\n")); + drop = TRUE; + goto done; + } + } + + /* Check if Neighbor solicitation during duplicate address detection procedure */ + if (IsIpv6DuplicateAddrDetect(pAd, pData, &Offset)) + { + /* Proxy MAC address/IPv6 mapping */ + //AddIPv6ProxyARPEntry(pAd, pMbss, pEntry->Addr, (pData + 50)); + DBGPRINT(RT_DEBUG_OFF, ("AddIPv6ProxyARPEntry:offset=%d\n", Offset)); + AddIPv6ProxyARPEntry(pAd, pMbss, pEntry->Addr, (pData + Offset)); + DBGPRINT(RT_DEBUG_ERROR, ("Drop IPv6 DAD\n")); + drop = TRUE; + goto done; + } + + /* Check if Router solicitation */ + if (IsIPv6RouterSolicitation(pAd, pData)) + { + /* Proxy MAC address/IPv6 mapping for link local address */ + AddIPv6ProxyARPEntry(pAd, pMbss, pEntry->Addr, (pData + 10)); + } + +//JERRY: add to parse DHCPv6 solicit to check proxy arp entry + if (IsIPv6DHCPv6Solicitation(pAd, pData)) + { + AddIPv6ProxyARPEntry(pAd, pMbss, pEntry->Addr, (pData + 10)); + } + + /* Check if Proxy ARP Candidate for IPv6 */ + if (IsIPv6ProxyARPCandidate(pAd, pData)) + { + FoundProxyARPEntry = IPv6ProxyARP(pAd, pMbss, pData, FALSE); + if (FoundProxyARPEntry) { + DBGPRINT(RT_DEBUG_TRACE, ("Find proxy entry for IPv6\n")); + drop = TRUE; + goto done; + } else { + /* Proxy MAC address/IPv6 mapping */ + AddIPv6ProxyARPEntry(pAd, pMbss, pEntry->Addr, (pData + 10)); + } + } + + if (!pEntry->pMbss->HotSpotCtrl.DGAFDisable) + { + if (IsGratuitousARP(pAd, pData, pRxBlk->pHeader->Addr3, pMbss)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Drop Gratutious ARP\n")); + drop = TRUE; + goto done; + } + + if (IsUnsolicitedNeighborAdver(pAd, pData)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Drop unsoclicited neighbor advertisement packet\n")); + drop = TRUE; + goto done; + } + } + +done: + return drop; +} + +BOOLEAN hotspot_rx_l2_filter(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, RX_BLK *pRxBlk) +{ + BSS_STRUCT *pMbss = pEntry->pMbss; + BOOLEAN drop = FALSE; + PUCHAR pData = NdisEqualMemory(SNAP_802_1H, pRxBlk->pData, 6) ? (pRxBlk->pData + 6) : pRxBlk->pData; + + if (pEntry->pMbss->HotSpotCtrl.L2Filter == L2FilterBuiltIn) + { + BOOLEAN NeedDrop = FALSE; + NeedDrop = L2FilterInspection(pAd, &pMbss->HotSpotCtrl, pData); + + if (NeedDrop) + { + DBGPRINT(RT_DEBUG_OFF, ("Drop Filter BuiltIn packet\n")); + drop = TRUE; + goto done; + } + } + else if (pMbss->HotSpotCtrl.L2Filter == L2FilterExternal) + { + UINT16 Index; + BOOLEAN NeedSendToExternal; + BSS_STRUCT *pMbss = pEntry->pMbss; + PUCHAR pData = NdisEqualMemory(SNAP_802_1H, pRxBlk->pData, 6) ? (pRxBlk->pData + 6) : pRxBlk->pData; + + NeedSendToExternal = L2FilterInspection(pAd, &pMbss->HotSpotCtrl, pData); + + if (NeedSendToExternal) + { + /* Change to broadcast DS */ + DBGPRINT(RT_DEBUG_OFF, ("Change to broadcast under L2FilterExternal\n")); + for (Index = 0; Index < MAC_ADDR_LEN; Index++) + DBGPRINT(RT_DEBUG_OFF, ("DA[%d] = %x\n", Index, pRxBlk->pHeader->Addr3[Index])); + + pRxBlk->pHeader->Addr3[0] = 0xf0; + pRxBlk->pHeader->Addr3[1] = 0xde; + pRxBlk->pHeader->Addr3[2] = 0xf1; + pRxBlk->pHeader->Addr3[3] = 0x70; + pRxBlk->pHeader->Addr3[4] = 0x86; + pRxBlk->pHeader->Addr3[5] = 0x52; + } + } + + /* Check if TDLS/DLS frame */ + if (IsTDLSPacket(pAd, pData)) + { + DBGPRINT(RT_DEBUG_OFF, ("Drop TDLS Packet\n")); + drop = TRUE; + } + +done: + return drop; +} + + +BOOLEAN hotspot_rx_handler(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, RX_BLK *pRxBlk) +{ + BOOLEAN drop = FALSE; + if (pEntry->pMbss->WNMCtrl.ProxyARPEnable) + drop = hotspot_rx_snoop(pAd, pEntry, pRxBlk); + + if ((drop == FALSE) && (pEntry->pMbss->HotSpotCtrl.L2Filter != L2FilterDisable)) + drop = hotspot_rx_l2_filter(pAd, pEntry, pRxBlk); + + if (drop == TRUE) { + RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE); + } + + return drop; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/igmp_snoop.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/igmp_snoop.c new file mode 100644 index 000000000..4ad657655 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/igmp_snoop.c @@ -0,0 +1,1759 @@ +#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, (RT_LIST_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, (RT_LIST_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 */ + 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)); + 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_TRACE, ("%s: already in Members list.\n", __FUNCTION__)); + return FALSE; + } + + pMemberEntry = pMemberEntry->pNext; + } + } + + RTMP_SEM_LOCK(&pMulticastFilterTable->MulticastFilterTabLock); + do + { + ULONG Now; + /* the multicast entry already exist but doesn't include the member yet. */ + if (pEntry != NULL && pMemberAddr != NULL) + { + InsertIgmpMember(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)) + { + 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_TRACE, ("%s: the Group doesn't exist.\n", __FUNCTION__)); + } + } while(FALSE); + + RTMP_SEM_UNLOCK(&pMulticastFilterTable->MulticastFilterTabLock); + + return TRUE; +} + +/* + ========================================================================== + Description: + Look up the MAC address in the IGMP table. Return NULL if not found. + Return: + pEntry - pointer to the MAC entry; NULL is not found + ========================================================================== +*/ +PMULTICAST_FILTER_TABLE_ENTRY MulticastFilterTableLookup( + IN 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; +} + + +BOOLEAN ismDNS( + IN PUCHAR pDstMacAddr, + IN PUCHAR pIpHeader) +{ + UINT16 IpProtocol = ntohs(*((UINT16 *) (pIpHeader))); + UCHAR IpUDP; + UCHAR mDNSv6[16] = {0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 ,0x00, 0x00, 0x00, 0x00, 0x00, 0xFB}; + + if (IpProtocol == ETH_P_IP) { + IpUDP = (UCHAR)*(pIpHeader + 11); + if (IpUDP == IP_UDP) { + /* check the ip address : 224.0.0.x reserved for mDNS & well known Protocol*/ + if (((UCHAR)*(pIpHeader + (11+7)) == 0xE0) + && ((UCHAR)*(pIpHeader + (11+8)) == 0x00) + && ((UCHAR)*(pIpHeader + (11+9)) == 0x00) + ) + return TRUE; + } + } else if (IpProtocol == ETH_P_IPV6) { + IpUDP = (UCHAR)*(pIpHeader + 8); + if (IpUDP == IP_UDP) { + /* check the ipv6 address : ff02::fb reserved for mDNSv6 */ + if (!memcmp((pIpHeader + (8+18)), mDNSv6, 16)) + 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, (RT_LIST_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, (RT_LIST_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, (RT_LIST_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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT i; + BOOLEAN bGroupId = 1; + RTMP_STRING *value; + RTMP_STRING *thisChar; + UCHAR IpAddr[4]; + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR GroupId[MAC_ADDR_LEN]; + PUCHAR *pAddr = (PUCHAR *)&Addr; + PNET_DEV pDev; + POS_COOKIE pObj; + UCHAR ifIndex; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + pDev = (ifIndex == MAIN_MBSSID) ? (pAd->net_dev) : (pAd->ApCfg.MBSSID[ifIndex].wdev.if_dev); + + while ((thisChar = strsep((char **)&arg, "-")) != NULL) + { + /* refuse the Member if it's not a MAC address. */ + if((bGroupId == 0) && (strlen(thisChar) != 17)) + continue; + + if(strlen(thisChar) == 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + { + for (i=0, value = rstrtok(thisChar,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid */ + + AtoH(value, &Addr[i++], 1); + } + + if(i != 6) + return FALSE; /*Invalid */ + } + else + { + for (i=0, value = rstrtok(thisChar,"."); value; value = rstrtok(NULL,".")) + { + if((strlen(value) > 0) && (strlen(value) <= 3)) + { + int ii; + for(ii=0; iiOS_Cookie; + ifIndex = pObj->ioctl_if; + + pDev = (ifIndex == MAIN_MBSSID) ? (pAd->net_dev) : (pAd->ApCfg.MBSSID[ifIndex].wdev.if_dev); + + while ((thisChar = strsep((char **)&arg, "-")) != NULL) + { + /* refuse the Member if it's not a MAC address. */ + if((bGroupId == 0) && (strlen(thisChar) != 17)) + continue; + + if(strlen(thisChar) == 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + { + for (i=0, value = rstrtok(thisChar,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid */ + + AtoH(value, &Addr[i++], 1); + } + + if(i != 6) + return FALSE; /*Invalid */ + } + else + { + for (i=0, value = rstrtok(thisChar,"."); value; value = rstrtok(NULL,".")) + { + if((strlen(value) > 0) && (strlen(value) <= 3)) + { + int ii; + for(ii=0; ii 0 ) + MulticastFilterTableDeleteEntry(pAd, (PUCHAR)GroupId, Addr, pDev); + + 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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + IGMPTableDisplay(pAd); + return TRUE; +} + +void rtmp_read_igmp_snoop_from_file( + IN PRTMP_ADAPTER pAd, + RTMP_STRING *tmpbuf, + RTMP_STRING *buffer) +{ + /*IgmpSnEnable */ + if(RTMPGetKeyParameter("IgmpSnEnable", tmpbuf, 128, buffer, TRUE)) + { + if ((strncmp(tmpbuf, "0", 1) == 0)) + pAd->ApCfg.IgmpSnoopEnable = FALSE; + else if ((strncmp(tmpbuf, "1", 1) == 0)) + pAd->ApCfg.IgmpSnoopEnable = TRUE; + else + pAd->ApCfg.IgmpSnoopEnable = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, (" IGMP Snooping Enable=%d\n", pAd->ApCfg.IgmpSnoopEnable)); + } +} + +NDIS_STATUS IgmpPktInfoQuery( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSrcBufVA, + IN PNDIS_PACKET pPacket, + IN struct wifi_dev *wdev, + OUT INT *pInIgmpGroup, + OUT PMULTICAST_FILTER_TABLE_ENTRY *ppGroupEntry) +{ + if(IS_MULTICAST_MAC_ADDR(pSrcBufVA)) + { + BOOLEAN IgmpMldPkt = FALSE; + PUCHAR pIpHeader = pSrcBufVA + 12; + + if(ntohs(*((UINT16 *)(pIpHeader))) == ETH_P_IPV6) + IgmpMldPkt = IPv6MulticastFilterExcluded(pSrcBufVA, pIpHeader); + else + IgmpMldPkt = isIgmpPkt(pSrcBufVA, pIpHeader); + + if (ismDNS(pSrcBufVA, pIpHeader)) { + /* just update the timestamp */ + *ppGroupEntry = MulticastFilterTableLookup(pAd->pMulticastFilterTable, + pSrcBufVA, + wdev->if_dev); + + *pInIgmpGroup = IGMP_NONE; + return NDIS_STATUS_SUCCESS; + } + + if (IgmpMldPkt) + { + *ppGroupEntry = NULL; + *pInIgmpGroup = IGMP_PKT; + } + else if ((*ppGroupEntry = MulticastFilterTableLookup(pAd->pMulticastFilterTable, pSrcBufVA, + wdev->if_dev)) == NULL) + { + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + else + *pInIgmpGroup = IGMP_IN_GROUP; + } + else if (IS_BROADCAST_MAC_ADDR(pSrcBufVA)) + { + PUCHAR pDstIpAddr = pSrcBufVA + 30; /* point to Destination of Ip address of IP header. */ + UCHAR GroupMacAddr[6]; + PUCHAR pGroupMacAddr = (PUCHAR)&GroupMacAddr; + + ConvertMulticastIP2MAC(pDstIpAddr, (PUCHAR *)&pGroupMacAddr, ETH_P_IP); + if ((*ppGroupEntry = MulticastFilterTableLookup(pAd->pMulticastFilterTable, pGroupMacAddr, + wdev->if_dev)) != NULL) + { + *pInIgmpGroup = IGMP_IN_GROUP; + } + } + + return NDIS_STATUS_SUCCESS; +} + +NDIS_STATUS IgmpProtocolPktClone( + 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; + STA_TR_ENTRY *tr_entry = NULL; + UCHAR wcid = RESERVED_WCID; +#ifdef IP_ASSEMBLY + INT ret=0; + PACKET_INFO PacketInfo; + UCHAR *pSrcBufVA; + UINT SrcBufLen; + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + if ((!pSrcBufVA) || (SrcBufLen <= 14)) { + goto drop_pkt; + } +#endif /* IP_ASSEMBLY */ + + if ((IgmpPktInGroup != IGMP_PKT)) + return NDIS_STATUS_FAILURE; + + wcid = RTMP_GET_PACKET_WCID(pPacket); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): wcid=%d\n", __FUNCTION__, wcid)); + if (!(VALID_TR_WCID(wcid) && IS_VALID_ENTRY(&pAd->MacTab.tr_entry[wcid]))) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Invalid wcid=%d\n", __func__, wcid)); + return NDIS_STATUS_FAILURE; + } + + tr_entry = &pAd->MacTab.tr_entry[wcid]; + if (!tr_entry->wdev) { + return NDIS_STATUS_FAILURE; + } + + + /* check all members of the IGMP group. */ + + OS_PKT_CLONE(pAd, pPacket, pSkbClone, MEM_ALLOC_FLAG); + //pSkbClone=(PNDIS_PACKET)OS_PKT_COPY(pPacket); + if (pSkbClone) + { + if (pAd->TxSwQueue[QueIdx].Number >= pAd->TxSwQMaxLen) + { + { +#ifdef BLOCK_NET_IF + StopNetIfQueue(pAd, QueIdx, pSkbClone); +#endif /* BLOCK_NET_IF */ + goto drop_pkt; + + } + }else { +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + if ((pAd->MacTab.fAnyStationInPsm == 1) && (tr_entry->EntryType == ENTRY_CAT_MCAST)) { + if (tr_entry->tx_queue[QID_AC_BE].Number > MAX_PACKETS_IN_MCAST_PS_QUEUE) { + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): BSS tx_queue full\n", __FUNCTION__, __LINE__)); + goto drop_pkt; + } + } else if ((tr_entry->EntryType != ENTRY_CAT_MCAST) && (tr_entry->PsMode == PWR_SAVE)) { + if (tr_entry->tx_queue[QID_AC_BE].Number+tr_entry->tx_queue[QID_AC_BK].Number+tr_entry->tx_queue[QID_AC_VI].Number+tr_entry->tx_queue[QID_AC_VO].Number > MAX_PACKETS_IN_PS_QUEUE) { + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): STA tx_queue full\n", __FUNCTION__, __LINE__)); + goto drop_pkt; + } + } + } +#endif /* MT_MAC */ + +#ifdef UAPSD_SUPPORT + if (IS_ENTRY_CLIENT(tr_entry) && (wcid < MAX_LEN_OF_MAC_TABLE) + && (tr_entry->PsMode == PWR_SAVE) + && UAPSD_MR_IS_UAPSD_AC(&pAd->MacTab.Content[wcid], QueIdx)) + { + UAPSD_PacketEnqueue(pAd, &pAd->MacTab.Content[wcid], pSkbClone, QueIdx, FALSE); + } + else +#endif /* UAPSD_SUPPORT */ +#ifdef IP_ASSEMBLY + if ((pAd->CommonCfg.BACapability.field.AutoBA == FALSE) && (ret = rtmp_IpAssembleHandle(pAd,tr_entry, pPacket,QueIdx,PacketInfo))!=NDIS_STATUS_INVALID_DATA) + { + if(ret == NDIS_STATUS_FAILURE) + { + goto nofree_drop_pkt; + } + /*else if success do normal path means*/ + + }else +#endif /* IP_ASSEMBLY */ + if (rtmp_enq_req(pAd, pSkbClone, QueIdx, tr_entry, FALSE,NULL) == FALSE) { + goto drop_pkt; + } + + /* If the data is broadcast/multicast and any stations are in PWR_SAVE, we set BCAST TIM bit. */ + /* If the data is unicast and the station is in PWR_SAVE, we set STA TIM bit */ + + if (tr_entry->EntryType == ENTRY_CAT_MCAST) + { + if (pAd->MacTab.fAnyStationInPsm == TRUE) + WLAN_MR_TIM_BCMC_SET(tr_entry->func_tb_idx); /* mark MCAST/BCAST TIM bit */ + } + else + { + if (IS_ENTRY_CLIENT(tr_entry) && (tr_entry->PsMode == PWR_SAVE)) + { + /* mark corresponding TIM bit in outgoing BEACON frame */ +#ifdef UAPSD_SUPPORT + if (wcid < MAX_LEN_OF_MAC_TABLE && UAPSD_MR_IS_NOT_TIM_BIT_NEEDED_HANDLED(&pAd->MacTab.Content[wcid], 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, tr_entry->func_tb_idx, tr_entry->wcid); + } + } + } + } + } + + return NDIS_STATUS_SUCCESS; +drop_pkt: + if (pSkbClone) + RELEASE_NDIS_PACKET(pAd, pSkbClone, NDIS_STATUS_FAILURE); +nofree_drop_pkt: + + return NDIS_STATUS_FAILURE; +} + + + +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; + STA_TR_ENTRY *tr_entry = NULL; + USHORT Aid; + SST Sst = SST_ASSOC; + UCHAR PsMode = PWR_ACTIVE; + UCHAR Rate; +#ifndef MT_MAC + unsigned long IrqFlags; +#endif + 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) + { + 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); + // TODO: shiang-usw, check get_netdev_from_bssid() here!! + if (pMacEntry && IS_ENTRY_CLIENT(pMacEntry) + && get_netdev_from_bssid(pAd, pMacEntry->wdev->wdev_idx) == 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) && + (pAd->MacTab.tr_entry[pMacEntry->wcid].PortSecured == WPA_802_1X_PORT_SECURED)) + { + OS_PKT_CLONE(pAd, pPacket, pSkbClone, MEM_ALLOC_FLAG); + if ((pSkbClone) +#ifdef DOT11V_WNM_SUPPORT + && (pMacEntry->Beclone == FALSE) +#endif /* DOT11V_WNM_SUPPORT */ + ) + { + RTMP_SET_PACKET_WCID(pSkbClone, (UCHAR)pMacEntry->Aid); + +//copy APSendPacket() unicast check portion. +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + tr_entry = &pAd->MacTab.tr_entry[pMacEntry->wcid]; + + if ((tr_entry->EntryType != ENTRY_CAT_MCAST) && (tr_entry->PsMode == PWR_SAVE)) + { + if (tr_entry->tx_queue[QID_AC_BE].Number+tr_entry->tx_queue[QID_AC_BK].Number+tr_entry->tx_queue[QID_AC_VI].Number+tr_entry->tx_queue[QID_AC_VO].Number > MAX_PACKETS_IN_PS_QUEUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): (wcid=%u)STA tx_queue full\n", __FUNCTION__, __LINE__,pMacEntry->wcid)); + RELEASE_NDIS_PACKET(pAd, pSkbClone, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + + } + } + + +#if defined(RTMP_MAC) || defined(RLT_MAC) + /* detect AC Category of tx packets to tune AC0(BE) TX_OP (MAC reg 0x1300) */ + // TODO: shiang-usw, check this for REG access, it should not be here! + if ((pAd->chipCap.hif_type == HIF_RTMP) || (pAd->chipCap.hif_type == HIF_RLT)) + detect_wmm_traffic(pAd, UserPriority, 1); +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + RTMP_SET_PACKET_UP(pSkbClone, UserPriority); + + + if (rtmp_enq_req(pAd, pSkbClone, QueIdx, tr_entry, FALSE, NULL) == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): (wcid=%u)STA rtmp_enq_req() fail!\n", __FUNCTION__, __LINE__,pMacEntry->wcid)); + RELEASE_NDIS_PACKET(pAd, pSkbClone, NDIS_STATUS_FAILURE); + return NDIS_STATUS_FAILURE; + } + + + if (tr_entry->EntryType == ENTRY_CAT_MCAST) //should not be here!! + { + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): (wcid=%u) ENTRY_CAT_MCAST !! ERROR check should not be here!\n", __FUNCTION__, __LINE__,pMacEntry->wcid)); + + if (pAd->MacTab.fAnyStationInPsm == 1) + WLAN_MR_TIM_BCMC_SET(tr_entry->func_tb_idx); /* mark MCAST/BCAST TIM bit */ + } + else + { + if (IS_ENTRY_CLIENT(tr_entry) && (tr_entry->PsMode == PWR_SAVE)) + { + /* mark corresponding TIM bit in outgoing BEACON frame */ +#ifdef UAPSD_SUPPORT + if (UAPSD_MR_IS_NOT_TIM_BIT_NEEDED_HANDLED(&pAd->MacTab.Content[tr_entry->wcid], 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, tr_entry->func_tb_idx, tr_entry->wcid); + } + } + } + + } +#endif /* MT_MAC */ + + } + 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->wdev->wdev_idx) == 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; + +#ifdef DOT11V_WNM_SUPPORT + pMacEntry->Beclone = FALSE; +#endif /* DOT11V_WNM_SUPPORT */ + continue; + } + +#ifndef MT_MAC +/*did't queue to AC queue for MT_MAC */ + if (PsMode == PWR_SAVE) + { + APInsertPsQueue(pAd, pSkbClone, pMacEntry, QueIdx); + } + else + { + 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); + } + } +#endif /* !MT_MAC */ + +#ifdef DOT11_N_SUPPORT + RTMP_BASetup(pAd, tr_entry, 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); + // TODO: shiang-usw, check for pMacEntry->wdev->wdev_idx here! + if (pMacEntry && IS_ENTRY_CLIENT(pMacEntry) + && get_netdev_from_bssid(pAd, pMacEntry->wdev->wdev_idx) == 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/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/map.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/map.c new file mode 100644 index 000000000..3aa80f1ed --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/map.c @@ -0,0 +1,386 @@ + + +#include "rt_config.h" +#include "map.h" + + +UCHAR MAP_OUI[3] = {0x50, 0x6F, 0x9A}; +UCHAR MAP_OUI_TYPE[1] = {0x1B}; +UCHAR MAP_EXT_ATTRI[1] = {0x06}; +UCHAR MAP_ATTRI_LEN[1] = {1}; + +UCHAR multicast_mac_1905[MAC_ADDR_LEN] = {0x01, 0x80, 0xC2, 0x00, 0x00, 0x13}; + +static UCHAR MAP_CheckDevRole( + PRTMP_ADAPTER pAd, + UCHAR wdev_type +) +{ + UCHAR res = 0; + + switch (wdev_type) { + case WDEV_TYPE_AP: + res = BIT(MAP_ROLE_FRONTHAUL_BSS); /* BH_BSS will be set by map cmd */ + break; + + /*case WDEV_TYPE_APCLI:*/ + case WDEV_TYPE_STA: + res = BIT(MAP_ROLE_BACKHAUL_STA); + break; + + default: + res = 0; + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_INFO, + ("%s():AP Role not set (Fixed me)\n", __func__)); + } + + return res; +} + +INT MAP_InsertMapWscAttr( + IN PRTMP_ADAPTER pAd, + IN struct wifi_dev *wdev, + OUT PUCHAR pFrameBuf +) +{ + UCHAR MapVendorExt[10] = {0}; + UCHAR va[2] = {0x10, 0x49}; + UCHAR vl[2] = {0x00, 0x06}; + UCHAR vi[3] = {0x00, 0x37, 0x2A}; + + /*WPS Vendor Extension */ + NdisMoveMemory(MapVendorExt, va, 2); + NdisMoveMemory(MapVendorExt + 2, vl, 2); + NdisMoveMemory(MapVendorExt + 4, vi, 3); + NdisMoveMemory(MapVendorExt + 7, MAP_EXT_ATTRI, 1); + NdisMoveMemory(MapVendorExt + 8, MAP_ATTRI_LEN, 1); + NdisMoveMemory(MapVendorExt + 9, &wdev->MAPCfg.DevOwnRole, 1); + + NdisMoveMemory(pFrameBuf, MapVendorExt, sizeof(MapVendorExt)); + + return sizeof(MapVendorExt); +} + +VOID MAP_InsertMapCapIE( + IN PRTMP_ADAPTER pAd, + IN struct wifi_dev *wdev, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen +) +{ + ULONG TmpLen; + UCHAR IEType = IE_VENDOR_SPECIFIC; + UCHAR IELen = 7; + UCHAR MAP_EXT_ATTRI_LEN = 1; + UCHAR MAP_EXT_ATTRI_VAL = wdev->MAPCfg.DevOwnRole; + + MakeOutgoingFrame(pFrameBuf, &TmpLen, + 1, &IEType, + 1, &IELen, + 3, MAP_OUI, + 1, MAP_OUI_TYPE, + 1, MAP_EXT_ATTRI, + 1, &MAP_EXT_ATTRI_LEN, + 1, &MAP_EXT_ATTRI_VAL, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TmpLen; +} + + +/* return map attribute*/ +BOOLEAN map_check_cap_ie( + IN PEID_STRUCT eid, + OUT unsigned char *cap +) +{ + BOOLEAN Ret = FALSE; + + if (NdisEqualMemory(eid->Octet, MAP_OUI, sizeof(MAP_OUI)) && (eid->Len >= 7)) { + if (NdisEqualMemory((UCHAR *)&eid->Octet[3], MAP_OUI_TYPE, sizeof(MAP_OUI_TYPE)) && + NdisEqualMemory((UCHAR *)&eid->Octet[4], MAP_EXT_ATTRI, sizeof(MAP_EXT_ATTRI)) && + eid->Octet[5] == 1) { + + *cap = eid->Octet[6]; + Ret = TRUE; + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s:[MAP] STA Attri = %d\n", __func__, eid->Octet[6])); + } + } + + return Ret; +} + + +UCHAR getNonOpChnNum( + IN PRTMP_ADAPTER pAd, + IN struct wifi_dev *wdev, + IN UCHAR op_class +) +{ + UCHAR i = 0, j = 0; + UCHAR nonOpChnNum = 0, opChnNum = 0; + UCHAR *opChList = get_channelset_by_reg_class(pAd, op_class); + UCHAR opChListLen = get_channel_set_num(opChList); + + for (i = 0; i < opChListLen; i++) { + for (j = -0; j < pAd->ChannelListNum; j++) { + if (opChList[i] == pAd->ChannelList[j].Channel) { + opChnNum++; + break; + } + } + } + nonOpChnNum = opChListLen - opChnNum; + + return nonOpChnNum; +} + +VOID setNonOpChnList( + IN PRTMP_ADAPTER pAd, + IN struct wifi_dev *wdev, + IN PCHAR nonOpChnList, + IN UCHAR op_class, + IN UCHAR nonOpChnNum +) +{ + UCHAR i = 0, j = 0, k = 0; + BOOLEAN found = false; + UCHAR *opChList = get_channelset_by_reg_class(pAd, op_class); + UCHAR opChListLen = get_channel_set_num(opChList); + + if (nonOpChnNum > 0) { + for (i = 0; i < opChListLen; i++) { + for (j = -0; j < pAd->ChannelListNum; j++) { + if (opChList[i] == pAd->ChannelList[j].Channel) + found = true; + } + + if (found == false) { + nonOpChnList[k] = opChList[i]; + k++; + } else + found = false; + } + } else + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("No Non Op Channel\n")); + + +} + +VOID MAP_Init( + IN PRTMP_ADAPTER pAd, + struct wifi_dev *wdev, + IN UCHAR wdev_type +) +{ + wdev->MAPCfg.DevOwnRole = MAP_CheckDevRole(pAd, wdev_type); + + wdev->MAPCfg.bUnAssocStaLinkMetricRptOpBss = TRUE;/*by default*/ + wdev->MAPCfg.bUnAssocStaLinkMetricRptNonOpBss = FALSE;/*by default*/ + pAd->ApCfg.SteerPolicy.steer_policy = 0; + pAd->ApCfg.SteerPolicy.cu_thr = 0; + pAd->ApCfg.SteerPolicy.rcpi_thr = 0; + NdisZeroMemory(wdev->MAPCfg.vendor_ie_buf, VENDOR_SPECIFIC_LEN); +} + +INT map_send_bh_sta_wps_done_event( + IN PRTMP_ADAPTER adapter, + IN PMAC_TABLE_ENTRY mac_entry, + IN BOOLEAN is_ap) +{ + struct wifi_dev *wdev; + struct wapp_event event; + BOOLEAN send_event = FALSE; + + if (mac_entry) { + +#ifdef APCLI_SUPPORT + PAPCLI_STRUCT apcli_entry; + struct wapp_bhsta_info *bsta_info = &event.data.bhsta_info; +#endif + + if (is_ap) { + if (IS_MAP_ENABLE(adapter) && (mac_entry->DevPeerRole & BIT(MAP_ROLE_BACKHAUL_STA))) + send_event = TRUE; + } +#ifdef APCLI_SUPPORT + else { + apcli_entry = &adapter->ApCfg.ApCliTab[mac_entry->func_tb_idx]; + if (IS_MAP_ENABLE(adapter) && + (mac_entry->DevPeerRole & + (BIT(MAP_ROLE_FRONTHAUL_BSS) | BIT(MAP_ROLE_BACKHAUL_BSS)))) + COPY_MAC_ADDR(bsta_info->connected_bssid, apcli_entry->wdev.bssid); + COPY_MAC_ADDR(bsta_info->mac_addr, apcli_entry->wdev.if_addr); + send_event = TRUE; + } +#endif + if (send_event) { + wdev = mac_entry->wdev; + event.event_id = MAP_BH_STA_WPS_DONE; + event.ifindex = RtmpOsGetNetIfIndex(wdev->if_dev); + wext_send_wapp_qry_rsp(adapter->net_dev, &event); + } + } + + return 0; +} + +void wapp_send_rssi_steer_event( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + char rssi_thrd) +{ + struct wifi_dev *wdev; + wdev_steer_sta *str_sta; + struct wapp_event event; + + /* send event to daemon */ + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_INFO, ("Trigger Rssi steering!\n")); + pEntry->isTriggerSteering = TRUE; + + wdev = pEntry->wdev; + event.event_id = MAP_TRIGGER_RSSI_STEER; + event.ifindex = RtmpOsGetNetIfIndex(wdev->if_dev); + str_sta = &event.data.str_sta; + COPY_MAC_ADDR(str_sta->mac_addr, pEntry->Addr); + wext_send_wapp_qry_rsp(pAd->net_dev, &event); +} + +VOID map_rssi_status_check( + IN PRTMP_ADAPTER pAd) +{ + int i = 0; + char rssi_thrd = 0; + + if (pAd->ApCfg.SteerPolicy.steer_policy == AGENT_INIT_RSSI_STEER_ALLOW || + pAd->ApCfg.SteerPolicy.steer_policy == AGENT_INIT_RSSI_STEER_MANDATE) { + rssi_thrd = (pAd->ApCfg.SteerPolicy.rcpi_thr >> 1) - 110; + + for (i = 0; VALID_UCAST_ENTRY_WCID(i); i++) { + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[i]; + + if (pEntry && IS_ENTRY_CLIENT(pEntry)) { + if (pEntry->RssiSample.AvgRssi[0] < rssi_thrd) { + pEntry->cur_rssi_status = BELOW_THRESHOLD; + + /* + * If sta's rssi is within RCPI tollenant boundary, + * ignore this rssi detection to avoid sending event + * to wapp constantly + */ + if (pEntry->isTriggerSteering == TRUE && + pEntry->pre_rssi_status == ABOVE_THRESHOLD && + pEntry->cur_rssi_status == BELOW_THRESHOLD && + abs(pEntry->RssiSample.AvgRssi[0] - rssi_thrd) <= RCPI_TOLLENACE) + return; + + wapp_send_rssi_steer_event(pAd, pEntry, rssi_thrd); + } else + pEntry->cur_rssi_status = ABOVE_THRESHOLD; + + if ((pEntry->pre_rssi_status == ABOVE_THRESHOLD) && + (pEntry->cur_rssi_status == BELOW_THRESHOLD) && + abs(pEntry->RssiSample.AvgRssi[0] - rssi_thrd) > RCPI_TOLLENACE) + pEntry->isTriggerSteering = FALSE; + + pEntry->pre_rssi_status = pEntry->cur_rssi_status; + } + } + } +} + +INT ReadMapParameterFromFile( + PRTMP_ADAPTER pAd, + RTMP_STRING *tmpbuf, + RTMP_STRING *pBuffer) +{ + INT i; + RTMP_STRING *macptr; + + return TRUE; +} + + +#ifdef A4_CONN +BOOLEAN map_a4_peer_enable( + IN PRTMP_ADAPTER adapter, + IN PMAC_TABLE_ENTRY entry, + IN BOOLEAN is_ap /*if i'm AP or not*/ +) +{ +#ifdef APCLI_SUPPORT + PAPCLI_STRUCT apcli_entry; +#endif + + if (is_ap) { + if (IS_MAP_ENABLE(adapter) && (entry->DevPeerRole & BIT(MAP_ROLE_BACKHAUL_STA))) + return a4_ap_peer_enable(adapter, entry, A4_TYPE_MAP); + } +#ifdef APCLI_SUPPORT + else { + apcli_entry = &adapter->ApCfg.ApCliTab[entry->func_tb_idx]; + if (IS_MAP_ENABLE(adapter) && + (entry->DevPeerRole & (BIT(MAP_ROLE_FRONTHAUL_BSS) | BIT(MAP_ROLE_BACKHAUL_BSS)))) { + return a4_apcli_peer_enable(adapter, + apcli_entry, + entry, + A4_TYPE_MAP); + } + } +#endif + + return FALSE; +} + +BOOLEAN map_a4_peer_disable( + IN PRTMP_ADAPTER adapter, + IN PMAC_TABLE_ENTRY entry, + IN BOOLEAN is_ap /*if i'm AP or not*/ +) +{ + if (is_ap) + return a4_ap_peer_disable(adapter, entry, A4_TYPE_MAP); +#ifdef APCLI_SUPPORT + else + return a4_apcli_peer_disable(adapter, &adapter->ApCfg.ApCliTab[entry->func_tb_idx], entry, A4_TYPE_MAP); +#else + return FALSE; +#endif +} + + +BOOLEAN map_a4_init( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN BOOLEAN is_ap +) +{ + return a4_interface_init(adapter, if_index, is_ap, A4_TYPE_MAP); +} + + +BOOLEAN map_a4_deinit( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN BOOLEAN is_ap +) +{ + return a4_interface_deinit(adapter, if_index, is_ap, A4_TYPE_MAP); +} + +BOOLEAN MapNotRequestedChannel(struct wifi_dev *wdev, unsigned char channel) +{ + int i = 0; + + if (wdev->MAPCfg.scan_bh_ssids.scan_channel_count == 0) + return FALSE; + for (i = 0; i < wdev->MAPCfg.scan_bh_ssids.scan_channel_count; i++) { + if (channel == wdev->MAPCfg.scan_bh_ssids.scan_channel_list[i]) + return FALSE; + } + return TRUE; +} + +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mbo.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mbo.c new file mode 100644 index 000000000..b686641c4 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mbo.c @@ -0,0 +1,1135 @@ +/**************************************************************************** +* Mediatek Inc. +* 5F., No.5, Taiyuan 1st St., Zhubei City, +* Hsinchu County 302, Taiwan, R.O.C. +* (c) Copyright 2014, Mediatek, Inc. +* +* All rights reserved. Mediatek's source code 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: + mbo.c + + Abstract: + MBO (AP) implementation. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + kyle 2016.8.10 Initial version: MBO IE API +*/ + +#ifdef MBO_SUPPORT +#include "rt_config.h" +#include "mbo.h" + +static MBO_ERR_CODE MboInsertAttrById( + struct wifi_dev *wdev, + PUINT8 pAttrTotalLen, + PUINT8 pAttrBuf, + UINT8 AttrId + ) +{ + P_MBO_CTRL pMboCtrl = NULL; + MBO_ATTR_STRUCT MboAttr; + PUINT8 pAttrBufOffset = (pAttrBuf + *pAttrTotalLen); + UINT16 OverflowChk = 0; + + if (wdev) { + pMboCtrl = &wdev->MboCtrl; + } else { + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - Mbss is NULL !!!!!\n", __func__)); + return MBO_INVALID_ARG; + } + + if (!VALID_MBO_ATTR_ID(AttrId)) { + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s %d - Invalid attr Id [%d] !!!!!\n", __func__, __LINE__, AttrId)); + return MBO_INVALID_ARG; + } + + NdisZeroMemory(&MboAttr, sizeof(MBO_ATTR_STRUCT)); + + switch (AttrId) { + case MBO_ATTR_AP_CAP_INDCATION: + MboAttr.AttrID = MBO_ATTR_AP_CAP_INDCATION; + MboAttr.AttrLen = 1; + MboAttr.AttrBody[0] = pMboCtrl->MboCapIndication; + break; + case MBO_ATTR_AP_ASSOC_DISALLOW: + MboAttr.AttrID = MBO_ATTR_AP_ASSOC_DISALLOW; + MboAttr.AttrLen = 1; + MboAttr.AttrBody[0] = pMboCtrl->AssocDisallowReason; + break; + case MBO_ATTR_AP_CDCP: + MboAttr.AttrID = MBO_ATTR_AP_CDCP; + MboAttr.AttrLen = 1; + MboAttr.AttrBody[0] = pMboCtrl->CellularPreference; + break; + case MBO_ATTR_AP_TRANS_REASON: + MboAttr.AttrID = MBO_ATTR_AP_TRANS_REASON; + MboAttr.AttrLen = 1; + MboAttr.AttrBody[0] = pMboCtrl->TransitionReason; + break; + case MBO_ATTR_AP_ASSOC_RETRY_DELAY: + MboAttr.AttrID = MBO_ATTR_AP_ASSOC_RETRY_DELAY; + MboAttr.AttrLen = 2; + NdisCopyMemory(&MboAttr.AttrBody[0], &pMboCtrl->ReAssocDelay, MboAttr.AttrLen); + break; + default: + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - UNKNOWN AttrId [%d] !!!!!\n", __func__, AttrId)); + } + + OverflowChk = *pAttrTotalLen + MboAttr.AttrLen + 2; + if (OverflowChk >= MBO_ATTR_MAX_LEN) { + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - AttrTotalLen %d Overflow, should be below %d !!!!!\n", + __func__, OverflowChk, MBO_ATTR_MAX_LEN)); + return MBO_UNEXP; + }/*else {*/ + /* safe, insert the attribute */ + NdisCopyMemory(pAttrBufOffset, &MboAttr, MboAttr.AttrLen+2); + *pAttrTotalLen += (MboAttr.AttrLen + 2); + /*} Fix Coding Style.*/ + + return MBO_SUCCESS; +} + + +static MBO_ERR_CODE MboCollectAttribute( + PRTMP_ADAPTER pAd, + struct wifi_dev *wdev, + PUINT8 pAttrLen, + PUINT8 pAttrBuf, + UINT8 FrameType + ) +{ + UINT8 ErrCode = MBO_SUCCESS; + P_MBO_CTRL pMboCtrl = NULL; + + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_INFO, + ("%s - collect attr for FrameType %d\n", __func__, FrameType)); + + if (!pAd || !wdev || !pAttrLen || !pAttrBuf) { + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - Invalid input argument !!!!!\n", __func__)); + return MBO_INVALID_ARG; + } + + pMboCtrl = &wdev->MboCtrl; + + switch (FrameType) { +#ifdef CONFIG_AP_SUPPORT + case MBO_FRAME_TYPE_BEACON: + case MBO_FRAME_TYPE_ASSOC_RSP: + case MBO_FRAME_TYPE_PROBE_RSP: + ErrCode = MboInsertAttrById(wdev, pAttrLen, pAttrBuf, MBO_ATTR_AP_CAP_INDCATION); + if (!MBO_AP_ALLOW_ASSOC(wdev)) + ErrCode = MboInsertAttrById(wdev, pAttrLen, pAttrBuf, MBO_ATTR_AP_ASSOC_DISALLOW); + break; +#endif /* CONFIG_AP_SUPPORT */ + + + default: + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - UNKNOWN FrameType %d !!!!!\n", __func__, FrameType)); + return MBO_UNEXP; + } + + return ErrCode; +} + +VOID MakeMboOceIE( + PRTMP_ADAPTER pAd, + struct wifi_dev *wdev, + PUINT8 pFrameBuf, + PULONG pFrameLen, + UINT8 FrameType + ) +{ + ULONG TempLen; + UINT8 IEId = IE_MBO_ELEMENT_ID; + UINT8 IELen = 0; + UINT8 AttrLen = 0; + UCHAR MBO_OCE_OUIBYTE[4] = {0x50, 0x6f, 0x9a, 0x16}; + PUCHAR pAttrBuf = NULL; + + if (wdev == NULL) + return; + + + MlmeAllocateMemory(pAd, &pAttrBuf); + + if (pAttrBuf == NULL) + return; + + MboCollectAttribute(pAd, wdev, &AttrLen, pAttrBuf, FrameType); + + IELen = 4 + AttrLen; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &IEId, + 1, &IELen, + 4, MBO_OCE_OUIBYTE, + AttrLen, pAttrBuf, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + MlmeFreeMemory(pAd, pAttrBuf); + /*return; Coding style Fix*/ +} + +MBO_ERR_CODE ReadMboParameterFromFile( + PRTMP_ADAPTER pAd, + RTMP_STRING *tmpbuf, + RTMP_STRING *pBuffer) +{ + INT loop; + RTMP_STRING *macptr; + + /* MboSupport */ + if (RTMPGetKeyParameter("MboSupport", tmpbuf, 128, pBuffer, TRUE)) { +#ifdef CONFIG_AP_SUPPORT + for (loop = 0, macptr = rstrtok(tmpbuf, ";"); + (macptr && loop < MAX_MBSSID_NUM(pAd)); + macptr = rstrtok(NULL, ";"), loop++) { + UINT8 Enable; + + Enable = (UINT8)simple_strtol(macptr, 0, 10); + pAd->ApCfg.MBSSID[loop].wdev.MboCtrl.bMboEnable = + (Enable) ? TRUE : FALSE; + pAd->ApCfg.MBSSID[loop].wdev.MboCtrl.MboCapIndication = + (Enable) ? MBO_AP_CAP_CELLULAR_AWARE : MBO_AP_CAP_NOT_SUPPORT; + + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s::(bMboEnable[%d]=%d, MboCapIndication = 0x%02x)\n", __func__, loop, + pAd->ApCfg.MBSSID[loop].wdev.MboCtrl.bMboEnable, + pAd->ApCfg.MBSSID[loop].wdev.MboCtrl.MboCapIndication)); + + } +#endif /*CONFIG_AP_SUPPORT*/ + + + } + return MBO_SUCCESS; +} + + +MBO_ERR_CODE MboInit( + PRTMP_ADAPTER pAd) +{ + INT loop; + P_MBO_CTRL pMboCtrl = NULL; + +#ifdef CONFIG_AP_SUPPORT + for (loop = 0; loop < MAX_MBSSID_NUM(pAd); loop++) { + pMboCtrl = &pAd->ApCfg.MBSSID[loop].wdev.MboCtrl; + NdisZeroMemory(pMboCtrl, sizeof(MBO_CTRL)); + } +#endif /* CONFIG_AP_SUPPORT */ + + + return MBO_SUCCESS; +} + +#ifdef CONFIG_AP_SUPPORT +static VOID WextMboSendNeighborReportToDaemonEvent( + PNET_DEV net_dev, + P_DAEMON_EVENT_NR_LIST NeighborRepList, + UINT16 report_buf_len) +{ + P_DAEMON_NR_MSG pNRMsg; + UINT16 buflen = 0; + char *buf; + + buflen = sizeof(DAEMON_NR_MSG); + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + pNRMsg = (P_DAEMON_NR_MSG)buf; + + NdisCopyMemory(&pNRMsg->evt_nr_list, NeighborRepList, report_buf_len); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - sizeof %u report_buf_len %u buflen %u\n", + __func__, (UINT32)sizeof(DAEMON_EVENT_NR_LIST), report_buf_len, buflen)); + RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM, + OID_NEIGHBOR_REPORT, NULL, (PUCHAR)buf, buflen); + + os_free_mem(NULL, buf); +} + +static VOID MboUpdateNRElement( + RTMP_ADAPTER *pAd, + struct wifi_dev *pWdev, + BSS_ENTRY *pBssEntry, + DAEMON_NEIGHBOR_REP_INFO *pNeighborEntry) +{ + RRM_BSSID_INFO BssidInfo; + BOOLEAN bInsertMyOwnBss = (pBssEntry == NULL)?TRUE:FALSE; + BSS_ENTRY myOwnBss; + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[pWdev->func_idx]; + + if (bInsertMyOwnBss) { + UINT8 CondensedPhyType = 0; + + COPY_MAC_ADDR(pNeighborEntry->Bssid, pWdev->bssid); + pBssEntry = &myOwnBss; + NdisZeroMemory(pBssEntry, sizeof(BSS_ENTRY)); + + pBssEntry->CapabilityInfo = pMbss->CapabilityInfo; + + BssidInfo.word = 0; + BssidInfo.field.APReachAble = 3; + BssidInfo.field.Security = 1; + BssidInfo.field.KeyScope = 0; + BssidInfo.field.SepctrumMng = (pBssEntry->CapabilityInfo & (1 << 8)) ? 1:0; + BssidInfo.field.Qos = (pBssEntry->CapabilityInfo & (1 << 9)) ? 1:0; + BssidInfo.field.APSD = (pBssEntry->CapabilityInfo & (1 << 11)) ? 1:0; + BssidInfo.field.RRM = (pBssEntry->CapabilityInfo & RRM_CAP_BIT) ? 1:0; + BssidInfo.field.DelayBlockAck = (pBssEntry->CapabilityInfo & (1 << 14)) ? 1:0; + BssidInfo.field.ImmediateBA = (pBssEntry->CapabilityInfo & (1 << 15)) ? 1:0; +#ifdef DOT11R_FT_SUPPORT + BssidInfo.field.MobilityDomain = (pMbss->FtCfg.FtCapFlag.Dot11rFtEnable) ? 1:0; +#endif /* DOT11R_FT_SUPPORT */ + BssidInfo.field.HT = WMODE_CAP_N(pWdev->PhyMode) ? 1:0; +#ifdef DOT11_VHT_AC + BssidInfo.field.VHT = WMODE_CAP_AC(pWdev->PhyMode) ? 1:0; +#endif /* DOT11_VHT_AC */ + + if (pWdev->channel > 14) { + if (BssidInfo.field.HT) { +#ifdef DOT11_VHT_AC + if (BssidInfo.field.VHT) + CondensedPhyType = 9; + else +#endif /* DOT11_VHT_AC */ + CondensedPhyType = 7; + } else { + CondensedPhyType = 4; + } + } else { + if (BssidInfo.field.HT) + CondensedPhyType = 7; + else if (ERP_IS_NON_ERP_PRESENT(pAd->ApCfg.ErpIeContent)) + CondensedPhyType = 6; + else if (pBssEntry->SupRateLen > 4) + CondensedPhyType = 4; + } + + pNeighborEntry->BssidInfo = BssidInfo.word; + /*pNeighborEntry->RegulatoryClass = get_regulatory_class(pAd, pWdev->channel, + pWdev->PhyMode, pWdev); + */ + pNeighborEntry->RegulatoryClass = get_regulatory_class(pAd, pWdev->channel); + pNeighborEntry->ChNum = pWdev->channel; + pNeighborEntry->PhyType = CondensedPhyType; + } else { + COPY_MAC_ADDR(pNeighborEntry->Bssid, pBssEntry->Bssid); + /* update Neighbor Report Information Elements */ + BssidInfo.word = 0; + BssidInfo.field.APReachAble = 3; + BssidInfo.field.Security = 1; /* default value, will be updated in daemon */ + BssidInfo.field.KeyScope = 0; + BssidInfo.field.SepctrumMng = (pBssEntry->CapabilityInfo & (1 << 8)) ? 1:0; + BssidInfo.field.Qos = (pBssEntry->CapabilityInfo & (1 << 9)) ? 1:0; + BssidInfo.field.APSD = (pBssEntry->CapabilityInfo & (1 << 11)) ? 1:0; + BssidInfo.field.RRM = (pBssEntry->CapabilityInfo & RRM_CAP_BIT) ? 1:0; + BssidInfo.field.DelayBlockAck = (pBssEntry->CapabilityInfo & (1 << 14)) ? 1:0; + BssidInfo.field.ImmediateBA = (pBssEntry->CapabilityInfo & (1 << 15)) ? 1:0; + BssidInfo.field.MobilityDomain = (pBssEntry->bHasMDIE) ? 1:0; + BssidInfo.field.HT = (pBssEntry->HtCapabilityLen != 0) ? 1:0; +#ifdef DOT11_VHT_AC + BssidInfo.field.VHT = (pBssEntry->vht_cap_len != 0) ? 1:0; +#endif /* DOT11_VHT_AC */ + + if (pBssEntry->Channel > 14) { + if (pBssEntry->HtCapabilityLen != 0) { +#ifdef DOT11_VHT_AC + if (pBssEntry->vht_cap_len != 0) + pBssEntry->CondensedPhyType = 9; + else +#endif /* DOT11_VHT_AC */ + pBssEntry->CondensedPhyType = 7; + } else { + pBssEntry->CondensedPhyType = 4; + } + } else { + if (pBssEntry->HtCapabilityLen != 0) + pBssEntry->CondensedPhyType = 7; + else if (ERP_IS_NON_ERP_PRESENT(pBssEntry->Erp)) + pBssEntry->CondensedPhyType = 6; + else if (pBssEntry->SupRateLen > 4) + pBssEntry->CondensedPhyType = 4; + } + + pNeighborEntry->BssidInfo = BssidInfo.word; + /*pNeighborEntry->RegulatoryClass = get_regulatory_class(pAd, pBssEntry->Channel, + pWdev->PhyMode, pWdev); + */ + pNeighborEntry->RegulatoryClass = get_regulatory_class(pAd, pBssEntry->Channel); + pNeighborEntry->ChNum = pBssEntry->Channel; + pNeighborEntry->PhyType = pBssEntry->CondensedPhyType; + + /*pNeighborEntry->akm = pBssEntry->AKMMap;*/ + pNeighborEntry->akm = pBssEntry->AuthMode; + /*pNeighborEntry->cipher = pBssEntry->PairwiseCipher;*/ + pNeighborEntry->cipher = pBssEntry->AuthMode; + } + + + /* add BSS Transition Candidate Preference subelement - [Subelement ID=3][length=1][preference=20] */ + pNeighborEntry->CandidatePrefSubID = MBO_RRM_SUBID_BSS_TRANSITION_CANDIDATE_PREFERENCE; + pNeighborEntry->CandidatePrefSubLen = 1; + if (bInsertMyOwnBss && !MBO_AP_ALLOW_ASSOC(pWdev)) + pNeighborEntry->CandidatePref = 0; +#ifdef DOT11R_FT_SUPPORT + else if (pMbss->FtCfg.FtCapFlag.Dot11rFtEnable == TRUE) { + /* YF_NR */ + pNeighborEntry->CandidatePref = MBO_AP_DEFAULT_CAND_PREF; + + if (bInsertMyOwnBss) + pNeighborEntry->CandidatePref = 0; + else if (pBssEntry->bHasMDIE && + NdisCmpMemory(pBssEntry->FT_MDIE.MdId, pMbss->FtCfg.FtMdId, FT_MDID_LEN) == 0) { + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_FT, DBG_LVL_OFF, + ("AP(%02x:%02x:%02x:%02x:%02x:%02x) same in FT Domain\n", + PRINT_MAC(pNeighborEntry->Bssid))); + pNeighborEntry->CandidatePref = 255; + } + } +#endif /* DOT11R_FT_SUPPORT */ + else + pNeighborEntry->CandidatePref = MBO_AP_DEFAULT_CAND_PREF; +} + +/*format : iwpriv [interface] set mbo_nr=[append]-[nr_entry_num] + sample : iwpriv ra0 set mbo_nr=0-12 + ==> renew list,not append,indicate 12 entries +*/ +INT SetMboNRIndicateProc( + PRTMP_ADAPTER pAd, + RTMP_STRING *arg) +{ + UINT8 i = 0, input = 0, ReportNum = 0; + RTMP_STRING *macptr; + BOOLEAN AppendMode = FALSE; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + /*struct wifi_dev *pWdev = &pAd->ApCfg.MBSSID[pObj->ioctl_if].wdev;*/ + struct wifi_dev *pWdev = get_wdev_by_ioctl_idx_and_iftype(pAd, pObj->ioctl_if, pObj->ioctl_if_type); + + for (i = 0, macptr = rstrtok(arg, "-"); macptr; macptr = rstrtok(NULL, "-"), i++) { + if (i == 0) + input = (UINT8) simple_strtol(macptr, 0, 10); + else if (i == 1) + ReportNum = (UINT8) simple_strtol(macptr, 0, 10); + else + break; + } + + AppendMode = (input)?TRUE:FALSE; + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - AppendMode %d , reportNum %d\n", + __func__, AppendMode, ReportNum)); + + if (ReportNum == 0) + ReportNum = 10; + + MboIndicateNeighborReportToDaemon(pAd, pWdev, AppendMode, ReportNum); + + return TRUE; +} + +INT MboIndicateNeighborReportToDaemon( + PRTMP_ADAPTER pAd, + struct wifi_dev *pWdev, + BOOLEAN AppendMode, + UINT8 ReportNum) +{ +#ifdef DOT11K_RRM_SUPPORT +#ifdef AP_SCAN_SUPPORT + UINT32 loop = 0; + DAEMON_EVENT_NR_LIST NeighborRepList; + BOOLEAN bNewlist = !AppendMode; + + DAEMON_NEIGHBOR_REP_INFO *pNeighborEntry = NULL; + UINT8 TotalReportNum = 0; + /*BSS_TABLE *ScanTab = get_scan_tab_by_wdev(pAd, pWdev);*/ + BSS_TABLE *ScanTab = &pAd->ScanTab; + + if (ScanTab == NULL) + return FALSE; + + NdisZeroMemory(&NeighborRepList, sizeof(DAEMON_EVENT_NR_LIST)); + + + if (ScanTab->BssNr > 0) { + + BssTableSortByRssi(ScanTab, FALSE); + + TotalReportNum = ReportNum < ScanTab->BssNr ? + ReportNum : ScanTab->BssNr; + NeighborRepList.TotalNum = TotalReportNum; + + /* insert our own bss info into NR list first */ + pNeighborEntry = &NeighborRepList.EvtNRInfo[NeighborRepList.CurrNum++]; + + MboUpdateNRElement(pAd, pWdev, NULL, pNeighborEntry); + + for (loop = 0; loop < TotalReportNum - 1; loop++) {/* minus our own NR entry */ + BSS_ENTRY *pBssEntry = &ScanTab->BssEntry[loop]; + DAEMON_NEIGHBOR_REP_INFO *pNeighborEntry = &NeighborRepList.EvtNRInfo[NeighborRepList.CurrNum]; + + NeighborRepList.CurrNum++; + + MboUpdateNRElement(pAd, pWdev, pBssEntry, pNeighborEntry); + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s - append NO. %u len %u BSSID %02X:%02X:%02X:%02X:%02X:%02X Chnum %d BssidInfo %X\n" + "PhyType %x RegulatoryClass %x Privacy %d SSID %s\n", + __func__, loop, (UINT32)sizeof(DAEMON_NEIGHBOR_REP_INFO), + PRINT_MAC(pNeighborEntry->Bssid), + pNeighborEntry->ChNum, pNeighborEntry->BssidInfo, + pNeighborEntry->PhyType, pNeighborEntry->RegulatoryClass, + pBssEntry->Privacy, pBssEntry->Ssid)); + hex_dump("neighbor_entry", (UCHAR *)pNeighborEntry, sizeof(DAEMON_NEIGHBOR_REP_INFO)); + + if ((NeighborRepList.CurrNum % PER_EVENT_LIST_MAX_NUM == 0) + && (NeighborRepList.CurrNum != 0) + ) { + NeighborRepList.Newlist = bNewlist; + bNewlist = FALSE; + /* indicate sublist to daemon */ + WextMboSendNeighborReportToDaemonEvent(pAd->net_dev, + &NeighborRepList, + sizeof(DAEMON_EVENT_NR_LIST)); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("\033[1;32m %s, %u .Newlist %d .TotalNum %d .CurrNum %d\033[0m\n", + __func__, __LINE__, NeighborRepList.Newlist, NeighborRepList.TotalNum, + NeighborRepList.CurrNum)); + NdisZeroMemory(&NeighborRepList, sizeof(DAEMON_EVENT_NR_LIST)); + NeighborRepList.TotalNum = TotalReportNum; + } + + } + + if (NeighborRepList.CurrNum != 0) { + NeighborRepList.Newlist = bNewlist; + bNewlist = FALSE; + /* indicate the last sublist to daemon */ + WextMboSendNeighborReportToDaemonEvent(pAd->net_dev, + &NeighborRepList, + sizeof(DAEMON_EVENT_NR_LIST)); + + NdisZeroMemory(&NeighborRepList, sizeof(DAEMON_EVENT_NR_LIST)); + } + } else { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - nothing to indicate, pAd->ScanTab.BssNr = %d\n", + __func__, ScanTab->BssNr)); + NdisZeroMemory(&NeighborRepList, sizeof(DAEMON_EVENT_NR_LIST)); + TotalReportNum = 1; + NeighborRepList.TotalNum = TotalReportNum; + /*Insert our own bss info into NR list first*/ + pNeighborEntry = &NeighborRepList.EvtNRInfo[NeighborRepList.CurrNum++]; + MboUpdateNRElement(pAd, pWdev, NULL, pNeighborEntry); + NeighborRepList.Newlist = TRUE; + /*NeighborRepList.TotalNum = 0;*/ + + /* indicate zero to daemon */ + /*WextMboSendNeighborReportToDaemonEvent(pAd->net_dev, + &NeighborRepList, + sizeof(DAEMON_EVENT_NR_LIST)); + */ + /* indicate our own bss to daemon */ + WextMboSendNeighborReportToDaemonEvent(pAd->net_dev, + &NeighborRepList, + sizeof(DAEMON_EVENT_NR_LIST)); + } + +#endif /* AP_SCAN_SUPPORT */ +#endif /* DOT11K_RRM_SUPPORT */ + + return TRUE; +} + +INT MBO_MsgHandle( + IN PRTMP_ADAPTER pAd, + UINT32 Param, + UINT32 Value) +{ + + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UCHAR APIndex = pObj->ioctl_if; + P_MBO_CTRL pMboCtrl; + + pMboCtrl = &pAd->ApCfg.MBSSID[APIndex].wdev.MboCtrl; + + switch (Param) { + case PARAM_MBO_AP_ASSOC_DISALLOW: + pMboCtrl->AssocDisallowReason = Value; + break; + case PARAM_MBO_AP_CAP: + pMboCtrl->MboCapIndication = Value; + break; + case PARAM_MBO_AP_CDCP: + pMboCtrl->CellularPreference = Value; + break; + case PARAM_MBO_AP_BSS_TERM: + MboBssTermStart(pAd, Value); + break; + default: + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("Unknown Parameter:%d\n", Param)); + break; + } + return 0; +} + +VOID MboWaitAllStaGone(PRTMP_ADAPTER pAd, INT apidx) +{ + UINT i = 0, j = 0; + PMAC_TABLE_ENTRY pEntry; + + for (j = 0; j < 10; j++) { + BOOLEAN bSTAIsKeep = FALSE; + + for (i = 0; VALID_UCAST_ENTRY_WCID(i); i++) { + pEntry = &pAd->MacTab.Content[i]; + if (pEntry && IS_ENTRY_CLIENT(pEntry) + && pEntry->func_tb_idx == apidx && pEntry->IsKeep) { + bSTAIsKeep = TRUE; + break; + } + } + + if (bSTAIsKeep) + RtmpOsMsDelay(50); + else + return; /* All Sta Gone , return */ + } + + /* exceed 500 ms */ + /*return; coding style fix*/ +} + +#endif /* CONFIG_AP_SUPPORT */ + +static VOID WextMboSendStaInfoToDaemonEvent( + PNET_DEV pNetDev, + P_MBO_STA_CH_PREF_CDC_INFO pStaInfo, + MBO_MSG_TYPE MsgType, + UINT16 ReportBufLen) +{ + P_MBO_MSG pMboMsg; + UINT16 buflen = 0; + char *buf; + + buflen = sizeof(MBO_MSG); + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + pMboMsg = (P_MBO_MSG)buf; + pMboMsg->ifindex = RtmpOsGetNetIfIndex(pNetDev); + pMboMsg->MboMsgLen = ReportBufLen; + pMboMsg->MboMsgType = MsgType; + + NdisCopyMemory(&pMboMsg->MboMsgBody.MboEvtStaInfo, pStaInfo, ReportBufLen); + + if (MsgType == MBO_MSG_CDC_UPDATE) + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s, indicate STA CDC %d\n", + __func__, pMboMsg->MboMsgBody.MboEvtStaInfo.cdc)); + + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - sizeof %u report_buf_len %d buflen %u msg_type %s\n", + __func__, (UINT32)sizeof(MBO_STA_CH_PREF_CDC_INFO), ReportBufLen, + buflen, MboMsgTypeToString(MsgType))); + RtmpOSWrielessEventSend(pNetDev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_MBO_MSG, NULL, (PUCHAR)buf, buflen); + + os_free_mem(NULL, buf); +} + +INT MboIndicateStaInfoToDaemon( + PRTMP_ADAPTER pAd, + P_MBO_STA_CH_PREF_CDC_INFO pStaInfo, + MBO_MSG_TYPE MsgType) +{ + /* mac table lookup & update sta's akm/cipher here */ + PMAC_TABLE_ENTRY pEntry = MacTableLookup(pAd, pStaInfo->mac_addr); + + if (pEntry != NULL) { + pStaInfo->akm = pEntry->AuthMode;/*pEntry->SecConfig.AKMMap;*/ + pStaInfo->cipher = pEntry->AuthMode;/*pEntry->SecConfig.PairwiseCipher;*/ + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_WARN, + ("\033[1;33m %s, %u pEntry->wcid %d pStaInfo->akm 0x%x pStaInfo->cipher 0x%x\033[0m\n" + , __func__, __LINE__, pEntry->wcid, pStaInfo->akm, pStaInfo->cipher)); + } else { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s [ERROR] can't find sta entry!!\n", + __func__)); + return FALSE; + } + + /* send wext event */ + WextMboSendStaInfoToDaemonEvent(pAd->net_dev, pStaInfo, MsgType, sizeof(MBO_STA_CH_PREF_CDC_INFO)); + + return TRUE; +} + +VOID MboParseStaNPCElement( + PRTMP_ADAPTER pAd, + struct wifi_dev *pWdev, + UCHAR *PktContent, + UINT8 ElementLen, + P_MBO_STA_CH_PREF_CDC_INFO pMboStaCHInfo, + MBO_FRAME_TYPE MboFrameType) +{ + /* PktContent starts at Operating Class Field */ + CHAR NpclListLen = 0; + BOOLEAN bEmptyNPC = FALSE; + + if (MboFrameType == MBO_FRAME_TYPE_WNM_REQ) { + bEmptyNPC = (ElementLen <= 4)?TRUE:FALSE; /* contains only OUI == EmptyNPC */ + /* OUI 4 bytes , Operating Class 1 byte, Pref 1 byte, Reason Code 1 byte */ + NpclListLen = (ElementLen > 7)?ElementLen - 7:0; + } else if (MboFrameType == MBO_FRAME_TYPE_ASSOC_REQ) { + bEmptyNPC = (ElementLen == 0)?TRUE:FALSE; /* no op class == EmptyNPC */ + /* Operating Class 1 byte, Pref 1 byte, Reason Code 1 byte */ + NpclListLen = (ElementLen > 3)?ElementLen - 3:0; + } else { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s, UNKNOWN Frame Type %d , quit.\n", __func__, MboFrameType)); + return; + } + + + if (bEmptyNPC) { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s, ElementLen %d indicates no NPC list, All OP-Class CH good.\n" + , __func__, ElementLen)); + + pMboStaCHInfo->npc_num = 255; + return; + } else { + UINT8 OperatingClass = *PktContent; + UCHAR *ChListStart = PktContent + 1; + UINT8 Preference = *(ChListStart + NpclListLen); + UINT8 ReasonCode = *(ChListStart + NpclListLen + 1); + UCHAR *OpChList = get_channelset_by_reg_class(pAd, OperatingClass); + UCHAR OpChListLen = get_channel_set_num(OpChList); + UINT8 NpcList[MAX_NOT_PREFER_CH_NUM] = {0}; + UINT8 i = 0, j = 0; + + /* to prevent NpclListLen overflow, should not happen */ + if (NpclListLen > MAX_NOT_PREFER_CH_NUM) + NpclListLen = MAX_NOT_PREFER_CH_NUM; + + /* to prevent pMboStaCHInfo->npc stack overflow */ + if (pMboStaCHInfo->npc_num + OpChListLen >= MBO_NPC_MAX_LEN) { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s, cur_npc_num %d, OpChListLen %d >= MBO_NPC_MAX_LEN %d, return due to overflow.\n", + __func__, pMboStaCHInfo->npc_num, OpChListLen, MBO_NPC_MAX_LEN)); + return; + } + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s, NpclListLen %d, OperClass %d, Preference%d, ReaCode %d OpChListLen %d npc_num %d\n", + __func__, NpclListLen, OperatingClass, Preference, ReasonCode, + OpChListLen, pMboStaCHInfo->npc_num)); + + if (OpChListLen == 0) + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s, Got OpChListLen %d can't find OperatingClass 0x%x ERROR!!!!!!!!!!!!!!!!\n", + __func__, OpChListLen, OperatingClass)); + + for (i = 0; i < NpclListLen; i++) { + NpcList[i] = *(ChListStart + i); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("NpcList[%d] = %d\n", i, NpcList[i])); + } + + /* append channel list to pMboStaCHInfo */ + for (j = 0; j < OpChListLen; j++) { + BOOLEAN bIsNpc = FALSE; + UINT8 offset = pMboStaCHInfo->npc_num + j; + P_STA_CH_PREF pNpc = &pMboStaCHInfo->npc[offset]; + + for (i = 0; i < NpclListLen; i++) { + if (OpChList[j] == NpcList[i]) + bIsNpc = TRUE; + } + + pNpc->pref = (bIsNpc)?Preference:255; + pNpc->ch = OpChList[j]; + pNpc->reason_code = ReasonCode; + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("++ final NPC struct [%d] : ch %d , pref %d\n", offset, pNpc->ch, pNpc->pref)); + } + + pMboStaCHInfo->npc_num += OpChListLen; + } + +} + +VOID MboParseStaMboIE(PRTMP_ADAPTER pAd, struct wifi_dev *pWdev, struct _MAC_TABLE_ENTRY *pEntry, + UCHAR *buf, UCHAR len, MBO_FRAME_TYPE MboFrameType) +{ + UCHAR *pos = NULL; + UCHAR ParsedLen = 0; + MBO_STA_CH_PREF_CDC_INFO *pMboStaInfoNPC = NULL; + MBO_STA_CH_PREF_CDC_INFO *pMboStaInfoCDC = NULL; + PEID_STRUCT eid_ptr; + + if (!pEntry) { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - pEntry is NULL!!!\n", __func__)); + return; + } + + pMboStaInfoCDC = &pEntry->MboStaInfoCDC; + pMboStaInfoNPC = &pEntry->MboStaInfoNPC; + pEntry->bIndicateCDC = FALSE; + pEntry->bIndicateNPC = FALSE; + + NdisZeroMemory(pMboStaInfoNPC, sizeof(MBO_STA_CH_PREF_CDC_INFO)); + NdisZeroMemory(pMboStaInfoCDC, sizeof(MBO_STA_CH_PREF_CDC_INFO)); + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s - Got MBO IE len [%d]\n", __func__, len)); + + + pos = buf; + + /* skip OUI 4 bytes */ + pos += 4; + ParsedLen += 4; + + eid_ptr = (PEID_STRUCT)pos; + + /*in empty NPC case , MBO IE contains only OUI and NPC eid 2 len 0. + so ParsedLen+2 == len + */ + while ((ParsedLen+2) <= len) { + switch (eid_ptr->Eid) { + case MBO_ATTR_STA_CDC: + COPY_MAC_ADDR(pMboStaInfoCDC->mac_addr, pEntry->Addr); + pMboStaInfoCDC->cdc = eid_ptr->Octet[0]; + pMboStaInfoCDC->npc_num = 0; + pEntry->bIndicateCDC = TRUE; + break; + case MBO_ATTR_STA_NOT_PREFER_CH_REP: + COPY_MAC_ADDR(pMboStaInfoNPC->mac_addr, pEntry->Addr); + MboParseStaNPCElement(pAd, pWdev, &eid_ptr->Octet[0], eid_ptr->Len, + pMboStaInfoNPC, MboFrameType); + pEntry->bIndicateNPC = TRUE; + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s, %u npc_num %d mac_addr %02X:%02X:%02X:%02X:%02X:%02X bIndicateNPC %d\n" + , __func__, __LINE__, pMboStaInfoNPC->npc_num, PRINT_MAC(pMboStaInfoNPC->mac_addr), + pEntry->bIndicateNPC)); + break; + default: + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - ignored MBO_ATTR [%d]\n", __func__, eid_ptr->Eid)); + } + + ParsedLen += (2 + eid_ptr->Len); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s, %u eid_ptr->Len %d ParsedLen %d IE len %d Break %d\n" + , __func__, __LINE__, eid_ptr->Len, ParsedLen, len, ((ParsedLen+2) < len))); + eid_ptr = (PEID_STRUCT)((UCHAR *)eid_ptr + 2 + eid_ptr->Len); + } + +} + +VOID MboIndicateStaBssidInfo(PRTMP_ADAPTER pAd, struct wifi_dev *pWdev, UCHAR *mac_addr) +{ + MBO_STA_CH_PREF_CDC_INFO MboStaInfo; + + NdisZeroMemory(&MboStaInfo, sizeof(MBO_STA_CH_PREF_CDC_INFO)); + COPY_MAC_ADDR(&MboStaInfo.mac_addr, mac_addr); + COPY_MAC_ADDR(&MboStaInfo.bssid, pWdev->bssid); + MboIndicateStaInfoToDaemon(pAd, &MboStaInfo, MBO_MSG_BSSID_UPDATE); +} + +static VOID WextMboSendStaDisassocToDaemonEvent( + PNET_DEV pNetDev, + P_MBO_EVENT_STA_DISASSOC pStaDisassocInfo, + MBO_MSG_TYPE MsgType, + UINT16 ReportBufLen) +{ + P_MBO_MSG pMboMsg; + UINT16 buflen = 0; + char *buf; + + buflen = sizeof(MBO_MSG); + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + pMboMsg = (P_MBO_MSG)buf; + pMboMsg->ifindex = RtmpOsGetNetIfIndex(pNetDev); + pMboMsg->MboMsgLen = ReportBufLen; + pMboMsg->MboMsgType = MsgType; + + if (MsgType != MBO_MSG_AP_TERMINATION) + NdisCopyMemory(&pMboMsg->MboMsgBody.MboEvtStaDisassoc, pStaDisassocInfo, ReportBufLen); + + if (pStaDisassocInfo && pStaDisassocInfo->mac_addr) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s [%02x:%02x:%02x:%02x:%02x:%02x] sizeof %u report_buf_len %d buflen %d msg_type %s\n", + __func__, PRINT_MAC(pStaDisassocInfo->mac_addr), (UINT32)sizeof(MBO_EVENT_STA_DISASSOC), + ReportBufLen, buflen, MboMsgTypeToString(MsgType))); + + RtmpOSWrielessEventSend(pNetDev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_MBO_MSG, NULL, (PUCHAR)buf, buflen); + } + os_free_mem(NULL, buf); +} + +INT MboIndicateStaDisassocToDaemon( + PRTMP_ADAPTER pAd, + P_MBO_EVENT_STA_DISASSOC pStaDisassocInfo, + MBO_MSG_TYPE MsgType) +{ + WextMboSendStaDisassocToDaemonEvent(pAd->net_dev, pStaDisassocInfo, MsgType, sizeof(MBO_EVENT_STA_DISASSOC)); + + return TRUE; +} + +static VOID WextMboSendBssTermToDaemonEvent( + PNET_DEV pNetDev, + P_MBO_EVENT_BSS_TERM pBssTermTsf, + MBO_MSG_TYPE MsgType, + UINT16 ReportBufLen) +{ + P_MBO_MSG pMboMsg; + UINT16 buflen = 0; + char *buf; + + if (pBssTermTsf == NULL) + return; + + buflen = sizeof(MBO_MSG); + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + pMboMsg = (P_MBO_MSG)buf; + pMboMsg->ifindex = RtmpOsGetNetIfIndex(pNetDev); + pMboMsg->MboMsgLen = ReportBufLen; + pMboMsg->MboMsgType = MsgType; + + NdisCopyMemory(&pMboMsg->MboMsgBody.MboEvtBssTermTsf, pBssTermTsf, ReportBufLen); + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s - sizeof %u report_buf_len %d buflen %d msg_type %s\n", + __func__, (UINT32)sizeof(MBO_EVENT_BSS_TERM), ReportBufLen, + buflen, MboMsgTypeToString(MsgType))); + + RtmpOSWrielessEventSend(pNetDev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_MBO_MSG, NULL, (PUCHAR)buf, buflen); + os_free_mem(NULL, buf); +} + +RTMP_STRING *MboMsgTypeToString(MBO_MSG_TYPE MsgType) +{ + if (MsgType == MBO_MSG_NEIGHBOR_REPORT) + return "MBO_MSG_NEIGHBOR_REPORT"; + else if (MsgType == MBO_MSG_STA_PREF_UPDATE) + return "MBO_MSG_STA_PREF_UPDATE"; + else if (MsgType == MBO_MSG_CDC_UPDATE) + return "MBO_MSG_CDC_UPDATE"; + else if (MsgType == MBO_MSG_STA_STEERING) + return "MBO_MSG_STA_STEERING"; + else if (MsgType == MBO_MSG_DISASSOC_STA) + return "MBO_MSG_DISASSOC_STA"; + else if (MsgType == MBO_MSG_AP_TERMINATION) + return "MBO_MSG_AP_TERMINATION"; + else if (MsgType == MBO_MSG_BSSID_UPDATE) + return "MBO_MSG_BSSID_UPDATE"; + else if (MsgType == MBO_MSG_REMOVE_STA) + return "MBO_MSG_REMOVE_STA"; + else + return "UNKNOWN MSG TYPE"; + +} + + +RTMP_STRING *MboAttrValueToString(UINT8 AttrID, UINT8 AttrValue) +{ + switch (AttrID) { + case MBO_ATTR_AP_CAP_INDCATION: + if (AttrValue == MBO_AP_CAP_NOT_SUPPORT) + return "MBO_AP_CAP_NOT_SUPPORT"; + else if (AttrValue == MBO_AP_CAP_CELLULAR_AWARE) + return "MBO_AP_CAP_CELLULAR_AWARE"; + else + return "UNKNOWN ATTR VALUE..."; + break; + case MBO_ATTR_AP_ASSOC_DISALLOW: + if (AttrValue == MBO_AP_DISALLOW_REASON_RESERVED) + return "MBO_AP_ALLOW_ASSOC"; + else if (AttrValue == MBO_AP_DISALLOW_REASON_UNSPECIFIED) + return "MBO_AP_DISALLOW_REASON_UNSPECIFIED"; + else if (AttrValue == MBO_AP_DISALLOW_MAX_STA_NUM_REACHED) + return "MBO_AP_DISALLOW_MAX_STA_NUM_REACHED"; + else if (AttrValue == MBO_AP_DISALLOW_AIR_OVERLOADED) + return "MBO_AP_DISALLOW_AIR_OVERLOADED"; + else if (AttrValue == MBO_AP_DISALLOW_AUTH_SERVER_OVERLOADED) + return "MBO_AP_DISALLOW_AUTH_SERVER_OVERLOADED"; + else if (AttrValue == MBO_AP_DISALLOW_RSSI_TOO_LOW) + return "MBO_AP_DISALLOW_RSSI_TOO_LOW"; + else + return "UNKNOWN ATTR VALUE..."; + break; + case MBO_ATTR_AP_CDCP: + if (AttrValue == MBO_AP_CDCP_FORBID_STA_USE_CDC) + return "MBO_AP_CDCP_FORBID_STA_USE_CDC"; + else if (AttrValue == MBO_AP_CDCP_PREFER_STA_NOT_USE_CDC) + return "MBO_AP_CDCP_PREFER_STA_NOT_USE_CDC"; + else if (AttrValue == MBO_AP_CDCP_PREFER_STA_USE_CDC) + return "MBO_AP_CDCP_PREFER_STA_USE_CDC"; + else + return "UNKNOWN ATTR VALUE..."; + break; + case MBO_ATTR_AP_TRANS_REASON: + if (AttrValue == MBO_AP_TRANS_REASON_UNSPECIFIED) + return "MBO_AP_TRANS_REASON_UNSPECIFIED"; + else if (AttrValue == MBO_AP_TRANS_REASON_TX_PER_TOO_HIGH) + return "MBO_AP_TRANS_REASON_TX_PER_TOO_HIGH"; + else if (AttrValue == MBO_AP_TRANS_REASON_TRAFFIC_DELAY) + return "MBO_AP_TRANS_REASON_TRAFFIC_DELAY"; + else if (AttrValue == MBO_AP_TRANS_REASON_INSUFFICIENT_BW) + return "MBO_AP_TRANS_REASON_INSUFFICIENT_BW"; + else if (AttrValue == MBO_AP_TRANS_REASON_LOAD_BALACING) + return "MBO_AP_TRANS_REASON_LOAD_BALACING"; + else if (AttrValue == MBO_AP_TRANS_REASON_RSSI_LOW) + return "MBO_AP_TRANS_REASON_RSSI_LOW"; + else if (AttrValue == MBO_AP_TRANS_REASON_TOO_MANY_RETRY) + return "MBO_AP_TRANS_REASON_TOO_MANY_RETRY"; + else if (AttrValue == MBO_AP_TRANS_REASON_HIGH_INTRFERENCE) + return "MBO_AP_TRANS_REASON_HIGH_INTRFERENCE"; + else if (AttrValue == MBO_AP_TRANS_REASON_GRAY_ZONE) + return "MBO_AP_TRANS_REASON_GRAY_ZONE"; + else if (AttrValue == MBO_AP_TRANS_REASON_TO_PREMIUM_AP) + return "MBO_AP_TRANS_REASON_TO_PREMIUM_AP"; + else + return "UNKNOWN ATTR VALUE..."; + break; + default: + return "UNKNOWN ATTR VALUE..."; + } +} + + +INT32 ShowMboStatProc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT8 loop = 0; + P_MBO_CTRL pMboCtrl = NULL; +#ifdef CONFIG_AP_SUPPORT + for (loop = 0; loop < pAd->ApCfg.BssidNum; loop++) { + pMboCtrl = &pAd->ApCfg.MBSSID[loop].wdev.MboCtrl; + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("========= apidx %d ===========\n", loop)); + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("bMboEnable \t\t %d\n", + pMboCtrl->bMboEnable)); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("AssocDisallowReason \t 0x%x [%s]\n", + pMboCtrl->AssocDisallowReason, MboAttrValueToString(MBO_ATTR_AP_ASSOC_DISALLOW, + pMboCtrl->AssocDisallowReason))); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("CellularPreference \t 0x%x [%s]\n", + pMboCtrl->CellularPreference, MboAttrValueToString(MBO_ATTR_AP_CDCP, + pMboCtrl->CellularPreference))); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("TransitionReason \t 0x%x [%s]\n", + pMboCtrl->TransitionReason, MboAttrValueToString(MBO_ATTR_AP_TRANS_REASON, + pMboCtrl->TransitionReason))); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("ReAssocDelay \t\t 0x%x [second]\n", + pMboCtrl->ReAssocDelay)); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("MboCapIndication \t\t 0x%x\n", + pMboCtrl->MboCapIndication)); + } +#endif /* CONFIG_AP_SUPPORT */ + + + return TRUE; +} + +VOID MboIndicateOneNRtoDaemonByBssEntry( + PRTMP_ADAPTER pAd, + struct wifi_dev *pWdev, + BSS_ENTRY *pBssEntry) +{ + DAEMON_EVENT_NR_LIST NeighborRepList; + DAEMON_NEIGHBOR_REP_INFO *pNeighborEntry = NULL; + + pNeighborEntry = &NeighborRepList.EvtNRInfo[0]; + NdisZeroMemory(pNeighborEntry, sizeof(DAEMON_NEIGHBOR_REP_INFO)); + /* Fill the NR entry */ + MboUpdateNRElement(pAd, pWdev, pBssEntry, pNeighborEntry); + /* Fill the NR list */ + NeighborRepList.Newlist = FALSE; + NeighborRepList.TotalNum = 1; + NeighborRepList.CurrNum = 1; + /* Send the list to daemon (which contains only one entry) */ + WextMboSendNeighborReportToDaemonEvent(pAd->net_dev, + &NeighborRepList, + sizeof(DAEMON_EVENT_NR_LIST)); +} + +VOID MboBssTermStart( + PRTMP_ADAPTER pAd, + UINT8 countdown) +{ + UINT32 hTsf, lTsf, tTsf; + MBO_EVENT_BSS_TERM bss_term; + + AsicGetTsfTime(pAd, &hTsf, &lTsf); + + /* Calcuate target TSF */ + /* tTsf = countdown << 20; */ /* sec to usec */ + tTsf = countdown*1000000; /* sec to usec */ + tTsf = lTsf + tTsf; + if (tTsf < lTsf) + hTsf++; + bss_term.TsfLowPart = tTsf; + bss_term.TsfHighPart = hTsf; + + /* Send an event to daemon */ + WextMboSendBssTermToDaemonEvent(pAd->net_dev, + &bss_term, + MBO_MSG_AP_TERMINATION, + sizeof(MBO_EVENT_BSS_TERM)); + + /* Trigger BSS Termination count Down */ + pAd->MboBssTermCountDown = countdown + 1; /* plus 1 in case subtract immediately */ + +} +static NTSTATUS RTMP_BSS_TERMINATION(RTMP_ADAPTER *pAd, struct wifi_dev *wdev) +{ + MlmeRadioOff(pAd); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("==>HwCtrlBssTermination (OFF)\n")); + + return NDIS_STATUS_SUCCESS; +} + +VOID MboCheckBssTermination( + PRTMP_ADAPTER pAd) +{ + struct wifi_dev *wdev = NULL; + + if (pAd->MboBssTermCountDown != 0) { + if ((--pAd->MboBssTermCountDown) == 0) { + wdev = &pAd->ApCfg.MBSSID[0].wdev; + RTMP_BSS_TERMINATION(pAd, wdev); + } + } +} +#endif /* MBO_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/misc.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/misc.c new file mode 100644 index 000000000..72ca95604 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/misc.c @@ -0,0 +1,35 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2009, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + misc.c + + Abstract: + + Handling Misc Problem + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Sean Wang 2009-08-12 Create + John Li 2009-11-30 Modified +*/ + +#include "rt_config.h" +#include "misc.h" + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mlme.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mlme.c new file mode 100644 index 000000000..dc61bde6b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mlme.c @@ -0,0 +1,6403 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + mlme.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" +#include +#ifdef DOT11R_FT_SUPPORT +#include "ft.h" +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT +#include "wnm.h" +#endif /* DOT11V_WNM_SUPPORT */ + +UCHAR CISCO_OUI[] = {0x00, 0x40, 0x96}; +UCHAR RALINK_OUI[] = {0x00, 0x0c, 0x43}; +#if (defined(WH_EZ_SETUP) || defined(MWDS) || defined(STA_FORCE_ROAM_SUPPORT)) || defined(WAPP_SUPPORT) +UCHAR MTK_OUI[] = {0x00, 0x0c, 0xe7}; +#endif +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}; + + +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 */ +}; + + +#ifdef SW_ATF_SUPPORT +static UINT32 badCnt; +static UINT32 goodCnt; +#endif + + + +/* 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 APPLE_OUI[] = {0x00, 0x17, 0xf2}; /* For IOS immediately connect */ +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 DYNAMIC_VGA_SUPPORT +void periodic_monitor_false_cca_adjust_vga(RTMP_ADAPTER *pAd) +{ + if ((pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable) && (pAd->chipCap.dynamic_vga_support) && + OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED)) { + UCHAR val1, val2; + UINT32 bbp_val1, bbp_val2; + + RTMP_BBP_IO_READ32(pAd, AGC1_R8, &bbp_val1); + val1 = ((bbp_val1 & (0x00007f00)) >> 8) & 0x7f; + RTMP_BBP_IO_READ32(pAd, AGC1_R9, &bbp_val2); + val2 = ((bbp_val2 & (0x00007f00)) >> 8) & 0x7f; + + DBGPRINT(RT_DEBUG_INFO, ("vga_init_0 = %x, vga_init_1 = %x\n", pAd->CommonCfg.lna_vga_ctl.agc_vga_init_0, pAd->CommonCfg.lna_vga_ctl.agc_vga_init_1)); + DBGPRINT(RT_DEBUG_INFO, + ("one second False CCA=%d, fixed agc_vga_0:0%x, fixed agc_vga_1:0%x\n", pAd->RalinkCounters.OneSecFalseCCACnt, val1, val2)); + + if (pAd->RalinkCounters.OneSecFalseCCACnt > pAd->CommonCfg.lna_vga_ctl.nFalseCCATh) { + if (val1 > (pAd->CommonCfg.lna_vga_ctl.agc_vga_init_0 - 0x10)) { + val1 -= 0x02; + bbp_val1 = (bbp_val1 & 0xffff80ff) | (val1 << 8); + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, bbp_val1); +#ifdef DFS_SUPPORT + pAd->CommonCfg.RadarDetect.bAdjustDfsAgc = TRUE; +#endif + } + + if (pAd->CommonCfg.RxStream >= 2) { + if (val2 > (pAd->CommonCfg.lna_vga_ctl.agc_vga_init_1 - 0x10)) { + val2 -= 0x02; + bbp_val2 = (bbp_val2 & 0xffff80ff) | (val2 << 8); + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, bbp_val2); + } + } + } else if (pAd->RalinkCounters.OneSecFalseCCACnt < + pAd->CommonCfg.lna_vga_ctl.nLowFalseCCATh) { + if (val1 < pAd->CommonCfg.lna_vga_ctl.agc_vga_init_0) { + val1 += 0x02; + bbp_val1 = (bbp_val1 & 0xffff80ff) | (val1 << 8); + RTMP_BBP_IO_WRITE32(pAd, AGC1_R8, bbp_val1); +#ifdef DFS_SUPPORT + pAd->CommonCfg.RadarDetect.bAdjustDfsAgc = TRUE; +#endif + } + + if (pAd->CommonCfg.RxStream >= 2) { + if (val2 < pAd->CommonCfg.lna_vga_ctl.agc_vga_init_1) { + val2 += 0x02; + bbp_val2 = (bbp_val2 & 0xffff80ff) | (val2 << 8); + RTMP_BBP_IO_WRITE32(pAd, AGC1_R9, bbp_val2); + } + } + } + } +} + +#endif + + +VOID set_default_ap_edca_param(RTMP_ADAPTER *pAd) +{ + pAd->CommonCfg.APEdcaParm.bValid = TRUE; + pAd->CommonCfg.APEdcaParm.Aifsn[0] = 3; + pAd->CommonCfg.APEdcaParm.Aifsn[1] = 7; + pAd->CommonCfg.APEdcaParm.Aifsn[2] = 1; + pAd->CommonCfg.APEdcaParm.Aifsn[3] = 1; + + pAd->CommonCfg.APEdcaParm.Cwmin[0] = 4; + pAd->CommonCfg.APEdcaParm.Cwmin[1] = 4; + pAd->CommonCfg.APEdcaParm.Cwmin[2] = 3; + pAd->CommonCfg.APEdcaParm.Cwmin[3] = 2; + + pAd->CommonCfg.APEdcaParm.Cwmax[0] = 6; + pAd->CommonCfg.APEdcaParm.Cwmax[1] = 10; + pAd->CommonCfg.APEdcaParm.Cwmax[2] = 4; + pAd->CommonCfg.APEdcaParm.Cwmax[3] = 3; + + pAd->CommonCfg.APEdcaParm.Txop[0] = 0; + pAd->CommonCfg.APEdcaParm.Txop[1] = 0; + pAd->CommonCfg.APEdcaParm.Txop[2] = 94; + pAd->CommonCfg.APEdcaParm.Txop[3] = 47; +} + + +#ifdef CONFIG_AP_SUPPORT +VOID set_default_sta_edca_param(RTMP_ADAPTER *pAd) +{ + pAd->ApCfg.BssEdcaParm.bValid = TRUE; + pAd->ApCfg.BssEdcaParm.Aifsn[0] = 3; + pAd->ApCfg.BssEdcaParm.Aifsn[1] = 7; + pAd->ApCfg.BssEdcaParm.Aifsn[2] = 2; + pAd->ApCfg.BssEdcaParm.Aifsn[3] = 2; + + pAd->ApCfg.BssEdcaParm.Cwmin[0] = 4; + pAd->ApCfg.BssEdcaParm.Cwmin[1] = 4; + pAd->ApCfg.BssEdcaParm.Cwmin[2] = 3; + pAd->ApCfg.BssEdcaParm.Cwmin[3] = 2; + + pAd->ApCfg.BssEdcaParm.Cwmax[0] = 10; + pAd->ApCfg.BssEdcaParm.Cwmax[1] = 10; + pAd->ApCfg.BssEdcaParm.Cwmax[2] = 4; + pAd->ApCfg.BssEdcaParm.Cwmax[3] = 3; + + pAd->ApCfg.BssEdcaParm.Txop[0] = 0; + pAd->ApCfg.BssEdcaParm.Txop[1] = 0; + pAd->ApCfg.BssEdcaParm.Txop[2] = 94; /*96; */ + pAd->ApCfg.BssEdcaParm.Txop[3] = 47; /*48; */ +} +#endif /* CONFIG_AP_SUPPORT */ + + +UCHAR dot11_max_sup_rate(INT SupRateLen, UCHAR *SupRate, INT ExtRateLen, UCHAR *ExtRate) +{ + INT idx; + UCHAR MaxSupportedRateIn500Kbps = 0; + + /* supported rates array may not be sorted. sort it and find the maximum rate */ + for (idx = 0; idx < SupRateLen; idx++) { + if (MaxSupportedRateIn500Kbps < (SupRate[idx] & 0x7f)) + MaxSupportedRateIn500Kbps = SupRate[idx] & 0x7f; + } + + if (ExtRateLen > 0 && ExtRate != NULL) + { + for (idx = 0; idx < ExtRateLen; idx++) { + if (MaxSupportedRateIn500Kbps < (ExtRate[idx] & 0x7f)) + MaxSupportedRateIn500Kbps = ExtRate[idx] & 0x7f; + } + } + + return MaxSupportedRateIn500Kbps; +} + + +UCHAR dot11_2_ra_rate(UCHAR MaxSupportedRateIn500Kbps) +{ + UCHAR MaxSupportedRate; + + switch (MaxSupportedRateIn500Kbps) + { + case 108: MaxSupportedRate = RATE_54; break; + case 96: MaxSupportedRate = RATE_48; break; + case 72: MaxSupportedRate = RATE_36; break; + case 48: MaxSupportedRate = RATE_24; break; + case 36: MaxSupportedRate = RATE_18; break; + case 24: MaxSupportedRate = RATE_12; break; + case 18: MaxSupportedRate = RATE_9; break; + case 12: MaxSupportedRate = RATE_6; break; + case 22: MaxSupportedRate = RATE_11; break; + case 11: MaxSupportedRate = RATE_5_5; break; + case 4: MaxSupportedRate = RATE_2; break; + case 2: MaxSupportedRate = RATE_1; break; + default: MaxSupportedRate = RATE_11; break; + } + + return MaxSupportedRate; +} + + +/* + ======================================================================== + + Routine Description: + Suspend MSDU transmission + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID RTMPSuspendMsduTransmission(RTMP_ADAPTER *pAd) +{ + DBGPRINT(RT_DEBUG_TRACE,("SCANNING, suspend MSDU transmission ...\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef CARRIER_DETECTION_SUPPORT /* Roger sync Carrier */ + /* no carrier detection when scanning */ + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + CarrierDetectionStop(pAd); +#endif +#endif /* CONFIG_AP_SUPPORT */ + + /* + Before BSS_SCAN_IN_PROGRESS, we need to keep Current R66 value and + use Lowbound as R66 value on ScanNextChannel(...) + */ + bbp_get_agc(pAd, &pAd->BbpTuning.R66CurrentValue, RX_CHAIN_0); + + pAd->hw_cfg.bbp_bw = pAd->CommonCfg.BBPCurrentBW; + + RTMPSetAGCInitValue(pAd, BW_20); + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); +} + + +/* + ======================================================================== + + Routine Description: + Resume MSDU transmission + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPResumeMsduTransmission(RTMP_ADAPTER *pAd) +{ + DBGPRINT(RT_DEBUG_TRACE,("SCAN done, resume MSDU transmission ...\n")); + +#ifdef CONFIG_AP_SUPPORT +#ifdef CARRIER_DETECTION_SUPPORT + /* no carrier detection when scanning*/ + if (pAd->CommonCfg.CarrierDetect.Enable == TRUE) + CarrierDetectionStart(pAd); +#endif /* CARRIER_DETECTION_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + /* + After finish BSS_SCAN_IN_PROGRESS, we need to restore Current R66 value + R66 should not be 0 + */ + if (pAd->BbpTuning.R66CurrentValue == 0) + { + pAd->BbpTuning.R66CurrentValue = 0x38; + DBGPRINT_ERR(("RTMPResumeMsduTransmission, R66CurrentValue=0...\n")); + } + bbp_set_agc(pAd, pAd->BbpTuning.R66CurrentValue, RX_CHAIN_ALL); + + pAd->CommonCfg.BBPCurrentBW = pAd->hw_cfg.bbp_bw; + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS); +/* sample, for IRQ LOCK to SEM LOCK */ +/* + IrqState = pAd->irq_disabled; + if (IrqState) + RTMPDeQueuePacket(pAd, TRUE, NUM_OF_TX_RING, MAX_TX_PROCESS); + else +*/ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, WCID_ALL, MAX_TX_PROCESS); +} + + +/* + ========================================================================== + Description: + Send out a NULL frame to a specified STA at a higher TX rate. The + purpose is to ensure the designated client is okay to received at this + rate. + ========================================================================== + */ +VOID RtmpEnqueueNullFrame( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + IN UCHAR TxRate, + IN UCHAR AID, + IN UCHAR apidx, + IN BOOLEAN bQosNull, + IN BOOLEAN bEOSP, + IN UCHAR OldUP) +{ + NDIS_STATUS NState; + HEADER_802_11 *pNullFr; + UCHAR *pFrame; + UINT frm_len; + MAC_TABLE_ENTRY *pEntry; + pEntry = MacTableLookup(pAd, pAddr); + + NState = MlmeAllocateMemory(pAd, (UCHAR **)&pFrame); + pNullFr = (PHEADER_802_11) pFrame; + + if (NState == NDIS_STATUS_SUCCESS) + { + frm_len = sizeof(HEADER_802_11); + +#ifdef CONFIG_AP_SUPPORT +// IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + if (pEntry && pEntry->wdev->wdev_type == WDEV_TYPE_AP) + { + MgtMacHeaderInit(pAd, pNullFr, SUBTYPE_DATA_NULL, 0, pAddr, + pAd->ApCfg.MBSSID[apidx].wdev.if_addr, + pAd->ApCfg.MBSSID[apidx].wdev.bssid); + pNullFr->FC.ToDs = 0; + pNullFr->FC.FrDs = 1; + goto body; + } +#endif /* CONFIG_AP_SUPPORT */ + + +body: + pNullFr->FC.Type = FC_TYPE_DATA; + + if (bQosNull) + { + UCHAR *qos_p = ((UCHAR *)pNullFr) + frm_len; + + pNullFr->FC.SubType = SUBTYPE_QOS_NULL; + + /* copy QOS control bytes */ + qos_p[0] = ((bEOSP) ? (1 << 4) : 0) | OldUP; + qos_p[1] = 0; + frm_len += 2; + } else + pNullFr->FC.SubType = SUBTYPE_DATA_NULL; + + /* since TxRate may change, we have to change Duration each time */ + pNullFr->Duration = RTMPCalcDuration(pAd, TxRate, frm_len); + + DBGPRINT(RT_DEBUG_INFO, ("send NULL Frame @%d Mbps to AID#%d...\n", RateIdToMbps[TxRate], AID & 0x3f)); + MiniportMMRequest(pAd, WMM_UP2AC_MAP[7], (PUCHAR)pNullFr, frm_len); + + MlmeFreeMemory(pAd, pFrame); + } +} + + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +VOID ApCliRTMPSendNullFrame( + IN PRTMP_ADAPTER pAd, + IN UCHAR TxRate, + IN BOOLEAN bQosNull, + IN PMAC_TABLE_ENTRY pMacEntry, + IN USHORT PwrMgmt) +{ + UCHAR NullFrame[48]; + ULONG Length; + HEADER_802_11 *wifi_hdr; + STA_TR_ENTRY *tr_entry; + PAPCLI_STRUCT pApCliEntry = NULL; + struct wifi_dev *wdev; + + pApCliEntry = &pAd->ApCfg.ApCliTab[pMacEntry->func_tb_idx]; + tr_entry = &pAd->MacTab.tr_entry[pMacEntry->wcid]; + wdev = &pApCliEntry->wdev; + + /* WPA 802.1x secured port control */ + // TODO: shiang-usw, check [wdev/tr_entry]->PortSecured! + if ((wdev->PortSecured == WPA_802_1X_PORT_NOT_SECURED) || + (tr_entry->PortSecured == WPA_802_1X_PORT_NOT_SECURED)) + return; + + NdisZeroMemory(NullFrame, 48); + Length = sizeof(HEADER_802_11); + + wifi_hdr = (HEADER_802_11 *)NullFrame; + + wifi_hdr->FC.Type = FC_TYPE_DATA; + wifi_hdr->FC.SubType = SUBTYPE_DATA_NULL; + wifi_hdr->FC.ToDs = 1; + + COPY_MAC_ADDR(wifi_hdr->Addr1, pMacEntry->Addr); +#ifdef MAC_REPEATER_SUPPORT + if (pMacEntry && (pMacEntry->bReptCli == TRUE)) + COPY_MAC_ADDR(wifi_hdr->Addr2, pMacEntry->ReptCliAddr); + else +#endif /* MAC_REPEATER_SUPPORT */ + COPY_MAC_ADDR(wifi_hdr->Addr2, pApCliEntry->wdev.if_addr); + COPY_MAC_ADDR(wifi_hdr->Addr3, pMacEntry->Addr); + + if (pAd->CommonCfg.bAPSDForcePowerSave) + wifi_hdr->FC.PwrMgmt = PWR_SAVE; + else + wifi_hdr->FC.PwrMgmt = PwrMgmt; + wifi_hdr->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, TxRate, 14); + + /* sequence is increased in MlmeHardTx */ + wifi_hdr->Sequence = pAd->Sequence; + pAd->Sequence = (pAd->Sequence + 1) & MAXSEQ; /* next sequence */ + + /* Prepare QosNull function frame */ + if (bQosNull) { + wifi_hdr->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*/ +#endif /* CONFIG_AP_SUPPORT */ + + + +VOID RtmpPrepareHwNullFrame( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN BOOLEAN bQosNull, + IN BOOLEAN bEOSP, + IN UCHAR OldUP, + IN UCHAR OpMode, + IN UCHAR PwrMgmt, + IN BOOLEAN bWaitACK, + IN CHAR Index) +{ + UINT8 TXWISize = pAd->chipCap.TXWISize; + UCHAR *pNullFrame, *tmac_info = (UCHAR *)&pAd->NullTxWI; + NDIS_STATUS NState; + HEADER_802_11 *pNullFr; + ULONG Length; + UCHAR *ptr; + UINT i; + UINT32 longValue; + MAC_TX_INFO mac_info; + + // TODO: shiang-7603!! fix me + if (IS_MT7603(pAd) || IS_MT7628(pAd)) { + DBGPRINT(RT_DEBUG_OFF, ("%s(): MT7603 Not support yet!\n", __FUNCTION__)); + return; + } + + NState = MlmeAllocateMemory(pAd, (PUCHAR *)&pNullFrame); + + NdisZeroMemory(pNullFrame, 48); + NdisZeroMemory(tmac_info, TXWISize); + + if (NState == NDIS_STATUS_SUCCESS) + { + pNullFr = (PHEADER_802_11) pNullFrame; + Length = sizeof(HEADER_802_11); + + pNullFr->FC.Type = FC_TYPE_DATA; + pNullFr->FC.SubType = SUBTYPE_DATA_NULL; + if (Index == 1) + pNullFr->FC.ToDs = 0; + else + pNullFr->FC.ToDs = 1; + pNullFr->FC.FrDs = 0; + + COPY_MAC_ADDR(pNullFr->Addr1, pEntry->Addr); + { + COPY_MAC_ADDR(pNullFr->Addr2, pAd->CurrentAddress); + COPY_MAC_ADDR(pNullFr->Addr3, pAd->CommonCfg.Bssid); + } + + pNullFr->FC.PwrMgmt = PwrMgmt; + + pNullFr->Duration = pAd->CommonCfg.Dsifs + RTMPCalcDuration(pAd, pAd->CommonCfg.TxRate, 14); + + /* sequence is increased in MlmeHardTx */ + pNullFr->Sequence = pAd->Sequence; + pAd->Sequence = (pAd->Sequence+1) & MAXSEQ; /* next sequence */ + + if (bQosNull) + { + UCHAR *qos_p = ((UCHAR *)pNullFr) + Length; + + pNullFr->FC.SubType = SUBTYPE_QOS_NULL; + + /* copy QOS control bytes */ + qos_p[0] = ((bEOSP) ? (1 << 4) : 0) | OldUP; + qos_p[1] = 0; + Length += 2; + } + + NdisZeroMemory((UCHAR *)&mac_info, sizeof(mac_info)); + mac_info.FRAG = FALSE; + + mac_info.CFACK = FALSE; + mac_info.InsTimestamp = FALSE; + mac_info.AMPDU = FALSE; + + mac_info.BM = IS_BM_MAC_ADDR(pNullFr->Addr1); + mac_info.Ack = TRUE; + mac_info.NSeq = TRUE; + mac_info.BASize = 0; + + mac_info.WCID = pEntry->Aid; + mac_info.Length = Length; + + mac_info.TID = 0; + mac_info.Txopmode = IFS_HTTXOP; + mac_info.Preamble = LONG_PREAMBLE; + mac_info.SpeEn = 1; + + if (Index == 1) + { + HTTRANSMIT_SETTING Transmit; + + Transmit.word = pEntry->MaxHTPhyMode.word; + Transmit.field.BW = 0; + if (Transmit.field.MCS > 7) + Transmit.field.MCS = 7; + + mac_info.PID = (UCHAR)Transmit.field.MCS; + mac_info.TxRate = (UCHAR)Transmit.field.MCS; + write_tmac_info(pAd, tmac_info, &mac_info, &Transmit); + } + else + { + mac_info.PID = (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS; + mac_info.TxRate = (UCHAR)pAd->CommonCfg.MlmeTransmit.field.MCS; + write_tmac_info(pAd, tmac_info, &mac_info, + &pAd->CommonCfg.MlmeTransmit); + } + + if (bWaitACK) { +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + TXWI_STRUC *pTxWI = (TXWI_STRUC *)tmac_info; + + pTxWI->TXWI_O.TXRPT = 1; + } +#endif /* RTMP_MAC */ +#ifdef RLT_MAC + // TODO: shiang, how about RT65xx series?? +#endif /* RLT_MAC */ + } + + ptr = (PUCHAR)&pAd->NullTxWI; +#ifdef RT_BIG_ENDIAN + RTMPWIEndianChange(pAd, ptr, TYPE_TXWI); +#endif /* RT_BIG_ENDIAN */ + for (i=0; i < TXWISize; i+=4) + { + longValue = *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + (*(ptr + 3) << 24); + if (Index == 0) + RTMP_IO_WRITE32(pAd, pAd->NullBufOffset[0] + i, longValue); + else if (Index == 1) + RTMP_IO_WRITE32(pAd, pAd->NullBufOffset[1] + i, longValue); + + ptr += 4; + } + + ptr = pNullFrame; +#ifdef RT_BIG_ENDIAN + RTMPFrameEndianChange(pAd, ptr, DIR_WRITE, FALSE); +#endif /* RT_BIG_ENDIAN */ + for (i= 0; i< Length; i+=4) + { + longValue = *ptr + (*(ptr + 1) << 8) + (*(ptr + 2) << 16) + (*(ptr + 3) << 24); + if (Index == 0) //for ra0 + RTMP_IO_WRITE32(pAd, pAd->NullBufOffset[0] + TXWISize+ i, longValue); + else if (Index == 1) //for p2p0 + RTMP_IO_WRITE32(pAd, pAd->NullBufOffset[1] + TXWISize+ i, longValue); + + ptr += 4; + } + } + + if (pNullFrame) + MlmeFreeMemory(pAd, pNullFrame); +} + + +/* + ========================================================================== + Description: + main loop of the MLME + Pre: + Mlme has to be initialized, and there are something inside the queue + Note: + This function is invoked from MPSetInformation and MPReceive; + This task guarantee only one FSM will run. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +#ifdef WH_EZ_SETUP +#ifdef DUAL_CHIP +extern NDIS_SPIN_LOCK ez_mlme_sync_lock; +#endif +#endif + +VOID MlmeHandler(RTMP_ADAPTER *pAd) +{ + MLME_QUEUE_ELEM *Elem = NULL; +#ifdef APCLI_SUPPORT + SHORT apcliIfIndex; +#endif /* APCLI_SUPPORT */ + + /* Only accept MLME and Frame from peer side, no other (control/data) frame should*/ + /* get into this state machine*/ +#ifdef WH_EZ_SETUP + EZ_ACQUIRE_DUAL_CHIP_DBDC_MLME_LOCK(pAd); +#endif + + NdisAcquireSpinLock(&pAd->Mlme.TaskLock); + if(pAd->Mlme.bRunning) + { + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); +#ifdef WH_EZ_SETUP + EZ_RELEASE_DUAL_CHIP_DBDC_MLME_LOCK(pAd); +#endif + + return; + } + else + { +#ifdef WH_EZ_SETUP + if (ez_is_other_band_mlme_running(&pAd->ApCfg.MBSSID[0].wdev)) { + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + EZ_RELEASE_DUAL_CHIP_DBDC_MLME_LOCK(pAd); + return; + } +#endif + pAd->Mlme.bRunning = TRUE; + } + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); +#ifdef WH_EZ_SETUP + EZ_RELEASE_DUAL_CHIP_DBDC_MLME_LOCK(pAd); +#endif + while (!MlmeQueueEmpty(&pAd->Mlme.Queue) +#ifdef EAPOL_QUEUE_SUPPORT + || !(EAPMlmeQueueEmpty(&pAd->Mlme.EAP_Queue)) +#endif /* EAPOL_QUEUE_SUPPORT */ + ) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) || + RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_SUSPEND) + ) + { + DBGPRINT(RT_DEBUG_OFF, ("System halted, removed or MlmeRest, exit MlmeTask!(QNum = %ld)\n", + pAd->Mlme.Queue.Num)); + break; + } + +#ifdef CONFIG_ATE + if(ATE_ON(pAd)) + { + DBGPRINT(RT_DEBUG_INFO, ("%s(): Driver is in ATE mode\n", __FUNCTION__)); + break; + } +#endif /* CONFIG_ATE */ + + /*From message type, determine which state machine I should drive*/ + + Elem = NULL; +#ifdef EAPOL_QUEUE_SUPPORT + if (!EAPMlmeQueueEmpty(&pAd->Mlme.EAP_Queue)) + EAPMlmeDequeue(&pAd->Mlme.EAP_Queue, &Elem); + else if (!MlmeQueueEmpty(&pAd->Mlme.Queue)) +#endif /* EAPOL_QUEUE_SUPPORT */ + MlmeDequeue(&pAd->Mlme.Queue, &Elem); + + if (Elem) + { + + if (Elem->Machine == WPA_STATE_MACHINE && Elem->MsgType == MT2_EAPOLKey) + { + if (((!OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED)) && + ( !OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED))) + + ) + { +#ifdef EAPOL_QUEUE_SUPPORT + EAP_MLME_QUEUE *Queue = (EAP_MLME_QUEUE *)&pAd->Mlme.EAP_Queue; +#else /* EAPOL_QUEUE_SUPPORT */ + MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; +#endif /* !EAPOL_QUEUE_SUPPORT */ + ULONG Tail; + NdisAcquireSpinLock(&(Queue->Lock)); + Tail = Queue->Tail; + Queue->Tail++; + Queue->Num++; + if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) + Queue->Tail = 0; + + Queue->Entry[Tail].Wcid = RESERVED_WCID; + Queue->Entry[Tail].Occupied = TRUE; + Queue->Entry[Tail].Machine = Elem->Machine; + Queue->Entry[Tail].MsgType = Elem->MsgType; + Queue->Entry[Tail].MsgLen = Elem->MsgLen; + Queue->Entry[Tail].Priv = Elem->Priv; + NdisZeroMemory(Queue->Entry[Tail].Msg, MGMT_DMA_BUFFER_SIZE); + + NdisMoveMemory(Queue->Entry[Tail].Msg, Elem->Msg, Elem->MsgLen); + + + NdisReleaseSpinLock(&(Queue->Lock)); + + Elem->Occupied = FALSE; + Elem->MsgLen = 0; + continue; + + } + } + + /* if dequeue success*/ + switch (Elem->Machine) + { + /* STA state machines*/ + + 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 WH_EZ_SETUP +#ifdef EZ_MOD_SUPPORT + case EZ_STATE_MACHINE: +//! Levarage from MP1.0 CL#170063 + StateMachinePerformAction(pAd, &pAd->Mlme.EzMachine, + Elem, pAd->Mlme.EzMachine.CurrState); + break; + +#else + case EZ_ROAM_STATE_MACHINE: +//! Levarage from MP1.0 CL#170063 + StateMachinePerformAction(pAd, &pAd->Mlme.EzRoamMachine, + Elem, pAd->Mlme.EzRoamMachine.CurrState); + break; + case AP_TRIBAND_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.ApTriBandMachine, + Elem, pAd->Mlme.ApTriBandMachine.CurrState); + break; + +#endif +#endif + +#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; + + if (Elem->Priv >= 64) { + CliIdx = ((Elem->Priv - 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; +#ifdef MULTI_APCLI_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("\x1b[35m APCLI_SYNC_STATE_MACHINE apcliIfindex = %d SyncCurrState=%lu \x1b[m\n", apcliIfIndex, pAd->ApCfg.ApCliTab[apcliIfIndex].SyncCurrState)); +#endif /* MULTI_APCLI_SUPPORT */ + if(isValidApCliIf(apcliIfIndex)) + StateMachinePerformAction(pAd, &pAd->Mlme.ApCliSyncMachine, Elem, + (pAd->ApCfg.ApCliTab[apcliIfIndex].SyncCurrState)); + break; + + case APCLI_CTRL_STATE_MACHINE: + apcliIfIndex = Elem->Priv; + +#ifdef MULTI_APCLI_SUPPORT + DBGPRINT(RT_DEBUG_TRACE, ("\x1b[34m APCLI_CTRL_STATE_MACHINE apcliIfindex=%d CtrlCurrState=%lu \x1b[m\n", apcliIfIndex, pAd->ApCfg.ApCliTab[apcliIfIndex].CtrlCurrState)); +#endif /* MULTI_APCLI_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT + if (apcliIfIndex >= 64) + apcliIfIndex = ((apcliIfIndex - 64) / 16); +#endif /* MAC_REPEATER_SUPPORT */ + + if(isValidApCliIf(apcliIfIndex)) + { + ULONG CtrlCurrState = pAd->ApCfg.ApCliTab[apcliIfIndex].CtrlCurrState; +#ifdef MAC_REPEATER_SUPPORT + UCHAR CliIdx = 0; + + apcliIfIndex = Elem->Priv; + + if (apcliIfIndex >= 64) + { + CliIdx = ((apcliIfIndex - 64) % 16); + apcliIfIndex = ((apcliIfIndex - 64) / 16); + CtrlCurrState = pAd->ApCfg.ApCliTab[apcliIfIndex].RepeaterCli[CliIdx].CtrlCurrState; + } +#endif /* MAC_REPEATER_SUPPORT */ + StateMachinePerformAction(pAd, &pAd->Mlme.ApCliCtrlMachine, Elem, CtrlCurrState); + } + break; +#endif /* APCLI_SUPPORT */ + +#endif /* CONFIG_AP_SUPPORT */ + case WPA_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.WpaMachine, Elem, pAd->Mlme.WpaMachine.CurrState); + break; +#ifdef WSC_INCLUDED + case WSC_STATE_MACHINE: + if (pAd->pWscElme) + { + RTMP_SEM_LOCK(&pAd->WscElmeLock); + NdisMoveMemory(pAd->pWscElme, Elem, sizeof(MLME_QUEUE_ELEM)); + RTMP_SEM_UNLOCK(&pAd->WscElmeLock); + RtmpOsTaskWakeUp(&(pAd->wscTask)); + } + break; +#endif /* WSC_INCLUDED */ + + + +#ifdef CONFIG_HOTSPOT + case HSCTRL_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.HSCtrlMachine, Elem, + HSCtrlCurrentState(pAd, Elem)); + break; +#endif + +#ifdef DOT11K_RRM_SUPPORT + case BCN_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.BCNMachine, Elem, + BCNPeerCurrentState(pAd, Elem)); + break; + case NEIGHBOR_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.NRMachine, Elem, + NRPeerCurrentState(pAd, Elem)); + break; +#endif + +#ifdef DOT11U_INTERWORKING + case GAS_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.GASMachine, Elem, + GASPeerCurrentState(pAd, Elem)); + break; +#endif + +#ifdef CONFIG_DOT11V_WNM + case BTM_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.BTMMachine, Elem, + BTMPeerCurrentState(pAd, Elem)); + break; +#ifdef CONFIG_HOTSPOT_R2 + case WNM_NOTIFY_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->Mlme.WNMNotifyMachine, Elem, + WNMNotifyPeerCurrentState(pAd, Elem)); + break; +#endif +#endif + +#ifdef MIXMODE_SUPPORT + case MIX_MODE_STATE_MACHINE: + StateMachinePerformAction(pAd, &pAd->MixModeCtrl.MixModeStatMachine, Elem, + pAd->MixModeCtrl.MixModeStatMachine.CurrState); + break; +#endif /* MIXMODE_SUPPORT */ +#ifdef WIFI_DIAG + case WIFI_DAIG_STATE_MACHINE: + DiagLogFileWrite(); + DiagAssocErrorFileWrite(); + break; +#endif + default: + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Illegal SM %ld\n", + __FUNCTION__, Elem->Machine)); + break; + } /* end of switch*/ + + /* free MLME element*/ + Elem->Occupied = FALSE; + Elem->MsgLen = 0; + + } + else { + DBGPRINT_ERR(("%s(): MlmeQ empty\n", __FUNCTION__)); + } + } + +#ifdef WH_EZ_SETUP + EZ_ACQUIRE_DUAL_CHIP_DBDC_MLME_LOCK(pAd); +#endif + NdisAcquireSpinLock(&pAd->Mlme.TaskLock); + pAd->Mlme.bRunning = FALSE; + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); +#ifdef WH_EZ_SETUP + EZ_RELEASE_DUAL_CHIP_DBDC_MLME_LOCK(pAd); +#endif +} + + +/* +======================================================================== +Routine Description: + MLME kernel thread. + +Arguments: + Context the pAd, driver control block pointer + +Return Value: + 0 close the thread + +Note: +======================================================================== +*/ +static INT MlmeThread(ULONG Context) +{ + RTMP_ADAPTER *pAd; + RTMP_OS_TASK *pTask; + int status; + status = 0; + + pTask = (RTMP_OS_TASK *)Context; + pAd = (PRTMP_ADAPTER)RTMP_OS_TASK_DATA_GET(pTask); + if (pAd == NULL) + goto LabelExit; + + RtmpOSTaskCustomize(pTask); + + while (!RTMP_OS_TASK_IS_KILLED(pTask)) + { + if (RtmpOSTaskWait(pAd, pTask, &status) == FALSE) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + break; + } + + /* lock the device pointers , need to check if required*/ + /*down(&(pAd->usbdev_semaphore)); */ + + if (!pAd->PM_FlgSuspend) + MlmeHandler(pAd); + } + + /* notify the exit routine that we're actually exiting now + * + * complete()/wait_for_completion() is similar to up()/down(), + * except that complete() is safe in the case where the structure + * is getting deleted in a parallel mode of execution (i.e. just + * after the down() -- that's necessary for the thread-shutdown + * case. + * + * complete_and_exit() goes even further than this -- it is safe in + * the case that the thread of the caller is going away (not just + * the structure) -- this is necessary for the module-remove case. + * This is important in preemption kernels, which transfer the flow + * of execution immediately upon a complete(). + */ +LabelExit: + DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__)); + RtmpOSTaskNotifyToExit(pTask); + return 0; + +} + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +static VOID ApCliMlmeInit(RTMP_ADAPTER *pAd) +{ + /* init apcli state machines*/ + ASSERT(APCLI_AUTH_FUNC_SIZE == APCLI_MAX_AUTH_MSG * APCLI_MAX_AUTH_STATE); + ApCliAuthStateMachineInit(pAd, &pAd->Mlme.ApCliAuthMachine, pAd->Mlme.ApCliAuthFunc); + + ASSERT(APCLI_ASSOC_FUNC_SIZE == APCLI_MAX_ASSOC_MSG * APCLI_MAX_ASSOC_STATE); + ApCliAssocStateMachineInit(pAd, &pAd->Mlme.ApCliAssocMachine, pAd->Mlme.ApCliAssocFunc); + + ASSERT(APCLI_SYNC_FUNC_SIZE == APCLI_MAX_SYNC_MSG * APCLI_MAX_SYNC_STATE); + ApCliSyncStateMachineInit(pAd, &pAd->Mlme.ApCliSyncMachine, pAd->Mlme.ApCliSyncFunc); + + ASSERT(APCLI_CTRL_FUNC_SIZE == APCLI_MAX_CTRL_MSG * APCLI_MAX_CTRL_STATE); + ApCliCtrlStateMachineInit(pAd, &pAd->Mlme.ApCliCtrlMachine, pAd->Mlme.ApCliCtrlFunc); +} +#endif /* APCLI_SUPPORT */ + +static VOID ApMlmeInit(RTMP_ADAPTER *pAd) +{ + /* init AP state machines*/ + APAssocStateMachineInit(pAd, &pAd->Mlme.ApAssocMachine, pAd->Mlme.ApAssocFunc); + APAuthStateMachineInit(pAd, &pAd->Mlme.ApAuthMachine, pAd->Mlme.ApAuthFunc); + APSyncStateMachineInit(pAd, &pAd->Mlme.ApSyncMachine, pAd->Mlme.ApSyncFunc); +#ifdef WH_EZ_SETUP +#ifdef EZ_MOD_SUPPORT + EzStateMachineInit(pAd, &pAd->Mlme.EzMachine, pAd->Mlme.EzFunc); +#else + //! Levarage from MP1.0 CL#170063 + EzRoamStateMachineInit(pAd, &pAd->Mlme.EzRoamMachine, pAd->Mlme.EzRoamFunc); + APTriBandStateMachineInit(pAd, &pAd->Mlme.ApTriBandMachine, pAd->Mlme.ApTriBandFunc); +#endif +#endif + +} +#endif /* CONFIG_AP_SUPPORT */ + +/* + ========================================================================== + Description: + initialize the MLME task and its data structure (queue, spinlock, + timer, state machines). + + IRQL = PASSIVE_LEVEL + + Return: + always return NDIS_STATUS_SUCCESS + + ========================================================================== +*/ +NDIS_STATUS MlmeInit(RTMP_ADAPTER *pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + DBGPRINT(RT_DEBUG_TRACE, ("--> MLME Initialize\n")); + + do + { + +#ifdef EAPOL_QUEUE_SUPPORT + Status = MlmeQueueInit(pAd, &pAd->Mlme.EAP_Queue, &pAd->Mlme.Queue); +#else /* EAPOL_QUEUE_SUPPORT */ + Status = MlmeQueueInit(pAd, &pAd->Mlme.Queue); +#endif /* !EAPOL_QUEUE_SUPPORT */ + + if(Status != NDIS_STATUS_SUCCESS) + break; + + pAd->Mlme.bRunning = FALSE; + NdisAllocateSpinLock(pAd, &pAd->Mlme.TaskLock); + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + ApMlmeInit(pAd); +#ifdef APCLI_SUPPORT + ApCliMlmeInit(pAd); +#endif /* APCLI_SUPPORT */ + } + +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef WSC_INCLUDED + /* Init Wsc state machine */ + ASSERT(WSC_FUNC_SIZE == MAX_WSC_MSG * MAX_WSC_STATE); + WscStateMachineInit(pAd, &pAd->Mlme.WscMachine, pAd->Mlme.WscFunc); +#endif /* WSC_INCLUDED */ + + WpaStateMachineInit(pAd, &pAd->Mlme.WpaMachine, pAd->Mlme.WpaFunc); + +#ifdef CONFIG_HOTSPOT + HSCtrlStateMachineInit(pAd, &pAd->Mlme.HSCtrlMachine, pAd->Mlme.HSCtrlFunc); +#endif/*CONFIG_HOTSPOT*/ +#ifdef DOT11U_INTERWORKING + GASStateMachineInit(pAd, &pAd->Mlme.GASMachine, pAd->Mlme.GASFunc); +#endif + +#ifdef DOT11K_RRM_SUPPORT + RRMBcnReqStateMachineInit(pAd, &pAd->Mlme.BCNMachine, pAd->Mlme.BCNFunc); + NRStateMachineInit(pAd, &pAd->Mlme.NRMachine, pAd->Mlme.NRFunc); +#endif + +#ifdef CONFIG_DOT11V_WNM + WNMCtrlInit(pAd); + BTMStateMachineInit(pAd, &pAd->Mlme.BTMMachine, pAd->Mlme.BTMFunc); +#ifdef CONFIG_HOTSPOT_R2 + WNMNotifyStateMachineInit(pAd, &pAd->Mlme.WNMNotifyMachine, pAd->Mlme.WNMNotifyFunc); +#endif +#endif + +#ifdef ACL_V2_SUPPORT + ACL_V2_CtrlInit(pAd); +#endif /* ACL_V2_SUPPORT */ + + +#ifdef SNIFFER_MIB_CMD + sniffer_mib_ctrlInit(pAd); +#endif /* SNIFFER_MIB_CMD */ + + + ActionStateMachineInit(pAd, &pAd->Mlme.ActMachine, pAd->Mlme.ActFunc); + + /* Init mlme periodic timer*/ + RTMPInitTimer(pAd, &pAd->Mlme.PeriodicTimer, GET_TIMER_FUNCTION(MlmePeriodicExecTimer), 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 */ + + + + } while (FALSE); + + { + RTMP_OS_TASK *pTask; + + /* Creat MLME Thread */ + pTask = &pAd->mlmeTask; + RTMP_OS_TASK_INIT(pTask, "RtmpMlmeTask", pAd); + Status = RtmpOSTaskAttach(pTask, MlmeThread, (ULONG)pTask); + if (Status == NDIS_STATUS_FAILURE) { + DBGPRINT (RT_DEBUG_ERROR, ("%s: unable to start MlmeThread\n", RTMP_OS_NETDEV_GET_DEVNAME(pAd->net_dev))); + } + } + DBGPRINT(RT_DEBUG_TRACE, ("<-- MLME Initialize\n")); + + return Status; +} + + +/* + ========================================================================== + Description: + Destructor of MLME (Destroy queue, state machine, spin lock and timer) + Parameters: + Adapter - NIC Adapter pointer + Post: + The MLME task will no longer work properly + + IRQL = PASSIVE_LEVEL + + ========================================================================== + */ +VOID MlmeHalt(RTMP_ADAPTER *pAd) +{ + BOOLEAN Cancelled; + RTMP_OS_TASK *pTask; + + DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeHalt\n")); + + /* Terminate Mlme Thread */ + pTask = &pAd->mlmeTask; + if (RtmpOSTaskKill(pTask) == NDIS_STATUS_FAILURE) { + DBGPRINT(RT_DEBUG_ERROR, ("kill mlme task failed!\n")); + } + +#if (defined(MT_WOW_SUPPORT) && defined(WOW_IFDOWN_SUPPORT)) + if (!((pAd->WOW_Cfg.bEnable == TRUE) && INFRA_ON(pAd))) +#endif + 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); + + + RTMPCancelTimer(&pAd->Mlme.RxAntEvalTimer, &Cancelled); + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_SUPPORT + UCHAR idx = 0; +#endif /* APCLI_SUPPORT */ + RTMPCancelTimer(&pAd->Mlme.APSDPeriodicTimer, &Cancelled); + + if (pAd->ApCfg.ApQuickResponeForRateUpTimerRunning == TRUE) + RTMPCancelTimer(&pAd->ApCfg.ApQuickResponeForRateUpTimer, &Cancelled); + +#ifdef APCLI_SUPPORT + for (idx = 0; idx < MAX_APCLI_NUM; idx++) + { + PAPCLI_STRUCT pApCliEntry = &pAd->ApCfg.ApCliTab[idx]; + RTMPCancelTimer(&pApCliEntry->MlmeAux.ProbeTimer, &Cancelled); + RTMPCancelTimer(&pApCliEntry->MlmeAux.ApCliAssocTimer, &Cancelled); + RTMPCancelTimer(&pApCliEntry->MlmeAux.ApCliAuthTimer, &Cancelled); + +#ifdef WSC_AP_SUPPORT + if (pApCliEntry->WscControl.WscProfileRetryTimerRunning) + { + pApCliEntry->WscControl.WscProfileRetryTimerRunning = FALSE; + RTMPCancelTimer(&pApCliEntry->WscControl.WscProfileRetryTimer, &Cancelled); + } +#endif /* WSC_AP_SUPPORT */ + } +#endif /* APCLI_SUPPORT */ + RTMPCancelTimer(&pAd->ScanCtrl.APScanTimer, &Cancelled); + } + +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_HOTSPOT + HSCtrlHalt(pAd); + HSCtrlExit(pAd); +#endif + +#ifdef DOT11U_INTERWORKING + GASCtrlExit(pAd); +#endif + +#ifdef CONFIG_DOT11V_WNM + WNMCtrlExit(pAd); +#endif + +#ifdef ACL_V2_SUPPORT + ACL_V2_CtrlExit(pAd); +#endif /* ACL_V2_SUPPORT */ + +#ifdef SNIFFER_MIB_CMD + sniffer_mib_ctrlExit(pAd); +#endif /* SNIFFER_MIB_CMD */ + + + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + +#ifdef LED_CONTROL_SUPPORT + /* Set LED*/ + RTMPSetLED(pAd, LED_HALT); + RTMPSetSignalLED(pAd, -100); /* Force signal strength Led to be turned off, firmware is not done it.*/ +#endif /* LED_CONTROL_SUPPORT */ + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) || defined(MT_WOW_SUPPORT) + if (!(pAd->WOW_Cfg.bEnable == TRUE) && INFRA_ON(pAd)) +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) || defined(MT_WOW_SUPPORT)*/ + if (pChipOps->AsicHaltAction) + pChipOps->AsicHaltAction(pAd); + } + + RtmpusecDelay(5000); /* 5 msec to gurantee Ant Diversity timer canceled*/ + +#ifdef EAPOL_QUEUE_SUPPORT + MlmeQueueDestroy(&pAd->Mlme.EAP_Queue, &pAd->Mlme.Queue); +#else /* EAPOL_QUEUE_SUPPORT */ + MlmeQueueDestroy(&pAd->Mlme.Queue); +#endif /* !EAPOL_QUEUE_SUPPORT */ + + NdisFreeSpinLock(&pAd->Mlme.TaskLock); + + DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeHalt\n")); +} + + +VOID MlmeResetRalinkCounters(RTMP_ADAPTER *pAd) +{ + pAd->RalinkCounters.LastOneSecRxOkDataCnt = pAd->RalinkCounters.OneSecRxOkDataCnt; + +#ifdef CONFIG_ATE + if (!ATE_ON(pAd)) +#endif /* CONFIG_ATE */ + /* for performace enchanement */ + NdisZeroMemory(&pAd->RalinkCounters, + (UINT32)&pAd->RalinkCounters.OneSecEnd - + (UINT32)&pAd->RalinkCounters.OneSecStart); + + return; +} + +int TX_IDLE_TIME = 100; +int Tx_Idle_Count[MAX_LEN_OF_MAC_TABLE]; +int pkg_cnt[MAX_LEN_OF_MAC_TABLE]; +void TIMMonitor(RTMP_ADAPTER *pAd) +{ + STA_TR_ENTRY *tr_entry = NULL; + int wcid=0; + UINT32 ent_type = ENTRY_CLIENT; + int i,j; + int Total_Packet_Number=0; + static int init=0; +#ifdef UAPSD_SUPPORT + QUEUE_HEADER *pQueApsd; +#endif + + if (init == 0) + { + for (i=0; iMacTab.Content[i]; + + /* dump MacTable entries which match the EntryType */ + if (pEntry->EntryType != ent_type) + continue; + + if ((IS_ENTRY_CLIENT(pEntry) ) && (pEntry->Sst != SST_ASSOC)) + continue; + + wcid = pEntry->wcid; + tr_entry = &pAd->MacTab.tr_entry[wcid]; + + for (j=0;j< WMM_NUM_OF_AC;j++) + { + Total_Packet_Number = Total_Packet_Number + tr_entry->tx_queue[j].Number; + } + Total_Packet_Number = Total_Packet_Number + tr_entry->ps_queue.Number; + +#ifdef UAPSD_SUPPORT + for(j=(WMM_NUM_OF_AC-1); j>=0; j--) + { + pQueApsd = &(pEntry->UAPSDQueue[j]); + Total_Packet_Number = Total_Packet_Number + pQueApsd->Number; + } +#endif + if (Total_Packet_Number != 0) + { + //WLAN_MR_TIM_BIT_SET(pAd, tr_entry->func_tb_idx, tr_entry->wcid); + Tx_Idle_Count[wcid] = TX_IDLE_TIME; + pkg_cnt[wcid]=10; + } + else + { + if (Tx_Idle_Count[wcid]) + { + Tx_Idle_Count[wcid]--; + } + else + { + WLAN_MR_TIM_BIT_CLEAR1(pAd, tr_entry->func_tb_idx, tr_entry->wcid); + } + + if (pkg_cnt[wcid]) + pkg_cnt[wcid]--; + else + pkg_cnt[wcid]=10; + } + } +} + + +#ifdef SW_ATF_SUPPORT + +/* Decide if wcid in tx flow */ +static BOOLEAN isTxFlow(PRTMP_ADAPTER pAd, PMAC_TABLE_ENTRY pEntry) +{ +/* +* according deqCnt to decide if wcid in tx flow +* period 100ms, pkt len = 1514, target TP = 5M, so deqCount = 43 +*/ + if (pEntry->atfPara.deqCount_100ms > pAd->AtfParaSet.wcidTxThr) { + pEntry->atfPara.inTxFlow = TRUE; + return TRUE; + } else { + pEntry->atfPara.inTxFlow = FALSE; + pEntry->atfPara.deqCount_100ms = 0; + pEntry->atfPara.isBadNode = FALSE; + return FALSE; + } +} +static void findBadNode(PRTMP_ADAPTER pAd, UINT32 *wcidInTxFlow) +{ + PMAC_TABLE_ENTRY pEntry1, pEntry2; + UINT32 tmp; + LONG rssi0, rssi1, avgRssi1, avgRssi2; +/* Just condsider 2 STA, n mdoe and b/g mode */ + if (pAd->AtfParaSet.txWcidNum == 2) { + pEntry1 = &(pAd->MacTab.Content[wcidInTxFlow[1]]); + pEntry2 = &(pAd->MacTab.Content[wcidInTxFlow[2]]); + goodCnt = pEntry1->atfPara.deqCount_100ms; + badCnt = pEntry2->atfPara.deqCount_100ms; + pEntry1->atfPara.deqCount_100ms = 0; + pEntry2->atfPara.deqCount_100ms = 0; + if (pEntry1->SupportRateMode & SUPPORT_HT_MODE) { + if (!(pEntry2->SupportRateMode & SUPPORT_HT_MODE)) { + pEntry1->atfPara.isBadNode = FALSE; + pEntry2->atfPara.isBadNode = TRUE; + pAd->AtfParaSet.flagATF = TRUE; + /* default set badNode index to 1 */ + tmp = wcidInTxFlow[1]; + wcidInTxFlow[1] = wcidInTxFlow[2]; + wcidInTxFlow[2] = tmp; + return; + } + } else if (pEntry2->SupportRateMode & SUPPORT_HT_MODE) { + if (!(pEntry1->SupportRateMode & SUPPORT_HT_MODE)) { + pEntry1->atfPara.isBadNode = TRUE; + pEntry2->atfPara.isBadNode = FALSE; + pAd->AtfParaSet.flagATF = TRUE; + tmp = goodCnt; + goodCnt = badCnt; + badCnt = tmp; + return; + } + } + rssi0 = pEntry1->RssiSample.AvgRssi[0] - pAd->BbpRssiToDbmDelta; + rssi1 = pEntry1->RssiSample.AvgRssi[1] - pAd->BbpRssiToDbmDelta; + avgRssi1 = (rssi0 + rssi1) / 2; + rssi0 = pEntry2->RssiSample.AvgRssi[0] - pAd->BbpRssiToDbmDelta; + rssi1 = pEntry2->RssiSample.AvgRssi[1] - pAd->BbpRssiToDbmDelta; + avgRssi2 = (rssi0 + rssi1) / 2; + if ((avgRssi2 > -45) && (avgRssi1 < -60) && (pEntry1->HTPhyMode.field.MCS != 15)) { + pEntry1->atfPara.isBadNode = TRUE; + pEntry2->atfPara.isBadNode = FALSE; + pAd->AtfParaSet.flagATF = TRUE; + tmp = goodCnt; + goodCnt = badCnt; + badCnt = tmp; + return; + } else if ((avgRssi1 > -45) && (avgRssi2 < -60) && (pEntry2->HTPhyMode.field.MCS != 15)) { + pEntry2->atfPara.isBadNode = TRUE; + pEntry1->atfPara.isBadNode = FALSE; + tmp = wcidInTxFlow[1]; + wcidInTxFlow[1] = wcidInTxFlow[2]; + wcidInTxFlow[2] = tmp; + pAd->AtfParaSet.flagATF = TRUE; + return; + + } + } + pAd->AtfParaSet.flagATF = FALSE; + return; +} +static void setGoodNodeEntryPara(PRTMP_ADAPTER pAd, PMAC_TABLE_ENTRY entry) +{ + entry->atfThr.deqMaxThr = pAd->AtfParaSet.deq_goodNodeMaxThr; + entry->atfThr.deqMinThr = pAd->AtfParaSet.deq_goodNodeMinThr; + +} +static void setBadNodeEntryPara(PRTMP_ADAPTER pAd, PMAC_TABLE_ENTRY entry) +{ + entry->atfThr.enqMaxThr = pAd->AtfParaSet.enq_badNodeMaxThr; + entry->atfThr.enqMinThr = pAd->AtfParaSet.enq_badNodeMinThr; + entry->atfThr.deqMinThr = pAd->AtfParaSet.deq_badNodeMinThr; +} +static void setWcidenqThr(PRTMP_ADAPTER pAd, UINT32 *wcidInTxFlow) +{ + PMAC_TABLE_ENTRY goodNodeEntry = NULL; + PMAC_TABLE_ENTRY badNodeEntry = NULL; + + goodNodeEntry = &(pAd->MacTab.Content[wcidInTxFlow[2]]); + badNodeEntry = &(pAd->MacTab.Content[wcidInTxFlow[1]]); + setGoodNodeEntryPara(pAd, goodNodeEntry); + setBadNodeEntryPara(pAd, badNodeEntry); + DBGPRINT(RT_DEBUG_INFO, + ("notBadWcid:%d,deqCount:%d\n", goodNodeEntry->wcid, goodNodeEntry->atfPara.deqCount_100ms)); + DBGPRINT(RT_DEBUG_INFO, + ("badWcid:%d,deqCount:%d\n", badNodeEntry->wcid, badNodeEntry->atfPara.deqCount_100ms)); + if (goodCnt > goodNodeEntry->atfThr.deqMaxThr) { + if (pAd->AtfParaSet.flagOnce == FALSE) { + if (pAd->AtfParaSet.enq_badNodeCurrent >= 10) + pAd->AtfParaSet.enq_badNodeCurrent = 10; + else + pAd->AtfParaSet.enq_badNodeCurrent++; + badNodeEntry->atfThr.enqCurrentThr = pAd->AtfParaSet.enq_badNodeCurrent; + } else + badNodeEntry->atfThr.enqCurrentThr = badNodeEntry->atfThr.enqMaxThr; + } else if (goodCnt < goodNodeEntry->atfThr.deqMinThr) { + if (pAd->AtfParaSet.flagOnce == FALSE) { + if (pAd->AtfParaSet.enq_badNodeCurrent <= 2) + pAd->AtfParaSet.enq_badNodeCurrent = 2; + else + pAd->AtfParaSet.enq_badNodeCurrent--; + badNodeEntry->atfThr.enqCurrentThr = pAd->AtfParaSet.enq_badNodeCurrent; + } else + badNodeEntry->atfThr.enqCurrentThr = badNodeEntry->atfThr.enqMinThr; + } + if (badCnt < badNodeEntry->atfThr.deqMinThr) { + if (pAd->AtfParaSet.flagOnce == FALSE) { + if (pAd->AtfParaSet.enq_badNodeCurrent >= 10) + pAd->AtfParaSet.enq_badNodeCurrent = 10; + else + pAd->AtfParaSet.enq_badNodeCurrent++; + badNodeEntry->atfThr.enqCurrentThr = pAd->AtfParaSet.enq_badNodeCurrent; + } else + badNodeEntry->atfThr.enqCurrentThr = badNodeEntry->atfThr.enqMaxThr; + } + badNodeEntry->atfPara.deqCount_100ms = 0; + goodNodeEntry->atfPara.deqCount_100ms = 0; +} + +static void badNodeDetect(PRTMP_ADAPTER pAd) +{ + UINT32 i = 0, j = 1; + UINT32 wcidInTxFlow[MAX_LEN_OF_MAC_TABLE] = {0}; + PMAC_TABLE_ENTRY pEntry; + + pAd->AtfParaSet.txWcidNum = 0; +/* +*step1: Find associated wcid in tx flow. +*step2: According to per wcid, we should set wcid priority and through get deq parameter to set enq drop threshold. +*/ +/* step1 */ + if (pAd->RalinkCounters.OneSecFalseCCACnt >= pAd->AtfParaSet.atfFalseCCAThr) { + pAd->AtfParaSet.flagATF = FALSE; + return; + } + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) { + pEntry = &(pAd->MacTab.Content[i]); + if (pEntry != NULL && IS_ENTRY_CLIENT(pEntry) && pEntry->Sst == SST_ASSOC) { + if (isTxFlow(pAd, pEntry)) { + pAd->AtfParaSet.txWcidNum++; + wcidInTxFlow[j++] = pEntry->wcid; + } + } + } +/*step2 */ + if (pAd->AtfParaSet.txWcidNum == 2) { + /*find badNode*/ + findBadNode(pAd, wcidInTxFlow); + if (pAd->AtfParaSet.flagATF) { + setWcidenqThr(pAd, wcidInTxFlow); + return; + } + } + pAd->AtfParaSet.flagATF = FALSE; + return; +} +#endif +/* + ========================================================================== + 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 + + ========================================================================== + */ + +VOID MlmePeriodicExecTimer( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + RTEnqueueInternalCmd(pAd, CMDTHREAD_MLME_PERIOIDC_EXEC, NULL, 0); +} + +NTSTATUS MlmePeriodicExec(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + ULONG TxTotalCnt; + //RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + /* No More 0x84 MCU CMD from v.30 FW*/ + +//CFG + +#ifdef MICROWAVE_OVEN_SUPPORT + /* update False CCA count to an array */ + NICUpdateRxStatusCnt1(pAd, pAd->Mlme.PeriodicRound%10); + + if (pAd->CommonCfg.MO_Cfg.bEnable) + { + UINT8 stage = pAd->Mlme.PeriodicRound%10; + + if (stage == MO_MEAS_PERIOD) + { + ASIC_MEASURE_FALSE_CCA(pAd); + pAd->CommonCfg.MO_Cfg.nPeriod_Cnt = 0; + } + else if (stage == MO_IDLE_PERIOD) + { + UINT16 Idx; + + for (Idx = MO_MEAS_PERIOD + 1; Idx < MO_IDLE_PERIOD + 1; Idx++) + pAd->CommonCfg.MO_Cfg.nFalseCCACnt += pAd->RalinkCounters.FalseCCACnt_100MS[Idx]; + + //printk("%s: fales cca1 %d\n", __FUNCTION__, pAd->CommonCfg.MO_Cfg.nFalseCCACnt); + if (pAd->CommonCfg.MO_Cfg.nFalseCCACnt > pAd->CommonCfg.MO_Cfg.nFalseCCATh) + ASIC_MITIGATE_MICROWAVE(pAd); + + } + } +#endif /* MICROWAVE_OVEN_SUPPORT */ + +#ifdef INF_AMAZON_SE +#endif /* INF_AMAZON_SE */ + + + /* 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 NDIS_STATUS_SUCCESS; + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_START_UP)) + return NDIS_STATUS_SUCCESS; + +#ifdef CONFIG_FPGA_MODE +#ifdef CAPTURE_MODE + cap_status_chk_and_get(pAd); +#endif /* CAPTURE_MODE */ +#endif /* CONFIG_FPGA_MODE */ + + + + pAd->bUpdateBcnCntDone = FALSE; + +/* RECBATimerTimeout(SystemSpecific1,FunctionContext,SystemSpecific2,SystemSpecific3);*/ + pAd->Mlme.PeriodicRound ++; + pAd->Mlme.GPIORound++; + +#ifdef CONFIG_BA_REORDER_MONITOR + ba_timeout_monitor(pAd); +#endif + +#ifndef WFA_VHT_PF +#endif /* WFA_VHT_PF */ + +#if defined(MT_MAC) && defined(CONFIG_STA_SUPPORT) + if((pAd->Mlme.PeriodicRound % 10) == 0) + { + periodic_monitor_ac_counter(pAd,QID_AC_VI); + } +#endif + + +#ifdef MT_MAC + if ((pAd->Mlme.PeriodicRound % 1) == 0) + { +#ifdef RTMP_MAC_PCI + if (pAd->PDMAWatchDogEn) + { + PDMAWatchDog(pAd); + } + + if (pAd->PSEWatchDogEn) + { +#ifdef DMA_RESET_SUPPORT + //check every second + if ((pAd->Mlme.PeriodicRound % 10) == 0) + { + PSEACStuckWatchDog(pAd); + } +#endif /* DMA_RESET_SUPPORT */ + + PSEWatchDog(pAd); + } +#endif + } +#ifdef MT_PS + if ((pAd->Mlme.PeriodicRound % 10) == 0) { + UINT32 i; + STA_TR_ENTRY *tr_entry; + MAC_TABLE_ENTRY *pMacEntry; + ULONG Now32; + + NdisGetSystemUpTime(&Now32); + + NdisAcquireSpinLock(&pAd->MacTabLock); + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) { + tr_entry = &pAd->MacTab.tr_entry[i]; + pMacEntry = &pAd->MacTab.Content[i]; + if (IS_VALID_ENTRY(tr_entry) && IS_ENTRY_CLIENT(pMacEntry)) { + if ((tr_entry->ps_state != APPS_RETRIEVE_DONE) && + (tr_entry->ps_state != APPS_RETRIEVE_IDLE) && + RTMP_TIME_AFTER((unsigned long)Now32, + (unsigned long)(tr_entry->ps_start_time + 4 * OS_HZ))) { + PsRetrieveTimeout(pAd, tr_entry); + } + } + } + NdisReleaseSpinLock(&pAd->MacTabLock); + } +#endif + + /* Following is the TxOP scenario, monitor traffic in every minutes */ + if ((pAd->Mlme.PeriodicRound % 10) == 0) + { +#ifdef DYNAMIC_WMM + if (pAd->CommonCfg.DynamicWmm == 1) + DynamicWMMDetectAction(pAd); + else +#endif + TxOPUpdatingAlgo(pAd); + } + +#endif /* MT_MAC */ + + +#ifdef SW_ATF_SUPPORT +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + badNodeDetect(pAd); +#endif +#endif + + + /* by default, execute every 500ms */ + if ((pAd->ra_interval) && + ((pAd->Mlme.PeriodicRound % (pAd->ra_interval / 100)) == 0)) + { + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + //AsicRssiUpdate(pAd); + //AsicTxCntUpdate(pAd, 0); + } +#endif /* MT_MAC */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + APMlmeDynamicTxRateSwitching(pAd); +#endif /* CONFIG_AP_SUPPORT */ + } + +#ifdef DFS_SUPPORT +#ifdef CONFIG_AP_SUPPORT +#endif /* CONFIG_AP_SUPPORT */ +#endif /* DFS_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { + TIMMonitor(pAd); + } +#endif /* CONFIG_AP_SUPPORT */ + + + + + /* Normal 1 second Mlme PeriodicExec.*/ + if (pAd->Mlme.PeriodicRound %MLME_TASK_EXEC_MULTIPLE == 0) + { + pAd->Mlme.OneSecPeriodicRound ++; + +#ifdef CONFIG_AP_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*/ +#endif /* CONFIG_AP_SUPPORT */ + + NdisGetSystemUpTime(&pAd->Mlme.Now32); + + /* add the most up-to-date h/w raw counters into software variable, so that*/ + /* the dynamic tuning mechanism below are based on most up-to-date information*/ + /* Hint: throughput impact is very serious in the function */ +#ifndef RTMP_SDIO_SUPPORT + NICUpdateRawCounters(pAd); +#endif /*leonardo mark it for FPGA debug*/ + RTMP_SECOND_CCA_DETECTION(pAd); + +#ifdef ANTI_INTERFERENCE_SUPPORT + if (pAd->bDynamicRaInterval) + DynamicRaInterval(pAd); +#endif /* ANTI_INTERFERENCE_SUPPORT */ + +#ifdef DYNAMIC_VGA_SUPPORT + dynamic_vga_adjust(pAd); +#endif /* DYNAMIC_VGA_SUPPORT */ + + +#ifdef DOT11_N_SUPPORT + /* Need statistics after read counter. So put after NICUpdateRawCounters*/ + ORIBATimerTimeout(pAd); +#endif /* DOT11_N_SUPPORT */ + +#ifdef CONFIG_WIFI_TEST + if (pAd->Mlme.OneSecPeriodicRound % 1 == 0) + { +#ifdef RTMP_PCI_SUPPORT + MonitorTxRing(pAd); + MonitorTxRing(pAd); + MonitorTxRing(pAd); + MonitorTxRing(pAd); +#endif + } +#endif + +#ifdef DYNAMIC_VGA_SUPPORT +#ifdef CONFIG_AP_SUPPORT +#endif /* CONFIG_AP_SUPPORT */ + +#endif /* DYNAMIC_VGA_SUPPORT */ + + /* + if (pAd->RalinkCounters.MgmtRingFullCount >= 2) + RTMP_SET_FLAG(pAd, fRTMP_HW_ERR); + else + pAd->RalinkCounters.MgmtRingFullCount = 0; + */ + + /* The time period for checking antenna is according to traffic*/ + { + if (pAd->Mlme.bEnableAutoAntennaCheck) + { + TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + + pAd->RalinkCounters.OneSecTxRetryOkCount + + pAd->RalinkCounters.OneSecTxFailCount; + + /* dynamic adjust antenna evaluation period according to the traffic*/ + if (TxTotalCnt > 50) + { + if (pAd->Mlme.OneSecPeriodicRound % 10 == 0) + AsicEvaluateRxAnt(pAd); + } + else + { + if (pAd->Mlme.OneSecPeriodicRound % 3 == 0) + AsicEvaluateRxAnt(pAd); + } + } + } + +#ifdef VIDEO_TURBINE_SUPPORT + /* + VideoTurbineUpdate(pAd); + VideoTurbineDynamicTune(pAd); + */ +#endif /* VIDEO_TURBINE_SUPPORT */ + +#ifdef MT76x0_TSSI_CAL_COMPENSATION + if (IS_MT76x0(pAd) && + (pAd->chipCap.bInternalTxALC) && + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET) == FALSE)) + { + if ((pAd->Mlme.OneSecPeriodicRound % 1) == 0) + { + /* TSSI compensation */ + MT76x0_IntTxAlcProcess(pAd); + } + } +#endif /* MT76x0_TSSI_CAL_COMPENSATION */ + + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET) == FALSE) + { + if ((pAd->Mlme.OneSecPeriodicRound % 10) == 0) + { + { + } + } + } + +#ifdef DOT11_N_SUPPORT +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + /* Not RDG, update the TxOP else keep the default RDG's TxOP */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE) == FALSE) + { + } + } +#endif /* MT_MAC */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + APMlmePeriodicExec(pAd); +#ifdef CONFIG_HOTSPOT_R2 +#ifdef WAPP_SUPPORT + wapp_bss_load_check(pAd); +#endif/* WAPP_SUPPORT */ +#endif/* CONFIG_HOTSPOT_R2 */ + + if ((pAd->RalinkCounters.OneSecBeaconSentCnt == 0) + && (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS)) + && (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + && ((pAd->CommonCfg.bIEEE80211H != 1) + || (pAd->Dot11_H.RDMode != RD_SILENCE_MODE)) +#ifdef WDS_SUPPORT + && (pAd->WdsTab.Mode != WDS_BRIDGE_MODE) +#endif /* WDS_SUPPORT */ +#ifdef CARRIER_DETECTION_SUPPORT + && (isCarrierDetectExist(pAd) == FALSE) +#endif /* CARRIER_DETECTION_SUPPORT */ + ) + pAd->macwd ++; + else + pAd->macwd = 0; + + if (pAd->macwd > 1) + { + DBGPRINT(RT_DEBUG_WARN, ("MAC specific condition \n")); + + AsicSetMacWD(pAd); + +#ifdef AP_QLOAD_SUPPORT + Show_QoSLoad_Proc(pAd, NULL); +#endif /* AP_QLOAD_SUPPORT */ + } + } +#endif /* CONFIG_AP_SUPPORT */ + + + +#ifdef SMART_CARRIER_SENSE_SUPPORT + + if (pAd->SCSCtrl.SCSEnable == SCS_ENABLE) + { + Smart_Carrier_Sense(pAd); + } +#endif /* SMART_CARRIER_SENSE_SUPPORT */ + + + RTMP_SECOND_CCA_DETECTION(pAd); + + MlmeResetRalinkCounters(pAd); + +#if defined(RTMP_MAC) || defined(RLT_MAC) +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + RTMP_MLME_HANDLER(pAd); + } + +#ifdef CONFIG_AP_SUPPORT +#ifdef AP_PARTIAL_SCAN_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if ((pAd->ApCfg.bPartialScanning == TRUE) && + (pAd->ApCfg.PartialScanChannelNum == DEFLAUT_PARTIAL_SCAN_CH_NUM))/* pAd->ApCfg.PartialScanChannelNum == DEFLAUT_PARTIAL_SCAN_CH_NUM means that one partial scan is finished */ + { + if (((pAd->ApCfg.PartialScanBreakTime++)%DEFLAUT_PARTIAL_SCAN_BREAK_TIME) == 0) + ApSiteSurvey(pAd, NULL, SCAN_ACTIVE, FALSE, NULL); + } + } +#endif /* AP_PARTIAL_SCAN_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef WSC_INCLUDED + WSC_HDR_BTN_MR_HANDLE(pAd); +#endif /* WSC_INCLUDED */ + + + + + /*add for hook function on Mlme timer interrupt*/ + RTMP_OS_TXRXHOOK_CALL(WLAN_TX_MLME_PERIOD,NULL,1,pAd); + + pAd->bUpdateBcnCntDone = FALSE; + + if(pAd->ed_chk != FALSE) + ed_status_read(pAd); + return NDIS_STATUS_SUCCESS; +} + + +/* + ========================================================================== + Validate SSID for connection try and rescan purpose + Valid SSID will have visible chars only. + The valid length is from 0 to 32. + IRQL = DISPATCH_LEVEL + ========================================================================== + */ +BOOLEAN MlmeValidateSSID(UCHAR *pSsid, UCHAR SsidLen) +{ + int index; + + if (SsidLen > MAX_LEN_OF_SSID) + return (FALSE); + + /* Check each character value*/ + for (index = 0; index < SsidLen; index++) + { + if (pSsid[index] < 0x20) + return (FALSE); + } + + /* All checked*/ + return (TRUE); +} + + + +VOID RTMPSetEnterPsmNullBit(PPWR_MGMT_STRUCT pPwrMgmt) +{ + //pAd->StaCfg.PwrMgmt.bEnterPsmNull = TRUE; + pPwrMgmt->bEnterPsmNull = TRUE; +} + +VOID RTMPClearEnterPsmNullBit(PPWR_MGMT_STRUCT pPwrMgmt) +{ + //pAd->StaCfg.PwrMgmt.bEnterPsmNull = FALSE; + pPwrMgmt->bEnterPsmNull = FALSE; +} + +BOOLEAN RTMPEnterPsmNullBitStatus(PPWR_MGMT_STRUCT pPwrMgmt) +{ + //return (pAd->StaCfg.PwrMgmt.bEnterPsmNull); + return (pPwrMgmt->bEnterPsmNull); +} + + +/* + ========================================================================== + 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*/ + +#if (defined(STA_LP_PHASE_1_SUPPORT) || defined(STA_LP_PHASE_2_SUPPORT)) && defined(CONFIG_STA_SUPPORT) + struct wifi_dev *wdev = &pAd->StaCfg.wdev; +#endif + + + + + 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->LastRssi[0], + pRssiSample->LastRssi[1], + pRssiSample->LastRssi[2]); + + + /* + 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; + +#if (defined(STA_LP_PHASE_1_SUPPORT) || defined(STA_LP_PHASE_2_SUPPORT)) && defined(CONFIG_STA_SUPPORT) + if (INFRA_ON(pAd) && (pMacEntry->wcid == BSSID_WCID) && + (pAd->StaCfg.PwrMgmt.bBeaconLost) && + OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + pAd->Mlme.ChannelQuality = 0; + DBGPRINT(RT_DEBUG_TRACE, ("%s::MT7636 BEACON lost meet\n", __FUNCTION__)); + } + else +#endif + { + /* decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER*/ + { + /* 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_AP_SUPPORT + if (pAd->OpMode == OPMODE_AP) + { + if (pMacEntry != NULL) + pMacEntry->ChannelQuality = (ChannelQuality > 100) ? 100 : ChannelQuality; + pAd->Mlme.ChannelQuality = (ChannelQuality > 100) ? 100 : ChannelQuality; + } +#endif /* CONFIG_AP_SUPPORT */ + + +} + + +VOID MlmeSetTxPreamble(RTMP_ADAPTER *pAd, USHORT TxPreamble) +{ + /* Always use Long preamble before verifiation short preamble functionality works well.*/ + /* Todo: remove the following line if short preamble functionality works*/ + + if (TxPreamble == Rt802_11PreambleLong) + { + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + } + else + { + /* NOTE: 1Mbps should always use long preamble*/ + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + } + DBGPRINT(RT_DEBUG_TRACE, ("MlmeSetTxPreamble = %s PREAMBLE\n", + ((TxPreamble == Rt802_11PreambleLong) ? "LONG" : "SHORT"))); + + AsicSetTxPreamble(pAd, TxPreamble); +} + + +/* + ========================================================================== + Description: + Update basic rate bitmap + ========================================================================== +*/ +#ifdef DYNAMIC_RX_RATE_ADJ +VOID UpdateBasicRateBitmap(RTMP_ADAPTER *pAdapter, UCHAR apidx) +#else +VOID UpdateBasicRateBitmap(RTMP_ADAPTER *pAdapter) +#endif /* DYNAMIC_RX_RATE_ADJ */ +{ + 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; + +#ifdef DYNAMIC_RX_RATE_ADJ + if (apidx < MIN_NET_DEVICE_FOR_WDS) + { + sup_p = pAdapter->ApCfg.MBSSID[apidx].SupRate; + ext_p = pAdapter->ApCfg.MBSSID[apidx].ExtRate; + } +#endif /* DYNAMIC_RX_RATE_ADJ */ + + /* if A mode, always use fix BasicRateBitMap */ + /*if (pAdapter->CommonCfg.Channel == WMODE_A)*/ + if (pAdapter->CommonCfg.Channel > 14) + { + if (pAdapter->CommonCfg.BasicRateBitmap & 0xF) + { + /* no 11b rate in 5G band */ + pAdapter->CommonCfg.BasicRateBitmapOld = \ + pAdapter->CommonCfg.BasicRateBitmap; + pAdapter->CommonCfg.BasicRateBitmap &= (~0xF); /* no 11b */ + } + + /* force to 6,12,24M in a-band */ + pAdapter->CommonCfg.BasicRateBitmap |= 0x150; /* 6, 12, 24M */ + } + else + { + /* no need to modify in 2.4G (bg mixed) */ + pAdapter->CommonCfg.BasicRateBitmap = \ + pAdapter->CommonCfg.BasicRateBitmapOld; + } + bitmap = pAdapter->CommonCfg.BasicRateBitmap; /* renew bitmap value */ + + if (pAdapter->CommonCfg.BasicRateBitmap > 4095) + { + /* (2 ^ MAX_LEN_OF_SUPPORTED_RATES) -1 */ + return; + } + + for(i=0; iCommonCfg.DesireRate[i] & 0x7f) + { + case 2: Rate = RATE_1; num++; break; + case 4: Rate = RATE_2; num++; break; + case 11: Rate = RATE_5_5; num++; break; + case 22: Rate = RATE_11; num++; break; + case 12: Rate = RATE_6; num++; break; + case 18: Rate = RATE_9; num++; break; + case 24: Rate = RATE_12; num++; break; + case 36: Rate = RATE_18; num++; break; + case 48: Rate = RATE_24; num++; break; + case 72: Rate = RATE_36; num++; break; + case 96: Rate = RATE_48; num++; break; + case 108: Rate = RATE_54; num++; break; + /*default: Rate = RATE_1; break;*/ + } + if (MaxDesire < Rate) MaxDesire = Rate; + } + +/*===========================================================================*/ + do + { +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) + { + UCHAR idx = apidx - MIN_NET_DEVICE_FOR_APCLI; + + if (idx < MAX_APCLI_NUM) + { + wdev = &pAd->ApCfg.ApCliTab[idx].wdev; + break; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid idx(%d)\n", __FUNCTION__, idx)); + return; + } + } +#endif /* APCLI_SUPPORT */ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef WDS_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_WDS) + { + UCHAR idx = apidx - MIN_NET_DEVICE_FOR_WDS; + + if (idx < MAX_WDS_ENTRY) + { + wdev = &pAd->WdsTab.WdsEntry[idx].wdev; + break; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid apidx(%d)\n", __FUNCTION__, apidx)); + return; + } + } +#endif /* WDS_SUPPORT */ + + if ((apidx < pAd->ApCfg.BssidNum) && + (apidx < MAX_MBSSID_NUM(pAd)) && + (apidx < HW_BEACON_MAX_NUM)) + { + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid apidx(%d)\n", __FUNCTION__, apidx)); + } + break; + } +#endif /* CONFIG_AP_SUPPORT */ + + } while(FALSE); + + if (wdev) + { + pHtPhy = &wdev->HTPhyMode; + pMaxHtPhy = &wdev->MaxHTPhyMode; + pMinHtPhy = &wdev->MinHTPhyMode; + + auto_rate_cur_p = &wdev->bAutoTxRateSwitch; + HtMcs = wdev->DesiredTransmitSetting.field.MCS; + } + + pAd->CommonCfg.MaxDesiredRate = MaxDesire; + + if (pMinHtPhy == NULL) + return; + pMinHtPhy->word = 0; + pMaxHtPhy->word = 0; + pHtPhy->word = 0; + + /* + Auto rate switching is enabled only if more than one DESIRED RATES are + specified; otherwise disabled + */ + if (num <= 1) + *auto_rate_cur_p = FALSE; + else + *auto_rate_cur_p = TRUE; + + if (HtMcs != MCS_AUTO) + *auto_rate_cur_p = FALSE; + else + *auto_rate_cur_p = TRUE; + + { + 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; + } + + // TODO: shiang-7603, need to revise for MT7603!! +#if defined(MT7603) || defined(MT7628) + if (IS_MT7603(pAd) || IS_MT7628(pAd)) + ; + else +#endif /* MT7603 */ + { + RTMP_IO_WRITE32(pAd, LEGACY_BASIC_RATE, BasicRateBitmap); + } + + for (i=0; iCommonCfg.ExpectedACKRate[i] = CurrBasicRate; + } + + DBGPRINT(RT_DEBUG_TRACE,("%s():[MaxSupport = %d] = MaxDesire %d Mbps\n", + __FUNCTION__, RateIdToMbps[MaxSupport], RateIdToMbps[MaxDesire])); + /* max tx rate = min {max desire rate, max supported rate}*/ + if (MaxSupport < MaxDesire) + pAd->CommonCfg.MaxTxRate = MaxSupport; + else + pAd->CommonCfg.MaxTxRate = MaxDesire; + + pAd->CommonCfg.MinTxRate = MinSupport; + /* + 2003-07-31 john - 2500 doesn't have good sensitivity at high OFDM rates. to increase the success + ratio of initial DHCP packet exchange, TX rate starts from a lower rate depending + on average RSSI + 1. RSSI >= -70db, start at 54 Mbps (short distance) + 2. -70 > RSSI >= -75, start at 24 Mbps (mid distance) + 3. -75 > RSSI, start at 11 Mbps (long distance) + */ + if (*auto_rate_cur_p) + { + short dbm = 0; +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + dbm =0; +#endif /* CONFIG_AP_SUPPORT */ + if (bLinkUp == TRUE) + pAd->CommonCfg.TxRate = RATE_24; + else + pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; + + if (dbm < -75) + pAd->CommonCfg.TxRate = RATE_11; + else if (dbm < -70) + pAd->CommonCfg.TxRate = RATE_24; + + /* should never exceed MaxTxRate (consider 11B-only mode)*/ + if (pAd->CommonCfg.TxRate > pAd->CommonCfg.MaxTxRate) + pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; + + pAd->CommonCfg.TxRateIndex = 0; + + } + else + { + pAd->CommonCfg.TxRate = pAd->CommonCfg.MaxTxRate; + + /* Choose the Desire Tx MCS in CCK/OFDM mode */ + if (num > RATE_6) + { + if (HtMcs <= MCS_7) + MaxDesire = RxwiMCSToOfdmRate[HtMcs]; + else + MaxDesire = MinSupport; + } + else + { + if (HtMcs <= MCS_3) + MaxDesire = HtMcs; + else + MaxDesire = MinSupport; + } + + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.STBC = pHtPhy->field.STBC; + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.ShortGI = pHtPhy->field.ShortGI; + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MCS = pHtPhy->field.MCS; + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.field.MODE = pHtPhy->field.MODE; + + } + + if (pAd->CommonCfg.TxRate <= RATE_11) + { + pMaxHtPhy->field.MODE = MODE_CCK; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + pMaxHtPhy->field.MCS = MaxDesire; + } +#endif /* CONFIG_AP_SUPPORT */ + + } + else + { + pMaxHtPhy->field.MODE = MODE_OFDM; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + pMaxHtPhy->field.MCS = OfdmRateToRxwiMCS[MaxDesire]; + } +#endif /* CONFIG_AP_SUPPORT */ + + } + + pHtPhy->word = (pMaxHtPhy->word); + if (bLinkUp && (pAd->OpMode == OPMODE_STA)) + { + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word = pHtPhy->word; + pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word = pMaxHtPhy->word; + pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word = pMinHtPhy->word; + } + else + { + if (WMODE_CAP(pAd->CommonCfg.PhyMode, WMODE_B) && + pAd->CommonCfg.Channel <= 14) + { + pAd->CommonCfg.MlmeRate = RATE_1; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_CCK; + pAd->CommonCfg.MlmeTransmit.field.MCS = RATE_1; + pAd->CommonCfg.RtsRate = RATE_11; + } + else + { + pAd->CommonCfg.MlmeRate = RATE_6; + pAd->CommonCfg.RtsRate = RATE_6; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + pAd->CommonCfg.MlmeTransmit.field.MCS = OfdmRateToRxwiMCS[pAd->CommonCfg.MlmeRate]; + } + + /* Keep Basic Mlme Rate.*/ + pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word = pAd->CommonCfg.MlmeTransmit.word; + if (pAd->CommonCfg.MlmeTransmit.field.MODE == MODE_OFDM) + pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = OfdmRateToRxwiMCS[RATE_6]; + else + pAd->MacTab.Content[MCAST_WCID].HTPhyMode.field.MCS = RATE_1; + pAd->CommonCfg.BasicMlmeRate = pAd->CommonCfg.MlmeRate; + +#ifdef CONFIG_AP_SUPPORT +#ifdef MCAST_RATE_SPECIFIC + { + /* set default value if MCastPhyMode is not initialized */ + HTTRANSMIT_SETTING tPhyMode; + + memset(&tPhyMode, 0, sizeof(HTTRANSMIT_SETTING)); + if (memcmp(&pAd->CommonCfg.MCastPhyMode, &tPhyMode, sizeof(HTTRANSMIT_SETTING)) == 0) + { + memmove(&pAd->CommonCfg.MCastPhyMode, &pAd->MacTab.Content[MCAST_WCID].HTPhyMode, + sizeof(HTTRANSMIT_SETTING)); + } + } +#endif /* MCAST_RATE_SPECIFIC */ +#endif /* CONFIG_AP_SUPPORT */ + } + + DBGPRINT(RT_DEBUG_TRACE, (" %s(): (MaxDesire=%d, MaxSupport=%d, MaxTxRate=%d, MinRate=%d, Rate Switching =%d)\n", + __FUNCTION__, RateIdToMbps[MaxDesire], RateIdToMbps[MaxSupport], + RateIdToMbps[pAd->CommonCfg.MaxTxRate], + RateIdToMbps[pAd->CommonCfg.MinTxRate], + /*OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_TX_RATE_SWITCH_ENABLED)*/*auto_rate_cur_p)); + DBGPRINT(RT_DEBUG_TRACE, (" %s(): (TxRate=%d, RtsRate=%d, BasicRateBitmap=0x%04lx)\n", + __FUNCTION__, RateIdToMbps[pAd->CommonCfg.TxRate], + RateIdToMbps[pAd->CommonCfg.RtsRate], BasicRateBitmap)); + DBGPRINT(RT_DEBUG_TRACE, ("%s(): (MlmeTransmit=0x%x, MinHTPhyMode=%x, MaxHTPhyMode=0x%x, HTPhyMode=0x%x)\n", + __FUNCTION__, pAd->CommonCfg.MlmeTransmit.word, + pAd->MacTab.Content[BSSID_WCID].MinHTPhyMode.word, + pAd->MacTab.Content[BSSID_WCID].MaxHTPhyMode.word, + pAd->MacTab.Content[BSSID_WCID].HTPhyMode.word )); +} + + +#ifdef DOT11_N_SUPPORT +/* + ========================================================================== + Description: + This function update HT Rate setting. + Input Wcid value is valid for 2 case : + 1. it's used for Station in infra mode that copy AP rate to Mactable. + 2. OR Station in adhoc mode to copy peer's HT rate to Mactable. + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID MlmeUpdateHtTxRates(RTMP_ADAPTER *pAd, UCHAR apidx) +{ + //UCHAR StbcMcs; + RT_HT_CAPABILITY *pRtHtCap = NULL; + RT_PHY_INFO *pActiveHtPhy = NULL; + //ULONG BasicMCS; + RT_PHY_INFO *pDesireHtPhy = NULL; + PHTTRANSMIT_SETTING pHtPhy = NULL; + PHTTRANSMIT_SETTING pMaxHtPhy = NULL; + PHTTRANSMIT_SETTING pMinHtPhy = NULL; + BOOLEAN *auto_rate_cur_p; + struct wifi_dev *wdev = NULL; + + + DBGPRINT(RT_DEBUG_TRACE,("%s()===> \n", __FUNCTION__)); + + auto_rate_cur_p = NULL; + + do + { +#ifdef CONFIG_AP_SUPPORT + +#ifdef APCLI_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) + { + UCHAR idx = apidx - MIN_NET_DEVICE_FOR_APCLI; + + if (idx < MAX_APCLI_NUM) + { + wdev = &pAd->ApCfg.ApCliTab[idx].wdev; + break; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid idx(%d)\n", __FUNCTION__, idx)); + return; + } + } +#endif /* APCLI_SUPPORT */ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef WDS_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_WDS) + { + UCHAR idx = apidx - MIN_NET_DEVICE_FOR_WDS; + + if (idx < MAX_WDS_ENTRY) + { + wdev = &pAd->WdsTab.WdsEntry[idx].wdev; + break; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid apidx(%d)\n", __FUNCTION__, apidx)); + return; + } + } +#endif /* WDS_SUPPORT */ + + if ((apidx < pAd->ApCfg.BssidNum) && (apidx < HW_BEACON_MAX_NUM)) + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): invalid apidx(%d)\n", __FUNCTION__, apidx)); + } + break; + } +#endif /* CONFIG_AP_SUPPORT */ + + } while (FALSE); + + if (wdev) + { + pDesireHtPhy = &wdev->DesiredHtPhyInfo; + pActiveHtPhy = &wdev->DesiredHtPhyInfo; + pHtPhy = &wdev->HTPhyMode; + pMaxHtPhy = &wdev->MaxHTPhyMode; + pMinHtPhy = &wdev->MinHTPhyMode; + + auto_rate_cur_p = &wdev->bAutoTxRateSwitch; + } + + { + if ((!pDesireHtPhy) || pDesireHtPhy->bHtEnable == FALSE) + return; + + pRtHtCap = &pAd->CommonCfg.DesiredHtPhy; + //StbcMcs = (UCHAR)pAd->CommonCfg.AddHTInfo.AddHtInfo3.StbcMcs; + //BasicMCS = pAd->CommonCfg.AddHTInfo.MCSSet[0]+(pAd->CommonCfg.AddHTInfo.MCSSet[1]<<8)+(StbcMcs<<16); + if ((pAd->CommonCfg.DesiredHtPhy.TxSTBC) && (pAd->Antenna.field.TxPath >= 2)) + pMaxHtPhy->field.STBC = STBC_USE; + else + pMaxHtPhy->field.STBC = STBC_NONE; + } + + /* Decide MAX ht rate.*/ + if ((pRtHtCap->GF) && (pAd->CommonCfg.DesiredHtPhy.GF)) + pMaxHtPhy->field.MODE = MODE_HTGREENFIELD; + else + pMaxHtPhy->field.MODE = MODE_HTMIX; + + if ((pAd->CommonCfg.DesiredHtPhy.ChannelWidth) && (pRtHtCap->ChannelWidth)) + pMaxHtPhy->field.BW = BW_40; + else + pMaxHtPhy->field.BW = BW_20; + + if (pMaxHtPhy->field.BW == BW_20) + pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor20 & pRtHtCap->ShortGIfor20); + else + pMaxHtPhy->field.ShortGI = (pAd->CommonCfg.DesiredHtPhy.ShortGIfor40 & pRtHtCap->ShortGIfor40); + + if (pDesireHtPhy->MCSSet[4] != 0) + { + pMaxHtPhy->field.MCS = 32; + } + + pMaxHtPhy->field.MCS = get_ht_max_mcs(pAd, &pDesireHtPhy->MCSSet[0], + &pActiveHtPhy->MCSSet[0]); + + /* Copy MIN ht rate. rt2860???*/ + pMinHtPhy->field.BW = BW_20; + pMinHtPhy->field.MCS = 0; + pMinHtPhy->field.STBC = 0; + pMinHtPhy->field.ShortGI = 0; + /*If STA assigns fixed rate. update to fixed here.*/ + + + /* Decide ht rate*/ + pHtPhy->field.STBC = pMaxHtPhy->field.STBC; + pHtPhy->field.BW = pMaxHtPhy->field.BW; + pHtPhy->field.MODE = pMaxHtPhy->field.MODE; + pHtPhy->field.MCS = pMaxHtPhy->field.MCS; + pHtPhy->field.ShortGI = pMaxHtPhy->field.ShortGI; + + /* use default now. rt2860*/ + if (pDesireHtPhy->MCSSet[0] != 0xff) + *auto_rate_cur_p = FALSE; + else + *auto_rate_cur_p = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, (" %s():<---.AMsduSize = %d \n", __FUNCTION__, pAd->CommonCfg.DesiredHtPhy.AmsduSize )); + DBGPRINT(RT_DEBUG_TRACE,("TX: MCS[0] = %x (choose %d), BW = %d, ShortGI = %d, MODE = %d, \n", pActiveHtPhy->MCSSet[0],pHtPhy->field.MCS, + pHtPhy->field.BW, pHtPhy->field.ShortGI, pHtPhy->field.MODE)); + DBGPRINT(RT_DEBUG_TRACE,("%s():<=== \n", __FUNCTION__)); +} + + +VOID BATableInit(RTMP_ADAPTER *pAd, BA_TABLE *Tab) +{ + int i; + + Tab->numAsOriginator = 0; + Tab->numAsRecipient = 0; + Tab->numDoneOriginator = 0; + NdisAllocateSpinLock(pAd, &pAd->BATabLock); +#ifdef CONFIG_BA_REORDER_MONITOR +#define REORDERING_PACKET_TIMEOUT ((100 * OS_HZ)/1000) /* system ticks -- 100 ms*/ + pAd->BATable.ba_timeout_check = FALSE; + pAd->BATable.ba_reordering_packet_timeout = REORDERING_PACKET_TIMEOUT; + NdisZeroMemory((UCHAR *)&pAd->BATable.ba_timeout_bitmap[0], sizeof(UINT32) * 16); +#endif + for (i = 0; i < MAX_LEN_OF_BA_REC_TABLE; i++) + { + Tab->BARecEntry[i].REC_BA_Status = Recipient_NONE; + NdisAllocateSpinLock(pAd, &(Tab->BARecEntry[i].RxReRingLock)); + } + for (i = 0; i < MAX_LEN_OF_BA_ORI_TABLE; i++) + { + Tab->BAOriEntry[i].ORI_BA_Status = Originator_NONE; + } +} + + +VOID BATableExit(RTMP_ADAPTER *pAd) +{ + int i; + + for(i=0; iBATable.BARecEntry[i].RxReRingLock); + } + NdisFreeSpinLock(&pAd->BATabLock); +} +#endif /* DOT11_N_SUPPORT */ + + +VOID MlmeRadioOff(RTMP_ADAPTER *pAd) +{ +#ifdef LED_CONTROL_SUPPORT + RTMPSetLED(pAd, LED_RADIO_OFF); +#endif /* LED_CONTROL_SUPPORT */ + +#ifdef RTMP_MAC_PCI + if (IS_PCI_INF(pAd) || IS_RBUS_INF(pAd)) + PciMlmeRadioOFF(pAd); +#endif /* RTMP_MAC_PCI */ +} + + +VOID MlmeRadioOn(RTMP_ADAPTER *pAd) +{ +#ifdef RTMP_MAC_PCI + if (IS_PCI_INF(pAd) || IS_RBUS_INF(pAd)) + PciMlmeRadioOn(pAd); +#endif /* RTMP_MAC_PCI */ +#ifdef LED_CONTROL_SUPPORT + RTMPSetLED(pAd, LED_LINK_UP); +#endif /* LED_CONTROL_SUPPORT */ + +} + + +/*! \brief initialize BSS table + * \param p_tab pointer to the table + * \return none + * \pre + * \post + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + */ +VOID BssTableInit(BSS_TABLE *Tab) +{ + int i; + + Tab->BssNr = 0; + Tab->BssOverlapNr = 0; + + for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++) + { + UCHAR *pOldAddr = Tab->BssEntry[i].pVarIeFromProbRsp; + + NdisZeroMemory(&Tab->BssEntry[i], sizeof(BSS_ENTRY)); + + Tab->BssEntry[i].Rssi = -127; /* initial the rssi as a minimum value */ + if (pOldAddr) + { + RTMPZeroMemory(pOldAddr, MAX_VIE_LEN); + Tab->BssEntry[i].pVarIeFromProbRsp = pOldAddr; + } + } +} + + +/*! \brief search the BSS table by SSID + * \param p_tab pointer to the bss table + * \param ssid SSID string + * \return index of the table, BSS_NOT_FOUND if not in the table + * \pre + * \post + * \note search by sequential search + + IRQL = DISPATCH_LEVEL + + */ +ULONG BssTableSearch(BSS_TABLE *Tab, UCHAR *pBssid, UCHAR Channel) +{ + UCHAR i; + + for (i = 0; i < Tab->BssNr; i++) + { + + /* + Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G. + We should distinguish this case. + */ + if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || + ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && + MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid)) + { + return i; + } + } + return (ULONG)BSS_NOT_FOUND; +} + + +ULONG BssSsidTableSearch( + IN BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR Channel) +{ + UCHAR i; + + for (i = 0; i < Tab->BssNr; i++) + { + + /* Some AP that support A/B/G mode that may used the same BSSID on 11A and 11B/G.*/ + /* We should distinguish this case.*/ + /* */ + if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || + ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && + MAC_ADDR_EQUAL(Tab->BssEntry[i].Bssid, pBssid) && + SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen)) + { + return i; + } + } + return (ULONG)BSS_NOT_FOUND; +} + + +ULONG BssTableSearchWithSSID( + IN BSS_TABLE *Tab, + IN PUCHAR Bssid, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR Channel) +{ + UCHAR i; + + for (i = 0; i < Tab->BssNr; i++) + { + if ((((Tab->BssEntry[i].Channel <= 14) && (Channel <= 14)) || + ((Tab->BssEntry[i].Channel > 14) && (Channel > 14))) && + MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid) && + (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen) || + (NdisEqualMemory(pSsid, ZeroSsid, SsidLen)) || + (NdisEqualMemory(Tab->BssEntry[i].Ssid, ZeroSsid, Tab->BssEntry[i].SsidLen)))) + { + return i; + } + } + return (ULONG)BSS_NOT_FOUND; +} + + +ULONG BssSsidTableSearchBySSID(BSS_TABLE *Tab, UCHAR *pSsid, UCHAR SsidLen) +{ + UCHAR i; + + for (i = 0; i < Tab->BssNr; i++) + { + if (SSID_EQUAL(pSsid, SsidLen, Tab->BssEntry[i].Ssid, Tab->BssEntry[i].SsidLen)) + { + return i; + } + } + return (ULONG)BSS_NOT_FOUND; +} + + +VOID BssTableDeleteEntry(BSS_TABLE *Tab, UCHAR *pBssid, UCHAR Channel) +{ + UCHAR i, j; +#ifdef WH_EZ_SETUP + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("BssTableDeleteEntry called for : %02x-%02x-%02x-%02x-%02x-%02x, Channel=%d\n", + pBssid[0],pBssid[1],pBssid[2],pBssid[3],pBssid[4],pBssid[5],Channel)); +#endif + + 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; + } + } +} + +#ifdef APCLI_OWE_SUPPORT +static VOID update_bss_by_owe_trans(struct _RTMP_ADAPTER *ad, + ULONG bss_idx, + UCHAR *pair_bssid, + UCHAR *pair_ssid, + UCHAR pair_ssid_len) +{ + BSS_ENTRY *extracted_trans_bss = &ad->ScanTab.BssEntry[bss_idx]; + + if (MAC_ADDR_EQUAL(extracted_trans_bss->Bssid, pair_bssid)) { + if (extracted_trans_bss->Hidden == 1) { + /*double confirm the hidden bss is OWE AKM*/ + if (extracted_trans_bss->AuthMode != Ndis802_11AuthModeOWE) + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s : %02x-%02x-%02x-%02x-%02x-%02x, hidden SSID but not OWE_AKM:0x%x!?\n", + __func__, + PRINT_MAC(extracted_trans_bss->Bssid), + extracted_trans_bss->AuthMode)); + + extracted_trans_bss->hide_owe_bss = TRUE; + + extracted_trans_bss->bhas_owe_trans_ie = TRUE; + + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s : %02x-%02x-%02x-%02x-%02x-%02x, update hidden SSID:%s\n", + __func__, + PRINT_MAC(extracted_trans_bss->Bssid), + extracted_trans_bss->Ssid)); + } + } +} +#endif + + +/*! \brief + * \param + * \return + * \pre + * \post + */ +VOID BssEntrySet( + IN RTMP_ADAPTER *pAd, + OUT BSS_ENTRY *pBss, + IN BCN_IE_LIST *ie_list, + IN CHAR Rssi, + IN USHORT LengthVIE, + IN PNDIS_802_11_VARIABLE_IEs pVIE +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + , + IN UCHAR Snr0, + IN UCHAR Snr1 +#endif + ) +{ + COPY_MAC_ADDR(pBss->Bssid, ie_list->Bssid); + /* Default Hidden SSID to be TRUE, it will be turned to FALSE after coping SSID*/ + pBss->Hidden = 1; + pBss->FromBcnReport = ie_list->FromBcnReport; + if (ie_list->SsidLen > 0) + { + /* For hidden SSID AP, it might send beacon with SSID len equal to 0*/ + /* Or send beacon /probe response with SSID len matching real SSID length,*/ + /* but SSID is all zero. such as "00-00-00-00" with length 4.*/ + /* We have to prevent this case overwrite correct table*/ + if (NdisEqualMemory(ie_list->Ssid, ZeroSsid, ie_list->SsidLen) == 0) + { + NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pBss->Ssid, ie_list->Ssid, ie_list->SsidLen); + pBss->SsidLen = ie_list->SsidLen; + pBss->Hidden = 0; + } + } + else + { + /* avoid Hidden SSID form beacon to overwirite correct SSID from probe response */ + if (NdisEqualMemory(pBss->Ssid, ZeroSsid, pBss->SsidLen)) + { + NdisZeroMemory(pBss->Ssid, MAX_LEN_OF_SSID); + pBss->SsidLen = 0; + } + } + + pBss->BssType = ie_list->BssType; + pBss->BeaconPeriod = ie_list->BeaconPeriod; + if (ie_list->BssType == BSS_INFRA) + { + if (ie_list->CfParm.bValid) + { + pBss->CfpCount = ie_list->CfParm.CfpCount; + pBss->CfpPeriod = ie_list->CfParm.CfpPeriod; + pBss->CfpMaxDuration = ie_list->CfParm.CfpMaxDuration; + pBss->CfpDurRemaining = ie_list->CfParm.CfpDurRemaining; + } + } + else + { + pBss->AtimWin = ie_list->AtimWin; + } + + NdisGetSystemUpTime(&pBss->LastBeaconRxTime); + pBss->CapabilityInfo = ie_list->CapabilityInfo; + /* The privacy bit indicate security is ON, it maight be WEP, TKIP or AES*/ + /* Combine with AuthMode, they will decide the connection methods.*/ + pBss->Privacy = CAP_IS_PRIVACY_ON(pBss->CapabilityInfo); + ASSERT(ie_list->SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES); + if (ie_list->SupRateLen <= MAX_LEN_OF_SUPPORTED_RATES) + NdisMoveMemory(pBss->SupRate, ie_list->SupRate, ie_list->SupRateLen); + else + NdisMoveMemory(pBss->SupRate, ie_list->SupRate, MAX_LEN_OF_SUPPORTED_RATES); + pBss->SupRateLen = ie_list->SupRateLen; + ASSERT(ie_list->ExtRateLen <= MAX_LEN_OF_SUPPORTED_RATES); + if (ie_list->ExtRateLen > MAX_LEN_OF_SUPPORTED_RATES) + ie_list->ExtRateLen = MAX_LEN_OF_SUPPORTED_RATES; + NdisMoveMemory(pBss->ExtRate, ie_list->ExtRate, ie_list->ExtRateLen); + pBss->NewExtChanOffset = ie_list->NewExtChannelOffset; + pBss->ExtRateLen = ie_list->ExtRateLen; + pBss->Erp = ie_list-> Erp; + pBss->Channel = ie_list->Channel; + pBss->CentralChannel = ie_list->Channel; + pBss->Rssi = Rssi; +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + pBss->Snr0 = Snr0; + pBss->Snr1 = Snr1; +#endif +#ifdef NEIGHBORING_AP_STAT + pBss->DtimPeriod = ie_list->DtimPeriod; +#endif + /* Update CkipFlag. if not exists, the value is 0x0*/ + pBss->CkipFlag = ie_list->CkipFlag; + + /* New for microsoft Fixed IEs*/ + NdisMoveMemory(pBss->FixIEs.Timestamp, &ie_list->TimeStamp, 8); + pBss->FixIEs.BeaconInterval = ie_list->BeaconPeriod; + pBss->FixIEs.Capabilities = ie_list->CapabilityInfo; +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + pBss->LastBeaconRxTime = jiffies_to_msecs(jiffies); +#endif + +#ifdef APCLI_OWE_SUPPORT + NdisZeroMemory(pBss->owe_trans_ie, MAX_VIE_LEN); + pBss->owe_trans_ie_len = 0; + pBss->bhas_owe_trans_ie = FALSE; +#endif + + /* New for microsoft Variable IEs*/ + if (LengthVIE != 0) + { + pBss->VarIELen = LengthVIE; + NdisMoveMemory(pBss->VarIEs, pVIE, pBss->VarIELen); + } + else + { + pBss->VarIELen = 0; + } + + + pBss->AddHtInfoLen = 0; + pBss->HtCapabilityLen = 0; +#ifdef DOT11_N_SUPPORT + if (ie_list->HtCapabilityLen> 0) + { + pBss->HtCapabilityLen = ie_list->HtCapabilityLen; + NdisMoveMemory(&pBss->HtCapability, &ie_list->HtCapability, ie_list->HtCapabilityLen); + if (ie_list->AddHtInfoLen > 0) + { + pBss->AddHtInfoLen = ie_list->AddHtInfoLen; + NdisMoveMemory(&pBss->AddHtInfo, &ie_list->AddHtInfo, ie_list->AddHtInfoLen); + + pBss->CentralChannel = get_cent_ch_by_htinfo(pAd, &ie_list->AddHtInfo, + &ie_list->HtCapability); + } + +#ifdef DOT11_VHT_AC + if (ie_list->vht_cap_len) { + NdisMoveMemory(&pBss->vht_cap_ie, &ie_list->vht_cap_ie, ie_list->vht_cap_len); + pBss->vht_cap_len = ie_list->vht_cap_len; + } + + if (ie_list->vht_op_len) { + VHT_OP_IE *vht_op; + + NdisMoveMemory(&pBss->vht_op_ie, &ie_list->vht_op_ie, ie_list->vht_op_len); + pBss->vht_op_len = ie_list->vht_op_len; + vht_op = &ie_list->vht_op_ie; + if ((vht_op->vht_op_info.ch_width > 0) && + (ie_list->AddHtInfo.AddHtInfo.ExtChanOffset != EXTCHA_NONE) && + (ie_list->HtCapability.HtCapInfo.ChannelWidth == BW_40) && + (pBss->CentralChannel != ie_list->AddHtInfo.ControlChan)) + { + UCHAR cent_ch; + + cent_ch = vht_cent_ch_freq(pAd, ie_list->AddHtInfo.ControlChan); + DBGPRINT(RT_DEBUG_TRACE, ("%s():VHT cent_ch=%d, vht_op_info->center_freq_1=%d, Bss->CentCh=%d, change from CentralChannel to cent_ch!\n", + __FUNCTION__, cent_ch, vht_op->vht_op_info.center_freq_1, pBss->CentralChannel)); + pBss->CentralChannel = vht_op->vht_op_info.center_freq_1; + } + } +#endif /* DOT11_VHT_AC */ + } +#endif /* DOT11_N_SUPPORT */ + + BssCipherParse(pBss); + + /* new for QOS*/ + if (ie_list->EdcaParm.bValid) + NdisMoveMemory(&pBss->EdcaParm, &ie_list->EdcaParm, sizeof(EDCA_PARM)); + else + pBss->EdcaParm.bValid = FALSE; + if (ie_list->QosCapability.bValid) + NdisMoveMemory(&pBss->QosCapability, &ie_list->QosCapability, sizeof(QOS_CAPABILITY_PARM)); + else + pBss->QosCapability.bValid = FALSE; + if (ie_list->QbssLoad.bValid) + NdisMoveMemory(&pBss->QbssLoad, &ie_list->QbssLoad, sizeof(QBSS_LOAD_PARM)); + else + pBss->QbssLoad.bValid = FALSE; + +#ifdef WH_EZ_SETUP // Rakesh: recognize an easy enabled network only if enabled on own device too, acceptable?? + //! differentiate between EZ and NON Ez beacons from other triband repeaters + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)){ + if (ie_list->vendor_ie.support_easy_setup && !(ie_list->vendor_ie.non_ez_beacon)) + { + pBss->support_easy_setup = 1; + pBss->easy_setup_capability = ie_list->vendor_ie.ez_capability; + } + else + { + //! if it is a non ez beacon, disable EZ setup from that BSS + pBss->non_ez_beacon = ie_list->vendor_ie.non_ez_beacon; + pBss->support_easy_setup = 0; + pBss->easy_setup_capability = 0; + } +#ifdef NEW_CONNECTION_ALGO + ez_update_bss_entry(pBss, ie_list); +#endif + } +#endif /* WH_EZ_SETUP */ + + { + PEID_STRUCT pEid; + USHORT Length = 0; + +#ifdef WSC_INCLUDED + pBss->WpsAP = 0x00; + pBss->WscDPIDFromWpsAP = 0xFFFF; +#endif /* WSC_INCLUDED */ + + pEid = (PEID_STRUCT) pVIE; + while ((Length + 2 + (USHORT)pEid->Len) <= LengthVIE) + { +#define WPS_AP 0x01 + switch(pEid->Eid) + { + case IE_WPA: + if (NdisEqualMemory(pEid->Octet, WPS_OUI, 4) + ) + { +#ifdef WSC_INCLUDED + pBss->WpsAP |= WPS_AP; + WscCheckWpsIeFromWpsAP(pAd, + pEid, + &pBss->WscDPIDFromWpsAP); +#endif /* WSC_INCLUDED */ + break; + } +#ifdef MWDS + check_vendor_ie(pAd, (UCHAR *)pEid, &(ie_list->vendor_ie)); + if(ie_list->vendor_ie.mtk_cap_found) + { + if(ie_list->vendor_ie.support_mwds) + pBss->bSupportMWDS = TRUE; + else + pBss->bSupportMWDS = FALSE; + } +#endif /* MWDS */ +#ifdef APCLI_OWE_SUPPORT + if (NdisEqualMemory(pEid->Octet, OWE_TRANS_OUI, 4)) { + ULONG bss_idx = BSS_NOT_FOUND; + UCHAR pair_ch = 0; + UCHAR pair_bssid[MAC_ADDR_LEN] = {0}; + UCHAR pair_ssid[MAX_LEN_OF_SSID] = {0}; + UCHAR pair_band = 0; + UCHAR pair_ssid_len = 0; + + NdisZeroMemory(pBss->owe_trans_ie, MAX_VIE_LEN); + NdisMoveMemory(pBss->owe_trans_ie, pEid->Octet + 4, pEid->Len - 4); + pBss->owe_trans_ie_len = pEid->Len - 4; + + pBss->bhas_owe_trans_ie = TRUE; + + extract_pair_owe_bss_info(pEid->Octet + 4, + pEid->Len - 4, + pair_bssid, + pair_ssid, + &pair_ssid_len, + &pair_band, + &pair_ch); + if (pair_ch != 0) + bss_idx = BssTableSearch(&pAd->ScanTab, pair_bssid, pair_ch); + else + bss_idx = BssTableSearch(&pAd->ScanTab, + pair_bssid, ie_list->Channel); + + if (bss_idx != BSS_NOT_FOUND) + update_bss_by_owe_trans(pAd, + bss_idx, + pair_bssid, + pair_ssid, + pair_ssid_len); + } +#endif + break; + + } + Length = Length + 2 + (USHORT)pEid->Len; /* Eid[1] + Len[1]+ content[Len]*/ + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + } +} + + + +/*! + * \brief insert an entry into the bss table + * \param p_tab The BSS table + * \param Bssid BSSID + * \param ssid SSID + * \param ssid_len Length of SSID + * \param bss_type + * \param beacon_period + * \param timestamp + * \param p_cf + * \param atim_win + * \param cap + * \param rates + * \param rates_len + * \param channel_idx + * \return none + * \pre + * \post + * \note If SSID is identical, the old entry will be replaced by the new one + + IRQL = DISPATCH_LEVEL + + */ +ULONG BssTableSetEntry( + IN PRTMP_ADAPTER pAd, + OUT BSS_TABLE *Tab, + IN BCN_IE_LIST *ie_list, + IN CHAR Rssi, + IN USHORT LengthVIE, + IN PNDIS_802_11_VARIABLE_IEs pVIE +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + , + IN UCHAR Snr0, + IN UCHAR Snr1 +#endif + ) +{ + ULONG Idx; +#ifdef APCLI_SUPPORT + BOOLEAN bInsert = FALSE; + PAPCLI_STRUCT pApCliEntry = NULL; + UCHAR i; +#endif /* APCLI_SUPPORT */ + + + Idx = BssTableSearch(Tab, ie_list->Bssid, ie_list->Channel); + if (Idx == BSS_NOT_FOUND) + { + if (Tab->BssNr >= MAX_LEN_OF_BSS_TABLE) + { + /* + It may happen when BSS Table was full. + The desired AP will not be added into BSS Table + In this case, if we found the desired AP then overwrite BSS Table. + */ +#ifdef APCLI_SUPPORT + for (i = 0; i < pAd->ApCfg.ApCliNum; i++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[i]; + if (MAC_ADDR_EQUAL(pApCliEntry->MlmeAux.Bssid, ie_list->Bssid) + || SSID_EQUAL(pApCliEntry->MlmeAux.Ssid, pApCliEntry->MlmeAux.SsidLen, ie_list->Ssid, ie_list->SsidLen)) + { + bInsert = TRUE; + break; + } + } +#endif /* APCLI_SUPPORT */ + if(!OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED) || + !OPSTATUS_TEST_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED)) + { + if (MAC_ADDR_EQUAL(pAd->ScanCtrl.Bssid, ie_list->Bssid) || + SSID_EQUAL(pAd->ScanCtrl.Ssid, pAd->ScanCtrl.SsidLen, ie_list->Ssid, ie_list->SsidLen) +#ifdef APCLI_SUPPORT + || bInsert +#endif /* APCLI_SUPPORT */ + ) + { + Idx = Tab->BssOverlapNr; + NdisZeroMemory(&(Tab->BssEntry[Idx]), sizeof(BSS_ENTRY)); + BssEntrySet(pAd, &Tab->BssEntry[Idx], ie_list, Rssi, LengthVIE, pVIE +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + , Snr0, Snr1 +#endif + ); + 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], ie_list, Rssi, LengthVIE, pVIE +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + , Snr0, Snr1 +#endif + ); + Tab->BssNr++; + } + else + { + BssEntrySet(pAd, &Tab->BssEntry[Idx], ie_list, Rssi, LengthVIE, pVIE +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + , Snr0, Snr1 +#endif + ); + } + + return Idx; +} + + + +#if (defined(CONFIG_STA_SUPPORT) || defined(WH_EZ_SETUP)) +UCHAR wmode_2_rfic(UCHAR PhyMode) +{ + if(WMODE_CAP_2G(PhyMode) && WMODE_CAP_5G(PhyMode)) + { + return RFIC_DUAL_BAND; + }else + if(WMODE_CAP_2G(PhyMode)) + { + return RFIC_24GHZ; + }else + if(WMODE_CAP_5G(PhyMode)) + { + return RFIC_5GHZ; + } + return RFIC_24GHZ; +} +//#ifdef WH_EZ_SETUP +VOID BssTableSsidSort( + IN RTMP_ADAPTER *pAd, + IN struct wifi_dev *wdev, + OUT BSS_TABLE *OutTab, + IN CHAR Ssid[], + IN UCHAR SsidLen) +{ + INT i; +#ifdef WSC_STA_SUPPORT + PWSC_CTRL pWpsCtrl = &pAd->StaCfg.WscControl; +#endif /* WSC_STA_SUPPORT */ + //struct wifi_dev *wdev = &pAd->StaCfg.wdev; +#ifdef WH_EZ_SETUP + UCHAR RfIC; + UCHAR BssType; +#endif + + BssTableInit(OutTab); + +#ifdef WH_EZ_SETUP + BssType = BSS_INFRA; +#endif + + +#ifdef WH_EZ_SETUP + RfIC = wmode_2_rfic(wdev->PhyMode); +#endif + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + BSS_ENTRY *pInBss = &pAd->ScanTab.BssEntry[i]; + BOOLEAN bIsHiddenApIncluded = FALSE; + +#ifdef WH_EZ_SETUP +#ifdef NEW_CONNECTION_ALGO + if(IS_EZ_SETUP_ENABLED(wdev)) + { + if (ez_is_weight_same(wdev,pInBss->beacon_info.network_weight)) + { + continue; + } + } + +#endif +#endif + + if (((pAd->CommonCfg.bIEEE80211H == 1) && +#ifdef WH_EZ_SETUP + (RfIC & RFIC_5GHZ) && +#else + (pAd->MlmeAux.Channel > 14) && +#endif + RadarChannelCheck(pAd, pInBss->Channel)) +#ifdef WIFI_REGION32_HIDDEN_SSID_SUPPORT + ||((pInBss->Channel == 12) || (pInBss->Channel == 13)) +#endif /* WIFI_REGION32_HIDDEN_SSID_SUPPORT */ +#ifdef CARRIER_DETECTION_SUPPORT /* Roger sync Carrier */ + || (pAd->CommonCfg.CarrierDetect.Enable == TRUE) +#endif /* CARRIER_DETECTION_SUPPORT */ + ) + { + if (pInBss->Hidden) + bIsHiddenApIncluded = TRUE; + } +#if(defined(DBDC_MODE) && defined(WH_EZ_SETUP)) + if( (pAd->CommonCfg.dbdc_mode) && (IS_EZ_SETUP_ENABLED(wdev)) ){ + if( ( WMODE_2G_ONLY(wdev->PhyMode) && (pInBss->Channel <= 14) ) || + ( WMODE_5G_ONLY(wdev->PhyMode) && (pInBss->Channel > 14) ) ) + { + // Own band network + } + else{ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_OFF,("Ignore Other Band network.\n")); + continue; + } + } +#endif + + + if ( +#ifdef WH_EZ_SETUP + (pInBss->BssType == BssType) && +#else + (pInBss->BssType == pAd->StaCfg.BssType) && +#endif + (SSID_EQUAL(Ssid, SsidLen, pInBss->Ssid, pInBss->SsidLen) || bIsHiddenApIncluded)) + { + BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; + +#ifdef DOT11_N_SUPPORT + /* 2.4G/5G N only mode*/ + if ((pInBss->HtCapabilityLen == 0) && + (WMODE_HT_ONLY(pAd->CommonCfg.PhyMode))) + { + DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n")); + continue; + } + + if ((pAd->CommonCfg.PhyMode == (WMODE_G | WMODE_GN)) && + ((pInBss->SupRateLen + pInBss->ExtRateLen) < 12)) + { + DBGPRINT(RT_DEBUG_TRACE,("STA is in GN-only Mode, this AP is in B mode.\n")); + continue; + } +#endif /* DOT11_N_SUPPORT */ + + + + /* New for WPA2*/ + /* Check the Authmode first*/ + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + { + /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode*/ + if ((wdev->AuthMode != pInBss->AuthMode) && (wdev->AuthMode != pInBss->AuthModeAux)) + /* None matched*/ + continue; + + /* Check cipher suite, AP must have more secured cipher than station setting*/ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) + { + /* If it's not mixed mode, we should only let BSS pass with the same encryption*/ + if (pInBss->WPA.bMixMode == FALSE) + if (wdev->WepStatus != pInBss->WPA.GroupCipher) + continue; + + /* check group cipher*/ + if ((wdev->WepStatus < pInBss->WPA.GroupCipher) && + (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP40Enabled) && + (pInBss->WPA.GroupCipher != Ndis802_11GroupWEP104Enabled)) + continue; + + /* check pairwise cipher, skip if none matched*/ + /* If profile set to AES, let it pass without question.*/ + /* If profile set to TKIP, we must find one mateched*/ + if ((wdev->WepStatus == Ndis802_11TKIPEnable) && + (wdev->WepStatus != pInBss->WPA.PairCipher) && + (wdev->WepStatus != pInBss->WPA.PairCipherAux)) + continue; + } + else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + /* If it's not mixed mode, we should only let BSS pass with the same encryption*/ + if (pInBss->WPA2.bMixMode == FALSE) + if (wdev->WepStatus != pInBss->WPA2.GroupCipher) + continue; + + /* check group cipher*/ + if ((wdev->WepStatus < pInBss->WPA.GroupCipher) && + (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP40Enabled) && + (pInBss->WPA2.GroupCipher != Ndis802_11GroupWEP104Enabled)) + continue; + + /* check pairwise cipher, skip if none matched*/ + /* If profile set to AES, let it pass without question.*/ + /* If profile set to TKIP, we must find one mateched*/ + if ((wdev->WepStatus == Ndis802_11TKIPEnable) && + (wdev->WepStatus != pInBss->WPA2.PairCipher) && + (wdev->WepStatus != pInBss->WPA2.PairCipherAux)) + continue; + } +#ifdef WAPI_SUPPORT + else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK)) + { + /* check cipher algorithm*/ + if ((wdev->WepStatus != pInBss->WAPI.GroupCipher) || + (wdev->WepStatus != pInBss->WAPI.PairCipher)) + continue; + } +#endif /* WAPI_SUPPORT */ + } + /* Bss Type matched, SSID matched. */ + /* We will check wepstatus for qualification Bss*/ + else if (wdev->WepStatus != pInBss->WepStatus) + { + DBGPRINT(RT_DEBUG_TRACE,("StaCfg.WepStatus=%d, while pInBss->WepStatus=%d\n", wdev->WepStatus, pInBss->WepStatus)); + + /* For the SESv2 case, we will not qualify WepStatus.*/ + + if (!pInBss->bSES) + continue; + } + + /* Since the AP is using hidden SSID, and we are trying to connect to ANY*/ + /* It definitely will fail. So, skip it.*/ + /* CCX also require not even try to connect it!!*/ + if (SsidLen == 0) + continue; + + /* copy matching BSS from InTab to OutTab*/ + NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); + + OutTab->BssNr++; + } + else if ( +#ifdef WH_EZ_SETUP + (pInBss->BssType == BssType) && +#else + (pInBss->BssType == pAd->StaCfg.BssType) && +#endif + (SsidLen == 0)) + { + BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; + +#ifdef WSC_STA_SUPPORT + if ((pWpsCtrl->WscConfMode != WSC_DISABLE) && pWpsCtrl->bWscTrigger) + { + /* copy matching BSS from InTab to OutTab*/ + NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); + OutTab->BssNr++; + continue; + } +#endif /* WSC_STA_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + /* 2.4G/5G N only mode*/ + if ((pInBss->HtCapabilityLen == 0) && + WMODE_HT_ONLY(pAd->CommonCfg.PhyMode)) + { + DBGPRINT(RT_DEBUG_TRACE,("STA is in N-only Mode, this AP don't have Ht capability in Beacon.\n")); + continue; + } + + if ((pAd->CommonCfg.PhyMode == (WMODE_G | WMODE_GN)) && + ((pInBss->SupRateLen + pInBss->ExtRateLen) < 12)) + { + DBGPRINT(RT_DEBUG_TRACE,("STA is in GN-only Mode, this AP is in B mode.\n")); + continue; + } +#endif /* DOT11_N_SUPPORT */ + + /* New for WPA2*/ + /* Check the Authmode first*/ + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + { + /* Check AuthMode and AuthModeAux for matching, in case AP support dual-mode*/ + if ((wdev->AuthMode != pInBss->AuthMode) && (wdev->AuthMode != pInBss->AuthModeAux)) + /* None matched*/ + continue; + + /* Check cipher suite, AP must have more secured cipher than station setting*/ + if ((wdev->AuthMode == Ndis802_11AuthModeWPA) || (wdev->AuthMode == Ndis802_11AuthModeWPAPSK)) + { + /* If it's not mixed mode, we should only let BSS pass with the same encryption*/ + if (pInBss->WPA.bMixMode == FALSE) + if (wdev->WepStatus != pInBss->WPA.GroupCipher) + continue; + + /* check group cipher*/ + if (wdev->WepStatus < pInBss->WPA.GroupCipher) + continue; + + /* check pairwise cipher, skip if none matched*/ + /* If profile set to AES, let it pass without question.*/ + /* If profile set to TKIP, we must find one mateched*/ + if ((wdev->WepStatus == Ndis802_11TKIPEnable) && + (wdev->WepStatus != pInBss->WPA.PairCipher) && + (wdev->WepStatus != pInBss->WPA.PairCipherAux)) + continue; + } + else if ((wdev->AuthMode == Ndis802_11AuthModeWPA2) || (wdev->AuthMode == Ndis802_11AuthModeWPA2PSK)) + { + /* If it's not mixed mode, we should only let BSS pass with the same encryption*/ + if (pInBss->WPA2.bMixMode == FALSE) + if (wdev->WepStatus != pInBss->WPA2.GroupCipher) + continue; + + /* check group cipher*/ + if (wdev->WepStatus < pInBss->WPA2.GroupCipher) + continue; + + /* check pairwise cipher, skip if none matched*/ + /* If profile set to AES, let it pass without question.*/ + /* If profile set to TKIP, we must find one mateched*/ + if ((wdev->WepStatus == Ndis802_11TKIPEnable) && + (wdev->WepStatus != pInBss->WPA2.PairCipher) && + (wdev->WepStatus != pInBss->WPA2.PairCipherAux)) + continue; + } +#ifdef WAPI_SUPPORT + else if ((wdev->AuthMode == Ndis802_11AuthModeWAICERT) || (wdev->AuthMode == Ndis802_11AuthModeWAIPSK)) + { + /* check cipher algorithm*/ + if ((wdev->WepStatus != pInBss->WAPI.GroupCipher) || + (wdev->WepStatus != pInBss->WAPI.PairCipher)) + continue; + } +#endif /* WAPI_SUPPORT */ + } + /* Bss Type matched, SSID matched. */ + /* We will check wepstatus for qualification Bss*/ + else if (wdev->WepStatus != pInBss->WepStatus) + continue; + + /* copy matching BSS from InTab to OutTab*/ + NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); + + OutTab->BssNr++; + } +#ifdef WSC_STA_SUPPORT + else if ((pWpsCtrl->WscConfMode != WSC_DISABLE) && + (pWpsCtrl->bWscTrigger) && + MAC_ADDR_EQUAL(pWpsCtrl->WscBssid, pInBss->Bssid)) + { + BSS_ENTRY *pOutBss = &OutTab->BssEntry[OutTab->BssNr]; + + /* copy matching BSS from InTab to OutTab*/ + NdisMoveMemory(pOutBss, pInBss, sizeof(BSS_ENTRY)); + + /* + Linksys WRT610N WPS AP will change the SSID from linksys to linksys_WPS_ + when the Linksys WRT610N is in the state 'WPS Unconfigured' after set to factory default. + */ + NdisZeroMemory(pAd->MlmeAux.Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.Ssid, pInBss->Ssid, pInBss->SsidLen); + pAd->MlmeAux.SsidLen = pInBss->SsidLen; + + + /* Update Reconnect Ssid, that user desired to connect.*/ + + NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.Ssid, pAd->MlmeAux.SsidLen); + pAd->MlmeAux.AutoReconnectSsidLen = pAd->MlmeAux.SsidLen; + + OutTab->BssNr++; + continue; + } +#endif /* WSC_STA_SUPPORT */ + + if (OutTab->BssNr >= MAX_LEN_OF_BSS_TABLE) + break; + } + + BssTableSortByRssi(OutTab, FALSE); +} + +#endif +/*#if defined(CONFIG_STA_SUPPORT) || defined(APCLI_AUTO_CONNECT_SUPPORT) || defined(WH_EZ_SETUP)*/ +/* IRQL = DISPATCH_LEVEL*/ +VOID BssTableSortByRssi( + IN OUT BSS_TABLE *OutTab, + IN BOOLEAN isInverseOrder) +{ + INT i, j; + BSS_ENTRY *pTmpBss = NULL; + + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&pTmpBss, sizeof(BSS_ENTRY)); + if (pTmpBss == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + + for (i = 0; i < OutTab->BssNr - 1; i++) + { + for (j = i+1; j < OutTab->BssNr; j++) + { + if (OutTab->BssEntry[j].Rssi > OutTab->BssEntry[i].Rssi ? + !isInverseOrder : isInverseOrder) + { + if (OutTab->BssEntry[j].Rssi != OutTab->BssEntry[i].Rssi ) + { + NdisMoveMemory(pTmpBss, &OutTab->BssEntry[j], sizeof(BSS_ENTRY)); + NdisMoveMemory(&OutTab->BssEntry[j], &OutTab->BssEntry[i], sizeof(BSS_ENTRY)); + NdisMoveMemory(&OutTab->BssEntry[i], pTmpBss, sizeof(BSS_ENTRY)); + } + } + } + } + + if (pTmpBss != NULL) + os_free_mem(NULL, pTmpBss); +} +/*#endif defined(CONFIG_STA_SUPPORT) || defined(APCLI_AUTO_CONNECT_SUPPORT) */ + +VOID BssCipherParse(BSS_ENTRY *pBss) +{ + PEID_STRUCT pEid; + PUCHAR pTmp; + PRSN_IE_HEADER_STRUCT pRsnHeader; + PCIPHER_SUITE_STRUCT pCipher; + PAKM_SUITE_STRUCT pAKM; + USHORT Count; + INT Length; + NDIS_802_11_ENCRYPTION_STATUS TmpCipher; +#ifdef APCLI_SECURITY_IMPROVEMENT_SUPPORT + UCHAR end_field = 0; + UCHAR res = TRUE; +#endif + + + /* WepStatus will be reset later, if AP announce TKIP or AES on the beacon frame.*/ + + if (pBss->Privacy) + { + pBss->WepStatus = Ndis802_11WEPEnabled; + } + else + { + pBss->WepStatus = Ndis802_11WEPDisabled; + } + /* Set default to disable & open authentication before parsing variable IE*/ + pBss->AuthMode = Ndis802_11AuthModeOpen; + pBss->AuthModeAux = Ndis802_11AuthModeOpen; +#ifdef DOT11W_PMF_SUPPORT + pBss->IsSupportSHA256KeyDerivation = FALSE; +#endif /* DOT11W_PMF_SUPPORT */ + + /* Init WPA setting*/ + pBss->WPA.PairCipher = Ndis802_11WEPDisabled; + pBss->WPA.PairCipherAux = Ndis802_11WEPDisabled; + pBss->WPA.GroupCipher = Ndis802_11WEPDisabled; + pBss->WPA.RsnCapability = 0; + pBss->WPA.bMixMode = FALSE; + + /* Init WPA2 setting*/ + pBss->WPA2.PairCipher = Ndis802_11WEPDisabled; + pBss->WPA2.PairCipherAux = Ndis802_11WEPDisabled; + pBss->WPA2.GroupCipher = Ndis802_11WEPDisabled; + pBss->WPA2.RsnCapability = 0; + pBss->WPA2.bMixMode = FALSE; + +#ifdef WAPI_SUPPORT + /* Init WAPI setting*/ + pBss->WAPI.PairCipher = Ndis802_11WEPDisabled; + pBss->WAPI.PairCipherAux = Ndis802_11WEPDisabled; + pBss->WAPI.GroupCipher = Ndis802_11WEPDisabled; + pBss->WAPI.RsnCapability = 0; + pBss->WAPI.bMixMode = FALSE; +#endif /* WAPI_SUPPORT */ + + Length = (INT) pBss->VarIELen; + + while (Length > 0) + { + /* Parse cipher suite base on WPA1 & WPA2, they should be parsed differently*/ + pTmp = ((PUCHAR) pBss->VarIEs) + pBss->VarIELen - Length; + pEid = (PEID_STRUCT) pTmp; + switch (pEid->Eid) + { + case IE_WPA: + if (NdisEqualMemory(pEid->Octet, SES_OUI, 3) && (pEid->Len == 7)) + { + pBss->bSES = TRUE; + break; + } + else if (NdisEqualMemory(pEid->Octet, WPA_OUI, 4) != 1) + { + /* if unsupported vendor specific IE*/ + break; + } + /* + Skip OUI, version, and multicast suite + This part should be improved in the future when AP supported multiple cipher suite. + For now, it's OK since almost all APs have fixed cipher suite supported. + */ + /* pTmp = (PUCHAR) pEid->Octet;*/ + pTmp += 11; + + /* + Cipher Suite Selectors from Spec P802.11i/D3.2 P26. + Value Meaning + 0 None + 1 WEP-40 + 2 Tkip + 3 WRAP + 4 AES + 5 WEP-104 + */ + /* Parse group cipher*/ + switch (*pTmp) + { + case 1: + pBss->WPA.GroupCipher = Ndis802_11GroupWEP40Enabled; + break; + case 5: + pBss->WPA.GroupCipher = Ndis802_11GroupWEP104Enabled; + break; + case 2: + pBss->WPA.GroupCipher = Ndis802_11TKIPEnable; + break; + case 4: + pBss->WPA.GroupCipher = Ndis802_11AESEnable; + break; + default: + break; + } + /* number of unicast suite*/ + pTmp += 1; + + /* skip all unicast cipher suites*/ + /*Count = *(PUSHORT) pTmp; */ + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + /* Parsing all unicast cipher suite*/ + while (Count > 0) + { + /* Skip OUI*/ + pTmp += 3; + TmpCipher = Ndis802_11WEPDisabled; + switch (*pTmp) + { + case 1: + case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway*/ + TmpCipher = Ndis802_11WEPEnabled; + break; + case 2: + TmpCipher = Ndis802_11TKIPEnable; + break; + case 4: + TmpCipher = Ndis802_11AESEnable; + break; + default: + break; + } + if (TmpCipher > pBss->WPA.PairCipher) + { + /* Move the lower cipher suite to PairCipherAux*/ + pBss->WPA.PairCipherAux = pBss->WPA.PairCipher; + pBss->WPA.PairCipher = TmpCipher; + } + else + { + pBss->WPA.PairCipherAux = TmpCipher; + } + pTmp++; + Count--; + } + + /* 4. get AKM suite counts*/ + /*Count = *(PUSHORT) pTmp;*/ + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + pTmp += 3; + + switch (*pTmp) + { + case 1: + /* Set AP support WPA-enterprise mode*/ + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPA; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPA; + break; + case 2: + /* Set AP support WPA-PSK mode*/ + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPAPSK; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPAPSK; + break; + default: + break; + } + pTmp += 1; + + /* Fixed for WPA-None*/ + if (pBss->BssType == BSS_ADHOC) + { + pBss->AuthMode = Ndis802_11AuthModeWPANone; + pBss->AuthModeAux = Ndis802_11AuthModeWPANone; + pBss->WepStatus = pBss->WPA.GroupCipher; + /* Patched bugs for old driver*/ + if (pBss->WPA.PairCipherAux == Ndis802_11WEPDisabled) + pBss->WPA.PairCipherAux = pBss->WPA.GroupCipher; + } + else + pBss->WepStatus = pBss->WPA.PairCipher; + + /* Check the Pair & Group, if different, turn on mixed mode flag*/ + if (pBss->WPA.GroupCipher != pBss->WPA.PairCipher) + pBss->WPA.bMixMode = TRUE; + + break; + + case IE_RSN: + pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp; +#ifdef APCLI_SECURITY_IMPROVEMENT_SUPPORT + res = wpa_rsne_sanity(pTmp, le2cpu16(pRsnHeader->Length) + 2, &end_field); + if (res == FALSE) + break; + + if (end_field < RSN_FIELD_GROUP_CIPHER) + pBss->WPA2.GroupCipher = Ndis802_11AESEnable; + if (end_field < RSN_FIELD_PAIRWISE_CIPHER) + pBss->WPA2.GroupCipher = Ndis802_11AESEnable; + if (end_field < RSN_FIELD_AKM) + pBss->AuthMode = Ndis802_11AuthModeWPA2PSK; +#endif + /* 0. Version must be 1*/ + if (le2cpu16(pRsnHeader->Version) != 1) + break; + pTmp += sizeof(RSN_IE_HEADER_STRUCT); + + /* 1. Check group cipher*/ +#ifdef APCLI_SECURITY_IMPROVEMENT_SUPPORT + if (end_field < RSN_FIELD_GROUP_CIPHER) + break; +#endif + pCipher = (PCIPHER_SUITE_STRUCT) pTmp; + if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) + break; + + /* Parse group cipher*/ + switch (pCipher->Type) + { + case 1: + pBss->WPA2.GroupCipher = Ndis802_11GroupWEP40Enabled; + break; + case 5: + pBss->WPA2.GroupCipher = Ndis802_11GroupWEP104Enabled; + break; + case 2: + pBss->WPA2.GroupCipher = Ndis802_11TKIPEnable; + break; + case 4: + pBss->WPA2.GroupCipher = Ndis802_11AESEnable; + break; + default: + break; + } + /* set to correct offset for next parsing*/ + pTmp += sizeof(CIPHER_SUITE_STRUCT); + + /* 2. Get pairwise cipher counts*/ +#ifdef APCLI_SECURITY_IMPROVEMENT_SUPPORT + if (end_field < RSN_FIELD_PAIRWISE_CIPHER) + break; +#endif + /*Count = *(PUSHORT) pTmp;*/ + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + /* 3. Get pairwise cipher*/ + /* Parsing all unicast cipher suite*/ + while (Count > 0) + { + /* Skip OUI*/ + pCipher = (PCIPHER_SUITE_STRUCT) pTmp; + TmpCipher = Ndis802_11WEPDisabled; + switch (pCipher->Type) + { + case 1: + case 5: /* Although WEP is not allowed in WPA related auth mode, we parse it anyway*/ + TmpCipher = Ndis802_11WEPEnabled; + break; + case 2: + TmpCipher = Ndis802_11TKIPEnable; + break; + case 4: + TmpCipher = Ndis802_11AESEnable; + break; + default: + break; + } + if (TmpCipher > pBss->WPA2.PairCipher) + { + /* Move the lower cipher suite to PairCipherAux*/ + pBss->WPA2.PairCipherAux = pBss->WPA2.PairCipher; + pBss->WPA2.PairCipher = TmpCipher; + } + else + { + pBss->WPA2.PairCipherAux = TmpCipher; + } + pTmp += sizeof(CIPHER_SUITE_STRUCT); + Count--; + } + + /* 4. get AKM suite counts*/ +#ifdef APCLI_SECURITY_IMPROVEMENT_SUPPORT + if (end_field < RSN_FIELD_AKM) + break; +#endif + /*Count = *(PUSHORT) pTmp;*/ + Count = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + /* 5. Get AKM ciphers*/ + /* Parsing all AKM ciphers*/ + while (Count > 0) + { + pAKM = (PAKM_SUITE_STRUCT) pTmp; + if (!RTMPEqualMemory(pTmp, RSN_OUI, 3)) + break; + + switch (pAKM->Type) + { + case 0: + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPANone; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPANone; + break; + case 1: +#ifdef DOT11R_FT_SUPPORT + case 3: +#endif /* DOT11R_FT_SUPPORT */ + /* Set AP support WPA-enterprise mode*/ + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPA2; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPA2; + break; + case 2: +#ifdef DOT11R_FT_SUPPORT + case 4: +#endif /* DOT11R_FT_SUPPORT */ +#ifdef DOT11W_PMF_SUPPORT + case 6: +#endif /* DOT11W_PMF_SUPPORT */ + /* Set AP support WPA-PSK mode*/ + if (pBss->AuthMode == Ndis802_11AuthModeOpen) + pBss->AuthMode = Ndis802_11AuthModeWPA2PSK; + else + pBss->AuthModeAux = Ndis802_11AuthModeWPA2PSK; + +#ifdef DOT11W_PMF_SUPPORT + if (pAKM->Type == 6) + pBss->IsSupportSHA256KeyDerivation = TRUE; +#endif /* DOT11W_PMF_SUPPORT */ + + break; +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + case 8: + pBss->AuthMode = Ndis802_11AuthModeWPA3PSK; + break; + + case 18: + pBss->AuthMode = Ndis802_11AuthModeOWE; + break; +#endif + + 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*/ +#ifdef APCLI_SECURITY_IMPROVEMENT_SUPPORT + if (end_field < RSN_FIELD_RSN_CAP) + break; +#endif + /*pBss->WPA2.RsnCapability = *(PUSHORT) pTmp;*/ + pBss->WPA2.RsnCapability = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + /* Check the Pair & Group, if different, turn on mixed mode flag*/ + if (pBss->WPA2.GroupCipher != pBss->WPA2.PairCipher) + pBss->WPA2.bMixMode = TRUE; + + break; +#ifdef WAPI_SUPPORT + case IE_WAPI: + pRsnHeader = (PRSN_IE_HEADER_STRUCT) pTmp; + + /* 0. The version number must be 1*/ + if (le2cpu16(pRsnHeader->Version) != 1) + break; + pTmp += sizeof(RSN_IE_HEADER_STRUCT); + + /* 1. Get AKM suite counts*/ + NdisMoveMemory(&Count, pTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + pTmp += sizeof(USHORT); + + /* 2. Get AKM ciphers*/ + pAKM = (PAKM_SUITE_STRUCT) pTmp; + if (!RTMPEqualMemory(pTmp, WAPI_OUI, 3)) + break; + + switch (pAKM->Type) + { + case 1: + /* Support WAI certificate authentication*/ + pBss->AuthMode = Ndis802_11AuthModeWAICERT; + break; + case 2: + /* Support WAI PSK*/ + pBss->AuthMode = Ndis802_11AuthModeWAIPSK; + break; + default: + break; + } + pTmp += (Count * sizeof(AKM_SUITE_STRUCT)); + + /* 3. Get pairwise cipher counts*/ + NdisMoveMemory(&Count, pTmp, sizeof(USHORT)); + Count = cpu2le16(Count); + pTmp += sizeof(USHORT); + + /* 4. Get pairwise cipher*/ + /* Parsing all unicast cipher suite*/ + while (Count > 0) + { + if (!RTMPEqualMemory(pTmp, WAPI_OUI, 3)) + break; + + /* Skip OUI*/ + pCipher = (PCIPHER_SUITE_STRUCT) pTmp; + TmpCipher = Ndis802_11WEPDisabled; + switch (pCipher->Type) + { + case 1: + TmpCipher = Ndis802_11EncryptionSMS4Enabled; + break; + default: + break; + } + + if (TmpCipher > pBss->WAPI.PairCipher) + { + /* Move the lower cipher suite to PairCipherAux*/ + pBss->WAPI.PairCipherAux = pBss->WAPI.PairCipher; + pBss->WAPI.PairCipher = TmpCipher; + } + else + { + pBss->WAPI.PairCipherAux = TmpCipher; + } + pTmp += sizeof(CIPHER_SUITE_STRUCT); + Count--; + } + + /* 5. Check group cipher*/ + if (!RTMPEqualMemory(pTmp, WAPI_OUI, 3)) + break; + + pCipher = (PCIPHER_SUITE_STRUCT) pTmp; + /* Parse group cipher*/ + switch (pCipher->Type) + { + case 1: + pBss->WAPI.GroupCipher = Ndis802_11EncryptionSMS4Enabled; + break; + default: + break; + } + /* set to correct offset for next parsing*/ + pTmp += sizeof(CIPHER_SUITE_STRUCT); + + /* update the encryption type*/ + pBss->WepStatus = pBss->WAPI.PairCipher; + + /* update the WAPI capability*/ + pBss->WAPI.RsnCapability = (pTmp[1]<<8) + pTmp[0]; + pTmp += sizeof(USHORT); + + break; +#endif /* WAPI_SUPPORT */ + default: + break; + } + Length -= (pEid->Len + 2); + } +} + + +/*! \brief generates a random mac address value for IBSS BSSID + * \param Addr the bssid location + * \return none + * \pre + * \post + */ +VOID MacAddrRandomBssid(RTMP_ADAPTER *pAd, UCHAR *pAddr) +{ + INT i; + + for (i = 0; i < MAC_ADDR_LEN; i++) + { + pAddr[i] = RandomByte(pAd); + } + + pAddr[0] = (pAddr[0] & 0xfe) | 0x02; /* the first 2 bits must be 01xxxxxxxx*/ +} + + +/* + ========================================================================== + 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; +} + + +/*! \brief init the management mac frame header + * \param p_hdr mac header + * \param subtype subtype of the frame + * \param p_ds destination address, don't care if it is a broadcast address + * \return none + * \pre the station has the following information in the pAd->StaCfg + * - bssid + * - station address + * \post + * \note this function initializes the following field + */ +VOID MgtMacHeaderInit( + IN RTMP_ADAPTER *pAd, + INOUT HEADER_802_11 *pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN UCHAR *pDA, + IN UCHAR *pSA, + IN UCHAR *pBssid) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + + pHdr80211->FC.Type = FC_TYPE_MGMT; + pHdr80211->FC.SubType = SubType; + pHdr80211->FC.ToDs = ToDs; + COPY_MAC_ADDR(pHdr80211->Addr1, pDA); +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + COPY_MAC_ADDR(pHdr80211->Addr2, pBssid); +#endif /* CONFIG_AP_SUPPORT */ + COPY_MAC_ADDR(pHdr80211->Addr3, pBssid); +} + + +VOID MgtMacHeaderInitExt( + IN RTMP_ADAPTER *pAd, + IN OUT HEADER_802_11 *pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN UCHAR *pAddr1, + IN UCHAR *pAddr2, + IN UCHAR *pAddr3) +{ + NdisZeroMemory(pHdr80211, sizeof(HEADER_802_11)); + + pHdr80211->FC.Type = FC_TYPE_MGMT; + pHdr80211->FC.SubType = SubType; + pHdr80211->FC.ToDs = ToDs; + COPY_MAC_ADDR(pHdr80211->Addr1, pAddr1); + COPY_MAC_ADDR(pHdr80211->Addr2, pAddr2); + COPY_MAC_ADDR(pHdr80211->Addr3, pAddr3); +} + + +/*!*************************************************************************** + * This routine build an outgoing frame, and fill all information specified + * in argument list to the frame body. The actual frame size is the summation + * of all arguments. + * input params: + * Buffer - pointer to a pre-allocated memory segment + * args - a list of pairs. + * NOTE NOTE NOTE!!!! the last argument must be NULL, otherwise this + * function will FAIL!!! + * return: + * Size of the buffer + * usage: + * MakeOutgoingFrame(Buffer, output_length, 2, &fc, 2, &dur, 6, p_addr1, 6,p_addr2, END_OF_ARGS); + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ****************************************************************************/ +ULONG MakeOutgoingFrame(UCHAR *Buffer, ULONG *FrameLen, ...) +{ + UCHAR *p; + int leng; + ULONG TotLeng; + va_list Args; + + /* calculates the total length*/ + TotLeng = 0; + va_start(Args, FrameLen); + do + { + leng = va_arg(Args, int); + if (leng == END_OF_ARGS) + { + break; + } + p = va_arg(Args, PVOID); + NdisMoveMemory(&Buffer[TotLeng], p, leng); + TotLeng = TotLeng + leng; + } while(TRUE); + + va_end(Args); /* clean up */ + *FrameLen = TotLeng; + return TotLeng; +} + + +/*! \brief Initialize The MLME Queue, used by MLME Functions + * \param *Queue The MLME Queue + * \return Always Return NDIS_STATE_SUCCESS in this implementation + * \pre + * \post + * \note Because this is done only once (at the init stage), no need to be locked + + IRQL = PASSIVE_LEVEL + + */ +NDIS_STATUS MlmeQueueInit( + IN PRTMP_ADAPTER pAd, +#ifdef EAPOL_QUEUE_SUPPORT + IN EAP_MLME_QUEUE *EAP_Queue, +#endif /* EAPOL_QUEUE_SUPPORT */ + IN MLME_QUEUE *Queue) +{ + INT i; + + NdisAllocateSpinLock(pAd, &Queue->Lock); + + Queue->Num = 0; + Queue->Head = 0; + Queue->Tail = 0; + + for (i = 0; i < MAX_LEN_OF_MLME_QUEUE; i++) + { + Queue->Entry[i].Occupied = FALSE; + Queue->Entry[i].MsgLen = 0; + NdisZeroMemory(Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE); + } + +#ifdef EAPOL_QUEUE_SUPPORT + NdisAllocateSpinLock(pAd, &EAP_Queue->Lock); + + EAP_Queue->Num = 0; + EAP_Queue->Head = 0; + EAP_Queue->Tail = 0; + + for (i = 0; i < MAX_LEN_OF_EAP_QUEUE; i++) + { + EAP_Queue->Entry[i].Occupied = FALSE; + EAP_Queue->Entry[i].MsgLen = 0; + NdisZeroMemory(EAP_Queue->Entry[i].Msg, MGMT_DMA_BUFFER_SIZE); + } +#endif /* EAPOL_QUEUE_SUPPORT */ + + return NDIS_STATUS_SUCCESS; +} + + +/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread + * \param *Queue The MLME Queue + * \param Machine The State Machine Id + * \param MsgType The Message Type + * \param MsgLen The Message length + * \param *Msg The message pointer + * \return TRUE if enqueue is successful, FALSE if the queue is full + * \pre + * \post + * \note The message has to be initialized + */ +BOOLEAN MlmeEnqueue( + IN RTMP_ADAPTER *pAd, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg, + IN ULONG Priv) +{ + INT Tail; + MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; + + /* Do nothing if the driver is starting halt state.*/ + /* This might happen when timer already been fired before cancel timer with mlmehalt*/ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return FALSE; + + /* First check the size, it MUST not exceed the mlme queue size*/ + if (MsgLen > MGMT_DMA_BUFFER_SIZE) + { + DBGPRINT_ERR(("MlmeEnqueue: msg too large, size = %ld \n", MsgLen)); + return FALSE; + } + + if (MlmeQueueFull(Queue, 1)) + { + return FALSE; + } + + NdisAcquireSpinLock(&(Queue->Lock)); + Tail = Queue->Tail; + /* + Double check for safety in multi-thread system. + */ + if (Queue->Entry[Tail].Occupied) + { + NdisReleaseSpinLock(&(Queue->Lock)); + return FALSE; + } + Queue->Tail++; + Queue->Num++; + if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) + Queue->Tail = 0; + + Queue->Entry[Tail].Wcid = RESERVED_WCID; + Queue->Entry[Tail].Occupied = TRUE; + Queue->Entry[Tail].Machine = Machine; + Queue->Entry[Tail].MsgType = MsgType; + Queue->Entry[Tail].MsgLen = MsgLen; + Queue->Entry[Tail].Priv = Priv; + + if (Msg != NULL) + { + NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); + } + + NdisReleaseSpinLock(&(Queue->Lock)); + + return TRUE; +} + + + +#ifdef EAPOL_QUEUE_SUPPORT +BOOLEAN EAPMlmeEnqueue( + IN RTMP_ADAPTER *pAd, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg, + IN ULONG Priv) +{ + INT Tail; + EAP_MLME_QUEUE *Queue = (EAP_MLME_QUEUE *)&pAd->Mlme.EAP_Queue; + + /* Do nothing if the driver is starting halt state.*/ + /* This might happen when timer already been fired before cancel timer with mlmehalt*/ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return FALSE; + + /* First check the size, it MUST not exceed the mlme queue size*/ + if (MsgLen > MGMT_DMA_BUFFER_SIZE) + { + DBGPRINT_ERR(("%s: msg too large, size = %ld \n", __FUNCTION__, MsgLen)); + return FALSE; + } + + if (EAPMlmeQueueFull(Queue)) + { + return FALSE; + } + + NdisAcquireSpinLock(&(Queue->Lock)); + Tail = Queue->Tail; + /* + Double check for safety in multi-thread system. + */ + if (Queue->Entry[Tail].Occupied) + { + NdisReleaseSpinLock(&(Queue->Lock)); + return FALSE; + } + Queue->Tail++; + Queue->Num++; + if (Queue->Tail == MAX_LEN_OF_EAP_QUEUE) + Queue->Tail = 0; + + Queue->Entry[Tail].Wcid = RESERVED_WCID; + Queue->Entry[Tail].Occupied = TRUE; + Queue->Entry[Tail].Machine = Machine; + Queue->Entry[Tail].MsgType = MsgType; + Queue->Entry[Tail].MsgLen = MsgLen; + Queue->Entry[Tail].Priv = Priv; + + if (Msg != NULL) + { + NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); + } + + NdisReleaseSpinLock(&(Queue->Lock)); + + return TRUE; +} +#endif /* EAPOL_QUEUE_SUPPORT */ + + +/*! \brief This function is used when Recv gets a MLME message + * \param *Queue The MLME Queue + * \param TimeStampHigh The upper 32 bit of timestamp + * \param TimeStampLow The lower 32 bit of timestamp + * \param Rssi The receiving RSSI strength + * \param MsgLen The length of the message + * \param *Msg The message pointer + * \return TRUE if everything ok, FALSE otherwise (like Queue Full) + * \pre + * \post + */ +BOOLEAN MlmeEnqueueForRecv( + IN RTMP_ADAPTER *pAd, + IN ULONG Wcid, + IN struct raw_rssi_info *rssi_info, +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + IN UCHAR Snr0, + IN UCHAR Snr1, +#endif + IN ULONG MsgLen, + IN VOID *Msg, + IN UCHAR OpMode) +{ + INT Tail, Machine = 0xff; + UINT32 TimeStampHigh, TimeStampLow; + PFRAME_802_11 pFrame = (PFRAME_802_11)Msg; + INT MsgType = 0x0; + +#ifdef EAPOL_QUEUE_SUPPORT + EAP_MLME_QUEUE *EAP_Queue = (EAP_MLME_QUEUE *)&pAd->Mlme.EAP_Queue; +#endif /* EAPOL_QUEUE_SUPPORT */ + + 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 */ + + if (!pFrame) { + DBGPRINT(RT_DEBUG_ERROR, ("%s() has NULL parameter: Msg\n", __func__)); + return FALSE; + } + +#ifdef CONFIG_ATE + /* Nothing to do in ATE mode */ + if(ATE_ON(pAd)) + return FALSE; +#endif /* CONFIG_ATE */ + + /* + Do nothing if the driver is starting halt state. + This might happen when timer already been fired before cancel timer with mlmehalt + */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + DBGPRINT_ERR(("%s(): fRTMP_ADAPTER_HALT_IN_PROGRESS\n", __FUNCTION__)); + return FALSE; + } + + /* First check the size, it MUST not exceed the mlme queue size*/ + if (MsgLen > MGMT_DMA_BUFFER_SIZE) + { + DBGPRINT_ERR(("%s(): frame too large, size = %ld \n", __FUNCTION__, MsgLen)); + return FALSE; + } + +#ifdef EAPOL_QUEUE_SUPPORT + if (MlmeQueueFull(Queue, 0) && EAPMlmeQueueFull(EAP_Queue)) +#else /* EAPOL_QUEUE_SUPPORT */ + if (MlmeQueueFull(Queue, 0)) +#endif /* !EAPOL_QUEUE_SUPPORT */ + { + RTMP_MLME_HANDLER(pAd); + + return FALSE; + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + +#ifdef APCLI_SUPPORT + /* + Beacon must be handled by ap-sync state machine. + Probe-rsp must be handled by apcli-sync state machine. + Those packets don't need to check its MAC address + */ + do + { + BOOLEAN bToApCli = FALSE; + UCHAR i; + /* + 1. When P2P GO On and receive Probe Response, preCheckMsgTypeSubset function will + enquene Probe response to APCli sync state machine + Solution: when GO On skip preCheckMsgTypeSubset redirect to APMsgTypeSubst + 2. When P2P Cli On and receive Probe Response, preCheckMsgTypeSubset function will + enquene Probe response to APCli sync state machine + Solution: handle MsgType == APCLI_MT2_PEER_PROBE_RSP on ApCli Sync state machine + when ApCli on idle state. + */ + for (i = 0; i < pAd->ApCfg.ApCliNum; i++) + { + if (MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[i].MlmeAux.Bssid, pFrame->Hdr.Addr2) +#ifdef MULTI_APCLI_SUPPORT + || MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[i].wdev.if_addr, pFrame->Hdr.Addr1) +#endif /* MULTI_APCLI_SUPPORT */ + + ) + { +#ifdef MULTI_APCLI_SUPPORT + ApCliIdx = i; +#endif /* MULTI_APCLI_SUPPORT */ + bToApCli = TRUE; + break; + } + } + + if (!MAC_ADDR_EQUAL(pFrame->Hdr.Addr1, pAd->CurrentAddress) && + preCheckMsgTypeSubset(pAd, pFrame, &Machine, &MsgType)) + break; + + if (!MAC_ADDR_EQUAL(pFrame->Hdr.Addr1, pAd->CurrentAddress) && bToApCli) + { + if (ApCliMsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) + break; + } +#ifndef WH_EZ_SETUP // make it same as 7615 handling. + else +#endif + { + if (APMsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) + break; + } + + DBGPRINT_ERR(("%s(): un-recongnized mgmt->subtype=%d, STA-%02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, pFrame->Hdr.FC.SubType, PRINT_MAC(pFrame->Hdr.Addr2))); + return FALSE; + + } while (FALSE); +#else + if (!APMsgTypeSubst(pAd, pFrame, &Machine, &MsgType)) + { + DBGPRINT_ERR(("%s(): un-recongnized mgmt->subtype=%d\n", + __FUNCTION__, pFrame->Hdr.FC.SubType)); + return FALSE; + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + TimeStampHigh = TimeStampLow = 0; +#ifdef RTMP_MAC_PCI + if (!IS_USB_INF(pAd)) + AsicGetTsfTime(pAd, &TimeStampHigh, &TimeStampLow); +#endif /* RTMP_MAC_PCI */ + + +#ifdef EAPOL_QUEUE_SUPPORT + if (Machine == WPA_STATE_MACHINE) + { + + if (EAPMlmeQueueFull(EAP_Queue)) + { + RTMP_MLME_HANDLER(pAd); + return FALSE; + } + + /* OK, we got all the informations, it is time to put things into queue*/ + NdisAcquireSpinLock(&(EAP_Queue->Lock)); + Tail = EAP_Queue->Tail; + /* + Double check for safety in multi-thread system. + */ + if (EAP_Queue->Entry[Tail].Occupied) + { + NdisReleaseSpinLock(&(EAP_Queue->Lock)); + return FALSE; + } + EAP_Queue->Tail++; + EAP_Queue->Num++; + if (EAP_Queue->Tail == MAX_LEN_OF_EAP_QUEUE) + EAP_Queue->Tail = 0; + + EAP_Queue->Entry[Tail].Occupied = TRUE; + EAP_Queue->Entry[Tail].Machine = Machine; + EAP_Queue->Entry[Tail].MsgType = MsgType; + EAP_Queue->Entry[Tail].MsgLen = MsgLen; + EAP_Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow; + EAP_Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh; + NdisMoveMemory(&EAP_Queue->Entry[Tail].rssi_info, rssi_info, sizeof(struct raw_rssi_info)); + EAP_Queue->Entry[Tail].Signal = rssi_info->raw_snr; +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + EAP_Queue->Entry[Tail].Snr0= Snr0; + EAP_Queue->Entry[Tail].Snr1= Snr1; +#endif + EAP_Queue->Entry[Tail].Wcid = (UCHAR)Wcid; + EAP_Queue->Entry[Tail].OpMode = (ULONG)OpMode; + EAP_Queue->Entry[Tail].Channel = pAd->CommonCfg.BBPCurrentBW == BW_40 ? + pAd->CommonCfg.Channel : pAd->LatchRfRegs.Channel; + EAP_Queue->Entry[Tail].Priv = 0; +#ifdef APCLI_SUPPORT + EAP_Queue->Entry[Tail].Priv = ApCliIdx; +#endif /* APCLI_SUPPORT */ +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + { + for (CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) + { + if (MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[ApCliIdx].RepeaterCli[CliIdx].CurrentAddress, pFrame->Hdr.Addr1)) + { + EAP_Queue->Entry[Tail].Priv = (64 + (MAX_EXT_MAC_ADDR_SIZE * ApCliIdx) + CliIdx); + break; + } + } + } +#endif /* MAC_REPEATER_SUPPORT */ + + if (Msg != NULL) + { + NdisMoveMemory(EAP_Queue->Entry[Tail].Msg, Msg, MsgLen); + } + + NdisReleaseSpinLock(&(EAP_Queue->Lock)); + } + else +#endif /* EAPOL_QUEUE_SUPPORT */ + { + + if (MlmeQueueFull(Queue, 0)) + { + RTMP_MLME_HANDLER(pAd); + return FALSE; + } + + /* OK, we got all the informations, it is time to put things into queue*/ + NdisAcquireSpinLock(&(Queue->Lock)); + Tail = Queue->Tail; + /* + Double check for safety in multi-thread system. + */ + if (Queue->Entry[Tail].Occupied) + { + NdisReleaseSpinLock(&(Queue->Lock)); + return FALSE; + } + Queue->Tail++; + Queue->Num++; + if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) + Queue->Tail = 0; + + Queue->Entry[Tail].Occupied = TRUE; + Queue->Entry[Tail].Machine = Machine; + Queue->Entry[Tail].MsgType = MsgType; + Queue->Entry[Tail].MsgLen = MsgLen; + Queue->Entry[Tail].TimeStamp.u.LowPart = TimeStampLow; + Queue->Entry[Tail].TimeStamp.u.HighPart = TimeStampHigh; + NdisMoveMemory(&Queue->Entry[Tail].rssi_info, rssi_info, sizeof(struct raw_rssi_info)); + Queue->Entry[Tail].Signal = rssi_info->raw_snr; +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + Queue->Entry[Tail].Snr0= Snr0; + Queue->Entry[Tail].Snr1= Snr1; +#endif + Queue->Entry[Tail].Wcid = (UCHAR)Wcid; + Queue->Entry[Tail].OpMode = (ULONG)OpMode; + Queue->Entry[Tail].Channel = pAd->CommonCfg.BBPCurrentBW == BW_40 ? + pAd->CommonCfg.Channel : pAd->LatchRfRegs.Channel; + Queue->Entry[Tail].Priv = 0; +#ifdef APCLI_SUPPORT + Queue->Entry[Tail].Priv = ApCliIdx; +#endif /* APCLI_SUPPORT */ +#ifdef MAC_REPEATER_SUPPORT + if (pAd->ApCfg.bMACRepeaterEn) + { + for (CliIdx = 0; CliIdx < MAX_EXT_MAC_ADDR_SIZE; CliIdx++) + { + if (MAC_ADDR_EQUAL(pAd->ApCfg.ApCliTab[ApCliIdx].RepeaterCli[CliIdx].CurrentAddress, pFrame->Hdr.Addr1)) + { + Queue->Entry[Tail].Priv = (64 + (MAX_EXT_MAC_ADDR_SIZE * ApCliIdx) + CliIdx); + break; + } + } + } +#endif /* MAC_REPEATER_SUPPORT */ + + if (Msg != NULL) + { + NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); + } + + NdisReleaseSpinLock(&(Queue->Lock)); + } + + + RTMP_MLME_HANDLER(pAd); + + return TRUE; +} + + +#ifdef WSC_INCLUDED +/*! \brief Enqueue a message for other threads, if they want to send messages to MLME thread + * \param *Queue The MLME Queue + * \param TimeStampLow The lower 32 bit of timestamp, here we used for eventID. + * \param Machine The State Machine Id + * \param MsgType The Message Type + * \param MsgLen The Message length + * \param *Msg The message pointer + * \return TRUE if enqueue is successful, FALSE if the queue is full + * \pre + * \post + * \note The message has to be initialized + */ +BOOLEAN MlmeEnqueueForWsc( + IN RTMP_ADAPTER *pAd, + IN ULONG eventID, + IN LONG senderID, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg) +{ + INT Tail; + MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> MlmeEnqueueForWsc\n")); + /* Do nothing if the driver is starting halt state.*/ + /* This might happen when timer already been fired before cancel timer with mlmehalt*/ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) + return FALSE; + + /* First check the size, it MUST not exceed the mlme queue size*/ + if (MsgLen > MGMT_DMA_BUFFER_SIZE) + { + DBGPRINT_ERR(("MlmeEnqueueForWsc: msg too large, size = %ld \n", MsgLen)); + return FALSE; + } + + if (MlmeQueueFull(Queue, 1)) + { + + return FALSE; + } + + /* OK, we got all the informations, it is time to put things into queue*/ + NdisAcquireSpinLock(&(Queue->Lock)); + Tail = Queue->Tail; + /* + Double check for safety in multi-thread system. + */ + if (Queue->Entry[Tail].Occupied) + { + NdisReleaseSpinLock(&(Queue->Lock)); + return FALSE; + } + Queue->Tail++; + Queue->Num++; + if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) + { + Queue->Tail = 0; + } + + Queue->Entry[Tail].Occupied = TRUE; + Queue->Entry[Tail].Machine = Machine; + Queue->Entry[Tail].MsgType = MsgType; + Queue->Entry[Tail].MsgLen = MsgLen; + Queue->Entry[Tail].TimeStamp.u.LowPart = eventID; + Queue->Entry[Tail].TimeStamp.u.HighPart = senderID; + if (Msg != NULL) + NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); + + NdisReleaseSpinLock(&(Queue->Lock)); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- MlmeEnqueueForWsc\n")); + + return TRUE; +} +#endif /* WSC_INCLUDED */ + + +/*! \brief Dequeue a message from the MLME Queue + * \param *Queue The MLME Queue + * \param *Elem The message dequeued from MLME Queue + * \return TRUE if the Elem contains something, FALSE otherwise + * \pre + * \post + */ +BOOLEAN MlmeDequeue(MLME_QUEUE *Queue, MLME_QUEUE_ELEM **Elem) +{ + NdisAcquireSpinLock(&(Queue->Lock)); + *Elem = &(Queue->Entry[Queue->Head]); + Queue->Num--; + Queue->Head++; + if (Queue->Head == MAX_LEN_OF_MLME_QUEUE) + { + Queue->Head = 0; + } + NdisReleaseSpinLock(&(Queue->Lock)); + return TRUE; +} + +#ifdef EAPOL_QUEUE_SUPPORT +BOOLEAN EAPMlmeDequeue( + IN EAP_MLME_QUEUE *Queue, + OUT MLME_QUEUE_ELEM **Elem) +{ + NdisAcquireSpinLock(&(Queue->Lock)); + *Elem = &(Queue->Entry[Queue->Head]); + Queue->Num--; + Queue->Head++; + if (Queue->Head == MAX_LEN_OF_EAP_QUEUE) + { + Queue->Head = 0; + } + NdisReleaseSpinLock(&(Queue->Lock)); + return TRUE; +} +#endif /* EAPOL_QUEUE_SUPPORT */ + +VOID MlmeRestartStateMachine(RTMP_ADAPTER *pAd) +{ +#ifdef RTMP_MAC_PCI + MLME_QUEUE_ELEM *Elem = NULL; +#endif /* RTMP_MAC_PCI */ + + DBGPRINT(RT_DEBUG_TRACE, ("MlmeRestartStateMachine \n")); + +#ifdef RTMP_MAC_PCI + NdisAcquireSpinLock(&pAd->Mlme.TaskLock); + if(pAd->Mlme.bRunning) + { + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + return; + } + else + { + pAd->Mlme.bRunning = TRUE; + } + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + +#ifdef EAPOL_QUEUE_SUPPORT + while (!EAPMlmeQueueEmpty(&pAd->Mlme.EAP_Queue)) + { + /*From message type, determine which state machine I should drive*/ + if (EAPMlmeDequeue(&pAd->Mlme.EAP_Queue, &Elem)) + { + /* free MLME element*/ + Elem->Occupied = FALSE; + Elem->MsgLen = 0; + + } + else { + DBGPRINT_ERR(("MlmeRestartStateMachine: EAP MlmeQueue empty\n")); + } + } +#endif /* EAPOL_QUEUE_SUPPORT */ + + /* Remove all Mlme queues elements*/ + while (!MlmeQueueEmpty(&pAd->Mlme.Queue)) + { + /*From message type, determine which state machine I should drive*/ + if (MlmeDequeue(&pAd->Mlme.Queue, &Elem)) + { + /* free MLME element*/ + Elem->Occupied = FALSE; + Elem->MsgLen = 0; + + } + else { + DBGPRINT_ERR(("MlmeRestartStateMachine: MlmeQueue empty\n")); + } + } +#endif /* RTMP_MAC_PCI */ + + + /* Change back to original channel in case of doing scan*/ + { + AsicSwitchChannel(pAd, pAd->CommonCfg.Channel, FALSE); + AsicLockChannel(pAd, pAd->CommonCfg.Channel); + } + + /* Resume MSDU which is turned off durning scan*/ + RTMPResumeMsduTransmission(pAd); + + +#ifdef RTMP_MAC_PCI + /* Remove running state*/ + NdisAcquireSpinLock(&pAd->Mlme.TaskLock); + pAd->Mlme.bRunning = FALSE; + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); +#endif /* RTMP_MAC_PCI */ + +//CFG_TODO for SCAN +} + + +/*! \brief test if the MLME Queue is empty + * \param *Queue The MLME Queue + * \return TRUE if the Queue is empty, FALSE otherwise + * \pre + * \post + + IRQL = DISPATCH_LEVEL + + */ +BOOLEAN MlmeQueueEmpty(MLME_QUEUE *Queue) +{ + BOOLEAN Ans; + + NdisAcquireSpinLock(&(Queue->Lock)); + Ans = (Queue->Num == 0); + NdisReleaseSpinLock(&(Queue->Lock)); + + return Ans; +} + +#ifdef EAPOL_QUEUE_SUPPORT +BOOLEAN EAPMlmeQueueEmpty( + IN EAP_MLME_QUEUE *Queue) +{ + BOOLEAN Ans; + + NdisAcquireSpinLock(&(Queue->Lock)); + Ans = (Queue->Num == 0); + NdisReleaseSpinLock(&(Queue->Lock)); + + return Ans; +} +#endif /* EAPOL_QUEUE_SUPPORT */ + +/*! \brief test if the MLME Queue is full + * \param *Queue The MLME Queue + * \return TRUE if the Queue is empty, FALSE otherwise + * \pre + * \post + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + */ +BOOLEAN MlmeQueueFull(MLME_QUEUE *Queue, UCHAR SendId) +{ + BOOLEAN Ans; + + NdisAcquireSpinLock(&(Queue->Lock)); + if (SendId == 0) + Ans = ((Queue->Num >= (MAX_LEN_OF_MLME_QUEUE / 2)) || Queue->Entry[Queue->Tail].Occupied); + else + Ans = ((Queue->Num == MAX_LEN_OF_MLME_QUEUE) || Queue->Entry[Queue->Tail].Occupied); + NdisReleaseSpinLock(&(Queue->Lock)); + + return Ans; +} + +#ifdef EAPOL_QUEUE_SUPPORT +BOOLEAN EAPMlmeQueueFull( + IN EAP_MLME_QUEUE *Queue) +{ + BOOLEAN Ans; + + NdisAcquireSpinLock(&(Queue->Lock)); + Ans = (Queue->Num == MAX_LEN_OF_EAP_QUEUE); + NdisReleaseSpinLock(&(Queue->Lock)); + + return Ans; +} +#endif /* EAPOL_QUEUE_SUPPORT */ + +/*! \brief The destructor of MLME Queue + * \param + * \return + * \pre + * \post + * \note Clear Mlme Queue, Set Queue->Num to Zero. + + IRQL = PASSIVE_LEVEL + + */ +VOID MlmeQueueDestroy( +#ifdef EAPOL_QUEUE_SUPPORT + IN EAP_MLME_QUEUE *pEAP_Queue, +#endif + IN MLME_QUEUE *pQueue) +{ + NdisAcquireSpinLock(&(pQueue->Lock)); + pQueue->Num = 0; + pQueue->Head = 0; + pQueue->Tail = 0; + NdisReleaseSpinLock(&(pQueue->Lock)); + NdisFreeSpinLock(&(pQueue->Lock)); + +#ifdef EAPOL_QUEUE_SUPPORT + NdisAcquireSpinLock(&(pEAP_Queue->Lock)); + pEAP_Queue->Num = 0; + pEAP_Queue->Head = 0; + pEAP_Queue->Tail = 0; + NdisReleaseSpinLock(&(pEAP_Queue->Lock)); + NdisFreeSpinLock(&(pEAP_Queue->Lock)); +#endif /* EAPOL_QUEUE_SUPPORT */ + +} + + +/*! \brief To substitute the message type if the message is coming from external + * \param pFrame The frame received + * \param *Machine The state machine + * \param *MsgType the message type for the state machine + * \return TRUE if the substitution is successful, FALSE otherwise + * \pre + * \post + + IRQL = DISPATCH_LEVEL + + */ + + +/*! \brief Initialize the state machine. + * \param *S pointer to the state machine + * \param Trans State machine transition function + * \param StNr number of states + * \param MsgNr number of messages + * \param DefFunc default function, when there is invalid state/message combination + * \param InitState initial state of the state machine + * \param Base StateMachine base, internal use only + * \pre p_sm should be a legal pointer + * \post + + IRQL = PASSIVE_LEVEL + + */ +VOID StateMachineInit( + IN STATE_MACHINE *S, + IN STATE_MACHINE_FUNC Trans[], + IN ULONG StNr, + IN ULONG MsgNr, + IN STATE_MACHINE_FUNC DefFunc, + IN ULONG InitState, + IN ULONG Base) +{ + ULONG i, j; + + /* set number of states and messages*/ + S->NrState = StNr; + S->NrMsg = MsgNr; + S->Base = Base; + + S->TransFunc = Trans; + + /* init all state transition to default function*/ + for (i = 0; i < StNr; i++) + { + for (j = 0; j < MsgNr; j++) + { + S->TransFunc[i * MsgNr + j] = DefFunc; + } + } + + /* set the starting state*/ + S->CurrState = InitState; +} + + +/*! \brief This function fills in the function pointer into the cell in the state machine + * \param *S pointer to the state machine + * \param St state + * \param Msg incoming message + * \param f the function to be executed when (state, message) combination occurs at the state machine + * \pre *S should be a legal pointer to the state machine, st, msg, should be all within the range, Base should be set in the initial state + * \post + + IRQL = PASSIVE_LEVEL + + */ +VOID StateMachineSetAction( + IN STATE_MACHINE *S, + IN ULONG St, + IN ULONG Msg, + IN STATE_MACHINE_FUNC Func) +{ + ULONG MsgIdx; + + MsgIdx = Msg - S->Base; + + if (St < S->NrState && MsgIdx < S->NrMsg) + { + /* boundary checking before setting the action*/ + S->TransFunc[St * S->NrMsg + MsgIdx] = Func; + } +} + + +/*! \brief This function does the state transition + * \param *Adapter the NIC adapter pointer + * \param *S the state machine + * \param *Elem the message to be executed + * \return None + */ +VOID StateMachinePerformAction( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem, + IN ULONG CurrState) +{ + if (S->TransFunc[(CurrState) * S->NrMsg + Elem->MsgType - S->Base]) + (*(S->TransFunc[(CurrState) * S->NrMsg + Elem->MsgType - S->Base]))(pAd, Elem); +} + + +/* + ========================================================================== + Description: + The drop function, when machine executes this, the message is simply + ignored. This function does nothing, the message is freed in + StateMachinePerformAction() + ========================================================================== + */ +VOID Drop(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ +} + + +/* + ========================================================================== + Description: + ========================================================================== + */ +UCHAR RandomByte(RTMP_ADAPTER *pAd) +{ + ULONG i; + UCHAR R, Result; + + R = 0; + + if (pAd->Mlme.ShiftReg == 0) + NdisGetSystemUpTime((ULONG *)&pAd->Mlme.ShiftReg); + + for (i = 0; i < 8; i++) + { + if (pAd->Mlme.ShiftReg & 0x00000001) + { + pAd->Mlme.ShiftReg = ((pAd->Mlme.ShiftReg ^ LFSR_MASK) >> 1) | 0x80000000; + Result = 1; + } + else + { + pAd->Mlme.ShiftReg = pAd->Mlme.ShiftReg >> 1; + Result = 0; + } + R = (R << 1) | Result; + } + + return R; +} + + +UCHAR RandomByte2(RTMP_ADAPTER *pAd) +{ + UINT32 a,b; + UCHAR value, seed = 0; + + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return 0; + } + + /*MAC statistic related*/ + a = AsicGetCCACnt(pAd); + a &= 0x0000ffff; + b = AsicGetCrcErrCnt(pAd); + b &= 0x0000ffff; + value = (a<<16)|b; + + /*get seed by RSSI or SNR related info */ + seed = get_random_seed_by_phy(pAd); + + return value ^ seed ^ RandomByte(pAd); +} + + +/* + ======================================================================== + + Routine Description: + Verify the support rate for different PHY type + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + ======================================================================== +*/ +VOID RTMPCheckRates(RTMP_ADAPTER *pAd, UCHAR SupRate[], UCHAR *SupRateLen) +{ + UCHAR RateIdx, i, j; + UCHAR NewRate[12]={0}, NewRateLen; + + NewRateLen = 0; + + if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B)) + RateIdx = 4; + else + RateIdx = 12; + + /* Check for support rates exclude basic rate bit */ + for (i = 0; i < *SupRateLen; i++) + for (j = 0; j < RateIdx; j++) + if ((SupRate[i] & 0x7f) == RateIdTo500Kbps[j]) + NewRate[NewRateLen++] = SupRate[i]; + + *SupRateLen = NewRateLen; + NdisMoveMemory(SupRate, NewRate, NewRateLen); +} + + + +CHAR RTMPAvgRssi(RTMP_ADAPTER *pAd, RSSI_SAMPLE *pRssi) +{ + CHAR Rssi; + + if(pAd->Antenna.field.RxPath == 3) + { + Rssi = (pRssi->AvgRssi[0] + pRssi->AvgRssi[1] + pRssi->AvgRssi[2])/3; + } + else if(pAd->Antenna.field.RxPath == 2) + { + Rssi = (pRssi->AvgRssi[0] + pRssi->AvgRssi[1])>>1; + } + else + { + Rssi = pRssi->AvgRssi[0]; + } + + return Rssi; +} + + +CHAR RTMPMaxRssi(RTMP_ADAPTER *pAd, CHAR Rssi0, CHAR Rssi1, CHAR Rssi2) +{ + CHAR larger = -127; + + if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 <= 0)) + { + larger = Rssi0; + } + + if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 <= 0)) + { + larger = max(Rssi0, Rssi1); + } + + if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 <= 0)) + { + larger = max(larger, Rssi2); + } + + if (larger == -127) + larger = 0; + + return larger; +} + +CHAR RTMPMinRssi(RTMP_ADAPTER *pAd, CHAR Rssi0, CHAR Rssi1, CHAR Rssi2) +{ + CHAR smaller = -127; + + if ((pAd->Antenna.field.RxPath == 1) && (Rssi0 <= 0)) + { + smaller = Rssi0; + } + + if ((pAd->Antenna.field.RxPath >= 2) && (Rssi1 <= 0)) + { + smaller = min(Rssi0, Rssi1); + } + + if ((pAd->Antenna.field.RxPath == 3) && (Rssi2 <= 0)) + { + smaller = min(smaller, Rssi2); + } + + if (smaller == -127) + smaller = 0; + + return smaller; +} + + +CHAR RTMPMinSnr(RTMP_ADAPTER *pAd, CHAR Snr0, CHAR Snr1) +{ + CHAR smaller = Snr0; + + if (pAd->Antenna.field.RxPath == 1) + { + smaller = Snr0; + } + + if ((pAd->Antenna.field.RxPath >= 2) && (Snr1 != 0)) + { + smaller = min(Snr0, Snr1); + } + + return smaller; +} + + +/* + ======================================================================== + Routine Description: + Periodic evaluate antenna link status + + Arguments: + pAd - Adapter pointer + + Return Value: + None + + ======================================================================== +*/ +VOID AsicEvaluateRxAnt(RTMP_ADAPTER *pAd) +{ +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + return; +#endif /* CONFIG_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 MT_MAC + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) + return; +#endif /* MT_MAC */ + + { +#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 */ + } +} + + +/* + ======================================================================== + 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_ATE + if (ATE_ON(pAd)) + return; +#endif /* CONFIG_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 */ + } +} + + +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: + check if this entry need to switch rate automatically + + Arguments: + pAd + pEntry + + Return Value: + TURE + FALSE + + ======================================================================== +*/ +BOOLEAN RTMPCheckEntryEnableAutoRateSwitch( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + BOOLEAN result = TRUE; + + if ((!pEntry) || (!(pEntry->wdev))) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): entry or wdev is NULL!\n", + __FUNCTION__)); + return FALSE; + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { + result = pEntry->wdev->bAutoTxRateSwitch; + } +#endif /* CONFIG_AP_SUPPORT */ + + + + + + + return result; +} + + +BOOLEAN RTMPAutoRateSwitchCheck(RTMP_ADAPTER *pAd) +{ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + INT apidx = 0; + + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + if (pAd->ApCfg.MBSSID[apidx].wdev.bAutoTxRateSwitch) + return TRUE; + } +#ifdef WDS_SUPPORT + for (apidx = 0; apidx < MAX_WDS_ENTRY; apidx++) + { + if (pAd->WdsTab.WdsEntry[apidx].wdev.bAutoTxRateSwitch) + return TRUE; + } +#endif /* WDS_SUPPORT */ +#ifdef APCLI_SUPPORT + for (apidx = 0; apidx < MAX_APCLI_NUM; apidx++) + { + if (pAd->ApCfg.ApCliTab[apidx].wdev.bAutoTxRateSwitch) + return TRUE; + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + return FALSE; +} + + +/* + ======================================================================== + Routine Description: + check if this entry need to fix tx legacy rate + + Arguments: + pAd + pEntry + + Return Value: + TURE + FALSE + + ======================================================================== +*/ +UCHAR RTMPStaFixedTxMode(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + UCHAR tx_mode = FIXED_TXMODE_HT; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + if (pEntry) + { + if (IS_ENTRY_CLIENT(pEntry)) + tx_mode = (UCHAR)pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.DesiredTransmitSetting.field.FixedTxMode; +#ifdef WDS_SUPPORT + else if (IS_ENTRY_WDS(pEntry)) + tx_mode = (UCHAR)pAd->WdsTab.WdsEntry[pEntry->func_tb_idx].wdev.DesiredTransmitSetting.field.FixedTxMode; +#endif /* WDS_SUPPORT */ +#ifdef APCLI_SUPPORT + else if (IS_ENTRY_APCLI(pEntry)) + tx_mode = (UCHAR)pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].wdev.DesiredTransmitSetting.field.FixedTxMode; +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + + return tx_mode; +} + + +/* + ======================================================================== + Routine Description: + Overwrite HT Tx Mode by Fixed Legency Tx Mode, if specified. + + Arguments: + pAd + pEntry + + Return Value: + TURE + FALSE + + ======================================================================== +*/ +VOID RTMPUpdateLegacyTxSetting(UCHAR fixed_tx_mode, MAC_TABLE_ENTRY *pEntry) +{ + HTTRANSMIT_SETTING TransmitSetting; + + if ((fixed_tx_mode != FIXED_TXMODE_CCK) && + (fixed_tx_mode != FIXED_TXMODE_OFDM) +#ifdef DOT11_VHT_AC + && (fixed_tx_mode != FIXED_TXMODE_VHT) +#endif /* DOT11_VHT_AC */ + ) + return; + + TransmitSetting.word = 0; + + TransmitSetting.field.MODE = pEntry->HTPhyMode.field.MODE; + TransmitSetting.field.MCS = pEntry->HTPhyMode.field.MCS; + +#ifdef DOT11_VHT_AC + if (fixed_tx_mode == FIXED_TXMODE_VHT) + { + TransmitSetting.field.MODE = MODE_VHT; + TransmitSetting.field.BW = pEntry->MaxHTPhyMode.field.BW; + /* CCK mode allow MCS 0~3*/ + if (TransmitSetting.field.MCS > ((1 << 4) + MCS_7)) + TransmitSetting.field.MCS = ((1 << 4) + MCS_7); + } + else +#endif /* DOT11_VHT_AC */ + if (fixed_tx_mode == FIXED_TXMODE_CCK) + { + TransmitSetting.field.MODE = MODE_CCK; + /* CCK mode allow MCS 0~3*/ + if (TransmitSetting.field.MCS > MCS_3) + TransmitSetting.field.MCS = MCS_3; + } + else + { + TransmitSetting.field.MODE = MODE_OFDM; + /* OFDM mode allow MCS 0~7*/ + if (TransmitSetting.field.MCS > MCS_7) + TransmitSetting.field.MCS = MCS_7; + } + + if (pEntry->HTPhyMode.field.MODE >= TransmitSetting.field.MODE) + { + pEntry->HTPhyMode.word = TransmitSetting.word; + DBGPRINT(RT_DEBUG_TRACE, ("RTMPUpdateLegacyTxSetting : wcid-%d, MODE=%s, MCS=%d \n", + pEntry->wcid, get_phymode_str(pEntry->HTPhyMode.field.MODE), pEntry->HTPhyMode.field.MCS)); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : the fixed TxMode is invalid \n", __FUNCTION__)); + } +} + + + +VOID RTMPSetAGCInitValue(RTMP_ADAPTER *pAd, UCHAR BandWidth) +{ + if (pAd->chipOps.ChipAGCInit != NULL) + pAd->chipOps.ChipAGCInit(pAd, BandWidth); +} + + +/* +======================================================================== +Routine Description: + Check if the channel has the property. + +Arguments: + pAd - WLAN control block pointer + ChanNum - channel number + Property - channel property, CHANNEL_PASSIVE_SCAN, etc. + +Return Value: + TRUE - YES + FALSE - NO + +Note: +======================================================================== +*/ +BOOLEAN CHAN_PropertyCheck(RTMP_ADAPTER *pAd, UINT32 ChanNum, UCHAR Property) +{ + UINT32 IdChan; + + /* look for all registered channels */ + for(IdChan=0; IdChanChannelListNum; IdChan++) + { + if (pAd->ChannelList[IdChan].Channel == ChanNum) + { + if ((pAd->ChannelList[IdChan].Flags & Property) == Property) + return TRUE; + + break; + } + } + + return FALSE; +} + +#ifdef P2P_CHANNEL_LIST_SEPARATE + +BOOLEAN P2P_CHAN_PropertyCheck( + IN PRTMP_ADAPTER pAd, + IN UINT32 ChanNum, + IN UCHAR Property) +{ + UINT32 IdChan; + PCFG80211_CTRL pCfg80211_Ctrl = &pAd->cfg80211_ctrl; + + + /* look for all registered channels */ + for(IdChan = 0; IdChan < pCfg80211_Ctrl->ChannelListNum; IdChan++) + { + if (pCfg80211_Ctrl->ChannelList[IdChan].Channel == ChanNum) + { + if ((pCfg80211_Ctrl->ChannelList[IdChan].Flags & Property) == Property) + return TRUE; + + break; + } + } + + return FALSE; +} +#endif /* P2P_CHANNEL_LIST_SEPARATE */ + + + +NDIS_STATUS RtmpEnqueueTokenFrame( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + IN UCHAR TxRate, + IN UCHAR AID, + IN UCHAR apidx, + IN UCHAR OldUP) +{ + NDIS_STATUS NState = NDIS_STATUS_FAILURE; + HEADER_802_11 *pNullFr; + UCHAR *pFrame; + UINT frm_len; + + NState = MlmeAllocateMemory(pAd, (UCHAR **)&pFrame); + if (NState == NDIS_STATUS_SUCCESS) + { + UCHAR *qos_p; + pNullFr = (PHEADER_802_11) pFrame; + frm_len = sizeof(HEADER_802_11); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { + MgtMacHeaderInit(pAd, pNullFr, SUBTYPE_DATA_NULL, 0, pAddr, + pAd->ApCfg.MBSSID[apidx].wdev.if_addr, + pAd->ApCfg.MBSSID[apidx].wdev.bssid); + pNullFr->FC.ToDs = 0; + pNullFr->FC.FrDs = 1; + pNullFr->Frag = 0x0f; + } +#endif /* CONFIG_AP_SUPPORT */ + + pNullFr->FC.Type = FC_TYPE_DATA; + qos_p = ((UCHAR *)pNullFr) + frm_len; + pNullFr->FC.SubType = SUBTYPE_QOS_NULL; + + /* copy QOS control bytes */ + qos_p[0] = OldUP; + qos_p[1] = PS_RETRIEVE_TOKEN; + frm_len += 2; + + /* since TxRate may change, we have to change Duration each time */ + pNullFr->Duration = RTMPCalcDuration(pAd, TxRate, frm_len); + + NState = MiniportMMRequest(pAd, OldUP | MGMT_USE_QUEUE_FLAG, (PUCHAR)pNullFr, frm_len); + MlmeFreeMemory(pAd, pFrame); + } + + return NState; +} + + +#ifdef DYNAMIC_RX_RATE_ADJ +VOID UpdateSuppRateBitmap( + IN RTMP_ADAPTER *pAd) +{ + UCHAR idx = 0, j = 0, supp_rate_num = 0; + UCHAR ext_rate_num = 0, des_rate_num = 0; + ULONG bitmap = 0; + BOOLEAN bABandPhyMode = FALSE; + UCHAR apidx = 0; + + for(apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + idx = 0; + j = 0; + supp_rate_num = 0; + ext_rate_num = 0; + des_rate_num = 0; + bitmap = pAd->ApCfg.MBSSID[apidx].SuppRateBitmap; + bABandPhyMode = FALSE; + + if (pAd->ApCfg.MBSSID[apidx].wdev.PhyMode == WMODE_B) + pAd->ApCfg.MBSSID[apidx].SuppRateBitmap &= 0x0F; + + if (WMODE_CAP_5G(pAd->ApCfg.MBSSID[apidx].wdev.PhyMode)) + { + pAd->ApCfg.MBSSID[apidx].SuppRateBitmap &= 0xFF0; + bABandPhyMode = TRUE; + } + + for(idx=0; idx < MAX_LEN_OF_SUPPORTED_RATES; idx++) + { + if (bitmap & (1 << idx)) + { + switch (idx) + { + case 0 : + pAd->ApCfg.MBSSID[apidx].ExpectedSuppRate[supp_rate_num]= 0x02; + pAd->ApCfg.MBSSID[apidx].ExpectedDesireRate[des_rate_num] = 2; + supp_rate_num++; + des_rate_num++; + break; /* RATE_1 */ + case 1 : + pAd->ApCfg.MBSSID[apidx].ExpectedSuppRate[supp_rate_num]= 0x04; + pAd->ApCfg.MBSSID[apidx].ExpectedDesireRate[des_rate_num] = 4; + supp_rate_num++; + des_rate_num++; + break; /* RATE_2 */ + case 2 : + pAd->ApCfg.MBSSID[apidx].ExpectedSuppRate[supp_rate_num]= 0x0B; + pAd->ApCfg.MBSSID[apidx].ExpectedDesireRate[des_rate_num] = 11; + supp_rate_num++; + des_rate_num++; + break; /* RATE_5_5 */ + case 3 : + pAd->ApCfg.MBSSID[apidx].ExpectedSuppRate[supp_rate_num]= 0x16; + pAd->ApCfg.MBSSID[apidx].ExpectedDesireRate[des_rate_num] = 22; + supp_rate_num++; + des_rate_num++; + break; /* RATE_11 */ + case 4 : + if (bABandPhyMode == TRUE) + { + pAd->ApCfg.MBSSID[apidx].ExpectedSuppRate[supp_rate_num]= 0x8C; + supp_rate_num++; + } + else + { + pAd->ApCfg.MBSSID[apidx].ExpectedExtRate[ext_rate_num]= 0x0C; + ext_rate_num++; + } + + pAd->ApCfg.MBSSID[apidx].ExpectedDesireRate[des_rate_num] = 12; + des_rate_num++; + break; /* RATE_6 */ + case 5 : + pAd->ApCfg.MBSSID[apidx].ExpectedSuppRate[supp_rate_num]= 0x12; + pAd->ApCfg.MBSSID[apidx].ExpectedDesireRate[des_rate_num] = 18; + supp_rate_num++; + des_rate_num++; + break; /* RATE_9 */ + case 6 : + if (bABandPhyMode == TRUE) + { + pAd->ApCfg.MBSSID[apidx].ExpectedSuppRate[supp_rate_num]= 0x98; + supp_rate_num++; + } + else + { + pAd->ApCfg.MBSSID[apidx].ExpectedExtRate[ext_rate_num]= 0x18; + ext_rate_num++; + } + + pAd->ApCfg.MBSSID[apidx].ExpectedDesireRate[des_rate_num] = 24; + des_rate_num++; + break; /* RATE_12 */ + case 7 : + pAd->ApCfg.MBSSID[apidx].ExpectedSuppRate[supp_rate_num]= 0x24; + pAd->ApCfg.MBSSID[apidx].ExpectedDesireRate[des_rate_num] = 36; + supp_rate_num++; + des_rate_num++; + break; /* RATE_18 */ + case 8 : + if (bABandPhyMode == TRUE) + { + pAd->ApCfg.MBSSID[apidx].ExpectedSuppRate[supp_rate_num]= 0xB0; + supp_rate_num++; + } + else + { + pAd->ApCfg.MBSSID[apidx].ExpectedExtRate[ext_rate_num]= 0x30; + ext_rate_num++; + } + + pAd->ApCfg.MBSSID[apidx].ExpectedDesireRate[des_rate_num] = 48; + des_rate_num++; + break; /* RATE_24 */ + case 9 : + pAd->ApCfg.MBSSID[apidx].ExpectedSuppRate[supp_rate_num]= 0x48; + pAd->ApCfg.MBSSID[apidx].ExpectedDesireRate[des_rate_num] = 72; + supp_rate_num++; + des_rate_num++; + break; /* RATE_36 */ + case 10: + if (bABandPhyMode == TRUE) + { + pAd->ApCfg.MBSSID[apidx].ExpectedSuppRate[supp_rate_num]= 0x60; + supp_rate_num++; + } + else + { + pAd->ApCfg.MBSSID[apidx].ExpectedExtRate[ext_rate_num]= 0x60; + ext_rate_num++; + } + + pAd->ApCfg.MBSSID[apidx].ExpectedDesireRate[des_rate_num] = 96; + des_rate_num++; + break; /* RATE_48 */ + case 11: + pAd->ApCfg.MBSSID[apidx].ExpectedSuppRate[supp_rate_num]= 0x6C; + pAd->ApCfg.MBSSID[apidx].ExpectedDesireRate[des_rate_num] = 108; + supp_rate_num++; + des_rate_num++; + break; /* RATE_54 */ + } + } + } + + pAd->ApCfg.MBSSID[apidx].ExpectedSuppRateLen = supp_rate_num; + pAd->ApCfg.MBSSID[apidx].ExpectedExtRateLen = ext_rate_num; + + NdisZeroMemory(pAd->ApCfg.MBSSID[apidx].SupRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisZeroMemory(pAd->ApCfg.MBSSID[apidx].ExtRate, MAX_LEN_OF_SUPPORTED_RATES); + NdisZeroMemory(pAd->ApCfg.MBSSID[apidx].DesireRate, MAX_LEN_OF_SUPPORTED_RATES); + + NdisMoveMemory(pAd->ApCfg.MBSSID[apidx].SupRate, pAd->ApCfg.MBSSID[apidx].ExpectedSuppRate, supp_rate_num); + pAd->ApCfg.MBSSID[apidx].SupRateLen = supp_rate_num; + DBGPRINT(RT_DEBUG_OFF, ("BSS%d SupRateLen=%x\n", apidx, pAd->ApCfg.MBSSID[apidx].SupRateLen)); + NdisMoveMemory(pAd->ApCfg.MBSSID[apidx].ExtRate, pAd->ApCfg.MBSSID[apidx].ExpectedExtRate, ext_rate_num); + pAd->ApCfg.MBSSID[apidx].ExtRateLen = ext_rate_num; + DBGPRINT(RT_DEBUG_OFF, ("BSS%d ExtRateLen=%x\n", apidx, pAd->ApCfg.MBSSID[apidx].ExtRateLen)); + NdisMoveMemory(pAd->ApCfg.MBSSID[apidx].DesireRate, pAd->ApCfg.MBSSID[apidx].ExpectedDesireRate, des_rate_num); + } +} + +VOID UpdateSuppHTRateBitmap( + IN RTMP_ADAPTER *pAd) +{ + UCHAR idx = 0, j = 0; + ULONG bitmap = 0; + UCHAR apidx = 0; + + for(apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + idx = 0; + j = 0; + bitmap = pAd->ApCfg.MBSSID[apidx].SuppHTRateBitmap; + + NdisZeroMemory(&pAd->ApCfg.MBSSID[apidx].ExpectedSuppHTMCSSet[0], 16); + + for(idx=0; idx < MAX_LEN_OF_HT_RATES; idx++) + { + if (bitmap & (1 << idx)) + { + j = idx / 8; + pAd->ApCfg.MBSSID[apidx].ExpectedSuppHTMCSSet[j] |= (1 << (idx % 8)); + } + } + } +} +#endif /* DYNAMIC_RX_RATE_ADJ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mt_io.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mt_io.c new file mode 100644 index 000000000..07211de7f --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mt_io.c @@ -0,0 +1,132 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of MediaTek. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + mt_io.c +*/ +#include "rt_config.h" + +UINT32 mt_mac_cr_range[] = { + 0x60000000, 0x20000, 0x200, /* WF_CFG */ + 0x60100000, 0x21000, 0x200, /* WF_TRB */ + 0x60110000, 0x21200, 0x200, /* WF_AGG */ + 0x60120000, 0x21400, 0x200, /* WF_ARB */ + 0x60130000, 0x21600, 0x200, /* WF_TMAC */ + 0x60140000, 0x21800, 0x200, /* WF_RMAC */ + 0x60150000, 0x21A00, 0x200, /* WF_SEC */ + 0x60160000, 0x21C00, 0x200, /* WF_DMA */ + 0x60170000, 0x21E00, 0x200, /* WF_CFGOFF */ + 0x60180000, 0x22000, 0x1000, /* WF_PF */ + 0x60190000, 0x23000, 0x200, /* WF_WTBLOFF */ + 0x601A0000, 0x23200, 0x200, /* WF_ETBF */ + + 0x60300000, 0x24000, 0x400, /* WF_LPON */ + 0x60310000, 0x24400, 0x200, /* WF_INT */ + 0x60320000, 0x28000, 0x4000, /* WF_WTBLON */ + 0x60330000, 0x2C000, 0x200, /* WF_MIB */ + 0x60400000, 0x2D000, 0x200, /* WF_AON */ + + 0x80020000, 0x00000, 0x2000, /* TOP_CFG */ + 0x80000000, 0x02000, 0x2000, /* MCU_CFG */ + 0x50000000, 0x04000, 0x4000, /* PDMA_CFG */ +#if defined(MT7603_FPGA) || defined(MT7628_FPGA) + 0xA0000000, 0x80000, 0x10000, /* PSE_CFG after remap 2 */ +#else + 0xA0000000, 0x08000, 0x8000, /* PSE_CFG */ +#endif /* MT7603_FPGA */ + 0x60200000, 0x10000, 0x10000, /* WF_PHY */ + + 0x0, 0x0, 0x0, +}; + + +BOOLEAN mt_mac_cr_range_mapping(UINT32 *mac_addr) +{ + UINT32 mac_addr_hif = *mac_addr; + INT idx = 0; + BOOLEAN IsFound = 0; + + if (mac_addr_hif > 0x4ffff) + { + do + { + if (mac_addr_hif >= mt_mac_cr_range[idx] && + mac_addr_hif < (mt_mac_cr_range[idx] + mt_mac_cr_range[idx + 2])) + { + mac_addr_hif -= mt_mac_cr_range[idx]; + mac_addr_hif += mt_mac_cr_range[idx + 1]; + IsFound = 1; + break; + } + idx += 3; + } while (mt_mac_cr_range[idx] != 0); + } + else + { + IsFound = 1; + } + + *mac_addr = mac_addr_hif; + + return IsFound; +} + + +UINT32 mt_physical_addr_map(UINT32 addr) +{ + UINT32 global_addr = 0x0, idx = 1; + + if (addr < 0x2000) + global_addr = 0x80020000 + addr; + else if ((addr >= 0x2000) && (addr < 0x4000)) + global_addr = 0x80000000 + addr - 0x2000; + else if ((addr >= 0x4000) && (addr < 0x8000)) + global_addr = 0x50000000 + addr - 0x4000; + else if ((addr >= 0x8000) && (addr < 0x10000)) + global_addr = 0xa0000000 + addr - 0x8000; + else if ((addr >= 0x10000) && (addr < 0x20000)) + global_addr = 0x60200000 + addr - 0x10000; + else if ((addr >= 0x20000) && (addr < 0x40000)) + { + do { + if ((addr >= mt_mac_cr_range[idx]) && (addr < (mt_mac_cr_range[idx]+mt_mac_cr_range[idx+1]))) { + global_addr = mt_mac_cr_range[idx-1]+(addr-mt_mac_cr_range[idx]); + break; + } + idx += 3; + } while (mt_mac_cr_range[idx] != 0); + + if (mt_mac_cr_range[idx] == 0) + { + DBGPRINT(RT_DEBUG_OFF, ("unknow addr range = %x\n", addr)); + } + } + else if ((addr >= 0x40000) && (addr < 0x80000)) //WTBL Address + { + global_addr = 0xa5000000 + addr - 0x40000; + DBGPRINT(RT_DEBUG_INFO, ("==>global_addr1=0x%x\n", global_addr)); + } + else if ((addr >= 0xc0000) && (addr < 0xc0100)) //PSE Client + { + global_addr = 0x800c0000 + addr - 0xc0000; + DBGPRINT(RT_DEBUG_INFO, ("==>global_addr2=0x%x\n", global_addr)); + } + else + { + global_addr = addr; + DBGPRINT(RT_DEBUG_INFO, ("==>global_addr3=0x%x\n", global_addr)); + } + + return global_addr; +} + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mt_ps.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mt_ps.c new file mode 100644 index 000000000..bee9ccf2a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mt_ps.c @@ -0,0 +1,666 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2010, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + + Abstract: + + All related POWER SAVE function body. + +***************************************************************************/ + +#include "rt_config.h" + +#ifdef MT_PS +static VOID MtReadPseRdTabAccessReg( + RTMP_ADAPTER *pAd, + UCHAR wcid, + UINT32 *p_rPseRdTabAccessReg) +{ + *p_rPseRdTabAccessReg = PSE_RTA_RD_KICK_BUSY | PSE_RTA_TAG(wcid); + RTMP_IO_WRITE32(pAd, PSE_RTA, *p_rPseRdTabAccessReg); + do + { + RTMP_IO_READ32(pAd,PSE_RTA, p_rPseRdTabAccessReg); + } + while ( GET_PSE_RTA_RD_KICK_BUSY(*p_rPseRdTabAccessReg) == 1 ); + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("%s: *p_rPseRdTabAccessReg = 0x%x\n", + __FUNCTION__, *p_rPseRdTabAccessReg)); +} + + +static VOID MtClearPseRdTab( + RTMP_ADAPTER *pAd, + UCHAR wcid ) +{ + UINT32 rPseRdTabAccessReg = 0; + rPseRdTabAccessReg = PSE_RTA_RD_RW | PSE_RTA_RD_KICK_BUSY | PSE_RTA_TAG(wcid); + RTMP_IO_WRITE32(pAd, PSE_RTA, rPseRdTabAccessReg); + do + { + RTMP_IO_READ32(pAd,PSE_RTA, &rPseRdTabAccessReg); + } + while ( GET_PSE_RTA_RD_KICK_BUSY(rPseRdTabAccessReg) == 1 ); + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("%s: rPseRdTabAccessReg = 0x%x wcid=%d\n", + __FUNCTION__, rPseRdTabAccessReg, wcid)); +} + +VOID MtSetIgnorePsm( + RTMP_ADAPTER *pAd, + MAC_TABLE_ENTRY *pEntry, + UCHAR value) +{ +#ifdef RTMP_PCI_SUPPORT + ULONG IrqFlags = 0; +#endif /* RTMP_PCI_SUPPORT */ + struct wtbl_entry tb_entry; + union WTBL_1_DW3 *dw3 = (union WTBL_1_DW3 *)&tb_entry.wtbl_1.wtbl_1_d3.word; + + NdisZeroMemory(&tb_entry, sizeof(tb_entry)); + + if (mt_wtbl_get_entry234(pAd, pEntry->wcid, &tb_entry) == FALSE) + { + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("%s():Cannot found WTBL2/3/4\n",__FUNCTION__)); + return; + } + +#ifdef RTMP_PCI_SUPPORT + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); +#endif /* RTMP_PCI_SUPPORT */ + + pEntry->i_psm = value; + RTMP_IO_READ32(pAd, tb_entry.wtbl_addr[0]+12, &dw3->word); + dw3->field.du_i_psm = value; /* I_PSM changed by HW automatically is enabled. */ + dw3->field.i_psm = value; /* follow PSM value. */ + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + 12, dw3->word); + +#ifdef RTMP_PCI_SUPPORT + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); +#endif /* RTMP_PCI_SUPPORT */ +} + +VOID CheckSkipTX( + RTMP_ADAPTER *pAd, + MAC_TABLE_ENTRY *pEntry) +{ + struct wtbl_entry tb_entry; + union WTBL_1_DW3 *dw3 = (union WTBL_1_DW3 *)&tb_entry.wtbl_1.wtbl_1_d3.word; + STA_TR_ENTRY *tr_entry; + CHAR isChange = FALSE; + + NdisZeroMemory(&tb_entry, sizeof(tb_entry)); + if (mt_wtbl_get_entry234(pAd, pEntry->wcid, &tb_entry) == FALSE) + { + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("%s():Cannot found WTBL2/3/4\n",__FUNCTION__)); + return; + } + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + + RTMP_IO_READ32(pAd, tb_entry.wtbl_addr[0]+12, &dw3->word); + if ((tr_entry->ps_state != APPS_RETRIEVE_START_PS) && (dw3->field.skip_tx == 1)) + { + dw3->field.skip_tx = 0; + isChange = TRUE; + } + + if ((tr_entry->ps_state < APPS_RETRIEVE_DONE) && (dw3->field.du_i_psm == 1)) + { + dw3->field.du_i_psm = 0; + dw3->field.i_psm = 0; + /* also sync pEntry flag*/ + pEntry->i_psm = 0 ; + isChange = TRUE; + } + + if (isChange == TRUE) { + pAd->SkipTxRCount++; + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0]+12, dw3->word); + } + return; +} + +#endif /* MT_PS */ + +#ifdef MT7603 +INT MtPSDummyCR(RTMP_ADAPTER *pAd) +{ + INT value; + + RTMP_IO_READ32(pAd, 0x817c, &value); + value &= 0xff; + return value; +} + +#ifdef RTMP_MAC_PCI +VOID MtTriggerMCUINT(RTMP_ADAPTER *pAd) +{ + INT value; + INT restore_remap_addr; + + RTMP_IO_READ32(pAd, 0x2504, &restore_remap_addr); + RTMP_IO_WRITE32(pAd, 0x2504, 0x81000000); + RTMP_IO_READ32(pAd, 0xc00c0, &value); + value |= 0x100; + RTMP_IO_WRITE32(pAd, 0xc00c0, value); //Trigger INT to MCU, 0x810400c0 + RTMP_IO_WRITE32(pAd, 0x2504, restore_remap_addr); +} +#endif /* RTMP_MAC_PCI */ + +BOOLEAN MtStartPSRetrieve(RTMP_ADAPTER *pAd, USHORT wcid) +{ + NdisAcquireSpinLock(&pAd->PSRetrieveLock); + if (MtPSDummyCR(pAd) != 0) { + NdisReleaseSpinLock(&pAd->PSRetrieveLock); + return FALSE; + } + + RTMP_IO_WRITE32(pAd, 0x817c, wcid); + +#ifdef RTMP_MAC_PCI +// MtTriggerMCUINT(pAd); +#endif /* RTMP_MAC_PCI */ + NdisReleaseSpinLock(&pAd->PSRetrieveLock); + return TRUE; +} +#endif + +/* + ======================================================================== + 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 MtHandleRxPsPoll(RTMP_ADAPTER *pAd, UCHAR *pAddr, USHORT wcid, BOOLEAN isActive) +{ +#ifdef CONFIG_AP_SUPPORT +#if defined(MT_PS) || defined(UAPSD_SUPPORT) + MAC_TABLE_ENTRY *pMacEntry; +#endif + STA_TR_ENTRY *tr_entry; + BOOLEAN IsDequeu= FALSE; + INT DequeuAC = QID_AC_BE; + INT DequeuCOUNT; +#ifdef MT_PS + INT i, Total_Packet_Number = 0; + unsigned long IrqFlags = 0; +#endif /* MT_PS */ + //struct tx_swq_fifo *fifo_swq; + + ASSERT(wcid < MAX_LEN_OF_MAC_TABLE); +#if defined(MT_PS) || defined(UAPSD_SUPPORT) + pMacEntry = &pAd->MacTab.Content[wcid]; +#endif + tr_entry = &pAd->MacTab.tr_entry[wcid]; + + if (isActive == FALSE) /* ps poll */ + { +#ifdef MT_PS + if (tr_entry->ps_state == APPS_RETRIEVE_DONE) /*state is finish(sleep)*/ + { + if (pMacEntry->i_psm == I_PSM_DISABLE) + { + MT_SET_IGNORE_PSM(pAd, pMacEntry, I_PSM_ENABLE); + } + } + + if(tr_entry->ps_state == APPS_RETRIEVE_DONE || tr_entry->ps_state == APPS_RETRIEVE_IDLE) + { + for (i = 0; i < WMM_QUE_NUM; i++) + Total_Packet_Number = Total_Packet_Number + tr_entry->tx_queue[i].Number; + + if (Total_Packet_Number > 0) + { + { + DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_PS, ("RtmpHandleRxPsPoll fetch tx queue tr_entry->ps_queue.Number= %x tr_entry->tx_queue[0].Number=%x Total_Packet_Number=%x\n", + tr_entry->ps_queue.Number, tr_entry->tx_queue[QID_AC_BE].Number, Total_Packet_Number)); + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + for (i = (WMM_QUE_NUM - 1); i >=0; i--) + { + if (tr_entry->tx_queue[i].Head) + { + if (Total_Packet_Number > 1) + { + RTMP_SET_PACKET_MOREDATA(RTPKT_TO_OSPKT(tr_entry->tx_queue[i].Head), TRUE); + } + RTMP_SET_PACKET_TXTYPE(RTPKT_TO_OSPKT(tr_entry->tx_queue[i].Head), TX_LEGACY_FRAME); + + DequeuAC = i; + IsDequeu = TRUE; + DequeuCOUNT = 1; + tr_entry->PsQIdleCount = 0; + break; + } + } + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + } + } + else /* Recieve ps_poll but no packet==>send NULL Packet */ + { + BOOLEAN bQosNull = FALSE; + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("RtmpHandleRxPsPoll no packet tr_entry->ps_queue.Number= %x tr_entry->tx_queue[0].Number=%x Total_Packet_Number=%x\n" + ,tr_entry->ps_queue.Number, tr_entry->tx_queue[QID_AC_BE].Number, Total_Packet_Number)); + if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)) + bQosNull = TRUE; + + RtmpEnqueueNullFrame(pAd, pMacEntry->Addr, tr_entry->CurrTxRate, + pMacEntry->Aid, pMacEntry->func_tb_idx, + bQosNull, TRUE, 0); + } + if (Total_Packet_Number >1) + { + WLAN_MR_TIM_BIT_SET(pAd, tr_entry->func_tb_idx, tr_entry->wcid); + } + else + { + WLAN_MR_TIM_BIT_CLEAR(pAd, tr_entry->func_tb_idx, tr_entry->wcid); + } + } else + tr_entry->PsDeQWaitCnt = 0; +#else + /* + Need to check !! @20140212 + New architecture has per AC sw-Q for per entry. + We should check packets by ACs priority --> 1. VO, 2. VI, 3. BE, 4. BK + */ + DequeuAC = QID_AC_BE; + IsDequeu = TRUE; + DequeuCOUNT = 1; + tr_entry->PsQIdleCount = 0; +#endif /* Ps_poll and ifndef MT_PS */ + + } + else /* Receive Power bit 0 frame */ + { + WLAN_MR_TIM_BIT_CLEAR(pAd, tr_entry->func_tb_idx, tr_entry->wcid); +#ifdef MT_PS + if (pMacEntry->i_psm == I_PSM_ENABLE) + { + MT_SET_IGNORE_PSM(pAd, pMacEntry, I_PSM_DISABLE); + } +#endif /*Power bit is 1 and ifndef MT_PS */ + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("RtmpHandleRxPsPoll null0/1 wcid = %x mt_ps_queue.Number = %d\n", + tr_entry->wcid, + tr_entry->ps_queue.Number)); + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("%s(%d) tx_queue.Number = BE:%d, BK:%d, VI:%d, VO:%d, ps_state:%x, tx_queue.TokenCount = BE:%d, BK:%d, VI:%d, VO:%d\n", + __FUNCTION__, __LINE__, + tr_entry->tx_queue[QID_AC_BE].Number, + tr_entry->tx_queue[QID_AC_BK].Number, + tr_entry->tx_queue[QID_AC_VI].Number, + tr_entry->tx_queue[QID_AC_VO].Number, + tr_entry->ps_state, + tr_entry->TokenCount[QID_AC_BE], + tr_entry->TokenCount[QID_AC_BK], + tr_entry->TokenCount[QID_AC_VI], + tr_entry->TokenCount[QID_AC_VO])); + +#ifdef UAPSD_SUPPORT + if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_APSD_CAPABLE)) + { + /* deliver all queued UAPSD packets */ + UAPSD_AllPacketDeliver(pAd, pMacEntry); + + /* end the SP if exists */ + UAPSD_MR_ENTRY_RESET(pAd, pMacEntry); + } +#endif /* UAPSD_SUPPORT */ + + if (tr_entry->enqCount > 0) + { + IsDequeu = TRUE; + DequeuAC = NUM_OF_TX_RING; + if (tr_entry->enqCount > MAX_TX_PROCESS) + { + DequeuCOUNT = MAX_TX_PROCESS; + rtmp_ps_enq(pAd,tr_entry); + } + else + { + DequeuCOUNT = tr_entry->enqCount; + } + } + } + + if (IsDequeu == TRUE) + { + RTMPDeQueuePacket(pAd, FALSE, DequeuAC, tr_entry->wcid, DequeuCOUNT); + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("RtmpHandleRxPsPoll IsDequeu == TRUE tr_entry->wcid=%x DequeuCOUNT=%d, ps_state=%d\n",tr_entry->wcid, DequeuCOUNT, tr_entry->ps_state)); + } + return; + +#endif /* CONFIG_AP_SUPPORT */ +} + +VOID PsRetrieveTimeout(RTMP_ADAPTER *pAd, STA_TR_ENTRY *tr_entry) +{ + UCHAR ps_state_tmp; + + ps_state_tmp = tr_entry->ps_state; + if (tr_entry->PsMode == PWR_ACTIVE) + tr_entry->ps_state = APPS_RETRIEVE_IDLE; + else + tr_entry->ps_state = APPS_RETRIEVE_DONE; + + MtPsRedirectDisableCheck(pAd, tr_entry->wcid); + +/* + DBGPRINT(RT_DEBUG_OFF, ("%s() Recover ps state(state %d to state %d) [wcid = %d]!!\n", + __func__, ps_state_tmp, tr_entry->ps_state, tr_entry->wcid)); +*/ +} + +/* + ========================================================================== + 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 MtPsIndicate(RTMP_ADAPTER *pAd, UCHAR *pAddr, UCHAR wcid, UCHAR Psm) +{ + MAC_TABLE_ENTRY *pEntry; + UCHAR old_psmode; + STA_TR_ENTRY *tr_entry; + + if (wcid >= MAX_LEN_OF_MAC_TABLE) + { + return PWR_ACTIVE; + } + + pEntry = &pAd->MacTab.Content[wcid]; + tr_entry = &pAd->MacTab.tr_entry[wcid]; + + /* + Change power save mode first because we will call + RTMPDeQueuePacket() in RtmpHandleRxPsPoll(). + + Or when Psm = PWR_ACTIVE, we will not do Aggregation in + RTMPDeQueuePacket(). + */ + old_psmode = pEntry->PsMode; + pEntry->NoDataIdleCount = 0; + pEntry->PsMode = Psm; + pAd->MacTab.tr_entry[wcid].PsMode = Psm; + + if ((old_psmode == PWR_SAVE) && (Psm == PWR_ACTIVE)) + { + /* + STA wakes up. + */ + if(tr_entry->ps_state == APPS_RETRIEVE_DONE) + { + tr_entry->ps_state = APPS_RETRIEVE_IDLE; + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("%s(%d): STA wakes up!\n", __FUNCTION__, __LINE__)); + MtHandleRxPsPoll(pAd, pAddr, wcid, TRUE); + } + else + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("%s(%d):wcid=%d, old_psmode=%d, now_psmode=%d, wrong ps_state=%d ???\n", + __FUNCTION__, __LINE__, wcid, old_psmode, Psm, tr_entry->ps_state)); + } + else if ((old_psmode == PWR_ACTIVE) && (Psm == PWR_SAVE)) + { + /* + STA goes to sleep. + */ + + if (tr_entry->ps_state == APPS_RETRIEVE_IDLE) + { +#ifdef MT_PS + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("%s(%d):wcid=%d, old_psmode=%d, now_psmode=%d, ps_state=%d start retrieving!!\n", + __FUNCTION__, __LINE__, wcid, old_psmode, Psm, tr_entry->ps_state)); + +#if defined(MT7603) && defined(RTMP_PCI_SUPPORT) + if (MtStartPSRetrieve(pAd, wcid) == TRUE) { + tr_entry->ps_state = APPS_RETRIEVE_START_PS; + tr_entry->ps_start_time = jiffies; + } else { + struct tx_swq_fifo *ps_fifo_swq; + INT enq_idx; + + ps_fifo_swq = &pAd->apps_cr_q; + enq_idx = ps_fifo_swq->enqIdx; + if (ps_fifo_swq->swq[enq_idx] == 0) + { + ps_fifo_swq->swq[enq_idx] = wcid; + INC_RING_INDEX(ps_fifo_swq->enqIdx, TX_SWQ_FIFO_LEN); + tr_entry->ps_state = APPS_RETRIEVE_CR_PADDING; + } else { + INT idx; + tr_entry->ps_state = APPS_RETRIEVE_DONE; + DBGPRINT(RT_DEBUG_ERROR, ("%s: ERROR!! ps_fifo_swq->deqIdx=%d, ps_fifo_swq->enqIdx=%d\n", __FUNCTION__,ps_fifo_swq->deqIdx,ps_fifo_swq->enqIdx)); + for (idx =0; idx < TX_SWQ_FIFO_LEN;idx++) { + DBGPRINT(RT_DEBUG_ERROR, (",[%d] =%d\n", idx, ps_fifo_swq->swq[idx])); + if ((idx % 16) == 0) + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + } + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + } + } +#else /* !MT7603 && RTMP_PCI_SUPPORT */ + RTEnqueueInternalCmd(pAd, CMDTHREAD_PS_RETRIEVE_START, pEntry, sizeof(MAC_TABLE_ENTRY)); +#endif /* MT7603 && RTMP_PCI_SUPPORT */ +#else /* MT_PS */ + tr_entry->ps_state = APPS_RETRIEVE_DONE; +#endif /* !MT_PS */ + } + else + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("%s(%d):wcid=%d, old_psmode=%d, now_psmode=%d, wrong ps_state=%d ???\n", + __FUNCTION__, __LINE__, wcid, old_psmode, Psm, tr_entry->ps_state)); + } + else + { + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("%s(%d): ps state is not changed, do nothing here.\n", + __FUNCTION__, __LINE__)); + } + + return old_psmode; +} + +#ifdef MT_PS +VOID MtPsRedirectDisableCheck( + RTMP_ADAPTER *pAd, + UCHAR wcid) +{ + UINT32 Reg = 0, wlan_idx = 0; + BOOLEAN pfgForce = 0; + + if (pAd->chipCap.hif_type != HIF_MT) + { + return; + } + + MtReadPseRdTabAccessReg(pAd, wcid, &Reg); + + pfgForce = ( BOOLEAN ) GET_PSE_RTA_RD_RULE_F(Reg); + + if (pfgForce) + { + wlan_idx = (UINT32)wcid; + DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("%s(%d): [wlan_idx=0x%x] PS Redirect mode(pfgForce = %d) is enabled. Send PC Clear command to FW.\n", + __FUNCTION__, __LINE__, wlan_idx, pfgForce)); + //RTEnqueueInternalCmd(pAd, CMDTHREAD_PS_CLEAR, (VOID *)&wlan_idx, sizeof(UINT32)); + /* clear CR directly instead of inband cmd, PSE Reset may lead cmd is not success */ + MtClearPseRdTab(pAd, wlan_idx); + } + +} + +VOID MtPsSendToken( + RTMP_ADAPTER *pAd, + UINT32 WlanIdx) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + STA_TR_ENTRY *tr_entry; + NDIS_STATUS token_status; + struct wtbl_entry tb_entry; + union WTBL_1_DW3 *dw3; + UINT32 Reg = 0; + BOOLEAN pfgForce = 0; + unsigned char q_idx; + + if (pAd->chipCap.hif_type != HIF_MT) + { + return; + } + + DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("%s(wcid=%d): Driver didn't receive PsRetrieveStartRsp from FW.\n",__FUNCTION__, WlanIdx)); + pEntry = &pAd->MacTab.Content[WlanIdx]; + + tr_entry = &pAd->MacTab.tr_entry[WlanIdx]; + NdisZeroMemory(&tb_entry, sizeof(tb_entry)); + dw3 = (union WTBL_1_DW3 *)&tb_entry.wtbl_1.wtbl_1_d3.word; + + if (mt_wtbl_get_entry234(pAd, WlanIdx, &tb_entry) == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("%s():Cannot found WTBL2/3/4, wcid=%d\n",__FUNCTION__, WlanIdx)); + return; + } + + RTMP_IO_READ32(pAd, tb_entry.wtbl_addr[0]+12, &dw3->word); + + MtReadPseRdTabAccessReg(pAd, pEntry->wcid, &Reg); + + pfgForce = ( BOOLEAN ) GET_PSE_RTA_RD_RULE_F(Reg); + + if (pfgForce == 0) + { + DBGPRINT(RT_DEBUG_WARN | DBG_FUNC_PS, ("%s(ps_state = %d): PS Redirect mode didn't be enabled. Driver doesn't need to send token.\n",__FUNCTION__, tr_entry->ps_state)); + DBGPRINT(RT_DEBUG_WARN | DBG_FUNC_PS, ("%s: Reset ps_state to IDLE.\n",__FUNCTION__)); + tr_entry->ps_state = APPS_RETRIEVE_IDLE; + return; + } + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("---->%s: Start to send TOKEN frames.\n", __FUNCTION__)); + + tr_entry->ps_state = APPS_RETRIEVE_GOING; + + tr_entry->ps_qbitmap = 0; + + for (q_idx = 0; q_idx < NUM_OF_TX_RING; q_idx++) + { + token_status = RtmpEnqueueTokenFrame(pAd, &(pEntry->Addr[0]), 0, WlanIdx, 0, q_idx); + if (!token_status) + tr_entry->ps_qbitmap |= (1 << q_idx); + else + DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("%s(%d) Fail: Send TOKEN Frame, AC=%d\n", __FUNCTION__, __LINE__, q_idx)); + } + + if (tr_entry->ps_qbitmap == 0) + { + tr_entry->ps_state = APPS_RETRIEVE_WAIT_EVENT; + RTEnqueueInternalCmd(pAd, CMDTHREAD_PS_CLEAR, (VOID *)&WlanIdx, sizeof(UINT32)); + DBGPRINT(RT_DEBUG_WARN | DBG_FUNC_PS, ("(ps_state = %d) token enqueue failed for all queues ==> send CMDTHREAD_PS_CLEAR cmd.\n", tr_entry->ps_state)); + } +} + +VOID MtPsRecovery( + RTMP_ADAPTER *pAd) +{ + MAC_TABLE_ENTRY *pMacEntry; + STA_TR_ENTRY *tr_entry; + UINT32 i; + + for (i=1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + pMacEntry = &pAd->MacTab.Content[i]; + tr_entry = &pAd->MacTab.tr_entry[i]; + if (IS_ENTRY_CLIENT(pMacEntry)) + { + if (tr_entry->ps_state == APPS_RETRIEVE_CR_PADDING) { + tr_entry->ps_state = APPS_RETRIEVE_IDLE; + } else if ((tr_entry->ps_state == APPS_RETRIEVE_START_PS) + || (tr_entry->ps_state == APPS_RETRIEVE_GOING)) + { + if (tr_entry->ps_queue.Number) { + MtEnqTxSwqFromPsQueue(pAd, QID_AC_BE, tr_entry); + } + + + if (pAd->MacTab.tr_entry[i].PsMode == PWR_ACTIVE) { + tr_entry->ps_state = APPS_RETRIEVE_IDLE; + MtHandleRxPsPoll(pAd, &pMacEntry->Addr[0], i, TRUE); + } else + tr_entry->ps_state = APPS_RETRIEVE_DONE; + } else if(tr_entry->ps_state == APPS_RETRIEVE_WAIT_EVENT) + { + RTEnqueueInternalCmd(pAd, CMDTHREAD_PS_CLEAR, (VOID *)&i, sizeof(UINT32)); + } + } + } +} + + +VOID MtEnqTxSwqFromPsQueue(RTMP_ADAPTER *pAd, UCHAR qidx, STA_TR_ENTRY *tr_entry) +{ + ULONG IrqFlags = 0; + //struct tx_swq_fifo *fifo_swq; + QUEUE_ENTRY *pQEntry; + QUEUE_HEADER *pAcPsQue; + QUEUE_HEADER *pAcTxQue; +#ifdef UAPSD_SUPPORT + MAC_TABLE_ENTRY *pEntry = &pAd->MacTab.Content[tr_entry->wcid]; +#endif /* UAPSD_SUPPORT */ + + //fifo_swq = &pAd->tx_swq[qidx]; + pAcPsQue = &tr_entry->ps_queue; + pAcTxQue = &tr_entry->tx_queue[qidx]; + + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); +#ifdef UAPSD_SUPPORT + if (UAPSD_MR_IS_UAPSD_AC(pEntry, qidx)) + { + while(pAcPsQue->Head) + { + pQEntry = RemoveTailQueue(pAcPsQue); + UAPSD_PacketEnqueue(pAd, pEntry, PACKET_TO_QUEUE_ENTRY(pQEntry), qidx, TRUE); + } + } + else +#endif /* UAPSD_SUPPORT */ + { + /*check and insert PS Token queue*/ + if(pAcPsQue->Number > 0 && tr_entry->wcid > 0 && tr_entry->wcid < MAX_LEN_OF_TR_TABLE) + { + rtmp_ps_enq(pAd,tr_entry); + DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_PS, ("pAcPsQue->Number=%d,PS:%d\n",pAcPsQue->Number,tr_entry->PsTokenFlag)); + } + + while(pAcPsQue->Head) + { + pQEntry = RemoveTailQueue(pAcPsQue); + if(tr_entry->enqCount > SQ_ENQ_NORMAL_MAX) { + RELEASE_NDIS_PACKET(pAd, QUEUE_ENTRY_TO_PACKET(pQEntry), NDIS_STATUS_FAILURE); + continue; + } + InsertHeadQueue(pAcTxQue, pQEntry); +#ifdef LIMIT_GLOBAL_SW_QUEUE + TR_ENQ_COUNT_INC(tr_entry, &pAd->TxSwQueue[qidx]); +#else /* LIMIT_GLOBAL_SW_QUEUE */ + TR_ENQ_COUNT_INC(tr_entry); +#endif /* ! LIMIT_GLOBAL_SW_QUEUE */ + } + } + RTMP_IRQ_UNLOCK(&pAd->irq_lock, IrqFlags); + + return; +} +#endif /* MT_PS */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mtsdio_data.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mtsdio_data.c new file mode 100644 index 000000000..b07b1fdd7 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mtsdio_data.c @@ -0,0 +1,710 @@ +/* + *************************************************************************** + * 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: + mtsdio_data.c +*/ + +#include "rt_config.h" + + +/* <-------------- to be removed to another header file */ + + +void MTSDIOProcessSoftwareInterrupt(IN RTMP_ADAPTER *pAd); +void MTSDIOProcessFwOwnBackInterrupt(IN RTMP_ADAPTER *pAd); +void MTSDIOProcessAbnormalInterrupt(IN RTMP_ADAPTER *pAd); +void MTSDIOProcessTxInterrupt(IN RTMP_ADAPTER *pAd); +void MTSDIOProcessRxInterrupt(IN RTMP_ADAPTER *pAd); +INT32 MTSDIOSingleProcessRx0(RTMP_ADAPTER *pAd, INT32 Length); +INT32 MTSDIOSingleProcessRx1(RTMP_ADAPTER *pAd, INT32 Length); + +typedef struct _INT_EVENT_MAP_T { + UINT32 u4Int; + UINT32 u4Event; +} INT_EVENT_MAP_T, *P_INT_EVENT_MAP_T; + +typedef VOID (*IST_EVENT_FUNCTION)(RTMP_ADAPTER *); + +enum ENUM_INT_EVENT_T { + INT_EVENT_ABNORMAL, + INT_EVENT_SW_INT, + INT_EVENT_TX, + INT_EVENT_RX, + INT_EVENT_NUM +}; + +#define PORT_INDEX_LMAC 0 +#define PORT_INDEX_MCU 1 + +/* MCU quque index */ +typedef enum _ENUM_MCU_Q_INDEX_T { + MCU_Q0_INDEX = 0, + MCU_Q1_INDEX, + MCU_Q2_INDEX, + MCU_Q3_INDEX, + MCU_Q_NUM +} ENUM_MCU_Q_INDEX_T; + +/* LMAC Tx queue index */ +typedef enum _ENUM_MAC_TXQ_INDEX_T { + MAC_TXQ_AC0_INDEX = 0, + MAC_TXQ_AC1_INDEX, + MAC_TXQ_AC2_INDEX, + MAC_TXQ_AC3_INDEX, + MAC_TXQ_AC4_INDEX, + MAC_TXQ_AC5_INDEX, + MAC_TXQ_AC6_INDEX, + MAC_TXQ_BMC_INDEX, + MAC_TXQ_BCN_INDEX, + MAC_TXQ_AC10_INDEX, + MAC_TXQ_AC11_INDEX, + MAC_TXQ_AC12_INDEX, + MAC_TXQ_AC13_INDEX, + MAC_TXQ_AC14_INDEX, + MAC_TXQ_NUM +} ENUM_MAC_TXQ_INDEX_T; + +/* HIF Tx interrupt status queue index*/ +typedef enum _ENUM_HIF_TX_INDEX_T { + HIF_TX_AC0_INDEX = 0, /* HIF TX: AC0 packets */ + HIF_TX_AC1_INDEX, /* HIF TX: AC1 packets */ + HIF_TX_AC2_INDEX, /* HIF TX: AC2 packets */ + HIF_TX_AC3_INDEX, /* HIF TX: AC3 packets */ + HIF_TX_AC4_INDEX, /* HIF TX: AC4 packets */ + HIF_TX_AC5_INDEX, /* HIF TX: AC5 packets */ + HIF_TX_AC6_INDEX, /* HIF TX: AC6 packets */ + HIF_TX_BMC_INDEX, /* HIF TX: BMC packets */ + HIF_TX_BCN_INDEX, /* HIF TX: BCN packets */ + HIF_TX_AC10_INDEX, /* HIF TX: AC10 packets */ + HIF_TX_AC11_INDEX, /* HIF TX: AC11 packets */ + HIF_TX_AC12_INDEX, /* HIF TX: AC12 packets */ + HIF_TX_AC13_INDEX, /* HIF TX: AC13 packets */ + HIF_TX_AC14_INDEX, /* HIF TX: AC14 packets */ + HIF_TX_FFA_INDEX, /* HIF TX: free-for-all */ + HIF_TX_CPU_INDEX, /* HIF TX: CPU */ + HIF_TX_NUM /* Maximum number of HIF TX port. */ +} ENUM_HIF_TX_INDEX_T; + +typedef struct _TX_RESOURCE_CONTROL_T { + /* HW TX queue definition */ + UINT8 ucDestPortIndex; + UINT8 ucDestQueueIndex; + /* HIF Interrupt status index*/ + UINT8 ucHifTxQIndex; +} TX_RESOURCE_CONTROL_T, *PTX_RESOURCE_CONTROL_T; + +static const TX_RESOURCE_CONTROL_T arTcResourceControl[TC_NUM] = { + /* dest port index, dest queue index, HIF TX queue index */ + /* First HW queue */ + {PORT_INDEX_LMAC, MAC_TXQ_AC0_INDEX, HIF_TX_AC0_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC1_INDEX, HIF_TX_AC1_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC2_INDEX, HIF_TX_AC2_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC3_INDEX, HIF_TX_AC3_INDEX}, + {PORT_INDEX_MCU, MCU_Q1_INDEX, HIF_TX_CPU_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC4_INDEX, HIF_TX_AC4_INDEX}, + + /* Second HW queue */ + {PORT_INDEX_LMAC, MAC_TXQ_AC10_INDEX, HIF_TX_AC10_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC11_INDEX, HIF_TX_AC11_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC12_INDEX, HIF_TX_AC12_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC13_INDEX, HIF_TX_AC13_INDEX}, + {PORT_INDEX_LMAC, MAC_TXQ_AC14_INDEX, HIF_TX_AC14_INDEX}, +}; + +static INT_EVENT_MAP_T arIntEventMapTable[] = { + {ABNORMAL_INT, INT_EVENT_ABNORMAL}, + {D2H_SW_INT, INT_EVENT_SW_INT}, + {TX_DONE_INT, INT_EVENT_TX}, + {(RX0_DONE_INT | RX1_DONE_INT), INT_EVENT_RX} + +}; + + +#define SDIO_TX_DESC_LONG_FORMAT_LENGTH_DW 7 //in unit of double word +#define SDIO_TX_DESC_LONG_FORMAT_LENGTH (SDIO_TX_DESC_LONG_FORMAT_LENGTH_DW << 2) +#define SDIO_TX_DESC_PADDING_LENGTH_DW 0 //in unit of double word +#define SDIO_TX_DESC_PADDING_LENGTH (SDIO_TX_DESC_PADDING_LENGTH_DW << 2) +#define SDIO_TX_PAGE_SIZE_IS_POWER_OF_2 TRUE +#define SDIO_TX_PAGE_SIZE_IN_POWER_OF_2 7 +#define SDIO_TX_PAGE_SIZE 128 +#define SDIO_TX_MAX_PAGE_PER_FRAME MAX_AGGREGATION_SIZE +#define SDIO_TX_BUFF_COUNT_TC0 1 +#define SDIO_TX_BUFF_COUNT_TC1 34 +#define SDIO_TX_BUFF_COUNT_TC2 1 +#define SDIO_TX_BUFF_COUNT_TC3 1 +#define SDIO_TX_BUFF_COUNT_TC4 4 +#define SDIO_TX_BUFF_COUNT_TC5 1 + + +#define SDIO_TX_PAGE_COUNT_TC0 (SDIO_TX_BUFF_COUNT_TC0 * SDIO_TX_MAX_PAGE_PER_FRAME / SDIO_TX_PAGE_SIZE) +#define SDIO_TX_PAGE_COUNT_TC1 (SDIO_TX_BUFF_COUNT_TC0 * SDIO_TX_MAX_PAGE_PER_FRAME / SDIO_TX_PAGE_SIZE) +#define SDIO_TX_PAGE_COUNT_TC2 (SDIO_TX_BUFF_COUNT_TC0 * SDIO_TX_MAX_PAGE_PER_FRAME / SDIO_TX_PAGE_SIZE) +#define SDIO_TX_PAGE_COUNT_TC3 (SDIO_TX_BUFF_COUNT_TC0 * SDIO_TX_MAX_PAGE_PER_FRAME / SDIO_TX_PAGE_SIZE) +#define SDIO_TX_PAGE_COUNT_TC4 (SDIO_TX_BUFF_COUNT_TC0 * SDIO_TX_MAX_PAGE_PER_FRAME / SDIO_TX_PAGE_SIZE) +#define SDIO_TX_PAGE_COUNT_TC5 (SDIO_TX_BUFF_COUNT_TC0 * SDIO_TX_MAX_PAGE_PER_FRAME / SDIO_TX_PAGE_SIZE) + + +/* --------------- end ----------------------------------> */ + +static const UINT8 ucIntEventMapSize = (sizeof(arIntEventMapTable) / sizeof(INT_EVENT_MAP_T)); + +static IST_EVENT_FUNCTION apfnEventFuncTable[] = { + MTSDIOProcessAbnormalInterrupt, /*!< INT_EVENT_ABNORMAL */ + MTSDIOProcessSoftwareInterrupt, /*!< INT_EVENT_SW_INT */ + MTSDIOProcessTxInterrupt, /*!< INT_EVENT_TX */ + MTSDIOProcessRxInterrupt, /*!< INT_EVENT_RX */ +}; + + + +VOID +MTSDIOTxResetResource ( + IN RTMP_ADAPTER *pAd +) +{ + P_TX_CTRL_T prTxCtrl = NULL; + unsigned long flags = 0; + + ASSERT(pAd); + + prTxCtrl = &pAd->rTxCtrl; + + RTMP_SPIN_LOCK_IRQSAVE(&pAd->TcCountLock, &flags); + + NdisZeroMemory(prTxCtrl->rTc.au2TxDonePageCount, sizeof(prTxCtrl->rTc.au2TxDonePageCount)); + prTxCtrl->rTc.ucNextTcIdx = TC0_INDEX; + prTxCtrl->rTc.u2AvailiablePageCount = 0; + + prTxCtrl->rTc.au2MaxNumOfBuffer[TC0_INDEX] = SDIO_TX_BUFF_COUNT_TC0; + prTxCtrl->rTc.au2FreeBufferCount[TC0_INDEX] = SDIO_TX_BUFF_COUNT_TC0; + + prTxCtrl->rTc.au2MaxNumOfBuffer[TC1_INDEX] = SDIO_TX_BUFF_COUNT_TC1; + prTxCtrl->rTc.au2FreeBufferCount[TC1_INDEX] = SDIO_TX_BUFF_COUNT_TC1; + + prTxCtrl->rTc.au2MaxNumOfBuffer[TC2_INDEX] = SDIO_TX_BUFF_COUNT_TC2; + prTxCtrl->rTc.au2FreeBufferCount[TC2_INDEX] = SDIO_TX_BUFF_COUNT_TC2; + + prTxCtrl->rTc.au2MaxNumOfBuffer[TC3_INDEX] = SDIO_TX_BUFF_COUNT_TC3; + prTxCtrl->rTc.au2FreeBufferCount[TC3_INDEX] = SDIO_TX_BUFF_COUNT_TC3; + + prTxCtrl->rTc.au2MaxNumOfBuffer[TC4_INDEX] = SDIO_TX_BUFF_COUNT_TC4; + prTxCtrl->rTc.au2FreeBufferCount[TC4_INDEX] = SDIO_TX_BUFF_COUNT_TC4; + + prTxCtrl->rTc.au2MaxNumOfBuffer[TC5_INDEX] = SDIO_TX_BUFF_COUNT_TC5; + prTxCtrl->rTc.au2FreeBufferCount[TC5_INDEX] = SDIO_TX_BUFF_COUNT_TC5; + + prTxCtrl->rTc.au2MaxNumOfPage[TC0_INDEX] = SDIO_TX_PAGE_COUNT_TC0; + prTxCtrl->rTc.au2FreePageCount[TC0_INDEX] = SDIO_TX_PAGE_COUNT_TC0; + + prTxCtrl->rTc.au2MaxNumOfPage[TC1_INDEX] = SDIO_TX_PAGE_COUNT_TC1; + prTxCtrl->rTc.au2FreePageCount[TC1_INDEX] = SDIO_TX_PAGE_COUNT_TC1; + + prTxCtrl->rTc.au2MaxNumOfPage[TC2_INDEX] = SDIO_TX_PAGE_COUNT_TC2; + prTxCtrl->rTc.au2FreePageCount[TC2_INDEX] = SDIO_TX_PAGE_COUNT_TC2; + + prTxCtrl->rTc.au2MaxNumOfPage[TC3_INDEX] = SDIO_TX_PAGE_COUNT_TC3; + prTxCtrl->rTc.au2FreePageCount[TC3_INDEX] = SDIO_TX_PAGE_COUNT_TC3; + + prTxCtrl->rTc.au2MaxNumOfPage[TC4_INDEX] = SDIO_TX_PAGE_COUNT_TC4; + prTxCtrl->rTc.au2FreePageCount[TC4_INDEX] = SDIO_TX_PAGE_COUNT_TC4; + + prTxCtrl->rTc.au2MaxNumOfPage[TC5_INDEX] = SDIO_TX_PAGE_COUNT_TC5; + prTxCtrl->rTc.au2FreePageCount[TC5_INDEX] = SDIO_TX_PAGE_COUNT_TC5; + + RTMP_SPIN_UNLOCK_IRQRESTORE(&pAd->TcCountLock, &flags); + + return; +} + +INT32 +MTSDIOTxAcquireResource( + IN RTMP_ADAPTER *pAd, + IN UINT8 ucTC, + IN UINT8 ucPageCount +) +{ + P_TX_CTRL_T prTxCtrl = NULL; + INT32 u4Ret = 0; + unsigned long flags = 0; + + prTxCtrl = &pAd->rTxCtrl; + + RTMP_SPIN_LOCK_IRQSAVE(&pAd->TcCountLock, &flags); + if (prTxCtrl->rTc.au2FreePageCount[ucTC] >= ucPageCount) { + prTxCtrl->rTc.au2FreePageCount[ucTC] -= ucPageCount; + prTxCtrl->rTc.au2FreeBufferCount[ucTC] = (prTxCtrl->rTc.au2FreePageCount[ucTC] / SDIO_TX_MAX_PAGE_PER_FRAME); + } + RTMP_SPIN_UNLOCK_IRQRESTORE(&pAd->TcCountLock, &flags); + + return u4Ret; +} + + +UINT8 +MTSDIOTxGetPageCount ( + IN UINT32 u4FrameLength, + IN BOOLEAN fgIncludeDesc + ) +{ + UINT32 u4RequiredBufferSize = 0; + UINT8 ucPageCount = 0; + + /* Frame Buffer + * |<--Tx Descriptor-->|<--Tx descriptor padding-->|<--802.3/802.11 Header-->|<--Header padding-->|<--Payload-->| + */ + if(fgIncludeDesc) { + u4RequiredBufferSize = u4FrameLength; + } + else { + u4RequiredBufferSize = + SDIO_TX_DESC_LONG_FORMAT_LENGTH + + SDIO_TX_DESC_PADDING_LENGTH + + u4FrameLength; + } + + if(SDIO_TX_PAGE_SIZE_IS_POWER_OF_2) { + ucPageCount = (UINT8)((u4RequiredBufferSize + (SDIO_TX_PAGE_SIZE - 1)) >> SDIO_TX_PAGE_SIZE_IN_POWER_OF_2); + } + else { + ucPageCount = (UINT8)((u4RequiredBufferSize + (SDIO_TX_PAGE_SIZE - 1)) / SDIO_TX_PAGE_SIZE); + } + + return ucPageCount; +} + + + +VOID +MTSDIOTxAdjustTcq ( + IN RTMP_ADAPTER *pAd +) +{ + ASSERT(pAd); + // TODO: implement QM for adaptive quota control +} + +BOOLEAN +MTSDIOTxCalculateResource( + IN RTMP_ADAPTER *pAd, + IN UINT16 *au2TxRlsCnt, + OUT UINT16 *au2FreeTcResource +) +{ + P_TX_TCQ_STATUS_T prTcqStatus = NULL; + prTcqStatus = &pAd->rTxCtrl.rTc; + UINT16 u2TotalTxDonePageCount = 0; + UINT8 ucTcIdx = 0; + prTcqStatus = &pAd->rTxCtrl.rTc; + BOOLEAN bStatus = FALSE; + + prTcqStatus->u2AvailiablePageCount += au2TxRlsCnt[HIF_TX_FFA_INDEX]; + + for (ucTcIdx = TC0_INDEX; ucTcIdx < TC_NUM; ucTcIdx++) { + prTcqStatus->au2TxDonePageCount[ucTcIdx] += au2TxRlsCnt[arTcResourceControl[ucTcIdx].ucHifTxQIndex]; + u2TotalTxDonePageCount += prTcqStatus->au2TxDonePageCount[ucTcIdx]; + } + + DBGPRINT(RT_DEBUG_OFF, ("Tx Done INT result, FFA[%u] AC[%u:%u:%u:%u:%u] CPU[%u]\n", + au2TxRlsCnt[HIF_TX_FFA_INDEX], + au2TxRlsCnt[HIF_TX_AC0_INDEX], + au2TxRlsCnt[HIF_TX_AC1_INDEX], + au2TxRlsCnt[HIF_TX_AC2_INDEX], + au2TxRlsCnt[HIF_TX_AC3_INDEX], + au2TxRlsCnt[HIF_TX_AC4_INDEX], + au2TxRlsCnt[HIF_TX_CPU_INDEX])); + + + if (prTcqStatus->u2AvailiablePageCount) { + if (prTcqStatus->u2AvailiablePageCount >= u2TotalTxDonePageCount) { + + NdisCopyMemory(au2FreeTcResource, prTcqStatus->au2TxDonePageCount, + sizeof(prTcqStatus->au2TxDonePageCount)); + NdisZeroMemory(prTcqStatus->au2TxDonePageCount, + sizeof(prTcqStatus->au2TxDonePageCount)); + prTcqStatus->u2AvailiablePageCount -= u2TotalTxDonePageCount; + + if (prTcqStatus->u2AvailiablePageCount) { + } + } else { + ucTcIdx = prTcqStatus->ucNextTcIdx; + while (prTcqStatus->u2AvailiablePageCount) { + if (prTcqStatus->u2AvailiablePageCount >= prTcqStatus->au2TxDonePageCount[ucTcIdx]) { + au2FreeTcResource[ucTcIdx] = prTcqStatus->au2TxDonePageCount[ucTcIdx]; + prTcqStatus->u2AvailiablePageCount -= prTcqStatus->au2TxDonePageCount[ucTcIdx]; + ucTcIdx++; + ucTcIdx %= TC_NUM; + } else { + au2FreeTcResource[ucTcIdx] = prTcqStatus->u2AvailiablePageCount; + prTcqStatus->au2TxDonePageCount[ucTcIdx] -= prTcqStatus->u2AvailiablePageCount; + prTcqStatus->u2AvailiablePageCount = 0; + } + prTcqStatus->ucNextTcIdx = ucTcIdx; + } + bStatus = TRUE; + } + } else { + DBGPRINT(RT_DEBUG_OFF, ("No FFA count to release\n")); + } + + return bStatus; +} + +BOOLEAN +MTSDIOTxReleaseResource( + IN RTMP_ADAPTER *pAd, + IN UINT16 *au2TxRlsCnt +) +{ + P_TX_TCQ_STATUS_T prTcqStatus = NULL; + BOOLEAN bStatus = FALSE; + UINT16 au2FreeTcResource[TC_NUM] = {0}; + UINT32 u4BufferCountToBeFeed = 0; + UINT8 i = 0; + unsigned long flags = 0; + + prTcqStatus = &pAd->rTxCtrl.rTc; + + if (MTSDIOTxCalculateResource(pAd, au2TxRlsCnt, au2FreeTcResource)) { + + RTMP_SPIN_LOCK_IRQSAVE(&pAd->TcCountLock, &flags); + + for (i = TC0_INDEX; i < TC_NUM; i++) { + /* Real page counter */ + prTcqStatus->au2FreePageCount[i] += au2FreeTcResource[i]; + /* Buffer counter. For development only */ + /* Convert page count to buffer count */ + u4BufferCountToBeFeed = (prTcqStatus->au2FreePageCount[i] / SDIO_TX_MAX_PAGE_PER_FRAME); + prTcqStatus->au2FreeBufferCount[i] = u4BufferCountToBeFeed; + + if (au2FreeTcResource[i]) { + DBGPRINT(RT_DEBUG_OFF, ("Release: TC%lu ReturnPageCnt[%u] FreePageCnt[%u] FreeBufferCnt[%u]\n", + i, + au2FreeTcResource[i], + prTcqStatus->au2FreePageCount[i], + prTcqStatus->au2FreeBufferCount[i])); + } + } + RTMP_SPIN_UNLOCK_IRQRESTORE(&pAd->TcCountLock, &flags); + + bStatus = TRUE; + } + + return bStatus; +} + + +VOID +MTSDIOProcessIST_impl ( + IN RTMP_ADAPTER *pAd, + IN UINT32 u4IntStatus +) +{ + UINT32 u4Status = 0; + UINT32 u4IntCount = 0; + P_INT_EVENT_MAP_T prIntEventMap = NULL; + //unsigned long flags = 0; + + ASSERT(pAd); + + //pAd->IntStatus = u4IntStatus; + if (pAd->IntStatus & ABNORMAL_INT) + { + + } + if (pAd->IntStatus & (RX0_DONE_INT | RX1_DONE_INT)) + { + MTSDIOProcessRxInterrupt(pAd); + } + if (pAd->IntStatus & TX_DONE_INT) + { + + } + +} + + +VOID +MTSDIOProcessIST (IN RTMP_ADAPTER *pAd) +{ + UINT32 u4IntStatus = 0; + unsigned long flags = 0; + + //MTSDIORead32(pAd, WHISR, &u4IntStatus); + //u4IntStatus = pAd->IntStatus; + DBGPRINT(RT_DEBUG_ERROR, ("MTSDIOProcessIST pAd->IntStatus: %x\n",pAd->IntStatus)); + + if (pAd->IntStatus & ~(WHIER_DEFAULT | FW_OWN_BACK_INT_EN)) { + //RTMP_SPIN_LOCK_IRQSAVE(&pAd->IntStatusLock, &flags); + pAd->IntStatus = pAd->IntStatus & WHIER_DEFAULT; + //RTMP_SPIN_UNLOCK_IRQRESTORE(&pAd->IntStatusLock, &flags); + } + + MTSDIOProcessIST_impl(pAd, pAd->IntStatus); +} + + + +VOID +MTSDIOProcessSoftwareInterrupt(IN RTMP_ADAPTER *pAd) +{ + return; +} + + +VOID +MTSDIOProcessFwOwnBackInterrupt(IN RTMP_ADAPTER *pAd) +{ + return; +} + + +VOID +MTSDIOProcessAbnormalInterrupt(IN RTMP_ADAPTER *pAd) +{ + return; +} + +VOID +MTSDIOProcessTxInterrupt(IN RTMP_ADAPTER *pAd) +{ + P_TX_CTRL_T prTxCtrl = NULL; + UINT32 au4TxCount[8]; + + MTSDIORead32(pAd, &au4TxCount[0], WTQCR0); // AC0 + MTSDIORead32(pAd, &au4TxCount[1], WTQCR1); // AC1 + MTSDIORead32(pAd, &au4TxCount[2], WTQCR2); // AC2 + MTSDIORead32(pAd, &au4TxCount[3], WTQCR3); // AC3 + MTSDIORead32(pAd, &au4TxCount[4], WTQCR4); // AC4 + MTSDIORead32(pAd, &au4TxCount[5], WTQCR5); // AC5 + MTSDIORead32(pAd, &au4TxCount[6], WTQCR6); // AC6 + MTSDIORead32(pAd, &au4TxCount[7], WTQCR7); // AC7 + //MTSDIOTxReleaseResource(pAd, (PUINT8) au4TxCount); + + //MTSDIOTxAdjustTcq(pAd); + /* TODO: Check if there's any packets */ + return; +} + + +void MTSDIOProcessRxInterrupt(IN RTMP_ADAPTER *pAd) +{ + UINT32 Value = 0; + UINT32 RX0PacketLen = 0, RX1PacketLen = 0; + + ASSERT(pAd); + + MTSDIORead32(pAd, WRPLR, &Value); + RX0PacketLen = GET_RX0_PACKET_LENGTH(Value); + RX1PacketLen = GET_RX1_PACKET_LENGTH(Value); + + if (RX0PacketLen != 0) { + MTSDIOSingleProcessRx0(pAd, RX0PacketLen); + } + if (RX1PacketLen != 0) { + MTSDIOSingleProcessRx1(pAd, RX1PacketLen); + } +} + + +INT32 MTSDIOCmdTx(RTMP_ADAPTER *pAd, UCHAR *Buf, UINT32 Length) +{ + INT32 Ret; + + Ret = MTSDIOMultiWrite(pAd, WTDR1, Buf, Length); + + return Ret; +} + + +INT32 MTSDIODataTx(RTMP_ADAPTER *pAd, UCHAR *Buf, UINT32 Length) +{ + INT32 Ret; + + Ret = MTSDIOMultiWrite(pAd, WTDR1, Buf, Length); + + return Ret; +} + + +INT32 MTSDIODataRx0(RTMP_ADAPTER *pAd, UCHAR *Buf, UINT32 Length) +{ + INT32 Ret; + + Ret = MTSDIOMultiRead(pAd, WRDR0, Buf, Length); + + return Ret; +} + + +INT32 MTSDIODataRx1(RTMP_ADAPTER *pAd, UCHAR *Buf, UINT32 Length) +{ + INT32 Ret; + + Ret = MTSDIOMultiRead(pAd, WRDR1, Buf, Length); + + return Ret; +} + + +VOID MTSDIOAddWorkerTaskList(RTMP_ADAPTER *pAd) +{ + SDIOWorkTask *NewTask; + unsigned long flags; + + os_alloc_mem(pAd, (UCHAR **)&NewTask, sizeof(*NewTask)); + + if (NewTask == NULL) + return; + + RTMP_SPIN_LOCK_IRQSAVE(&pAd->SdioWorkTaskLock, &flags); + DlListAddTail(&pAd->SdioWorkTaskList, &NewTask->List); + RTMP_SPIN_UNLOCK_IRQRESTORE(&pAd->SdioWorkTaskLock, &flags); +} + + +INT32 MTSDIOSingleProcessRx0(RTMP_ADAPTER *pAd, INT32 Length) +{ + DBGPRINT(RT_DEBUG_OFF, ("%s: =============>\n", __FUNCTION__)); + + UINT32 i; + PUCHAR buf; + + if (Length >= pAd->BlockSize) + Length = (Length + ((-Length) & (pAd->BlockSize - 1))); + + pAd->SDIORxPacket = RTMP_AllocateFragPacketBuffer(pAd, Length); + DBGPRINT(RT_DEBUG_OFF, ("%s: =============>\n", __FUNCTION__)); + + if (!pAd->SDIORxPacket) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: allocate net packet fail\n", + __FUNCTION__)); + + return; + } + + MTSDIODataRx0(pAd, GET_OS_PKT_DATAPTR(pAd->SDIORxPacket), Length); + + SET_OS_PKT_LEN(pAd->SDIORxPacket, Length); + buf = GET_OS_PKT_DATAPTR(pAd->SDIORxPacket); + + DBGPRINT(RT_DEBUG_OFF, ("%s: ================len = %x ===\n", __FUNCTION__, Length)); + for(i=0;iSDIORxPacket); + return; + } + + rtmp_rx_done_handle(pAd); +} + + +INT32 MTSDIOSingleProcessRx1(RTMP_ADAPTER *pAd, INT32 Length) +{ + UINT32 i; + PUCHAR buf; + + if (Length >= pAd->BlockSize) + Length = (Length + ((-Length) & (pAd->BlockSize - 1))); + + pAd->SDIORxPacket = RTMP_AllocateFragPacketBuffer(pAd, Length); + + if (!pAd->SDIORxPacket) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: allocate net packet fail\n", + __FUNCTION__)); + + return; + } + + MTSDIODataRx1(pAd, GET_OS_PKT_DATAPTR(pAd->SDIORxPacket), Length); + + SET_OS_PKT_LEN(pAd->SDIORxPacket, Length); + buf = GET_OS_PKT_DATAPTR(pAd->SDIORxPacket); + DBGPRINT(RT_DEBUG_OFF, ("%s: ================len = %x ===\n", __FUNCTION__, Length)); + for(i=0;iSDIORxPacket); + return; + } + + rtmp_rx_done_handle(pAd); +} + + +VOID MTSDIODataWorkerTask(RTMP_ADAPTER *pAd) +{ + //UINT32 IntStatus; + void* handle = pAd->OS_Cookie; + struct sdio_func *dev_func = ((POS_COOKIE)handle)->sdio_dev; + UINT32 Value; + + //MTSDIORead32(pAd, WHISR, &pAd->IntStatus); + //IntStatus = pAd->IntStatus; + + /* Process RX0/RX1, Abnormal, TX done ISR */ + if (pAd->IntStatus & WHIER_DEFAULT) { + MTSDIOProcessIST(pAd); + pAd->IntStatus =0; + /* Enable Interrupt */ + RTMP_SDIO_WRITE32(pAd, WHLPCR, W_INT_EN_SET); + } + /* Process Command */ + + AndesMTSendCmdMsgToSdio(pAd); + + /* Process TX */ +} + + +VOID MTSDIODataIsr(RTMP_ADAPTER *pAd) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UINT32 Value; + unsigned long flags; + struct sdio_func *dev_func =pObj->sdio_dev; + INT32 Ret = 0; + + /* Disable Interrupt */ + RTMP_SDIO_WRITE32(pAd, WHLPCR, W_INT_EN_CLR); + + Value = sdio_readl(dev_func, WHISR, &Ret); + + if (Ret) { + DBGPRINT(RT_DEBUG_ERROR, ("RTSDIORead32 failure!\n")); + } + + if (Value) { +// DBGPRINT(RT_DEBUG_ERROR, ("%s()!!!! WHISR:%x \n", __FUNCTION__,Value)); + + //RTMP_SPIN_LOCK_IRQSAVE(&pAd->IntStatusLock, &flags); + pAd->IntStatus |= Value; + //RTMP_SPIN_UNLOCK_IRQRESTORE(&pAd->IntStatusLock, &flags); + DBGPRINT(RT_DEBUG_TRACE, ("%s() disbale interrupt \n", __FUNCTION__)); + DBGPRINT(RT_DEBUG_OFF, ("%s() ======================> \n", __FUNCTION__)); + MTSDIOAddWorkerTaskList(pAd); + queue_work(pObj->SdioWq, &pObj->SdioWork); + } +} diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mtsdio_io.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mtsdio_io.c new file mode 100644 index 000000000..8f3f97295 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mtsdio_io.c @@ -0,0 +1,121 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of MediaTek. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + mtusb_io.c +*/ + +#include "rt_config.h" + +INT32 MTSDIORead32(RTMP_ADAPTER *pAd, UINT32 Offset, UINT32 *Value) +{ + + INT32 Ret = 0; + void* handle = pAd->OS_Cookie; + struct sdio_func *dev_func = ((POS_COOKIE)handle)->sdio_dev; + + sdio_claim_host(dev_func); + *Value = sdio_readl(dev_func, Offset, &Ret); + sdio_release_host(dev_func); + + if (Ret) { + DBGPRINT(RT_DEBUG_ERROR, ("RTSDIORead32 failure!\n")); + } + + return Ret; +} + + +INT32 MTSDIOWrite32(RTMP_ADAPTER *pAd, UINT32 Offset, UINT32 Value) +{ + INT32 Ret = 0; + void* handle = pAd->OS_Cookie; + struct sdio_func *dev_func = ((POS_COOKIE)handle)->sdio_dev; + + sdio_claim_host(dev_func); + sdio_writel(dev_func, Value, Offset, &Ret); + sdio_release_host(dev_func); + + return Ret; +} + + +INT32 MTSDIOMultiRead(RTMP_ADAPTER *pAd, UINT32 Offset, + UCHAR *Buf,UINT32 Length) +{ + UINT32 Count = Length; + void* handle = pAd->OS_Cookie; + struct sdio_func *dev_func = ((POS_COOKIE)handle)->sdio_dev; + UINT32 bNum = 0; + INT32 Ret; + + while (Count >= pAd->BlockSize) { + Count -= pAd->BlockSize; + bNum++; + } + + if (Count > 0 && bNum > 0) { + bNum++; + } + + sdio_claim_host(dev_func); + + if (bNum > 0) { + Ret = sdio_readsb(dev_func, Buf, Offset, pAd->BlockSize * bNum); + } + else + { + Ret = sdio_readsb(dev_func, Buf, Offset, Count); + } + + sdio_release_host(dev_func); + + return Ret; +} + + +INT32 MTSDIOMultiWrite(RTMP_ADAPTER *pAd, UINT32 Offset, + UCHAR *Buf,UINT32 Length) +{ + + UINT32 Count = Length; + void* handle = pAd->OS_Cookie; + struct sdio_func *dev_func = ((POS_COOKIE)handle)->sdio_dev; + INT32 Ret = 0; + UINT32 bNum = 0; + + while (Count >= pAd->BlockSize) { + Count -= pAd->BlockSize; + bNum++; + } + + if (Count > 0 && bNum > 0) { + bNum++; + } + + sdio_claim_host(dev_func); + + if (bNum > 0) + { + Ret = sdio_writesb(dev_func, Offset, Buf, pAd->BlockSize * bNum); + } + else + { + Ret = sdio_writesb(dev_func, Offset, Buf, Count); + } + + sdio_release_host(dev_func); + + return Ret; +} + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mtusb_io.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mtusb_io.c new file mode 100644 index 000000000..b35c5c6f4 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mtusb_io.c @@ -0,0 +1,625 @@ +/* + *************************************************************************** + * 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: + mtusb_io.c +*/ +#include "rt_config.h" + +#define MAX_VENDOR_REQ_RETRY_COUNT 10 + +/* + ======================================================================== + + Routine Description: NIC initialization complete + + Arguments: + + Return Value: + + IRQL = + + Note: + + ======================================================================== +*/ +void mtusb_cfg_read(RTMP_ADAPTER *ad, UINT32 *value) +{ + RTUSB_VendorRequest(ad, (USBD_TRANSFER_DIRECTION_IN | + USBD_SHORT_TRANSFER_OK), + DEVICE_VENDOR_REQUEST_IN, + 0x63, (0x50029018 & 0xffff0000) >> 16, + (0x50029018 & 0x0000ffff), value, 4); +} + +void mtusb_cfg_write(RTMP_ADAPTER *ad, UINT32 value) +{ + RTUSB_VendorRequest( + ad, + USBD_TRANSFER_DIRECTION_OUT, + DEVICE_VENDOR_REQUEST_OUT, + 0x66, + (0x50029018 & 0xffff0000) >> 16, + (0x50029018 & 0x0000ffff), + &value, + 4); +} + + +NTSTATUS RTUSBVenderReset(RTMP_ADAPTER *pAd) +{ + NTSTATUS Status; + DBGPRINT_RAW(RT_DEBUG_ERROR, ("-->RTUSBVenderReset\n")); + Status = RTUSB_VendorRequest( + pAd, + USBD_TRANSFER_DIRECTION_OUT, + DEVICE_VENDOR_REQUEST_OUT, + 0x01, + 0x1, + 0, + NULL, + 0); + + DBGPRINT_RAW(RT_DEBUG_ERROR, ("<--RTUSBVenderReset\n")); + return Status; +} + + +static NTSTATUS mtusb_multiwrite(RTMP_ADAPTER *pAd, + IN UINT32 Offset, + IN UCHAR *buf, + IN USHORT len, + IN USHORT batchLen) +{ + NTSTATUS Status = STATUS_SUCCESS; + UINT32 index = Offset, actLen = batchLen, leftLen = len; + UCHAR *pSrc = buf; + + do + { + actLen = (actLen > batchLen ? batchLen : actLen); + Status = RTUSB_VendorRequest( + pAd, + USBD_TRANSFER_DIRECTION_OUT, + DEVICE_VENDOR_REQUEST_OUT, + 0x66, + (index & 0xffff0000) >> 16, + (index & 0x0000ffff), + pSrc, + actLen); + + if (Status != STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_ERROR, ("VendrCmdMultiWrite_nBytes failed!\n")); + break; + } + + index += actLen; + leftLen -= actLen; + pSrc = pSrc + actLen; + } while (leftLen > 0); + + return Status; +} + + +static NTSTATUS mtusb_multiread(RTMP_ADAPTER *pAd, UINT32 addr, UCHAR *buf, UINT32 len) +{ + NTSTATUS Status; + + Status = RTUSB_VendorRequest(pAd, (USBD_TRANSFER_DIRECTION_IN | + USBD_SHORT_TRANSFER_OK), + DEVICE_VENDOR_REQUEST_IN, + 0x63, (addr & 0xffff0000) >> 16, + (addr & 0x0000ffff), buf, len); + + return Status; +} + + +NTSTATUS mtusb_read_reg(RTMP_ADAPTER *pAd, UINT32 addr, UINT32 *value) +{ + NTSTATUS Status = 0; + UINT32 localVal; + UINT32 global_addr = mt_physical_addr_map(addr); + +#if defined(CONFIG_STA_SUPPORT) && defined(STA_LP_PHASE_1_SUPPORT) + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + if (pAd->CountDowntoPsm == 0) + { + pAd->CountDowntoPsm = 2; /* 100 ms; stay awake 200ms at most, average will be 1xx ms */ + } + + AsicForceWakeup(pAd, TRUE); + } +#endif /* #ifdef CONFIG_STA_SUPPORT && STA_LP_PHASE_1_SUPPORT */ + + Status = mtusb_multiread(pAd, global_addr, (PUCHAR)&localVal, 4); + + *value = le2cpu32(localVal); + + if (Status != 0) + *value = 0xffffffff; + + return Status; +} + + +NTSTATUS mtusb_write_reg(RTMP_ADAPTER *pAd, UINT32 addr, UINT32 value) +{ + NTSTATUS Status; + UINT32 global_addr = mt_physical_addr_map(addr); + +#if defined(CONFIG_STA_SUPPORT) && defined(STA_LP_PHASE_1_SUPPORT) + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + if (pAd->CountDowntoPsm == 0) + { + pAd->CountDowntoPsm = 2; /* 100 ms; stay awake 200ms at most, average will be 1xx ms */ + } + + AsicForceWakeup(pAd, TRUE); + } +#endif /* #ifdef CONFIG_STA_SUPPORT && STA_LP_PHASE_1_SUPPORT */ + + Status = mtusb_multiwrite(pAd, global_addr, (PUCHAR)&value, 4, 4); + + return Status; +} + +NTSTATUS RTUSBMultiWrite( + IN RTMP_ADAPTER *pAd, + IN USHORT Offset, + IN UCHAR *pData, + IN USHORT length, + IN BOOLEAN bWriteHigh) +{ + return NDIS_STATUS_SUCCESS; +} + +NTSTATUS RTUSBMultiWrite_OneByte(RTMP_ADAPTER *pAd, USHORT Offset, UCHAR *pData) +{ + return NDIS_STATUS_SUCCESS; +} + +NTSTATUS RTUSBMultiWrite_nBytes( + IN RTMP_ADAPTER *pAd, + IN USHORT Offset, + IN UCHAR *buf, + IN USHORT len, + IN USHORT batchLen) +{ + return NDIS_STATUS_SUCCESS; +} + +NTSTATUS RTUSBWriteMACRegister( + IN RTMP_ADAPTER *pAd, + IN USHORT Offset, + IN UINT32 Value, + IN BOOLEAN bWriteHigh) +{ + mtusb_multiwrite(pAd, Offset, (PUCHAR)&Value, 4, 4); + + return NDIS_STATUS_SUCCESS; +} + + +static NTSTATUS ResetBulkOutHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + DBGPRINT(RT_DEBUG_TRACE, ("CMDTHREAD_RESET_BULK_OUT(ResetPipeid=0x%0x)===>\n", pAd->bulkResetPipeid)); + + return NDIS_STATUS_SUCCESS; +} + + +/* All transfers must be aborted or cancelled before attempting to reset the pipe.*/ +static NTSTATUS ResetBulkInHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_IN === >\n")); + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("CmdThread : CMDTHREAD_RESET_BULK_IN <===\n")); + return NDIS_STATUS_SUCCESS; +} + + +static NTSTATUS SetAsicWcidHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS DelAsicWcidHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + RT_SET_ASIC_WCID SetAsicWcid; + SetAsicWcid = *((PRT_SET_ASIC_WCID)(CMDQelmt->buffer)); + + if (SetAsicWcid.WCID >= MAX_LEN_OF_MAC_TABLE) + return NDIS_STATUS_FAILURE; + + AsicDelWcidTab(pAd, (UCHAR)SetAsicWcid.WCID); + + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS SetWcidSecInfoHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + PRT_ASIC_WCID_SEC_INFO pInfo; + + pInfo = (PRT_ASIC_WCID_SEC_INFO)CMDQelmt->buffer; + RTMPSetWcidSecurityInfo(pAd, + pInfo->BssIdx, + pInfo->KeyIdx, + pInfo->CipherAlg, + pInfo->Wcid, + pInfo->KeyTabFlag); + + return NDIS_STATUS_SUCCESS; +} + + +static NTSTATUS SetAsicWcidIVEIVHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + PRT_ASIC_WCID_IVEIV_ENTRY pInfo; + + pInfo = (PRT_ASIC_WCID_IVEIV_ENTRY)CMDQelmt->buffer; + AsicUpdateWCIDIVEIV(pAd, + pInfo->Wcid, + pInfo->Iv, + pInfo->Eiv); + + return NDIS_STATUS_SUCCESS; +} + + +static NTSTATUS SetAsicWcidAttrHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + PRT_ASIC_WCID_ATTR_ENTRY pInfo; + + pInfo = (PRT_ASIC_WCID_ATTR_ENTRY)CMDQelmt->buffer; + AsicUpdateWcidAttributeEntry(pAd, + pInfo->BssIdx, + pInfo->KeyIdx, + pInfo->CipherAlg, + pInfo->Wcid, + pInfo->KeyTabFlag); + + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS SETAsicSharedKeyHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + PRT_ASIC_SHARED_KEY pInfo; + + pInfo = (PRT_ASIC_SHARED_KEY)CMDQelmt->buffer; + AsicAddSharedKeyEntry(pAd, + pInfo->BssIndex, + pInfo->KeyIdx, + &pInfo->CipherKey); + + return NDIS_STATUS_SUCCESS; +} + +static NTSTATUS SetAsicPairwiseKeyHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + PRT_ASIC_PAIRWISE_KEY pInfo; + + pInfo = (PRT_ASIC_PAIRWISE_KEY)CMDQelmt->buffer; + AsicAddPairwiseKeyEntry(pAd, + pInfo->WCID, + &pInfo->CipherKey); + + return NDIS_STATUS_SUCCESS; +} + + + +static NTSTATUS RemovePairwiseKeyHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + UCHAR Wcid = *((PUCHAR)(CMDQelmt->buffer)); + + AsicRemovePairwiseKeyEntry(pAd, Wcid); + return NDIS_STATUS_SUCCESS; +} + + +static NTSTATUS SetClientMACEntryHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + PRT_SET_ASIC_WCID pInfo; + + pInfo = (PRT_SET_ASIC_WCID)CMDQelmt->buffer; + AsicUpdateRxWCIDTable(pAd, pInfo->WCID, pInfo->Addr); + return NDIS_STATUS_SUCCESS; +} + + +static NTSTATUS UpdateProtectHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + PRT_ASIC_PROTECT_INFO pAsicProtectInfo; + + pAsicProtectInfo = (PRT_ASIC_PROTECT_INFO)CMDQelmt->buffer; + AsicUpdateProtect(pAd, pAsicProtectInfo->OperationMode, pAsicProtectInfo->SetMask, + pAsicProtectInfo->bDisableBGProtect, pAsicProtectInfo->bNonGFExist); + + return NDIS_STATUS_SUCCESS; +} + + +#ifdef CONFIG_AP_SUPPORT +static NTSTATUS APUpdateCapabilityAndErpieHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + APUpdateCapabilityAndErpIe(pAd); + return NDIS_STATUS_SUCCESS; +} +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +static NTSTATUS _802_11_CounterMeasureHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + MAC_TABLE_ENTRY *pEntry; + + pEntry = (MAC_TABLE_ENTRY *)CMDQelmt->buffer; + HandleCounterMeasure(pAd, pEntry); + } + + return NDIS_STATUS_SUCCESS; +} +#endif /* CONFIG_AP_SUPPORT */ + + + + +#ifdef CONFIG_AP_SUPPORT +static NTSTATUS APEnableTXBurstHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::CMDTHREAD_AP_ENABLE_TX_BURST \n")); + + AsicSetWmmParam(pAd, WMM_PARAM_AC_0, WMM_PARAM_TXOP, 0x20); + } + + return NDIS_STATUS_SUCCESS; +} + + +static NTSTATUS APDisableTXBurstHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::CMDTHREAD_AP_DISABLE_TX_BURST \n")); + + AsicSetWmmParam(pAd, WMM_PARAM_AC_0, WMM_PARAM_TXOP, 0x00); + } + + return NDIS_STATUS_SUCCESS; +} + + +static NTSTATUS APAdjustEXPAckTimeHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::CMDTHREAD_AP_ADJUST_EXP_ACK_TIME \n")); + } + + return NDIS_STATUS_SUCCESS; +} + + +static NTSTATUS APRecoverEXPAckTimeHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + DBGPRINT(RT_DEBUG_TRACE, ("CmdThread::CMDTHREAD_AP_RECOVER_EXP_ACK_TIME \n")); + } + + return NDIS_STATUS_SUCCESS; +} +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef LED_CONTROL_SUPPORT +static NTSTATUS SetLEDStatusHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + UCHAR LEDStatus = *((PUCHAR)(CMDQelmt->buffer)); + + RTMPSetLEDStatus(pAd, LEDStatus); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: CMDTHREAD_SET_LED_STATUS (LEDStatus = %d)\n", + __FUNCTION__, LEDStatus)); + + return NDIS_STATUS_SUCCESS; +} +#endif /* LED_CONTROL_SUPPORT */ + +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT +/*WPS LED MODE 10*/ +static NTSTATUS LEDWPSMode10Hdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + UINT WPSLedMode10 = *((PUINT)(CMDQelmt->buffer)); + + DBGPRINT(RT_DEBUG_INFO, ("WPS LED mode 10::ON or Flash or OFF : %x\n", WPSLedMode10)); + + switch(WPSLedMode10) + { + case LINK_STATUS_WPS_MODE10_TURN_ON: + RTMPSetLEDStatus(pAd, LED_WPS_MODE10_TURN_ON); + break; + case LINK_STATUS_WPS_MODE10_FLASH: + RTMPSetLEDStatus(pAd,LED_WPS_MODE10_FLASH); + break; + case LINK_STATUS_WPS_MODE10_TURN_OFF: + RTMPSetLEDStatus(pAd, LED_WPS_MODE10_TURN_OFF); + break; + default: + DBGPRINT(RT_DEBUG_INFO, ("WPS LED mode 10:: No this status %d!!!\n", WPSLedMode10)); + break; + } + + return NDIS_STATUS_SUCCESS; +} +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ + + +#ifdef CONFIG_AP_SUPPORT +static NTSTATUS ChannelRescanHdlr(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt) +{ + DBGPRINT(RT_DEBUG_TRACE, ("cmd> Re-scan channel! \n")); + + pAd->CommonCfg.Channel = AP_AUTO_CH_SEL(pAd, TRUE); +#ifdef DOT11_N_SUPPORT + /* If WMODE_CAP_N(phymode) and BW=40 check extension channel, after select channel */ + N_ChannelCheck(pAd); +#endif /* DOT11_N_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("cmd> Switch to %d! \n", pAd->CommonCfg.Channel)); + APStop(pAd); + APStartUp(pAd); + +#ifdef AP_QLOAD_SUPPORT + QBSS_LoadAlarmResume(pAd); +#endif /* AP_QLOAD_SUPPORT */ + + return NDIS_STATUS_SUCCESS; +} +#endif /* CONFIG_AP_SUPPORT*/ + + +#ifdef LINUX +#endif /* LINUX */ + + + +#ifdef STREAM_MODE_SUPPORT +static NTSTATUS UpdateTXChainAddress(RTMP_ADAPTER *pAd, IN PCmdQElmt CMDQelmt) +{ + AsicUpdateTxChainAddress(pAd, CMDQelmt->buffer); + return NDIS_STATUS_SUCCESS; +} +#endif /* STREAM_MODE_SUPPORT */ + + +#ifdef MT_MAC +static NTSTATUS AddRemoveKeyHdlr(RTMP_ADAPTER *pAd, IN PCmdQElmt CMDQelmt) +{ + PMT_ASIC_SEC_INFO pInfo; + + pInfo = (PMT_ASIC_SEC_INFO)CMDQelmt->buffer; + + CmdProcAddRemoveKey(pAd, pInfo->AddRemove, pInfo->BssIdx, pInfo->KeyIdx, pInfo->Wcid, pInfo->KeyTabFlag, &pInfo->CipherKey, pInfo->Addr); + return NDIS_STATUS_SUCCESS; +} +#endif /* MT_MAC */ + +typedef NTSTATUS (*CMDHdlr)(RTMP_ADAPTER *pAd, IN PCmdQElmt CMDQelmt); + +CMDHdlr CMDHdlrTable[] = { + ResetBulkOutHdlr, /* CMDTHREAD_RESET_BULK_OUT*/ + ResetBulkInHdlr, /* CMDTHREAD_RESET_BULK_IN*/ + NULL, //CheckGPIOHdlr, /* CMDTHREAD_CHECK_GPIO */ + SetAsicWcidHdlr, /* CMDTHREAD_SET_ASIC_WCID*/ + DelAsicWcidHdlr, /* CMDTHREAD_DEL_ASIC_WCID*/ + SetClientMACEntryHdlr, /* CMDTHREAD_SET_CLIENT_MAC_ENTRY*/ + + NULL, + NULL, + NULL, + NULL, + +#ifdef CONFIG_AP_SUPPORT + APUpdateCapabilityAndErpieHdlr, /* CMDTHREAD_AP_UPDATE_CAPABILITY_AND_ERPIE*/ + APEnableTXBurstHdlr, /* CMDTHREAD_AP_ENABLE_TX_BURST*/ + APDisableTXBurstHdlr, /* CMDTHREAD_AP_DISABLE_TX_BURST*/ + APAdjustEXPAckTimeHdlr, /* CMDTHREAD_AP_ADJUST_EXP_ACK_TIME*/ + APRecoverEXPAckTimeHdlr, /* CMDTHREAD_AP_RECOVER_EXP_ACK_TIME*/ + ChannelRescanHdlr, /* CMDTHREAD_CHAN_RESCAN*/ +#else + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef LED_CONTROL_SUPPORT + SetLEDStatusHdlr, /* CMDTHREAD_SET_LED_STATUS*/ +#else + NULL, +#endif /* LED_CONTROL_SUPPORT */ + +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT + LEDWPSMode10Hdlr, /* CMDTHREAD_LED_WPS_MODE10*/ +#else + NULL, +#endif /* WSC_LED_SUPPORT */ + +#else + NULL, +#endif /* WSC_INCLUDED */ + + /* Security related */ + SetWcidSecInfoHdlr, /* CMDTHREAD_SET_WCID_SEC_INFO*/ + SetAsicWcidIVEIVHdlr, /* CMDTHREAD_SET_ASIC_WCID_IVEIV*/ + SetAsicWcidAttrHdlr, /* CMDTHREAD_SET_ASIC_WCID_ATTR*/ + SETAsicSharedKeyHdlr, /* CMDTHREAD_SET_ASIC_SHARED_KEY*/ + SetAsicPairwiseKeyHdlr, /* CMDTHREAD_SET_ASIC_PAIRWISE_KEY*/ + RemovePairwiseKeyHdlr, /* CMDTHREAD_REMOVE_PAIRWISE_KEY*/ + + NULL, + +#ifdef CONFIG_AP_SUPPORT + _802_11_CounterMeasureHdlr, /* CMDTHREAD_802_11_COUNTER_MEASURE*/ +#else + NULL, +#endif /* CONFIG_AP_SUPPORT */ + + UpdateProtectHdlr, /* CMDTHREAD_UPDATE_PROTECT*/ + + +#ifdef LINUX + NULL, + NULL, + NULL, + NULL, + +#else + NULL, + NULL, + NULL, + NULL, +#endif /* LINUX */ + + NULL, + + NULL, + +#ifdef STREAM_MODE_SUPPORT + UpdateTXChainAddress, /* CMDTHREAD_UPDATE_TX_CHAIN_ADDRESS */ +#else + NULL, +#endif + + NULL, +#ifdef MT_MAC + AddRemoveKeyHdlr, /* CMDTHREAD_ADDREMOVE_ASIC_KEY */ +#else + NULL, +#endif /* MT_MAC */ +}; + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mwds.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mwds.c new file mode 100644 index 000000000..b51d479a8 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/mwds.c @@ -0,0 +1,282 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2009, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + + Module Name: + mwds.c + + Abstract: + This is MWDS feature used to process those 4-addr of connected APClient or STA. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ +#ifdef MWDS +#include "rt_config.h" + + +VOID MWDSAPPeerEnable( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry +) +{ + BOOLEAN mwds_enable = FALSE; + BOOLEAN Ret = FALSE; + + if (pEntry->bSupportMWDS && pEntry->wdev && pEntry->wdev->bSupportMWDS) + mwds_enable = TRUE; + + + if (mwds_enable) + Ret = a4_ap_peer_enable(pAd, pEntry, A4_TYPE_MWDS); + + if (Ret == FALSE) + MWDSAPPeerDisable(pAd, pEntry); +} + +VOID MWDSAPPeerDisable( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry +) +{ + BOOLEAN Ret; + + Ret = a4_ap_peer_disable(pAd, pEntry, A4_TYPE_MWDS); + if (Ret) + pEntry->bSupportMWDS = FALSE; +} + +#ifdef APCLI_SUPPORT +VOID MWDSAPCliPeerEnable( + IN PRTMP_ADAPTER pAd, + IN PAPCLI_STRUCT pApCliEntry, + IN PMAC_TABLE_ENTRY pEntry +) +{ + BOOLEAN mwds_enable = FALSE; + BOOLEAN Ret = FALSE; + + if (pApCliEntry->MlmeAux.bSupportMWDS && pApCliEntry->wdev.bSupportMWDS) + mwds_enable = TRUE; + + + if (mwds_enable) + Ret = a4_apcli_peer_enable(pAd, pApCliEntry, pEntry, A4_TYPE_MWDS); + + if (Ret == FALSE) + MWDSAPCliPeerDisable(pAd, pApCliEntry, pEntry); +} + +VOID MWDSAPCliPeerDisable( + IN PRTMP_ADAPTER pAd, + IN PAPCLI_STRUCT pApCliEntry, + IN PMAC_TABLE_ENTRY pEntry +) +{ + a4_apcli_peer_disable(pAd, pApCliEntry, pEntry, A4_TYPE_MWDS); +} +#endif /* APCLI_SUPPORT */ + +INT MWDSEnable( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex, + IN BOOLEAN isAP, + IN BOOLEAN isDevOpen +) +{ + struct wifi_dev *wdev = NULL; + + if (isAP) { + if (ifIndex < HW_BEACON_MAX_NUM) { + wdev = &pAd->ApCfg.MBSSID[ifIndex].wdev; + + if (!wdev->bSupportMWDS) { + wdev->bSupportMWDS = TRUE; + a4_interface_init(pAd, ifIndex, TRUE, A4_TYPE_MWDS); + } + } + } + +#ifdef APCLI_SUPPORT + else { + if (ifIndex < MAX_APCLI_NUM) { + wdev = &pAd->ApCfg.ApCliTab[ifIndex].wdev; + + if (!wdev->bSupportMWDS) { + wdev->bSupportMWDS = TRUE; + a4_interface_init(pAd, ifIndex, FALSE, A4_TYPE_MWDS); + } + } + } + +#endif /* APCLI_SUPPORT */ + + return TRUE; +} + +INT MWDSDisable( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex, + IN BOOLEAN isAP, + IN BOOLEAN isDevClose +) +{ + struct wifi_dev *wdev = NULL; + + if (isAP) { + if (ifIndex < HW_BEACON_MAX_NUM) { + wdev = &pAd->ApCfg.MBSSID[ifIndex].wdev; + + if (wdev && wdev->bSupportMWDS) { + wdev->bSupportMWDS = FALSE; + a4_interface_deinit(pAd, ifIndex, TRUE, A4_TYPE_MWDS); + } + } + } + +#ifdef APCLI_SUPPORT + else { + if (ifIndex < MAX_APCLI_NUM) { + wdev = &pAd->ApCfg.ApCliTab[ifIndex].wdev; + + if (wdev && wdev->bSupportMWDS) { + wdev->bSupportMWDS = FALSE; + a4_interface_deinit(pAd, ifIndex, FALSE, A4_TYPE_MWDS); + } + } + } + +#endif /* APCLI_SUPPORT */ + + return TRUE; +} + + +INT Set_Enable_MWDS_Proc( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN Enable, + IN BOOLEAN isAP +) +{ + POS_COOKIE pObj; + UCHAR ifIndex; + pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (isAP) { + ifIndex = pObj->ioctl_if; + pAd->ApCfg.MBSSID[ifIndex].wdev.bDefaultMwdsStatus = (Enable == 0) ? FALSE : TRUE; + } + +#ifdef APCLI_SUPPORT + else { + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + pAd->ApCfg.ApCliTab[ifIndex].wdev.bDefaultMwdsStatus = (Enable == 0) ? FALSE : TRUE; + } + +#endif /* APCLI_SUPPORT */ + + if (Enable) + MWDSEnable(pAd, ifIndex, isAP, FALSE); + else + MWDSDisable(pAd, ifIndex, isAP, FALSE); + + return TRUE; +} + +INT Set_Ap_MWDS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg +) +{ + UCHAR Enable; + Enable = simple_strtol(arg, 0, 10); + return Set_Enable_MWDS_Proc(pAd, Enable, TRUE); +} + +INT Set_ApCli_MWDS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg +) +{ + UCHAR Enable; + Enable = simple_strtol(arg, 0, 10); + return Set_Enable_MWDS_Proc(pAd, Enable, FALSE); +} + + +VOID rtmp_read_MWDS_from_file( + IN PRTMP_ADAPTER pAd, + PSTRING tmpbuf, + PSTRING buffer +) +{ + PSTRING tmpptr = NULL; +#ifdef CONFIG_AP_SUPPORT + + /* ApMWDS */ + if (RTMPGetKeyParameter("ApMWDS", tmpbuf, 256, buffer, TRUE)) { + INT Value; + UCHAR i = 0; + + for (i = 0, tmpptr = rstrtok(tmpbuf, ";"); tmpptr; tmpptr = rstrtok(NULL, ";"), i++) { + if (i >= pAd->ApCfg.BssidNum) + break; + + Value = (INT) simple_strtol(tmpptr, 0, 10); + + if (Value == 0) + MWDSDisable(pAd, i, TRUE, FALSE); + else + MWDSEnable(pAd, i, TRUE, FALSE); + + pAd->ApCfg.MBSSID[i].wdev.bDefaultMwdsStatus = (Value == 0) ? FALSE : TRUE; + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("ApMWDS=%d\n", Value)); + } + } + +#endif /* CONFIG_AP_SUPPORT */ +#ifdef APCLI_SUPPORT + + /* ApCliMWDS */ + if (RTMPGetKeyParameter("ApCliMWDS", tmpbuf, 256, buffer, TRUE)) { + INT Value; + UCHAR i = 0; + + for (i = 0, tmpptr = rstrtok(tmpbuf, ";"); tmpptr; tmpptr = rstrtok(NULL, ";"), i++) { + if (i >= MAX_APCLI_NUM) + break; + + Value = (INT) simple_strtol(tmpptr, 0, 10); + + if (Value == 0) + MWDSDisable(pAd, i, FALSE, FALSE); + else + MWDSEnable(pAd, i, FALSE, FALSE); + + pAd->ApCfg.ApCliTab[i].wdev.bDefaultMwdsStatus = (Value == 0) ? FALSE : TRUE; + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("ApCliMWDS=%d\n", Value)); + } + } + +#endif /* APCLI_SUPPORT */ +} + +#endif /* MWDS */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/netif_block.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/netif_block.c new file mode 100644 index 000000000..ed03652b2 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/netif_block.c @@ -0,0 +1,87 @@ +#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(RTMP_ADAPTER *pAd) +{ + int i; + + initList(&freeNetIfEntryList); + for (i = 0; i < FREE_NETIF_POOL_SIZE; i++) + insertTailList(&freeNetIfEntryList, (RT_LIST_ENTRY *)&freeNetIfEntryPool[i]); + + for (i=0; i < NUM_OF_TX_RING; i++) + initList(&pAd->blockQueueTab[i].NetIfList); + + return; +} + + +BOOLEAN blockNetIf(BLOCK_QUEUE_ENTRY *pBlockQueueEntry, PNET_DEV pNetDev) +{ + NETIF_ENTRY *pNetIfEntry = NULL; + + if ((pNetIfEntry = (NETIF_ENTRY *)removeHeadList(&freeNetIfEntryList)) != NULL) + { + RTMP_OS_NETDEV_STOP_QUEUE(pNetDev); + pNetIfEntry->pNetDev = pNetDev; + insertTailList(&pBlockQueueEntry->NetIfList, (RT_LIST_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(BLOCK_QUEUE_ENTRY *pBlockQueueEntry) +{ + NETIF_ENTRY *pNetIfEntry = NULL; + LIST_HEADER *pNetIfList = &pBlockQueueEntry->NetIfList; + + while((pNetIfEntry = (NETIF_ENTRY *)removeHeadList(pNetIfList)) != NULL) + { + PNET_DEV pNetDev = pNetIfEntry->pNetDev; + + if (pNetDev) { + RTMP_OS_NETDEV_WAKE_QUEUE(pNetDev); + DBGPRINT(RT_DEBUG_TRACE, ("RTMP_OS_NETDEV_WAKE_QUEUE(%s)\n", + RTMP_OS_NETDEV_GET_DEVNAME(pNetDev))); + } + insertTailList(&freeNetIfEntryList, (RT_LIST_ENTRY *)pNetIfEntry); + } + pBlockQueueEntry->SwTxQueueBlockFlag = FALSE; + + return; +} + + +VOID StopNetIfQueue(RTMP_ADAPTER *pAd, UCHAR QueIdx, PNDIS_PACKET pPacket) +{ + UCHAR wdev_idx; + struct wifi_dev *wdev; + + wdev_idx = RTMP_GET_PACKET_WDEV(pPacket); + if ((wdev_idx < WDEV_NUM_MAX) && (pAd->wdev_list[wdev_idx] != NULL)) + { + wdev = pAd->wdev_list[wdev_idx]; + + /* 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.*/ + if ((wdev->bWmmCapable == FALSE) && (wdev->if_dev)) + blockNetIf(&pAd->blockQueueTab[QueIdx], wdev->if_dev); + } + return; +} + +#endif /* BLOCK_NET_IF */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/nfc.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/nfc.c new file mode 100644 index 000000000..9a6a5b6df --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/nfc.c @@ -0,0 +1,906 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2006, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + wsc_v2.c +*/ + +#include "rt_config.h" + +#ifdef WSC_NFC_SUPPORT + +extern UINT8 WPS_DH_G_VALUE[1]; +extern UINT8 WPS_DH_P_VALUE[192]; + +typedef struct _NFC_CMD_INFO { + USHORT vendor_id; + UCHAR action; + UCHAR type; + USHORT data_len; + UCHAR data[0]; +} NFC_CMD_INFO; + +/* + Packet Type: PACKET_OTHERHOST + Packet Protocol: 0x6605 + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Vendor Id | Action | Type | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Length | Data¡K¡K + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- + + Vendor: 0x14C3 + Action: b¡¦<7:6>: 0x0 ¡V To NFC, 0x1 ¡V From NFC + b¡¦<5:0>: 0x00 ¡V Get, 0x01 - Set + Type: + 0 ¡V Command Result (1 byte) + 1 - Configuration (WSC TLV) + 2 ¡V Password (32 bytes) + 3 ¡V IP address (4 bytes) + 4 ¡V RTSP port (4 bytes) + 5 ¡V NFC Status (1 byte) + b'0: 1 - ON, 0 - OFF + b'1: 1 - nfc device detect + 6 ¡V Wireless Radio Status (1byte) +*/ +#define ETH_MTK_NFC 0x6605 +#define NFC_VENDOR_ID 0x14C3 +VOID NfcCommand( + IN PRTMP_ADAPTER pAd, + IN UCHAR Action, + IN UCHAR Type, + IN SHORT DataLen, + IN PUCHAR pData) +{ + PNET_DEV pNetDev = pAd->net_dev; + UCHAR *pBuffer = NULL; + USHORT len; + USHORT vendor_id = NFC_VENDOR_ID, type = ETH_MTK_NFC, net_type; + UCHAR Header802_3[LENGTH_802_3]; + UCHAR SrcMacAddr[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x66, 0x05}; + struct wifi_dev *wdev; + BSS_STRUCT *pMbss; + + len = sizeof(vendor_id) + sizeof(Action) + sizeof(Type) + sizeof(USHORT) + LENGTH_802_3; + if (DataLen > 0) + len += DataLen; + + os_alloc_mem(pAd, (UCHAR **)&pBuffer, (len*sizeof(UCHAR))); + if (pBuffer == NULL) + return; + + pMbss = &pAd->ApCfg.MBSSID[0]; + wdev = &pMbss->wdev; + NdisZeroMemory(pBuffer, len); + NdisZeroMemory(&Header802_3[0], LENGTH_802_3); + + NdisMoveMemory(&Header802_3[0], wdev->bssid, MAC_ADDR_LEN); + NdisMoveMemory((&Header802_3[0] + MAC_ADDR_LEN), &SrcMacAddr[0], MAC_ADDR_LEN); + net_type = htons(type); + NdisMoveMemory((&Header802_3[0] + MAC_ADDR_LEN * 2), &net_type, LENGTH_802_3_TYPE); + //hex_dump("Header802_3", &Header802_3[0], LENGTH_802_3); + + NdisMoveMemory(pBuffer, &Header802_3[0], LENGTH_802_3); + NdisMoveMemory(pBuffer+LENGTH_802_3, &vendor_id, sizeof(vendor_id)); + NdisMoveMemory(pBuffer+LENGTH_802_3+sizeof(vendor_id), &Action, sizeof(Action)); + NdisMoveMemory(pBuffer+LENGTH_802_3+sizeof(vendor_id)+sizeof(Action), &Type, sizeof(Type)); + NdisMoveMemory(pBuffer+LENGTH_802_3+sizeof(vendor_id)+sizeof(Action)+sizeof(Type), &DataLen, sizeof(USHORT)); + if ((DataLen > 0) && (pData != NULL)) + NdisMoveMemory(pBuffer+LENGTH_802_3+sizeof(vendor_id)+sizeof(Action)+sizeof(Type)+sizeof(USHORT), pData, DataLen); + hex_dump("NfcCommand", pBuffer, len); + RtmpOSNotifyRawData(pNetDev, pBuffer, len, 0, ETH_MTK_NFC); + os_free_mem(NULL,pBuffer); + return; +} + + +VOID NfcGenRandomPasswd( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscCtrl) +{ + UCHAR idx = 0; + + NdisZeroMemory(&pWscCtrl->NfcPasswd[0], 32); + + for (idx = 0; idx < NFC_DEV_PASSWD_LEN; idx++) + { + pWscCtrl->NfcPasswd[idx] = RandomByte(pAd); + } + pWscCtrl->NfcPasswdLen = NFC_DEV_PASSWD_LEN; + return; +} + +#define NFC_WSC_TLV_SIZE 512 +INT NfcBuildWscProfileTLV( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscCtrl, + OUT UCHAR *pbuf, + OUT USHORT *pBufLen) +{ + INT Status = NDIS_STATUS_SUCCESS; + PWSC_CREDENTIAL pCredential = NULL; + UCHAR apidx = pWscCtrl->EntryIfIdx; + UCHAR *TB = NULL; + UCHAR *pData = NULL, *pSrcData = NULL; + INT CerLen = 0; + USHORT AuthType = 0; + USHORT EncrType = 0; + //PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscCtrl->RegData; + INT Len = 0, templen = 0; + struct wifi_dev *wdev; + BSS_STRUCT *pMbss; +#ifdef WSC_V2_SUPPORT + PWSC_TLV pWscTLV = &pWscCtrl->WscV2Info.ExtraTlv; +#endif /* WSC_V2_SUPPORT */ + UCHAR RF_Band; + USHORT Channel = 0; + + os_alloc_mem(pAd, (UCHAR **)&pData, (NFC_WSC_TLV_SIZE*sizeof(UCHAR))); + if (pData == NULL) + { + return NDIS_STATUS_RESOURCES; + } + + os_alloc_mem(pAd, (UCHAR **)&TB, (256*sizeof(UCHAR))); + if (TB == NULL) + { + os_free_mem(NULL, pData); + return NDIS_STATUS_RESOURCES; + } + + pMbss = &pAd->ApCfg.MBSSID[apidx]; + wdev = &pMbss->wdev; + pSrcData = pData; + NdisZeroMemory(pData, NFC_WSC_TLV_SIZE); + NdisZeroMemory(&TB[0], 256); + WscCreateProfileFromCfg(pAd, REGISTRAR_ACTION | AP_MODE, pWscCtrl, &pWscCtrl->WscProfile); + pCredential = &pAd->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0]; + // Credential + CerLen += AppendWSCTLV(WSC_ID_NW_INDEX, &TB[0], (PUCHAR)"1", 0); + + AuthType = cpu2be16(pCredential->AuthType); + EncrType = cpu2be16(pCredential->EncrType); + CerLen += AppendWSCTLV(WSC_ID_SSID, &TB[CerLen], pCredential->SSID.Ssid, pCredential->SSID.SsidLength); + CerLen += AppendWSCTLV(WSC_ID_AUTH_TYPE, &TB[CerLen], (UINT8 *)&AuthType, 0); + CerLen += AppendWSCTLV(WSC_ID_ENCR_TYPE, &TB[CerLen], (UINT8 *)&EncrType, 0); + CerLen += AppendWSCTLV(WSC_ID_NW_KEY_INDEX, &TB[CerLen], &pCredential->KeyIndex, 0); + CerLen += AppendWSCTLV(WSC_ID_NW_KEY, &TB[CerLen], pCredential->Key, pCredential->KeyLength); + CerLen += AppendWSCTLV(WSC_ID_MAC_ADDR, &TB[CerLen], wdev->bssid, 0); + + // Prepare plain text + // Reguired attribute item in M8 if Enrollee is STA. + templen = AppendWSCTLV(WSC_ID_CREDENTIAL, pData, TB, CerLen); + pData += templen; + Len += templen; + + /* Optional items. RF_Band, AP_Channel, MAC_Address */ + if (pAd->CommonCfg.Channel > 14) + RF_Band = 0x02; /* 5.0GHz */ + else + RF_Band = 0x01; /* 2.4GHz */ + + templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, &RF_Band, 0); + pData += templen; + Len += templen; + + Channel = pAd->CommonCfg.Channel; +#ifdef RT_BIG_ENDIAN + Channel = SWAP16(Channel); +#endif /* RT_BIG_ENDIAN */ + templen = AppendWSCTLV(WSC_ID_AP_CHANNEL, pData, (UINT8 *)&Channel, 0); + pData += templen; + Len += templen; + + templen = AppendWSCTLV(WSC_ID_MAC_ADDR, pData, wdev->bssid, 0); + pData += templen; + Len += templen; + +#ifdef WSC_V2_SUPPORT + if (pWscCtrl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscCtrl, + FALSE, + NULL, + 0, + &pData, + &Len); + + /* Extra attribute that is not defined in WSC Sepc. */ + if (pWscTLV->pTlvData && pWscTLV->TlvLen) + { + templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen); + pData += templen; + Len += templen; + } + } +#endif // WSC_V2_SUPPORT // + + hex_dump("NfcBuildWscProfileTLV - pData", pSrcData, Len); + if (pbuf && (Len < NFC_WSC_TLV_SIZE)) + { + NdisMoveMemory(pbuf, pSrcData, Len); + *pBufLen = (USHORT)Len; + hex_dump("NfcBuildWscProfileTLV", pbuf, *pBufLen); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: (Len=%d)\n", __FUNCTION__, Len)); + Status = NDIS_STATUS_RESOURCES; + } + + os_free_mem(NULL, pSrcData); + os_free_mem(NULL, TB); + return Status; +} + +INT NfcBuildOOBDevPasswdTLV( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscCtrl, + IN UCHAR HandoverType, + OUT UCHAR *pbuf, + OUT USHORT *pBufLen) +{ + UCHAR *TB = NULL;; + PUCHAR pData = NULL; + PUCHAR pSrcData = NULL; + USHORT PasswdID = 0, len; + //PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscCtrl->RegData; + INT Len = 0, templen = 0; + INT DH_Len = 0, idx; + UCHAR HashData[SHA256_DIGEST_SIZE]; + INT nfc_dev_passwd_len=0; +#ifdef WSC_V2_SUPPORT + PWSC_TLV pWscTLV = &pWscCtrl->WscV2Info.ExtraTlv; +#endif /* WSC_V2_SUPPORT */ + UCHAR RF_Band; + USHORT Channel = 0; + INT Status = NDIS_STATUS_SUCCESS; + + + os_alloc_mem(pAd, (UCHAR **)&pData, (NFC_WSC_TLV_SIZE*sizeof(UCHAR))); + if (pData == NULL) + { + return NDIS_STATUS_RESOURCES; + } + + os_alloc_mem(pAd, (UCHAR **)&TB, (128*sizeof(UCHAR))); + if (pData == NULL) + { + os_free_mem(NULL, pData); + return NDIS_STATUS_RESOURCES; + } + + DH_Len = sizeof(pWscCtrl->RegData.Pke); + /* + Enrollee 192 random bytes for DH key generation + */ + for (idx = 0; idx < 192; idx++) + pWscCtrl->RegData.EnrolleeRandom[idx] = RandomByte(pAd); + + RT_DH_PublicKey_Generate ( + WPS_DH_G_VALUE, sizeof(WPS_DH_G_VALUE), + WPS_DH_P_VALUE, sizeof(WPS_DH_P_VALUE), + pWscCtrl->RegData.EnrolleeRandom, sizeof(pWscCtrl->RegData.EnrolleeRandom), + pWscCtrl->RegData.Pke, (UINT *) &DH_Len); + + /* For Handover case, We may as Registrar + So keep the same public key for Registrar */ + RTMPMoveMemory(pWscCtrl->RegData.Pkr, pWscCtrl->RegData.Pke, DH_Len); + hex_dump("Pkr", pWscCtrl->RegData.Pkr, DH_Len); + hex_dump("Pke", pWscCtrl->RegData.Pkr, DH_Len); + + + RT_SHA256(&pWscCtrl->RegData.Pke[0], 192, &HashData[0]); + RTMPMoveMemory(&pWscCtrl->NfcPasswdHash[0], &HashData[0], NFC_DEV_PASSWD_HASH_LEN); + hex_dump("NfcBuildOOBDevPasswdTLV - Public Key HashData", &HashData[0], 20); + + if (HandoverType == TYPE_PASSWDHO_S || HandoverType == TYPE_PASSWDHO_R) + { + PasswdID = DEV_PASS_ID_NFC_HANDOVER; + pWscCtrl->NfcPasswdID = cpu2be16(PasswdID); + NdisZeroMemory(&pWscCtrl->NfcPasswd[0], 32); + pWscCtrl->NfcPasswdLen = NFC_DEV_PASSWD_LEN; + } + else + { + PasswdID = (RandomByte(pAd) << 8) + RandomByte(pAd); + if (PasswdID < 0x10) + PasswdID = 0x10; + pWscCtrl->NfcPasswdID = cpu2be16(PasswdID); + + NfcGenRandomPasswd(pAd, pWscCtrl); + hex_dump("NfcBuildOOBDevPasswdTLV - NfcPasswd", &pWscCtrl->NfcPasswd[0], NFC_DEV_PASSWD_LEN); + } + + pSrcData = pData; + NdisZeroMemory(pData, NFC_WSC_TLV_SIZE); + NdisZeroMemory(&TB[0], 128); + + if (HandoverType == TYPE_PASSWDHO_R || HandoverType == TYPE_PASSWDHO_S) + { + /* Reserv for "Length of WSC attribute" */ + pData += 2; + } + + hex_dump("NfcBuildOOBDevPasswdTLV - 1 pSrcData", pSrcData, Len); + + NdisMoveMemory(&TB[0], &HashData[0], NFC_DEV_PASSWD_HASH_LEN); + NdisMoveMemory(&TB[20], &pWscCtrl->NfcPasswdID, sizeof(pWscCtrl->NfcPasswdID)); + if (HandoverType == TYPE_PASSWORD) + { + /* New SPEC Handover remove this part. */ + NdisMoveMemory(&TB[22], &pWscCtrl->NfcPasswd[0], NFC_DEV_PASSWD_LEN); + nfc_dev_passwd_len = NFC_DEV_PASSWD_LEN; + } + + templen = AppendWSCTLV(WSC_ID_OOB_DEV_PWD, pData, &TB[0], NFC_DEV_PASSWD_HASH_LEN+sizeof(PasswdID)+nfc_dev_passwd_len); + pData += templen; + Len += templen; + + hex_dump("NfcBuildOOBDevPasswdTLV - 2 pSrcData", pSrcData, Len); + + if (HandoverType == TYPE_PASSWDHO_S) /* Build for Handover Select Message */ + { + templen = AppendWSCTLV(WSC_ID_SSID, pData, pAd->ApCfg.MBSSID[0].Ssid, pAd->ApCfg.MBSSID[0].SsidLen); + pData += templen; + Len += templen; + /* Optional items. RF_Band, AP_Channel and MAC_Address */ + if (pAd->CommonCfg.Channel > 14) + RF_Band = 0x02; /* 5.0GHz */ + else + RF_Band = 0x01; /* 2.4GHz */ + + templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, &RF_Band, 0); + pData += templen; + Len += templen; + + Channel = pAd->CommonCfg.Channel; +#ifdef RT_BIG_ENDIAN + Channel = SWAP16(Channel); +#endif /* RT_BIG_ENDIAN */ + templen = AppendWSCTLV(WSC_ID_AP_CHANNEL, pData, (UINT8 *)&Channel, 0); + pData += templen; + Len += templen; + + templen = AppendWSCTLV(WSC_ID_MAC_ADDR, pData, pAd->CommonCfg.Bssid, 0); + pData += templen; + Len += templen; + + } + else if (HandoverType == TYPE_PASSWDHO_R) /* Build for Handover Request Message */ + { + templen = AppendWSCTLV(WSC_ID_UUID_E, pData, &pWscCtrl->Wsc_Uuid_E[0], 0); + pData += templen; + Len += templen; + } + +#ifdef WSC_V2_SUPPORT + if (pWscCtrl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscCtrl, + FALSE, + NULL, + 0, + &pData, + &Len); + + /* Extra attribute that is not defined in WSC Sepc. */ + if (pWscTLV->pTlvData && pWscTLV->TlvLen) + { + templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen); + pData += templen; + Len += templen; + } + } +#endif // WSC_V2_SUPPORT // + + if (HandoverType == TYPE_PASSWDHO_R || HandoverType == TYPE_PASSWDHO_S) + { + /*Assign for "Length of WSC attribute" */ + len = cpu2be16(Len); + memcpy(pSrcData, &len, 2); + hex_dump("NfcBuildOOBDevPasswdTLV - pSrcData", pSrcData, Len+2); + } + else + hex_dump("NfcBuildOOBDevPasswdTLV - pSrcData", pSrcData, Len); + if (pbuf && (Len < NFC_WSC_TLV_SIZE)) + { + if (HandoverType == TYPE_PASSWDHO_R || HandoverType == TYPE_PASSWDHO_S) + { + NdisMoveMemory(pbuf, pSrcData, Len+2); + *pBufLen = (USHORT)Len+2; + } + else + { + NdisMoveMemory(pbuf, pSrcData, Len); + *pBufLen = (USHORT)Len; + } + hex_dump("NfcBuildOOBDevPasswdTLV", pbuf, *pBufLen); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: (Len=%d)\n", __FUNCTION__, Len)); + Status = NDIS_STATUS_RESOURCES; + } + + os_free_mem(NULL, pSrcData); + os_free_mem(NULL, TB); + return Status; +} + +static BOOLEAN NfcProcessPasswdTV( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR pPlainData, + IN INT PlainLength, + IN PWSC_CTRL pWscCtrl, + IN UCHAR bHandOver) +{ + USHORT WscType, WscLen; + PUCHAR pData; + INT DH_Len = 0, idx; + + pData = pPlainData; + + hex_dump("NfcProcessPasswdTV - PlainData", pPlainData, PlainLength); + // Start to process WSC IEs within credential + if (bHandOver) + { + pData +=2; /* Skip length of WSC attribute */ + PlainLength -= 2; + } + + while (PlainLength > 4) + { + WSC_IE TLV_Recv; + memcpy((UINT8 *)&TLV_Recv, pData, 4); + WscType = be2cpu16(TLV_Recv.Type); + WscLen = be2cpu16(TLV_Recv.Length); + pData += 4; + PlainLength -= 4; + + // Parse M2 WSC type and store to RegData structure + switch (WscType) + { + case WSC_ID_OOB_DEV_PWD: + hex_dump("NfcProcessPasswdTV - WSC_ID_OOB_DEV_PWD", pData, WscLen); + NdisMoveMemory(&pWscCtrl->PeerNfcPasswdHash[0], pData, NFC_DEV_PASSWD_HASH_LEN); + NdisMoveMemory(&pWscCtrl->PeerNfcPasswdID, pData+20, sizeof(pWscCtrl->PeerNfcPasswdID)); + pWscCtrl->PeerNfcPasswdLen = WscLen - 2 - NFC_DEV_PASSWD_HASH_LEN; + if (pWscCtrl->PeerNfcPasswdLen > NFC_DEV_PASSWD_LEN) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s --> PeerNfcPasswdLen(%d) > NFC_DEV_PASSWD_LEN(%d)\n", + __FUNCTION__, pWscCtrl->PeerNfcPasswdLen, NFC_DEV_PASSWD_LEN)); + pWscCtrl->PeerNfcPasswdLen = NFC_DEV_PASSWD_LEN; + } + if (bHandOver== TRUE) + { + if (pWscCtrl->PeerNfcPasswdID != DEV_PASS_ID_NFC_HANDOVER) + DBGPRINT(RT_DEBUG_TRACE, ("%s --> PeerNfcPasswdID(%04x) it should 0x0007 \n", + __FUNCTION__, pWscCtrl->PeerNfcPasswdID)); + } + NdisMoveMemory(&pWscCtrl->PeerNfcPasswd[0], pData+20+sizeof(pWscCtrl->PeerNfcPasswdID), pWscCtrl->PeerNfcPasswdLen); + hex_dump("PeerNfcPasswd", pWscCtrl->PeerNfcPasswd, pWscCtrl->PeerNfcPasswdLen); + + if (bHandOver==FALSE) + { + /* Due to M3 & M4 use the same WscGenPSK1 function, + need copy to NfcPasswd, too */ + NdisMoveMemory(&pWscCtrl->NfcPasswd[0], &pWscCtrl->PeerNfcPasswd[0], pWscCtrl->PeerNfcPasswdLen); + pWscCtrl->NfcPasswdLen = pWscCtrl->PeerNfcPasswdLen; + } + + break; + case WSC_ID_UUID_E: + NdisMoveMemory(pWscCtrl->RegData.PeerInfo.Uuid, pData, WscLen); + break; + case WSC_ID_SSID: + hex_dump("NfcProcessPasswdTV - WSC_ID_SSID", pData, WscLen); + break; + case WSC_ID_VENDOR_EXT: + hex_dump("NfcProcessPasswdTV - WSC_ID_VENDOR_EXT", pData, WscLen); + break; + default: + DBGPRINT(RT_DEBUG_TRACE, ("%s --> Unknown IE 0x%04x\n", __FUNCTION__, WscType)); + break; + } + + // Offset to net WSC Ie + pData += WscLen; + PlainLength -= WscLen; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s --> bHandOver=%d", __FUNCTION__, bHandOver)); + if (bHandOver== FALSE) + { + DH_Len = sizeof(pWscCtrl->RegData.Pkr); + // Enrollee 192 random bytes for DH key generation + for (idx = 0; idx < 192; idx++) + pWscCtrl->RegData.EnrolleeRandom[idx] = RandomByte(pAdapter); + + RT_DH_PublicKey_Generate ( + WPS_DH_G_VALUE, sizeof(WPS_DH_G_VALUE), + WPS_DH_P_VALUE, sizeof(WPS_DH_P_VALUE), + pWscCtrl->RegData.EnrolleeRandom, sizeof(pWscCtrl->RegData.EnrolleeRandom), + pWscCtrl->RegData.Pkr, (UINT *) &DH_Len); + + hex_dump("Pkr", pWscCtrl->RegData.Pkr, 192); + } + + return TRUE; +} + + +VOID NfcParseRspCommand( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN USHORT DataLen) +{ + NFC_CMD_INFO *pNfcCmdInfo = NULL; + BOOLEAN bSetFromNfc = FALSE; + PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[0].WscControl; + + DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__)); + hex_dump("Packet", pData, DataLen); + + os_alloc_mem(pAd, (UCHAR **)&pNfcCmdInfo, (DataLen*sizeof(UCHAR))); + if (pNfcCmdInfo) + { + NdisMoveMemory(pNfcCmdInfo, pData, DataLen); + hex_dump("Packet", &pNfcCmdInfo->data[0], pNfcCmdInfo->data_len); + bSetFromNfc = ((pNfcCmdInfo->action & 0x41) == 0x41); + DBGPRINT(RT_DEBUG_TRACE, ("==> vendor_id: 0x%04x, action = 0x%0x, type = %d, data_len = %u, bSetFromNfc = %d\n", + pNfcCmdInfo->vendor_id, pNfcCmdInfo->action, pNfcCmdInfo->type, pNfcCmdInfo->data_len, bSetFromNfc)); + switch(pNfcCmdInfo->type) + { + case TYPE_CMD_RESULT: + DBGPRINT(RT_DEBUG_TRACE, ("TYPE_CMD_RESULT(=%d): Command result = %d\n", pNfcCmdInfo->type, pNfcCmdInfo->data[0])); + break; + case TYPE_CONFIGURATION: + DBGPRINT(RT_DEBUG_TRACE, ("TYPE_CONFIGURATION(=%d)\n", pNfcCmdInfo->type)); + if (bSetFromNfc) + { + if (pNfcCmdInfo->data_len != 1) + { + /* + Receive Configuration from NFC daemon. + */ + if (WscProcessCredential(pAd, &pNfcCmdInfo->data[0], pNfcCmdInfo->data_len, pWscCtrl) == FALSE) + { + DBGPRINT(RT_DEBUG_TRACE, ("ProcessCredential fail..\n")); + } + else + { + if ((pAd->OpMode == OPMODE_AP) && (pWscCtrl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED)) + { + pWscCtrl->WscConfStatus = WSC_SCSTATE_CONFIGURED; + WscBuildBeaconIE(pAd, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, 0, NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, 0, NULL, 0, AP_MODE); + APUpdateAllBeaconFrame(pAd); + + } + if (pWscCtrl->WscUpdatePortCfgTimerRunning) + { + BOOLEAN bCancel; + RTMPCancelTimer(&pWscCtrl->WscUpdatePortCfgTimer, &bCancel); + } + else + pWscCtrl->WscUpdatePortCfgTimerRunning = TRUE; + RTMPSetTimer(&pWscCtrl->WscUpdatePortCfgTimer, 1000); + } + } + } + else + { + Set_NfcConfigurationToken_Proc(pAd, "1"); + } + break; + case TYPE_PASSWORD: + DBGPRINT(RT_DEBUG_TRACE, ("TYPE_PASSWORD(=%d)\n", pNfcCmdInfo->type)); + if (bSetFromNfc) + { + if (pNfcCmdInfo->data_len != 1) + { + /* + Receive Passwd from NFC daemon. + */ + NfcProcessPasswdTV(pAd, &pNfcCmdInfo->data[0], pNfcCmdInfo->data_len, pWscCtrl, FALSE); + WscGetConfWithoutTrigger(pAd, pWscCtrl, FALSE); + pWscCtrl->bTriggerByNFC = TRUE; + pWscCtrl->NfcModel = MODEL_PASSWORD_TOKEN; + } + } + else + { + Set_NfcPasswdToken_Proc(pAd, "1"); + } + break; + /* New type for Handover */ + case TYPE_PASSWDHO_S: + DBGPRINT(RT_DEBUG_TRACE, ("TYPE_PASSWDHO_S(=%d)\n", pNfcCmdInfo->type)); + if (bSetFromNfc) + { + if (pNfcCmdInfo->data_len != 1) + { + /* + Receive Passwd from NFC daemon. "So far" no this case. + Due to AP always as Registrar in handover procedure, + AP only receive "Handover Request Message". + */ + NfcProcessPasswdTV(pAd, &pNfcCmdInfo->data[0], pNfcCmdInfo->data_len, pWscCtrl, TRUE); + WscGetConfWithoutTrigger(pAd, pWscCtrl, FALSE); + pWscCtrl->bTriggerByNFC = TRUE; + pWscCtrl->NfcModel = MODEL_HANDOVER; /* 2 */ + } + } + else + { + Set_NfcPasswdToken_Proc(pAd, "2"); + } + break; + case TYPE_PASSWDHO_R: + DBGPRINT(RT_DEBUG_TRACE, ("TYPE_PASSWDHO_R(=%d)\n", pNfcCmdInfo->type)); + if (bSetFromNfc) + { + if (pNfcCmdInfo->data_len != 1) + { + /* + Receive Passwd from NFC daemon. + */ + NfcProcessPasswdTV(pAd, &pNfcCmdInfo->data[0], pNfcCmdInfo->data_len, pWscCtrl, TRUE); + WscGetConfWithoutTrigger(pAd, pWscCtrl, FALSE); + pWscCtrl->bTriggerByNFC = TRUE; + pWscCtrl->NfcModel = MODEL_HANDOVER; /* 2 */ + } + } + else + { + /* + "So far" no this case. + Due to AP always as Registrar in handover procedure, + AP only send "Handover Select Message". + */ + Set_NfcPasswdToken_Proc(pAd, "3"); + } + break; + case TYPE_NFC_STATUS: + DBGPRINT(RT_DEBUG_OFF, ("TYPE_NFC_STATUS(=%d): NFC Status = %d\n", pNfcCmdInfo->type, pNfcCmdInfo->data[0])); + pWscCtrl->NfcStatus = pNfcCmdInfo->data[0]; + //complete(&pWscCtrl->NfcComplete); + break; + case TYPE_WIFI_RADIO_STATUS: + DBGPRINT(RT_DEBUG_TRACE, ("TYPE_WIFI_RADIO_STATUS(=%d)\n", pNfcCmdInfo->type)); + if (bSetFromNfc) + { + if (pNfcCmdInfo->data[0] == 1) + MlmeRadioOn(pAd); + else + MlmeRadioOff(pAd); + } + else + { + UCHAR RadioStatus = 0; + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + RadioStatus = 0; + else + RadioStatus = 1; + NfcCommand(pAd, 0x01, TYPE_WIFI_RADIO_STATUS, 1, &RadioStatus); + } + break; + default: + DBGPRINT(RT_DEBUG_TRACE, ("Unknow type(=%d)\n", pNfcCmdInfo->type)); + break; + } + os_free_mem(NULL, pNfcCmdInfo); + } + DBGPRINT(RT_DEBUG_TRACE, ("<==== %s\n", __FUNCTION__)); + return; +} + +INT Set_NfcStatus_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR data = 0; + + /* + Action: b¡¦<7:6>: 0x00 ¡V Request, 0x01 ¡V Notify + b¡¦<5:0>: 0x00 ¡V Get, 0x01 - Set + */ + UCHAR action = 1, type = TYPE_NFC_STATUS; /* 5 - NFC Status */ + + if (simple_strtol(arg, 0, 10) != 0) + data = 1; + + data = (UCHAR)simple_strtol(arg, 0, 10); + DBGPRINT(RT_DEBUG_TRACE, ("%s: Set NFC Status(=%d)\n", __FUNCTION__, data)); + NfcCommand(pAd, action, type, 1, &data); + + return TRUE; +} + +INT Set_NfcPasswdToken_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl; + PUCHAR pBuf = NULL; + USHORT BufLen = 0; + UCHAR action = 1, type = TYPE_PASSWORD; + UCHAR val=0; + BOOLEAN bHandover=FALSE; + /* + Action: b¡¦<7:6>: 0x00 ¡V Request, 0x01 ¡V Notify + b¡¦<5:0>: 0x00 ¡V Get, 0x01 - Set + */ + val = (UCHAR)simple_strtol(arg, 0, 10); + if (val == 1) /* Password Token */ + { + bHandover = FALSE; + type = TYPE_PASSWORD; + } + else if (val == 2) /* Handover Select */ + { + bHandover = TRUE; + type = TYPE_PASSWDHO_S; + } + else if (val == 3) /* Handover Request */ + { + bHandover = TRUE; + type = TYPE_PASSWDHO_R; + } + + os_alloc_mem(pAd, (UCHAR **)&pBuf, (NFC_WSC_TLV_SIZE*sizeof(UCHAR))); + if (pBuf == NULL) + { + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: NfcBuildOOBDevPasswdTLV value(=%d) type(=%d) HandOver(%d)\n", + __FUNCTION__,val, type, bHandover)); + + NfcBuildOOBDevPasswdTLV(pAd, pWscCtrl, type, pBuf, &BufLen); + if (pBuf && (BufLen != 0)) + { + pWscCtrl->bTriggerByNFC = TRUE; + if (type ==TYPE_PASSWORD) + pWscCtrl->NfcModel = MODEL_PASSWORD_TOKEN; + else + pWscCtrl->NfcModel = MODEL_HANDOVER; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: NfcBuildOOBDevPasswdTLV NfcModel(=%d)\n", __FUNCTION__,pWscCtrl->NfcModel)); + NfcCommand(pAd, action, type, BufLen, pBuf); + os_free_mem(NULL, pBuf); + } + + return TRUE; +} + + +INT Set_NfcConfigurationToken_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl; + PUCHAR pBuf = NULL; + USHORT BufLen = 0; + /* + Action: b¡¦<7:6>: 0x00 ¡V Request, 0x01 ¡V Notify + b¡¦<5:0>: 0x00 ¡V Get, 0x01 - Set + */ + UCHAR action = 1, type = TYPE_CONFIGURATION; + + os_alloc_mem(pAd, (UCHAR **)&pBuf, (NFC_WSC_TLV_SIZE*sizeof(UCHAR))); + if (pBuf == NULL) + { + return FALSE; + } + + NfcBuildWscProfileTLV(pAd, pWscCtrl, pBuf, &BufLen); + if (pBuf && (BufLen != 0)) + { + NfcCommand(pAd, action, type, BufLen, pBuf); + os_free_mem(NULL, pBuf); + } + + if ((pAd->OpMode == OPMODE_AP) && (pWscCtrl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED)) + { + pWscCtrl->WscConfStatus = WSC_SCSTATE_CONFIGURED; + WscBuildBeaconIE(pAd, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, 0, NULL, 0,AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, 0, NULL, 0,AP_MODE); + APUpdateAllBeaconFrame(pAd); + + } + if (pWscCtrl->WscUpdatePortCfgTimerRunning) + { + BOOLEAN bCancel; + RTMPCancelTimer(&pWscCtrl->WscUpdatePortCfgTimer, &bCancel); + } + else + pWscCtrl->WscUpdatePortCfgTimerRunning = TRUE; + RTMPSetTimer(&pWscCtrl->WscUpdatePortCfgTimer, 1000); + return TRUE; +} + +INT Get_NfcStatus_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[pObj->ioctl_if].WscControl; + /* + Action: b¡¦<7:6>: 0x0 ¡V To NFC, 0x1 ¡V From NFC + b¡¦<5:0>: 0x0 ¡V Get, 0x01 - Set + */ + UCHAR action = 0, type = TYPE_NFC_STATUS; /* 5 - NFC Status */ + + NfcCommand(pAd, action, type, 0, NULL); + //wait_for_completion_interruptible_timeout(&pWscCtrl->NfcComplete, 10); /* Use timeout to prevent nfchod not exist */ + DBGPRINT(RT_DEBUG_TRACE, ("NfcStatus=%d \n", pWscCtrl->NfcStatus)); + + return TRUE; +} + +/* + NfcPasswdCompute: + 1 - use hex device passwd to calculate PSK1 & PSK2. + 2 - the device password is expressed in hexadecimal using ASCII characters (two characters per octet, uppercase letters only) to caculate PSK1 & PSK2. +*/ +INT Set_DoWpsByNFC_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PWSC_CTRL pWscCtrl; + UINT32 val = 0; + + pWscCtrl = &pAd->ApCfg.MBSSID[apidx].WscControl; + + val = simple_strtol(arg, 0, 10); + if (val == 0) + pWscCtrl->bTriggerByNFC = FALSE; + else + { + pWscCtrl->bTriggerByNFC = TRUE; + pWscCtrl->NfcPasswdCaculate = val; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s : bTriggerByNFC=%d, NfcPasswdCaculate = %d\n", + __FUNCTION__, pWscCtrl->bTriggerByNFC, pWscCtrl->NfcPasswdCaculate)); + + return TRUE; +} + +INT Set_NfcRegenPK_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR apidx = pObj->ioctl_if; + PWSC_CTRL pWscCtrl; + UINT32 val = 0; + + pWscCtrl = &pAd->ApCfg.MBSSID[apidx].WscControl; + + val = simple_strtol(arg, 0, 10); + if (val == 1) + pWscCtrl->bRegenPublicKey = 1; + else + pWscCtrl->bRegenPublicKey = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s : bRegenPublicKey=%d, \n", + __FUNCTION__, pWscCtrl->bRegenPublicKey)); + + return TRUE; +} +#endif /* WSC_NFC_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/op_class.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/op_class.c new file mode 100644 index 000000000..96d984b9e --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/op_class.c @@ -0,0 +1,375 @@ +#ifdef DOT11_N_SUPPORT +#include "rt_config.h" + +typedef enum { + Reserved, + FREQ_2G407, + FREQ_2G414, + FREQ_3G00, + FREQ_3G0025, + FREQ_4G00, + FREQ_4G0025, + FREQ_4G85, + FREQ_4G89, + FREQ_4G9375, + FREQ_5G00, + FREQ_5G0025 +} START_FREQ; +/*definition for Behavior limits set Reference 11n/11ac spec Table D-2 */ +typedef enum { + NOMADICBEHAVIOR = (1 << 1), + LICENSEEXEMPTBEHAVIOR = (1 << 10), + PRIMARYCHANNELLOWERBEHAVIOR = (1 << 13), + PRIMARYCHANNELUPPERBEHAVIOR = (1 << 14), + CCA_EDBEHAVIOR = (1 << 15), + DFS_50_100_BEHAVIOR = (1 << 16), + ITS_NONMOBILE_OPERATIONS = (1 << 17), + ITS_MOBILE_OPERATIONS = (1 << 18), + PLUS_80 = (1 << 19), + USEEIRPFORVHTTXPOWENV = (1 << 20), + COMMON = 0xffffff +} BEHAVIOR_LIMITS_SET; + +/* definition for Behavior limits set Reference 11n/11ac spec Table D-2 */ + +typedef struct { + UCHAR reg_class; /* regulatory class */ + UCHAR global_class; /* Global operating class */ + START_FREQ start_freq; /* Channel starting frequency*/ + UCHAR spacing; /* 0: 20Mhz, 1: 40Mhz */ + UCHAR channelset[16]; /* max 15 channels, use 0 as terminator */ + BEHAVIOR_LIMITS_SET behavior_limit_set; /* Behavior limits set */ +} REG_CLASS, *PREG_CLASS; + +/* +* Table E-1—Operating classes in the United States (11N) +*/ +REG_CLASS reg_class_fcc[] = { + {0, 0, 0, 0, {0}, 0}, /* Invlid entry */ + {1, 115, FREQ_5G00, BW_20, {36, 40, 44, 48, 0}, COMMON}, + {2, 118, FREQ_5G00, BW_20, {52, 56, 60, 64, 0}, DFS_50_100_BEHAVIOR}, + {3, 124, FREQ_5G00, BW_20, {149, 153, 157, 161, 0}, NOMADICBEHAVIOR}, + {4, 121, FREQ_5G00, BW_20, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0}, DFS_50_100_BEHAVIOR}, + {5, 125, FREQ_5G00, BW_20, {149, 153, 157, 161, 165, 0}, LICENSEEXEMPTBEHAVIOR}, + {6, 103, FREQ_4G9375, BW_5, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0}, COMMON}, + {7, 103, FREQ_4G9375, BW_5, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0}, COMMON}, + {8, 102, FREQ_4G89, BW_10, {11, 13, 15, 17, 19, 0}, COMMON}, + {9, 102, FREQ_4G89, BW_10, {11, 13, 15, 17, 19, 0}, COMMON}, + {10, 101, FREQ_4G85, BW_20, {21, 25, 0}, COMMON}, + {11, 101, FREQ_4G85, BW_20, {21, 25, 0}, COMMON}, + {12, 81, FREQ_2G407, BW_25, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0}, LICENSEEXEMPTBEHAVIOR}, + {13, 94, FREQ_3G00, BW_20, {133, 137, 0}, CCA_EDBEHAVIOR}, + {14, 95, FREQ_3G00, BW_10, {132, 134, 136, 138, 0}, CCA_EDBEHAVIOR}, + {15, 96, FREQ_3G0025, BW_5, {131, 132, 133, 134, 135, 136, 137, 138, 0}, CCA_EDBEHAVIOR}, + {16, 0, FREQ_5G0025, BW_5, {170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 0}, ITS_NONMOBILE_OPERATIONS | ITS_MOBILE_OPERATIONS}, + {17, 0, FREQ_5G00, BW_10, {171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 0}, ITS_NONMOBILE_OPERATIONS | ITS_MOBILE_OPERATIONS}, + {18, 0, FREQ_5G00, BW_20, {172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 0}, ITS_NONMOBILE_OPERATIONS | ITS_MOBILE_OPERATIONS}, + {22, 116, FREQ_5G00, BW_40, {36, 44, 0}, PRIMARYCHANNELLOWERBEHAVIOR}, + {23, 119, FREQ_5G00, BW_40, {52, 60, 0}, PRIMARYCHANNELLOWERBEHAVIOR}, + {24, 122, FREQ_5G00, BW_40, {100, 108, 116, 124, 132, 0}, PRIMARYCHANNELLOWERBEHAVIOR | DFS_50_100_BEHAVIOR}, + {25, 126, FREQ_5G00, BW_40, {149, 157, 0}, PRIMARYCHANNELLOWERBEHAVIOR}, + {26, 126, FREQ_5G00, BW_40, {149, 157, 0}, LICENSEEXEMPTBEHAVIOR | PRIMARYCHANNELLOWERBEHAVIOR}, + {27, 117, FREQ_5G00, BW_40, {40, 48, 0}, PRIMARYCHANNELUPPERBEHAVIOR}, + {28, 120, FREQ_5G00, BW_40, {56, 64, 0}, PRIMARYCHANNELUPPERBEHAVIOR}, + {29, 123, FREQ_5G00, BW_40, {104, 112, 120, 128, 136, 0}, NOMADICBEHAVIOR | PRIMARYCHANNELUPPERBEHAVIOR | DFS_50_100_BEHAVIOR}, + {30, 127, FREQ_5G00, BW_40, {153, 161, 0}, NOMADICBEHAVIOR | PRIMARYCHANNELUPPERBEHAVIOR}, + {31, 127, FREQ_5G00, BW_40, {153, 161, 0}, LICENSEEXEMPTBEHAVIOR | PRIMARYCHANNELUPPERBEHAVIOR}, + {32, 83, FREQ_2G407, BW_40, {1, 2, 3, 4, 5, 6, 7, 0}, LICENSEEXEMPTBEHAVIOR | PRIMARYCHANNELLOWERBEHAVIOR}, + {33, 84, FREQ_2G407, BW_40, {5, 6, 7, 8, 9, 10, 11, 0}, LICENSEEXEMPTBEHAVIOR | PRIMARYCHANNELUPPERBEHAVIOR}, + {128, 128, FREQ_5G00, BW_80, {0}, COMMON}, + {129, 129, FREQ_5G00, BW_80, {0}, COMMON}, + {130, 130, FREQ_5G00, BW_80, {0}, COMMON}, + + {0, 0, 0, 0, {0}, 0} /* end */ +}; + +/* + Table E-2—Operating classes in Europe (11N) +*/ +REG_CLASS reg_class_ce[] = { + {0, 0, 0, 0, {0}, 0}, /* Invlid entry */ + {1, 115, FREQ_5G00, BW_20, {36, 40, 44, 48, 0}, COMMON}, + {2, 118, FREQ_5G00, BW_20, {52, 56, 60, 64, 0}, NOMADICBEHAVIOR}, + {3, 121, FREQ_5G00, BW_20, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0}, COMMON}, + {4, 81, FREQ_2G407, BW_25, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0}, LICENSEEXEMPTBEHAVIOR}, + {5, 116, FREQ_5G00, BW_40, {36, 44, 0}, PRIMARYCHANNELLOWERBEHAVIOR}, + {6, 119, FREQ_5G00, BW_40, {52, 60, 0}, PRIMARYCHANNELLOWERBEHAVIOR}, + {7, 122, FREQ_5G00, BW_40, {100, 108, 116, 124, 132, 0}, PRIMARYCHANNELLOWERBEHAVIOR}, + {8, 117, FREQ_5G00, BW_40, {40, 48, 0}, PRIMARYCHANNELUPPERBEHAVIOR}, + {9, 120, FREQ_5G00, BW_40, {56, 64, 0}, PRIMARYCHANNELUPPERBEHAVIOR}, + {10, 123, FREQ_5G00, BW_40, {104, 112, 120, 128, 136, 0}, PRIMARYCHANNELUPPERBEHAVIOR}, /* 10 */ + {11, 83, FREQ_2G407, BW_40, {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, LICENSEEXEMPTBEHAVIOR | PRIMARYCHANNELLOWERBEHAVIOR}, + {12, 84, FREQ_2G407, BW_40, {5, 6, 7, 8, 9, 10, 11, 12, 13, 0}, LICENSEEXEMPTBEHAVIOR | PRIMARYCHANNELUPPERBEHAVIOR}, + {13, 0, FREQ_5G0025, BW_5, {171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 0}, ITS_NONMOBILE_OPERATIONS | ITS_MOBILE_OPERATIONS}, + {14, 0, FREQ_5G00, BW_10, {171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 0}, ITS_NONMOBILE_OPERATIONS | ITS_MOBILE_OPERATIONS}, + {15, 0, FREQ_5G00, BW_20, {172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 0}, ITS_NONMOBILE_OPERATIONS | ITS_MOBILE_OPERATIONS}, + {16, 0, FREQ_5G00, BW_20, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0}, ITS_NONMOBILE_OPERATIONS | ITS_MOBILE_OPERATIONS}, + {17, 125, FREQ_5G00, BW_20, {149, 153, 157, 161, 165, 169, 0}, COMMON}, + {0, 0, 0, 0, {0}, 0} /* end */ +}; + +/* + Table E-3—Operating classes in Japan (11N) +*/ +REG_CLASS reg_class_jp[] = { + {0, 0, 0, 0, {0}, 0}, /* Invlid entry */ + {1, 115, FREQ_5G00, BW_20, {34, 36, 38, 40, 42, 44, 46, 48, 0}, COMMON},/* 1 */ + {2, 112, FREQ_5G00, BW_20, {8, 12, 16, 0}, COMMON}, + {3, 112, FREQ_5G00, BW_20, {8, 12, 16, 0}, COMMON}, + {4, 112, FREQ_5G00, BW_20, {8, 12, 16, 0}, COMMON}, + {5, 112, FREQ_5G00, BW_20, {8, 12, 16, 0}, COMMON}, + {6, 112, FREQ_5G00, BW_20, {8, 12, 16, 0}, COMMON}, + {7, 109, FREQ_4G00, BW_20, {184, 188, 192, 196, 0}, COMMON}, + {8, 109, FREQ_4G00, BW_20, {184, 188, 192, 196, 0}, COMMON}, + {9, 109, FREQ_4G00, BW_20, {184, 188, 192, 196, 0}, COMMON}, + {10, 109, FREQ_4G00, BW_20, {184, 188, 192, 196, 0}, COMMON},/* 10 */ + {11, 109, FREQ_4G00, BW_20, {184, 188, 192, 196, 0}, COMMON}, + {12, 113, FREQ_5G00, BW_10, {7, 8, 9, 11, 0}, COMMON}, + {13, 113, FREQ_5G00, BW_10, {7, 8, 9, 11, 0}, COMMON}, + {14, 113, FREQ_5G00, BW_10, {7, 8, 9, 11, 0}, COMMON}, + {15, 113, FREQ_5G00, BW_10, {7, 8, 9, 11, 0}, COMMON}, + {16, 110, FREQ_4G00, BW_10, {183, 184, 185, 187, 188, 189, 0}, COMMON}, + {17, 110, FREQ_4G00, BW_10, {183, 184, 185, 187, 188, 189, 0}, COMMON}, + {18, 110, FREQ_4G00, BW_10, {183, 184, 185, 187, 188, 189, 0}, COMMON}, + {19, 110, FREQ_4G00, BW_10, {183, 184, 185, 187, 188, 189, 0}, COMMON}, + {20, 110, FREQ_4G00, BW_10, {183, 184, 185, 187, 188, 189, 0}, COMMON}, + {21, 114, FREQ_5G0025, BW_5, {6, 7, 8, 9, 10, 11, 0}, COMMON}, + {22, 114, FREQ_5G0025, BW_5, {6, 7, 8, 9, 10, 11, 0}, COMMON}, + {23, 114, FREQ_5G0025, BW_5, {6, 7, 8, 9, 10, 11, 0}, COMMON}, + {24, 114, FREQ_5G0025, BW_5, {6, 7, 8, 9, 10, 11, 0}, COMMON}, + {25, 111, FREQ_4G0025, BW_5, {182, 183, 184, 185, 186, 187, 188, 189, 0}, COMMON}, + {26, 111, FREQ_4G0025, BW_5, {182, 183, 184, 185, 186, 187, 188, 189, 0}, COMMON}, + {27, 111, FREQ_4G0025, BW_5, {182, 183, 184, 185, 186, 187, 188, 189, 0}, COMMON}, + {28, 111, FREQ_4G0025, BW_5, {182, 183, 184, 185, 186, 187, 188, 189, 0}, COMMON}, + {29, 111, FREQ_4G0025, BW_5, {182, 183, 184, 185, 186, 187, 188, 189, 0}, COMMON}, + {30, 81, FREQ_2G407, BW_25, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0}, LICENSEEXEMPTBEHAVIOR}, + {31, 82, FREQ_2G414, BW_25, {14, 0}, LICENSEEXEMPTBEHAVIOR}, + {32, 118, FREQ_5G00, BW_20, {52, 56, 60, 64, 0}, COMMON}, + {33, 118, FREQ_5G00, BW_20, {52, 56, 60, 64, 0}, COMMON}, + {34, 121, FREQ_5G00, BW_20, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0}, DFS_50_100_BEHAVIOR}, + {35, 121, FREQ_5G00, BW_20, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0}, DFS_50_100_BEHAVIOR}, + {36, 116, FREQ_5G00, BW_40, {36, 44, 0}, PRIMARYCHANNELLOWERBEHAVIOR}, + {37, 119, FREQ_5G00, BW_40, {52, 60, 0}, PRIMARYCHANNELLOWERBEHAVIOR}, + {38, 119, FREQ_5G00, BW_40, {52, 60, 0}, PRIMARYCHANNELLOWERBEHAVIOR}, + {39, 122, FREQ_5G00, BW_40, {100, 108, 116, 124, 132, 0}, PRIMARYCHANNELLOWERBEHAVIOR | DFS_50_100_BEHAVIOR}, + {40, 122, FREQ_5G00, BW_40, {100, 108, 116, 124, 132, 0}, PRIMARYCHANNELLOWERBEHAVIOR | DFS_50_100_BEHAVIOR}, + {41, 117, FREQ_5G00, BW_40, {40, 48, 0}, PRIMARYCHANNELUPPERBEHAVIOR}, + {42, 120, FREQ_5G00, BW_40, {56, 64, 0}, PRIMARYCHANNELUPPERBEHAVIOR}, + {43, 120, FREQ_5G00, BW_40, {56, 64, 0}, PRIMARYCHANNELUPPERBEHAVIOR}, + {44, 123, FREQ_5G00, BW_40, {104, 112, 120, 128, 136, 0}, PRIMARYCHANNELUPPERBEHAVIOR | DFS_50_100_BEHAVIOR}, + {45, 123, FREQ_5G00, BW_40, {104, 112, 120, 128, 136, 0}, PRIMARYCHANNELUPPERBEHAVIOR | DFS_50_100_BEHAVIOR}, + {46, 104, FREQ_4G00, BW_40, {184, 192, 0}, PRIMARYCHANNELLOWERBEHAVIOR}, + {47, 104, FREQ_4G00, BW_40, {184, 192, 0}, PRIMARYCHANNELLOWERBEHAVIOR}, + {48, 104, FREQ_4G00, BW_40, {184, 192, 0}, PRIMARYCHANNELLOWERBEHAVIOR}, + {49, 104, FREQ_4G00, BW_40, {184, 192, 0}, PRIMARYCHANNELLOWERBEHAVIOR}, + {50, 104, FREQ_4G00, BW_40, {184, 192, 0}, PRIMARYCHANNELLOWERBEHAVIOR}, + {51, 105, FREQ_4G00, BW_40, {188, 196, 0}, PRIMARYCHANNELUPPERBEHAVIOR}, + {52, 105, FREQ_4G00, BW_40, {188, 196, 0}, PRIMARYCHANNELUPPERBEHAVIOR}, + {53, 105, FREQ_4G00, BW_40, {188, 196, 0}, PRIMARYCHANNELUPPERBEHAVIOR}, + {54, 105, FREQ_4G00, BW_40, {188, 196, 0}, PRIMARYCHANNELUPPERBEHAVIOR}, + {55, 105, FREQ_4G00, BW_40, {188, 196, 0}, PRIMARYCHANNELUPPERBEHAVIOR}, + {56, 83, FREQ_2G407, BW_40, {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, LICENSEEXEMPTBEHAVIOR | PRIMARYCHANNELLOWERBEHAVIOR}, + {57, 84, FREQ_2G407, BW_40, {5, 6, 7, 8, 9, 10, 11, 12, 13, 0}, LICENSEEXEMPTBEHAVIOR | PRIMARYCHANNELUPPERBEHAVIOR}, + {58, 121, FREQ_5G00, BW_20, {100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 0}, NOMADICBEHAVIOR | LICENSEEXEMPTBEHAVIOR}, + {0, 0, 0, 0, {0}, 0} /* end */ +}; + +REG_CLASS reg_class_cn[] = { + {0, 0, 0, 0, {0}, 0}, /* Invlid entry */ + {1, 115, FREQ_5G00, BW_20, {36, 40, 44, 48, 0}, USEEIRPFORVHTTXPOWENV}, + {2, 118, FREQ_5G00, BW_20, {52, 56, 60, 64, 0}, DFS_50_100_BEHAVIOR | USEEIRPFORVHTTXPOWENV}, + {3, 125, FREQ_5G00, BW_20, {149, 153, 157, 161, 165, 0}, USEEIRPFORVHTTXPOWENV}, + {4, 116, FREQ_5G00, BW_40, {36, 44, 0}, PRIMARYCHANNELLOWERBEHAVIOR | USEEIRPFORVHTTXPOWENV}, + {5, 119, FREQ_5G00, BW_40, {52, 60, 0}, PRIMARYCHANNELLOWERBEHAVIOR | DFS_50_100_BEHAVIOR | USEEIRPFORVHTTXPOWENV}, + {6, 126, FREQ_5G00, BW_40, {149, 157, 0}, PRIMARYCHANNELLOWERBEHAVIOR | USEEIRPFORVHTTXPOWENV}, + {7, 81, FREQ_2G407, BW_25, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0}, LICENSEEXEMPTBEHAVIOR}, + {8, 83, FREQ_2G407, BW_40, {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}, LICENSEEXEMPTBEHAVIOR | PRIMARYCHANNELLOWERBEHAVIOR}, + {9, 84, FREQ_2G407, BW_40, {5, 6, 7, 8, 9, 10, 11, 12, 13, 0}, LICENSEEXEMPTBEHAVIOR | PRIMARYCHANNELUPPERBEHAVIOR}, + {0, 0, 0, 0, {0}, 0} /* end */ +}; + +BOOLEAN is_channel_in_channelset(UCHAR *ChannelSet, UCHAR Channel) +{ + int index = 0; + + while (ChannelSet[index] != 0) { + /* TODO: Need to consider behavior limits set!! */ + if (ChannelSet[index] == Channel) + return TRUE; + + index++; + } + + return FALSE; +} + +PVOID get_reg_table_by_country(UCHAR *CountryCode) +{ + UCHAR reg_region; + PVOID reg_class_table = NULL; +#ifdef EXT_BUILD_CHANNEL_LIST + PCH_REGION pChReg; + + pChReg = GetChRegion(CountryCode); + reg_region = pChReg->DfsType; +#else + PCOUNTRY_PROP pCountryProp; + + pCountryProp = GetCountryProp(CountryCode); + reg_region = pCountryProp->DfsType; +#endif + + { + switch (reg_region) { + case CE: + reg_class_table = (PVOID)reg_class_ce; + break; + + case JAP: + reg_class_table = (PVOID)reg_class_jp; + break; + + case CHN: + reg_class_table = (PVOID)reg_class_cn; + break; + + case FCC: + default: + reg_class_table = (PVOID)reg_class_fcc; + break; + } + } + + return reg_class_table; +} + +PUCHAR get_channelset_by_reg_class( + IN RTMP_ADAPTER *pAd, + IN UINT8 RegulatoryClass) +{ + int i = 1; /* skip Invlid entry */ + PUCHAR channelset = NULL; + + PREG_CLASS reg_class = (PREG_CLASS)get_reg_table_by_country(pAd->CommonCfg.CountryCode); + + if (reg_class) { + do { + /* find channelset */ + if ((reg_class[i].reg_class == RegulatoryClass) + || (reg_class[i].global_class == RegulatoryClass)) { + channelset = reg_class[i].channelset; + break; + } + + i++; + } while (reg_class[i].reg_class != 0); + } + + return channelset; +} + + +UINT BW_VALUE[] = {20, 40, 80, 160, 10, 5, 162, 60, 25}; +UCHAR get_regulatory_class(RTMP_ADAPTER *pAd, UCHAR Channel) +{ + int i = 1; /* skip Invlid entry */ + UCHAR regclass = 0; + UINT16 bw = BW_20; + UCHAR cfg_ht_bw = pAd->CommonCfg.RegTransmitSetting.field.BW; + UCHAR reg_domain = pAd->reg_domain; + + if (cfg_ht_bw) + bw = BW_40; + else + bw = BW_20; + + if (Channel == 0) + Channel = pAd->CommonCfg.Channel; + + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_INFO, + ("%s(): Channel=%d,HT_BW=%d bw=%d\n", + __func__, + Channel, + cfg_ht_bw, + bw)); + { + PREG_CLASS reg_class = (PREG_CLASS)get_reg_table_by_country(pAd->CommonCfg.CountryCode); + + if (reg_class) { + do { + if (BW_VALUE[reg_class[i].spacing] >= BW_VALUE[bw]) { + /* find channelset */ + if (is_channel_in_channelset(reg_class[i].channelset, Channel)) { + regclass = (reg_domain == REG_LOCAL) ? + reg_class[i].reg_class : reg_class[i].global_class; + break; + } + } + i++; + } while (reg_class[i].reg_class != 0); + } + } + + return regclass; +} + +INT Show_ChannelSet_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + int i = 1; /* skip Invlid entry */ + int Channel = 0, Type = 0, IsAc = 0, OpClass = 0; + RTMP_STRING *arg0_type = NULL, *arg1_channel = NULL, *arg2_is_ac = NULL; + + arg0_type = strsep(&arg, ":"); + arg1_channel = strsep(&arg, ":"); + arg2_is_ac = strsep(&arg, ":"); + + if (arg0_type == NULL || arg1_channel == NULL || arg2_is_ac == NULL) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + (":%s: Invalid parameters\n", __func__)); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + (":%s: TYPE:CHANNEL:ISAC\n", __func__)); + return FALSE; + } + + Type = simple_strtol(arg0_type, 0, 10); + Channel = simple_strtol(arg1_channel, 0, 10); + IsAc = simple_strtol(arg2_is_ac, 0, 10); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + (":%s: Type = %d Channel = %d IsAc = %d\n", __func__, Type, Channel, IsAc)); + + if (Type != 0) { + OpClass = get_regulatory_class(pAd, Channel); + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("OpClass(%d) Channel(%d)\n", OpClass, Channel)); + } else { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("\n%-8s%-8s%-16s\n", "Regclass", "Spacing", "Channelset/CenterFreq")); + { + PREG_CLASS reg_class = (PREG_CLASS)get_reg_table_by_country(pAd->CommonCfg.CountryCode); + + do { + int j = 0; + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-8d%-8d", reg_class[i].reg_class, reg_class[i].spacing)); + + while (reg_class[i].channelset[j] != 0) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%-2d,", reg_class[i].channelset[j])); + j++; + } + + i++; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("\n")); + } while (reg_class[i].reg_class != 0); + } + } + + return TRUE; +} + + +#endif /* DOT11_N_SUPPORT */ + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/owe.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/owe.c new file mode 100644 index 000000000..beae0d21a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/owe.c @@ -0,0 +1,595 @@ +#ifdef CONFIG_OWE_SUPPORT + +#include "rt_config.h" +#include "ecc.h" +#include "crypt_sha2.h" + +UCHAR OWE_TRANS_OUI[] = {0x50, 0x6f, 0x9a, 0x1c}; + +#ifdef APCLI_OWE_SUPPORT +UCHAR apcli_owe_supp_groups[APCLI_MAX_SUPPORTED_OWE_GROUPS] = {19, 20}; +#endif + +static inline UINT16 GET_LE16(const UCHAR *a) +{ + return (a[1] << 8) | a[0]; +} + +static UINT owe_process_peer_pubkey(OWE_INFO *owe, UCHAR *peer_pub_key, UCHAR pubkey_len) +{ + SAE_BN *peer_pubkey_bn = NULL; + BIG_INTEGER_EC_POINT *peer_pub_point = NULL; + EC_GROUP_INFO_BI *ec_group_bi = (EC_GROUP_INFO_BI *)owe->group_info_bi; + UINT ret = 0; + + if (owe->peer_pub_key != NULL) + ecc_point_free((BIG_INTEGER_EC_POINT **)&owe->peer_pub_key); + + ecc_point_init(&peer_pub_point); + SAE_BN_BIN2BI((UINT8 *)peer_pub_key, + pubkey_len, + &peer_pubkey_bn); + + SAE_BN_COPY(peer_pubkey_bn, &peer_pub_point->x); + + while (peer_pub_point->y == NULL) + ecc_point_find_by_x(ec_group_bi, peer_pub_point->x, &peer_pub_point->y, TRUE); + + if (ecc_point_is_on_curve(ec_group_bi, peer_pub_point) == FALSE) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_OFF, ("%s, point is not on curve\n", __func__)); + goto err; + } + SAE_ECC_SET_Z_TO_1(peer_pub_point); + owe->peer_pub_key = (VOID *)peer_pub_point; + + ret = 1; + +err: + if (peer_pubkey_bn) + SAE_BN_FREE(&peer_pubkey_bn); + + return ret; +} + +INT owe_calculate_secret(OWE_INFO *owe, SAE_BN **secret) +{ + BIG_INTEGER_EC_POINT *peer_pub = (BIG_INTEGER_EC_POINT *)owe->peer_pub_key; + SAE_BN *priv_key = owe->priv_key; + BIG_INTEGER_EC_POINT *secret_point = NULL; + EC_GROUP_INFO_BI *ec_group_bi = (EC_GROUP_INFO_BI *)owe->group_info_bi; + INT ret = 0; + + ECC_POINT_MUL(peer_pub, priv_key, ec_group_bi, &secret_point); + SAE_ECC_3D_to_2D(ec_group_bi, secret_point); + + if (secret_point == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_ERROR, + ("==> %s(), can't output the common secret point\n", __func__)); + return ret; + } + + SAE_BN_COPY(secret_point->x, secret); + + if (secret_point) + ecc_point_free(&secret_point); + ret = 1; + + return ret; +} + +static BIG_INTEGER_EC_POINT *get_owe_pub_key(OWE_INFO *owe) +{ + return (BIG_INTEGER_EC_POINT *)owe->pub_key; +} + +static VOID owe_calculate_pmkid(OWE_INFO *owe, + SAE_BN * my_pubkey, + UCHAR *peer_pub, + UCHAR type, + UCHAR peer_pub_length, + UINT16 group, + UCHAR *pmkid) +{ + EC_GROUP_INFO *ec_group = NULL; + UCHAR *material = NULL; + UINT material_length = 0; + const UCHAR *_addr[2]; + INT _len[2]; + + ec_group = (EC_GROUP_INFO *)owe->group_info; + + if (os_alloc_mem(NULL, (UCHAR **)&material, ec_group->prime_len) == NDIS_STATUS_FAILURE) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_ERROR, + ("==> %s(), alloc buf for material failed...\n", __func__)); + goto err; + } + + /* Truncate-128(hash(C | A)) */ + if (type == SUBTYPE_ASSOC_REQ) { + /*we are processing ecdh from (re)assoc req*/ + _addr[0] = peer_pub; + _len[0] = peer_pub_length; + SAE_BN_BI2BIN_WITH_PAD(my_pubkey, material, &material_length, ec_group->prime_len); + _addr[1] = material; + _len[1] = material_length; + } else { + SAE_BN_BI2BIN_WITH_PAD(my_pubkey, material, &material_length, ec_group->prime_len); + _addr[0] = material; + _len[0] = material_length; + _addr[1] = peer_pub; + _len[1] = peer_pub_length; + } + + switch (group) { + case ECDH_GROUP_521: + break; + case ECDH_GROUP_384: + rt_sha384_vector(2, _addr, _len, pmkid); + break; + case ECDH_GROUP_256: + default: + rt_sha256_vector(2, _addr, _len, pmkid); + } + + hex_dump("OWE PMKID:", pmkid, LEN_PMKID); + + if (owe->pmkid) + os_free_mem(NULL, owe->pmkid); + + if (os_alloc_mem(NULL, (UCHAR **)&owe->pmkid, LEN_PMKID) == NDIS_STATUS_FAILURE) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_ERROR, + ("==> %s(), alloc pmkid failed...\n", __func__)); + goto err; + } + NdisMoveMemory(owe->pmkid, pmkid, LEN_PMKID); + +err: + if (material) + os_free_mem(NULL, material); +} + +INT process_ecdh_element( + struct _RTMP_ADAPTER *ad, + VOID *pEntry_v, + EXT_ECDH_PARAMETER_IE *ext_ie_ptr, + UCHAR ie_len, + UCHAR type, + BOOLEAN update_only_grp_info) +{ + MAC_TABLE_ENTRY *entry = (MAC_TABLE_ENTRY *)pEntry_v; + OWE_INFO *owe = &entry->owe; + UINT16 peer_group = 0; + UCHAR remain_len = 0; + UCHAR *pos = NULL; + UCHAR *peer_pub = NULL; + SAE_BN *secret = NULL; + UCHAR *hkey = NULL; + BIG_INTEGER_EC_POINT *my_pubkey = NULL; + EC_GROUP_INFO *ec_group = NULL; + UINT hkey_length = 0; + UCHAR *sec_buf = NULL; + UINT sec_length = 0; + UCHAR prk[SHA512_DIGEST_SIZE], pmkid[SHA512_DIGEST_SIZE]; + UCHAR hash_len = 0; + + if ((ext_ie_ptr->ext_ie_id == 0) && (ext_ie_ptr->length == 0)) + return MLME_SUCCESS; + + remain_len = ie_len - 1;/*the length which starts from group field directly.*/ + pos = (UCHAR *)&ext_ie_ptr->group;/*start from group field directly.*/ + + peer_group = GET_LE16((UCHAR *)&ext_ie_ptr->group); + if ((peer_group != ECDH_GROUP_256) && (peer_group != ECDH_GROUP_384) && (peer_group != ECDH_GROUP_521)) + owe->last_try_group = 0; + else { + owe->last_try_group = peer_group; + + switch (peer_group) { + case ECDH_GROUP_521: + entry->key_deri_alg = SEC_KEY_DERI_SHA512; + return MLME_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; + case ECDH_GROUP_384: + entry->key_deri_alg = SEC_KEY_DERI_SHA384; + return MLME_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; + case ECDH_GROUP_256: + default: + entry->key_deri_alg = SEC_KEY_DERI_SHA256; + } + } + + if (update_only_grp_info == TRUE) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_TRACE, + ("==> %s(), Update group info :%d\n", __func__, entry->key_deri_alg)); + return MLME_SUCCESS; + } + + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_TRACE, + ("==> %s(), peer_group:%d\n", __func__, peer_group)); + + /*if we cannot support the group, skip the further steps.*/ + if (owe->last_try_group == 0) + return MLME_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; + + pos = pos + sizeof(peer_group); + remain_len = remain_len - sizeof(peer_group); + + if (init_owe_group(owe, peer_group) == 0) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_ERROR, + ("==> %s(), init_owe_group failed. shall not happen!\n", __func__)); + return MLME_UNSPECIFY_FAIL; + } + + if (os_alloc_mem(NULL, (UCHAR **)&peer_pub, remain_len) == NDIS_STATUS_FAILURE) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_ERROR, + ("==> %s(), alloc buf for peer_pub failed...\n", __func__)); + return MLME_UNSPECIFY_FAIL; + } + NdisMoveMemory(peer_pub, pos, remain_len); + if (owe_process_peer_pubkey(owe, peer_pub, remain_len) == 0) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_ERROR, + ("==> %s(), owe_process_peer_pubkey failed...\n", __func__)); + return MLME_UNSPECIFY_FAIL; + } + + SAE_BN_INIT(&secret); + if (owe_calculate_secret(owe, &secret) == 0) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_ERROR, + ("==> %s(), owe_calculate_secret failed...\n", __func__)); + return MLME_UNSPECIFY_FAIL; + } + + ec_group = (EC_GROUP_INFO *)owe->group_info; + if (os_alloc_mem(NULL, (UCHAR **)&sec_buf, ec_group->prime_len) == NDIS_STATUS_FAILURE) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_ERROR, + ("==> %s(), alloc buf for hkey failed...\n", __func__)); + return MLME_UNSPECIFY_FAIL; + } + SAE_BN_BI2BIN_WITH_PAD(secret, sec_buf, &sec_length, ec_group->prime_len); + + if (os_alloc_mem(NULL, (UCHAR **)&hkey, ec_group->prime_len + remain_len + 2) == NDIS_STATUS_FAILURE) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_ERROR, + ("==> %s(), alloc buf for hkey failed...\n", __func__)); + return MLME_UNSPECIFY_FAIL; + } + + my_pubkey = get_owe_pub_key(owe); + if (my_pubkey == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_ERROR, + ("==> %s(), get own pub failed, shall not happen...\n", __func__)); + return MLME_UNSPECIFY_FAIL; + } + + owe_calculate_pmkid(owe, my_pubkey->x, peer_pub, type, remain_len, peer_group, pmkid); + + /* C | A | group */ + if (type == SUBTYPE_ASSOC_REQ) { + /*we are processing ecdh from (re)assoc req*/ + NdisMoveMemory(hkey, peer_pub, remain_len); + SAE_BN_BI2BIN_WITH_PAD(my_pubkey->x, hkey + remain_len, &hkey_length, ec_group->prime_len); + hkey_length += remain_len; + NdisMoveMemory(hkey+hkey_length, &peer_group, sizeof(peer_group)); + hkey_length += sizeof(peer_group); + } else if (type == SUBTYPE_ASSOC_RSP) { + SAE_BN_BI2BIN_WITH_PAD(my_pubkey->x, hkey + hkey_length, &hkey_length, ec_group->prime_len); + NdisMoveMemory(hkey + hkey_length, peer_pub, remain_len); + hkey_length += remain_len; + NdisMoveMemory(hkey + hkey_length, &peer_group, sizeof(peer_group)); + hkey_length += sizeof(peer_group); + } else { + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_ERROR, + ("==> %s(), parsing wrong type, shall not happen\n", __func__)); + return MLME_UNSPECIFY_FAIL; + } + if (peer_group == ECDH_GROUP_256) { + hash_len = SHA256_DIGEST_SIZE; + RT_HMAC_SHA256(hkey, hkey_length, sec_buf, sec_length, prk, hash_len); + /*FIXME: is the length of PMK that to use LEN_PMK here is correct?*/ + HKDF_expand_sha256(prk, + hash_len, + "OWE Key Generation", + 18, + entry->PMK, + LEN_PMK); + } else if (peer_group == ECDH_GROUP_384) { + hash_len = SHA384_DIGEST_SIZE; + RT_HMAC_SHA384(hkey, hkey_length, sec_buf, sec_length, prk, hash_len); + HKDF_expand_sha384(prk, + hash_len, + "OWE Key Generation", + 18, + entry->PMK, + LEN_PMK_SHA384); + } + hex_dump("OWE PRK:", prk, hash_len); + hex_dump("OWE PMK:", entry->PMK, hash_len); + + if (sec_buf) + os_free_mem(NULL, sec_buf); + if (hkey) + os_free_mem(NULL, hkey); + + if (secret) + SAE_BN_FREE(&secret); + if (peer_pub) + os_free_mem(NULL, peer_pub); + + return MLME_SUCCESS; +} + +INT init_owe_group(OWE_INFO *owe, UCHAR group) +{ + BIG_INTEGER_EC_POINT *generator = NULL; + EC_GROUP_INFO *ec_group = get_ecc_group_info(group); + EC_GROUP_INFO_BI *ec_group_bi = get_ecc_group_info_bi(group); + INT ret = 0; + + if (owe->inited == TRUE) + return 1; + + if (ec_group == NULL || ec_group_bi == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_ERROR, + ("==> %s(), get ec_group failed. shall not happen!\n", __func__)); + goto err; + } + + if (owe->group_info == NULL) + owe->group_info = (VOID *)ec_group; + if (owe->group_info_bi == NULL) + owe->group_info_bi = (VOID *)ec_group_bi; + + ecc_point_init(&generator); + SAE_BN_COPY(ec_group_bi->gx, &generator->x); + SAE_BN_COPY(ec_group_bi->gy, &generator->y); + SAE_ECC_SET_Z_TO_1(generator); + + owe->generator = (VOID *)generator; + if (ecc_gen_key(ec_group, ec_group_bi, &owe->priv_key, generator, &owe->pub_key) == 0) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_ERROR, + ("==> %s(), ecc_gen_key failed...\n", __func__)); + goto err; + } + + owe->inited = TRUE; + + ret = 1; +err: + return ret; +} + +INT build_owe_dh_ie(struct _RTMP_ADAPTER *ad, + VOID *pEntry_v, + UCHAR *buf, + UCHAR group) +{ + MAC_TABLE_ENTRY *pentry = (MAC_TABLE_ENTRY *)pEntry_v; + OWE_INFO *owe = &pentry->owe; + + EC_GROUP_INFO *ec_group = NULL; + EC_GROUP_INFO_BI *ec_group_bi = NULL; + BIG_INTEGER_EC_POINT *generator = NULL; + BIG_INTEGER_EC_POINT *my_pub_key = NULL; + UCHAR *pub_buf = NULL; + INT extend_length = 0; + UCHAR ie = IE_WLAN_EXTENSION; + UCHAR ie_len = 0; + UCHAR ext_ie = IE_EXTENSION_ID_ECDH; + UINT16 g = group; + UINT pub_buf_length = 0; + + ec_group = (EC_GROUP_INFO *)owe->group_info; + ec_group_bi = (EC_GROUP_INFO_BI *)owe->group_info_bi; + + generator = (BIG_INTEGER_EC_POINT *)owe->generator; + my_pub_key = (BIG_INTEGER_EC_POINT *)owe->pub_key; + + if (os_alloc_mem(NULL, (UCHAR **)&pub_buf, ec_group->prime_len) == NDIS_STATUS_FAILURE) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_OWE, DBG_LVL_ERROR, + ("==> %s(), ecc_gen_key failed...\n", __func__)); + goto err; + } + SAE_BN_BI2BIN_WITH_PAD(my_pub_key->x, pub_buf, &pub_buf_length, ec_group->prime_len); + + NdisMoveMemory(buf + extend_length, &ie, sizeof(ie)); + extend_length += 1; + + ie_len = 1 + 2 + ec_group->prime_len; + NdisMoveMemory(buf + extend_length, &ie_len, sizeof(ie_len)); + extend_length += 1; + + NdisMoveMemory(buf + extend_length, &ext_ie, sizeof(ext_ie)); + extend_length += 1; + + NdisMoveMemory(buf + extend_length, &g, sizeof(g)); + extend_length += 2; + + NdisMoveMemory(buf + extend_length, pub_buf, ec_group->prime_len); + extend_length += ec_group->prime_len; + + hex_dump("ECDH parameter:", (UCHAR *)buf, extend_length); + +err: + if (pub_buf) + os_free_mem(NULL, pub_buf); + + return extend_length; +} + +INT deinit_owe_group(OWE_INFO *owe) +{ + if (owe->peer_pub_key != NULL) { + ecc_point_free((BIG_INTEGER_EC_POINT **)&owe->peer_pub_key); + owe->peer_pub_key = NULL; + } + if (owe->pub_key != NULL) { + ecc_point_free((BIG_INTEGER_EC_POINT **)&owe->pub_key); + owe->pub_key = NULL; + } + if (owe->generator != NULL) { + ecc_point_free((BIG_INTEGER_EC_POINT **)&owe->generator); + owe->generator = NULL; + } + if (owe->priv_key != NULL) { + SAE_BN_FREE(&owe->priv_key); + owe->priv_key = NULL; + } + + if (owe->pmkid != NULL) { + os_free_mem(NULL, owe->pmkid); + owe->pmkid = NULL; + } + + /*TODO: deinit group_info itself. need to discuss with E*/ + owe->group_info = NULL; + owe->group_info_bi = NULL; + + owe->last_try_group = 0; + owe->inited = FALSE; + + return 0; +} + +#ifdef CONFIG_AP_SUPPORT +USHORT owe_pmkid_ecdh_process(RTMP_ADAPTER *pAd, + VOID *pEntry_v, + UCHAR *rsn_ie, + UCHAR rsn_ie_len, + EXT_ECDH_PARAMETER_IE *ecdh_ie, + UCHAR ecdh_ie_length, + PUINT8 pPmkid, + UINT8 *pmkid_count, + UCHAR type) +{ + BOOLEAN need_update_grp_info = FALSE; + BOOLEAN need_process_ecdh_ie = FALSE; + INT CacheIdx;/* Key cache */ + USHORT ret = MLME_SUCCESS; + MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY *)pEntry_v; + + pPmkid = WPA_ExtractSuiteFromRSNIE(rsn_ie, + rsn_ie_len, + PMKID_LIST, + pmkid_count); + if (pPmkid != NULL) { + CacheIdx = RTMPSearchPMKIDCache(pAd, + pEntry->func_tb_idx, + pEntry->Addr); + if ((CacheIdx == -1) || + ((RTMPEqualMemory(pPmkid, + &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].PMKIDCache.BSSIDInfo[CacheIdx].PMKID, + LEN_PMKID)) == 0)) { + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s: no OWE PMKID, do normal ECDH procedure\n", + __func__)); + need_process_ecdh_ie = TRUE; + } else { + store_pmkid_cache_in_entry(pAd, pEntry, CacheIdx); + need_update_grp_info = TRUE; + } + } else + need_process_ecdh_ie = TRUE; + + if (need_process_ecdh_ie == TRUE || (need_update_grp_info == TRUE)) { + ret = process_ecdh_element(pAd, + pEntry, + ecdh_ie, + ecdh_ie_length, + type, + need_update_grp_info); + } + return ret; +} +#endif + +/*parse from bssid field directly*/ +BOOLEAN extract_pair_owe_bss_info(UCHAR *owe_vendor_ie, + UCHAR owe_vendor_ie_len, + UCHAR *pair_bssid, + UCHAR *pair_ssid, + UCHAR *pair_ssid_len, + UCHAR *pair_band, + UCHAR *pair_ch) +{ + BOOLEAN ret = TRUE; + BOOLEAN has_band_ch_info = FALSE; + UCHAR local_ssid_len = *(owe_vendor_ie + MAC_ADDR_LEN); + UCHAR ssid_field_len = sizeof(UCHAR); + UCHAR at_least_length = local_ssid_len + MAC_ADDR_LEN + ssid_field_len; + UCHAR *pos = owe_vendor_ie; + + /*Sanity check length information*/ + if (owe_vendor_ie_len < (local_ssid_len + MAC_ADDR_LEN)) { + ret = FALSE; + goto end; + } else if (owe_vendor_ie_len > at_least_length) + has_band_ch_info = TRUE;/*remain length */ + + NdisMoveMemory(pair_bssid, pos, MAC_ADDR_LEN); + pos = pos + MAC_ADDR_LEN + ssid_field_len; + NdisMoveMemory(pair_ssid, pos, local_ssid_len); + + *pair_ssid_len = local_ssid_len; + + if (has_band_ch_info == TRUE) { + pos = pos + local_ssid_len;/*parse ch info field*/ + *pair_band = *pos; + /*TODO: sanity check of Operating Class and CH???? */ + pos = pos + sizeof(UCHAR); + *pair_ch = *pos; + } + +end: + return ret; +} + +#ifdef APCLI_OWE_SUPPORT +void wext_send_owe_trans_chan_event(PNET_DEV net_dev, + UCHAR event_id, + UCHAR *pair_bssid, + UCHAR *pair_ssid, + UCHAR *pair_ssid_len, + UCHAR *pair_band, + UCHAR *pair_ch) +{ + struct owe_trans_channel_change_info *owe_tran_ch_data = NULL; + struct owe_event *event_data = NULL; + UINT16 buflen = 0; + char *buf = NULL; + + + buflen = sizeof(struct owe_event) + sizeof(struct owe_trans_channel_change_info); + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + event_data = (struct owe_event *)buf; + event_data->event_id = event_id; + + event_data->event_len = sizeof(*owe_tran_ch_data); + owe_tran_ch_data = (struct owe_trans_channel_change_info *)event_data->event_body; + + NdisCopyMemory(owe_tran_ch_data->ifname, RtmpOsGetNetDevName(net_dev), IFNAMSIZ); + + if (pair_bssid) + memcpy(owe_tran_ch_data->pair_bssid, pair_bssid, 6); + if (pair_ssid) + memcpy(owe_tran_ch_data->pair_ssid, pair_ssid, *pair_ssid_len); + + if (pair_ssid_len) + owe_tran_ch_data->pair_ssid_len = *pair_ssid_len; + + if (pair_band && (*pair_band != 0)) + owe_tran_ch_data->pair_band = *pair_band; + + if (pair_ch && (*pair_ch != 0)) + owe_tran_ch_data->pair_ch = *pair_ch; + + + RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_OWE_TRANS_EVENT, NULL, (PUCHAR)buf, buflen); + os_free_mem(NULL, buf); +} + +#endif + + + +#endif /*CONFIG_OWE_SUPPORT*/ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/pmf.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/pmf.c new file mode 100644 index 000000000..e5a3b8c76 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/pmf.c @@ -0,0 +1,1797 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2006, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + Abstract: + IEEE P802.11w + +***************************************************************************/ + +#ifdef DOT11W_PMF_SUPPORT + +#include "rt_config.h" + +/* The definition in IEEE 802.11w - Table 7-32 Cipher suite selectors */ +UCHAR OUI_PMF_BIP_CIPHER[4]= {0x00, 0x0F, 0xAC, 0x06}; + +/* The definition in IEEE 802.11w - Table 7-34 AKM suite selectors */ +UCHAR OUI_PMF_8021X_AKM[4]= {0x00, 0x0F, 0xAC, 0x05}; +UCHAR OUI_PMF_PSK_AKM[4]= {0x00, 0x0F, 0xAC, 0x06}; + +UCHAR PMF_MMIE_BUFFER[18]= {0x4C, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +#define SAQ_IDLE 0 +#define SAQ_RETRY 1 +#define SAQ_SENDING 2 + +#ifdef CONFIG_SECURITY_IMPROVEMENT_SUPPORT +UCHAR OUI_PMF_BIP_CMAC_128_CIPHER[4] = {0x00, 0x0F, 0xAC, 0x06}; +UCHAR OUI_PMF_BIP_CMAC_256_CIPHER[4] = {0x00, 0x0F, 0xAC, 0x0d}; +UCHAR OUI_PMF_BIP_GMAC_128_CIPHER[4] = {0x00, 0x0F, 0xAC, 0x0b}; +UCHAR OUI_PMF_BIP_GMAC_256_CIPHER[4] = {0x00, 0x0F, 0xAC, 0x0c}; +#endif + + + +VOID PMF_PeerAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + DBGPRINT(RT_DEBUG_WARN, ("[PMF]%s : PMF_PeerAction Action=%d\n", __FUNCTION__, Action)); + switch (Action) { + case ACTION_SAQ_REQUEST: + PMF_PeerSAQueryReqAction(pAd, Elem); + break; + case ACTION_SAQ_RESPONSE: + PMF_PeerSAQueryRspAction(pAd, Elem); + break; + } +} + + +VOID PMF_MlmeSAQueryReq( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry) +{ + PUCHAR pOutBuffer = NULL; + HEADER_802_11 SAQReqHdr; + UINT32 FrameLen = 0; + UCHAR SACategoryType, SAActionType; + //UINT ccmp_len = LEN_CCMP_HDR + LEN_CCMP_MIC; + //UCHAR ccmp_buf[ccmp_len]; + PPMF_CFG pPmfCfg = NULL; + + if (!pEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Entry is NULL\n", __FUNCTION__)); + return; + } + + if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE))) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Entry is not PMF capable, STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pEntry->Addr))); + return; + } + + if (pEntry->SAQueryStatus == SAQ_SENDING) + return; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef APCLI_SUPPORT + if ((pEntry) && IS_ENTRY_APCLI(pEntry)) + pPmfCfg = &pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].PmfCfg; + else +#endif /* APCLI_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + pPmfCfg = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].PmfCfg; + } +#endif /* CONFIG_AP_SUPPORT */ + + if (pPmfCfg) + { + /* Send the SA Query Request */ + os_alloc_mem(NULL, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER); + if(pOutBuffer == NULL) + return; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef APCLI_SUPPORT + if ((pEntry) && IS_ENTRY_APCLI(pEntry)) { + ApCliMgtMacHeaderInit(pAd, + &SAQReqHdr, + SUBTYPE_ACTION, 0, + pEntry->Addr, + pEntry->Addr, + pEntry->func_tb_idx); + } else +#endif /* APCLI_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + { + MgtMacHeaderInit(pAd, &SAQReqHdr, SUBTYPE_ACTION, 0, pEntry->Addr, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid); + } + } +#endif /* CONFIG_AP_SUPPORT */ + + pEntry->TransactionID++; + + SACategoryType = CATEGORY_SA; + SAActionType = ACTION_SAQ_REQUEST; + MakeOutgoingFrame(pOutBuffer, (ULONG *) &FrameLen, + sizeof(HEADER_802_11), &SAQReqHdr, + 1, &SACategoryType, + 1, &SAActionType, + 2, &pEntry->TransactionID, + END_OF_ARGS); + + if (pEntry->SAQueryStatus == SAQ_IDLE) { + RTMPSetTimer(&pEntry->SAQueryTimer, 1000); /* 1000ms */ + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s -- SAQueryTimer\n", __FUNCTION__)); + } + + pEntry->SAQueryStatus = SAQ_SENDING; + RTMPSetTimer(&pEntry->SAQueryConfirmTimer, 200); /* 200ms */ + + /* transmit the frame */ + MiniportMMRequest(pAd, QID_MGMT, pOutBuffer, FrameLen); + os_free_mem(NULL, pOutBuffer); + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s - Send SA Query Request to STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", + __FUNCTION__, PRINT_MAC(pEntry->Addr))); + } +} + + +VOID PMF_PeerSAQueryReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + if (Action == ACTION_SAQ_REQUEST) + { + PMAC_TABLE_ENTRY pEntry; + PFRAME_802_11 pHeader; + USHORT TransactionID; + PUCHAR pOutBuffer = NULL; + HEADER_802_11 SAQRspHdr; + UINT32 FrameLen = 0; + UCHAR SACategoryType, SAActionType; + //UINT ccmp_len = LEN_CCMP_HDR + LEN_CCMP_MIC; + //UCHAR ccmp_buf[ccmp_len]; + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Receive SA Query Request\n", __FUNCTION__)); + pHeader = (PFRAME_802_11) Elem->Msg; + + pEntry = MacTableLookup(pAd, pHeader->Hdr.Addr2); + + if (!pEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Entry is not found, STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pHeader->Hdr.Addr2))); + return; + } + + if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE))) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Entry is not PMF capable, STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pHeader->Hdr.Addr2))); + return; + } + + NdisMoveMemory(&TransactionID, &Elem->Msg[LENGTH_802_11+2], sizeof(USHORT)); + + /* Response the SA Query */ + os_alloc_mem(NULL, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER); + if(pOutBuffer == NULL) + return; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef APCLI_SUPPORT + if (pEntry && IS_ENTRY_APCLI(pEntry)) { + ApCliMgtMacHeaderInit(pAd, &SAQRspHdr, + SUBTYPE_ACTION, 0, + pHeader->Hdr.Addr2, + pHeader->Hdr.Addr2, + pEntry->func_tb_idx); + } else +#endif /* APCLI_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + { + MgtMacHeaderInit(pAd, &SAQRspHdr, SUBTYPE_ACTION, 0, pHeader->Hdr.Addr2, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid); + } + } +#endif /* CONFIG_AP_SUPPORT */ + + SACategoryType = CATEGORY_SA; + SAActionType = ACTION_SAQ_RESPONSE; + MakeOutgoingFrame(pOutBuffer, (ULONG *) &FrameLen, + sizeof(HEADER_802_11), &SAQRspHdr, + 1, &SACategoryType, + 1, &SAActionType, + 2, &TransactionID, + END_OF_ARGS); + + /* transmit the frame */ + MiniportMMRequest(pAd, QID_MGMT, pOutBuffer, FrameLen); + os_free_mem(NULL, pOutBuffer); + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s - Send SA Query Response to STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(SAQRspHdr.Addr1))); + } +} + + +VOID PMF_PeerSAQueryRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + if (Action == ACTION_SAQ_RESPONSE) + { + PMAC_TABLE_ENTRY pEntry; + PFRAME_802_11 pHeader; + USHORT TransactionID; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Receive SA Query Response\n", __FUNCTION__)); + + pHeader = (PFRAME_802_11) Elem->Msg; + + pEntry = MacTableLookup(pAd, pHeader->Hdr.Addr2); + + if (!pEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Entry is not found, STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pHeader->Hdr.Addr2))); + return; + } + + if (!(CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE))) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Entry is not PMF capable, STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pHeader->Hdr.Addr2))); + return; + } + + NdisMoveMemory(&TransactionID, &Elem->Msg[LENGTH_802_11+2], sizeof(USHORT)); + + if (pEntry->TransactionID == TransactionID) + { + pEntry->SAQueryStatus = SAQ_IDLE; + RTMPCancelTimer(&pEntry->SAQueryTimer, &Cancelled); + RTMPCancelTimer(&pEntry->SAQueryConfirmTimer, &Cancelled); + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s - Compare TransactionID correctly, STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pHeader->Hdr.Addr2))); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s - Compare TransactionID wrong, STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pHeader->Hdr.Addr2))); + } + } +} + + +VOID PMF_SAQueryTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY *)FunctionContext; + +#ifdef APCLI_DOT11W_PMF_SUPPORT + USHORT ifIndex = 0; +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + if (pEntry) + { + RTMP_ADAPTER *pAd = (RTMP_ADAPTER*)pEntry->pAd; + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s - STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", + __FUNCTION__, PRINT_MAC(pEntry->Addr))); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) { + BOOLEAN Cancelled; + MLME_DISASSOC_REQ_STRUCT DisassocReq; + PULONG pCurrState = NULL; + + RTMPCancelTimer(&pEntry->SAQueryTimer, &Cancelled); + RTMPCancelTimer(&pEntry->SAQueryConfirmTimer, &Cancelled); + DisassocParmFill(pAd, &DisassocReq, + pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].MlmeAux.Bssid, + REASON_DISASSOC_STA_LEAVING); + + pCurrState = &pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].CtrlCurrState; + ifIndex = pEntry->func_tb_idx; + + *pCurrState = APCLI_CTRL_DEASSOC; + + MlmeEnqueue(pAd, APCLI_ASSOC_STATE_MACHINE, + APCLI_MT2_MLME_DISASSOC_REQ, + sizeof(MLME_DISASSOC_REQ_STRUCT), + &DisassocReq, ifIndex); + + RTMP_MLME_HANDLER(pAd); + } else +#endif /* APCLI_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + MacTableDeleteEntry(pAd, pEntry->wcid, pEntry->Addr); + } +#endif /* CONFIG_AP_SUPPORT */ + } +} + + +VOID PMF_SAQueryConfirmTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + MAC_TABLE_ENTRY *pEntry = (MAC_TABLE_ENTRY *)FunctionContext; + + if (pEntry) + { + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pEntry->pAd; + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s - STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", __FUNCTION__, PRINT_MAC(pEntry->Addr))); + pEntry->SAQueryStatus = SAQ_RETRY; + PMF_MlmeSAQueryReq(pAd, pEntry); + } +} + + +VOID PMF_ConstructBIPAad( + IN PUCHAR pHdr, + OUT UCHAR *aad_hdr) +{ + UINT8 aad_len = 0; + + /* Frame control - + Retry bit (bit 11) masked to 0 + PwrMgt bit (bit 12) masked to 0 + MoreData bit (bit 13) masked to 0 */ + aad_hdr[0] = (*pHdr); + aad_hdr[1] = (*(pHdr + 1)) & 0xc7; + aad_len = 2; + + /* Append Addr 1, 2 & 3 */ + NdisMoveMemory(&aad_hdr[aad_len], pHdr + 4, 3 * MAC_ADDR_LEN); + aad_len += (3 * MAC_ADDR_LEN); +} + + +BOOLEAN PMF_CalculateBIPMIC( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAadHdr, + IN PUCHAR pFrameBuf, + IN UINT32 FrameLen, + IN PUCHAR pKey, + OUT PUCHAR pBipMic) +{ + UCHAR *m_buf; + UINT32 total_len; + UCHAR cmac_output[16]; + UINT mlen = AES_KEY128_LENGTH; + + /* Allocate memory for MIC calculation */ + os_alloc_mem(NULL, (PUCHAR *)&m_buf, MGMT_DMA_BUFFER_SIZE); + if (m_buf == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : out of resource.\n", __FUNCTION__)); + return FALSE; + } + + /* Initialize the buffer */ + NdisZeroMemory(m_buf, MGMT_DMA_BUFFER_SIZE); + + /* Construct the concatenation */ + NdisMoveMemory(m_buf, pAadHdr, LEN_PMF_BIP_AAD_HDR); + total_len = LEN_PMF_BIP_AAD_HDR; + + /* Append the Mgmt frame into the concatenation */ + NdisMoveMemory(&m_buf[total_len], pFrameBuf, FrameLen); + total_len += FrameLen; + + /* Compute AES-128-CMAC over the concatenation */ + AES_CMAC(m_buf, total_len, pKey, 16, cmac_output, &mlen); + + /* Truncate the first 64-bits */ + NdisMoveMemory(pBipMic, cmac_output, LEN_PMF_BIP_MIC); + + os_free_mem(NULL, m_buf); + + return TRUE; + +} + + +VOID PMF_DerivePTK( + IN PRTMP_ADAPTER pAd, + IN UCHAR *PMK, + IN UCHAR *ANonce, + IN UCHAR *AA, + IN UCHAR *SNonce, + IN UCHAR *SA, + OUT UCHAR *output, + IN UINT len) +{ + UCHAR concatenation[76]; + UINT CurrPos = 0; + UCHAR temp[32]; + UCHAR Prefix[] = {'P', 'a', 'i', 'r', 'w', 'i', 's', 'e', ' ', 'k', 'e', 'y', ' ', + 'e', 'x', 'p', 'a', 'n', 's', 'i', 'o', 'n'}; + + /* initiate the concatenation input */ + NdisZeroMemory(temp, sizeof(temp)); + NdisZeroMemory(concatenation, 76); + + /* Get smaller address */ + if (RTMPCompareMemory(SA, AA, 6) == 1) + NdisMoveMemory(concatenation, AA, 6); + else + NdisMoveMemory(concatenation, SA, 6); + CurrPos += 6; + + /* Get larger address */ + if (RTMPCompareMemory(SA, AA, 6) == 1) + NdisMoveMemory(&concatenation[CurrPos], SA, 6); + else + NdisMoveMemory(&concatenation[CurrPos], AA, 6); + + /* store the larger mac address for backward compatible of + ralink proprietary STA-key issue */ + NdisMoveMemory(temp, &concatenation[CurrPos], MAC_ADDR_LEN); + CurrPos += 6; + + /* Get smaller Nonce */ + if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) + NdisMoveMemory(&concatenation[CurrPos], temp, 32); + else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) + NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); + else + NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); + CurrPos += 32; + + /* Get larger Nonce */ + if (RTMPCompareMemory(ANonce, SNonce, 32) == 0) + NdisMoveMemory(&concatenation[CurrPos], temp, 32); + else if (RTMPCompareMemory(ANonce, SNonce, 32) == 1) + NdisMoveMemory(&concatenation[CurrPos], ANonce, 32); + else + NdisMoveMemory(&concatenation[CurrPos], SNonce, 32); + CurrPos += 32; + + hex_dump("[PMF]PMK", PMK, LEN_PMK); + hex_dump("[PMF]concatenation=", concatenation, 76); + + /* Calculate a key material through FT-KDF */ + KDF(PMK, LEN_PMK, Prefix, 22, concatenation, 76, output, len); +} + + +/* + ======================================================================== + + Routine Description: + Derive IGTK randomly + IGTK, a hierarchy consisting of a single key to provide integrity + protection for broadcast and multicast Robust Management frames + + Arguments: + + Return Value: + + Note: + It's defined in IEEE 802.11w 8.5.1.3a + + ======================================================================== +*/ +VOID PMF_DeriveIGTK( + IN PRTMP_ADAPTER pAd, + OUT UCHAR *output) +{ + INT i; + + for(i = 0; i < LEN_TK; i++) + output[i] = RandomByte(pAd); +} + + +/* + ======================================================================== + + Routine Description: + Insert IGTK KDE. The field shall be included in pair-Msg3-WPA2 and + group-Msg1-WPA2. + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +VOID PMF_InsertIGTKKDE( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + PPMF_IGTK_KDE igtk_kde_ptr; + UINT8 idx = 0; + PPMF_CFG pPmfCfg = NULL; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + pPmfCfg = &pAd->ApCfg.MBSSID[apidx].PmfCfg; +#endif /* CONFIG_AP_SUPPORT */ + + if (!pPmfCfg) + return; + + /* Construct the common KDE format */ + WPA_ConstructKdeHdr(KDE_IGTK, LEN_PMF_IGTK_KDE, pFrameBuf); + + /* Prepare the IGTK KDE */ + igtk_kde_ptr = (PPMF_IGTK_KDE)(pFrameBuf + LEN_KDE_HDR); + NdisZeroMemory(igtk_kde_ptr, LEN_PMF_IGTK_KDE); + + /* Bits 0-11 define a value in the range 0-4095. + Bits 12 - 15 are reserved and set to 0 on transmission and ignored on reception. + The IGTK Key ID is either 4 or 5. The remaining Key IDs are reserved. */ + igtk_kde_ptr->KeyID[0] = pPmfCfg->IGTK_KeyIdx; + idx = (pPmfCfg->IGTK_KeyIdx == 5) ? 1 : 0; + + /* Fill in the IPN field */ + NdisMoveMemory(igtk_kde_ptr->IPN, &pPmfCfg->IPN[idx][0], LEN_WPA_TSC); + + /* Fill uin the IGTK field */ + NdisMoveMemory(igtk_kde_ptr->IGTK, &pPmfCfg->IGTK[idx][0], LEN_AES_GTK); + + /* Update the total output length */ + *pFrameLen = *pFrameLen + LEN_KDE_HDR + LEN_PMF_IGTK_KDE; + + return; +} + + +/* + ======================================================================== + + Routine Description: + Extract IGTK KDE. + + Arguments: + + Return Value: + + Note: + + ======================================================================== +*/ +#ifndef APCLI_DOT11W_PMF_SUPPORT +BOOLEAN PMF_ExtractIGTKKDE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBuf, + IN INT buf_len) +{ + return FALSE; +} +#else +BOOLEAN PMF_ExtractIGTKKDE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBuf, + IN INT buf_len + , IN MAC_TABLE_ENTRY *pEntry + ) +{ + PPMF_IGTK_KDE igtk_kde_ptr; + UINT8 idx = 0; + UINT8 offset = 0; + PPMF_CFG pPmfCfg = NULL; +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + pPmfCfg = &pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].PmfCfg; +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + + if (pPmfCfg == NULL) + return FALSE; + + igtk_kde_ptr = (PPMF_IGTK_KDE) pBuf; + pPmfCfg->IGTK_KeyIdx = igtk_kde_ptr->KeyID[0]; + if (pPmfCfg->IGTK_KeyIdx == 5) + idx = 1; + offset += 2; + + NdisMoveMemory(&pPmfCfg->IPN[idx][0], igtk_kde_ptr->IPN, LEN_WPA_TSC); + offset += LEN_WPA_TSC; + + if ((buf_len - offset) == LEN_AES_GTK) { + NdisMoveMemory(&pPmfCfg->IGTK[idx][0], igtk_kde_ptr->IGTK, LEN_AES_GTK); + } else { + DBGPRINT(RT_DEBUG_ERROR, ("%s : the IGTK length(%d) is invalid\n", + __func__, (buf_len - offset))); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s : IGTK_Key_ID=%d\n", + __func__, pPmfCfg->IGTK_KeyIdx)); + return TRUE; +} +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + + +/* + ======================================================================== + + Routine Description: + Build Group Management Cipher in RSN-IE. + It only shall be called by RTMPMakeRSNIE. + + Arguments: + pAd - pointer to our pAdapter context + ElementID - indicate the WPA1 or WPA2 + apidx - indicate the interface index + + Return Value: + + Note: + + ======================================================================== +*/ +VOID PMF_MakeRsnIeGMgmtCipher( + IN PRTMP_ADAPTER pAd, + IN UCHAR ElementID, + IN UCHAR apidx, + OUT PUCHAR pRsnIe, + OUT UCHAR *rsn_len) +{ + PUINT8 pBuf; + BOOLEAN MFP_Enabled = FALSE; + + /* it could be ignored in WPA1 mode */ + if (ElementID == WpaIe) + return; + + pBuf = (pRsnIe + (*rsn_len)); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef APCLI_SUPPORT + if (apidx >= MIN_NET_DEVICE_FOR_APCLI) { + PAPCLI_STRUCT pApCliEntry = &pAd->ApCfg.ApCliTab[apidx - MIN_NET_DEVICE_FOR_APCLI]; + + MFP_Enabled = pApCliEntry->PmfCfg.MFPC; + } else +#endif /* APCLI_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + if (apidx < pAd->ApCfg.BssidNum) + { + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; + + MFP_Enabled = pMbss->PmfCfg.MFPC; + } + } +#endif /* CONFIG_AP_SUPPORT */ + + /* default group management cipher suite in an RSNA with + Management Frame Protection enabled. */ + if (MFP_Enabled) + { + NdisMoveMemory(pBuf, OUI_PMF_BIP_CIPHER, LEN_OUI_SUITE); + (*rsn_len) += sizeof(LEN_OUI_SUITE); + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: Insert BIP to the group management cipher of RSNIE\n", __FUNCTION__)); + } +} + + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +NTSTATUS PMF_RsnCapableValidation( + IN PRTMP_ADAPTER pAd, + IN PUINT8 pRsnie, + IN UINT rsnie_len, + IN BOOLEAN self_MFPC, + IN BOOLEAN self_MFPR, +#ifdef CONFIG_SECURITY_IMPROVEMENT_SUPPORT + IN UCHAR end_field, +#endif +#ifdef CONFIG_OWE_SUPPORT + IN INT apidx, +#endif + IN PMAC_TABLE_ENTRY pEntry) +{ + UINT8 count; + PUINT8 pBuf = NULL; + BOOLEAN peer_MFPC = FALSE, peer_MFPR = FALSE; + + /* Check the peer's MPFC and MPFR - + Refer to Table 8-1a, IEEE 802.11W to check the PMF policy */ + if ((pBuf = WPA_ExtractSuiteFromRSNIE(pRsnie, rsnie_len, RSN_CAP_INFO, &count)) == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : Peer's MPFC isn't used.\n", __FUNCTION__)); + if (self_MFPR) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : PMF policy violation.\n", __FUNCTION__)); + return PMF_POLICY_VIOLATION; + } + } + else + { + RSN_CAPABILITIES RsnCap; + + NdisMoveMemory(&RsnCap, pBuf, sizeof(RSN_CAPABILITIES)); + RsnCap.word = cpu2le16(RsnCap.word); + + peer_MFPC = RsnCap.field.MFPC; + peer_MFPR = RsnCap.field.MFPR; + + if ((self_MFPC == TRUE) && (peer_MFPC == FALSE )) + { + if ((self_MFPR == TRUE) && (peer_MFPR == FALSE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : PMF policy violation for case 4\n", __FUNCTION__)); + return PMF_POLICY_VIOLATION; + } + + if (peer_MFPR == TRUE) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : PMF policy violation for case 7\n", __FUNCTION__)); + return PMF_POLICY_VIOLATION; + } + } + + if ((self_MFPC == TRUE) && (peer_MFPC == TRUE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: PMF Connection \n", __FUNCTION__)); + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE); + } + +#ifdef CONFIG_OWE_SUPPORT + if (pEntry->AuthMode == Ndis802_11AuthModeOWE) { + pAd->ApCfg.MBSSID[apidx].PmfCfg.MFPC = TRUE; + pAd->ApCfg.MBSSID[apidx].PmfCfg.MFPR = TRUE; + } +#endif + +#ifdef DOT11_SAE_SUPPORT + if (pEntry->AuthMode == Ndis802_11AuthModeWPA3PSK && (peer_MFPC == FALSE)) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_PMF, DBG_LVL_ERROR, + ("[PMF]%s: SAE connection fail due to not PMF connection(peer MFPR = %d, MFPC = %d)\n", + __func__, peer_MFPR, peer_MFPC)); + return PMF_POLICY_VIOLATION; + } +#endif + } + /* SHA1 or SHA256 */ + if ((self_MFPC == TRUE) + && (pBuf = WPA_ExtractSuiteFromRSNIE(pRsnie, rsnie_len, AKM_SUITE, &count)) != NULL) + { + UCHAR OUI_WPA2_1X_SHA256[4] = {0x00, 0x0F, 0xAC, 0x05}; + UCHAR OUI_WPA2_PSK_SHA256[4] = {0x00, 0x0F, 0xAC, 0x06}; +#ifdef DOT11_SAE_SUPPORT + UCHAR OUI_WPA2_SAE_SHA256[4] = {0x00, 0x0F, 0xAC, 0x08}; +#endif + while (count > 0) + { + if (RTMPEqualMemory(pBuf, OUI_WPA2_1X_SHA256, 4) || + RTMPEqualMemory(pBuf, OUI_WPA2_PSK_SHA256, 4) +#ifdef DOT11_SAE_SUPPORT + || RTMPEqualMemory(pBuf, OUI_WPA2_SAE_SHA256, 4) + +#endif + ) { +#ifdef DOT11_SAE_SUPPORT + pEntry->key_deri_alg = SEC_KEY_DERI_SHA256; +#endif + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_USE_SHA256); + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : SHA256 Support\n", __FUNCTION__)); + } + pBuf += 4; + count--; + } + } + +#ifdef CONFIG_SECURITY_IMPROVEMENT_SUPPORT + /* Group Management Cipher Suite */ + if ((self_MFPC == TRUE) && (peer_MFPC == TRUE)) { + if (end_field < RSN_FIELD_GROUP_MGMT_CIPHER) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_PMF, DBG_LVL_ERROR, + ("[PMF]%s : Use default Group_mgmt_cipher_suite\n", __func__)); + return PMF_STATUS_SUCCESS; + } + + pBuf = WPA_ExtractSuiteFromRSNIE(pRsnie, rsnie_len, G_MGMT_SUITE, &count); + + if (pBuf == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_PMF, DBG_LVL_ERROR, + ("[PMF]%s : The peer RSNIE doesn't include Group_mgmt_cipher_suite\n", __func__)); + return PMF_POLICY_VIOLATION; + } + + if (RTMPEqualMemory(pBuf, OUI_PMF_BIP_CMAC_128_CIPHER, LEN_OUI_SUITE)) { + return PMF_STATUS_SUCCESS; + } else if (RTMPEqualMemory(pBuf, OUI_PMF_BIP_CMAC_256_CIPHER, LEN_OUI_SUITE)) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_PMF, DBG_LVL_ERROR, + ("[PMF]%s : Not support BIP_CMAC_256\n", __func__)); + return PMF_POLICY_VIOLATION; + } else if (RTMPEqualMemory(pBuf, OUI_PMF_BIP_GMAC_128_CIPHER, LEN_OUI_SUITE)) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_PMF, DBG_LVL_ERROR, + ("[PMF]%s : Not support BIP_GMAC_128\n", __func__)); + return PMF_POLICY_VIOLATION; + } else if (RTMPEqualMemory(pBuf, OUI_PMF_BIP_GMAC_256_CIPHER, LEN_OUI_SUITE)) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_PMF, DBG_LVL_ERROR, + ("[PMF]%s : Not support BIP_GMAC_256\n", __func__)); + return PMF_POLICY_VIOLATION; + } + MTWF_LOG(DBG_CAT_SEC, CATSEC_PMF, DBG_LVL_ERROR, + ("[PMF]%s : unknown peer Group_mgmt_cipher_suite\n", __func__)); + hex_dump("peer Group_mgmt_cipher_suite", pBuf, LEN_OUI_SUITE); + return PMF_POLICY_VIOLATION; + } + +#endif + + return PMF_STATUS_SUCCESS; +} + + +/* +======================================================================== +Routine Description: + Decide if the frame is PMF Robust frame + +Arguments: + pHdr : pointer to the 802.11 header + pFrame : point to frame body. It exclude the 802.11 header + frame_len : the frame length without 802.11 header + +Return Value: + NOT_ROBUST_FRAME + UNICAST_ROBUST_FRAME + GROUP_ROBUST_FRAME + +Note: + +======================================================================== +*/ +INT PMF_RobustFrameClassify( + IN PHEADER_802_11 pHdr, + IN PUCHAR pFrame, + IN UINT frame_len, + IN PUCHAR pData, + IN BOOLEAN IsRx) +{ + PMAC_TABLE_ENTRY pEntry = (PMAC_TABLE_ENTRY)pData; + + if ((pHdr->FC.Type != FC_TYPE_MGMT) || (frame_len <= 0)) + return NORMAL_FRAME; + + /* Classify the frame */ + switch (pHdr->FC.SubType) + { + case SUBTYPE_DISASSOC: + case SUBTYPE_DEAUTH: + break; + case SUBTYPE_ACTION: + { + if ((IsRx == FALSE) + || (IsRx && (pHdr->FC.Wep == 0))) + { + UCHAR Category = (UCHAR) (pHdr->Octet[0]); + + switch (Category) + { + /* Refer to IEEE 802.11w Table7-24 */ + case CATEGORY_SPECTRUM: + case CATEGORY_QOS: + case CATEGORY_DLS: + case CATEGORY_BA: + case CATEGORY_RM: + case CATEGORY_FT: + case CATEGORY_SA: + case CATEGORY_PD: + case CATEGORY_VSP: + case CATEGORY_WNM: + break; + default: + return NORMAL_FRAME; + } + } + break; + } + default: + return NORMAL_FRAME; + } + + if (pHdr->Addr1[0] & 0x01) /* Broadcast frame */ + { + UINT8 offset_mmie; + + if (frame_len <= (LEN_PMF_MMIE + 2)) + return NOT_ROBUST_GROUP_FRAME; + + /* The offset of MMIE */ + offset_mmie = frame_len - (LEN_PMF_MMIE + 2); + + /* check if this is a group Robust frame */ + if (((*(pFrame + offset_mmie)) == IE_PMF_MMIE) && + ((*(pFrame + offset_mmie + 1)) == LEN_PMF_MMIE)) + return GROUP_ROBUST_FRAME; + else + return NOT_ROBUST_GROUP_FRAME; + } + + /* Unicast frame */ + else if (pEntry == NULL) + return NORMAL_FRAME; + else if (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE)) + return NORMAL_FRAME; + else if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE) && (pHdr->FC.Wep == 0) && (IsRx == TRUE)) + return NOT_ROBUST_UNICAST_FRAME; + else if (((IsRx == TRUE) && (pHdr->FC.Wep == 1)) || (IsRx == FALSE)) + return UNICAST_ROBUST_FRAME; + + return ERROR_FRAME; +} + + +INT PMF_EncryptUniRobustFrameAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMgmtFrame, + IN UINT mgmt_len) +{ + PMAC_TABLE_ENTRY pEntry = NULL; + PHEADER_802_11 pHdr = (PHEADER_802_11)pMgmtFrame; + INT data_len; + PUCHAR pBuf; + INT Status; + + /* Check if the length is valid */ + data_len = mgmt_len - (LENGTH_802_11 + LEN_CCMP_HDR + LEN_CCMP_MIC); + if (data_len <= 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The payload length(%d) is invalid\n", + __FUNCTION__, data_len)); + return PMF_UNICAST_ENCRYPT_FAILURE; + } + + /* Look up the entry through Address 1 of 802.11 header */ + pEntry = MacTableLookup(pAd, pHdr->Addr1); + + if (pEntry == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The entry doesn't exist\n", __FUNCTION__)); + return PMF_UNICAST_ENCRYPT_FAILURE; + } + + /* check the PMF capable for this entry */ + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE) == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR,("%s : the entry no PMF capable !\n", __FUNCTION__)); + return PMF_UNICAST_ENCRYPT_FAILURE; + } + + /* Allocate a buffer for building PMF packet */ + Status = MlmeAllocateMemory(pAd, &pBuf); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR,("%s : allocate PMF buffer fail!\n", __FUNCTION__)); + return PMF_UNICAST_ENCRYPT_FAILURE; + } + + /* Construct and insert 8-bytes CCMP header to MPDU header */ + RTMPConstructCCMPHdr(0, pEntry->PmfTxTsc, pBuf); + + NdisMoveMemory(pBuf + LEN_CCMP_HDR, + &pHdr->Octet[0], + data_len); + + // Encrypt the MPDU data by software + RTMPSoftEncryptCCMP(pAd, + (PUCHAR)pHdr, + pEntry->PmfTxTsc, + pEntry->PairwiseKey.Key, + pBuf + LEN_CCMP_HDR, + data_len); + + data_len += (LEN_CCMP_HDR + LEN_CCMP_MIC); + NdisMoveMemory(&pHdr->Octet[0], pBuf, data_len); + + /* TSC increment for next transmittion */ + INC_TX_TSC(pEntry->PmfTxTsc, LEN_WPA_TSC); + + MlmeFreeMemory(pAd, pBuf); + + return PMF_STATUS_SUCCESS; + +} + +INT PMF_DecryptUniRobustFrameAction( + IN PRTMP_ADAPTER pAd, + INOUT PUCHAR pMgmtFrame, + IN UINT mgmt_len) +{ + PMAC_TABLE_ENTRY pEntry = NULL; + PHEADER_802_11 pHeader = (PHEADER_802_11)pMgmtFrame; + PUCHAR pDate = pMgmtFrame + LENGTH_802_11; + UINT16 data_len = mgmt_len - LENGTH_802_11; + + /* Check if the length is valid */ + if (data_len <= LEN_CCMP_HDR + LEN_CCMP_MIC) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The payload length(%d) is invalid\n", + __FUNCTION__, data_len)); + return PMF_UNICAST_DECRYPT_FAILURE; + } + + /* Look up the entry through Address 2 of 802.11 header */ + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + if (pEntry == NULL) + { + DBGPRINT(RT_DEBUG_ERROR,("%s : the entry doesn't exist !\n", __FUNCTION__)); + return PMF_STATUS_SUCCESS; + } + + /* check the PMF capable for this entry */ + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE) == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR,("%s : the entry no PMF capable !\n", __FUNCTION__)); + return PMF_UNICAST_DECRYPT_FAILURE; + } + + if (RTMPSoftDecryptCCMP(pAd, + pMgmtFrame, + &pEntry->PairwiseKey, + pDate, + &data_len) == FALSE) + { + return PMF_UNICAST_DECRYPT_FAILURE; + } + + return PMF_STATUS_SUCCESS; +} + + +INT PMF_EncapBIPAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMgmtFrame, + IN UINT mgmt_len) +{ + PHEADER_802_11 pHdr = (PHEADER_802_11)pMgmtFrame; + PPMF_CFG pPmfCfg = NULL; + PPMF_MMIE pMMIE; + INT idx = 0; + PUCHAR pKey = NULL; + UCHAR aad_hdr[LEN_PMF_BIP_AAD_HDR]; + UCHAR BIP_MIC[LEN_PMF_BIP_MIC]; + PUCHAR pFrameBody = &pHdr->Octet[0]; + UINT32 body_len = mgmt_len - LENGTH_802_11; +#ifdef RT_BIG_ENDIAN + PUCHAR pMacHdr = NULL; + BOOLEAN bSwaped = FALSE; +#endif + /* Sanity check the total frame body length */ + if (body_len <= (2 + LEN_PMF_MMIE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : the total length(%d) is too short\n", + __FUNCTION__, body_len)); + return PMF_ENCAP_BIP_FAILURE; + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + pPmfCfg = &pAd->ApCfg.MBSSID[MAIN_MBSSID].PmfCfg; + } +#endif /* CONFIG_AP_SUPPORT */ + + /* Sanity check */ + if (pPmfCfg == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : No related PMF configuation\n", __FUNCTION__)); + return PMF_ENCAP_BIP_FAILURE; + } + + if (pPmfCfg && pPmfCfg->MFPC == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s : PMF is disabled \n", __FUNCTION__)); + return PMF_ENCAP_BIP_FAILURE; + } + + /* Pointer to the position of MMIE */ + pMMIE = (PPMF_MMIE)(pMgmtFrame + (mgmt_len - LEN_PMF_MMIE)); + + /* Select the IGTK currently active for transmission of frames to + the intended group of recipients and construct the MMIE (see 7.3.2.55) + with the MIC field masked to zero and the KeyID field set to the + corresponding IGTK KeyID value. */ + if (pPmfCfg->IGTK_KeyIdx == 5) + idx = 1; + pKey = &pPmfCfg->IGTK[idx][0]; + + NdisZeroMemory(pMMIE, LEN_PMF_MMIE); + + /* Bits 0-11 define a value in the range 0-4095. + Bits 12 - 15 are reserved and set to 0 on transmission and ignored on reception. + The IGTK Key ID is either 4 or 5. The remaining Key IDs are reserved. */ + pMMIE->KeyID[0] = pPmfCfg->IGTK_KeyIdx; + NdisMoveMemory(pMMIE->IPN, &pPmfCfg->IPN[idx][0], LEN_WPA_TSC); + + /* The transmitter shall insert a monotonically increasing non-neg- + ative integer into the MMIE IPN field. */ + INC_TX_TSC(pPmfCfg->IPN[idx], LEN_WPA_TSC); + + /* Compute AAD */ +#ifdef RT_BIG_ENDIAN + if (pHdr->FC.SubType == SUBTYPE_DISASSOC || pHdr->FC.SubType == SUBTYPE_DEAUTH) + { + pMacHdr = (PUCHAR) pHdr; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); //swap frame-control + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); //swap reason code + bSwaped= TRUE; + } +#endif + + PMF_ConstructBIPAad((PUCHAR)pHdr, aad_hdr); + + /* Calculate BIP MIC */ + PMF_CalculateBIPMIC(pAd, aad_hdr, pFrameBody, body_len, pKey, BIP_MIC); + + /* Fill into the MMIE MIC field */ + NdisMoveMemory(pMMIE->MIC, BIP_MIC, LEN_PMF_BIP_MIC); + +#ifdef RT_BIG_ENDIAN + if (bSwaped) + { + pMacHdr = (PUCHAR) pHdr; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + } +#endif + + /* BIP doesn't need encrypt frame */ + pHdr->FC.Wep = 0; + + return PMF_STATUS_SUCCESS; +} + +INT PMF_ExtractBIPAction( + IN PRTMP_ADAPTER pAd, + INOUT PUCHAR pMgmtFrame, + IN UINT mgmt_len) +{ + PPMF_CFG pPmfCfg = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + PHEADER_802_11 pHeader = (PHEADER_802_11)pMgmtFrame; + PPMF_MMIE pMMIE; + INT idx = 0; + PUCHAR pKey = NULL; + UCHAR aad_hdr[LEN_PMF_BIP_AAD_HDR]; + UCHAR rcvd_mic[LEN_PMF_BIP_MIC]; + UCHAR cal_mic[LEN_PMF_BIP_MIC]; + UINT32 body_len = mgmt_len - LENGTH_802_11; + + /* Sanity check the total frame body length */ + if (body_len <= (2 + LEN_PMF_MMIE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : the total length(%d) is too short\n", + __FUNCTION__, body_len)); + return PMF_EXTRACT_BIP_FAILURE; + } + + /* Look up the entry through Address 2 of 802.11 header */ + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + if (pEntry == NULL) + { + DBGPRINT(RT_DEBUG_ERROR,("%s : the entry doesn't exist !\n", __FUNCTION__)); + return PMF_STATUS_SUCCESS; + } + + /* check the PMF capable for this entry */ + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE) == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR,("%s : the entry no PMF capable !\n", __FUNCTION__)); + return PMF_EXTRACT_BIP_FAILURE; + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef APCLI_SUPPORT + if (IS_ENTRY_APCLI(pEntry)) + pPmfCfg = &pAd->ApCfg.ApCliTab[pEntry->func_tb_idx].PmfCfg; + else +#endif /* APCLI_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + pPmfCfg = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].PmfCfg; + } +#endif // CONFIG_AP_SUPPORT // + + + /* Pointer to the position of MMIE */ + pMMIE = (PPMF_MMIE)(pMgmtFrame + (mgmt_len - LEN_PMF_MMIE)); + + /* Select the IGTK currently active for transmission of frames to + the intended group of recipients and construct the MMIE (see 7.3.2.55) + with the MIC field masked to zero and the KeyID field set to the + corresponding IGTK KeyID value. */ + if (pMMIE->KeyID[0] == 5) + idx = 1; + pKey = &pPmfCfg->IGTK[idx][0]; + + /* store the MIC value of the received frame */ + NdisMoveMemory(rcvd_mic, pMMIE->MIC, LEN_PMF_BIP_MIC); + NdisZeroMemory(pMMIE->MIC, LEN_PMF_BIP_MIC); + + /* Compute AAD */ + PMF_ConstructBIPAad((PUCHAR)pMgmtFrame, aad_hdr); + + /* Calculate BIP MIC */ + PMF_CalculateBIPMIC(pAd, aad_hdr, + pMgmtFrame + LENGTH_802_11, + body_len, pKey, cal_mic); + + if (!NdisEqualMemory(rcvd_mic, cal_mic, LEN_PMF_BIP_MIC)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : MIC Different !\n", __FUNCTION__)); + return PMF_EXTRACT_BIP_FAILURE; + } + + return PMF_STATUS_SUCCESS; +} + + +BOOLEAN PMF_PerformTxFrameAction( + IN PRTMP_ADAPTER pAd, + OUT PNDIS_PACKET pPacket) +{ + PHEADER_802_11 pHeader_802_11; + PACKET_INFO PacketInfo; + PUCHAR pSrcBufVA; + UINT SrcBufLen; +#if !defined(MT7603) && !defined(MT7628) + UINT8 TXWISize = pAd->chipCap.TXWISize; +#endif + UINT8 tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len; + INT FrameType; + INT ret = 0; + PMAC_TABLE_ENTRY pEntry = NULL; + + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + if (pSrcBufVA == NULL) + return NORMAL_FRAME; + + // TODO: shiang-7603 + pHeader_802_11 = (HEADER_802_11 *) (pSrcBufVA + tx_hw_hdr_len); + + pEntry = MacTableLookup(pAd, pHeader_802_11->Addr1); + + if(pEntry == NULL) + return TRUE; + + if (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE)) + return TRUE; + + FrameType = PMF_RobustFrameClassify( + (PHEADER_802_11)pHeader_802_11, + (PUCHAR)(pHeader_802_11 + LENGTH_802_11), + (SrcBufLen - LENGTH_802_11), + (PUCHAR) pEntry, + FALSE); + + switch (FrameType) + { + case ERROR_FRAME: + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: ERROR FRAME\n", __FUNCTION__)); + return FALSE; + case NORMAL_FRAME: + case NOT_ROBUST_GROUP_FRAME: + case NOT_ROBUST_UNICAST_FRAME: + break; + case UNICAST_ROBUST_FRAME: + { + int tailroom =0 ; + + tailroom = GET_OS_PKT_END(pPacket) - GET_OS_PKT_DATATAIL(pPacket); + pHeader_802_11->FC.Wep = 1; + + /* Format: Mac header|CCMP header|Data|MIC|FCS */ + if (tailroom < (LEN_CCMP_HDR + LEN_CCMP_MIC)) + { + int headroom =GET_OS_PKT_DATAPTR(pPacket) - GET_OS_PKT_HEAD(pPacket) ; + pPacket = OS_PKT_COPY_EXPAND(pPacket, headroom, (LEN_CCMP_HDR + LEN_CCMP_MIC)); + } + + if (pPacket != NULL) { + OS_PKT_TAIL_BUF_EXTEND(pPacket, (LEN_CCMP_HDR + LEN_CCMP_MIC)); + RTMP_QueryPacketInfo(pPacket, &PacketInfo, &pSrcBufVA, &SrcBufLen); + } + if (pSrcBufVA == NULL) + return NORMAL_FRAME; + +#if defined(MT7603) || defined(MT7628) + // TODO: shiang-7603 + pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + tx_hw_hdr_len); + ret = PMF_EncryptUniRobustFrameAction(pAd, + (PUCHAR)pHeader_802_11, + (SrcBufLen - tx_hw_hdr_len)); + +#else + pHeader_802_11 = (PHEADER_802_11) (pSrcBufVA + TXINFO_SIZE + TXWISize); + ret = PMF_EncryptUniRobustFrameAction(pAd, + (PUCHAR)pHeader_802_11, + (SrcBufLen - TXINFO_SIZE - TXWISize)); +#endif + break; + } + case GROUP_ROBUST_FRAME: + { + ret = PMF_EncapBIPAction(pAd, + (PUCHAR)pHeader_802_11, + SrcBufLen); + + break; + } + } + + if (ret == PMF_STATUS_SUCCESS) + return TRUE; + else + return FALSE; +} + + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +#ifndef APCLI_DOT11W_PMF_SUPPORT +BOOLEAN PMF_PerformRxFrameAction(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + INT FrameType; + PUCHAR pMgmtFrame; + UINT mgmt_len; + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PMAC_TABLE_ENTRY pEntry = NULL; + + pMgmtFrame = (PUCHAR)pHeader; + mgmt_len = pRxBlk->MPDUtotalByteCnt; + + if (pRxBlk->wcid < MAX_LEN_OF_MAC_TABLE) + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + else + { + return TRUE; + } + + if (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE)) + { + return TRUE; + } + + FrameType = PMF_RobustFrameClassify(pHeader, + (PUCHAR)(pMgmtFrame + LENGTH_802_11), + (mgmt_len - LENGTH_802_11), + (PUCHAR) pEntry, + TRUE); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + switch (FrameType) + { + case ERROR_FRAME: + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: ERROR FRAME\n", __FUNCTION__)); + return FALSE; + case NORMAL_FRAME: + case NOT_ROBUST_GROUP_FRAME: + break; + case NOT_ROBUST_UNICAST_FRAME: + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s: ERROR FRAME\n", __FUNCTION__)); + return FALSE; + case UNICAST_ROBUST_FRAME: + { + if (pAd->chipCap.hif_type != HIF_MT) + { + if (PMF_DecryptUniRobustFrameAction(pAd, + pMgmtFrame, + mgmt_len) != PMF_STATUS_SUCCESS) + return FALSE; + + pRxBlk->MPDUtotalByteCnt -= (LEN_CCMP_HDR + LEN_CCMP_MIC); + } + break; + } + case GROUP_ROBUST_FRAME: + { + if (pAd->chipCap.hif_type != HIF_MT) + { + if (PMF_ExtractBIPAction(pAd, + pMgmtFrame, + mgmt_len) != PMF_STATUS_SUCCESS) + return FALSE; + + pRxBlk->MPDUtotalByteCnt -= (2 + LEN_PMF_MMIE); + } + break; + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + + + return TRUE; +} +#else +BOOLEAN PMF_PerformRxFrameAction(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk) +{ + INT FrameType; + PUCHAR pMgmtFrame; + UINT mgmt_len; + PHEADER_802_11 pHeader = pRxBlk->pHeader; + PMAC_TABLE_ENTRY pEntry = NULL; + + pMgmtFrame = (PUCHAR)pHeader; + mgmt_len = pRxBlk->MPDUtotalByteCnt; + + if (pRxBlk->wcid < MAX_LEN_OF_MAC_TABLE) + pEntry = &pAd->MacTab.Content[pRxBlk->wcid]; + else { +#if defined(CONFIG_STA_SUPPORT) || defined(APCLI_SUPPORT) + if ((pHeader->Addr1[0] & 0x01) && + (pHeader->FC.Type == FC_TYPE_MGMT) && + ((pHeader->FC.SubType == SUBTYPE_DISASSOC) + || (pHeader->FC.SubType == SUBTYPE_DEAUTH))) { + +#ifdef APCLI_SUPPORT + pEntry = MacTableLookup(pAd, pHeader->Addr2); +#endif /* APCLI_SUPPORT */ + + + if (!pEntry) + return TRUE; + + if (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE)) + return TRUE; + + } else { + return TRUE; + } +#endif /* defined (CONFIG_STA_SUPPORT) || defined (APCLI_SUPPORT) */ + } + + if (pEntry == NULL) + return TRUE; + + if (!CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_PMF_CAPABLE)) { +#if defined(CONFIG_STA_SUPPORT) || defined(APCLI_SUPPORT) + if ((pHeader->Addr1[0] & 0x01) && + (pHeader->FC.Type == FC_TYPE_MGMT) && + ((pHeader->FC.SubType == SUBTYPE_DISASSOC) + || (pHeader->FC.SubType == SUBTYPE_DEAUTH))) { + +#ifdef APCLI_SUPPORT + pEntry = MacTableLookup(pAd, pHeader->Addr2); +#endif /* APCLI_SUPPORT */ + + + if (!pEntry) + return TRUE; + } else + return TRUE; +#endif /* defined (CONFIG_STA_SUPPORT) || defined (APCLI_SUPPORT) */ + } + + FrameType = PMF_RobustFrameClassify(pHeader, + (PUCHAR)(pMgmtFrame + LENGTH_802_11), + (mgmt_len - LENGTH_802_11), + (PUCHAR) pEntry, + TRUE); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + switch (FrameType) { + case ERROR_FRAME: + DBGPRINT(RT_DEBUG_ERROR, + ("[PMF]%s: ERROR FRAME\n", __func__)); + return FALSE; + case NORMAL_FRAME: + case NOT_ROBUST_GROUP_FRAME: +#ifdef APCLI_SUPPORT + if ((pEntry) && IS_ENTRY_APCLI(pEntry)) { + if (CLIENT_STATUS_TEST_FLAG(pEntry, + fCLIENT_STATUS_PMF_CAPABLE)) + return FALSE; + } +#endif /* APCLI_SUPPORT */ + break; + case NOT_ROBUST_UNICAST_FRAME: +#ifdef APCLI_SUPPORT + if ((pEntry) && IS_ENTRY_APCLI(pEntry)) { + if (((pHeader->FC.SubType == SUBTYPE_DISASSOC) + || (pHeader->FC.SubType == SUBTYPE_DEAUTH)) + && CLIENT_STATUS_TEST_FLAG(pEntry, + fCLIENT_STATUS_PMF_CAPABLE)) { + PMF_MlmeSAQueryReq(pAd, pEntry); + return FALSE; + } + } +#endif /* APCLI_SUPPORT */ + DBGPRINT(RT_DEBUG_ERROR, + ("[PMF]%s: ERROR FRAME\n", __func__)); + return FALSE; + case UNICAST_ROBUST_FRAME: + { + if (pAd->chipCap.hif_type != HIF_MT) { + if (PMF_DecryptUniRobustFrameAction(pAd, + pMgmtFrame, + mgmt_len) != PMF_STATUS_SUCCESS) + return FALSE; + + pRxBlk->MPDUtotalByteCnt -= (LEN_CCMP_HDR + LEN_CCMP_MIC); + } + break; + } + case GROUP_ROBUST_FRAME: + { + /*if (pAd->chipCap.hif_type != HIF_MT) */ + /*//MT7603 Mgmt pkt Bcast is S/W Procress.*/ + { + if (PMF_ExtractBIPAction(pAd, + pMgmtFrame, + mgmt_len) != PMF_STATUS_SUCCESS) + return FALSE; + + pRxBlk->MPDUtotalByteCnt -= (2 + LEN_PMF_MMIE); + } + break; + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + + + return TRUE; +} +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + + +/* +======================================================================== +Routine Description: + Protection Management Frame Capable + Protection Management Frame Required + +Arguments: + +Return Value: + +Note: +RSNA policy selection in a ESS: IEEE P802.11w Table 8-1a +RSNA policy selection in an IBSS: IEEE P802.11w Table 8-1b +======================================================================== +*/ +void rtmp_read_pmf_parameters_from_file( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *tmpbuf, + IN RTMP_STRING *pBuffer) +{ + RTMP_STRING *macptr; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + INT apidx; + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + pAd->ApCfg.MBSSID[apidx].PmfCfg.Desired_MFPC = FALSE; + pAd->ApCfg.MBSSID[apidx].PmfCfg.Desired_MFPR = FALSE; + pAd->ApCfg.MBSSID[apidx].PmfCfg.Desired_PMFSHA256 = FALSE; + } + + /* Protection Management Frame Capable */ + if (RTMPGetKeyParameter("PMFMFPC", tmpbuf, 32, pBuffer, TRUE)) + { + for (apidx = 0, macptr = rstrtok(tmpbuf,";"); (macptr && apidx < pAd->ApCfg.BssidNum); macptr = rstrtok(NULL,";"), apidx++) + { + pObj->ioctl_if = apidx; + Set_PMFMFPC_Proc(pAd, macptr); + } + } + + /* Protection Management Frame Required */ + if (RTMPGetKeyParameter("PMFMFPR", tmpbuf, 32, pBuffer, TRUE)) + { + for (apidx = 0, macptr = rstrtok(tmpbuf,";"); (macptr && apidx < pAd->ApCfg.BssidNum); macptr = rstrtok(NULL,";"), apidx++) + { + pObj->ioctl_if = apidx; + Set_PMFMFPR_Proc(pAd, macptr); + } + } + + if (RTMPGetKeyParameter("PMFSHA256", tmpbuf, 32, pBuffer, TRUE)) + { + for (apidx = 0, macptr = rstrtok(tmpbuf,";"); (macptr && apidx < pAd->ApCfg.BssidNum); macptr = rstrtok(NULL,";"), apidx++) + { + pObj->ioctl_if = apidx; + Set_PMFSHA256_Proc(pAd, macptr); + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + +} + + +/* +======================================================================== +Routine Description: Protection Management Frame Capable + +Arguments: + +Return Value: + +Note: +RSNA policy selection in a ESS: IEEE P802.11w Table 8-1a +RSNA policy selection in an IBSS: IEEE P802.11w Table 8-1b +======================================================================== +*/ +INT Set_PMFMFPC_Proc ( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + if(strlen(arg) == 0) + return FALSE; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (simple_strtol(arg, 0, 10)) + pAd->ApCfg.MBSSID[pObj->ioctl_if].PmfCfg.Desired_MFPC = TRUE; + else + pAd->ApCfg.MBSSID[pObj->ioctl_if].PmfCfg.Desired_MFPC = FALSE; + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: apidx=%d, Desired MFPC=%d\n", __FUNCTION__ + , pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].PmfCfg.Desired_MFPC)); + } +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +/* +======================================================================== +Routine Description: Protection Management Frame Required + +Arguments: + +Return Value: + +Note: +RSNA policy selection in a ESS: IEEE P802.11w Table 8-1a +RSNA policy selection in an IBSS: IEEE P802.11w Table 8-1b +======================================================================== +*/ +INT Set_PMFMFPR_Proc ( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + if(strlen(arg) == 0) + return FALSE; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (simple_strtol(arg, 0, 10)) + pAd->ApCfg.MBSSID[pObj->ioctl_if].PmfCfg.Desired_MFPR = TRUE; + else + pAd->ApCfg.MBSSID[pObj->ioctl_if].PmfCfg.Desired_MFPR = FALSE; + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: apidx=%d, Desired MFPR=%d\n", __FUNCTION__ + , pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].PmfCfg.Desired_MFPR)); + } +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + + +INT Set_PMFSHA256_Proc ( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + if(strlen(arg) == 0) + return FALSE; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + POS_COOKIE pObj; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (simple_strtol(arg, 0, 10)) + pAd->ApCfg.MBSSID[pObj->ioctl_if].PmfCfg.Desired_PMFSHA256 = TRUE; + else + pAd->ApCfg.MBSSID[pObj->ioctl_if].PmfCfg.Desired_PMFSHA256 = FALSE; + + DBGPRINT(RT_DEBUG_ERROR, ("[PMF]%s:: apidx=%d, Desired PMFSHA256=%d\n", __FUNCTION__ + , pObj->ioctl_if, pAd->ApCfg.MBSSID[pObj->ioctl_if].PmfCfg.Desired_PMFSHA256)); + } +#endif /* CONFIG_AP_SUPPORT */ + + return TRUE; +} + +#endif /* DOT11W_PMF_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ps.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ps.c new file mode 100644 index 000000000..d0b2f4716 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ps.c @@ -0,0 +1,255 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2010, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + + Abstract: + + All related POWER SAVE function body. + +***************************************************************************/ + +#include "rt_config.h" + + +/* + ======================================================================== + Routine Description: + This routine is used to do insert packet into power-saveing queue. + + Arguments: + pAd: Pointer to our adapter + pPacket: Pointer to send packet + pMacEntry: portint to entry of MacTab. the pMacEntry store attribute of client (STA). + QueIdx: Priority queue idex. + + Return Value: + NDIS_STATUS_SUCCESS:If succes to queue the packet into TxSwQ. + NDIS_STATUS_FAILURE: If failed to do en-queue. +======================================================================== +*/ +NDIS_STATUS RtmpInsertPsQueue( + RTMP_ADAPTER *pAd, + PNDIS_PACKET pPacket, + MAC_TABLE_ENTRY *pMacEntry, + UCHAR QueIdx) +{ + ULONG IrqFlags = 0; +#ifdef UAPSD_SUPPORT + UINT32 ac_id; +#endif + STA_TR_ENTRY *tr_entry = &pAd->MacTab.tr_entry[pMacEntry->wcid];; +#ifdef UAPSD_SUPPORT + /* put the U-APSD packet to its U-APSD queue by AC ID */ + ac_id = QueIdx - QID_AC_BE; /* should be >= 0 */ + + tr_entry = &pAd->MacTab.tr_entry[pMacEntry->wcid]; + + if (UAPSD_MR_IS_UAPSD_AC(pMacEntry, ac_id)) + { + UAPSD_PacketEnqueue(pAd, pMacEntry, pPacket, ac_id, FALSE); + +#ifdef CFG_TDLS_SUPPORT + cfg_tdls_send_PeerTrafficIndication(pAd,pMacEntry->Addr); +#endif /* CFG_TDLS_SUPPORT */ + } + else +#endif /* UAPSD_SUPPORT */ + { + if (tr_entry->ps_queue.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 /*&tr_entry->ps_queue_lock*/, IrqFlags); + InsertTailQueue(&tr_entry->ps_queue, PACKET_TO_QUEUE_ENTRY(pPacket)); + RTMP_IRQ_UNLOCK(&pAd->irq_lock /*&tr_entry->ps_queue_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->func_tb_idx, pMacEntry->Aid); + + } +#endif /* CONFIG_AP_SUPPORT */ + + return NDIS_STATUS_SUCCESS; +} + + +/* + ========================================================================== + Description: + This routine is used to clean up a specified power-saving queue. It's + used whenever a wireless client is deleted. + ========================================================================== + */ +VOID RtmpCleanupPsQueue(RTMP_ADAPTER *pAd, QUEUE_HEADER *pQueue) +{ + QUEUE_ENTRY *pQEntry; + PNDIS_PACKET pPacket; + + DBGPRINT(RT_DEBUG_TRACE, ("RtmpCleanupPsQueue (0x%08lx)...\n", (ULONG)pQueue)); + + while (pQueue->Head) + { + DBGPRINT(RT_DEBUG_TRACE, + ("RtmpCleanupPsQueue %d...\n",pQueue->Number)); + + pQEntry = RemoveHeadQueue(pQueue); + /*pPacket = CONTAINING_RECORD(pEntry, NDIS_PACKET, MiniportReservedEx); */ + pPacket = QUEUE_ENTRY_TO_PACKET(pQEntry); + RELEASE_NDIS_PACKET(pAd, pPacket, NDIS_STATUS_FAILURE); + + DBGPRINT(RT_DEBUG_TRACE, ("RtmpCleanupPsQueue pkt = %lx...\n", (ULONG)pPacket)); + } +} + + +/* + ======================================================================== + Description: + This routine frees all packets in PSQ that's destined to a specific DA. + BCAST/MCAST in DTIMCount=0 case is also handled here, just like a PS-POLL + is received from a WSTA which has MAC address FF:FF:FF:FF:FF:FF + ======================================================================== +*/ +VOID RtmpHandleRxPsPoll(RTMP_ADAPTER *pAd, UCHAR *pAddr, USHORT wcid, BOOLEAN isActive) +{ + MAC_TABLE_ENTRY *pMacEntry; + STA_TR_ENTRY *tr_entry = NULL; + + ASSERT(wcid < MAX_LEN_OF_MAC_TABLE); + + pMacEntry = &pAd->MacTab.Content[wcid]; + tr_entry = &pAd->MacTab.tr_entry[wcid]; + + if (!RTMPEqualMemory(pMacEntry->Addr, pAddr, MAC_ADDR_LEN)) + { + DBGPRINT(RT_DEBUG_WARN | DBG_FUNC_PS,("%s(%d) PS-POLL (MAC addr not match) from %02x:%02x:%02x:%02x:%02x:%02x. Why???\n", + __FUNCTION__, __LINE__, PRINT_MAC(pAddr))); + return; + } + +#ifdef UAPSD_SUPPORT00 + if (UAPSD_MR_IS_ALL_AC_UAPSD(isActive, pMacEntry)) + { + /* + IEEE802.11e spec. + 11.2.1.7 Receive operation for STAs in PS mode during the CP + When a non-AP QSTA that is using U-APSD and has all ACs + delivery-enabled detects that the bit corresponding to its AID + is set in the TIM, the non-AP QSTA shall issue a trigger frame + or a PS-Poll frame to retrieve the buffered MSDU or management + frames. + + WMM Spec. v1.1a 070601 + 3.6.2 U-APSD STA Operation + 3.6.2.3 In case one or more ACs are not + delivery-enabled ACs, the WMM STA may retrieve MSDUs and + MMPDUs belonging to those ACs by sending PS-Polls to the WMM AP. + In case all ACs are delivery enabled ACs, WMM STA should only + use trigger frames to retrieve MSDUs and MMPDUs belonging to + those ACs, and it should not send PS-Poll frames. + + Different definitions in IEEE802.11e and WMM spec. + But we follow the WiFi WMM Spec. + */ + + DBGPRINT(RT_DEBUG_TRACE, ("All AC are UAPSD, can not use PS-Poll\n")); + return; /* all AC are U-APSD, can not use PS-Poll */ + } +#endif /* UAPSD_SUPPORT */ + + /* Reset ContinueTxFailCnt */ + pMacEntry->ContinueTxFailCnt = 0; + pAd->MacTab.tr_entry[pMacEntry->wcid].ContinueTxFailCnt = 0; + + if (isActive == FALSE) + { + if (tr_entry->PsDeQWaitCnt == 0) { + tr_entry->PsDeQWaitCnt = 1; + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): : packet not send by HW then ignore other PS-Poll Aid[%d]!\n", + __FUNCTION__, pMacEntry->Aid)); + return; + } + } + else + tr_entry->PsDeQWaitCnt = 0; + +#ifdef CONFIG_AP_SUPPORT +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + MtHandleRxPsPoll(pAd, pAddr, wcid, isActive); + } +#endif /* MT_MAC */ + +#if defined(RTMP_MAC) || defined(RLT_MAC) + if ((pAd->chipCap.hif_type == HIF_RTMP) + || (pAd->chipCap.hif_type == HIF_RLT)) + { + RalHandleRxPsPoll(pAd, pAddr, wcid, isActive); + } +#endif /* RTMP_MAC || RLT_MAC */ +#endif /* CONFIG_AP_SUPPORT */ +} + + +/* + ========================================================================== + Description: + Update the station current power save mode. Calling this routine also + prove the specified client is still alive. Otherwise AP will age-out + this client once IdleCount exceeds a threshold. + ========================================================================== + */ +BOOLEAN RtmpPsIndicate(RTMP_ADAPTER *pAd, UCHAR *pAddr, UCHAR wcid, UCHAR Psm) +{ +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + return MtPsIndicate(pAd, pAddr, wcid, Psm); + } +#endif /* MT_MAC */ + +#if defined(RTMP_MAC) || defined(RLT_MAC) + if ((pAd->chipCap.hif_type == HIF_RTMP) + || (pAd->chipCap.hif_type == HIF_RLT)) + { + return RalPsIndicate(pAd, pAddr, wcid, Psm); + } +#endif /* RTMP_MAC || RLT_MAC */ + return FALSE; +} + + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ral_ps.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ral_ps.c new file mode 100644 index 000000000..89ef390bc --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/ral_ps.c @@ -0,0 +1,215 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2010, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + + Abstract: + + All related POWER SAVE function body. + +***************************************************************************/ + +#include "rt_config.h" + +/* + ======================================================================== + 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 RalHandleRxPsPoll(RTMP_ADAPTER *pAd, UCHAR *pAddr, USHORT wcid, BOOLEAN isActive) +{ + QUEUE_ENTRY *pQEntry; + MAC_TABLE_ENTRY *pMacEntry; + unsigned long IrqFlags; + STA_TR_ENTRY *tr_entry; + + /* + DBGPRINT(RT_DEBUG_TRACE, ("rcv PS-POLL (AID=%d) from %02x:%02x:%02x:%02x:%02x:%02x\n", + Aid, PRINT_MAC(pAddr))); + */ + + pMacEntry = &pAd->MacTab.Content[wcid]; + tr_entry = &pAd->MacTab.tr_entry[wcid]; + + { + /*NdisAcquireSpinLock(&pAd->MacTabLock); */ + /*NdisAcquireSpinLock(&pAd->TxSwQueueLock); */ + RTMP_IRQ_LOCK(&pAd->irq_lock, IrqFlags); + if (isActive == FALSE) + { + if (tr_entry->ps_queue.Head) + { +#ifdef UAPSD_SUPPORT + UINT32 NumOfOldPsPkt; + NumOfOldPsPkt = pAd->TxSwQueue[QID_AC_BE].Number; +#endif /* UAPSD_SUPPORT */ + + pQEntry = RemoveHeadQueue(&tr_entry->ps_queue); + if (tr_entry->ps_queue.Number >= 1) + { + RTMP_SET_PACKET_MOREDATA(RTPKT_TO_OSPKT(pQEntry), TRUE); + RTMP_SET_PACKET_TXTYPE(RTPKT_TO_OSPKT(pQEntry), TX_LEGACY_FRAME); + } + InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QID_AC_BE], pQEntry); + +#ifdef UAPSD_SUPPORT + /* we need to call RTMPDeQueuePacket() immediately as below */ + if (NumOfOldPsPkt != pAd->TxSwQueue[QID_AC_BE].Number) + { + if (RTMP_GET_PACKET_DHCP(RTPKT_TO_OSPKT(pQEntry)) || + RTMP_GET_PACKET_EAPOL(RTPKT_TO_OSPKT(pQEntry)) || + RTMP_GET_PACKET_WAI(RTPKT_TO_OSPKT(pQEntry))) + { + /* + These packets will use 1M/6M rate to send. + If you use 1M(2.4G)/6M(5G) to send, no statistics + count in NICUpdateFifoStaCounters(). + + So we can not count it for UAPSD; Or the SP will + not closed until timeout. + */ + } + else + UAPSD_MR_MIX_PS_POLL_RCV(pAd, pMacEntry); + } +#endif /* UAPSD_SUPPORT */ + } + else + { + /* + or transmit a (QoS) Null Frame; + + In addtion, in Station Keep Alive mechanism, we need to + send a QoS Null frame to detect the station live status. + */ + BOOLEAN bQosNull = FALSE; + + if (CLIENT_STATUS_TEST_FLAG(pMacEntry, fCLIENT_STATUS_WMM_CAPABLE)) + bQosNull = TRUE; + + RtmpEnqueueNullFrame(pAd, pMacEntry->Addr, tr_entry->CurrTxRate, + pMacEntry->Aid, pMacEntry->func_tb_idx, + 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(tr_entry->ps_queue.Head) + { + pQEntry = RemoveHeadQueue(&tr_entry->ps_queue); + InsertTailQueueAc(pAd, pMacEntry, &pAd->TxSwQueue[QID_AC_BE], pQEntry); + } + } + + /*NdisReleaseSpinLock(&pAd->TxSwQueueLock); */ + /*NdisReleaseSpinLock(&pAd->MacTabLock); */ + + if ((pMacEntry->Aid > 0) && (pMacEntry->Aid < MAX_LEN_OF_MAC_TABLE) && + (tr_entry->ps_queue.Number == 0)) + { + /* clear corresponding TIM bit because no any PS packet */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { + WLAN_MR_TIM_BIT_CLEAR(pAd, pMacEntry->func_tb_idx, pMacEntry->Aid); + } +#endif /* CONFIG_AP_SUPPORT */ + tr_entry->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, wcid, MAX_TX_PROCESS); + } +} + + +/* + ========================================================================== + 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 RalPsIndicate(RTMP_ADAPTER *pAd, UCHAR *pAddr, UCHAR wcid, UCHAR Psm) +{ + MAC_TABLE_ENTRY *pEntry; + UCHAR old_psmode; + STA_TR_ENTRY *tr_entry; + tr_entry = &pAd->MacTab.tr_entry[wcid]; + + 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; + // TODO: shiang-usw, we need to rmove upper setting and migrate to tr_entry->PsMode + pAd->MacTab.tr_entry[wcid].PsMode = Psm; + + if (old_psmode != Psm) { + DBGPRINT(RT_DEBUG_INFO, ("%s():%02x:%02x:%02x:%02x:%02x:%02x %s!\n", + __FUNCTION__, PRINT_MAC(pAddr), + (Psm == PWR_SAVE ? "Sleep" : "wakes up, act like rx PS-POLL"))); + } + + if ((old_psmode == PWR_SAVE) && (Psm == PWR_ACTIVE)) + { +#ifdef RTMP_MAC_PCI +#ifdef DOT11_N_SUPPORT + /* + When sta wake up, we send BAR to refresh the BA sequence. + TODO: + For RT2870, how to handle BA when STA in PS mode? + */ + SendRefreshBAR(pAd, pEntry); +#endif /* DOT11_N_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + + /* sleep station awakes, move all pending frames from PSQ to TXQ if any */ + RtmpHandleRxPsPoll(pAd, pAddr, pEntry->wcid, TRUE); + } + } + return old_psmode; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/routing_tab.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/routing_tab.c new file mode 100644 index 000000000..a5535b673 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/routing_tab.c @@ -0,0 +1,1644 @@ +/* + + + *************************************************************************** + + + * Ralink Tech Inc. + + + * 5F., No.36, Taiyuan St., Jhubei City, + + + * Hsinchu County 302, + + + * Taiwan, R.O.C. + + + * + + + * (c) Copyright 2002-2009, Ralink Technology, Inc. + + + * + + + * All rights reserved. Ralink's source code is an unpublished work and the + + + * use of a copyright notice does not imply otherwise. This source code + + + * contains confidential trade secret material of Ralink Tech. Any attemp + + + * or participation in deciphering, decoding, reverse engineering or in any + + + * way altering the source code is stricitly prohibited, unless the prior + + + * written consent of Ralink Technology, Inc. is obtained. + + + *************************************************************************** + + + + + + + + + Module Name: + + + routing_tab.c + + + + + + Abstract: + + + This is a tab used to record all entries behind associated APClinet or STA/PC. + + + + + + Revision History: + + + Who When What + + + --------- ---------- ---------------------------------------------- + + + */ + + +#ifdef ROUTING_TAB_SUPPORT + + +#include "rt_config.h" + + +#include + + +#include + + + + + + + + +VOID RoutingTabInit( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN UINT32 Flag) + + +{ + + + UINT32 i; + + + BSS_STRUCT *pMbss = NULL; + + + + + + if((ifIndex >= HW_BEACON_MAX_NUM)) + + + return; + + + + + + pMbss = &pAd->ApCfg.MBSSID[ifIndex]; + + + if(pMbss->bRoutingTabInit) + + + { + + + pMbss->RoutingTabFlag |= Flag; + + + return; + + + } + + + + + + if(pMbss->pRoutingEntryPool== NULL) + + + os_alloc_mem(pAd, (UCHAR **)&pMbss->pRoutingEntryPool, sizeof(ROUTING_ENTRY) * ROUTING_POOL_SIZE); + + + + + + if (pMbss->pRoutingEntryPool) + + + { + + + NdisZeroMemory(pMbss->pRoutingEntryPool, sizeof(ROUTING_ENTRY) * ROUTING_POOL_SIZE); + + + initList(&pMbss->RoutingEntryFreeList); + + + for (i = 0; i < ROUTING_POOL_SIZE; i++) + + + insertTailList(&pMbss->RoutingEntryFreeList, (RT_LIST_ENTRY *)(pMbss->pRoutingEntryPool+i)); + + + + + + for (i = 0; i < ROUTING_HASH_TAB_SIZE; i++) + + + initList(&pMbss->RoutingTab[i]); + + + + + + NdisAllocateSpinLock(pAd, &pMbss->RoutingTabLock); + + + pMbss->RoutingTabFlag |= Flag; + + + pMbss->bRoutingTabInit = TRUE; + + + } + + + else + + + DBGPRINT(RT_DEBUG_ERROR, ("%s: Fail to alloc memory for MBSSID[%d].pRoutingEntryPool\n" + + + , __FUNCTION__, ifIndex)); + + +} + + + + + +VOID RoutingTabDestory( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN UINT32 Flag) + + +{ + + + BSS_STRUCT *pMbss = NULL; + + + + + + if((ifIndex >= HW_BEACON_MAX_NUM)) + + + return; + + + + + + pMbss = &pAd->ApCfg.MBSSID[ifIndex]; + + + if(!pMbss->bRoutingTabInit) + + + return; + + + + + + RoutingTabClear(pAd, ifIndex, Flag); + + + + + + pMbss->RoutingTabFlag &= ~Flag; + + + if(pMbss->RoutingTabFlag == 0) + + + { + + + NdisFreeSpinLock(&pMbss->RoutingTabLock); + + + if (pMbss->pRoutingEntryPool) + + + os_free_mem(NULL,pMbss->pRoutingEntryPool); + + + pMbss->pRoutingEntryPool = NULL; + + + initList(&pMbss->RoutingEntryFreeList); + + + pMbss->bRoutingTabInit = FALSE; + + + } + + +} + + + + + +VOID RoutingTabClear( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN UINT32 Flag) + + +{ + + + INT32 i; + + + BSS_STRUCT *pMbss = NULL; + + + PROUTING_ENTRY pRoutingEntry = NULL, pRoutingEntryNext = NULL; + + + + + + if((ifIndex >= HW_BEACON_MAX_NUM)) + + + return; + + + + + + pMbss = &pAd->ApCfg.MBSSID[ifIndex]; + + + RTMP_SEM_LOCK(&pMbss->RoutingTabLock); + + + for (i = 0; i < ROUTING_HASH_TAB_SIZE; i++) + + + { + + + pRoutingEntry = GetRoutingTabHead(pAd, ifIndex, i); + + + while(pRoutingEntry) + + + { + + + pRoutingEntryNext = pRoutingEntry->pNext; + + + if(pRoutingEntry->Valid && ROUTING_ENTRY_TEST_FLAG(pRoutingEntry, Flag)) + + + { + + + CLEAR_ROUTING_ENTRY(pRoutingEntry, Flag); + + + /* If not any entry type, then recycle to free list. */ + + + if(!IS_ROUTING_ENTRY(pRoutingEntry)) + + + { + + + delEntryList(&pMbss->RoutingTab[i], (RT_LIST_ENTRY *)pRoutingEntry); + + + NdisZeroMemory(pRoutingEntry, sizeof(ROUTING_ENTRY)); + + + insertTailList(&pMbss->RoutingEntryFreeList, (RT_LIST_ENTRY *)pRoutingEntry); + + + } + + + } + + + pRoutingEntry = pRoutingEntryNext; + + + } + + + } + + + RTMP_SEM_UNLOCK(&pMbss->RoutingTabLock); + + +} + + + + + +PROUTING_ENTRY RoutingTabGetFree( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex) + + +{ + + + BSS_STRUCT *pMbss = NULL; + + + PROUTING_ENTRY pRoutingEntry = NULL; + + + + + + if((ifIndex >= HW_BEACON_MAX_NUM)) + + + return NULL; + + + + + + pMbss = &pAd->ApCfg.MBSSID[ifIndex]; + + + if(!pMbss->bRoutingTabInit) + + + return NULL; + + + + + + RTMP_SEM_LOCK(&pMbss->RoutingTabLock); + + + pRoutingEntry = (PROUTING_ENTRY)removeHeadList(&pMbss->RoutingEntryFreeList); + + + RTMP_SEM_UNLOCK(&pMbss->RoutingTabLock); + + + + + + return pRoutingEntry; + + +} + + + + + +VOID RoutingTabSetAllFree( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN UCHAR Wcid, + + + IN UINT32 Flag) + + +{ + + + INT32 i; + + + BSS_STRUCT *pMbss = NULL; + + + PROUTING_ENTRY pRoutingEntry = NULL, pRoutingEntryNext = NULL; + + + + + + if((ifIndex >= HW_BEACON_MAX_NUM)) + + + return; + + + + + + pMbss = &pAd->ApCfg.MBSSID[ifIndex]; + + + if(!pMbss->bRoutingTabInit) + + + return; + + + + + + RTMP_SEM_LOCK(&pMbss->RoutingTabLock); + + + for (i = 0; i < ROUTING_HASH_TAB_SIZE; i++) + + + { + + + pRoutingEntry = GetRoutingTabHead(pAd, ifIndex, i); + + + while(pRoutingEntry) + + + { + + + pRoutingEntryNext = pRoutingEntry->pNext; + + + if(pRoutingEntry->Valid && (pRoutingEntry->Wcid == Wcid)) + + + { + + + CLEAR_ROUTING_ENTRY(pRoutingEntry, Flag); + + + /* If not any entry type, then recycle to free list. */ + + + if(!IS_ROUTING_ENTRY(pRoutingEntry)) + + + { + + + delEntryList(&pMbss->RoutingTab[i], (RT_LIST_ENTRY *)pRoutingEntry); + + + NdisZeroMemory(pRoutingEntry, sizeof(ROUTING_ENTRY)); + + + insertTailList(&pMbss->RoutingEntryFreeList, (RT_LIST_ENTRY *)pRoutingEntry); + + + } + + + } + + + pRoutingEntry = pRoutingEntryNext; + + + } + + + } + + + RTMP_SEM_UNLOCK(&pMbss->RoutingTabLock); + + +} + + + + + +VOID RoutingTabSetOneFree( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN PUCHAR pMac, + + + IN UINT32 Flag) + + +{ + + + INT32 HashId; + + + BSS_STRUCT *pMbss = NULL; + + + PROUTING_ENTRY pRoutingEntry = NULL; + + + + + + if((ifIndex >= HW_BEACON_MAX_NUM)) + + + return; + + + + + + pMbss = &pAd->ApCfg.MBSSID[ifIndex]; + + + if(!pMbss->bRoutingTabInit) + + + return; + + + + + + HashId = GetHashID(pMac); + + + if(HashId < 0) + + + { + + + DBGPRINT(RT_DEBUG_ERROR, ("%s: Hash Id isn't correct!\n", __FUNCTION__)); + + + return; + + + } + + + + + + RTMP_SEM_LOCK(&pMbss->RoutingTabLock); + + + pRoutingEntry = GetRoutingTabHead(pAd, ifIndex, HashId); + + + while (pRoutingEntry) + + + { + + + if (pRoutingEntry->Valid && MAC_ADDR_EQUAL(pMac, pRoutingEntry->Mac)) + + + { + + + CLEAR_ROUTING_ENTRY(pRoutingEntry, Flag); + + + /* If not any entry type, then recycle to free list. */ + + + if(!IS_ROUTING_ENTRY(pRoutingEntry)) + + + { + + + delEntryList(&pMbss->RoutingTab[HashId], (RT_LIST_ENTRY *)pRoutingEntry); + + + NdisZeroMemory(pRoutingEntry, sizeof(ROUTING_ENTRY)); + + + insertTailList(&pMbss->RoutingEntryFreeList, (RT_LIST_ENTRY *)pRoutingEntry); + + + } + + + break; + + + } + + + pRoutingEntry = pRoutingEntry->pNext; + + + } + + + RTMP_SEM_UNLOCK(&pMbss->RoutingTabLock); + + +} + + + + + +VOID RoutingEntryRefresh( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN PROUTING_ENTRY pRoutingEntry) + + +{ + + + ULONG Now; + + + BSS_STRUCT *pMbss = NULL; + + + + + + if((ifIndex >= HW_BEACON_MAX_NUM)) + + + return; + + + + + + pMbss = &pAd->ApCfg.MBSSID[ifIndex]; + + + if(!pMbss->bRoutingTabInit || !pRoutingEntry) + + + return; + + + + + + NdisGetSystemUpTime(&Now); + + + pRoutingEntry->KeepAliveTime = Now + ROUTING_ENTRY_AGEOUT; + + +} + + + + + +VOID RoutingEntrySet( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN UCHAR Wcid, + + + IN PUCHAR pMac, + + + IN PROUTING_ENTRY pRoutingEntry) + + +{ + + + INT32 HashId; + + + BSS_STRUCT *pMbss = NULL; + + + + + + if((ifIndex >= HW_BEACON_MAX_NUM)) + + + return; + + + + + + pMbss = &pAd->ApCfg.MBSSID[ifIndex]; + + + if(!pMbss->bRoutingTabInit || !pRoutingEntry) + + + return; + + + + + + HashId = GetHashID(pMac); + + + if(HashId < 0) + + + { + + + DBGPRINT(RT_DEBUG_ERROR, ("%s: Hash Id isn't correct!\n", __FUNCTION__)); + + + return; + + + } + + + + + + pRoutingEntry->Valid = 1; + + + pRoutingEntry->Wcid = Wcid; + + + COPY_MAC_ADDR(&pRoutingEntry->Mac, pMac); + + + pRoutingEntry->pNext = NULL; + + + RoutingEntryRefresh(pAd, ifIndex, pRoutingEntry); + + + + + + RTMP_SEM_LOCK(&pMbss->RoutingTabLock); + + + insertTailList(&pMbss->RoutingTab[HashId], (RT_LIST_ENTRY *)pRoutingEntry); + + + RTMP_SEM_UNLOCK(&pMbss->RoutingTabLock); + + +} + + + + + +INT32 GetHashID( + + + IN PUCHAR pMac) + + +{ + + + INT32 HashId = -1; + + + if(pMac) + + + HashId = (*(pMac + 5)&(ROUTING_HASH_TAB_SIZE - 1)); + + + + + + return HashId; + + +} + + + + + +PROUTING_ENTRY GetRoutingTabHead( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN INT32 Index) + + +{ + + + BSS_STRUCT *pMbss = NULL; + + + + + + if((ifIndex >= HW_BEACON_MAX_NUM)) + + + return NULL; + + + + + + pMbss = &pAd->ApCfg.MBSSID[ifIndex]; + + + if(!pMbss->bRoutingTabInit) + + + return NULL; + + + + + + if(Index < ROUTING_HASH_TAB_SIZE) + + + return (PROUTING_ENTRY)pMbss->RoutingTab[Index].pHead; + + + else + + + return NULL; + + +} + + + + + +BOOLEAN GetRoutingEntryAll( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN UCHAR Wcid, + + + IN UINT32 Flag, + + + IN INT32 BufMaxCount, + + + OUT ROUTING_ENTRY **pEntryListBuf, + + + OUT PUINT32 pCount) + + +{ + + + INT32 i, Total; + + + BSS_STRUCT *pMbss = NULL; + + + PROUTING_ENTRY pRoutingEntry = NULL; + + + BOOLEAN bFull = FALSE; + + + + + + if((ifIndex >= HW_BEACON_MAX_NUM)) + + + return FALSE; + + + + + + pMbss = &pAd->ApCfg.MBSSID[ifIndex]; + + + if(!pMbss->bRoutingTabInit || !pEntryListBuf) + + + return FALSE; + + + + + + RTMP_SEM_LOCK(&pMbss->RoutingTabLock); + + + for (i = 0, Total = 0; i < ROUTING_HASH_TAB_SIZE; i++) + + + { + + + pRoutingEntry = GetRoutingTabHead(pAd, ifIndex, i); + + + while(pRoutingEntry) + + + { + + + if(pRoutingEntry->Valid && + + + (pRoutingEntry->Wcid == Wcid) && + + + ROUTING_ENTRY_TEST_FLAG(pRoutingEntry, Flag)) + + + { + + + if(Total < BufMaxCount) + + + *(pEntryListBuf+Total++) = pRoutingEntry; + + + else + + + { + + + bFull = TRUE; + + + break; + + + } + + + } + + + pRoutingEntry = pRoutingEntry->pNext; + + + } + + + + + + if(bFull) + + + break; + + + } + + + RTMP_SEM_UNLOCK(&pMbss->RoutingTabLock); + + + + + + *pCount = Total; + + + return TRUE; + + +} + + + + + +INT RoutingTabGetEntryCount( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex) + + +{ + + + int count = 0; + + + BSS_STRUCT *pMbss = NULL; + + + + + + if((ifIndex >= HW_BEACON_MAX_NUM)) + + + return 0; + + + + + + pMbss = &pAd->ApCfg.MBSSID[ifIndex]; + + + if(!pMbss->bRoutingTabInit) + + + return 0; + + + + + + count = (ROUTING_POOL_SIZE - getListSize(&pMbss->RoutingEntryFreeList)); + + + return count; + + +} + + + + + +PROUTING_ENTRY RoutingTabLookup( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN PUCHAR pMac, + + + IN BOOLEAN bUpdateAliveTime, + + + OUT UCHAR* pWcid) + + +{ + + + INT32 HashId; + + + PROUTING_ENTRY pRoutingEntry = NULL; + + + + + + if(RoutingTabGetEntryCount(pAd, ifIndex) == 0) + + + return NULL; + + + + + + HashId = GetHashID(pMac); + + + if(HashId < 0) + + + { + + + DBGPRINT(RT_DEBUG_ERROR, ("%s: Hash Id isn't correct!\n", __FUNCTION__)); + + + return NULL; + + + } + + + + + + pRoutingEntry = GetRoutingTabHead(pAd, ifIndex, HashId); + + + while (pRoutingEntry) + + + { + + + if (pRoutingEntry->Valid && MAC_ADDR_EQUAL(pMac, pRoutingEntry->Mac)) + + + { + + + if (VALID_WCID(pRoutingEntry->Wcid)) + + + { + + + if(bUpdateAliveTime) + + + { + + + RoutingEntryRefresh(pAd, ifIndex, pRoutingEntry); + + + pRoutingEntry->Retry = 0; +#ifdef A4_CONN + pRoutingEntry->NeedRefresh = FALSE; +#endif + + } + + + + + + if(pWcid) *pWcid = pRoutingEntry->Wcid; + + + return pRoutingEntry; + + + } + + + else + + + return NULL; + + + } + + + pRoutingEntry = pRoutingEntry->pNext; + + + } + + + + + + return NULL; + + +} + + + + + +VOID RoutingTabARPLookupUpdate( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN PROUTING_ENTRY pRoutingEntry, + + + IN UINT32 ARPSenderIP) + + +{ + + + if(!pRoutingEntry || (RoutingTabGetEntryCount(pAd, ifIndex) == 0)) + + + return; + + + + + + NdisCopyMemory(&pRoutingEntry->IPAddr, &ARPSenderIP, 4); + + +} + + + + + +INT RoutingEntrySendAliveCheck( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN PROUTING_ENTRY pRoutingEntry, + + + IN UCHAR *pSrcMAC, + + + IN UINT32 SrcIP) + + +{ + + + struct wifi_dev *wdev = NULL; + + + struct sk_buff *skb = NULL; + + + PMAC_TABLE_ENTRY pEntry = NULL; + + + + + + if(!pRoutingEntry || !pSrcMAC || + + + !VALID_WCID(pRoutingEntry->Wcid) || + + + (SrcIP == 0) || (pRoutingEntry->IPAddr == 0)) + + + return FALSE; + + + + + + if(RoutingTabGetEntryCount(pAd, ifIndex) == 0) + + + return FALSE; + + + + + + pEntry = &pAd->MacTab.Content[pRoutingEntry->Wcid]; + + + wdev = pEntry->wdev; + + + if(!wdev) + + + return FALSE; + + + + + + skb = arp_create(ARPOP_REQUEST, ETH_P_ARP, pRoutingEntry->IPAddr, wdev->if_dev, + + + SrcIP, BROADCAST_ADDR, pSrcMAC, ZERO_MAC_ADDR); + + + if(!skb) + + + { + + + DBGPRINT(RT_DEBUG_ERROR, ("%s: Fail to alloc memory for arp request!\n", __FUNCTION__)); + + + return FALSE; + + + } + + + + + + RTMP_SET_PACKET_WCID(skb, pRoutingEntry->Wcid); + + + RTMP_SET_PACKET_WDEV(skb, wdev->wdev_idx); + + + RTMP_SET_PACKET_MOREDATA(skb, FALSE); + + +#ifdef CUT_THROUGH + + +#ifdef CUT_THROUGH_FULL_OFFLOAD + + + if(wdev->tx_pkt_ct_handle) + + + { + + + UCHAR que_idx = 0, user_prio = QID_AC_BE; + + + wdev->tx_pkt_ct_handle(pAd, skb, que_idx, user_prio); + + + } + + + else + + +#endif /* CUT_THROUGH_FULL_OFFLOAD */ + + +#endif /* CUT_THROUGH */ + + + if(wdev->tx_pkt_handle) + + + wdev->tx_pkt_handle(pAd, skb); + + + + + + return TRUE; + + +} + + + + + +VOID RoutingTabMaintain( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex) +{ + UINT32 i = 0, BridgeIP = 0; + ULONG Now = 0; + BSS_STRUCT *pMbss = NULL; + PROUTING_ENTRY pRoutingEntry = NULL, pRoutingEntryNext = NULL; + BOOLEAN bNeedSend = FALSE, bBridgeFound = FALSE, bNeedDelete = FALSE, bCreateARP = FALSE; + UCHAR BridgeMAC[MAC_ADDR_LEN] = {0}; + + if (ifIndex >= HW_BEACON_MAX_NUM) + return; + + if (RoutingTabGetEntryCount(pAd, ifIndex) == 0) + return; + +#ifdef MAC_REPEATER_SUPPORT + if (!MAC_ADDR_EQUAL(pAd->ApCfg.BridgeAddress, ZERO_MAC_ADDR)) { + COPY_MAC_ADDR(BridgeMAC, pAd->ApCfg.BridgeAddress); + bBridgeFound = TRUE; + } else +#endif /* MAC_REPEATER_SUPPORT */ + { +#ifdef LINUX + struct net_device *pBridgeNetDev = NULL; + struct net *net = &init_net; + + for_each_netdev(net, pBridgeNetDev) { + if (pBridgeNetDev->priv_flags == IFF_EBRIDGE) { + const struct in_device *pBridgeInDev = pBridgeNetDev->ip_ptr; + + if (pBridgeInDev) { + const struct in_ifaddr *ifa = pBridgeInDev->ifa_list; + + if (ifa) { + COPY_MAC_ADDR(BridgeMAC, pBridgeNetDev->dev_addr); + NdisCopyMemory(&BridgeIP, &ifa->ifa_address, 4); + + bBridgeFound = TRUE; + break; + } + } + } + } +#endif /* LINUX */ + } + + if (!bBridgeFound) + return; + + pMbss = &pAd->ApCfg.MBSSID[ifIndex]; + NdisGetSystemUpTime(&Now); + RTMP_SEM_LOCK(&pMbss->RoutingTabLock); + + for (i = 0; i < ROUTING_HASH_TAB_SIZE; i++) { + pRoutingEntry = GetRoutingTabHead(pAd, ifIndex, i); + + while (pRoutingEntry) { + bCreateARP = FALSE; + bNeedDelete = FALSE; + pRoutingEntryNext = pRoutingEntry->pNext; +#ifdef A4_CONN + if (pAd->a4_need_refresh) + pRoutingEntry->NeedRefresh = TRUE; +#endif + + /* Stage 1 Check*/ + if ((pRoutingEntry->Valid && RTMP_TIME_AFTER(Now, pRoutingEntry->KeepAliveTime) + && pRoutingEntry->IPAddr != 0)/*porting from mt7615*/ +#ifdef A4_CONN + || pRoutingEntry->NeedRefresh +#endif + ) { + if (bBridgeFound) { + /* Stage 2 Check*/ + + /*porting from mt7615*/ + if (pRoutingEntry->Retry == 0 || RTMP_TIME_AFTER(Now, pRoutingEntry->RetryTime) +#ifdef A4_CONN + || pRoutingEntry->NeedRefresh +#endif + ) { + if (pRoutingEntry->Retry >= ROUTING_ENTRY_MAX_RETRY) + bNeedDelete = TRUE; + else { + bCreateARP = TRUE; + pRoutingEntry->Retry++; + pRoutingEntry->RetryTime = Now + ROUTING_ENTRY_RETRY_TIME; + } + } + + if (bCreateARP) { + if (RoutingEntrySendAliveCheck(pAd, ifIndex, pRoutingEntry, BridgeMAC, BridgeIP)) + bNeedSend = TRUE; + } + } else + bNeedDelete = TRUE; + + if (bNeedDelete) { + delEntryList(&pMbss->RoutingTab[i], (RT_LIST_ENTRY *)pRoutingEntry); + NdisZeroMemory(pRoutingEntry, sizeof(ROUTING_ENTRY)); + insertTailList(&pMbss->RoutingEntryFreeList, (RT_LIST_ENTRY *)pRoutingEntry); + } + } else + pRoutingEntry->Retry = 0; + + pRoutingEntry = pRoutingEntryNext; + } + } + RTMP_SEM_UNLOCK(&pMbss->RoutingTabLock); + + /* Dequeue outgoing frames from TxSwQueue[] and process it */ + if (bNeedSend) + RTMPDeQueuePacket(pAd, FALSE, WMM_NUM_OF_AC, WCID_ALL, MAX_TX_PROCESS); +} + +#endif /* ROUTING_TAB_SUPPORT */ + + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rrm.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rrm.c new file mode 100644 index 000000000..b2e78afbe --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rrm.c @@ -0,0 +1,2559 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2006, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + Abstract: + +***************************************************************************/ + +#ifdef DOT11K_RRM_SUPPORT + +#include "rt_config.h" + +/* +static CHAR ZeroSsid[32] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; +*/ + + +static VOID RRM_QuietOffsetTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +static VOID RRM_QuietTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +DECLARE_TIMER_FUNCTION(RRM_QuietOffsetTimeout); +DECLARE_TIMER_FUNCTION(RRM_QuietTimeout); + +BUILD_TIMER_FUNCTION(RRM_QuietOffsetTimeout); +BUILD_TIMER_FUNCTION(RRM_QuietTimeout); + + + +static VOID RRM_QuietOffsetTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + INT idx; + PRRM_CONFIG pRrmCfg = NULL; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + PRALINK_TIMER_STRUCT pTimer = (PRALINK_TIMER_STRUCT) SystemSpecific3; + + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) + { + pRrmCfg = &pAd->ApCfg.MBSSID[idx].RrmCfg; + if (&pRrmCfg->QuietCB.QuietOffsetTimer == pTimer) + break; + } + + /* start Quiet . */ + if (idx == pAd->ApCfg.BssidNum) + return; + + pRrmCfg = &pAd->ApCfg.MBSSID[idx].RrmCfg; + pRrmCfg->QuietCB.QuietState = RRM_QUIET_SILENT; + RTMPSetTimer(&pRrmCfg->QuietCB.QuietTimer, + pRrmCfg->QuietCB.QuietDuration); + + return; +} + +static VOID RRM_QuietTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + INT idx; + PRRM_CONFIG pRrmCfg = NULL; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)FunctionContext; + PRALINK_TIMER_STRUCT pTimer = (PRALINK_TIMER_STRUCT) SystemSpecific3; + + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) + { + pRrmCfg = &pAd->ApCfg.MBSSID[idx].RrmCfg; + if (&pRrmCfg->QuietCB.QuietTimer == pTimer) + break; + } + + /* stop Quiet . */ + if (idx == pAd->ApCfg.BssidNum) + return; + + pRrmCfg = &pAd->ApCfg.MBSSID[idx].RrmCfg; + pRrmCfg->QuietCB.QuietState = RRM_QUIET_IDLE; + + return; +} + +void RRM_ReadParametersFromFile( + IN PRTMP_ADAPTER pAd, + RTMP_STRING *tmpbuf, + RTMP_STRING *buffer) +{ + INT loop; + RTMP_STRING *macptr; + + /* RRMEnable */ + if (RTMPGetKeyParameter("RRMEnable", tmpbuf, 255, buffer, TRUE)) + { + for (loop=0, macptr = rstrtok(tmpbuf,";"); + (macptr && loop < MAX_MBSSID_NUM(pAd)); + macptr = rstrtok(NULL,";"), loop++) + { + LONG Enable; + Enable = simple_strtol(macptr, 0, 10); + pAd->ApCfg.MBSSID[loop].RrmCfg.bDot11kRRMEnable = + (Enable > 0) ? TRUE : FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("%s::(bDot11kRRMEnable[%d]=%d)\n", + __FUNCTION__, loop, + pAd->ApCfg.MBSSID[loop].RrmCfg.bDot11kRRMEnable)); + } + } + else + { + for (loop = 0; loop < MAX_MBSSID_NUM(pAd); loop++) + pAd->ApCfg.MBSSID[loop].RrmCfg.bDot11kRRMEnable = FALSE; + } + + /* Regulatory Class */ + if (RTMPGetKeyParameter("RegulatoryClass", tmpbuf, 255, buffer, TRUE)) + { + LONG Value; + for (loop=0, macptr = rstrtok(tmpbuf,";"); + (macptr && loop < MAX_NUM_OF_REGULATORY_CLASS); + macptr = rstrtok(NULL,";"), loop++) + { + Value = simple_strtol(macptr, 0, 10); + pAd->CommonCfg.RegulatoryClass[loop] = Value; + } + + } + if (RTMPGetKeyParameter("RegDomain", tmpbuf, 255, buffer, TRUE)) { + if (!strncmp(tmpbuf, "Global", 6)) + pAd->reg_domain = REG_GLOBAL; + else + pAd->reg_domain = REG_LOCAL; + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("pAd->reg_domain = %u\n", + pAd->reg_domain)); + } + + return; +} + +UINT16 bcn_rand_int; +INT Set_BeaconReq_RandInt_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + bcn_rand_int = (UINT) simple_strtol(arg, 0, 10); + return TRUE; +} + +INT Set_Dot11kRRM_Enable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex = pObj->ioctl_if; + ULONG Value; + + if (ifIndex >= pAd->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_OFF, ("Unknow If index (%d)", ifIndex)); + return -1; + } + + Value = (UINT) simple_strtol(arg, 0, 10); + pAd->ApCfg.MBSSID[ifIndex].RrmCfg.bDot11kRRMEnable = + (BOOLEAN)(Value) == 0 ? FALSE : TRUE; + + if(pAd->ApCfg.MBSSID[ifIndex].RrmCfg.bDot11kRRMEnable) + pAd->ApCfg.MBSSID[ifIndex].CapabilityInfo |= RRM_CAP_BIT; + else + pAd->ApCfg.MBSSID[ifIndex].CapabilityInfo &= ~RRM_CAP_BIT; + + return 1; +} + +INT Set_BeaconReq_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT Loop; + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex = pObj->ioctl_if; + UINT Aid = 1; + UINT ArgIdx; + RTMP_STRING *thisChar; + + RRM_MLME_BCN_REQ_INFO BcnReq; + UINT8 default_request_ie[MAX_NUM_OF_REQ_IE] = { + 0, /* SSID */ + 1, /* Support Rate*/ + + 50, /* Extended Support Rate*/ + + 45, /* HT IE*/ + 61, /* HT ADD*/ + + 127, /* Ext Cap*/ + + 191, /* VHT 1*/ + 192, /* VHT 2*/ + 195, /* VHT 3*/ + + 48, /* RSN IE */ + 70, /* RRM Capabilities. */ + 54, /* Mobility Domain. */ + 221 + }; /* Vendor Specific. */ + + ArgIdx = 0; + NdisZeroMemory(&BcnReq, sizeof(RRM_MLME_BCN_REQ_INFO)); + BcnReq.report_detail = 1; /*set default report detail to 1*/ + /*set default request ie*/ + BcnReq.request_ie_num = MAX_NUM_OF_REQ_IE; + NdisCopyMemory(BcnReq.request_ie, default_request_ie, MAX_NUM_OF_REQ_IE); + + while ((thisChar = strsep((char **)&arg, "!")) != NULL) + { + switch(ArgIdx) + { + case 0:/* Aid or Peer's MAC Addr */ + if (strlen(thisChar) == 17) { + UCHAR mac_addr[MAC_ADDR_LEN]; + CHAR *token; + MAC_TABLE_ENTRY *pEntry = NULL; + INT i = 0; + + token = rstrtok(thisChar, ":"); + while (token != NULL) { + AtoH(token, (char *) &mac_addr[i], 1); + i++; + if (i >= MAC_ADDR_LEN) + break; + token = rstrtok(NULL, ":"); + } + pEntry = MacTableLookup(pAd, mac_addr); + if (pEntry != NULL) + Aid = pEntry->wcid; + } else { + Aid = (UINT8) simple_strtol(thisChar, 0, 16); + } + if (!VALID_WCID(Aid)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid)); + return TRUE; + } + break; + + case 1: /* Meausre Duration. */ + BcnReq.MeasureDuration = (UINT8) simple_strtol(thisChar, 0, 10); + break; + + case 2: /* Regulator Class */ + BcnReq.RegulatoryClass = (UINT8) simple_strtol(thisChar, 0, 10); + break; + + case 3: /* BSSID */ + if(strlen(thisChar) != 17) + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: invalid value BSSID.\n", __FUNCTION__)); + return TRUE; + } + + if(strlen(thisChar) == 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17 */ + { + RTMP_STRING *value; + for (Loop=0, value = rstrtok(thisChar,":"); value; value = rstrtok(NULL,":")) + { + if((strlen(value) != 2) || (!isxdigit(*value)) || (!isxdigit(*(value+1))) ) + return FALSE; /*Invalid */ + + AtoH(value, &BcnReq.Bssid[Loop++], 1); + } + + if(Loop != 6) + return TRUE; + } + break; + + case 4: /* SSID */ + BcnReq.pSsid = (PUINT8)thisChar; + BcnReq.SsidLen = strlen(thisChar); + break; + + case 5: /* measure channel */ + BcnReq.MeasureCh = (UINT8) simple_strtol(thisChar, 0, 10); + break; + + case 6: /* measure mode. */ + BcnReq.MeasureMode = (UINT8) simple_strtol(thisChar, 0, 10); + break; + case 7: /* regulatory class. */ + { + RTMP_STRING *RegClassString; + int RegClassIdx; + + RegClassIdx = 0; + while ((RegClassString = strsep((char **)&thisChar, "+")) != NULL) + { + BcnReq.ChRepRegulatoryClass[RegClassIdx] = + (UINT8) simple_strtol(RegClassString, 0, 10); + RegClassIdx++; + } + } + break; + case 8:{/* Channel Report List. */ + RTMP_STRING *ChIdString; + int ChId; + + ChId = 0; + + while ((ChIdString = strsep((char **)&thisChar, "#")) != NULL) { + BcnReq.ChRepList[ChId] = (UINT8) simple_strtol(ChIdString, 0, 10); + ChId++; + } + } + break; + case 9:/* report detail*/ + BcnReq.report_detail = (UINT8) simple_strtol(thisChar, 0, 10); + break; + case 10: {/* request ie */ + RTMP_STRING *req_ie_str; + + BcnReq.request_ie_num = 0; + + while ((req_ie_str = strsep((char **)&thisChar, "#")) != NULL) { + if (req_ie_str[0] == '\0') + break; + + BcnReq.request_ie[BcnReq.request_ie_num] = + (UINT8) simple_strtol(req_ie_str, 0, 10); + BcnReq.request_ie_num++; + } + + if (BcnReq.request_ie_num == 0) { + /*if request ie list is empty, add SSID ie to it*/ + BcnReq.request_ie_num = 1; + BcnReq.request_ie[0] = 0; + } + } + break; + } + ArgIdx++; + } + + if (ArgIdx < 7 || ArgIdx > 11) + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: invalid args (%d).\n", __FUNCTION__, ArgIdx)); + DBGPRINT(RT_DEBUG_ERROR, + ("eg: iwpriv ra0 set BcnReq=-------\n")); + DBGPRINT(RT_DEBUG_ERROR, + ("eg: iwpriv ra0 set BcnReq=1!50!12!FF:FF:FF:FF:FF:FF!WiFi1!255!1!32+1!1#6#36#48\n")); + return TRUE; + } + + + BcnReq.BcnReqCapFlag.field.ReportCondition = TRUE; + /* Add MeasureMode Sanity check of peer STA */ + if (VALID_UCAST_ENTRY_WCID(Aid)) { + PMAC_TABLE_ENTRY pEntry = &pAd->MacTab.Content[Aid]; + + if (!pEntry) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pEntry is NULL!\n", __func__)); + return FALSE; + } + + switch (BcnReq.MeasureMode) { + case RRM_BCN_REQ_MODE_PASSIVE: + if (!IS_RRM_BEACON_PASSIVE_MEASURE(pEntry)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: invalid Measure Mode. %d, Peer STA Support(PASS:%d, ACT:%d, TAB:%d)!\n", + __func__, BcnReq.MeasureMode, IS_RRM_BEACON_PASSIVE_MEASURE(pEntry), + IS_RRM_BEACON_MEASURE(pEntry), IS_RRM_BEACON_TABLE_MEASURE(pEntry))); + /* return TRUE; */ + } + break; + + case RRM_BCN_REQ_MODE_ACTIVE: + if (!IS_RRM_BEACON_MEASURE(pEntry)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: invalid Measure Mode. %d, Peer STA Support(PASS:%d, ACT:%d, TAB:%d)!\n", + __func__, BcnReq.MeasureMode, IS_RRM_BEACON_PASSIVE_MEASURE(pEntry), + IS_RRM_BEACON_MEASURE(pEntry), IS_RRM_BEACON_TABLE_MEASURE(pEntry))); + /* return TRUE; */ + } + break; + + case RRM_BCN_REQ_MODE_BCNTAB: + if (!IS_RRM_BEACON_TABLE_MEASURE(pEntry)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: invalid Measure Mode. %d, Peer STA Support(PASS:%d, ACT:%d, TAB:%d)!\n", + __func__, BcnReq.MeasureMode, IS_RRM_BEACON_PASSIVE_MEASURE(pEntry), + IS_RRM_BEACON_MEASURE(pEntry), IS_RRM_BEACON_TABLE_MEASURE(pEntry))); + /* return TRUE; */ + } + break; + + default: + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: invalid Measure Mode. %d\n", __func__, BcnReq.MeasureMode)); + /* return TRUE; */ + } + break; + } + } + if (BcnReq.MeasureCh == 255) + BcnReq.BcnReqCapFlag.field.ChannelRep = TRUE; + else + BcnReq.BcnReqCapFlag.field.ChannelRep = FALSE; + BcnReq.RandInt = bcn_rand_int; + RRM_EnqueueBcnReq(pAd, Aid, ifIndex, &BcnReq); + + return TRUE; +} + +INT Set_LinkMeasureReq_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex = pObj->ioctl_if; + UINT Aid = 1; + + Aid = simple_strtol(arg, 0, 10); + RRM_EnqueueLinkMeasureReq(pAd, Aid, ifIndex); + + return TRUE; +} + +INT Set_TxStreamMeasureReq_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex = pObj->ioctl_if; + UINT Aid = 1; + UINT ArgIdx; + RTMP_STRING *thisChar; + + RRM_MLME_TRANSMIT_REQ_INFO TransmitReq; + PMAC_TABLE_ENTRY pMacEntry; + + ArgIdx = 0; + NdisZeroMemory(&TransmitReq, sizeof(RRM_MLME_TRANSMIT_REQ_INFO)); + + while ((thisChar = strsep((char **)&arg, "-")) != NULL) + { + switch(ArgIdx) + { + case 0: /* Aid. */ + Aid = (UINT8) simple_strtol(thisChar, 0, 10); + if (!VALID_WCID(Aid)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, Aid)); + return TRUE; + } + break; + + case 1: /* DurationMandotory. */ + TransmitReq.bDurationMandatory = + ((UINT16)simple_strtol(thisChar, 0, 10) > 0 ? TRUE : FALSE); + break; + + case 2: /* Measure Duration */ + TransmitReq.MeasureDuration = (UINT16)simple_strtol(thisChar, 0, 10); + break; + + case 3: /* TID */ + TransmitReq.Tid = (UINT8) simple_strtol(thisChar, 0, 10); + break; + + case 4: /* Bin 0 Range */ + TransmitReq.BinRange = (UINT8) simple_strtol(thisChar, 0, 10); + break; + + case 5: /* Averange Condition */ + TransmitReq.ArvCondition = + ((UINT8) simple_strtol(thisChar, 0, 10)) > 0 ? 1 : 0; + break; + + case 6: /* Consecutive Condition */ + TransmitReq.ConsecutiveCondition = + ((UINT8) simple_strtol(thisChar, 0, 10)) > 0 ? 1 : 0; + break; + + case 7: /* Delay Condition */ + TransmitReq.DelayCondition = + ((UINT8) simple_strtol(thisChar, 0, 10)) > 0 ? 1 : 0; + break; + + case 8: /* Averange Error Threshold */ + TransmitReq.AvrErrorThreshold = + (UINT8) simple_strtol(thisChar, 0, 10); + break; + + case 9: /* Consecutive Error Threshold */ + TransmitReq.ConsecutiveErrorThreshold = + (UINT8) simple_strtol(thisChar, 0, 10); + break; + + case 10: /* Delay Threshold */ + TransmitReq.DelayThreshold = + (UINT8) simple_strtol(thisChar, 0, 10); + break; + + case 11: /* Measure counter */ + TransmitReq.MeasureCnt = + (UINT8) simple_strtol(thisChar, 0, 10); + + break; + + case 12: /* Trigger time out */ + TransmitReq.TriggerTimeout = + (UINT8) simple_strtol(thisChar, 0, 10); + break; + + } + ArgIdx++; + } + + if ((ArgIdx != 13) && (ArgIdx != 5)) + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: invalid args (%d).\n", __FUNCTION__, ArgIdx)); + DBGPRINT(RT_DEBUG_ERROR, + ("eg: iwpriv ra0 set txreq=----[--------]\n")); + return TRUE; + } + + if (ArgIdx == 5) + TransmitReq.bTriggerReport = 0; + else + TransmitReq.bTriggerReport = 1; + + pMacEntry = &pAd->MacTab.Content[Aid]; + DBGPRINT(RT_DEBUG_ERROR, ("%s::Aid=%d, PeerMac=%02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, Aid, pMacEntry->Addr[0], pMacEntry->Addr[1], + pMacEntry->Addr[2], pMacEntry->Addr[3], pMacEntry->Addr[4], pMacEntry->Addr[5])); + + DBGPRINT(RT_DEBUG_ERROR, ("Duration=%d, Tid=%d, Bin 0 Range=%d\n", + TransmitReq.MeasureDuration, TransmitReq.Tid, TransmitReq.BinRange)); + + DBGPRINT(RT_DEBUG_ERROR, ("ArvCondition=%d, ConsecutiveCondition=%d, DelayCondition=%d\n", + TransmitReq.ArvCondition, TransmitReq.ConsecutiveCondition, TransmitReq.DelayCondition)); + + DBGPRINT(RT_DEBUG_ERROR, ("AvrErrorThreshold=%d, ConsecutiveErrorThreshold=%d\n", + TransmitReq.AvrErrorThreshold, TransmitReq.ConsecutiveErrorThreshold)); + + DBGPRINT(RT_DEBUG_ERROR, ("DelayThreshold=%d\n", TransmitReq.DelayThreshold)); + + DBGPRINT(RT_DEBUG_ERROR, ("MeasureCnt=%d, TriggerTimeout=%d\n", + TransmitReq.MeasureCnt, TransmitReq.TriggerTimeout)); + + RRM_EnqueueTxStreamMeasureReq(pAd, Aid, ifIndex, &TransmitReq); + + return TRUE; +} + +INT Set_RRM_Selftest_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT Cmd = 1; + + PMAC_TABLE_ENTRY pEntry; + UCHAR StaAddr[MAC_ADDR_LEN] = {0x00,0x0c,0x43,0x00,0x00,0x00}; + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[0/*pEntry->func_tb_idx*/].wdev; + + Cmd = simple_strtol(arg, 0, 10); + + switch(Cmd) + { + case 1: /* insert a STA for RRM Beacon Report request testing. */ + pEntry = MacTableInsertEntry(pAd, StaAddr, wdev, ENTRY_CLIENT, OPMODE_AP, TRUE); + pEntry->Sst = SST_ASSOC; + pEntry->CapabilityInfo |= RRM_CAP_BIT; + pEntry->RrmEnCap.field.BeaconActiveMeasureCap = 1; + break; + } + return TRUE; +} + +INT RRM_InfoDisplay_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT loop; + + for (loop = 0; loop < pAd->ApCfg.BssidNum; loop++) + { + DBGPRINT(RT_DEBUG_OFF, ("%d: bDot11kRRMEnable=%d\n", + loop, pAd->ApCfg.MBSSID[loop].RrmCfg.bDot11kRRMEnable)); + } + + DBGPRINT(RT_DEBUG_OFF, ("Country Code=%s\n", + pAd->CommonCfg.CountryCode)); + + DBGPRINT(RT_DEBUG_OFF, ("Power Constraint=%d\n", + pAd->CommonCfg.PwrConstraint)); + + DBGPRINT(RT_DEBUG_OFF, ("Regulator Class=")); + for (loop = 0; loop < MAX_NUM_OF_REGULATORY_CLASS; loop++) + { + if (pAd->CommonCfg.RegulatoryClass[loop] == 0) + break; + + DBGPRINT(RT_DEBUG_OFF, ("%d ", + pAd->CommonCfg.RegulatoryClass[loop])); + } + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("Regulator TxPowerPercentage=%ld\n", + pAd->CommonCfg.TxPowerPercentage)); + return TRUE; +} + +VOID RRM_CfgInit( + IN PRTMP_ADAPTER pAd) +{ + INT loop; + PRRM_CONFIG pRrmCfg; + + for (loop = 0; loop < MAX_MBSSID_NUM(pAd); loop++) + { + pRrmCfg = &pAd->ApCfg.MBSSID[loop].RrmCfg; + pRrmCfg->QuietCB.QuietPeriod = RRM_DEFAULT_QUIET_PERIOD; + pRrmCfg->QuietCB.QuietDuration = RRM_DEFAULT_QUIET_DURATION; + pRrmCfg->QuietCB.QuietOffset = RRM_DEFAULT_QUIET_OFFSET; + + RTMPInitTimer(pAd, &pRrmCfg->QuietCB.QuietOffsetTimer, GET_TIMER_FUNCTION(RRM_QuietOffsetTimeout), pAd, FALSE); + RTMPInitTimer(pAd, &pRrmCfg->QuietCB.QuietTimer, GET_TIMER_FUNCTION(RRM_QuietTimeout), pAd, FALSE); + + pRrmCfg->QuietCB.QuietState = RRM_QUIET_IDLE; + pRrmCfg->QuietCB.CurAid = 1; + pRrmCfg->bDot11kRRMNeighborRepTSFEnable = FALSE; + } + + return; +} + +VOID RRM_QuietUpdata( + IN PRTMP_ADAPTER pAd) +{ + INT loop; + PRRM_CONFIG pRrmCfg; + + BSS_STRUCT *mbss; + struct wifi_dev *wdev; + for (loop = 0; loop < pAd->ApCfg.BssidNum; loop++) + { + mbss = &pAd->ApCfg.MBSSID[loop]; + wdev = &mbss->wdev; + + if ((wdev->if_dev == NULL) || ((wdev->if_dev != NULL) && + !(RTMP_OS_NETDEV_STATE_RUNNING(wdev->if_dev)))) + { + /* the interface is down */ + continue; + } + + + pRrmCfg = &pAd->ApCfg.MBSSID[loop].RrmCfg; + if (pRrmCfg->bDot11kRRMEnable != TRUE) + continue; + + if (pRrmCfg->QuietCB.QuietCnt == pRrmCfg->QuietCB.QuietPeriod) + { + /* issue Bcn Report Request to STAs supported RRM-Bcn Report. */ + /* Voice-enterpise doesn't require it in testing-event3 so remove it. */ + /*RRM_BcnReortQuery(pAd, loop, pRrmCfg); */ + } + + if ((pRrmCfg->QuietCB.QuietCnt == 0) + && (pRrmCfg->QuietCB.QuietState == RRM_QUIET_IDLE)) + { + if (pRrmCfg->QuietCB.QuietOffset != 0) + { + /* Start QuietOffsetTimer. */ + RTMPSetTimer(&pRrmCfg->QuietCB.QuietOffsetTimer, + pRrmCfg->QuietCB.QuietOffset); + } + else + { + /* Start Quiet Timer. */ + pRrmCfg->QuietCB.QuietState = RRM_QUIET_SILENT; + + RTMPSetTimer(&pRrmCfg->QuietCB.QuietTimer, + pRrmCfg->QuietCB.QuietDuration); + } + } + + RRM_QUIET_CNT_DEC(pRrmCfg->QuietCB.QuietCnt, pRrmCfg->QuietCB.QuietPeriod); + } + return; +} + +VOID RRM_PeerNeighborReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; + PUCHAR pFramePtr = pFr->Octet; + PMAC_TABLE_ENTRY pEntry; + UINT8 DialogToken; + PCHAR pSsid = NULL; + CHAR ssidbuf[MAX_LEN_OF_SSID+1]; + + UINT8 SsidLen = 0; + PMEASURE_REQ_ENTRY pMeasure_Entry = NULL; + PNET_DEV NetDev = NULL; + UINT32 FrameLen = 0; + UINT8 NRReqToken = 0, APIndex = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s::\n", __FUNCTION__)); + + pEntry = MacTableLookup(pAd, pFr->Hdr.Addr2); + if (!pEntry || (pEntry->Sst != SST_ASSOC)) + return; + + /*whether the up-layer or driver handle the request*/ + if (pAd->ApCfg.HandleNRReqbyUplayer) { + /*send event to the up-layer */ + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) { + if (MAC_ADDR_EQUAL(pFr->Hdr.Addr3, pAd->ApCfg.MBSSID[APIndex].wdev.bssid)) { + NetDev = pAd->ApCfg.MBSSID[APIndex].wdev.if_dev; + break; + } + } + if (NetDev == NULL) { + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("no valid NetDev! BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pFr->Hdr.Addr3))); + return; + } + /* skip Category and action code. */ + pFramePtr += 2; + NdisMoveMemory(&NRReqToken, pFramePtr, 1); + pMeasure_Entry = MeasureReqInsert(pAd, NRReqToken); + RTMP_SEM_LOCK(&pAd->CommonCfg.MeasureReqTabLock); + pMeasure_Entry->skip_time_check = TRUE; + pMeasure_Entry->CurrentState = WAIT_NR_RSP; + pMeasure_Entry->Priv = pAd; + pMeasure_Entry->ControlIndex = APIndex; + memcpy(pMeasure_Entry->StaMac, pEntry->Addr, MAC_ADDR_LEN); + RTMPInitTimer(pAd, &pMeasure_Entry->WaitNRRspTimer, + GET_TIMER_FUNCTION(WaitNRRspTimeout), pMeasure_Entry, FALSE); + RTMP_SEM_UNLOCK(&pAd->CommonCfg.MeasureReqTabLock); + + FrameLen = Elem->MsgLen - sizeof(HEADER_802_11) - 2; + wext_send_nr_req_event(NetDev, pFr->Hdr.Addr2, pFramePtr, FrameLen); + + RTMPSetTimer(&pMeasure_Entry->WaitNRRspTimer, NR_RSP_TIMEOUT_VALUE); + } else { + if (RRM_PeerNeighborReqSanity(pAd, Elem->Msg, Elem->MsgLen, &DialogToken, &pSsid, &SsidLen)) { + DBGPRINT(RT_DEBUG_TRACE, ("DialogToken=%x\n", DialogToken)); + snprintf(ssidbuf, sizeof(ssidbuf), "%s", pSsid); + ssidbuf[SsidLen] = '\0'; + + DBGPRINT(RT_DEBUG_TRACE, ("pSsid=%s\n", /*pSsid*/ssidbuf)); + DBGPRINT(RT_DEBUG_TRACE, ("SsidLen=%d\n", SsidLen)); + RRM_EnqueueNeighborRep(pAd, pEntry, DialogToken, pSsid, SsidLen); + } + } + return; +} + +VOID RRM_BeaconReportHandler( + IN PRTMP_ADAPTER pAd, + IN struct wifi_dev *wdev, + IN PRRM_BEACON_REP_INFO pBcnRepInfo, + IN LONG Length, + IN PMEASURE_REQ_ENTRY pDialogEntry +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + , + IN UCHAR *Snr +#endif +) +{ + CHAR Rssi; + USHORT LenVIE = 0; + NDIS_802_11_VARIABLE_IEs *pVIE = NULL; + UCHAR VarIE[MAX_VIE_LEN]; + ULONG Idx = BSS_NOT_FOUND; + LONG RemainLen = Length; + PRRM_BEACON_REP_INFO pBcnRep; + PUINT8 ptr; + RRM_BEACON_REP_INFO_FIELD BcnReqInfoField; + UINT32 Ptsf; + BCN_IE_LIST *ie_list = NULL; + PNET_DEV NetDev = NULL; + BOOLEAN bFrameBody = FALSE; + + os_alloc_mem(NULL, (UCHAR **)&ie_list, sizeof(BCN_IE_LIST)); + if (ie_list == NULL) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Alloc ie_list failed!\n", __FUNCTION__)); + return; + } + NdisZeroMemory(ie_list, sizeof(BCN_IE_LIST)); + + ptr = (PUINT8)pBcnRepInfo; + + pBcnRep = (PRRM_BEACON_REP_INFO)ptr; +#ifdef RT_BIG_ENDIAN + pBcnRep->ActualMeasureStartTime = le2cpu64(pBcnRep->ActualMeasureStartTime); + pBcnRep->MeasureDuration = le2cpu16(pBcnRep->MeasureDuration); + pBcnRep->ParentTSF = le2cpu32(pBcnRep->ParentTSF); +#endif + /* send Beacon Response to up-layer */ + NetDev = pAd->ApCfg.MBSSID[pDialogEntry->ControlIndex].wdev.if_dev; + wext_send_bcn_rsp_event(NetDev, pDialogEntry->StaMac, + ptr, sizeof(*pBcnRepInfo), pDialogEntry->DialogToken); + + Ptsf = pBcnRep->ParentTSF; + BcnReqInfoField.word = pBcnRep->RepFrameInfo; + + DBGPRINT(RT_DEBUG_TRACE, ("%s:: ReqClass=%d, Channel=%d\n", + __FUNCTION__, pBcnRep->RegulatoryClass, pBcnRep->ChNumber)); + + DBGPRINT(RT_DEBUG_TRACE, ("Bssid=%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pBcnRep->Bssid))); + + Rssi = pBcnRep->RCPI + pAd->BbpRssiToDbmDelta; + + RemainLen -= sizeof(RRM_BEACON_REP_INFO); + ptr += sizeof(RRM_BEACON_REP_INFO); + + /* check option sub element IE. */ + while (RemainLen > 0) + { + PRRM_SUBFRAME_INFO pRrmSubFrame; + pRrmSubFrame = (PRRM_SUBFRAME_INFO)ptr; + + switch(pRrmSubFrame->SubId) + { + case 1: + if (BcnReqInfoField.field.ReportFrameType == 0) + { + /* Init Variable IE structure */ + pVIE = (PNDIS_802_11_VARIABLE_IEs) VarIE; + pVIE->Length = 0; + + bFrameBody = PeerBeaconAndProbeRspSanity(pAd, + pRrmSubFrame->Oct, + pRrmSubFrame->Length, + pBcnRep->ChNumber, + ie_list, + &LenVIE, + pVIE, + FALSE, + TRUE); + } + break; + + case 221: + DBGPRINT(RT_DEBUG_TRACE, ("%s:: SubIe: ID=%x, Len=%d\n", + __FUNCTION__, pRrmSubFrame->SubId, pRrmSubFrame->Length)); + break; + } + + RemainLen -= (pRrmSubFrame->Length + 2); + ptr += (pRrmSubFrame->Length + 2); + + /* avoid infinite loop. */ + if (pRrmSubFrame->Length == 0) + break; + } + + if (NdisEqualMemory(pBcnRep->Bssid, ie_list->Bssid, MAC_ADDR_LEN) == FALSE) { + DBGPRINT(RT_DEBUG_WARN, ("%s():BcnReq->BSSID not equal ie_list->Bssid!\n", __FUNCTION__)); + if (NdisEqualMemory(ie_list->Bssid, ZERO_MAC_ADDR, MAC_ADDR_LEN)) { + COPY_MAC_ADDR(&ie_list->Addr2[0], pBcnRep->Bssid); + COPY_MAC_ADDR(&ie_list->Bssid[0], pBcnRep->Bssid); + } + } + + if (ie_list->Channel == 0) + ie_list->Channel = pBcnRep->ChNumber; + +#ifdef AP_SCAN_SUPPORT + if (bFrameBody) + { + + ie_list->FromBcnReport = TRUE; + + Idx = BssTableSetEntry(pAd, &pAd->ScanTab, ie_list, Rssi, LenVIE, pVIE +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + , + Snr[0], + Snr[1] +#endif + ); + if (Idx != BSS_NOT_FOUND) { + BSS_ENTRY *pBssEntry = &pAd->ScanTab.BssEntry[Idx]; + + NdisMoveMemory(pBssEntry->PTSF, (PUCHAR)&Ptsf, 4); + pBssEntry->RegulatoryClass = pBcnRep->RegulatoryClass; + pBssEntry->CondensedPhyType = BcnReqInfoField.field.CondensePhyType; + pBssEntry->RSNI = pBcnRep->RSNI; +#ifdef MBO_SUPPORT + /* update this entry to daemon */ + MboIndicateOneNRtoDaemonByBssEntry(pAd, wdev, pBssEntry); +#endif + DBGPRINT(RT_DEBUG_TRACE, + ("%s():RegulatoryClass=%d, CondensedPhyType=%d, ", + __func__, pBssEntry->RegulatoryClass, pBssEntry->CondensedPhyType)); + DBGPRINT(RT_DEBUG_TRACE, ("BSSID=%02x:%02x:%02x:%02x:%02x:%02x, RSNI=%d\n", + PRINT_MAC(pBssEntry->Bssid), pBssEntry->RSNI)); + } + } +#endif /* AP_SCAN_SUPPORT */ + if (ie_list != NULL) + os_free_mem(NULL, ie_list); + + return; +} + +VOID RRM_PeerMeasureRepAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; + PUCHAR pFramePtr = pFr->Octet; + ULONG MsgLen = Elem->MsgLen; + PMEASURE_REQ_ENTRY pDialogEntry = NULL; + PMAC_TABLE_ENTRY pEntry; + UINT8 DialogToken; + BOOLEAN Cancelled; + PNET_DEV NetDev = NULL; +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + UCHAR Snr[2]; + + Snr[0] = Elem->Snr0; + Snr[1] = Elem->Snr1; + + Snr[0] = ConvertToSnr(pAd, Snr[0]); + Snr[1] = ConvertToSnr(pAd, Snr[1]); +#endif + + DBGPRINT(RT_DEBUG_TRACE, ("%s::\n", __FUNCTION__)); + + /* skip Category and action code. */ + pFramePtr += 2; + MsgLen -= 2; + + /* get DialogToken. */ + NdisMoveMemory(&DialogToken, pFramePtr, 1); + pFramePtr += 1; + MsgLen -= 1; + + /* + Not a autonomous measure report (non zero DialogToken). + check the dialog token field. + drop it if the dialog token doesn't match. + */ + if (DialogToken != 0) { + DBGPRINT(RT_DEBUG_TRACE, + ("DialogToken is non-zere, check DialogToken!\n")); + + pDialogEntry = MeasureReqLookUp(pAd, DialogToken); + if (!pDialogEntry) { + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("DialogToken invalid(%d)!", DialogToken)); + return; + } + RTMPCancelTimer(&pDialogEntry->WaitBCNRepTimer, &Cancelled); + RTMPReleaseTimer(&pDialogEntry->WaitBCNRepTimer, &Cancelled); + } else { + if (pFramePtr[2] != 0) { + DBGPRINT(RT_DEBUG_TRACE, + ("DialogToken is zere, MeasurementToken is non-zero, check MeasurementToken!\n")); + + pDialogEntry = MeasureReqLookUp(pAd, pFramePtr[2]); + if (!pDialogEntry) { + DBGPRINT(RT_DEBUG_ERROR, + ("MeasurementToken invalid(%d)!", pFramePtr[2])); + return; + } + RTMPCancelTimer(&pDialogEntry->WaitBCNRepTimer, &Cancelled); + RTMPReleaseTimer(&pDialogEntry->WaitBCNRepTimer, &Cancelled); + } else { + DBGPRINT(RT_DEBUG_ERROR, + ("Both DialogToken and MeasurementToken are zero, drop this packet!\n")); + return; + } + } + + do + { + PEID_STRUCT eid_ptr; + MEASURE_REPORT_MODE ReportMode; + UINT8 ReportType; + PRRM_BEACON_REP_INFO pMeasureRep; + + /* Is the STA associated. Dorp the Measure report if it's not. */ + pEntry = MacTableLookup(pAd, pFr->Hdr.Addr2); + if (!pEntry || (pEntry->Sst != SST_ASSOC) || !pEntry->wdev) + break; + + + eid_ptr = (PEID_STRUCT)pFramePtr; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) + { + switch (eid_ptr->Eid) { + case IE_MEASUREMENT_REPORT: + { + LONG BcnRepLen = (LONG)eid_ptr->Len - 3; + + NdisMoveMemory(&ReportMode, eid_ptr->Octet + 1, 1); + NdisMoveMemory(&ReportType, eid_ptr->Octet + 2, 1); + pMeasureRep = (PVOID)(eid_ptr->Octet + 3); + if (BcnRepLen) { + if (ReportType == RRM_MEASURE_SUBTYPE_BEACON) + RRM_BeaconReportHandler(pAd, pEntry->wdev, pMeasureRep, + BcnRepLen, pDialogEntry +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + , Snr +#endif + ); +#if defined(WAPP_SUPPORT) + wapp_send_bcn_report(pAd, pEntry, eid_ptr->Octet + 3, BcnRepLen); +#endif + } else { + if (ReportMode.field.Refused) { + DBGPRINT(RT_DEBUG_TRACE, + ("STA refuse to do mesurement with type(%d)", + ReportType)); + } else if (ReportMode.field.Incapable) { + DBGPRINT(RT_DEBUG_TRACE, + ("STA do not support mesurement with type(%d)", + ReportType)); + } else if (ReportMode.field.Late) { + DBGPRINT(RT_DEBUG_TRACE, + ("the request to do mesurement with type(%d) is too late", + ReportType)); + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("STA has no beacon report(%02x:%02x:%02x:%02x:%02x:%02x) info to report", + PRINT_MAC(pFr->Hdr.Addr2))); + } + /* send Beacon Response to up-layer */ + NetDev = pAd->ApCfg.MBSSID[pDialogEntry->ControlIndex].wdev.if_dev; + wext_send_bcn_rsp_event(NetDev, pDialogEntry->StaMac, + (PUCHAR)eid_ptr->Octet, 3, DialogToken); + } + } + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } +#if defined(WAPP_SUPPORT) + wapp_send_bcn_report_complete(pAd, pEntry); +#endif + } while(FALSE); + MeasureReqDelete(pAd, pDialogEntry->DialogToken); +} + + +int rrm_MsgHandle(PRTMP_ADAPTER pAd, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + p_rrm_command_t p_rrm_command = NULL; + int status = NDIS_STATUS_FAILURE; + + os_alloc_mem(NULL, (UCHAR **)&p_rrm_command, wrq->u.data.length); + if (p_rrm_command == NULL) { + DBGPRINT(RT_DEBUG_TRACE, ("!!!(%s) : no memory!!!\n", __func__)); + return NDIS_STATUS_FAILURE; + } + + copy_from_user(p_rrm_command, wrq->u.data.pointer, wrq->u.data.length); + + switch (p_rrm_command->command_id) { + case OID_802_11_RRM_CMD_ENABLE: + if (p_rrm_command->command_len == 0x1) { + status = Set_Dot11kRRM_Enable(pAd, p_rrm_command->command_body[0]); + } else { + DBGPRINT(RT_DEBUG_TRACE, ("Unexpected command len (%d)", p_rrm_command->command_len)); + status = NDIS_STATUS_FAILURE; + } + break; + + case OID_802_11_RRM_CMD_CAP: + if (p_rrm_command->command_len == 0x8) { + status = set_rrm_capabilities(pAd, p_rrm_command->command_body); + } else { + DBGPRINT(RT_DEBUG_TRACE, ("Unexpected command len (%d)", p_rrm_command->command_len)); + status = NDIS_STATUS_FAILURE; + } + break; + /*this cmd is used to compose beacon request frame by the up-layer raw data */ + case OID_802_11_RRM_CMD_SEND_BEACON_REQ: + status = rrm_send_beacon_req(pAd, + (p_bcn_req_data_t)p_rrm_command->command_body, + p_rrm_command->command_len); + break; + /*this cmd is used to compose beacon request frame by the up-layer parameters*/ + case OID_802_11_RRM_CMD_SET_BEACON_REQ_PARAM: + status = rrm_send_beacon_req_param(pAd, + (p_bcn_req_info)p_rrm_command->command_body, + p_rrm_command->command_len); + break; + /*this cmd is used to compose neighbor report frame by the up-layer raw data*/ + case OID_802_11_RRM_CMD_SEND_NEIGHBOR_REPORT: + status = rrm_send_nr_rsp_ie(pAd, + (p_nr_rsp_data_t)p_rrm_command->command_body, + p_rrm_command->command_len); + break; + /*this cmd is used to compose neighbor report frame by the up-layer parameters*/ + case OID_802_11_RRM_CMD_SET_NEIGHBOR_REPORT_PARAM: + status = rrm_send_nr_rsp_param(pAd, + (p_rrm_nrrsp_info_custom_t)p_rrm_command->command_body, + p_rrm_command->command_len); + break; + /*this cmd is used to config whether the driver or the up-layer handle the neighbor report request*/ + case OID_802_11_RRM_CMD_HANDLE_NEIGHBOR_REQUEST_BY_DAEMON: + status = rrm_set_handle_nr_req_flag(pAd, p_rrm_command->command_body[0]); + break; + } + os_free_mem(NULL, p_rrm_command); + return status; +} + + +int Set_Dot11kRRM_Enable(RTMP_ADAPTER *pAd, UINT8 enable) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex = pObj->ioctl_if; + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[ifIndex]; + + if (ifIndex >= pAd->ApCfg.BssidNum) { + DBGPRINT(RT_DEBUG_TRACE, ("Unknown If index (%d)", ifIndex)); + return NDIS_STATUS_FAILURE; + } + + pMbss->RrmCfg.bDot11kRRMEnable = (BOOLEAN)(enable) == 0 ? FALSE : TRUE; + + if (pMbss->RrmCfg.bDot11kRRMEnable == TRUE) + pMbss->CapabilityInfo |= RRM_CAP_BIT; + else + pMbss->CapabilityInfo &= ~RRM_CAP_BIT; + + APUpdateCapabilityAndErpIe(pAd); + APUpdateBeaconFrame(pAd, ifIndex); + return NDIS_STATUS_SUCCESS; +} + +int set_rrm_capabilities(RTMP_ADAPTER *pAd, UINT8 *rrm_capabilities) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + UCHAR ifIndex = pObj->ioctl_if; + BSS_STRUCT *pMbss; + PRRM_CONFIG pRrmCfg; + + if (ifIndex >= pAd->ApCfg.BssidNum) { + DBGPRINT(RT_DEBUG_OFF, ("Unknown If index (%d)", ifIndex)); + return NDIS_STATUS_FAILURE; + } + + pMbss = &pAd->ApCfg.MBSSID[ifIndex]; + pRrmCfg = &pMbss->RrmCfg; + NdisCopyMemory((void *)&pRrmCfg->rrm_capabilities, (void *)rrm_capabilities, sizeof(RRM_EN_CAP_IE)); + + pRrmCfg->rrm_capabilities.word &= pRrmCfg->max_rrm_capabilities.word; + + if (pMbss->RrmCfg.bDot11kRRMEnable == TRUE) + APUpdateBeaconFrame(pAd, ifIndex); + + return NDIS_STATUS_SUCCESS; +} + +int rrm_send_beacon_req( + RTMP_ADAPTER *pAd, + p_bcn_req_data_t p_bcn_req_data, + UINT32 bcn_req_len) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + PUCHAR pBuf = NULL; + PBCN_EVENT_DATA Event; + PMEASURE_REQ_ENTRY pEntry = NULL; + BSS_STRUCT *pMbss = NULL; + UINT32 EventLen = 0, Len = 0; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + UCHAR IfIdx = pObj->ioctl_if; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s\n", __func__)); + + /* check the AP supports 11k or not */ + pMbss = &pAd->ApCfg.MBSSID[IfIdx]; + if (pMbss->RrmCfg.bDot11kRRMEnable == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() AP(%02x:%02x:%02x:%02x:%02x:%02x) not support rrm\n", + __func__, PRINT_MAC(pMbss->wdev.bssid))); + return NDIS_STATUS_FAILURE; + } + + Len = sizeof(*p_bcn_req_data) + p_bcn_req_data->bcn_req_len; + if (bcn_req_len != Len) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s, bcn req len check failed len1=%d, len2=%d\n", + __func__, bcn_req_len, Len)); + return NDIS_STATUS_FAILURE; + } + + /*send bcn req msg into mlme*/ + EventLen = sizeof(*Event) + bcn_req_len; + os_alloc_mem(NULL, (UCHAR **)&pBuf, EventLen); + if (!pBuf) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s, allocate event memory failed\n", __func__)); + return NDIS_STATUS_RESOURCES; + } + NdisZeroMemory(pBuf, EventLen); + + /*insert bcn req token into measure table*/ + if (p_bcn_req_data->dialog_token == 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s, invalid MesureReq Token(0)!\n", + __func__)); + os_free_mem(NULL, pBuf); + return NDIS_STATUS_FAILURE; + } + pEntry = MeasureReqInsert(pAd, p_bcn_req_data->dialog_token); + if (!pEntry) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s, Fail to Insert MesureReq Token(%d)!\n", + __func__, p_bcn_req_data->dialog_token)); + os_free_mem(NULL, pBuf); + return NDIS_STATUS_FAILURE; + } + pEntry->skip_time_check = TRUE; + pEntry->CurrentState = WAIT_BCN_REQ; + pEntry->Priv = pAd; + pEntry->ControlIndex = IfIdx; + + Event = (BCN_EVENT_DATA *)pBuf; + Event->ControlIndex = IfIdx; + Event->MeasureReqToken = p_bcn_req_data->dialog_token; + RTMPMoveMemory(Event->stamac, p_bcn_req_data->peer_address, MAC_ADDR_LEN); + Event->DataLen = bcn_req_len; + NdisMoveMemory(Event->Data, p_bcn_req_data, bcn_req_len); + + if (MlmeEnqueue(pAd, BCN_STATE_MACHINE, BCN_REQ_RAW, EventLen, pBuf, 0) + == FALSE) { + NStatus = NDIS_STATUS_FAILURE; + MeasureReqDelete(pAd, p_bcn_req_data->dialog_token); + } + + /*free memory*/ + os_free_mem(NULL, pBuf); + return NStatus; +} + +INT rrm_send_beacon_req_param( + IN PRTMP_ADAPTER pAd, + IN p_bcn_req_info pBcnReq, + IN UINT32 BcnReqLen) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + BSS_STRUCT *pMbss = NULL; + PMEASURE_REQ_ENTRY pEntry = NULL; + PBCN_EVENT_DATA Event = NULL; + UINT32 Len = 0; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + PUCHAR pBuf = NULL; + UINT8 IfIdx = pObj->ioctl_if; + UINT8 MeasureReqToken = 0; + static UINT8 k; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s\n", __func__)); + + /* check the AP supports 11k or not */ + pMbss = &pAd->ApCfg.MBSSID[IfIdx]; + if (pMbss->RrmCfg.bDot11kRRMEnable == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() rrm off\n", __func__)); + return NDIS_STATUS_FAILURE; + } + + if (BcnReqLen != sizeof(*pBcnReq)) { + DBGPRINT(RT_DEBUG_ERROR, ("%s, bcn req len check failed len1=%d, len2=%d\n", + __func__, BcnReqLen, sizeof(*pBcnReq))); + return NDIS_STATUS_FAILURE; + } + + /*send bcn req msg into mlme*/ + Len = sizeof(*Event) + BcnReqLen; + os_alloc_mem(NULL, (UCHAR **)&pBuf, Len); + if (!pBuf) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s, allocate event memory failed\n", __func__)); + return NDIS_STATUS_RESOURCES; + } + NdisZeroMemory(pBuf, Len); + + /*insert bcn req token into measure table*/ + k++; + if (k == 0) + k = 1; + MeasureReqToken = k; + pEntry = MeasureReqInsert(pAd, MeasureReqToken); + if (!pEntry) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s, Fail to Insert MesureReq Token(%d)!\n", + __func__, MeasureReqToken)); + os_free_mem(NULL, pBuf); + return NDIS_STATUS_FAILURE; + } + pEntry->skip_time_check = TRUE; + pEntry->CurrentState = WAIT_BCN_REQ; + pEntry->Priv = pAd; + pEntry->ControlIndex = IfIdx; + COPY_MAC_ADDR(pEntry->StaMac, pBcnReq->peer_address); + + Event = (PBCN_EVENT_DATA)pBuf; + Event->ControlIndex = IfIdx; + Event->MeasureReqToken = MeasureReqToken; + RTMPMoveMemory(Event->stamac, pBcnReq->peer_address, MAC_ADDR_LEN); + Event->DataLen = BcnReqLen; + NdisMoveMemory(Event->Data, pBcnReq, BcnReqLen); + + if (MlmeEnqueue(pAd, BCN_STATE_MACHINE, BCN_REQ, Len, pBuf, 0) == FALSE) { + NStatus = NDIS_STATUS_FAILURE; + MeasureReqDelete(pAd, MeasureReqToken); + } + + /*free memory*/ + os_free_mem(NULL, pBuf); + return NStatus; +} + + + +void RRM_measurement_report_to_host(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; + PUCHAR pFramePtr = pFr->Octet; + ULONG MsgLen = Elem->MsgLen; + UINT8 DialogToken; + p_rrm_event_t p_rrm_event; + p_bcn_rsp_data_t p_bcn_rsp_data; + + MsgLen -= sizeof(HEADER_802_11); + + /* skip category and action code. */ + pFramePtr += 2; + MsgLen -= 2; + DialogToken = *pFramePtr; + + pFramePtr += 1; + MsgLen -= 1; + os_alloc_mem(NULL, (UCHAR **)&p_rrm_event, sizeof(rrm_event_t) + sizeof(bcn_rsp_data_t) + MsgLen); + if (p_rrm_event == NULL) { + DBGPRINT(RT_DEBUG_OFF, ("!!!(%s) : no memory!!!\n", __func__)); + return; + } + + p_rrm_event->event_id = 1; + p_rrm_event->event_len = sizeof(bcn_rsp_data_t) + MsgLen; + p_bcn_rsp_data = (p_bcn_rsp_data_t)(&p_rrm_event->event_body[0]); + p_bcn_rsp_data->dialog_token = DialogToken; + p_bcn_rsp_data->ifindex = 1; + p_bcn_rsp_data->bcn_rsp_len = MsgLen; + COPY_MAC_ADDR(p_bcn_rsp_data->peer_address, pFr->Hdr.Addr2); + memcpy(&p_bcn_rsp_data->bcn_rsp[0], pFramePtr, MsgLen); + RtmpOSWrielessEventSend( + pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_802_11_RRM_EVENT, + NULL, + (UCHAR *) p_rrm_event, + sizeof(rrm_event_t) + sizeof(bcn_rsp_data_t) + MsgLen); + os_free_mem(NULL, p_rrm_event); +} + + +/* +* this function is used to compose the neighbor report response frame with +* parameters sent by the up-layer +* return value: error reason or success +*/ +int rrm_send_nr_rsp_param(RTMP_ADAPTER *pAd, + p_rrm_nrrsp_info_custom_t p_nr_rsp_data, UINT32 nr_rsp_data_len) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + PNR_EVENT_DATA Event = NULL; + BSS_STRUCT *pMbss = NULL; + PUCHAR pBuf = NULL; + UINT32 Len = 0; + UCHAR ifIndex = pObj->ioctl_if; + + pMbss = &pAd->ApCfg.MBSSID[ifIndex]; + if (pMbss->RrmCfg.bDot11kRRMEnable == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() rrm off\n", __func__)); + return NDIS_STATUS_FAILURE; + } + + Len = MAC_ADDR_LEN + 2 + + p_nr_rsp_data->nrresp_info_count * sizeof(struct nr_info); + if (nr_rsp_data_len != Len) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() length check failed nr_rsp_data_len=%d, Len=%d\n", + __func__, nr_rsp_data_len, Len)); + return NDIS_STATUS_FAILURE; + } + + if (p_nr_rsp_data->nrresp_info_count > MAX_CANDIDATE_NUM) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s the num of candidate(%d) excceed %d\n", __func__, + p_nr_rsp_data->nrresp_info_count, MAX_CANDIDATE_NUM)); + return NDIS_STATUS_FAILURE; + } + + /*send msg to mlme*/ + Len = sizeof(*Event) + nr_rsp_data_len; + os_alloc_mem(NULL, (UCHAR **)&pBuf, Len); + if (!pBuf) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s():allocate event memory failed\n", __func__)); + return NDIS_STATUS_RESOURCES; + } + NdisZeroMemory(pBuf, Len); + Event = (PNR_EVENT_DATA)pBuf; + Event->ControlIndex = ifIndex; + Event->MeasureReqToken = p_nr_rsp_data->dialogtoken; + NdisMoveMemory(Event->stamac, p_nr_rsp_data->peer_address, + MAC_ADDR_LEN); + Event->DataLen = nr_rsp_data_len; + NdisMoveMemory(Event->Data, (PUCHAR)p_nr_rsp_data, nr_rsp_data_len); + MlmeEnqueue(pAd, NEIGHBOR_STATE_MACHINE, NR_RSP_PARAM, Len, pBuf, 0); + + /*free the memory*/ + os_free_mem(NULL, pBuf); + + return NDIS_STATUS_SUCCESS; +} + + +/*this function is used to check the validity of customer parameters*/ +int check_rrm_nrrsp_custom_params( + RTMP_ADAPTER *pAd, + p_rrm_nrrsp_info_custom_t p_nr_rsp_data, + UINT32 nr_rsp_data_len) +{ + struct nr_info *pinfo = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + UINT32 Len = 0; + UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + RRM_EN_CAP_IE Zero_RrmEnCap; + + pEntry = MacTableLookup(pAd, p_nr_rsp_data->peer_address); + if (!pEntry || !((Ndis802_11AuthModeAutoSwitch >= + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.AuthMode) || + ((pEntry->WpaState == AS_PTKINITDONE) && + (pEntry->GTKState == REKEY_ESTABLISHED)))) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() STA(%02x:%02x:%02x:%02x:%02x:%02x) not associates with AP!\n", + __func__, PRINT_MAC(p_nr_rsp_data->peer_address))); + goto error; + } + + memset((PUCHAR)&Zero_RrmEnCap, 0, sizeof(Zero_RrmEnCap)); + if (!memcmp(&Zero_RrmEnCap, &pEntry->RrmEnCap, + sizeof(RRM_EN_CAP_IE))) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() STA(%02x:%02x:%02x:%02x:%02x:%02x) not support rrm\n", + __func__, PRINT_MAC(p_nr_rsp_data->peer_address))); + goto error; + } + + if (p_nr_rsp_data->nrresp_info_count == 0) { + DBGPRINT(RT_DEBUG_WARN, + ("%s() nr count equals to 0; neighbor report response is meaningless\n", + __func__)); + return NDIS_STATUS_SUCCESS; + } + + Len = p_nr_rsp_data->nrresp_info_count * sizeof(struct nr_info); + pinfo = p_nr_rsp_data->nrresp_info; + +/* +* need check the validity of each neighbor report candidates +* check bssid field of each neighbor report candidates +*/ + while (Len > 0) { + if (MAC_ADDR_EQUAL(pinfo->bssid, ZERO_MAC_ADDR)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() bssid check failed\n", __func__)); + goto error; + } + if (pinfo->channum == 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() channel check failed\n", __func__)); + goto error; + } + + Len -= sizeof(struct nr_info); + pinfo++; + } + + return NDIS_STATUS_SUCCESS; + +error: + return NDIS_STATUS_FAILURE; +} + + + +void compose_rrm_nrrsp_ie(RTMP_ADAPTER *pAd, + PUCHAR nr_rsp_ie, PUINT32 p_ie_len, + struct nr_info *p_candidate_info, UINT8 cnt) +{ + UINT i = 0; + struct nr_info *p_info = p_candidate_info; + BOOLEAN nr_flag = FALSE; + ULONG bss_index = BSS_NOT_FOUND; + BSS_ENTRY *pBssEntry = NULL; + RRM_NEIGHBOR_REP_INFO NeighborRepInfo; + RRM_BSSID_INFO BssidInfo; + + for (i = 0; i < cnt; i++, p_info++) { +/* +* first, check if need get info from scan table to compose +* neighbor report response ie +*/ + if (!(p_info->phytype && + p_info->regclass && + p_info->capinfo && + p_info->is_ht && + p_info->is_vht && + p_info->mobility)) { + nr_flag = TRUE; + } +/* +* if nr_flag equals to TRUE, it means that the up-layer need driver to +* help with the build of neighbor report ie. so need find info to complete +* the ie from scan table matched by bssid. if do not find info in +* scan table, just skip this candidate +*/ + if (nr_flag) { + bss_index = + BssTableSearch(&pAd->ScanTab, p_info->bssid, p_info->channum); + if (bss_index == BSS_NOT_FOUND) { + DBGPRINT(RT_DEBUG_WARN, + ("%s() bss not found\n", __func__)); + continue; + } + pBssEntry = &pAd->ScanTab.BssEntry[bss_index]; + if (p_info->regclass == 0) + p_info->regclass = pBssEntry->RegulatoryClass; + if (p_info->capinfo == 0) + p_info->capinfo = pBssEntry->CapabilityInfo; + if (p_info->is_ht == 0) + p_info->is_ht = (pBssEntry->HtCapabilityLen != 0)?1:0; +#ifdef DOT11_VHT_AC + if (p_info->is_vht == 0) + p_info->is_vht = (pBssEntry->vht_cap_len != 0)?1:0; +#endif /* DOT11_VHT_AC */ + if (p_info->is_ht == 0) + p_info->is_ht = (pBssEntry->HtCapabilityLen != 0)?1:0; + if (p_info->mobility == 0) + p_info->mobility = (pBssEntry->bHasMDIE)?1:0; + + if (pBssEntry->Channel > 14) { + if (pBssEntry->HtCapabilityLen != 0) { +#ifdef DOT11_VHT_AC + if (pBssEntry->vht_cap_len != 0) + pBssEntry->CondensedPhyType = 9; + else +#endif /* DOT11_VHT_AC */ + pBssEntry->CondensedPhyType = 7; + } else { /* OFDM case */ + pBssEntry->CondensedPhyType = 4; + } + } else { + if (pBssEntry->HtCapabilityLen != 0) /* HT case */ + pBssEntry->CondensedPhyType = 7; + else if (ERP_IS_NON_ERP_PRESENT(pBssEntry->Erp)) /* ERP case */ + pBssEntry->CondensedPhyType = 6; + else if (pBssEntry->SupRateLen > 4) /* OFDM case (1,2,5.5,11 for CCK 4 Rates) */ + pBssEntry->CondensedPhyType = 4; + /* no CCK's definition in spec. */ + } + if (p_info->phytype == 0) + p_info->phytype = pBssEntry->CondensedPhyType; + } + + /*compose neighbor report ie buffer*/ + BssidInfo.word = 0; + BssidInfo.field.APReachAble = + (p_info->ap_reachability == 0)?3:p_info->ap_reachability; + BssidInfo.field.Security = p_info->security; + BssidInfo.field.KeyScope = p_info->key_scope; + BssidInfo.field.SepctrumMng = (p_info->capinfo & (1 << 8))?1:0; + BssidInfo.field.Qos = (p_info->capinfo & (1 << 9))?1:0; + BssidInfo.field.APSD = (p_info->capinfo & (1 << 11))?1:0; + BssidInfo.field.RRM = (p_info->capinfo & RRM_CAP_BIT)?1:0; + BssidInfo.field.DelayBlockAck = (p_info->capinfo & (1 << 14))?1:0; + BssidInfo.field.ImmediateBA = (p_info->capinfo & (1 << 15))?1:0; + BssidInfo.field.MobilityDomain = p_info->mobility; + BssidInfo.field.HT = p_info->is_ht; +#ifdef DOT11_VHT_AC + BssidInfo.field.VHT = p_info->is_vht; +#endif /* DOT11_VHT_AC */ + COPY_MAC_ADDR(NeighborRepInfo.Bssid, p_info->bssid); + NeighborRepInfo.BssidInfo = cpu2le32(BssidInfo.word); + NeighborRepInfo.RegulatoryClass = p_info->regclass; + NeighborRepInfo.ChNum = p_info->channum; + NeighborRepInfo.PhyType = p_info->phytype; + + RRM_InsertNeighborRepIE_New(pAd, (nr_rsp_ie + *p_ie_len), (PULONG)p_ie_len, + sizeof(RRM_NEIGHBOR_REP_INFO), &NeighborRepInfo); + } + +} + + + +VOID send_nr_resp_toair( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PNR_EVENT_DATA Event = (PNR_EVENT_DATA)Elem->Msg; + PMEASURE_REQ_ENTRY pEntry = NULL; + PMAC_TABLE_ENTRY pMacEntry = NULL; + PUCHAR Buf = NULL; + PRRM_FRAME RRMFrame = NULL; + UINT32 FrameLen = 0, VarLen = Event->DataLen; + BOOLEAN Cancelled; + RRM_EN_CAP_IE Zero_RrmEnCap; + + /*check token*/ + pEntry = MeasureReqLookUp(pAd, Event->MeasureReqToken); + if (pEntry == NULL && Event->MeasureReqToken != 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() invalid token(%d)\n", __func__, + Event->MeasureReqToken)); + return; + } + + pMacEntry = MacTableLookup(pAd, Event->stamac); + if (!pMacEntry || !((Ndis802_11AuthModeAutoSwitch >= + pAd->ApCfg.MBSSID[pMacEntry->func_tb_idx].wdev.AuthMode) || + ((pMacEntry->WpaState == AS_PTKINITDONE) && + (pMacEntry->GTKState == REKEY_ESTABLISHED)))) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() STA(%02x:%02x:%02x:%02x:%02x:%02x not associates with AP!\n", + __func__, PRINT_MAC(Event->stamac))); + return; + } + + memset((PUCHAR)&Zero_RrmEnCap, 0, sizeof(Zero_RrmEnCap)); + if (!memcmp((PUCHAR)&Zero_RrmEnCap, (PUCHAR)&pMacEntry->RrmEnCap, + sizeof(RRM_EN_CAP_IE))) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() STA(%02x:%02x:%02x:%02x:%02x:%02x) not support rrm\n", + __func__, PRINT_MAC(Event->stamac))); + return; + } + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*RRMFrame) + VarLen); + if (!Buf) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s Not available memory for neighbor report frame\n", + __func__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*RRMFrame) + VarLen); + RRMFrame = (PRRM_FRAME)Buf; + ActHeaderInit(pAd, &RRMFrame->Hdr, Event->stamac, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid); + FrameLen = sizeof(HEADER_802_11); + RRMFrame->Category = CATEGORY_RM; + FrameLen += 1; + RRMFrame->u.NR_RSP.Action = RRM_NEIGHTBOR_RSP; + FrameLen += 1; + RRMFrame->u.NR_RSP.DialogToken = Event->MeasureReqToken; + FrameLen += 1; + NdisMoveMemory(RRMFrame->u.NR_RSP.Variable, Event->Data, + Event->DataLen); + FrameLen += Event->DataLen; + + /*receive neighbor report response; cancel timer*/ + if (Event->MeasureReqToken) { + RTMPCancelTimer(&pEntry->WaitNRRspTimer, &Cancelled); + RTMPReleaseTimer(&pEntry->WaitNRRspTimer, &Cancelled); + } + MeasureReqDelete(pAd, Event->MeasureReqToken); + MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | QID_AC_BE), Buf, FrameLen); + os_free_mem(NULL, Buf); + +} + + + +VOID send_nr_rsp_param_toair( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PNR_EVENT_DATA Event = (PNR_EVENT_DATA)Elem->Msg; + p_rrm_nrrsp_info_custom_t p_nr_rsp_data = NULL; + PMEASURE_REQ_ENTRY pEntry = NULL; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + UINT32 nr_rsp_data_len = Event->DataLen; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + BOOLEAN Cancelled; + HEADER_802_11 ActHdr; + + p_nr_rsp_data = (p_rrm_nrrsp_info_custom_t)Event->Data; + + /*check token*/ + pEntry = MeasureReqLookUp(pAd, p_nr_rsp_data->dialogtoken); + if (pEntry == NULL && p_nr_rsp_data->dialogtoken != 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() invalid token(%d)\n", __func__, + p_nr_rsp_data->dialogtoken)); + return; + } + /*check the other parameters*/ + NStatus = check_rrm_nrrsp_custom_params(pAd, p_nr_rsp_data, nr_rsp_data_len); + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() check customer params failed\n", __func__)); + return; + } + + /*allocate a buffer prepare for Neighbor report IE*/ + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() allocate memory for neighbor report frame failed\n", + __func__)); + return; + } + /*compose 80211 header*/ + ActHeaderInit(pAd, &ActHdr, p_nr_rsp_data->peer_address, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid); + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(ActHdr)); + FrameLen = sizeof(ActHdr); + + /*compose the Neighbor report header + * category, action and token + */ + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, + CATEGORY_RM, RRM_NEIGHTBOR_RSP); + InsertDialogToken(pAd, (pOutBuffer + FrameLen), + &FrameLen, p_nr_rsp_data->dialogtoken); + + hex_dump("nr rsp header", pOutBuffer, FrameLen); + /*compose the Neighbor report ie*/ + compose_rrm_nrrsp_ie(pAd, pOutBuffer, (PUINT32)&FrameLen, + p_nr_rsp_data->nrresp_info, + p_nr_rsp_data->nrresp_info_count); + hex_dump("nr rsp payload", pOutBuffer, + FrameLen); + /*receive neighbor report response; + * cancel timer + */ + if (p_nr_rsp_data->dialogtoken) { + RTMPCancelTimer(&pEntry->WaitNRRspTimer, &Cancelled); + RTMPReleaseTimer(&pEntry->WaitNRRspTimer, &Cancelled); + } + MeasureReqDelete(pAd, p_nr_rsp_data->dialogtoken); + MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | QID_AC_BE), pOutBuffer, FrameLen); + os_free_mem(NULL, pOutBuffer); + +} + + + +int rrm_send_nr_rsp_ie(RTMP_ADAPTER *pAd, + p_nr_rsp_data_t p_nr_rsp_data, + UINT32 nr_rsp_data_len) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + BSS_STRUCT *pMbss = NULL; + PNR_EVENT_DATA Event = NULL; + PUCHAR pBuf = NULL; + UINT32 FrameLen = p_nr_rsp_data->nr_rsp_len; + UINT32 Len = 0; + UINT8 ifIndex = pObj->ioctl_if; + + + pMbss = &pAd->ApCfg.MBSSID[ifIndex]; + if (pMbss->RrmCfg.bDot11kRRMEnable == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() rrm off\n", __func__)); + return NDIS_STATUS_FAILURE; + } + + Len = sizeof(*p_nr_rsp_data) + FrameLen; + if (nr_rsp_data_len != Len) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() length check failed nr_rsp_data_len=%d, Len=%d\n", + __func__, nr_rsp_data_len, Len)); + return NDIS_STATUS_FAILURE; + } + + if (FrameLen > 1000) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s nr rsp ie len(%d) is too long", __func__, FrameLen)); + return NDIS_STATUS_FAILURE; + } + + /*send a msg into mlme*/ + Len = sizeof(*Event) + FrameLen; + os_alloc_mem(NULL, (UCHAR **)&pBuf, Len); + if (!pBuf) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() allocate event memory failed\n", __func__)); + return NDIS_STATUS_RESOURCES; + } + NdisZeroMemory(pBuf, Len); + Event = (PNR_EVENT_DATA)pBuf; + Event->ControlIndex = ifIndex; + Event->MeasureReqToken = p_nr_rsp_data->dialog_token; + NdisMoveMemory(Event->stamac, p_nr_rsp_data->peer_address, + MAC_ADDR_LEN); + Event->DataLen = FrameLen; + NdisMoveMemory(Event->Data, p_nr_rsp_data->nr_rsp, FrameLen); + MlmeEnqueue(pAd, NEIGHBOR_STATE_MACHINE, NR_RSP, Len, pBuf, 0); + + /*free the memory*/ + os_free_mem(NULL, pBuf); + + return NDIS_STATUS_SUCCESS; +} + + + +/*this func is used to config whether the driver or +* the up-layer handle the neighbor report request + */ +int rrm_set_handle_nr_req_flag(RTMP_ADAPTER *pAd, UINT8 by_daemon) +{ + pAd->ApCfg.HandleNRReqbyUplayer = (by_daemon == 0) ? 0:1; + DBGPRINT(RT_DEBUG_TRACE, + ("%s, HandleNRReqbyUplayer(%d)!\n", + __func__, pAd->ApCfg.HandleNRReqbyUplayer)); + + return NDIS_STATUS_SUCCESS; +} + + + +void wext_send_nr_req_event(PNET_DEV net_dev, + const char *peer_mac_addr, + const char *nr_req, + UINT16 nr_req_len) +{ + struct nr_req_data *data = NULL; + p_rrm_event_t event_data = NULL; + UINT32 buflen = 0; + UCHAR *buf; + + buflen = sizeof(*event_data) + sizeof(*data) + nr_req_len; + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + event_data = (p_rrm_event_t)buf; + event_data->event_id = OID_802_11_RRM_EVT_NEIGHBOR_REQUEST; + event_data->event_len = sizeof(*data) + nr_req_len; + + data = (struct nr_req_data *)event_data->event_body; + data->ifindex = RtmpOsGetNetIfIndex(net_dev); + memcpy(data->peer_mac_addr, peer_mac_addr, 6); + data->nr_req_len = nr_req_len; + memcpy(data->nr_req, nr_req, nr_req_len); + + RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_RRM_EVENT, NULL, (PUCHAR)buf, buflen); + + os_free_mem(NULL, buf); +} + + + +/*used to check if the up-layer does not send neighbor report response in time*/ +VOID NRRspTimeout( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PNR_EVENT_DATA Event = (PNR_EVENT_DATA)Elem->Msg; + PMEASURE_REQ_ENTRY pEntry = NULL; + UINT8 MeasureReqToken = Event->MeasureReqToken; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s StaMac(%02x:%02x:%02x:%02x:%02x:%02x), MeasureReqToken=%d\n", + __func__, PRINT_MAC(Event->stamac), MeasureReqToken)); + + pEntry = MeasureReqLookUp(pAd, MeasureReqToken); + + if (!pEntry) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s nr response entry not founded\n", __func__)); + return; + } + + RTMPReleaseTimer(&pEntry->WaitNRRspTimer, &Cancelled); + /*delete measure entry to avoid the full condition of measure table*/ + MeasureReqDelete(pAd, MeasureReqToken); +} + + + +VOID WaitNRRspTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PMEASURE_REQ_ENTRY pEntry = (PMEASURE_REQ_ENTRY)FunctionContext; + PRTMP_ADAPTER pAd; + UINT32 Len = 0; + NR_EVENT_DATA Event; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __func__)); + + if (!pEntry) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s: MeasureReq Entry doesn't exist\n", __func__)); + return; + } + + pAd = pEntry->Priv; + NdisZeroMemory(&Event, sizeof(Event)); + Event.ControlIndex = pEntry->ControlIndex; + Event.MeasureReqToken = pEntry->DialogToken; + memcpy(Event.stamac, pEntry->StaMac, MAC_ADDR_LEN); + Event.DataLen = 0; + Len = sizeof(Event); + + MlmeEnqueue(pAd, NEIGHBOR_STATE_MACHINE, NR_RSP_TIMEOUT, Len, &Event, 0); + +} +BUILD_TIMER_FUNCTION(WaitNRRspTimeout); + + +enum NR_STATE NRPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PNR_EVENT_DATA Event = (PNR_EVENT_DATA)Elem->Msg; + PMEASURE_REQ_ENTRY pEntry = NULL; + UINT8 MeasureReqToken = Event->MeasureReqToken; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s, MeasureReqToken=%d!\n", __func__, MeasureReqToken)); + + pEntry = MeasureReqLookUp(pAd, MeasureReqToken); + + if (pEntry != NULL) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s, CurrentState=%d!\n", __func__, pEntry->CurrentState)); + return pEntry->CurrentState; + } else { + DBGPRINT(RT_DEBUG_ERROR, + ("%s, invalid MeasureReqToken!\n", __func__)); + + return NR_UNKNOWN; + } +} + +int check_rrm_BcnReq_custom_params( + RTMP_ADAPTER *pAd, + p_bcn_req_info p_beacon_req) +{ + PMAC_TABLE_ENTRY pEntry = NULL; + UCHAR ZERO_OpClassList[OP_LEN] = {0}; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s()\n", __func__)); + + /* the the peer is connected or not */ + pEntry = MacTableLookup(pAd, p_beacon_req->peer_address); + if (!pEntry || !((Ndis802_11AuthModeAutoSwitch >= + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.AuthMode) || + ((pEntry->WpaState == AS_PTKINITDONE) && + (pEntry->GTKState == REKEY_ESTABLISHED)))) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() STA(%02x:%02x:%02x:%02x:%02x:%02x) not associates with AP!\n", + __func__, PRINT_MAC(p_beacon_req->peer_address))); + goto error; + } + + /* check the peer supports 11k or not */ + if (!(pEntry->RrmEnCap.field.BeaconPassiveMeasureCap || + pEntry->RrmEnCap.field.BeaconActiveMeasureCap)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() STA(%02x:%02x:%02x:%02x:%02x:%02x) not support beacon report!\n", + __func__, PRINT_MAC(p_beacon_req->peer_address))); + goto error; + } + + + /* operating class; only mandatory when channel is set to 0*/ + if (p_beacon_req->channum == 0 && p_beacon_req->regclass == 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() regclass cannot set to 0 when channel is set to 0\n", + __func__)); + goto error; + } + + if (p_beacon_req->channum == 255) { + if (p_beacon_req->op_class_len == 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() op class must be set when channel is set to 255!\n", + __func__)); + goto error; + } + if (!RTMPCompareMemory(p_beacon_req->op_class_list, + ZERO_OpClassList, OP_LEN)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() op class list is invalid!\n", __func__)); + goto error; + } + } + + return NDIS_STATUS_SUCCESS; + +error: + return NDIS_STATUS_FAILURE; +} + + + +VOID set_rrm_BcnReq_optional_params( + RTMP_ADAPTER *pAd, + p_bcn_req_info p_beacon_req) +{ + PMAC_TABLE_ENTRY pEntry = NULL; + UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0}; + UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + UCHAR DefaultRequest[13] = {0, /* SSID */ + 1, /* Support Rate*/ + 45, /* HT IE*/ + 48, /* RSN IE */ + 50, /* Extended Support Rate*/ + 54, /* Mobility Domain. */ + 61, /* HT ADD*/ + 70, /* RRM Capabilities. */ + 127, /* Ext Cap*/ + 191, /* VHT 1*/ + 192, /* VHT 2*/ + 195, /* VHT 3*/ + 221 /*vendor ie*/ + }; + + pEntry = MacTableLookup(pAd, p_beacon_req->peer_address); + + if (p_beacon_req->channum != 0 && p_beacon_req->channum != 255) { + if (p_beacon_req->regclass == 0) { + p_beacon_req->regclass = + get_regulatory_class(pAd, p_beacon_req->channum); + DBGPRINT(RT_DEBUG_TRACE, + ("%s() set optional regclass = %d\n", + __func__, p_beacon_req->regclass)); + } + } + if (p_beacon_req->duration == 0) { + p_beacon_req->duration = 20; + DBGPRINT(RT_DEBUG_TRACE, + ("%s() set optional duration = %d\n", + __func__, p_beacon_req->duration)); + } + if (!RTMPCompareMemory(p_beacon_req->bssid, ZERO_MAC_ADDR, MAC_ADDR_LEN)) { + RTMPMoveMemory(p_beacon_req->bssid, BROADCAST_ADDR, MAC_ADDR_LEN); + DBGPRINT(RT_DEBUG_TRACE, + ("%s() set optional bssid = %02x:%02x:%02x:%02x:%02x:%02x\n", + __func__, PRINT_MAC(p_beacon_req->bssid))); + } + if (p_beacon_req->mode == 0) { + if (pEntry != NULL && pEntry->RrmEnCap.field.BeaconActiveMeasureCap) + p_beacon_req->mode = 1; + else + p_beacon_req->mode = 0; + } else { + p_beacon_req->mode--; + } + DBGPRINT(RT_DEBUG_TRACE, + ("%s() set optional mode = %d!\n", + __func__, p_beacon_req->mode)); + + if (p_beacon_req->timeout == 0) { + p_beacon_req->timeout = BCN_REP_TIMEOUT_VALUE; + DBGPRINT(RT_DEBUG_TRACE, + ("%s() set optional timeout = %d!\n", + __func__, p_beacon_req->timeout)); + } + + if (p_beacon_req->detail == 0) { + p_beacon_req->detail = 1; + DBGPRINT(RT_DEBUG_TRACE, + ("%s() set optional detail = %d\n", + __func__, p_beacon_req->detail)); + p_beacon_req->request_len = 13; + RTMPMoveMemory(p_beacon_req->request, DefaultRequest, 13); + } else { + p_beacon_req->detail--; + } +} + + + +void compose_rrm_BcnReq_ie(RTMP_ADAPTER *pAd, + PUCHAR beacon_req_ie, PUINT32 beacon_req_ie_len, + p_bcn_req_info p_beacon_req, UINT8 measure_req_token, UCHAR ifidx) +{ + PUCHAR pOutBuffer = beacon_req_ie; + ULONG FrameLen = 0, HeaderLen = 0; + UINT32 FramelenTmp = 0; + UINT16 Repetitions = 0; + UINT8 MeasureReqType = RRM_MEASURE_SUBTYPE_BEACON; + UINT8 TotalLen = 0, idx = 0; + MEASURE_REQ_MODE MeasureReqMode; + RRM_BEACON_REQ_INFO BcnReq; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s\n", __func__)); + /* + * Action header has a field to indicate total length of packet + * but the total length is unknown untial whole packet completd. + * So skip the action here and fill it late. + * 1. skip Catgore (1 octect), Action(1 octect). + * 2. skip dailog token (1 octect). + * 3. skip Num Of Repetitions field (2 octects) + * 3. skip MeasureReqIE (2 + sizeof(MEASURE_REQ_INFO)). + */ + FrameLen = 7 + sizeof(MEASURE_REQ_INFO); + TotalLen = sizeof(MEASURE_REQ_INFO); + /*Insert Beacon Req IE*/ + BcnReq.RegulatoryClass = p_beacon_req->regclass; + BcnReq.ChNumber = p_beacon_req->channum; + BcnReq.RandomInterval = cpu2le16(p_beacon_req->random_ivl); + BcnReq.MeasureDuration = cpu2le16(p_beacon_req->duration); + BcnReq.MeasureMode = p_beacon_req->mode; + COPY_MAC_ADDR(BcnReq.Bssid, p_beacon_req->bssid); + RRM_InsertBcnReqIE(pAd, (pOutBuffer+FrameLen), + &FrameLen, (PUCHAR)&BcnReq); + TotalLen += sizeof(RRM_BEACON_REQ_INFO); + DBGPRINT(RT_DEBUG_TRACE, + ("%s RegulatoryClass=%d ChNumber=%d RandomInterval=%d ", + __func__, BcnReq.RegulatoryClass, BcnReq.ChNumber, + BcnReq.RandomInterval)); + DBGPRINT(RT_DEBUG_TRACE, + ("MeasureDuration=%d MeasureMode=%d ", + BcnReq.MeasureDuration, BcnReq.MeasureMode)); + DBGPRINT(RT_DEBUG_TRACE, + ("Bssid(%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(BcnReq.Bssid))); + + + /* inssert SSID sub field. + * Fix Voice Enterprise : Item V-E-4.3, + * case2 still need to include the SSID sub filed even SsidLen is 0 + */ + RRM_InsertBcnReqSsidSubIE(pAd, (pOutBuffer+FrameLen), + &FrameLen, (PUCHAR)p_beacon_req->req_ssid, p_beacon_req->req_ssid_len); + TotalLen += (p_beacon_req->req_ssid_len + 2); + + /* inssert beacon reporting information sub field. */ + RRM_InsertBcnReqRepCndSubIE(pAd, (pOutBuffer+FrameLen), + &FrameLen, p_beacon_req->rep_conditon, p_beacon_req->ref_value); + TotalLen += (2 + 2); + + /* inssert reporting detail sub field. */ + RRM_InsertBcnReqRepDetailSubIE(pAd, (pOutBuffer+FrameLen), + &FrameLen, p_beacon_req->detail); + TotalLen += (2 + 1); + + if (p_beacon_req->detail == 1) { + RRM_InsertRequestIE_NEW(pAd, (pOutBuffer+FrameLen), + &FrameLen, p_beacon_req->request, p_beacon_req->request_len); + TotalLen += (p_beacon_req->request_len + 2); + } + + /* inssert channel report sub field. */ + if (p_beacon_req->channum == 255) { + idx = 0; + while (p_beacon_req->op_class_list[idx] != 0) { + FramelenTmp = FrameLen; + InsertChannelRepIE(pAd, (pOutBuffer+FrameLen), &FrameLen, + (RTMP_STRING *)pAd->CommonCfg.CountryCode, + p_beacon_req->op_class_list[idx], p_beacon_req->ch_list); + TotalLen += (FrameLen - FramelenTmp); + idx++; + } + } + + if (TotalLen > 250) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() MeasureReq IE len > 255!\n", __func__)); + } + + /* Insert Action header here. */ + MeasureReqMode.word = 0; + Repetitions = p_beacon_req->num_rpt; + MakeMeasurementReqFrame(pAd, pOutBuffer, &HeaderLen, + TotalLen, CATEGORY_RM, RRM_MEASURE_REQ, measure_req_token, + MeasureReqMode.word, MeasureReqType, Repetitions); + + *beacon_req_ie_len = FrameLen; +} + + + +void wext_send_bcn_rsp_event(PNET_DEV net_dev, + PUCHAR peer_mac_addr, + PUCHAR bcn_rsp, + UINT32 bcn_rsp_len, + UINT8 dia_token) +{ + p_bcn_rsp_data_t data = NULL; + p_rrm_event_t event_data = NULL; + UINT32 buflen = 0; + UCHAR *buf; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s\n", __func__)); + + buflen = sizeof(*event_data) + sizeof(*data) + bcn_rsp_len; + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + event_data = (p_rrm_event_t)buf; + event_data->event_id = OID_802_11_RRM_EVT_BEACON_REPORT; + DBGPRINT(RT_DEBUG_TRACE, + ("%s event_data->event_id = %d\n", __func__, + event_data->event_id)); + event_data->event_len = sizeof(*data) + bcn_rsp_len; + + data = (p_bcn_rsp_data_t)event_data->event_body; + data->dialog_token = dia_token; + data->ifindex = RtmpOsGetNetIfIndex(net_dev); + memcpy(data->peer_address, peer_mac_addr, 6); + data->bcn_rsp_len = bcn_rsp_len; + memcpy(data->bcn_rsp, bcn_rsp, bcn_rsp_len); + + hex_dump("data in Driver", buf, buflen); + + RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_RRM_EVENT, NULL, (PUCHAR)buf, buflen); + + os_free_mem(NULL, buf); + +} + + +static VOID BcnRepTimeout( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PNET_DEV NetDev = NULL; + PMEASURE_REQ_ENTRY pEntry = NULL; + PBCN_EVENT_DATA Event = (BCN_EVENT_DATA *)Elem->Msg; + UINT8 MeasureReqToken = Event->MeasureReqToken; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s StaMac(%02x:%02x:%02x:%02x:%02x:%02x) MeasureReqToken=%d\n", + __func__, PRINT_MAC(Event->stamac), MeasureReqToken)); + + + pEntry = MeasureReqLookUp(pAd, MeasureReqToken); + if (!pEntry) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s Bcnreq entry not founded\n", __func__)); + return; + } + + RTMPReleaseTimer(&pEntry->WaitBCNRepTimer, &Cancelled); + MeasureReqDelete(pAd, MeasureReqToken); + + /* send Beacon Request timeout to up-layer */ + NetDev = pAd->ApCfg.MBSSID[pEntry->ControlIndex].wdev.if_dev; + if (NetDev == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("no valid NetDev! IfIndex=%d\n", pEntry->ControlIndex)); + return; + } + + wext_send_bcn_rsp_event(NetDev, Event->stamac, Event->Data, + 0, MeasureReqToken); +} + + + +VOID WaitPeerBCNRepTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PMEASURE_REQ_ENTRY pEntry = (PMEASURE_REQ_ENTRY)FunctionContext; + PRTMP_ADAPTER pAd = NULL; + UINT32 Len = 0; + BCN_EVENT_DATA Event; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s\n", __func__)); + + pAd = pEntry->Priv; + Len = sizeof(Event); + NdisZeroMemory((PUCHAR)&Event, Len); + Event.MeasureReqToken = pEntry->DialogToken; + RTMPMoveMemory(Event.stamac, pEntry->StaMac, MAC_ADDR_LEN); + Event.DataLen = 0; + + MlmeEnqueue(pAd, BCN_STATE_MACHINE, BCN_REP_TIMEOUT, + Len, (PUCHAR)&Event, 0); +} +BUILD_TIMER_FUNCTION(WaitPeerBCNRepTimeout); + + +static VOID SendBcnReqToAir_SetParam( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + BCN_EVENT_DATA *Event = (BCN_EVENT_DATA *)Elem->Msg; + p_bcn_req_info pBcnReq = (p_bcn_req_info)Event->Data; + PMEASURE_REQ_ENTRY pMeasureReqEntry = NULL; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + UINT32 FrameLen = 0, TmpLen = 0; + ULONG Timeout = 0; + UINT8 MeasureReqToken = Event->MeasureReqToken; + UINT8 IfIdx = Event->ControlIndex; + HEADER_802_11 ActHdr; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s()\n", __func__)); + + /*check the parameters*/ + NStatus = check_rrm_BcnReq_custom_params(pAd, pBcnReq); + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() check customer params failed\n", __func__)); + MeasureReqDelete(pAd, MeasureReqToken); + return; + } + + /*set the optional paratmeters when customer don't set*/ + set_rrm_BcnReq_optional_params(pAd, pBcnReq); + + /*compose the Beacon Request frame*/ + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s, MEMORY ALLOC Failed!!\n", __func__)); + MeasureReqDelete(pAd, MeasureReqToken); + return; + } + ActHeaderInit(pAd, &ActHdr, Event->stamac, + pAd->ApCfg.MBSSID[IfIdx].wdev.bssid, + pAd->ApCfg.MBSSID[IfIdx].wdev.bssid); + memcpy(pOutBuffer, (PUCHAR)&ActHdr, sizeof(ActHdr)); + FrameLen = sizeof(ActHdr); + + compose_rrm_BcnReq_ie(pAd, (pOutBuffer+FrameLen), &TmpLen, + pBcnReq, MeasureReqToken, IfIdx); + FrameLen += TmpLen; + + hex_dump("bcn req frame", pOutBuffer, FrameLen); + + MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | QID_AC_BE), pOutBuffer, FrameLen); + + pMeasureReqEntry = MeasureReqLookUp(pAd, MeasureReqToken); + if (pMeasureReqEntry == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() pMeasureReqEntry is NULL!\n", __func__)); + MlmeFreeMemory(pAd, pOutBuffer); + return; + } + pMeasureReqEntry->CurrentState = WAIT_BCN_REP; + Timeout = pBcnReq->timeout * 1000; + DBGPRINT(RT_DEBUG_TRACE, + ("%s() Timeout=%lds!\n", __func__, Timeout/1000)); + RTMPInitTimer(pAd, &pMeasureReqEntry->WaitBCNRepTimer, + GET_TIMER_FUNCTION(WaitPeerBCNRepTimeout), pMeasureReqEntry, FALSE); + RTMPSetTimer(&pMeasureReqEntry->WaitBCNRepTimer, Timeout); + + MlmeFreeMemory(pAd, pOutBuffer); + +} + + +static VOID SendBcnReqToAir_Raw( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PBCN_EVENT_DATA Event = (PBCN_EVENT_DATA)Elem->Msg; + PMEASURE_REQ_ENTRY pMeasureReqEntry = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + p_bcn_req_data_t p_bcn_req_data_raw = (p_bcn_req_data_t)Event->Data; + PUCHAR pbuf = NULL; + ULONG Timeout = 0, FrameLen = 0; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + UINT8 MeasureReqToken = Event->MeasureReqToken; + UINT8 IfIdx = Event->ControlIndex; + HEADER_802_11 ActHdr; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s()\n", __func__)); + + /* the the peer is connected or not */ + pEntry = MacTableLookup(pAd, p_bcn_req_data_raw->peer_address); + if (!pEntry || !((Ndis802_11AuthModeAutoSwitch >= + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.AuthMode) || + ((pEntry->WpaState == AS_PTKINITDONE) && + (pEntry->GTKState == REKEY_ESTABLISHED)))) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() STA(%02x:%02x:%02x:%02x:%02x:%02x) not associates with AP!\n", + __func__, PRINT_MAC(p_bcn_req_data_raw->peer_address))); + MeasureReqDelete(pAd, MeasureReqToken); + return; + } + + /* check the peer supports 11k or not */ + if (!(pEntry->RrmEnCap.field.BeaconPassiveMeasureCap || + pEntry->RrmEnCap.field.BeaconActiveMeasureCap)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() STA(%02x:%02x:%02x:%02x:%02x:%02x) does not support beacon report!\n", + __func__, PRINT_MAC(p_bcn_req_data_raw->peer_address))); + MeasureReqDelete(pAd, MeasureReqToken); + return; + } + + /*compose the Beacon Request frame*/ + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pbuf); + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s() allocate memory failed\n", __func__)); + MeasureReqDelete(pAd, MeasureReqToken); + return; + } + + ActHeaderInit(pAd, &ActHdr, p_bcn_req_data_raw->peer_address, + pAd->ApCfg.MBSSID[IfIdx].wdev.bssid, + pAd->ApCfg.MBSSID[IfIdx].wdev.bssid); + NdisMoveMemory(pbuf, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pbuf + FrameLen), &FrameLen, + MT2_PEER_RM_CATE, RRM_MEASURE_REQ); + InsertDialogToken(pAd, (pbuf + FrameLen), &FrameLen, + p_bcn_req_data_raw->dialog_token); + memcpy((pbuf + FrameLen), p_bcn_req_data_raw->bcn_req, + p_bcn_req_data_raw->bcn_req_len); + FrameLen += p_bcn_req_data_raw->bcn_req_len; + + MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | QID_AC_BE), + pbuf, FrameLen); + + pMeasureReqEntry = MeasureReqLookUp(pAd, MeasureReqToken); + if (pMeasureReqEntry == NULL) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() pMeasureReqEntry is NULL!\n", __func__)); + MlmeFreeMemory(pAd, pbuf); + return; + } + pMeasureReqEntry->CurrentState = WAIT_BCN_REP; + Timeout = BCN_REP_TIMEOUT_VALUE; + DBGPRINT(RT_DEBUG_TRACE, + ("%s() Timeout=%lds!\n", __func__, Timeout/1000)); + + RTMPInitTimer(pAd, &pMeasureReqEntry->WaitBCNRepTimer, + GET_TIMER_FUNCTION(WaitPeerBCNRepTimeout), pMeasureReqEntry, FALSE); + RTMPSetTimer(&pMeasureReqEntry->WaitBCNRepTimer, Timeout); + + MlmeFreeMemory(pAd, pbuf); + return; +} + +enum BCN_STATE BCNPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PBCN_EVENT_DATA Event = (PBCN_EVENT_DATA)Elem->Msg; + PMEASURE_REQ_ENTRY pEntry = NULL; + UINT8 MeasureReqToken = Event->MeasureReqToken; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s, MeasureReqToken=%d!\n", __func__, MeasureReqToken)); + + pEntry = MeasureReqLookUp(pAd, MeasureReqToken); + if (pEntry != NULL) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s, CurrentState=%d!\n", __func__, pEntry->CurrentState)); + return pEntry->CurrentState; + } else { + DBGPRINT(RT_DEBUG_TRACE, + ("%s, invalid MeasureReqToken!\n", __func__)); + return BCN_IDLE; + } +} + + + +VOID RRMBcnReqStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE * S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __func__)); + + StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_BCN_STATE, MAX_BCN_MSG, + (STATE_MACHINE_FUNC)Drop, BCN_IDLE, BCN_MACHINE_BASE); + +#ifdef CONFIG_AP_SUPPORT + StateMachineSetAction(S, WAIT_BCN_REQ, BCN_REQ, (STATE_MACHINE_FUNC)SendBcnReqToAir_SetParam); + StateMachineSetAction(S, WAIT_BCN_REQ, BCN_REQ_RAW, (STATE_MACHINE_FUNC)SendBcnReqToAir_Raw); + StateMachineSetAction(S, WAIT_BCN_REP, BCN_REP_TIMEOUT, (STATE_MACHINE_FUNC)BcnRepTimeout); +#endif /* CONFIG_AP_SUPPORT */ +} + + +VOID NRStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE * S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __func__)); + + StateMachineInit(S, (STATE_MACHINE_FUNC *)Trans, MAX_NR_STATE, MAX_NR_MSG, + (STATE_MACHINE_FUNC)Drop, NR_UNKNOWN, NR_MACHINE_BASE); + +#ifdef CONFIG_AP_SUPPORT + StateMachineSetAction(S, WAIT_NR_RSP, NR_RSP, (STATE_MACHINE_FUNC)send_nr_resp_toair); + StateMachineSetAction(S, WAIT_NR_RSP, NR_RSP_PARAM, (STATE_MACHINE_FUNC)send_nr_rsp_param_toair); + StateMachineSetAction(S, WAIT_NR_RSP, NR_RSP_TIMEOUT, (STATE_MACHINE_FUNC)NRRspTimeout); +#endif /* CONFIG_AP_SUPPORT */ +} + + +#endif /* DOT11K_RRM_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rrm_sanity.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rrm_sanity.c new file mode 100644 index 000000000..6cd9310a5 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rrm_sanity.c @@ -0,0 +1,147 @@ + +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2006, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + Abstract: + +***************************************************************************/ + +#ifdef DOT11K_RRM_SUPPORT + +#include "rt_config.h" + + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +BOOLEAN RRM_PeerNeighborReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT8 pDialogToken, + OUT PCHAR *pSsid, + OUT PUINT8 pSsidLen) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; + PUCHAR pFramePtr = Fr->Octet; + BOOLEAN result = FALSE; + PEID_STRUCT eid_ptr; + PMAC_TABLE_ENTRY pEntry; + + MsgLen -= sizeof(HEADER_802_11); + + /* skip category and action code. */ + pFramePtr += 2; + MsgLen -= 2; + + if (pDialogToken == NULL) + return result; + + pEntry = MacTableLookup(pAd, Fr->Hdr.Addr2); + if (pEntry == NULL) + return result; + if (pEntry->func_tb_idx > pAd->ApCfg.BssidNum) + return result; + *pSsid = pAd->ApCfg.MBSSID[pEntry->func_tb_idx].Ssid; + *pSsidLen = pAd->ApCfg.MBSSID[pEntry->func_tb_idx].SsidLen; + + result = TRUE; + NdisMoveMemory(pDialogToken, pFramePtr, 1); + pFramePtr += 1; + MsgLen -= 1; + + eid_ptr = (PEID_STRUCT)pFramePtr; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case RRM_NEIGHBOR_REQ_SSID_SUB_ID: + *pSsid = (PCHAR)eid_ptr->Octet; + *pSsidLen = eid_ptr->Len; + break; + + case RRM_NEIGHBOR_REQ_VENDOR_SUB_ID: + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return result; +} + + +BOOLEAN RRM_PeerMeasureReportSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT8 pDialogToken, + OUT PMEASURE_REPORT_INFO pMeasureReportInfo, + OUT PVOID *pMeasureRep) +{ + PFRAME_802_11 Fr = (PFRAME_802_11)pMsg; + PUCHAR pFramePtr = Fr->Octet; + BOOLEAN result = FALSE; + PEID_STRUCT eid_ptr; + + /* skip 802.11 header. */ + MsgLen -= sizeof(HEADER_802_11); + + /* skip category and action code. */ + pFramePtr += 2; + MsgLen -= 2; + + if (pMeasureReportInfo == NULL) + return result; + + NdisMoveMemory(pDialogToken, pFramePtr, 1); + pFramePtr += 1; + MsgLen -= 1; + + eid_ptr = (PEID_STRUCT)pFramePtr; + while (((UCHAR*)eid_ptr + eid_ptr->Len + 1) < ((PUCHAR)pFramePtr + MsgLen)) + { + switch(eid_ptr->Eid) + { + case IE_MEASUREMENT_REPORT: + NdisMoveMemory(&pMeasureReportInfo->Token, eid_ptr->Octet, 1); + NdisMoveMemory(&pMeasureReportInfo->ReportMode, eid_ptr->Octet + 1, 1); + NdisMoveMemory(&pMeasureReportInfo->ReportType, eid_ptr->Octet + 2, 1); + *pMeasureRep = (PVOID)(eid_ptr->Octet + 3); + result = TRUE; + break; + + default: + break; + } + eid_ptr = (PEID_STRUCT)((UCHAR*)eid_ptr + 2 + eid_ptr->Len); + } + + return result; +} + +#endif /* DOT11K_RRM_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rrm_tlv.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rrm_tlv.c new file mode 100644 index 000000000..0cafbc6cc --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rrm_tlv.c @@ -0,0 +1,941 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2006, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + Abstract: + +***************************************************************************/ + +#ifdef DOT11K_RRM_SUPPORT + +#include "rt_config.h" + +#define RTMP_INSERT_IE(_FRAMEBUFER, _TOTALFRAMELEN, _FRAMELEN, _FRAME) {\ + ULONG _TempLen; \ + MakeOutgoingFrame( (_FRAMEBUFER), &(_TempLen), \ + (_FRAMELEN), (_FRAME), \ + END_OF_ARGS); \ + *(_TOTALFRAMELEN) += (_TempLen); \ +} + + +VOID RRM_InsertBcnReqIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pBcnReq) +{ + RTMP_INSERT_IE(pFrameBuf, pFrameLen, sizeof(RRM_BEACON_REQ_INFO), pBcnReq); +} + +VOID RRM_InsertBcnReqSsidSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pSsid, + IN UINT8 SsidLen) +{ + ULONG TempLen; + UINT8 SubId = RRM_BCN_REQ_SUBID_SSID; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &SubId, + 1, &SsidLen, + SsidLen, (PUCHAR)pSsid, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; +} + +VOID RRM_InsertBcnReqRepCndSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 RepCnd, + IN UINT8 Threshold) +{ + ULONG TempLen; + UINT8 Len = 2; + UINT8 SubId = RRM_BCN_REQ_SUBID_BCN_REP_INFO; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &SubId, + 1, &Len, + 1, &RepCnd, + 1, &Threshold, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; +} + +VOID RRM_InsertBcnReqRepDetailSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Detail) +{ + ULONG TempLen; + UINT8 Len = 1; + UINT8 SubId = RRM_BCN_REQ_SUBID_RET_DETAIL; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &SubId, + 1, &Len, + 1, &Detail, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; +} + +/* + ========================================================================== + Description: + Insert RRM Enable Capabilitys IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + + Return : None. + ========================================================================== + */ +VOID RRM_InsertRRMEnCapIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN INT BssIdx) +{ + ULONG TempLen; + UINT8 Len = 5; + UINT8 ElementID = IE_RRM_EN_CAP; + RRM_EN_CAP_IE RrmEnCap; + BSS_STRUCT *pMBss = NULL; + + if (BssIdx < MAX_MBSSID_NUM(pAd)) + pMBss = &pAd->ApCfg.MBSSID[BssIdx]; + else + return; + + RrmEnCap.field.LinkMeasureCap = 1; + RrmEnCap.field.NeighborRepCap = 1; + RrmEnCap.field.ParallelMeasureCap = 0; + RrmEnCap.field.RepeatMeasureCap = 0; + RrmEnCap.field.BeaconPassiveMeasureCap = 1; + RrmEnCap.field.BeaconActiveMeasureCap = 1; + RrmEnCap.field.BeaconTabMeasureCap = 1; + RrmEnCap.field.BeaconMeasureReportCndCap = 1; + RrmEnCap.field.FrameMeasureCap = 0; + RrmEnCap.field.ChannelLoadMeasureCap = 0; + RrmEnCap.field.NoiseHistogramMeasureCap = 0; + RrmEnCap.field.StatisticMeasureCap = 0; + RrmEnCap.field.LCIMeasureCap = 0; + RrmEnCap.field.LCIAzimuthCap = 0; + RrmEnCap.field.TransmitStreamCap = 1; + RrmEnCap.field.TriggeredTransmitStreamCap = 1; + RrmEnCap.field.APChannelReportCap = 1; + RrmEnCap.field.RRMMibCap = 0; + RrmEnCap.field.OperatingChMaxMeasureDuration = 0; + RrmEnCap.field.NotOperatingChMaxMeasureDuration = 0; + RrmEnCap.field.MeasurePilotCap = 0; + RrmEnCap.field.MeasurePilotTxInfoCap = 0; + RrmEnCap.field.NeighReportTSFOffsetCap = + (pMBss->RrmCfg.bDot11kRRMNeighborRepTSFEnable) ? 1 : 0; + RrmEnCap.field.RCPIMeasureCap = 0; + RrmEnCap.field.RSNIMeasureCap = 0; + RrmEnCap.field.BssAvgAccessDelayCap = 0; + RrmEnCap.field.BssAvaiableAcmCap = + 0; + RrmEnCap.field.AntennaInfoCap = 0; + +#ifdef RT_BIG_ENDIAN + (*((UINT64 *)&RrmEnCap)) = cpu2le64(*((UINT64 *)&RrmEnCap)); +#endif + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &ElementID, + 1, &Len, + Len, (PUCHAR)&RrmEnCap.word, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +VOID RRM_InsertNeighborRepIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Len, + IN PUINT8 pBssid, + IN RRM_BSSID_INFO BssidInfo, + IN UINT8 RegClass, + IN UINT8 Channel, + IN UINT8 PhyType) +{ + ULONG TempLen; + UINT8 IEId = IE_RRM_NEIGHBOR_REP; + + RRM_NEIGHBOR_REP_INFO NeighborRepInfo; + + COPY_MAC_ADDR(NeighborRepInfo.Bssid, pBssid); + NeighborRepInfo.BssidInfo = BssidInfo.word; + NeighborRepInfo.RegulatoryClass = RegClass; + NeighborRepInfo.ChNum = Channel; + NeighborRepInfo.PhyType = PhyType; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &IEId, + 1, &Len, + sizeof(RRM_NEIGHBOR_REP_INFO), &NeighborRepInfo, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + + +VOID RRM_InsertNeighborRepIE_New( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Len, + IN RRM_PNEIGHBOR_REP_INFO pNeighborRepInfo) +{ + ULONG TempLen; + UINT8 IEId = IE_RRM_NEIGHBOR_REP; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &IEId, + 1, &Len, + sizeof(RRM_NEIGHBOR_REP_INFO), pNeighborRepInfo, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; +} + + +VOID RRM_InsertNeighborTSFOffsetSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT16 TSFOffset, + IN UINT16 BcnInterval) +{ + ULONG TempLen; + UINT8 Len = 4; + UINT8 SubId = RRM_NEIGHBOR_REP_TSF_INFO_SUB_ID; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &SubId, + 1, &Len, + 2, &TSFOffset, + 2, &BcnInterval, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; +} + +VOID RRM_InsertQuietIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 QuietCnt, + IN UINT8 QuietPeriod, + IN UINT8 QuietDuration, + IN UINT8 QuietOffset) +{ + ULONG TempLen; + UINT8 IEId = IE_QUIET; + QUIET_INFO QuietInfo; + UINT8 Len; + + QuietInfo.QuietCnt = QuietCnt; + QuietInfo.QuietPeriod = QuietPeriod; + QuietInfo.QuietDuration = cpu2le16(QuietDuration); + QuietInfo.QuietOffset = cpu2le16(QuietOffset); + Len = 6; + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &IEId, + 1, &Len, + Len, &QuietInfo, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +VOID RRM_InsertBssACDelayIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + ULONG TempLen; + UINT8 IEId = IE_BSS_AC_DELAY; + RRM_BSS_AC_DELAY_INFO AcDelayInfo; + UINT8 Len; + + Len = 4; + AcDelayInfo.BE_ACDelay = 255; + AcDelayInfo.BK_ACDelay = 255; + AcDelayInfo.VI_ACDelay = 255; + AcDelayInfo.VO_ACDelay = 255; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &IEId, + 1, &Len, + Len, &AcDelayInfo, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + +VOID RRM_InsertBssAvailableACIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen) +{ + INT idx; + ULONG TempLen; + UINT8 IEId = IE_BSS_AVAILABLE_AC; + RRM_BSS_AVAILABLE_AC_INFO AvailableAcInfo; + PRRM_BSS_AVAILABLE_AC_BITMAP pAcBitMap; + UINT8 Len; + + + pAcBitMap = (PRRM_BSS_AVAILABLE_AC_BITMAP) \ + &AvailableAcInfo.AvailableAcBitMap; + + pAcBitMap->word = 0; + + /* cacule the total length of the IE. */ + Len = 2; + for (idx=0; idx<12; idx++) + { + if (pAcBitMap->word & (0x1 << idx)) + Len += 2; + } + +#ifdef RT_BIG_ENDIAN + pAcBitMap->word = cpu2le16(pAcBitMap->word); +#endif + + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &IEId, + 1, &Len, + sizeof(RRM_BSS_AVAILABLE_AC_INFO), &AvailableAcInfo, + END_OF_ARGS); + + *pFrameLen += TempLen; + pFrameBuf += TempLen; + + + return; +} + +VOID RRM_InsertRequestIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 ie_num, + IN PUINT8 ie_list) +{ + ULONG TempLen; + UINT8 IEId = IE_802_11D_REQUEST; + UINT8 Len; + + /*Len = 5; + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &IEId, + 1, &Len, + Len, RequestIEs, + END_OF_ARGS); + */ + Len = ie_num; + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &IEId, + 1, &Len, + Len, ie_list, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + return; +} + +VOID RRM_InsertRequestIE_NEW( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pRequest, + IN UINT8 RequestLen) +{ + ULONG TempLen = 0; + UINT8 IEId = IE_802_11D_REQUEST; + UINT8 Len = 0; + + Len = RequestLen; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &IEId, + 1, &Len, + Len, pRequest, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; +} + +VOID RRM_InsertTxStreamReqIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pBuf) +{ + RTMP_INSERT_IE(pFrameBuf, pFrameLen, + sizeof(RRM_TRANSMIT_MEASURE_INFO), pBuf); +} + +VOID RRM_InsertTxStreamReqTriggerReportSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pBuf) +{ + ULONG TempLen; + ULONG Len = sizeof(RRM_TRANSMIT_MEASURE_TRIGGER_REPORT); + UINT8 SubId = RRM_TX_STREAM_SUBID_TRIGGER_REPORT; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &SubId, + 1, &Len, + Len, pBuf, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; +} + +VOID RRM_EnqueueBcnReq( + IN PRTMP_ADAPTER pAd, + IN UINT8 Aid, + IN UINT8 IfIdx, + IN PRRM_MLME_BCN_REQ_INFO pMlmeBcnReq) +{ + UINT8 MeasureReqType = RRM_MEASURE_SUBTYPE_BEACON; + MEASURE_REQ_MODE MeasureReqMode; + UINT8 MeasureReqToken = RandomByte(pAd); + RRM_BEACON_REQ_INFO BcnReq; + UINT8 ReportDetail; + UINT8 TotalLen; + + HEADER_802_11 ActHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory */ + if (NStatus != NDIS_STATUS_SUCCESS) { + DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); + return; + } + + /* build action frame header. */ + if (Aid) { + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pAd->MacTab.Content[Aid].Addr, + pAd->ApCfg.MBSSID[IfIdx].wdev.if_addr, + pAd->ApCfg.MBSSID[IfIdx].wdev.bssid); + } else { + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pMlmeBcnReq->Addr, + pAd->ApCfg.MBSSID[IfIdx].wdev.if_addr, + pAd->ApCfg.MBSSID[IfIdx].wdev.bssid); + } + + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + /* + * Action header has a field to indicate total length of packet + * but the total length is unknown untial whole packet completd. + * So skip the action here and fill it late. + * 1. skip Catgore (1 octect), Action(1 octect). + * 2. skip dailog token (1 octect). + * 3. skip Num Of Repetitions field (2 octects) + * 3. skip MeasureReqIE (2 + sizeof(MEASURE_REQ_INFO)). + */ + FrameLen += (7 + sizeof(MEASURE_REQ_INFO)); + + TotalLen = sizeof(MEASURE_REQ_INFO); + /* + * Insert Beacon Req IE. + */ + BcnReq.RegulatoryClass = pMlmeBcnReq->RegulatoryClass; + BcnReq.ChNumber = pMlmeBcnReq->MeasureCh; + /*BcnReq.RandomInterval = 0;*/ + BcnReq.RandomInterval = cpu2le16(pMlmeBcnReq->RandInt); + BcnReq.MeasureDuration = cpu2le16(pMlmeBcnReq->MeasureDuration); + BcnReq.MeasureMode = pMlmeBcnReq->MeasureMode; + COPY_MAC_ADDR(BcnReq.Bssid, pMlmeBcnReq->Bssid); + + RRM_InsertBcnReqIE(pAd, (pOutBuffer+FrameLen), + &FrameLen, (PUCHAR)&BcnReq); + + TotalLen += sizeof(RRM_BEACON_REQ_INFO); + + /* inssert SSID sub field. */ + if (pMlmeBcnReq->SsidLen != 0) + { + RRM_InsertBcnReqSsidSubIE(pAd, (pOutBuffer+FrameLen), + &FrameLen, (PUCHAR)pMlmeBcnReq->pSsid, pMlmeBcnReq->SsidLen); + + TotalLen += (pMlmeBcnReq->SsidLen + 2); /* SSID sub field. */ + } + + /* inssert report condition sub field. */ + if (pMlmeBcnReq->BcnReqCapFlag.field.ReportCondition == TRUE) + { + RRM_InsertBcnReqRepCndSubIE(pAd, (pOutBuffer+FrameLen), &FrameLen, 0, 0); + TotalLen += (2 + 2); /* SSID sub field. */ + } + + /* inssert channel report sub field. */ + if (pMlmeBcnReq->BcnReqCapFlag.field.ChannelRep == TRUE) + { + ULONG idx; + idx = 0; + while(pMlmeBcnReq->ChRepRegulatoryClass[idx] != 0) + { + ULONG FramelenTmp = FrameLen; + InsertChannelRepIE(pAd, (pOutBuffer+FrameLen), &FrameLen, + (RTMP_STRING *)pAd->CommonCfg.CountryCode, + pMlmeBcnReq->ChRepRegulatoryClass[idx], + &pMlmeBcnReq->ChRepList[0]); + TotalLen += (FrameLen - FramelenTmp); + idx ++; + } + } + + + /* inssert report detail sub field. */ + ReportDetail = pMlmeBcnReq->report_detail; + /*if (BcnReq.MeasureMode == 2) + ReportDetail = 0; + else + ReportDetail = 1; + + if (ReportDetail == 1) + { + ULONG FramelenTmp = FrameLen; + RRM_InsertBcnReqRepDetailSubIE(pAd, (pOutBuffer+FrameLen), &FrameLen, 1); + TotalLen += (FrameLen - FramelenTmp); + + FramelenTmp = FrameLen; + RRM_InsertRequestIE(pAd, (pOutBuffer+FrameLen), &FrameLen, + pMlmeBcnReq->request_ie_num, pMlmeBcnReq->request_ie); + TotalLen += (FrameLen - FramelenTmp); + } + else + { + ULONG FramelenTmp = FrameLen; + RRM_InsertBcnReqRepDetailSubIE(pAd, (pOutBuffer+FrameLen), &FrameLen, 0); + TotalLen += (FrameLen - FramelenTmp); + } +*/ + if (BcnReq.MeasureMode == RRM_BCN_REQ_MODE_BCNTAB) + ReportDetail = 0; /*force report detail to 0 when it is table mode*/ + { /*insert report detail sub ie*/ + ULONG FramelenTmp = FrameLen; + + RRM_InsertBcnReqRepDetailSubIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ReportDetail); + TotalLen += (FrameLen - FramelenTmp); + } + if (ReportDetail == 1) { + /*if report detail is 1, insert request ie list*/ + ULONG FramelenTmp = FrameLen; + + RRM_InsertRequestIE (pAd, + (pOutBuffer + FrameLen), + &FrameLen, + pMlmeBcnReq->request_ie_num, + pMlmeBcnReq->request_ie); + TotalLen += (FrameLen - FramelenTmp); + } + + + /* Insert Action header here. */ + { + ULONG tmpLen = sizeof(HEADER_802_11);; + MeasureReqMode.word = 0; + MeasureReqMode.field.DurationMandatory = 0; + MeasureReqMode.field.Report = 0; + MeasureReqMode.field.Request = 0; + MeasureReqMode.field.Enable = 0; + MeasureReqMode.field.Parallel = 0; + MakeMeasurementReqFrame(pAd, pOutBuffer, &tmpLen, + TotalLen, CATEGORY_RM, RRM_MEASURE_REQ, MeasureReqToken, + MeasureReqMode.word, MeasureReqType, 0); + } + + MeasureReqInsert(pAd, MeasureReqToken); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + + if (pOutBuffer) + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + + +/* +* reference 2012 spec. +* 802.11-2012.pdf +* page#581 (0 is not euqal to no security ) +* The Security bit, if 1, indicates that the AP identified by this BSSID supports the same security provisioning +* as used by the STA in its current association. If the bit is 0, it indicates either that the AP does not support +* the same security provisioning or that the security information is not available at this time. +*/ +BOOLEAN RRM_CheckBssAndStaSecurityMatch( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN BSS_ENTRY * pBssEntry) +{ + BOOLEAN ret = FALSE; + + if ((pBssEntry->AuthMode == pEntry->AuthMode) + && (pBssEntry->WepStatus == pEntry->WepStatus)) + ret = TRUE; + else + ret = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: pBssEntry %s/%s & pSTA %s/%s = (%d/%d) ret %d\n", __func__, + GetAuthMode(pBssEntry->AuthMode), GetEncryptType(pBssEntry->WepStatus), + GetAuthMode(pEntry->AuthMode), GetEncryptType(pEntry->WepStatus), + (pBssEntry->AuthMode == pEntry->AuthMode), + (pBssEntry->WepStatus == pEntry->WepStatus), + ret + )); + + return ret; +} + +VOID RRM_EnqueueNeighborRep( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UINT8 DialogToken, + IN PCHAR pSsid, + IN UINT8 SsidLen) +{ +#define MIN(_x, _y) ((_x) > (_y) ? (_x) : (_y)) + INT loop; + HEADER_802_11 ActHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + ULONG PktLen; + + if ((pEntry == NULL) || (pEntry->func_tb_idx >= pAd->ApCfg.BssidNum)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid STA.\n", __FUNCTION__)); + return; + } + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory */ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); + return; + } + + /* build action frame header. */ + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pEntry->Addr, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.if_addr, + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid); + + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, + CATEGORY_RM, RRM_NEIGHTBOR_RSP); + + /* fill Dialog Token */ + InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); + +#ifdef AP_SCAN_SUPPORT + /* insert NeighborRep IE. */ + for (loop = 0; loop < pAd->ScanTab.BssNr; loop++) + { + UINT8 BssMatch = FALSE; + BSS_ENTRY *pBssEntry = &pAd->ScanTab.BssEntry[loop]; + + /* Discards all remain Bss if the packet length exceed packet buffer size. */ + PktLen = FrameLen + sizeof(RRM_NEIGHBOR_REP_INFO) + + (pAd->ApCfg.MBSSID[pEntry->func_tb_idx].RrmCfg.bDot11kRRMNeighborRepTSFEnable == TRUE ? 6 : 0); + if (PktLen >= MGMT_DMA_BUFFER_SIZE) + break; + + if (SsidLen != 0) + BssMatch = RTMPEqualMemory(pBssEntry->Ssid, pSsid, + MIN(SsidLen, pBssEntry->SsidLen)); + else + BssMatch = TRUE; + + if (BssMatch) + { + RRM_BSSID_INFO BssidInfo; + BssidInfo.word = 0; + BssidInfo.field.APReachAble = 3; + BssidInfo.field.Security = RRM_CheckBssAndStaSecurityMatch(pAd, pEntry, pBssEntry); + BssidInfo.field.KeyScope = 0; /* "report AP has same authenticator as the AP. */ + BssidInfo.field.SepctrumMng = (pBssEntry->CapabilityInfo & (1 << 8))?1:0; + BssidInfo.field.Qos = (pBssEntry->CapabilityInfo & (1 << 9))?1:0; + BssidInfo.field.APSD = (pBssEntry->CapabilityInfo & (1 << 11))?1:0; + BssidInfo.field.RRM = (pBssEntry->CapabilityInfo & RRM_CAP_BIT)?1:0; + BssidInfo.field.DelayBlockAck = (pBssEntry->CapabilityInfo & (1 << 14))?1:0; + BssidInfo.field.ImmediateBA = (pBssEntry->CapabilityInfo & (1 << 15))?1:0; + + RRM_InsertNeighborRepIE(pAd, (pOutBuffer + FrameLen), &FrameLen, + sizeof(RRM_NEIGHBOR_REP_INFO), pBssEntry->Bssid, + BssidInfo, pBssEntry->RegulatoryClass, + pBssEntry->Channel, pBssEntry->CondensedPhyType); + } + + /* + shall insert Neighbor Report TSF offset + when the MIB attribute + dot11RRMNeighborReportTSFOffsetEnabled is true. + */ + if (pAd->ApCfg.MBSSID[pEntry->func_tb_idx].RrmCfg.bDot11kRRMNeighborRepTSFEnable) + { + UINT32 Ttfs = (UINT32)(pBssEntry->TTSF[3] << 24) + + (UINT32)(pBssEntry->TTSF[2] << 16) + + (UINT32)(pBssEntry->TTSF[1] << 8) + + (UINT32)(pBssEntry->TTSF[0]); + + UINT32 Ptfs = (UINT32)(pBssEntry->PTSF[3] << 24) + + (UINT32)(pBssEntry->PTSF[2] << 16) + + (UINT32)(pBssEntry->PTSF[1] << 8) + + (UINT32)(pBssEntry->PTSF[0]); + + RRM_InsertNeighborTSFOffsetSubIE(pAd, (pOutBuffer + FrameLen), + &FrameLen, cpu2le16((UINT16)ABS(Ttfs, Ptfs)), + pBssEntry->BeaconPeriod); + } + } +#endif /* AP_SCAN_SUPPORT */ + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + + if (pOutBuffer) + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +VOID RRM_EnqueueLinkMeasureReq( + IN PRTMP_ADAPTER pAd, + IN UINT8 Aid, + IN UINT8 apidx) +{ + UINT8 DialogToken = RandomByte(pAd); + HEADER_802_11 ActHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + PMAC_TABLE_ENTRY pEntry; + + if ((apidx >= pAd->ApCfg.BssidNum) + || (Aid >= MAX_LEN_OF_MAC_TABLE)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Invalid STA. apidx=%d Aid=%d\n", + __FUNCTION__, apidx, Aid)); + return; + } + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /* Get an unused nonpaged memory */ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); + return; + } + + pEntry = &pAd->MacTab.Content[Aid]; + + /* build action frame header. */ + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pEntry->Addr, + pAd->ApCfg.MBSSID[apidx].wdev.if_addr, + pAd->ApCfg.MBSSID[apidx].wdev.bssid); + + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, + CATEGORY_RM, RRM_LNK_MEASURE_REQ); + + /* fill Dialog Token */ + InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); + + /* fill Tx Power Used field */ + { + ULONG TempLen; + UINT8 TxPwr = RTMP_GetTxPwr(pAd, pAd->CommonCfg.MlmeTransmit); + MakeOutgoingFrame(pOutBuffer + FrameLen, &TempLen, + 1, &TxPwr, + END_OF_ARGS); + + FrameLen += TempLen; + } + + + /* fill Max Tx Power field */ + { + ULONG TempLen; + UINT8 MaxTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); + MakeOutgoingFrame(pOutBuffer + FrameLen, &TempLen, + 1, &MaxTxPwr, + END_OF_ARGS); + + FrameLen += TempLen; + } + + + MeasureReqInsert(pAd, DialogToken); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + + if (pOutBuffer) + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +VOID RRM_EnqueueTxStreamMeasureReq( + IN PRTMP_ADAPTER pAd, + IN UINT8 Aid, + IN UINT8 apidx, + IN PRRM_MLME_TRANSMIT_REQ_INFO pMlmeTxMeasureReq) +{ + UINT8 MeasureReqType = RRM_MEASURE_SUBTYPE_TX_STREAM; + MEASURE_REQ_MODE MeasureReqMode; + UINT8 MeasureReqToken = RandomByte(pAd); + RRM_TRANSMIT_MEASURE_INFO TxMeasureReq; + RRM_TRANSMIT_MEASURE_TRIGGER_REPORT TriggerReport; + UINT8 TotalLen; + + HEADER_802_11 ActHdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory */ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); + return; + } + + MeasureReqMode.word = 0; + + /* build action frame header. */ + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pAd->MacTab.Content[Aid].Addr, + pAd->ApCfg.MBSSID[apidx].wdev.if_addr, + pAd->ApCfg.MBSSID[apidx].wdev.bssid); + + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + /* + Action header has a field to indicate total length of packet + but the total length is unknow untial whole packet completd. + So skip the action here and fill it late. + 1. skip Catgore (1 octect), Action(1 octect). + 2. skip dailog token (1 octect). + 3. skip Num Of Repetitions field (2 octects) + 3. skip MeasureReqIE (2 + sizeof(MEASURE_REQ_INFO)). + */ + FrameLen += (7 + sizeof(MEASURE_REQ_INFO)); + + TotalLen = sizeof(MEASURE_REQ_INFO); + + /* + Insert Tx stream Measure Req IE. + */ + + /* according to WiFi Voice-enterprise testing req. the RandomInterval shall be zero. */ + TxMeasureReq.RandomInterval = 0; + TxMeasureReq.MeasureDuration = cpu2le16(pMlmeTxMeasureReq->MeasureDuration); + COPY_MAC_ADDR(TxMeasureReq.PeerStaMac, pAd->MacTab.Content[Aid].Addr); + TxMeasureReq.TIDField.Rev = 0; + TxMeasureReq.TIDField.TID = pMlmeTxMeasureReq->Tid; + TxMeasureReq.Bin0Range = pMlmeTxMeasureReq->BinRange; + + RRM_InsertTxStreamReqIE(pAd, (pOutBuffer+FrameLen), + &FrameLen, (PUCHAR)&TxMeasureReq); + + TotalLen += sizeof(RRM_TRANSMIT_MEASURE_INFO); + + /* inssert Trigger report sub field. */ + if (pMlmeTxMeasureReq->bTriggerReport == 1) + { + PRRM_TRANSMIT_MEASURE_TRIGGER_CONDITION pTiggerCon + = (PRRM_TRANSMIT_MEASURE_TRIGGER_CONDITION)&TriggerReport.TriggerCondition; + + pTiggerCon->field.Average = pMlmeTxMeasureReq->ArvCondition; + pTiggerCon->field.Consecutive = pMlmeTxMeasureReq->ConsecutiveCondition; + pTiggerCon->field.Delay = pMlmeTxMeasureReq->DelayCondition; + if (pTiggerCon->field.Average) + TriggerReport.AvrErrorThreshold = pMlmeTxMeasureReq->AvrErrorThreshold; + if (pTiggerCon->field.Consecutive) + TriggerReport.ConsecutiveErrorThreshold = pMlmeTxMeasureReq->ConsecutiveErrorThreshold; + if (pTiggerCon->field.Delay) + TriggerReport.DelayThreshold = pMlmeTxMeasureReq->DelayThreshold; + + TriggerReport.TriggerTimeout = pMlmeTxMeasureReq->TriggerTimeout; + TriggerReport.MeasurementCnt = pMlmeTxMeasureReq->MeasureCnt; + RRM_InsertTxStreamReqTriggerReportSubIE(pAd, (pOutBuffer+FrameLen), + &FrameLen, (PUCHAR)&TriggerReport); + + TotalLen += + (sizeof(RRM_TRANSMIT_MEASURE_TRIGGER_REPORT) + 2); + + MeasureReqMode.field.Report = 1; + } + + /* Insert Action header here. */ + { + ULONG tmpLen = sizeof(HEADER_802_11);; + MeasureReqMode.field.Enable = 1; + MeasureReqMode.field.DurationMandatory = + pMlmeTxMeasureReq->bDurationMandatory; + MakeMeasurementReqFrame(pAd, pOutBuffer, &tmpLen, + TotalLen, CATEGORY_RM, RRM_MEASURE_REQ, MeasureReqToken, + MeasureReqMode.word, MeasureReqType, 0xffff); + } + + MeasureReqInsert(pAd, MeasureReqToken); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + + if (pOutBuffer) + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + +#endif /* DOT11K_RRM_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt2860.bin b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt2860.bin new file mode 100644 index 0000000000000000000000000000000000000000..5a058e1455aaceff60b637a4540552e219ad30ca GIT binary patch literal 8192 zcmeHMU2Gf25hnMJ6h%qakv!^O^7%^ImVZx@owR}xDUv8Twrt8a_2V?QuZRmcj*VPw zUQz_Gd6gnG4P5vt`8|QuqRB%*)X+nL772SwlZO;3aYlfkK-0C%ZPFyR4vnvs|HRH7 zsYq^;Ht9pr2MN&r%+Actely&i+eK&^p>1Lw{*ZeMt@6m#RILA$!5J$vmKn`t)ohKC zmSRkhE7jR5EL~%gK1*kLEPTiy*E>ng(v={#BRb3C$RA{hm%Ac!avv`bM%F1Z8H_B- zCA{p5AjNmit!+Gqw1}>7*d7>1;MTnjOnpS=_p8{zn=7*9`tRgFngOPc!&> z2H(iw`3x?uDF|XXpT&z=d@qadX7QaYzMaLlvUuT3)u~yoC|NFz_(?)$!wC%;Bhq0% z8Gz0JbPm6Fs6>KxugN;NRT@9J&$u8OaOjNW_6nr{Y=eZnf*%@dCB`e1IStk;ltV)l zLZw2$OE$;0$jlYZJv;Gg5NX;QMzB$9X*rP9u<<2J2^ZZSDZEi7$(s(8xglgVOHf*y; zb2}7!?7Ahcd7Zr`E(5A&eMJPk_pQoE2VLHv`}H7tB4>+spU%3#5Hl^RKSnwGg8icX zg8eJ|BUP_4FQ~70LPqrEHU8&g{9`|Lxu`Puy5EKPUz5QZ zR7pl8?A6^B@cjz+1?U_~55Y|Uj0%X682@sgNLMboJIi%r{%2GK1rC%DOlmR^05!aO(xJLq(QtF^kvhkM-CJ>BD>&IA8n zPb>n_%GvwvxZ0k#CEfG0WWbtE=HZ{Q%s9jq?&-ADUHPJUy7EBsK^Sa>D-$=>X4Dzg zG!&iSDuX~MIme`j5b_rnIJxX1x-OmDV(HxWWTyjOB4rQbgr+N?j{2AkUwNssTUXl1 zaDf0#Jp0m>OKj&^9Jy;zNLz7S_qZ%FlBkr~RJDdu0o~)C2b6>U_4 zE2@yFwg~&RwPYNdzSfK@mzG+JhtFZD09Z;XEcA-*Oc9tprl*Lhc8mrR1Vc3)vX3l5 z&GK*|Bvpr2D8~uQ9*!Nca&U!bk)fONCS8eAH|S^!I8Dsi5;zUC+>{w?OZRCKMbZ{) zmHnhG+@|=$t(vzGdk&RBVMVB;W%A`{3%$(hx5u#jTQru`HrZs6W3Y&=WP=itYCPnaK+2@r zS|CdKH>3cNJ?e&X4TU$Dr_9q@B{?Sj#cR+eYo0PrgXxU2PTE@_)c`vq^#=f2N3LW^ zj&8<0=@G7#k@n*V)(ZPFOSRCAIYc++f&$p16-Te|LlB_~r%q_=r4wG#J2j^@Qf@W{2W84ddK1>->lS++dgom?o`Myhoj4;r$xfXF zfs@MuSHD_7ok$9&*{M^GbNq@ZouXpbv}(szr@4dl3OPn1&UG{>b~p-_%zd@urze!< z-#vq8FG-!X_;{<#Pdz>H?36O`4A~Y6B|7YF#$X)r7$Ss+VtWgF?FSS>-nCFQV z$!qQAEtvG7;)IQ}S{-dxB)$zR9q^uafs0ruT{mbTE*Q78(6Vh*k~M(1;#4h|Sne2C z2FBHW=Sz&c=NKpO@;YAL493O4xF8s}XQgpkvw2HvUoo4u_1~Cw3qt*K&~CwN#!90K zM?J)D8AlU>#3vT%NPH5DLDG|3$_iqT6~vaZf{O#@Vew+Z9D$uYYNW{lUf#pYPeu@| zs6J~RRtMcW@?r2G>{{Q_*&TQWHB3WMO^aYk2-baH=UANh%u)}yK?ELIsH7UDr5<$Q z1fvw$sGd8(hL+h-{X0}Wyjh|8w{`YGd|agBZ|gx8c1%bjt~KZ`ge4r#(KC1&a?awh zn{vastA{p1K2&Gvp=PM-q23I&2=zudxM<2~Ikd#@9bMH#QbJ_cO+BbGwjjaF%*O!;pM}Jv4n?N`0}ty^w!Y3y2q(fD~Ut6BkfMb6DV4 zqi%H&UR4fgrDOm$swiV0AW=DNxPfLIel42r3^ouFones4IJ=?bUgHcIZb+b=!GpZK z8=~5AMZ;WSzQD>HIpqfk)PqPJWR?sg+Z|KE5bBwe>OnArK_Hy~SR3Y?6l#ry6ZHJN z02xh<+ywYxzzfo!dZ?QLUk|iJXm7S4u>&M~DrxfW6fgvyVH`9Y3!bS0$0X;z=o)Zq z53oaQ^pwMF@bV?0QUjfHryqu;OAIpT!r^IaYi@D*?Fe4DYL|OoeCT>lgs&WB6PB)a z!wI5*`?&@%7u?S^LcIy}qbRRsPI5m^6S F^PfpY8?*ob literal 0 HcmV?d00001 diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt2860.bin.dfs b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt2860.bin.dfs new file mode 100644 index 0000000000000000000000000000000000000000..dcdc97bf98ab63d39316c59b2722358eef99a1bb GIT binary patch literal 8192 zcmeG>Yitxpn$y)iJu`led&YPSel)$~*f=~I3xsBu*On)?s;!k5iCKoQR*aS~^*6vAi{n3V}E)Z!3sz z0|10QGjdkTpf6}Oil1a#>pPL^w$=}_9MuAZtN@Idv;wcSUUT${FM6y)B1Z2V6JMgx zP4v!j@g#+Ap?6N`%j?7!x&C8DlYES~n)`1V8|2awO5~!9fub(!`N3lD0)Q7>cYY8~ z8Kv`S&5Aw!u04<3cc$;O_!8HD9P}N3NFV+deY3Pj_33>P@g&!O!gvDWlch=W399uI zqsW=51Mae##Uv|R>~(_~0lN;z>^yFMi``k;qjpdAX{O(WP5)Bc^s{*6O}Q@Ef2!|X zzt(rwS{?`}&yeNubBVL2e}%Q&2H$wC){}+UUqz$a(oek>f)gKB>2(%jRU=#8+y0a_qL{Stst;D zEwD8$&^jj|TMbHnqn|W5DagT&YZ-L&4Tm_r9u{km_d9eM=zL-NU2$Xeb_&n^?i`Gr0v={)CNqZFT_`tU8aC8&0U7i+530ZHWvs@^ctyyqFC>O3;Srsl__z4u&Qf`JU^=wwyS>d-hK z`FhW7N+4s&m5$gs!L!B?9o808E5M{taOD}igJ?=lIrIc)YJsGkh>ebpc8~Uq+M{^Y z52MM+kEiq>{|LEXLVRoT^1xmA)v=QX^QHI3gt3HT6i+zk>PQX5tWmt$Q^!s0Hkjtg z8%ZOZL7dkw))}U^C3%6ltp3YDN_j@Md`kH=2&zop@08&RtiE0MOBmj#y5M*9{qCzD zzTfkqJqz9V?7x0*ygL`gPlxem!}!04@#n+%i(!0w7~dJj+s~raIFxdCeE{_awbAof0 zFF$_ip+E_qzjg4e%3*#zc_xA`A5+H%1_q29ulM|tGYB(J6LK1Wj_vqm)Y5pjb=H(ZRg;W11 zjYyH;%oL?@)BE&g)9X5u6&hFBa^t?ltabhREthj`c-%aWz~cx!j=cmD z0Qn{4e;WCpLBYK!xDOTPqQblpxEr9tZD;|J-MpB~3L#PEc`=U_7G=pEUd#ueU6N*Q z?ZK_im3=q8vco&Ye^2&bTj~GB8voy{E%3D$wC^a`zq4Tfu7dqa!C!Y2Ozsx0s6y)z z;nU}Z)}z9-76_jTw4M%JI}`ZA2nKqBPrmAMQI&8<-;jh0Iei_#%?AayS{;KZ-`Y1= z#hXkn+{NGlfX<`XZn)Z`V4a9qna!FTr)v*6CX<63kv)JLIlFf^JO@A#RX(Ay0AX^J zDt5{g9;*XhPn7D%N;EZ;l}q^sy}Z7i(c4~~K_h{p;i<~uK@n)I-XILU$tQaECCdr1xxKF2>X2hi0zWnU}J2#m=Zz%E=2@G00yy)4brK^Bz3H zop-@HdB(5azUnpHBQ@7*u6=xu9Qmp0_^m?3%CMro7f?Jw@;&{Sp}+Wqew^1|D%MX7 zU)eJg6^FT;e4nZ&-<=gLnHBwkeyUDCU7??G>yctzKQLd^kD-dS3LdA`bJ&N&Ow~?P zty8z}j*&foWHIJ(k?x=N;CYO+S_13qN0{s#z+|7bcTg*XWR;6ew-+}u_LS*%W95Mj zd3aly2Be)N+ew?gK1H6>4>06lyo@|S){$DWHc?JC#!E;Ac}m|OA}3Av&msl(KqLh} z7Nm~GOJM`x#yVTykjhNRIGvsk4@r!S66z=f_Ht%54JA#@1*-2n>%`P>5*?VfB-}Gf zmLO zb#QL5a=wA|T#D#%AV6s`Pgb)dQx(kwo~B8%%i5)_lGVlUw92g|Y0d)5nFE~O2us-v z6PV zmMUHdBREJF{Ci@b-ocp2ON(Myy!joITa5=%$pAD(v=O4BP*`vJIjsD_)^{)HsA4Fepar8Q_Z04wsL4@N;38Qz1rgt%V2fT=P7(NJ|8-ho6 zSY2vioB>>X-<7Udolx|J)iubX1na!3WhT!d#TocmIK-Vn^w&Y?C2^QMC$*vt?xv72Rk!=tJ8Mo`oN}3+oJCT-&h1H73~!#h zjIyC7?$R2gXsDUHBpd#r&D^DxhHvN;cWDI`=wAr63or|1>=KAHWV^o<`fBLQAYvt$ zbO8ig^AB_YjDReKehKtt&{sqGH3p>H_P{s*$yd{rc40E3^Zc0 zItkW9$NE5I)0~DM&REqJXNdKW5~HVt;`;GMk@`LmIrS*Rtc@r~Ih7FHXcl%@XT#|3 z80oX(IaK^qal``=p7M!uL2y4hp4<&Z@6Tv?%G6%RVRtG3|F-(Lp(LEcv2CDRwf~3Yd-$EH5CcZRNKbq z8|7w=Zp;{sQln?X9Nbu5whn}+ApuHW4bt{MoU^Rd10Uzt?YCbZ6EPrvtV~Z@XMtPY z6_4r9WdUA!Fqw!sxK5;%nCE(J(8t~#GdVc!9Vi7LKCFESw8%771tN1i>9KwQ88z|P z+h@nfb2Cbv&)NeUKH|Jt#9{IZ2=RBvroCey-udvJ!2h#;fQ>Q|u*fx>r_cI8*>+#>?2>kg*;H%}E{s&~-8u|bL literal 0 HcmV?d00001 diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt2870_sw_ch_offload.bin b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt2870_sw_ch_offload.bin new file mode 100644 index 0000000000000000000000000000000000000000..f933b5c7ace62541092d6a7e18345d46d8ac6f5c GIT binary patch literal 8192 zcmeHLYit}>753bjb!^A6XJh2&epvj160P%tA4s5eAtDmuM%jU)D&&e}c(ies@6OJy zcbx3qCGWZSyzV*Yo_p^(lh5ag+D_CSqMjsr6VaQAt`dDj(}Q8M@epZwf#}~N z`bnxtEH3eAptfz5thGKHt*vcqk~RI;VJdx-MK8BG!%?O>pNulairK`fq3Q!yIcTXm zo}IZ36`*V)|H>IIX;wN<|eQzgXO{v;E96*V>H4pK#7TElnM z-|bX?_Hd9q7py-PJpX*~&neBZYia~nkhxtsYU&)KDVsZk*G(Z#^x8HeN9ERWGCQcP z{C0urF_y6$AABN9!r9uHA)>uS)f(mw<=kO+gsL)|YY(J{CA-TTM=>UL)EjqVtk@B6 z{7@rR37b0xRGl3xpc*{XX*oTtA|#jA(?FdF+#(GGnDHKuEBuP_K9D@;KIQhOcjwbx z`I(`DmFB~#7@tl(1aG`(XV&E0r`=KaFg2rmnrGJD+7D`~ERuiqbZ+tAI4k_4>UNHO z!6G7ZhUE@1!=~mgOjVY5h8Ct`z0~Y zo=3hC7O&&SAA9lmqc1s~+}Smats~6%J5*7%@2KsUt-9Z8ec&nwq#XDjs|2dHh=~Q{=LA90b%C5K(jnt9bgL+O#^{+ zuVl+P7yD^2YQBmcJp_0fa1d|;a0u`W;4t88fC<3Y`M7L-Pt!+pi`EptxKciIdXpM8 z4>B6KFeeeao*9?9U5^C3h?@7!g1bT^v zwFjBeyhK>(3tbaNM*d;Qo7raOkwICKvwX6m>qhta&dyH5zFEf&;b5pF?DXP-Sks?# zk2ps*vq+8mV(!5&A=-IwDtS{)e?0*5{6uT)qP5Yt1xAh*Yyf7`mxqRtk_Hj_`Kj1$ zp$UZ13c|wFzreO4&TaMg5g-n%1&=uvQmy+w6_)=>Z)Yj zQ^_j9p`E@%-MtB$n){j2op%z(xqdfcbT3S7iPec&e2Xi#3A~fmt_pzzw-+F5KT$Me zw^(;6t{?TLC5xLY<2rJyxPG>zVOd;1S3xL?>vJW7AJ@-UuDUaJw%qx1H#@)0cYfO~ zorl13=PLyes7XumqJNEG5mO zWg^Jj$Ce9Rw1S>j)I9Dayqf}VM`HX4uKVwc^L`x9NKb-&CV{iH?y`7TcK8pAvt!{* zA{L!?c0dfT$(e+BPK;&G$#g1M@q)Z1UXX%Be%?uVPf**k$78unRy-AZ6XJ4QMzT<* z;95e+t+*{NCd?Ml+f zAyBw5l-O^J%uki5);#DUB_sVyxbr2M+Sso|h97N8%4CCTDVm--)gyLjP73t)wAu2( zoENPyA?8{h86kZ0OpJGC;RBq0*t|v#GD}Os$AbJrAE6$c}_h8QI}*&K=9lI{QP(Cqv0ELrSu1`tt4-VZBvln=T;u8e5@ehKPc%Iy6i}^( z8M5iK2}M5#8(Cr_EzeLg&7yw<_Xt%UVMoK}SE=+$>ID?vc;GcfR3dsiqvi&&O@JE# zw*iJdyuo1^egw|=C5pW0W!>qzj(ts{cD-h!WPFd?AspZe!x8xCG{CHF3mmxYojvB$exWb`0DlK z{kiv3A@5E#air$*>z8I%d8(yIxx&LuZz{h*El14`7QOVT%q%q#d$k3|BKB%4UPOC=qL_f7J-wWdz>->6h~#oc{m!x9R_X za@YO;8@KM8KVbd;8}y#^|F?0ryh;9V_WynNr2p@;&)sqV-&gKhvHvfR0&ZaM14*g> zFDK%A(1)h~@2mFzqQxqHQ>ga;-dBoh|6lmvQtki$_x*q4-|l_?-)H~l{ePc*+y1|= n+W(in4pjU9d)WW?Rr~+{hyK5>+W+5W8(9_qkVfF`U8Da3h6QrC literal 0 HcmV?d00001 diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt_channel.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt_channel.c new file mode 100644 index 000000000..d2179ad3c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt_channel.c @@ -0,0 +1,2275 @@ +/* + +*/ +#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}, + {} +}; + +CH_DESC Country_Region22_ChDesc_5GHZ[] = +{ + {100, 11, CHANNEL_DEFAULT_PROP}, + {} +}; + +COUNTRY_REGION_CH_DESC Country_Region_ChDesc_5GHZ[] = +{ + {REGION_0_A_BAND, Country_Region0_ChDesc_5GHZ}, + {REGION_1_A_BAND, Country_Region1_ChDesc_5GHZ}, + {REGION_2_A_BAND, Country_Region2_ChDesc_5GHZ}, + {REGION_3_A_BAND, Country_Region3_ChDesc_5GHZ}, + {REGION_4_A_BAND, Country_Region4_ChDesc_5GHZ}, + {REGION_5_A_BAND, Country_Region5_ChDesc_5GHZ}, + {REGION_6_A_BAND, Country_Region6_ChDesc_5GHZ}, + {REGION_7_A_BAND, Country_Region7_ChDesc_5GHZ}, + {REGION_8_A_BAND, Country_Region8_ChDesc_5GHZ}, + {REGION_9_A_BAND, Country_Region9_ChDesc_5GHZ}, + {REGION_10_A_BAND, Country_Region10_ChDesc_5GHZ}, + {REGION_11_A_BAND, Country_Region11_ChDesc_5GHZ}, + {REGION_12_A_BAND, Country_Region12_ChDesc_5GHZ}, + {REGION_13_A_BAND, Country_Region13_ChDesc_5GHZ}, + {REGION_14_A_BAND, Country_Region14_ChDesc_5GHZ}, + {REGION_15_A_BAND, Country_Region15_ChDesc_5GHZ}, + {REGION_16_A_BAND, Country_Region16_ChDesc_5GHZ}, + {REGION_17_A_BAND, Country_Region17_ChDesc_5GHZ}, + {REGION_18_A_BAND, Country_Region18_ChDesc_5GHZ}, + {REGION_19_A_BAND, Country_Region19_ChDesc_5GHZ}, + {REGION_20_A_BAND, Country_Region20_ChDesc_5GHZ}, + {REGION_21_A_BAND, Country_Region21_ChDesc_5GHZ}, + {REGION_22_A_BAND, Country_Region22_ChDesc_5GHZ}, + {} +}; + +UINT16 const Country_Region_GroupNum_5GHZ = sizeof(Country_Region_ChDesc_5GHZ) / sizeof(COUNTRY_REGION_CH_DESC); + +UINT16 TotalChNum(PCH_DESC pChDesc) +{ + UINT16 TotalChNum = 0; + + while(pChDesc->FirstChannel) + { + TotalChNum += pChDesc->NumOfCh; + pChDesc++; + } + + return TotalChNum; +} + + +UCHAR GetChannel_5GHZ(PCH_DESC pChDesc, UCHAR index) +{ + while (pChDesc->FirstChannel) + { + if (index < pChDesc->NumOfCh) + return pChDesc->FirstChannel + index * 4; + else + { + index -= pChDesc->NumOfCh; + pChDesc++; + } + } + + return 0; +} + +UCHAR GetChannel_2GHZ(PCH_DESC pChDesc, UCHAR index) +{ + + while (pChDesc->FirstChannel) + { + if (index < pChDesc->NumOfCh) + return pChDesc->FirstChannel + index; + else + { + index -= pChDesc->NumOfCh; + pChDesc++; + } + } + + return 0; +} + +UCHAR GetChannelFlag(PCH_DESC pChDesc, UCHAR index) +{ + + while (pChDesc->FirstChannel) + { + if (index < pChDesc->NumOfCh) + return pChDesc->ChannelProp; + else + { + index -= pChDesc->NumOfCh; + pChDesc++; + } + } + + return 0; +} + +#ifdef EXT_BUILD_CHANNEL_LIST +PCH_REGION GetChRegion( + IN PUCHAR CntryCode) +{ + INT loop = 0; + PCH_REGION pChRegion = NULL; + + while (strcmp((RTMP_STRING *) ChRegion[loop].CountReg, "") != 0) { + if (strncmp((RTMP_STRING *) ChRegion[loop].CountReg, (RTMP_STRING *) CntryCode, 2) == 0) { + pChRegion = &ChRegion[loop]; + break; + } + loop++; + } + + /* Default: use WO*/ + if (pChRegion == NULL) + pChRegion = GetChRegion("WO"); + + return pChRegion; +} + + +/*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, TRUE}, /* Albania */ + {"DZ", CE, Country_DZ_ChDesp, TRUE}, /* Algeria */ + {"AR", CE, Country_AR_ChDesp, TRUE}, /* Argentina */ + {"AM", CE, Country_AM_ChDesp, TRUE}, /* Armenia */ + {"AW", CE, Country_AW_ChDesp, TRUE}, /* Aruba */ + {"AU", CE, Country_AU_ChDesp, FALSE}, /* Australia */ + {"AT", CE, Country_AT_ChDesp, TRUE}, /* Austria */ + {"AZ", CE, Country_AZ_ChDesp, TRUE}, /* Azerbaijan */ + {"BH", CE, Country_BH_ChDesp, TRUE}, /* Bahrain */ + {"BD", CE, Country_BD_ChDesp, TRUE}, /* Bangladesh */ + {"BB", CE, Country_BB_ChDesp, TRUE}, /* Barbados */ + {"BY", CE, Country_BY_ChDesp, TRUE}, /* Belarus */ + {"BE", CE, Country_BE_ChDesp, TRUE}, /* Belgium */ + {"BZ", CE, Country_BZ_ChDesp, TRUE}, /* Belize */ + {"BO", CE, Country_BO_ChDesp, TRUE}, /* Bolivia */ + {"BA", CE, Country_BA_ChDesp, TRUE}, /* Bosnia and Herzegovina */ + {"BR", CE, Country_BR_ChDesp, FALSE}, /* Brazil */ + {"BN", CE, Country_BN_ChDesp, TRUE}, /* Brunei Darussalam */ + {"BG", CE, Country_BG_ChDesp, TRUE}, /* Bulgaria */ + {"KH", CE, Country_KH_ChDesp, TRUE}, /* Cambodia */ + {"CA", FCC,Country_CA_ChDesp, FALSE}, /* Canada */ + {"CL", CE, Country_CL_ChDesp, TRUE}, /* Chile */ + {"CN", CHN, Country_CN_ChDesp, FALSE}, /* China */ + {"CO", CE, Country_CO_ChDesp, TRUE}, /* Colombia */ + {"CR", CE, Country_CR_ChDesp, TRUE}, /* Costa Rica */ + {"HR", CE, Country_HR_ChDesp, TRUE}, /* Croatia */ + {"CY", CE, Country_CY_ChDesp, TRUE}, /* Cyprus */ + {"CZ", CE, Country_CZ_ChDesp, TRUE}, /* Czech Republic */ + {"DK", CE, Country_DK_ChDesp, TRUE}, /* Denmark */ + {"DO", CE, Country_DO_ChDesp, TRUE}, /* Dominican Republic */ + {"EC", CE, Country_EC_ChDesp, TRUE}, /* Ecuador */ + {"EG", CE, Country_EG_ChDesp, TRUE}, /* Egypt */ + {"SV", CE, Country_SV_ChDesp, TRUE}, /* El Salvador */ + {"EE", CE, Country_EE_ChDesp, TRUE}, /* Estonia */ + {"FI", CE, Country_FI_ChDesp, TRUE}, /* Finland */ + {"FR", CE, Country_FR_ChDesp, TRUE}, /* France */ + {"GE", CE, Country_GE_ChDesp, TRUE}, /* Georgia */ + {"DE", CE, Country_DE_ChDesp, TRUE}, /* Germany */ + {"GR", CE, Country_GR_ChDesp, TRUE}, /* Greece */ + {"GL", CE, Country_GL_ChDesp, TRUE}, /* Greenland */ + {"GD", CE, Country_GD_ChDesp, TRUE}, /* Grenada */ + {"GU", CE, Country_GU_ChDesp, TRUE}, /* Guam */ + {"GT", CE, Country_GT_ChDesp, TRUE}, /* Guatemala */ + {"HT", CE, Country_HT_ChDesp, TRUE}, /* Haiti */ + {"HN", CE, Country_HN_ChDesp, TRUE}, /* Honduras */ + {"HK", CE, Country_HK_ChDesp, TRUE}, /* Hong Kong */ + {"HU", CE, Country_HU_ChDesp, TRUE}, /* Hungary */ + {"IS", CE, Country_IS_ChDesp, TRUE}, /* Iceland */ + {"IN", CE, Country_IN_ChDesp, TRUE}, /* India */ + {"ID", CE, Country_ID_ChDesp, TRUE}, /* Indonesia */ + {"IR", CE, Country_IR_ChDesp, TRUE}, /* Iran, Islamic Republic of */ + {"IE", CE, Country_IE_ChDesp, TRUE}, /* Ireland */ + {"IL", CE, Country_IL_ChDesp, FALSE}, /* Israel */ + {"IT", CE, Country_IT_ChDesp, TRUE}, /* Italy */ + {"JM", CE, Country_JM_ChDesp, TRUE}, /* Jamaica */ + {"JP", JAP,Country_JP_ChDesp, FALSE}, /* Japan */ + {"JO", CE, Country_JO_ChDesp, TRUE}, /* Jordan */ + {"KZ", CE, Country_KZ_ChDesp, TRUE}, /* Kazakhstan */ + {"KE", CE, Country_KE_ChDesp, TRUE}, /* Kenya */ + {"KP", CE, Country_KP_ChDesp, TRUE}, /* Korea, Democratic People's Republic of */ + {"KR", CE, Country_KR_ChDesp, FALSE}, /* Korea, Republic of */ + {"KW", CE, Country_KW_ChDesp, TRUE}, /* Kuwait */ + {"LV", CE, Country_LV_ChDesp, TRUE}, /* Latvia */ + {"LB", CE, Country_LB_ChDesp, TRUE}, /* Lebanon */ + {"LI", CE, Country_LI_ChDesp, TRUE}, /* Liechtenstein */ + {"LT", CE, Country_LT_ChDesp, TRUE}, /* Lithuania */ + {"LU", CE, Country_LU_ChDesp, TRUE}, /* Luxembourg */ + {"MO", CE, Country_MO_ChDesp, TRUE}, /* Macao */ + {"MK", CE, Country_MK_ChDesp, TRUE}, /* Macedonia, Republic of */ + {"MY", CE, Country_MY_ChDesp, TRUE}, /* Malaysia */ + {"MT", CE, Country_MT_ChDesp, TRUE}, /* Malta */ + {"MX", CE, Country_MX_ChDesp, FALSE}, /* Mexico */ + {"MC", CE, Country_MC_ChDesp, TRUE}, /* Monaco */ + {"MA", CE, Country_MA_ChDesp, TRUE}, /* Morocco */ + {"NP", CE, Country_NP_ChDesp, TRUE}, /* Nepal */ + {"NL", CE, Country_NL_ChDesp, TRUE}, /* Netherlands */ + {"AN", CE, Country_AN_ChDesp, TRUE}, /* Netherlands Antilles */ + {"NZ", CE, Country_NZ_ChDesp, TRUE}, /* New Zealand */ + {"NO", CE, Country_NO_ChDesp, TRUE}, /* Norway */ + {"OM", CE, Country_OM_ChDesp, TRUE}, /* Oman */ + {"PK", CE, Country_PK_ChDesp, TRUE}, /* Pakistan */ + {"PA", CE, Country_PA_ChDesp, TRUE}, /* Panama */ + {"PG", CE, Country_PG_ChDesp, TRUE}, /* Papua New Guinea */ + {"PE", CE, Country_PE_ChDesp, TRUE}, /* Peru */ + {"PH", CE, Country_PH_ChDesp, TRUE}, /* Philippines */ + {"PL", CE, Country_PL_ChDesp, TRUE}, /* Poland */ + {"PT", CE, Country_PT_ChDesp, TRUE}, /* Portuga l*/ + {"PR", CE, Country_PR_ChDesp, TRUE}, /* Puerto Rico */ + {"QA", CE, Country_QA_ChDesp, TRUE}, /* Qatar */ + {"RO", CE, Country_RO_ChDesp, TRUE}, /* Romania */ + {"RU", CE, Country_RU_ChDesp, FALSE}, /* Russian Federation */ + {"BL", CE, Country_BL_ChDesp, TRUE}, /* Saint Barth'elemy */ + {"SA", CE, Country_SA_ChDesp, TRUE}, /* Saudi Arabia */ + {"SG", CE, Country_SG_ChDesp, TRUE}, /* Singapore */ + {"SK", CE, Country_SK_ChDesp, TRUE}, /* Slovakia */ + {"SI", CE, Country_SI_ChDesp, TRUE}, /* Slovenia */ + {"ZA", CE, Country_ZA_ChDesp, FALSE}, /* South Africa */ + {"ES", CE, Country_ES_ChDesp, TRUE}, /* Spain */ + {"LK", CE, Country_LK_ChDesp, TRUE}, /* Sri Lanka */ + {"SE", CE, Country_SE_ChDesp, TRUE}, /* Sweden */ + {"CH", CE, Country_CH_ChDesp, TRUE}, /* Switzerland */ + {"SY", CE, Country_SY_ChDesp, TRUE}, /* Syrian Arab Republic */ + {"TW", FCC,Country_TW_ChDesp, FALSE}, /* Taiwan */ + {"TH", CE, Country_TH_ChDesp, FALSE}, /* Thailand */ + {"TT", CE, Country_TT_ChDesp, TRUE}, /* Trinidad and Tobago */ + {"TN", CE, Country_TN_ChDesp, TRUE}, /* Tunisia */ + {"TR", CE, Country_TR_ChDesp, TRUE}, /* Turkey */ + {"UA", CE, Country_UA_ChDesp, TRUE}, /* Ukraine */ + {"AE", CE, Country_AE_ChDesp, TRUE}, /* United Arab Emirates */ + {"GB", CE, Country_GB_ChDesp, TRUE}, /* United Kingdom */ + {"US", FCC,Country_US_ChDesp, FALSE}, /* United States */ + {"UY", CE, Country_UY_ChDesp, TRUE}, /* Uruguay */ + {"UZ", CE, Country_UZ_ChDesp, TRUE}, /* Uzbekistan */ + {"VE", CE, Country_VE_ChDesp, TRUE}, /* Venezuela */ + {"VN", CE, Country_VN_ChDesp, TRUE}, /* Viet Nam */ + {"YE", CE, Country_YE_ChDesp, TRUE}, /* Yemen */ + {"ZW", CE, Country_ZW_ChDesp, TRUE}, /* Zimbabwe */ + {"EU", CE, Country_EU_ChDesp, TRUE}, /* Europe */ + {"NA", FCC,Country_NA_ChDesp, FALSE}, /* North America */ + {"WO", FCC, Country_WO_ChDesp, FALSE}, /* World Wide */ + {"" , 0, NULL, FALSE} , /* End */ +}; +#endif + +#ifdef EXT_BUILD_CHANNEL_LIST +static VOID ChBandCheck( + IN UCHAR PhyMode, + OUT PUCHAR pChType) +{ + *pChType = 0; + if (WMODE_CAP_5G(PhyMode)) + *pChType |= BAND_5G; + if (WMODE_CAP_2G(PhyMode)) + *pChType |= BAND_24G; + + if (*pChType == 0) + *pChType = BAND_24G; +} + +static UCHAR FillChList( + IN PRTMP_ADAPTER pAd, + IN PCH_DESP pChDesp, + IN UCHAR Offset, + IN UCHAR increment, + IN UCHAR regulatoryDomain) +{ + INT i, j, l; + UCHAR channel; + + j = Offset; + for (i = 0; i < pChDesp->NumOfCh; i++) + { + channel = pChDesp->FirstChannel + i * increment; + if (!strncmp((RTMP_STRING *) pAd->CommonCfg.CountryCode, "JP", 2)) + { + /* for JP, ch14 can only be used when PhyMode is "B only" */ + if ( (channel==14) && + (!WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B))) + { + pChDesp->NumOfCh--; + break; + } + } +/*New FCC spec restrict the used channel under DFS */ +#ifdef CONFIG_AP_SUPPORT + if ((pAd->CommonCfg.bIEEE80211H == 1) && + (pAd->CommonCfg.RDDurRegion == FCC) && + (pAd->Dot11_H.bDFSIndoor == 1)) + { + if (RESTRICTION_BAND_1(pAd)) + continue; + } + else if ((pAd->CommonCfg.bIEEE80211H == 1) && + (pAd->CommonCfg.RDDurRegion == FCC) && + (pAd->Dot11_H.bDFSIndoor == 0)) + { + if ((channel >= 100) && (channel <= 140)) + continue; + } + +#endif /* CONFIG_AP_SUPPORT */ + for (l=0; lTxPower[l].Channel) + { + pAd->ChannelList[j].Power = pAd->TxPower[l].Power; + pAd->ChannelList[j].Power2 = pAd->TxPower[l].Power2; +#ifdef DOT11N_SS3_SUPPORT + pAd->ChannelList[j].Power3 = pAd->TxPower[l].Power3; +#endif /* DOT11N_SS3_SUPPORT */ + break; + } + } + if (l == MAX_NUM_OF_CHANNELS) + continue; + + pAd->ChannelList[j].Channel = pChDesp->FirstChannel + i * increment; + pAd->ChannelList[j].MaxTxPwr = pChDesp->MaxTxPwr; + pAd->ChannelList[j].DfsReq = pChDesp->DfsReq; + pAd->ChannelList[j].RegulatoryDomain = regulatoryDomain; +#ifdef DOT11_N_SUPPORT + if (N_ChannelGroupCheck(pAd, pAd->ChannelList[j].Channel)) + pAd->ChannelList[j].Flags |= CHANNEL_40M_CAP; +#ifdef DOT11_VHT_AC + if (vht80_channel_group(pAd, pAd->ChannelList[j].Channel)) + pAd->ChannelList[j].Flags |= CHANNEL_80M_CAP; +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + + + j++; + } + pAd->ChannelListNum = j; + + return j; +} + + +static inline VOID CreateChList( + IN PRTMP_ADAPTER pAd, + IN PCH_REGION pChRegion, + IN UCHAR Geography) +{ + INT i; + UCHAR offset = 0; + PCH_DESP pChDesp; + UCHAR ChType; + UCHAR increment; + UCHAR regulatoryDomain; + + if (pChRegion == NULL) + return; + + ChBandCheck(pAd->CommonCfg.PhyMode, &ChType); + + if (pAd->CommonCfg.pChDesp != NULL) + pChDesp = (PCH_DESP) pAd->CommonCfg.pChDesp; + else + pChDesp = pChRegion->pChDesp; + + for (i = 0; pChDesp[i].FirstChannel != 0; i++) + { + if (pChDesp[i].FirstChannel == 0) + break; + + if (ChType == BAND_5G) + { + if (pChDesp[i].FirstChannel <= 14) + continue; + } + else if (ChType == BAND_24G) + { + if (pChDesp[i].FirstChannel > 14) + continue; + } + + if ((pChDesp[i].Geography == BOTH) + || (Geography == BOTH) + || (pChDesp[i].Geography == Geography)) + { + if (pChDesp[i].FirstChannel > 14) + increment = 4; + else + increment = 1; + if (pAd->CommonCfg.DfsType != MAX_RD_REGION) + regulatoryDomain = pAd->CommonCfg.DfsType; + else + regulatoryDomain = pChRegion->DfsType; + offset = FillChList(pAd, &pChDesp[i], offset, increment, regulatoryDomain); + } + } +} + + +VOID BuildChannelListEx( + IN PRTMP_ADAPTER pAd) +{ + PCH_REGION pChReg; + + pChReg = GetChRegion(pAd->CommonCfg.CountryCode); + CreateChList(pAd, pChReg, pAd->CommonCfg.Geography); +} + +VOID BuildBeaconChList( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pBuf, + OUT PULONG pBufLen) +{ + INT i; + ULONG TmpLen; + PCH_REGION pChRegion; + PCH_DESP pChDesp; + UCHAR ChType; + + pChRegion = GetChRegion(pAd->CommonCfg.CountryCode); + + if (pChRegion == NULL) + return; + + ChBandCheck(pAd->CommonCfg.PhyMode, &ChType); + *pBufLen = 0; + + if (pAd->CommonCfg.pChDesp != NULL) + pChDesp = (PCH_DESP) pAd->CommonCfg.pChDesp; + else + pChDesp = pChRegion->pChDesp; + + for (i=0; pChRegion->pChDesp[i].FirstChannel != 0; i++) + { + if (pChDesp[i].FirstChannel == 0) + break; + + if (ChType == BAND_5G) + { + if (pChDesp[i].FirstChannel <= 14) + continue; + } + else if (ChType == BAND_24G) + { + if (pChDesp[i].FirstChannel > 14) + continue; + } + + if ((pChDesp[i].Geography == BOTH) || + (pChDesp[i].Geography == pAd->CommonCfg.Geography)) + { + MakeOutgoingFrame(pBuf + *pBufLen, &TmpLen, + 1, &pChDesp[i].FirstChannel, + 1, &pChDesp[i].NumOfCh, + 1, &pChDesp[i].MaxTxPwr, + END_OF_ARGS); + *pBufLen += TmpLen; + } + } +} +#endif /* EXT_BUILD_CHANNEL_LIST */ + + +COUNTRY_PROP CountryProp[]= +{ + {"AL", CE, TRUE}, /* Albania */ + {"DZ", CE, TRUE }, /* Algeria */ + {"AR", CE, TRUE }, /* Argentina */ + {"AM", CE, TRUE }, /* Armenia */ + {"AW", CE, TRUE }, /* Aruba */ + {"AU", CE, FALSE }, /* Australia */ + {"AT", CE, TRUE }, /* Austria */ + {"AZ", CE, TRUE }, /* Azerbaijan */ + {"BH", CE, TRUE }, /* Bahrain */ + {"BD", CE, TRUE }, /* Bangladesh */ + {"BB", CE, TRUE }, /* Barbados */ + {"BY", CE, TRUE }, /* Belarus */ + {"BE", CE, TRUE }, /* Belgium */ + {"BZ", CE, TRUE }, /* Belize */ + {"BO", CE, TRUE }, /* Bolivia */ + {"BA", CE, TRUE }, /* Bosnia and Herzegovina */ + {"BR", CE, FALSE }, /* Brazil */ + {"BN", CE, TRUE }, /* Brunei Darussalam */ + {"BG", CE, TRUE }, /* Bulgaria */ + {"KH", CE, TRUE }, /* Cambodia */ + {"CA", FCC, FALSE}, /* Canada */ + {"CL", CE, TRUE }, /* Chile */ + {"CN", CE, FALSE }, /* China */ + {"CO", CE, TRUE }, /* Colombia */ + {"CR", CE, TRUE }, /* Costa Rica */ + {"HR", CE, TRUE }, /* Croatia */ + {"CY", CE, TRUE }, /* Cyprus */ + {"CZ", CE, TRUE }, /* Czech Republic */ + {"DK", CE, TRUE }, /* Denmark */ + {"DO", CE, TRUE }, /* Dominican Republic */ + {"EC", CE, TRUE }, /* Ecuador */ + {"EG", CE, TRUE }, /* Egypt */ + {"SV", CE, TRUE }, /* El Salvador */ + {"EE", CE, TRUE }, /* Estonia */ + {"FI", CE, TRUE }, /* Finland */ + {"FR", CE, TRUE }, /* France */ + {"GE", CE, TRUE }, /* Georgia */ + {"DE", CE, TRUE }, /* Germany */ + {"GR", CE, TRUE }, /* Greece */ + {"GL", CE, TRUE }, /* Greenland */ + {"GD", CE, TRUE }, /* Grenada */ + {"GU", CE, TRUE }, /* Guam */ + {"GT", CE, TRUE }, /* Guatemala */ + {"HT", CE, TRUE }, /* Haiti */ + {"HN", CE, TRUE }, /* Honduras */ + {"HK", CE, TRUE }, /* Hong Kong */ + {"HU", CE, TRUE }, /* Hungary */ + {"IS", CE, TRUE }, /* Iceland */ + {"IN", CE, TRUE }, /* India */ + {"ID", CE, TRUE }, /* Indonesia */ + {"IR", CE, TRUE }, /* Iran, Islamic Republic of */ + {"IE", CE, TRUE }, /* Ireland */ + {"IL", CE, FALSE }, /* Israel */ + {"IT", CE, TRUE }, /* Italy */ + {"JM", CE, TRUE }, /* Jamaica */ + {"JP", JAP, FALSE}, /* Japan */ + {"JO", CE, TRUE }, /* Jordan */ + {"KZ", CE, TRUE }, /* Kazakhstan */ + {"KE", CE, TRUE }, /* Kenya */ + {"KP", CE, TRUE }, /* Korea, Democratic People's Republic of */ + {"KR", CE, FALSE }, /* Korea, Republic of */ + {"KW", CE, TRUE }, /* Kuwait */ + {"LV", CE, TRUE }, /* Latvia */ + {"LB", CE, TRUE }, /* Lebanon */ + {"LI", CE, TRUE }, /* Liechtenstein */ + {"LT", CE, TRUE }, /* Lithuania */ + {"LU", CE, TRUE }, /* Luxembourg */ + {"MO", CE, TRUE }, /* Macao */ + {"MK", CE, TRUE }, /* Macedonia, Republic of */ + {"MY", CE, TRUE }, /* Malaysia */ + {"MT", CE, TRUE }, /* Malta */ + {"MX", CE, FALSE }, /* Mexico */ + {"MC", CE, TRUE }, /* Monaco */ + {"MA", CE, TRUE }, /* Morocco */ + {"NP", CE, TRUE }, /* Nepal */ + {"NL", CE, TRUE }, /* Netherlands */ + {"AN", CE, TRUE }, /* Netherlands Antilles */ + {"NZ", CE, TRUE }, /* New Zealand */ + {"NO", CE, TRUE }, /* Norway */ + {"OM", CE, TRUE }, /* Oman */ + {"PK", CE, TRUE }, /* Pakistan */ + {"PA", CE, TRUE }, /* Panama */ + {"PG", CE, TRUE }, /* Papua New Guinea */ + {"PE", CE, TRUE }, /* Peru */ + {"PH", CE, TRUE }, /* Philippines */ + {"PL", CE, TRUE }, /* Poland */ + {"PT", CE, TRUE }, /* Portuga l*/ + {"PR", CE, TRUE }, /* Puerto Rico */ + {"QA", CE, TRUE }, /* Qatar */ + {"RO", CE, TRUE }, /* Romania */ + {"RU", CE, FALSE }, /* Russian Federation */ + {"BL", CE, TRUE }, /* Saint Barth'elemy */ + {"SA", CE, TRUE }, /* Saudi Arabia */ + {"SG", CE, TRUE }, /* Singapore */ + {"SK", CE, TRUE }, /* Slovakia */ + {"SI", CE, TRUE }, /* Slovenia */ + {"ZA", CE, FALSE }, /* South Africa */ + {"ES", CE, TRUE }, /* Spain */ + {"LK", CE, TRUE }, /* Sri Lanka */ + {"SE", CE, TRUE }, /* Sweden */ + {"CH", CE, TRUE }, /* Switzerland */ + {"SY", CE, TRUE }, /* Syrian Arab Republic */ + {"TW", FCC, FALSE}, /* Taiwan */ + {"TH", CE, FALSE }, /* Thailand */ + {"TT", CE, TRUE }, /* Trinidad and Tobago */ + {"TN", CE, TRUE }, /* Tunisia */ + {"TR", CE, TRUE }, /* Turkey */ + {"UA", CE, TRUE }, /* Ukraine */ + {"AE", CE, TRUE }, /* United Arab Emirates */ + {"GB", CE, TRUE }, /* United Kingdom */ + {"US", FCC, FALSE}, /* United States */ + {"UY", CE, TRUE }, /* Uruguay */ + {"UZ", CE, TRUE }, /* Uzbekistan */ + {"VE", CE, TRUE }, /* Venezuela */ + {"VN", CE, TRUE }, /* Viet Nam */ + {"YE", CE, TRUE }, /* Yemen */ + {"ZW", CE, TRUE }, /* Zimbabwe */ + {"EU", CE, TRUE }, /* Europe */ + {"NA", FCC, FALSE}, /* North America */ + {"WO", FCC, FALSE}, /* World Wide */ + {"" , 0, FALSE} , /* End */ +}; + +#ifndef EXT_BUILD_CHANNEL_LIST +PCOUNTRY_PROP GetCountryProp( + IN PUCHAR CntryCode) +{ + INT loop = 0; + PCOUNTRY_PROP pCountryProp = NULL; + + while (strcmp((RTMP_STRING *) CountryProp[loop].CountReg, "") != 0) + { + if (strncmp((RTMP_STRING *) CountryProp[loop].CountReg, (RTMP_STRING *) CntryCode, 2) == 0) + { + pCountryProp = &CountryProp[loop]; + break; + } + loop++; + } + + /* Default: use WO*/ + if (pCountryProp == NULL) + pCountryProp = GetCountryProp("WO"); + + return pCountryProp; +} +#endif /* !EXT_BUILD_CHANNEL_LIST */ +BOOLEAN GetEDCCASupport( + IN PRTMP_ADAPTER pAd) +{ + BOOLEAN ret = FALSE; + +#ifdef EXT_BUILD_CHANNEL_LIST + PCH_REGION pChReg; + + pChReg = GetChRegion(pAd->CommonCfg.CountryCode); + + if ((pChReg->DfsType == CE) && (pChReg->edcca_on == TRUE) ) + { + // actually need to check PM's table in CE country + ret = TRUE; + } +#else + PCOUNTRY_PROP pCountryProp; + + pCountryProp = GetCountryProp(pAd->CommonCfg.CountryCode); + + if ((pCountryProp->DfsType == CE) && (pCountryProp->edcca_on == TRUE)) + { + // actually need to check PM's table in CE country + ret = TRUE; + } +#endif + + return ret; + +} +#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(RTMP_ADAPTER *pAd) +{ + INT idx; + UCHAR Channel = pAd->CommonCfg.Channel; + static const UCHAR wfa_ht_ch_ext[] = { + 36, EXTCHA_ABOVE, 40, EXTCHA_BELOW, + 44, EXTCHA_ABOVE, 48, EXTCHA_BELOW, + 52, EXTCHA_ABOVE, 56, EXTCHA_BELOW, + 60, EXTCHA_ABOVE, 64, EXTCHA_BELOW, + 100, EXTCHA_ABOVE, 104, EXTCHA_BELOW, + 108, EXTCHA_ABOVE, 112, EXTCHA_BELOW, + 116, EXTCHA_ABOVE, 120, EXTCHA_BELOW, + 124, EXTCHA_ABOVE, 128, EXTCHA_BELOW, + 132, EXTCHA_ABOVE, 136, EXTCHA_BELOW, + 149, EXTCHA_ABOVE, 153, EXTCHA_BELOW, + 157, EXTCHA_ABOVE, 161, EXTCHA_BELOW, + 0, 0}; + + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40)) + { + if (Channel > 14) + { + idx = 0; + while(wfa_ht_ch_ext[idx] != 0) { + if (wfa_ht_ch_ext[idx] == Channel) { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = wfa_ht_ch_ext[idx + 1]; + break; + } + idx += 2; + }; + if (wfa_ht_ch_ext[idx] == 0) + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + } + else + { + do + { + UCHAR ExtCh; + UCHAR Dir = pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; + ExtCh = GetExtCh(Channel, Dir); + if (IsValidChannel(pAd, ExtCh)) + break; + + Dir = (Dir == EXTCHA_ABOVE) ? EXTCHA_BELOW : EXTCHA_ABOVE; + ExtCh = GetExtCh(Channel, Dir); + if (IsValidChannel(pAd, ExtCh)) + { + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = Dir; + break; + } + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + } while(FALSE); + + if (Channel == 14) + { + pAd->CommonCfg.RegTransmitSetting.field.BW = BW_20; + /*pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = EXTCHA_NONE; We didn't set the ExtCh as NONE due to it'll set in RTMPSetHT()*/ + } + } + } +} + + +UCHAR N_SetCenCh(RTMP_ADAPTER *pAd, UCHAR prim_ch) +{ + if (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + { + if (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + pAd->CommonCfg.CentralChannel = prim_ch + 2; + else + { + if (prim_ch == 14) + pAd->CommonCfg.CentralChannel = prim_ch - 1; + else + pAd->CommonCfg.CentralChannel = prim_ch - 2; + } + } + else + pAd->CommonCfg.CentralChannel = prim_ch; + + return pAd->CommonCfg.CentralChannel; +} +#endif /* DOT11_N_SUPPORT */ + + +UINT8 GetCuntryMaxTxPwr( + IN PRTMP_ADAPTER pAd, + IN UINT8 channel) +{ + int i; + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (pAd->ChannelList[i].Channel == channel) + break; + } + + if (i == pAd->ChannelListNum) + return 0xff; +#ifdef SINGLE_SKU + if (pAd->CommonCfg.bSKUMode == TRUE) + { + UINT deltaTxStreamPwr = 0; + +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && (pAd->CommonCfg.TxStream == 2)) + deltaTxStreamPwr = 3; /* If 2Tx case, antenna gain will increase 3dBm*/ +#endif /* DOT11_N_SUPPORT */ + + if (pAd->ChannelList[i].RegulatoryDomain == FCC) + { + /* FCC should maintain 20/40 Bandwidth, and without antenna gain */ +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + (pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) && + (channel == 1 || channel == 11)) + return (pAd->ChannelList[i].MaxTxPwr - pAd->CommonCfg.BandedgeDelta - deltaTxStreamPwr); + else +#endif /* DOT11_N_SUPPORT */ + return (pAd->ChannelList[i].MaxTxPwr - deltaTxStreamPwr); + } + else if (pAd->ChannelList[i].RegulatoryDomain == CE) + { + return (pAd->ChannelList[i].MaxTxPwr - pAd->CommonCfg.AntGain - deltaTxStreamPwr); + } + else + return 0xff; + } + else +#endif /* SINGLE_SKU */ + return pAd->ChannelList[i].MaxTxPwr; +} + + +/* for OS_ABL */ +VOID RTMP_MapChannelID2KHZ( + IN UCHAR Ch, + OUT UINT32 *pFreq) +{ + int chIdx; + for (chIdx = 0; chIdx < CH_HZ_ID_MAP_NUM; chIdx++) + { + if ((Ch) == CH_HZ_ID_MAP[chIdx].channel) + { + (*pFreq) = CH_HZ_ID_MAP[chIdx].freqKHz * 1000; + break; + } + } + if (chIdx == CH_HZ_ID_MAP_NUM) + (*pFreq) = 2412000; +} + +/* for OS_ABL */ +VOID RTMP_MapKHZ2ChannelID( + IN ULONG Freq, + OUT INT *pCh) +{ + int chIdx; + for (chIdx = 0; chIdx < CH_HZ_ID_MAP_NUM; chIdx++) + { + if ((Freq) == CH_HZ_ID_MAP[chIdx].freqKHz) + { + (*pCh) = CH_HZ_ID_MAP[chIdx].channel; + break; + } + } + if (chIdx == CH_HZ_ID_MAP_NUM) + (*pCh) = 1; +} + +UCHAR RTMP_GetPrimaryCh(RTMP_ADAPTER *pAd, UCHAR ch) +{ + UCHAR primCh = 0; + + if ((ch != pAd->CommonCfg.Channel) + && (ch != pAd->CommonCfg.CentralChannel) +#ifdef DOT11_VHT_AC + && (ch != pAd->CommonCfg.vht_cent_ch) +#endif /* DOT11_VHT_AC */ + ) + { + if ((ch > 2) && + (pAd->CommonCfg.BBPCurrentBW == BW_40) && + (pAd->CommonCfg.CentralChannel == EXTCHA_ABOVE) + ) + { + primCh = (ch - 2); + } + else if ((pAd->CommonCfg.BBPCurrentBW == BW_40) && + (pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset == EXTCHA_BELOW)) + { + if (ch == 14) + primCh = (ch + 1); + else + primCh = (ch + 2); + } + else + primCh = ch; + } + else + primCh = pAd->CommonCfg.Channel; + + + return primCh; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt_led.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt_led.c new file mode 100644 index 000000000..c54075584 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt_led.c @@ -0,0 +1,565 @@ +/**************************************************************************** + * 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_ANDES_SUPPORT +INT LED_Array[16][12]={ + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 0, 2, 1, 0, -1, -1, 0, -1, 5, -1, -1, 17}, + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 3, 2, -1, -1, -1, -1, 16, 1, 5, -1, -1, 17}, + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, + { 1, 2, 1, -1, -1, -1, 3, -1, 6, -1, -1, 0}, + { 1, 2, 1, -1, -1, -1, -1, 1, 4, -1, -1, 18} +}; +#endif /* CONFIG_ANDES_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(RTMP_ADAPTER *pAd, UCHAR Status) +{ + /*ULONG data; */ + UCHAR LinkStatus = 0; + UCHAR LedMode; + UCHAR MCUCmd = 0; + BOOLEAN bIgnored = FALSE; +#ifdef MT7603 + INT LED_CMD = -1; +#endif /*MT7603*/ +#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 */ +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ + +#ifdef CONFIG_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 /* CONFIG_ATE */ + + + + LedMode = 1;//LED_MODE(pAd); +#ifdef MT7603 + if (IS_MT7603(pAd)) + { + if (LedMode < 0 || Status <0 || LedMode > 15 || Status > 11) + return; + else + LED_CMD = LED_Array[LedMode][Status]; + } +#endif /*MT7603*/ + 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 CONFIG_ATE +#endif /* CONFIG_ATE */ +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT + case LED_WPS_IN_PROCESS: + if (WscSupportWPSLEDMode(pAd)) + { + LinkStatus = LINK_STATUS_WPS_IN_PROCESS; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_IN_PROCESS; + DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_IN_PROCESS\n", __FUNCTION__)); + } + else + bIgnored = TRUE; + break; + case LED_WPS_ERROR: + if (WscSupportWPSLEDMode(pAd)) + { + /* In the case of LED mode 9, the error LED should be turned on only after WPS walk time expiration. */ + if ((pWscControl->bWPSWalkTimeExpiration == FALSE) && + (LED_MODE(pAd) == WPS_LED_MODE_9)) + { + /* do nothing. */ + } + else + { + LinkStatus = LINK_STATUS_WPS_ERROR; + MCUCmd = MCU_SET_WPS_LED_MODE; + } + + pWscControl->WscLEDMode = LED_WPS_ERROR; + pWscControl->WscLastWarningLEDMode = LED_WPS_ERROR; + + } + else + bIgnored = TRUE; + break; + case LED_WPS_SESSION_OVERLAP_DETECTED: + if (WscSupportWPSLEDMode(pAd)) + { + LinkStatus = LINK_STATUS_WPS_SESSION_OVERLAP_DETECTED; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_SESSION_OVERLAP_DETECTED; + pWscControl->WscLastWarningLEDMode = LED_WPS_SESSION_OVERLAP_DETECTED; + } + else + bIgnored = TRUE; + break; + case LED_WPS_SUCCESS: + if (WscSupportWPSLEDMode(pAd)) + { + if ((LED_MODE(pAd) == WPS_LED_MODE_7) || + (LED_MODE(pAd) == WPS_LED_MODE_11) || + (LED_MODE(pAd) == WPS_LED_MODE_12) + ) + { + /* In the WPS LED mode 7, 11 and 12, the blue LED would last 300 seconds regardless of the AP's security settings. */ + LinkStatus = LINK_STATUS_WPS_SUCCESS_WITH_SECURITY; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_SUCCESS; + + /* Turn off the WPS successful LED pattern after 300 seconds. */ + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_SUCCESSFUL_LED_PATTERN_TIMEOUT); + } + else if (LED_MODE(pAd) == WPS_LED_MODE_8) /* The WPS LED mode 8 */ + { + if (WscAPHasSecuritySetting(pAd, pWscControl)) /* The WPS AP has the security setting. */ + { + LinkStatus = LINK_STATUS_WPS_SUCCESS_WITH_SECURITY; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_SUCCESS; + + /* Turn off the WPS successful LED pattern after 300 seconds. */ + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_SUCCESSFUL_LED_PATTERN_TIMEOUT); + } + else /* The WPS AP does not have the secuirty setting. */ + { + LinkStatus = LINK_STATUS_WPS_SUCCESS_WITHOUT_SECURITY; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_SUCCESS; + + /* Turn off the WPS successful LED pattern after 300 seconds. */ + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_SUCCESSFUL_LED_PATTERN_TIMEOUT); + } + } + else if (LED_MODE(pAd) == WPS_LED_MODE_9) /* The WPS LED mode 9. */ + { + /* Always turn on the WPS blue LED for 300 seconds. */ + LinkStatus = LINK_STATUS_WPS_BLUE_LED; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_SUCCESS; + + /* Turn off the WPS successful LED pattern after 300 seconds. */ + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_SUCCESSFUL_LED_PATTERN_TIMEOUT); + + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_SUCCESS (Incorrect LED mode = %d)\n", + __FUNCTION__, LED_MODE(pAd))); + ASSERT(FALSE); + } + } + else + bIgnored = TRUE; + break; + case LED_WPS_TURN_LED_OFF: + if (WscSupportWPSLEDMode(pAd)) + { + LinkStatus = LINK_STATUS_WPS_TURN_LED_OFF; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_TURN_LED_OFF; + } + else + bIgnored = TRUE; + break; + case LED_WPS_TURN_ON_BLUE_LED: + if (WscSupportWPSLEDMode(pAd)) + { + LinkStatus = LINK_STATUS_WPS_BLUE_LED; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_SUCCESS; + } + else + bIgnored = TRUE; + break; + case LED_NORMAL_CONNECTION_WITHOUT_SECURITY: + if (WscSupportWPSLEDMode(pAd)) + { + LinkStatus = LINK_STATUS_NORMAL_CONNECTION_WITHOUT_SECURITY; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_SUCCESS; + } + else + bIgnored = TRUE; + break; + case LED_NORMAL_CONNECTION_WITH_SECURITY: + if (WscSupportWPSLEDMode(pAd)) + { + LinkStatus = LINK_STATUS_NORMAL_CONNECTION_WITH_SECURITY; + MCUCmd = MCU_SET_WPS_LED_MODE; + pWscControl->WscLEDMode = LED_WPS_SUCCESS; + } + else + bIgnored = TRUE; + break; + /*WPS LED Mode 10 */ + case LED_WPS_MODE10_TURN_ON: + if(WscSupportWPSLEDMode10(pAd)) + { + LinkStatus = LINK_STATUS_WPS_MODE10_TURN_ON; + MCUCmd = MCU_SET_WPS_LED_MODE; + } + else + bIgnored = TRUE; + break; + case LED_WPS_MODE10_FLASH: + if(WscSupportWPSLEDMode10(pAd)) + { + LinkStatus = LINK_STATUS_WPS_MODE10_FLASH; + MCUCmd = MCU_SET_WPS_LED_MODE; + } + else + bIgnored = TRUE; + break; + case LED_WPS_MODE10_TURN_OFF: + if(WscSupportWPSLEDMode10(pAd)) + { + LinkStatus = LINK_STATUS_WPS_MODE10_TURN_OFF; + MCUCmd = MCU_SET_WPS_LED_MODE;; + } + else + bIgnored = TRUE; + break; +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ + default: + DBGPRINT(RT_DEBUG_WARN, ("RTMPSetLED::Unknown Status 0x%x\n", Status)); + break; + } + +#ifdef MT7603 + if (IS_MT7603(pAd)) + { + AndesLedOP(pAd, 0, LED_CMD); + DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_CMD:0x%x, LED Mode:0x%x, LinkStatus:0x%x\n", __FUNCTION__, LED_CMD, LedMode, LinkStatus)); + } else +#endif /*MT7603*/ + 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(RTMP_ADAPTER *pAd, 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(RTMP_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(RTMP_ADAPTER *pAd, 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 rtmp_read_led_setting_from_eeprom(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) +{ +} + + +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) +{ + + RTMPSetLED(pAd, LED_RADIO_OFF); + + return; +} + +#endif /* LED_CONTROL_SUPPORT */ + + +INT RTMPSetLED(RTMP_ADAPTER *pAd, UCHAR Status) +{ + // TODO: shiang-7603 + +#ifdef LED_CONTROL_METHOD_1 + if (pAd->LedCntl.LedConfigMethod == 1) + return TRUE; +#endif /* LED_CONTROL_Method1 */ + + +#ifdef RTMP_MAC_PCI + if (IS_PCI_INF(pAd) || IS_RBUS_INF(pAd)) + { +#ifdef LED_CONTROL_SUPPORT + RTMPSetLEDStatus(pAd, Status); +#endif /* LED_CONTROL_SUPPORT */ + } +#endif /* RTMP_MAC_PCI */ + + return TRUE; +} + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt_os_util.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt_os_util.c new file mode 100644 index 000000000..d54ca300b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rt_os_util.c @@ -0,0 +1,140 @@ +/**************************************************************************** + + 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,/* CCK and OFDM */ + 13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260, + 39, 78, 117, 156, 234, 312, 351, 390, /* BW 20, 800ns GI, MCS 0~23 */ + 27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, + 81, 162, 243, 324, 486, 648, 729, 810, /* BW 40, 800ns GI, MCS 0~23 */ + 14, 29, 43, 57, 87, 115, 130, 144, 29, 59, 87, 115, 173, 230, 260, 288, + 43, 87, 130, 173, 260, 317, 390, 433, /* BW 20, 400ns GI, MCS 0~23 */ + 30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, + 90, 180, 270, 360, 540, 720, 810, 900, /* BW 40, 400ns GI, MCS 0~23 */ + 13, 26, 39, 52, 78, 104, 117, 130, 156, /* 11ac: 20Mhz, 800ns GI, MCS: 0~8 */ + 27, 54, 81, 108, 162, 216, 243, 270, 324, 360, /*11ac: 40Mhz, 800ns GI, MCS: 0~9 */ + 59, 117, 176, 234, 351, 468, 527, 585, 702, 780, /*11ac: 80Mhz, 800ns GI, MCS: 0~9 */ + 14, 29, 43, 57, 87, 115, 130, 144, 173, /* 11ac: 20Mhz, 400ns GI, MCS: 0~8 */ + 30, 60, 90, 120, 180, 240, 270, 300, 360, 400, /*11ac: 40Mhz, 400ns GI, MCS: 0~9 */ + 65, 130, 195, 260, 390, 520, 585, 650, 780, 867, /*11ac: 80Mhz, 400ns GI, MCS: 0~9 */ + 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 UINT8 MODE, + IN UINT8 ShortGI, + IN UINT8 BW, + IN UINT8 MCS, + OUT UINT32 *pRate) +{ + int rate_index = 0; + +#ifdef DOT11_VHT_AC + if (MODE >= MODE_VHT) + { + if (BW == 0/*20Mhz*/) { + rate_index = 112 + + ((UCHAR)ShortGI * 29) + + ((UCHAR)MCS); + } + else if (BW == 1/*40Mhz*/) { + rate_index = 121 + + ((UCHAR)ShortGI * 29) + + ((UCHAR)MCS); + } + else if (BW == 2/*80Mhz*/) { + rate_index = 131 + + ((UCHAR)ShortGI * 29) + + ((UCHAR)MCS); + } + } + else +#endif /* DOT11_VHT_AC */ + +#ifdef DOT11_N_SUPPORT + if ((MODE >= MODE_HTMIX) && (MODE < MODE_VHT)) + { + /* 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)) +{ +} + + + + +BOOLEAN RtmpOsCmdDisplayLenCheck( + IN UINT32 LenSrc, + IN UINT32 Offset) +{ + if (LenSrc > (IW_PRIV_SIZE_MASK - Offset)) + return FALSE; + + return TRUE; +} + + + + + + +INT32 RtPrivIoctlSetVal(VOID) +{ + return (INT32)RTPRIV_IOCTL_SET; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rtmp_init.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rtmp_init.c new file mode 100644 index 000000000..a0d9eb2ad --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rtmp_init.c @@ -0,0 +1,2737 @@ +/* + *************************************************************************** + * 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" + +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +#include "ecc.h" +#endif + +#ifdef OS_ABL_FUNC_SUPPORT +/* Os utility link: printk, scanf */ +RTMP_OS_ABL_OPS RaOsOps, *pRaOsOps = &RaOsOps; +#endif /* OS_ABL_FUNC_SUPPORT */ + +UCHAR NUM_BIT8[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; +#ifdef DBG +char *CipherName[] = {"none","wep64","wep128","TKIP","AES","CKIP64","CKIP128","CKIP152","SMS4","WEP152"}; +#endif + + + +/* + Use the global variable is not a good solution. + But we can not put it to pAd and use the lock in pAd of RALINK_TIMER_STRUCT; + Or when the structure is cleared, we maybe get NULL for pAd and can not lock. + Maybe we can put pAd in RTMPSetTimer/ RTMPModTimer/ RTMPCancelTimer. +*/ +NDIS_SPIN_LOCK TimerSemLock; + + +/* + ======================================================================== + + Routine Description: + Allocate RTMP_ADAPTER data block and do some initialization + + Arguments: + Adapter Pointer to our adapter + + Return Value: + NDIS_STATUS_SUCCESS + NDIS_STATUS_FAILURE + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS RTMPAllocAdapterBlock(VOID *handle, VOID **ppAdapter) +{ + RTMP_ADAPTER *pAd = NULL; + NDIS_STATUS Status; + INT index; + +#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*/ + Status = AdapterBlockAllocateMemory(handle, (PVOID *)&pAd, sizeof(RTMP_ADAPTER)); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("Failed to allocate memory - ADAPTER\n")); + break; + } + else + { + /* init resource list (must be after pAd allocation) */ + initList(&pAd->RscTimerMemList); + initList(&pAd->RscTaskMemList); + initList(&pAd->RscLockMemList); + initList(&pAd->RscTaskletMemList); + initList(&pAd->RscSemMemList); + initList(&pAd->RscAtomicMemList); + + initList(&pAd->RscTimerCreateList); + + pAd->OS_Cookie = handle; + ((POS_COOKIE)(handle))->pAd_va = (UINT32)pAd; + } + DBGPRINT(RT_DEBUG_OFF, ("\n\n=== pAd = %p, size = %d ===\n\n", pAd, 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 + for (index = 0; index < NUM_OF_RX_RING; index++) + NdisAllocateSpinLock(pAd, &pAd->RxRingLock[index]); + +#ifdef CONFIG_ANDES_SUPPORT + NdisAllocateSpinLock(pAd, &pAd->CtrlRingLock); +#endif /* CONFIG_ANDES_SUPPORT */ + +#ifdef MT_MAC + NdisAllocateSpinLock(pAd, &pAd->BcnRingLock); +#endif /* MT_MAC */ + + NdisAllocateSpinLock(pAd, &pAd->tssi_lock); +#endif /* RTMP_MAC_PCI */ + +#if defined(RT3290) || defined(RLT_MAC) + NdisAllocateSpinLock(pAd, &pAd->WlanEnLock); +#endif /* defined(RT3290) || defined(RLT_MAC) */ + + for (index =0 ; index < NUM_OF_TX_RING; index++) + { + NdisAllocateSpinLock(pAd, &pAd->TxSwQueueLock[index]); + NdisAllocateSpinLock(pAd, &pAd->DeQueueLock[index]); + pAd->DeQueueRunning[index] = FALSE; + } + +#ifdef RESOURCE_PRE_ALLOC + /* + move this function from rt28xx_init() to here. now this function only allocate memory and + leave the initialization job to RTMPInitTxRxRingMemory() which called in rt28xx_init(). + */ + Status = RTMPAllocTxRxRingMemory(pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("Failed to allocate memory - TxRxRing\n")); + break; + } +#endif /* RESOURCE_PRE_ALLOC */ + + NdisAllocateSpinLock(pAd, &pAd->irq_lock); + +#ifdef RTMP_MAC_PCI + NdisAllocateSpinLock(pAd, &pAd->LockInterrupt); +#endif /* RTMP_MAC_PCI */ + + NdisAllocateSpinLock(pAd, &TimerSemLock); + + + +#ifdef CONFIG_ATE +#endif /* CONFIG_ATE */ + + *ppAdapter = (VOID *)pAd; + } while (FALSE); + + if (Status != NDIS_STATUS_SUCCESS) + { + if (pAd) + { + if (pAd->stats) { + os_free_mem(NULL, pAd->stats); + pAd->stats = NULL; + } + + if (pAd->iw_stats) { + os_free_mem(NULL, pAd->iw_stats); + pAd->iw_stats = NULL; + } + + RtmpOsVfree(pAd); + + } + + return Status; + } + + /* Init ProbeRespIE Table */ + for (index = 0; index < MAX_LEN_OF_BSS_TABLE; index++) + { + if (os_alloc_mem(pAd,&pAd->ProbeRespIE[index].pIe, MAX_VIE_LEN) == NDIS_STATUS_SUCCESS) + RTMPZeroMemory(pAd->ProbeRespIE[index].pIe, MAX_VIE_LEN); + else + pAd->ProbeRespIE[index].pIe = NULL; + } + + /*init queue for ip assembly*/ +#if defined(MT_MAC) && defined(IP_ASSEMBLY) + for(index = 0; index < NUM_OF_TX_RING ; index++) + { + DlListInit(&pAd->assebQueue[index]); + } +#endif + + DBGPRINT_S(("<-- RTMPAllocAdapterBlock, Status=%x\n", Status)); + + return Status; +} + + +BOOLEAN RTMPCheckPhyMode(RTMP_ADAPTER *pAd, UINT8 band_cap, UCHAR *pPhyMode) +{ + BOOLEAN RetVal = TRUE; + + if (band_cap == RFIC_24GHZ) + { + if (!WMODE_2G_ONLY(*pPhyMode)) + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): Warning! The board type is 2.4G only!\n", + __FUNCTION__)); + RetVal = FALSE; + } + } + else if (band_cap == RFIC_5GHZ) + { + if (!WMODE_5G_ONLY(*pPhyMode)) + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): Warning! The board type is 5G only!\n", + __FUNCTION__)); + RetVal = FALSE; + } + } + else if (band_cap == RFIC_DUAL_BAND) + { + RetVal = TRUE; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): Unknown supported band (%u), assume dual band used.\n", + __FUNCTION__, band_cap)); + + RetVal = TRUE; + } + + if (RetVal == FALSE) + { +#ifdef DOT11_N_SUPPORT + if (band_cap == RFIC_5GHZ) /*5G ony: change to A/N mode */ + *pPhyMode = PHY_11AN_MIXED; + else /* 2.4G only or Unknown supported band: change to B/G/N mode */ + *pPhyMode = PHY_11BGN_MIXED; +#else + if (band_cap == RFIC_5GHZ) /*5G ony: change to A mode */ + *pPhyMode = PHY_11A; + else /* 2.4G only or Unknown supported band: change to B/G mode */ + *pPhyMode = PHY_11BG_MIXED; +#endif /* !DOT11_N_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): Changed PhyMode to %u\n", + __FUNCTION__, *pPhyMode)); + } + + return RetVal; + +} + + +/* + ======================================================================== + + Routine Description: + Set default value from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID NICInitAsicFromEEPROM(RTMP_ADAPTER *pAd) +{ +#ifdef CONFIG_ATE + USHORT value; +#endif /* CONFIG_ATE */ + EEPROM_NIC_CONFIG2_STRUC NicConfig2; + + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitAsicFromEEPROM\n")); + + NicConfig2.word = pAd->NicConfig2.word; + + /* finally set primary ant */ + AntCfgInit(pAd); + + RTMP_CHIP_ASIC_INIT_TEMPERATURE_COMPENSATION(pAd); + +#ifdef RTMP_RF_RW_SUPPORT + /*Init RFRegisters after read RFIC type from EEPROM*/ + InitRFRegisters(pAd); +#endif /* RTMP_RF_RW_SUPPORT */ + + + +#ifdef WIN_NDIS + /* Turn off patching for cardbus controller */ + /* + if (NicConfig2.field.CardbusAcceleration == 1) + pAd->bTest1 = TRUE; + */ +#endif /* WIN_NDIS */ + + if (NicConfig2.field.DynamicTxAgcControl == 1) + pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = TRUE; + else + pAd->bAutoTxAgcA = pAd->bAutoTxAgcG = FALSE; + +#ifdef RTMP_INTERNAL_TX_ALC + /* + Internal Tx ALC support is starting from RT3370 / RT3390, which combine PA / LNA in single chip. + The old chipset don't have this, add new feature flag RTMP_INTERNAL_TX_ALC. + */ + + /* Internal Tx ALC */ + if (((NicConfig2.field.DynamicTxAgcControl == 1) && + (NicConfig2.field.bInternalTxALC == 1)) || + ((!IS_RT3390(pAd)) && (!IS_RT3350(pAd)) && + (!IS_RT3352(pAd)) && (!IS_RT5350(pAd)) && + (!IS_RT5390(pAd)) && (!IS_RT3290(pAd)) && (!IS_RT6352(pAd)) && (!IS_MT7601(pAd)))) + { + /* + If both DynamicTxAgcControl and bInternalTxALC are enabled, + it is a wrong configuration. + If the chipset does not support Internal TX ALC, we shall disable it. + */ + pAd->TxPowerCtrl.bInternalTxALC = FALSE; + } + else + { + if (NicConfig2.field.bInternalTxALC == 1) + pAd->TxPowerCtrl.bInternalTxALC = TRUE; + else + pAd->TxPowerCtrl.bInternalTxALC = FALSE; + } + + + /* Old 5390 NIC always disables the internal ALC */ + if ((pAd->MACVersion == 0x53900501) + ) + pAd->TxPowerCtrl.bInternalTxALC = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: pAd->TxPowerCtrl.bInternalTxALC = %d\n", + __FUNCTION__, pAd->TxPowerCtrl.bInternalTxALC)); +#endif /* RTMP_INTERNAL_TX_ALC */ + +#ifdef CONFIG_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 /* CONFIG_ATE */ + + AsicSetRxStream(pAd, pAd->Antenna.field.RxPath); + + + RTMP_EEPROM_ASIC_INIT(pAd); + + + + 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")); +} + + +INT hif_sys_exit(RTMP_ADAPTER *pAd) +{ +#ifdef RESOURCE_PRE_ALLOC + RTMPResetTxRxRingMemory(pAd); +#else + RTMPFreeTxRxRingMemory(pAd); +#endif /* RESOURCE_PRE_ALLOC */ + + return TRUE; +} + + +INT hif_sys_init(RTMP_ADAPTER *pAd, BOOLEAN bHardReset) +{ + NDIS_STATUS status; + + DBGPRINT(RT_DEBUG_TRACE, ("%s()-->\n", __FUNCTION__)); + + RT28XXDMADisable(pAd); + DBGPRINT(RT_DEBUG_TRACE, ("%s():Disable WPDMA\n", __FUNCTION__)); + +#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 err; + } + + +#ifdef WLAN_SKB_RECYCLE + skb_queue_head_init(&pAd->rx0_recycle); +#endif /* WLAN_SKB_RECYCLE */ + +#ifdef RTMP_MAC_PCI + { + /* pbf hardware reset, asic simulation sequence put this ahead before loading firmware */ +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (pAd->chipCap.hif_type == HIF_RTMP || pAd->chipCap.hif_type == HIF_RLT) + { + RTMP_IO_WRITE32(pAd, WPDMA_RST_IDX, 0xffffffff /*0x1003f*/); + + { + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe1f); + RTMP_IO_WRITE32(pAd, PBF_SYS_CTRL, 0xe00); + } + } +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + AsicInitTxRxRing(pAd); + } +#endif /* RTMP_MAC_PCI */ + +#ifdef MT_MAC + mt_hif_sys_init(pAd); +#endif /* MT_MAC */ + + DBGPRINT(RT_DEBUG_TRACE, ("<--%s(), Success!\n", __FUNCTION__)); + return TRUE; + +err: + DBGPRINT(RT_DEBUG_TRACE, ("<--%s(), Err! status=%d\n", __FUNCTION__, status)); + return FALSE; +} + + +/* + ======================================================================== + + Routine Description: + Initialize NIC hardware + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS NICInitializeAdapter(RTMP_ADAPTER *pAd, BOOLEAN bHardReset) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + UINT rty_cnt = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():--> \n", __FUNCTION__)); + + /* Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits */ +retry: + + if (AsicWaitPDMAIdle(pAd, 100, 1000) != TRUE) { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return NDIS_STATUS_FAILURE; + } + + /* Initialze ASIC for TX & Rx operation */ + if (NICInitializeAsic(pAd , bHardReset) != NDIS_STATUS_SUCCESS) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return NDIS_STATUS_FAILURE; + + if (pAd->chipOps.loadFirmware) + { + if (rty_cnt++ == 0) + { + NICLoadFirmware(pAd); + goto retry; + } + } + return NDIS_STATUS_FAILURE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("<--%s()\n", __FUNCTION__)); + return Status; +} + + +INT rtmp_hif_cyc_init(RTMP_ADAPTER *pAd, UINT8 val) +{ + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return FALSE; + } + +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (pAd->chipCap.hif_type == HIF_RTMP || pAd->chipCap.hif_type == HIF_RLT) + { + US_CYC_CNT_STRUC USCycCnt; + + RTMP_IO_READ32(pAd, US_CYC_CNT, &USCycCnt.word); + USCycCnt.field.UsCycCnt = val; + RTMP_IO_WRITE32(pAd, US_CYC_CNT, USCycCnt.word); + } +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + return TRUE; +} + + +/* + ======================================================================== + + Routine Description: + Initialize ASIC + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +NDIS_STATUS NICInitializeAsic(RTMP_ADAPTER *pAd, BOOLEAN bHardReset) +{ + DBGPRINT(RT_DEBUG_TRACE, ("--> NICInitializeAsic\n")); + +#ifdef RTMP_MAC_PCI + NICInitPwrPinCfg(pAd); +#endif /* RTMP_MAC_PCI */ + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support rtmp_mac_sys_reset () for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + } else { +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (rtmp_mac_sys_reset(pAd, bHardReset) == FALSE) + return NDIS_STATUS_FAILURE; +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + } + + +#ifdef RTMP_PCI_SUPPORT + pAd->CommonCfg.bPCIeBus = FALSE; +#ifdef RTMP_MAC + if ((pAd->chipCap.hif_type == HIF_RTMP) && IS_PCI_INF(pAd)) + { + { + UINT32 mac_val = 0; + + /* PCI and PCIe have different cyc value */ + RTMP_IO_READ32(pAd, PCI_CFG, &mac_val); + if ((mac_val & 0x10000) == 0) + { + rtmp_hif_cyc_init(pAd, 0x7d); + pAd->CommonCfg.bPCIeBus = TRUE; + } + } + } +#endif /* RTMP_MAC */ + DBGPRINT(RT_DEBUG_TRACE, ("%s():device act as PCI%s driver\n", + __FUNCTION__, (pAd->CommonCfg.bPCIeBus ? "-E" : ""))); +#endif /* RTMP_PCI_SUPPORT */ + +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (pAd->chipCap.hif_type == HIF_RTMP || pAd->chipCap.hif_type == HIF_RLT) + { + if (pAd->chipOps.FwInit) + pAd->chipOps.FwInit(pAd); + + rtmp_mac_init(pAd); + + rtmp_mac_bcn_buf_init(pAd, bHardReset); + + rtmp_hw_tb_init(pAd, bHardReset); + + } +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + // TODO: shiang-7603, init MAC setting + // TODO: shiang-7603, init beacon buffer + mt_mac_init(pAd); + mt_hw_tb_init(pAd, bHardReset); + } +#endif /* MT_MAC */ + + /* Set the current MAC to ASIC */ + AsicSetDevMac(pAd, pAd->CurrentAddress, 0x0); + + DBGPRINT_RAW(RT_DEBUG_TRACE,("Current MAC: =%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pAd->CurrentAddress))); + + NICInitBBP(pAd); + + + /* Clear raw counters*/ + NicResetRawCounters(pAd); + + + DBGPRINT(RT_DEBUG_TRACE, ("<-- NICInitializeAsic\n")); + + return NDIS_STATUS_SUCCESS; +} + + + +/* + ======================================================================== + + Routine Description: + Reset NIC from error + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + Reset NIC from error state + + ======================================================================== +*/ +VOID NICResetFromError(RTMP_ADAPTER *pAd) +{ + UCHAR rf_channel; + + /* Reset BBP (according to alex, reset ASIC will force reset BBP*/ + /* Therefore, skip the reset BBP*/ + /* RTMP_IO_WRITE32(pAd, MAC_CSR1, 0x2);*/ + // TODO: shaing-7603 + if (IS_MT7603(pAd) || IS_MT7628(pAd)) { + DBGPRINT(RT_DEBUG_OFF, ("%s(): for MT7603\n", __FUNCTION__)); + + NICInitializeAdapter(pAd, FALSE); + + NICInitAsicFromEEPROM(pAd); + + RTMPEnableRxTx(pAd); + + return; + } + +#ifndef MT_MAC + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x1); + /* Remove ASIC from reset state*/ + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, 0x0); +#endif /*ndef MT_MAC */ + + NICInitializeAdapter(pAd, FALSE); + NICInitAsicFromEEPROM(pAd); + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + AsicBBPAdjust(pAd); + } + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + rf_channel = pAd->CommonCfg.CentralChannel; + } +#endif /* CONFIG_AP_SUPPORT */ + +#if defined(CONFIG_AP_SUPPORT) || defined(CONFIG_STA_SUPPORT) + AsicSwitchChannel(pAd, rf_channel, FALSE); + AsicLockChannel(pAd, rf_channel); +#endif /* defined(CONFIG_AP_SUPPORT) || defined(CONFIG_STA_SUPPORT) */ +} + + +VOID NICUpdateFifoStaCounters(RTMP_ADAPTER *pAd) +{ +#ifdef CONFIG_ATE + /* Nothing to do in ATE mode */ + if (ATE_ON(pAd)) + return; +#endif /* CONFIG_ATE */ + + +#ifdef CONFIG_AP_SUPPORT +#endif + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { +// DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", +// __FUNCTION__, __LINE__)); + return; + } + +#if defined(RTMP_MAC) || defined(RLT_MAC) + if (pAd->chipCap.hif_type == HIF_RTMP || pAd->chipCap.hif_type == HIF_RLT) + rtmp_mac_fifo_stat_update(pAd); +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ +} + + +int load_patch(RTMP_ADAPTER *ad) +{ + int ret = NDIS_STATUS_SUCCESS; +#ifdef DBG + ULONG Old, New, Diff; +#endif /* DBG */ + if (ad->chipOps.load_rom_patch) { + +#ifdef DBG + RTMP_GetCurrentSystemTick(&Old); +#endif /* DBG */ + ret = ad->chipOps.load_rom_patch(ad); + +#ifdef DBG + RTMP_GetCurrentSystemTick(&New); +#endif /* DBG */ + +#ifdef DBG + Diff = (New - Old) * 1000 / OS_HZ; + DBGPRINT(RT_DEBUG_TRACE, ("load rom patch spent %ldms\n", Diff)); +#endif /* DBG */ + } + + return ret; +} + + +int NICLoadFirmware(RTMP_ADAPTER *ad) +{ + int ret = NDIS_STATUS_SUCCESS; + ULONG Old, New; + + if (ad->chipOps.loadFirmware) { + RTMP_GetCurrentSystemTick(&Old); + ret = ad->chipOps.loadFirmware(ad); + RTMP_GetCurrentSystemTick(&New); + DBGPRINT(RT_DEBUG_TRACE, ("load fw spent %ldms\n", (New - Old) * 1000 / OS_HZ)); + + } + + return ret; +} + + +VOID NICEraseFirmware(RTMP_ADAPTER *pAd) +{ + if (pAd->chipOps.eraseFirmware) + pAd->chipOps.eraseFirmware(pAd); +} + + +/* + ======================================================================== + + Routine Description: + Compare two memory block + + Arguments: + pSrc1 Pointer to first memory address + pSrc2 Pointer to second memory address + + Return Value: + 0: memory is equal + 1: pSrc1 memory is larger + 2: pSrc2 memory is larger + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +ULONG RTMPCompareMemory(VOID *pSrc1, VOID *pSrc2, ULONG Length) +{ + PUCHAR pMem1; + PUCHAR pMem2; + ULONG Index = 0; + + pMem1 = (PUCHAR) pSrc1; + pMem2 = (PUCHAR) pSrc2; + + for (Index = 0; Index < Length; Index++) + { + if (pMem1[Index] > pMem2[Index]) + return (1); + else if (pMem1[Index] < pMem2[Index]) + return (2); + } + + /* Equal*/ + return (0); +} + + +/* + ======================================================================== + + Routine Description: + Zero out memory block + + Arguments: + pSrc1 Pointer to memory address + Length Size + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPZeroMemory(VOID *pSrc, ULONG Length) +{ + PUCHAR pMem; + ULONG Index = 0; + + pMem = (PUCHAR) pSrc; + + for (Index = 0; Index < Length; Index++) + { + pMem[Index] = 0x00; + } +} + + +/* + ======================================================================== + + Routine Description: + Copy data from memory block 1 to memory block 2 + + Arguments: + pDest Pointer to destination memory address + pSrc Pointer to source memory address + Length Copy size + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPMoveMemory(VOID *pDest, VOID *pSrc, ULONG Length) +{ + PUCHAR pMem1; + PUCHAR pMem2; + UINT Index; + + ASSERT((Length==0) || (pDest && pSrc)); + + pMem1 = (PUCHAR) pDest; + pMem2 = (PUCHAR) pSrc; + + for (Index = 0; Index < Length; Index++) + { + pMem1[Index] = pMem2[Index]; + } +} + + +VOID UserCfgExit(RTMP_ADAPTER *pAd) +{ + +#ifdef DOT11_N_SUPPORT + BATableExit(pAd); +#endif /* DOT11_N_SUPPORT */ + + + NdisFreeSpinLock(&pAd->MacTabLock); + +#ifdef RTMP_PCI_SUPPORT + NdisFreeSpinLock(&pAd->IndirectUpdateLock); +#endif + + +#ifdef MAC_REPEATER_SUPPORT + NdisFreeSpinLock(&pAd->ApCfg.ReptCliEntryLock); +#endif /* MAC_REPEATER_SUPPORT */ +#ifdef BAND_STEERING + if (pAd->ApCfg.BandSteering) { + BndStrg_Release(pAd); + } +#endif /* BAND_STEERING */ + +#ifdef MT_PS + NdisFreeSpinLock(&pAd->PSRetrieveLock); +#endif + +#ifdef DOT11_SAE_SUPPORT + sae_cfg_deinit(pAd, &pAd->SaeCfg); +#endif /* DOT11_SAE_SUPPORT */ +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + group_info_bi_deinit(); +#endif + +} + + +/* + ======================================================================== + + Routine Description: + Initialize port configuration structure + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID UserCfgInit(RTMP_ADAPTER *pAd) +{ + UINT i; +#ifdef CONFIG_AP_SUPPORT + UINT j; +#endif /* CONFIG_AP_SUPPORT */ + UINT key_index, bss_index; + + 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 */ +#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; +#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 = pAd->CommonCfg.PhyMode; + pAd->CommonCfg.BandState = UNKNOWN_BAND; + + pAd->wmm_cw_min = 4; + switch (pAd->OpMode) + { + case OPMODE_AP: + pAd->wmm_cw_max = 6; + break; + case OPMODE_STA: + pAd->wmm_cw_max = 10; + break; + } + + +#ifdef CONFIG_AP_SUPPORT +#ifdef AP_SCAN_SUPPORT + pAd->ApCfg.ACSCheckTime = 0; +#endif /* AP_SCAN_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CARRIER_DETECTION_SUPPORT + pAd->CommonCfg.CarrierDetect.delta = CARRIER_DETECT_DELTA; + pAd->CommonCfg.CarrierDetect.div_flag = CARRIER_DETECT_DIV_FLAG; + pAd->CommonCfg.CarrierDetect.criteria = CARRIER_DETECT_CRITIRIA; + pAd->CommonCfg.CarrierDetect.threshold = CARRIER_DETECT_THRESHOLD; + pAd->CommonCfg.CarrierDetect.recheck1 = CARRIER_DETECT_RECHECK_TIME; + pAd->CommonCfg.CarrierDetect.CarrierGoneThreshold = CARRIER_GONE_TRESHOLD; + pAd->CommonCfg.CarrierDetect.VGA_Mask = CARRIER_DETECT_DEFAULT_MASK; + pAd->CommonCfg.CarrierDetect.Packet_End_Mask = CARRIER_DETECT_DEFAULT_MASK; + pAd->CommonCfg.CarrierDetect.Rx_PE_Mask = CARRIER_DETECT_DEFAULT_MASK; +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef DFS_SUPPORT + pAd->CommonCfg.RadarDetect.bDfsInit = FALSE; +#endif /* DFS_SUPPORT */ + + pAd->Dot11_H.ChMovingTime = 65; + +#ifdef UAPSD_SUPPORT +#ifdef CONFIG_AP_SUPPORT +{ + UINT32 IdMbss; + + for(IdMbss=0; IdMbssApCfg.MBSSID[IdMbss].wdev.UapsdInfo); +} +#endif /* CONFIG_AP_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; + +#ifdef DOT11_N_SUPPORT + NdisZeroMemory(&pAd->CommonCfg.HtCapability, sizeof(pAd->CommonCfg.HtCapability)); + pAd->bBroadComHT = FALSE; + pAd->CommonCfg.bRdg = FALSE; + +#ifdef DOT11N_DRAFT3 + pAd->CommonCfg.Dot11OBssScanPassiveDwell = dot11OBSSScanPassiveDwell; /* Unit : TU. 5~1000*/ + pAd->CommonCfg.Dot11OBssScanActiveDwell = dot11OBSSScanActiveDwell; /* Unit : TU. 10~1000*/ + pAd->CommonCfg.Dot11BssWidthTriggerScanInt = dot11BSSWidthTriggerScanInterval; /* Unit : Second */ + pAd->CommonCfg.Dot11OBssScanPassiveTotalPerChannel = dot11OBSSScanPassiveTotalPerChannel; /* Unit : TU. 200~10000*/ + pAd->CommonCfg.Dot11OBssScanActiveTotalPerChannel = dot11OBSSScanActiveTotalPerChannel; /* Unit : TU. 20~10000*/ + pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor = dot11BSSWidthChannelTransactionDelayFactor; + pAd->CommonCfg.Dot11OBssScanActivityThre = dot11BSSScanActivityThreshold; /* Unit : percentage*/ + pAd->CommonCfg.Dot11BssWidthChanTranDelay = (pAd->CommonCfg.Dot11BssWidthTriggerScanInt * pAd->CommonCfg.Dot11BssWidthChanTranDelayFactor); + + pAd->CommonCfg.bBssCoexEnable = TRUE; /* by default, we enable this feature, you can disable it via the profile or ioctl command*/ + pAd->CommonCfg.BssCoexApCntThr = 0; + pAd->CommonCfg.Bss2040NeedFallBack = 0; +#endif /* DOT11N_DRAFT3 */ + + pAd->CommonCfg.bRcvBSSWidthTriggerEvents = FALSE; + + NdisZeroMemory(&pAd->CommonCfg.AddHTInfo, sizeof(pAd->CommonCfg.AddHTInfo)); + pAd->CommonCfg.BACapability.field.MMPSmode = MMPS_DISABLE; + pAd->CommonCfg.BACapability.field.MpduDensity = 0; + pAd->CommonCfg.BACapability.field.Policy = IMMED_BA; + pAd->CommonCfg.BACapability.field.RxBAWinLimit = 64; /*32;*/ + pAd->CommonCfg.BACapability.field.TxBAWinLimit = 64; /*32;*/ + DBGPRINT(RT_DEBUG_TRACE, ("--> UserCfgInit. BACapability = 0x%x\n", pAd->CommonCfg.BACapability.word)); + + pAd->CommonCfg.BACapability.field.AutoBA = FALSE; + BATableInit(pAd, &pAd->BATable); + + pAd->CommonCfg.bExtChannelSwitchAnnouncement = 1; + pAd->CommonCfg.bHTProtect = 1; + pAd->CommonCfg.bMIMOPSEnable = TRUE; +#ifdef GREENAP_SUPPORT + pAd->ApCfg.bGreenAPEnable=FALSE; + pAd->ApCfg.bGreenAPActive = FALSE; + pAd->ApCfg.GreenAPLevel= GREENAP_WITHOUT_ANY_STAS_CONNECT; +#endif /* GREENAP_SUPPORT */ + pAd->CommonCfg.bBADecline = FALSE; + pAd->CommonCfg.bDisableReordering = FALSE; + + if (pAd->MACVersion == 0x28720200) + pAd->CommonCfg.TxBASize = 13; /*by Jerry recommend*/ + else + pAd->CommonCfg.TxBASize = 7; + + pAd->CommonCfg.REGBACapability.word = pAd->CommonCfg.BACapability.word; +#endif /* DOT11_N_SUPPORT */ + + pAd->CommonCfg.TxRate = RATE_6; + + pAd->CommonCfg.MlmeTransmit.field.MCS = MCS_RATE_6; + pAd->CommonCfg.MlmeTransmit.field.BW = BW_20; + pAd->CommonCfg.MlmeTransmit.field.MODE = MODE_OFDM; + + pAd->CommonCfg.BeaconPeriod = 100; /* in mSec*/ + +#ifdef STREAM_MODE_SUPPORT + if (pAd->chipCap.FlgHwStreamMode) + { + pAd->CommonCfg.StreamMode = 3; + pAd->CommonCfg.StreamModeMCS = 0x0B0B; + NdisMoveMemory(&pAd->CommonCfg.StreamModeMac[0][0], + BROADCAST_ADDR, MAC_ADDR_LEN); + } +#endif /* STREAM_MODE_SUPPORT */ + + +#ifdef NEW_RATE_ADAPT_SUPPORT + pAd->CommonCfg.lowTrafficThrd = 2; + pAd->CommonCfg.TrainUpRule = 2; // 1; + pAd->CommonCfg.TrainUpRuleRSSI = -70; // 0; + pAd->CommonCfg.TrainUpLowThrd = 90; + pAd->CommonCfg.TrainUpHighThrd = 110; +#endif /* NEW_RATE_ADAPT_SUPPORT */ + + + +#ifdef CFO_TRACK +#endif /* CFO_TRACK */ + +#ifdef DBG_CTRL_SUPPORT + pAd->CommonCfg.DebugFlags = 0; +#endif /* DBG_CTRL_SUPPORT */ + +#ifdef WAPI_SUPPORT + pAd->CommonCfg.wapi_usk_rekey_method = REKEY_METHOD_DISABLE; + pAd->CommonCfg.wapi_msk_rekey_method = REKEY_METHOD_DISABLE; + pAd->CommonCfg.wapi_msk_rekey_cnt = 0; +#endif /* WAPI_SUPPORT */ + +#ifdef MCAST_RATE_SPECIFIC + pAd->CommonCfg.MCastPhyMode.word = pAd->MacTab.Content[MCAST_WCID].HTPhyMode.word; +#endif /* MCAST_RATE_SPECIFIC */ + + /* WFA policy - disallow TH rate in WEP or TKIP cipher */ + pAd->CommonCfg.HT_DisallowTKIP = TRUE; + + /* Frequency for rate adaptation */ + pAd->ra_interval = DEF_RA_TIME_INTRVAL; + pAd->ra_fast_interval = DEF_QUICK_RA_TIME_INTERVAL; + +#ifdef AGS_SUPPORT + if (pAd->rateAlg == RATE_ALG_AGS) + pAd->ra_fast_interval = AGS_QUICK_RA_TIME_INTERVAL; +#endif /* AGS_SUPPORT */ + + /* Tx Sw queue length setting */ + pAd->TxSwQMaxLen = MAX_PACKETS_IN_QUEUE; + // TODO: shiang-usw, we may need to move this function to better place. + rtmp_tx_swq_init(pAd); + + pAd->CommonCfg.bRalinkBurstMode = FALSE; + + + /* global variables mXXXX used in MAC protocol state machines*/ + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RECEIVE_DTIM); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_ADHOC_ON); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_INFRA_ON); + + /* PHY specification*/ + pAd->CommonCfg.PhyMode = (WMODE_B | WMODE_G); /* default PHY mode*/ + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); /* CCK use LONG preamble*/ + + + /* Default for extra information is not valid*/ + pAd->ExtraInfo = EXTRA_INFO_CLEAR; + + /* Default Config change flag*/ + pAd->bConfigChanged = FALSE; + + /* + part III. AP configurations + */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* Set MBSS Default Configurations*/ + pAd->ApCfg.BssidNum = MAX_MBSSID_NUM(pAd); + for(j = BSS0; j < pAd->ApCfg.BssidNum; j++) + { + BSS_STRUCT *mbss = &pAd->ApCfg.MBSSID[j]; + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[j].wdev; + + wdev->AuthMode = Ndis802_11AuthModeOpen; + wdev->WepStatus = Ndis802_11EncryptionDisabled; + wdev->GroupKeyWepStatus = Ndis802_11EncryptionDisabled; + wdev->DefaultKeyId = 0; + wdev->WpaMixPairCipher = MIX_CIPHER_NOTUSE; + mbss->RekeyCountDown = 0; /* it's used for WPA rekey */ + + /* init the default 60 seconds*/ + mbss->StationKeepAliveTime = 60; + + mbss->ProbeRspTimes = 3; +#ifdef SPECIFIC_TX_POWER_SUPPORT + if (IS_RT6352(pAd)) + mbss->TxPwrAdj = -1; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + +#ifdef DOT1X_SUPPORT + mbss->wdev.IEEE8021X = FALSE; + mbss->PreAuth = FALSE; + + /* PMK cache setting*/ +#ifdef R1KH_HARD_RETRY/* yiwei no give up! */ + /* profile already set to 120to prevent PMK is delete on DUT */ + mbss->PMKCachePeriod = (120 * 60 * OS_HZ);/* unit : tick(default: 120 minute)*/ +#else/* R1KH_HARD_RETRY */ + mbss->PMKCachePeriod = (10 * 60 * OS_HZ);/* unit : tick(default: 10 minute)*/ +#endif/* !R1KH_HARD_RETRY */ + NdisZeroMemory(&mbss->PMKIDCache, sizeof(NDIS_AP_802_11_PMKID)); + + /* dot1x related per BSS */ + mbss->radius_srv_num = 0; + mbss->NasIdLen = 0; +#endif /* DOT1X_SUPPORT */ + + /* VLAN related */ + mbss->wdev.VLAN_VID = 0; + + /* Default MCS as AUTO*/ + wdev->bAutoTxRateSwitch = TRUE; + wdev->DesiredTransmitSetting.field.MCS = MCS_AUTO; + + /* Default is zero. It means no limit.*/ + mbss->MaxStaNum = 0; + mbss->StaCount = 0; + +#ifdef WSC_AP_SUPPORT + mbss->WscSecurityMode = 0xff; + { + PWSC_CTRL pWscControl; + INT idx; +#ifdef WSC_V2_SUPPORT + PWSC_V2_INFO pWscV2Info; +#endif /* WSC_V2_SUPPORT */ + /* + WscControl cannot be zero here, because WscControl timers are initial in MLME Initialize + and MLME Initialize is called before UserCfgInit. + */ + pWscControl = &mbss->WscControl; + NdisZeroMemory(&pWscControl->RegData, sizeof(WSC_REG_DATA)); + NdisZeroMemory(&pAd->CommonCfg.WscStaPbcProbeInfo, sizeof(WSC_STA_PBC_PROBE_INFO)); + pWscControl->WscMode = 1; + pWscControl->WscConfStatus = 1; +#ifdef WSC_V2_SUPPORT + pWscControl->WscConfigMethods= 0x238C; +#else + pWscControl->WscConfigMethods= 0x0084; +#endif /* WSC_V2_SUPPORT */ +#ifdef WSC_NFC_SUPPORT + pWscControl->WscConfigMethods |= WPS_CONFIG_METHODS_ENT; +#endif /* WSC_NFC_SUPPORT */ + pWscControl->RegData.ReComputePke = 1; + pWscControl->lastId = 1; + /* pWscControl->EntryIfIdx = (MIN_NET_DEVICE_FOR_MBSSID | j); */ + pWscControl->pAd = pAd; + pWscControl->WscRejectSamePinFromEnrollee = FALSE; + pAd->CommonCfg.WscPBCOverlap = FALSE; + pWscControl->WscConfMode = 0; + pWscControl->WscStatus = 0; + pWscControl->WscState = 0; + pWscControl->WscPinCode = 0; + pWscControl->WscLastPinFromEnrollee = 0; + pWscControl->WscEnrollee4digitPinCode = FALSE; + pWscControl->WscEnrolleePinCode = 0; + pWscControl->WscSelReg = 0; + pWscControl->WscUseUPnP = 0; + pWscControl->bWCNTest = FALSE; + pWscControl->WscKeyASCII = 0; /* default, 0 (64 Hex) */ + + /* + Enrollee 192 random bytes for DH key generation + */ + for (idx = 0; idx < 192; idx++) + pWscControl->RegData.EnrolleeRandom[idx] = RandomByte(pAd); + + /* Enrollee Nonce, first generate and save to Wsc Control Block*/ + for (idx = 0; idx < 16; idx++) + pWscControl->RegData.SelfNonce[idx] = RandomByte(pAd); + + NdisZeroMemory(&pWscControl->WscDefaultSsid, sizeof(NDIS_802_11_SSID)); + NdisZeroMemory(&pWscControl->Wsc_Uuid_Str[0], UUID_LEN_STR); + NdisZeroMemory(&pWscControl->Wsc_Uuid_E[0], UUID_LEN_HEX); + pWscControl->bCheckMultiByte = FALSE; + pWscControl->bWscAutoTigeer = FALSE; + pWscControl->bWscFragment = FALSE; + pWscControl->WscFragSize = 128; + pWscControl->WscRxBufLen = 0; + pWscControl->pWscRxBuf = NULL; + os_alloc_mem(pAd, &pWscControl->pWscRxBuf, MGMT_DMA_BUFFER_SIZE); + if (pWscControl->pWscRxBuf) + NdisZeroMemory(pWscControl->pWscRxBuf, MGMT_DMA_BUFFER_SIZE); + pWscControl->WscTxBufLen = 0; + pWscControl->pWscTxBuf = NULL; + os_alloc_mem(pAd, &pWscControl->pWscTxBuf, MGMT_DMA_BUFFER_SIZE); + if (pWscControl->pWscTxBuf) + NdisZeroMemory(pWscControl->pWscTxBuf, MGMT_DMA_BUFFER_SIZE); + initList(&pWscControl->WscPeerList); + NdisAllocateSpinLock(pAd, &pWscControl->WscPeerListSemLock); + pWscControl->PinAttackCount = 0; + pWscControl->bSetupLock = FALSE; + pWscControl->SetupLockTime = WSC_WPS_AP_SETUP_LOCK_TIME; + pWscControl->MaxPinAttack = WSC_WPS_AP_MAX_PIN_ATTACK; +#ifdef WSC_V2_SUPPORT + pWscV2Info = &pWscControl->WscV2Info; + pWscV2Info->bWpsEnable = TRUE; + pWscV2Info->ExtraTlv.TlvLen = 0; + pWscV2Info->ExtraTlv.TlvTag = 0; + pWscV2Info->ExtraTlv.pTlvData = NULL; + pWscV2Info->ExtraTlv.TlvType = TLV_ASCII; + pWscV2Info->bEnableWpsV2 = TRUE; +#ifdef WSC_NFC_SUPPORT + pWscControl->NfcPasswdCaculate = 2; +#endif /* WSC_NFC_SUPPORT */ + +#endif /* WSC_V2_SUPPORT */ + } +#endif /* WSC_AP_SUPPORT */ + + + for(i = 0; i < WLAN_MAX_NUM_OF_TIM; i++) + mbss->TimBitmaps[i] = 0; + +#ifdef DYNAMIC_RX_RATE_ADJ + mbss->SuppRateBitmap = 0xFFF; + mbss->SuppHTRateBitmap = 0xFFFF; +#endif /* DYNAMIC_RX_RATE_ADJ */ + + } + 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 + pAd->bWscDriverAutoUpdateCfg = TRUE; +#endif /* CONFIG_AP_SUPPORT */ +#endif /* WSC_INCLUDED */ + +#ifdef APCLI_SUPPORT + pAd->ApCfg.FlgApCliIsUapsdInfoUpdated = FALSE; + pAd->ApCfg.ApCliNum = MAX_APCLI_NUM; + for(j = 0; j < MAX_APCLI_NUM; j++) + { + APCLI_STRUCT *apcli_entry = &pAd->ApCfg.ApCliTab[j]; + struct wifi_dev *wdev = &apcli_entry->wdev; +#ifdef APCLI_AUTO_CONNECT_SUPPORT + apcli_entry->AutoConnectFlag = FALSE; +#endif + wdev->AuthMode = Ndis802_11AuthModeOpen; + wdev->WepStatus = Ndis802_11WEPDisabled; + wdev->bAutoTxRateSwitch = TRUE; + wdev->DesiredTransmitSetting.field.MCS = MCS_AUTO; + apcli_entry->wdev.UapsdInfo.bAPSDCapable = FALSE; + +#ifdef WSC_AP_SUPPORT + apcli_entry->WscControl.WscApCliScanMode = TRIGGER_FULL_SCAN; +#endif /* WSC_AP_SUPPORT */ + } +#endif /* APCLI_SUPPORT */ + pAd->ApCfg.EntryClientCount = 0; + } + +#ifdef DYNAMIC_VGA_SUPPORT + if (IS_MT76x2(pAd)) { + pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable = FALSE; + pAd->CommonCfg.lna_vga_ctl.nFalseCCATh = 800; + pAd->CommonCfg.lna_vga_ctl.nLowFalseCCATh = 10; + } +#endif /* DYNAMIC_VGA_SUPPORT */ +#ifdef APCLI_SUPPORT +#ifdef ROAMING_ENHANCE_SUPPORT + pAd->ApCfg.bRoamingEnhance= FALSE; +#endif /* ROAMING_ENHANCE_SUPPORT */ +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_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; + +#ifdef RTMP_BBP + pAd->Bbp94 = BBPR94_DEFAULT; +#endif /* RTMP_BBP */ + pAd->BbpForCCK = FALSE; + + /* initialize MAC table and allocate spin lock*/ + NdisZeroMemory(&pAd->MacTab, sizeof(MAC_TABLE)); + InitializeQueueHeader(&pAd->MacTab.McastPsQueue); + NdisAllocateSpinLock(pAd, &pAd->MacTabLock); + + /*RTMPInitTimer(pAd, &pAd->RECBATimer, RECBATimerTimeout, pAd, TRUE);*/ + /*RTMPSetTimer(&pAd->RECBATimer, REORDER_EXEC_INTV);*/ + + + pAd->CommonCfg.bWiFiTest = FALSE; +#ifdef RTMP_MAC_PCI + pAd->bPCIclkOff = FALSE; +#endif /* RTMP_MAC_PCI */ + +#ifdef CONFIG_AP_SUPPORT + pAd->ApCfg.EntryLifeCheck = MAC_ENTRY_LIFE_CHECK_CNT; + +#ifdef DOT11R_FT_SUPPORT + FT_CfgInitial(pAd); +#endif /* DOT11R_FT_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef DOT11_SAE_SUPPORT + sae_cfg_init(pAd, &pAd->SaeCfg); +#endif /* DOT11_SAE_SUPPORT */ + + pAd->RxAnt.Pair1PrimaryRxAnt = 0; + pAd->RxAnt.Pair1SecondaryRxAnt = 1; + pAd->MaxTxPwr = 27; + + pAd->RxAnt.EvaluatePeriod = 0; + pAd->RxAnt.RcvPktNumWhenEvaluate = 0; +#ifdef CONFIG_AP_SUPPORT + pAd->RxAnt.Pair1AvgRssiGroup1[0] = pAd->RxAnt.Pair1AvgRssiGroup1[1] = 0; + pAd->RxAnt.Pair1AvgRssiGroup2[0] = pAd->RxAnt.Pair1AvgRssiGroup2[1] = 0; +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef TXRX_SW_ANTDIV_SUPPORT + pAd->chipCap.bTxRxSwAntDiv = FALSE; +#endif /* TXRX_SW_ANTDIV_SUPPORT */ + + +#if defined(AP_SCAN_SUPPORT) || defined(CONFIG_STA_SUPPORT) + for (i = 0; i < MAX_LEN_OF_BSS_TABLE; i++) + { + BSS_ENTRY *pBssEntry = &pAd->ScanTab.BssEntry[i]; + + if (pAd->ProbeRespIE[i].pIe) + pBssEntry->pVarIeFromProbRsp = pAd->ProbeRespIE[i].pIe; + else + pBssEntry->pVarIeFromProbRsp = NULL; + } +#endif /* defined(AP_SCAN_SUPPORT) || defined(CONFIG_STA_SUPPORT) */ + + +#ifdef WSC_INCLUDED + NdisZeroMemory(&pAd->CommonCfg.WscStaPbcProbeInfo, sizeof(WSC_STA_PBC_PROBE_INFO)); + pAd->CommonCfg.WscPBCOverlap = FALSE; +#endif /* WSC_INCLUDED */ +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) + if (wf_fwd_set_cb_num != NULL) + wf_fwd_set_cb_num(PACKET_BAND_CB, RECV_FROM_CB); +#endif /* CONFIG_WIFI_PKT_FWD */ +#endif + +#ifdef RMTP_RBUS_SUPPORT +#ifdef VIDEO_TURBINE_SUPPORT + VideoConfigInit(pAd); +#endif /* VIDEO_TURBINE_SUPPORT */ +#endif /* RMTP_RBUS_SUPPORT */ + + + + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) || defined(MT_WOW_SUPPORT) + pAd->WOW_Cfg.bEnable = FALSE; + pAd->WOW_Cfg.bWOWFirmware = FALSE; /* load normal firmware */ + pAd->WOW_Cfg.bInBand = TRUE; /* use in-band signal */ + pAd->WOW_Cfg.nSelectedGPIO = 2; + pAd->WOW_Cfg.nDelay = 3; /* (3+1)*3 = 12 sec */ + pAd->WOW_Cfg.nHoldTime = 1000; // unit is us + pAd->WOW_Cfg.nWakeupInterface = WOW_WAKEUP_BY_USB; /* USB as default */ + pAd->WOW_Cfg.bGPIOHighLow = WOW_GPIO_LOW_TO_HIGH; + //DBGPRINT(RT_DEBUG_OFF, ("WOW Enable %d, WOWFirmware %d\n", pAd->WOW_Cfg.bEnable, pAd->WOW_Cfg.bWOWFirmware)); +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) || defined(MT_WOW_SUPPORT) */ + + /* 802.11H and DFS related params*/ + pAd->Dot11_H.CSCount = 0; + pAd->Dot11_H.CSPeriod = 10; + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + pAd->Dot11_H.RDMode = RD_SILENCE_MODE; +#endif + + pAd->Dot11_H.ChMovingTime = 65; + pAd->Dot11_H.bDFSIndoor = 1; + + +#ifdef MAC_REPEATER_SUPPORT + for (i = 0; i < MAX_APCLI_NUM; i++) + { + for (j = 0; j < MAX_EXT_MAC_ADDR_SIZE; j++) + { + NdisZeroMemory(pAd->ApCfg.ApCliTab[i].RepeaterCli[j].OriginalAddress, MAC_ADDR_LEN); + NdisZeroMemory(pAd->ApCfg.ApCliTab[i].RepeaterCli[j].CurrentAddress, MAC_ADDR_LEN); + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].CliConnectState = 0; + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].CliEnable= FALSE; + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].CliValid= FALSE; + pAd->ApCfg.ApCliTab[i].RepeaterCli[j].bEthCli = FALSE; + } + NdisZeroMemory(pAd->ApCfg.ReptMapHash,sizeof(pAd->ApCfg.ReptMapHash)); + NdisZeroMemory(pAd->ApCfg.ReptCliHash,sizeof(pAd->ApCfg.ReptCliHash)); + } + NdisAllocateSpinLock(pAd, &pAd->ApCfg.ReptCliEntryLock); + pAd->ApCfg.RepeaterCliSize = 0; + + NdisZeroMemory(&pAd->ApCfg.ReptControl, sizeof(REPEATER_CTRL_STRUCT)); +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef AP_PARTIAL_SCAN_SUPPORT + pAd->ApCfg.bPartialScanEnable = TRUE; + pAd->ApCfg.bPartialScanning = FALSE; + pAd->ApCfg.PartialScanChannelNum = DEFLAUT_PARTIAL_SCAN_CH_NUM; + pAd->ApCfg.LastPartialScanChannel = 0; + pAd->ApCfg.PartialScanBreakTime = 0; +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + + +#ifdef APCLI_SUPPORT +#ifdef APCLI_AUTO_CONNECT_SUPPORT + pAd->ApCfg.ApCliAutoConnectRunning= FALSE; + pAd->ApCfg.ApCliAutoConnectChannelSwitching = FALSE; +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + +#ifdef DOT11_VHT_AC +#ifdef WFA_VHT_PF + pAd->force_amsdu = FALSE; + pAd->force_noack = FALSE; + pAd->force_vht_op_mode = FALSE; + pAd->vht_force_sgi = FALSE; + pAd->vht_force_tx_stbc = FALSE; + pAd->CommonCfg.vht_nss_cap = pAd->chipCap.max_nss; + pAd->CommonCfg.vht_mcs_cap = pAd->chipCap.max_vht_mcs; + pAd->CommonCfg.vht_cent_ch2 = 0; // we don't support 160MHz BW now! +#endif /* WFA_VHT_PF */ +#endif /* DOT11_VHT_AC */ + +#ifdef CONFIG_FPGA_MODE + pAd->fpga_ctl.fpga_on = 0x0; + pAd->fpga_ctl.tx_kick_cnt = 0; + pAd->fpga_ctl.tx_data_phy = 0; + pAd->fpga_ctl.tx_data_ldpc = 0; + pAd->fpga_ctl.tx_data_mcs = 0; + pAd->fpga_ctl.tx_data_bw = 0; + pAd->fpga_ctl.tx_data_gi = 0; + pAd->fpga_ctl.rx_data_phy = 0; + pAd->fpga_ctl.rx_data_ldpc = 0; + pAd->fpga_ctl.rx_data_mcs = 0; + pAd->fpga_ctl.rx_data_bw = 0; + pAd->fpga_ctl.rx_data_gi = 0; +#ifdef CAPTURE_MODE + pAd->fpga_ctl.cap_type = 2; /* CAP_MODE_ADC8; */ + pAd->fpga_ctl.cap_trigger = 2; /* CAP_TRIGGER_AUTO; */ + pAd->fpga_ctl.trigger_offset = 200; + pAd->fpga_ctl.cap_support = 0; +#endif /* CAPTURE_MODE */ + + pAd->fpga_ctl.dma_mode = DMA_SCH_LMAC; + +#endif /* CONFIG_FPGA_MODE */ + +#ifdef MICROWAVE_OVEN_SUPPORT + if (pAd->OpMode == OPMODE_AP) + pAd->CommonCfg.MO_Cfg.bEnable = TRUE; + else + pAd->CommonCfg.MO_Cfg.bEnable = FALSE; + pAd->CommonCfg.MO_Cfg.nFalseCCATh = MO_FALSE_CCA_TH; +#endif /* MICROWAVE_OVEN_SUPPORT */ + +#ifdef DYNAMIC_VGA_SUPPORT + pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable = TRUE; + pAd->CommonCfg.lna_vga_ctl.nFalseCCATh = 600; + pAd->CommonCfg.lna_vga_ctl.nLowFalseCCATh = 100; +#endif /* DYNAMIC_VGA_SUPPORT */ + + + +#ifdef DOT11_VHT_AC + pAd->CommonCfg.bNonVhtDisallow = FALSE; +#endif /* DOT11_VHT_AC */ + + +#ifdef MT_MAC + pAd->chipCap.TmrEnable = 0; + +#ifdef RTMP_PCI_SUPPORT + NdisAllocateSpinLock(pAd, &pAd->IndirectUpdateLock); +#endif + + pAd->PSEWatchDogEn = 0; + pAd->RxPseCheckTimes = 0; + pAd->PSEResetCount = 0; + pAd->PSETriggerType1Count = 0; + pAd->PSETriggerType1Count = 0; + pAd->PSEResetFailCount = 0; + pAd->pse_reset_exclude_flag = FALSE; +#ifdef DMA_RESET_SUPPORT + pAd->PSEResetFailRecover = FALSE; + pAd->PSEResetFailRetryQuota = 0; + + pAd->bcn_didx_val = 255; + pAd-> bcn_not_idle_tx_dma_busy = 0; + pAd->dma_force_reset_count = 0; + pAd-> pse_reset_flag = FALSE; + pAd->bcn_reset_en = FALSE; + pAd->AC0HitCount = 0; + pAd->AC1HitCount = 0; + pAd->AC2HitCount = 0; + pAd->AC3HitCount = 0; + pAd->MgtHitCount = 0; +#endif /* DMA_RESET_SUPPORT */ +#endif /* MT_MAC */ + + +#ifdef RTMP_MAC_PCI + pAd->PDMAWatchDogEn = 0; + pAd->PDMAWatchDogDbg = 0; + pAd->TxDMAResetCount = 0; + pAd->RxDMAResetCount = 0; + pAd->PDMAResetFailCount = 0; + pAd->TxDMACheckTimes = 0; + pAd->RxDMACheckTimes = 0; + pAd->RxResetDropCount = 0; + pAd->RxReset = 0; + pAd->DropInvalidPacket = 0; +#endif + +#ifdef LOAD_FW_ONE_TIME + pAd->FWLoad = 0; +#endif /* LOAD_FW_ONE_TIME */ +#ifdef CONFIG_AP_SUPPORT +#ifdef PREVENT_ARP_SPOOFING + pAd->ApCfg.ARPSpoofChk = FALSE; +#endif /* PREVENT_ARP_SPOOFING */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef MT_MAC + pAd->rx_pspoll_filter = 0; +#endif /* MT_MAC */ + + pAd->bPS_Retrieve =1; + + pAd->CommonCfg.bTXRX_RXV_ON = 1/*0*/;/*default on*/ + +#ifdef DYNAMIC_WMM + pAd->CommonCfg.DynamicWmm = 0; +#endif +#ifdef INTERFERENCE_RA_SUPPORT + pAd->CommonCfg.Interfra = 0; +#endif + pAd->CommonCfg.ManualTxop = 0; + + pAd->CommonCfg.ManualTxopThreshold = 10; // Mbps + + pAd->CommonCfg.ManualTxopUpBound = 15; // Ratio align with 7628 + + pAd->CommonCfg.ManualTxopLowBound = 5; // Ratio +#ifdef CONFIG_SNIFFER_SUPPORT + pAd->monitor_ctrl.current_monitor_mode = 0; +#endif /* CONFIG_SNIFFER_SUPPORT */ + +#ifdef SMART_CARRIER_SENSE_SUPPORT + pAd->SCSCtrl.SCSEnable = SCS_ENABLE; + pAd->SCSCtrl.SCSMinRssi=0; + pAd->SCSCtrl.SCSStatus=SCS_STATUS_DEFAULT; + pAd->SCSCtrl.SCSTrafficThreshold = 62500; /* 500Kbps */ + pAd->SCSCtrl.CurrSensitivity=-102; + pAd->SCSCtrl.AdjustSensitivity=-102; + pAd->SCSCtrl.FixedRssiBond=-72; + pAd->SCSCtrl.FalseCcaUpBond=600; + pAd->SCSCtrl.FalseCcaLowBond=60; + pAd->SCSCtrl.SCSMinRssiTolerance =10; + pAd->SCSCtrl.ForceMode=0; +#endif + +#ifdef ANTI_INTERFERENCE_SUPPORT + pAd->bDynamicRaInterval = FALSE; +#endif + + pAd->ed_chk = FALSE; //let country region to turn on + pAd->ed_th = 52; + pAd->ed_on = FALSE; + pAd->ed_debug = FALSE; + pAd->ed_th = 0xff; + pAd->ed_chk_period = 100; + pAd->ed_threshold = 90; + pAd->ed_false_cca_threshold = 150; + pAd->ed_block_tx_threshold = 10; + pAd->ed_big_rssi_count = 0; + + pAd->Cts2SelfTh = 1500; + pAd->Cts2SelfMonitorCnt = 0; + pAd->RtsMonitorCnt = 0; +#ifdef DATA_QUEUE_RESERVE + pAd->bQueueRsv = TRUE; +#endif /* DATA_QUEUE_RESERVE */ +#if defined(MAX_CONTINUOUS_TX_CNT) || defined(NEW_IXIA_METHOD) + pAd->DeltaRssiTh = 10;/* initial as 10dBm*/ + pAd->ContinousTxCnt = 1; + pAd->MonitorFlag = TRUE;/*Default monitor*/ + pAd->RateTh = 104; + pAd->chkTmr = 2; + pAd->pktthld = 0;/*50.*/ + pAd->protectpara = 0; +#endif +#ifdef STA_FORCE_ROAM_SUPPORT + load_froam_defaults(pAd); +#endif +#if defined(MBO_SUPPORT) || defined(MAP_SUPPORT) + pAd->reg_domain = REG_GLOBAL; +#endif/* MBO_SUPPORT */ +#ifdef WAPP_SUPPORT + pAd->bss_load_info.high_thrd = MAX_BSSLOAD_THRD; + pAd->bss_load_info.low_thrd = 0; +#endif /* WAPP_SUPPORT */ +#ifdef MT_PS + NdisAllocateSpinLock(pAd, &pAd->PSRetrieveLock); +#endif + DBGPRINT(RT_DEBUG_TRACE, ("<-- UserCfgInit\n")); +} + + +/* IRQL = PASSIVE_LEVEL*/ +UCHAR BtoH(RTMP_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(RTMP_STRING *src, PUCHAR dest, int destlen) +{ + RTMP_STRING *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++; + } +} + + +/* +======================================================================== +Routine Description: + Add a timer to the timer list. + +Arguments: + pAd - WLAN control block pointer + pRsc - the OS resource + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RTMP_TimerListAdd(RTMP_ADAPTER *pAd, VOID *pRsc) +{ + LIST_HEADER *pRscList = &pAd->RscTimerCreateList; + LIST_RESOURCE_OBJ_ENTRY *pObj; + + + /* try to find old entry */ + pObj = (LIST_RESOURCE_OBJ_ENTRY *)(pRscList->pHead); + while(1) + { + if (pObj == NULL) + break; + if ((ULONG)(pObj->pRscObj) == (ULONG)pRsc) + return; + 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, (RT_LIST_ENTRY *)pObj); + DBGPRINT(RT_DEBUG_INFO, ("%s: add timer obj %lx!\n", __FUNCTION__, (ULONG)pRsc)); + } +} + + +VOID RTMP_TimerListRelease(RTMP_ADAPTER *pAd, VOID *pRsc) +{ + LIST_HEADER *pRscList = &pAd->RscTimerCreateList; + LIST_RESOURCE_OBJ_ENTRY *pObj; + RT_LIST_ENTRY *pListEntry; + + pListEntry = pRscList->pHead; + pObj = (LIST_RESOURCE_OBJ_ENTRY *)pListEntry; + + while (pObj) + { + if ((ULONG)(pObj->pRscObj) == (ULONG)pRsc) + { + pListEntry = (RT_LIST_ENTRY *)pObj; + break; + } + + pListEntry = pListEntry->pNext; + pObj = (LIST_RESOURCE_OBJ_ENTRY *)pListEntry; + } + + if (pListEntry) + { + delEntryList(pRscList, pListEntry); + + /* free a timer record entry */ + DBGPRINT(RT_DEBUG_INFO, ("%s: release timer obj %lx!\n", __FUNCTION__, (ULONG)pRsc)); + os_free_mem(NULL, pObj); + } +} + +/* +======================================================================== +Routine Description: + Cancel all timers in the timer list. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RTMP_AllTimerListRelease(RTMP_ADAPTER *pAd) +{ + LIST_HEADER *pRscList = &pAd->RscTimerCreateList; + LIST_RESOURCE_OBJ_ENTRY *pObj, *pObjOld; + BOOLEAN Cancel; + + /* try to find old entry */ + pObj = (LIST_RESOURCE_OBJ_ENTRY *)(pRscList->pHead); + while(1) + { + if (pObj == NULL) + break; + DBGPRINT(RT_DEBUG_INFO, ("%s: Cancel timer obj %lx!\n", __FUNCTION__, (ULONG)(pObj->pRscObj))); + pObjOld = pObj; + pObj = pObj->pNext; + RTMPReleaseTimer(pObjOld->pRscObj, &Cancel); + //os_free_mem(NULL, pObjOld); + } + + /* reset TimerList */ + initList(&pAd->RscTimerCreateList); +} + + +/* + ======================================================================== + + Routine Description: + Init timer objects + + Arguments: + pAd Pointer to our adapter + pTimer Timer structure + pTimerFunc Function to execute when timer expired + Repeat Ture for period timer + + Return Value: + None + + Note: + + ======================================================================== +*/ +VOID RTMPInitTimer( + IN RTMP_ADAPTER *pAd, + IN RALINK_TIMER_STRUCT *pTimer, + IN VOID *pTimerFunc, + IN VOID *pData, + IN BOOLEAN Repeat) +{ + RTMP_SEM_LOCK(&TimerSemLock); + + RTMP_TimerListAdd(pAd, pTimer); + + + /* Set Valid to TRUE for later used.*/ + /* It will crash if we cancel a timer or set a timer */ + /* that we haven't initialize before.*/ + /* */ + pTimer->Valid = TRUE; + + pTimer->PeriodicType = Repeat; + pTimer->State = FALSE; + pTimer->cookie = (ULONG) pData; + pTimer->pAd = pAd; + + RTMP_OS_Init_Timer(pAd, &pTimer->TimerObj, pTimerFunc, (PVOID) pTimer, &pAd->RscTimerMemList); + DBGPRINT(RT_DEBUG_INFO, ("%s: %lx\n",__FUNCTION__, (ULONG)pTimer)); + + RTMP_SEM_UNLOCK(&TimerSemLock); +} + + +/* + ======================================================================== + + Routine Description: + Init timer objects + + Arguments: + pTimer Timer structure + Value Timer value in milliseconds + + Return Value: + None + + Note: + To use this routine, must call RTMPInitTimer before. + + ======================================================================== +*/ +VOID RTMPSetTimer(RALINK_TIMER_STRUCT *pTimer, ULONG Value) +{ + RTMP_SEM_LOCK(&TimerSemLock); + + if (pTimer->Valid) + { + RTMP_ADAPTER *pAd; + + pAd = (RTMP_ADAPTER *)pTimer->pAd; + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + { + DBGPRINT_ERR(("RTMPSetTimer failed, Halt in Progress!\n")); + RTMP_SEM_UNLOCK(&TimerSemLock); + return; + } + + pTimer->TimerValue = Value; + pTimer->State = FALSE; + if (pTimer->PeriodicType == TRUE) + { + pTimer->Repeat = TRUE; + RTMP_SetPeriodicTimer(&pTimer->TimerObj, Value); + } + else + { + pTimer->Repeat = FALSE; + RTMP_OS_Add_Timer(&pTimer->TimerObj, Value); + } + + DBGPRINT(RT_DEBUG_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(RALINK_TIMER_STRUCT *pTimer, ULONG Value) +{ + BOOLEAN Cancel; + + + RTMP_SEM_LOCK(&TimerSemLock); + + if (pTimer->Valid) + { + pTimer->TimerValue = Value; + pTimer->State = FALSE; + if (pTimer->PeriodicType == TRUE) + { + RTMP_SEM_UNLOCK(&TimerSemLock); + RTMPCancelTimer(pTimer, &Cancel); + RTMPSetTimer(pTimer, Value); + } + else + { + RTMP_OS_Mod_Timer(&pTimer->TimerObj, Value); + RTMP_SEM_UNLOCK(&TimerSemLock); + } + DBGPRINT(RT_DEBUG_INFO, ("%s: %lx\n",__FUNCTION__, (ULONG)pTimer)); + } + else + { + DBGPRINT_ERR(("RTMPModTimer failed, Timer hasn't been initialize!\n")); + RTMP_SEM_UNLOCK(&TimerSemLock); + } +} + + +/* + ======================================================================== + + Routine Description: + Cancel timer objects + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + Note: + 1.) To use this routine, must call RTMPInitTimer before. + 2.) Reset NIC to initial state AS IS system boot up time. + + ======================================================================== +*/ +VOID RTMPCancelTimer(RALINK_TIMER_STRUCT *pTimer, BOOLEAN *pCancelled) +{ + // TODO: shiang-usw, check the purpose of this SemLock! + RTMP_SEM_LOCK(&TimerSemLock); + + if (pTimer->Valid) + { + if (pTimer->State == FALSE) + pTimer->Repeat = FALSE; + + RTMP_SEM_UNLOCK(&TimerSemLock); + RTMP_OS_Del_Timer(&pTimer->TimerObj, pCancelled); + RTMP_SEM_LOCK(&TimerSemLock); + + if (*pCancelled == TRUE) + pTimer->State = TRUE; + +#ifdef RTMP_TIMER_TASK_SUPPORT + /* We need to go-through the TimerQ to findout this timer handler and remove it if */ + /* it's still waiting for execution.*/ + RtmpTimerQRemove(pTimer->pAd, pTimer); +#endif /* RTMP_TIMER_TASK_SUPPORT */ + + DBGPRINT(RT_DEBUG_INFO,("%s: %lx\n",__FUNCTION__, (ULONG)pTimer)); + } + else + { + DBGPRINT(RT_DEBUG_INFO, ("RTMPCancelTimer failed, Timer hasn't been initialize!\n")); + } + + RTMP_SEM_UNLOCK(&TimerSemLock); +} + + +VOID RTMPReleaseTimer(RALINK_TIMER_STRUCT *pTimer, BOOLEAN *pCancelled) +{ + RTMP_SEM_LOCK(&TimerSemLock); + + if (pTimer->Valid) + { + if (pTimer->State == FALSE) + pTimer->Repeat = FALSE; + + RTMP_SEM_UNLOCK(&TimerSemLock); + RTMP_OS_Del_Timer(&pTimer->TimerObj, pCancelled); + RTMP_SEM_LOCK(&TimerSemLock); + + if (*pCancelled == TRUE) + pTimer->State = TRUE; + +#ifdef RTMP_TIMER_TASK_SUPPORT + /* We need to go-through the TimerQ to findout this timer handler and remove it if */ + /* it's still waiting for execution.*/ + RtmpTimerQRemove(pTimer->pAd, pTimer); +#endif /* RTMP_TIMER_TASK_SUPPORT */ + + /* release timer */ + RTMP_OS_Release_Timer(&pTimer->TimerObj); + + pTimer->Valid = FALSE; + // TODO: shiang-usw, merge this from NXTC, make sure if that's necessary here!! + RTMP_TimerListRelease(pTimer->pAd, pTimer); + + 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(RTMP_ADAPTER *pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPEnableRxTx\n")); + + RT28XXDMAEnable(pAd); + + AsicSetRxFilter(pAd); + + { + if (pAd->CommonCfg.bTXRX_RXV_ON) + AsicSetMacTxRx(pAd, ASIC_MAC_TXRX_RXV, TRUE); + else + AsicSetMacTxRx(pAd, ASIC_MAC_TXRX, TRUE); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPEnableRxTx\n")); +} + +VOID RTMPDisableRxTx(RTMP_ADAPTER *pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("==> RTMPDisableRxTx\n")); + + RT28XXDMADisable(pAd); + + AsicClearRxFilter(pAd); + + { + if (pAd->CommonCfg.bTXRX_RXV_ON) + AsicSetMacTxRx(pAd, ASIC_MAC_TXRX_RXV, FALSE); + else + AsicSetMacTxRx(pAd, ASIC_MAC_TXRX, FALSE); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<== RTMPDisableRxTx\n")); +} + +void CfgInitHook(RTMP_ADAPTER *pAd) +{ + /*pAd->bBroadComHT = TRUE;*/ +} + + +static INT RtmpChipOpsRegister(RTMP_ADAPTER *pAd, INT infType) +{ + RTMP_CHIP_OP *pChipOps = &pAd->chipOps; + int ret = 0; + + NdisZeroMemory(pChipOps, sizeof(RTMP_CHIP_OP)); + NdisZeroMemory(&pAd->chipCap, sizeof(RTMP_CHIP_CAP)); + + ret = RtmpChipOpsHook(pAd); + + if (ret) { + DBGPRINT(RT_DEBUG_ERROR, ("chipOps hook error\n")); + return ret; + } + + /* MCU related */ + ChipOpsMCUHook(pAd, pAd->chipCap.MCUType); + + get_dev_config_idx(pAd); + + return ret; +} + + + + +PNET_DEV get_netdev_from_bssid(RTMP_ADAPTER *pAd, UCHAR wdev_idx) +{ + PNET_DEV dev_p = NULL; + + if (wdev_idx < WDEV_NUM_MAX) + dev_p = pAd->wdev_list[wdev_idx]->if_dev; + + ASSERT((dev_p != NULL)); + return dev_p; +} + + +INT RtmpRaDevCtrlInit(VOID *pAdSrc, RTMP_INF_TYPE infType) +{ + RTMP_ADAPTER *pAd = (PRTMP_ADAPTER)pAdSrc; + + /* Assign the interface type. We need use it when do register/EEPROM access.*/ + pAd->infType = infType; + + +#ifdef CONFIG_AP_SUPPORT + pAd->OpMode = OPMODE_AP; + DBGPRINT(RT_DEBUG_OFF, ("MT7603 AP Driver version %s\n", AP_DRIVER_VERSION)); +#endif /* CONFIG_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("pAd->infType=%d\n", pAd->infType)); + + + RTMP_SEM_EVENT_INIT(&(pAd->AutoRateLock), &pAd->RscSemMemList); + RTMP_SEM_EVENT_INIT(&(pAd->e2p_read_lock), &pAd->RscSemMemList); + +#ifdef MULTIPLE_CARD_SUPPORT +#ifdef RTMP_FLASH_SUPPORT +/* if ((IS_PCIE_INF(pAd))) */ + { + /* specific for RT6855/RT6856 */ + pAd->E2P_OFFSET_IN_FLASH[0] = 0x40000; + pAd->E2P_OFFSET_IN_FLASH[1] = 0x48000; + } +#endif /* RTMP_FLASH_SUPPORT */ +#endif /* MULTIPLE_CARD_SUPPORT */ + + if (RtmpChipOpsRegister(pAd, infType)) + return FALSE; + + +#ifdef MULTIPLE_CARD_SUPPORT +{ + extern BOOLEAN RTMP_CardInfoRead(PRTMP_ADAPTER pAd); + + /* find its profile path*/ + pAd->MC_RowID = -1; /* use default profile path*/ + RTMP_CardInfoRead(pAd); + + if (pAd->MC_RowID == -1) +#ifdef CONFIG_AP_SUPPORT + strcpy(pAd->MC_FileName, AP_PROFILE_PATH); +#endif /* CONFIG_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("MC> ROW = %d, PATH = %s\n", pAd->MC_RowID, pAd->MC_FileName)); +} +#endif /* MULTIPLE_CARD_SUPPORT */ + + +#ifdef MCS_LUT_SUPPORT + if (pAd->chipCap.asic_caps & fASIC_CAP_MCS_LUT) { + if (MAX_LEN_OF_MAC_TABLE < 128) { + RTMP_SET_MORE_FLAG(pAd, fASIC_CAP_MCS_LUT); + } else { + DBGPRINT(RT_DEBUG_WARN, ("%s(): MCS_LUT not used becasue MacTb size(%d) > 128!\n", + __FUNCTION__, MAX_LEN_OF_MAC_TABLE)); + } + } +#endif /* MCS_LUT_SUPPORT */ + +#ifdef SINGLE_SKU_V2 + pAd->SKUEn = 1; +#endif /* SINGLE_SKU_V2 */ + +#ifdef MT_MAC + if (pAd->chipCap.hif_type != HIF_MT) +#endif + { + printk("JERRY:prepare load_patch..\n"); + if (load_patch(pAd) != NDIS_STATUS_SUCCESS) { + DBGPRINT_ERR(("load patch failed!\n")); + return FALSE; + } + } + +#ifdef E2P_WITHOUT_FW_SUPPORT + /* hook e2p operation */ + RtmpChipOpsEepromHook(pAd, pAd->infType, E2P_NONE); +#endif /* E2P_WITHOUT_FW_SUPPORT */ + return 0; +} + + +BOOLEAN RtmpRaDevCtrlExit(IN VOID *pAdSrc) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pAdSrc; + INT index; + +#ifdef MULTIPLE_CARD_SUPPORT +extern UINT8 MC_CardUsed[MAX_NUM_OF_MULTIPLE_CARD]; + + if ((pAd->MC_RowID >= 0) && (pAd->MC_RowID <= MAX_NUM_OF_MULTIPLE_CARD)) + MC_CardUsed[pAd->MC_RowID] = 0; /* not clear MAC address*/ +#endif /* MULTIPLE_CARD_SUPPORT */ + + +#ifdef RLT_MAC + if ((IS_MT76x0(pAd) || IS_MT76x2(pAd))&& (pAd->WlanFunCtrl.field.WLAN_EN == 1)) + { + rlt_wlan_chip_onoff(pAd, FALSE, FALSE); + } +#endif /* RLT_MAC */ + + RTMP_SEM_EVENT_DESTORY(&(pAd->AutoRateLock)); + RTMP_SEM_EVENT_DESTORY(&(pAd->e2p_read_lock)); + + + /* + Free ProbeRespIE Table + */ + for (index = 0; index < MAX_LEN_OF_BSS_TABLE; index++) + { + if (pAd->ProbeRespIE[index].pIe) + os_free_mem(pAd, pAd->ProbeRespIE[index].pIe); + } + +#ifdef RESOURCE_PRE_ALLOC + RTMPFreeTxRxRingMemory(pAd); +#endif /* RESOURCE_PRE_ALLOC */ + + RTMPFreeAdapter(pAd); + + return TRUE; +} + + +#ifdef CONFIG_AP_SUPPORT +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 +VOID RTMP_11N_D3_TimerInit(RTMP_ADAPTER *pAd) +{ + RTMPInitTimer(pAd, &pAd->CommonCfg.Bss2040CoexistTimer, GET_TIMER_FUNCTION(Bss2040CoexistTimeOut), pAd, FALSE); +} +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef VENDOR_FEATURE3_SUPPORT +VOID RTMP_IO_WRITE32( + PRTMP_ADAPTER pAd, + UINT32 Offset, + UINT32 Value) +{ + _RTMP_IO_WRITE32(pAd, Offset, Value); +} +#endif /* VENDOR_FEATURE3_SUPPORT */ + + +#ifdef RTMP_MAC_PCI +VOID CMDHandler(RTMP_ADAPTER *pAd) +{ + PCmdQElmt cmdqelmt; + UCHAR *pData; +#ifdef WH_EZ_SETUP + //PAPCLI_STRUCT pApCliTab; + struct wifi_dev *wdev = NULL; +#endif + //NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS; + + while (pAd && pAd->CmdQ.size > 0) + { + //NdisStatus = NDIS_STATUS_SUCCESS; + + NdisAcquireSpinLock(&pAd->CmdQLock); + RTThreadDequeueCmd(&pAd->CmdQ, &cmdqelmt); + NdisReleaseSpinLock(&pAd->CmdQLock); + + if (cmdqelmt == NULL) + break; +#ifdef WH_EZ_SETUP + // pApCliTab = (PAPCLI_STRUCT)cmdqelmt->buffer; +#endif + 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 WMODE_CAP_N(phymode) and BW=40 check extension channel, after select channel */ + N_ChannelCheck(pAd); +#endif /* DOT11_N_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("cmd> Switch to %d! \n", pAd->CommonCfg.Channel)); + APStop(pAd); + APStartUp(pAd); + +#ifdef AP_QLOAD_SUPPORT + QBSS_LoadAlarmResume(pAd); +#endif /* AP_QLOAD_SUPPORT */ + break; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef SNIFFER_MIB_CMD + case CMDTHREAD_CHAN_RESTORE: + sniffer_channel_restore(pAd); + break; +#endif /* SNIFFER_MIB_CMD */ + + case CMDTHREAD_REG_HINT: +#ifdef LINUX +#endif /* LINUX */ + break; + + case CMDTHREAD_REG_HINT_11D: +#ifdef LINUX +#endif /* LINUX */ + break; + + case CMDTHREAD_SCAN_END: + break; + + case CMDTHREAD_CONNECT_RESULT_INFORM: + break; +#ifdef MT_MAC +#ifdef MT_PS + case CMDTHREAD_PS_CLEAR: + { + UINT32 wlanidx = 0; + + NdisMoveMemory(&wlanidx , pData, sizeof(UINT32)); + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("wcid=0x%x, Send Ps Clear CMD to MCU\n", wlanidx)); + CmdPsClearReq(pAd, wlanidx, TRUE); + } + break; + + case CMDTHREAD_PS_RETRIEVE_START: + { + MAC_TABLE_ENTRY *pMacEntry = (MAC_TABLE_ENTRY *)(pData); + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("wcid=%d CmdPsRetrieveStartReq CMD to MCU\n", pMacEntry->wcid)); + CmdPsRetrieveStartReq(pAd, pMacEntry->wcid); + } + break; +#endif /* MT_PS */ + + case CMDTHREAD_APCLI_PBC_TIMEOUT: + { + UCHAR channel = 0; + RTMP_STRING ChStr[5] = {0}; + NdisMoveMemory(&channel , pData, sizeof(UCHAR)); + DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_PS, ("channel=%d CMDTHREAD_APCLI_PBC_TIMEOUT\n", channel)); + snprintf(ChStr, sizeof(ChStr), "%d", channel); +#ifdef WH_EZ_SETUP + wdev = &pAd->ApCfg.ApCliTab[BSS0].wdev; + if(IS_EZ_SETUP_ENABLED(wdev)) + { + wdev->ez_driver_params.do_not_restart_interfaces = TRUE; + } +#endif +#ifdef WH_EZ_SETUP + if(IS_EZ_SETUP_ENABLED(wdev)) + rtmp_set_channel(pAd, wdev, channel); + else +#endif + Set_Channel_Proc(pAd, ChStr); +#ifdef WH_EZ_SETUP + if(IS_EZ_SETUP_ENABLED(wdev)) + { + wdev->ez_driver_params.do_not_restart_interfaces = FALSE; + } +#endif + } + break; +#endif /* MT_MAC */ + case HWCMD_ID_BMC_CNT_UPDATE: + { + CHAR idx = 0; + //printk("cmd HWCMD_ID_BMC_CNT_UPDATE \n"); + NdisMoveMemory(&idx , pData, sizeof(CHAR)); + + /* BMC start */ + AsicSetBmcQCR(pAd, BMC_CNT_UPDATE, CR_WRITE, idx, NULL); + } + break; + case CMDTHREAD_PERODIC_CR_ACCESS_ASIC_UPDATE_PROTECT: + { + MtCmdAsicUpdateProtect(pAd, cmdqelmt); + } + break; + + case CMDTHREAD_PERODIC_CR_ACCESS_NIC_UPDATE_RAW_COUNTERS: + { + MtCmdNICUpdateRawCounters(pAd, cmdqelmt); + } + break; + + case CMDTHREAD_PERODIC_CR_ACCESS_WTBL_RATE_TABLE_UPDATE: + { + MtCmdWtbl2RateTableUpdate(pAd, cmdqelmt); + } + break; + + + case CMDTHREAD_MLME_PERIOIDC_EXEC: + { + MlmePeriodicExec(pAd, cmdqelmt); + } + break; + + case CMDTHREAD_PWR_MGT_BIT: + { + MtCmdWtblTxpsUpdate(pAd, cmdqelmt); + } + break; + + default: + DBGPRINT(RT_DEBUG_ERROR, ("--> Control Thread !! ERROR !! Unknown(cmdqelmt->command=0x%x) !! \n", cmdqelmt->command)); + break; + } + } + + if (cmdqelmt->CmdFromNdis == TRUE) + { + if (cmdqelmt->buffer != NULL) + os_free_mem(pAd, cmdqelmt->buffer); + os_free_mem(pAd, cmdqelmt); + } + else + { + if ((cmdqelmt->buffer != NULL) && (cmdqelmt->bufferlength != 0)) + os_free_mem(pAd, cmdqelmt->buffer); + os_free_mem(pAd, cmdqelmt); + } + } +} +#endif /* RTMP_MAC_PCI */ + + +VOID AntCfgInit(RTMP_ADAPTER *pAd) +{ + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return; + } + + + + +#ifdef TXRX_SW_ANTDIV_SUPPORT + /* EEPROM 0x34[15:12] = 0xF is invalid, 0x2~0x3 is TX/RX SW AntDiv */ + DBGPRINT(RT_DEBUG_OFF, ("%s: bTxRxSwAntDiv %d\n", __FUNCTION__, pAd->chipCap.bTxRxSwAntDiv)); + if (pAd->chipCap.bTxRxSwAntDiv) + { + DBGPRINT(RT_DEBUG_OFF, ("Antenna word %X/%d, AntDiv %d\n", + pAd->Antenna.word, pAd->Antenna.field.BoardType, pAd->NicConfig2.field.AntDiversity)); + } +#endif /* TXRX_SW_ANTDIV_SUPPORT */ + + { + if (pAd->NicConfig2.field.AntOpt== 1) /* ant selected by efuse */ + { + if (pAd->NicConfig2.field.AntDiversity == 0) /* main */ + { + pAd->RxAnt.Pair1PrimaryRxAnt = 0; + pAd->RxAnt.Pair1SecondaryRxAnt = 1; + } + else/* aux */ + { + pAd->RxAnt.Pair1PrimaryRxAnt = 1; + pAd->RxAnt.Pair1SecondaryRxAnt = 0; + } + } + else if (pAd->NicConfig2.field.AntDiversity == 0) /* Ant div off: default ant is main */ + { + pAd->RxAnt.Pair1PrimaryRxAnt = 0; + pAd->RxAnt.Pair1SecondaryRxAnt = 1; + } + else if (pAd->NicConfig2.field.AntDiversity == 1)/* Ant div on */ + {/* eeprom on, but sw ant div support is not enabled: default ant is main */ + pAd->RxAnt.Pair1PrimaryRxAnt = 0; + pAd->RxAnt.Pair1SecondaryRxAnt = 1; + } + } + + DBGPRINT(RT_DEBUG_OFF, ("%s: primary/secondary ant %d/%d\n", + __FUNCTION__, + pAd->RxAnt.Pair1PrimaryRxAnt, + pAd->RxAnt.Pair1SecondaryRxAnt)); +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rtmp_init_inf.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rtmp_init_inf.c new file mode 100644 index 000000000..232b6c3d6 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rtmp_init_inf.c @@ -0,0 +1,1095 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + rtmp_init_inf.c + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#include "rt_config.h" +#ifdef DOT11R_FT_SUPPORT +#include "ft.h" +#endif /* DOT11R_FT_SUPPORT */ + + + + +#ifdef LINUX +#ifdef OS_ABL_FUNC_SUPPORT +/* Utilities provided from NET module */ +RTMP_NET_ABL_OPS RtmpDrvNetOps, *pRtmpDrvNetOps = &RtmpDrvNetOps; +RTMP_PCI_CONFIG RtmpPciConfig, *pRtmpPciConfig = &RtmpPciConfig; +RTMP_USB_CONFIG RtmpUsbConfig, *pRtmpUsbConfig = &RtmpUsbConfig; + +VOID RtmpDrvOpsInit( + OUT VOID *pDrvOpsOrg, + INOUT VOID *pDrvNetOpsOrg, + IN RTMP_PCI_CONFIG *pPciConfig, + IN RTMP_USB_CONFIG *pUsbConfig) +{ + RTMP_DRV_ABL_OPS *pDrvOps = (RTMP_DRV_ABL_OPS *)pDrvOpsOrg; + + + /* init PCI/USB configuration in different OS */ + if (pPciConfig != NULL) + RtmpPciConfig = *pPciConfig; + + if (pUsbConfig != NULL) + RtmpUsbConfig = *pUsbConfig; + + /* init operators provided from us (DRIVER module) */ + pDrvOps->RTMPAllocAdapterBlock = RTMPAllocAdapterBlock; + pDrvOps->RTMPFreeAdapter = RTMPFreeAdapter; + + pDrvOps->RtmpRaDevCtrlExit = RtmpRaDevCtrlExit; + pDrvOps->RtmpRaDevCtrlInit = RtmpRaDevCtrlInit; +#ifdef RTMP_MAC_PCI + pDrvOps->RTMPHandleInterrupt = RTMPHandleInterrupt; +#endif /* RTMP_MAC_PCI */ + pDrvOps->RTMPSendPackets = RTMPSendPackets; + + pDrvOps->RTMP_COM_IoctlHandle = RTMP_COM_IoctlHandle; +#ifdef CONFIG_AP_SUPPORT + pDrvOps->RTMP_AP_IoctlHandle = RTMP_AP_IoctlHandle; +#endif /* CONFIG_AP_SUPPORT */ + + 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 rtmp_sys_exit(RTMP_ADAPTER *pAd) +{ + + MeasureReqTabExit(pAd); + TpcReqTabExit(pAd); + +#ifdef DOT11_N_SUPPORT + if(pAd->mpdu_blk_pool.mem) { + os_free_mem(pAd, pAd->mpdu_blk_pool.mem); /* free BA pool*/ + pAd->mpdu_blk_pool.mem = NULL; + } +#endif /* DOT11_N_SUPPORT */ + + return TRUE; +} + + +INT rtmp_sys_init(RTMP_ADAPTER *pAd) +{ + NDIS_STATUS status; + +#ifdef DOT11_N_SUPPORT + /* Allocate BA Reordering memory*/ + if (ba_reordering_resource_init(pAd, MAX_REORDERING_MPDU_NUM) != TRUE) + goto err; +#endif /* DOT11_N_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 err; + } + status = TpcReqTabInit(pAd); + if (status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("TpcReqTabInit failed, Status[=0x%08x]\n", status)); + goto err; + } + + +#ifdef WH_EZ_SETUP + pAd->CurWdevIdx = 0; +#endif + + return TRUE; + +err: + return FALSE; + +} + + + +INT rtmp_cfg_exit(RTMP_ADAPTER *pAd) +{ + UserCfgExit(pAd); + + return TRUE; +} + + +INT rtmp_cfg_init(RTMP_ADAPTER *pAd, RTMP_STRING *pHostName) +{ + NDIS_STATUS status; + + UserCfgInit(pAd); +#ifdef MBO_SUPPORT + MboInit(pAd); +#endif/* MBO_SUPPORT */ + + CfgInitHook(pAd); + + /* + WiFi system operation mode setting base on following partitions: + 1. Parameters from config file + 2. Hardware cap from EEPROM + 3. Chip capabilities in code + */ + if (pAd->RfIcType == 0) { + /* RfIcType not assigned, should not happened! */ + pAd->RfIcType = RFIC_UNKNOWN; + DBGPRINT(RT_DEBUG_OFF, ("%s(): Invalid RfIcType, reset it first\n", + __FUNCTION__)); + } + + + RTMPPreReadParametersHook(pAd); + status = RTMPReadParametersHook(pAd); + if (status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("RTMPReadParametersHook failed, Status[=0x%08x]\n",status)); + return FALSE; + } + +#ifdef DOT11_N_SUPPORT + /*Init Ba Capability parameters.*/ + pAd->CommonCfg.DesiredHtPhy.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; + pAd->CommonCfg.DesiredHtPhy.AmsduEnable = (USHORT)pAd->CommonCfg.BACapability.field.AmsduEnable; + pAd->CommonCfg.DesiredHtPhy.AmsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; + pAd->CommonCfg.DesiredHtPhy.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; + /* Updata to HT IE*/ + pAd->CommonCfg.HtCapability.HtCapInfo.MimoPs = (USHORT)pAd->CommonCfg.BACapability.field.MMPSmode; + pAd->CommonCfg.HtCapability.HtCapInfo.AMsduSize = (USHORT)pAd->CommonCfg.BACapability.field.AmsduSize; + pAd->CommonCfg.HtCapability.HtCapParm.MpduDensity = (UCHAR)pAd->CommonCfg.BACapability.field.MpduDensity; +#endif /* DOT11_N_SUPPORT */ + + return TRUE; +} + + +INT rtmp_mgmt_init(RTMP_ADAPTER *pAd) +{ + + return TRUE; +} + + +int rt28xx_init(VOID *pAdSrc, RTMP_STRING *pDefaultMac, RTMP_STRING *pHostName) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pAdSrc; + NDIS_STATUS Status; + + if (!pAd) + return FALSE; + +#if defined(RLT_MAC) || defined(RTMP_MAC) + if (rtmp_asic_top_init(pAd) != TRUE) + goto err0; +#endif /* defined(RLT_MAC) || defined(RTMP_MAC) */ + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + if (mt_asic_top_init(pAd) != TRUE) + goto err0; + } +#endif /* MT_MAC */ + + DBGPRINT(RT_DEBUG_TRACE, ("MAC[Ver:Rev=0x%08x : 0x%08x]\n", + pAd->MACVersion, pAd->ChipID)); + + /* TxS Setting */ + InitTxSTypeTable(pAd); + + if (hif_sys_init(pAd, TRUE) != TRUE) + goto err1; + + Status = RtmpNetTaskInit(pAd); + if (Status != NDIS_STATUS_SUCCESS) + goto err2; + +#ifdef RTMP_MAC_PCI + // TODO: shiang-usw, need to check this for RTMP_MAC + /* Disable interrupts here which is as soon as possible*/ + /* This statement should never be true. We might consider to remove it later*/ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) + { + RTMP_ASIC_INTERRUPT_DISABLE(pAd); + } +#endif /* RTMP_MAC_PCI */ + + /* reset Adapter flags */ + RTMP_CLEAR_FLAGS(pAd); + + + + Status = RtmpMgmtTaskInit(pAd); + if (Status != NDIS_STATUS_SUCCESS) + goto err3; + + + /* initialize MLME*/ + Status = MlmeInit(pAd); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("MlmeInit failed, Status[=0x%08x]\n", Status)); + goto err4; + } + + /* Initialize pAd->StaCfg, pAd->ApCfg, pAd->CommonCfg to manufacture default*/ + if (rtmp_cfg_init(pAd, pHostName) != TRUE) + goto err5; + + pAd->LowerMcsValue = 0; //Set to default + pAd->HigherMcsValue = 0; //Set to default + + if (MCUSysInit(pAd) != NDIS_STATUS_SUCCESS) + goto err6; + + /* hook e2p operation */ + RtmpChipOpsEepromHook(pAd, pAd->infType,E2P_NONE); + +#if defined(MT7603_FPGA) || defined(MT7628_FPGA) + if (pAd->chipCap.hif_type == HIF_MT) { + UINT32 ver, date_code, rev; + UINT32 mac_val; + + RTMP_IO_READ32(pAd, 0x2700, &ver); + RTMP_IO_READ32(pAd, 0x2704, &rev); + RTMP_IO_READ32(pAd, 0x2708, &date_code); + RTMP_IO_READ32(pAd, 0x201f8, &mac_val); + DBGPRINT(RT_DEBUG_OFF, ("##########################################\n")); + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): MT7603 FPGA Version:\n", __FUNCTION__, __LINE__)); + + DBGPRINT(RT_DEBUG_OFF, ("\tFGPA1: Code[0x700]:0x%x, [0x704]:0x%x, [0x708]:0x%x\n", + ver, rev, date_code)); + DBGPRINT(RT_DEBUG_OFF, ("\tFPGA2: Version[0x201f8]:0x%x\n", mac_val)); + DBGPRINT(RT_DEBUG_OFF, ("##########################################\n")); + } +#endif /* MT7603_FPGA */ + + 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 err6; + } + + if (rtmp_sys_init(pAd) != TRUE) + goto err7; + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); + + + DBGPRINT(RT_DEBUG_OFF, ("1. Phy Mode = %d\n", pAd->CommonCfg.PhyMode)); + + /* We should read EEPROM for all cases */ + // TODO: shiang-7603, revise this! + NICReadEEPROMParameters(pAd, (RTMP_STRING *)pDefaultMac); + + DBGPRINT(RT_DEBUG_OFF, ("2. Phy Mode = %d\n", pAd->CommonCfg.PhyMode)); + + RTMP_NET_DEV_NICKNAME_INIT(pAd); + +#ifdef SMART_CARRIER_SENSE_SUPPORT + /* Backup CR_AGC_0 & CR_AGC_3 value */ + RTMP_IO_READ32(pAd, CR_AGC_0, &pAd->SCSCtrl.CR_AGC_0_default); + RTMP_IO_READ32(pAd, CR_AGC_3, &pAd->SCSCtrl.CR_AGC_3_default); +#endif /* SMART_CARRIER_SENSE_SUPPORT */ + + /* After operation mode is finialized, init the AP or STA mode */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + APInitialize(pAd); + + /* Init BssTab & ChannelInfo tabbles for auto channel select.*/ + AutoChBssTableInit(pAd); + ChannelInfoInit(pAd); + } +#endif /* CONFIG_AP_SUPPORT */ + + + /* after reading Registry, we now know if in AP mode or STA mode */ + DBGPRINT(RT_DEBUG_OFF, ("3. Phy Mode = %d\n", pAd->CommonCfg.PhyMode)); + + /* + All settle down, now it's time to init asic related parameters + */ + /* Init the hardware, we need to init asic before read registry, otherwise mac register will be reset */ + Status = NICInitializeAdapter(pAd, TRUE); + if (Status != NDIS_STATUS_SUCCESS) + { + DBGPRINT_ERR(("NICInitializeAdapter failed, Status[=0x%08x]\n", Status)); + if (Status != NDIS_STATUS_SUCCESS) + goto err8; + } + +#ifdef CONFIG_FPGA_MODE +#ifdef CAPTURE_MODE + cap_mode_init(pAd); +#endif /* CAPTURE_MODE */ +#endif /* CONFIG_FPGA_MODE */ + + NICInitAsicFromEEPROM(pAd); + + + +#ifdef LED_CONTROL_SUPPORT + /* Send LED Setting to MCU */ + RTMPInitLEDMode(pAd); +#endif /* LED_CONTROL_SUPPORT */ + + /* + Do necessary calibration after ASIC initialized + this's chip variant and may different for different chips + */ + + + tx_pwr_comp_init(pAd); + + + /* Set PHY to appropriate mode and will update the ChannelListNum in this function */ + RTMPSetPhyMode(pAd, pAd->CommonCfg.PhyMode); + if (pAd->ChannelListNum == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("Wrong configuration. No valid channel found. Check \"ContryCode\" and \"ChannelGeography\" setting.\n")); + goto err8; + } + +#ifdef DOT11_N_SUPPORT + DBGPRINT(RT_DEBUG_OFF, ("MCS Set = %02x %02x %02x %02x %02x\n", + pAd->CommonCfg.HtCapability.MCSSet[0], + pAd->CommonCfg.HtCapability.MCSSet[1], + pAd->CommonCfg.HtCapability.MCSSet[2], + pAd->CommonCfg.HtCapability.MCSSet[3], + pAd->CommonCfg.HtCapability.MCSSet[4])); +#endif /* DOT11_N_SUPPORT */ + +#ifdef WIN_NDIS + /* Patch cardbus controller if EEPROM said so. */ + if (pAd->bTest1 == FALSE) + RTMPPatchCardBus(pAd); +#endif /* WIN_NDIS */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef AP_QLOAD_SUPPORT + QBSS_LoadInit(pAd); +#endif /* AP_QLOAD_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef IKANOS_VX_1X0 + VR_IKANOS_FP_Init(pAd->ApCfg.BssidNum, pAd->PermanentAddress); +#endif /* IKANOS_VX_1X0 */ + + +#ifdef CONFIG_ATE + if (ATEInit(pAd) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): ATE initialization failed !\n", __FUNCTION__)); + goto err9; + } + +#endif /* CONFIG_ATE */ + + +#ifdef RTMP_INTERNAL_TX_ALC +#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. + */ + + /* Microsoft HCT require driver send a disconnect event after driver initialization.*/ + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED); + OPSTATUS_CLEAR_FLAG(pAd, fOP_AP_STATUS_MEDIA_STATE_CONNECTED); + + DBGPRINT(RT_DEBUG_TRACE, ("NDIS_STATUS_MEDIA_DISCONNECT Event B!\n")); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (pAd->ApCfg.bAutoChannelAtBootup || (pAd->CommonCfg.Channel == 0)) + { + /* Enable Interrupt first due to we need to scan channel to receive beacons.*/ +#ifdef RTMP_MAC_PCI + RTMP_IRQ_ENABLE(pAd); +#endif /* RTMP_MAC_PCI */ + + /* Now Enable RxTx*/ + RTMPEnableRxTx(pAd); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP); + + /* Let BBP register at 20MHz to do scan */ + bbp_set_bw(pAd, BW_20); + + /* Now we can receive the beacon and do the listen beacon*/ + /* use default BW to select channel*/ + pAd->CommonCfg.Channel = AP_AUTO_CH_SEL(pAd, pAd->ApCfg.AutoChannelAlg); + pAd->ApCfg.bAutoChannelAtBootup = FALSE; + } + +#ifdef DOT11_N_SUPPORT + /* If WMODE_CAP_N(phymode) and BW=40 check extension channel, after select channel */ + N_ChannelCheck(pAd); + +#ifdef DOT11N_DRAFT3 + /* + We only do this Overlapping BSS Scan when system up, for the + other situation of channel changing, we depends on station's + report to adjust ourself. + */ + if (pAd->CommonCfg.bForty_Mhz_Intolerant == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Disable 20/40 BSSCoex Channel Scan(BssCoex=%d, 40MHzIntolerant=%d)\n", + pAd->CommonCfg.bBssCoexEnable, + pAd->CommonCfg.bForty_Mhz_Intolerant)); + } + else if(pAd->CommonCfg.bBssCoexEnable == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, ("Enable 20/40 BSSCoex Channel Scan(BssCoex=%d)\n", + pAd->CommonCfg.bBssCoexEnable)); + APOverlappingBSSScan(pAd); + } + + RTMP_11N_D3_TimerInit(pAd); +/* RTMPInitTimer(pAd, &pAd->CommonCfg.Bss2040CoexistTimer, GET_TIMER_FUNCTION(Bss2040CoexistTimeOut), pAd, FALSE);*/ +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + APStartUp(pAd); + + MlmeRadioOn(pAd); + + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef DYNAMIC_VGA_SUPPORT + if (pAd->CommonCfg.lna_vga_ctl.bDyncVgaEnable) + { + dynamic_vga_enable(pAd); + } +#endif /* DYNAMIC_VGA_SUPPORT */ + + +// TODO: shiang-7603, work-around for it now!! Need a better place for it! + IF_DEV_CONFIG_OPMODE_ON_STA(pAd) + { + if (IS_MT7603(pAd) || IS_MT7628(pAd) || IS_MT7636(pAd)) { + /* Now Enable RxTx*/ +#ifdef RTMP_MAC_PCI + RTMP_IRQ_ENABLE(pAd); + +#ifdef LOAD_FW_ONE_TIME + { + UINT32 value; + RTMP_IO_READ32(pAd, AGG_TEMP, &value); + value &= 0x0000ffff; + RTMP_IO_WRITE32(pAd, AGG_TEMP, value); + } +#endif /* LOAD_FW_ONE_TIME */ + +#endif /* RTMP_MAC_PCI */ + RTMPEnableRxTx(pAd); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP); + } + } + + + /* Set up the Mac address*/ +#ifdef CONFIG_AP_SUPPORT + RtmpOSNetDevAddrSet(pAd->OpMode, pAd->net_dev, &pAd->CurrentAddress[0], NULL); +#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 CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + ap_func_init(pAd); +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef STREAM_MODE_SUPPORT + RtmpStreamModeInit(pAd); +#endif /* STREAM_MODE_SUPPORT */ + + +#ifdef DOT11_N_SUPPORT +#endif /* DOT11_N_SUPPORT */ + + + +#ifdef LED_CONTROL_METHOD_1 + AndesLedEnhanceOP(pAd, 0, 200, 200, 31); +#endif + +#ifdef MT_WOW_SUPPORT + ASIC_WOW_INIT(pAd); +#endif + +#ifdef USB_IOT_WORKAROUND2 + pAd->bUSBIOTReady = TRUE; +#endif + +#ifdef MIXMODE_SUPPORT + MixModeInit(pAd); +#endif +#ifdef MAC_REPEATER_SUPPORT + if(pAd->ApCfg.bMACRepeaterEn) + AsicSetMacAddrExt(pAd, TRUE); +#endif /*MAC_REPEATER_SUPPORT*/ + + DBGPRINT_S(("<==== rt28xx_init, Status=%x\n", Status)); + + return TRUE; + +#ifdef CONFIG_ATE +err9: + ATEExit(pAd); +#endif + +err8: +#ifdef IGMP_SNOOP_SUPPORT + MultiCastFilterTableReset(&pAd->pMulticastFilterTable); +#endif /* IGMP_SNOOP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { + /* Free BssTab & ChannelInfo tabbles.*/ + AutoChBssTableDestroy(pAd); + ChannelInfoDestroy(pAd); + } +#endif /* CONFIG_AP_SUPPORT */ + +err7: + rtmp_sys_exit(pAd); + +err6: + MCUSysExit(pAd); + +err5: + rtmp_cfg_exit(pAd); + +err4: + MlmeHalt(pAd); + RTMP_AllTimerListRelease(pAd); + +err3: + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE); + + RtmpMgmtTaskExit(pAd); +#ifdef RTMP_TIMER_TASK_SUPPORT + NdisFreeSpinLock(&pAd->TimerQLock); +#endif + +err2: + RtmpNetTaskExit(pAd); + +err1: + hif_sys_exit(pAd); + +err0: + + DBGPRINT(RT_DEBUG_ERROR, ("!!! rt28xx init fail !!!\n")); + return FALSE; +} + + +VOID RTMPDrvOpen(VOID *pAdSrc) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pAdSrc; + + RTMP_CLEAR_PSFLAG(pAd, fRTMP_PS_MCU_SLEEP); + +#ifdef RTMP_MAC + // TODO: shiang-usw, check this for RMTP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { +#ifdef RTMP_MAC_PCI + /* Enable Interrupt*/ + RTMP_IRQ_ENABLE(pAd); +#endif /* RTMP_MAC_PCI */ + + /* Now Enable RxTx*/ + RTMPEnableRxTx(pAd); + } +#endif /* RTMP_MAC */ + + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP); + + + + + +#ifdef CONFIG_AP_SUPPORT +#ifdef BG_FT_SUPPORT + BG_FTPH_Init(); +#endif /* BG_FT_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + + + + + +#ifdef WSC_INCLUDED +#ifdef CONFIG_AP_SUPPORT + if ((pAd->OpMode == OPMODE_AP) + ) + { + INT index; + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { +#ifdef HOSTAPD_SUPPORT + if (pAd->ApCfg.MBSSID[index].Hostapd == Hostapd_EXT) + { + DBGPRINT(RT_DEBUG_TRACE, ("WPS is control by hostapd now.\n")); + } + else +#endif /*HOSTAPD_SUPPORT*/ + { + PWSC_CTRL pWscControl; + UCHAR zeros16[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + pWscControl = &pAd->ApCfg.MBSSID[index].WscControl; + DBGPRINT(RT_DEBUG_TRACE, ("Generate UUID for apidx(%d)\n", index)); + if (NdisEqualMemory(&pWscControl->Wsc_Uuid_E[0], zeros16, UUID_LEN_HEX)) + WscGenerateUUID(pAd, &pWscControl->Wsc_Uuid_E[0], &pWscControl->Wsc_Uuid_Str[0], index, FALSE); + WscInit(pAd, FALSE, index); + } + } + +#ifdef APCLI_SUPPORT + for(index = 0; index < MAX_APCLI_NUM; index++) + { + PWSC_CTRL pWpsCtrl = &pAd->ApCfg.ApCliTab[index].WscControl; + + pWpsCtrl->pAd = pAd; + NdisZeroMemory(pWpsCtrl->EntryAddr, MAC_ADDR_LEN); +#ifdef WSC_V2_SUPPORT + pWpsCtrl->WscConfigMethods= 0x278C; +#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 */ + + + /* WSC hardware push button function 0811 */ + WSC_HDR_BTN_Init(pAd); +#endif /* WSC_INCLUDED */ + +#ifdef MT_MAC + pAd->PSEWatchDogEn = 1; +#ifdef RTMP_PCI_SUPPORT + pAd->PDMAWatchDogEn = 1; +#endif + +#ifdef DMA_RESET_SUPPORT + pAd->bcn_reset_en = TRUE; +#endif /* DMA_RESET_SUPPORT */ + +#ifdef MT_WOW_SUPPORT + pAd->WOW_Cfg.bWoWRunning = FALSE; +#endif + +#endif + + if (pAd->ed_th >= NON_CE_REGION_MAX_ED_TH) {/*original ED flow*/ + /* Only turn EDCCA on in CE region */ + BOOLEAN bEdcca = FALSE; + + bEdcca = GetEDCCASupport(pAd); + if (bEdcca) { + /*pAd->ed_current_region_is_CE = TRUE;*/ + ed_monitor_init(pAd); + } else + ed_monitor_exit(pAd); + } else + ed_monitor_init(pAd);/*false enable edcca for all region*/ + +} + + +VOID RTMPDrvClose(VOID *pAdSrc, VOID *net_dev) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pAdSrc; + UINT32 i = 0; + +#ifdef MT_MAC + pAd->PSEWatchDogEn = 0; +#ifdef RTMP_PCI_SUPPORT + pAd->PDMAWatchDogEn = 0; +#endif + +#ifdef DMA_RESET_SUPPORT + pAd->bcn_reset_en = FALSE; + pAd->PSEResetFailRecover = FALSE; + pAd->PSEResetFailRetryQuota = FALSE; +#endif /* DMA_RESET_SUPPORT */ + +#endif + + +#ifdef CONFIG_AP_SUPPORT +#ifdef BG_FT_SUPPORT + BG_FTPH_Remove(); +#endif /* BG_FT_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + + +#if ((defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) || defined(MT_WOW_SUPPORT)) && defined(WOW_IFDOWN_SUPPORT) + if (!((pAd->WOW_Cfg.bEnable == TRUE) && INFRA_ON(pAd))) +#endif /* ((defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) || defined(MT_WOW_SUPPORT)) && defined(WOW_IFDOWN_SUPPORT) */ + { +#ifdef MT_MAC + if (pAd->chipCap.hif_type != HIF_MT) +#endif /* MT_MAC */ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + } + +#ifdef EXT_BUILD_CHANNEL_LIST + if (pAd->CommonCfg.pChDesp != NULL) + os_free_mem(NULL, pAd->CommonCfg.pChDesp); + pAd->CommonCfg.pChDesp = NULL; + pAd->CommonCfg.DfsType = MAX_RD_REGION; + pAd->CommonCfg.bCountryFlag = 0; +#endif /* EXT_BUILD_CHANNEL_LIST */ + pAd->CommonCfg.bCountryFlag = FALSE; + + + +#ifdef WDS_SUPPORT + WdsDown(pAd); +#endif /* WDS_SUPPORT */ + + 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) + { +#if (defined(RTMP_MAC_USB) && !defined(BCN_OFFLOAD_SUPPORT)) || defined(DOT11N_DRAFT3) + BOOLEAN Cancelled = FALSE; +#endif /* (defined(RTMP_MAC_USB) && !defined(BCN_OFFLOAD_SUPPORT)) || defined(DOT11N_DRAFT3) */ + +#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 */ + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef MAT_SUPPORT + MATEngineExit(pAd); +#endif /* MAT_SUPPORT */ + +#ifdef CLIENT_WDS + CliWds_ProxyTabDestory(pAd); +#endif /* CLIENT_WDS */ + +#ifdef DMA_RESET_SUPPORT + pAd->bcn_not_idle_tx_dma_busy=0; + pAd->bcn_didx_val = 255; + pAd->pse_reset_flag = FALSE; + pAd->dma_force_reset_count=0; +#endif /* DMA_RESET_SUPPORT */ + + /* 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 */ + + /* Close net tasklets*/ + RtmpNetTaskExit(pAd); + + /* Stop Mlme state machine*/ + MlmeHalt(pAd); + + 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 + { + RTMPDisableRxTx(pAd); + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) + { + DISABLE_TX_RX(pAd, RTMP_HALT); + RTMP_ASIC_INTERRUPT_DISABLE(pAd); + } + } + + /* Receive packets to clear DMA index after disable interrupt. */ + /*RTMPHandleRxDoneInterrupt(pAd);*/ + /* put to radio off to save power when driver unload. After radiooff, can't write /read register. So need to finish all */ + /* register access before Radio off.*/ + +#ifdef RTMP_PCI_SUPPORT + if (pAd->infType == RTMP_DEV_INF_PCI || pAd->infType == RTMP_DEV_INF_PCIE) + { + BOOLEAN brc = TRUE; + + 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 */ + + MCU_CTRL_EXIT(pAd); + + /* Free Ring or USB buffers*/ +#ifdef RESOURCE_PRE_ALLOC + RTMPResetTxRxRingMemory(pAd); +#else + /* Free Ring or USB buffers*/ + RTMPFreeTxRxRingMemory(pAd); +#endif /* RESOURCE_PRE_ALLOC */ + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + +#ifdef WLAN_SKB_RECYCLE + skb_queue_purge(&pAd->rx0_recycle); +#endif /* WLAN_SKB_RECYCLE */ + +#ifdef DOT11_N_SUPPORT + /* Free BA reorder resource*/ + ba_reordering_resource_release(pAd); +#endif /* DOT11_N_SUPPORT */ + + UserCfgExit(pAd); /* must after ba_reordering_resource_release */ + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + ExitTxSTypeTable(pAd); +#endif + + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP); + +/*+++Modify by woody to solve the bulk fail+++*/ + + /* clear MAC table */ + /* TODO: do not clear spin lock, such as fLastChangeAccordingMfbLock */ + NdisZeroMemory(&pAd->MacTab, sizeof(MAC_TABLE)); + + /* release all timers */ + RtmpusecDelay(2000); + RTMP_AllTimerListRelease(pAd); + +#ifdef RTMP_TIMER_TASK_SUPPORT + NdisFreeSpinLock(&pAd->TimerQLock); +#endif /* RTMP_TIMER_TASK_SUPPORT */ + +#ifdef CONFIG_FPGA_MODE +#ifdef CAPTURE_MODE + cap_mode_deinit(pAd); +#endif /* CAPTURE_MODE */ +#endif /* CONFIG_FPGA_MODE */ + +} + + +VOID RTMPInfClose(VOID *pAdSrc) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pAdSrc; +#ifdef CONFIG_AP_SUPPORT + pAd->ApCfg.MBSSID[MAIN_MBSSID].bcn_buf.bBcnSntReq = FALSE; + + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* kick out all STAs behind the bss.*/ + MbssKickOutStas(pAd, MAIN_MBSSID, REASON_DISASSOC_INACTIVE); + } + + //CFG_TODO + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); +#ifdef BAND_STEERING + if(pAd->ApCfg.BandSteering) + { + PBND_STRG_CLI_TABLE table; + table = Get_BndStrgTable(pAd, BSS0); + if(table) + { + /* Inform daemon interface down */ + BndStrg_SetInfFlags(pAd, &pAd->ApCfg.MBSSID[BSS0].wdev, table, FALSE); + } + } +#endif /* BAND_STEERING */ +#endif /* CONFIG_AP_SUPPORT */ + + + +} + + + + +PNET_DEV RtmpPhyNetDevMainCreate(VOID *pAdSrc) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pAdSrc; + PNET_DEV pDevNew; + UINT32 MC_RowID = 0, IoctlIF = 0; + char *dev_name; + +#ifdef MULTIPLE_CARD_SUPPORT + MC_RowID = pAd->MC_RowID; +#endif /* MULTIPLE_CARD_SUPPORT */ +#ifdef HOSTAPD_SUPPORT + IoctlIF = pAd->IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + + if (load_dev_l1profile(pAd) == NDIS_STATUS_SUCCESS) + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_INFO, ("load l1profile succeed!\n")); + else + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("load l1profile failed!\n")); + + dev_name = get_dev_name_prefix(pAd, INT_MAIN); + pDevNew = RtmpOSNetDevCreate((INT32)MC_RowID, (UINT32 *)&IoctlIF, + INT_MAIN, 0, sizeof(struct mt_dev_priv), dev_name); + +#ifdef HOSTAPD_SUPPORT + pAd->IoctlIF = IoctlIF; +#endif /* HOSTAPD_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + if (pAd->OpMode == OPMODE_AP) + { + BSS_STRUCT *pMbss; + pMbss = &pAd->ApCfg.MBSSID[MAIN_MBSSID]; + ASSERT(pMbss); + if (pMbss) { + wdev_bcn_buf_init(pAd, &pMbss->bcn_buf); + } else { + DBGPRINT(RT_DEBUG_ERROR, ("%s():func_dev is NULL!\n", __FUNCTION__)); + return NULL; + } + } +#endif + + return pDevNew; +} + + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rtmp_timer.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rtmp_timer.c new file mode 100644 index 000000000..13be80e8e --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/rtmp_timer.c @@ -0,0 +1,368 @@ +/* + *************************************************************************** + * 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(MlmePeriodicExecTimer); +/*BUILD_TIMER_FUNCTION(MlmeRssiReportExec);*/ +BUILD_TIMER_FUNCTION(AsicRxAntEvalTimeout); +BUILD_TIMER_FUNCTION(APSDPeriodicExec); +BUILD_TIMER_FUNCTION(EnqueueStartForPSKExec); + +#ifdef DOT11W_PMF_SUPPORT +BUILD_TIMER_FUNCTION(PMF_SAQueryTimeOut); +BUILD_TIMER_FUNCTION(PMF_SAQueryConfirmTimeOut); +#endif /* DOT11W_PMF_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +extern VOID APDetectOverlappingExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +BUILD_TIMER_FUNCTION(APDetectOverlappingExec); + +#ifdef DOT11N_DRAFT3 +BUILD_TIMER_FUNCTION(Bss2040CoexistTimeOut); +#endif /* DOT11N_DRAFT3 */ + +BUILD_TIMER_FUNCTION(GREKEYPeriodicExec); +BUILD_TIMER_FUNCTION(CMTimerExec); +BUILD_TIMER_FUNCTION(WPARetryExec); +#ifdef AP_SCAN_SUPPORT +BUILD_TIMER_FUNCTION(APScanTimeout); +#endif /* AP_SCAN_SUPPORT */ +BUILD_TIMER_FUNCTION(APQuickResponeForRateUpExec); +#ifdef IDS_SUPPORT +BUILD_TIMER_FUNCTION(RTMPIdsPeriodicExec); +#endif /* IDS_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT +BUILD_TIMER_FUNCTION(FT_KDP_InfoBroadcast); +#endif /* DOT11R_FT_SUPPORT */ + +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef WSC_INCLUDED +BUILD_TIMER_FUNCTION(WscEAPOLTimeOutAction); +BUILD_TIMER_FUNCTION(Wsc2MinsTimeOutAction); +BUILD_TIMER_FUNCTION(WscUPnPMsgTimeOutAction); +BUILD_TIMER_FUNCTION(WscM2DTimeOutAction); + +BUILD_TIMER_FUNCTION(WscPBCTimeOutAction); +BUILD_TIMER_FUNCTION(WscScanTimeOutAction); +BUILD_TIMER_FUNCTION(WscProfileRetryTimeout); +#ifdef WSC_LED_SUPPORT +BUILD_TIMER_FUNCTION(WscLEDTimer); +BUILD_TIMER_FUNCTION(WscSkipTurnOffLEDTimer); +#endif /* WSC_LED_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +BUILD_TIMER_FUNCTION(WscUpdatePortCfgTimeout); +BUILD_TIMER_FUNCTION(WscSetupLockTimeout); +#ifdef MT_MAC +BUILD_TIMER_FUNCTION(WscEapReqIdRetryTimeout); +#endif /* MT_MAC */ +#endif /* CONFIG_AP_SUPPORT */ + + +#endif /* WSC_INCLUDED */ + + + + + +#ifdef CONFIG_ATE +BUILD_TIMER_FUNCTION(ATEPeriodicExec); +#endif /* CONFIG_ATE */ + +#ifdef MIXMODE_SUPPORT +BUILD_TIMER_FUNCTION(MixModeTimeout); +#endif /* MIXMODE_SUPPORT */ + +#ifdef WH_EZ_SETUP +BUILD_TIMER_FUNCTION(ez_scan_timeout); +//BUILD_TIMER_FUNCTION(ez_stop_scan_timeout); +BUILD_TIMER_FUNCTION(ez_scan_pause_timeout); +#ifdef EZ_NETWORK_MERGE_SUPPORT +BUILD_TIMER_FUNCTION(ez_group_merge_timeout); +#endif +#ifdef NEW_CONNECTION_ALGO +BUILD_TIMER_FUNCTION(ez_wait_for_connection_allow_timeout); +#endif +#ifdef EZ_DUAL_BAND_SUPPORT +BUILD_TIMER_FUNCTION(ez_loop_chk_timeout); +#endif +#endif /* WH_EZ_SETUP */ + +#ifdef RTMP_TIMER_TASK_SUPPORT +static void RtmpTimerQHandle(RTMP_ADAPTER *pAd) +{ + int status; + RALINK_TIMER_STRUCT *pTimer; + RTMP_TIMER_TASK_ENTRY *pEntry; + unsigned long irqFlag; + RTMP_OS_TASK *pTask; + + pTask = &pAd->timerTask; + while(!RTMP_OS_TASK_IS_KILLED(pTask)) + { + pTimer = NULL; + + if (RtmpOSTaskWait(pAd, pTask, &status) == FALSE) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + break; + } + + if (pAd->TimerQ.status == RTMP_TASK_STAT_STOPED) + break; + + /* event happened.*/ + while(pAd->TimerQ.pQHead) + { + RTMP_INT_LOCK(&pAd->TimerQLock, irqFlag); + pEntry = pAd->TimerQ.pQHead; + if (pEntry) + { + pTimer = pEntry->pRaTimer; + + /* update pQHead*/ + pAd->TimerQ.pQHead = pEntry->pNext; + if (pEntry == pAd->TimerQ.pQTail) + pAd->TimerQ.pQTail = NULL; + + /* return this queue entry to timerQFreeList.*/ + pEntry->pNext = pAd->TimerQ.pQPollFreeList; + pAd->TimerQ.pQPollFreeList = pEntry; + } + RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlag); + + if (pTimer) + { + if ((pTimer->handle != NULL) && (!pAd->PM_FlgSuspend)) + pTimer->handle(NULL, (PVOID) pTimer->cookie, NULL, pTimer); + if ((pTimer->Repeat) && (pTimer->State == FALSE)) + RTMP_OS_Add_Timer(&pTimer->TimerObj, pTimer->TimerValue); + } + } + + if (status != 0) + { + pAd->TimerQ.status = RTMP_TASK_STAT_STOPED; + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + break; + } + } +} + + +INT RtmpTimerQThread( + IN ULONG Context) +{ + RTMP_OS_TASK *pTask; + PRTMP_ADAPTER pAd = NULL; + + + pTask = (RTMP_OS_TASK *)Context; + pAd = (PRTMP_ADAPTER)RTMP_OS_TASK_DATA_GET(pTask); + + if (pAd == NULL) + { + DBGPRINT(RT_DEBUG_ERROR,( "%s:: pAd is NULL!\n",__FUNCTION__)); + return 0; + } + + RtmpOSTaskCustomize(pTask); + + RtmpTimerQHandle(pAd); + + DBGPRINT(RT_DEBUG_TRACE,( "<---%s\n",__FUNCTION__)); + /* notify the exit routine that we're actually exiting now + * + * complete()/wait_for_completion() is similar to up()/down(), + * except that complete() is safe in the case where the structure + * is getting deleted in a parallel mode of execution (i.e. just + * after the down() -- that's necessary for the thread-shutdown + * case. + * + * complete_and_exit() goes even further than this -- it is safe in + * the case that the thread of the caller is going away (not just + * the structure) -- this is necessary for the module-remove case. + * This is important in preemption kernels, which transfer the flow + * of execution immediately upon a complete(). + */ + RtmpOSTaskNotifyToExit(pTask); + + return 0; + +} + + +RTMP_TIMER_TASK_ENTRY *RtmpTimerQInsert( + IN RTMP_ADAPTER *pAd, + IN RALINK_TIMER_STRUCT *pTimer) +{ + RTMP_TIMER_TASK_ENTRY *pQNode = NULL, *pQTail; + unsigned long irqFlags; + RTMP_OS_TASK *pTask = &pAd->timerTask; + + RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); + if (pAd->TimerQ.status & RTMP_TASK_CAN_DO_INSERT) + { + if(pAd->TimerQ.pQPollFreeList) + { + pQNode = pAd->TimerQ.pQPollFreeList; + pAd->TimerQ.pQPollFreeList = pQNode->pNext; + + pQNode->pRaTimer = pTimer; + pQNode->pNext = NULL; + + pQTail = pAd->TimerQ.pQTail; + if (pAd->TimerQ.pQTail != NULL) + pQTail->pNext = pQNode; + pAd->TimerQ.pQTail = pQNode; + if (pAd->TimerQ.pQHead == NULL) + pAd->TimerQ.pQHead = pQNode; + } + } + RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); + + if (pQNode) + { + RTMP_OS_TASK_WAKE_UP(pTask); + } + + return pQNode; +} + + +BOOLEAN RtmpTimerQRemove( + IN RTMP_ADAPTER *pAd, + IN RALINK_TIMER_STRUCT *pTimer) +{ + RTMP_TIMER_TASK_ENTRY *pNode, *pPrev = NULL; + unsigned long irqFlags; + + RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); + if (pAd->TimerQ.status >= RTMP_TASK_STAT_INITED) + { + pNode = pAd->TimerQ.pQHead; + while (pNode) + { + if (pNode->pRaTimer == pTimer) + break; + pPrev = pNode; + pNode = pNode->pNext; + } + + /* Now move it to freeList queue.*/ + if (pNode) + { + if (pNode == pAd->TimerQ.pQHead) + pAd->TimerQ.pQHead = pNode->pNext; + if (pNode == pAd->TimerQ.pQTail) + pAd->TimerQ.pQTail = pPrev; + if (pPrev != NULL) + pPrev->pNext = pNode->pNext; + + /* return this queue entry to timerQFreeList.*/ + pNode->pNext = pAd->TimerQ.pQPollFreeList; + pAd->TimerQ.pQPollFreeList = pNode; + } + } + RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); + + return TRUE; +} + + +void RtmpTimerQExit(RTMP_ADAPTER *pAd) +{ + RTMP_TIMER_TASK_ENTRY *pTimerQ; + unsigned long irqFlags; + + RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); + while (pAd->TimerQ.pQHead) + { + pTimerQ = pAd->TimerQ.pQHead; + pAd->TimerQ.pQHead = pTimerQ->pNext; + /* remove the timeQ*/ + } + pAd->TimerQ.pQPollFreeList = NULL; + os_free_mem(pAd, pAd->TimerQ.pTimerQPoll); + pAd->TimerQ.pQTail = NULL; + pAd->TimerQ.pQHead = NULL; +/*#ifndef KTHREAD_SUPPORT*/ + pAd->TimerQ.status = RTMP_TASK_STAT_STOPED; +/*#endif*/ + RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); +/* NdisFreeSpinLock(&pAd->TimerQLock); */ +} + + +void RtmpTimerQInit(RTMP_ADAPTER *pAd) +{ + int i; + RTMP_TIMER_TASK_ENTRY *pQNode, *pEntry; + unsigned long irqFlags; + + NdisAllocateSpinLock(pAd, &pAd->TimerQLock); + + NdisZeroMemory(&pAd->TimerQ, sizeof(pAd->TimerQ)); + + os_alloc_mem(pAd, &pAd->TimerQ.pTimerQPoll, sizeof(RTMP_TIMER_TASK_ENTRY) * TIMER_QUEUE_SIZE_MAX); + if (pAd->TimerQ.pTimerQPoll) + { + pEntry = NULL; + pQNode = (RTMP_TIMER_TASK_ENTRY *)pAd->TimerQ.pTimerQPoll; + NdisZeroMemory(pAd->TimerQ.pTimerQPoll, sizeof(RTMP_TIMER_TASK_ENTRY) * TIMER_QUEUE_SIZE_MAX); + + RTMP_INT_LOCK(&pAd->TimerQLock, irqFlags); + for (i = 0 ;i pNext = pEntry; + pEntry = pQNode; + pQNode++; + } + pAd->TimerQ.pQPollFreeList = pEntry; + pAd->TimerQ.pQHead = NULL; + pAd->TimerQ.pQTail = NULL; + pAd->TimerQ.status = RTMP_TASK_STAT_INITED; + RTMP_INT_UNLOCK(&pAd->TimerQLock, irqFlags); + } +} +#endif /* RTMP_TIMER_TASK_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/sae.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/sae.c new file mode 100644 index 000000000..d0ac22b62 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/sae.c @@ -0,0 +1,2759 @@ +#ifdef DOT11_SAE_SUPPORT + +#include "rt_config.h" +#include "ecc.h" + +BUILD_TIMER_FUNCTION(sae_auth_retransmit); + +const SAE_GROUP_OP ecc_group_op = { + .sae_group_init = sae_group_init_ecc, + .sae_group_deinit = sae_group_deinit_ecc, + .sae_cn_confirm = sae_cn_confirm_ecc, + .sae_parse_commit_element = sae_parse_commit_element_ecc, + .sae_derive_commit_element = sae_derive_commit_element_ecc, + .sae_derive_pwe = sae_derive_pwe_ecc, + .sae_derive_k = sae_derive_k_ecc, + .sae_reflection_check = sae_reflection_check_ecc, +}; + +const SAE_GROUP_OP ffc_group_op = { + .sae_group_init = sae_group_init_ffc, + .sae_group_deinit = sae_group_deinit_ffc, + .sae_cn_confirm = sae_cn_confirm_ffc, + .sae_parse_commit_element = sae_parse_commit_element_ffc, + .sae_derive_commit_element = sae_derive_commit_element_ffc, + .sae_derive_pwe = sae_derive_pwe_ffc, + .sae_derive_k = sae_derive_k_ffc, + .sae_reflection_check = sae_reflection_check_ffc, +}; + +static DH_GROUP_INFO dh_groups[] = { + DH_GROUP(5, 1), + DH_GROUP(1, 1), + DH_GROUP(2, 1), + DH_GROUP(14, 1), + DH_GROUP(15, 1), + DH_GROUP(16, 1), + DH_GROUP(17, 1), + DH_GROUP(18, 1), + DH_GROUP(22, 0), + DH_GROUP(23, 0), + DH_GROUP(24, 0) +}; + + + +static DH_GROUP_INFO_BI dh_groups_bi[] = { + DH_GROUP_BI(5, 1), + DH_GROUP_BI(1, 1), + DH_GROUP_BI(2, 1), + DH_GROUP_BI(14, 1), + DH_GROUP_BI(15, 1), + DH_GROUP_BI(16, 1), + DH_GROUP_BI(17, 1), + DH_GROUP_BI(18, 1), + DH_GROUP_BI(22, 0), + DH_GROUP_BI(23, 0), + DH_GROUP_BI(24, 0) +}; + +#ifdef BI_POOL_DBG +UINT32 sae_expected_cnt[20]; /* 0~12 is used */ +#endif + +int SAE_DEBUG_LEVEL = DBG_LVL_LOUD; +int SAE_DEBUG_LEVEL2 = DBG_LVL_TRACE; +int SAE_COST_TIME_DBG_LVL = DBG_LVL_INFO; + +UCHAR sae_support_group_list[] = {19, 20, 25, 26}; + +static UCHAR delete_all_removable_sae_instance( + IN SAE_CFG * pSaeCfg) +{ + UINT32 i; + SAE_INSTANCE *pSaeIns = NULL; + UINT32 del_ins_cnt = 0; + + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) { + pSaeIns = &pSaeCfg->sae_ins[i]; + + if (pSaeCfg->sae_ins[i].valid == FALSE) + continue; + + if (pSaeIns->same_mac_ins) { + if (pSaeIns->same_mac_ins->valid == TRUE) { + delete_sae_instance(pSaeIns->same_mac_ins); + del_ins_cnt++; + } + pSaeIns->same_mac_ins = NULL; + } + + if (pSaeIns->removable == TRUE) { + delete_sae_instance(pSaeIns); + del_ins_cnt++; + } + } + + if (del_ins_cnt != 0) + return TRUE; + else + return FALSE; +} + + +INT show_sae_info_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 i; + SAE_CFG * pSaeCfg = &pAd->SaeCfg; + SAE_INSTANCE *pSaeIns = NULL; + UINT32 input = 0; + + if (arg != NULL) + input = simple_strtol(arg, 0, 10); + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_OFF, ("total ins: %d\n", pSaeCfg->total_ins)); + + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) { + if (pSaeCfg->sae_ins[i].valid == FALSE && input != 1) + continue; + + pSaeIns = &pSaeCfg->sae_ins[i]; + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_OFF, + ("idx:%d, v/r:%d/%d, OM=0x%02x:%02x:%02x:%02x:%02x:%02x, PM=0x%02x:%02x:%02x:%02x:%02x:%02x\n", + i, pSaeIns->valid, pSaeIns->removable, + PRINT_MAC(pSaeIns->own_mac), PRINT_MAC(pSaeIns->peer_mac))); + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_OFF, + ("\tstate:%d, group:%d, sync:%d, sc:0x%x, last_peer_sc:0x%x, same_mac_ins=%d, timer_state=%d\n", + pSaeIns->state, pSaeIns->group, pSaeIns->sync, + pSaeIns->send_confirm, pSaeIns->last_peer_sc, + (pSaeIns->same_mac_ins != NULL), + pSaeIns->sae_retry_timer.State)); + + if (pSaeIns->valid && pSaeIns->pParentSaeCfg == NULL) + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_OFF, + ("\t[error]pSaeIns->pParentSaeCfg is NULL\n")); + if (pSaeIns->valid && pSaeIns->psk == NULL) + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_OFF, + ("\t[error]pSaeIns->psk is NULL\n")); + } + + return TRUE; +} + +VOID sae_cfg_init( + IN RTMP_ADAPTER * pAd, + IN SAE_CFG * pSaeCfg) +{ + UINT32 i = 0; + +#ifdef BI_POOL + big_integer_pool_init(); +#endif + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + /* 12.4.8.5.1 When the parent SAE process starts up, Open is set to zero (0) */ + pSaeCfg->pAd = pAd; + pSaeCfg->open = 0; + pSaeCfg->dot11RSNASAERetransPeriod = 2; + pSaeCfg->total_ins = 0; + pSaeCfg->sae_anti_clogging_threshold = 10; + pSaeCfg->last_token_key_time = 0; + NdisZeroMemory(&pSaeCfg->token_key, SAE_TOKEN_KEY_LEN); + + NdisZeroMemory(&pSaeCfg->support_group, MAX_SIZE_OF_ALLOWED_GROUP); + + for (i = 0; i < sizeof(sae_support_group_list)/sizeof(UCHAR); i++) + pSaeCfg->support_group[i] = sae_support_group_list[i]; +} + +VOID sae_cfg_deinit( + IN RTMP_ADAPTER * pAd, + IN SAE_CFG * pSaeCfg) +{ + UINT32 i; + +#ifdef BI_POOL + big_integer_pool_deinit(); +#endif + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) + if (pSaeCfg->sae_ins[i].valid == FALSE) + continue; + else + delete_sae_instance(&pSaeCfg->sae_ins[i]); +} + + + +SAE_INSTANCE *search_sae_instance( + IN SAE_CFG * pSaeCfg, + IN UCHAR *own_mac, + IN UCHAR *peer_mac) +{ + UINT32 i; + SAE_INSTANCE *pSaeIns = NULL; + UINT32 ins_cnt = 0; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + if (!pSaeCfg || !own_mac || !peer_mac) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): search fail with null input\n", __func__)); + return NULL; + } + + NdisAcquireSpinLock(&pSaeCfg->sae_cfg_lock); + + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) { + if (pSaeCfg->sae_ins[i].valid == FALSE) + continue; + + if (RTMPEqualMemory(pSaeCfg->sae_ins[i].own_mac, own_mac, MAC_ADDR_LEN) /* ellis */ + && RTMPEqualMemory(pSaeCfg->sae_ins[i].peer_mac, peer_mac, MAC_ADDR_LEN)) { + pSaeIns = &pSaeCfg->sae_ins[i]; + break; + } + + ins_cnt++; + + if (ins_cnt == pSaeCfg->total_ins) + break; + } + + NdisReleaseSpinLock(&pSaeCfg->sae_cfg_lock); + + if (pSaeIns + && pSaeIns->state == SAE_ACCEPTED + && pSaeIns->same_mac_ins) + pSaeIns = pSaeIns->same_mac_ins; + + return pSaeIns; +} + + +SAE_INSTANCE *create_sae_instance( + IN RTMP_ADAPTER * pAd, + IN SAE_CFG * pSaeCfg, + IN UCHAR *own_mac, + IN UCHAR *peer_mac, + IN UCHAR *bssid, + IN UCHAR *psk) +{ + UINT32 i; + SAE_INSTANCE *pSaeIns = NULL; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("==> %s()\n", __func__)); + + if (pSaeCfg == NULL || own_mac == NULL || + peer_mac == NULL || bssid == NULL || psk == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s():input should not be null\n", __func__)); + return NULL; + } + + if ((pSaeCfg->total_ins == MAX_LEN_OF_MAC_TABLE) && + (delete_all_removable_sae_instance(pSaeCfg) == FALSE)) { + return NULL; + } + + NdisAcquireSpinLock(&pSaeCfg->sae_cfg_lock); + + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) { + if (pSaeCfg->sae_ins[i].valid == FALSE) { + pSaeIns = &pSaeCfg->sae_ins[i]; + sae_ins_init(pAd, pSaeCfg, pSaeIns, + own_mac, peer_mac, bssid, psk); + pSaeIns->valid = TRUE; + pSaeCfg->total_ins++; + break; + } + } + + NdisReleaseSpinLock(&pSaeCfg->sae_cfg_lock); + return pSaeIns; +} + + +VOID delete_sae_instance( + IN SAE_INSTANCE *pSaeIns) +{ + SAE_CFG *pSaeCfg = NULL; + BOOLEAN Cancelled; + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + if (pSaeIns == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): pSaeIns is NULL\n", __func__)); + return; + } + + pSaeCfg = pSaeIns->pParentSaeCfg; + if (pSaeCfg == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): pSaeCfg is NULL\n", __func__)); + return; + } + + NdisAcquireSpinLock(&pSaeCfg->sae_cfg_lock); + RTMPReleaseTimer(&pSaeIns->sae_retry_timer, &Cancelled); + pSaeIns->valid = FALSE; + pSaeIns->removable = FALSE; + if (pSaeIns->group_op) + pSaeIns->group_op->sae_group_deinit(pSaeIns); + + if (pSaeIns->anti_clogging_token) { + os_free_mem(NULL, pSaeIns->anti_clogging_token); + pSaeIns->anti_clogging_token = NULL; + } + + SAE_BN_FREE(&pSaeIns->sae_rand); + + if (pSaeIns->same_mac_ins) { + pSaeIns->same_mac_ins->same_mac_ins = NULL; + pSaeIns->same_mac_ins = NULL; + } + SAE_BN_FREE(&pSaeIns->own_commit_scalar); + SAE_BN_FREE(&pSaeIns->peer_commit_scalar); + NdisZeroMemory(pSaeIns, sizeof(SAE_INSTANCE)); + pSaeCfg->total_ins--; + NdisReleaseSpinLock(&pSaeCfg->sae_cfg_lock); + return; +} + +UCHAR set_sae_instance_removable( + IN SAE_CFG * pSaeCfg, + IN UCHAR *own_mac, + IN UCHAR *peer_mac) +{ + SAE_INSTANCE *pSaeIns = search_sae_instance(pSaeCfg, own_mac, peer_mac); + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("%s:OM=%02x:%02x:%02x:%02x:%02x:%02x, PM=%02x:%02x:%02x:%02x:%02x:%02x\n", + __func__, PRINT_MAC(own_mac), PRINT_MAC(peer_mac))); + + if (pSaeIns == NULL) + return FALSE; + + pSaeIns->removable = TRUE; + return TRUE; +} + +VOID sae_ins_init( + IN RTMP_ADAPTER * pAd, + IN SAE_CFG *pSaeCfg, + IN SAE_INSTANCE *pSaeIns, + IN UCHAR *own_mac, + IN UCHAR *peer_mac, + IN UCHAR *bssid, + IN UCHAR *psk) +{ + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + NdisZeroMemory(pSaeIns, sizeof(SAE_INSTANCE)); + COPY_MAC_ADDR(pSaeIns->own_mac, own_mac); + COPY_MAC_ADDR(pSaeIns->peer_mac, peer_mac); + COPY_MAC_ADDR(pSaeIns->bssid, bssid); + RTMPInitTimer(pAd, &pSaeIns->sae_retry_timer, GET_TIMER_FUNCTION(sae_auth_retransmit), pSaeIns, FALSE); + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_INFO, ("%s: timer valid = %d\n", __func__, pSaeIns->sae_retry_timer.Valid)); + pSaeIns->pParentSaeCfg = pSaeCfg; + pSaeIns->psk = psk; + SET_NOTHING_STATE(pSaeIns); + pSaeIns->sync = 0; + /* 12.4.8.5.2 + * The number of Confirm messages that have been sent. + * This is the send-confirm counter used in the construction of Confirm messages + */ + pSaeIns->send_confirm = 0; /* ellis */ + pSaeIns->last_peer_sc = 0; + pSaeIns->support_group_idx = 0; + pSaeIns->same_mac_ins = NULL; + pSaeIns->removable = FALSE; +} + +/* partial */ +VOID sae_clear_data( + IN SAE_INSTANCE *pSaeIns) +{ + BOOLEAN Cancelled; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + if (pSaeIns->group_op) + pSaeIns->group_op->sae_group_deinit(pSaeIns); + + if (pSaeIns->anti_clogging_token) { + os_free_mem(NULL, pSaeIns->anti_clogging_token); + pSaeIns->anti_clogging_token = NULL; + } + + SAE_BN_FREE(&pSaeIns->sae_rand); + SAE_BN_FREE(&pSaeIns->peer_commit_scalar); + SAE_BN_FREE(&pSaeIns->own_commit_scalar); + SET_NOTHING_STATE(pSaeIns); + NdisZeroMemory(pSaeIns, offsetof(SAE_INSTANCE, valid)); + RTMPCancelTimer(&pSaeIns->sae_retry_timer, &Cancelled); + /* RTMPReleaseTimer(&pSaeIns->sae_retry_timer, &Cancelled); */ +} + +static VOID sae_record_time_begin( + INOUT ULONG *time_interval) +{ + NdisGetSystemUpTime(time_interval); +} + +static VOID sae_record_time_end( + IN UCHAR *str, + INOUT ULONG *time_interval) +{ + ULONG temp; + NdisGetSystemUpTime(&temp); + *time_interval = temp - *time_interval; +} + + +VOID sae_dump_time( + IN SAE_TIME_INTERVAL * time_cost +) +{ + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, SAE_COST_TIME_DBG_LVL, ("cost time:")); + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, SAE_COST_TIME_DBG_LVL, ("\npwe: %lu jiffies", time_cost->derive_pwe_time)); +#ifdef LINUX + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, SAE_COST_TIME_DBG_LVL, (", %u msec", jiffies_to_msecs(time_cost->derive_pwe_time))); +#endif + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, SAE_COST_TIME_DBG_LVL, ("\nparse scalar: %lu jiffies", time_cost->parse_commit_scalar_time)); +#ifdef LINUX + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, SAE_COST_TIME_DBG_LVL, (", %u msec", jiffies_to_msecs(time_cost->parse_commit_scalar_time))); +#endif + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, SAE_COST_TIME_DBG_LVL, ("\nparse element: %lu jiffies", time_cost->parse_commit_element_time)); +#ifdef LINUX + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, SAE_COST_TIME_DBG_LVL, (", %u msec", jiffies_to_msecs(time_cost->parse_commit_element_time))); +#endif + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, SAE_COST_TIME_DBG_LVL, ("\nderive scalar: %lu jiffies", time_cost->derive_commit_scalar_time)); +#ifdef LINUX + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, SAE_COST_TIME_DBG_LVL, (", %u msec", jiffies_to_msecs(time_cost->derive_commit_scalar_time))); +#endif + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, SAE_COST_TIME_DBG_LVL, ("\nderive element: %lu jiffies", time_cost->derive_commit_element_time)); +#ifdef LINUX + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, SAE_COST_TIME_DBG_LVL, (", %u msec", jiffies_to_msecs(time_cost->derive_commit_element_time))); +#endif + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, SAE_COST_TIME_DBG_LVL, ("\nk: %lu jiffies", time_cost->derive_k_time)); +#ifdef LINUX + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, SAE_COST_TIME_DBG_LVL, (", %u msec", jiffies_to_msecs(time_cost->derive_k_time))); +#endif + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, SAE_COST_TIME_DBG_LVL, ("\npmk: %lu jiffies", time_cost->derive_pmk_time)); +#ifdef LINUX + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, SAE_COST_TIME_DBG_LVL, (", %u msec", jiffies_to_msecs(time_cost->derive_pmk_time))); +#endif + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, SAE_COST_TIME_DBG_LVL, ("\n")); + + time_cost->derive_pwe_time = 0; + time_cost->parse_commit_scalar_time = 0; + time_cost->parse_commit_element_time = 0; + time_cost->derive_commit_scalar_time = 0; + time_cost->derive_commit_element_time = 0; + time_cost->derive_k_time = 0; + time_cost->derive_pmk_time = 0; + +#ifdef BI_POOL + sae_dump_pool_info_check(0, FALSE, TRUE); +#endif +} + + +UCHAR sae_using_anti_clogging( + IN SAE_CFG *pSaeCfg) +{ + UINT32 i; + UINT32 ins_cnt = 0; + UINT32 open = 0; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + if (pSaeCfg->total_ins < pSaeCfg->sae_anti_clogging_threshold) + return FALSE; + + NdisAcquireSpinLock(&pSaeCfg->sae_cfg_lock); + + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) { + if (pSaeCfg->sae_ins[i].valid == FALSE) + continue; + + ins_cnt++; + + if ((pSaeCfg->sae_ins[i].state == SAE_COMMITTED) + || (pSaeCfg->sae_ins[i].state == SAE_CONFIRMED)) + open++; + + if (open >= pSaeCfg->sae_anti_clogging_threshold) { + NdisReleaseSpinLock(&pSaeCfg->sae_cfg_lock); + return TRUE; + } + + if (ins_cnt == pSaeCfg->total_ins) + break; + } + + NdisReleaseSpinLock(&pSaeCfg->sae_cfg_lock); + return FALSE; +} + + +VOID sae_set_retransmit_timer( + IN SAE_INSTANCE *pSaeIns) +{ + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + RTMPSetTimer(&pSaeIns->sae_retry_timer, pSaeIns->pParentSaeCfg->dot11RSNASAERetransPeriod * 1000); +} + + +VOID sae_clear_retransmit_timer( + IN SAE_INSTANCE *pSaeIns) +{ + BOOLEAN Cancelled; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + RTMPCancelTimer(&pSaeIns->sae_retry_timer, &Cancelled); +} + +VOID sae_auth_retransmit( + IN VOID *SystemSpecific1, + IN VOID *FunctionContext, + IN VOID *SystemSpecific2, + IN VOID *SystemSpecific3) +{ + SAE_INSTANCE *pSaeIns = (SAE_INSTANCE *) FunctionContext; + RALINK_TIMER_STRUCT *pTimer = (RALINK_TIMER_STRUCT *) SystemSpecific3; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)pTimer->pAd; + UCHAR ret; +#ifdef APCLI_SUPPORT +#ifdef APCLI_SAE_SUPPORT + UCHAR idx = 0; + PAPCLI_STRUCT apcli_entry = NULL; + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + USHORT ifIndex = 0; +#ifdef MAC_REPEATER_SUPPORT + REPEATER_CLIENT_ENTRY *rept_entry = NULL; +#endif +#endif +#endif + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + +#ifdef APCLI_SUPPORT +#ifdef APCLI_SAE_SUPPORT + /*In case of ApCli and mac repeater ,we need to reset state machine if sync exceeds threshold*/ + for (idx = 0; idx < pAd->ApCfg.ApCliNum; idx++) { + + apcli_entry = &pAd->ApCfg.ApCliTab[idx]; + + if (MAC_ADDR_EQUAL(pSaeIns->own_mac, apcli_entry->wdev.if_addr) + && pSaeIns && sae_check_big_sync(pSaeIns)) { + + apcli_entry->AuthCurrState = APCLI_AUTH_REQ_IDLE; + ApCliCtrlMsg.Status = MLME_UNSPECIFY_FAIL; +#ifdef MAC_REPEATER_SUPPORT + ApCliCtrlMsg.CliIdx = 0xFF; + ApCliCtrlMsg.BssIdx = apcli_entry->wdev.func_idx; + ifIndex = apcli_entry->wdev.func_idx; +#endif /* MAC_REPEATER_SUPPORT */ + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("==> %s():reset apcli state machine\n", __func__)); + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + RTMP_MLME_HANDLER(pAd); + return; + } + } +#ifdef MAC_REPEATER_SUPPORT + + rept_entry = lookup_rept_entry(pAd, pSaeIns->own_mac); + + if ((rept_entry != NULL) + && pSaeIns && sae_check_big_sync(pSaeIns)) { + + rept_entry->AuthCurrState = APCLI_AUTH_REQ_IDLE; + /*If SAE instance has been deleted*/ + ApCliCtrlMsg.Status = MLME_UNSPECIFY_FAIL; +#ifdef MAC_REPEATER_SUPPORT + ApCliCtrlMsg.CliIdx = rept_entry->MatchLinkIdx; + ApCliCtrlMsg.BssIdx = rept_entry->MatchApCliIdx; +#endif /* MAC_REPEATER_SUPPORT */ + ifIndex = REPT_MLME_START_IDX + rept_entry->MatchLinkIdx; + + MlmeEnqueue(pAd, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, ifIndex); + RTMP_MLME_HANDLER(pAd); + return; + } +#endif + +#endif +#endif + if (pSaeIns && sae_check_big_sync(pSaeIns)) /* ellis */ + return; + + switch (pSaeIns->state) { + case SAE_COMMITTED: + ret = sae_send_auth_commit(pAd, pSaeIns); + sae_set_retransmit_timer(pSaeIns); + break; + + case SAE_CONFIRMED: + /* If Sync is not greater than dot11RSNASAESync, the Sync counter shall be incremented, + * Sc shall be incremented, and the protocol instance shall create a new Confirm (with the new Sc value) Message, + * transmit it to the peer, and set the t0 (retransmission) timer + */ + ret = sae_send_auth_confirm(pAd, pSaeIns); + sae_set_retransmit_timer(pSaeIns); + break; + + default: + ret = FALSE; + break; + } + + if (ret == FALSE) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): retransemit fail (state = %d, sync = %d)\n", + __func__, pSaeIns->state, pSaeIns->sync)); + } +} + + +UCHAR sae_auth_init( + IN RTMP_ADAPTER *pAd, + IN SAE_CFG *pSaeCfg, + IN UCHAR *own_mac, + IN UCHAR *peer_mac, + IN UCHAR *bssid, + IN UCHAR *psk, + IN INT32 group) +{ + SAE_INSTANCE *pSaeIns = search_sae_instance(pSaeCfg, own_mac, peer_mac); + SAE_INSTANCE *pPreSaeIns = pSaeIns; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("==>%s(): pSaeIns = %p, pSaeIns->state = %d\n", __func__, pSaeIns, (pSaeIns) ? pSaeIns->state : -1)); + + /* 12.4.8.6.1 Upon receipt of an Initiate event, the parent process shall check whether there exists a protocol instance for + * the peer MAC address (from the Init event) in either Committed or Confirmed state. If there is, the Initiate + * event shall be ignored. Otherwise, a protocol instance shall be created, and an Init event shall be sent to the + * protocol instance. + */ + if (pSaeIns && + ((pSaeIns->state == SAE_COMMITTED) + || (pSaeIns->state == SAE_CONFIRMED))) + return FALSE; + + pSaeIns = create_sae_instance(pAd, pSaeCfg, own_mac, peer_mac, bssid, psk); + + if (!pSaeIns) + return FALSE; + + pSaeIns->same_mac_ins = pPreSaeIns; + + if (pPreSaeIns) + pPreSaeIns->same_mac_ins = pSaeIns; + + if (sae_group_allowed(pSaeIns, pSaeCfg->support_group, group) != MLME_SUCCESS) + goto FAIL; + + if (sae_prepare_commit(pSaeIns) != MLME_SUCCESS) + goto FAIL; + + if (sae_send_auth_commit(pAd, pSaeIns) == FALSE) + goto FAIL; + + SET_COMMITTED_STATE(pSaeIns); + sae_set_retransmit_timer(pSaeIns); + return TRUE; +FAIL: + delete_sae_instance(pSaeIns); + return FALSE; +} + + +UCHAR sae_handle_auth( + IN RTMP_ADAPTER *pAd, + IN SAE_CFG *pSaeCfg, + IN VOID *msg, + IN UINT32 msg_len, + IN UCHAR *psk, + IN USHORT auth_seq, + IN USHORT auth_status, + OUT UCHAR** pmk) +{ + USHORT res = MLME_SUCCESS; + FRAME_802_11 *Fr = (PFRAME_802_11)msg; + SAE_INSTANCE *pSaeIns = search_sae_instance(pSaeCfg, Fr->Hdr.Addr1, Fr->Hdr.Addr2); + UINT8 is_token_req = FALSE; + UCHAR *token = NULL; + UINT32 token_len = 0; + UCHAR data[SHA256_DIGEST_SIZE + 2]; + UINT32 data_len = 0; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("==>%s(): receive seq #%d with status code %d, instance %p, own mac addr = %02x:%02x:%02x:%02x:%02x:%02x, peer mac addr = %02x:%02x:%02x:%02x:%02x:%02x\n", + __func__, auth_seq, auth_status, pSaeIns, PRINT_MAC(Fr->Hdr.Addr1), PRINT_MAC(Fr->Hdr.Addr2))); + + /* Upon receipt of a Com event, the t0 (retransmission) timer shall be cancelled in Committed/Confirmed state */ + /* Upon receipt of a Con event, the t0 (retransmission) timer shall be cancelled in Committed/Confirmed state */ + if (pSaeIns) { + sae_clear_retransmit_timer(pSaeIns); /* ellis */ + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("%s(): state = %d\n", + __func__, pSaeIns->state)); + } + + switch (auth_seq) { + case SAE_COMMIT_SEQ: + if (auth_status != MLME_SUCCESS) { + if (!pSaeIns) + goto unfinished; + + /* 12.4.8.6.3 Upon receipt of a Com event, the protocol instance shall check the Status of the Authentication frame. If the + * Status code is nonzero, the frame shall be silently discarded and a Del event shall be sent to the parent + * process. + */ + /* comments: it's not expected to receive the rejection commit msg in NOTHING/ACCEPTED state */ + if (pSaeIns->state == SAE_NOTHING + || pSaeIns->state == SAE_ACCEPTED) { + delete_sae_instance(pSaeIns); + pSaeIns = NULL; + goto unfinished; + } else if (pSaeIns->state == SAE_CONFIRMED) { + /* 12.4.8.6.5 Upon receipt of a Com event, if the Status is nonzero, the frame shall be silently discarded, the t0 (retransmission) timer set + * If Sync is greater than dot11RSNASAESync, the protocol instance shall send the parent process a Del event and transitions back to Nothing state + */ + if (sae_check_big_sync(pSaeIns)) + goto unfinished; + sae_set_retransmit_timer(pSaeIns); + goto unfinished; + } + + if (auth_status == MLME_ANTI_CLOGGING_TOKEN_REQ) { + /*Check presence of Anti-Clogging Token*/ + /*If Anti-Clogging Token present store the anti-clogging token content and length*/ + is_token_req = TRUE; + res = sae_parse_commit(pSaeCfg, pSaeIns, msg, msg_len, &token, &token_len, is_token_req); + + if (res != MLME_SUCCESS) + break; + + if (token && (token_len > 0)) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s:AntiClogging Request token found,token_len = %d\n", __func__, token_len)); + + os_alloc_mem(pAd, &pSaeIns->anti_clogging_token, token_len); + + if (pSaeIns->anti_clogging_token == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s:AntiClogging token allocation fail\n", __func__)); + + sae_set_retransmit_timer(pSaeIns); + goto unfinished; + + } + NdisZeroMemory(pSaeIns->anti_clogging_token, token_len); + pSaeIns->anti_clogging_token_len = token_len; + + + NdisMoveMemory(pSaeIns->anti_clogging_token, (UCHAR *)token, + pSaeIns->anti_clogging_token_len); + + + sae_send_auth_commit(pAd, pSaeIns); + sae_set_retransmit_timer(pSaeIns); + goto unfinished; + + } else { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s:AntiClogging Request token empty fail\n", __func__)); + sae_set_retransmit_timer(pSaeIns); + goto unfinished; + } + + + + } else if (auth_status == MLME_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) { + USHORT sae_group; + USHORT new_sae_group; + UCHAR *pos = &Fr->Octet[6]; + /* 12.4.8.6.4 If the Status code is 77, the protocol instance shall check the finite cyclic group field being rejected.*/ + /* Check Finite Cyclic Group */ + NdisMoveMemory(&sae_group, pos, 2); /* ellis bigendian */ + sae_group = cpu2le16(sae_group); + + /* If the rejected group does not match the last offered group the protocol instance shall silently discard the message and set the t0 (retransmission) timer */ + if (sae_group != pSaeIns->group) { + sae_set_retransmit_timer(pSaeIns); + goto unfinished; + } else { + /* If the rejected group matches the last offered group, + * the protocol instance shall choose a different group and generate the PWE and the secret + * values according to 12.4.5.2; it then generates and transmits a new Commit Message to the peer, + * zeros Sync, sets the t0 (retransmission) timer, and remains in Committed state. + */ + new_sae_group = pSaeCfg->support_group[++pSaeIns->support_group_idx]; + + /*If there are no other groups to choose, + the protocol instance shall send a Del event to the parent process and transitions back to Nothing state. */ + if ((new_sae_group != 0) + && (sae_group_allowed(pSaeIns, pSaeCfg->support_group, new_sae_group) != MLME_SUCCESS) + && (sae_prepare_commit(pSaeIns) != MLME_SUCCESS)) { + delete_sae_instance(pSaeIns); + pSaeIns= NULL; + goto unfinished; + } + + sae_send_auth_commit(pAd, pSaeIns); + sae_set_retransmit_timer(pSaeIns); + goto unfinished; + } + } else { + /* 12.4.8.6.4 If the Status is some other nonzero value, the frame shall be silently discarded and the t0 (retransmission) timer shall be set. + * 12.4.8.6.5 Upon receipt of a Com event, the t0 (retransmission) timer shall be canceled. If the Status is nonzero, + * the frame shall be silently discarded, the t0 (retransmission) timer set, and the protocol instance shall remain in the Confirmed state + */ + sae_set_retransmit_timer(pSaeIns); + goto unfinished; + } + } + + if (!pSaeIns + || pSaeIns->state == SAE_ACCEPTED) { + /* 12.4.8.6, the parent process checks the value of Open first. + * If Open is not greater than dot11RSNASAEAntiCloggingThreshold or Anti-Clogging Token exists and is correct, + * the parent process shall create a protocol instance. + * comment: But, parsing anti-clogging token needs group info, so always create instance first + */ + SAE_INSTANCE *pPreSaeIns = pSaeIns; + pSaeIns = create_sae_instance(pAd, pSaeCfg, Fr->Hdr.Addr1, Fr->Hdr.Addr2, Fr->Hdr.Addr3, psk); + + if (!pSaeIns) + res = MLME_UNSPECIFY_FAIL; + + pSaeIns->same_mac_ins = pPreSaeIns; + + if (pPreSaeIns) + pPreSaeIns->same_mac_ins = pSaeIns; + } + + res = sae_parse_commit(pSaeCfg, pSaeIns, msg, msg_len, &token, &token_len, is_token_req); + + if (res == MLME_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) { + /* 12.4.8.6.3(NOTHING) the frame shall be processed by first checking the finite cyclic group field to see if the requested group is supported. + * If not, BadGrp shall be set and the protocol instance shall construct and transmit a an Authentication frame with Status code UNSUPPORTED_FINITE_CYCLIC_GROUP + * indicating rejection with the finite cyclic group field set to the rejected group, and shall send the parent process a Del event + */ + if (pSaeIns->state == SAE_NOTHING) { + delete_sae_instance(pSaeIns); + pSaeIns = NULL; + } + /* 12.4.8.6.4(COMMITTED) If the Status is zero, the finite cyclic group field is checked. If the group is not supported, BadGrp shall be set and the value of Sync shall be checked. + * -If Sync is greater than dot11RSNASAESync, the protocol instance shall send a Del event to the parent process and transitions back to Nothing state. + * -If Sync is not greater than dot11RSNASAESync, Sync shall be incremented, a Commit Message with Status code equal to 77 indicating rejection, + * and the Algorithm identifier set to the rejected algorithm, shall be sent to the peer, + * the t0 (retransmission) timer shall be set and the protocol instance shall remain in Committed state + */ + if (pSaeIns->state == SAE_COMMITTED && sae_check_big_sync(pSaeIns)) + goto unfinished; + + if (pSaeIns->state == SAE_COMMITTED) + sae_set_retransmit_timer(pSaeIns); + + /* 12.4.8.6.5(CONFIRMED) the protocol instance shall verify that the finite cyclic group is the same as the previously received Commit frame. + * If not, the frame shall be silently discarded + * If so, the protocol instance shall increment Sync, increment Sc, and transmit its Commit and Confirm (with the new Sc value) messages. + * It then shall set the t0 (retransmission) timer. + */ + if (pSaeIns->state == SAE_CONFIRMED) { + sae_set_retransmit_timer(pSaeIns); + goto unfinished; + } + } else if (res == SAE_SILENTLY_DISCARDED) { + sae_set_retransmit_timer(pSaeIns); + goto unfinished; + } else if (res != MLME_SUCCESS) { + if (pSaeIns->state == SAE_NOTHING) { + delete_sae_instance(pSaeIns); + pSaeIns = NULL; + } + break; + } + + if (is_token_req) { + /* 12.4.8.6.4 The protocol instance shall check the Status code of the Authentication frame. + * If the Status code is 76, a new Commit Message shall be constructed with the Anti-Clogging Token from the received + * Authentication frame, and the commit-scalar and COMMIT-ELEMENT previously sent + */ + /* The new Commit Message shall be transmitted to the peer, + *Sync shall be zeroed, and the t0 (retransmission) timer shall be set + */ + pSaeIns->sync = 0; + } + + if (token && sae_check_token(pSaeIns, token, token_len) == FALSE) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): check token fail with peer mac %02x:%02x:%02x:%02x:%02x:%02x\n", + __func__, PRINT_MAC(pSaeIns->peer_mac))); + delete_sae_instance(pSaeIns); + pSaeIns = NULL; + res = MLME_UNSPECIFY_FAIL; + break; + } + + if (!token && sae_using_anti_clogging(pSaeCfg)) { + sae_build_token_req(pAd, pSaeIns, data, &data_len); + res = MLME_ANTI_CLOGGING_TOKEN_REQ; + break; + } + + res = sae_sm_step(pAd, pSaeIns, auth_seq); + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_INFO, + ("%s(): SAE_COMMIT_SEQ, res(sae_sm_step) = %d\n", + __func__, res)); + break; + + case SAE_CONFIRM_SEQ: + if (!pSaeIns || pSaeIns->state == SAE_NOTHING) + goto unfinished; + + /* 12.4.8.6.5 Rejection frames received in Confirmed state shall be silently discarded */ + /* Comment: It is not clear in spec about how to handle confirm message with error status. */ + if (auth_status != MLME_SUCCESS) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): receive error status auth confirm msg, so delete the instance\n", __func__)); + delete_sae_instance(pSaeIns); + pSaeIns = NULL; + goto unfinished; + } + if (pSaeIns->state == SAE_CONFIRMED || pSaeIns->state == SAE_ACCEPTED) + res = sae_parse_confirm(pSaeIns, msg, msg_len); + + /* Comment: It is not clear in spec about how to handle if the confirm be verified fail. */ + if (res != MLME_SUCCESS) { + if (pSaeIns->state == SAE_ACCEPTED) { + /* 12.4.8.6.6(ACCEPTED) Upon receipt of a Con event, the Sync counter shall be checked */ + /* the value of send-confirm shall be checked. If the value is not greater than Rc or is equal to 2^16 ¡V 1, + * the received frame shall be silently discarded. Otherwise, the Confirm portion of the frame shall be checked according to 12.4.5.6. + * If the verification fails, the received frame shall be silently discarded + */ + sae_check_big_sync(pSaeIns); + goto unfinished; + } + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): verify confirm fail, remove instance\n", __func__)); + delete_sae_instance(pSaeIns); + pSaeIns = NULL; + break; + } + + res = sae_sm_step(pAd, pSaeIns, auth_seq); + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("%s(): SAE_CONFIRM_SEQ, res(sae_sm_step) = %d\n", + __func__, res)); + break; + + default: + if (pSaeIns) { + delete_sae_instance(pSaeIns); + pSaeIns = NULL; + } + + res = MLME_SEQ_NR_OUT_OF_SEQUENCE; + break; + } + + if (res != MLME_SUCCESS + && res != SAE_SILENTLY_DISCARDED) + sae_send_auth(pAd, Fr->Hdr.Addr1, Fr->Hdr.Addr2, Fr->Hdr.Addr3, AUTH_MODE_SAE, auth_seq, res, data, data_len); + + if (pSaeIns && pSaeIns->state == SAE_ACCEPTED) { + sae_dump_time(&pSaeIns->sae_cost_time); + SAE_LOG_TIME_DUMP(); + ecc_point_dump_time(); + *pmk = pSaeIns->pmk; + return TRUE; + } +unfinished: + *pmk = NULL; + if (!pSaeIns) + return FALSE; + else + return TRUE; + +} + + +USHORT sae_sm_step( + IN RTMP_ADAPTER *pAd, + IN SAE_INSTANCE *pSaeIns, + IN USHORT auth_seq) +{ +#define F(a, b) (a << 2 | b) + USHORT res = MLME_SUCCESS; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + switch (F(pSaeIns->state, auth_seq)) { + case F(SAE_NOTHING, SAE_COMMIT_SEQ): + /* 12.4.8.6.3 If validation of the received + * Commit Message fails, the protocol instance shall send a Del event to the parent process; otherwise, it shall + * construct and transmit a Commit Message (see 12.4.5.3) followed by a Confirm Message (see 12.4.5.5). The + * Sync counter shall be set to zero and the t0 (retransmission) timer shall be set. The protocol instance + * transitions to Confirmed state. + */ + res = sae_prepare_commit(pSaeIns); + + if (res != MLME_SUCCESS) + return res; + + if (sae_send_auth_commit(pAd, pSaeIns) == FALSE) + return SAE_SILENTLY_DISCARDED; + + res = sae_process_commit(pSaeIns); + + if (res != MLME_SUCCESS) + return res; + + if (sae_send_auth_confirm(pAd, pSaeIns) == FALSE) + return SAE_SILENTLY_DISCARDED; + SET_CONFIRMED_STATE(pSaeIns); + pSaeIns->sync = 0; + sae_set_retransmit_timer(pSaeIns); + break; + + case F(SAE_COMMITTED, SAE_COMMIT_SEQ): + /* 12.4.8.6.4 If the received element and scalar differ from the element and + * scalar offered, the received Commit Message shall be processed according to 12.4.5.4, the Sc + * counter shall be incremented (thereby setting its value to one), the protocol instance shall then + * construct a Confirm Message, transmit it to the peer, and set the t0 (retransmission) timer. It shall + * then transition to Confirmed state. + */ + res = sae_process_commit(pSaeIns); + if (res != MLME_SUCCESS) + return res; + if (sae_send_auth_confirm(pAd, pSaeIns) == FALSE) + return SAE_SILENTLY_DISCARDED; + SET_CONFIRMED_STATE(pSaeIns); + pSaeIns->sync = 0; + sae_set_retransmit_timer(pSaeIns); + break; + + case F(SAE_COMMITTED, SAE_CONFIRM_SEQ): + /* 12.4.8.6.4 Upon receipt of a Con event, If Sync is not greater than + * dot11RSNASAESync, the protocol instance shall increment Sync, transmit the last Commit Message sent to + * the peer, and set the t0 (retransmission) timer. + * comments: In COMMITTED state, it's still awaiting for peer commit msg + */ + if (sae_send_auth_commit(pAd, pSaeIns) == FALSE) + return SAE_SILENTLY_DISCARDED; + sae_set_retransmit_timer(pSaeIns); + break; + + case F(SAE_CONFIRMED, SAE_COMMIT_SEQ): + /* 12.4.8.6.5 the protocol instance shall verify that the finite cyclic group is the same as the previously received Commit + * frame. If not, the frame shall be silently discarded. If so, the protocol instance shall increment Sync, + * increment Sc, and transmit its Commit and Confirm (with the new Sc value) messages. + * It then shall set the t0 (retransmission) timer. + */ + if (sae_check_big_sync(pSaeIns)) + return MLME_SUCCESS; + if (pSaeIns->need_recalculate_key) { + res = sae_process_commit(pSaeIns); + if (res != MLME_SUCCESS) + return res; + pSaeIns->need_recalculate_key = FALSE; + } + + if (sae_send_auth_commit(pAd, pSaeIns) == FALSE) + return SAE_SILENTLY_DISCARDED; + if (sae_send_auth_confirm(pAd, pSaeIns) == FALSE) + return SAE_SILENTLY_DISCARDED; + sae_set_retransmit_timer(pSaeIns); + break; + + case F(SAE_CONFIRMED, SAE_CONFIRM_SEQ): + /* 12.4.8.6.5 If processing is successful and the Confirm Message has been verified, + * the Rc variable shall be set to the send-confirm portion of the frame, Sc shall be set to the value 2^16 ¡V 1, the + * t1 (key expiry) timer shall be set, and the protocol instance shall transition to Accepted state + */ + pSaeIns->last_peer_sc = pSaeIns->peer_send_confirm; + pSaeIns->send_confirm = SAE_MAX_SEND_CONFIRM; + + /* If another protocol instance exists in the database indexed by the same peer identity as the protocol + * instance that sent the Auth event, the other protocol instance shall be destroyed. + */ + if (pSaeIns->same_mac_ins) { + delete_sae_instance(pSaeIns->same_mac_ins); + pSaeIns->same_mac_ins = NULL; + } + + SET_ACCEPTED_STATE(pSaeIns); + /* ellis todo: t1 (key expiry) timer shall be set, and the protocol instance shall transition to Accepted state */ + /* auth done */ + break; + + case F(SAE_ACCEPTED, SAE_CONFIRM_SEQ): + /* 12.4.8.6.6 Upon receipt of a Con event, the Sync counter shall be checked */ + if (sae_check_big_sync(pSaeIns)) + return MLME_SUCCESS; + + /* 12.4.8.6.6 If the verification succeeds, the Rc variable + * shall be set to the send-confirm portion of the frame, the Sync shall be incremented and a new Confirm + * Message shall be constructed (with Sc set to 216 ¡V 1) and sent to the peer + */ + pSaeIns->sync++; + pSaeIns->last_peer_sc = pSaeIns->peer_send_confirm; + if (sae_send_auth_confirm(pAd, pSaeIns) == FALSE) + return SAE_SILENTLY_DISCARDED; + break; + + default: + break; + } + + return res; +} + +/* if this api return TRUE, the instance will be removed, the caller should directly return and not access the instance */ +UCHAR sae_check_big_sync( + IN SAE_INSTANCE *pSaeIns) +{ + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + if (pSaeIns->sync > DOT11RSNASAESYNC) { + delete_sae_instance(pSaeIns); + return TRUE; + } + + pSaeIns->sync++; + + return FALSE; +} + +UCHAR sae_get_pmk_cache( + IN SAE_CFG *pSaeCfg, + IN UCHAR *own_mac, + IN UCHAR *peer_mac, + OUT UCHAR *pmkid, + OUT UCHAR *pmk) +{ + /* PMKID = L((commit-scalar + peer-commit-scalar) mod r, 0, 128) */ + SAE_BN *tmp = NULL; + UINT32 len = LEN_PMKID; + SAE_INSTANCE *pSaeIns = search_sae_instance(pSaeCfg, own_mac, peer_mac); + + if (pSaeIns == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("%s(): pSaeIns not found\n", __func__)); + return FALSE; + } + + if (pSaeIns->state != SAE_ACCEPTED + || !pSaeIns->own_commit_scalar + || !pSaeIns->peer_commit_scalar) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): get pmkid fail\n", __func__)); + return FALSE; + } + + if (pmkid) { + SAE_BN_INIT(&tmp); + + SAE_BN_MOD_ADD_QUICK(pSaeIns->own_commit_scalar, pSaeIns->peer_commit_scalar, pSaeIns->order, &tmp); + SAE_BN_BI2BIN_WITH_PAD(tmp, pmkid, &len, LEN_PMKID); + + SAE_BN_FREE(&tmp); + } + + if (pmk && pSaeIns->pmk) + NdisMoveMemory(pmk, pSaeIns->pmk, LEN_PMK); + else if (!pSaeIns->pmk) + return FALSE; + + return TRUE; +} + +static VOID sae_renew_token_key( + IN SAE_CFG * pSaeCfg) +{ +#define TOKEN_REKEY_INTERVAL 100000 /* unit: jiffies*/ + ULONG cur_time; + UINT32 i; + + NdisGetSystemUpTime(&cur_time); + + if (cur_time > (pSaeCfg->last_token_key_time + TOKEN_REKEY_INTERVAL) && + (cur_time - TOKEN_REKEY_INTERVAL) > pSaeCfg->last_token_key_time) { + pSaeCfg->last_token_key_time = cur_time; + for (i = 0; i < SAE_TOKEN_KEY_LEN; i++) + pSaeCfg->token_key[i] = RandomByte(pSaeCfg->pAd); + } +} + +UCHAR sae_build_token_req( + IN RTMP_ADAPTER * pAd, + IN SAE_INSTANCE * pSaeIns, + OUT UCHAR *token, + OUT UINT32 *token_len) +{ + SAE_CFG *sae_cfg = pSaeIns->pParentSaeCfg; + + NdisMoveMemory(token, &pSaeIns->group, 2); + sae_renew_token_key(sae_cfg); + RT_HMAC_SHA256(sae_cfg->token_key, SAE_TOKEN_KEY_LEN, pSaeIns->peer_mac, MAC_ADDR_LEN, token, SHA256_DIGEST_SIZE); + *token_len = SHA256_DIGEST_SIZE + 2; + + return TRUE; +} + + +UCHAR sae_check_token( + IN SAE_INSTANCE * pSaeIns, + IN UCHAR *peer_token, + IN UINT32 peer_token_len) +{ + SAE_CFG *sae_cfg = pSaeIns->pParentSaeCfg; + UCHAR token[SHA256_DIGEST_SIZE]; + + if (peer_token_len != SHA256_DIGEST_SIZE) + return FALSE; + + RT_HMAC_SHA256(sae_cfg->token_key, SAE_TOKEN_KEY_LEN, pSaeIns->peer_mac, MAC_ADDR_LEN, token, SHA256_DIGEST_SIZE); + + if (RTMPEqualMemory(token, peer_token, SHA256_DIGEST_SIZE)) + return TRUE; + + return FALSE; + +} + + +VOID sae_parse_commit_token_req( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR **pos, + IN UCHAR *end, + IN UCHAR **token, + IN UINT32 *token_len) +{ + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); +/*George:As per spec in Anticlogging request frame only group and anticlogging token expected in the commit frame*/ + if ((end - *pos) > 0) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("%s:add anti clogging token\n", __func__)); + + if (token) + *token = *pos; + + if (token_len) + *token_len = (UINT32)(end - *pos); + + *pos += *token_len; + } else { + if (token) + *token = NULL; + + if (token_len) + *token_len = 0; + } +} + +USHORT sae_parse_commit( + IN SAE_CFG *pSaeCfg, + IN SAE_INSTANCE *pSaeIns, + IN UCHAR *msg, + IN UINT32 msg_len, + IN UCHAR **token, + IN UINT32 *token_len, + IN UCHAR is_token_req) +{ + USHORT sae_group; + USHORT res; + FRAME_802_11 *Fr = (PFRAME_802_11)msg; + UCHAR *pos = &Fr->Octet[6]; + UCHAR *end = msg + msg_len; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + /* Check Finite Cyclic Group */ + NdisMoveMemory(&sae_group, pos, 2); /* ellis bigendian */ + sae_group = cpu2le16(sae_group); + res = sae_group_allowed(pSaeIns, pSaeCfg->support_group, sae_group); + + if (res != MLME_SUCCESS) + return res; + + pos = pos + 2; + + if (is_token_req == TRUE) { + /* process the rejection with anti-clogging */ + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s:Parsing AntiClogging Request token\n", __func__)); + + sae_parse_commit_token_req(pSaeIns, &pos, end, token, token_len); + return MLME_SUCCESS; + } + + /* Optional Anti-Clogging Token */ + sae_parse_commit_token(pSaeIns, &pos, end, token, token_len); + sae_record_time_begin(&pSaeIns->sae_cost_time.parse_commit_scalar_time); + /* commit-scalar */ + res = sae_parse_commit_scalar(pSaeIns, &pos, end); + + if (res != MLME_SUCCESS) + return res; + + sae_record_time_end("parse_commit_scalar_time", &pSaeIns->sae_cost_time.parse_commit_scalar_time); + /* commit-element */ + res = sae_parse_commit_element(pSaeIns, pos, end); + + if (res != MLME_SUCCESS) + return res; + + /* 12.4.8.6.4 the protocol instance checks the peer-commit-scalar and PEER-COMMIT-ELEMENT + * from the message. If they match those sent as part of the protocol instance¡¦s own Commit Message, + * the frame shall be silently discarded (because it is evidence of a reflection attack) + */ + if (pSaeIns->group_op) + return pSaeIns->group_op->sae_reflection_check(pSaeIns); + else + return MLME_UNSPECIFY_FAIL; + +} + +VOID sae_parse_commit_token( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR **pos, + IN UCHAR *end, + IN UCHAR **token, + IN UINT32 *token_len) +{ + UINT32 non_token_len = (is_sae_group_ecc(pSaeIns->group) ? 3 : 2) * pSaeIns->prime_len; /* ellis */ + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + if (*pos + non_token_len < end) { + if (token) + *token = *pos; + + if (token_len) + *token_len = (UINT32)(end - *pos) - non_token_len; + + *pos += *token_len; + } else { + if (token) + *token = NULL; + + if (token_len) + *token_len = 0; + } +} + + +USHORT sae_parse_commit_scalar( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR **pos, + IN UCHAR *end) +{ + SAE_BN *peer_scalar = NULL; + SAE_INSTANCE *pPreSaeIns = pSaeIns->same_mac_ins; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + if (*pos + pSaeIns->prime_len > end) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): not enough data for scalar\n", __func__)); + return MLME_UNSPECIFY_FAIL; + } + + hex_dump_with_lvl("peer scalar:", (char *)*pos, pSaeIns->prime_len, SAE_DEBUG_LEVEL); + SAE_BN_BIN2BI(*pos, pSaeIns->prime_len, &peer_scalar); + + /* + * IEEE Std 802.11-2016, 12.4.8.6.1: If there is a protocol instance for + * the peer and it is in Authenticated state, the new Commit Message + * shall be dropped if the peer-scalar is identical to the one used in + * the existing protocol instance. + */ + + if (pPreSaeIns + && (pPreSaeIns->state == SAE_ACCEPTED) + && (pPreSaeIns->peer_commit_scalar) + && !SAE_BN_UCMP(peer_scalar, pPreSaeIns->peer_commit_scalar)) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): do not accept re-use of previous peer-commit-scalar\n", __func__)); + SAE_BN_FREE(&peer_scalar); + return MLME_UNSPECIFY_FAIL; + } + + if (pSaeIns->state == SAE_CONFIRMED + && (pSaeIns->peer_commit_scalar) + && SAE_BN_UCMP(peer_scalar, pSaeIns->peer_commit_scalar)) + pSaeIns->need_recalculate_key = TRUE; + + /* If the scalar value is greater than zero (0) and less than the order, r, of the negotiated group, scalar validation succeeds */ + /* 0 < scalar < r */ + if (SAE_BN_IS_ZERO(peer_scalar) + || (SAE_BN_UCMP(peer_scalar, pSaeIns->order) >= 0)) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): Invalid peer scalar\n", __func__)); + SAE_BN_FREE(&peer_scalar); + return MLME_UNSPECIFY_FAIL; + } + + SAE_BN_FREE(&pSaeIns->peer_commit_scalar); + pSaeIns->peer_commit_scalar = peer_scalar; + *pos += pSaeIns->prime_len; + return MLME_SUCCESS; +} + +USHORT sae_parse_commit_element( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR *pos, + IN UCHAR *end) +{ + USHORT res = MLME_UNSPECIFY_FAIL; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + sae_record_time_begin(&pSaeIns->sae_cost_time.parse_commit_element_time); + + if (pSaeIns->group_op) + res = pSaeIns->group_op->sae_parse_commit_element(pSaeIns, pos, end); + + sae_record_time_end("parse_commit_element_time", &pSaeIns->sae_cost_time.parse_commit_element_time); + return res; +} + + + + +USHORT sae_prepare_commit( + IN SAE_INSTANCE *pSaeIns) +{ + USHORT res; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + sae_record_time_begin(&pSaeIns->sae_cost_time.derive_pwe_time); + + if (pSaeIns->group_op) + res = pSaeIns->group_op->sae_derive_pwe(pSaeIns); + else + return MLME_UNSPECIFY_FAIL; + + sae_record_time_end("derive_pwe_time", &pSaeIns->sae_cost_time.derive_pwe_time); + + if (res != MLME_SUCCESS) + return res; + + return sae_derive_commit(pSaeIns); +} + + +USHORT sae_derive_commit( + IN SAE_INSTANCE *pSaeIns) +{ + SAE_BN *mask = NULL; + USHORT res = MLME_SUCCESS; + UINT32 counter = 0; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + sae_record_time_begin(&pSaeIns->sae_cost_time.derive_commit_scalar_time); + + + POOL_COUNTER_CHECK_BEGIN(sae_expected_cnt[0]); + + do { + counter++; + + if (counter > 100) { + res = MLME_UNSPECIFY_FAIL; + goto end; + } + + SAE_BN_FREE(&pSaeIns->sae_rand); + pSaeIns->sae_rand = sae_gen_rand(pSaeIns); + SAE_BN_FREE(&mask); + mask = sae_gen_rand(pSaeIns); + + if (pSaeIns->own_commit_scalar == NULL) { + SAE_BN_INIT(&pSaeIns->own_commit_scalar); + + if (pSaeIns->own_commit_scalar == NULL) { + res = MLME_UNSPECIFY_FAIL; + goto end; + } + } + + /* commit-scalar = (rand + mask) modulo r */ + SAE_BN_MOD_ADD(pSaeIns->sae_rand, mask, pSaeIns->order, &pSaeIns->own_commit_scalar); + } while (SAE_BN_IS_ZERO(pSaeIns->own_commit_scalar) + /*|| SAE_BN_IS_ONE(pSaeIns->own_commit_scalar)*/); + + sae_record_time_end("derive_commit_scalar_time", &pSaeIns->sae_cost_time.derive_commit_scalar_time); + sae_record_time_begin(&pSaeIns->sae_cost_time.derive_commit_element_time); + + if (pSaeIns->group_info == NULL + || pSaeIns->group_op == NULL + || pSaeIns->group_op->sae_derive_commit_element(pSaeIns, mask) == FALSE) + res = MLME_UNSPECIFY_FAIL; + + sae_record_time_end("derive_commit_element_time", &pSaeIns->sae_cost_time.derive_commit_element_time); +end: + SAE_BN_FREE(&mask); + POOL_COUNTER_CHECK_END(sae_expected_cnt[0]); + return res; +} + + +USHORT sae_process_commit( + IN SAE_INSTANCE *pSaeIns) +{ + UCHAR *k = NULL; + USHORT res = MLME_SUCCESS; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + sae_record_time_begin(&pSaeIns->sae_cost_time.derive_k_time); + + os_alloc_mem(NULL, (UCHAR **)&k, SAE_MAX_PRIME_LEN); + + if (pSaeIns->group_op + && (pSaeIns->group_op->sae_derive_k(pSaeIns, k) == TRUE)) { + sae_record_time_end("derive_k_time", &pSaeIns->sae_cost_time.derive_k_time); + sae_record_time_begin(&pSaeIns->sae_cost_time.derive_pmk_time); + + if (sae_derive_key(pSaeIns, k) == TRUE) + res = MLME_SUCCESS; + else + res = MLME_UNSPECIFY_FAIL; + + sae_record_time_end("derive_pmk_time", &pSaeIns->sae_cost_time.derive_pmk_time); + } else + res = MLME_UNSPECIFY_FAIL; + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("%s() <==, res = %d\n", __func__, res)); + + os_free_mem(NULL, k); + return res; +} + + +UCHAR sae_derive_key( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR *k) +{ + UCHAR null_key[SAE_KEYSEED_KEY_LEN]; + UCHAR keyseed[SHA256_DIGEST_SIZE]; + UCHAR *val = NULL; + UINT32 val_len = SAE_MAX_PRIME_LEN; + UCHAR keys[SAE_KCK_LEN + LEN_PMK]; + SAE_BN *tmp = NULL; + UCHAR res = TRUE; + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + /* keyseed = H(<0>32, k) */ + NdisZeroMemory(null_key, SAE_KEYSEED_KEY_LEN); + RT_HMAC_SHA256(null_key, SAE_KEYSEED_KEY_LEN, k, + pSaeIns->prime_len, keyseed, SHA256_DIGEST_SIZE); + + hex_dump_with_lvl("keyseed:", (char *)keyseed, SHA256_DIGEST_SIZE, SAE_DEBUG_LEVEL); + + /* KCK || PMK = KDF-512(keyseed, "SAE KCK and PMK", + * (commit-scalar + peer-commit-scalar) modulo r) + */ + + os_alloc_mem(NULL, (UCHAR **)&val, SAE_MAX_PRIME_LEN); + POOL_COUNTER_CHECK_BEGIN(sae_expected_cnt[1]); + GET_BI_INS_FROM_POOL(tmp); + SAE_BN_INIT(&tmp); + SAE_BN_MOD_ADD(pSaeIns->own_commit_scalar, pSaeIns->peer_commit_scalar, pSaeIns->order, &tmp); + SAE_BN_BI2BIN_WITH_PAD(tmp, val, &val_len, pSaeIns->prime_len); + hex_dump_with_lvl("(commit-scalar + peer-commit-scalar) modulo r:", (char *)val, val_len, SAE_DEBUG_LEVEL); + + if (val_len < pSaeIns->prime_len) { + SAE_BN_FREE(&tmp); + res = FALSE; + goto Free; + } + + KDF(keyseed, sizeof(keyseed), (UINT8 *)"SAE KCK and PMK", 15, val, val_len, keys, sizeof(keys)); /* ellis KDF-512 */ + NdisCopyMemory(pSaeIns->kck, keys, SAE_KCK_LEN); + NdisCopyMemory(pSaeIns->pmk, keys + SAE_KCK_LEN, LEN_PMK); + hex_dump_with_lvl("kck:", (char *)pSaeIns->kck, SAE_KCK_LEN, SAE_DEBUG_LEVEL); + hex_dump_with_lvl("pmk:", (char *)pSaeIns->pmk, LEN_PMK, SAE_DEBUG_LEVEL); +Free: + SAE_BN_RELEASE_BACK_TO_POOL(&tmp); + POOL_COUNTER_CHECK_END(sae_expected_cnt[1]); + os_free_mem(NULL, val); + return res; +} + +VOID sae_send_auth( + IN RTMP_ADAPTER *pAd, + IN UCHAR *own_mac, + IN UCHAR *peer_mac, + IN UCHAR *bssid, + IN USHORT alg, + IN USHORT seq, + IN USHORT status_code, + IN UCHAR *buf, + IN UINT32 buf_len) +{ + HEADER_802_11 AuthHdr; + ULONG FrameLen = 0; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("==> %s(), seq = %d, statuscode = %d, own mac addr = %02x:%02x:%02x:%02x:%02x:%02x, peer mac addr = %02x:%02x:%02x:%02x:%02x:%02x\n", + __func__, seq, status_code, PRINT_MAC(own_mac), PRINT_MAC(peer_mac))); + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + MgtMacHeaderInitExt(pAd, &AuthHdr, SUBTYPE_AUTH, 0, peer_mac, + own_mac, + bssid); + + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &AuthHdr, + 2, &alg, + 2, &seq, + 2, &status_code, + buf_len, buf, + END_OF_ARGS); + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(NULL, pOutBuffer); +} + +UCHAR sae_send_auth_commit( + IN RTMP_ADAPTER *pAd, + IN SAE_INSTANCE *pSaeIns) +{ + UCHAR *buf = NULL; + UCHAR *pos; + UCHAR *end; + UINT32 len; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("==> %s():\n", __func__)); + os_alloc_mem(pAd, &buf, SAE_COMMIT_MAX_LEN); + + if (buf == NULL) + return FALSE; + + pos = buf; + end = buf + SAE_COMMIT_MAX_LEN; + NdisZeroMemory(pos, SAE_COMMIT_MAX_LEN); + NdisMoveMemory(pos, &pSaeIns->group, 2); + pos += 2; + + if (pSaeIns->anti_clogging_token) { + NdisMoveMemory(pos, pSaeIns->anti_clogging_token, + pSaeIns->anti_clogging_token_len); + pos += pSaeIns->anti_clogging_token_len; + } + + len = pSaeIns->prime_len; + SAE_BN_BI2BIN_WITH_PAD(pSaeIns->own_commit_scalar, pos, &len, pSaeIns->prime_len); + pos += len; + + if (is_sae_group_ecc(pSaeIns->group)) { + BIG_INTEGER_EC_POINT *element = (BIG_INTEGER_EC_POINT *) pSaeIns->own_commit_element; + len = pSaeIns->prime_len; + SAE_BN_BI2BIN_WITH_PAD(element->x, pos, &len, pSaeIns->prime_len); + pos += len; + len = pSaeIns->prime_len; + SAE_BN_BI2BIN_WITH_PAD(element->y, pos, &len, pSaeIns->prime_len); + pos += len; + } else { + SAE_BN *element = (SAE_BN *) pSaeIns->own_commit_element; + len = pSaeIns->prime_len; + SAE_BN_BI2BIN_WITH_PAD(element, pos, &len, pSaeIns->prime_len); + pos += len; + } + + sae_send_auth(pAd, pSaeIns->own_mac, pSaeIns->peer_mac, pSaeIns->bssid, + AUTH_MODE_SAE, SAE_COMMIT_SEQ, MLME_SUCCESS, buf, pos - buf); + os_free_mem(NULL, buf); + return TRUE; +} + + +UCHAR sae_send_auth_confirm( + IN RTMP_ADAPTER *pAd, + IN SAE_INSTANCE *pSaeIns) +{ + UCHAR *buf = NULL; + UCHAR *pos; + UCHAR *end; + UCHAR confirm[SHA256_DIGEST_SIZE]; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + os_alloc_mem(pAd, &buf, SAE_CONFIRM_MAX_LEN); + pos = buf; + end = buf + SAE_CONFIRM_MAX_LEN; + + /* 12.4.8.6.4 the Sc counter shall be incremented (thereby setting its value to one), the protocol instance shall then + * construct a Confirm Message, transmit it to the peer + * 12.4.8.6.5 the protocol instance shall increment Sync, + * increment Sc, and transmit its Commit and Confirm (with the new Sc value) messages + * => increment send_confirm first and send comfirm msg with new sc value + */ + if (pSaeIns->send_confirm != SAE_MAX_SEND_CONFIRM) + pSaeIns->send_confirm++; + + NdisMoveMemory(pos, &pSaeIns->send_confirm, 2); + pos += 2; + + if (pSaeIns->group_op) + pSaeIns->group_op->sae_cn_confirm(pSaeIns, TRUE, confirm); + + NdisMoveMemory(pos, confirm, SHA256_DIGEST_SIZE); + hex_dump_with_lvl("confirm(pos):", (char *)pos, SHA256_DIGEST_SIZE, SAE_DEBUG_LEVEL); + pos += SHA256_DIGEST_SIZE; + sae_send_auth(pAd, pSaeIns->own_mac, pSaeIns->peer_mac, pSaeIns->bssid, + AUTH_MODE_SAE, SAE_CONFIRM_SEQ, MLME_SUCCESS, buf, pos - buf); + os_free_mem(NULL, buf); + return TRUE; +} + +USHORT sae_parse_confirm( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR *msg, + IN UINT32 msg_len) +{ + UCHAR peer_confirm[SHA256_DIGEST_SIZE]; + FRAME_802_11 *Fr = (PFRAME_802_11)msg; + UCHAR *pos = &Fr->Octet[6]; + UCHAR *end = msg + msg_len; + USHORT peer_send_confirm; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + /* peer-send-confirm */ + if (end - pos < 2) + return MLME_UNSPECIFY_FAIL; + + NdisMoveMemory(&peer_send_confirm, pos, 2); + pos = pos + 2; + + /* 12.4.8.6.6 Upon receipt of a Con event, the value of send-confirm shall be checked. + * If the value is not greater than Rc or is equal to 2^16 ¡V 1, the received frame shall be silently discarded + */ + if (pSaeIns->state == SAE_ACCEPTED + && (peer_send_confirm <= pSaeIns->last_peer_sc + || peer_send_confirm == SAE_MAX_SEND_CONFIRM)) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_WARN, + ("confirm fail: SAE_SILENTLY_DISCARDED due to peer_send_confirm =%d, ast_peer_sc = %d\n", + peer_send_confirm, pSaeIns->last_peer_sc)); + pSaeIns->peer_send_confirm = peer_send_confirm; + /* return SAE_SILENTLY_DISCARDED; */ + } else + pSaeIns->peer_send_confirm = peer_send_confirm; + + /* send-confirm */ + if (end - pos < SHA256_DIGEST_SIZE) + return MLME_UNSPECIFY_FAIL; + + NdisMoveMemory(peer_confirm, pos, SHA256_DIGEST_SIZE); + return sae_check_confirm(pSaeIns, peer_confirm); +} + + +USHORT sae_check_confirm( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR *peer_confirm) +{ + UCHAR verifier[SHA256_DIGEST_SIZE]; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + if (pSaeIns->peer_commit_element == NULL + || pSaeIns->peer_commit_scalar == NULL + || pSaeIns->own_commit_element == NULL + || pSaeIns->own_commit_scalar == NULL) + return MLME_UNSPECIFY_FAIL; + + if (pSaeIns->group_op) + pSaeIns->group_op->sae_cn_confirm(pSaeIns, FALSE, verifier); + else + return MLME_UNSPECIFY_FAIL; + + if (RTMPEqualMemory(peer_confirm, verifier, SHA256_DIGEST_SIZE)) + return MLME_SUCCESS; + else { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("peer_send_confirm = %d\n", pSaeIns->peer_send_confirm)); + hex_dump_with_lvl("peer_confirm:", (char *)peer_confirm, SHA256_DIGEST_SIZE, SAE_DEBUG_LEVEL2); + hex_dump_with_lvl("verifier:", (char *)verifier, SHA256_DIGEST_SIZE, SAE_DEBUG_LEVEL2); + return MLME_UNSPECIFY_FAIL; + } +} + +SAE_BN *sae_gen_rand( + IN SAE_INSTANCE *pSaeIns) +{ + UINT8 *rand = NULL; + UINT32 i; + SAE_BN *rand_bi = NULL; + UINT32 iter = 0; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + if (!pSaeIns->order) + return NULL; + + os_alloc_mem(NULL, (UCHAR **)&rand, SAE_MAX_PRIME_LEN); + + for (iter = 0; iter < 100; iter++) { + for (i = 0; i < pSaeIns->order_len; i++) + rand[i] = RandomByte(pSaeIns->pParentSaeCfg->pAd); + + hex_dump_with_lvl("rand:", (char *)rand, pSaeIns->order_len, SAE_DEBUG_LEVEL); + SAE_BN_BIN2BI(rand, pSaeIns->order_len, &rand_bi); + + if (SAE_BN_IS_ZERO(rand_bi) + || SAE_BN_IS_ONE(rand_bi) + || SAE_BN_UCMP(rand_bi, pSaeIns->order) >= 0) + continue; + else { + os_free_mem(NULL, rand); + return rand_bi; + } + } + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): gen rand fail\n", __func__)); + SAE_BN_FREE(&rand_bi); + os_free_mem(NULL, rand); + return NULL; +} + + +USHORT sae_group_allowed( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR *allowed_groups, + IN INT32 group) +{ + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s():\n", __func__)); + + if (allowed_groups) { + UINT32 i; + + for (i = 0; allowed_groups[i] > 0; i++) + if (allowed_groups[i] == group) + break; + + if (allowed_groups[i] != group) + return MLME_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; + } + + if (pSaeIns->group != group) { + /* 12.4.8.6.5 the protocol instance shall verify that the finite cyclic group is the same as the previously received Commit frame. + * If not, the frame shall be silently discarded. + */ + if (pSaeIns->state == SAE_CONFIRMED) { + delete_sae_instance(pSaeIns); + return SAE_SILENTLY_DISCARDED; + } + + sae_clear_data(pSaeIns); + + if (is_sae_group_ecc(group)) + pSaeIns->group_op = &ecc_group_op; + else if (is_sae_group_ffc(group)) + pSaeIns->group_op = &ffc_group_op; + else + return MLME_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; + + pSaeIns->group_op->sae_group_init(pSaeIns, group); /* ellis exception */ + + if (pSaeIns->group_info == NULL + || pSaeIns->group_op == NULL) + return MLME_UNSPECIFY_FAIL; + } + + return MLME_SUCCESS; +} + + +UCHAR is_sae_group_ecc( + IN INT32 group) +{ + switch (group) { + case 19: + case 20: + case 21: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + return TRUE; + + default: + return FALSE; + } +} + + +UCHAR is_sae_group_ffc( + IN INT32 group) +{ + switch (group) { + case 1: + case 2: + case 5: + case 14: + case 15: + case 16: + case 17: + case 18: + case 22: + case 23: + case 24: + return TRUE; + + default: + return FALSE; + } +} + +VOID sae_group_init_ecc( + IN SAE_INSTANCE *pSaeIns, + IN INT32 group) +{ + EC_GROUP_INFO *ec_group = NULL; + EC_GROUP_INFO_BI *ec_group_bi = NULL; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + ec_group = get_ecc_group_info(group); + ec_group_bi = get_ecc_group_info_bi(group); + + if (ec_group == NULL + || ec_group_bi == NULL) + return; + pSaeIns->group_info = (VOID *) ec_group; + pSaeIns->group_info_bi = (VOID *) ec_group_bi; + pSaeIns->prime = ec_group_bi->prime; + pSaeIns->prime_len = ec_group->prime_len; + pSaeIns->order = ec_group_bi->order; + pSaeIns->order_len = ec_group->order_len; + pSaeIns->group = group; +} + + +VOID sae_group_init_ffc( + IN SAE_INSTANCE *pSaeIns, + IN INT32 group) +{ + UINT32 i; + DH_GROUP_INFO *dh_group = NULL; + DH_GROUP_INFO_BI *dh_group_bi = NULL; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + for (i = 0; i < DH_GROUP_NUM; i++) { + if (dh_groups[i].group_id == group) { + dh_group = &dh_groups[i]; + dh_group_bi = &dh_groups_bi[i]; + } + } + + if (dh_group == NULL + || dh_group_bi == NULL) + return; + + if (dh_group_bi->is_init == FALSE) { + dh_group_bi->prime = NULL; + dh_group_bi->order = NULL; + dh_group_bi->generator = NULL; + SAE_BN_BIN2BI((UINT8 *)dh_group->prime, + dh_group->prime_len, + &dh_group_bi->prime); + SAE_BN_BIN2BI((UINT8 *)dh_group->order, + dh_group->order_len, + &dh_group_bi->order); + SAE_BN_BIN2BI((UINT8 *)dh_group->generator, + dh_group->generator_len, + &dh_group_bi->generator); + } + + pSaeIns->group_info = (VOID *) dh_group; + pSaeIns->group_info_bi = (VOID *) dh_group_bi; + pSaeIns->prime = dh_group_bi->prime; + pSaeIns->prime_len = dh_group->prime_len; + pSaeIns->order = dh_group_bi->order; + pSaeIns->order_len = dh_group->order_len; + pSaeIns->group = group; +} + + +VOID sae_group_deinit_ecc( + IN SAE_INSTANCE *pSaeIns) +{ + BIG_INTEGER_EC_POINT *own_element = NULL; + BIG_INTEGER_EC_POINT *peer_element = NULL; + BIG_INTEGER_EC_POINT *pwe = NULL; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + own_element = (BIG_INTEGER_EC_POINT *)pSaeIns->own_commit_element; + peer_element = (BIG_INTEGER_EC_POINT *)pSaeIns->peer_commit_element; + pwe = (BIG_INTEGER_EC_POINT *)pSaeIns->pwe; + + if (own_element) + ecc_point_free(&own_element); + + if (peer_element) + ecc_point_free(&peer_element); + + if (pwe) + ecc_point_free(&pwe); +} + + +VOID sae_group_deinit_ffc( + IN SAE_INSTANCE *pSaeIns) +{ + SAE_BN *own_element = NULL; + SAE_BN *peer_element = NULL; + SAE_BN *pwe = NULL; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + own_element = (SAE_BN *)pSaeIns->own_commit_element; + peer_element = (SAE_BN *)pSaeIns->peer_commit_element; + pwe = (SAE_BN *)pSaeIns->pwe; + + if (own_element) + SAE_BN_FREE(&own_element); + + pSaeIns->own_commit_element = NULL; + + if (peer_element) + SAE_BN_FREE(&peer_element); + + pSaeIns->peer_commit_element = NULL; + + if (pwe) + SAE_BN_FREE(&pwe); + + pSaeIns->pwe = NULL; +} + + + +VOID sae_cn_confirm_ecc( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR is_send, /* otherwise, is verfication */ + OUT UCHAR *confirm) +{ + UCHAR own_element_bin[2 * SAE_MAX_ECC_PRIME_LEN]; + UCHAR peer_element_bin[2 * SAE_MAX_ECC_PRIME_LEN]; + UINT32 prime_len; + BIG_INTEGER_EC_POINT *own_element = (BIG_INTEGER_EC_POINT *)pSaeIns->own_commit_element; /* ellis */ + BIG_INTEGER_EC_POINT *peer_element = (BIG_INTEGER_EC_POINT *)pSaeIns->peer_commit_element; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + prime_len = pSaeIns->prime_len; /* ellis */ + SAE_BN_BI2BIN_WITH_PAD(own_element->x, own_element_bin, + &prime_len, pSaeIns->prime_len); + prime_len = pSaeIns->prime_len; + SAE_BN_BI2BIN_WITH_PAD(own_element->y, own_element_bin + pSaeIns->prime_len, + &prime_len, pSaeIns->prime_len); + prime_len = pSaeIns->prime_len; + SAE_BN_BI2BIN_WITH_PAD(peer_element->x, peer_element_bin, + &prime_len, pSaeIns->prime_len); + prime_len = pSaeIns->prime_len; + SAE_BN_BI2BIN_WITH_PAD(peer_element->y, peer_element_bin + pSaeIns->prime_len, + &prime_len, pSaeIns->prime_len); + + if (is_send) + sae_cn_confirm_cmm(pSaeIns, pSaeIns->own_commit_scalar, + pSaeIns->peer_commit_scalar, + own_element_bin, peer_element_bin, + 2 * pSaeIns->prime_len, + pSaeIns->send_confirm, + confirm); + else + sae_cn_confirm_cmm(pSaeIns, pSaeIns->peer_commit_scalar, + pSaeIns->own_commit_scalar, + peer_element_bin, own_element_bin, + 2 * pSaeIns->prime_len, + pSaeIns->peer_send_confirm, + confirm); +} + + + +VOID sae_cn_confirm_ffc( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR is_send, /* otherwise, is verfication */ + OUT UCHAR *confirm) +{ + UCHAR *own_element_bin = NULL; + UCHAR *peer_element_bin = NULL; + UINT32 prime_len; + SAE_BN *own_element = (SAE_BN *)pSaeIns->own_commit_element; + SAE_BN *peer_element = (SAE_BN *)pSaeIns->peer_commit_element; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()is_send = %d\n", __func__, is_send)); + os_alloc_mem(NULL, (UCHAR **)&own_element_bin, SAE_MAX_PRIME_LEN); + + if (own_element_bin == NULL) + return; + + os_alloc_mem(NULL, (UCHAR **)&peer_element_bin, SAE_MAX_PRIME_LEN); + + if (peer_element_bin == NULL) { + os_free_mem(NULL, own_element_bin); + return; + } + + prime_len = pSaeIns->prime_len; /* ellis */ + SAE_BN_BI2BIN_WITH_PAD(own_element, own_element_bin, + &prime_len, pSaeIns->prime_len); + prime_len = pSaeIns->prime_len; /* ellis */ + SAE_BN_BI2BIN_WITH_PAD(peer_element, peer_element_bin, + &prime_len, pSaeIns->prime_len); + + if (is_send) + sae_cn_confirm_cmm(pSaeIns, pSaeIns->own_commit_scalar, + pSaeIns->peer_commit_scalar, + own_element_bin, peer_element_bin, + pSaeIns->prime_len, + pSaeIns->send_confirm, + confirm); + else + sae_cn_confirm_cmm(pSaeIns, pSaeIns->peer_commit_scalar, + pSaeIns->own_commit_scalar, + peer_element_bin, own_element_bin, + pSaeIns->prime_len, + pSaeIns->peer_send_confirm, + confirm); + + os_free_mem(NULL, own_element_bin); + os_free_mem(NULL, peer_element_bin); +} + +VOID sae_cn_confirm_cmm( + IN SAE_INSTANCE *pSaeIns, + IN SAE_BN *scalar1, + IN SAE_BN *scalar2, + IN UCHAR *element_bin1, + IN UCHAR *element_bin2, + IN UINT32 element_len, + IN USHORT send_confirm, + OUT UCHAR *confirm) +{ + UCHAR *msg; + UINT32 msg_len = sizeof(send_confirm) + 2 * element_len + 2 * pSaeIns->prime_len; + UINT32 offset = 0; + UINT32 prime_len; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s(), send_confirm = %d\n", __func__, send_confirm)); + os_alloc_mem(NULL, &msg, msg_len); + + if (msg == NULL) + return; + + /* + * CN(key, X, Y, Z, ¡K) = HMAC-SHA256(key, D2OS(X) || D2OS(Y) || D2OS(Z) || ¡K) + * where D2OS() represents the data to octet string conversion functions in 12.4.7.2. + * confirm = CN(KCK, send-confirm, commit-scalar, COMMIT-ELEMENT, + * peer-commit-scalar, PEER-COMMIT-ELEMENT) + * verifier = CN(KCK, peer-send-confirm, peer-commit-scalar, + * PEER-COMMIT-ELEMENT, commit-scalar, COMMIT-ELEMENT) + */ + NdisMoveMemory(msg, &send_confirm, sizeof(send_confirm)); + offset += sizeof(send_confirm); + prime_len = pSaeIns->prime_len; + SAE_BN_BI2BIN_WITH_PAD(scalar1, msg + offset, + &prime_len, pSaeIns->prime_len); + offset += pSaeIns->prime_len; + NdisMoveMemory(msg + offset, element_bin1, element_len); + offset += element_len; + prime_len = pSaeIns->prime_len; + SAE_BN_BI2BIN_WITH_PAD(scalar2, msg + offset, + &prime_len, pSaeIns->prime_len); + offset += pSaeIns->prime_len; + NdisMoveMemory(msg + offset, element_bin2, element_len); + offset += element_len; + + hex_dump_with_lvl("element_bin1:", (char *)element_bin1, element_len, SAE_DEBUG_LEVEL); + hex_dump_with_lvl("element_bin2:", (char *)element_bin2, element_len, SAE_DEBUG_LEVEL); + RT_HMAC_SHA256(pSaeIns->kck, SAE_KCK_LEN, msg, msg_len, confirm, SHA256_DIGEST_SIZE); + hex_dump_with_lvl("confirm:", (char *)confirm, SHA256_DIGEST_SIZE, SAE_DEBUG_LEVEL); + + os_free_mem(NULL, msg); +} + +USHORT sae_parse_commit_element_ecc( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR *pos, + IN UCHAR *end) +{ + SAE_BN *peer_element_x = NULL; + SAE_BN *peer_element_y = NULL; + BIG_INTEGER_EC_POINT *peer_element = NULL; + EC_GROUP_INFO_BI *ec_group_bi = (EC_GROUP_INFO_BI *) pSaeIns->group_info_bi; + USHORT res = MLME_SUCCESS; + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + if (pos + 2 * pSaeIns->prime_len > end) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): not enough data in commit element\n", __func__)); + + res = MLME_UNSPECIFY_FAIL; + goto fail; + } + POOL_COUNTER_CHECK_BEGIN(sae_expected_cnt[2]); + GET_BI_INS_FROM_POOL(peer_element_x); + GET_BI_INS_FROM_POOL(peer_element_y); + + SAE_BN_BIN2BI(pos, pSaeIns->prime_len, &peer_element_x); + SAE_BN_BIN2BI(pos + pSaeIns->prime_len, pSaeIns->prime_len, &peer_element_y); + hex_dump_with_lvl("peer element x:", (char *)pos, pSaeIns->prime_len, SAE_DEBUG_LEVEL2); + hex_dump_with_lvl("peer element y:", (char *)pos + pSaeIns->prime_len, pSaeIns->prime_len, SAE_DEBUG_LEVEL2); + /* + * For ECC groups, both the x- and ycoordinates + * of the element shall be non-negative integers less than the prime number p, and the two + * coordinates shall produce a valid point on the curve satisfying the group¡¦s curve definition, not being equal + * to the ¡§point at the infinity.¡¨ If either of those conditions does not hold, element validation fails; otherwise, + * element validation succeeds. + */ + ecc_point_init(&peer_element); + SAE_BN_COPY(peer_element_x, &peer_element->x); + SAE_BN_COPY(peer_element_y, &peer_element->y); + SAE_ECC_SET_Z_TO_1(peer_element); + + if (ecc_point_is_on_curve(ec_group_bi, peer_element) == FALSE) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): is not on curve\n", __func__)); + ecc_point_free(&peer_element); + res = MLME_UNSPECIFY_FAIL; + goto fail; + } + + pSaeIns->peer_commit_element = peer_element; +fail: + SAE_BN_RELEASE_BACK_TO_POOL(&peer_element_x); + SAE_BN_RELEASE_BACK_TO_POOL(&peer_element_y); + POOL_COUNTER_CHECK_END(sae_expected_cnt[2]); + return res; +} + +USHORT sae_parse_commit_element_ffc( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR *pos, + IN UCHAR *end) +{ + SAE_BN *scalar_op_res = NULL; + SAE_BN *peer_commit_element = NULL; + USHORT res = MLME_UNSPECIFY_FAIL; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + if (pos + pSaeIns->prime_len > end) + goto fail; + + SAE_BN_BIN2BI(pos, pSaeIns->prime_len, &peer_commit_element); + hex_dump_with_lvl("peer element:", (char *)pos, pSaeIns->prime_len, SAE_DEBUG_LEVEL2); + + if (peer_commit_element == NULL) + goto fail; + + /* + * For FFC groups, the element shall be an integer greater than zero (0) and less than the prime number p, + * and the scalar operation of the element and the order of the group, r, shall equal one (1) modulo the prime number p + */ + /* 0 < element < p */ + if (SAE_BN_IS_ZERO(peer_commit_element) + || SAE_BN_UCMP(peer_commit_element, pSaeIns->prime) >= 0) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): invalid peer element\n", __func__)); + goto fail; + } + + POOL_COUNTER_CHECK_BEGIN(sae_expected_cnt[3]); + /* GET_BI_INS_FROM_POOL(scalar_op_res); */ + + /* scalar-op(r, ELEMENT) = 1 modulo p */ + SAE_BN_MOD_EXP_MONT(peer_commit_element, pSaeIns->order, pSaeIns->prime, &scalar_op_res); + + if (!SAE_BN_IS_ONE(scalar_op_res)) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): invalid peer element (scalar-op)\n", __func__)); + goto fail; + } + + pSaeIns->peer_commit_element = peer_commit_element; + res = MLME_SUCCESS; +fail: + if (res != MLME_SUCCESS) + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): fail\n", __func__)); + + SAE_BN_RELEASE_BACK_TO_POOL(&scalar_op_res); + POOL_COUNTER_CHECK_END(sae_expected_cnt[3]); + + if (res == MLME_UNSPECIFY_FAIL) + SAE_BN_FREE(&peer_commit_element); + + return res; +} + +UCHAR sae_derive_commit_element_ecc( + IN SAE_INSTANCE *pSaeIns, + IN SAE_BN *mask) +{ + BIG_INTEGER_EC_POINT *pwe = (BIG_INTEGER_EC_POINT *)pSaeIns->pwe; + BIG_INTEGER_EC_POINT *commit_element = NULL; + EC_GROUP_INFO_BI *ec_group_bi = (EC_GROUP_INFO_BI *)pSaeIns->group_info_bi; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */ + if (pwe == NULL || mask == NULL) + return FALSE; + + ECC_POINT_MUL(pwe, mask, ec_group_bi, &commit_element); + + SAE_ECC_3D_to_2D(ec_group_bi, commit_element); + + if (commit_element == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): ECC_POINT_MUL fail\n", __func__)); + return FALSE; + } + + if (!ecc_point_is_on_curve(ec_group_bi, commit_element)) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, ("ecc_point_mul_dblandadd fail!!!!!!\n")); + return FALSE; + } + + ecc_point_inverse(commit_element, ec_group_bi->prime, &commit_element); + + if (commit_element == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): inverse fail\n", __func__)); + return FALSE; + } + + pSaeIns->own_commit_element = (VOID *) commit_element; + return TRUE; +} + +UCHAR sae_derive_commit_element_ffc( + IN SAE_INSTANCE *pSaeIns, + IN SAE_BN *mask) +{ + SAE_BN *commit_element = NULL; + SAE_BN *tmp = NULL; + SAE_BN *pwe = (SAE_BN *) pSaeIns->pwe; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */ + if (pwe == NULL || mask == NULL) + return FALSE; + + POOL_COUNTER_CHECK_BEGIN(sae_expected_cnt[4]); + /* GET_BI_INS_FROM_POOL(tmp); */ + + SAE_BN_INIT(&tmp); + SAE_BN_MOD_EXP_MONT(pwe, mask, pSaeIns->prime, &tmp); + /* SAE_BN_MOD_EXP_MONT(pwe, mask, pSaeIns->prime, &commit_element); */ + SAE_BN_MOD_MUL_INV(tmp, pSaeIns->prime, &commit_element); + /* SAE_BN_MOD_MUL_INV(commit_element, pSaeIns->prime, &tmp); */ + SAE_BN_FREE(&tmp); + + if (commit_element == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): inverse fail\n", __func__)); + return FALSE; + } + + pSaeIns->own_commit_element = (VOID *) commit_element; + SAE_BN_RELEASE_BACK_TO_POOL(&tmp); + POOL_COUNTER_CHECK_END(sae_expected_cnt[4]); + return TRUE; +} + +USHORT sae_derive_pwe_ecc( + IN SAE_INSTANCE *pSaeIns) +{ + UCHAR counter = 0; + /*UCHAR k = 50;*/ + UCHAR addrs[2 * MAC_ADDR_LEN]; + BIG_INTEGER_EC_POINT *res = NULL; + UCHAR base[LEN_PSK + 1]; + UCHAR msg[LEN_PSK + 2]; /* sizeof(base)+sizeof(counter) */ + UINT32 base_len = strlen(pSaeIns->psk); + UINT32 msg_len; + UCHAR pwd_seed[SHA256_DIGEST_SIZE]; + UCHAR pwd_value[SAE_MAX_ECC_PRIME_LEN]; + EC_GROUP_INFO *ec_group; + EC_GROUP_INFO_BI *ec_group_bi; + SAE_BN *x = NULL; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + /* Get larger address first */ + if (RTMPCompareMemory(pSaeIns->own_mac, pSaeIns->peer_mac, MAC_ADDR_LEN) == 1) { + COPY_MAC_ADDR(addrs, pSaeIns->own_mac); + COPY_MAC_ADDR(addrs + MAC_ADDR_LEN, pSaeIns->peer_mac); + } else { + COPY_MAC_ADDR(addrs, pSaeIns->peer_mac); + COPY_MAC_ADDR(addrs + MAC_ADDR_LEN, pSaeIns->own_mac); + } + + NdisMoveMemory(base, pSaeIns->psk, base_len); + + hex_dump_with_lvl("base:", (char *)base, base_len, SAE_DEBUG_LEVEL2); + ec_group = (EC_GROUP_INFO *)pSaeIns->group_info; + ec_group_bi = (EC_GROUP_INFO_BI *)pSaeIns->group_info_bi; + + for (counter = 1; /*counter <= k ||*/ !res; counter++) { + UCHAR shift_idx; + SAE_BN *y = NULL; + UINT32 i; + UINT8 lsb_pwd_seed; + UINT8 lsb_y; + UCHAR has_y; + + if (counter == 0) { + SAE_BN_FREE(&x); + return MLME_UNSPECIFY_FAIL; + } + + /* pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC), + base || counter) */ + NdisMoveMemory(msg, base, base_len); + NdisMoveMemory(msg + base_len, &counter, sizeof(counter)); + msg_len = base_len + sizeof(counter); + + RT_HMAC_SHA256(addrs, sizeof(addrs), msg, msg_len, pwd_seed, sizeof(pwd_seed)); + lsb_pwd_seed = pwd_seed[SHA256_DIGEST_SIZE - 1] & BIT0; + + hex_dump_with_lvl("pwd_seed:", (char *)pwd_seed, sizeof(pwd_seed), SAE_DEBUG_LEVEL); + /* z = len(p) + pwd-value = KDF-z(pwd-seed, ¡§SAE Hunting and Pecking¡¨, p) */ + KDF(pwd_seed, sizeof(pwd_seed), (UINT8 *)"SAE Hunting and Pecking", 23, + (UINT8 *)ec_group->prime, ec_group->prime_len, + pwd_value, pSaeIns->prime_len); + + hex_dump_with_lvl("pwd_value:", (char *)pwd_value, pSaeIns->prime_len, SAE_DEBUG_LEVEL); + /* pwd-value should be less than prime */ + shift_idx = ec_group->prime_len - (pSaeIns->prime_len); + + if (NdisCmpMemory(pwd_value, ec_group->prime + shift_idx, + pSaeIns->prime_len) == 1) + continue; + + /* x = pwd-value + y^2 = x^3 + ax + b */ + SAE_BN_BIN2BI(pwd_value, pSaeIns->prime_len, &x); + has_y = ecc_point_find_by_x(ec_group_bi, x, &y, (res == NULL)); + + if (has_y == FALSE) + continue; + + if (!res) { + ecc_point_init(&res); + + if (res == NULL) { + SAE_BN_FREE(&x); + SAE_BN_FREE(&y); + return MLME_UNSPECIFY_FAIL; + } + + /* if LSB(pwd-seed) = LSB(y) + * then PWE = (x, y) + * else PWE = (x, p - y) + */ + lsb_y = SAE_BN_IS_ODD(y); + res->x = x; + + if (lsb_pwd_seed == lsb_y) + res->y = y; + else { + res->y = NULL; + SAE_BN_SUB(ec_group_bi->prime, y, &res->y); + SAE_BN_FREE(&y); + } + + SAE_ECC_SET_Z_TO_1(res); + + if (DebugLevel >= DBG_LVL_TRACE) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_OFF, ("pwe->x\n")); + SAE_BN_PRINT(res->x); + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_OFF, ("pwe->y\n")); + SAE_BN_PRINT(res->y); + } + x = NULL; + } else { + SAE_BN_FREE(&y); + + /* base = new-random-number */ + for (i = 0; i < base_len; i++) + base[i] = RandomByte(pSaeIns->pParentSaeCfg->pAd); + } + } + + SAE_BN_FREE(&x); + pSaeIns->pwe = (VOID *)res; + return MLME_SUCCESS; +} + + +USHORT sae_derive_pwe_ffc( + IN SAE_INSTANCE *pSaeIns) +{ + UCHAR counter = 0; + UCHAR found = FALSE; + UCHAR addrs[2 * MAC_ADDR_LEN]; + SAE_BN *pwe = NULL; + SAE_BN *exp = NULL; + UCHAR msg[LEN_PSK + 2]; /* sizeof(base)+sizeof(counter) */ + UINT32 msg_len; + UCHAR pwd_seed[SHA256_DIGEST_SIZE]; + UCHAR *pwd_value = NULL; + SAE_BN *pwd_value_bi = NULL; + SAE_BN *tmp_bi = NULL; + DH_GROUP_INFO *dh_group; + DH_GROUP_INFO_BI *dh_group_bi; + UCHAR tmp[1]; + USHORT res; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + POOL_COUNTER_CHECK_BEGIN(sae_expected_cnt[5]); + /* GET_BI_INS_FROM_POOL(exp); */ + /* GET_BI_INS_FROM_POOL(pwd_value_bi); */ + + /* Get larger address first */ + if (RTMPCompareMemory(pSaeIns->own_mac, pSaeIns->peer_mac, MAC_ADDR_LEN) == 1) { + COPY_MAC_ADDR(addrs, pSaeIns->own_mac); + COPY_MAC_ADDR(addrs + MAC_ADDR_LEN, pSaeIns->peer_mac); + } else { + COPY_MAC_ADDR(addrs, pSaeIns->peer_mac); + COPY_MAC_ADDR(addrs + MAC_ADDR_LEN, pSaeIns->own_mac); + } + + + hex_dump_with_lvl("psk:", (char *)pSaeIns->psk, strlen(pSaeIns->psk), SAE_DEBUG_LEVEL); + dh_group = (DH_GROUP_INFO *)pSaeIns->group_info; + /* dh_group_bi->prime == pSaeIns->prime, dh_group_bi->order == pSaeIns->order */ + dh_group_bi = (DH_GROUP_INFO_BI *)pSaeIns->group_info_bi; + SAE_BN_INIT(&exp); + SAE_BN_INIT(&pwd_value_bi); + SAE_BN_INIT(&pwe); + SAE_BN_INIT(&tmp_bi); + + os_alloc_mem(NULL, (UCHAR **)&pwd_value, SAE_MAX_PRIME_LEN); + + for (counter = 1; counter <= 200; counter++) { + UCHAR shift_idx; + /* pwd-seed = H(MAX(STA-A-MAC, STA-B-MAC) || MIN(STA-A-MAC, STA-B-MAC), + password || counter) */ + NdisMoveMemory(msg, pSaeIns->psk, strlen(pSaeIns->psk)); + hex_dump_with_lvl("msg:", (char *)msg, strlen(pSaeIns->psk), SAE_DEBUG_LEVEL); + NdisMoveMemory(msg + strlen(pSaeIns->psk), &counter, sizeof(counter)); + msg_len = strlen(pSaeIns->psk) + sizeof(counter); + hex_dump_with_lvl("addr:", (char *)addrs, 2 * MAC_ADDR_LEN, SAE_DEBUG_LEVEL); + hex_dump_with_lvl("msg:", (char *)msg, msg_len, SAE_DEBUG_LEVEL); + RT_HMAC_SHA256(addrs, sizeof(addrs), msg, msg_len, pwd_seed, sizeof(pwd_seed)); + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_TRACE, + ("%s(): z = len(p) = %d\n", __func__, SAE_BN_GET_LEN(pSaeIns->prime))); + + hex_dump_with_lvl("pwd_seed:", (char *)pwd_seed, SHA256_DIGEST_SIZE, SAE_DEBUG_LEVEL); + hex_dump_with_lvl("prime:", (char *)dh_group->prime, dh_group->prime_len, SAE_DEBUG_LEVEL); + /* z = len(p) + pwd-value = KDF-z(pwd-seed, ¡§SAE Hunting and Pecking¡¨, p) */ + KDF(pwd_seed, sizeof(pwd_seed), (UINT8 *)"SAE Hunting and Pecking", 23, + (UINT8 *)dh_group->prime, dh_group->prime_len, + pwd_value, pSaeIns->prime_len); + hex_dump_with_lvl("pwd_value:", (char *)pwd_value, pSaeIns->prime_len, SAE_DEBUG_LEVEL); + /* pwd-value should be less than prime */ + shift_idx = dh_group->prime_len - pSaeIns->prime_len; + + if (NdisCmpMemory(pwd_value, dh_group->prime + shift_idx, + dh_group->prime_len) == 1) + continue; + + /* PWE = pwd-value^(p-1)/r modulo p */ + if (dh_group->safe_prime) { + /* + * r = (p-1)/2 => (p-1)/r = 2 + */ + tmp[0] = 2; + SAE_BN_BIN2BI(tmp, sizeof(tmp), &exp); + } else { + /* GET_BI_INS_FROM_POOL(tmp_bi); */ + tmp[0] = 1; + SAE_BN_BIN2BI(tmp, sizeof(tmp), &exp); + SAE_BN_SUB(dh_group_bi->prime, exp, &tmp_bi); /* ellis: SAE_BN_SUB(A, B, A) need to be fix */ + SAE_BN_MOD(tmp_bi, dh_group_bi->order, &exp); + } + + SAE_BN_BIN2BI(pwd_value, dh_group->prime_len, &pwd_value_bi); + SAE_BN_MOD_EXP_MONT(pwd_value_bi, exp, dh_group_bi->prime, &pwe); + + /* if (PWE > 1) => found */ + if (!SAE_BN_IS_ZERO(pwe) && !SAE_BN_IS_ONE(pwe)) { + found = TRUE; + break; + } + } + + if (found) { + pSaeIns->pwe = (VOID *) pwe; + res = MLME_SUCCESS; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_INFO, + ("%s(): Success to derive PWE\n", __func__)); + } else { + SAE_BN_FREE(&pwe); + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): Failed to derive PWE\n", __func__)); + res = MLME_UNSPECIFY_FAIL; + } + os_free_mem(NULL, pwd_value); + SAE_BN_RELEASE_BACK_TO_POOL(&exp); + SAE_BN_RELEASE_BACK_TO_POOL(&pwd_value_bi); + SAE_BN_RELEASE_BACK_TO_POOL(&tmp_bi); + POOL_COUNTER_CHECK_END(sae_expected_cnt[5]); + return res; +} + + + +UCHAR sae_derive_k_ecc( + IN SAE_INSTANCE *pSaeIns, + OUT UCHAR *k) +{ + BIG_INTEGER_EC_POINT *K = NULL; + BIG_INTEGER_EC_POINT *pwe = (BIG_INTEGER_EC_POINT *) pSaeIns->pwe; + BIG_INTEGER_EC_POINT *peer_commit_element = + (BIG_INTEGER_EC_POINT *) pSaeIns->peer_commit_element; + EC_GROUP_INFO_BI *ec_group_bi = (EC_GROUP_INFO_BI *)pSaeIns->group_info_bi; + UINT32 len = SAE_MAX_ECC_PRIME_LEN; + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + /* + * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE), + * PEER-COMMIT-ELEMENT))) + */ + ECC_POINT_MUL(pwe, pSaeIns->peer_commit_scalar, ec_group_bi, &K); + ecc_point_add(K, peer_commit_element, ec_group_bi, &K); + ECC_POINT_MUL(K, pSaeIns->sae_rand, ec_group_bi, &K); + + SAE_ECC_3D_to_2D(ec_group_bi, K); + + /* If K is point-at-infinity, reject. */ + if (K == NULL) { + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): K should not be point-at-infinity\n", __func__)); + return FALSE; + } + + /* k = F(K) (= x coordinate) */ + SAE_BN_BI2BIN_WITH_PAD(K->x, k, &len, pSaeIns->prime_len); + hex_dump_with_lvl("k:", (char *)k, len, SAE_DEBUG_LEVEL2); + ecc_point_free(&K); + return TRUE; +} + +UCHAR sae_derive_k_ffc( + IN SAE_INSTANCE *pSaeIns, + OUT UCHAR *k) +{ + SAE_BN *K = NULL; + SAE_BN *tmp = NULL; + SAE_BN *tmp2 = NULL; + SAE_BN *pwe = NULL; + UINT32 len = SAE_MAX_PRIME_LEN; + UCHAR res = TRUE; + + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_LOUD, + ("==> %s()\n", __func__)); + + POOL_COUNTER_CHECK_BEGIN(sae_expected_cnt[6]); + /* GET_BI_INS_FROM_POOL(tmp); */ + /* GET_BI_INS_FROM_POOL(tmp2); */ + /* GET_BI_INS_FROM_POOL(K); */ + + /* + * K = scalar-op(rand, (elem-op(scalar-op(peer-commit-scalar, PWE), + * PEER-COMMIT-ELEMENT))) + * the K should be scalar-op((rand + peer-rand) modulo r, pwe) + */ + pwe = (SAE_BN *) pSaeIns->pwe; + SAE_BN_INIT(&K); + SAE_BN_INIT(&tmp); + SAE_BN_INIT(&tmp2); + SAE_BN_MOD_EXP_MONT(pwe, pSaeIns->peer_commit_scalar, pSaeIns->prime, &tmp); + SAE_BN_MOD_MUL(tmp, (SAE_BN *)pSaeIns->peer_commit_element, pSaeIns->prime, &tmp2); + SAE_BN_MOD_EXP_MONT(tmp2, pSaeIns->sae_rand, pSaeIns->prime, &K); + + /* If K is identity element (one), reject. */ + if (SAE_BN_IS_ONE(K)) { + SAE_BN_FREE(&K); + MTWF_LOG(DBG_CAT_SEC, CATSEC_SAE, DBG_LVL_ERROR, + ("%s(): K should not be one\n", __func__)); + res = FALSE; + goto Free; + } + + /* k = F(K) (= x coordinate) */ + SAE_BN_BI2BIN_WITH_PAD(K, k, &len, pSaeIns->prime_len); + hex_dump_with_lvl("k:", (char *)k, len, SAE_DEBUG_LEVEL); +Free: + SAE_BN_RELEASE_BACK_TO_POOL(&K); + SAE_BN_RELEASE_BACK_TO_POOL(&tmp); + SAE_BN_RELEASE_BACK_TO_POOL(&tmp2); + POOL_COUNTER_CHECK_END(sae_expected_cnt[6]); + return TRUE; +} + +USHORT sae_reflection_check_ecc( + IN SAE_INSTANCE *pSaeIns) +{ + BIG_INTEGER_EC_POINT *own_commit_element = (BIG_INTEGER_EC_POINT *)pSaeIns->own_commit_element; + BIG_INTEGER_EC_POINT *peer_commit_element = (BIG_INTEGER_EC_POINT *)pSaeIns->peer_commit_element; + + if (!pSaeIns->own_commit_scalar + || (SAE_BN_UCMP(pSaeIns->own_commit_scalar, pSaeIns->peer_commit_scalar) != 0) + || !own_commit_element + || (SAE_BN_UCMP(own_commit_element->x, peer_commit_element->x) != 0) + || (SAE_BN_UCMP(own_commit_element->y, peer_commit_element->y) != 0)) + return MLME_SUCCESS; + else + return SAE_SILENTLY_DISCARDED; +} + +USHORT sae_reflection_check_ffc( + IN SAE_INSTANCE *pSaeIns) +{ + if (!pSaeIns->own_commit_scalar + || (SAE_BN_UCMP(pSaeIns->own_commit_scalar, pSaeIns->peer_commit_scalar) != 0) + || !pSaeIns->own_commit_element + || (SAE_BN_UCMP(pSaeIns->own_commit_element, pSaeIns->peer_commit_element) != 0)) + return MLME_SUCCESS; + else + return SAE_SILENTLY_DISCARDED; +} +#endif /* DOT11_SAE_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/scan.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/scan.c new file mode 100644 index 000000000..b72b12e6a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/scan.c @@ -0,0 +1,729 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + +#ifdef SCAN_SUPPORT +static INT scan_ch_restore(RTMP_ADAPTER *pAd, UCHAR OpMode, struct wifi_dev *pwdev) +{ + INT bw, ch; + +#ifdef WH_EZ_SETUP + struct wifi_dev *wdev = pAd->ApCfg.ScanReqwdev; + + if (IS_EZ_SETUP_ENABLED(wdev) && ez_handle_scan_channel_restore(pAd->ApCfg.ScanReqwdev)) { + + } +#endif /* WH_EZ_SETUP */ + + + if (pAd->CommonCfg.BBPCurrentBW != pAd->hw_cfg.bbp_bw) + bbp_set_bw(pAd, pAd->hw_cfg.bbp_bw); + +#ifdef DOT11_VHT_AC + if (pAd->hw_cfg.bbp_bw == BW_80) + ch = pAd->CommonCfg.vht_cent_ch; + else +#endif /* DOT11_VHT_AC */ + if (pAd->hw_cfg.bbp_bw == BW_40) + ch = pAd->CommonCfg.CentralChannel; + else + ch = pAd->CommonCfg.Channel; + + switch(pAd->CommonCfg.BBPCurrentBW) + { + case BW_80: + bw = 80; + break; + case BW_40: + bw = 40; + break; + case BW_10: + bw = 10; + break; + case BW_20: + default: + bw =20; + break; + } + + + ASSERT((ch != 0)); + AsicSwitchChannel(pAd, ch, FALSE); + AsicLockChannel(pAd, ch); + + DBGPRINT(RT_DEBUG_TRACE, ("SYNC - End of SCAN, restore to %dMHz channel %d, Total BSS[%02d]\n", + bw, ch, pAd->ScanTab.BssNr)); + + +#ifdef CONFIG_AP_SUPPORT + if (OpMode == OPMODE_AP) + { +#ifdef APCLI_SUPPORT +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if ((pAd->ApCfg.ApCliAutoConnectRunning == TRUE) +#ifdef AP_PARTIAL_SCAN_SUPPORT + && (pAd->ApCfg.bPartialScanning == FALSE) +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + ) + { + if (!ApCliAutoConnectExec(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR, ("Error in %s\n", __FUNCTION__)); + } + } +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ +#endif /* APCLI_SUPPORT */ + pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; + RTMPResumeMsduTransmission(pAd); + + /* iwpriv set auto channel selection*/ + /* scanned all channels*/ + if (pAd->ApCfg.bAutoChannelAtBootup==TRUE) + { +#ifdef ACS_CTCC_SUPPORT + if (pAd->ApCfg.AutoChannelScoreFlag == FALSE) { +#endif + 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); + } +#ifdef ACS_CTCC_SUPPORT + else { + SelectBestChannel(pAd, pAd->ApCfg.AutoChannelAlg); + pAd->ApCfg.bAutoChannelAtBootup = FALSE; + pAd->ApCfg.AutoChannelScoreFlag = FALSE; + RTMPSendWirelessEvent(pAd, IW_CHANNEL_CHANGE_EVENT_FLAG, 0, 0, 0); + } + } +#endif + if (!((pAd->CommonCfg.Channel > 14) && (pAd->CommonCfg.bIEEE80211H == TRUE) && (pAd->Dot11_H.RDMode != RD_NORMAL_MODE))) + AsicEnableBssSync(pAd, pAd->CommonCfg.BeaconPeriod); + +#ifdef APCLI_SUPPORT +#ifdef WSC_AP_SUPPORT + if (pwdev && (pwdev->wdev_type == WDEV_TYPE_STA) + && (pwdev->func_idx < MAX_APCLI_NUM)) { + WSC_CTRL *pWpsCtrlTemp = &pAd->ApCfg.ApCliTab[pwdev->func_idx].WscControl; + + if ((pWpsCtrlTemp->WscConfMode != WSC_DISABLE) && + (pWpsCtrlTemp->bWscTrigger == TRUE) && + (pWpsCtrlTemp->WscMode == WSC_PBC_MODE)) { + if (pWpsCtrlTemp->WscApCliScanMode == TRIGGER_PARTIAL_SCAN) { + if ((pAd->ScanCtrl.PartialScan.bScanning == FALSE) && + (pAd->ScanCtrl.PartialScan.LastScanChannel == 0)) { + DBGPRINT(RT_DEBUG_TRACE, + ("[%s] %s AP-Client WPS Partial Scan done!!!\n", + __func__, (ch > 14 ? "5G" : "2G"))); + + { + if (!pWpsCtrlTemp->WscPBCTimerRunning) { + RTMPSetTimer(&pWpsCtrlTemp->WscPBCTimer, 1000); + pWpsCtrlTemp->WscPBCTimerRunning = TRUE; + } + } + } + } else { + } + } + } +#endif /* WSC_AP_SUPPORT */ +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + + return TRUE; +} + + + +static INT scan_active(RTMP_ADAPTER *pAd, UCHAR OpMode, UCHAR ScanType) +{ + UCHAR *frm_buf = NULL; + HEADER_802_11 Hdr80211; + ULONG FrameLen = 0; + UCHAR SsidLen = 0; + + + if (MlmeAllocateMemory(pAd, &frm_buf) != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s():allocate memory fail\n", __FUNCTION__)); + +#ifdef CONFIG_AP_SUPPORT + if (OpMode == OPMODE_AP) + pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; +#endif /* CONFIG_AP_SUPPORT */ + return FALSE; + } + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (ScanType == SCAN_2040_BSS_COEXIST) + { + DBGPRINT(RT_DEBUG_INFO, ("SYNC - SCAN_2040_BSS_COEXIST !! Prepare to send Probe Request\n")); + } +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + /* There is no need to send broadcast probe request if active scan is in effect.*/ + SsidLen = 0; + 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->ScanCtrl.SsidLen; + + { +#ifdef CONFIG_AP_SUPPORT + /*IF_DEV_CONFIG_OPMODE_ON_AP(pAd) */ + if (OpMode == OPMODE_AP) + { + MgtMacHeaderInitExt(pAd, &Hdr80211, SUBTYPE_PROBE_REQ, 0, BROADCAST_ADDR, + pAd->ApCfg.MBSSID[0].wdev.bssid, + BROADCAST_ADDR); + } +#endif /* CONFIG_AP_SUPPORT */ + + MakeOutgoingFrame(frm_buf, &FrameLen, + sizeof(HEADER_802_11), &Hdr80211, + 1, &SsidIe, + 1, &SsidLen, + SsidLen, pAd->ScanCtrl.Ssid, + 1, &SupRateIe, + 1, &pAd->CommonCfg.SupRateLen, + pAd->CommonCfg.SupRateLen, pAd->CommonCfg.SupRate, + END_OF_ARGS); + + if (pAd->CommonCfg.ExtRateLen) + { + ULONG Tmp; + MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, + 1, &ExtRateIe, + 1, &pAd->CommonCfg.ExtRateLen, + pAd->CommonCfg.ExtRateLen, pAd->CommonCfg.ExtRate, + END_OF_ARGS); + FrameLen += Tmp; + } + } + +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode)) + { + ULONG Tmp; + UCHAR HtLen; +#ifdef RT_BIG_ENDIAN + HT_CAPABILITY_IE HtCapabilityTmp; +#endif + + { + HtLen = sizeof(HT_CAPABILITY_IE); +#ifdef RT_BIG_ENDIAN + NdisMoveMemory(&HtCapabilityTmp, &pAd->CommonCfg.HtCapability, SIZE_HT_CAP_IE); + *(USHORT *)(&HtCapabilityTmp.HtCapInfo) = SWAP16(*(USHORT *)(&HtCapabilityTmp.HtCapInfo)); +#ifdef UNALIGNMENT_SUPPORT + { + EXT_HT_CAP_INFO extHtCapInfo; + + NdisMoveMemory((PUCHAR)(&extHtCapInfo), (PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + *(USHORT *)(&extHtCapInfo) = cpu2le16(*(USHORT *)(&extHtCapInfo)); + NdisMoveMemory((PUCHAR)(&HtCapabilityTmp.ExtHtCapInfo), (PUCHAR)(&extHtCapInfo), sizeof(EXT_HT_CAP_INFO)); + } +#else + *(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo) = cpu2le16(*(USHORT *)(&HtCapabilityTmp.ExtHtCapInfo)); +#endif /* UNALIGNMENT_SUPPORT */ + + MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &HtCapabilityTmp, + END_OF_ARGS); +#else + MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, + 1, &HtCapIe, + 1, &HtLen, + HtLen, &pAd->CommonCfg.HtCapability, + END_OF_ARGS); +#endif /* RT_BIG_ENDIAN */ + } + FrameLen += Tmp; + +#ifdef DOT11N_DRAFT3 + if ((pAd->ScanCtrl.Channel <= 14) && (pAd->CommonCfg.bBssCoexEnable == TRUE)) + { + ULONG Tmp; + HtLen = 1; + MakeOutgoingFrame(frm_buf + FrameLen, &Tmp, + 1, &ExtHtCapIe, + 1, &HtLen, + 1, &pAd->CommonCfg.BSSCoexist2040.word, + END_OF_ARGS); + + FrameLen += Tmp; + } +#endif /* DOT11N_DRAFT3 */ + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(pAd->CommonCfg.PhyMode) && + (pAd->ScanCtrl.Channel > 14)) { + FrameLen += build_vht_ies(pAd, (UCHAR *)(frm_buf + FrameLen), SUBTYPE_PROBE_REQ); + } +#endif /* DOT11_VHT_AC */ + +#ifdef WSC_STA_SUPPORT + if (OpMode == OPMODE_STA) + { + BOOLEAN bHasWscIe = FALSE; + /* + Append WSC information in probe request if WSC state is running + */ + if ((pAd->StaCfg.WscControl.WscEnProbeReqIE) && + (pAd->StaCfg.WscControl.WscConfMode != WSC_DISABLE) && + (pAd->StaCfg.WscControl.bWscTrigger == TRUE)) + bHasWscIe = TRUE; +#ifdef WSC_V2_SUPPORT + else if ((pAd->StaCfg.WscControl.WscEnProbeReqIE) && + (pAd->StaCfg.WscControl.WscV2Info.bEnableWpsV2)) + bHasWscIe = TRUE; +#endif /* WSC_V2_SUPPORT */ + + + if (bHasWscIe) + { + UCHAR *pWscBuf = NULL, WscIeLen = 0; + ULONG WscTmpLen = 0; + + os_alloc_mem(NULL, (UCHAR **)&pWscBuf, 512); + if (pWscBuf != NULL) + { + NdisZeroMemory(pWscBuf, 512); + WscBuildProbeReqIE(pAd, STA_MODE, &pAd->StaCfg.WscControl, pWscBuf, &WscIeLen); + + MakeOutgoingFrame(frm_buf + FrameLen, &WscTmpLen, + WscIeLen, pWscBuf, + END_OF_ARGS); + + FrameLen += WscTmpLen; + os_free_mem(NULL, pWscBuf); + } + else + DBGPRINT(RT_DEBUG_WARN, ("%s:: WscBuf Allocate failed!\n", __FUNCTION__)); + } + } + +#endif /* WSC_STA_SUPPORT */ + + + +#ifdef WH_EZ_SETUP + if (ez_is_triband()) { +#ifdef EZ_NETWORK_MERGE_SUPPORT + ULONG tmp_len; + /* + Insert capability TLV + */ + ez_triband_insert_tlv(pAd, EZ_TAG_CAPABILITY_INFO, + frm_buf + FrameLen, + &tmp_len); + FrameLen += tmp_len; + +#endif + } +#endif + + MiniportMMRequest(pAd, 0, frm_buf, FrameLen); + + + MlmeFreeMemory(pAd, frm_buf); + + return TRUE; +} + +/* + ========================================================================== + Description: + Scan next channel + ========================================================================== + */ + +#if defined(WH_EZ_SETUP) || defined(MAP_SUPPORT) +#ifdef APCLI_SUPPORT +static void FireExtraProbeReq(RTMP_ADAPTER *pAd, UCHAR OpMode, UCHAR ScanType, + struct wifi_dev *wdev, UCHAR *desSsid, UCHAR desSsidLen) +{ + UCHAR backSsid[MAX_LEN_OF_SSID]; + UCHAR backSsidLen = 0; + + NdisZeroMemory(backSsid, MAX_LEN_OF_SSID); + + //1. backup the original MlmeAux + backSsidLen = pAd->ScanCtrl.SsidLen; + NdisCopyMemory(backSsid, pAd->ScanCtrl.Ssid, backSsidLen); + + //2. fill the desried ssid into SM + pAd->ScanCtrl.SsidLen = desSsidLen; + NdisCopyMemory(pAd->ScanCtrl.Ssid, desSsid, desSsidLen); + + //3. scan action + scan_active(pAd, OpMode, ScanType); + + //4. restore to ScanCtrl + pAd->ScanCtrl.SsidLen = backSsidLen; + NdisCopyMemory(pAd->ScanCtrl.Ssid, backSsid, backSsidLen); +} +#endif /* APCLI_SUPPORT */ +#endif + +/* + ========================================================================== + Description: + Scan next channel + ========================================================================== + */ +VOID ScanNextChannel(RTMP_ADAPTER *pAd, UCHAR OpMode, struct wifi_dev *pwdev) +{ + UCHAR ScanType = SCAN_TYPE_MAX; + UINT ScanTimeIn5gChannel = SHORT_CHANNEL_TIME; + BOOLEAN ScanPending = FALSE; + RALINK_TIMER_STRUCT *sc_timer = NULL; + UINT stay_time = 0; +#ifdef APCLI_SUPPORT +#endif +#ifdef WH_EZ_SETUP + CHAR apcli_idx = -1; + MAC_TABLE_ENTRY *pMacEntry = NULL; + struct wifi_dev *wdev = pAd->ApCfg.ScanReqwdev; + APCLI_STRUCT *pApCliTable = NULL; + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if(wdev) { + apcli_idx = wdev->func_idx; + pMacEntry = MacTableLookup(pAd, pAd->ApCfg.ApCliTab[apcli_idx].wdev.bssid); + } +#endif +#endif + if(apcli_idx != -1) + pApCliTable = &pAd->ApCfg.ApCliTab[apcli_idx]; + +#endif + +#ifdef CONFIG_ATE + /* Nothing to do in ATE mode. */ + if (ATE_ON(pAd)) + return; +#endif /* CONFIG_ATE */ + + + +#ifdef CONFIG_AP_SUPPORT + if (OpMode == OPMODE_AP) + ScanType = pAd->ScanCtrl.ScanType; +#endif /* CONFIG_AP_SUPPORT */ + if (ScanType == SCAN_TYPE_MAX) { +#ifdef WH_EZ_SETUP + if(pApCliTable && (IS_EZ_SETUP_ENABLED(&pApCliTable->wdev)) + && (pAd->Mlme.ApSyncMachine.CurrState == AP_SCAN_LISTEN)) + pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; +#endif + DBGPRINT(RT_DEBUG_ERROR, ("%s():Incorrect ScanType!\n", __FUNCTION__)); + return; + } + if ((pAd->ScanCtrl.Channel == 0) || ScanPending) + { + scan_ch_restore(pAd, OpMode, pwdev); +#ifdef NEIGHBORING_AP_STAT + if (!pAd->ApCfg.bPartialScanning) { + RtmpOSWrielessEventSend(pAd->net_dev, + RT_WLAN_EVENT_CUSTOM, + OID_CUST_SCAN_DONE_EVENT, + NULL, + (UCHAR *)&pAd->ScanTab.BssNr, + sizeof(pAd->ScanTab.BssNr)); + DBGPRINT(RT_DEBUG_OFF, ("Send Scan Result of Size:%d\n", pAd->ScanTab.BssNr)); + } +#endif + +#ifdef WH_EZ_SETUP +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if(pMacEntry && pApCliTable && pApCliTable->Valid + && IS_EZ_SETUP_ENABLED(&pApCliTable->wdev)) + { + ApCliRTMPSendNullFrame(pAd,pMacEntry->CurrTxRate, FALSE, pMacEntry, PWR_ACTIVE); + } + if (IS_EZ_SETUP_ENABLED(&pApCliTable->wdev) && wdev->ez_driver_params.ez_scan == TRUE) + { + wdev->ez_driver_params.ez_scan = FALSE; + EZ_DEBUG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("Start Join For wdev-> type = %d wdev = %d\n", wdev->wdev_type,wdev->wdev_idx)); + ApCliIfUp(pAd); + + } + +#ifdef MOBILE_APP_SUPPORT + else if (pApCliTable && IS_EZ_SETUP_ENABLED(&pApCliTable->wdev) ){ + int i=0; + unsigned char bssid[6] = {0}; + + for (i = 0; i < pAd->ScanTab.BssNr; i++) + { + BSS_ENTRY *bss_entry = NULL; + PAPCLI_STRUCT apcli_entry = &pAd->ApCfg.ApCliTab[apcli_idx]; + bss_entry = &pAd->ScanTab.BssEntry[i]; + + + if (bss_entry->non_ez_beacon) + { + continue; + } + if (bss_entry->support_easy_setup == TRUE) + { + continue; + } + if (SSID_EQUAL(apcli_entry->CfgSsid, apcli_entry->CfgSsidLen,bss_entry->Ssid, bss_entry->SsidLen)) + { + + COPY_MAC_ADDR(bssid, bss_entry->Bssid); + } + } + { + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, OID_WH_EZ_MAN_TRIBAND_SCAN_COMPLETE_EVENT, + NULL, bssid, MAC_ADDR_LEN); + } + } +#endif +#endif //APCLI_SUPPORT +#endif //CONFIG_AP_SUPPORT +#endif // WH_EZ_SETUP + + } + else + { + +#ifdef WIFI_REGION32_HIDDEN_SSID_SUPPORT + if (((pAd->ScanCtrl.Channel == 12) || (pAd->ScanCtrl.Channel == 13)) && + ((pAd->CommonCfg.CountryRegion & 0x7f) == REGION_32_BG_BAND)) + CmdIdConfigInternalSetting(pAd, DPD_CONF, DPD_OFF); + else + CmdIdConfigInternalSetting(pAd, DPD_CONF, DPD_ON); +#endif /* WIFI_REGION32_HIDDEN_SSID_SUPPORT */ + + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev) && (wdev && wdev->ez_driver_params.scan_one_channel)) { + EZ_DEBUG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("AP SYNC %s() - Only scan ch.%d and keep original channel setting.\n", + __FUNCTION__, pAd->ScanCtrl.Channel)); + } + else +#endif /* WH_EZ_SETUP */ + { + AsicSwitchChannel(pAd, pAd->ScanCtrl.Channel, TRUE); + AsicLockChannel(pAd, pAd->ScanCtrl.Channel); + } + + /* Check if channel if passive scan under current regulatory domain */ +#ifdef P2P_CHANNEL_LIST_SEPARATE + if ((pAd->ScanCtrl.ScanType == SCAN_P2P)) + { + if (P2P_CHAN_PropertyCheck(pAd, pAd->ScanCtrl.Channel, CHANNEL_PASSIVE_SCAN) == TRUE) + ScanType = SCAN_PASSIVE; + } + else +#endif /* P2P_CHANNEL_LIST_SEPARATE */ + if (CHAN_PropertyCheck(pAd, pAd->ScanCtrl.Channel, CHANNEL_PASSIVE_SCAN) == TRUE) + ScanType = SCAN_PASSIVE; + +#if defined(DPA_T) || defined(WIFI_REGION32_HIDDEN_SSID_SUPPORT) + /* Ch 12~14 is passive scan, No matter DFS and 80211H setting is y or n */ + if ((pAd->ScanCtrl.Channel >= 12) && (pAd->ScanCtrl.Channel <= 14) + && ((pAd->CommonCfg.CountryRegion & 0x7f) == REGION_32_BG_BAND)) + ScanType = SCAN_PASSIVE; +#endif /* DPA_T */ + +#ifdef CONFIG_AP_SUPPORT + if (OpMode == OPMODE_AP) + sc_timer = &pAd->ScanCtrl.APScanTimer; +#endif /* CONFIG_AP_SUPPORT */ + if (!sc_timer) { +#ifdef WH_EZ_SETUP + if((IS_EZ_SETUP_ENABLED(&pAd->ApCfg.ApCliTab[apcli_idx].wdev)) + && (pAd->Mlme.ApSyncMachine.CurrState == AP_SCAN_LISTEN)) + pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; +#endif + DBGPRINT(RT_DEBUG_ERROR, ("%s():ScanTimer not assigned!\n", __FUNCTION__)); + return; + } + + /* We need to shorten active scan time in order for WZC connect issue */ + /* Chnage the channel scan time for CISCO stuff based on its IAPP announcement */ + if (ScanType == FAST_SCAN_ACTIVE) + stay_time = FAST_ACTIVE_SCAN_TIME; + else /* must be SCAN_PASSIVE or SCAN_ACTIVE*/ + { + +#ifdef CONFIG_AP_SUPPORT + if ((OpMode == OPMODE_AP) && (pAd->ApCfg.bAutoChannelAtBootup)) + stay_time = AUTO_CHANNEL_SEL_TIMEOUT; + else +#endif /* CONFIG_AP_SUPPORT */ + if (WMODE_CAP_2G(pAd->CommonCfg.PhyMode) && + WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + { + if (pAd->ScanCtrl.Channel > 14) + stay_time = ScanTimeIn5gChannel; + else + stay_time = MIN_CHANNEL_TIME; +#ifdef WH_EZ_SETUP + if ((IS_EZ_SETUP_ENABLED(wdev)) && ScanType != SCAN_PASSIVE) + stay_time = FAST_ACTIVE_SCAN_TIME; +#endif + + } + else + { +#if defined (EZ_NETWORK_MERGE_SUPPORT) && defined (WH_EZ_SETUP) + if (IS_EZ_SETUP_ENABLED(wdev)) + { + if (ScanType != SCAN_PASSIVE) + stay_time = FAST_ACTIVE_SCAN_TIME; + else + stay_time = MIN_CHANNEL_TIME; + } + else +#endif + stay_time = MAX_CHANNEL_TIME; + } +#ifdef CONFIG_AP_SUPPORT +#endif + } + RTMPSetTimer(sc_timer, stay_time); +#ifdef APCLI_SUPPORT +#endif + + if (SCAN_MODE_ACT(ScanType)) + { +#ifdef APCLI_SUPPORT +#ifdef WH_EZ_SETUP + PAPCLI_STRUCT pApCliEntry = NULL; + UINT index = 0; +#endif +#endif + if (scan_active(pAd, OpMode, ScanType) == FALSE){ +#ifdef WH_EZ_SETUP + if(pApCliTable&&(IS_EZ_SETUP_ENABLED(&pApCliTable->wdev)) + && (pAd->Mlme.ApSyncMachine.CurrState == AP_SCAN_LISTEN)) + pAd->Mlme.ApSyncMachine.CurrState = AP_SYNC_IDLE; +#endif + + return; + } + +#ifdef APCLI_SUPPORT +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev)) { + for(index = 0; index < MAX_APCLI_NUM; index++) + { + pApCliEntry = &pAd->ApCfg.ApCliTab[index]; + if(pApCliEntry->CfgHideSsidLen > 0){ + FireExtraProbeReq(pAd, OpMode, ScanType, wdev, + pApCliEntry->CfgHideSsid, pApCliEntry->CfgHideSsidLen); + } + } + } +#endif +#endif + + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +#ifdef AP_PARTIAL_SCAN_SUPPORT + if (pAd->ApCfg.bPartialScanning == TRUE) + { + /* Enhance Connectivity & for Hidden Ssid Scanning*/ + CHAR backSsid[MAX_LEN_OF_SSID]; + UCHAR desiredSsidLen, backSsidLen; + + desiredSsidLen= pAd->ApCfg.ApCliTab[0].CfgSsidLen; + + if (desiredSsidLen > 0) + { + //printk("=====================>specific the %s scanning\n", pAd->ApCfg.ApCliTab[0].CfgSsid); + /* 1. backup the original ScanCtrl */ + backSsidLen = pAd->ScanCtrl.SsidLen; + NdisCopyMemory(backSsid, pAd->ScanCtrl.Ssid, backSsidLen); + + /* 2. fill the desried ssid into SM */ + pAd->ScanCtrl.SsidLen = desiredSsidLen; + NdisCopyMemory(pAd->ScanCtrl.Ssid, pAd->ApCfg.ApCliTab[0].CfgSsid, desiredSsidLen); + + /* 3. scan action */ + scan_active(pAd, OpMode, ScanType); + + /* 4. restore to ScanCtrl */ + pAd->ScanCtrl.SsidLen = backSsidLen; + NdisCopyMemory(pAd->ScanCtrl.Ssid, backSsid, backSsidLen); + } + } +#endif /* AP_PARTIAL_SCAN_SUPPORT */ +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + } + + /* For SCAN_CISCO_PASSIVE, do nothing and silently wait for beacon or other probe reponse*/ + +#ifdef CONFIG_AP_SUPPORT + if (OpMode == OPMODE_AP) + pAd->Mlme.ApSyncMachine.CurrState = AP_SCAN_LISTEN; +#endif /* CONFIG_AP_SUPPORT */ + } +} + + +BOOLEAN ScanRunning(RTMP_ADAPTER *pAd) +{ + BOOLEAN rv = FALSE; + +#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; +} + +#endif /* SCAN_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/spectrum.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/spectrum.c new file mode 100644 index 000000000..95f63f3d8 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/spectrum.c @@ -0,0 +1,2415 @@ +/**************************************************************************** + * 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_INFO 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_INFO)) + + +/* The regulatory information in Europe */ +DOT11_REGULATORY_INFO 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_INFO)) + + +/* The regulatory information in Japan */ +DOT11_REGULATORY_INFO 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_INFO)) + + +UINT8 GetRegulatoryMaxTxPwr(RTMP_ADAPTER *pAd, UINT8 channel) +{ + ULONG RegulatoryClassLoop, ChIdx; + UINT8 RegulatoryClass; + UINT8 MaxRegulatoryClassNum; + DOT11_REGULATORY_INFO *pRegulatoryClass; + RTMP_STRING *pCountry = (RTMP_STRING *)(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(RTMP_ADAPTER *pAd, HTTRANSMIT_SETTING HTTxMode) +{ + UINT32 Value; + INT Idx; + UINT8 PhyMode; + CHAR CurTxPwr; + UINT8 TxPwrRef = 0; + CHAR DaltaPwr; + ULONG TxPwr[5]; + + +#ifdef SINGLE_SKU + CurTxPwr = pAd->CommonCfg.DefineMaxTxPwr; +#else + CurTxPwr = 19; +#endif /* SINGLE_SKU */ + + /* check Tx Power setting from UI. */ + if (pAd->CommonCfg.TxPowerPercentage > 90) + ; + else if (pAd->CommonCfg.TxPowerPercentage > 60) /* reduce Pwr for 1 dB. */ + CurTxPwr -= 1; + else if (pAd->CommonCfg.TxPowerPercentage > 30) /* reduce Pwr for 3 dB. */ + CurTxPwr -= 3; + else if (pAd->CommonCfg.TxPowerPercentage > 15) /* reduce Pwr for 6 dB. */ + CurTxPwr -= 6; + else if (pAd->CommonCfg.TxPowerPercentage > 9) /* reduce Pwr for 9 dB. */ + CurTxPwr -= 9; + else /* reduce Pwr for 12 dB. */ + CurTxPwr -= 12; + + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + if (pAd->CommonCfg.CentralChannel > 14) + { + TxPwr[0] = pAd->Tx40MPwrCfgABand[0]; + TxPwr[1] = pAd->Tx40MPwrCfgABand[1]; + TxPwr[2] = pAd->Tx40MPwrCfgABand[2]; + TxPwr[3] = pAd->Tx40MPwrCfgABand[3]; + TxPwr[4] = pAd->Tx40MPwrCfgABand[4]; + } + else + { + TxPwr[0] = pAd->Tx40MPwrCfgGBand[0]; + TxPwr[1] = pAd->Tx40MPwrCfgGBand[1]; + TxPwr[2] = pAd->Tx40MPwrCfgGBand[2]; + TxPwr[3] = pAd->Tx40MPwrCfgGBand[3]; + TxPwr[4] = pAd->Tx40MPwrCfgGBand[4]; + } + } + else + { + if (pAd->CommonCfg.Channel > 14) + { + TxPwr[0] = pAd->Tx20MPwrCfgABand[0]; + TxPwr[1] = pAd->Tx20MPwrCfgABand[1]; + TxPwr[2] = pAd->Tx20MPwrCfgABand[2]; + TxPwr[3] = pAd->Tx20MPwrCfgABand[3]; + TxPwr[4] = pAd->Tx20MPwrCfgABand[4]; + } + else + { + TxPwr[0] = pAd->Tx20MPwrCfgGBand[0]; + TxPwr[1] = pAd->Tx20MPwrCfgGBand[1]; + TxPwr[2] = pAd->Tx20MPwrCfgGBand[2]; + TxPwr[3] = pAd->Tx20MPwrCfgGBand[3]; + TxPwr[4] = pAd->Tx20MPwrCfgGBand[4]; + } + } + + + switch(HTTxMode.field.MODE) + { + case MODE_CCK: + case MODE_OFDM: + Value = TxPwr[1]; + TxPwrRef = (Value & 0x00000f00) >> 8; + + break; + +#ifdef DOT11_N_SUPPORT + case MODE_HTMIX: + case MODE_HTGREENFIELD: + if (pAd->CommonCfg.TxStream == 1) + { + Value = TxPwr[2]; + TxPwrRef = (Value & 0x00000f00) >> 8; + } + else if (pAd->CommonCfg.TxStream == 2) + { + Value = TxPwr[3]; + TxPwrRef = (Value & 0x00000f00) >> 8; + } + break; +#endif /* DOT11_N_SUPPORT */ + } + + PhyMode = +#ifdef DOT11_N_SUPPORT + (HTTxMode.field.MODE == MODE_HTGREENFIELD) + ? MODE_HTMIX : +#endif /* DOT11_N_SUPPORT */ + HTTxMode.field.MODE; + + for (Idx = 0; Idx < MAX_TXPWR_TAB_SIZE; Idx++) + { + if ((TxPwrCfg[Idx].Mode == PhyMode) + && (TxPwrCfg[Idx].MCS == HTTxMode.field.MCS)) + { + Value = TxPwr[TxPwrCfg[Idx].req]; + DaltaPwr = TxPwrRef - (CHAR)((Value & TxPwrCfg[Idx].BitMask) + >> TxPwrCfg[Idx].shift); + CurTxPwr -= DaltaPwr; + break; + } + } + + return CurTxPwr; +} + + +NDIS_STATUS MeasureReqTabInit(RTMP_ADAPTER *pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + os_alloc_mem(pAd, (UCHAR **)&(pAd->CommonCfg.pMeasureReqTab), sizeof(MEASURE_REQ_TAB)); + if (pAd->CommonCfg.pMeasureReqTab) { + NdisZeroMemory(pAd->CommonCfg.pMeasureReqTab, sizeof(MEASURE_REQ_TAB)); + + NdisAllocateSpinLock(pAd, &pAd->CommonCfg.MeasureReqTabLock); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pMeasureReqTab.\n", __FUNCTION__)); + Status = NDIS_STATUS_FAILURE; + } + + return Status; +} + + +VOID MeasureReqTabExit(RTMP_ADAPTER *pAd) +{ + if (pAd->CommonCfg.pMeasureReqTab) { + os_free_mem(NULL, pAd->CommonCfg.pMeasureReqTab); + pAd->CommonCfg.pMeasureReqTab = NULL; + + NdisFreeSpinLock(&pAd->CommonCfg.MeasureReqTabLock); + } + return; +} + + +PMEASURE_REQ_ENTRY MeasureReqLookUp(RTMP_ADAPTER *pAd, 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(RTMP_ADAPTER *pAd, 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]; + BOOLEAN Cancelled; + + /* 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); + + RTMPCancelTimer(&pEntry->WaitBCNRepTimer, &Cancelled); + RTMPReleaseTimer(&pEntry->WaitBCNRepTimer, &Cancelled); + RTMPCancelTimer(&pEntry->WaitNRRspTimer, &Cancelled); + RTMPReleaseTimer(&pEntry->WaitNRRspTimer, &Cancelled); + 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(RTMP_ADAPTER *pAd, 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(RTMP_ADAPTER *pAd) +{ + NDIS_STATUS Status = NDIS_STATUS_SUCCESS; + + os_alloc_mem(pAd, (UCHAR **)&(pAd->CommonCfg.pTpcReqTab), sizeof(TPC_REQ_TAB)); + if (pAd->CommonCfg.pTpcReqTab) { + NdisZeroMemory(pAd->CommonCfg.pTpcReqTab, sizeof(TPC_REQ_TAB)); + + NdisAllocateSpinLock(pAd, &pAd->CommonCfg.TpcReqTabLock); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Fail to alloc memory for pAd->CommonCfg.pTpcReqTab.\n", __FUNCTION__)); + Status = NDIS_STATUS_FAILURE; + } + + return Status; +} + + +VOID TpcReqTabExit(RTMP_ADAPTER *pAd) +{ + if (pAd->CommonCfg.pTpcReqTab) { + os_free_mem(NULL, pAd->CommonCfg.pTpcReqTab); + pAd->CommonCfg.pTpcReqTab = NULL; + + NdisFreeSpinLock(&pAd->CommonCfg.TpcReqTabLock); + } + + return; +} + + +static PTPC_REQ_ENTRY TpcReqLookUp(RTMP_ADAPTER *pAd, 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(RTMP_ADAPTER *pAd, 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(RTMP_ADAPTER *pAd, 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(RTMP_ADAPTER *pAd) +{ + /* get current time stamp.*/ + return 0; +} + + +/* + ========================================================================== + Description: + Get Current Transmit Power. + + Parametrs: + + Return : Current Time Stamp. + ========================================================================== + */ +static UINT8 GetCurTxPwr(RTMP_ADAPTER *pAd, UINT8 Wcid) +{ + return 16; /* 16 dBm */ +} + + +/* + ========================================================================== + Description: + Get Current Transmit Power. + + Parametrs: + + Return : Current Time Stamp. + ========================================================================== + */ +VOID InsertChannelRepIE( + IN RTMP_ADAPTER *pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN RTMP_STRING *pCountry, + IN UINT8 RegulatoryClass, + IN UINT8 *ChReptList) +{ + ULONG TempLen; + UINT8 Len; + UINT8 IEId = IE_AP_CHANNEL_REPORT; + PUCHAR pChListPtr = NULL; + UINT8 i,j; + PUCHAR channel_set = NULL; + UCHAR ChannelList[16] ={0}; + UINT8 NumberOfChannels = 0; + UINT8 *pChannelList = NULL; + UCHAR channel_set_num = 0; + UCHAR ch_list_num = 0; + + Len = 1; + + channel_set = get_channelset_by_reg_class(pAd, RegulatoryClass); + channel_set_num = get_channel_set_num(channel_set); + + ch_list_num = get_channel_set_num(ChReptList); + + /* no match channel set. */ + if (channel_set == NULL) + return; + + /* empty channel set. */ + if (channel_set_num == 0) + return; + + if (ch_list_num) { /* assign partial channel list */ + for (i = 0; i < channel_set_num; i++) { + for (j = 0; j < ch_list_num; j++) { + if (ChReptList[j] == channel_set[i]) + ChannelList[NumberOfChannels++] = channel_set[i]; + } + } + + pChannelList = &ChannelList[0]; + } else { + NumberOfChannels = channel_set_num; + pChannelList = channel_set; + } + + Len += NumberOfChannels; + pChListPtr = pChannelList; + + if (Len > 1) + { + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &IEId, + 1, &Len, + 1, &RegulatoryClass, + Len -1, pChListPtr, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + } + return; +} + +/* +* ========================================================================== +* Description: +* Add last beacon report indication request into beacon request +* +* Parametrs: +* +* Return : NAN +* ========================================================================== + */ +VOID InsertBcnReportIndicationReqIE( + IN RTMP_ADAPTER *pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Data +) +{ + ULONG TempLen; + UINT8 Len; + UINT8 IEId = IE_LAST_BCN_REPORT_INDICATION_REQUEST; + + Len = 1; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &IEId, + 1, &Len, + 1, &Data, + END_OF_ARGS); + *pFrameLen = *pFrameLen + TempLen; +} + +/* + ========================================================================== + Description: + Insert Dialog Token into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. Dialog token. + + Return : None. + ========================================================================== + */ +VOID InsertDialogToken( + IN RTMP_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(RTMP_ADAPTER *pAd, UCHAR *frm_buf, ULONG *frm_len) +{ + ULONG TempLen; + UINT8 Len = 0; + UINT8 ElementID = IE_TPC_REQUEST; + + MakeOutgoingFrame(frm_buf, &TempLen, + 1, &ElementID, + 1, &Len, + END_OF_ARGS); + + *frm_len = *frm_len + 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 RTMP_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 RTMP_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 RTMP_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 RTMP_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; + UINT16 leRepetitions; + + InsertActField(pAd, (pOutBuffer + *pFrameLen), pFrameLen, Category, Action); + + /* fill Dialog Token*/ + InsertDialogToken(pAd, (pOutBuffer + *pFrameLen), pFrameLen, MeasureToken); + leRepetitions = cpu2le16(NumOfRepetitions); + + + /* fill Number of repetitions. */ + if (Category == CATEGORY_RM) + { + MakeOutgoingFrame((pOutBuffer+*pFrameLen), &TempLen, + 2, &leRepetitions, + 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 RTMP_ADAPTER *pAd, + IN PUCHAR pDA, + IN UINT8 DialogToken, + IN UINT8 MeasureToken, + IN UINT8 MeasureReqMode, + IN UINT8 MeasureReqType, + IN UINT8 ReportInfoLen, + IN PUINT8 pReportInfo) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + HEADER_802_11 ActHdr; + MEASURE_REPORT_INFO MeasureRepIE; + + /* build action frame header.*/ + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, + pAd->CurrentAddress, + pAd->CurrentAddress); + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory*/ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); + return; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_MRP); + + /* fill Dialog Token*/ + InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); + + /* prepare Measurement IE.*/ + NdisZeroMemory(&MeasureRepIE, sizeof(MEASURE_REPORT_INFO)); + MeasureRepIE.Token = MeasureToken; + MeasureRepIE.ReportMode = MeasureReqMode; + MeasureRepIE.ReportType = MeasureReqType; + InsertMeasureReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, &MeasureRepIE, ReportInfoLen, pReportInfo); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + + +/* + ========================================================================== + Description: + Prepare TPC Request action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueTPCReq( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pDA, + IN UCHAR DialogToken) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + + HEADER_802_11 ActHdr; + + /* build action frame header.*/ + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, + pAd->CurrentAddress, + pAd->CurrentAddress); + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory*/ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); + return; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRQ); + + /* fill Dialog Token*/ + InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); + + /* Insert TPC Request IE.*/ + InsertTpcReqIE(pAd, (pOutBuffer + FrameLen), &FrameLen); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + + +/* + ========================================================================== + Description: + Prepare TPC Report action frame and enqueue it into + management queue waiting for transmition. + + Parametrs: + 1. the destination mac address of the frame. + + Return : None. + ========================================================================== + */ +VOID EnqueueTPCRep( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pDA, + IN UINT8 DialogToken, + IN UINT8 TxPwr, + IN UINT8 LinkMargin) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + + HEADER_802_11 ActHdr; + + /* build action frame header.*/ + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, + pAd->CurrentAddress, + pAd->CurrentAddress); + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory*/ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); + return; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_TPCRP); + + /* fill Dialog Token*/ + InsertDialogToken(pAd, (pOutBuffer + FrameLen), &FrameLen, DialogToken); + + /* Insert TPC Request IE.*/ + InsertTpcReportIE(pAd, (pOutBuffer + FrameLen), &FrameLen, TxPwr, LinkMargin); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} + + +#ifdef WDS_SUPPORT +/* + ========================================================================== + Description: + Insert Channel Switch Announcement IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + 3. channel switch announcement mode. + 4. new selected channel. + 5. channel switch announcement count. + + Return : None. + ========================================================================== + */ +static VOID InsertChSwAnnIE( + IN RTMP_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 RTMP_ADAPTER *pAd, + IN PUCHAR pDA, + IN UINT8 ChSwMode, + IN UINT8 NewCh) +{ + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen; + + HEADER_802_11 ActHdr; + + /* build action frame header.*/ + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pDA, + pAd->CurrentAddress, + pAd->CurrentAddress); + + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); /*Get an unused nonpaged memory*/ + if(NStatus != NDIS_STATUS_SUCCESS) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s() allocate memory failed \n", __FUNCTION__)); + return; + } + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, CATEGORY_SPECTRUM, SPEC_CHANNEL_SWITCH); + + InsertChSwAnnIE(pAd, (pOutBuffer + FrameLen), &FrameLen, ChSwMode, NewCh, 0); + + MiniportMMRequest(pAd, QID_AC_BE, pOutBuffer, FrameLen); + MlmeFreeMemory(pAd, pOutBuffer); + + return; +} +#endif /* WDS_SUPPORT */ + + +static BOOLEAN DfsRequirementCheck(RTMP_ADAPTER *pAd, 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 RTMP_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(RTMP_ADAPTER *pAd, UCHAR Channel, 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 RTMP_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 RTMP_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 RTMP_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 RTMP_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 RTMP_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(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + CH_SW_ANN_INFO ChSwAnnInfo; + PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; + + 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 */ + + + return; +} + + +/* + ========================================================================== + Description: + Measurement Request action frame handler. + + Parametrs: + Elme - MLME message containing the received frame + + Return : None. + ========================================================================== + */ +static VOID PeerMeasureReqAction(RTMP_ADAPTER *pAd, 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(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem) +{ + MEASURE_REPORT_INFO MeasureReportInfo; + PFRAME_802_11 pFr = (PFRAME_802_11)Elem->Msg; + UINT8 DialogToken; + PUINT8 pMeasureReportInfo; + + os_alloc_mem(pAd, (UCHAR **)&pMeasureReportInfo, sizeof(MEASURE_RPI_REPORT)); + 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")); + + 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(RTMP_ADAPTER *pAd, 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->rssi_info, RSSI_IDX_0), + ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_1), + ConvertToRssi(pAd, &Elem->rssi_info, RSSI_IDX_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(RTMP_ADAPTER *pAd, 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(RTMP_ADAPTER *pAd, 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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT wcid = 1; + UINT ArgIdx; + RTMP_STRING *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.*/ + wcid = (UINT8) simple_strtol(thisChar, 0, 16); + break; + + case 2: /* Measurement Request Type.*/ + MeasureReqType = simple_strtol(thisChar, 0, 16); + if (MeasureReqType > 3) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow MeasureReqType(%d)\n", __FUNCTION__, MeasureReqType)); + goto END_OF_MEASURE_REQ; + } + break; + + case 3: /* Measurement channel.*/ + MeasureCh = (UINT8) simple_strtol(thisChar, 0, 16); + break; + } + ArgIdx++; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s::Aid = %d, MeasureReqType=%d MeasureCh=%d\n", + __FUNCTION__, wcid, MeasureReqType, MeasureCh)); + if (!VALID_WCID(wcid)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, wcid)); + goto END_OF_MEASURE_REQ; + } + + MeasureReqMode.word = 0; + MeasureReqMode.field.Enable = 1; + + MeasureReqInsert(pAd, MeasureReqToken); + + /* build action frame header.*/ + MgtMacHeaderInit(pAd, &ActHdr, SUBTYPE_ACTION, 0, pAd->MacTab.Content[wcid].Addr, + pAd->CurrentAddress, + pAd->CurrentAddress); + + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(HEADER_802_11)); + FrameLen = sizeof(HEADER_802_11); + + //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(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT wcid; + + UINT8 TpcReqToken = RandomByte(pAd); + + wcid = (UINT) simple_strtol(arg, 0, 16); + + DBGPRINT(RT_DEBUG_TRACE, ("%s::wcid = %d\n", __FUNCTION__, wcid)); + if (!VALID_WCID(wcid)) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknow sta of Aid(%d)\n", __FUNCTION__, wcid)); + return TRUE; + } + + TpcReqInsert(pAd, TpcReqToken); + + EnqueueTPCReq(pAd, pAd->MacTab.Content[wcid].Addr, TpcReqToken); + + return TRUE; +} + +#ifdef CONFIG_AP_SUPPORT +INT Set_PwrConstraint(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + +typedef struct __PWR_CONSTRAIN_CFG +{ + CHAR Attenuation; + ULONG TxPowerPercentage; +} PWR_CONSTRAIN_CFG; + + PWR_CONSTRAIN_CFG PwrConstrainTab[] = + { + {0, 100}, + {1, 70}, + {4, 50}, + {6, 20}, + {10, 10}, + {13, 5} + }; +#define PWR_CONSTRAION_TAB_SIZE \ + (sizeof(PwrConstrainTab)/sizeof(PWR_CONSTRAIN_CFG)) + + INT Idx; + LONG Value; + CHAR MaxTxPwr; + CHAR CurTxPwr; + CHAR DaltaPwr; + + Value = (UINT) simple_strtol(arg, 0, 10); + MaxTxPwr = GetRegulatoryMaxTxPwr(pAd, pAd->CommonCfg.Channel) - (CHAR)Value; + CurTxPwr = RTMP_GetTxPwr(pAd, pAd->MacTab.Content[0].HTPhyMode); + DaltaPwr = CurTxPwr - MaxTxPwr; + + if (pAd->CommonCfg.TxPowerPercentage > 90) + ; + else if (pAd->CommonCfg.TxPowerPercentage > 60) /* reduce Pwr for 1 dB. */ + DaltaPwr += 1; + else if (pAd->CommonCfg.TxPowerPercentage > 30) /* reduce Pwr for 3 dB. */ + DaltaPwr += 3; + else if (pAd->CommonCfg.TxPowerPercentage > 15) /* reduce Pwr for 6 dB. */ + DaltaPwr += 6; + else if (pAd->CommonCfg.TxPowerPercentage > 9) /* reduce Pwr for 9 dB. */ + DaltaPwr += 9; + else /* reduce Pwr for 12 dB. */ + DaltaPwr += 12; + + DBGPRINT(RT_DEBUG_OFF, ("MaxTxPwr=%d, CurTxPwr=%d, DaltaPwr=%d\n", + MaxTxPwr, CurTxPwr, DaltaPwr)); + + for (Idx = 0; Idx < PWR_CONSTRAION_TAB_SIZE; Idx++) + { + if (DaltaPwr < PwrConstrainTab[Idx].Attenuation) + { + pAd->CommonCfg.PwrConstraint = Value; + pAd->CommonCfg.TxPowerPercentage = + PwrConstrainTab[Idx].TxPowerPercentage; + + break; + } + } + + if (Idx == PWR_CONSTRAION_TAB_SIZE) + { + DBGPRINT(RT_DEBUG_ERROR, \ + ("Power constraint value be in range from 0 to 13dB\n")); + } + + + return TRUE; +} + +#ifdef DOT11K_RRM_SUPPORT +#endif /* DOT11K_RRM_SUPPORT */ + + +static DOT11_REGULATORY_INFO *GetRugClassRegion(RTMP_STRING *pCountryCode, UINT8 RugClass) +{ + DOT11_REGULATORY_INFO *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(RTMP_ADAPTER *pAd, UCHAR *pBuf, ULONG *pBufLen) +{ + INT loop; + ULONG TmpLen; + DOT11_REGULATORY_INFO *pRguClassRegion; + DOT11_CHANNEL_SET *pChList; + + for (loop = 0 ;loop < MAX_NUM_OF_REGULATORY_CLASS; loop++) + { + if (pAd->CommonCfg.RegulatoryClass[loop] == 0) + break; + + pRguClassRegion = GetRugClassRegion( + (RTMP_STRING *)pAd->CommonCfg.CountryCode, + pAd->CommonCfg.RegulatoryClass[loop]); + + pChList = &pRguClassRegion->ChannelSet; + + if (pRguClassRegion == NULL) + return; + + MakeOutgoingFrame(pBuf + *pBufLen, &TmpLen, + 1, &pChList->ChannelList[0], + 1, &pChList->NumberOfChannels, + 1, &pChList->MaxTxPwr, + END_OF_ARGS); + + *pBufLen += TmpLen; + } + + return; +} +#endif /* CONFIG_AP_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/sys_log.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/sys_log.c new file mode 100644 index 000000000..8d598cac9 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/sys_log.c @@ -0,0 +1,282 @@ +/* + +*/ + + +#ifdef SYSTEM_LOG_SUPPORT + +#include "rt_config.h" + + +/* for wireless system event message */ +char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = { + /* system status event */ + "had associated successfully", /* IW_ASSOC_EVENT_FLAG */ + "had disassociated", /* IW_DISASSOC_EVENT_FLAG */ + "had deauthenticated", /* IW_DEAUTH_EVENT_FLAG */ + "had been aged-out and disassociated", /* IW_AGEOUT_EVENT_FLAG */ + "occurred CounterMeasures attack", /* IW_COUNTER_MEASURES_EVENT_FLAG */ + "occurred replay counter different in Key Handshaking", /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */ + "occurred RSNIE different in Key Handshaking", /* IW_RSNIE_DIFF_EVENT_FLAG */ + "occurred MIC different in Key Handshaking", /* IW_MIC_DIFF_EVENT_FLAG */ + "occurred ICV error in RX", /* IW_ICV_ERROR_EVENT_FLAG */ + "occurred MIC error in RX", /* IW_MIC_ERROR_EVENT_FLAG */ + "Group Key Handshaking timeout", /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */ + "Pairwise Key Handshaking timeout", /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */ + "RSN IE sanity check failure", /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */ + "set key done in WPA/WPAPSK", /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */ + "set key done in WPA2/WPA2PSK", /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */ + "connects with our wireless client", /* IW_STA_LINKUP_EVENT_FLAG */ + "disconnects with our wireless client", /* IW_STA_LINKDOWN_EVENT_FLAG */ + "scan completed", /* IW_SCAN_COMPLETED_EVENT_FLAG */ + "scan terminate!! Busy!! Enqueue fail!!", /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */ + "channel switch to ", /* IW_CHANNEL_CHANGE_EVENT_FLAG */ + "wireless mode is not support", /* IW_STA_MODE_EVENT_FLAG */ + "blacklisted in MAC filter list", /* IW_MAC_FILTER_LIST_EVENT_FLAG */ + "Authentication rejected because of challenge failure", /* IW_AUTH_REJECT_CHALLENGE_FAILURE */ + "Scanning", /* IW_SCANNING_EVENT_FLAG */ + "Start a new IBSS", /* IW_START_IBSS_FLAG */ + "Join the IBSS", /* IW_JOIN_IBSS_FLAG */ + "Shared WEP fail", /* IW_SHARED_WEP_FAIL*/ + }; + +#ifdef IDS_SUPPORT +/* for wireless IDS_spoof_attack event message */ +char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = { + "detected conflict SSID", /* IW_CONFLICT_SSID_EVENT_FLAG */ + "detected spoofed association response", /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */ + "detected spoofed reassociation responses", /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */ + "detected spoofed probe response", /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */ + "detected spoofed beacon", /* IW_SPOOF_BEACON_EVENT_FLAG */ + "detected spoofed disassociation", /* IW_SPOOF_DISASSOC_EVENT_FLAG */ + "detected spoofed authentication", /* IW_SPOOF_AUTH_EVENT_FLAG */ + "detected spoofed deauthentication", /* IW_SPOOF_DEAUTH_EVENT_FLAG */ + "detected spoofed unknown management frame", /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */ + "detected replay attack" /* IW_REPLAY_ATTACK_EVENT_FLAG */ + }; + +/* for wireless IDS_flooding_attack event message */ +char const *pWirelessFloodEventText[IW_FLOOD_EVENT_TYPE_NUM] = { + "detected authentication flooding", /* IW_FLOOD_AUTH_EVENT_FLAG */ + "detected association request flooding", /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */ + "detected reassociation request flooding", /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */ + "detected probe request flooding", /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */ + "detected disassociation flooding", /* IW_FLOOD_DISASSOC_EVENT_FLAG */ + "detected deauthentication flooding", /* IW_FLOOD_DEAUTH_EVENT_FLAG */ + "detected 802.1x eap-request flooding" /* IW_FLOOD_EAP_REQ_EVENT_FLAG */ + }; +#endif /* IDS_SUPPORT */ + +#ifdef WSC_INCLUDED +/* for WSC wireless event message */ +char const *pWirelessWscEventText[IW_WSC_EVENT_TYPE_NUM] = { + "PBC Session Overlap", /* IW_WSC_PBC_SESSION_OVERLAP */ + "This WPS Registrar supports PBC", /* IW_WSC_REGISTRAR_SUPPORT_PBC */ + "This WPS Registrar supports PIN", /* IW_WSC_REGISTRAR_SUPPORT_PIN */ + "WPS status success", /* IW_WSC_STATUS_SUCCESS */ + "WPS status fail", /* IW_WSC_STATUS_FAIL */ + "WPS 2 mins time out!", /* IW_WSC_2MINS_TIMEOUT */ + "WPS Send EAPOL_Start!", /* IW_WSC_SEND_EAPOL_START */ + "WPS Send WscStart!", /* IW_WSC_SEND_WSC_START */ + "WPS Send M1!", /* IW_WSC_SEND_M1 */ + "WPS Send M2!", /* IW_WSC_SEND_M2 */ + "WPS Send M3!", /* IW_WSC_SEND_M3 */ + "WPS Send M4!", /* IW_WSC_SEND_M4 */ + "WPS Send M5!", /* IW_WSC_SEND_M5 */ + "WPS Send M6!", /* IW_WSC_SEND_M6 */ + "WPS Send M7!", /* IW_WSC_SEND_M7 */ + "WPS Send M8!", /* IW_WSC_SEND_M8 */ + "WPS Send WscDone!", /* IW_WSC_SEND_DONE */ + "WPS Send WscAck!", /* IW_WSC_SEND_ACK */ + "WPS Send WscNack!", /* IW_WSC_SEND_NACK */ + "WPS Receive WscStart!", /* IW_WSC_RECEIVE_WSC_START */ + "WPS Receive M1!", /* IW_WSC_RECEIVE_M1 */ + "WPS Receive M2!", /* IW_WSC_RECEIVE_M2 */ + "WPS Receive M3!", /* IW_WSC_RECEIVE_M3 */ + "WPS Receive M4!", /* IW_WSC_RECEIVE_M4 */ + "WPS Receive M5!", /* IW_WSC_RECEIVE_M5 */ + "WPS Receive M6!", /* IW_WSC_RECEIVE_M6 */ + "WPS Receive M7!", /* IW_WSC_RECEIVE_M7 */ + "WPS Receive M8!", /* IW_WSC_RECEIVE_M8 */ + "WPS Receive WscDone!", /* IW_WSC_RECEIVE_DONE */ + "WPS Receive WscAck!", /* IW_WSC_RECEIVE_ACK */ + "WPS Receive WscNack!", /* IW_WSC_RECEIVE_NACK */ + "Not only one candidate found" /* IW_WSC_MANY_CANDIDATE */ + }; +#endif /* WSC_INCLUDED */ + + +#ifdef WH_EZ_SETUP +// For whole home coverage - easy setup wireless event - start +char const *pWirelessEasySetupEventText[IW_WH_EZ_EVENT_TYPE_NUM] = { + "WH_EZ - Provider searching", /* IW_WH_EZ_PROVIDER_SEARCHING */ + "WH_EZ - Provider found", /* IW_WH_EZ_PROVIDER_FOUND */ + "WH_EZ - Stop provider searching", /* IW_WH_EZ_PROVIDER_STOP_SEARCHING */ + "WH_EZ - Configured AP searching", /* IW_WH_EZ_CONFIGURED_AP_SEARCHING */ + "WH_EZ - Configured AP found", /* IW_WH_EZ_CONFIGURED_AP_FOUND */ + "WH_EZ - My APCLI connects", /* IW_WH_EZ_MY_APCLI_CONNECTED */ + "WH_EZ - My APCLI disconnects", /* IW_WH_EZ_MY_APCLI_DISCONNECTED */ + "WH_EZ - This client is APCLI", /* IW_WH_EZ_MY_AP_HAS_APCLI */ + "WH_EZ - My AP doesn't has APCLI", /* IW_WH_EZ_MY_AP_DOES_NOT_HAS_APCLI */ + "WH_EZ - Become configured", /* IW_WH_EZ_BECOME_CONFIGURED */ + + }; +/* For whole home coverage - easy setup wireless event - end */ +#endif /* CONFIG_STA_SUPPORT */ + + +/* + ======================================================================== + + Routine Description: + Send log message through wireless event + + Support standard iw_event with IWEVCUSTOM. It is used below. + + iwreq_data.data.flags is used to store event_flag that is defined by user. + iwreq_data.data.length is the length of the event log. + + The format of the event log is composed of the entry's MAC address and + the desired log message (refer to pWirelessEventText). + + ex: 11:22:33:44:55:66 has associated successfully + + p.s. The requirement of Wireless Extension is v15 or newer. + + ======================================================================== +*/ +VOID RtmpDrvSendWirelessEvent( + IN VOID *pAdSrc, + IN USHORT Event_flag, + IN PUCHAR pAddr, + IN UCHAR wdev_idx, + IN CHAR Rssi) +{ + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdSrc; + RTMP_STRING *pBuf = NULL, *pBufPtr = NULL; + USHORT event, type, BufLen; + UCHAR event_table_len = 0; + struct wifi_dev *wdev; + + if (pAd->CommonCfg.bWirelessEvent == FALSE) + return; + + ASSERT(wdev_idx < WDEV_NUM_MAX); + if (wdev_idx >= WDEV_NUM_MAX) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Invalid wdev_idx(%d)\n", __FUNCTION__, wdev_idx)); + return; + } + + wdev = pAd->wdev_list[wdev_idx]; + 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 WH_EZ_SETUP + case IW_WH_EZ_EVENT_FLAG_START: + if (IS_EZ_SETUP_ENABLED(wdev)) + { + event_table_len = IW_WH_EZ_EVENT_TYPE_NUM; + } + break; +#endif /* WH_EZ_SETUP */ + + } + + 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. */ + 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 ((wdev->wdev_type == WDEV_TYPE_AP) && (wdev->func_idx < MAX_MBSSID_NUM(pAd))) + pBufPtr += sprintf(pBufPtr, "(RT2860) BSS(ra%d) ", wdev->func_idx); +#ifdef WH_EZ_SETUP + else if(wdev->wdev_type == WDEV_TYPE_STA) //Rakesh: easy enabled need not be checked + pBufPtr += sprintf(pBufPtr, "BSS(apcli%d) ", wdev->func_idx); +#endif + 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 WH_EZ_SETUP + else if( (type == IW_WH_EZ_EVENT_FLAG_START) && IS_EZ_SETUP_ENABLED(wdev) ) + pBufPtr += sprintf(pBufPtr, "%s", pWirelessEasySetupEventText[event]); +#endif /* WH_EZ_SETUP */ + else + pBufPtr += sprintf(pBufPtr, "%s", "unknown event"); + + pBufPtr[pBufPtr - pBuf] = '\0'; + BufLen = pBufPtr - pBuf; +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(wdev)){ + RtmpOSWrielessEventSend(wdev->if_dev, RT_WLAN_EVENT_CUSTOM, Event_flag, NULL, (PUCHAR)pBuf, BufLen); + } + else +#endif + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, Event_flag, NULL, (PUCHAR)pBuf, BufLen); + /*DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __FUNCTION__, pBuf)); */ + + os_free_mem(NULL, pBuf); + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s : Can't allocate memory for wireless event.\n", __FUNCTION__)); +} + +#endif /* SYSTEM_LOG_SUPPORT */ + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/txpower.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/txpower.c new file mode 100644 index 000000000..52d7f03ff --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/txpower.c @@ -0,0 +1,1948 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + +INT tx_temp_dbg = 0; + +#ifdef RTMP_TEMPERATURE_COMPENSATION + +/* + Lookup table format: + +ArrayIdx: + 0 1 2 10 11 12 13 14 ...... 46 + +PwrCompen: -12 -11 -10 ...... -2 -1 0 1 2 ....... 31 32 +TempRange: -4 3 10 ....... 114 116 + | + \/ + Temperature reference base + + PwrCompensation in unit of 0.5dB + TempRange in temperature sensor value +*/ + +#define LUT_POSITIVE(_band, _idx) pAd->TxPowerCtrl.LookupTable[(_band)][(_idx) + Offset] +#define LUT_NEGATIVE(_band, _idx) pAd->TxPowerCtrl.LookupTable[(_band)][Offset - (_idx)] +#define LUT_BASE(_band) pAd->TxPowerCtrl.LookupTable[(_band)][Offset] +#define LUT_INDEX(_band, _idx) pAd->TxPowerCtrl.LookupTable[(_band)][(_idx)] + + +VOID InitLookupTable( + IN PRTMP_ADAPTER pAd) +{ + int lut_idx, IdxTmp, pos_idx, pos_bound, neg_idx, neg_bound; + int step_cnt, comp_val; + enum IEEE80211_BAND band; + int band_nums = 1, Offset; + EEPROM_WORD_STRUC WordStruct; + UCHAR PlusStepNum[IEEE80211_BAND_NUMS][8]; + UCHAR MinusStepNum[IEEE80211_BAND_NUMS][8]; + UCHAR Step[IEEE80211_BAND_NUMS]; + + + DBGPRINT(RT_DEBUG_TRACE, ("==> InitLookupTable\n")); + + /* Read from EEPROM, as parameters for lookup table for G band */ + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 2.4G] EEPROM\n")); + RT28xx_EEPROM_READ16(pAd, 0x6e, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\t6e = 0x%x\n", WordStruct.word)); + PlusStepNum[IEEE80211_BAND_2G][0] = (WordStruct.field.Byte0 & 0x0F); + PlusStepNum[IEEE80211_BAND_2G][1] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F); + PlusStepNum[IEEE80211_BAND_2G][2] = (WordStruct.field.Byte1 & 0x0F); + PlusStepNum[IEEE80211_BAND_2G][3] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F); + + RT28xx_EEPROM_READ16(pAd, 0x70, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\t70 = 0x%x\n", WordStruct.word)); + PlusStepNum[IEEE80211_BAND_2G][4] = (WordStruct.field.Byte0 & 0x0F); + PlusStepNum[IEEE80211_BAND_2G][5] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F); + PlusStepNum[IEEE80211_BAND_2G][6] = (WordStruct.field.Byte1 & 0x0F); + PlusStepNum[IEEE80211_BAND_2G][7] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F); + + RT28xx_EEPROM_READ16(pAd, 0x72, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\t72 = 0x%x\n", WordStruct.word)); + MinusStepNum[IEEE80211_BAND_2G][0] = (WordStruct.field.Byte0 & 0x0F); + MinusStepNum[IEEE80211_BAND_2G][1] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F); + MinusStepNum[IEEE80211_BAND_2G][2] = (WordStruct.field.Byte1 & 0x0F); + MinusStepNum[IEEE80211_BAND_2G][3] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F); + + RT28xx_EEPROM_READ16(pAd, 0x74, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\t74 = 0x%x\n", WordStruct.word)); + MinusStepNum[IEEE80211_BAND_2G][4] = (WordStruct.field.Byte0 & 0x0F); + MinusStepNum[IEEE80211_BAND_2G][5] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F); + MinusStepNum[IEEE80211_BAND_2G][6] = (WordStruct.field.Byte1 & 0x0F); + MinusStepNum[IEEE80211_BAND_2G][7] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F); + + RT28xx_EEPROM_READ16(pAd, 0x76, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\t76 = 0x%x\n", WordStruct.word)); + pAd->TxPowerCtrl.TssiGain[IEEE80211_BAND_2G] = (WordStruct.field.Byte0 & 0x0F); + Step[IEEE80211_BAND_2G] = (WordStruct.field.Byte0 >> 4); + pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_2G] = (CHAR)WordStruct.field.Byte1; + + DBGPRINT(RT_DEBUG_TRACE, ("\tPlus = %u %u %u %u %u %u %u %u\n", + PlusStepNum[IEEE80211_BAND_2G][0], + PlusStepNum[IEEE80211_BAND_2G][1], + PlusStepNum[IEEE80211_BAND_2G][2], + PlusStepNum[IEEE80211_BAND_2G][3], + PlusStepNum[IEEE80211_BAND_2G][4], + PlusStepNum[IEEE80211_BAND_2G][5], + PlusStepNum[IEEE80211_BAND_2G][6], + PlusStepNum[IEEE80211_BAND_2G][7] + )); + DBGPRINT(RT_DEBUG_TRACE, ("\tMinus = %u %u %u %u %u %u %u %u\n", + MinusStepNum[IEEE80211_BAND_2G][0], + MinusStepNum[IEEE80211_BAND_2G][1], + MinusStepNum[IEEE80211_BAND_2G][2], + MinusStepNum[IEEE80211_BAND_2G][3], + MinusStepNum[IEEE80211_BAND_2G][4], + MinusStepNum[IEEE80211_BAND_2G][5], + MinusStepNum[IEEE80211_BAND_2G][6], + MinusStepNum[IEEE80211_BAND_2G][7] + )); + DBGPRINT(RT_DEBUG_TRACE, ("\ttssi gain/step = %u\n", pAd->TxPowerCtrl.TssiGain[IEEE80211_BAND_2G])); + DBGPRINT(RT_DEBUG_TRACE, ("\tStep = %u\n", Step[IEEE80211_BAND_2G])); + DBGPRINT(RT_DEBUG_TRACE, ("\tRefTemp = %d\n", pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_2G])); + +#ifdef A_BAND_SUPPORT + if (RFIC_IS_5G_BAND(pAd)) + { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation 5G] EEPROM\n")); + /* Read from EEPROM, as parameters for lookup table for A band */ + RT28xx_EEPROM_READ16(pAd, 0xd4, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\td4 = 0x%x\n", WordStruct.word)); + PlusStepNum[IEEE80211_BAND_5G][0] = (WordStruct.field.Byte0 & 0x0F); + PlusStepNum[IEEE80211_BAND_5G][1] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F); + PlusStepNum[IEEE80211_BAND_5G][2] = (WordStruct.field.Byte1 & 0x0F); + PlusStepNum[IEEE80211_BAND_5G][3] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F); + + RT28xx_EEPROM_READ16(pAd, 0xd6, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\td6 = 0x%x\n", WordStruct.word)); + PlusStepNum[IEEE80211_BAND_5G][4] = (WordStruct.field.Byte0 & 0x0F); + PlusStepNum[IEEE80211_BAND_5G][5] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F); + PlusStepNum[IEEE80211_BAND_5G][6] = (WordStruct.field.Byte1 & 0x0F); + PlusStepNum[IEEE80211_BAND_5G][7] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F); + + RT28xx_EEPROM_READ16(pAd, 0xd8, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\td8 = 0x%x\n", WordStruct.word)); + MinusStepNum[IEEE80211_BAND_5G][0] = (WordStruct.field.Byte0 & 0x0F); + MinusStepNum[IEEE80211_BAND_5G][1] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F); + MinusStepNum[IEEE80211_BAND_5G][2] = (WordStruct.field.Byte1 & 0x0F); + MinusStepNum[IEEE80211_BAND_5G][3] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F); + + RT28xx_EEPROM_READ16(pAd, 0xda, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\tda = 0x%x\n", WordStruct.word)); + MinusStepNum[IEEE80211_BAND_5G][4] = (WordStruct.field.Byte0 & 0x0F); + MinusStepNum[IEEE80211_BAND_5G][5] = (((WordStruct.field.Byte0 & 0xF0) >> 4) & 0x0F); + MinusStepNum[IEEE80211_BAND_5G][6] = (WordStruct.field.Byte1 & 0x0F); + MinusStepNum[IEEE80211_BAND_5G][7] = (((WordStruct.field.Byte1 & 0xF0) >> 4) & 0x0F); + + RT28xx_EEPROM_READ16(pAd, 0xdc, WordStruct.word); + DBGPRINT(RT_DEBUG_TRACE, ("\tdc = 0x%x\n", WordStruct.word)); + pAd->TxPowerCtrl.TssiGain[IEEE80211_BAND_5G] = (WordStruct.field.Byte0 & 0x0F); + Step[IEEE80211_BAND_5G] = (WordStruct.field.Byte0 >> 4); + pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_5G] = (CHAR)WordStruct.field.Byte1; + + DBGPRINT(RT_DEBUG_TRACE, ("\tPlus = %u %u %u %u %u %u %u %u\n", + PlusStepNum[IEEE80211_BAND_5G][0], + PlusStepNum[IEEE80211_BAND_5G][1], + PlusStepNum[IEEE80211_BAND_5G][2], + PlusStepNum[IEEE80211_BAND_5G][3], + PlusStepNum[IEEE80211_BAND_5G][4], + PlusStepNum[IEEE80211_BAND_5G][5], + PlusStepNum[IEEE80211_BAND_5G][6], + PlusStepNum[IEEE80211_BAND_5G][7] + )); + DBGPRINT(RT_DEBUG_TRACE, ("\tMinus = %u %u %u %u %u %u %u %u\n", + MinusStepNum[IEEE80211_BAND_5G][0], + MinusStepNum[IEEE80211_BAND_5G][1], + MinusStepNum[IEEE80211_BAND_5G][2], + MinusStepNum[IEEE80211_BAND_5G][3], + MinusStepNum[IEEE80211_BAND_5G][4], + MinusStepNum[IEEE80211_BAND_5G][5], + MinusStepNum[IEEE80211_BAND_5G][6], + MinusStepNum[IEEE80211_BAND_5G][7] + )); + DBGPRINT(RT_DEBUG_TRACE, ("\ttssi gain/step = %u\n", pAd->TxPowerCtrl.TssiGain[IEEE80211_BAND_5G])); + DBGPRINT(RT_DEBUG_TRACE, ("\tStep = %u\n", Step[IEEE80211_BAND_5G])); + DBGPRINT(RT_DEBUG_TRACE, ("\tRefTemp= %d\n", pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_5G])); + + band_nums = IEEE80211_BAND_NUMS; + } +#endif /* A_BAND_SUPPORT */ + + { + pos_bound = 26; + neg_bound = 8; + Offset = 7; + } + + for (band = IEEE80211_BAND_2G; band < band_nums; band++) + { + /* + For positive table, in sequence 0, 1, 2 ...., 31, 32 + F(x) = F(x-1) + Step(x) + with following exception: + F(0) = F(1) - Compensation(x); + F(1) = Step(band) / 2; + + After each step, Compensation value will decrease base on step value and + Compensation(x) = Step(band) - step_cnt; + */ + + LUT_POSITIVE(band,1) = Step[band] / 2; + LUT_BASE(band) = LUT_POSITIVE(band, 1) - Step[band]; + + step_cnt = 0; + IdxTmp = 1; + for (pos_idx = 2; pos_idx <= pos_bound;) + { + comp_val = Step[band] - step_cnt; + LUT_POSITIVE(band, pos_idx) = LUT_POSITIVE(band, pos_idx - 1) + comp_val /* (Step[band] - (step_cnt+1) + 1)*/; + if (PlusStepNum[band][step_cnt] != 0 || step_cnt >= 8) + { + if (pos_idx >= IdxTmp + PlusStepNum[band][step_cnt] && step_cnt < 8) + { + IdxTmp = IdxTmp + PlusStepNum[band][step_cnt]; + step_cnt += 1; + } + pos_idx++; + } + else + { + step_cnt += 1; + } + } + + /* negative */ + step_cnt = 0; + IdxTmp = 1; + for (neg_idx = 1; neg_idx <= neg_bound;) + { + comp_val = Step[band] + step_cnt; + LUT_NEGATIVE(band, neg_idx) = LUT_NEGATIVE(band, (neg_idx - 1)) - comp_val; + if (MinusStepNum[band][step_cnt] != 0 || step_cnt >= 8) + { + if ((neg_idx + 1) >= IdxTmp + MinusStepNum[band][step_cnt] && step_cnt < 8) + { + IdxTmp = IdxTmp + MinusStepNum[band][step_cnt]; + step_cnt += 1; + } + neg_idx++; + } + else + { + step_cnt += 1; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation %sG band(%d)] Lookup table:\n", + (band == 0 ? "2.4" : "5"), band)); + for (lut_idx = 0; lut_idx < LOOKUP_TB_SIZE; lut_idx++) + { + DBGPRINT(RT_DEBUG_TRACE, ("\t%d, %d\n", lut_idx - Offset, LUT_INDEX(band, lut_idx))); + } + } + + bbp_tx_comp_init(pAd, 1, 0); +} + + +VOID AsicGetAutoAgcOffsetForTemperatureSensor( + IN RTMP_ADAPTER *pAd, + IN CHAR *pDeltaPwr, + IN CHAR *pTotalDeltaPwr, + IN CHAR *pAgcCompensate, + IN CHAR *pDeltaPowerByBbpR1) +{ + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTable; + TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTableEntry0 = NULL; /* Ant0 */ + TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTableEntry1 = NULL; /* Ant1 */ + BOOLEAN bAutoTxAgc = FALSE; + PCHAR pTxAgcCompensate = NULL; + UCHAR RFValue = 0; + CHAR TuningTableUpperBound = 0, TuningTableIndex0 = 0, TuningTableIndex1 = 0; + CHAR temper_val, rf_txpwr_bnd; + INT CurrentTemp = 0, RefTemp, lut_base; + INT *LookupTable, LookupTableIndex; + + DBGPRINT(RT_DEBUG_INFO, ("-->%s\n", __FUNCTION__)); + + lut_base = TEMPERATURE_COMPENSATION_LOOKUP_TABLE_OFFSET; + LookupTableIndex = pAd->TxPowerCtrl.LookupTableIndex + lut_base; + + *pTotalDeltaPwr = 0; + +#ifdef A_BAND_SUPPORT + if (pAd->CommonCfg.Channel > 14) + { + /* a band channel */ + bAutoTxAgc = pAd->bAutoTxAgcA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + TxPowerTuningTable = pChipCap->TxPowerTuningTable_5G; + RefTemp = pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_5G]; + LookupTable = &pAd->TxPowerCtrl.LookupTable[IEEE80211_BAND_5G][0]; + TuningTableUpperBound = pChipCap->TxAlcTxPowerUpperBound_5G; + rf_txpwr_bnd = 0x2b; + } + else +#endif /* A_BAND_SUPPORT */ + { + /* bg band channel */ + bAutoTxAgc = pAd->bAutoTxAgcG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + TxPowerTuningTable = pChipCap->TxPowerTuningTable_2G; + RefTemp = pAd->TxPowerCtrl.RefTemp[IEEE80211_BAND_2G]; + LookupTable = &pAd->TxPowerCtrl.LookupTable[IEEE80211_BAND_2G][0]; + TuningTableUpperBound = pChipCap->TxAlcTxPowerUpperBound_2G; + rf_txpwr_bnd = 0x27; + } + + /* AutoTxAgc in EEPROM means temperature compensation enabled/diablded. */ + if (bAutoTxAgc) + { + /* Current temperature */ + bbp_get_temp(pAd, &temper_val); + CurrentTemp = temper_val; + + if (tx_temp_dbg) { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] current temp = %d(0x%x), pAd->curr_temp=%d, temper_val=%d\n", + CurrentTemp, CurrentTemp, pAd->curr_temp, temper_val)); + } + CurrentTemp = pAd->curr_temp; + if (tx_temp_dbg) { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] RefTemp = %d\n", RefTemp)); + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] index = %d\n", pAd->TxPowerCtrl.LookupTableIndex)); + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] f(%d)= %d\n", pAd->TxPowerCtrl.LookupTableIndex - 1, LookupTable[LookupTableIndex - 1])); + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] f(%d)= %d\n", pAd->TxPowerCtrl.LookupTableIndex, LookupTable[LookupTableIndex])); + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] f(%d)= %d\n", pAd->TxPowerCtrl.LookupTableIndex + 1, LookupTable[LookupTableIndex + 1])); + } + if (CurrentTemp > RefTemp + LookupTable[LookupTableIndex + 1] + ((LookupTable[LookupTableIndex + 1] - LookupTable[LookupTableIndex]) >> 2) && + LookupTableIndex < (LOOKUP_TB_SIZE - 1)) + { + if (tx_temp_dbg) { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] ++\n")); + } + LookupTableIndex++; + pAd->TxPowerCtrl.LookupTableIndex++; + } + else if (CurrentTemp < RefTemp + LookupTable[LookupTableIndex] - ((LookupTable[LookupTableIndex] - LookupTable[LookupTableIndex - 1]) >> 2) && + LookupTableIndex > 0) + { + if (tx_temp_dbg) { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] --\n")); + } + LookupTableIndex--; + pAd->TxPowerCtrl.LookupTableIndex--; + } + else + { + if (tx_temp_dbg) { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] ==\n")); + } + } + + if (tx_temp_dbg) { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] idxTxPowerTable=%d, idxTxPowerTable2=%d, TuningTableUpperBound=%d\n", + pAd->TxPowerCtrl.idxTxPowerTable + pAd->TxPowerCtrl.LookupTableIndex, + pAd->TxPowerCtrl.idxTxPowerTable2 + pAd->TxPowerCtrl.LookupTableIndex, + TuningTableUpperBound)); + } + +#ifdef E3_DBG_FALLBACK + TuningTableIndex0 = pAd->TxPowerCtrl.idxTxPowerTable + + pAd->TxPowerCtrl.LookupTableIndex +#ifdef DOT11_N_SUPPORT + + pAd->TxPower[pAd->CommonCfg.CentralChannel-1].Power; +#else + + pAd->TxPower[pAd->CommonCfg.Channel-1].Power; +#endif /* DOT11_N_SUPPORT */ +#else + TuningTableIndex0 = pAd->TxPowerCtrl.idxTxPowerTable + + pAd->TxPowerCtrl.LookupTableIndex + + pAd->hw_cfg.cur_ch_pwr[0]; +#endif /* E3_DBG_FALLBACK */ + /* The boundary verification */ + TuningTableIndex0 = (TuningTableIndex0 > TuningTableUpperBound) ? TuningTableUpperBound : TuningTableIndex0; + TuningTableIndex0 = (TuningTableIndex0 < LOWERBOUND_TX_POWER_TUNING_ENTRY) ? + LOWERBOUND_TX_POWER_TUNING_ENTRY : TuningTableIndex0; + TxPowerTuningTableEntry0 = &TxPowerTuningTable[TuningTableIndex0 + TX_POWER_TUNING_ENTRY_OFFSET]; + +#ifdef E3_DBG_FALLBACK + TuningTableIndex1 = pAd->TxPowerCtrl.idxTxPowerTable2 + + pAd->TxPowerCtrl.LookupTableIndex +#ifdef DOT11_N_SUPPORT + + pAd->TxPower[pAd->CommonCfg.CentralChannel-1].Power2; +#else + + pAd->TxPower[pAd->CommonCfg.Channel-1].Power2; +#endif /* DOT11_N_SUPPORT */ +#else + TuningTableIndex1 = pAd->TxPowerCtrl.idxTxPowerTable2 + + pAd->TxPowerCtrl.LookupTableIndex + + pAd->hw_cfg.cur_ch_pwr[1]; +#endif /* E3_DBG_FALLBACK */ + /* The boundary verification */ + TuningTableIndex1 = (TuningTableIndex1 > TuningTableUpperBound) ? TuningTableUpperBound : TuningTableIndex1; + TuningTableIndex1 = (TuningTableIndex1 < LOWERBOUND_TX_POWER_TUNING_ENTRY) ? + LOWERBOUND_TX_POWER_TUNING_ENTRY : TuningTableIndex1; + TxPowerTuningTableEntry1 = &TxPowerTuningTable[TuningTableIndex1 + TX_POWER_TUNING_ENTRY_OFFSET]; + + /* + Update RF_R49 [0:5], RF_R50[0:5] + The valid range of the RF R49 (<5:0>tx0_alc<5:0>) is 0x00~0x27 + The valid range of the RF R50 (<5:0>tx0_alc<5:0>) is 0x00~0x27 + */ + RT30xxReadRFRegister(pAd, RF_R49, &RFValue); + RFValue &= (~0x3F); + // TODO: Shiang-6590, for a band, the upper bound of RF_R49/RF_R50 shall be 0x2b instead of 0x27!!!! + RFValue |= ((TxPowerTuningTableEntry0->RF_TX_ALC > rf_txpwr_bnd) ? rf_txpwr_bnd : TxPowerTuningTableEntry0->RF_TX_ALC); + RT30xxWriteRFRegister(pAd, RF_R49, RFValue); + if (tx_temp_dbg) { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] (tx0)RF_TX_ALC = %x, MAC_PowerDelta = %d, TuningTableIndex = %d\n", + TxPowerTuningTableEntry0->RF_TX_ALC, TxPowerTuningTableEntry0->MAC_PowerDelta, TuningTableIndex0)); + DBGPRINT(RT_DEBUG_TRACE, ("\tUpdate RF_R49[0:5] to 0x%x\n", (RFValue & 0x3f))); + } + + RT30xxReadRFRegister(pAd, RF_R50, &RFValue); + RFValue &= (~0x3F); + RFValue |= ((TxPowerTuningTableEntry1->RF_TX_ALC > rf_txpwr_bnd) ? rf_txpwr_bnd : TxPowerTuningTableEntry1->RF_TX_ALC); + RT30xxWriteRFRegister(pAd, RF_R50, RFValue); + if (tx_temp_dbg) { + DBGPRINT(RT_DEBUG_TRACE, ("[temp. compensation] (tx1)RF_TX_ALC = %x, MAC_PowerDelta = %d, TuningTableIndex = %d\n", + TxPowerTuningTableEntry1->RF_TX_ALC, TxPowerTuningTableEntry1->MAC_PowerDelta, TuningTableIndex1)); + DBGPRINT(RT_DEBUG_TRACE, ("\tUpdate RF_R50[0:5] to 0x%x\n", (RFValue & 0x3f))); + } + + *pTotalDeltaPwr = TxPowerTuningTableEntry0->MAC_PowerDelta; + } + + *pAgcCompensate = *pTxAgcCompensate; + + if (tx_temp_dbg) { + DBGPRINT(RT_DEBUG_TRACE, ("<--%s(): pDeltaPwr=%d, TotalDeltaPwr=%d, AgcCompensate=%d, DeltaPowerByBbpR1=%d\n", + __FUNCTION__, *pDeltaPwr, *pTotalDeltaPwr, *pAgcCompensate, *pDeltaPowerByBbpR1)); +} +} + + +/* + Note: This function use E2P_OFFSET_START and E2P_OFFSET_END to + determine the table type is minus or plus. +*/ +BOOLEAN LoadTempCompTableFromEEPROM( + IN RTMP_ADAPTER *pAd, + IN const USHORT E2P_OFFSET_START, + IN const USHORT E2P_OFFSET_END, + OUT PUCHAR TssiTable, + IN const INT StartIndex, + IN const UINT32 TABLE_SIZE) +{ + USHORT e2p_value; + INT e2p_index, table_index; + CHAR table_sign; /* +1 for plus table, -1 for minus table */ + + table_sign = (E2P_OFFSET_START < E2P_OFFSET_END) ? 1 : (-1); + + if (StartIndex < TABLE_SIZE) + table_index = StartIndex; + else + { + DBGPRINT(RT_DEBUG_ERROR, + ("%s(): Error! Wrong starting index (%d).\n", + __FUNCTION__, StartIndex)); + return FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE, + ("%s(): Load %s %s table from E2P 0x%x to 0x%x. StartIndex = %d\n", + __FUNCTION__, + pAd->CommonCfg.Channel > 14 ? "5G" : "2.4G", + (table_sign == 1) ? "plus" : "minus", + E2P_OFFSET_START, E2P_OFFSET_END, StartIndex)); + // TODO: Load two bytes + for (e2p_index = E2P_OFFSET_START; + e2p_index != (E2P_OFFSET_END + (1*table_sign)); + e2p_index = e2p_index + (1*table_sign)) + { + RT28xx_EEPROM_READ16(pAd, e2p_index, e2p_value); + TssiTable[table_index] = (UCHAR)(e2p_value & 0xFF); + if ((++table_index) >= TABLE_SIZE) + break; /* table full */ + } + + if (e2p_index != E2P_OFFSET_END) + { + /* Table is full before e2p_offset_end */ + DBGPRINT(RT_DEBUG_WARN, + ("%s(): Warning! EEPROM table may not be completely loaded.\n", + __FUNCTION__)); + return FALSE; + } + else + { + for (table_index = 0; table_index < TABLE_SIZE; table_index++) + DBGPRINT(RT_DEBUG_TRACE, ("\tTable[%d] = %3d (0x%02X)\n", + table_index, (CHAR)TssiTable[table_index], TssiTable[table_index])); + return TRUE; + } + + return TRUE; +} +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + +#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 + + + + +#if defined(RTMP_MAC) || defined(RLT_MAC) +VOID AsicGetTxPowerOffset(RTMP_ADAPTER *pAd, ULONG *TxPwr) +{ + CONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC CfgOfTxPwrCtrlOverMAC; + DBGPRINT(RT_DEBUG_INFO, ("-->AsicGetTxPowerOffset\n")); + + NdisZeroMemory(&CfgOfTxPwrCtrlOverMAC, sizeof(CfgOfTxPwrCtrlOverMAC)); + + CfgOfTxPwrCtrlOverMAC.NumOfEntries = 5; /* MAC 0x1314, 0x1318, 0x131C, 0x1320 and 1324 */ + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return; + } + +#ifdef DOT11_VHT_AC + if (pAd->CommonCfg.BBPCurrentBW == BW_80 && + pAd->CommonCfg.Channel > 14) + { + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].MACRegisterOffset = TX_PWR_CFG_0; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue = pAd->Tx80MPwrCfgABand[0]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].MACRegisterOffset = TX_PWR_CFG_1; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = pAd->Tx80MPwrCfgABand[1]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_2; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx80MPwrCfgABand[2]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_3; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = pAd->Tx80MPwrCfgABand[3]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_4; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx80MPwrCfgABand[4]; + } + else +#endif /* DOT11_VHT_AC */ + if (pAd->CommonCfg.BBPCurrentBW == BW_40) + { + if (pAd->CommonCfg.CentralChannel > 14) + { + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].MACRegisterOffset = TX_PWR_CFG_0; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue = pAd->Tx40MPwrCfgABand[0]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].MACRegisterOffset = TX_PWR_CFG_1; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = pAd->Tx40MPwrCfgABand[1]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_2; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx40MPwrCfgABand[2]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_3; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = pAd->Tx40MPwrCfgABand[3]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_4; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx40MPwrCfgABand[4]; + } + else + { + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].MACRegisterOffset = TX_PWR_CFG_0; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue = pAd->Tx40MPwrCfgGBand[0]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].MACRegisterOffset = TX_PWR_CFG_1; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = pAd->Tx40MPwrCfgGBand[1]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_2; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx40MPwrCfgGBand[2]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_3; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = pAd->Tx40MPwrCfgGBand[3]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_4; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx40MPwrCfgGBand[4]; + } + } + else + { + if (pAd->CommonCfg.CentralChannel > 14) + { + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].MACRegisterOffset = TX_PWR_CFG_0; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue = pAd->Tx20MPwrCfgABand[0]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].MACRegisterOffset = TX_PWR_CFG_1; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = pAd->Tx20MPwrCfgABand[1]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_2; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx20MPwrCfgABand[2]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_3; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = pAd->Tx20MPwrCfgABand[3]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_4; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx20MPwrCfgABand[4]; + } + else + { + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].MACRegisterOffset = TX_PWR_CFG_0; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue = pAd->Tx20MPwrCfgGBand[0]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].MACRegisterOffset = TX_PWR_CFG_1; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[1].RegisterValue = pAd->Tx20MPwrCfgGBand[1]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].MACRegisterOffset = TX_PWR_CFG_2; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[2].RegisterValue = pAd->Tx20MPwrCfgGBand[2]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].MACRegisterOffset = TX_PWR_CFG_3; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[3].RegisterValue = pAd->Tx20MPwrCfgGBand[3]; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].MACRegisterOffset = TX_PWR_CFG_4; + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[4].RegisterValue = pAd->Tx20MPwrCfgGBand[4]; + } + } + + NdisCopyMemory(TxPwr, (UCHAR *)&CfgOfTxPwrCtrlOverMAC, sizeof(CfgOfTxPwrCtrlOverMAC)); + + DBGPRINT(RT_DEBUG_INFO, ("<--AsicGetTxPowerOffset\n")); +} +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + +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][0]; + pTssiPlusBoundary = &pAd->TssiPlusBoundaryA[0][0]; + TxAgcStep = pAd->TxAgcStepA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + { + bbp_get_temp(pAd, &BbpR49.byte); + + /* TSSI representation */ + if (IS_RT3071(pAd) || IS_RT3390(pAd) || IS_RT3090A(pAd) || IS_RT3572(pAd)) /* 5-bits */ + { + BbpR49.byte = (BbpR49.byte & 0x1F); + } + + /* (p) TssiPlusBoundaryG[0] = 0 = (m) TssiMinusBoundaryG[0] */ + /* compensate: +4 +3 +2 +1 0 -1 -2 -3 -4 * steps */ + /* step value is defined in pAd->TxAgcStepG for tx power value */ + + /* [4]+1+[4] p4 p3 p2 p1 o1 m1 m2 m3 m4 */ + /* ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 + above value are examined in mass factory production */ + /* [4] [3] [2] [1] [0] [1] [2] [3] [4] */ + + /* plus (+) is 0x00 ~ 0x45, minus (-) is 0xa0 ~ 0xf0 */ + /* if value is between p1 ~ o1 or o1 ~ s1, no need to adjust tx power */ + /* if value is 0xa5, tx power will be -= TxAgcStep*(2-1) */ + + if (BbpR49.byte > pTssiMinusBoundary[1]) + { + /* Reading is larger than the reference value */ + /* Check for how large we need to decrease the Tx power */ + for (idx = 1; idx < 5; idx++) + { + if (BbpR49.byte <= pTssiMinusBoundary[idx]) /* Found the range */ + break; + } + /* The index is the step we should decrease, idx = 0 means there is nothing to compensate */ + + *pTxAgcCompensate = -(TxAgcStep * (idx-1)); + DeltaPwr += (*pTxAgcCompensate); + DBGPRINT(RT_DEBUG_TRACE, ("-- Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = -%d\n", + BbpR49.byte, TssiRef, TxAgcStep, idx-1)); + } + else if (BbpR49.byte < pTssiPlusBoundary[1]) + { + /* Reading is smaller than the reference value */ + /* Check for how large we need to increase the Tx power */ + for (idx = 1; idx < 5; idx++) + { + if (BbpR49.byte >= pTssiPlusBoundary[idx]) /* Found the range*/ + break; + } + + /* The index is the step we should increase, idx = 0 means there is nothing to compensate */ + *pTxAgcCompensate = TxAgcStep * (idx-1); + DeltaPwr += (*pTxAgcCompensate); + DBGPRINT(RT_DEBUG_TRACE, ("++ Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49.byte, TssiRef, TxAgcStep, idx-1)); + } + else + { + *pTxAgcCompensate = 0; + DBGPRINT(RT_DEBUG_TRACE, (" Tx Power, BBP R49=%x, TssiRef=%x, TxAgcStep=%x, step = +%d\n", + BbpR49.byte, TssiRef, TxAgcStep, 0)); + } + } + } + else + { + if (pAd->CommonCfg.Channel <= 14) + { + bAutoTxAgc = pAd->bAutoTxAgcG; + pTxAgcCompensate = &pAd->TxAgcCompensateG; + } + else + { + bAutoTxAgc = pAd->bAutoTxAgcA; + pTxAgcCompensate = &pAd->TxAgcCompensateA; + } + + if (bAutoTxAgc) + DeltaPwr += (*pTxAgcCompensate); + } + + + *pDeltaPwr = DeltaPwr; + *pAgcCompensate = *pTxAgcCompensate; + + DBGPRINT(RT_DEBUG_INFO, ("<--%s\n", __FUNCTION__)); +} + + +#if defined(RTMP_MAC) || defined(RLT_MAC) +VOID AsicExtraPowerOverMAC(RTMP_ADAPTER *pAd) +{ + UINT32 txpwr = 0; + UINT32 txpwr7 = 0, txpwr8 = 0, txpwr9 = 0; + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return; + } + + /* For OFDM_54 and HT_MCS_7, extra fill the corresponding register value into MAC 0x13D4 */ + RTMP_IO_READ32(pAd, TX_PWR_CFG_1, &txpwr); + txpwr7 |= (txpwr & 0x0000FF00) >> 8; /* Get Tx power for OFDM 54 */ + RTMP_IO_READ32(pAd, TX_PWR_CFG_2, &txpwr); + txpwr7 |= (txpwr & 0x0000FF00) << 8; /* Get Tx power for HT MCS 7 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_7, txpwr7); + + /* For STBC_MCS_7, extra fill the corresponding register value into MAC 0x13DC */ + RTMP_IO_READ32(pAd, TX_PWR_CFG_4, &txpwr); + txpwr9 |= (txpwr & 0x0000FF00) >> 8; /* Get Tx power for STBC MCS 7 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_9, txpwr9); + + if (pAd->CommonCfg.TxStream == 2) + { + /* For HT_MCS_15, extra fill the corresponding register value into MAC 0x13DC */ + RTMP_IO_READ32(pAd, TX_PWR_CFG_3, &txpwr); + txpwr8 |= (txpwr & 0x0000FF00) >> 8; /* Get Tx power for HT MCS 15 */ + RTMP_IO_WRITE32(pAd, TX_PWR_CFG_8, txpwr8); + } + +} +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + +/* + ========================================================================== + Description: + Gives CCK TX rate 2 more dB TX power. + This routine works only in LINK UP in INFRASTRUCTURE mode. + + calculate desired Tx power in RF R3.Tx0~5, should consider - + 0. if current radio is a noisy environment (pAd->DrsCounters.fNoisyEnvironment) + 1. TxPowerPercentage + 2. auto calibration based on TSSI feedback + 3. extra 2 db for CCK + 4. -10 db upon very-short distance (AvgRSSI >= -40db) to AP + + NOTE: Since this routine requires the value of (pAd->DrsCounters.fNoisyEnvironment), + it should be called AFTER MlmeDynamicTxRatSwitching() + ========================================================================== + */ +VOID AsicAdjustTxPower(RTMP_ADAPTER *pAd) +{ + INT i, j; + CHAR Value; + CHAR Rssi = -127; + CHAR DeltaPwr = 0; + CHAR TxAgcCompensate = 0; + CHAR DeltaPowerByBbpR1 = 0; + CHAR TotalDeltaPower = 0; /* (non-positive number) including the transmit power controlled by the MAC and the BBP R1 */ + CONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC CfgOfTxPwrCtrlOverMAC = {0}; +#ifdef SINGLE_SKU + CHAR TotalDeltaPowerOri = 0; + UCHAR SingleSKUBbpR1Offset = 0; + ULONG SingleSKUTotalDeltaPwr[MAX_TXPOWER_ARRAY_SIZE] = {0}; +#endif /* SINGLE_SKU */ + + + + /* 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)); + + + + /* Get delta power based on the percentage specified from UI */ + AsicPercentageDeltaPower(pAd, Rssi, &DeltaPwr,&DeltaPowerByBbpR1); + + /* The transmit power controlled by the BBP */ + TotalDeltaPower += DeltaPowerByBbpR1; + /* The transmit power controlled by the MAC */ + TotalDeltaPower += DeltaPwr; + +#ifdef SINGLE_SKU + if (pAd->CommonCfg.bSKUMode == TRUE) + { + /* Re calculate delta power while enabling Single SKU */ + GetSingleSkuDeltaPower(pAd, &TotalDeltaPower, (PULONG)&SingleSKUTotalDeltaPwr, &SingleSKUBbpR1Offset); + + TotalDeltaPowerOri = TotalDeltaPower; + } + else +#endif /* SINGLE_SKU */ + { + AsicCompensatePowerViaBBP(pAd, &TotalDeltaPower); + } + + + /* Power will be updated each 4 sec. */ + if (pAd->Mlme.OneSecPeriodicRound % 4 == 0) + { + /* 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 */ + _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 */ +#ifdef E3_DBG_FALLBACK + pTxPwrEntry->RegisterValue = (reg_val & ~(0x0000000F << j*4)) | (Value << j*4); +#else + reg_val = (reg_val & ~(0x0000000F << j*4)) | (Value << j*4); +#endif /* E3_DBG_FALLBACK */ + } + +#ifndef E3_DBG_FALLBACK + pTxPwrEntry->RegisterValue = reg_val; +#endif /* E3_DBG_FALLBACK */ + RTMP_IO_WRITE32(pAd, pTxPwrEntry->MACRegisterOffset, pTxPwrEntry->RegisterValue); + + } + } + + /* Extra set MAC registers to compensate Tx power if any */ + RTMP_CHIP_ASIC_EXTRA_POWER_OVER_MAC(pAd); + } + +} + + +#ifdef SINGLE_SKU +VOID GetSingleSkuDeltaPower( + IN RTMP_ADAPTER *pAd, + IN CHAR *pTotalDeltaPower, + INOUT ULONG *pSingleSKUTotalDeltaPwr, + INOUT UCHAR *pSingleSKUBbpR1Offset) +{ + INT i, j; + CHAR Value; + CHAR MinValue = 127; + UCHAR BbpR1 = 0; + UCHAR TxPwrInEEPROM = 0xFF, CountryTxPwr = 0xFF, criterion; + UCHAR AdjustMaxTxPwr[(MAX_TX_PWR_CONTROL_OVER_MAC_REGISTERS * 8)]; + CONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC CfgOfTxPwrCtrlOverMAC = {0}; + + /* Get TX rate offset table which from EEPROM 0xDEh ~ 0xEFh */ + RTMP_CHIP_ASIC_TX_POWER_OFFSET_GET(pAd, (PULONG)&CfgOfTxPwrCtrlOverMAC); + + /* Handle regulatory max. TX power constraint */ + if (pAd->CommonCfg.Channel > 14) + { + TxPwrInEEPROM = ((pAd->CommonCfg.DefineMaxTxPwr & 0xFF00) >> 8); /* 5G band */ + } + else + { + TxPwrInEEPROM = (pAd->CommonCfg.DefineMaxTxPwr & 0x00FF); /* 2.4G band */ + } + + CountryTxPwr = GetCuntryMaxTxPwr(pAd, pAd->CommonCfg.Channel); + + /* Use OFDM 6M as the criterion */ + criterion = (UCHAR)((CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[0].RegisterValue & 0x000F0000) >> 16); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: criterion=%d, TxPwrInEEPROM=%d, CountryTxPwr=%d\n", + __FUNCTION__, criterion, TxPwrInEEPROM, CountryTxPwr)); + + /* Adjust max. TX power according to the relationship of TX power in EEPROM */ + for (i=0; i> j*4) & 0x0F); + + if (j < 4) + { + AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion) + 4; /* CCK has 4dBm larger than OFDM */ + } + else + { + AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion); + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: offset = 0x%04X, i/j=%d/%d, (Default)Value=%d, %d\n", + __FUNCTION__, + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].MACRegisterOffset, + i, + j, + Value, + AdjustMaxTxPwr[i*8+j])); + } + } + else + { + for (j=0; j<8; j++) + { + Value = (CHAR)((CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].RegisterValue >> j*4) & 0x0F); + + AdjustMaxTxPwr[i*8+j] = TxPwrInEEPROM + (Value - criterion); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: offset = 0x%04X, i/j=%d/%d, (Default)Value=%d, %d\n", + __FUNCTION__, + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].MACRegisterOffset, + i, + j, + Value, + AdjustMaxTxPwr[i*8+j])); + } + } + } + + /* Adjust TX power according to the relationship */ + for (i=0; i> j*4) & 0x0F); + + /* The TX power is larger than the regulatory, the power should be restrained */ + if (AdjustMaxTxPwr[i*8+j] > CountryTxPwr) + { + Value = (AdjustMaxTxPwr[i*8+j] - CountryTxPwr); + + if (Value > 0xF) + { + /* The output power is larger than Country Regulatory over 15dBm, the origianl design has overflow case */ + DBGPRINT(RT_DEBUG_ERROR,("%s: Value overflow - %d\n", __FUNCTION__, Value)); + } + + *(pSingleSKUTotalDeltaPwr+i) = (*(pSingleSKUTotalDeltaPwr+i) & ~(0x0000000F << j*4)) | (Value << j*4); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: offset = 0x%04X, i/j=%d/%d, (Exceed)Value=%d, %d\n", + __FUNCTION__, + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].MACRegisterOffset, + i, + j, + Value, + AdjustMaxTxPwr[i*8+j])); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: offset = 0x%04X, i/j=%d/%d, Value=%d, %d, no change\n", + __FUNCTION__, + CfgOfTxPwrCtrlOverMAC.TxPwrCtrlOverMAC[i].MACRegisterOffset, + i, + j, + Value, + AdjustMaxTxPwr[i*8+j])); + } + } + } + } + + /* Calculate the min. TX power */ + for(i=0; i> j*4) & 0x0F); /* 0 ~ 15 */ + + /* Fix the corner case of Single SKU read eeprom offset 0xF0h ~ 0xFEh which for BBP Instruction configuration */ + if (Value == 0xF) + continue; + + /* Value_offset is current Pwr comapre with Country Regulation and need adjust delta value */ + PwrChange = (CHAR)((*(pSingleSKUTotalDeltaPwr+i) >> j*4) & 0x0F); /* 0 ~ 15 */ + PwrChange -= *pTotalDeltaPower; + + Value -= PwrChange; + + if (MinValue > Value) + MinValue = Value; + } + } + } +#ifdef RTMP_BBP + // TODO: shiang, handle this for RLT_BBP!! + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1); +#endif /* RTMP_BBP */ + /* Depend on the min. TX power to adjust and prevent the value of MAC_TX_PWR_CFG less than 0 */ + if ((MinValue < 0) && (MinValue >= -6)) + { + BbpR1 |= MDSM_DROP_TX_POWER_BY_6dBm; + *pSingleSKUBbpR1Offset = 6; + } + else if ((MinValue < -6)&&(MinValue >= -12)) + { + BbpR1 |= MDSM_DROP_TX_POWER_BY_12dBm; + *pSingleSKUBbpR1Offset = 12; + } + else if (MinValue < -12) + { + DBGPRINT(RT_DEBUG_WARN, ("%s: ASIC limit..\n", __FUNCTION__)); + BbpR1 |= MDSM_DROP_TX_POWER_BY_12dBm; + *pSingleSKUBbpR1Offset = 12; + } +#ifndef E3_DBG_FALLBACK + else { + BbpR1 &= ~MDSM_BBP_R1_STATIC_TX_POWER_CONTROL_MASK; + *pSingleSKUBbpR1Offset = 0; + } +#endif /* E3_DBG_FALLBACK */ +#ifdef RTMP_BBP + // TODO: shiang, handle this for RLT_BBP!! + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); +#endif /* RTMP_BBP */ + + DBGPRINT(RT_DEBUG_TRACE, ("%s: TotalDeltaPower = %d dBm, BbpR1 = 0x%02X \n", __FUNCTION__, *pTotalDeltaPower, BbpR1)); +} +#endif /* SINGLE_SKU */ + +#if defined(RTMP_INTERNAL_TX_ALC) || defined(MT76x0_TSSI_CAL_COMPENSATION) +INT16 MT76xx_lin2dBd( + IN UINT16 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; + } + } + } + + 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 */ + dBd=(dBd<<2)+(dBd<<1)+(dBd>>6)+(dBd>>7); + dBd=(dBd>>10); /* S10.5 */ + + return(dBd); +} +#endif /* defined(RTMP_INTERNAL_TX_ALC) || defined(MT76x0_TSSI_CAL_COMPENSATION) */ + +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 */ + { + } + else if (pAd->CommonCfg.TxPowerPercentage > 90) /* 91 ~ 100% & AUTO, treat as 100% in terms of mW */ + ; + else if (pAd->CommonCfg.TxPowerPercentage > 60) /* 61 ~ 90%, treat as 75% in terms of mW DeltaPwr -= 1; */ + { + *pDeltaPwr -= 1; + } + else if (pAd->CommonCfg.TxPowerPercentage > 30) /* 31 ~ 60%, treat as 50% in terms of mW DeltaPwr -= 3; */ + { + *pDeltaPwr -= 3; + } + else if (pAd->CommonCfg.TxPowerPercentage > 15) /* 16 ~ 30%, treat as 25% in terms of mW DeltaPwr -= 6; */ + { + *pDeltaPowerByBbpR1 -= 6; /* -6 dBm */ + } + else if (pAd->CommonCfg.TxPowerPercentage > 9) /* 10 ~ 15%, treat as 12.5% in terms of mW DeltaPwr -= 9; */ + { + *pDeltaPowerByBbpR1 -= 6; /* -6 dBm */ + *pDeltaPwr -= 3; + } + else /* 0 ~ 9 %, treat as MIN(~3%) in terms of mW DeltaPwr -= 12; */ + { + *pDeltaPowerByBbpR1 -= 12; /* -12 dBm */ + } +} + + +VOID AsicCompensatePowerViaBBP(RTMP_ADAPTER *pAd, CHAR *pTotalDeltaPower) +{ + UCHAR mdsm_drop_pwr; + + + DBGPRINT(RT_DEBUG_INFO, ("%s: TotalDeltaPower = %d dBm\n", __FUNCTION__, *pTotalDeltaPower)); + + if (*pTotalDeltaPower <= -12) + { + *pTotalDeltaPower += 12; + mdsm_drop_pwr = MDSM_DROP_TX_POWER_BY_12dBm; + } + else if ((*pTotalDeltaPower <= -6) && (*pTotalDeltaPower > -12)) + { + *pTotalDeltaPower += 6; + mdsm_drop_pwr = MDSM_DROP_TX_POWER_BY_6dBm; + } + else + { + /* Control the the transmit power by using the MAC only */ + mdsm_drop_pwr = MDSM_NORMAL_TX_POWER; + } + + DBGPRINT(RT_DEBUG_INFO, ("%s: Drop the BBP transmit power by %d dBm!\n", + __FUNCTION__, + (mdsm_drop_pwr == MDSM_DROP_TX_POWER_BY_12dBm ? 12 : \ + (mdsm_drop_pwr == MDSM_DROP_TX_POWER_BY_6dBm ? 6 : 0)))); + + +#ifdef RTMP_BBP + if (pAd->chipCap.hif_type == HIF_RTMP) + { + UCHAR BbpR1 = 0; + + /* The BBP R1 controls the transmit power for all rates */ + RTMP_BBP_IO_READ8_BY_REG_ID(pAd, BBP_R1, &BbpR1); + BbpR1 &= ~MDSM_BBP_R1_STATIC_TX_POWER_CONTROL_MASK; + BbpR1 |= mdsm_drop_pwr; + RTMP_BBP_IO_WRITE8_BY_REG_ID(pAd, BBP_R1, BbpR1); + + DBGPRINT(RT_DEBUG_INFO, ("%s: TotalDeltaPower = %d dBm, BbpR1 = 0x%02X \n", __FUNCTION__, *pTotalDeltaPower, BbpR1)); + } +#endif /* RTMP_BBP */ +} + + +/* + ======================================================================== + + Routine Description: + Read initial Tx power per MCS and BW from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPReadTxPwrPerRate(RTMP_ADAPTER *pAd) +{ + ULONG data, Adata, Gdata; + USHORT i, value, value2; + USHORT value_1, value_2, value_3, value_4; + INT Apwrdelta, Gpwrdelta; + UCHAR t1,t2,t3,t4; + BOOLEAN bApwrdeltaMinus = TRUE, bGpwrdeltaMinus = TRUE; + + + + + + + + + + +#ifdef MT7603 + if (IS_MT7603(pAd)) + { + mt7603_get_tx_pwr_per_rate(pAd); + return; + } +#endif /* MT7603 */ + + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return; + } + + + /* For default one, go here!! */ + { + + /* Get power delta for 20MHz and 40MHz.*/ + DBGPRINT(RT_DEBUG_TRACE, ("Txpower per Rate\n")); + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_DELTA, value2); + Apwrdelta = 0; + Gpwrdelta = 0; + + if ((value2 & 0xff) != 0xff) + { + if ((value2 & 0x80)) + Gpwrdelta = (value2&0xf); + + if ((value2 & 0x40)) + bGpwrdeltaMinus = FALSE; + else + bGpwrdeltaMinus = TRUE; + } + if ((value2 & 0xff00) != 0xff00) + { + if ((value2 & 0x8000)) + Apwrdelta = ((value2&0xf00)>>8); + + if ((value2 & 0x4000)) + bApwrdeltaMinus = FALSE; + else + bApwrdeltaMinus = TRUE; + } + DBGPRINT(RT_DEBUG_TRACE, ("Gpwrdelta = %x, Apwrdelta = %x .\n", Gpwrdelta, Apwrdelta)); + + + /* Get Txpower per MCS for 20MHz in 2.4G.*/ + + for (i=0; i<5; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4, value); + data = value; + + /* use value_1 ~ value_4 for code size reduce */ + value_1 = value&0xf; + value_2 = (value&0xf0)>>4; + value_3 = (value&0xf00)>>8; + value_4 = (value&0xf000)>>12; + + if (bApwrdeltaMinus == FALSE) + { + t1 = value_1+(Apwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = value_2+(Apwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = value_3+(Apwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = value_4+(Apwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if (value_1 > Apwrdelta) + t1 = value_1-(Apwrdelta); + else + t1 = 0; + if (value_2 > Apwrdelta) + t2 = value_2-(Apwrdelta); + else + t2 = 0; + if (value_3 > Apwrdelta) + t3 = value_3-(Apwrdelta); + else + t3 = 0; + if (value_4 > Apwrdelta) + t4 = value_4-(Apwrdelta); + else + t4 = 0; + } + Adata = t1 + (t2<<4) + (t3<<8) + (t4<<12); + if (bGpwrdeltaMinus == FALSE) + { + t1 = value_1+(Gpwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = value_2+(Gpwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = value_3+(Gpwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = value_4+(Gpwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if (value_1 > Gpwrdelta) + t1 = value_1-(Gpwrdelta); + else + t1 = 0; + if (value_2 > Gpwrdelta) + t2 = value_2-(Gpwrdelta); + else + t2 = 0; + if (value_3 > Gpwrdelta) + t3 = value_3-(Gpwrdelta); + else + t3 = 0; + if (value_4 > Gpwrdelta) + t4 = value_4-(Gpwrdelta); + else + t4 = 0; + } + Gdata = t1 + (t2<<4) + (t3<<8) + (t4<<12); + + RT28xx_EEPROM_READ16(pAd, EEPROM_TXPOWER_BYRATE_20MHZ_2_4G + i*4 + 2, value); + + /* use value_1 ~ value_4 for code size reduce */ + value_1 = value&0xf; + value_2 = (value&0xf0)>>4; + value_3 = (value&0xf00)>>8; + value_4 = (value&0xf000)>>12; + + if (bApwrdeltaMinus == FALSE) + { + t1 = value_1+(Apwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = value_2+(Apwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = value_3+(Apwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = value_4+(Apwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if (value_1 > Apwrdelta) + t1 = value_1-(Apwrdelta); + else + t1 = 0; + if (value_2 > Apwrdelta) + t2 = value_2-(Apwrdelta); + else + t2 = 0; + if (value_3 > Apwrdelta) + t3 = value_3-(Apwrdelta); + else + t3 = 0; + if (value_4 > Apwrdelta) + t4 = value_4-(Apwrdelta); + else + t4 = 0; + } + Adata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); + if (bGpwrdeltaMinus == FALSE) + { + t1 = value_1+(Gpwrdelta); + if (t1 > 0xf) + t1 = 0xf; + t2 = value_2+(Gpwrdelta); + if (t2 > 0xf) + t2 = 0xf; + t3 = value_3+(Gpwrdelta); + if (t3 > 0xf) + t3 = 0xf; + t4 = value_4+(Gpwrdelta); + if (t4 > 0xf) + t4 = 0xf; + } + else + { + if (value_1 > Gpwrdelta) + t1 = value_1-(Gpwrdelta); + else + t1 = 0; + if (value_2 > Gpwrdelta) + t2 = value_2-(Gpwrdelta); + else + t2 = 0; + if (value_3 > Gpwrdelta) + t3 = value_3-(Gpwrdelta); + else + t3 = 0; + if (value_4 > Gpwrdelta) + t4 = value_4-(Gpwrdelta); + else + t4 = 0; + } + Gdata |= ((t1<<16) + (t2<<20) + (t3<<24) + (t4<<28)); + data |= (value<<16); + + /* For 20M/40M Power Delta issue */ + pAd->Tx20MPwrCfgABand[i] = data; + pAd->Tx20MPwrCfgGBand[i] = data; + pAd->Tx40MPwrCfgABand[i] = Adata; + pAd->Tx40MPwrCfgGBand[i] = Gdata; + +#if defined(RTMP_MAC) || defined(RLT_MAC) + 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)); +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + } + } +} + + +/* + ======================================================================== + + Routine Description: + Read initial channel power parameters from EEPROM + + Arguments: + Adapter Pointer to our adapter + + Return Value: + None + + IRQL = PASSIVE_LEVEL + + Note: + + ======================================================================== +*/ +VOID RTMPReadChannelPwr(RTMP_ADAPTER *pAd) +{ + UINT32 i, choffset; + EEPROM_TX_PWR_STRUC Power; + EEPROM_TX_PWR_STRUC Power2; +#if (defined(RT30xx) && defined(RTMP_MAC_PCI)) || defined(RT3593) + UCHAR Tx0ALC = 0, Tx1ALC = 0, Tx0FinePowerCtrl = 0, Tx1FinePowerCtrl = 0; +#endif /* (defined(RT30xx) && defined(RTMP_MAC_PCI)) || defined(RT3593) */ + + /* Read Tx power value for all channels*/ + /* Value from 1 - 0x7f. Default value is 24.*/ + /* Power value : 2.4G 0x00 (0) ~ 0x1F (31)*/ + /* : 5.5G 0xF9 (-7) ~ 0x0F (15)*/ + + /* 0. 11b/g, ch1 - ch 14*/ + for (i = 0; i < 7; i++) + { + { /* Default routine. RT3070 and RT3370 run here. */ + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX_PWR_OFFSET + i * 2, Power.word); + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TX2_PWR_OFFSET + i * 2, Power2.word); + pAd->TxPower[i * 2].Channel = i * 2 + 1; + pAd->TxPower[i * 2 + 1].Channel = i * 2 + 2; + + pAd->TxPower[i * 2].Power = Power.field.Byte0; + if(!IS_RT3390(pAd)) // 3370 has different Tx power range + { + if ((Power.field.Byte0 > 31) || (Power.field.Byte0 < 0)) + pAd->TxPower[i * 2].Power = DEFAULT_RF_TX_POWER; + } + + pAd->TxPower[i * 2 + 1].Power = Power.field.Byte1; + if(!IS_RT3390(pAd)) // 3370 has different Tx power range + { + if ((Power.field.Byte1 > 31) || (Power.field.Byte1 < 0)) + pAd->TxPower[i * 2 + 1].Power = DEFAULT_RF_TX_POWER; + } + + if ((Power2.field.Byte0 > 31) || (Power2.field.Byte0 < 0)) + pAd->TxPower[i * 2].Power2 = DEFAULT_RF_TX_POWER; + else + pAd->TxPower[i * 2].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 > 31) || (Power2.field.Byte1 < 0)) + pAd->TxPower[i * 2 + 1].Power2 = DEFAULT_RF_TX_POWER; + else + pAd->TxPower[i * 2 + 1].Power2 = Power2.field.Byte1; + } + } + + + { + if (IS_RT5592(pAd)) + return; + + /* 1. U-NII lower/middle band: 36, 38, 40; 44, 46, 48; 52, 54, 56; 60, 62, 64 (including central frequency in BW 40MHz)*/ + /* 1.1 Fill up channel*/ + choffset = 14; + for (i = 0; i < 4; i++) + { + pAd->TxPower[3 * i + choffset + 0].Channel = 36 + i * 8 + 0; + pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 1].Channel = 36 + i * 8 + 2; + pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 2].Channel = 36 + i * 8 + 4; + pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; + } + + /* 1.2 Fill up power*/ + for (i = 0; i < 6; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + i * 2, Power.word); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + i * 2, Power2.word); + + if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; + + if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; + + if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; + } + + /* 2. HipperLAN 2 100, 102 ,104; 108, 110, 112; 116, 118, 120; 124, 126, 128; 132, 134, 136; 140 (including central frequency in BW 40MHz)*/ + /* 2.1 Fill up channel*/ + choffset = 14 + 12; + for (i = 0; i < 5; i++) + { + pAd->TxPower[3 * i + choffset + 0].Channel = 100 + i * 8 + 0; + pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 1].Channel = 100 + i * 8 + 2; + pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 2].Channel = 100 + i * 8 + 4; + pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; + } + pAd->TxPower[3 * 5 + choffset + 0].Channel = 140; + pAd->TxPower[3 * 5 + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * 5 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + /* 2.2 Fill up power*/ + for (i = 0; i < 8; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word); + + if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; + + if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; + + if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; + } + + /* 3. U-NII upper band: 149, 151, 153; 157, 159, 161; 165, 167, 169; 171, 173 (including central frequency in BW 40MHz)*/ + /* 3.1 Fill up channel*/ + choffset = 14 + 12 + 16; + /*for (i = 0; i < 2; i++)*/ + for (i = 0; i < 3; i++) + { + pAd->TxPower[3 * i + choffset + 0].Channel = 149 + i * 8 + 0; + pAd->TxPower[3 * i + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 1].Channel = 149 + i * 8 + 2; + pAd->TxPower[3 * i + choffset + 1].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * i + choffset + 2].Channel = 149 + i * 8 + 4; + pAd->TxPower[3 * i + choffset + 2].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * i + choffset + 2].Power2 = DEFAULT_RF_TX_POWER; + } + pAd->TxPower[3 * 3 + choffset + 0].Channel = 171; + pAd->TxPower[3 * 3 + choffset + 0].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * 3 + choffset + 0].Power2 = DEFAULT_RF_TX_POWER; + + pAd->TxPower[3 * 3 + choffset + 1].Channel = 173; + pAd->TxPower[3 * 3 + choffset + 1].Power = DEFAULT_RF_TX_POWER; + pAd->TxPower[3 * 3 + choffset + 1].Power2 = DEFAULT_RF_TX_POWER; + + /* 3.2 Fill up power*/ + /*for (i = 0; i < 4; i++)*/ + for (i = 0; i < 6; i++) + { + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX_PWR_OFFSET + (choffset - 14) + i * 2, Power.word); + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TX2_PWR_OFFSET + (choffset - 14) + i * 2, Power2.word); + + if ((Power.field.Byte0 < 16) && (Power.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power = Power.field.Byte0; + + if ((Power.field.Byte1 < 16) && (Power.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power = Power.field.Byte1; + + if ((Power2.field.Byte0 < 16) && (Power2.field.Byte0 >= -7)) + pAd->TxPower[i * 2 + choffset + 0].Power2 = Power2.field.Byte0; + + if ((Power2.field.Byte1 < 16) && (Power2.field.Byte1 >= -7)) + pAd->TxPower[i * 2 + choffset + 1].Power2 = Power2.field.Byte1; + } + } + + + /* 4. Print and Debug*/ + /*choffset = 14 + 12 + 16 + 7;*/ + choffset = 14 + 12 + 16 + 11; + + +} + + +VOID LoadTssiInfoFromEEPROM(RTMP_ADAPTER *pAd) +{ + EEPROM_TX_PWR_STRUC Power; + + Power.word = 0; + + /* Read TSSI reference and TSSI boundary for temperature compensation. This is ugly */ + /* 0. 11b/g*/ + { + /* these are tempature reference value (0x00 ~ 0xFE) + ex: 0x00 0x15 0x25 0x45 0x88 0xA0 0xB5 0xD0 0xF0 + TssiPlusBoundaryG [4] [3] [2] [1] [0] (smaller) + + TssiMinusBoundaryG[0] [1] [2] [3] [4] (larger) */ + { + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TSSI_BOUND1, Power.word); + pAd->TssiMinusBoundaryG[4] = Power.field.Byte0; + pAd->TssiMinusBoundaryG[3] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TSSI_BOUND2, Power.word); + pAd->TssiMinusBoundaryG[2] = Power.field.Byte0; + pAd->TssiMinusBoundaryG[1] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TSSI_BOUND3, Power.word); + pAd->TssiRefG = Power.field.Byte0; /* reference value [0] */ + pAd->TssiPlusBoundaryG[1] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TSSI_BOUND4, Power.word); + pAd->TssiPlusBoundaryG[2] = Power.field.Byte0; + pAd->TssiPlusBoundaryG[3] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_G_TSSI_BOUND5, Power.word); + pAd->TssiPlusBoundaryG[4] = Power.field.Byte0; + pAd->TxAgcStepG = Power.field.Byte1; + pAd->TxAgcCompensateG = 0; + pAd->TssiMinusBoundaryG[0] = pAd->TssiRefG; + pAd->TssiPlusBoundaryG[0] = pAd->TssiRefG; + + /* Disable TxAgc if the based value is not right*/ + if (pAd->TssiRefG == 0xff) + pAd->bAutoTxAgcG = FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE,("E2PROM: G Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n", + pAd->TssiMinusBoundaryG[4], pAd->TssiMinusBoundaryG[3], pAd->TssiMinusBoundaryG[2], pAd->TssiMinusBoundaryG[1], + pAd->TssiRefG, + pAd->TssiPlusBoundaryG[1], pAd->TssiPlusBoundaryG[2], pAd->TssiPlusBoundaryG[3], pAd->TssiPlusBoundaryG[4], + pAd->TxAgcStepG, pAd->bAutoTxAgcG)); + } + + /* 1. 11a*/ + { + { + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND1, Power.word); + pAd->TssiMinusBoundaryA[0][4] = Power.field.Byte0; + pAd->TssiMinusBoundaryA[0][3] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND2, Power.word); + pAd->TssiMinusBoundaryA[0][2] = Power.field.Byte0; + pAd->TssiMinusBoundaryA[0][1] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND3, Power.word); + pAd->TssiRefA = Power.field.Byte0; + pAd->TssiPlusBoundaryA[0][1] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND4, Power.word); + pAd->TssiPlusBoundaryA[0][2] = Power.field.Byte0; + pAd->TssiPlusBoundaryA[0][3] = Power.field.Byte1; + RT28xx_EEPROM_READ16(pAd, EEPROM_A_TSSI_BOUND5, Power.word); + pAd->TssiPlusBoundaryA[0][4] = Power.field.Byte0; + pAd->TxAgcStepA = Power.field.Byte1; + pAd->TxAgcCompensateA = 0; + pAd->TssiMinusBoundaryA[0][0] = pAd->TssiRefA; + pAd->TssiPlusBoundaryA[0][0] = pAd->TssiRefA; + + /* Disable TxAgc if the based value is not right*/ + if (pAd->TssiRefA == 0xff) + pAd->bAutoTxAgcA = FALSE; + } + + DBGPRINT(RT_DEBUG_TRACE,("E2PROM: A Tssi[-4 .. +4] = %d %d %d %d - %d -%d %d %d %d, step=%d, tuning=%d\n", + pAd->TssiMinusBoundaryA[0][4], pAd->TssiMinusBoundaryA[0][3], pAd->TssiMinusBoundaryA[0][2], pAd->TssiMinusBoundaryA[0][1], + pAd->TssiRefA, + pAd->TssiPlusBoundaryA[0][1], pAd->TssiPlusBoundaryA[0][2], pAd->TssiPlusBoundaryA[0][3], pAd->TssiPlusBoundaryA[0][4], + pAd->TxAgcStepA, pAd->bAutoTxAgcA)); + } +} + + +INT tx_pwr_comp_init(RTMP_ADAPTER *pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("%s()-->\n", __FUNCTION__)); + // TODO: shiang-7603, + if (IS_MT7603(pAd)) { + DBGPRINT(RT_DEBUG_TRACE, ("<--%s()\n", __FUNCTION__)); + return FALSE; + } + + +#ifdef RTMP_INTERNAL_TX_ALC + /* Initialize the desired TSSI table */ + RTMP_CHIP_ASIC_TSSI_TABLE_INIT(pAd); +#endif /* RTMP_INTERNAL_TX_ALC */ + +#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 */ + + return TRUE; +} + +INT32 get_low_mid_hi_index(UINT8 channel) +{ + INT32 index = G_BAND_LOW; + + if (channel <= 14) { + if (channel >= 1 && channel <= 5) + index = G_BAND_LOW; + else if (channel >= 6 && channel <= 10) + index = G_BAND_MID; + else if (channel >= 11 && channel <= 14) + index = G_BAND_HI; + else + DBGPRINT(RT_DEBUG_ERROR, ("illegal channel(%d)\n", channel)); + } else { + if (channel >= 184 && channel <= 188) + index = A_BAND_LOW; + else if (channel >= 192 && channel <= 196) + index = A_BAND_HI; + else if (channel >= 36 && channel <= 42) + index = A_BAND_LOW; + else if (channel >= 44 && channel <= 48) + index = A_BAND_HI; + else if (channel >= 52 && channel <= 56) + index = A_BAND_LOW; + else if (channel >= 58 && channel <= 64) + index = A_BAND_HI; + else if (channel >= 98 && channel <= 104) + index = A_BAND_LOW; + else if (channel >= 106 && channel <= 114) + index = A_BAND_HI; + else if (channel >= 116 && channel <= 128) + index = A_BAND_LOW; + else if (channel >= 130 && channel <= 144) + index = A_BAND_HI; + else if (channel >= 149 && channel <= 156) + index = A_BAND_LOW; + else if (channel >= 157 && channel <= 165) + index = A_BAND_HI; + else + DBGPRINT(RT_DEBUG_ERROR, ("illegal channel(%d)\n", channel)); + } + + return index; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/uapsd.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/uapsd.c new file mode 100644 index 000000000..1e7344d2d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/uapsd.c @@ -0,0 +1,2513 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + + +#define MODULE_WMM_UAPSD +#include "rt_config.h" + +#ifdef UAPSD_SUPPORT +#include "uapsd.h" + +/*#define UAPSD_DEBUG */ + +/* used to enable or disable UAPSD power save queue maintain mechanism */ +UCHAR gUAPSD_FlgNotQueueMaintain; + +#ifdef UAPSD_DEBUG +UINT32 gUAPSD_SP_CloseAbnormalNum; +#endif /* UAPSD_DEBUG */ + +#ifdef UAPSD_TIMING_RECORD_FUNC +/* all unit: us */ + +UCHAR gUAPSD_TimingFlag; +UINT32 gUAPSD_TimingIndexUapsd; +UINT32 gUAPSD_TimingLoopIndex; + +/* ISR start timestamp */ +UINT64 gUAPSD_TimingIsr[UAPSD_TIMING_RECORD_MAX]; + +/* Tasklet start timestamp */ +UINT64 gUAPSD_TimingTasklet[UAPSD_TIMING_RECORD_MAX]; + +UINT64 gUAPSD_TimingTrgRcv[UAPSD_TIMING_RECORD_MAX]; +UINT64 gUAPSD_TimingMov2Tx[UAPSD_TIMING_RECORD_MAX]; +UINT64 gUAPSD_TimingTx2Air[UAPSD_TIMING_RECORD_MAX]; + +UINT32 gUAPSD_TimingSumIsr2Tasklet; +UINT32 gUAPSD_TimingSumTrig2Txqueue; +UINT32 gUAPSD_TimingSumTxqueue2Air; +#endif /* UAPSD_TIMING_RECORD_FUNC */ + +#ifdef LINUX +#define UAPSD_SEM_LOCK(__UAPSDEOSPLock, __flags2) \ +{ \ + if (irqs_disabled()) \ + { \ + RTMP_INT_LOCK((__UAPSDEOSPLock), __flags2); \ + } \ + else \ + { \ + RTMP_SEM_LOCK((__UAPSDEOSPLock)); \ + } \ +} + +#define UAPSD_SEM_UNLOCK(__UAPSDEOSPLock, __flags2) \ +{ \ + if (irqs_disabled()) \ + { \ + RTMP_INT_UNLOCK((__UAPSDEOSPLock), __flags2); \ + } \ + else \ + { \ + RTMP_SEM_UNLOCK((__UAPSDEOSPLock)); \ + } \ +} +#else +#define UAPSD_SEM_LOCK(__UAPSDEOSPLock, __flags2) \ +{ \ + __flags2 = 0; \ + RTMP_SEM_LOCK((__UAPSDEOSPLock)); \ +} + +#define UAPSD_SEM_UNLOCK(__UAPSDEOSPLock, __flags2) \ +{ \ + __flags2 = 0; \ + RTMP_SEM_UNLOCK((__UAPSDEOSPLock)); \ +} +#endif + + +/* +======================================================================== +Routine Description: + UAPSD Module Init. + +Arguments: + pAd Pointer to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_Init(RTMP_ADAPTER *pAd) +{ + /* allocate a lock resource for SMP environment */ + NdisAllocateSpinLock(pAd, &pAd->UAPSDEOSPLock); + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> allocate a spinlock!\n")); +#endif /* UAPSD_DEBUG */ + +#ifdef UAPSD_DEBUG + gUAPSD_SP_CloseAbnormalNum = 0; +#endif /* UAPSD_DEBUG */ + +#ifdef UAPSD_TIMING_RECORD_FUNC + gUAPSD_TimingFlag = 0; /* default: DISABLE */ + gUAPSD_TimingIndexUapsd = 0; + gUAPSD_TimingLoopIndex = 0; + + + gUAPSD_TimingSumIsr2Tasklet = 0; + gUAPSD_TimingSumTrig2Txqueue = 0; + gUAPSD_TimingSumTxqueue2Air = 0; +#endif /* UAPSD_TIMING_RECORD_FUNC */ +} + + +/* +======================================================================== +Routine Description: + UAPSD Module Release. + +Arguments: + pAd Pointer to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_Release(RTMP_ADAPTER *pAd) +{ + /* free the lock resource for SMP environment */ + NdisFreeSpinLock(&pAd->UAPSDEOSPLock); + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> release a spinlock!\n")); +#endif /* UAPSD_DEBUG */ +} /* End of UAPSD_Release */ + + +/* +======================================================================== +Routine Description: + Check if ASIC can enter sleep mode. Not software sleep. + +Arguments: + pAd Pointer to our adapter + +Return Value: + None + +Note: +======================================================================== +*/ +VOID RtmpAsicSleepHandle(RTMP_ADAPTER *pAd) +{ +} + + + +/* +======================================================================== +Routine Description: + Close current Service Period. + +Arguments: + pAd Pointer to our adapter + pEntry Close the SP of the entry + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_SP_Close(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + ULONG flags = 0; + if ((pEntry != NULL) && (pEntry->PsMode == PWR_SAVE)) + { + UAPSD_SEM_LOCK(&pAd->UAPSDEOSPLock, flags); + + if (pEntry->bAPSDFlagSPStart != 0) + { + /* SP is started for the station */ +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_UAPSD, ("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 | DBG_FUNC_UAPSD, ("uapsd> [3] Free EOSP (UP = %d)!\n", + RTMP_GET_PACKET_UP( + QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame)))); +#endif /* UAPSD_DEBUG */ + + RELEASE_NDIS_PACKET(pAd, + QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame), + NDIS_STATUS_FAILURE); + pEntry->pUAPSDEOSPFrame = NULL; + } + + /* re-init SP related parameters */ + pEntry->UAPSDTxNum = 0; + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagEOSPOK = 0; + pEntry->bAPSDFlagLegacySent = 0; + UAPSD_SP_END(pAd, pEntry); + + } + + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + } +} + + +/* +======================================================================== +Routine Description: + Check if the SP for entry is closed. + +Arguments: + pAd Pointer to our adapter + pEntry the peer entry + +Return Value: + None + +Note: +======================================================================== +*/ +BOOLEAN UAPSD_SP_IsClosed(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + BOOLEAN FlgIsSpClosed = TRUE; + ULONG flags = 0; + + UAPSD_SEM_LOCK(&pAd->UAPSDEOSPLock, flags); + + if ((pEntry) && + (pEntry->PsMode == PWR_SAVE) && + (pEntry->bAPSDFlagSPStart != 0) + ) + FlgIsSpClosed = FALSE; + + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + + return FlgIsSpClosed; +} + +/* +======================================================================== +Routine Description: + Deliver all queued packets. + +Arguments: + pAd Pointer to our adapter + *pEntry STATION + +Return Value: + None + +Note: + SMP protection by caller for packet enqueue. +======================================================================== +*/ +VOID UAPSD_AllPacketDeliver(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + QUEUE_HEADER *pQueApsd; + PQUEUE_ENTRY pQueEntry; + UCHAR QueIdList[WMM_NUM_OF_AC] = { QID_AC_BE, QID_AC_BK, + QID_AC_VI, QID_AC_VO }; + INT32 IdAc, QueId; /* must be signed, can not be unsigned */ + STA_TR_ENTRY *tr_entry = NULL; + ULONG flags = 0; + + UAPSD_SEM_LOCK(&pAd->UAPSDEOSPLock, flags); + + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + /* 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; + } + + if (rtmp_enq_req(pAd, QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame), QueId, tr_entry, FALSE, NULL) == FALSE) + RELEASE_NDIS_PACKET(pAd, QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame), NDIS_STATUS_FAILURE); + + pEntry->pUAPSDEOSPFrame = NULL; + pEntry->UAPSDTxNum = 0; + } + + /* deliver ALL U-APSD packets from AC3 to AC0 (AC0 to AC3 is also ok) */ + for(IdAc=(WMM_NUM_OF_AC-1); IdAc>=0; IdAc--) + { + pQueApsd = &(pEntry->UAPSDQueue[IdAc]); + QueId = QueIdList[IdAc]; + + while(pQueApsd->Head) + { + pQueEntry = RemoveHeadQueue(pQueApsd); + + if (rtmp_enq_req(pAd, QUEUE_ENTRY_TO_PACKET(pQueEntry), QueId, tr_entry, FALSE, NULL) == FALSE) + RELEASE_NDIS_PACKET(pAd, QUEUE_ENTRY_TO_PACKET(pQueEntry), NDIS_STATUS_FAILURE); + } + } + + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); +} + + +/* +======================================================================== +Routine Description: + Parse the UAPSD field in WMM element in (re)association request frame. + +Arguments: + pAd Pointer to our adapter + *pEntry STATION + *pElm QoS information field + FlgApsdCapable TRUE: Support UAPSD + +Return Value: + None + +Note: + No protection is needed. + + 1. Association -> TSPEC: + use static UAPSD settings in Association + update UAPSD settings in TSPEC + + 2. Association -> TSPEC(11r) -> Reassociation: + update UAPSD settings in TSPEC + backup static UAPSD settings in Reassociation + + 3. Association -> Reassociation: + update UAPSD settings in TSPEC + backup static UAPSD settings in Reassociation +======================================================================== +*/ +VOID UAPSD_AssocParse( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR *pElm, + IN BOOLEAN FlgApsdCapable) +{ + PQBSS_STA_INFO_PARM pQosInfo; + UCHAR UAPSD[4]; + UINT32 IdApsd; + + + /* check if the station enables UAPSD function */ + if ((pEntry) && (FlgApsdCapable == TRUE)) + { + /* backup its UAPSD parameters */ + pQosInfo = (PQBSS_STA_INFO_PARM) pElm; + + + UAPSD[QID_AC_BE] = pQosInfo->UAPSD_AC_BE; + UAPSD[QID_AC_BK] = pQosInfo->UAPSD_AC_BK; + UAPSD[QID_AC_VI] = pQosInfo->UAPSD_AC_VI; + UAPSD[QID_AC_VO] = pQosInfo->UAPSD_AC_VO; + + pEntry->MaxSPLength = pQosInfo->MaxSPLength; + + DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_UAPSD, ("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 | DBG_FUNC_UAPSD, ("apsd> MaxSPLength = %d\n", + pEntry->MaxSPLength)); + + /* use static UAPSD setting of association request frame */ + for(IdApsd=0; IdApsd<4; IdApsd++) + { + pEntry->bAPSDCapablePerAC[IdApsd] = UAPSD[IdApsd]; + pEntry->bAPSDDeliverEnabledPerAC[IdApsd] = UAPSD[IdApsd]; + + } + + if ((pEntry->bAPSDCapablePerAC[QID_AC_BE] == 0) && + (pEntry->bAPSDCapablePerAC[QID_AC_BK] == 0) && + (pEntry->bAPSDCapablePerAC[QID_AC_VI] == 0) && + (pEntry->bAPSDCapablePerAC[QID_AC_VO] == 0)) + { + CLIENT_STATUS_CLEAR_FLAG(pEntry, fCLIENT_STATUS_APSD_CAPABLE); + } + else + { + CLIENT_STATUS_SET_FLAG(pEntry, fCLIENT_STATUS_APSD_CAPABLE); + } + + if ((pEntry->bAPSDCapablePerAC[QID_AC_BE] == 1) && + (pEntry->bAPSDCapablePerAC[QID_AC_BK] == 1) && + (pEntry->bAPSDCapablePerAC[QID_AC_VI] == 1) && + (pEntry->bAPSDCapablePerAC[QID_AC_VO] == 1)) + { + /* all AC are U-APSD */ + DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_UAPSD, ("apsd> all AC are UAPSD\n")); + pEntry->bAPSDAllAC = 1; + } + else + { + /* at least one AC is not U-APSD */ + DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_UAPSD, ("apsd> at least one AC is not UAPSD %d %d %d %d\n", + pEntry->bAPSDCapablePerAC[QID_AC_BE], + pEntry->bAPSDCapablePerAC[QID_AC_BK], + pEntry->bAPSDCapablePerAC[QID_AC_VI], + pEntry->bAPSDCapablePerAC[QID_AC_VO])); + pEntry->bAPSDAllAC = 0; + } + + pEntry->VirtualTimeout = 0; + + DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_UAPSD, ("apsd> MaxSPLength = %d\n", pEntry->MaxSPLength)); + } +} + + +/* +======================================================================== +Routine Description: + Enqueue a UAPSD packet. + +Arguments: + pAd Pointer to our adapter + *pEntry STATION + pPacket UAPSD dnlink packet + IdAc UAPSD AC ID (0 ~ 3) + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_PacketEnqueue( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN PNDIS_PACKET pPacket, + IN UINT32 IdAc, + IN BOOLEAN bFromHead) +{ + /* + 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; + ULONG flags = 0; + + + /* 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; + } + + 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(%d) 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 */ + UAPSD_SEM_LOCK(&pAd->UAPSDEOSPLock, flags); + if (bFromHead) + InsertHeadQueue(pQueUapsd, PACKET_TO_QUEUE_ENTRY(pPacket)) + else + InsertTailQueue(pQueUapsd, PACKET_TO_QUEUE_ENTRY(pPacket)); + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + +#ifdef UAPSD_DEBUG + if (RTMP_GET_PACKET_MGMT_PKT(pPacket) == 1) + { + DBGPRINT(RT_DEBUG_TRACE, ("ps> mgmt to uapsd queue...\n")); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, + ("ps> data (0x%08lx) (AC%d) to uapsd queue (num of pkt = %u)...\n", + (ULONG)pPacket, IdAc, + pQueUapsd->Number)); + } +#endif /* UAPSD_DEBUG */ + } +} + + +#ifdef RTMP_MAC_PCI +/* +======================================================================== +Routine Description: + Check if we need to close current SP. + +Arguments: + pAd Pointer to our adapter + pPacket Completed TX packet + pDstMac Destinated MAC address + +Return Value: + None + +Note: + 1. We need to call the function in TxDone ISR. + 2. SMP protection by caller for packet enqueue. +======================================================================== +*/ +VOID UAPSD_SP_PacketCheck( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR *pDstMac) +{ + MAC_TABLE_ENTRY *pEntry; + HEADER_802_11 *pHeader; + UINT16 QueId = 0; + UCHAR FlgEosp; + UINT8 TXWISize = pAd->chipCap.TXWISize; + STA_TR_ENTRY *tr_entry = NULL; + UCHAR PktCB8 = 0; +#ifdef LINUX + unsigned long flags2 = 0; +#endif /* LINUX */ + +#ifdef CONFIG_ATE + /* Nothing to do in ATE mode */ + if (ATE_ON(pAd)) + return; +#endif /* CONFIG_ATE */ + + if (pPacket == NULL) + return; + + PktCB8 = (UCHAR)PACKET_CB(pPacket, 8); + + /* + NOTE: no aggregation function in U-APSD so dont care about + pTxD->pNextSkb + */ + + if ((RTMP_GET_PACKET_EOSP(pPacket) == FALSE) && + (PktCB8 == 0xFF)) + { + /* + This is non-EOSP null frame. Ignore it. + */ + return; + } + + /* check if the packet is a U-APSD packet */ + if (RTMP_GET_PACKET_UAPSD_Flag(pPacket) == FALSE) + return; + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_UAPSD, ("\nuapsd> ----> %s(%d)\n", + __FUNCTION__, __LINE__)); +#endif /* UAPSD_DEBUG */ + + + /* + Check if all U-APSD packets have been transmitted except + the EOSP packet because we must sure the EOSP packet is + transmitted at last. + */ + + /* get RA STATION entry */ + pEntry = NULL; + if (RTMP_GET_PACKET_MGMT_PKT(pPacket) == 1) + { + /* + Currently, our QoS Null frame is sent through MMRequest(), + in the function, only SDPtr0 is used, SDPtr1 is not used, + so pDstMac must be got from skb->data + TXWI_SIZE + */ + pDstMac = GET_OS_PKT_DATAPTR(pPacket) + TXWISize; + } + + pHeader = (HEADER_802_11 *)(pDstMac); + + if (pHeader != NULL) + { + if (((pHeader->FC.Type == FC_TYPE_DATA) && + (pHeader->FC.SubType == SUBTYPE_QOS_NULL)) || + ((pHeader->FC.Type == FC_TYPE_MGMT) && + (pHeader->FC.SubType == SUBTYPE_ACTION))) + { + /* the packet is a QoS NULL frame */ + UAPSD_QoSNullTxMgmtTxDoneHandle(pAd, pPacket, pDstMac, TRUE); + return; + } + + /* Addr1 = receiver address */ + pEntry = MacTableLookup(pAd, pHeader->Addr1); + } + + if(pEntry != NULL) + { + if (pEntry->wdev->UapsdInfo.bAPSDCapable == FALSE) + { + return; + } + } + + FlgEosp = FALSE; + + UAPSD_SEM_LOCK(&pAd->UAPSDEOSPLock, flags2); + + if ((pEntry != NULL) && (pEntry->bAPSDFlagSpRoughUse != 0)) + { + /* Note: UAPSDTxNum does NOT include the EOSP packet */ + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; +#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; + } + + if (rtmp_enq_req(pAd, QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame), QueId, tr_entry, TRUE, NULL) == FALSE) + { + /* May need to reschedule the EOSP if enq fail */ + RELEASE_NDIS_PACKET(pAd, QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame), NDIS_STATUS_FAILURE); + pEntry->bAPSDFlagEOSPOK = 0; + pEntry->bAPSDFlagLegacySent = 0; + UAPSD_SP_END(pAd, pEntry); + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags2); + return; + } + + if (tr_entry->tx_queue[QueId].Number != 1) + { + DBGPRINT(RT_DEBUG_ERROR, ("uapsd> %s(%d) tx_queue[%d].Number = %d (shall be 1)!!!\n", + __FUNCTION__, __LINE__, QueId, tr_entry->tx_queue[QueId].Number)); + } + + pEntry->pUAPSDEOSPFrame = NULL; + FlgEosp = TRUE; + + /* + The EOSP frame will be put into ASIC to tx in + RTMPHandleTxRingDmaDoneInterrupt(), not + the function. + */ + } + } + + /* a UAPSD frame is transmitted so decrease the counter */ + pEntry->UAPSDTxNum --; + } + else + { + /* UAPSDTxNum == 0 so the packet is the EOSP packet */ + + if (pEntry->bAPSDFlagSPStart != 0) + { + UINT32 IntSrcReg, INT_RX = 0, int_src = 0; + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + INT_RX = MT_INT_RX_DATA; + int_src = MT_INT_SOURCE_CSR; + } +#endif /* MT_MAC */ +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + INT_RX = RLT_INT_RX_DATA; + int_src = INT_SOURCE_CSR; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + INT_RX = RTMP_INT_RX; + int_src = INT_SOURCE_CSR; + } +#endif /* RTMP_MAC */ + /* activate RX Done handle thread */ + + /* + Maybe some uplink packets are received between + EOSP frame start transmission and end + transmssion, we must forward them first or we + will regard them as new trigger frames. + + We will clear all STATION bAPSDFlagSPStart flag + in RX done handler when U-APSD function is + enabled. + + I dont want to use another flag to check if do + the job because I also need a spin lock to + protect the flag, the protection will cause TX + DONE & RX DONE relation. + */ + + /* 1: means EOSP is sent to the peer so we can close current SP */ + + /* + We can not guarantee RTMPHandleRxDoneInterrupt() + will be called before + RTMPHandleTxRingDmaDoneInterrupt() in RTMPIsr() + */ + RTMP_IO_READ32(pAd, int_src, &IntSrcReg); + + if ((IntSrcReg & INT_RX) == 0) + { + /* No any received packet exists so no any uplink packet exists. */ + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagEOSPOK = 0; + pEntry->bAPSDFlagLegacySent = 0; + UAPSD_SP_END(pAd, pEntry); + } + else + { + /* + A received packet exists we will handle it + in RTMPIsr(), dont worry. + But we only handle max 16 received packets + in RTMPHandleRxDoneInterrupt so risk exists. + */ + pEntry->bAPSDFlagEOSPOK = 1; + } + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> close SP in SP_PacketCheck()!\n")); +#endif /* UAPSD_DEBUG */ + } + } + } + + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags2); + + /* 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! + */ + if ((pAd->chipCap.hif_type == HIF_RLT) + || (pAd->chipCap.hif_type == HIF_RTMP)) + RTMP_OS_TASKLET_SCHE(&pCookie->uapsd_eosp_sent_task); +#ifdef MT_PS + else + { + RTMPDeQueuePacket(pAd, TRUE, QueId, pEntry->wcid, 1); + } +#endif /* MT_PS */ + } +} + + +/* +======================================================================== +Routine Description: + Handle QoS Null Frame Tx Done or Management Tx Done interrupt. + +Arguments: + pAd Pointer to our adapter + pPacket Completed TX packet + pDstMac Destinated MAC address + +Return Value: + None + +Note: + Only for PCI-based device. +======================================================================== +*/ +VOID UAPSD_QoSNullTxMgmtTxDoneHandle( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR *pDstMac, + IN BOOLEAN FlgIsLocked) +{ + HEADER_802_11 *pHeader; + MAC_TABLE_ENTRY *pEntry; + UINT32 IntSrcReg, INT_RX = 0, int_src = 0; + ULONG flags = 0; + + if (pPacket == NULL) + return; + + /* check if the packet is a U-APSD packet, must be QoS Null frame */ + if (RTMP_GET_PACKET_UAPSD_Flag(pPacket) != TRUE) + return; + + /* check if the packet sub type is QoS Null */ + if (pDstMac == NULL) + return; + + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + INT_RX = MT_INT_RX_DATA; + int_src = MT_INT_SOURCE_CSR; + } +#endif /* MT_MAC */ +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + INT_RX = RLT_INT_RX_DATA; + int_src = INT_SOURCE_CSR; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + INT_RX = RTMP_INT_RX; + int_src = INT_SOURCE_CSR; + } +#endif /* RTMP_MAC */ + + pHeader = (HEADER_802_11 *)pDstMac; + + /* find the destination STATION */ + pEntry = MacTableLookup(pAd, pHeader->Addr1); + + if ((pHeader->FC.Type == FC_TYPE_DATA) && + (pHeader->FC.SubType == SUBTYPE_QOS_NULL)) + { + /* + Currently, QoS Null type is only used in UAPSD mechanism + and no any UAPSD data packet exists + */ + UAPSD_SEM_LOCK(&pAd->UAPSDEOSPLock, flags); + + if ((pEntry != NULL) && + (pEntry->bAPSDFlagSpRoughUse != 0) && + (pEntry->bAPSDFlagSPStart != 0)) + { + /* SP is started for the station */ + + if (pEntry->pUAPSDEOSPFrame != NULL) + { + /* SP will be closed, should not have EOSP frame */ + RELEASE_NDIS_PACKET(pAd, + QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame), + NDIS_STATUS_FAILURE); + pEntry->pUAPSDEOSPFrame = NULL; + } + + pEntry->UAPSDTxNum = 0; + + /* check if rx done interrupt exists */ + RTMP_IO_READ32(pAd, int_src, &IntSrcReg); + + if ((IntSrcReg & INT_RX) == 0) + { + /* no any new uplink packet is received */ + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagEOSPOK = 0; + pEntry->bAPSDFlagLegacySent = 0; + UAPSD_SP_END(pAd, pEntry); + } + else + { + /* + A new uplink packet is received so check if the uplink + packet is transmitted from the station and close SP + in RxDone(). + */ + pEntry->bAPSDFlagEOSPOK = 1; + } + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> close SP in QoSNullTxDoneHandle()!\n")); +#endif /* UAPSD_DEBUG */ + } + + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + } + else if ((pHeader->FC.Type == FC_TYPE_MGMT) && + (pHeader->FC.SubType == SUBTYPE_ACTION)) + { + UINT16 QueId = 0; + + + UAPSD_SEM_LOCK(&pAd->UAPSDEOSPLock, flags); + + if ((pEntry != NULL) && + (pEntry->bAPSDFlagSpRoughUse != 0) && + (pEntry->bAPSDFlagSPStart != 0)) + { + BOOLEAN FlgEosp = FALSE; + STA_TR_ENTRY *tr_entry = NULL; + + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + /* Note: UAPSDTxNum does NOT include the EOSP packet */ +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> a ps mgmt frame is DMA done(Num = %d)!\n", + pEntry->UAPSDTxNum)); +#endif /* UAPSD_DEBUG */ + + if (pEntry->UAPSDTxNum > 0) + { + /* some UAPSD packets are not yet transmitted */ + + if (pEntry->UAPSDTxNum == 1) + { + /* this is the last UAPSD packet */ + if (pEntry->pUAPSDEOSPFrame != NULL) + { + /* so transmit its EOSP frame */ + PNDIS_PACKET pPkt; + + + pPkt = QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame); + QueId = RTMP_GET_PACKET_UAPSD_QUE_ID(pPkt); + + if (QueId > QID_AC_VO) + { + /* should not be here, only for sanity */ + QueId = QID_AC_BE; + } + + if (rtmp_enq_req(pAd, QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame), QueId, tr_entry, FlgIsLocked, NULL) == FALSE) + { + RELEASE_NDIS_PACKET(pAd, QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame), NDIS_STATUS_FAILURE); + pEntry->bAPSDFlagEOSPOK = 0; + pEntry->bAPSDFlagLegacySent = 0; + UAPSD_SP_END(pAd, pEntry); + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + return; + } + + pEntry->pUAPSDEOSPFrame = NULL; + FlgEosp = TRUE; + + /* + The EOSP frame will be put into ASIC to tx + in RTMPHandleTxRingDmaDoneInterrupt(), + not the function. + */ + } + } + + /* a UAPSD frame is transmitted so counter -- */ + pEntry->UAPSDTxNum --; + } + else + { + /* UAPSDTxNum == 0 so the packet is the EOSP packet */ + + if (pEntry->bAPSDFlagSPStart != 0) + { + /* + Activate RX Done handle thread + + Maybe some uplink packets are received between + EOSP frame start transmission and end + transmssion, we must forward them first or we + will regard them as new trigger frames. + + We will clear all STATION bAPSDFlagSPStart flag + in RX done handler when U-APSD function is + enabled. + + I dont want to use another flag to check if do + the job because I also need a spin lock to + protect the flag, the protection will cause TX + DONE & RX DONE relation. + + 1: means EOSP is sent to the peer so we can close + current SP. + + We can not guarantee RTMPHandleRxDoneInterrupt() + will be called before + RTMPHandleTxRingDmaDoneInterrupt() in RTMPIsr(). + */ + UINT32 INT_RX = 0, int_csr = 0; + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + INT_RX = MT_INT_RX_DATA; + int_csr = MT_INT_SOURCE_CSR; + } +#endif /* MT_MAC */ +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + INT_RX = RLT_INT_RX_DATA; + int_csr = INT_SOURCE_CSR; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + INT_RX = RTMP_INT_RX; + int_csr = INT_SOURCE_CSR; + } +#endif /* RTMP_MAC */ + + RTMP_IO_READ32(pAd, int_csr, &IntSrcReg); + if ((IntSrcReg & INT_RX) == 0) + { + /* + No any received pkt exists so no any uplink pkt exists. + */ + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagEOSPOK = 0; + pEntry->bAPSDFlagLegacySent = 0; + UAPSD_SP_END(pAd, pEntry); + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> close SP2 in QoSNullTxMgmtTxDoneHandle()!\n")); +#endif /* UAPSD_DEBUG */ + } + else + { + /* + A received packet exists we will handle it + in RTMPIsr(), dont worry. + But we only handle max 16 received packets + in RTMPHandleRxDoneInterrupt so risk exists. + */ + pEntry->bAPSDFlagEOSPOK = 1; + } + } + } + + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + + /* maybe transmit the EOSP frame */ + if (FlgEosp == TRUE) + { + POS_COOKIE pCookie = (POS_COOKIE) pAd->OS_Cookie; + + /* + Too many functions call NICUpdateFifoStaCounters() and + NICUpdateFifoStaCounters() will call UAPSD_SP_AUE_Handle(), + if we call RTMPDeQueuePacket() here, double-IRQ LOCK will + occur. so we need to activate a tasklet to send EOSP frame. + + ex: RTMPDeQueuePacket() --> RTMPFreeTXDUponTxDmaDone() --> + NICUpdateFifoStaCounters() --> UAPSD_SP_AUE_Handle() --> + RTMPDeQueuePacket() ERROR! or + + RTMPHandleTxRingDmaDoneInterrupt() --> + RTMP_IRQ_LOCK() --> + RTMPFreeTXDUponTxDmaDone() --> + NICUpdateFifoStaCounters() --> + UAPSD_SP_AUE_Handle() --> + RTMPDeQueuePacket() --> + DEQUEUE_LOCK() --> + RTMP_IRQ_LOCK() ERROR! + */ + if ((pAd->chipCap.hif_type == HIF_RLT) + || (pAd->chipCap.hif_type == HIF_RTMP)) + RTMP_OS_TASKLET_SCHE(&pCookie->uapsd_eosp_sent_task); +#ifdef MT_PS + else + { + RTMPDeQueuePacket(pAd, TRUE, QueId, pEntry->wcid, 1); + } +#endif /* MT_PS */ + } + } + else + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + } +} +#endif /* RTMP_MAC_PCI */ + + +/* +======================================================================== +Routine Description: + Maintenance our UAPSD PS queue. Release all queued packet if timeout. + +Arguments: + pAd Pointer to our adapter + *pEntry STATION + +Return Value: + None + +Note: + If in RT2870, pEntry can not be removed during UAPSD_QueueMaintenance() +======================================================================== +*/ +VOID UAPSD_QueueMaintenance(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + QUEUE_HEADER *pQue; + UINT32 IdAc; + BOOLEAN FlgUapsdPkt, FlgEospPkt; + STA_TR_ENTRY *tr_entry; + ULONG flags = 0; + + // TODO: shiang-usw, revise to fix it!!!! + //DBGPRINT(RT_DEBUG_OFF, ("%s(): Shiang-USW, Into UAPSD QueueHandler, not finish yet!\n", __FUNCTION__)); + return; + + if (gUAPSD_FlgNotQueueMaintain) + return; + + if (pEntry->PsMode != PWR_SAVE) + return; /* UAPSD packet only for power-save STA, not active STA */ + + /* init */ + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + UAPSD_SEM_LOCK(&pAd->UAPSDEOSPLock, flags); + + pQue = pEntry->UAPSDQueue; + FlgUapsdPkt = 0; + FlgEospPkt = 0; + + /* check if more than one U-APSD packets exists */ + for(IdAc=0; IdAcpUAPSDEOSPFrame != NULL) + FlgEospPkt = 1; + + /* check if any queued UAPSD packet exists */ + if (FlgUapsdPkt || FlgEospPkt) + { + + pEntry->UAPSDQIdleCount ++; + if (pEntry->UAPSDQIdleCount > pAd->MacTab.MsduLifeTime) + { + if (FlgUapsdPkt) + { + DBGPRINT(RT_DEBUG_TRACE, + ("uapsd> UAPSD queue timeout! clean all queued frames...\n")); + } + + if (FlgEospPkt) + { + DBGPRINT(RT_DEBUG_TRACE, + ("uapsd> UAPSD EOSP timeout! clean the EOSP frame!\n")); + } + + /* UAPSDQIdleCount will be 0 after trigger frame is received */ + + /* clear all U-APSD packets */ + if (FlgUapsdPkt) + { + for(IdAc=0; IdAcUAPSDTxNum = 0; + + if (pEntry->pUAPSDEOSPFrame != NULL) + { + RELEASE_NDIS_PACKET(pAd, + QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame), + NDIS_STATUS_FAILURE); + pEntry->pUAPSDEOSPFrame = NULL; + } + + pEntry->bAPSDFlagEOSPOK = 0; + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagLegacySent = 0; + UAPSD_SP_END(pAd, pEntry); + + /* clear idle counter */ + pEntry->UAPSDQIdleCount = 0; + +#ifdef CONFIG_AP_SUPPORT + /* check TIM bit */ + if (tr_entry->ps_queue.Number == 0) + { + WLAN_MR_TIM_BIT_CLEAR(pAd, pEntry->func_tb_idx, pEntry->Aid); + } +#endif /* CONFIG_AP_SUPPORT */ + } + + } + else + { + /* clear idle counter */ + pEntry->UAPSDQIdleCount = 0; + } + + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + + /* virtual timeout handle */ + RTMP_PS_VIRTUAL_TIMEOUT_HANDLE(pEntry); +} + + +/* +======================================================================== +Routine Description: + Close SP in Tx Done, not Tx DMA Done. + +Arguments: + pAd Pointer to our adapter + pEntry destination entry + FlgSuccess 0:tx success, 1:tx fail + +Return Value: + None + +Note: + For RT28xx series, for packetID=0 or multicast frame, no statistics + count can be got, ex: ARP response or DHCP packets, we will use + low rate to set (CCK, MCS=0=packetID). + So SP will not be close until UAPSD_EPT_SP_INT timeout. + + So if the tx rate is 1Mbps for a entry, we will use DMA done, not + use UAPSD_SP_AUE_Handle(). +======================================================================== +*/ +VOID UAPSD_SP_AUE_Handle( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR FlgSuccess) +{ +#ifdef UAPSD_SP_ACCURATE + USHORT QueId = 0; + STA_TR_ENTRY *tr_entry = NULL; + + if (pEntry == NULL) + return; + + if (pEntry->PsMode == PWR_ACTIVE) + { +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> aux: Station actives! Close SP!\n")); +#endif /* UAPSD_DEBUG */ + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagEOSPOK = 0; + UAPSD_SP_END(pAd, pEntry); + return; + } + + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + + if (pEntry->PsMode == PWR_SAVE) + { + BOOLEAN FlgEosp; + ULONG flags = 0; + + UAPSD_SEM_LOCK(&pAd->UAPSDEOSPLock, flags); + + if (pEntry->bAPSDFlagSpRoughUse != 0) + { + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + return; /* use DMA mechanism, not statistics count mechanism */ + } + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> aux: Tx Num = %d\n", pEntry->UAPSDTxNum)); +#endif /* UAPSD_DEBUG */ + + FlgEosp = FALSE; + + if (pEntry->bAPSDFlagSPStart == 0) + { + /* + When SP is not started, all packets are from legacy PS queue. + One downlink packet for one PS-Poll packet. + */ + pEntry->bAPSDFlagLegacySent = 0; + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> legacy PS packet is sent!\n")); +#endif /* UAPSD_DEBUG */ + } + else + { +#ifdef UAPSD_TIMING_RECORD_FUNC + UAPSD_TIMING_RECORD(pAd, UAPSD_TIMING_RECORD_TX2AIR); +#endif /* UAPSD_TIMING_RECORD_FUNC */ + } + + /* record current time */ + UAPSD_TIME_GET(pAd, pEntry->UAPSDTimeStampLast); + + /* Note: UAPSDTxNum does NOT include the EOSP packet */ + if (pEntry->UAPSDTxNum > 0) + { + /* some UAPSD packets are not yet transmitted */ + + if (pEntry->UAPSDTxNum == 1) + { + /* this is the last UAPSD packet */ + if (pEntry->pUAPSDEOSPFrame != NULL) + { + /* transmit the EOSP frame */ + PNDIS_PACKET pPkt; + + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> aux: send EOSP frame...\n")); +#endif /* UAPSD_DEBUG */ + + pPkt = QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame); + QueId = RTMP_GET_PACKET_UAPSD_QUE_ID(pPkt); + + if (QueId > QID_AC_VO) + { + /* should not be here, only for sanity */ + QueId = QID_AC_BE; + } + /* + TODO: We need to check FlgIsLocked is TRUE or FALSE. + For MT_MAC, this function will not be invoked now, but RTMP_MAC/RLT_MAC will. + @20140403 + */ + if (rtmp_enq_req(pAd, QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame), QueId, tr_entry, TRUE, NULL) == FALSE) + { + RELEASE_NDIS_PACKET(pAd, QUEUE_ENTRY_TO_PACKET(pEntry->pUAPSDEOSPFrame), NDIS_STATUS_FAILURE); + + if (pAd->bAPSDFlagSPSuspend == 1) + { +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> aux: SP is suspend, keep SP if exists!\n")); +#endif /* UAPSD_DEBUG */ + + /* keep SP, not to close SP */ + pEntry->bAPSDFlagEOSPOK = 1; + } + + if ((pEntry->bAPSDFlagSPStart != 0) && + (pAd->bAPSDFlagSPSuspend == 0)) + { + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagEOSPOK = 0; + UAPSD_SP_END(pAd, pEntry); + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> aux: close a SP.\n\n\n")); +#endif /* UAPSD_DEBUG */ + } + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + return; + } + pEntry->pUAPSDEOSPFrame = NULL; + FlgEosp = TRUE; + } + } + + /* a UAPSD frame is transmitted so decrease the counter */ + pEntry->UAPSDTxNum --; + + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + + /* maybe transmit the EOSP frame */ + if (FlgEosp == TRUE) + { + POS_COOKIE pCookie = (POS_COOKIE)pAd->OS_Cookie; + + /* + Too many functions call NICUpdateFifoStaCounters() and + NICUpdateFifoStaCounters() will call UAPSD_SP_AUE_Handle(), + if we call RTMPDeQueuePacket() here, double-IRQ LOCK will + occur. so we need to activate a tasklet to send EOSP frame. + + ex: RTMPDeQueuePacket() --> RTMPFreeTXDUponTxDmaDone() --> + NICUpdateFifoStaCounters() --> UAPSD_SP_AUE_Handle() --> + RTMPDeQueuePacket() ERROR! or + + RTMPHandleTxRingDmaDoneInterrupt() --> + RTMP_IRQ_LOCK() --> + RTMPFreeTXDUponTxDmaDone() --> + NICUpdateFifoStaCounters() --> + UAPSD_SP_AUE_Handle() --> + RTMPDeQueuePacket() --> + DEQUEUE_LOCK() --> + RTMP_IRQ_LOCK() ERROR! + */ + if ((pAd->chipCap.hif_type == HIF_RLT) + || (pAd->chipCap.hif_type == HIF_RTMP)) + RTMP_OS_TASKLET_SCHE(&pCookie->uapsd_eosp_sent_task); +#ifdef MT_PS + else + { + RTMPDeQueuePacket(pAd, FALSE, QueId, pEntry->wcid, MAX_TX_PROCESS); + } +#endif /* MT_PS */ + } + /* must return here; Or double unlock UAPSDEOSPLock */ + return; + } + else + { + /* UAPSDTxNum == 0 so the packet is the EOSP packet */ + + if (pAd->bAPSDFlagSPSuspend == 1) + { +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> aux: SP is suspend, keep SP if exists!\n")); +#endif /* UAPSD_DEBUG */ + + /* keep SP, not to close SP */ + pEntry->bAPSDFlagEOSPOK = 1; + } + + if ((pEntry->bAPSDFlagSPStart != 0) && + (pAd->bAPSDFlagSPSuspend == 0)) + { + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagEOSPOK = 0; + UAPSD_SP_END(pAd, pEntry); + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> aux: close a SP.\n\n\n")); +#endif /* UAPSD_DEBUG */ + } + } + + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + } +#endif /* UAPSD_SP_ACCURATE */ +} + + +/* +======================================================================== +Routine Description: + Close current Service Period. + +Arguments: + pAd Pointer to our adapter + +Return Value: + None + +Note: + When we receive EOSP frame tx done interrupt and a uplink packet + from the station simultaneously, we will regard it as a new trigger + frame because the packet is received when EOSP frame tx done interrupt. + + We can not sure the uplink packet is sent after old SP or in the old SP. + So we must close the old SP in receive done ISR to avoid the problem. +======================================================================== +*/ +VOID UAPSD_SP_CloseInRVDone(RTMP_ADAPTER *pAd) +{ + UINT32 IdEntry; + int FirstWcid = 0; + + + if (pAd->MacTab.fAnyStationInPsm == FALSE) + return; /* no any station is in power save mode */ + + + /* 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]; + ULONG flags = 0; + + UAPSD_SEM_LOCK(&pAd->UAPSDEOSPLock, flags); + + /* check if SP is started and EOSP is transmitted ok */ + if ((pEntry->bAPSDFlagSPStart != 0) && + (pEntry->bAPSDFlagEOSPOK != 0)) + { + /* + 1. SP is started; + 2. EOSP frame is sent ok. + */ + + /* + We close current SP for the STATION so we can receive new + trigger frame from the STATION again. + */ +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE,("uapsd> close SP in %s()!\n", + __FUNCTION__)); +#endif /* UAPSD_DEBUG */ + + //pEntry->bAPSDFlagSPStart = 0; + pEntry->bAPSDFlagEOSPOK = 0; + pEntry->bAPSDFlagLegacySent = 0; + UAPSD_SP_END(pAd, pEntry); + } + + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + } +} + + +#ifdef UAPSD_TIMING_RECORD_FUNC +/* +======================================================================== +Routine Description: + Enable/Disable Timing Record Function. + +Arguments: + pAd Pointer to our adapter + Flag 1 (Enable) or 0 (Disable) + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_TimingRecordCtrl(UINT32 Flag) +{ + if (gUAPSD_TimingFlag == UAPSD_TIMING_CTRL_SUSPEND) + return; + + gUAPSD_TimingFlag = Flag; +} + + +/* +======================================================================== +Routine Description: + Record some timings. + +Arguments: + pAd Pointer to our adapter + Type The timing is for what type + +Return Value: + None + +Note: + UAPSD_TIMING_RECORD_ISR + UAPSD_TIMING_RECORD_TASKLET + UAPSD_TIMING_RECORD_TRG_RCV + UAPSD_TIMING_RECORD_MOVE2TX + UAPSD_TIMING_RECORD_TX2AIR +======================================================================== +*/ +VOID UAPSD_TimingRecord(RTMP_ADAPTER *pAd, UINT32 Type) +{ + UINT32 Index; + + if (gUAPSD_TimingFlag == UAPSD_TIMING_CTRL_STOP) + return; + + if ((gUAPSD_TimingFlag == UAPSD_TIMING_CTRL_SUSPEND) && + (Type != UAPSD_TIMING_RECORD_TX2AIR)) + { + return; + } + + Index = gUAPSD_TimingIndexUapsd; + + switch(Type) + { + case UAPSD_TIMING_RECORD_ISR: + /* start to record the timing */ + UAPSD_TIMESTAMP_GET(pAd, gUAPSD_TimingIsr[Index]); + break; + + case UAPSD_TIMING_RECORD_TASKLET: + UAPSD_TIMESTAMP_GET(pAd, gUAPSD_TimingTasklet[Index]); + break; + + case UAPSD_TIMING_RECORD_TRG_RCV: + if (gUAPSD_TimingLoopIndex == 0) + { + /* + The trigger frame is the first received frame. + The received time will be the time recorded in ISR. + */ + gUAPSD_TimingTrgRcv[Index] = gUAPSD_TimingIsr[Index]; + } + else + { + /* + Some packets are handled before the trigger frame so + we record next one. + */ + UAPSD_TIMING_RECORD_STOP(); + } + break; + + case UAPSD_TIMING_RECORD_MOVE2TX: + UAPSD_TIMESTAMP_GET(pAd, gUAPSD_TimingMov2Tx[Index]); + + /* prepare to wait for tx done */ + UAPSD_TimingRecordCtrl(UAPSD_TIMING_CTRL_SUSPEND); + break; + + case UAPSD_TIMING_RECORD_TX2AIR: + UAPSD_TIMESTAMP_GET(pAd, gUAPSD_TimingTx2Air[Index]); + + /* sum the delay */ + gUAPSD_TimingSumIsr2Tasklet += \ + (UINT32)(gUAPSD_TimingTasklet[Index] - gUAPSD_TimingIsr[Index]); + gUAPSD_TimingSumTrig2Txqueue += \ + (UINT32)(gUAPSD_TimingMov2Tx[Index] - gUAPSD_TimingTrgRcv[Index]); + gUAPSD_TimingSumTxqueue2Air += \ + (UINT32)(gUAPSD_TimingTx2Air[Index] - gUAPSD_TimingMov2Tx[Index]); + + /* display average delay */ + if ((Index % UAPSD_TIMING_RECORD_DISPLAY_TIMES) == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> Isr2Tasklet=%d, Trig2Queue=%d, Queue2Air=%d micro seconds\n", + gUAPSD_TimingSumIsr2Tasklet/ + UAPSD_TIMING_RECORD_DISPLAY_TIMES, + gUAPSD_TimingSumTrig2Txqueue/ + UAPSD_TIMING_RECORD_DISPLAY_TIMES, + gUAPSD_TimingSumTxqueue2Air/ + UAPSD_TIMING_RECORD_DISPLAY_TIMES)); + gUAPSD_TimingSumIsr2Tasklet = 0; + gUAPSD_TimingSumTrig2Txqueue = 0; + gUAPSD_TimingSumTxqueue2Air = 0; + } + + /* ok, a record is finished; prepare to record the next one */ + gUAPSD_TimingIndexUapsd ++; + + if (gUAPSD_TimingIndexUapsd >= UAPSD_TIMING_RECORD_MAX) + gUAPSD_TimingIndexUapsd = 0; + + /* stop the record */ + gUAPSD_TimingFlag = UAPSD_TIMING_CTRL_STOP; + + DBGPRINT(RT_DEBUG_TRACE, ("sam> Isr->Tasklet:%d, Trig->TxQueue:%d, TxQueue->TxDone:%d\n", + (UINT32)(gUAPSD_TimingTasklet[Index] - gUAPSD_TimingIsr[Index]), + (UINT32)(gUAPSD_TimingMov2Tx[Index] - gUAPSD_TimingTrgRcv[Index]), + (UINT32)(gUAPSD_TimingTx2Air[Index] - gUAPSD_TimingMov2Tx[Index]))); + break; + } +} + + +/* +======================================================================== +Routine Description: + Record the loop index for received packet handle. + +Arguments: + pAd Pointer to our adapter + LoopIndex The RxProcessed in rtmp_rx_done_handle() + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_TimeingRecordLoopIndex(UINT32 LoopIndex) +{ + gUAPSD_TimingLoopIndex = LoopIndex; +} +#endif /* UAPSD_TIMING_RECORD_FUNC */ + + +/* +======================================================================== +Routine Description: + Handle PS-Poll Frame. + +Arguments: + pAd Pointer to our adapter + *pEntry the source STATION + +Return Value: + TRUE Handle OK + FALSE Handle FAIL + +Note: +======================================================================== +*/ +BOOLEAN UAPSD_PsPollHandle(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + QUEUE_HEADER *pAcPsQue; + 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 = QID_AC_BE; + STA_TR_ENTRY *tr_entry = NULL; + ULONG flags = 0; + + + if (pEntry == NULL) + return FALSE; + + FlgQueEmpty = TRUE; + pQuedPkt = NULL; + + UAPSD_SEM_LOCK(&pAd->UAPSDEOSPLock, flags); + + if (pEntry->bAPSDAllAC == 0) + { + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + return FALSE; /* not all AC are delivery-enabled */ + } + + if (pEntry->bAPSDFlagSPStart != 0) + { + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + return FALSE; /* its service period is not yet ended */ + } + + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + + /* from highest priority AC3 --> AC2 --> AC0 --> lowest priority AC1 */ + for (IdAc=(WMM_NUM_OF_AC-1); IdAc>=0; IdAc--) + { + AcQueId = AcPriority[IdAc]; + + /* + NOTE: get U-APSD queue pointer here to speed up, do NOT use + pEntry->UAPSDQueue[AcQueId] throughout codes because + compiler will compile it to many assembly codes. + */ + pAcPsQue = &pEntry->UAPSDQueue[AcQueId]; + + /* check if any U-APSD packet is queued for the AC */ + if (pAcPsQue->Head == NULL) + continue; + + /* at least one U-APSD packet exists here */ + + /* put U-APSD packets to the AC software queue */ + if ((pAcPsQue->Head != NULL) && (pQuedPkt == NULL)) + { + /* get AC software queue */ + QueId = QueIdList[AcQueId]; + /* 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); + RTMP_SET_PACKET_TXTYPE(pQuedPkt, TX_LEGACY_FRAME); + + /* set U-APSD flag & its software queue ID */ + RTMP_SET_PACKET_UAPSD(pQuedPkt, TRUE, QueId); + } + } + + if (pAcPsQue->Head != NULL) + { + /* still have packets in queue */ + FlgQueEmpty = FALSE; + break; + } + } + + if (pQuedPkt != NULL) + { + if (FlgQueEmpty == TRUE) + { + /* + No any more queued U-APSD packet so clear More Data bit of + the last frame. + */ + RTMP_SET_PACKET_MOREDATA(pQuedPkt, FALSE); + } + + if (rtmp_enq_req(pAd, pQuedPkt, QueId, tr_entry, TRUE, NULL) == FALSE) + RELEASE_NDIS_PACKET(pAd, pQuedPkt, NDIS_STATUS_FAILURE); + + } + + /* 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->func_tb_idx, Aid); + } +#endif /* CONFIG_AP_SUPPORT */ + } + + /* reset idle timeout here whenever a trigger frame is received */ + pEntry->UAPSDQIdleCount = 0; + + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, WCID_ALL, 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) +{ + ULONG flags = 0; + + *pFlgIsAnyPktForBK = FALSE; + *pFlgIsAnyPktForBE = FALSE; + *pFlgIsAnyPktForVI = FALSE; + *pFlgIsAnyPktForVO = FALSE; + + if (pEntry == NULL) + return; + + /* get queue status */ + UAPSD_SEM_LOCK(&pAd->UAPSDEOSPLock, flags); + 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; + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); +} + + +/* +======================================================================== +Routine Description: + Handle UAPSD Trigger Frame. + +Arguments: + pAd Pointer to our adapter + *pEntry the source STATION + UpOfFrame the UP of the trigger frame + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_TriggerFrameHandle(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, UCHAR UpOfFrame) +{ + QUEUE_HEADER *pAcPsQue; + 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 */ + STA_TR_ENTRY *tr_entry = NULL; + ULONG flags = 0; + +#ifdef UAPSD_SP_ACCURATE + ULONG TimeNow; +#endif /* UAPSD_SP_ACCURATE */ +#ifdef MT_PS + BOOLEAN bDoDeQ = TRUE; +#endif /* MT_PS */ + + + /* sanity check for Service Period of the STATION */ + UAPSD_SEM_LOCK(&pAd->UAPSDEOSPLock, flags); + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_UAPSD, ("\nuapsd> bAPSDFlagLegacySent = %d!\n", + pEntry->bAPSDFlagLegacySent)); +#endif /* UAPSD_DEBUG */ + + if (pEntry->bAPSDFlagSPStart != 0) + { + /* + reset ContinueTxFailCnt + */ + pEntry->ContinueTxFailCnt = 0; + // TODO: shiang-usw, remove upper setting because we need to mirgate to tr_entry! + pAd->MacTab.tr_entry[pEntry->wcid].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 | DBG_FUNC_UAPSD, ("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 | DBG_FUNC_UAPSD, ("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 */ + + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + UAPSD_SP_Close(pAd, pEntry); + UAPSD_SEM_LOCK(&pAd->UAPSDEOSPLock, flags); + } + else + { +#endif /* UAPSD_SP_ACCURATE */ + + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + return; + +#ifdef UAPSD_SP_ACCURATE + } +#endif /* UAPSD_SP_ACCURATE */ + } + +#ifdef UAPSD_TIMING_RECORD_FUNC + UAPSD_TIMING_RECORD(pAd, UAPSD_TIMING_RECORD_TRG_RCV); +#endif /* UAPSD_TIMING_RECORD_FUNC */ + +#ifdef UAPSD_DEBUG + if (pEntry->pUAPSDEOSPFrame != NULL) + { + DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_UAPSD, ("uapsd> EOSP is not NULL!\n")); + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + return; + } +#endif /* UAPSD_DEBUG */ + + if (pEntry->MaxSPLength >= 4) + { + /* fatal error, should be 0 ~ 3 so reset it to 0 */ + DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_UAPSD, + ("uapsd> MaxSPLength >= 4 (%d)!\n", pEntry->MaxSPLength)); + pEntry->MaxSPLength = 0; + } + + tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + +#ifdef UAPSD_SP_ACCURATE + /* mark the start time for the SP */ + UAPSD_TIME_GET(pAd, pEntry->UAPSDTimeStampLast); + + + /* check if current rate of the entry is 1Mbps (2.4GHz) or 6Mbps (5GHz) */ +#ifdef RTMP_MAC_PCI + if (((pEntry->HTPhyMode.field.MODE == MODE_CCK) && + (pEntry->HTPhyMode.field.MCS == MCS_0)) || + ((pEntry->HTPhyMode.field.MODE == MODE_OFDM) && + (pEntry->HTPhyMode.field.MCS == MCS_0))) + { + /* + Note: because no any statistics count for CCK, MCS0 so we need + to use old UAPSD DMA mechanism. + */ + pEntry->bAPSDFlagSpRoughUse = 1; + } + else + pEntry->bAPSDFlagSpRoughUse = 0; + + if (pEntry->bAPSDFlagSpRoughUse != 0) + { + /* + Note: because no any indication for UAPSD packet or PS-Poll + packet, we need to use old UAPSD DMA mechanism if part of AC + uses legacy PS mechanism. + */ + if (pEntry->bAPSDAllAC == 0) + pEntry->bAPSDFlagSpRoughUse = 0; + } +#endif /* RTMP_MAC_PCI */ + +#else /* UAPSD_SP_ACCURATE */ + + pEntry->bAPSDFlagSpRoughUse = 1; +#endif /* !UAPSD_SP_ACCURATE */ + + /* sanity Check for UAPSD condition */ + if (UpOfFrame >= 8) + UpOfFrame = 1; /* shout not be here */ + + /* get the AC ID of incoming packet */ + AcQueId = WMM_UP2AC_MAP[UpOfFrame]; + + /* check whether the AC is trigger-enabled AC */ + if (pEntry->bAPSDCapablePerAC[AcQueId] == 0) + { + /* + WMM Specification V1.1 Page 4 + Trigger Frame: A QoS Data or QoS Null frame from a WMM STA in + Power Save Mode associated with an AC the WMM STA has configured + to be a trigger-enabled AC. + + A QoS Data or QoS Null frame that indicates transition to/from + Power Save Mode is not considered to be a Trigger Frame and the + AP shall not respond with a QoS Null frame. + */ + + /* + ERROR! the AC does not belong to a trigger-enabled AC or + the ACM of the AC is set. + */ + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + return; + } + + + /* enqueue U-APSD packets to AC software queues */ + + /* + Protect TxSwQueue0 & McastPsQueue because use them in + interrupt context. + */ +/* RTMP_IRQ_LOCK(FlgIrq); */ + + /* init */ + FlgQueEmpty = TRUE; + TxPktNum = 0; + SpMaxLen = SpLenMap[pEntry->MaxSPLength]; + pQuedPkt = NULL; + FlgMgmtFrame = 0; + + /* from highest priority AC3 --> AC2 --> AC0 --> lowest priority AC1 */ + for (IdAc=(WMM_NUM_OF_AC-1); IdAc>=0; IdAc--) + { + AcQueId = AcPriority[IdAc]; + + /* check if the AC is delivery-enable AC */ + if (pEntry->bAPSDDeliverEnabledPerAC[AcQueId] == 0) + continue; + + /* + NOTE: get U-APSD queue pointer here to speed up, do NOT use + pEntry->UAPSDQueue[AcQueId] throughout codes because + compiler will compile it to many assembly codes. + */ + pAcPsQue = &pEntry->UAPSDQueue[AcQueId]; + + /* check if any U-APSD packet is queued for the AC */ + if (pAcPsQue->Head == NULL) + continue; + + /* at least one U-APSD packet exists here */ + + /* get AC software queue */ + QueId = QueIdList[AcQueId]; + + /* put U-APSD packets to the AC software queue */ + while(pAcPsQue->Head) + { + /* check if Max SP Length != 0 */ + if (SpMaxLen != 0) + { + /* + WMM Specification V1.1 3.6.1.7 + At each USP for a WMM STA, the WMM AP shall attempt to + transmit at least one MSDU or MMPDU, but no more than the + value encoded in the Max SP Length field in the QoS Info + Field of a WMM Information Element from delivery-enabled + ACs, that are destined for the WMM STA. + */ + if (TxPktNum >= SpMaxLen) + { + /* + Some queued U-APSD packets still exists so we will + not clear MoreData bit of the packet. + */ + FlgQueEmpty = FALSE; + break; + } + } + + /* count U-APSD packet number */ + TxPktNum ++; + + /* queue last U-APSD packet */ + if (pQuedPkt != NULL) + { + /* + enqueue U-APSD packet to tx software queue + + WMM Specification V1.1 3.6.1.7: + Each buffered frame shall be delivered using the access + parameters of its AC. + */ + if (rtmp_enq_req(pAd, pQuedPkt, QueId, tr_entry, TRUE, NULL) == FALSE) + { + RELEASE_NDIS_PACKET(pAd, pQuedPkt, NDIS_STATUS_FAILURE); + TxPktNum --; + } + } + + /* get the U-APSD packet */ + pQuedEntry = RemoveHeadQueue(pAcPsQue); + pQuedPkt = QUEUE_ENTRY_TO_PACKET(pQuedEntry); + if (pQuedPkt != NULL) + { + if (RTMP_GET_PACKET_MGMT_PKT(pQuedPkt) == 1) + FlgMgmtFrame = 1; + + /* + WMM Specification V1.1 3.6.1.7 + The More Data bit (b13) of the directed MSDU or MMPDU + associated with delivery-enabled ACs and destined for + that WMM STA indicates that more frames are buffered for + the delivery-enabled ACs. + */ + RTMP_SET_PACKET_MOREDATA(pQuedPkt, TRUE); + RTMP_SET_PACKET_TXTYPE(pQuedPkt, TX_LEGACY_FRAME); + + /* set U-APSD flag & its software queue ID */ + RTMP_SET_PACKET_UAPSD(pQuedPkt, TRUE, QueId); + } + } + + if (FlgQueEmpty == FALSE) + { + /* FlgQueEmpty will be FALSE only when TxPktNum >= SpMaxLen */ + break; + } + } + + /* + For any mamagement UAPSD frame, we use DMA to do SP check + because no any FIFO statistics for management frame. + */ + if (FlgMgmtFrame) + pEntry->bAPSDFlagSpRoughUse = 1; + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + /* + UAPSD_SP_ACCURATE is not ready for MT_MAC now. @20140403 + */ + pEntry->bAPSDFlagSpRoughUse = 1; +#ifdef MT_PS + if ((tr_entry->ps_state != APPS_RETRIEVE_IDLE) && + (tr_entry->ps_state != APPS_RETRIEVE_DONE)) + bDoDeQ = FALSE; +#endif /* MT_PS */ + } +#endif /* MT_AC */ + + /* + No need to protect EOSP handle code because we will be here + only when last SP is ended. + */ + FlgNullSnd = FALSE; + + if (TxPktNum >= 1) + { + if (FlgQueEmpty == TRUE) + { + /* + No any more queued U-APSD packet so clear More Data bit of + the last frame. + */ + RTMP_SET_PACKET_MOREDATA(pQuedPkt, FALSE); + } + } + + //pEntry->bAPSDFlagSPStart = 1; /* set the SP start flag */ + UAPSD_SP_START(pAd, pEntry); /* set the SP start flag */ + pEntry->bAPSDFlagEOSPOK = 0; + +#ifdef UAPSD_DEBUG +{ + ULONG DebugTimeNow; + + UAPSD_TIME_GET(pAd, DebugTimeNow); + + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> start a SP (Tx Num = %d) (Rough SP = %d) " + "(Has Any Mgmt = %d) (Abnormal = %d) (Time = %lu)\n", + TxPktNum, pEntry->bAPSDFlagSpRoughUse, FlgMgmtFrame, + gUAPSD_SP_CloseAbnormalNum, DebugTimeNow)); +} +#endif /* UAPSD_DEBUG */ + + if (TxPktNum <= 1) + { + /* if no data needs to tx, respond with QosNull for the trigger frame */ + pEntry->pUAPSDEOSPFrame = NULL; + pEntry->UAPSDTxNum = TxPktNum; +#ifdef MT_PS + tr_entry->bEospNullSnd = FALSE; +#endif /* MT_PS */ + + if (TxPktNum == 0) + { + pEntry->UAPSDTxNum = 0; +#ifdef MT_PS + if ((pAd->chipCap.hif_type == HIF_MT) && + (tr_entry->ps_state != APPS_RETRIEVE_IDLE) && + (tr_entry->ps_state != APPS_RETRIEVE_DONE)) + { + tr_entry->bEospNullSnd = TRUE; + tr_entry->EospNullUp = UpOfFrame; + } + else +#endif /* MT_PS */ + { + 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); + RTMP_SET_PACKET_TXTYPE(pQuedPkt, TX_LEGACY_FRAME); + + //AcQueId = WMM_UP2AC_MAP[UpOfFrame]; + AcQueId = RTMP_GET_PACKET_UAPSD_QUE_ID(pQuedPkt); + if (rtmp_enq_req(pAd, pQuedPkt, AcQueId, tr_entry, FALSE, NULL) == FALSE) + { + RELEASE_NDIS_PACKET(pAd, pQuedPkt, NDIS_STATUS_FAILURE); + pEntry->bAPSDFlagEOSPOK = 0; + pEntry->bAPSDFlagLegacySent = 0; + UAPSD_SP_END(pAd, pEntry); + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + return; + } + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, + ("uapsd> Only one packet with UP = %d\n", + RTMP_GET_PACKET_UP(pQuedPkt))); +#endif /* RELEASE_EXCLUDE */ + } + + /* + We will send the QoS Null frame below and we will hande the + QoS Null tx done in RTMPFreeTXDUponTxDmaDone(). + */ + } + else + { + /* more than two U-APSD packets */ + + /* + NOTE: EOSP bit != !MoreData bit because Max SP Length, + we can not use MoreData bit to decide EOSP bit. + */ + + /* + Backup the EOSP frame and + we will transmit the EOSP frame in RTMPFreeTXDUponTxDmaDone(). + */ + RTMP_SET_PACKET_EOSP(pQuedPkt, TRUE); + RTMP_SET_PACKET_TXTYPE(pQuedPkt, TX_LEGACY_FRAME); + + pEntry->pUAPSDEOSPFrame = (PQUEUE_ENTRY)pQuedPkt; + pEntry->UAPSDTxNum = TxPktNum-1; /* skip the EOSP frame */ + } + +#ifdef UAPSD_DEBUG + if ((pEntry->pUAPSDEOSPFrame != NULL) && + (RTMP_GET_PACKET_MGMT_PKT(pEntry->pUAPSDEOSPFrame) == 1)) + { + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> The EOSP frame is a management frame.\n")); + } +#endif /* UAPSD_DEBUG */ + + +#ifdef UAPSD_SP_ACCURATE + /* count for legacy PS packet */ + + /* + Note: A worse case for mix mode (UAPSD + legacy PS): + PS-Poll --> legacy ps packet --> trigger frame --> QoS Null frame + (QSTA) (QAP) (QSTA) (QAP) + + where statistics handler is NICUpdateFifoStaCounters(). + + If we receive the trigger frame before the legacy ps packet is sent to + the air, when we call statistics handler in tx done, it maybe the + legacy ps statistics, not the QoS Null frame statistics, so we will + do UAPSD counting fail. + + We need to count the legacy PS here if it is not yet sent to the air. + */ + + /* + Note: in addition, only one legacy PS need to count because one legacy + packet for one PS-Poll packet; if we receive a trigger frame from a + station, it means that only one legacy ps packet is possible not sent + to the air, it is impossible more than 2 legacy packets are not yet + sent to the air. + */ + if ((pEntry->bAPSDFlagSpRoughUse == 0) && + (pEntry->bAPSDFlagLegacySent != 0)) + { + pEntry->UAPSDTxNum ++; + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> A legacy PS is sent! UAPSDTxNum = %d\n", + pEntry->UAPSDTxNum)); +#endif /* UAPSD_DEBUG */ + } +#endif /* UAPSD_SP_ACCURATE */ + + + /* clear corresponding TIM bit */ + + /* get its AID for the station */ + Aid = pEntry->Aid; + + if ((pEntry->bAPSDAllAC == 1) && (FlgQueEmpty == 1)) + { + /* all AC are U-APSD and no any U-APSD packet is queued, set TIM */ + +#ifdef CONFIG_AP_SUPPORT + /* clear TIM bit */ + if ((Aid > 0) && (Aid < MAX_LEN_OF_MAC_TABLE)) + { + WLAN_MR_TIM_BIT_CLEAR(pAd, pEntry->func_tb_idx, Aid); + } +#endif /* CONFIG_AP_SUPPORT */ + } + + /* reset idle timeout here whenever a trigger frame is received */ + pEntry->UAPSDQIdleCount = 0; + + UAPSD_SEM_UNLOCK(&pAd->UAPSDEOSPLock, flags); + + + /* 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. + */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef MT_PS + if (pEntry->i_psm == I_PSM_DISABLE) + { + MT_SET_IGNORE_PSM(pAd, pEntry, I_PSM_ENABLE); + } +#endif /* MT_PS */ +#endif /* CONFIG_AP_SUPPORT */ + + RtmpEnqueueNullFrame(pAd, pEntry->Addr, pEntry->CurrTxRate, + Aid, pEntry->func_tb_idx, TRUE, TRUE, UpOfFrame); + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> end a SP by a QoS Null frame!\n")); +#endif /* UAPSD_DEBUG */ + +#ifdef MT_PS + bDoDeQ = FALSE; +#endif /* MT_PS */ + } + +#ifdef UAPSD_TIMING_RECORD_FUNC + UAPSD_TIMING_RECORD(pAd, UAPSD_TIMING_RECORD_MOVE2TX); +#endif /* UAPSD_TIMING_RECORD_FUNC */ + +#ifdef MT_PS + if (bDoDeQ) +#endif /* MT_PS */ + { + /* need to use pEntry->UAPSDTxNum to make sure all packets are Dequeued in USB Throughtput case */ + RTMPDeQueuePacket(pAd, FALSE, NUM_OF_TX_RING, pEntry->wcid, pEntry->UAPSDTxNum); + } +} + + + +#endif /* UAPSD_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/vendor.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/vendor.c new file mode 100644 index 000000000..dcb71de0e --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/vendor.c @@ -0,0 +1,802 @@ +#include "rt_config.h" +#ifdef CONFIG_OWE_SUPPORT +static VOID show_format(VOID) +{ + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("\nCommand Format: 'op'-frm_map:'bitmap'-oui:'xxxxxx'-length:'len'-ctnt:'xxxxxx'\n")); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("op: 1: ADD, 2: UPDATE, 3: REMOVE, 4: SHOW\n")); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("\nbitmap: 0x1: BEACON, 0x2: PROBE_REQ, 0x4: PROBE_RESP, 0x8: ASSOC_REQ\n")); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("\t 0x10: ASSOC_RESP, 0x20: AUTH_REQ, 0x40: AUTH_RESP\n")); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("\noui: in hex format, such as 000c43\n")); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("\nlength: the total length of oui and content\n")); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("\nctnt: in hex format, such as aabbcc\n")); + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("\nCase 1: Add or Update\n")); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("\tiwpriv ra0 set vie_op=1-frm_map:1-oui:00aabb-length:4-ctnt:cc\n")); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("\nCase 2: Remove\n")); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("\tiwpriv ra0 set vie_op=3-frm_map:1-oui:00aabb-length:4-ctnt:cc\n")); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("\nCase 3: Show\n")); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("\tiwpriv ra0 set vie_op=4-frm_map:1\n")); +} + +VOID print_vie(struct wifi_dev *wdev, UINT32 frm_map) +{ + struct vie_struct *current_vie = NULL; + VIE_CTRL *vie_ctrl = NULL; + int i; + int index; + + for (i = VIE_BEACON; i < VIE_FRM_TYPE_MAX; i++) { + vie_ctrl = &wdev->vie_ctrl[i]; + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("\nFrm_Type:%s, vie_num:%d\n", + (i == VIE_BEACON) ? "Beacon" : + (i == VIE_PROBE_REQ) ? "Probe_Req" : + (i == VIE_PROBE_RESP) ? "Probe_Resp" : + (i == VIE_ASSOC_REQ) ? "Assoc_Req" : + (i == VIE_ASSOC_RESP) ? "Assoc_Resp" : + (i == VIE_AUTH_REQ) ? "Auth_Req" : "Auth_Resp", + vie_ctrl->vie_num)); + + current_vie = vie_ctrl->vie_in_frm; + index = 0; + while (current_vie) { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("vie_index:%d oui:0x%02x 0x%02x 0x%02x\n", + index, + current_vie->oui_oitype[0], + current_vie->oui_oitype[1], + current_vie->oui_oitype[2])); + + hex_dump("ie_content:", current_vie->ie_ctnt, current_vie->vie_length); + current_vie = current_vie->next_vie; + index++; + } + } +} + +static INT vie_sanity_check(UINT32 oper, UINT32 input_argument, UINT32 frm_map, UINT32 length, UCHAR *oui, UCHAR *ctnt) +{ + INT ret = NDIS_STATUS_SUCCESS; + + if (oper >= VIE_OPER_MAX) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("oper error:%d\n", oper)); + ret = NDIS_STATUS_FAILURE; + goto err; + } + + if (((oper != VIE_SHOW) && (input_argument != 5)) || + ((oper == VIE_SHOW) && (input_argument != 2))) { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("oper:%d, input_argument:%d\n", oper, input_argument)); + ret = NDIS_STATUS_FAILURE; + goto err; + } + + if (frm_map >= VIE_FRM_TYPE_MAX_BITMAP) { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("frm_map error:0x%x\n", frm_map)); + ret = NDIS_STATUS_FAILURE; + goto err; + } + + if (oper != VIE_SHOW) { + if (strlen(oui) != OUI_LEN * 2) { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("oui format error:%s, should be xxxxxx!\n", oui)); + ret = NDIS_STATUS_FAILURE; + goto err; + } + + if (strlen(ctnt) != (length * 2) - strlen(oui)) { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("oui len + ctnt length:%d != input length:%d!\n", + (UINT32)(strlen(ctnt) / 2), length)); + ret = NDIS_STATUS_FAILURE; + goto err; + } + } +err: + + return ret; +} + +INT vie_oper_proc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + INT ret = TRUE; + struct wifi_dev *wdev = NULL; + struct os_cookie *os_obj; + UINT32 oper = 0; + UINT32 length = 0; + UINT32 input_argument = 0; + UINT32 frm_map = 0; + UINT32 oui_oitype = 0; + UCHAR oui[OUI_LEN * 2] = {0}; + UCHAR ctnt[(MAX_VENDOR_IE_LEN + 1) * 2] = {0}; + UCHAR ie_hex_ctnt[MAX_VENDOR_IE_LEN] = {0}; + + os_obj = (struct os_cookie *)pAd->OS_Cookie; +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) { + wdev = &pAd->ApCfg.MBSSID[os_obj->ioctl_if].wdev; + } +#endif /* CONFIG_AP_SUPPORT */ + + if (arg) { + input_argument = sscanf(arg, + "%d-frm_map:%x-oui:%6s-length:%d-ctnt:%s", + &oper, &frm_map, oui, &length, ctnt); + + if (vie_sanity_check(oper, + input_argument, + frm_map, + length, + oui, + ctnt) == NDIS_STATUS_FAILURE) { + ret = FALSE; + goto print_format; + } + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s(): oper:%d, frm_map:0x%x, oui:%s, length:%d, ctnt:%s\n", + __func__, oper, frm_map, oui, length, ctnt)); + + if ((oper == VIE_ADD) || (oper == VIE_UPDATE) || (oper == VIE_REMOVE)) { + /*add/update case*/ + AtoH(oui, ie_hex_ctnt, OUI_LEN); + AtoH(ctnt, ie_hex_ctnt + OUI_LEN, length - OUI_LEN); + NdisMoveMemory(&oui_oitype, ie_hex_ctnt, sizeof(UINT32)); + + if (oper == VIE_REMOVE) { + if (remove_vie(pAd, + wdev, + frm_map, + oui_oitype, + length, + ie_hex_ctnt) == NDIS_STATUS_FAILURE) { + ret = FALSE; + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s(): remove failed.\n", __func__)); + } + } else { + if (add_vie(pAd, + wdev, + frm_map, + oui_oitype, + length, + ie_hex_ctnt) == NDIS_STATUS_FAILURE) { + ret = FALSE; + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s(): %s failed.\n", + __func__, (oper == VIE_ADD) ? "add" : "update")); + } + } + } else if (oper == VIE_SHOW) + print_vie(wdev, frm_map); + } + + return ret; + +print_format: + show_format(); + return ret; +} + +static VOID get_vie_ctrl(struct wifi_dev *wdev, VIE_CTRL **vie_ctrl, UINT32 frm_type_bitmap) +{ + switch (frm_type_bitmap) { + case VIE_BEACON_BITMAP: + *vie_ctrl = &wdev->vie_ctrl[VIE_BEACON]; + break; + case VIE_PROBE_REQ_BITMAP: + *vie_ctrl = &wdev->vie_ctrl[VIE_PROBE_REQ]; + break; + case VIE_PROBE_RESP_BITMAP: + *vie_ctrl = &wdev->vie_ctrl[VIE_PROBE_RESP]; + break; + case VIE_ASSOC_REQ_BITMAP: + *vie_ctrl = &wdev->vie_ctrl[VIE_ASSOC_REQ]; + break; + case VIE_ASSOC_RESP_BITMAP: + *vie_ctrl = &wdev->vie_ctrl[VIE_ASSOC_RESP]; + break; + case VIE_AUTH_REQ_BITMAP: + *vie_ctrl = &wdev->vie_ctrl[VIE_AUTH_REQ]; + break; + case VIE_AUTH_RESP_BITMAP: + *vie_ctrl = &wdev->vie_ctrl[VIE_AUTH_RESP]; + break; + default: + break; + } +} + +static INT32 insert_vie(struct wifi_dev *wdev, + struct vie_struct **out_vie, + UINT32 frm_type_index, + UINT32 oui_oitype, + ULONG ie_length, + UCHAR *frame_buffer) +{ + struct vie_struct *vie = NULL; + struct vie_struct *current_frm_tail_vie = NULL; + INT32 ret = NDIS_STATUS_SUCCESS; + VIE_CTRL *vie_ctrl = NULL; + UINT32 local_oui_oitype = oui_oitype; + + if (os_alloc_mem(NULL, (UCHAR **)&vie, sizeof(struct vie_struct)) == NDIS_STATUS_FAILURE) { + ret = NDIS_STATUS_FAILURE; + return ret; + } + + get_vie_ctrl(wdev, &vie_ctrl, frm_type_index); + if (vie_ctrl == NULL) { + ret = NDIS_STATUS_FAILURE; + return ret; + } + + current_frm_tail_vie = vie_ctrl->vie_in_frm; + if (vie_ctrl->vie_num > 0) { + while (current_frm_tail_vie) { + if (current_frm_tail_vie->next_vie) + current_frm_tail_vie = current_frm_tail_vie->next_vie; + else { + current_frm_tail_vie->next_vie = vie; + break; + } + } + } else + vie_ctrl->vie_in_frm = vie; + + vie->vie_length = ie_length; + NdisMoveMemory(vie->oui_oitype, &local_oui_oitype, sizeof(local_oui_oitype)); + + if (os_alloc_mem(NULL, (UCHAR **)&vie->ie_ctnt, ie_length) == NDIS_STATUS_FAILURE) { + ret = NDIS_STATUS_FAILURE; + goto end; + } else + NdisMoveMemory(vie->ie_ctnt, frame_buffer, ie_length); + + vie->next_vie = NULL; + vie_ctrl->vie_num++; + *out_vie = vie; + +end: + return ret; +} + +BOOLEAN find_oui_oitype(struct wifi_dev *wdev, UINT frm_type_bit, UINT32 oui_oitype, struct vie_struct **vie) +{ + BOOLEAN found = FALSE; + + struct vie_struct *current_vie = NULL; + VIE_CTRL *vie_ctrl = NULL; + UINT32 local_oui_oitype = oui_oitype; + + get_vie_ctrl(wdev, &vie_ctrl, frm_type_bit); + if (vie_ctrl == NULL) { + /*FATAL ERROR shall not happen.*/ + return found; + } + + current_vie = vie_ctrl->vie_in_frm; + while (current_vie) { + if (NdisEqualMemory(current_vie->oui_oitype, (UCHAR *)&local_oui_oitype, sizeof(UINT32))) { + *vie = current_vie; + found = TRUE; + break; + } + + current_vie = current_vie->next_vie; + } + return found; +} + +INT32 add_vie(struct _RTMP_ADAPTER *pAd, + struct wifi_dev *wdev, + UINT32 frm_type_map, + UINT32 oui_oitype, + ULONG ie_length, + UCHAR *frame_buffer) +{ + struct vie_struct *vie = NULL; + UINT frm_type; + UINT frm_type_mask = 0; + UINT frm_type_bit = 0; + INT32 ret = NDIS_STATUS_SUCCESS; + + /* + * check if there is the same oui and oi_type vie exists already, if it does, update it. + * the cons is, it only accepts one group of same oui and oitype. + */ + for (frm_type = VIE_BEACON; frm_type < VIE_FRM_TYPE_MAX; frm_type++) { + frm_type_mask = (1 << frm_type); + frm_type_bit = frm_type_map & frm_type_mask; + if (frm_type_bit) { + if (find_oui_oitype(wdev, frm_type_bit, oui_oitype, &vie) == TRUE) { + /*we found a duplicate oui and oi type, update it.*/ + vie->vie_length = ie_length; + /*the check should be not necessary, but check it anyway.*/ + if (vie->ie_ctnt) + os_free_mem(NULL, vie->ie_ctnt); + + if (os_alloc_mem(pAd, (UCHAR **)&vie->ie_ctnt, ie_length) == NDIS_STATUS_FAILURE) { + ret = NDIS_STATUS_FAILURE; + goto end; + } else + NdisMoveMemory(vie->ie_ctnt, frame_buffer, ie_length); + } else { + /*cannot find a exist oui_oitype in this kind of frm_type pkt. add a new one in it.*/ + if (insert_vie(wdev, + &vie, + frm_type_bit, + oui_oitype, + ie_length, + frame_buffer) == NDIS_STATUS_FAILURE) { + ret = NDIS_STATUS_FAILURE; + goto end; + } + } + } + } + +end: + return ret; +} + +static VOID do_delete_vie(VIE_CTRL *vie_ctrl, struct vie_struct *remove_vie) +{ + struct vie_struct *head_vie = NULL; + struct vie_struct *prev_vie = NULL; + struct vie_struct *curr_vie = NULL; + + head_vie = vie_ctrl->vie_in_frm; + if (remove_vie == head_vie) { + vie_ctrl->vie_in_frm = head_vie->next_vie; + } else { + curr_vie = head_vie->next_vie; + prev_vie = head_vie; + + while (curr_vie) { + if (curr_vie == remove_vie) { + prev_vie->next_vie = curr_vie->next_vie; + break; + } + prev_vie = curr_vie; + curr_vie = curr_vie->next_vie; + } + } + + if (remove_vie->ie_ctnt) + os_free_mem(NULL, remove_vie->ie_ctnt); + if (remove_vie) + os_free_mem(NULL, remove_vie); + vie_ctrl->vie_num--; +} + +INT32 remove_vie(struct _RTMP_ADAPTER *pAd, + struct wifi_dev *wdev, + UINT32 frm_type_map, + UINT32 oui_oitype, + ULONG ie_length, + UCHAR *frame_buffer) +{ + struct vie_struct *vie = NULL; + UINT frm_type; + UINT frm_type_mask = 0; + UINT frm_type_bit = 0; + INT32 ret = NDIS_STATUS_SUCCESS; + VIE_CTRL *vie_ctrl = NULL; + + for (frm_type = VIE_BEACON; frm_type < VIE_FRM_TYPE_MAX; frm_type++) { + frm_type_mask = (1 << frm_type); + frm_type_bit = frm_type_map & frm_type_mask; + if (frm_type_bit) { + get_vie_ctrl(wdev, &vie_ctrl, frm_type_bit); + if (vie_ctrl == NULL) { + ret = NDIS_STATUS_FAILURE; + return ret; + } + if (find_oui_oitype(wdev, frm_type_bit, oui_oitype, &vie) == TRUE) + do_delete_vie(vie_ctrl, vie); + } + } + + return ret; +} + +VOID init_vie_ctrl(struct wifi_dev *wdev) +{ + int i; + VIE_CTRL *vie_ctrl = NULL; + struct vie_struct *vie = NULL; + struct vie_struct *temp_vie = NULL; + + for (i = 0; i < VIE_FRM_TYPE_MAX; i++) { + vie_ctrl = &wdev->vie_ctrl[i]; + vie = vie_ctrl->vie_in_frm; + vie_ctrl->type = i; + vie_ctrl->vie_num = 0; + + /*should be not necessary for this step.*/ + while (vie != NULL) { + if (vie->next_vie != NULL) + temp_vie = vie->next_vie; + + if (vie->ie_ctnt != NULL) { + os_free_mem(NULL, vie->ie_ctnt); + vie->ie_ctnt = NULL; + } + vie->next_vie = NULL; + os_free_mem(NULL, vie); + + vie = temp_vie; + } + vie_ctrl->vie_in_frm = NULL; + } +} + +VOID deinit_vie_ctrl(struct wifi_dev *wdev) +{ + int i; + VIE_CTRL *vie_ctrl = NULL; + struct vie_struct *vie = NULL; + struct vie_struct *temp_vie = NULL; + + for (i = 0; i < VIE_FRM_TYPE_MAX; i++) { + vie_ctrl = &wdev->vie_ctrl[i]; + vie = vie_ctrl->vie_in_frm; + vie_ctrl->type = 0; + + while ((vie != NULL) && (vie_ctrl->vie_num > 0)) { + if (vie->next_vie != NULL) + temp_vie = vie->next_vie; + + if (vie->ie_ctnt != NULL) { + os_free_mem(NULL, vie->ie_ctnt); + vie->ie_ctnt = NULL; + } + vie->next_vie = NULL; + os_free_mem(NULL, vie); + + vie_ctrl->vie_num--; + + vie = temp_vie; + } + vie_ctrl->vie_in_frm = NULL; + } +} +#endif + + + +ULONG build_vendor_ie(struct _RTMP_ADAPTER *pAd, + struct wifi_dev *wdev, + UCHAR *frame_buffer +#ifdef CONFIG_OWE_SUPPORT + , VIE_FRM_TYPE vie_frm_type +#endif +#ifdef WH_EZ_SETUP + , UCHAR SubType +#endif + ) +{ + struct _ralink_ie ra_ie; + ULONG ra_ie_len = 0; + +#ifdef CONFIG_OWE_SUPPORT + VIE_CTRL *vie_ctrl = NULL; + ULONG app_vie_len; + struct vie_struct *vie = NULL; + struct _generic_vie_t vendor_ie; +#endif + +#ifdef MT_MAC + struct _mediatek_ie mtk_ie; + ULONG mtk_ie_len = 0; + struct _mediatek_vht_ie mtk_vht_ie; + ULONG mtk_vht_ie_len = 0; + UCHAR mtk_vht_cap[] = { + 0xBF, // EID + 0x0C, // LEN + 0xB1, 0x01, 0xC0, 0x33, // VHT Cap. Info. + 0x2A, 0xFF, 0x92, 0x04, 0x2A, 0xFF, 0x92, 0x04 //Supported MCS and Nss + }; + UCHAR mtk_vht_op[] = { + 0xC0, // EID + 0x05, // LEN + 0x0, 0x0, 0x0, // VHT Op. Info. + 0x2A, 0xFF // Basic MCS and Nss + }; + UCHAR mtk_vht_txpwr_env[] = { + 0xC3, // EID + 0x03, // LEN + 0x01, // TX PWR Info. + 0x02, 0x02 // Max. Power for 20 & 40Mhz + }; +#endif /* MT_MAC */ +#ifdef BRCM_256QAM + struct _broadcom_ie brcm_ie; + UCHAR brcm_vht_cap[] = { + 0xBF, // EID + 0x0C, // LEN + 0xB2, 0x59, 0x82, 0x0F, // VHT Cap. Info. + 0xEA, 0xFF, 0x0, 0x0, 0xEA, 0xFF, 0x0, 0x0 //Supported MCS and Nss + }; + UCHAR brcm_vht_op[] = { + 0xC0, // EID + 0x05, // LEN + 0x0, 0x04, 0x0, // VHT Op. Info. + 0x0, 0x0 // Basic MCS and Nss + }; + UCHAR brcm_vht_txpwe_env[] = { + 0xC3, // EID + 0x03, // LEN + 0x01, // TX PWR Info. + 0x02, 0x02 // Max. Power for 20 & 40Mhz + }; + ULONG brcm_ie_len = 0; +#endif /* BRCM_256QAM */ + ULONG vendor_ie_len = 0; + + NdisZeroMemory(&ra_ie, sizeof(struct _ralink_ie)); + + ra_ie.ie_hdr.eid = IE_VENDOR_SPECIFIC; + ra_ie.ie_hdr.len = 0x7; + ra_ie.oui[0] = 0x00; + ra_ie.oui[1] = 0x0C; + ra_ie.oui[2] = 0x43; + + if (pAd->CommonCfg.bAggregationCapable) { + ra_ie.cap0 |= RALINK_AGG_CAP; + } + + if (pAd->CommonCfg.bPiggyBackCapable) { + ra_ie.cap0 |= RALINK_PIGGY_CAP; + } + + if (pAd->CommonCfg.bRdg) { + ra_ie.cap0 |= RALINK_RDG_CAP; + } + MakeOutgoingFrame(frame_buffer, + &ra_ie_len, (ra_ie.ie_hdr.len + 2), &ra_ie, + END_OF_ARGS); + + //hex_dump ("build vendor_ie: Ralink_OUI", frame_buffer, (ra_ie.ie_hdr.len + 2)); + + vendor_ie_len = ra_ie_len; + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + +#ifdef WH_EZ_SETUP + /* + To prevent old device has trouble to parse MTK vendor IE, + insert easy setup IE first. + */ + if (IS_EZ_SETUP_ENABLED(wdev) && + ((SubType == SUBTYPE_BEACON) || (SubType == SUBTYPE_PROBE_RSP))) { + vendor_ie_len += ez_build_beacon_ie(wdev, (frame_buffer + vendor_ie_len)); + } else { + if (ez_is_triband()) + { + if (!IS_EZ_SETUP_ENABLED(wdev) && ((SubType == SUBTYPE_BEACON) || (SubType == SUBTYPE_PROBE_RSP))) + { + ULONG tmp_len = 0; + ez_triband_insert_tlv(wdev->sys_handle, EZ_TAG_NON_EZ_BEACON, + frame_buffer + vendor_ie_len, + &tmp_len); + vendor_ie_len += tmp_len; + } + } + } +#endif /* WH_EZ_SETUP */ + + NdisZeroMemory(&mtk_ie, sizeof(struct _mediatek_ie)); + NdisZeroMemory(&mtk_vht_ie, sizeof(struct _mediatek_vht_ie)); + mtk_vht_ie_len = sizeof(mtk_vht_cap) + sizeof(mtk_vht_op) + sizeof(mtk_vht_txpwr_env); + + mtk_ie.ie_hdr.eid = IE_VENDOR_SPECIFIC; + mtk_ie.ie_hdr.len = (0x7 + mtk_vht_ie_len); + mtk_ie.oui[0] = 0x00; + mtk_ie.oui[1] = 0x0C; + mtk_ie.oui[2] = 0xE7; + //MTK VHT CAP IE + memcpy(&mtk_vht_ie.vht_cap, (VHT_CAP *)mtk_vht_cap, sizeof(VHT_CAP)); + //MTK VHT OP IE + memcpy(&mtk_vht_ie.vht_op, (VHT_OP *)mtk_vht_op, sizeof(VHT_OP)); + //MTK VHT TX PWR ENV IE + memcpy(&mtk_vht_ie.vht_txpwr_env, (VHT_TX_PWR_ENV *)mtk_vht_txpwr_env, + sizeof(VHT_TX_PWR_ENV)); +#ifdef MWDS + if(wdev->bSupportMWDS) { + mtk_ie.cap0 |= MEDIATEK_MWDS_CAP; + } +#endif /* MWDS */ +#ifdef STA_FORCE_ROAM_SUPPORT + if((wdev->wdev_type == WDEV_TYPE_STA) && pAd->en_force_roam_supp) + mtk_ie.cap0 |= MEDIATEK_CLI_ENTRY; +#endif + MakeOutgoingFrame((frame_buffer + vendor_ie_len), + &mtk_ie_len, sizeof(struct _mediatek_ie), &mtk_ie, + END_OF_ARGS); + + vendor_ie_len += mtk_ie_len; + + MakeOutgoingFrame((frame_buffer + vendor_ie_len), + &mtk_vht_ie_len, + (sizeof(mtk_vht_cap) + sizeof(mtk_vht_op) + sizeof(mtk_vht_txpwr_env)), + &mtk_vht_ie, + END_OF_ARGS); + + //hex_dump ("build vendor_ie: MediaTek_OUI", + // (frame_buffer+vendor_ie_len-mtk_ie_len), (mtk_ie.ie_hdr.len + 2)); + + vendor_ie_len += mtk_vht_ie_len; + +#ifdef WH_EVENT_NOTIFIER + if(wdev->custom_vie.ie_hdr.len > 0) + { + ULONG custom_vie_len; + ULONG total_custom_vie_len = sizeof(struct Custom_IE_Header) + wdev->custom_vie.ie_hdr.len; + MakeOutgoingFrame((frame_buffer + vendor_ie_len), + &custom_vie_len, total_custom_vie_len, (UCHAR*)&wdev->custom_vie, END_OF_ARGS); + vendor_ie_len += custom_vie_len; + } +#endif /* WH_EVENT_NOTIFIER */ + } +#endif /* MT_MAC */ + +#ifdef BRCM_256QAM + NdisZeroMemory(&brcm_ie, sizeof(struct _broadcom_ie)); + + if (pAd->CommonCfg.g_band_256_qam && pAd->chipCap.g_band_256_qam + && WMODE_CAP(wdev->PhyMode, WMODE_GN)) { + brcm_ie.ie_hdr.eid = IE_VENDOR_SPECIFIC; + brcm_ie.ie_hdr.len = 0x1F; // VHT_CAP + VHT_OP + VHT_TX_PWR_ENV + brcm_ie.oui[0] = 0x00; + brcm_ie.oui[1] = 0x90; + brcm_ie.oui[2] = 0x4C; + brcm_ie.fixed_pattern[0] = 0x04; + brcm_ie.fixed_pattern[1] = 0x08; + //BRCM VHT CAP IE + memcpy(&brcm_ie.vht_cap, (VHT_CAP *)brcm_vht_cap, sizeof(VHT_CAP)); + //BRCM VHT OP IE + memcpy(&brcm_ie.vht_op, (VHT_OP *)brcm_vht_op, sizeof(VHT_OP)); + //BRCM VHT TX PWR ENV IE + memcpy(&brcm_ie.vht_txpwr_env, (VHT_TX_PWR_ENV *)brcm_vht_txpwe_env, + sizeof(VHT_TX_PWR_ENV)); + + MakeOutgoingFrame((frame_buffer + vendor_ie_len), + &brcm_ie_len, (brcm_ie.ie_hdr.len + 2), &brcm_ie, + END_OF_ARGS); + + //hex_dump ("build vendor_ie: Broadcom_OUI", + // (frame_buffer+vendor_ie_len), (brcm_ie.ie_hdr.len + 2)); + + vendor_ie_len += brcm_ie_len; + } +#endif /* BRCM_256QAM */ +#ifdef CONFIG_OWE_SUPPORT + get_vie_ctrl(wdev, &vie_ctrl, GET_VIE_FRM_BITMAP(vie_frm_type)); + if (vie_ctrl == NULL) + goto end; + + vie = vie_ctrl->vie_in_frm; + for (vie = vie_ctrl->vie_in_frm; (vie != NULL); vie = vie->next_vie) { + app_vie_len = 0; + NdisZeroMemory(&vendor_ie, sizeof(struct _generic_vie_t)); + vendor_ie.ie_hdr.eid = IE_VENDOR_SPECIFIC; + vendor_ie.ie_hdr.len = vie->vie_length; + NdisCopyMemory(vendor_ie.vie_ctnt, vie->ie_ctnt, vie->vie_length); + + MakeOutgoingFrame( + (frame_buffer + vendor_ie_len), &app_vie_len, + (vendor_ie.ie_hdr.len + 2), &vendor_ie, + END_OF_ARGS); + + vendor_ie_len += app_vie_len; + } +end: +#endif + return vendor_ie_len; +} + + +#if defined(MWDS) || defined(MAP_SUPPORT) +VOID check_vendor_ie(struct _RTMP_ADAPTER *pAd, + UCHAR *ie_buffer, struct _vendor_ie_cap *vendor_ie) +{ + PEID_STRUCT info_elem = (PEID_STRUCT)ie_buffer; + UCHAR ralink_oui[] = {0x00, 0x0c, 0x43}; + UCHAR mediatek_oui[] = {0x00, 0x0c, 0xe7}; + UCHAR broadcom_oui[] = {0x00, 0x90, 0x4c}; + UCHAR quantenna_oui[] = {0x00, 0x26, 0x86}; + //UCHAR broadcom_fixed_pattern[] = {0x04, 0x08}; + + if (NdisEqualMemory(info_elem->Octet, ralink_oui, 3) + && (info_elem->Len == 7)) + { + vendor_ie->ra_cap = (ULONG)info_elem->Octet[3]; + vendor_ie->is_rlt = TRUE; + vendor_ie->ldpc = TRUE; + vendor_ie->sgi = TRUE; + //hex_dump ("recv. vendor_ie: Ralink_OUI", (UCHAR *)info_elem, (info_elem->Len + 2)); + } + else if (NdisEqualMemory(info_elem->Octet, mediatek_oui, 3) + && (info_elem->Len >= 7)) + { + vendor_ie->mtk_cap = (ULONG)info_elem->Octet[3]; + vendor_ie->is_mtk = TRUE; + +#define MAP_TURNKEY_IE(B1) ((B1)&0x01) + +#ifdef WH_EZ_SETUP // Rakesh: Parse Easy setup IE only if easy enabled on own, acceptable?? + if ((IS_ADPTR_EZ_SETUP_ENABLED(pAd)) && (info_elem->Octet[3] & MEDIATEK_EASY_SETUP)) { + ez_vendor_ie_parse(vendor_ie, info_elem); + } + else +#endif /* WH_EZ_SETUP */ + if (info_elem->Len > 7) { + + /* have MTK VHT IEs */ + vendor_ie->ldpc = TRUE; + vendor_ie->sgi = TRUE; +#ifdef MWDS + /* We can't be covered by easy setup customized mtk ie. */ + vendor_ie->mtk_cap_found = TRUE; + if (MWDS_SUPPORT(vendor_ie->mtk_cap)) + vendor_ie->support_mwds = TRUE; + else + vendor_ie->support_mwds = FALSE; +#endif /* MWDS */ + } else { + vendor_ie->ldpc = FALSE; + vendor_ie->sgi = FALSE; + } + //hex_dump ("recv. vendor_ie: MediaTek_OUI", (UCHAR *)info_elem, (info_elem->Len + 2)); + } + else if (NdisEqualMemory(info_elem->Octet, broadcom_oui, 3) + //&& NdisEqualMemory(info_elem->Octet+3, broadcom_fixed_pattern, 2)) + ) + { + vendor_ie->brcm_cap = BROADCOM_256QAM_CAP; + vendor_ie->ldpc = TRUE; + vendor_ie->sgi = TRUE; + //hex_dump ("recv. vendor_ie: Broadcom_OUI", (UCHAR *)info_elem, (info_elem->Len + 2)); + } + else if (NdisEqualMemory(info_elem->Octet, quantenna_oui, 3)) + { + vendor_ie->is_quant = TRUE; + } +#ifdef WH_EVENT_NOTIFIER + else if(pAd->ApCfg.EventNotifyCfg.CustomOUILen && + (info_elem->Len >= pAd->ApCfg.EventNotifyCfg.CustomOUILen) && + NdisEqualMemory(info_elem->Octet, pAd->ApCfg.EventNotifyCfg.CustomOUI,pAd->ApCfg.EventNotifyCfg.CustomOUILen)) + { + vendor_ie->custom_ie_len = info_elem->Len; + NdisMoveMemory(vendor_ie->custom_ie, info_elem->Octet, info_elem->Len); + } +#endif /* WH_EVENT_NOTIFIER */ + else + { + //printk ("Other Vendor IE: OUI: %02x %02x %02x\n", + // info_elem->Octet[0], info_elem->Octet[1], info_elem->Octet[2]); + //hex_dump ("recv. vendor_ie: xxx_OUI", (UCHAR *)info_elem, (info_elem->Len + 2)); + } +} +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/vht.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/vht.c new file mode 100644 index 000000000..50f5a575a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/vht.c @@ -0,0 +1,638 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#include "rt_config.h" + + +struct vht_ch_layout{ + UCHAR ch_low_bnd; + UCHAR ch_up_bnd; + UCHAR cent_freq_idx; +}; + +static struct vht_ch_layout vht_ch_80M[]={ + {36, 48, 42}, + {52, 64, 58}, + {100,112, 106}, + {116, 128, 122}, + {132, 144, 138}, + {149, 161, 155}, + {0, 0 ,0}, +}; + + + + +VOID dump_vht_cap(RTMP_ADAPTER *pAd, VHT_CAP_IE *vht_ie) +{ + VHT_CAP_INFO *vht_cap = &vht_ie->vht_cap; + VHT_MCS_SET *vht_mcs = &vht_ie->mcs_set; + + DBGPRINT(RT_DEBUG_OFF, ("Dump VHT_CAP IE\n")); + hex_dump("VHT CAP IE Raw Data", (UCHAR *)vht_ie, sizeof(VHT_CAP_IE)); + + DBGPRINT(RT_DEBUG_OFF, ("VHT Capabilities Info Field\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tMaximum MPDU Length=%d\n", vht_cap->max_mpdu_len)); + DBGPRINT(RT_DEBUG_OFF, ("\tSupported Channel Width=%d\n", vht_cap->ch_width)); + DBGPRINT(RT_DEBUG_OFF, ("\tRxLDPC=%d\n", vht_cap->rx_ldpc)); + DBGPRINT(RT_DEBUG_OFF, ("\tShortGI_80M=%d\n", vht_cap->sgi_80M)); + DBGPRINT(RT_DEBUG_OFF, ("\tShortGI_160M=%d\n", vht_cap->sgi_160M)); + DBGPRINT(RT_DEBUG_OFF, ("\tTxSTBC=%d\n", vht_cap->tx_stbc)); + DBGPRINT(RT_DEBUG_OFF, ("\tRxSTBC=%d\n", vht_cap->rx_stbc)); + DBGPRINT(RT_DEBUG_OFF, ("\tSU BeamformerCap=%d\n", vht_cap->bfer_cap_su)); + DBGPRINT(RT_DEBUG_OFF, ("\tSU BeamformeeCap=%d\n", vht_cap->bfee_cap_su)); + DBGPRINT(RT_DEBUG_OFF, ("\tCompressedSteeringNumOfBeamformerAnt=%d\n", vht_cap->cmp_st_num_bfer)); + DBGPRINT(RT_DEBUG_OFF, ("\tNumber of Sounding Dimensions=%d\n", vht_cap->num_snd_dimension)); + DBGPRINT(RT_DEBUG_OFF, ("\tMU BeamformerCap=%d\n", vht_cap->bfer_cap_mu)); + DBGPRINT(RT_DEBUG_OFF, ("\tMU BeamformeeCap=%d\n", vht_cap->bfee_cap_mu)); + DBGPRINT(RT_DEBUG_OFF, ("\tVHT TXOP PS=%d\n", vht_cap->vht_txop_ps)); + DBGPRINT(RT_DEBUG_OFF, ("\t+HTC-VHT Capable=%d\n", vht_cap->htc_vht_cap)); + DBGPRINT(RT_DEBUG_OFF, ("\tMaximum A-MPDU Length Exponent=%d\n", vht_cap->max_ampdu_exp)); + DBGPRINT(RT_DEBUG_OFF, ("\tVHT LinkAdaptation Capable=%d\n", vht_cap->vht_link_adapt)); + + DBGPRINT(RT_DEBUG_OFF, ("VHT Supported MCS Set Field\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tRx Highest SupDataRate=%d\n", vht_mcs->rx_high_rate)); + DBGPRINT(RT_DEBUG_OFF, ("\tRxMCS Map_1SS=%d\n", vht_mcs->rx_mcs_map.mcs_ss1)); + DBGPRINT(RT_DEBUG_OFF, ("\tRxMCS Map_2SS=%d\n", vht_mcs->rx_mcs_map.mcs_ss2)); + DBGPRINT(RT_DEBUG_OFF, ("\tTx Highest SupDataRate=%d\n", vht_mcs->tx_high_rate)); + DBGPRINT(RT_DEBUG_OFF, ("\tTxMCS Map_1SS=%d\n", vht_mcs->tx_mcs_map.mcs_ss1)); + DBGPRINT(RT_DEBUG_OFF, ("\tTxMCS Map_2SS=%d\n", vht_mcs->tx_mcs_map.mcs_ss2)); +} + + +VOID dump_vht_op(RTMP_ADAPTER *pAd, VHT_OP_IE *vht_ie) +{ + VHT_OP_INFO *vht_op = &vht_ie->vht_op_info; + VHT_MCS_MAP *vht_mcs = &vht_ie->basic_mcs_set; + + DBGPRINT(RT_DEBUG_OFF, ("Dump VHT_OP IE\n")); + hex_dump("VHT OP IE Raw Data", (UCHAR *)vht_ie, sizeof(VHT_OP_IE)); + + DBGPRINT(RT_DEBUG_OFF, ("VHT Operation Info Field\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tChannelWidth=%d\n", vht_op->ch_width)); + DBGPRINT(RT_DEBUG_OFF, ("\tChannelCenterFrequency Seg 1=%d\n", vht_op->center_freq_1)); + DBGPRINT(RT_DEBUG_OFF, ("\tChannelCenterFrequency Seg 1=%d\n", vht_op->center_freq_2)); + + DBGPRINT(RT_DEBUG_OFF, ("VHT Basic MCS Set Field\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tRxMCS Map_1SS=%d\n", vht_mcs->mcs_ss1)); + DBGPRINT(RT_DEBUG_OFF, ("\tRxMCS Map_2SS=%d\n", vht_mcs->mcs_ss2)); +} + + +#ifdef VHT_TXBF_SUPPORT +VOID trigger_vht_ndpa(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *entry) +{ + UCHAR *buf; + VHT_NDPA_FRAME *vht_ndpa; + struct wifi_dev *wdev = entry->wdev; + UINT frm_len, sta_cnt; + SNDING_STA_INFO *sta_info; + + if (MlmeAllocateMemory(pAd, &buf) != NDIS_STATUS_SUCCESS) + return; + + NdisZeroMemory(buf, MGMT_DMA_BUFFER_SIZE); + + vht_ndpa = (VHT_NDPA_FRAME *)buf; + frm_len = sizeof(VHT_NDPA_FRAME); + vht_ndpa->fc.Type = FC_TYPE_CNTL; + vht_ndpa->fc.SubType = SUBTYPE_VHT_NDPA; + COPY_MAC_ADDR(vht_ndpa->ra, entry->Addr); + COPY_MAC_ADDR(vht_ndpa->ta, wdev->if_addr); + + /* Currnetly we only support 1 STA for a VHT DNPA */ + sta_info = vht_ndpa->sta_info; + for (sta_cnt = 0; sta_cnt < 1; sta_cnt++) { + sta_info->aid12 = entry->Aid; + sta_info->fb_type = SNDING_FB_SU; + sta_info->nc_idx = 0; + vht_ndpa->token.token_num = entry->snd_dialog_token; + frm_len += sizeof(SNDING_STA_INFO); + sta_info++; + if (frm_len >= (MGMT_DMA_BUFFER_SIZE - sizeof(SNDING_STA_INFO))) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): len(%d) too large!cnt=%d\n", + __FUNCTION__, frm_len, sta_cnt)); + break; + } + } + if (entry->snd_dialog_token & 0xc0) + entry->snd_dialog_token = 0; + else + entry->snd_dialog_token++; + + vht_ndpa->duration = pAd->CommonCfg.Dsifs + + RTMPCalcDuration(pAd, pAd->CommonCfg.MlmeRate, frm_len); + + DBGPRINT(RT_DEBUG_OFF, ("Send VHT NDPA Frame to STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", + PRINT_MAC(entry->Addr))); + hex_dump("VHT NDPA Frame", buf, frm_len); + MiniportMMRequest(pAd, 0, buf, frm_len); + MlmeFreeMemory(pAd, buf); + +#ifdef SOFT_SOUNDING + if (1) { + HEADER_802_11 *pNullFr; + UCHAR *qos_p; + UCHAR NullFrame[48]; + + NdisZeroMemory(NullFrame, 48); + pNullFr = (PHEADER_802_11)&NullFrame[0]; + frm_len = sizeof(HEADER_802_11); + + pNullFr->FC.Type = FC_TYPE_DATA; + pNullFr->FC.SubType = SUBTYPE_QOS_NULL; + pNullFr->FC.FrDs = 1; + pNullFr->FC.ToDs = 0; + COPY_MAC_ADDR(pNullFr->Addr1, entry->Addr); + COPY_MAC_ADDR(pNullFr->Addr2, wdev->if_addr); + COPY_MAC_ADDR(pNullFr->Addr3, wdev->bssid); + + qos_p = ((UCHAR *)pNullFr) + frm_len; + qos_p[0] = 0; + qos_p[1] = 0; + frm_len += 2; + + entry->snd_reqired = TRUE; + DBGPRINT(RT_DEBUG_OFF, ("Send sounding QoSNULL Frame to STA(%02x:%02x:%02x:%02x:%02x:%02x)\n", + PRINT_MAC(entry->Addr))); + + hex_dump("VHT NDP Frame(QoSNull)", NullFrame, frm_len); + + HAL_KickOutNullFrameTx(pAd, 0, NullFrame, frm_len); + } +#endif /* SOFT_SOUNDING */ + +} +#endif /* VHT_TXBF_SUPPORT */ + + +/* + Get BBP Channel Index by RF channel info + return value: 0~3 +*/ +UCHAR vht_prim_ch_idx(UCHAR vht_cent_ch, UCHAR prim_ch) +{ + INT idx = 0; + UCHAR bbp_idx = 0; + + if (vht_cent_ch == prim_ch) + goto done; + + while (vht_ch_80M[idx].ch_up_bnd != 0) + { + if (vht_cent_ch == vht_ch_80M[idx].cent_freq_idx) + { + if (prim_ch == vht_ch_80M[idx].ch_up_bnd) + bbp_idx = 3; + else if (prim_ch == vht_ch_80M[idx].ch_low_bnd) + bbp_idx = 0; + else { + bbp_idx = prim_ch > vht_cent_ch ? 2 : 1; + } + break; + } + idx++; + } + +done: + DBGPRINT(RT_DEBUG_INFO, ("%s():(VhtCentCh=%d, PrimCh=%d) =>BbpChIdx=%d\n", + __FUNCTION__, vht_cent_ch, prim_ch, bbp_idx)); + return bbp_idx; +} + + +/* + Currently we only consider about VHT 80MHz! +*/ +UCHAR vht_cent_ch_freq(RTMP_ADAPTER *pAd, UCHAR prim_ch) +{ + INT idx = 0; + + + if (pAd->CommonCfg.vht_bw < VHT_BW_80 || prim_ch < 36) + { + //pAd->CommonCfg.vht_cent_ch = 0; + //pAd->CommonCfg.vht_cent_ch2 = 0; + return prim_ch; + } + + while (vht_ch_80M[idx].ch_up_bnd != 0) + { + if (prim_ch >= vht_ch_80M[idx].ch_low_bnd && + prim_ch <= vht_ch_80M[idx].ch_up_bnd) + { + //pAd->CommonCfg.vht_cent_ch = vht_ch_80M[idx].cent_freq_idx; + return vht_ch_80M[idx].cent_freq_idx; + } + idx++; + } + + return prim_ch; +} + + +INT vht_mode_adjust(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, VHT_CAP_IE *cap, VHT_OP_IE *op) +{ + pEntry->MaxHTPhyMode.field.MODE = MODE_VHT; + pAd->CommonCfg.AddHTInfo.AddHtInfo2.NonGfPresent = 1; + pAd->MacTab.fAnyStationNonGF = TRUE; + + if (op->vht_op_info.ch_width >= 1 && pEntry->MaxHTPhyMode.field.BW == BW_40) + { + pEntry->MaxHTPhyMode.field.BW= BW_80; + pEntry->MaxHTPhyMode.field.ShortGI = (cap->vht_cap.sgi_80M); + pEntry->MaxHTPhyMode.field.STBC = (cap->vht_cap.rx_stbc > 1 ? 1 : 0); + } + + return TRUE; +} + + +INT get_vht_op_ch_width(RTMP_ADAPTER *pAd) +{ + + return TRUE; +} + + +/******************************************************************** + Procedures for 802.11 AC Information elements +********************************************************************/ +/* + Defined in IEEE 802.11AC + + Appeared in Beacon, ProbResp frames +*/ +INT build_quiet_channel(RTMP_ADAPTER *pAd, UCHAR *buf) +{ + INT len = 0; + + + return len; +} + + +/* + Defined in IEEE 802.11AC + + Appeared in Beacon, ProbResp frames +*/ +INT build_ext_bss_load(RTMP_ADAPTER *pAd, UCHAR *buf) +{ + INT len = 0; + + + return len; +} + + + + +/* + Defined in IEEE 802.11AC + + Appeared in Beacon, ProbResp frames +*/ +INT build_ext_pwr_constraint(RTMP_ADAPTER *pAd, UCHAR *buf) +{ + INT len = 0; + + + return len; +} + + +/* + Defined in IEEE 802.11AC + + Appeared in Beacon, ProbResp frames +*/ +INT build_vht_txpwr_envelope(RTMP_ADAPTER *pAd, UCHAR *buf) +{ + INT len = 0, pwr_cnt; + VHT_TXPWR_ENV_IE txpwr_env; + + NdisZeroMemory(&txpwr_env, sizeof(txpwr_env)); + + if (pAd->CommonCfg.vht_bw == VHT_BW_80) { + pwr_cnt = 2; + } else { + if (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 1) + pwr_cnt = 1; + else + pwr_cnt = 0; + } + txpwr_env.tx_pwr_info.max_tx_pwr_cnt = pwr_cnt; + txpwr_env.tx_pwr_info.max_tx_pwr_interpretation = TX_PWR_INTERPRET_EIRP; + +// TODO: fixme, we need the real tx_pwr value for each port. + for (len = 0; len < pwr_cnt; len++) + txpwr_env.tx_pwr_bw[len] = 15; + + len = 2 + pwr_cnt; + NdisMoveMemory(buf, &txpwr_env, len); + + return len; +} + + +/* + Defined in IEEE 802.11AC + + Appeared in Beacon, (Re)AssocResp, ProbResp frames +*/ +INT build_vht_op_ie(RTMP_ADAPTER *pAd, UCHAR *buf) +{ + VHT_OP_IE vht_op; + UCHAR cent_ch; +#ifdef RT_BIG_ENDIAN + UINT16 tmp; +#endif /* RT_BIG_ENDIAN */ + + NdisZeroMemory((UCHAR *)&vht_op, sizeof(VHT_OP_IE)); + vht_op.vht_op_info.ch_width = (pAd->CommonCfg.vht_bw == VHT_BW_80 ? 1: 0); + +#ifdef CONFIG_AP_SUPPORT + if (pAd->CommonCfg.Channel > 14 && + (pAd->CommonCfg.bIEEE80211H == 1) && + (pAd->Dot11_H.RDMode == RD_SWITCHING_MODE)) + cent_ch = vht_cent_ch_freq(pAd, pAd->Dot11_H.org_ch); + else +#endif /* CONFIG_AP_SUPPORT */ + cent_ch = vht_cent_ch_freq(pAd, pAd->CommonCfg.Channel); + + switch (vht_op.vht_op_info.ch_width) + { + case 0: + vht_op.vht_op_info.center_freq_1 = 0; + vht_op.vht_op_info.center_freq_2 = 0; + break; + case 1: + case 2: + vht_op.vht_op_info.center_freq_1 = cent_ch; + vht_op.vht_op_info.center_freq_2 = 0; + break; + case 3: + vht_op.vht_op_info.center_freq_1 = cent_ch; + vht_op.vht_op_info.center_freq_2 = pAd->CommonCfg.vht_cent_ch2; + break; + } + + vht_op.basic_mcs_set.mcs_ss1 = VHT_MCS_CAP_NA; + vht_op.basic_mcs_set.mcs_ss2 = VHT_MCS_CAP_NA; + vht_op.basic_mcs_set.mcs_ss3 = VHT_MCS_CAP_NA; + vht_op.basic_mcs_set.mcs_ss4 = VHT_MCS_CAP_NA; + vht_op.basic_mcs_set.mcs_ss5 = VHT_MCS_CAP_NA; + vht_op.basic_mcs_set.mcs_ss6 = VHT_MCS_CAP_NA; + vht_op.basic_mcs_set.mcs_ss7 = VHT_MCS_CAP_NA; + vht_op.basic_mcs_set.mcs_ss8 = VHT_MCS_CAP_NA; + switch (pAd->CommonCfg.RxStream) + { + case 2: + vht_op.basic_mcs_set.mcs_ss2 = VHT_MCS_CAP_7; + case 1: + vht_op.basic_mcs_set.mcs_ss1 = VHT_MCS_CAP_7; + break; + } + +#ifdef RT_BIG_ENDIAN + //SWAP16((UINT16)vht_op.basic_mcs_set); + NdisCopyMemory(&tmp,&vht_op.basic_mcs_set, 2); + tmp=SWAP16(tmp); + NdisCopyMemory(&vht_op.basic_mcs_set,&tmp, 2); +#endif /* RT_BIG_ENDIAN */ + NdisMoveMemory((UCHAR *)buf, (UCHAR *)&vht_op, sizeof(VHT_OP_IE)); + + return sizeof(VHT_OP_IE); +} + + +/* + Defined in IEEE 802.11AC + + Appeared in Beacon, (Re)AssocReq, (Re)AssocResp, ProbReq/Resp frames +*/ +INT build_vht_cap_ie(RTMP_ADAPTER *pAd, UCHAR *buf) +{ + VHT_CAP_IE vht_cap_ie; + INT rx_nss, tx_nss, mcs_cap; +#ifdef RT_BIG_ENDIAN + UINT32 tmp_1; + UINT64 tmp_2; +#endif /*RT_BIG_ENDIAN*/ + + NdisZeroMemory((UCHAR *)&vht_cap_ie, sizeof(VHT_CAP_IE)); + vht_cap_ie.vht_cap.max_mpdu_len = 0; // TODO: Ask Jerry about hardware limitation. + vht_cap_ie.vht_cap.ch_width = 0; /* not support 160 or 80 + 80 MHz */ + + if (pAd->CommonCfg.vht_ldpc && (pAd->chipCap.phy_caps & fPHY_CAP_LDPC)) + vht_cap_ie.vht_cap.rx_ldpc = 1; + else + vht_cap_ie.vht_cap.rx_ldpc = 0; + + vht_cap_ie.vht_cap.sgi_80M = pAd->CommonCfg.vht_sgi_80; + vht_cap_ie.vht_cap.htc_vht_cap = 1; + vht_cap_ie.vht_cap.max_ampdu_exp = 3; // TODO: Ask Jerry about the hardware limitation, currently set as 64K + + vht_cap_ie.vht_cap.tx_stbc = 0; + vht_cap_ie.vht_cap.rx_stbc = 0; + if (pAd->CommonCfg.vht_stbc) + { + if (pAd->CommonCfg.TxStream >= 2) + vht_cap_ie.vht_cap.tx_stbc = 1; + else + vht_cap_ie.vht_cap.tx_stbc = 0; + + if (pAd->CommonCfg.RxStream >= 1) + vht_cap_ie.vht_cap.rx_stbc = 1; // TODO: is it depends on the number of our antennas? + else + vht_cap_ie.vht_cap.rx_stbc = 0; + } + + vht_cap_ie.vht_cap.tx_ant_consistency = 1; + vht_cap_ie.vht_cap.rx_ant_consistency = 1; + + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss1 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss2 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss3 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss4 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss5 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss6 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss7 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss8 = VHT_MCS_CAP_NA; + + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss1 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss2 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss3 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss4 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss5 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss6 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss7 = VHT_MCS_CAP_NA; + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss8 = VHT_MCS_CAP_NA; + + mcs_cap = pAd->chipCap.max_vht_mcs; + + rx_nss = pAd->CommonCfg.RxStream; + tx_nss = pAd->CommonCfg.TxStream; +#ifdef WFA_VHT_PF + if ((pAd->CommonCfg.vht_nss_cap > 0) && + (pAd->CommonCfg.vht_nss_cap < pAd->CommonCfg.RxStream)) + rx_nss = pAd->CommonCfg.vht_nss_cap; + + if ((pAd->CommonCfg.vht_nss_cap > 0) && + (pAd->CommonCfg.vht_nss_cap < pAd->CommonCfg.TxStream)) + tx_nss = pAd->CommonCfg.vht_nss_cap; + + if (pAd->CommonCfg.vht_mcs_cap chipCap.max_vht_mcs) + mcs_cap = pAd->CommonCfg.vht_mcs_cap; +#endif /* WFA_VHT_PF */ + + switch (rx_nss) + { + case 1: + vht_cap_ie.mcs_set.rx_high_rate = 292; + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss1 = mcs_cap; + break; + case 2: + if (mcs_cap == VHT_MCS_CAP_9) + vht_cap_ie.mcs_set.rx_high_rate = 780; + else + vht_cap_ie.mcs_set.rx_high_rate = 585; + + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss1 = mcs_cap; + vht_cap_ie.mcs_set.rx_mcs_map.mcs_ss2 = mcs_cap; + break; + default: + vht_cap_ie.mcs_set.rx_high_rate = 0; + break; + } + + switch (tx_nss) + { + case 1: + vht_cap_ie.mcs_set.tx_high_rate = 292; + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss1 = mcs_cap; + break; + case 2: + if (mcs_cap == VHT_MCS_CAP_9) + vht_cap_ie.mcs_set.tx_high_rate = 780; + else + vht_cap_ie.mcs_set.tx_high_rate = 585; + + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss1 = mcs_cap; + vht_cap_ie.mcs_set.tx_mcs_map.mcs_ss2 = mcs_cap; + break; + default: + vht_cap_ie.mcs_set.tx_high_rate = 0; + break; + } + +#ifdef RT_BIG_ENDIAN + NdisCopyMemory(&tmp_1,&vht_cap_ie.vht_cap, 4); + tmp_1 = SWAP32(tmp_1); + NdisCopyMemory(&vht_cap_ie.vht_cap,&tmp_1, 4); + + NdisCopyMemory(&tmp_2,&vht_cap_ie.mcs_set, 8); + tmp_2=SWAP64(tmp_2); + NdisCopyMemory(&vht_cap_ie.mcs_set,&tmp_2, 8); + + //hex_dump("&vht_cap_ie", &vht_cap_ie, sizeof(VHT_CAP_IE)); + //SWAP32((UINT32)vht_cap_ie.vht_cap); + //SWAP32((UINT32)vht_cap_ie.mcs_set); +#endif /* RT_BIG_ENDIAN */ + +#ifdef VHT_TXBF_SUPPORT + if (pAd->chipCap.FlgHwTxBfCap) + { + vht_cap_ie.vht_cap.num_snd_dimension = pAd->CommonCfg.vht_cap_ie.vht_cap.num_snd_dimension; + vht_cap_ie.vht_cap.cmp_st_num_bfer= pAd->CommonCfg.vht_cap_ie.vht_cap.cmp_st_num_bfer; + vht_cap_ie.vht_cap.bfee_cap_su=pAd->CommonCfg.vht_cap_ie.vht_cap.bfee_cap_su; + vht_cap_ie.vht_cap.bfer_cap_su=pAd->CommonCfg.vht_cap_ie.vht_cap.bfer_cap_su; + } +#endif + + NdisMoveMemory(buf, (UCHAR *)&vht_cap_ie, sizeof(VHT_CAP_IE)); + + return sizeof(VHT_CAP_IE); +} + + +INT build_vht_ies(RTMP_ADAPTER *pAd, UCHAR *buf, UCHAR frm) +{ + INT len = 0; + EID_STRUCT eid_hdr; + + + eid_hdr.Eid = IE_VHT_CAP; + eid_hdr.Len = sizeof(VHT_CAP_IE); + NdisMoveMemory(buf, (UCHAR *)&eid_hdr, 2); + len = 2; + + len += build_vht_cap_ie(pAd, (UCHAR *)(buf + len)); + if (frm == SUBTYPE_BEACON || frm == SUBTYPE_PROBE_RSP || + frm == SUBTYPE_ASSOC_RSP || frm == SUBTYPE_REASSOC_RSP) + { + eid_hdr.Eid = IE_VHT_OP; + eid_hdr.Len = sizeof(VHT_OP_IE); + NdisMoveMemory((UCHAR *)(buf + len), (UCHAR *)&eid_hdr, 2); + len +=2; + + len += build_vht_op_ie(pAd, (UCHAR *)(buf + len)); + } + + return len; +} + +BOOLEAN vht80_channel_group( RTMP_ADAPTER *pAd, UCHAR channel) +{ + INT idx = 0; + + if (channel <= 14) + return FALSE; + + while (vht_ch_80M[idx].ch_up_bnd != 0) + { + if (channel >= vht_ch_80M[idx].ch_low_bnd && + channel <= vht_ch_80M[idx].ch_up_bnd) + { + if ( (pAd->CommonCfg.RDDurRegion == JAP || + pAd->CommonCfg.RDDurRegion == JAP_W53 || + pAd->CommonCfg.RDDurRegion == JAP_W56) && + vht_ch_80M[idx].cent_freq_idx == 138) + { + idx++; + continue; + } + + return TRUE; + } + idx++; + } + + return FALSE; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wapi.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wapi.c new file mode 100644 index 000000000..c09f41390 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wapi.c @@ -0,0 +1,1219 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2006, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + wapi.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Albert 2008-4-3 Supoort WAPI protocol +*/ +/*#include */ +/*#include */ +/*#include */ +/*#include */ + +#ifdef WAPI_SUPPORT + +#include "rt_config.h" + +/* WAPI AKM OUI */ +UCHAR OUI_WAI_CERT_AKM[4] = {0x00, 0x14, 0x72, 0x01}; +UCHAR OUI_WAI_PSK_AKM[4] = {0x00, 0x14, 0x72, 0x02}; + +/* WAPI CIPHER OUI */ +UCHAR OUI_WPI_CIPHER_SMS4[4] = {0x00, 0x14, 0x72, 0x01}; + +UCHAR WAPI_TYPE[] = {0x88, 0xb4}; + +/* IV default value */ +UCHAR AE_BCAST_PN[LEN_WAPI_TSC] = {0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, + 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c}; +UCHAR ASUE_UCAST_PN[LEN_WAPI_TSC] = {0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, + 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c}; +UCHAR AE_UCAST_PN[LEN_WAPI_TSC] = {0x37, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, + 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c}; + +BUILD_TIMER_FUNCTION(RTMPWapiUskRekeyPeriodicExec); +BUILD_TIMER_FUNCTION(RTMPWapiMskRekeyPeriodicExec); + +static void kd_hmac_sha256( + unsigned char *key, + unsigned int key_len, + unsigned char *text, + unsigned int text_len, + unsigned char *output, + unsigned int output_len) +{ + int i; + + for (i = 0; output_len/SHA256_DIGEST_SIZE; i++, output_len -= SHA256_DIGEST_SIZE) + { + RT_HMAC_SHA256(key, key_len, text, text_len, &output[i*SHA256_DIGEST_SIZE], SHA256_DIGEST_SIZE); + text = &output[i*SHA256_DIGEST_SIZE]; + text_len = SHA256_DIGEST_SIZE; + } + + if (output_len > 0) + RT_HMAC_SHA256(key, key_len, text, text_len, &output[i*SHA256_DIGEST_SIZE], output_len); + +} + + +/* + ======================================================================== + + Routine Description: + Build WAPI IE in RSN-IE. + It only shall be called by RTMPMakeRSNIE. + + Arguments: + pAd - pointer to our pAdapter context + AuthMode - indicate the authentication mode + WepStatus - indicate the encryption type + + Return Value: + + Note: + + ======================================================================== +*/ +VOID RTMPInsertWapiIe( + IN UINT AuthMode, + IN UINT WepStatus, + OUT PUCHAR pWIe, + OUT UCHAR *w_len) +{ + WAPIIE *pWapiHdr = (WAPIIE*)pWIe; + WAPIIE_UCAST *pWIE_ucast; + WAPIIE_MCAST *pWIE_mcast; + + *w_len = 0; + + /* Assign the verson as 1 */ + pWapiHdr->version = 1; + + /* Set the AKM count and suite */ + pWapiHdr->acount = 1; + switch (AuthMode) + { + case Ndis802_11AuthModeWAICERT: + NdisMoveMemory(pWapiHdr->auth[0].oui, OUI_WAI_CERT_AKM, 4); + break; + + case Ndis802_11AuthModeWAIPSK: + NdisMoveMemory(pWapiHdr->auth[0].oui, OUI_WAI_PSK_AKM, 4); + break; + } + + /* swap for big-endian platform */ + pWapiHdr->version = cpu2le16(pWapiHdr->version); + pWapiHdr->acount = cpu2le16(pWapiHdr->acount); + + /* update current length */ + (*w_len) += sizeof(WAPIIE); + + /* Set the unicast cipher and count */ + pWIE_ucast = (WAPIIE_UCAST*)(pWIe + (*w_len)); + pWIE_ucast->ucount = 1; + NdisMoveMemory(pWIE_ucast->ucast[0].oui, OUI_WPI_CIPHER_SMS4, 4); + + /* swap for big-endian platform */ + pWIE_ucast->ucount = cpu2le16(pWIE_ucast->ucount); + + /* update current length */ + (*w_len) += sizeof(WAPIIE_UCAST); + + /* Set the multicast cipher and capability */ + pWIE_mcast = (WAPIIE_MCAST*)(pWIe + (*w_len)); + NdisMoveMemory(pWIE_mcast->mcast, OUI_WPI_CIPHER_SMS4, 4); + pWIE_mcast->capability = 0; /* Todo AlbertY - support pre-authentication */ + + /* update current length */ + (*w_len) += sizeof(WAPIIE_MCAST); + +} + +/* + ========================================================================== + Description: + Check whether the received frame is WAPI frame. + + Arguments: + pAd - pointer to our pAdapter context + pData - the received frame + DataByteCount - the received frame's length + + Return: + TRUE - This frame is WAPI frame + FALSE - otherwise + ========================================================================== +*/ +BOOLEAN RTMPCheckWAIframe( + IN PUCHAR pData, + IN ULONG DataByteCount) +{ + if(DataByteCount < (LENGTH_802_1_H + LENGTH_WAI_H)) + return FALSE; + + + /* Skip LLC header */ + if (NdisEqualMemory(SNAP_802_1H, pData, 6)) + { + pData += 6; + } + /* Skip 2-bytes EAPoL type */ + if (NdisEqualMemory(WAPI_TYPE, pData, 2)) + { + DBGPRINT(RT_DEBUG_TRACE, ("--> Receive a WAI frame \n")); + pData += 2; + } + else + return FALSE; + + return TRUE; +} + + +/* + ========================================================================== + Description: + Check whether the cipher is SMS4. + + Arguments: + pAd - pointer to our pAdapter context + apidx - interface index + + Return: + TRUE - The cipher is SMS4 + FALSE - otherwise + ========================================================================== +*/ +BOOLEAN RTMPIsWapiCipher( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx) +{ + NDIS_802_11_ENCRYPTION_STATUS cipher_mode = Ndis802_11EncryptionDisabled; + + /* Currently, WAPI only support MBSS */ + if (apidx >= MAX_MBSSID_NUM(pAd) + MAX_P2P_NUM) + return FALSE; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (apidx < MAX_MBSSID_NUM(pAd)) + cipher_mode = pAd->ApCfg.MBSSID[apidx].wdev.WepStatus; + } +#endif /* CONFIG_AP_SUPPORT */ + + 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, + RTMP_STRING *tmpbuf, + RTMP_STRING *buffer) +{ + UINT32 ip_addr; +#ifdef CONFIG_AP_SUPPORT + INT apidx = 0; +#endif /* CONFIG_AP_SUPPORT */ + RTMP_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) + { + RTMP_STRING tok_str[16]; + + /* WapiPskX */ + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + snprintf(tok_str, sizeof(tok_str), "WapiPsk%d", apidx + 1); + + NdisZeroMemory(pAd->ApCfg.MBSSID[apidx].WAPIPassPhrase, 64); + pAd->ApCfg.MBSSID[apidx].WAPIPassPhraseLen = 0; + if(RTMPGetKeyParameter(tok_str, tmpbuf, 65, buffer, FALSE)) + { + if (strlen(tmpbuf) >= 8 && strlen(tmpbuf) <= 64) + { + NdisMoveMemory(pAd->ApCfg.MBSSID[apidx].WAPIPassPhrase, tmpbuf, strlen(tmpbuf)); + pAd->ApCfg.MBSSID[apidx].WAPIPassPhraseLen = strlen(tmpbuf); + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) WapiPsk=(%s), len=%d\n", apidx, tmpbuf, strlen(tmpbuf))); + } + else + { + if (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode == Ndis802_11AuthModeWAIPSK) + { + pAd->ApCfg.MBSSID[apidx].wdev.AuthMode = Ndis802_11AuthModeOpen; + pAd->ApCfg.MBSSID[apidx].wdev.WepStatus = Ndis802_11EncryptionDisabled; + } + DBGPRINT(RT_DEBUG_ERROR, ("IF(ra%d) The length of WAPI PSKPassPhrase is invalid(len=%d). \n", apidx, strlen(tmpbuf))); + } + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + + + + /* WapiPskType */ + if (RTMPGetKeyParameter("WapiPskType", tmpbuf, 32, buffer, TRUE)) + { + INT err; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + RTMP_STRING *macptr; + + for (apidx = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), apidx++) + { + err = 0; + + if (apidx >= pAd->ApCfg.BssidNum) + break; + + /* HEX */ + if(simple_strtol(macptr, 0, 10) == 0) + { + pAd->ApCfg.MBSSID[apidx].WapiPskType = HEX_MODE; + + if (pAd->ApCfg.MBSSID[apidx].WAPIPassPhraseLen % 2 != 0) + { + err = 1; + DBGPRINT(RT_DEBUG_ERROR, ("I/F(ra%d) The WAPI-PSK key length MUST be even in Hex mode\n", apidx)); + } + } + /* ASCII */ + else + { + pAd->ApCfg.MBSSID[apidx].WapiPskType = ASCII_MODE; + } + + if (err) + { + pAd->ApCfg.MBSSID[apidx].wdev.AuthMode = Ndis802_11AuthModeOpen; + pAd->ApCfg.MBSSID[apidx].wdev.WepStatus = Ndis802_11EncryptionDisabled; + } + else + DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WapiPskType=%s\n", apidx, (pAd->ApCfg.MBSSID[apidx].WapiPskType == HEX_MODE) ? "HEX" : "ASCII")); + } + } +#endif /* CONFIG_AP_SUPPORT */ + + + } + + /* 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) + { + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; + + if (pMbss->wdev.if_dev != NULL) + { + PNET_DEV dev = pMbss->wdev.if_dev; + + NdisMoveMemory(pConf->ifname, RtmpOsGetNetDevName(dev), strlen(RtmpOsGetNetDevName(dev))); + pConf->ifname_len = strlen(RtmpOsGetNetDevName(dev)); + } + else + { + RTMP_STRING slot_name[IFNAMSIZ]; + + snprintf(slot_name, sizeof(slot_name), "ra%d", apidx); + NdisMoveMemory(pConf->ifname, slot_name, strlen(slot_name)); + pConf->ifname_len = strlen(slot_name); + } + + /* Decide the authentication mode */ + if (pMbss->wdev.AuthMode == Ndis802_11AuthModeWAICERT) + pConf->auth_mode = WAPI_AUTH_CERT; + else if (pMbss->wdev.AuthMode == Ndis802_11AuthModeWAIPSK) + pConf->auth_mode = WAPI_AUTH_PSK; + else + pConf->auth_mode = WAPI_AUTH_DISABLE; + + /* Fill in WAI pre-shared key */ + if (pMbss->WAPIPassPhraseLen > 0) + { + if (pMbss->WapiPskType == HEX_MODE) + { + pConf->psk_len = pMbss->WAPIPassPhraseLen / 2; + AtoH((RTMP_STRING *) 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 */ + + +} + + +/* + ========================================================================== + 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 */ + + /* 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->func_tb_idx, + pEntry->Addr, + WAI_MLME_UPDATE_USK); + } + +} + + +/* + ========================================================================== + Description: + Timer execution function for periodically updating WAPI key. + Return: + ========================================================================== +*/ +VOID RTMPWapiMskRekeyPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + UINT i; + UINT32 tmp_cnt = 0; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; + + + /* if no any WAPI STA associated, don't do anything. */ + if (pAd->MacTab.fAnyWapiStation == FALSE) + return; + + /* increase counter for TIME method */ + if (pAd->CommonCfg.wapi_msk_rekey_method == REKEY_METHOD_TIME) + { + tmp_cnt = (++pAd->CommonCfg.wapi_msk_rekey_cnt); + } + else if (pAd->CommonCfg.wapi_msk_rekey_method == REKEY_METHOD_PKT) + { + /* the unit is 1K packets */ + tmp_cnt = pAd->CommonCfg.wapi_msk_rekey_cnt/1000; + } + else + return; + + if (tmp_cnt > pAd->CommonCfg.wapi_msk_rekey_threshold) + { + pAd->CommonCfg.wapi_msk_rekey_cnt = 0; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + INT apidx = 0; + UINT cnt; + + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + UINT m_wcid; + + pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId = pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId == 0 ? 1 : 0; + inc_iv_byte(pAd->ApCfg.MBSSID[apidx].key_announce_flag, LEN_WAPI_TSC, 1); + + /* Generate NMK randomly */ + for (cnt = 0; cnt < 16; cnt++) + pAd->ApCfg.MBSSID[apidx].NMK[cnt] = RandomByte(pAd); + + RTMPDeriveWapiGTK(pAd->ApCfg.MBSSID[apidx].NMK, pAd->ApCfg.MBSSID[apidx].GTK); + + GET_GroupKey_WCID(pAd, m_wcid, apidx); + /* Install Shared key */ + WAPIInstallSharedKey(pAd, + pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus, + apidx, + pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId, + m_wcid, + pAd->ApCfg.MBSSID[apidx].GTK); + } + } +#endif /* CONFIG_AP_SUPPORT */ + + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + MAC_TABLE_ENTRY *pEntry; + STA_TR_ENTRY *tr_entry = NULL; + + pEntry = &pAd->MacTab.Content[i]; + tr_entry = &pAd->MacTab.tr_entry[i]; + if (IS_ENTRY_CLIENT(pEntry) && + (pEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled) && + (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED)) + { + WAPI_InternalCmdAction(pAd, + pEntry->AuthMode, + pEntry->func_tb_idx, + pEntry->Addr, + WAI_MLME_UPDATE_MSK); + } + } + } + +} + + +VOID RTMPInitWapiRekeyTimerAction( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry) +{ + if (pEntry) + { + DBGPRINT(RT_DEBUG_TRACE, (" RTMPInitWapiRekeyTimerAction : WAPI USK rekey timer (wcid-%d) \n", pEntry->wcid)); + RTMPInitTimer(pAd, &pEntry->WapiUskRekeyTimer, GET_TIMER_FUNCTION(RTMPWapiUskRekeyPeriodicExec), pEntry, TRUE); + pEntry->WapiUskRekeyTimerRunning = FALSE; + } + else + { + RTMPInitTimer(pAd, &pAd->CommonCfg.WapiMskRekeyTimer, GET_TIMER_FUNCTION(RTMPWapiMskRekeyPeriodicExec), pAd, TRUE); + pAd->CommonCfg.WapiMskRekeyTimerRunning = FALSE; + } +} + +VOID RTMPStartWapiRekeyTimerAction( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry) +{ + if (pEntry) + { + if ((pAd->CommonCfg.wapi_usk_rekey_method != REKEY_METHOD_DISABLE) && + (pAd->CommonCfg.wapi_usk_rekey_threshold > 0)) + { + /* Regularly check the timer */ + if (pEntry->WapiUskRekeyTimerRunning == FALSE) + { + RTMPSetTimer(&pEntry->WapiUskRekeyTimer, WAPI_KEY_UPDATE_EXEC_INTV); + + pEntry->WapiUskRekeyTimerRunning = TRUE; + pEntry->wapi_usk_rekey_cnt = 0; + DBGPRINT(RT_DEBUG_TRACE, (" RTMPStartWapiRekeyTimerAction : WAPI USK rekey timer is started (%d) \n", pAd->CommonCfg.wapi_usk_rekey_threshold)); + } + } + } + else + { + if ((pAd->CommonCfg.wapi_msk_rekey_method != REKEY_METHOD_DISABLE) && + (pAd->CommonCfg.wapi_msk_rekey_threshold > 0)) + { + /* Regularly check the timer */ + if (pAd->CommonCfg.WapiMskRekeyTimerRunning == FALSE) + { + RTMPSetTimer(&pAd->CommonCfg.WapiMskRekeyTimer, WAPI_KEY_UPDATE_EXEC_INTV); + + pAd->CommonCfg.WapiMskRekeyTimerRunning = TRUE; + pAd->CommonCfg.wapi_msk_rekey_cnt = 0; + DBGPRINT(RT_DEBUG_TRACE, (" RTMPStartWapiRekeyTimerAction : WAPI MSK rekey timer is started \n")); + } + } + } + +} + +VOID RTMPCancelWapiRekeyTimerAction( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry) +{ + if(pEntry) + { + if (pEntry->WapiUskRekeyTimerRunning == TRUE) + { + BOOLEAN Cancelled; + + RTMPCancelTimer(&pEntry->WapiUskRekeyTimer, &Cancelled); + pEntry->wapi_usk_rekey_cnt = 0; + pEntry->WapiUskRekeyTimerRunning = FALSE; + } + } + else + { + if (pAd->CommonCfg.WapiMskRekeyTimerRunning == TRUE) + { + BOOLEAN Cancelled; + + RTMPCancelTimer(&pAd->CommonCfg.WapiMskRekeyTimer, &Cancelled); + pAd->CommonCfg.wapi_msk_rekey_cnt = 0; + pAd->CommonCfg.WapiMskRekeyTimerRunning = FALSE; + } + } + +} + +/* + ======================================================================== + + Routine Description: + Prepare a L2 frame to wapi daemon to trigger WAPI state machine + + Arguments: + pAd - pointer to our pAdapter context + + Return Value: + + Note: + + ======================================================================== +*/ +BOOLEAN WAPI_InternalCmdAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR AuthMode, + IN UCHAR apidx, + IN PUCHAR pAddr, + IN UCHAR flag) +{ + // TODO: shiang-usw, fix me for pEntry->apidx to func_tb_idx + if ((AuthMode == Ndis802_11AuthModeWAICERT) || + (AuthMode == Ndis802_11AuthModeWAIPSK)) + { + UCHAR WAPI_IE[] = {0x88, 0xb4}; + UINT8 frame_len = LENGTH_802_3 + 12; /* 12 indicates the WAPI internal command length */ + UCHAR FrameBuf[frame_len]; + UINT8 offset = 0; + + /* Init the frame buffer */ + NdisZeroMemory(FrameBuf, frame_len); + + /* Prepare the 802.3 header */ +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + MAKE_802_3_HEADER(FrameBuf, pAd->ApCfg.MBSSID[apidx].wdev.bssid, pAddr, WAPI_IE); + } +#endif /* CONFIG_AP_SUPPORT */ + offset += LENGTH_802_3; + + /* Prepare the specific WAPI header */ + NdisMoveMemory(&FrameBuf[offset], RALINK_OUI, 3); + offset += 3; + + /* Set the state of this command */ + FrameBuf[offset] = flag; + + DBGPRINT(RT_DEBUG_TRACE, ("Trigger WAPI for this sta(%02x:%02x:%02x:%02x:%02x:%02x)\n", PRINT_MAC(pAddr))); + + /* Report to upper layer */ + if (RTMP_L2_FRAME_TX_ACTION(pAd, apidx, FrameBuf, frame_len) == FALSE) + return FALSE; + + } + + return TRUE; +} + + +VOID RTMPGetWapiTxTscFromAsic( + IN PRTMP_ADAPTER pAd, + IN UINT Wcid, + OUT UCHAR *tx_tsc) +{ + USHORT offset; + int i; + + if (IS_HW_WAPI_SUPPORT(pAd)) + { + UINT32 iveiv_tb_base = 0, iveiv_tb_size = 0; + UINT32 wapi_pn_base = 0, wapi_pn_size = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + iveiv_tb_base = RLT_MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = RLT_HW_IVEIV_ENTRY_SIZE; + wapi_pn_base = RLT_WAPI_PN_TABLE_BASE; + wapi_pn_size = RLT_WAPI_PN_ENTRY_SIZE; + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + iveiv_tb_base = MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = HW_IVEIV_ENTRY_SIZE; + wapi_pn_base = WAPI_PN_TABLE_BASE; + wapi_pn_size = WAPI_PN_ENTRY_SIZE; + } +#endif /* RTMP_MAC */ + + NdisZeroMemory(tx_tsc, LEN_WAPI_TSC); + + /* Read IVEIV from Asic */ + offset = iveiv_tb_base + (Wcid * iveiv_tb_size); + for (i=0 ; i < iveiv_tb_size; i++) + RTMP_IO_READ8(pAd, offset+i, &tx_tsc[i]); + + /* Read WAPI PM from Asic */ + offset = wapi_pn_base + (Wcid * wapi_pn_size); + for (i=0 ; i < wapi_pn_size; i++) + RTMP_IO_READ8(pAd, offset+i, &tx_tsc[iveiv_tb_size + i]); + + DBGPRINT(RT_DEBUG_TRACE, ("%s : WCID(%d) offset(%u)", __FUNCTION__, Wcid,offset)); + hex_dump("TxTsc", tx_tsc, LEN_WAPI_TSC); + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s : Not support HW_WAPI_PN_TABLE\n", + __FUNCTION__)); + } + +} + + +VOID WAPIInstallPairwiseKey( + PRTMP_ADAPTER pAd, + PMAC_TABLE_ENTRY pEntry, + BOOLEAN bAE) +{ + PCIPHER_KEY pKey; + + pKey = &pEntry->PairwiseKey; + NdisZeroMemory(pKey, sizeof(CIPHER_KEY)); + + /* Assign the pairwise cipher algorithm */ + if (pEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled) + pKey->CipherAlg = CIPHER_SMS4; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : fails (wcid-%d)\n", + __FUNCTION__, pEntry->wcid)); + return; + } + + /* Prepare pair-wise key material */ + pKey->KeyLen = LEN_TK; + NdisMoveMemory(pKey->Key, &pEntry->PTK[0], 16); + NdisMoveMemory(pKey->TxMic, &pEntry->PTK[16], 8); + NdisMoveMemory(pKey->RxMic, &pEntry->PTK[24], 8); + + /* Initial TSC for unicast */ + if (bAE) + NdisMoveMemory(pKey->TxTsc, AE_UCAST_PN, LEN_WAPI_TSC); + else + NdisMoveMemory(pKey->TxTsc, ASUE_UCAST_PN, LEN_WAPI_TSC); + NdisZeroMemory(pKey->RxTsc, LEN_WAPI_TSC); + + /* HW_WAPI is supported in RT3883 or later */ + if (IS_HW_WAPI_SUPPORT(pAd)) + { + UINT32 CONST_WAPI_PN = 0x5C365C36; + + /* Set unicast packet's PN to Asic. */ + if (bAE) + AsicUpdateWCIDIVEIV(pAd, pEntry->wcid, CONST_WAPI_PN + 1, CONST_WAPI_PN); + else + AsicUpdateWCIDIVEIV(pAd, pEntry->wcid, CONST_WAPI_PN, CONST_WAPI_PN); + AsicUpdateWAPIPN(pAd, pEntry->wcid, CONST_WAPI_PN, CONST_WAPI_PN); + + /* Add Pair-wise key to Asic */ + AsicAddPairwiseKeyEntry( + pAd, + (UCHAR)pEntry->wcid, + &pEntry->PairwiseKey); + + /* update WCID attribute table and IVEIV table for this entry */ + AsicUpdateWcidAttributeEntry( + pAd, + pEntry->func_tb_idx, + pEntry->usk_id, + pEntry->PairwiseKey.CipherAlg, + (UCHAR)pEntry->wcid, + PAIRWISEKEYTABLE); + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + CmdProcAddRemoveKey(pAd, 0, pEntry->func_tb_idx, 0, pEntry->wcid, PAIRWISEKEYTABLE, &pEntry->PairwiseKey, pEntry->Addr); +#endif /* MT_MAC */ + } + +} + + +VOID WAPIInstallSharedKey( + PRTMP_ADAPTER pAd, + UINT8 GroupCipher, + UINT8 BssIdx, + UINT8 KeyIdx, + UINT8 Wcid, + PUINT8 pGtk) +{ + UINT32 CONST_WAPI_PN = 0x5C365C36; + PCIPHER_KEY pSharedKey; + + if (BssIdx >= MAX_MBSSID_NUM(pAd) + MAX_P2P_NUM) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : The BSS-index(%d) is out of range for MBSSID link. \n", + __FUNCTION__, BssIdx)); + return; + } + + pSharedKey = &pAd->SharedKey[BssIdx][KeyIdx]; + NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY)); + + if (GroupCipher == Ndis802_11EncryptionSMS4Enabled) + pSharedKey->CipherAlg = CIPHER_SMS4; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s : fails (IF/ra%d) \n", + __FUNCTION__, BssIdx)); + return; + } + + /* Assign key material into SW key table */ + pSharedKey->KeyLen = LEN_TK; + NdisMoveMemory(pSharedKey->Key, pGtk, LEN_TK); + NdisMoveMemory(pSharedKey->TxMic, pGtk + 16, LEN_TKIP_MIC); + NdisMoveMemory(pSharedKey->RxMic, pGtk + 24, LEN_TKIP_MIC); + + /* Initial TSC for B/Mcast */ + NdisMoveMemory(pSharedKey->TxTsc, AE_BCAST_PN, LEN_WAPI_TSC); + NdisZeroMemory(pSharedKey->RxTsc, LEN_WAPI_TSC); + + /* HW_WAPI is supported in RT3883 or later */ + if (IS_HW_WAPI_SUPPORT(pAd)) + { + /* Install Group Key to MAC ASIC */ + AsicAddSharedKeyEntry( + pAd, + BssIdx, + KeyIdx, + pSharedKey); + + /* When Wcid isn't zero, it means that this is a Authenticator Role. + Only Authenticator entity needs to set HW IE/EIV table (0x6000), + WAPI PN table (0x7800) + and WCID attribute table (0x6800) for group key. */ + if (Wcid != 0) + { + /* Set 16-bytes PN to Asic. */ + AsicUpdateWCIDIVEIV(pAd, Wcid, CONST_WAPI_PN, CONST_WAPI_PN); + AsicUpdateWAPIPN(pAd, Wcid, CONST_WAPI_PN, CONST_WAPI_PN); + + /* update Group key information to ASIC */ + AsicUpdateWcidAttributeEntry( + pAd, + BssIdx, + KeyIdx, + pSharedKey->CipherAlg, + Wcid, + SHAREDKEYTABLE); + } + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + CmdProcAddRemoveKey(pAd, 0, BssIdx, KeyIdx, Wcid, SHAREDKEYTABLE, pSharedKey, BROADCAST_ADDR); +#endif + } +} + +#endif /* WAPI_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wapi_crypt.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wapi_crypt.c new file mode 100644 index 000000000..53842f7c8 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wapi_crypt.c @@ -0,0 +1,509 @@ + +#ifdef LINUX +#include +#include +#include /* Needed for the macros */ +#endif /* LINUX */ + +#include "rtmp_type.h" +#include "wpa_cmm.h" +#include "wapi_def.h" +#include "wapi_sms4.h" + +void dump_bin(char *name, void *data, int len) +{ + int i = 0; + unsigned char *p = data; + + if(name != NULL) + { + printk("%s(%d): \n", name, len); + } + printk("\t"); + + for(i=0; i pMem2[Index]) + return (1); + else if (pMem1[Index] < pMem2[Index]) + return (2); + } + + /* Equal */ + return (0); +} + +/************************************/ +/* bitwise_xor() */ +/* A 128 bit, bitwise exclusive or */ +/************************************/ + +void bitwise_xor_wpi(unsigned char *ina, unsigned char *inb, unsigned char *out) +{ + int i; + for (i=0; i<16; i++) + { + out[i] = ina[i] ^ inb[i]; + } +} + +/*cbc_mac*/ +int wpi_cbc_mac_engine( + unsigned char * maciv_in, + unsigned char * in_data1, + unsigned int in_data1_len, + unsigned char * in_data2, + unsigned int in_data2_len, + unsigned char * pkey, + unsigned char * mac_out) +{ + unsigned char mactmp[16]; + unsigned int i; + unsigned int num_blocks_1, num_blocks_2; + unsigned int prmackey_in[32]; + + num_blocks_1 = (in_data1_len) >> 4; + num_blocks_2 = (in_data2_len) >> 4; + + if((num_blocks_1 + num_blocks_2 ) < 1) return 1; + if((num_blocks_1 + num_blocks_2 ) > 4096) return 1; + + SMS4KeyExt(pkey, prmackey_in, 0); + SMS4Crypt(maciv_in, mactmp, prmackey_in); + + for (i = 0; i < num_blocks_1; i++) + { + bitwise_xor_wpi(mactmp, in_data1, mactmp); + in_data1 += 16; + SMS4Crypt(mactmp, mactmp, prmackey_in); + } + + for (i = 0; i < num_blocks_2; i++) + { + bitwise_xor_wpi(mactmp, in_data2, mactmp); + in_data2 += 16; + SMS4Crypt(mactmp, mactmp, prmackey_in); + } + memcpy(mac_out, mactmp, 16); + + return 0; +} + +/*ofb encrypt*/ +int wpi_sms4_ofb_engine( + unsigned char * pofbiv_in, + unsigned char * pbw_in, + unsigned int plbw_in, + unsigned char * pkey, + unsigned char * pcw_out) +{ + unsigned char ofbtmp[16]; + /*unsigned int * pint0, * pint1; */ + /*unsigned char * pchar0, * pchar1,* pchar2; */ + unsigned int counter,comp,i; + unsigned int prkey_in[32]; + + + if(plbw_in<1) return 1; + /*if(plbw_in>65536) return 1; */ + + SMS4KeyExt(pkey, prkey_in, 0); + + /* get the multiple of 16 */ + counter = plbw_in >> 4; + /* get the remainder of 16 */ + comp = plbw_in & 0x0f; + + /*get the iv */ + SMS4Crypt(pofbiv_in, ofbtmp, prkey_in); + + for(i = 0; i < counter; i++) + { + bitwise_xor_wpi(pbw_in, ofbtmp, pcw_out); + pbw_in += 16; + pcw_out += 16; + SMS4Crypt(ofbtmp, ofbtmp, prkey_in); + } + + for(i = 0; i < comp; i++) + { + pcw_out[i]=pbw_in[i]^ofbtmp[i]; + } + + return 0; +} + + +/* + ======================================================================== + + Routine Description: + Make the integrity check header for WPI MIC + + Arguments: + pAd - pointer to our pAdapter context + + Return Value: + + Note: + + ======================================================================== +*/ +UINT32 wpi_construct_mic_hdr( + IN PUCHAR pHdr, + IN UINT32 data_len, + IN UCHAR keyidx, + OUT UCHAR *mic_hdr) +{ + UINT8 from_ds, to_ds, a4_exists, qc_exists; + //UINT8 frame_type; + UINT8 frame_subtype; + UINT8 mhdr_len = 0; + UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + //frame_type = (((*pHdr) >> 2) & 0x03); + frame_subtype = (((*pHdr) >> 4) & 0x0f); + + /* Check if Addr4 is available */ + from_ds = ((*(pHdr + 1)) & 0x2) >> 1; + to_ds = ((*(pHdr + 1)) & 0x1); + a4_exists = (from_ds & to_ds); + + /* Check if Qos is available */ + qc_exists = ((frame_subtype == 0x08) || /* QoS Data */ + (frame_subtype == 0x09) || /* QoS Data + CF-Ack */ + (frame_subtype == 0x0a) || /* QoS Data + CF-Poll */ + (frame_subtype == 0x0b) /* QoS Data + CF-Ack + CF-Poll */ + ); + + /* Frame control */ + /* bit 4,5,6 must be zero */ + /* bit 11,12,13 must be zero */ + /* bit 14 must be 1 */ + mic_hdr[mhdr_len] = (*pHdr) & 0x8f; + mic_hdr[mhdr_len + 1] = (*(pHdr + 1)) & 0xc7; + mhdr_len = 2; + + /* Addr1 & 2 */ + WapiMoveMemory(&mic_hdr[mhdr_len], pHdr + 4, 2 * MAC_ADDR_LEN); + mhdr_len += (2 * MAC_ADDR_LEN); + + /* In Sequence Control field, mute sequence numer bits (12-bit) */ + mic_hdr[mhdr_len] = (*(pHdr + 22)) & 0x0f; + mic_hdr[mhdr_len + 1] = 0x00; + mhdr_len += 2; + + /* Addr3 */ + WapiMoveMemory(&mic_hdr[mhdr_len], pHdr + 16, MAC_ADDR_LEN); + mhdr_len += MAC_ADDR_LEN; + + /* Fill the Addr4 field. */ + /* If the Addr4 is unused, it shall be padded zero. */ + if (a4_exists) + WapiMoveMemory(&mic_hdr[mhdr_len], pHdr + 24, MAC_ADDR_LEN); + else + WapiMoveMemory(&mic_hdr[mhdr_len], ZERO_MAC_ADDR, MAC_ADDR_LEN); + mhdr_len += MAC_ADDR_LEN; + + /* Qos field */ + if (qc_exists & a4_exists) + { + mic_hdr[mhdr_len] = (*(pHdr + 30)) & 0x0f; /* Qos_TC */ + mic_hdr[mhdr_len + 1] = 0x00; + mhdr_len += 2; + } + else if (qc_exists & !a4_exists) + { + mic_hdr[mhdr_len] = (*(pHdr + 24)) & 0x0f; /* Qos_TC */ + mic_hdr[mhdr_len + 1] = 0x00; + mhdr_len += 2; + } + + /* fill the KeyIdx and reserve field */ + mic_hdr[mhdr_len] = keyidx; + mic_hdr[mhdr_len + 1] = 0x00; + mhdr_len += 2; + + /* Fill in data len field */ + mic_hdr[mhdr_len] = (data_len >> 8) & 0xff; + mic_hdr[mhdr_len + 1] = (data_len) & 0xff; + mhdr_len += 2; + + /* the len must be the multiple of 16 */ + /* If the Qos field doesn't exist, the header length shall be 32. */ + /* If the Qos exists, the header is 34. We need to expand it as 48 by padding zero. */ + /*DBGPRINT(RT_DEBUG_TRACE, ("mhdr_len(%d)\n", mhdr_len)); */ + mhdr_len = (mhdr_len > 32) ? 48 : 32; + + return mhdr_len; +} + +/* + ======================================================================== + + Routine Description: + Calculate the MIC of WPI data. + + Arguments: + pAd - pointer to our pAdapter context + + Return Value: + TRUE - success + FLASE - failure + + Note: + + ======================================================================== +*/ +BOOLEAN RTMPCalculateWpiMic( + IN PUCHAR pHeader, + IN PUCHAR pData, + IN UINT32 data_len, + IN UINT8 key_idx, + IN PUCHAR pKey, + IN PUCHAR pIV, + OUT PUCHAR pOutMic) +{ + UCHAR mic_header[48]; + UINT8 mic_hdr_len = 0; + UINT8 pad_len = 0; + UINT8 remainder = 0; + + WapiZeroMemory(mic_header, 48); + + /* Construct integrity verify data header */ + mic_hdr_len = wpi_construct_mic_hdr(pHeader, data_len, key_idx, mic_header); + + /* calculate the padded length */ + if ((remainder = data_len & 0x0f) != 0) + pad_len = (16 - remainder); + + /* Calculate MIC */ + wpi_cbc_mac_engine(pIV, + mic_header, + mic_hdr_len, + pData, + data_len + pad_len, + pKey, + pOutMic); + + return TRUE; + +} + +/* + ======================================================================== + + Routine Description: + Encrypt WPI-data by software. + + Arguments: + pAd - pointer to our pAdapter context + + Return Value: + TRUE - success + FLASE - failure + + Note: + + ======================================================================== +*/ +INT RTMPSoftEncryptSMS4( + IN PUCHAR pHeader, + IN PUCHAR pData, + IN UINT32 data_len, + IN UCHAR key_id, + IN PUCHAR pKey, + IN PUCHAR pIv) +{ + INT i; + UCHAR out_mic[LEN_WPI_MIC]; + UCHAR iv_inv[LEN_WAPI_TSC]; + + /* Inverse IV byte order */ + for (i=0; i < LEN_WAPI_TSC; i++) + { + iv_inv[LEN_WAPI_TSC - 1 - i] = (*(pIv + i)) & 0xFF; + } + + WapiZeroMemory(out_mic, LEN_WPI_MIC); + /* clear enough space for calculating WPI MIC later */ + WapiZeroMemory(pData + data_len, LEN_WPI_MIC); + /* Calculate WPI MIC */ + RTMPCalculateWpiMic(pHeader, + pData, + data_len, + key_id, + pKey + 16, + iv_inv, + out_mic); + + /* append MIC to the data tail */ + WapiMoveMemory(pData + data_len, out_mic, LEN_WPI_MIC); + + /* Encrypt WPI data by software */ + wpi_sms4_ofb_engine(iv_inv, pData, data_len + LEN_WPI_MIC, pKey, pData); + + return TRUE; + +} + +/* + ======================================================================== + + Routine Description: + Decrypt WPI-data by software. + + Arguments: + pAd - pointer to our pAdapter context + + Return Value: + TRUE - success + FLASE - failure + + Note: + + ======================================================================== +*/ +INT RTMPSoftDecryptSMS4( + IN PUCHAR pHdr, + IN BOOLEAN bSanityIV, + IN PCIPHER_KEY pKey, + INOUT PUCHAR pData, + INOUT UINT16 *DataByteCnt) +{ + UCHAR i; + UCHAR key_idx; + PUCHAR iv_ptr; + UCHAR iv_inv[LEN_WAPI_TSC]; + UCHAR MIC[LEN_WPI_MIC]; + UCHAR TrailMIC[LEN_WPI_MIC]; + /*PUCHAR mic_ptr; */ + /*UINT32 mic_data_len; */ + /*PUCHAR buf_ptr = NULL; */ + PUCHAR plaintext_ptr; + UINT16 plaintext_len; + PUCHAR ciphertext_ptr; + UINT16 ciphertext_len; + + /* Check the key is valid */ + if (pKey->KeyLen == 0) + { + return STATUS_WAPI_KEY_INVALID; + } + + /* extract key index from the IV header */ + key_idx = *(pData) & 0xFF; + + /* Skip 2-bytes(key_idx and reserve field) and point to IV field */ + iv_ptr = pData + 2; + + /* IV sanity check */ + if (bSanityIV) + { + if (WapiCompareMemory(iv_ptr, pKey->RxTsc, LEN_WAPI_TSC) > 1) + { + return STATUS_WAPI_IV_MISMATCH; + } + else + { + /* Record the received IV */ + WapiMoveMemory(pKey->RxTsc, iv_ptr, LEN_WAPI_TSC); + } + } + + /* Inverse IV byte order for SMS4 calculation */ + for (i = 0; i < LEN_WAPI_TSC; i++) + { + iv_inv[LEN_WAPI_TSC - 1 - i] = (*(iv_ptr + i)) & 0xFF; + } + + /* Skip the WPI IV header (18-bytes) */ + ciphertext_ptr = pData + LEN_WPI_IV_HDR; + ciphertext_len = *DataByteCnt - LEN_WPI_IV_HDR; + + /* skip payload length is zero */ + if ((*DataByteCnt ) <= LEN_WPI_IV_HDR) + return FALSE; + + /* Decrypt the WPI MPDU. It shall include plaintext and MIC. + The result output would overwrite the original WPI IV header position */ + wpi_sms4_ofb_engine(iv_inv, ciphertext_ptr, ciphertext_len, pKey->Key, pData); + + /* Point to the plainext data frame and its length shall exclude MIC length */ + plaintext_ptr = pData; + plaintext_len = ciphertext_len - LEN_WPI_MIC; + + /* Extract peer's MIC and zero the MIC field of received frame */ + WapiMoveMemory(TrailMIC, plaintext_ptr + plaintext_len, LEN_WPI_MIC); + WapiZeroMemory(plaintext_ptr + plaintext_len, LEN_WPI_MIC); + + /* Calculate WPI MIC */ + WapiZeroMemory(MIC, LEN_WPI_MIC); + RTMPCalculateWpiMic(pHdr, + plaintext_ptr, + plaintext_len, + key_idx, + pKey->TxMic, + iv_inv, + MIC); + + /* Compare the MIC field */ + if (!WapiEqualMemory(MIC, TrailMIC, LEN_WPI_MIC)) + { + return STATUS_WAPI_MIC_DIFF; + } + + /* Update the total data length */ + *DataByteCnt = plaintext_len; + + return STATUS_SUCCESS; +} + +//#ifndef RTMP_RBUS_SUPPORT + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wapi_sms4.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wapi_sms4.c new file mode 100644 index 000000000..540dffc34 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wapi_sms4.c @@ -0,0 +1,127 @@ + + +const unsigned char ISbox[256] = { +0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05, +0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99, +0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62, +0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6, +0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8, +0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35, +0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87, +0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e, +0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1, +0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3, +0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f, +0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51, +0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8, +0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0, +0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84, +0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48 +}; + +const unsigned int CK[32] = { + 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, + 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, + 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, + 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, + 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, + 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, + 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, + 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 }; + +#define Rotl(_x, _y) (((_x) << (_y)) | ((_x) >> (32 - (_y)))) +#define getbyte(_x,_y) (((unsigned char *)&(_x))[_y]) + +#define ByteSub(_A) (ISbox[((unsigned int)_A) >> 24 & 0xFF] << 24 ^ \ + ISbox[((unsigned int)_A) >> 16 & 0xFF] << 16 ^ \ + ISbox[((unsigned int)_A) >> 8 & 0xFF] << 8 ^ \ + ISbox[((unsigned int)_A) & 0xFF]) + +#define L1(_B) ((_B) ^ Rotl(_B, 2) ^ Rotl(_B, 10) ^ Rotl(_B, 18) ^ Rotl(_B, 24)) +#define L2(_B) ((_B) ^ Rotl(_B, 13) ^ Rotl(_B, 23)) + +#ifdef RT_BIG_ENDIAN +#define byteReverse(x0, x1, x2, x3) /* Nothing */ +#else +void byteReverse(unsigned int *x0, unsigned int *x1, unsigned int *x2, unsigned int *x3); +void byteReverse(unsigned int *x0, unsigned int *x1, unsigned int *x2, unsigned int *x3) +{ + *x0 = Rotl(*x0, 16); *x0 = ((*x0 & 0x00FF00FF) << 8) ^ ((*x0 & 0xFF00FF00) >> 8); + *x1 = Rotl(*x1, 16); *x1 = ((*x1 & 0x00FF00FF) << 8) ^ ((*x1 & 0xFF00FF00) >> 8); + *x2 = Rotl(*x2, 16); *x2 = ((*x2 & 0x00FF00FF) << 8) ^ ((*x2 & 0xFF00FF00) >> 8); + *x3 = Rotl(*x3, 16); *x3 = ((*x3 & 0x00FF00FF) << 8) ^ ((*x3 & 0xFF00FF00) >> 8); +} +#endif + +#define ENCRYPT 0 +#define DECRYPT 1 + +void SMS4Crypt(unsigned char *Input, unsigned char *Output, unsigned int *rk) +{ + unsigned int r, mid, x0, x1, x2, x3, *p; + p = (unsigned int *)Input; + x0 = p[0]; + x1 = p[1]; + x2 = p[2]; + x3 = p[3]; + + byteReverse(&x0, &x1, &x2, &x3); + for (r = 0; r < 32; r += 4) + { + mid = x1 ^ x2 ^ x3 ^ rk[r + 0]; + mid = ByteSub(mid); + x0 ^= L1(mid); + mid = x2 ^ x3 ^ x0 ^ rk[r + 1]; + mid = ByteSub(mid); + x1 ^= L1(mid); + mid = x3 ^ x0 ^ x1 ^ rk[r + 2]; + mid = ByteSub(mid); + x2 ^= L1(mid); + mid = x0 ^ x1 ^ x2 ^ rk[r + 3]; + mid = ByteSub(mid); + x3 ^= L1(mid); + } + + byteReverse(&x0, &x1, &x2, &x3); + + p = (unsigned int *)Output; + p[0] = x3; + p[1] = x2; + p[2] = x1; + p[3] = x0; + +} + + +void SMS4KeyExt(unsigned char *Key, unsigned int *rk, unsigned int CryptFlag) +{ + unsigned int r, mid, x0, x1, x2, x3, *p; + p = (unsigned int *)Key; + x0 = p[0]; + x1 = p[1]; + x2 = p[2]; + x3 = p[3]; + + byteReverse(&x0, &x1, &x2, &x3); + + x0 ^= 0xa3b1bac6; + x1 ^= 0x56aa3350; + x2 ^= 0x677d9197; + x3 ^= 0xb27022dc; + for (r = 0; r < 32; r += 4) + { + mid = x1 ^ x2 ^ x3 ^ CK[r + 0]; + mid = ByteSub(mid); + rk[r + 0] = x0 ^= L2(mid); + mid = x2 ^ x3 ^ x0 ^ CK[r + 1]; + mid = ByteSub(mid); + rk[r + 1] = x1 ^= L2(mid); + mid = x3 ^ x0 ^ x1 ^ CK[r + 2]; + mid = ByteSub(mid); + rk[r + 2] = x2 ^= L2(mid); + mid = x0 ^ x1 ^ x2 ^ CK[r + 3]; + mid = ByteSub(mid); + rk[r + 3] = x3 ^= L2(mid); + } +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wfd.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wfd.c new file mode 100644 index 000000000..b7a1a830b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wfd.c @@ -0,0 +1,18 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + + +#include "rt_config.h" +#include "wfd_cmm.h" + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wnm.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wnm.c new file mode 100644 index 000000000..3d8f3f068 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wnm.c @@ -0,0 +1,3561 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2011, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + wnm.c + + Abstract: + Wireless Network Management(WNM) + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + +static UCHAR ZERO_IP_ADDR[4] = {0x00, 0x00, 0x00, 0x00}; + +static char SolicitedMulticastAddr[] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xff}; +static char AllNodeLinkLocalMulticastAddr[] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01}; + +static char link_local[] = {0xfe, 0x80}; + +#define IP_PROTO_HOPOPTS 0 /* IP6 hop-by-hop options - RFC1883 */ +#define IP_PROTO_ROUTING 43 /* IP6 routing header */ +#define IP_PROTO_FRAGMENT 44 /* IP6 fragmentation header */ +#define IP_PROTO_AH 51 /* Authentication Header for IPv6 - RFC2402*/ +#define IP_PROTO_DSTOPTS 60 /* IP6 destination options - RFC1883 */ + +#ifndef MAT_SUPPORT +#define IS_UNSPECIFIED_IPV6_ADDR(_addr) \ + (!((_addr).ipv6_addr32[0] | (_addr).ipv6_addr32[1] | (_addr).ipv6_addr32[2] | (_addr).ipv6_addr32[3])) +#endif + +#ifdef CONFIG_AP_SUPPORT +/*#ifndef CONFIG_HOTSPOT_R2 #ifdef WNM_NEW_API*/ +#ifndef WAPP_SUPPORT +void wext_send_btm_query_event_newapi(PNET_DEV net_dev, const char *peer_mac_addr, + const char *btm_query, UINT16 btm_query_len) +{ + struct btm_query_data *query_data = NULL; + struct wnm_event *event_data = NULL; + UINT16 buflen = 0; + char *buf; + + buflen = sizeof(struct wnm_event) + sizeof(struct btm_query_data) + btm_query_len; + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + event_data = (struct wnm_event *)buf; + event_data->event_id = OID_802_11_WNM_EVT_BTM_QUERY; + event_data->event_len = sizeof(*query_data) + btm_query_len; + + query_data = (struct btm_query_data *)event_data->event_body; + query_data->ifindex = RtmpOsGetNetIfIndex(net_dev); + memcpy(query_data->peer_mac_addr, peer_mac_addr, 6); + query_data->btm_query_len = btm_query_len; + memcpy(query_data->btm_query, btm_query, btm_query_len); + + RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_WNM_EVENT, NULL, (PUCHAR)buf, buflen); + + os_free_mem(NULL, buf); +} + +#endif +const UCHAR wfa_oui[3] = {0x50, 0x6F, 0x9A}; + +void wext_send_btm_query_event(PNET_DEV net_dev, const char *peer_mac_addr, + const char *btm_query, UINT16 btm_query_len) +{ + struct btm_query_data *query_data; + UINT16 buflen = 0; + char *buf; + + buflen = sizeof(*query_data) + btm_query_len; + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + query_data = (struct btm_query_data *)buf; + query_data->ifindex = RtmpOsGetNetIfIndex(net_dev); + memcpy(query_data->peer_mac_addr, peer_mac_addr, 6); + query_data->btm_query_len = btm_query_len; + memcpy(query_data->btm_query, btm_query, btm_query_len); + + RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_WNM_BTM_QUERY, NULL, (PUCHAR)buf, buflen); + + os_free_mem(NULL, buf); +} + + +void SendBTMQueryEvent(PNET_DEV net_dev, const char *peer_mac_addr, + const char *btm_query, UINT16 btm_query_len, UINT8 ipc_type) +{ + if (ipc_type == RA_WEXT) { +/*#ifndef CONFIG_HOTSPOT_R2 #ifdef WNM_NEW_API*/ +#ifndef WAPP_SUPPORT + if (1) { + wext_send_btm_query_event_newapi(net_dev, + peer_mac_addr, + btm_query, + btm_query_len); + + } else +#endif + wext_send_btm_query_event(net_dev, + peer_mac_addr, + btm_query, + btm_query_len); + } +} + +/*#ifndef CONFIG_HOTSPOT_R2 #ifdef WNM_NEW_API*/ +#ifndef WAPP_SUPPORT +void wext_send_btm_cfm_event_newapi(PNET_DEV net_dev, const char *peer_mac_addr, + const char *btm_rsp, UINT16 btm_rsp_len) +{ + struct btm_rsp_data *rsp_data = NULL; + struct wnm_event *event_data = NULL; + UINT16 buflen = 0; + char *buf; + + + buflen = sizeof(struct wnm_event) + sizeof(*rsp_data) + btm_rsp_len; + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + event_data = (struct wnm_event *)buf; + event_data->event_id = OID_802_11_WNM_EVT_BTM_RSP; + event_data->event_len = sizeof(struct btm_rsp_data) + btm_rsp_len; + + + rsp_data = (struct btm_rsp_data *)event_data->event_body; + rsp_data->ifindex = RtmpOsGetNetIfIndex(net_dev); + memcpy(rsp_data->peer_mac_addr, peer_mac_addr, 6); + rsp_data->btm_rsp_len = btm_rsp_len; + memcpy(rsp_data->btm_rsp, btm_rsp, btm_rsp_len); + + RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_WNM_EVENT, NULL, (PUCHAR)buf, buflen); + + os_free_mem(NULL, buf); +} + +#endif + +void wext_send_btm_cfm_event(PNET_DEV net_dev, const char *peer_mac_addr, + const char *btm_rsp, UINT16 btm_rsp_len) +{ + struct btm_rsp_data *rsp_data; + UINT16 buflen = 0; + char *buf; + + + buflen = sizeof(*rsp_data) + btm_rsp_len; + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + rsp_data = (struct btm_rsp_data *)buf; + rsp_data->ifindex = RtmpOsGetNetIfIndex(net_dev); + memcpy(rsp_data->peer_mac_addr, peer_mac_addr, 6); + rsp_data->btm_rsp_len = btm_rsp_len; + memcpy(rsp_data->btm_rsp, btm_rsp, btm_rsp_len); + + RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_WNM_BTM_RSP, NULL, (PUCHAR)buf, buflen); + + os_free_mem(NULL, buf); +} + + +void SendBTMConfirmEvent(PNET_DEV net_dev, const char *peer_mac_addr, + const char *btm_rsp, UINT16 btm_rsp_len, UINT8 ipc_type) +{ + if (ipc_type == RA_WEXT) { +/*#ifndef CONFIG_HOTSPOT_R2 #ifdef WNM_NEW_API*/ +#ifndef WAPP_SUPPORT + if (1) { + wext_send_btm_cfm_event_newapi(net_dev, + peer_mac_addr, + btm_rsp, + btm_rsp_len); + } else +#endif + wext_send_btm_cfm_event(net_dev, + peer_mac_addr, + btm_rsp, + btm_rsp_len); + } +} + + +void wext_send_proxy_arp_event(PNET_DEV net_dev, + const char *source_mac_addr, + const char *source_ip_addr, + const char *target_mac_addr, + const char *target_ip_addr, + UINT8 ip_type, + UINT8 from_ds, + unsigned char IsDAD) +{ + struct proxy_arp_entry *arp_entry; + UINT16 varlen = 0, buflen = 0; + char *buf; + + if (ip_type == IPV4) + varlen += 8; + else if (ip_type == IPV6) + varlen += 32; + + //for IsDAD, add one more byte + varlen++; + + buflen = sizeof(*arp_entry) + varlen; + + os_alloc_mem(NULL, (UCHAR **)&buf, buflen); + NdisZeroMemory(buf, buflen); + + arp_entry = (struct proxy_arp_entry *)buf; + + arp_entry->ifindex = RtmpOsGetNetIfIndex(net_dev); + arp_entry->ip_type = ip_type; + arp_entry->from_ds = from_ds; + arp_entry->IsDAD = IsDAD; + memcpy(arp_entry->source_mac_addr, source_mac_addr, 6); + memcpy(arp_entry->target_mac_addr, target_mac_addr, 6); + + if (ip_type == IPV4) { + memcpy(arp_entry->ip_addr, source_ip_addr, 4); + memcpy(arp_entry->ip_addr + 4, target_ip_addr, 4); + } else if (ip_type == IPV6) { + memcpy(arp_entry->ip_addr, source_ip_addr, 16); + memcpy(arp_entry->ip_addr + 16, target_ip_addr, 16); + } else + printk("error not such ip type packet\n"); + + RtmpOSWrielessEventSend(net_dev, RT_WLAN_EVENT_CUSTOM, + OID_802_11_WNM_PROXY_ARP, NULL, (PUCHAR)buf, buflen); + + os_free_mem(NULL, buf); +} + + +void SendProxyARPEvent(PNET_DEV net_dev, + const char *source_mac_addr, + const char *source_ip_addr, + const char *target_mac_addr, + const char *target_ip_addr, + UINT8 ip_type, + UINT8 from_ds, + unsigned char IsDAD) +{ + wext_send_proxy_arp_event(net_dev, + source_mac_addr, + source_ip_addr, + target_mac_addr, + target_ip_addr, + ip_type, + from_ds, + IsDAD); +} + + +BOOLEAN IsGratuitousARP(IN RTMP_ADAPTER *pAd, + IN UCHAR *pData, + IN UCHAR *DAMacAddr, + IN struct _BSS_STRUCT *pMbss) +{ + UCHAR *Pos = pData; + UINT16 ProtoType; + UCHAR *SenderIP; + UCHAR *TargetIP; + UCHAR BroadcastMac[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; +#ifdef CONFIG_HOTSPOT_R2 + UINT16 ARPOperation; + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PROXY_ARP_IPV4_ENTRY *ProxyARPEntry; + BOOLEAN IsDrop = FALSE; + INT32 Ret; +#endif + PUCHAR SourceMACAddr; + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_ARP) + { + /* + * Check if Gratuitous ARP, Sender IP equal Target IP + */ + SourceMACAddr = Pos + 8; + SenderIP = Pos + 14; + TargetIP = Pos + 24; + if ((NdisCmpMemory(SenderIP, TargetIP, 4) == 0) && (NdisCmpMemory(DAMacAddr, BroadcastMac, 6) == 0)) + { + DBGPRINT(RT_DEBUG_TRACE, ("The Packet is GratuitousARP\n")); + return TRUE; + } +#ifdef CONFIG_HOTSPOT_R2 + Pos += 6; + NdisMoveMemory(&ARPOperation, Pos, 2); + ARPOperation = OS_NTOHS(ARPOperation); + Pos += 2; + + if (ARPOperation == 0x0002) + { + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + if ((IPV4_ADDR_EQUAL(ProxyARPEntry->TargetIPAddr, SenderIP)) && (MAC_ADDR_EQUAL(ProxyARPEntry->TargetMACAddr, SourceMACAddr) == FALSE)) + { + IsDrop = TRUE; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + + if (IsDrop == TRUE) + { + printk("Drop pkt, ip not qeual mac\n"); + return TRUE; + } + } +#endif + } + + return FALSE; +} + + +BOOLEAN IsUnsolicitedNeighborAdver(PRTMP_ADAPTER pAd, + PUCHAR pData) +{ + UCHAR *Pos = pData; + UINT16 ProtoType; + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_IPV6) + { + Pos += 24; + + if (RTMPEqualMemory(Pos, AllNodeLinkLocalMulticastAddr, 16)) + { + Pos += 16; + + /* Check if neighbor advertisement type */ + if (*Pos == 0x88) + { + Pos += 4; + + /* Check if solicited flag set to 0 */ + if ((*Pos & 0x40) == 0x00) + { + DBGPRINT(RT_DEBUG_OFF, ("The Packet is UnsolicitedNeighborAdver\n")); + Pos += 4; + return TRUE; + } + } + } + + } + + return FALSE; +} + + +BOOLEAN IsIPv4ProxyARPCandidate(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData) +{ + UCHAR *Pos = pData; + UINT16 ProtoType; + UINT16 ARPOperation; + UCHAR *SenderIP; + UCHAR *TargetIP; + + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_ARP) + { + Pos += 6; + NdisMoveMemory(&ARPOperation, Pos, 2); + ARPOperation = OS_NTOHS(ARPOperation); + Pos += 2; + + if (ARPOperation == 0x0001) + { + SenderIP = Pos + 6; + TargetIP = Pos + 16; + /* ARP Request */ + if (NdisCmpMemory(SenderIP, TargetIP, 4) != 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("IPv4ProxyARPCandidate\n")); + return TRUE; + } + } + } + + return FALSE; +} + + +BOOLEAN IsIpv6DuplicateAddrDetect(PRTMP_ADAPTER pAd, + PUCHAR pData, + PUCHAR pOffset) +{ + UCHAR *Pos = pData; + UINT16 ProtoType; + RT_IPV6_ADDR *pIPv6Addr; + UCHAR *pData_offset = Pos; + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_IPV6) + { + INT32 PayloadLen = 0;//((*(Pos+5) & 0xff) << 8) | (*(Pos+4) & 0xff); + UCHAR NextHeader = *(Pos+6); + UCHAR IsExtenHeader = 0; + + NdisMoveMemory(&PayloadLen, (Pos+4), 2); + PayloadLen = OS_NTOHS(PayloadLen); + + Pos += 8; + pIPv6Addr = (RT_IPV6_ADDR *)Pos; + + if (IS_UNSPECIFIED_IPV6_ADDR(*pIPv6Addr)) + { + Pos += 16; + if (RTMPEqualMemory(Pos, SolicitedMulticastAddr, 13)) + { + Pos += 16; + + if ((NextHeader == IP_PROTO_HOPOPTS) || (NextHeader == IP_PROTO_ROUTING) || (NextHeader == IP_PROTO_FRAGMENT) || (NextHeader == IP_PROTO_AH) || (NextHeader == IP_PROTO_DSTOPTS)) + { + IsExtenHeader = 1; + + do + { + printk("IsIpv6DuplicateAddrDetect: nextheader=0x%x, %d, %d\n", NextHeader, PayloadLen, IsExtenHeader); + switch (NextHeader) + { + case IP_PROTO_HOPOPTS: + case IP_PROTO_ROUTING: + case IP_PROTO_DSTOPTS: + { + UCHAR HdrExtLen = *(Pos+1); + + NextHeader = *Pos; + PayloadLen -= ((HdrExtLen+1)<<3); + Pos += ((HdrExtLen+1)<<3); + } + break; + case IP_PROTO_FRAGMENT: + { + NextHeader = *Pos; + PayloadLen -= 8; + Pos += 8; + } + break; + case IP_PROTO_AH: + { + UCHAR AHPayloadLen = *(Pos+1); + UCHAR AHLen = (8+(AHPayloadLen<<2)); + + NextHeader = *Pos; + PayloadLen -= AHLen; + Pos += AHLen; + } + break; + default: + IsExtenHeader = 0; + break; + } + } + while((PayloadLen > 0) && (IsExtenHeader == 1)); + + if (PayloadLen <= 0) + return FALSE; + } + + /* Check if neighbor solicitation */ + if (*Pos == 0x87) + { + DBGPRINT(RT_DEBUG_OFF, ("THe Packet is for Ipv6DuplicateAddrDetect\n")); + *pOffset = Pos-pData_offset+8; + return TRUE; + } + } + } + } + + return FALSE; +} + +BOOLEAN IsIPv6ProxyARPCandidate(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData) +{ + UCHAR *Pos = pData; + UINT16 ProtoType; + //RT_IPV6_ADDR *pIPv6Addr; + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_IPV6) + { + INT32 PayloadLen = 0; //((*(Pos+5) & 0xff) << 8) | (*(Pos+4) & 0xff); + UCHAR NextHeader = *(Pos+6); + UCHAR IsExtenHeader = 0; + + NdisMoveMemory(&PayloadLen, (Pos+4), 2); + PayloadLen = OS_NTOHS(PayloadLen); + + Pos += 8; + //pIPv6Addr = (RT_IPV6_ADDR *)Pos; + + //if (!IS_UNSPECIFIED_IPV6_ADDR(*pIPv6Addr)) + //{ + Pos += 16; + if (RTMPEqualMemory(Pos, SolicitedMulticastAddr, 13)) + { + Pos+= 16; + + if ((NextHeader == IP_PROTO_HOPOPTS) || (NextHeader == IP_PROTO_ROUTING) || (NextHeader == IP_PROTO_FRAGMENT) || (NextHeader == IP_PROTO_AH) || (NextHeader == IP_PROTO_DSTOPTS)) + { + IsExtenHeader = 1; + + do + { + printk("IsIPv6ProxyARPCandidate: nextheader=0x%x, %d, %d\n", NextHeader, PayloadLen, IsExtenHeader); + switch (NextHeader) + { + case IP_PROTO_HOPOPTS: + case IP_PROTO_ROUTING: + case IP_PROTO_DSTOPTS: + { + UCHAR HdrExtLen = *(Pos+1); + + NextHeader = *Pos; + PayloadLen -= ((HdrExtLen+1)<<3); + Pos += ((HdrExtLen+1)<<3); + } + break; + case IP_PROTO_FRAGMENT: + { + NextHeader = *Pos; + PayloadLen -= 8; + Pos += 8; + } + break; + case IP_PROTO_AH: + { + UCHAR AHPayloadLen = *(Pos+1); + UCHAR AHLen = (8+(AHPayloadLen<<2)); + + NextHeader = *Pos; + PayloadLen -= AHLen; + Pos += AHLen; + } + break; + default: + IsExtenHeader = 0; + break; + } + } + while((PayloadLen > 0) && (IsExtenHeader == 1)); + + if (PayloadLen <= 0) + return FALSE; + } + + /* Check if neighbor solicitation */ + if (*Pos == 0x87) + { + DBGPRINT(RT_DEBUG_TRACE, ("The Packet is IPv6ProxyARPCandidate\n")); + return TRUE; + } + } + //} + } + + return FALSE; +} + +//JERRY +BOOLEAN IsIPv6DHCPv6Solicitation(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData) +{ + UCHAR *Pos = pData; + UINT16 ProtoType, SrcPort, DstPort; + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_IPV6) + { + INT32 PayloadLen = 0; //((*(Pos+5) & 0xff) << 8) | (*(Pos+4) & 0xff); + UCHAR NextHeader = *(Pos+6); + UCHAR IsExtenHeader = 0; + + NdisMoveMemory(&PayloadLen, (Pos+4), 2); + PayloadLen = OS_NTOHS(PayloadLen); + + if ((NextHeader != IP_PROTO_HOPOPTS) && (NextHeader != IP_PROTO_ROUTING) && (NextHeader != IP_PROTO_FRAGMENT) && (NextHeader != IP_PROTO_AH) && (NextHeader != IP_PROTO_DSTOPTS)) + { + if (NextHeader == 0x11) + { + Pos += 40; + } + else + return FALSE; + } + else + { + IsExtenHeader = 1; + Pos += 40; + + do + { + printk("IsIPv6DHCPv6Solicitation: nextheader=0x%x, %d, %d\n", NextHeader, PayloadLen, IsExtenHeader); + switch (NextHeader) + { + case IP_PROTO_HOPOPTS: + case IP_PROTO_ROUTING: + case IP_PROTO_DSTOPTS: + { + UCHAR HdrExtLen = *(Pos+1); + + NextHeader = *Pos; + PayloadLen -= ((HdrExtLen+1)<<3); + Pos += ((HdrExtLen+1)<<3); + } + break; + case IP_PROTO_FRAGMENT: + { + NextHeader = *Pos; + PayloadLen -= 8; + Pos += 8; + } + break; + case IP_PROTO_AH: + { + UCHAR AHPayloadLen = *(Pos+1); + UCHAR AHLen = (8+(AHPayloadLen<<2)); + + NextHeader = *Pos; + PayloadLen -= AHLen; + Pos += AHLen; + } + break; + default: + IsExtenHeader = 0; + break; + } + } + while((PayloadLen > 0) && (IsExtenHeader == 1)); + + if (PayloadLen <= 0) + return FALSE; + } + + /* Check if DHCPv6 solicitation */ + { + unsigned char *type = (unsigned char *)(Pos+8); + + if ((*type == 1) || (*type == 4)) + { + NdisMoveMemory(&SrcPort, Pos, 2); + SrcPort = OS_NTOHS(SrcPort); + NdisMoveMemory(&DstPort, Pos+2, 2); + DstPort = OS_NTOHS(DstPort); + + if ((SrcPort == 546) && (DstPort == 547)) + { + DBGPRINT(RT_DEBUG_OFF, ("The Packet is DHCPv6 Solicitation,msg type=%d\n", *type)); + return TRUE; + } + } + } + } + + return FALSE; +} + + +BOOLEAN IsIPv6RouterSolicitation(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData) +{ + UCHAR *Pos = pData; + UINT16 ProtoType; + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_IPV6) + { + INT32 PayloadLen = 0; //((*(Pos+5) & 0xff) << 8) | (*(Pos+4) & 0xff); + UCHAR NextHeader = *(Pos+6); + UCHAR IsExtenHeader = 0; + + NdisMoveMemory(&PayloadLen, (Pos+4), 2); + PayloadLen = OS_NTOHS(PayloadLen); + + if ((NextHeader != IP_PROTO_HOPOPTS) && (NextHeader != IP_PROTO_ROUTING) && (NextHeader != IP_PROTO_FRAGMENT) && (NextHeader != IP_PROTO_AH) && (NextHeader != IP_PROTO_DSTOPTS)) + { + Pos += 40; + } + else + { + IsExtenHeader = 1; + Pos += 40; + + do + { + printk("IsIPv6RouterSolicitation: nextheader=0x%x, %d, %d\n", NextHeader, PayloadLen, IsExtenHeader); + switch (NextHeader) + { + case IP_PROTO_HOPOPTS: + case IP_PROTO_ROUTING: + case IP_PROTO_DSTOPTS: + { + UCHAR HdrExtLen = *(Pos+1); + + NextHeader = *Pos; + PayloadLen -= ((HdrExtLen+1)<<3); + Pos += ((HdrExtLen+1)<<3); + } + break; + case IP_PROTO_FRAGMENT: + { + NextHeader = *Pos; + PayloadLen -= 8; + Pos += 8; + } + break; + case IP_PROTO_AH: + { + UCHAR AHPayloadLen = *(Pos+1); + UCHAR AHLen = (8+(AHPayloadLen<<2)); + + NextHeader = *Pos; + PayloadLen -= AHLen; + Pos += AHLen; + } + break; + default: + IsExtenHeader = 0; + break; + } + } + while((PayloadLen > 0) && (IsExtenHeader == 1)); + + if (PayloadLen <= 0) + return FALSE; + } + + /* Check if router solicitation */ + if (*Pos == 0x85) + { + DBGPRINT(RT_DEBUG_OFF, ("The Packet is IPv6 Router Solicitation\n")); + return TRUE; + } + } + + return FALSE; +} + + +BOOLEAN IsIPv6RouterAdvertisement(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN PUCHAR pOffset) +{ + UCHAR *Pos = pData; + UINT16 ProtoType; + UCHAR *pData_offset = NULL; + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == ETH_P_IPV6) + { + INT32 PayloadLen = 0; + UCHAR NextHeader = *(Pos+6); + UCHAR IsExtenHeader = 0; + + NdisMoveMemory(&PayloadLen, (Pos+4), 2); + PayloadLen = OS_NTOHS(PayloadLen); + + if ((NextHeader != IP_PROTO_HOPOPTS) && + (NextHeader != IP_PROTO_ROUTING) && + (NextHeader != IP_PROTO_FRAGMENT) && + (NextHeader != IP_PROTO_AH) && + (NextHeader != IP_PROTO_DSTOPTS)) + { + Pos += 40; + pData_offset = Pos; + } + else + { + IsExtenHeader = 1; + Pos += 40; + pData_offset = Pos; + + do + { + DBGPRINT(RT_DEBUG_TRACE, ("IsIPv6RouterAdvertisement: nextheader=0x%x, %d, %d\n", NextHeader, PayloadLen, IsExtenHeader)); + switch (NextHeader) + { + case IP_PROTO_HOPOPTS: + case IP_PROTO_ROUTING: + case IP_PROTO_DSTOPTS: + { + UCHAR HdrExtLen = *(Pos+1); + + NextHeader = *Pos; + PayloadLen -= ((HdrExtLen+1)<<3); + Pos += ((HdrExtLen+1)<<3); + } + break; + case IP_PROTO_FRAGMENT: + { + NextHeader = *Pos; + PayloadLen -= 8; + Pos += 8; + } + break; + case IP_PROTO_AH: + { + UCHAR AHPayloadLen = *(Pos+1); + UCHAR AHLen = (8+(AHPayloadLen<<2)); + + NextHeader = *Pos; + PayloadLen -= AHLen; + Pos += AHLen; + } + break; + default: + IsExtenHeader = 0; + break; + } + } + while((PayloadLen > 0) && (IsExtenHeader == 1)); + + if (PayloadLen <= 0) + return FALSE; + } + + /* Check if router advertisement */ + if (*Pos == 0x86) + { + DBGPRINT(RT_DEBUG_TRACE, ("The Packet is IPv6 Router Advertisement\n")); + *pOffset = Pos-pData_offset; + return TRUE; + } + } + + return FALSE; +} + + +BOOLEAN IsTDLSPacket(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData) +{ + UCHAR *Pos = pData; + UINT16 ProtoType; + + NdisMoveMemory(&ProtoType, pData, 2); + ProtoType = OS_NTOHS(ProtoType); + Pos += 2; + + if (ProtoType == 0x890d) + { + DBGPRINT(RT_DEBUG_TRACE, ("THe Packet is TDLS\n")); + return TRUE; + } + + return FALSE; +} + + +UINT32 IPv4ProxyARPTableLen(IN PRTMP_ADAPTER pAd, + IN struct _BSS_STRUCT *pMbss) +{ + + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PROXY_ARP_IPV4_ENTRY *ProxyARPEntry; + UINT32 TableLen = 0; + INT32 Ret; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + TableLen += sizeof(PROXY_ARP_IPV4_UNIT); + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + + return TableLen; +} + +UINT32 IPv6ProxyARPTableLen(IN PRTMP_ADAPTER pAd, + IN struct _BSS_STRUCT *pMbss) +{ + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PROXY_ARP_IPV6_ENTRY *ProxyARPEntry; + UINT32 TableLen = 0; + INT32 Ret; + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPIPv6ListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv6ProxyARPList, PROXY_ARP_IPV6_ENTRY, List) + { + TableLen += sizeof(PROXY_ARP_IPV6_UNIT); + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPIPv6ListLock); + + return TableLen; +} + +BOOLEAN GetIPv4ProxyARPTable(IN PRTMP_ADAPTER pAd, + IN struct _BSS_STRUCT *pMbss, + PUCHAR *ProxyARPTable) +{ + + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PROXY_ARP_IPV4_ENTRY *ProxyARPEntry; + PROXY_ARP_IPV4_UNIT *ProxyARPUnit = (PROXY_ARP_IPV4_UNIT *)(*ProxyARPTable); + INT32 Ret; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + NdisMoveMemory(ProxyARPUnit->TargetMACAddr, ProxyARPEntry->TargetMACAddr, MAC_ADDR_LEN); + NdisMoveMemory(ProxyARPUnit->TargetIPAddr, ProxyARPEntry->TargetIPAddr, 4); + ProxyARPUnit++; + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + + return TRUE; +} + +BOOLEAN GetIPv6ProxyARPTable(IN PRTMP_ADAPTER pAd, + IN struct _BSS_STRUCT *pMbss, + PUCHAR *ProxyARPTable) +{ + + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PROXY_ARP_IPV6_ENTRY *ProxyARPEntry; + PROXY_ARP_IPV6_UNIT *ProxyARPUnit = (PROXY_ARP_IPV6_UNIT *)(*ProxyARPTable); + INT32 Ret; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPIPv6ListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv6ProxyARPList, PROXY_ARP_IPV6_ENTRY, List) + { + NdisMoveMemory(ProxyARPUnit->TargetMACAddr, ProxyARPEntry->TargetMACAddr, MAC_ADDR_LEN); + ProxyARPUnit->TargetIPType = ProxyARPEntry->TargetIPType; + NdisMoveMemory(ProxyARPUnit->TargetIPAddr, ProxyARPEntry->TargetIPAddr, 16); + ProxyARPUnit++; + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPIPv6ListLock); + + return TRUE; +} + +UINT32 AddIPv4ProxyARPEntry(IN PRTMP_ADAPTER pAd, + IN BSS_STRUCT *pMbss, + PUCHAR pTargetMACAddr, + PUCHAR pTargetIPAddr) +{ + + int i = 0, find_list = 0; + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PROXY_ARP_IPV4_ENTRY *ProxyARPEntry; + INT32 Ret; + + DBGPRINT(RT_DEBUG_OFF, ("%s ====>\n", __FUNCTION__)); + + if ((pTargetIPAddr[0] == 0) && (pTargetIPAddr[1] == 0)) { + DBGPRINT(RT_DEBUG_ERROR, ("Drop invalid IP Addr:%d.%d.%d.%d\n", pTargetIPAddr[0], pTargetIPAddr[1], pTargetIPAddr[2], pTargetIPAddr[3])); + return FALSE; + } + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + if (MAC_ADDR_EQUAL(ProxyARPEntry->TargetMACAddr, pTargetMACAddr)) + { + //RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + //return FALSE; + find_list = 1; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + + if (find_list == 0) + os_alloc_mem(NULL, (UCHAR **)&ProxyARPEntry, sizeof(*ProxyARPEntry)); + + if (!ProxyARPEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return FALSE; + } + + NdisMoveMemory(ProxyARPEntry->TargetMACAddr, pTargetMACAddr, 6); + NdisMoveMemory(ProxyARPEntry->TargetIPAddr, pTargetIPAddr, 4); + + for (i = 0; i < 4; i++) + DBGPRINT(RT_DEBUG_OFF,("pTargetIPv4Addr[%i] = %d\n", i, pTargetIPAddr[i])); + + /* Add ProxyARP Entry to list */ + if (find_list == 0) + { + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListAddTail(&pWNMCtrl->IPv4ProxyARPList, &ProxyARPEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + } + + return TRUE; +} + +VOID RemoveIPv4ProxyARPEntry(IN PRTMP_ADAPTER pAd, + IN BSS_STRUCT *pMbss, + PUCHAR pTargetMACAddr) +{ + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PROXY_ARP_IPV4_ENTRY *ProxyARPEntry, *ProxyARPEntryTmp; + INT32 Ret; + + DBGPRINT(RT_DEBUG_OFF, ("%s ====>\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + + DlListForEachSafe(ProxyARPEntry, ProxyARPEntryTmp, &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + if (!ProxyARPEntry) + break; + + if (MAC_ADDR_EQUAL(ProxyARPEntry->TargetMACAddr, pTargetMACAddr)) + { + //RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + //return FALSE; + DlListDel(&ProxyARPEntry->List); + os_free_mem(NULL, ProxyARPEntry); + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); +} + +UINT32 AddIPv6ProxyARPEntry(IN PRTMP_ADAPTER pAd, + IN BSS_STRUCT *pMbss, + PUCHAR pTargetMACAddr, + PUCHAR pTargetIPAddr) +{ + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PROXY_ARP_IPV6_ENTRY *ProxyARPEntry; + INT32 Ret; + UINT8 i; + BOOLEAN IsDAD = FALSE; + PNET_DEV NetDev = pMbss->wdev.if_dev; + DBGPRINT(RT_DEBUG_OFF, ("%s ====>\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPIPv6ListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv6ProxyARPList, PROXY_ARP_IPV6_ENTRY, List) + { + if (MAC_ADDR_EQUAL(ProxyARPEntry->TargetMACAddr, pTargetMACAddr) && + IPV6_ADDR_EQUAL(ProxyARPEntry->TargetIPAddr, pTargetIPAddr)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s, the Mac address and IPv6 Address exactly same as the one in List already!\n", __FUNCTION__)); + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPIPv6ListLock); + return FALSE; + } + + if ((MAC_ADDR_EQUAL(ProxyARPEntry->TargetMACAddr, pTargetMACAddr) == FALSE) && + IPV6_ADDR_EQUAL(ProxyARPEntry->TargetIPAddr, pTargetIPAddr)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s, different Mac address use IPv6 address which already in List!\n", __func__)); + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPIPv6ListLock); + IsDAD = TRUE; + + /*we got IPv6 DAD here, AP shall issue Neighbor Advertisement back to sender in below format */ + /* SenderMAC is the mac which in List, */ + /* DestMAC is multicast address e.g, 33:33:00:00:00:01 */ + /* SourceIP = TargetIP = TentativeIP, in this case is the IP which in List */ + /* DestIP = FF02::1 */ + SendProxyARPEvent(NetDev, + pTargetMACAddr, + ProxyARPEntry->TargetIPAddr, + ProxyARPEntry->TargetMACAddr, + ProxyARPEntry->TargetIPAddr, + IPV6, + FALSE, + IsDAD); + + return FALSE; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPIPv6ListLock); + + os_alloc_mem(NULL, (UCHAR **)&ProxyARPEntry, sizeof(*ProxyARPEntry)); + + if (!ProxyARPEntry) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return FALSE; + } + + NdisMoveMemory(ProxyARPEntry->TargetMACAddr, pTargetMACAddr, 6); + + if (NdisEqualMemory(link_local, pTargetIPAddr, 2)) + ProxyARPEntry->TargetIPType = IPV6_LINK_LOCAL; + else + ProxyARPEntry->TargetIPType = IPV6_GLOBAL; + + NdisMoveMemory(ProxyARPEntry->TargetIPAddr, pTargetIPAddr, 16); + + for (i = 0; i < 6; i++) + DBGPRINT(RT_DEBUG_OFF,("pTargetMACAddr[%i] = %x\n", i, pTargetMACAddr[i])); + + for (i = 0; i < 16; i++) + DBGPRINT(RT_DEBUG_OFF,("pTargetIPv6Addr[%i] = %d\n", i, pTargetIPAddr[i])); + + /* Add ProxyARP Entry to list */ + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPIPv6ListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListAddTail(&pWNMCtrl->IPv6ProxyARPList, &ProxyARPEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPIPv6ListLock); + + return TRUE; +} + +VOID RemoveIPv6ProxyARPEntry(IN PRTMP_ADAPTER pAd, + IN BSS_STRUCT *pMbss, + PUCHAR pTargetMACAddr) +{ + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PROXY_ARP_IPV6_ENTRY *ProxyARPEntry, *ProxyARPEntryTmp; + INT32 Ret; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPIPv6ListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + + DlListForEachSafe(ProxyARPEntry, ProxyARPEntryTmp, &pWNMCtrl->IPv6ProxyARPList, PROXY_ARP_IPV6_ENTRY, List) + { + if (!ProxyARPEntry) + break; + + if (MAC_ADDR_EQUAL(ProxyARPEntry->TargetMACAddr, pTargetMACAddr)) + { + DlListDel(&ProxyARPEntry->List); + os_free_mem(NULL, ProxyARPEntry); + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPIPv6ListLock); +} + +BOOLEAN IPv4ProxyARP(IN PRTMP_ADAPTER pAd, + IN BSS_STRUCT *pMbss, + IN PUCHAR pData, + IN BOOLEAN FromDS) +{ + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PNET_DEV NetDev = pMbss->wdev.if_dev; + BOOLEAN IsFound = FALSE, InTable = FALSE; + PROXY_ARP_IPV4_ENTRY *ProxyARPEntry; + PUCHAR SourceMACAddr = pData + 10; + PUCHAR SourceIPAddr = pData + 16; + PUCHAR TargetIPAddr = pData + 26; + INT32 Ret; + BOOLEAN IsDAD = FALSE; + PUCHAR TargetMACAddr = pData + 20; + UCHAR ALL_ZERO_BROADCAST_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + if (IPV4_ADDR_EQUAL(ProxyARPEntry->TargetIPAddr, TargetIPAddr)) + { + IsFound = TRUE; + + if ( + (MAC_ADDR_EQUAL(ProxyARPEntry->TargetMACAddr, SourceMACAddr) == FALSE) && + ((MAC_ADDR_EQUAL(TargetMACAddr, BROADCAST_ADDR) == TRUE) || + (MAC_ADDR_EQUAL(TargetMACAddr, ALL_ZERO_BROADCAST_ADDR) == TRUE)) && + (IPV4_ADDR_EQUAL(SourceIPAddr, ZERO_IP_ADDR) == TRUE) + ) { + //Mac address is not equal to the one which already in List. + //it's a DAD arp. + IsDAD = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("%s, Found DAD!!!!\n", __FUNCTION__)); + printk("found dad...\n"); + } + + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + + if (IsFound) + { + /* ARP Probe and ARP Entry already Build and not DAD */ + if ((IsDAD == FALSE) && (IPV4_ADDR_EQUAL(SourceIPAddr, ZERO_IP_ADDR) == TRUE)) + return IsFound; + + /* Send proxy arp indication to daemon */ + SendProxyARPEvent(NetDev, + SourceMACAddr, + SourceIPAddr, + ProxyARPEntry->TargetMACAddr, + ProxyARPEntry->TargetIPAddr, + IPV4, + FromDS, + IsDAD); + + if ((IsDAD == FALSE) && (FromDS == FALSE)) { + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + if (IPV4_ADDR_EQUAL(ProxyARPEntry->TargetIPAddr, SourceIPAddr)) + { + InTable = TRUE; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + if (InTable == FALSE) { + AddIPv4ProxyARPEntry(pAd, pMbss, SourceMACAddr, SourceIPAddr); + DBGPRINT(RT_DEBUG_ERROR, + ("%s, New Station take arp request, Learning ARP Entry from it\n", __func__)); + } + } + } + else + { + if ( + ((MAC_ADDR_EQUAL(TargetMACAddr, BROADCAST_ADDR) == TRUE) || + (MAC_ADDR_EQUAL(TargetMACAddr, ALL_ZERO_BROADCAST_ADDR) == TRUE)) && (FromDS == FALSE) + ) { + //waht if there is a new mac for List, and take BOARDCAST and ZERO_IP, + //it's a station take DAD packet to ask the network. + //In this case, AP shall learn the mac/ip mapping from it. + if (IPV4_ADDR_EQUAL(SourceIPAddr, ZERO_IP_ADDR) == TRUE) { + AddIPv4ProxyARPEntry(pAd, pMbss, SourceMACAddr, TargetIPAddr); + DBGPRINT(RT_DEBUG_ERROR, + ("%s, New Station take DAD to detect, Learning ARP Entry from it\n", __func__)); + } + else { + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + if (IPV4_ADDR_EQUAL(ProxyARPEntry->TargetIPAddr, SourceIPAddr)) + { + InTable = TRUE; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + if (InTable == FALSE) { + AddIPv4ProxyARPEntry(pAd, pMbss, SourceMACAddr, SourceIPAddr); + DBGPRINT(RT_DEBUG_ERROR, + ("%s, New Station take arp request to detect, Learning ARP Entry from it\n", __func__)); + } + } + } + } + + return IsFound; +} + +BOOLEAN IPv6ProxyARP(IN PRTMP_ADAPTER pAd, + IN BSS_STRUCT *pMbss, + IN PUCHAR pData, + IN BOOLEAN FromDS) +{ + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + PNET_DEV NetDev = pMbss->wdev.if_dev; + BOOLEAN IsFound = FALSE; + PROXY_ARP_IPV6_ENTRY *ProxyARPEntry; + PUCHAR SourceMACAddr = pData + 68; + PUCHAR SourceIPAddr = pData + 10; + PUCHAR TargetIPAddr = pData + 50; + INT32 Ret; + BOOLEAN IsDAD = FALSE; + + //DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv6ProxyARPList, PROXY_ARP_IPV6_ENTRY, List) + { + if (IPV6_ADDR_EQUAL(ProxyARPEntry->TargetIPAddr, TargetIPAddr)) + { + IsFound = TRUE; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + + if (IsFound) + { + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + /* Send proxy arp indication to daemon */ + SendProxyARPEvent(NetDev, + SourceMACAddr, + SourceIPAddr, + ProxyARPEntry->TargetMACAddr, + ProxyARPEntry->TargetIPAddr, + IPV6, + FromDS, + IsDAD); + } + + return IsFound; +} + + +VOID WNMIPv4ProxyARPCheck( + IN PRTMP_ADAPTER pAd, + PNDIS_PACKET pPacket, + USHORT srcPort, + USHORT dstPort, + PUCHAR pSrcBuf) +{ + struct wifi_dev *wdev; + UCHAR wdev_idx = RTMP_GET_PACKET_WDEV(pPacket); + BSS_STRUCT *pMbss; + MAC_TABLE_ENTRY *pEntry; + + ASSERT(wdev_idx < WDEV_NUM_MAX); + if (wdev_idx >= WDEV_NUM_MAX) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Invalid wdev_idx(%d)\n", __FUNCTION__, wdev_idx)); + return; + } + + wdev = pAd->wdev_list[wdev_idx]; + ASSERT(wdev->func_idx < pAd->ApCfg.BssidNum); + pMbss = &pAd->ApCfg.MBSSID[wdev->func_idx]; + if (srcPort == 0x43 && dstPort == 0x44) + { + UCHAR *pTargetIPAddr = pSrcBuf + 24; + /* Client hardware address */ + UCHAR *pTargetMACAddr = pSrcBuf + 36; + + if ((pMbss->WNMCtrl.ProxyARPEnable) && (pEntry = MacTableLookup(pAd, pTargetMACAddr))) + { + printk("entry apidx=%d,%d,%d\n",pEntry->func_tb_idx, wdev_idx, pMbss->WNMCtrl.ProxyARPEnable); + + if ((pEntry->func_tb_idx == wdev_idx) && pMbss->WNMCtrl.ProxyARPEnable) + { + /* Proxy MAC address/IP mapping */ + AddIPv4ProxyARPEntry(pAd, pMbss, pTargetMACAddr, pTargetIPAddr); + } + } + } +} + + +VOID WNMIPv6ProxyARPCheck( + IN PRTMP_ADAPTER pAd, + PNDIS_PACKET pPacket, + PUCHAR pSrcBuf) +{ + struct wifi_dev *wdev; + UCHAR wdev_idx = RTMP_GET_PACKET_WDEV(pPacket); + BSS_STRUCT *pMbss; + UCHAR Offset = 0; + + ASSERT(wdev_idx < WDEV_NUM_MAX); + if (wdev_idx >= WDEV_NUM_MAX) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Invalid wdev_idx(%d)\n", __FUNCTION__, wdev_idx)); + return; + } + + wdev = pAd->wdev_list[wdev_idx]; + ASSERT(wdev->func_idx < pAd->ApCfg.BssidNum); + pMbss = &pAd->ApCfg.MBSSID[wdev->func_idx]; + if (pMbss->WNMCtrl.ProxyARPEnable) + { + /* Check if router advertisement, and add proxy entry */ + if (IsIPv6RouterAdvertisement(pAd, pSrcBuf - 2, &Offset)) + { + UCHAR *Pos = pSrcBuf + 4; + UCHAR TargetIPAddr[16]; + INT32 PayloadLen; + DBGPRINT(RT_DEBUG_OFF, ("This packet is router advertisement\n")); + + NdisMoveMemory(&PayloadLen, Pos, 2); + PayloadLen = OS_NTOHS(PayloadLen); + + printk("WNMIPv6ProxyARPCheck: offset=%d\n", Offset); + /* IPv6 options */ + Pos += 52 + Offset; + PayloadLen -= (16 + Offset); + + while (PayloadLen > 0) + { + UINT8 OptionsLen = (*(Pos + 1)) * 8; + + /* Prefix information */ + if (*Pos == 0x03) + { + UCHAR *Prefix; + INT32 Ret; + PROXY_ARP_IPV6_ENTRY *ProxyARPEntry; + PWNM_CTRL pWNMCtrl = &pMbss->WNMCtrl; + + /* Prefix */ + Prefix = (Pos + 16); + + /* Copy global address prefix */ + NdisMoveMemory(TargetIPAddr, Prefix, 8); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(ProxyARPEntry, &pWNMCtrl->IPv6ProxyARPList, + PROXY_ARP_IPV6_ENTRY, List) + { + if (ProxyARPEntry->TargetIPType == IPV6_LINK_LOCAL) + { + + /* Copy host ipv6 interface identifier */ + NdisMoveMemory(&TargetIPAddr[8], + &ProxyARPEntry->TargetIPAddr[8], 8); + + /* Proxy MAC address/IPv6 mapping for global address */ + AddIPv6ProxyARPEntry(pAd, pMbss, ProxyARPEntry->TargetMACAddr, + TargetIPAddr); + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + } + + Pos += OptionsLen; + PayloadLen -= OptionsLen; + } + } + } +} + + +static VOID ReceiveBTMQuery(IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + WNM_FRAME *WNMFrame = (WNM_FRAME *)Elem->Msg; + BTM_PEER_ENTRY *BTMPeerEntry; + PWNM_CTRL pWNMCtrl = NULL; + UCHAR APIndex; + UINT16 VarLen; + INT32 Ret; + BOOLEAN IsFound = FALSE; + PNET_DEV NetDev = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __func__)); + + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) { + if (MAC_ADDR_EQUAL(WNMFrame->Hdr.Addr3, pAd->ApCfg.MBSSID[APIndex].wdev.bssid)) { + pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; + break; + } + } + + if (!pWNMCtrl) { + DBGPRINT(RT_DEBUG_ERROR, ("%s Can not find Peer Control\n", __FUNCTION__)); + return; + } + + if (pWNMCtrl->WNMBTMEnable == 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s BTM Not Supported Drop!!\n", __func__)); + return; + } + + NetDev = pAd->ApCfg.MBSSID[APIndex].wdev.if_dev; + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + + DlListForEach(BTMPeerEntry, &pWNMCtrl->BTMPeerList, BTM_PEER_ENTRY, List) { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, WNMFrame->Hdr.Addr2)) + IsFound = TRUE; + + break; + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + + if (IsFound) { + DBGPRINT(RT_DEBUG_ERROR, ("%s Find peer address in BTMPeerList already\n", __FUNCTION__)); + return; + } + + os_alloc_mem(NULL, (UCHAR **)&BTMPeerEntry, sizeof(*BTMPeerEntry)); + + if (!BTMPeerEntry) { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(BTMPeerEntry, sizeof(*BTMPeerEntry)); + BTMPeerEntry->CurrentState = WAIT_BTM_REQ; + + NdisMoveMemory(BTMPeerEntry->PeerMACAddr, WNMFrame->Hdr.Addr2, MAC_ADDR_LEN); + BTMPeerEntry->DialogToken = WNMFrame->u.BTM_QUERY.DialogToken; + BTMPeerEntry->Priv = pAd; + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListAddTail(&pWNMCtrl->BTMPeerList, &BTMPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + + VarLen = Elem->MsgLen - + (sizeof(HEADER_802_11) + 1 + sizeof(WNMFrame->u.BTM_QUERY)) + 1; + SendBTMQueryEvent(NetDev, + WNMFrame->Hdr.Addr2, + (PUCHAR)&(WNMFrame->u.BTM_QUERY.DialogToken), + VarLen, + RA_WEXT); + + RTMPInitTimer(pAd, &BTMPeerEntry->WaitPeerBTMReqTimer, + GET_TIMER_FUNCTION(WaitPeerBTMReqTimeout), BTMPeerEntry, FALSE); + RTMPSetTimer(&BTMPeerEntry->WaitPeerBTMReqTimer, WaitPeerBTMReqTimeoutVale); +} + + +static VOID ReceiveBTMRsp(IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + WNM_FRAME *WNMFrame = (WNM_FRAME *)Elem->Msg; + BTM_PEER_ENTRY *BTMPeerEntry; + PWNM_CTRL pWNMCtrl = NULL; + UCHAR APIndex; + UINT16 VarLen = 0; + INT32 Ret; + BOOLEAN IsFound = FALSE, Cancelled; + PNET_DEV NetDev = NULL; + + printk("%s\n", __FUNCTION__); + + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + if (MAC_ADDR_EQUAL(WNMFrame->Hdr.Addr3, pAd->ApCfg.MBSSID[APIndex].wdev.bssid)) + { + pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; + break; + } + } + + if (!pWNMCtrl) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Can not find Peer Control\n", __FUNCTION__)); + return; + } + + if (pWNMCtrl->WNMBTMEnable == 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s BTM Not Supported Drop!!\n", __func__)); + return; + } + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListForEach(BTMPeerEntry, &pWNMCtrl->BTMPeerList, BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, WNMFrame->Hdr.Addr2)) + IsFound = TRUE; + + break; + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + + if (!IsFound) { + DBGPRINT(RT_DEBUG_ERROR, ("Not found peer entry in list\n")); + return; + } + + /* Cancel Wait peer wnm response frame */ + RTMPCancelTimer(&BTMPeerEntry->WaitPeerBTMRspTimer, &Cancelled); + RTMPReleaseTimer(&BTMPeerEntry->WaitPeerBTMRspTimer, &Cancelled); + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListDel(&BTMPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + os_free_mem(NULL, BTMPeerEntry); + + NetDev = pAd->ApCfg.MBSSID[APIndex].wdev.if_dev; + /* Send BTM confirm to daemon */ + VarLen = Elem->MsgLen - + (sizeof(HEADER_802_11) + 1 + sizeof(WNMFrame->u.BTM_RSP)) + 1; + SendBTMConfirmEvent(NetDev, + WNMFrame->Hdr.Addr2, + (PUCHAR)&(WNMFrame->u.BTM_RSP.DialogToken), + VarLen, + RA_WEXT); +} + + +VOID BTMSetPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem, + IN enum BTM_STATE State) +{ + PWNM_CTRL pWNMCtrl; + PBTM_PEER_ENTRY BTMPeerEntry; + PBTM_EVENT_DATA Event = (PBTM_EVENT_DATA)Elem->Msg; + INT32 Ret; + +#ifdef CONFIG_AP_SUPPORT + pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; +#endif /* CONFIG_AP_SUPPORT */ + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(BTMPeerEntry, &pWNMCtrl->BTMPeerList, + BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + BTMPeerEntry->CurrentState = State; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); +} + +static VOID SendBTMQueryIndication( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + BTM_EVENT_DATA *Event = (BTM_EVENT_DATA *)Elem->Msg; + PNET_DEV NetDev = pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.if_dev; + + printk("%s\n", __FUNCTION__); + + /* Send BTM query indication to daemon */ + SendBTMQueryEvent(NetDev, + Event->PeerMACAddr, + Event->u.PEER_BTM_QUERY_DATA.BTMQuery, + Event->u.PEER_BTM_QUERY_DATA.BTMQueryLen, + RA_WEXT); + + BTMSetPeerCurrentState(pAd, Elem, WAIT_BTM_REQ); +} + + +VOID WaitPeerBTMReqTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + BTM_PEER_ENTRY *BTMPeerEntry = (BTM_PEER_ENTRY *)FunctionContext; + PRTMP_ADAPTER pAd = NULL; + BTM_EVENT_DATA event; + + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s BTMPeerEntry:%p\n", __func__, BTMPeerEntry)); + if (!BTMPeerEntry) + return; + + pAd = BTMPeerEntry->Priv; + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS + | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + memset(&event, 0, sizeof(event)); + memcpy(event.PeerMACAddr, BTMPeerEntry->PeerMACAddr, MAC_ADDR_LEN); + event.ControlIndex = BTMPeerEntry->ControlIndex; + event.u.BTM_REQ_DATA.DialogToken = BTMPeerEntry->DialogToken; + + MlmeEnqueue(pAd, BTM_STATE_MACHINE, BTM_REQ_TIMEOUT, + sizeof(BTM_EVENT_DATA), &event, 0); +} +BUILD_TIMER_FUNCTION(WaitPeerBTMReqTimeout); + + +VOID WaitPeerBTMRspTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PBTM_PEER_ENTRY BTMPeerEntry = (PBTM_PEER_ENTRY)FunctionContext; + PRTMP_ADAPTER pAd = NULL; + BTM_EVENT_DATA event; + + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s BTMPeerEntry:%p\n", __func__, BTMPeerEntry)); + + if (!BTMPeerEntry) + return; + + pAd = BTMPeerEntry->Priv; + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS + | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + memset(&event, 0, sizeof(event)); + memcpy(event.PeerMACAddr, BTMPeerEntry->PeerMACAddr, MAC_ADDR_LEN); + event.ControlIndex = BTMPeerEntry->ControlIndex; + event.u.PEER_BTM_RSP_DATA.DialogToken = BTMPeerEntry->DialogToken; + + MlmeEnqueue(pAd, BTM_STATE_MACHINE, PEER_BTM_RSP_TIMEOUT, + sizeof(BTM_EVENT_DATA), &event, 0); + +} +BUILD_TIMER_FUNCTION(WaitPeerBTMRspTimeout); + + +static VOID SendBTMReq( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + BTM_EVENT_DATA *Event = (BTM_EVENT_DATA *)Elem->Msg; + UCHAR *Buf; + WNM_FRAME *WNMFrame; + BTM_PEER_ENTRY *BTMPeerEntry = NULL; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; + UINT32 FrameLen = 0, VarLen = Event->u.BTM_REQ_DATA.BTMReqLen; + INT32 Ret; + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(BTMPeerEntry, &pWNMCtrl->BTMPeerList, + BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*WNMFrame) + VarLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*WNMFrame) + VarLen); + + WNMFrame = (WNM_FRAME *)Buf; + + ActHeaderInit(pAd, &WNMFrame->Hdr, Event->PeerMACAddr, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid); + + FrameLen += sizeof(HEADER_802_11); + + WNMFrame->Category = CATEGORY_WNM; + FrameLen += 1; + + WNMFrame->u.BTM_REQ.Action = BSS_TRANSITION_REQ; + FrameLen += 1; + + WNMFrame->u.BTM_REQ.DialogToken = Event->u.BTM_REQ_DATA.DialogToken; + FrameLen += 1; + + NdisMoveMemory(WNMFrame->u.BTM_REQ.Variable, Event->u.BTM_REQ_DATA.BTMReq, + Event->u.BTM_REQ_DATA.BTMReqLen); + FrameLen += Event->u.BTM_REQ_DATA.BTMReqLen; + + BTMSetPeerCurrentState(pAd, Elem, WAIT_PEER_BTM_RSP); + + MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | QID_AC_BE), Buf, FrameLen); + + RTMPSetTimer(&BTMPeerEntry->WaitPeerBTMRspTimer, WaitPeerBTMRspTimeoutVale); + +#if (defined(CONFIG_HOTSPOT_R2) || defined(CONFIG_DOT11V_WNM)) + { + MAC_TABLE_ENTRY *pEntry; + + pEntry = MacTableLookup(pAd, Event->PeerMACAddr); + if (pEntry != NULL) { + UINT8 *BTMData = (UINT8 *)Event->u.BTM_REQ_DATA.BTMReq; + /*if (*BTMData & 0x04) {*/ + if ((*(BTMData) & 0x1C) != 0) { + pEntry->BTMDisassocCount = (((*(BTMData+2) << 8) | (*(BTMData+1)))*pAd->CommonCfg.BeaconPeriod)/1000; + DBGPRINT(RT_DEBUG_OFF, ("[%s] bss DisAssocCount sec=%d\n", __func__, pEntry->BTMDisassocCount)); + if (pEntry->BTMDisassocCount < 1) + pEntry->BTMDisassocCount = 1; + } + } + } +#endif + + os_free_mem(NULL, Buf); +} + + +static VOID SendBTMReqIE( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem) +{ + PBTM_EVENT_DATA Event = (PBTM_EVENT_DATA)Elem->Msg; + PBTM_PEER_ENTRY BTMPeerEntry = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; + PUCHAR p_btm_req_data = Event->u.BTM_REQ_DATA.BTMReq; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + UINT32 btm_reqinfo_len = Event->u.BTM_REQ_DATA.BTMReqLen; + INT32 Ret; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + BOOLEAN isfound = FALSE, Cancelled; + HEADER_802_11 ActHdr; + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListForEach(BTMPeerEntry, &pWNMCtrl->BTMPeerList, + BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, Event->PeerMACAddr)) { + isfound = TRUE; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + + if (!isfound) { + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_RRM, DBG_LVL_ERROR, + ("%s() BTMPeerEntry is already deleted\n", + __func__)); + return; + } + + pEntry = MacTableLookup(pAd, Event->PeerMACAddr); + if (!pEntry || !((Ndis802_11AuthModeAutoSwitch >= + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.AuthMode) || + ((pEntry->WpaState == AS_PTKINITDONE) && + (pEntry->GTKState == REKEY_ESTABLISHED)))) { + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_RRM, DBG_LVL_ERROR, + ("%s() STA(%02x:%02x:%02x:%02x:%02x:%02x)not associates with AP!\n", + __func__, PRINT_MAC(Event->PeerMACAddr))); + goto error; + } + + /*allocate a buffer prepare for btm req frame*/ + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) { + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_RRM, DBG_LVL_ERROR, + ("%s() allocate memory for btm req frame failed\n", + __func__)); + goto error; + } + + /*compose 80211 header*/ + ActHeaderInit(pAd, &ActHdr, Event->PeerMACAddr, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid); + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(ActHdr)); + FrameLen = sizeof(ActHdr); + /*compose the Neighbor report header + * category, action and token + */ + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, + CATEGORY_WNM, BSS_TRANSITION_REQ); + InsertDialogToken(pAd, (pOutBuffer + FrameLen), + &FrameLen, Event->u.BTM_REQ_DATA.DialogToken); + memcpy((pOutBuffer + FrameLen), p_btm_req_data, btm_reqinfo_len); + FrameLen += btm_reqinfo_len; + + BTMPeerEntry->CurrentState = WAIT_PEER_BTM_RSP; + MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | QID_AC_BE), pOutBuffer, FrameLen); + RTMPCancelTimer(&BTMPeerEntry->WaitPeerBTMReqTimer, &Cancelled); + RTMPReleaseTimer(&BTMPeerEntry->WaitPeerBTMReqTimer, &Cancelled); + RTMPInitTimer(pAd, &BTMPeerEntry->WaitPeerBTMRspTimer, + GET_TIMER_FUNCTION(WaitPeerBTMRspTimeout), BTMPeerEntry, FALSE); + RTMPSetTimer(&BTMPeerEntry->WaitPeerBTMRspTimer, + (BTMPeerEntry->WaitPeerBTMRspTime == 0) ? WaitPeerBTMRspTimeoutVale : BTMPeerEntry->WaitPeerBTMRspTime); + + if (p_btm_req_data[0] & 0x04) { + pEntry->BTMDisassocCount = + (p_btm_req_data[1] | p_btm_req_data[2]<<8) * pAd->CommonCfg.BeaconPeriod / 1000; + DBGPRINT(RT_DEBUG_OFF, ("bss discount sec=%d\n", pEntry->BTMDisassocCount)); + if (pEntry->BTMDisassocCount < 1) + pEntry->BTMDisassocCount = 1; + } + + os_free_mem(NULL, pOutBuffer); + return; + +error: + if (BTMPeerEntry->WaitPeerBTMReqTimer.Valid) { + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_RRM, DBG_LVL_ERROR, + ("%s() BTMReqTimer is valid, wait timeout to delete BTMPeerEntry\n", + __func__)); + } else { + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_RRM, DBG_LVL_ERROR, + ("%s() BTMReqTimer is not valid, delete BTMPeerEntry now\n", + __func__)); + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListDel(&BTMPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + os_free_mem(NULL, BTMPeerEntry); + } +} + +static VOID SendBTMReqParam( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem) +{ + PBTM_EVENT_DATA Event = (PBTM_EVENT_DATA)Elem->Msg; + PBTM_PEER_ENTRY BTMPeerEntry = NULL; + PMAC_TABLE_ENTRY pEntry = NULL; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; + p_btm_reqinfo_t p_btm_req_data = + (p_btm_reqinfo_t)Event->u.BTM_REQ_DATA.BTMReq; + PUCHAR pOutBuffer = NULL; + ULONG FrameLen = 0; + UINT32 TmpLen = 0; + UINT32 btm_reqinfo_len = Event->u.BTM_REQ_DATA.BTMReqLen; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + INT32 Ret; + BOOLEAN isfound = FALSE, Cancelled; + HEADER_802_11 ActHdr; + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListForEach(BTMPeerEntry, &pWNMCtrl->BTMPeerList, + BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, Event->PeerMACAddr)) { + isfound = TRUE; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + + if (!isfound) { + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_RRM, DBG_LVL_ERROR, + ("%s() BTMPeerEntry is already deleted\n", + __func__)); + return; + } + + /*check the parameters*/ + NStatus = check_btm_custom_params(pAd, p_btm_req_data, btm_reqinfo_len); + if (NStatus != NDIS_STATUS_SUCCESS) { + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_RRM, DBG_LVL_ERROR, + ("%s() check customer params failed\n", __func__)); + goto error; + } + + /*allocate a buffer prepare for btm req frame*/ + NStatus = MlmeAllocateMemory(pAd, (PVOID)&pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) { + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_RRM, DBG_LVL_ERROR, + ("%s() allocate memory for btm req frame failed\n", + __func__)); + goto error; + } + /*compose 80211 header*/ + ActHeaderInit(pAd, &ActHdr, p_btm_req_data->sta_mac, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid); + NdisMoveMemory(pOutBuffer, (PCHAR)&ActHdr, sizeof(ActHdr)); + FrameLen = sizeof(ActHdr); + + /*compose the Neighbor report header + * category, action and token + */ + InsertActField(pAd, (pOutBuffer + FrameLen), &FrameLen, + CATEGORY_WNM, BSS_TRANSITION_REQ); + InsertDialogToken(pAd, (pOutBuffer + FrameLen), + &FrameLen, p_btm_req_data->dialogtoken); + + /*compose the Neighbor report IE*/ + compose_btm_req_ie(pAd, (pOutBuffer + FrameLen), &TmpLen, + p_btm_req_data, btm_reqinfo_len); + FrameLen += TmpLen; + + BTMPeerEntry->CurrentState = WAIT_PEER_BTM_RSP; + MiniportMMRequest(pAd, (MGMT_USE_QUEUE_FLAG | QID_AC_BE), pOutBuffer, FrameLen); + + RTMPCancelTimer(&BTMPeerEntry->WaitPeerBTMReqTimer, &Cancelled); + RTMPReleaseTimer(&BTMPeerEntry->WaitPeerBTMReqTimer, &Cancelled); + RTMPInitTimer(pAd, &BTMPeerEntry->WaitPeerBTMRspTimer, + GET_TIMER_FUNCTION(WaitPeerBTMRspTimeout), BTMPeerEntry, FALSE); + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_RRM, DBG_LVL_ERROR, + ("HZ=%d, WaitPeerBTMRspTime=%d\n", HZ, BTMPeerEntry->WaitPeerBTMRspTime)); + RTMPSetTimer(&BTMPeerEntry->WaitPeerBTMRspTimer, + (BTMPeerEntry->WaitPeerBTMRspTime == 0) ? WaitPeerBTMRspTimeoutVale : BTMPeerEntry->WaitPeerBTMRspTime); + + pEntry = MacTableLookup(pAd, Event->PeerMACAddr); + if (pEntry != NULL) { + if (p_btm_req_data->reqmode & 0x04) { + pEntry->BTMDisassocCount = + p_btm_req_data->disassoc_timer * pAd->CommonCfg.BeaconPeriod / 1000; + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_RRM, DBG_LVL_ERROR, + ("bss discount sec=%d\n", pEntry->BTMDisassocCount)); + if (pEntry->BTMDisassocCount < 1) + pEntry->BTMDisassocCount = 1; + } + } + + os_free_mem(NULL, pOutBuffer); + return; + +error: + if (BTMPeerEntry->WaitPeerBTMReqTimer.Valid) { + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_RRM, DBG_LVL_ERROR, + ("%s() BTMReqTimer is valid, wait timeout to delete BTMPeerEntry\n", + __func__)); + } else { + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_RRM, DBG_LVL_ERROR, + ("%s() BTMReqTimer is not valid, delete BTMPeerEntry now\n", + __func__)); + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListDel(&BTMPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + os_free_mem(NULL, BTMPeerEntry); + } +} + + +static VOID SendBTMConfirm( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + PBTM_PEER_ENTRY BTMPeerEntry, BTMPeerEntryTmp; + BTM_EVENT_DATA *Event = (BTM_EVENT_DATA *)Elem->Msg; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; + PNET_DEV NetDev = pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.if_dev; + INT32 Ret; + + printk("%s\n", __FUNCTION__); + + /* Send BTM confirm to daemon */ + SendBTMConfirmEvent(NetDev, + Event->PeerMACAddr, + Event->u.PEER_BTM_RSP_DATA.BTMRsp, + Event->u.PEER_BTM_RSP_DATA.BTMRspLen, + RA_WEXT); + + /* Delete BTM peer entry */ + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEachSafe(BTMPeerEntry, BTMPeerEntryTmp, &pWNMCtrl->BTMPeerList, BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + + DlListDel(&BTMPeerEntry->List); + os_free_mem(NULL, BTMPeerEntry); + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + +} + +static VOID BTMReqTimeout( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem) +{ + BTM_EVENT_DATA event; + BTM_PEER_ENTRY *BTMPeerEntry = NULL, *BTMPeerEntryTmp = NULL; + PWNM_CTRL pWNMCtrl = NULL; + INT32 Ret; + BOOLEAN Cancelled; + + DBGPRINT(RT_DEBUG_OFF, + ("%s\n", __func__)); + + RTMPMoveMemory(&event, Elem->Msg, sizeof(event)); + + pWNMCtrl = &pAd->ApCfg.MBSSID[event.ControlIndex].WNMCtrl; + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListForEachSafe(BTMPeerEntry, BTMPeerEntryTmp, &pWNMCtrl->BTMPeerList, BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, &event.PeerMACAddr[0])) + break; + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + + /* + * no other place to delete BTMPeerEntry when receive btm query; + * so here must exist BTMPeerEntry + */ + if (BTMPeerEntry->WaitPeerBTMRspTimer.Valid) { + DBGPRINT(RT_DEBUG_OFF, + ("%s receive btm req and set btm rsp timer no need to delete BTMPeerEntry\n", + __func__)); + } else { + /*timeout; need delete BTMPeerEntry*/ + DBGPRINT(RT_DEBUG_OFF, + ("%s receive btm req timeout the uplayer does not send btm req in time\n", + __func__)); + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListDel(&BTMPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + RTMPReleaseTimer(&BTMPeerEntry->WaitPeerBTMReqTimer, &Cancelled); + os_free_mem(NULL, BTMPeerEntry); + } +} + + +static VOID ReceiveBTMRspTimeout( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem) +{ + BTM_EVENT_DATA event; + BTM_PEER_ENTRY *BTMPeerEntry = NULL, *BTMPeerEntryTmp = NULL; + PWNM_CTRL pWNMCtrl = NULL; + INT32 Ret; + BOOLEAN Cancelled; + PNET_DEV NetDev = NULL; + BOOLEAN isfound = FALSE; + + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s\n", __func__)); + + memcpy(&event, Elem->Msg, sizeof(BTM_EVENT_DATA)); + + pWNMCtrl = &pAd->ApCfg.MBSSID[event.ControlIndex].WNMCtrl; + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListForEachSafe(BTMPeerEntry, BTMPeerEntryTmp, &pWNMCtrl->BTMPeerList, BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, &event.PeerMACAddr[0])) { + isfound = TRUE; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + if (isfound == FALSE) { + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_WNM, DBG_LVL_OFF, + ("%s receive btm rsp;BTMPeerEntry is already deleted\n", __func__)); + return; + } + + NetDev = pAd->ApCfg.MBSSID[event.ControlIndex].wdev.if_dev; + /* Send BTM RSP timeout indication to daemon */ + SendBTMConfirmEvent(NetDev, + event.PeerMACAddr, + (PUCHAR)&(event.u.PEER_BTM_RSP_DATA.DialogToken), + 1, + RA_WEXT); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListDel(&BTMPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + RTMPReleaseTimer(&BTMPeerEntry->WaitPeerBTMRspTimer, &Cancelled); + os_free_mem(NULL, BTMPeerEntry); + +} + +#ifndef WAPP_SUPPORT/*CONFIG_HOTSPOT_R2 #ifdef WNM_NEW_API*/ +NDIS_STATUS wnm_handle_command(IN PRTMP_ADAPTER pAd, IN struct wnm_command *pCmd_data) +{ + + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UCHAR APIndex = pObj->ioctl_if; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; + int status = NDIS_STATUS_SUCCESS; + + switch (pCmd_data->command_id) { + case OID_802_11_WNM_CMD_ENABLE: + { + + if (pCmd_data->command_body[0] == 0) { + /*Disable All Features*/ + pWNMCtrl->WNMBTMEnable = 0; + APUpdateBeaconFrame(pAd, APIndex); + } else { + DBGPRINT(RT_DEBUG_OFF, ("%s OID_802_11_WNM_CMD_ENABLE, do nothing\n", + __func__)); + } + } + break; + case OID_802_11_WNM_CMD_CAP: + { + + if (pCmd_data->command_body[0] & BTM_ENABLE_OFFSET) + pWNMCtrl->WNMBTMEnable = 1; + else + pWNMCtrl->WNMBTMEnable = 0; + + APUpdateBeaconFrame(pAd, APIndex); + } + break; + case OID_802_11_WNM_CMD_SEND_BTM_REQ_IE: + { + status = send_btm_req_ie(pAd, + (p_btm_req_ie_data_t)pCmd_data->command_body, + pCmd_data->command_len); + } + break; + case OID_802_11_WNM_CMD_SET_BTM_REQ_PARAM: + { + status = send_btm_req_param(pAd, + (p_btm_reqinfo_t)pCmd_data->command_body, + pCmd_data->command_len); + } + break; + default: + DBGPRINT(RT_DEBUG_OFF, ("%s Invalid Command %d\n", + __func__, pCmd_data->command_id)); + status = NDIS_STATUS_INVALID_DATA; + break; + + } + return status; +} +#endif +void WNM_ReadParametersFromFile( + IN PRTMP_ADAPTER pAd, + RTMP_STRING *tmpbuf, + RTMP_STRING *buffer) +{ + INT loop; + RTMP_STRING *macptr; + + if (RTMPGetKeyParameter("WNMEnable", tmpbuf, 255, buffer, TRUE)) { + for (loop = 0, macptr = rstrtok(tmpbuf, ";"); + (macptr && loop < MAX_MBSSID_NUM(pAd)); + macptr = rstrtok(NULL, ";"), loop++) { + LONG Enable; + + kstrtol(macptr, 10, &Enable); + pAd->ApCfg.MBSSID[loop].WNMCtrl.WNMBTMEnable = + (Enable > 0) ? TRUE : FALSE; + DBGPRINT(RT_DEBUG_TRACE, ("%s::(bDot11vWNMEnable[%d]=%d\n", + __func__, loop, + pAd->ApCfg.MBSSID[loop].WNMCtrl.WNMBTMEnable)); + } + } else { + for (loop = 0; loop < MAX_MBSSID_NUM(pAd); loop++) + pAd->ApCfg.MBSSID[loop].WNMCtrl.WNMBTMEnable = FALSE; + } +} +#endif /* CONFIG_AP_SUPPORT */ + + + +enum BTM_STATE BTMPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PWNM_CTRL pWNMCtrl; + PBTM_PEER_ENTRY BTMPeerEntry; + PBTM_EVENT_DATA Event = (PBTM_EVENT_DATA)Elem->Msg; + INT32 Ret; + +#ifdef CONFIG_AP_SUPPORT + pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; +#endif /* CONFIG_AP_SUPPORT */ + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(BTMPeerEntry, &pWNMCtrl->BTMPeerList, BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + return BTMPeerEntry->CurrentState; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + + return BTM_UNKNOWN; +} + + +void PeerWNMAction(IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + UCHAR Action = Elem->Msg[LENGTH_802_11+1]; + + switch(Action) + { +#ifdef CONFIG_AP_SUPPORT + case BSS_TRANSITION_QUERY: + ReceiveBTMQuery(pAd, Elem); + break; + case BSS_TRANSITION_RSP: + ReceiveBTMRsp(pAd, Elem); + break; + case WNM_NOTIFICATION_RSP: + ReceiveWNMNotifyRsp(pAd, Elem); + break; + case WNM_NOTIFICATION_REQ: + ReceiveWNMNotifyReq(pAd, Elem); + break; +#endif /* CONFIG_AP_SUPPORT */ + + default: + DBGPRINT(RT_DEBUG_TRACE, ("Invalid action field = %d\n", Action)); + break; + } +} + +VOID WNMCtrlInit(IN PRTMP_ADAPTER pAd) +{ + PWNM_CTRL pWNMCtrl; + BOOLEAN WNMBTMEnable = TRUE; +#ifdef CONFIG_AP_SUPPORT + UCHAR APIndex; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; +#ifndef CONFIG_HOTSPOT_R2 + if (pWNMCtrl->WNMBTMEnable) + WNMBTMEnable = pWNMCtrl->WNMBTMEnable; +#endif + NdisZeroMemory(pWNMCtrl, sizeof(*pWNMCtrl)); + RTMP_SEM_EVENT_INIT(&pWNMCtrl->BTMPeerListLock, &pAd->RscSemMemList); + RTMP_SEM_EVENT_INIT(&pWNMCtrl->ProxyARPListLock, &pAd->RscSemMemList); + RTMP_SEM_EVENT_INIT(&pWNMCtrl->ProxyARPIPv6ListLock, &pAd->RscSemMemList); + DlListInit(&pWNMCtrl->BTMPeerList); + DlListInit(&pWNMCtrl->IPv4ProxyARPList); + DlListInit(&pWNMCtrl->IPv6ProxyARPList); +#ifdef CONFIG_HOTSPOT_R2 + RTMP_SEM_EVENT_INIT(&pWNMCtrl->WNMNotifyPeerListLock, &pAd->RscSemMemList); + DlListInit(&pWNMCtrl->WNMNotifyPeerList); +#endif + pWNMCtrl->WNMBTMEnable = WNMBTMEnable; + } +#endif +} + + +static VOID WNMCtrlRemoveAllIE(PWNM_CTRL pWNMCtrl) +{ + if (pWNMCtrl->TimeadvertisementIELen) + { + pWNMCtrl->TimeadvertisementIELen = 0; + os_free_mem(NULL, pWNMCtrl->TimeadvertisementIE); + } + + if (pWNMCtrl->TimezoneIELen) + { + pWNMCtrl->TimezoneIELen = 0; + os_free_mem(NULL, pWNMCtrl->TimezoneIE); + } +} + + +VOID WNMCtrlExit(IN PRTMP_ADAPTER pAd) +{ + PWNM_CTRL pWNMCtrl; + UINT32 Ret; + BTM_PEER_ENTRY *BTMPeerEntry, *BTMPeerEntryTmp; +#ifdef CONFIG_AP_SUPPORT + PROXY_ARP_IPV4_ENTRY *ProxyARPIPv4Entry, *ProxyARPIPv4EntryTmp; + PROXY_ARP_IPV6_ENTRY *ProxyARPIPv6Entry, *ProxyARPIPv6EntryTmp; + UCHAR APIndex; +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_HOTSPOT_R2 + WNM_NOTIFY_PEER_ENTRY *WNMNotifyPeerEntry, *WNMNotifyPeerEntryTmp; +#endif + +#ifdef CONFIG_AP_SUPPORT + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + + /* Remove all btm peer entry */ + DlListForEachSafe(BTMPeerEntry, BTMPeerEntryTmp, + &pWNMCtrl->BTMPeerList, BTM_PEER_ENTRY, List) + { + DlListDel(&BTMPeerEntry->List); + os_free_mem(NULL, BTMPeerEntry); + } + + DlListInit(&pWNMCtrl->BTMPeerList); + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + RTMP_SEM_EVENT_DESTORY(&pWNMCtrl->BTMPeerListLock); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + /* Remove all proxy arp entry */ + DlListForEachSafe(ProxyARPIPv4Entry, ProxyARPIPv4EntryTmp, + &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + DlListDel(&ProxyARPIPv4Entry->List); + os_free_mem(NULL, ProxyARPIPv4Entry); + } + DlListInit(&pWNMCtrl->IPv4ProxyARPList); + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPIPv6ListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEachSafe(ProxyARPIPv6Entry, ProxyARPIPv6EntryTmp, + &pWNMCtrl->IPv6ProxyARPList, PROXY_ARP_IPV6_ENTRY, List) + { + DlListDel(&ProxyARPIPv6Entry->List); + os_free_mem(NULL, ProxyARPIPv6Entry); + } + DlListInit(&pWNMCtrl->IPv6ProxyARPList); + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPIPv6ListLock); + + RTMP_SEM_EVENT_DESTORY(&pWNMCtrl->ProxyARPListLock); + RTMP_SEM_EVENT_DESTORY(&pWNMCtrl->ProxyARPIPv6ListLock); + +#ifdef CONFIG_HOTSPOT_R2 + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->WNMNotifyPeerListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + + /* Remove all wnm notify peer entry */ + DlListForEachSafe(WNMNotifyPeerEntry, WNMNotifyPeerEntryTmp, + &pWNMCtrl->WNMNotifyPeerList, WNM_NOTIFY_PEER_ENTRY, List) + { + DlListDel(&WNMNotifyPeerEntry->List); + os_free_mem(NULL, WNMNotifyPeerEntry); + } + + DlListInit(&pWNMCtrl->WNMNotifyPeerList); + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); + RTMP_SEM_EVENT_DESTORY(&pWNMCtrl->WNMNotifyPeerListLock); +#endif + /* Remove all WNM IEs */ + WNMCtrlRemoveAllIE(pWNMCtrl); + } +#endif /* CONFIG_AP_SUPPORT */ + +} + + +#ifdef CONFIG_AP_SUPPORT +VOID Clear_All_PROXY_TABLE(IN PRTMP_ADAPTER pAd) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + UCHAR APIndex = pObj->ioctl_if; + PWNM_CTRL pWNMCtrl; + UINT32 Ret; + PROXY_ARP_IPV4_ENTRY *ProxyARPIPv4Entry, *ProxyARPIPv4EntryTmp; + PROXY_ARP_IPV6_ENTRY *ProxyARPIPv6Entry, *ProxyARPIPv6EntryTmp; + + pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + /* Remove all proxy arp entry */ + DlListForEachSafe(ProxyARPIPv4Entry, ProxyARPIPv4EntryTmp, + &pWNMCtrl->IPv4ProxyARPList, PROXY_ARP_IPV4_ENTRY, List) + { + DlListDel(&ProxyARPIPv4Entry->List); + os_free_mem(NULL, ProxyARPIPv4Entry); + } + DlListInit(&pWNMCtrl->IPv4ProxyARPList); + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPListLock); + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->ProxyARPIPv6ListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEachSafe(ProxyARPIPv6Entry, ProxyARPIPv6EntryTmp, + &pWNMCtrl->IPv6ProxyARPList, PROXY_ARP_IPV6_ENTRY, List) + { + DlListDel(&ProxyARPIPv6Entry->List); + os_free_mem(NULL, ProxyARPIPv6Entry); + } + DlListInit(&pWNMCtrl->IPv6ProxyARPList); + RTMP_SEM_EVENT_UP(&pWNMCtrl->ProxyARPIPv6ListLock); +} +#endif + +VOID BTMStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + + StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, MAX_BTM_STATE, MAX_BTM_MSG, (STATE_MACHINE_FUNC)Drop, BTM_UNKNOWN, BTM_MACHINE_BASE); + +#ifdef CONFIG_AP_SUPPORT + StateMachineSetAction(S, WAIT_PEER_BTM_QUERY, PEER_BTM_QUERY, (STATE_MACHINE_FUNC)SendBTMQueryIndication); + StateMachineSetAction(S, WAIT_BTM_REQ, BTM_REQ, (STATE_MACHINE_FUNC)SendBTMReq); + StateMachineSetAction(S, WAIT_BTM_REQ, BTM_REQ_IE, (STATE_MACHINE_FUNC)SendBTMReqIE); + StateMachineSetAction(S, WAIT_BTM_REQ, BTM_REQ_PARAM, (STATE_MACHINE_FUNC)SendBTMReqParam); + StateMachineSetAction(S, WAIT_BTM_REQ, BTM_REQ_TIMEOUT, (STATE_MACHINE_FUNC)BTMReqTimeout); + StateMachineSetAction(S, WAIT_PEER_BTM_RSP, PEER_BTM_RSP, (STATE_MACHINE_FUNC)SendBTMConfirm); + StateMachineSetAction(S, WAIT_PEER_BTM_RSP, PEER_BTM_RSP_TIMEOUT, (STATE_MACHINE_FUNC)ReceiveBTMRspTimeout); +#endif /* CONFIG_AP_SUPPORT */ + +} + + +int send_btm_req_ie( + IN PRTMP_ADAPTER pAd, + IN p_btm_req_ie_data_t p_btm_req_data, + IN UINT32 btm_req_data_len) +{ + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + BSS_STRUCT *pMbss = NULL; + PWNM_CTRL pWNMCtrl = NULL; + PBTM_EVENT_DATA Event = NULL; + PBTM_PEER_ENTRY BTMPeerEntry = NULL; + PUCHAR Buf = NULL; + UINT32 Len = 0; + + static UINT8 j; + INT32 Ret; + UCHAR APIndex = pObj->ioctl_if; + BOOLEAN IsFound = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __func__)); + + pMbss = &pAd->ApCfg.MBSSID[APIndex]; + pWNMCtrl = &pMbss->WNMCtrl; + if (pWNMCtrl->WNMBTMEnable == FALSE) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s() btm off\n", __func__)); + return NDIS_STATUS_FAILURE; + } + + if (btm_req_data_len > 1000) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s BTM Req ie len(%d) is too long", __func__, + btm_req_data_len)); + return NDIS_STATUS_FAILURE; + } + + Len = sizeof(*Event) + btm_req_data_len; + os_alloc_mem(NULL, (UCHAR **)&Buf, Len); + if (!Buf) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s Not available memory for btm req msg\n", __func__)); + return NDIS_STATUS_FAILURE; + } + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListForEach(BTMPeerEntry, &pWNMCtrl->BTMPeerList, BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, p_btm_req_data->peer_mac_addr)) { + IsFound = TRUE; + break; + } + } + if (IsFound) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s() found BTMPeerEntry in BTMEntrylist that say receive btm query before\n", + __func__)); + BTMPeerEntry->CurrentState = WAIT_BTM_REQ; + BTMPeerEntry->WaitPeerBTMRspTime = p_btm_req_data->timeout * 1000; + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + + if (!IsFound) { + os_alloc_mem(NULL, (UCHAR **)&BTMPeerEntry, sizeof(*BTMPeerEntry)); + + if (!BTMPeerEntry) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s Not available memory for BTMPeerEntry\n", __func__)); + os_free_mem(NULL, Buf); + return NDIS_STATUS_FAILURE; + } + + NdisZeroMemory(BTMPeerEntry, sizeof(*BTMPeerEntry)); + + BTMPeerEntry->CurrentState = WAIT_BTM_REQ; + BTMPeerEntry->ControlIndex = APIndex; + NdisMoveMemory(BTMPeerEntry->PeerMACAddr, + p_btm_req_data->peer_mac_addr, MAC_ADDR_LEN); + if (p_btm_req_data->dialog_token) { + BTMPeerEntry->DialogToken = p_btm_req_data->dialog_token; + } else { + j++; + if (j == 0) + j = 1; + BTMPeerEntry->DialogToken = j; + p_btm_req_data->dialog_token = j; + } + BTMPeerEntry->Priv = pAd; + BTMPeerEntry->WaitPeerBTMRspTime = p_btm_req_data->timeout * 1000; + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListAddTail(&pWNMCtrl->BTMPeerList, &BTMPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + } + + NdisZeroMemory(Buf, Len); + Event = (BTM_EVENT_DATA *)Buf; + Event->ControlIndex = APIndex; + NdisMoveMemory(Event->PeerMACAddr, + p_btm_req_data->peer_mac_addr, MAC_ADDR_LEN); + Event->EventType = BTM_REQ_IE; + /* + * if we receive btm query and btm req is sent in query session + * then we think the btm req sent for btm query + */ + Event->u.BTM_REQ_DATA.DialogToken = p_btm_req_data->dialog_token; + Event->u.BTM_REQ_DATA.BTMReqLen = p_btm_req_data->btm_req_len; + + NdisMoveMemory(Event->u.BTM_REQ_DATA.BTMReq, + p_btm_req_data->btm_req, p_btm_req_data->btm_req_len); + + if (!MlmeEnqueue(pAd, BTM_STATE_MACHINE, BTM_REQ_IE, Len, Buf, 0)) { + DBGPRINT(RT_DEBUG_TRACE, + ("%s() mlme enqueue failed\n", __func__)); + if (!IsFound) { + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListDel(&BTMPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + os_free_mem(NULL, BTMPeerEntry); + } + } + os_free_mem(NULL, Buf); + + return NDIS_STATUS_SUCCESS; +} + + +/* +* this function is used to compose the btm request frame with +* parameters sent by the up-layer +* return value: error reason or success +*/ +int send_btm_req_param( + IN PRTMP_ADAPTER pAd, + IN p_btm_reqinfo_t p_btm_req_data, + IN UINT32 btm_req_data_len) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + BSS_STRUCT *pMbss = NULL; + PWNM_CTRL pWNMCtrl = NULL; + PBTM_EVENT_DATA Event = NULL; + PBTM_PEER_ENTRY BTMPeerEntry = NULL; + PUCHAR pBuf = NULL; + UINT32 Len = 0; + static UINT8 i; + INT32 Ret; + UCHAR ifIndex = pObj->ioctl_if; + BOOLEAN IsFound = FALSE; + + pMbss = &pAd->ApCfg.MBSSID[ifIndex]; + pWNMCtrl = &pMbss->WNMCtrl; + if (pWNMCtrl->WNMBTMEnable == FALSE) { + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_RRM, DBG_LVL_ERROR, + ("%s() btm off\n", __func__)); + return NDIS_STATUS_FAILURE; + } + + Len = sizeof(*p_btm_req_data) + + p_btm_req_data->num_candidates * sizeof(struct nr_info); + if (btm_req_data_len != Len) { + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_RRM, DBG_LVL_ERROR, + ("%s() length check failed btm_req_data_len=%d, Len=%d\n", + __func__, btm_req_data_len, Len)); + return NDIS_STATUS_FAILURE; + } + + if (p_btm_req_data->num_candidates > MAX_CANDIDATE_NUM) { + MTWF_LOG(DBG_CAT_PROTO, CATPROTO_RRM, DBG_LVL_ERROR, + ("%s the num of candidate(%d) excceed %d", __func__, + p_btm_req_data->num_candidates, MAX_CANDIDATE_NUM)); + return NDIS_STATUS_FAILURE; + } + + /*send btm req msg to mlme*/ + Len = sizeof(*Event) + btm_req_data_len; + os_alloc_mem(NULL, (UCHAR **)&pBuf, Len); + if (!pBuf) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s Not available memory for btm req msg\n", __func__)); + return NDIS_STATUS_RESOURCES; + } + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListForEach(BTMPeerEntry, &pWNMCtrl->BTMPeerList, BTM_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(BTMPeerEntry->PeerMACAddr, p_btm_req_data->sta_mac)) { + IsFound = TRUE; + break; + } + } + if (IsFound) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s() found BTMPeerEntry in BTMEntrylist that say receive btm query before\n", + __func__)); + BTMPeerEntry->CurrentState = WAIT_BTM_REQ; + BTMPeerEntry->WaitPeerBTMRspTime = p_btm_req_data->timeout * 1000; + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + + if (!IsFound) { + os_alloc_mem(NULL, (UCHAR **)&BTMPeerEntry, sizeof(*BTMPeerEntry)); + + if (!BTMPeerEntry) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s Not available memory for BTMPeerEntry\n", __func__)); + os_free_mem(NULL, pBuf); + return NDIS_STATUS_RESOURCES; + } + + NdisZeroMemory(BTMPeerEntry, sizeof(*BTMPeerEntry)); + BTMPeerEntry->CurrentState = WAIT_BTM_REQ; + BTMPeerEntry->ControlIndex = ifIndex; + NdisMoveMemory(BTMPeerEntry->PeerMACAddr, p_btm_req_data->sta_mac, + MAC_ADDR_LEN); + if (p_btm_req_data->dialogtoken) { + BTMPeerEntry->DialogToken = p_btm_req_data->dialogtoken; + } else { + i++; + if (i == 0) + i = 1; + BTMPeerEntry->DialogToken = i; + p_btm_req_data->dialogtoken = i; + } + BTMPeerEntry->Priv = pAd; + BTMPeerEntry->WaitPeerBTMRspTime = p_btm_req_data->timeout * 1000; + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListAddTail(&pWNMCtrl->BTMPeerList, &BTMPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + } + + NdisZeroMemory(pBuf, Len); + Event = (PBTM_EVENT_DATA)pBuf; + Event->ControlIndex = ifIndex; + NdisMoveMemory(Event->PeerMACAddr, + p_btm_req_data->sta_mac, MAC_ADDR_LEN); + Event->EventType = BTM_REQ_PARAM; + /* + *if we receive btm query and btm req is sent in query session + * then we think the btm req sent for btm query + */ + Event->u.BTM_REQ_DATA.DialogToken = p_btm_req_data->dialogtoken; + Event->u.BTM_REQ_DATA.BTMReqLen = btm_req_data_len; + NdisMoveMemory(Event->u.BTM_REQ_DATA.BTMReq, + (PUCHAR)p_btm_req_data, btm_req_data_len); + + if (!MlmeEnqueue(pAd, BTM_STATE_MACHINE, BTM_REQ_PARAM, Len, pBuf, 0)) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s() mlme enqueue failed", __func__)); + if (!IsFound) { + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->BTMPeerListLock, Ret); + DlListDel(&BTMPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->BTMPeerListLock); + os_free_mem(NULL, BTMPeerEntry); + } + } + + /*free the memory*/ + os_free_mem(NULL, pBuf); + + return NDIS_STATUS_SUCCESS; +} + +int check_btm_custom_params( + IN PRTMP_ADAPTER pAd, + IN p_btm_reqinfo_t p_btm_req_data, + IN UINT32 btm_req_data_len) +{ + PMAC_TABLE_ENTRY pEntry = NULL; + struct nr_info *pinfo = NULL; + INT32 Len = 0; + UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + pEntry = MacTableLookup(pAd, p_btm_req_data->sta_mac); + if (!pEntry || !((Ndis802_11AuthModeAutoSwitch >= + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.AuthMode) || + ((pEntry->WpaState == AS_PTKINITDONE) && + (pEntry->GTKState == REKEY_ESTABLISHED)))) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() STA(%02x:%02x:%02x:%02x:%02x:%02x) not associates with AP!\n", + __func__, PRINT_MAC(p_btm_req_data->sta_mac))); + goto error; + } + + + if (!pEntry->BssTransitionManmtSupport) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() STA(%02x:%02x:%02x:%02x:%02x:%02x) not support btm!\n", + __func__, PRINT_MAC(p_btm_req_data->sta_mac))); + goto error; + } + + if (p_btm_req_data->num_candidates == 0) { + DBGPRINT(RT_DEBUG_WARN, + ("%s() candidate count equals to 0; btm request is meaningless\n", + __func__)); + return NDIS_STATUS_SUCCESS; + } + + Len = p_btm_req_data->num_candidates * sizeof(struct nr_info); + pinfo = p_btm_req_data->candidates; + + /* + *need check the validity of each neighbor report candidates + *check bssid field of each neighbor report candidates + */ + while (Len > 0) { + if (MAC_ADDR_EQUAL(pinfo->bssid, ZERO_MAC_ADDR)) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() bssid check failed\n", __func__)); + goto error; + } + if (pinfo->channum == 0) { + DBGPRINT(RT_DEBUG_ERROR, + ("%s() channel check failed\n", __func__)); + goto error; + } + + Len -= sizeof(struct nr_info); + pinfo++; + } + + return NDIS_STATUS_SUCCESS; + +error: + return NDIS_STATUS_FAILURE; +} + +int compose_btm_req_ie( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR p_btm_req_ie, + OUT PUINT32 p_btm_req_ie_len, + IN p_btm_reqinfo_t p_btm_req_data, + IN UINT32 btm_req_data_len) +{ + struct nr_info *p_info = p_btm_req_data->candidates; + BOOLEAN nr_flag = FALSE; + ULONG bss_index = BSS_NOT_FOUND; + BSS_ENTRY *pBssEntry = NULL; + RRM_NEIGHBOR_REP_INFO NeighborRepInfo; + RRM_BSSID_INFO BssidInfo; + NDIS_STATUS NStatus = NDIS_STATUS_SUCCESS; + PUCHAR pos = p_btm_req_ie; + UINT32 TmpLen = 0, i = 0; + UINT16 disassoc_timer = 0; + + DBGPRINT(RT_DEBUG_TRACE, + ("%s\n", __func__)); + + /*set Request Mode*/ + if (p_btm_req_data->disassoc_timer) + p_btm_req_data->reqmode |= BTM_DISASSOC_OFFSET; + else + p_btm_req_data->reqmode &= ~BTM_DISASSOC_OFFSET; + + if (p_btm_req_data->duration) + p_btm_req_data->reqmode |= BTM_TERMINATION_OFFSET; + else + p_btm_req_data->reqmode &= ~BTM_TERMINATION_OFFSET; + + if (p_btm_req_data->url_len) + p_btm_req_data->reqmode |= BTM_URL_OFFSET; + else + p_btm_req_data->reqmode &= ~BTM_URL_OFFSET; + + p_btm_req_data->reqmode &= ~BTM_CANDIDATE_OFFSET; + + /*fill request mode into ie buffer*/ + memcpy(pos+TmpLen, &p_btm_req_data->reqmode, 1); + TmpLen += 1; + + disassoc_timer = cpu2le16(p_btm_req_data->disassoc_timer); + + /*fill disassociation timer into ie buffer*/ + memcpy(pos+TmpLen, &disassoc_timer, 2); + TmpLen += 2; + /*fill validity interval into ie buffer*/ + memcpy(pos+TmpLen, &p_btm_req_data->valint, 1); + TmpLen += 1; + /*fill bss termination duration into ie buffer; optional*/ + if (p_btm_req_data->reqmode & BTM_TERMINATION_OFFSET) { + WNM_InsertBSSTerminationSubIE(pAd, pos+TmpLen, &TmpLen, + p_btm_req_data->TSF, + p_btm_req_data->duration); + } + if (p_btm_req_data->reqmode & BTM_URL_OFFSET) { + memcpy(pos + TmpLen, &p_btm_req_data->url_len, 1); + TmpLen += 1; + memcpy(pos + TmpLen, &p_btm_req_data->url, + p_btm_req_data->url_len); + TmpLen += p_btm_req_data->url_len; + } + /*before add neighbor report ie*/ + *p_btm_req_ie_len = TmpLen; + /*after add neighbor report ie*/ + for (i = 0; i < p_btm_req_data->num_candidates; i++, p_info++) { + /* + *first, check if need get info from scan table to compose + *neighbor report response ie + */ + if (!(p_info->phytype && + p_info->regclass && + p_info->capinfo && + p_info->is_ht && + p_info->is_vht && + p_info->mobility)) { + nr_flag = TRUE; + } + /* + *if nr_flag equals to TRUE, it means that the up-layer need driver to + *help with the build of neighbor report ie. so need find info to complete + *the ie from scan table matched by bssid. if do not find info in + *scan table, just skip this candidate + */ + if (nr_flag) { + bss_index = + BssTableSearch(&pAd->ScanTab, p_info->bssid, p_info->channum); + if (bss_index == BSS_NOT_FOUND) { + DBGPRINT(RT_DEBUG_WARN, + ("%s() bss not found\n", __func__)); + continue; + } + pBssEntry = &pAd->ScanTab.BssEntry[bss_index]; + if (p_info->regclass == 0) + p_info->regclass = pBssEntry->RegulatoryClass; + if (p_info->capinfo == 0) + p_info->capinfo = pBssEntry->CapabilityInfo; + if (p_info->is_ht == 0) + p_info->is_ht = (pBssEntry->HtCapabilityLen != 0)?1:0; +#ifdef DOT11_VHT_AC + if (p_info->is_vht == 0) + p_info->is_vht = (pBssEntry->vht_cap_len != 0)?1:0; +#endif /* DOT11_VHT_AC */ + if (p_info->is_ht == 0) + p_info->is_ht = (pBssEntry->HtCapabilityLen != 0)?1:0; + if (p_info->mobility == 0) + p_info->mobility = (pBssEntry->bHasMDIE)?1:0; + + if (pBssEntry->Channel > 14) { + if (pBssEntry->HtCapabilityLen != 0) { +#ifdef DOT11_VHT_AC + if (pBssEntry->vht_cap_len != 0) + pBssEntry->CondensedPhyType = 9; + else +#endif /* DOT11_VHT_AC */ + pBssEntry->CondensedPhyType = 7; + } else { /* OFDM case */ + pBssEntry->CondensedPhyType = 4; + } + } else { + if (pBssEntry->HtCapabilityLen != 0) /* HT case */ + pBssEntry->CondensedPhyType = 7; + else if (ERP_IS_NON_ERP_PRESENT(pBssEntry->Erp)) /* ERP case */ + pBssEntry->CondensedPhyType = 6; + else if (pBssEntry->SupRateLen > 4) /* OFDM case (1,2,5.5,11 for CCK 4 Rates) */ + pBssEntry->CondensedPhyType = 4; + /* no CCK's definition in spec. */ + } + if (p_info->phytype == 0) + p_info->phytype = pBssEntry->CondensedPhyType; + } + + /*compose neighbor report ie buffer*/ + BssidInfo.word = 0; + BssidInfo.field.APReachAble = + (p_info->ap_reachability == 0)?3:p_info->ap_reachability; + BssidInfo.field.Security = p_info->security; + BssidInfo.field.KeyScope = p_info->key_scope; + BssidInfo.field.SepctrumMng = (p_info->capinfo & (1 << 8))?1:0; + BssidInfo.field.Qos = (p_info->capinfo & (1 << 9))?1:0; + BssidInfo.field.APSD = (p_info->capinfo & (1 << 11))?1:0; + BssidInfo.field.RRM = (p_info->capinfo & RRM_CAP_BIT)?1:0; + BssidInfo.field.DelayBlockAck = (p_info->capinfo & (1 << 14))?1:0; + BssidInfo.field.ImmediateBA = (p_info->capinfo & (1 << 15))?1:0; + BssidInfo.field.MobilityDomain = p_info->mobility; + BssidInfo.field.HT = p_info->is_ht; +#ifdef DOT11_VHT_AC + BssidInfo.field.VHT = p_info->is_vht; +#endif /* DOT11_VHT_AC */ + COPY_MAC_ADDR(NeighborRepInfo.Bssid, p_info->bssid); + NeighborRepInfo.BssidInfo = cpu2le32(BssidInfo.word); + NeighborRepInfo.RegulatoryClass = p_info->regclass; + NeighborRepInfo.ChNum = p_info->channum; + NeighborRepInfo.PhyType = p_info->phytype; + + RRM_InsertNeighborRepIE_New(pAd, (pos+TmpLen), (PULONG)&TmpLen, + sizeof(RRM_NEIGHBOR_REP_INFO), &NeighborRepInfo); + if (p_info->preference) + RRM_InsertPreferenceSubIE(pAd, (pos+TmpLen), &TmpLen, + p_info->preference); + } + if (TmpLen > *p_btm_req_ie_len) { + *p_btm_req_ie_len = TmpLen; + pos[0] |= BTM_CANDIDATE_OFFSET; + } + + return NStatus; +} + +VOID WNM_InsertBSSTerminationSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PUINT32 pFrameLen, + IN UINT64 TSF, + IN UINT16 Duration) +{ + ULONG TempLen = 0; + UINT8 Len = 10; + UINT8 SubId = WNM_BSS_TERMINATION_SUBIE; + +#ifdef RT_BIG_ENDIAN + TSF = cpu2le64(TSF); + Duration = cpu2le16(Duration); +#endif + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &SubId, + 1, &Len, + 8, &TSF, + 2, &Duration, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; +} + +VOID RRM_InsertPreferenceSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PUINT32 pFrameLen, + IN UINT8 preference) +{ + ULONG TempLen = 0; + UINT8 Len = 1; + UINT8 SubId = WNM_BSS_PERFERENCE_SUBIE; + + MakeOutgoingFrame(pFrameBuf, &TempLen, + 1, &SubId, + 1, &Len, + 1, &preference, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; +} + + +#ifdef CONFIG_AP_SUPPORT +VOID WNMSetPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem, + IN enum WNM_NOTIFY_STATE State) +{ + PWNM_CTRL pWNMCtrl; + PWNM_NOTIFY_PEER_ENTRY WNMNotifyPeerEntry; + PWNM_NOTIFY_EVENT_DATA Event = (PWNM_NOTIFY_EVENT_DATA)Elem->Msg; + INT32 Ret; + +#ifdef CONFIG_AP_SUPPORT + pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; +#endif /* CONFIG_AP_SUPPORT */ + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->WNMNotifyPeerListLock, Ret); + if (Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n", __func__, Ret)); + + DlListForEach(WNMNotifyPeerEntry, &pWNMCtrl->WNMNotifyPeerList, + WNM_NOTIFY_PEER_ENTRY, List) { + if (MAC_ADDR_EQUAL(WNMNotifyPeerEntry->PeerMACAddr, Event->PeerMACAddr)) { + WNMNotifyPeerEntry->CurrentState = State; + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); +} + +enum WNM_NOTIFY_STATE WNMNotifyPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem) +{ + PWNM_CTRL pWNMCtrl; + PWNM_NOTIFY_PEER_ENTRY WNMNotifyPeerEntry; + PWNM_NOTIFY_EVENT_DATA Event = (PWNM_NOTIFY_EVENT_DATA)Elem->Msg; + INT32 Ret; + +#ifdef CONFIG_AP_SUPPORT + pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; +#endif /* CONFIG_AP_SUPPORT */ + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->WNMNotifyPeerListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n", __func__, Ret)); + + DlListForEach(WNMNotifyPeerEntry, &pWNMCtrl->WNMNotifyPeerList, WNM_NOTIFY_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(WNMNotifyPeerEntry->PeerMACAddr, Event->PeerMACAddr)) { + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); + return WNMNotifyPeerEntry->CurrentState; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); + + return WNM_NOTIFY_UNKNOWN; +} + +VOID WaitPeerWNMNotifyRspTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + WNM_NOTIFY_PEER_ENTRY *WNMNotifyPeerEntry = (WNM_NOTIFY_PEER_ENTRY *)FunctionContext; + PRTMP_ADAPTER pAd; + PWNM_CTRL pWNMCtrl; + INT32 Ret; + BOOLEAN Cancelled; + + printk("%s\n", __FUNCTION__); + + if (!WNMNotifyPeerEntry) + return; + + pAd = WNMNotifyPeerEntry->Priv; + + RTMPReleaseTimer(&WNMNotifyPeerEntry->WaitPeerWNMNotifyRspTimer, &Cancelled); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS + | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + pWNMCtrl = &pAd->ApCfg.MBSSID[WNMNotifyPeerEntry->ControlIndex].WNMCtrl; + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->WNMNotifyPeerListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListDel(&WNMNotifyPeerEntry->List); + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); + os_free_mem(NULL, WNMNotifyPeerEntry); +} +BUILD_TIMER_FUNCTION(WaitPeerWNMNotifyRspTimeout); +VOID ReceiveWNMNotifyReq(IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + WNM_FRAME *WNMFrame = (WNM_FRAME *)Elem->Msg; + UINT pos = 0; + /* skip category, action, DialogToken, type */ + UINT OptionalElementLen = (UINT)Elem->MsgLen - sizeof(HEADER_802_11) - 4; + UINT ElementID = 0, ElementLen = 0; +#ifdef MBO_SUPPORT + struct wifi_dev *pWdev = wdev_search_by_address(pAd, WNMFrame->Hdr.Addr1); + + MBO_STA_CH_PREF_CDC_INFO MboStaInfoNPC; + MBO_STA_CH_PREF_CDC_INFO MboStaInfoCDC; + BOOLEAN bIndicateNPC = FALSE; +#endif /* MBO_SUPPORT */ + +#ifdef MBO_SUPPORT + NdisZeroMemory(&MboStaInfoNPC, sizeof(MBO_STA_CH_PREF_CDC_INFO)); + COPY_MAC_ADDR(MboStaInfoNPC.mac_addr, WNMFrame->Hdr.Addr2); + NdisZeroMemory(&MboStaInfoCDC, sizeof(MBO_STA_CH_PREF_CDC_INFO)); + COPY_MAC_ADDR(MboStaInfoCDC.mac_addr, WNMFrame->Hdr.Addr2); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("%s sta mac %02x:%02x:%02x:%02x:%02x:%02x\n", + __func__, PRINT_MAC(WNMFrame->Hdr.Addr2))); +#endif /* MBO_SUPPORT */ + + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("%s MsgLen %ld MBSS %02x:%02x:%02x:%02x:%02x:%02x\n", + __func__, Elem->MsgLen, PRINT_MAC(WNMFrame->Hdr.Addr1))); + + while ((pos+1) <= OptionalElementLen) { + ElementID = WNMFrame->u.WNM_NOTIFY_REQ.Variable[pos]; + ElementLen = WNMFrame->u.WNM_NOTIFY_REQ.Variable[pos+1]; + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s, %u pos %d OptionalElementLen %d ElementID %d ElementLen %d\n", + __func__, __LINE__, pos, OptionalElementLen, ElementID, ElementLen)); + + pos += 2; + + switch (ElementID) { + case IE_VENDOR_SPECIFIC: + if (NdisEqualMemory(wfa_oui, &WNMFrame->u.WNM_NOTIFY_REQ.Variable[pos], 3)) { + UINT8 ouiType = WNMFrame->u.WNM_NOTIFY_REQ.Variable[pos+3]; + + switch (ouiType) { +#ifdef MBO_SUPPORT +/* Non-Preferred Channel Report : NPC Report */ + case MBO_OUI_NON_PREFERRED_CHANNEL_REPORT: + MboParseStaNPCElement(pAd, pWdev, &WNMFrame->u.WNM_NOTIFY_REQ.Variable[pos+4] + , ElementLen, &MboStaInfoNPC, MBO_FRAME_TYPE_WNM_REQ); + bIndicateNPC = TRUE; + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s, %u npc_num %d mac_addr %02X:%02X:%02X:%02X:%02X:%02X bIndicateNPC %d\n" + , __func__, __LINE__, MboStaInfoNPC.npc_num, + PRINT_MAC(MboStaInfoNPC.mac_addr), bIndicateNPC)); + break; + case MBO_OUI_CELLULAR_DATA_CAPABILITY: + MboStaInfoCDC.cdc = WNMFrame->u.WNM_NOTIFY_REQ.Variable[pos+4]; + MboStaInfoCDC.npc_num = 0; + MboIndicateStaInfoToDaemon(pAd, &MboStaInfoCDC, MBO_MSG_CDC_UPDATE); + break; +#endif/* MBO_SUPPORT */ + default: + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("\033[1;32m %s, %u vendor specific, but unknown OUI type, please check \033[0m\n", + __func__, __LINE__)); + } + } else { + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s, %u vendor specific, but unknown OUI, please check\n", + __func__, __LINE__)); + } + break; + default: + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s, UNKNOWN ElementID 0x%X , break parsing\n", __func__, ElementID)); + } + + pos += ElementLen; /* forward to next element */ + } + + +#ifdef MBO_SUPPORT + if (bIndicateNPC) + MboIndicateStaInfoToDaemon(pAd, &MboStaInfoNPC, MBO_MSG_STA_PREF_UPDATE); +#endif /* MBO_SUPPORT */ + + /*return;*/ +} +VOID ReceiveWNMNotifyRsp(IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + WNM_NOTIFY_EVENT_DATA *Event; + WNM_FRAME *WNMFrame = (WNM_FRAME *)Elem->Msg; + WNM_NOTIFY_PEER_ENTRY *WNMNotifyPeerEntry; + PWNM_CTRL pWNMCtrl = NULL; + UCHAR APIndex, *Buf; + UINT16 VarLen = 0; + UINT32 Len = 0; + INT32 Ret; + BOOLEAN IsFound = FALSE, Cancelled; + + printk("%s\n", __FUNCTION__); + + for (APIndex = 0; APIndex < MAX_MBSSID_NUM(pAd); APIndex++) + { + if (MAC_ADDR_EQUAL(WNMFrame->Hdr.Addr3, pAd->ApCfg.MBSSID[APIndex].wdev.bssid)) + { + pWNMCtrl = &pAd->ApCfg.MBSSID[APIndex].WNMCtrl; + break; + } + } + + if (!pWNMCtrl) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Can not find Peer Control\n", __FUNCTION__)); + return; + } + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->WNMNotifyPeerListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(WNMNotifyPeerEntry, &pWNMCtrl->WNMNotifyPeerList, WNM_NOTIFY_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(WNMNotifyPeerEntry->PeerMACAddr, WNMFrame->Hdr.Addr2)) + IsFound = TRUE; + + break; + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); + + if (!IsFound) { + DBGPRINT(RT_DEBUG_ERROR, ("Not found peer entry in list\n")); + { + unsigned char *tmp1 = (unsigned char *)WNMFrame->Hdr.Addr2; + unsigned char *tmp2; + printk("client mac:%02x:%02x:%02x:%02x:%02x:%02x\n",*(tmp1),*(tmp1+1),*(tmp1+2),*(tmp1+3),*(tmp1+4),*(tmp1+5)); + DlListForEach(WNMNotifyPeerEntry, &pWNMCtrl->WNMNotifyPeerList, WNM_NOTIFY_PEER_ENTRY, List) + { + tmp2 = (unsigned char *)WNMNotifyPeerEntry->PeerMACAddr; + printk("list=> %02x:%02x:%02x:%02x:%02x:%02x\n",*(tmp2),*(tmp2+1),*(tmp2+2),*(tmp2+3),*(tmp2+4),*(tmp2+5)); + } + printk("\n"); + } + return; + } + + /* Cancel Wait peer wnm response frame */ + RTMPCancelTimer(&WNMNotifyPeerEntry->WaitPeerWNMNotifyRspTimer, &Cancelled); + RTMPReleaseTimer(&WNMNotifyPeerEntry->WaitPeerWNMNotifyRspTimer, &Cancelled); + + VarLen = 1; + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*Event) + VarLen); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*Event) + VarLen); + + Event = (WNM_NOTIFY_EVENT_DATA *)Buf; + + Event->ControlIndex = APIndex; + Len += 1; + + NdisMoveMemory(Event->PeerMACAddr, WNMFrame->Hdr.Addr2, MAC_ADDR_LEN); + Len += MAC_ADDR_LEN; + + Event->EventType = WNM_NOTIFY_RSP; + Len += 2; + + Event->u.WNM_NOTIFY_RSP_DATA.DialogToken = WNMFrame->u.WNM_NOTIFY_RSP.DialogToken; + Len += 1; + + Event->u.WNM_NOTIFY_RSP_DATA.WNMNotifyRspLen = 1;// = WNMFrame->u.WNM_NOTIFY_RSP.DialogToken; + Len += 2; + + //NdisMoveMemory(Event->u.WNM_NOTIFY_RSP_DATA.WNMNotifyRsp, WNMFrame->u.WNM_NOTIFY_RSP.Variable, + // VarLen); + Event->u.WNM_NOTIFY_RSP_DATA.WNMNotifyRsp[0] = WNMFrame->u.WNM_NOTIFY_RSP.RespStatus; + Len += VarLen; + + MlmeEnqueue(pAd, WNM_NOTIFY_STATE_MACHINE, WNM_NOTIFY_RSP, Len, Buf,0); + + os_free_mem(NULL, Buf); + + return; +} + +static VOID SendWNMNotifyReq( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + WNM_NOTIFY_EVENT_DATA *Event = (WNM_NOTIFY_EVENT_DATA *)Elem->Msg; + UCHAR *Buf; + WNM_FRAME *WNMFrame; + WNM_NOTIFY_PEER_ENTRY *WNMNotifyPeerEntry = NULL; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; + UINT32 FrameLen = 0, VarLen = Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen; + INT32 Ret; + + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->WNMNotifyPeerListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEach(WNMNotifyPeerEntry, &pWNMCtrl->WNMNotifyPeerList, + WNM_NOTIFY_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(WNMNotifyPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); + + os_alloc_mem(NULL, (UCHAR **)&Buf, sizeof(*WNMFrame) + VarLen + 7); + + if (!Buf) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s Not available memory\n", __FUNCTION__)); + return; + } + + NdisZeroMemory(Buf, sizeof(*WNMFrame) + VarLen); + + WNMFrame = (WNM_FRAME *)Buf; + + ActHeaderInit(pAd, &WNMFrame->Hdr, Event->PeerMACAddr, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid, + pAd->ApCfg.MBSSID[Event->ControlIndex].wdev.bssid); + + FrameLen += sizeof(HEADER_802_11); + + WNMFrame->Category = CATEGORY_WNM; + FrameLen += 1; + + WNMFrame->u.WNM_NOTIFY_REQ.Action = WNM_NOTIFICATION_REQ; + FrameLen += 1; + + WNMFrame->u.WNM_NOTIFY_REQ.DialogToken = Event->u.WNM_NOTIFY_REQ_DATA.DialogToken; + FrameLen += 1; + + WNMFrame->u.WNM_NOTIFY_REQ.Type = 1; + FrameLen += 1; + + if (Event->EventType == 0) //remediation + { + printk("remediation\n"); + WNMFrame->u.WNM_NOTIFY_REQ.Variable[0] = 0xdd; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[1] = 5+Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[2] = 0x50; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[3] = 0x6f; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[4] = 0x9a; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[5] = 0x00; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[6] = Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen; + FrameLen += 7; + NdisMoveMemory(&WNMFrame->u.WNM_NOTIFY_REQ.Variable[7], Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReq, + Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen); + FrameLen += Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen; + } + else if (Event->EventType == 2) //remediation+service method + { + printk("remediation with method\n"); + WNMFrame->u.WNM_NOTIFY_REQ.Variable[0] = 0xdd; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[1] = 5+Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[2] = 0x50; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[3] = 0x6f; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[4] = 0x9a; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[5] = 0x00; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[6] = Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen-1; + FrameLen += 7; + NdisMoveMemory(&WNMFrame->u.WNM_NOTIFY_REQ.Variable[7], Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReq, + Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen); + FrameLen += Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen; + } + else if (Event->EventType == 1) //deauth imminent notice + { + MAC_TABLE_ENTRY *pEntry; + + printk("deauth imminent: %d\n", Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen); + WNMFrame->u.WNM_NOTIFY_REQ.Variable[0] = 0xdd; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[1] = 5+Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[2] = 0x50; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[3] = 0x6f; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[4] = 0x9a; + WNMFrame->u.WNM_NOTIFY_REQ.Variable[5] = 0x01; + NdisMoveMemory(&WNMFrame->u.WNM_NOTIFY_REQ.Variable[6], Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReq, + 3); + WNMFrame->u.WNM_NOTIFY_REQ.Variable[9] = Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen-3; + FrameLen += 10; + if (WNMFrame->u.WNM_NOTIFY_REQ.Variable[9] != 0) + { + NdisMoveMemory(&WNMFrame->u.WNM_NOTIFY_REQ.Variable[10], &Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReq[3], + Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen-3); + FrameLen += (Event->u.WNM_NOTIFY_REQ_DATA.WNMNotifyReqLen-3); + } + + if ((pEntry = MacTableLookup(pAd, Event->PeerMACAddr)) != NULL) + { + pEntry->BTMDisassocCount = 40; //20; + } + } + else + { + printk("no match event type:%d\n", Event->EventType); + os_free_mem(NULL, Buf); + } + WNMSetPeerCurrentState(pAd, Elem, WAIT_WNM_NOTIFY_RSP); + + MiniportMMRequest(pAd, 0, Buf, FrameLen); + + RTMPSetTimer(&WNMNotifyPeerEntry->WaitPeerWNMNotifyRspTimer, WaitPeerWNMNotifyRspTimeoutVale); + + os_free_mem(NULL, Buf); +} + +VOID SendWNMNotifyConfirm( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + PWNM_NOTIFY_PEER_ENTRY WNMNotifyPeerEntry, WNMNotifyPeerEntryTmp; + WNM_NOTIFY_EVENT_DATA *Event = (WNM_NOTIFY_EVENT_DATA *)Elem->Msg; + PWNM_CTRL pWNMCtrl = &pAd->ApCfg.MBSSID[Event->ControlIndex].WNMCtrl; + INT32 Ret; + + printk("%s\n", __FUNCTION__); + + printk("Receive WNM Notify Response Status:%d\n", Event->u.WNM_NOTIFY_RSP_DATA.WNMNotifyRsp[0]); + /* Delete BTM peer entry */ + RTMP_SEM_EVENT_WAIT(&pWNMCtrl->WNMNotifyPeerListLock, Ret); + if(Ret != 0) + DBGPRINT(RT_DEBUG_OFF, ("%s:(%d) RTMP_SEM_EVENT_WAIT failed!\n",__FUNCTION__,Ret)); + DlListForEachSafe(WNMNotifyPeerEntry, WNMNotifyPeerEntryTmp, &pWNMCtrl->WNMNotifyPeerList, WNM_NOTIFY_PEER_ENTRY, List) + { + if (MAC_ADDR_EQUAL(WNMNotifyPeerEntry->PeerMACAddr, Event->PeerMACAddr)) + { + + DlListDel(&WNMNotifyPeerEntry->List); + os_free_mem(NULL, WNMNotifyPeerEntry); + break; + } + } + RTMP_SEM_EVENT_UP(&pWNMCtrl->WNMNotifyPeerListLock); + +} +#endif /* CONFIG_AP_SUPPORT */ + +VOID WNMNotifyStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]) +{ + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + + StateMachineInit(S, (STATE_MACHINE_FUNC*)Trans, MAX_WNM_NOTIFY_STATE, MAX_WNM_NOTIFY_MSG, (STATE_MACHINE_FUNC)Drop, WNM_NOTIFY_UNKNOWN, WNM_NOTIFY_MACHINE_BASE); + +#ifdef CONFIG_AP_SUPPORT + StateMachineSetAction(S, WAIT_WNM_NOTIFY_REQ, WNM_NOTIFY_REQ, (STATE_MACHINE_FUNC)SendWNMNotifyReq); + StateMachineSetAction(S, WAIT_WNM_NOTIFY_RSP, WNM_NOTIFY_RSP, (STATE_MACHINE_FUNC)SendWNMNotifyConfirm); +#endif /* CONFIG_AP_SUPPORT */ + +} diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wnm_tlv.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wnm_tlv.c new file mode 100644 index 000000000..60ebe7d80 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wnm_tlv.c @@ -0,0 +1,63 @@ +#include "rt_config.h" + + +VOID InsertDMSReqElement( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN WNM_DMS_REQUEST_ELEMENT DMSReqElement) +{ + ULONG TempLen; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 3, &DMSReqElement, + END_OF_ARGS); + +/* *pFrameLen = *pFrameLen + TempLen; */ + + return; +} + + + +VOID WNM_InsertDMS( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Len, + IN UCHAR DMSID, + IN WNM_TCLAS wmn_tclas, + IN ULONG IpAddr) +{ + ULONG TempLen; + UINT8 DMSIDId = DMSID; + WNM_TCLAS tclas; + UCHAR TCLASElementID = WNM_CATEGORY; + UCHAR TCLASLength = WNM_TCLAS_TYPE_IP_V4_LEN; + + tclas.UserPriority = 0; + tclas.ClassifierType = 1; + tclas.ClassifierMask = 255; + tclas.Clasifier.IPv4.Version = 0; + tclas.Clasifier.IPv4.IpSource = 0; + tclas.Clasifier.IPv4.PortSource = 0; + tclas.Clasifier.IPv4.PortDest = 0; + tclas.Clasifier.IPv4.DSCP = 0; + tclas.Clasifier.IPv4.Protocol = 4; + + tclas.Clasifier.IPv4.IpDest = IpAddr; + + MakeOutgoingFrame( pFrameBuf, &TempLen, + 1, &DMSIDId, + 1, &Len, + 1, &TCLASElementID, + 1, &TCLASLength, + WNM_TCLAS_TYPE_IP_V4_LEN, &tclas, + END_OF_ARGS); + + *pFrameLen = *pFrameLen + TempLen; + + return; +} + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wsc.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wsc.c new file mode 100644 index 000000000..3281fb301 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wsc.c @@ -0,0 +1,9890 @@ +/* + *************************************************************************** + * 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[]; + + +#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 RTMP_STRING *arg); + +INT WscSetEncrypType( + IN PRTMP_ADAPTER pAd, + IN UCHAR CurOpMode, + IN UCHAR apidx, + IN RTMP_STRING *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); + + +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]; + + + /* 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; + + + + 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! */ + + uuid_t.clockSeqLow = clkSeq & 0xFF; + uuid_t.clockSeqHi_Var = (clkSeq & 0x3F00) >> 8; + uuid_t.clockSeqHi_Var |= 0x80; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + /* copy the Mac address as the value of node */ + NdisMoveMemory(&uuid_t.node[0], &pAd->ApCfg.MBSSID[apIdx].wdev.bssid[0], sizeof(uuid_t.node)); + } +#endif /* CONFIG_AP_SUPPORT */ + + + /* 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((RTMP_STRING *)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); + WSC_TIMER_INIT(pAd, pWScControl, &pWScControl->WscSetupLockTimer, pWScControl->WscSetupLockTimerRunning, WscSetupLockTimeout); + } + +#ifdef APCLI_SUPPORT + for (apidx = 0; apidx < MAX_APCLI_NUM; apidx++) + { + pWScControl = &pAd->ApCfg.ApCliTab[apidx].WscControl; + pWScControl->EntryIfIdx= (MIN_NET_DEVICE_FOR_APCLI | apidx); + WscInitCommonTimers(pAd, pWScControl); + WscInitClientTimers(pAd, pWScControl); + } +#endif /* APCLI_SUPPORT */ + } + +#endif /* CONFIG_AP_SUPPORT */ + +} + +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_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 */ + (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 != 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); + 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; + struct wifi_dev *wdev = NULL; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscEAPOLStartAction\n")); + + pHeader = (PHEADER_802_11)Elem->Msg; + pEntry = MacTableLookup(pAd, pHeader->Addr2); + + wdev = pEntry->wdev; + + /* 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_AP_SUPPORT + if (CurOpMode == AP_MODE) + pWpsCtrl = &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].WscControl; +#endif /* CONFIG_AP_SUPPORT */ + + if (pWpsCtrl == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pWpsCtrl == NULL!\n", __FUNCTION__)); + return; + } + + 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 */ + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPOLStartAction\n")); + return; + } + } + + + + DBGPRINT(RT_DEBUG_TRACE, ("WscState = %d\n", pWpsCtrl->WscState)); + if ((pEntry->Receive_EapolStart_EapRspId == 0) || + (pWpsCtrl->WscState <= WSC_STATE_WAIT_REQ_ID)) + { + /* Receive the first EapolStart packet of this wps station. */ + pEntry->Receive_EapolStart_EapRspId |= WSC_ENTRY_GET_EAPOL_START; + + DBGPRINT(RT_DEBUG_TRACE, ("WscEAPOLStartAction - receive EAPOL-Start from %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pEntry->Addr))); + + /* EapolStart packet is sent by station means this station wants to do wps process with AP. */ + pWpsCtrl->EapMsgRunning = TRUE; + /* Update EntryAddr again */ + NdisMoveMemory(pWpsCtrl->EntryAddr, pEntry->Addr, MAC_ADDR_LEN); + + if (pEntry->bWscCapable == FALSE) + pEntry->bWscCapable = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("WscEAPOLStartAction(ra%d) - send EAP-Req(Id) to %02x:%02x:%02x:%02x:%02x:%02x\n", + pEntry->func_tb_idx, PRINT_MAC(pEntry->Addr))); + +#ifdef MT_MAC + if (pEntry->bEapReqIdRetryTimerRunning == FALSE) + { + RTMPSetTimer(&pEntry->EapReqIdRetryTimer, WSC_EAP_EAP_FAIL_TIME_OUT); + pEntry->bEapReqIdRetryTimerRunning = TRUE; + } +#endif /* MT_MAC */ + + /* 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_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (!bUPnPMsg) + { + if (pEntry) + { + if (IS_ENTRY_CLIENT(pEntry) && pEntry->func_tb_idx >= pAdapter->ApCfg.BssidNum) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: Unknow apidex(=%d).\n", pEntry->func_tb_idx)); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPAction\n")); + return; + } + else + { + apidx = pEntry->func_tb_idx; + DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: apidex=%d.\n", pEntry->func_tb_idx)); + } + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: pEntry is NULL.\n")); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPAction\n")); + return; + } +#ifdef APCLI_SUPPORT + /* for ap-client packets */ + if (pEntry && IS_ENTRY_APCLI(pEntry)) + pWscControl = &pAdapter->ApCfg.ApCliTab[apidx].WscControl; + else +#endif /* APCLI_SUPPORT */ + pWscControl = &pAdapter->ApCfg.MBSSID[apidx].WscControl; + } + else + { + int i; + for (i = 0 ; i < MAX_MBSSID_NUM(pAdapter); i++) + { + if(NdisEqualMemory(pAdapter->ApCfg.MBSSID[i].wdev.bssid, MacAddr, MAC_ADDR_LEN)) + { + apidx = i; + break; + } + } + pWscControl = &pAdapter->ApCfg.MBSSID[apidx].WscControl; + pWscUPnPNodeInfo = &pAdapter->ApCfg.MBSSID[apidx].WscControl.WscUPnPNodeInfo; + pWscUPnPNodeInfo->bUPnPMsgTimerPending = TRUE; + } + } +#endif /* CONFIG_AP_SUPPORT */ + + + if (pWscControl == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pWscControl == NULL!\n", __FUNCTION__)); + return; + } + + if (pEntry && IS_ENTRY_CLIENT(pEntry)) + { + if ((MsgType == WSC_MSG_EAP_REG_RSP_ID) || (MsgType == WSC_MSG_EAP_ENR_RSP_ID)) + { + if (((pEntry->Receive_EapolStart_EapRspId & WSC_ENTRY_GET_EAP_RSP_ID) == WSC_ENTRY_GET_EAP_RSP_ID) + && (pWscControl->WscState > WSC_STATE_WAIT_M1)) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: Already receive EAP_RSP(Identitry) from this STA, ignore it.\n")); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPAction\n")); + return; + } + else + pEntry->Receive_EapolStart_EapRspId |= WSC_ENTRY_GET_EAP_RSP_ID; + } + } + + pWscControl->EapolTimerPending = TRUE; + +#ifdef WSC_V2_SUPPORT + if (MsgType == WSC_MSG_EAP_FRAG_ACK) + { + WscSendEapFragData(pAdapter, pWscControl, pEntry); + return; + } + else +#endif /* WSC_V2_SUPPORT */ + if (MsgType == WSC_MSG_EAP_REG_RSP_ID) + { + /* Receive EAP-Response/Id from external registrar, so the role of AP is enrollee. */ + if (((pWscControl->WscConfMode & WSC_ENROLLEE) != 0) || + (((pWscControl->WscConfMode & WSC_PROXY) != 0) && bUPnPMsg)) + { + pWscControl->WscActionMode= WSC_ENROLLEE; + pWscControl->WscUseUPnP = bUPnPMsg ? 1 : 0; + MsgType = WSC_MSG_EAP_RSP_ID; + WscEapEnrolleeAction(pAdapter, Elem, WSC_MSG_EAP_RSP_ID, pEntry, pWscControl); + } + } + else if (MsgType == WSC_MSG_EAP_ENR_RSP_ID) + { + /* Receive EAP-Response/Id from wps enrollee station, so the role of AP is Registrar or Proxy. */ + DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: Rx Identity\n")); +#ifdef MT_MAC + /* + Sometimes TXS would delay and received after M1. + Cancel EapReqIdRetryTimer here if timer is still running. + */ + + if (pEntry && pEntry->bEapReqIdRetryTimerRunning) + { + BOOLEAN bCancelled; + RTMPCancelTimer(&pEntry->EapReqIdRetryTimer, &bCancelled); + pEntry->bEapReqIdRetryTimerRunning = FALSE; + } +#endif /* MT_MAC */ + pWscControl->WscActionMode = WSC_REGISTRAR; + if (bUPnPMsg) + { + /* Receive enrollee identity from UPnP */ + } + else + { +#ifdef CONFIG_AP_SUPPORT + /* Receive enrollee identity from EAP */ + if ((pWscControl->WscMode == WSC_PBC_MODE) + ) + { + /* + Some WPS PBC Station select AP from UI directly; doesn't do PBC scan. + Need to check DPID from STA again here. + */ + WscPBC_DPID_FromSTA(pAdapter, pWscControl->EntryAddr); + WscPBCSessionOverlapCheck(pAdapter); + if ((pAdapter->CommonCfg.WscStaPbcProbeInfo.WscPBCStaProbeCount == 1) && + !NdisEqualMemory(pAdapter->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[0], &ZERO_MAC_ADDR[0], MAC_ADDR_LEN) && + (NdisEqualMemory(pAdapter->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[0], &pWscControl->EntryAddr[0], 6) == FALSE)) + { + pAdapter->CommonCfg.WscPBCOverlap = TRUE; + } + if (pAdapter->CommonCfg.WscPBCOverlap) + { + hex_dump("EntryAddr", pWscControl->EntryAddr, 6); + hex_dump("StaMacAddr0", pAdapter->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[0], 6); + hex_dump("StaMacAddr1", pAdapter->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[1], 6); + hex_dump("StaMacAddr2", pAdapter->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[2], 6); + hex_dump("StaMacAddr3", pAdapter->CommonCfg.WscStaPbcProbeInfo.StaMacAddr[3], 6); + } + } + + if ((pWscControl->WscMode == WSC_PBC_MODE) && + (pAdapter->CommonCfg.WscPBCOverlap == TRUE)) + { + /* PBC session overlap */ + pWscControl->WscStatus = STATUS_WSC_PBC_SESSION_OVERLAP; + RTMPSendWirelessEvent(pAdapter, IW_WSC_PBC_SESSION_OVERLAP, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + DBGPRINT(RT_DEBUG_TRACE, ("WscEAPAction: PBC Session Overlap!\n")); + } + 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->func_tb_idx].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 WH_EZ_SETUP + if(IS_EZ_SETUP_ENABLED(pEntry->wdev)){ + pEntry->wdev->ez_driver_params.ez_wps_reconnect = TRUE; + NdisGetSystemUpTime(&pEntry->wdev->ez_driver_params.ez_wps_reconnect_timestamp); + COPY_MAC_ADDR(pEntry->wdev->ez_driver_params.ez_wps_bssid,pWscControl->WscBssid); + } +#endif + + /* Bring apcli interface down first */ + if(pEntry && IS_ENTRY_APCLI(pEntry) && pAdapter->ApCfg.ApCliTab[BSS0].Enable == TRUE ) + { + pAdapter->ApCfg.ApCliTab[pEntry->func_tb_idx].Enable = FALSE; + ApCliIfDown(pAdapter); + + pAdapter->ApCfg.ApCliTab[pEntry->func_tb_idx].Enable = TRUE; + } + } +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + } + else if (pWscControl->WscState == WSC_STATE_RX_M2D) + { + /* Wait M2; */ + } + 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); + + + pWscControl->WscConfMode = WSC_DISABLE; + /* Change the state to next one */ + pWscControl->WscState = WSC_STATE_OFF; + + } + } + else if (MsgType == WSC_MSG_M1) + { + /* + 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 + { + if (pEntry) + WscEapRegistrarAction(pAdapter, Elem, MsgType, pEntry, pWscControl); + else + DBGPRINT(RT_DEBUG_TRACE, ("%s(): pEntry is NULL!\n", __FUNCTION__)); + } + } +#ifdef CONFIG_AP_SUPPORT + if (((pWscControl->WscConfMode & WSC_PROXY) != 0) && (!bUPnPMsg) && (CurOpMode == AP_MODE)) + { + if ((pWscControl->bWscTrigger + ) + && (pWscControl->WscState >= WSC_STATE_WAIT_M3)) + ; + else + { + pWscControl->WscActionMode = WSC_PROXY; + WscEapApProxyAction(pAdapter, Elem, MsgType, pEntry, pWscControl); + } + } + else if ((!pWscControl->bWscTrigger) && ((pWscControl->WscConfMode & WSC_PROXY) == 0) && (pAdapter->OpMode == OPMODE_AP)) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscTrigger is FALSE, ignore EAP M1.\n")); + goto out; + } +#endif /* CONFIG_AP_SUPPORT */ + } + else if (MsgType == WSC_MSG_M3 || + MsgType == WSC_MSG_M5 || + MsgType == WSC_MSG_M7 || + MsgType == WSC_MSG_WSC_DONE) + { + BOOLEAN bNonceMatch = WscCheckNonce(pAdapter, Elem, TRUE, pWscControl); + if (((pWscControl->WscConfMode & WSC_REGISTRAR) != 0) && + (pWscControl->bWscTrigger + ) && + bNonceMatch) + { + /* If Message is from EAP, but UPnP Registrar is in progress now, ignore EAP Messages */ + if (!bUPnPMsg && pWscControl->WscUPnPNodeInfo.bUPnPInProgress) + { + DBGPRINT(RT_DEBUG_TRACE, ("UPnP Registrar is working now, ignore EAP Messages.\n")); + goto out; + } + else + { + pWscControl->WscActionMode = WSC_REGISTRAR; + WscEapRegistrarAction(pAdapter, Elem, MsgType, pEntry, pWscControl); + } + } +#ifdef CONFIG_AP_SUPPORT + else if (((pWscControl->WscConfMode & WSC_PROXY) != 0) && (!bUPnPMsg) && (CurOpMode == AP_MODE)) + { + pWscControl->WscActionMode = WSC_PROXY; + WscEapApProxyAction(pAdapter, Elem, MsgType, pEntry, pWscControl); + } +#endif /* CONFIG_AP_SUPPORT */ + } + else if (MsgType == WSC_MSG_M2 || + MsgType == WSC_MSG_M2D || + MsgType == WSC_MSG_M4 || + MsgType == WSC_MSG_M6 || + MsgType == WSC_MSG_M8) + { + BOOLEAN bNonceMatch = WscCheckNonce(pAdapter, Elem, FALSE, pWscControl); + BOOLEAN bGoWPS = FALSE; + + if ((CurOpMode == AP_MODE) || + ((CurOpMode == STA_MODE) && + (pWscControl->bWscTrigger + ))) + 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 */ + + + 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) + { + 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; + pWscControl->WscStatus = STATUS_WSC_CONFIGURED; + bReSetWscIE = TRUE; + } + { + int dataLen; + UCHAR *pWscData; + BOOLEAN bUPnPStatus = FALSE; + + os_alloc_mem(NULL, (UCHAR **)&pWscData, WSC_MAX_DATA_LEN); + if (pWscData != NULL) + { + memset(pWscData, 0, WSC_MAX_DATA_LEN); + dataLen = BuildMessageNACK(pAdapter, pWscControl, pWscData); + bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), WSC_OPCODE_UPNP_DATA, + WSC_UPNP_DATA_SUB_NORMAL, pWscData, dataLen, + Elem->TimeStamp.u.LowPart, Elem->TimeStamp.u.HighPart, + &pAdapter->CurrentAddress[0], CurOpMode); + os_free_mem(NULL, pWscData); + if (bUPnPStatus == FALSE) + WscUPnPErrHandle(pAdapter, pWscControl, Elem->TimeStamp.u.LowPart); + } + + if (pWscUPnPNodeInfo->bUPnPMsgTimerRunning == TRUE) + { + RTMPCancelTimer(&pWscUPnPNodeInfo->UPnPMsgTimer, &Cancelled); + pWscUPnPNodeInfo->bUPnPMsgTimerRunning = FALSE; + } + pWscUPnPNodeInfo->bUPnPInProgress = FALSE; + + RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_FAIL, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + } + + } + + if (!bUPnPMsg && + (WscCheckNonce(pAdapter, Elem, FALSE, pWscControl) || WscCheckNonce(pAdapter, Elem, TRUE, pWscControl))) + { + USHORT config_error = 0; + DBGPRINT(RT_DEBUG_TRACE, ("Receive NACK from WPS client.\n")); + WscGetConfigErrFromNack(pAdapter, Elem, &config_error); + /* + If a PIN authentication or communication error occurs, + the Registrar MUST warn the user and MUST NOT automatically reuse the PIN. + Furthermore, if the Registrar detects this situation and prompts the user for a new PIN from the Enrollee device, + it MUST NOT accept the same PIN again without warning the user of a potential attack. + */ + if ((pWscControl->WscState >= WSC_STATE_WAIT_M5) && (config_error != WSC_ERROR_SETUP_LOCKED)) + { + pWscControl->WscRejectSamePinFromEnrollee = TRUE; + pWscControl->WscPinCode = 0; + + if (pWscControl->WscState < WSC_STATE_WAIT_M8) + { + pWscControl->WscStatus = STATUS_WSC_FAIL; + RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_FAIL, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + bReSetWscIE = TRUE; + } + } + +#ifdef CONFIG_AP_SUPPORT + if ((pWscControl->WscState == WSC_STATE_OFF) + && (CurOpMode == AP_MODE) + && (pWscControl->RegData.SelfInfo.ConfigError != WSC_ERROR_NO_ERROR)) + { + bReSetWscIE = TRUE; + } +#endif /* CONFIG_AP_SUPPORT */ + + if ((pWscControl->WscState == WSC_STATE_WAIT_M8) && + (pWscControl->WscConfStatus == WSC_SCSTATE_CONFIGURED)) + { + /* Some external sta will send NACK when AP is configured. */ + /* bWscTrigger should be set FALSE, otherwise Proxy will send NACK to enrollee. */ + pWscControl->bWscTrigger = FALSE; + bReSetWscIE = TRUE; + pWscControl->WscStatus = STATUS_WSC_CONFIGURED; + pWscControl->WscRejectSamePinFromEnrollee = FALSE; + RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_SUCCESS, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + } +#ifdef CONFIG_AP_SUPPORT + else if ((CurOpMode == AP_MODE) && + (pWscControl->WscState == WSC_STATE_WAIT_DONE) && + (pWscControl->WscConfStatus == WSC_SCSTATE_CONFIGURED) && + (pAdapter->ApCfg.MBSSID[apidx].wdev.WepStatus == Ndis802_11WEPEnabled)) + { + bReSetWscIE = TRUE; + pWscControl->WscStatus = STATUS_WSC_FAIL; + } + + if ((CurOpMode == AP_MODE) && bReSetWscIE) + { + WscBuildBeaconIE(pAdapter, pWscControl->WscConfStatus, FALSE, 0, 0, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, CurOpMode); + WscBuildProbeRespIE(pAdapter, WSC_MSGTYPE_AP_WLAN_MGR, pWscControl->WscConfStatus, 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; + } + + 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_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 */ + 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 == 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 WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC) + ; /* Do NOT need to generate EnrolleeRandom and DH public key here. */ + else +#endif /* WSC_NFC_SUPPORT */ + { +#ifdef CONFIG_AP_SUPPORT + /* + We don't need to consider P2P case. + */ + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + { + if ((pWscControl->bWscAutoTriggerDisable == TRUE) && + (pWscControl->bWscTrigger == FALSE)) + { + if (bUPnPMsg == TRUE) + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s(%d): WscAutoTrigger is disabled.\n", __FUNCTION__, __LINE__)); + WscUPnPErrHandle(pAdapter, pWscControl, Elem->TimeStamp.u.LowPart); + if (WscData) + os_free_mem(NULL, WscData); + return; + } + else if (pEntry && IS_ENTRY_CLIENT(pEntry)) + { + DBGPRINT(RT_DEBUG_TRACE, + ("%s(%d): WscAutoTrigger is disabled! Send EapFail to STA.\n", __FUNCTION__, __LINE__)); + WscSendEapFail(pAdapter, pWscControl, TRUE); + if (WscData) + os_free_mem(NULL, WscData); + + return; + } + else + ; /* Keep going. APCLI shall be the else case. */ + } + } +#endif /* CONFIG_AP_SUPPORT */ + + if (pWscControl->RegData.ReComputePke == 1) + { + INT idx; + DH_Len = sizeof(pWscControl->RegData.Pke); + /* Enrollee 192 random bytes for DH key generation */ + for (idx = 0; idx < 192; idx++) + pWscControl->RegData.EnrolleeRandom[idx] = RandomByte(pAdapter); + 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 + if ((CurOpMode == AP_MODE) && pWscControl->bSetupLock) + { + rv = WSC_ERROR_SETUP_LOCKED; + goto Fail; + } +#endif /* CONFIG_AP_SUPPORT */ +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC && pWscControl->NfcModel == MODEL_HANDOVER ) + { + /* NFC handover Skip M3~M8 */ + OpCode |= WSC_OPCODE_DONE; + DataLen = BuildMessageDONE(pAdapter, pWscControl, WscData); + //pWscControl->WscStatus = STATUS_WSC_EAP_M3_SENT; + pWscControl->WscState = WSC_STATE_WAIT_ACK; + pWscControl->PinAttackCount = 0; + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_DONE, NULL, pWscControl->EntryIfIdx, 0); + } + else +#endif /* WSC_NFC_SUPPORT */ + { + OpCode |= WSC_OPCODE_MSG; + DataLen = BuildMessageM3(pAdapter, pWscControl, WscData); + pWscControl->WscStatus = STATUS_WSC_EAP_M3_SENT; + + /* Change the state to next one */ + pWscControl->WscState = WSC_STATE_WAIT_M4; + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M3, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + } + } + } + break; + + case WSC_MSG_M2D: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx M2D\n")); + + /* Receive M2D, if we are at WSC_STATE_WAIT_M2 start, process it immediately */ + if (pWscControl->WscState == WSC_STATE_SENT_M1 || + pWscControl->WscState == WSC_STATE_RX_M2D) + { + if ((rv = ProcessMessageM2D(pAdapter, Elem->Msg, Elem->MsgLen, &pWscControl->RegData))) + goto Fail; + + pWscControl->WscStatus = STATUS_WSC_EAP_M2D_RECEIVED; + + if ((CurOpMode == STA_MODE) + ) + { + /* 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); + } + else + { + /* For VISTA SP1 internal registrar test */ + OpCode |= WSC_OPCODE_NACK; + pWscControl->RegData.SelfInfo.ConfigError = WSC_ERROR_NO_ERROR; + DataLen = BuildMessageNACK(pAdapter, pWscControl, WscData); + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_NACK, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + } + /* Change the state to next one */ + pWscControl->WscState = WSC_STATE_RX_M2D; + } + break; + + case WSC_MSG_M4: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx M4\n")); + + /* Receive M4, if we are at WSC_STATE_WAIT_M4 start, process it immediately */ + if (pWscControl->WscState == WSC_STATE_WAIT_M4) + { + /* Process M4 */ + pWscControl->WscStatus = STATUS_WSC_EAP_M4_RECEIVED; + if ((rv = ProcessMessageM4(pAdapter, pWscControl, Elem->Msg, Elem->MsgLen, &pWscControl->RegData))) + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + WscCheckPinAttackCount(pAdapter, pWscControl); +#endif /* CONFIG_AP_SUPPORT */ + goto Fail; + } + else + { + OpCode |= WSC_OPCODE_MSG; + DataLen = BuildMessageM5(pAdapter, pWscControl, WscData); + pWscControl->WscStatus = STATUS_WSC_EAP_M5_SENT; + + /* Change the state to next one */ + pWscControl->WscState = WSC_STATE_WAIT_M6; + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M5, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + } + } + break; + + case WSC_MSG_M6: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx M6\n")); + + /* Receive M6, if we are at WSC_STATE_WAIT_M6 start, process it immediately */ + if (pWscControl->WscState == WSC_STATE_WAIT_M6) + { + /* Process M6 */ + pWscControl->WscStatus = STATUS_WSC_EAP_M6_RECEIVED; + if ((rv=ProcessMessageM6(pAdapter, pWscControl, Elem->Msg, Elem->MsgLen, &pWscControl->RegData))) + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + WscCheckPinAttackCount(pAdapter, pWscControl); +#endif /* CONFIG_AP_SUPPORT */ + goto Fail; + } + else + { + OpCode |= WSC_OPCODE_MSG; + + DataLen = BuildMessageM7(pAdapter, pWscControl, WscData); + pWscControl->WscStatus = STATUS_WSC_EAP_M7_SENT; + /* Change the state to next one */ + pWscControl->WscState = WSC_STATE_WAIT_M8; + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_M7, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + /* + Complete WPS with this STA. Delete it from WscPeerList for others STA to do WSC with AP + */ + if (pEntry) + { + RTMP_SEM_LOCK(&pWscControl->WscPeerListSemLock); + WscDelListEntryByMAC(&pWscControl->WscPeerList, pEntry->Addr); + RTMP_SEM_UNLOCK(&pWscControl->WscPeerListSemLock); + } + } + } + break; + + case WSC_MSG_M8: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx M8\n")); + + /* Receive M8, if we are at WSC_STATE_WAIT_M6 start, process it immediately */ + if (pWscControl->WscState == WSC_STATE_WAIT_M8) + { + /* Process M8 */ + pWscControl->WscStatus = STATUS_WSC_EAP_M8_RECEIVED; + if ((rv=ProcessMessageM8(pAdapter, Elem->Msg, Elem->MsgLen, pWscControl))) + goto Fail; + else + { + OpCode |= WSC_OPCODE_DONE; + DataLen = BuildMessageDONE(pAdapter, pWscControl, WscData); + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + /* Change the state to next one */ +#ifdef APCLI_SUPPORT + /* Ap Client only supports Inband(EAP)-Enrollee. */ + if (!bUPnPMsg && pEntry && IS_ENTRY_APCLI(pEntry)) + pWscControl->WscState = WSC_STATE_WAIT_EAPFAIL; + else +#endif /* APCLI_SUPPORT */ + pWscControl->WscState = WSC_STATE_WAIT_ACK; + } +#endif /* CONFIG_AP_SUPPORT */ + + RTMPSendWirelessEvent(pAdapter, IW_WSC_SEND_DONE, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + } + } + break; + +#ifdef CONFIG_AP_SUPPORT + case WSC_MSG_WSC_ACK: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Rx ACK\n")); + + /* Receive ACK */ + if (pWscControl->WscState == WSC_STATE_WAIT_ACK) + { + /* Process ACK */ + pWscControl->WscStatus = STATUS_WSC_EAP_RAP_RSP_ACK; + /* Send out EAP-Fail */ + WscSendEapFail(pAdapter, pWscControl, FALSE); + pWscControl->WscState = WSC_STATE_CONFIGURED; + pWscControl->WscStatus = STATUS_WSC_CONFIGURED; + } + break; +#endif /* CONFIG_AP_SUPPORT */ + + default: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : Unsupported Msg Type\n")); + break; + } + + if (bUPnPMsg) + { + if ((MsgType == WSC_MSG_M8) && (pWscControl->WscState == WSC_STATE_WAIT_ACK)) + { + pWscControl->EapMsgRunning = FALSE; + pWscControl->WscState = WSC_STATE_CONFIGURED; + pWscControl->WscStatus = STATUS_WSC_CONFIGURED; + if(pWscUPnPInfo->bUPnPMsgTimerRunning == TRUE) + { + RTMPCancelTimer(&pWscUPnPInfo->UPnPMsgTimer, &Cancelled); + pWscUPnPInfo->bUPnPMsgTimerRunning = FALSE; + } + pWscUPnPInfo->bUPnPInProgress = FALSE; + pWscUPnPInfo->registrarID = 0; + } + } + else + { + if (((MsgType == WSC_MSG_WSC_ACK) && (pWscControl->WscState == WSC_STATE_CONFIGURED)) || + ((MsgType == WSC_MSG_M8) && (pWscControl->WscState == WSC_STATE_WAIT_ACK))) + { + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + pWscControl->EapolTimerRunning = FALSE; + pWscControl->EapMsgRunning = FALSE; + /*NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); */ + } + } + + if(OpCode > WSC_OPCODE_UPNP_MASK) + bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), WSC_OPCODE_UPNP_DATA, + WSC_UPNP_DATA_SUB_NORMAL, WscData, DataLen, + Elem->TimeStamp.u.LowPart, Elem->TimeStamp.u.HighPart, + &pAdapter->CurrentAddress[0], CurOpMode); + else if(OpCode > 0 && OpCode < WSC_OPCODE_UPNP_MASK) + { + if (pWscControl->WscState != WSC_STATE_CONFIGURED) + { +#ifdef WSC_V2_SUPPORT + pWscControl->WscTxBufLen = 0; + pWscControl->pWscCurBufIdx = NULL; + pWscControl->bWscLastOne = TRUE; + if (pWscControl->bWscFragment && (DataLen > pWscControl->WscFragSize)) + { + ASSERT(DataLen < MGMT_DMA_BUFFER_SIZE); + NdisMoveMemory(pWscControl->pWscTxBuf, WscData, DataLen); + pWscControl->WscTxBufLen = DataLen; + NdisZeroMemory(WscData, DataLen); + pWscControl->bWscLastOne = FALSE; + pWscControl->bWscFirstOne = TRUE; + NdisMoveMemory(WscData, pWscControl->pWscTxBuf, pWscControl->WscFragSize); + DataLen = pWscControl->WscFragSize; + pWscControl->WscTxBufLen -= pWscControl->WscFragSize; + pWscControl->pWscCurBufIdx = (pWscControl->pWscTxBuf + pWscControl->WscFragSize); + } +#endif /* WSC_V2_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (pEntry && IS_ENTRY_APCLI(pEntry)) + WscSendMessage(pAdapter, OpCode, WscData, DataLen, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP); + else + WscSendMessage(pAdapter, OpCode, WscData, DataLen, pWscControl, AP_MODE, EAP_CODE_REQ); + } +#endif /* CONFIG_AP_SUPPORT */ + + } + } + else + bUPnPStatus = TRUE; + +Fail: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapEnrolleeAction : rv = %d\n", rv)); + if (rv) + { +#ifdef CONFIG_AP_SUPPORT + if ((CurOpMode == AP_MODE) && pWscControl->bSetupLock) + rv = WSC_ERROR_SETUP_LOCKED; +#endif /* CONFIG_AP_SUPPORT */ + + if (rv <= WSC_ERROR_DEV_PWD_AUTH_FAIL) + pWscControl->RegData.SelfInfo.ConfigError = rv; + else if ((rv == WSC_ERROR_HASH_FAIL) || (rv == WSC_ERROR_HMAC_FAIL)) + pWscControl->RegData.SelfInfo.ConfigError = WSC_ERROR_DECRYPT_CRC_FAIL; + + switch(rv) + { + case WSC_ERROR_DEV_PWD_AUTH_FAIL: + pWscControl->WscStatus = STATUS_WSC_ERROR_DEV_PWD_AUTH_FAIL; + break; + default: + pWscControl->WscStatus = STATUS_WSC_FAIL; + break; + } + RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_FAIL, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + if (bUPnPMsg) + { + if (pWscUPnPInfo->bUPnPMsgTimerRunning == TRUE) + { + RTMPCancelTimer(&pWscUPnPInfo->UPnPMsgTimer, &Cancelled); + pWscUPnPInfo->bUPnPMsgTimerRunning = FALSE; + } + pWscUPnPInfo->bUPnPInProgress = FALSE; + } + else + WscSendNACK(pAdapter, pEntry, pWscControl); + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + pWscControl->WscState = WSC_STATE_OFF; + } +#endif /* CONFIG_AP_SUPPORT */ + + + /*NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); */ + /*pWscControl->WscMode = 1; */ +#ifdef WSC_NFC_SUPPORT + pWscControl->bTriggerByNFC = FALSE; +#endif /* WSC_NFC_SUPPORT */ + + 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 */ + + if (rv == 1) + { +#ifdef WSC_LED_SUPPORT + UCHAR WPSLEDStatus; +#endif /* WSC_LED_SUPPORT */ +#ifdef WSC_NFC_SUPPORT + pWscControl->bTriggerByNFC = FALSE; +#endif /* WSC_NFC_SUPPORT */ + pWscControl->bWscTrigger = FALSE; + pWscControl->RegData.ReComputePke = 1; + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + if (pWscControl->Wsc2MinsTimerRunning) + { + pWscControl->Wsc2MinsTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->Wsc2MinsTimer, &Cancelled); + } + if ((pWscControl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED) +#ifdef CONFIG_AP_SUPPORT + || (pWscControl->bWCNTest == TRUE) + || ((CurOpMode == AP_MODE) && !pWscControl->bSetupLock) +#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 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 WSC_LED_SUPPORT + /* The protocol is finished. */ + WPSLEDStatus = LED_WPS_SUCCESS; + RTMPSetLED(pAdapter, WPSLEDStatus); +#endif /* WSC_LED_SUPPORT */ + } +} + +#ifdef CONFIG_AP_SUPPORT +/* + ============================================================================ + Proxy Proxy Proxy + ============================================================================ +*/ +VOID WscEapApProxyAction( + IN PRTMP_ADAPTER pAdapter, + IN MLME_QUEUE_ELEM *Elem, + IN UCHAR MsgType, + IN MAC_TABLE_ENTRY *pEntry, + IN PWSC_CTRL pWscControl) +{ + PUCHAR WscData = NULL; + BOOLEAN sendToUPnP = FALSE, bUPnPStatus = FALSE, Cancelled; + int reqID = 0; + WSC_UPNP_NODE_INFO *pWscUPnPInfo = &pWscControl->WscUPnPNodeInfo; + UINT MaxWscDataLen = WSC_MAX_DATA_LEN; + + DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction Enter!\n")); + + if (Elem->MsgType == WSC_EAPOL_UPNP_MSG) + { + reqID = Elem->TimeStamp.u.LowPart; + if(reqID > 0) + sendToUPnP = TRUE; + } + + DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction():pEntry=%p, ElemMsgType=%ld, MsgType=%d!\n", pEntry, Elem->MsgType, MsgType)); + + if ((pWscControl->WscActionMode != WSC_PROXY) || + ((Elem->MsgType == WSC_EAPOL_PACKET_MSG) && (pEntry == NULL))) + { + DBGPRINT(RT_DEBUG_TRACE, ("EarlyCheckFailed: gWscActionMode=%d, pEntry=%p!\n", pWscControl->WscActionMode, pEntry)); + goto Fail; + } + +#ifdef WSC_V2_SUPPORT + MaxWscDataLen = MaxWscDataLen + (UINT)pWscControl->WscV2Info.ExtraTlv.TlvLen; +#endif /* WSC_V2_SUPPORT */ + os_alloc_mem(NULL, (UCHAR **)&WscData, MaxWscDataLen); + if (WscData == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscData Allocate failed!\n")); + goto Fail; + } + NdisZeroMemory(WscData, MaxWscDataLen); + + /* Base on state doing the Msg, State change diagram */ + if (Elem->MsgType == WSC_EAPOL_UPNP_MSG) + { /* WSC message send from UPnP. */ + switch (MsgType) + { + case WSC_MSG_M2: + case WSC_MSG_M4: + case WSC_MSG_M6: + case WSC_MSG_M8: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction: Rx WscMsg(%d) from UPnP, eventID=0x%x!\n", MsgType, reqID)); + WscSendMessage(pAdapter, WSC_OPCODE_MSG, Elem->Msg, Elem->MsgLen, pWscControl, AP_MODE, EAP_CODE_REQ); + + /*Notify the UPnP daemon which remote registar is negotiating with enrollee. */ + if (MsgType == WSC_MSG_M2) + { + pWscUPnPInfo->registrarID = Elem->TimeStamp.u.HighPart; + DBGPRINT(RT_DEBUG_TRACE, ("%s():registrarID=0x%x!\n", __FUNCTION__, pWscUPnPInfo->registrarID)); + bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_MGMT, WSC_UPNP_MGMT_SUB_REG_SELECT, + (PUCHAR)(&pWscUPnPInfo->registrarID), sizeof(UINT), 0, 0, NULL, AP_MODE); + + /*Reset the UPnP timer and status. */ + if (pWscControl->bM2DTimerRunning == TRUE) + { + RTMPCancelTimer(&pWscControl->M2DTimer, &Cancelled); + pWscControl->bM2DTimerRunning = FALSE; + } + pWscControl->M2DACKBalance = 0; + pWscUPnPInfo->registrarID = 0; + } + if (MsgType == WSC_MSG_M8) + { + WscBuildBeaconIE(pAdapter, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAdapter, WSC_MSGTYPE_AP_WLAN_MGR, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, pWscControl->EntryIfIdx, NULL, 0, AP_MODE); + APUpdateBeaconFrame(pAdapter, pWscControl->EntryIfIdx & 0x0F); + } + break; + + case WSC_MSG_M2D: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction: Rx WscMsg M2D(%d) from UPnP, eventID=0x%x!\n", MsgType, reqID)); + + /*If it's send by UPnP Action, response ok directly to remote UPnP Control Point! */ + if (reqID > 0) + bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_ACK, + 0, 0, reqID, 0, NULL, AP_MODE); + + /*Send M2D to wireless station. */ + WscSendMessage(pAdapter, WSC_OPCODE_MSG, Elem->Msg, Elem->MsgLen, pWscControl, AP_MODE, EAP_CODE_REQ); + pWscControl->M2DACKBalance++; + if ((pWscUPnPInfo->registrarID == 0) && (pWscControl->bM2DTimerRunning == FALSE)) + { + /* Add M2D timer used to trigger the EAPFail Packet! */ + RTMPSetTimer(&pWscControl->M2DTimer, WSC_UPNP_M2D_TIME_OUT); + pWscControl->bM2DTimerRunning = TRUE; + } + break; + + case WSC_MSG_WSC_NACK: + default: + DBGPRINT(RT_DEBUG_TRACE, ("Recv WscMsg(%d) from UPnP, request EventID=%d! drop it!\n", MsgType, reqID)); + break; + } + } + else + { /*WSC msg send from EAP. */ + switch (MsgType) + { + case WSC_MSG_M1: + case WSC_MSG_M3: + case WSC_MSG_M5: + case WSC_MSG_M7: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction: Rx WscMsg(%d) from EAP\n", MsgType)); + /*This msg send to event-based external registrar */ + if (MsgType == WSC_MSG_M1) + { + bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_TO_ALL, + Elem->Msg, Elem->MsgLen, 0, 0, &pWscControl->EntryAddr[0], AP_MODE); + pWscControl->WscState = WSC_STATE_SENT_M1; + } + else + bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_TO_ALL, + Elem->Msg, Elem->MsgLen, 0, pWscUPnPInfo->registrarID, + &pWscControl->EntryAddr[0], AP_MODE); + + break; + + case WSC_MSG_WSC_ACK: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction: Rx WSC_ACK from EAP\n")); + + /* The M2D must appeared before the ACK, so we just need sub it when (pWscUPnPInfo->M2DACKBalance > 0) */ + if (pWscControl->M2DACKBalance > 0) + pWscControl->M2DACKBalance--; + break; + + case WSC_MSG_WSC_DONE: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction: Rx WSC_DONE from EAP\n")); + DBGPRINT(RT_DEBUG_TRACE, ("WscEapApProxyAction: send WSC_DONE to UPnP Registrar!\n")); + /*Send msg to event-based external registrar */ + bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_TO_ONE, + Elem->Msg, Elem->MsgLen, 0, + pWscUPnPInfo->registrarID, &pWscControl->EntryAddr[0], AP_MODE); + + /*Send EAPFail to wireless station to finish the whole process. */ + WscSendEapFail(pAdapter, pWscControl, FALSE); + + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + pWscControl->EapolTimerRunning = FALSE; + + pEntry->bWscCapable = FALSE; + pWscControl->EapMsgRunning = FALSE; + NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); + + if (pWscControl->Wsc2MinsTimerRunning) + { + pWscControl->Wsc2MinsTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->Wsc2MinsTimer, &Cancelled); + } + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("Recv WSC Msg(%d) from EAP , it's impossible, drop it!\n", MsgType)); + break; + } + } + +Fail: + if (WscData) + os_free_mem(NULL, WscData); + if (sendToUPnP && (bUPnPStatus == FALSE)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Need to send UPnP but bUPnPStatus is false!MsgType=%d, regID=0x%x!\n", MsgType, reqID)); + WscUPnPErrHandle(pAdapter, pWscControl, reqID); + } + +} +#endif /* CONFIG_AP_SUPPORT */ + +/* + ============================================================================ + Registrar Registrar Registrar + ============================================================================ +*/ +VOID WscEapRegistrarAction( + IN PRTMP_ADAPTER pAdapter, + IN MLME_QUEUE_ELEM *Elem, + IN UCHAR MsgType, + IN MAC_TABLE_ENTRY *pEntry, + IN PWSC_CTRL pWscControl) +{ + INT DataLen = 0, rv = 0; + UCHAR OpCode = 0; + UCHAR *WscData = NULL; + BOOLEAN bUPnPMsg, bUPnPStatus = FALSE, Cancelled; + WSC_UPNP_NODE_INFO *pWscUPnPInfo = &pWscControl->WscUPnPNodeInfo; + UINT MaxWscDataLen = WSC_MAX_DATA_LEN; + UCHAR CurOpMode = 0xFF; + + DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction Enter!\n")); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + CurOpMode = AP_MODE; +#endif // CONFIG_AP_SUPPORT // + + + bUPnPMsg = Elem->MsgType == WSC_EAPOL_UPNP_MSG ? TRUE : FALSE; + + if(bUPnPMsg) + { + if(MsgType == WSC_MSG_M1) + { /* It's a M1 message, we may need to initialize our state machine. */ + if ((pWscControl->WscActionMode == WSC_REGISTRAR) + && (pWscControl->EntryIfIdx == WSC_INIT_ENTRY_APIDX) + && (pWscControl->WscState < WSC_STATE_WAIT_M1) + && (pWscUPnPInfo->bUPnPInProgress == FALSE)) + { + pWscUPnPInfo->bUPnPInProgress = TRUE; + /*Set the WscState as "WSC_STATE_WAIT_RESP_ID" because UPnP start from this state. */ + pWscControl->WscState = WSC_STATE_WAIT_M1; + RTMPSetTimer(&pWscUPnPInfo->UPnPMsgTimer, WSC_UPNP_MSG_TIME_OUT); + pWscUPnPInfo->bUPnPMsgTimerRunning = TRUE; + } + } + OpCode = WSC_OPCODE_UPNP_MASK; + + } else { + if (pWscControl->EapolTimerRunning) + pWscControl->EapolTimerRunning = FALSE; + + } + +#ifdef WSC_V2_SUPPORT + MaxWscDataLen = MaxWscDataLen + (UINT)pWscControl->WscV2Info.ExtraTlv.TlvLen; +#endif /* WSC_V2_SUPPORT */ + os_alloc_mem(NULL, (UCHAR **)&WscData, MaxWscDataLen); + if (WscData == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscData Allocate failed!\n")); + goto Fail; + } + NdisZeroMemory(WscData, MaxWscDataLen); + + /* Base on state doing the Msg, State change diagram */ + switch (MsgType) + { + case WSC_MSG_M1: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction : Rx M1\n")); + + /* Receive M1, if we are at WSC_STATE_WAIT_M1 start, process it immediately */ + pWscControl->WscStatus = STATUS_WSC_EAP_M1_RECEIVED; + if (pWscControl->WscState == WSC_STATE_WAIT_M1) + { + OpCode |= WSC_OPCODE_MSG; + + /* Process M1 */ + if ((rv=ProcessMessageM1(pAdapter, pWscControl, Elem->Msg, Elem->MsgLen, &pWscControl->RegData))) + goto Fail; + else + { + BOOLEAN bSendM2D = TRUE; + + + + if (pWscControl->bWscTrigger && (!pWscControl->bWscAutoTigeer)) + { + if (((pWscControl->WscMode == WSC_PBC_MODE) || (pWscControl->WscMode == WSC_SMPBC_MODE)) + || (pWscControl->WscMode == WSC_PIN_MODE && pWscControl->WscPinCode != 0)) + bSendM2D = FALSE; + } + +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC) + { + bSendM2D = FALSE; + if (pWscControl->RegData.SelfInfo.ConfigError == WSC_ERROR_PUBLIC_KEY_HASH_MISMATCH) + { + DBGPRINT(RT_DEBUG_TRACE, ("WSC_ERROR_PUBLIC_KEY_HASH_MISMATCH ConfigError=%d \n", pWscControl->RegData.SelfInfo.ConfigError)); + bSendM2D = TRUE; + } + } +#endif /* WSC_NFC_SUPPORT */ + + if (bSendM2D) + { + DataLen = BuildMessageM2D(pAdapter, pWscControl, WscData); + pWscControl->WscState = WSC_STATE_SENT_M2D; + pWscControl->M2DACKBalance++; + if (pWscControl->bM2DTimerRunning == FALSE) + { + // Add M2D timer used to trigger the EAPFail Packet! + RTMPSetTimer(&pWscControl->M2DTimer, WSC_UPNP_M2D_TIME_OUT); + pWscControl->bM2DTimerRunning = TRUE; + } + } + else + { + pWscControl->WscStatus = STATUS_WSC_EAP_M2_SENT; + DataLen = BuildMessageM2(pAdapter, pWscControl, WscData); + + /* Change the state to next one */ +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC && pWscControl->NfcModel == MODEL_HANDOVER) + { + pWscControl->WscState = WSC_STATE_WAIT_DONE; /* Skip M3~M8 */ + } + else +#endif /* WSC_NFC_SUPPORT */ + pWscControl->WscState = WSC_STATE_WAIT_M3; + 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 */ + (0)) + { + OpCode |= WSC_OPCODE_MSG; + DataLen = BuildMessageM8(pAdapter, pWscControl, WscData); + pWscControl->WscStatus = STATUS_WSC_EAP_M8_SENT; + /* Change the state to next one */ + pWscControl->WscState = WSC_STATE_WAIT_DONE; + 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->func_tb_idx, 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 */ + + } + } + } + break; + + case WSC_MSG_WSC_DONE: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction : Rx DONE\n")); + if (pWscControl->WscState == WSC_STATE_WAIT_DONE) + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + pWscControl->WscStatus = STATUS_WSC_EAP_RAP_RSP_DONE_SENT; + /* Send EAP-Fail */ + WscSendEapFail(pAdapter, pWscControl, FALSE); + pWscControl->WscStatus = STATUS_WSC_CONFIGURED; + } +#endif /* CONFIG_AP_SUPPORT */ + + + pWscControl->WscState = WSC_STATE_CONFIGURED; + RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_SUCCESS, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + pWscControl->EapMsgRunning = FALSE; + } + break; + default: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction : Unsupported Msg Type\n")); + if (WscData) + os_free_mem(NULL, WscData); + return; + } + + if(OpCode > WSC_OPCODE_UPNP_MASK) + bUPnPStatus = WscSendUPnPMessage(pAdapter, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_NORMAL, + WscData, DataLen, + Elem->TimeStamp.u.LowPart, Elem->TimeStamp.u.HighPart, &pWscControl->EntryAddr[0], CurOpMode); + else if(OpCode > 0 && OpCode < WSC_OPCODE_UPNP_MASK) + { +#ifdef WSC_V2_SUPPORT + pWscControl->WscTxBufLen = 0; + pWscControl->pWscCurBufIdx = NULL; + pWscControl->bWscLastOne = TRUE; + if (pWscControl->bWscFragment && (DataLen > pWscControl->WscFragSize)) + { + ASSERT(DataLen < MGMT_DMA_BUFFER_SIZE); + NdisMoveMemory(pWscControl->pWscTxBuf, WscData, DataLen); + pWscControl->WscTxBufLen = DataLen; + NdisZeroMemory(WscData, DataLen); + pWscControl->bWscLastOne = FALSE; + pWscControl->bWscFirstOne = TRUE; + NdisMoveMemory(WscData, pWscControl->pWscTxBuf, pWscControl->WscFragSize); + DataLen = pWscControl->WscFragSize; + pWscControl->WscTxBufLen -= pWscControl->WscFragSize; + pWscControl->pWscCurBufIdx = (pWscControl->pWscTxBuf + pWscControl->WscFragSize); + } +#endif /* WSC_V2_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (pWscControl->WscState != WSC_STATE_CONFIGURED) + WscSendMessage(pAdapter, OpCode, WscData, DataLen, pWscControl, AP_MODE, EAP_CODE_REQ); + } +#endif /* CONFIG_AP_SUPPORT */ + + + } + else + bUPnPStatus = TRUE; + + if(bUPnPMsg) + { + if(pWscControl->WscState == WSC_STATE_SENT_M2D) + { /*After M2D, reset the status of State Machine. */ + pWscControl->WscState = WSC_STATE_WAIT_UPNP_START; + pWscUPnPInfo->bUPnPInProgress = FALSE; + } + } +Fail: + DBGPRINT(RT_DEBUG_TRACE, ("WscEapRegistrarAction : rv = %d\n", rv)); + if (rv) + { + if (rv <= WSC_ERROR_DEV_PWD_AUTH_FAIL) + { + pWscControl->RegData.SelfInfo.ConfigError = rv; + } + else if ((rv == WSC_ERROR_HASH_FAIL) || (rv == WSC_ERROR_HMAC_FAIL)) + pWscControl->RegData.SelfInfo.ConfigError = WSC_ERROR_DECRYPT_CRC_FAIL; + + switch(rv) + { + case WSC_ERROR_HASH_FAIL: + pWscControl->WscStatus = STATUS_WSC_ERROR_HASH_FAIL; + break; + case WSC_ERROR_HMAC_FAIL: + pWscControl->WscStatus = STATUS_WSC_ERROR_HMAC_FAIL; + break; + default: + pWscControl->WscStatus = STATUS_WSC_FAIL; + break; + } + RTMPSendWirelessEvent(pAdapter, IW_WSC_STATUS_FAIL, NULL, (pWscControl->EntryIfIdx & 0x0F), 0); + if (bUPnPMsg) + { + if (pWscUPnPInfo->bUPnPMsgTimerRunning == TRUE) + { + RTMPCancelTimer(&pWscUPnPInfo->UPnPMsgTimer, &Cancelled); + pWscUPnPInfo->bUPnPMsgTimerRunning = FALSE; + } + pWscUPnPInfo->bUPnPInProgress = FALSE; + } + else + { + DataLen = BuildMessageNACK(pAdapter, pWscControl, WscData); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + WscSendMessage(pAdapter, WSC_OPCODE_NACK, WscData, DataLen, pWscControl, AP_MODE, EAP_CODE_REQ); + pEntry->bWscCapable = FALSE; + } +#endif /* CONFIG_AP_SUPPORT */ + + + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + pWscControl->EapolTimerRunning = FALSE; + } + /* + If a PIN authentication or communication error occurs after sending message M6, + the Registrar MUST warn the user and MUST NOT automatically reuse the PIN. + Furthermore, if the Registrar detects this situation and prompts the user for a new PIN from the Enrollee device, + it MUST NOT accept the same PIN again without warning the user of a potential attack. + */ + if (pWscControl->WscState >= WSC_STATE_WAIT_M7) + { + pWscControl->WscRejectSamePinFromEnrollee = TRUE; + pWscControl->WscPinCode = 0; + } + pWscControl->WscState = WSC_STATE_OFF; + pWscControl->WscStatus = STATUS_WSC_IDLE; + /*NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); */ + /*pWscControl->WscMode = 1; */ +#ifdef WSC_NFC_SUPPORT + pWscControl->bTriggerByNFC = FALSE; +#endif /* WSC_NFC_SUPPORT */ + + bUPnPStatus = FALSE; + } + + if(WscData) + os_free_mem(NULL, WscData); + + if(bUPnPMsg && (bUPnPStatus == FALSE)) + WscUPnPErrHandle(pAdapter, pWscControl, Elem->TimeStamp.u.LowPart); + + if (pWscControl->WscState == WSC_STATE_CONFIGURED) + { +#ifdef WSC_LED_SUPPORT + UCHAR WPSLEDStatus; +#endif /* WSC_LED_SUPPORT */ +#ifdef WSC_NFC_SUPPORT + pWscControl->bTriggerByNFC = FALSE; +#endif /* WSC_NFC_SUPPORT */ + + pWscControl->bWscTrigger = FALSE; + +/* WPS_BandSteering Support */ +#ifdef BAND_STEERING + if (pAdapter->ApCfg.BandSteering) { + + int apidx = pWscControl->EntryIfIdx & 0x0F; + struct wifi_dev *wdev = NULL; + + if (apidx < HW_BEACON_MAX_NUM) + wdev = &pAdapter->ApCfg.MBSSID[apidx].wdev; + + if (wdev) { + PBND_STRG_CLI_TABLE table = Get_BndStrgTable(pAdapter, wdev->func_idx); + + if (table && table->bEnabled) { + NdisAcquireSpinLock(&table->WpsWhiteListLock); + ClearWpsWhiteList(&table->WpsWhiteList); + NdisReleaseSpinLock(&table->WpsWhiteListLock); + MTWF_LOG(DBG_CAT_SEC, CATSEC_WPS, DBG_LVL_TRACE, ("%s:channel %u wps whitelist cleared, size : %d\n", + __func__, table->Channel, table->WpsWhiteList.size)); + } + } + } +#endif + + 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->func_tb_idx, NULL, 0, CurOpMode); + WscBuildProbeRespIE(pAdapter, WSC_MSGTYPE_AP_WLAN_MGR, WSC_SCSTATE_CONFIGURED, FALSE, 0, 0, pWscControl->EntryIfIdx, NULL, 0, CurOpMode); + APUpdateBeaconFrame(pAdapter, pEntry->func_tb_idx); + + } + } + NdisZeroMemory(&pAdapter->CommonCfg.WscStaPbcProbeInfo, sizeof(WSC_STA_PBC_PROBE_INFO)); +#endif /* CONFIG_AP_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 WSC_LED_SUPPORT + /* The protocol is finished. */ + WPSLEDStatus = LED_WPS_SUCCESS; + RTMPSetLED(pAdapter, WPSLEDStatus); +#endif /* WSC_LED_SUPPORT */ + { + pWscControl->WscPinCode = 0; + pWscControl->WscMode = 1; + } + RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); + pWscControl->EapolTimerRunning = FALSE; + + 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 // + + + 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; + + + return; + } + else if (nWscState == WSC_STATE_WAIT_EAPFAIL) + { + pWscControl->WscState = WSC_STATE_OFF; + pWscControl->WscStatus = STATUS_WSC_CONFIGURED; + pWscControl->WscConfMode = WSC_DISABLE; + } + else + { +#ifdef CONFIG_AP_SUPPORT + if ((pWscControl->WscActionMode == WSC_PROXY) && (pAd->OpMode == OPMODE_AP)) + { + pWscControl->WscState = WSC_STATE_OFF; + } + else +#endif /* CONFIG_AP_SUPPORT */ + pWscControl->WscState = WSC_STATE_FAIL; + } + + if (nWscState == WSC_STATE_WAIT_M8) + pWscControl->bWscTrigger = FALSE; + pWscControl->WscRetryCount = 0; + NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); + pWscControl->EapolTimerRunning = FALSE; + if (pWscControl->WscMode == 1) + WscMode = DEV_PASS_ID_PIN; + else + WscMode = DEV_PASS_ID_PBC; + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if ((pWscControl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED) && + ((nWscState == WSC_STATE_WAIT_DONE) || (nWscState == WSC_STATE_WAIT_ACK))) + { + pWscControl->bWscTrigger = FALSE; + pWscControl->WscConfStatus = WSC_SCSTATE_CONFIGURED; + WscBuildBeaconIE(pAd, pWscControl->WscConfStatus, FALSE, WscMode, pWscControl->WscConfigMethods, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, CurOpMode); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, pWscControl->WscConfStatus, FALSE, WscMode, pWscControl->WscConfigMethods, pWscControl->EntryIfIdx, NULL, 0, CurOpMode); + pAd->WriteWscCfgToDatFile = pWscControl->EntryIfIdx; + WscWriteConfToPortCfg(pAd, + pWscControl, + &pWscControl->WscProfile.Profile[0], + FALSE); + { + APStop(pAd); + APStartUp(pAd); + } + +/*#ifdef KTHREAD_SUPPORT */ +/* WAKE_UP(&(pAd->wscTask)); */ +/*#else */ +/* RTMP_SEM_EVENT_UP(&(pAd->wscTask.taskSema)); */ +/*#endif */ + RtmpOsTaskWakeUp(&(pAd->wscTask)); + } + else + { + if (pEntry && IS_ENTRY_CLIENT(pEntry)) + { + pEntry->bWscCapable = FALSE; + WscSendEapFail(pAd, pWscControl, TRUE); + } + + WscBuildBeaconIE(pAd, pWscControl->WscConfStatus, FALSE, WscMode, pWscControl->WscConfigMethods, (pWscControl->EntryIfIdx & 0x0F), NULL, 0, CurOpMode); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, pWscControl->WscConfStatus, FALSE, WscMode, pWscControl->WscConfigMethods, pWscControl->EntryIfIdx, NULL, 0, CurOpMode); + } +#ifdef APCLI_SUPPORT + if (pEntry && IS_ENTRY_APCLI(pEntry)) + { + WscApCliLinkDown(pAd, pWscControl); + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + + 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 // + + + 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 */ + + pWscControl->EapolTimerRunning = FALSE; + NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); + DBGPRINT(RT_DEBUG_TRACE, ("sta is left.\n")); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPOLTimeOutAction\n")); + return; + } + } + + if (!pWscControl->EapolTimerRunning) + { + pWscControl->WscRetryCount = 0; + goto out; + } + + if (pWscControl->EapolTimerPending) + { + RTMPModTimer(&pWscControl->EapolTimer, WSC_EAP_MSG_TIME_OUT); + DBGPRINT(RT_DEBUG_TRACE, ("EapolTimer Pending......\n")); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscEAPOLTimeOutAction\n")); + return; + } + +#ifdef WSC_V2_SUPPORT + MaxWscDataLen = MaxWscDataLen + (UINT)pWscControl->WscV2Info.ExtraTlv.TlvLen; +#endif /* WSC_V2_SUPPORT */ + os_alloc_mem(NULL, (UCHAR **)&WscData, MaxWscDataLen); + if (WscData != NULL) + NdisZeroMemory(WscData, WSC_MAX_DATA_LEN); + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (pEntry && IS_ENTRY_CLIENT(pEntry) && (pWscControl->WscState <= WSC_STATE_CONFIGURED) && (pWscControl->WscActionMode != WSC_PROXY)) + { + /* A timer in the AP should cause to be disconnected after 5 seconds if a */ + /* valid EAP-Rsp/Identity indicating WPS is not received. */ + /* << from WPS EAPoL and RSN handling.doc >> */ + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_RESP_ID, pWscControl); + + /* If do disassocation here, it will affect connection of non-WPS clients. */ + goto out; + } + } +#endif /* CONFIG_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("WscState = %d\n", pWscControl->WscState)); + switch(pWscControl->WscState) + { + case WSC_STATE_WAIT_REQ_ID: + /* For IWSC case, keep sending EAPOL_START until 2 mins timeout */ + if ((pWscControl->WscRetryCount >= 2) + ) + WscTimeOutProcess(pWscControl->pAd, pEntry, WSC_STATE_WAIT_REQ_ID, pWscControl); + else + { + pWscControl->WscRetryCount++; + 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 */ + 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 */ + + } + } + 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 */ + + } + } + 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 */ + + } + } + 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 */ + + } + } + 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 */ + + } + } + 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 */ + + } + } + 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 */ + + } + } + 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 */ + + } + } + 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 + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + CurOpMode = AP_MODE; +#endif /* CONFIG_AP_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) + { +/* WPS_BandSteering Support */ +#ifdef BAND_STEERING + if (pAd->ApCfg.BandSteering) { + PBND_STRG_CLI_TABLE table = Get_BndStrgTable(pAd, MAIN_MBSSID); + + if (table && table->bEnabled) { + NdisAcquireSpinLock(&table->WpsWhiteListLock); + ClearWpsWhiteList(&table->WpsWhiteList); + NdisReleaseSpinLock(&table->WpsWhiteListLock); + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("%s:channel %u wps whitelist cleared, size : %d\n", + __func__, table->Channel, table->WpsWhiteList.size)); + } + } +#endif + 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); + + if (pWscControl->WscScanTimerRunning) + { + pWscControl->WscScanTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->WscScanTimer, &Cancelled); + } + if (pWscControl->WscPBCTimerRunning) + { + pWscControl->WscPBCTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->WscPBCTimer, &Cancelled); + } +#ifdef WSC_NFC_SUPPORT + pWscControl->bTriggerByNFC = FALSE; +#endif /* WSC_NFC_SUPPORT */ + } + +#ifdef WSC_LED_SUPPORT + /* if link is up, there shall be nothing wrong */ + /* perhaps we will set another flag to do it */ + if ((OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) && + (pWscControl->WscState == WSC_STATE_OFF) && + (pWscControl->WscStatus == STATUS_WSC_CONFIGURED)) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscConnectTimeout --> Connection OK\n")); + } + else + { + UCHAR WPSLEDStatus; + + pWscControl->WscStatus = STATUS_WSC_FAIL; + pWscControl->WscState = WSC_STATE_OFF; + + /* WPS LED mode 7, 8, 11 or 12. */ + if ((LED_MODE(pAd) == WPS_LED_MODE_7) || + (LED_MODE(pAd) == WPS_LED_MODE_8) || + (LED_MODE(pAd) == WPS_LED_MODE_11) || + (LED_MODE(pAd) == WPS_LED_MODE_12)) + { + pWscControl->bSkipWPSTurnOffLED = FALSE; + + /* Turn off the WPS LED modoe due to the maximum WPS processing time is expired (120 seconds). */ + WPSLEDStatus = LED_WPS_TURN_LED_OFF; + RTMPSetLED(pAd, WPSLEDStatus); + } + else if ((LED_MODE(pAd) == WPS_LED_MODE_9) /* WPS LED mode 9. */ + ) + { + if (pWscControl->WscMode == WSC_PIN_MODE) /* PIN method. */ + { + /* The NIC using PIN method fails to finish the WPS handshaking within 120 seconds. */ + WPSLEDStatus = LED_WPS_ERROR; + RTMPSetLED(pAd, WPSLEDStatus); + /* Turn off the WPS LED after 15 seconds. */ + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_WPS_FAIL_LED_PATTERN_TIMEOUT); + + /* The Ralink UI would make RT_OID_DISCONNECT_REQUEST request while it receive STATUS_WSC_EAP_FAILED. */ + /* Allow the NIC to turn off the WPS LED after WSC_WPS_SKIP_TURN_OFF_LED_TIMEOUT seconds. */ + pWscControl->bSkipWPSTurnOffLED = TRUE; + RTMPSetTimer(&pWscControl->WscSkipTurnOffLEDTimer, WSC_WPS_SKIP_TURN_OFF_LED_TIMEOUT); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: The NIC using PIN method fails to finish the WPS handshaking within 120 seconds.\n", __FUNCTION__)); + } + else if (pWscControl->WscMode == WSC_PBC_MODE) /* PBC method. */ + { + switch (pWscControl->WscLastWarningLEDMode) /* Based on last WPS warning LED mode. */ + { + case 0: + case LED_WPS_ERROR: + case LED_WPS_SESSION_OVERLAP_DETECTED: + /* Failed to find any partner. */ + WPSLEDStatus = LED_WPS_ERROR; + RTMPSetLED(pAd, WPSLEDStatus); + + /* Turn off the WPS LED after 15 seconds. */ + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_WPS_FAIL_LED_PATTERN_TIMEOUT); + + /* The Ralink UI would make RT_OID_DISCONNECT_REQUEST request while it receive STATUS_WSC_EAP_FAILED. */ + /* Allow the NIC to turn off the WPS LED after WSC_WPS_SKIP_TURN_OFF_LED_TIMEOUT seconds. */ + pWscControl->bSkipWPSTurnOffLED = TRUE; + RTMPSetTimer(&pWscControl->WscSkipTurnOffLEDTimer, WSC_WPS_SKIP_TURN_OFF_LED_TIMEOUT); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Last WPS LED status is LED_WPS_ERROR.\n", __FUNCTION__)); + break; + + default: + /* do nothing. */ + break; + } + } + else + { + /* do nothing. */ + } + } + else + { + /* do nothing. */ + } + + DBGPRINT(RT_DEBUG_TRACE, ("WscConnectTimeout --> Fail to connect\n")); + } +#endif /* WSC_LED_SUPPORT */ + } + + + DBGPRINT(RT_DEBUG_TRACE, ("<----- Wsc2MinsTimeOutAction\n")); +} + +/* + ======================================================================== + + Routine Description: + Classify EAP message type for enrolee + + Arguments: + pAd - NIC Adapter pointer + Elem - The EAP packet + + Return Value: + Received EAP message type + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +UCHAR WscRxMsgType( + IN PRTMP_ADAPTER pAdapter, + IN PMLME_QUEUE_ELEM pElem) +{ + USHORT Length; + PUCHAR pData; + USHORT WscType, WscLen; + RTMP_STRING id_data[] = {"hello"}; + RTMP_STRING fail_data[] = {"EAP_FAIL"}; + RTMP_STRING wsc_start[] = {"WSC_START"}; +#ifdef WSC_V2_SUPPORT + RTMP_STRING wsc_frag_ack[] = "WSC_FRAG_ACK"; +#endif /* WSC_V2_SUPPORT */ + RTMP_STRING regIdentity[] = {"WFA-SimpleConfig-Registrar"}; + RTMP_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(RTMP_ADAPTER *pAd, WSC_CTRL *pWscControl, UCHAR apidx) +{ + UCHAR CurOpMode = 0xff; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscInitRegistrarPair\n")); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + CurOpMode = AP_MODE; +#endif // CONFIG_AP_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, pAd->ApCfg.MBSSID[apidx].wdev.bssid, 6); + } +#endif /* CONFIG_AP_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 */ + + + /* 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 */ + + + /* 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 (WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + pWscControl->RegData.SelfInfo.RfBand |= WSC_RFBAND_50GHZ; /* 5.0G */ + + if (WMODE_CAP_2G(pAd->CommonCfg.PhyMode)) + pWscControl->RegData.SelfInfo.RfBand |= WSC_RFBAND_24GHZ; /* 2.4G */ + + /* 16. Config Method */ + pWscControl->RegData.SelfInfo.ConfigMethods = cpu2be16(pWscControl->WscConfigMethods); + /*pWscControl->RegData.EnrolleeInfo.ConfigMethods = cpu2be16(WSC_CONFIG_METHODS); // Label, Display, PBC */ + /*pWscControl->RegData.EnrolleeInfo.ConfigMethods = cpu2be16(0x0084); // Label, Display, PBC */ + + /* 17. Simple Config State */ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + pWscControl->RegData.SelfInfo.ScState = pWscControl->WscConfStatus; +#endif /* CONFIG_AP_SUPPORT */ + + /* 18. Device Password ID */ + if (pWscControl->WscMode == WSC_PIN_MODE) + { + pWscControl->RegData.SelfInfo.DevPwdId = cpu2be16(DEV_PASS_ID_PIN); /* PIN mode */ + } + 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, pAd->ApCfg.MBSSID[apidx].Ssid, pAd->ApCfg.MBSSID[apidx].SsidLen); +#endif /* CONFIG_AP_SUPPORT */ + + /* 20. Primary Device Type */ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (pWscControl->EntryIfIdx & MIN_NET_DEVICE_FOR_APCLI) + NdisMoveMemory(&pWscControl->RegData.SelfInfo.PriDeviceType, &STA_Wsc_Pri_Dev_Type[0], 8); + else + NdisMoveMemory(&pWscControl->RegData.SelfInfo.PriDeviceType, &AP_Wsc_Pri_Dev_Type[0], 8); + } +#endif /* CONFIG_AP_SUPPORT */ + + + 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->func_tb_idx].WscControl; + MAKE_802_3_HEADER(Header802_3, + &pEntry->Addr[0], + &pAd->ApCfg.MBSSID[pEntry->func_tb_idx].wdev.bssid[0], + EAPOL); + } +#endif /* CONFIG_AP_SUPPORT */ + + + if (pWpsCtrl == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("pWpsCtrl == NULL!\n")); + return; + } + + /* Length, -1 NULL pointer of string */ + Length = sizeof(EAP_FRAME) + sizeof(Data) - 1; + + /* Zero 802.1x body */ + NdisZeroMemory(&Ieee_8021x, sizeof(Ieee_8021x)); + Ieee_8021x.Version = EAPOL_VER; + Ieee_8021x.Type = EAPPacket; + Ieee_8021x.Length = cpu2be16(Length); + + /* Zero EAP frame */ + NdisZeroMemory(&EapFrame, sizeof(EapFrame)); + /* RFC 3748 Ch 4.1: recommended to initalize Identifier with a + * random number */ + Id = RandomByte(pAd); + if (Id == pWpsCtrl->lastId) + Id += 1; + EapFrame.Code = EAP_CODE_REQ; + EapFrame.Id = Id; + EapFrame.Length = cpu2be16(Length); + EapFrame.Type = EAP_TYPE_ID; + pWpsCtrl->lastId = Id; + + /* Out buffer for transmitting EAP-Req(Identity) */ + os_alloc_mem(NULL, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER); + if(pOutBuffer == NULL) + return; + + FrameLen = 0; + + /* Make Transmitting frame */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(IEEE8021X_FRAME), &Ieee_8021x, + sizeof(EapFrame), &EapFrame, + (sizeof(Data) - 1), Data, + END_OF_ARGS); + + /* Copy frame to Tx ring */ + RTMPToWirelessSta(pAd, pEntry, Header802_3, sizeof(Header802_3), (PUCHAR)pOutBuffer, FrameLen, 0x80); /* To indicate this packet is EapReqId */ + + pWpsCtrl->WscRetryCount = 0; + if (pOutBuffer) + os_free_mem(NULL, pOutBuffer); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscSendEapReqId\n")); +} + +/* + ======================================================================== + + Routine Description: + Send EAPoL-Start packet to AP. + + Arguments: + pAd - NIC Adapter pointer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after link up + 1. Change the correct parameters + 2. Send EAPOL - START + + ======================================================================== +*/ +VOID WscSendEapolStart( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR pBssid, + IN UCHAR CurOpMode) +{ + IEEE8021X_FRAME Packet; + UCHAR Header802_3[14]; + MAC_TABLE_ENTRY *pEntry; + + pEntry = MacTableLookup(pAdapter, pBssid); + + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscSendEapolStart\n")); + + NdisZeroMemory(Header802_3,sizeof(UCHAR)*14); + + /* 1. Change the authentication to open and encryption to none if necessary. */ + + /* init 802.3 header and Fill Packet */ +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (CurOpMode == AP_MODE) + { + MAKE_802_3_HEADER(Header802_3, + pBssid, + &pAdapter->ApCfg.ApCliTab[0].wdev.if_addr[0], + EAPOL); + } +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + /* 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 */ + + 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"; +#if (defined(CONFIG_AP_SUPPORT) && defined(APCLI_SUPPORT)) || defined(CONFIG_STA_SUPPORT) + UCHAR CurOpMode = 0xff; +#endif + 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) +#ifdef APCLI_SUPPORT + CurOpMode = AP_MODE; +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + if (CurOpMode == AP_MODE) + { + MAKE_802_3_HEADER(Header802_3, + &pEntry->Addr[0], + &pAdapter->ApCfg.ApCliTab[0].wdev.if_addr[0], + EAPOL); + 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 */ + + + /* Zero 802.1x body */ + NdisZeroMemory(&Ieee_8021x, sizeof(Ieee_8021x)); + Ieee_8021x.Version = EAPOL_VER; + Ieee_8021x.Type = EAPPacket; + Ieee_8021x.Length = cpu2be16(Length); + + /* Zero EAP frame */ + NdisZeroMemory(&EapFrame, sizeof(EapFrame)); + EapFrame.Code = EAP_CODE_RSP; + EapFrame.Id = pWscControl->lastId; + EapFrame.Length = cpu2be16(Length); + EapFrame.Type = EAP_TYPE_ID; + + /* Out buffer for transmitting EAP-Req(Identity) */ + os_alloc_mem(NULL, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER); + if(pOutBuffer == NULL) + return; + + FrameLen = 0; + + if (pWscControl->WscConfMode == WSC_REGISTRAR) + { + /* Make tx frame */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(IEEE8021X_FRAME), &Ieee_8021x, + sizeof(EapFrame), &EapFrame, + (sizeof(regIdentity) - 1), regIdentity, + END_OF_ARGS); + } + else if (pWscControl->WscConfMode == WSC_ENROLLEE) + { + /* 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 */ + + + pWscControl->WscRetryCount = 0; + if (!pWscControl->EapolTimerRunning) + { + pWscControl->EapolTimerRunning = TRUE; + RTMPSetTimer(&pWscControl->EapolTimer, WSC_EAP_ID_TIME_OUT); + } +out: + if (pOutBuffer) + os_free_mem(NULL, pOutBuffer); + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscSendEapRspId\n")); +} + +VOID WscUPnPErrHandle( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl, + IN UINT eventID) +{ + int dataLen; + UCHAR *pWscData; + UCHAR CurOpMode; + + DBGPRINT(RT_DEBUG_TRACE, ("Into WscUPnPErrHandle, send WSC_OPCODE_UPNP_CTRL with eventID=0x%x!\n", eventID)); + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + CurOpMode = AP_MODE; +#endif // CONFIG_AP_SUPPORT // + + + os_alloc_mem(NULL, (UCHAR **)&pWscData, WSC_MAX_DATA_LEN); + if (pWscData != NULL) + { + NdisZeroMemory(pWscData, WSC_MAX_DATA_LEN); + + dataLen = BuildMessageNACK(pAd, pWscControl, pWscData); + WscSendUPnPMessage(pAd, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_DATA, WSC_UPNP_DATA_SUB_NORMAL, + pWscData, dataLen, eventID, 0, NULL, CurOpMode); + + os_free_mem(NULL, pWscData); + } + else + { + WscSendUPnPMessage(pAd, (pWscControl->EntryIfIdx & 0x0F), + WSC_OPCODE_UPNP_CTRL, 0, NULL, 0, eventID, 0, NULL, CurOpMode); + } +} + +/* + Format of iwcustom msg WSC clientJoin message: + 1. SSID which station want to probe(32 bytes): + + *If the length if SSID string is small than 32 bytes, fill 0x0 for remaining bytes. + 2. sender MAC address(6 bytes): + 3. Status: + Set as 1 means change APStatus as 1. + Set as 2 means change STAStatus as 1. + Set as 3 means trigger msg. + + 32 6 1 + +----------+--------+------+ + |SSIDString| SrcMAC |Status| +*/ +int WscSendUPnPConfReqMsg( + IN PRTMP_ADAPTER pAd, + IN UCHAR apIdx, + IN PUCHAR ssidStr, + IN PUCHAR macAddr, + IN INT Status, + IN UINT eventID, + IN UCHAR CurOpMode) +{ + UCHAR pData[39] = {0}; + + + strncpy((RTMP_STRING *) pData, (RTMP_STRING *)ssidStr, strlen((RTMP_STRING *) 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; + + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscSendUPnPMessage\n")); + + if ((msgType & WSC_OPCODE_UPNP_MASK) != WSC_OPCODE_UPNP_MASK) + return FALSE; + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { +#ifdef APCLI_SUPPORT + if (devIfIdx & MIN_NET_DEVICE_FOR_APCLI) + { + bssIdx &= (~MIN_NET_DEVICE_FOR_APCLI); + if (bssIdx >= MAX_APCLI_NUM) + return FALSE; + pDevAddr = &pAd->ApCfg.ApCliTab[bssIdx].wdev.if_addr[0]; + } + else +#endif /* APCLI_SUPPORT */ + pDevAddr = &pAd->ApCfg.MBSSID[bssIdx].wdev.bssid[0]; + } +#endif /* CONFIG_AP_SUPPORT */ + + 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 != 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) + { + if(pMACAddr != NULL) + { + NdisMoveMemory(pBufPtr, pMACAddr, MAC_ADDR_LEN); + pBufPtr += MAC_ADDR_LEN; + copyLen -= MAC_ADDR_LEN; + } + else + DBGPRINT(RT_DEBUG_ERROR, ("%s(): %d pMACAddr is NULL!\n", __FUNCTION__,__LINE__)); + } + NdisMoveMemory(pBufPtr, pPos, copyLen); + pPos += copyLen; + firstSeg = 0; + } else { + NdisMoveMemory(pBufPtr, pPos, pNLMsgHdr->segLen); + pPos += pNLMsgHdr->segLen; + } + + /*Send WSC Msg to wscd, msg length = pNLMsgHdr->segLen + sizeof(RTMP_WSC_NLMSG_HDR) */ + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, RT_WSC_UPNP_EVENT_FLAG, NULL, pBuf, pNLMsgHdr->segLen + sizeof(RTMP_WSC_NLMSG_HDR)); + } + + os_free_mem(NULL, pBuf); + } + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscSendUPnPMessage\n")); + return TRUE; +} + + +VOID WscSendMessage( + IN PRTMP_ADAPTER pAdapter, + IN UCHAR OpCode, + IN PUCHAR pData, + IN INT Len, + IN PWSC_CTRL pWscControl, + IN UCHAR OpMode, + IN UCHAR EapType) +{ + /* Inb-EAP Message */ + UCHAR Header802_3[14]; + USHORT Length, MsgLen; + IEEE8021X_FRAME Ieee_8021x; + EAP_FRAME EapFrame; + WSC_FRAME WscFrame; + UCHAR *pOutBuffer = NULL; + ULONG FrameLen = 0; + MAC_TABLE_ENTRY *pEntry; +#ifdef CONFIG_AP_SUPPORT + UCHAR bssIdx = (pWscControl->EntryIfIdx & 0x0F); +#endif /* CONFIG_AP_SUPPORT */ + UCHAR CurOpMode = 0xFF; + + if ((Len <= 0) && (OpCode != WSC_OPCODE_START) && (OpCode != WSC_OPCODE_FRAG_ACK)) + return; + + /* Send message */ + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscSendMessage\n")); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + CurOpMode = AP_MODE; +#endif /* CONFIG_AP_SUPPORT */ + + NdisZeroMemory(Header802_3,sizeof(UCHAR)*14); + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (OpMode == AP_MODE) + { + MAKE_802_3_HEADER(Header802_3, &pWscControl->EntryAddr[0], &pAdapter->ApCfg.MBSSID[bssIdx].wdev.bssid[0], EAPOL); + } +#ifdef APCLI_SUPPORT + else if (OpMode == AP_CLIENT_MODE) + { + MAKE_802_3_HEADER(Header802_3, &pWscControl->EntryAddr[0], &pAdapter->ApCfg.ApCliTab[0].wdev.if_addr[0], EAPOL); + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + /* 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; + + + /* 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 */ + + 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; + ieHdr.oui[3] = 0x04; + + pData = (PUCHAR) &Data[0]; + Len = 0; + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Simple Config State */ + templen = AppendWSCTLV(WSC_ID_SC_STATE, pData, (UINT8 *)&b_configured, 0); + pData += templen; + Len += templen; + +#ifdef CONFIG_AP_SUPPORT + if ((CurOpMode == AP_MODE) && pWpsCtrl->bSetupLock) + { + // AP Setup Lock + templen = AppendWSCTLV(WSC_ID_AP_SETUP_LOCKED, pData, (UINT8 *)&pWpsCtrl->bSetupLock, 0); + pData += templen; + Len += templen; + } +#endif /* CONFIG_AP_SUPPORT */ + + if ( b_selRegistrar ) + { + /* 3.Selected Registrar */ + templen = AppendWSCTLV(WSC_ID_SEL_REGISTRAR, pData, (UINT8 *)&b_selRegistrar, 0); + pData += templen; + Len += templen; + + /*4. Device Password ID */ + tempVal = htons(devPwdId); + templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + + /* 5. Selected Registrar Config Methods */ + tempVal = selRegCfgMethods; + tempVal = htons(tempVal); + templen = AppendWSCTLV(WSC_ID_SEL_REG_CFG_METHODS, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + } + + /* 6. UUID last 6 bytes use MAC */ + templen = AppendWSCTLV(WSC_ID_UUID_E, pData, &pWpsCtrl->Wsc_Uuid_E[0], 0); + pData += templen; + Len += templen; + + /* 7. RF Bands */ + if (CurOpMode == AP_MODE) + { + if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + tempVal = 2; + else + tempVal = 1; + } + else + { + if (pAd->CommonCfg.Channel > 14) + tempVal = 2; + else + tempVal = 1; + } + +#ifdef RT_BIG_ENDIAN + tempVal =SWAP16(tempVal); +#endif /* RT_BIG_ENDIAN */ + templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + + +#ifdef WSC_V2_SUPPORT + if (pWpsCtrl && pWpsCtrl->WscV2Info.bEnableWpsV2) + { + PWSC_TLV pWscTLV = &pWpsCtrl->WscV2Info.ExtraTlv; + WscGenV2Msg(pWpsCtrl, + b_selRegistrar, + pAuthorizedMACs, + AuthorizedMACsLen, + &pData, + &Len); + + /* Extra attribute that is not defined in WSC Sepc. */ + if (pWscTLV->pTlvData && pWscTLV->TlvLen) + { + templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen); + pData += templen; + Len += templen; + } + } +#endif /* WSC_V2_SUPPORT */ + + + + ieHdr.length = ieHdr.length + Len; + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + memcpy(pAd->ApCfg.MBSSID[apidx].WscIEBeacon.Value, &ieHdr, sizeof(WSC_IE_HEADER)); + memcpy(pAd->ApCfg.MBSSID[apidx].WscIEBeacon.Value + sizeof(WSC_IE_HEADER), Data, Len); + pAd->ApCfg.MBSSID[apidx].WscIEBeacon.ValueLen = sizeof(WSC_IE_HEADER) + Len; + } +#endif /* CONFIG_AP_SUPPORT */ + + + 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 = NULL; + PUCHAR pData; + INT Len = 0, templen = 0; + USHORT tempVal = 0; + PWSC_CTRL pWpsCtrl = NULL; + PWSC_REG_DATA pReg = NULL; + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&Data, 512); + if (Data == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + pWpsCtrl = &pAd->ApCfg.MBSSID[apidx & 0x0F].WscControl; +#endif /* CONFIG_AP_SUPPORT */ + + 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; + ieHdr.oui[3] = 0x04; + + pData = (PUCHAR) &Data[0]; + Len = 0; + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Simple Config State */ + templen = AppendWSCTLV(WSC_ID_SC_STATE, pData, (UINT8 *)&scState, 0); + pData += templen; + Len += templen; + +#ifdef CONFIG_AP_SUPPORT + if ((CurOpMode == AP_MODE) && pWpsCtrl->bSetupLock) + { + // AP Setup Lock + templen = AppendWSCTLV(WSC_ID_AP_SETUP_LOCKED, pData, (UINT8 *)&pWpsCtrl->bSetupLock, 0); + pData += templen; + Len += templen; + } +#endif /* CONFIG_AP_SUPPORT */ + + if ( b_selRegistrar ) + { + /* 3. Selected Registrar */ + templen = AppendWSCTLV(WSC_ID_SEL_REGISTRAR, pData, (UINT8 *)&b_selRegistrar, 0); + pData += templen; + Len += templen; + + /* 4. Device Password ID */ + tempVal = htons(devPwdId); + templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + + /* 5. Selected Registrar Config Methods */ + tempVal = htons(selRegCfgMethods); + templen = AppendWSCTLV(WSC_ID_SEL_REG_CFG_METHODS, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + + } + + /* 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((RTMP_STRING *) 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((RTMP_STRING *) 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((RTMP_STRING *) 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((RTMP_STRING *) 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((RTMP_STRING *) pReg->SelfInfo.DeviceName)); + pData += templen; + Len += templen; + + /* 14. Config Methods */ + /*tempVal = htons(0x008a); */ + /*tempVal = htons(0x0084); */ + { + /* + WSC 1.0 WCN logo testing will check the value of config method in probe response and M1. + Config method shall be identical in probe response and M1. + */ +#ifdef WSC_V2_SUPPORT + if(pWpsCtrl) + { + if (pWpsCtrl->WscV2Info.bEnableWpsV2) + tempVal = pWpsCtrl->WscConfigMethods & 0xF97F; + else +#endif /* WSC_V2_SUPPORT */ + tempVal = pWpsCtrl->WscConfigMethods & 0x00FF; +#ifdef WSC_V2_SUPPORT + } +#endif /* WSC_V2_SUPPORT */ + } + + tempVal = htons(tempVal); + templen = AppendWSCTLV(WSC_ID_CONFIG_METHODS, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + + + /* 15. RF Bands */ + if (CurOpMode == AP_MODE) + { + if (WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + tempVal = 2; + else + tempVal = 1; + } + else + { + if (pAd->CommonCfg.Channel > 14) + tempVal = 2; + else + tempVal = 1; + } +#ifdef RT_BIG_ENDIAN + tempVal =SWAP16(tempVal); +#endif /* RT_BIG_ENDIAN */ + templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + + +#ifdef WSC_V2_SUPPORT + if (pWpsCtrl && pWpsCtrl->WscV2Info.bEnableWpsV2) + { + PWSC_TLV pWscTLV = &pWpsCtrl->WscV2Info.ExtraTlv; + WscGenV2Msg(pWpsCtrl, + b_selRegistrar, + pAuthorizedMACs, + AuthorizedMACsLen, + &pData, + &Len); + + /* Extra attribute that is not defined in WSC Sepc. */ + if (pWscTLV->pTlvData && pWscTLV->TlvLen) + { + templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen); + pData += templen; + Len += templen; + } + } +#endif /* WSC_V2_SUPPORT */ + + + if (Len > 251) + { + DBGPRINT(RT_DEBUG_TRACE, ("Len is overflow!\n")); + } + + ieHdr.length = ieHdr.length + Len; + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + memcpy(pAd->ApCfg.MBSSID[apidx & 0xF].WscIEProbeResp.Value, &ieHdr, sizeof(WSC_IE_HEADER)); + memcpy(pAd->ApCfg.MBSSID[apidx & 0xF].WscIEProbeResp.Value + sizeof(WSC_IE_HEADER), Data, Len); + pAd->ApCfg.MBSSID[apidx & 0xF].WscIEProbeResp.ValueLen = sizeof(WSC_IE_HEADER) + Len; + } +#endif /* CONFIG_AP_SUPPORT */ + + + 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_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + MAKE_802_3_HEADER(Header802_3, + &pWscControl->EntryAddr[0], + &pAd->ApCfg.MBSSID[apidx].wdev.bssid[0], + EAPOL); + } +#endif /* CONFIG_AP_SUPPORT */ + + + /* Length, -1 type size, Eap-Fail doesn't need Type item */ + Length = sizeof(EAP_FRAME) - sizeof(UCHAR); + + /* Zero 802.1x body */ + NdisZeroMemory(&Ieee_8021x, sizeof(Ieee_8021x)); + Ieee_8021x.Version = EAPOL_VER; + Ieee_8021x.Type = EAPPacket; + Ieee_8021x.Length = cpu2be16(Length); + + /* Zero EAP frame */ + NdisZeroMemory(&EapFrame, sizeof(EapFrame)); + EapFrame.Code = EAP_CODE_FAIL; + EapFrame.Id = pWscControl->lastId; + EapFrame.Length = cpu2be16(Length); + + /* Out buffer for transmitting EAP-Req(Identity) */ + os_alloc_mem(NULL, (UCHAR **)&pOutBuffer, MAX_LEN_OF_MLME_BUFFER); + if(pOutBuffer == NULL) + return; + + FrameLen = 0; + + /* Make Transmitting frame */ + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(IEEE8021X_FRAME), &Ieee_8021x, + sizeof(EapFrame)-1, &EapFrame, END_OF_ARGS); + + pEntry = MacTableLookup(pAd, &pWscControl->EntryAddr[0]); + /* Copy frame to Tx ring */ + RTMPToWirelessSta(pAd, pEntry, Header802_3, sizeof(Header802_3), (PUCHAR)pOutBuffer, FrameLen, TRUE); + + + if (pOutBuffer) + os_free_mem(NULL, pOutBuffer); + +#ifdef CONFIG_AP_SUPPORT + if (pEntry && bSendDeAuth && (CurOpMode == AP_MODE)) + { + MlmeDeAuthAction(pAd, pEntry, REASON_DEAUTH_STA_LEAVING, TRUE); + } + if (pEntry == NULL) + { + /* + If STA dis-connect un-normally, reset EntryAddr here. + */ + NdisZeroMemory(pWscControl->EntryAddr, MAC_ADDR_LEN); + } +#endif /* CONFIG_AP_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscSendEapFail\n")); +} + +#ifdef CONFIG_AP_SUPPORT +VOID WscBuildAssocRespIE( + IN PRTMP_ADAPTER pAd, + IN UCHAR ApIdx, + IN UCHAR Reason, + OUT PUCHAR pOutBuf, + OUT PUCHAR pIeLen) +{ + WSC_IE_HEADER ieHdr; +/* UCHAR Data[512] = {0}; */ + UCHAR *Data = NULL; + PUCHAR pData; + INT Len = 0, templen = 0; + UINT8 tempVal = 0; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pAd->ApCfg.MBSSID[ApIdx].WscControl.RegData; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscBuildAssocRespIE\n")); + + /* allocate memory */ + os_alloc_mem(NULL, (UCHAR **)&Data, 512); + if (Data == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + return; + } + Data[0] = 0; + + /* WSC IE Header */ + ieHdr.elemId = 221; + ieHdr.length = 4; + ieHdr.oui[0] = 0x00; ieHdr.oui[1] = 0x50; + ieHdr.oui[2] = 0xF2; ieHdr.oui[3] = 0x04; + + pData = (PUCHAR) &Data[0]; + Len = 0; + + /* Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* Request Type */ + tempVal = WSC_MSGTYPE_AP_WLAN_MGR; + templen = AppendWSCTLV(WSC_ID_RESP_TYPE, pData, (UINT8 *)&tempVal, 0); + pData += templen; + Len += templen; + +#ifdef WSC_V2_SUPPORT + if (pAd->ApCfg.MBSSID[ApIdx].WscControl.WscV2Info.bEnableWpsV2) + { + WscGenV2Msg(&pAd->ApCfg.MBSSID[ApIdx].WscControl, + FALSE, + NULL, + 0, + &pData, + &Len); + } +#endif /* WSC_V2_SUPPORT */ + + + ieHdr.length = ieHdr.length + Len; + NdisMoveMemory(pOutBuf, &ieHdr, sizeof(WSC_IE_HEADER)); + NdisMoveMemory(pOutBuf + sizeof(WSC_IE_HEADER), Data, Len); + *pIeLen = sizeof(WSC_IE_HEADER) + Len; + + if (Data != NULL) + os_free_mem(NULL, Data); + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscBuildAssocRespIE\n")); +} + + +VOID WscSelectedRegistrar( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pReginfo, + IN UINT Length, + IN UCHAR apidx) +{ + PUCHAR pData; + //INT IsAPConfigured; + UCHAR /*wsc_version,*/ wsc_sel_reg = 0; + USHORT wsc_dev_pass_id = 0, wsc_sel_reg_conf_mthd = 0; + USHORT WscType, WscLen; + PUCHAR pAuthorizedMACs = NULL; + UCHAR AuthorizedMACsLen = 0; + PWSC_CTRL pWscCtrl = &pAd->ApCfg.MBSSID[apidx].WscControl; + + pData = (PUCHAR)pReginfo; + + if (Length < 4) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscSelectedRegistrar --> Unknown IE \n")); + return; + } + + hex_dump("WscSelectedRegistrar - Reginfo", pReginfo, Length); + while (Length > 4) + { + /* arm-cpu has packet alignment issue, it's better to use memcpy to retrieve data */ + NdisMoveMemory(&WscType, pData, 2); + NdisMoveMemory(&WscLen, pData + 2, 2); + WscLen = ntohs(WscLen); + pData += 4; + Length -= 4; + switch (ntohs(WscType)) + { + case WSC_ID_VERSION: + //wsc_version = *pData; + break; + + case WSC_ID_SEL_REGISTRAR: + wsc_sel_reg = *pData; + break; + + case WSC_ID_DEVICE_PWD_ID: + NdisMoveMemory(&wsc_dev_pass_id, pData, sizeof(USHORT)); + wsc_dev_pass_id = be2cpu16(wsc_dev_pass_id); + break; + + case WSC_ID_SEL_REG_CFG_METHODS: + NdisMoveMemory(&wsc_sel_reg_conf_mthd, pData, sizeof(USHORT)); + wsc_sel_reg_conf_mthd = be2cpu16(wsc_sel_reg_conf_mthd); + break; + + case WSC_ID_VENDOR_EXT: +#ifdef WSC_V2_SUPPORT + if (pWscCtrl->WscV2Info.bEnableWpsV2 && (WscLen > 0)) + { + /* + Find WFA_EXT_ID_AUTHORIZEDMACS + */ + if(pAuthorizedMACs != NULL) + { + os_free_mem(NULL, pAuthorizedMACs); + pAuthorizedMACs = NULL; + } + 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 + if(pAuthorizedMACs != NULL) + { + 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, + (RT_LIST_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 */ + + +/* + ======================================================================== + + Routine Description: + Make WSC IE for the ProbeReq frame + + Arguments: + pAd - NIC Adapter pointer + pOutBuf - all of WSC IE field + pIeLen - length + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + None + + ======================================================================== +*/ +VOID WscBuildProbeReqIE( + IN PRTMP_ADAPTER pAd, + IN UCHAR CurOpMode, + IN PWSC_CTRL pWpsCtrl, + OUT PUCHAR pOutBuf, + OUT PUCHAR pIeLen) +{ +/* UCHAR WscIEFixed[] = {0xdd, 0x0e, 0x00, 0x50, 0xf2, 0x04}; // length will modify later */ + WSC_IE_HEADER ieHdr; +/* UCHAR OutMsgBuf[512]; // buffer to create message contents */ + UCHAR *OutMsgBuf = NULL; /* buffer to create message contents */ + INT Len =0, templen = 0; + PUCHAR pData; + USHORT tempVal = 0; + + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWpsCtrl->RegData; + + + 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; + 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 (pWpsCtrl->WscConfMode == WSC_REGISTRAR) + tempVal = WSC_MSGTYPE_REGISTRAR; + else if (pWpsCtrl->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 (pWpsCtrl->WscV2Info.bEnableWpsV2) + { +#ifdef APCLI_SUPPORT + if (pWpsCtrl->bWscTrigger) + { + DBGPRINT(RT_DEBUG_INFO, ("WscBuildProbeReqIE : Apclient WPS2 enable trigger\n")); + if (pWpsCtrl->WscMode == WSC_PIN_MODE) + { + tempVal = (pWpsCtrl->WscConfigMethods & 0x200F); + } + else + { + DBGPRINT(RT_DEBUG_INFO, ("WscBuildProbeReqIE : Apclient WPS2 enable trigger & PBC mode\n")); + tempVal = (pWpsCtrl->WscConfigMethods & 0x02F0); + } + } + else + tempVal = pWpsCtrl->WscConfigMethods; +#else + tempVal = pWpsCtrl->WscConfigMethods; +#endif /* APCLI_SUPPORT */ + } + else +#endif /* WSC_V2_SUPPORT */ + { + tempVal = (pWpsCtrl->WscConfigMethods & 0x00FF); + } + + + 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 WSC_V2_SUPPORT + if (pWpsCtrl->WscV2Info.bEnableWpsV2) + { + /* 10. Manufacturer */ + NdisZeroMemory(pData, 64 + 4); + templen = AppendWSCTLV(WSC_ID_MANUFACTURER, pData, pReg->SelfInfo.Manufacturer, strlen((RTMP_STRING *) 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((RTMP_STRING *) 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((RTMP_STRING *) 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((RTMP_STRING *) pReg->SelfInfo.DeviceName)); + pData += templen; + Len += templen; + + /* Version2 */ + WscGenV2Msg(pWpsCtrl, + 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; + 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")); +} + + +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_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]; + STA_TR_ENTRY *tr_entry = &pAdapter->MacTab.tr_entry[i]; + + if ( IS_ENTRY_APCLI(pEntry) && + (pEntry->Sst == SST_ASSOC) && + (tr_entry->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 */ + + + 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)); + } + } +} + +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) { +#ifdef APCLI_SUPPORT + if (pWscControl->WscApCliScanMode != TRIGGER_PARTIAL_SCAN) +#endif /* APCLI_SUPPORT */ + { + { + 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 */ +#ifdef WSC_STA_SUPPORT + if (pWscControl->WscState != WSC_STATE_OFF) { + RTMPSetTimer(&pWscControl->WscPINTimer, 10000); + pWscControl->WscPINTimerRunning = TRUE; + } + +#endif + } + + 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->func_tb_idx >= pAd->ApCfg.BssidNum) + return; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscInformFromWPA\n")); + + if (MAC_ADDR_EQUAL(pEntry->Addr, pAd->ApCfg.MBSSID[pEntry->func_tb_idx].WscControl.EntryAddr)) + { + NdisZeroMemory(pAd->ApCfg.MBSSID[pEntry->func_tb_idx].WscControl.EntryAddr, MAC_ADDR_LEN); + RTMPCancelTimer(&pAd->ApCfg.MBSSID[pEntry->func_tb_idx].WscControl.EapolTimer, &Cancelled); + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].WscControl.EapolTimerRunning = FALSE; + pEntry->bWscCapable = FALSE; + pAd->ApCfg.MBSSID[pEntry->func_tb_idx].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 */ + + + + 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 + WscPBCSessionOverlapClear(pAd); + + 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; + +/* WPS_BandSteering Support */ +#ifdef CONFIG_AP_SUPPORT +#ifdef BAND_STEERING + /* WPS: clear WPS WHITELIST in case of AP Wsc Stop */ + if (!bFromApCli && (pAd->ApCfg.BandSteering)) { + + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[pWscControl->EntryIfIdx & 0x0F].wdev; + PBND_STRG_CLI_TABLE table = Get_BndStrgTable(pAd, wdev->func_idx); + + if (table && table->bEnabled) { + NdisAcquireSpinLock(&table->WpsWhiteListLock); + ClearWpsWhiteList(&table->WpsWhiteList); + NdisReleaseSpinLock(&table->WpsWhiteListLock); + MTWF_LOG(DBG_CAT_SEC, CATSEC_WPS, DBG_LVL_TRACE, ("%s:channel %u wps whitelist cleared, size : %d\n", + __func__, table->Channel, table->WpsWhiteList.size)); + } + } +#endif +#endif /* CONFIG_AP_SUPPORT */ + + if (pWscControl->WscScanTimerRunning) + { + pWscControl->WscScanTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->WscScanTimer, &Cancelled); + } + + if (pWscControl->WscPBCTimerRunning) + { + pWscControl->WscPBCTimerRunning = FALSE; + RTMPCancelTimer(&pWscControl->WscPBCTimer, &Cancelled); + } + + +#ifdef WSC_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 */ + +} + +VOID WscInit( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromApCli, + IN UCHAR BssIndex) +{ + IN PWSC_CTRL pWscControl = NULL; + 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 */ + + + 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; + + + pWscControl->WscStatus = STATUS_WSC_IDLE; +#ifdef CONFIG_AP_SUPPORT + if (((CurOpMode == AP_MODE) && + (pWscControl->WscConfMode == WSC_DISABLE)) +#ifdef WSC_V2_SUPPORT + || ((pWscControl->WscV2Info.bWpsEnable == FALSE) && pWscControl->WscV2Info.bEnableWpsV2) +#endif /* WSC_V2_SUPPORT */ + ) + { + if (CurOpMode == AP_MODE) + { +#ifdef APCLI_SUPPORT + if (!bFromApCli) +#endif /* APCLI_SUPPORT */ + { + pAd->ApCfg.MBSSID[BssIndex & 0x0F].WscIEBeacon.ValueLen = 0; + pAd->ApCfg.MBSSID[BssIndex & 0x0F].WscIEProbeResp.ValueLen = 0; + } + } + } + else +#endif /* CONFIG_AP_SUPPORT */ + { + + WscInitRegistrarPair(pAd, pWscControl, BssIndex); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { +#ifdef APCLI_SUPPORT + if (!bFromApCli) +#endif /* APCLI_SUPPORT */ + { + IsAPConfigured = pWscControl->WscConfStatus; + WscBuildBeaconIE(pAd, IsAPConfigured, FALSE, 0, 0, (BssIndex & 0x0F), NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, FALSE, 0, 0, BssIndex, NULL, 0, AP_MODE); + APUpdateBeaconFrame(pAd, pWscControl->EntryIfIdx & 0x0F); + } + } +#endif /* CONFIG_AP_SUPPORT */ + } +#ifdef WSC_NFC_SUPPORT + pWscControl->bTriggerByNFC = FALSE; + pWscControl->bRegenPublicKey = FALSE; + NdisZeroMemory(&pWscControl->NfcPasswd[0], NFC_DEV_PASSWD_LEN); +#endif /* WSC_NFC_SUPPORT */ +} + +USHORT WscGetAuthType( + IN NDIS_802_11_AUTHENTICATION_MODE authType) +{ + switch(authType) + { + case Ndis802_11AuthModeOpen: + return WSC_AUTHTYPE_OPEN; + case Ndis802_11AuthModeWPAPSK: + return WSC_AUTHTYPE_WPAPSK; + case Ndis802_11AuthModeShared: + return WSC_AUTHTYPE_SHARED; + case Ndis802_11AuthModeWPANone: + return WSC_AUTHTYPE_WPANONE; + case Ndis802_11AuthModeWPA: + return WSC_AUTHTYPE_WPA; + case Ndis802_11AuthModeWPA1WPA2: + return (WSC_AUTHTYPE_WPA | WSC_AUTHTYPE_WPA2); + case Ndis802_11AuthModeWPA2: + return WSC_AUTHTYPE_WPA2; + case Ndis802_11AuthModeWPA1PSKWPA2PSK: + return (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK); + case Ndis802_11AuthModeWPA2PSK: + return WSC_AUTHTYPE_WPA2PSK; + default: + return WSC_AUTHTYPE_OPEN; + } +} + +USHORT WscGetEncryType( + IN NDIS_802_11_WEP_STATUS encryType) +{ + switch(encryType) + { + case Ndis802_11WEPDisabled: + return WSC_ENCRTYPE_NONE; + case Ndis802_11WEPEnabled: + return WSC_ENCRTYPE_WEP; + case Ndis802_11TKIPEnable: + return WSC_ENCRTYPE_TKIP; + case Ndis802_11TKIPAESMix: + return (WSC_ENCRTYPE_AES | WSC_ENCRTYPE_TKIP); + default: + case Ndis802_11AESEnable: + return WSC_ENCRTYPE_AES; + } +} + +RTMP_STRING *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"; + } +} + +RTMP_STRING *WscGetEncryTypeStr( + IN USHORT encryFlag) +{ + switch(encryFlag) + { + case WSC_ENCRTYPE_NONE: + return "NONE"; + case WSC_ENCRTYPE_WEP: + return "WEP"; + case WSC_ENCRTYPE_TKIP: + return "TKIP"; + default: + case (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES): + return "TKIPAES"; + case WSC_ENCRTYPE_AES: + return "AES"; + } +} + +NDIS_802_11_AUTHENTICATION_MODE WscGetAuthMode( + IN USHORT authFlag) +{ + switch(authFlag) + { + case WSC_AUTHTYPE_OPEN: + return Ndis802_11AuthModeOpen; + case WSC_AUTHTYPE_WPAPSK: + return Ndis802_11AuthModeWPAPSK; + case WSC_AUTHTYPE_SHARED: + return Ndis802_11AuthModeShared; + case WSC_AUTHTYPE_WPANONE: + return Ndis802_11AuthModeWPANone; + case WSC_AUTHTYPE_WPA: + return Ndis802_11AuthModeWPA; + case WSC_AUTHTYPE_WPA2: + return Ndis802_11AuthModeWPA2; + default: + case (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK): + return Ndis802_11AuthModeWPA1PSKWPA2PSK; + case WSC_AUTHTYPE_WPA2PSK: + return Ndis802_11AuthModeWPA2PSK; + } +} + +NDIS_802_11_WEP_STATUS WscGetWepStatus( + IN USHORT encryFlag) +{ + switch(encryFlag) + { + case WSC_ENCRTYPE_NONE: + return Ndis802_11WEPDisabled; + case WSC_ENCRTYPE_WEP: + return Ndis802_11WEPEnabled; + case WSC_ENCRTYPE_TKIP: + return Ndis802_11TKIPEnable; + default: + case (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES): + return Ndis802_11TKIPAESMix; + case WSC_ENCRTYPE_AES: + return Ndis802_11AESEnable; + } +} + +void WscWriteConfToPortCfg( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl, + IN PWSC_CREDENTIAL pCredential, + IN BOOLEAN bEnrollee) +{ + UCHAR CurApIdx = MAIN_MBSSID; + UCHAR CurOpMode = AP_MODE; + + DBGPRINT(RT_DEBUG_TRACE, ("-----> WscWriteConfToPortCfg\n")); + + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + CurApIdx = (pWscControl->EntryIfIdx & 0x0F); + } +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + if (bEnrollee || (CurOpMode == AP_MODE)) + { + if (CurOpMode == AP_MODE) + { + NdisZeroMemory(pAd->ApCfg.MBSSID[CurApIdx].Ssid, MAX_LEN_OF_SSID); + NdisMoveMemory(pAd->ApCfg.MBSSID[CurApIdx].Ssid, pCredential->SSID.Ssid, pCredential->SSID.SsidLength); + pAd->ApCfg.MBSSID[CurApIdx].SsidLen = pCredential->SSID.SsidLength; + } +#endif /* CONFIG_AP_SUPPORT */ + + + 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_AP_SUPPORT +#ifdef WSC_V2_SUPPORT + if ((CurOpMode == AP_MODE) && (pWscControl->WscV2Info.bEnableWpsV2)) + { + if (pCredential->AuthType == WSC_AUTHTYPE_WPAPSK) + pCredential->AuthType = (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK); + if (pCredential->EncrType == WSC_ENCRTYPE_TKIP) + pCredential->EncrType = (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES); + } +#endif /* WSC_V2_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + } + WscSetAuthMode(pAd, CurOpMode, CurApIdx, WscGetAuthTypeStr(pCredential->AuthType)); + WscSetEncrypType(pAd, CurOpMode, CurApIdx, WscGetEncryTypeStr(pCredential->EncrType)); + if (pCredential->EncrType != WSC_ENCRTYPE_NONE) + { + if (pCredential->EncrType & (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES)) + { +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + pAd->ApCfg.MBSSID[CurApIdx].wdev.DefaultKeyId = 1; +#endif /* CONFIG_AP_SUPPORT */ + + if (pCredential->KeyLength >= 8 && pCredential->KeyLength <= 64) + { + UCHAR *pPMKBuf = NULL, *pSSIDStr = NULL; + INT ssidLen = 0; + RTMP_STRING PassphraseStr[65] = {0}; + + pWscControl->WpaPskLen = pCredential->KeyLength; + RTMPZeroMemory(pWscControl->WpaPsk, 64); + RTMPMoveMemory(pWscControl->WpaPsk, pCredential->Key, pWscControl->WpaPskLen); + RTMPMoveMemory(PassphraseStr, pCredential->Key, pWscControl->WpaPskLen); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + pPMKBuf = pAd->ApCfg.MBSSID[CurApIdx].PMK; + pSSIDStr = (PUCHAR)pAd->ApCfg.MBSSID[CurApIdx].Ssid; + ssidLen = pAd->ApCfg.MBSSID[CurApIdx].SsidLen; + RTMPZeroMemory(pAd->ApCfg.MBSSID[CurApIdx].WPAKeyString, 65); + RTMPMoveMemory(pAd->ApCfg.MBSSID[CurApIdx].WPAKeyString, pCredential->Key, pWscControl->WpaPskLen); + } +#endif /* CONFIG_AP_SUPPORT */ + RT_CfgSetWPAPSKKey(pAd, pCredential->Key, pWscControl->WpaPskLen, pSSIDStr, ssidLen, pPMKBuf); + DBGPRINT(RT_DEBUG_TRACE, ("WpaPskLen = %d\n", pWscControl->WpaPskLen)); + } + else + { + pWscControl->WpaPskLen = 0; + DBGPRINT(RT_DEBUG_TRACE, ("WPAPSK: Invalid Key Length (%d)\n", pCredential->KeyLength)); + } + } + else if (pCredential->EncrType == WSC_ENCRTYPE_WEP) + { + UCHAR WepKeyId = 0; + USHORT WepKeyLen = pCredential->KeyLength; + + if ((pCredential->KeyIndex >= 1) && (pCredential->KeyIndex <= 4)) + { + WepKeyId = (pCredential->KeyIndex - 1); /* KeyIndex = 1 ~ 4 */ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + pAd->ApCfg.MBSSID[CurApIdx].wdev.DefaultKeyId = WepKeyId; +#endif /* CONFIG_AP_SUPPORT */ + + /* 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((RTMP_STRING *) pCredential->Key, pAd->SharedKey[CurApIdx][WepKeyId].Key, WepKeyLen/2); + if (WepKeyLen == 10) + pAd->SharedKey[CurApIdx][WepKeyId].CipherAlg = CIPHER_WEP64; + else + pAd->SharedKey[CurApIdx][WepKeyId].CipherAlg = CIPHER_WEP128; + } + } + else + DBGPRINT(RT_DEBUG_TRACE, ("WEP: Invalid Key Length (%d)\n", pCredential->KeyLength)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Unsupport default key index (%d)\n", WepKeyId)); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + pAd->ApCfg.MBSSID[CurApIdx].wdev.DefaultKeyId = 0; +#endif /* CONFIG_AP_SUPPORT */ + + } + } + } +#ifdef CONFIG_AP_SUPPORT + } +#endif /* CONFIG_AP_SUPPORT */ + + + DBGPRINT(RT_DEBUG_TRACE, ("<----- ra%d - WscWriteConfToPortCfg\n", CurApIdx)); +} + + +VOID WscWriteSsidToDatFile( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *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_AP_SUPPORT + else + { + RTMP_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 RTMP_STRING *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_AP_SUPPORT + else + { + RTMP_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((RTMP_STRING *) tempPIN, sizeof(tempPIN), "00000000"); + memcpy(pWscControl->RegData.PIN, tempPIN, 8); + pWscControl->RegData.PinCodeLen = 8; + } + else + { + if ( pWscControl->WscPinCodeLen == 4) + { + UCHAR temp4PIN[5] = {0}; + snprintf((RTMP_STRING *) temp4PIN, sizeof(temp4PIN), "%04u", pWscControl->WscPinCode); + memcpy(pWscControl->RegData.PIN, temp4PIN, 4); + pWscControl->RegData.PinCodeLen = 4; + } + else + { + snprintf((RTMP_STRING *) 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 */ + + + if (WscData) + os_free_mem(NULL, WscData); + + /* RTMPCancelTimer(&pWscControl->EapolTimer, &Cancelled); */ + /* pWscControl->EapolTimerRunning = FALSE; */ +} + + +VOID WscGetConfigErrFromNack( + IN RTMP_ADAPTER *pAdapter, + IN MLME_QUEUE_ELEM *pElem, + OUT USHORT *pConfigError) +{ + USHORT Length = 0; + PUCHAR pData; + USHORT WscType, WscLen, ConfigError = 0; + + pData = pElem->Msg; + Length = pElem->MsgLen; + + while (Length > 4) + { + WSC_IE TLV_Recv; + memcpy((UINT8 *)&TLV_Recv, pData, 4); + WscType = be2cpu16(TLV_Recv.Type); + WscLen = be2cpu16(TLV_Recv.Length); + pData += 4; + Length -= 4; + + if (WscType == WSC_ID_CONFIG_ERROR) + { + NdisMoveMemory(&ConfigError, pData, sizeof(USHORT)); + DBGPRINT(RT_DEBUG_TRACE, ("WSC_ID_CONFIG_ERROR: %d\n", ntohs(ConfigError))); + *pConfigError = ntohs(ConfigError); + return; + } + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + DBGPRINT(RT_DEBUG_TRACE, ("WSC_ID_CONFIG_ERROR is missing\n")); +} + + +INT WscSetAuthMode( + IN PRTMP_ADAPTER pAd, + IN UCHAR CurOpMode, + IN UCHAR apidx, + IN RTMP_STRING *arg) +{ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + UINT32 i; + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + + if (rtstrcasecmp(arg, "WEPAUTO") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeAutoSwitch; + else if (rtstrcasecmp(arg, "OPEN") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeOpen; + else if (rtstrcasecmp(arg, "SHARED") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeShared; + else if (rtstrcasecmp(arg, "WPAPSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPAPSK; + else if (rtstrcasecmp(arg, "WPA") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA; + else if (rtstrcasecmp(arg, "WPA2PSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA2PSK; + else if (rtstrcasecmp(arg, "WPA2") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA2; + else if (rtstrcasecmp(arg, "WPA1WPA2") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA1WPA2; + else if (rtstrcasecmp(arg, "WPAPSKWPA2PSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPA1PSKWPA2PSK; + else + { + wdev->AuthMode = Ndis802_11AuthModeOpen; + DBGPRINT(RT_DEBUG_TRACE, ("%s: Unknow AuthMode (%s), set AuthMode to OPEN\n", __FUNCTION__, arg)); + } + + for (i=0; iMacTab.Content[i])) + { + pAd->MacTab.tr_entry[i].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + } + } + pAd->ApCfg.MBSSID[apidx].wdev.PortSecured = WPA_802_1X_PORT_NOT_SECURED; + /*RTMPMakeRSNIE(pAd, pAd->ApCfg.MBSSID[apidx].AuthMode, pAd->ApCfg.MBSSID[apidx].WepStatus, apidx); */ + + wdev->DefaultKeyId = 0; + + if(wdev->AuthMode >= Ndis802_11AuthModeWPA) + wdev->DefaultKeyId = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) %s::(AuthMode=%d)\n", apidx, __FUNCTION__, wdev->AuthMode)); + } +#endif /* CONFIG_AP_SUPPORT */ + + + return TRUE; +} + +INT WscSetEncrypType( + IN PRTMP_ADAPTER pAd, + IN UCHAR CurOpMode, + IN UCHAR apidx, + IN RTMP_STRING *arg) +{ +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + + if (rtstrcasecmp(arg, "NONE") == TRUE) + wdev->WepStatus = Ndis802_11WEPDisabled; + else if (rtstrcasecmp(arg, "WEP") == TRUE) + wdev->WepStatus = Ndis802_11WEPEnabled; + else if (rtstrcasecmp(arg, "TKIP") == TRUE) + wdev->WepStatus = Ndis802_11TKIPEnable; + else if (rtstrcasecmp(arg, "AES") == TRUE) + wdev->WepStatus = Ndis802_11AESEnable; + else if (rtstrcasecmp(arg, "TKIPAES") == TRUE) + wdev->WepStatus = Ndis802_11TKIPAESMix; + else + { + wdev->WepStatus = Ndis802_11WEPDisabled; + DBGPRINT(RT_DEBUG_TRACE, ("%s: Unknow EncrypType (%s), set EncrypType to NONE\n", __FUNCTION__, arg)); + } + + if (wdev->WepStatus >= Ndis802_11TKIPEnable) + wdev->DefaultKeyId = 0; + + /*RTMPMakeRSNIE(pAd, pAd->ApCfg.MBSSID[apidx].AuthMode, pAd->ApCfg.MBSSID[apidx].WepStatus, apidx); */ + DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) %s::(EncrypType=%d)\n", apidx, __FUNCTION__, wdev->WepStatus)); + + return TRUE; + } +#endif /* CONFIG_AP_SUPPORT */ + + + return TRUE; +} + + +/* + ======================================================================== + + 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. */ + #ifdef APCLI_SUPPORT + if (pWscControl->WscApCliScanMode != TRIGGER_PARTIAL_SCAN) +#endif /* APCLI_SUPPORT */ + { + { + 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 */ +#ifdef APCLI_SUPPORT + UCHAR if_idx = (pWscControl->EntryIfIdx & 0x0F); +#endif /*APCLI_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) + { +#ifdef AP_SCAN_SUPPORT + if (pWscControl->WscApCliScanMode == TRIGGER_PARTIAL_SCAN) { + if ((!pAd->ScanCtrl.PartialScan.bScanning) && + (pAd->ScanCtrl.PartialScan.LastScanChannel == 0)) { + pAd->ScanCtrl.PartialScan.pwdev = &pAd->ApCfg.ApCliTab[if_idx].wdev; + pAd->ScanCtrl.PartialScan.bScanning = TRUE; + } + } +#endif /* AP_SCAN_SUPPORT */ + ApSiteSurvey(pAd, NULL, SCAN_WSC_ACTIVE, FALSE, &pAd->ApCfg.ApCliTab[if_idx].wdev); + } +#endif /* APCLI_SUPPORT */ + + +} + +/* + ======================================================================== + + Routine Description: + Doing PBC conenction verification, it will check current BSS list + and find the correct number of PBC AP. If only 1 exists, it will + start to make connection. Otherwise, it will set a scan timer + to perform another scan for next PBC connection execution. + + Arguments: + pAd - NIC Adapter pointer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + + ======================================================================== +*/ +BOOLEAN WscPBCExec( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bFromM2, + IN PWSC_CTRL pWscControl) +{ +#ifdef WSC_LED_SUPPORT + UCHAR WPSLEDStatus; +#endif /* WSC_LED_SUPPORT */ +#if defined(CONFIG_STA_SUPPORT) || defined(APCLI_SUPPORT) + UCHAR CurOpMode = AP_MODE; +#endif /* #if defined(CONFIG_STA_SUPPORT) || defined(APCLI_SUPPORT) */ + + if (pWscControl == NULL) + return FALSE; + + + 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)); + + { + /* 2.1. Set 1 second timer to invoke another scan */ + RTMPSetTimer(&pWscControl->WscScanTimer, 1000); + pWscControl->WscScanTimerRunning = TRUE; + } + } + else + { + pWscControl->WscStatus = STATUS_WSC_PBC_TOO_MANY_AP; + RTMPSendWirelessEvent(pAd, IW_WSC_PBC_SESSION_OVERLAP, NULL, BSS0, 0); + +#ifdef WSC_LED_SUPPORT + if (LED_MODE(pAd) == WPS_LED_MODE_9) /* WPS LED mode 9. */ + { + /* In case of the WPS LED mode 9, the UI would abort the connection attempt by making the RT_OID_802_11_WSC_SET_WPS_STATE_MACHINE_TERMINATION request. */ + DBGPRINT(RT_DEBUG_TRACE, ("%s: Skip the WPS session overlap detected LED indication.\n", __FUNCTION__)); + } + else /* Other LED mode. */ + { + /* Session overlap detected. */ + WPSLEDStatus = LED_WPS_SESSION_OVERLAP_DETECTED; + RTMPSetLED(pAd, WPSLEDStatus); + + + } +#endif /* WSC_LED_SUPPORT */ + + /* + 20101210 - According to the response from WFA: + The station shall not continue scanning waiting for only one registrar to appear + */ + DBGPRINT(RT_DEBUG_TRACE, ("WscPBCExec --> AP list is %d, stop WPS process!\n", + pWscControl->WscPBCBssCount)); + + WscStop(pAd, +#ifdef CONFIG_AP_SUPPORT + FALSE, +#endif /* CONFIG_AP_SUPPORT */ + pWscControl); + pWscControl->WscConfMode = WSC_DISABLE; + } + + /* 2.2 We have to quit for now */ + return FALSE; + } + + if (bFromM2) + return TRUE; + + + + +#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) + { +#ifdef RTMP_TIMER_TASK_SUPPORT + RTMP_STRING ChStr[5] = {0}; +#else + UCHAR channel; +#endif +#ifdef WH_EZ_SETUP + UCHAR apcli_idx = (pWscControl->EntryIfIdx & 0x0F); + struct wifi_dev *cli_wdev = &pAd->ApCfg.ApCliTab[apcli_idx].wdev; +#endif + + NdisMoveMemory(pWscControl->RegData.SelfInfo.MacAddr, + pAd->ApCfg.ApCliTab[BSS0].wdev.if_addr, + MAC_ADDR_LEN); + +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(cli_wdev)) + { + struct wifi_dev *ap_wdev = &pAd->ApCfg.MBSSID[cli_wdev->func_idx].wdev; + ez_send_delay_disconnect_for_pbc(ap_wdev); + } +#endif + +#ifdef RTMP_TIMER_TASK_SUPPORT + // TODO: shiang-usw, check about this Channel setting here? Original it indicate to pAd->MlmeAux.Channel! + snprintf(ChStr, sizeof(ChStr), "%d", pAd->ApCfg.ApCliTab[BSS0].MlmeAux.Channel); +#ifdef WH_EZ_SETUP + if (IS_EZ_SETUP_ENABLED(cli_wdev)) + rtmp_set_channel(pAd, cli_wdev, pAd->ApCfg.ApCliTab[BSS0].MlmeAux.Channel); + else +#endif + Set_Channel_Proc(pAd, ChStr); +#else + channel = pAd->ApCfg.ApCliTab[BSS0].MlmeAux.Channel; + RTEnqueueInternalCmd(pAd, CMDTHREAD_APCLI_PBC_TIMEOUT, (VOID *)&channel, sizeof(UCHAR)); +#endif + + /* 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 */ + + + DBGPRINT(RT_DEBUG_OFF, ("<----- WscPBCExec !!!\n")); + return TRUE; +} + +BOOLEAN WscBssWpsIESearchForPBC( + RTMP_ADAPTER *pAd, + WSC_CTRL *pWscControl, + BSS_ENTRY *pInBss, + UUID_BSSID_CH_INFO ApUuidBssid[], + INT VarIeLen, + PUCHAR pVar) +{ + INT j = 0, Len = 0, idx = 0; + BOOLEAN bFound, bSameAP, bSelReg; + PUCHAR pData = NULL; + PBEACON_EID_STRUCT pEid; + USHORT DevicePasswordID; + PWSC_IE pWscIE; + UUID_BSSID_CH_INFO TmpInfo; + UCHAR zeros16[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + + 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) + ) + { + /* 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)); + } + + + /* 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); + } + + + if ((bFound == TRUE) && (bSelReg == TRUE)) + { + if (pWscControl->WscPBCBssCount == 8) + { + break; + } + + if (pWscControl->WscPBCBssCount > 0) + { + for (j = 0; j < pWscControl->WscPBCBssCount; j++) + { + if (RTMPCompareMemory(&ApUuidBssid[j].Uuid[0], &TmpInfo.Uuid[0], 16) == 0) + { + if (RTMPCompareMemory(&TmpInfo.Uuid[0], zeros16, 16) != 0) + { + /* + Same UUID, indicate concurrent AP + We can indicate 1 AP only. + */ + bSameAP = TRUE; + break; + } + else if (RTMPCompareMemory(&TmpInfo.Uuid[0], zeros16, 16) == 0) + { + if (ApUuidBssid[j].Band != TmpInfo.Band) + { + if (RTMPCompareMemory(&ApUuidBssid[j].Bssid[0], &TmpInfo.Bssid[0], 5) == 0) + { + /* + Zero UUID at different band, and first 5bytes of two BSSIDs are the same. + Indicate concurrent AP, we can indicate 1 AP only. + */ + bSameAP = TRUE; + break; + } + } + } + } + else if ((RTMPCompareMemory(&TmpInfo.Uuid[0], zeros16, 16) == 0) || + (RTMPCompareMemory(&ApUuidBssid[j].Uuid[0], zeros16, 16) == 0)) + { + if ((RTMPCompareMemory(&ApUuidBssid[j].Bssid[0], &TmpInfo.Bssid[0], 5) == 0) && + (ApUuidBssid[j].Band != TmpInfo.Band)) + { + INT tmpDiff = (INT)(ApUuidBssid[j].Bssid[5] - TmpInfo.Bssid[5]); + /* + Zero UUID and Non-zero UUID at different band, and two BSSIDs are very close. + Indicate concurrent AP, we can indicate 1 AP only. + */ + if ((tmpDiff <= 4) || + (tmpDiff >= -4)) + { + bSameAP = TRUE; + break; + } + } + } + } + } + + if (bSameAP) + { + if ((pWscControl->WpsApBand == PREFERRED_WPS_AP_PHY_TYPE_2DOT4_G_FIRST) && + (TmpInfo.Band == WSC_RFBAND_24GHZ) && + (ApUuidBssid[j].Band != TmpInfo.Band)) + { + RTMPMoveMemory(&(ApUuidBssid[j].Bssid[0]), &TmpInfo.Bssid[0], MAC_ADDR_LEN); + RTMPZeroMemory(&(ApUuidBssid[j].Ssid[0]), MAX_LEN_OF_SSID); + RTMPMoveMemory(&(ApUuidBssid[j].Ssid[0]), &TmpInfo.Ssid[0], TmpInfo.SsidLen); + ApUuidBssid[j].SsidLen = TmpInfo.SsidLen; + ApUuidBssid[j].Channel = TmpInfo.Channel; + } + else if ((pWscControl->WpsApBand == PREFERRED_WPS_AP_PHY_TYPE_5_G_FIRST) && + (TmpInfo.Band == WSC_RFBAND_50GHZ) && + (ApUuidBssid[j].Band != TmpInfo.Band)) + { + RTMPMoveMemory(&(ApUuidBssid[j].Bssid[0]), &TmpInfo.Bssid[0], MAC_ADDR_LEN); + RTMPZeroMemory(&(ApUuidBssid[j].Ssid[0]), MAX_LEN_OF_SSID); + RTMPMoveMemory(&(ApUuidBssid[j].Ssid[0]), &TmpInfo.Ssid[0], TmpInfo.SsidLen); + ApUuidBssid[j].SsidLen = TmpInfo.SsidLen; + ApUuidBssid[j].Channel = TmpInfo.Channel; + } + } + + if (bSameAP == FALSE) + { + UCHAR index = pWscControl->WscPBCBssCount; + + /* Store UUID */ + RTMPMoveMemory(&(ApUuidBssid[index].Uuid[0]), &TmpInfo.Uuid[0], 16); + RTMPMoveMemory(&(ApUuidBssid[index].Bssid[0]), &pInBss->Bssid[0], MAC_ADDR_LEN); + RTMPZeroMemory(&(ApUuidBssid[index].Ssid[0]), MAX_LEN_OF_SSID); + RTMPMoveMemory(&(ApUuidBssid[index].Ssid[0]), &pInBss->Ssid[0], pInBss->SsidLen); + ApUuidBssid[index].SsidLen = pInBss->SsidLen; + ApUuidBssid[index].Channel = pInBss->Channel; + if (ApUuidBssid[index].Channel > 14) + ApUuidBssid[index].Band = WSC_RFBAND_50GHZ; + else + ApUuidBssid[index].Band = WSC_RFBAND_24GHZ; + DBGPRINT(RT_DEBUG_ERROR, ("UUID-E= ")); + for(idx=0; idx<16; idx++) + DBGPRINT_RAW(RT_DEBUG_ERROR, ("%02x ", ApUuidBssid[index].Uuid[idx])); + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + + pWscControl->WscPBCBssCount++; + } + } + } + + return (bFound && bSelReg); +} + +/* + ======================================================================== + + Routine Description: + Find WSC PBC activated AP list + + Arguments: + pAd - NIC Adapter pointer + OutTab - Qualified AP BSS table + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + All these constants are defined in wsc.h + + ======================================================================== +*/ +VOID WscPBCBssTableSort( + IN RTMP_ADAPTER *pAd, + IN WSC_CTRL *pWscControl) +{ + INT i; + BSS_ENTRY *pInBss; + UUID_BSSID_CH_INFO *ApUuidBssid = NULL; + BOOLEAN rv = FALSE; +#if defined(CONFIG_STA_SUPPORT) || defined(APCLI_SUPPORT) + UCHAR CurOpMode = AP_MODE; +#endif /* #if defined(CONFIG_STA_SUPPORT) || defined(APCLI_SUPPORT) */ + +#ifdef APCLI_SUPPORT +if (CurOpMode == AP_MODE) + pWscControl = &pAd->ApCfg.ApCliTab[BSS0].WscControl; +#endif /* APCLI_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 = (BSS_ENTRY *) &pAd->ScanTab.BssEntry[i]; + + /* 1. Check VarIE length */ + if (pInBss->VarIELen == 0) + continue; + + + /* 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); + RTMPMoveMemory(pWscControl->WscPeerUuid, ApUuidBssid[0].Uuid, sizeof(ApUuidBssid[0].Uuid)); + +#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; + pAd->ApCfg.ApCliTab[BSS0].MlmeAux.Channel = ApUuidBssid[0].Channel; + COPY_MAC_ADDR(pAd->ApCfg.ApCliTab[BSS0].CfgApCliBssid, pWscControl->WscBssid); + + DBGPRINT(RT_DEBUG_OFF, ("will connect %s (%02X:%02X:%02X:%02X:%02X:%02X) on %d\n", + pWscControl->WscSsid.Ssid, PRINT_MAC(pWscControl->WscBssid), ApUuidBssid[0].Channel)); + } +#endif /* APCLI_SUPPORT */ + + } + + if (ApUuidBssid != NULL) + os_free_mem(NULL, ApUuidBssid); + + 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((RTMP_STRING *) &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_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if ((OpMode & 0x0F) == AP_MODE) + { + /* + AP needs to choose the STA's authType and encyType in two cases. + 1. AP is unconfigurated (authType and encyType will be updated to mixed mode by WscWriteConfToPortCfg() ) + 2. AP's authType is mixed mode, we should choose the suitable authType and encyType to STA + STA's authType and encyType depend on WscSecurityMode flag + */ + + if (((pWscControl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED ) || + (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode == Ndis802_11AuthModeWPA1PSKWPA2PSK)) && + (OpMode & REGISTRAR_ACTION)) + { + switch (pAd->ApCfg.MBSSID[apidx].WscSecurityMode) + { + case WPAPSKTKIP: + authType = WSC_AUTHTYPE_WPAPSK; + encyType = WSC_ENCRTYPE_TKIP; + break; + case WPAPSKAES: + authType = WSC_AUTHTYPE_WPAPSK; + encyType = WSC_ENCRTYPE_AES; + break; + case WPA2PSKTKIP: + authType = WSC_AUTHTYPE_WPA2PSK; + encyType = WSC_ENCRTYPE_TKIP; + break; + case WPA2PSKAES: + authType = WSC_AUTHTYPE_WPA2PSK; + encyType = WSC_ENCRTYPE_AES; + break; + default: + authType = (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK); + encyType = (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES); + break; + } + + if (pWscControl->WscConfStatus == WSC_SCSTATE_CONFIGURED) + { + /* + Although AuthMode is mixed mode, cipher maybe not mixed mode. + We need to correct cipher here. + */ + if (pAd->ApCfg.MBSSID[apidx].wdev.WepStatus == Ndis802_11TKIPEnable) + encyType = WSC_ENCRTYPE_TKIP; + if (pAd->ApCfg.MBSSID[apidx].wdev.WepStatus == Ndis802_11AESEnable) + encyType = WSC_ENCRTYPE_AES; + } + } + else + { + authType = WscGetAuthType(pAd->ApCfg.MBSSID[apidx].wdev.AuthMode); + encyType = WscGetEncryType(pAd->ApCfg.MBSSID[apidx].wdev.WepStatus); + } + WepKeyId = pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId; + } +#ifdef APCLI_SUPPORT + else if (OpMode == AP_CLIENT_MODE) + { + apidx = apidx & 0x0F; + authType = WscGetAuthType(pAd->ApCfg.ApCliTab[apidx].wdev.AuthMode); + encyType = WscGetEncryType(pAd->ApCfg.ApCliTab[apidx].wdev.WepStatus); + WepKeyId = pAd->ApCfg.ApCliTab[apidx].wdev.DefaultKeyId; + } +#endif /* APCLI_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + 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) + ) && (OpMode & REGISTRAR_ACTION))) + { + pCredential->KeyIndex = 1; + if ((OpMode & 0x0F) == STA_MODE) + { + { + 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((RTMP_STRING *) 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((RTMP_STRING *) pCredential->Key, 64, "%s%02x", pCredential->Key, pAd->ApCfg.ApCliTab[apidx].SharedKey[WepKeyId].Key[i]); + } + pCredential->KeyLength = pAd->SharedKey[apidx][WepKeyId].KeyLen*2; + } +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + break; + case WSC_ENCRTYPE_TKIP: + case WSC_ENCRTYPE_AES: + case (WSC_ENCRTYPE_AES | WSC_ENCRTYPE_TKIP): + pCredential->KeyLength = pWscControl->WpaPskLen; + memcpy(pCredential->Key, + pWscControl->WpaPsk, + pWscControl->WpaPskLen); + break; + } + } + + pCredential->AuthType = authType; + pCredential->EncrType = encyType; + +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if ((OpMode & 0x0F) == AP_MODE) + { + NdisMoveMemory(pCredential->MacAddr, pAd->ApCfg.MBSSID[apidx].wdev.bssid, 6); + if ((pWscControl->WscConfStatus == WSC_SCSTATE_UNCONFIGURED) && + (pWscControl->WscDefaultSsid.SsidLength > 0) && + (pWscControl->WscDefaultSsid.SsidLength < 33)) + { + NdisMoveMemory(pCredential->SSID.Ssid, pWscControl->WscDefaultSsid.Ssid, pWscControl->WscDefaultSsid.SsidLength); + pCredential->SSID.SsidLength = pWscControl->WscDefaultSsid.SsidLength; + } + else + { + NdisMoveMemory(pCredential->SSID.Ssid, pAd->ApCfg.MBSSID[apidx].Ssid, pAd->ApCfg.MBSSID[apidx].SsidLen); + pCredential->SSID.SsidLength = pAd->ApCfg.MBSSID[apidx].SsidLen; + } + } +#ifdef APCLI_SUPPORT + else if (OpMode == 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 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 WscSet_ApCli_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING * arg, + struct wifi_dev *wdev, + UCHAR CurApIdx) +{ + int i = 0; + + if (rtstrcasecmp(arg, "WEPAUTO") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeAutoSwitch; + else if (rtstrcasecmp(arg, "SHARED") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeShared; + else if (rtstrcasecmp(arg, "WPAPSK") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeWPAPSK; + else if ((rtstrcasecmp(arg, "WPA2PSK") == TRUE) || (rtstrcasecmp(arg, "WPAPSKWPA2PSK") == TRUE)) + wdev->AuthMode = Ndis802_11AuthModeWPA2PSK; +#ifdef APCLI_SAE_SUPPORT + else if ((strcmp(arg, "WPA3PSK") == 0) || (strcmp(arg, "wpa3psk") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA3PSK; + else if ((strcmp(arg, "WPA2PSKWPA3PSK") == 0) || (strcmp(arg, "wpa2pskwpa3psk") == 0)) + wdev->AuthMode = Ndis802_11AuthModeWPA3PSK; /* WPA3PSK has transition function in station mode */ +#endif /* APCLI_SAE_SUPPORT */ +#ifdef APCLI_OWE_SUPPORT + else if (rtstrcasecmp(arg, "OWE") == TRUE) + wdev->AuthMode = Ndis802_11AuthModeOWE; +#endif + else + wdev->AuthMode = Ndis802_11AuthModeOpen; + + for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++) { + if (IS_ENTRY_APCLI(&pAd->MacTab.Content[i])) + pAd->MacTab.tr_entry[i].PortSecured = WPA_802_1X_PORT_NOT_SECURED; + } + + RTMPMakeRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, (CurApIdx + MIN_NET_DEVICE_FOR_APCLI)); + + wdev->DefaultKeyId = 0; + + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + wdev->DefaultKeyId = 1; + + DBGPRINT(RT_DEBUG_ERROR, ("IF(apcli%d) %s::(AuthMode=%d)\n", CurApIdx, __func__, wdev->AuthMode)); + +} + +void WscSet_ApCli_EncrypType_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING * arg, + struct wifi_dev *wdev, + UCHAR CurApIdx) +{ + wdev->WepStatus = Ndis802_11WEPDisabled; + if (rtstrcasecmp(arg, "WEP") == TRUE) { + if (wdev->AuthMode < Ndis802_11AuthModeWPA) + wdev->WepStatus = Ndis802_11WEPEnabled; + } else if (rtstrcasecmp(arg, "TKIP") == TRUE) { + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + wdev->WepStatus = Ndis802_11TKIPEnable; + } else if ((rtstrcasecmp(arg, "AES") == TRUE) || (rtstrcasecmp(arg, "TKIPAES") == TRUE)) { + if (wdev->AuthMode >= Ndis802_11AuthModeWPA) + wdev->WepStatus = Ndis802_11AESEnable; + } +#ifdef APCLI_OWE_SUPPORT + else if (rtstrcasecmp(arg, "CCMP128") == TRUE) + wdev->WepStatus = Ndis802_11CCMP128Enable; + else if (rtstrcasecmp(arg, "CCMP256") == TRUE) + wdev->WepStatus = Ndis802_11CCMP256Enable; +#endif + + else + wdev->WepStatus = Ndis802_11WEPDisabled; + + + if (wdev->WepStatus >= Ndis802_11TKIPEnable) + wdev->DefaultKeyId = 1; + + RTMPMakeRSNIE(pAd, wdev->AuthMode, wdev->WepStatus, (CurApIdx + MIN_NET_DEVICE_FOR_APCLI)); + DBGPRINT(RT_DEBUG_OFF, ("IF(apcli%d) %s::(EncrypType=%d)\n", CurApIdx, __func__, wdev->WepStatus)); +} + +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); + { + struct wifi_dev *wdev = NULL; + + pApCliTab = &pAd->ApCfg.ApCliTab[CurApIdx]; + wdev = &pApCliTab->wdev; + + 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; + NdisZeroMemory(pApCliTab->CfgApCliBssid, MAC_ADDR_LEN); + 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; + } + } + WscSet_ApCli_AuthMode_Proc(pAd, WscGetAuthTypeStr(pCredential->AuthType), wdev, CurApIdx); + WscSet_ApCli_EncrypType_Proc(pAd, WscGetEncryTypeStr(pCredential->EncrType), wdev, CurApIdx); + + pApCliTab->PairCipher = wdev->WepStatus; + pApCliTab->GroupCipher = wdev->WepStatus; + pApCliTab->bMixCipher = FALSE; + + if (pCredential->EncrType != WSC_ENCRTYPE_NONE) + { + if (pCredential->EncrType & (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES)) + { + pApCliTab->wdev.DefaultKeyId = 0; + + if (pCredential->KeyLength >= 8 && pCredential->KeyLength <= 64) + { + pWscControl->WpaPskLen = (INT) pCredential->KeyLength; + NdisZeroMemory(pWscControl->WpaPsk, 64); + NdisMoveMemory(pWscControl->WpaPsk, pCredential->Key, pWscControl->WpaPskLen); + RT_CfgSetWPAPSKKey(pAd, (RTMP_STRING *) 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->wdev.DefaultKeyId = WepKeyId; + + /* 5 or 13 ASCII characters */ + /* 10 or 26 Hex characters */ + if (WepKeyLen == 5 || WepKeyLen == 13 || WepKeyLen == 10 || WepKeyLen == 26) + { + if (WepKeyLen == 5 || WepKeyLen == 13) + { + pApCliTab->SharedKey[WepKeyId].KeyLen = WepKeyLen; + memcpy(pApCliTab->SharedKey[WepKeyId].Key, + pCredential->Key,WepKeyLen); + if (WepKeyLen == 5) + pApCliTab->SharedKey[WepKeyId].CipherAlg = CIPHER_WEP64; + else + pApCliTab->SharedKey[WepKeyId].CipherAlg = CIPHER_WEP128; + } + else + { + pApCliTab->SharedKey[WepKeyId].KeyLen = (UCHAR) WepKeyLen/2; + AtoH((RTMP_STRING *) pCredential->Key, pApCliTab->SharedKey[WepKeyId].Key, WepKeyLen/2); + if (WepKeyLen == 10) + pApCliTab->SharedKey[WepKeyId].CipherAlg = CIPHER_WEP64; + else + pApCliTab->SharedKey[WepKeyId].CipherAlg = CIPHER_WEP128; + } + } + else + DBGPRINT(RT_DEBUG_TRACE, ("WEP: Invalid Key Length (%d)\n", pCredential->KeyLength)); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Unsupport default key index (%d), use key Index 1.\n", WepKeyId)); + pApCliTab->wdev.DefaultKeyId = WepKeyId = 0; + } + } + } + } + + if (pWscControl->WscProfile.ProfileCnt > 1) + { + pWscControl->WscProfileRetryTimerRunning = TRUE; + RTMPSetTimer(&pWscControl->WscProfileRetryTimer, WSC_PROFILE_RETRY_TIME_OUT); + } + + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscWriteConfToApCliCfg\n")); +} + +VOID WscApCliLinkDown( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl) +{ + UCHAR apidx = (pWscControl->EntryIfIdx & 0x0F); + UCHAR mac_addr[MAC_ADDR_LEN]; + BOOLEAN apcliEn = pAd->ApCfg.ApCliTab[apidx].Enable; + + NdisMoveMemory(pWscControl->RegData.SelfInfo.MacAddr, + pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, + 6); + + /* bring apcli interface down first */ + if(apcliEn == TRUE ) + { + pAd->ApCfg.ApCliTab[apidx].Enable = FALSE; + ApCliIfDown(pAd); + } + pAd->ApCfg.ApCliTab[apidx].Enable = apcliEn; + memcpy(mac_addr, pAd->ApCfg.ApCliTab[apidx].wdev.if_addr, MAC_ADDR_LEN); + pWscControl->WscStatus = STATUS_WSC_LINK_UP; + pWscControl->bWscTrigger = TRUE; +} +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +VOID WpsSmProcess( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + int HeaderLen = LENGTH_802_11; + 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 // + + + 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; +#ifdef A4_CONN + if (pHeader->FC.FrDs == 1 && pHeader->FC.ToDs == 1) + HeaderLen = LENGTH_802_11_WITH_ADDR4; +#endif + HeaderLen += LENGTH_802_1_H + sizeof(IEEE8021X_FRAME) + sizeof(EAP_FRAME); + + if (Elem->MsgType == WSC_EAPOL_PACKET_MSG) + { + if ((pEntry = MacTableLookup(pAd, pHeader->Addr2))) + apidx = pEntry->func_tb_idx; + } + +#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 */ + + 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 */ + RTMP_STRING *pData; + PEAP_FRAME pEapFrame; + /* Skip the EAP LLC header */ + pData = (RTMP_STRING *) &Elem->Msg[LENGTH_802_11 + LENGTH_802_1_H]; +#ifdef A4_CONN + if (pHeader->FC.FrDs == 1 && pHeader->FC.ToDs == 1) + pData = (RTMP_STRING *) &Elem->Msg[LENGTH_802_11_WITH_ADDR4 + LENGTH_802_1_H]; +#endif + 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 */ + RTMP_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) */ + RTMP_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 -= HeaderLen; + 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 + */ + RTMP_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) + { + RTMP_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 -= HeaderLen; + 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 + */ + RTMP_STRING wsc_frag_ack[] = "WSC_FRAG_ACK"; + NdisMoveMemory(Elem->Msg+MAC_ADDR_LEN, wsc_frag_ack, strlen(wsc_frag_ack)); + Elem->MsgLen = strlen(wsc_frag_ack); + StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState); + } + else + { + if (pWsc->Flags & WSC_MSG_FLAG_LF) + { + pData += (sizeof(WSC_FRAME) + 2); + Elem->MsgLen -= (sizeof(WSC_FRAME) + 2); + } + else + { + pData += sizeof(WSC_FRAME); + Elem->MsgLen -= sizeof(WSC_FRAME); + } + + if ((pWpsCtrl->WscRxBufLen + Elem->MsgLen) < (MGMT_DMA_BUFFER_SIZE-6)) + { + NdisMoveMemory((pWpsCtrl->pWscRxBuf + pWpsCtrl->WscRxBufLen), pData, Elem->MsgLen); + pWpsCtrl->WscRxBufLen += Elem->MsgLen; + } +#ifdef WSC_V2_SUPPORT + if (pWsc->Flags & WSC_MSG_FLAG_MF) + WscSendEapFragAck(pAd, pWpsCtrl, pEntry); + else +#endif /* WSC_V2_SUPPORT */ + { + //NdisMoveMemory(Elem->Msg+6, pData, Elem->MsgLen); + NdisMoveMemory(Elem->Msg+6, pWpsCtrl->pWscRxBuf, pWpsCtrl->WscRxBufLen); + Elem->MsgLen = pWpsCtrl->WscRxBufLen; + StateMachinePerformAction(pAd, &pAd->Mlme.WscMachine, Elem, pAd->Mlme.WscMachine.CurrState); + pWpsCtrl->WscRxBufLen = 0; + NdisZeroMemory(pWpsCtrl->pWscRxBuf, MGMT_DMA_BUFFER_SIZE); + } + } + return; + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("ERROR: WscCheckWSCHeader() return FALSE!\n")); + return; + } + } + } + else + DBGPRINT(RT_DEBUG_WARN, ("Unknow Message Type (=%lu)\n", Elem->MsgType)); +} + +#ifdef CONFIG_AP_SUPPORT + +#define WSC_SINGLE_TRIGGER_APPNAME "unknown" + +#ifdef SDK_GOAHEAD_HTTPD +#undef WSC_SINGLE_TRIGGER_APPNAME +#define WSC_SINGLE_TRIGGER_APPNAME "goahead" +#endif /* SDK_GOAHEAD_HTTPD */ + +#ifdef SDK_USER_LIGHTY +#undef WSC_SINGLE_TRIGGER_APPNAME +#define WSC_SINGLE_TRIGGER_APPNAME "nvram_daemon" +#endif /* SDK_USER_LIGHTY */ + +INT WscGetConfWithoutTrigger( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl, + IN BOOLEAN bFromUPnP) +{ + INT WscMode; + INT IsAPConfigured; + //PWSC_UPNP_NODE_INFO pWscUPnPNodeInfo; + UCHAR apIdx; + +#ifdef LINUX +#ifdef WSC_SINGLE_TRIGGER +/* +++ added by YYHuang@Ralink, 08/03/12 */ +/* + Notify user space application that WPS procedure will begin. + Signal + ra0: SIGXFSZ + rai0: SIGWINCH +*/ + { + struct task_struct *p; + + DBGPRINT(RT_DEBUG_TRACE, ("%s - WSC_SINGLE_TRIGGER_APPNAME: %s!\n", + __FUNCTION__, WSC_SINGLE_TRIGGER_APPNAME)); + + rcu_read_lock(); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) + for_each_process(p) +#else + for_each_task(p) +#endif + { + if(!strcmp(p->comm, WSC_SINGLE_TRIGGER_APPNAME)) + { + if (pAd->dev_idx == 0) + send_sig(SIGXFSZ, p, 0); + else + send_sig(SIGWINCH, p, 0); + } + } + rcu_read_unlock(); + } +/* --- added by YYHuang@Ralink, 08/03/12 */ +#endif /* WSC_SINGLE_TRIGGER */ +#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].wdev.bssid, 3, 0, AP_MODE); + + pWscControl->bWscTrigger = TRUE; + pWscControl->bWscAutoTigeer = TRUE; + DBGPRINT(RT_DEBUG_TRACE, ("%s:: trigger WSC state machine\n", __FUNCTION__)); + + return TRUE; +} +#endif /* CONFIG_AP_SUPPORT */ + +VOID WscSendNACK( + IN PRTMP_ADAPTER pAdapter, + IN MAC_TABLE_ENTRY *pEntry, + IN PWSC_CTRL pWscControl) +{ + INT DataLen = 0; + PUCHAR pWscData = NULL; + BOOLEAN Cancelled; + UCHAR CurOpMode = AP_MODE; + + + os_alloc_mem(NULL, (UCHAR **)&pWscData, WSC_MAX_DATA_LEN); + if (pWscData == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscSendNACK:: WscData Allocate failed!\n")); + return; + } + + NdisZeroMemory(pWscData, WSC_MAX_DATA_LEN); + DataLen = BuildMessageNACK(pAdapter, pWscControl, pWscData); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + if (pEntry && + (IS_ENTRY_APCLI(pEntry) + ) + ) + WscSendMessage(pAdapter, WSC_OPCODE_NACK, pWscData, DataLen, pWscControl, AP_CLIENT_MODE, EAP_CODE_RSP); + else + WscSendMessage(pAdapter, WSC_OPCODE_NACK, pWscData, DataLen, pWscControl, AP_MODE, EAP_CODE_REQ); + } +#endif /* CONFIG_AP_SUPPORT */ + + + 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) + ) + { + 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; + } + } + + + /* 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 */ + + +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 WscPBCSessionOverlapClear( + IN RTMP_ADAPTER *pAd) +{ + PWSC_STA_PBC_PROBE_INFO pWscStaPbcProbeInfo = &pAd->CommonCfg.WscStaPbcProbeInfo; + UCHAR i; + + for (i = 0; i < MAX_PBC_STA_TABLE_SIZE; i++) { + NdisZeroMemory(&(pWscStaPbcProbeInfo->StaMacAddr[i][0]), MAC_ADDR_LEN); + pWscStaPbcProbeInfo->ReciveTime[i] = 0; + pWscStaPbcProbeInfo->Valid[i] = FALSE; + } + pWscStaPbcProbeInfo->WscPBCStaProbeCount = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("WscPBCSessionOverlapClear : WscPBCStaProbeCount = %d\n", + pWscStaPbcProbeInfo->WscPBCStaProbeCount)); +} + +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(RTMP_ADAPTER *pAd, UCHAR CurOpMode) +{ + char *cfgData = 0; + RTMP_STRING *fileName = NULL; + RTMP_OS_FD file_r, file_w; + RTMP_OS_FS_INFO osFSInfo; + LONG rv, fileLen = 0; + char *offset = 0; + RTMP_STRING *pTempStr = NULL; +#ifdef CONFIG_AP_SUPPORT + INT index = 0; + UCHAR apidx = (pAd->WriteWscCfgToDatFile & 0x0F); +#endif /* CONFIG_AP_SUPPORT */ + PWSC_CTRL pWscControl = NULL; + PWSC_CREDENTIAL pCredentail = NULL; + RTMP_STRING WepKeyName[MAX_WEPKEYNAME_LEN] = {0}; + RTMP_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; + } + fileName = get_dev_profile(pAd); + + snprintf((RTMP_STRING *) WepKeyName, sizeof(WepKeyName), "Key%dStr%d=", pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId+1, apidx+1); + snprintf((RTMP_STRING *) WepKeyFormatName, sizeof(WepKeyFormatName), "Key%dType=", pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId+1); + } +#endif /* CONFIG_AP_SUPPORT */ + + + RtmpOSFSInfoChange(&osFSInfo, TRUE); + + file_r = RtmpOSFileOpen(fileName, O_RDONLY, 0); + if (IS_FILE_OPEN_ERR(file_r)) + { + DBGPRINT(RT_DEBUG_TRACE, ("-->1) %s: Error opening file %s\n", __FUNCTION__, fileName)); + return; + } + else + { + char tempStr[64] = {0}; + while((rv = RtmpOSFileRead(file_r, tempStr, 64)) > 0) + { + fileLen += rv; + } + os_alloc_mem(NULL, (UCHAR **)&cfgData, fileLen); + if (cfgData == NULL) + { + RtmpOSFileClose(file_r); + DBGPRINT(RT_DEBUG_TRACE, ("CfgData mem alloc fail. (fileLen = %ld)\n", fileLen)); + goto out; + } + NdisZeroMemory(cfgData, fileLen); + RtmpOSFileSeek(file_r, 0); + rv = RtmpOSFileRead(file_r, (RTMP_STRING *)cfgData, fileLen); + RtmpOSFileClose(file_r); + if (rv != fileLen) + { + DBGPRINT(RT_DEBUG_TRACE, ("CfgData mem alloc fail, fileLen = %ld\n", fileLen)); + goto ReadErr; + } + } + + file_w = RtmpOSFileOpen(fileName, O_WRONLY|O_TRUNC, 0); + if (IS_FILE_OPEN_ERR(file_w)) + { + goto WriteFileOpenErr; + } + else + { + offset = (PCHAR) rtstrstr((RTMP_STRING *) cfgData, "Default\n"); + offset += strlen("Default\n"); + RtmpOSFileWrite(file_w, (RTMP_STRING *)cfgData, (int)(offset-cfgData)); + os_alloc_mem(NULL, (UCHAR **)&pTempStr, WSC_WR_FILE_MAX_BUF); + if (!pTempStr) + { + DBGPRINT(RT_DEBUG_TRACE, ("pTempStr mem alloc fail. (WSC_WR_FILE_MAX_BUF)\n")); + RtmpOSFileClose(file_w); + goto WriteErr; + } + + for (;;) + { + int i = 0; + RTMP_STRING *ptr; + BOOLEAN bNewFormat = TRUE; + + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + + if ((size_t)(offset - cfgData) < fileLen) + { + ptr = (PSTRING) offset; + while(*ptr && *ptr != '\n') + { + pTempStr[i++] = *ptr++; + } + pTempStr[i] = 0x00; + + offset += strlen(pTempStr) + 1; + if ((strncmp(pTempStr, "SSID=", strlen("SSID=")) == 0) || + strncmp(pTempStr, "SSID1=", strlen("SSID1=")) == 0 || + strncmp(pTempStr, "SSID2=", strlen("SSID2=")) == 0 || + strncmp(pTempStr, "SSID3=", strlen("SSID3=")) == 0 || + strncmp(pTempStr, "SSID4=", strlen("SSID4=")) == 0 + ) + { + if (rtstrstr(pTempStr, "SSID=")) + bNewFormat = FALSE; + + WscWriteSsidToDatFile(pAd, pTempStr, bNewFormat, CurOpMode); + } + else if (strncmp(pTempStr, "AuthMode=", strlen("AuthMode=")) == 0) + { + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "AuthMode="); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + if (pAd->ApCfg.MBSSID[index].SsidLen) + { + if (index == 0) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%s", pTempStr, RTMPGetRalinkAuthModeStr(pAd->ApCfg.MBSSID[index].wdev.AuthMode)); + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s;%s", pTempStr, RTMPGetRalinkAuthModeStr(pAd->ApCfg.MBSSID[index].wdev.AuthMode)); + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + } + else if (strncmp(pTempStr, "EncrypType=", strlen("EncrypType=")) == 0) + { + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "EncrypType="); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + if (index == 0) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%s", pTempStr, RTMPGetRalinkEncryModeStr(pAd->ApCfg.MBSSID[index].wdev.WepStatus)); + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s;%s", pTempStr, RTMPGetRalinkEncryModeStr(pAd->ApCfg.MBSSID[index].wdev.WepStatus)); + } + } +#endif /* CONFIG_AP_SUPPORT */ + } + else if ((strncmp(pTempStr, "WPAPSK=", strlen("WPAPSK=")) == 0) || + (strncmp(pTempStr, "WPAPSK1=", strlen("WPAPSK1=")) == 0) || + (strncmp(pTempStr, "WPAPSK2=", strlen("WPAPSK2=")) == 0) || + (strncmp(pTempStr, "WPAPSK3=", strlen("WPAPSK3=")) == 0) || + (strncmp(pTempStr, "WPAPSK4=", strlen("WPAPSK4=")) == 0)) + { + bNewFormat = TRUE; + if (strstr(pTempStr, "WPAPSK=")) + bNewFormat = FALSE; + WscWriteWpaPskToDatFile(pAd, pTempStr, bNewFormat); + } + else if (strncmp(pTempStr, "WscConfMode=", strlen("WscConfMode=")) == 0) + { + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "WscConfMode="); +#ifdef CONFIG_AP_SUPPORT + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + pWscControl = &pAd->ApCfg.MBSSID[index].WscControl; + if (index == 0) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%d", pTempStr, pWscControl->WscConfMode); + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s;%d", pTempStr, pWscControl->WscConfMode); + } +#endif /* CONFIG_AP_SUPPORT */ + } + else if (strncmp(pTempStr, "WscConfStatus=", strlen("WscConfStatus=")) == 0) + { + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "WscConfStatus="); +#ifdef CONFIG_AP_SUPPORT + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + pWscControl = &pAd->ApCfg.MBSSID[index].WscControl; + if (index == 0) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%d", pTempStr, pWscControl->WscConfStatus); + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s;%d", pTempStr, pWscControl->WscConfStatus); + } +#endif /* CONFIG_AP_SUPPORT */ + } + else if (strncmp(pTempStr, "DefaultKeyID=", strlen("DefaultKeyID=")) == 0) + { + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "DefaultKeyID="); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + if (index == 0) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%d", pTempStr, pAd->ApCfg.MBSSID[index].wdev.DefaultKeyId+1); + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s;%d", pTempStr, pAd->ApCfg.MBSSID[index].wdev.DefaultKeyId+1); + } + } +#endif /* CONFIG_AP_SUPPORT */ + } +#ifdef CONFIG_AP_SUPPORT + else if ((strncmp(pTempStr, WepKeyFormatName, strlen(WepKeyFormatName)) == 0) && + (CurOpMode == AP_MODE)) + { + pCredentail = &pAd->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0]; + if (pAd->ApCfg.MBSSID[apidx].wdev.WepStatus == Ndis802_11WEPEnabled) + { + UCHAR idx = 0, KeyType[4] = {0}; + RTMP_STRING *ptr2, *temp_ptr; + + temp_ptr = pTempStr; /* Save pTempStr original address */ + ptr2 = rtstrstr(pTempStr, "="); + if (ptr2) + { + pTempStr = ptr2+1; + + if (pTempStr == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():%d: pTempStr is NULL!\n", __FUNCTION__,__LINE__)); + } + KeyType[0] = (UCHAR)(*pTempStr - 0x30); + for (idx = 1; idx < 4; idx++) + { + ptr2 = rtstrstr(pTempStr, ";"); + if (ptr2 == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():%d: ptr2 is NULL!\n", __FUNCTION__,__LINE__)); + } + + pTempStr = ptr2+1; + if (pTempStr == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():%d: pTempStr is NULL!\n", __FUNCTION__,__LINE__)); + } + if ((pTempStr != NULL) && + ((*pTempStr == '0') || + (*pTempStr == '1'))) + KeyType[idx] = (UCHAR)(*pTempStr - 0x30); + } + } + pTempStr = temp_ptr; /* Restore pTempStr original address */ + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + NdisMoveMemory(pTempStr, WepKeyFormatName, strlen(WepKeyFormatName)); + for (idx = 0; idx < pAd->ApCfg.BssidNum; idx++) + { + if (idx == apidx) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s0", pTempStr); + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%d", pTempStr, KeyType[idx]); + + if (apidx < (pAd->ApCfg.BssidNum - 1)) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s;", pTempStr); + } + } + } + else if ((strncmp(pTempStr, WepKeyName, strlen(WepKeyName)) == 0) && + (CurOpMode == AP_MODE)) + { + pCredentail = &pAd->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0]; + if (pAd->ApCfg.MBSSID[apidx].wdev.WepStatus == Ndis802_11WEPEnabled) + { + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + NdisMoveMemory(pTempStr, WepKeyName, strlen(WepKeyName)); + tempStrLen = strlen(pTempStr); + if (pCredentail->KeyLength) + { + if ((pCredentail->KeyLength == 5) || + (pCredentail->KeyLength == 13)) + { + int jjj=0; + for (jjj=0; jjjKeyLength; jjj++) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%02x", pTempStr, pCredentail->Key[jjj]); + } + else if ((pCredentail->KeyLength == 10) || + (pCredentail->KeyLength == 26)) + { + NdisMoveMemory(pTempStr + tempStrLen, pCredentail->Key, pCredentail->KeyLength); + } + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + + + RtmpOSFileWrite(file_w, pTempStr, strlen(pTempStr)); + RtmpOSFileWrite(file_w, "\n", 1); + } + else + { + break; + } + } + RtmpOSFileClose(file_w); + } + +WriteErr: + if (pTempStr) + os_free_mem(NULL, pTempStr); +ReadErr: +WriteFileOpenErr: + if (cfgData) + os_free_mem(NULL, cfgData); +out: + RtmpOSFSInfoChange(&osFSInfo, FALSE); + + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscWriteConfToDatFile\n")); + return; +} + +#ifdef CONFIG_AP_SUPPORT +void WscWriteConfToAR9File( + IN PRTMP_ADAPTER pAd, + IN UCHAR CurOpMode) +{ + RTMP_STRING *fileName = NULL; + RTMP_OS_FD file_w; + RTMP_OS_FS_INFO osFSInfo; + INT offset = 0; + INT datoffset = 0; + RTMP_STRING *pTempStr = 0; + RTMP_STRING *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; + RTMP_STRING WepKeyName[MAX_WEPKEYNAME_LEN] = {0}; + RTMP_STRING WepKeyFormatName[MAX_WEPKEYTYPE_LEN] = {0}; + INT tempStrLen = 0; + RTMP_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((RTMP_STRING *) WepKeyName, sizeof(WepKeyName), "Key%dStr1=", pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.DefaultKeyId+1); + snprintf((RTMP_STRING *) WepKeyFormatName, sizeof(WepKeyFormatName), "Key%dType=", pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.DefaultKeyId+1); + } +#endif /* CONFIG_AP_SUPPORT */ + + + RtmpOSFSInfoChange(&osFSInfo, TRUE); + file_w = RtmpOSFileOpen(fileName, O_WRONLY|O_CREAT, 0); + if (IS_FILE_OPEN_ERR(file_w)) + { + goto WriteFileOpenErr; + } + else + { + os_alloc_mem(NULL, (UCHAR **)&pTempStr, WSC_WR_FILE_MAX_BUF); + if (!pTempStr) + { + DBGPRINT(RT_DEBUG_TRACE, ("pTempStr mem alloc fail. (WSC_WR_FILE_MAX_BUF)\n")); + RtmpOSFileClose(file_w); + goto WriteErr; + } + os_alloc_mem(NULL, (UCHAR **)&pDatStr, 4096); + if (!pDatStr) + { + DBGPRINT(RT_DEBUG_TRACE, ("pDatStr mem alloc fail. (4096)\n")); + RtmpOSFileClose(file_w); + goto WriteErr; + } + + /*for (;;) */ + { + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + 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, WSC_WR_FILE_MAX_BUF); + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "AuthMode="); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + if (pAd->ApCfg.MBSSID[index].SsidLen) + { + if (index == 0) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%s", pTempStr, RTMPGetRalinkAuthModeStr(pAd->ApCfg.MBSSID[index].wdev.AuthMode)); + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s;%s", pTempStr, RTMPGetRalinkAuthModeStr(pAd->ApCfg.MBSSID[index].wdev.AuthMode)); + } + } + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s\n", pTempStr); + offset=strlen(pTempStr); + NdisMoveMemory(pDatStr+datoffset,pTempStr,offset); + datoffset += offset; + } +#endif /* CONFIG_AP_SUPPORT */ + } + + { + offset=0; + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "EncrypType="); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + if (index == 0) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%s", pTempStr, RTMPGetRalinkEncryModeStr(pAd->ApCfg.MBSSID[index].wdev.WepStatus)); + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s;%s", pTempStr, RTMPGetRalinkEncryModeStr(pAd->ApCfg.MBSSID[index].wdev.WepStatus)); + } + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s\n", pTempStr); + offset=strlen(pTempStr); + NdisMoveMemory(pDatStr+datoffset,pTempStr,offset); + datoffset += offset; + } +#endif /* CONFIG_AP_SUPPORT */ + } + + { + offset=0; + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + 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, WSC_WR_FILE_MAX_BUF); + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "WscConfMode="); +#ifdef CONFIG_AP_SUPPORT + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + pWscControl = &pAd->ApCfg.MBSSID[index].WscControl; + if (index == 0) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%d", pTempStr, pWscControl->WscConfMode); + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s;%d", pTempStr, pWscControl->WscConfMode); + } + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s\n", pTempStr); + offset=strlen(pTempStr); + NdisMoveMemory(pDatStr+datoffset,pTempStr,offset); + datoffset += offset; +#endif /* CONFIG_AP_SUPPORT */ + } + + { + offset=0; + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "WscConfStatus="); +#ifdef CONFIG_AP_SUPPORT + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + pWscControl = &pAd->ApCfg.MBSSID[index].WscControl; + if (index == 0) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%d", pTempStr, pWscControl->WscConfStatus); + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s;%d", pTempStr, pWscControl->WscConfStatus); + } + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s\n", pTempStr); + offset=strlen(pTempStr); + NdisMoveMemory(pDatStr+datoffset,pTempStr,offset); + datoffset += offset; +#endif /* CONFIG_AP_SUPPORT */ + } + + { + offset=0; + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "DefaultKeyID="); +#ifdef CONFIG_AP_SUPPORT + if (CurOpMode == AP_MODE) + { + for (index = 0; index < pAd->ApCfg.BssidNum; index++) + { + pWscControl = &pAd->ApCfg.MBSSID[index].WscControl; + if (index == 0) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s%d", pTempStr, pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId+1); + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s;%d", pTempStr, pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId+1); + } + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%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, WSC_WR_FILE_MAX_BUF); + offset=0; + NdisMoveMemory(pTempStr, WepKeyFormatName, strlen(WepKeyFormatName)); + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + if (pAd->ApCfg.MBSSID[MAIN_MBSSID].wdev.WepStatus == Ndis802_11WEPEnabled) + { + pCredentail = &pAd->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0]; + if ((pCredentail->KeyLength == 5) || + (pCredentail->KeyLength == 13)) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s1", pTempStr); /* ASCII */ + else + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s0", pTempStr); /* Hex */ + } + if (apidx < (pAd->ApCfg.BssidNum - 1)) + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%s;", pTempStr); + } + snprintf(pTempStr, WSC_WR_FILE_MAX_BUF, "%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, WSC_WR_FILE_MAX_BUF); + 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, WSC_WR_FILE_MAX_BUF, "%s\n", pTempStr); + offset=strlen(pTempStr); + NdisMoveMemory(pDatStr+datoffset,pTempStr,offset); + datoffset += offset; + } + + for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++) + { + snprintf(WepKeyName, sizeof(WepKeyName), "Key%dStr%d=", index, (apidx + 1)); + if ((pAd->ApCfg.MBSSID[apidx].wdev.WepStatus == Ndis802_11WEPEnabled)) + { + NdisZeroMemory(pTempStr, WSC_WR_FILE_MAX_BUF); + NdisMoveMemory(pTempStr, WepKeyName, strlen(WepKeyName)); + tempStrLen = strlen(pTempStr); + pCredentail = &pAd->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0]; + NdisMoveMemory(pTempStr + tempStrLen, pCredentail->Key, pCredentail->KeyLength); + NdisMoveMemory(pTempStr + tempStrLen+pCredentail->KeyLength, "\n", 1); + } + offset=tempStrLen+pCredentail->KeyLength+1; + NdisMoveMemory(pDatStr+datoffset,pTempStr,offset); + datoffset += offset; + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + RtmpOSFileWrite(file_w, pDatStr, datoffset); + /*RtmpOSFileWrite(file_w, "\n", 1); */ + } + } + RtmpOSFileClose(file_w); + } + +WriteErr: + if (pTempStr) + os_free_mem(NULL, pTempStr); + if (pDatStr) + os_free_mem(NULL, pDatStr); + +WriteFileOpenErr: + RtmpOSFSInfoChange(&osFSInfo, FALSE); + + + DBGPRINT(RT_DEBUG_TRACE, ("<----- WscWriteConfToAR9File\n")); + return; +} +#endif/*CONFIG_AP_SUPPORT*/ + +static INT wsc_write_dat_file_thread ( + IN ULONG Context) +{ + RTMP_OS_TASK *pTask; + RTMP_ADAPTER *pAd; + int Status = 0; + + pTask = (RTMP_OS_TASK *)Context; + pAd = (PRTMP_ADAPTER)RTMP_OS_TASK_DATA_GET(pTask); + + if (pAd == NULL) + return 0; + + RtmpOSTaskCustomize(pTask); + + while (pTask && !RTMP_OS_TASK_IS_KILLED(pTask)) + { + RtmpusecDelay(2000); + + if (RtmpOSTaskWait(pAd, pTask, &Status) == FALSE) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); + break; + } + + if (Status != 0) + break; + + + if (pAd->pWscElme && (pAd->pWscElme->MsgLen != 0)) + { + MLME_QUEUE_ELEM *pElme; + os_alloc_mem(pAd, (UCHAR **)&pElme, sizeof(MLME_QUEUE_ELEM)); + if (pElme) + { + NdisZeroMemory(pElme, sizeof(MLME_QUEUE_ELEM)); + RTMP_SEM_LOCK(&pAd->WscElmeLock); + NdisMoveMemory(pElme, pAd->pWscElme, sizeof(MLME_QUEUE_ELEM)); + pAd->pWscElme->MsgLen = 0; + NdisZeroMemory(pAd->pWscElme->Msg, MGMT_DMA_BUFFER_SIZE); + RTMP_SEM_UNLOCK(&pAd->WscElmeLock); + WpsSmProcess(pAd, pElme); + os_free_mem(NULL, pElme); + } + } + + if (pAd->WriteWscCfgToDatFile != 0xFF) + { + UCHAR CurOpMode = AP_MODE; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + CurOpMode = AP_MODE; +#endif /* CONFIG_AP_SUPPORT */ + + + WscWriteConfToDatFile(pAd, CurOpMode); + +#ifdef CONFIG_AP_SUPPORT +#ifdef INF_AR9 +#ifdef AR9_MAPI_SUPPORT + WscWriteConfToAR9File(pAd, CurOpMode); +#endif /*AR9_MAPI_SUPPORT*/ +#endif /* INF_AR9 */ +#endif/*CONFIG_AP_SUPPORT*/ + pAd->WriteWscCfgToDatFile = 0xFF; + } + } + + if (pTask) + RtmpOSTaskNotifyToExit(pTask); + + return 0; +} + + +/* + * This kernel thread init in the probe fucntion, so we should kill it when do remove module. + */ +BOOLEAN WscThreadExit(RTMP_ADAPTER *pAd) +{ + INT ret; + + /* + This kernel thread init in the probe fucntion, so kill it when do remove module. + */ + ret = RtmpOSTaskKill(&pAd->wscTask); + if (ret == NDIS_STATUS_FAILURE) + { + DBGPRINT(RT_DEBUG_ERROR, ("kill wsc task failed!\n")); + } + + if (pAd->pHmacData) + { + os_free_mem(NULL, pAd->pHmacData); + pAd->pHmacData = NULL; + } + if (pAd->pWscElme) + { + os_free_mem(NULL, pAd->pWscElme); + pAd->pWscElme = NULL; + } + NdisFreeSpinLock(&pAd->WscElmeLock); +#ifdef CONFIG_AP_SUPPORT + if ((pAd->OpMode == OPMODE_AP) + ) + { + INT ap_idx; + UCHAR MaxBssidNum = MAX_MBSSID_NUM(pAd); + + for (ap_idx = 0; ap_idx < MaxBssidNum; ap_idx++) + { + PWSC_CTRL pWpsCtrl = &pAd->ApCfg.MBSSID[ap_idx].WscControl; + WscStop(pAd, FALSE, pWpsCtrl); + pWpsCtrl->WscRxBufLen = 0; + if (pWpsCtrl->pWscRxBuf) + { + os_free_mem(pAd, pWpsCtrl->pWscRxBuf); + pWpsCtrl->pWscRxBuf = NULL; + } + pWpsCtrl->WscTxBufLen = 0; + if (pWpsCtrl->pWscTxBuf) + { + os_free_mem(pAd, pWpsCtrl->pWscTxBuf); + pWpsCtrl->pWscTxBuf = NULL; + } +#ifdef WSC_V2_SUPPORT + if (pWpsCtrl->WscSetupLockTimerRunning) + { + BOOLEAN Cancelled; + pWpsCtrl->WscSetupLockTimerRunning = FALSE; + RTMPCancelTimer(&pWpsCtrl->WscSetupLockTimer, &Cancelled); + } + if (pWpsCtrl->WscV2Info.ExtraTlv.pTlvData) + { + os_free_mem(NULL, pWpsCtrl->WscV2Info.ExtraTlv.pTlvData); + pWpsCtrl->WscV2Info.ExtraTlv.pTlvData = NULL; + } +#endif // WSC_V2_SUPPORT // + WscClearPeerList(&pWpsCtrl->WscPeerList); + NdisFreeSpinLock(&pWpsCtrl->WscPeerListSemLock); + } +#ifdef APCLI_SUPPORT + { + INT index; + WscStop(pAd, TRUE, &pAd->ApCfg.ApCliTab[BSS0].WscControl); + + for(index = 0; index < MAX_APCLI_NUM; index++) + { + PWSC_CTRL pWpsCtrl = &pAd->ApCfg.ApCliTab[index].WscControl; + + pWpsCtrl->WscTxBufLen = 0; + if (pWpsCtrl->pWscTxBuf) + os_free_mem(pAd, pWpsCtrl->pWscTxBuf); + pWpsCtrl->WscRxBufLen = 0; + if (pWpsCtrl->pWscRxBuf) + os_free_mem(pAd, pWpsCtrl->pWscRxBuf); + WscClearPeerList(&pWpsCtrl->WscPeerList); + NdisFreeSpinLock(&pWpsCtrl->WscPeerListSemLock); + } + } +#endif // APCLI_SUPPORT // + } +#endif /* CONFIG_AP_SUPPORT */ + + /* 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 = FALSE; + + + 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 */ + + 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 */ + + switch (pWscControl->WscProfile.Profile[currentIdx].EncrType) + { + case WSC_ENCRTYPE_NONE: + { + bAPHasSecuritySetting = FALSE; + break; + } + + case WSC_ENCRTYPE_WEP: + case WSC_ENCRTYPE_TKIP: + case (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES): + case WSC_ENCRTYPE_AES: + { + bAPHasSecuritySetting = TRUE; + break; + } + + default: + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: Incorrect encryption types (%d)\n", + __FUNCTION__, pWscControl->WscProfile.Profile[currentIdx].EncrType)); + ASSERT(FALSE); + break; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s: WSC Entryption Type = %d\n", + __FUNCTION__, pWscControl->WscProfile.Profile[currentIdx].EncrType)); + + return bAPHasSecuritySetting; +} + + +/* */ +/* After the NIC connects with a WPS AP or not, */ +/* the WscLEDTimer timer controls the LED behavior according to LED mode. */ +/* */ +VOID WscLEDTimer( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext; + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pWscControl->pAd; + UCHAR WPSLEDStatus = 0; + + /* WPS LED mode 7, 8, 11 and 12. */ + if ((LED_MODE(pAd) == WPS_LED_MODE_7) || + (LED_MODE(pAd) == WPS_LED_MODE_8) || + (LED_MODE(pAd) == WPS_LED_MODE_11) || + (LED_MODE(pAd) == WPS_LED_MODE_12)) + { + WPSLEDStatus = LED_WPS_TURN_LED_OFF; + DBGPRINT(RT_DEBUG_TRACE, ("%s: Turn off the WPS successful LED pattern.\n", __FUNCTION__)); + } + else if ((LED_MODE(pAd) == WPS_LED_MODE_9) /* WPS LED mode 9. */ +#ifdef CONFIG_WIFI_LED_SUPPORT + || (LED_MODE(pAd) == WPS_LED_MODE_SHARE) +#endif /* CONFIG_WIFI_LED_SUPPORT */ + ) + { + switch (pWscControl->WscLEDMode) /* Last WPS LED state. */ + { + + + /* Turn off the blue LED after 300 seconds. */ + case LED_WPS_SUCCESS: + WPSLEDStatus = LED_WPS_TURN_LED_OFF; + + /* Turn on/off the WPS success LED according to AP's encryption algorithm after one second. */ + RTMPSetTimer(&pWscControl->WscLEDTimer, WSC_WPS_TURN_OFF_LED_TIMEOUT); + pWscControl->WscLEDTimerRunning = TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_SUCCESS => LED_WPS_TURN_LED_OFF\n", __FUNCTION__)); + break; + + /* After turn off the blue LED for one second. */ + /* AP uses an encryption algorithm: */ + /* a) YES: Turn on the blue LED. */ + /* b) NO: Turn off the blue LED. */ + case LED_WPS_TURN_LED_OFF: + if ((pWscControl->WscState == WSC_STATE_OFF) && + (pWscControl->WscStatus == STATUS_WSC_CONFIGURED)) + { + if (WscAPHasSecuritySetting(pAd, pWscControl) == TRUE) /* The NIC connects with an AP using an encryption algorithm. */ + { + /* Turn WPS success LED. */ + WPSLEDStatus = LED_WPS_TURN_ON_BLUE_LED; + DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_TURN_LED_OFF => LED_WPS_TURN_ON_BLUE_LED\n", __FUNCTION__)); + } + else /* The NIC connects with an AP using OPEN-NONE. */ + { + /* Turn off the WPS LED. */ + WPSLEDStatus = LED_WPS_TURN_LED_OFF; + DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_TURN_LED_OFF => LED_WPS_TURN_LED_OFF\n", __FUNCTION__)); + } + } + break; + + /* Turn off the amber LED after 15 seconds. */ + case LED_WPS_ERROR: + WPSLEDStatus = LED_WPS_TURN_LED_OFF; /* Turn off the WPS LED. */ + + DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_ERROR/LED_WPS_SESSION_OVERLAP_DETECTED => LED_WPS_TURN_LED_OFF\n", __FUNCTION__)); + break; + /* Turn off the amber LED after ~3 seconds. */ + case LED_WPS_SESSION_OVERLAP_DETECTED: + WPSLEDStatus = LED_WPS_TURN_LED_OFF; /* Turn off the WPS LED. */ + + DBGPRINT(RT_DEBUG_TRACE, ("%s: LED_WPS_SESSION_OVERLAP_DETECTED => LED_WPS_TURN_LED_OFF\n", __FUNCTION__)); + break; + + default: + /* do nothing. */ + break; + } + + if (WPSLEDStatus) + RTMPSetLED(pAd, WPSLEDStatus); + } + else + { + /* do nothing. */ + } +} + + +VOID WscSkipTurnOffLEDTimer( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext; + + /* Allow the NIC to turn off the WPS LED again. */ + pWscControl->bSkipWPSTurnOffLED = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: Allow the NIC to turn off the WPS LED again.\n", __FUNCTION__)); +} + +#endif /* WSC_LED_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +VOID WscUpdatePortCfgTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + WSC_CTRL *pWscControl = (WSC_CTRL *)FunctionContext; + RTMP_ADAPTER *pAd = NULL; + BOOLEAN bEnrollee = TRUE; + WSC_CREDENTIAL *pCredential = NULL; + BSS_STRUCT *pMbss = NULL; + + if (pWscControl == NULL) + return; + + pCredential = (PWSC_CREDENTIAL) &pWscControl->WscProfile.Profile[0]; + pAd = (PRTMP_ADAPTER)pWscControl->pAd; + + if (pAd == NULL) + return; + + pMbss = &pAd->ApCfg.MBSSID[pWscControl->EntryIfIdx & 0x0F]; + if (WscGetAuthMode(pCredential->AuthType) == pMbss->wdev.AuthMode && + WscGetWepStatus(pCredential->EncrType) == pMbss->wdev.WepStatus && + NdisEqualMemory(pMbss->Ssid, pCredential->SSID.Ssid, pCredential->SSID.SsidLength) && + NdisEqualMemory(pWscControl->WpaPsk, pCredential->Key, pCredential->KeyLength)) + { + return; + } + + if (pWscControl->WscProfile.ApplyProfileIdx & 0x8000) + bEnrollee = FALSE; + WscWriteConfToPortCfg(pAd, + pWscControl, + &pWscControl->WscProfile.Profile[0], + bEnrollee); + pWscControl->WscProfile.ApplyProfileIdx &= 0x7FFF; + { + pAd->WriteWscCfgToDatFile = (pWscControl->EntryIfIdx & 0x0F); + APStop(pAd); + APStartUp(pAd); + } + +/*#ifdef KTHREAD_SUPPORT */ +/* WAKE_UP(&(pAd->wscTask)); */ +/*#else */ +/* RTMP_SEM_EVENT_UP(&(pAd->wscTask.taskSema)); */ +/*#endif */ + RtmpOsTaskWakeUp(&(pAd->wscTask)); + + return; +} +#endif /* CONFIG_AP_SUPPORT */ + +VOID WscCheckPeerDPID( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 Fr, + IN PUCHAR eid_data, + IN INT eid_len) +{ + WSC_IE *pWscIE; + PUCHAR pData = NULL; + INT Len = 0; + USHORT DevicePasswordID; + PWSC_CTRL pWscCtrl = NULL; + + pData = eid_data + 4; + Len = eid_len - 4; + while (Len > 0) + { + WSC_IE WscIE; + NdisMoveMemory(&WscIE, pData, sizeof(WSC_IE)); + /* Check for WSC IEs*/ + pWscIE = &WscIE; + + /* Check for device password ID, PBC = 0x0004*/ + if (be2cpu16(pWscIE->Type) == WSC_ID_DEVICE_PWD_ID) + { + /* Found device password ID*/ + NdisMoveMemory(&DevicePasswordID, pData + 4, sizeof(DevicePasswordID)); + DevicePasswordID = be2cpu16(DevicePasswordID); + if (DevicePasswordID == DEV_PASS_ID_PBC) /* Check for PBC value*/ + { + WscPBC_DPID_FromSTA(pAd, Fr->Hdr.Addr2); + hex_dump("PBC STA:", Fr->Hdr.Addr2, MAC_ADDR_LEN); + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + } + else if (DevicePasswordID == DEV_PASS_ID_PIN) + { +#ifdef CONFIG_AP_SUPPORT + if ((pAd->OpMode == OPMODE_AP) + ) + { + UCHAR ap_idx = 0; + for (ap_idx = 0; ap_idx < pAd->ApCfg.BssidNum; ap_idx++) + { + if (NdisEqualMemory(Fr->Hdr.Addr1, pAd->ApCfg.MBSSID[ap_idx].wdev.bssid, MAC_ADDR_LEN)) + break; + } + + if (ap_idx >= pAd->ApCfg.BssidNum) + { + break; + } + + pWscCtrl = &pAd->ApCfg.MBSSID[ap_idx].WscControl; + } +#endif /* CONFIG_AP_SUPPORT */ + + /* + WSC 2.0 STA will send probe request with WPS IE anyway. + Do NOT add this STA to WscPeerList after AP is triggered to do PBC. + */ + if (pWscCtrl && + (!pWscCtrl->bWscTrigger || (pWscCtrl->WscMode != WSC_PBC_MODE))) + { + RTMP_SEM_LOCK(&pWscCtrl->WscPeerListSemLock); + WscInsertPeerEntryByMAC(&pWscCtrl->WscPeerList, Fr->Hdr.Addr2); + RTMP_SEM_UNLOCK(&pWscCtrl->WscPeerListSemLock); + } + } + else { + DBGPRINT(RT_DEBUG_TRACE, ("%s : DevicePasswordID = 0x%04x\n", + __FUNCTION__, DevicePasswordID)); + } + break; + } + + + /* 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) +{ + RT_LIST_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; + RT_LIST_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, (RT_LIST_ENTRY *)pWscPeer); + } + ASSERT(pWscPeer != NULL); + } +} + +#ifdef CONFIG_AP_SUPPORT +INT WscApShowPeerList(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UCHAR ApIdx = 0; + PWSC_CTRL pWscControl = NULL; + PWSC_PEER_ENTRY pPeerEntry = NULL; + RT_LIST_ENTRY *pListEntry = NULL; + PLIST_HEADER pWscEnList = NULL; + + for (ApIdx = 0; ApIdx < pAd->ApCfg.BssidNum; ApIdx++) + { + pWscControl = &pAd->ApCfg.MBSSID[ApIdx].WscControl; + pWscEnList = &pWscControl->WscPeerList; + + if (pWscEnList->size != 0) + { + WscMaintainPeerList(pAd, pWscControl); + RTMP_SEM_LOCK(&pWscControl->WscPeerListSemLock); + pListEntry = pWscEnList->pHead; + pPeerEntry = (PWSC_PEER_ENTRY)pListEntry; + while (pPeerEntry != NULL) + { + printk("MAC:%02x:%02x:%02x:%02x:%02x:%02x\tReveive Time:%lu\n", + pPeerEntry->mac_addr[0], + pPeerEntry->mac_addr[1], + pPeerEntry->mac_addr[2], + pPeerEntry->mac_addr[3], + pPeerEntry->mac_addr[4], + pPeerEntry->mac_addr[5], + pPeerEntry->receive_time); + pListEntry = pListEntry->pNext; + pPeerEntry = (PWSC_PEER_ENTRY)pListEntry; + } + RTMP_SEM_UNLOCK(&pWscControl->WscPeerListSemLock); + } + printk("\n"); + } + + return TRUE; +} + +VOID WscSetupLockTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + PWSC_CTRL pWscControl = (PWSC_CTRL)FunctionContext; + PRTMP_ADAPTER pAd = NULL; + + if (pWscControl == NULL) + return; + + pAd = (PRTMP_ADAPTER)pWscControl->pAd; + + if (pAd == NULL) + return; + + pWscControl->bSetupLock = FALSE; + pWscControl->WscSetupLockTimerRunning = FALSE; + + WscBuildBeaconIE(pAd, + pWscControl->WscConfStatus, + FALSE, + 0, + 0, + (pWscControl->EntryIfIdx & 0xF), + NULL, + 0, + AP_MODE); + WscBuildProbeRespIE(pAd, + WSC_MSGTYPE_AP_WLAN_MGR, + pWscControl->WscConfStatus, + FALSE, + 0, + 0, + pWscControl->EntryIfIdx, + NULL, + 0, + AP_MODE); + + APUpdateBeaconFrame(pAd, pWscControl->EntryIfIdx & 0x0F); + DBGPRINT(RT_DEBUG_TRACE, ("WscSetupLockTimeout!\n")); + + return; +} + +VOID WscCheckPinAttackCount( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscControl) +{ + BOOLEAN bCancelled; + + if ((pWscControl->EntryIfIdx & MIN_NET_DEVICE_FOR_APCLI) + ) + { + /* + APCLI and P2P CLI don't need to do PIN attack checking. + */ + return; + } + + /* + If a static PIN is used, + the AP must track multiple failed attempts to authenticate an external Registrar and then enter a lock-down state + (This state is signified by setting the attribute AP Setup Locked to TRUE). + After at most 10 failed, consecutive attempts, with no time limitation, from any number of external Registrars, + the AP shall revert to a locked down state, and the AP shall remain in the locked down state indefinitely + (i.e., until the user intervenes to unlock AP's PIN for use by external Registrars) + */ + pWscControl->PinAttackCount++; + printk("sn 1 - pWscControl->PinAttackCount =%d, pWscControl->MaxPinAttack = %d, SetupLockTime = %d\n", + pWscControl->PinAttackCount, pWscControl->MaxPinAttack, pWscControl->SetupLockTime); + + if (pWscControl->PinAttackCount >= pWscControl->MaxPinAttack) + { + printk("sn 2 - pWscControl->PinAttackCount =%d, pWscControl->MaxPinAttack = %d\n", 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); + } + 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 // + + +VOID WscMaintainPeerList( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWpsCtrl) +{ + PWSC_PEER_ENTRY pPeerEntry = NULL; + RT_LIST_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) +{ + RT_LIST_ENTRY *pListEntry = NULL; + pListEntry = (RT_LIST_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; +} + +#ifdef MT_MAC +VOID WscEapReqIdRetryTimeout( + 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) + && pEntry->bEapReqIdRetryTimerRunning) + { + PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pEntry->pAd; + + DBGPRINT(RT_DEBUG_TRACE, ("%s: re-send EapReqId again.\n", __FUNCTION__)); + WscSendEapReqId(pAd, pEntry, AP_MODE); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("%s: cancel this timer.\n", __FUNCTION__)); + pEntry->EapReqIdRetryTimer.PeriodicType = FALSE; + pEntry->EapReqIdRetryTimer.Repeat = FALSE; + } + + return; +} + +#endif /* MT_MAC */ + +#endif /* WSC_INCLUDED */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wsc_tlv.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wsc_tlv.c new file mode 100644 index 000000000..41fb4dc0d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wsc_tlv.c @@ -0,0 +1,4324 @@ +/* + *************************************************************************** + * 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 */ + /* 0x106F ¡V 0x1FFF*/ + /* 0x000 ¡V 0x0FFF,0x2000 ¡V 0xFFFF*/ +}; + +extern UINT8 WPS_DH_G_VALUE[1]; +extern UINT8 WPS_DH_P_VALUE[192]; + +int AppendWSCTLV(USHORT index, OUT UCHAR * obuf, IN UCHAR * ibuf, IN USHORT varlen) +{ + USHORT len, dataLen, tag = cpu2be16(index); + + /* + The max len of WPS Vendor Extension is 1024B + */ + dataLen = ( varlen != (USHORT)0 ) ? varlen : wsc_tlv_0b[WSC_TLV_ENT(index)].len; + + NdisMoveMemory(obuf, &tag, 2); + len = cpu2be16(dataLen); + memcpy(obuf + 2, &len, 2); + if (dataLen != 0) + memcpy(obuf + 4, ibuf, dataLen); + return (dataLen + 4); +} + +/* + ======================================================================== + + Routine Description: + Process elements encryption settings + + Arguments: + pAdapter - NIC Adapter pointer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + 1. Recv M4 M5 M6 M7 + + ======================================================================== +*/ +static VOID WscParseEncrSettings( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR pPlainData, + IN INT PlainLength, + IN PWSC_CTRL pWscControl) +{ + USHORT WscType, WscLen, HmacLen; + PUCHAR pData; + UCHAR Hmac[8]={0}, 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; + + + 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 + + ======================================================================== +*/ +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 */ + + 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; + 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; + + + 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]={0}; + unsigned char hmac[32]; + unsigned int temp; + + iterations = ((keyBits/8) + 32 - 1)/32; + + /*Prepare the input buffer. During the iterations, we need only replace the */ + /*value of i at the start of the buffer. */ + temp = cpu2be32(i); + memcpy(input, &temp, 4); + memcpy(input+4, prsnlString, str_len); + + temp = cpu2be32(keyBits); + memcpy(input+4+str_len, &temp, 4); + + for(i = 0; i < iterations; i++) + { + /*Set the current value of i at the start of the input buffer */ + temp = cpu2be32(i+1); /*i should start at 1 */ + memcpy(input,&temp,4); + RT_HMAC_SHA256(kdk, kdk_len, input, 4+str_len+4, hmac, SHA256_DIGEST_SIZE); + memcpy(output+i*32, hmac, 32); + } + + /*Sanity check */ + if(keyBits/8 > (32*iterations)) + { + + return 1; /*failed */ + } + + memcpy(key, output, 80); + + return 0; /*success */ + +} + +VOID WscGenPSK1( + PRTMP_ADAPTER pAd, + PWSC_CTRL pWscCtrl, + UCHAR *pPSK1) +{ + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscCtrl->RegData; + PUCHAR pTempPsk = NULL; +#ifdef WSC_NFC_SUPPORT + PUCHAR pTempPasswd = NULL; + UCHAR idx; +#endif /* WSC_NFC_SUPPORT */ + + os_alloc_mem(NULL, &pTempPsk, SHA256_DIGEST_SIZE); + if (pTempPsk == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s - pTempPsk alloc failed.", __FUNCTION__)); + return; + } + +#ifdef WSC_NFC_SUPPORT + if (pWscCtrl->bTriggerByNFC) + { + hex_dump("WscGenPSK1 1 - NfcPasswd", &pWscCtrl->NfcPasswd[0], pWscCtrl->NfcPasswdLen/2); + hex_dump("WscGenPSK1 - pReg->AuthKey", pReg->AuthKey, 32); + os_alloc_mem(NULL, &pTempPasswd, pWscCtrl->NfcPasswdLen); + if (pTempPasswd) + { + NdisZeroMemory(pTempPasswd, pWscCtrl->NfcPasswdLen); + if (pWscCtrl->NfcPasswdCaculate == 2) + { + for (idx = 0; idx < (pWscCtrl->NfcPasswdLen/2); idx++) + sprintf((RTMP_STRING *) pTempPasswd, "%s%02X", pTempPasswd, pWscCtrl->NfcPasswd[idx]); + RT_HMAC_SHA256(pReg->AuthKey, 32, pTempPasswd, pWscCtrl->NfcPasswdLen, pTempPsk, SHA256_DIGEST_SIZE); + } + else + { + RT_HMAC_SHA256(pReg->AuthKey, 32, pWscCtrl->NfcPasswd, pWscCtrl->NfcPasswdLen/2, pTempPsk, SHA256_DIGEST_SIZE); + } + + os_free_mem(NULL, pTempPasswd); + } + } + else +#endif /* WSC_NFC_SUPPORT */ + { + printk("sn - PinCodeLen = %d\n", pReg->PinCodeLen); //snowpin test + hex_dump("WscGenPSK1: PIN", pReg->PIN, 8); //snowpin test + // Generate PSK1 + if (pReg->PinCodeLen == 4) + RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[0], 2, pTempPsk, SHA256_DIGEST_SIZE); + else + RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[0], 4, pTempPsk, SHA256_DIGEST_SIZE); + } + NdisMoveMemory(pPSK1, pTempPsk, SHA256_DIGEST_SIZE); + os_free_mem(NULL, pTempPsk); +} + +VOID WscGenPSK2( + PRTMP_ADAPTER pAd, + PWSC_CTRL pWscCtrl, + UCHAR *pPSK2) +{ + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscCtrl->RegData; + PUCHAR pTempPsk = NULL; +#ifdef WSC_NFC_SUPPORT + PUCHAR pTempPasswd = NULL; + UCHAR idx; +#endif /* WSC_NFC_SUPPORT */ + + os_alloc_mem(NULL, &pTempPsk, SHA256_DIGEST_SIZE); + if (pTempPsk == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s - pTempPsk alloc failed.", __FUNCTION__)); + return; + } + +#ifdef WSC_NFC_SUPPORT + if (pWscCtrl->bTriggerByNFC) + { + hex_dump("WscGenPSK2 1 - NfcPasswd", &pWscCtrl->NfcPasswd[pWscCtrl->NfcPasswdLen/2], pWscCtrl->NfcPasswdLen/2); + hex_dump("WscGenPSK2 - pReg->AuthKey", pReg->AuthKey, 32); + os_alloc_mem(NULL, &pTempPasswd, pWscCtrl->NfcPasswdLen); + if (pTempPasswd) + { + NdisZeroMemory(pTempPasswd, pWscCtrl->NfcPasswdLen); + if (pWscCtrl->NfcPasswdCaculate == 2) + { + for (idx = (pWscCtrl->NfcPasswdLen/2); idx < pWscCtrl->NfcPasswdLen; idx++) + sprintf((RTMP_STRING *) pTempPasswd, "%s%02X", pTempPasswd, pWscCtrl->NfcPasswd[idx]); + RT_HMAC_SHA256(pReg->AuthKey, 32, pTempPasswd, pWscCtrl->NfcPasswdLen, pTempPsk, SHA256_DIGEST_SIZE); + } + else + { + RT_HMAC_SHA256(pReg->AuthKey, 32, &pWscCtrl->NfcPasswd[pWscCtrl->NfcPasswdLen/2], pWscCtrl->NfcPasswdLen/2, pTempPsk, SHA256_DIGEST_SIZE); + } + os_free_mem(NULL, pTempPasswd); + } + } + else +#endif /* WSC_NFC_SUPPORT */ + { + // Generate PSK2 + if (pReg->PinCodeLen == 4) + RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[2], 2, pTempPsk, SHA256_DIGEST_SIZE); + else + RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[4], 4, pTempPsk, SHA256_DIGEST_SIZE); + } + NdisMoveMemory(pPSK2, pTempPsk, SHA256_DIGEST_SIZE); + os_free_mem(NULL, pTempPsk); +} + + +/* + ======================================================================== + + Routine Description: + Build WSC M1 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - rewrite buffer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after Rx EAP-Req(ID) + 1. Change the correct parameters + 2. Build M1 + + ======================================================================== +*/ +int BuildMessageM1( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf) +{ + UCHAR TB[1]; + INT Len = 0, templen = 0; + PUCHAR pData = (PUCHAR)pbuf; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData; + INT idx; + USHORT ConfigError = 0, ConfigMethods = 0; +#ifdef WSC_V2_SUPPORT + PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv; +#endif /* WSC_V2_SUPPORT */ + UCHAR CurOpMode = 0xFF; + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + CurOpMode = AP_MODE; +#endif /* CONFIG_AP_SUPPORT */ + + + // 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 & 0x210F); + }*/ + + + if ((CurOpMode == AP_MODE) && ((pWscControl->WscConfMode & WSC_ENROLLEE) != 0) + && (pWscControl->WscMode == WSC_PBC_MODE)) + { + ConfigMethods |= WSC_CONFMET_PBC; + DBGPRINT(RT_DEBUG_TRACE, ("[NOTICE] BuildMessageM1 - Add PBC in ConfigMethods for AP_MODE & WSC_ENROLLEE & PBC\n")); + }else if( CurOpMode == AP_MODE ){ + ConfigMethods = (pWscControl->WscConfigMethods & 0x210F); + } + } + 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((RTMP_STRING *) pReg->SelfInfo.Manufacturer)); + pData += templen; + Len += templen; + + /*13. Model Name */ + templen = AppendWSCTLV(WSC_ID_MODEL_NAME, pData, pReg->SelfInfo.ModelName, strlen((RTMP_STRING *) pReg->SelfInfo.ModelName)); + pData += templen; + Len += templen; + + /*14. Model Number */ + templen = AppendWSCTLV(WSC_ID_MODEL_NUMBER, pData, pReg->SelfInfo.ModelNumber, strlen((RTMP_STRING *) pReg->SelfInfo.ModelNumber)); + pData += templen; + Len += templen; + + /*15. Serial Number */ + templen = AppendWSCTLV(WSC_ID_SERIAL_NUM, pData, pReg->SelfInfo.SerialNumber, strlen((RTMP_STRING *) 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((RTMP_STRING *) pReg->SelfInfo.DeviceName)); + pData += templen; + Len += templen; + + /*18. RF Band */ + templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, (UINT8 *)&pReg->SelfInfo.RfBand, 0); + pData += templen; + Len += templen; + + /*19. Associate state (Not associated) */ + templen = AppendWSCTLV(WSC_ID_ASSOC_STATE, pData, (UINT8 *)&pReg->SelfInfo.AssocState, 0); + pData += templen; + Len += templen; + + /*20. Device Password ID */ +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC) + { + templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&pWscControl->NfcPasswdID, 0); + } + else +#endif /* WSC_NFC_SUPPORT */ + templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&pReg->SelfInfo.DevPwdId, 0); + pData += templen; + Len += templen; + + /*21. Configure Error */ + templen = AppendWSCTLV(WSC_ID_CONFIG_ERROR, pData, (UINT8 *)&ConfigError, 0); + pData += templen; + Len += templen; + + /*22. OS Version Not associated) */ + templen = AppendWSCTLV(WSC_ID_OS_VERSION, pData, (UINT8 *)&pReg->SelfInfo.OsVersion, 0); + pData += templen; + Len += templen; + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscControl, + FALSE, + NULL, + 0, + &pData, + &Len); + + /* Extra attribute that is not defined in WSC Sepc. */ + if (pWscTLV->pTlvData && pWscTLV->TlvLen) + { + templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen); + pData += templen; + Len += templen; + } + } +#endif /* WSC_V2_SUPPORT */ + + + + +#ifdef WSC_V2_SUPPORT + /* Extra attribute that is not defined in WSC Sepc. */ + if (pWscControl->WscV2Info.bEnableWpsV2 && pWscTLV->pTlvData && pWscTLV->TlvLen) + { + templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen); + pData += templen; + Len += templen; + } +#endif /* WSC_V2_SUPPORT */ + + DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM1 - bUPnPMsgTimerRunning = %d, pWscControl->WscUseUPnP = %d, pWscControl->EapMsgRunning = %d\n", + pWscControl->WscUPnPNodeInfo.bUPnPMsgTimerRunning, + pWscControl->WscUseUPnP, + pWscControl->EapMsgRunning)); + + /* Fixed WCN vista logo 2 registrar test item issue. */ + /* Also prevent that WCN GetDeviceInfo disturbs EAP processing. */ + if (pWscControl->WscUPnPNodeInfo.bUPnPMsgTimerRunning || + (pWscControl->WscUseUPnP && pWscControl->EapMsgRunning)) + ; + else + { + /* Copy the content to Regdata for lasttx information */ + pReg->LastTx.Length = Len; + NdisMoveMemory(pReg->LastTx.Data, pbuf, Len); + } + + pWscControl->WscRetryCount = 0; + DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM1.\n")); + return Len; +} + +/* + ======================================================================== + + Routine Description: + Build WSC M2 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - rewrite buffer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after M1 + 1. Change the correct parameters + 2. Build M2 + + ======================================================================== +*/ +int BuildMessageM2( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf) +{ +#ifdef WSC_NFC_SUPPORT + UCHAR TB[256]; +#else + UCHAR TB[1]; +#endif + INT Len = 0, templen = 0; + PUCHAR pData = (PUCHAR)pbuf, pAuth; + PWSC_REG_DATA pReg; + UCHAR DHKey[32], KDK[32], KdkInput[38], KdfKey[80]; + INT DH_Len; + INT HmacLen = 0; + INT idx; + USHORT ConfigMethods; +#ifdef WSC_V2_SUPPORT + PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv; +#endif /* WSC_V2_SUPPORT */ + + pReg = (PWSC_REG_DATA) &pWscControl->RegData; + + // Enrollee 16 byte E-S1 generation + for (idx = 0; idx < 16; idx++) + { + pReg->Es1[idx] = RandomByte(pAdapter); + } + + // Enrollee 16 byte E-S2 generation + for (idx = 0; idx < 16; idx++) + { + pReg->Es2[idx] = RandomByte(pAdapter); + } + + DH_Len = sizeof(pReg->SecretKey); + 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. + */ + } + 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((RTMP_STRING *) pReg->SelfInfo.Manufacturer)); + pData += templen; + Len += templen; + + /* Model Name */ + templen = AppendWSCTLV(WSC_ID_MODEL_NAME, pData, pReg->SelfInfo.ModelName, strlen((RTMP_STRING *) pReg->SelfInfo.ModelName)); + pData += templen; + Len += templen; + + /* Model Number */ + templen = AppendWSCTLV(WSC_ID_MODEL_NUMBER, pData, pReg->SelfInfo.ModelNumber, strlen((RTMP_STRING *) pReg->SelfInfo.ModelNumber)); + pData += templen; + Len += templen; + + /* Serial Number */ + templen = AppendWSCTLV(WSC_ID_SERIAL_NUM, pData, pReg->SelfInfo.SerialNumber, strlen((RTMP_STRING *) 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((RTMP_STRING *) pReg->SelfInfo.DeviceName)); + pData += templen; + Len += templen; + + /* RF Band */ + templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, (UINT8 *)&pReg->SelfInfo.RfBand, 0); + pData += templen; + Len += templen; + + /* Assoc State */ + templen = AppendWSCTLV(WSC_ID_ASSOC_STATE, pData, (UINT8 *)&pReg->SelfInfo.AssocState, 0); + pData += templen; + Len += templen; + + /* Config Error */ + templen = AppendWSCTLV(WSC_ID_CONFIG_ERROR, pData, (UINT8 *)&pReg->SelfInfo.ConfigError, 0); + pData += templen; + Len += templen; + + /* Device Password ID */ +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC) + { + templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&pWscControl->PeerNfcPasswdID, 0); + } + else +#endif /* WSC_NFC_SUPPORT */ + templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&pReg->SelfInfo.DevPwdId, 0); + pData += templen; + Len += templen; + + /* OS Version */ + templen = AppendWSCTLV(WSC_ID_OS_VERSION, pData, (UINT8 *)&pReg->SelfInfo.OsVersion, 0); + pData += templen; + Len += templen; + + + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscControl, + FALSE, + NULL, + 0, + &pData, + &Len); + + /* Extra attribute that is not defined in WSC Sepc. */ + if (pWscTLV->pTlvData && pWscTLV->TlvLen) + { + templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen); + pData += templen; + Len += templen; + } + } +#endif /* WSC_V2_SUPPORT */ + + /* Create KDK input data */ + NdisMoveMemory(&KdkInput[0], &pReg->EnrolleeNonce[0], 16); + NdisMoveMemory(&KdkInput[16], &pReg->PeerInfo.MacAddr[0], 6); + NdisMoveMemory(&KdkInput[22], pReg->RegistrarNonce, 16); + + /* Generate the KDK */ + RT_HMAC_SHA256(DHKey, 32, KdkInput, 38, KDK, SHA256_DIGEST_SIZE); + + /* KDF */ + WscDeriveKey(KDK, 32, Wsc_Personal_String, (sizeof(Wsc_Personal_String) - 1), KdfKey, 640); + + /* Assign Key from KDF */ + NdisMoveMemory(pReg->AuthKey, &KdfKey[0], 32); + NdisMoveMemory(pReg->KeyWrapKey, &KdfKey[32], 16); + NdisMoveMemory(pReg->Emsk, &KdfKey[48], 32); + +#ifdef WSC_NFC_SUPPORT +#ifdef CONFIG_AP_SUPPORT + if (pWscControl->bTriggerByNFC && pWscControl->NfcModel == MODEL_HANDOVER) + { + PWSC_CREDENTIAL pCredential = NULL; + INT CerLen = 0, PlainLen = 0, EncrLen; + USHORT AuthType = 0; + USHORT EncrType = 0; + UCHAR Plain[300], *IV_EncrData; + + IV_EncrData = kmalloc(512, MEM_ALLOC_FLAG); + if(IV_EncrData) + { + WscCreateProfileFromCfg(pAdapter, REGISTRAR_ACTION | AP_MODE, pWscControl, &pWscControl->WscProfile); + pCredential = &pAdapter->ApCfg.MBSSID[0].WscControl.WscProfile.Profile[0]; + + // 4a. Encrypted R-S1 + CerLen += AppendWSCTLV(WSC_ID_NW_INDEX, &TB[0], (PUCHAR)"1", 0); + + AuthType = cpu2be16(pCredential->AuthType); + EncrType = cpu2be16(pCredential->EncrType); + CerLen += AppendWSCTLV(WSC_ID_SSID, &TB[CerLen], pCredential->SSID.Ssid, pCredential->SSID.SsidLength); + CerLen += AppendWSCTLV(WSC_ID_AUTH_TYPE, &TB[CerLen], (UINT8 *)&AuthType, 0); + CerLen += AppendWSCTLV(WSC_ID_ENCR_TYPE, &TB[CerLen], (UINT8 *)&EncrType, 0); + CerLen += AppendWSCTLV(WSC_ID_NW_KEY_INDEX, &TB[CerLen], &pCredential->KeyIndex, 0); + CerLen += AppendWSCTLV(WSC_ID_NW_KEY, &TB[CerLen], pCredential->Key, pCredential->KeyLength); + CerLen += AppendWSCTLV(WSC_ID_MAC_ADDR, &TB[CerLen], pCredential->MacAddr, 0); + + // Prepare plain text + // Reguired attribute item in M8 if Enrollee is STA. + if (pAdapter->OpMode == OPMODE_AP) + PlainLen += AppendWSCTLV(WSC_ID_CREDENTIAL, &Plain[0], TB, CerLen); + + // Generate HMAC + RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE); + PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0); + + // 4b. Encrypted Settings + // Encrypt data + EncrLen = sizeof(IV_EncrData) - 16; + AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen); + templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, IV_EncrData, 16 + EncrLen);//IVLen + EncrLen + pData += templen; + Len += templen; + + kfree(IV_EncrData); + } + } +#endif // CONFIG_AP_SUPPORT // +#endif /* WSC_NFC_SUPPORT */ + + + /* Combine last TX & RX message contents and validate the HMAC */ + /* We have to exclude last 12 bytes from last receive since it's authenticator value */ + HmacLen = Len + pReg->LastRx.Length; + if (pAdapter->pHmacData) + { + pAuth = (PUCHAR) pAdapter->pHmacData; + NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length); + pAuth += pReg->LastRx.Length; + NdisMoveMemory(pAuth, pbuf, Len); + + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE); + } + /* 22. Hmac */ + templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, KDK, 0); + pData += templen; + Len += templen; + + /* Copy the content to Regdata for lasttx information */ + pReg->LastTx.Length = Len; + NdisMoveMemory(pReg->LastTx.Data, pbuf, Len); + + pWscControl->WscRetryCount = 0; + DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM2.\n")); + return Len; +} + +/* + ======================================================================== + + Routine Description: + Build WSC M2D Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - rewrite buffer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after M1 process Error + 1. Change the correct parameters + 2. Build M2D + + ======================================================================== +*/ +int BuildMessageM2D( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf) +{ + UCHAR TB[1]; + INT Len = 0, templen = 0; + PUCHAR pData = (PUCHAR)pbuf; + PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData; +#ifdef WSC_V2_SUPPORT + PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv; +#endif /* WSC_V2_SUPPORT */ + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Message Type, M2D */ + TB[0] = WSC_ID_MESSAGE_M2D; + templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0); + pData += templen; + Len += templen; + + /* 3. Enrollee Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0); + pData += templen; + Len += templen; + + /* 4. Registrar Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->SelfNonce, 0); + /*templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0); */ + pData += templen; + Len += templen; + + /* UUID, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_UUID_R, pData, pReg->SelfInfo.Uuid, 0); + pData += templen; + Len += templen; + + + /* 7. Authentication Type Flags */ + templen = AppendWSCTLV(WSC_ID_AUTH_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.AuthTypeFlags, 0); + pData += templen; + Len += templen; + + /* Encrypt Type */ + templen = AppendWSCTLV(WSC_ID_ENCR_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.EncrTypeFlags, 0); + pData += templen; + Len += templen; + + /* Connection Type */ + templen = AppendWSCTLV(WSC_ID_CONN_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.ConnTypeFlags, 0); + pData += templen; + Len += templen; + + /* Config Methods */ + templen = AppendWSCTLV(WSC_ID_CONFIG_METHODS, pData, (UINT8 *)&pReg->SelfInfo.ConfigMethods, 0); + pData += templen; + Len += templen; + + /* Manufacturer Name */ + templen = AppendWSCTLV(WSC_ID_MANUFACTURER, pData, pReg->SelfInfo.Manufacturer, strlen((RTMP_STRING *) pReg->SelfInfo.Manufacturer)); + pData += templen; + Len += templen; + + /* Model Name */ + templen = AppendWSCTLV(WSC_ID_MODEL_NAME, pData, pReg->SelfInfo.ModelName, strlen((RTMP_STRING *) pReg->SelfInfo.ModelName)); + pData += templen; + Len += templen; + + /* Model Number */ + templen = AppendWSCTLV(WSC_ID_MODEL_NUMBER, pData, pReg->SelfInfo.ModelNumber, strlen((RTMP_STRING *) pReg->SelfInfo.ModelNumber)); + pData += templen; + Len += templen; + + /* Serial Number */ + templen = AppendWSCTLV(WSC_ID_SERIAL_NUM, pData, pReg->SelfInfo.SerialNumber, strlen((RTMP_STRING *) 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((RTMP_STRING *) 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 */ + + os_alloc_mem(NULL, (UCHAR **)&pHash, 512); + if(NULL == pHash) + return Len; + pReg = (PWSC_REG_DATA) &pWscControl->RegData; + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Message Type, M3 */ + TB[0] = WSC_ID_MESSAGE_M3; + templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0); + pData += templen; + Len += templen; + + /* 3. Registrar Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0); + pData += templen; + Len += templen; + + /* 4. E-Hash1 */ + /* */ + /* Generate PSK1 */ + WscGenPSK1(pAdapter, pWscControl, &TB[0]); + + /* Copy first 16 bytes to PSK1 */ + NdisMoveMemory(pReg->Psk1, TB, 16); + + hex_dump("Es1", pReg->Es1, 16); + hex_dump("Es2", pReg->Es2, 16); + + /* Create input for E-Hash1 */ + NdisMoveMemory(pHash, pReg->Es1, 16); + NdisMoveMemory(pHash + 16, pReg->Psk1, 16); + NdisMoveMemory(pHash + 32, pReg->Pke, 192); + NdisMoveMemory(pHash + 224, pReg->Pkr, 192); + + /* Generate E-Hash1 */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, pReg->EHash1, SHA256_DIGEST_SIZE); + + templen = AppendWSCTLV(WSC_ID_E_HASH1, pData, pReg->EHash1, 0); + pData += templen; + Len += templen; + + /* 5. E-Hash2 */ + /* */ + /* Generate PSK2 */ + WscGenPSK2(pAdapter, pWscControl, &TB[0]); + /* Copy first 16 bytes to PSK2 */ + NdisMoveMemory(pReg->Psk2, TB, 16); + + /* Create input for E-Hash2 */ + NdisMoveMemory(pHash, pReg->Es2, 16); + NdisMoveMemory(pHash + 16, pReg->Psk2, 16); + NdisMoveMemory(pHash + 32, pReg->Pke, 192); + NdisMoveMemory(pHash + 224, pReg->Pkr, 192); + + /* Generate E-Hash2 */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, pReg->EHash2, SHA256_DIGEST_SIZE); + + templen = AppendWSCTLV(WSC_ID_E_HASH2, pData, pReg->EHash2, 0); + pData += templen; + Len += templen; + + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscControl, + FALSE, + NULL, + 0, + &pData, + &Len); + + /* Extra attribute that is not defined in WSC Sepc. */ + if (pWscTLV->pTlvData && pWscTLV->TlvLen) + { + templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen); + pData += templen; + Len += templen; + } + } +#endif /* WSC_V2_SUPPORT */ + + /* + Generate authenticator + Combine last TX & RX message contents and validate the HMAC + */ + HmacLen = Len + pReg->LastRx.Length; + if (pAdapter->pHmacData) + { + pAuth = (PUCHAR) pAdapter->pHmacData; + NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length); + pAuth += pReg->LastRx.Length; + NdisMoveMemory(pAuth, pbuf, Len); + + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, TB, SHA256_DIGEST_SIZE); + } + + templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, TB, 0); + pData += templen; + Len += templen; + + /* Copy the content to Regdata for lasttx information */ + pReg->LastTx.Length = Len; + NdisMoveMemory(pReg->LastTx.Data, pbuf, Len); + + if(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 */ + + os_alloc_mem(NULL, (UCHAR **)&pHash, 512); + if(NULL == pHash) + return Len; + + os_alloc_mem(NULL, (UCHAR **)&IV_EncrData, IV_ENCR_DATA_LEN_144); + if (IV_EncrData == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__)); + goto LabelErr; + } + + /* 1. Version */ + templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0); + pData += templen; + Len += templen; + + /* 2. Message Type, M4 */ + TB[0] = WSC_ID_MESSAGE_M4; + templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0); + pData += templen; + Len += templen; + + /* 3. Enrollee Nonce, 16 bytes */ + templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0); + pData += templen; + Len += templen; + + /* 4. R-Hash1 */ + /* */ + /* Generate PSK1 */ + WscGenPSK1(pAdapter, pWscControl, &TB[0]); + + /* Copy first 16 bytes to PSK1 */ + NdisMoveMemory(pReg->Psk1, TB, 16); + + hex_dump("Es1", pReg->Es1, 16); + hex_dump("Es2", pReg->Es2, 16); + /* Create input for R-Hash1 */ + NdisMoveMemory(pHash, pReg->Es1, 16); + NdisMoveMemory(pHash + 16, pReg->Psk1, 16); + NdisMoveMemory(pHash + 32, pReg->Pke, 192); + NdisMoveMemory(pHash + 224, pReg->Pkr, 192); + + /* Generate R-Hash1 */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, pReg->RHash1, SHA256_DIGEST_SIZE); + + templen = AppendWSCTLV(WSC_ID_R_HASH1, pData, pReg->RHash1, 0); + pData += templen; + Len += templen; + + /* 5. R-Hash2 */ + /* */ + /* Generate PSK2 */ + WscGenPSK2(pAdapter, pWscControl, &TB[0]); + + /* Copy first 16 bytes to PSK2 */ + NdisMoveMemory(pReg->Psk2, TB, 16); + + /* Create input for R-Hash2 */ + NdisMoveMemory(pHash, pReg->Es2, 16); + NdisMoveMemory(pHash + 16, pReg->Psk2, 16); + NdisMoveMemory(pHash + 32, pReg->Pke, 192); + NdisMoveMemory(pHash + 224, pReg->Pkr, 192); + + /* Generate R-Hash2 */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, pReg->RHash2, SHA256_DIGEST_SIZE); + + templen = AppendWSCTLV(WSC_ID_R_HASH2, pData, pReg->RHash2, 0); + pData += templen; + Len += templen; + + /* 6a. Encrypted R-S1 */ + /* Prepare plain text */ + PlainLen += AppendWSCTLV(WSC_ID_R_SNONCE1, &Plain[0], pReg->Es1, 0); + + /* Generate HMAC */ + RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE); + PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0); + + /* 6b. Encrypted Settings */ + /* Encrypt data */ + EncrLen = IV_ENCR_DATA_LEN_144 - 16; + AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen); + templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, &IV_EncrData[0], 16 + EncrLen);/*IVLen + EncrLen */ + pData += templen; + Len += templen; + + +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + /* Version2 */ + WscGenV2Msg(pWscControl, + FALSE, + NULL, + 0, + &pData, + &Len); + + /* Extra attribute that is not defined in WSC Sepc. */ + if (pWscTLV->pTlvData && pWscTLV->TlvLen) + { + templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen); + pData += templen; + Len += templen; + } + } +#endif /* WSC_V2_SUPPORT */ + + /* + Combine last TX & RX message contents and validate the HMAC + We have to exclude last 12 bytes from last receive since it's authenticator value + */ + HmacLen = Len + pReg->LastRx.Length; + if (pAdapter->pHmacData) + { + pAuth = (PUCHAR) pAdapter->pHmacData; + NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length); + pAuth += pReg->LastRx.Length; + NdisMoveMemory(pAuth, pbuf, Len); + + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE); + } + + templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, KDK, 0); + pData += templen; + Len += templen; + + /* Copy the content to Regdata for lasttx information */ + pReg->LastTx.Length = Len; + NdisMoveMemory(pReg->LastTx.Data, pbuf, Len); + +LabelErr: + if(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; + + 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 */ + + + /* 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(IV_EncrData) + os_free_mem(NULL, IV_EncrData); + + pWscControl->WscRetryCount = 0; + DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM7 : \n")); + return Len; +} + +unsigned char same_band_profile( + PWSC_CTRL pWscControl, + unsigned char profile_index, + struct wifi_dev *wdev) +{ + int i = 0; + struct wifi_dev *wdev_entry = NULL; + PRTMP_ADAPTER ad = wdev->sys_handle; + + for (i = 0; i < HW_BEACON_MAX_NUM; i++) { + wdev_entry = ad->wdev_list[i]; + if (wdev_entry == NULL) + continue; + if (MAC_ADDR_EQUAL(wdev_entry->bssid, + pWscControl->WscBhProfiles.Profile[profile_index].MacAddr)) { + if (wdev_entry->channel == wdev->channel) + return TRUE; + else + return FALSE; + } + } + return FALSE; +} +/* + ======================================================================== + + 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; + + 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 */ + + + /* 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 */ + + { + /* 4a. Encrypted R-S1 */ + CerLen += AppendWSCTLV(WSC_ID_NW_INDEX, &TB[0], (PUCHAR)"1", 0); + + if (pCredential == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: pWscControl == NULL!\n", __FUNCTION__)); + goto LabelErr; + } + + AuthType = pCredential->AuthType; + EncrType = pCredential->EncrType; + /* + Some Win7 WSC 1.0 STA has problem to receive mixed authType and encyType. + We need to check STA is WSC 1.0 or WSC 2.0 here. + If STA is WSC 1.0, re-assign authType and encyType. + */ + { + if (AuthType == (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK)) + AuthType = WSC_AUTHTYPE_WPA2PSK; + if (EncrType == (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES)) + EncrType = WSC_ENCRTYPE_AES; + } + + AuthType = cpu2be16(AuthType); + EncrType = cpu2be16(EncrType); + CerLen += AppendWSCTLV(WSC_ID_SSID, &TB[CerLen], pCredential->SSID.Ssid, pCredential->SSID.SsidLength); + CerLen += AppendWSCTLV(WSC_ID_AUTH_TYPE, &TB[CerLen], (UINT8 *)&AuthType, 0); + CerLen += AppendWSCTLV(WSC_ID_ENCR_TYPE, &TB[CerLen], (UINT8 *)&EncrType, 0); + CerLen += AppendWSCTLV(WSC_ID_NW_KEY_INDEX, &TB[CerLen], &pCredential->KeyIndex, 0); + CerLen += AppendWSCTLV(WSC_ID_NW_KEY, &TB[CerLen], pCredential->Key, pCredential->KeyLength); + CerLen += AppendWSCTLV(WSC_ID_MAC_ADDR, &TB[CerLen], pCredential->MacAddr, 0); + + /* Prepare plain text */ + } + if ((CurOpMode == AP_MODE) + ) + { + /* Reguired attribute item in M8 if Enrollee is STA. */ + PlainLen += AppendWSCTLV(WSC_ID_CREDENTIAL, &Plain[0], TB, CerLen); + } + + /* Generate HMAC */ + RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE); + PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0); + + /* 4b. Encrypted Settings */ + /* Encrypt data */ + EncrLen = 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(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}; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + //CurOpMode = AP_MODE; +#endif /* CONFIG_AP_SUPPORT */ + + + pReg->PeerInfo.Version2 = 0; +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC) + pWscControl->RegData.SelfInfo.ConfigError = WSC_ERROR_NO_ERROR; + + if (pWscControl->bTriggerByNFC && pWscControl->bRegenPublicKey == 0) + ; /* Do NOT need to generate EnrolleeRandom and DH public key here. */ + else +#endif /* WSC_NFC_SUPPORT */ + { + + DH_Len = sizeof(pReg->Pkr); + /* 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); +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC) + { + DBGPRINT(RT_DEBUG_ERROR, ("Re-generate public key for negative test!\n")); + pWscControl->bRegenPublicKey = 0; + } +#endif /* WSC_NFC_SUPPORT */ + } + + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_UUID_E))] |= (1 << WSC_TLV_BYTE1(WSC_ID_UUID_E)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MAC_ADDR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MAC_ADDR)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PUBLIC_KEY))] |= (1 << WSC_TLV_BYTE1(WSC_ID_PUBLIC_KEY)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTH_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTH_TYPE_FLAGS)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_TYPE_FLAGS)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONN_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONN_TYPE_FLAGS)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_METHODS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_METHODS)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SC_STATE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_SC_STATE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MANUFACTURER))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MANUFACTURER)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NAME))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NAME)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NUMBER))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NUMBER)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SERIAL_NUM))] |= (1 << WSC_TLV_BYTE1(WSC_ID_SERIAL_NUM)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PRIM_DEV_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_PRIM_DEV_TYPE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_NAME))] |= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_NAME)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_RF_BAND))] |= (1 << WSC_TLV_BYTE1(WSC_ID_RF_BAND)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ASSOC_STATE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ASSOC_STATE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_ERROR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_ERROR)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_PWD_ID))] |= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_PWD_ID)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_OS_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_OS_VERSION)); + /* Copy the content to Regdata for lastRx information */ + /* Length must include authenticator IE size */ + pReg->LastRx.Length = Length; + NdisMoveMemory(pReg->LastRx.Data, precv, Length); + pData = pReg->LastRx.Data; + + NdisZeroMemory(&pWscControl->WscPeerInfo, sizeof(WSC_PEER_DEV_INFO)); + + /* Start to process WSC IEs */ + while (Length > 4) + { + WSC_IE TLV_Recv; + memcpy((UINT8 *)&TLV_Recv, pData, 4); + WscType = be2cpu16(TLV_Recv.Type); + WscLen = be2cpu16(TLV_Recv.Length); + pData += 4; + Length -= 4; + + /* Parse M1 WSC type and store to RegData structure */ + switch (WscType) + { + case WSC_ID_VERSION: + if(pReg->SelfInfo.Version != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION)); + break; + + case WSC_ID_MSG_TYPE: + if(WSC_ID_MESSAGE_M1 != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE)); + break; + + case WSC_ID_UUID_E: + NdisMoveMemory(pReg->PeerInfo.Uuid, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_UUID_E))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_UUID_E)); + break; + + case WSC_ID_MAC_ADDR: + NdisMoveMemory(pReg->PeerInfo.MacAddr, pData, WscLen); + NdisMoveMemory(pWscControl->WscPeerInfo.WscPeerMAC, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MAC_ADDR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MAC_ADDR)); + break; + + case WSC_ID_ENROLLEE_NONCE: + NdisMoveMemory(pReg->EnrolleeNonce, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE)); + break; + + case WSC_ID_PUBLIC_KEY: + /* Get Enrollee Public Key */ + NdisMoveMemory(pReg->Pke, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PUBLIC_KEY))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_PUBLIC_KEY)); +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC) + { + UCHAR HashData[SHA256_DIGEST_SIZE]; + RT_SHA256(&pWscControl->RegData.Pke[0], 192, &HashData[0]); + hex_dump("public_key RAW:", &pWscControl->RegData.Pke[0], 192); + if (NdisEqualMemory(&HashData[0], &pWscControl->PeerNfcPasswdHash[0], NFC_DEV_PASSWD_HASH_LEN) == FALSE) + { + hex_dump("HashData", &HashData[0], NFC_DEV_PASSWD_HASH_LEN); + hex_dump("PeerNfcPasswdHash", &pWscControl->PeerNfcPasswdHash[0], NFC_DEV_PASSWD_HASH_LEN); + DBGPRINT(RT_DEBUG_ERROR, ("Enrollee public key hash different!\n")); + pWscControl->RegData.SelfInfo.ConfigError = WSC_ERROR_PUBLIC_KEY_HASH_MISMATCH; + } + } +#endif /* WSC_NFC_SUPPORT */ + break; + + case WSC_ID_AUTH_TYPE_FLAGS: + pReg->PeerInfo.AuthTypeFlags = *((PUSHORT) pData); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTH_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTH_TYPE_FLAGS)); + break; + + case WSC_ID_ENCR_TYPE_FLAGS: + pReg->PeerInfo.EncrTypeFlags = *((PUSHORT) pData); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_TYPE_FLAGS)); + break; + + case WSC_ID_CONN_TYPE_FLAGS: + pReg->PeerInfo.ConnTypeFlags = *pData; + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONN_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONN_TYPE_FLAGS)); + break; + + case WSC_ID_CONFIG_METHODS: + pReg->PeerInfo.ConfigMethods = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */ + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_METHODS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_METHODS)); + break; + + case WSC_ID_SC_STATE: + pReg->PeerInfo.ScState = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */ + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SC_STATE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_SC_STATE)); + break; + + case WSC_ID_MANUFACTURER: + NdisMoveMemory(&pReg->PeerInfo.Manufacturer, pData, WscLen); + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerManufacturer, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MANUFACTURER))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MANUFACTURER)); + break; + + case WSC_ID_MODEL_NAME: + NdisMoveMemory(&pReg->PeerInfo.ModelName, pData, WscLen); + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerModelName, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NAME))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NAME)); + break; + + case WSC_ID_MODEL_NUMBER: + NdisMoveMemory(&pReg->PeerInfo.ModelNumber, pData, WscLen); + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerModelNumber, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NUMBER))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NUMBER)); + break; + + case WSC_ID_SERIAL_NUM: + NdisMoveMemory(&pReg->PeerInfo.SerialNumber, pData, WscLen); + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerSerialNumber, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SERIAL_NUM))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_SERIAL_NUM)); + break; + + case WSC_ID_PRIM_DEV_TYPE: + NdisMoveMemory(&pReg->PeerInfo.PriDeviceType, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PRIM_DEV_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_PRIM_DEV_TYPE)); + break; + + case WSC_ID_DEVICE_NAME: + NdisMoveMemory(&pReg->PeerInfo.DeviceName, pData, WscLen); + NdisMoveMemory(pWscControl->WscPeerInfo.WscPeerDeviceName, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_NAME))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_NAME)); + break; + + case WSC_ID_RF_BAND: + pReg->PeerInfo.RfBand = *pData; + /*if() ret = WSC_ERROR_CHAN24_NOT_SUPP; */ + /*if() ret = WSC_ERROR_CHAN50_NOT_SUPP; */ + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_RF_BAND))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_RF_BAND)); + break; + + case WSC_ID_ASSOC_STATE: + pReg->PeerInfo.AssocState = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */ + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ASSOC_STATE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ASSOC_STATE)); + break; + + case WSC_ID_CONFIG_ERROR: + pReg->PeerInfo.ConfigError = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */ + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_ERROR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_ERROR)); + break; + + case WSC_ID_DEVICE_PWD_ID: + DBGPRINT(RT_DEBUG_TRACE, (" WPS Registrar DPID %04x\n",pReg->SelfInfo.DevPwdId)); + if(WSC_DEVICEPWDID_DEFAULT == get_unaligned((PUSHORT) pData))/**(PUSHORT) pData) */ + { + DBGPRINT(RT_DEBUG_TRACE, ("Rx WPS DPID PIN\n")); + pWscControl->RegData.SelfInfo.DevPwdId = cpu2be16(DEV_PASS_ID_PIN); + } + else if(WSC_DEVICEPWDID_PUSH_BTN == get_unaligned((PUSHORT) pData))/**(PUSHORT) pData) */ + { + DBGPRINT(RT_DEBUG_TRACE, ("Rx WPS DPID PBC\n")); + pWscControl->RegData.SelfInfo.DevPwdId = cpu2be16(DEV_PASS_ID_PBC); + } + else + { + DBGPRINT(RT_DEBUG_TRACE, ("Rx WPS DPID unsupport\n")); + } + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_PWD_ID))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_PWD_ID)); + break; + + case WSC_ID_OS_VERSION: + pReg->PeerInfo.OsVersion = get_unalignedlong((PULONG) pData);/**((PULONG) pData); */ + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_OS_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_OS_VERSION)); + break; + + case WSC_ID_VENDOR_EXT: +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + UCHAR tmp_data_len = 0; + WscParseV2SubItem(WFA_EXT_ID_VERSION2, pData, WscLen, &pReg->PeerInfo.Version2, &tmp_data_len); + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM1 --> Version2 = %x\n", pReg->PeerInfo.Version2)); + } +#endif // WSC_V2_SUPPORT // + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM1 --> Unknown IE 0x%04x\n", WscType)); + break; + } + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + + if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] ) + ret = WSC_ERROR_WANTING_FIELD; + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM1 : \n")); + return ret; +} + +/* + ======================================================================== + + Routine Description: + Process WSC M2 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - rewrite buffer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after Rx M2 + 1. Change the correct parameters + 2. Process M2 + + ======================================================================== +*/ +int ProcessMessageM2( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + IN UCHAR apidx, + OUT PWSC_REG_DATA pReg) +{ + int ret = WSC_ERROR_NO_ERROR; + INT HmacLen; + UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32]; + UCHAR DHKey[32], KdkInput[38], KdfKey[80]; + INT DH_Len; + PUCHAR pData = NULL; + USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0}; + //MAC_TABLE_ENTRY *pEntry = NULL; + //UCHAR CurOpMode = 0xFF; +#ifdef WSC_NFC_SUPPORT + INT EncrLen; + UCHAR *IV_DecrData=NULL;//IV len 16 ,DecrData len + BOOLEAN bWscEncrSettings=FALSE; + USHORT IV_DecrDataLen; +#endif /* WSC_NFC_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter) + //CurOpMode = AP_MODE; +#endif /* CONFIG_AP_SUPPORT */ + + + 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)); + +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC && pWscControl->NfcModel == MODEL_HANDOVER) + { + IV_DecrData = kmalloc(1024, MEM_ALLOC_FLAG); + if(NULL == IV_DecrData) + { + ret = WSC_ERROR_CAN_NOT_ALLOCMEM; + DBGPRINT(RT_DEBUG_ERROR, ("Allocate IV_DecrData fail @ %s\n", __FUNCTION__)); + return ret; + } + } +#endif /* WSC_NFC_SUPPORT */ + + /* Start to process WSC IEs */ + while (Length > 4) + { + WSC_IE TLV_Recv; + memcpy((UINT8 *)&TLV_Recv, pData, 4); + WscType = be2cpu16(TLV_Recv.Type); + WscLen = be2cpu16(TLV_Recv.Length); + pData += 4; + Length -= 4; + + /* Parse M2 WSC type and store to RegData structure */ + switch (WscType) + { + case WSC_ID_VERSION: + if(pReg->SelfInfo.Version != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION)); + break; + + case WSC_ID_MSG_TYPE: + if(WSC_ID_MESSAGE_M2 != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE)); + break; + + case WSC_ID_ENROLLEE_NONCE: + /* for verification with our enrollee nonce */ + if (RTMPCompareMemory(pReg->SelfNonce, pData, WscLen) != 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("Rx M2 Compare enrollee nonce mismatched \n")); + } + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE)); + break; + + case WSC_ID_REGISTRAR_NONCE: + NdisMoveMemory(pReg->RegistrarNonce, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE)); + break; + + case WSC_ID_UUID_R: + NdisMoveMemory(pReg->PeerInfo.Uuid, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_UUID_R))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_UUID_R)); + break; + + case WSC_ID_PUBLIC_KEY: + /* Get Registrar Public Key */ + NdisMoveMemory(&pReg->Pkr, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PUBLIC_KEY))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_PUBLIC_KEY)); +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC && pWscControl->NfcModel == MODEL_HANDOVER) /* So far no this test case. */ + { + DBGPRINT(RT_DEBUG_TRACE, ("NfcModel(=%d) \n", pWscControl->NfcModel)); + UCHAR HashData[SHA256_DIGEST_SIZE]; + RT_SHA256(&pWscControl->RegData.Pkr[0], 192, &HashData[0]); + if (NdisEqualMemory(&HashData[0], &pWscControl->NfcPasswdHash[0], NFC_DEV_PASSWD_HASH_LEN) == FALSE) + { + hex_dump("HashData", &HashData[0], NFC_DEV_PASSWD_HASH_LEN); + hex_dump("PeerNfcPasswdHash", &pWscControl->NfcPasswdHash[0], NFC_DEV_PASSWD_HASH_LEN); + DBGPRINT(RT_DEBUG_ERROR, ("Registrar public key hash different!\n")); + ret = WSC_ERROR_PUBLIC_KEY_HASH_MISMATCH; + } + } +#endif /* WSC_NFC_SUPPORT */ + break; + + case WSC_ID_AUTH_TYPE_FLAGS: + pReg->PeerInfo.AuthTypeFlags = get_unaligned((PUSHORT) pData); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTH_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTH_TYPE_FLAGS)); + break; + + case WSC_ID_ENCR_TYPE_FLAGS: + pReg->PeerInfo.EncrTypeFlags = get_unaligned((PUSHORT) pData); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_TYPE_FLAGS)); + break; + + case WSC_ID_CONN_TYPE_FLAGS: + pReg->PeerInfo.ConnTypeFlags = *pData; + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONN_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONN_TYPE_FLAGS)); + break; + + case WSC_ID_CONFIG_METHODS: + pReg->PeerInfo.ConfigMethods = get_unaligned((PUSHORT) pData); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_METHODS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_METHODS)); + break; + + case WSC_ID_MANUFACTURER: + NdisMoveMemory(&pReg->PeerInfo.Manufacturer, pData, WscLen); + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerManufacturer, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MANUFACTURER))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MANUFACTURER)); + break; + + case WSC_ID_MODEL_NAME: + NdisMoveMemory(&pReg->PeerInfo.ModelName, pData, WscLen); + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerModelName, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NAME))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NAME)); + break; + + case WSC_ID_MODEL_NUMBER: + NdisMoveMemory(&pReg->PeerInfo.ModelNumber, pData, WscLen); + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerModelNumber, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NUMBER))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NUMBER)); + break; + + case WSC_ID_SERIAL_NUM: + NdisMoveMemory(&pReg->PeerInfo.SerialNumber, pData, WscLen); + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerSerialNumber, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SERIAL_NUM))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_SERIAL_NUM)); + break; + + case WSC_ID_PRIM_DEV_TYPE: + NdisMoveMemory(&pReg->PeerInfo.PriDeviceType, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PRIM_DEV_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_PRIM_DEV_TYPE)); + break; + + case WSC_ID_DEVICE_NAME: + NdisMoveMemory(&pReg->PeerInfo.DeviceName, pData, WscLen); + NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerDeviceName, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_NAME))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_NAME)); + break; + + case WSC_ID_RF_BAND: + pReg->PeerInfo.RfBand = *pData; + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_RF_BAND))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_RF_BAND)); + break; + + case WSC_ID_ASSOC_STATE: + pReg->PeerInfo.AssocState = get_unaligned((PUSHORT) pData); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ASSOC_STATE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ASSOC_STATE)); + break; + + case WSC_ID_CONFIG_ERROR: + pReg->PeerInfo.ConfigError = get_unaligned((PUSHORT) pData); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_ERROR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_ERROR)); + break; + + case WSC_ID_DEVICE_PWD_ID: + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_PWD_ID))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_PWD_ID)); + break; + + case WSC_ID_OS_VERSION: + pReg->PeerInfo.OsVersion = get_unalignedlong((PULONG) pData); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_OS_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_OS_VERSION)); + break; + + case WSC_ID_AUTHENTICATOR: + NdisMoveMemory(Hmac, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR)); + break; + + case WSC_ID_VENDOR_EXT: +#ifdef WSC_V2_SUPPORT + if (pWscControl->WscV2Info.bEnableWpsV2) + { + UCHAR tmp_data_len = 0; + WscParseV2SubItem(WFA_EXT_ID_VERSION2, pData, WscLen, &pReg->PeerInfo.Version2, &tmp_data_len); + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2 --> Version2 = %x\n", pReg->PeerInfo.Version2)); + } +#endif // WSC_V2_SUPPORT // + break; +#ifdef WSC_NFC_SUPPORT + case WSC_ID_ENCR_SETTINGS: + // There shall have smoe kind of length check + if (pWscControl->bTriggerByNFC && pWscControl->NfcModel == MODEL_HANDOVER) + { + DBGPRINT(RT_DEBUG_TRACE, ("WSC_ID_ENCR_SETTINGS at %s\n", __FUNCTION__)); + if (WscLen <= 16) + break; + if (WscLen > 1024) + { + // ApEncrSetting is not enough + DBGPRINT(RT_DEBUG_TRACE, ("ApEncrSettings array size is not enough, require %d\n", WscLen)); + break; + } + NdisMoveMemory(IV_DecrData, pData, WscLen); + hex_dump("WSC_ID_ENCR_SETTINGS-pData", pData, WscLen); + hex_dump("WSC_ID_ENCR_SETTINGS-IV_DecrData", IV_DecrData, WscLen); + IV_DecrDataLen = WscLen; + bWscEncrSettings = TRUE; + } + break; +#endif /* WSC_NFC_SUPPORT */ + default: + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2 --> Unknown IE 0x%04x\n", WscType)); + break; + } + + 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); + +#ifdef WSC_NFC_SUPPORT + if (pWscControl->bTriggerByNFC && bWscEncrSettings && pWscControl->NfcModel == MODEL_HANDOVER) + { + EncrLen = sizeof(pReg->ApEncrSettings); + AES_CBC_Decrypt(IV_DecrData + 16, (IV_DecrDataLen - 16),pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),IV_DecrData, 16, (UINT8 *) pReg->ApEncrSettings, (UINT *) &EncrLen); + DBGPRINT(RT_DEBUG_TRACE, ("M2 ApEncrSettings len = %d\n ", EncrLen)); + + // Parse encryption settings + if (WscProcessCredential(pAdapter, pReg->ApEncrSettings, EncrLen, pWscControl) == FALSE) + { + return WSC_ERROR_SETUP_LOCKED; + } + } +#endif /* WSC_NFC_SUPPORT */ + + /* Combine last TX & RX message contents and validate the HMAC */ + /* We have to exclude last 12 bytes from last receive since it's authenticator value */ + HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12; + if (pAdapter->pHmacData) + { + NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length); + NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12); + + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE); + } + + if (RTMPEqualMemory(Hmac, KDK, 8) != 1) + { + DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM2 --> HMAC not match\n")); + DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4))))); + DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4])))); + ret = WSC_ERROR_HMAC_FAIL; + } + + if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] ) + ret = WSC_ERROR_WANTING_FIELD; + +/* out : */ + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2 : \n")); + return ret; +} + +/* + ======================================================================== + + Routine Description: + Process WSC M2D Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - rewrite buffer + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after Rx M2D + 1. Change the correct parameters + 2. Process M2D + + ======================================================================== +*/ +int ProcessMessageM2D( + IN PRTMP_ADAPTER pAdapter, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg) +{ + int ret = WSC_ERROR_NO_ERROR; + PUCHAR pData = NULL; + USHORT WscType, WscLen; + + /* Copy the content to Regdata for lastRx information */ + /* Length must include authenticator IE size */ + pReg->LastRx.Length = Length; + NdisMoveMemory(pReg->LastRx.Data, precv, Length); + pData = pReg->LastRx.Data; + + /* Start to process WSC IEs */ + while (Length > 4) + { + WSC_IE TLV_Recv; + memcpy((UINT8 *)&TLV_Recv, pData, 4); + WscType = be2cpu16(TLV_Recv.Type); + WscLen = be2cpu16(TLV_Recv.Length); + pData += 4; + Length -= 4; + + /* Parse M2 WSC type and store to RegData structure */ + switch (WscType) + { + case WSC_ID_VERSION: + if(pReg->SelfInfo.Version != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData)); + break; + + case WSC_ID_MSG_TYPE: + if(WSC_ID_MESSAGE_M2D != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData)); + break; + + case WSC_ID_ENROLLEE_NONCE: + /* for verification with our enrollee nonce */ + if (RTMPCompareMemory(pReg->EnrolleeNonce, pData, WscLen) != 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("Rx M2 Compare enrollee nonce mismatched \n")); + } + break; + + case WSC_ID_REGISTRAR_NONCE: + NdisMoveMemory(pReg->RegistrarNonce, pData, WscLen); + break; + + case WSC_ID_UUID_R: + NdisMoveMemory(pReg->PeerInfo.Uuid, pData, WscLen); + break; + + case WSC_ID_PUBLIC_KEY: + /* There shall be no Public transmitted in M2D */ + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2D --> Receive WSC_ID_PUBLIC_KEY!! werid!\n")); + break; + + case WSC_ID_AUTH_TYPE_FLAGS: + pReg->PeerInfo.AuthTypeFlags = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */ + break; + + case WSC_ID_ENCR_TYPE_FLAGS: + pReg->PeerInfo.EncrTypeFlags = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */ + break; + + case WSC_ID_CONN_TYPE_FLAGS: + pReg->PeerInfo.ConnTypeFlags = *pData; + break; + + case WSC_ID_CONFIG_METHODS: + pReg->PeerInfo.ConfigMethods = be2cpu16(get_unaligned((PUSHORT) pData));/*be2cpu16(*((PUSHORT) pData)); */ + break; + + case WSC_ID_MANUFACTURER: + NdisMoveMemory(&pReg->PeerInfo.Manufacturer, pData, WscLen); + break; + + case WSC_ID_MODEL_NAME: + NdisMoveMemory(&pReg->PeerInfo.ModelName, pData, WscLen); + break; + + case WSC_ID_MODEL_NUMBER: + NdisMoveMemory(&pReg->PeerInfo.ModelNumber, pData, WscLen); + break; + + case WSC_ID_SERIAL_NUM: + NdisMoveMemory(&pReg->PeerInfo.SerialNumber, pData, WscLen); + break; + + case WSC_ID_PRIM_DEV_TYPE: + NdisMoveMemory(&pReg->PeerInfo.PriDeviceType, pData, WscLen); + break; + + case WSC_ID_DEVICE_NAME: + NdisMoveMemory(&pReg->PeerInfo.DeviceName, pData, WscLen); + break; + + case WSC_ID_RF_BAND: + pReg->PeerInfo.RfBand = *pData; + break; + + case WSC_ID_ASSOC_STATE: + pReg->PeerInfo.AssocState = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */ + break; + + case WSC_ID_CONFIG_ERROR: + pReg->PeerInfo.ConfigError = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */ + break; + + case WSC_ID_DEVICE_PWD_ID: + break; + + case WSC_ID_OS_VERSION: + pReg->PeerInfo.OsVersion = get_unalignedlong((PULONG)pData); + break; + + case WSC_ID_AUTHENTICATOR: + /* No authenticator in M2D */ + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2D --> Unknown IE 0x%04x\n", WscType)); + break; + + } + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2D : \n")); + return ret; +} + +/* + ======================================================================== + + Routine Description: + Process WSC M3 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - recv buffer + Length - recv Length + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after Rx M3 + 1. Change the correct parameters + 2. Process M3 + + ======================================================================== +*/ +int ProcessMessageM3( + IN PRTMP_ADAPTER pAdapter, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg) +{ + int ret = WSC_ERROR_NO_ERROR; + INT HmacLen; + UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32]; + PUCHAR pData = NULL; + USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0}; + + RTMPZeroMemory(KDK, 32); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_E_HASH1))] |= (1 << WSC_TLV_BYTE1(WSC_ID_E_HASH1)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_E_HASH2))] |= (1 << WSC_TLV_BYTE1(WSC_ID_E_HASH2)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR)); + + /* Copy the content to Regdata for lastRx information */ + /* Length must include authenticator IE size */ + pReg->LastRx.Length = Length; + NdisMoveMemory(pReg->LastRx.Data, precv, Length); + pData = pReg->LastRx.Data; + + /* Start to process WSC IEs */ + while (Length > 4) + { + WSC_IE TLV_Recv; + memcpy((UINT8 *)&TLV_Recv, pData, 4); + WscType = be2cpu16(TLV_Recv.Type); + WscLen = be2cpu16(TLV_Recv.Length); + pData += 4; + Length -= 4; + + /* Parse M3 WSC type and store to RegData structure */ + switch (WscType) + { + case WSC_ID_VERSION: + if(pReg->SelfInfo.Version != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION)); + break; + + case WSC_ID_MSG_TYPE: + if(WSC_ID_MESSAGE_M3 != *pData) + DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE)); + break; + + case WSC_ID_REGISTRAR_NONCE: + /* for verification with our Registrar nonce */ + if (RTMPCompareMemory(pReg->RegistrarNonce, pData, WscLen) != 0) + DBGPRINT(RT_DEBUG_TRACE, ("Rx M3 Compare Registrar nonce mismatched \n")); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE)); + break; + + case WSC_ID_E_HASH1: + NdisMoveMemory(&pReg->EHash1[0], pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_E_HASH1))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_E_HASH1)); + break; + + case WSC_ID_E_HASH2: + NdisMoveMemory(&pReg->EHash2[0], pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_E_HASH2))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_E_HASH2)); + break; + + case WSC_ID_AUTHENTICATOR: + NdisMoveMemory(Hmac, pData, WscLen); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR)); + break; + + default: + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM3 --> Unknown IE 0x%04x\n", WscType)); + break; + } + + /* Offset to net WSC Ie */ + pData += WscLen; + Length -= WscLen; + } + + /* Combine last TX & RX message contents and validate the HMAC */ + /* We have to exclude last 12 bytes from last receive since it's authenticator value */ + HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12; + if (pAdapter->pHmacData) + { + NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length); + NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12); + + /* Validate HMAC, reuse KDK buffer */ + RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE); + } + + if (RTMPEqualMemory(Hmac, KDK, 8) != 1) + { + DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM3 --> HMAC not match\n")); + DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4))))); + DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4])))); + ret = WSC_ERROR_HMAC_FAIL; + } + + if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] ) + ret = WSC_ERROR_WANTING_FIELD; + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM3 : \n")); + return ret; +} + +/* + ======================================================================== + + Routine Description: + Process WSC M4 Message + + Arguments: + pAdapter - NIC Adapter pointer + pbuf - recv buffer + Length - recv Length + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + Note: + Actions after Rx M4 + 1. Change the correct parameters + 2. Process M4 + + ======================================================================== +*/ +int ProcessMessageM4( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg) +{ + int ret = WSC_ERROR_NO_ERROR; + INT HmacLen; + UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32], RHash[32]; + INT EncrLen; + PUCHAR pData = NULL; + UCHAR *IV_DecrData=NULL;/*IV len 16 ,DecrData len */ + UCHAR *pHash=NULL;/*Reuse IV_DecrData memory */ + USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0}; + + RTMPZeroMemory(KDK, 32); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_R_HASH1))] |= (1 << WSC_TLV_BYTE1(WSC_ID_R_HASH1)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_R_HASH2))] |= (1 << WSC_TLV_BYTE1(WSC_ID_R_HASH2)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS)); + FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR)); + + 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(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)); + + 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(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)); + + 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(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); + 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)); + + + /* 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(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); + 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(IV_DecrData) + os_free_mem(NULL, IV_DecrData); + DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM8 : \n")); + return ret; +} + +#endif /* WSC_INCLUDED */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wsc_ufd.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wsc_ufd.c new file mode 100644 index 000000000..c18110848 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wsc_ufd.c @@ -0,0 +1,598 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2006, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + wsc_ufd.c + + Abstract: + + Revision History: + Who When What +*/ + +#include "rt_config.h" + +#ifdef WSC_UFD + +static const RTMP_STRING *XML_DECLARE_START = ""; +static const RTMP_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 { + RTMP_STRING *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 { + RTMP_STRING *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 RTMP_STRING **pXmlData) +{ + RTMP_STRING *ptr; + + DBGPRINT(RT_DEBUG_TRACE, ("======> WscPassXmlDeclare\n")); + + ptr = rtstrstr(*pXmlData, (RTMP_STRING *)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 RTMP_STRING *pXmlData, + OUT NDIS_802_11_SSID *pSsid) +{ + RTMP_STRING *ptr, *pBuffer = pXmlData; + + ptr = rtstrstr(pBuffer, (RTMP_STRING *)XML_SSID_START); + if (ptr == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlSSID: missing "); + if (ptr) + { + pBuffer = ptr + 1; + } + + ptr = rtstrstr(pBuffer, (RTMP_STRING *)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 RTMP_STRING *pXmlData, + OUT USHORT *pAuthType) +{ + RTMP_STRING *ptr, *pBuffer = pXmlData; + RTMP_STRING AuthStr[10] = {0}; + UINT AuthStrLen = 0; + + *pAuthType = 0; + ptr = rtstrstr(pBuffer, (RTMP_STRING *)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, (RTMP_STRING *)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 RTMP_STRING *pXmlData, + OUT USHORT *pEncrType) +{ + RTMP_STRING *ptr, *pBuffer = pXmlData; + RTMP_STRING EncrStr[10] = {0}; + UINT EncrStrLen = 0; + + *pEncrType = 0; + ptr = rtstrstr(pBuffer, (RTMP_STRING *)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, (RTMP_STRING *)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 RTMP_STRING *pXmlData, + OUT UCHAR *pKey, + OUT USHORT *pKeyLen) +{ + RTMP_STRING *ptr, *pBuffer = pXmlData; + UINT KeyLen = 0; + + ptr = rtstrstr(pBuffer, (RTMP_STRING *)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, (RTMP_STRING *)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 RTMP_STRING *pXmlData, + OUT UCHAR *pKeyIndex) +{ + RTMP_STRING *ptr, *pBuffer = pXmlData; + + *pKeyIndex = 1; + ptr = rtstrstr(pBuffer, (RTMP_STRING *)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, (RTMP_STRING *)XML_KEY_INDEX_END); + if (ptr == NULL) + { + DBGPRINT(RT_DEBUG_TRACE, ("WscGetXmlKeyIndex: missing %s\n", XML_KEY_INDEX_END)); + return FALSE; + } + + *pKeyIndex = *(--ptr) - 0x30; + + return TRUE; +} + + + +BOOLEAN WscReadProfileFromUfdFile( + IN RTMP_ADAPTER *pAd, + IN UCHAR ApIdx, + IN RTMP_STRING *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; + RTMP_STRING *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 mem alloc fail. (fileLen = %d)\n", fileLen)); + return FALSE; + } + RTMPZeroMemory(pXmlData, fileLen+1); + RtmpOSFileSeek(file_r, 0); + rv = RtmpOSFileRead(file_r, (RTMP_STRING *)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 RTMP_STRING *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; + RTMP_STRING *offset, *pXmlTemplate = (RTMP_STRING *)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, (RTMP_STRING *)XML_GUID_MARK)) != NULL) + { + RtmpOSFileWrite(file_w, (RTMP_STRING *)pXmlTemplate, (int)(offset - pXmlTemplate)); + RtmpOSFileWrite(file_w, (RTMP_STRING *)&Guid_Str[0], (int)UUID_LEN_STR); + pXmlTemplate = offset + strlen(XML_GUID_MARK); + } + + if ((offset = rtstrstr(pXmlTemplate, (RTMP_STRING *)XML_AP_GUID_MARK)) != NULL) + { + RtmpOSFileWrite(file_w, (RTMP_STRING *)pXmlTemplate, (int)(offset - pXmlTemplate)); + RtmpOSFileWrite(file_w, (RTMP_STRING *)&pWscControl->Wsc_Uuid_Str[0], (int)UUID_LEN_STR); + pXmlTemplate = offset + strlen(XML_AP_GUID_MARK); + } + if ((offset = rtstrstr(pXmlTemplate, (RTMP_STRING *)XML_SSID_MARK)) != NULL) + { + RtmpOSFileWrite(file_w, (RTMP_STRING *)pXmlTemplate, (int)(offset - pXmlTemplate)); + RtmpOSFileWrite(file_w, (RTMP_STRING *)&pCredential->SSID.Ssid[0], (int)pCredential->SSID.SsidLength); + pXmlTemplate = offset + strlen(XML_SSID_MARK); + } + if ((offset = rtstrstr(pXmlTemplate, (RTMP_STRING *)XML_AUTH_MARK)) != NULL) + { + RtmpOSFileWrite(file_w, (RTMP_STRING *)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, + (RTMP_STRING *)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, (RTMP_STRING *)XML_ENCR_MARK)) != NULL) + { + bFound = FALSE; + RtmpOSFileWrite(file_w, (RTMP_STRING *)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, + (RTMP_STRING *)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, (RTMP_STRING *)XML_KEY_MARK)) != NULL) + { + if (pCredential->EncrType != WSC_ENCRTYPE_NONE) + { + RtmpOSFileWrite(file_w, (RTMP_STRING *)pXmlTemplate, (int)(offset - pXmlTemplate)); + RtmpOSFileWrite(file_w, + (RTMP_STRING *)pCredential->Key, + (int)pCredential->KeyLength); + pXmlTemplate = offset + strlen(XML_KEY_MARK); + } + else + { + RtmpOSFileWrite(file_w, (RTMP_STRING *)XML_ENCR_END, (int)strlen(XML_ENCR_END)); + RtmpOSFileWrite(file_w, (RTMP_STRING *)"\n", (int)1); + pXmlTemplate = offset + strlen(XML_KEY_MARK) + strlen(XML_KEY_END) + 1; /* 1: '\n' */ + } + } + RtmpOSFileWrite(file_w, (RTMP_STRING *)pXmlTemplate, (int)strlen(pXmlTemplate)); + } + +out: + RtmpOSFileClose(file_w); + RtmpOSFSInfoChange(&osFSInfo, FALSE); + + return bRtn; +} + + +#endif /* WSC_UFD */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wsc_v2.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wsc_v2.c new file mode 100644 index 000000000..840d393be --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/common/wsc_v2.c @@ -0,0 +1,296 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2006, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + wsc_v2.c +*/ + +#include "rt_config.h" + +#ifdef WSC_V2_SUPPORT +#include "wsc_tlv.h" + +BOOLEAN WscAppendV2SubItem( + IN UCHAR SubID, + IN PUCHAR pData, + IN UCHAR DataLen, + OUT PUCHAR pOutBuf, + OUT PUCHAR pOutBufLen); + +#ifdef CONFIG_AP_SUPPORT +VOID WscOnOff( + IN PRTMP_ADAPTER pAd, + IN INT ApIdx, + IN BOOLEAN bOff) +{ + PWSC_V2_INFO pWpsV2Info = &pAd->ApCfg.MBSSID[ApIdx & 0x0F].WscControl.WscV2Info; + if (bOff) + { + /* + AP must not support WEP in WPS V2 + */ + pWpsV2Info->bWpsEnable = FALSE; + pAd->ApCfg.MBSSID[ApIdx & 0x0F].WscIEBeacon.ValueLen = 0; + pAd->ApCfg.MBSSID[ApIdx & 0x0F].WscIEProbeResp.ValueLen = 0; + DBGPRINT(RT_DEBUG_TRACE, ("WscOnOff - OFF.\n")); + } + else + { + pWpsV2Info->bWpsEnable = TRUE; + if (pAd->ApCfg.MBSSID[ApIdx & 0x0F].WscControl.WscConfMode != WSC_DISABLE) + { + INT IsAPConfigured; + IsAPConfigured = pAd->ApCfg.MBSSID[ApIdx & 0x0F].WscControl.WscConfStatus; + WscBuildBeaconIE(pAd, IsAPConfigured, FALSE, 0, 0, (ApIdx & 0x0F), NULL, 0, AP_MODE); + WscBuildProbeRespIE(pAd, WSC_MSGTYPE_AP_WLAN_MGR, IsAPConfigured, FALSE, 0, 0, ApIdx, NULL, 0, AP_MODE); + DBGPRINT(RT_DEBUG_TRACE, ("WscOnOff - ON.\n")); + } + } + DBGPRINT(RT_DEBUG_TRACE, ("WscOnOff - bWpsEnable = %d\n", pWpsV2Info->bWpsEnable)); +} + +VOID WscAddEntryToAclList( + IN PRTMP_ADAPTER pAd, + IN INT ApIdx, + IN PUCHAR pMacAddr) +{ + PRT_802_11_ACL pACL = NULL; + INT i; + BOOLEAN bFound = FALSE; + + pACL = &pAd->ApCfg.MBSSID[ApIdx].AccessControlList; + + if ((pACL->Policy == 0) || + (pACL->Policy == 2)) + return; + + if (pACL->Num >= (MAX_NUM_OF_ACL_LIST - 1)) + { + DBGPRINT(RT_DEBUG_WARN, ("The AccessControlList is full, and no more entry can join the list!\n")); + return; + } + + for (i=0; iNum; i++) + { + if (NdisEqualMemory(pACL->Entry[i].Addr, pMacAddr, MAC_ADDR_LEN)) + bFound = TRUE; + } + if (bFound == FALSE) + { + NdisMoveMemory(pACL->Entry[i].Addr, pMacAddr, MAC_ADDR_LEN); + pACL->Num++; + } +} +#endif /* CONFIG_AP_SUPPORT */ + +/* + Vendor ID: 0x00372A + Subelements ID (one-octet) + Version2 0x00 + AuthorizedMACs 0x01 + Network Key Shareable 0x02 + Request to Enroll 0x03 + Settings Delay Time 0x04 + Reserved for future use 0x05 to 0xFF + Length (one-octet) - number of octets in the payload of this subelment + Version2 1B + AuthorizedMACs <=30B + Network Key Shareable Bool + Request to Enroll Bool + Settings Delay Time 1B +*/ +BOOLEAN WscGenV2Msg( + IN PWSC_CTRL pWpsCtrl, + IN BOOLEAN bSelRegistrar, + IN PUCHAR pAuthorizedMACs, + IN INT AuthorizedMACsLen, + OUT UCHAR **pOutBuf, + OUT INT *pOutBufLen) +{ + PUCHAR pWscV2Msg = NULL; + USHORT WscV2MsgLen = 0; + PWSC_REG_DATA pReg = &pWpsCtrl->RegData; + INT templen = 0; + + os_alloc_mem(NULL, (UCHAR **)&pWscV2Msg, 128); + if (pWscV2Msg) + { + UCHAR TmpLen = 0; + pWscV2Msg[0] = 0x00; + pWscV2Msg[1] = 0x37; + pWscV2Msg[2] = 0x2A; + + /* Version2 */ + WscAppendV2SubItem(WFA_EXT_ID_VERSION2, &pReg->SelfInfo.Version2, 1, pWscV2Msg+3, &TmpLen); + WscV2MsgLen += (3 + (USHORT)TmpLen); + + if (bSelRegistrar) + { + /* + Authorized MACs + Registrars (both internal and external) shall add the AuthorizedMACs subelement, + this applies to all Configuration Methods, including PIN, PBC and NFC. + */ + if (pAuthorizedMACs) + { + WscAppendV2SubItem( WFA_EXT_ID_AUTHORIZEDMACS, + pAuthorizedMACs, + AuthorizedMACsLen, + pWscV2Msg+WscV2MsgLen, + &TmpLen ); + WscV2MsgLen += (USHORT)TmpLen; + } + else + { + WscAppendV2SubItem( WFA_EXT_ID_AUTHORIZEDMACS, + BROADCAST_ADDR, + MAC_ADDR_LEN, + pWscV2Msg+WscV2MsgLen, + &TmpLen ); + WscV2MsgLen += (USHORT)TmpLen; + } + } + + templen = AppendWSCTLV(WSC_ID_VENDOR_EXT, (*pOutBuf), (UINT8 *)pWscV2Msg, WscV2MsgLen); + (*pOutBuf) += templen; + (*pOutBufLen) += templen; + + os_free_mem(NULL, pWscV2Msg); + + return TRUE; + } + return FALSE; +} + +BOOLEAN WscAppendV2SubItem( + IN UCHAR SubID, + IN PUCHAR pData, + IN UCHAR DataLen, + OUT PUCHAR pOutBuf, + OUT PUCHAR pOutBufLen) +{ + PUCHAR pBuf = NULL; + os_alloc_mem(NULL, &pBuf, DataLen + 10); + if (pBuf) + { + pBuf[0] = SubID; + pBuf[1] = DataLen; + NdisMoveMemory(pBuf+2, pData, DataLen); + *pOutBufLen = (DataLen + 2); + NdisMoveMemory(pOutBuf, pBuf, *pOutBufLen); + os_free_mem(NULL, pBuf); + return TRUE; + } + return FALSE; +} + +BOOLEAN WscParseV2SubItem( + IN UCHAR SubID, + IN PUCHAR pData, + IN USHORT DataLen, + OUT PUCHAR pOutBuf, + OUT PUCHAR pOutBufLen) +{ + PEID_STRUCT pEid; + USHORT Length = 0; + pEid = (PEID_STRUCT) (pData + 3); + hex_dump("WscParseV2SubItem - pData", (pData+3), DataLen-3); + while ((Length + 2 + pEid->Len) <= (DataLen-3)) + { + if (pEid->Eid == SubID) + { + *pOutBufLen = pEid->Len; + NdisMoveMemory(pOutBuf, &pEid->Octet[0], pEid->Len); + return TRUE; + } + Length = Length + 2 + pEid->Len; + pEid = (PEID_STRUCT)((UCHAR*)pEid + 2 + pEid->Len); + } + return FALSE; +} + +VOID WscSendEapFragAck( + IN PRTMP_ADAPTER pAdapter, + IN PWSC_CTRL pWscControl, + IN PMAC_TABLE_ENTRY pEntry) +{ + if (pEntry == NULL) + { + ASSERT(pEntry!=NULL); + return; + } + if (IS_ENTRY_CLIENT(pEntry)) + { + pWscControl->bWscLastOne = TRUE; + if (pAdapter->OpMode == OPMODE_AP) + WscSendMessage(pAdapter, WSC_OPCODE_FRAG_ACK, NULL, 0, pWscControl, AP_MODE, EAP_CODE_REQ); + else + { + if (ADHOC_ON(pAdapter) && (pWscControl->WscConfMode == WSC_REGISTRAR)) + WscSendMessage(pAdapter, WSC_OPCODE_FRAG_ACK, NULL, 0, pWscControl, STA_MODE, EAP_CODE_REQ); + else + WscSendMessage(pAdapter, WSC_OPCODE_FRAG_ACK, NULL, 0, pWscControl, STA_MODE, EAP_CODE_RSP); + } + } + else if (IS_ENTRY_APCLI(pEntry)) + WscSendMessage(pAdapter, WSC_OPCODE_FRAG_ACK, NULL, 0, pWscControl, AP_CLIENT_MODE, EAP_CODE_REQ); +} + +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 // + +} + +#endif /* WSC_V2_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2860AP.dat b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2860AP.dat new file mode 100644 index 000000000..b81ced989 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2860AP.dat @@ -0,0 +1,147 @@ +#The word of "Default" must not be removed +Default +ed_th_nonCE=52 +Cts2SelfTh=1500 +CountryRegion=5 +CountryRegionABand=7 +CountryCode=TW +BssidNum=1 +SSID1=RT2860AP1 +SSID2= +SSID3= +SSID4= +WirelessMode=9 +TxRate=0 +Channel=11 +BasicRate=15 +BeaconPeriod=100 +DtimPeriod=1 +TxPower=100 +DisableOLBC=0 +BGProtection=0 +MaxStaNum=0 +TxPreamble=0 +RTSThreshold=2347 +FragThreshold=2346 +TxBurst=1 +PktAggregate=0 +TurboRate=0 +WmmCapable=0 +APSDCapable=0 +DLSCapable=0 +APAifsn=3;7;1;1 +APCwmin=4;4;3;2 +APCwmax=6;10;4;3 +APTxop=0;0;94;47 +APACM=0;0;0;0 +BSSAifsn=3;7;2;2 +BSSCwmin=4;4;3;2 +BSSCwmax=10;10;4;3 +BSSTxop=0;0;94;47 +BSSACM=0;0;0;0 +AckPolicy=0;0;0;0 +NoForwarding=0 +NoForwardingBTNBSSID=0 +HideSSID=0 +StationKeepAlive=0 +ShortSlot=1 +AutoChannelSelect=0 +IEEE8021X=0 +IEEE80211H=0 +CSPeriod=10 +WirelessEvent=0 +IdsEnable=0 +AuthFloodThreshold=32 +AssocReqFloodThreshold=32 +ReassocReqFloodThreshold=32 +ProbeReqFloodThreshold=32 +DisassocFloodThreshold=32 +DeauthFloodThreshold=32 +EapReqFooldThreshold=32 +PreAuth=0 +AuthMode=OPEN +EncrypType=NONE +RekeyInterval=0 +RekeyMethod=DISABLE +PMKCachePeriod=10 +WPAPSK1= +WPAPSK2= +WPAPSK3= +WPAPSK4= +DefaultKeyID=1 +Key1Type=0 +Key1Str1= +Key1Str2= +Key1Str3= +Key1Str4= +Key2Type=0 +Key2Str1= +Key2Str2= +Key2Str3= +Key2Str4= +Key3Type=0 +Key3Str1= +Key3Str2= +Key3Str3= +Key3Str4= +Key4Type=0 +Key4Str1= +Key4Str2= +Key4Str3= +Key4Str4= +HSCounter=0 +AccessPolicy0=0 +AccessControlList0= +AccessPolicy1=0 +AccessControlList1= +AccessPolicy2=0 +AccessControlList2= +AccessPolicy3=0 +AccessControlList3= +WdsEnable=0 +WdsEncrypType=NONE +WdsList= +WdsKey= +RADIUS_Server=192.168.2.3 +RADIUS_Port=1812 +RADIUS_Key=ralink +own_ip_addr=192.168.5.234 +EAPifname=br0 +PreAuthifname=br0 +HT_HTC=0 +HT_RDG=0 +HT_EXTCHA=0 +HT_LinkAdapt=0 +HT_OpMode=0 +HT_MpduDensity=5 +HT_BW=1 +HT_AutoBA=1 +HT_AMSDU=0 +HT_BAWinSize=64 +HT_GI=1 +HT_LDPC=0 +HT_MCS=33 +VHT_BW=1 +VHT_SGI=1 +VHT_STBC=0 +VHT_BW_SIGNAL=0 +VHT_DisallowNonVHT=0 +VHT_LDPC=0 +MeshId=MESH +MeshAutoLink=1 +MeshAuthMode=OPEN +MeshEncrypType=NONE +MeshWPAKEY= +MeshDefaultkey=1 +MeshWEPKEY= +WscManufacturer= +WscModelName= +WscDeviceName= +WscModelNumber= +WscSerialNumber= +RadioOn=1 +PMFMFPC=0 +PMFMFPR=0 +PMFSHA256=0 +LoadCodeMethod=0 +ed_th_nonCE=52 diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2860AP.dat_ac b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2860AP.dat_ac new file mode 100644 index 000000000..122db3892 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2860AP.dat_ac @@ -0,0 +1,133 @@ +#The word of "Default" must not be removed +Default +CountryRegion=5 +CountryRegionABand=7 +CountryCode=TW +BssidNum=1 +SSID1=RT85592AP +SSID2= +SSID3= +SSID4= +WirelessMode=14 +TxRate=0 +Channel=56 +BasicRate=15 +BeaconPeriod=100 +DtimPeriod=3 +TxPower=100 +DisableOLBC=0 +BGProtection=0 +MaxStaNum=0 +TxPreamble=0 +RTSThreshold=2347 +FragThreshold=2346 +TxBurst=1 +PktAggregate=0 +TurboRate=0 +WmmCapable=0 +APSDCapable=0 +DLSCapable=0 +APAifsn=3;7;1;1 +APCwmin=4;4;3;2 +APCwmax=6;10;4;3 +APTxop=0;0;94;47 +APACM=0;0;0;0 +BSSAifsn=3;7;2;2 +BSSCwmin=4;4;3;2 +BSSCwmax=10;10;4;3 +BSSTxop=0;0;94;47 +BSSACM=0;0;0;0 +AckPolicy=0;0;0;0 +NoForwarding=0 +NoForwardingBTNBSSID=0 +HideSSID=0 +StationKeepAlive=0 +ShortSlot=1 +AutoChannelSelect=0 +IEEE8021X=0 +IEEE80211H=0 +CSPeriod=10 +WirelessEvent=0 +IdsEnable=0 +AuthFloodThreshold=32 +AssocReqFloodThreshold=32 +ReassocReqFloodThreshold=32 +ProbeReqFloodThreshold=32 +DisassocFloodThreshold=32 +DeauthFloodThreshold=32 +EapReqFooldThreshold=32 +PreAuth=0 +AuthMode=OPEN +EncrypType=NONE +RekeyInterval=0 +RekeyMethod=DISABLE +PMKCachePeriod=10 +WPAPSK1= +WPAPSK2= +WPAPSK3= +WPAPSK4= +DefaultKeyID=1 +Key1Type=0 +Key1Str1= +Key1Str2= +Key1Str3= +Key1Str4= +Key2Type=0 +Key2Str1= +Key2Str2= +Key2Str3= +Key2Str4= +Key3Type=0 +Key3Str1= +Key3Str2= +Key3Str3= +Key3Str4= +Key4Type=0 +Key4Str1= +Key4Str2= +Key4Str3= +Key4Str4= +HSCounter=0 +AccessPolicy0=0 +AccessControlList0= +AccessPolicy1=0 +AccessControlList1= +AccessPolicy2=0 +AccessControlList2= +AccessPolicy3=0 +AccessControlList3= +WdsEnable=0 +WdsEncrypType=NONE +WdsList= +WdsKey= +RADIUS_Server=192.168.2.3 +RADIUS_Port=1812 +RADIUS_Key=ralink +own_ip_addr=192.168.5.234 +EAPifname=br0 +PreAuthifname=br0 +HT_HTC=0 +HT_RDG=0 +HT_EXTCHA=0 +HT_LinkAdapt=0 +HT_OpMode=0 +HT_MpduDensity=5 +HT_BW=1 +HT_AutoBA=1 +HT_AMSDU=0 +HT_BAWinSize=64 +HT_GI=1 +HT_MCS=33 +MeshId=MESH +MeshAutoLink=1 +MeshAuthMode=OPEN +MeshEncrypType=NONE +MeshWPAKEY= +MeshDefaultkey=1 +MeshWEPKEY= +WscManufacturer= +WscModelName= +WscDeviceName= +WscModelNumber= +WscSerialNumber= +RadioOn=1 diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2860APCard.dat b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2860APCard.dat new file mode 100644 index 000000000..4532b4ba4 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/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/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2860STA.dat b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2860STA.dat new file mode 100644 index 000000000..5f306b91d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2860STA.dat @@ -0,0 +1,95 @@ +#The word of "Default" must not be removed +Default +CountryRegion=5 +CountryRegionABand=7 +CountryCode= +ChannelGeography=1 +SSID=Dennis2860AP +NetworkType=Infra +WirelessMode=9 +Channel=0 +BeaconPeriod=100 +TxPower=100 +BGProtection=0 +TxPreamble=0 +RTSThreshold=2347 +FragThreshold=2346 +TxBurst=1 +PktAggregate=0 +WmmCapable=1 +AckPolicy=0;0;0;0 +AuthMode=OPEN +EncrypType=NONE +WPAPSK= +DefaultKeyID=1 +Key1Type=0 +Key1Str= +Key2Type=0 +Key2Str= +Key3Type=0 +Key3Str= +Key4Type=0 +Key4Str= +PSMode=CAM +AutoRoaming=0 +RoamThreshold=70 +APSDCapable=0 +APSDAC=0;0;0;0 +HT_RDG=1 +HT_EXTCHA=0 +HT_OpMode=0 +HT_MpduDensity=4 +HT_BW=1 +HT_AutoBA=1 +HT_BADecline=0 +HT_AMSDU=0 +HT_BAWinSize=64 +HT_GI=1 +HT_MCS=33 +HT_MIMOPSMode=3 +HT_DisallowTKIP=1 +HT_LDPC=0 +HT_STBC=0 +VHT_BW=1 +VHT_SGI=1 +VHT_STBC=0 +VHT_BW_SIGNAL=0 +VHT_DisallowNonVHT=0 +VHT_LDPC=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 +SnifferType=0 +LoadCodeMethod=0 diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2860STACard.dat b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2860STACard.dat new file mode 100644 index 000000000..c3f9d7499 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/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/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2870AP.dat b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2870AP.dat new file mode 100644 index 000000000..b956f1408 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2870AP.dat @@ -0,0 +1,128 @@ +#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_LDPC=0 +HT_MCS=33 +VHT_BW=1 +VHT_SGI=1 +VHT_STBC=0 +VHT_BW_SIGNAL=0 +VHT_DisallowNonVHT=0 +VHT_LDPC=0 +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 +USBAggregation=1 +LoadCodeMethod=0 diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2870APCard.dat b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2870APCard.dat new file mode 100644 index 000000000..3d1a1a837 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/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/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2870STA.dat b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2870STA.dat new file mode 100644 index 000000000..4b4fcbbcc --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2870STA.dat @@ -0,0 +1,104 @@ +#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=1 +APSDAC=1;1;1;1 +TDLS_MaxSPLength=0 +TDLS_APSDAC=1;1;1;1 +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_LDPC=0 +HT_STBC=0 +VHT_BW=1 +VHT_SGI=1 +VHT_STBC=0 +VHT_BW_SIGNAL=0 +VHT_DisallowNonVHT=0 +VHT_LDPC=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 +SnifferType=0 +USBAggregation=1 +LoadCodeMethod=0 +WOW_Enable=0 +WOW_Interface=1 +WOW_GPIO=2 +WOW_Hold=100000 +WOW_GPIOHighLow=1 + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2870STACard.dat b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/RT2870STACard.dat new file mode 100644 index 000000000..1df6a49d8 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/conf/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/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/History.txt b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/History.txt new file mode 100644 index 000000000..67af4f5f9 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/History.txt @@ -0,0 +1,96 @@ +Release Note: + +[V4.0.0.7] +Host Driver: +1. Bug fixed for TGn 4.2.12 PMK caching and 4.2.11 pre-authentication issue. +2. Bug fixed for 802.1x issue of WEP encryption. +3. Add UAPSD support. +4. Add APCLI_AUTO_CONNECT_SUPPORT function. +5. Fix MCU INT CR read/write issue. +6. modify rate retry rule. +7. Fix QA tool: check the writing length to write all to flash. +8. Fix memory leak issue when command TxPwr send fail. +9. Fix MT7603E load fw fail issue that need to adjust PCIe LDO setting to 1.2V. +10. Fix the WSC config status( in beacon & probe resp ) is wrong when we key the wrong DUT's enrolee PIN. +11. ATE tool: + a. fix txpower can not be set at ATE mode issue. + b. Add code for TxTone Power HQADLL command and iwpriv. +12. Fix Makefile/Kconfig: + a. we should use CONFIG_SINGLE_SKU_V2, not CONFIG_SINGLE_SKU. + b. Remove RTMP_TEMPERATURE_TX_ALC because this driver flag is not valid. (controlled by FW) + +F/W: +1. Add EDCA and Slot time set command. +2. Enable and update CCK_MRC fix. +3. Enable TX PA dynamic GC +4. Support negative TMAC PWR +5. Set CR_TSSI_PA_OFFSET_HPA +6. Lower WF0/WF1 TSSI ON TH to 0dBm + + +[V4.0.0.6 ] +Host Driver: +1.Add tx power percentage function for iPA +2. Modify AP PS, use CR replace AP PS CMD +3.fix apcli vs DIR655 IOT can't set ba size to 21 +4.Set MSSID *7, iPhone5 connect then ping overnight, still ping fail (?¶çˆ¾PSE Redirection bit被è?èµ? STA ping fail) +for ps retrieve function, rename "token_enq_fail" to "token_enq_all_fail" to let it more clear. +5. MT7603 auto rate update +6. Fix [AP][TGn]:4.2.47 Power Save, fail on step 8,each PS poll the station sends to the APUT, the APUT is expected to send only one directed data packet in response. +7. Fix TGn 4.2.11 & 4.2.12 PMK cache is delete in Auth. Req. +8. add PSE logical reset when detect pse abonormal condition +9. add sw based PDMA watchdog to detect & recovery PDMA TX/RX hang + +F/W: +Fix PCIE FW download fail when sw reboot, reset HIF then trigger WDT. +1. Add DMA scheduler workaround. +2. Add Admission control. +3. Add TX power % support. + + +[MT7603E_DPA_LinuxAP_4.0.0.5_20140511] +1. Fixed Cal Free IC eeprom endian issue. +2. Fixed IOT issue with Linksys WUSB6300. +3. AP-client repeater: fixed icv error when authmode/encryptype update. +4. Fixed crash issue that tasklet for processing pci dma done for mcu cmd sometimes will execute after event tasklet. +5. Update auto fall back config and algorithm. +6. Update firmware to fixed FW re-download fail issue. +7. Do 802.11 header endian swap for ps retrieve packet. +8. Fixed LED command big endian issue. +9. Fixed MlmeHardTransmitTxRing cache flush issue that will cause memory for dma and cache non sync at big endian platform. +10. Modify check en/disable RTS/CTS conditions. +11. Fixed radio on/off cmd parameters to correct value. +12. Update patch for flash mode. +13. Fixed LED RadioOff issue. +14. ATE: + a. fixed Tx/Rx antenna switch resulting wrong Tx power level work around. + b. patch PCIE ASPM write efuse Add PCIe Compile flag. + c. add iwpriv TXCONT + d. add iwpriv for carrier suppression test TXCARR + e. Initialize Tx power with EEPROM array when ATESTART + f. Fix CONFIG_QA blocking setting power when only CONFIG_ATE is chosen + + +[MT7603E_DPA_LinuxAP_4.0.0.4_20140411] +1. Support IGMP Snooping function. +2. Fix NewRateAdapt Error in STA mode. +3. Fixed apcli ICV error issue to decrypt Broadcast packet from AP. +4. Fixed BAR issues: + a. Change SW BAR rate to CCK 1M. + b. Send SW BAR for ap power saving to refresh peer sta side reordering buffer (Intel IOT). + c. Add SW BAR mechanism which SN will control by wtbl per tid. + d. Considering the BAR data rate in both 2.4G & 5G + e. SendRefreshBar when recv. CmdPsClearRsp, this modify will make sure the 1st. packet in PSE is BAR after PS. +5. Update new firmware for BBP issue. +6. Upload E1/E2 default EEPROM bin file. +7. Fixed ATE bugs for Tx power setting, BW40 channel control, and Rx issue. +8. Change MAX_NUMBER_OF_MAC definition to support 32 association STAs. +9. Correct ApCli entry setting to fix throughput issue. +10. Fix sometimes software tx will stuck since Intel STA in ps mode is very frequently. +11. Fine tune TXOP settings. +12. Fixed the bug when spatial extension on/off. +13. Fixed AP client TKIP/WEP connection issue with Broadcom AP. + + +[MT7603E_DPA_LinuxAP_4.0.0.4_20140401] +1. Init AP Driver version diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/README b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/README new file mode 100644 index 000000000..55eab644a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/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/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/README_STA_pci b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/README_STA_pci new file mode 100644 index 000000000..fc8020d73 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/README_STA_pci @@ -0,0 +1,528 @@ +* README +* +* Ralink Tech Inc. +* +* http://www.ralinktech.com +* + +======================================================================= +ModelName: +=========== +RT2860 Wireless Lan Linux Driver + + +======================================================================= +Driver lName: +============= +rt2860.o/rt2860.ko + + +======================================================================= +Supporting Kernel: +=================== +linux kernel 2.4 and 2.6 series. +Tested in Redhat 7.3 or later. + + +======================================================================= +Description: +============= +This is a linux device driver for Ralink RT2860 ABGN WLAN Card. + + +======================================================================= +Contents: +============= +Makefile : Makefile +*.c : c files +*.h : header files + + +======================================================================= +Features: +========== + This driver implements basic IEEE802.11. Infrastructure and adhoc mode with + open or shared or WPA-PSK or WPA2-PSK authentication method. + NONE, WEP, TKIP and AES encryption. + + +======================================================================= +Build Instructions: +==================== + +1> $tar -xvzf DPB_RT2860_Linux_STA_x.x.x.x.tgz + go to "./DPB_RT2860_Linux_STA_x.x.x.x" directory. + +2> In Makefile + set the "MODE = STA" in Makefile and chose the TARGET to Linux by set "TARGET = LINUX" + define the linux kernel source include file path LINUX_SRC + modify to meet your need. + +3> In os/linux/config.mk + define the GCC and LD of the target machine + define the compiler flags CFLAGS + modify to meet your need. + ** Build for being controlled by NetworkManager or wpa_supplicant wext functions + Please set 'HAS_WPA_SUPPLICANT=y' and 'HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=y'. + => #>cd wpa_supplicant-x.x + => #>./wpa_supplicant -Dwext -ira0 -c wpa_supplicant.conf -d + ** Build for being controlled by WpaSupplicant with Ralink Driver + Please set 'HAS_WPA_SUPPLICANT=y' and 'HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=n'. + => #>cd wpa_supplicant-0.5.7 + => #>./wpa_supplicant -Dralink -ira0 -c wpa_supplicant.conf -d + +4> $make + # compile driver source code + # To fix "error: too few arguments to function ¡¥iwe_stream_add_event" + => $patch -i os/linux/sta_ioctl.c.patch os/linux/sta_ioctl.c + +5> $cp RT2860STA.dat /etc/Wireless/RT2860STA/RT2860STA.dat + +6> load driver + #[kernel 2.4] + # $/sbin/insmod rt2860sta.o + # $/sbin/ifconfig ra0 inet YOUR_IP up + + #[kernel 2.6] + # $/sbin/insmod rt2860sta.ko + # $/sbin/ifconfig ra0 inet YOUR_IP up + +7> unload driver + $/sbin/ifconfig ra0 down + $/sbin/rmmod rt2860sta + +======================================================================= +CONFIGURATION: +==================== +RT2860 driver can be configured via following interfaces, +i.e. (i)"iwconfig" command, (ii)"iwpriv" command, (iii) configuration file + +i) iwconfig comes with kernel. +ii) iwpriv usage, please refer to file "iwpriv_usage.txt" for details. +iii)modify configuration file "RT2860STA.dat" in /etc/Wireless/RT2860STA/RT2860STA.dat. + +Configuration File : RT2860STA.dat +--------------------------------------- +# Copy this file to /etc/Wireless/RT2860STA/RT2860STA.dat +# This file is a binary file and will be read on loading rt.o module. +# +# Use "vi -b rt61sta.dat" to modify settings according to your need. +# +# 1.) set NetworkType to "Adhoc" for using Adhoc-mode, otherwise using Infrastructure +# 2.) set Channel to "0" for auto-select on Infrastructure mode +# 3.) set SSID for connecting to your Accss-point. +# 4.) AuthMode can be "WEPAUTO", "OPEN", "SHARED", "WPAPSK", "WPA2PSK", "WPANONE" +# 5.) EncrypType can be "NONE", "WEP", "TKIP", "AES" +# for more information refer to the Readme file. +# +#The word of "Default" must not be removed +Default +CountryRegion=5 +CountryRegionABand=7 +CountryCode= +SSID=Dennis2860AP +NetworkType=Infra +WirelessMode=9 +Channel=0 +BeaconPeriod=100 +TxPower=100 +BGProtection=0 +TxPreamble=0 +RTSThreshold=2347 +FragThreshold=2346 +TxBurst=1 +WmmCapable=0 +AckPolicy=0;0;0;0 +AuthMode=OPEN +EncrypType=NONE +WPAPSK= +DefaultKeyID=1 +Key1Type=0 +Key1Str= +Key2Type=0 +Key2Str= +Key3Type=0 +Key3Str= +Key4Type=0 +Key4Str= +PSMode=CAM +FastRoaming=0 +RoamThreshold=70 +HT_RDG=1 +HT_EXTCHA=0 +HT_OpMode=1 +HT_MpduDensity=4 +HT_BW=1 +HT_AutoBA=1 +HT_BADecline=0 +HT_AMSDU=0 +HT_BAWinSize=64 +HT_GI=1 +HT_MCS=33 +HT_MIMOPSMode=3 +EthConvertMode= +EthCloneMac= +IEEE80211H=0 +TGnWifiTest=0 +WirelessEvent=0 +MeshId=MESH +MeshAutoLink=1 +MeshAuthMode=OPEN +MeshEncrypType=NONE +MeshWPAKEY= +MeshDefaultkey=1 +MeshWEPKEY= +CarrierDetect=0 + +----------------------------------------------- +*NOTE: + WMM parameters + WmmCapable Set it as 1 to turn on WMM Qos support + AckPolicy1~4 Ack policy which support normal Ack or no Ack + (AC_BK, AC_BE, AC_VI, AC_VO) + + All WMM parameters do not support iwpriv command but ¡¥WmmCapable¡¦¡¦, + please store all parameter to RT2860STA.dat, and restart driver. + +----------------------------------------------- +syntax is 'Param'='Value' and describes below. + +@> CountryRegion=value + value + 0: use 1 ~ 11 Channel + 1: use 1 ~ 13 Channel + 2: use 10 ~ 11 Channel + 3: use 10 ~ 13 Channel + 4: use 14 Channel + 5: use 1 ~ 14 Channel + 6: use 3 ~ 9 Channel + 7: use 5 ~ 13 Channel + 31: use 1 ~ 14 Channel (ch1-11:active scan, ch12-14 passive scan) + +@> CountryRegionABand=value + value + 0: use 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165 Channel + 1: use 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 Channel + 2: use 36, 40, 44, 48, 52, 56, 60, 64 Channel + 3: use 52, 56, 60, 64, 149, 153, 157, 161 Channel + 4: use 149, 153, 157, 161, 165 Channel + 5: use 149, 153, 157, 161 Channel + 6: use 36, 40, 44, 48 Channel + 7: use 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 Channel + 8: use 52, 56, 60, 64 Channel + 9: use 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165 Channel + 10: use 36, 40, 44, 48, 149, 153, 157, 161, 165 Channel + 11: use 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161 Channel + +@> CountryCode=value + value + AG, AR, AW, AU, AT, BS, BB, BM, BR, BE, BG, CA, KY, CL, CN, CO, CR, CY, CZ, DK, DO, EC, SV, FI, FR, DE, + GR, GU, GT, HT, HN, HK, HU, IS, IN, ID, IE, IL, IT, JP, JO, LV, LI, LT, LU, MY, MT, MA, MX, NL, NZ, NO, + PE, PT, PL, RO, RU, SA, CS, SG, SK, SI, ZA, KR, ES, SE, CH, TW, TR, GB, UA, AE, US, VE + "" => using default setting: 2.4 G - ch 1~11; 5G - ch 52~64, 100~140, 149~165 + +@> SSID=value + value + 0~z, 1~32 ascii characters. + +@> WirelessMode=value + value + 0: legacy 11b/g mixed + 1: legacy 11B only + 2: legacy 11A only //Not support in RfIcType=1(id=RFIC_5225) and RfIcType=2(id=RFIC_5325) + 3: legacy 11a/b/g mixed //Not support in RfIcType=1(id=RFIC_5225) and RfIcType=2(id=RFIC_5325) + 4: legacy 11G only + 5: 11ABGN mixed + 6: 11N only + 7: 11GN mixed + 8: 11AN mixed + 9: 11BGN mixed + 10: 11AGN mixed + +@> Channel=value + value + depends on CountryRegion or CountryRegionABand + +@> BGProtection=value + value + 0: Auto + 1: Always on + 2: Always off + +@> TxPreamble=value + value + 0:Preamble Long + 1:Preamble Short + 2:Auto + +@> RTSThreshold=value + value + 1~2347 + +@> FragThreshold=value + value + 256~2346 + +@> TxBurst=value + value + 0: Disable + 1: Enable + +@> NetworkType=value + value + Infra: infrastructure mode + Adhoc: adhoc mode + +@> AuthMode=value + value + OPEN For open system + SHARED For shared key system + WEPAUTO Auto switch between OPEN and SHARED + WPAPSK For WPA pre-shared key (Infra) + WPA2PSK For WPA2 pre-shared key (Infra) + WPANONE For WPA pre-shared key (Adhoc) + WPA Use WPA-Supplicant + WPA2 Use WPA-Supplicant + +@> EncrypType=value + value + NONE For AuthMode=OPEN + WEP For AuthMode=OPEN or AuthMode=SHARED + TKIP For AuthMode=WPAPSK or WPA2PSK + AES For AuthMode=WPAPSK or WPA2PSK + +@> DefaultKeyID=value + value + 1~4 + +@> Key1=value + Key2=value + Key3=value + Key4=value + value + 10 or 26 hexadecimal characters eg: 012345678 + 5 or 13 ascii characters eg: passd + (usage : "iwpriv" only) + +@> Key1Type=vaule + Key2Type=value + Key3Type=vaule + Key4Type=vaule + value + 0 hexadecimal type + 1 assic type + (usage : reading profile only) + +@> Key1Str=value + Key2Str=value + Key3Str=vaule + Key4Str=vaule + value + 10 or 26 characters (key type=0) + 5 or 13 characters (key type=1) + (usage : reading profile only) + +@> WPAPSK=value + value + 8~63 ASCII or + 64 HEX characters + +@> WmmCapable=value + value + 0: Disable WMM + 1: Enable WMM + +@> PSMode=value + value + CAM Constantly Awake Mode + Max_PSP Max Power Savings + Fast_PSP Power Save Mode + +@> FastRoaming=value + value + 0 Disabled + 1 Enabled + +@> RoamThreshold=value + value + Positive Interger(dBm) + +@> HT_RDG=value + value + 0 Disabled + 1 Enabled + +@> HT_EXTCHA=value (Extended Channel Switch Announcement) + value + 0 Below + 1 Above + +@> HT_OpMode=value + value + 0 HT mixed format + 1 HT greenfield format + +@> HT_MpduDensity=value + value (based on 802.11n D2.0) + 0: no restriction + 1: 1/4 £gs + 2: 1/2 £gs + 3: 1 £gs + 4: 2 £gs + 5: 4 £gs + 6: 8 £gs + 7: 16 £gs + +@> HT_BW=value + value + 0 20MHz + 1 40MHz + +@> HT_AutoBA=value + value + 0 Disabled + 1 Enabled + +@> HT_BADecline + value + 0 Disabled + 1 Enabled + +@> HT_AMSDU=value + value + 0 Disabled + 1 Enabled + +@> HT_BAWinSize=value + value + 1 ~ 64 + +@> HT_GI=value + value + 0 long GI + 1 short GI + +@> HT_MCS=value + value + 0 ~ 15 + 33: auto + +@> HT_MIMOPSMode=value + value (based on 802.11n D2.0) + 0 Static SM Power Save Mode + 1 Dynamic SM Power Save Mode + 2 Reserved + 3 SM enabled + (not fully support yet) + +@> EthConvertMode=value + value + dongle + clone + hybrid + +@> EthCloneMac=value + value + xx:xx:xx:xx:xx:xx + +@> IEEE80211H=value + value + 0 Disabled + 1 Enabled + +@> TGnWifiTest=value + value + 0 Disabled + 1 Enabled + +@> WirelessEvent=value + value + 0 Disabled + 1 Enabled + +@> MeshId=value + value + Length 1~32 ascii characters + +@> MeshAutoLink=value + value + 0 Disabled + 1 Enabled + +@> MeshAuthMode=value + value + OPEN For open system + WPANONE For WPA pre-shared key (Adhoc) + +@> MeshEncrypType=value + value + NONE For MeshAuthMode=OPEN + WEP For MeshAuthMode=OPEN + TKIP For MeshAuthMode=WPANONE + AES For MeshAuthMode=WPANONE + +@> MeshWPAKEY=value + value + 8~63 ASCII or + 64 HEX characters + +@> MeshDefaultkey=value + value + 1~4 + +@> MeshWEPKEY=value + value + 10 or 26 characters + 5 or 13 characters + +@> CarrierDetect=value + value + 0 Disabled + 1 Enabled + +MORE INFORMATION +================================================================================= +If you want for rt2860 driver to auto-load at boot time: +A) choose ra0 for first RT2860 WLAN card, ra1 for second RT2860 WLAN card, etc. + +B) create(edit) 'ifcfg-ra0' file in /etc/sysconfig/network-scripts/, + edit( or add the line) in /etc/modules.conf: + alias ra0 rt2860sta + +C) edit(create) the file /etc/sysconfig/network-scripts/ifcfg-ra0 + DEVICE='ra0' + ONBOOT='yes' + + +NOTE: + if you use dhcp, add this line too . + BOOTPROTO='dhcp' + +*D) To ease the Default Gateway setting, + add the line + GATEWAY=x.x.x.x + in /etc/sysconfig/network + +======================================================================= +Dongle/Clone Features: +====================== +A) Dongle mode: + Provides a 1-to-N MAC address mapping mechanism such that more than one PC behind the STA + can transparently connect to the AP. + +B) Clone mode: + Provides a 1-to-1 MAC address mapping mechanism. + STA can use own MAC as SA MAC or + use user desired MAC as SA MAC or + use source MAC of first packet coming from wired device as SA MAC. + NOTE: In this mode, only the PC who own the specified MAC can connect to the AP. + + +C) Hybrid mode(Dongle+Clone): + Provides a 1-to-N MAC address mapping mechanism such that more than one PC behind the STA + can transparently connect to the AP. + STA can use own MAC as SA MAC or + use user desired MAC as SA MAC or + use source MAC of first packet coming from wired device as SA MAC. + +D) Please refer to "Config STA to link as dongle mode..." in iwpriv_usage.txt for releated commands. \ No newline at end of file diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/README_STA_usb b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/README_STA_usb new file mode 100644 index 000000000..9d15d6992 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/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/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/RT2860card.readme b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/RT2860card.readme new file mode 100644 index 000000000..4ecd4d719 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/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/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/RT_WIFI_Revision_History_2010_April.xls b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/RT_WIFI_Revision_History_2010_April.xls new file mode 100644 index 0000000000000000000000000000000000000000..53c6da4744a23cc0dec4de08f7e427bc3c086c8b GIT binary patch literal 123904 zcmeFa3wWg2dDmI$>6z(~ZyDQhY{!?+8hhOBkxI9|&Uj{0DoNe)NG*+|o}S5!Qz?~7 zt#V6Ma#g8Y?POwe31JgR!Wa^8%qw)2Lg9Z4zkluS-McY+i!c2A|3CjPnSuXAKmQGD_5kT5=|Pg#{9)25 z(j%l%(wj(cCcTC9R?^!@fI#6<(%VVzAib0Hm85r(zKZm2(tAknC4DvNeWdr3K0x{) zDItA`G)8)i^kLFRNRN{~N;*wCL;4u$3DP)ef>b0;lBP)0q#4pI=`86S={)HI=_2V8 z=}FR4q>q!HCOt!Xmh?5G5^0W9Ce4!;NQ#)t=I%$V=gS1O(kUmAaN!lar zlbWO!>45ZUQk&EvbxDV$Tcq2hBhnqxXGq^b`bN^Lq;Dd9mh?H&IyJR;GhyUS{6pZ{|q<3XUV1q7%Mbz6ZiuRj-QKaTx=+t+;k+tB_ar@n#>|6t+!KlsxR|18-3 zAs+rx;Y8sFPyQtT7YhG~^a_y1-oH|995kB6|CE*ear^&i!%6IbkN?^Sg#|>n9x8l|mHX}X|Cs&%R{kF; z{8@YF?_16^SW9zrs_>m!){);@I63lz^{H3iy7Mz%mhekH(%`Pw{_?-sl=H5N#d45F0-WSG> zBOd-d%+@jWkAQit@5esB``P23pUXDQX|l{*lO=O`dUm4g@AV#v~!0;$GZ(Wj(aAkdS+;yJ!?cyHOH;o8h)T} z4jvvU8^krhnu5MK*5g|K(F|t$=AjSPKbD7efA&c1@sMX9KlWJ;T8F&%=sn&$8=-v2 zduNY*?*#lt*sp!>?Sh>z9#iM|J)WJs$FrXUc8;sFXO;Wu=`oPJ@*aR?g`4WA#Sg~_(Z&R>4YW!n~^`tW4eaU`?r(+XiJgZE6O=aQ(C&yv^ zU;-->S+Q4g-<97}{%P1lP<_53I?&ga=VZ-2`)tLaPqB%9};uFzrX*=gmQk-*!M!=KivHaKq`K|lqi3Mpa0=* zQYifU`^yJU4=sOOzG@v-|NocsM@)Ru2=(!KX2<#b3uEhZ^7q^P59a^CG5OzrO#Yud zCjWbm$^TQw|uKpjfdL&31e5UjB`;N)?{tTA){tV{-;bZFg zp=0uY)bb@P58p3OI6MnG+b8a$Geh%1AARHc<5vIsV*bxS?+ed-Fv5w1=-zqobr%V- zebm=3c-qVV&PN~p?l*n+n+hkt%jzEiXAUbr0@5CqPY1l7pE22$Y4mYP*th`G{}-(OBQGbZb&^Z!_H z{+r@Fd^pQb`1-bi{J#37?67%D*Twf8cs6BtiT5I_m3)M5mMlc>Y6{PbNHre?0$T>iN(K%75ddkDfYt>SW>M zTOJj?c$h+#f7G8pO+KqUP+s}R)kFD#dQ?CC>C0E&tp8J?-2k7bY`oO34P_tiKLpXs z_l*m>NIqD%FJFqVVfg?6`KZGB%6tBC^$eCr$R64s@8@7Wp3nUBwVU>{Z@g084eP&; zm-$qM_Q}J;U_Sxuq4nt1VfA}?TIuVj=MUEJ^G4yJeFSD`7_OrxH!i@s%JG-A^ULVaHdZmAsGPXdaKRM9X_0m1uV!Uy0WI4J&zl`QED| z0)8Kr+aUYf3dv(N=-A5(&UL7HftP*|<+dDI}_g)>b zd-qYvy;ny(;C)nb@6{0lcpsJAdv%igtK{CRBbMzxdUEg85&z|tNHYCmy>NE`v+2Rz zfBD6`*#^AUhaMlN#L45)GxEpFx!Q(VpHR0SxcmPyL&}p6lK3=wi5IwWs!WaE_0=6#@3 zv9Y_K8%aC$>Zzl?k;xMHAT#eByL_QFtRv+d|n(tnnx?I zo|@=uTNcO@>8z@{9>5tK@nkw;8H)7jdBJI@TVR1S>+E19Q@r+uFz+VZ<13lIze)lg zIHo5v_g6{41IJV{dw-P#Ja9}UXYa3)fCoY){mXfdN_;uBI!gJ~85vxO^F6Khzi>j$ zC^PK&W4eCfek!^9?7b_wct4e-1m>9WU!s!Z$A9A0Q~g-wNnXgX%Cpbj>V^MwQ@;Lt zw1KVFxGD2{&mK@!$g{l{H>L7;WS_Vx^Lc}vdWy37PCYxkQvucWbn4k>pB1XJwqvJ4 zUQef#7y5+O-7!x-Z?IDzPdg=m&?gUC#yktJe&6?f-@r`$m+MqNNB=Y}X88Aug@=aE z)ZM>ol*J}w5C=X(B^eH6T6!z_{E4qZl6s^tGK2pABZUOdjim6-?`Z$V>B4KL7D&7v zJ|ibTfTz)5IdyUb%k#r0>pTD8m;c?}2lZX@2W@>sqKDdebXXfRL)sV{(uU(PYvaNC z&aeFZ&kb+m?Zeub9n!|*L)vgOXKg%G-}x8+?&pWM@s43_oE_4}$A+}wSkT&dxW4nt zzxc0)xAD$lZJZm@MsY|RLXu%UPO%>U`hOqZ##at&h3tc_uC_2D6H_3#-PDcptfUmgFA%J}?=w-mxrZn>)>rPKyAOqOF9Xq^v}Qkl;t^;uK2H-@ zm%ib(Qx|$)8F?Q)(vt|t4~nWI{EG1E`xlXr10X+w@tJx~ZJzqp*G^sTt>=OFP>-I7 z10EpS58*%hFmtl{8~(!G5g4}Y*F%i@;lf9mgppTYdhL`J+InsOjf}jP;;+7x@0 z*f+_?p>HP(r$6`LkePdsnfs<&53T>qO`o~9;9|g(pZeDC{)Qi`zpe7xsZMW;C*F1U zWFbBkZz;m0c@PU3+m-Zc?P^?lC??g%mHj%^^X!qHUs~ypeeNXv?E{bpPcn^v^taW% z&U<^Z@WkgH9-uUOrOSFEDKyTOMDsW~605Vx@n3Or{8yYD z|D}CV)FOTVx4w1fTk6+ee(ls`Uz6upr1(@EX&ivoAppdi3X@`8BKLWzw}zAN2QK_s z1g;35s!Kv_4uijmNe*=hYxmdnp-@*IQ)32PTQPtcsB1dbCG6Z^*GEEKd5l~re9xbM zX?R^Tu`XfZ{<_YDy7HK}Q25;T_YSXXHrAz0*k9K~s4I_Q@sR!#KQ+9rv#~B=)&9Ds zLtS}HS}6P<-?ccbu19e12K3(Zspa4O+Nmd~%`k)gH}b&S06jg4Fz_$}*9VtgH5eEX z9Gw>&sYHUu+-s+v?tA|$fTQ>{ZiIXtpr#B}J!lyFLRO<-p})pQ(;6Kb44QJi3N_w+ z_K$w)7Z|SkcrmL{5Yb=b+tV5yCXT7m*^d)ejOYApiCG6K}(P6>RpspZet+5s@DD&B9kP-t2jPE+p6wV3CLo)xtwY z0)=4xSH3R~!J9bp^=BfFPm4VM!i$6C@v9luFT5Brm|<+>_qYxc@&h(}3vQ_Fgq?5u z#O82}`X*o^K8-M8^??Yjj&DEpV&U6!o9{aTok#g6*W)c*q3bx+cX6iIw-wShPO5Tn zzl0k_gX0N0aFCT)ChrFBu3fg}`NG$mGxj$#?&V3z`VSR0cI)--v~pJeMlNSYIsfo) z=5l7gaO&NKFXZ~AXZlFP@`rGA|3kTF%KvT5!>tEyJ@AtwrwTtw;rIW`k-~p0pzQ`v z|9f77OPQ~B>-;M3HV!)VE*UGW?KcA4!$ez1>PmYn^1bdaIsvs{8e1 zV`FK4JSiP^cQuBj+T2bSnzi~}-A%UY-7W>zX`q-asT0-iu!r=eV=oT0W7RO6w6RWC zt=+8G4|t<}r@@JXZY!y^n$3Exdu#*676*3r585q;tPaj?Y$Tof9)~ZeNW|TRb98}pgA-6c%U)gNFvW0_AOKao-la4oA9GyuaMiqDNG;5*exx>cZc9|7y*7ugd6RMMKs`jbx@c zm97|$SE2Pc78~Rw46mQ9 z#&&UcJkk2azZG9HWmfj9jV9}QOGR&YtO@>9x_fEP?k5VTg#U+3yNJv6#Zo$uwZ+G# zi=*?c=105iAK&ziE|Y${czR}PdTR2*0=-&|R%Twd6$td+{o>CgJ==4yF$8Q^>yr$y&EM#+*>k&r1+#K60)S_{P0sI%N) zu>;UZy_-DF`dys5I0fFRcMJ?b7S%m1(Nu9ak6xLSy+-r!2uK%th43XSrSkf!fQ-Go zb*D=Oymo_HL*=nmd%;^4p%Zba0ja{n^iSg}vi_yD&v9~dqYUwSl4;r(9a(6Cx(@3L zRS-Uyuif2jK(H5E?dz;bQUVj}1re0at^snVF2Y(`TU{2W1k2DPuhScCEYH zJO|#42A0-}@ZtArQyo_K+x6|kCRG>?Z8eMEmd95HFE-|N9|fHqs5B)5d4%N9n16NP zz1#!@CgS)RT0d+yHOsd5Dy&vzvoyE7P+7RTx&Bgy#k4cFtKDj`mON=~FEx{uYHhO$ z^R(3L)Z5(!QIykX*corUEP`;52WU#XT8b63&6+hrp6yB~weRE#q^cq!(rV^f`?4Fw zgYnwN9C*^$M*JNj$=Rzy2B)WH&KkIa=o&YS*0QS(J6p+ai^sU72nkh_oqDx<2(ILi z$6RIZ+VXS!w^%7HFI`??0>@zX1Md-O`$c0Plkq#P!vvZE^HXiZ$H2xVw_EM)<0=w} zcItUH0ET1zhIw1{r zk}=rS(+8#PiDya&kkKNwcUAk-PbZt}*A~uu)(x7(jSEW*&Wi=Ap^r@G&OhkQDTby`oygwHf+?O3g?2I{<}cvIyHbFih2 zjL^gSb`d|W>#f%I9fX1iHS3GdEiErcc=(d7JJWh`YG!&mP;(Jj&nm)L)!Nn0F7xQkHEf~pCvgO1Zp!6NS_?+16lqN@>GF|D@-f-p0^~%PzwYAmt%`=*4qlGt$`#1ly zYk_O{L~FOX&cXOzTJ!v2qjnR1^Pt7H4>Cs$mfMluN_oTSQqpL`^%-F~>n||MYF)XW z)SEZx1E2~kv<>$k2o9tX_69Ld1bDf0HJMEO|IzFG2!(DN9fmg5>Ya|5;z*_vAOuc_ zTDR-9wz1};<+W=tGF1_);wY5$bOsi0G=|@hZB8&m+=-LMh%|uo06Ic8joSx^d93XI zzF#Bl>&Q+UG^K50<$c+-YUM4Vc`#^>ZL%UMC)raLmYDHZ4i2C=RxGZ?wgJL~ z0YbN3ZFctIlESL7Dz|xzc;4~m8%;X8Q$=cGwu}Y}EPK~dqFot&cWM z8cr%!!WV%S_Zq?pt7{8aC$FwvU9h36m?TPY+UdDA0Kr>Pr>#2jV(IPxfRH!q~6I+Q|&dMj{P9vn_-ZGtu> zI*Rz@8a?oSk6Zn!&}!a6QPQEVM-(k1+p@yo2erLMSehlUxMt)9XeC6YzP@pFX+g9Z z)C-NIm2Klnon?f%W>IWSyD-K@$B-N+c*`77l$WTS6#jyLyUY3+rx zf!kenZrAYblZo@o8EdM|WbAV8Wz~92oyF0G{B-njz1QoAL@rZ_?M=qMX>8oM=CKcr z3H+E{vaNAg$w6kmwAX2+HNbivHchzVO))IU8;x4sIQTH8QhCMc$dk!cwOiHuz)^Uw zx}(jCNCszqBcbqGWu>!ySccE(K=_zAuetbz{FpL+&sK^h*8I%ZpBJmWW^#d67*1hW zjo?NkG3T8d$i|>sgDHCtVF{d-A7tpMu^f%|rz>&1YvrXl-cR`Y!B?#%TeZpkT5=7h zGg)glTBhs?3)?dRk}|HX8K(4C98GkJ-8UX-dADA>xj?7e(!FV@Ti5sZ*Xy5-S}Epu zzj_C?j##3kehV}qDB7}p4+}YIJXnoy0Xuby&*c~UlcU*Q1S>Gk>NZpa+LG}E?fOLA zqL9Ie6Gq!DByr>r(VB1bdAWC8DD}cSIlOexy3GW(c2HJ9PQtHdQoVsxJ09DBDV0EK z64Tk+)jP=wDj|y7eis_KT?PFza3-K#Ouj2WvBzMErJa=)QfjM>DiPR_!qCONfP#XO z)WA*?b7ey)RLTd?DLk#j21#N-?JV+ty(Ziab8ySvXtt8MdX-vZnX@Va3M;H{&dy$# znjF>NOH&Vkbv75iJ!ZpEdcJEEH(yK^UI@F&MaZodKukBZ!O-)xL2F>UEfjjZByVC(OZkwcThPe3kyi>EAe#!SExPrUh$V~ z#`R8>5wN#6j}~t2mveo~D7r-QQ0dgs^vsk2?D}G5{gO>x?$J#8XnNq;`S@&R`gFPc z+?oD&&*q-5F3ztE6hLYcx?QZyTpC&dB2xO?Du5OJ+IqVMq0kzgo5{1?mJy}6ugn;) zbrp>HgoN5`X}>m6>PvfX`gd1^!OkZ^#~NfYVX90XQ$2>ZJCJM`2}!Ig`HdV@Fe^yC zXjD<$+^nLZYdK47{4eMZG@kJy+pXKp$-@KTUC1`ws2AVDR_?({gRB=QxZRz(cywec zC}E_?YC%o*y>%B{8ZJ9T#>#m`l-#X}pcR}*Rqn+kxh%b)Y!d9Usww@%;j9H+wDr0P zjfFv?kOwTv-#4?(e6Z!5y{sG+nKsScc~= z*2X}!bTvpFBBsmIbtTVXpFq<(Q#@asJ@+BuV>2~mTmi_1A7Xtm8SNEoZNu4M21M*# zl=OjiNzUAEYzyCtZwT^|nIH^|f*cxNlJEf%HEf*nrYwe7(uwN}Yr=}ocTQ|Rx3pH| zj9}3OYV97zo?%1%=mll^2oRy=X=_RkDaa&%Pce}u) zWNoetCWmDK-KzS%>H#!UYwg`kK=G-r#k6Zbf(KK(aifVkI1%44fdQxGY;Cl-n8j?n z-8uk<_ZU5My03W%jDi#atfegsHYH8a9tJOcv0V$lb(^wX6gXB>l&ge61}kH*){V>U zmTi8BhEd&#PW6_mH2I{+ITWxtz|q@fr_cG45fF=s4IFCg3LTiT8`v8<8mu(a=)reK zwbD&=UE|61!-M=xn|w2TUVX#HWv~Hi+oJDc1z;PrZ{t%JuU9QTVY)d_J{WnV=+r^i~YS>3-^S-`Q;5Q>~kpIq#x+)R&N?p zz6>MxOtNvMG+miry1cNlS=m_n+6C-)wW@ZdEp0IJ?KiY{lj-w8u`SVT;6(~RX-)H8 z{Ki7z|H<}&g6Se~a$7<*h_uuO?l8#4eRr>kOVDJYw)#xcIe_CbleK`sOb$*i_t3XU zIRjJ}!olt?X3a=xcqWPCM)U2qYTfOlGsZ|hKY z_Tm$wjjW)X-LOL#Hw@FiClv@fnP$RcISUlKM_rD$0FI(nHp5T4qFh|r3c$7AX)e{v zjRR=y=`)i(xuxe;PM`T#&icXPOu@N0KgySKYvOvVomb3^t_1C_tmos&3*}YpxbTFL z8I26zI4iJIrEIc;thXyUybGQmH%|B5%y?36(|3^L%+$)2&xl@})tB*PNm>)peE3bs zetg0Eq|SvtjVBvd*AsZn+9BF}A!g_!Vox>Mh$el#3sYLYvb0uNU5nIObC1>qmFEN^ zZ8KZ?Pp;r@A!Z2+4M7ZzUxAqtOl>u8On7dB%|@c#mitr$7&urznxA-Peja7asLJQ4 z8jOCj{vzWSo73zfH?dAoWKZv*nWZ;h zEU#YO1Zujwt?l9&EDET4WrURC6|5}kAniWp&YD>X)UV5H%aP{2pdvsK;M-%~uhI}* zrAasQKRLRNMd9jm@x5f;{XJ9_&Mj=IWP@EQC`6+;P zF%z|$Hs2iCY}UK9x5sfFfI7g8@%pEy&%n8CCogW6mK}DAi9JY8&zup=$t9wibndW4 z_6_RVZ~-|r?j}-RCoEXnQW@;bGK@h_4@K*5WBv&S z2m`I9)$-~*bj-4v^~ zztaURas;25h;UcIBJ@Lr#W~)p zwi~9r1)W5JK=YuI2#m%g?^ll+`-l68O^Mso{jsS`WW!oL=oD9~M^_K`S9jKTmJFz> zw=iG}x~i;}2|tpc#nH6P8>(XyRTlreXTvdpLYz=n7SxW=o1w+l_8~91iLD4s4dw5O zu)Z3utF6Jc-Kraw%vSDZ;o3U!a`9*~y?LX#UB~4BF31^BfrQiuf$Q3Xe^C##%2%M! zd-atY``vXorTP6Tc5=*)psDuZK^M+X4U7Hpi5@YS%_iD-Xm5@RrOc@8yAGlfI6XOR zFymKQdnojH@+sjVpFfNRnSr!-2#%@QBKIbn2|beANrRYKlX@y)__nW;bvzVS zI~(0L{n6L7>GN~SxHeEy&HGR%r`dB5Fu&^p@_{fJq)<%1&_vL8&2e%n%B zmV?rIx1))L_*Ll+N@$4Mt?J&PFp&Yjm0HAP!N!rJ%CKUXEnL6ihQs9QH4J^W0L8~O z$?hDI1NUs6<@aMo^QDZ&1%1IW6Y+d0xqNMj&Th*^$5p7NeQToDhe2cDlH^!+7=?=$ zXCXopbBi#-5icQ(O&8T)8LR13irSXumltGNtqahH6_AFYa|nOe+@64LxC=_qiI{ym z7#J%X3(E`T&7~I>Fgb1@ZqAQ=4aR7Mj`AK5zjjkjQ5o4exZREtj)RQ&Xmc-#6hfBJ zBDxz@F(9Ksj`H$MPS%XRFS5`)w|QlKp)?kSz?G>X1h(+&!5M(e)?MZ zN@@Mf>8YccndFJ&wA_!Dua+v8OG{VfQgG&D=gv&do_WeBv#@P=ZJ=E8vE&?<+1WGH zLS<7=CB_2P6GcT_QiL4qj_+MUl4qz`B{!9i+eYgIvTxjEZ76wR_Ziru_HT+c&??L0sAI$ z|5J$#RMoXzwJ%EVv!(^F@+|f+^sW{Pb?g;U`hc?BEdsiQhCsS5F>|E}c?!TQ$*LM$ zh)iqTY_Yvy8_W^8Lr1WrGDC84Si`+xZf;G(01-AmV>~-u8a)r?Te8Kq{JJ{sUCqH& zI+@u1;l9QC?^h3`3@QH8!pO_Gl^^0Ho)DY8L0o&elz)<6PZmb`U;h-hJ;9E+MnwM^ zPAGXS^*Zs94=hGPpwr+d-SJSxXHH$wdj5Qtx;=}e|5g8rtLy8*V7%!ZQv|lvN!a8jd~8P z?Zo<9$4Oq1=MSw!zIBz(`c>t5hjKMaXVK~tMqDp^nzuEwu8lU1E9S%($>3Bvbga z(W-U9`D%gop-qd%#v4SUVWGf<@DcMxeGee$ncxN(_Y4YmqtO0?!~VI3ckj9 z6|<|ACr!%(OBYJ}pv$XkFTo&eZZ2KDyir-ifK^#pURkJ=uDw{LuKENVHerKgLKV-w!NMwSO0Ot&srj(7K<3jr_E>$du`>pGh8bHk4YFziPNatiZNCj| z5NZpF_+@*gh@D27(M>n)#muJAYJ|jJRAtzcIWk_b@;W7jmpA{n`kzt zFBI=s$Gp|0)lH@xCp45>Iw`VV*MW zs#f#-Y`z@QBa`B7Q!F|Yb&89utC2RTc7Wsql&Kh6>rK=6n*_)BOlv2>B6Am{4xKSz z`i(m-UWAd{N382UnTS|REoDeT3p72wvZeDXa;B6OyZoHgUUQ}JDk`{_rLZ^0IzO94r8=#jb`iIR4Va3=zK?RC6SOjI7 zi>r-U2aQaiH*4YO3tX&oM=D$?38n34wW4nwUvr8OSXdOS+jYqX9c_zvEDHam?Ybeu zte=hUKNM2fN5r0V-ZtnzM*A}1!C`PiW}egN&yr3dUsBBb*5Tew@*KI>LGBX6(w`dh zq!ce|Bg<}ea#UcHUnU<2!#&y7YdGYMU0t)nKHcDSNK!AiU@PH7i>6wO zu6bADVT$XewWT75%&G^INC_?!qF{^NHO*7O$rw9go?6?wXA?M&nDPX6oz<>;7% zv%S&z9%mKTjgI98EH~=nF3K@6#mQrM?x0fyE5ER?zOl4=wNhT4Ur3&LI(cqk{p!MU z%sxFcetvxBk{j{uMe9I)K;oLVdLIKosCg2f%E8JfCn*EITivLvZvvky;N)uu_Fl?X}7)JG4*}A$sAW2HnauTFlDZtxm4s7 zL|lU$fADyc!bX}~({hQiaG`6Lp9ZtFeGZ8bpUZKYK)~?b!LIwd+F1u{dU<(sn1EU& z0HA2Uy~(!QlY_avu!MaODI}*cmX6IK$h0$bA?+tn6?hNoJ1~lp_C;h}h9|4F-MuN7 zVhjdkV~fFYC28+iUMTktE?-KwM(V?i!XA~19L@(DkhZIepLNC5XFzqbp`~2iDAo!E z>2X{|hj^*Ab{}9-%1c;fqWV{O5o869HacST0@RPgs?Ci1X`rmiX**Hv_F*kk<-Q!( zI}$Kwk1toT1PM;3XJ@CzojE{9qjoQwz&1W=48sK&hKsYLvmA|^!i+vWd%;S%SjQ^o z(4p%OTws(mKZ{^qtbHW*AV)=$_30^KVx1#;#`vi_7&|g~GkpnY0N2wk$T!s`%oDy7 z<`IUCxsJz;5E^H;A=Z#bGfi`J4A(Hu&bp_Y9cPRbhYi}Lx_z-Tots;DOu&aWWY9FRAdbPJO}tb9*0DI zcRjmlp0$=BFSX#MT6>Cg_c-1(mZ=8}?UdK%^)kJf9}q0-6*-=dT$ zl9KuTP$ND-_3au~^Y9%9K&jEvGJMw>_$(nh_H@3@$$%E=d_W+ro8FW}E`sG3#P#mJvlZjeSkLtKv&t%3SieMDEDcN?`#d%@w}uf$X}QlKQ%rE3G#k}e~gqonx=Y(&GZd;^6qqO#BGg`cryDHyQ zKxwS4ooZ60oD)D~3qPK6cB4$4fJ`R|bxM`Poihe!e3_+*?K+3H*j{FglL&xI`bN3( z!c0_Pe}0JFMPhG|(OpzSNQQ)7Kd4GZVQF>N(6%?@fH61a11D}k9PnfzY(P*5WRHu< zX@O$>$j*j8DS=-|(a$LWAZYrS6|&@5c19C2o|mh2-oYJiOI^v=E?ke>IS9|cXhVqt z1Au5JR<9kfS?VCRP4md~eh+v_hGPuFCq5;SE*^|05+!moiudf|5+@lqHdogdM!&yxm`8YP9Qs`4@$kuGlht{rBw-Z-ZdV>JTcdYfy;!ACX7Bf zABF}KMT=0)*seUl#FOzrG-S?q{U~IwBC_ky_hg7fQE6LS+8zF8%-DTp2wVq$?Tqgg zz@cdi=Ld3UZ?yw}Prx;|Q%#)TZQwHpLbn|Y&z32EG5{r86!ik0FZgs^yfBr#FmrZl z>X{*3QbPbrjT5}?7~8Ghl#*!w5LZ8`h%gme7zdZLG)o`UhBmcXP=xu}{q@Z`oSy9X zK2$DiU$(n*LwAPoMhMxET!-$TmaB=3HR_QYYtHC&&xh^pyt+as!S(jq408m}%`}RX ztMEU0D98=*+>R4TF-XSqm{7`5AMro>ZpDJw?KwN$o7?H*PwTi_`YWEF5AXWihaZR4 zgHBd5ouTkF*pC9Ek#d9Kw=k;_m#8C%sMfiUf!rQ_g33k(K&oVrF)hBfg9)xxLsuI! zIET>KsTgt0GTUuDe`ASuH>Y_BopfVcEOEP;D}FE|hBB1nN5<~v^4vz4FSWg;Fc!HY zIws*>a{1gIorr30)^D^1i@AeCZ-u72&$4nPKQ^G*bBQCL0{{lAWayoWh2_rWIJ+D& zdY8BlXUEFrREU3%<}S){FykqAokC8mCu`P|CoWI&cv_7$sIKJltV>xDi}H|r z0pZ1bxUv#X_tPS>t7Z?i%00ha(UO+d(rB%+GPif&pZnj^ak{LCi#dU{POHl0hDOM- zLX+|^w6!^3G&s&wR_x}W7|8N6rAANQF&Zz~#?3ve)>GQITiOE=g@J~$Ze_2A>E&!P zuS^CM6u*YxJo<@)DDa?fwusJL+i&tJ!iahEwLLJW(y*hfMi2dA&zN!9`F$#hihPLf6z4$5FEF9LV8)GX2Jarr)z%e2=7IpaR3J@o$V%5>TU8>bN%y-G7*e zLEJbIBT`9j1G=w4J}31-%V(x|J8o4RWwMIWt(s+-LqV)T_ACo^l7go%lf}8w^k&Fj zzrwty-~tE^MJGMTLv7&Im<}!=6RR(s_}F_pNB&5muxzI?Hdf0whfsE8Ba~sz(qi?% zMgWzJ@v|&CNI00^OwxLisNH}|mG@i-4<)%dH8gUbrzkd{0UHn~k12}G(x_8AYqf^V z>gy5)S9f;CrAvLoPr3$9ii6p5zI_W%n@;`Z`x;-}!dJMV!rg&=6n-lIqv2S2yE-LJ zWu=2{5{|BYtA6LB8qa_2HY9TfW3fYR7~_)csF&;A4f?ZT-Fa_REVx=z%7fB+`3ly# z>VEOV$XhZ+c%(O07$wyh=adrX@y8O36db)lBZzGUoo}C+CmMNV1YSDSLr8Iy z69N{Q0}*IUPoju6hCq1#)x3Q~=HXX_Suzy&O3xN~g#tbNj_IEIH;HBT?Of0EAXUB_ za%!uP(L;w{@tqtsT0Iod6j&K4a($L6>B$rEHRW4MvqGJ%&MQWdcrSV%g8KXNz{303 zesU*Kq_`N>ah*o9x(9#0vR3Xpfom!a*}9oDIO=-)4@h~8by#*0S#JIO0YU?7-BoasIQ{mpL!6S*bMrldb3$Ydt}OKG=Qms z^l<@sRJf*8%JidhjFC5@Yg>l}b#M?krq`TMTO)!Yv22!?%B8EDHViC=1f}X3iTsKG zt5q(l^cfryq$>|?Kb_pEcPw;)^g*(X%PxiGw0wC9-CgNwpJjGsb^hA&!elaUJ9amihnl&i zT`etFHebXoq};Ow*o0A9&UTzk5y6&{Zo<|6Mm0P$HO!cgjUDz^VjQd9X+ zGo3z35l}QCQH@9L!v_o}S&o8W&%VQpD96}{a+Gowo>LrHUwV3yc8rw(M+-&eC#|@P z@$i0E#19k#S;6_xj(nfT1;hw)COy9}P^IQI#)i$=yZ1SrZl?N3$k;L0HkXzsuP!*^ zn_tJx9!Fb~7&}FbYYZdhEwsSKm_dDYIsoBB?vc_|W{o(yV9%@_@u(q zbA*zfEmU~(MV`ILH}|-ev8RRSY6XweDLhV<^zR~mr}Ffzar;HEm13AThiBscqE7BV z-6-QzBtgqVNaI*eumO5*TX5wucMsXG?nO!#3?@XblZ}HwxOP%k#HH7~>cR;uzuR%; z;3p4lQ0wE#%tdtj9ux}-np!ngLH|x<-(-g1Xn|i@Gie96fg+cY3Gb)4-VllLSu%Uu zmq=tYD9(6sFjs%|c38B`$*OObu?|gIeg~+3<|ZXs70eOq1fk`d8m?0 zk#9Aftb3_o-eNj=h|c4V=rKI!J7*Yg5r>KkxNjnfW=4TxX~^nksMpQd+3(0I1=Pgk zw()4g%-n~1R@_rxl1+|RNF5C&+{k%K)$?*(mmcgNGi_~yK|Mzl99=)mxLfTGM-Gx9 zd#ALmuoSsnqWv&Tn=()^nZWhTPs+zIi&!K=XmYSO3=PLsLEkJpKRJ4-jfbtGTcuod zcV3WtxZ3;xy4Dm2clPCv>Q$LjY&g5 zs#S7>Z@=>@N3nr`(&8>r8Tl+>~9b9L~v1 zCzE(_$oDIou~1vFHj^zjPt7Wvc}#1a+#Q=ENx9X;i%$@us3SI*@x*)twmI*_jOZ;w z40Bi)Nyu1fV+|o2sd>F;_25$ErZpJg4exi03ksO#dKPF7+aN>(jl26Q0ldQ+g z+s4(((gLai=f3d5%Js(-&<~<0T-#VJ)31f{>W0NDc^v0>#d@%t7$je${%xEkNKu6j z)*2^>)Pv$W&5v?GJ|_~)pt#9t)_F7Han0r~e1X%Yl8hJ$=U>I-3EFQkDkF?zD=5HA zhesaz)&jJpIjx8ldd$BvhXe`JjSiNPGYRW=u#VVb>UXcXFK88GU!&!?xQm_*GBw1f zDfl?efVKtdPRj^~VS5S8D0cif`1Ben4E>wRy#s4)7^kt1Zl#^BCR8?X{9$~s~AFK78+Obp!Tmp0axOD};J zpIdlotu(KoPhsfTv3x6j;*DG7aD$vw%*Q2Cb8RmCJ~@{RU%-h*+e<}hQ(f$%eqdI- zE8j9Wf#L=1S&K2D%z^B*g*z0YIwKe4mR&2rPeFAXRYib~=m)X7SWa$D7tbX$IEW_< z{6kTfc8<V)PCKB<;M2E|<{UQ396L~uGvdw> zxe+3NtG=BR_Q5IC=z8RcUotB%H2<(^tc}rutOi`pwBzEO%D3eC)$x* zLpzXQco6RVf%0Ih(~R1oRzVj2*YgS{Bn@qJi<IlVQ`9!0+dsu}B(9|1$Xt1sxcqCUU?GWvr zL&{%!=ZGW16BELTD8@Le#TkiLURav1Or5)U{_!=w%$}Vt`T33Ero-W{crcaWZwzl` zc43sW(6YTTuCz-t`NH#y-leIjbBiiGSKq@$DwI8UVK!g(+|;~ve|lRa~B2La2^St&T=vkuVEnTRB zJf*7_ckc1L3!eXx?KK|6ur>f1kCelt$topQBr>c^R~Oey6YVNT*+KD@fZ`2fr<`MQ zWwSDOz4(1;U)Vx2`YHl==v|7!a~Zu)dpw6!L2w)h6(}c=@3`rDEPq1X=CY6?@j=&! z@IH7wFr|IB>6CZZ?UJ6CKMC+(sWvztzLA#Iil6g?4o>%_#S7nf2L9Cr6kt48rc{VC zI9-|IfW*Xf@o2Bp0~<&%z3ZU$1_N+F;V27?l4@kZsh~>Nq@$)=w(+?SCTx76(Npl0$bY z_7{xdlKm^H`oJaw`#jA^iEoh6k8KBw0bLVSA~{P1QzGCqe0CvOS`E4)NX3+oTdD|W zlc3vD{J?btj@K}hMG+28xM^tCFd92cA7`zH6BW2<7L5b-m|y2+FU)*Zy4~7!#5Rti zwq5R45ajF~SyeL85^xi0^<(XMCe@5c;+gh!guo(9i0(;InLBf!;fuJrh;1lA6b@0V zZr4278LRw_P#MnVb|))StYL6_VKPS;rFo|1VI0Lk=>&c3{ zfOCqVRyVK@V-Y~Ue_Z|pXbRAITjVrRmG#-6E|GaLS&~Xgx~C9J!M9venlH1;RcwBQ zJ>B(4~!^US?Q&4UY z5JAS`;I<+fSDczIPG2I_O}0T@O`B=tBX^v`0GE5VAkN=q=Z$(6KAasNTq&_1x@-^( zsVf+~eyCU21*T?xkq>KQ{axSGuVG|~w;kh3bkEKq4R%OV5u>RYRQig-HbJ$eu*AB4-rzj7Tj3yo8=gYy=6M+FAksR*xsb#}!vjoIv zJZ0z`%BPH$2&=&__yragW`hj}9^j~o?4;q$eAA!$>iD@@N4L$Obqe5Q|e}XG~lnkn*)uaE2U;zLV(b{4NkhsDemx~ zx~(WiI!_474?)ot#*kTi@!X5X06AnsfI&ckuxigVb`(&F89^>oyD8sax`$(J}y9PnIR=#IN#-xLq`ll?TlCG377D8XOHyH@HM{JyRTG<>! zHe(8pz;n!7z|lGzKlP&-1`!NE6~bu{lUL9Xm04?|E?(i*oT4tWGAA_7mg-hm51kwW z>gy<;P#E@(R2l_{?%=vUy3yi@j0KgIs%L$1sg{_hk{}Gy4dFR#D0Hjfintiy3u{I? zBo1!XkDkO;gYog-%%srI8A!Sn4sLrQ3sHdZELSl^o-0>uxAE(RutXcm;j;(4wH<-X zvR^zS0jc}`q3XHLAt1X{&|(Xk&1lC=FTcr-MF&JF;GpG67hL>SyL6e| z>sFfu41z9OwYL#$voP`D!kpFrB|&pH0oQpH-2no0L8n|tvv5;2)Q%QG@DyE4cU zJYcjOUN)*v>odfA58601knCkw9B3oEobOz8XRl@2*L;jK&e5hzpFu+({y>Q%_`N>A z(TkiBG*jsb{FFjwCK8dG`F<>VHS;Sa$&6;ImbDR(%0)0XC4n$bzS!-?HUW5^#tA_Y z5Q-E1!jcI_e(ob@Ur&YEw+VYA08F9&wJ$S&-Wlq?+$gG=?SzmvAp&X$@GZ=)P~WqH zcRNi+pts86>iWvH<nkhC!hE^pa*4H~&8wrzY(Fkr6FL270Y#)r3_&;Ij>q-;g z)(_9PV=?|^X$BF7Xf|7Q#hqaDDOgCpKE=Q4&?h~!pqr@ZVJg|jQV6j0t|ixm>0Nkr zXS4togASeiv!?JnCpZeeBf1dN-_KsMN(0=by>#Y{N)b`=_sNc$yyDTU6hn118I8;u zH=61U&dw%r`#6LHvW2uwQN=RnS^L9@KGpwPh&tLE>@#`#20&iwnPbH(@9%wrt)ranU5|2Z79&l?A-Sz5$Gkh08E1)l{yblH)UqOyP zQN0r+y$iEH?e+|X^(WS!jUA1D^y8B2fe4;Y$*6AJl0iU-K-^MCOV5F{$*rx)Hqlz+ zeUibU;nM8*C?FJI*8$Idc+jf|x@s>(FbVByp|3A4mo9H4PduFvQcX7xz?N0S9EP8K zO-%{P((KwZc{YbHmu6o%*2WU5*<4y#Sm&bTjpur5qdkfG=~b+;)rG}t8w!?e_p{!s z@=|54bTtbSHNkZTo72-+KQ?CL>(qI5;d*5qELSPbm)3}S|Hk#&R4lG9JYOkulfWD= zE8WoL4$ z(VX$?hm4_lF|aw8Ui=!0P(um^=!(+8W$H)<1dzp_wIF1_)`> zsqWH@$q*4Bp^ZWJ7x8A%c&0Jo5IZ)s*lJ(7y&kxhF_RFCVV5C4gr6>M=cZQHri@il ztJzHFc@E8R%BQ|D=@63vr)*qPUMt~2S{_UJ^(a^1A7|m?T}y(n04%*X7}oC)6p=gU zL{!(9NiZ?e+AD#?H7C=EH@JBAN5#Rz%%WXKq+-v9M9PWp?Mb~@@79VRQM6gRH3F<4 zcO5m4_>0~~EQutmO>`13V#gpH6-+wPb5Bs6++E5R``wH5S%W#s5kg>8Z`@#w&1(W} zUtFlC(?RAYKNU*TJSW^~zL-hJt|;$Czl1Oxr#6JMmrO}Eg^#OC=jTcZPE3Av zv!8;He*l$Z=G8pAyjfan5zymK@}Z}brInS1d9YH>&Cd8|E>`Q_Dc0WJqjGj_)`!kz zAa9BoU?swYrcukD=TlROiWQIqc8FCzI!E%%4tNgGge17IOgyvEt(Lj)-F#a(^d(^q z2E}eT6;B-ONbFblJhQMQ;AuJBRrb*1bQS9aMHlx&aW5+lCt>1)r%10e$DfYd86Gij z)HfJ}>d7YHSO7=LEKaT%N=FgVF&so4l-cy9Ba0Vuso&*fF?wAx{j%P3sHrmbT=fKO z#Gr$-Gjqi!MlhXNND2=MAR9@}(=iM=Roo7siWoaBSI`apJtYCoAqC^X-)u*v_L(e; z$R@c%r~O+m|2sWC5{YtdXQuQwmxq{Qaz?+0zh$N;L3@m&oOsw_Q?p-gehR;ST^WW8 zG9K;WqFZ$0xrq=ewV18N8ql){OzlRtQbE7P$pwf<0Tj@!cB6S~*&&#roAI?1BOaDs z;ov<;x`M!WEC74L{|6jBQP_4x3De=2HnGC097a)absbB&P5vm3uX z$QCT@{0>j67M@)t6zfcZ>h*3yP5zdGtB(?Utjljdgfq>78^tb*A?p>PY@2>40-E

6Xe=xLn?@PRYI-*mepG$>R4&SVDbm#raU~gvndZV872g~;s zH9qf`Mv^dN{ry&SHy`Ew^iEOTt`fq(LLXO|kKz5B?dxCvTzKR-#fkg!+Puaa!{*~` zUwgfy+yP3|&b^>UtElL7f*H+IgufQ=`rBXLx-Ak*FZOiapd^EfDz)#?MqKeYr%5`e z2`jQgKLp`fxn9Un3mTPQNZ_#E1&Rfc*_sN%HSSo8pklIcnN%W1-zNFmQ`!-2%609i zna_c)AMk4o1Y6o)4Vw$~$uEU)xa{3++CjR?VT)36?`ZYg_LeSjh;y9P@B3$g{kaD8 zuNGD)qsV~qVuZMJ_sNNuPQ*MPP26q59yfq@Z(F;wX>*j7_Axs=zH#Y$&r}?LS&AxX;E9u)vzm4?UN$3v>-$D9L((fR>MnX?j_?@KR zMfxt%cawfM>GzPnKthZve3A5fNxzTu`$>O*^an}bOZr2kKTP^Q(jOuHwzOpC$b{(vOk;I}+OJ!jF^w0_iW3 zeuDHR(od5966r6K{tD^8C;b%Zuaf>6>3<;okEH*J^g8LMNq?R6H%Nbz^gomS7U^%3 zeungSNPm~~_elQ>>1RoQpY#t%KS%m`(l3zyA?X)MzeM^+r2m!lk4e8w`X{7+O8RG{ ze@^-rq<=~JSEOINd-tx=zs-H;=YRGGh;0I$N#PoFV~)SNa>VIU|GpWv=XPw52#y84 zafj*mE--x%@RCE^jgi94)a2PIoy+2mIJuX|sl((*OqHl@?6Gc(tW^&rZ^*8g0$-$*4%aZgvj472VX1u&-iFr^ZJ|6>gH7Ca|{?xj21+xTz{5 z6{U{*#`49{(X!v;gUVSa2BSVGg!2hEHahz}*a5X=_VMEyq(A7PIz9(}&xm_==;j?a z));T?!({|^eWr1ap=m$c8$CnQX`$nz!G+8`nV%;BxL?wTq|_denL$%M+IiAWy7|B=PLJ#y+1 z!XkI;H{{-AqLMCds$~WxZktFZl1-R%t{*FNdo-a_%LMsExs@ulB-gsQ zVdKfNtZ4pqp{dPkeWo$HGj@3IA1l1w2+X(gSIF~k^Y=gS_gDG*!I47YLnH4f%u4?9!tj4DQ&;6FORW0}1G>iG)QitV!14jAZ4!7BJ*Oz6#qxnNsm@37B9y#Rp zWVv*eX1Or>RM4x@@l@6JRMb;gW^uRocko{6%S1IzL5#s6#8E0XJtcgU#dLa$IoD*4 zVy8z6hEY+lrHA^0ELDH37s(ofHu!)2_Ht|{sekodrS*W)p<`)#)DSvb zS)wjogJv7m%T-?3Zf|m*PxHof+7)gY)%i7Q4fl_EQH;y$@jyMbyuuv9&)mJaq0s-z!$v(4fsT6x!qytnDYY)XsS$0sP#CE zz{w@tpj~BV^JQHRmU7l2?%6KtDzAKQQs!ZU?R8q`g)hgCr^!}FCCdFJnf7qzqblrM= zvDIFOpSX6ga8$49U^|G>4Df(7(BU!e3~r2{)xlAogzIJTyD4Ig2`vV*kZTzI$Bn|s zBCNZ@>Gy`Z-$2Y=K=@ulfM4Qo1#zK_B1M0%kyk;0kfLJ^QCKlu62$JPvXXcm1&jA3 zQYj=vXmP>AZy%KCATea0zY>@gGv@tC(kDo`n#z@5QlMojtQ&1n-&}dl`|HBJM1?8-XFgb@-71Jk>zRH^Ur(LrIx6KdR<2Vn8~^i zPTB(AR%j!zz&4276eBRpP7rM^R;o2S>S9u42(l*?f`T^aZ~FX-tZHP|kutMLXdGg& z>(o1uP757u(=mj4WYsp>Y>vza1Vg%Yb@Rr44jc&!(HSx(DK{>QV z0Cp5rMw&xZE0FWJ!0xXy$~B1C^MWn&2i_sqJEotB3pQ)wNE&O`gO~ zqm$P=HECq3+Y3jyQX}DoNj9(D?=FmN7#`3rmOV_m`(^gItXQ(y`F<8wah$MfjMY_a z8@g|(1oI?|-vm}FSr)|9M7xLr=E<6;{4;#(w|I!n(zVlW$%_ov2JM$%&mv1j*5=xs#RfOwwgp{*GtZ9`Bv6^2R!J{bVju@y zyfTWoJHpotPSfcM^EZCnB%MKWMB5yjAgY8KUgmDXlNe+iiBEMg`6(G?bA}bPtG)68N+aMOvawJvyIIRKhw1n-3DJVl+KEJ~U{= zXiCLg<=0mz_t+fXj(==Qh+`i+$vplsy~Ull_mj1q64-nJ9=mXm5v5}v8!FE~MVFO( z+dLI4#D6T)^BD2P-8bUX-nUb2(eTI4@TSlBl2)Fbmmc~!_3h0+&EC!_$Fc%x-RaXH z!+Vk3V{-<@MI%4&{f|TJlUV&IaIE{+>wZQ;(5KiayWx4?<2Y^icr4lbn8(;U1QhWp z!|rL@hDQsrz_7>0ZpCrOw_zwyTDbCHNaeZ5emqC-XO;76ys0J(y6>@+P}vjvmVY}! za;{AOV_kWZtD*0)si8Nq zzMb;5*~|I2*?zf`S6(L9cDiOcEYbToJGK=X7!^)+1%!Kb<{IX!9uK+YB^Da`IKA$L zw|hL9M^Q)XbE5Dl6x+0QZbl_Ary=IZD2ftTsNvbrg2959o(u!E0&(OL*-n;9_06^-ISkc6lLB>)UiDoWEyRx2+w524VGo@ z-Vmkwl$3m(-Np{8KItf!fPi`}h(NN5za}@SRNHIq7FNQ2PJrB+F#(x_9Xfg-jw0A& zv)}}nRCFH2l)Ug8nOew|K^ljP)>k&eyFrBm!wt@x4d-LyeBr1X^+}P%S!Zyo8&~UH zqDSF8S;u&Rax0yFq0bEDp5Q=sxLn@OW5MdE?{rZzBCJkT25KFKktOJR9z>3dni#Y7 zS}`oBsFz|GA!1a;DASuSUiXU}*7@Rw_$WWba~g>1`kL$(HzW@n8eZ83oM?FQY2`*%ZqmFj#LI4#&9EMJW{1KBe@ zc7?j^VRpx!I8yAcwVOJi&6yHhPeVwDhzeCOn?y#}yMFOl3=$E-Y$MnT40C8I(&@HS z-0I~usl=YtxA-cjK*hdUJa$`}DvCP0)19MG0ccDnv|=_u&6IFK+u{Gn*rO->QjHGj+uu09r>~K9y8d%dKn+;Xc@xd z-VJ<)c1xP2)3e&soOhMPr)QFu49h|r5Id#s@`pN6WWeM5Sri>dq5tz_A+63PqUXQS z=ppV>Yo2=+PvOR$Vf+RU4PK#|uJi7zHhU_eT3%0J9%O*x0`F%OTI=z1PPwtMRBdDuVs0}u1U+~7mWB%#ke52H8} z$20IS_o61qhvGa=Hb#9*AMV>FeaAdJ*eAGH@3ZX9V0Z0#o>prdm~6qh_j3=$x#+}8 z_B4GMZg}l!HIpue$VS;iHQFP%Xq-JfVXx?tW8Txfn@S}^A4aKS_(R+GYBS}~(rQz2 zW$43uReQcTSnZ%3ldG0>$%BC{wxp1t~sZc)}ftg13ay?>-&NJ>UD!zSs`WjC#+KV93C{!F)eH0Nd- zn|w~HM~RuiULJN*4yt2;G|P1yS+?6CtOG)~>Z}Ju(J!I1^p|zD_n0&fd*D`M?#XkP z2Q!|f>xvub=v6xewa|q3uZi{OPEVIxhq4WJ7R=VYAwvg|fNDrVx)V_cp+wK*Fo_1- zb%43&*Q1V|bCh;2avaX3CVp7=I|lA|t6rrS@ya|XpW<#f@n;wza9YsLQ?9D}AQWCs z4KuYCEh_|4mh9x$Ca#@NFUph^CPEngkSX{-g1K;VdUjGl&#G>b30LVHaG|3C$Tlkq z(=hlP6wDfEipo`wek~WK2JEqOBY;ulrXy$})5w|Eqdqj+N$WNep*i~n&%{xS@-o;~ zW#;lRy{w$O49`_ZdeWrLUG|C8h<#C>*?#R>C< z1>&+icd|}+{iAYl@Q)gGfhMTWk6+w4V=fm*pYUL?IB3~L6Wr9-3lYMm3c@T0F2?&? zPoSL7IKn=@?i_Ia}68IebvbC7aEN{5A2+JHvNHvT8}DlP7xFnn+glP$e|q-nZUz!Ie+N ztQ@zP+Qh}ytf3r>WUZZ7Ysc{qD#1GBCSo+1J}cP<+~S9Nu~D64;HYxyZ5f?9r=K{Z ztn+Snww#GGqodz)0=L|Nwji9;cErFs*=IO8% z+PJYcZzdvh<;=*}#UqJ;lDM!;Za%lPW|u_HOqLcnVlsU+d3|B+*>ETq*WhqCSGN$P zzl`}0Pn_2eKm59BdnFf(?hUWQ2>gXW*FB3OAE6wtGgl;@#*LBq973GiPWguZ3-8tC zjH~Dk)D5%-nwpgmFz|x0vWG`HkZk+{Q;>4EyyixXTwY3>aXpQM?j~*loX~Ygf|R^v zPKjxd*d&>~aOsl32@lp?i}uZVUsOSI{*tz4kGMKOmxpZCVTSHcJ3N3m(T=Ss-h(v* z6ziO|-Z5h1%t(9_+y^{_dSRCP>UEu;#k5$P!;SN$jY@fQeObEWi)tO%fuKR0xlKkY zis)X@+dHTX4h%E}dbcz9esXA~d<_nuij$m?#cIl3n0};)7id^%+l>~FGy+5Fl$gay z39HnzgY`}>KuWqI%xRe!tGBgp>xp94 zbo#^yAhbhLS0!2#_|Po6rR7p}F~J2y%G3NS)BtzaQ(ha$?shPRp^o~C9^c;(T_>GJ z?MF5G$4(X^*_5YsUhERq1WN{bWXLlkbvpgjUl^(oQEXPQUxTAsXJ)L{SUCL6zcWak zXGN9X=##IaSHok?LbZ9fak zK)I%RD>4+6*W#$6WENn|7>mH77>vu}YeiU^ffBa-X^Ekg*t)z?5vD&aGLsDUB(>SA zC)2(%VTQ9lIo{N0{9|R$rMoOlLl0WjKm(^`W3>6CdB`D0m|%~4uj=xNxEQOd1 z{9pZez#PX5I&5%`e-}7XFo{o_|GLDl=tV1UwQb(@xB%{T zmoMiR%*HzOOUD_!#W{4o>XR$5DP28ON@T;|6_KB!ap{ zwYb4|#c8-jlF#oBHOp^U9(S9xt?@6|;Ro-jyo;~WqgBg`qtudzoB(D`e%a-0ux zHlu2;d$G9q;+CkaTipZ z=HFY#8moC^{)V@$Cc%o=IY*uH!`^20&k-3SgNKs! zFTziMPrLS31`CSVpjJIji`T93#oFZ^IXsR;)}mV9N+CA3obQLmJ5nf&eoIhTO6!*s zunmKNCG#{wA)9I$IwHPO@8gW_*xMo>c^NrRV+^MlLCfO@$MeIfNxnlvEFgO9w0f|@ zlzgNFsK;weuW~PwzZbiZ$E;C&&2=IFI7+SdSm>NNyVQ^6Af|m1=Iq&C95)L4>pqE` z|C}xcuM}9{)agQcAuquZZnT!>Ikf&o5eT7#X{$1&g)tsyd@*! z=Swo$>pv;m_r+9dfg`s&FXk}{x&vyIYSkUdFQ>g>SZcj_=B9JrTWEDHssWnT-UGi< zIVscvI-YV~9Vk^-JSDREqLk^QtMTxdS>K7fAkPa0Rf6RvirbC4?jK4A6XFX7T~Nx3 zMCl~cyKp#P9u7^eAA`-!?CxPzw_WnNthfgsvPH>9nN9|dXK(^`gX1Jb7;DNw#7yWc zi*6nWOUCKaDmQBUsSXS}W&rcO`Wyo@v{vhz@#YJWH8zLwKK$`YC-X2{kdva&XGg%O_`PEi+75egsikpQ1)|}psVKdl5Vg6-o5n{ zwAgz#y7wRwiv07FZdl+vua0^wU0%V#yvgmwrc*`3<%e6J#=%VBmaSjo21B=!S)MO& zL~FScyBjGgKu{0&f}n0gtIt`CP9mw6;~6N^*h)CX8-Hc4I;fK8Cj20W4sDs4r+uf4 zQ`*y?SbIlMBUlva5Gkctv)yKw0cw+hPG)Vl&F1#s)P-Ds+%n_*Uqna8BP`C_Y@!9f zg>FfwF}P@lqxf=(ms5W{zrk>1Au&IE*hTS?x-HuM(1{d)rDxbI*?L?uL(jCYN9Sha zfZO115ZwfQjGgrWuUH5{Cd;u;dim9(VUa4jjIzADQ75t}#+>ufcr@0>04re4UQ6|I zAOO{Y!VDDuNSITPitI+w@x(W>4!lFCtXX+O#xX?aKApL8h{nH6{>t`3ROHz&fJR%{ zAMwK!vAMH9v8r&AKix947Qcs(dB4S$P&bK~TazJhxhQD~-Hw_nonlWlkv+s=JXttG zRm7=!qZMvc8BSTkxzM0;+dL}m)mExUE9DJ^Hnhh7@AlpTI;-P*8=VLtXmBZ(;1WXc z;K6x;ge16YAh-m#QnWxRRw(XLC{P@V6=|^oMT!-QwzRZJp>FiH3moIts#!civdQoCi5;4 zev;j-IfIg|p}eB{NHI(iS)CXs(CKe<*Je#x{}mSxBK#|^HG54N_rJfpdy?7@H5a)I zg`t>^=jcHv@zCKK)_vAwYD~1g4h`B5)f&2&HZ+m;poX@jS3J@(A?saN%?8r>5ZUA zGei05xc?BrYON7g1FXP}x|&kBTMAQ5&&sK%KD{)(?!5u6%p(HcCqV0_bSHJ#prNJ~ zC%87nQu(In*v)#iSqV*B*Baz#XN(>jefpsSYb@d>mI1B_?%P|QS9yAj+dB8gDUa54 z$~<|QoST&U869WI+MHlnSds4+2T&K(uOGRBFoAs->w!qx`Am0d^$XyzN!nhd#%vnJ z%ZtU0TbEgqbHeery}h_GfvdQnQ?(0c<)Y~E^YQimFo}Jm`QqFuLu_Zs=g#7KrFhN2efHxHbMqgAi&x zK+oF*d2fQff5KW(!6r%^aD{@Y9ao!%GaAfj=1|ufduZo6ZLla88Cj)F*>VxREl%Dc z4A+_Z61@w9Z^-CP_(MYr;u$j^wu3ZG92%pa`z#p2M`CfeZk?4+m(#STb5mbz{mxD6 z^MSffqt8TnW8Uj*-Nd4;JTRGFuvmxkmezu}J`Ww(t5-i7>1`KfKp8l^dV_TLK&9{$ z7}d%+xCMNmK6MVxFoKbRpYn#+Xu0(EL*LeUD%MFM&g(NOIhjD^O}oso1BNmQHILS+ z$RVNDLTTeSf|RD?6;M-X#VV1u+Ur{q!v@f9n&f0YM2-TIw~~_*VS9bO>9!yZA=dqI z9(#I2Wi>sFKhCD2-oq_@|1$l1CwHeY$dUWe8@Nc;7us)$;TAfa;P?(KrQCWngW^GF zk6^q^OXWmE5&}|$kd|(>HK!LJ^}}s6&I5WCRd?DWa5tmUE@v@Qvyoym$#G6y(N#O5 zJGn{*OCLbps5QBF)Sw7c!(k4L4Cr4bG0~a`QPZ)`O|~b^$<#jR_6jAZzJ4qMCtFxb zypaH}n50)!$26-~pPu0er9M*kOnj_Cc`}~w*61^&Y2`B_l-^J>jG8K{JGXkY5$miw zdme0+w?6j3y2)kERHtXp(`w(6dQdt5kf12-_OzV7^5f!EbDGmkz?|EZ)_HWswOnrd zRf$wdaUa#?$I$>~YJ^nFaf|wIZL#HI+I=yNNaS7PF?;l)5j0Hcx@JYA-uM50J{+*x z42C1KSBJ}k8wRHYH`!?p)Vn{Pr7uoT-X>X32k;XBrLbs1FOMbrcufT_M1T%+4?d*7 z1i$(K_}o)>#i(GNb3~(w-9pg_>GAyD1kGcGe!nKxoiX5G3?VNQEtt;48IVl3`Y_k% z`mSC8uou&;B{h3Jp4Xvh8Oq)#-PO9W?~Y{O&2q(}nvDm9H6$-ZrCfje*YY0ioZug4 z!OijtEGov(%l@tyt{Yt(sbX##=<(DJg4!z?oJrCFn7j-)oFI+dG+h z6MA4>2jg`g>>*HBQ>g-8-WFOnu4P18$Dw13sjK7#Lrga@g4&Yhx6)!V{8pM*briiP z>#U%1+=*Bnq;uFCJy}9ssl5p49o@a=7(ttMbea8YYNZueK8j&;BFEL>x9T%7w$4^a>Ps9Eg^2OyLrlmm!`EHGV)>Fi^CzHAq^o{PVZdT7( zyK`$g+LNA=!?0r?5!5;5SzY2~$;l_MZh*ZpR^v~bK=W8Sqo+H*(4q-{(TlvC46B8t zbYvj$-0`of{Ir5ySK)=5ArF9jK!>h7E;I+qPN^6^6D{;B;;;9vJ57%^oQ11>03G4 z6Ku~C(96@RYh-A>G7UoM_^Qqc6)T3;t=mKo>FgFn@O%1b4agc3>RQog2_Iua1MEDe zZ{&k_PsB+>G;^h`>U!Q{uSp93ssRdxR@|_`%3g)BTy0ZO#wSNf@ct>Iab<9Q#kV6v z>GoT5x{+9qZn-t58#}n6hFf>mF&Vh+){Aaw;dZ5clgzr=7fQMw^bemn+QT}mKW`|G zDaTDJpjw#DaX`2+iQ|88JIXo$$Y!I3FM7J}Uq|_o--M>4%g!}Bp#$sa9o6(YjZs(% zpb5;srzH%e*1A?&sqdn#b$D2iH|O99RoWs&Zz&$qmnO@@d&939$TKSp-82&k<=2Vp z6+$cv5Fo!KynAhfNW1lF^U9*@L^EsAj~oQ@Lr{kYB=#CeJ9sGR0B+cfot20z)c^f^ zn6k14w^ryR&H8jumg`24Rcon0tYBh5mu3;%J5yaqWTFm0GfM9P)hZjv{-;=7ypkeeRAUR5S>nC-u zy#`(OnoR@hyRDON;rY|M|WQZA}QkP4&;B4sE>BtMm2 z<)XXy_D@DD(9Q+RkxCgUz=~A6U%&qlLbjv~>26(Pz2(WC`r5|>*_9hLo*e4B{5oM? z%d{$5U1W*%kn+HOs6kYMbdQl=0n;v#_8BG)z$LGlPnu3ZA%sB=i9TNri|(MQ_ZPod+OMmij5z`qih&Vsi3 ze(vQ{lK-Rr@DEn`sL9cpO==f?uA$FcG|fBfPeost_hHJV;kPPYz%sAKz?mMfmtrz8ET_j}xsj{46pvc3WN}) zs&rKp5MBuMph>enxyF`qA6DXoKv7{`8sz z;@vY)sSdl5-k0i(X?ud=YQcYY&KT%WOr%rc&wVQvUhT zD-dYWu3Z4V_Te4EB|B#>P%2{(?c`lZw$NwTVtVBRb?-T;LtB!LUI(#^Y@u|WSWaCC zEuLOop;Q}6-$$#+E=u3F)ztA(euS*0S58oVG+IZmWuWwqSWhR2Q+nrZR4O~AGiejy zQ~osCLgAFo9y?0>MEdU;C6^1Vv^Mf^qg)9WrM-+wzmc|iOpk5j%7?xIsl{YrLs zJwvaEAe?b$seH)p2j}Q|viIa?R4!y^-b-X3*}3uxz1D&39B_m3fbc$|cRTz|>7M?C z@{#!WJ*E0W*KPQT@aV#%Un$>Hleg;Ur)H5|MN|2yXiEReAV2jXm2W?K3}Y(U(LSA@ z8b;;XExn%_OE@btQaI&vbS6LAX+*D&p!eloBmVdteySnaQ#Y5NszUtjU-MJ(RF8J$ z@l%_~u9ErvR45jsgLBX?U8sMEihumo!r+`47P>;9j%yMSm`w#KsKeC68Hcj|LErLH zK2jE`_I0gg{?0Av#H55`^=tPAqh?{xio>#v_>i!8BtLyN~Ns#MQ4zu)Xa>u#qmJgWD&yl;H{ zTD7c4$45_lw72-Pw|@S((XtmGUmW&($#nIuuNpn+beYH*r?#*9;m_aG7oM;vU7Pn$ zmG9ba&E-tT?}cx#7n!=x_;1VK-Fu8l3^{zQ7=Z*7$y-8mH8&9{f&?< zdmBD}(Bbuu!~QOPE1_@1{Nz`kADk1BE8^XKySqO6Xe&Jxp#J$MAVpTKzqaw4qm)IJ zD3o$vb*5(^lgrS1jr%1}p8XkRQTl1mryQPiXOKYp2FPmq5qrH&}vV^>Ov)Q49ZFPEFI+N*gT?VS`8Y4%8~wDOxhEn znWFEHTRmdV&C1;m7O&rJ=cn5a{-WwGd#(1VRhL)Zy8iXUNtG|$&31KZlMHRcm!-}y zBk_F1oBMtk8@@5mdtWrl`$>4e`=_!$dOR}MnccIp-u0bMjvrU(>YOQC_k0<8ZBMDI zVb8VY5k+T6F;rmfl}{KBWx6^6dHmn*_H`qk?bdJ zn+?oUKifxzUgT>qW?=VXv3(j2+k9h3o}?=crnmq6;m8qBmiHXqYjN&kFEZ@OSvXUc zHFV?U*z|yjt@;$1lT<6FaeRq{kNgMr9DcppizR>c4)mWlseH9Rm;QR^&_CtJ{C;-) z#}^|q&wIK5amzBTs@LnbGIfRgl@7N*{A|jBY3q&;o{)RC?@FGmk2|&<_2<@4N4A|( zxM1+LQ$uoBJ{-4+UT7WrN93%p>#vxT>rRIKZ*HI1uQo) zot0Aue3$j7ziv(|b7b^ye|^)r)A&Dk?3?%E+sH22N^L4Ow&>o9sUL(_xY1?f z=FCIFZ#7-j@!XR9+tdBlY4(#+A!Wm}A4(dX{l{<4Z|$(+#HWu7Zs@tC^p@|Jd^EJ< zfzTU^D_8$y`^xfLhxeV;q;HjR0bTmMcKz|tFP8U-{Y-6tej;{jc>N`N1|0t4Y*LQs z;ZZRMJGR~Od55uYygL5Qxmm5=-*cl;;*NS5PG{`f{I}7GoAy?HelNr62RS$Xu;*Hz zgNMI@@a~2mzHBmU{gRoLSIxOJvRB%z8NPVB;q&Cv6L$TaFf!l0pBtxLx$0=1A4rKRO_Hs|pSJESux^%dy3`qP|Nvqhi3Jri1R!TK@9u&)<18WnG!1 zHB0UsOf&W9qKjkx{%P9vW(C&LZ@$}Oh75YXanhf^hCHjWd-t*_-$&)ok@LtO&#u%u z@=E>v>bIq>Lu!^e^=ZLZ*9+7d{p!iCA))my)?1UabM-%-o>`l-^Z1u9|4d!vhn8>r zS%2j02KCnD=@HWZMer{@vpsAa`^SSGrACKsxR5rl|I;j&^JTAkG*9<)X9tyjQ1bcS z317tr9jbcZ`_l*V&6vBU$g&Tn%ni7GZ`q#x#akY&c>euW_wN+Xzp#AHwFL*Hd-!F! zJN@%k+wkAbjFI#T9 zS@}lPkhyg(Eibp^df9L4fA!kk-qWHQpWS||LdKalMtqfVfAI!OJ1jU>d4Ha;KXN~r z@Nn^?BQevvKUn(|TbA0(MUo4#S-txclT>9;Ud1cqmnYA@!S+R#3_N86F zDZKEtkoEW4?ti`OgN`TGj+{T?gJwBb{CH^0iV=tZ8GC1W_D@fp-#b4r-G{9!hwLp= zspF6eyL|cMPVT+BXzurye>#(8M*WLZe1|VA%jz4S)VNNr4QIYQmLXN8zH{z zrV~+x+UkwU*^3%i>7v2u4 zlDqkksgM3zT(;fCz_&l`cR!(Vw!PzC>)EpO=Q}=ZIV-8?)hf4NmY$Sh{rz?HK zFO(U5`V@5tM|b3y8t>og-2*R9^b2lX??{$wPiLp^nf2?eeJkyp^s+_U0p(3XuW>&%!^HR?pIqN%>URIzmK^lyGJ z<7C9Sq%Uuts<7bY+=AVzrT-;v<*bi$1pU~z^_0H@TO5Bn`AqO1e%mhZ-g~}OV6@a1=z&KJCSJSOiqiiV|#Y~Ugq?+ zR|C6WxE$Fv!^WC>>Q8GF_g=%2*(Ud^)2`f|5rI4Uv^yB?TbQL>{+5|q7j5;V=FK8o zHYVSjx9w^Ew8yT-RPtS!a4g?1wSKKKYt^f`%2hrYnLMOXr!oE0|Mlha*%^A?cxUOf zn7Z>H*UGtL-R3WT?m4Q}n3;Jll_}c4Rq2^&yR<5vYF33O%}N|k(`4)UHqEQ8=zMN+ zK&ja0xr+WcwfGxN3aop5)vNgX<-6T(lk@ZZcPHMSaj*TPqCo=!I*mJ4DSxA4jjG+8 zcJfSYyIz;qZRvC6ny+u^QrCLje*9=`NQw4MhUXo#GVbQ6)kA9#c=3W~&^VHSg!!$4wc#XiJ^>YFFFl%S*p#n9#Av?eJ3v=d^t5 zdB#coCZFi{)$>y~DZS;x(vJ) zkz-V@TIcfZxY6=L((ga)ytg(gvTB+%8LJNN@+@v?r}Qg}*I0hMP?qS#u(-BAoes^u z;Yn1Zi?jL{|8d)iKjsD&>YMz_sK}t?6UCYj%Q`;jt$BQ$7C zv8e&Q_tfk>t=W5Lt0%4PF=>3ITt(u(sM9FV$#fGA?%vw&WTj!{a;zM4t3*h#Z|+Qe z`*HtG^J}MXy0O~nw*Dt-kGa+2@9J|G)%);eF&d@+?QLbaG-u^r3L#%tA%=S#w>&S_ zxLgtKiN&Nn9+_?OuM1}>H9esW}_K`yAV=le@dj3j+ldV$qR|yvXmGp zD}jTtnC3z5)ch~1L|l_pG>K9w75(c-*1rSiT`djHM8EiE{ZN2u<-%gUc- z%JhS>QfzIoKb9)-Jv~kGX$tSxNI{1P!RkA%Gtqt_tV0TeRRdaNP|DWfqF~j57B(Cm z$|6{Oi4PMG7X_=;LI?0*wT5|ZJestSZWkxY)**v~Rie0-R#r$CnVvoj2Wn}s>WmMg zLp2XpABk&mQLxHDixW;f7!a(s344)O!D^zgmsUPVS4_l1VpDPeJXoC*@o062bhSnL zu-uT+Hq_r>)kE;2KBv@SW*4mTi2S3K9nuXGI$CWZ-Dg5aD?g;Wiy}37MXNxhYr{IF z%bZqd{-wioIAvOB1?XQoTFoKdWahQ;Xk($k`6dyX^|3jYrH={szi@@tr_OeVQ7DiDNR;P zwDrc+@@*-AUaO1(1BxGUHQ`kcOG-rt-=i*BQV?B-TIA;+L@`sV80JFCed?^{@)unG z%!OJ81b?!t3H5@u1TIGc7wVZ66I`fa;PN+I$QPgbLURQOt^i>d`jl9DEun=+cN>Tc zH4*3ml!r}e7`7#Fq4t3*z;Geged?v=3KU#{!mdE(LR|$qdaovUYmt^x(Sv`epH>*S zP&2_5Xt+?OKJ|;{N+q~b39eMc6{Ap(ftQLf;uLDICBZJ#T}!gd%aT%4exMGcexTO) zl>cz6exNj+`homztn4yFj>Id}bD$v2O%!UlC4n#0NI~@Qqg`e}#x~SRpUSAYQVXus z%oU~)Qgc2QG!nQ983|m4jbz(~d_@0m)kV~CpUR@Sf|;v`z9v}M70mfq)P#Wx{wM4T z=K4|GNZ=|#61aj57g~@{<F8ju^=#>waC8&*V33(V{!oXEVbEP$07*8Cobb>3L;7Z5k6{+#) z_6^lAM*>$_6Xv!no#8^?;!`EHUGNkfyWlf5rlo7klJvwCPY>nV66`8(Byd$Q61Xao zgz`#nxX^R?RD|ZrAh_VAIb0c-tCGgcKz6m@+ncBx8MtmlnJ{ow(Oek}7g~=`C1|dU zf-56)+3hPMb5+%NbnBGts%9kE1^*Mw8L9O-ePTw#g&x%53Sln0&clat+HweU)zEk$ z%vIA!;HqULH&=+^LjUY=!H06nE0f5>OvKehMQglF%;iYns%^sDT$v0PdJ>=Nqw_Gc z;DQhBlvif9tB%IYOkA-vGFrKonaiu5k-%lwjm(A%UkO&33mC61g^#;p&n*2To{FXYKi8`%62u;*JKstm6hy@Aw(-3S;?*#`e#ev ziZzlu53?FBjB!4-S94_(d6-S)VK&agW*RRWamCZPWpQQWJd87vn=6~)!U*bcWfxr8 z1y^?BiY0stJv(zH7zyKLb0dMP1xd)m?1l?ttxp}$cI6OUIYb`j;5=-p@p5n;wlWg9 zS{uo2R}RC4k=&;)Xs(=sE2rSf$y{wTUQXt6ByhDgVc@cTshoxjeuBf5OK|04F57R* z#d+9HCi3t#wyQJ6Ji^z(u4YvKEEIPMy=E+d|Kn44bP44V=y`-Cc^JKmPDdWj zHAjLaT}>Fc?9nlg;evPNQ_nP4Ucr@@x$F@uFLQO%czKztyOF@v!${ytBnh=Vui=8X zMqZ)j$|tz;3A^$!S5J+XkGXmo30z4=a@&>9aKXcKxbh3G{KBsM%+*`tToVdVjc7)D?yMf90FR6|PXXq+PP3?A zXlU%`KZsIb{d2zAn*a3K$y|e#f>7cKR>`U8!^|X6%E78AoLi%V=bCah2>&&h)@=~a zo*}}EO*sq2h@CPXywhM+0Zy&C7Cvgqc<@w%)%HL{vpGtzPV&O%3|6<<4m%z^&y;Bi zXPv|=?GZ16b#lc6Ehc69;1j0gfM*!2(ge|m$v=2^!73A6BVz}AykIp)#Dk}o5)Wf~ zN*z47l;u&`BObiDl=0xxrNo1mmeMx(YAJQ_*iz!b>q;39zE?^eJg{K(5JLm!3ubGf z^xbJMp`yKnDz_&T%I#$!#YcY`%58Iyk>D{5HWJ#V?YV}UwuyS}aD@r3Fy=z>06mPk zhLD7wI*hrR>Yh4G_^M$B9WBJC{?I*IK}Jv3cm)M|K}H{H!Y~dv5?cQ-69!9cAEBV( zLd$cw3NhDkeN7?3RfxD^=+&T>U4^)pv2(2u_cS9-n47DR;X;e1`Sb{DK3!PkT4BLe zn7Kw#eDsNhO^;TXc$%uwny0YHzruzGy@XE%X`Uj?Ge%!iMDP@0p0OqjJ*RC`5w>ZZ z33J<2#Biba@u{?$t0;4g*VhykTt&I8UZ*hFRMgm1lzAqYYrq4q-il?<+0mmpJjF!b z6%#zg*rqo$UNKQl#h7cN33J<2%-DpUlIHB%rs9IDxZo7p7|Cr{ zal?fk*x@R{Ty|YAA-GDgT~jq)31L?WwriRRbK6zIaG_^+xJnAUa9_ch1D0gF-qd&{ zgaC z%82|c!#wEkfmeojV$?fELVvNqNZ?v%Byc5?1gjFXC9_)dR1h{*Fg)@v0#tgD^xT*@ar6&N`j}7;Hkts>oiX#!&8ZQ)@z&-T z$?(8eba*NYp2~u!GV^TEc$JxFqmfWX?-|K$Q)R;iAJnHB>oSUBt|t1LC{adH%(aQa zP}`!I%dTxvqGX~BI_d-+La5QJ2=pofy$Yjm*639PdKH0Q#h}A4_NjIny{gEkssg<# zqrb1ws|xh00==q1hlfpT2O7PaK(8jyt1ppu_9;sct&$H3WJMfnI~rw`uem0=@pI# zc9VoO)M75o+53fH&fbsKiZC}%(!cI`x}{6v7)cZZawpfnB)*d$O~@(dR<%8Jbyz3o z*mXVP)$`ER_s}))&^2V8yzAV^Bc9Jg*O+y3E{=X7SS1A0hnYJ!Wu2Vw$9U*sJ#@`H zba5WKcn@8IhpxGY4)e2=<O6d(P0v}pO!qUA@M7Kxhdpw|}t3iiP` zEwVPF@1^)?XSEp}ZM`_CFPu+jj5mwX@Jaw37zs9S>JRcef zBj5oexqF#9#wN5nhYR~7oO?^yAK}SF$VlKiY$P{VUBiXe>{Fw)UG)T4 zJ?64K73{@`p^~xkiJpEV=_4b7>!^{yb&MqBbUnj`Uc#p)YA$+6*=1LKVOM?TIvHj>+}`i2X=58cPoTn(7(6Mans!PS7dPEr_B+km-H6R^LesXAq@aq~1V zJm}GAe~IR4$UL@h+)(f|O#^z%AJjTzk@ryDc+1qwr{G&WW=W-C6^tc{r`hVaqTU^H;hn=m?t29#zK zk@hBp9-}UrFpSQQgmS-R!oY6NB$^mYFv>Xj)Reg{>uZ{d@@UGITrpv&%b$}3yO3W^ zIekqgo|~Gdnc;z#-&B2Ju5sJb%^?0)@FW->cr8AaU)$51dG3)8 z<!dTIQt$3(Y z)Pi~J5xa%qfluY|v=ltpq3ie^Es3Y4`bzV(G(0Vt=WET=Qt-4iJn++e>TPXLE5XxB z@U&uk9%-IdhNl(te4}|<37%Gl2fm+A&C@)s1y5_i)0%i<)VG?awc%;aJdZU`Yv##d zV%fa_{7HwWjo@j+JoX6ChVA)IW)nv1Xl;a)q%NQXuJ;0dIVy>1(SnmQGuK{iS9j*Rtns=tS4JaYhoC>wvX4Fxw2@y-pu7l zuq&$xb941JTSuT`&iT}3&C{QG=u8~u=`U>R&pdc`7-{HFJhA*Fu_eK#ye7=u ze)}6PjGqqI0OCqe`Sdjd1lIuKicxeH58E`r*ffA_YN`sDYrqp~V%hB%W3t0DP~_b} z<_Xg|Igok6G{Qi`Gm!Icp^4?@8EEXmIPX)}blweO9=qNR5En{RPYRCo^Z`G)bI>tp3<6UDD$9Y!k(dq2fmn3z0y3x1kW(R zGmLp6G|w=@GmLr4Xr5urV~@4N3=jM}S|J@}tu_s3o=APoaKSU2%crd78E$xnGtXSY zLB0(a`8M3}z-OdYEzL86dF*;Uf_dz|dj#{)sf3&(BMi?7<|(h!HbU4l!tlTkb$CXK zd>bk38A&|xs)EKFNjz=|eNROb<{l$P8ZP*^4%aB=vg`IJ!8MA@2q#jZlt(caa%&XZ zR9W+k5;l!8Jn)$vp3%al(IW3gGf$M}8Etq*Gfx%GGg|PBHazgd9iB0QXAJX%Q4FMe z43|+=%`?W7(HQ2brg_FNPj0#fR*x|}@a-L*v4Ur;$hWb~Q(g0nH9TXPr-tSkD|p5l z9?TaUo^i}mQ(rSq@Qh;~oF|5qjx#*tm?zp?gL+`Mp>c)>a}ZkL)OCBjuxGsB8PDZY zTl0)JJmZ^>Xw8i(g~!Sg!v*lp-_;)z%FG~VmP6R+wU33a=Hk=%9r zb+!rf{_Q;Pw`cs;OkYa&T;KhPc+Nk}`zKJEQ{Fdz!$UXGLpRAoH<@*9#2kN$N4%-5 z`!N-Ln0fj%)_ud*M*CSO2E56-TmkNQ(^)6y-!oVzd1rdWd&?u;mQRK_ptQ!(U zA5`hAw9IB*5DL-g=CJM^VK4gHlzBSOLpPsw*M)8Gu&%hsmjxcz!cR%b@vet%k%w-v zhi-|7ZmEZEnTKwe1mzyC3Qv}ZxVb2u9gMP=SYHFUTf@iAWnaVr~nrEuvnaVuPwLMdX zJyQ)2`Z9-Sn&6oxc&2f_wa|Feh$mJ#62^j-CJc4XUeB6lxX?$^K1yxVo6KeVId6(G zdXsHxrEPlC*z_jb^abIdZoet=?oGpke%Ild&OCNooi1#e&OEI(&ve5xoq5`5d!~!L zn{If}mpeQ&MBdF{9(x>}K|Jw%77hA@8HQ&D^WgAV*fWE9Y`8~ z=4nrOxFb1}dF(x*Ga0>uwsodK$4KL#za`M$61nvjqvK2^r1mXBkLMGXED5vUPA1Iu z2COi69-S!+Jt;;phi{hPnP~ z&uqgpn`%O9)l>7#7Bz0R;lU{G@XTSJUiz9jqO9hyJxL}kkXU;gDHT0|+{Z|;$sUR3 z7%q4RJ~cq+-CV&nS8&Z`uD*nayqjxmnoBmdQ+Cfimu<3n<`Pdd*9UkU4$nNnGf(i$ zW1fDRXP)7iCwS%wo_WR|criXTMB6i8l+k?Vv0LkW;)zxLb^gpJp7t&Y^=^O(v+Esd zHhdz7;T^&7j$n9)83t;UcbLJEz%a;!xf$SLISdN~!vc|43plR^6AH>?fyt`{BCi&R zyjo!L3SOJTvygf0+5AGmvygd)Xr6_JXQAL(D0mhc9(aNd&%4ZH-+g>n@Vv`8mP|b8 z+1@3dSjr{qdGL1`Jp*B(CBMt)Ln$W81b(H%u!tFkQ5a$_5)6yjlHuBtMaGgv!jeV8 zl10W6_^LiNT-UC}qGT2ep2f^FLh~#(Jd2sf_CFRgkL|ZDHazfu9iAnEXNllh!aO52 z&l1D4gn35kJXj*^Sz>tLQ#(9M1833alE5`6{R6q1*fJDGQgT~ zu4bK_>8|n6t@Y5YW8G0ooia1*^&asyc<45=PR?rI^U!VbxOOw^kmlCL1X=#hOAA zxK=aQwPb5mdo^>}H?_6X@$0 z-S(!|5qhkesqxlvDL4{*owrPw?dzalTxYn@8#r9+1=o6E$$GYAmd0Dpme{k>^;`;X zQy9?K8+7z5KDAI=vVqa}aHwyHPgx*=r z(dZi)eXfy^GmQxgY2Rqj(bqZX?=kv3ea(9U{XI_md=rKd=p7@u(cd%Z=rw7lvQGOZ zk@igjeG{WE(0H3D?N06ABywhxK}Y}Vpl=pw-z?BKGx|b}zM0Tlt9Om$PWxs;58;-J zo}Bix=(N8t(*C|cf1lA8X}tFteX)_;=dJ;Gl0|^dyL z*6M4v6FRNXQVe)V+ZlZwg`vf4r(VaW^{74T%{4)!x7*cr!-MhI;n^YbXos+32lH&u zcss}nr{?bvHGhXe$H?xW?-b}e1^P}#->A`datXX=B&6NGE4I_1!$3dwkr*R@md?F5+pgHc=WdKEn5KxONM!-GXa3b8XgX-!1ZKx5%g6 z#u9ij4*DKOx9id#fxd^)-`D7S1o|FEw`=MigARYlLEkIVzE_~{W%Ml?eXl^@E7HE# zpu@9r(Dw=SeT*JPF;G+YG5S`GzK`>Mn~~5Cs!&YS;(Z1kKAMBRU!d<7==%x1jru_2 z?WZz!OX!WZn=m)me!~Ud&!pu=x>&_81I!y4fuf&LMrA2DI> z{_`V&{t=^NCOeTjdF$D5YxlVOsc+}IHD`6633t9B4(^>ErBtT8H+jrMcicmF!bA75 zhwc*(-ANDKDG%Lg58W9L-C5S%37`+^D6ARzr>v7R@^c=#^B%ejtUDM?A7)1WnMb^f zq)VOROuI`SI`rA8m7Gyt@rd_1>#F3S55s$vb@JM4tdq7~XI)%c`Y?HLgLM&b35@Qh zhYt6XQmaE^MdKFhB*$$J-IuJB>AT|*?=I`o1=0uGhSBpVeRo>PQPBpEax1aDnWNlF zY(L;Aw{Y7JI7+R=@dJ)>D*-xcGVRjTecv&GevHv=FY*|nhp3Nq8$8D7M~&p}S&tcX zvP%}IfNlF`qaF!ZdS8p)mZlLj5V5S?nO(|(H4?e&gR z0{s-DH`I8iDD95ld&>0NsE6pq9L&>nCJpA!k!hFX9=^jx~MVFQaW3!OGZLE z;jtl|=!Koq`czf640-agcM^ua4^q{6rUF`f!Na~9(fot&mIKV!@I&?OC!Ob`Ab?24>ZaZ#(ZcbV4~Lo zCdP9I^K-)Vsjqa*&k56~>@nhV!tAWRHepETBO|%f34g$+s_JxJ73sVx(s@;+^D3wF z8;yCD%LwU2iCyEE-|Dby9MfJkyv8xHY6y$qWzcRJ&3;|5Ul;7x*`mi9^EzXGXC!xN z!b@>5Z!jkAz9D5d1m+FG?5e)kC^rbRn|fj-U_K=Y>4cZ#VBTcRXFBFh#_?9f5gAVBTTO-!#e{#&|iPg}M=Oa4oX+15S6OF3J(@1c9(p?m0| z`^rOyJ~$=EBM;p-9=dNmbdNoB-+Ac1XPvy4_{1aLQxDxU){W0aA7+;FoONHNck6y& zot$aBV4a+$ykuQnF?;)wb@Cl&KY3jHvxn{%)=A!9J>vc5q5IuK_lJk>Pu59}zdYjo z?V)?+aqT}T;-O!-M>?NsrTc|@qF=Zt+QvO@8-ME7aF5%@Uq(XPut#FlUpnznW8N3- z?LMRYt*^T;TJ3$&YEk29SC>Y4AW$A~%EBlHdb$UU`ATCxV9bAv90|~V$1*|xiQgV9n7x<=GTmA z`v_k%W}rs-TIA=~B0tgMY1fC&&qo6Dk-&V!n5i`8BZ2uyV4}yMyUrT(8ZqtnE+?cWK^?*!&|jG0zre#e;UjD&J8L0D*w=rJA4 z?*-=f!uIbOGrdOno-s2R$z7Mw}o!eqhWTMgpeYD`Hfl zJL($q1!LyaF<%JG7mS(9gdxvt&*p{6Gt?K1Y7XX0#qrm);G4q-*q%)t9+?W_u9n7B?Grx}clfe9mF$PONavpd^H0Vsqf!3kbVeGty<}c<8cv=(4d+ z@@8k~S0At$YL4d#vV9c5tGk`H`83~y1Ex-`SDA77BP@n`dN^KK{9JD>fKu(!$ zEm|zS_hgK9Pa>5_St`b~J-$?oSw~~0;*`}j5>jTbkD&6tf$7%+WC!WmC>2@9C$aU9HG#%!!( z1`Et!#%yB3fZ5bYNT;2j=&@+^Sf?|M$j>w)KhrQ~j7CYr`59{@VA{0@J)VP^R$!(T z=}gO*%`{3{#*8zP8xuVyt&8e(rW2UyL^{(kX1qp8$C&nAm~>p1(48Vb(c?Op=>=wb z#thSSH$7t}Xw38$rjd|N8xuXYgPB2KW)SJjz?dyGN(R3`>O)!@2_?3Iu+VZch*YEh zr#DvUoXE%wt@L#nMeb%~hSnx56*1sBdthc{Onc6Q@x#Fk5vdLlm?4bWR-=S)PP8+U zyTma5IGC9j({2Ho1ZF0}3{mYhN+!naU?g`7!1zV0OWO9#BAuBTGfbCQX2$GDC@5)+ zan5yF_&R&-CyPi+7PhaGX3xTDvDYfHh@J>zB%L&`(~?!BC9A;9%9x!sW>&`RVkCE- zVT`4d-Zf@6ftgKUW@F5*8YLUoo^D3MJ&W!}0)t)B7_n(ZKr>_)4A})kc4p|IQL=NY z6OH696^!@}W)6XwLty4$%$|gTd-ypR6XgT{z(L3<5OOkt-K*zhgkCxwIT^ve>yeYn zr@I+z;a|`^UR#<=VCE93%Eg#T8Z#GT_BIkQ(X*k|z(1ikFYB<}gz2OGQg#^b--Q_o zb-J&KiT2#wNWg?&4@~$sKJu7t37Gwj1k3?O0_H$1!3T1#%OmW|L-sk>Akcw6#NkT1vXO^gr=n~6M>^+t3apfoWo+c;q6MHK~n;jS>KQXjXR(u;b;E5a3IZ#%g%P ztLdSul|qMBg8G-JPU=3G#2Fa zPcjnxrO8Herys2>QQgrDg_vQAj#)@B6k>*{CJZ@bGZZ2lI;&|W%cg`q!xnJAzlri7ZC`B35p5ql2o)!8W2eTMs&eGQv6PU#q^KBD` z{G4qhJDtc0^jV2&jt(nMn2BcOE>4(<<~f<-oS$<|OkmD45-{zN8-1RGSwdiz5a}$z znDaGC39>zeSGJI{6703uWrRL6QT?Iwvm|3K(ASkD%$_PtmwQRZTxi08IhU>mW=VmG zJ~vUl(wL=0I!lRkmSW6zHD)O;qeVu7?WmVvK%bqc7VEHZff>%2VLF}RjJd?bgg4+w z$lawT3=H;q0Y-pCwM>VV77V3Ds!KD&auXAnD~tq8+ke9d;$TJy%m{%QL71J@N{tf1 zIkCz}z(fl`PGAIbFv|$cG6J&7zS~%a%g?T77|#;bS{*Y|FhmN5 zNY06MCT1$tORYB&QjL0sRAW4JFv~LL1|74kz%0v{8%-F}`JR#NJ`0!_PZQN99afGp zHyg?QhK+KJ`96iAU&5H1sB(~#29)x2o#XeFr?fbJUwOLD@%zg2Xs|^yl&3OkqqZ6e zDYN}PjNpl?q-LnVDch!FRuBvoIAtH0Fj#B%QWZom1rH!mMQF^5jA_p)D+`;3HIZm;aYgGy9AHD*=D+^=I+73r+Xm>-(3RCL0_0VAO<*(-bS zz#PnKBAwMlI;%0}L5)(4(wSuTC{&~TbTHw;IhfT2W_6Ly>Wq0vV^(L|4;#si2@lZ0 ztRXOKh;-Iq%p)452B-5QBe^l*K{}W<1!hf=&YFyQRHM{n%wtA!W5NSXR0DJw)nZKB zm#QT&Ycb|=jZ%v-Z4a;(=O^kXW@2?{Ij*07H`&>*Rfl`X2Ebc<35>=+KL#YvK{F zDeIn54m-2G7}m*mYoJF=$=l2WFU~_3@1aXz-EsQs@M6t2wUW9P9=evSlV#M3butfH zvrd*?`jLo z+Kl0i)yJD70-GfrT}G3FhO8ONA+jpW8e-=CU72n%y@wr&zSc#N<3rUH7E<%+`$gM8|B+m`{y_cJ$mx!2H2TzO977!hB|>vyH%P!ZZMLCw z_Es-7N*lKQMI_^RxZLy#MkX?GX7{(?5&a8x%{k(P&~+bngRcn;D#m zep#XawDZeH)&#Vn?55>RibUUnp3|nzT&gl@cKT(Z!zk>Zf9Qu$)Dgc#HOViS;^P|U zHyeG=nOW72Q_Wk{rjMfh(V{**^WHqaB2Yht)3N>4B>IQXDGH|~`_mc0I9b@A&ep}* zvi@{BB+mWwSG|IB(l4RvAAjYCG!PzD1EtcCIVvcV+Fam#YCJv_L`hADZCb9Mt{462 zMmSxl($n7_WGudCroT#MqUE-~HodqU(=D!6XV#ZweJTDsku?)|NzMW+;*Y#&><1%` z1;ScP>R^gellgB^irtfc9@Q%5`d-|id|Ru8>-%a|kW$lwuJ@yV{vy{)(%E6$eF&AE!F}KTsYo zF8xn=DE0qNd055wKY#y^$pN$|bQb8qUQtJuiayctrq(jN0_gwe=l`EM@QOA!V@F`h zAJmI`Q&ztGy;)MG_vZ$yQpI-Nj3nI_`bEEw@J9N39DSmmB+)Mh!J+h>ENMt>RwhHtcO}`TkJYR)t z@ZJ82rY{r1eN*#PJLiY*YSCnsaq>CxWB&V}|CRmzSI=Kv7Lg~@{CCOz@ZYz={-gBk zwjY~oVL$9`L%*=43;n`Qcu>$dA?ZYuj(7H9cQX>i_tepMVh;?Xr1N zV&c%U&ew9z*YYYoMFco97LnHt+ZeqW&lp+P(}(!+Q+3rqdh^{NdJjW4dS~GO?oSpX zbGMBD=6dAc!2c%Ve;Mb0m;b+n{ja0_f0^HpdiMZow6GyG7!}8=5dDei-F?Ww zEz(E200C-w_17a3VTR97tw7j=5~>>0&3hdDfgt7t@&`l-s!!4&*I KKmVuZ!2bo$!SV 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 "CONFIG_ATE" to Makefile + 2. Before doing ATE testing, please stop AP function + 3. If you want to test another ATE action, prefer to stop AP & ATE function + 4. All ATE function settings will lose efficacy after reboot. + 5. Before hardware register access, please reference hardware spec. + Note. + In ATE mode, the channel must set via "ATECHANNEL" + +=================================================================================================== +4. ated +======= +4.1 Introduction +The ated is an optional user space component for RT28xx Linux driver. +When Windows GUI starts, AP enters ATE mode (i.e.,ATESTART) immediately. +It behaves as a proxy between Windows GUI and RT28xx Linux driver when ATE process proceeds. +The ated will be killed automatically when Windows GUI is closed. +You can kill it manually, too(for example, type '$killall ated'). +RT28xx linux driver will leave ATE mode either ated is killed or Windows GUI is closed. + +4.2 Environment setup +1. Connect the platform you want to test directly with a Windows host by ether network line. +2. In the Windows host, run WinPcap_4_0.exe for the QA GUI or ./RT2880_ATE/RaUI.exe(please unrar "RT2880_ATE.rar" to get it). + +4.3 How to use ated for ATE purpose +0. First you should set both "HAS_ATE=y" and "HAS_QA_SUPPORT=y" in the file ~/Module/os/linux/config.mk and compile the driver. +1. Modify the Makefile according to our target "PLATFORM". +2. Change the path of "CROSS_COMPILE" if needed. +3. Then type 'make' command to compile the source code of the daemon. +4. After the driver interface has started up, attach both of the wireless interface and the ethernet interface to the bridge interface. +5. If you have no bridge interface, please give an IP address to the ethernet interface. + (for example : '$ated -beth0') +6. After the interfaces have entered forwarding states, manually start ated, type '$ated -bbrX -iraX'. +7. If your WLAN interface and Bridge interface is "ra0" and "br0" respectively, just type $ated. + (For further usage of options, type $ated -h) +8. In the Windows host, run RT28xxQA_ATE.exe or ./RT2880_ATE/RaUI.exe. +9. Select the wired network adapter, then press OK and wait for a moment. +10.If the Windows host cannot tolerate such a broadcast storm from ated, + please run ated with option -u.(for example : '$ated -ira1 -u') +11.If your target platform concerns its network security, please run RT28xxQA_unicast.exe instead of RT28xxQA_ATE.exe. + +Note : +a. The names of WLAN interface(default is "ra0") and Bridge interface(default is "br0") must be specified manually(for example : '$ated -bbr1 -ira2') if your WLAN interface or Bridge interface is not "ra0" or "br0" respectively ! +b. Please make sure no other RaUI is running before you excute ./RT2880_ATE/RaUI.exe. + + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/brftph_usage.txt b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/brftph_usage.txt new file mode 100644 index 000000000..63392e86d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/brftph_usage.txt @@ -0,0 +1,68 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ****************************************************************************/ + +The steps for bridge fast path function in wireless driver: + +1. Change HAS_BGFP_SUPPORT=y and HAS_BGFP_OPEN_SUPPORT=y + Note1: When you just only want to enable fast path in WLAN module, you can + only enable HAS_BGFP_SUPPORT. + Note2: When you want to enable fast path in WLAN and Ethernet module, you + need to enable HAS_BGFP_SUPPORT and HAS_BGFP_OPEN_SUPPORT. + + +The steps for bridge fast path function in ethernet driver: + +1. Find the function you pass received packets to upper layer. +2. Path code to the function. + +Note: If the ethernet driver is a library type, i.e. ***.ko, you must insert +the ethernet driver to the Linux kernel before RALINK WLAN driver. + +For examples: + +1. Declare a symbol and a function prototype. + UINT32 (*RALINK_FP_Handle)(PNDIS_PACKET pPacket); + EXPORT_SYMBOL(RALINK_FP_Handle); + +2. Support your received handler, called packet_forward() + + In Linux, find the keyword, netif_rx(), such as + packet_forward() + { + ...... + + // pass the packet to upper layer + skb->protocol = eth_type_trans(skb, skb->dev); + netif_rx(skb); + } + +3. Change the code segment to + packet_forward() + { + UINT32 HandRst = 1; + + ...... + + if (RALINK_FP_Handle != NULL) + HandRst = RALINK_FP_Handle(skb); + + if (HandRst != 0) + { + // pass the packet to upper layer + // printk("pass to upper layer!\n"); + skb->protocol = eth_type_trans(skb, skb->dev); + netif_rx(skb); + } + } diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/iwpriv_usage.txt b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/iwpriv_usage.txt new file mode 100644 index 000000000..940d646c9 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/iwpriv_usage.txt @@ -0,0 +1,447 @@ +iwpriv +================= +This is detailed explanation of each parameters for iwpriv. +Before reading this document, make sure you already read README. + +------------------------------------------------------------------------------------------------------- +USAGE: + iwpriv ra0 commands val + +NOTE: + Wireless Extension Private Handlers + +where +[commands] [val] + {range} +----------------- ------------------------------------------------- +wsc_conf_mode {0, 1, 2} + ::Set WPS conf mode + 0: WPS Disabled + 1: Enrollee + 2: Registrar + +wsc_mode {1, 2} + ::PIN or PBC + 1: PIN + 2: PBC + +wsc_pin {00000000 ~ 99999999} + ::Set Enrollee's PIN Code + +wsc_ssid {0~z, 1~32 ascii characters} + ::Set WPS AP SSID + +wsc_start NULL + ::Trigger RT2860 STA driver to do WPS process + +wsc_stop NULL + ::Stop WPS process + +wsc_gen_pincode NULL + ::Generate new PIN code + +wsc_cred_count {1 ~ 8} + ::Set count of WPS credential + +wsc_cred_ssid {"idx ssid_str"} + ::Set SSID into credtentail[idx] + idx: 0 ~ 7 + ssid_str: 0~z, 1~32 ascii characters + +wsc_cred_auth {"idx auth_str"} + ::Set AuthMode into credtentail[idx] + idx: 0 ~ 7 + auth_str: OPEN, WPAPSK, WPA2PSK, SHARED, WPA, WPA2 + +wsc_cred_encr {"idx encr_str"} + ::Set EncrypType into credtentail[idx] + idx: 0 ~ 7 + encr_str: NONE, WEP, TKIP, AES + +wsc_cred_keyIdx {"idx key_index"} + ::Set Key Index into credtentail[idx] + idx: 0 ~ 7 + key_index: 1 ~ 4 + +wsc_cred_key {"idx key"} + ::Set Key into credtentail[idx] + idx: 0 ~ 7 + key: ASCII string (wep_key_len(=5,13), passphrase_len(=8~63)) + OR + Hex string (wep_key_len(=10,26), passphrase_len(=64)) + +wsc_cred_mac {"idx mac_str"} + ::Set AP's MAC into credtentail[idx] + idx: 0 ~ 7 + mac_str: xx:xx:xx:xx:xx:xx + +wsc_conn_by_idx {0 ~ 7} + ::Connect AP by credential index + +wsc_auto_conn {0, 1} + ::Set driver to re-connecting to AP or not after registration. + 0: Disabled, driver won't re-connect to AP with new configurations. + 1: Enabled, driver will re-connect to AP with new configurations. + +wsc_ap_band {0, 1, 2} + ::Set prefer band to do WPS with dual band WPS AP + 0 : prefer 2.4G + 1 : prefer 5G + 2 : auto + Default value is auto (2) + +------------------------------------------------------------------------------------------------------- +USAGE: + iwpriv ra0 set [parameters]=[val] + +NOTE: + Execute one iwpriv/set command simultaneously. + +where +[parameters] [val] + {range} +----------------- ------------------------------------------------- +CountryRegion {0~7} + ::Set country region + 0: 1 ~ 11 ch + 1: 1 ~ 13 ch + 2: 10, 11 ch + 3: 10 ~ 13 ch + 4: 14 ch + 5: 1 ~ 14 ch + 6: 3 ~ 9 ch + 7: 5 ~ 13 ch + 31: 1 ~ 14 ch (ch1-11:active scan, ch12-14 passive scan) + +CountryRegionABand {0~11} + ::Set country region for A band + 0: 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165 ch + 1: 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 ch + 2: 36, 40, 44, 48, 52, 56, 60, 64 ch + 3: 52, 56, 60, 64, 149, 153, 157, 161 ch + 4: 149, 153, 157, 161, 165 ch + 5: 149, 153, 157, 161 ch + 6: 36, 40, 44, 48 ch + 7: 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 ch + 8: 52, 56, 60, 64 ch + 9: 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165 ch + 10: 36, 40, 44, 48, 149, 153, 157, 161, 165 ch + 11: 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161 ch + +SSID {0~z, 1~32 ascii characters} + ::Set AP SSID + +WirelessMode {0~10} + ::Set Wireless Mode + 0: legacy 11b/g mixed + 1: legacy 11B only + 2: legacy 11A only + 3: legacy 11a/b/g mixed + 4: legacy 11G only + 5: 11ABGN mixed + 6: 11N only + 7: 11GN mixed + 8: 11AN mixed + 9: 11BGN mixed + 10: 11AGN mixed + +Channel depends on CountryRegion or CountryRegionForABand + ::Set Channel + +BGProtection {0~2} + ::Set 11B/11G Protection + 0:Auto, + 1:Always on, + 2:Always off + +TxPreamble {0~2} + ::Set TxPreamble + 0:Preamble Long, + 1:Preamble Short, + 2:Auto + +RTSThreshold {1~2347} + ::Set RTS Threshold + +FragThreshold {256~2346} + ::Set Fragment Threshold + +TxBurst {0,1} + ::Set TxBurst Enable or Disable + 0:Disable, + 1:Enable + +NetworkType {Infra,Adhoc} + ::Set Network type + +AuthMode {OPEN,SHARED,WEPAUTO,WPAPSK,WPA2PSK,WPANONE} + ::Set Authentication Mode + +EncrypType {NONE,WEP,TKIP,AES} + ::Set Encryption Type + +DefaultKeyID {1~4} + ::Set Default Key ID + + +Key1 {5 ascii characters or 10 hex number or + 13 ascii characters or 26 hex numbers} + ::Set Key1 String + +Key2 {5 ascii characters or 10 hex number or + 13 ascii characters or 26 hex numbers} + ::Set Key2 String + +Key3 {5 ascii characters or 10 hex number or + 13 ascii characters or 26 hex numbers} + ::Set Key3 String + +Key4 {5 ascii characters or 10 hex number or + 13 ascii characters or 26 hex numbers} + ::Set Key4 String + +WPAPSK {8~63 ascii or 64 hex characters} + ::WPA Pre-Shared Key + +WmmCapable {0,1} + ::Set WMM Capable + 0:Disable WMM, + 1:Enable WMM + +PSMode {CAM, MAX_PSP, FAST_PSP} + ::Set Power Saving Mode + +HtBw {0,1} + ::Set BandWidth + 0: 20Hz + 1: 40Hz + +HtMcs {0 ~ 15, 33} + ::Set MCS + 33: Auto Rate + +HtGi {0,1} + ::Set Guard Interval(GI) + 0: long GI + 1: short GI + +HtOpMode {0,1} + ::Set HT Operation Mode + 0: HT mixed format + 1: HT greenfield format + +HtExtcha {0,1} + ::Set Extended Channel Switch Announcement + 0: Below + 1: Above + +HtMpduDensity {0 ~ 7} + ::Set The Minimum Time Between MPDUs within an AMPDU + +HtBaWinSize {1 ~ 64} + ::Set BA WinSize + +HtRdg {0,1} + ::Set RDG Capable + 0: Disabled + 1: Enabled + +HtAmsdu {0,1} + ::Set AMSDU Capable + 0: Disabled + 1: Enabled + +HtAutoBa {0,1} + ::Set Auto BA Capable + 0: Disabled + 1: Enabled + +HtBaDecline {0,1} + ::Reject BA request from AP + 0: Disabled + 1: Enabled + +HtProtect {0,1} + ::Set HT Protect Capable + 0: Disabled + 1: Enabled + +FixedTxMode {CCK, OFDM} + :: Set Fixed Tx Mode for fixed rate setting + Mode = CCK + MCS = 0 => 1Mbps + = 1 => 2Mbps + = 2 => 5.5 Mbps + = 3 => 11 Mbps + Mode = OFDM + MCS = 0 => 6Mbps + = 1 => 9Mbps + = 2 => 12Mbps + = 3 => 18Mbps + = 4 => 24Mbps + = 5 => 36Mbps + = 6 => 48Mbps + = 7 => 54Mbps + +==> Build Ethernet Convert function. Please set 'HAS_ETH_CONVERT_SUPPORT=y' in os/linux/config.mk +EthConvertMode {dongle, clone, hybrid} + ::Set Ethernet Convert Mode + +EthCloneMac {xx:xx:xx:xx:xx:xx} + :: Set Clone MAC + +LongRetry {0,255} + :: Set Tx Long Retry Limit + +ShortRetry {0,255} + :: Set Tx Short Retry Limit + +MeshId {Length 1~32 ascii characters} + :: Set Mesh ID + +MeshHostName {Length 1~32 ascii characters} + :: Set Mesh Host Name + +MeshAutoLink {1,0} + :: Set Mesh Auto Link Capable + 0: Disabled + 1: Enabled + +MeshAddLink {xx:xx:xx:xx:xx:xx} + :: Add Mesh Link + +MeshDelLink {xx:xx:xx:xx:xx:xx} + :: Delete Mesh Link + +MeshMultiCastAgeOut {20 ~ 65535 seconds} + :: Set AgeOut time for Mesh MultiCast + +MeshAuthMode {OPEN, WPANONE} + :: Set Mesh Authentication Mode + +MeshEncrypType {NONE, WEP, TKIP, AES} + :: Set Mesh Encryption Type + +MeshDefaultkey {1 ~ 4} + :: Set Mesh Default Key ID + +MeshWEPKEY {5 ascii characters or 10 hex number or + 13 ascii characters or 26 hex numbers} + :: Set Mesh WEP Key String + +MeshWPAKEY {8~63 ascii or 64 hex characters} + :: Set Mesh WPA Pre-Shared Key + +Examples +=================================================================== +------------------------------------------------------------------------------------------------------- +a> Config STA to link with AP which is OPEN/NONE(Authentication/Encryption) + 1. iwpriv ra0 set NetworkType=Infra + 2. iwpriv ra0 set AuthMode=OPEN + 3. iwpriv ra0 set EncrypType=NONE + 4. iwpriv ra0 set SSID="AP's SSID" + +b> Config STA to link with AP which is SHARED/WEP(Authentication/Encryption) + 1. iwpriv ra0 set NetworkType=Infra + 2. iwpriv ra0 set AuthMode=SHARED + 3. iwpriv ra0 set EncrypType=WEP + 4. iwpriv ra0 set DefaultKeyID=1 + 5. iwpriv ra0 set Key1="AP's wep key" + 6. iwpriv ra0 set SSID="AP's SSID" + +c> Config STA to link with AP which is WPAPSK/TKIP(Authentication/Encryption) + 1. iwpriv ra0 set NetworkType=Infra + 2. iwpriv ra0 set AuthMode=WPAPSK + 3. iwpriv ra0 set EncrypType=TKIP + 4. iwpriv ra0 set SSID="AP's SSID" + 5. iwpriv ra0 set WPAPSK="AP's wpa-preshared key" + 6. iwpriv ra0 set SSID="AP's SSID" + +d> Config STA to link with AP which is WPAPSK/AES(Authentication/Encryption) + 1. iwpriv ra0 set NetworkType=Infra + 2. iwpriv ra0 set AuthMode=WPAPSK + 3. iwpriv ra0 set EncrypType=AES + 4. iwpriv ra0 set SSID="AP's SSID" + 5. iwpriv ra0 set WPAPSK="AP's wpa-preshared key" + 6. iwpriv ra0 set SSID="AP's SSID" + +e> Config STA to link with AP which is WPA2PSK/TKIP(Authentication/Encryption) + 1. iwpriv ra0 set NetworkType=Infra + 2. iwpriv ra0 set AuthMode=WPA2PSK + 3. iwpriv ra0 set EncrypType=TKIP + 4. iwpriv ra0 set SSID="AP's SSID" + 5. iwpriv ra0 set WPAPSK=12345678 + 6. iwpriv ra0 set SSID="AP's SSID" + +f> Config STA to create/link as adhoc mode, which is OPEN/NONE(Authentication/Encryption) + 1. iwpriv ra0 set NetworkType=Adhoc + 2. iwpriv ra0 set AuthMode=OPEN + 3. iwpriv ra0 set EncrypType=NONE + 4. iwpriv ra0 set SSID="Adhoc's SSID" + +g> Config STA to create/link as adhoc mode, which is WPANONE/TKIP(Authentication/Encryption) + 1. iwpriv ra0 set NetworkType=Adhoc + 2. iwpriv ra0 set AuthMode=WPANONE + 3. iwpriv ra0 set EncrypType=TKIP + 4. iwpriv ra0 set SSID="AP's SSID" + 5. iwpriv ra0 set WPAPSK=12345678 + 6. iwpriv ra0 set SSID="AP's SSID" + +h> Get site survey + usage: iwpriv ra0 get_site_survey + +i> Get Statistics + usage: iwpriv ra0 stat ; read statistic counter + iwpriv ra0 set ResetCounter=0 ; reset statistic counter + +j> Link with an AP which is the largest strength ; set ANY SSID (ssidLen=0) + usage: iwconfig ra0 essid "" + or + usage: iwpriv ra0 set SSID="" + +k> Config STA to link as dongle mode with STA own MAC + usage: iwpriv ra0 set EthConvertMode=dongle + +l> Config STA to link as clone mode + usage: iwpriv ra0 set EthConvertMode=clone + iwpriv ra0 set EthCloneMac="Desired MAC" ;; 00:00:00:00:00:00 means using STA own MAC + ;; FF:FF:FF:FF:FF:FF means using source MAC of first packet coming from wired device + +m> Config STA to link as hybrid(dongle+clone) mode + usage: iwpriv ra0 set EthConvertMode=hybrid + iwpriv ra0 set EthCloneMac="Desired MAC" ;; 00:00:00:00:00:00 means using STA own MAC + ;; FF:FF:FF:FF:FF:FF means using source MAC of first packet coming from wired device + +=================================================================== + +iwlist +================= +This is detailed explanation of each parameters for iwlist. + +------------------------------------------------------------------------------------------------------- +iwlist ra0 scanning ; list the results after scanning(manual rescan) + + + +======================================================================================================= + +iwconfig +================= +The following are our support in standard configuration - iwconfig + +------------------------------------------------------------------------------------------------------- +iwconfig ra0 essid {NN|on|off} ; set essid +iwconfig ra0 mode {managed|ad-hoc|...} ; set wireless mode +>> rt2860sta driver support monitor mode with linux kernel > 2.4.20. +>> Note: For using monitor mode => if mesh interface is ON, please down the mesh interface first. +iwconfig ra0 freq N.NNNN[k|M|G]] ; set frequency +iwconfig ra0 channel N ; set channel +iwconfig ra0 ap {N|off|auto} ; set AP address +iwconfig ra0 nick N ; set nickname +iwconfig ra0 rate {N|auto|fixed} ; set rate (only support legacy rate setting) +iwconfig ra0 rts {N|auto|fixed|off} ; set RTS threshold +iwconfig ra0 frag {N|auto|fixed|off} ; set Fragment threshold +iwconfig ra0 enc {NNNN-NNNN|off} ; set encryption type +iwconfig ra0 power {period N|timeout N} ; set power management modes + +*** Wireless extension usage please refer to man page of 'iwconfig', 'iwlist' and 'iwpriv'. *** diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/mbss_phy.readme b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/mbss_phy.readme new file mode 100644 index 000000000..fd89411a6 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/mbss_phy.readme @@ -0,0 +1,65 @@ +Readme for different phy mode of different BSS as below: + +1. Extend WirelessMode usage in DAT file + + EX: WirelessMode=0;9;1;9 i.e. bg, bgn, b-only, bgn, pAd->CommonCfg.PhyMode will be 9 + + EX: WirelessMode=0;0;1;0 i.e. bg, bg, b-only, bg, pAd->CommonCfg.PhyMode will be 0 + + + + +2. Add a new parameter, PhyMode, in MULTISSID_STRUCT structure + + + +3. Use pAd->ApCfg.MBSSID[apidx].PhyMode, not pAd->CommonCfg.PhyMode in APUpdateBeaconFrame() + + Use pAd->ApCfg.MBSSID[apidx].PhyMode, not pAd->CommonCfg.PhyMode in APPeerProbeReqAction() + + + +4. Use maximum capability for all BSS in RT_CfgSetWirelessMode(). + + EX: In MBSS mode, BSS0 is 11g-only, BSS1 is 11b-only, pAd->CommonCfg.PhyMode will be 11bg-mixed. + + EX: In MBSS mode, BSS0 is 11n-2.4G-only, BSS1 is also 11n-2.4G-only, pAd->CommonCfg.PhyMode will be 11n-2.4G-only, not 11bgn-mixed. + + EX: In MBSS mode, BSS0 is 11b-only, BSS1 is also 11b-only, pAd->CommonCfg.PhyMode will be 11b-only. + + EX: In MBSS mode, BSS0 is 11b-only, BSS1 is also 11bgn-mixed, pAd->CommonCfg.PhyMode will be 11bgn-mixed. + + + + So no impact for GreenAP mode. Check with K.H. + + + +5. Add two new command + + (1) iwpriv ra0 set MBSSWirelessMode=[0 ~ 11] + + Set different phy mode for different BSS. + + (2) iwpriv ra0 show mbss + + Show current phy mode for different BSS. EX: + + + + BSS Idx Phy Mode + MAX BGN Mixed + 0 BG Mixed + 1 BG Mixed + 2 BG Mixed + 3 BGN Mixed + + + +6. When ra0 use 2.4G, users set ra1 to 5G, ra0 will be same as ra1. + When ra0 use 5G, users set ra1 to 2.4G, ra0 will be same as ra1. + EX: BSS0 is 11bg-mixed, then users set BSS1 to 11a-only, ra0 will be 11a-only, not 11an-mixed. + EX: BSS0 is 11bg-mixed, then users set BSS1 to 11an-mixed, ra0 will be 11an-mixed. + + +7. Use CONFIG_AP_SUPPORT and MBSS_SUPPORT to include these codes. diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/sta_ate_iwpriv_usage.txt b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/sta_ate_iwpriv_usage.txt new file mode 100644 index 000000000..b235e13cf --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/sta_ate_iwpriv_usage.txt @@ -0,0 +1,445 @@ +=================================================================================================== +ATE Test Command Format for station driver + +****** IMPORTANT ****** +If you are not familiar with hardware, it is recommanded not to modify hardware default value. +It may damage hardware. + +=================================================================================================== +Usage: + iwpriv ra0 [act] [parameters]=[val] + + +where + +[act] [parameters] [val] constraints explaination +----- ------------- ----------------- -------------------------------- + +===================================== +1. Set ATE actions. + Value: + ATESTART - Start ATE function and stop station function. + ATESTOP - Stop ATE function and start station function. + TXCONT - Start continuous TX, for power mask. + TXCARR - Start carrier test, for frequency calibration. + TXFRAME - Transmit frame, for EVM. + RXFRAME - Continuous RX, for PER/FER. + +1.1 ATEDA + Set ATE frame header destination address. + Value: + xx:xx:xx:xx:xx:xx ; hex + +1.2 ATESA + Set ATE frame header source addr. + Value: + xx:xx:xx:xx:xx:xx ; hex + +1.3 ATEBSSID + Set ATE frame header BSSID. + Value: + xx:xx:xx:xx:xx:xx ; hex + +1.4 ATECHANNEL + Set ATE Channel, deimal. + Value: + 802.11b/g: 1 ~ 14 depends on CountryRegion setting + +1.5 ATETXPOW0 + Set ATE Tx power for Antenna 1. + Value: + 0 ~ 31 ; 2.4GHz, deimal + -7 ~15 ; 5.5GHz, deimal + +1.6 ATETXPOW1 + Set ATE Tx power for Antenna 2. + Value: + 0 ~ 31 ; 2.4GHz, decimal + -7 ~15 ; 5.5GHz, deimal + +1.7 ATETXFREQOFFSET + Set ATE RF frequency offset. + Value: + 0 ~ 63 ; unit: 2KHz, decimal + +1.8 ATETXLEN + Set ATE frame length. + Value: + 24 ~ 2312 ; decimal + +1.9 ATETXCNT + Set ATE frame Tx count. + Value: + 1 ~ ; 32-bit, decimal + +1.10 ATETXMODE (Refer to TxMode) + Set ATE Tx Mode. + Value: + 0: CCK 802.11b + 1: OFDM 802.11g + 2: HT_MIX 802.11b/g/n + 3: Green Field 802.11n + +1.11 ATETXBW (Refer to TxMode) + Set ATE Tx and Rx Bandwidth. + Value: + 0: 20MHz + 1: 40MHz + +1.12 ATETXGI (Refer to TxMode) + Set ATE Tx Guard Interval. + Value: + 0: Long + 1: Short + +1.13 ATETXMCS (Refer to TxMode) + Set ATE Tx MCS type. + Value: + 0 ~ 15 + +1.14 ATETXANT + Set ATE TX antenna. + Value: + 0: All + 1: Antenna one + 2: Antenna two + +1.15 ATERXANT + Set ATE RX antenna. + Value: + 0: All + 1: Antenna one + 2: Antenna two + 3: Antenna three + +1.16 ATERXFER + Set ATE to periodically reset and show up RxCount (per-second) and RxTotalCount. + Value: + 0: Disable counter visability + 1: Enable counter visability + +1.17 ATESHOW + Show all parameters of ATE. + Value: + 1 + +1.18 ATEHELP + List all commands of ATE. + Value: + 1 + +1.19 ResetCounter + Reset statistic counter. + Value: + 1 + +1.20 ATERRF + Read all of the RF registers. + Value: + 1 + +1.21 ATEWRF1 + Write the RF register 1. + Value: + xxxxxxxx ;32-bit, hex + +1.22 ATEWRF2 + Write the RF register 2. + Value: + xxxxxxxx ;32-bit, hex + +1.23 ATEWRF3 + Write the RF register 3. + Value: + xxxxxxxx ;32-bit, hex + +1.24 ATEWRF4 + Write the RF register 4. + Value: + xxxxxxxx ;32-bit, hex + +1.25 ATELDE2P + Overwrite all EEPROM contents + Value: + 1 + E.g. + iwpriv ra0 set ATELDE2P=1 + +1.26 ATERE2P + Display all EEPROM content. + Value: + 1 + E.g. + iwpriv ra0 set ATERE2P=1 + +=================================================================================================== +2. Examples: +========= + +2.1 Check EVM & Power + iwpriv ra0 set ATE=ATESTART + iwpriv ra0 set ATEDA=00:11:22:33:44:55 + iwpriv ra0 set ATESA=00:aa:bb:cc:dd:ee + iwpriv ra0 set ATEBSSID=00:11:22:33:44:55 + iwpriv ra0 set ATECHANNEL=1 ; set Channel + iwpriv ra0 set ATETXMODE=1 ; set TX-Mode. + iwpriv ra0 set ATETXMCS=7 ; set MCS type. + iwpriv ra0 set ATETXBW=0 ; set Bandwidth + iwpriv ra0 set ATETXGI=0 ; set Long GI. + iwpriv ra0 set ATETXLEN=1024 ; set packet length. + iwpriv ra0 set ATETXPOW0=18 + iwpriv ra0 set ATETXPOW1=18 + iwpriv ra0 set ATETXCNT=100000 + iwpriv ra0 set ATE=TXFRAME + ¡K + iwpriv ra0 set ATETXPOW0=19 + ¡K + iwpriv ra0 set ATETXPOW0=20 + ¡K + iwpriv ra0 set ATE=ATESTART + +2.2 Check Carrier + iwpriv ra0 set ATE=ATESTART + iwpriv ra0 set ATECHANNEL=1 ; set Channel + iwpriv ra0 set ATETXMODE=1 ; set TX-Mode. + iwpriv ra0 set ATETXMCS=7 ; set MCS type. + iwpriv ra0 set ATETXBW=0 ; set Bandwidth + iwpriv ra0 set ATETXCNT=200 ; Tx frame count(decmial) + iwpriv ra0 set ATE=TXFRAME ; Start Tx Frame(inform BBP to change, modulation mode) + iwpriv ra0 set ATE=TXCARR ; Start Tx carrier, Measure carrier with instrument + iwpriv ra0 set ATETXPOW0=05 + iwpriv ra0 set ATETXPOW1=05 + iwpriv ra0 set ATETXFREQOFFSET=19 + iwpriv ra0 set ATE=ATESTART + +2.3 Check specturm mask + iwpriv ra0 set ATE=ATESTART + iwpriv ra0 set ATECHANNEL=1 ; set Channel + iwpriv ra0 set ATETXMODE=1 ; set TX-Mode. + iwpriv ra0 set ATETXMCS=7 ; set MCS type. + iwpriv ra0 set ATETXBW=0 ; set Bandwidth + iwpriv ra0 set ATETXCNT=200 ; Tx frame count(decmial) + iwpriv ra0 set ATE=TXFRAME ; Start Tx Frame(inform BBP to change, modulation mode) + iwpriv ra0 set ATE=TXCONT ; Start continuous TX, Measure specturm mask with instrument + iwpriv ra0 set ATETXPOW0=5 + iwpriv ra0 set ATETXPOW1=5 + iwpriv ra0 set ATE=ATESTART + +2.4 Frequency offset tuning + iwpriv ra0 set ATE=ATESTART + iwpriv ra0 set ATECHANNEL=1 ; set Channel + iwpriv ra0 set ATETXMODE=1 ; set TX-Mode. + iwpriv ra0 set ATETXMCS=7 ; set MCS type. + iwpriv ra0 set ATETXCNT=200 ; Tx frame count(decmial) + iwpriv ra0 set ATETXFREQOFFSET=0 ; Set frequency offset 0(decimal) + iwpriv ra0 set ATE=TXFRAME ; Start Tx Frame + iwpriv ra0 set ATE=TXCARR ; Start Tx carrier, Measure carrier frequency with instrument + iwpriv ra0 set ATETXFREQOFFSET=10 ; Dynamic turning frequency offset, 10(decimal) + iwpriv ra0 set ATETXFREQOFFSET=20 ; Dynamic turning frequency offset, 20(decimal) + iwpriv ra0 set ATE=ATESTART ; Stop, Store the tuning result to EEPROM + +2.5 Rx + iwpriv ra0 set ATE=ATESTART + iwpriv ra0 set ATECHANNEL=1 ; set Channel + iwpriv ra0 set ResetCounter=1 ; Reset statistic counter + iwpriv ra0 set ATETXFREQOFFSET=value ;To use the ¡§value¡¨(decimal) you got in tx calibration + iwpriv ra0 set ATETXMODE=1 ; set TX-Mode. + iwpriv ra0 set ATETXMCS=7 ; set MCS type. + iwpriv ra0 set ATETXBW=0 ; set Bandwidth + iwpriv ra0 set ATE=RXFRAME ; Start Rx, + iwpriv ra0 set ATERXFER=1 ; show RxCnt and RSSI/per-antenna, Transmit test packets + iwpriv ra0 set ATE=ATESTART ; Stop + iwpriv ra0 stat ; get statistics counter + iwpriv ra0 set ATERXFER=1 + iwpriv ra0 set ATERXANT=1 + + iwpriv ra0 set ATE=ATESTART + iwpriv ra0 set ATERXANT=0 + iwpriv ra0 set ATE=RXFRAME + +2.6 Show all ate parameters + iwpriv ra0 set ATESHOW=1 + + Mode=4 + TxPower0=0 + TxPower1=0 + TxAntennaSel=0 + RxAntennaSel=0 + BBPCurrentBW=0 + GI=0 + MCS=7 + TxMode=1 + Addr1=00:11:22:aa:bb:cc + Addr2=00:11:22:aa:bb:cc + Addr3=00:11:22:aa:bb:cc + Channel=1 + TxLength=1024 + TxCount=40000 + TxRate=11 + RFFreqOffset=0 + +2.7 Online help + iwpriv ra0 set ATEHELP=1 + + ATE=ATESTART, ATESTOP, TXCONT, TXCARR, TXFRAME, RXFRAME + ATEDA + ATESA + ATEBSSID + ATECHANNEL, range:0~14(unless A band !). + ATETXPOW0, set power level of antenna 1. + ATETXPOW1, set power level of antenna 2. + ATETXANT, set TX antenna. 0: all, 1: antenna one, 2: antenna two. + ATERXANT, set RX antenna.0: all, 1: antenna one, 2: antenna two, 3: antenna three. + ATETXFREQOFFSET, set frequency offset, range 0~63. + ATETXBW, set BandWidth, 0:20MHz, 1:40MHz. + ATETXLEN, set Frame length, range 24~2312. + ATETXCNT, set how many frame going to transmit. + ATETXMCS, set MCS, reference to rate table. + ATETXMODE, set Mode 0: CCK, 1: OFDM, 2: HT-Mix, 3: GreenField, reference to rate table. + ATETXGI, set GI interval, 0: Long, 1: Short. + ATERXFER, 0: disable Rx Frame error rate. 1: enable Rx Frame error rate. + ATERRF, show all RF registers. + ATEWRF1, set RF1 register. + ATEWRF2, set RF2 register. + ATEWRF3, set RF3 register. + ATEWRF4, set RF4 register. + ATELDE2P, load EEPROM from .bin file. + ATERE2P, display all EEPROM content. + ATESHOW, display all parameters of ATE. + ATEHELP, online help. + +2.8 Display Rx Packet Count and RSSI + iwpriv ra0 set ATERXANT=0 ==> Enable All Three Rx Antennas + iwpriv ra0 set ATERXFER=1 ==> Enable Rx Frame Error Rate: RxCnt/RxTotal + iwpriv ra0 set ATE=RXFRAME ==> Start Rx + MlmePeriodicExec: Rx packet cnt = 2/4 + MlmePeriodicExec: Rx AvgRssi0=-88, AvgRssi1=-80, AvgRssi2=-91 + MlmePeriodicExec: Rx packet cnt = 2/6 + MlmePeriodicExec: Rx AvgRssi0=-86, AvgRssi1=-77, AvgRssi2=-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 "CONFIG_ATE" to Makefile + 2. Before doing ATE testing, please stop AP function + 3. If you want to test another ATE action, prefer to stop AP & ATE function + 4. All ATE function settings will lose efficacy after reboot. + 5. Before hardware register access, please reference hardware spec. + Note. + In ATE mode, the channel must set via "ATECHANNEL" + +=================================================================================================== +4. ated +======= +4.1 Introduction +The ated is an optional user space component for RT28xx Linux driver. +When Windows GUI starts, AP enters ATE mode (i.e.,ATESTART) immediately. +It behaves as a proxy between Windows GUI and RT28xx Linux driver when ATE process proceeds. +The ated will be killed automatically when Windows GUI is closed. +You can kill it manually, too(for example, type '$killall ated'). +RT28xx linux driver will leave ATE mode either ated is killed or Windows GUI is closed. + +4.2 Environment setup +1. Connect the platform you want to test directly with a Windows host by ether network line. +2. In the Windows host, run WinPcap_4_0.exe for the QA GUI or ./RT2880_ATE/RaUI.exe(please unrar "RT2880_ATE.rar" to get it). + +4.3 How to use ated for ATE purpose +0. First you should set both "HAS_ATE=y" and "HAS_QA_SUPPORT=y" in the file ~/Module/os/linux/config.mk and compile the driver. +1. Modify the Makefile according to our target "PLATFORM". +2. Change the path of "CROSS_COMPILE" if needed. +3. Then type 'make' command to compile the source code of the daemon. +4. After the driver interface has started up, attach both of the wireless interface and the ethernet interface to the bridge interface. +5. If you have no bridge interface, please give an IP address to the ethernet interface. + (for example : '$ated -beth0') +6. After the interfaces have entered forwarding states, manually start ated, type '$ated -bbrX -iraX'. +7. If your WLAN interface and Bridge interface is "ra0" and "br0" respectively, just type $ated. + (For further usage of options, type $ated -h) +8. In the Windows host, run RT28xxQA_ATE.exe or ./RT2880_ATE/RaUI.exe. +9. Select the wired network adapter, then press OK and wait for a moment. +10.If the Windows host cannot tolerate such a broadcast storm from ated, + please run ated with option -u.(for example : '$ated -ira1 -u') +11.If your target platform concerns its network security, please run RT28xxQA_unicast.exe instead of RT28xxQA_ATE.exe. + +Note : +a. The names of WLAN interface(default is "ra0") and Bridge interface(default is "br0") must be specified manually(for example : '$ated -bbr1 -ira2') if your WLAN interface or Bridge interface is not "ra0" or "br0" respectively ! +b. Please make sure no other RaUI is running before you excute ./RT2880_ATE/RaUI.exe. + + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/wps_iwpriv_usage.txt b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/wps_iwpriv_usage.txt new file mode 100644 index 000000000..89d87b922 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/doc/wps_iwpriv_usage.txt @@ -0,0 +1,173 @@ +/* + * README: WPS STA as an Enrollee or Registrar +*/ + +0. Build WPS function. Please set 'HAS_WSC=y'. + +1. Enrollee Mode + +1.1) PIN mode: + +Running Scenarios (case 'a' and 'b') + -------------------------------------------------------- + a. Adding an Enrollee to AP+Registrar (EAP) + [AP+Registrar]<----EAP--->[Enrollee Client] + -------------------------------------------------------- + b. Adding an Enrollee with external Registrar (UPnP/EAP) + [External Registrar]<----UPnP--->[AP_Proxy]<---EAP--->[Enrollee Client] + -------------------------------------------------------- + Note: 'EAP' indicates to use wireless medium and 'UPnP' indicates to use + wired or wireless medium. + +(i) [Registrar] or [AP+Registrar] + Enter the Enrollee PinCode on the Registrar and start WPS on the Registrar. + Note: How to get the Enrollee PinCode? Use 'iwpriv ra0 stat' on the Enrollee. + +(ii)[RT2860 Linux WPS STA] + iwpriv ra0 wsc_conf_mode 1 ;; Enrollee + iwpriv ra0 wsc_mode 1 ;; PIN + iwpriv ra0 wsc_ap_band 0 (or 1) ;; 0: prefer 2.4G, 1: prefer 5G + iwpriv ra0 wsc_ssid "AP's SSID" + iwpriv ra0 wsc_start + +{iii) If the registration is successful, the Enrollee will be re-configured + with the new parameters, and will connect to the AP with these new parameters. + +1.2) PBC mode: + + Running Scenarios (case 'a' only) + -------------------------------------------------------- + a. Adding an Enrollee to AP+Registrar (EAP) + [AP+Registrar]<----EAP--->[Client] + -------------------------------------------------------- + +(i) [AP+Registrar] + Start PBC on the Registrar. + +{ii)[RT2860 Linux WPS STA] + iwpriv ra0 wsc_conf_mode 1 ;; Enrollee + iwpriv ra0 wsc_mode 2 ;; PBC + iwpriv ra0 wsc_ap_band 0 (or 1) ;; 0: prefer 2.4G, 1: prefer 5G + iwpriv ra0 wsc_start + +{iii) If the registration is successful, the Enrollee will be re-configured + with the new parameters, and will connect to the AP with these new parameters. + + +2. Registrar Mode + +2.1) PIN mode: + +Running Scenarios (case 'a' and 'b') + -------------------------------------------------------- + a. Configure the un-configured AP + [Unconfigured AP]<----EAP--->[Registrar] + -------------------------------------------------------- + b. Configure the configured AP + [Configured AP]<----EAP--->[Registrar] + -------------------------------------------------------- + +(i) [AP] + Start PIN on the Enrollee WPS AP. + +(ii)[RT2860 Linux WPS STA] + iwpriv ra0 wsc_conf_mode 2 ;; Registrar + iwpriv ra0 wsc_mode 1 ;; PIN + iwpriv ra0 wsc_pin xxxxxxxx ;; AP's PIN Code + iwpriv ra0 wsc_ap_band 0 (or 1) ;; 0: prefer 2.4G, 1: prefer 5G + iwpriv ra0 wsc_ssid "AP's SSID" + iwpriv ra0 wsc_start + +{iii) If the registration is successful; + in case 'a': + The Registrar will be re-configured with the new parameters, + and will connect to the AP with these new parameters; + in case 'b': + The Registrar will be re-configured with AP's configurations, + and will connect to the AP with these new parameters. + +2.2) PBC mode: + same scenarios as PIN mod + +(i) [AP] + Start PBC on the Enrollee WPS AP. + +(ii)[RT2860 Linux WPS STA] + iwpriv ra0 wsc_conf_mode 2 ;; Registrar + iwpriv ra0 wsc_mode 2 ;; PBC + iwpriv ra0 wsc_ap_band 0 (or 1) ;; 0: prefer 2.4, 1: prefer 5G + iwpriv ra0 wsc_start + +{iii) If the registration is successful; + in case 'a': + The Registrar will be re-configured with the new parameters, + and will connect to the AP with these new parameters; + in case 'b': + The Registrar will be re-configured with AP's configurations, + and will connect to the AP with these new parameters. + + +3. Others + iwpriv ra0 wsc_cred_count 1 ;; Set count of credentials, Only support one credential for M8 in Registrar mode. + integer: 1 ~ 8 + + iwpriv ra0 wsc_cred_ssid "idx ssid_str" ;; Set SSID into credtentail[idx] + string: + idx: 0 ~ 7 + ssid_str: SSID for AP + example: + iwpriv ra0 wsc_cred_ssid "0 wps_ap1" + + iwpriv ra0 wsc_cred_auth "idx auth_str" ;; Set AuthMode into credtentail[idx] + string: + idx: 0 ~ 7 + auth_str: OPEN, WPAPSK, WPA2PSK, SHARED, WPA, WPA2 + example: + iwpriv ra0 wsc_cred_auth "0 WPAPSK" + + iwpriv ra0 wsc_cred_encr "idx encr_str" ;; Set EncrypType into credtentail[idx] + string: + idx: 0 ~ 7 + encr_str: NONE, WEP, TKIP, AES + example: + iwpriv ra0 wsc_cred_encr "0 TKIP" + + iwpriv ra0 wsc_cred_keyIdx "idx key_index" ;; Set Key Index into credtentail[idx] + string: + idx: 0 ~ 7 + key_index: 1 ~ 4 + example: + iwpriv ra0 wsc_cred_keyIdx "0 1" + + iwpriv ra0 wsc_cred_key "idx key" ;; Set Key into credtentail[idx] + string: + idx: 0 ~ 7 + key: ASCII string (wep_key_len(=5,13), passphrase_len(=8~63)) + OR + Hex string (wep_key_len(=10,26), passphrase_len(=64)) + example: + iwpriv ra0 wsc_cred_key "0 12345678" ;; Passphrase + iwpriv ra0 wsc_cred_key "0 abcd" ;; WEP Key + + iwpriv ra0 wsc_cred_mac "idx mac_str" ;; Set AP's MAC into credtentail[idx] + string: + idx: 0 ~ 7 + mac_str: xx:xx:xx:xx:xx:xx + example: + iwpriv ra0 wsc_cred_mac "0 00:11:22:33:44:55" + + iwpriv ra0 wsc_conn_by_idx 0 ;; Connect AP by credential index. + integer: 0 ~ 7 + + iwpriv ra0 wsc_auto_conn 0 ;; If the registration is successful, driver will re-connect to AP or not. + integer: 0 ;; Disabled, driver won't re-connect to AP with new configurations. + 1 ;; Enabled, driver will re-connect to AP with new configurations. + Note. Default value is 1. + + iwpriv ra0 wsc_stop ;; Stop WSC work and don't wait upon two-minute timeout + iwpriv ra0 wsc_ap_band val + val: 0 ;; prefer 2.4G AP + 1 ;; prefer 5G AP + 2 ;; Auto + iwpriv ra0 stat ;; Read statistics counter and WPS status. + \ No newline at end of file diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/easy_setup/ez_hooks.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/easy_setup/ez_hooks.c new file mode 100644 index 000000000..bd13d1e30 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/easy_setup/ez_hooks.c @@ -0,0 +1,4784 @@ +/* + *************************************************************************** + * 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_ez.c + + Abstract: + Easy Setup APIs + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#include "rt_config.h" +#include "easy_setup/ez_mod_hooks.h" + +extern ez_driver_ops_t ez_driver_ops_7603; +int EzDebugLevel = DBG_LVL_ERROR; + +unsigned long ez_build_beacon_ie( + void *wdev_obj, + unsigned char *frame_buf) + +{ + struct wifi_dev *wdev = wdev_obj; + if (wdev->ez_driver_params.ezdev) + { + return ez_build_beacon_ie_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, frame_buf); + } else { + ASSERT(FAIL); + return 0; + } +} + +unsigned long ez_build_probe_request_ie( + void *wdev_obj, + unsigned char *frame_buf) +{ + struct wifi_dev *wdev = wdev_obj; + if (wdev->ez_driver_params.ezdev) + return ez_build_probe_request_ie_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, frame_buf); + + ASSERT(FAIL); + return 0; + +} + +unsigned long ez_build_probe_response_ie( + void *wdev_obj, + unsigned char *frame_buf) +{ + struct wifi_dev *wdev = wdev_obj; + if (wdev->ez_driver_params.ezdev) + return ez_build_probe_response_ie_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, frame_buf); + + ASSERT(FAIL); + return 0; + + +} + +unsigned long ez_build_auth_request_ie( + void *wdev_obj, + unsigned char *peer_addr, + unsigned char *frame_buf) +{ + struct wifi_dev *wdev = wdev_obj; + if (wdev->ez_driver_params.ezdev) + return ez_build_auth_request_ie_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, + peer_addr, frame_buf); + return 0; + +} + +unsigned long ez_build_auth_response_ie( + void *wdev_obj, + unsigned char *peer_addr, + unsigned char *frame_buf) +{ + struct wifi_dev *wdev = wdev_obj; + if (wdev->ez_driver_params.ezdev) + return ez_build_auth_response_ie_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, + peer_addr, frame_buf); + + ASSERT(FAIL); + return 0; + + +} + +unsigned long ez_build_assoc_request_ie( + void *ad_obj, + void *wdev_obj, + unsigned char *peer_addr, + unsigned char *frame_buf, + unsigned int frame_buf_len) +{ + struct wifi_dev *wdev = wdev_obj; + if (wdev->ez_driver_params.ezdev) + return ez_build_assoc_request_ie_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, + peer_addr, frame_buf, frame_buf_len); + + + ASSERT(FAIL); + return 0; + +} + +unsigned long ez_build_assoc_response_ie( + void *wdev_obj, + unsigned char *peer_addr, + unsigned char *ap_gtk, + unsigned int ap_gtk_len, + unsigned char *frame_buf) +{ + struct wifi_dev *wdev = wdev_obj; + if (wdev->ez_driver_params.ezdev) + return ez_build_assoc_response_ie_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, + peer_addr, ap_gtk, ap_gtk_len, frame_buf); + return 0; +} + + +unsigned char ez_process_probe_request( + void *ad_obj, + void *wdev_obj, + unsigned char *peer_addr, + void *msg, + unsigned long msg_len) +{ + struct wifi_dev *wdev = wdev_obj; + if (wdev->ez_driver_params.ezdev) + return ez_process_probe_request_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, + peer_addr, msg, msg_len); + + ASSERT(FAIL); + return 0; +} + +void ez_process_beacon_probe_response( + void *wdev_obj, + void *msg, + unsigned long msg_len) +{ + struct wifi_dev *wdev = wdev_obj; + if (wdev->ez_driver_params.ezdev) { + ez_process_beacon_probe_response_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, + msg, msg_len); + } else { + ASSERT(FAIL); + } +} + +unsigned char ez_process_auth_request( + void *ad_obj, + void *wdev_obj, + void *auth_info_obj, + void *msg, + unsigned long msg_len) +{ + struct wifi_dev *wdev = wdev_obj; + if (wdev->ez_driver_params.ezdev) + return ez_process_auth_request_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, + auth_info_obj, msg, msg_len); + + ASSERT(FAIL); + return 0; +} + +void ez_process_auth_response( + void *ad_obj, + void *wdev_obj, + unsigned char *peer_addr, + unsigned long *current_state, + void *msg, + unsigned long msg_len) +{ + struct wifi_dev *wdev = wdev_obj; + PRTMP_ADAPTER ad= ad_obj; + APCLI_CTRL_MSG_STRUCT ApCliCtrlMsg; + if (wdev->ez_driver_params.ezdev) { + ApCliCtrlMsg.Status = ez_process_auth_response_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, + peer_addr, msg, msg_len); + *current_state = APCLI_AUTH_REQ_IDLE; + MlmeEnqueue(ad, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_AUTH_RSP, + sizeof(APCLI_CTRL_MSG_STRUCT), &ApCliCtrlMsg, wdev->func_idx); + } else { + ASSERT(FAIL); + } +} + +unsigned short ez_process_assoc_request( + void *wdev_obj, + void *entry_obj, + unsigned char isReassoc, + void *msg, + unsigned long msg_len) +{ + struct wifi_dev *wdev = wdev_obj; + MAC_TABLE_ENTRY *entry = entry_obj; + if (wdev->ez_driver_params.ezdev) + return ez_process_assoc_request_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, + entry->Addr,&entry->easy_setup_mic_valid, isReassoc, msg, msg_len); + + ASSERT(FAIL); + return 0; + +} + + +unsigned short ez_process_assoc_response( + void *wdev_obj, + unsigned char *peer_addr, + void *msg, + unsigned long msg_len) +{ + struct wifi_dev *wdev = wdev_obj; + if (wdev->ez_driver_params.ezdev) + return ez_process_assoc_response_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, + peer_addr, msg, msg_len); + + ASSERT(FAIL); + return 0; + +} + +INT Show_EasySetupInfo_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj; + UCHAR apidx; + struct wifi_dev *wdev; + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + wdev = &pAd->ApCfg.ApCliTab[apidx].wdev; + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + } + if (wdev->ez_driver_params.ezdev) + ez_show_information_hook((ez_dev_t *)wdev->ez_driver_params.ezdev); + else + return FALSE; + return TRUE; +} + + + + +/* + ========================================================================== + Description: + For Debug information + Change DebugLevel + Return: + TRUE if all parameters are OK, FALSE otherwise + ========================================================================== +*/ +INT Set_EasySetup_Debug_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + ULONG dbg; + POS_COOKIE pObj; + int apidx; + struct wifi_dev *wdev; + pObj = (POS_COOKIE) pAd->OS_Cookie; + + apidx = pObj->ioctl_if; + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + + dbg = simple_strtol(arg, 0, 10); + + if( dbg <= DBG_LVL_MAX) + { + if (wdev->ez_driver_params.ez_ad) + { + EZ_ADAPTER *ez_ad = wdev->ez_driver_params.ez_ad; + ez_ad->debug = dbg; + EzDebugLevel = dbg; + MTWF_PRINT("%s(): (EzDebugLevel = %d)\n", __FUNCTION__, ez_ad->debug); + } else { + MTWF_PRINT("%s(): Not EZ Interface\n", __FUNCTION__); + return FALSE; + } + } + + return TRUE; +} + + +INT Set_EasySetup_RoamTime_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT8 roam_time; + POS_COOKIE pObj; + int apidx; + struct wifi_dev *wdev; + pObj = (POS_COOKIE) pAd->OS_Cookie; + + apidx = pObj->ioctl_if; + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + roam_time = simple_strtol(arg, 0, 10); + if (roam_time == 0) + { + return FALSE; + } + + if (wdev->ez_driver_params.ez_ad) + { + EZ_ADAPTER *ez_ad = wdev->ez_driver_params.ez_ad; + ez_ad->ez_roam_time = roam_time; + } else { + MTWF_PRINT("%s(): Not EZ Interface\n", __FUNCTION__); + return FALSE; + } + return TRUE; + +} + +INT Set_EasySetup_Delay_Disconnect_Count_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + unsigned char delay_disconnect_count; + POS_COOKIE pObj; + int apidx; + struct wifi_dev *wdev; + pObj = (POS_COOKIE) pAd->OS_Cookie; + + apidx = pObj->ioctl_if; + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + delay_disconnect_count = simple_strtol(arg, 0, 10); + + if (wdev->ez_driver_params.ez_ad) + { + EZ_ADAPTER *ez_ad = wdev->ez_driver_params.ez_ad; + ez_ad->ez_delay_disconnect_count = delay_disconnect_count; + MTWF_PRINT("%s(): (ez_delay_disconnect_count = %d)\n", __FUNCTION__, delay_disconnect_count); + } else { + MTWF_PRINT("%s(): Not EZ Interface\n", __FUNCTION__); + return FALSE; + } + return TRUE; + +} + +INT Set_EasySetup_Wait_For_Info_Transfer_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT8 wait_for_info_transfer; + POS_COOKIE pObj; + int apidx; + struct wifi_dev *wdev; + pObj = (POS_COOKIE) pAd->OS_Cookie; + + apidx = pObj->ioctl_if; + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + wait_for_info_transfer = simple_strtol(arg, 0, 10); + + if (wdev->ez_driver_params.ez_ad) + { + EZ_ADAPTER *ez_ad = wdev->ez_driver_params.ez_ad; + ez_ad->ez_wait_for_info_transfer = wait_for_info_transfer; + MTWF_PRINT("%s(): (ez_wait_for_info_transfer = %d)\n", __FUNCTION__, wait_for_info_transfer); + } else { + MTWF_PRINT("%s(): Not EZ Interface\n", __FUNCTION__); + return FALSE; + } + return TRUE; + +} + +INT Set_EasySetup_WDL_Missing_Time_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT8 wdl_missing_time; + POS_COOKIE pObj; + int apidx; + struct wifi_dev *wdev; + pObj = (POS_COOKIE) pAd->OS_Cookie; + + apidx = pObj->ioctl_if; + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + wdl_missing_time = simple_strtol(arg, 0, 10); + + if (wdev->ez_driver_params.ez_ad) + { + EZ_ADAPTER *ez_ad = wdev->ez_driver_params.ez_ad; + ez_ad->ez_wdl_missing_time = wdl_missing_time; + MTWF_PRINT("%s(): (ez_wdl_missing_time = %d)\n", __FUNCTION__, wdl_missing_time); + } else { + MTWF_PRINT("%s(): Not EZ Interface\n", __FUNCTION__); + return FALSE; + } + return TRUE; + +} + +INT Set_EasySetup_Force_Connect_Bssid_Time_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 force_connect_bssid_time; + POS_COOKIE pObj; + int apidx; + struct wifi_dev *wdev; + pObj = (POS_COOKIE) pAd->OS_Cookie; + + apidx = pObj->ioctl_if; + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + force_connect_bssid_time = simple_strtol(arg, 0, 10); + + if (wdev->ez_driver_params.ez_ad) + { + EZ_ADAPTER *ez_ad = wdev->ez_driver_params.ez_ad; + ez_ad->ez_force_connect_bssid_time = force_connect_bssid_time; + MTWF_PRINT("%s(): (ez_wdl_missing_time = %d)\n", __FUNCTION__, force_connect_bssid_time); + } else { + MTWF_PRINT("%s(): Not EZ Interface\n", __FUNCTION__); + return FALSE; + } + return TRUE; + +} + +INT Set_EasySetup_Peer_Entry_Age_Out_time_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 peer_entry_age_out_time; + POS_COOKIE pObj; + int apidx; + struct wifi_dev *wdev; + pObj = (POS_COOKIE) pAd->OS_Cookie; + + apidx = pObj->ioctl_if; + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + peer_entry_age_out_time = simple_strtol(arg, 0, 10); + + if (wdev->ez_driver_params.ez_ad) + { + EZ_ADAPTER *ez_ad = wdev->ez_driver_params.ez_ad; + ez_ad->ez_peer_entry_age_out_time = peer_entry_age_out_time; + MTWF_PRINT("%s(): (ez_peer_entry_age_out_time = %d)\n", __FUNCTION__, peer_entry_age_out_time); + } else { + MTWF_PRINT("%s(): Not EZ Interface\n", __FUNCTION__); + return FALSE; + } + return TRUE; + +} + +INT Set_EasySetup_Scan_Same_Channel_Time_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT8 scan_same_channel_time; + POS_COOKIE pObj; + int apidx; + struct wifi_dev *wdev; + pObj = (POS_COOKIE) pAd->OS_Cookie; + + apidx = pObj->ioctl_if; + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + scan_same_channel_time = simple_strtol(arg, 0, 10); + + if (wdev->ez_driver_params.ez_ad) + { + EZ_ADAPTER *ez_ad = wdev->ez_driver_params.ez_ad; + ez_ad->ez_scan_same_channel_time = scan_same_channel_time; + MTWF_PRINT("%s(): (ez_scan_same_channel_time = %d)\n", __FUNCTION__, scan_same_channel_time); + } else { + MTWF_PRINT("%s(): Not EZ Interface\n", __FUNCTION__); + return FALSE; + } + return TRUE; + +} + +INT Set_EasySetup_Partial_Scan_Time_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + UINT32 partial_scan_time; + POS_COOKIE pObj; + int apidx; + struct wifi_dev *wdev; + pObj = (POS_COOKIE) pAd->OS_Cookie; + + apidx = pObj->ioctl_if; + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + partial_scan_time = simple_strtol(arg, 0, 10); + + if (wdev->ez_driver_params.ez_ad) + { + EZ_ADAPTER *ez_ad = wdev->ez_driver_params.ez_ad; + ez_ad->ez_partial_scan_time = partial_scan_time; + MTWF_PRINT("%s(): (ez_partial_scan_time = %d)\n", __FUNCTION__, partial_scan_time); + } else { + MTWF_PRINT("%s(): Not EZ Interface\n", __FUNCTION__); + return FALSE; + } + return TRUE; + +} + +INT ez_send_broadcast_deauth_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + POS_COOKIE pObj; + int apidx; + struct wifi_dev *wdev; + pObj = (POS_COOKIE) pAd->OS_Cookie; + + apidx = pObj->ioctl_if; + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + + if (wdev->ez_driver_params.ezdev) + { + ez_send_broadcast_deauth_proc_hook((ez_dev_t *)wdev->ez_driver_params.ezdev); + } else { + MTWF_PRINT("%s(): Not EZ Interface\n", __FUNCTION__); + return FALSE; + } + return TRUE; + +} + +INT Set_EasySetup_Start_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING * arg) +{ + POS_COOKIE pObj; + UCHAR apidx; + struct wifi_dev *wdev; + BOOLEAN ap_mode = FALSE; + + INT ez_enable = simple_strtol(arg, 0, 10); + + if (ez_enable != 0 && ez_enable != 1) { + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s() invalid ez_enable(%d), valid ez_enable is 0 or 1.\n", __func__, ez_enable)); + return FALSE; + } + + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) { + if (apidx >= MAX_APCLI_NUM) + return FALSE; + + wdev = &pAd->ApCfg.ApCliTab[apidx].wdev; + ap_mode = FALSE; + } else +#endif /* APCLI_SUPPORT */ + { + if (apidx >= pAd->ApCfg.BssidNum) + return FALSE; + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + ap_mode = TRUE; + } + + if (!IS_CONF_EZ_SETUP_ENABLED(wdev)) { + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s:easy-setup haven't configured by user yet, can't do this operation.\n", __func__)); + return TRUE; + } + + if (wdev) { + if (ez_enable) + ez_start(wdev, ap_mode); + else + ez_stop(wdev); + + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s() set ezstart=%d.\n", __func__, ez_enable)); + } + return TRUE; +} + +INT Set_EasySetup_GroupID_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj; + UCHAR apidx; + struct wifi_dev *wdev; + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + wdev = &pAd->ApCfg.ApCliTab[apidx].wdev; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: This command is from apcli interface now.\n", + apidx, __FUNCTION__)); + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(ra%d) %s:: This command is from ra interface now.\n", + apidx, __FUNCTION__)); + } + if (wdev->ez_driver_params.ezdev) + { + ez_set_ezgroup_id_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, arg, strlen(arg), apidx); + return ez_set_group_id_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, arg, strlen(arg), apidx); + } + return FALSE; +} + + +INT Set_EasySetup_GenGroupID_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj; + UCHAR apidx; + struct wifi_dev *wdev; + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + wdev = &pAd->ApCfg.ApCliTab[apidx].wdev; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: This command is from apcli interface now.\n", + apidx, __FUNCTION__)); + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(ra%d) %s:: This command is from ra interface now.\n", + apidx, __FUNCTION__)); + } + + if (wdev->ez_driver_params.ezdev) + { + ez_set_gen_group_id_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, arg, strlen(arg), apidx); + return ez_set_gen_group_id_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, arg, strlen(arg), apidx); + } + return FALSE; +} + + +INT Set_EasySetup_RssiThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj; + UCHAR apidx; + struct wifi_dev *wdev; + INT rssi_threshold; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + + rssi_threshold = simple_strtol(arg, 0, 10); + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + wdev = &pAd->ApCfg.ApCliTab[apidx].wdev; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: This command is from apcli interface now.\n", + apidx, __FUNCTION__)); + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(ra%d) %s:: This command is from ra interface now.\n", + apidx, __FUNCTION__)); + } + + if (wdev->ez_driver_params.ezdev) { + //ez_set_rssi_threshold_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, (-1)*rssi_threshold); + ez_dev_t *ezdev = wdev->ez_driver_params.ezdev; + ezdev->ez_security.rssi_threshold = -1*rssi_threshold; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s:: - wdev->rssi_threshold = %d.\n", + __FUNCTION__, ezdev->ez_security.rssi_threshold)); + + } else { + return FALSE; + } + + return TRUE; +} + +INT Set_EasySetup_MaxScanDelay( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj; + UCHAR apidx; + //struct _ez_security *ez_security; + UINT32 max_scan_delay; + struct wifi_dev *wdev; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + max_scan_delay = simple_strtol(arg, 0, 10); +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + wdev = &pAd->ApCfg.ApCliTab[apidx].wdev; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: This command is from apcli interface now.\n", + apidx, __FUNCTION__)); + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(ra%d) %s:: This command is from ra interface now.\n", + apidx, __FUNCTION__)); + } + + + if (wdev->ez_driver_params.ezdev) { + EZ_ADAPTER *ez_ad; + ez_ad = wdev->ez_driver_params.ez_ad; + ez_ad->max_scan_delay = max_scan_delay; + //ez_set_max_scan_delay_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, max_scan_delay); + } else { + return FALSE; + } + return TRUE; +} + +INT set_EasySetup_Api_Mode( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + UCHAR ez_api_mode; + UCHAR *macptr; + POS_COOKIE pObj; + UCHAR apidx; + struct wifi_dev *wdev; + macptr = arg; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + ez_api_mode = simple_strtol(arg, 0, 10); +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + wdev = &pAd->ApCfg.ApCliTab[apidx].wdev; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: This command is from apcli interface now.\n", + apidx, __FUNCTION__)); + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(ra%d) %s:: This command is from ra interface now.\n", + apidx, __FUNCTION__)); + } + + if (ez_api_mode > 2) + { + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s:: POSSIBLE VALUES 0/1/2, ez_api_mode = %d\n", __FUNCTION__, ez_api_mode)); + return FALSE; + } + + + if (wdev->ez_driver_params.ez_ad) { + EZ_ADAPTER *ez_ad = wdev->ez_driver_params.ez_ad; + ez_ad->ez_api_mode = ez_api_mode; + wdev->ez_driver_params.ez_api_mode = ez_api_mode; + } else { + return FALSE; + } + + return TRUE; +} + + +INT set_EasySetup_MergeGroup_proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj; + UCHAR apidx; + UCHAR *macptr; + int j; + UCHAR macAddress[6]; + UCHAR broadcast_address_string[] = "FF:FF:FF:FF:FF:FF"; + struct wifi_dev *wdev; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + wdev = &pAd->ApCfg.ApCliTab[apidx].wdev; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: This command is from apcli interface now.\n", + apidx, __FUNCTION__)); + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(ra%d) %s:: This command is from ra interface now.\n", + apidx, __FUNCTION__)); + } + + macptr = arg; + if (strlen(macptr) == 0) + { + macptr = broadcast_address_string; + } + if(strlen(macptr) != 17) /*Mac address acceptable format 01:02:03:04:05:06 length 17*/ + { + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("Incorrect Peer Address Format %s, expected is XX:XX:XX:XX:XX:XX.\n", + macptr)); + return FALSE; + } + if(strcmp(macptr,"00:00:00:00:00:00") == 0) + { + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("Incorrect Peer Address Format %s, expected is XX:XX:XX:XX:XX:XX. All zeros not allowed\n", + macptr)); + return FALSE; + } + for (j=0; jez_driver_params.ezdev) + return ez_merge_group_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, macAddress); + else + return FALSE; +} + + +INT Set_EasySetup_ForceSsid_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj; + UCHAR apidx; + INT success = FALSE; + struct wifi_dev *wdev; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + apidx = pObj->ioctl_if; + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + wdev = &pAd->ApCfg.ApCliTab[apidx].wdev; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: This command is from apcli interface now.\n", + apidx, __FUNCTION__)); + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(ra%d) %s:: This command is from ra interface now.\n", + apidx, __FUNCTION__)); + } + + if (wdev->ez_driver_params.ezdev) { + if(strlen(arg) <= MAX_LEN_OF_SSID) + { + ez_dev_t *ezdev = wdev->ez_driver_params.ezdev; + //ez_apcli_force_ssid_hook((ez_dev_t *)wdev->ez_driver_params.ezdev,(PUCHAR)arg,strlen(arg)); + { + NdisZeroMemory(ezdev->ez_security.ez_apcli_force_ssid,MAX_LEN_OF_SSID); + NdisCopyMemory(ezdev->ez_security.ez_apcli_force_ssid,(PUCHAR)arg,strlen(arg)); + ezdev->ez_security.ez_apcli_force_ssid_len = strlen(arg); + } + } + else + success = FALSE; + } else { + success = FALSE; + } + return success; +} + + +INT Set_EasySetup_ForceBssid_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + INT i; + RTMP_STRING *value; + UCHAR apidx; + POS_COOKIE pObj; + struct wifi_dev *wdev; + unsigned char forced_bssid[6]; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + apidx = pObj->ioctl_if; + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + wdev = &pAd->ApCfg.ApCliTab[apidx].wdev; + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + } + + + 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, &forced_bssid[i], 1); + } + + if(i != 6) + return FALSE; /* Invalid */ + } + + if (wdev->ez_driver_params.ezdev){ + ez_dev_t *ezdev = wdev->ez_driver_params.ezdev; + NdisCopyMemory(ezdev->ez_security.ez_apcli_force_bssid, + forced_bssid,MAC_ADDR_LEN); + //ez_set_force_bssid_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, forced_bssid); + } + return TRUE; +} + +INT Set_EasySetup_BWPushConfig(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + + UINT8 same_bw_push; + //PRTMP_ADAPTER adOthBand = NULL; + UCHAR apidx; + POS_COOKIE pObj; + struct wifi_dev *wdev; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + apidx = pObj->ioctl_if; + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + wdev = &pAd->ApCfg.ApCliTab[apidx].wdev; + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + } + + same_bw_push = simple_strtol(arg, 0, 10); + + if (wdev->ez_driver_params.ez_ad) { + EZ_ADAPTER *ez_ad = wdev->ez_driver_params.ez_ad; + ez_ad->push_bw_config = same_bw_push; + //ez_set_push_bw_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, same_bw_push); + return TRUE; + } else { + return FALSE; + } + + return TRUE; +} + +void ez_handle_action_txstatus(void *ad_obj, unsigned int wcid) +{ + MAC_TABLE_ENTRY *pEntry; + RTMP_ADAPTER *pAd = ad_obj; + + pEntry = &pAd->MacTab.Content[wcid]; + EZ_DEBUG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s(): before calling deauth for Dev = %02x-%02x-%02x-%02x-%02x-%02x\n", __FUNCTION__, + pEntry->Addr[0],pEntry->Addr[1],pEntry->Addr[2],pEntry->Addr[3],pEntry->Addr[4],pEntry->Addr[5])); + + if (pEntry->wdev->ez_driver_params.ezdev) + ez_handle_action_txstatus_hook((ez_dev_t *)pEntry->wdev->ez_driver_params.ezdev, pEntry->Addr); + +} + + + +//! Leverage form MP.1.0 CL 170364 +INT Set_EasySetup_ssid_psk_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + char *value; + char ssid[MAX_LEN_OF_SSID * 3 + 3]; + char psk[(LEN_PSK * 3) + 3]; + char EncrypType[32]; + char AuthMode[32]; + char ssid1[MAX_LEN_OF_SSID], ssid2[MAX_LEN_OF_SSID], ssid3[MAX_LEN_OF_SSID]; + char psk1[LEN_PSK + 1], psk2[LEN_PSK + 1], psk3[LEN_PSK + 1]; + char pmk1[LEN_PMK], pmk2[LEN_PMK], pmk3[LEN_PMK]; + char EncrypType1[32], EncrypType2[32]; + char AuthMode1[32], AuthMode2[32]; + int i; + struct wifi_dev *wdev; + + wdev = &pAd->ApCfg.MBSSID[0].wdev; + + memset(ssid, '\0', sizeof(ssid)); + NdisZeroMemory(psk, sizeof(psk)); + memset(EncrypType, '\0', sizeof(EncrypType)); + memset(AuthMode, '\0', sizeof(AuthMode)); + + memset(ssid1, '\0', MAX_LEN_OF_SSID); + memset(ssid2, '\0', MAX_LEN_OF_SSID); + memset(ssid3, '\0', MAX_LEN_OF_SSID); + + memset(psk1, '\0',LEN_PSK); + memset(psk2, '\0', LEN_PSK); + memset(psk3, '\0', LEN_PSK); + + memset(EncrypType1, '\0', sizeof(EncrypType1)); + memset(EncrypType2, '\0', sizeof(EncrypType2)); + + memset(AuthMode1, '\0', sizeof(AuthMode1)); + memset(AuthMode2, '\0', sizeof(AuthMode2)); + + for (i=0, value = rstrtok(arg,";"); value; value = rstrtok(NULL,";"), i++) + { + if (i == 0) + { + //NdisZeroMemory(ssid,MAX_LEN_OF_SSID); + memset(ssid, '\0', MAX_LEN_OF_SSID); + NdisCopyMemory(ssid,value,strlen(value)); + ssid[strlen(value)] = '\0'; + } + else if(i==1) + { + NdisZeroMemory(psk,LEN_PSK + 1); + NdisCopyMemory(psk, value,strlen(value)); + psk[strlen(value)] = '\0'; + } + else if(i == 2) + { + //NdisZeroMemory(EncrypType, 15); + NdisCopyMemory(EncrypType, value,strlen(value)); + EncrypType[strlen(value)] = '\0'; + } + else if(i == 3) + { + //NdisZeroMemory(AuthMode, 27); + NdisCopyMemory(AuthMode, value,strlen(value)); + AuthMode[strlen(value)] = '\0'; + } + + if (i > 3) + { + break; + } + } +// ssid_len = strlen(ssid); + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("New SSID = %s\n SSID_LEN = %d\n New PSK = %s\n", ssid, (int)strlen(ssid),psk)); + + for (i=0, value = rstrtok(ssid,":"); value; value = rstrtok(NULL,":"), i++) + { + if (i == 0) + { + memset(ssid1, '\0', MAX_LEN_OF_SSID); + NdisCopyMemory(ssid1,value,strlen(value)); + } else if (i == 1){ + memset(ssid2, '\0', MAX_LEN_OF_SSID); + NdisCopyMemory(ssid2,value,strlen(value)); + } else if (i == 2){ + memset(ssid3, '\0', MAX_LEN_OF_SSID); + NdisCopyMemory(ssid3,value,strlen(value)); + } + } + + for (i=0, value = rstrtok(psk,":"); value; value = rstrtok(NULL,":"), i++) + { + if (i == 0) + { + NdisZeroMemory(psk1,LEN_PSK + 1); + NdisCopyMemory(psk1, value,strlen(value)); + psk1[strlen(value)] = '\0'; + } else if (i == 1){ + NdisZeroMemory(psk2,LEN_PSK + 1); + NdisCopyMemory(psk2, value,strlen(value)); + psk2[strlen(value)] = '\0'; + } else if (i == 2){ + NdisZeroMemory(psk3,LEN_PSK + 1); + NdisCopyMemory(psk3, value,strlen(value)); + psk3[strlen(value)] = '\0'; + } + } + + for (i=0, value = rstrtok(EncrypType,":"); value; value = rstrtok(NULL,":"), i++) + { + if (i == 0) + { + //memset(EncrypType1, '\0', 7); + NdisCopyMemory(EncrypType1,value,strlen(value)); + } else if (i == 1){ + //memset(EncrypType2, '\0', 7); + NdisCopyMemory(EncrypType2,value,strlen(value)); + } + } + + for (i=0, value = rstrtok(AuthMode,":"); value; value = rstrtok(NULL,":"), i++) + { + if (i == 0) + { + //memset(AuthMode1, '\0', 7); + NdisCopyMemory(AuthMode1,value,strlen(value)); + } else if (i == 1){ + //memset(AuthMode2, '\0', 7); + NdisCopyMemory(AuthMode2,value,strlen(value)); + } + } + + //SetWPAPSKKey(pAd, psk, strlen(psk), ssid, strlen(ssid), pmk); + RT_CfgSetWPAPSKKey(pAd, psk1, strlen(psk1), ssid1, strlen(ssid1), pmk1); + RT_CfgSetWPAPSKKey(pAd, psk2, strlen(psk2), ssid2, strlen(ssid2), pmk2); + RT_CfgSetWPAPSKKey(pAd, psk3, strlen(psk3), ssid3, strlen(ssid3), pmk3); + + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("New SSID1 = %s\n SSID_LEN1 = %d\n New PSK1 = %s\n", ssid1, (int)strlen(ssid1),psk1)); + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("New SSID2 = %s\n SSID_LEN2 = %d\n New PSK2 = %s\n", ssid2, (int)strlen(ssid2),psk2)); + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("New SSID3 = %s\n SSID_LEN3 = %d\n New PSK3 = %s\n", ssid3, (int)strlen(ssid3),psk3)); + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("New Encr1 = %s\n encr_LEN1 = %d\n New encr2 = %s\n encr_LEN2 = %d\n", EncrypType1, (int)strlen(EncrypType1), EncrypType2, (int)strlen(EncrypType2))); + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("New Encr1 = %s\n encr_LEN1 = %d\n New encr2 = %s\n encr_LEN2 = %d\n", AuthMode1, (int)strlen(AuthMode1), AuthMode2, (int)strlen(AuthMode2))); + + + if (wdev->ez_driver_params.ezdev) + { + ez_update_ssid_psk_msg_t update_ssid_psk_msg; + + NdisZeroMemory(&update_ssid_psk_msg, sizeof(update_ssid_psk_msg)); + + NdisCopyMemory(update_ssid_psk_msg.ssid1,ssid1,strlen(ssid1)); + NdisCopyMemory(update_ssid_psk_msg.ssid2,ssid2,strlen(ssid2)); + NdisCopyMemory(update_ssid_psk_msg.ssid3,ssid3,strlen(ssid3)); + + NdisCopyMemory(update_ssid_psk_msg.psk1,psk1,strlen(psk1)); + NdisCopyMemory(update_ssid_psk_msg.psk2,psk2,strlen(psk2)); + NdisCopyMemory(update_ssid_psk_msg.psk3,psk3,strlen(psk3)); + + + NdisCopyMemory(update_ssid_psk_msg.pmk1,pmk1,sizeof(pmk1)); + NdisCopyMemory(update_ssid_psk_msg.pmk2,pmk2,sizeof(pmk2)); + NdisCopyMemory(update_ssid_psk_msg.pmk3,pmk3,sizeof(pmk3)); + + NdisCopyMemory(update_ssid_psk_msg.EncrypType1,EncrypType1,strlen(EncrypType1)); + NdisCopyMemory(update_ssid_psk_msg.EncrypType2,EncrypType2,strlen(EncrypType2)); + + NdisCopyMemory(update_ssid_psk_msg.AuthMode1,AuthMode1,strlen(AuthMode1)); + NdisCopyMemory(update_ssid_psk_msg.AuthMode2,AuthMode2,strlen(AuthMode2)); + + EzMlmeEnqueue(pAd, EZ_STATE_MACHINE, EZ_UPDATE_SSID_PSK_REQ, sizeof(update_ssid_psk_msg), &update_ssid_psk_msg, (ULONG)wdev); + } else { + return FALSE; + } + + + return TRUE; +} + + +//! Leverage form MP.1.0 CL 170364 +INT Set_EasySetup_conf_ssid_psk_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + char *value; + char ssid[3*MAX_LEN_OF_SSID + 3]; + char psk[3*LEN_PSK + 3]; + char EncrypType[32]; + char AuthMode[32]; + unsigned char ssid_len, psk_len, EncrypType_len, AuthMode_len, len; + web_conf_info_t conf_info; + int i; + + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("arg %s\n", arg)); + for (i=0, value = rstrtok(arg,";"); value; value = rstrtok(NULL,";"), i++) + { + if (i == 0) + { + memset(ssid, '\0', 3*MAX_LEN_OF_SSID + 3); + NdisCopyMemory(ssid,value,strlen(value)); + ssid[strlen(value)] = '\0'; + } + else if(i == 1) + { + NdisZeroMemory(psk, 3*LEN_PSK + 3); + NdisCopyMemory(psk, value,strlen(value)); + psk[strlen(value)] = '\0'; + } + else if(i == 2) + { + NdisZeroMemory(EncrypType, sizeof(EncrypType)); + NdisCopyMemory(EncrypType, value,strlen(value)); + EncrypType[strlen(value)] = '\0'; + } + else if(i == 3) + { + NdisZeroMemory(AuthMode, sizeof(AuthMode)); + NdisCopyMemory(AuthMode, value,strlen(value)); + AuthMode[strlen(value)] = '\0'; + } + + if (i > 3) + { + break; + } + } + + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("ssid %s\n", ssid)); + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("psk %s\n", psk)); + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("EncrypType %s\n", EncrypType)); + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("AuthMode %s\n", AuthMode)); + + + ssid_len = strlen(ssid); + psk_len = strlen(psk); + EncrypType_len = strlen(EncrypType); + AuthMode_len = strlen(AuthMode); + conf_info.data_len = 1 + ssid_len + 1 + psk_len + 1 + EncrypType_len + 1 + AuthMode_len; + len = 0; + memcpy(&conf_info.data[0] + len, &ssid_len, 1); + len += 1; + memcpy(&conf_info.data[0] + len, ssid, ssid_len); + len += ssid_len; + memcpy(&conf_info.data[0] + len , &psk_len, 1); + len += 1; + memcpy(&conf_info.data[0] + len, psk, psk_len); + len += psk_len; + memcpy(&conf_info.data[0] + len , &EncrypType_len, 1); + len += 1; + memcpy(&conf_info.data[0] + len , EncrypType, EncrypType_len); + len += EncrypType_len; + memcpy(&conf_info.data[0] + len , &AuthMode_len, 1); + len += 1; + memcpy(&conf_info.data[0] + len , AuthMode, AuthMode_len); + + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("conf_info.data_len %d\n", conf_info.data_len)); + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("conf_info.data %s\n", conf_info.data)); + { +#ifdef SYSTEM_LOG_SUPPORT + //RTMPSendWirelessEvent(pAd, OID_WH_EZ_MAN_CONF_EVENT, NULL, wdev->wdev_idx, 0); +#else /* SYSTEM_LOG_SUPPORT */ + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, OID_WH_EZ_MAN_CONF_EVENT, + NULL, (void *)&conf_info, sizeof(web_conf_info_t)); +#endif /* !SYSTEM_LOG_SUPPORT */ + + } + return TRUE; +} + + +void ez_apcli_link_down( + void *ad_obj, + void *apcli_obj, + unsigned char if_idx) +{ + RTMP_ADAPTER *ad; + APCLI_STRUCT *apcli_entry; + unsigned char wcid; + struct wifi_dev *ap_wdev; + + ad = (RTMP_ADAPTER *)ad_obj; + apcli_entry = (APCLI_STRUCT *)apcli_obj; + wcid = apcli_entry->MacTabWCID; + ap_wdev = &ad->ApCfg.MBSSID[if_idx].wdev; + if(ap_wdev) + { + if (IS_EZ_SETUP_ENABLED(&apcli_entry->wdev) + && (wcid < MAX_LEN_OF_MAC_TABLE)) { + STA_TR_ENTRY *tr_entry; + tr_entry = &ad->MacTab.tr_entry[wcid]; + if (tr_entry->PortSecured == WPA_802_1X_PORT_SECURED) { + + /* + Clear easy setup flag and CfgBssid for roaming. + */ + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("(%s) ApCli interface[%d] Clear easy setup flag and CfgBssid for roaming.\n", + __FUNCTION__, if_idx)); + apcli_entry->MlmeAux.support_easy_setup = FALSE; + NdisZeroMemory(&apcli_entry->CfgApCliBssid[0], MAC_ADDR_LEN); + + if(apcli_entry->wdev.ez_driver_params.ezdev) + ez_apcli_link_down_hook((ez_dev_t *)apcli_entry->wdev.ez_driver_params.ezdev,apcli_entry->Disconnect_Sub_Reason); + +#ifdef SYSTEM_LOG_SUPPORT + RTMPSendWirelessEvent(ad, IW_WH_EZ_MY_APCLI_DISCONNECTED, NULL, ap_wdev->wdev_idx, 0); +#else /* SYSTEM_LOG_SUPPORT */ + RtmpOSWrielessEventSend(ap_wdev->if_dev, RT_WLAN_EVENT_CUSTOM, IW_WH_EZ_MY_APCLI_DISCONNECTED, + NULL, NULL, 0); +#endif /* !SYSTEM_LOG_SUPPORT */ + } + } +#ifdef IF_UP_DOWN + apcli_entry->wdev.ez_driver_params.ez_apcli_peer_ap_config_cnt = 0; +#endif + } +} + + +BOOLEAN ez_update_connection_permission( + void *ad_obj, + struct wifi_dev *wdev, + enum EZ_CONN_ACTION action) +{ + if (wdev->ez_driver_params.ezdev) + { + return ez_update_connection_permission_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, action); + } + + return TRUE; +} + + +BOOLEAN ez_is_connection_allowed(struct wifi_dev *wdev) +{ + if (wdev->ez_driver_params.ezdev){ + ez_dev_t *ezdev = wdev->ez_driver_params.ezdev; +#ifdef EZ_API_SUPPORT + if (ezdev->ez_security.ez_api_mode == CONNECTION_OFFLOAD) + return TRUE; +#endif + +#ifdef IF_UP_DOWN + if (!ez_all_intf_up(ezdev->ez_ad)) + return FALSE; +#endif + return ezdev->ez_security.ez_is_connection_allowed; + }else + return TRUE; + +} + +BOOLEAN ez_probe_rsp_join_action(void *ad_obj, void *wdev_obj, OUT BCN_IE_LIST *ie_list, unsigned long Bssidx) +{ + struct wifi_dev *wdev; + wdev = (struct wifi_dev *)wdev_obj; + + if (wdev->ez_driver_params.ezdev) + return ez_probe_rsp_join_action_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, ie_list->vendor_ie.beacon_info.network_weight); + else + return TRUE; +} + +void ez_update_connection(void *ad_obj, void *wdev_obj) +{ + struct wifi_dev *wdev; + wdev = (struct wifi_dev *)wdev_obj; + + if (wdev->ez_driver_params.ezdev) + { + ez_update_connection_hook((ez_dev_t *)wdev->ez_driver_params.ezdev); + } +} + + +void ez_handle_pairmsg4(void *ad_obj, IN MAC_TABLE_ENTRY *pEntry) +{ + RTMP_ADAPTER *pAd = ad_obj; + struct wifi_dev *wdev = pEntry->wdev; + ez_dev_t *ezdev; + APCLI_STRUCT *apcli_entry = &pAd->ApCfg.ApCliTab[pEntry->wdev->func_idx]; + + + apcli_entry->MlmeAux.attempted_candidate_index = EZ_INDEX_NOT_FOUND; + + if (wdev->ez_driver_params.ezdev) + { + ezdev = wdev->ez_driver_params.ezdev; + + NdisCopyMemory(ezdev->ez_security.this_band_info.shared_info.ssid,apcli_entry->Ssid,apcli_entry->SsidLen); + NdisCopyMemory(ezdev->ez_security.this_band_info.pmk, apcli_entry->PMK,PMK_LEN); + + ezdev->ez_security.this_band_info.shared_info.ssid_len = apcli_entry->SsidLen; + wdev->ez_driver_params.ez_wps_reconnect = FALSE; + + printk("%s, %d\n", __FUNCTION__, __LINE__); + ez_handle_pairmsg4_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, pEntry->Addr); + } + + +} + + + +void ez_roam(struct wifi_dev *wdev,BSS_ENTRY *pBssEntry) +{ + if (wdev->ez_driver_params.ezdev) + { + ez_roam_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, pBssEntry->support_easy_setup, &pBssEntry->beacon_info, + pBssEntry->Bssid, pBssEntry->Channel); + } + +} + + +ULONG +BssTableSearchWithBssId( + IN BSS_TABLE *Tab, + IN PUCHAR Bssid, + IN UCHAR Channel) +{ + UCHAR i; + UINT BssNr = Tab->BssNr; + + for (i = 0; i < BssNr; i++) + { + if ((i < MAX_LEN_OF_BSS_TABLE) && + MAC_ADDR_EQUAL(&(Tab->BssEntry[i].Bssid), Bssid)) + { + return i; + } + } + return (ULONG)BSS_NOT_FOUND; +} + +BSS_ENTRY *ez_find_roam_candidate(void * ad_obj, unsigned char *bssid, struct wifi_dev *wdev) +{ + PRTMP_ADAPTER pAd = ad_obj; + ULONG bss_idx; +// BSS_ENTRY * pBssEntry = NULL; + //if (IS_SINGLE_CHIP_DBDC(pAd)) + { + bss_idx = BssTableSearchWithBssId(&pAd->ScanTab,bssid,0); + } + if (bss_idx == BSS_NOT_FOUND) + { + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("ez_find_roam_candidate: Roam entry not found\n")); + return NULL; + } + else + { + return &pAd->ScanTab.BssEntry[bss_idx]; + } + +} + + + +INT Set_EasySetup_RoamBssid_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + INT i; + + RTMP_STRING *value; + UCHAR ifIndex; + POS_COOKIE pObj; + BSS_ENTRY *pBssEntry = NULL; + struct wifi_dev *wdev; + UCHAR roam_bssid[6]; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + + if (pObj->ioctl_if_type != INT_APCLI) + return FALSE; + + ifIndex = pObj->ioctl_if; + + wdev = &pAd->ApCfg.ApCliTab[ifIndex].wdev; + 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, &roam_bssid[i], 1); + } + + if(i != 6) + return FALSE; /* Invalid */ + } + + + /*if connection not already ongoing, then initiate a connection.*/ + pBssEntry = ez_find_roam_candidate(pAd,roam_bssid,&pAd->ApCfg.ApCliTab[ifIndex].wdev ); + if (pBssEntry!= NULL){ +//! Levarage from MP1.0 CL#170063 + if (wdev->ez_driver_params.ezdev) { + if (ez_set_roam_bssid_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, roam_bssid)) + EzMlmeEnqueue(pAd, EZ_STATE_MACHINE, EZ_ROAM_REQ, 0, NULL, (ULONG)&pAd->ApCfg.ApCliTab[ifIndex].wdev); + return TRUE; + } + } + else { + if (wdev->ez_driver_params.ezdev) + ez_reset_roam_bssid_hook((ez_dev_t *)wdev->ez_driver_params.ezdev); + + return FALSE; + } + return FALSE; +} + + +void ez_prepare_security_key( + void *wdev_obj, + unsigned char *peer_addr, + unsigned char authenticator) +{ + struct wifi_dev *wdev = wdev_obj; + wdev = (struct wifi_dev *)wdev_obj; + + + if (wdev->ez_driver_params.ezdev) + { + ez_prepare_security_key_hook((ez_dev_t *)wdev->ez_driver_params.ezdev,peer_addr,authenticator); + } else { + ASSERT(FALSE); + } +} + +BOOLEAN ez_is_channel_same(struct wifi_dev *wdev) +{ + PRTMP_ADAPTER pAd = wdev->sys_handle; + struct wifi_dev *apcli_wdev = &pAd->ApCfg.ApCliTab[wdev->func_idx].wdev; + channel_info_t *channel_info; + ez_dev_t *ezdev = wdev->ez_driver_params.ezdev; + + if (wdev->ez_driver_params.ezdev){ + channel_info = &ezdev->ez_security.this_band_info.shared_info.channel_info; + } else { + return FALSE; + } + + if ((pAd->CommonCfg.Channel == channel_info->channel) && +#ifdef EZ_PUSH_BW_SUPPORT + (ezdev->ez_security.ap_did_fallback) && + (ez_driver_ops_wlan_config_get_ht_bw_mt7603(wdev->ez_driver_params.ezdev) == channel_info->ht_bw && ez_driver_ops_wlan_config_get_ht_bw_mt7603(apcli_wdev->ez_driver_params.ezdev) == channel_info->ht_bw) && + (ez_driver_ops_wlan_config_get_vht_bw_mt7603(wdev->ez_driver_params.ezdev) == channel_info->vht_bw && ez_driver_ops_wlan_config_get_vht_bw_mt7603(apcli_wdev) == channel_info->vht_bw) && +#endif + (ez_driver_ops_wlan_config_get_ext_cha_mt7603(wdev->ez_driver_params.ezdev) == channel_info->extcha && ez_driver_ops_wlan_config_get_ext_cha_mt7603(apcli_wdev->ez_driver_params.ezdev) == channel_info->extcha) + ){ +#if (defined(DOT11_N_SUPPORT) && defined(DOT11N_DRAFT3)) + if(ezdev->ez_security.ap_did_fallback){ + if(ezdev->ez_security.fallback_channel == channel_info->channel){ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("\nez_is_channel_same: Restoring ap to fallback mode\n")); + ez_driver_ops_wlan_operate_set_ht_bw_mt7603(wdev->ez_driver_params.ezdev, HT_BW_20); + ez_driver_ops_wlan_operate_set_ext_cha_mt7603(wdev->ez_driver_params.ezdev, EXTCHA_NONE); + } + } +#endif + return TRUE; + + } + else + return FALSE; +} + +void ez_process_action_frame( + void *ad_obj, + void *elem_obj) +{ + + RTMP_ADAPTER *ad = (RTMP_ADAPTER *)ad_obj; + MLME_QUEUE_ELEM *elem; + MAC_TABLE_ENTRY *entry; + struct wifi_dev *wdev; + elem = (MLME_QUEUE_ELEM *)elem_obj; + entry = &ad->MacTab.Content[elem->Wcid]; + wdev = entry->wdev; + + if (wdev->ez_driver_params.ezdev) + ez_process_action_frame_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, + entry->Addr,elem->Msg,elem->MsgLen); +} + + +unsigned char ez_set_driver_group_id( + ez_driver_params_t *ez_driver_param, + unsigned char *ez_group_id, + unsigned int ez_group_id_len, + unsigned char inf_idx) +{ + int i; + if (ez_driver_param->ez_group_id_len != 0) { + os_free_mem(NULL, ez_driver_param->ez_group_id); + ez_driver_param->ez_group_id_len = 0; + } + ez_driver_param->ez_group_id_len = ez_group_id_len; + os_alloc_mem(NULL, &ez_driver_param->ez_group_id, ez_group_id_len); + if (ez_driver_param->ez_group_id) { + NdisZeroMemory(ez_driver_param->ez_group_id, ez_group_id_len); + NdisCopyMemory(ez_driver_param->ez_group_id, ez_group_id, ez_group_id_len); + + ez_driver_param->ez_group_id_len = ez_group_id_len; + ez_driver_param->group_id_len = ez_group_id_len; + ez_driver_param->group_id = ez_driver_param->ez_group_id; + + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("IF(ra%d) %s :: group id \n", + inf_idx, __FUNCTION__)); + for (i = 0; i < ez_driver_param->ez_group_id_len; i++) { + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%02x ", ez_driver_param->ez_group_id[i])); + } + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("\n")); + return TRUE; + } + else { + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("IF(ra%d) %s::Memory alloc fails\n\n", + inf_idx, __FUNCTION__)); + ez_driver_param->ez_group_id_len = 0; + return FALSE; + } +} + + +unsigned char ez_set_gen_driver_group_id( + ez_driver_params_t *ez_driver_param, + unsigned char *gen_group_id, + unsigned int gen_group_id_len, + unsigned char inf_idx) +{ + int i; + UCHAR hash_data[LEN_PMK]; + + if (ez_driver_param->gen_group_id_len != 0) + { + os_free_mem(NULL, ez_driver_param->gen_group_id); + ez_driver_param->gen_group_id_len = 0; + } + + NdisZeroMemory(&hash_data[0], LEN_PMK); + RT_SHA256(gen_group_id, gen_group_id_len, &hash_data[0]); + ez_set_driver_group_id(ez_driver_param, &hash_data[0], LEN_PMK, inf_idx); + + ez_driver_param->gen_group_id_len = gen_group_id_len; + os_alloc_mem(NULL, &ez_driver_param->gen_group_id, gen_group_id_len); + + if (ez_driver_param->gen_group_id) + { + NdisZeroMemory(ez_driver_param->gen_group_id, ez_driver_param->gen_group_id_len); + NdisCopyMemory(ez_driver_param->gen_group_id, gen_group_id, ez_driver_param->gen_group_id_len); + MTWF_LOG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("IF(ra%d) %s :: group id \n", + inf_idx, __FUNCTION__)); + for (i = 0; i < ez_driver_param->gen_group_id_len; i++) { + MTWF_LOG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%02x ", ez_driver_param->gen_group_id[i])); + } + MTWF_LOG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("\n")); + return TRUE; + } + else + { + MTWF_LOG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("IF(ra%d) %s::Memory alloc fails\n\n", + inf_idx, __FUNCTION__)); + ez_driver_param->gen_group_id_len = 0; + return FALSE; + } +} + +unsigned char ez_set_driver_open_group_id( + ez_driver_params_t *ez_driver_param, + unsigned char *open_group_id, + unsigned int open_group_id_len, + unsigned char inf_idx) +{ + int i; + if (ez_driver_param->open_group_id_len != 0) { + NdisZeroMemory(ez_driver_param->open_group_id,OPEN_GROUP_MAX_LEN); + ez_driver_param->open_group_id_len = 0; + } + if(open_group_id_len > OPEN_GROUP_MAX_LEN) + return FALSE; + ez_driver_param->open_group_id_len = open_group_id_len; + //EZ_MEM_ALLOC(NULL, &ez_security->group_id, ez_security->group_id_len); + NdisZeroMemory(ez_driver_param->open_group_id, OPEN_GROUP_MAX_LEN); + NdisCopyMemory(ez_driver_param->open_group_id, open_group_id, ez_driver_param->open_group_id_len); + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("IF(ra%d) %s :: open_group id \n", + inf_idx, __FUNCTION__)); + for (i = 0; i < ez_driver_param->open_group_id_len; i++) { + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%02x ", ez_driver_param->open_group_id[i])); + } + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("\n")); + return TRUE; +} + + +void convert_pmk_string_to_hex(char *sys_pmk_string, char *sys_pmk) +{ + int ret; + unsigned char nibble; + + for (ret = 0; ret < 64; ret++) + { + nibble = sys_pmk_string[ret]; + if ((nibble <= '9')) + { + nibble = nibble - '0'; + } + else if (nibble < 'a') + { + nibble = nibble - 'A' + 10; + } else { + nibble = nibble - 'a' + 10; + } + if (ret % 2) + { + sys_pmk[ret/2] |= nibble; + } + else + { + sys_pmk[ret/2] = nibble << 4; + } + } + +} + +void ez_read_parms_from_file( + void *ad_obj, + char *tmpbuf, + char *buffer) +{ + int i; + RTMP_STRING *macptr; + RTMP_ADAPTER *ad; + + ad = (RTMP_ADAPTER *)ad_obj; + if(RTMPGetKeyParameter("EzEnable", tmpbuf, 10, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + INT ez_enable = simple_strtol(macptr, 0, 10); + + if (i >= ad->ApCfg.BssidNum) + break; + + if (ez_enable == 0) + { + ad->ApCfg.MBSSID[i].wdev.ez_driver_params.enable_easy_setup = FALSE; + } + else + { + ad->ApCfg.MBSSID[i].wdev.ez_driver_params.enable_easy_setup = TRUE; + } + + EZ_DEBUG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("I/F(ra%d) EzEnable=%d\n", + i, ad->ApCfg.MBSSID[i].wdev.ez_driver_params.enable_easy_setup)); + } + } + if(RTMPGetKeyParameter("EtherTrafficBand", tmpbuf, 10, buffer, TRUE)) + { + INT default_group_data_band = 0; + + macptr = rstrtok(tmpbuf,";"); + if(macptr) + default_group_data_band = simple_strtol(macptr, 0, 10); + + + if (default_group_data_band == 0) + { + ad->ApCfg.MBSSID[MAIN_MBSSID].wdev.ez_driver_params.default_group_data_band = EZ_DROP_GROUP_DATA_BAND24G; + } + else + { + EZ_DEBUG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("===============DROP BAND 5G\n")); + ad->ApCfg.MBSSID[MAIN_MBSSID].wdev.ez_driver_params.default_group_data_band = EZ_DROP_GROUP_DATA_BAND5G; + } + } + + if(RTMPGetKeyParameter("EzGroupID", tmpbuf, 256, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + ez_driver_params_t *ez_driver_param; + + if (i >= ad->ApCfg.BssidNum) + break; + ez_driver_param = &ad->ApCfg.MBSSID[i].wdev.ez_driver_params; + + ez_set_driver_group_id(ez_driver_param, macptr, strlen(macptr), i); + } + } + if(RTMPGetKeyParameter("EzGenGroupID", tmpbuf, 256, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + ez_driver_params_t *ez_driver_param; + + if (i >= ad->ApCfg.BssidNum) + break; + + ez_driver_param = &ad->ApCfg.MBSSID[i].wdev.ez_driver_params; + ez_set_gen_driver_group_id(ez_driver_param, macptr, strlen(macptr), i); + } + } + if(RTMPGetKeyParameter("EzOpenGroupID", tmpbuf, 256, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + ez_driver_params_t *ez_driver_param; + + if (i >= ad->ApCfg.BssidNum) + break; + ez_driver_param = &ad->ApCfg.MBSSID[i].wdev.ez_driver_params; + ez_set_driver_open_group_id(ez_driver_param, macptr, strlen(macptr), i); + } + } +#ifdef EZ_API_SUPPORT + if(RTMPGetKeyParameter("EzApiMode", tmpbuf, 256, buffer, TRUE)) + { + //for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + + INT ez_api_mode = 0; + EZ_ADAPTER *ez_ad = ad->ez_ad; + macptr = rstrtok(tmpbuf,";"); + if(macptr) + ez_api_mode = simple_strtol(macptr, 0, 10); + + ez_ad->ez_api_mode = ez_api_mode; + //break; + } + } +#endif +#ifdef EZ_PUSH_BW_SUPPORT + if(RTMPGetKeyParameter("EzPushBw", tmpbuf, 10, buffer, TRUE)) + { + INT ez_push_bw = 0; + EZ_ADAPTER *ez_ad = ad->ez_ad; + + macptr = rstrtok(tmpbuf,";"); + if(macptr) + ez_push_bw = simple_strtol(macptr, 0, 10); + + if (ez_push_bw == 0) + { + ez_ad->push_bw_config = FALSE; + } + else + { + ez_ad->push_bw_config = TRUE; + } + + EZ_DEBUG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("EzPushBw=%d\n", + ez_ad->push_bw_config)); + } +#endif +#ifdef APCLI_SUPPORT + if(RTMPGetKeyParameter("ApCliEzEnable", tmpbuf, 10, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + INT ez_enable = simple_strtol(macptr, 0, 10); + + if (i >= MAX_APCLI_NUM) + break; + + if (ez_enable == 0) + { + ad->ApCfg.ApCliTab[i].wdev.ez_driver_params.enable_easy_setup = FALSE; + } + else + { + ad->ApCfg.ApCliTab[i].wdev.ez_driver_params.enable_easy_setup = TRUE; + } + + EZ_DEBUG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("I/F(apcli%d) ApCliEzEnable=%d\n", + i, ad->ApCfg.ApCliTab[i].wdev.ez_driver_params.enable_easy_setup)); + } + } + + if(RTMPGetKeyParameter("ApCliEzGroupID", tmpbuf, 256, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + ez_driver_params_t *ez_driver_param; + + if (i >= MAX_APCLI_NUM) + break; + + ez_driver_param = &ad->ApCfg.ApCliTab[i].wdev.ez_driver_params; + ez_set_driver_group_id(ez_driver_param, macptr, strlen(macptr), i); + //ez_set_group_id(ez_security, macptr, strlen(macptr), i); + } + } + if(RTMPGetKeyParameter("ApCliEzGenGroupID", tmpbuf, 256, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + ez_driver_params_t *ez_driver_param; + + if (i >= MAX_APCLI_NUM) + break; + + ez_driver_param = &ad->ApCfg.ApCliTab[i].wdev.ez_driver_params; + + ez_set_gen_driver_group_id(ez_driver_param, macptr, strlen(macptr), i); + } + } + + if(RTMPGetKeyParameter("ApCliEzOpenGroupID", tmpbuf, 256, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + ez_driver_params_t *ez_driver_param; + + if (i >= MAX_APCLI_NUM) + break; + + ez_driver_param = &ad->ApCfg.ApCliTab[i].wdev.ez_driver_params; + ez_set_driver_open_group_id(ez_driver_param, macptr, strlen(macptr), i); + } + } + + if(RTMPGetKeyParameter("ApCliEzRssiThreshold", tmpbuf, 10, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + INT rssi_threshold = simple_strtol(macptr, 0, 10); + + if (i >= MAX_APCLI_NUM) + break; + + ad->ApCfg.ApCliTab[i].wdev.ez_driver_params.rssi_threshold = (CHAR)(-1)*rssi_threshold; + + EZ_DEBUG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("I/F(apcli%d) rssi_threshold=%d\n", + i, ad->ApCfg.ApCliTab[i].wdev.ez_driver_params.rssi_threshold)); + } + } +#endif /* APCLI_SUPPORT */ + + if(RTMPGetKeyParameter("EzDefaultSsid", tmpbuf, 256, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + + ad->ApCfg.MBSSID[i].wdev.ez_driver_params.default_ssid_len = strlen(macptr); + NdisZeroMemory(ad->ApCfg.MBSSID[i].wdev.ez_driver_params.default_ssid,MAX_LEN_OF_SSID); + NdisCopyMemory(ad->ApCfg.MBSSID[i].wdev.ez_driver_params.default_ssid,macptr, strlen(macptr)); + + NdisZeroMemory(ad->ApCfg.ApCliTab[i].wdev.ez_driver_params.default_ssid,MAX_LEN_OF_SSID); + ad->ApCfg.ApCliTab[i].wdev.ez_driver_params.default_ssid_len = strlen(macptr); + NdisCopyMemory(ad->ApCfg.ApCliTab[i].wdev.ez_driver_params.default_ssid,macptr, strlen(macptr)); + + } + } + if(RTMPGetKeyParameter("EzDefaultPmk", tmpbuf, 256, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + convert_pmk_string_to_hex(macptr, ad->ApCfg.MBSSID[i].wdev.ez_driver_params.default_pmk); + NdisCopyMemory(ad->ApCfg.ApCliTab[i].wdev.ez_driver_params.default_pmk,ad->ApCfg.MBSSID[i].wdev.ez_driver_params.default_pmk,PMK_LEN); + } + } + + if(RTMPGetKeyParameter("EzDefaultPmkValid", tmpbuf, 256, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + + ad->ApCfg.MBSSID[i].wdev.ez_driver_params.default_pmk_valid = simple_strtol(macptr,0, 10); + ad->ApCfg.ApCliTab[i].wdev.ez_driver_params.default_pmk_valid = simple_strtol(macptr, 0 , 10); +//! Levarage from MP1.0 CL 170210 + + } + } +//! Levarage from MP1.0 CL 170210 +#ifdef EZ_REGROUP_SUPPORT // add for multiprofile too? + if(RTMPGetKeyParameter("RegroupSupport", tmpbuf, 10, buffer, TRUE)) + { + for (i = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), i++) + { + INT regrp_supp = simple_strtol(macptr, 0, 10); + + if (i >= ad->ApCfg.BssidNum) + break; + + if (regrp_supp == 0) + { + ad->ApCfg.MBSSID[i].wdev.ez_driver_params.en_regrp_supp = FALSE; + ad->ApCfg.ApCliTab[i].wdev.ez_driver_params.en_regrp_supp = FALSE; + } + else + { + ad->ApCfg.MBSSID[i].wdev.ez_driver_params.en_regrp_supp = TRUE; + ad->ApCfg.ApCliTab[i].wdev.ez_driver_params.en_regrp_supp = TRUE; + } + + EZ_DEBUG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("I/F(ra%d) RegroupSupport=%d\n", + i, ad->ApCfg.MBSSID[i].wdev.ez_driver_params.en_regrp_supp)); + } + + } +#endif +#ifdef IF_UP_DOWN + if (RTMPGetKeyParameter("EzIntfCnt", tmpbuf, 10, buffer, TRUE)) { + for (i = 0, macptr = rstrtok(tmpbuf, ";"); macptr; macptr = rstrtok(NULL, ";"), i++) { + UINT intf_cnt_ap, intf_cnt_cli; + RTMP_STRING *macptr1 = NULL; + + if (i >= ad->ApCfg.BssidNum) + break; + macptr1 = rstrtok(macptr, ":"); + intf_cnt_ap = simple_strtol(macptr1, 0, 10); + macptr1 = rstrtok(macptr, ":"); + intf_cnt_cli = simple_strtol(macptr1, 0, 10); + + ad->ApCfg.MBSSID[i].wdev.ez_driver_params.ez_intf_count_config_ap = intf_cnt_ap; + ad->ApCfg.MBSSID[i].wdev.ez_driver_params.ez_intf_count_config_cli = intf_cnt_cli; + + EZ_DEBUG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("I/F(ra%d) IntfCnt=%d:%d\n", + i, ad->ApCfg.MBSSID[i].wdev.ez_driver_params.ez_intf_count_config_ap, + ad->ApCfg.MBSSID[i].wdev.ez_driver_params.ez_intf_count_config_cli)); + } + } +#endif +} + +int ez_internet_msg_handle(void *ad_obj, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + RTMP_ADAPTER *pAd; + int status; + POS_COOKIE pObj; + int apidx; + struct wifi_dev *wdev; + int Status; + p_internet_command_t p_internet_command; + p_internet_command = NULL; + status = NDIS_STATUS_SUCCESS; + pAd = (RTMP_ADAPTER *)ad_obj; + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + + os_alloc_mem(NULL, (UCHAR **)&p_internet_command, wrq->u.data.length); + + if (p_internet_command == NULL) + { + EZ_DEBUG(DBG_CAT_PROTO, CATPROTO_RRM, DBG_LVL_ERROR, ("!!!(%s) : no memory!!!\n", __FUNCTION__)); + return NDIS_STATUS_FAILURE; + } + + copy_from_user(p_internet_command, wrq->u.data.pointer, wrq->u.data.length); + + EZ_DEBUG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("Net_status =%d,\n", + p_internet_command->Net_status)); + Status = ez_internet_msghandle_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, p_internet_command); + os_free_mem(pAd, p_internet_command); + if(Status != NDIS_STATUS_SUCCESS) + { + Status = -NDIS_STATUS_FAILURE; + } + return Status; +} + +INT Custom_DataHandle(void *ad_obj, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + RTMP_ADAPTER *pAd; + p_ez_custom_data_cmd_t p_custom_data; + + pAd = (RTMP_ADAPTER *)ad_obj; + p_custom_data = NULL; + + os_alloc_mem(NULL, (UCHAR **)&p_custom_data, wrq->u.data.length); + if (p_custom_data == NULL) + { + MTWF_LOG(DBG_CAT_PROTO, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("!!!(%s) : no memory!!!\n", __FUNCTION__)); + return NDIS_STATUS_FAILURE; + } + + memset(p_custom_data, '\0', wrq->u.data.length); + + copy_from_user(p_custom_data, wrq->u.data.pointer, wrq->u.data.length); + + ez_custom_data_handle_hook((EZ_ADAPTER *)pAd->ez_ad, p_custom_data, (unsigned char )wrq->u.data.length); + + os_free_mem(pAd, p_custom_data); + + return NDIS_STATUS_SUCCESS; +} + + +#ifdef EZ_REGROUP_SUPPORT + +regrp_ap_info_struct * ez_find_regrp_ap_by_bssid(regrp_ap_info_struct *p_ap_info_list, UINT8 * bssid) +{ + int i; + for(i=0; i< EZ_MAX_DEVICE_SUPPORT; i++) + { + if(p_ap_info_list[i].valid && MAC_ADDR_EQUAL(p_ap_info_list[i].bssid,bssid)) + return &p_ap_info_list[i]; + } + return NULL; +} + +void ez_delete_regrp_old_ap(regrp_ap_info_struct *p_ap_info_list) +{ + int i; + ULONG now; + NdisGetSystemUpTime(&now); + for(i=0; i< EZ_MAX_DEVICE_SUPPORT; i++) + { + if(p_ap_info_list[i].valid && RTMP_TIME_AFTER(now,p_ap_info_list[i].last_rx_time + 5*OS_HZ)) + { + printk("%s: %02x:%02x:%02x:%02x:%02x:%02x\n",__func__, PRINT_MAC(p_ap_info_list[i].bssid)); + // hex_dump("RegrpAPDel: Ageout",p_ap_info_list[i].bssid,MAC_ADDR_LEN); + NdisZeroMemory(&p_ap_info_list[i],sizeof(regrp_ap_info_struct)); + // p_ap_info_list[i].valid = 1; + } + } +} + +regrp_ap_info_struct * ez_add_regrp_ap(regrp_ap_info_struct *p_ap_info_list) +{ + int i; + + ez_delete_regrp_old_ap(p_ap_info_list); + + for(i=0; i< EZ_MAX_DEVICE_SUPPORT; i++) + { + if(!p_ap_info_list[i].valid) + { + NdisZeroMemory(&p_ap_info_list[i],sizeof(regrp_ap_info_struct)); + p_ap_info_list[i].valid = 1; + return &p_ap_info_list[i]; + } + } + return NULL; +} + +extern regrp_ap_info_struct regrp_ap_info[2][EZ_MAX_DEVICE_SUPPORT]; + +void ez_print_cand_list(p_regrp_ap_info_struct p_ap_info) +{ + int i; + for (i = 0; (i < EZ_MAX_DEVICE_SUPPORT) ; i++) + { + if(p_ap_info[i].valid == 1) + { + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[%d] %02x:%02x:%02x:%02x:%02x:%02x RSSI=%d: %d EZ=%d InternetStatus= 0x%x\n", i, + PRINT_MAC(p_ap_info[i].bssid), + p_ap_info[i].avg_rssi,p_ap_info[i].last_rssi, !p_ap_info[i].Non_MAN,p_ap_info[i].internet_status)); + } + } +} +int ez_get_candidate_list(struct wifi_dev *wdev, pregrp_cmd_cand_list peer_list, UINT8 *data_len) +{ + UCHAR i=0; +// BSS_ENTRY *bss_entry = NULL; + pntw_info pcand_entry = NULL; + //RTMP_ADAPTER *pAd = (RTMP_ADAPTER *) wdev->sys_handle; + //PAPCLI_STRUCT pApCliEntry = NULL; + UINT8 band; + + if(wdev->channel <= 14) + band =0; + else + band = 1; + + + //pApCliEntry = &pAd->ApCfg.ApCliTab[wdev->func_idx]; + + peer_list->cand_count = 0; + pcand_entry = (pntw_info) &peer_list->list[0]; + printk("<<===>%s : %d>>\n",__FUNCTION__,band); + // following logic referred from ez_apcli_search_best_ap_configured(), with required checks kept + ez_delete_regrp_old_ap(regrp_ap_info[0]); + ez_delete_regrp_old_ap(regrp_ap_info[1]); + ez_print_cand_list(regrp_ap_info[band]); + + for (i = 0; (i < EZ_MAX_DEVICE_SUPPORT) ; i++) + { + p_regrp_ap_info_struct p_ap_info = ®rp_ap_info[band][i]; + if(p_ap_info->valid) + { + // fill the candidate info + //memcpy(pcand_entry->ssid,bss_entry->Ssid,bss_entry->SsidLen); + NdisCopyMemory(pcand_entry->bssid,p_ap_info->bssid, MAC_ADDR_LEN); + pcand_entry->Non_MAN = p_ap_info->Non_MAN; + pcand_entry->rssi = p_ap_info->avg_rssi; + if(!pcand_entry->Non_MAN){ + NdisCopyMemory(pcand_entry->nw_wt,p_ap_info->nw_wt, NETWORK_WEIGHT_LEN); + NdisCopyMemory(&pcand_entry->node_number, &p_ap_info->node_number,sizeof(EZ_NODE_NUMBER)); + } + else + { + NdisZeroMemory(pcand_entry->nw_wt,NETWORK_WEIGHT_LEN); + NdisZeroMemory(&pcand_entry->node_number,sizeof(EZ_NODE_NUMBER)); + } + + peer_list->cand_count++; + pcand_entry++; + + } + } + + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("Number of Candidates = %d\n", peer_list->cand_count)); + NdisZeroMemory(®rp_ap_info[band][0], sizeof(regrp_ap_info_struct)*EZ_MAX_DEVICE_SUPPORT); +#ifdef DBG +// printk("Raghav0\n"); + pcand_entry = (pntw_info) &peer_list->list[0]; +// printk("Raghav1\n"); + for (i=0; icand_count; i++) { + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("[%d] %02x:%02x:%02x:%02x:%02x:%02x RSSI=%d EZ=%d InternetStatus= 0x%x\n", i, + pcand_entry[i].bssid[0], + pcand_entry[i].bssid[1], + pcand_entry[i].bssid[2], + pcand_entry[i].bssid[3], + pcand_entry[i].bssid[4], + pcand_entry[i].bssid[5], + pcand_entry[i].rssi, !pcand_entry[i].Non_MAN,pcand_entry[i].internet_status)); + } + + //EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + // ("%s(line.%d) - apcli_entry->CfgSsid-%s, apcli_entry->Ssid-%s\n", + // __FUNCTION__, __LINE__,apcli_entry->CfgSsid, apcli_entry->Ssid)); +#endif + + // skip rssi sorting to save time, as requestor can do it if required + //BssTableSortByRssi(out_table, FALSE); + *data_len = peer_list->cand_count * sizeof(ntw_info); + + return NDIS_STATUS_SUCCESS; +} + +int ez_handle_regroup_query_cmd(RTMP_ADAPTER *pAd, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + int Status = NDIS_STATUS_SUCCESS; + p_regrp_command_t p_regrp_cmd; + struct wifi_dev *wdev; + UCHAR ifIndex; + BOOLEAN apcliEn=FALSE; + EZ_ADAPTER *ez_ad = pAd->ez_ad; + printk("===>%s\n",__FUNCTION__); + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + if(wrq->u.data.length < sizeof(regrp_command_t)) + return FALSE; + + p_regrp_cmd = (p_regrp_command_t)(wrq->u.data.pointer); + + switch(p_regrp_cmd->command_id) + { + case OID_REGROUP_CMD_REGRP_SUPP: + { + pcmd_regrp_supp pbuf = (pcmd_regrp_supp)p_regrp_cmd; + printk("===>%s OID_REGROUP_CMD_REGRP_SUPP\n",__FUNCTION__); + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: OID_REGROUP_CMD_CONNECTED_PEER_LIST", + ifIndex, __FUNCTION__)); + + wdev = &pAd->ApCfg.ApCliTab[ifIndex].wdev; + //apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + //if (!apcliEn){ + // wrq->u.data.length = sizeof(regrp_command_t); + // return NDIS_STATUS_SUCCESS; + //} + + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[ifIndex].wdev; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(ra%d) %s:: ", + ifIndex, __FUNCTION__)); + } + + if(IS_REGRP_SUPP(wdev)){ + pbuf->regrp_supp = TRUE; + } + else + pbuf->regrp_supp = FALSE; + + if(IS_EZ_SETUP_ENABLED(wdev)){ + pbuf->ez_supp = TRUE; + + + pbuf->configured = TRUE; + } + else + pbuf->ez_supp = FALSE; + + // always take channel from ap context, though apcli wdev should have same channel + pbuf->channel = pAd->ApCfg.MBSSID[ifIndex].wdev.channel; + + break; + } + + case OID_REGROUP_CMD_CAND_LIST: + printk("===>%s OID_REGROUP_CMD_CAND_LIST\n",__FUNCTION__); + + if (pObj->ioctl_if_type == INT_APCLI) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: OID_REGROUP_CMD_ROAM_AP_LIST", + ifIndex, __FUNCTION__)); + + wdev = &pAd->ApCfg.ApCliTab[ifIndex].wdev; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + if (!apcliEn || (!IS_REGRP_SUPP(wdev) || !IS_EZ_SETUP_ENABLED(wdev)) ){ + wrq->u.data.length = sizeof(regrp_command_t); + return NDIS_STATUS_FAILURE; // proper?? + } + + Status = ez_get_candidate_list(wdev,(pregrp_cmd_cand_list)p_regrp_cmd,&p_regrp_cmd->command_len); + + wrq->u.data.length = sizeof(regrp_cmd_hdr) + p_regrp_cmd->command_len; + Status = copy_to_user(wrq->u.data.pointer, p_regrp_cmd, wrq->u.data.length); + } + else + Status = -EOPNOTSUPP; + break; + + case OID_REGROUP_QUERY_INTERFACE_DETAILS: + { + vr_ap_info_struct ap_info; + printk("===>%s OID_REGROUP_QUERY_INTERFACE_DETAILS\n",__FUNCTION__); + + NdisZeroMemory(&ap_info,sizeof(ap_info)); + ap_info.ssid_len = pAd->ApCfg.MBSSID[ifIndex].SsidLen; + NdisCopyMemory(ap_info.ssid,pAd->ApCfg.MBSSID[ifIndex].Ssid,pAd->ApCfg.MBSSID[ifIndex].SsidLen); + COPY_MAC_ADDR(ap_info.mac_addr, pAd->ApCfg.MBSSID[ifIndex].wdev.bssid); + NdisCopyMemory(ap_info.intf_prefix, get_dev_name_prefix(pAd, INT_MAIN), strlen(get_dev_name_prefix(pAd, INT_MAIN))); + ap_info.wdev_id = ifIndex; + Status = copy_to_user(wrq->u.data.pointer, &ap_info, wrq->u.data.length); + break; + } + case OID_REGROUP_QUERY_NODE_NUMBER_WT: + { + node_num_wt node_wt; + + printk("===>%s OID_REGROUP_QUERY_NODE_NUMBER_WT\n",__FUNCTION__); + NdisCopyMemory(&node_wt.node_number, &ez_ad->device_info.ez_node_number,sizeof(EZ_NODE_NUMBER)); + NdisCopyMemory(node_wt.network_wt, ez_ad->device_info.network_weight,NETWORK_WEIGHT_LEN); + + Status = copy_to_user(wrq->u.data.pointer, &node_wt, sizeof(node_wt)); + break; + } + default: + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("Query::unknown IOCTL's subcmd = 0x%08x, IFidx=%d\n", p_regrp_cmd->command_id, ifIndex)); + Status = -EOPNOTSUPP; + break; + } + + return Status; + +} + +int regrp_set_mode(struct wifi_dev *wdev, UINT8 req_mode){ + int Status = NDIS_STATUS_SUCCESS; + UINT8 *pcurr_mode = &wdev->ez_driver_params.regrp_mode; + + RTMP_SEM_LOCK(&wdev->ez_driver_params.regrp_mode_lock); + + printk("regrp_set_mode => Current Stae: %d, requested State : %d", *pcurr_mode, req_mode); + + if(*pcurr_mode == req_mode){ + printk("regrp_set_mode: Same Mode request\n"); + goto exit_func; + } + + switch(req_mode){ // check handling required for requested mode, based on possible current mode + + case REGRP_MODE_BLOCKED: + { + if(*pcurr_mode == NON_REGRP_MODE){ // regroup actviity started on device + // startRegrpModeTimer(wdev); // should happen only once + } + else { // unblocked mdoe to blocked mode i.e. regp finished for this interface + // stopRegrpUnblockModeTimer(wdev); + // do other cleanup like candiate list cleanup ?? if apcli / ap check + // ensure conenct activity gets stopped? + } + *pcurr_mode = req_mode; + //cancel the scan timer if running + if(wdev->ez_driver_params.ez_scan_timer.ez_timer_running== TRUE) + { + EZ_CANCEL_TIMER(&wdev->ez_driver_params.ez_scan_timer.ez_timer, + wdev->ez_driver_params.ez_scan_timer.ez_timer_running); + //RTMPCancelTimer(&wdev->ez_security.ez_scan_timer,&Cancelled); + } + } + break; + case REGRP_MODE_UNBLOCKED: + if(*pcurr_mode == NON_REGRP_MODE){ // regroup actviity started on device + printk(" Abnormal transition requested \n"); + Status = NDIS_STATUS_FAILURE; // proper? + goto exit_func; + } + else{ // blocked to unblocked mode regrp started for this interface + // init context required for conenct attempt ... if ap/apcli check + + // check conenct state too? + + if(ez_is_roaming_ongoing_hook(wdev->sys_handle)){ + printk(" Reject as roaming ongoing \n"); + Status = NDIS_STATUS_FAILURE; // proper? + goto exit_func; + } + + } + *pcurr_mode = req_mode; + + break; + + case NON_REGRP_MODE: + if(*pcurr_mode == REGRP_MODE_BLOCKED){ // regroup actviity started on device + //stopRegrpModeTimer(wdev); + // other cleanup?? + } + else{ // unblocked mdoe to blocked mode + // stopRegrpUnblockModeTimer(wdev); + // do other cleanup like candiate list cleanup ?? if apcli/ap check + // ensure conenct activity gets stopped? + + //stopRegrpModeTimer(wdev); + // other cleanup + + } + *pcurr_mode = req_mode; + + break; + default: + printk("regrp_set_mod: Unknown mode requested\n"); + Status = NDIS_STATUS_FAILURE; // proper? + break; + } + +exit_func: + + RTMP_SEM_UNLOCK(&wdev->ez_driver_params.regrp_mode_lock); + + return Status; +} + + +int ez_handle_regroup_set_cmd(RTMP_ADAPTER *pAd, RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; + int Status = NDIS_STATUS_SUCCESS; + p_regrp_command_t p_regrp_cmd; + struct wifi_dev *wdev; + UCHAR ifIndex; + // BOOLEAN apcliEn=FALSE; + +// BOOLEAN apcliEn=FALSE; + printk("===>%s \n",__FUNCTION__); + + pObj = (POS_COOKIE) pAd->OS_Cookie; + ifIndex = pObj->ioctl_if; + + if(wrq->u.data.length < sizeof(regrp_command_t)) + return FALSE; + + p_regrp_cmd = (p_regrp_command_t)(wrq->u.data.pointer); + + switch(p_regrp_cmd->command_id) + { + case OID_REGROUP_CMD_EN_REGRP_MODE: + { + + pcmd_regrp_mode pbuf = (pcmd_regrp_mode)p_regrp_cmd; + printk("===>%s OID_REGROUP_CMD_EN_REGRP_MODE\n",__FUNCTION__); + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: OID_REGROUP_CMD_CONNECTED_PEER_LIST", + ifIndex, __FUNCTION__)); + + wdev = &pAd->ApCfg.ApCliTab[ifIndex].wdev; + //apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + //if (!apcliEn){ + // wrq->u.data.length = sizeof(regrp_command_t); + // return NDIS_STATUS_SUCCESS; + //} + + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[ifIndex].wdev; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(ra%d) %s:: ", + ifIndex, __FUNCTION__)); + } + + Status = regrp_set_mode(wdev,pbuf->mode); + + break; + } + default: + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("Set::unknown IOCTL's subcmd = 0x%08x, IFidx=%d\n", p_regrp_cmd->command_id, ifIndex)); + Status = -EOPNOTSUPP; + break; + } + + return Status; + +} + +#endif + + + + +int ez_parse_set_command(void *ad_obj, RTMP_IOCTL_INPUT_STRUCT *wrq, IN int cmd) +{ + RTMP_ADAPTER *pAd; + struct wifi_dev *wdev; + UCHAR inf_idx; + int Status = NDIS_STATUS_SUCCESS; + POS_COOKIE pObj; + pAd = (RTMP_ADAPTER *)ad_obj; + pObj = (POS_COOKIE) pAd->OS_Cookie; + inf_idx = pObj->ioctl_if; +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) { + wdev = &pAd->ApCfg.ApCliTab[inf_idx].wdev; + if (!pAd->ApCfg.ApCliTab[inf_idx].Enable) + return FALSE; + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: ", + inf_idx, __FUNCTION__)); + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[inf_idx].wdev; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(ra%d) %s:: ", + inf_idx, __FUNCTION__)); + } + + switch(cmd & 0x7FFF) + { + + case OID_WH_EZ_ENABLE: + inf_idx = pObj->ioctl_if; +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) { + wdev = &pAd->ApCfg.ApCliTab[inf_idx].wdev; + if (!pAd->ApCfg.ApCliTab[inf_idx].Enable) + return FALSE; + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: ", + inf_idx, __FUNCTION__)); + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[inf_idx].wdev; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(ra%d) %s:: ", + inf_idx, __FUNCTION__)); + } + + if (wrq->u.data.length != sizeof(UCHAR)) + Status = -EINVAL; + else + { + Status = copy_from_user(&wdev->ez_driver_params.enable_easy_setup, wrq->u.data.pointer, wrq->u.data.length); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("%s:: enable_easy_setup = %d.\n", + __FUNCTION__, wdev->ez_driver_params.enable_easy_setup)); + } + break; + + case OID_WH_EZ_GROUP_ID: + inf_idx = pObj->ioctl_if; +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) { + wdev = &pAd->ApCfg.ApCliTab[inf_idx].wdev; + if (!pAd->ApCfg.ApCliTab[inf_idx].Enable) + return FALSE; + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: ", + inf_idx, __FUNCTION__)); + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[inf_idx].wdev; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(ra%d) %s:: ", + inf_idx, __FUNCTION__)); + } + if (wdev->ez_driver_params.ezdev) { + ez_set_ezgroup_id_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, wrq->u.data.pointer, wrq->u.data.length, inf_idx); + ez_set_group_id_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, wrq->u.data.pointer, wrq->u.data.length, inf_idx); + } else { + return FALSE; + } + break; + + case OID_WH_EZ_GEN_GROUP_ID: + inf_idx = pObj->ioctl_if; +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) { + wdev = &pAd->ApCfg.ApCliTab[inf_idx].wdev; + if (!pAd->ApCfg.ApCliTab[inf_idx].Enable) + return FALSE; + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: ", + inf_idx, __FUNCTION__)); + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[inf_idx].wdev; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(ra%d) %s:: ", + inf_idx, __FUNCTION__)); + } + if (wrq->u.data.length == 0) { + Status = -EINVAL; + } + else { + if (wdev->ez_driver_params.ezdev) { + Status = ez_set_gen_group_id_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, + wrq->u.data.pointer, wrq->u.data.length, inf_idx); + } else { + Status = -EINVAL; + } + } + break; + + case OID_WH_EZ_RSSI_THRESHOLD: + inf_idx = pObj->ioctl_if; +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) { + wdev = &pAd->ApCfg.ApCliTab[inf_idx].wdev; + if (!pAd->ApCfg.ApCliTab[inf_idx].Enable) + return FALSE; + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: ", + inf_idx, __FUNCTION__)); + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[inf_idx].wdev; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(ra%d) %s:: ", + inf_idx, __FUNCTION__)); + } + if (wrq->u.data.length != sizeof(CHAR)) + Status = -EINVAL; + else + { + if (wdev->ez_driver_params.ezdev){ + ez_dev_t *ezdev = wdev->ez_driver_params.ezdev; + char rssi_val; + Status = copy_from_user(&rssi_val, wrq->u.data.pointer, wrq->u.data.length); + ezdev->ez_security.rssi_threshold = -1 * rssi_val; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("%s:: rssi_threshold = %d.\n", + __FUNCTION__, wdev->ez_driver_params.enable_easy_setup)); + } + } + break; + + case OID_WH_EZ_INTERNET_COMMAND: + if (wdev->ez_driver_params.ezdev){ + Status = ez_internet_msg_handle(ad_obj, wrq); + + } else { + Status = -NDIS_STATUS_FAILURE; + } + break; + +#ifdef EZ_PUSH_BW_SUPPORT + case OID_WH_EZ_PUSH_BW: + { + //PRTMP_ADAPTER adOthBand = NULL; + + if (wrq->u.data.length != sizeof(CHAR)) + Status = -EINVAL; + else + { + BOOLEAN push_bw_config; + Status = copy_from_user(&push_bw_config, wrq->u.data.pointer, wrq->u.data.length); + if (wdev->ez_driver_params.ez_ad) { + ((EZ_ADAPTER *)(wdev->ez_driver_params.ez_ad))->push_bw_config = push_bw_config; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("%s:: push_bw_config = %d.\n", + __FUNCTION__, ((EZ_ADAPTER *)(wdev->ez_driver_params.ez_ad))->push_bw_config)); + + } + } + } + break; +#endif + case OID_WH_EZ_CUSTOM_DATA_CMD: + { + inf_idx = pObj->ioctl_if; + + Status = Custom_DataHandle(pAd, wrq); + + if(Status != NDIS_STATUS_SUCCESS) + { + Status = -NDIS_STATUS_FAILURE; + } + + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("OID_WH_EZ_CUSTOM_DATA_CMD Status : %d\n", Status)); + } + break; +#ifdef EZ_REGROUP_SUPPORT + case OID_WH_EZ_REGROUP_COMMAND: + + printk("===>%s OID_WH_EZ_REGROUP_COMMAND\n",__FUNCTION__); + Status = ez_handle_regroup_set_cmd(pAd, wrq); + + break; +#endif + + default: + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("Set::unknown IOCTL's subcmd = 0x%08x\n", cmd)); + Status = -EOPNOTSUPP; + break; + } + return Status; +} + +// Arvind : Todo +int ez_parse_query_command(void *ad_obj, RTMP_IOCTL_INPUT_STRUCT *wrq, IN int cmd) +{ + NDIS_802_11_AUTHENTICATION_MODE AuthMode; + NDIS_802_11_WEP_STATUS WepStatus; + RTMP_ADAPTER *pAd; + struct wifi_dev *wdev; + UCHAR ifIndex; + POS_COOKIE pObj; + UCHAR apidx; + BOOLEAN apcliEn=FALSE; + int Status = NDIS_STATUS_SUCCESS; + struct ez_GUI_info GUI_info; + struct wifi_dev *apcli_wdev; + APCLI_STRUCT *apcli_entry; + pAd = (RTMP_ADAPTER *)ad_obj; + pObj = (POS_COOKIE) pAd->OS_Cookie; + + apidx = pObj->ioctl_if; + ifIndex = pObj->ioctl_if; + + AuthMode = Ndis802_11AuthModeOpen; + WepStatus = Ndis802_11WEPDisabled; + + + switch(cmd & 0x7FFF) + { + case OID_WH_EZ_ENABLE: + ifIndex = pObj->ioctl_if; +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) { + wdev = &pAd->ApCfg.ApCliTab[ifIndex].wdev; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + if (!apcliEn) + return FALSE; + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: ", + ifIndex, __FUNCTION__)); + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[ifIndex].wdev; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(ra%d) %s:: ", + ifIndex, __FUNCTION__)); + } + wrq->u.data.length = sizeof(wdev->ez_driver_params.enable_easy_setup); + Status = copy_to_user(wrq->u.data.pointer, &wdev->ez_driver_params.enable_easy_setup, wrq->u.data.length); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("Status = %d, enable_easy_setup = %d\n", + Status, wdev->ez_driver_params.enable_easy_setup)); + break; + + case OID_WH_EZ_GROUP_ID: + ifIndex = pObj->ioctl_if; +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) { + wdev = &pAd->ApCfg.ApCliTab[ifIndex].wdev; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + if (!apcliEn) + return FALSE; + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: ", + ifIndex, __FUNCTION__)); + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[ifIndex].wdev; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(ra%d) %s:: ", + ifIndex, __FUNCTION__)); + } + wrq->u.data.length = ((ez_dev_t *)(wdev->ez_driver_params.ezdev))->ez_security.group_id_len; + Status = copy_to_user(wrq->u.data.pointer, + ((ez_dev_t *)(wdev->ez_driver_params.ezdev))->ez_security.group_id, + ((ez_dev_t *)(wdev->ez_driver_params.ezdev))->ez_security.group_id_len); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("Status = %d, OID_WH_EZ_GROUP_ID\n", + Status)); + break; + + case OID_WH_EZ_RSSI_THRESHOLD: + ifIndex = pObj->ioctl_if; +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) { + wdev = &pAd->ApCfg.ApCliTab[ifIndex].wdev; + apcliEn = pAd->ApCfg.ApCliTab[ifIndex].Enable; + if (!apcliEn) + return FALSE; + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: ", + ifIndex, __FUNCTION__)); + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[ifIndex].wdev; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(ra%d) %s:: ", + ifIndex, __FUNCTION__)); + } + + wrq->u.data.length = sizeof(((ez_dev_t *)(wdev->ez_driver_params.ezdev))->ez_security.rssi_threshold); + Status = copy_to_user(wrq->u.data.pointer, + &((ez_dev_t *)(wdev->ez_driver_params.ezdev))->ez_security.rssi_threshold, + wrq->u.data.length); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("Status = %d, rssi_threshold = %d\n", + Status, ((ez_dev_t *)(wdev->ez_driver_params.ezdev))->ez_security.rssi_threshold)); + break; + + case OID_WH_EZ_GET_GUI_INFO: + + ifIndex = pObj->ioctl_if; +#ifdef APCLI_SUPPORT + apcli_entry = &pAd->ApCfg.ApCliTab[ifIndex]; + apcli_wdev = &pAd->ApCfg.ApCliTab[ifIndex].wdev; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("IF(apcli%d) %s:: ", ifIndex, __FUNCTION__)); +#endif /* APCLI_SUPPORT */ + + wdev = &pAd->ApCfg.MBSSID[ifIndex].wdev; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("IF(ra%d) %s:: ", ifIndex, __FUNCTION__)); + + memset(&GUI_info, '\0', sizeof(GUI_info)); + NdisCopyMemory(&GUI_info.EzEnable, &wdev->ez_driver_params.enable_easy_setup, sizeof(wdev->ez_driver_params.enable_easy_setup)); + //NdisCopyMemory(&GUI_info.EzConfStatus, &ez_adapter.configured_status, sizeof(ez_adapter.configured_status)); + if (IS_EZ_SETUP_ENABLED(wdev)) + { + NdisCopyMemory(GUI_info.EzGroupID, + ((ez_dev_t *)(wdev->ez_driver_params.ezdev))->ez_security.ez_group_id, + ((ez_dev_t *)(wdev->ez_driver_params.ezdev))->ez_security.ez_group_id_len); + NdisCopyMemory(GUI_info.EzGenGroupId, + ((ez_dev_t *)(wdev->ez_driver_params.ezdev))->ez_security.gen_group_id, + ((ez_dev_t *)(wdev->ez_driver_params.ezdev))->ez_security.gen_group_id_len); + NdisCopyMemory(GUI_info.EzOpenGroupID, + ((ez_dev_t *)(wdev->ez_driver_params.ezdev))->ez_security.open_group_id, + ((ez_dev_t *)(wdev->ez_driver_params.ezdev))->ez_security.open_group_id_len); +#ifdef APCLI_SUPPORT + //NdisCopyMemory(&GUI_info.ApCliEzConfStatus, &ez_adapter.configured_status, sizeof(ez_adapter.configured_status)); + NdisCopyMemory(GUI_info.ApCliEzGroupID, + ((ez_dev_t *)(apcli_wdev->ez_driver_params.ezdev))->ez_security.ez_group_id, + ((ez_dev_t *)(apcli_wdev->ez_driver_params.ezdev))->ez_security.ez_group_id_len); + NdisCopyMemory(GUI_info.ApCliEzGenGroupId, + ((ez_dev_t *)(apcli_wdev->ez_driver_params.ezdev))->ez_security.gen_group_id, + ((ez_dev_t *)(apcli_wdev->ez_driver_params.ezdev))->ez_security.gen_group_id_len); + NdisCopyMemory(GUI_info.ApCliEzOpenGroupID, + ((ez_dev_t *)(apcli_wdev->ez_driver_params.ezdev))->ez_security.open_group_id, + ((ez_dev_t *)(apcli_wdev->ez_driver_params.ezdev))->ez_security.open_group_id_len); + NdisCopyMemory(GUI_info.ApCliHideSSID, apcli_entry->CfgHideSsid, apcli_entry->CfgHideSsidLen); + + AuthMode = apcli_wdev->AuthMode; + if ((AuthMode >= Ndis802_11AuthModeOpen) && + (AuthMode <= Ndis802_11AuthModeWPA1PSKWPA2PSK)) + NdisCopyMemory(GUI_info.ApCliAuthMode, RTMPGetRalinkAuthModeStr(AuthMode), strlen(RTMPGetRalinkAuthModeStr(AuthMode))); + + WepStatus = apcli_wdev->WepStatus; + if ((WepStatus >= Ndis802_11WEPEnabled) && + (WepStatus <= Ndis802_11Encryption4KeyAbsent)) + NdisCopyMemory(GUI_info.ApCliEncrypType, RTMPGetRalinkEncryModeStr(WepStatus), strlen(RTMPGetRalinkEncryModeStr(WepStatus))); + + NdisCopyMemory(GUI_info.ApCliWPAPSK, &pAd->ApCfg.ApCliTab[ifIndex].PSK, strlen(pAd->ApCfg.ApCliTab[ifIndex].PSK)); + + NdisCopyMemory(GUI_info.ApCliSsid, apcli_entry->CfgSsid, apcli_entry->CfgSsidLen); + NdisCopyMemory(&GUI_info.ApCliEnable, &pAd->ApCfg.ApCliTab[ifIndex].Enable, sizeof(pAd->ApCfg.ApCliTab[ifIndex].Enable)); + NdisCopyMemory(&GUI_info.ApCliEzEnable, &apcli_wdev->ez_driver_params.enable_easy_setup, sizeof(apcli_wdev->ez_driver_params.enable_easy_setup)); +#endif + } + wrq->u.data.length = sizeof(GUI_info); + Status = copy_to_user(wrq->u.data.pointer, &GUI_info, sizeof(GUI_info)); + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("Status = %d, OID_WH_EZ_GROUP_ID\n", Status)); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("sizeof(GUI_info):%d\n", sizeof(GUI_info))); + + break; + + case OID_WH_EZ_UPDATE_STA_INFO: + { + int sta_cnt; + int i = 0; + char buf[256]; + MAC_TABLE_ENTRY *pMacEntry = NULL; + struct wifi_dev *wdev = &pAd->ApCfg.MBSSID[ifIndex].wdev; + EZ_ADAPTER *ez_ad = wdev->ez_driver_params.ez_ad; + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("\n OID_WH_EZ_UPDATE_STA_INFO \n")); + Status = copy_from_user(&buf[0], wrq->u.data.pointer, wrq->u.data.length); + + + sta_cnt = wrq->u.data.length / 6; + for (i = 0; i < sta_cnt; i ++) + { + if (ez_is_triband()) + { + + pMacEntry = MacTableLookup2(ez_ad->non_ez_band_info[0].pAd,&buf[i*MAC_ADDR_LEN],NULL); + if(pMacEntry != NULL){ + MacTableDeleteEntry(ez_ad->non_ez_band_info[0].pAd,pMacEntry->wcid,pMacEntry->Addr); + pMacEntry = NULL; + } + + + pMacEntry = MacTableLookup2(ez_ad->non_ez_band_info[1].pAd,&buf[i*MAC_ADDR_LEN],NULL); + if(pMacEntry != NULL){ + MacTableDeleteEntry(ez_ad->non_ez_band_info[1].pAd,pMacEntry->wcid,pMacEntry->Addr); + pMacEntry = NULL; + } + } else { + pMacEntry = MacTableLookup2(ez_ad->ez_band_info[0].pAd,&buf[i*MAC_ADDR_LEN],NULL); + if(pMacEntry != NULL){ + MacTableDeleteEntry(ez_ad->ez_band_info[0].pAd,pMacEntry->wcid,pMacEntry->Addr); + pMacEntry = NULL; + } + + + if(ez_ad->ez_band_info[1].pAd) + { + pMacEntry = MacTableLookup2(ez_ad->ez_band_info[1].pAd,&buf[i*MAC_ADDR_LEN],NULL); + if(pMacEntry != NULL){ + MacTableDeleteEntry(ez_ad->ez_band_info[1].pAd,pMacEntry->wcid,pMacEntry->Addr); + pMacEntry = NULL; + } + + } + } + } + RtmpOSWrielessEventSend(pAd->net_dev, RT_WLAN_EVENT_CUSTOM, OID_WH_EZ_UPDATE_STA_INFO, + NULL, buf, wrq->u.data.length); + + break; + } +#ifdef EZ_REGROUP_SUPPORT + case OID_WH_EZ_REGROUP_COMMAND: + printk("===>%s OID_WH_EZ_REGROUP_COMMAND\n",__FUNCTION__); + Status = ez_handle_regroup_query_cmd(pAd, wrq); + break; +#endif + + default: + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("Query::unknown IOCTL's subcmd = 0x%08x, apidx=%d\n", cmd, apidx)); + Status = -EOPNOTSUPP; + break; + } + + return Status; +} + +void ez_vendor_ie_parse(struct _vendor_ie_cap *vendor_ie, PEID_STRUCT info_elem) +{ + + vendor_ie->support_easy_setup = TRUE; + + if (info_elem->Octet[EZ_TAG_OFFSET] + == EZ_TAG_CAPABILITY_INFO) { + NdisCopyMemory(&vendor_ie->ez_capability, + &info_elem->Octet[EZ_TAG_DATA_OFFSET], + EZ_CAPABILITY_LEN); + vendor_ie->ez_capability = be2cpu32(vendor_ie->ez_capability); + } + if (info_elem->Octet[EZ_TAG_OFFSET] + == EZ_TAG_BEACON_INFO) { + NdisCopyMemory(&vendor_ie->beacon_info,&info_elem->Octet[EZ_TAG_DATA_OFFSET], info_elem->Octet[EZ_TAG_LEN_OFFSET]); + } + + if (info_elem->Octet[EZ_TAG_OFFSET] + == EZ_TAG_NON_EZ_BEACON) { + vendor_ie->non_ez_beacon = TRUE; + } + + if (info_elem->Octet[EZ_TAG_OFFSET] + == EZ_TAG_OPEN_GROUP_ID) { + NdisCopyMemory(vendor_ie->open_group_id, + &info_elem->Octet[EZ_TAG_DATA_OFFSET], + info_elem->Octet[EZ_TAG_LEN_OFFSET]); + vendor_ie->open_group_id_len = info_elem->Octet[EZ_TAG_LEN_OFFSET]; + } + +} + +void ez_set_ap_fallback_context(struct wifi_dev *wdev, BOOLEAN fallback, unsigned char fallback_channel) +{ + if (wdev->ez_driver_params.ezdev){ + ez_dev_t *ezdev = wdev->ez_driver_params.ezdev; + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("\nez_set_ap_fallback_context: ezdev idx %x, type %x, fallback %x, chan %d\n", + ezdev->ez_band_idx, ezdev->ezdev_type, fallback, fallback_channel)); + ezdev->ez_security.ap_did_fallback = fallback; + ezdev->ez_security.fallback_channel = fallback_channel; + + //ez_set_ap_fallback_context_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, fallback, fallback_channel); + } +} + +void *ez_peer_table_search_by_addr( + struct wifi_dev *wdev, + unsigned char *addr) +{ + if (wdev->ez_driver_params.ezdev) + return ez_peer_table_search_by_addr_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, addr); + return NULL; +} + +void ez_set_delete_peer_in_differed_context(struct wifi_dev *wdev, void *ez_peer_obj, BOOLEAN set) +{ + struct _ez_peer_security_info *ez_peer = ez_peer_obj; + if (wdev->ez_driver_params.ezdev){ + if (set) + { + ez_peer->delete_in_differred_context = TRUE; + } else { + ez_peer->delete_in_differred_context = FALSE; + } + } +} + +#ifdef APCLI_AUTO_CONNECT_SUPPORT +BOOLEAN ez_probe_count_handle(PAPCLI_STRUCT pApCliEntry) +{ + BOOLEAN attempt_same_peer= FALSE; + pApCliEntry->ProbeReqCnt = 0; + return attempt_same_peer; +} +#endif + +BOOLEAN ez_ApCliAutoConnectBWAdjust( + IN void *ad_obj, + IN struct wifi_dev *wdev, + IN void *bss_entry_obj) +{ + RTMP_ADAPTER *pAd = ad_obj; + BSS_ENTRY *bss_entry = bss_entry_obj; + BOOLEAN bAdjust = FALSE; + BOOLEAN bAdjust_by_channel = FALSE; + BOOLEAN bAdjust_by_ht = FALSE; + BOOLEAN bAdjust_by_vht = FALSE; + UCHAR orig_op_ht_bw; + UCHAR orig_op_vht_bw; + UCHAR orig_ext_cha; + EZ_ADAPTER *ez_ad = wdev->ez_driver_params.ez_ad; + + if (pAd == NULL || wdev == NULL || bss_entry == NULL) { + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("(%s) Error! entry is NULL.\n", __FUNCTION__)); + return FALSE; + } + + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("BW info of root AP (%s):\n",bss_entry->Ssid)); + orig_op_ht_bw = ez_driver_ops_wlan_config_get_ht_bw_mt7603(wdev->ez_driver_params.ezdev); + orig_op_vht_bw = ez_driver_ops_wlan_config_get_vht_bw_mt7603(wdev->ez_driver_params.ezdev); + orig_ext_cha = ez_driver_ops_wlan_config_get_ext_cha_mt7603(wdev->ez_driver_params.ezdev); + + if((pAd->CommonCfg.Channel != bss_entry->Channel)) { + bAdjust = TRUE; + bAdjust_by_channel = TRUE; + } + +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(wdev->PhyMode) && (bss_entry->AddHtInfoLen != 0)) + { + ADD_HTINFO *add_ht_info = &bss_entry->AddHtInfo.AddHtInfo; + UCHAR op_ht_bw = ez_driver_ops_wlan_config_get_ht_bw_mt7603(wdev->ez_driver_params.ezdev); + UCHAR ext_cha = ez_driver_ops_wlan_config_get_ext_cha_mt7603(wdev->ez_driver_params.ezdev); + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("(%s)op_ht_bw = %d, ext_cha = %d, recommended = %d\n", __FUNCTION__, op_ht_bw, ext_cha, add_ht_info->RecomWidth)); + if(!bAdjust && + ((ext_cha != add_ht_info->ExtChanOffset) || + (op_ht_bw != add_ht_info->RecomWidth))) { + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("Need to adjust bandwidth\n")); + bAdjust = TRUE; + } + + if (bAdjust) + { + switch (add_ht_info->RecomWidth) //peer side vht bw + { + case BW_20: + if (op_ht_bw == BW_40) { + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("Bring it down to 20\n")); +#ifdef EZ_PUSH_BW_SUPPORT + if( ez_ad->push_bw_config ) + { + ez_driver_ops_wlan_config_set_ht_bw_mt7603(wdev->ez_driver_params.ezdev, add_ht_info->RecomWidth); + } +#endif + bAdjust_by_ht = TRUE; + } + break; + case BW_40: + if (op_ht_bw == BW_20) { + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("bring it up to 40 ans set EXTXHA\n")); +#ifdef EZ_PUSH_BW_SUPPORT + if( ez_ad->push_bw_config ) + { + ez_driver_ops_wlan_config_set_ht_bw_mt7603(wdev->ez_driver_params.ezdev, add_ht_info->RecomWidth); + } +#endif + ez_driver_ops_wlan_config_set_ext_cha_mt7603(wdev->ez_driver_params.ezdev, add_ht_info->ExtChanOffset); + bAdjust_by_ht = TRUE; + } else { + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("just set the EXTCHA\n")); + ez_driver_ops_wlan_config_set_ext_cha_mt7603(wdev->ez_driver_params.ezdev, add_ht_info->ExtChanOffset); + bAdjust_by_ht = TRUE; + } + break; + } + } + } +#endif /* DOT11_N_SUPPORT */ + + +#ifdef DOT11_VHT_AC + if (WMODE_CAP_AC(wdev->PhyMode) && IS_CAP_BW160(pAd) && (bss_entry->vht_cap_len != 0) && (bss_entry->vht_op_len !=0)) + { + VHT_OP_INFO *vht_op = &bss_entry->vht_op_ie.vht_op_info; + UCHAR bw = VHT_BW_2040; +#ifdef DOT11_VHT_R2 + bw = check_vht_op_bw (vht_op); +#else + bw = vht_op->ch_width; + print_vht_op_info(vht_op); +#endif /* DOT11_VHT_R2 */ + +#ifdef EZ_PUSH_BW_SUPPORT + if( ez_ad->push_bw_config ) + { +#ifdef DOT11_VHT_AC + wlan_config_set_vht_bw(wdev, bw); +#endif + } +#endif + + } +#endif /* DOT11_VHT_AC */ + bAdjust = FALSE; + if (bAdjust_by_channel == TRUE) + bAdjust = TRUE; + if (bAdjust_by_ht == TRUE) + bAdjust = TRUE; + if (bAdjust_by_vht == TRUE) + bAdjust = TRUE; + if (bAdjust) { + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("%s:Adjust (%d %d %d)\n\r",__func__, + bAdjust_by_channel,bAdjust_by_ht,bAdjust_by_vht)); + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("%s:HT BW:%d to %d. MAX(%d)\n\r",__func__, + orig_op_ht_bw, ez_driver_ops_wlan_operate_get_ht_bw_mt7603(wdev->ez_driver_params.ezdev),ez_driver_ops_wlan_config_get_ht_bw_mt7603(wdev->ez_driver_params.ezdev))); +#ifdef DOT11_VHT_AC + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("%s:VHT BW:%d to %d. MAX(%d)\n\r",__func__, + orig_op_vht_bw,ez_driver_ops_wlan_operate_get_vht_bw_mt7603(wdev->ez_driver_params.ezdev),wlan_config_get_vht_bw(wdev))); +#endif + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("%s:EXT CH:%d to %d. CFG(%d)\n\r",__func__, + orig_ext_cha,ez_driver_ops_wlan_operate_get_ext_cha_mt7603(wdev->ez_driver_params.ezdev),ez_driver_ops_wlan_config_get_ext_cha_mt7603(wdev->ez_driver_params.ezdev))); + } + + SetCommonHT(pAd); + return bAdjust; +} + +BOOLEAN ez_is_triband() +{ + return ez_is_triband_hook(); +} + +unsigned short ez_check_for_ez_enable( + struct wifi_dev *wdev, + void *msg, + unsigned long msg_len + ) +{ + return ez_check_for_ez_enable_hook(msg, msg_len); +} + +BOOLEAN ez_is_roam_blocked_mac(struct wifi_dev *wdev, UCHAR *mac_addr) +{ + if (wdev->ez_driver_params.ezdev){ + ez_dev_t *ezdev = wdev->ez_driver_params.ezdev; + return MAC_ADDR_EQUAL(ezdev->ez_security.ez_ap_roam_blocked_mac + , mac_addr); + } + return FALSE; +} +void ez_peer_table_maintenance(PRTMP_ADAPTER ad) +{ + ULONG now; + int i; + + if (ad->ez_ad) + ez_peer_table_maintenance_hook((EZ_ADAPTER *)ad->ez_ad); + + NdisGetSystemUpTime(&now); + + for (i = 0; i < ad->ApCfg.BssidNum; i++) + { + struct wifi_dev * ez_wdev = &ad->ApCfg.ApCliTab[i].wdev; + + if (ez_wdev->ez_driver_params.ezdev + && ez_wdev->ez_driver_params.ez_wps_reconnect + && RTMP_TIME_AFTER(now, ez_wdev->ez_driver_params.ez_wps_reconnect_timestamp + 60*OS_HZ)) + { + ez_wdev->ez_driver_params.ez_wps_reconnect = FALSE; + NdisZeroMemory(ez_wdev->ez_driver_params.ez_wps_bssid,MAC_ADDR_LEN); + } + } +} + +BOOLEAN ez_port_secured( + void *ad_obj, + void *entry_obj, + unsigned char if_idx, + unsigned char ap_mode) +{ + + MAC_TABLE_ENTRY *entry; + struct wifi_dev *wdev; + entry = (MAC_TABLE_ENTRY *)entry_obj; + wdev = entry->wdev; + + entry->easy_setup_enabled = TRUE; + + if (wdev->wdev_type == WDEV_TYPE_STA) + { + APCLI_STRUCT *apcli_entry = wdev->func_dev; + apcli_entry->MlmeAux.attempted_candidate_index = EZ_INDEX_NOT_FOUND; + } + + if (wdev->ez_driver_params.ezdev) + return ez_port_secured_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, entry->Addr,ap_mode); + return 0; +} + +void increment_best_ap_rssi_threshold(struct wifi_dev *wdev) +{ + if (wdev->ez_driver_params.ezdev) + increment_best_ap_rssi_threshold_hook(wdev->ez_driver_params.ezdev); +} + +UCHAR ez_get_delay_disconnect_count(struct wifi_dev *wdev) +{ + if (wdev->ez_driver_params.ezdev) + { + ez_dev_t *ezdev = wdev->ez_driver_params.ezdev; + return ezdev->ez_security.delay_disconnect_count; + } + return 0; +} +#ifdef IF_UP_DOWN +BOOLEAN ez_all_intf_up(void *ez_ad) +{ + return ez_all_intf_up_hook(ez_ad); +} + +void ez_apcli_disconnect_both_intf(struct wifi_dev *wdev) +{ + ez_dev_t *ezdev = wdev->ez_driver_params.ezdev; + + ez_apcli_disconnect_both_intf_hook(ezdev, wdev->bssid); +} + +BOOLEAN ez_apcli_check_beacon_params(struct wifi_dev *wdev, beacon_info_tag_t beacon_info) +{ + ez_dev_t *ezdev = wdev->ez_driver_params.ezdev; + EZ_ADAPTER *ez_ad = NULL; + struct _ez_peer_security_info *ez_peer = NULL; + + if (ezdev == NULL) { + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s(line.%d) - Ezdev NULL.\n", + __func__, __LINE__)); + return FALSE; + } + ez_ad = ezdev->ez_ad; + /*check the node number and network weight of beacon with the ones stored with us.*/ + + ez_peer = ez_peer_table_search_by_addr(wdev, wdev->bssid); + + + if (ez_peer == NULL || ez_ad == NULL) { + /*Connected to third party AP*/ + return TRUE; + } + + if (!NdisEqualMemory(ez_ad->device_info.network_weight, beacon_info.network_weight, NETWORK_WEIGHT_LEN) + || !((ez_peer->device_info.ez_node_number.path_len == beacon_info.node_number.path_len) + && NdisEqualMemory(ez_peer->device_info.ez_node_number.root_mac, + beacon_info.node_number.root_mac, + beacon_info.node_number.path_len)) + ) { + + hex_dump("EzPeerWt", (PUCHAR)ez_ad->device_info.network_weight, NETWORK_WEIGHT_LEN); + hex_dump("BcnWt", (PUCHAR)beacon_info.network_weight, NETWORK_WEIGHT_LEN); + + hex_dump("EzPeerNN", (PUCHAR)&ez_peer->device_info.ez_node_number, sizeof(EZ_NODE_NUMBER)); + hex_dump("BcnNN", (PUCHAR)&beacon_info.node_number, sizeof(EZ_NODE_NUMBER)); + return FALSE; + } + return TRUE; +} + +#endif + +void ez_set_delay_disconnect_count(struct wifi_dev *wdev, unsigned char count) +{ + if (wdev->ez_driver_params.ezdev) + { + ez_dev_t *ezdev = wdev->ez_driver_params.ezdev; + ezdev->ez_security.delay_disconnect_count = count; + } +} + +void ez_acquire_lock(PRTMP_ADAPTER pAd, struct wifi_dev *wdev,unsigned char lock_id) +{ + if (pAd) + { + ez_acquire_lock_hook(pAd->ez_ad, NULL, lock_id); + } else if (wdev) + { + ez_acquire_lock_hook(NULL, (ez_dev_t *)wdev->ez_driver_params.ezdev, lock_id); + } +} + + +void ez_release_lock(PRTMP_ADAPTER pAd, struct wifi_dev *wdev,unsigned char lock_id) +{ + if (pAd) + { + ez_release_lock_hook((EZ_ADAPTER *)pAd->ez_ad, NULL, lock_id); + } else if (wdev) + { + ez_release_lock_hook(NULL, (ez_dev_t *)wdev->ez_driver_params.ezdev, lock_id); + } +} + +BOOLEAN ez_is_weight_same(struct wifi_dev *wdev, UCHAR * weight) +{ + if (wdev->ez_driver_params.ezdev) + { + return ez_is_weight_same_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, weight); + } + return FALSE; +} + +BOOLEAN ez_is_other_band_mlme_running(struct wifi_dev *wdev) +{ + if (!IS_CONF_EZ_SETUP_ENABLED(wdev)) + return FALSE; + + if (wdev->ez_driver_params.ezdev) + return ez_is_other_band_mlme_running_hook((ez_dev_t *)wdev->ez_driver_params.ezdev); + return FALSE; +} + +BOOLEAN ez_handle_scan_channel_restore(struct wifi_dev *wdev) +{ + if (wdev) { + if (wdev->ez_driver_params.scan_one_channel) { + wdev->ez_driver_params.scan_one_channel = FALSE; + return TRUE; + } + } + return FALSE; +} + +void ez_triband_insert_tlv(PRTMP_ADAPTER pAd, unsigned int tag_ID, UCHAR * buffer, ULONG* tag_len) +{ + if (pAd->ez_ad) + ez_triband_insert_tlv_hook((EZ_ADAPTER *)pAd->ez_ad, tag_ID, buffer,tag_len); +} + + +void ez_ap_peer_beacon_action(struct wifi_dev *ez_wdev, unsigned char * mac_addr, int capability, CHAR *RealRssi, BCN_IE_LIST *ie_list) +{ + //RTMP_ADAPTER *pAd = ez_wdev->sys_handle; + + if (ez_wdev->ez_driver_params.ezdev) { + ez_dev_t * ezdev = ez_wdev->ez_driver_params.ezdev; + ez_ap_peer_beacon_action_hook(ezdev, mac_addr, capability); + + +#ifdef EZ_REGROUP_SUPPORT + + if(IS_REGRP_SUPP(ez_wdev) && ez_wdev->channel == ie_list->Channel) + { + UINT8 band; + //UINT8 mac[6]= {0x20,0xaa,0x4b,0x6a,0x36,0x63}; + //printk("My SSID = %s\n", ezdev->ez_security.this_band_info.shared_info.ssid); + if(ez_wdev->channel <= 14) + band =0; + else + band = 1; + if((ie_list->vendor_ie.support_easy_setup == 1 && + ie_list->vendor_ie.open_group_id_len == ezdev->ez_security.open_group_id_len + && NdisEqualMemory(ie_list->vendor_ie.open_group_id,ezdev->ez_security.open_group_id,ie_list->vendor_ie.open_group_id_len)) + || + (ie_list->vendor_ie.support_easy_setup == 0 && + SSID_EQUAL(ezdev->ez_security.this_band_info.shared_info.ssid, + ezdev->ez_security.this_band_info.shared_info.ssid_len, + ie_list->Ssid, ie_list->SsidLen)) + ) + { + p_regrp_ap_info_struct ap_info = NULL; + + ap_info = ez_find_regrp_ap_by_bssid(regrp_ap_info[band],ie_list->Bssid); + if(ap_info == NULL) + { + ap_info = ez_add_regrp_ap(regrp_ap_info[band]); + printk("Added Entry: %02x:%02x:%02x:%02x:%02x:%02x, RSSI: %d\n",PRINT_MAC(ie_list->Bssid),*RealRssi); + } + if(ap_info != NULL) + { + ap_info->Non_MAN = !ie_list->vendor_ie.support_easy_setup; + COPY_MAC_ADDR(ap_info->bssid,ie_list->Bssid); + if(ap_info->Non_MAN == 0) + { + NdisCopyMemory(&ap_info->node_number, + &ie_list->vendor_ie.beacon_info.node_number, + sizeof(EZ_NODE_NUMBER)); + NdisCopyMemory(ap_info->nw_wt, + ie_list->vendor_ie.beacon_info.network_weight, + NETWORK_WEIGHT_LEN); + } + else + { + NdisZeroMemory(&ap_info->node_number, + sizeof(EZ_NODE_NUMBER)); + NdisZeroMemory(ap_info->nw_wt, + NETWORK_WEIGHT_LEN); + } + ap_info->last_rssi = *RealRssi; + ap_info->rx_cnt++; + ap_info->rssi_sum += *RealRssi; + if(ap_info->rx_cnt <= 0) + { + ap_info->rssi_sum = *RealRssi; + ap_info->rx_cnt = 1; + } + ap_info->avg_rssi = (CHAR)( (ap_info->rssi_sum)/(INT32)(ap_info->rx_cnt)); + NdisGetSystemUpTime(&ap_info->last_rx_time); + + + } + } + } +#endif + } +} + +void ez_handle_peer_disconnection(struct wifi_dev *wdev, unsigned char * mac_addr) +{ + if (wdev->ez_driver_params.ezdev && !wdev->ez_driver_params.ez_wps_reconnect) + { + ez_handle_peer_disconnection_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, mac_addr); + } +} + + +int ez_handle_send_packets(struct wifi_dev *wdev, PNDIS_PACKET pPacket) +{ + + //UCHAR *pDestAddr = GET_OS_PKT_DATAPTR(pPacket); + int ret = 1; + + if (wdev->ez_driver_params.ezdev){ + ret =ez_handle_send_packets_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, pPacket); + if( ret == 0) + RELEASE_NDIS_PACKET(wdev->sys_handle, pPacket, NDIS_STATUS_FAILURE); + } + return ret; +} + +BOOLEAN ez_sta_rx_pkt_handle(struct wifi_dev *wdev, RX_BLK *pRxBlk) +{ + if (wdev->ez_driver_params.ezdev) + return ez_sta_rx_pkt_handle_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, + pRxBlk->pData, pRxBlk->MPDUtotalByteCnt); + return 0; +} +BOOLEAN ez_apcli_rx_grp_pkt_drop( + IN struct wifi_dev *wdev, + IN struct sk_buff *pSkb) +{ + if (wdev->ez_driver_params.ezdev) + { + return ez_apcli_rx_grp_pkt_drop_hook((ez_dev_t *)wdev->ez_driver_params.ezdev,GET_OS_PKT_DATAPTR(pSkb)); + } + ASSERT(FALSE); + return FALSE; + +} + +BOOLEAN ez_apcli_tx_grp_pkt_drop(struct wifi_dev *wdev,struct sk_buff *pSkb) +{ + if (wdev->ez_driver_params.ezdev) + return ez_apcli_tx_grp_pkt_drop_hook((ez_dev_t *)wdev->ez_driver_params.ezdev,pSkb); + ASSERT(FALSE); + return FALSE; +} + + + +void ez_send_delay_disconnect_for_pbc(struct wifi_dev *wdev) +{ + PRTMP_ADAPTER ad = wdev->sys_handle; + struct wifi_dev *ap_wdev = &ad->ApCfg.MBSSID[wdev->func_idx].wdev; + + if(ap_wdev->ez_driver_params.ezdev) + { + send_delay_disconnect_to_peers_hook((ez_dev_t *)ap_wdev->ez_driver_params.ezdev); + } else { + ASSERT(FALSE); + } +} + +//Arvind : To be handle + + + +INT Set_EasySetup_Open_GenGroupID_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj; + UCHAR apidx; + UINT32 data_len; + struct wifi_dev * wdev; + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + +#ifdef APCLI_SUPPORT + if (pObj->ioctl_if_type == INT_APCLI) + { + wdev = &pAd->ApCfg.ApCliTab[apidx].wdev; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(apcli%d) %s:: This command is from apcli interface now.\n", + apidx, __FUNCTION__)); + } + else +#endif /* APCLI_SUPPORT */ + { + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("IF(ra%d) %s:: This command is from ra interface now.\n", + apidx, __FUNCTION__)); + } + + data_len = strlen(arg); + + if (wdev->ez_driver_params.ezdev){ + return ez_set_open_group_id_hook((ez_dev_t*)wdev->ez_driver_params.ezdev, + arg, data_len, apidx); + } else + { + return FALSE; + } + return TRUE; +} + +BOOLEAN ez_join_timeout_handle(void *ad_obj, unsigned char ifIndex) +{ + PRTMP_ADAPTER pAd = ad_obj; + PAPCLI_STRUCT pApCliEntry; + PULONG pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + BSS_TABLE *aux_bss_table; + + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + NdisZeroMemory(pApCliEntry->MlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pApCliEntry->MlmeAux.Ssid, MAX_LEN_OF_SSID); + pApCliEntry->MlmeAux.SsidLen = 0; + aux_bss_table = &pApCliEntry->MlmeAux.SsidBssTab; + if((pApCliEntry->MlmeAux.attempted_candidate_index != EZ_INDEX_NOT_FOUND) && + (pApCliEntry->MlmeAux.attempted_candidate_index <= aux_bss_table->BssNr) ){ + aux_bss_table->BssEntry[pApCliEntry->MlmeAux.attempted_candidate_index].bConnectAttemptFailed = TRUE; + } + if (IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev) && !ez_apcli_search_best_ap(pAd,pApCliEntry,ifIndex)){ + *pCurrState = APCLI_CTRL_DISCONNECTED; + return FALSE; + } + return TRUE; +} + +void ez_update_bss_entry(OUT BSS_ENTRY *pBss, IN BCN_IE_LIST *ie_list) +{ + NdisCopyMemory(&pBss->beacon_info,&ie_list->vendor_ie.beacon_info,sizeof(beacon_info_tag_t)); + NdisCopyMemory(pBss->open_group_id,ie_list->vendor_ie.open_group_id, ie_list->vendor_ie.open_group_id_len); + pBss->open_group_id_len = ie_list->vendor_ie.open_group_id_len; +} + + + +VOID APTribandUpdateChannelReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + printk("Not Implemented\n"); + return; +} + + +VOID EzTribandRestartNonEzReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + if (pAd->ez_ad) + APTribandRestartNonEzReqAction_hook((EZ_ADAPTER *)pAd->ez_ad); +} + + + +//! Levarage from MP1.0 CL#170063 +void EzRoamReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + + struct wifi_dev *wdev = (struct wifi_dev *)Elem->Priv; + BSS_ENTRY *pBssEntry = NULL; + ez_dev_t *ezdev = wdev->ez_driver_params.ezdev; + if (ezdev) + { + } else { + return; + } + /*if connection not already ongoing, then initiate a connection.*/ + pBssEntry = ez_find_roam_candidate(pAd, + ezdev->ez_security.ez_roam_info.ez_apcli_roam_bssid, + wdev); + if (pBssEntry!= NULL){ + ez_roam(wdev, pBssEntry); + return; + } + else { + MTWF_LOG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("bss entry for this bssid not found!!\n")); + ez_reset_roam_bssid_hook((ez_dev_t *)wdev->ez_driver_params.ezdev); + + return; + } +} + + +void EzPeriodicExecAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + if (IS_ADPTR_EZ_SETUP_ENABLED(pAd)) + ez_peer_table_maintenance(pAd); +} + + +void EzUpdateSsidPskAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + ez_update_ssid_psk_msg_t *ez_update_ssid_psk_msg = (ez_update_ssid_psk_msg_t *)Elem->Msg; + struct wifi_dev *wdev = (struct wifi_dev *)Elem->Priv; + set_ssid_psk_hook((ez_dev_t *)wdev->ez_driver_params.ezdev, + ez_update_ssid_psk_msg->ssid1, ez_update_ssid_psk_msg->pmk1, ez_update_ssid_psk_msg->psk1, + ez_update_ssid_psk_msg->ssid2, ez_update_ssid_psk_msg->pmk2, ez_update_ssid_psk_msg->psk2, + ez_update_ssid_psk_msg->ssid3, ez_update_ssid_psk_msg->pmk3, ez_update_ssid_psk_msg->psk3, + ez_update_ssid_psk_msg->EncrypType1, ez_update_ssid_psk_msg->EncrypType2, + ez_update_ssid_psk_msg->AuthMode1, ez_update_ssid_psk_msg->AuthMode2); +} + +VOID EzStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]) +{ + StateMachineInit(Sm, (STATE_MACHINE_FUNC *)Trans, EZ_MAX_STATE, EZ_MAX_MSG, (STATE_MACHINE_FUNC)Drop, EZ_IDLE, EZ_MACHINE_BASE); + StateMachineSetAction(Sm, EZ_IDLE, EZ_ROAM_REQ, (STATE_MACHINE_FUNC)EzRoamReqAction); + StateMachineSetAction(Sm, EZ_IDLE, EZ_TRIBAND_RESTART_NON_EZ_REQ, (STATE_MACHINE_FUNC)EzTribandRestartNonEzReqAction); + StateMachineSetAction(Sm, EZ_IDLE, EZ_PERIODIC_EXEC_REQ, (STATE_MACHINE_FUNC)EzPeriodicExecAction); + StateMachineSetAction(Sm, EZ_IDLE, EZ_UPDATE_SSID_PSK_REQ, (STATE_MACHINE_FUNC)EzUpdateSsidPskAction); + +} + +VOID ez_ApCliCtrlJoinFailAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + PAPCLI_STRUCT pApCliEntry; + USHORT ifIndex = (USHORT)(Elem->Priv); + PULONG pCurrState = &pAd->ApCfg.ApCliTab[ifIndex].CtrlCurrState; + BSS_TABLE *aux_bss_table; + APCLI_MLME_JOIN_REQ_STRUCT JoinReq; + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("(%s)\n", __FUNCTION__)); + + { + struct wifi_dev *ap_wdev = &pAd->ApCfg.MBSSID[ifIndex].wdev; + ez_restore_channel_config(ap_wdev); + NdisZeroMemory(pAd->ApCfg.ApCliTab[ifIndex].CfgSsid,MAX_LEN_OF_SSID); + pAd->ApCfg.ApCliTab[ifIndex].CfgSsidLen = 0; + pAd->ApCfg.ApCliTab[ifIndex].CfgSsidLen = pAd->ApCfg.MBSSID[ifIndex].SsidLen; + NdisCopyMemory(pAd->ApCfg.ApCliTab[ifIndex].CfgSsid,pAd->ApCfg.MBSSID[ifIndex].Ssid,pAd->ApCfg.MBSSID[ifIndex].SsidLen); + } + if (ifIndex >= MAX_APCLI_NUM) + return; + pApCliEntry = &pAd->ApCfg.ApCliTab[ifIndex]; + if (ApScanRunning(pAd) == TRUE) + { + ez_update_connection_permission(pAd,&pApCliEntry->wdev,EZ_ALLOW_ALL); + *pCurrState = APCLI_CTRL_DISCONNECTED; + return; + } + +#ifdef EZ_API_SUPPORT + if (pApCliEntry->wdev.ez_driver_params.ez_api_mode == CONNECTION_OFFLOAD) + { + ez_dev_t * ezdev = pApCliEntry->wdev.ez_driver_params.ezdev; + if(ezdev){ + NdisZeroMemory(ezdev->ez_security.ez_apcli_force_bssid,MAC_ADDR_LEN); + } +#ifdef SYSTEM_LOG_SUPPORT + RTMPSendWirelessEvent(pAd, IW_WH_EZ_MY_APCLI_DISCONNECTED, NULL, pApCliEntry->wdev.wdev_idx, 0); +#else /* SYSTEM_LOG_SUPPORT */ + RtmpOSWrielessEventSend(pApCliEntry->wdev.if_dev, RT_WLAN_EVENT_CUSTOM, IW_WH_EZ_MY_APCLI_DISCONNECTED, + NULL, NULL, 0); +#endif /* !SYSTEM_LOG_SUPPORT */ + } +#endif + + NdisZeroMemory(pApCliEntry->MlmeAux.Bssid, MAC_ADDR_LEN); + NdisZeroMemory(pApCliEntry->MlmeAux.Ssid, MAX_LEN_OF_SSID); + pApCliEntry->MlmeAux.SsidLen = 0; + aux_bss_table = &pApCliEntry->MlmeAux.SsidBssTab; + if((pApCliEntry->MlmeAux.attempted_candidate_index != EZ_INDEX_NOT_FOUND) && + (pApCliEntry->MlmeAux.attempted_candidate_index <= aux_bss_table->BssNr) ){ + aux_bss_table->BssEntry[pApCliEntry->MlmeAux.attempted_candidate_index].bConnectAttemptFailed = TRUE; + } +#ifdef APCLI_AUTO_CONNECT_SUPPORT + pApCliEntry->ProbeReqCnt = 0; +#endif + pApCliEntry->AuthReqCnt = 0; + pApCliEntry->AssocReqCnt = 0; + *pCurrState = APCLI_CTRL_PROBE; + NdisZeroMemory(&JoinReq, sizeof(APCLI_MLME_JOIN_REQ_STRUCT)); + +#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 (IS_EZ_SETUP_ENABLED(&pApCliEntry->wdev) + && !pApCliEntry->wdev.ez_driver_params.ez_wps_reconnect) + { + if (!ez_update_connection_permission(pAd,&pApCliEntry->wdev,EZ_DISALLOW_ALL_ALLOW_ME)) + { + *pCurrState = APCLI_CTRL_DISCONNECTED; + return; + } + if(!ez_apcli_search_best_ap(pAd,pApCliEntry,ifIndex)) + { + *pCurrState = APCLI_CTRL_DISCONNECTED; + if(pApCliEntry->wdev.ez_driver_params.ezdev){ + if (!ez_update_connection_permission_hook(pApCliEntry->wdev.ez_driver_params.ezdev + ,EZ_ALLOW_ALL)) + { + ASSERT(FALSE); + } + } + return; + } + } + + if (pApCliEntry->CfgSsidLen != 0) + { + JoinReq.SsidLen = pApCliEntry->CfgSsidLen; + NdisMoveMemory(&(JoinReq.Ssid), pApCliEntry->CfgSsid, JoinReq.SsidLen); + } + } + + if (!MAC_ADDR_EQUAL(pApCliEntry->CfgApCliBssid, ZERO_MAC_ADDR)) + { + COPY_MAC_ADDR(JoinReq.Bssid, pApCliEntry->CfgApCliBssid); + } + + EZ_DEBUG(DBG_CAT_CLIENT, DBG_SUBCAT_ALL, DBG_LVL_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; +} + +BOOLEAN ascii2int(RTMP_STRING *in, UINT32 *out) +{ + UINT32 decimal_val, val; + CHAR *p, asc_val; + decimal_val = 0; + p = (char *)in; + while((*p) != 0) + { + val = 0; + asc_val = *p; + if ((asc_val >= '0') && (asc_val <= '9')) + val = asc_val - 48; + else + return FALSE; + decimal_val = (decimal_val * 10) + val; + p++; + } + *out = decimal_val; + return TRUE; +} + +VOID RTMPIoctlGetEzScanTable( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq) +{ + RTMP_STRING *msg; + INT i=0; + INT WaitCnt; + INT Status=0; + INT max_len = LINE_LEN; + RTMP_STRING *this_char; + UINT32 bss_start_idx; + BSS_ENTRY *pBss; + UINT32 TotalLen, BufLen = IW_SCAN_MAX_DATA; + + this_char = wrq->u.data.pointer; + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s(): Before check, this_char = %s\n" , + __FUNCTION__, this_char)); + if (ascii2int(this_char, &bss_start_idx) == FALSE) + bss_start_idx = 0; + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s(): After check, this_char = %s, out = %d\n" , + __FUNCTION__, this_char, bss_start_idx)); + + TotalLen = sizeof(CHAR)*((MAX_LEN_OF_BSS_TABLE)*max_len) + 100; + + BufLen = IW_SCAN_MAX_DATA; + + os_alloc_mem(NULL, (PUCHAR *)&msg, TotalLen); + + if (msg == NULL) + { + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s(): msg memory alloc fail.\n", + __FUNCTION__)); + return; + } + + memset(msg, 0 , TotalLen); + if (pAdapter->ScanTab.BssNr ==0) { + sprintf(msg,"No BssInfo\n"); + wrq->u.data.length = strlen(msg); + Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s(): wrq->u.data.length = %d\n", + __FUNCTION__, wrq->u.data.length)); + os_free_mem(pAdapter, (PUCHAR)msg); + return; + } + if (bss_start_idx > (pAdapter->ScanTab.BssNr-1)) { + sprintf(msg,"BssInfo Idx(%d) is out of range(0~%d)\n", + bss_start_idx, (pAdapter->ScanTab.BssNr-1)); + wrq->u.data.length = strlen(msg); + Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s(): wrq->u.data.length = %d\n", __FUNCTION__, wrq->u.data.length)); + os_free_mem(pAdapter, (PUCHAR)msg); + return; + } + sprintf(msg,"%s","\n"); + sprintf(msg+strlen(msg),"%s","\n"); + sprintf(msg+strlen(msg),"%-12s%-4s%-33s%-20s%-23s%-9s%-7s%-7s%-3s\n", + " Capability", "Ch", "SSID", "BSSID", "Security", "Siganl(%)", "W-Mode", " ExtCH"," NT"); + + WaitCnt = 0; + + while ((ScanRunning(pAdapter) == TRUE) && (WaitCnt++ < 200)) + OS_WAIT(500); + + for(i=bss_start_idx; iScanTab.BssNr ;i++) + { + pBss = &pAdapter->ScanTab.BssEntry[i]; + + if (pBss->support_easy_setup) { + if( pBss->Channel==0) + break; + + if((strlen(msg)+100 ) >= BufLen) + break; + + /* + EZ Capability + */ + sprintf(msg+strlen(msg)," 0x%-9x", pBss->easy_setup_capability); + + RTMPCommSiteSurveyData(msg, pBss, TotalLen); + } + + } + wrq->u.data.length = strlen(msg); + Status = copy_to_user(wrq->u.data.pointer, msg, wrq->u.data.length); + + MTWF_LOG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s(): wrq->u.data.length = %d\n", __FUNCTION__, wrq->u.data.length)); + os_free_mem(pAdapter, (PUCHAR)msg); +} + + +INT Set_EasySetup_Best_Ap_RSSI_Threshold(RTMP_ADAPTER *pAd, RTMP_STRING *arg) +{ + char *value; + int i; + EZ_ADAPTER *ez_ad = pAd->ez_ad; + if (ez_ad == NULL) + return FALSE; + for (i=0, value = rstrtok(arg,";"); value; value = rstrtok(NULL,";"), i++) + { + if (i == 0) + { + ez_ad->best_ap_rssi_threshld_max = simple_strtol(value, 0, 10); + } else { + ez_ad->best_ap_rssi_threshld[i - 1] = simple_strtol(value, 0, 10); + } + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("%d;", ez_ad->best_ap_rssi_threshld[i])); + } + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("\n")); + return TRUE; +} + +BOOLEAN ez_ap_tx_grp_pkt_drop_to_ez_apcli(struct wifi_dev *wdev,struct sk_buff *pSkb) +{ + if (wdev->ez_driver_params.ezdev) + return ez_ap_tx_grp_pkt_drop_to_ez_apcli_hook(wdev->ez_driver_params.ezdev,pSkb); + + return FALSE; +} + +void ez_init( + void *ad_obj, + void *wdev_obj, + unsigned char ap_mode) +{ + PRTMP_ADAPTER ad = ad_obj; + EZ_ADAPTER *ez_ad; + struct wifi_dev *wdev = wdev_obj; +/* + if (!IS_EZ_SETUP_ENABLED(wdev)) { + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - easy setup function is disabled.(wdev_type=0x%x)\n", + __func__, wdev->wdev_type)); + return; + } +*/ + EZ_DEBUG(DBG_CAT_INIT, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("ez_init(), %s\n", wdev->if_dev->name)); + + ez_ad = ez_init_hook(ad_obj, wdev_obj, ap_mode); + ad->ez_ad = ez_ad; + ad->SingleChip = &ez_ad->SingleChip; + wdev->ez_driver_params.ez_started = FALSE; + +#ifdef EZ_REGROUP_SUPPORT + NdisAllocateSpinLock(ad, &wdev->ez_driver_params.regrp_mode_lock); + wdev->ez_driver_params.regrp_mode = NON_REGRP_MODE; + EZ_DEBUG(DBG_CAT_INIT, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("\n[REGROUP] => Regroup Support = %d\n",wdev->ez_driver_params.en_regrp_supp)); +#endif +} + +void ez_init_ap_security_settings(struct wifi_dev *wdev) +{ + + BSS_STRUCT *ap_mbss = wdev->func_dev; + if (wdev->ez_driver_params.default_pmk_valid){ + + ap_mbss->SsidLen = wdev->ez_driver_params.default_ssid_len; + NdisCopyMemory(ap_mbss->Ssid,wdev->ez_driver_params.default_ssid,wdev->ez_driver_params.default_ssid_len); + NdisCopyMemory(ap_mbss->PMK, wdev->ez_driver_params.default_pmk, LEN_PMK); + //NdisCopyMemory(ap_mbss->PMK,wdev->SecConfig.PMK,LEN_PMK); + } else { + RT_CfgSetWPAPSKKey(wdev->sys_handle, ap_mbss->PSK, strlen(ap_mbss->PSK), + ap_mbss->Ssid, ap_mbss->SsidLen, ap_mbss->PMK); + //NdisCopyMemory(wdev->SecConfig.PMK,ap_mbss->PMK,LEN_PMK); + } + + SET_AUTHMODE_WPA2PSK(wdev->AuthMode); + SET_ENCRYTYPE_AES(wdev->WepStatus); + SET_ENCRYTYPE_AES(wdev->GroupKeyWepStatus); + //SetWdevEncrypMode(&wdev->SecConfig, "AES"); + //SetWdevAuthMode(&wdev->SecConfig, "WPA2PSK"); + ap_security_init(wdev->sys_handle, wdev, wdev->func_idx); + ap_key_tb_init(wdev->sys_handle); +} + +void ez_init_apcli_settings(struct wifi_dev *wdev) +{ + BSS_STRUCT *ap_mbss; + PRTMP_ADAPTER ad = wdev->sys_handle; + APCLI_STRUCT *apcli_entry; + ap_mbss = &ad->ApCfg.MBSSID[wdev->func_idx]; + apcli_entry = &ad->ApCfg.ApCliTab[wdev->func_idx]; + apcli_entry->MlmeAux.SsidBssTab.BssNr = 0; + apcli_entry->MlmeAux.attempted_candidate_index = EZ_INDEX_NOT_FOUND; + apcli_entry->avoid_loop = TRUE; + apcli_entry->stop_auto_connect = FALSE; + apcli_entry->CfgSsidLen = ap_mbss->SsidLen; + NdisCopyMemory(apcli_entry->PMK, ap_mbss->PMK, LEN_PMK); + NdisCopyMemory(apcli_entry->CfgSsid, ap_mbss->Ssid, ap_mbss->SsidLen); +} + +void ez_init_shared_params(ez_init_params_t *init_params, struct wifi_dev *wdev) +{ + PRTMP_ADAPTER ad = wdev->sys_handle; + EZ_ADAPTER *ez_ad = ad->ez_ad; + BSS_STRUCT *ap_mbss; + ap_mbss = &ad->ApCfg.MBSSID[wdev->func_idx]; + init_params->ad_obj = wdev->sys_handle; + init_params->wdev_obj = wdev; + init_params->ezdev_type = wdev->wdev_type; + + COPY_MAC_ADDR(init_params->mac_add, wdev->if_addr); + if (wdev->wdev_type == WDEV_TYPE_AP){ + NdisCopyMemory(init_params->ssid, + ((BSS_STRUCT *)(wdev->func_dev))->Ssid, + ((BSS_STRUCT *)(wdev->func_dev))->SsidLen); + init_params->ssid_len = ((BSS_STRUCT *)(wdev->func_dev))->SsidLen; + NdisCopyMemory(init_params->pmk, ((BSS_STRUCT *)(wdev->func_dev))->PMK,PMK_LEN); + } else { + NdisCopyMemory(init_params->ssid, + ((APCLI_STRUCT *)(wdev->func_dev))->CfgSsid, + ((APCLI_STRUCT *)(wdev->func_dev))->CfgSsidLen); + init_params->ssid_len = ((APCLI_STRUCT *)(wdev->func_dev))->CfgSsidLen; + NdisCopyMemory(init_params->pmk, ((APCLI_STRUCT *)(wdev->func_dev))->PMK,PMK_LEN); + init_params->ezdev_type = WDEV_TYPE_APCLI; + } + + //NdisCopyMemory(init_params->pmk,wdev->SecConfig.PMK,PMK_LEN); + + init_params->group_id_len = wdev->ez_driver_params.group_id_len; + init_params->ez_group_id_len = wdev->ez_driver_params.ez_group_id_len; //for localy maintain EzGroupID + init_params->gen_group_id_len = wdev->ez_driver_params.gen_group_id_len; //for localy maintain EzGenGroupID + + init_params->group_id = wdev->ez_driver_params.group_id; + init_params->ez_group_id= wdev->ez_driver_params.ez_group_id; //for localy maintain EzGroupID + init_params->gen_group_id= wdev->ez_driver_params.gen_group_id; //for localy maintain EzGenGroupID + + NdisCopyMemory(init_params->open_group_id, + wdev->ez_driver_params.open_group_id, + wdev->ez_driver_params.open_group_id_len); + + init_params->open_group_id_len = wdev->ez_driver_params.open_group_id_len; + wdev->ez_driver_params.ez_api_mode = ez_ad->ez_api_mode; + init_params->driver_ops_lut = &ez_driver_ops_7603; + init_params->func_idx = wdev->func_idx; + init_params->channel = &ad->CommonCfg.Channel;//&wdev->channel; + + init_params->ez_scan_timer = &wdev->ez_driver_params.ez_scan_timer; + //init_params->ez_stop_scan_timer = &wdev->ez_driver_params.ez_stop_scan_timer; + init_params->ez_scan_pause_timer = &wdev->ez_driver_params.ez_scan_pause_timer; + init_params->ez_group_merge_timer = &wdev->ez_driver_params.ez_group_merge_timer; + init_params->ez_connect_wait_timer = &wdev->ez_driver_params.ez_connect_wait_timer; + init_params->ez_loop_chk_timer = &wdev->ez_driver_params.ez_loop_chk_timer; + init_params->os_hz = OS_HZ; + + init_params->channel_info.ht_bw = ad->CommonCfg.RegTransmitSetting.field.BW; + init_params->channel_info.vht_bw = 0; + init_params->channel_info.channel = ad->CommonCfg.Channel; //wdev->channel; + init_params->channel_info.extcha = ad->CommonCfg.RegTransmitSetting.field.EXTCHA; + init_params->default_group_data_band = wdev->ez_driver_params.default_group_data_band; +#ifdef IF_UP_DOWN + init_params->ez_intf_count_config_ap = wdev->ez_driver_params.ez_intf_count_config_ap; + init_params->ez_intf_count_config_cli = wdev->ez_driver_params.ez_intf_count_config_cli; + init_params->non_ez_intf_count_config_ap = 0; + init_params->non_ez_intf_count_config_cli = 0; +#endif +} + +VOID ez_scan_timeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + ez_driver_params_t *ez_driver_params; + + if (FunctionContext) { + ez_driver_params = (ez_driver_params_t *)FunctionContext; + if (ez_driver_params->ez_scan_timer.ez_timer_running) { + + ez_driver_params->ez_scan_timer.ez_timer_running = FALSE; + if(ez_driver_params->ezdev){ + ez_scan_timeout_hook(ez_driver_params->ezdev); + } + } + else { + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - Timer expired but timer running flag is FALSE. Do nothing here.\n", + __FUNCTION__)); + } + } + else { + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - FunctionContext is null?? CHECK!!\n", __FUNCTION__)); + } +} + +VOID ez_scan_pause_timeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + ez_driver_params_t *ez_driver_params; + ez_dev_t *ezdev; + RTMP_ADAPTER *ad; + struct wifi_dev *wdev; +#ifdef APCLI_SUPPORT + APCLI_STRUCT *apcli_entry; +#endif + + if (FunctionContext) { + ez_driver_params = (ez_driver_params_t *)FunctionContext; + ezdev = ez_driver_params->ezdev; + if(ezdev){ + + wdev = ezdev->wdev; + ad = wdev->sys_handle; + + //RTMP_SEM_LOCK(&ez_sec_info->ez_scan_pause_timer_lock); + ez_acquire_lock(NULL, wdev,SCAN_PAUSE_TIMER_LOCK); + if (ez_driver_params->ez_scan_pause_timer.ez_timer_running) { + ez_driver_params->ez_scan_pause_timer.ez_timer_running = FALSE; + +#ifdef APCLI_SUPPORT + /* Timeout for peer apcli to conenct to my ap is over. + Allow scan on apcli interface now. + */ + apcli_entry = &ad->ApCfg.ApCliTab[wdev->func_idx]; + apcli_entry->stop_auto_connect = FALSE; + + // Let internal periodic apcli join logic handle when to resume scan + +#endif /* APCLI_SUPPORT */ + + } + else { + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - Timer expired but timer running flag is FALSE. Do nothing here.\n", + __FUNCTION__)); + } + + ez_release_lock(NULL, wdev,SCAN_PAUSE_TIMER_LOCK); + + } + } + else { + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - FunctionContext is null?? CHECK!!\n", __FUNCTION__)); + } +} + +VOID ez_group_merge_timeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + ez_driver_params_t *ez_driver_params; + ez_driver_params = (ez_driver_params_t *)FunctionContext; + ez_driver_params->ez_group_merge_timer.ez_timer_running = FALSE; + + if(ez_driver_params->ezdev) + ez_group_merge_timeout_hook(ez_driver_params->ezdev); + +} + + +void ez_wait_for_connection_allow_timeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + ez_driver_params_t *ez_driver_params; + + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,(" %s -->\n", __FUNCTION__)); + + if (FunctionContext) { + ez_driver_params = (ez_driver_params_t *)FunctionContext; + if (ez_driver_params->ez_connect_wait_timer.ez_timer_running) { + ez_driver_params->ez_connect_wait_timer.ez_timer_running = FALSE; + if(ez_driver_params->ezdev) + ez_update_connection_permission_hook(ez_driver_params->ezdev,EZ_ALLOW_ALL_TIMEOUT); + } + else { + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - Timer expired but timer running flag is FALSE. Do nothing here.\n", + __FUNCTION__)); + } + } + else { + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - FunctionContext is null?? CHECK!!\n", __FUNCTION__)); + } +} + +/* Loop Check timeout handler*/ +VOID ez_loop_chk_timeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3) +{ + ez_driver_params_t * ez_driver_params = NULL; + if(FunctionContext){ + ez_driver_params = (ez_driver_params_t *)FunctionContext; + + if(ez_driver_params->ez_loop_chk_timer.ez_timer_running){ + + //EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("ez_loop_chk_timeout : wdev_idx=0x%x, wdev_type=0x%x, func_idx=0x%x :clear loop chk context\n", + // wdev->wdev_idx,wdev->wdev_type,wdev->func_idx)); + + ez_driver_params->ez_loop_chk_timer.ez_timer_running = FALSE; + + if(ez_driver_params->ezdev) + ez_loop_chk_timeout_hook(ez_driver_params->ezdev); + } + else{ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("ERROR !!! ez_loop_chk_timeout: not found mac entry\n")); + } + } + else{ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("ez_loop_chk_timeout: FunctionContext NULL !!!\n")); + } + +} + +void ez_start( + void *wdev_obj, + unsigned char ap_mode) +{ + struct wifi_dev *wdev; + //struct _ez_security *ez_security; + ez_init_params_t init_params; + PRTMP_ADAPTER ad; + EZ_ADAPTER *ez_ad; + + wdev = (struct wifi_dev *)wdev_obj; + ad = wdev->sys_handle; + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("------> %s(%s)\n", __func__, wdev->if_dev->name)); + +/* if (!IS_EZ_SETUP_ENABLED(wdev)) { + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s - easy setup function is disabled.(wdev_type=0x%x)\n", + __FUNCTION__, wdev->wdev_type)); + return; + } +*/ + + NdisAcquireSpinLock(&ad->Mlme.TaskLock); + if (wdev->ez_driver_params.ez_started == TRUE) { + NdisReleaseSpinLock(&ad->Mlme.TaskLock); + DBGPRINT(RT_DEBUG_ERROR, ("easy-setup already started, skip ez_start.\n")); + return; + } + wdev->ez_driver_params.ez_started = TRUE; + + if (wdev->ez_driver_params.group_id_len == 0) { + wdev->ez_driver_params.ez_started = FALSE; + NdisReleaseSpinLock(&ad->Mlme.TaskLock); + + /*Do NOT start easy function if there is no group id information.*/ + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("%s - No group id information. return and don't start easy set up.\n", + __func__)); + return; + } + NdisReleaseSpinLock(&ad->Mlme.TaskLock); + + if (wdev->wdev_type == WDEV_TYPE_AP) + ez_init_ap_security_settings(wdev); + + if (wdev->wdev_type == WDEV_TYPE_STA) + ez_init_apcli_settings(wdev); + + EZ_TIMER_INIT(ad, &wdev->ez_driver_params, + &wdev->ez_driver_params.ez_scan_timer.ez_timer, + wdev->ez_driver_params.ez_scan_timer.ez_timer_running, + ez_scan_timeout); + EZ_TIMER_INIT(ad, &wdev->ez_driver_params, + &wdev->ez_driver_params.ez_scan_pause_timer.ez_timer, + wdev->ez_driver_params.ez_scan_pause_timer.ez_timer_running, + ez_scan_pause_timeout); +#ifdef EZ_NETWORK_MERGE_SUPPORT + EZ_TIMER_INIT(ad, &wdev->ez_driver_params, + &wdev->ez_driver_params.ez_group_merge_timer.ez_timer, + wdev->ez_driver_params.ez_group_merge_timer.ez_timer_running, + ez_group_merge_timeout); +#endif +#ifdef NEW_CONNECTION_ALGO + EZ_TIMER_INIT(ad,&wdev->ez_driver_params, + &wdev->ez_driver_params.ez_connect_wait_timer.ez_timer, + wdev->ez_driver_params.ez_connect_wait_timer.ez_timer_running, + ez_wait_for_connection_allow_timeout); +#endif +#ifdef EZ_DUAL_BAND_SUPPORT + EZ_TIMER_INIT(ad, &wdev->ez_driver_params, + &wdev->ez_driver_params.ez_loop_chk_timer.ez_timer, + wdev->ez_driver_params.ez_loop_chk_timer.ez_timer_running, + ez_loop_chk_timeout); +#endif + +#ifdef EZ_REGROUP_SUPPORT + wdev->ez_driver_params.regrp_mode = NON_REGRP_MODE; + EZ_DEBUG(DBG_CAT_INIT, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("\n[REGROUP] => Regroup Support = %d\n",wdev->ez_driver_params.en_regrp_supp)); + wdev->ez_driver_params.ap_entry_count = 0; + NdisZeroMemory(&wdev->ez_driver_params.ap_list[0], MAX_AP_CANDIDATES * sizeof(struct _drvr_cand_list)); +#endif + + ez_init_shared_params(&init_params,wdev); + wdev->ez_driver_params.ezdev = ez_start_hook(&init_params); + + wdev->ez_driver_params.ez_ad = ez_get_adapter_hook(); + + printk("sizeof EZ_ADAPTER = %d\n", sizeof(EZ_ADAPTER)); + printk("sizeof ez_dev_t = %d\n", sizeof(ez_dev_t)); + + + ez_ad = wdev->ez_driver_params.ez_ad; + if (ez_ad->sanity_check1 == &ez_ad->sanity_check1) + { + printk("content of sanity1 ==== %p\n", ez_ad->sanity_check1); + printk("Address of sanity1 ==== %p\n", &ez_ad->sanity_check1); + printk("1 passed\n"); + } else { + printk("content of sanity1 ==== %p\n", ez_ad->sanity_check1); + printk("Address of sanity1 ==== %p\n", &ez_ad->sanity_check1); + } + + if (ez_ad->sanity_check == &ez_ad->sanity_check) + { + printk("content of sanity ==== %p\n", ez_ad->sanity_check); + printk("Address of sanity ==== %p\n", &ez_ad->sanity_check); + + printk("DRIVER MOD structures are in sync\n"); + } else { + printk("content of sanity ==== %p\n", ez_ad->sanity_check); + printk("Address of sanity ==== %p\n", &ez_ad->sanity_check); + + printk("DRIVER MOD structures do not match\n"); + + } +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) + if ((wf_fwd_set_easy_setup_mode != NULL) && (wdev->ez_driver_params.ez_api_mode != CONNECTION_OFFLOAD)){ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("SET EASY SETUP MODE IN FWD MODULE\n")); + wf_fwd_set_easy_setup_mode(TRUE); // Arvind Need to handle + } +#endif + + if (ap_mode) { + + UpdateBeaconHandler(ad, wdev, IE_CHANGE); + } + + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("<------ %s()\n", __FUNCTION__)); +} + + + +void ez_stop( + void *wdev_obj) +{ + struct wifi_dev *wdev; + PRTMP_ADAPTER pAd; + BOOLEAN is_triband = FALSE; + ez_timer_t *ptimer; + + wdev = (struct wifi_dev *)wdev_obj; + pAd = wdev->sys_handle; + is_triband = ez_is_triband(); + + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("-->%s(%s): wdev_type=0x%x\n", __func__, wdev->if_dev->name, wdev->wdev_type)); + + while(1) + { + if (IS_DUAL_CHIP_DBDC(pAd) && !is_triband) + { + ez_acquire_lock(pAd, NULL, MLME_SYNC_LOCK); + } + NdisAcquireSpinLock(&pAd->Mlme.TaskLock); + + if (wdev->ez_driver_params.ez_started == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, ("easy-setup already stopped, skip ez_stop.\n")); + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + if (IS_DUAL_CHIP_DBDC(pAd) && !is_triband) + ez_release_lock(pAd, NULL, MLME_SYNC_LOCK); + return; + } + + if (pAd->Mlme.bRunning == FALSE) { + if (IS_DUAL_CHIP_DBDC(pAd) && !is_triband) { + if (ez_is_other_band_mlme_running(&pAd->ApCfg.MBSSID[0].wdev)) { + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + ez_release_lock(pAd, NULL, MLME_SYNC_LOCK); + RtmpusecDelay(5000); + continue; + } + } + + wdev->ez_driver_params.ez_started = FALSE; + if (wdev->ez_driver_params.ezdev) { + ez_stop_hook(wdev->ez_driver_params.ezdev); + wdev->ez_driver_params.ezdev = NULL; + } + +#if defined (CONFIG_WIFI_PKT_FWD) + /*if (IS_EZ_SETUP_ENABLED(wdev) && (wf_fwd_set_easy_setup_mode != NULL)){*/ + if (wf_fwd_set_easy_setup_mode != NULL) { + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("CLEAR EASY SETUP MODE IN FWD MODULE\n")); + wf_fwd_set_easy_setup_mode(FALSE); /* Arvind Need to handle*/ + } +#endif +#ifdef EZ_REGROUP_SUPPORT + wdev->ez_driver_params.ap_entry_count = 0; + NdisZeroMemory(&wdev->ez_driver_params.ap_list[0], + MAX_AP_CANDIDATES * sizeof(struct _drvr_cand_list)); + wdev->ez_driver_params.regrp_mode = NON_REGRP_MODE; + EZ_DEBUG(DBG_CAT_INIT, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("\n[REGROUP] => Regroup Support = %d\n", wdev->ez_driver_params.en_regrp_supp)); +#endif + + ptimer = &wdev->ez_driver_params.ez_scan_timer; + if (ptimer->ez_timer_running == TRUE) + EZ_CANCEL_TIMER(&ptimer->ez_timer, ptimer->ez_timer_running); + EZ_RELEASE_TIMER(&ptimer->ez_timer, ptimer->ez_timer_running); + + ptimer = &wdev->ez_driver_params.ez_scan_pause_timer; + if (ptimer->ez_timer_running == TRUE) + EZ_CANCEL_TIMER(&ptimer->ez_timer, ptimer->ez_timer_running); + EZ_RELEASE_TIMER(&ptimer->ez_timer, ptimer->ez_timer_running); + +#ifdef EZ_NETWORK_MERGE_SUPPORT + ptimer = &wdev->ez_driver_params.ez_group_merge_timer; + if (ptimer->ez_timer_running == TRUE) + EZ_CANCEL_TIMER(&ptimer->ez_timer, ptimer->ez_timer_running); + EZ_RELEASE_TIMER(&ptimer->ez_timer, ptimer->ez_timer_running); +#endif + +#ifdef NEW_CONNECTION_ALGO + ptimer = &wdev->ez_driver_params.ez_connect_wait_timer; + if (ptimer->ez_timer_running == TRUE) + EZ_CANCEL_TIMER(&ptimer->ez_timer, ptimer->ez_timer_running); + EZ_RELEASE_TIMER(&ptimer->ez_timer, ptimer->ez_timer_running); +#endif + +#ifdef EZ_DUAL_BAND_SUPPORT + ptimer = &wdev->ez_driver_params.ez_loop_chk_timer; + if (ptimer->ez_timer_running == TRUE) + EZ_CANCEL_TIMER(&ptimer->ez_timer, ptimer->ez_timer_running); + EZ_RELEASE_TIMER(&ptimer->ez_timer, ptimer->ez_timer_running); +#endif + + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + if (IS_DUAL_CHIP_DBDC(pAd) && !is_triband) + ez_release_lock(pAd, NULL, MLME_SYNC_LOCK); + break; + } + NdisReleaseSpinLock(&pAd->Mlme.TaskLock); + if (IS_DUAL_CHIP_DBDC(pAd) && !is_triband) + ez_release_lock(pAd, NULL, MLME_SYNC_LOCK); + RtmpusecDelay(5000); + } + + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("<------ %s()\n", __FUNCTION__)); +} + +INT Set_ez_connection_allow_all( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg) +{ + POS_COOKIE pObj; + UCHAR apidx; + struct wifi_dev *wdev; + + pObj = (POS_COOKIE) pAd->OS_Cookie; + apidx = pObj->ioctl_if; + + wdev = &pAd->ApCfg.MBSSID[apidx].wdev; + if (IS_EZ_SETUP_ENABLED(wdev) && pAd->ez_ad) { + ez_connection_allow_all_hook(pAd->ez_ad, wdev->ez_driver_params.default_pmk_valid); + return TRUE; + } + printk("Ez setup not activated on this interface\n"); + return FALSE; +} + + +void ez_restore_channel_config(struct wifi_dev *wdev) +{ + PRTMP_ADAPTER ad; + struct wifi_dev *apcli_wdev; + ez_dev_t *ezdev = wdev->ez_driver_params.ezdev; + EZ_ADAPTER *ez_ad=NULL; + if(ezdev) + ez_ad = ezdev->ez_ad; + + ad = wdev->sys_handle; + apcli_wdev = &ad->ApCfg.ApCliTab[wdev->func_idx].wdev; + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("%s\n", __FUNCTION__)); + + // Rakesh: Disabling this as doing it here is not right in various scenarios. + // Optimization can be done in future for caller to choose/inform whether to skip. + if(ez_ad){ + if( +#ifdef EZ_PUSH_BW_SUPPORT + ( !ez_ad->push_bw_config ) && +#endif + (ez_is_channel_same(wdev) == TRUE) ) + { + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("ez_restore_channel_config: Channel already same\n")); + return; + } + +#ifdef EZ_PUSH_BW_SUPPORT + if( ez_ad->push_bw_config ) + { + if(ezdev->ez_security.this_band_info.shared_info.channel_info.ht_bw != 0xFF) + ez_driver_ops_wlan_config_set_ht_bw_mt7603(ezdev, ezdev->ez_security.this_band_info.shared_info.channel_info.ht_bw); +#ifdef DOT11_VHT_AC + if(ezdev->ez_security.this_band_info.shared_info.channel_info.vht_bw != 0xFF) + wlan_config_set_vht_bw(wdev, ezdev->ez_security.this_band_info.shared_info.channel_info.vht_bw); +#endif + } +#endif + + ez_driver_ops_wlan_config_set_ext_cha_mt7603(ezdev, ezdev->ez_security.this_band_info.shared_info.channel_info.extcha); + +#ifdef EZ_PUSH_BW_SUPPORT + if( ez_ad->push_bw_config ) + { + if(ezdev->ez_security.this_band_info.shared_info.channel_info.ht_bw != 0xFF) + ez_driver_ops_wlan_config_set_ht_bw_mt7603(ezdev, ezdev->ez_security.this_band_info.shared_info.channel_info.ht_bw); +#ifdef DOT11_VHT_AC + if(ezdev->ez_security.this_band_info.shared_info.channel_info.vht_bw != 0xFF) + wlan_config_set_vht_bw(apcli_wdev, ezdev->ez_security.this_band_info.shared_info.channel_info.vht_bw); +#endif + } +#endif + + ez_driver_ops_wlan_config_set_ext_cha_mt7603(ezdev, ezdev->ez_security.this_band_info.shared_info.channel_info.extcha); + +#if (defined(DOT11_N_SUPPORT) && defined(DOT11N_DRAFT3)) + if(ezdev->ez_security.ap_did_fallback){ + if(ezdev->ez_security.fallback_channel == ezdev->ez_security.this_band_info.shared_info.channel_info.channel){ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("\nez_restore_channel_config: Restoring ap to fallback mode\n")); + ez_driver_ops_wlan_operate_set_ht_bw_mt7603(wdev->ez_driver_params.ezdev, HT_BW_20); + ez_driver_ops_wlan_operate_set_ext_cha_mt7603(wdev->ez_driver_params.ezdev, EXTCHA_NONE); + } + } +#endif + + wdev->ez_driver_params.do_not_restart_interfaces = 1; + rtmp_set_channel(wdev->sys_handle, wdev, ezdev->ez_security.this_band_info.shared_info.channel_info.channel); + wdev->ez_driver_params.do_not_restart_interfaces = 0; + } +} + + +BOOLEAN ez_ap_scan_complete_handle(struct wifi_dev *wdev) +{ + ez_dev_t *ezdev = NULL; + + if (wdev) + ezdev = wdev->ez_driver_params.ezdev; + + if(ezdev) + return (wdev->ez_driver_params.scan_one_channel + || ezdev->ez_security.internal_force_connect_bssid); + else + return FALSE; +} + +BOOLEAN ez_need_bypass_rx_fwd(struct wifi_dev *wdev) +{ + ez_dev_t *ezdev = wdev->ez_driver_params.ezdev; + if(ezdev) + return ez_need_bypass_rx_fwd_hook(ezdev); + else + return FALSE; + +} + +//extern void ez_exit_hook( +// ez_dev_t *ezdev); + +void ez_exit( + void *wdev_obj) +{ + struct wifi_dev *wdev = wdev_obj; + ez_exit_hook((RTMP_ADAPTER *)wdev->sys_handle); +#ifdef EZ_REGROUP_SUPPORT + NdisFreeSpinLock(&wdev->ez_driver_params.regrp_mode_lock); +#endif +} + +void ez_driver_ops_fill_out_table_mt7603(BSS_TABLE* Tab, EZ_BSS_TABLE *pEzBss); + +BOOLEAN ez_apcli_search_best_ap_hook( + void *ez_ad_obj, + void *ezdev_obj, + void *out_tab); + +BOOLEAN ez_apcli_search_best_ap( + void *ad_obj, + void *apcli_entry_obj, + unsigned char inf_idx) +{ + BOOLEAN ret; + PRTMP_ADAPTER pAd = ad_obj; + APCLI_STRUCT *apcli_entry = apcli_entry_obj; + EZ_BSS_TABLE *out_tab = NULL; + ez_dev_t *ezdev; +// BSS_STRUCT *ap_mbss = &pAd->ApCfg.MBSSID[apcli_entry->wdev.func_idx]; + os_alloc_mem(pAd, (PUCHAR *)&out_tab, sizeof(EZ_BSS_TABLE)); + if(out_tab == NULL) + return FALSE; + + ezdev = apcli_entry->wdev.ez_driver_params.ezdev; + if(ezdev){ + if (apcli_entry->stop_auto_connect) { + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s(line.%d) - Provider search Paused.\n", + __FUNCTION__, __LINE__)); + os_free_mem(ad_obj,out_tab); + return FALSE; + } +#ifdef EZ_REGROUP_SUPPORT + if(apcli_entry->wdev.ez_driver_params.regrp_mode == REGRP_MODE_BLOCKED){ + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s(line.%d) - Provider search Blocked for Regroup on this wdev_idx : %d.\n", + __FUNCTION__, __LINE__, apcli_entry->wdev.wdev_idx)); + os_free_mem(ad_obj,out_tab); + return FALSE; + } +#endif +#ifdef IF_UP_DOWN + if (pAd->ez_ad && !ez_all_intf_up(pAd->ez_ad)) { + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, + ("%s(line.%d) - Provider search Blocked for All interfaces not up. wdev_idx : %d.\n", + __func__, __LINE__, apcli_entry->wdev.wdev_idx)); + os_free_mem(ad_obj, out_tab); + return FALSE; + } +#endif + ez_driver_ops_fill_out_table_mt7603(&apcli_entry->MlmeAux.SsidBssTab,out_tab); + + NdisZeroMemory(ezdev->CfgSsid, sizeof(ezdev->CfgSsid)); + NdisZeroMemory(apcli_entry->CfgSsid, sizeof(apcli_entry->CfgSsid)); + NdisCopyMemory(apcli_entry->CfgSsid, ezdev->ez_security.this_band_info.shared_info.ssid, ezdev->ez_security.this_band_info.shared_info.ssid_len); + apcli_entry->CfgSsidLen = ezdev->ez_security.this_band_info.shared_info.ssid_len; + NdisCopyMemory(ezdev->CfgSsid, apcli_entry->CfgSsid,apcli_entry->CfgSsidLen); + + ezdev->CfgSsidLen = ezdev->ez_security.this_band_info.shared_info.ssid_len; + printk("%s, ezdev->CfgSsid--->%s\n", __FUNCTION__, ezdev->CfgSsid); + ret = ez_apcli_search_best_ap_hook(pAd->ez_ad,apcli_entry->wdev.ez_driver_params.ezdev,out_tab); + os_free_mem(ad_obj,out_tab); + return ret; + } + else + return FALSE; + +} + +void ez_send_unicast_deauth(void *ad_obj, UCHAR *peer_addr) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + struct wifi_dev *wdev; + pEntry = MacTableLookup(ad_obj,peer_addr); + + wdev = pEntry->wdev; + if(wdev->ez_driver_params.ezdev) + ez_driver_ops_send_unicast_deauth_mt7603(wdev->ez_driver_params.ezdev,peer_addr); +} + +void ez_allocate_or_update_non_ez_band(void *wdev_obj) +{ + struct wifi_dev *wdev = wdev_obj; + + ez_allocate_or_update_non_ez_band_hook(wdev, wdev->sys_handle, wdev->wdev_type, wdev->func_idx,NULL, &wdev->channel); + +} diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/easy_setup/mt7603_chip_ops.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/easy_setup/mt7603_chip_ops.c new file mode 100644 index 000000000..bd1a65133 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/easy_setup/mt7603_chip_ops.c @@ -0,0 +1,1401 @@ +/* + *************************************************************************** + * 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_ez.c + + Abstract: + Easy Setup APIs + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef WH_EZ_SETUP +#include "rt_config.h" + +//ez_chipops_t ez_chipops; +UCHAR IPV4TYPE[] = {0x08, 0x00}; + +//int EzDebugLevel = DBG_LVL_ERROR; + +//---------------------------------------------------------------------------------------------------------- +// Arvind code +//----------------------------------------------------------------------------------------------------------- + +void ez_hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen) +{ +#ifdef DBG + unsigned char *pt; + int x; + if (EzDebugLevel < DBG_LVL_TRACE) + return; + pt = pSrcBufVA; + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("%s: %p, len = %d\n", str, pSrcBufVA, SrcBufLen)); + for (x = 0; x < SrcBufLen; x++) { + if (x % 16 == 0) + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("0x%04x : ", x)); + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("%02x ", ((unsigned char)pt[x]))); + if (x % 16 == 15) + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("\n")); + } + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("\n")); +#endif /* DBG */ +} + +VOID UpdateBeaconHandler( + void *ad_obj, + struct wifi_dev *wdev, + UCHAR BCN_UPDATE_REASON) +{ + RTMP_ADAPTER *pAd; + pAd = (RTMP_ADAPTER *)ad_obj; + +#ifdef WH_EZ_SETUP +#ifdef DUAL_CHIP + if(!IS_SINGLE_CHIP_DBDC(pAd)) + { + if ((wdev !=NULL) && wdev->enable_easy_setup) + RTMP_SEM_LOCK(&pAd->ez_beacon_update_lock); + } +#endif +#endif + + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + +#ifdef WH_EZ_SETUP +#ifdef DUAL_CHIP + if(!IS_SINGLE_CHIP_DBDC(pAd)) + { + if ((wdev !=NULL) && wdev->enable_easy_setup) + RTMP_SEM_UNLOCK(&pAd->ez_beacon_update_lock); + } +#endif +#endif +} + +void ez_install_pairwise_key_mt7603( + RTMP_ADAPTER *pAd, + struct wifi_dev *wdev, + char *peer_mac, + unsigned char *pmk, + unsigned char *ptk, + unsigned char authenticator) +{ + + //struct _ez_peer_security_info *ez_peer = (struct _ez_peer_security_info *)peer; + //ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + //RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->ad; + //struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + MAC_TABLE_ENTRY *entry; + STA_TR_ENTRY *tr_entry; + + entry = MacTableLookup(pAd, peer_mac); + tr_entry = &pAd->MacTab.tr_entry[entry->tr_tb_idx]; + + SET_AUTHMODE_WPA2PSK(entry->AuthMode); + SET_CIPHER_CCMP128(entry->WepStatus); + SET_CIPHER_CCMP128(entry->GroupKeyWepStatus); + //entry->SecConfig.PairwiseKeyId = 1; //Arvind don't need always use 0 + + if (wdev && (wdev->wdev_type == WDEV_TYPE_AP)) { + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[wdev->func_idx]; + NdisZeroMemory(&pMbss->PMK[0], LEN_PMK); + NdisCopyMemory(&pMbss->PMK[0], pmk, LEN_PMK); + + } else if (entry->wdev && entry->wdev->wdev_type == WDEV_TYPE_STA){ + APCLI_STRUCT *apcli_entry = &pAd->ApCfg.ApCliTab[wdev->func_idx]; + NdisZeroMemory(&apcli_entry->PMK[0], LEN_PMK); + NdisCopyMemory(&apcli_entry->PMK[0], pmk, LEN_PMK); + } + NdisZeroMemory(&entry->PTK[0], LEN_PTK); + NdisCopyMemory(&entry->PTK[0], ptk, LEN_PTK); + /* Set key material to Asic */ + WPAInstallPairwiseKey(pAd, entry->func_tb_idx, entry, authenticator); + + /* Update status and set Port as Secured */ + entry->WpaState = AS_PTKINITDONE; + entry->GTKState = REKEY_ESTABLISHED; + entry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + tr_entry->PortSecured = WPA_802_1X_PORT_SECURED; + + //WifiSysUpdatePortSecur(pAd, entry); +} + + +unsigned char ez_RandomByte_mt7603(RTMP_ADAPTER *pAd) +{ + return RandomByte(pAd); +} + +void ez_DH_PublicKey_Generate_mt7603( + UINT8 GValue[], + UINT GValueLength, + UINT8 PValue[], + UINT PValueLength, + UINT8 PrivateKey[], + UINT PrivateKeyLength, + UINT8 PublicKey[], + UINT *PublicKeyLength) +{ + + DH_PublicKey_Generate(GValue, GValueLength, PValue, PValueLength, + PrivateKey, PrivateKeyLength, PublicKey, PublicKeyLength); +} + +void ez_RT_DH_SecretKey_Generate_mt7603( + UINT8 PublicKey[], + UINT PublicKeyLength, + UINT8 PValue[], + UINT PValueLength, + UINT8 PrivateKey[], + UINT PrivateKeyLength, + UINT8 SecretKey[], + UINT *SecretKeyLength) +{ + + RT_DH_SecretKey_Generate(PublicKey, PublicKeyLength, PValue, PValueLength, + PrivateKey, PrivateKeyLength, SecretKey, SecretKeyLength); +} + +void ez_RT_SHA256_mt7603( + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 DigestMessage[]) +{ + RT_SHA256(Message, MessageLen, DigestMessage); +} + + +VOID ez_WpaDerivePTK_mt7603( + RTMP_ADAPTER *pAd, + UCHAR *PMK, + UCHAR *ANonce, + UCHAR *AA, + UCHAR *SNonce, + UCHAR *SA, + UCHAR *output, + UINT len) +{ + WpaDerivePTK(pAd, PMK, ANonce, AA, SNonce, SA, output, len); +} + +INT ez_AES_Key_Unwrap_mt7603( + UINT8 CipherText[], + UINT CipherTextLength, + UINT8 Key[], + UINT KeyLength, + UINT8 PlainText[], + UINT *PlainTextLength) +{ + + return AES_Key_Unwrap(CipherText, CipherTextLength, Key, KeyLength, PlainText,PlainTextLength); + +} + + +#ifdef APCLI_SUPPORT +void ez_apcli_install_group_key_mt7603( + RTMP_ADAPTER *ad, + char *peer_gtk, + unsigned char gtk_len, + MAC_TABLE_ENTRY *entry) +{ + /* Set Group key material, TxMic and RxMic for AP-Client*/ + APCliInstallSharedKey( + ad, + peer_gtk, + gtk_len, + 1, + entry); +} +#endif /* APCLI_SUPPORT */ + +INT ez_wlan_config_get_ht_bw_mt7603(RTMP_ADAPTER *pAd) +{ + return pAd->CommonCfg.RegTransmitSetting.field.BW; +} + +#ifdef DOT11_VHT_AC +INT ez_wlan_config_get_vht_bw_mt7603(RTMP_ADAPTER *pAd) +{ + return pAd->CommonCfg.vht_bw; +} + +#endif + +INT ez_wlan_operate_get_ht_bw_mt7603(RTMP_ADAPTER *pAd) +{ + return pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; +} + +INT ez_wlan_operate_get_ext_cha_mt7603(RTMP_ADAPTER *pAd) +{ + return pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset; +} + +INT ez_wlan_config_get_ext_cha_mt7603(RTMP_ADAPTER *pAd) +{ + return pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; +} + +int ez_get_cli_aid_mt7603(RTMP_ADAPTER *pAd, char *peer_mac) +{ + MAC_TABLE_ENTRY *pEntry; + pEntry = MacTableLookup(pAd, peer_mac); + + if(pEntry) + return pEntry->Aid; + else { + printk("%s Entry not found\n", __FUNCTION__); + ASSERT(FALSE); + return -1; + } + +} + +void ez_cancel_timer_mt7603( + RTMP_ADAPTER *pAd, + void * timer_struct) +{ + ez_timer_t *timer = (ez_timer_t *)timer_struct; + + EZ_CANCEL_TIMER(&timer->ez_timer, timer->ez_timer_running); + return ; +} + +void ez_set_timer_mt7603( + RTMP_ADAPTER *pAd, + void * timer_struct, + unsigned long time) +{ + ez_timer_t *timer = (ez_timer_t *)timer_struct; + + RTMPSetTimer(&timer->ez_timer, time); + return ; +} + +int ez_is_timer_running_mt7603( + RTMP_ADAPTER *pAd, + void * timer_struct) +{ + + //ez_is_timer_running(void * ezdev, void * timer_struct) + return 0; +} + +#ifdef APCLI_SUPPORT +int get_apcli_enable_mt7603( + RTMP_ADAPTER *pAd, + int ifIndex) +{ + if(pAd->ApCfg.ApCliTab[ifIndex].Enable) + return 1; + else + return 0; +} +#endif + +int ez_ApScanRunning_mt7603(RTMP_ADAPTER *pAd) +{ + if(ApScanRunning(pAd)) + return 1; + else + return 0; + +} + +BOOLEAN EzMlmeEnqueue( + IN RTMP_ADAPTER *pAd, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg, + IN ULONG Priv) +{ + INT Tail; + MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; + + /* Do nothing if the driver is starting halt state.*/ + /* This might happen when timer already been fired before cancel timer with mlmehalt*/ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return FALSE; + + /* First check the size, it MUST not exceed the mlme queue size*/ + if (MsgLen > MGMT_DMA_BUFFER_SIZE) + { + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("MlmeEnqueue: msg too large, size = %ld \n", MsgLen)); + return FALSE; + } + + if (MlmeQueueFull(Queue, 1)) + { + return FALSE; + } + + NdisAcquireSpinLock(&(Queue->Lock)); + Tail = Queue->Tail; + /* + Double check for safety in multi-thread system. + */ + if (Queue->Entry[Tail].Occupied) + { + NdisReleaseSpinLock(&(Queue->Lock)); + return FALSE; + } + Queue->Tail++; + Queue->Num++; + if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) + Queue->Tail = 0; + + Queue->Entry[Tail].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) + { + Queue->Entry[Tail].Wcid = ((MLME_QUEUE_ELEM *)Msg)->Wcid; + NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); + } + + NdisReleaseSpinLock(&(Queue->Lock)); + + return TRUE; +} + +void ez_send_unicast_deauth_ap(void *ad_obj, UCHAR *peer_addr) +{ + MLME_DEAUTH_REQ_STRUCT *pInfo = NULL; + MLME_QUEUE_ELEM *Elem; + MAC_TABLE_ENTRY *pEntry = NULL; + RTMP_ADAPTER *pAd = ad_obj; + //struct _ez_peer_security_info *ez_peer; + BOOLEAN ez_peer = FALSE; + os_alloc_mem(pAd, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + if(Elem == NULL) + { + EZ_DEBUG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("Set::OID_802_11_DEAUTHENTICATION, Failed!!\n")); + return; + } + if (Elem) + { + pInfo = (MLME_DEAUTH_REQ_STRUCT *) Elem->Msg; + pInfo->Reason = REASON_NO_LONGER_VALID; + NdisCopyMemory(pInfo->Addr, peer_addr, MAC_ADDR_LEN); + if ((pEntry = MacTableLookup(pAd, peer_addr)) != NULL) + { + Elem->Wcid = pEntry->wcid; + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("WCID = %d\n;", Elem->Wcid)); + ez_hex_dump("address :", pEntry->Addr, 6); + ez_peer = is_ez_peer(pEntry->wdev,pEntry->Addr); + + if (ez_peer && !ez_get_peer_delete_in_differred_context(pEntry->wdev,pEntry->Addr)){ + APMlmeDeauthReqAction(pAd, Elem); + } else { + + EzMlmeEnqueue(pAd, AP_AUTH_STATE_MACHINE, APMT2_MLME_DEAUTH_REQ, + sizeof(MLME_DEAUTH_REQ_STRUCT), Elem, 0); + } + EZ_DEBUG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("EZ Set::OID_802_11_DEAUTHENTICATION (Reason=%d)\n", pInfo->Reason)); + } + os_free_mem(pAd, Elem); + } +} + +void ez_send_unicast_deauth_apcli(void *ad_obj, USHORT idx) +{ + MLME_QUEUE_ELEM *Elem; + //struct _ez_peer_security_info *ez_peer = NULL; + BOOLEAN ez_peer = FALSE; + struct wifi_dev *wdev; + PRTMP_ADAPTER ad = ad_obj; + + wdev = &ad->ApCfg.ApCliTab[idx].wdev; + + os_alloc_mem(ad_obj, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + if(Elem == NULL) + { + EZ_DEBUG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("Set::OID_802_11_DEAUTHENTICATION, Failed!!\n")); + return; + } + + ez_peer = is_ez_peer(wdev, wdev->bssid); + + if (ez_peer && !ez_get_peer_delete_in_differred_context(wdev, wdev->bssid)){ + Elem->Priv = idx | IMM_DISCONNECT; + ApCliCtrlDeAuthAction(ad_obj, Elem); + } else { + MlmeEnqueue(ad, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, idx); + } + + os_free_mem(ad, Elem); +} + +void ez_send_unicast_deauth_mt7603(void *ad_obj, UCHAR *peer_addr) +{ + MAC_TABLE_ENTRY *pEntry = NULL; + + pEntry = MacTableLookup(ad_obj,peer_addr); + + RtmpOsMsDelay(50); + + if (pEntry && pEntry->wdev->wdev_type == WDEV_TYPE_AP) + { + ez_send_unicast_deauth_ap(ad_obj, peer_addr); + } else if (pEntry && pEntry->wdev->wdev_type == WDEV_TYPE_STA) { + ez_send_unicast_deauth_apcli(ad_obj, pEntry->wdev->func_idx); + } +} + +void ez_UpdateBeaconHandler_mt7603( + RTMP_ADAPTER *ez_ad, + struct wifi_dev *wdev, + UCHAR reason) +{ + UpdateBeaconHandler(ez_ad, wdev, reason); + return; +} + +void ez_update_security_setting_mt7603( + RTMP_ADAPTER *pAd, + struct wifi_dev *wdev, + unsigned char *pmk) +{ + int i; + unsigned char *ptr; + + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("------> %s()\n", __FUNCTION__)); + + if(wdev->wdev_type == WDEV_TYPE_AP) + { + BSS_STRUCT *pMbss; + pMbss = &pAd->ApCfg.MBSSID[wdev->func_idx]; + + NdisCopyMemory(&pMbss->PMK[0], pmk, LEN_PMK); + hex_dump("pMbss_pmk", &pMbss->PMK[0], LEN_PMK); + ptr = &pMbss->PSK[0]; + NdisZeroMemory(ptr, sizeof(pMbss->PSK)); + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_INFO, + ("%s() pMbss->PSK: %s (%d)\n", + __FUNCTION__, pMbss->PSK, (int)strlen(pMbss->PSK))); + + } + else if(wdev->wdev_type == WDEV_TYPE_STA) + { + APCLI_STRUCT *pApCliEntry; + pApCliEntry = &pAd->ApCfg.ApCliTab[wdev->func_idx]; + + NdisCopyMemory(&pApCliEntry->PMK[0], pmk, LEN_PMK); + hex_dump("pApCliEntry_pmk", &pApCliEntry->PMK[0], LEN_PMK); + ptr = &pApCliEntry->PSK[0]; + NdisZeroMemory(ptr, sizeof(pApCliEntry->PSK)); + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_INFO, + ("%s() pApCliEntry.PSK: %s (%d)\n", + __FUNCTION__, pApCliEntry->PSK, (int)strlen(pApCliEntry->PSK))); + + } + + for (i = 0; i < LEN_PMK; i++) { + snprintf(ptr, (LEN_PSK+1), "%s%02x", ptr, pmk[i]); + } + + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("<------ %s()\n", __FUNCTION__)); +} + +#ifdef WSC_AP_SUPPORT +void ez_updage_ap_wsc_profile_mt7603( + RTMP_ADAPTER *pAd, + struct wifi_dev *wdev, + unsigned char if_idx) +{ + WSC_CTRL *wsc_ctrl; + BSS_STRUCT *pMbss; + + pMbss = &pAd->ApCfg.MBSSID[if_idx]; + wsc_ctrl = &pAd->ApCfg.MBSSID[if_idx].WscControl; + NdisZeroMemory(&wsc_ctrl->WpaPsk[0], LEN_PSK); + wsc_ctrl->WpaPskLen = strlen(pMbss->PSK); + NdisCopyMemory(&wsc_ctrl->WpaPsk[0], pMbss->PSK, wsc_ctrl->WpaPskLen); +#ifdef APCLI_SUPPORT + if ((wdev->wdev_type == WDEV_TYPE_STA) + && (pAd->ApCfg.MBSSID[if_idx].wdev.enable_easy_setup)) { + APCLI_STRUCT *pApCliEntry; + pApCliEntry = &pAd->ApCfg.ApCliTab[if_idx]; + + NdisZeroMemory(pMbss->PSK, sizeof(pMbss->PSK)); + NdisCopyMemory(pMbss->PSK, pApCliEntry->PSK, sizeof(pMbss->PSK)); + + } +#endif /* APCLI_SUPPORT */ + wsc_ctrl->WscConfStatus = WSC_SCSTATE_CONFIGURED; +} +#endif /* WSC_AP_SUPPORT */ + +void ez_MiniportMMRequest_mt7603( + RTMP_ADAPTER *pAd, + UCHAR QueIdx, + UCHAR *out_buf, + UINT frame_len) +{ + MiniportMMRequest(pAd, QueIdx, out_buf, frame_len); + return; +} + +void ez_NdisGetSystemUpTime_mt7603(ULONG *time) +{ + NdisGetSystemUpTime(time); + return; +} + +INT ez_AES_Key_Wrap_mt7603( + UINT8 PlainText[], + UINT PlainTextLength, + UINT8 Key[], + UINT KeyLength, + UINT8 CipherText[], + UINT *CipherTextLength) +{ + return AES_Key_Wrap(PlainText, PlainTextLength, Key, KeyLength, CipherText, CipherTextLength); + +} + +INT ez_RtmpOSWrielessEventSendExt_mt7603( + PNET_DEV pNetDev, + UINT32 eventType, + INT flags, + PUCHAR pSrcMac, + PUCHAR pData, + UINT32 dataLen) +{ + return RtmpOSWrielessEventSendExt(pNetDev, eventType, flags, pSrcMac, pData, dataLen, 0); + +} + +#ifdef EZ_NETWORK_MERGE_SUPPORT +VOID ez_APMlmeBroadcastDeauthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_BROADCAST_DEAUTH_REQ_STRUCT *pInfo; + HEADER_802_11 Hdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + MAC_TABLE_ENTRY *pEntry; + UCHAR apidx = 0; + struct wifi_dev *wdev; + int wcid, startWcid; + startWcid = 1; + + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("%s\n", __FUNCTION__)); + + pInfo = (PMLME_BROADCAST_DEAUTH_REQ_STRUCT)Elem->Msg; + + if (!MAC_ADDR_EQUAL(pInfo->Addr,BROADCAST_ADDR)) + { + return; + } + + wdev = pInfo->wdev; + apidx = wdev->func_idx; + + for (wcid = startWcid; wcid < MAX_LEN_OF_MAC_TABLE; wcid++) + { + pEntry = &pAd->MacTab.Content[wcid]; + if ((pEntry->wdev != wdev)) + { + continue; + } + if (wdev->enable_easy_setup && is_ez_peer(pEntry->wdev, pEntry->Addr)) + { + continue; + } + + RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pEntry->Addr, 0, 0); + ApLogEvent(pAd, pInfo->Addr, EVENT_DISASSOCIATED); + ez_hex_dump("DeleteEntryAddr",pEntry->Addr,6); + + MacTableDeleteEntry(pAd, wcid, pEntry->Addr); + +#ifdef WH_EVENT_NOTIFIER + { + EventHdlr pEventHdlrHook = NULL; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_STA_LEAVE); + if(pEventHdlrHook && wdev) + pEventHdlrHook(pAd, wdev, pEntry->Addr, Elem->Channel); + } +#endif /* WH_EVENT_NOTIFIER */ + } + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + EZ_DEBUG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("AUTH - Send DE-AUTH req to %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pInfo->Addr))); + MgtMacHeaderInit(pAd, &Hdr, SUBTYPE_DEAUTH, 0, pInfo->Addr, + pAd->ApCfg.MBSSID[apidx].wdev.if_addr, + pAd->ApCfg.MBSSID[apidx].wdev.bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr, + 2, &pInfo->Reason, + END_OF_ARGS); + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(NULL, pOutBuffer); +} +#endif + +void ez_send_broadcast_deauth_mt7603(RTMP_ADAPTER *pAd, struct wifi_dev *wdev) +{ + MLME_BROADCAST_DEAUTH_REQ_STRUCT *pInfo = NULL; + MLME_QUEUE_ELEM *Elem; + + os_alloc_mem(pAd, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + + if(Elem == NULL) + { + EZ_DEBUG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("Set::OID_802_11_DEAUTHENTICATION, Failed!!\n")); + return; + } + + if (Elem) + { + pInfo = (MLME_BROADCAST_DEAUTH_REQ_STRUCT *) Elem->Msg; + pInfo->wdev = wdev; + Elem->Wcid = WCID_ALL; + pInfo->Reason = MLME_EZ_DISCONNECT_NON_EZ; + NdisCopyMemory(pInfo->Addr, BROADCAST_ADDR, MAC_ADDR_LEN); + APMlmeDeauthReqAction(pAd, Elem); + os_free_mem(pAd, Elem); + } +} + +void ez_timer_init_mt7603(RTMP_ADAPTER *pAd, void* timer, void *callback) +{ + //EZ_TIMER_INIT(pAd, void* timer, void *callback); + +} +void ez_set_ap_ssid_null_mt7603( + RTMP_ADAPTER *pAd, + INT apidx) +{ + BSS_STRUCT *mbss; + + mbss = &pAd->ApCfg.MBSSID[apidx]; + NdisZeroMemory(mbss->Ssid, MAX_LEN_OF_SSID); + mbss->SsidLen = 0; + return ; +} +void ez_set_entry_apcli_mt7603( + RTMP_ADAPTER *pAd, + UCHAR *mac_addr, + BOOLEAN is_apcli) +{ + MAC_TABLE_ENTRY *pEntry; + pEntry = MacTableLookup(pAd, mac_addr); + + if(pEntry && is_apcli) + SET_ENTRY_APCLI(pEntry); + else + printk("%s Entry not found\n", __FUNCTION__); + + return; +} +void* ez_get_pentry_mt7603( + RTMP_ADAPTER *pAd, + UCHAR *mac_addr) +{ + MAC_TABLE_ENTRY *pEntry; + pEntry = MacTableLookup(pAd, mac_addr); + + return pEntry; +} +void ez_mark_entry_duplicate_mt7603(RTMP_ADAPTER *pAd, UCHAR *mac_addr) +{ + MAC_TABLE_ENTRY *pEntry; + pEntry = MacTableLookup(pAd, mac_addr); + +#ifdef WH_EZ_SETUP +#ifdef EZ_DUAL_BAND_SUPPORT + + if(pEntry) + pEntry->link_duplicate = TRUE; + else + printk("%s Entry not found !! \n", __FUNCTION__); + +#endif +#endif /* WH_EZ_SETUP */ + return ; +} + +void ez_ScanTableInit_mt7603(RTMP_ADAPTER *pAd) +{ + BssTableInit(&pAd->ScanTab); + return ; +} + +//------------------------------------------------- +// raghav +//-------------------------------------------------- + +void ez_wlan_operate_set_ht_bw_mt7603(RTMP_ADAPTER *pAd,UINT8 ht_bw) +{ + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = ht_bw; +} + +void ez_wlan_operate_set_ext_cha_mt7603(RTMP_ADAPTER *pAd,UINT8 ext_cha) +{ + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = ext_cha; +} + +INT rtmp_set_channel_mt7603(RTMP_ADAPTER *pAd, struct wifi_dev *wdev, UCHAR Channel) +{ +#ifdef CONFIG_AP_SUPPORT + INT32 i; +#endif /* CONFIG_AP_SUPPORT */ + INT32 Success = TRUE; + UCHAR RFChannel; + + pAd->CommonCfg.Channel = Channel; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if (pAd->ApCfg.ApCliAutoConnectChannelSwitching == FALSE) + pAd->ApCfg.ApCliAutoConnectChannelSwitching = TRUE; +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + /* check if this channel is valid*/ + if (ChannelSanity(pAd, Channel) == TRUE) + { + 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_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if ((WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + && (pAd->CommonCfg.bIEEE80211H == TRUE)) + { + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (pAd->ChannelList[i].Channel == Channel) + { + if (pAd->ChannelList[i].RemainingTimeForUse > 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: previous detection of a radar on this channel(Channel=%d)\n", Channel)); + Success = FALSE; + break; + } + else + { + DBGPRINT(RT_DEBUG_INFO, ("RemainingTimeForUse %d ,Channel %d\n", + pAd->ChannelList[i].RemainingTimeForUse, Channel)); + } + } + } + } + + if (Success == TRUE) + { + if ((pAd->CommonCfg.Channel > 14 ) + && (pAd->CommonCfg.bIEEE80211H == TRUE)) + { + pAd->Dot11_H.org_ch = pAd->CommonCfg.Channel; + } + + pAd->CommonCfg.Channel = Channel; //lk added + +#ifdef DOT11_N_SUPPORT + N_ChannelCheck(pAd); + + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + RFChannel = N_SetCenCh(pAd, pAd->CommonCfg.Channel); + else +#endif /* DOT11_N_SUPPORT */ + RFChannel = pAd->CommonCfg.Channel; + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): CtrlChannel(%d), CentralChannel(%d) \n", + __FUNCTION__, pAd->CommonCfg.Channel, + pAd->CommonCfg.CentralChannel)); + + if ((pAd->CommonCfg.Channel > 14 ) + && (pAd->CommonCfg.bIEEE80211H == TRUE) +#ifdef WH_EZ_SETUP + && (!((wdev->enable_easy_setup == TRUE) && (pAd->Dot11_H.RDMode == RD_NORMAL_MODE))) +#endif + + ) + { + if (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) + { + AsicSwitchChannel(pAd, RFChannel, FALSE); +#ifdef WH_EZ_SETUP +#ifdef EZ_NETWORK_MERGE_SUPPORT + //! base channel is different from target channel, do restart AP + if (!IS_EZ_SETUP_ENABLED(wdev) || wdev->do_not_restart_interfaces != 1) + { +#endif +#endif + APStop(pAd); + APStartUp(pAd); +#ifdef WH_EZ_SETUP +#ifdef EZ_NETWORK_MERGE_SUPPORT + } else { + + if(Channel > 14) + ap_phy_rrm_init(pAd); + else + ap_phy_rrm_init(pAd); + } +#endif +#endif + + } + else + { + NotifyChSwAnnToPeerAPs(pAd, ZERO_MAC_ADDR, pAd->CurrentAddress, 1, pAd->CommonCfg.Channel); + pAd->Dot11_H.RDMode = RD_SWITCHING_MODE; + pAd->Dot11_H.CSCount = 0; + pAd->Dot11_H.new_channel = Channel; + } + } + else + { +#ifdef WH_EZ_SETUP +#ifdef EZ_NETWORK_MERGE_SUPPORT + //! base channel is different from target channel, do not restart AP + if (!IS_EZ_SETUP_ENABLED(wdev) || wdev->do_not_restart_interfaces != 1) + { +#endif +#endif + AsicSwitchChannel(pAd, RFChannel, FALSE); + APStop(pAd); + APStartUp(pAd); +#ifdef WH_EZ_SETUP +#ifdef EZ_NETWORK_MERGE_SUPPORT + } else { + if(Channel > 14) + ap_phy_rrm_init(pAd); + else + ap_phy_rrm_init(pAd); + } + +#endif +#endif + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + + if (Success == TRUE) + DBGPRINT(RT_DEBUG_TRACE, ("Set_Channel_Proc::(Channel=%d)\n", pAd->CommonCfg.Channel)); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_AUTO_CONNECT_SUPPORT + pAd->ApCfg.ApCliAutoConnectChannelSwitching = FALSE; +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + return Success; +} + +void ez_APScanCnclAction_mt7603(RTMP_ADAPTER *pAd) +{ + APScanCnclAction(pAd, NULL); +} + + + +/* Form and transmit Custom loop detect Pkt*/ + void ez_send_loop_detect_pkt_mt7603( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pMacEntry, + IN PUCHAR pOtherCliMac) +{ + UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + UCHAR Header802_3[14]={0}; + UCHAR CustomPayload[26]={0x45,0x00, // version(4bit), hdr lenght(4bit), tos + 0x00,0x1A, // total ip datagram length + 0x00,0x01, // identification + 0x40,0x00, // flag & fragmentation + 0x40,0xFD, // TTL, Protocol type + 0x39,0xE7, // hdr checksum (considered 0 for calculation) + 0x00,0x00, // Source IP + 0x00,0x00, // Source IP + 0xFF,0xFF, // Dest IP + 0xFF,0xFF, // Dest IP + 0x11,0x22, // Random Bytes + 0x33,0x44, // Random bytes + 0x55,0x66}; // Random bytes + + //Protocol Type (0x3D any host internal protocol,0x3F any local host network,0xFD & 0xFE for experimentation, 0xFF reserved) + // 2 byte header checksum field, calculated manually by formula and assuming checksum is zero + + //MTWF_LOG(DBG_CAT_CLIENT, CATCLIENT_APCLI, DBG_LVL_OFF, ("-----> ez_send_loop_detect_pkt\n")); + //EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("ez_send_loop_detect_pkt---->\n")); + + NdisZeroMemory(Header802_3,sizeof(UCHAR)*14); + + MAKE_802_3_HEADER(Header802_3, BROADCAST_ADDR, &pMacEntry->wdev->if_addr[0], IPV4TYPE); // or snap type? + + // Using fixed payload due to checksum calculation required using one's complement + NdisCopyMemory(&CustomPayload[20],pOtherCliMac,MAC_ADDR_LEN); + //EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("ez_send_loop_detect_pkt=> Add in payload Other CLi MAC: %02x-%02x-%02x-%02x-%02x-%02x\n", + // CustomPayload[20],CustomPayload[21],CustomPayload[22],CustomPayload[23],CustomPayload[24],CustomPayload[25])); + + // Copy frame to Tx ring + + // Pkt 1 + //EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("ez_send_loop_detect_pkt: wdev_idx:0x%x => Send Loop Detection Pkt 1\n",pMacEntry->wdev->wdev_idx)); + RTMPToWirelessSta((PRTMP_ADAPTER)pAd, pMacEntry, + Header802_3, LENGTH_802_3, (PUCHAR)CustomPayload, 26, FALSE); + OS_WAIT(5); + + // Pkt 2 + //EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("ez_send_loop_detect_pkt: wdev_idx:0x%x => Send Loop Detection Pkt 2\n",pMacEntry->wdev->wdev_idx)); + RTMPToWirelessSta((PRTMP_ADAPTER)pAd, pMacEntry, + Header802_3, LENGTH_802_3, (PUCHAR)CustomPayload, 26, FALSE); + OS_WAIT(5); + + // Pkt 3 + //EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("ez_send_loop_detect_pkt: wdev_idx:0x%x => Send Loop Detection Pkt 3\n",pMacEntry->wdev->wdev_idx)); + RTMPToWirelessSta((PRTMP_ADAPTER)pAd, pMacEntry, + Header802_3, LENGTH_802_3, (PUCHAR)CustomPayload, 26, FALSE); + + //EZ_DEBUG(DBG_CAT_CLIENT, CATCLIENT_APCLI, DBG_LVL_OFF, ("<----- ez_send_loop_detect_pkt\n")); +} + + +#ifdef DOT11_N_SUPPORT +/* + ======================================================================== + Rakesh: based on ApCliCheckHt + + ======================================================================== +*/ +static BOOLEAN ez_ApStaSetHt( + IN struct wifi_dev *wdev, + MAC_TABLE_ENTRY *pEntry) +{ + HT_CAPABILITY_IE *aux_ht_cap; + UCHAR cfg_ht_bw; + PRTMP_ADAPTER ad = (PRTMP_ADAPTER)wdev->sys_handle; + + cfg_ht_bw = ez_wlan_config_get_ht_bw_mt7603(ad); + + aux_ht_cap = &pEntry->HTCapability; + /* choose smaller setting */ + +#ifdef CONFIG_MULTI_CHANNEL + aux_ht_cap->HtCapInfo.ChannelWidth = cfg_ht_bw; //pAddHtInfo->AddHtInfo.RecomWidth; +#else /* CONFIG_MULTI_CHANNEL */ + aux_ht_cap->HtCapInfo.ChannelWidth = cfg_ht_bw; //pAddHtInfo->AddHtInfo.RecomWidth & cfg_ht_bw; +#endif /* !CONFIG_MULTI_CHANNEL */ + + /* Fix throughput issue for some vendor AP with AES mode */ + if (cfg_ht_bw) // remove pAddHtInfo->AddHtInfo.RecomWidth & check + aux_ht_cap->HtCapInfo.CCKmodein40 = ad->CommonCfg.HtCapability.HtCapInfo.CCKmodein40; + else + aux_ht_cap->HtCapInfo.CCKmodein40 = 0; + + return TRUE; +} + +/* + ======================================================================== + Rakesh: based on ApCliCheckHt + + ======================================================================== +*/ +BOOLEAN ez_ApCliSetHt_mt7603( + IN APCLI_STRUCT *pApCliEntry, + MAC_TABLE_ENTRY *pEntry) +{ + HT_CAPABILITY_IE *aux_ht_cap; + UCHAR cfg_ht_bw; + PRTMP_ADAPTER ad = (PRTMP_ADAPTER)(pApCliEntry->wdev.sys_handle); + + cfg_ht_bw = ez_wlan_config_get_ht_bw_mt7603(ad); + + aux_ht_cap = &pApCliEntry->MlmeAux.HtCapability; + /* choose smaller setting */ + +#ifdef CONFIG_MULTI_CHANNEL + aux_ht_cap->HtCapInfo.ChannelWidth = cfg_ht_bw; //pAddHtInfo->AddHtInfo.RecomWidth; +#else /* CONFIG_MULTI_CHANNEL */ + aux_ht_cap->HtCapInfo.ChannelWidth = cfg_ht_bw; //pAddHtInfo->AddHtInfo.RecomWidth & cfg_ht_bw; +#endif /* !CONFIG_MULTI_CHANNEL */ + + /* Fix throughput issue for some vendor AP with AES mode */ + if (cfg_ht_bw) // remove pAddHtInfo->AddHtInfo.RecomWidth & check + aux_ht_cap->HtCapInfo.CCKmodein40 = ad->CommonCfg.HtCapability.HtCapInfo.CCKmodein40; + else + aux_ht_cap->HtCapInfo.CCKmodein40 = 0; + + /* Record the RxMcs of AP */ + NdisMoveMemory(pApCliEntry->RxMcsSet, ad->CommonCfg.HtCapability.MCSSet, 16); + + NdisMoveMemory(&pEntry->HTCapability, &pApCliEntry->MlmeAux.HtCapability, sizeof(HT_CAPABILITY_IE)); + NdisMoveMemory(pEntry->HTCapability.MCSSet, pApCliEntry->RxMcsSet, 16); + + return TRUE; +} + +#endif + +void ez_update_cli_peer_record_mt7603(void * ad_obj, void * wdev_obj, BOOLEAN band_switched, PUCHAR peer_addr) +{ + struct wifi_dev* wdev = wdev_obj; + struct wifi_dev *ap_wdev = NULL; + APCLI_STRUCT *pApCliEntry; + PRTMP_ADAPTER pAd = ad_obj; + MAC_TABLE_ENTRY *pMacEntry= NULL; +#ifdef DOT11_N_SUPPORT + UCHAR supported_bw; +#endif +#ifdef DOT11_VHT_AC + unsigned char vht_bw; +#endif + pAd = ((PRTMP_ADAPTER)wdev->sys_handle); + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_INFO,("%s >>>\n", __FUNCTION__)); + + if (wdev->wdev_type == WDEV_TYPE_AP) + { + wdev = &pAd->ApCfg.ApCliTab[wdev->func_idx].wdev; + } + pApCliEntry = wdev->func_dev; + + + + + + pMacEntry = MacTableLookup(wdev->sys_handle,peer_addr); + + if(pMacEntry != NULL){ + + // Rakesh: print current info pMacEntry->HTPhyMode.word pMacEntry->MaxHTPhyMode.word ClientStatusFlags + // pApCliEntry->MlmeAux.HtCapability pMacEntry->HTCapability (pApCliEntry->MlmeAux.vht_cap), (pApCliEntry->MlmeAux.vht_op) + // pMacEntry->vht_cap_ie + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_INFO,("%s(),MacEntry CURRENT MODE = %d, BW = %d\n", __FUNCTION__, + pMacEntry->MaxHTPhyMode.field.MODE, + pMacEntry->MaxHTPhyMode.field.BW)); + + // Rakesh: following code taken from ApCliLinkUp + + ap_wdev = &(pAd->ApCfg.MBSSID[wdev->func_idx].wdev); + +#ifdef DOT11_N_SUPPORT + supported_bw = ez_wlan_config_get_ht_bw_mt7603(pAd); + + if(pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth != supported_bw){ + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("**** CmnCfg HtCap chan width not in sync with current ht bw\n")); + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = supported_bw; + } + + ez_ApCliSetHt_mt7603(pApCliEntry,pMacEntry); // will update pEntry->HTCapability +#endif +#ifdef DOT11_VHT_AC + vht_bw = ez_wlan_config_get_vht_bw_mt7603(wdev); + + if(pAd->CommonCfg.vht_bw != vht_bw){ + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("**** CmnCfg VHt Cap chan width not in sync with current vht bw\n")); + pAd->CommonCfg.vht_bw = vht_bw; + } + + ez_ApCliSetVht(pApCliEntry,pMacEntry); // will update pEntry->vht_cap_ie +#endif + +#ifdef DOT11_N_SUPPORT + /* If this Entry supports 802.11n, upgrade to HT rate. */ + //if (pApCliEntry->MlmeAux.HtCapabilityLen != 0) Rakesh: todo check peer capability before updating + if (WMODE_CAP_N(pApCliEntry->wdev.PhyMode)) // Rakesh: code written asuming all device suport same PhyMode + { + // Rakesh refer ht_mode_adjust() for partial changes taken here as applicable + + if ( //(peer->HtCapInfo.ChannelWidth) && Rakesh: todo check peer capability before updating + (ez_wlan_config_get_ht_bw_mt7603(pAd)) && (ez_wlan_operate_get_ht_bw_mt7603(pAd)) && (supported_bw == BW_40)) + { + pMacEntry->MaxHTPhyMode.field.BW= BW_40; + } + else + { + pMacEntry->MaxHTPhyMode.field.BW = BW_20; + pAd->MacTab.fAnyStation20Only = TRUE; + } + + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_INFO,("%s(),MacEntry Updated MODE = %d, BW = %d\n", __FUNCTION__, + pMacEntry->MaxHTPhyMode.field.MODE, + pMacEntry->MaxHTPhyMode.field.BW)); + + pMacEntry->HTPhyMode.word = pMacEntry->MaxHTPhyMode.word; + + } + //else Rakesh: Todo check AP capability + //{ + // pAd->MacTab.fAnyStationIsLegacy = TRUE; + // MTWF_LOG(DBG_CAT_CLIENT, CATCLIENT_APCLI, DBG_LVL_TRACE, ("ApCliLinkUp - MaxSupRate=%d Mbps\n", + // RateIdToMbps[pMacEntry->MaxSupportedRate])); + //} +#endif /* DOT11_N_SUPPORT */ + + + pMacEntry->HTPhyMode.word = pMacEntry->MaxHTPhyMode.word; + + pApCliEntry->MlmeAux.SupRateLen = pAd->CommonCfg.SupRateLen;//ap_wdev->rate.SupRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.SupRate, pAd->CommonCfg.SupRate, pApCliEntry->MlmeAux.SupRateLen); // Rakesh: RTMPCheckRates not required as same phy mode on all devices + + pApCliEntry->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, pApCliEntry->MlmeAux.ExtRateLen); // Rakesh: RTMPCheckRates not required as same phy mode on all devices + + RTMPSetSupportMCS(wdev->sys_handle, + OPMODE_AP, + pMacEntry, + pApCliEntry->MlmeAux.SupRate, + pApCliEntry->MlmeAux.SupRateLen, + pApCliEntry->MlmeAux.ExtRate, + pApCliEntry->MlmeAux.ExtRateLen, +#ifdef DOT11_VHT_AC + pApCliEntry->MlmeAux.vht_cap_len, + &pApCliEntry->MlmeAux.vht_cap, +#endif /* DOT11_VHT_AC */ + &pApCliEntry->MlmeAux.HtCapability, + pApCliEntry->MlmeAux.HtCapabilityLen); + + //WifiSysApCliChBwUpdate(pAd,pApCliEntry,CliIdx, pMacEntry); + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + + if (wdev->bAutoTxRateSwitch == TRUE) + { + pMacEntry->bAutoTxRateSwitch = TRUE; + } + else + { + pMacEntry->HTPhyMode.field.MCS = wdev->HTPhyMode.field.MCS; + pMacEntry->bAutoTxRateSwitch = FALSE; + + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((UCHAR)wdev->DesiredTransmitSetting.field.FixedTxMode, pMacEntry); + } + + MlmeRAInit(pAd, pMacEntry); + + } +#endif + } + else{ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("ERROR !!! not found other peer mac entry\n")); + ASSERT(FALSE); + } + + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_INFO,("%s <<<\n", __FUNCTION__)); +} + + +void ez_update_ap_peer_record_mt7603(void * ad_obj, void * wdev_obj, BOOLEAN band_switched, PUCHAR peer_addr) +{ + struct wifi_dev* wdev = wdev_obj; + PRTMP_ADAPTER pAd = ad_obj; + MAC_TABLE_ENTRY *pEntry= NULL; +#ifdef DOT11_N_SUPPORT + UCHAR supported_bw; +#endif +#ifdef DOT11_VHT_AC + UCHAR vht_bw; +#endif + //PRTMP_ADAPTER adOthBand = ez_get_otherband_ad(wdev); + + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_INFO,("%s >>>\n",__FUNCTION__)); + + if (wdev->wdev_type == WDEV_TYPE_STA) + { + wdev = &pAd->ApCfg.MBSSID[wdev->func_idx].wdev; + } + + + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("%s, wdev->idx:%x ap_peer_mac = %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__,wdev->wdev_idx,PRINT_MAC(peer_addr))); + + pEntry = MacTableLookup(wdev->sys_handle,peer_addr); + + if(pEntry != NULL){ + + // Rakesh: print current info pMacEntry->HTPhyMode.word pMacEntry->MaxHTPhyMode.word ClientStatusFlags + // pApCliEntry->MlmeAux.HtCapability pMacEntry->HTCapability (pApCliEntry->MlmeAux.vht_cap), (pApCliEntry->MlmeAux.vht_op) + // pMacEntry->vht_cap_ie + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_INFO,("%s(),MacEntry CURRENT MODE = %d, BW = %d\n", __FUNCTION__, + pEntry->MaxHTPhyMode.field.MODE, + pEntry->MaxHTPhyMode.field.BW)); + + // Rakesh: following code taken from update_associated_mac_entry & ap_cmm_peer_assoc_req_action + +#ifdef DOT11_N_SUPPORT + supported_bw = ez_wlan_config_get_ht_bw_mt7603(pAd); + + if(((PRTMP_ADAPTER)wdev->sys_handle)->CommonCfg.HtCapability.HtCapInfo.ChannelWidth != supported_bw){ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("**** CmnCfg HtCap chan width not in sync with current ht bw\n")); + ((PRTMP_ADAPTER)wdev->sys_handle)->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = supported_bw; + } + + ez_ApStaSetHt(wdev,pEntry); // will update pEntry->HTCapability +#endif +#ifdef DOT11_VHT_AC + vht_bw = ez_wlan_config_get_vht_bw_mt7603(wdev); + + if(((PRTMP_ADAPTER)wdev->sys_handle)->CommonCfg.vht_bw != vht_bw){ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("**** CmnCfg VHt Cap chan width not in sync with current vht bw\n")); + ((PRTMP_ADAPTER)wdev->sys_handle)->CommonCfg.vht_bw = vht_bw; + } + + ez_ApStaSetVht(wdev,pEntry); // will update pEntry->vht_cap_ie +#endif + RTMPSetSupportMCS(wdev->sys_handle, + OPMODE_AP, + pEntry, + pAd->CommonCfg.SupRate, //ie_list->SupportedRates, // Rakesh: use ap values as same phy mode on all devices, no need to use RTMPCheckRates as done by Cli + pAd->CommonCfg.SupRateLen, //ie_list->SupportedRatesLen, + NULL, //wdev->rate.ExtRate can be used + 0, //wdev->rate.ExtRateLen can be used +#ifdef DOT11_VHT_AC + sizeof(pEntry->vht_cap_ie), //use build_vht_cap_ie?? + &pEntry->vht_cap_ie, +#endif /* DOT11_VHT_AC */ + &pEntry->HTCapability, + sizeof(pEntry->HTCapability)); + +#ifdef DOT11_N_SUPPORT + + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if (//(ie_list->ht_cap_len != 0) && // Rakesh: todo check peer capability first before updating + //(wdev->DesiredHtPhyInfo.bHtEnable) && + WMODE_CAP_N(wdev->PhyMode)) // Rakesh: current code assumes all devices on same PhyMode + { + // Rakesh refer ht_mode_adjust() for partial changes taken here as applicable + + if ( //(peer->HtCapInfo.ChannelWidth) && Rakesh: todo check peer capability before updating + (ez_wlan_config_get_ht_bw_mt7603(pAd)) && (ez_wlan_operate_get_ht_bw_mt7603(pAd)) && (supported_bw == BW_40)) + { + pEntry->MaxHTPhyMode.field.BW= BW_40; + } + else + { + pEntry->MaxHTPhyMode.field.BW = BW_20; + pAd->MacTab.fAnyStation20Only = TRUE; + } + + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_INFO,("%s(),MacEntry Updated MODE = %d, BW = %d\n", __FUNCTION__, + pEntry->MaxHTPhyMode.field.MODE, + pEntry->MaxHTPhyMode.field.BW)); + + } + //else Rakesh: todo: check actual cability + //{ + // pAd->MacTab.fAnyStationIsLegacy = TRUE; + // NdisZeroMemory(&pEntry->HTCapability, sizeof(HT_CAPABILITY_IE)); +//#ifdef DOT11_VHT_AC + // // TODO: shiang-usw, it's ugly and need to revise it + // NdisZeroMemory(&pEntry->vht_cap_ie, sizeof(VHT_CAP_IE)); + // pEntry->SupportVHTMCS1SS = 0; + // pEntry->SupportVHTMCS2SS = 0; + // pEntry->SupportVHTMCS3SS = 0; + // pEntry->SupportVHTMCS4SS = 0; + // pEntry->SupportRateMode &= (~SUPPORT_VHT_MODE); +//#endif /* DOT11_VHT_AC */ + //} +#endif /* DOT11_N_SUPPORT */ + + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + +#ifdef MT_MAC + if (((PRTMP_ADAPTER)wdev->sys_handle)->chipCap.hif_type == HIF_MT) + { + if (wdev->bAutoTxRateSwitch == TRUE) + { + pEntry->bAutoTxRateSwitch = TRUE; + } + else + { + pEntry->HTPhyMode.field.MCS = wdev->HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + +#ifdef WFA_VHT_PF + if (WMODE_CAP_AC(wdev->PhyMode)) { + pEntry->HTPhyMode.field.MCS = wdev->DesiredTransmitSetting.field.MCS + + ((wlan_config_get_tx_stream(wdev) - 1) << 4); + } +#endif /* WFA_VHT_PF */ + +#ifdef DOT11_VHT_AC + if (pEntry->HTPhyMode.field.MODE == MODE_VHT) + { + pEntry->HTPhyMode.field.MCS = wdev->DesiredTransmitSetting.field.MCS + + ((wlan_config_get_tx_stream(wdev) - 1) << 4); + } +#endif + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((UCHAR)wdev->DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + + } +#endif /* MT_MAC */ + + // WifiSysApPeerChBwUpdate(((PRTMP_ADAPTER)wdev->sys_handle),pEntry);//,ie_list); // Rakesh: todo pass peer capabilities + + } + else{ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("ERROR !!! not found other peer mac entry\n")); + ASSERT(FALSE); + } + + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_INFO,("%s <<<\n", __FUNCTION__)); + + +} + +//---------------------------------------------------------------------------------------------------------- +// chip ops +//----------------------------------------------------------------------------------------------------------- + +#endif + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/easy_setup/mt7603_chip_ops_api.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/easy_setup/mt7603_chip_ops_api.c new file mode 100644 index 000000000..755ad0fff --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/easy_setup/mt7603_chip_ops_api.c @@ -0,0 +1,2103 @@ +/* + *************************************************************************** + * 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_ez.c + + Abstract: + Easy Setup APIs + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef WH_EZ_SETUP + +#include "rt_config.h" +#include "easy_setup/ez_mod_hooks.h" + +UCHAR IPV4TYPE[] = {0x08, 0x00}; + +unsigned char ez_driver_ops_RandomByte_mt7603(void *ezdev) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + return RandomByte(pAd); +} + +void ez_driver_ops_GenRandom_mt7603( + void *ezdev, + UCHAR *macAddr, + UCHAR *random) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + GenRandom(pAd, macAddr, random); +} + +void ez_driver_ops_DH_PublicKey_Generate_mt7603( + void *ezdev, + UINT8 GValue[], + UINT GValueLength, + UINT8 PValue[], + UINT PValueLength, + UINT8 PrivateKey[], + UINT PrivateKeyLength, + UINT8 PublicKey[], + UINT *PublicKeyLength) +{ + DH_PublicKey_Generate(GValue, GValueLength, PValue, PValueLength, + PrivateKey, PrivateKeyLength, PublicKey, PublicKeyLength); + return; +} + +void ez_driver_ops_RT_DH_SecretKey_Generate_mt7603( + void *ezdev, + UINT8 PublicKey[], + UINT PublicKeyLength, + UINT8 PValue[], + UINT PValueLength, + UINT8 PrivateKey[], + UINT PrivateKeyLength, + UINT8 SecretKey[], + UINT *SecretKeyLength) +{ + RT_DH_SecretKey_Generate(PublicKey, PublicKeyLength, PValue, PValueLength, + PrivateKey, PrivateKeyLength, SecretKey, SecretKeyLength); + return; +} + +void ez_driver_ops_RT_SHA256_mt7603( + void *ezdev, + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 DigestMessage[]) +{ + RT_SHA256(Message, MessageLen, DigestMessage); + return; +} + +VOID ez_driver_ops_WpaDerivePTK_mt7603( + void *ezdev, + UCHAR *PMK, + UCHAR *ANonce, + UCHAR *AA, + UCHAR *SNonce, + UCHAR *SA, + UCHAR *output, + UINT len) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + WpaDerivePTK(pAd, PMK, ANonce, AA, SNonce, SA, output, len); + + return; +} + +INT ez_driver_ops_AES_Key_Unwrap_mt7603( + void *ezdev, + UINT8 CipherText[], + UINT CipherTextLength, + UINT8 Key[], + UINT KeyLength, + UINT8 PlainText[], + UINT *PlainTextLength) +{ + return AES_Key_Unwrap(CipherText, CipherTextLength, Key, KeyLength, PlainText,PlainTextLength); +} + +void ez_driver_ops_install_pairwise_key_mt7603( + void *ezdev, + char *peer_mac, + unsigned char *pmk, + unsigned char *ptk, + unsigned char authenticator) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + MAC_TABLE_ENTRY *entry; + STA_TR_ENTRY *tr_entry; + + entry = MacTableLookup(pAd, peer_mac); + tr_entry = &pAd->MacTab.tr_entry[entry->wcid]; + + SET_AUTHMODE_WPA2PSK(entry->AuthMode); + SET_ENCRYTYPE_AES(entry->WepStatus); + SET_ENCRYTYPE_AES(entry->GroupKeyWepStatus); + //entry->SecConfig.PairwiseKeyId = 1; //Arvind don't need always use 0 + + if (wdev && (wdev->wdev_type == WDEV_TYPE_AP)) { + BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[wdev->func_idx]; + NdisZeroMemory(&pMbss->PMK[0], LEN_PMK); + NdisCopyMemory(&pMbss->PMK[0], pmk, LEN_PMK); + + } else if (entry->wdev && entry->wdev->wdev_type == WDEV_TYPE_STA){ + APCLI_STRUCT *apcli_entry = &pAd->ApCfg.ApCliTab[wdev->func_idx]; + NdisZeroMemory(&apcli_entry->PMK[0], LEN_PMK); + NdisCopyMemory(&apcli_entry->PMK[0], pmk, LEN_PMK); + } + NdisZeroMemory(&entry->PTK[0], LEN_PTK); + NdisCopyMemory(&entry->PTK[0], ptk, LEN_PTK); + /* Set key material to Asic */ + WPAInstallPairwiseKey(pAd, entry->func_tb_idx, entry, authenticator); + + /* Update status and set Port as Secured */ + entry->WpaState = AS_PTKINITDONE; + entry->GTKState = REKEY_ESTABLISHED; + entry->PrivacyFilter = Ndis802_11PrivFilterAcceptAll; + tr_entry->PortSecured = WPA_802_1X_PORT_SECURED; + + //WifiSysUpdatePortSecur(pAd, entry); +} + + +#ifdef APCLI_SUPPORT +void ez_driver_ops_apcli_install_group_key_mt7603( + void *ezdev, + char *peer_mac, + char *peer_gtk, + unsigned char gtk_len) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + MAC_TABLE_ENTRY *entry; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + entry = MacTableLookup(pAd, peer_mac); + + /* Set Group key material, TxMic and RxMic for AP-Client*/ + if(entry) + { + APCliInstallSharedKey( + pAd, + peer_gtk, + gtk_len, + 1, + entry); + } + return; +} +#endif + +int ez_driver_ops_wlan_config_get_ht_bw_mt7603(void *ezdev) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + return pAd->CommonCfg.RegTransmitSetting.field.BW; + +} + +int ez_driver_ops_wlan_config_get_vht_bw_mt7603(void *ezdev) +{ +#ifdef DOT11_VHT_AC + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + return pAd->CommonCfg.vht_bw; +#endif + return 0; +} + +int ez_driver_ops_wlan_operate_get_ht_bw_mt7603(void *ezdev) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + return pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth; +} + +int ez_driver_ops_wlan_operate_get_vht_bw_mt7603(void *ezdev) +{ +#ifdef DOT11_VHT_AC + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + return pAd->CommonCfg.vht_bw; +#endif + return 0; +} + +int ez_driver_ops_wlan_config_get_ext_cha_mt7603(void *ezdev ) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + return pAd->CommonCfg.RegTransmitSetting.field.EXTCHA; +} + +int ez_driver_ops_wlan_operate_get_ext_cha_mt7603(void *ezdev) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + return pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset; +} + +int ez_driver_ops_get_cli_aid_mt7603( + void *ezdev, + char * peer_mac) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + MAC_TABLE_ENTRY *pEntry; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + pEntry = MacTableLookup(pAd, peer_mac); + + if(pEntry) + return pEntry->Aid; + else { + printk("%s Entry not found\n", __FUNCTION__); + ASSERT(FALSE); + return -1; + } +} + +void ez_driver_ops_ez_cancel_timer_mt7603( + void * ezdev, + void * timer_struct) +{ + ez_timer_t *timer = (ez_timer_t *)timer_struct; + + EZ_CANCEL_TIMER(&timer->ez_timer, timer->ez_timer_running); + + return; +} + +void ez_driver_ops_ez_set_timer_mt7603( + void *ezdev, + void * timer_struct, + unsigned long time) +{ + ez_timer_t *timer = (ez_timer_t *)timer_struct; + + RTMPSetTimer(&timer->ez_timer, time); + timer->ez_timer_running = TRUE; + return; +} + +BOOLEAN ez_driver_ops_is_timer_running_mt7603( + void *ezdev, + void * timer_struct) +{ + ez_timer_t *timer = (ez_timer_t *)timer_struct; + + // Arvind : ToDo + return timer->ez_timer_running; +} + +int ez_driver_ops_get_apcli_enable_mt7603(void *ezdev) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + +#ifdef APCLI_SUPPORT + + if(pAd->ApCfg.ApCliTab[wdev->func_idx].Enable) + return TRUE; + else +#endif + return FALSE; +} + +int ez_driver_ops_ApScanRunning_mt7603(void *ezdev) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + if(ApScanRunning(pAd)) + return TRUE; + else + return FALSE; +} + +BOOLEAN EzMlmeEnqueue( + IN RTMP_ADAPTER *pAd, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg, + IN ULONG Priv) +{ + INT Tail; + MLME_QUEUE *Queue = (MLME_QUEUE *)&pAd->Mlme.Queue; + + /* Do nothing if the driver is starting halt state.*/ + /* This might happen when timer already been fired before cancel timer with mlmehalt*/ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS | fRTMP_ADAPTER_NIC_NOT_EXIST)) + return FALSE; + + /* First check the size, it MUST not exceed the mlme queue size*/ + if (MsgLen > MGMT_DMA_BUFFER_SIZE) + { + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("MlmeEnqueue: msg too large, size = %ld \n", MsgLen)); + return FALSE; + } + + if (MlmeQueueFull(Queue, 1)) + { + return FALSE; + } + + NdisAcquireSpinLock(&(Queue->Lock)); + Tail = Queue->Tail; + /* + Double check for safety in multi-thread system. + */ + if (Queue->Entry[Tail].Occupied) + { + NdisReleaseSpinLock(&(Queue->Lock)); + return FALSE; + } + Queue->Tail++; + Queue->Num++; + if (Queue->Tail == MAX_LEN_OF_MLME_QUEUE) + Queue->Tail = 0; + + Queue->Entry[Tail].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) + { + Queue->Entry[Tail].Wcid = ((MLME_QUEUE_ELEM *)Msg)->Wcid; + NdisMoveMemory(Queue->Entry[Tail].Msg, Msg, MsgLen); + } + + NdisReleaseSpinLock(&(Queue->Lock)); + + return TRUE; +} + +void ez_send_unicast_deauth_ap(void *ad_obj, UCHAR *peer_addr) +{ + MLME_DEAUTH_REQ_STRUCT *pInfo = NULL; + MLME_QUEUE_ELEM *Elem; + MAC_TABLE_ENTRY *pEntry = NULL; + RTMP_ADAPTER *pAd = ad_obj; + struct _ez_peer_security_info *ez_peer; + //BOOLEAN ez_peer = FALSE; + os_alloc_mem(pAd, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + if(Elem == NULL) + { + EZ_DEBUG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("Set::OID_802_11_DEAUTHENTICATION, Failed!!\n")); + return; + } + if (Elem) + { + pInfo = (MLME_DEAUTH_REQ_STRUCT *) Elem->Msg; + pInfo->Reason = REASON_NO_LONGER_VALID; + NdisCopyMemory(pInfo->Addr, peer_addr, MAC_ADDR_LEN); + if ((pEntry = MacTableLookup(pAd, peer_addr)) != NULL) + { + Elem->Wcid = pEntry->wcid; + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("WCID = %d\n;", Elem->Wcid)); + hex_dump("address :", pEntry->Addr, 6); + ez_peer = ez_peer_table_search_by_addr(pEntry->wdev,pEntry->Addr); + + if (ez_peer && !ez_peer->delete_in_differred_context){ + APMlmeDeauthReqAction(pAd, Elem); + } else { + + EzMlmeEnqueue(pAd, AP_AUTH_STATE_MACHINE, APMT2_MLME_DEAUTH_REQ, + sizeof(MLME_DEAUTH_REQ_STRUCT), Elem, 0); + } + EZ_DEBUG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("EZ Set::OID_802_11_DEAUTHENTICATION (Reason=%d)\n", pInfo->Reason)); + } + os_free_mem(pAd, Elem); + } +} + +void ez_send_unicast_deauth_apcli(void *ad_obj, USHORT idx) +{ + MLME_QUEUE_ELEM *Elem; + struct _ez_peer_security_info *ez_peer = NULL; + //BOOLEAN ez_peer = FALSE; + struct wifi_dev *wdev; + PRTMP_ADAPTER ad = ad_obj; + + wdev = &ad->ApCfg.ApCliTab[idx].wdev; + os_alloc_mem(ad_obj, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + if(Elem == NULL) + { + EZ_DEBUG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("Set::OID_802_11_DEAUTHENTICATION, Failed!!\n")); + return; + } + ez_peer = ez_peer_table_search_by_addr(wdev, wdev->bssid); + + if (ez_peer && !ez_peer->delete_in_differred_context){ + Elem->Priv = idx | IMM_DISCONNECT; + ApCliCtrlDeAuthAction(ad_obj, Elem); + } else { + MlmeEnqueue(ad, APCLI_CTRL_STATE_MACHINE, APCLI_CTRL_DISCONNECT_REQ, 0, NULL, idx); + } + + os_free_mem(ad, Elem); +} + +void ez_driver_ops_send_unicast_deauth_mt7603( + void *ezdev, + char *peer_mac) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + MAC_TABLE_ENTRY *pEntry = NULL; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + pEntry = MacTableLookup(pAd, peer_mac); + + RtmpOsMsDelay(50); + + if (pEntry && pEntry->wdev->wdev_type == WDEV_TYPE_AP) + { + ez_send_unicast_deauth_ap(ez_dev->driver_ad, peer_mac); + } else if (pEntry && pEntry->wdev->wdev_type == WDEV_TYPE_STA) { + ez_send_unicast_deauth_apcli(ez_dev->driver_ad, pEntry->wdev->func_idx); + } + +} + +VOID UpdateBeaconHandler( + void *ad_obj, + struct wifi_dev *wdev, + UCHAR BCN_UPDATE_REASON) +{ + RTMP_ADAPTER *pAd; + pAd = (RTMP_ADAPTER *)ad_obj; + +#ifdef WH_EZ_SETUP +#ifdef DUAL_CHIP + if(!IS_SINGLE_CHIP_DBDC(pAd)) + { + if ((wdev !=NULL) && IS_EZ_SETUP_ENABLED(wdev)) + RTMP_SEM_LOCK(&pAd->ez_beacon_update_lock); + } +#endif +#endif + + APMakeAllBssBeacon(pAd); + APUpdateAllBeaconFrame(pAd); + +#ifdef WH_EZ_SETUP +#ifdef DUAL_CHIP + if(!IS_SINGLE_CHIP_DBDC(pAd)) + { + if ((wdev !=NULL) && IS_EZ_SETUP_ENABLED(wdev)) + RTMP_SEM_UNLOCK(&pAd->ez_beacon_update_lock); + } +#endif +#endif +} + +void ez_driver_ops_UpdateBeaconHandler_mt7603( + void *ezdev, + int reason) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + + UpdateBeaconHandler(pAd, wdev, (UCHAR)reason); + +} + +void ez_driver_ops_update_security_setting_mt7603( + void *ezdev, + unsigned char *pmk) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + int i; + unsigned char *ptr = NULL; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("------> %s()\n", __FUNCTION__)); + + if(wdev->wdev_type == WDEV_TYPE_AP) + { + BSS_STRUCT *pMbss; + pMbss = &pAd->ApCfg.MBSSID[wdev->func_idx]; + + NdisCopyMemory(&pMbss->PMK[0], pmk, LEN_PMK); + hex_dump("pMbss_pmk", &pMbss->PMK[0], LEN_PMK); + ptr = &pMbss->PSK[0]; + NdisZeroMemory(ptr, sizeof(pMbss->PSK)); + for (i = 0; i < LEN_PMK; i++) { + snprintf(ptr, (LEN_PSK+1), "%s%02x", ptr, pmk[i]); + } + + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_INFO, + ("%s() pMbss->PSK: %s (%d)\n", + __FUNCTION__, pMbss->PSK, (int)strlen(pMbss->PSK))); + + } + else if(wdev->wdev_type == WDEV_TYPE_STA) + { + APCLI_STRUCT *pApCliEntry; + pApCliEntry = &pAd->ApCfg.ApCliTab[wdev->func_idx]; + + NdisCopyMemory(&pApCliEntry->PMK[0], pmk, LEN_PMK); + hex_dump("pApCliEntry_pmk", &pApCliEntry->PMK[0], LEN_PMK); + ptr = &pApCliEntry->PSK[0]; + NdisZeroMemory(ptr, sizeof(pApCliEntry->PSK)); + for (i = 0; i < LEN_PMK; i++) { + snprintf(ptr, (LEN_PSK+1), "%s%02x", ptr, pmk[i]); + } + + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_INFO, + ("%s() pApCliEntry.PSK: %s (%d)\n", + __FUNCTION__, pApCliEntry->PSK, (int)strlen(pApCliEntry->PSK))); + + } + + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("<------ %s()\n", __FUNCTION__)); + +} + + +void ez_driver_ops_update_ap_wsc_profile_mt7603(void *ezdev) +{ +#ifdef WSC_AP_SUPPORT + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + + WSC_CTRL *wsc_ctrl; + BSS_STRUCT *pMbss; + + pMbss = &pAd->ApCfg.MBSSID[wdev->func_idx]; + wsc_ctrl = &pAd->ApCfg.MBSSID[wdev->func_idx].WscControl; + NdisZeroMemory(&wsc_ctrl->WpaPsk[0], LEN_PSK); + wsc_ctrl->WpaPskLen = strlen(pMbss->PSK); + NdisCopyMemory(&wsc_ctrl->WpaPsk[0], pMbss->PSK, wsc_ctrl->WpaPskLen); +#ifdef APCLI_SUPPORT + if ((wdev->wdev_type == WDEV_TYPE_STA) + && (IS_EZ_SETUP_ENABLED(&pAd->ApCfg.MBSSID[wdev->func_idx].wdev))) { + APCLI_STRUCT *pApCliEntry; + pApCliEntry = &pAd->ApCfg.ApCliTab[wdev->func_idx]; + + NdisZeroMemory(pMbss->PSK, sizeof(pMbss->PSK)); + NdisCopyMemory(pMbss->PSK, pApCliEntry->PSK, sizeof(pMbss->PSK)); + + } +#endif /* APCLI_SUPPORT */ + + wsc_ctrl->WscConfStatus = WSC_SCSTATE_CONFIGURED; +#endif /* WSC_AP_SUPPORT */ + +} + +void ez_driver_ops_MiniportMMRequest_mt7603( + void *ezdev, + char *out_buf, + int frame_len, + BOOLEAN need_tx_status) +{ + struct wifi_dev *wdev; + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + wdev = ez_dev->wdev; + wdev->ez_driver_params.need_tx_satus = need_tx_status; + + MiniportMMRequest(pAd, 0, out_buf, frame_len); + + return; +} + +void ez_driver_ops_NdisGetSystemUpTime_mt7603( + void *ezdev, + ULONG *time) +{ + NdisGetSystemUpTime(time); + return; +} + + +INT ez_driver_ops_AES_Key_Wrap_mt7603( + void *ezdev, + UINT8 PlainText[], + UINT PlainTextLength, + UINT8 Key[], + UINT KeyLength, + UINT8 CipherText[], + UINT *CipherTextLength) +{ + return AES_Key_Wrap(PlainText, PlainTextLength, Key, KeyLength, CipherText, CipherTextLength); +} + +INT ez_driver_ops_RtmpOSWrielessEventSendExt_mt7603( + void *ezdev, + UINT32 eventType, + INT flags, + PUCHAR pSrcMac, + PUCHAR pData, + UINT32 dataLen) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + // Arvind : family field needed + return RtmpOSWrielessEventSendExt(pAd->net_dev, eventType, flags, pSrcMac, pData, dataLen, 0); + return 1; + +} + +#ifdef EZ_NETWORK_MERGE_SUPPORT +VOID ez_APMlmeBroadcastDeauthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) +{ + MLME_BROADCAST_DEAUTH_REQ_STRUCT *pInfo; + HEADER_802_11 Hdr; + PUCHAR pOutBuffer = NULL; + NDIS_STATUS NStatus; + ULONG FrameLen = 0; + MAC_TABLE_ENTRY *pEntry; + UCHAR apidx = 0; + struct wifi_dev *wdev; + int wcid, startWcid; + startWcid = 1; + + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("%s\n", __FUNCTION__)); + pInfo = (PMLME_BROADCAST_DEAUTH_REQ_STRUCT)Elem->Msg; + if (!MAC_ADDR_EQUAL(pInfo->Addr,BROADCAST_ADDR)) + { + return; + } + + wdev = pInfo->wdev; + + apidx = wdev->func_idx; + + for (wcid = startWcid; wcid < MAX_LEN_OF_MAC_TABLE; wcid++) + { + pEntry = &pAd->MacTab.Content[wcid]; + if ((pEntry->wdev != wdev)) + { + continue; + } + if (IS_EZ_SETUP_ENABLED(wdev) && (ez_peer_table_search_by_addr(pEntry->wdev, pEntry->Addr) != NULL)) + { + continue; + } + + RTMPSendWirelessEvent(pAd, IW_DEAUTH_EVENT_FLAG, pEntry->Addr, 0, 0); + ApLogEvent(pAd, pInfo->Addr, EVENT_DISASSOCIATED); + hex_dump("DeleteEntryAddr",pEntry->Addr,6); + + MacTableDeleteEntry(pAd, wcid, pEntry->Addr); + +#ifdef WH_EVENT_NOTIFIER + { + EventHdlr pEventHdlrHook = NULL; + pEventHdlrHook = GetEventNotiferHook(WHC_DRVEVNT_STA_LEAVE); + if(pEventHdlrHook && wdev) + pEventHdlrHook(pAd, wdev, pEntry->Addr, Elem->Channel); + } +#endif /* WH_EVENT_NOTIFIER */ + } + + NStatus = MlmeAllocateMemory(pAd, &pOutBuffer); + if (NStatus != NDIS_STATUS_SUCCESS) + return; + + EZ_DEBUG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("AUTH - Send DE-AUTH req to %02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(pInfo->Addr))); + MgtMacHeaderInit(pAd, &Hdr, SUBTYPE_DEAUTH, 0, pInfo->Addr, + pAd->ApCfg.MBSSID[apidx].wdev.if_addr, + pAd->ApCfg.MBSSID[apidx].wdev.bssid); + MakeOutgoingFrame(pOutBuffer, &FrameLen, + sizeof(HEADER_802_11), &Hdr, + 2, &pInfo->Reason, + END_OF_ARGS); + + MiniportMMRequest(pAd, 0, pOutBuffer, FrameLen); + MlmeFreeMemory(NULL, pOutBuffer); +} +#endif + +void ez_driver_ops_send_broadcast_deauth_mt7603(void *ezdev) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + MLME_BROADCAST_DEAUTH_REQ_STRUCT *pInfo = NULL; + MLME_QUEUE_ELEM *Elem; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + + os_alloc_mem(pAd, (UCHAR **)&Elem, sizeof(MLME_QUEUE_ELEM)); + + if(Elem == NULL) + { + EZ_DEBUG(DBG_CAT_CFG, DBG_SUBCAT_ALL, DBG_LVL_ERROR, ("Set::OID_802_11_DEAUTHENTICATION, Failed!!\n")); + return; + } + if (Elem) + { + pInfo = (MLME_BROADCAST_DEAUTH_REQ_STRUCT *) Elem->Msg; + pInfo->wdev = wdev; + Elem->Wcid = WCID_ALL; + pInfo->Reason = MLME_EZ_DISCONNECT_NON_EZ; + NdisCopyMemory(pInfo->Addr, BROADCAST_ADDR, MAC_ADDR_LEN); + APMlmeDeauthReqAction(pAd, Elem); + os_free_mem(pAd, Elem); + } + +} + +void ez_driver_ops_apcli_stop_auto_connect_mt7603( + void *ezdev, + BOOLEAN enable) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + APCLI_STRUCT *apcli_entry; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + + // Arvind : ToDo by raghav + apcli_entry = &pAd->ApCfg.ApCliTab[wdev->func_idx]; + apcli_entry->stop_auto_connect = enable; +} + +void ez_driver_ops_timer_init_mt7603( + void *ezdev, + void* timer, + void *callback) +{ +// ez_dev_t *ez_dev = (ez_dev_t *)ezdev; +// RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; +// struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + + // Arvind : ToDo +} + +void ez_driver_ops_set_ap_ssid_null_mt7603(void *ezdev) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + UCHAR apidx; + BSS_STRUCT *mbss; + + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + apidx = wdev->func_idx; + + mbss = &pAd->ApCfg.MBSSID[apidx]; + NdisZeroMemory(mbss->Ssid, MAX_LEN_OF_SSID); + mbss->SsidLen = 0; + return ; +} + +void* ez_driver_ops_get_pentry_mt7603( + void *ezdev, + UCHAR *mac_addr) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + MAC_TABLE_ENTRY *pEntry; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + pEntry = MacTableLookup(pAd, mac_addr); + + return pEntry; +} + +void ez_driver_ops_reset_entry_duplicate_mt7603( + void *ezdev, + UCHAR *mac_addr) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + MAC_TABLE_ENTRY *pEntry; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + pEntry = MacTableLookup(pAd, mac_addr); +#ifdef WH_EZ_SETUP +#ifdef EZ_DUAL_BAND_SUPPORT + if(pEntry) + pEntry->link_duplicate = FALSE; + else + printk("%s Entry not found !! \n", __FUNCTION__); + +#endif +#endif /* WH_EZ_SETUP */ + printk("\n %s, Prakhar pEntry->link_duplicate is %d\n", __func__, pEntry->link_duplicate); + return ; + +} + +void ez_driver_ops_mark_entry_duplicate_mt7603( + void *ezdev, + UCHAR *mac_addr) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + MAC_TABLE_ENTRY *pEntry; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + pEntry = MacTableLookup(pAd, mac_addr); + +#ifdef WH_EZ_SETUP +#ifdef EZ_DUAL_BAND_SUPPORT + + if(pEntry) + pEntry->link_duplicate = TRUE; + else + printk("%s Entry not found !! \n", __FUNCTION__); + +#endif +#endif /* WH_EZ_SETUP */ + return ; + +} + +void ez_driver_ops_restore_cli_config_mt7603(void *ezdev) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + APCLI_STRUCT *apcli_entry; + BSS_STRUCT *pMbss; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + + //Arvind : todo by raghav + apcli_entry = &pAd->ApCfg.ApCliTab[wdev->func_idx]; + pMbss = &pAd->ApCfg.MBSSID[wdev->func_idx]; + + //! this is a configuration push so I need to switch back to my older configutration. + NdisZeroMemory(apcli_entry->Ssid, apcli_entry->SsidLen); + apcli_entry->SsidLen = pMbss->SsidLen; + NdisCopyMemory(apcli_entry->Ssid, pMbss->Ssid, pMbss->SsidLen); + NdisZeroMemory(apcli_entry->CfgSsid, apcli_entry->SsidLen); + apcli_entry->CfgSsidLen = pMbss->SsidLen; + NdisCopyMemory(apcli_entry->CfgSsid, pMbss->Ssid, pMbss->SsidLen); +} + +void ez_driver_ops_ScanTableInit_mt7603(void *ezdev) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; +// struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + + BssTableInit(&pAd->ScanTab); + return ; +} + + +void ez_driver_ops_RT_HMAC_SHA1_mt7603( + void * ezdev, + UINT8 Key[], + UINT KeyLen, + UINT8 Message[], + UINT MessageLen, + UINT8 MAC[], + UINT MACLen) +{ + RT_HMAC_SHA1(Key, KeyLen, Message, MessageLen, MAC, MACLen); + + return ; +} + +void ez_driver_ops_wlan_config_set_ht_bw_mt7603( + void *ezdev, + UINT8 ht_bw) +{ + + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + pAd->CommonCfg.RegTransmitSetting.field.BW = ht_bw; + + return; +} + +void ez_driver_ops_wlan_config_set_ext_cha_mt7603( + void *ezdev, + UINT8 ext_cha) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + pAd->CommonCfg.RegTransmitSetting.field.EXTCHA = ext_cha; + + return; +} +// +// raghav +// +void ez_driver_ops_wlan_operate_set_ht_bw_mt7603( + void *ezdev, + UINT8 ht_bw) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth = ht_bw; + +} + +void ez_driver_ops_wlan_operate_set_ext_cha_mt7603( + void *ezdev, + UINT8 ext_cha) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + pAd->CommonCfg.AddHTInfo.AddHtInfo.ExtChanOffset = ext_cha; + return; +} + +INT rtmp_set_channel(RTMP_ADAPTER *pAd, struct wifi_dev *wdev, UCHAR Channel) +{ +#ifdef CONFIG_AP_SUPPORT + INT32 i; +#endif /* CONFIG_AP_SUPPORT */ + INT32 Success = TRUE; + //UCHAR Channel; + UCHAR RFChannel; + + pAd->CommonCfg.Channel = Channel; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_AUTO_CONNECT_SUPPORT + if (pAd->ApCfg.ApCliAutoConnectChannelSwitching == FALSE) + pAd->ApCfg.ApCliAutoConnectChannelSwitching = TRUE; +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + + /* check if this channel is valid*/ + if (ChannelSanity(pAd, Channel) == TRUE) + { + 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_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if ((WMODE_CAP_5G(pAd->CommonCfg.PhyMode)) + && (pAd->CommonCfg.bIEEE80211H == TRUE)) + { + for (i = 0; i < pAd->ChannelListNum; i++) + { + if (pAd->ChannelList[i].Channel == Channel) + { + if (pAd->ChannelList[i].RemainingTimeForUse > 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("ERROR: previous detection of a radar on this channel(Channel=%d)\n", Channel)); + Success = FALSE; + break; + } + else + { + DBGPRINT(RT_DEBUG_INFO, ("RemainingTimeForUse %d ,Channel %d\n", + pAd->ChannelList[i].RemainingTimeForUse, Channel)); + } + } + } + } + + if (Success == TRUE) + { + if ((pAd->CommonCfg.Channel > 14 ) + && (pAd->CommonCfg.bIEEE80211H == TRUE)) + { + pAd->Dot11_H.org_ch = pAd->CommonCfg.Channel; + } + + pAd->CommonCfg.Channel = Channel; //lk added + +#ifdef DOT11_N_SUPPORT + N_ChannelCheck(pAd); + + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && + pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40) + RFChannel = N_SetCenCh(pAd, pAd->CommonCfg.Channel); + else +#endif /* DOT11_N_SUPPORT */ + RFChannel = pAd->CommonCfg.Channel; + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): CtrlChannel(%d), CentralChannel(%d) \n", + __FUNCTION__, pAd->CommonCfg.Channel, + pAd->CommonCfg.CentralChannel)); + + if ((pAd->CommonCfg.Channel > 14 ) + && (pAd->CommonCfg.bIEEE80211H == TRUE) +#ifdef WH_EZ_SETUP + && (!(IS_EZ_SETUP_ENABLED(wdev) && (pAd->Dot11_H.RDMode == RD_NORMAL_MODE))) +#endif + + ) + { + if (pAd->Dot11_H.RDMode == RD_SILENCE_MODE) + { + AsicSwitchChannel(pAd, RFChannel, FALSE); +#ifdef WH_EZ_SETUP +#ifdef EZ_NETWORK_MERGE_SUPPORT + //! base channel is different from target channel, do restart AP + if (!IS_EZ_SETUP_ENABLED(wdev) || wdev->ez_driver_params.do_not_restart_interfaces != 1) + { +#endif +#endif + APStop(pAd); + APStartUp(pAd); +#ifdef WH_EZ_SETUP +#ifdef EZ_NETWORK_MERGE_SUPPORT + } else { + + if(Channel > 14) + ap_phy_rrm_init(pAd); + else + ap_phy_rrm_init(pAd); + } +#endif +#endif + + } + else + { + NotifyChSwAnnToPeerAPs(pAd, ZERO_MAC_ADDR, pAd->CurrentAddress, 1, pAd->CommonCfg.Channel); + pAd->Dot11_H.RDMode = RD_SWITCHING_MODE; + pAd->Dot11_H.CSCount = 0; + pAd->Dot11_H.new_channel = Channel; + } + } + else + { +#ifdef WH_EZ_SETUP +#ifdef EZ_NETWORK_MERGE_SUPPORT + //! base channel is different from target channel, do not restart AP + if (!IS_EZ_SETUP_ENABLED(wdev) || wdev->ez_driver_params.do_not_restart_interfaces != 1) + { +#endif +#endif + AsicSwitchChannel(pAd, RFChannel, FALSE); + APStop(pAd); + APStartUp(pAd); +#ifdef WH_EZ_SETUP +#ifdef EZ_NETWORK_MERGE_SUPPORT + } else { + if(Channel > 14) + ap_phy_rrm_init(pAd); + else + ap_phy_rrm_init(pAd); + } + +#endif +#endif + } + } + } +#endif /* CONFIG_AP_SUPPORT */ + + if (Success == TRUE) + DBGPRINT(RT_DEBUG_TRACE, ("Set_Channel_Proc::(Channel=%d)\n", pAd->CommonCfg.Channel)); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { +#ifdef APCLI_AUTO_CONNECT_SUPPORT + pAd->ApCfg.ApCliAutoConnectChannelSwitching = FALSE; +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + } +#endif /* CONFIG_AP_SUPPORT */ + return Success; +} + +void ez_driver_ops_rtmp_set_channel_mt7603( + void *ad_obj, + void * wdev_obj, + UCHAR Channel) +{ +// ez_dev_t *ez_dev = (ez_dev_t *)ezdev; +// RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; +// struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + + struct wifi_dev *wdev = (struct wifi_dev *)wdev_obj; + wdev->ez_driver_params.do_not_restart_interfaces = 1; + rtmp_set_channel(ad_obj,wdev_obj,Channel); + wdev->ez_driver_params.do_not_restart_interfaces = 0; + +// rtmp_set_channel(pAd, wdev, Channel); + +} + +void ez_driver_ops_APScanCnclAction_mt7603(void *ezdev) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + + APScanCnclAction(pAd, NULL); + return ; +} + + +/* Form and transmit Custom loop detect Pkt*/ + void ez_send_loop_detect_pkt_mt7603( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pMacEntry, + IN PUCHAR pOtherCliMac) +{ + UCHAR BROADCAST_ADDR[MAC_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + UCHAR Header802_3[14]={0}; + UCHAR CustomPayload[26]={0x45,0x00, // version(4bit), hdr lenght(4bit), tos + 0x00,0x1A, // total ip datagram length + 0x00,0x01, // identification + 0x40,0x00, // flag & fragmentation + 0x40,0xFD, // TTL, Protocol type + 0x39,0xE7, // hdr checksum (considered 0 for calculation) + 0x00,0x00, // Source IP + 0x00,0x00, // Source IP + 0xFF,0xFF, // Dest IP + 0xFF,0xFF, // Dest IP + 0x11,0x22, // Random Bytes + 0x33,0x44, // Random bytes + 0x55,0x66}; // Random bytes + + //Protocol Type (0x3D any host internal protocol,0x3F any local host network,0xFD & 0xFE for experimentation, 0xFF reserved) + // 2 byte header checksum field, calculated manually by formula and assuming checksum is zero + + //MTWF_LOG(DBG_CAT_CLIENT, CATCLIENT_APCLI, DBG_LVL_OFF, ("-----> ez_send_loop_detect_pkt\n")); + //EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("ez_send_loop_detect_pkt---->\n")); + + NdisZeroMemory(Header802_3,sizeof(UCHAR)*14); + + MAKE_802_3_HEADER(Header802_3, BROADCAST_ADDR, &pMacEntry->wdev->if_addr[0], IPV4TYPE); // or snap type? + + // Using fixed payload due to checksum calculation required using one's complement + NdisCopyMemory(&CustomPayload[20],pOtherCliMac,MAC_ADDR_LEN); + //EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("ez_send_loop_detect_pkt=> Add in payload Other CLi MAC: %02x-%02x-%02x-%02x-%02x-%02x\n", + // CustomPayload[20],CustomPayload[21],CustomPayload[22],CustomPayload[23],CustomPayload[24],CustomPayload[25])); + + // Copy frame to Tx ring + + // Pkt 1 + //EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("ez_send_loop_detect_pkt: wdev_idx:0x%x => Send Loop Detection Pkt 1\n",pMacEntry->wdev->wdev_idx)); + RTMPToWirelessSta((PRTMP_ADAPTER)pAd, pMacEntry, + Header802_3, LENGTH_802_3, (PUCHAR)CustomPayload, 26, FALSE); + OS_WAIT(5); + + // Pkt 2 + //EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("ez_send_loop_detect_pkt: wdev_idx:0x%x => Send Loop Detection Pkt 2\n",pMacEntry->wdev->wdev_idx)); + RTMPToWirelessSta((PRTMP_ADAPTER)pAd, pMacEntry, + Header802_3, LENGTH_802_3, (PUCHAR)CustomPayload, 26, FALSE); + OS_WAIT(5); + + // Pkt 3 + //EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF,("ez_send_loop_detect_pkt: wdev_idx:0x%x => Send Loop Detection Pkt 3\n",pMacEntry->wdev->wdev_idx)); + RTMPToWirelessSta((PRTMP_ADAPTER)pAd, pMacEntry, + Header802_3, LENGTH_802_3, (PUCHAR)CustomPayload, 26, FALSE); + + //EZ_DEBUG(DBG_CAT_CLIENT, CATCLIENT_APCLI, DBG_LVL_OFF, ("<----- ez_send_loop_detect_pkt\n")); +} + +void ez_driver_ops_send_loop_detect_pkt_mt7603( + void *ezdev, + PUCHAR pOtherCliMac) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + PMAC_TABLE_ENTRY pEntry = MacTableLookup2(pAd,((struct wifi_dev *)(wdev))->bssid, wdev); + + if(pEntry && IS_ENTRY_APCLI(pEntry)) + { + ez_send_loop_detect_pkt_mt7603(pAd,pEntry,pOtherCliMac); + } + + return; +} + +/* + ======================================================================== + Rakesh: based on ApCliCheckHt + + ======================================================================== +*/ +static BOOLEAN ez_ApStaSetHt( + IN struct wifi_dev *wdev, + MAC_TABLE_ENTRY *pEntry) +{ + HT_CAPABILITY_IE *aux_ht_cap; + UCHAR cfg_ht_bw; + PRTMP_ADAPTER ad = (PRTMP_ADAPTER)wdev->sys_handle; + + cfg_ht_bw = ad->CommonCfg.RegTransmitSetting.field.BW; + + aux_ht_cap = &pEntry->HTCapability; + /* choose smaller setting */ + +#ifdef CONFIG_MULTI_CHANNEL + aux_ht_cap->HtCapInfo.ChannelWidth = cfg_ht_bw; //pAddHtInfo->AddHtInfo.RecomWidth; +#else /* CONFIG_MULTI_CHANNEL */ + aux_ht_cap->HtCapInfo.ChannelWidth = cfg_ht_bw; //pAddHtInfo->AddHtInfo.RecomWidth & cfg_ht_bw; +#endif /* !CONFIG_MULTI_CHANNEL */ + + /* Fix throughput issue for some vendor AP with AES mode */ + if (cfg_ht_bw) // remove pAddHtInfo->AddHtInfo.RecomWidth & check + aux_ht_cap->HtCapInfo.CCKmodein40 = ad->CommonCfg.HtCapability.HtCapInfo.CCKmodein40; + else + aux_ht_cap->HtCapInfo.CCKmodein40 = 0; + + return TRUE; +} + +/* + ======================================================================== + Rakesh: based on ApCliCheckHt + + ======================================================================== +*/ +BOOLEAN ez_ApCliSetHt( + IN APCLI_STRUCT *pApCliEntry, + MAC_TABLE_ENTRY *pEntry) +{ + HT_CAPABILITY_IE *aux_ht_cap; + UCHAR cfg_ht_bw; + PRTMP_ADAPTER ad = (PRTMP_ADAPTER)(pApCliEntry->wdev.sys_handle); + + cfg_ht_bw = ez_driver_ops_wlan_config_get_ht_bw_mt7603(pApCliEntry->wdev.ez_driver_params.ezdev); //Arvind pass ez_dev + + aux_ht_cap = &pApCliEntry->MlmeAux.HtCapability; + /* choose smaller setting */ + +#ifdef CONFIG_MULTI_CHANNEL + aux_ht_cap->HtCapInfo.ChannelWidth = cfg_ht_bw; //pAddHtInfo->AddHtInfo.RecomWidth; +#else /* CONFIG_MULTI_CHANNEL */ + aux_ht_cap->HtCapInfo.ChannelWidth = cfg_ht_bw; //pAddHtInfo->AddHtInfo.RecomWidth & cfg_ht_bw; +#endif /* !CONFIG_MULTI_CHANNEL */ + + /* Fix throughput issue for some vendor AP with AES mode */ + if (cfg_ht_bw) // remove pAddHtInfo->AddHtInfo.RecomWidth & check + aux_ht_cap->HtCapInfo.CCKmodein40 = ad->CommonCfg.HtCapability.HtCapInfo.CCKmodein40; + else + aux_ht_cap->HtCapInfo.CCKmodein40 = 0; + + /* Record the RxMcs of AP */ + NdisMoveMemory(pApCliEntry->RxMcsSet, ad->CommonCfg.HtCapability.MCSSet, 16); + + NdisMoveMemory(&pEntry->HTCapability, &pApCliEntry->MlmeAux.HtCapability, sizeof(HT_CAPABILITY_IE)); + NdisMoveMemory(pEntry->HTCapability.MCSSet, pApCliEntry->RxMcsSet, 16); + + return TRUE; +} + + +void ez_driver_ops_update_ap_peer_record_mt7603( + void *ezdev, + BOOLEAN band_switched, + PUCHAR peer_addr) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + MAC_TABLE_ENTRY *pEntry= NULL; +#ifdef DOT11_N_SUPPORT + UCHAR supported_bw; +#endif +#ifdef DOT11_VHT_AC + UCHAR vht_bw; +#endif + //PRTMP_ADAPTER adOthBand = ez_get_otherband_ad(wdev); + + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_INFO,("%s >>>\n",__FUNCTION__)); + + if (wdev->wdev_type == WDEV_TYPE_STA) + { + wdev = &pAd->ApCfg.MBSSID[wdev->func_idx].wdev; + } + + + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("%s, wdev->idx:%x ap_peer_mac = %02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__,wdev->wdev_idx,PRINT_MAC(peer_addr))); + + pEntry = MacTableLookup(pAd, peer_addr); + + if(pEntry != NULL){ + + // Rakesh: print current info pMacEntry->HTPhyMode.word pMacEntry->MaxHTPhyMode.word ClientStatusFlags + // pApCliEntry->MlmeAux.HtCapability pMacEntry->HTCapability (pApCliEntry->MlmeAux.vht_cap), (pApCliEntry->MlmeAux.vht_op) + // pMacEntry->vht_cap_ie + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_INFO,("%s(),MacEntry CURRENT MODE = %d, BW = %d\n", __FUNCTION__, + pEntry->MaxHTPhyMode.field.MODE, + pEntry->MaxHTPhyMode.field.BW)); + + // Rakesh: following code taken from update_associated_mac_entry & ap_cmm_peer_assoc_req_action + +#ifdef DOT11_N_SUPPORT + supported_bw = ez_driver_ops_wlan_config_get_ht_bw_mt7603(ezdev); + + if(pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth != supported_bw){ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("**** CmnCfg HtCap chan width not in sync with current ht bw\n")); + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = supported_bw; + } + + ez_ApStaSetHt(wdev,pEntry); // will update pEntry->HTCapability +#endif +#ifdef DOT11_VHT_AC + vht_bw = pAd->CommonCfg.vht_bw;//ez_wlan_config_get_vht_bw_mt7603(wdev); + + if(pAd->CommonCfg.vht_bw != vht_bw){ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("**** CmnCfg VHt Cap chan width not in sync with current vht bw\n")); + pAd->CommonCfg.vht_bw = vht_bw; + } + + ez_ApStaSetVht(wdev,pEntry); // will update pEntry->vht_cap_ie +#endif + RTMPSetSupportMCS(pAd, + OPMODE_AP, + pEntry, + pAd->CommonCfg.SupRate, //ie_list->SupportedRates, // Rakesh: use ap values as same phy mode on all devices, no need to use RTMPCheckRates as done by Cli + pAd->CommonCfg.SupRateLen, //ie_list->SupportedRatesLen, + NULL, //wdev->rate.ExtRate can be used + 0, //wdev->rate.ExtRateLen can be used +#ifdef DOT11_VHT_AC + sizeof(pEntry->vht_cap_ie), //use build_vht_cap_ie?? + &pEntry->vht_cap_ie, +#endif /* DOT11_VHT_AC */ + &pEntry->HTCapability, + sizeof(pEntry->HTCapability)); + +#ifdef DOT11_N_SUPPORT + + /* If this Entry supports 802.11n, upgrade to HT rate. */ + if (//(ie_list->ht_cap_len != 0) && // Rakesh: todo check peer capability first before updating + //(wdev->DesiredHtPhyInfo.bHtEnable) && + WMODE_CAP_N(wdev->PhyMode)) // Rakesh: current code assumes all devices on same PhyMode + { + // Rakesh refer ht_mode_adjust() for partial changes taken here as applicable + + if ( //(peer->HtCapInfo.ChannelWidth) && Rakesh: todo check peer capability before updating + (ez_driver_ops_wlan_config_get_ht_bw_mt7603(ezdev)) && (ez_driver_ops_wlan_operate_get_ht_bw_mt7603(ezdev)) && (supported_bw == BW_40)) + { + pEntry->MaxHTPhyMode.field.BW= BW_40; + } + else + { + pEntry->MaxHTPhyMode.field.BW = BW_20; + pAd->MacTab.fAnyStation20Only = TRUE; + } + + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_INFO,("%s(),MacEntry Updated MODE = %d, BW = %d\n", __FUNCTION__, + pEntry->MaxHTPhyMode.field.MODE, + pEntry->MaxHTPhyMode.field.BW)); + + } + //else Rakesh: todo: check actual cability + //{ + // pAd->MacTab.fAnyStationIsLegacy = TRUE; + // NdisZeroMemory(&pEntry->HTCapability, sizeof(HT_CAPABILITY_IE)); +//#ifdef DOT11_VHT_AC + // // TODO: shiang-usw, it's ugly and need to revise it + // NdisZeroMemory(&pEntry->vht_cap_ie, sizeof(VHT_CAP_IE)); + // pEntry->SupportVHTMCS1SS = 0; + // pEntry->SupportVHTMCS2SS = 0; + // pEntry->SupportVHTMCS3SS = 0; + // pEntry->SupportVHTMCS4SS = 0; + // pEntry->SupportRateMode &= (~SUPPORT_VHT_MODE); +//#endif /* DOT11_VHT_AC */ + //} +#endif /* DOT11_N_SUPPORT */ + + pEntry->HTPhyMode.word = pEntry->MaxHTPhyMode.word; + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) + { + if (wdev->bAutoTxRateSwitch == TRUE) + { + pEntry->bAutoTxRateSwitch = TRUE; + } + else + { + pEntry->HTPhyMode.field.MCS = wdev->HTPhyMode.field.MCS; + pEntry->bAutoTxRateSwitch = FALSE; + +#ifdef WFA_VHT_PF + if (WMODE_CAP_AC(wdev->PhyMode)) { + pEntry->HTPhyMode.field.MCS = wdev->DesiredTransmitSetting.field.MCS + + ((wlan_config_get_tx_stream(wdev) - 1) << 4); + } +#endif /* WFA_VHT_PF */ + +#ifdef DOT11_VHT_AC + if (pEntry->HTPhyMode.field.MODE == MODE_VHT) + { + pEntry->HTPhyMode.field.MCS = wdev->DesiredTransmitSetting.field.MCS + + ((wlan_config_get_tx_stream(wdev) - 1) << 4); + } +#endif + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((UCHAR)wdev->DesiredTransmitSetting.field.FixedTxMode, pEntry); + } + + } +#endif /* MT_MAC */ + + // WifiSysApPeerChBwUpdate(((PRTMP_ADAPTER)wdev->sys_handle),pEntry);//,ie_list); // Rakesh: todo pass peer capabilities + + } + else{ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("ERROR !!! not found other peer mac entry\n")); + ASSERT(FALSE); + } + + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_INFO,("%s <<<\n", __FUNCTION__)); + + +} + +void ez_driver_ops_update_cli_peer_record_mt7603( + void *ezdev, + BOOLEAN band_switched, + PUCHAR peer_addr) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + //RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + //struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + struct wifi_dev* wdev = ez_dev->wdev; + struct wifi_dev *ap_wdev = NULL; + APCLI_STRUCT *pApCliEntry; + PRTMP_ADAPTER pAd = ez_dev->driver_ad; + MAC_TABLE_ENTRY *pMacEntry= NULL; +#ifdef DOT11_N_SUPPORT + UCHAR supported_bw; +#endif +#ifdef DOT11_VHT_AC + unsigned char vht_bw; +#endif + pAd = ((PRTMP_ADAPTER)wdev->sys_handle); + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_INFO,("%s >>>\n", __FUNCTION__)); + + if (wdev->wdev_type == WDEV_TYPE_AP) + { + wdev = &pAd->ApCfg.ApCliTab[wdev->func_idx].wdev; + } + pApCliEntry = wdev->func_dev; + + pMacEntry = MacTableLookup(wdev->sys_handle,peer_addr); + + if(pMacEntry != NULL){ + + // Rakesh: print current info pMacEntry->HTPhyMode.word pMacEntry->MaxHTPhyMode.word ClientStatusFlags + // pApCliEntry->MlmeAux.HtCapability pMacEntry->HTCapability (pApCliEntry->MlmeAux.vht_cap), (pApCliEntry->MlmeAux.vht_op) + // pMacEntry->vht_cap_ie + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_INFO,("%s(),MacEntry CURRENT MODE = %d, BW = %d\n", __FUNCTION__, + pMacEntry->MaxHTPhyMode.field.MODE, + pMacEntry->MaxHTPhyMode.field.BW)); + + // Rakesh: following code taken from ApCliLinkUp + + ap_wdev = &(pAd->ApCfg.MBSSID[wdev->func_idx].wdev); + +#ifdef DOT11_N_SUPPORT + supported_bw = ez_driver_ops_wlan_config_get_ht_bw_mt7603(ezdev); + + if(pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth != supported_bw){ + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("**** CmnCfg HtCap chan width not in sync with current ht bw\n")); + pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth = supported_bw; + } + + ez_ApCliSetHt(pApCliEntry,pMacEntry); // will update pEntry->HTCapability +#endif +#ifdef DOT11_VHT_AC + vht_bw = ez_wlan_config_get_vht_bw_mt7603(wdev); + + if(pAd->CommonCfg.vht_bw != vht_bw){ + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("**** CmnCfg VHt Cap chan width not in sync with current vht bw\n")); + pAd->CommonCfg.vht_bw = vht_bw; + } + + ez_ApCliSetVht(pApCliEntry,pMacEntry); // will update pEntry->vht_cap_ie +#endif + +#ifdef DOT11_N_SUPPORT + /* If this Entry supports 802.11n, upgrade to HT rate. */ + //if (pApCliEntry->MlmeAux.HtCapabilityLen != 0) Rakesh: todo check peer capability before updating + if (WMODE_CAP_N(pApCliEntry->wdev.PhyMode)) // Rakesh: code written asuming all device suport same PhyMode + { + // Rakesh refer ht_mode_adjust() for partial changes taken here as applicable + + if ( //(peer->HtCapInfo.ChannelWidth) && Rakesh: todo check peer capability before updating + (ez_driver_ops_wlan_config_get_ht_bw_mt7603(ezdev)) && (ez_driver_ops_wlan_operate_get_ht_bw_mt7603(ezdev)) && (supported_bw == BW_40)) + { + pMacEntry->MaxHTPhyMode.field.BW= BW_40; + } + else + { + pMacEntry->MaxHTPhyMode.field.BW = BW_20; + pAd->MacTab.fAnyStation20Only = TRUE; + } + + MTWF_LOG(DBG_CAT_AP, DBG_SUBCAT_ALL, DBG_LVL_INFO,("%s(),MacEntry Updated MODE = %d, BW = %d\n", __FUNCTION__, + pMacEntry->MaxHTPhyMode.field.MODE, + pMacEntry->MaxHTPhyMode.field.BW)); + + pMacEntry->HTPhyMode.word = pMacEntry->MaxHTPhyMode.word; + + } + //else Rakesh: Todo check AP capability + //{ + // pAd->MacTab.fAnyStationIsLegacy = TRUE; + // MTWF_LOG(DBG_CAT_CLIENT, CATCLIENT_APCLI, DBG_LVL_TRACE, ("ApCliLinkUp - MaxSupRate=%d Mbps\n", + // RateIdToMbps[pMacEntry->MaxSupportedRate])); + //} +#endif /* DOT11_N_SUPPORT */ + + + pMacEntry->HTPhyMode.word = pMacEntry->MaxHTPhyMode.word; + + pApCliEntry->MlmeAux.SupRateLen = pAd->CommonCfg.SupRateLen;//ap_wdev->rate.SupRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.SupRate, pAd->CommonCfg.SupRate, pApCliEntry->MlmeAux.SupRateLen); // Rakesh: RTMPCheckRates not required as same phy mode on all devices + + pApCliEntry->MlmeAux.ExtRateLen = pAd->CommonCfg.ExtRateLen; + NdisMoveMemory(pApCliEntry->MlmeAux.ExtRate, pAd->CommonCfg.ExtRate, pApCliEntry->MlmeAux.ExtRateLen); // Rakesh: RTMPCheckRates not required as same phy mode on all devices + + RTMPSetSupportMCS(wdev->sys_handle, + OPMODE_AP, + pMacEntry, + pApCliEntry->MlmeAux.SupRate, + pApCliEntry->MlmeAux.SupRateLen, + pApCliEntry->MlmeAux.ExtRate, + pApCliEntry->MlmeAux.ExtRateLen, +#ifdef DOT11_VHT_AC + pApCliEntry->MlmeAux.vht_cap_len, + &pApCliEntry->MlmeAux.vht_cap, +#endif /* DOT11_VHT_AC */ + &pApCliEntry->MlmeAux.HtCapability, + pApCliEntry->MlmeAux.HtCapabilityLen); + + //WifiSysApCliChBwUpdate(pAd,pApCliEntry,CliIdx, pMacEntry); + +#ifdef MT_MAC + if (pAd->chipCap.hif_type == HIF_MT) { + + if (wdev->bAutoTxRateSwitch == TRUE) + { + pMacEntry->bAutoTxRateSwitch = TRUE; + } + else + { + pMacEntry->HTPhyMode.field.MCS = wdev->HTPhyMode.field.MCS; + pMacEntry->bAutoTxRateSwitch = FALSE; + + /* If the legacy mode is set, overwrite the transmit setting of this entry. */ + RTMPUpdateLegacyTxSetting((UCHAR)wdev->DesiredTransmitSetting.field.FixedTxMode, pMacEntry); + } + + MlmeRAInit(pAd, pMacEntry); + + } +#endif + } + else{ + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("ERROR !!! not found other peer mac entry\n")); + ASSERT(FALSE); + } + + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_INFO,("%s <<<\n", __FUNCTION__)); +} + + +void ez_driver_ops_MgtMacHeaderInit_mt7603( + void *ezdev, + HEADER_802_11_EZ *pHdr80211, + UCHAR SubType, + UCHAR ToDs, + UCHAR *pDA, + UCHAR *pSA, + UCHAR *pBssid) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + //struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + + MgtMacHeaderInit(pAd, (HEADER_802_11 *)pHdr80211, SubType, ToDs, pDA, pSA, pBssid); + return; +} +// raghav +BOOLEAN ez_driver_ops_is_mlme_running_mt7603(void *ezdev) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + return pAd->Mlme.bRunning; +} + +VOID ez_driver_ops_ApSiteSurvey_by_wdev_mt7603( + void *ezdev_obj, + void * pSsid, + UCHAR ScanType, + BOOLEAN ChannelSel, + BOOLEAN scan_one_channel) +{ + ez_dev_t *ezdev = ezdev_obj; + struct wifi_dev *wdev = ezdev->wdev; + PRTMP_ADAPTER ad = wdev->sys_handle; + wdev->ez_driver_params.ez_scan = TRUE; + wdev->ez_driver_params.scan_one_channel = scan_one_channel; + ApSiteSurvey(ad, pSsid, ScanType, ChannelSel, wdev); + + //Arvind need to implement +} + +void ez_driver_ops_fill_out_table_mt7603(BSS_TABLE* Tab, EZ_BSS_TABLE *pEzBss) +{ + UINT16 i; + pEzBss->BssNr = Tab->BssNr; + for (i = 0; i < Tab->BssNr; i++) + { + COPY_MAC_ADDR(pEzBss->BssEntry[i].MacAddr, Tab->BssEntry[i].MacAddr); + COPY_MAC_ADDR(pEzBss->BssEntry[i].Bssid, Tab->BssEntry[i].Bssid); + pEzBss->BssEntry[i].Channel = Tab->BssEntry[i].Channel; + pEzBss->BssEntry[i].CentralChannel = Tab->BssEntry[i].CentralChannel; + pEzBss->BssEntry[i].Rssi = Tab->BssEntry[i].Rssi; + pEzBss->BssEntry[i].SsidLen = Tab->BssEntry[i].SsidLen; + NdisCopyMemory(pEzBss->BssEntry[i].Ssid, Tab->BssEntry[i].Ssid, pEzBss->BssEntry[i].SsidLen); + pEzBss->BssEntry[i].AKMMap = AuthMode_to_AKM_map(Tab->BssEntry[i].AuthMode); // Arvind convet into bitmap + pEzBss->BssEntry[i].PairwiseCipher = WepStatus_to_PairwiseCipher(Tab->BssEntry[i].WepStatus); + pEzBss->BssEntry[i].GroupCipher = WepStatus_to_PairwiseCipher(Tab->BssEntry[i].WepStatus);//Tab->BssEntry[i].GroupCipher;// Arvind handle later + pEzBss->BssEntry[i].support_easy_setup = Tab->BssEntry[i].support_easy_setup; + pEzBss->BssEntry[i].easy_setup_capability = Tab->BssEntry[i].easy_setup_capability; + pEzBss->BssEntry[i].bConnectAttemptFailed = Tab->BssEntry[i].bConnectAttemptFailed; + pEzBss->BssEntry[i].non_ez_beacon = Tab->BssEntry[i].non_ez_beacon; + NdisCopyMemory(pEzBss->BssEntry[i].open_group_id, + Tab->BssEntry[i].open_group_id,Tab->BssEntry[i].open_group_id_len); + pEzBss->BssEntry[i].open_group_id_len = Tab->BssEntry[i].open_group_id_len; + NdisCopyMemory(&pEzBss->BssEntry[i].beacon_info,&Tab->BssEntry[i].beacon_info,sizeof(beacon_info_tag_t)); + } +} + + +void ez_driver_sort_apcli_tab_by_rssi_mt7603(void *ad_obj, void *wdev_obj) +{ + PRTMP_ADAPTER pAd = ad_obj; + struct wifi_dev *wdev = wdev_obj; + APCLI_STRUCT *apcli_entry = &pAd->ApCfg.ApCliTab[wdev->func_idx]; + BSS_TABLE *Tab = &apcli_entry->MlmeAux.SsidBssTab; + BssTableSortByRssi(Tab, FALSE); +} + +void ez_driver_ops_add_entry_in_apcli_tab_mt7603(void *ad_obj, void *wdev_obj, ULONG bss_entry_idx) +{ + PRTMP_ADAPTER pAd = ad_obj; + struct wifi_dev *wdev = wdev_obj; + APCLI_STRUCT *apcli_entry = &pAd->ApCfg.ApCliTab[wdev->func_idx]; + BSS_TABLE *Tab = &apcli_entry->MlmeAux.SsidBssTab; + NdisCopyMemory(&Tab->BssEntry[Tab->BssNr],&pAd->ScanTab.BssEntry[bss_entry_idx],sizeof(BSS_ENTRY)); + Tab->BssNr++; + Tab->BssOverlapNr++; +} + +void ez_driver_ops_ApCliBssTabInit_mt7603(void *ad_obj, void *wdev_obj) +{ + PRTMP_ADAPTER pAd = ad_obj; + struct wifi_dev *wdev = wdev_obj; + APCLI_STRUCT *apcli_entry = &pAd->ApCfg.ApCliTab[wdev->func_idx]; + BSS_TABLE *Tab = &apcli_entry->MlmeAux.SsidBssTab; + BssTableInit(Tab); +} + + +void ez_driver_ops_get_scan_table_mt7603(void *ad_obj,EZ_BSS_TABLE *pEzBss) +{ + PRTMP_ADAPTER pAd = ad_obj; + BSS_TABLE *Tab = &pAd->ScanTab; + UINT16 i; + pEzBss->BssNr = Tab->BssNr; + + for (i = 0; i < Tab->BssNr; i++) + { + COPY_MAC_ADDR(pEzBss->BssEntry[i].MacAddr, Tab->BssEntry[i].MacAddr); + COPY_MAC_ADDR(pEzBss->BssEntry[i].Bssid, Tab->BssEntry[i].Bssid); + pEzBss->BssEntry[i].Channel = Tab->BssEntry[i].Channel; + pEzBss->BssEntry[i].CentralChannel = Tab->BssEntry[i].CentralChannel; + pEzBss->BssEntry[i].Rssi = Tab->BssEntry[i].Rssi; + pEzBss->BssEntry[i].SsidLen = Tab->BssEntry[i].SsidLen; + NdisCopyMemory(pEzBss->BssEntry[i].Ssid, Tab->BssEntry[i].Ssid, pEzBss->BssEntry[i].SsidLen); + pEzBss->BssEntry[i].AKMMap = AuthMode_to_AKM_map(Tab->BssEntry[i].AuthMode); // Arvind convet into bitmap + pEzBss->BssEntry[i].PairwiseCipher = WepStatus_to_PairwiseCipher(Tab->BssEntry[i].WepStatus); + pEzBss->BssEntry[i].GroupCipher = WepStatus_to_PairwiseCipher(Tab->BssEntry[i].WepStatus);//Tab->BssEntry[i].; // Arvind handle later + pEzBss->BssEntry[i].support_easy_setup = Tab->BssEntry[i].support_easy_setup; + pEzBss->BssEntry[i].easy_setup_capability = Tab->BssEntry[i].easy_setup_capability; + pEzBss->BssEntry[i].bConnectAttemptFailed = Tab->BssEntry[i].bConnectAttemptFailed; + pEzBss->BssEntry[i].non_ez_beacon = Tab->BssEntry[i].non_ez_beacon; + NdisCopyMemory(pEzBss->BssEntry[i].open_group_id, + Tab->BssEntry[i].open_group_id,Tab->BssEntry[i].open_group_id_len); + pEzBss->BssEntry[i].open_group_id_len = Tab->BssEntry[i].open_group_id_len; + NdisCopyMemory(&pEzBss->BssEntry[i].beacon_info,&Tab->BssEntry[i].beacon_info,sizeof(beacon_info_tag_t)); + + } + +} + + + +void ez_driver_ops_update_partial_scan_mt7603(void * ez_ad_obj, void *wdev_obj) +{ + ULONG now; + EZ_ADAPTER *ez_ad = ez_ad_obj; + struct wifi_dev *wdev = wdev_obj; + NdisGetSystemUpTime(&now); + if (RTMP_TIME_AFTER(now,wdev->ez_driver_params.partial_scan_time_stamp + ez_ad->ez_partial_scan_time*OS_HZ)) + { + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s() Eligible candidate found !!! Restart partial scan timer\n", __FUNCTION__)); + NdisGetSystemUpTime(&wdev->ez_driver_params.partial_scan_time_stamp); + + } + + +} + +VOID ez_driver_ops_BssTableSsidSort_mt7603( + IN void * ad_obj, + IN void *wdev_obj, + OUT EZ_BSS_TABLE *OutTab, + IN CHAR Ssid[], + IN UCHAR SsidLen) +{ + PRTMP_ADAPTER pAd = ad_obj; + struct wifi_dev *wdev = wdev_obj; + APCLI_STRUCT *apcli_entry = &pAd->ApCfg.ApCliTab[wdev->func_idx]; + + BSS_TABLE *Tab = &apcli_entry->MlmeAux.SsidBssTab; + + //BSS_TABLE *driver_out_tab; + //os_alloc_mem(ad_obj,(UCHAR **)&driver_out_tab,sizeof(BSS_TABLE)); + //if(driver_out_tab == NULL) + // return; + BssTableSsidSort(ad_obj,wdev_obj,Tab,Ssid,SsidLen); + ez_driver_ops_fill_out_table_mt7603(Tab,OutTab); + //os_free_mem(driver_out_tab); +} + + +BOOLEAN ez_driver_ops_update_cli_conn_mt7603(void* ad_obj,void *ez_dev_obj, EZ_BSS_ENTRY *bss_entry) +{ + PRTMP_ADAPTER pAd = ad_obj; + ez_dev_t *ezdev = ez_dev_obj; + EZ_ADAPTER *ez_ad = ezdev->ez_ad; + ez_dev_t *ap_ezdev = &ez_ad->ez_band_info[ezdev->ez_band_idx].ap_ezdev; + struct wifi_dev *wdev = ((ez_dev_t *)ezdev)->wdev; + struct wifi_dev *ap_wdev = &pAd->ApCfg.MBSSID[wdev->func_idx].wdev; + PAPCLI_STRUCT apcli_entry; + apcli_entry = &pAd->ApCfg.ApCliTab[wdev->func_idx]; + + COPY_MAC_ADDR(apcli_entry->CfgApCliBssid, bss_entry->Bssid); + NdisZeroMemory(apcli_entry->CfgSsid, MAX_LEN_OF_SSID); + NdisMoveMemory(apcli_entry->CfgSsid, bss_entry->Ssid, bss_entry->SsidLen); + apcli_entry->CfgSsidLen = bss_entry->SsidLen; + wdev->AuthMode= AKM_map_to_AuthMode(bss_entry->AKMMap); // Arvind convert bitmap to real value same for below + wdev->WepStatus= PairwiseCipher_to_WepStatus(bss_entry->PairwiseCipher); + wdev->GroupKeyWepStatus = PairwiseCipher_to_WepStatus(bss_entry->GroupCipher); + + apcli_entry->MlmeAux.attempted_candidate_index = ezdev->attempted_candidate_index; + apcli_entry->MlmeAux.support_easy_setup = ezdev->support_ez_setup; + +#ifdef EZ_NETWORK_MERGE_SUPPORT + if(ezdev->ez_security.internal_force_connect_bssid == TRUE) + { + if (pAd->CommonCfg.Channel != bss_entry->Channel) + { + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_ERROR,("stale scan list %d %d!!!\n",pAd->CommonCfg.Channel,bss_entry->Channel)); + //ASSERT(FALSE); + ez_initiate_new_scan_hook(ezdev->ez_ad); + return FALSE; + } + } + //! adjust APCLI's operating bandwidth to that of peer + ez_ApCliAutoConnectBWAdjust(pAd, wdev, bss_entry); + ez_ApCliAutoConnectBWAdjust(pAd, ap_wdev, bss_entry); +#ifdef EZ_NETWORK_MERGE_SUPPORT +#ifdef EZ_DUAL_BAND_SUPPORT + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("ez_apcli_search_best_ap_configured\nAPCLI=> CurrChannel: %d, TarChannel: %d\n", + ezdev->ez_security.this_band_info.shared_info.channel_info.channel, + bss_entry->Channel)); +#ifdef EZ_PUSH_BW_SUPPORT + //if( ((PRTMP_ADAPTER)(wdev->sys_handle))->push_bw_config ) + { + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("\tHT-BW: %d, CFG:%d OPER:%d\n", + ezdev->ez_security.this_band_info.shared_info.channel_info.ht_bw, + ez_driver_ops_wlan_config_get_ht_bw_mt7603(wdev->ez_driver_params.ezdev), ez_driver_ops_wlan_operate_get_ht_bw_mt7603(wdev->ez_driver_params.ezdev))); +#ifdef DOT11_VHT_AC + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("\tVHT-BW: %d CFG:%d OPER:%d\n", + ezdev->ez_security.this_band_info.shared_info.channel_info.vht_bw, + ez_driver_ops_wlan_config_get_vht_bw_mt7603(wdev),ez_driver_ops_wlan_operate_get_vht_bw_mt7603(wdev))); +#endif + } +#else + { + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("\tHT-BW: CFG:%d OPER:%d\n", + ez_driver_ops_wlan_config_get_ht_bw_mt7603(wdev->ez_driver_params.ezdev),ez_driver_ops_wlan_operate_get_ht_bw_mt7603(wdev->ez_driver_params.ezdev))); +#ifdef DOT11_VHT_AC + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("\tVHT-BW: CFG:%d OPER:%d\n", + ez_driver_ops_wlan_config_get_vht_bw_mt7603(wdev),ez_driver_ops_wlan_operate_get_vht_bw_mt7603(wdev))); +#endif + } +#endif + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("\tEXTCHA: %d CFG:%d OPER:%d\n", + ezdev->ez_security.this_band_info.shared_info.channel_info.extcha, + ez_driver_ops_wlan_config_get_ext_cha_mt7603(wdev->ez_driver_params.ezdev), ez_driver_ops_wlan_operate_get_ext_cha_mt7603(wdev->ez_driver_params.ezdev))); + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("AP=> CurrChannel: %d, TarChannel: %d\n", + ap_ezdev->ez_security.this_band_info.shared_info.channel_info.channel, + bss_entry->Channel)); +#ifdef EZ_PUSH_BW_SUPPORT + //if( ((PRTMP_ADAPTER)(ap_wdev->sys_handle))->push_bw_config ) + { + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("\tHT-BW: %d, CFG:%d OPER:%d\n", + ap_ezdev->ez_security.this_band_info.shared_info.channel_info.ht_bw, + ez_driver_ops_wlan_config_get_ht_bw_mt7603(ap_wdev->ez_driver_params.ezdev),ez_driver_ops_wlan_operate_get_ht_bw_mt7603(ap_wdev->ez_driver_params.ezdev))); +#ifdef DOT11_VHT_AC + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("\tVHT-BW: %d CFG:%d OPER:%d\n", + ap_ezdev->ez_security.this_band_info.shared_info.channel_info.vht_bw, + wlan_config_get_vht_bw(ap_wdev),wlan_operate_get_vht_bw(ap_wdev))); +#endif + } +#else + { + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("\tHT-BW: CFG:%d OPER:%d\n", + ez_driver_ops_wlan_config_get_ht_bw_mt7603(ap_wdev->ez_driver_params.ezdev),ez_driver_ops_wlan_operate_get_ht_bw_mt7603(ap_wdev->ez_driver_params.ezdev))); +#ifdef DOT11_VHT_AC + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("\tVHT-BW: CFG:%d OPER:%d\n", + wlan_config_get_vht_bw(ap_wdev),wlan_operate_get_vht_bw(ap_wdev))); +#endif + } +#endif + + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE,("\tEXTCHA: %d CFG:%d OPER:%d\n", + ap_ezdev->ez_security.this_band_info.shared_info.channel_info.extcha, + ez_driver_ops_wlan_config_get_ext_cha_mt7603(ap_wdev->ez_driver_params.ezdev),ez_driver_ops_wlan_operate_get_ext_cha_mt7603(ap_wdev->ez_driver_params.ezdev))); +#endif +#endif + + ap_wdev->ez_driver_params.do_not_restart_interfaces = 1; + + rtmp_set_channel(pAd,ap_wdev, bss_entry->Channel); + + ap_wdev->ez_driver_params.do_not_restart_interfaces = 0; +#else + if ((pAd->CommonCfg.Channel != bss_entry->Channel)) { + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE, + ("%s - Switch channel to ch.%d\n", __FUNCTION__, bss_entry->Channel)); + rtmp_set_channel(pAd,ap_wdev, bss_entry->Channel); +#ifdef APCLI_AUTO_CONNECT_SUPPORT +#ifdef APCLI_AUTO_BW_TMP + if(ez_ApCliAutoConnectBWAdjust(pAd, wdev, bss_entry)) + rtmp_set_channel(pAd, ap_wdev, bss_entry->Channel); + else + EZ_DEBUG(DBG_CAT_MLME, DBG_SUBCAT_ALL, DBG_LVL_TRACE, ("%s(): ApCliAutoConnectBWAdjust() return FALSE\n", __FUNCTION__)); + +#endif //APCLI_AUTO_BW_TMP +#endif //APCLI_AUTO_CONNECT_SUPPORT + } +#endif + return TRUE; +} + + +// prakhar ::: + +BOOLEAN ez_driver_ops_update_ap_mt7603( + void *ezdev, + void *updated_configs) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + EZ_ADAPTER *ez_ad = (EZ_ADAPTER *)ez_dev->ez_ad; + struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + updated_configs_t *update_configs =(updated_configs_t *)updated_configs; + + BSS_STRUCT *mbss; + if (wdev->wdev_type == WDEV_TYPE_STA) + { + wdev = &pAd->ApCfg.MBSSID[wdev->func_idx].wdev; + } + mbss = wdev->func_dev; + + mbss->SsidLen = update_configs->this_band_info.shared_info.ssid_len ; + NdisZeroMemory(mbss->Ssid, MAX_LEN_OF_SSID); + NdisCopyMemory(mbss->Ssid, update_configs->this_band_info.shared_info.ssid, mbss->SsidLen); + if (ez_ad->band_count == 1 && ez_ad->non_ez_band_count == 2) + { + mbss->SsidLen = 0; + NdisZeroMemory(mbss->Ssid, MAX_LEN_OF_SSID); + NdisCopyMemory(mbss->Ssid, "\0", sizeof("\0")); + + } + + NdisCopyMemory(&mbss->PMK[0], update_configs->this_band_info.pmk, LEN_PMK); + + SET_AUTHMODE_WPA2PSK(wdev->AuthMode); + SET_ENCRYTYPE_AES(wdev->WepStatus); + SET_ENCRYTYPE_AES(wdev->GroupKeyWepStatus); + + return TRUE; +} + + +BOOLEAN ez_driver_ops_update_cli_mt7603( + void *ezdev, + void *updated_configs) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + updated_configs_t *update_configs =(updated_configs_t *)updated_configs; + APCLI_STRUCT *apcli_entry; + + if (wdev->wdev_type == WDEV_TYPE_AP) + { + wdev = &pAd->ApCfg.ApCliTab[wdev->func_idx].wdev; + } + apcli_entry = wdev->func_dev; + + NdisZeroMemory(apcli_entry->Ssid,MAX_LEN_OF_SSID); + apcli_entry->SsidLen = update_configs->this_band_info.shared_info.ssid_len ; + NdisCopyMemory(apcli_entry->Ssid, update_configs->this_band_info.shared_info.ssid,update_configs->this_band_info.shared_info.ssid_len ); + + NdisZeroMemory(apcli_entry->CfgSsid,MAX_LEN_OF_SSID); + apcli_entry->CfgSsidLen = update_configs->this_band_info.shared_info.ssid_len ; + NdisCopyMemory(apcli_entry->CfgSsid, update_configs->this_band_info.shared_info.ssid,update_configs->this_band_info.shared_info.ssid_len ); + + NdisCopyMemory(&apcli_entry->PMK[0], update_configs->this_band_info.pmk, LEN_PMK); + + return TRUE; +} + + + +void ez_driver_ops_ApSiteSurvey_mt7603( + void *ezdev, + int scan_one_channel) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + + ApSiteSurvey(pAd, NULL, SCAN_ACTIVE, FALSE, wdev); + return; +} + + +void ez_driver_ops_wlan_config_set_vht_bw_mt7603(void *ezdev, UINT8 vht_bw) +{ + //ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + //struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + + // Arvind not supported + + return; + +} + +INT ez_driver_ops_SetCommonHtVht_mt7603(void *ezdev) +{ + ez_dev_t *ez_dev = (ez_dev_t *)ezdev; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)ez_dev->driver_ad; + //struct wifi_dev *wdev = (struct wifi_dev *)ez_dev->wdev; + + return SetCommonHT(pAd); +} +void ez_driver_ops_restore_channel_config_7603(void * ezdev) +{ + ez_restore_channel_config(((ez_dev_t *)ezdev)->wdev); +} +ez_driver_ops_t ez_driver_ops_7603 = { + .RandomByte = ez_driver_ops_RandomByte_mt7603, + .GenRandom = ez_driver_ops_GenRandom_mt7603, + .DH_PublicKey_Generate = ez_driver_ops_DH_PublicKey_Generate_mt7603, + .RT_DH_SecretKey_Generate = ez_driver_ops_RT_DH_SecretKey_Generate_mt7603, + .RT_SHA256 = ez_driver_ops_RT_SHA256_mt7603, + .WpaDerivePTK = ez_driver_ops_WpaDerivePTK_mt7603, + .AES_Key_Unwrap = ez_driver_ops_AES_Key_Unwrap_mt7603, + .ez_install_pairwise_key = ez_driver_ops_install_pairwise_key_mt7603, + .ez_apcli_install_group_key = ez_driver_ops_apcli_install_group_key_mt7603, + .wlan_config_get_ht_bw = ez_driver_ops_wlan_config_get_ht_bw_mt7603, + .wlan_config_get_vht_bw = ez_driver_ops_wlan_config_get_vht_bw_mt7603, + .wlan_operate_get_ht_bw = ez_driver_ops_wlan_operate_get_ht_bw_mt7603, + .wlan_operate_get_vht_bw = ez_driver_ops_wlan_operate_get_vht_bw_mt7603, + .wlan_config_get_ext_cha = ez_driver_ops_wlan_config_get_ext_cha_mt7603, + .wlan_operate_get_ext_cha = ez_driver_ops_wlan_operate_get_ext_cha_mt7603, + .get_cli_aid = ez_driver_ops_get_cli_aid_mt7603, + .ez_cancel_timer = ez_driver_ops_ez_cancel_timer_mt7603, + .ez_set_timer = ez_driver_ops_ez_set_timer_mt7603, + .ez_is_timer_running = ez_driver_ops_is_timer_running_mt7603, + .get_apcli_enable = ez_driver_ops_get_apcli_enable_mt7603, + .ApScanRunning = ez_driver_ops_ApScanRunning_mt7603, + .ez_send_unicast_deauth = ez_driver_ops_send_unicast_deauth_mt7603, + .ez_restore_channel_config = ez_driver_ops_restore_channel_config_7603, + .UpdateBeaconHandler = ez_driver_ops_UpdateBeaconHandler_mt7603, + .ez_update_security_setting = ez_driver_ops_update_security_setting_mt7603, + .ez_update_ap_wsc_profile = ez_driver_ops_update_ap_wsc_profile_mt7603, + .APScanCnclAction = ez_driver_ops_APScanCnclAction_mt7603, + .ez_send_loop_detect_pkt = ez_driver_ops_send_loop_detect_pkt_mt7603, + .ez_update_ap = ez_driver_ops_update_ap_mt7603, + .ez_update_cli = ez_driver_ops_update_cli_mt7603, + .ez_update_ap_peer_record = ez_driver_ops_update_ap_peer_record_mt7603, + .ez_update_cli_peer_record = ez_driver_ops_update_cli_peer_record_mt7603, + .MiniportMMRequest = ez_driver_ops_MiniportMMRequest_mt7603, + .NdisGetSystemUpTime = ez_driver_ops_NdisGetSystemUpTime_mt7603, + .AES_Key_Wrap = ez_driver_ops_AES_Key_Wrap_mt7603, + .RtmpOSWrielessEventSendExt = ez_driver_ops_RtmpOSWrielessEventSendExt_mt7603, + .ez_send_broadcast_deauth = ez_driver_ops_send_broadcast_deauth_mt7603, + .MgtMacHeaderInit = ez_driver_ops_MgtMacHeaderInit_mt7603, + .apcli_stop_auto_connect = ez_driver_ops_apcli_stop_auto_connect_mt7603, + .timer_init = NULL, + .set_ap_ssid_null = ez_driver_ops_set_ap_ssid_null_mt7603, + //.ez_set_entry_apcli = ez_driver_ops_set_entry_apcli_mt7603, + .ez_get_pentry = ez_driver_ops_get_pentry_mt7603, + .ez_mark_entry_duplicate = ez_driver_ops_mark_entry_duplicate_mt7603, + .ez_restore_cli_config = ez_driver_ops_restore_cli_config_mt7603, + .ScanTableInit = ez_driver_ops_ScanTableInit_mt7603, + .RT_HMAC_SHA1 = ez_driver_ops_RT_HMAC_SHA1_mt7603, + .is_mlme_running = ez_driver_ops_is_mlme_running_mt7603, + //.ApSiteSurvey = ez_driver_ops_ApSiteSurvey_mt7603, + .ez_ApSiteSurvey_by_wdev = ez_driver_ops_ApSiteSurvey_by_wdev_mt7603, + .ez_BssTableSsidSort = ez_driver_ops_BssTableSsidSort_mt7603, + .ez_get_scan_table = ez_driver_ops_get_scan_table_mt7603, + .ez_add_entry_in_apcli_tab = ez_driver_ops_add_entry_in_apcli_tab_mt7603, + .ez_sort_apcli_tab_by_rssi = ez_driver_sort_apcli_tab_by_rssi_mt7603, + .ez_ApCliBssTabInit = ez_driver_ops_ApCliBssTabInit_mt7603, + .ez_update_cli_conn = ez_driver_ops_update_cli_conn_mt7603, + .ez_update_partial_scan = ez_driver_ops_update_partial_scan_mt7603, + .ez_rtmp_set_channel = ez_driver_ops_rtmp_set_channel_mt7603, + .wlan_config_set_ht_bw = ez_driver_ops_wlan_config_set_ht_bw_mt7603, + .wlan_config_set_vht_bw = ez_driver_ops_wlan_config_set_vht_bw_mt7603, + .wlan_config_set_ext_cha = ez_driver_ops_wlan_config_set_ext_cha_mt7603, + .SetCommonHtVht = ez_driver_ops_SetCommonHtVht_mt7603, + .ez_reset_entry_duplicate = ez_driver_ops_reset_entry_duplicate_mt7603 + + }; +#endif + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/easy_setup/mt7603_driver_specific_func.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/easy_setup/mt7603_driver_specific_func.c new file mode 100644 index 000000000..4db663ffc --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/easy_setup/mt7603_driver_specific_func.c @@ -0,0 +1,173 @@ +/* + *************************************************************************** + * 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_ez.c + + Abstract: + Easy Setup APIs + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifdef WH_EZ_SETUP +#include "rt_config.h" + +UINT32 AuthMode_to_AKM_map(NDIS_802_11_AUTHENTICATION_MODE authMode) +{ + UINT32 _AKMMap; + + CLEAR_SEC_AKM(_AKMMap); + + switch(authMode) + { + case Ndis802_11AuthModeOpen: + SET_AKM_OPEN(_AKMMap); + break; + case Ndis802_11AuthModeShared: + SET_AKM_SHARED(_AKMMap); + break; + case Ndis802_11AuthModeAutoSwitch: + SET_AKM_AUTOSWITCH(_AKMMap); + break; + case Ndis802_11AuthModeWPA: + SET_AKM_WPA1(_AKMMap); + break; + case Ndis802_11AuthModeWPAPSK: + SET_AKM_WPA1PSK(_AKMMap); + break; + case Ndis802_11AuthModeWPANone: + SET_AKM_WPANONE(_AKMMap); + break; + case Ndis802_11AuthModeWPA2: + SET_AKM_WPA2(_AKMMap); + break; + case Ndis802_11AuthModeWPA2PSK: + SET_AKM_WPA2PSK(_AKMMap); + break; + case Ndis802_11AuthModeWPA1WPA2: + //SET_AKM_FT_WPA2(_AKMMap); //Arvind : not found + break; + case Ndis802_11AuthModeWPA1PSKWPA2PSK: + //SET_AKM_FT_WPA2PSK(_AKMMap); //Arvind : not found + break; +#ifdef WAPI_SUPPORT + case Ndis802_11AuthModeWAICERT : + SET_AKM_WAICERT(_AKMMap); + break; + case Ndis802_11AuthModeWAIPSK : + SET_AKM_WPIPSK(_AKMMap); + break; +#endif + default: + break; + } + + return _AKMMap; +} + +NDIS_802_11_AUTHENTICATION_MODE AKM_map_to_AuthMode(UINT32 _AKMMap) +{ + + NDIS_802_11_AUTHENTICATION_MODE authMode; + authMode = 0; + + if(IS_AKM_OPEN(_AKMMap)) + authMode =Ndis802_11AuthModeOpen; + else if(IS_AKM_SHARED(_AKMMap)) + authMode =Ndis802_11AuthModeShared; + else if(IS_AKM_AUTOSWITCH(_AKMMap)) + authMode =Ndis802_11AuthModeAutoSwitch; + else if(IS_AKM_WPA1(_AKMMap)) + authMode =Ndis802_11AuthModeWPA; + else if(IS_AKM_WPA1PSK(_AKMMap)) + authMode =Ndis802_11AuthModeWPAPSK; + else if(IS_AKM_WPANONE(_AKMMap)) + authMode =Ndis802_11AuthModeWPANone; + else if(IS_AKM_WPA2(_AKMMap)) + authMode =Ndis802_11AuthModeWPA2; + else if(IS_AKM_WPA2PSK(_AKMMap)) + authMode =Ndis802_11AuthModeWPA2PSK; +#ifdef WAPI_SUPPORT + else if(IS_AKM_WAICERT(_AKMMap)) + authMode =Ndis802_11AuthModeWAICERT; + else if(IS_AKM_WPIPSK(_AKMMap)) + authMode =Ndis802_11AuthModeWAIPSK; +#endif + + return authMode; +} + +UINT32 WepStatus_to_PairwiseCipher(NDIS_802_11_WEP_STATUS WepStatus) +{ + UINT32 PairwiseCipher; + + PairwiseCipher = 0x0; + + switch(WepStatus) + { + case Ndis802_11WEPDisabled: + SET_CIPHER_NONE(PairwiseCipher); + break; + case Ndis802_11WEPEnabled: + SET_CIPHER_WEP(PairwiseCipher); + break; + case Ndis802_11TKIPEnable: + SET_CIPHER_TKIP(PairwiseCipher); + break; + case Ndis802_11AESEnable: + SET_CIPHER_CCMP128(PairwiseCipher); + break; + case Ndis802_11TKIPAESMix: + SET_CIPHER_TKIP(PairwiseCipher); + SET_CIPHER_CCMP128(PairwiseCipher); + break; + default: + break; + } + + return PairwiseCipher; +} + + +NDIS_802_11_WEP_STATUS PairwiseCipher_to_WepStatus(UINT32 PairwiseCipher) +{ + + NDIS_802_11_WEP_STATUS WepStatus; + WepStatus = 0; + + if(IS_CIPHER_NONE(PairwiseCipher)) + WepStatus =Ndis802_11WEPDisabled; + else if(IS_CIPHER_WEP(PairwiseCipher)) + WepStatus =Ndis802_11WEPEnabled; + else if(IS_CIPHER_TKIP(PairwiseCipher)) + WepStatus =Ndis802_11TKIPEnable; + else if(IS_CIPHER_CCMP128(PairwiseCipher)) + WepStatus =Ndis802_11AESEnable; + else if(IS_CIPHER_TKIP(PairwiseCipher) && IS_CIPHER_CCMP128(PairwiseCipher)) + WepStatus =Ndis802_11TKIPAESMix; + + return WepStatus; +} + + + + +#endif + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7601_USB_V0_D-20130416.bin b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7601_USB_V0_D-20130416.bin new file mode 100644 index 0000000000000000000000000000000000000000..2b98110b8cb3d6c8d3158bf4030026129b8692cd GIT binary patch literal 512 zcmZQ9W8h`raaK!k_zwn*O#LE^Wef~n42%p70UQj>3``6R4F4G&5*i>1fTZAm7LEV^ zbr}EupE@*fC5Gy@XYz}~=+Q2%!}NDcy&Oc)gY|7T!?C{jXF`+%{L zfnkcn28WY8Kv4*ZBn@Q3%pjINcI?QJBL@xu2_SiZbp7b|fLybOfuRFLg8;fbIv=76 LM*au-dw2l=Qrd|- literal 0 HcmV?d00001 diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7603E1E2_EEPROM_layout_2014011_ePAeLNA.bin b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7603E1E2_EEPROM_layout_2014011_ePAeLNA.bin new file mode 100644 index 0000000000000000000000000000000000000000..06cb339c720adef67ddca5873400e12b3d6cf311 GIT binary patch literal 512 zcmZQB<6&UnaaK!kU@ki>@*fC5Gy@XYz}~=+Q2%!}NDcy&%y=07|7T!?C{jXF`+%{L zfnkcn28WYCQyCy6k~EMBGlN+A*s&u=jvP1uB!J`rO#OUJ47|Kt2s;Rw3sSj@*fC5Gy@XYz}~=+Q2%!}NDcy&Oc)gY|7T!?C{jXF`+%{L zfnkcn28UznK+yw7K_ml%6a~bwV@Hl0IdA|-0LcRk3@|s4OM{%Uhk>C3M1ue!b0Df< L@*fC5G*Aoyi4t5T1H%K5 jn1}@*fC5Gy@XYz}~=+Q2%!}NDcy&%o!Ab3V<3xKnX&D$p?&$ z3=AR;3=YSXf&2qUK_ml%6a~bwV@Hl0IdA|-0LcRk3@|s4OM{$ppMjwZM1ue!b0Df< MW7*<0CbR8IsgCw literal 0 HcmV?d00001 diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7603E_EEPROM.bin b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7603E_EEPROM.bin new file mode 100644 index 0000000000000000000000000000000000000000..4d9fab4b7b23fa2e59a544ba068ee956cd9c3a52 GIT binary patch literal 512 zcmZQB<7QysaaK!kU@ki>@*fC5Gy@XYz}~=+Q2%!}NDcy&Oc)gY|7T!?C{jXF`+%{L zfnkcn28WY8Kv4*ZBn@Q3%pjINcI?QJBL@xu2_SiZbp7b|fLybOfuRFLg8;fbIv=76 LM*au-dw2l=Qrd|- literal 0 HcmV?d00001 diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7662E1_EEPROM_layout_20130301.bin b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7662E1_EEPROM_layout_20130301.bin new file mode 100644 index 0000000000000000000000000000000000000000..e0b42d3b755068e36063be5c6f0627f4e71e4520 GIT binary patch literal 512 zcmYc)V}OFBvcn=ECXD_M1?Cs#G9=Xhoefh5r2jK0Ffi<4goymVk0b+UN`YBOB$!D$ Q0XGl_1Ln$6n!FGI0D1&eKL7v# literal 0 HcmV?d00001 diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7662E2_EEPROM_20130412.bin b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7662E2_EEPROM_20130412.bin new file mode 100644 index 0000000000000000000000000000000000000000..2fd84a82778ebbcf53fa70932b78a1fcdc26dbab GIT binary patch literal 512 zcmYc)V_;z5aV|?@NGdxl0%XJK|4?9lV=hBN{omOz{{R0<{}~j33K>DF85sWGhtQ~` z6qt)df|;ZfsHS4_5UwJR#eb^g=nHlOTgD9>Y7BfVq6}RO4nSKt80K;?2ps@26j-z- mFfgbvvV?G4SfHT*wS@yh1ARZp!GXr6!z`|D>>Qlf9SQ)6DlZ%W literal 0 HcmV?d00001 diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7662E2_EEPROM_20130527.bin b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/eeprom/MT7662E2_EEPROM_20130527.bin new file mode 100644 index 0000000000000000000000000000000000000000..41d39dcaa1bdd9bb3569d28df0de4e5c5715d2a8 GIT binary patch literal 512 zcmYc)V_;z5aV|?@NGdxl0%XJK|4?9lV=hBN{omOz{{R0<{}~ki|KG(3Qq92d|2~8U zkq@9^EnHGSUNbj{tYQO_V4{Kp$f{!k5@ljQqErS*RDx83iE5C#auFa=#|jb?1QHAk zhk<~B;n1O`CJ+XR96AIdA!5x82v?EE;y+b#^aZ=Gsf-Yf|L;Q$K%!c>)PTHZ zZV*|;1|upsfUG(uAW((gOb|#gFdRO7g1qfG>$KpR#a`Xkefi2?(4mAco7Ey*S1_z)G91L?g7=#W0844^~6Brm&7+FF% gE-cVcfZDt70EWgtpa1{> literal 0 HcmV?d00001 diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hif/hif_pci.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hif/hif_pci.c new file mode 100644 index 000000000..4cf320fb2 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hif/hif_pci.c @@ -0,0 +1,36 @@ + +#include "rt_config.h" + + +#ifdef RTMP_MAC_PCI +INT NICInitPwrPinCfg(RTMP_ADAPTER *pAd) +{ +#if defined(RTMP_MAC) || defined(RLT_MAC) + UINT32 mac_val = 0; +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + + return FALSE; + } + +#if defined(RTMP_MAC) || defined(RLT_MAC) + /*@!Release + For MT76x0 series, + PWR_PIN_CFG[2:0]: obsolete, no function + Don't need to change PWR_PIN_CFG here. + */ + mac_val = 0x3; /* To fix driver disable/enable hang issue when radio off*/ + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, mac_val); +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + return TRUE; +} + + + +#endif /* RTMP_MAC_PCI */ + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/cmm_asic.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/cmm_asic.c new file mode 100644 index 000000000..c38c74ad1 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/cmm_asic.c @@ -0,0 +1,3310 @@ +/* + *************************************************************************** + * 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" + + +UINT32 AsicGetCrcErrCnt(RTMP_ADAPTER *pAd) +{ + RX_STA_CNT0_STRUC RxStaCnt; + + RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt.word); + + return RxStaCnt.field.CrcErr; +} + + +UINT32 AsicGetCCACnt(RTMP_ADAPTER *pAd) +{ + RX_STA_CNT1_STRUC RxStaCnt1; + + RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt1.word); + + return RxStaCnt1.field.FalseCca; +} + + +UINT32 AsicGetChBusyCnt(RTMP_ADAPTER *pAd, UCHAR ch_idx) +{ + UINT32 cnt = 0, reg = 0; + + if (ch_idx == 0) + reg = CH_BUSY_STA; + else if (ch_idx == 1) + reg = CH_BUSY_STA_SEC; + + if (reg) + RTMP_IO_READ32(pAd, reg, &cnt); + + return cnt; +} + + +#ifdef FIFO_EXT_SUPPORT +BOOLEAN NicGetMacFifoTxCnt(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + if (pEntry->wcid >= 1 && pEntry->wcid <= 8) + { + WCID_TX_CNT_STRUC wcidTxCnt; + UINT32 regAddr; + + regAddr = WCID_TX_CNT_0 + (pEntry->wcid - 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(RTMP_ADAPTER *pAd, 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->wcid >=1 && pEntry->wcid <= 8) + { + regAddr = WCID_TX_CNT_0 + (pEntry->wcid - 1) * 4; + RTMP_IO_READ32(pAd, regAddr, &wcidTxCnt.word); + } + } +} +#endif /* FIFO_EXT_SUPPORT */ + + + + +INT AsicSetAutoFallBack(RTMP_ADAPTER *pAd, BOOLEAN enable) +{ + TX_RTY_CFG_STRUC tx_rty_cfg = {.word = 0}; + + RTMP_IO_READ32(pAd, TX_RTY_CFG, &tx_rty_cfg.word); + tx_rty_cfg.field.TxautoFBEnable = ((enable == TRUE) ? 1 : 0); + RTMP_IO_WRITE32(pAd, TX_RTY_CFG, tx_rty_cfg.word); + + return TRUE; +} + + +INT AsicAutoFallbackInit(RTMP_ADAPTER *pAd) +{ +#ifdef RANGE_EXTEND + RTMP_IO_WRITE32(pAd, HT_FBK_CFG1, 0xedcba980); +#endif // RANGE_EXTEND // +#ifdef DOT11N_SS3_SUPPORT + if (pAd->CommonCfg.TxStream >= 3) + { + RTMP_IO_WRITE32(pAd, TX_FBK_CFG_3S_0, 0x12111008); + RTMP_IO_WRITE32(pAd, TX_FBK_CFG_3S_1, 0x16151413); + } +#endif /* DOT11N_SS3_SUPPORT */ + + return TRUE; +} + + +/* + ======================================================================== + + Routine Description: + Set MAC register value according operation mode. + OperationMode AND bNonGFExist are for MM and GF Proteciton. + If MM or GF mask is not set, those passing argument doesn't not take effect. + + Operation mode meaning: + = 0 : Pure HT, no preotection. + = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS. + = 0x10: No Transmission in 40M is protected. + = 0x11: Transmission in both 40M and 20M shall be protected + if (bNonGFExist) + we should choose not to use GF. But still set correct ASIC registers. + ======================================================================== +*/ +typedef enum _PROT_REG_IDX_{ + REG_IDX_CCK = 0, /* 0x1364 */ + REG_IDX_OFDM = 1, /* 0x1368 */ + REG_IDX_MM20 = 2, /* 0x136c */ + REG_IDX_MM40 = 3, /* 0x1370 */ + REG_IDX_GF20 = 4, /* 0x1374 */ + REG_IDX_GF40 = 5, /* 0x1378 */ +}PROT_REG_IDX; + + +VOID AsicUpdateProtect( + IN PRTMP_ADAPTER pAd, + IN USHORT OperationMode, + IN UCHAR SetMask, + IN BOOLEAN bDisableBGProtect, + IN BOOLEAN bNonGFExist) +{ + PROT_CFG_STRUC ProtCfg, ProtCfg4; + UINT32 Protect[6], PhyMode = 0x4000; + USHORT offset; + UCHAR i; + UINT32 MacReg = 0; +#ifdef DOT11_VHT_AC +#endif /* DOT11_VHT_AC */ + +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + return; +#endif /* CONFIG_ATE */ + +#ifdef DOT11_N_SUPPORT + if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8)) + return; + + if (pAd->BATable.numDoneOriginator) + { + /* enable the RTS/CTS to avoid channel collision*/ + SetMask |= ALLN_SETPROTECT; + OperationMode = 8; + } +#endif /* DOT11_N_SUPPORT */ + + /* Config ASIC RTS threshold register*/ + RTMP_IO_READ32(pAd, TX_RTS_CFG, &MacReg); + MacReg &= 0xFF0000FF; + /* If the user want disable RtsThreshold and enbale Amsdu/Ralink-Aggregation, set the RtsThreshold as 4096*/ + if (( +#ifdef DOT11_N_SUPPORT + (pAd->CommonCfg.BACapability.field.AmsduEnable) || +#endif /* DOT11_N_SUPPORT */ + (pAd->CommonCfg.bAggregationCapable == TRUE)) + && pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD) + { + MacReg |= (0x1000 << 8); + } + else + { + MacReg |= (pAd->CommonCfg.RtsThreshold << 8); + } + + RTMP_IO_WRITE32(pAd, TX_RTS_CFG, MacReg); + + /* Initial common protection settings*/ + RTMPZeroMemory(Protect, sizeof(Protect)); + ProtCfg4.word = 0; + ProtCfg.word = 0; + ProtCfg.field.TxopAllowGF40 = 1; + ProtCfg.field.TxopAllowGF20 = 1; + ProtCfg.field.TxopAllowMM40 = 1; + ProtCfg.field.TxopAllowMM20 = 1; + ProtCfg.field.TxopAllowOfdm = 1; + ProtCfg.field.TxopAllowCck = 1; + ProtCfg.field.RTSThEn = 1; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + +#ifdef DOT11_VHT_AC +#endif /* DOT11_VHT_AC */ + + /* update PHY mode and rate*/ + if (pAd->OpMode == OPMODE_AP) + { + /* update PHY mode and rate*/ + if (pAd->CommonCfg.Channel > 14) + ProtCfg.field.ProtectRate = PhyMode; + ProtCfg.field.ProtectRate |= pAd->CommonCfg.RtsRate; + } + else if (pAd->OpMode == OPMODE_STA) + { + // Decide Protect Rate for Legacy packet + if (pAd->CommonCfg.Channel > 14) + { + ProtCfg.field.ProtectRate = PhyMode; // OFDM 6Mbps + } + else + { + ProtCfg.field.ProtectRate = 0x0000; // CCK 1Mbps + if (pAd->CommonCfg.MinTxRate > RATE_11) + ProtCfg.field.ProtectRate |= PhyMode; // OFDM 6Mbps + } + } + +#ifdef DOT11_VHT_AC +#endif /* DOT11_VHT_AC */ + +#ifdef CONFIG_FPGA_MODE +//+++Add by shiang for debug + if (pAd->fpga_ctl.fpga_on & 0x8) + { + DBGPRINT(RT_DEBUG_TRACE, ("%s():RtsRate=%d\n", + __FUNCTION__, pAd->CommonCfg.RtsRate)); + } +//---Add by shiang for debug +#endif /* CONFIG_FPGA_MODE */ + + /* Handle legacy(B/G) protection*/ + if (bDisableBGProtect) + { + /*ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;*/ + ProtCfg.field.ProtectCtrl = 0; + Protect[REG_IDX_CCK] = ProtCfg.word; + Protect[REG_IDX_OFDM] = ProtCfg.word; + pAd->FlgCtsEnabled = 0; /* CTS-self is not used */ + } + else + { + if (pAd->CommonCfg.Channel <= 14) { + /*ProtCfg.field.ProtectRate = pAd->CommonCfg.RtsRate;*/ + ProtCfg.field.ProtectCtrl = 0; /* CCK do not need to be protected*/ + Protect[REG_IDX_CCK] = ProtCfg.word; + ProtCfg.field.ProtectCtrl = ASIC_CTS; /* OFDM needs using CCK to protect*/ + Protect[REG_IDX_OFDM] = ProtCfg.word; + pAd->FlgCtsEnabled = 1; /* CTS-self is used */ + } else { + ProtCfg.field.ProtectCtrl = 0; + Protect[REG_IDX_CCK] = ProtCfg.word; + Protect[REG_IDX_OFDM] = ProtCfg.word; + pAd->FlgCtsEnabled = 0; /* CTS-self is not used */ + } + } + +#ifdef DOT11_N_SUPPORT + /* Decide HT frame protection.*/ + if ((SetMask & ALLN_SETPROTECT) != 0) + { + switch(OperationMode) + { + case 0x0: + /* NO PROTECT */ + /* 1.All STAs in the BSS are 20/40 MHz HT*/ + /* 2. in ai 20/40MHz BSS*/ + /* 3. all STAs are 20MHz in a 20MHz BSS*/ + /* Pure HT. no protection.*/ + + /* MM20_PROT_CFG*/ + /* Reserved (31:27)*/ + /* PROT_TXOP(25:20) -- 010111*/ + /* PROT_NAV(19:18) -- 01 (Short NAV protection)*/ + /* PROT_CTRL(17:16) -- 00 (None)*/ + /* PROT_RATE(15:0) -- 0x4004 (OFDM 24M)*/ + Protect[2] = 0x01744004; + + /* MM40_PROT_CFG*/ + /* Reserved (31:27)*/ + /* PROT_TXOP(25:20) -- 111111*/ + /* PROT_NAV(19:18) -- 01 (Short NAV protection)*/ + /* PROT_CTRL(17:16) -- 00 (None) */ + /* PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)*/ + Protect[3] = 0x03f44084; + + /* CF20_PROT_CFG*/ + /* Reserved (31:27)*/ + /* PROT_TXOP(25:20) -- 010111*/ + /* PROT_NAV(19:18) -- 01 (Short NAV protection)*/ + /* PROT_CTRL(17:16) -- 00 (None)*/ + /* PROT_RATE(15:0) -- 0x4004 (OFDM 24M)*/ + Protect[4] = 0x01744004; + + /* CF40_PROT_CFG*/ + /* Reserved (31:27)*/ + /* PROT_TXOP(25:20) -- 111111*/ + /* PROT_NAV(19:18) -- 01 (Short NAV protection)*/ + /* PROT_CTRL(17:16) -- 00 (None)*/ + /* PROT_RATE(15:0) -- 0x4084 (duplicate OFDM 24M)*/ + Protect[5] = 0x03f44084; + + if (bNonGFExist) + { + /* PROT_NAV(19:18) -- 01 (Short NAV protectiion)*/ + /* PROT_CTRL(17:16) -- 01 (RTS/CTS)*/ + Protect[REG_IDX_GF20] = 0x01754004; + Protect[REG_IDX_GF40] = 0x03f54084; + } + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; + +#ifdef DOT11_VHT_AC +#endif /* DOT11_VHT_AC */ + break; + + case 1: + /* This is "HT non-member protection mode." */ + /* If there may be non-HT STAs my BSS*/ + ProtCfg.word = 0x01744004; /* PROT_CTRL(17:16) : 0 (None) */ + ProtCfg4.word = 0x03f44084; /* duplicaet legacy 24M. BW set 1 */ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + { + ProtCfg.word = 0x01740003; /*ERP use Protection bit is set, use protection rate at Clause 18..*/ + ProtCfg4.word = 0x03f40003; /* Don't duplicate RTS/CTS in CCK mode. 0x03f40083; */ + } + /* Assign Protection method for 20&40 MHz packets */ + ProtCfg.field.ProtectCtrl = ASIC_RTS; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + ProtCfg4.field.ProtectCtrl = ASIC_RTS; + ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; + Protect[REG_IDX_MM20] = ProtCfg.word; + Protect[REG_IDX_MM40] = ProtCfg4.word; + Protect[REG_IDX_GF20] = ProtCfg.word; + Protect[REG_IDX_GF40] = ProtCfg4.word; + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; + +#ifdef DOT11_VHT_AC +#endif /* DOT11_VHT_AC */ + + break; + + case 2: + /* If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets */ + ProtCfg.word = 0x01744004; /* PROT_CTRL(17:16) : 0 (None) */ + ProtCfg4.word = 0x03f44084; /* duplicaet legacy 24M. BW set 1 */ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + { + ProtCfg.word = 0x01740003; /* ERP use Protection bit is set, use protection rate at Clause 18..*/ + ProtCfg4.word = 0x03f40003; /* Don't duplicate RTS/CTS in CCK mode. 0x03f40083; */ + } + /* Assign Protection method for 40MHz packets */ + ProtCfg4.field.ProtectCtrl = ASIC_RTS; + ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; + Protect[REG_IDX_MM20] = ProtCfg.word; + Protect[REG_IDX_MM40] = ProtCfg4.word; + if (bNonGFExist) + { + ProtCfg.field.ProtectCtrl = ASIC_RTS; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + } + Protect[REG_IDX_GF20] = ProtCfg.word; + Protect[REG_IDX_GF40] = ProtCfg4.word; + + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = FALSE; + +#ifdef DOT11_VHT_AC +#endif /* DOT11_VHT_AC */ + break; + + case 3: + /* HT mixed mode. PROTECT ALL!*/ + /* Assign Rate */ + ProtCfg.word = 0x01744004; /* Duplicaet legacy 24M. BW set 1 */ + ProtCfg4.word = 0x03f44084; + /* both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the */ + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + { + ProtCfg.word = 0x01740003; /* ERP use Protection bit is set, use protection rate at Clause 18 */ + ProtCfg4.word = 0x03f40003; /* Don't duplicate RTS/CTS in CCK mode. 0x03f40083 */ + } + /* Assign Protection method for 20&40 MHz packets */ + ProtCfg.field.ProtectCtrl = ASIC_RTS; + ProtCfg.field.ProtectNav = ASIC_SHORTNAV; + ProtCfg4.field.ProtectCtrl = ASIC_RTS; + ProtCfg4.field.ProtectNav = ASIC_SHORTNAV; + Protect[REG_IDX_MM20] = ProtCfg.word; + Protect[REG_IDX_MM40] = ProtCfg4.word; + Protect[REG_IDX_GF20] = ProtCfg.word; + Protect[REG_IDX_GF40] = ProtCfg4.word; + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; + +#ifdef DOT11_VHT_AC +#endif /* DOT11_VHT_AC */ + break; + + case 8: + /* Special on for Atheros problem n chip. */ + ProtCfg.word = 0x01754004; /* Duplicaet legacy 24M. BW set 1. */ + ProtCfg4.word = 0x03f54084; + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_BG_PROTECTION_INUSED)) + { + ProtCfg.word = 0x01750003; /* ERP use Protection bit is set, use protection rate at Clause 18 */ + ProtCfg4.word = 0x03f50003; /* Don't duplicate RTS/CTS in CCK mode. 0x03f40083 */ + } + +#ifdef ENHANCE_ULTP + if (pAd->rts_option == 1) { + // disable RTS/CTS only when one STA with High MCS rate + if (pAd->MacTab.Content.N) + + } else if (pAd->rts_option == 2) { + ProtCfg.word = 0x01744004; /*duplicaet legacy 24M. BW set 1.*/ + ProtCfg4.word = 0x03f44084; + DBGPRINT(RT_DEBUG_TRACE, ("Enhance RTS/CTS ------\n")); + } +#endif /* ENHANCE_ULTP */ + + Protect[REG_IDX_MM20] = ProtCfg.word; /* 0x01754004; */ + Protect[REG_IDX_MM40] = ProtCfg4.word; /* 0x03f54084; */ + Protect[REG_IDX_GF20] = ProtCfg.word; /* 0x01754004; */ + Protect[REG_IDX_GF40] = ProtCfg4.word; /* 0x03f54084; */ + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; + break; + } + } +#endif /* DOT11_N_SUPPORT */ + + offset = CCK_PROT_CFG; + for (i = 0;i < 6;i++) + { + if ((SetMask & (1<< i))) + { + } + RTMP_IO_WRITE32(pAd, offset + i*4, Protect[i]); + } + +#ifdef DOT11_VHT_AC +#endif /* DOT11_VHT_AC */ +} + + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSwitchChannel(RTMP_ADAPTER *pAd, UCHAR Channel, BOOLEAN bScan) +{ + UCHAR bw; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + +#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 */ + + if (pAd->chipOps.ChipSwitchChannel) + pAd->chipOps.ChipSwitchChannel(pAd, Channel, bScan); + else + DBGPRINT(RT_DEBUG_ERROR, ("For this chip, no specified channel switch function!\n")); + + /* R66 should be set according to Channel and use 20MHz when scanning*/ + if (bScan) + bw = BW_20; + else { + bw = pAd->CommonCfg.BBPCurrentBW; + } + RTMPSetAGCInitValue(pAd, bw); +} + + +/* + ========================================================================== + Description: + This function is required for 2421 only, and should not be used during + site survey. It's only required after NIC decided to stay at a channel + for a longer period. + When this function is called, it's always after AsicSwitchChannel(). + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicLockChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) +{ +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ + + +VOID AsicResetBBPAgent(RTMP_ADAPTER *pAd) +{ + BBP_CSR_CFG_STRUC BbpCsr; + + /* Still need to find why BBP agent keeps busy, but in fact, hardware still function ok. Now clear busy first. */ + /* IF chipOps.AsicResetBbpAgent == NULL, run "else" part */ + if (pAd->chipOps.AsicResetBbpAgent != NULL) + pAd->chipOps.AsicResetBbpAgent(pAd); + else if (pAd->chipCap.MCUType != ANDES) + { + DBGPRINT(RT_DEBUG_INFO, ("Reset BBP Agent busy bit.!! \n")); + RTMP_IO_READ32(pAd, H2M_BBP_AGENT, &BbpCsr.word); + BbpCsr.field.Busy = 0; + RTMP_IO_WRITE32(pAd, H2M_BBP_AGENT, BbpCsr.word); + } +} + + + + +/* + ========================================================================== + Description: + Set My BSSID + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ + /* CFG_TODO */ +VOID AsicSetBssid(RTMP_ADAPTER *pAd, UCHAR *pBssid, UCHAR omac_idx) +{ + UINT32 Addr4; + + DBGPRINT(RT_DEBUG_TRACE, ("===> AsicSetBssid %x:%x:%x:%x:%x:%x\n", + PRINT_MAC(pBssid))); + + Addr4 = (UINT32)(pBssid[0]) | + (UINT32)(pBssid[1] << 8) | + (UINT32)(pBssid[2] << 16) | + (UINT32)(pBssid[3] << 24); + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW0, Addr4); + +#ifdef HDR_TRANS_SUPPORT + RTMP_IO_WRITE32(pAd, HT_MAC_BSSID_DW0, Addr4); +#endif /* HDR_TRANS_SUPPORT */ + + Addr4 = 0; + /* always one BSSID in STA mode*/ + Addr4 = (UINT32)(pBssid[4]) | (ULONG)(pBssid[5] << 8); + + + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, Addr4); + +#ifdef HDR_TRANS_SUPPORT + Addr4 |= 0x18000000; + RTMP_IO_WRITE32(pAd, HT_MAC_BSSID_DW1, Addr4); +#endif /* HDR_TRANS_SUPPORT */ + +} + + +INT AsicSetDevMac(RTMP_ADAPTER *pAd, UCHAR *addr, UCHAR omac_idx) +{ + MAC_DW0_STRUC csr2; + MAC_DW1_STRUC csr3; + + csr2.field.Byte0 = addr[0]; + csr2.field.Byte1 = addr[1]; + csr2.field.Byte2 = addr[2]; + csr2.field.Byte3 = addr[3]; + RTMP_IO_WRITE32(pAd, MAC_ADDR_DW0, csr2.word); + + csr3.word = 0; + csr3.field.Byte4 = addr[4]; + { + csr3.field.Byte5 = addr[5]; + csr3.field.U2MeMask = 0xff; + } + RTMP_IO_WRITE32(pAd, MAC_ADDR_DW1, csr3.word); + + DBGPRINT_RAW(RT_DEBUG_TRACE, ("SetDevMAC=%02x:%02x:%02x:%02x:%02x:%02x\n", + PRINT_MAC(addr))); + +#ifdef HDR_TRANS_SUPPORT + RTMP_IO_WRITE32(pAd, HT_MAC_ADDR_DW0, csr2.word); + csr3.word &= 0xff00ffff; + csr3.word |= 0x00410000; // HW test code + RTMP_IO_WRITE32(pAd, HT_MAC_ADDR_DW1, csr3.word); +#endif /* HDR_TRANS_SUPPORT */ + + return TRUE; +} + +#ifdef CONFIG_AP_SUPPORT +VOID AsicSetMbssMode(RTMP_ADAPTER *pAd, UCHAR NumOfBcns) +{ + UCHAR NumOfMacs; + UINT32 regValue; + + RTMP_IO_READ32(pAd, MAC_BSSID_DW1, ®Value); + regValue &= 0x0000FFFF; + + /* + Note: + 1.The MAC address of Mesh and AP-Client link are different from Main BSSID. + 2.If the Mesh link is included, its MAC address shall follow the last MBSSID's MAC by increasing 1. + 3.If the AP-Client link is included, its MAC address shall follow the Mesh interface MAC by increasing 1. + */ + NumOfMacs = pAd->ApCfg.BssidNum + MAX_MESH_NUM + MAX_APCLI_NUM; + + + /* set Multiple BSSID mode */ + if (NumOfMacs <= 1) + { + pAd->ApCfg.MacMask = ~(1-1); + /*regValue |= 0x0; */ + } + else if (NumOfMacs <= 2) + { + if ((pAd->CurrentAddress[5] % 2 != 0) + ) + DBGPRINT(RT_DEBUG_ERROR, ("The 2-BSSID mode is enabled, the BSSID byte5 MUST be the multiple of 2\n")); + + 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); + } + else if (NumOfMacs <= 16) + { + /* Set MULTI_BSSID_MODE_BIT4 in MAC register 0x1014 */ + regValue |= (1<<22); + pAd->ApCfg.MacMask = ~(16-1); + } + + /* set Multiple BSSID Beacon number */ + if (NumOfBcns > 1) + { + if (NumOfBcns > 8) + regValue |= (((NumOfBcns - 1) >> 3) << 23); + regValue |= (((NumOfBcns - 1) & 0x7) << 18); + } + + /* set as 0/1 bit-21 of MAC_BSSID_DW1(offset: 0x1014) + to disable/enable the new MAC address assignment. */ + if (pAd->chipCap.MBSSIDMode >= MBSSID_MODE1) + { + regValue |= (1 << 21); +#ifdef ENHANCE_NEW_MBSSID_MODE + if (pAd->chipCap.MBSSIDMode == MBSSID_MODE2) + regValue |= (1 << 24); + else if (pAd->chipCap.MBSSIDMode == MBSSID_MODE3) + regValue |= (2 << 24); + else if (pAd->chipCap.MBSSIDMode == MBSSID_MODE4) + regValue |= (3 << 24); + else if (pAd->chipCap.MBSSIDMode == MBSSID_MODE5) + regValue |= (4 << 24); + else if (pAd->chipCap.MBSSIDMode == MBSSID_MODE6) + regValue |= (5 << 24); +#endif /* ENHANCE_NEW_MBSSID_MODE */ + } + + RTMP_IO_WRITE32(pAd, MAC_BSSID_DW1, regValue); + +#ifdef HDR_TRANS_SUPPORT + /* + point WCID MAC table to 0x1800 + This is for debug. + But HDR_TRANS doesn't work if you remove it. + Check after IC formal release. + */ + regValue |= 0x18000000; + RTMP_IO_WRITE32(pAd, HT_MAC_BSSID_DW1, regValue); +#endif /* HDR_TRANS_SUPPORT */ +} +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef APCLI_SUPPORT +#ifdef MAC_REPEATER_SUPPORT +INT AsicSetMacAddrExt(RTMP_ADAPTER *pAd, BOOLEAN enable) +{ + UINT32 mac_val; + + RTMP_IO_READ32(pAd, MAC_ADDR_EXT_EN, &mac_val); + if (enable) + mac_val |= 0x1; + else + mac_val &= (~0x1); + RTMP_IO_WRITE32(pAd, MAC_ADDR_EXT_EN, mac_val); + + return TRUE; +} + +VOID RTMPInsertRepeaterAsicEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR CliIdx, + IN PUCHAR pAddr) +{ + ULONG offset, Addr; + UCHAR tempMAC[MAC_ADDR_LEN]; + + DBGPRINT(RT_DEBUG_WARN, (" %s.\n", __FUNCTION__)); + + COPY_MAC_ADDR(tempMAC, pAddr); + + offset = 0x1480 + (HW_WCID_ENTRY_SIZE * CliIdx); + Addr = tempMAC[0] + (tempMAC[1] << 8) +(tempMAC[2] << 16) +(tempMAC[3] << 24); + RTMP_IO_WRITE32(pAd, offset, Addr); + Addr = tempMAC[4] + (tempMAC[5] << 8); + RTMP_IO_WRITE32(pAd, offset + 4, Addr); + + DBGPRINT(RT_DEBUG_ERROR, ("\n%02x:%02x:%02x:%02x:%02x:%02x-%02x\n", + PRINT_MAC(tempMAC), 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); +} +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* APCLI_SUPPORT */ + + +INT AsicSetRxFilter(RTMP_ADAPTER *pAd) +{ + UINT32 rx_filter_flag; + + /* 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); + + return TRUE; +} + +INT AsicClearRxFilter(RTMP_ADAPTER *pAd) +{ + return TRUE; +} + +#ifdef DOT11_N_SUPPORT +INT AsicSetRDG(RTMP_ADAPTER *pAd, BOOLEAN bEnable) +{ + TX_LINK_CFG_STRUC TxLinkCfg; + UINT32 Data = 0; + + RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); + TxLinkCfg.field.TxRDGEn = (bEnable ? 1 : 0); + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + Data &= 0xFFFFFF00; + if (bEnable) { + Data |= 0x80; + } else { + /* For CWC test, change txop from 0x30 to 0x20 in TxBurst mode*/ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE) + && (pAd->CommonCfg.bEnableTxBurst == TRUE) +#ifdef DOT11_N_SUPPORT + && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE) +#endif /* DOT11_N_SUPPORT */ + ) + Data |= 0x20; + } + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + + + if (bEnable) + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); + else + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); + + return TRUE; +} +#endif /* DOT11_N_SUPPORT */ + + +/* + ======================================================================== + Routine Description: + Set/reset MAC registers according to bPiggyBack parameter + + Arguments: + pAd - Adapter pointer + bPiggyBack - Enable / Disable Piggy-Back + + Return Value: + None + + ======================================================================== +*/ +VOID RTMPSetPiggyBack(RTMP_ADAPTER *pAd, BOOLEAN bPiggyBack) +{ + TX_LINK_CFG_STRUC TxLinkCfg; + + RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); + + TxLinkCfg.field.TxCFAckEn = bPiggyBack; + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); +} + + +static INT AsicSetIntTimerEn(RTMP_ADAPTER *pAd, BOOLEAN enable, UINT32 type, UINT32 timeout) +{ + UINT32 val, mask, time_mask; + + if (type == INT_TIMER_EN_PRE_TBTT) { + mask = 0x1; + timeout = (timeout & 0xffff); + time_mask = 0xffff; + } + else if (type == INT_TIMER_EN_GP_TIMER) { + mask = 0x2; + timeout = (timeout & 0xffff) << 16; + time_mask = (0xffff << 16); + } + else + mask = 0x3; + + RTMP_IO_READ32(pAd, INT_TIMER_EN, &val); + if (enable == FALSE) + val &= (~mask); + else + val |= mask; + RTMP_IO_WRITE32(pAd, INT_TIMER_EN, val); + + if (enable) { + RTMP_IO_READ32(pAd, INT_TIMER_CFG, &val); + val = (val & (~time_mask)) | timeout; + RTMP_IO_WRITE32(pAd, INT_TIMER_CFG, val); + } + + return TRUE; +} + + +INT AsicSetPreTbtt(RTMP_ADAPTER *pAd, BOOLEAN enable) +{ + UINT32 timeout = 0; + + if (enable == TRUE) + timeout = 6 << 4; /* Pre-TBTT is 6ms before TBTT interrupt. 1~10 ms is reasonable. */ + + return AsicSetIntTimerEn(pAd, enable, INT_TIMER_EN_PRE_TBTT, timeout); +} + + +INT AsicSetGPTimer(RTMP_ADAPTER *pAd, BOOLEAN enable, UINT32 timeout) +{ + return AsicSetIntTimerEn(pAd, enable, INT_TIMER_EN_GP_TIMER, timeout); +} + + +INT AsicSetChBusyStat(RTMP_ADAPTER *pAd, BOOLEAN enable) +{ + UINT32 mac_val; + + /* Note: if bit 0 == 0, the function will be disabled */ + if (enable) { + /* + Count EIFS, NAV, RX busy, TX busy as channel busy and + enable Channel statistic timer (bit 0) + */ + mac_val = 0x0000001F; + } + else + mac_val = 0x0; + RTMP_IO_WRITE32(pAd, CH_TIME_CFG, mac_val); + + return TRUE; +} + + +INT AsicGetTsfTime(RTMP_ADAPTER *pAd, UINT32 *high_part, UINT32 *low_part) +{ + RTMP_IO_READ32(pAd, TSF_TIMER_DW1, high_part); + RTMP_IO_READ32(pAd, TSF_TIMER_DW0, low_part); + + return TRUE; +} + + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicDisableSync(RTMP_ADAPTER *pAd) +{ + BCN_TIME_CFG_STRUC csr; + + DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n")); + + pAd->TbttTickCount = 0; + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + csr.field.bBeaconGen = 0; + csr.field.bTBTTEnable = 0; + csr.field.TsfSyncMode = 0; + csr.field.bTsfTicking = 0; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); + +} + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicEnableBssSync(PRTMP_ADAPTER pAd, USHORT BeaconPeriod) +{ + BCN_TIME_CFG_STRUC csr; + + DBGPRINT(RT_DEBUG_TRACE, ("--->%s()\n", __FUNCTION__)); + + 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 = 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 */ + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); +} + +/*CFG_TODO*/ +VOID AsicEnableApBssSync(RTMP_ADAPTER *pAd, USHORT BeaconPeriod) +{ + BCN_TIME_CFG_STRUC csr; + + DBGPRINT(RT_DEBUG_TRACE, ("--->%s()\n", __FUNCTION__)); + + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + + csr.field.BeaconInterval = BeaconPeriod << 4; /* ASIC register in units of 1/16 TU*/ + csr.field.bTsfTicking = 1; + csr.field.TsfSyncMode = 3; /* sync TSF similar as in ADHOC mode?*/ + csr.field.bBeaconGen = 1; /* AP should generate BEACON*/ + csr.field.bTBTTEnable = 1; + + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); +} + + + + +static UINT32 wmm_cr_addr[] = { + EDCA_AC0_CFG, /* WMM_PARAM_AC_0 */ + EDCA_AC1_CFG, /* WMM_PARAM_AC_1 */ + EDCA_AC2_CFG, /* WMM_PARAM_AC_2 */ + EDCA_AC3_CFG, /* WMM_PARAM_AC_3 */ +}; + +static RTMP_REG_PAIR wmm_cr_mask[] = { + {0x000ff, 0}, /* WMM_PARAM_TXOP */ + {0x00f00, 8}, /* WMM_PARAM_AIFSN */ + {0x0f000, 12}, /* WMM_PARAM_CWMIN */ + {0xf0000, 16}, /* WMM_PARAM_CWMAX */ + {0xfffff, 0}, /* WMM_PARAM_ALL */ +}; + + +INT AsicSetWmmParam(RTMP_ADAPTER *pAd, UINT ac, UINT type, UINT val) +{ + UINT32 addr = 0, cr_val, mask = 0, shift; + + if (ac <= WMM_PARAM_AC_3) + addr = wmm_cr_addr[ac]; + + if (type <= WMM_PARAM_ALL) { + mask = wmm_cr_mask[type].Register; + shift = wmm_cr_mask[type].Value; + } + + if (addr && mask) { + RTMP_IO_READ32(pAd, addr, &cr_val); + cr_val &= (~mask); + cr_val |= (val << shift); + RTMP_IO_WRITE32(pAd, addr, cr_val); + return TRUE; + } + + return FALSE; +} + + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSetEdcaParm(RTMP_ADAPTER *pAd, PEDCA_PARM pEdcaParm) +{ + EDCA_AC_CFG_STRUC Ac0Cfg, Ac1Cfg, Ac2Cfg, Ac3Cfg; + AC_TXOP_CSR0_STRUC csr0; + AC_TXOP_CSR1_STRUC csr1; + AIFSN_CSR_STRUC AifsnCsr; + CWMIN_CSR_STRUC CwminCsr; + CWMAX_CSR_STRUC CwmaxCsr; + int i; + + Ac0Cfg.word = 0; + Ac1Cfg.word = 0; + Ac2Cfg.word = 0; + Ac3Cfg.word = 0; + if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE)) + { + DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n")); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED); + for (i=0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + if (IS_ENTRY_CLIENT(&pAd->MacTab.Content[i]) || IS_ENTRY_APCLI(&pAd->MacTab.Content[i])) + CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE); + } + + /*========================================================*/ + /* MAC Register has a copy .*/ + /*========================================================*/ + if( pAd->CommonCfg.bEnableTxBurst ) + { + /* For CWC test, change txop from 0x30 to 0x20 in TxBurst mode*/ + Ac0Cfg.field.AcTxop = 0x20; /* Suggest by John for TxBurst in HT Mode*/ + } + else + Ac0Cfg.field.AcTxop = 0; /* QID_AC_BE*/ + Ac0Cfg.field.Cwmin = pAd->wmm_cw_min; + Ac0Cfg.field.Cwmax = pAd->wmm_cw_max; + Ac0Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Ac0Cfg.word); + + Ac1Cfg.field.AcTxop = 0; /* QID_AC_BK*/ + Ac1Cfg.field.Cwmin = pAd->wmm_cw_min; + Ac1Cfg.field.Cwmax = pAd->wmm_cw_max; + Ac1Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC1_CFG, Ac1Cfg.word); + + if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B)) + { + Ac2Cfg.field.AcTxop = 192; /* AC_VI: 192*32us ~= 6ms*/ + Ac3Cfg.field.AcTxop = 96; /* AC_VO: 96*32us ~= 3ms*/ + } + else + { + Ac2Cfg.field.AcTxop = 94; /* AC_VI: 94*32us ~= 3ms*/ + Ac3Cfg.field.AcTxop = 47; /* AC_VO: 47*32us ~= 1.5ms*/ + } + Ac2Cfg.field.Cwmin = pAd->wmm_cw_min; + Ac2Cfg.field.Cwmax = pAd->wmm_cw_max; + Ac2Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC2_CFG, Ac2Cfg.word); + Ac3Cfg.field.Cwmin = pAd->wmm_cw_min; + Ac3Cfg.field.Cwmax = pAd->wmm_cw_max; + Ac3Cfg.field.Aifsn = 2; + RTMP_IO_WRITE32(pAd, EDCA_AC3_CFG, Ac3Cfg.word); + + /*========================================================*/ + /* DMA Register has a copy too.*/ + /*========================================================*/ + csr0.field.Ac0Txop = 0; /* QID_AC_BE*/ + csr0.field.Ac1Txop = 0; /* QID_AC_BK*/ + RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); + if (WMODE_EQUAL(pAd->CommonCfg.PhyMode, WMODE_B)) + { + csr1.field.Ac2Txop = 192; /* AC_VI: 192*32us ~= 6ms*/ + csr1.field.Ac3Txop = 96; /* AC_VO: 96*32us ~= 3ms*/ + } + else + { + csr1.field.Ac2Txop = 94; /* AC_VI: 94*32us ~= 3ms*/ + csr1.field.Ac3Txop = 47; /* AC_VO: 47*32us ~= 1.5ms*/ + } + RTMP_IO_WRITE32(pAd, WMM_TXOP1_CFG, csr1.word); + + CwminCsr.word = 0; + CwminCsr.field.Cwmin0 = pAd->wmm_cw_min; + CwminCsr.field.Cwmin1 = pAd->wmm_cw_min; + CwminCsr.field.Cwmin2 = pAd->wmm_cw_min; + CwminCsr.field.Cwmin3 = pAd->wmm_cw_min; + RTMP_IO_WRITE32(pAd, WMM_CWMIN_CFG, CwminCsr.word); + + CwmaxCsr.word = 0; + CwmaxCsr.field.Cwmax0 = pAd->wmm_cw_max; + CwmaxCsr.field.Cwmax1 = pAd->wmm_cw_max; + CwmaxCsr.field.Cwmax2 = pAd->wmm_cw_max; + CwmaxCsr.field.Cwmax3 = pAd->wmm_cw_max; + RTMP_IO_WRITE32(pAd, WMM_CWMAX_CFG, CwmaxCsr.word); + + RTMP_IO_WRITE32(pAd, WMM_AIFSN_CFG, 0x00002222); + + NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM)); + + } + else + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED); + /*========================================================*/ + /* MAC Register has a copy.*/ + /*========================================================*/ + + /* Modify Cwmin/Cwmax/Txop on queue[QID_AC_VI], Recommend by Jerry 2005/07/27*/ + /* To degrade our VIDEO Queue's throughput for WiFi WMM S3T07 Issue.*/ + + /*pEdcaParm->Txop[QID_AC_VI] = pEdcaParm->Txop[QID_AC_VI] * 7 / 10; rt2860c need this */ + + Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE]; + Ac0Cfg.field.Cwmin= pEdcaParm->Cwmin[QID_AC_BE]; + Ac0Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BE]; + Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]; /*+1;*/ + + Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK]; + Ac1Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_BK]; /*+2; */ + Ac1Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_BK]; + Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; /*+1;*/ + + + Ac2Cfg.field.AcTxop = (pEdcaParm->Txop[QID_AC_VI] * 6) / 10; + { + 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 */ + + + Ac3Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VO]; + Ac3Cfg.field.Cwmin = pEdcaParm->Cwmin[QID_AC_VO]; + Ac3Cfg.field.Cwmax = pEdcaParm->Cwmax[QID_AC_VO]; + Ac3Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_VO]; + + if (pAd->CommonCfg.bWiFiTest) + { + if (Ac3Cfg.field.AcTxop == 102) + { + Ac0Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BE] ? pEdcaParm->Txop[QID_AC_BE] : 10; + Ac0Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BE]-1; /* AIFSN must >= 1 */ + Ac1Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_BK]; + Ac1Cfg.field.Aifsn = pEdcaParm->Aifsn[QID_AC_BK]; + Ac2Cfg.field.AcTxop = pEdcaParm->Txop[QID_AC_VI]; + } + } + + + 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 */ + 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];*/ + 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_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + AifsnCsr.field.Aifsn3 = Ac3Cfg.field.Aifsn; /*pEdcaParm->Aifsn[QID_AC_VO]*/ +#endif /* CONFIG_AP_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; +} + + + +#ifdef CONFIG_AP_SUPPORT +/* + Wirte non-zero value to AC0 TXOP to boost performace + To pass WMM, AC0 TXOP must be zero. + It is necessary to turn AC0 TX_OP dynamically. +*/ +VOID dynamic_tune_be_tx_op(RTMP_ADAPTER *pAd, ULONG nonBEpackets) +{ + UINT32 RegValue; + AC_TXOP_CSR0_STRUC csr0; + + if (pAd->CommonCfg.bEnableTxBurst +#ifdef DOT11_N_SUPPORT + || pAd->CommonCfg.bRdg + || pAd->CommonCfg.bRalinkBurstMode +#endif /* DOT11_N_SUPPORT */ + ) + { + if ( +#ifdef DOT11_N_SUPPORT + (pAd->WIFItestbed.bGreenField && pAd->MacTab.fAnyStationNonGF == TRUE) || + ((pAd->OneSecondnonBEpackets > nonBEpackets) || pAd->MacTab.fAnyStationMIMOPSDynamic) || +#endif /* DOT11_N_SUPPORT */ + (pAd->MacTab.fAnyTxOPForceDisable)) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)) + { + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &RegValue); + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE)) + { + RegValue = pAd->CommonCfg.RestoreBurstMode; + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE); + } + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE)) + { + TX_LINK_CFG_STRUC TxLinkCfg; + + RTMP_IO_READ32(pAd, TX_LINK_CFG, &TxLinkCfg.word); + TxLinkCfg.field.TxRDGEn = 0; + RTMP_IO_WRITE32(pAd, TX_LINK_CFG, TxLinkCfg.word); + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); + } + /* disable AC0(BE) TX_OP */ + RegValue &= 0xFFFFFF00; /* for WMM test */ + /*if ((RegValue & 0x0000FF00) == 0x00004300) */ + /* RegValue += 0x00001100; */ + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, RegValue); + if (pAd->CommonCfg.APEdcaParm.Txop[QID_AC_VO] != 102) + { + csr0.field.Ac0Txop = 0; /* QID_AC_BE */ + } + else + { + /* for legacy b mode STA */ + csr0.field.Ac0Txop = 10; /* QID_AC_BE */ + } + csr0.field.Ac1Txop = 0; /* QID_AC_BK */ + RTMP_IO_WRITE32(pAd, WMM_TXOP0_CFG, csr0.word); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE); + } + } + else + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE)==0) + { + /* enable AC0(BE) TX_OP */ + UCHAR txop_value_burst = 0x20; /* default txop for Tx-Burst */ + UCHAR txop_value; + +#ifdef LINUX +#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; +} +#endif /* CONFIG_AP_SUPPORT */ + + +INT AsicSetRetryLimit(RTMP_ADAPTER *pAd, UINT32 type, UINT32 limit) +{ + TX_RTY_CFG_STRUC tx_rty_cfg; + + RTMP_IO_READ32(pAd, TX_RTY_CFG, &tx_rty_cfg.word); + if (type == TX_RTY_CFG_RTY_LIMIT_SHORT) + tx_rty_cfg.field.ShortRtyLimit = limit; + else if (type == TX_RTY_CFG_RTY_LIMIT_LONG) + tx_rty_cfg.field.LongRtyLimit = limit; + RTMP_IO_WRITE32(pAd, TX_RTY_CFG, tx_rty_cfg.word); + + return TRUE; +} + + +UINT32 AsicGetRetryLimit(RTMP_ADAPTER *pAd, UINT32 type) +{ + TX_RTY_CFG_STRUC tx_rty_cfg = {.word = 0}; + + RTMP_IO_READ32(pAd, TX_RTY_CFG, &tx_rty_cfg.word); + if (type == TX_RTY_CFG_RTY_LIMIT_SHORT) + return tx_rty_cfg.field.ShortRtyLimit; + else if (type == TX_RTY_CFG_RTY_LIMIT_LONG) + return tx_rty_cfg.field.LongRtyLimit; + + return 0; +} + + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSetSlotTime( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bUseShortSlotTime, + IN UCHAR channel) +{ + ULONG SlotTime; + UINT32 RegValue = 0; + + + 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; + + + + /* For some reasons, always set it to short slot time.*/ + /* ToDo: Should consider capability with 11B*/ + + RTMP_IO_READ32(pAd, BKOFF_SLOT_CFG, &RegValue); + RegValue = RegValue & 0xFFFFFF00; + + RegValue |= SlotTime; + + RTMP_IO_WRITE32(pAd, BKOFF_SLOT_CFG, RegValue); +} + + + + +INT AsicSetMacMaxLen(RTMP_ADAPTER *pAd) +{ + UINT32 mac_val; + +#ifdef RTMP_MAC_PCI + /* TODO: check MACVersion, currently, rbus-based chip use this.*/ + if (pAd->MACVersion == 0x28720200) + { + /*Maximum PSDU length from 16K to 32K bytes */ + RTMP_IO_READ32(pAd, MAX_LEN_CFG, &mac_val); + mac_val &= ~(0x3<<12); + mac_val |= (0x2<<12); + RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, mac_val); + } +#endif /* RTMP_MAC_PCI */ + + if ((IS_RT3883(pAd)) || IS_RT65XX(pAd) || + ((pAd->MACVersion >= RALINK_2880E_VERSION) && + (pAd->MACVersion < RALINK_3070_VERSION))) /* 3*3*/ + { + RTMP_IO_READ32(pAd, MAX_LEN_CFG, &mac_val); + { + mac_val &= 0xFFF; + mac_val |= 0x2000; + } + RTMP_IO_WRITE32(pAd, MAX_LEN_CFG, mac_val); + } + +#ifdef DOT11_N_SUPPORT + + + +#endif /* DOT11_N_SUPPORT */ + + return TRUE; +} + + +#ifdef CONFIG_AP_SUPPORT +VOID RTMPGetTxTscFromAsic(RTMP_ADAPTER *pAd, UCHAR apidx, UCHAR *pTxTsc) +{ + USHORT Wcid; + USHORT offset; + UCHAR IvEiv[8]; + INT i; + + /* Sanity check of apidx */ + if (apidx >= MAX_MBSSID_NUM(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPGetTxTscFromAsic : invalid apidx(%d)\n", apidx)); + return; + } + + /* Initial value */ + NdisZeroMemory(IvEiv, 8); + NdisZeroMemory(pTxTsc, 6); + + /* Get apidx for this BSSID */ + GET_GroupKey_WCID(pAd, Wcid, apidx); + + /* When the group rekey action is triggered, a count-down(3 seconds) is started. + During the count-down, use the initial PN as TSC. + Otherwise, get the IVEIV from ASIC. */ + if (pAd->ApCfg.MBSSID[apidx].RekeyCountDown > 0) + { + /* + In IEEE 802.11-2007 8.3.3.4.3 described : + The PN shall be implemented as a 48-bit monotonically incrementing + non-negative integer, initialized to 1 when the corresponding + temporal key is initialized or refreshed. */ + IvEiv[0] = 1; + } + else + { + UINT32 temp1, temp2; + UINT32 iveiv_tb_base = 0, iveiv_tb_size = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + iveiv_tb_base = RLT_MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = RLT_HW_IVEIV_ENTRY_SIZE; + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + iveiv_tb_base = MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = HW_IVEIV_ENTRY_SIZE; + } +#endif /* RTMP_MAC */ + /* Read IVEIV from Asic */ + offset = iveiv_tb_base + (Wcid * iveiv_tb_size); + + /* Use Read32 to avoid endian problem */ + RTMP_IO_READ32(pAd, offset, &temp1); + RTMP_IO_READ32(pAd, offset+4, &temp2); + for ( i=0; i<4; i++) + { + IvEiv[i] = (UCHAR)(temp1 >> (i*8)); + IvEiv[i+4] = (UCHAR)(temp2 >> (i*8)); + } + } + + /* Record current TxTsc */ + if (pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus == Ndis802_11AESEnable) + { /* AES */ + *pTxTsc = IvEiv[0]; + *(pTxTsc+1) = IvEiv[1]; + *(pTxTsc+2) = IvEiv[4]; + *(pTxTsc+3) = IvEiv[5]; + *(pTxTsc+4) = IvEiv[6]; + *(pTxTsc+5) = IvEiv[7]; + } + else + { /* TKIP */ + *pTxTsc = IvEiv[2]; + *(pTxTsc+1) = IvEiv[0]; + *(pTxTsc+2) = IvEiv[4]; + *(pTxTsc+3) = IvEiv[5]; + *(pTxTsc+4) = IvEiv[6]; + *(pTxTsc+5) = IvEiv[7]; + } + DBGPRINT(RT_DEBUG_TRACE, ("RTMPGetTxTscFromAsic : WCID(%d) TxTsc 0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x \n", + Wcid, *pTxTsc, *(pTxTsc+1), *(pTxTsc+2), *(pTxTsc+3), *(pTxTsc+4), *(pTxTsc+5))); + + +} +#endif /* CONFIG_AP_SUPPORT */ + + +/* + ======================================================================== + Description: + Add Shared key information into ASIC. + Update shared key, TxMic and RxMic to Asic Shared key table + Update its cipherAlg to Asic Shared key Mode. + + Return: + ======================================================================== +*/ +VOID AsicAddSharedKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIndex, + IN UCHAR KeyIdx, + IN PCIPHER_KEY pCipherKey) +{ + ULONG offset; /*, csr0;*/ + SHAREDKEY_MODE_STRUC csr1; + UCHAR org_bssindex; +#ifdef RTMP_MAC_PCI + INT i; +#endif /* RTMP_MAC_PCI */ + + PUCHAR pKey = pCipherKey->Key; + PUCHAR pTxMic = pCipherKey->TxMic; + PUCHAR pRxMic = pCipherKey->RxMic; + UCHAR CipherAlg = pCipherKey->CipherAlg; + + DBGPRINT(RT_DEBUG_TRACE, ("AsicAddSharedKeyEntry BssIndex=%d, KeyIdx=%d\n", BssIndex,KeyIdx)); +/*============================================================================================*/ + + DBGPRINT(RT_DEBUG_TRACE,("AsicAddSharedKeyEntry: %s key #%d\n", CipherName[CipherAlg], BssIndex*4 + KeyIdx)); + DBGPRINT_RAW(RT_DEBUG_TRACE, (" Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pKey[0],pKey[1],pKey[2],pKey[3],pKey[4],pKey[5],pKey[6],pKey[7],pKey[8],pKey[9],pKey[10],pKey[11],pKey[12],pKey[13],pKey[14],pKey[15])); + if (pRxMic) + { + DBGPRINT_RAW(RT_DEBUG_TRACE, (" Rx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pRxMic[0],pRxMic[1],pRxMic[2],pRxMic[3],pRxMic[4],pRxMic[5],pRxMic[6],pRxMic[7])); + } + if (pTxMic) + { + DBGPRINT_RAW(RT_DEBUG_TRACE, (" Tx MIC Key = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + pTxMic[0],pTxMic[1],pTxMic[2],pTxMic[3],pTxMic[4],pTxMic[5],pTxMic[6],pTxMic[7])); + } +/*============================================================================================*/ + + org_bssindex = BssIndex; + if (BssIndex >= 8) + BssIndex -= 8; + + { + /* fill key material - key + TX MIC + RX MIC*/ + UINT32 share_key_base = 0, share_key_size = 0; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + if (org_bssindex >= 8) + share_key_base = RLT_SHARED_KEY_TABLE_BASE_EXT; + else + share_key_base = RLT_SHARED_KEY_TABLE_BASE; + share_key_size = RLT_HW_KEY_ENTRY_SIZE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + if (org_bssindex >= 8) + share_key_base = SHARED_KEY_TABLE_BASE_EXT; + else + share_key_base = SHARED_KEY_TABLE_BASE; + share_key_size = HW_KEY_ENTRY_SIZE; + } +#endif /* RTMP_MAC */ + + offset = share_key_base + (4*BssIndex + KeyIdx)*share_key_size; +#ifdef RTMP_MAC_PCI + { + for (i=0; ichipCap.hif_type == HIF_RLT) { + if (org_bssindex >= 8) + share_key_mode_base = RLT_SHARED_KEY_MODE_BASE_EXT; + else + share_key_mode_base= RLT_SHARED_KEY_MODE_BASE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + if (org_bssindex >= 8) + share_key_mode_base = SHARED_KEY_MODE_BASE_EXT; + else + share_key_mode_base = SHARED_KEY_MODE_BASE; + } +#endif /* RTMP_MAC */ + + /* Update cipher algorithm. WSTA always use BSS0*/ + RTMP_IO_READ32(pAd, share_key_mode_base + 4 * (BssIndex/2), &csr1.word); + DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word)); + if ((BssIndex%2) == 0) + { + if (KeyIdx == 0) + csr1.field.Bss0Key0CipherAlg = CipherAlg; + else if (KeyIdx == 1) + csr1.field.Bss0Key1CipherAlg = CipherAlg; + else if (KeyIdx == 2) + csr1.field.Bss0Key2CipherAlg = CipherAlg; + else + csr1.field.Bss0Key3CipherAlg = CipherAlg; + } + else + { + if (KeyIdx == 0) + csr1.field.Bss1Key0CipherAlg = CipherAlg; + else if (KeyIdx == 1) + csr1.field.Bss1Key1CipherAlg = CipherAlg; + else if (KeyIdx == 2) + csr1.field.Bss1Key2CipherAlg = CipherAlg; + else + csr1.field.Bss1Key3CipherAlg = CipherAlg; + } + DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word)); + RTMP_IO_WRITE32(pAd, share_key_mode_base+ 4 * (BssIndex/2), csr1.word); + } +} + + +/* IRQL = DISPATCH_LEVEL*/ +VOID AsicRemoveSharedKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIndex, + IN UCHAR KeyIdx) +{ + /*ULONG SecCsr0;*/ + SHAREDKEY_MODE_STRUC csr1; + + DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx)); + + { + UINT32 share_key_mode_base = 0; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + share_key_mode_base= RLT_SHARED_KEY_MODE_BASE; +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + share_key_mode_base = SHARED_KEY_MODE_BASE; +#endif /* RTMP_MAC */ + + RTMP_IO_READ32(pAd, share_key_mode_base+4*(BssIndex/2), &csr1.word); + if ((BssIndex%2) == 0) + { + if (KeyIdx == 0) + csr1.field.Bss0Key0CipherAlg = 0; + else if (KeyIdx == 1) + csr1.field.Bss0Key1CipherAlg = 0; + else if (KeyIdx == 2) + csr1.field.Bss0Key2CipherAlg = 0; + else + csr1.field.Bss0Key3CipherAlg = 0; + } + else + { + if (KeyIdx == 0) + csr1.field.Bss1Key0CipherAlg = 0; + else if (KeyIdx == 1) + csr1.field.Bss1Key1CipherAlg = 0; + else if (KeyIdx == 2) + csr1.field.Bss1Key2CipherAlg = 0; + else + csr1.field.Bss1Key3CipherAlg = 0; + } + DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word)); + RTMP_IO_WRITE32(pAd, share_key_mode_base+4*(BssIndex/2), csr1.word); + } + ASSERT(BssIndex < 4); + ASSERT(KeyIdx < 4); + +} + + +VOID AsicUpdateWCIDIVEIV( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN ULONG uIV, + IN ULONG uEIV) +{ + ULONG offset; + UINT32 iveiv_tb_base = 0, iveiv_tb_size = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + iveiv_tb_base = RLT_MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = RLT_HW_IVEIV_ENTRY_SIZE; + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + iveiv_tb_base = MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = HW_IVEIV_ENTRY_SIZE; + } +#endif /* RTMP_MAC */ + + offset = iveiv_tb_base + (WCID * iveiv_tb_size); + + RTMP_IO_WRITE32(pAd, offset, uIV); + RTMP_IO_WRITE32(pAd, offset + 4, uEIV); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: wcid(%d) 0x%08lx, 0x%08lx \n", + __FUNCTION__, WCID, uIV, uEIV)); +} + + +#ifdef MCS_LUT_SUPPORT +VOID asic_mcs_lut_update(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ +#ifdef PEER_DELBA_TX_ADAPT + if (pEntry->bPeerDelBaTxAdaptEn) + { + DBGPRINT(RT_DEBUG_WARN, + ("%s(): Rate not update due to bPeerDelBaTxAdaptEn is 0x%x.\n", + __FUNCTION__, pEntry->bPeerDelBaTxAdaptEn)); + return; + } +#endif /* PEER_DELBA_TX_ADAPT */ + + if(RTMP_TEST_MORE_FLAG(pAd, fASIC_CAP_MCS_LUT) && (pEntry->wcid < 128)) + { + UINT32 wcid_offset; + HW_RATE_CTRL_STRUCT rate_ctrl; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + rate_ctrl.RATE_CTRL_N.PHYMODE = pEntry->HTPhyMode.field.MODE; + rate_ctrl.RATE_CTRL_N.STBC = pEntry->HTPhyMode.field.STBC; + rate_ctrl.RATE_CTRL_N.ShortGI = pEntry->HTPhyMode.field.ShortGI; + rate_ctrl.RATE_CTRL_N.BW = pEntry->HTPhyMode.field.BW; + + if (pAd->chipCap.phy_caps & fPHY_CAP_LDPC) + rate_ctrl.RATE_CTRL_N.ldpc = pEntry->HTPhyMode.field.ldpc; + + rate_ctrl.RATE_CTRL_N.MCS = pEntry->HTPhyMode.field.MCS; + } + else +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + rate_ctrl.RATE_CTRL_O.PHYMODE = pEntry->HTPhyMode.field.MODE; + rate_ctrl.RATE_CTRL_O.STBC = pEntry->HTPhyMode.field.STBC; + rate_ctrl.RATE_CTRL_O.ShortGI = pEntry->HTPhyMode.field.ShortGI; + rate_ctrl.RATE_CTRL_O.BW = pEntry->HTPhyMode.field.BW; + rate_ctrl.RATE_CTRL_O.MCS = pEntry->HTPhyMode.field.MCS; + } + else +#endif /* RTMP_MAC */ + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): HIF Type Error !!!\n", __FUNCTION__)); + return; + } + + wcid_offset = MAC_MCS_LUT_BASE + (pEntry->wcid * 8); + + RTMP_IO_WRITE32(pAd, wcid_offset, rate_ctrl.word); + RTMP_IO_WRITE32(pAd, wcid_offset + 4, 0x00); + + DBGPRINT(RT_DEBUG_INFO, ("%s():MCS_LUT update, write to MAC=0x%08x, Value=0x%04x, WCID=%d\n", + __FUNCTION__, wcid_offset, pEntry->HTPhyMode.word, pEntry->wcid)); + + DBGPRINT_RAW(RT_DEBUG_INFO, ("\tWcid=%d, APMlmeSetTxRate - CurrTxRateIdx=%d, MCS=%d, STBC=%d, ShortGI=%d, Mode=%d, BW=%d \n" + "\ ETxBf=%d, ITxBf=%d\n\n", + pEntry->wcid, + pEntry->CurrTxRateIndex, + pEntry->HTPhyMode.field.MCS, + pEntry->HTPhyMode.field.STBC, + pEntry->HTPhyMode.field.ShortGI, + pEntry->HTPhyMode.field.MODE, + pEntry->HTPhyMode.field.BW, + pEntry->HTPhyMode.field.eTxBF, + pEntry->HTPhyMode.field.iTxBF)); + } +} +#endif /* MCS_LUT_SUPPORT */ + + +VOID AsicUpdateBASession(RTMP_ADAPTER *pAd, UCHAR wcid, UCHAR tid, UCHAR basize, BOOLEAN isAdd, INT ses_type) +{ + UINT32 Value = 0, Offset; + + if (ses_type == BA_SESSION_RECP) { + Offset = MAC_WCID_BASE + wcid * HW_WCID_ENTRY_SIZE + 4; + RTMP_IO_READ32(pAd, Offset, &Value); + if (isAdd) + Value |= (0x10000 << tid); + else + Value &= (~(0x10000 << tid)); + RTMP_IO_WRITE32(pAd, Offset, Value); + } +} + + +VOID AsicUpdateRxWCIDTable(RTMP_ADAPTER *pAd, USHORT WCID, UCHAR *pAddr) +{ + ULONG offset; + ULONG Addr; + + offset = MAC_WCID_BASE + (WCID * HW_WCID_ENTRY_SIZE); + Addr = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24); + RTMP_IO_WRITE32(pAd, offset, Addr); + Addr = pAddr[4] + (pAddr[5] << 8); + RTMP_IO_WRITE32(pAd, offset + 4, Addr); +} + + +/* + ======================================================================== + Description: + Add Client security information into ASIC WCID table and IVEIV table. + Return: + + Note : + The key table selection rule : + 1. Wds-links and Mesh-links always use Pair-wise key table. + 2. When the CipherAlg is TKIP, AES, SMS4 or the dynamic WEP is enabled, + it needs to set key into Pair-wise Key Table. + 3. The pair-wise key security mode is set NONE, it means as no security. + 4. In STA Adhoc mode, it always use shared key table. + 5. Otherwise, use shared key table + + ======================================================================== +*/ +VOID AsicUpdateWcidAttributeEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIdx, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN UINT8 Wcid, + IN UINT8 KeyTabFlag) +{ + WCID_ATTRIBUTE_STRUC WCIDAttri; + USHORT offset; + UINT32 wcid_attr_base = 0, wcid_attr_size = 0; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + wcid_attr_base = RLT_MAC_WCID_ATTRIBUTE_BASE; + wcid_attr_size = RLT_HW_WCID_ATTRI_SIZE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + wcid_attr_base = MAC_WCID_ATTRIBUTE_BASE; + wcid_attr_size = HW_WCID_ATTRI_SIZE; + } +#endif /* RTMP_MAC */ + + /* Initialize the content of WCID Attribue */ + WCIDAttri.word = 0; + + /* The limitation of HW WCID table */ + if (Wcid > 254) + { + DBGPRINT(RT_DEBUG_WARN, ("%s:Invalid wcid(%d)\n", __FUNCTION__, Wcid)); + return; + } + + /* Update the pairwise key security mode. + Use bit10 and bit3~1 to indicate the pairwise cipher mode */ + WCIDAttri.field.PairKeyModeExt = ((CipherAlg & 0x08) >> 3); + WCIDAttri.field.PairKeyMode = (CipherAlg & 0x07); + + /* Update the MBSS index. + Use bit11 and bit6~4 to indicate the BSS index */ + WCIDAttri.field.BSSIdxExt = ((BssIdx & 0x08) >> 3); + WCIDAttri.field.BSSIdx = (BssIdx & 0x07); + +#ifdef WAPI_SUPPORT + /* Update WAPI related information */ + if (CipherAlg == CIPHER_SMS4) + { + if (KeyTabFlag == SHAREDKEYTABLE) + WCIDAttri.field.WAPI_MCBC = 1; + WCIDAttri.field.WAPIKeyIdx = ((KeyIdx == 0) ? 0 : 1); + } +#endif /* WAPI_SUPPORT */ + + /* Assign Key Table selection */ + WCIDAttri.field.KeyTab = KeyTabFlag; + + /* Update related information to ASIC */ + offset = wcid_attr_base + (Wcid * wcid_attr_size); + RTMP_IO_WRITE32(pAd, offset, WCIDAttri.word); + + DBGPRINT(RT_DEBUG_TRACE, ("%s:WCID #%d, KeyIdx #%d, WCIDAttri=0x%x, Alg=%s\n", + __FUNCTION__, Wcid, KeyIdx, WCIDAttri.word, CipherName[CipherAlg])); +} + + +/* + ========================================================================== + Description: + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicDelWcidTab(RTMP_ADAPTER *pAd, UCHAR wcid_idx) +{ + UINT32 offset; + UCHAR cnt, cnt_s, cnt_e; +#ifdef MCS_LUT_SUPPORT + UINT32 mcs_tb_offset = 0; +#endif /* MCS_LUT_SUPPORT */ + + + DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>wcid_idx = 0x%x\n",wcid_idx)); + if (wcid_idx == WCID_ALL) { + cnt_s = 0; + cnt_e = (WCID_ALL - 1); + } else { +#ifdef MCS_LUT_SUPPORT + if (RTMP_TEST_MORE_FLAG(pAd, fASIC_CAP_MCS_LUT)) + mcs_tb_offset = 0x400; +#endif /* MCS_LUT_SUPPORT */ + cnt_s = cnt_e = wcid_idx; + } + + for (cnt = cnt_s; cnt_s <= cnt_e; cnt_s++) + { + offset = MAC_WCID_BASE + cnt * HW_WCID_ENTRY_SIZE; + RTMP_IO_WRITE32(pAd, offset, 0x0); + RTMP_IO_WRITE32(pAd, offset + 4, 0x0); +#ifdef MCS_LUT_SUPPORT + if (mcs_tb_offset) { + offset += mcs_tb_offset; + RTMP_IO_WRITE32(pAd, offset, 0x0); + RTMP_IO_WRITE32(pAd, offset + 4, 0x0); + } +#endif /* MCS_LUT_SUPPORT */ + } +} + + +/* + ======================================================================== + Description: + Add Pair-wise key material into ASIC. + Update pairwise key, TxMic and RxMic to Asic Pair-wise key table + + Return: + ======================================================================== +*/ +VOID AsicAddPairwiseKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR WCID, + IN PCIPHER_KEY pCipherKey) +{ + INT i; + ULONG offset; + UINT32 pairwise_key_base = 0, pairwise_key_len = 0; + UCHAR *pKey = pCipherKey->Key; + UCHAR *pTxMic = pCipherKey->TxMic; + UCHAR *pRxMic = pCipherKey->RxMic; + UCHAR CipherAlg = pCipherKey->CipherAlg; +#ifdef RTMP_MAC +#ifdef RTMP_MAC_PCI +#endif /* RTMP_MAC_PCI */ +#endif /* RTMP_MAC */ + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + pairwise_key_base = RLT_PAIRWISE_KEY_TABLE_BASE; + pairwise_key_len = RLT_HW_KEY_ENTRY_SIZE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + pairwise_key_base = PAIRWISE_KEY_TABLE_BASE; + pairwise_key_len = HW_KEY_ENTRY_SIZE; +#ifdef RTMP_MAC_PCI +#endif /* RTMP_MAC_PCI */ + } +#endif /* RTMP_MAC */ + + /* EKEY */ + offset = pairwise_key_base + (WCID * pairwise_key_len); +#ifdef RTMP_MAC_PCI + for (i=0; ichipOps.sendCommandToMcu) + return pAd->chipOps.sendCommandToMcu(pAd, Command, Token, Arg0, Arg1, in_atomic); + else + return FALSE; +} + + +BOOLEAN AsicSendCmdToMcuAndWait( + IN RTMP_ADAPTER *pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN in_atomic) +{ + BOOLEAN cmd_done = TRUE; + + AsicSendCommandToMcu(pAd, Command, Token, Arg0, Arg1, in_atomic); + +#ifdef RTMP_MAC_PCI + cmd_done = AsicCheckCommanOk(pAd, Token); +#endif /* RTMP_MAC_PCI */ + + return cmd_done; +} + + +BOOLEAN AsicSendCommandToMcuBBP( + IN PRTMP_ADAPTER pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN FlgIsNeedLocked) +{ + + + 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(RTMP_ADAPTER *pAd, UCHAR Channel) +{ + if (pAd->chipOps.AsicRfTurnOff) + { + pAd->chipOps.AsicRfTurnOff(pAd); + } + else + { +#if defined(RT28xx) || defined(RT2880) || defined(RT2883) + /* RF R2 bit 18 = 0*/ + UINT32 R1 = 0, R2 = 0, R3 = 0; + UCHAR index; + RTMP_RF_REGS *RFRegTable; + + RFRegTable = RF2850RegTable; +#endif /* defined(RT28xx) || defined(RT2880) || defined(RT2883) */ + + switch (pAd->RfIcType) + { +#if defined(RT28xx) || defined(RT2880) || defined(RT2883) +#if defined(RT28xx) || defined(RT2880) + case RFIC_2820: + case RFIC_2850: + case RFIC_2720: + case RFIC_2750: +#endif /* defined(RT28xx) || defined(RT2880) */ + for (index = 0; index < NUM_OF_2850_CHNL; index++) + { + if (Channel == RFRegTable[index].Channel) + { + R1 = RFRegTable[index].R1 & 0xffffdfff; + R2 = RFRegTable[index].R2 & 0xfffbffff; + R3 = RFRegTable[index].R3 & 0xfff3ffff; + + RTMP_RF_IO_WRITE32(pAd, R1); + RTMP_RF_IO_WRITE32(pAd, R2); + + /* Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0. */ + /* Set RF R2 bit18=0, R3 bit[18:19]=0*/ + /*if (pAd->StaCfg.bRadio == FALSE)*/ + if (1) + { + RTMP_RF_IO_WRITE32(pAd, R3); + + DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n", + Channel, pAd->RfIcType, R2, R3)); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n", + Channel, pAd->RfIcType, R2)); + break; + } + } + break; +#endif /* defined(RT28xx) || defined(RT2880) || defined(RT2883) */ + default: + DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d : Unkonwn RFIC=%d\n", + Channel, pAd->RfIcType)); + break; + } + } +} + + +#ifdef WAPI_SUPPORT +VOID AsicUpdateWAPIPN( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN ULONG pn_low, + IN ULONG pn_high) +{ + if (IS_HW_WAPI_SUPPORT(pAd)) + { + UINT32 offset; + UINT32 wapi_pn_base = 0, wapi_pn_size = 0; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + wapi_pn_base = RLT_WAPI_PN_TABLE_BASE; + wapi_pn_size = RLT_WAPI_PN_ENTRY_SIZE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + wapi_pn_base = WAPI_PN_TABLE_BASE; + wapi_pn_size = WAPI_PN_ENTRY_SIZE; + } +#endif /* RTMP_MAC */ + + offset = wapi_pn_base + (WCID * wapi_pn_size); + + RTMP_IO_WRITE32(pAd, offset, pn_low); + RTMP_IO_WRITE32(pAd, offset + 4, pn_high); + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s : Not support HW_WAPI_PN_TABLE\n", + __FUNCTION__)); + } + +} +#endif /* WAPI_SUPPORT */ + + + + + +#ifdef STREAM_MODE_SUPPORT +// StreamModeRegVal - return MAC reg value for StreamMode setting +UINT32 StreamModeRegVal( + IN RTMP_ADAPTER *pAd) +{ + UINT32 streamWord; + + switch (pAd->CommonCfg.StreamMode) + { + case 1: + streamWord = 0x030000; + break; + case 2: + streamWord = 0x0c0000; + break; + case 3: + streamWord = 0x0f0000; + break; + default: + streamWord = 0x0; + break; + } + + return streamWord; +} + + +/* + ======================================================================== + Description: + configure the stream mode of specific MAC or all MAC and set to ASIC. + + Prameters: + pAd --- + pMacAddr --- + bClear --- disable the stream mode for specific macAddr when + (pMacAddr!=NULL) + + Return: + ======================================================================== +*/ +VOID AsicSetStreamMode( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pMacAddr, + IN INT chainIdx, + IN BOOLEAN bEnabled) +{ + UINT32 streamWord; + UINT32 regAddr, regVal; + + + if (!pAd->chipCap.FlgHwStreamMode) + return; + + streamWord = StreamModeRegVal(pAd); + if (!bEnabled) + streamWord = 0; + + regAddr = TX_CHAIN_ADDR0_L + chainIdx * 8; + RTMP_IO_WRITE32(pAd, regAddr, + (UINT32)(pMacAddr[0]) | + (UINT32)(pMacAddr[1] << 8) | + (UINT32)(pMacAddr[2] << 16) | + (UINT32)(pMacAddr[3] << 24)); + + RTMP_IO_READ32(pAd, regAddr + 4, ®Val); + regVal &= (~0x000f0000); + RTMP_IO_WRITE32(pAd, regAddr + 4, + (regVal | streamWord) | + (UINT32)(pMacAddr[4]) | + (UINT32)(pMacAddr[5] << 8)); + +} + + +VOID RtmpStreamModeInit(RTMP_ADAPTER *pAd) +{ + int chainIdx; + UCHAR *pMacAddr; + + if (pAd->chipCap.FlgHwStreamMode == FALSE) + return; + + for (chainIdx = 0; chainIdx < STREAM_MODE_STA_NUM; chainIdx++) + { + pMacAddr = &pAd->CommonCfg.StreamModeMac[chainIdx][0]; + AsicSetStreamMode(pAd, pMacAddr, chainIdx, TRUE); + } +} +#endif // STREAM_MODE_SUPPORT // + + +VOID AsicSetTxPreamble(RTMP_ADAPTER *pAd, USHORT TxPreamble) +{ + AUTO_RSP_CFG_STRUC csr4; + + RTMP_IO_READ32(pAd, AUTO_RSP_CFG, &csr4.word); + if (TxPreamble == Rt802_11PreambleLong) + csr4.field.AutoResponderPreamble = 0; + else + csr4.field.AutoResponderPreamble = 1; + RTMP_IO_WRITE32(pAd, AUTO_RSP_CFG, csr4.word); +} + + +#ifdef DOT11_N_SUPPORT +INT AsicSetRalinkBurstMode(RTMP_ADAPTER *pAd, BOOLEAN enable) +{ + UINT32 Data = 0; + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + if (enable) + { + pAd->CommonCfg.RestoreBurstMode = Data; + Data &= 0xFFF00000; + Data |= 0x86380; + } else { + Data = pAd->CommonCfg.RestoreBurstMode; + Data &= 0xFFFFFF00; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE) +#ifdef DOT11_N_SUPPORT + && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE) +#endif // DOT11_N_SUPPORT // + ) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE)) + Data |= 0x80; + else if (pAd->CommonCfg.bEnableTxBurst) + Data |= 0x20; + } + } + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + + if (enable) + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE); + else + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE); + + return TRUE; +} +#endif // DOT11_N_SUPPORT // + + + + +#ifdef MICROWAVE_OVEN_SUPPORT +VOID AsicMeasureFalseCCA( + IN PRTMP_ADAPTER pAd +) +{ + if (pAd->chipOps.AsicMeasureFalseCCA) + pAd->chipOps.AsicMeasureFalseCCA(pAd); +} + +VOID AsicMitigateMicrowave( + IN PRTMP_ADAPTER pAd +) +{ + if (pAd->chipOps.AsicMitigateMicrowave) + pAd->chipOps.AsicMitigateMicrowave(pAd); +} +#endif /* MICROWAVE_OVEN_SUPPORT */ + + +INT AsicWaitMacTxRxIdle(RTMP_ADAPTER *pAd) +{ + UINT32 Index = 0, val; + + do + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return FALSE; + + RTMP_IO_READ32(pAd, MAC_STATUS_CFG, &val); + if ((val & 0x03) == 0) /* if BB.RF is stable*/ + return TRUE; + + DBGPRINT(RT_DEBUG_TRACE, ("Check if MAC_STATUS_CFG is busy(=%x)\n", val)); + RtmpusecDelay(1000); + } while (Index++ < 100); + + return FALSE; +} + + +INT AsicSetMacTxRx(RTMP_ADAPTER *pAd, INT txrx, BOOLEAN enable) +{ + UINT32 mac_val, val_field; + + switch (txrx) + { + case ASIC_MAC_TX: + val_field = MAC_SYS_CTRL_TXEN; + break; + case ASIC_MAC_RX: + val_field = MAC_SYS_CTRL_RXEN; + break; + case ASIC_MAC_TXRX: + val_field = MAC_SYS_CTRL_RXEN | MAC_SYS_CTRL_TXEN; + break; + default: + val_field = 0; + break; + } + + RTMP_IO_READ32(pAd, MAC_SYS_CTRL, &mac_val); + if (enable) + mac_val |= val_field; + else + mac_val &= (~val_field); + RTMP_IO_WRITE32(pAd, MAC_SYS_CTRL, mac_val); + + return TRUE; +} + + +INT AsicSetWPDMA(RTMP_ADAPTER *pAd, BOOLEAN enable) +{ +#ifdef RTMP_MAC_PCI + WPDMA_GLO_CFG_STRUC GloCfg; + + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG , &GloCfg.word); + if (enable == TRUE) + { + GloCfg.field.EnableTxDMA = 1; + GloCfg.field.EnableRxDMA = 1; + GloCfg.field.EnTXWriteBackDDONE = 1; + GloCfg.field.WPDMABurstSIZE = pAd->chipCap.WPDMABurstSIZE; + } else { + GloCfg.field.EnableRxDMA = 0; + GloCfg.field.EnableTxDMA = 0; + GloCfg.field.EnTXWriteBackDDONE = 0; + } + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, GloCfg.word); +#endif /* RTMP_MAC_PCI */ + return TRUE; +} + + +BOOLEAN AsicWaitPDMAIdle(struct _RTMP_ADAPTER *pAd, INT round, INT wait_us) +{ +#ifdef RTMP_MAC_PCI + INT i = 0; + WPDMA_GLO_CFG_STRUC GloCfg; + + + do { + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) { + DBGPRINT(RT_DEBUG_TRACE, ("==> DMAIdle, GloCfg=0x%x\n", GloCfg.word)); + return TRUE; + } + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return FALSE; + RtmpusecDelay(wait_us); + }while ((i++) < round); + + DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy, GloCfg=0x%x\n", GloCfg.word)); +#endif /* RTMP_MAC_PCI */ + return FALSE; +} + + +INT AsicSetMacWD(RTMP_ADAPTER *pAd) +{ + int count = 0; + BOOLEAN MAC_ready = FALSE; + UINT32 MacCsr12 = 0; + + /* Disable MAC*/ + AsicSetMacTxRx(pAd, ASIC_MAC_TXRX, FALSE); + + /* polling MAC status*/ + while (count < 10) + { + RtmpusecDelay(1000); + 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")); + } + + { + AsicSetMacTxRx(pAd, ASIC_MAC_TXRX, TRUE); + } + + return TRUE; +} + + +INT rtmp_asic_hif_init(RTMP_ADAPTER *pAd) +{ + + return TRUE; +} + + +INT rtmp_asic_top_init(RTMP_ADAPTER *pAd) +{ + UINT32 mac_val; + +#ifdef RLT_MAC + + if (IS_MT76x0(pAd) || IS_MT76x2(pAd) || IS_MT7601(pAd)) { + if (pAd->WlanFunCtrl.field.WLAN_EN == 0) + rlt_wlan_chip_onoff(pAd, TRUE, FALSE); + } +#endif /* RLT_MAC */ + + + + /* Make sure MAC gets ready.*/ + if (WaitForAsicReady(pAd) != TRUE) + return FALSE; + +#ifdef RTMP_MAC_PCI + + mac_val = 0x2; /* To fix driver disable/enable hang issue when radio off*/ + RTMP_IO_WRITE32(pAd, PWR_PIN_CFG, mac_val); +#endif /* RTMP_MAC_PCI */ + + return TRUE; +} + + +INT StopDmaRx(RTMP_ADAPTER *pAd, UCHAR Level) +{ + PNDIS_PACKET pRxPacket; + RX_BLK RxBlk, *pRxBlk; + UINT32 RxPending = 0, MacReg = 0, MTxCycle = 0; + BOOLEAN bReschedule = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__)); + + /* + process whole rx ring + */ + while (1) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return 0; + pRxBlk = &RxBlk; + pRxPacket = GetPacketFromRxRing(pAd, pRxBlk, &bReschedule, &RxPending, 0); + if ((RxPending == 0) && (bReschedule == FALSE)) + break; + else + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + } + + /* + Check DMA Rx idle + */ + for (MTxCycle = 0; MTxCycle < 2000; MTxCycle++) + { +#ifdef RTMP_MAC_PCI + + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &MacReg); + if (MacReg & 0x8) + { + RtmpusecDelay(50); + } + else + break; + +#endif + + + if (MacReg == 0xFFFFFFFF) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); + return 0; + } + } + + if (MTxCycle >= 2000) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:RX DMA busy!! DMA_CFG = 0x%08x\n", __FUNCTION__, MacReg)); + } + + if (Level == RTMP_HALT) + { + /* Disable DMA RX */ +#ifdef RTMP_MAC_PCI + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &MacReg); + MacReg &= ~(0x4); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, MacReg); +#endif + } + + DBGPRINT(RT_DEBUG_TRACE, ("<==== %s\n", __FUNCTION__)); + + return 0; +} + + +INT StopDmaTx(RTMP_ADAPTER *pAd, UCHAR Level) +{ + UINT32 MacReg = 0, MTxCycle = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__)); + + for (MTxCycle = 0; MTxCycle < 2000; MTxCycle++) + { +#ifdef RTMP_MAC_PCI + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &MacReg); + if ((MacReg & 0x2) == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("==> DMA Tx Idle, MacReg=0x%x\n", MacReg)); + break; + } +#endif + + + if (MacReg == 0xFFFFFFFF) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); + return 0; + } + } + + if (MTxCycle >= 2000) + { + DBGPRINT(RT_DEBUG_ERROR, ("TX DMA busy!! DMA_CFG(%x)\n", MacReg)); + } + + if (Level == RTMP_HALT) + { +#ifdef RTMP_MAC_PCI + RTMP_IO_READ32(pAd, WPDMA_GLO_CFG, &MacReg); + MacReg &= ~(0x00000001); + RTMP_IO_WRITE32(pAd, WPDMA_GLO_CFG, MacReg); +#endif + + } + + DBGPRINT(RT_DEBUG_TRACE, ("<==== %s\n", __FUNCTION__)); + + return 0; +} + + +#ifdef DOT11_N_SUPPORT +#define MAX_AGG_CNT 8 +INT AsicReadAggCnt(RTMP_ADAPTER *pAd, ULONG *aggCnt, int cnt_len) +{ + UINT32 reg_addr; + TX_AGG_CNT_STRUC reg_val; + int i, cnt, seg; + static USHORT aggReg[] = { + TX_AGG_CNT, TX_AGG_CNT3, +#if MAX_AGG_CNT > 8 + TX_AGG_CNT4, TX_AGG_CNT7, +#endif +#if MAX_AGG_CNT > 16 + TX_AGG_CNT8, TX_AGG_CNT15, +#endif +#if MAX_AGG_CNT > 32 + TX_AGG_CNT16, TX_AGG_CNT23, +#endif + }; + + + NdisZeroMemory(aggCnt, cnt_len * sizeof(ULONG)); + seg = (sizeof(aggReg) /sizeof(USHORT)); + + cnt = 0; + for (i = 0; i < seg; i += 2) + { + for (reg_addr = aggReg[i] ; reg_addr <= aggReg[i+1] ; reg_addr += 4) + { + RTMP_IO_READ32(pAd, reg_addr, ®_val.word); + if (cnt < (cnt_len -1)) { + aggCnt[cnt] = reg_val.field.AggCnt_x; + aggCnt[cnt+1] = reg_val.field.AggCnt_y; + DBGPRINT(RT_DEBUG_TRACE, ("%s():Get AggSize at Reg(0x%x) with val(0x%08x) [AGG_%d=>%ld, AGG_%d=>%ld]\n", + __FUNCTION__, reg_addr, reg_val.word, cnt, aggCnt[cnt], cnt+1, aggCnt[cnt+1])); + cnt += 2; + } else { + DBGPRINT(RT_DEBUG_TRACE, ("%s():Get AggSize at Reg(0x%x) failed, no enough buffer(cnt_len=%d, cnt=%d)\n", + __FUNCTION__, reg_addr, cnt_len, cnt)); + } + } + } + + return TRUE; +} + +#endif /* DOT11_N_SUPPORT */ + + +// TODO: shiang-usw, revise this function!! +INT AsicRltSetTxStream(RTMP_ADAPTER *pAd, UCHAR opmode, BOOLEAN up) +{ + /* + Select DAC according to HT or Legacy, write to BBP R1(bit4:3) + In HT mode and two stream mode, both DACs are selected. + In legacy mode or one stream mode, DAC-0 is selected. + */ +#ifdef CONFIG_AP_SUPPORT + if (opmode == OPMODE_AP) + { + +#ifdef DOT11_N_SUPPORT + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && (pAd->Antenna.field.TxPath == 2)) + bbp_set_txdac(pAd, 2); + else +#endif /* DOT11_N_SUPPORT */ + bbp_set_txdac(pAd, 0); + } +#endif /* CONFIG_AP_SUPPORT */ + + + return TRUE; +} + + +INT AsicSetRxStream(RTMP_ADAPTER *pAd, UINT32 rx_path) +{ + /* Receiver Antenna selection */ + bbp_set_rxpath(pAd, rx_path); + + return TRUE; +} + + +INT AsicSetBW(RTMP_ADAPTER *pAd, INT bw) +{ + return bbp_set_bw(pAd, bw); +} + + +INT AsicSetChannel(RTMP_ADAPTER *pAd, UCHAR ch, UINT8 bw, UINT8 ext_ch, BOOLEAN bScan) +{ + bbp_set_bw(pAd, bw); + + /* Tx/RX : control channel setting */ + bbp_set_ctrlch(pAd, ext_ch); + rtmp_mac_set_ctrlch(pAd, ext_ch); + + /* Let BBP register at 20MHz to do scan */ + AsicSwitchChannel(pAd, ch, bScan); + AsicLockChannel(pAd, ch); + +#ifdef RT28xx + RT28xx_ch_tunning(pAd, bw); +#endif /* RT28xx */ + + return 0; +} + + +#ifdef MAC_APCLI_SUPPORT +/* + ========================================================================== + Description: + Set BSSID of Root AP + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSetApCliBssid( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBssid, + IN UCHAR index) +{ + UINT32 Addr4 = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():%x:%x:%x:%x:%x:%x\n", + __FUNCTION__, PRINT_MAC(pBssid))); + + Addr4 = (UINT32)(pBssid[0]) | + (UINT32)(pBssid[1] << 8) | + (UINT32)(pBssid[2] << 16) | + (UINT32)(pBssid[3] << 24); + RTMP_IO_WRITE32(pAd, MAC_APCLI_BSSID_DW0, Addr4); + + Addr4 = 0; + Addr4 = (ULONG)(pBssid[4]) | (ULONG)(pBssid[5] << 8); + /* Enable APCLI mode */ + Addr4 |= 0x10000; + + RTMP_IO_WRITE32(pAd, MAC_APCLI_BSSID_DW1, Addr4); +} +#endif /* MAC_APCLI_SUPPORT */ + +#ifdef NEW_WOW_SUPPORT +VOID RT28xxAndesWOWEnable( + IN PRTMP_ADAPTER pAd) +{ + NEW_WOW_MASK_CFG_STRUCT mask_cfg; + NEW_WOW_SEC_CFG_STRUCT sec_cfg; + NEW_WOW_INFRA_CFG_STRUCT infra_cfg; + NEW_WOW_P2P_CFG_STRUCT p2p_cfg; + NEW_WOW_PARAM_STRUCT wow_param; + struct CMD_UNIT CmdUnit; + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + INT32 Ret; + MAC_TABLE_ENTRY *pEntry = NULL; + + + NdisZeroMemory(&CmdUnit, sizeof(CmdUnit)); + + /* WOW enable */ + NdisZeroMemory(&wow_param, sizeof(wow_param)); + + wow_param.Parameter = WOW_ENABLE; /* WOW enable */ + wow_param.Value = TRUE; + + CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; /* feature enable */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&wow_param; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__, + CmdUnit.u.ANDES.Type, wow_param.Parameter); + return; + } + + RtmpOsMsDelay(1); + /* mask configuration */ + NdisZeroMemory(&mask_cfg, sizeof(mask_cfg)); + + mask_cfg.Config_Type = WOW_MASK_CFG; /* detect mask config */ + mask_cfg.Function_Enable = TRUE; + mask_cfg.Detect_Mask = 1UL << WOW_MAGIC_PKT; /* magic packet */ + mask_cfg.Event_Mask = 0; + + CmdUnit.u.ANDES.Type = CMD_WOW_CONFIG; /* WOW config */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_MASK_CFG_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&mask_cfg; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed!!(%d/%d)\x1b[m\n", __FUNCTION__, + CmdUnit.u.ANDES.Type, mask_cfg.Config_Type); + return; + } + + RtmpOsMsDelay(1); + + /* security configuration */ + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPAPSK) + { + NdisZeroMemory(&sec_cfg, sizeof(sec_cfg)); + + sec_cfg.Config_Type = WOW_SEC_CFG; /* security config */ + + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) + sec_cfg.WPA_Ver = 0; + else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) + sec_cfg.WPA_Ver = 1; + + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + + NdisCopyMemory(sec_cfg.PTK, pEntry->PTK, 64); + NdisCopyMemory(sec_cfg.R_COUNTER, pEntry->R_Counter, LEN_KEY_DESC_REPLAY); + + sec_cfg.Key_Id = pAd->StaCfg.DefaultKeyId; + sec_cfg.Cipher_Alg = pEntry->WepStatus; + printk("\x1b[31m%s: wep status %d\x1b[m\n", __FUNCTION__, pEntry->WepStatus); + sec_cfg.Group_Cipher = pAd->StaCfg.GroupCipher; + printk("\x1b[31m%s: group status %d\x1b[m\n", __FUNCTION__, sec_cfg.Group_Cipher); + printk("\x1b[31m%s: aid %d\x1b[m\n", __FUNCTION__, pEntry->Aid); + sec_cfg.WCID = BSSID_WCID; + + CmdUnit.u.ANDES.Type = CMD_WOW_CONFIG; /* WOW config */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_SEC_CFG_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&sec_cfg; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__, + CmdUnit.u.ANDES.Type, sec_cfg.Config_Type); + return; + } + + RtmpOsMsDelay(1); + } + + /* Infra configuration */ + + NdisZeroMemory(&infra_cfg, sizeof(infra_cfg)); + + infra_cfg.Config_Type = WOW_INFRA_CFG; /* infra config */ + + COPY_MAC_ADDR(infra_cfg.STA_MAC, pAd->CurrentAddress); + COPY_MAC_ADDR(infra_cfg.AP_MAC, pAd->CommonCfg.Bssid); + + CmdUnit.u.ANDES.Type = CMD_WOW_CONFIG; /* WOW config */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_INFRA_CFG_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&infra_cfg; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + infra_cfg.AP_Status = TRUE; + else + infra_cfg.AP_Status = FALSE; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__, + CmdUnit.u.ANDES.Type, infra_cfg.Config_Type); + return; + } + + RtmpOsMsDelay(1); + + + /* P2P configuration */ + + /* Wakeup Option */ + NdisZeroMemory(&wow_param, sizeof(wow_param)); + + wow_param.Parameter = WOW_WAKEUP; /* Wakeup Option */ + if (pAd->WOW_Cfg.bInBand) + { +#ifdef RTMP_MAC_PCI + wow_param.Value = WOW_WAKEUP_BY_PCIE; +#else + wow_param.Value = WOW_WAKEUP_BY_USB; +#endif /* RTMP_MAC_PCI */ + } + else + { + INT32 Value; + + wow_param.Value = WOW_WAKEUP_BY_GPIO; + + RTMP_IO_READ32(pAd, WLAN_FUN_CTRL, &Value); + printk("\x1b[31m%s: 0x80 = %x\x1b[m\n", __FUNCTION__, Value); + Value &= ~0x01010000; /* GPIO0(ouput) --> 0(data) */ + RTMP_IO_WRITE32(pAd, WLAN_FUN_CTRL, Value); + } + + CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; /* feature enable */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&wow_param; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__, + CmdUnit.u.ANDES.Type, wow_param.Parameter); + return; + } + + RtmpOsMsDelay(1); + + + /* traffic to Andes */ + NdisZeroMemory(&wow_param, sizeof(wow_param)); + wow_param.Parameter = WOW_TRAFFIC; /* Traffic switch */ + wow_param.Value = WOW_PKT_TO_ANDES; /* incoming packet to FW */ + + CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; /* feature enable */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&wow_param.Parameter; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__, + CmdUnit.u.ANDES.Type, wow_param.Parameter); + return; + } + + RtmpOsMsDelay(1); + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); +} + +VOID RT28xxAndesWOWDisable( + IN PRTMP_ADAPTER pAd) +{ + NEW_WOW_PARAM_STRUCT param; + struct CMD_UNIT CmdUnit; + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + INT32 Ret; + UINT32 Value; + MAC_TABLE_ENTRY *pEntry = NULL; + + printk("\x1b[31m%s: ...\x1b[m", __FUNCTION__); + + /* clean BulkIn Reset flag */ + //pAd->Flags &= ~0x80000; + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); + + NdisZeroMemory(&CmdUnit, sizeof(CmdUnit)); + + /* WOW disable */ + NdisZeroMemory(¶m, sizeof(param)); + param.Parameter = WOW_ENABLE; + param.Value = FALSE; + + CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; /* WOW enable */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)¶m; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed!!\x1b[m\n", __FUNCTION__); + return; + } + + RtmpOsMsDelay(1); + + + /* traffic to Host */ + NdisZeroMemory(¶m, sizeof(param)); + param.Parameter = WOW_TRAFFIC; + param.Value = WOW_PKT_TO_HOST; + + CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)¶m; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed!!\x1b[m\n", __FUNCTION__); + return; + } + + RtmpOsMsDelay(1); + + + /* Restore MAC TX/RX */ + AsicSetMacTxRx(pAd, ASIC_MAC_TXRX, TRUE); + + RTUSBBulkReceive(pAd); + RTUSBBulkCmdRspEventReceive(pAd); + + /* restore hardware remote wakeup flag */ + RTMP_IO_READ32(pAd, WLAN_FUN_CTRL, &Value); + printk("\x1b[31m%s: 0x80 %08x\x1b[m\n", __FUNCTION__, Value); + Value &= ~0x80; + RTMP_IO_WRITE32(pAd, WLAN_FUN_CTRL, Value); + + if (pAd->WOW_Cfg.bInBand == FALSE) + { + INT32 Value; + + RTMP_IO_READ32(pAd, WLAN_FUN_CTRL, &Value); + printk("\x1b[31m%s: 0x80 = %x\x1b[m\n", __FUNCTION__, Value); + Value &= ~0x01010000; /* GPIO0(ouput) --> 0(data) */ + RTMP_IO_WRITE32(pAd, WLAN_FUN_CTRL, Value); + } +} + +#endif /* NEW_WOW_SUPPORT */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/cmm_asic_mt.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/cmm_asic_mt.c new file mode 100644 index 000000000..a8c0c0ec5 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/cmm_asic_mt.c @@ -0,0 +1,6817 @@ +/* + *************************************************************************** + * 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" +//#include "mac/mac_ral/rtmp_mac.h" + +extern const UCHAR wmm_aci_2_hw_ac_queue[18] ; + +UINT32 AsicGetCrcErrCnt(RTMP_ADAPTER *pAd) +{ + return 0; +} + + +UINT32 AsicGetPhyErrCnt(RTMP_ADAPTER *pAd) +{ + return 0; +} + + +UINT32 AsicGetCCACnt(RTMP_ADAPTER *pAd) +{ + return 0; +} + + +UINT32 AsicGetChBusyCnt(RTMP_ADAPTER *pAd, UCHAR ch_idx) +{ + UINT32 msdr16; + RTMP_IO_READ32(pAd, MIB_MSDR16, &msdr16); + msdr16 &= 0x00ffffff; + return msdr16; +} + + + + +INT AsicSetAutoFallBack(RTMP_ADAPTER *pAd, BOOLEAN enable) +{ + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + } + return FALSE; +} + + +INT32 AsicAutoFallbackInit(RTMP_ADAPTER *pAd) +{ + UINT32 Value; + + RTMP_IO_READ32(pAd, AGG_ARUCR, &Value); + Value &= ~RATE1_UP_MPDU_LIMIT_MASK; + Value |= RATE1_UP_MPDU_LINIT(2); + Value &= ~RATE2_UP_MPDU_LIMIT_MASK; + Value |= RATE2_UP_MPDU_LIMIT(2); + Value &= ~RATE3_UP_MPDU_LIMIT_MASK; + Value |= RATE3_UP_MPDU_LIMIT(2); + Value &= ~RATE4_UP_MPDU_LIMIT_MASK; + Value |= RATE4_UP_MPDU_LIMIT(2); + Value &= ~RATE5_UP_MPDU_LIMIT_MASK; + Value |= RATE5_UP_MPDU_LIMIT(1); + Value &= ~RATE6_UP_MPDU_LIMIT_MASK; + Value |= RATE6_UP_MPDU_LIMIT(1); + Value &= ~RATE7_UP_MPDU_LIMIT_MASK; + Value |= RATE7_UP_MPDU_LIMIT(1); + Value &= ~RATE8_UP_MPDU_LIMIT_MASK; + Value |= RATE8_UP_MPDU_LIMIT(1); + RTMP_IO_WRITE32(pAd, AGG_ARUCR, Value); + + RTMP_IO_READ32(pAd, AGG_ARDCR, &Value); + Value &= ~RATE1_DOWN_MPDU_LIMIT_MASK; + Value |= RATE1_DOWN_MPDU_LIMIT(0); + Value &= ~RATE2_DOWN_MPDU_LIMIT_MASK; + Value |= RATE2_DOWN_MPDU_LIMIT(0); + Value &= ~RATE3_DOWN_MPDU_LIMIT_MASK; + Value |= RATE3_DOWN_MPDU_LIMIT(0); + Value &= ~RATE4_DOWN_MPDU_LIMIT_MASK; + Value |= RATE4_DOWN_MPDU_LIMIT(0); + Value &= ~RATE5_DOWN_MPDU_LIMIT_MASK; + Value |= RATE5_DOWN_MPDU_LIMIT(0); + Value &= ~RATE6_DOWN_MPDU_LIMIT_MASK; + Value |= RATE6_DOWN_MPDU_LIMIT(0); + Value &= ~RATE7_DOWN_MPDU_LIMIT_MASK; + Value |= RATE7_DOWN_MPDU_LIMIT(0); + Value &= ~RATE8_DOWN_MPDU_LIMIT_MASK; + Value |= RATE8_DOWN_MPDU_LIMIT(0); + RTMP_IO_WRITE32(pAd, AGG_ARDCR, Value); + + RTMP_IO_READ32(pAd, AGG_ARCR, &Value); + Value |= INI_RATE1; + Value |= FB_SGI_DIS; + Value &= ~RTS_RATE_DOWN_TH_MASK; + Value |= RTS_RATE_DOWN_TH(2); + Value &= ~RATE_DOWN_EXTRA_RATIO_MASK; + Value |= RATE_DOWN_EXTRA_RATIO(2); + Value |= RATE_DOWN_EXTRA_RATIO_EN; + Value &= ~RATE_UP_EXTRA_TH_MASK; + Value |= RATE_UP_EXTRA_TH(4); + RTMP_IO_WRITE32(pAd, AGG_ARCR, Value); + + return TRUE; +} + + +/* + ======================================================================== + + Routine Description: + Set MAC register value according operation mode. + OperationMode AND bNonGFExist are for MM and GF Proteciton. + If MM or GF mask is not set, those passing argument doesn't not take effect. + + Operation mode meaning: + = 0 : Pure HT, no preotection. + = 0x01; there may be non-HT devices in both the control and extension channel, protection is optional in BSS. + = 0x10: No Transmission in 40M is protected. + = 0x11: Transmission in both 40M and 20M shall be protected + if (bNonGFExist) + we should choose not to use GF. But still set correct ASIC registers. + ======================================================================== +*/ +typedef enum _PROT_REG_IDX_{ + REG_IDX_CCK = 0, /* 0x1364 */ + REG_IDX_OFDM = 1, /* 0x1368 */ + REG_IDX_MM20 = 2, /* 0x136c */ + REG_IDX_MM40 = 3, /* 0x1370 */ + REG_IDX_GF20 = 4, /* 0x1374 */ + REG_IDX_GF40 = 5, /* 0x1378 */ +}PROT_REG_IDX; + + +VOID AsicUpdateProtect( + IN PRTMP_ADAPTER pAd, + IN USHORT OperationMode, + IN UCHAR SetMask, + IN BOOLEAN bDisableBGProtect, + IN BOOLEAN bNonGFExist) +{ + ASIC_UPDATE_PROTECT rAsicUpdateProtect = {0}; + + rAsicUpdateProtect.OperationMode = OperationMode; + rAsicUpdateProtect.SetMask = SetMask; + rAsicUpdateProtect.bDisableBGProtect = bDisableBGProtect; + rAsicUpdateProtect.bNonGFExist = bNonGFExist; + + //DBGPRINT(RT_DEBUG_OFF, ("%s(%d)(%d, %d, %d, %d)\n", __FUNCTION__, __LINE__, rAsicUpdateProtect.OperationMode, rAsicUpdateProtect.SetMask, rAsicUpdateProtect.bDisableBGProtect, rAsicUpdateProtect.bNonGFExist )); + + RTEnqueueInternalCmd(pAd, CMDTHREAD_PERODIC_CR_ACCESS_ASIC_UPDATE_PROTECT, &rAsicUpdateProtect, sizeof(rAsicUpdateProtect)); +} + +NTSTATUS MtCmdAsicUpdateProtect(RTMP_ADAPTER *pAd, PCmdQElmt CMDQelmt) +{ + UINT32 Value = 0; + UINT32 tmac_trcr = 0; + PASIC_UPDATE_PROTECT pAsicUpdateProtect = (PASIC_UPDATE_PROTECT)(CMDQelmt->buffer); + USHORT OperationMode = pAsicUpdateProtect->OperationMode; + UCHAR SetMask = pAsicUpdateProtect->SetMask; + BOOLEAN bDisableBGProtect = pAsicUpdateProtect->bDisableBGProtect; + + + BOOLEAN bNonGFExist = pAsicUpdateProtect->bNonGFExist; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + DBGPRINT(RT_DEBUG_INFO, ("%s(%d): H/W in PM4, return\n", __FUNCTION__, __LINE__)); + return NDIS_STATUS_SUCCESS; + } + + //DBGPRINT(RT_DEBUG_OFF, ("%s(%d): --->\n", __FUNCTION__, __LINE__)); + //DBGPRINT(RT_DEBUG_OFF, ("%s(%d)(%d, %d, %d, %d)\n", __FUNCTION__, __LINE__, OperationMode, SetMask, bDisableBGProtect, bNonGFExist )); + + pAd->CommonCfg.RestoreProtection.OperationMode = OperationMode; + pAd->CommonCfg.RestoreProtection.SetMask = SetMask; + pAd->CommonCfg.RestoreProtection.bDisableBGProtect = bDisableBGProtect; + pAd->CommonCfg.RestoreProtection.bNonGFExist = bNonGFExist; + +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + return NDIS_STATUS_SUCCESS; +#endif /* CONFIG_ATE */ + +#ifdef DOT11_N_SUPPORT + if (!(pAd->CommonCfg.bHTProtect) && (OperationMode != 8)) + return NDIS_STATUS_SUCCESS; +#endif /* DOT11_N_SUPPORT */ + + if (pAd->chipCap.hif_type == HIF_MT) { + /* Config ASIC RTS threshold register*/ + RTMP_IO_READ32(pAd, AGG_PCR1, &Value); + Value &= ~RTS_THRESHOLD_MASK; + Value &= ~RTS_PKT_NUM_THRESHOLD_MASK; + + if (( +#ifdef DOT11_N_SUPPORT + (pAd->CommonCfg.BACapability.field.AmsduEnable) || +#endif /* DOT11_N_SUPPORT */ + (pAd->bDisableRtsProtect == TRUE)) + && (pAd->CommonCfg.RtsThreshold == MAX_RTS_THRESHOLD)) { + Value |= RTS_THRESHOLD(0xFFFFF); + Value |= RTS_PKT_NUM_THRESHOLD(0x7F); + tmac_trcr = 0; + } else { + Value |= RTS_THRESHOLD(pAd->CommonCfg.RtsThreshold); + Value |= RTS_PKT_NUM_THRESHOLD(1); + tmac_trcr = I2T_CHK_EN; + } + +#if defined(MAX_CONTINUOUS_TX_CNT) || defined(NEW_IXIA_METHOD) + /*special for IXIA*/ + if ((pAd->ContinousTxCnt == CONTINUOUS_TX_CNT) || ((pAd->protectpara & 0x1) == 1)) { + Value |= RTS_THRESHOLD(0xFFFFF); + Value |= RTS_PKT_NUM_THRESHOLD(0x7F); + } +#endif + RTMP_IO_WRITE32(pAd, AGG_PCR1, Value); + if(pAd->RalinkCounters.OneSecFalseCCACnt > pAd->Cts2SelfTh) { + /*continuous FalseCCA is high within 3 seconds, force cts to self*/ + if(pAd->Cts2SelfMonitorCnt >= 3) { + bDisableBGProtect = FALSE; + OperationMode = 0x3; + RTMP_IO_READ32(pAd, TMAC_TRCR, &Value); + if ((Value & 0xff) != 0x88) { + Value &= 0xffffff00; + Value |= 0x88; + RTMP_IO_WRITE32(pAd, TMAC_TRCR, Value); + } + RTMP_IO_READ32(pAd, AGG_TEMP, &Value); + if ((Value & (1<<1)) == 0) { + Value |= (1<<1); + RTMP_IO_WRITE32(pAd, AGG_TEMP, Value); + } + RTMP_IO_READ32(pAd, AGG_PCR, &Value); + Value |= ERP_PROTECTION_MASK; + RTMP_IO_WRITE32(pAd, AGG_PCR, Value); + + RTMP_IO_READ32(pAd, AGG_PCR1, &Value); + Value &= ~RTS_THRESHOLD_MASK; + Value &= ~RTS_PKT_NUM_THRESHOLD_MASK; + Value |= RTS_THRESHOLD(0xFFFFF); + Value |= RTS_PKT_NUM_THRESHOLD(0x7F); + RTMP_IO_WRITE32(pAd, AGG_PCR1, Value); + tmac_trcr = 0; + } else + pAd->Cts2SelfMonitorCnt++; + pAd->RtsMonitorCnt = 0; + } else { + /*continuous FalseCCA is high within 3 seconds, follow the default flow*/ + if(pAd->RtsMonitorCnt >= 3) { + RTMP_IO_READ32(pAd, TMAC_TRCR, &Value); + if ((Value & 0xff) != 0x82) { + Value &= 0xffffff00; + Value |= 0x82; + RTMP_IO_WRITE32(pAd, TMAC_TRCR, Value); + } + + RTMP_IO_READ32(pAd, AGG_TEMP, &Value); + if ((Value & (1<<1)) != 0) { + Value &= (0<<1); + RTMP_IO_WRITE32(pAd, AGG_TEMP, Value); + } + } else { + pAd->RtsMonitorCnt++; + } + pAd->Cts2SelfMonitorCnt = 0; + } + + RTMP_IO_READ32(pAd, TMAC_TRCR, &Value); + Value |= tmac_trcr; + /*affect peak performance,only enable in IXIA test!*/ + /*RTMP_IO_WRITE32(pAd, TMAC_TRCR, Value);*/ + + /* Handle legacy(B/G) protection*/ + if (bDisableBGProtect) { + RTMP_IO_READ32(pAd, AGG_PCR, &Value); + Value &= ~ERP_PROTECTION_MASK; + RTMP_IO_WRITE32(pAd, AGG_PCR, Value); + pAd->FlgCtsEnabled = 0; /* CTS-self is not used */ + } else { + pAd->FlgCtsEnabled = 1; /* CTS-self is used */ + } + + RTMP_IO_READ32(pAd, AGG_PCR, &Value); + + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE)) + { /* Single Protection Mode */ + Value |= PROTECTION_MODE; + } + else + { + Value &= ~PROTECTION_MODE; + } + + + RTMP_IO_WRITE32(pAd, AGG_PCR, Value); + + +#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.*/ + RTMP_IO_READ32(pAd, AGG_PCR, &Value); + Value &= ~(MM_PROTECTION | GF_PROTECTION | BW40_PROTECTION + | RIFS_PROTECTION | BW80_PROTECTION | BW160_PROTECTION); + + RTMP_IO_WRITE32(pAd, AGG_PCR, Value); + break; + case 0x1: + /* This is "HT non-member protection mode." */ + /* If there may be non-HT STAs my BSS*/ + RTMP_IO_READ32(pAd, AGG_PCR, &Value); + Value &= ~(MM_PROTECTION | GF_PROTECTION | BW40_PROTECTION + | RIFS_PROTECTION | BW80_PROTECTION | BW160_PROTECTION); + + Value |= (MM_PROTECTION | GF_PROTECTION | BW40_PROTECTION); + + RTMP_IO_WRITE32(pAd, AGG_PCR, Value); + break; + case 0x2: + /* If only HT STAs are in BSS. at least one is 20MHz. Only protect 40MHz packets */ + RTMP_IO_READ32(pAd, AGG_PCR, &Value); + Value &= ~(MM_PROTECTION | GF_PROTECTION | BW40_PROTECTION + | RIFS_PROTECTION | BW80_PROTECTION | BW160_PROTECTION); + + Value |= (BW40_PROTECTION); + + RTMP_IO_WRITE32(pAd, AGG_PCR, Value); + break; + + case 0x3: + /* HT mixed mode. PROTECT ALL!*/ + /* both 20MHz and 40MHz are protected. Whether use RTS or CTS-to-self depends on the */ + RTMP_IO_READ32(pAd, AGG_PCR, &Value); + Value &= ~(MM_PROTECTION | GF_PROTECTION | BW40_PROTECTION + | RIFS_PROTECTION | BW80_PROTECTION | BW160_PROTECTION); + + Value |= (MM_PROTECTION | GF_PROTECTION | BW40_PROTECTION); + + RTMP_IO_WRITE32(pAd, AGG_PCR, Value); + pAd->CommonCfg.IOTestParm.bRTSLongProtOn = TRUE; + break; + + case 0x8: + // TODO: + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: unknown protection mode(%d)\n", __FUNCTION__, OperationMode)); + } + } +#endif /* DOT11_N_SUPPORT */ + } + + return NDIS_STATUS_SUCCESS; +} + +VOID AsicWtblSetRTS(RTMP_ADAPTER *pAd, UCHAR widx, BOOLEAN bEnable) +{ + struct wtbl_entry tb_entry; + union WTBL_1_DW2 *dw2 = &tb_entry.wtbl_1.wtbl_1_d2; + + NdisZeroMemory(&tb_entry, sizeof(tb_entry)); + if (mt_wtbl_get_entry234(pAd, widx, &tb_entry) == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Cannot found WTBL2/3/4 for WCID(%d)\n", + __FUNCTION__, widx)); + return; + } + + RTMP_IO_READ32(pAd, tb_entry.wtbl_addr[0] + (2 * 4), &dw2->word); + if (bEnable != dw2->field.rts) + { + dw2->field.rts = bEnable; + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + (2 * 4), dw2->word); + } +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSwitchChannel(RTMP_ADAPTER *pAd, UCHAR Channel, BOOLEAN bScan) +{ + UCHAR bw; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF)) + return; + +#ifdef MT_WOW_SUPPORT + if (pAd->WOW_Cfg.bWoWRunning){ + DBGPRINT(RT_DEBUG_OFF, ("[%s] WoW is running, skip!\n", __func__)); + return; + } +#endif + +#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 */ + + if (pAd->chipOps.ChipSwitchChannel) + pAd->chipOps.ChipSwitchChannel(pAd, Channel, bScan); + else + DBGPRINT(RT_DEBUG_ERROR, ("For this chip, no specified channel switch function!\n")); + +#ifdef MT_MAC + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + UINT32 val; + + RTMP_IO_READ32(pAd, RMAC_CHFREQ, &val); + val = 1; + RTMP_IO_WRITE32(pAd, RMAC_CHFREQ, val); + + } +#endif /* MT_MAC */ + + /* R66 should be set according to Channel and use 20MHz when scanning*/ + if (bScan) + bw = BW_20; + else { + bw = pAd->CommonCfg.BBPCurrentBW; + } + RTMPSetAGCInitValue(pAd, bw); +} + + +/* + ========================================================================== + Description: + This function is required for 2421 only, and should not be used during + site survey. It's only required after NIC decided to stay at a channel + for a longer period. + When this function is called, it's always after AsicSwitchChannel(). + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicLockChannel( + IN PRTMP_ADAPTER pAd, + IN UCHAR Channel) +{ +} + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ + + +VOID AsicResetBBPAgent(RTMP_ADAPTER *pAd) +{ + /* Still need to find why BBP agent keeps busy, but in fact, hardware still function ok. Now clear busy first. */ + /* IF chipOps.AsicResetBbpAgent == NULL, run "else" part */ + if (pAd->chipOps.AsicResetBbpAgent != NULL) + pAd->chipOps.AsicResetBbpAgent(pAd); +} + + + + +/* + ========================================================================== + Description: + Set My BSSID + + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ + /* CFG_TODO */ +VOID AsicSetBssid(RTMP_ADAPTER *pAd, UCHAR *pBssid, UCHAR curr_bssid_idx) +{ + UINT32 val; + // TODO: shiang-7603, now only configure Current BSSID Address 0 + ULONG curr_bssid_reg_base = RMAC_CB0R0;//register for Current_Bssid from 0x60140004 + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Set BSSID=%02x:%02x:%02x:%02x:%02x:%02x, curr_bssid_idx = %d\n", + __FUNCTION__, PRINT_MAC(pBssid), curr_bssid_idx)); + + + val = (UINT32)((pBssid[0]) | + (UINT32)(pBssid[1] << 8) | + (UINT32)(pBssid[2] << 16) | + (UINT32)(pBssid[3] << 24)); + RTMP_IO_WRITE32(pAd, curr_bssid_reg_base + (curr_bssid_idx * 8), val); + + val = (UINT32)(pBssid[4]) | (UINT32)(pBssid[5] << 8) | (1 <<16); + RTMP_IO_WRITE32(pAd, (curr_bssid_reg_base + 4) + (curr_bssid_idx * 8), val); + + // If we enable BSSID0, we should not enable MBSS0, or the BSSID index will wrong + //RTMP_IO_READ32(pAd, RMAC_ACBEN, &val); + //val |= 0x1; + //RTMP_IO_WRITE32(pAd, RMAC_ACBEN, val); + + return; +} + + +INT AsicSetDevMac(RTMP_ADAPTER *pAd, UCHAR *addr, UCHAR omac_idx) +{ + UINT32 val; + ULONG own_mac_reg_base = RMAC_OMA0R0;//register for Own_Mac from 0x60140024 + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Set OwnMac=%02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, PRINT_MAC(addr))); + + val = (addr[0]) | (addr[1]<<8) | (addr[2]<<16) | (addr[3]<<24); + RTMP_IO_WRITE32(pAd, own_mac_reg_base + (omac_idx * 8), val); + + val = addr[4] | (addr[5]<<8) | (1 <<16); + RTMP_IO_WRITE32(pAd, (own_mac_reg_base + 4) + (omac_idx * 8), val); + + return TRUE; +} + + +#ifdef CONFIG_AP_SUPPORT +VOID AsicSetMbssMode(RTMP_ADAPTER *pAd, UCHAR NumOfBcns) +{ + UCHAR NumOfMacs; + UINT32 regValue; + + /* + Note: + 1.The MAC address of Mesh and AP-Client link are different from Main BSSID. + 2.If the Mesh link is included, its MAC address shall follow the last MBSSID's MAC by increasing 1. + 3.If the AP-Client link is included, its MAC address shall follow the Mesh interface MAC by increasing 1. + */ + NumOfMacs = pAd->ApCfg.BssidNum + MAX_MESH_NUM + MAX_APCLI_NUM; + + /* set Multiple BSSID mode */ + if (NumOfMacs <= 1) + { + pAd->ApCfg.MacMask = ~(1-1); + } + else if (NumOfMacs <= 2) + { + if ((pAd->CurrentAddress[5] % 2 != 0) + ) + DBGPRINT(RT_DEBUG_ERROR, ("The 2-BSSID mode is enabled, the BSSID byte5 MUST be the multiple of 2\n")); + + 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")); + + 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")); + + pAd->ApCfg.MacMask = ~(8-1); + } + else if (NumOfMacs <= 16) + { + /* Set MULTI_BSSID_MODE_BIT4 in MAC register 0x1014 */ + pAd->ApCfg.MacMask = ~(16-1); + } + + // TODO: shiang-7603 + RTMP_IO_READ32(pAd, RMAC_ACBEN, ®Value); + regValue |= ((1 << NumOfMacs) - 1); + // TODO: shiang-MT7603, for MBSS0, now we use BSS0 instead of MBSS0, or the BSSID Index will be mismatch! + regValue &= (~0x01); + RTMP_IO_WRITE32(pAd, RMAC_ACBEN, regValue); + +} +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef APCLI_SUPPORT +#ifdef MAC_REPEATER_SUPPORT +INT AsicSetMacAddrExt(RTMP_ADAPTER *pAd, BOOLEAN bEnable) +{ + RMAC_MORE_STRUC rmac_more; + if (pAd->chipCap.hif_type == HIF_MT) { + RTMP_IO_READ32(pAd, RMAC_MORE, &rmac_more.word); + + if (bEnable == 0) + rmac_more.field.muar_mode_sel = 0; + else + rmac_more.field.muar_mode_sel = 1; + + RTMP_IO_WRITE32(pAd, RMAC_MORE, rmac_more.word); + } + else + return FALSE; + + return TRUE; +} + +VOID RTMPInsertRepeaterAsicEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR CliIdx, + IN PUCHAR pAddr) +{ + UCHAR tempMAC[MAC_ADDR_LEN]; + RMAC_MAR0_STRUC rmac_mcbcs0; + RMAC_MAR1_STRUC rmac_mcbcs1; + + COPY_MAC_ADDR(tempMAC, pAddr); + + DBGPRINT(RT_DEBUG_ERROR, ("\n%s %02x:%02x:%02x:%02x:%02x:%02x-%02x\n", + __func__, PRINT_MAC(tempMAC), CliIdx)); + + NdisZeroMemory(&rmac_mcbcs0, sizeof(RMAC_MAR0_STRUC)); + rmac_mcbcs0.addr_31_0 = tempMAC[0] + (tempMAC[1] << 8) +(tempMAC[2] << 16) +(tempMAC[3] << 24); + RTMP_IO_WRITE32(pAd, RMAC_MAR0, rmac_mcbcs0.addr_31_0); + + NdisZeroMemory(&rmac_mcbcs1, sizeof(RMAC_MAR1_STRUC)); + rmac_mcbcs1.field.addr_39_32 = tempMAC[4]; + rmac_mcbcs1.field.addr_47_40 = tempMAC[5]; + rmac_mcbcs1.field.access_start = 1; + rmac_mcbcs1.field.readwrite = 1; + rmac_mcbcs1.field.multicast_addr_index = CliIdx; + RTMP_IO_WRITE32(pAd, RMAC_MAR1, rmac_mcbcs1.word); + + return; +} + +VOID RTMPRemoveRepeaterAsicEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR CliIdx) +{ + RMAC_MAR0_STRUC rmac_mcbcs0; + RMAC_MAR1_STRUC rmac_mcbcs1; + + DBGPRINT(RT_DEBUG_WARN, (" %s.\n", __FUNCTION__)); + + NdisZeroMemory(&rmac_mcbcs0, sizeof(RMAC_MAR0_STRUC)); + RTMP_IO_WRITE32(pAd, RMAC_MAR0, rmac_mcbcs0.addr_31_0); + + NdisZeroMemory(&rmac_mcbcs1, sizeof(RMAC_MAR1_STRUC)); + rmac_mcbcs1.field.access_start = 1; + rmac_mcbcs1.field.readwrite = 1; + + rmac_mcbcs1.field.multicast_addr_index = CliIdx;//start from idx 0 + + RTMP_IO_WRITE32(pAd, RMAC_MAR1, rmac_mcbcs1.word);//clear client entry first. + + NdisZeroMemory(&rmac_mcbcs0, sizeof(RMAC_MAR0_STRUC)); + RTMP_IO_WRITE32(pAd, RMAC_MAR0, rmac_mcbcs0.addr_31_0); + + NdisZeroMemory(&rmac_mcbcs1, sizeof(RMAC_MAR1_STRUC)); + rmac_mcbcs1.field.access_start = 1; + rmac_mcbcs1.field.readwrite = 1; + + rmac_mcbcs1.field.multicast_addr_index = 0x10 + CliIdx;//start from idx 16 + + RTMP_IO_WRITE32(pAd, RMAC_MAR1, rmac_mcbcs1.word);//clear rootap entry. +} + +void insert_repeater_root_entry( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR *pAddr, + IN UCHAR ReptCliIdx) +{ + struct rtmp_mac_ctrl *wtbl_ctrl = &pAd->mac_ctrl; + struct wtbl_entry tb_entry; + union WTBL_1_DW0 *dw0 = (union WTBL_1_DW0 *)&tb_entry.wtbl_1.wtbl_1_d0.word; + union WTBL_1_DW1 *dw1 = (union WTBL_1_DW1 *)&tb_entry.wtbl_1.wtbl_1_d1.word; + union WTBL_1_DW2 *dw2 = (union WTBL_1_DW2 *)&tb_entry.wtbl_1.wtbl_1_d2.word; + RMAC_MAR0_STRUC rmac_mcbcs0; + RMAC_MAR1_STRUC rmac_mcbcs1; + //STA_TR_ENTRY *tr_entry; + + if (pEntry) + { + //tr_entry = &pAd->MacTab.tr_entry[pEntry->wcid]; + //tr_entry->PortSecured = WPA_802_1X_PORT_SECURED; + //pEntry->AuthState = AS_AUTH_OPEN;//TODO, Carter, check this. + //pEntry->Sst = SST_ASSOC; + + tb_entry.wtbl_addr[0] = wtbl_ctrl->wtbl_base_addr[0] + + pEntry->wcid * wtbl_ctrl->wtbl_entry_size[0]; + + RTMP_IO_READ32(pAd, tb_entry.wtbl_addr[0], &tb_entry.wtbl_1.wtbl_1_d0.word); + RTMP_IO_READ32(pAd, tb_entry.wtbl_addr[0] + 4, &tb_entry.wtbl_1.wtbl_1_d1.word); + RTMP_IO_READ32(pAd, tb_entry.wtbl_addr[0] + 8, &tb_entry.wtbl_1.wtbl_1_d2.word); + dw0->field.wm = 0; + dw0->field.muar_idx = 0x20 + ReptCliIdx; + dw0->field.rc_a1 = 1; + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0], dw0->word); + + DBGPRINT(RT_DEBUG_OFF, ("%s(%d):Write WTBL 1 Addr:0x%x, Value:0x%x\n", + __FUNCTION__, ReptCliIdx, tb_entry.wtbl_addr[0], dw0->word)); + DBGPRINT(RT_DEBUG_OFF, ("%s(%d):Write WTBL 1 Addr:0x%x, Value:0x%x\n", + __FUNCTION__, ReptCliIdx, tb_entry.wtbl_addr[0] + 4, dw1->word)); + DBGPRINT(RT_DEBUG_OFF, ("%s(%d):Write WTBL 1 Addr:0x%x, Value:0x%x\n", + __FUNCTION__, ReptCliIdx, tb_entry.wtbl_addr[0] + 8, dw2->word)); + + NdisZeroMemory(&rmac_mcbcs0, sizeof(RMAC_MAR0_STRUC)); + rmac_mcbcs0.addr_31_0 = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24); + RTMP_IO_WRITE32(pAd, RMAC_MAR0, rmac_mcbcs0.addr_31_0); + + NdisZeroMemory(&rmac_mcbcs1, sizeof(RMAC_MAR1_STRUC)); + rmac_mcbcs1.field.addr_39_32 = pAddr[4]; + rmac_mcbcs1.field.addr_47_40 = pAddr[5]; + rmac_mcbcs1.field.access_start = 1; + rmac_mcbcs1.field.readwrite = 1; + rmac_mcbcs1.field.multicast_addr_index = 0x10 + ReptCliIdx; + RTMP_IO_WRITE32(pAd, RMAC_MAR1, rmac_mcbcs1.word); + } +} + + +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* APCLI_SUPPORT */ + + +INT AsicSetRxFilter(RTMP_ADAPTER *pAd) +{ + //UINT32 rx_filter_flag = 0; + UINT32 Value; + + /* enable RX of MAC block*/ + if ((pAd->OpMode == OPMODE_AP) + ) + { + //rx_filter_flag = APNORMAL; + Value = 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 */ + } + + if (pAd->chipCap.hif_type == HIF_MT) { + RTMP_IO_READ32(pAd, RMAC_RFCR, &Value); + Value &= ~RM_FRAME_REPORT_EN; + Value &= ~DROP_NOT_MY_BSSID; + Value &= ~DROP_NOT_IN_MC_TABLE; +#if defined(MT7628_FPGA) + Value = 0x1002; +#endif + /*disable RX diff BSSID BCN filter */ + Value &= ~DROP_DIFF_BSSID_BCN; + /*disable RX PROB request filter */ + Value &= ~DROP_PROBE_REQ; + /* Disable Rx Duplicate Packet Drop filter */ + Value &= ~DROP_DUPLICATE; + +#ifdef CONFIG_SNIFFER_SUPPORT + if ((MONITOR_ON(pAd)) && pAd->monitor_ctrl.current_monitor_mode == MONITOR_MODE_FULL) /* Enable Rx with promiscuous reception */ + Value = 0x3; +#endif + +#ifdef MIXMODE_SUPPORT + if (MONITOR_ON(pAd) && pAd->MixModeCtrl.current_monitor_mode == MIX_MODE_FULL) + Value = 0x10e003; + else if(Value == 0x10e003) + Value = APNORMAL; +#endif + + + RTMP_IO_WRITE32(pAd, RMAC_RFCR, Value); + RTMP_IO_WRITE32(pAd, RMAC_RFCR1, 0); + } + + return TRUE; +} + +INT AsicClearRxFilter(RTMP_ADAPTER *pAd) +{ + UINT32 Value; + if (pAd->chipCap.hif_type == HIF_MT) { + #define MT_RXFILTER_NORMAL 0x001FEF9A + Value = MT_RXFILTER_NORMAL; + RTMP_IO_WRITE32(pAd, RMAC_RFCR, Value); + RTMP_IO_WRITE32(pAd, RMAC_RFCR1, 0); + } + + return TRUE; +} + +#ifdef DOT11_N_SUPPORT +INT AsicWtblSetRDG(RTMP_ADAPTER *pAd, BOOLEAN bEnable) +{ + UINT32 wcid; + MAC_TABLE *pMacTable; + MAC_TABLE_ENTRY *pEntry; + struct wtbl_entry tb_entry; + union WTBL_1_DW2 *dw2 = (union WTBL_1_DW2 *)&tb_entry.wtbl_1.wtbl_1_d2.word; + + pMacTable = &pAd->MacTab; + NdisZeroMemory(&tb_entry, sizeof(tb_entry)); + + /* Search for the Ralink STA */ + for (wcid = 1; wcid < MAX_LEN_OF_MAC_TABLE; wcid++) + { + pEntry = &pMacTable->Content[wcid]; + + if (CLIENT_STATUS_TEST_FLAG(pEntry, fCLIENT_STATUS_RALINK_CHIPSET)) + { + if (mt_wtbl_get_entry234(pAd, wcid, &tb_entry) == FALSE) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Cannot found WTBL2/3/4 for WCID(%d)\n", + __FUNCTION__, wcid)); + return FALSE; + } + + RTMP_IO_READ32(pAd, tb_entry.wtbl_addr[0] + (2 * 4), &dw2->word); + + if (bEnable) + { + dw2->field.r = 1; + dw2->field.rdg_ba = 1; + } + else + { + dw2->field.r = 0; + dw2->field.rdg_ba = 0; + } + + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + (2 * 4), dw2->word); + } + } + + return TRUE; +} + + +INT AsicSetRDG(RTMP_ADAPTER *pAd, BOOLEAN bEnable) +{ + UINT32 tmac_tcr, agg_pcr, tmac_trcr; + + + RTMP_IO_READ32(pAd, TMAC_TCR, &tmac_tcr); + RTMP_IO_READ32(pAd, AGG_PCR, &agg_pcr); + RTMP_IO_READ32(pAd, TMAC_TRCR, &tmac_trcr); + + + if (bEnable) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); + /* enable RDG Rsp. also w/ Ralink Mode is necessary */ + tmac_tcr |= (RDG_RA_MODE | RDG_RESP_EN); + /* LongNAV protect */ + agg_pcr &= ~(PROTECTION_MODE); + + tmac_trcr = tmac_trcr & ~I2T_CHK_EN; + } + else + { + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE); + /* disable RDG Rsp. also w/ Ralink Mode is necessary */ + tmac_tcr &= ~(RDG_RA_MODE | RDG_RESP_EN); + /* single frame protect */ + agg_pcr |= PROTECTION_MODE; + + tmac_trcr = tmac_trcr | I2T_CHK_EN; + } + + RTMP_IO_WRITE32(pAd, TMAC_TCR, tmac_tcr); + RTMP_IO_WRITE32(pAd, AGG_PCR, agg_pcr); + RTMP_IO_WRITE32(pAd, TMAC_TRCR, tmac_trcr); + + return TRUE; +} +#endif /* DOT11_N_SUPPORT */ + + +/* + ======================================================================== + Routine Description: + Set/reset MAC registers according to bPiggyBack parameter + + Arguments: + pAd - Adapter pointer + bPiggyBack - Enable / Disable Piggy-Back + + Return Value: + None + + ======================================================================== +*/ +VOID RTMPSetPiggyBack(RTMP_ADAPTER *pAd, BOOLEAN bPiggyBack) +{ + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + } + + return; +} + + +#define INT_TIMER_EN_PRE_TBTT 0x1 +#define INT_TIMER_EN_GP_TIMER 0x2 +static INT AsicSetIntTimerEn(RTMP_ADAPTER *pAd, BOOLEAN enable, UINT32 type, UINT32 timeout) +{ + +return 0; + +} + + +INT AsicSetPreTbtt(RTMP_ADAPTER *pAd, BOOLEAN enable) +{ + UINT32 timeout = 0, bitmask = 0; + INT bss_idx = 0; // TODO: this index may carried by parameters! + + ASSERT(bss_idx <= 3); + bitmask = 0xff << (bss_idx * 8); + + if (enable == TRUE) { + /* + each HW BSSID has its own PreTBTT interval, + unit is 64us, 0x00~0xff is configurable. + Base on RTMP chip experience, + Pre-TBTT is 6ms before TBTT interrupt. 1~10 ms is reasonable. + */ + + + RTMP_IO_READ32(pAd, LPON_PISR, &timeout); + timeout &= (~bitmask); + timeout |= (0xa0 << (bss_idx * 8)); + RTMP_IO_WRITE32(pAd, LPON_PISR, timeout); + + DBGPRINT(RT_DEBUG_OFF, ("%s(): bss_idx=%d, PreTBTT timeout = 0x%x\n", + __FUNCTION__, bss_idx, timeout)); + } + else { + RTMP_IO_READ32(pAd, LPON_PISR, &timeout); + timeout &= (~bitmask); + RTMP_IO_WRITE32(pAd, LPON_PISR, timeout); + DBGPRINT(RT_DEBUG_OFF, ("%s(): bss_idx=%d, PreTBTT timeout = 0x%x\n", + __FUNCTION__, bss_idx, timeout)); + } + + return TRUE; +} + + +INT AsicSetGPTimer(RTMP_ADAPTER *pAd, BOOLEAN enable, UINT32 timeout) +{ + return AsicSetIntTimerEn(pAd, enable, INT_TIMER_EN_GP_TIMER, timeout); +} + + +INT AsicSetChBusyStat(RTMP_ADAPTER *pAd, BOOLEAN enable) +{ + //UINT32 mac_val; + + /* Note: if bit 0 == 0, the function will be disabled */ + if (enable) { + /* + Count EIFS, NAV, RX busy, TX busy as channel busy and + enable Channel statistic timer (bit 0) + */ + //mac_val = 0x0000001F; + } + else + //mac_val = 0x0; + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + } + + + return TRUE; +} + + +INT AsicGetTsfTime(RTMP_ADAPTER *pAd, UINT32 *high_part, UINT32 *low_part) +{ + UINT32 Value = 0; + RTMP_IO_READ32(pAd, LPON_T0CR, &Value); + Value = (Value & 0xc) | TSF_TIMER_VALUE_READ;//keep HW mode value. + //Value = Value | TSF_TIMER_VALUE_READ; + RTMP_IO_WRITE32(pAd, LPON_T0CR, Value); + + RTMP_IO_READ32(pAd, LPON_UTTR0, low_part); + RTMP_IO_READ32(pAd, LPON_UTTR1, high_part); + + return TRUE; +} + + +#ifdef LINUX +#ifdef RTMP_WLAN_HOOK_SUPPORT +EXPORT_SYMBOL(AsicGetTsfTime); +#endif /* RTMP_WLAN_HOOK_SUPPORT */ +#endif /* LINUX */ + + +#ifdef CONFIG_AP_SUPPORT +static UCHAR check_point_num = 0; +static UCHAR pse_rst_counter = 0; + +static VOID DumpBcnQMessage(RTMP_ADAPTER *pAd, INT apidx) +{ + int j = 0; + //BSS_STRUCT *pMbss; + UINT32 tmp_value = 0, hif_br_start_base = 0x4540; + CHAR tmp[5]; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) { + return; + } + + //pMbss = &pAd->ApCfg.MBSSID[apidx]; + + DBGPRINT(RT_DEBUG_ERROR, ("hif cr dump:\n")); + for (j = 0; j < 80; j++) + { + RTMP_IO_READ32(pAd, (hif_br_start_base + (j * 4)), &tmp_value); + DBGPRINT(RT_DEBUG_ERROR, ("CR:0x%x=%x\t", (hif_br_start_base + (j * 4)), tmp_value)); + if ((j % 4) == 3) + DBGPRINT(RT_DEBUG_ERROR, ("\n")); + } + + DBGPRINT(RT_DEBUG_ERROR, ("\ncheck PSE Q:\n")); + for (j = 0; j <= 8; j++) { + sprintf(tmp,"%d",j); + set_get_fid(pAd, tmp); + } + + DBGPRINT(RT_DEBUG_ERROR, ("check TX_START and SLOT_IDLE\n")); + for (j = 0; j < 10; j++) { + RTMP_IO_READ32(pAd, ARB_BCNQCR0, &tmp_value); + DBGPRINT(RT_DEBUG_ERROR, ("ARB_BCNQCR0: %x\n", tmp_value)); + } +#ifdef DBG + if (RT_DEBUG_ERROR <= RTDebugLevel) { + Show_PSTable_Proc(pAd,""); + ShowPseInfo(pAd,NULL); + show_trinfo_proc(pAd, NULL); + +#ifdef RTMP_PCI_SUPPORT +/* Dump PDMA debug CR */ +{ + UINT32 value0,value1,value2,value3,value4,value5,value6,value7,value8,value9; + RTMP_IO_WRITE32(pAd,0x4244,0x08000000 ); + RTMP_IO_READ32(pAd, 0x4244, &value0); + //read 3 more times + RTMP_IO_READ32(pAd, 0x4244, &value0); + RTMP_IO_READ32(pAd, 0x4244, &value0); + RTMP_IO_READ32(pAd, 0x4244, &value0); + + + RTMP_IO_WRITE32(pAd,0x4244,0x18000000 ); + RTMP_IO_READ32(pAd, 0x4244, &value1); + //read 3 more times + RTMP_IO_READ32(pAd, 0x4244, &value1); + RTMP_IO_READ32(pAd, 0x4244, &value1); + RTMP_IO_READ32(pAd, 0x4244, &value1); + + RTMP_IO_WRITE32(pAd,0x4244,0x28000000 ); + RTMP_IO_READ32(pAd, 0x4244, &value2); + //read 3 more times + RTMP_IO_READ32(pAd, 0x4244, &value2); + RTMP_IO_READ32(pAd, 0x4244, &value2); + RTMP_IO_READ32(pAd, 0x4244, &value2); + + RTMP_IO_WRITE32(pAd,0x4244,0x38000000 ); + RTMP_IO_READ32(pAd, 0x4244, &value3); + //read 3 more times + RTMP_IO_READ32(pAd, 0x4244, &value3); + RTMP_IO_READ32(pAd, 0x4244, &value3); + RTMP_IO_READ32(pAd, 0x4244, &value3); + + RTMP_IO_WRITE32(pAd,0x4244,0x48000000 ); + RTMP_IO_READ32(pAd, 0x4244, &value4); + //read 3 more times + RTMP_IO_READ32(pAd, 0x4244, &value4); + RTMP_IO_READ32(pAd, 0x4244, &value4); + RTMP_IO_READ32(pAd, 0x4244, &value4); + + RTMP_IO_WRITE32(pAd,0x4244,0x58000000 ); + RTMP_IO_READ32(pAd, 0x4244, &value5); + //read 3 more times + RTMP_IO_READ32(pAd, 0x4244, &value5); + RTMP_IO_READ32(pAd, 0x4244, &value5); + RTMP_IO_READ32(pAd, 0x4244, &value5); + + RTMP_IO_WRITE32(pAd,0x4244,0x68000000 ); + RTMP_IO_READ32(pAd, 0x4244, &value6); + //read 3 more times + RTMP_IO_READ32(pAd, 0x4244, &value6); + RTMP_IO_READ32(pAd, 0x4244, &value6); + RTMP_IO_READ32(pAd, 0x4244, &value6); + + RTMP_IO_WRITE32(pAd,0x4244,0x78000000 ); + RTMP_IO_READ32(pAd, 0x4244, &value7); + //read 3 more times + RTMP_IO_READ32(pAd, 0x4244, &value7); + RTMP_IO_READ32(pAd, 0x4244, &value7); + RTMP_IO_READ32(pAd, 0x4244, &value7); + + RTMP_IO_WRITE32(pAd,0x4244,0x88000000 ); + RTMP_IO_READ32(pAd, 0x4244, &value8); + //read 3 more times + RTMP_IO_READ32(pAd, 0x4244, &value8); + RTMP_IO_READ32(pAd, 0x4244, &value8); + RTMP_IO_READ32(pAd, 0x4244, &value8); + + RTMP_IO_WRITE32(pAd,0x4244,0x98000000 ); + RTMP_IO_READ32(pAd, 0x4244, &value9); + //read 3 more times + RTMP_IO_READ32(pAd, 0x4244, &value9); + RTMP_IO_READ32(pAd, 0x4244, &value9); + RTMP_IO_READ32(pAd, 0x4244, &value9); + + DBGPRINT(RT_DEBUG_ERROR, ("BEGIN ================================\n")); + DBGPRINT(RT_DEBUG_ERROR, ("mac 4244[0x08000000]=0x%x\n", value0)); + DBGPRINT(RT_DEBUG_ERROR, ("mac 4244[0x18000000]=0x%x\n", value1)); + DBGPRINT(RT_DEBUG_ERROR, ("mac 4244[0x28000000]=0x%x\n", value2)); + DBGPRINT(RT_DEBUG_ERROR, ("mac 4244[0x38000000]=0x%x\n", value3)); + DBGPRINT(RT_DEBUG_ERROR, ("mac 4244[0x48000000]=0x%x\n", value4)); + DBGPRINT(RT_DEBUG_ERROR, ("mac 4244[0x58000000]=0x%x\n", value5)); + DBGPRINT(RT_DEBUG_ERROR, ("mac 4244[0x68000000]=0x%x\n", value6)); + DBGPRINT(RT_DEBUG_ERROR, ("mac 4244[0x78000000]=0x%x\n", value7)); + DBGPRINT(RT_DEBUG_ERROR, ("mac 4244[0x88000000]=0x%x\n", value8)); + DBGPRINT(RT_DEBUG_ERROR, ("mac 4244[0x98000000]=0x%x\n", value9)); + DBGPRINT(RT_DEBUG_ERROR, ("END =================================\n")); +} +#endif /* RTMP_PCI_SUPPORT */ + + } +#endif /*DBG*/ + +#ifdef TXRXCR_DEBUG_SUPPORT + SetTxRxCr_Proc(pAd, "1"); +#endif /* TXRXCR_DEBUG_SUPPORT */ + +} + + +VOID APCheckBcnQHandler(RTMP_ADAPTER *pAd, INT apidx, BOOLEAN *is_pretbtt_int) +{ + UINT32 val=0, temp = 0; + int j = 0; + BSS_STRUCT *pMbss; + //struct wifi_dev *wdev; + + UINT32 Lowpart, Highpart; + UINT32 int_delta; +#ifdef DMA_RESET_SUPPORT + UINT32 bcn_didx_val; + UINT32 mac_val; +#endif + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) + return; + + pMbss = &pAd->ApCfg.MBSSID[apidx]; + //wdev = &pMbss->wdev; + + if (pMbss->bcn_buf.bcn_state < BCN_TX_DMA_DONE) { + if (apidx == 0) { +#ifdef DMA_RESET_SUPPORT + if (pAd->bcn_reset_en && pAd->pse_reset_flag) + { + check_point_num=0; + return; + } +#endif /* DMA_RESET_SUPPORT */ + check_point_num++; + +#ifdef DMA_RESET_SUPPORT + if ((pAd->bcn_reset_en) && (check_point_num > 4) && (pAd->bcn_not_idle_tx_dma_busy)) + { + RTMP_IO_READ32(pAd, MT_WPDMA_GLO_CFG, &mac_val); + RTMP_IO_READ32(pAd, pAd->BcnRing.hw_didx_addr, &bcn_didx_val); + + if ((mac_val & 0x2) && (bcn_didx_val == pAd->bcn_didx_val)) + { + pAd->dma_force_reset_count++; + pAd->bcn_not_idle_tx_dma_busy=0; + pAd->pse_reset_flag=TRUE; + pAd->bcn_didx_val = 255; + check_point_num=0; + } + else + { + pAd->bcn_not_idle_tx_dma_busy=0; + pAd->bcn_didx_val = 255; + } + } +#endif /* DMA_RESET_SUPPORT */ + + if (check_point_num > 10) { + DumpBcnQMessage(pAd, apidx); + + DBGPRINT(RT_DEBUG_ERROR, + ("%s(line:%d):bcn_state = %d, pse_rst_counter=%d\n", + __func__, __LINE__, pMbss->bcn_buf.bcn_state, pse_rst_counter)); +#ifdef DMA_RESET_SUPPORT + if (pAd->bcn_reset_en) + { + RTMP_IO_READ32(pAd, MT_WPDMA_GLO_CFG, &mac_val); + if (mac_val & 0x2) + { + pAd->bcn_not_idle_tx_dma_busy=1; + RTMP_IO_READ32(pAd, pAd->BcnRing.hw_didx_addr, &pAd->bcn_didx_val); + } + else + { + pAd->bcn_not_idle_tx_dma_busy=0; + pAd->bcn_didx_val = 255; + } + } +#endif /* DMA_RESET_SUPPORT */ + pse_rst_counter++; + + if (pse_rst_counter >= 3) { + pAd->pse_reset_flag = TRUE; + pse_rst_counter = 0; + } + check_point_num = 0; + } +#ifdef TXRXCR_DEBUG_SUPPORT + else if (check_point_num == 7) { + SetTxRxCr_Proc(pAd, "0"); + } +#endif /* TXRXCR_DEBUG_SUPPORT */ + + } + return; + } else if (apidx == 0) { + check_point_num = 0; + pse_rst_counter = 0; +#ifdef DMA_RESET_SUPPORT + pAd->bcn_not_idle_tx_dma_busy=0; + pAd->bcn_didx_val = 255; +#endif + } + + AsicGetTsfTime(pAd, &Highpart, &Lowpart); + int_delta = Lowpart - pMbss->WriteBcnDoneTime[pMbss->timer_loop]; + if (int_delta < (pAd->CommonCfg.BeaconPeriod * 1024/* unit is usec */)) + { + /* update beacon has been called more than once in 1 bcn period, + it might be called other than HandlePreTBTT interrupt routine.*/ + *is_pretbtt_int = FALSE; + return; + } + + if (pMbss->bcn_not_idle_time % 10 == 9) { + pMbss->bcn_not_idle_time = 0; + + if (apidx == 0) { + DumpBcnQMessage(pAd, apidx); + DBGPRINT(RT_DEBUG_ERROR, ("%s(line:%d):bcn_buf->bcn_state = %d\n", + __func__, __LINE__, pMbss->bcn_buf.bcn_state)); + } + + *is_pretbtt_int = FALSE; + return; + } + else if (pMbss->bcn_not_idle_time % 3 == 2) { + pMbss->bcn_not_idle_time++; + pMbss->bcn_recovery_num++; + *is_pretbtt_int = TRUE; + } +#ifdef TXRXCR_DEBUG_SUPPORT + else if (pMbss->bcn_not_idle_time % 10 == 7) { + SetTxRxCr_Proc(pAd, "0"); + } +#endif /* TXRXCR_DEBUG_SUPPORT */ + else { + pMbss->bcn_not_idle_time++; + *is_pretbtt_int = FALSE; + return; + } + + if (apidx > 0) + val = val | (1 << (apidx+15)); + else + val = 1; + + j = 0; + /* Flush Beacon Queue */ + RTMP_IO_WRITE32(pAd, ARB_BCNQCR1, val); + while (1) { + RTMP_IO_READ32(pAd, ARB_BCNQCR1, &temp);//check bcn_flush cr status + if (temp & val) { + j++; + OS_WAIT(1); + if (j > 1000) { + printk("%s, bcn_flush too long!, j = %x\n", __func__, j); + break; + } + } + else { + break; + } + } + + val = 0xa8c70000; + j = 0; + temp = 0; + if (apidx > 0) + val = val | 0x1000 | (apidx << 8); + + RTMP_IO_WRITE32(pAd, 0x21c08, val);//flush all stuck bcn + + while (1) { + RTMP_IO_READ32(pAd, 0x21c08, &temp);//flush all stuck bcn + if (temp >> 31) { + j++; + OS_WAIT(1); + if (j > 1000) { + printk("%s, flush all stuck bcn too long!! j = %x\n", __func__, j); + break; + } + } + else { + break; + } + } + + //check filter resilt + RTMP_IO_READ32(pAd, 0x21c0c, &temp); + DBGPRINT(RT_DEBUG_ERROR, ("flush result = %x\n", temp)); + DBGPRINT(RT_DEBUG_ERROR, ("check pse fid Q7:")); + set_get_fid(pAd, "7"); + + val = 0; + if (apidx > 0) + val = val | (1 << (apidx+15)); + else + val = 1; + + RTMP_IO_READ32(pAd, ARB_BCNQCR0, &temp);//re-enable bcn_start + temp = temp | val; + RTMP_IO_WRITE32(pAd, ARB_BCNQCR0, temp); + + pMbss->bcn_buf.bcn_state = BCN_TX_IDLE; +} + + +#endif /* CONFIG_AP_SUPPORT */ + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicDisableSync(RTMP_ADAPTER *pAd) +{ + UINT32 value; + DBGPRINT(RT_DEBUG_TRACE, ("--->Disable TSF synchronization\n")); + + pAd->TbttTickCount = 0; + + if (pAd->chipCap.hif_type == HIF_MT) { +#ifdef CONFIG_AP_SUPPORT + //INT32 IdBss, MaxNumBss = pAd->ApCfg.BssidNum; + + /* Disable PreTBTT/TBTT interrupt for inform host */ + value = 0; + RTMP_IO_WRITE32(pAd, HWIER3, value); + + return; +#endif /* CONFIG_AP_SUPPORT */ + + + } +} + + + +VOID AsicEnableBssSync(RTMP_ADAPTER *pAd, USHORT BeaconPeriod) +{ + UINT32 bitmask = 0; + UINT32 Value; + INT bss_idx = 0; // TODO: this index may carried by parameters! + + DBGPRINT(RT_DEBUG_TRACE, ("--->%s():\n", __FUNCTION__)); + + /* Configure Beacon interval */ + RTMP_IO_READ32(pAd, LPON_T0TPCR, &Value); + Value = 0; + Value &= ~BEACONPERIODn_MASK; + Value |= BEACONPERIODn(BeaconPeriod); + Value |= TBTTn_CAL_EN; + RTMP_IO_WRITE32(pAd, LPON_T0TPCR, Value); + + /* Enable Pre-TBTT Trigger, and calcuate next TBTT timer by HW*/ + //enable PRETBTT0INT_EN, PRETBTT0TIMEUP_EN + //and TBTT0PERIODTIMER_EN, TBTT0TIMEUP_EN + RTMP_IO_WRITE32(pAd, LPON_MPTCR0, 0x99);//TODO: TBTT1, TBTT2. + + /* Set Pre-TBTT interval */ + /* + each HW BSSID has its own PreTBTT interval, + unit is 64us, 0x00~0xff is configurable. + Base on RTMP chip experience, + Pre-TBTT is 6ms before TBTT interrupt. 1~10 ms is reasonable. + */ + ASSERT(bss_idx <= 3); + bitmask = 0xff << (bss_idx * 8); + RTMP_IO_READ32(pAd, LPON_PISR, &Value); + Value &= (~bitmask); + Value |= (0x50 << (bss_idx * 8)); + //mac_val =0x50505050; + RTMP_IO_WRITE32(pAd, LPON_PISR, Value); + + /* Enable interrupt */ + RTMP_IO_READ32(pAd, HWIER3, &Value); + Value = 0; + Value |= TBTT0; + Value |= PRETBTT0; + RTMP_IO_WRITE32(pAd, HWIER3, Value); + + /* Config BCN/BMC timoeut, or the normal Tx wil be blocked forever if no beacon frame in Queue */ + Value = 0x01800180; + //RTMP_IO_WRITE32(pAd, LPON_BCNTR, mac_val); + + /* Configure Beacon Queue Operation mode */ + RTMP_IO_READ32(pAd, ARB_SCR, &Value); + + Value &= (~(ARB_SCR_TBTT_BCN_CTRL)); // work-around to make BCN need to content with other ACs + Value |= ARB_SCR_TBTT_BM_CTRL; + Value |= ARB_SCR_BCNQ_EMPTY_CTRL; + Value |= BCNQ_OP_MODE_AP;//TODO, Carter, when use other HWBSSID, shall could choose index to set correcorresponding bit. + //Value = Value & 0xefffffff; + RTMP_IO_WRITE32(pAd, ARB_SCR, Value); + + /* Start Beacon Queue */ + RTMP_IO_READ32(pAd, ARB_BCNQCR0, &Value); + Value |= 0x1; + RTMP_IO_WRITE32(pAd, ARB_BCNQCR0, Value); +} + +/* YF: Generate Beacon using HW1 */ +VOID AsicEnableApBssSync(RTMP_ADAPTER *pAd, USHORT BeaconPeriod) +{ + UINT32 bitmask = 0; + UINT32 Value; + INT bss_idx = 0; // TODO: this index may carried by parameters! + DBGPRINT(RT_DEBUG_TRACE, ("--->%s():\n", __FUNCTION__)); + +#ifdef CONFIG_AP_SUPPORT + //INT32 IdBss, MaxNumBss = pAd->ApCfg.BssidNum; +#endif /* CONFIG_AP_SUPPORT */ + + /* Configure Beacon interval */ + RTMP_IO_READ32(pAd, LPON_T1TPCR, &Value); + Value = 0; + Value &= ~BEACONPERIODn_MASK; + Value |= BEACONPERIODn(BeaconPeriod); + Value |= TBTTn_CAL_EN; + RTMP_IO_WRITE32(pAd, LPON_T1TPCR, Value); + + /* Enable Pre-TBTT Trigger, and calcuate next TBTT timer by HW*/ + //enable PRETBTT0INT_EN, PRETBTT0TIMEUP_EN + //and TBTT0PERIODTIMER_EN, TBTT0TIMEUP_EN + RTMP_IO_WRITE32(pAd, LPON_MPTCR0, 0x9900);//TODO: TBTT1, TBTT2. + + /* + Set Pre-TBTT interval : + each HW BSSID has its own PreTBTT interval, + unit is 64us, 0x00~0xff is configurable. + Base on RTMP chip experience, + Pre-TBTT is 6ms before TBTT interrupt. 1~10 ms is reasonable. + */ + ASSERT(bss_idx <= 3); + bitmask = 0xff << (bss_idx * 8); + RTMP_IO_READ32(pAd, LPON_PISR, &Value); + Value &= (~bitmask); + Value |= (0x50 << (bss_idx * 8)); + //mac_val =0x50505050; + RTMP_IO_WRITE32(pAd, LPON_PISR, Value); + + /* Enable interrupt */ + RTMP_IO_READ32(pAd, HWIER3, &Value); + Value = 0; + Value |= TBTT0; + Value |= PRETBTT0; + RTMP_IO_WRITE32(pAd, HWIER3, Value); + + /* Config BCN/BMC timoeut, or the normal Tx wil be blocked forever if no beacon frame in Queue */ + Value = 0x01800180; + //RTMP_IO_WRITE32(pAd, LPON_BCNTR, mac_val); + + /* Configure Beacon Queue Operation mode */ + RTMP_IO_READ32(pAd, ARB_SCR, &Value); + + Value &= (~(1<<30)); // work-around to make BCN need to content with other ACs + Value &= (~(1<<31)); // work-around to make BMC need to content with other ACs - 20140109 discussion. + Value |= (BCNQ_OP_MODE_AP << 2);//TODO, Carter, when use other HWBSSID, shall could choose index to set correcorresponding bit. + //Value = Value & 0xefffffff; + RTMP_IO_WRITE32(pAd, ARB_SCR, Value); + + /* Start Beacon Queue */ + RTMP_IO_READ32(pAd, ARB_BCNQCR0, &Value); + Value |= 0x2; + RTMP_IO_WRITE32(pAd, ARB_BCNQCR0, Value); +} + + + + +typedef struct _RTMP_WMM_PAIR { + UINT32 Address; + UINT32 Mask; + UINT32 Shift; +} RTMP_WMM_PAIR, *PRTMP_WMM_PAIR; + + +static RTMP_WMM_PAIR wmm_txop_mask[] = { + {TMAC_ACTXOPLR1, 0x0000ffff, 0}, /* AC0 - BK */ + {TMAC_ACTXOPLR1, 0xffff0000, 16}, /* AC1 - BE */ + {TMAC_ACTXOPLR0, 0x0000ffff, 0}, /* AC2 - VI */ + {TMAC_ACTXOPLR0, 0xffff0000, 16}, /* AC3 - VO */ +}; + + +static RTMP_WMM_PAIR wmm_aifsn_mask[] = { + {ARB_AIFSR0, 0x0000000f, 0}, /* AC0 - BK */ + {ARB_AIFSR0, 0x000000f0, 4}, /* AC1 - BE */ + {ARB_AIFSR0, 0x00000f00, 8}, /* AC2 - VI */ + {ARB_AIFSR0, 0x0000f000, 12}, /* AC3 - VO */ +}; + +static RTMP_WMM_PAIR wmm_cwmin_mask[] = { + {ARB_ACCWIR0, 0x000000ff, 0}, /* AC0 - BK */ + {ARB_ACCWIR0, 0x0000ff00, 8}, /* AC1 - BE */ + {ARB_ACCWIR0, 0x00ff0000, 16}, /* AC2 - VI */ + {ARB_ACCWIR0, 0xff000000, 24}, /* AC3 - VO */ +}; + +static RTMP_WMM_PAIR wmm_cwmax_mask[] = { + {ARB_ACCWXR0, 0x0000ffff, 0}, /* AC0 - BK */ + {ARB_ACCWXR0, 0xffff0000, 16}, /* AC1 - BE */ + {ARB_ACCWXR1, 0x0000ffff, 0}, /* AC2 - VI */ + {ARB_ACCWXR1, 0xffff0000, 16}, /* AC3 - VO */ +}; + + +UINT32 AsicGetWmmParam(RTMP_ADAPTER *pAd, UINT32 ac, UINT32 type) +{ + UINT32 addr = 0, cr_val, mask = 0, shift; + + if (ac <= WMM_PARAM_AC_3) + { + switch (type) + { + case WMM_PARAM_TXOP: + addr = wmm_txop_mask[ac].Address; + mask = wmm_txop_mask[ac].Mask; + shift = wmm_txop_mask[ac].Shift; + break; + case WMM_PARAM_AIFSN: + addr = wmm_aifsn_mask[ac].Address; + mask = wmm_aifsn_mask[ac].Mask; + shift = wmm_aifsn_mask[ac].Shift; + break; + case WMM_PARAM_CWMIN: + addr = wmm_cwmin_mask[ac].Address; + mask = wmm_cwmin_mask[ac].Mask; + shift = wmm_cwmin_mask[ac].Shift; + break; + case WMM_PARAM_CWMAX: + addr = wmm_cwmax_mask[ac].Address; + mask = wmm_cwmax_mask[ac].Mask; + shift = wmm_cwmax_mask[ac].Shift; + break; + default: + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Error type=%d\n", __FUNCTION__, __LINE__, type)); + break; + } + } + + if (addr && mask) + { + RTMP_IO_READ32(pAd, addr, &cr_val); + cr_val = (cr_val & mask) >> shift; + + return cr_val; + } + + return 0xdeadbeef; +} + + +INT AsicSetWmmParam(RTMP_ADAPTER *pAd, UINT ac, UINT type, UINT val) +{ + CMD_EDCA_SET_T EdcaParam; + P_TX_AC_PARAM_T pAcParam; + + NdisZeroMemory(&EdcaParam,sizeof(CMD_EDCA_SET_T)); + EdcaParam.ucTotalNum = 1; + pAcParam = &EdcaParam.rAcParam[0]; + pAcParam->ucAcNum = ac; + + switch (type) { + case WMM_PARAM_TXOP: + pAcParam->ucVaildBit = CMD_EDCA_TXOP_BIT; + pAcParam->u2Txop= val; + break; + case WMM_PARAM_AIFSN: + pAcParam->ucVaildBit = CMD_EDCA_AIFS_BIT; + pAcParam->ucAifs = val; + break; + case WMM_PARAM_CWMIN: + pAcParam->ucVaildBit = CMD_EDCA_WIN_MIN_BIT; + pAcParam->ucWinMin= val; + break; + case WMM_PARAM_CWMAX: + pAcParam->ucVaildBit = CMD_EDCA_WIN_MAX_BIT; + pAcParam->u2WinMax= val; + break; + default: + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Error type=%d\n", __FUNCTION__, __LINE__, type)); + break; + } + + NdisCopyMemory(&pAd->CurrEdcaParam[ac], pAcParam, sizeof(TX_AC_PARAM_T)); + +#ifdef RT_BIG_ENDIAN + pAcParam->u2WinMax=cpu2le16(pAcParam->u2WinMax); + pAcParam->u2Txop=cpu2le16(pAcParam->u2Txop); + +#endif + + CmdEdcaParameterSet(pAd,EdcaParam); + + return TRUE; +} + + +INT AsicSetAllWmmParam(RTMP_ADAPTER *pAd,PEDCA_PARM pEdcaParm) +{ + CMD_EDCA_SET_T EdcaParam; + P_TX_AC_PARAM_T pAcParam; + UINT32 ac=0,index=0;; + + NdisZeroMemory(&EdcaParam,sizeof(CMD_EDCA_SET_T)); + EdcaParam.ucTotalNum = CMD_EDCA_AC_MAX; + + for ( ac=0; ac < CMD_EDCA_AC_MAX; ac++) + { + index = wmm_aci_2_hw_ac_queue[ac]; + pAcParam = &EdcaParam.rAcParam[index]; + pAcParam->ucVaildBit = CMD_EDCA_ALL_BITS; + pAcParam->ucAcNum = ac; + pAcParam->ucAifs = pEdcaParm->Aifsn[index]; + pAcParam->ucWinMin= (1 << pEdcaParm->Cwmin[index]) -1; + pAcParam->u2WinMax= (1 << pEdcaParm->Cwmax[index]) -1; + pAcParam->u2Txop= pEdcaParm->Txop[index]; + + NdisCopyMemory(&pAd->CurrEdcaParam[index], pAcParam, sizeof(TX_AC_PARAM_T)); + +#ifdef RT_BIG_ENDIAN + pAcParam->u2WinMax=cpu2le16(pAcParam->u2WinMax); + pAcParam->u2Txop=cpu2le16(pAcParam->u2Txop); +#endif + + } + CmdEdcaParameterSet(pAd,EdcaParam); + + return TRUE; +} + + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSetEdcaParm(RTMP_ADAPTER *pAd, PEDCA_PARM pEdcaParm) +{ + int i; + + if ((pEdcaParm == NULL) || (pEdcaParm->bValid == FALSE)) + { + DBGPRINT(RT_DEBUG_TRACE,("AsicSetEdcaParm\n")); + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_WMM_INUSED); + for (i=0; i < MAX_LEN_OF_MAC_TABLE; i++) + { + if (IS_ENTRY_CLIENT(&pAd->MacTab.Content[i]) || IS_ENTRY_APCLI(&pAd->MacTab.Content[i])) + CLIENT_STATUS_CLEAR_FLAG(&pAd->MacTab.Content[i], fCLIENT_STATUS_WMM_CAPABLE); + } + + NdisZeroMemory(&pAd->CommonCfg.APEdcaParm, sizeof(EDCA_PARM)); + + } + else + { + OPSTATUS_SET_FLAG(pAd, fOP_STATUS_WMM_INUSED); + + + 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])); + } + + if (pAd->chipCap.hif_type == HIF_MT) + { + AsicSetAllWmmParam(pAd,pEdcaParm); + } + } + // TODO: shiang-MT7603, fix me after BurstMode is finished! +} + + + +#ifdef CONFIG_AP_SUPPORT +/* + Wirte non-zero value to AC0 TXOP to boost performace + To pass WMM, AC0 TXOP must be zero. + It is necessary to turn AC0 TX_OP dynamically. +*/ +VOID dynamic_tune_be_tx_op(RTMP_ADAPTER *pAd, ULONG nonBEpackets) +{ + //UINT32 RegValue; + //AC_TXOP_CSR0_STRUC csr0; + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { +// DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", +// __FUNCTION__, __LINE__)); + } + + return; +} +#endif /* CONFIG_AP_SUPPORT */ + + +INT AsicSetRetryLimit(RTMP_ADAPTER *pAd, UINT32 type, UINT32 limit) +{ + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + } + + return FALSE; +} + + +UINT32 AsicGetRetryLimit(RTMP_ADAPTER *pAd, UINT32 type) +{ + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + } + + return 0; +} + + +/* + ========================================================================== + Description: + + IRQL = PASSIVE_LEVEL + IRQL = DISPATCH_LEVEL + + ========================================================================== + */ +VOID AsicSetSlotTime( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bUseShortSlotTime, + IN UCHAR channel) +{ + UINT32 SlotTime, SifsTime; + + + 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; + + + + /* For some reasons, always set it to short slot time.*/ + /* ToDo: Should consider capability with 11B*/ + + + + if (channel > 14) + SifsTime = SIFS_TIME_5G; + else + SifsTime = SIFS_TIME_24G; + + CmdSlotTimeSet(pAd,SlotTime,SifsTime,RIFS_TIME,EIFS_TIME); + + + DBGPRINT(RT_DEBUG_TRACE, ("%s: SlotTime =%u us, SIFS Time = %u us,\ + RIFS Time = %d, EIFS Time = %d\n",\ + __FUNCTION__, SlotTime, SifsTime, RIFS_TIME, EIFS_TIME)); +} + + +#define MAX_RX_PKT_LENGTH 0x400 /* WORD(4 Bytes) unit */ +INT AsicSetMacMaxLen(RTMP_ADAPTER *pAd) +{ + // TODO: shiang-7603 + UINT32 val; + + // Rx max packet length + RTMP_IO_READ32(pAd, DMA_DCR0, &val); + val &= (~0xfffc); + val |= (MAX_RX_PKT_LENGTH << 2); + RTMP_IO_WRITE32(pAd, DMA_DCR0, val); + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Set the Max RxPktLen=%d!\n", + __FUNCTION__, __LINE__, MAX_RX_PKT_LENGTH)); + + return TRUE; +} + + +#ifdef CONFIG_AP_SUPPORT +VOID RTMPGetTxTscFromAsic(RTMP_ADAPTER *pAd, UCHAR apidx, UCHAR *pTxTsc) +{ + USHORT Wcid; + USHORT offset; + UCHAR IvEiv[8]; + INT i; + + /* Sanity check of apidx */ + if (apidx >= MAX_MBSSID_NUM(pAd)) + { + DBGPRINT(RT_DEBUG_ERROR, ("RTMPGetTxTscFromAsic : invalid apidx(%d)\n", apidx)); + return; + } + + if (pAd->chipCap.hif_type == HIF_MT) { + struct wtbl_entry tb_entry; + UINT32 addr = 0, val = 0; + + GET_GroupKey_WCID(pAd, Wcid, apidx); + NdisZeroMemory(&tb_entry, sizeof(tb_entry)); + if (mt_wtbl_get_entry234(pAd, Wcid, &tb_entry) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Cannot found WTBL2/3/4 for WCID(%d)\n", + __FUNCTION__, Wcid)); + return; + } + addr = pAd->mac_ctrl.wtbl_base_addr[1] + Wcid * pAd->mac_ctrl.wtbl_entry_size[1]; + RTMP_IO_READ32(pAd, addr, &val); + + *pTxTsc = val & 0xff; + *(pTxTsc+1) = (val >> 8) & 0xff; + *(pTxTsc+2) = (val >> 16) & 0xff; + *(pTxTsc+3) = (val >> 24) & 0xff; + + RTMP_IO_READ32(pAd, addr+4, &val); + *(pTxTsc+4) = val & 0xff; + *(pTxTsc+5) = (val >> 8) & 0xff; + + DBGPRINT(RT_DEBUG_INFO, ("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))); + + return; + } + + /* Initial value */ + NdisZeroMemory(IvEiv, 8); + NdisZeroMemory(pTxTsc, 6); + + /* Get apidx for this BSSID */ + GET_GroupKey_WCID(pAd, Wcid, apidx); + + /* When the group rekey action is triggered, a count-down(3 seconds) is started. + During the count-down, use the initial PN as TSC. + Otherwise, get the IVEIV from ASIC. */ + if (pAd->ApCfg.MBSSID[apidx].RekeyCountDown > 0) + { + /* + In IEEE 802.11-2007 8.3.3.4.3 described : + The PN shall be implemented as a 48-bit monotonically incrementing + non-negative integer, initialized to 1 when the corresponding + temporal key is initialized or refreshed. */ + IvEiv[0] = 1; + } + else + { + UINT32 temp1, temp2; + UINT32 iveiv_tb_base = 0, iveiv_tb_size = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + iveiv_tb_base = RLT_MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = RLT_HW_IVEIV_ENTRY_SIZE; + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + iveiv_tb_base = MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = HW_IVEIV_ENTRY_SIZE; + } +#endif /* RTMP_MAC */ + /* Read IVEIV from Asic */ + offset = iveiv_tb_base + (Wcid * iveiv_tb_size); + + /* Use Read32 to avoid endian problem */ + RTMP_IO_READ32(pAd, offset, &temp1); + RTMP_IO_READ32(pAd, offset+4, &temp2); + for ( i=0; i<4; i++) + { + IvEiv[i] = (UCHAR)(temp1 >> (i*8)); + IvEiv[i+4] = (UCHAR)(temp2 >> (i*8)); + } + } + + /* Record current TxTsc */ + if (pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus == Ndis802_11AESEnable) + { /* AES */ + *pTxTsc = IvEiv[0]; + *(pTxTsc+1) = IvEiv[1]; + *(pTxTsc+2) = IvEiv[4]; + *(pTxTsc+3) = IvEiv[5]; + *(pTxTsc+4) = IvEiv[6]; + *(pTxTsc+5) = IvEiv[7]; + } + else + { /* TKIP */ + *pTxTsc = IvEiv[2]; + *(pTxTsc+1) = IvEiv[0]; + *(pTxTsc+2) = IvEiv[4]; + *(pTxTsc+3) = IvEiv[5]; + *(pTxTsc+4) = IvEiv[6]; + *(pTxTsc+5) = IvEiv[7]; + } + DBGPRINT(RT_DEBUG_TRACE, ("RTMPGetTxTscFromAsic : WCID(%d) TxTsc 0x%02x-0x%02x-0x%02x-0x%02x-0x%02x-0x%02x \n", + Wcid, *pTxTsc, *(pTxTsc+1), *(pTxTsc+2), *(pTxTsc+3), *(pTxTsc+4), *(pTxTsc+5))); + + +} +#endif /* CONFIG_AP_SUPPORT */ + + +/* + ======================================================================== + Description: + Add Shared key information into ASIC. + Update shared key, TxMic and RxMic to Asic Shared key table + Update its cipherAlg to Asic Shared key Mode. + + Return: + ======================================================================== +*/ +VOID AsicAddSharedKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIndex, + IN UCHAR KeyIdx, + IN PCIPHER_KEY pCipherKey) +{ + ULONG offset; /*, csr0;*/ + //SHAREDKEY_MODE_STRUC csr1; +#if defined(RLT_MAC) || defined(RTMP_MAC) + UCHAR org_bssindex = BssIndex; +#endif /* defined(RLT_MAC) || defined(RTMP_MAC) */ +#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)); + + //org_bssindex = BssIndex; + if (BssIndex >= 8) + BssIndex -= 8; + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return; + } + + { + /* fill key material - key + TX MIC + RX MIC*/ + UINT32 share_key_base = 0, share_key_size = 0; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + if (org_bssindex >= 8) + share_key_base = RLT_SHARED_KEY_TABLE_BASE_EXT; + else + share_key_base = RLT_SHARED_KEY_TABLE_BASE; + share_key_size = RLT_HW_KEY_ENTRY_SIZE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + if (org_bssindex >= 8) + share_key_base = SHARED_KEY_TABLE_BASE_EXT; + else + share_key_base = SHARED_KEY_TABLE_BASE; + share_key_size = HW_KEY_ENTRY_SIZE; + } +#endif /* RTMP_MAC */ + + offset = share_key_base + (4*BssIndex + KeyIdx)*share_key_size; +#ifdef RTMP_MAC_PCI + { + for (i=0; ichipCap.hif_type == HIF_RLT) { + if (org_bssindex >= 8) + share_key_mode_base = RLT_SHARED_KEY_MODE_BASE_EXT; + else + share_key_mode_base= RLT_SHARED_KEY_MODE_BASE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + if (org_bssindex >= 8) + share_key_mode_base = SHARED_KEY_MODE_BASE_EXT; + else + share_key_mode_base = SHARED_KEY_MODE_BASE; + } +#endif /* RTMP_MAC */ + + /* Update cipher algorithm. WSTA always use BSS0*/ + //RTMP_IO_READ32(pAd, share_key_mode_base + 4 * (BssIndex/2), &csr1.word); + //DBGPRINT(RT_DEBUG_TRACE,("Read: SHARED_KEY_MODE_BASE at this Bss[%d] KeyIdx[%d]= 0x%x \n", BssIndex,KeyIdx, csr1.word)); + //DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word)); + //RTMP_IO_WRITE32(pAd, share_key_mode_base+ 4 * (BssIndex/2), csr1.word); + } +} + + +/* IRQL = DISPATCH_LEVEL*/ +VOID AsicRemoveSharedKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIndex, + IN UCHAR KeyIdx) +{ + /*ULONG SecCsr0;*/ + //SHAREDKEY_MODE_STRUC csr1; + + DBGPRINT(RT_DEBUG_TRACE,("AsicRemoveSharedKeyEntry: #%d \n", BssIndex*4 + KeyIdx)); + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return; + } + + { + //UINT32 share_key_mode_base = 0; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + share_key_mode_base= RLT_SHARED_KEY_MODE_BASE; +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + share_key_mode_base = SHARED_KEY_MODE_BASE; +#endif /* RTMP_MAC */ + + //DBGPRINT(RT_DEBUG_TRACE,("Write: SHARED_KEY_MODE_BASE at this Bss[%d] = 0x%x \n", BssIndex, csr1.word)); + //RTMP_IO_WRITE32(pAd, share_key_mode_base+4*(BssIndex/2), csr1.word); + } + ASSERT(BssIndex < 4); + ASSERT(KeyIdx < 4); + +} + + +VOID AsicUpdateWCIDIVEIV( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN ULONG uIV, + IN ULONG uEIV) +{ + ULONG offset; + UINT32 iveiv_tb_base = 0, iveiv_tb_size = 0; + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_INFO, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return; + } + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + iveiv_tb_base = RLT_MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = RLT_HW_IVEIV_ENTRY_SIZE; + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + iveiv_tb_base = MAC_IVEIV_TABLE_BASE; + iveiv_tb_size = HW_IVEIV_ENTRY_SIZE; + } +#endif /* RTMP_MAC */ + + offset = iveiv_tb_base + (WCID * iveiv_tb_size); + + RTMP_IO_WRITE32(pAd, offset, uIV); + RTMP_IO_WRITE32(pAd, offset + 4, uEIV); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: wcid(%d) 0x%08lx, 0x%08lx \n", + __FUNCTION__, WCID, uIV, uEIV)); +} + + +/** + * Wtbl2RateTableUpdate + * + * + * + */ +VOID Wtbl2RateTableUpdate(RTMP_ADAPTER *pAd, UCHAR ucWcid, UINT32 u4Wtbl2D9, UINT32* Rate) +{ + WTBL2_RATE_TABLE_UPDATE rWtbl2RateTableUpdate = {0}; + + rWtbl2RateTableUpdate.ucWcid = ucWcid; + rWtbl2RateTableUpdate.u4Wtbl2D9 = u4Wtbl2D9; + RTMPMoveMemory(rWtbl2RateTableUpdate.rate, Rate, sizeof(rWtbl2RateTableUpdate.rate)); + + RTEnqueueInternalCmd(pAd, CMDTHREAD_PERODIC_CR_ACCESS_WTBL_RATE_TABLE_UPDATE, &rWtbl2RateTableUpdate, sizeof(rWtbl2RateTableUpdate)); +} + +//VOID MtCmdWtbl2RateTableUpdate(RTMP_ADAPTER *pAd, UCHAR ucWcid, UINT32 u4Wtbl2D9, UINT32* Rate) +NTSTATUS MtCmdWtbl2RateTableUpdate(RTMP_ADAPTER *pAd, PCmdQElmt CMDQelmt) +{ + UINT32 u4RegVal; + UCHAR ucWaitCnt = 0; + + PWTBL2_RATE_TABLE_UPDATE pWtbl2RateTableUpdate = (PWTBL2_RATE_TABLE_UPDATE)(CMDQelmt->buffer); + UCHAR ucWcid = pWtbl2RateTableUpdate->ucWcid; + UINT32 u4Wtbl2D9 = pWtbl2RateTableUpdate->u4Wtbl2D9; + UINT32* Rate = pWtbl2RateTableUpdate->rate; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): H/W in PM4, return\n", __FUNCTION__, __LINE__)); + return NDIS_STATUS_SUCCESS; + } + + +#ifdef RTMP_PCI_SUPPORT + NdisAcquireSpinLock(&pAd->IndirectUpdateLock); +#endif + + do { + RTMP_IO_READ32(pAd, WTBL_OFF_WIUCR, &u4RegVal); + if ((u4RegVal & 0x10000) == 0) + break; + ucWaitCnt++; + RtmpusecDelay(50); + }while (ucWaitCnt < 100); + + if (ucWaitCnt == 100) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Previous update not applied by HW yet!(reg_val=0x%x)\n", + __FUNCTION__, u4RegVal)); + +#ifdef RTMP_PCI_SUPPORT + NdisReleaseSpinLock(&pAd->IndirectUpdateLock); +#endif + return NDIS_STATUS_SUCCESS; + } + + RTMP_IO_WRITE32(pAd, WTBL_ON_RIUCR0, u4Wtbl2D9); + u4RegVal = (Rate[0] | (Rate[1] << 12) | (Rate[2] << 24)); + RTMP_IO_WRITE32(pAd, WTBL_ON_RIUCR1, u4RegVal); + u4RegVal = ((Rate[2] >> 8) | (Rate[3] << 4) | (Rate[4] << 16) | (Rate[5] << 28)); + RTMP_IO_WRITE32(pAd, WTBL_ON_RIUCR2, u4RegVal); + u4RegVal = ((Rate[5] >> 4) | (Rate[6] << 8) | (Rate[7] << 20)); + RTMP_IO_WRITE32(pAd, WTBL_ON_RIUCR3, u4RegVal); + + // TODO: shiang-MT7603, shall we also clear TxCnt/RxCnt/AdmCnt here?? + u4RegVal = (ucWcid | (1 << 13) | (1 << 14)); + RTMP_IO_WRITE32(pAd, WTBL_OFF_WIUCR, u4RegVal); + +#ifdef RTMP_PCI_SUPPORT + NdisReleaseSpinLock(&pAd->IndirectUpdateLock); +#endif + + + return NDIS_STATUS_SUCCESS; +} + + +/** + * Wtbl2TxRateCounterGet + * + * + * + */ +VOID Wtbl2TxRateCounterGet(RTMP_ADAPTER *pAd, UCHAR ucWcid, TX_CNT_INFO *tx_cnt_info) +{ + UINT32 u4RegVal; + UCHAR ucWaitCnt = 0; + struct rtmp_mac_ctrl *wtbl_ctrl; + UCHAR wtbl_idx; + UINT32 addr/*, val[16]*/; +#ifdef FAST_DETECT_STA_OFF + union WTBL_2_DW7 wtbl_2_d7; + union WTBL_2_DW8 wtbl_2_d8; +#endif + + wtbl_ctrl = &pAd->mac_ctrl; + if (wtbl_ctrl->wtbl_entry_cnt[0] > 0) + wtbl_idx = (ucWcid < wtbl_ctrl->wtbl_entry_cnt[0] ? ucWcid : wtbl_ctrl->wtbl_entry_cnt[0] - 1); + else { + DBGPRINT(RT_DEBUG_ERROR, ("%s():PSE not init yet!\n", __FUNCTION__)); + return; + } + + addr = pAd->mac_ctrl.wtbl_base_addr[1] + wtbl_idx * pAd->mac_ctrl.wtbl_entry_size[1]; + RTMP_IO_READ32(pAd, addr + 5 * 4, &(tx_cnt_info->wtbl_2_d5.word)); + RTMP_IO_READ32(pAd, addr + 6 * 4, &(tx_cnt_info->wtbl_2_d6.word)); + RTMP_IO_READ32(pAd, addr + 7 * 4, &(tx_cnt_info->wtbl_2_d7.word)); + RTMP_IO_READ32(pAd, addr + 8 * 4, &(tx_cnt_info->wtbl_2_d8.word)); + RTMP_IO_READ32(pAd, addr + 9 * 4, &(tx_cnt_info->wtbl_2_d9.word)); + + +#ifdef RTMP_PCI_SUPPORT + NdisAcquireSpinLock(&pAd->IndirectUpdateLock); +#endif + + do { + RTMP_IO_READ32(pAd, WTBL_OFF_WIUCR, &u4RegVal); + if ((u4RegVal & 0x10000) == 0) + break; + ucWaitCnt++; + RtmpusecDelay(50); + }while (ucWaitCnt < 100); + + if (ucWaitCnt == 100) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Previous update not applied by HW yet!(reg_val=0x%x)\n", + __FUNCTION__, u4RegVal)); + +#ifdef RTMP_PCI_SUPPORT + NdisReleaseSpinLock(&pAd->IndirectUpdateLock); +#endif + return; + } + + u4RegVal = (ucWcid | (1 << 14)); + RTMP_IO_WRITE32(pAd, WTBL_OFF_WIUCR, u4RegVal); + +#ifdef FAST_DETECT_STA_OFF + if (Flag_fast_detect_sta_off == 1) { + ucWaitCnt = 0; + do { + RTMP_IO_READ32(pAd, WTBL_OFF_WIUCR, &u4RegVal); + if ((u4RegVal & 0x10000) == 0) + break; + ucWaitCnt++; + RtmpusecDelay(50); + } while (ucWaitCnt < 100); + + RTMP_IO_READ32(pAd, addr + 7 * 4, &(wtbl_2_d7.word)); + RTMP_IO_READ32(pAd, addr + 8 * 4, &(wtbl_2_d8.word)); + + if (wtbl_2_d7.field.current_bw_tx_cnt > 50) { + RTMP_IO_WRITE32(pAd, addr + 7 * 4, 0); + RTMP_IO_READ32(pAd, addr + 7 * 4, &(wtbl_2_d7.word)); + DBGPRINT(RT_DEBUG_ERROR, + ("After write wtbl_2_d7:%d, %d, %d, %d, %d\n", + wtbl_idx, wtbl_2_d7.field.current_bw_tx_cnt, + wtbl_2_d7.field.current_bw_fail_cnt, ucWaitCnt, u4RegVal)); + } + if (wtbl_2_d8.field.other_bw_tx_cnt > 50) { + RTMP_IO_WRITE32(pAd, addr + 8 * 4, 0); + RTMP_IO_READ32(pAd, addr + 8 * 4, &(wtbl_2_d8.word)); + DBGPRINT(RT_DEBUG_ERROR, + ("After write wtbl_2_d8:%d, %d, %d, %d, %d\n", + wtbl_idx, wtbl_2_d8.field.other_bw_tx_cnt, + wtbl_2_d8.field.other_bw_fail_cnt, ucWaitCnt, u4RegVal)); + } + } +#endif + + +#ifdef RTMP_PCI_SUPPORT + NdisReleaseSpinLock(&pAd->IndirectUpdateLock); +#endif +} + + +/** + * Wtbl2RcpiGet + * + * + * + */ +VOID Wtbl2RcpiGet(RTMP_ADAPTER *pAd, UCHAR ucWcid, union WTBL_2_DW13 *wtbl_2_d13) +{ + struct rtmp_mac_ctrl *wtbl_ctrl; + UCHAR wtbl_idx; + UINT32 addr/*, val[16]*/; +#ifdef RTMP_SDIO_SUPPORT + return; +#endif /*leonardo remark it temporarily*/ + wtbl_ctrl = &pAd->mac_ctrl; + if (wtbl_ctrl->wtbl_entry_cnt[0] > 0) + wtbl_idx = (ucWcid < wtbl_ctrl->wtbl_entry_cnt[0] ? ucWcid : wtbl_ctrl->wtbl_entry_cnt[0] - 1); + else { + DBGPRINT(RT_DEBUG_ERROR, ("%s():PSE not init yet!\n", __FUNCTION__)); + return; + } + + addr = pAd->mac_ctrl.wtbl_base_addr[1] + wtbl_idx * pAd->mac_ctrl.wtbl_entry_size[1]; + RTMP_IO_READ32(pAd, addr + 13 * 4, &(wtbl_2_d13->word)); +} + + +VOID AsicTxCntUpdate(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, MT_TX_COUNTER *pTxInfo) +{ + TX_CNT_INFO tx_cnt_info; + UINT32 TxSuccess; +#ifdef FAST_DETECT_STA_OFF + UINT32 LatestTotalTxFailCheckCnt = 0; + COUNTER_CON *ConCounters = &pEntry->ConCounters; + UINT16 i = 0; +#endif + + if (IS_VALID_ENTRY(pEntry)) { + Wtbl2TxRateCounterGet(pAd, pEntry->wcid, &tx_cnt_info); + pTxInfo->TxCount = tx_cnt_info.wtbl_2_d7.field.current_bw_tx_cnt ; + pTxInfo->TxCount += tx_cnt_info.wtbl_2_d8.field.other_bw_tx_cnt; + pTxInfo->TxFailCount = tx_cnt_info.wtbl_2_d7.field.current_bw_fail_cnt ; + pTxInfo->TxFailCount += tx_cnt_info.wtbl_2_d8.field.other_bw_fail_cnt; + + pTxInfo->Rate1TxCnt = tx_cnt_info.wtbl_2_d5.field.rate_1_tx_cnt; + pTxInfo->Rate1FailCnt = tx_cnt_info.wtbl_2_d5.field.rate_1_fail_cnt; + pTxInfo->Rate2TxCnt = tx_cnt_info.wtbl_2_d6.field.rate_2_tx_cnt; + pTxInfo->Rate3TxCnt = tx_cnt_info.wtbl_2_d6.field.rate_3_tx_cnt; + pTxInfo->Rate4TxCnt = tx_cnt_info.wtbl_2_d6.field.rate_4_tx_cnt; + pTxInfo->Rate5TxCnt = tx_cnt_info.wtbl_2_d6.field.rate_5_tx_cnt; + + pTxInfo->RateIndex = tx_cnt_info.wtbl_2_d9.field.rate_idx; +/* + if ( pTxInfo->TxFailCount == 0 ) + pEntry->OneSecTxNoRetryOkCount += pTxInfo->TxSuccessCount; + else + { + pEntry->OneSecTxRetryOkCount += pTxInfo->TxSuccessCount; + pEntry->OneSecTxFailCount += pTxInfo->TxFailCount; + } +*/ + + TxSuccess = pTxInfo->TxCount -pTxInfo->TxFailCount; +#ifdef FAST_DETECT_STA_OFF + if (Flag_fast_detect_sta_off == 1) { + if ((TxSuccess == 0) && (pTxInfo->TxFailCount > 0)) { + ConCounters->CountinueTxFailCheckTimes++; + ConCounters->TxFailCnt[ConCounters->Idx] = pTxInfo->TxFailCount; + if (++ConCounters->Idx >= COUTINUE_TX_FAIL_CHECK_TIMES) + ConCounters->Idx = 0; + } else { + ConCounters->CountinueTxFailCheckTimes = 0; + ConCounters->Idx = 0; + } + + if (ConCounters->CountinueTxFailCheckTimes >= COUTINUE_TX_FAIL_CHECK_TIMES) { + + for (i = 0; i < COUTINUE_TX_FAIL_CHECK_TIMES; i++) + LatestTotalTxFailCheckCnt += ConCounters->TxFailCnt[i]; + + if (LatestTotalTxFailCheckCnt >= COUTINUE_TX_FAIL_CHECK_CNT) { + ConCounters->DisconnectFlag = 1; + DBGPRINT(RT_DEBUG_OFF, ("%s:wcid=%d is inactive, CheckTimes:%d Cnt:%d\n", + __func__, pEntry->wcid, ConCounters->CountinueTxFailCheckTimes, + LatestTotalTxFailCheckCnt)); + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s:wcid=%d TxSuccess=%d TxFailCount:%d, TxCount:%d\n", + __func__, pEntry->wcid, TxSuccess, pTxInfo->TxFailCount, pTxInfo->TxCount)); + } +#endif + + if ( pTxInfo->TxFailCount == 0 ) + { + pAd->RalinkCounters.OneSecTxNoRetryOkCount += pTxInfo->TxCount; + pAd->MacTab.Content[pEntry->wcid].OneSecTxNoRetryOkCount += pTxInfo->TxCount; + } + else + { + pAd->RalinkCounters.OneSecTxRetryOkCount += pTxInfo->TxCount; + pAd->MacTab.Content[pEntry->wcid].OneSecTxRetryOkCount += pTxInfo->TxCount; + } + + pAd->RalinkCounters.OneSecTxFailCount += pTxInfo->TxFailCount; + pAd->MacTab.Content[pEntry->wcid].OneSecTxFailCount += pTxInfo->TxFailCount; + +#ifdef STATS_COUNT_SUPPORT + pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += TxSuccess; + pAd->WlanCounters.FailedCount.u.LowPart += pTxInfo->TxFailCount; +#endif /* STATS_COUNT_SUPPORT */ + + if ((TxSuccess == 0) && (pTxInfo->TxFailCount > 0)) + { + /* No TxPkt ok in this period as continue tx fail */ + pEntry->ContinueTxFailCnt += pTxInfo->TxFailCount; + pEntry->TxSucCnt = 0; + } + else + { + pEntry->ContinueTxFailCnt = 0; + pEntry->TxSucCnt = TxSuccess; + if (TxSuccess > 0) + pEntry->NoDataIdleCount = 0; + } + + DBGPRINT(RT_DEBUG_INFO, ("%s:(OK:%d, FAIL:%d, ConFail:%d) \n",__FUNCTION__, + TxSuccess, pTxInfo->TxFailCount, pEntry->ContinueTxFailCnt)); +#ifdef WIFI_DIAG + pEntry->diag_tx_count += pTxInfo->TxCount; + pEntry->diag_tx_succ_count += TxSuccess; +#endif + } + +} + + +VOID AsicRssiUpdate(RTMP_ADAPTER *pAd) +{ + union WTBL_2_DW13 wtbl_2_d13; + MAC_TABLE_ENTRY *pEntry; + UINT16 i; + INT32 Rssi0 = 0, Rssi1 = 0, Rssi2 = 0; + INT32 TotalRssi0 = 0, TotalRssi1 = 0, TotalRssi2 = 0; + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if ( pAd->MacTab.Size == 0 ) + { + pEntry = &pAd->MacTab.Content[MCAST_WCID]; + Wtbl2RcpiGet(pAd, pEntry->wcid, &wtbl_2_d13); + + Rssi0 = (wtbl_2_d13.field.resp_rcpi_0 - 220) / 2; + Rssi1 = (wtbl_2_d13.field.resp_rcpi_1 - 220) / 2; + Rssi2 = 0; + + pEntry->RssiSample.AvgRssi[0] = pEntry->RssiSample.LastRssi[0] = Rssi0; + pEntry->RssiSample.AvgRssi[1] = pEntry->RssiSample.LastRssi[1] = Rssi1; + pEntry->RssiSample.AvgRssi[2] = pEntry->RssiSample.LastRssi[2] = Rssi2; + + pAd->ApCfg.RssiSample.AvgRssi[0] = Rssi0; + pAd->ApCfg.RssiSample.AvgRssi[1] = Rssi1; + pAd->ApCfg.RssiSample.AvgRssi[2] = Rssi2; + + pAd->ApCfg.RssiSample.LastRssi[0] = Rssi0; + pAd->ApCfg.RssiSample.LastRssi[1] = Rssi1; + pAd->ApCfg.RssiSample.LastRssi[2] = Rssi2; + } + else + { + for (i = 1; i < MAX_LEN_OF_MAC_TABLE; i++) + { + pEntry = &pAd->MacTab.Content[i]; + if (IS_VALID_ENTRY(pEntry)) { + Wtbl2RcpiGet(pAd, pEntry->wcid, &wtbl_2_d13); + + Rssi0 = (wtbl_2_d13.field.resp_rcpi_0 - 220) / 2; + Rssi1 = (wtbl_2_d13.field.resp_rcpi_1 - 220) / 2; + Rssi2 = 0; + + pEntry->RssiSample.AvgRssi[0] = pEntry->RssiSample.LastRssi[0] = Rssi0; + pEntry->RssiSample.AvgRssi[1] = pEntry->RssiSample.LastRssi[1] = Rssi1; + pEntry->RssiSample.AvgRssi[2] = pEntry->RssiSample.LastRssi[2] = Rssi2; + + TotalRssi0 += Rssi0; + TotalRssi1 += Rssi1; + TotalRssi2 += Rssi2; + } + } + + pAd->ApCfg.RssiSample.AvgRssi[0] = pAd->ApCfg.RssiSample.LastRssi[0] = TotalRssi0 / pAd->MacTab.Size; + pAd->ApCfg.RssiSample.AvgRssi[1] = pAd->ApCfg.RssiSample.LastRssi[1] = TotalRssi1 / pAd->MacTab.Size; + pAd->ApCfg.RssiSample.AvgRssi[2] = pAd->ApCfg.RssiSample.LastRssi[2] = TotalRssi2 / pAd->MacTab.Size; + } + + } +#endif /* CONFIG_AP_SUPPORT */ + +} + + +VOID AsicRcpiReset(RTMP_ADAPTER *pAd, UCHAR ucWcid) +{ + UINT32 u4RegVal; + UCHAR ucWaitCnt = 0; + + + +#ifdef RTMP_PCI_SUPPORT + NdisAcquireSpinLock(&pAd->IndirectUpdateLock); +#endif + do { + RTMP_IO_READ32(pAd, WTBL_OFF_WIUCR, &u4RegVal); + if ((u4RegVal & 0x10000) == 0) + break; + ucWaitCnt++; + RtmpusecDelay(50); + }while (ucWaitCnt < 100); + + if (ucWaitCnt == 100) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Previous update not applied by HW yet!(reg_val=0x%x)\n", + __FUNCTION__, u4RegVal)); + +#ifdef RTMP_PCI_SUPPORT + NdisReleaseSpinLock(&pAd->IndirectUpdateLock); +#endif + return; + } + + u4RegVal = (ucWcid | (1 << 15)); + RTMP_IO_WRITE32(pAd, WTBL_OFF_WIUCR, u4RegVal); + + +#ifdef RTMP_PCI_SUPPORT + NdisReleaseSpinLock(&pAd->IndirectUpdateLock); +#endif +} + + +VOID AsicSetSMPS(RTMP_ADAPTER *pAd, UCHAR wcid, UCHAR smps) +{ + struct wtbl_entry tb_entry; + struct wtbl_1_struc wtbl_1; + + NdisZeroMemory((UCHAR *)&wtbl_1, sizeof(struct wtbl_1_struc)); + NdisZeroMemory(&tb_entry, sizeof(tb_entry)); + if (mt_wtbl_get_entry234(pAd, wcid, &tb_entry) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Cannot found WTBL2/3/4 for WCID(%d)\n", + __FUNCTION__, wcid)); + + return ; + } + // WTBL1.dw2 bit19, support Dynamic SMPS + RTMP_IO_READ32(pAd, tb_entry.wtbl_addr[0] + 8, &wtbl_1.wtbl_1_d2.word); + wtbl_1.wtbl_1_d2.field.smps = smps; + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + 8, wtbl_1.wtbl_1_d2.word); +} + + +#ifdef MCS_LUT_SUPPORT +UCHAR aucHtMaxRetryLimit[]={ + MCS_0, 4, + MCS_1, 4, + MCS_2, 7, + MCS_3, 8, + MCS_4, 9, + MCS_5, 10, + MCS_6, 11, + MCS_7, 12, + MCS_8, 4, + MCS_9, 7, + MCS_10, 8, + MCS_11, 9, + MCS_12, 10, + MCS_13, 11, + MCS_14, 12, + MCS_15, 12, +}; +VOID asic_mcs_lut_update(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + union WTBL_2_DW9 wtbl_2_d9 = {.word = 0}; + UINT32 /*reg_val,*/ rate[8]; + UCHAR stbc, bw, nss, preamble/*, wait_cnt = 0*/; + CHAR rssi; + UCHAR ucMaxTxRetryCnt = 0; + + // TODO: shiang-MT7603, shall we use MaxHTPhyMode.field.BW or HTPhyMode.field.BW here?? + switch (pEntry->HTPhyMode.field.BW) + { + case BW_80: + bw = 2; + break; + case BW_40: + bw = 1; + break; + case BW_20: + //case BW_10: + default: + bw = 0; + break; + } + wtbl_2_d9.field.fcap = bw; + wtbl_2_d9.field.ccbw_sel = bw; + wtbl_2_d9.field.cbrn = 7; // change bw as (fcap/2) if rate_idx > 7, temporary code + + + if (pEntry->HTPhyMode.field.ShortGI) { + wtbl_2_d9.field.g2 = 1; + wtbl_2_d9.field.g4 = 1; + wtbl_2_d9.field.g8 = 1; + wtbl_2_d9.field.g16 = 1; + } else { + wtbl_2_d9.field.g2 = 0; + wtbl_2_d9.field.g4 = 0; + wtbl_2_d9.field.g8 = 0; + wtbl_2_d9.field.g16 = 0; + } + wtbl_2_d9.field.rate_idx = 0; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED)) + preamble = SHORT_PREAMBLE; + else + preamble = LONG_PREAMBLE; + + stbc = pEntry->HTPhyMode.field.STBC; + +#ifdef THERMAL_PROTECT_SUPPORT + if (pAd->force_one_tx_stream == TRUE) { + stbc = 0; + } +#endif /* THERMAL_PROTECT_SUPPORT */ + + nss = get_nss_by_mcs(pEntry->HTPhyMode.field.MODE, pEntry->HTPhyMode.field.MCS, stbc); + + + if (((pEntry->MmpsMode != MMPS_STATIC) || ( pEntry->HTPhyMode.field.MODE < MODE_HTMIX )) +#ifdef THERMAL_PROTECT_SUPPORT + && (pAd->force_one_tx_stream == FALSE) +#endif /* THERMAL_PROTECT_SUPPORT */ + ) + { + rssi = RTMPMaxRssi(pAd, pEntry->RssiSample.AvgRssi[0], pEntry->RssiSample.AvgRssi[1], pEntry->RssiSample.AvgRssi[2]); + if (rssi < -50 ) + { + wtbl_2_d9.field.spe_en = 1; + } + } + + rate[0] = tx_rate_to_tmi_rate(pEntry->HTPhyMode.field.MODE, + pEntry->HTPhyMode.field.MCS, + nss, + pEntry->HTPhyMode.field.MCS == MCS_32?0:stbc, + preamble); + rate[0] &= 0xfff; + + if ( pEntry->bAutoTxRateSwitch == TRUE ) + { + UCHAR ucIndex; + UCHAR DownRateIdx, CurrRateIdx; + UCHAR mode, mcs; + BOOLEAN fgLowestRate = FALSE; + + CurrRateIdx = pEntry->CurrTxRateIndex; + DownRateIdx = CurrRateIdx; + +#ifdef NEW_RATE_ADAPT_SUPPORT +#ifdef WAPI_SUPPORT + if (IS_MT7603(pAd) || IS_MT7628(pAd) || IS_MT7636(pAd)) + { + if ((pEntry->AuthMode == Ndis802_11AuthModeWAICERT) || (pEntry->AuthMode == Ndis802_11AuthModeWAIPSK)) + { + if (pEntry->pTable == RateSwitchTableAdapt11N2S) + { + if ((CurrRateIdx >= 14) && (CurrRateIdx <= 16)) + { + CurrRateIdx = 13; + } + } + } + } +#endif /* WAPI_SUPPORT */ +#endif /* NEW_RATE_ADAPT_SUPPORT */ + + for ( ucIndex = 1; ucIndex < 8 ; ucIndex++ ) + { + if (ADAPT_RATE_TABLE(pEntry->pTable)) { + RTMP_RA_GRP_TB *pCurrTxRate; + + if ( ucIndex == 7 ) + { + if (fgLowestRate == FALSE) + { + do { + /* Avoid rate index over range */ + if ((pEntry->CurrTxRateIndex >= RATE_TABLE_SIZE(pEntry->pTable)) || + (CurrRateIdx >= RATE_TABLE_SIZE(pEntry->pTable))) { + pEntry->CurrTxRateIndex = RATE_TABLE_SIZE(pEntry->pTable) - 1; + CurrRateIdx = pEntry->CurrTxRateIndex; + DownRateIdx = CurrRateIdx; + } + CurrRateIdx = DownRateIdx; + DownRateIdx = MlmeSelectDownRate(pAd, pEntry, CurrRateIdx); + } while ( CurrRateIdx != DownRateIdx ); + } + } + else + { + DownRateIdx = MlmeSelectDownRate(pAd, pEntry, CurrRateIdx); + if (fgLowestRate == FALSE) + { + DownRateIdx = MlmeSelectDownRate(pAd, pEntry, CurrRateIdx); + } + } + + if (pEntry->HTPhyMode.field.ShortGI) + { + pCurrTxRate = PTX_RA_GRP_ENTRY(pEntry->pTable, DownRateIdx); + + if ( pCurrTxRate->CurrMCS == pEntry->HTPhyMode.field.MCS ) + { + CurrRateIdx = DownRateIdx; + DownRateIdx = MlmeSelectDownRate(pAd, pEntry, CurrRateIdx); + } + } + + pCurrTxRate = PTX_RA_GRP_ENTRY(pEntry->pTable, DownRateIdx); + mode = pCurrTxRate->Mode; + mcs = pCurrTxRate->CurrMCS; + } else { + mode = MODE_CCK; + mcs = 0; + DownRateIdx = 0; + DBGPRINT(RT_DEBUG_ERROR, ("%s: Not support legacy table.\n", __FUNCTION__)); + } + + + nss = get_nss_by_mcs(mode, mcs, pEntry->HTPhyMode.field.STBC); + rate[ucIndex] = tx_rate_to_tmi_rate(mode, + mcs, + nss, + pEntry->HTPhyMode.field.MCS == MCS_32?0:stbc, + preamble); + + rate[ucIndex] &= 0xfff; + + if (CurrRateIdx == DownRateIdx) + { + fgLowestRate = TRUE; + } + else + { + CurrRateIdx = DownRateIdx; + } + } + } + else + { + rate[1] = rate[2] = rate[3] = rate[4] = rate[5] = rate[6] = rate[7] = rate[0]; + } + + Wtbl2RateTableUpdate(pAd, pEntry->wcid, wtbl_2_d9.word, rate); + + if (pEntry->MaxHTPhyMode.field.MODE == MODE_HTMIX) + { + if (pEntry->bAutoTxRateSwitch == TRUE) + { + if(pEntry->HTPhyMode.field.MODE == MODE_CCK) + { + if(pEntry->HTPhyMode.field.MCS == 0) + { + ucMaxTxRetryCnt = 3; + } + else + { + ucMaxTxRetryCnt = 4; + } + } + else + { + if(pEntry->HTPhyMode.field.MCS == MCS_32) + { + ucMaxTxRetryCnt = 4; + } + else + { + ucMaxTxRetryCnt = aucHtMaxRetryLimit[(pEntry->HTPhyMode.field.MCS*2) + 1]; + } + } + } + else + { + ucMaxTxRetryCnt = MT_TX_SHORT_RETRY; + } + } + else + { + ucMaxTxRetryCnt = MT_TX_SHORT_RETRY; + } + + if (pAd->MacTab.Size > 3) + { +#ifdef MULTI_CLIENT_SUPPORT + if (is_multiclient_mode_on(pAd)) + pEntry->ucMaxTxRetryCnt = (ucMaxTxRetryCnt / 2); + else +#endif + pEntry->ucMaxTxRetryCnt = ucMaxTxRetryCnt; + } + else + pEntry->ucMaxTxRetryCnt = MT_TX_SHORT_RETRY; + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA, ("%s():WCID=%d, HTPhyMode=0x%x\n", + __FUNCTION__, pEntry->wcid, pEntry->HTPhyMode.word)); + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_RA, ("\tCurTxRateIdx=%d, Mode/BW/MCS/STBC/SGI=%d/%d/%d/%d/%d\n\n", + pEntry->CurrTxRateIndex, + pEntry->HTPhyMode.field.MODE, + pEntry->HTPhyMode.field.BW, + pEntry->HTPhyMode.field.MCS, + pEntry->HTPhyMode.field.STBC, + pEntry->HTPhyMode.field.ShortGI)); +} +#endif /* MCS_LUT_SUPPORT */ + + +UINT16 AsicGetTidSn(RTMP_ADAPTER *pAd, UCHAR Wcid, UCHAR Tid) +{ + UINT16 Sn = 0; + UINT32 Reg = 0; + struct wtbl_entry Entry = {0}; + struct wtbl_2_struc *Wtbl_2 = NULL; + + + NdisZeroMemory((UCHAR *)(&Entry), sizeof(struct wtbl_entry)); + + if (!mt_wtbl_get_entry234(pAd, Wcid, &Entry)) + return 0; + + Wtbl_2 = &Entry.wtbl_2; + + switch (Tid) + { + case 0: + Reg = Entry.wtbl_addr[1] + (4 * 2); //WTBL2.DW2 + RTMP_IO_READ32(pAd, Reg, &Wtbl_2->wtbl_2_d2.word); + Sn = Wtbl_2->wtbl_2_d2.field.tid_ac_0_sn; + break; + + case 1: + Reg = Entry.wtbl_addr[1] + (4 * 2); //WTBL2.DW2 + RTMP_IO_READ32(pAd, Reg, &Wtbl_2->wtbl_2_d2.word); + Sn = Wtbl_2->wtbl_2_d2.field.tid_ac_1_sn; + break; + + case 2: + Reg = Entry.wtbl_addr[1] + (4 * 2); //WTBL2.DW2 + RTMP_IO_READ32(pAd, Reg, &Wtbl_2->wtbl_2_d2.word); + Sn = Wtbl_2->wtbl_2_d2.field.tid_ac_2_sn_0; + + Reg = Entry.wtbl_addr[1] + (4 * 3); //WTBL2.DW3 + RTMP_IO_READ32(pAd, Reg, &Wtbl_2->wtbl_2_d3.word); + Sn = (Wtbl_2->wtbl_2_d3.field.tid_ac_2_sn_9 << 8) | Sn; + break; + + case 3: + Reg = Entry.wtbl_addr[1] + (4 * 3); //WTBL2.DW3 + RTMP_IO_READ32(pAd, Reg, &Wtbl_2->wtbl_2_d3.word); + Sn = Wtbl_2->wtbl_2_d3.field.tid_ac_3_sn; + break; + + case 4: + Reg = Entry.wtbl_addr[1] + (4 * 3); //WTBL2.DW3 + RTMP_IO_READ32(pAd, Reg, &Wtbl_2->wtbl_2_d3.word); + Sn = Wtbl_2->wtbl_2_d3.field.tid_4_sn; + break; + + case 5: + Reg = Entry.wtbl_addr[1] + (4 * 3); //WTBL2.DW3 + RTMP_IO_READ32(pAd, Reg, &Wtbl_2->wtbl_2_d3.word); + Sn = Wtbl_2->wtbl_2_d3.field.tid_5_sn_0; + + Reg = Entry.wtbl_addr[1] + (4 * 4); //WTBL2.DW4 + RTMP_IO_READ32(pAd, Reg, &Wtbl_2->wtbl_2_d4.word); + Sn = (Wtbl_2->wtbl_2_d4.field.tid_5_sn_5 << 4) | Sn; + break; + + case 6: + Reg = Entry.wtbl_addr[1] + (4 * 4); //WTBL2.DW4 + RTMP_IO_READ32(pAd, Reg, &Wtbl_2->wtbl_2_d4.word); + Sn = Wtbl_2->wtbl_2_d4.field.tid_6_sn; + break; + + case 7: + Reg = Entry.wtbl_addr[1] + (4 * 4); //WTBL2.DW4 + RTMP_IO_READ32(pAd, Reg, &Wtbl_2->wtbl_2_d4.word); + Sn = Wtbl_2->wtbl_2_d4.field.tid_7_sn; + break; + + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknown TID(%d) \n", __FUNCTION__, Tid)); + break; + } + + return Sn; +} + + +static UCHAR ba_range[] = {4, 5, 8, 10, 16, 20, 21, 42}; +VOID AsicUpdateBASession(RTMP_ADAPTER *pAd, UCHAR wcid, UCHAR tid, UINT16 sn, UCHAR basize, BOOLEAN isAdd, INT ses_type) +{ + struct wtbl_entry ent; + struct wtbl_2_struc *wtbl_2; + UINT32 range_mask = 0x7 << (tid * 3); + UINT32 reg, value; + MAC_TABLE_ENTRY *mac_entry; + + DBGPRINT(RT_DEBUG_TRACE, ("%s():Update BA Session Info of wcid(%d)=>tid=%d, sn = %d, basize=%d, isAdd=%d, ses_type=%s(%d)\n", + __FUNCTION__, wcid, tid, sn, basize, isAdd, (ses_type == BA_SESSION_ORI ? "Ori" : "Recp"), ses_type)); + + if (ses_type == BA_SESSION_RECP) + { + /* Reset BA SSN & Score Board Bitmap, for BA Receiptor */ + if (isAdd) + { + mac_entry = &pAd->MacTab.Content[wcid]; + value = (mac_entry->Addr[0] | (mac_entry->Addr[1] << 8) | + (mac_entry->Addr[2] << 16) | (mac_entry->Addr[3] << 24)); + RTMP_IO_WRITE32(pAd, BSCR0, value); + + RTMP_IO_READ32(pAd, BSCR1, &value); + value &= ~(BA_MAC_ADDR_47_32_MASK | RST_BA_TID_MASK | RST_BA_SEL_MASK); + value |= BA_MAC_ADDR_47_32((mac_entry->Addr[4] | (mac_entry->Addr[5] << 8))); + value |= (RST_BA_SEL(RST_BA_MAC_TID_MATCH) | RST_BA_TID(tid) | START_RST_BA_SB); + RTMP_IO_WRITE32(pAd, BSCR1, value); + } + } + else + { + NdisZeroMemory((UCHAR *)(&ent), sizeof(struct wtbl_entry)); + if (!mt_wtbl_get_entry234(pAd, wcid, &ent)) + return; + + wtbl_2 = &ent.wtbl_2; + + if (isAdd) + { + INT idx = 0; + + while (ba_range[idx] < basize) { + if (idx == 7) + break; + idx++; + }; + + if (ba_range[idx] > basize) + idx--; + + reg = ent.wtbl_addr[1] + (15 * 4); + RTMP_IO_READ32(pAd, reg, &wtbl_2->wtbl_2_d15.word); + + wtbl_2->wtbl_2_d15.field.ba_en |= 1 <wtbl_2_d15.field.ba_win_size_tid &= (~range_mask); + wtbl_2->wtbl_2_d15.field.ba_win_size_tid |= (idx << (tid * 3)); + + RTMP_IO_WRITE32(pAd, reg, wtbl_2->wtbl_2_d15.word); + } + else + { + reg = ent.wtbl_addr[1] + (15 * 4); + RTMP_IO_READ32(pAd, reg, &wtbl_2->wtbl_2_d15.word); + + wtbl_2->wtbl_2_d15.field.ba_en &= (~(1 <wtbl_2_d15.field.ba_win_size_tid &= (~range_mask); + + RTMP_IO_WRITE32(pAd, reg, wtbl_2->wtbl_2_d15.word); + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): ent->wtbl_addr[1]=0x%x, val=0x%08x\n", __FUNCTION__, reg, wtbl_2->wtbl_2_d15.word)); + } +} + + +VOID AsicUpdateRxWCIDTable(RTMP_ADAPTER *pAd, USHORT WCID, UCHAR *pAddr) +{ + struct wtbl_entry tb_entry; + //struct wtbl_2_struc *wtbl_2; + union WTBL_1_DW0 *dw0 = (union WTBL_1_DW0 *)&tb_entry.wtbl_1.wtbl_1_d0.word; + union WTBL_1_DW1 *dw1 = (union WTBL_1_DW1 *)&tb_entry.wtbl_1.wtbl_1_d1.word; + union WTBL_1_DW2 *dw2 = (union WTBL_1_DW2 *)&tb_entry.wtbl_1.wtbl_1_d2.word; + union WTBL_1_DW3 *dw3 = (union WTBL_1_DW3 *)&tb_entry.wtbl_1.wtbl_1_d3.word; + union WTBL_1_DW4 *dw4 = (union WTBL_1_DW4 *)&tb_entry.wtbl_1.wtbl_1_d4.word; + struct rtmp_mac_ctrl *wtbl_ctrl = &pAd->mac_ctrl; + MAC_TABLE_ENTRY *mac_entry; + UINT32 Value, Index; + UCHAR WaitCnt = 0; + INT apidx = MAIN_MBSSID; + + + if (wtbl_ctrl->wtbl_entry_cnt[0] > 0) + WCID = (WCID < wtbl_ctrl->wtbl_entry_cnt[0] ? WCID : MCAST_WCID); + else { + DBGPRINT(RT_DEBUG_ERROR, ("%s():PSE not init yet!\n", __FUNCTION__)); + return; + } + + // TODO: shiang-7603 + + NdisZeroMemory(&tb_entry, sizeof(tb_entry)); + if (mt_wtbl_get_entry234(pAd, WCID, &tb_entry) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Cannot found WTBL2/3/4 for WCID(%d)\n", + __FUNCTION__, WCID)); + return; + } + + dw0->field.wm = 0; + if (WCID == MCAST_WCID ) { + dw0->field.muar_idx = 0xe; + dw2->field.adm = 0; + dw2->field.cipher_suit = WTBL_CIPHER_NONE; + //YF TODO: check ? + dw0->field.rv = 1; + dw0->field.rc_a1 = 1; + dw0->field.rc_a2 = 1; + } +#ifdef MULTI_APCLI_SUPPORT + else if (WCID == APCLI_MCAST_WCID(0) || WCID == APCLI_MCAST_WCID(1)) { +#else /* MULTI_APCLI_SUPPORT */ + else if (WCID == APCLI_MCAST_WCID ) { +#endif /* !MULTI_APCLI_SUPPORT */ + dw0->field.muar_idx = 0xe; + dw0->field.rv = 1; + dw2->field.adm = 0; + dw2->field.cipher_suit = WTBL_CIPHER_NONE; + dw0->field.rc_a1 = 1; + dw0->field.rc_a2 = 1; + dw3->field.i_psm = 1; + dw3->field.du_i_psm = 1; + } + else { + mac_entry = &pAd->MacTab.Content[WCID]; + + //dw0->field.muar_idx = 0x0; // TODO: need to change depends on different BssIdx! + if (IS_ENTRY_CLIENT(mac_entry)) { + if (mac_entry->func_tb_idx == 0) + dw0->field.muar_idx = 0x0; + else if (mac_entry->func_tb_idx >= 1 && mac_entry->func_tb_idx <= 15) + dw0->field.muar_idx = 0x10 | mac_entry->func_tb_idx; + + /* for concurrent to handle HW_BSSID_1/2/3 */ + if (mac_entry->wdev->hw_bssid_idx != 0) + dw0->field.muar_idx = mac_entry->wdev->hw_bssid_idx ; + } + else if (IS_ENTRY_APCLI(mac_entry)) { +#ifdef MULTI_APCLI_SUPPORT + dw0->field.muar_idx = (0x1 + mac_entry->func_tb_idx); +#else /* MULTI_APCLI_SUPPORT */ + dw0->field.muar_idx = 0x1;//Carter, MT_MAC apcli use HWBSSID1 to go. +#endif /* !MULTI_APCLI_SUPPORT */ + dw0->field.rc_a1 = 1; + dw3->field.i_psm = 1; + dw3->field.du_i_psm = 1; + } + else + dw0->field.muar_idx = 0x0; + + dw0->field.rv = 1; + DBGPRINT(RT_DEBUG_TRACE, ("%s(): mac_entry->type=%d, pMacEntry->MaxHTPhyMode.field.MODE=%d, StatusFlag=0x%lx\n", + __FUNCTION__, mac_entry->EntryType, + mac_entry->MaxHTPhyMode.field.MODE, + mac_entry->ClientStatusFlags)); + + dw0->field.rc_a2 = 1; + // TODO: shiang-MT7603, in which case we need to check A1??? + //dw0->field.rc_a1 = 1; + dw2->field.adm = 1; + switch (mac_entry->WepStatus) + { + case Ndis802_11WEPDisabled: + dw2->field.cipher_suit = WTBL_CIPHER_NONE; + break; + default: + break; + } + + if (mac_entry->AuthMode == Ndis802_11AuthModeShared || + mac_entry->AuthMode == Ndis802_11AuthModeAutoSwitch) + { + dw0->field.rkv = 0; + dw2->field.cipher_suit = WTBL_CIPHER_WEP_40; + } + + if (IS_HT_STA(mac_entry)) { + dw2->field.ht = 1; + dw2->field.qos = 1; + dw2->field.mm = mac_entry->MpduDensity; + dw2->field.af = mac_entry->MaxRAmpduFactor; + if (CLIENT_STATUS_TEST_FLAG(mac_entry, fCLIENT_STATUS_RDG_CAPABLE)) { + dw2->field.r = 1; + dw2->field.rdg_ba = 1; + } + + if (mac_entry->MmpsMode == MMPS_DYNAMIC) + dw2->field.smps = 1; + else + dw2->field.smps = 0; + + dw4->field.partial_aid = WCID; + } + } + + dw0->field.addr_4 = pAddr[4]; + dw0->field.addr_5 = pAddr[5]; + dw1->word = pAddr[0] + (pAddr[1] << 8) +(pAddr[2] << 16) +(pAddr[3] << 24); + dw3->field.wtbl2_fid = tb_entry.wtbl_fid[1]; + dw3->field.wtbl2_eid = tb_entry.wtbl_eid[1]; + dw3->field.wtbl4_fid = tb_entry.wtbl_fid[3]; + dw3->field.psm = 0; +#ifndef MT_PS + dw3->field.i_psm = 1; + dw3->field.du_i_psm = 1; +#endif /* !MT_PS */ + dw4->field.wtbl3_fid = tb_entry.wtbl_fid[2]; + dw4->field.wtbl3_eid = tb_entry.wtbl_eid[2]; + dw4->field.wtbl4_eid = tb_entry.wtbl_eid[3]; + + if (WCID >= 0) { + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + 8, dw2->word); + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + 4, dw1->word); + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0], dw0->word); + + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d):Write WTBL 1 Addr:0x%x, Value:0x%x\n", + __FUNCTION__, WCID, tb_entry.wtbl_addr[0], dw0->word)); + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d):Write WTBL 1 Addr:0x%x, Value:0x%x\n", + __FUNCTION__, WCID, tb_entry.wtbl_addr[0] + 4, dw1->word)); + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d):Write WTBL 1 Addr:0x%x, Value:0x%x\n", + __FUNCTION__, WCID, tb_entry.wtbl_addr[0] + 8, dw2->word)); + + RTMP_IO_READ32(pAd, WTBL1OR, &Value); + Value |= PSM_W_FLAG; + RTMP_IO_WRITE32(pAd, WTBL1OR, Value); + + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + 12, dw3->word); + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d):Write WTBL 1 Addr:0x%x, Value:0x%x\n", + __FUNCTION__, WCID, tb_entry.wtbl_addr[0] + 12, dw3->word)); + + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + 16, dw4->word); + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d):Write WTBL 1 Addr:0x%x, Value:0x%x\n", + __FUNCTION__, WCID, tb_entry.wtbl_addr[0] + 16, dw4->word)); + + RTMP_IO_READ32(pAd, WTBL1OR, &Value); + Value &= ~PSM_W_FLAG; + RTMP_IO_WRITE32(pAd, WTBL1OR, Value); + + + /* Clear BA Information */ + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[1] + (15 * 4), tb_entry.wtbl_2.wtbl_2_d15.word); + /* IOT issue with BCM's AP (ex: TP-LINK AC1900 C8/C9): Clear PN in wtbl2 + * The PN shall be initialized when the corresponding TK is initialized or refreshed + * If the PN (Packet Number) exceed the threshold, AP will drop the data frames. + */ + tb_entry.wtbl_2.wtbl_2_d0.pn_0 = 0x0; + tb_entry.wtbl_2.wtbl_2_d1.field.pn_32 = 0x0; + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[1] + (0 * 4), tb_entry.wtbl_2.wtbl_2_d0.word); + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[1] + (1 * 4), tb_entry.wtbl_2.wtbl_2_d1.word); + + /* Clear WTBL2 TID SN to default */ + /* We need change disable TX to just disable TX Q only, or RX path may have problem due to we can not TX ack*/ + //AsicSetMacTxRx(pAd, ASIC_MAC_TX, FALSE); + MtAsicACQueue(pAd, AC_QUEUE_STOP, apidx, 0xF); + + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[1] + (2 * 4), 0x0); + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[1] + (3 * 4), 0x0); + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[1] + (4 * 4), 0x0); +#ifdef RTMP_PCI_SUPPORT + NdisAcquireSpinLock(&pAd->IndirectUpdateLock); +#endif + RTMP_IO_READ32(pAd, WTBL_OFF_WIUCR, &Value); + Value &= ~WLAN_IDX_MASK; + Value |= WLAN_IDX(WCID); + Value |= WTBL2_UPDATE_FLAG; + RTMP_IO_WRITE32(pAd, WTBL_OFF_WIUCR, Value); + + WaitCnt = 0; + + do { + RTMP_IO_READ32(pAd, WTBL_OFF_WIUCR, &Value); + if ((Value & IU_BUSY) == 0) + break; + WaitCnt++; + RtmpusecDelay(50); + } while (WaitCnt < 100); + + if (WaitCnt == 100) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Previous update not applied by HW yet!(reg_val=0x%x)\n", + __FUNCTION__, Value)); +#ifdef RTMP_PCI_SUPPORT + NdisReleaseSpinLock(&pAd->IndirectUpdateLock); +#endif + //AsicSetMacTxRx(pAd, ASIC_MAC_TX, TRUE); + MtAsicACQueue(pAd, AC_QUEUE_START, apidx, 0xF); + return; + } + +#ifdef RTMP_PCI_SUPPORT + NdisReleaseSpinLock(&pAd->IndirectUpdateLock); +#endif + //AsicSetMacTxRx(pAd, ASIC_MAC_TX, TRUE); + MtAsicACQueue(pAd, AC_QUEUE_START, apidx, 0xF); + + +#ifdef RTMP_PCI_SUPPORT + NdisAcquireSpinLock(&pAd->IndirectUpdateLock); +#endif + + /* RX Counter Clear */ + RTMP_IO_READ32(pAd, WTBL_OFF_WIUCR, &Value); + Value &= ~WLAN_IDX_MASK; + Value |= WLAN_IDX(WCID); + Value |= RX_CNT_CLEAR; + RTMP_IO_WRITE32(pAd, WTBL_OFF_WIUCR, Value); + + WaitCnt = 0; + + do { + RTMP_IO_READ32(pAd, WTBL_OFF_WIUCR, &Value); + if ((Value & IU_BUSY) == 0) + break; + WaitCnt++; + RtmpusecDelay(50); + } while (WaitCnt < 100); + + if (WaitCnt == 100) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Previous update not applied by HW yet!(reg_val=0x%x)\n", + __FUNCTION__, Value)); + + +#ifdef RTMP_PCI_SUPPORT + NdisReleaseSpinLock(&pAd->IndirectUpdateLock); +#endif + return; + } + + /* TX Counter Clear */ + RTMP_IO_READ32(pAd, WTBL_OFF_WIUCR, &Value); + Value &= ~WLAN_IDX_MASK; + Value |= WLAN_IDX(WCID); + Value |= TX_CNT_CLEAR; + RTMP_IO_WRITE32(pAd, WTBL_OFF_WIUCR, Value); + + WaitCnt = 0; + + do { + RTMP_IO_READ32(pAd, WTBL_OFF_WIUCR, &Value); + if ((Value & IU_BUSY) == 0) + break; + WaitCnt++; + RtmpusecDelay(50); + } while (WaitCnt < 100); + + if (WaitCnt == 100) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Previous update not applied by HW yet!(reg_val=0x%x)\n", + __FUNCTION__, Value)); + + +#ifdef RTMP_PCI_SUPPORT + NdisReleaseSpinLock(&pAd->IndirectUpdateLock); +#endif + return; + } + + /* Clear Cipher Key */ + for (Index = 0; Index < 8; Index++) + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[2] + (4 * Index), 0x0); + + /* Admission Control Counter Clear */ + RTMP_IO_READ32(pAd, WTBL_OFF_WIUCR, &Value); + Value &= ~WLAN_IDX_MASK; + Value |= WLAN_IDX(WCID); + Value |= ADM_CNT_CLEAR; + RTMP_IO_WRITE32(pAd, WTBL_OFF_WIUCR, Value); + + WaitCnt = 0; + + do { + RTMP_IO_READ32(pAd, WTBL_OFF_WIUCR, &Value); + if ((Value & IU_BUSY) == 0) + break; + WaitCnt++; + RtmpusecDelay(50); + } while (WaitCnt < 100); + + if (WaitCnt == 100) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Previous update not applied by HW yet!(reg_val=0x%x)\n", + __FUNCTION__, Value)); + + +#ifdef RTMP_PCI_SUPPORT + NdisReleaseSpinLock(&pAd->IndirectUpdateLock); +#endif + return; + } + + +#ifdef RTMP_PCI_SUPPORT + NdisReleaseSpinLock(&pAd->IndirectUpdateLock); +#endif + } +} + + +/* + ======================================================================== +Description: +Add Client security information into ASIC WCID table and IVEIV table. +Return: + +Note : +The key table selection rule : +1. Wds-links and Mesh-links always use Pair-wise key table. +2. When the CipherAlg is TKIP, AES, SMS4 or the dynamic WEP is enabled, +it needs to set key into Pair-wise Key Table. +3. The pair-wise key security mode is set NONE, it means as no security. +4. In STA Adhoc mode, it always use shared key table. +5. Otherwise, use shared key table + +======================================================================== + */ +VOID AsicUpdateWcidAttributeEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR BssIdx, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN UINT8 Wcid, + IN UINT8 KeyTabFlag) +{ + // WCID_ATTRIBUTE_STRUC WCIDAttri; + //USHORT offset; + //UINT32 wcid_attr_base = 0, wcid_attr_size = 0; + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_INFO, ("%s(%d): , Wcid=%d, BssIdx=%d, KeyIdx=%d, Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__, Wcid, BssIdx, KeyIdx)); + return; + } + + /* The limitation of HW WCID table */ + if (Wcid > 254) + { + DBGPRINT(RT_DEBUG_WARN, ("%s:Invalid wcid(%d)\n", __FUNCTION__, Wcid)); + return; + } + +} + + +/* + ========================================================================== +Description: + +IRQL = DISPATCH_LEVEL + +========================================================================== + */ +VOID AsicDelWcidTab(RTMP_ADAPTER *pAd, UCHAR wcid_idx) +{ + UCHAR cnt, cnt_s, cnt_e; + struct wtbl_entry tb_entry; + UCHAR WaitCnt = 0; + UINT32 Index = 0, Value; + union WTBL_1_DW0 *dw0 = (union WTBL_1_DW0 *)&tb_entry.wtbl_1.wtbl_1_d0.word; + union WTBL_1_DW3 *dw3 = (union WTBL_1_DW3 *)&tb_entry.wtbl_1.wtbl_1_d3.word; + union WTBL_1_DW4 *dw4 = (union WTBL_1_DW4 *)&tb_entry.wtbl_1.wtbl_1_d4.word; + + + DBGPRINT(RT_DEBUG_TRACE, ("AsicDelWcidTab==>wcid_idx = 0x%x\n",wcid_idx)); + + if (wcid_idx == WCID_ALL) { + cnt_s = 0; + cnt_e = (WCID_ALL - 1); + } else { + cnt_s = cnt_e = wcid_idx; + } + + for (cnt = cnt_s; cnt_s <= cnt_e; cnt_s++) + { + cnt = cnt_s; + NdisZeroMemory(&tb_entry, sizeof(tb_entry)); + if (mt_wtbl_get_entry234(pAd, cnt, &tb_entry) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Cannot found WTBL2/3/4 for WCID(%d)\n", + __FUNCTION__, cnt)); + return; + } + + dw0->field.wm = 0; + dw0->field.rc_a2 = 1; + dw0->field.rv = 1; + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0], tb_entry.wtbl_1.wtbl_1_d0.word); + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + 4, tb_entry.wtbl_1.wtbl_1_d1.word); + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + 8, tb_entry.wtbl_1.wtbl_1_d2.word); + + RTMP_IO_READ32(pAd, WTBL1OR, &Value); + Value |= PSM_W_FLAG; + RTMP_IO_WRITE32(pAd, WTBL1OR, Value); + + dw3->field.wtbl2_fid = tb_entry.wtbl_fid[1]; + dw3->field.wtbl2_eid = tb_entry.wtbl_eid[1]; + dw3->field.wtbl4_fid = tb_entry.wtbl_fid[3]; + dw4->field.wtbl3_fid = tb_entry.wtbl_fid[2]; + dw4->field.wtbl3_eid = tb_entry.wtbl_eid[2]; + dw4->field.wtbl4_eid = tb_entry.wtbl_eid[3]; + +#ifdef MT_PS + if (cnt == MCAST_WCID) { + dw3->field.i_psm=1; + dw3->field.du_i_psm=1; + } +#endif /*leonardo workaround*/ + + //RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + 12, tb_entry.wtbl_1.wtbl_1_d3.word); + //RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + 16, tb_entry.wtbl_1.wtbl_1_d4.word); + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + 12, dw3->word); + + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + 16, dw4->word); + + RTMP_IO_READ32(pAd, WTBL1OR, &Value); + Value &= ~PSM_W_FLAG; + RTMP_IO_WRITE32(pAd, WTBL1OR, Value); + + + /* Clear BA Information */ + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[1] + (15 * 4), tb_entry.wtbl_2.wtbl_2_d15.word); + /*Clear PN */ + tb_entry.wtbl_2.wtbl_2_d0.pn_0=0; + tb_entry.wtbl_2.wtbl_2_d1.field.pn_32=0; + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[1] + (0 * 4), tb_entry.wtbl_2.wtbl_2_d0.word); + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[1] + (1 * 4), tb_entry.wtbl_2.wtbl_2_d1.word); + + +#ifdef RTMP_PCI_SUPPORT + NdisAcquireSpinLock(&pAd->IndirectUpdateLock); +#endif + /* RX Counter Clear */ + RTMP_IO_READ32(pAd, WTBL_OFF_WIUCR, &Value); + Value &= ~WLAN_IDX_MASK; + Value |= WLAN_IDX(cnt); + Value |= RX_CNT_CLEAR; + RTMP_IO_WRITE32(pAd, WTBL_OFF_WIUCR, Value); + + WaitCnt = 0; + + do { + RTMP_IO_READ32(pAd, WTBL_OFF_WIUCR, &Value); + if ((Value & IU_BUSY) == 0) + break; + WaitCnt++; + RtmpusecDelay(50); + } while (WaitCnt < 100); + + if (WaitCnt == 100) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Previous update not applied by HW yet!(reg_val=0x%x)\n", + __FUNCTION__, Value)); + +#ifdef RTMP_PCI_SUPPORT + NdisReleaseSpinLock(&pAd->IndirectUpdateLock); +#endif + return; + } + + /* TX Counter Clear */ + RTMP_IO_READ32(pAd, WTBL_OFF_WIUCR, &Value); + Value &= ~WLAN_IDX_MASK; + Value |= WLAN_IDX(cnt); + Value |= TX_CNT_CLEAR; + RTMP_IO_WRITE32(pAd, WTBL_OFF_WIUCR, Value); + + WaitCnt = 0; + + do { + RTMP_IO_READ32(pAd, WTBL_OFF_WIUCR, &Value); + if ((Value & IU_BUSY) == 0) + break; + WaitCnt++; + RtmpusecDelay(50); + } while (WaitCnt < 100); + + if (WaitCnt == 100) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Previous update not applied by HW yet!(reg_val=0x%x)\n", + __FUNCTION__, Value)); + + +#ifdef RTMP_PCI_SUPPORT + NdisReleaseSpinLock(&pAd->IndirectUpdateLock); +#endif + return; + } + + /* Clear Cipher Key */ + for (Index = 0; Index < 8; Index++) + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[2] + (4 * Index), 0x0); + + /* Admission Control Counter Clear */ + RTMP_IO_READ32(pAd, WTBL_OFF_WIUCR, &Value); + Value &= ~WLAN_IDX_MASK; + Value |= WLAN_IDX(cnt); + Value |= ADM_CNT_CLEAR; + RTMP_IO_WRITE32(pAd, WTBL_OFF_WIUCR, Value); + + WaitCnt = 0; + + do { + RTMP_IO_READ32(pAd, WTBL_OFF_WIUCR, &Value); + if ((Value & IU_BUSY) == 0) + break; + WaitCnt++; + RtmpusecDelay(50); + } while (WaitCnt < 100); + + if (WaitCnt == 100) { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Previous update not applied by HW yet!(reg_val=0x%x)\n", + __FUNCTION__, Value)); + +#ifdef RTMP_PCI_SUPPORT + NdisReleaseSpinLock(&pAd->IndirectUpdateLock); +#endif + return; + } + + +#ifdef RTMP_PCI_SUPPORT + NdisReleaseSpinLock(&pAd->IndirectUpdateLock); +#endif + } +} + + +VOID CmdProcAddRemoveKey( + IN PRTMP_ADAPTER pAd, + IN UCHAR AddRemove, + IN UCHAR BssIdx, + IN UCHAR key_idx, + IN UCHAR Wcid, + IN UCHAR KeyTabFlag, + IN PCIPHER_KEY pCipherKey, + IN PUCHAR PeerAddr) +{ + CMD_802_11_KEY CmdKey; + UCHAR *pKey = pCipherKey->Key; + UCHAR *pTxMic = pCipherKey->TxMic; + UCHAR *pRxMic = pCipherKey->RxMic; + UCHAR CipherAlg = pCipherKey->CipherAlg; + struct wtbl_entry tb_entry; + union WTBL_1_DW0 *dw0 = (union WTBL_1_DW0 *)&tb_entry.wtbl_1.wtbl_1_d0.word; + union WTBL_1_DW1 *dw1 = (union WTBL_1_DW1 *)&tb_entry.wtbl_1.wtbl_1_d1.word; + union WTBL_1_DW2 *dw2 = (union WTBL_1_DW2 *)&tb_entry.wtbl_1.wtbl_1_d2.word; + //union WTBL_1_DW3 *dw3 = (union WTBL_1_DW3 *)&tb_entry.wtbl_1.wtbl_1_d3.word; + //union WTBL_1_DW4 *dw4 = (union WTBL_1_DW4 *)&tb_entry.wtbl_1.wtbl_1_d4.word; + //struct rtmp_mac_ctrl *wtbl_ctrl = &pAd->mac_ctrl; + + memset(&CmdKey, 0x00, sizeof(CMD_802_11_KEY)); + + CmdKey.ucAddRemove = AddRemove; + CmdKey.ucWlanIndex = Wcid; + CmdKey.ucBssIndex = BssIdx; + CmdKey.ucKeyId = key_idx; + CmdKey.ucKeyType = KeyTabFlag; + memcpy(CmdKey.aucPeerAddr, PeerAddr, 6); + switch(CipherAlg) + { + case CIPHER_WEP64: + CmdKey.ucAlgorithmId = 1; + CmdKey.ucKeyLen = 5; + memcpy(CmdKey.aucKeyMaterial, pKey, CmdKey.ucKeyLen); + break; + case CIPHER_WEP128: + CmdKey.ucAlgorithmId = 5; + CmdKey.ucKeyLen = 13; + memcpy(CmdKey.aucKeyMaterial, pKey, CmdKey.ucKeyLen); + break; + case CIPHER_TKIP: + CmdKey.ucAlgorithmId = 2; + CmdKey.ucKeyLen = 32; + memcpy(CmdKey.aucKeyMaterial, pKey, 16); + memcpy(&CmdKey.aucKeyMaterial[16], pRxMic, 8); + memcpy(&CmdKey.aucKeyMaterial[24], pTxMic, 8); + break; + case CIPHER_AES: + CmdKey.ucAlgorithmId = 4; + CmdKey.ucKeyLen = 16; + memcpy(CmdKey.aucKeyMaterial, pKey, CmdKey.ucKeyLen); + break; + case CIPHER_SMS4: + CmdKey.ucAlgorithmId = 8; + CmdKey.ucKeyLen = 32; + memcpy(CmdKey.aucKeyMaterial, pKey, 16); + memcpy(&CmdKey.aucKeyMaterial[16], pTxMic, 8); + memcpy(&CmdKey.aucKeyMaterial[24], pRxMic, 8); + break; + case CIPHER_WEP152: + CmdKey.ucAlgorithmId = 7; + CmdKey.ucKeyLen = 16; + memcpy(CmdKey.aucKeyMaterial, pKey, CmdKey.ucKeyLen); + break; + case CIPHER_BIP: + CmdKey.ucAlgorithmId = 6; + CmdKey.ucKeyLen = 16; + memcpy(CmdKey.aucKeyMaterial, pKey, CmdKey.ucKeyLen); + break; + default: + if (CmdKey.ucAddRemove) + break; + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support Cipher[%d] for HIF_MT yet!\n", + __FUNCTION__, __LINE__, CipherAlg)); + return; + } + + /* Driver set security key */ + if (CmdKey.ucAddRemove == 0) { + DBGPRINT(RT_DEBUG_TRACE, ("add key table:wcid[%d]\n", CmdKey.ucWlanIndex)); + + NdisZeroMemory(&tb_entry, sizeof(tb_entry)); + if (mt_wtbl_get_entry234(pAd, CmdKey.ucWlanIndex, &tb_entry) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Cannot found WTBL2/3/4 for WCID(%d)\n", + __FUNCTION__, CmdKey.ucWlanIndex)); + return; + } + + { + UINT32 addr = 0, index = 0, *pKey = (UINT32 *)CmdKey.aucKeyMaterial; + addr = pAd->mac_ctrl.wtbl_base_addr[2] + CmdKey.ucWlanIndex * pAd->mac_ctrl.wtbl_entry_size[2]; + if ((CipherAlg == CIPHER_WEP64) || (CipherAlg == CIPHER_WEP128) || (CipherAlg == CIPHER_WEP152)) + addr = CmdKey.ucKeyId*16+addr; + if (CipherAlg == CIPHER_SMS4) + addr = CmdKey.ucKeyId*32+addr; + if (CipherAlg == CIPHER_BIP) + addr = addr+16; + for (index=0;indexword); + RTMP_IO_READ32(pAd, tb_entry.wtbl_addr[0]+4, &dw1->word); + RTMP_IO_READ32(pAd, tb_entry.wtbl_addr[0]+8, &dw2->word); + + dw0->field.wm = 0; + if((Wcid != MCAST_WCID) +#ifdef APCLI_SUPPORT +#ifdef MULTI_APCLI_SUPPORT + && ((Wcid != APCLI_MCAST_WCID(0)) && (Wcid != APCLI_MCAST_WCID(1)) ) +#else /* MULTI_APCLI_SUPPORT */ + && (Wcid != APCLI_MCAST_WCID) +#endif /*! MULTI_APCLI_SUPPORT */ +#endif /* APCLI_SUPPORT */ + ) + { + dw0->field.addr_4 = CmdKey.aucPeerAddr[4]; + dw0->field.addr_5 = CmdKey.aucPeerAddr[5]; + dw1->word = CmdKey.aucPeerAddr[0] + (CmdKey.aucPeerAddr[1] << 8) +(CmdKey.aucPeerAddr[2] << 16) +(CmdKey.aucPeerAddr[3] << 24); + } + +#ifdef CONFIG_AP_SUPPORT + if ((pAd->OpMode == OPMODE_AP) + ) + { + if (KeyTabFlag == SHAREDKEYTABLE) { + dw0->field.rv = 0; + dw0->field.rkv = 0; +#ifdef APCLI_SUPPORT +#ifdef MULTI_APCLI_SUPPORT + if ((Wcid == APCLI_MCAST_WCID(0)) || (Wcid == APCLI_MCAST_WCID(1))) { +#else /* MULTI_APCLI_SUPPORT */ + if (Wcid == APCLI_MCAST_WCID) { +#endif /*! MULTI_APCLI_SUPPORT */ + dw0->field.rv = 1; + dw0->field.rkv = 1; + } +#endif /* APCLI_SUPPORT */ + } + else { + dw0->field.rv = 1; + dw0->field.rkv = 1; + } + } + else +#endif /* CONFIG_AP_SUPPORT */ +{ +} + dw2->field.adm = 1; + dw2->field.cipher_suit = CmdKey.ucAlgorithmId; + dw0->field.kid = CmdKey.ucKeyId; + + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + 8, dw2->word); + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + 4, dw1->word); + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0], dw0->word); + + DBGPRINT(RT_DEBUG_INFO, ("%s(%d):Write WTBL 1 Addr:0x%x, Value:0x%x\n", + __FUNCTION__, CmdKey.ucWlanIndex, tb_entry.wtbl_addr[0], dw0->word)); + DBGPRINT(RT_DEBUG_INFO, ("%s(%d):Write WTBL 1 Addr:0x%x, Value:0x%x\n", + __FUNCTION__, CmdKey.ucWlanIndex, tb_entry.wtbl_addr[0] + 4, dw1->word)); + DBGPRINT(RT_DEBUG_INFO, ("%s(%d):Write WTBL 1 Addr:0x%x, Value:0x%x\n", + __FUNCTION__, CmdKey.ucWlanIndex, tb_entry.wtbl_addr[0] + 8, dw2->word)); + + } else { + DBGPRINT(RT_DEBUG_TRACE, ("remove key table:wcid[%d]\n", CmdKey.ucWlanIndex)); + + NdisZeroMemory(&tb_entry, sizeof(tb_entry)); + if (mt_wtbl_get_entry234(pAd, CmdKey.ucWlanIndex, &tb_entry) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Cannot found WTBL2/3/4 for WCID(%d)\n", + __FUNCTION__, CmdKey.ucWlanIndex)); + return; + } + + { + UINT32 addr = 0, index = 0; + addr = pAd->mac_ctrl.wtbl_base_addr[2] + CmdKey.ucWlanIndex * pAd->mac_ctrl.wtbl_entry_size[2]; + if ((CipherAlg == CIPHER_WEP64) || (CipherAlg == CIPHER_WEP128) || (CipherAlg == CIPHER_WEP152)) + addr = CmdKey.ucKeyId*16+addr; + + for (index=0;indexword); + RTMP_IO_READ32(pAd, tb_entry.wtbl_addr[0]+4, &dw1->word); + RTMP_IO_READ32(pAd, tb_entry.wtbl_addr[0]+8, &dw2->word); + + dw0->field.wm = 0; + dw0->field.addr_4 = CmdKey.aucPeerAddr[4]; + dw0->field.addr_5 = CmdKey.aucPeerAddr[5]; + dw1->word = CmdKey.aucPeerAddr[0] + (CmdKey.aucPeerAddr[1] << 8) +(CmdKey.aucPeerAddr[2] << 16) +(CmdKey.aucPeerAddr[3] << 24); + + dw0->field.rv = 0; + dw2->field.adm = 0; + dw0->field.rkv = 0; + dw2->field.cipher_suit = 0; + dw0->field.kid = 0; + + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0], dw0->word); + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + 4, dw1->word); + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + 8, dw2->word); + + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d):Write WTBL 1 Addr:0x%x, Value:0x%x\n", + __FUNCTION__, CmdKey.ucWlanIndex, tb_entry.wtbl_addr[0], dw0->word)); + + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d):Write WTBL 1 Addr:0x%x, Value:0x%x\n", + __FUNCTION__, CmdKey.ucWlanIndex, tb_entry.wtbl_addr[0] + 4, dw1->word)); + + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d):Write WTBL 1 Addr:0x%x, Value:0x%x\n", + __FUNCTION__, CmdKey.ucWlanIndex, tb_entry.wtbl_addr[0] + 8, dw2->word)); + + + } + + //dump_wtbl_info(pAd, Wcid); +} + +/* + ======================================================================== + Description: + Add Pair-wise key material into ASIC. + Update pairwise key, TxMic and RxMic to Asic Pair-wise key table + + Return: + ======================================================================== +*/ +VOID AsicAddPairwiseKeyEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR WCID, + IN PCIPHER_KEY pCipherKey) +{ + INT i; + ULONG offset; + UINT32 pairwise_key_base = 0, pairwise_key_len = 0; + UCHAR *pKey = pCipherKey->Key; + UCHAR *pTxMic = pCipherKey->TxMic; + UCHAR *pRxMic = pCipherKey->RxMic; + UCHAR CipherAlg = pCipherKey->CipherAlg; +#ifdef RTMP_MAC +#ifdef RTMP_MAC_PCI +#endif /* RTMP_MAC_PCI */ +#endif /* RTMP_MAC */ + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_INFO, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return; + } + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + pairwise_key_base = RLT_PAIRWISE_KEY_TABLE_BASE; + pairwise_key_len = RLT_HW_KEY_ENTRY_SIZE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + pairwise_key_base = PAIRWISE_KEY_TABLE_BASE; + pairwise_key_len = HW_KEY_ENTRY_SIZE; +#ifdef RTMP_MAC_PCI +#endif /* RTMP_MAC_PCI */ + } +#endif /* RTMP_MAC */ + + /* EKEY */ + offset = pairwise_key_base + (WCID * pairwise_key_len); +#ifdef RTMP_MAC_PCI + for (i=0; ichipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_TRACE, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return TRUE; + } + + + +#ifdef RTMP_MAC_PCI + if (IS_PCI_INF(pAd) || IS_RBUS_INF(pAd)) + in_atomic = TRUE; +#endif /* RTMP_MAC_PCI */ + if (pAd->chipOps.sendCommandToMcu) + return pAd->chipOps.sendCommandToMcu(pAd, Command, Token, Arg0, Arg1, in_atomic); + else + return FALSE; +} + + +BOOLEAN AsicSendCmdToMcuAndWait( + IN RTMP_ADAPTER *pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN in_atomic) +{ + BOOLEAN cmd_done = TRUE; + + AsicSendCommandToMcu(pAd, Command, Token, Arg0, Arg1, in_atomic); + +#ifdef RTMP_MAC_PCI + cmd_done = AsicCheckCommanOk(pAd, Token); +#endif /* RTMP_MAC_PCI */ + + return cmd_done; +} + + +BOOLEAN AsicSendCommandToMcuBBP( + IN PRTMP_ADAPTER pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN FlgIsNeedLocked) +{ + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return TRUE; + } + + + + 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(RTMP_ADAPTER *pAd, UCHAR Channel) +{ + if (pAd->chipOps.AsicRfTurnOff) + { + pAd->chipOps.AsicRfTurnOff(pAd); + } + else + { +#if defined(RT28xx) || defined(RT2880) || defined(RT2883) + /* RF R2 bit 18 = 0*/ + UINT32 R1 = 0, R2 = 0, R3 = 0; + UCHAR index; + RTMP_RF_REGS *RFRegTable; + + RFRegTable = RF2850RegTable; +#endif /* defined(RT28xx) || defined(RT2880) || defined(RT2883) */ + + switch (pAd->RfIcType) + { +#if defined(RT28xx) || defined(RT2880) || defined(RT2883) +#if defined(RT28xx) || defined(RT2880) + case RFIC_2820: + case RFIC_2850: + case RFIC_2720: + case RFIC_2750: +#endif /* defined(RT28xx) || defined(RT2880) */ + for (index = 0; index < NUM_OF_2850_CHNL; index++) + { + if (Channel == RFRegTable[index].Channel) + { + R1 = RFRegTable[index].R1 & 0xffffdfff; + R2 = RFRegTable[index].R2 & 0xfffbffff; + R3 = RFRegTable[index].R3 & 0xfff3ffff; + + RTMP_RF_IO_WRITE32(pAd, R1); + RTMP_RF_IO_WRITE32(pAd, R2); + + /* Program R1b13 to 1, R3/b18,19 to 0, R2b18 to 0. */ + /* Set RF R2 bit18=0, R3 bit[18:19]=0*/ + /*if (pAd->StaCfg.bRadio == FALSE)*/ + if (1) + { + RTMP_RF_IO_WRITE32(pAd, R3); + + DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x, R3 = 0x%08x \n", + Channel, pAd->RfIcType, R2, R3)); + } + else + DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d(RF=%d, ) , R2=0x%08x \n", + Channel, pAd->RfIcType, R2)); + break; + } + } + break; +#endif /* defined(RT28xx) || defined(RT2880) || defined(RT2883) */ + default: + DBGPRINT(RT_DEBUG_TRACE, ("AsicTurnOffRFClk#%d : Unkonwn RFIC=%d\n", + Channel, pAd->RfIcType)); + break; + } + } +} + + +#ifdef WAPI_SUPPORT +VOID AsicUpdateWAPIPN( + IN PRTMP_ADAPTER pAd, + IN USHORT WCID, + IN ULONG pn_low, + IN ULONG pn_high) +{ + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return; + } + + if (IS_HW_WAPI_SUPPORT(pAd)) + { + UINT32 offset; + UINT32 wapi_pn_base = 0, wapi_pn_size = 0; +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + wapi_pn_base = RLT_WAPI_PN_TABLE_BASE; + wapi_pn_size = RLT_WAPI_PN_ENTRY_SIZE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + wapi_pn_base = WAPI_PN_TABLE_BASE; + wapi_pn_size = WAPI_PN_ENTRY_SIZE; + } +#endif /* RTMP_MAC */ + + offset = wapi_pn_base + (WCID * wapi_pn_size); + + RTMP_IO_WRITE32(pAd, offset, pn_low); + RTMP_IO_WRITE32(pAd, offset + 4, pn_high); + } + else + { + DBGPRINT(RT_DEBUG_WARN, ("%s : Not support HW_WAPI_PN_TABLE\n", + __FUNCTION__)); + } + +} +#endif /* WAPI_SUPPORT */ + + + + + +#ifdef 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; + + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return; + } + + if (!pAd->chipCap.FlgHwStreamMode) + return; + + streamWord = StreamModeRegVal(pAd); + if (!bEnabled) + streamWord = 0; + + regAddr = TX_CHAIN_ADDR0_L + chainIdx * 8; + RTMP_IO_WRITE32(pAd, regAddr, + (UINT32)(pMacAddr[0]) | + (UINT32)(pMacAddr[1] << 8) | + (UINT32)(pMacAddr[2] << 16) | + (UINT32)(pMacAddr[3] << 24)); + + RTMP_IO_READ32(pAd, regAddr + 4, ®Val); + regVal &= (~0x000f0000); + RTMP_IO_WRITE32(pAd, regAddr + 4, + (regVal | streamWord) | + (UINT32)(pMacAddr[4]) | + (UINT32)(pMacAddr[5] << 8)); + +} + + +VOID RtmpStreamModeInit(RTMP_ADAPTER *pAd) +{ + int chainIdx; + UCHAR *pMacAddr; + + if (pAd->chipCap.FlgHwStreamMode == FALSE) + return; + + for (chainIdx = 0; chainIdx < STREAM_MODE_STA_NUM; chainIdx++) + { + pMacAddr = &pAd->CommonCfg.StreamModeMac[chainIdx][0]; + AsicSetStreamMode(pAd, pMacAddr, chainIdx, TRUE); + } +} +#endif // STREAM_MODE_SUPPORT // + + +VOID AsicSetTxPreamble(RTMP_ADAPTER *pAd, USHORT TxPreamble) +{ + //AUTO_RSP_CFG_STRUC csr4; + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return; + } +} + + +#ifdef DOT11_N_SUPPORT +INT AsicSetRalinkBurstMode(RTMP_ADAPTER *pAd, BOOLEAN enable) +{ +#ifdef MT_MAC + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return FALSE; + } +#else + UINT32 Data = 0; + + RTMP_IO_READ32(pAd, EDCA_AC0_CFG, &Data); + if (enable) + { + pAd->CommonCfg.RestoreBurstMode = Data; + Data &= 0xFFF00000; + Data |= 0x86380; + } else { + Data = pAd->CommonCfg.RestoreBurstMode; + Data &= 0xFFFFFF00; + + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE) +#ifdef DOT11_N_SUPPORT + && (pAd->MacTab.fAnyStationMIMOPSDynamic == FALSE) +#endif // DOT11_N_SUPPORT // + ) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RDG_ACTIVE)) + Data |= 0x80; + else if (pAd->CommonCfg.bEnableTxBurst) + Data |= 0x20; + } + } + RTMP_IO_WRITE32(pAd, EDCA_AC0_CFG, Data); + + if (enable) + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE); + else + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RALINK_BURST_MODE); + +#endif /* MT_MAC */ + return TRUE; +} + + +INT AsicUpdateTxOP(RTMP_ADAPTER *pAd, UINT32 ac_num, UINT32 txop_val) +{ + UINT32 last_txop_val; + + if (pAd->CommonCfg.ManualTxop) + { + return TRUE; + } + + last_txop_val = pAd->CurrEdcaParam[ac_num].u2Txop; + + if (last_txop_val == txop_val) + { /* No need to Update TxOP CR */ + return TRUE; + } + else if (last_txop_val == 0xdeadbeef) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Error CR value for TxOP = 0x%08x\n", __FUNCTION__, last_txop_val)); + + return FALSE; + } + else {} + + AsicSetWmmParam(pAd, ac_num, WMM_PARAM_TXOP, txop_val); + + return TRUE; +} +#endif // DOT11_N_SUPPORT // + + + + +#ifdef MICROWAVE_OVEN_SUPPORT +VOID AsicMeasureFalseCCA(RTMP_ADAPTER *pAd) +{ + if (pAd->chipOps.AsicMeasureFalseCCA) + pAd->chipOps.AsicMeasureFalseCCA(pAd); +} + +VOID AsicMitigateMicrowave(RTMP_ADAPTER *pAd) +{ + if (pAd->chipOps.AsicMitigateMicrowave) + pAd->chipOps.AsicMitigateMicrowave(pAd); +} +#endif /* MICROWAVE_OVEN_SUPPORT */ + + +INT AsicWaitMacTxRxIdle(RTMP_ADAPTER *pAd) +{ + return TRUE; +} + + +INT32 AsicSetMacTxRx(RTMP_ADAPTER *pAd, INT32 TxRx, BOOLEAN Enable) +{ + UINT32 Value, Value1, Value2, Value3; + + RTMP_IO_READ32(pAd, ARB_SCR, &Value); + RTMP_IO_READ32(pAd, ARB_TQCR0, &Value1); + RTMP_IO_READ32(pAd, ARB_RQCR, &Value2); + RTMP_IO_READ32(pAd, WF_PHY_BASE + 0x426c, &Value3); + + switch (TxRx) + { + case ASIC_MAC_TX: + if (Enable) + { + Value &= ~MT_ARB_SCR_TXDIS; + Value1 = 0xffffffff; + } + else + { + Value |= MT_ARB_SCR_TXDIS; + Value1 = 0; + } + break; + case ASIC_MAC_RX: + if (Enable) + { + Value &= ~MT_ARB_SCR_RXDIS; + Value2 |= ARB_RQCR_RX_START; + } + else + { + Value |= MT_ARB_SCR_RXDIS; + Value2 &= ~ARB_RQCR_RX_START; + } + break; + case ASIC_MAC_TXRX: + if (Enable) + { + Value &= ~(MT_ARB_SCR_TXDIS | MT_ARB_SCR_RXDIS); + Value1 = 0xffffffff; + Value2 |= ARB_RQCR_RX_START; + } + else + { + Value |= (MT_ARB_SCR_TXDIS | MT_ARB_SCR_RXDIS); + Value1 = 0; + Value2 &= ~ARB_RQCR_RX_START; + + } + break; + case ASIC_MAC_TXRX_RXV: + if (Enable) + { + Value &= ~(MT_ARB_SCR_TXDIS | MT_ARB_SCR_RXDIS); + Value1 = 0xffffffff; + Value2 |= (ARB_RQCR_RX_START | ARB_RQCR_RXV_START | + ARB_RQCR_RXV_R_EN | ARB_RQCR_RXV_T_EN); + Value3 &= 0xffffff0f; + Value3 |= 0x40; + } + else + { + Value |= (MT_ARB_SCR_TXDIS | MT_ARB_SCR_RXDIS); + Value1 = 0; + Value2 &= ~(ARB_RQCR_RX_START | ARB_RQCR_RXV_START | + ARB_RQCR_RXV_R_EN | ARB_RQCR_RXV_T_EN); + } + break; + case ASIC_MAC_RXV: + if (Enable) + { + Value &= ~MT_ARB_SCR_RXDIS; + Value2 |= (ARB_RQCR_RXV_START | + ARB_RQCR_RXV_R_EN | ARB_RQCR_RXV_T_EN); + } + else + { + Value2 &= ~(ARB_RQCR_RXV_START | + ARB_RQCR_RXV_R_EN | ARB_RQCR_RXV_T_EN); + } + break; + case ASIC_MAC_RX_RXV: + if (Enable) + { + + Value &= ~MT_ARB_SCR_RXDIS; + Value2 |= (ARB_RQCR_RX_START | ARB_RQCR_RXV_START | + ARB_RQCR_RXV_R_EN | ARB_RQCR_RXV_T_EN); + + } + else + { + Value |= MT_ARB_SCR_RXDIS; + Value2 &= ~(ARB_RQCR_RX_START | ARB_RQCR_RXV_START | + ARB_RQCR_RXV_R_EN | ARB_RQCR_RXV_T_EN); + } + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknown path (%d\n", __FUNCTION__, + TxRx)); + break; + } + + RTMP_IO_WRITE32(pAd, ARB_SCR, Value); + RTMP_IO_WRITE32(pAd, ARB_TQCR0, Value1); + RTMP_IO_WRITE32(pAd, ARB_RQCR, Value2); + RTMP_IO_WRITE32(pAd, WF_PHY_BASE + 0x426c, Value3); + + return TRUE; +} + + +INT AsicSetWPDMA(RTMP_ADAPTER *pAd, INT32 TxRx, BOOLEAN enable) +{ +#ifdef RTMP_MAC_PCI + WPDMA_GLO_CFG_STRUC GloCfg; + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type != HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Invalid HIF type(%d)!\n", + __FUNCTION__, __LINE__, pAd->chipCap.hif_type)); + return FALSE; + } + + RTMP_IO_READ32(pAd, MT_WPDMA_GLO_CFG , &GloCfg.word); + + switch (TxRx) + { + case PDMA_TX: + if (enable == TRUE) + { + GloCfg.field.EnableTxDMA = 1; + GloCfg.field.EnTXWriteBackDDONE = 1; + GloCfg.field.WPDMABurstSIZE = pAd->chipCap.WPDMABurstSIZE; + } else { + GloCfg.field.EnableTxDMA = 0; + GloCfg.field.EnTXWriteBackDDONE = 0; + } + break; + case PDMA_RX: + if (enable == TRUE) + { + GloCfg.field.EnableRxDMA = 1; + GloCfg.field.WPDMABurstSIZE = pAd->chipCap.WPDMABurstSIZE; + } else { + GloCfg.field.EnableRxDMA = 0; + } + break; + case PDMA_TX_RX: + if (enable == TRUE) + { + GloCfg.field.EnableTxDMA = 1; + GloCfg.field.EnableRxDMA = 1; + GloCfg.field.EnTXWriteBackDDONE = 1; + GloCfg.field.WPDMABurstSIZE = pAd->chipCap.WPDMABurstSIZE; + } else { + GloCfg.field.EnableRxDMA = 0; + GloCfg.field.EnableTxDMA = 0; + GloCfg.field.EnTXWriteBackDDONE = 0; + } + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknown path (%d\n", __FUNCTION__, TxRx)); + break; + } + + RTMP_IO_WRITE32(pAd, MT_WPDMA_GLO_CFG, GloCfg.word); +#endif + + return TRUE; +} + + +BOOLEAN AsicWaitPDMAIdle(struct _RTMP_ADAPTER *pAd, INT round, INT wait_us) +{ +#ifdef RTMP_MAC_PCI + INT i = 0; + WPDMA_GLO_CFG_STRUC GloCfg; + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type != HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Invalid HIF type(%d)!\n", + __FUNCTION__, __LINE__, pAd->chipCap.hif_type)); + return FALSE; + } + + do { + RTMP_IO_READ32(pAd, MT_WPDMA_GLO_CFG, &GloCfg.word); + if ((GloCfg.field.TxDMABusy == 0) && (GloCfg.field.RxDMABusy == 0)) { + DBGPRINT(RT_DEBUG_TRACE, ("==> DMAIdle, GloCfg=0x%x\n", GloCfg.word)); + return TRUE; + } + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return FALSE; + RtmpusecDelay(wait_us); + }while ((i++) < round); + + DBGPRINT(RT_DEBUG_TRACE, ("==> DMABusy, GloCfg=0x%x\n", GloCfg.word)); + + return FALSE; +#endif + return TRUE; +} + + +INT AsicSetMacWD(RTMP_ADAPTER *pAd) +{ + return TRUE; +} + + +INT rtmp_asic_hif_init(RTMP_ADAPTER *pAd) +{ + + return TRUE; +} + + +INT StopDmaRx(RTMP_ADAPTER *pAd, UCHAR Level) +{ + PNDIS_PACKET pRxPacket; + RX_BLK RxBlk, *pRxBlk; + UINT32 RxPending = 0, MacReg = 0, MTxCycle = 0; + BOOLEAN bReschedule = FALSE; + + DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__)); + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return 0; + } + + /* + process whole rx ring + */ + while (1) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return 0; + pRxBlk = &RxBlk; + pRxPacket = GetPacketFromRxRing(pAd, pRxBlk, &bReschedule, &RxPending, 0); + if ((RxPending == 0) && (bReschedule == FALSE)) + break; + else + RELEASE_NDIS_PACKET(pAd, pRxPacket, NDIS_STATUS_SUCCESS); + } + + /* + Check DMA Rx idle + */ + for (MTxCycle = 0; MTxCycle < 2000; MTxCycle++) + { +#ifdef RTMP_MAC_PCI + + RTMP_IO_READ32(pAd, MT_WPDMA_GLO_CFG, &MacReg); + if (MacReg & 0x8) + { + RtmpusecDelay(50); + } + else + break; + +#endif + + + if (MacReg == 0xFFFFFFFF) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); + return 0; + } + } + + if (MTxCycle >= 2000) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s:RX DMA busy!! DMA_CFG = 0x%08x\n", __FUNCTION__, MacReg)); + } + + if (Level == RTMP_HALT) + { + /* Disable DMA RX */ +#ifdef RTMP_MAC_PCI + RTMP_IO_READ32(pAd, MT_WPDMA_GLO_CFG, &MacReg); + MacReg &= ~(0x4); + RTMP_IO_WRITE32(pAd, MT_WPDMA_GLO_CFG, MacReg); +#endif + } + + DBGPRINT(RT_DEBUG_TRACE, ("<==== %s\n", __FUNCTION__)); + + return 0; +} + + +INT StopDmaTx(RTMP_ADAPTER *pAd, UCHAR Level) +{ + UINT32 MacReg = 0, MTxCycle = 0; + + DBGPRINT(RT_DEBUG_TRACE, ("====> %s\n", __FUNCTION__)); + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return 0; + } + + for (MTxCycle = 0; MTxCycle < 2000; MTxCycle++) + { +#ifdef RTMP_MAC_PCI + RTMP_IO_READ32(pAd, MT_WPDMA_GLO_CFG, &MacReg); + if ((MacReg & 0x2) == 0) + { + DBGPRINT(RT_DEBUG_TRACE, ("==> DMA Tx Idle, MacReg=0x%x\n", MacReg)); + break; + } +#endif + + + if (MacReg == 0xFFFFFFFF) + { + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST); + return 0; + } + } + + if (MTxCycle >= 2000) + { + DBGPRINT(RT_DEBUG_ERROR, ("TX DMA busy!! DMA_CFG(%x)\n", MacReg)); + } + + if (Level == RTMP_HALT) + { +#ifdef RTMP_MAC_PCI + RTMP_IO_READ32(pAd, MT_WPDMA_GLO_CFG, &MacReg); + MacReg &= ~(0x00000001); + RTMP_IO_WRITE32(pAd, MT_WPDMA_GLO_CFG, MacReg); +#endif + + } + + DBGPRINT(RT_DEBUG_TRACE, ("<==== %s\n", __FUNCTION__)); + + return 0; +} + + +#ifdef DOT11_N_SUPPORT +INT AsicReadAggCnt(RTMP_ADAPTER *pAd, ULONG *aggCnt, int cnt_len) +{ + NdisZeroMemory(aggCnt, cnt_len * sizeof(ULONG)); + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return FALSE; + } + + return TRUE; +} + +#endif /* DOT11_N_SUPPORT */ + + +INT AsicSetTxStream(RTMP_ADAPTER *pAd, UINT32 StreamNums) +{ + UINT32 Value; + + RTMP_IO_READ32(pAd, TMAC_TCR, &Value); + + Value &= ~TMAC_TCR_TX_STREAM_NUM_MASK; + Value |= TMAC_TCR_TX_STREAM_NUM(StreamNums - 1); + + RTMP_IO_WRITE32(pAd, TMAC_TCR, Value); + + return TRUE; +} + + +INT AsicSetRxStream(RTMP_ADAPTER *pAd, UINT32 StreamNums) +{ + UINT32 Value, Mask = 0; + INT Ret = TRUE; + + RTMP_IO_READ32(pAd, RMAC_RMCR, &Value); + + Value &= ~(RMAC_RMCR_RX_STREAM_0 | + RMAC_RMCR_RX_STREAM_1 | + RMAC_RMCR_RX_STREAM_2); + + switch (StreamNums) { + case 3: + Mask |= RMAC_RMCR_RX_STREAM_2; + case 2: + Mask |= RMAC_RMCR_RX_STREAM_1; + case 1: + Mask |= RMAC_RMCR_RX_STREAM_0; + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("illegal StreamNums(%d\n", StreamNums)); + Ret = FALSE; + break; + } + + if (Ret) + { + Value |= Mask; + + Value &= ~RMAC_RMCR_SMPS_MODE_MASK; + Value |= RMAC_RMCR_SMPS_MODE(DISABLE_SMPS_RX_BYSETTING); + + RTMP_IO_WRITE32(pAd, RMAC_RMCR, Value); + } + + return Ret; +} + + +INT AsicSetBW(RTMP_ADAPTER *pAd, INT bw) +{ + UINT32 val; + + RTMP_IO_READ32(pAd, AGG_BWCR, &val); + val &= (~0x0c); + switch (bw) + { + case BW_20: + val |= (0); + break; + case BW_40: + val |= (0x1 << 2); + break; + case BW_80: + val |= (0x2 << 2); + break; + } + RTMP_IO_WRITE32(pAd, AGG_BWCR, val); + + bbp_set_bw(pAd, bw); + + return TRUE; +} + + +INT AsicSetChannel(RTMP_ADAPTER *pAd, UCHAR ch, UINT8 bw, UINT8 ext_ch, BOOLEAN bScan) +{ + bbp_set_bw(pAd, bw); + + /* Tx/RX : control channel setting */ + bbp_set_ctrlch(pAd, ext_ch); + mt_mac_set_ctrlch(pAd, ext_ch); + + /* Let BBP register at 20MHz to do scan */ + AsicSwitchChannel(pAd, ch, bScan); + AsicLockChannel(pAd, ch); + +#ifdef RT28xx + RT28xx_ch_tunning(pAd, bw); +#endif /* RT28xx */ + + return 0; +} + + +INT AsicSetRxPath(RTMP_ADAPTER *pAd, UINT32 RxPathSel) +{ + UINT32 Value = 0, Mask = 0; + INT Ret = TRUE; + + RTMP_IO_READ32(pAd, RMAC_RMCR, &Value); + + Value &= ~(RMAC_RMCR_RX_STREAM_0 | + RMAC_RMCR_RX_STREAM_1 | + RMAC_RMCR_RX_STREAM_2); + + switch (RxPathSel) { + case 0: /* ALL */ + Mask = (RMAC_RMCR_RX_STREAM_0 | RMAC_RMCR_RX_STREAM_1 | RMAC_RMCR_RX_STREAM_2); + if ((MTK_REV_GTE(pAd, MT7603, MT7603E1)) || + (MTK_REV_GTE(pAd, MT7628, MT7628E1)) || + (MTK_REV_GTE(pAd, MT7603, MT7603E2))) + { + RTMP_IO_WRITE32(pAd, CR_RXTD_39, 0x0004ba43); + } + break; + case 1: /* RX0 */ + Mask = RMAC_RMCR_RX_STREAM_0; + if ((MTK_REV_GTE(pAd, MT7603, MT7603E1)) || + (MTK_REV_GTE(pAd, MT7628, MT7628E1)) || + (MTK_REV_GTE(pAd, MT7603, MT7603E2))) + { + RTMP_IO_WRITE32(pAd, CR_RXTD_39, 0x0004ba43); + } + break; + case 2: /* RX1 */ + Mask = RMAC_RMCR_RX_STREAM_1; + if ((MTK_REV_GTE(pAd, MT7603, MT7603E1)) || + (MTK_REV_GTE(pAd, MT7628, MT7628E1)) || + (MTK_REV_GTE(pAd, MT7603, MT7603E2))) + { + RTMP_IO_WRITE32(pAd, CR_RXTD_39, 0x0005ba43); + } + break; + case 3: /* RX2 */ + Mask = RMAC_RMCR_RX_STREAM_2; + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("illegal RxPath(%d\n", RxPathSel)); + Ret = FALSE; + break; + } + + if (Ret) + { + Value |= Mask; + + Value &= ~RMAC_RMCR_SMPS_MODE_MASK; + Value |= RMAC_RMCR_SMPS_MODE(DISABLE_SMPS_RX_BYSETTING); + + RTMP_IO_WRITE32(pAd, RMAC_RMCR, Value); + } + + return Ret; + +} + +#ifdef CONFIG_ATE +INT AsicSetTxTonePower(RTMP_ADAPTER *pAd, INT dec0, INT dec1) +{ + INT Ret = TRUE; + + DBGPRINT(RT_DEBUG_OFF,("%s-v2 dec0 = %d, dec1 = %d\n",__FUNCTION__,dec0,dec1)); + if( dec0<0 || dec0>0xF || dec1>31 || dec1<-32) { + DBGPRINT(RT_DEBUG_ERROR,("%s dec value invalid\n",__FUNCTION__)); + DBGPRINT(RT_DEBUG_ERROR,("%s dec0 0~F, dec1 -32~31\n",__FUNCTION__)); + if(dec0 > 0xf) + dec0 = 0xf; + if(dec1 > 31) + dec1 = 31; + } + if((MTK_REV_GTE(pAd, MT7603, MT7603E1))|| + (MTK_REV_GTE(pAd, MT7603, MT7603E2))){ + UCHAR PowerDec0 = dec0&0x0F; + UINT32 SetValue = 0x04000000; + ULONG Tempdec1 = 0; + + SetValue |= PowerDec0<<20; + + //RF Gain 1 db + DBGPRINT(RT_DEBUG_TRACE,("%s RF 1db SetValue = 0x%x\n",__FUNCTION__,SetValue)); + + CmdRFRegAccessWrite(pAd, 0, 0x70, SetValue); //bit 26(0x04000000) is enable + CmdRFRegAccessWrite(pAd, 1, 0x70, SetValue); + //DC Gain + if(dec1<0){ + Tempdec1 = (0x40+dec1); + }else{ + Tempdec1 = dec1; + } + SetValue = 0x40000000|(Tempdec1<<20); + DBGPRINT(RT_DEBUG_TRACE,("%s DC 0.25db SetValue = 0x%x\n",__FUNCTION__,SetValue)); + RTMP_IO_WRITE32(pAd, CR_TSSI_9, SetValue); //0x10D24, bit 30(0x40000000) isenable + RTMP_IO_WRITE32(pAd, CR_WF1_TSSI_9, SetValue); //0x11D24, bit 30(0x40000000) isenable + }else{ + DBGPRINT(RT_DEBUG_OFF,("%s, for MT7636\n ",__FUNCTION__)); + /* For 7636 FW command */ + } + + return Ret; +} + +INT AsicSetRfFreqOffset(RTMP_ADAPTER *pAd, UINT32 FreqOffset) +{ + UINT32 Value = 0; + INT Ret = TRUE; + + if (FreqOffset > 127) + FreqOffset = 127; + + RTMP_IO_READ32(pAd, XTAL_CTL13, &Value); + Value &= ~DA_XO_C2_MASK; /* [14:8] (DA_XO_C2) */ + Value |= DA_XO_C2(0x3C); //set 60(DEC) + RTMP_IO_WRITE32(pAd,XTAL_CTL13,Value); + + RTMP_IO_READ32(pAd, XTAL_CTL14, &Value); + Value &= ~DA_XO_C2_MASK; + Value |= DA_XO_C2(0x7F); + RTMP_IO_WRITE32(pAd,XTAL_CTL14,Value); + + RTMP_IO_READ32(pAd, XTAL_CTL13, &Value); + Value &= ~DA_XO_C2_MASK; /* [14:8] (DA_XO_C2) */ + Value |= DA_XO_C2(FreqOffset); //set 60(DEC) + RTMP_IO_WRITE32(pAd,XTAL_CTL13,Value); + + + return Ret; +} + +INT AsicSetTSSI(RTMP_ADAPTER *pAd, UINT32 bOnOff, UCHAR WFSelect) +{ + UINT32 CRValue = 0x0; + UINT32 WF0Offset = 0x10D04; /* WF_PHY_CR_FRONT CR_WF0_TSSI_1 */ + UINT32 WF1Offset = 0x11D04; /* WF_PHY_CR_FRONT CR_WF1_TSSI_1 */ + INT Ret = TRUE; + /* !!TEST MODE ONLY!! Normal Mode control by FW and Never disable */ + /* WF0 = 0, WF1 = 1, WF ALL = 2 */ + + if (FALSE == bOnOff) + CRValue = 0xE3F3F800; + else + CRValue = 0xE1010800; + + if ((0 == WFSelect) || (2 == WFSelect)) { + DBGPRINT(RT_DEBUG_TRACE,("%s, Set WF#%d TSSI off\n",__FUNCTION__, WFSelect)); + RTMP_IO_WRITE32(pAd,WF0Offset,CRValue);//3 + } + + if ((1 == WFSelect) || (2 == WFSelect)) { + DBGPRINT(RT_DEBUG_TRACE,("%s, Set WF#%d TSSI on\n",__FUNCTION__, WFSelect)); + RTMP_IO_WRITE32(pAd,WF1Offset,CRValue);//3 + } + + return Ret; +} + +INT AsicSetDPD(RTMP_ADAPTER *pAd, UINT32 bOnOff, UCHAR WFSelect) +{ + UINT32 CRValue = 0x0; + ULONG WF0Offset = 0x10A08; + ULONG WF1Offset = 0x11A08; + INT Ret = TRUE; + /* !!TEST MODE ONLY!! Normal Mode control by FW and Never disable */ + /* WF0 = 0, WF1 = 1, WF ALL = 2 */ + + if (FALSE == bOnOff) { + //WF0 + if((0 == WFSelect) || (2 == WFSelect)) { + RTMP_IO_READ32(pAd, WF0Offset, &CRValue); + CRValue |= 0xF0000000; + RTMP_IO_WRITE32(pAd,WF0Offset,CRValue);//3 + } + //WF1 + if((1 == WFSelect) || (2 == WFSelect)) { + RTMP_IO_READ32(pAd, WF1Offset, &CRValue); + CRValue |= 0xF0000000; + RTMP_IO_WRITE32(pAd,WF1Offset,CRValue);//3 + } + DBGPRINT(RT_DEBUG_TRACE,("%s, Set WFSelect: %d DPD off\n",__FUNCTION__, WFSelect)); + } else { + if ((0 == WFSelect) || (2 == WFSelect)) { + RTMP_IO_READ32(pAd, WF0Offset, &CRValue); + CRValue &= (~0xF0000000); + RTMP_IO_WRITE32(pAd,WF0Offset,CRValue);//3 + } + if ((1 == WFSelect) || (2 == WFSelect)) { + RTMP_IO_READ32(pAd, WF1Offset, &CRValue); + CRValue &= (~0xF0000000); + RTMP_IO_WRITE32(pAd,WF1Offset,CRValue);//3 + } + DBGPRINT(RT_DEBUG_TRACE,("%s, Set WFSelect: %d DPD on\n",__FUNCTION__, WFSelect)); + } + + return Ret; +} +#ifndef CONFIG_QA +#if defined(BAND_STEERING) || defined(CUSTOMER_DCC_FEATURE) + +UINT32 AsicGetRxStat(RTMP_ADAPTER *pAd, UINT type) +{ + UINT32 value = 0; + DBGPRINT(RT_DEBUG_TRACE, ("%s, Type:%d\n", __FUNCTION__, type)); + switch (type) { + case HQA_RX_RESET_PHY_COUNT: + RTMP_IO_READ32(pAd,CR_PHYCTRL_2,&value); + value |= (1<<6); /* BIT6: CR_STSCNT_RST */ + RTMP_IO_WRITE32(pAd,CR_PHYCTRL_2,value); + value &= (~(1<<6)); + RTMP_IO_WRITE32(pAd,CR_PHYCTRL_2,value); + value |= (1<<7); /* BIT7: CR_STSCNT_EN */ + RTMP_IO_WRITE32(pAd,CR_PHYCTRL_2,value); + break; + default: + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s, Type(%d):%x\n", __FUNCTION__, type, value)); + return value; +} + +#endif +#endif +#ifdef CONFIG_QA + +UINT32 AsicGetRxStat(RTMP_ADAPTER *pAd, UINT type) +{ + UINT32 value = 0; + DBGPRINT(RT_DEBUG_TRACE, ("%s, Type:%d\n", __FUNCTION__, type)); + switch (type) { + case HQA_RX_STAT_MACFCSERRCNT: + RTMP_IO_READ32(pAd,MIB_MSDR4,&value); + value = (value >> 16) & 0xFFFF; /* [31:16] FCS ERR */ + break; + case HQA_RX_STAT_MAC_MDRDYCNT: + RTMP_IO_READ32(pAd,MIB_MSDR10,&value); + break; + case HQA_RX_STAT_PHY_MDRDYCNT: + /* [31:16] OFDM [15:0] CCK */ + RTMP_IO_READ32(pAd,RO_PHYCTRL_STS5,&value); + break; + case HQA_RX_STAT_PHY_FCSERRCNT: + /* [31:16] OFDM [15:0] CCK */ + RTMP_IO_READ32(pAd,RO_PHYCTRL_STS4,&value); + break; + case HQA_RX_STAT_PD: + /* [31:16] OFDM [15:0] CCK */ + RTMP_IO_READ32(pAd,RO_PHYCTRL_STS0,&value); + break; + case HQA_RX_STAT_CCK_SIG_SFD: + /* [31:16] SIG [15:0] SFD */ + RTMP_IO_READ32(pAd,RO_PHYCTRL_STS1,&value); + break; + case HQA_RX_STAT_OFDM_SIG_TAG: + /* [31:16] SIG [15:0] TAG */ + RTMP_IO_READ32(pAd,RO_PHYCTRL_STS2,&value); + break; + case HQA_RX_STAT_RSSI: + /*[31:24]IBRSSI0 [23:16]WBRSSI0 [15:8]IBRSSI1 [7:0]WBRSSI1*/ + RTMP_IO_READ32(pAd,RO_AGC_DEBUG_2,&value); + break; + case HQA_RX_RESET_PHY_COUNT: + RTMP_IO_READ32(pAd,CR_PHYCTRL_2,&value); + value |= (1<<6); /* BIT6: CR_STSCNT_RST */ + RTMP_IO_WRITE32(pAd,CR_PHYCTRL_2,value); + value &= (~(1<<6)); + RTMP_IO_WRITE32(pAd,CR_PHYCTRL_2,value); + value |= (1<<7); /* BIT7: CR_STSCNT_EN */ + RTMP_IO_WRITE32(pAd,CR_PHYCTRL_2,value); + break; + default: + break; + } + DBGPRINT(RT_DEBUG_TRACE, ("%s, Type(%d):%x\n", __FUNCTION__, type, value)); + return value; +} +#endif /* CONFIG_QA */ + +INT AsicSetTxToneTest(RTMP_ADAPTER *pAd, UINT32 bOnOff, UCHAR Type) +{ + DBGPRINT(RT_DEBUG_TRACE, ("%s, bOnOff:%d Type:%d\n", __FUNCTION__, bOnOff, Type)); + + if (bOnOff == 0) { /* 0 = off 1 = on */ + //WF0 + RTMP_IO_WRITE32(pAd, CR_PHYCK_CTRL, 0x00000000); //0x10000 + RTMP_IO_WRITE32(pAd, CR_FR_CKG_CTRL, 0x00000000); //0x10004 + RTMP_IO_WRITE32(pAd, CR_TSSI_0, 0x80274027); //0x10D00 + RTMP_IO_WRITE32(pAd, CR_TSSI_1, 0xC0000800); //0x10D04 + RTMP_IO_WRITE32(pAd, CR_PHYMUX_3, 0x00000008); //0x1420C + RTMP_IO_WRITE32(pAd, CR_PHYMUX_5, 0x00000580); //0x14214 + RTMP_IO_WRITE32(pAd, CR_TXFD_1, 0x00000000); //0x14704 + RTMP_IO_WRITE32(pAd, CR_TSSI_9, 0x00000000); //0x10D24 + RTMP_IO_WRITE32(pAd, CR_TXFE_3, 0x00000000); //0x10A08 + RTMP_IO_WRITE32(pAd, CR_TXPTN_00, 0x00000000); //0x101A0 + RTMP_IO_WRITE32(pAd, CR_TXPTN_01, 0x00000000); //0x101A4 + RTMP_IO_WRITE32(pAd, CR_RFINTF_03, 0x00000000); //0x1020C + RTMP_IO_WRITE32(pAd, CR_TXFE_4, 0x00000000); //0x10A0C + RTMP_IO_WRITE32(pAd, CR_DPD_CAL_03, 0x20300604); //0x1090C + //WF1 + RTMP_IO_WRITE32(pAd, CR_PHYCK_CTRL, 0x00000000); //0x10000 + RTMP_IO_WRITE32(pAd, CR_FR_CKG_CTRL, 0x00000000); //0x10004 + RTMP_IO_WRITE32(pAd, CR_WF1_TSSI_0, 0x80274027); //0x11D00 + RTMP_IO_WRITE32(pAd, CR_WF1_TSSI_1, 0xC0000800); //0x11D04 + RTMP_IO_WRITE32(pAd, CR_PHYMUX_WF1_3, 0x00000008); //0x1520C + RTMP_IO_WRITE32(pAd, CR_PHYMUX_WF1_5, 0x00000580); //0x15214 + RTMP_IO_WRITE32(pAd, CR_TXFD_1, 0x00000000); //0x14704 + RTMP_IO_WRITE32(pAd, CR_WF1_TSSI_9, 0x00000000); //0x11D24 + RTMP_IO_WRITE32(pAd, CR_TXFE1_3, 0x00000000); //0x11A08 + RTMP_IO_WRITE32(pAd, CR_TXPTN_00, 0x00000000); //0x101A0 + RTMP_IO_WRITE32(pAd, CR_TXPTN_01, 0x00000000); //0x101A4 + RTMP_IO_WRITE32(pAd, CR_RFINTF_03, 0x00000000); //0x1020C + RTMP_IO_WRITE32(pAd, CR_TXFE1_4, 0x00000000); //0x11A0C + RTMP_IO_WRITE32(pAd, CR_DPD_CAL_03, 0x20300604); //0x1090C + } else if (bOnOff == 1) { + /* WF0 */ + if (Type == WF0_TX_ONE_TONE_5M || Type == WF0_TX_TWO_TONE_5M || + Type == WF0_TX_ONE_TONE_10M || Type == WF0_TX_ONE_TONE_DC) { + /* 1. clock setup */ + RTMP_IO_WRITE32(pAd, CR_PHYCK_CTRL, 0x00000021); + RTMP_IO_WRITE32(pAd, CR_FR_CKG_CTRL, 0x00000021); + + /* 2. TX setup */ + RTMP_IO_WRITE32(pAd, CR_TSSI_0, 0x00274027); + RTMP_IO_WRITE32(pAd, CR_TSSI_1, 0xC0000400); + RTMP_IO_WRITE32(pAd, CR_PHYMUX_3, 0x80000008); + RTMP_IO_WRITE32(pAd, CR_PHYMUX_5, 0x00000597); + RTMP_IO_WRITE32(pAd, CR_TXFD_1, 0x10000000); + RTMP_IO_WRITE32(pAd, CR_TSSI_9, 0x60000000); + RTMP_IO_WRITE32(pAd, CR_TXFE_3, 0xF0000000); + + /* 3. Gen Tone */ + if (Type == WF0_TX_ONE_TONE_5M) { + RTMP_IO_WRITE32(pAd, CR_TXPTN_00, 0x000C100C); + RTMP_IO_WRITE32(pAd, CR_TXPTN_01, 0x00000000); + RTMP_IO_WRITE32(pAd, CR_RFINTF_03, 0x00010122); + RTMP_IO_WRITE32(pAd, CR_TXFE_4, 0x000000C0); + } else if (Type == WF0_TX_TWO_TONE_5M) { + RTMP_IO_WRITE32(pAd, CR_TXPTN_00, 0x000C104C); + RTMP_IO_WRITE32(pAd, CR_TXPTN_01, 0x00000000); + RTMP_IO_WRITE32(pAd, CR_RFINTF_03, 0x00010122); + RTMP_IO_WRITE32(pAd, CR_TXFE_4, 0x000000C0); + } else if (Type == WF0_TX_ONE_TONE_10M) { + RTMP_IO_WRITE32(pAd, CR_TXPTN_00, 0x000C101C); + RTMP_IO_WRITE32(pAd, CR_TXPTN_01, 0x00000000); + RTMP_IO_WRITE32(pAd, CR_RFINTF_03, 0x00011122); + RTMP_IO_WRITE32(pAd, CR_TXFE_4, 0x000000C0); + } else if (Type == WF0_TX_ONE_TONE_DC) { + RTMP_IO_WRITE32(pAd, CR_TXPTN_00, 0x000C1048); + RTMP_IO_WRITE32(pAd, CR_TXPTN_01, 0x07000700); + RTMP_IO_WRITE32(pAd, CR_RFINTF_03, 0x00010122); + RTMP_IO_WRITE32(pAd, CR_TXFE_4, 0x000000C0); + } else { + DBGPRINT(RT_DEBUG_WARN,("%s Type = %d error!!!\n",__FUNCTION__, Type)); + } + + } else if (Type == WF1_TX_ONE_TONE_5M || Type == WF1_TX_TWO_TONE_5M || + Type == WF1_TX_ONE_TONE_10M || Type == WF1_TX_ONE_TONE_DC) { + /* 1. clock setup */ + RTMP_IO_WRITE32(pAd, CR_PHYCK_CTRL, 0x00000021); + RTMP_IO_WRITE32(pAd, CR_FR_CKG_CTRL, 0x00000021); + + /* 2. TX setup */ + RTMP_IO_WRITE32(pAd, CR_WF1_TSSI_0, 0x00274027); + RTMP_IO_WRITE32(pAd, CR_WF1_TSSI_1, 0xC0000400); + RTMP_IO_WRITE32(pAd, CR_PHYMUX_WF1_3, 0x80000008); + RTMP_IO_WRITE32(pAd, CR_PHYMUX_WF1_5, 0x00000597); + RTMP_IO_WRITE32(pAd, CR_TXFD_1, 0x10000000); + RTMP_IO_WRITE32(pAd, CR_WF1_TSSI_9, 0x60000000); + RTMP_IO_WRITE32(pAd, CR_TXFE1_3, 0xF0000000); + + /* 3. Gen Tone */ + if (Type == WF1_TX_ONE_TONE_5M) { + RTMP_IO_WRITE32(pAd, CR_TXPTN_00, 0x000C100C); + RTMP_IO_WRITE32(pAd, CR_TXPTN_01, 0x00000000); + RTMP_IO_WRITE32(pAd, CR_RFINTF_03, 0x00010122); + RTMP_IO_WRITE32(pAd, CR_TXFE1_4, 0x000000C0); + } else if (Type == WF1_TX_TWO_TONE_5M) { + RTMP_IO_WRITE32(pAd, CR_TXPTN_00, 0x000C104C); + RTMP_IO_WRITE32(pAd, CR_TXPTN_01, 0x00000000); + RTMP_IO_WRITE32(pAd, CR_RFINTF_03, 0x00010122); + RTMP_IO_WRITE32(pAd, CR_TXFE1_4, 0x000000C0); + } else if (Type == WF1_TX_ONE_TONE_10M) { + RTMP_IO_WRITE32(pAd, CR_TXPTN_00, 0x000C101C); + RTMP_IO_WRITE32(pAd, CR_TXPTN_01, 0x00000000); + RTMP_IO_WRITE32(pAd, CR_RFINTF_03, 0x00011122); + RTMP_IO_WRITE32(pAd, CR_TXFE1_4, 0x000000C0); + } else if (Type == WF1_TX_ONE_TONE_DC) { + RTMP_IO_WRITE32(pAd, CR_TXPTN_00, 0x000C1048); + RTMP_IO_WRITE32(pAd, CR_TXPTN_01, 0x07000700); + RTMP_IO_WRITE32(pAd, CR_RFINTF_03, 0x00010122); + RTMP_IO_WRITE32(pAd, CR_TXFE1_4, 0x000000C0); + } else { + DBGPRINT(RT_DEBUG_WARN,("%s Type = %d error!!!\n",__FUNCTION__, Type)); + } + + } else { + DBGPRINT(RT_DEBUG_WARN,("%s Type = %d error!!!\n",__FUNCTION__, Type)); + } + } else { + DBGPRINT(RT_DEBUG_WARN,("%s bOnOff = %d error!!!\n",__FUNCTION__, bOnOff)); + } + + return 0; +} + +INT AsicStartContinousTx(RTMP_ADAPTER *pAd, UINT32 PhyMode, UINT32 BW, UINT32 PriCh, UINT32 Mcs, UINT32 WFSel) +{ + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + ATE_OPERATION *ATEOp = ATECtrl->ATEOp; + + UINT32 value = 0; + /* Band Edge */ + UINT32 cr_hilo = 0; + UINT32 bit = 0; + + UINT32 i = 0; + UINT32 reg = 0; + UINT32 reg1 = 0; + UINT32 reg2 = 0; + /* TSSI Patch */ + ATECtrl->Sgi = 0; + ATECtrl->tssi0_wf0_cr = 0; + ATECtrl->tssi0_wf1_cr = 0; + ATECtrl->tssi1_wf0_cr = 0; + ATECtrl->tssi1_wf1_cr = 0; + ATECtrl->phy_mux_27 = 0; + /* Change TSSI Training Time */ + RTMP_IO_READ32(pAd, CR_TSSI_0, &(ATECtrl->tssi0_wf0_cr)); //0x0D00 + RTMP_IO_READ32(pAd, CR_WF1_TSSI_0, &(ATECtrl->tssi0_wf1_cr)); //0x1D00 + RTMP_IO_READ32(pAd, CR_TSSI_1, &(ATECtrl->tssi1_wf0_cr)); //0x0D04 + RTMP_IO_READ32(pAd, CR_WF1_TSSI_1, &(ATECtrl->tssi1_wf1_cr)); //0x1D04 + + RTMP_IO_READ32(pAd, CR_TSSI_6, ®); /* 0x0D18 */ + RTMP_IO_READ32(pAd, CR_TSSI_13, ®1); /* 0x1D18 */ + + RTMP_IO_WRITE32(pAd, CR_FR_RST_CTRL, 0xFFFFFFFF); //0x10008 + RTMP_IO_WRITE32(pAd, CR_BK_RST_CTRL, 0xFFFFFFFF); //0x14004 + DBGPRINT(RT_DEBUG_TRACE,("%s(): 0x0D18: 0x%x, tx_pwr(0x0D34):0x%x\n", __FUNCTION__, reg, reg1)); + for(i=0; i<2; i++){ + mdelay(200); + ATECtrl->TxCount = 8; + ATECtrl->bQATxStart = TRUE; + ATEOp->StartTx(pAd); + DBGPRINT(RT_DEBUG_TRACE,("%s(): finish Start Tx\n",__FUNCTION__)); + mdelay(100); + ATECtrl->bQATxStart = FALSE; + ATEOp->StopTx(pAd, ATECtrl->Mode); + DBGPRINT(RT_DEBUG_TRACE,("%s(): finish StOP Tx\n",__FUNCTION__)); + } + DBGPRINT(RT_DEBUG_TRACE,("%s(): finish Tx TSSI Train \n", __FUNCTION__)); + + /* Original Flow */ + DBGPRINT(RT_DEBUG_TRACE,("%s Modulation = %d, BW=%d, pri_ch = %d, rate = %d, WFSelect = %d-->\n",__FUNCTION__, PhyMode, BW, PriCh, Mcs, WFSel)); + RTMP_IO_READ32(pAd, CR_TSSI_6, ®); + reg1 = reg; + RTMP_IO_READ32(pAd, CR_WF1_TSSI_6, ®2); + DBGPRINT(RT_DEBUG_TRACE,("%s, 0x0D18: %08x, 0x1D18: %08x\n", __FUNCTION__, reg1, reg2)); + + RTMP_IO_WRITE32(pAd, CR_PHYCK_CTRL, 0x00000078); //0x10000 + RTMP_IO_WRITE32(pAd, CR_FR_CKG_CTRL, 0x00000078); //0x10004 + RTMP_IO_READ32(pAd, CR_TSSI_0, &(ATECtrl->tssi0_wf0_cr)); //0x0D00 + RTMP_IO_READ32(pAd, CR_WF1_TSSI_0, &(ATECtrl->tssi0_wf1_cr)); //0x1D00 + RTMP_IO_READ32(pAd, CR_TSSI_1, &(ATECtrl->tssi1_wf0_cr)); //0x0D04 + RTMP_IO_READ32(pAd, CR_WF1_TSSI_1, &(ATECtrl->tssi1_wf1_cr)); //0x1D04 + /* Contiuous Tx power patch */ + RTMP_IO_WRITE32(pAd, CR_TSSI_0, 0x024041C0); //0x0D00 + RTMP_IO_WRITE32(pAd, CR_WF1_TSSI_0, 0x024041C0); //0x1D00 + RTMP_IO_WRITE32(pAd, CR_TSSI_1, 0x23F3F800); //0x0D04 + RTMP_IO_WRITE32(pAd, CR_WF1_TSSI_1, 0x23F3F800); //0x1D04 + RTMP_IO_WRITE32(pAd, CR_TSSI_6, reg1); //0x0D18 + RTMP_IO_WRITE32(pAd, CR_WF1_TSSI_6, reg2); //0x1D18 + + RTMP_IO_WRITE32(pAd, CR_FFT_MANU_CTRL, 0x0AA00000); //0x10704 + + if (BW_20 == BW) + value = 0x00000000; + else if (BW_40 == BW) + value = 0x01000000; + else if (BW_80 == BW) + value = 0x02000000; + else + DBGPRINT(RT_DEBUG_WARN,("%s BW = %d error!!!\n",__FUNCTION__, BW)); + + if (0 == PriCh) + value |= 0x00000000; + else if (1 == PriCh) + value |= 0x00100000; + else + DBGPRINT(RT_DEBUG_WARN,("%s pri_ch = %d error!!!\n",__FUNCTION__, PriCh)); + + RTMP_IO_WRITE32(pAd, CR_PHYCTRL_0, value); //0x14100 + RTMP_IO_WRITE32(pAd, CR_PHYCTRL_DBGCTRL, 0x80000030); //0x14140 + RTMP_IO_WRITE32(pAd, CR_PHYMUX_3, 0x80680008); //0x1420C + + switch (WFSel) { + case 0: + RTMP_IO_WRITE32(pAd, CR_PHYMUX_5, 0x00000597); //0x14214 + RTMP_IO_WRITE32(pAd, CR_PHYMUX_WF1_5, 0x00000010); //0x15214 + break; + case 1: + RTMP_IO_WRITE32(pAd, CR_PHYMUX_WF1_3, 0x80680008); //0x1520C + RTMP_IO_WRITE32(pAd, CR_PHYMUX_5, 0x00000590); //0x14214 + RTMP_IO_WRITE32(pAd, CR_PHYMUX_WF1_5, 0x00000017); //0x15214 + break; + case 2: + RTMP_IO_WRITE32(pAd, CR_PHYMUX_WF1_3, 0x80680008); //0x1520C + RTMP_IO_WRITE32(pAd, CR_PHYMUX_5, 0x00000597); //0x14214 + RTMP_IO_WRITE32(pAd, CR_PHYMUX_WF1_5, 0x00000017); //0x15214 + break; + default: + DBGPRINT(RT_DEBUG_WARN,("%s WFSelect = %d error!!!\n",__FUNCTION__, WFSel)); /* No ALL?*/ + break; + } + + if (BW_20 == BW) + RTMP_IO_WRITE32(pAd, CR_TXFD_0, 0x00030000); //0x14700 + else if (BW_40 == BW) + RTMP_IO_WRITE32(pAd, CR_TXFD_0, 0x14030000); //0x14700 + else + DBGPRINT(RT_DEBUG_WARN,("%s BW = %d error!!!\n",__FUNCTION__, BW)); + + if (0 == PhyMode) { /* MODULATION_SYSTEM_CCK */ + value = 0; + switch (Mcs) { + case MCS_0: + case MCS_8: + value = 0x00000000; + break; + case MCS_1: + case MCS_9: + value = 0x00200000; + break; + case MCS_2: + case MCS_10: + value = 0x00400000; + break; + case MCS_3: + case MCS_11: + value = 0x00600000; + break; + default: + DBGPRINT(RT_DEBUG_WARN,("%s CCK rate = %d error!!!\n",__FUNCTION__, Mcs)); + break; + } + RTMP_IO_WRITE32(pAd, CR_TXFD_3, value); + } + else if (1 == PhyMode) { /* MODULATION_SYSTEM_OFDM */ + RTMP_IO_READ32(pAd, CR_PHYMUX_26, &cr_hilo); /* 0x4268 */ + value = 0; + switch (Mcs) { + case MCS_0: + value = 0x01600000; + cr_hilo &= BIT(0); + break; + case MCS_1: + value = 0x01E00000; + cr_hilo &= BIT(1); + break; + case MCS_2: + value = 0x01400000; + cr_hilo &= BIT(2); + break; + case MCS_3: + value = 0x01C00000; + cr_hilo &= BIT(3); + break; + case MCS_4: + value = 0x01200000; + cr_hilo &= BIT(4); + break; + case MCS_5: + value = 0x01900000; + cr_hilo &= BIT(5); + break; + case MCS_6: + value = 0x01000000; + cr_hilo &= BIT(6); + break; + case MCS_7: + value = 0x01800000; + cr_hilo &= BIT(7); + break; + default: + DBGPRINT(RT_DEBUG_WARN,("%s OFDM rate = %d error!!!\n",__FUNCTION__, Mcs)); + break; + } + RTMP_IO_WRITE32(pAd, CR_TXFD_3, value); //0x1470C + RTMP_IO_READ32(pAd, CR_PHYMUX_27, &value); //0x1426C + ATECtrl->phy_mux_27 = value; + if(cr_hilo == 0){ //Low Rate + bit = value & BIT(12); + value |= bit << 2; + }else{ //High Rate + bit = value & BIT(13); + value |= bit << 1; + } + RTMP_IO_WRITE32(pAd, CR_PHYMUX_27, value); //0x1426C + } + else if (2 == PhyMode || 3 == PhyMode) { + /* MODULATION_SYSTEM_HT20 || MODULATION_SYSTEM_HT40 */ + RTMP_IO_READ32(pAd, CR_PHYMUX_25, &cr_hilo); /* 0x4264 */ + value = 0; + switch(Mcs) { + case MCS_0: + value = 0x00000000; + cr_hilo &= BIT(0); + break; + case MCS_1: + value = 0x00200000; + cr_hilo &= BIT(1); + break; + case MCS_2: + value = 0x00400000; + cr_hilo &= BIT(2); + break; + case MCS_3: + value = 0x00600000; + cr_hilo &= BIT(3); + break; + case MCS_4: + value = 0x00800000; + cr_hilo &= BIT(4); + break; + case MCS_5: + value = 0x00A00000; + cr_hilo &= BIT(5); + break; + case MCS_6: + value = 0x00C00000; + cr_hilo &= BIT(6); + break; + case MCS_7: + value = 0x00E00000; + cr_hilo &= BIT(7); + break; + case MCS_32: + value = 0x04000000; + cr_hilo &= BIT(0); + break; + default: + DBGPRINT(RT_DEBUG_WARN,("%s OFDM HT MCS = %d error!!!\n",__FUNCTION__, Mcs)); + break; + } + RTMP_IO_WRITE32(pAd, CR_TXFD_3, value); //0x1470C + RTMP_IO_READ32(pAd, CR_PHYMUX_27, &value); //0x1426C + ATECtrl->phy_mux_27 = value; + if(cr_hilo == 0){ //Low Rate + bit = value & BIT(12); + value |= bit << 2; + }else{ //High Rate + bit = value & BIT(13); + value |= bit << 1; + } + RTMP_IO_WRITE32(pAd, CR_PHYMUX_27, value); //0x1426C + + } + else { + DBGPRINT(RT_DEBUG_WARN,("%s Modulation = %d error!!!\n",__FUNCTION__, PhyMode)); + } + + if (0 == WFSel) + RTMP_IO_WRITE32(pAd, CR_PHYMUX_11, 0xA0000000); //0x1422C + else if (1 == WFSel) + RTMP_IO_WRITE32(pAd, CR_PHYMUX_11, 0x90000000); //0x1422C + else + DBGPRINT(RT_DEBUG_WARN,("%s WFSelect = %d error!!!\n",__FUNCTION__, WFSel)); /* No ALL?*/ + + if (0 == PhyMode) /* PREAMBLE_CCK */ + RTMP_IO_WRITE32(pAd, CR_TXFD_1, 0x300000F8); //0x14704 + else if (1 == PhyMode) /* PREAMBLE_OFDM */ + RTMP_IO_WRITE32(pAd, CR_TXFD_1, 0x310000F2); //0x14704 + else if (2 == PhyMode || 3 == PhyMode) /* PREAMBLE_GREEN_FIELD */ + RTMP_IO_WRITE32(pAd, CR_TXFD_1, 0x320000F2); //0x14704 + else + DBGPRINT(RT_DEBUG_WARN,("%s Modulation = %d error!!!\n",__FUNCTION__, PhyMode)); + + RTMP_IO_WRITE32(pAd, CR_TXFE_4, 0x000000C0); //0x10A0C + RTMP_IO_WRITE32(pAd, CR_TXFE1_4, 0x000000C0); //0x11A0C + + return 0; +} + +INT AsicStopContinousTx(RTMP_ADAPTER *pAd) +{ + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + RTMP_IO_WRITE32(pAd, CR_TXFD_1, 0x00000005); //0x14704 + RTMP_IO_WRITE32(pAd, CR_TXFD_1, 0x00000000); //0x14704 + RTMP_IO_WRITE32(pAd, CR_PHYCK_CTRL, 0x00000045); //0x10000 + RTMP_IO_WRITE32(pAd, CR_FR_CKG_CTRL, 0x00000045); //0x10004 + RTMP_IO_WRITE32(pAd, CR_FFT_MANU_CTRL, 0x00000000); //0x10704 + RTMP_IO_WRITE32(pAd, CR_PHYCTRL_0, 0x00000000); //0x14100 + RTMP_IO_WRITE32(pAd, CR_PHYCTRL_DBGCTRL, 0x00000000); //0x14140 + RTMP_IO_WRITE32(pAd, CR_PHYMUX_3, 0x7C900408); //0x1420C + RTMP_IO_WRITE32(pAd, CR_PHYMUX_5, 0x00000580); //0x14214 + RTMP_IO_WRITE32(pAd, CR_PHYMUX_WF1_5, 0x00000000); //0x15214 + RTMP_IO_WRITE32(pAd, CR_PHYMUX_10, 0x00000000); //0x14228 + RTMP_IO_WRITE32(pAd, CR_PHYMUX_11, 0x00000000); //0x1422C + RTMP_IO_WRITE32(pAd, CR_TXFE_4, 0x00000000); //0x10A0C + RTMP_IO_WRITE32(pAd, CR_TXFE1_4, 0x00000000); //0x11A0C + RTMP_IO_WRITE32(pAd, CR_TXFD_0, 0x00000000); //0x14700 + RTMP_IO_WRITE32(pAd, CR_TXFD_3, 0x00000000); //0x1470C + RTMP_IO_WRITE32(pAd, TMAC_PCTSR, 0x00000000); //0x21708 + RTMP_IO_WRITE32(pAd, CR_FR_RST_CTRL, 0xFFFFFFFF); //0x10008 + RTMP_IO_WRITE32(pAd, CR_BK_RST_CTRL, 0xFFFFFFFF); //0x14004 + /* Restore TSSI CR */ + RTMP_IO_WRITE32(pAd, CR_TSSI_0, ATECtrl->tssi0_wf0_cr); //0x0D00 + RTMP_IO_WRITE32(pAd, CR_WF1_TSSI_0, ATECtrl->tssi0_wf1_cr); //0x1D00 + RTMP_IO_WRITE32(pAd, CR_TSSI_1, ATECtrl->tssi1_wf0_cr); //0x0D04 + RTMP_IO_WRITE32(pAd, CR_WF1_TSSI_1, ATECtrl->tssi1_wf1_cr); //0x1D04 + /* Restore Band Edge Patch CR */ + RTMP_IO_WRITE32(pAd, CR_RFINTF_01, 0x00000000); /* 0x0204 */ + RTMP_IO_WRITE32(pAd, CR_WF1_RFINTF_01, 0x00000000); /* 0x1204 */ + RTMP_IO_WRITE32(pAd, CR_PHYMUX_27, ATECtrl->phy_mux_27); //0x1426C + + return 0; +} + +#endif /* CONFIG_ATE */ +#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 val; + + DBGPRINT(RT_DEBUG_TRACE, ("%s(): Set BSSID=%02x:%02x:%02x:%02x:%02x:%02x\n", + __FUNCTION__, PRINT_MAC(pBssid))); + + val = (UINT32)((pBssid[0]) | + (UINT32)(pBssid[1] << 8) | + (UINT32)(pBssid[2] << 16) | + (UINT32)(pBssid[3] << 24)); + RTMP_IO_WRITE32(pAd, RMAC_CB1R0, val); + + val = (UINT32)(pBssid[4]) | (UINT32)(pBssid[5] << 8) | (1 <<16); + RTMP_IO_WRITE32(pAd, RMAC_CB1R1, val); + + return; +} +#endif /* MAC_APCLI_SUPPORT */ + +#ifdef NEW_WOW_SUPPORT +VOID RT28xxAndesWOWEnable( + IN PRTMP_ADAPTER pAd) +{ + NEW_WOW_MASK_CFG_STRUCT mask_cfg; + NEW_WOW_SEC_CFG_STRUCT sec_cfg; + NEW_WOW_INFRA_CFG_STRUCT infra_cfg; + NEW_WOW_P2P_CFG_STRUCT p2p_cfg; + NEW_WOW_PARAM_STRUCT wow_param; + struct CMD_UNIT CmdUnit; + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + INT32 Ret; + MAC_TABLE_ENTRY *pEntry = NULL; + + + NdisZeroMemory(&CmdUnit, sizeof(CmdUnit)); + + /* WOW enable */ + NdisZeroMemory(&wow_param, sizeof(wow_param)); + + wow_param.Parameter = WOW_ENABLE; /* WOW enable */ + wow_param.Value = TRUE; + + CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; /* feature enable */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&wow_param; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__, + CmdUnit.u.ANDES.Type, wow_param.Parameter); + return; + } + + RtmpOsMsDelay(1); + /* mask configuration */ + NdisZeroMemory(&mask_cfg, sizeof(mask_cfg)); + + mask_cfg.Config_Type = WOW_MASK_CFG; /* detect mask config */ + mask_cfg.Function_Enable = TRUE; + mask_cfg.Detect_Mask = 1UL << WOW_MAGIC_PKT; /* magic packet */ + mask_cfg.Event_Mask = 0; + + CmdUnit.u.ANDES.Type = CMD_WOW_CONFIG; /* WOW config */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_MASK_CFG_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&mask_cfg; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed!!(%d/%d)\x1b[m\n", __FUNCTION__, + CmdUnit.u.ANDES.Type, mask_cfg.Config_Type); + return; + } + + RtmpOsMsDelay(1); + + /* security configuration */ + if (pAd->StaCfg.AuthMode >= Ndis802_11AuthModeWPAPSK) + { + NdisZeroMemory(&sec_cfg, sizeof(sec_cfg)); + + sec_cfg.Config_Type = WOW_SEC_CFG; /* security config */ + + if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPAPSK) + sec_cfg.WPA_Ver = 0; + else if (pAd->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) + sec_cfg.WPA_Ver = 1; + + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + + NdisCopyMemory(sec_cfg.PTK, pEntry->PTK, 64); + NdisCopyMemory(sec_cfg.R_COUNTER, pEntry->R_Counter, LEN_KEY_DESC_REPLAY); + + sec_cfg.Key_Id = pAd->StaCfg.DefaultKeyId; + sec_cfg.Cipher_Alg = pEntry->WepStatus; + printk("\x1b[31m%s: wep status %d\x1b[m\n", __FUNCTION__, pEntry->WepStatus); + sec_cfg.Group_Cipher = pAd->StaCfg.GroupCipher; + printk("\x1b[31m%s: group status %d\x1b[m\n", __FUNCTION__, sec_cfg.Group_Cipher); + printk("\x1b[31m%s: aid %d\x1b[m\n", __FUNCTION__, pEntry->Aid); + sec_cfg.WCID = BSSID_WCID; + + CmdUnit.u.ANDES.Type = CMD_WOW_CONFIG; /* WOW config */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_SEC_CFG_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&sec_cfg; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__, + CmdUnit.u.ANDES.Type, sec_cfg.Config_Type); + return; + } + + RtmpOsMsDelay(1); + } + + /* Infra configuration */ + + NdisZeroMemory(&infra_cfg, sizeof(infra_cfg)); + + infra_cfg.Config_Type = WOW_INFRA_CFG; /* infra config */ + + COPY_MAC_ADDR(infra_cfg.STA_MAC, pAd->CurrentAddress); + COPY_MAC_ADDR(infra_cfg.AP_MAC, pAd->CommonCfg.Bssid); + + CmdUnit.u.ANDES.Type = CMD_WOW_CONFIG; /* WOW config */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_INFRA_CFG_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&infra_cfg; + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_MEDIA_STATE_CONNECTED)) + infra_cfg.AP_Status = TRUE; + else + infra_cfg.AP_Status = FALSE; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__, + CmdUnit.u.ANDES.Type, infra_cfg.Config_Type); + return; + } + + RtmpOsMsDelay(1); + + + /* P2P configuration */ + + /* Wakeup Option */ + NdisZeroMemory(&wow_param, sizeof(wow_param)); + + wow_param.Parameter = WOW_WAKEUP; /* Wakeup Option */ + if (pAd->WOW_Cfg.bInBand) + { +#ifdef RTMP_MAC_PCI + wow_param.Value = WOW_WAKEUP_BY_PCIE; +#else + wow_param.Value = WOW_WAKEUP_BY_USB; +#endif /* RTMP_MAC_PCI */ + } + else + { + INT32 Value; + + wow_param.Value = WOW_WAKEUP_BY_GPIO; + + RTMP_IO_READ32(pAd, WLAN_FUN_CTRL, &Value); + printk("\x1b[31m%s: 0x80 = %x\x1b[m\n", __FUNCTION__, Value); + Value &= ~0x01010000; /* GPIO0(ouput) --> 0(data) */ + RTMP_IO_WRITE32(pAd, WLAN_FUN_CTRL, Value); + } + + CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; /* feature enable */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&wow_param; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__, + CmdUnit.u.ANDES.Type, wow_param.Parameter); + return; + } + + RtmpOsMsDelay(1); + + + /* traffic to Andes */ + NdisZeroMemory(&wow_param, sizeof(wow_param)); + wow_param.Parameter = WOW_TRAFFIC; /* Traffic switch */ + wow_param.Value = WOW_PKT_TO_ANDES; /* incoming packet to FW */ + + CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; /* feature enable */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)&wow_param.Parameter; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed(%d/%d)!!\x1b[m\n", __FUNCTION__, + CmdUnit.u.ANDES.Type, wow_param.Parameter); + return; + } + + RtmpOsMsDelay(1); + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); +} + +VOID RT28xxAndesWOWDisable( + IN PRTMP_ADAPTER pAd) +{ + NEW_WOW_PARAM_STRUCT param; + struct CMD_UNIT CmdUnit; + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + INT32 Ret; + UINT32 Value; + MAC_TABLE_ENTRY *pEntry = NULL; + + printk("\x1b[31m%s: ...\x1b[m", __FUNCTION__); + + /* clean BulkIn Reset flag */ + //pAd->Flags &= ~0x80000; + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); + + NdisZeroMemory(&CmdUnit, sizeof(CmdUnit)); + + /* WOW disable */ + NdisZeroMemory(¶m, sizeof(param)); + param.Parameter = WOW_ENABLE; + param.Value = FALSE; + + CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; /* WOW enable */ + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)¶m; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed!!\x1b[m\n", __FUNCTION__); + return; + } + + RtmpOsMsDelay(1); + + + /* traffic to Host */ + NdisZeroMemory(¶m, sizeof(param)); + param.Parameter = WOW_TRAFFIC; + param.Value = WOW_PKT_TO_HOST; + + CmdUnit.u.ANDES.Type = CMD_WOW_FEATURE; + CmdUnit.u.ANDES.CmdPayloadLen = sizeof(NEW_WOW_PARAM_STRUCT); + CmdUnit.u.ANDES.CmdPayload = (PUCHAR)¶m; + + Ret = AsicSendCmdToAndes(pAd, &CmdUnit); + + if (Ret != NDIS_STATUS_SUCCESS) + { + printk("\x1b[31m%s: send WOW config command failed!!\x1b[m\n", __FUNCTION__); + return; + } + + RtmpOsMsDelay(1); + + + /* Restore MAC TX/RX */ + if (pAd->CommonCfg.bTXRX_RXV_ON) + AsicSetMacTxRx(pAd, ASIC_MAC_TXRX_RXV, TRUE); + else + AsicSetMacTxRx(pAd, ASIC_MAC_TXRX, TRUE); + + RTUSBBulkReceive(pAd); + RTUSBBulkCmdRspEventReceive(pAd); + + /* restore hardware remote wakeup flag */ + RTMP_IO_READ32(pAd, WLAN_FUN_CTRL, &Value); + printk("\x1b[31m%s: 0x80 %08x\x1b[m\n", __FUNCTION__, Value); + Value &= ~0x80; + RTMP_IO_WRITE32(pAd, WLAN_FUN_CTRL, Value); + + if (pAd->WOW_Cfg.bInBand == FALSE) + { + INT32 Value; + + RTMP_IO_READ32(pAd, WLAN_FUN_CTRL, &Value); + printk("\x1b[31m%s: 0x80 = %x\x1b[m\n", __FUNCTION__, Value); + Value &= ~0x01010000; /* GPIO0(ouput) --> 0(data) */ + RTMP_IO_WRITE32(pAd, WLAN_FUN_CTRL, Value); + } +} +#endif /* NEW_WOW_SUPPORT */ + + +VOID MTPciMlmeRadioOn(PRTMP_ADAPTER pAd) +{ +#ifdef CONFIG_AP_SUPPORT + INT32 IdBss, MaxNumBss = pAd->ApCfg.BssidNum; +#endif + + MCU_CTRL_INIT(pAd); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_IDLE_RADIO_OFF); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD); + + +#ifdef RTMP_MAC_PCI + /* Enable Interrupt */ + RTMP_ASIC_INTERRUPT_ENABLE(pAd); +#endif /* RTMP_MAC_PCI */ + + /* Enable PDMA */ + AsicSetWPDMA(pAd, PDMA_TX_RX, 1); + + /* Send radio on command and wait for ack */ + if (pAd->iwpriv_command == TRUE) + { + UINT32 value; + RTMP_IO_READ32(pAd, AGG_TEMP, &value); + value &= 0x0000ffff; + RTMP_IO_WRITE32(pAd, AGG_TEMP, value); + } else { +#ifdef LOAD_FW_ONE_TIME + { + UINT32 value; + RTMP_IO_READ32(pAd, AGG_TEMP, &value); + value &= 0x0000ffff; + RTMP_IO_WRITE32(pAd, AGG_TEMP, value); + } +#else /* LOAD_FW_ONE_TIME */ + CmdRadioOnOffCtrl(pAd, WIFI_RADIO_ON); +#endif /* !LOAD_FW_ONE_TIME */ + } + + /* Send Led on command */ + + /* Enable RX */ + AsicSetMacTxRx(pAd, ASIC_MAC_RX, TRUE); + + /* Enable normal operation */ + RTMP_OS_NETDEV_START_QUEUE(pAd->net_dev); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (MaxNumBss > MAX_MBSSID_NUM(pAd)) + MaxNumBss = MAX_MBSSID_NUM(pAd); + + /* first IdBss must not be 0 (BSS0), must be 1 (BSS1) */ + for (IdBss = FIRST_MBSSID; IdBss < MAX_MBSSID_NUM(pAd); IdBss++) + { + if (pAd->ApCfg.MBSSID[IdBss].wdev.if_dev) + RTMP_OS_NETDEV_START_QUEUE(pAd->ApCfg.MBSSID[IdBss].wdev.if_dev); + } + } +#endif + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET); +} + + +#ifdef RTMP_PCI_SUPPORT +VOID MTPciPollTxRxEmpty(RTMP_ADAPTER *pAd) +{ + UINT32 Loop, Value/*, RxPending = 0*/; + UINT32 IdleTimes = 0; + UINT32 IdleTimesThreshold = 5000; + UINT32 PollLoopTimesThreshold = 20000; + + //PNDIS_PACKET pRxPacket; + //RX_BLK RxBlk, *pRxBlk; + //BOOLEAN bReschedule = FALSE; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + +#ifdef CONFIG_ATE + if (ATE_ON(pAd)) + { + IdleTimesThreshold = 10; + PollLoopTimesThreshold = 2000; + } +#endif /* CONFIG_ATE */ + + RtmpOsMsDelay(100); + + /* Fix Rx Ring FULL lead DMA Busy, when DUT is in reset stage */ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_POLL_IDLE); + + /* Poll Tx until empty */ + for (Loop = 0; Loop < PollLoopTimesThreshold; Loop++) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + RTMP_IO_READ32(pAd, MT_WPDMA_GLO_CFG, &Value); + + if ((Value & TX_DMA_BUSY) == 0x00) + { + IdleTimes++; + RtmpusecDelay(50); + } + + if (IdleTimes > IdleTimesThreshold) + break; + } + + if (Loop >= PollLoopTimesThreshold) + { + DBGPRINT(RT_DEBUG_OFF, ("%s: TX DMA Busy!! WPDMA_GLO_CFG_STRUC = %d\n", + __FUNCTION__, Value)); + } + + IdleTimes = 0; + + /* Poll Rx to empty */ + for (Loop = 0; Loop < PollLoopTimesThreshold; Loop++) + { + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) + return; + + RTMP_IO_READ32(pAd, MT_WPDMA_GLO_CFG, &Value); + + if ((Value & RX_DMA_BUSY) == 0x00) + { + IdleTimes++; + RtmpusecDelay(50); + } + + if (IdleTimes > IdleTimesThreshold) + break; + } + + if (Loop >= PollLoopTimesThreshold) + { + DBGPRINT(RT_DEBUG_OFF, ("%s: RX DMA Busy!! WPDMA_GLO_CFG_STRUC = %d\n", + __FUNCTION__, Value)); + } + + /* Fix Rx Ring FULL lead DMA Busy, when DUT is in reset stage */ + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_POLL_IDLE); +} + + +VOID MTPciMlmeRadioOff(PRTMP_ADAPTER pAd) +{ +#ifdef CONFIG_AP_SUPPORT + INT32 IdBss, MaxNumBss = pAd->ApCfg.BssidNum; +#endif /* CONFIG_AP_SUPPORT */ + + /* Stop send TX packets */ + RTMP_OS_NETDEV_STOP_QUEUE(pAd->net_dev); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (MaxNumBss > MAX_MBSSID_NUM(pAd)) + MaxNumBss = MAX_MBSSID_NUM(pAd); + + /* first IdBss must not be 0 (BSS0), must be 1 (BSS1) */ + for (IdBss = FIRST_MBSSID; IdBss < MAX_MBSSID_NUM(pAd); IdBss++) + { + if (pAd->ApCfg.MBSSID[IdBss].wdev.if_dev) + RTMP_OS_NETDEV_STOP_QUEUE(pAd->ApCfg.MBSSID[IdBss].wdev.if_dev); + } + } +#endif /* CONFIG_AP_SUPPORT */ + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET); + + /* Disable RX */ + AsicSetMacTxRx(pAd, ASIC_MAC_RX, FALSE); + + /* Polling TX/RX path until packets empty */ + MTPciPollTxRxEmpty(pAd); + + /* Send Led off command */ + + /* Send radio off command and wait for ack */ + if (pAd->iwpriv_command == TRUE) + { + UINT32 value; + RTMP_IO_READ32(pAd, AGG_TEMP, &value); + value |= 0xffff0000; + RTMP_IO_WRITE32(pAd, AGG_TEMP, value); + } else { +#ifdef LOAD_FW_ONE_TIME +{ + UINT32 value; + RTMP_IO_READ32(pAd, AGG_TEMP, &value); + value |= 0xffff0000; + RTMP_IO_WRITE32(pAd, AGG_TEMP, value); +} +#else /* LOAD_FW_ONE_TIME */ + CmdRadioOnOffCtrl(pAd, WIFI_RADIO_OFF); +#endif /* !LOAD_FW_ONE_TIME */ + } + + /* Disable PDMA */ + AsicSetWPDMA(pAd, PDMA_TX_RX, 0); + + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + + /* Disable Interrupt */ + if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) + { + RTMP_ASIC_INTERRUPT_DISABLE(pAd); + } +} +#endif + + +#ifdef RTMP_SDIO_SUPPORT +VOID MTSdioMlmeRadioOff(PRTMP_ADAPTER pAd) +{ +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT + if(LED_MODE(pAd) == WPS_LED_MODE_10) + { + WPSLedMode10 = LINK_STATUS_WPS_MODE10_TURN_OFF; + RTEnqueueInternalCmd(pAd, CMDTHREAD_LED_WPS_MODE10, &WPSLedMode10, sizeof(WPSLedMode10)); + } +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ + + + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + APStop(pAd); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef LED_CONTROL_SUPPORT + RTMPSetLED(pAd, LED_RADIO_OFF); +#endif /* LED_CONTROL_SUPPORT */ + + if (IS_MT7636(pAd)) + { + //CmdPmStateCtrl(pAd, PM5, ENTER_PM_STATE); replaced by bwlow function + CmdExtPmStateCtrl(pAd, BSSID_WCID, PM5, ENTER_PM_STATE); + } +// RTMP_SDIO_WRITE32(pAd, WHLPCR, W_FW_OWN_REQ_SET); + /* Set Radio off flag*/ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); +} + +VOID MTSdioMlmeRadioOn(PRTMP_ADAPTER pAd) +{ + UINT32 Value=0; + UINT32 counter=0; + + MTWF_LOG(DBG_CAT_ALL, DBG_LVL_TRACE,("%s()\n", __func__)); + + /* Clear Radio off flag*/ + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); + +/* + RTMP_SDIO_WRITE32(pAd, WHLPCR, W_FW_OWN_REQ_CLR); + + while(!GET_W_FW_OWN_REQ_SET(Value)) { + RTMP_SDIO_READ32(pAd, WHLPCR, &Value); + MTWF_LOG(DBG_CAT_ALL, DBG_LVL_OFF, ("%s(): Request FW-Own processing: %x\n",__FUNCTION__,Value)); + counter++; + RtmpOsMsDelay(50); + if(counter >100){ + MTWF_LOG(DBG_CAT_ALL, DBG_LVL_ERROR, ("%s: FW-Own back Faiure\n",__FUNCTION__)); + break; + } + } +*/ + if (IS_MT7636(pAd)) + { + //CmdPmStateCtrl(pAd, PM5, EXIT_PM_STATE); replaced by bwlow function + CmdExtPmStateCtrl(pAd, BSSID_WCID, PM5, EXIT_PM_STATE); + } + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + APStartUp(pAd); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef LED_CONTROL_SUPPORT + /* Set LED*/ +#ifdef CONFIG_AP_SUPPORT + RTMPSetLED(pAd, LED_LINK_UP); +#endif /* CONFIG_AP_SUPPORT */ +#endif /* LED_CONTROL_SUPPORT */ +} +#endif + +VOID AsicSetRxGroup(RTMP_ADAPTER *pAd, UINT32 Port, UINT32 Group, BOOLEAN Enable) +{ + UINT32 Value; + + if (Port == HIF_PORT) + { + RTMP_MCU_IO_READ32(pAd, RXINF, &Value); + + if (Enable) + { + if (Group & RXS_GROUP1) + Value |= RXSH_GROUP1_EN; + + if (Group & RXS_GROUP2) + Value |= RXSH_GROUP2_EN; + + if (Group & RXS_GROUP3) + Value |= RXSH_GROUP3_EN; + } + else + { + if (Group & RXS_GROUP1) + Value &= ~RXSH_GROUP1_EN; + + if (Group & RXS_GROUP2) + Value &= ~RXSH_GROUP2_EN; + + if (Group & RXS_GROUP3) + Value &= ~RXSH_GROUP3_EN; + } + + RTMP_MCU_IO_WRITE32(pAd, RXINF, Value); + } + else if (Port == MCU_PORT) + { + RTMP_IO_READ32(pAd, DMA_DCR1, &Value); + + if (Enable) + { + if (Group & RXS_GROUP1) + Value |= RXSM_GROUP1_EN; + + if (Group & RXS_GROUP2) + Value |= RXSM_GROUP2_EN; + + if (Group & RXS_GROUP3) + Value |= RXSM_GROUP3_EN; + } + else + { + if (Group & RXS_GROUP1) + Value &= ~RXSM_GROUP1_EN; + + if (Group & RXS_GROUP2) + Value &= ~RXSM_GROUP2_EN; + + if (Group & RXS_GROUP3) + Value &= ~RXSM_GROUP3_EN; + } + + RTMP_IO_WRITE32(pAd, DMA_DCR1, Value); + } + else + { + DBGPRINT(RT_DEBUG_OFF, ("illegal port (%d\n", Port)); + } +} + + +#if defined(RTMP_MAC_PCI) || defined(RTMP_MAC_USB) +static CHAR *dma_sch_str[] = { + "LMAC", + "ByPass", + "HyBrid", + }; + + +/* + DMA scheduer reservation page assignment + Q0~Q3: WMM1 + Q4: Management queue + Q5: MCU CMD + Q7: Beacon + Q8: MC/BC + Q9~Q12: WMM2 + Q13: Management queue +*/ +#define MAX_BEACON_SIZE 512 +#define MAX_BMCAST_SIZE 1536 +#define MAX_BMCAST_COUNT 3 +#define MAX_MCUCMD_SIZE 4096 /*must >= MAX_DATA_SIZE */ +#define MAX_DATA_SIZE 1792 /* 0xe*128=1792 */ +#define MAX_AMSDU_DATA_SIZE 4096 + +/*Nobody uses it currently*/ + +/* + HYBRID Mode: DMA scheduler would ignore the tx op time information from LMAC, and also use FFA and RSV for enqueue cal. + BYPASS Mode: Only for Firmware download +*/ +INT32 AsicDMASchedulerInit(RTMP_ADAPTER *pAd, INT mode) +{ + UINT32 mac_val; +#ifdef RTMP_PCI_SUPPORT + UINT32 mac_restore_val; +#endif /* RTMP_PCI_SUPPORT */ + UINT32 page_size = 128; + UINT32 page_cnt = 0x1ae; + INT dma_mode = mode; + +#ifdef CONFIG_FPGA_MODE + dma_mode = pAd->fpga_ctl.dma_mode; + + DBGPRINT(RT_DEBUG_OFF, ("%s(): DMA Scheduler Mode=%d(%s)\n", + __FUNCTION__, pAd->fpga_ctl.dma_mode, + dma_sch_str[pAd->fpga_ctl.dma_mode])); +#endif /* CONFIG_FPGA_MODE */ + +#if defined(MT7603_FPGA) || defined(MT7628_FPGA) || defined(MT7636_FPGA) + page_size = 256; +#endif /* MT7603_FPGA */ + + /* Got PSE P0 MAX Quota */ +#ifdef RTMP_PCI_SUPPORT + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &mac_restore_val); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, MT_PSE_BASE_ADDR); + RTMP_IO_READ32(pAd, 0x80120, &mac_val); + page_cnt = (mac_val & 0x0fff0000) >> 16; + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, mac_restore_val); +#endif + + /* Setting PSE page free priority,P0(HIF) > P1(MCU) > P2Q2(TXS) > P2Q1(RXV) = P2Q0(Rxdata)*/ + mac_val = 0x00004037; + RTMP_IO_WRITE32(pAd, FC_FRP,mac_val); + + if (dma_mode == DMA_SCH_BYPASS) + { + RTMP_IO_WRITE32(pAd, MT_SCH_REG_4, 1<<5); + + /* Disable DMA scheduler */ + RTMP_IO_READ32(pAd, AGG_DSCR1, &mac_val); + mac_val |= 0x80000000; + RTMP_IO_WRITE32(pAd, AGG_DSCR1, mac_val); + +#ifdef RTMP_PCI_SUPPORT + /* + Wei-Guo's comment: + 2DW/7DW => 0x800C_006C[14:12] = 3'b0 + 3DW/8DW =>0x800C_006C[14:12] = 3'b1 + */ + // In FPGA mode, we need to change tx pad by different DMA scheduler setting! + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, 0x80080000); + RTMP_IO_READ32(pAd, 0xc006c, &mac_val); + mac_val &= (~(7<<12)); + mac_val |= (1<<12); + RTMP_IO_WRITE32(pAd, 0xc006c, mac_val); + // After change the Tx Padding CR of PCI-E Client, we need to re-map for PSE region + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, MT_PSE_BASE_ADDR); +#endif /* RTMP_PCI_SUPPORT */ + + // work around for un-sync of TxD between HIF and LMAC + RTMP_IO_READ32(pAd, DMA_DCR1, &mac_val); + mac_val &= (~(0x7<<8)); + mac_val |= (0x1<<8); + RTMP_IO_WRITE32(pAd, DMA_DCR1, mac_val); + } + + if ((dma_mode == DMA_SCH_LMAC) || (dma_mode == DMA_SCH_HYBRID)) + { + UINT32 max_beacon_page_count = MAX_BEACON_SIZE/page_size; + UINT32 max_bmcast_page_count = MAX_BMCAST_SIZE/page_size; + UINT32 max_mcucmd_page_count = MAX_MCUCMD_SIZE/page_size; + UINT32 max_data_page_count = MAX_DATA_SIZE/page_size; + UINT32 mcu_restore_val; + UINT32 bcn_restore_val; + UINT32 mbc_restore_val; + + /* Highest Priority Q7: Beacon > Q8: MC/BC > Q5: MCU CMD */ + mac_val = 0x55555553; + RTMP_IO_WRITE32(pAd, MT_HIGH_PRIORITY_1, mac_val); + mac_val = 0x78555555; + RTMP_IO_WRITE32(pAd, MT_HIGH_PRIORITY_2, mac_val); + + /* Queue Priority */ + mac_val = 0x2b1a096e; + RTMP_IO_WRITE32(pAd, MT_QUEUE_PRIORITY_1, mac_val); + mac_val = 0x785f4d3c; + RTMP_IO_WRITE32(pAd, MT_QUEUE_PRIORITY_2, mac_val); + + RTMP_IO_WRITE32(pAd, MT_PRIORITY_MASK, 0xffffffff); + + /* Schedule Priority, page size/FFA, FFA = (page_cnt * page_size) */ + mac_val = (2 << 28) | (page_cnt); + RTMP_IO_WRITE32(pAd, MT_SCH_REG_1, mac_val); + mac_val = MAX_DATA_SIZE / page_size; + RTMP_IO_WRITE32(pAd, MT_SCH_REG_2, mac_val); + + /* Resvervation page */ + if(pAd->CommonCfg.BACapability.field.AmsduEnable==TRUE) + max_data_page_count = MAX_AMSDU_DATA_SIZE/page_size; + + RTMP_IO_WRITE32(pAd, MT_PAGE_CNT_0, max_data_page_count); + RTMP_IO_WRITE32(pAd, MT_PAGE_CNT_1, max_data_page_count); + RTMP_IO_WRITE32(pAd, MT_PAGE_CNT_2, max_data_page_count); + RTMP_IO_WRITE32(pAd, MT_PAGE_CNT_3, max_data_page_count); + RTMP_IO_WRITE32(pAd, MT_PAGE_CNT_4, max_data_page_count); + + mcu_restore_val = max_mcucmd_page_count; + RTMP_IO_WRITE32(pAd, MT_PAGE_CNT_5, mcu_restore_val); + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + if (pAd->ApCfg.BssidNum > 1) + bcn_restore_val = max_beacon_page_count*(pAd->ApCfg.BssidNum - 1) + max_data_page_count; + else + bcn_restore_val = max_data_page_count; + RTMP_IO_WRITE32(pAd, MT_PAGE_CNT_7, bcn_restore_val); + } +#endif /* CONFIG_AP_SUPPORT */ + mbc_restore_val = max_bmcast_page_count*MAX_BMCAST_COUNT + max_data_page_count; + RTMP_IO_WRITE32(pAd, MT_PAGE_CNT_8, mbc_restore_val); + + /* FFA1 max threshold */ + RTMP_IO_WRITE32(pAd, MT_RSV_MAX_THD, page_cnt); + + /* Group Threshold */ + if (MTK_REV_GTE(pAd, MT7603, MT7603E1) && MTK_REV_LT(pAd, MT7603, MT7603E2)) { + RTMP_IO_WRITE32(pAd, MT_GROUP_THD_0, page_cnt); + RTMP_IO_WRITE32(pAd, MT_BMAP_0, 0xffff); + } else { + /* Group 0 + 1+ 2 = PSE P0 */ + RTMP_IO_WRITE32(pAd, MT_GROUP_THD_0, (page_cnt - bcn_restore_val - mcu_restore_val)); + RTMP_IO_WRITE32(pAd, MT_GROUP_THD_1, bcn_restore_val); + RTMP_IO_WRITE32(pAd, MT_BMAP_0, 0x0080ff5f); + RTMP_IO_WRITE32(pAd, MT_GROUP_THD_2, mcu_restore_val); + RTMP_IO_WRITE32(pAd, MT_BMAP_1, 0x00000020); + } + + if (dma_mode == DMA_SCH_LMAC) { + /* config as LMAC prediction mode */ + RTMP_IO_WRITE32(pAd, MT_SCH_REG_4, 0x0); + } + + if (dma_mode == DMA_SCH_HYBRID) + { + /* config as hybrid mode */ + RTMP_IO_WRITE32(pAd, MT_SCH_REG_4, 1<<6); +#if defined(MT7603_FPGA) || defined(MT7628_FPGA) +#ifdef RTMP_PCI_SUPPORT + /* + Wei-Guo's comment: + 2DW/7DW => 0x800C_006C[14:12] = 3'b0 + 3DW/8DW =>0x800C_006C[14:12] = 3'b1 + */ + // In FPGA mode, we need to change tx pad by different DMA scheduler setting + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, 0x80080000); + RTMP_IO_READ32(pAd, 0xc006c, &mac_val); + mac_val &= (~(7<<12)); + RTMP_IO_WRITE32(pAd, 0xc006c, mac_val); + // After change the Tx Padding CR of PCI-E Client, we need to re-map for PSE region + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, MT_PSE_BASE_ADDR); +#endif /* RTMP_PCI_SUPPORT */ +#endif /* MT7603_FPGA */ + + // Disable TxD padding + RTMP_IO_READ32(pAd, DMA_DCR1, &mac_val); + mac_val &= (~(0x7<<8)); + RTMP_IO_WRITE32(pAd, DMA_DCR1, mac_val); + } + } + + if (MTK_REV_GTE(pAd, MT7603,MT7603E1)) { + mac_val = 0xfffff; + RTMP_IO_WRITE32(pAd, MT_TXTIME_THD_0, mac_val); + RTMP_IO_WRITE32(pAd, MT_TXTIME_THD_1, mac_val); + RTMP_IO_WRITE32(pAd, MT_TXTIME_THD_2, mac_val); + RTMP_IO_WRITE32(pAd, MT_TXTIME_THD_3, mac_val); + RTMP_IO_WRITE32(pAd, MT_TXTIME_THD_4, mac_val); + RTMP_IO_WRITE32(pAd, MT_TXTIME_THD_5, mac_val); + RTMP_IO_WRITE32(pAd, MT_TXTIME_THD_6, mac_val); + RTMP_IO_WRITE32(pAd, MT_TXTIME_THD_7, mac_val); + RTMP_IO_WRITE32(pAd, MT_TXTIME_THD_8, mac_val); + RTMP_IO_WRITE32(pAd, MT_TXTIME_THD_9, mac_val); + RTMP_IO_WRITE32(pAd, MT_TXTIME_THD_10, mac_val); + RTMP_IO_WRITE32(pAd, MT_TXTIME_THD_11, mac_val); + RTMP_IO_WRITE32(pAd, MT_TXTIME_THD_12, mac_val); + RTMP_IO_WRITE32(pAd, MT_TXTIME_THD_13, mac_val); + RTMP_IO_WRITE32(pAd, MT_TXTIME_THD_14, mac_val); + RTMP_IO_WRITE32(pAd, MT_TXTIME_THD_15, mac_val); + RTMP_IO_READ32(pAd, MT_SCH_REG_4, &mac_val); + mac_val |= 0x40; + RTMP_IO_WRITE32(pAd, MT_SCH_REG_4, mac_val); + } + + return TRUE; +} +#endif + + +VOID AsicSetBARTxCntLimit(RTMP_ADAPTER *pAd, BOOLEAN Enable, UINT32 Count) +{ + UINT32 Value; + + RTMP_IO_READ32(pAd, AGG_MRCR, &Value); + + if (Enable) + { + Value &= ~BAR_TX_CNT_LIMIT_MASK; + Value |= BAR_TX_CNT_LIMIT(Count); + } + else + { + Value &= ~BAR_TX_CNT_LIMIT_MASK; + Value |= BAR_TX_CNT_LIMIT(0); + } + + RTMP_IO_WRITE32(pAd, AGG_MRCR, Value); +} + +VOID AsicSetRTSTxCntLimit(RTMP_ADAPTER *pAd, BOOLEAN Enable, UINT32 Count) +{ + UINT32 Value; + + RTMP_IO_READ32(pAd, AGG_MRCR, &Value); + + if (Enable) + { + Value &= ~RTS_RTY_CNT_LIMIT_MASK; + Value |= RTS_RTY_CNT_LIMIT(Count); + } + else + { + Value &= ~RTS_RTY_CNT_LIMIT_MASK; + Value |= RTS_RTY_CNT_LIMIT(0); + } + + RTMP_IO_WRITE32(pAd, AGG_MRCR, Value); +} + +BOOLEAN AsicSetBmcQCR( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR Operation, + IN UCHAR CrReadWrite, + IN UINT32 apidx, + INOUT UINT32 *pcr_val) +{ + UINT32 cr_base = 0; + UINT32 cr_val = 0; + UCHAR fcnt = 0; + BOOLEAN result = FALSE; + + switch (Operation) + { + case BMC_FLUSH: + { + cr_base = ARB_BMCQCR1; + cr_val = *pcr_val; + RTMP_IO_WRITE32(pAd, cr_base, cr_val); + + /* check flush result */ + for (fcnt=0;fcnt<100;fcnt++) + { + RTMP_IO_READ32(pAd, cr_base, &cr_val); + if (cr_val == 0) + break; + } + *pcr_val = cr_val; + + if (fcnt == 100) + { + DBGPRINT(RT_DEBUG_OFF, + ("%s: flush take too long, flush cnt=%d\n", + __func__, + fcnt) + ); + return result; + } + } + break; + + case BMC_ENABLE: + { + cr_base = ARB_BMCQCR0; + cr_val = *pcr_val; + RTMP_IO_WRITE32(pAd, cr_base, cr_val); + } + break; + + case BMC_CNT_UPDATE: + { + if ((apidx >= 0) && (apidx <= 4)) + cr_base = ARB_BMCQCR2; + else if ((apidx >= 5) && (apidx <= 12)) + cr_base = ARB_BMCQCR3; + else if ((apidx >=13) && (apidx <= 15)) + cr_base = ARB_BMCQCR4; + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: apidx(%d) not support\n", __FUNCTION__, apidx)); + return result; + } + + if (CrReadWrite == CR_READ) + { + RTMP_IO_READ32(pAd, cr_base, &cr_val); + *pcr_val = cr_val; + } + else if (CrReadWrite == CR_WRITE) + { + cr_val = 0x1;//add 1 to cnt. + if (apidx == 0) + RTMP_IO_WRITE32(pAd, cr_base, cr_val); + else if (apidx >= 1 && apidx <= 4) + RTMP_IO_WRITE32(pAd, cr_base, (cr_val << (16 + ((apidx - 1) * 4)))); + else if (apidx >= 5 && apidx <= 12) + RTMP_IO_WRITE32(pAd, cr_base, (cr_val << ((apidx - 5) * 4))); + else if (apidx >= 13 && apidx <= 15) + RTMP_IO_WRITE32(pAd, cr_base, (cr_val << ((apidx - 13) * 4))); + } + } + break; + + default: + DBGPRINT(RT_DEBUG_OFF, + ("%s(): Operation Error (%d)\n", + __func__, + Operation) + ); + return result; + } + result = TRUE; + return result; +} + +VOID AsicSetTxSClassifyFilter(RTMP_ADAPTER *pAd, UINT32 Port, UINT8 DestQ, + UINT32 AggNums, UINT32 Filter) +{ + UINT32 Value; + + if (Port == TXS2HOST) + { + RTMP_IO_READ32(pAd, DMA_TCFR1, &Value); + Value &= ~TXS2H_BIT_MAP_MASK; + Value |= TXS2H_BIT_MAP(Filter); + Value &= ~TXS2H_AGG_CNT_MASK; + Value |= TXS2H_AGG_CNT(AggNums); + if (DestQ == 0) + Value &= ~TXS2H_QID; + else + Value |= TXS2H_QID; + + RTMP_IO_WRITE32(pAd, DMA_TCFR1, Value); + + } + else if (Port == TXS2MCU) + { + RTMP_IO_READ32(pAd, DMA_TCFR0, &Value); + Value &= ~TXS2M_BIT_MAP_MASK; + Value |= TXS2M_BIT_MAP(Filter); + Value &= ~TXS2M_AGG_CNT_MASK; + Value |= TXS2M_AGG_CNT(AggNums); + Value &= ~TXS2M_QID_MASK; + Value |= TXS2M_QID(DestQ); + RTMP_IO_WRITE32(pAd, DMA_TCFR0, Value); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Port(%d)\n", __FUNCTION__, Port)); + } +} + +VOID MtAsicSetRxPspollFilter(RTMP_ADAPTER *pAd, CHAR enable) +{ + UINT32 mac_val; + + RTMP_IO_READ32(pAd, DMA_RCFR0, &mac_val); + if (enable) + mac_val |= 0x00000008; //Non-BAR Control frame to MCU + else + mac_val &= 0xfffffff7; //Non-BAR Control frame to HIF + + RTMP_IO_WRITE32(pAd, DMA_RCFR0, mac_val); + +} + +#if defined(MT7603) || defined(MT7628) +INT32 MtAsicGetThemalSensor(RTMP_ADAPTER *pAd, CHAR type) + { + /* 0: get temperature; 1: get adc */ + /* Get Thermal sensor adc cal value: 0x80022000 bits(8,14) */ + INT32 result=0; + + if ((type == 0) || (type == 1)) { + UINT32 mac_val; +#ifdef RTMP_PCI_SUPPORT + UINT32 mac_restore_val; + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &mac_restore_val); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, MT_TOP_REMAP_ADDR); + RTMP_IO_READ32(pAd, MT_TOP_REMAP_ADDR_THEMAL, &mac_val); + result = (mac_val & 0x00007f00) >> 8; + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, mac_restore_val); +#endif + if (type == 0) { + INT32 g_ucThermoRefAdcVal, g_cThermoSlopeVariation, g_cThermoRefOffset; + + if (pAd->EEPROMImage[TEMPERATURE_SENSOR_CALIBRATION] & 0x80) + g_ucThermoRefAdcVal = pAd->EEPROMImage[TEMPERATURE_SENSOR_CALIBRATION] & THERMO_REF_ADC_VARIATION_MASK; + else + g_ucThermoRefAdcVal = 52; + + if (pAd->EEPROMImage[THADC_ANALOG_PART] & 0x80) { + g_cThermoSlopeVariation = pAd->EEPROMImage[THADC_SLOP] & THERMO_SLOPE_VARIATION_MASK; + if (g_cThermoSlopeVariation > 16) + g_cThermoSlopeVariation -= 32; + }else + g_cThermoSlopeVariation = 0; + + g_cThermoRefOffset = pAd->EEPROMImage[THERMAL_COMPENSATION_OFFSET] + 28; + result = (((result - g_ucThermoRefAdcVal) * (56 + g_cThermoSlopeVariation) )/30) + g_cThermoRefOffset; + } + } + + return result; + } + + +/* + * ucation: 0: stop; 1: flush; 2: start + */ + +VOID MtAsicACQueue(RTMP_ADAPTER *pAd, UINT8 ucation, UINT8 BssidIdx, UINT32 u4AcQueueMap) +{ + UINT32 ACQCR_0 = 0, ACQCR_1 = 0; + UINT32 Value_0 = 0, Value_1 = 0; + UINT8 ucQueueIdx; + + if (ucation > 2) + return; + + switch (ucation) + { + case AC_QUEUE_STOP: + ACQCR_0 = ARB_TQCR4; + ACQCR_1 = ARB_TQCR5; + break; + case AC_QUEUE_FLUSH: + ACQCR_0 = ARB_TQCR2; + ACQCR_1 = ARB_TQCR3; + break; + case AC_QUEUE_START: + ACQCR_0 = ARB_TQCR0; + ACQCR_1 = ARB_TQCR1; + break; + } + + for (ucQueueIdx = 0; ucQueueIdx < 14; ucQueueIdx++) + { + if (u4AcQueueMap & (1 << ucQueueIdx)) { + switch (ucQueueIdx) + { + case 0: + case 1: + case 2: + Value_0 |= (1 << (ucQueueIdx*5 + BssidIdx)); + break; + case 3: + case 4: + case 5: + Value_0 |= (1 << (ucQueueIdx*5 + BssidIdx + 1)); + break; + case 6: + Value_1 |= (1 << (BssidIdx + 26)); + break; + case 10: + case 11: + case 12: + Value_1 |= (1 << ((ucQueueIdx - 10)*5 + BssidIdx)); + break; + case 13: + case 14: + Value_1 |= (1 << ((ucQueueIdx - 10)*5 + BssidIdx + 1)); + break; + } + } + } + + if (ACQCR_0 && Value_0) { + RTMP_IO_WRITE32(pAd, ACQCR_0, Value_0); + DBGPRINT(RT_DEBUG_WARN, ("%s: Write CR:%x, Value=%x\n", __FUNCTION__, ACQCR_0, Value_0)); + } + + if (ACQCR_1 && Value_1) { + RTMP_IO_WRITE32(pAd, ACQCR_1, Value_1); + DBGPRINT(RT_DEBUG_WARN, ("%s: Write CR:%x, Value=%x\n", __FUNCTION__, ACQCR_1, Value_1)); + } +} + + +#endif /* MT7603 ||MT7628 */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/cmm_chip_mt.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/cmm_chip_mt.c new file mode 100644 index 000000000..b5823dd16 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/cmm_chip_mt.c @@ -0,0 +1,87 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + cmm_asic.c + + Abstract: + Functions used to communicate with ASIC + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#include "rt_config.h" + + +INT mt_asic_top_init(RTMP_ADAPTER *pAd) +{ +#if defined(MT7603_FPGA) || defined(MT7628_FPGA) + UINT32 mac_val; + + // TODO: shiang-7603 + // PSE/MAC Clock setting, Register work-around for FPGA, now it's take cared by ROM code! + //RTMP_IO_READ32(pAd, 0x1100, &mac_val); + //mac_val = 0x26110080; + //RTMP_IO_WRITE32(pAd, 0x1100, mac_val); + + // For FPGA, adjust Clock setting, now 100ms setting will mapping to 400ms in real time + /* Len's setting, + MCU run in 10MHz, LMAC run in 1.25MHz + so GPT timer will have 8 times differentiation with free run timer + =>LMAC time will 8 times slower than MCU time + => host driver set beacon interval 100ms, then real beacon interval will be 800ms + */ +#ifdef MT7628_FPGA + // enable MAC circuit + RTMP_IO_READ32(pAd, 0x2108, &mac_val); + mac_val &= (~0x7ff0); + RTMP_IO_WRITE32(pAd, 0x2108, mac_val); + + mac_val = 0x3e013; + RTMP_IO_WRITE32(pAd, 0x2d004, mac_val); +#endif /* MT7628_FPGA */ + + RTMP_IO_WRITE32(pAd, 0x24088, 0x900); // Set 40MHz Clock + RTMP_IO_WRITE32(pAd, 0x2d034, 0x64180003); // Set 32k clock, this clock is used for lower power. +#endif /* MT7603_FPGA */ + + return TRUE; +} + + +INT mt_hif_sys_init(RTMP_ADAPTER *pAd) +{ + +#ifdef RTMP_MAC_PCI + { + UINT32 mac_val; + + RTMP_IO_READ32(pAd, MT_WPDMA_GLO_CFG, &mac_val); + //mac_val |= 0xb0; // bit 7/5~4 => 1 + mac_val = 0x52000850; + RTMP_IO_WRITE32(pAd, MT_WPDMA_GLO_CFG, mac_val); + } +#endif /* RTMP_MAC_PCI */ + + + + return TRUE; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/coex.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/coex.c new file mode 100644 index 000000000..efc0d1772 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/coex.c @@ -0,0 +1,26 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/greenap.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/greenap.c new file mode 100644 index 000000000..723f37ae0 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/greenap.c @@ -0,0 +1,170 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + greenap.c + + Abstract: + Ralink Wireless driver green ap related functions + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + +#ifdef GREENAP_SUPPORT +VOID EnableAPMIMOPSv2(RTMP_ADAPTER *pAd, BOOLEAN ReduceCorePower) +{ +#if defined (MT7603) || defined (MT7628) + if (pAd->chipCap.hif_type == HIF_MT) { + if (pAd->Antenna.field.RxPath == 2) + AsicSetRxStream(pAd, 1); + } +#else + { + bbp_set_mmps(pAd, ReduceCorePower); + rtmp_mac_set_mmps(pAd, ReduceCorePower); + } +#endif /* defined (MT7603) || defined (MT7628) */ + + pAd->ApCfg.bGreenAPActive=TRUE; + DBGPRINT(RT_DEBUG_INFO, ("EnableAPMIMOPSNew, 30xx changes the # of antenna to 1\n")); +} + + +VOID DisableAPMIMOPSv2(RTMP_ADAPTER *pAd) +{ +#if defined (MT7603) || defined (MT7628) + if (pAd->chipCap.hif_type == HIF_MT) { + if (pAd->Antenna.field.RxPath == 2) + AsicSetRxStream(pAd, pAd->Antenna.field.RxPath); + } +#else + { + bbp_set_mmps(pAd, FALSE); + rtmp_mac_set_mmps(pAd, FALSE); + } +#endif /* defined (MT7603) || defined (MT7628) */ + + pAd->ApCfg.bGreenAPActive=FALSE; + DBGPRINT(RT_DEBUG_INFO, ("DisableAPMIMOPSNew, 30xx reserve only one antenna\n")); +} + +#if defined (MT7603) || defined (MT7628) +#else +VOID EnableAPMIMOPSv1( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN ReduceCorePower) +{ + UCHAR BBPR3 = 0,BBPR1 = 0; + ULONG TxPinCfg = 0x00050F0A;/*Gary 2007/08/09 0x050A0A*/ + UCHAR BBPR4=0; + UCHAR CentralChannel; + + + + if(pAd->CommonCfg.Channel>14) + TxPinCfg=0x00050F05; + + TxPinCfg &= 0xFFFFFFF3; + TxPinCfg &= 0xFFFFF3FF; + pAd->ApCfg.bGreenAPActive=TRUE; + + CentralChannel = pAd->CommonCfg.CentralChannel; + DBGPRINT(RT_DEBUG_INFO, ("Run with BW_20\n")); + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel; + CentralChannel = pAd->CommonCfg.Channel; + + /* Set BBP registers to BW20 */ + bbp_set_bw(pAd, BW_20); + + /* RF Bandwidth related registers would be set in AsicSwitchChannel() */ + if (pAd->Antenna.field.RxPath>1||pAd->Antenna.field.TxPath>1) + { + /*Tx/Rx Stream*/ + bbp_set_txdac(pAd, 0); + bbp_set_rxpath(pAd, 1); + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + + } + AsicSwitchChannel(pAd, CentralChannel, FALSE); + + DBGPRINT(RT_DEBUG_INFO, ("EnableAPMIMOPS, 305x/28xx changes the # of antenna to 1\n")); +} + + +VOID DisableAPMIMOPSv1( + IN PRTMP_ADAPTER pAd) +{ + UCHAR BBPR3=0,BBPR1=0; + ULONG TxPinCfg = 0x00050F0A; /* Gary 2007/08/09 0x050A0A */ + UCHAR CentralChannel; + UINT32 Value=0; + + + + if(pAd->CommonCfg.Channel>14) + TxPinCfg=0x00050F05; + /* Turn off unused PA or LNA when only 1T or 1R*/ + if (pAd->Antenna.field.TxPath == 1) + TxPinCfg &= 0xFFFFFFF3; + if (pAd->Antenna.field.RxPath == 1) + TxPinCfg &= 0xFFFFF3FF; + + pAd->ApCfg.bGreenAPActive=FALSE; + + if ((pAd->CommonCfg.HtCapability.HtCapInfo.ChannelWidth == BW_40) && (pAd->CommonCfg.Channel != 14)) + { + UINT8 ext_ch = EXTCHA_NONE; + + DBGPRINT(RT_DEBUG_INFO, ("Run with BW_40\n")); + /* Set CentralChannel to work for BW40 */ + if (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_ABOVE) + { + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel + 2; + ext_ch = EXTCHA_ABOVE; + } + else if ((pAd->CommonCfg.Channel > 2) && (pAd->CommonCfg.RegTransmitSetting.field.EXTCHA == EXTCHA_BELOW)) + { + pAd->CommonCfg.CentralChannel = pAd->CommonCfg.Channel - 2; + ext_ch = EXTCHA_BELOW; + } + CentralChannel = pAd->CommonCfg.CentralChannel; + AsicSetChannel(pAd, CentralChannel, BW_40, ext_ch, FALSE); + } + + /*Tx Stream*/ + if (WMODE_CAP_N(pAd->CommonCfg.PhyMode) && (pAd->Antenna.field.TxPath == 2)) + bbp_set_txdac(pAd, 2); + else + bbp_set_txdac(pAd, 0); + + /*Rx Stream*/ + bbp_set_rxpath(pAd, pAd->Antenna.field.RxPath); + + RTMP_IO_WRITE32(pAd, TX_PIN_CFG, TxPinCfg); + + + DBGPRINT(RT_DEBUG_INFO, ("DisableAPMIMOPS, 305x/28xx reserve only one antenna\n")); +} +#endif /* defined (MT7603) || defined (MT7628) */ +#endif /* GREENAP_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/mt_gpio.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/mt_gpio.c new file mode 100644 index 000000000..93129e0d9 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/hw_ctrl/mt_gpio.c @@ -0,0 +1,368 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of MediaTek. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + mt_gpio.c +*/ + +#include "rt_config.h" + +static VOID GPIOMuxSelect(RTMP_ADAPTER *pAd, UINT32 GPIO) +{ + + UINT32 RemapBase, RemapOffset; + UINT32 RestoreValue; + UINT32 Value; + + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + + switch (GPIO) + { + case GPIO0: + RemapBase = GET_REMAP_2_BASE(PINMUX_SEL1) << 19; + RemapOffset = GET_REMAP_2_OFFSET(PINMUX_SEL1); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~GPIO0_SEL_MASK; + Value |= GPIO0_SEL(GPIO0_SEL_VALUE); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + break; + case GPIO1: + RemapBase = GET_REMAP_2_BASE(PINMUX_SEL1) << 19; + RemapOffset = GET_REMAP_2_OFFSET(PINMUX_SEL1); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~GPIO1_SEL_MASK; + Value |= GPIO1_SEL(GPIO1_SEL_VALUE); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + break; + case GPIO2: + RemapBase = GET_REMAP_2_BASE(PINMUX_SEL1) << 19; + RemapOffset = GET_REMAP_2_OFFSET(PINMUX_SEL1); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~GPIO2_SEL_MASK; + Value |= GPIO2_SEL(GPIO2_SEL_VALUE); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + break; + case GPIO3: + RemapBase = GET_REMAP_2_BASE(PINMUX_SEL1) << 19; + RemapOffset = GET_REMAP_2_OFFSET(PINMUX_SEL1); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~GPIO3_SEL_MASK; + Value |= GPIO3_SEL(GPIO3_SEL_VALUE); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + break; + case GPIO4: + RemapBase = GET_REMAP_2_BASE(PINMUX_SEL1) << 19; + RemapOffset = GET_REMAP_2_OFFSET(PINMUX_SEL1); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~GPIO4_SEL_MASK; + Value |= GPIO4_SEL(GPIO4_SEL_VALUE); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + break; + case GPIO5: + RemapBase = GET_REMAP_2_BASE(PINMUX_SEL1) << 19; + RemapOffset = GET_REMAP_2_OFFSET(PINMUX_SEL1); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~GPIO5_SEL_MASK; + Value |= GPIO5_SEL(GPIO5_SEL_VALUE); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + break; + case GPIO6: + RemapBase = GET_REMAP_2_BASE(PINMUX_SEL1) << 19; + RemapOffset = GET_REMAP_2_OFFSET(PINMUX_SEL1); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~GPIO6_SEL_MASK; + Value |= GPIO6_SEL(GPIO6_SEL_VALUE); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + break; + case GPIO7: + RemapBase = GET_REMAP_2_BASE(PINMUX_SEL1) << 19; + RemapOffset = GET_REMAP_2_OFFSET(PINMUX_SEL1); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~GPIO7_SEL_MASK; + Value |= GPIO7_SEL(GPIO7_SEL_VALUE); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + break; + case GPIO8: + RemapBase = GET_REMAP_2_BASE(PINMUX_SEL2) << 19; + RemapOffset = GET_REMAP_2_OFFSET(PINMUX_SEL2); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~GPIO8_SEL_MASK; + Value |= GPIO8_SEL(GPIO8_SEL_VALUE); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + break; + case GPIO9: + RemapBase = GET_REMAP_2_BASE(PINMUX_SEL2) << 19; + RemapOffset = GET_REMAP_2_OFFSET(PINMUX_SEL2); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~GPIO9_SEL_MASK; + Value |= GPIO9_SEL(GPIO9_SEL_VALUE); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + break; + case GPIO10: + RemapBase = GET_REMAP_2_BASE(PINMUX_SEL2) << 19; + RemapOffset = GET_REMAP_2_OFFSET(PINMUX_SEL2); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~GPIO10_SEL_MASK; + Value |= GPIO10_SEL(GPIO10_SEL_VALUE); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + break; + case GPIO11: + RemapBase = GET_REMAP_2_BASE(PINMUX_SEL2) << 19; + RemapOffset = GET_REMAP_2_OFFSET(PINMUX_SEL2); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~GPIO11_SEL_MASK; + Value |= GPIO11_SEL(GPIO11_SEL_VALUE); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + break; + case GPIO12: + RemapBase = GET_REMAP_2_BASE(PINMUX_SEL2) << 19; + RemapOffset = GET_REMAP_2_OFFSET(PINMUX_SEL2); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~GPIO12_SEL_MASK; + Value |= GPIO12_SEL(GPIO12_SEL_VALUE); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + break; + case GPIO13: + RemapBase = GET_REMAP_2_BASE(PINMUX_SEL2) << 19; + RemapOffset = GET_REMAP_2_OFFSET(PINMUX_SEL2); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~GPIO13_SEL_MASK; + Value |= GPIO13_SEL(GPIO13_SEL_VALUE); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + break; + case GPIO14: + RemapBase = GET_REMAP_2_BASE(PINMUX_SEL2) << 19; + RemapOffset = GET_REMAP_2_OFFSET(PINMUX_SEL2); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~GPIO14_SEL_MASK; + Value |= GPIO14_SEL(GPIO14_SEL_VALUE); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + break; + case GPIO15: + RemapBase = GET_REMAP_2_BASE(PINMUX_SEL2) << 19; + RemapOffset = GET_REMAP_2_OFFSET(PINMUX_SEL2); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~GPIO15_SEL_MASK; + Value |= GPIO15_SEL(GPIO15_SEL_VALUE); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + break; + case GPIO16: + RemapBase = GET_REMAP_2_BASE(PINMUX_SEL3) << 19; + RemapOffset = GET_REMAP_2_OFFSET(PINMUX_SEL3); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + Value &= ~GPIO16_SEL_MASK; + Value |= GPIO16_SEL(GPIO16_SEL_VALUE); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, Value); + break; + default: + DBGPRINT(RT_DEBUG_OFF, ("GPIO (%d) not support\n", GPIO)); + break; + } + + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); +} + + +INT32 GPIODirectionInput(RTMP_ADAPTER *pAd, UINT32 GPIO) +{ + UINT32 RemapBase, RemapOffset; + UINT32 RestoreValue; + + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + + GPIOMuxSelect(pAd, GPIO); + + RemapBase = GET_REMAP_2_BASE(GPIO_OE1_RESET) << 19; + RemapOffset = GET_REMAP_2_OFFSET(GPIO_OE1_RESET); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, (1 << GPIO)); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); + + return 0; +} + + +INT32 GPIODirectionOuput(RTMP_ADAPTER *pAd, UINT32 GPIO, UINT8 Value) +{ + UINT32 RemapBase, RemapOffset; + UINT32 RestoreValue; + + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + + GPIOMuxSelect(pAd, GPIO); + + RemapBase = GET_REMAP_2_BASE(GPIO_OE1_SET) << 19; + RemapOffset = GET_REMAP_2_OFFSET(GPIO_OE1_SET); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, (1 << GPIO)); + + if (Value == OUTPUT_HIGH) + { + RemapBase = GET_REMAP_2_BASE(GPIO_DOUT1_SET) << 19; + RemapOffset = GET_REMAP_2_OFFSET(GPIO_DOUT1_SET); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, (1 << GPIO)); + } + else + { + RemapBase = GET_REMAP_2_BASE(GPIO_DOUT1_RESET) << 19; + RemapOffset = GET_REMAP_2_OFFSET(GPIO_DOUT1_RESET); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, (1 << GPIO)); + } + + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); + + return 0; +} + + +UINT32 GPIOGetValue(RTMP_ADAPTER *pAd, UINT32 GPIO) +{ + + UINT32 RemapBase, RemapOffset; + UINT32 RestoreValue; + UINT32 Value; + + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + + RemapBase = GET_REMAP_2_BASE(GPIO_DIN1) << 19; + RemapOffset = GET_REMAP_2_OFFSET(GPIO_DIN1); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); + + if (((Value & (1 << GPIO)) >> GPIO)) + return INPUT_HIGH; + else + return INPUT_LOW; +} + + +VOID GPIOSetValue(RTMP_ADAPTER *pAd, UINT32 GPIO, UINT8 Value) +{ + UINT32 RemapBase, RemapOffset; + UINT32 RestoreValue; + + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + + if (Value == OUTPUT_HIGH) + { + RemapBase = GET_REMAP_2_BASE(GPIO_DOUT1_SET) << 19; + RemapOffset = GET_REMAP_2_OFFSET(GPIO_DOUT1_SET); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, (1 << GPIO)); + } + else + { + RemapBase = GET_REMAP_2_BASE(GPIO_DOUT1_RESET) << 19; + RemapOffset = GET_REMAP_2_OFFSET(GPIO_DOUT1_RESET); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, (1 << GPIO)); + } + + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); +} + + +UINT32 GPIOGetMode(RTMP_ADAPTER *pAd, UINT32 GPIO) +{ + UINT32 RemapBase, RemapOffset; + UINT32 RestoreValue; + UINT32 Value; + + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + + RemapBase = GET_REMAP_2_BASE(GPIO_OE1) << 19; + RemapOffset = GET_REMAP_2_OFFSET(GPIO_OE1); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_READ32(pAd, 0x80000 + RemapOffset, &Value); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); + + if (((Value & (1 << GPIO)) >> GPIO)) + return GPIO_OUTPUT; + else + return GPIO_INPUT; +} + + +INT32 GPIOPullUp(RTMP_ADAPTER *pAd, UINT32 GPIO, UINT8 Value) +{ + UINT32 RemapBase, RemapOffset; + UINT32 RestoreValue; + + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + + if (Value == PULL_UP) + { + RemapBase = GET_REMAP_2_BASE(GPIO_PU1_SET) << 19; + RemapOffset = GET_REMAP_2_OFFSET(GPIO_PU1_SET); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, (1 << GPIO)); + } + else + { + RemapBase = GET_REMAP_2_BASE(GPIO_PU1_RESET) << 19; + RemapOffset = GET_REMAP_2_OFFSET(GPIO_PU1_RESET); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, (1 << GPIO)); + } + + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); + + return 0; +} + + +INT32 GPIOPullDown(RTMP_ADAPTER *pAd, UINT32 GPIO, UINT8 Value) +{ + UINT32 RemapBase, RemapOffset; + UINT32 RestoreValue; + + RTMP_IO_READ32(pAd, MCU_PCIE_REMAP_2, &RestoreValue); + + if (Value == PULL_DOWN) + { + RemapBase = GET_REMAP_2_BASE(GPIO_PD1_SET) << 19; + RemapOffset = GET_REMAP_2_OFFSET(GPIO_PD1_SET); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, (1 << GPIO)); + } + else + { + RemapBase = GET_REMAP_2_BASE(GPIO_PD1_RESET) << 19; + RemapOffset = GET_REMAP_2_OFFSET(GPIO_PD1_RESET); + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RemapBase); + RTMP_IO_WRITE32(pAd, 0x80000 + RemapOffset, (1 << GPIO)); + } + + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, RestoreValue); + + return 0; +} diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/a4_conn.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/a4_conn.h new file mode 100644 index 000000000..f90af783b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/a4_conn.h @@ -0,0 +1,144 @@ +#ifndef __A4_CONN_H__ +#define __A4_CONN_H__ +/* + *************************************************************************** + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2009, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + + Module Name: + a4_conn.h + + Abstract: + This is A4 connection function used to process those 4-addr of connected APClient or STA. + Used by MWDS and MAP feature + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ +#ifdef A4_CONN +#include "rtmp_def.h" + +typedef struct _A4_CONNECT_ENTRY { + DL_LIST List; + UCHAR valid; + UCHAR wcid; +} A4_CONNECT_ENTRY, *PA4_CONNECT_ENTRY; + + +#define A4_TYPE_NONE 0 +#define A4_TYPE_MWDS 1 +#define A4_TYPE_MAP 2 /*high priority*/ + + +#define IS_ENTRY_A4(_x) ((_x)->a4_entry != 0) +#define GET_ENTRY_A4(_x) ((_x)->a4_entry) +#define SET_ENTRY_A4(_x, _type) ((_x)->a4_entry = _type) + +#define IS_APCLI_A4(_x) ((_x)->a4_apcli != 0) +#define GET_APCLI_A4(_x) ((_x)->a4_apcli) +#define SET_APCLI_A4(_x, _type) ((_x)->a4_apcli = _type) + + +BOOLEAN a4_interface_init( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN BOOLEAN is_ap, + IN UCHAR a4_type +); + +BOOLEAN a4_interface_deinit( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN BOOLEAN is_ap, + IN UCHAR a4_type +); + +VOID a4_proxy_delete( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN PUCHAR mac_addr +); + +BOOLEAN a4_proxy_lookup( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN PUCHAR mac_addr, + IN BOOLEAN update_alive_time, + IN BOOLEAN is_rx, + OUT UCHAR *wcid +); + +VOID a4_proxy_update( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN UCHAR wcid, + IN PUCHAR mac_addr, + IN UINT32 ip /* ARP Sender IP*/ +); + +VOID a4_proxy_maintain( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index +); + +void a4_send_clone_pkt( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN PNDIS_PACKET pkt, + IN PUCHAR exclude_mac_addr +); + +BOOLEAN a4_ap_peer_enable( + IN PRTMP_ADAPTER adapter, + IN PMAC_TABLE_ENTRY entry, + IN UCHAR type +); + +BOOLEAN a4_ap_peer_disable( + IN PRTMP_ADAPTER adapter, + IN PMAC_TABLE_ENTRY entry, + IN UCHAR type +); + +#ifdef APCLI_SUPPORT +BOOLEAN a4_apcli_peer_enable( + IN PRTMP_ADAPTER adapter, + IN PAPCLI_STRUCT apcli_entry, + IN PMAC_TABLE_ENTRY entry, + IN UCHAR type +); + +BOOLEAN a4_apcli_peer_disable( + IN PRTMP_ADAPTER adapter, + IN PAPCLI_STRUCT apcli_entry, + IN PMAC_TABLE_ENTRY entry, + IN UCHAR type +); +#endif + +INT Set_APProxy_Status_Show_Proc( + IN PRTMP_ADAPTER adapter, + IN RTMP_STRING *arg +); + +INT Set_APProxy_Refresh_Proc( + IN PRTMP_ADAPTER adapter, + IN RTMP_STRING * arg); + +#endif /* A4_CONN */ +#endif /* __A4_CONN_H__*/ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/action.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/action.h new file mode 100644 index 000000000..460391ae7 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/action.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: + aironet.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ + +#ifndef __ACTION_H__ +#define __ACTION_H__ + + +struct _RTMP_ADAPTER; + + + +VOID MlmeQOSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDLSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeInvalidAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerRMAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerQOSAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef DOT11_N_SUPPORT +VOID PeerAddBAReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAddBARspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDelBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBAAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerHTAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifdef DOT11_VHT_AC +VOID PeerVHTAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) ; +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + +VOID PeerPublicAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + + +#ifdef CONFIG_AP_SUPPORT +VOID ApPublicAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif /* CONFIG_AP_SUPPORT */ + + +#endif /* __ACTION_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ags.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ags.h new file mode 100644 index 000000000..0840400be --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ags.h @@ -0,0 +1,102 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + + Abstract: + + All AGS (Adaptive Group Switching) Related Structure & Definition + +***************************************************************************/ + +#ifndef __AGS_H__ +#define __AGS_H__ + + +extern UCHAR AGS1x1HTRateTable[]; +extern UCHAR AGS2x2HTRateTable[]; +extern UCHAR AGS3x3HTRateTable[]; +#ifdef DOT11_VHT_AC +extern UCHAR Ags1x1VhtRateTable[]; +extern UCHAR Ags2x2VhtRateTable[]; +#endif /* DOT11_VHT_AC */ + +#define AGS_TX_QUALITY_WORST_BOUND 8 +#define AGS_QUICK_RA_TIME_INTERVAL 50 /* 50ms */ + +/* The size, in bytes, of an AGS entry in the rate switch table */ +#define SIZE_OF_AGS_RATE_TABLE_ENTRY 9 + +typedef struct _RTMP_RA_AGS_TB { + UCHAR ItemNo; + + UCHAR STBC:1; + UCHAR ShortGI:1; + UCHAR BW:2; + UCHAR Mode:3; + UCHAR Rsv1:1; + + UCHAR Nss:2; // NSS_XXX (VHT only) + UCHAR rsv2:6; // Reserved + + UCHAR CurrMCS; + UCHAR TrainUp; + UCHAR TrainDown; + UCHAR downMcs; + UCHAR upMcs3; + UCHAR upMcs2; + UCHAR upMcs1; +}RTMP_RA_AGS_TB; + + +/* AGS control */ +typedef struct _AGS_CONTROL { + UCHAR MCSGroup; /* The MCS group under testing */ + UCHAR lastRateIdx; +} AGS_CONTROL,*PAGS_CONTROL; + + +/* The statistics information for AGS */ +typedef struct _AGS_STATISTICS_INFO { + CHAR RSSI; + ULONG TxErrorRatio; + ULONG AccuTxTotalCnt; + ULONG TxTotalCnt; + ULONG TxSuccess; + ULONG TxRetransmit; + ULONG TxFailCount; +} AGS_STATISTICS_INFO, *PAGS_STATISTICS_INFO; + + +/* Support AGS (Adaptive Group Switching) */ +#define SUPPORT_AGS(__pAd) ((__pAd)->rateAlg == RATE_ALG_AGS) + +#ifdef DOT11_VHT_AC +#define AGS_IS_USING(__pAd, __pRateTable) \ + (SUPPORT_AGS(__pAd) && \ + ((__pRateTable == AGS1x1HTRateTable) ||\ + (__pRateTable == AGS2x2HTRateTable) ||\ + (__pRateTable == AGS3x3HTRateTable) ||\ + (__pRateTable == Ags1x1VhtRateTable) ||\ + (__pRateTable == Ags2x2VhtRateTable))) +#else +#define AGS_IS_USING(__pAd, __pRateTable) \ + (SUPPORT_AGS(__pAd) && \ + ((__pRateTable == AGS1x1HTRateTable) || \ + (__pRateTable == AGS2x2HTRateTable) || \ + (__pRateTable == AGS3x3HTRateTable))) +#endif /* DOT11_VHT_AC */ + +#endif /* __AGS_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/all_net_event.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/all_net_event.h new file mode 100644 index 000000000..d12edcb4c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/all_net_event.h @@ -0,0 +1,23 @@ +#ifndef __ALL_NET_EVENT__ +#define __ALL_NET_EVENT__ + +typedef enum FBT_NOTIFY_TYPE { + FBT_LINK_WEAK_NOTIFY = 0, + FBT_LINK_STRONG_NOTIFY = 1, + FBT_LINK_ONLINE_NOTIFY = 2, + FBT_LINK_OFFLINE_NOTIFY = 3, + FBT_LINK_STA_FOUND_NOTIFY = 4, +} FBT_NOTIFY_E; + +typedef struct _FBT_NOTIFY_ST { + UCHAR FbtNotifyExtApMac[20]; + UINT32 FbtChannel; + INT32 FbtRSSI; + FBT_NOTIFY_E FbtNotifyType; + UCHAR FbtNotifyMac[20]; +} FBT_NOTIFY_ST, PFBT_NOTIFY_ST; + +void wext_send_event(PNET_DEV net_dev, const char *peer_mac_addr, + const char *bssid, UINT32 channel, INT32 rssi, FBT_NOTIFY_E event_type); + +#endif /* __ALL_NET_EVENT__ */ \ No newline at end of file diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap.h new file mode 100644 index 000000000..10fcadeb5 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap.h @@ -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, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + ap.h + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#ifndef __AP_H__ +#define __AP_H__ + +#ifdef DOT11R_FT_SUPPORT +#include "ft_cmm.h" +#endif /* DOT11R_FT_SUPPORT */ + +INT ap_security_init(RTMP_ADAPTER *pAd, struct wifi_dev *wdev, INT idx); +INT ap_mlme_set_capability(RTMP_ADAPTER *pAd, BSS_STRUCT *pMbss); +INT ap_key_tb_single_init(RTMP_ADAPTER *pAd, BSS_STRUCT *pDstMbss); + +#if defined(MAP_SUPPORT) && defined(WAPP_SUPPORT) +#define VERIWAVE_2G_PKT_CNT_TH 100 +#define VERIWAVE_5G_PKT_CNT_TH 200 +#define BYTES_PER_SEC_TO_MBPS 17 +#define TX_MODE_RATIO_THRESHOLD 70 +#define RX_MODE_RATIO_THRESHOLD 70 +#define STA_TP_IDLE_THRESHOLD 10 +#define MULTI_CLIENT_NUMS_TH 16 +#define MULTI_CLIENT_2G_NUMS_TH 16 +#define INFRA_KEEP_STA_PKT_TH 1 +#define TRAFFIC_0 0 +#define TRAFFIC_DL_MODE 1 +#define TRAFFIC_UL_MODE 2 +#define TRAFFIC_BIDIR_ACTIVE_MODE 3 +#define TRAFFIC_BIDIR_IDLE_MODE 4 + +#endif + +/* ============================================================= */ +/* Common definition */ +/* ============================================================= */ +#define MBSS_VLAN_INFO_GET(__pAd, __VLAN_VID, __VLAN_Priority, __func_idx) \ +{ \ + if ((__func_idx < __pAd->ApCfg.BssidNum) && \ + (__func_idx < HW_BEACON_MAX_NUM) && \ + (__pAd->ApCfg.MBSSID[__func_idx].wdev.VLAN_VID != 0)) \ + { \ + __VLAN_VID = __pAd->ApCfg.MBSSID[__func_idx].wdev.VLAN_VID; \ + __VLAN_Priority = __pAd->ApCfg.MBSSID[__func_idx].wdev.VLAN_Priority; \ + } \ +} + +#define WDEV_VLAN_INFO_GET(__pAd, __VLAN_VID, __VLAN_Priority, __wdev) \ +{ \ + if ((__wdev->VLAN_VID != 0)) \ + { \ + __VLAN_VID = __wdev->VLAN_VID; \ + __VLAN_Priority = __wdev->VLAN_Priority; \ + } \ +} + + +typedef struct _AUTH_FRAME_INFO{ + UCHAR addr1[MAC_ADDR_LEN]; + UCHAR addr2[MAC_ADDR_LEN]; + USHORT auth_alg; + USHORT auth_seq; + USHORT auth_status; + CHAR Chtxt[CIPHER_TEXT_LEN]; +#ifdef DOT11R_FT_SUPPORT + FT_INFO FtInfo; +#endif /* DOT11R_FT_SUPPORT */ +}AUTH_FRAME_INFO; + +#ifdef CONN_FAIL_EVENT +#define OID_802_11_CONN_FAIL_MSG (0x0958) + +struct CONN_FAIL_MSG { + CHAR Ssid[32]; + UCHAR SsidLen; + UCHAR StaAddr[6]; + USHORT ReasonCode; +}; + +void ApSendConnFailMsg( + PRTMP_ADAPTER pAd, + CHAR *Ssid, + UCHAR SsidLen, + UCHAR *StaAddr, + USHORT ReasonCode); + +#endif + +/* ============================================================= */ +/* Function Prototypes */ +/* ============================================================= */ + +BOOLEAN APBridgeToWirelessSta( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pHeader, + IN UINT HdrLen, + IN PUCHAR pData, + IN UINT DataLen, + IN ULONG fromwdsidx); + +INT ApAllowToSendPacket( + IN RTMP_ADAPTER *pAd, + IN struct wifi_dev *wdev, + IN PNDIS_PACKET pPacket, + OUT UCHAR *pWcid); + +INT ap_rx_pkt_allow(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); +INT ap_rx_ps_handle(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); +INT ap_rx_foward_handle(RTMP_ADAPTER *pAd, struct wifi_dev *wdev, PNDIS_PACKET pPacket); + +INT APSendPacket(RTMP_ADAPTER *pAd, PNDIS_PACKET pPacket); + +NDIS_STATUS APInsertPsQueue( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN STA_TR_ENTRY *tr_entry, + IN UCHAR QueIdx); + +NDIS_STATUS APHardTransmit(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk); + +VOID rx_eapol_frm_handle( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR wdev_idx); + +VOID APRxErrorHandle(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); + +BOOLEAN APChkCls2Cls3Err( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN HEADER_802_11 *pHeader); + +VOID RTMPDescriptorEndianChange(UCHAR *pData, ULONG DescriptorType); + +VOID RTMPFrameEndianChange( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pData, + IN ULONG Dir, + IN BOOLEAN FromRxDoneInt); + +/* ap_assoc.c */ + +VOID APAssocStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MbssKickOutStas(RTMP_ADAPTER *pAd, INT apidx, USHORT Reason); +VOID APMlmeKickOutSta(RTMP_ADAPTER *pAd, UCHAR *staAddr, UCHAR Wcid, USHORT Reason); + +#ifdef DOT11W_PMF_SUPPORT +VOID APMlmeKickOutAllSta(RTMP_ADAPTER *pAd, UCHAR apidx, USHORT Reason); +#endif /* DOT11W_PMF_SUPPORT */ + +VOID APCls3errAction(RTMP_ADAPTER *pAd, ULONG wcid, HEADER_802_11 *hdr); + +/* ap_auth.c */ + +void APAuthStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +void ap_send_broadcast_deauth(void *ad_obj, struct wifi_dev *wdev); + +VOID APCls2errAction(RTMP_ADAPTER *pAd, ULONG wcid, HEADER_802_11 *hdr); + +/* ap_connect.c */ + +#ifdef CONFIG_AP_SUPPORT +BOOLEAN BeaconTransmitRequired(RTMP_ADAPTER *pAd, INT apidx, BSS_STRUCT *mbss); +#ifdef MT_MAC +VOID APMakeAllTimFrame(RTMP_ADAPTER *pAd); +VOID APMakeTimFrame(RTMP_ADAPTER *pAd, INT apidx); +VOID APCheckBcnQHandler(RTMP_ADAPTER *pAd, INT apidx, BOOLEAN *is_pretbtt_int); +#endif +#endif /* CONFIG_AP_SUPPORT */ + +VOID APMakeBssBeacon(RTMP_ADAPTER *pAd, INT apidx); +VOID APUpdateBeaconFrame(RTMP_ADAPTER *pAd, INT apidx); +VOID APMakeAllBssBeacon(RTMP_ADAPTER *pAd); +VOID APUpdateAllBeaconFrame(RTMP_ADAPTER *pAd); + +/* ap_sync.c */ +VOID APSyncStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +UCHAR get_regulatory_class(RTMP_ADAPTER *pAd, UCHAR Channel); + +INT ap_phy_rrm_init(RTMP_ADAPTER *pAd); + +#ifdef WH_EZ_SETUP +#ifdef EZ_MOD_SUPPORT +VOID EzStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); +#else +VOID EzRoamStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID APTriBandStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); +#endif + +INT ap_security_init(RTMP_ADAPTER *pAd, struct wifi_dev *wdev, INT idx); + +INT ap_key_tb_init(RTMP_ADAPTER *pAd); + +#endif + +VOID APScanTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID ApSiteSurvey( + IN PRTMP_ADAPTER pAd, + IN PNDIS_802_11_SSID pSsid, + IN UCHAR ScanType, + IN BOOLEAN ChannelSel, + IN struct wifi_dev *wdev +); + +VOID SupportRate( + IN PUCHAR SupRate, + IN UCHAR SupRateLen, + IN PUCHAR ExtRate, + IN UCHAR ExtRateLen, + OUT PUCHAR *Rates, + OUT PUCHAR RatesLen, + OUT PUCHAR pMaxSupportRate); + + +BOOLEAN ApScanRunning(RTMP_ADAPTER *pAd); + +#ifdef AP_PARTIAL_SCAN_SUPPORT +UCHAR FindPartialScanChannel( + IN PRTMP_ADAPTER pAd); +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +VOID APUpdateOperationMode(RTMP_ADAPTER *pAd); + +#ifdef DOT11N_DRAFT3 +VOID APOverlappingBSSScan(RTMP_ADAPTER *pAd); + +INT GetBssCoexEffectedChRange( + IN RTMP_ADAPTER *pAd, + IN BSS_COEX_CH_RANGE *pCoexChRange); +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + +/* ap_mlme.c */ +VOID APMlmePeriodicExec(RTMP_ADAPTER *pAd); + +BOOLEAN APMsgTypeSubst( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT INT *MsgType); + +VOID APQuickResponeForRateUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID APAsicEvaluateRxAnt(RTMP_ADAPTER *pAd); +VOID APAsicRxAntEvalTimeout(RTMP_ADAPTER *pAd); + +/* ap.c */ +UCHAR get_apidx_by_addr(RTMP_ADAPTER *pAd, UCHAR *addr); + +NDIS_STATUS APInitialize(RTMP_ADAPTER *pAd); + +INT ap_func_init(RTMP_ADAPTER *pAd); + +VOID APShutdown(RTMP_ADAPTER *pAd); +VOID APStartUp(RTMP_ADAPTER *pAd); +VOID APStop(RTMP_ADAPTER *pAd); +VOID APStopBssOnly(RTMP_ADAPTER *pAd, BSS_STRUCT *pMbss); + + +VOID APCleanupPsQueue(RTMP_ADAPTER *pAd, QUEUE_HEADER *pQueue); + + +VOID MacTableMaintenance(RTMP_ADAPTER *pAd); + +UINT32 MacTableAssocStaNumGet(RTMP_ADAPTER *pAd); + +MAC_TABLE_ENTRY *APSsPsInquiry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + OUT SST *Sst, + OUT USHORT *Aid, + OUT UCHAR *PsMode, + OUT UCHAR *Rate); + +#ifdef SYSTEM_LOG_SUPPORT +VOID ApLogEvent( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN USHORT Event); +#else +#define ApLogEvent(_pAd, _pAddr, _Event) +#endif /* SYSTEM_LOG_SUPPORT */ + +VOID APUpdateCapabilityAndErpIe(RTMP_ADAPTER *pAd); + +BOOLEAN ApCheckAccessControlList(RTMP_ADAPTER *pAd, UCHAR *addr, UCHAR apidx); +VOID ApUpdateAccessControlList(RTMP_ADAPTER *pAd, UCHAR apidx); +#ifdef STA_FORCE_ROAM_SUPPORT +BOOLEAN ApCheckFroamAccessControlList( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN UCHAR Apidx); +#endif + +#ifdef AP_QLOAD_SUPPORT +VOID QBSS_LoadInit(RTMP_ADAPTER *pAd); +VOID QBSS_LoadAlarmReset(RTMP_ADAPTER *pAd); +VOID QBSS_LoadAlarmResume(RTMP_ADAPTER *pAd); +UINT32 QBSS_LoadBusyTimeGet(RTMP_ADAPTER *pAd); +BOOLEAN QBSS_LoadIsAlarmIssued(RTMP_ADAPTER *pAd); +BOOLEAN QBSS_LoadIsBusyTimeAccepted(RTMP_ADAPTER *pAd, UINT32 BusyTime); +UINT32 QBSS_LoadElementAppend(RTMP_ADAPTER *pAd, UINT8 *buf_p); +VOID QBSS_LoadUpdate(RTMP_ADAPTER *pAd, ULONG UpTime); +VOID QBSS_LoadStatusClear(RTMP_ADAPTER *pAd); + +INT Show_QoSLoad_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#ifdef CONFIG_HOTSPOT_R2 +UINT32 QBSS_LoadElementAppend_HSTEST(RTMP_ADAPTER *pAd, UINT8 *pBeaconBuf, UCHAR apidx); +#endif /* CONFIG_HOTSPOT_R2 */ +#endif /* AP_QLOAD_SUPPORT */ + + +#ifdef DOT1X_SUPPORT +INT Set_OwnIPAddr_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_EAPIfName_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_PreAuthIfName_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +/* Define in ap.c */ +BOOLEAN DOT1X_InternalCmdAction( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UINT8 cmd); + +BOOLEAN DOT1X_EapTriggerAction(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry); +#endif /* DOT1X_SUPPORT */ + +VOID AP_E2PROM_IOCTL_PostCtrl(RTMP_IOCTL_INPUT_STRUCT *wrq, RTMP_STRING *msg); + +VOID IAPP_L2_UpdatePostCtrl(RTMP_ADAPTER *pAd, UINT8 *mac, INT wdev_idx); + +#ifdef AIRPLAY_SUPPORT +#define AIRPLAY_ON(_pAd) ((_pAd)->bAirplayEnable == 1) +#endif /* AIRPLAY_SUPPORT*/ +#ifdef STA_FORCE_ROAM_SUPPORT + + +#define FROAM_SUPP_DEF FALSE // TRUE by default? +#define STA_LOW_RSSI 65 // absolute +#define STA_DETECT_RSSI 55 // absolute +#define STALIST_AGEOUT_TIME 5 // sec +#define MNTRLIST_AGEOUT_TIME 4 // sec +#define MNTR_MIN_PKT_COUNT 5 +#define MNTR_MIN_TIME 1 // sec +#define AVG_RSSI_PKT_COUNT 5 +#define ACLLIST_AGEOUT_TIME 4 // sec +#define ACLLIST_HOLD_TIME 2 // sec + +void load_froam_defaults(RTMP_ADAPTER *pAd); +void froam_notify_sta_disconnect(void *ad_obj, void *pEntry); +#endif + +#endif /* __AP_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_acl_v2.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_acl_v2.h new file mode 100644 index 000000000..1f6dce356 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_acl_v2.h @@ -0,0 +1,125 @@ +#ifndef __AP_ACL_V2_H__ +#define __AP_ACL_V2_H__ + +#include "link_list.h" + +typedef enum FBT_IOT_PEER { + FBT_IOT_PEER_UNKNOWN = 0x00000001, + FBT_IOT_PEER_REALTEK = 0x00000002, + FBT_IOT_PEER_REALTEK_92SE = 0x00000004, + FBT_IOT_PEER_BROADCOM = 0x00000008, + FBT_IOT_PEER_RALINK = 0x00000010, + FBT_IOT_PEER_ATHEROS = 0x00000020, + FBT_IOT_PEER_CISCO = 0x00000040, + FBT_IOT_PEER_MERU = 0x00000080, + FBT_IOT_PEER_MARVEL = 0x00000100, + FBT_IOT_PEER_REALTEK_SOFTAP = 0x00000200, + FBT_IOT_PEER_SELF_SOFTAP = 0x00000400, + FBT_IOT_PEER_AIRGO = 0x00000800, + FBT_IOT_PEER_INTEL = 0x00001000, + FBT_IOT_PEER_RTK_APCLIENT = 0x00002000, + FBT_IOT_PEER_REALTEK_81XX = 0x00004000, + FBT_IOT_PEER_REALTEK_WOW = 0x00008000, + FBT_IOT_PEER_HTC = 0x00010000, + FBT_IOT_PEER_MAX = 0x00020000, +}FBT_IOT_PEER_E, *PFBT_IOT_PEER_E; + + +#define OUI_LEN 3 + +#define MAX_NUM_OF_ACL_V2_MAC 64 +#define MAX_NUM_OF_ACL_V2_OUI 64 + +typedef struct _OUI_ENTRY { + UINT32 ID; + UCHAR OUI[OUI_LEN]; +}OUI_ENTRY, *POUI_ENTRY; + + +typedef struct _ACL_MAC_CTRL { + DL_LIST List; + UCHAR MACAddr[MAC_ADDR_LEN]; + ULONG SetTime; +} ACL_MAC_CTRL, *PACL_MAC_CTRL; + +typedef struct _ACL_OUI_CTRL { + DL_LIST List; + UCHAR OUI[OUI_LEN]; + ULONG SetTime; +} ACL_OUI_CTRL, *PACL_OUI_CTRL; + + +typedef struct _ACL_V2_CTRL { + BOOLEAN OUI_Enable; + BOOLEAN MAC_Enable; + UINT32 OUI_ListNum; + UINT32 MAC_ListNum; + + PRTMP_ADAPTER pAd; + + ULONG BlockTime; // seconds to age out the MAC & OUI List Entry + RALINK_TIMER_STRUCT AgeOutTimer; + BOOLEAN AgeOutTimer_Running; + + RTMP_OS_SEM OUI_ListLock; + RTMP_OS_SEM MAC_ListLock; + + DL_LIST OUI_List; + DL_LIST MAC_List; +} ACL_V2_CTRL, *PACL_V2_CTRL; + +VOID ACL_V2_AgeOut( +IN PACL_V2_CTRL pACLCtrl); + +VOID ACL_V2_CtrlInit( + IN PRTMP_ADAPTER pAd); + +VOID ACL_V2_CtrlExit( + IN PRTMP_ADAPTER pAd); + +BOOLEAN ACL_V2_List_Check( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + IN UCHAR Apidx); + +INT Set_ACL_V2_DisConnectSta_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_ACL_V2_DisConnectOUI_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Show_ACL_V2_STAEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Show_ACL_V2_OUI_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +UINT32 Set_ACL_V2_AddSTAEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pTargetMACAddr); + +VOID Set_ACL_V2_DelSTAEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pTargetMACAddr); + +UINT32 Set_ACL_V2_AddOUIEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pTargetOUIAddr); + +VOID Set_ACL_V2_DelOUIEntry_Proc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pTargetOUIAddr); + +VOID Set_ACL_V2_EntryExpire_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +VOID Show_ACL_V2_EntryExpire_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +#endif /* __AP_ACL_V2_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_apcli.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_apcli.h new file mode 100644 index 000000000..66ef0235e --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_apcli.h @@ -0,0 +1,374 @@ +/* + *************************************************************************** + * 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 OPENWEP_ERRPKT_MAX_COUNT 3 +#define APCLI_WAIT_TIMEOUT RTMPMsecsToJiffies(300) + +#define APCLI_ROOT_BSSID_GET(pAd, wcid) ((pAd)->MacTab.Content[(wcid)].Addr) + +/* sanity check for apidx */ +#define APCLI_MR_APIDX_SANITY_CHECK(idx) \ +{ \ + if ((idx) >= MAX_APCLI_NUM) \ + { \ + (idx) = 0; \ + DBGPRINT(RT_DEBUG_ERROR, ("%s> Error! apcli-idx > MAX_APCLI_NUM!\n", __FUNCTION__)); \ + } \ +} + +typedef struct _APCLI_MLME_JOIN_REQ_STRUCT { + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR SsidLen; + UCHAR Ssid[MAX_LEN_OF_SSID]; +} APCLI_MLME_JOIN_REQ_STRUCT; + +typedef struct _APCLI_CTRL_MSG_STRUCT { + USHORT Status; + UCHAR SrcAddr[MAC_ADDR_LEN]; +#ifdef MAC_REPEATER_SUPPORT + UCHAR BssIdx; + UCHAR CliIdx; +#endif /* MAC_REPEATER_SUPPORT */ +} APCLI_CTRL_MSG_STRUCT, *PSTA_CTRL_MSG_STRUCT; + +BOOLEAN isValidApCliIf( + SHORT ifIndex); + +VOID ApCliCtrlStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID ApCliSyncStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID ApCliAuthStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID ApCliAssocStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +MAC_TABLE_ENTRY *ApCliTableLookUpByWcid( + IN RTMP_ADAPTER *pAd, + IN UCHAR wcid, + IN UCHAR *pAddrs); + +BOOLEAN ApCliValidateRSNIE( + IN RTMP_ADAPTER *pAd, + IN PEID_STRUCT pEid_ptr, + IN USHORT eid_len, + IN USHORT idx +#ifdef APCLI_OWE_SUPPORT + , IN UCHAR Privacy +#endif +); + + +VOID ApCli_Remove( + IN PRTMP_ADAPTER pAd); + +VOID RT28xx_ApCli_Close( + IN PRTMP_ADAPTER pAd); + + + +INT ApCliIfLookUp( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + + +VOID ApCliMgtMacHeaderInit( + IN PRTMP_ADAPTER pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN PUCHAR pDA, + IN PUCHAR pBssid, + IN USHORT ifIndex); + +#ifdef DOT11_N_SUPPORT +BOOLEAN ApCliCheckHt( + IN PRTMP_ADAPTER pAd, + IN USHORT IfIndex, + IN OUT HT_CAPABILITY_IE *pHtCapability, + IN OUT ADD_HT_INFO_IE *pAddHtInfo); +#endif /* DOT11_N_SUPPORT */ + +BOOLEAN ApCliLinkUp( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex); + +VOID ApCliLinkDown( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex); + +VOID ApCliIfUp( + IN PRTMP_ADAPTER pAd); + +VOID ApCliIfDown( + IN PRTMP_ADAPTER pAd); + +VOID ApCliIfMonitor( + IN PRTMP_ADAPTER pAd); + +BOOLEAN ApCliMsgTypeSubst( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT INT *MsgType); + +BOOLEAN preCheckMsgTypeSubset( + IN PRTMP_ADAPTER pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT INT *MsgType); + +BOOLEAN ApCliPeerAssocRspSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pStatus, + OUT USHORT *pAid, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT ADD_HT_INFO_IE *pAddHtInfo, /* AP might use this additional ht info IE */ + OUT UCHAR *pHtCapabilityLen, + OUT UCHAR *pAddHtInfoLen, + OUT UCHAR *pNewExtChannelOffset, + OUT PEDCA_PARM pEdcaParm, + OUT UCHAR *pCkipFlag, + OUT IE_LISTS *le_list); + +VOID ApCliPeerPairMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID ApCliPeerPairMsg3Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID ApCliPeerGroupMsg1Action( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +BOOLEAN ApCliCheckRSNIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR DataLen, + IN MAC_TABLE_ENTRY *pEntry, + OUT UCHAR *Offset); + +BOOLEAN ApCliParseKeyData( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pKeyData, + IN UCHAR KeyDataLen, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR IfIdx, + IN UCHAR bPairewise); + +BOOLEAN ApCliHandleRxBroadcastFrame( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR wdev_idx); + +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(RTMP_ADAPTER *pAd, USHORT ifIndex); + + +VOID APCli_Init( + IN RTMP_ADAPTER *pAd, + IN RTMP_OS_NETDEV_OP_HOOK *pNetDevOps); + +BOOLEAN ApCli_Open(RTMP_ADAPTER *pAd, PNET_DEV dev_p); +BOOLEAN ApCli_Close(RTMP_ADAPTER *pAd, PNET_DEV dev_p); + +BOOLEAN ApCliWaitProbRsp(RTMP_ADAPTER *pAd, USHORT ifIndex); +VOID ApCliSimulateRecvBeacon(RTMP_ADAPTER *pAd); + +#ifdef MAC_REPEATER_SUPPORT +INT AsicSetMacAddrExt(RTMP_ADAPTER *pAd, BOOLEAN enable); +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef APCLI_AUTO_CONNECT_SUPPORT +extern INT Set_ApCli_Enable_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +extern INT Set_ApCli_Bssid_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *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 */ +VOID ApCliRxOpenWEPCheck( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk, + IN BOOLEAN bSuccessPkt); +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef DOT11W_PMF_SUPPORT +INT Set_ApCliPMFMFPC_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_ApCliPMFMFPR_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_ApCliPMFSHA256_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ +#ifdef APCLI_SAE_SUPPORT +INT set_apcli_sae_group_proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +#endif + +#ifdef APCLI_OWE_SUPPORT +INT set_apcli_owe_group_proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +#endif + +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + +INT apcli_add_pmkid_cache( + IN PRTMP_ADAPTER pAd, + IN UCHAR *paddr, + IN UCHAR *pmkid, + IN UCHAR *pmk, + IN UINT8 pmk_len, + IN UINT8 if_index +#ifdef MAC_REPEATER_SUPPORT + , IN UINT8 cli_idx +#endif + ); + + + +INT apcli_search_pmkid_cache( + IN PRTMP_ADAPTER pAd, + IN UCHAR *paddr, + IN UCHAR if_index +#ifdef MAC_REPEATER_SUPPORT + , IN UINT8 cli_idx +#endif + ); + + + +VOID apcli_delete_pmkid_cache( + IN PRTMP_ADAPTER pAd, + IN UCHAR *paddr, + IN UCHAR if_index +#ifdef MAC_REPEATER_SUPPORT + , IN UINT8 cli_idx +#endif + ); + + +VOID apcli_delete_pmkid_cache_all( + IN PRTMP_ADAPTER pAd, + IN UCHAR if_index); + +INT set_apcli_del_pmkid_list( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +#endif + +#ifdef APCLI_OWE_SUPPORT + +VOID apcli_reset_owe_parameters( + IN PRTMP_ADAPTER pAd, + IN UCHAR if_index); + +#endif + + +#endif /* APCLI_SUPPORT */ + +#ifdef WH_EZ_SETUP +void send_unicast_deauth_apcli(void *ad_obj, USHORT idx); + +VOID ApCliMlmeDeauthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#endif + +#endif /* _AP_APCLI_H_ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_autoChSel.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_autoChSel.h new file mode 100644 index 000000000..31cad1833 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_autoChSel.h @@ -0,0 +1,83 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + 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/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_autoChSel_cmm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_autoChSel_cmm.h new file mode 100644 index 000000000..f0ab8d027 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_autoChSel_cmm.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. + **************************************************************************** + + Abstract: + + + */ + + +#ifndef __AUTOCHSELECT_CMM_H__ +#define __AUTOCHSELECT_CMM_H__ + +/* Note: RSSI_TO_DBM_OFFSET has been changed to variable for new RF (2004-0720). */ +/* SHould not refer to this constant anymore */ +//#define RSSI_TO_DBM_OFFSET 120 /* RSSI-115 = dBm */ + + +#ifdef ACS_CTCC_SUPPORT +typedef struct { + UCHAR BestCtrlChannel; /* Min in group */ + UCHAR CenChannel; + UCHAR RegulatoryDomain; + UINT32 Max_Busy_Time; /* Max in group */ + UINT32 Min_Busy_Time; /* Min in group */ + BOOLEAN SkipGroup; +} ACS_SCAN_CH_GROUP_LIST, *PACS_SCAN_CH_GROUP_LIST; +typedef struct { + UCHAR GroupType; /*0:BW20, 1:BW40, 2:BW80 */ + UCHAR ApCnt; + UCHAR Channel; + UCHAR CenChannel; + UCHAR DfsReq; + UCHAR RegulatoryDomain; + BOOLEAN SkipChannel; + UINT32 BusyTime; + +#define CHANNEL_DEFAULT_PROP 0x00 +#define CHANNEL_DISABLED 0x01 /* no use */ +#define CHANNEL_PASSIVE_SCAN 0x02 +#define CHANNEL_NO_IBSS 0x04 +#define CHANNEL_RADAR 0x08 +#define CHANNEL_NO_FAT_ABOVE 0x10 +#define CHANNEL_NO_FAT_BELOW 0x20 +#define CHANNEL_40M_CAP 0x40 +#define CHANNEL_80M_CAP 0x80 + UCHAR Flags; +} ACS_SCAN_SUPP_CH_LIST, *PACS_SCAN_SUPP_CH_LIST; +#endif +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; +#ifdef ACS_CTCC_SUPPORT + AUTO_CH_SEL_SCORE ChannelScore[MAX_NUM_OF_CHANNELS+1]; + UINT32 ChannelListNum; + UINT32 GroupChListNum; + ACS_SCAN_SUPP_CH_LIST suppChList[MAX_NUM_OF_CHANNELS+1]; + ACS_SCAN_CH_GROUP_LIST GroupChList[MAX_NUM_OF_CHANNELS+1]; +#endif +} 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, + ChannelAlgBusyTime, + ChannelAlgCombined +} ChannelSel_Alg; + +#endif /* __AUTOCHSELECT_CMM_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_cfg.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_cfg.h new file mode 100644 index 000000000..1fec696b4 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_cfg.h @@ -0,0 +1,259 @@ +#ifndef __AP_CFG_H__ +#define __AP_CFG_H__ + + +#include "rt_config.h" +#ifdef STA_FORCE_ROAM_SUPPORT +#define IS_MEDIATEK_CLI_ENTRY(B0) ((B0)&0x10) +#endif +#ifdef STA_FORCE_ROAM_SUPPORT +int froam_add_acl_entry(void *ad_obj, RTMP_IOCTL_INPUT_STRUCT *wrq); +int froam_del_acl_entry(void *ad_obj, RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif + +INT RTMPAPPrivIoctlSet( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *pIoctlCmdStr); + +INT RTMPAPPrivIoctlShow( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *pIoctlCmdStr); + +#if defined(INF_AR9) || defined(BB_SOC) +#if defined(AR9_MAPI_SUPPORT) || defined(BB_SOC) +INT RTMPAPPrivIoctlAR9Show( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *pIoctlCmdStr); + +VOID RTMPAR9IoctlGetMacTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlGetSTAT2( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlGetRadioDynInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif /*AR9_MAPI_SUPPORT*/ +#endif/* INF_AR9 */ + +INT RTMPAPSetInformation( + IN PRTMP_ADAPTER pAd, + IN OUT RTMP_IOCTL_INPUT_STRUCT *rq, + IN INT cmd); + +INT RTMPAPQueryInformation( + IN PRTMP_ADAPTER pAd, + IN OUT RTMP_IOCTL_INPUT_STRUCT *rq, + IN INT cmd); + +VOID RTMPIoctlStatistics( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlGetMacTableStaInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlGetMacTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlGetDriverInfo( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT * wrq); + +VOID RTMPAPIoctlE2PROM( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +#if defined(DBG) ||(defined(BB_SOC)&&defined(CONFIG_ATE)) +VOID RTMPAPIoctlBBP( + 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); + +#ifdef WSC_NFC_SUPPORT +VOID RTMPIoctlNfcStatus( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif /* WSC_NFC_SUPPORT */ + +/*add by woody */ +#if defined(INF_AR9) || defined(BB_SOC) +#if defined(AR9_MAPI_SUPPORT) || defined(BB_SOC) +VOID RTMPAR9IoctlWscProfile( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlWscPINCode( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + + +VOID RTMPIoctlWscStatus( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlGetWscDynInfo( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlGetWscRegsDynInfo( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif/*AR9_MAPI_SUPPORT*/ +#endif/* INF_AR9 */ +#endif /* WSC_AP_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +VOID RTMPIoctlQueryBaTable( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT1X_SUPPORT +VOID RTMPIoctlStaticWepCopy( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlRadiusData( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlAddWPAKey( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlAddPMKIDCache( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlSetIdleTimeout( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +VOID RTMPIoctlQueryStaAid( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif /* DOT1X_SUPPORT */ + +INT Set_AP_Daemon_Status( + IN PRTMP_ADAPTER pAd, + IN UINT8 WorkSpaceID, + IN BOOLEAN Status); + +INT Send_ANQP_Rsp( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *PeerMACAddr, + IN RTMP_STRING *ANQPReq, + IN UINT32 ANQPReqLen); + +INT ApCfg_Set_AuthMode_Proc( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN RTMP_STRING *arg); + +INT ApCfg_Set_MaxStaNum_Proc( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN RTMP_STRING *arg); + +INT ApCfg_Set_IdleTimeout_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +struct apcfg_parameters { + LONG cfg_mode[2]; /*WirelessMode*/ + ULONG tx_power_percentage; /*TxPower*/ + ULONG tx_preamble; /*TxPreamble*/ + UINT32 conf_len_thld; /*RTSThreshold*/ + UINT32 oper_len_thld; + UINT32 conf_frag_thld; /*FragThreshold*/ + UINT32 oper_frag_thld; + BOOLEAN bEnableTxBurst; /*TxBurst*/ + BOOLEAN bUseShortSlotTime; /*ShortSlot*/ +#ifdef DOT11_N_SUPPORT + UCHAR conf_ht_bw; /*HT_BW*/ + UCHAR oper_ht_bw; +#ifdef DOT11N_DRAFT3 + BOOLEAN bBssCoexEnable; /*HT_BSSCoexistence*/ +#endif + UCHAR ht_tx_streams; /*HT_TxStream*/ + UCHAR ht_rx_streams; /*HT_RxStream*/ + BOOLEAN bBADecline; /*HT_BADecline*/ + UINT32 AutoBA; /*HT_AutoBA*/ + UINT32 AmsduEnable; /*HT_AMSDU*/ + UINT32 RxBAWinLimit; /*HT_BAWinSize*/ + UCHAR ht_gi; /*HT_GI*/ + UCHAR ht_stbc; /*HT_STBC*/ + UCHAR ht_ldpc; /*HT_LDPC*/ + BOOLEAN bRdg; /*HT_RDG*/ +#endif + + BOOLEAN HT_DisallowTKIP; /*HT_DisallowTKIP*/ + +#ifdef DOT11_VHT_AC + UCHAR conf_vht_bw; /*VHT_BW*/ + UCHAR oper_vht_bw; + UCHAR vht_sgi; /*VHT_SGI*/ + UCHAR vht_stbc; /*VHT_STBC*/ + UCHAR vht_bw_signal; /*VHT_BW_SIGNAL*/ + UCHAR vht_ldpc; /*VHT_LDPC*/ + BOOLEAN g_band_256_qam; /*G_BAND_256QAM*/ +#endif + + BOOLEAN bIEEE80211H; /*IEEE80211H*/ + +#ifdef MT_DFS_SUPPORT + BOOLEAN bDfsEnable; /*DfsEnable*/ +#endif + +#ifdef BACKGROUND_SCAN_SUPPORT + BOOLEAN DfsZeroWaitSupport; /*DfsZeroWait*/ +#endif + +#ifdef DOT11_N_SUPPORT +#endif + + UINT32 ITxBfEn; /*ITxBfEn*/ + +#ifdef DOT11_N_SUPPORT +#endif + UCHAR channel; + UCHAR CentralChannel; + UCHAR ext_channel; +}; + +INT _Set_AP_VENDOR_SPECIFIC_IE( + IN PRTMP_ADAPTER pAd, + IN UINT8 OUIType, + IN RTMP_STRING *IE, + IN UINT32 IELen); + + +#ifdef APCLI_SUPPORT +#endif /* APCLI_SUPPORT */ +#endif /* __AP_CFG_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_diversity.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_diversity.h new file mode 100644 index 000000000..89d7bb176 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_diversity.h @@ -0,0 +1,138 @@ +/*************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + ap_diversity.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------- + YY Huang 06-10-2008 Init for RT3052. +*/ + +#ifndef _AP_DIVERSITY_H_ +#define _AP_DIVERSITY_H_ + +#include "rtmp.h" + +#define ADDBGPRINT(format,args...) do{if(atomic_read(&DEBUG_VERBOSE_MODE)) printk( format, ##args);}while(0) +#define PROC_DIR "AntDiv" + +/* + * For shorter udelay(). + * (ripped from rtmp.h) + */ +/* Read BBP register by register's ID. Generate PER to test BA */ +#define RTMP_BBP_IO_READ8_BY_REG_ID_SHORT_DELAY(_A, _I, _pV) \ +{ \ + BBP_CSR_CFG_STRUC BbpCsr; \ + int i, k; \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + for (i=0; iBbpWriteLatch[_I]; \ + RTMP_IO_READ32(_A, H2M_BBP_AGENT, &BbpCsr.word);\ + BbpCsr.field.Busy = 0; \ + RTMP_IO_WRITE32(_A, H2M_BBP_AGENT, BbpCsr.word);\ + } \ + } \ +} + + +/* + * proc fs related macros. + */ +#define CREATE_PROC_ENTRY(x) \ + if ((pProc##x = create_proc_entry(#x, 0, pProcDir))){ \ + pProc##x->read_proc = (read_proc_t*)&x##Read; \ + pProc##x->write_proc = (write_proc_t*)&x##Write; \ + } \ + +#define IMPLEMENT_PROC_ENTRY(x,y,z) \ +static struct proc_dir_entry *pProc##x; \ +IMPLEMENT_PROC_ENTRY_READ(x,y,z) \ +IMPLEMENT_PROC_ENTRY_WRITE(x,y,z) + +#define IMPLEMENT_PROC_ENTRY_READ(x,y,z) \ +static INT x##Read(char *page, char **start, off_t off, \ + int count, int *eof, void *data){ \ + INT len; \ + sprintf(page, "%d\n", atomic_read(&x)); \ + len = strlen(page) + 1; \ + *eof = 1; \ + return len; \ +} +#define IMPLEMENT_PROC_ENTRY_WRITE(x,y,z) \ +static INT x##Write(struct file *file, const char *buffer, \ + unsigned long count, void *data){ \ + CHAR tmp[32];INT tmp_val; \ + if (count > 32) count = 32; \ + memset(tmp, 0, 32); \ + if (copy_from_user(tmp, buffer, count)) \ + return -EFAULT; \ + tmp_val = simple_strtol(tmp, 0, 10); \ + if(tmp_val > z || tmp_val < y) \ + return -EFAULT; \ + atomic_set(&x, (int)tmp_val); \ + return count; \ +} +#define DESTORY_PROC_ENTRY(x) if (pProc##x) remove_proc_entry(#x, pProcDir); + +/* + * function prototype + */ +VOID RT3XXX_AntDiversity_Init(RTMP_ADAPTER *pAd); +VOID RT3XXX_AntDiversity_Fini(RTMP_ADAPTER *pAd); + +VOID AntDiversity_Update_Rssi_Sample( + IN RTMP_ADAPTER *pAd, + IN RSSI_SAMPLE *pRssi, + IN RXWI_STRUC *pRxWI); + +#endif + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_ids.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_ids.h new file mode 100644 index 000000000..c71dd80d0 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_ids.h @@ -0,0 +1,68 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + ap_ids.c + + Abstract: + IDS definition + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + */ + +VOID RTMPIdsPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +BOOLEAN RTMPSpoofedMgmtDetection( + IN RTMP_ADAPTER *pAd, + IN HEADER_802_11 *pHeader, + IN RX_BLK *rxblk); + +VOID RTMPConflictSsidDetection( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN CHAR Rssi0, + IN CHAR Rssi1, + IN CHAR Rssi2); + +BOOLEAN RTMPReplayAttackDetection( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr2, + IN RX_BLK *rxblk); + +VOID RTMPUpdateStaMgmtCounter( + IN PRTMP_ADAPTER pAd, + IN USHORT type); + +VOID RTMPClearAllIdsCounter( + IN PRTMP_ADAPTER pAd); + +VOID RTMPIdsStart( + IN PRTMP_ADAPTER pAd); + +VOID RTMPIdsStop( + IN PRTMP_ADAPTER pAd); + +VOID rtmp_read_ids_from_file( + IN PRTMP_ADAPTER pAd, + char *tmpbuf, + char *buffer); + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_mbss.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_mbss.h new file mode 100644 index 000000000..667b4728f --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/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 +*/ + + +/* + For MBSS, the phy mode is different; + So MBSS_PHY_MODE_RESET() can help us to adjust the correct mode & + maximum MCS for the BSS. +*/ +#define MBSS_PHY_MODE_RESET(__BssId, __HtPhyMode) \ + { \ + UCHAR __PhyMode = pAd->ApCfg.MBSSID[__BssId].wdev.PhyMode; \ + if ((__PhyMode == WMODE_B) && \ + (__HtPhyMode.field.MODE != MODE_CCK)) \ + { \ + __HtPhyMode.field.MODE = MODE_CCK; \ + __HtPhyMode.field.MCS = 3; \ + } \ + else if ((!WMODE_CAP_N(__PhyMode)) && \ + (__PhyMode != WMODE_B) && \ + (__HtPhyMode.field.MODE != MODE_OFDM)) \ + { \ + __HtPhyMode.field.MODE = MODE_OFDM; \ + __HtPhyMode.field.MCS = 7; \ + } \ + else if ((__PhyMode != WMODE_B) && \ + (__PhyMode != WMODE_G) && \ + (__PhyMode != WMODE_A) && \ + (!WMODE_CAP_AC(__PhyMode)) && \ + (__HtPhyMode.field.MODE != MODE_HTMIX)) \ + { \ + __HtPhyMode.field.MODE = MODE_HTMIX; \ + __HtPhyMode.field.MCS = 7; \ + } \ + else \ + { \ + __HtPhyMode.field.MODE = MODE_VHT; \ + __HtPhyMode.field.MCS = 9; \ + __HtPhyMode.field.BW = BW_80; \ + } \ + } + + +/* Public function list */ +INT Show_MbssInfo_Display_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +VOID MBSS_Init(RTMP_ADAPTER *pAd, RTMP_OS_NETDEV_OP_HOOK *pNetDevOps); + +VOID MBSS_Remove(RTMP_ADAPTER *pAd); + +INT MBSS_Open(PNET_DEV pDev); + +INT MBSS_Close(PNET_DEV pDev); + +INT32 RT28xx_MBSS_IdxGet( + IN PRTMP_ADAPTER pAd, + IN PNET_DEV pDev); + +#ifdef MT_MAC +INT mbss_cr_enable(PNET_DEV pDev); +INT mbss_cr_disable(PNET_DEV pDev); +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_wds.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_wds.h new file mode 100644 index 000000000..12042ef62 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ap_wds.h @@ -0,0 +1,159 @@ +/* + *************************************************************************** + * 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) + + +static inline BOOLEAN WDS_IF_UP_CHECK( + IN PRTMP_ADAPTER pAd, + IN ULONG ifidx) +{ + if ((pAd->flg_wds_init != TRUE) || + (ifidx >= MAX_WDS_ENTRY)) + return FALSE; + +/* if(RTMP_OS_NETDEV_STATE_RUNNING(pAd->WdsTab.WdsEntry[ifidx].dev)) */ +/* Patch for wds ,when dirver call apmlmeperiod => APMlmeDynamicTxRateSwitching check if wds device ready */ +if ((pAd->WdsTab.WdsEntry[ifidx].wdev.if_dev != NULL) && (RTMP_OS_NETDEV_STATE_RUNNING(pAd->WdsTab.WdsEntry[ifidx].wdev.if_dev))) + return TRUE; + + return FALSE; +} + +INT WdsEntryAlloc( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +VOID WdsEntryDel( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +MAC_TABLE_ENTRY *MacTableInsertWDSEntry( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + UINT WdsTabIdx); + +BOOLEAN MacTableDeleteWDSEntry( + IN PRTMP_ADAPTER pAd, + IN USHORT wcid, + IN PUCHAR pAddr); + +MAC_TABLE_ENTRY *WdsTableLookupByWcid( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount); + +MAC_TABLE_ENTRY *WdsTableLookup( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr, + IN BOOLEAN bResetIdelCount); + +MAC_TABLE_ENTRY *FindWdsEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR Wcid, + IN PUCHAR pAddr, + IN UINT32 PhyMode); + +VOID WdsTableMaintenance( + IN PRTMP_ADAPTER pAd); + + +VOID WdsDown( + IN PRTMP_ADAPTER pAd); + +VOID AsicUpdateWdsRxWCIDTable( + IN PRTMP_ADAPTER pAd); + +VOID AsicUpdateWdsEncryption( + IN PRTMP_ADAPTER pAd, + IN UCHAR wcid); + +VOID WdsPeerBeaconProc( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN USHORT CapabilityInfo, + IN UCHAR MaxSupportedRateIn500Kbps, + IN UCHAR MaxSupportedRateLen, + IN BOOLEAN bWmmCapable, + IN ULONG ClientRalinkIe, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen); + +VOID APWdsInitialize(RTMP_ADAPTER *pAd); + +INT Show_WdsTable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +VOID rtmp_read_wds_from_file( + IN PRTMP_ADAPTER pAd, + RTMP_STRING *tmpbuf, + RTMP_STRING *buffer); + +VOID WdsPrepareWepKeyFromMainBss(RTMP_ADAPTER *pAd); + +VOID RT28xx_WDS_Close(RTMP_ADAPTER *pAd); +VOID WDS_Init(RTMP_ADAPTER *pAd, RTMP_OS_NETDEV_OP_HOOK *pNetDevOps); +VOID WDS_Remove(RTMP_ADAPTER *pAd); +BOOLEAN WDS_StatsGet(RTMP_ADAPTER *pAd, RT_CMD_STATS *pStats); +VOID AP_WDS_KeyNameMakeUp(RTMP_STRING *pKey, UINT32 KeyMaxSize, INT KeyId); + +/* + ========================================================================== + Description: + Check the WDS Entry is valid or not. + ========================================================================== + */ +static inline BOOLEAN ValidWdsEntry( + IN PRTMP_ADAPTER pAd, + IN UCHAR WdsIndex) +{ + BOOLEAN result = FALSE; + PMAC_TABLE_ENTRY pMacEntry; + + if ((WdsIndex < MAX_WDS_ENTRY) && + (pAd->WdsTab.WdsEntry[WdsIndex].Valid == TRUE)) + { + if ((pAd->WdsTab.WdsEntry[WdsIndex].MacTabMatchWCID > 0) && + (pAd->WdsTab.WdsEntry[WdsIndex].MacTabMatchWCID < MAX_LEN_OF_MAC_TABLE)) + { + pMacEntry = &pAd->MacTab.Content[pAd->WdsTab.WdsEntry[WdsIndex].MacTabMatchWCID]; + if (IS_ENTRY_WDS(pMacEntry)) + result = TRUE; + } + } + + return result; +} + +#endif /* _AP_WDS_H_ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/band_steering.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/band_steering.h new file mode 100644 index 000000000..5a5e493a7 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/band_steering.h @@ -0,0 +1,112 @@ +/* + *************************************************************************** + * 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, RTMP_STRING *arg); +INT Show_BndStrg_Info(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_BndStrg_Enable(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_BndStrg_Param(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +#ifdef BND_STRG_DBG +INT Set_BndStrg_MonitorAddr(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +#endif /* BND_STRG_DBG */ + +INT BndStrg_Init(PRTMP_ADAPTER pAd); +INT BndStrg_Release(PRTMP_ADAPTER pAd); +INT BndStrg_TableInit(PRTMP_ADAPTER pAd, INT apidx); +INT BndStrg_TableRelease(PBND_STRG_CLI_TABLE table); +PBND_STRG_CLI_TABLE Get_BndStrgTable(PRTMP_ADAPTER pAd, INT apidx); + +/* WPS_BandSteering Support */ +PBND_STRG_CLI_ENTRY BndStrg_TableLookup(PBND_STRG_CLI_TABLE table, PUCHAR pAddr); + +PWPS_WHITELIST_ENTRY FindWpsWhiteListEntry(PLIST_HEADER pWpsWhiteList, PUCHAR pMacAddr); +VOID AddWpsWhiteList(PLIST_HEADER pWpsWhiteList, PUCHAR pMacAddr); +VOID DelWpsWhiteListExceptMac(PLIST_HEADER pWpsWhiteList, PUCHAR pMacAddr); +VOID ClearWpsWhiteList(PLIST_HEADER pWpsWhiteList); + +PBS_LIST_ENTRY FindBsListEntry(PLIST_HEADER pBsList, PUCHAR pMacAddr); +VOID AddBsListEntry(PLIST_HEADER pBsList, PUCHAR pMacAddr); +VOID DelBsListEntry(PLIST_HEADER pBsList, PUCHAR pMacAddr); +VOID ClearBsList(PLIST_HEADER pBsList); + +BOOLEAN BndStrg_CheckConnectionReq( + PRTMP_ADAPTER pAd, + struct wifi_dev *wdev, + PUCHAR pSrcAddr, + MLME_QUEUE_ELEM * Elem, + PEER_PROBE_REQ_PARAM * ProbeReqParam); + +INT BndStrg_Tb_Enable(PBND_STRG_CLI_TABLE table, BOOLEAN enable, CHAR *IfName); +INT BndStrg_SetInfFlags(PRTMP_ADAPTER pAd, struct wifi_dev *wdev, PBND_STRG_CLI_TABLE table, BOOLEAN bInfReady); +INT BndStrg_MsgHandle(PRTMP_ADAPTER pAd, RTMP_IOCTL_INPUT_STRUCT *wrq, INT apidx); +#ifdef VENDOR_FEATURE5_SUPPORT +void BndStrg_GetNvram(PRTMP_ADAPTER pAd, RTMP_IOCTL_INPUT_STRUCT *wrq, INT apidx); +void BndStrg_SetNvram(PRTMP_ADAPTER pAd, RTMP_IOCTL_INPUT_STRUCT *wrq, INT apidx); +INT Show_BndStrg_NvramTable(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +#endif /* VENDOR_FEATURE5_SUPPORT */ +INT Set_BndStrg_BssIdx(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +void BndStrg_UpdateEntry(PRTMP_ADAPTER pAd, MAC_TABLE_ENTRY *pEntry, IE_LISTS *ie_list, BOOLEAN bConnStatus); +UINT8 GetNssFromHTCapRxMCSBitmask(UINT32 RxMCSBitmask); +extern VOID EnableRadioChstats(PRTMP_ADAPTER pAd); +void BndStrgSetProfileParam(struct _RTMP_ADAPTER *pAd, RTMP_STRING *tmpbuf, RTMP_STRING *pBuffer); +void BndStrgHeartBeatMonitor(PRTMP_ADAPTER pAd); +INT BndStrgSendMsg(PRTMP_ADAPTER pAd, BNDSTRG_MSG *msg); +void BndStrg_send_BTM_req(IN PRTMP_ADAPTER pAd, IN RTMP_STRING *PeerMACAddr, IN RTMP_STRING *BTMReq, IN UINT32 BTMReqLen, PBND_STRG_CLI_TABLE table); +void BndStrg_Send_NeighborReport(PRTMP_ADAPTER pAd, PBND_STRG_CLI_TABLE table); +VOID BndStrg_KickOutAllSta(PRTMP_ADAPTER pAd, UCHAR apidx, USHORT Reason); + +#define IS_VALID_MAC(addr) \ + ((addr[0])|(addr[1])|(addr[2])|(addr[3])|(addr[4])|(addr[5])) + +#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_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, _Level, _Fmt) MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, _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_MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, _Level, _Fmt) +#endif /* !BND_STRG_DBG */ + +#ifdef BND_STRG_QA +#define BND_STRG_PRINTQAMSG(_table, _Addr, _Fmt) \ +{ \ + if (MAC_ADDR_EQUAL(_table->MonitorAddr, _Addr)) \ + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, _Fmt); \ +} +#else +#define BND_STRG_PRINTQAMSG(_Level, _Fmt) +#endif /* BND_STRG_QA */ + +#define BNDSTRG_IS_WPA_CAPABILITY(_x) \ + (_x == Ndis802_11AuthModeWPA || _x == Ndis802_11AuthModeWPAPSK || _x == Ndis802_11AuthModeWPANone || \ + _x == Ndis802_11AuthModeWPANone || _x == Ndis802_11AuthModeWPA2PSK || _x == Ndis802_11AuthModeWPA1PSKWPA2PSK ||\ + _x == Ndis802_11AuthModeWPA2) + +#endif /* BAND_STEERING */ +#endif /* _BAND_STEERING_H_ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/band_steering_def.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/band_steering_def.h new file mode 100644 index 000000000..8042676c5 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/band_steering_def.h @@ -0,0 +1,381 @@ +/* + *************************************************************************** + * 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 */ + +#define BND_STRG_MAX_TABLE_SIZE 64 +#define P_BND_STRG_TABLE(_x) (&pAd->ApCfg.BndStrgTable[_x]) +#define SIZE_OF_VHT_CAP_IE 12 +#define IS_2G_BAND(_p) (((_p)&BAND_24G)==BAND_24G) +#define IS_5G_BAND(_p) (((_p)&BAND_5G)==BAND_5G) + + +#define BND_STRG_DBG +#define BND_STRG_QA + +typedef struct _BND_STRG_CLI_ENTRY { + BOOLEAN bValid; + BOOLEAN bConnStatus; + UINT8 TableIndex; + UINT32 Control_Flags; + ULONG jiffies; /* timestamp when insert-entry */ + UINT32 elapsed_time; /* ms */ + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR BndStrg_Sta_State; + struct _BND_STRG_CLI_ENTRY *pNext; +} BND_STRG_CLI_ENTRY, *PBND_STRG_CLI_ENTRY; + +/* WPS_BandSteering Support */ +typedef struct _WPS_WHITELIST_ENTRY { + struct _WPS_WHITELIST_ENTRY *pNext; + UCHAR addr[MAC_ADDR_LEN]; + UCHAR state; +} WPS_WHITELIST_ENTRY, *PWPS_WHITELIST_ENTRY; + +typedef struct _BS_LIST_ENTRY { + struct _BS_LIST_ENTRY *pNext; + UCHAR addr[MAC_ADDR_LEN]; + UCHAR state; +} BS_LIST_ENTRY, *PBS_LIST_ENTRY; + +#define NVRAM_TABLE_SIZE 128 + +typedef struct _bndstrg_nvram_client { + UINT8 Addr[MAC_ADDR_LEN]; + UINT8 Manipulable; + UINT8 PhyMode; + UINT8 Band; + UINT8 Nss; +} BNDSTRG_NVRAM_CLIENT, *PBNDSTRG_NVRAM_CLIENT; + +typedef struct _bndstrg_nvram_list { + UINT8 Num; + BNDSTRG_NVRAM_CLIENT nvram_entry[NVRAM_TABLE_SIZE]; +} BNDSTRG_NVRAM_LIST, *PBNDSTRG_NVRAM_LIST; + +enum PhyMode { + fPhyMode_Legacy, + fPhyMode_HT, + fPhyMode_VHT, +}; + +#define OID_BNDSTRG_GET_NVRAM 0x0951 +#define OID_BNDSTRG_SET_NVRAM 0x0952 +#define BND_STRG_MAX_WHITELIST_ENTRY 16 +#define BND_STRG_MAX_BLACKLIST_ENTRY 4 + +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; + VOID *priv; + BOOLEAN bInfReady; + CHAR ucIfName[32]; + UINT8 uIdx; +#ifdef BND_STRG_DBG + UCHAR MonitorAddr[MAC_ADDR_LEN]; +#endif /* BND_STRG_DBG */ +#ifdef VENDOR_FEATURE5_SUPPORT + BNDSTRG_NVRAM_CLIENT nvram_entry[NVRAM_TABLE_SIZE]; + UINT8 bndstrg_nvram_client_count; +#endif /* VENDOR_FEATURE5_SUPPORT */ + UINT8 Band; + UINT8 Channel; + BOOLEAN bVHTCapable; + UINT8 nss; + UINT8 ActiveCount; + UINT32 DaemonPid; +#ifdef DOT11K_RRM_SUPPORT + RRM_NEIGHBOR_REP_INFO NeighborRepInfo; +#endif + UINT8 BndStrgMode; + /* WPS_BandSteering Support */ + LIST_HEADER WpsWhiteList; /* WPS: init in bandstearing table init */ + NDIS_SPIN_LOCK WpsWhiteListLock; + LIST_HEADER WhiteList; /* init in bandstearing table init */ + NDIS_SPIN_LOCK WhiteListLock; + LIST_HEADER BlackList; /* init in bandstearing table init */ + NDIS_SPIN_LOCK BlackListLock; +} BND_STRG_CLI_TABLE, *PBND_STRG_CLI_TABLE; + +enum BND_STRG_RETURN_CODE { + BND_STRG_SUCCESS = 0, + BND_STRG_INVALID_ARG, + BND_STRG_RESOURCE_ALLOC_FAIL, + BND_STRG_TABLE_FULL, + BND_STRG_TABLE_IS_NULL, + BND_STRG_NOT_INITIALIZED, + BND_STRG_2G_INF_NOT_READY, + BND_STRG_5G_INF_NOT_READY, + BND_STRG_STA_IS_CONNECTED, + BND_STRG_UNEXP, +}; + +#define OID_BNDSTRG_MSG 0x0950 +enum ACTION_CODE { + CLI_EVENT = 1, + CLI_ADD, + CLI_DEL, + CLI_STATUS_REQ, + CLI_STATUS_RSP, + CHANLOAD_STATUS_REQ, + CHANLOAD_STATUS_RSP, + INF_STATUS_QUERY, + INF_STATUS_RSP, + TABLE_INFO, + ENTRY_LIST, + BNDSTRG_ONOFF, + SET_MNT_ADDR, + NVRAM_UPDATE, + REJECT_EVENT, + HEARTBEAT_MONITOR, + BNDSTRG_WNM_BTM, + BNDSTRG_PARAM, + BNDSTRG_NEIGHBOR_REPORT, + UPDATE_WHITE_BLACK_LIST, +}; + +enum BND_STRG_STA_STATE { + BNDSTRG_STA_INIT = 0, + BNDSTRG_STA_ASSOC, + BNDSTRG_STA_DISASSOC, +}; + +enum bndstrg_mode{ + PRE_CONNECTION_STEERING = 0x01, + POST_CONNECTION_STEERING = 0x02, +}; + +enum bndstrg_list_type { + bndstrg_whitelist = 1, + bndstrg_blacklist = 2, +}; + +/* HEARTBEAT_MONITOR */ +struct bnd_msg_heartbeat { + CHAR ucIfName[32]; +}; + +struct bnd_msg_cli_probe { + BOOLEAN bAllowStaConnectInHt; + BOOLEAN bIosCapable; /* For IOS immediately connect */ + UINT8 bVHTCapable; + UINT8 Nss; + CHAR Rssi[4]; +}; + +struct bnd_msg_cli_auth { + CHAR Rssi[4]; +}; + +struct bnd_msg_cli_assoc { + BOOLEAN bAllowStaConnectInHt; + UINT8 bVHTCapable; + UINT8 Nss; + UINT8 BTMSupport; + BOOLEAN bWpsAssoc; +}; + +struct bnd_msg_cli_delete { +}; + +/* CLI_EVENT */ +struct bnd_msg_cli_event { + UINT8 FrameType; + UINT8 Band; + UINT8 Channel; + UCHAR Addr[MAC_ADDR_LEN]; + union { + struct bnd_msg_cli_probe cli_probe; + struct bnd_msg_cli_auth cli_auth; + struct bnd_msg_cli_assoc cli_assoc; + struct bnd_msg_cli_delete cli_delete; + } data; +}; + +/* CLI_ADD */ +struct bnd_msg_cli_add { + UINT8 TableIndex; + UCHAR Addr[MAC_ADDR_LEN]; +}; + +/* CLI_DEL */ +struct bnd_msg_cli_del { + UINT8 TableIndex; + UCHAR Addr[MAC_ADDR_LEN]; +}; + +/* CLI_STATUS_REQ */ +struct bnd_msg_cli_status_req { +}; + +/* CLI_STATUS_RSP */ +struct bnd_msg_cli_status_rsp { + UINT8 TableIndex; + UINT8 ReturnCode; + UCHAR Addr[MAC_ADDR_LEN]; + char data_Rssi; + UINT32 data_tx_Rate; + UINT32 data_rx_Rate; + UINT64 data_tx_Byte; + UINT64 data_rx_Byte; + UINT8 data_tx_Phymode; + UINT8 data_rx_Phymode; + UINT8 data_tx_mcs; + UINT8 data_rx_mcs; + UINT8 data_tx_bw; + UINT8 data_rx_bw; + UINT8 data_tx_sgi; + UINT8 data_rx_sgi; + UINT8 data_tx_stbc; + UINT8 data_rx_stbc; + UINT8 data_tx_ant; + UINT8 data_rx_ant; + UINT64 data_tx_packets; + UINT64 data_rx_packets; +}; + +/* CHANLOAD_STATUS_REQ */ +struct bnd_msg_chanload_status_req { + CHAR ucIfName[32]; + /* u8 band; */ + /* u8 Channel; */ +}; +/* CHANLOAD_STATUS_RSP */ +struct bnd_msg_chanload_status_rsp { + UINT8 ReturnCode; + UINT8 band; + UINT8 Channel; + /* TBD */ + UINT8 chanload; + UINT8 chan_busy_load; + UINT8 obss_load; + UINT8 edcca_load; + UINT8 myair_load; + UINT8 mytxair_load; + UINT8 myrxair_load; +}; + +/* INF_STATUS_QUERY */ +struct bnd_msg_inf_status_req { + CHAR ucIfName[32]; +}; + +struct bnd_msg_inf_status_rsp { + BOOLEAN bInfReady; + UINT8 Channel; + BOOLEAN bVHTCapable; + ULONG table_src_addr; + CHAR ucIfName[32]; + UINT8 nvram_support; + UINT8 nss; + UINT8 band; + UINT32 table_size; +}; + +/* BNDSTRG_ONOFF */ +struct bnd_msg_onoff { + UINT8 Band; + UINT8 Channel; + BOOLEAN OnOff; + UINT8 BndStrgMode; + CHAR ucIfName[32]; +}; + +/* set band steering paramater */ +struct bnd_msg_param { + UINT8 Band; + UINT8 Channel; + UINT8 len; + CHAR arg[64]; +}; + +struct bnd_msg_neighbor_report { + UCHAR Addr[MAC_ADDR_LEN]; + UINT8 Band; + UINT8 Channel; + CHAR NeighborRepInfo[64]; +}; + +/* SET_MNT_ADDR */ +struct bnd_msg_mnt_addr { + UCHAR Addr[MAC_ADDR_LEN]; +}; + +/* NVRAM_UPDATE */ +struct bnd_msg_nvram_entry_update { + UCHAR Addr[MAC_ADDR_LEN]; + BNDSTRG_NVRAM_CLIENT nvram_entry; +}; + +struct bnd_msg_reject_body { + UINT32 DaemonPid; +}; + +/*display type for list*/ +struct bnd_msg_display_entry_list { + UINT32 display_type; + UINT8 filer_band; + UINT8 channel; +}; + +struct bnd_msg_update_white_black_list { + CHAR ucIfName[32]; + UINT8 list_type; + UCHAR Addr[MAC_ADDR_LEN]; + BOOLEAN deladd; +}; + +struct bnd_msg_wnm_command { + UINT8 wnm_data[64]; +}; + +typedef struct _BNDSTRG_MSG { + UINT8 Action; + union { + struct bnd_msg_cli_event cli_event; + struct bnd_msg_cli_add cli_add; + struct bnd_msg_cli_del cli_del; + struct bnd_msg_cli_status_req cli_status_req; + struct bnd_msg_cli_status_rsp cli_status_rsp; + struct bnd_msg_chanload_status_req chanload_status_req; + struct bnd_msg_chanload_status_rsp chanload_status_rsp; + struct bnd_msg_inf_status_req inf_status_req; + struct bnd_msg_inf_status_rsp inf_status_rsp; + struct bnd_msg_onoff onoff; + struct bnd_msg_mnt_addr mnt_addr; + struct bnd_msg_nvram_entry_update entry_update; + struct bnd_msg_reject_body reject_body; + struct bnd_msg_display_entry_list display_type; + struct bnd_msg_heartbeat heartbeat; + struct bnd_msg_param bndstrg_param; + struct bnd_msg_update_white_black_list update_white_black_list; + struct bnd_msg_wnm_command wnm_cmd_data; + struct bnd_msg_neighbor_report Neighbor_Report; + } data; +} BNDSTRG_MSG, *PBNDSTRG_MSG; +#endif /* BAND_STEERING */ +#endif /* _BAND_STEERING_DEF_H_ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/bn.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/bn.h new file mode 100644 index 000000000..882252d3c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/bn.h @@ -0,0 +1,646 @@ +/* ==================================================================== + * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgment: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_BN_H +#define HEADER_BN_H + +#ifdef DOT11_SAE_OPENSSL_BN + +typedef struct bignum_ctx BN_CTX; +typedef struct bn_gencb_st BN_GENCB; +typedef struct bignum_st BIGNUM; +typedef struct bn_mont_ctx_st BN_MONT_CTX; +typedef struct bn_recp_ctx_st BN_RECP_CTX; + + + +#include "rtmp_type.h" +#include "rt_config.h" + +typedef UINT32 BN_ULONG; + +struct bignum_st { + BN_ULONG *d; /* Pointer to an array of 'BN_BITS2' bit chunks. */ + int top; /* Index of last used d +1. */ + /* The next are internal book keeping for bn_expand. */ + int dmax; /* Size of the d array. */ + int neg; /* one if the number is negative */ + int flags; +}; + +/* Used for montgomery multiplication */ +struct bn_mont_ctx_st { + int ri; /* number of bits in R */ + BIGNUM RR; /* used to convert to montgomery form */ + BIGNUM N; /* The modulus */ + BIGNUM Ni; /* R*(1/R mod N) - N*Ni = 1 (Ni is only stored for bignum algorithm) */ + BN_ULONG n0[2]; /* least significant word(s) of Ni; (type changed with 0.9.9, was "BN_ULONG n0;" before) */ + int flags; +}; + +/* + * Used for reciprocal division/mod functions It cannot be shared between + * threads + */ +struct bn_recp_ctx_st { + BIGNUM N; /* the divisor */ + BIGNUM Nr; /* the reciprocal */ + int num_bits; + int shift; + int flags; +}; + +/* Used for slow "generation" functions. */ +struct bn_gencb_st { + unsigned int ver; /* To handle binary (in)compatibility */ + void *arg; /* callback-specific data */ + union { + /* if (ver==1) - handles old style callbacks */ + void (*cb_1) (int, int, void *); + /* if (ver==2) - new callback style */ + int (*cb_2) (int, int, BN_GENCB *); + } cb; +}; + +/* How many bignums are in each "pool item"; */ +#define BN_CTX_POOL_SIZE 16 +/* The stack frame info is resizing, set a first-time expansion size; */ +#define BN_CTX_START_FRAMES 32 + +typedef struct bignum_pool_item { + /* The bignum values */ + BIGNUM vals[BN_CTX_POOL_SIZE]; + /* Linked-list admin */ + struct bignum_pool_item *prev, *next; +} BN_POOL_ITEM; + +typedef struct bignum_pool { + /* Linked-list admin */ + BN_POOL_ITEM *head; + BN_POOL_ITEM *curr; + BN_POOL_ITEM *tail; + /* Stack depth and allocation size */ + unsigned used; + unsigned size; +} BN_POOL; + +/* A wrapper to manage the "stack frames" */ +typedef struct bignum_ctx_stack { + /* Array of indexes into the bignum stack */ + unsigned int *indexes; + /* Number of stack frames, and the size of the allocated array */ + unsigned int depth; + unsigned int size; +} BN_STACK; + + + +/* The opaque BN_CTX type */ +struct bignum_ctx { + /* The bignum bundles */ + BN_POOL pool; + /* The "stack frames", if you will */ + BN_STACK stack; + /* The number of bignums currently assigned */ + unsigned int used; + /* Depth of stack overflow */ + int err_stack; + /* Block "gets" until an "end" (compatibility behaviour) */ + int too_many; + /* Flags. */ + int flags; +}; + + + +# define bn_pollute(a) +# define bn_check_top(a) +# define bn_fix_top(a) bn_correct_top(a) +# define bn_check_size(bn, bits) +# define bn_wcheck_size(bn, words) + +# define BNerr(f, r) + +#define BN_BYTES (4) +#define BN_MASK2 (~((BN_ULONG)0)) +#define BN_MASK2l (0xffff) +#define BN_MASK2h1 (0xffff8000L) +#define BN_MASK2h (0xffff0000L) +#define BN_BITS4 16 + + + +# define BN_BITS2 (BN_BYTES * 8) +# define BN_BITS (BN_BITS2 * 2) +# define BN_TBIT ((ULONG)1 << (BN_BITS2 - 1)) + +# define BN_FLG_MALLOCED 0x01 +# define BN_FLG_STATIC_DATA 0x02 + +/* + * avoid leaking exponent information through timing, + * BN_mod_exp_mont() will call BN_mod_exp_mont_consttime, + * BN_div() will call BN_div_no_branch, + * BN_mod_inverse() will call BN_mod_inverse_no_branch. + */ +# define BN_FLG_CONSTTIME 0x04 +# define BN_FLG_SECURE 0x08 + +# define BN_FLG_EXP_CONSTTIME BN_FLG_CONSTTIME +# define BN_FLG_FREE 0x8000 /* used for debugging */ + + +/* Values for |top| in BN_rand() */ +#define BN_RAND_TOP_ANY -1 +#define BN_RAND_TOP_ONE 0 +#define BN_RAND_TOP_TWO 1 + +/* Values for |bottom| in BN_rand() */ +#define BN_RAND_BOTTOM_ANY 0 +#define BN_RAND_BOTTOM_ODD 1 + +#define BN_prime_checks 0 /* default: select number of iterations based on the size of the number */ + +/* + * number of Miller-Rabin iterations for an error rate of less than 2^-80 for + * random 'b'-bit input, b >= 100 (taken from table 4.4 in the Handbook of + * Applied Cryptography [Menezes, van Oorschot, Vanstone; CRC Press 1996]; + * original paper: Damgaard, Landrock, Pomerance: Average case error + * estimates for the strong probable prime test. -- Math. Comp. 61 (1993) + * 177-194) + */ +# define BN_prime_checks_for_size(b) ((b) >= 1300 ? 2 : \ + (b) >= 850 ? 3 : \ + (b) >= 650 ? 4 : \ + (b) >= 550 ? 5 : \ + (b) >= 450 ? 6 : \ + (b) >= 400 ? 7 : \ + (b) >= 350 ? 8 : \ + (b) >= 300 ? 9 : \ + (b) >= 250 ? 12 : \ + (b) >= 200 ? 15 : \ + (b) >= 150 ? 18 : \ + /* b >= 100 */ 27) + +#define BN_num_bytes(a) ((BN_num_bits(a) + 7) / 8) + +#define BN_one(a) (BN_set_word((a), 1)) + +#define BN_zero(a) BN_zero_ex(a) + +/* BN_BLINDING flags */ +# define BN_BLINDING_NO_UPDATE 0x00000001 +# define BN_BLINDING_NO_RECREATE 0x00000002 + + +/*- + * BN_window_bits_for_exponent_size -- macro for sliding window mod_exp functions + * + * + * For window size 'w' (w >= 2) and a random 'b' bits exponent, + * the number of multiplications is a constant plus on average + * + * 2^(w-1) + (b-w)/(w+1); + * + * here 2^(w-1) is for precomputing the table (we actually need + * entries only for windows that have the lowest bit set), and + * (b-w)/(w+1) is an approximation for the expected number of + * w-bit windows, not counting the first one. + * + * Thus we should use + * + * w >= 6 if b > 671 + * w = 5 if 671 > b > 239 + * w = 4 if 239 > b > 79 + * w = 3 if 79 > b > 23 + * w <= 2 if 23 > b + * + * (with draws in between). Very small exponents are often selected + * with low Hamming weight, so we use w = 1 for b <= 23. + */ +# define BN_window_bits_for_exponent_size(b) \ + ((b) > 671 ? 6 : \ + (b) > 239 ? 5 : \ + (b) > 79 ? 4 : \ + (b) > 23 ? 3 : 1) + +/* + * BN_mod_exp_mont_conttime is based on the assumption that the L1 data cache + * line width of the target processor is at least the following value. + */ +#define MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH (64) +#define MOD_EXP_CTIME_MIN_CACHE_LINE_MASK (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - 1) + +/* + * Window sizes optimized for fixed window size modular exponentiation + * algorithm (BN_mod_exp_mont_consttime). To achieve the security goals of + * BN_mode_exp_mont_consttime, the maximum size of the window must not exceed + * log_2(MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH). Window size thresholds are + * defined for cache line sizes of 32 and 64, cache line sizes where + * log_2(32)=5 and log_2(64)=6 respectively. A window size of 7 should only be + * used on processors that have a 128 byte or greater cache line size. + */ +# if MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 64 + +# define BN_window_bits_for_ctime_exponent_size(b) \ + ((b) > 937 ? 6 : \ + (b) > 306 ? 5 : \ + (b) > 89 ? 4 : \ + (b) > 22 ? 3 : 1) +# define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE (6) + +# elif MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 32 + +# define BN_window_bits_for_ctime_exponent_size(b) \ + ((b) > 306 ? 5 : \ + (b) > 89 ? 4 : \ + (b) > 22 ? 3 : 1) +# define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE (5) + +# endif + + +void BN_set_flags(BIGNUM *b, int n); +int BN_get_flags(const BIGNUM *b, int n); +/* + * get a clone of a BIGNUM with changed flags, for *temporary* use only (the + * two BIGNUMs cannot be used in parallel!). Also only for *read only* use. The + * value |dest| should be a newly allocated BIGNUM obtained via BN_new() that + * has not been otherwise initialised or used. + */ +void BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags); + + +void BN_zero_ex(BIGNUM *a); +int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w); +int BN_is_zero(const BIGNUM *a); +int BN_is_one(const BIGNUM *a); +int BN_is_word(const BIGNUM *a, const BN_ULONG w); +int BN_is_odd(const BIGNUM *a); + +int BN_num_bits(const BIGNUM *a); +int BN_num_bits_word(BN_ULONG l); +int BN_security_bits(int L, int N); + +const BIGNUM *BN_value_one(void); + +BIGNUM *BN_new(void); +BIGNUM *BN_secure_new(void); +void BN_clear_free(BIGNUM *a); +BIGNUM *BN_dup(const BIGNUM *a); +BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b); +void BN_swap(BIGNUM *a, BIGNUM *b); +BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); +int BN_bn2bin(const BIGNUM *a, unsigned char *to); +int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen); +BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret); +int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen); +BIGNUM *bn_wexpand(BIGNUM *a, int words); +void bn_correct_top(BIGNUM *a); +int BN_set_word(BIGNUM *a, BN_ULONG w); + +int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + BN_MONT_CTX *mont, BN_CTX *ctx); +int BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx); +int BN_from_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx); + +BN_CTX *BN_CTX_new(void); +BN_CTX *BN_CTX_secure_new(void); +void BN_CTX_free(BN_CTX *c); +void BN_CTX_start(BN_CTX *ctx); +BIGNUM *BN_CTX_get(BN_CTX *ctx); +void BN_CTX_end(BN_CTX *ctx); +void BN_MONT_CTX_init(BN_MONT_CTX *ctx); +BN_MONT_CTX *BN_MONT_CTX_new(void); +int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx); +void BN_MONT_CTX_free(BN_MONT_CTX *mont); + +void BN_STACK_init(BN_STACK *); +void BN_STACK_finish(BN_STACK *); +int BN_STACK_push(BN_STACK *, unsigned int); +unsigned int BN_STACK_pop(BN_STACK *); +void BN_POOL_init(BN_POOL *); +void BN_POOL_finish(BN_POOL *); +BIGNUM *BN_POOL_get(BN_POOL *, int); +void BN_POOL_release(BN_POOL *, unsigned int); + +int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); +int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx); +void bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, int n, BN_ULONG *tmp); + +BIGNUM *BN_mod_inverse(BIGNUM *in, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx); + +int BN_lshift(BIGNUM *r, const BIGNUM *a, int n); +int BN_lshift1(BIGNUM *r, const BIGNUM *a); +int BN_rshift(BIGNUM *r, const BIGNUM *a, int n); +int BN_rshift1(BIGNUM *r, const BIGNUM *a); + +int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx); +int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx); +/* + * BN_mod_add variant that may be used if both a and b are non-negative and + * less than m + */ +int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m); +int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx); +/* + * BN_mod_sub variant that may be used if both a and b are non-negative and + * less than m + */ +int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + const BIGNUM *m); +/* slow but works */ +int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, + BN_CTX *ctx); +int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); +int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx); +/* + * BN_mod_lshift1 variant that may be used if a is non-negative and less than + * m + */ +int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m); +int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, + BN_CTX *ctx); +/* + * BN_mod_lshift variant that may be used if a is non-negative and less than + * m + */ +int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m); + +int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +/* unsigned add of b to a */ +int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +/* unsigned subtraction of b from a, a must be larger than b. */ +int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); +int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b); + +BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w); +BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w); +int BN_add_word(BIGNUM *a, BN_ULONG w); +int BN_sub_word(BIGNUM *a, BN_ULONG w); +int BN_mul_word(BIGNUM *a, BN_ULONG w); + +#define BN_mod(rem, m, d, ctx) BN_div(NULL, (rem), (m), (d), (ctx)) +int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, + BN_CTX *ctx); + + +int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx); + +int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); +int BN_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *in_mont); +int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1, const BIGNUM *p1, + const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m, + BN_CTX *ctx, BN_MONT_CTX *m_ctx); +int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); + +int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, + BN_RECP_CTX *recp, BN_CTX *ctx); + +int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx); + +int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y, + BN_RECP_CTX *recp, BN_CTX *ctx); +int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx); + +/** BN_set_negative sets sign of a BIGNUM + * \param b pointer to the BIGNUM object + * \param n 0 if the BIGNUM b should be positive and a value != 0 otherwise + */ +void BN_set_negative(BIGNUM *b, int n); + +/** BN_is_negative returns 1 if the BIGNUM is negative + * \param b pointer to the BIGNUM object + * \return 1 if a < 0 and 0 otherwise + */ +int BN_is_negative(const BIGNUM *b); + +int BN_cmp(const BIGNUM *a, const BIGNUM *b); +void BN_free(BIGNUM *a); +int BN_ucmp(const BIGNUM *a, const BIGNUM *b); + +int BN_rand(BIGNUM *rnd, int bits, int top, int bottom); +int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom); +int BN_rand_range(BIGNUM *rnd, const BIGNUM *range); +char *BN_bn2hex(const BIGNUM *a); + +BIGNUM *BN_mod_sqrt(BIGNUM *ret, + const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx); + +int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); + + +/* BEGIN ERROR CODES */ +/* + * The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +int ERR_load_BN_strings(void); + +/* Error codes for the BN functions. */ + +/* Function codes. */ +# define BN_F_BNRAND 127 +# define BN_F_BN_BLINDING_CONVERT_EX 100 +# define BN_F_BN_BLINDING_CREATE_PARAM 128 +# define BN_F_BN_BLINDING_INVERT_EX 101 +# define BN_F_BN_BLINDING_NEW 102 +# define BN_F_BN_BLINDING_UPDATE 103 +# define BN_F_BN_BN2DEC 104 +# define BN_F_BN_BN2HEX 105 +# define BN_F_BN_COMPUTE_WNAF 142 +# define BN_F_BN_CTX_GET 116 +# define BN_F_BN_CTX_NEW 106 +# define BN_F_BN_CTX_START 129 +# define BN_F_BN_DIV 107 +# define BN_F_BN_DIV_RECP 130 +# define BN_F_BN_EXP 123 +# define BN_F_BN_EXPAND_INTERNAL 120 +# define BN_F_BN_GENCB_NEW 143 +# define BN_F_BN_GENERATE_DSA_NONCE 140 +# define BN_F_BN_GENERATE_PRIME_EX 141 +# define BN_F_BN_GF2M_MOD 131 +# define BN_F_BN_GF2M_MOD_EXP 132 +# define BN_F_BN_GF2M_MOD_MUL 133 +# define BN_F_BN_GF2M_MOD_SOLVE_QUAD 134 +# define BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR 135 +# define BN_F_BN_GF2M_MOD_SQR 136 +# define BN_F_BN_GF2M_MOD_SQRT 137 +# define BN_F_BN_LSHIFT 145 +# define BN_F_BN_MOD_EXP2_MONT 118 +# define BN_F_BN_MOD_EXP_MONT 109 +# define BN_F_BN_MOD_EXP_MONT_CONSTTIME 124 +# define BN_F_BN_MOD_EXP_MONT_WORD 117 +# define BN_F_BN_MOD_EXP_RECP 125 +# define BN_F_BN_MOD_EXP_SIMPLE 126 +# define BN_F_BN_MOD_INVERSE 110 +# define BN_F_BN_MOD_INVERSE_NO_BRANCH 139 +# define BN_F_BN_MOD_LSHIFT_QUICK 119 +# define BN_F_BN_MOD_SQRT 121 +# define BN_F_BN_MPI2BN 112 +# define BN_F_BN_NEW 113 +# define BN_F_BN_RAND 114 +# define BN_F_BN_RAND_RANGE 122 +# define BN_F_BN_RSHIFT 146 +# define BN_F_BN_SET_WORDS 144 +# define BN_F_BN_USUB 115 + +/* Reason codes. */ +# define BN_R_ARG2_LT_ARG3 100 +# define BN_R_BAD_RECIPROCAL 101 +# define BN_R_BIGNUM_TOO_LONG 114 +# define BN_R_BITS_TOO_SMALL 118 +# define BN_R_CALLED_WITH_EVEN_MODULUS 102 +# define BN_R_DIV_BY_ZERO 103 +# define BN_R_ENCODING_ERROR 104 +# define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA 105 +# define BN_R_INPUT_NOT_REDUCED 110 +# define BN_R_INVALID_LENGTH 106 +# define BN_R_INVALID_RANGE 115 +# define BN_R_INVALID_SHIFT 119 +# define BN_R_NOT_A_SQUARE 111 +# define BN_R_NOT_INITIALIZED 107 +# define BN_R_NO_INVERSE 108 +# define BN_R_NO_SOLUTION 116 +# define BN_R_PRIVATE_KEY_TOO_LARGE 117 +# define BN_R_P_IS_NOT_PRIME 112 +# define BN_R_TOO_MANY_ITERATIONS 113 +# define BN_R_TOO_MANY_TEMPORARY_VARIABLES 109 + +/* fatal error */ +# define ERR_R_FATAL 64 +# define ERR_R_MALLOC_FAILURE (1|ERR_R_FATAL) +# define ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED (2|ERR_R_FATAL) +# define ERR_R_PASSED_NULL_PARAMETER (3|ERR_R_FATAL) +# define ERR_R_INTERNAL_ERROR (4|ERR_R_FATAL) +# define ERR_R_DISABLED (5|ERR_R_FATAL) +# define ERR_R_INIT_FAIL (6|ERR_R_FATAL) +# define ERR_R_PASSED_INVALID_ARGUMENT (7) + +#endif + +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/br_ftph.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/br_ftph.h new file mode 100644 index 000000000..7810cf134 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/br_ftph.h @@ -0,0 +1,81 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + + Abstract: + + All Bridge Fast Path Related Structure & Definition. + +***************************************************************************/ + +#ifndef __BR_FTPH_H__ +#define __BR_FTPH_H__ + +/* Public function prototype */ +/* +======================================================================== +Routine Description: + Init bridge fast path module. + +Arguments: + None + +Return Value: + None + +Note: + Used in module init. +======================================================================== +*/ +VOID BG_FTPH_Init(VOID); + +/* +======================================================================== +Routine Description: + Remove bridge fast path module. + +Arguments: + None + +Return Value: + None + +Note: + Used in module remove. +======================================================================== +*/ +VOID BG_FTPH_Remove(VOID); + +/* +======================================================================== +Routine Description: + Forward the received packet. + +Arguments: + pPacket - the received packet + +Return Value: + None + +Note: +======================================================================== +*/ +UINT32 BG_FTPH_PacketFromApHandle( + IN PNDIS_PACKET pPacket); + +#endif /* __BR_FTPH_H__ */ + +/* End of br_ftph.h */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cfg80211.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cfg80211.h new file mode 100644 index 000000000..8b16f43c2 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cfg80211.h @@ -0,0 +1,28 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + + Abstract: + + All MAC80211/CFG80211 Related Structure & Definition. + +***************************************************************************/ +#ifndef __CFG80211_H__ +#define __CFG80211_H__ + + +#endif /* __CFG80211_H__ */ + +/* End of cfg80211.h */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cfg80211_cmm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cfg80211_cmm.h new file mode 100644 index 000000000..89cc63d2a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cfg80211_cmm.h @@ -0,0 +1,30 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2013, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + + Abstract: + + All CFG80211 Function Prototype. + +***************************************************************************/ + + +#ifndef __CFG80211CMM_H__ +#define __CFG80211CMM_H__ + + +#endif /* __CFG80211CMM_H__ */ + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cfg80211extr.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cfg80211extr.h new file mode 100644 index 000000000..96c166987 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cfg80211extr.h @@ -0,0 +1,32 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2013, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + + Abstract: + + All CFG80211 Function Prototype. + +***************************************************************************/ + +#ifndef __CFG80211EXTR_H__ +#define __CFG80211EXTR_H__ + + +VOID CFG80211_JoinIBSS( + IN VOID *pAdCB, + IN UCHAR *pBSSID); + +#endif /* __CFG80211EXTR_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/chip_id.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/chip_id.h new file mode 100644 index 000000000..2ace72785 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/chip_id.h @@ -0,0 +1,85 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + chip_id.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __CHIP_ID_H__ +#define __CHIP_ID_H__ + + +#define NIC_PCI_VENDOR_ID 0x1814 +#define MTK_PCI_VENDOR_ID 0x14C3 + +#define NIC2860_PCI_DEVICE_ID 0x0601 +#define NIC2860_PCIe_DEVICE_ID 0x0681 +#define NIC2760_PCI_DEVICE_ID 0x0701 /* 1T/2R Cardbus ??? */ +#define NIC2790_PCIe_DEVICE_ID 0x0781 /* 1T/2R miniCard */ + +#define VEN_AWT_PCIe_DEVICE_ID 0x1059 +#define DLINK_PCI_VENDOR_ID 0x1186 +#define VEN_AWT_PCI_VENDOR_ID 0x1A3B + +#define EDIMAX_PCI_VENDOR_ID 0x1432 + +#define NIC3090_PCIe_DEVICE_ID 0x3090 /* 1T/1R miniCard */ +#define NIC3091_PCIe_DEVICE_ID 0x3091 /* 1T/2R miniCard */ +#define NIC3092_PCIe_DEVICE_ID 0x3092 /* 2T/2R miniCard */ +#define NIC3390_PCIe_DEVICE_ID 0x3390 /* 1T/1R miniCard */ + +#define NIC3062_PCI_DEVICE_ID 0x3062 /* 2T/2R miniCard */ +#define NIC3562_PCI_DEVICE_ID 0x3562 /* 2T/2R miniCard */ +#define NIC3060_PCI_DEVICE_ID 0x3060 /* 1T/1R miniCard */ + +#define NIC3592_PCIe_DEVICE_ID 0x3592 /* 2T/2R miniCard */ + +#define NIC3593_PCI_OR_PCIe_DEVICE_ID 0x3593 + +#define NIC5390_PCIe_DEVICE_ID 0x5390 +#define NIC539F_PCIe_DEVICE_ID 0x539F +#define NIC5392_PCIe_DEVICE_ID 0x5392 +#define NIC5360_PCI_DEVICE_ID 0x5360 +#define NIC5362_PCI_DEVICE_ID 0x5362 + +#define NIC5592_PCIe_DEVICE_ID 0x5592 + +#define NIC3290_PCIe_DEVICE_ID 0x3290 + +#define NIC6590_PCIe_DEVICE_ID 0x6590 +#define NIC7610_PCIe_DEVICE_ID 0x7610 +#define NIC7630_PCIe_DEVICE_ID 0x7630 +#define NIC7650_PCIe_DEVICE_ID 0x7650 +#define NIC7612_PCIe_DEVICE_ID 0x7612 +#define NIC7632_PCIe_DEVICE_ID 0x7632 +#define NIC7662_PCIe_DEVICE_ID 0x7662 + +#ifdef CONFIG_FPGA_MODE +#define NIC6390_PCIe_DEVICE_ID 0x6390 +#endif /* CONFIG_FPGA_MODE */ + +#define NIC7601_PCIe_DEVICE_ID 0x7601 + +#define NIC8592_PCIe_DEVICE_ID 0x8592 + +#define NIC7603_PCIe_DEVICE_ID 0x7603 +#endif /* __CHIP_ID_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/mt7603.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/mt7603.h new file mode 100644 index 000000000..6f8a81aec --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/mt7603.h @@ -0,0 +1,38 @@ +#ifndef __MT7603_H__ +#define __MT7603_H__ + +#include "../mcu/andes_core.h" +//#include "../mcu/andes_rlt.h" +#include "../phy/mt_rf.h" + +#ifdef RTMP_FLASH_SUPPORT +#ifdef RTMP_MAC_PCI +#define EEPROM_DEFAULT_7603_FILE_PATH "/etc_ro/wlan/MT7603E.bin" +#endif /* RTMP_MAC_PCI */ +#endif /* RTMP_FLASH_SUPPORT */ + +struct _RTMP_ADAPTER; + +#define MAX_RF_ID 127 +#define MAC_RF_BANK 7 + +void mt7603_init(struct _RTMP_ADAPTER *pAd); +void mt7603_get_tx_pwr_per_rate(struct _RTMP_ADAPTER *pAd); +void mt7603_get_tx_pwr_info(struct _RTMP_ADAPTER *pAd); +void mt7603_antenna_sel_ctl(struct _RTMP_ADAPTER *pAd); +int mt7603_read_chl_pwr(struct _RTMP_ADAPTER *pAd); +void mt7603_pwrOn(struct _RTMP_ADAPTER *pAd); +void mt7603_calibration(struct _RTMP_ADAPTER *pAd, UCHAR channel); +void mt7603_tssi_compensation(struct _RTMP_ADAPTER *pAd, UCHAR channel); +void mt7603_set_ed_cca(struct _RTMP_ADAPTER *pAd, BOOLEAN enable); + +#ifdef LED_CONTROL_SUPPORT +INT Set_MT7603LED_Proc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_MT7603LED_Enhance_Proc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_MT7603LED_Behavor_Proc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* LED_CONTROL_SUPPORT */ + + + +#endif // __MT7603_H__ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/mt7628.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/mt7628.h new file mode 100644 index 000000000..4aae28682 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/mt7628.h @@ -0,0 +1,33 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + mt7628.h + + Abstract: + 2*2 Wireless Chip SoC + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Carter.Chen 20130912 Initial version + */ + +#ifndef __MT7628_H__ +#define __MT7628_H__ + +#endif /*__MT7628_H__ */ +/* End of mt7628.h */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/mt7636.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/mt7636.h new file mode 100644 index 000000000..84b8d3341 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/mt7636.h @@ -0,0 +1,22 @@ +#ifndef __MT7636_H__ +#define __MT7636_H__ + +#include "../mcu/andes_core.h" +#include "../phy/mt_rf.h" + +struct _RTMP_ADAPTER; + +#define MAX_RF_ID 127 +#define MAC_RF_BANK 7 + +void mt7636_init(struct _RTMP_ADAPTER *pAd); +void mt7636_get_tx_pwr_per_rate(struct _RTMP_ADAPTER *pAd); +void mt7636_get_tx_pwr_info(struct _RTMP_ADAPTER *pAd); +void mt7636_antenna_sel_ctl(struct _RTMP_ADAPTER *pAd); +int mt7636_read_chl_pwr(struct _RTMP_ADAPTER *pAd); +void mt7636_pwrOn(struct _RTMP_ADAPTER *pAd); +void mt7636_calibration(struct _RTMP_ADAPTER *pAd, UCHAR channel); +void mt7636_tssi_compensation(struct _RTMP_ADAPTER *pAd, UCHAR channel); + +#endif // __MT7636_H__ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/mt76x0.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/mt76x0.h new file mode 100644 index 000000000..6a1012937 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/mt76x0.h @@ -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: + mt76x0.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __MT76X0_H__ +#define __MT76X0_H__ + +#include "../mcu/andes_core.h" +#include "../mcu/andes_rlt.h" + +struct _RTMP_ADAPTER; + +/* + R37 + R36 + R35 + R34 + R33 + R32<7:5> + R32<4:0> pll_den: (Denomina - 8) + R31<7:5> + R31<4:0> pll_k(Nominator) + R30<7> sdm_reset_n + R30<6:2> sdmmash_prbs,sin + R30<1> sdm_bp + R30<0> R29<7:0> (hex) pll_n + R28<7:6> isi_iso + R28<5:4> pfd_dly + R28<3:2> clksel option + R28<1:0> R27<7:0> R26<7:0> (hex) sdm_k + R24<1:0> xo_div +*/ +typedef struct _MT76x0_FREQ_ITEM { + UINT8 Channel; + UINT32 Band; + UINT8 pllR37; + UINT8 pllR36; + UINT8 pllR35; + UINT8 pllR34; + UINT8 pllR33; + UINT8 pllR32_b7b5; + UINT8 pllR32_b4b0; /* PLL_DEN */ + UINT8 pllR31_b7b5; + UINT8 pllR31_b4b0; /* PLL_K */ + UINT8 pllR30_b7; /* sdm_reset_n */ + UINT8 pllR30_b6b2; /* sdmmash_prbs,sin */ + UINT8 pllR30_b1; /* sdm_bp */ + UINT16 pll_n; /* R30<0>, R29<7:0> (hex) */ + UINT8 pllR28_b7b6; /* isi,iso */ + UINT8 pllR28_b5b4; /* pfd_dly */ + UINT8 pllR28_b3b2; /* clksel option */ + UINT32 Pll_sdm_k; /* R28<1:0>, R27<7:0>, R26<7:0> (hex) SDM_k */ + UINT8 pllR24_b1b0; /* xo_div */ +} MT76x0_FREQ_ITEM; + +#define RF_G_BAND 0x0100 +#define RF_A_BAND 0x0200 +#define RF_A_BAND_LB 0x0400 +#define RF_A_BAND_MB 0x0800 +#define RF_A_BAND_HB 0x1000 +#define RF_A_BAND_11J 0x2000 +typedef struct _RT6590_RF_SWITCH_ITEM { + UCHAR Bank; + UCHAR Register; + UINT32 BwBand; /* (BW_20, BW_40, BW_80) | (G_Band, A_Band_LB, A_Band_MB, A_Band_HB) */ + UCHAR Value; +} MT76x0_RF_SWITCH_ITEM, *PMT76x0_RF_SWITCH_ITEM; + +typedef struct _MT76x0_BBP_Table { + UINT32 BwBand; /* (BW_20, BW_40, BW_80) | (G_Band, A_Band_LB, A_Band_MB, A_Band_HB) */ + RTMP_REG_PAIR RegDate; +} MT76x0_BBP_Table, *PMT76x0_BBP_Table; + +typedef struct _MT76x0_RATE_PWR_ITEM { + CHAR MCS_Power; + UCHAR RF_PA_Mode; +} MT76x0_RATE_PWR_ITEM, *PMT76x0_RATE_PWR_ITEM; + +typedef struct _MT76x0_RATE_PWR_TABLE { + MT76x0_RATE_PWR_ITEM CCK[4]; + MT76x0_RATE_PWR_ITEM OFDM[8]; + MT76x0_RATE_PWR_ITEM HT[8]; + MT76x0_RATE_PWR_ITEM VHT[10]; + MT76x0_RATE_PWR_ITEM STBC[8]; + MT76x0_RATE_PWR_ITEM MCS32; +} MT76x0_RATE_PWR_Table, *PMT76x0_RATE_PWR_Table; + +VOID MT76x0_Init(struct _RTMP_ADAPTER *pAd); +INT MT76x0_ReadChannelPwr(struct _RTMP_ADAPTER *pAd); +INT MT76x0_DisableTxRx( + struct _RTMP_ADAPTER *pAd, + UCHAR Level); + +#ifdef DBG +VOID MT76x0_ShowDmaIndexCupIndex( + struct _RTMP_ADAPTER *pAd); +#endif /* DBG */ + +void mt76x0_read_per_rate_tx_pwr(struct _RTMP_ADAPTER *pAd); + +void mt76x0_antenna_sel_ctl(struct _RTMP_ADAPTER *ad); + +void mt76x0_vco_calibration(struct _RTMP_ADAPTER *ad, UINT8 channel); + +void mt76x0_calibration( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR channel, + IN BOOLEAN bPowerOn, + IN BOOLEAN bFullCal, + IN BOOLEAN bSaveCal); + +void mt76x0_temp_sensor(struct _RTMP_ADAPTER *ad); + +void mt76x0_temp_trigger_cal(struct _RTMP_ADAPTER *ad); + +#ifdef DFS_SUPPORT +VOID MT76x0_DFS_CR_Init( + IN struct _RTMP_ADAPTER *pAd); +#endif /* DFS_SUPPORT */ + +#ifdef RTMP_FLASH_SUPPORT +VOID MT76x0_ReadFlashAndInitAsic( + IN struct _RTMP_ADAPTER *pAd); +#endif /* RTMP_FLASH_SUPPORT */ + +#ifdef RTMP_MAC_PCI +VOID MT76x0_InitPCIeLinkCtrlValue( + IN struct _RTMP_ADAPTER *pAd); + +VOID MT76x0_PciMlmeRadioOFF( + IN struct _RTMP_ADAPTER *pAd); + +VOID MT76x0_PciMlmeRadioOn( + IN struct _RTMP_ADAPTER *pAd); +#endif /* RTMP_MAC_PCI */ + +INT Set_AntennaSelect_Proc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +VOID MT76x0_MakeUpRatePwrTable( + IN struct _RTMP_ADAPTER *pAd); + +VOID mt76x0_asic_adjust_tx_power( + IN struct _RTMP_ADAPTER *pAd); + +#ifdef RTMP_TEMPERATURE_COMPENSATION +void mt76x0_temp_tx_alc(struct _RTMP_ADAPTER *pAd); +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + +#ifdef MT76x0_TSSI_CAL_COMPENSATION +VOID MT76x0_TSSI_DC_Calibration( + IN struct _RTMP_ADAPTER *pAd); + +VOID MT76x0_IntTxAlcProcess( + IN struct _RTMP_ADAPTER *pAd); +#endif /* MT76x0_TSSI_CAL_COMPENSATION */ + +#ifdef SINGLE_SKU_V2 +UCHAR MT76x0_GetSkuChannelBasePwr( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR channel); + +UCHAR MT76x0_UpdateSkuPwr( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR channel); +#endif /* SINGLE_SKU_V2 */ + +void mt76x0_read_tx_alc_info_from_eeprom(struct _RTMP_ADAPTER *pAd); + +void mt76x0_adjust_per_rate_pwr(struct _RTMP_ADAPTER *ad); + +#endif /* __MT76x0_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/rt65xx.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/rt65xx.h new file mode 100644 index 000000000..163534f6a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/rt65xx.h @@ -0,0 +1,72 @@ +/* + *************************************************************************** + * MediaTek Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 1997-2012, MediaTek, Inc. + * + * All rights reserved. MediaTek source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of MediaTek. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of MediaTek Technology, Inc. is obtained. + *************************************************************************** + +*/ + +#ifndef __MT65XX_H__ +#define __MT65XX_H__ + + + +struct _RTMP_ADAPTER; + +/* b'00: 2.4G+5G external PA, b'01: 5G external PA, b'10: 2.4G external PA, b'11: Internal PA */ +#define EXT_PA_2G_5G 0x0 +#define EXT_PA_5G_ONLY 0x1 +#define EXT_PA_2G_ONLY 0x2 + +#define INT_PA_2G_5G 0x3 +#define INT_PA_5G 0x2 +#define INT_PA_2G 0x1 + +#define MAX_CHECK_COUNT 200 + + +/* + EEPROM format +*/ + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_NIC_CINFIG0_STRUC { + struct { + USHORT Rsv:6; + USHORT PAType:2; /* 00: 2.4G+5G external PA, 01: 5G external PA, 10: 2.4G external PA, 11: Internal PA */ + USHORT TxPath:4; /* 1: 1T, 2: 2T, 3: 3T */ + USHORT RxPath:4; /* 1: 1R, 2: 2R, 3: 3R */ + } field; + USHORT word; +} EEPROM_NIC_CONFIG0_STRUC, *PEEPROM_NIC_CONFIG0_STRUC; +#else +typedef union _EEPROM_NIC_CINFIG0_STRUC { + struct { + USHORT RxPath:4; /* 1: 1R, 2: 2R, 3: 3R */ + USHORT TxPath:4; /* 1: 1T, 2: 2T, 3: 3T */ + USHORT PAType:2; /* 00: 2.4G+5G external PA, 01: 5G external PA, 10: 2.4G external PA, 11: Internal PA */ + USHORT Rsv:6; + } field; + USHORT word; +} EEPROM_NIC_CONFIG0_STRUC, *PEEPROM_NIC_CONFIG0_STRUC; +#endif + +VOID RT65xxDisableTxRx(struct _RTMP_ADAPTER *pAd, UCHAR Level); +void MT76xx_PciMlmeRadioOFF(struct _RTMP_ADAPTER *pAd); +void MT76xx_PciMlmeRadioOn(struct _RTMP_ADAPTER *pAd); +VOID dump_bw_info(struct _RTMP_ADAPTER *pAd); +VOID dump_pwr_info(struct _RTMP_ADAPTER *pAd); + +#endif /* __MT65XX_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/rt8592.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/rt8592.h new file mode 100644 index 000000000..0833604a8 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chip/rt8592.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: + rt8592.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RT8592_H__ +#define __RT8592_H__ + +struct _RTMP_ADAPTER; + + +/* + * Frequency plan item for RT85592 + * N: R9[4], R8[7:0] + * K: R7[7], R9[3:0] + * mod: R9[7:5], R11[3:2] (eg. mod=8 => 0x0, mod=10 => 0x2) + * R: R11[1:0] (eg. R=1 => 0x0, R=3 => 0x2) + */ +typedef struct _RT8592_FREQ_ITEM { + UINT8 Channel; + UINT16 N; + UINT8 K; + UINT8 mod; + UINT8 R; +} RT8592_FREQ_ITEM; + + + +#endif /* __RT8592_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chlist.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chlist.h new file mode 100644 index 000000000..2c954a75a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/chlist.h @@ -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-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + chlist.c + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __CHLIST_H__ +#define __CHLIST_H__ + +#include "rtmp_type.h" +#include "rtmp_def.h" + + +typedef struct _CH_DESC { + UCHAR FirstChannel; + UCHAR NumOfCh; + UCHAR ChannelProp; +}CH_DESC, *PCH_DESC; + +typedef struct _COUNTRY_REGION_CH_DESC { + UCHAR RegionIndex; + PCH_DESC pChDesc; +}COUNTRY_REGION_CH_DESC, *PCOUNTRY_REGION_CH_DESC; + +#ifdef EXT_BUILD_CHANNEL_LIST +#define ODOR 0 +#define IDOR 1 +#define BOTH 2 + +typedef struct _CH_DESP { + UCHAR FirstChannel; + UCHAR NumOfCh; + CHAR MaxTxPwr; /* dBm */ + UCHAR Geography; /* 0:out door, 1:in door, 2:both */ + BOOLEAN DfsReq; /* Dfs require, 0: No, 1: yes. */ +} CH_DESP, *PCH_DESP; + +typedef struct _CH_REGION { + UCHAR CountReg[3]; + UCHAR DfsType; /* 0: CE, 1: FCC, 2: JAP, 3:JAP_W53, JAP_W56 */ + CH_DESP *pChDesp; + BOOLEAN edcca_on; +} CH_REGION, *PCH_REGION; + +extern CH_REGION ChRegion[]; +#endif /* EXT_BUILD_CHANNEL_LIST */ + +typedef struct _COUNTRY_PROP { + UCHAR CountReg[3]; + UCHAR DfsType; /* 0: CE, 1: FCC, 2: JAP, 3:JAP_W53, JAP_W56 */ + BOOLEAN edcca_on; +} COUNTRY_PROP, *PCOUNTRY_PROP; + +#ifdef SINGLE_SKU_V2 +// TODO: shiang-usw, integrate these data structures to a single one! +#define SINGLE_SKU_TABLE_LENGTH (SINGLE_SKU_TABLE_CCK_LENGTH+SINGLE_SKU_TABLE_OFDM_LENGTH+(SINGLE_SKU_TABLE_HT_LENGTH*2)+SINGLE_SKU_TABLE_VHT_LENGTH) + +#define SINGLE_SKU_TABLE_CCK_LENGTH 4 +#define SINGLE_SKU_TABLE_OFDM_LENGTH 8 +#define SINGLE_SKU_TABLE_HT_LENGTH 16 +#define SINGLE_SKU_TABLE_VHT_LENGTH 10 /* VHT80 MCS 0 ~ 9 */ + +// TODO: shiang-usw, need to re-organize these for MT7610/MT7601/MT7620!! +typedef struct _CH_POWER_{ + DL_LIST List; + UCHAR StartChannel; + UCHAR num; + UCHAR *Channel; + UCHAR PwrCCK[SINGLE_SKU_TABLE_CCK_LENGTH]; + UCHAR PwrOFDM[SINGLE_SKU_TABLE_OFDM_LENGTH]; + UCHAR PwrHT20[SINGLE_SKU_TABLE_HT_LENGTH]; + UCHAR PwrHT40[SINGLE_SKU_TABLE_HT_LENGTH]; + UCHAR PwrVHT80[SINGLE_SKU_TABLE_VHT_LENGTH]; +}CH_POWER; +#endif /* SINGLE_SKU_V2 */ + +typedef struct _CH_FREQ_MAP_{ + UINT16 channel; + UINT16 freqKHz; +}CH_FREQ_MAP; + +extern CH_FREQ_MAP CH_HZ_ID_MAP[]; +extern int CH_HZ_ID_MAP_NUM; + + +#define MAP_CHANNEL_ID_TO_KHZ(_ch, _khz) \ + RTMP_MapChannelID2KHZ(_ch, (UINT32 *)&(_khz)) +#define MAP_KHZ_TO_CHANNEL_ID(_khz, _ch) \ + RTMP_MapKHZ2ChannelID(_khz, (INT *)&(_ch)) + +/* Check if it is Japan W53(ch52,56,60,64) channel. */ +#define JapanChannelCheck(_ch) ((_ch == 52) || (_ch == 56) || (_ch == 60) || (_ch == 64)) + +BOOLEAN GetEDCCASupport( + IN PRTMP_ADAPTER pAd); + +#if defined(EXT_BUILD_CHANNEL_LIST) +PCH_REGION GetChRegion(IN PUCHAR CntryCode); +#else +PCOUNTRY_PROP GetCountryProp(IN PUCHAR CntryCode); +#endif + +#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(RTMP_ADAPTER *pAd); +UCHAR N_SetCenCh(RTMP_ADAPTER *pAd, UCHAR channel); +BOOLEAN N_ChannelGroupCheck(RTMP_ADAPTER *pAd, 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/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/client_wds.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/client_wds.h new file mode 100644 index 000000000..1b50d70ff --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/client_wds.h @@ -0,0 +1,57 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + 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); + + +UCHAR *CliWds_ProxyLookup(RTMP_ADAPTER *pAd, UCHAR *pMac); + + +VOID CliWds_ProxyTabUpdate( + IN PRTMP_ADAPTER pAd, + IN SHORT Aid, + IN PUCHAR pMac); + + +VOID CliWds_ProxyTabMaintain( + IN PRTMP_ADAPTER pAd); + +#endif /* __CLIENT_WDS_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/client_wds_cmm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/client_wds_cmm.h new file mode 100644 index 000000000..5043b1ae3 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/client_wds_cmm.h @@ -0,0 +1,46 @@ +/* + *************************************************************************** + * 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 + + +#define CLI_WDS_ENTRY_AGEOUT 5000 /* seconds */ + +#define CLIWDS_POOL_SIZE 128 +#define CLIWDS_HASH_TAB_SIZE 64 /* the legth of hash table must be power of 2. */ +typedef struct _CLIWDS_PROXY_ENTRY { + struct _CLIWDS_PROXY_ENTRY * pNext; + ULONG LastRefTime; + SHORT Aid; + UCHAR Addr[MAC_ADDR_LEN]; +} CLIWDS_PROXY_ENTRY, *PCLIWDS_PROXY_ENTRY; + +#endif /* CLIENT_WDS */ + +#endif /* __CLIENT_WDS_CMM_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cmm_asic_mt.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cmm_asic_mt.h new file mode 100644 index 000000000..756ac49c6 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cmm_asic_mt.h @@ -0,0 +1,26 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of MediaTek. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + cmm_asic_mt.h +*/ + +#ifndef __CMM_ASIC_MT_H__ +#define __CMM_ASIC_MT_H__ + +VOID MTPciPollTxRxEmpty(struct _RTMP_ADAPTER *pAd); +VOID MTPciMlmeRadioOff(struct _RTMP_ADAPTER *pAd); +VOID MTPciMlmeRadioOn(struct _RTMP_ADAPTER *pAd); +VOID MTUsbPollTxRxEmpty(struct _RTMP_ADAPTER *pAd); +VOID MTUsbMlmeRadioOff(struct _RTMP_ADAPTER *pAd); +VOID MTUsbMlmeRadioOn(struct _RTMP_ADAPTER *pAd); +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_aes.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_aes.h new file mode 100644 index 000000000..ab763ceb2 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_aes.h @@ -0,0 +1,176 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + Module Name: + AES + + Abstract: + RFC 3394: Advanced Encryption Standard (AES) Key Wrap Algorithm + RFC 3601: Counter with CBC-MAC (CCM) + RFC 4493: The AES-CMAC Algorithm + FIPS PUBS 197: ADVANCED ENCRYPTION STANDARD (AES) + NIST 800-38A: Recommendation for Block Cipher Modes of Operation + NIST 800-38C: The CCM Mode for Authentication and Confidentiality + + Revision History: + Who When What + -------- ---------- ------------------------------------------ + Eddy 2009/05/19 Create AES-Key Wrap + Eddy 2009/04/20 Create AES-CMAC, AES-CCM + Eddy 2009/01/19 Create AES-128, AES-192, AES-256, AES-CBC +***************************************************************************/ + +#ifndef __CRYPT_AES_H__ +#define __CRYPT_AES_H__ + +#include "rt_config.h" + + +/* AES definition & structure */ +#define AES_STATE_ROWS 4 /* Block size: 4*4*8 = 128 bits */ +#define AES_STATE_COLUMNS 4 +#define AES_BLOCK_SIZES AES_STATE_ROWS*AES_STATE_COLUMNS +#define AES_KEY_ROWS 4 +#define AES_KEY_COLUMNS 8 /*Key length: 4*{4,6,8}*8 = 128, 192, 256 bits */ +#define AES_KEY128_LENGTH 16 +#define AES_KEY192_LENGTH 24 +#define AES_KEY256_LENGTH 32 +#define AES_CBC_IV_LENGTH 16 + +typedef struct { + UINT8 State[AES_STATE_ROWS][AES_STATE_COLUMNS]; + UINT8 KeyWordExpansion[AES_KEY_ROWS][AES_KEY_ROWS*((AES_KEY256_LENGTH >> 2) + 6 + 1)]; +} AES_CTX_STRUC, *PAES_CTX_STRUC; + + +/* AES operations */ +VOID RT_AES_KeyExpansion ( + IN UINT8 Key[], + IN UINT KeyLength, + INOUT AES_CTX_STRUC *paes_ctx); + +VOID RT_AES_Encrypt ( + IN UINT8 PlainBlock[], + IN UINT PlainBlockSize, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 CipherBlock[], + INOUT UINT *CipherBlockSize); + +VOID RT_AES_Decrypt ( + IN UINT8 CipherBlock[], + IN UINT CipherBlockSize, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 PlainBlock[], + INOUT UINT *PlainBlockSize); + +/* AES Counter with CBC-MAC operations */ +VOID AES_CCM_MAC ( + IN UINT8 Payload[], + IN UINT PayloadLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 Nonce[], + IN UINT NonceLength, + IN UINT8 AAD[], + IN UINT AADLength, + IN UINT MACLength, + OUT UINT8 MACText[]); + +INT AES_CCM_Encrypt ( + IN UINT8 PlainText[], + IN UINT PlainTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 Nonce[], + IN UINT NonceLength, + IN UINT8 AAD[], + IN UINT AADLength, + IN UINT MACLength, + OUT UINT8 CipherText[], + INOUT UINT *CipherTextLength); + +INT AES_CCM_Decrypt ( + IN UINT8 CipherText[], + IN UINT CipherTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 Nonce[], + IN UINT NonceLength, + IN UINT8 AAD[], + IN UINT AADLength, + IN UINT MACLength, + OUT UINT8 PlainText[], + INOUT UINT *PlainTextLength); + +/* AES-CMAC operations */ +VOID AES_CMAC_GenerateSubKey ( + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 SubKey1[], + OUT UINT8 SubKey2[]); + +VOID AES_CMAC ( + IN UINT8 PlainText[], + IN UINT PlainTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 MACText[], + INOUT UINT *MACTextLength); + + + +/* AES-CBC operations */ +VOID AES_CBC_Encrypt ( + IN UINT8 PlainText[], + IN UINT PlainTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 IV[], + IN UINT IVLength, + OUT UINT8 CipherText[], + INOUT UINT *CipherTextLength); + +VOID AES_CBC_Decrypt ( + IN UINT8 CipherText[], + IN UINT CipherTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + IN UINT8 IV[], + IN UINT IVLength, + OUT UINT8 PlainText[], + INOUT UINT *PlainTextLength); + +/* AES key wrap operations */ +INT AES_Key_Wrap ( + IN UINT8 PlainText[], + IN UINT PlainTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 CipherText[], + OUT UINT *CipherTextLength); + +INT AES_Key_Unwrap ( + IN UINT8 CipherText[], + IN UINT CipherTextLength, + IN UINT8 Key[], + IN UINT KeyLength, + OUT UINT8 PlainText [], + OUT UINT *PlainTextLength); + + +#endif /* __CRYPT_AES_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_arc4.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_arc4.h new file mode 100644 index 000000000..63d87ce35 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_arc4.h @@ -0,0 +1,57 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + Module Name: + RC4 + + Abstract: + + Revision History: + Who When What + -------- ---------- ------------------------------------------ + Eddy 2009/05/13 ARC4 +***************************************************************************/ + +#ifndef __CRYPT_ARC4_H__ +#define __CRYPT_ARC4_H__ + +#include "rt_config.h" + +/* ARC4 definition & structure */ +#define ARC4_KEY_BLOCK_SIZE 256 + +typedef struct { + UINT BlockIndex1; + UINT BlockIndex2; + UINT8 KeyBlock[256]; +} ARC4_CTX_STRUC, *PARC4_CTX_STRUC; + +/* ARC4 operations */ +VOID ARC4_INIT( + IN ARC4_CTX_STRUC * pARC4_CTX, + IN PUCHAR pKey, + IN UINT KeyLength); + +VOID ARC4_Compute( + IN ARC4_CTX_STRUC * pARC4_CTX, + IN UINT8 InputBlock[], + IN UINT InputBlockSize, + OUT UINT8 OutputBlock[]); + +VOID ARC4_Discard_KeyLength( + IN ARC4_CTX_STRUC * pARC4_CTX, + IN UINT Length); + +#endif /* __CRYPT_ARC4_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_biginteger.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_biginteger.h new file mode 100644 index 000000000..58bcf7f4f --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_biginteger.h @@ -0,0 +1,523 @@ +/**************************************************************************** + * 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__ + +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +#include "rtmp_type.h" +#ifndef IN +#define IN +#endif +#ifndef OUT +#define OUT +#endif +#ifndef INOUT +#define INOUT +#endif + +typedef struct _BIG_INTEGER_STRUC BIG_INTEGER, *PBIG_INTEGER; +typedef struct _BI_OP_TIME_INTERVAL BI_OP_TIME_INTERVAL; +typedef struct _MONT_STRUC MONT_STRUC, *PMONT_STRUC; + + + +/* BigInteger definition & structure */ +#define SLIDING_WINDOW 16 +#ifndef DOT11_SAE_OPENSSL_BN +/*#define BI_POOL*/ +#endif +/*#define BI_TIME_REC */ +/*#define BI_POOL_DBG*/ + +#ifdef BI_POOL_DBG +#define POOL_COUNTER_CHECK_BEGIN(_expect_cnt) {_expect_cnt = sae_dump_pool_info_check(0, FALSE, FALSE); } +#define POOL_COUNTER_CHECK_END(_expect_cnt) {_expect_cnt = sae_dump_pool_info_check(_expect_cnt, TRUE, FALSE); } +#else +#define POOL_COUNTER_CHECK_BEGIN(_expect_cnt) +#define POOL_COUNTER_CHECK_END(_expect_cnt) +#endif + +#ifdef BI_POOL +#define GET_BI_INS_FROM_POOL(_ptr) {_ptr = get_temporal_usage_big_interger(); } +#else +#define GET_BI_INS_FROM_POOL(_ptr) +#endif + + +struct _BIG_INTEGER_STRUC { + RTMP_STRING Name[10]; + UINT32 *pIntegerArray; + UINT AllocSize; + UINT ArrayLength; + UINT IntegerLength; + INT Signed; + UCHAR invalid; +}; + + + +struct _BI_OP_TIME_INTERVAL { + ULONG avg_time_interval; + ULONG time_interval; + UINT32 exe_times; +}; + +struct _MONT_STRUC { + UINT16 Bits_Of_R; + BIG_INTEGER *pBI_X; + BIG_INTEGER *pBI_R; + BIG_INTEGER *pBI_PInverse; +}; + + +typedef struct _BI_OP_TIME_RECORD { + BI_OP_TIME_INTERVAL add_op; + BI_OP_TIME_INTERVAL sub_op; + BI_OP_TIME_INTERVAL mul_op; + BI_OP_TIME_INTERVAL div_op; + BI_OP_TIME_INTERVAL mod_op; + BI_OP_TIME_INTERVAL square_op; + BI_OP_TIME_INTERVAL sqrt_op; + BI_OP_TIME_INTERVAL exp_mod_op; + BI_OP_TIME_INTERVAL div_mod_op; + BI_OP_TIME_INTERVAL sqrt_mod_op; + BI_OP_TIME_INTERVAL mod_mul_inv_op; + BI_OP_TIME_INTERVAL simple_exp_mod_op; +} BI_OP_TIME_RECORD, *PBI_OP_TIME_RECORD; + +typedef struct _EC_POINT_OP_TIME_RECORD { + BI_OP_TIME_INTERVAL add_op; + BI_OP_TIME_INTERVAL dbl_op; + BI_OP_TIME_INTERVAL mul_op; + BI_OP_TIME_INTERVAL find_y_op; + BI_OP_TIME_INTERVAL on_curve_check_op; +} EC_POINT_OP_TIME_RECORD, *PEC_POINT_OP_TIME_RECORD; + + +#ifdef BI_POOL +VOID big_integer_pool_init( + VOID); + +VOID big_integer_pool_deinit( + VOID); + + +BIG_INTEGER *get_temporal_usage_big_interger( + VOID); + + +UINT32 sae_dump_pool_info_check( + INT32 expect_cnt, + UCHAR is_check, + UCHAR is_print); +#endif + +VOID release_temporal_usage_big_interger( + IN BIG_INTEGER **pBI); + + +VOID BigInteger_record_time_begin( + BI_OP_TIME_INTERVAL *time_rec); + +VOID BigInteger_record_time_end( + BI_OP_TIME_INTERVAL *time_rec); + + +/* 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); + +UINT32 BigInteger_getlen( + IN BIG_INTEGER * pBI); + + +VOID BigInteger_BI2Bin( + IN PBIG_INTEGER pBI, + OUT UINT8 * pValue, + OUT UINT *Length); + +VOID BigInteger_BI2Bin_with_pad( + IN PBIG_INTEGER pBI, + OUT UINT8 * pValue, + OUT UINT *Length, + IN UINT32 PadLen); + +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_MulMod( + IN PBIG_INTEGER pBI_A, + IN PBIG_INTEGER pBI_B, + IN PBIG_INTEGER pBI_P, + IN PBIG_INTEGER pBI_PInverse, + IN UINT Bits_Of_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); + +VOID BigInteger_Montgomery_MulMod_with_mont( + IN PBIG_INTEGER pBI_A, + IN PBIG_INTEGER pBI_B, + IN PBIG_INTEGER pBI_P, + IN MONT_STRUC * mont, + OUT PBIG_INTEGER * pBI_Result); + + +VOID BigInteger_Montgomery_ExpMod_with_mont( + IN PBIG_INTEGER pBI_G, + IN PBIG_INTEGER pBI_E, + IN PBIG_INTEGER pBI_P, + IN MONT_STRUC * mont, + OUT PBIG_INTEGER * pBI_Result); + +UCHAR BigInteger_is_zero(IN PBIG_INTEGER pBI); + +UCHAR BigInteger_is_one(IN PBIG_INTEGER pBI); + +VOID BigInteger_Mod( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + OUT PBIG_INTEGER *pBI_Result); + +VOID BigInteger_Mod_Mul( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER *pBI_Result); + +UCHAR BigInteger_is_odd( + IN PBIG_INTEGER pBI); + +VOID BigInteger_Mod_Square( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER * pBI_Result); + + +VOID BigInteger_Mod_Add( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER * pBI_Result); + +VOID BigInteger_Mod_Sub( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER * pBI_Result); + + +VOID BigInteger_Mod_Add_quick( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER * pBI_Result); + +VOID BigInteger_Mod_Sub_quick( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER * pBI_Result); + + +VOID BigInteger_Mod_Div( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER * pBI_Result); + + +VOID BigInteger_Mod_Sqrt( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pBI_P, + IN MONT_STRUC * mont, + OUT PBIG_INTEGER * pBI_Result); + + +VOID BigInteger_Euclidean_Div( + IN PBIG_INTEGER pFirstOperand, + IN PBIG_INTEGER pSecondOperand, + IN PBIG_INTEGER prev_u, + IN PBIG_INTEGER prev_v, + INOUT PBIG_INTEGER curr_u, + INOUT PBIG_INTEGER curr_v); + + +VOID BigInteger_Mod_Mul_Inverse( + IN PBIG_INTEGER pBI, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER * pBI_Result); + +VOID BigInteger_Mod_Mul_Inverse2( + IN PBIG_INTEGER pBI, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER * pBI_Result); + + +UCHAR BigInteger_Sqrt( + IN PBIG_INTEGER pBI, + OUT PBIG_INTEGER * pBI_Result); + +VOID BigInteger_Shift_Right1( + IN PBIG_INTEGER pBI, + OUT PBIG_INTEGER * pBI_Result); + +VOID BigInteger_Mod_Shift_Left( + IN PBIG_INTEGER pBI, + IN UCHAR bit, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER * pBI_Result); + + +VOID BigInteger_Shift_Left( + IN PBIG_INTEGER pBI, + IN UINT32 shift_bit, + OUT PBIG_INTEGER * pBI_Result); + + +/* treat pBi is positve and non-zero */ +VOID BigInteger_minus_one( + INOUT PBIG_INTEGER pBI); + + +/* treat pBi is positve and non-zero */ +VOID BigInteger_plus_one( + INOUT PBIG_INTEGER pBI); + + +/* an integer q is called a quadratic residue modulo n if it is congruent to a perfect square modulo n */ +UCHAR BigInteger_is_quadratic_residue( + IN BIG_INTEGER *q, + IN BIG_INTEGER *prime, + IN MONT_STRUC * mont); + +VOID BigInteger_Montgomery_ExpMod32( + IN PBIG_INTEGER pBI_G, + IN PBIG_INTEGER pBI_E, + IN PBIG_INTEGER pBI_P, + OUT PBIG_INTEGER * pBI_Result); + + +VOID BigInteger_DWtoBI( + IN UINT32 value, + OUT PBIG_INTEGER * pBI); + +VOID BigInteger_Add_DW( + INOUT PBIG_INTEGER pBI, + IN UINT32 value); + +VOID BigInteger_Mod_DW( + INOUT PBIG_INTEGER pBI, + IN UINT32 value, + OUT UINT32 *rem); + + +VOID BigInteger_DtoH( + INOUT PBIG_INTEGER pBI); + +VOID BigInteger_dump_time( + VOID); + +INT BigInteger_rand_range(IN BIG_INTEGER * range, INOUT BIG_INTEGER * r); + +#else + +#include "rt_config.h" + + +/* BigInteger definition & structure */ +#define SLIDING_WINDOW 16 +typedef struct _BIG_INTEGER_STRUC +{ + RTMP_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 /* defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) */ + + +#endif /* __CRYPT_BIGINTEGER_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_bignum.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_bignum.h new file mode 100644 index 000000000..bf1e64825 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_bignum.h @@ -0,0 +1,328 @@ +/* ==================================================================== + * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgment: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +/**************************************************************************** + Module Name: + Bignum + + + Revision History: + Who When What + -------- ---------- ------------------------------------------ + Eddy 2009/01/12 Create +***************************************************************************/ + +#ifndef __CRYPT_BIGNUM_H__ +#define __CRYPT_BIGNUM_H__ + + +#include "rtmp_type.h" +#include "bn.h" + +#ifndef IN +#define IN +#endif +#ifndef OUT +#define OUT +#endif +#ifndef INOUT +#define INOUT +#endif + + +/* Bignum operations */ +VOID Bignum_Print ( + IN BIGNUM *pBI); + + +VOID Bignum_Init( + INOUT BIGNUM **pBI); + +VOID Bignum_Free( + IN BIGNUM **pBI); + +UINT32 Bignum_getlen( + IN BIGNUM *pBI); + +INT Bignum_Get_rand_range(IN BIGNUM * range, INOUT BIGNUM * r); + +VOID Bignum_BI2Bin( + IN BIGNUM *pBI, + OUT UINT8 *pValue, + OUT UINT *Length); + +VOID Bignum_BI2Bin_with_pad( + IN BIGNUM *pBI, + OUT UINT8 *pValue, + OUT UINT *Length, + IN UINT32 PadLen); + +VOID Bignum_Bin2BI( + IN UINT8 *pValue, + IN UINT Length, + OUT BIGNUM **pBI); + +VOID Bignum_Copy( + IN BIGNUM *pBI_Copied, + OUT BIGNUM **pBI_Result); + +INT Bignum_UnsignedCompare( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand); + +VOID Bignum_Add( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand, + OUT BIGNUM **pBI_Result); + +VOID Bignum_Sub( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand, + OUT BIGNUM **pBI_Result); + +VOID Bignum_Mod( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand, + OUT BIGNUM **pBI_Result); + +VOID Bignum_Mod_Mul( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result); + + +VOID Bignum_Montgomery_ExpMod( + IN BIGNUM *pBI_G, + IN BIGNUM *pBI_E, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result); + +UCHAR Bignum_is_zero( + IN BIGNUM *pBI); + +UCHAR Bignum_is_one( + IN BIGNUM *pBI); + +UCHAR Bignum_is_odd( + IN BIGNUM *pBI); + +VOID Bignum_Mod_Square( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result); + + +VOID Bignum_Mod_Add( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result); + +VOID Bignum_Mod_Sub( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result); + + +VOID Bignum_Mod_Add_quick( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result); + +VOID Bignum_Mod_Sub_quick( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result); + + +VOID Bignum_Mod_Div( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pSecondOperand, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result); + + +VOID Bignum_Mod_Sqrt( + IN BIGNUM *pFirstOperand, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result); + + +VOID Bignum_Mod_Mul_Inverse( + IN BIGNUM *pBI, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result); + + +UCHAR Bignum_Sqrt( + IN BIGNUM *pBI, + OUT BIGNUM **pBI_Result); + +VOID Bignum_Shift_Right1( + IN BIGNUM *pBI, + OUT BIGNUM **pBI_Result); + +VOID Bignum_Mod_Shift_Left1( + IN BIGNUM *pBI, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result); + +VOID Bignum_Mod_Shift_Left( + IN BIGNUM *pBI, + IN UCHAR bit, + IN BIGNUM *pBI_P, + OUT BIGNUM **pBI_Result); + +VOID Bignum_Shift_Left( + IN BIGNUM *pBI, + IN UINT32 shift_bit, + OUT BIGNUM **pBI_Result); + + +/* treat pBi is positve and non-zero */ +VOID Bignum_minus_one( + INOUT BIGNUM *pBI); + + +/* treat pBi is positve and non-zero */ +VOID Bignum_plus_one( + INOUT BIGNUM *pBI); + + +/* an integer q is called a quadratic residue modulo n if it is congruent to a perfect square modulo n */ +UCHAR Bignum_is_quadratic_residue( + IN BIGNUM *q, + IN BIGNUM *prime); + +VOID Bignum_DWtoBI( + IN UINT32 value, + OUT BIGNUM **pBI); + +VOID Bignum_Add_DW( + INOUT BIGNUM *pBI, + IN UINT32 value); + +VOID Bignum_Mod_DW( + INOUT BIGNUM *pBI, + IN UINT32 value, + OUT UINT32 *rem); + + +VOID Bignum_DtoH( + INOUT BIGNUM *pBI); + + +#endif /* __CRYPT_BIGNUM_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_dh.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_dh.h new file mode 100644 index 000000000..b1cdab015 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_dh.h @@ -0,0 +1,65 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + Module Name: + DH + + Abstract: + RFC 2631: Diffie-Hellman Key Agreement Method + + Revision History: + Who When What + -------- ---------- ------------------------------------------ + Eddy 2009/01/21 Create Diffie-Hellman, Montgomery Algorithm +***************************************************************************/ + +#ifndef __CRYPT_DH_H__ +#define __CRYPT_DH_H__ + +#include "rt_config.h" + + +/* DH operations */ +void DH_PublicKey_Generate ( + IN UINT8 GValue[], + IN UINT GValueLength, + IN UINT8 PValue[], + IN UINT PValueLength, + IN UINT8 PrivateKey[], + IN UINT PrivateKeyLength, + OUT UINT8 PublicKey[], + INOUT UINT *PublicKeyLength); + +void DH_SecretKey_Generate ( + IN UINT8 PublicKey[], + IN UINT PublicKeyLength, + IN UINT8 PValue[], + IN UINT PValueLength, + IN UINT8 PrivateKey[], + IN UINT PrivateKeyLength, + OUT UINT8 SecretKey[], + INOUT UINT *SecretKeyLength); + +#define RT_DH_PublicKey_Generate(GK, GKL, PV, PVL, PriK, PriKL, PubK, PubKL) \ + DH_PublicKey_Generate((GK), (GKL), (PV), (PVL), (PriK), (PriKL), (UINT8 *) (PubK), (UINT *) (PubKL)) + +#define RT_DH_SecretKey_Generate(PubK, PubKL, PV, PVL, PriK, PriKL, SecK, SecKL) \ + DH_SecretKey_Generate((PubK), (PubKL), (PV), (PVL), (PriK), (PriKL), (UINT8 *) (SecK), (UINT *) (SecKL)) + +#define RT_DH_FREE_ALL() + + +#endif /* __CRYPT_DH_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_hmac.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_hmac.h new file mode 100644 index 000000000..59b30d08a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_hmac.h @@ -0,0 +1,111 @@ +/**************************************************************************** + * 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" +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +#include "rtmp_type.h" +#ifndef IN +#define IN +#endif +#ifndef OUT +#define OUT +#endif +#ifndef INOUT +#define INOUT +#endif + +#endif /* defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) */ + + +#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); +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +VOID RT_HMAC_SHA256_VECTOR( + IN const UINT8 key[], + IN UINT key_len, + IN UCHAR element_num, + IN const UINT8 *message[], + IN UINT *message_len, + OUT UINT8 mac[], + IN UINT mac_len); +#endif /* defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) */ +#endif /* SHA256_SUPPORT */ +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +#ifdef SHA384_SUPPORT +VOID RT_HMAC_SHA384( + IN const UINT8 Key[], + IN UINT KeyLen, + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 MAC[], + IN UINT MACLen); + +VOID RT_HMAC_SHA384_VECTOR( + IN const UINT8 key[], + IN UINT key_len, + IN UCHAR element_num, + IN const UINT8 *message[], + IN UINT *message_len, + OUT UINT8 mac[], + IN UINT mac_len); +#endif /* SHA384_SUPPORT */ +#endif /* defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) */ + +#ifdef MD5_SUPPORT +#define HMAC_MD5_SUPPORT +VOID RT_HMAC_MD5( + IN const UINT8 Key[], + IN UINT KeyLen, + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 MAC[], + IN UINT MACLen); +#endif /* MD5_SUPPORT */ + + +#endif /* __CRYPT_HMAC_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_md5.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_md5.h new file mode 100644 index 000000000..60cf5d3ba --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_md5.h @@ -0,0 +1,63 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + Module Name: + MD5 + + Abstract: + RFC1321: The MD5 Message-Digest Algorithm + + Revision History: + Who When What + -------- ---------- ------------------------------------------ + Eddy 2008/11/24 Create md5 +***************************************************************************/ + +#ifndef __CRYPT_MD5_H__ +#define __CRYPT_MD5_H__ + + +/* Algorithm options */ +#define MD5_SUPPORT + +#ifdef MD5_SUPPORT +#define MD5_BLOCK_SIZE 64 /* 512 bits = 64 bytes */ +#define MD5_DIGEST_SIZE 16 /* 128 bits = 16 bytes */ +typedef struct { + UINT32 HashValue[4]; + UINT64 MessageLen; + UINT8 Block[MD5_BLOCK_SIZE]; + UINT BlockLen; +} MD5_CTX_STRUC, *PMD5_CTX_STRUC; + +VOID RT_MD5_Init( + IN MD5_CTX_STRUC * pMD5_CTX); +VOID RT_MD5_Hash( + IN MD5_CTX_STRUC * pMD5_CTX); +VOID RT_MD5_Append( + IN MD5_CTX_STRUC * pMD5_CTX, + IN const UINT8 Message[], + IN UINT MessageLen); +VOID RT_MD5_End( + IN MD5_CTX_STRUC * pMD5_CTX, + OUT UINT8 DigestMessage[]); +VOID RT_MD5( + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 DigestMessage[]); +#endif /* MD5_SUPPORT */ + + +#endif /* __CRYPT_MD5_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_sha2.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_sha2.h new file mode 100644 index 000000000..8de8599d7 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/crypt_sha2.h @@ -0,0 +1,151 @@ +/**************************************************************************** + * 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__ + +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +#include "rtmp_type.h" +#ifndef IN +#define IN +#endif +#ifndef OUT +#define OUT +#endif +#ifndef INOUT +#define INOUT +#endif +#endif /* defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) */ + +/* Algorithm options */ +#define SHA1_SUPPORT +#define SHA256_SUPPORT +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +#define SHA384_SUPPORT +#endif /* defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_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[]); +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +VOID rt_sha256_vector( + IN UCHAR num, + IN const unsigned char **message, + IN UINT *messageLen, + OUT UINT8 *digestmessage); +#endif /* defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) */ +#endif /* SHA256_SUPPORT */ + +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +#ifdef SHA384_SUPPORT +#define SHA384_BLOCK_SIZE 128 /* 1024 bits = 128 bytes */ +#define SHA384_DIGEST_SIZE 48 /* 384 bits = 64 bytes */ +typedef struct _SHA384_CTX_STRUC { + UINT64 HashValue[8]; /* 8 = (SHA384_DIGEST_SIZE / 64) */ + UINT64 MessageLen; /* total size */ + UINT8 Block[SHA384_BLOCK_SIZE]; + UINT BlockLen; +} SHA384_CTX_STRUC, *PSHA384_CTX_STRUC; +VOID RT_SHA384_Init( + IN SHA384_CTX_STRUC * pSHA_CTX); +VOID RT_SHA384_Hash( + IN SHA384_CTX_STRUC * pSHA_CTX); +VOID RT_SHA384_Append( + IN SHA384_CTX_STRUC * pSHA_CTX, + IN const UINT8 Message[], + IN UINT MessageLen); +VOID RT_SHA384_End( + IN SHA384_CTX_STRUC * pSHA_CTX, + OUT UINT8 DigestMessage[]); +VOID RT_SHA384( + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 DigestMessage[]); +VOID rt_sha384_vector( + IN UCHAR num, + IN const unsigned char **message, + IN UINT *messageLen, + OUT UINT8 *digestmessage); +#endif /* SHA384_SUPPORT */ +/*#ifdef SHA512_SUPPORT*/ +/*FIXME: wrape it by SHA512_SUPPORT */ +#define SHA512_BLOCK_SIZE 128 /* 1024 bits = 128 bytes */ +#define SHA512_DIGEST_SIZE 64 /* 384 bits = 64 bytes */ +/*#endif*/ +#endif /* defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) */ + +#endif /* __CRYPT_SHA2_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cs.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cs.h new file mode 100644 index 000000000..5743aa510 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/cs.h @@ -0,0 +1,154 @@ +#ifndef __CS_H__ +#define __CS_H__ + +#ifdef CARRIER_DETECTION_SUPPORT +#define CARRIER_DETECT_RECHECK_TIME 3 +#define CARRIER_GONE_TRESHOLD 10 /* Radar tone count in 1 sec */ +#define CARRIER_DETECT_THRESHOLD 0x0fffffff +#define CARRIER_DETECT_STOP_RATIO 2 +#define CARRIER_DETECT_STOP_RECHECK_TIME 4 +#define CARRIER_DETECT_DEFAULT_MASK 20 +#define CARRIER_DETECT_DELTA 7 +#define CARRIER_DETECT_DIV_FLAG 0 +#define CD_INT_POLLING_CMD 0x67 +#define CARRIER_DETECT_CRITIRIA 7000 + +typedef enum CD_STATE_n { + CD_NORMAL, + CD_SILENCE, + CD_MAX_STATE +} CD_STATE; + +typedef enum _TONE_RADAR_VERSION { + DISABLE_TONE_RADAR = 0, + TONE_RADAR_V1, + TONE_RADAR_V2, + TONE_RADAR_V3 +} TONE_RADAR_VERSION; + +typedef struct CARRIER_DETECTION_s { + BOOLEAN Enable; + BOOLEAN bCsInit; + UINT8 CDSessionTime; + UINT8 CDPeriod; + CD_STATE CD_State; + UINT8 delta; + UINT8 SymRund; + UINT8 div_flag; + UINT32 threshold; + UINT8 recheck; + UINT8 recheck1; + UINT32 TimeStamp; /*unit:16us*/ + UINT32 criteria; + ULONG idle_time; + ULONG busy_time; + ULONG Debug; + ULONG OneSecIntCount; + UINT8 CarrierGoneThreshold; + UCHAR VGA_Mask; + UCHAR Packet_End_Mask; + UCHAR Rx_PE_Mask; +} CARRIER_DETECTION_STRUCT, *PCARRIER_DETECTION_STRUCT; + +#ifdef CARRIER_DETECTION_FIRMWARE_SUPPORT +/* Mcu command */ +#define CD_ONOFF_MCU_CMD 0x65 +#define CD_CHECKOUT_MCU_CMD 0x66 +/* share memory offsets */ +#define CD_CRITERIA 0x4CB2 +#define CD_CHECK_COUNT 0x4CB9 +#define RADAR_TONE_COUNT 0x4CBE +#define CD_RECHECK 0x4CBF +#undef CARRIER_DETECT_RECHECK_TIME +#undef CARRIER_GONE_TRESHOLD +#undef CARRIER_DETECT_THRESHOLD +#define CARRIER_DETECT_RECHECK_TIME 5 +#define CARRIER_GONE_TRESHOLD 35 +#define CARRIER_DETECT_THRESHOLD 0x4fffffff + +/* Parameters needed to decide the Carrier Detect State */ +typedef struct _CARRIER_DETECT_PARAM { + UINT8 RadarToneCount; /* Number of radar tones in 100 msec*/ + UINT8 ReCheck; +} CARRIER_DETECT_PARAM, *PCARRIER_DETECT_PARAM; + +/* For debug print */ +typedef struct _CARRIER_DETECT_DEBUG { + UINT8 delta_div; + UINT8 internalRadarToneCount; + UINT16 Criteria; + UINT32 Threshold; + UINT8 Count; + UINT8 CheckCount; + UINT8 Reserved; + UINT8 VGA_Mask; + UINT8 PckMask; + UINT8 RxPeMask; + UINT8 RadarToneCount; + UINT8 ReCheck; +} CARRIER_DETECT_DEBUG, *PCARRIER_DETECT_DEBUG; +#endif /*CARRIER_DETECTION_FIRMWARE_SUPPORT*/ + +INT isCarrierDetectExist( + IN PRTMP_ADAPTER pAd); + +INT CarrierDetectReset( + IN PRTMP_ADAPTER pAd); + +extern VOID RtmpOsMsDelay( + IN ULONG msec); + +INT Set_CarrierCriteria_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_CarrierReCheck_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_CarrierGoneThreshold_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_CarrierStopCheck_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_CarrierDebug_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_CarrierDelta_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_CarrierDivFlag_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_CarrierThrd_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +/* v2 functions */ +INT Set_CarrierSymRund_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_CarrierMask_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *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); + +VOID ToneRadarProgram_v3( + IN PRTMP_ADAPTER pAd, + IN ULONG threshold); + +VOID CarrierDetectionPeriodicStateCtrl( + IN PRTMP_ADAPTER pAd); + +#ifdef CONFIG_AP_SUPPORT +INT Set_CarrierDetect_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /*CONFIG_AP_SUPPORT*/ +#endif /* CARRIER_DETECTION_SUPPORT */ + +#endif /*__CS_H__*/ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dfs.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dfs.h new file mode 100644 index 000000000..39824faf6 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dfs.h @@ -0,0 +1,430 @@ + +/* + *************************************************************************** + * 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 HW_TIMER_INTERVAL 10 +#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) || \ + (ScanRunning(_pAd) == TRUE)) + + +typedef enum _DFS_VERSION { + SOFTWARE_DFS = 0, + HARDWARE_DFS_V1, + HARDWARE_DFS_V2 +} DFS_VERSION; + +typedef struct _NewDFSValidRadar +{ + USHORT type; + USHORT channel; /* bit map*/ + USHORT WLow; + USHORT WHigh; + USHORT W; /* for fixed width radar*/ + USHORT WMargin; + ULONG TLow; + ULONG THigh; + ULONG T; /* for fixed period radar */ + USHORT TMargin; +}NewDFSValidRadar, *pNewDFSValidRadar; + +typedef struct _NewDFSDebugPort { + ULONG counter; + ULONG timestamp; + USHORT width; + USHORT start_idx; /* start index to period table */ + USHORT end_idx; /* end index to period table */ +} NewDFSDebugPort, *pNewDFSDebugPort; + +/* Matched Period Table */ +typedef struct _NewDFSMPeriod { + USHORT idx; + USHORT width; + USHORT idx2; + USHORT width2; + ULONG period; +} NewDFSMPeriod, *pNewDFSMPeriod; + +typedef struct _DFS_ENGINE_LOCAL_CFG { + BOOLEAN valid; + UCHAR mode; + USHORT avgLen; + USHORT ELow; + USHORT EHigh; + USHORT WLow; + USHORT WHigh; + UCHAR EpsilonW; + ULONG TLow; + ULONG THigh; + UCHAR EpsilonT; + ULONG BLow; + ULONG BHigh; + UINT32 EventExpiration; + UINT16 PwrJump; +} DFS_ENGINE_LOCAL_CFG, *pDFS_ENGINE_LOCAL_CFG; + +typedef struct _DFS_PROGRAM_PARAM{ + DFS_ENGINE_LOCAL_CFG NewDFSTableEntry[NEW_DFS_MAX_CHANNEL*4]; + USHORT ChEnable; /* Enabled Dfs channels (bit wise)*/ + UCHAR DeltaDelay; + UCHAR Symmetric_Round; + UCHAR VGA_Mask; + UCHAR Packet_End_Mask; + UCHAR Rx_PE_Mask; + UCHAR PwrDown_Hold_Time; + UCHAR PwrGain_Offset; +}DFS_PROGRAM_PARAM, *PDFS_PROGRAM_PARAM; + +typedef struct _NewDFSTable +{ + USHORT type; + DFS_ENGINE_LOCAL_CFG entry[NEW_DFS_MAX_CHANNEL]; +}NewDFSTable, *pNewDFSTable; + +#ifdef DFS_DEBUG +typedef struct _NewDFSDebugResult +{ + char delta_delay_shift; + char EL_shift; + char EH_shift; + char WL_shift; + char WH_shift; + ULONG hit_time; + ULONG false_time; +}NewDFSDebugResult, *pNewDFSDebugResult; +#endif + +typedef struct _DFS_EVENT{ + UINT8 EngineId; + UINT32 TimeStamp; + UINT16 Width; +}DFS_EVENT, *PDFS_EVENT; + +typedef struct _DFS_SW_DETECT_PARAM{ + USHORT dfs_width_diff_ch1_Shift; + USHORT dfs_width_diff_ch2_Shift; + USHORT dfs_period_err; + ULONG dfs_max_period; /* Max possible Period */ + USHORT dfs_width_diff; + USHORT dfs_width_ch0_err_L; + USHORT dfs_width_ch0_err_H; + UCHAR dfs_check_loop; + UCHAR dfs_declare_thres; + ULONG dfs_w_counter; + DFS_EVENT PreDfsEvent; /* previous radar event */ + UINT32 EvtDropAdjTime; /* timing threshold for adjacent event */ + UINT sw_idx[NEW_DFS_MAX_CHANNEL]; + UINT hw_idx[NEW_DFS_MAX_CHANNEL]; + UINT pr_idx[NEW_DFS_MAX_CHANNEL]; + USHORT dfs_t_idx[NEW_DFS_MAX_CHANNEL]; + USHORT dfs_w_idx[NEW_DFS_MAX_CHANNEL]; + USHORT dfs_w_last_idx[NEW_DFS_MAX_CHANNEL]; + NewDFSDebugPort DFS_W[NEW_DFS_MAX_CHANNEL][NEW_DFS_DBG_PORT_ENT_NUM]; + NewDFSMPeriod DFS_T[NEW_DFS_MAX_CHANNEL][NEW_DFS_MPERIOD_ENT_NUM]; /* period table */ +}DFS_SW_DETECT_PARAM, *PDFS_SW_DETECT_PARAM; + +/*************************************************************************** + * structure for radar detection and channel switch + **************************************************************************/ +typedef struct _RADAR_DETECT_STRUCT { + UCHAR DFSAPRestart; + ULONG MCURadarRegion; + ULONG TimeStamp; /*unit: 1us*/ + UCHAR ChirpCheck; /* anounce on second detection of chirp radar */ + UCHAR bChannelSwitchInProgress; /* RDMode could cover this*/ + BOOLEAN bDfsSwDisable; /* disable sotfwre check */ + BOOLEAN bDfsInit; /* to indicate if dfs regs has been initialized */ + USHORT PollTime; + INT DfsRssiHigh; + INT DfsRssiLow; + BOOLEAN DfsRssiHighFromCfg; + BOOLEAN DfsRssiLowFromCfg; + BOOLEAN DfsRssiHighCfgValid; + BOOLEAN DfsRssiLowCfgValid; + BOOLEAN DFSParamFromConfig; + BOOLEAN use_tasklet; + UCHAR radarDeclared; + BOOLEAN SymRoundFromCfg; + BOOLEAN SymRoundCfgValid; + ULONG idle_time; + ULONG busy_time; + UCHAR ch_busy; + CHAR ch_busy_countdown; + UCHAR busy_channel; + UCHAR ch_busy_idle_ratio; + BOOLEAN BusyIdleFromCfg; + BOOLEAN BusyIdleCfgValid; + UCHAR print_ch_busy_sta; + ULONG ch_busy_sta[CH_BUSY_SAMPLE]; + ULONG ch_idle_sta[CH_BUSY_SAMPLE]; + UCHAR ch_busy_sta_index; + INT ch_busy_sum; + INT ch_idle_sum; + UCHAR McuRadarDebug; + USHORT McuRadarTick; + ULONG RadarTimeStampLow; + UCHAR EnabledChMask; /* Bit-wise mask for enabled DFS channels */ + BOOLEAN bAdjustDfsAgc; + pNewDFSTable pDFSTable; + DFS_PROGRAM_PARAM DfsProgramParam; + DFS_SW_DETECT_PARAM DfsSwParam; +#ifdef DFS_ATP_SUPPORT + BOOLEAN atp_radar_detect; + BOOLEAN atp_set_ht_bw; + BOOLEAN atp_set_vht_bw; + BOOLEAN atp_set_channel_ready; +#endif /* DFS_ATP_SUPPORT */ +} RADAR_DETECT_STRUCT, *PRADAR_DETECT_STRUCT; + +typedef struct _NewDFSProgParam +{ + UCHAR channel; + UCHAR mode; /* reg 0x10, Detection Mode[2:0]*/ + USHORT avgLen; /* reg 0x11~0x12, M[7:0] & M[8]*/ + USHORT ELow; /* reg 0x13~0x14, Energy Low[7:0] & Energy Low[11:8]*/ + USHORT EHigh; /* reg 0x15~0x16, Energy High[7:0] & Energy High[11:8]*/ + USHORT WLow; /* reg 0x28~0x29, Width Low[7:0] & Width Low[11:8]*/ + USHORT WHigh; /* reg 0x2a~0x2b, Width High[7:0] & Width High[11:8]*/ + UCHAR EpsilonW; /* reg 0x2c, Width Delta[7:0], (Width Measurement Uncertainty) */ + ULONG TLow; /* reg 0x17~0x1a, Period Low[7:0] & Period Low[15:8] & Period Low[23:16] & Period Low[31:24]*/ + ULONG THigh; /* reg 0x1b~0x1e, Period High[7:0] & Period High[15:8] & Period High[23:16] & Period High[31:24]*/ + UCHAR EpsilonT; /* reg 0x27, Period Delt[7:0], (Period Measurement Uncertainty) */ + ULONG BLow; /* reg 0x1f~0x22, Burst Low[7:0] & Burst Low[15:8] & Burst Low[23:16] & Burst Low[31:24]*/ + ULONG BHigh; /* reg 0x23~0x26, Burst High[7:0] & Burst High[15:8] & Burst High[23:16] & Burst High[31:24] */ +}NewDFSProgParam, *pNewDFSProgParam; + +#ifdef CONFIG_AP_SUPPORT +VOID NewRadarDetectionStart( + IN PRTMP_ADAPTER pAd); + +VOID NewRadarDetectionStop( + IN PRTMP_ADAPTER pAd); + +void modify_table1( + IN PRTMP_ADAPTER pAd, + IN ULONG idx, + IN ULONG value); + +void modify_table2( + IN PRTMP_ADAPTER pAd, + IN ULONG idx, + IN ULONG value); + +void schedule_dfs_task( + IN PRTMP_ADAPTER pAd); + +int SWRadarCheck( + IN PRTMP_ADAPTER pAd, USHORT id); + +VOID NewRadarDetectionProgram( + IN PRTMP_ADAPTER pAd, + IN pNewDFSTable pDFSTable); + +BOOLEAN DfsSwCheckOnHwDetection( + IN PRTMP_ADAPTER pAd, + IN pNewDFSTable pDFSTable, + IN UINT8 DfsChannel, + IN ULONG RadarPeriod, + IN ULONG RadarWidth); + +INT Show_BlockCh_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_RadarDebug_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ResetRadarHwDetect_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_DfsSwDisable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_DfsEnvtDropAdjTime_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_RadarStart_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_RadarStop_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef DFS_ATP_SUPPORT +INT Set_DfsAtpStart_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_DfsAtpReset_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_DfsAtpReport_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif + +INT Set_RadarSetTbl1_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_RadarSetTbl2_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_PollTime_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_PrintBusyIdle_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_BusyIdleRatio_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_DfsRssiHigh_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_DfsRssiLow_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +void dfs_tasklet(unsigned long data); + +VOID DFSInit( + IN PRTMP_ADAPTER pAd); + +VOID ApRadarDetectPeriodic( + IN PRTMP_ADAPTER pAd); + +#ifdef RTMP_MAC_PCI +VOID NewTimerCB_Radar( + IN PRTMP_ADAPTER pAd); +#endif /* RTMP_MAC_PCI */ + + +#endif /* CONFIG_AP_SUPPORT */ +#endif /* DFS_SUPPORT */ + +#endif /*_DFS_H__*/ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/diag.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/diag.h new file mode 100644 index 000000000..5958d2b50 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/diag.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016 MediaTek Inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _DIAG_H_ +#define _DIAG_H_ + +#ifdef WIFI_DIAG + +#include "rtmp_comm.h" +#include "rtmp_def.h" +#include "fpga/fpga_ctl.h" +#include "rtmp_timer.h" +#include "mlme.h" +#include "band_steering_def.h" +#include "rtmp_type.h" +#include "rtmp.h" + + + +typedef struct _DIAG_FRAME_INFO { + UCHAR isTX; + /* for RX: pRxBlk->wcid=>MAC table entry => apidx => MBSSID[apidx] => ssid + * for TX: (1) pHeader->Addr1 => MAC table entry (exist) => apidx => MBSSID[apidx] => ssid + * (2) if MAC table entry not exist, traverse all MBSSID entry + */ + UCHAR *ssid; + UCHAR ssid_len; + UCHAR band; /* 0:2G, 1:5G, get from pAd->LatchRfRegs.Channel */ + UCHAR *pData; /* include 80211 header, refer to pRxBlk (RX)/ pData (TX) */ + UINT32 dataLen; /* packet length */ +} DIAG_FRAME_INFO; + +typedef enum _ENUM_DIAG_CONN_ERROR_CODE { + DIAG_CONN_FRAME_LOST = 0, + DIAG_CONN_CAP_ERROR, + DIAG_CONN_AUTH_FAIL, + DIAG_CONN_ACL_BLK, + DIAG_CONN_STA_LIM, + DIAG_CONN_DEAUTH, + DIAG_CONN_BAND_STE, + DIAG_CONN_ERROR_MAX +} ENUM_DIAG_CONN_ERROR_CODE; + +void DiagGetProcessInfo(PRTMP_ADAPTER pAdapter, RTMP_IOCTL_INPUT_STRUCT *wrq); +void DiagApMlmeOneSecProc(PRTMP_ADAPTER pAd); +void DiagAddPid(INT pid, PUCHAR name); +void DiagDelPid(INT32 pid); +void DiagFrameCache(DIAG_FRAME_INFO *info); +void DiagMiniportMMRequest(PRTMP_ADAPTER pAd, UCHAR *pData, UINT Length); +void DiagDevRxMgmtFrm(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); +#ifdef CONFIG_SNIFFER_SUPPORT +void DiagDevRxCntlFrm(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); +#endif +void DiagBcnTx(RTMP_ADAPTER *pAd, BSS_STRUCT *pMbss, UCHAR *pBeaconFrame, ULONG FrameLen); +void DiagConnError(PRTMP_ADAPTER pAd, UCHAR apidx, UCHAR *addr, + ENUM_DIAG_CONN_ERROR_CODE Code, UINT32 Reason); +void DiagLogFileWrite(void); +void DiagAssocErrorFileWrite(void); +BOOLEAN DiagProcInit(PRTMP_ADAPTER pAd); +BOOLEAN DiagProcExit(PRTMP_ADAPTER pAd); +BOOLEAN DiagProcMemAllocate(void); +BOOLEAN DiagProcMemFree(void); +#endif +#endif /* #ifndef _DIAG_H_ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11_base.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11_base.h new file mode 100644 index 000000000..ba6f95a4c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11_base.h @@ -0,0 +1,152 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + dot11_base.h + + Abstract: + Defined IE/frame structures of 802.11 base line + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- +*/ + + +#ifndef _DOT11_BASE_H_ +#define _DOT11_BASE_H_ + +#include "rtmp_type.h" + + +/* value domain of 802.11 header FC.Tyte, which is b3..b2 of the 1st-byte of MAC header */ +#define FC_TYPE_MGMT 0 +#define FC_TYPE_CNTL 1 +#define FC_TYPE_DATA 2 +#define FC_TYPE_RSVED 3 + +/* value domain of 802.11 MGMT frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header */ +#define SUBTYPE_ASSOC_REQ 0 +#define SUBTYPE_ASSOC_RSP 1 +#define SUBTYPE_REASSOC_REQ 2 +#define SUBTYPE_REASSOC_RSP 3 +#define SUBTYPE_PROBE_REQ 4 +#define SUBTYPE_PROBE_RSP 5 +#define SUBTYPE_TIMING_ADV 6 +#define SUBTYPE_BEACON 8 +#define SUBTYPE_ATIM 9 +#define SUBTYPE_DISASSOC 10 +#define SUBTYPE_AUTH 11 +#define SUBTYPE_DEAUTH 12 +#define SUBTYPE_ACTION 13 +#define SUBTYPE_ACTION_NO_ACK 14 + +/* value domain of 802.11 CNTL frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header */ +#define SUBTYPE_VHT_NDPA 5 +#define SUBTYPE_WRAPPER 7 +#define SUBTYPE_BLOCK_ACK_REQ 8 +#define SUBTYPE_BLOCK_ACK 9 +#define SUBTYPE_PS_POLL 10 +#define SUBTYPE_RTS 11 +#define SUBTYPE_CTS 12 +#define SUBTYPE_ACK 13 +#define SUBTYPE_CFEND 14 +#define SUBTYPE_CFEND_CFACK 15 + +/* value domain of 802.11 DATA frame's FC.subtype, which is b7..4 of the 1st-byte of MAC header */ +#define SUBTYPE_DATA 0 +#define SUBTYPE_DATA_CFACK 1 +#define SUBTYPE_DATA_CFPOLL 2 +#define SUBTYPE_DATA_CFACK_CFPOLL 3 +#define SUBTYPE_DATA_NULL 4 +#define SUBTYPE_CFACK 5 +#define SUBTYPE_CFPOLL 6 +#define SUBTYPE_CFACK_CFPOLL 7 +#define SUBTYPE_QDATA 8 +#define SUBTYPE_QDATA_CFACK 9 +#define SUBTYPE_QDATA_CFPOLL 10 +#define SUBTYPE_QDATA_CFACK_CFPOLL 11 +#define SUBTYPE_QOS_NULL 12 +#define SUBTYPE_QOS_CFACK 13 +#define SUBTYPE_QOS_CFPOLL 14 +#define SUBTYPE_QOS_CFACK_CFPOLL 15 +#define SUBTYPE_ALL 16 + +/* 2-byte Frame control field */ +typedef struct GNU_PACKED { +#ifdef RT_BIG_ENDIAN + UINT16 Order:1; /* Strict order expected */ + UINT16 Wep:1; /* Wep data */ + UINT16 MoreData:1; /* More data bit */ + UINT16 PwrMgmt:1; /* Power management bit */ + UINT16 Retry:1; /* Retry status bit */ + UINT16 MoreFrag:1; /* More fragment bit */ + UINT16 FrDs:1; /* From DS indication */ + UINT16 ToDs:1; /* To DS indication */ + UINT16 SubType:4; /* MSDU subtype */ + UINT16 Type:2; /* MSDU type */ + UINT16 Ver:2; /* Protocol version */ +#else + UINT16 Ver:2; /* Protocol version */ + UINT16 Type:2; /* MSDU type, refer to FC_TYPE_XX */ + UINT16 SubType:4; /* MSDU subtype, refer to SUBTYPE_XXX */ + UINT16 ToDs:1; /* To DS indication */ + UINT16 FrDs:1; /* From DS indication */ + UINT16 MoreFrag:1; /* More fragment bit */ + UINT16 Retry:1; /* Retry status bit */ + UINT16 PwrMgmt:1; /* Power management bit */ + UINT16 MoreData:1; /* More data bit */ + UINT16 Wep:1; /* Wep data */ + UINT16 Order:1; /* Strict order expected */ +#endif /* !RT_BIG_ENDIAN */ +} FRAME_CONTROL, *PFRAME_CONTROL; + + +typedef struct GNU_PACKED _HEADER_802_11 { + FRAME_CONTROL FC; + UINT16 Duration; + UCHAR Addr1[6]; + UCHAR Addr2[6]; + UCHAR Addr3[6]; +#ifdef RT_BIG_ENDIAN + UINT16 Sequence:12; + UINT16 Frag:4; +#else + UINT16 Frag:4; + UINT16 Sequence:12; +#endif /* !RT_BIG_ENDIAN */ + UCHAR Octet[0]; +}HEADER_802_11, *PHEADER_802_11; + + +typedef struct GNU_PACKED _HEADER_PS_POLL{ + FRAME_CONTROL FC; + UINT16 AID; + UCHAR Addr1[6]; + UCHAR Addr2[6]; +}HEADER_PS_POLL; + + +#define SLOT_TIME_24G_LONG 20 // 802.11b (DS), 802.11g (ERP), 802.11n +#define SLOT_TIME_24G_SHORT 9 // 802.11g, 802.11n +#define SLOT_TIME_5G 9 // 802.11a, 802.11n, 802.11ac + +#define SIFS_TIME_24G 10 +#define SIFS_TIME_5G 16 + +#define RIFS_TIME 2 //802.11n +#define EIFS_TIME 84/*360*/ +#endif /* _DOT11_BASE_H_ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11ac_vht.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11ac_vht.h new file mode 100644 index 000000000..905a57047 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11ac_vht.h @@ -0,0 +1,665 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + dot11ac_vht.h + + Abstract: + Defined IE/frame structures of 802.11ac (D1.2). + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Shiang Tu 01-11-2012 created for 11ac + */ + +#ifdef DOT11_VHT_AC + + +#ifndef __DOT11AC_VHT_H +#define __DOT11AC_VHT_H + +#include "rtmp_type.h" +#include "dot11_base.h" + +#define IE_VHT_CAP 191 +#define IE_VHT_OP 192 +#define IE_EXT_BSS_LOAD 193 +#define IE_WIDE_BW_CH_SWITCH 194 +#define IE_VHT_TXPWR_ENV 195 +#define IE_CH_SWITCH_WRAPPER 196 +#define IE_AID 197 +#define IE_QUIET_CHANNEL 198 + + +#define BW_SIGNALING_DISABLE 0 +#define BW_SIGNALING_STATIC 1 +#define BW_SIGNALING_DYNAMIC 2 + +/* + IEEE 802.11AC D3.0 sec 8.4.1.50 + Operating Mode field + + ch_width: Channel width + -> 0: 20MHz + 1: 40MHz + 2: 80MHz + 3: 160 or 80+80MHz + Reserved if Rx Nss subfield is 1 + rx_nss: Rx Nss + If the Rx Nss Type subfield is 0, indicate the max number of SS STA can rx. + If the Rx Nss Type subfield is 1, indicate the max number of SS that the STA can receive as a + beamformee in a SU PPDU using a beamforming steering matrix derived from a VHT + compressed beamforming report with Feedback Type subfield indicating MU in the VHT + Compressed Beamforming frames + -> 0: Nss=1 + 1: Nss=2 + ... + 7: Nss=8 + + rx_nss_type: + -> 0: indicate the rx_nss subfield carries the max number of SS that the STA can receive + 1: indicate the rx_nss subfield carries the max number of SS that the STA can receive + as an SU PPDU using a beamforming steering matrix derived from a VHT compressed + Beamforming frame with the Feedback Type subfield indicating MU in the VHT compressed + Beamforming frames. +*/ +typedef struct GNU_PACKED _OPERATING_MODE{ +#ifdef RT_BIG_ENDIAN + UCHAR rx_nss_type:1; + UCHAR rx_nss:3; + UCHAR rsv2:2; + UCHAR ch_width:2; +#else + UCHAR ch_width:2; + UCHAR rsv2:2; + UCHAR rx_nss:3; + UCHAR rx_nss_type:1; +#endif /* RT_BIG_ENDIAN */ +}OPERATING_MODE; + + +/* + IEEE 802.11AC D3.0 sec 8.4.2.168 + Operating Mode Notification element + + Element ID: 199 (IE_OPERATING_MODE_NOTIFY) + Length: 1 +*/ +typedef struct GNU_PACKED _OPERATING_MODE_NOTIFICATION{ + OPERATING_MODE operating_mode; +}OPERATING_MODE_NOTIFICATION; + + +/* + IEEE 802.11AC D2.0, sec 8.4.2.160.2 + VHT Capabilities Info field + + max_mpdu_len: MAximun MPDU Length + ->Indicate the max MPDU length. + 0: 3895 octets(Max A-MSDU length in HT Cap set to 3839) + 1: 7991 octets(Max A-MSDU length in HT Cap set to 7935) + 2: 11454 octets(Max A-MSDU length in HT Cap set to 7935) + 3: reserved + ch_width: Supported Channel Width Set + ->Indicates the channel widths supported by the STA. + 0: the STA does not support either 160 or 80+80 MHz + 1: the STA support 160 MHz + 2: the STA support 160 MHz and 80 + 80 MHz + 3: reserved + rx_ldpc: Rx LDPC + -> Indicates support of receiving LDPC coded packets + 0: not support + 1: support + sgi_80M: Short GI for 80 MHz + -> Indicates short GI support for the reception of VHT+CBW80 packet + 0: not support + 1: support + sgi_160M: Short GI for 160 and 80 + 80 MHz + ->Indicates rx short GI for VHT+(CBW160 and CBW80+80) packet + 0: not support + 1: support + tx_stbc: Tx STBC + -> Indicates support for tx of at least 2x1 STBC + 0: not support + 1: support + rx_stbc: Rx STBC + -> Indicates support for rx of PPDUs using STBC + 0: not support + 1: support 1SS + 2: support 1SS and 2SS + 3: support 1SS, 2SS and 3SS + 4: support 1SS, 2SS, 3SS and 4SS + 5,6,7: reserved + bfer_cap_su: SU Beamformer Capable + ->Indicates support for operation as a single user beamformer + 0: not support + 1: support + bfee_cap_su: SU Beamformee Capable + -> Indicates support for operation as a single user beamformee + 0: not support + 1: support + cmp_st_num_bfer: Compressed Steering Number of Beamformer Antenna Supported + -> Beamformee's capability indicateing the max number of beamformer + antennas the beamformee can support when sending compressed + beamforming feedback + If SU beamformee capable, set to the max value minus 1. + otehrwise, reserved. + num_snd_dimension: Number of Sounding Dimensions + -> Beamformer's capability indicating the number of antennas used for + beamformed transmissions. + If SU beamformer capable, set to value minus 1. + otehrwise, reserved. + bfer_cap_mu: MU Beamformer Capable + -> Indicates support for operation as an MU beamformer + 0: if not supported or if sent by a non-AP STA + 1: supported + bfee_cap_mu: MU Beamformee Capable + -> Indicates support for operation as an MU beamformer + 0: if not supported or if snet by an AP + 1: supported + vht_txop_ps: VHT TXOP PS + -> Indicates whether or not the AP supports VHT TXOP Power Save Mode or + whether or not the STA is in VHT TXOP Power Save Mode + ->When tx by a VHT AP in the VHT Capabilities element included in Beacon, + ProbeResp, AssocResp, and ReassocResp, frames: + 0: if the VHT AP does not support VHT TXOP PS in the BSS. + 1: if the VHT AP support TXOP PS in the BSS. + ->When tx by a VHT non-AP STA in the VHT Capabilities element included + in AssocReq, ReassocReq and ProbReq frames: + 0: if the VHT STA is not in TXOP Power Save Mode. + 1: if the VHT STA is in TXOP Power Save Mode. + htc_vht_cap: +HTC-VHT Capable + -> Indicates whether or not the STA supports receiving an HT Control + field in the VHT format + 0: if not support + 1: if support + max_ampdu_exp: Maximum A-MPDU Length Exponent + -> Indicates the maximum length of A-MPDU pre-EOF padding that the STA + can receive. + ->The length defined by this field is equal to 2^(13 + max_ampdu_exp) -1 + 0~7 : integer in the range of 0 to 7. + vht_link_adapt: VHT Link Adaptation Capable + -> Indicates whether or not the STA support link adaptation using VHT + variant HT Control field. + -> This field is ignored if the _HTC-VHT Capble field is set to 0. + 0: (No Feedback), if the STA does not provide VHT MFB + 2: (Unsolicited), if the STA provides only unsolicited VHT MFB + 3: (Both), if the STA can provide VHT MFB in response to VHT MRQ + and if the STA provides unsolicited VHT MFB. + 1: reserved + rx_ant_consistency: Rx Antenna Pattern Consistency + ->Indicates the possibility of Rx antenna pattern change + 0: if Rx antenna pattern might change during association + 1: if Rx antenna pattern does not change during association + tx_ant_consistency: Tx Antenna Pattern Consistency + ->Indicates the possibility of Tx antenna pattern change + 0: if Tx antenna pattern might change during association + 1: if Tx antenna pattern does not change during association +*/ +typedef struct GNU_PACKED _VHT_CAP_INFO{ +#ifdef RT_BIG_ENDIAN + UINT32 rsv:2; + UINT32 tx_ant_consistency:1; + UINT32 rx_ant_consistency:1; + UINT32 vht_link_adapt:2; + UINT32 max_ampdu_exp:3; + UINT32 htc_vht_cap:1; + UINT32 vht_txop_ps:1; + UINT32 bfee_cap_mu:1; + UINT32 bfer_cap_mu:1; + UINT32 num_snd_dimension:3; + + UINT32 cmp_st_num_bfer:3; + UINT32 bfee_cap_su:1; + UINT32 bfer_cap_su:1; + UINT32 rx_stbc:3; + + UINT32 tx_stbc:1; + UINT32 sgi_160M:1; + UINT32 sgi_80M:1; + UINT32 rx_ldpc:1; + UINT32 ch_width:2; + UINT32 max_mpdu_len:2; +#else + UINT32 max_mpdu_len:2; /* 0: 3895, 1: 7991, 2: 11454, 3: rsv */ + UINT32 ch_width:2; /* */ + UINT32 rx_ldpc:1; + UINT32 sgi_80M:1; + UINT32 sgi_160M:1; + UINT32 tx_stbc:1; + + UINT32 rx_stbc:3; + UINT32 bfer_cap_su:1; + UINT32 bfee_cap_su:1; + UINT32 cmp_st_num_bfer:3; + + UINT32 num_snd_dimension:3; + UINT32 bfer_cap_mu:1; + UINT32 bfee_cap_mu:1; + UINT32 vht_txop_ps:1; + UINT32 htc_vht_cap:1; + UINT32 max_ampdu_exp:3; + UINT32 vht_link_adapt:2; + UINT32 rx_ant_consistency:1; + UINT32 tx_ant_consistency:1; + UINT32 rsv:2; +#endif /* RT_BIG_ENDIAN */ +}VHT_CAP_INFO; + + +/* + IEEE 802.11AC D2.0, sec 8.4.2.160.3 + Rx MCS Map and Tx MCS map, figure 8-401bt + + mcs_ss1: Max MCS for 1SS + mcs_ss2: Max MCS for 2SS + mcs_ss3: Max MCS for 3SS + mcs_ss4: Max MCS for 4SS + mcs_ss5: Max MCS for 5SS + mcs_ss6: Max MCS for 6SS + mcs_ss7: Max MCS for 7SS + mcs_ss8: Max MCS for 8SS + + The 2-bit MAx MCS for n SS field for each number of spatial streams n = 1~8 + is encoded as following: + 0: indicates support for MCS 0~7 + 1: indicates support for MCS 0~8 + 2: indicates support for MCS 0~9 + 3: indicates that n spatial streams is not supported. + Note: some MCSs are not be valid for particular bandwidth and number of + spatial stream combinations. +*/ +#define VHT_MCS_CAP_7 0 +#define VHT_MCS_CAP_8 1 +#define VHT_MCS_CAP_9 2 +#define VHT_MCS_CAP_NA 3 + +typedef struct GNU_PACKED _VHT_MCS_MAP{ +#ifdef RT_BIG_ENDIAN + UINT16 mcs_ss8:2; + UINT16 mcs_ss7:2; + UINT16 mcs_ss6:2; + UINT16 mcs_ss5:2; + UINT16 mcs_ss4:2; + UINT16 mcs_ss3:2; + UINT16 mcs_ss2:2; + UINT16 mcs_ss1:2; +#else + UINT16 mcs_ss1:2; + UINT16 mcs_ss2:2; + UINT16 mcs_ss3:2; + UINT16 mcs_ss4:2; + UINT16 mcs_ss5:2; + UINT16 mcs_ss6:2; + UINT16 mcs_ss7:2; + UINT16 mcs_ss8:2; +#endif /* RT_BIG_ENDIAN */ +}VHT_MCS_MAP; + + +/* + IEEE 802.11AC D2.0, sec 8.4.2.160.3 + VHT Supported MCS Set field, figure 8-401bs + + rx_mcs_map: Rx MCS Map + -> Indicates the maximum MCS that can be received for each number of + spatial streams + See "VHT_MCS_MAP" + rx_high_rate: Rx Highest Supported Data Rate + -> Indicates the maximum data rate that the STA can receive + -> In unit of 1Mb/s where 1 represents 1Mb/s, and incrementing in steps + of 1 Mb/s. + -> If the maximum data rate expressed in Mb/s is not an integer, then + the value is rounded up to the next integer. + tx_mcs_map: Tx MCS Map + tx_high_rate: Tx Highest Supported Data Rate + -> Indicates the maximum data rate that the STA will transmit + -> In unit of 1Mb/s where 1 represents 1Mb/s, and incrementing in steps + of 1 Mb/s. + -> If the maximum data rate expressed in Mb/s is not an integer, then + the value is rounded up to the next integer. +*/ + +// TODO: shiang-6590, check the layout of this data structure!!!! +typedef struct GNU_PACKED _VHT_MCS_SET{ +#ifdef RT_BIG_ENDIAN + UINT16 rsv2:3; + UINT16 tx_high_rate:13; + struct _VHT_MCS_MAP tx_mcs_map; + UINT16 rsv:3; + UINT16 rx_high_rate:13; + struct _VHT_MCS_MAP rx_mcs_map; +#else + struct _VHT_MCS_MAP rx_mcs_map; + UINT16 rx_high_rate:13; + UINT16 rsv:3; + struct _VHT_MCS_MAP tx_mcs_map; + UINT16 tx_high_rate:13; + UINT16 rsv2:3; +#endif /* RT_BIG_ENDIAN */ +}VHT_MCS_SET; + + +/* + IEEE 802.11AC D2.0, sec 8.4.2.160.1 + VHT Capabilities Element structure + + eid: Element ID + 191 (IE_VHT_CAP) + len: Length + 12 + vht_cap: VHT Capabilities Info + ->contains a numner of fields that are used to advertise VHT capabilities + of a VHT STA + mcs_set: VHT supported MCS Set + ->Used to convey the combinations of MCSs and spatial streams a STA + supports for both reception and transmission. +*/ +typedef struct GNU_PACKED _VHT_CAP_IE{ + VHT_CAP_INFO vht_cap; + VHT_MCS_SET mcs_set; +}VHT_CAP_IE; + + +/* + IEEE 802.11AC D2.0, sec 8.4.2.161 + VHT Operation Information field, figure 8-401bv + + The operation of VHT STAs in the BSS is controlled by the HT Operation + element and the VHT Operation element. + + ch_width: Channel Width + -> This field, together with the HT Operation element STA Channel Width + field, defines the BSS operating channel width. + 0: for 20MHz or 40MHz operating channel width + 1: for 80MHz operating channel width + 2: for 160MHz operating channel width + 3: for 80+80MHz operating channel width + 4~255: reserved + center_freq_1: Channel Center Frequency Segment 1 + -> Defines the channel center frequency for an 80 and 160MHz VHT BSS + and the segment 1 channel center frequency for an 80+90MHz VHT BSS. + -> For 80MHZ or 160MHz operating channel width, indicates the channel + center frequency index for the 80MHz or 160MHz channel on which the + VHT BSS operates. + ->For 80+80MHz operating channel width, indicates the channel center + frequency index for the 80MHz channel of frequency segment 1 on + which the VHT BSS operates. + ->Set 0 for 20MHz or 40MHz operating channel width. + + center_freq_2: Channel Center Frequency Segment 2 + -> Defines the seg 2 channel center frequency for an 80+80MHz VHT BSS + ->For a 80+80MHz operating channel width, indicates the channel center + frequency index of the 80MHz channel of frequency segment 2 on + which the VHT BSS operates. Reserved otherwise. +*/ +typedef struct GNU_PACKED _VHT_OP_INFO{ + UINT8 ch_width; + UINT8 center_freq_1; + UINT8 center_freq_2; +}VHT_OP_INFO; + + +/* + IEEE 802.11AC D2.0, sec 8.4.2.161 + VHT Operation element, figure 8-401bu + + The operation of VHT STAs in the BSS is controlled by the HT Operation + element and the VHT Operation element. + + eid: Element ID + 192 (IE_VHT_OP) + len: Length + 5 + vht_op_info: VHT Operation Information + basic_mcs_set: VHT Basic MCS Set +*/ +typedef struct GNU_PACKED _VHT_OP_IE{ + VHT_OP_INFO vht_op_info; + VHT_MCS_MAP basic_mcs_set; +}VHT_OP_IE; + + +/* + IEEE 802.11AC D2.0, sec 8.4.2.163 + Wide Bandwidth Channel Switch element, figure 8-401bx + + included in the Channel Switch Announcement frames. + + new_ch_width: New STA Channel Width + center_freq_1: New Channel Center Frequency Segment 1 + center_freq_2: New Channel Center Frequency Segment 2 + + The definition of upper subfields is the same as "VHT_OP_INFO" +*/ +typedef struct GNU_PACKED _WIDE_BW_CH_SWITCH_ELEMENT{ + UINT8 new_ch_width; + UINT8 center_freq_1; + UINT8 center_freq_2; +}WIDE_BW_CH_SWITCH_ELEMENT; + + +/* + IEEE 802.11AC D2.0, sec 8.4.2.164 + VHT Transmit Power Envelope element +*/ +typedef struct GNU_PACKED _CH_SEG_PAIR{ + UINT8 ch_center_freq; + UINT8 seg_ch_width; +}CH_SEG_PAIR; + + +/* + max_tx_pwr_cnt: + 0: Local Maximum Transmit Power For 20 MHz. + 1: Local Maximum Transmit Power For 20, 40MHz + 2: Local Maximum Transmit Power For 20, 40, 80MHz + 3: Local Maximum Transmit Power For 20, 40, 80, 160/80+80MHz + 4~7: rsv + + max_tx_pwr_interpretation: + 0: EIRP + 1~7: rsv +*/ +#define TX_PWR_INTERPRET_EIRP 0 +typedef struct GNU_PACKED _VHT_TX_PWR_INFO_{ +#ifdef RT_BIG_ENDIAN + UINT8 rsv6:2; + UINT8 max_tx_pwr_interpretation:3; + UINT8 max_tx_pwr_cnt: 3; +#else + UINT8 max_tx_pwr_cnt: 3; + UINT8 max_tx_pwr_interpretation:3; + UINT8 rsv6:2; +#endif +}VHT_TX_PWR_INFO; + + +/* + IEEE 802.11AC D2.0, sec 8.4.2.164 + VHT Transmit Power Envelope element + + max_txpwr: Maximum Transmit Power + -> Define the maximum transmit power limit of the tx bandwidth defined + by the VHT Transmit Power Envelop element. The Maximum Transmit + Power field is a 8 bit 2's complement signed integer in the range of + -64 dBm to 63.5 dBm with a 0.5 dB step. + + NOTE: The following two subfields may repeated as needed. + center_freq_1: Channel Center Frequency Segment + ch_seg_width: Segment Channel Width +*/ +typedef struct GNU_PACKED _VHT_TXPWR_ENV_IE{ + VHT_TX_PWR_INFO tx_pwr_info; + UINT8 tx_pwr_bw[4]; +}VHT_TXPWR_ENV_IE; + + +typedef struct GNU_PACKED _VHT_CONTROL{ +#ifdef RT_BIG_ENDIAN + UINT32 RDG:1; + UINT32 ACConstraint:1; + UINT32 unso_mfb:1; + UINT32 fb_tx_type:1; + UINT32 coding:1; + UINT32 gid_h:3; + UINT32 mfb_snr:6; + UINT32 mfb_bw:2; + UINT32 mfb_mcs:4; + UINT32 mfb_n_sts:3; + UINT32 mfsi_gidl:3; + UINT32 stbc_ind:1; + UINT32 comp_msi:2; + UINT32 mrq:1; + UINT32 rsv:1; + UINT32 vht:1; +#else + UINT32 vht:1; + UINT32 rsv:1; + UINT32 mrq:1; + UINT32 comp_msi:2; + UINT32 stbc_ind:1; + UINT32 mfsi_gidl:3; + UINT32 mfb_n_sts:3; + UINT32 mfb_mcs:4; + UINT32 mfb_bw:2; + UINT32 mfb_snr:6; + UINT32 gid_h:3; + UINT32 coding:1; + UINT32 fb_tx_type:1; + UINT32 unso_mfb:1; + UINT32 ACConstraint:1; + UINT32 RDG:1; +#endif +}VHT_CONTROL; + + +/* + 802.11 AC Draft3.1 - Section 8.3.1.19, Figure 8-29j + + token_num: Sounding Dialog Token Number + Contains a value selected by the beamformer to identify the VHT NDP + Announcment frame. +*/ +typedef struct GNU_PACKED _SNDING_DIALOG_TOKEN { +#ifdef RT_BIG_ENDIAN + UINT8 token_num:6; + UINT8 rsv:2; +#else + UINT8 rsv:2; + UINT8 token_num:6; +#endif /* RT_BIG_ENDIAN */ +}SNDING_DIALOG_TOKEN; + + +/* + 802.11 AC Draft3.1 - Section 8.3.1.19, Figure 8-29k + + aid12: AID12 + the 12 least significiant bits of the AID of a STA expected to + process the following VHT NDP and prepare the sounding + feedback. Equal to 0 if the STA is the AP, mesh STA or STA + that is a member of an IBSS + fb_type: Feedback Type + Indicates the type of feedback requested + 0: SU, 1: MU + nc_idx: Nc_Index + If the fb_type field indicates MU, then Nc Index indicates the + number of columns, Nc, in the compressed Beamforming + Feedback Matrix subfield minus one: + Set to 0 to request Nc=1, + Set to 1 to request Nc=2, + ... + Set to 7 to request Nc=8, + Reserved if the Feedback Type Field indicates SU. +*/ +typedef enum _SNDING_FB_TYPE{ + SNDING_FB_SU = 0, + SNDING_FB_MU = 1, +}SNDING_FB_TYPE; + +typedef struct GNU_PACKED _SNDING_STA_INFO { +#ifdef RT_BIG_ENDIAN + UINT16 nc_idx:3; + UINT16 fb_type:1; + UINT16 aid12:12; +#else + UINT16 aid12:12; + UINT16 fb_type:1; + UINT16 nc_idx:3; +#endif /* RT_BIG_ENDIAN */ +}SNDING_STA_INFO; + + +/* + 802.11 AC Draft3.1 - Section 8.3.1.19, Figure 8-29i + + VHT NDP Announcment frame format + + fc: Frame Control + + duration: Duration + + ra: RA + If the VHT NDPA frame contains only one STA Info field + => the RA field is set to the address of the STA + identified by the AID in the STA info field. + If the VHT NDPA frame contains more than one STA Info field, + => the RA field is set to the broadcast address. + ta: TA + The address of the STA transmitting the VHT NDPA frame. + + token: Sounding Dialog Token, refer to "SNDING_DIALOG_TOKEN" + + sta_info: STA Info 1, ..., STA Info n, refer to "SNDING_STA_INFO" + The VHT NDPA frame contains at least one STA Info field. + +*/ +typedef struct GNU_PACKED _VHT_NDPA_FRAME { + FRAME_CONTROL fc; + USHORT duration; + UCHAR ra[MAC_ADDR_LEN]; + UCHAR ta[MAC_ADDR_LEN]; + SNDING_DIALOG_TOKEN token; + SNDING_STA_INFO sta_info[0]; +} VHT_NDPA_FRAME; + +typedef struct GNU_PACKED _NDPA_PKT{ + USHORT frm_ctrl; + USHORT duration; + UINT8 ra[MAC_ADDR_LEN]; + UINT8 ta[MAC_ADDR_LEN]; + UINT8 snd_seq; +}DNPA_PKT; + +typedef struct GNU_PACKED _PLCP_SERVICE_FIELD{ +#ifdef RT_BIG_ENDIAN + UINT8 rsv7:1; + UINT8 cbw_in_non_ht:2; + UINT8 dyn_bw:1; + UINT8 rsv03:4; +#else + UINT8 rsv03:4; + UINT8 dyn_bw:1; + UINT8 cbw_in_non_ht:2; + UINT8 rsv7:1; +#endif /* RT_BIG_ENDIAN */ +}PLCP_SERVICE_FIELD; + +#endif /* __DOT11AC_VHT_H */ + +#endif /* DOT11_VHT_AC */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11i_wpa.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11i_wpa.h new file mode 100644 index 000000000..fa023da1c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11i_wpa.h @@ -0,0 +1,334 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 5F., No.36 Taiyuan St., Jhubei City, + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2008, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + dot11i_wpa.h + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + +*/ + +#ifndef __DOT11I_WPA_H__ +#define __DOT11I_WPA_H__ + +#include "rtmp_type.h" +#include "dot11_base.h" + +/* The length is the EAPoL-Key frame except key data field. + Please refer to 802.11i-2004 ,Figure 43u in p.78 */ +#define MIN_LEN_OF_EAPOL_KEY_MSG 95 + +/* The related length of the EAPOL Key frame */ +#define LEN_KEY_DESC_NONCE 32 +#define LEN_KEY_DESC_IV 16 +#define LEN_KEY_DESC_RSC 8 +#define LEN_KEY_DESC_ID 8 +#define LEN_KEY_DESC_REPLAY 8 +#define LEN_KEY_DESC_MIC 16 + +#ifdef CONFIG_OWE_SUPPORT +#define LEN_KEY_DESC_MIC_SHA384 24 + +#define LEN_PTK_KCK_SHA384 24 +#define LEN_PTK_KEK_SHA384 32 +#define LEN_TK_SHA384 32 +#define LEN_PTK_SHA384 (LEN_PTK_KCK_SHA384 + LEN_PTK_KEK_SHA384 + LEN_TK_SHA384) +#define LEN_OWE_PTK_SHA384 (LEN_PTK_KCK_SHA384 + LEN_PTK_KEK_SHA384 + LEN_AES_TK) +#endif + +/* EAP Code Type */ +#define EAP_CODE_REQUEST 1 +#define EAP_CODE_RESPONSE 2 +#define EAP_CODE_SUCCESS 3 +#define EAP_CODE_FAILURE 4 + +/* EAPOL frame Protocol Version */ +#define EAPOL_VER 1 +#define EAPOL_VER2 2 + +/* EAPOL-KEY Descriptor Type */ +#define WPA1_KEY_DESC 0xfe +#define WPA2_KEY_DESC 0x02 +#define OSEN_KEY_DESC 0x00 + +/* Key Descriptor Version of Key Information */ +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +#define KEY_DESC_NOT_DEFINED 0 +#define KEY_DESC_OSEN KEY_DESC_NOT_DEFINED +#else +#define KEY_DESC_OSEN 0 +#endif + +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +enum SEC_KEY_DERI_ALG { + SEC_KEY_DERI_SHA1 = 0, + SEC_KEY_DERI_SHA256, + SEC_KEY_DERI_SHA384, + SEC_KEY_DERI_SHA512 +}; +#endif + +#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 +#ifndef CONFIG_SECURITY_IMPROVEMENT_SUPPORT +#define MIN_LEN_OF_RSNIE 18 +#else +#define MIN_LEN_OF_RSNIE 2 +#endif +#define MAX_LEN_GTK 32 +#ifdef WH_EZ_SETUP +#define LEN_MAX_GTK 32 +#endif + +#if defined(DOT11_SAE_SUPPORT) +#define LEN_MAX_WPA2PSK_PSD 64 +#define LEN_MAX_WPA3PSK_PSD 63 +#endif +#define MIN_LEN_GTK 5 + +#define LEN_PMK 32 +#define LEN_PMKID 16 +#define LEN_PMK_NAME 16 + +#define LEN_GMK 32 + +#define LEN_PTK_KCK 16 +#define LEN_PTK_KEK 16 +#define LEN_TK 16 /* The length Temporal key. */ +#define LEN_TKIP_MIC 8 /* The length of TX/RX Mic of TKIP */ +#define LEN_TK2 (2 * LEN_TKIP_MIC) +#define LEN_PTK (LEN_PTK_KCK + LEN_PTK_KEK + LEN_TK + LEN_TK2) + +#define LEN_TKIP_PTK LEN_PTK +#define LEN_AES_PTK (LEN_PTK_KCK + LEN_PTK_KEK + LEN_TK) +#define LEN_TKIP_GTK (LEN_TK + LEN_TK2) +#define LEN_AES_GTK LEN_TK +#define LEN_TKIP_TK (LEN_TK + LEN_TK2) +#define LEN_AES_TK LEN_TK + +#define LEN_WEP64 5 +#define LEN_WEP128 13 + +#define OFFSET_OF_PTK_TK (LEN_PTK_KCK + LEN_PTK_KEK) /* The offset of the PTK Temporal key in PTK */ +#define OFFSET_OF_AP_TKIP_TX_MIC (OFFSET_OF_PTK_TK + LEN_TK) +#define OFFSET_OF_AP_TKIP_RX_MIC (OFFSET_OF_AP_TKIP_TX_MIC + LEN_TKIP_MIC) +#define OFFSET_OF_STA_TKIP_RX_MIC (OFFSET_OF_PTK_TK + LEN_TK) +#define OFFSET_OF_STA_TKIP_TX_MIC (OFFSET_OF_AP_TKIP_TX_MIC + LEN_TKIP_MIC) + +#define LEN_KDE_HDR 6 +#define LEN_NONCE 32 +#define LEN_PN 6 +#define LEN_TKIP_IV_HDR 8 +#define LEN_CCMP_HDR 8 +#define LEN_CCMP_MIC 8 +#define LEN_OUI_SUITE 4 +#define LEN_WEP_TSC 3 +#define LEN_WPA_TSC 6 +#define LEN_WEP_IV_HDR 4 +#define LEN_ICV 4 + +/* It's defined in IEEE Std 802.11-2007 Table 8-4 */ +typedef enum _WPA_KDE_ID +{ + KDE_RESV0, + KDE_GTK, + KDE_RESV2, + KDE_MAC_ADDR, + KDE_PMKID, + KDE_SMK, + KDE_NONCE, + KDE_LIFETIME, + KDE_ERROR, +#ifdef DOT11W_PMF_SUPPORT + KDE_IGTK, /* Defined in IEEE 802.11w/D10.0 */ +#endif /* DOT11W_PMF_SUPPORT */ + KDE_RESV_OTHER +} WPA_KDE_ID; + +/* EAPOL Key Information definition within Key descriptor format */ +typedef struct GNU_PACKED _KEY_INFO +{ +#ifdef RT_BIG_ENDIAN + UCHAR KeyAck:1; + UCHAR Install:1; + UCHAR KeyIndex:2; + UCHAR KeyType:1; + UCHAR KeyDescVer:3; + UCHAR Rsvd:3; + UCHAR EKD_DL:1; /* EKD for AP; DL for STA */ + UCHAR Request:1; + UCHAR Error:1; + UCHAR Secure:1; + UCHAR KeyMic:1; +#else + UCHAR KeyMic:1; + UCHAR Secure:1; + UCHAR Error:1; + UCHAR Request:1; + UCHAR EKD_DL:1; /* EKD for AP; DL for STA */ + UCHAR Rsvd:3; + UCHAR KeyDescVer:3; + UCHAR KeyType:1; + UCHAR KeyIndex:2; + UCHAR Install:1; + UCHAR KeyAck:1; +#endif +} KEY_INFO, *PKEY_INFO; + +/* EAPOL Key descriptor format */ +typedef struct GNU_PACKED _KEY_DESCRIPTER +{ + UCHAR Type; + KEY_INFO KeyInfo; + UCHAR KeyLength[2]; + UCHAR ReplayCounter[LEN_KEY_DESC_REPLAY]; + UCHAR KeyNonce[LEN_KEY_DESC_NONCE]; + UCHAR KeyIv[LEN_KEY_DESC_IV]; + UCHAR KeyRsc[LEN_KEY_DESC_RSC]; + UCHAR KeyId[LEN_KEY_DESC_ID]; + UCHAR KeyMic[LEN_KEY_DESC_MIC]; + UCHAR KeyDataLen[2]; + UCHAR KeyData[0]; +} KEY_DESCRIPTER, *PKEY_DESCRIPTER; + +typedef struct GNU_PACKED _EAPOL_PACKET +{ + UCHAR ProVer; + UCHAR ProType; + UCHAR Body_Len[2]; + KEY_DESCRIPTER KeyDesc; +} EAPOL_PACKET, *PEAPOL_PACKET; + +typedef struct GNU_PACKED _KDE_HDR +{ + UCHAR Type; + UCHAR Len; + UCHAR OUI[3]; + UCHAR DataType; + UCHAR octet[0]; +} KDE_HDR, *PKDE_HDR; + +/*802.11i D10 page 83 */ +typedef struct GNU_PACKED _GTK_KDE +{ +#ifndef RT_BIG_ENDIAN + UCHAR Kid:2; + UCHAR tx:1; + UCHAR rsv:5; + UCHAR rsv1; +#else + UCHAR rsv:5; + UCHAR tx:1; + UCHAR Kid:2; + UCHAR rsv1; +#endif + UCHAR GTK[0]; +} GTK_KDE, *PGTK_KDE; + +/* For WPA1 */ +typedef struct GNU_PACKED _RSNIE { + UCHAR oui[4]; + USHORT version; + UCHAR mcast[4]; + USHORT ucount; + struct GNU_PACKED { + UCHAR oui[4]; + }ucast[1]; +} RSNIE, *PRSNIE; + +/* For WPA2 */ +typedef struct GNU_PACKED _RSNIE2 { + USHORT version; + UCHAR mcast[4]; + USHORT ucount; + struct GNU_PACKED { + UCHAR oui[4]; + }ucast[1]; +} RSNIE2, *PRSNIE2; + +/* AKM Suite */ +typedef struct GNU_PACKED _RSNIE_AUTH { + USHORT acount; + struct GNU_PACKED { + UCHAR oui[4]; + }auth[1]; +} RSNIE_AUTH,*PRSNIE_AUTH; + +/* PMKID List */ +typedef struct GNU_PACKED _RSNIE_PMKID { + USHORT pcount; + struct GNU_PACKED { + UCHAR list[16]; + }pmkid[1]; +} RSNIE_PMKID,*PRSNIE_PMKID; + +typedef union GNU_PACKED _RSN_CAPABILITIES { + struct GNU_PACKED { +#ifdef RT_BIG_ENDIAN + USHORT Rsvd:8; + USHORT MFPC:1; + USHORT MFPR:1; + USHORT GTKSA_R_Counter:2; + USHORT PTKSA_R_Counter:2; + USHORT No_Pairwise:1; + USHORT PreAuth:1; +#else + USHORT PreAuth:1; + USHORT No_Pairwise:1; + USHORT PTKSA_R_Counter:2; + USHORT GTKSA_R_Counter:2; + USHORT MFPR:1; + USHORT MFPC:1; + USHORT Rsvd:8; +#endif + } field; + USHORT word; +} RSN_CAPABILITIES, *PRSN_CAPABILITIES; + +typedef struct GNU_PACKED _EAP_HDR { + UCHAR ProVer; + UCHAR ProType; + UCHAR Body_Len[2]; + UCHAR code; + UCHAR identifier; + UCHAR length[2]; /* including code and identifier, followed by length-2 octets of data */ +} EAP_HDR, *PEAP_HDR; + + +#endif /* __DOT11I_WPA_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11k_rrm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11k_rrm.h new file mode 100644 index 000000000..092af0189 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11k_rrm.h @@ -0,0 +1,375 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2006, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + Abstract: + +***************************************************************************/ + +#ifndef __DOT11K_RRM_H +#define __DOT11K_RRM_H + +#ifdef DOT11K_RRM_SUPPORT +#include "rtmp_type.h" + +#define RRM_CAP_BIT (1 << 12) /* Bit 12 in Capability information field. */ + +#define RRM_PHY_FHSS 1 +#define RRM_PHY_DSSS 2 +#define RRM_PHY_IRBASEBAND 3 +#define RRM_PHY_OFDM 4 +#define RRM_PHY_HRDSSS 5 +#define RRM_PHY_ERP 6 +#define RRM_PHY_HT 7 + +#define IE_RRM_NEIGHBOR_REP 52 +#define IE_BSS_AVAILABLE_AC 67 +#define IE_BSS_AC_DELAY 68 /* Bss Ac Access Dealy Element, Same as WAPI IE. */ +#define IE_RRM_EN_CAP 70 /* 802.11k. RRM Enable Capability element. */ + +#define RRM_MEASURE_REQ 0 +#define RRM_MEASURE_REP 1 +#define RRM_LNK_MEASURE_REQ 2 +#define RRM_LNK_MEASURE_RSP 3 +#define RRM_NEIGHTBOR_REQ 4 +#define RRM_NEIGHTBOR_RSP 5 + +#define RRM_MEASURE_SUBTYPE_BASIC 0 +#define RRM_MEASURE_SUBTYPE_CCA 1 +#define RRM_MEASURE_SUBTYPE_RPI_HISTOGRAM 2 +#define RRM_MEASURE_SUBTYPE_CH_LOAD 3 +#define RRM_MEASURE_SUBTYPE_NOISE_HISTOGRAM 4 +#define RRM_MEASURE_SUBTYPE_BEACON 5 +#define RRM_MEASURE_SUBTYPE_TX_STREAM 9 + +#define RRM_NEIGHBOR_REQ_SSID_SUB_ID 0 +#define RRM_NEIGHBOR_REQ_VENDOR_SUB_ID 221 + +#define RRM_NEIGHBOR_REP_TSF_INFO_SUB_ID 1 +#define RRM_NEIGHBOR_REP_COUNTRY_STRING_SUB_ID 2 +#define RRM_NEIGHBOR_REP_MEASURE_PILOT_TX_SUB_ID 66 +#define RRM_ENABLE_CAPABILTY_SUB_ID 70 +#define RRM_MULTIPLE_BSSID_SUB_ID 71 +#define RRM_VENDOR_SUB_ID 221 + +#define RRM_BCN_REQ_MODE_PASSIVE 0 +#define RRM_BCN_REQ_MODE_ACTIVE 1 +#define RRM_BCN_REQ_MODE_BCNTAB 2 + +#define RRM_BCN_REQ_SUBID_SSID 0 +#define RRM_BCN_REQ_SUBID_BCN_REP_INFO 1 +#define RRM_BCN_REQ_SUBID_RET_DETAIL 2 +#define RRM_BCN_REQ_SUBID_REQUEST 10 +#define RRM_BCN_REQ_SUBID_AP_CH_REP 51 +#define RRM_BCN_REQ_SUBID_VENDOR 221 + +#define RRM_BCN_REP_SUBID_REPORT_FRAME_BODY 1 +#define RRM_BCN_REP_SUBID_VENDOR 221 + +#define RRM_TX_STREAM_SUBID_TRIGGER_REPORT 1 +#define RRM_TX_STREAM_SUBID_VENDOR 221 + +typedef struct GNU_PACKED _RRM_SUBFRAME_INFO +{ + UINT8 SubId; + UINT8 Length; + UINT8 Oct[0]; +} RRM_SUBFRAME_INFO, *PRRM_SUBFRAME_INFO; + +typedef struct GNU_PACKED _RRM_BEACON_REQ_INFO +{ + UINT8 RegulatoryClass; + UINT8 ChNumber; + UINT16 RandomInterval; + UINT16 MeasureDuration; + UINT8 MeasureMode; + UINT8 Bssid[MAC_ADDR_LEN]; + UINT8 Option[0]; +} RRM_BEACON_REQ_INFO, *PRRM_BEACON_REQ_INFO; + +typedef union GNU_PACKED _RRM_BEACON_REP_INFO_FIELD +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT8 ReportFrameType:1; + UINT8 CondensePhyType:7; +#else + UINT8 CondensePhyType:7; + UINT8 ReportFrameType:1; +#endif + } field; + UINT8 word; +} RRM_BEACON_REP_INFO_FIELD, *PRRM_BEACON_REP_INFO_FIELD; + +typedef struct GNU_PACKED _RRM_BEACON_REP_INFO +{ + UINT8 RegulatoryClass; + UINT8 ChNumber; + UINT64 ActualMeasureStartTime; + UINT16 MeasureDuration; + UINT8 RepFrameInfo; + UINT8 RCPI; + UINT8 RSNI; + UINT8 Bssid[MAC_ADDR_LEN]; + UINT8 AnntaId; + UINT32 ParentTSF; + UINT8 Option[0]; +} RRM_BEACON_REP_INFO, *PRRM_BEACON_REP_INFO; + +typedef union GNU_PACKED _RRM_BSSID_INFO +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT32 Reserved:18; + UINT32 FTM:1; + UINT32 VHT:1; + UINT32 HT:1; + UINT32 MobilityDomain:1; + UINT32 ImmediateBA:1; + UINT32 DelayBlockAck:1; + UINT32 RRM:1; + UINT32 APSD:1; + UINT32 Qos:1; + UINT32 SepctrumMng:1; + UINT32 KeyScope:1; + UINT32 Security:1; + UINT32 APReachAble:2; +#else + UINT32 APReachAble:2; + UINT32 Security:1; + UINT32 KeyScope:1; + UINT32 SepctrumMng:1; + UINT32 Qos:1; + UINT32 APSD:1; + UINT32 RRM:1; + UINT32 DelayBlockAck:1; + UINT32 ImmediateBA:1; + UINT32 MobilityDomain:1; + UINT32 HT:1; + UINT32 VHT:1; + UINT32 FTM:1; + UINT32 Reserved:18; +#endif + } field; + UINT32 word; +} RRM_BSSID_INFO, *PRRM_BSSID_INFO; + +typedef struct GNU_PACKED _RRM_NEIGHBOR_REP_INFO +{ + UINT8 Bssid[MAC_ADDR_LEN]; + UINT32 BssidInfo; + UINT8 RegulatoryClass; + UINT8 ChNum; + UINT8 PhyType; + UINT8 Oct[0]; +} RRM_NEIGHBOR_REP_INFO, *RRM_PNEIGHBOR_REP_INFO; + +typedef union GNU_PACKED __RRM_EN_CAP_IE +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT64 :30; + UINT64 AntennaInfoCap:1; + UINT64 BssAvaiableAcmCap:1; + UINT64 BssAvgAccessDelayCap:1; + UINT64 RSNIMeasureCap:1; + UINT64 RCPIMeasureCap:1; + UINT64 NeighReportTSFOffsetCap:1; + UINT64 MeasurePilotTxInfoCap:1; + UINT64 MeasurePilotCap:3; + UINT64 NotOperatingChMaxMeasureDuration:3; + /*UINT64 RRMMibCap:1; */ + UINT64 OperatingChMaxMeasureDuration:3; + UINT64 RRMMibCap:1; + UINT64 APChannelReportCap:1; + UINT64 TriggeredTransmitStreamCap:1; + UINT64 TransmitStreamCap:1; + UINT64 LCIAzimuthCap:1; + UINT64 LCIMeasureCap:1; + UINT64 StatisticMeasureCap:1; + UINT64 NoiseHistogramMeasureCap:1; + UINT64 ChannelLoadMeasureCap:1; + UINT64 FrameMeasureCap:1; + UINT64 BeaconMeasureReportCndCap:1; + UINT64 BeaconTabMeasureCap:1; + UINT64 BeaconActiveMeasureCap:1; + UINT64 BeaconPassiveMeasureCap:1; + UINT64 RepeatMeasureCap:1; + UINT64 ParallelMeasureCap:1; + UINT64 NeighborRepCap:1; + UINT64 LinkMeasureCap:1; +#else + UINT64 LinkMeasureCap:1; + UINT64 NeighborRepCap:1; + UINT64 ParallelMeasureCap:1; + UINT64 RepeatMeasureCap:1; + UINT64 BeaconPassiveMeasureCap:1; + UINT64 BeaconActiveMeasureCap:1; + UINT64 BeaconTabMeasureCap:1; + UINT64 BeaconMeasureReportCndCap:1; + UINT64 FrameMeasureCap:1; + UINT64 ChannelLoadMeasureCap:1; + UINT64 NoiseHistogramMeasureCap:1; + UINT64 StatisticMeasureCap:1; + UINT64 LCIMeasureCap:1; + UINT64 LCIAzimuthCap:1; + UINT64 TransmitStreamCap:1; + UINT64 TriggeredTransmitStreamCap:1; + UINT64 APChannelReportCap:1; + UINT64 RRMMibCap:1; + UINT64 OperatingChMaxMeasureDuration:3; + UINT64 NotOperatingChMaxMeasureDuration:3; + UINT64 MeasurePilotCap:3; + UINT64 MeasurePilotTxInfoCap:1; + UINT64 NeighReportTSFOffsetCap:1; + UINT64 RCPIMeasureCap:1; + UINT64 RSNIMeasureCap:1; + UINT64 BssAvgAccessDelayCap:1; + UINT64 BssAvaiableAcmCap:1; + UINT64 AntennaInfoCap:1; + UINT64 :30; +#endif + } field; + UINT64 word; +} RRM_EN_CAP_IE, *PRRM_EN_CAP_IE; + +typedef union GNU_PACKED _RRM_BSS_AVAILABLE_AC_BITMAP +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT16 :4; + UINT16 AC3:1; + UINT16 AC2:1; + UINT16 AC1:1; + UINT16 AC0:1; + UINT16 UP7:1; + UINT16 UP6:1; + UINT16 UP5:1; + UINT16 UP4:1; + UINT16 UP3:1; + UINT16 UP2:1; + UINT16 UP1:1; + UINT16 UP0:1; +#else + UINT16 UP0:1; + UINT16 UP1:1; + UINT16 UP2:1; + UINT16 UP3:1; + UINT16 UP4:1; + UINT16 UP5:1; + UINT16 UP6:1; + UINT16 UP7:1; + UINT16 AC0:1; + UINT16 AC1:1; + UINT16 AC2:1; + UINT16 AC3:1; + UINT16 :4; +#endif + } field; + UINT16 word; +} RRM_BSS_AVAILABLE_AC_BITMAP, *PRRM_BSS_AVAILABLE_AC_BITMAP; + +typedef struct GNU_PACKED _RRM_BSS_AVAILABLE_AC_INFO +{ + UINT16 AvailableAcBitMap; + UINT8 Oct[0]; +} RRM_BSS_AVAILABLE_AC_INFO, *PRRM_BSS_AVAILABLE_AC_INFO; + +typedef struct GNU_PACKED _RRM_BSS_AC_DELAY_INFO +{ + UINT8 BE_ACDelay; + UINT8 BK_ACDelay; + UINT8 VI_ACDelay; + UINT8 VO_ACDelay; +} RRM_BSS_AC_DELAY_INFO, *PRRM_BSS_AC_DELAY_INFO; + +typedef union GNU_PACKED _RRM_TRANSMIT_MEASURE_TRIGGER_CONDITION +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT8 :5; + UINT8 Delay:1; + UINT8 Consecutive:1; + UINT8 Average:1; +#else + UINT8 Average:1; + UINT8 Consecutive:1; + UINT8 Delay:1; + UINT8 :5; +#endif + } field; + UINT8 word; +} RRM_TRANSMIT_MEASURE_TRIGGER_CONDITION, *PRRM_TRANSMIT_MEASURE_TRIGGER_CONDITION; + +typedef struct GNU_PACKED _RRM_TRANSMIT_MEASURE_DELAY_THRESHOLD +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT8 DealyMsduCnt:6; + UINT8 DealyMsduRange:2; +#else + UINT8 DealyMsduRange:2; + UINT8 DealyMsduCnt:6; +#endif + } field; + UINT8 word; +} RRM_TRANSMIT_MEASURE_DELAY_THRESHOLD, *PRRM_TRANSMIT_MEASURE_DELAY_THRESHOLD; + +typedef struct GNU_PACKED _RRM_TRANSMIT_MEASURE_TRIGGER_REPORT +{ + UINT8 TriggerCondition; + UINT8 AvrErrorThreshold; + UINT8 ConsecutiveErrorThreshold; + UINT8 DelayThreshold; + UINT8 MeasurementCnt; + UINT8 TriggerTimeout; +} RRM_TRANSMIT_MEASURE_TRIGGER_REPORT, *PRRM_TRANSMIT_MEASURE_TRIGGER_REPORT; + +typedef struct GNU_PACKED _RRM_TID +{ + +} RRM_TID, *PRRM_TID; + +typedef struct GNU_PACKED _RRM_TRANSMIT_MEASURE_INFO +{ + UINT16 RandomInterval; + UINT16 MeasureDuration; + UINT8 PeerStaMac[MAC_ADDR_LEN]; + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT8 TID:4; + UINT8 Rev:4; +#else + UINT8 Rev:4; + UINT8 TID:4; +#endif + } TIDField; + UINT8 Bin0Range; + UINT8 Oct[0]; +} RRM_TRANSMIT_MEASURE_INFO, *PRRM_TRANSMIT_MEASURE_INFO; + +#endif /* DOT11K_RRM_SUPPORT */ + +#endif /* __DOT11K_RRM_H */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11n_ht.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11n_ht.h new file mode 100644 index 000000000..9b5534bfa --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11n_ht.h @@ -0,0 +1,353 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + dot11n_ht.h + + Abstract: + Defined IE/frame structures of 802.11n + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- +*/ + +#ifdef DOT11_N_SUPPORT + + +#ifndef _DOT11N_HT_H_ +#define _DOT11N_HT_H_ + +#include "rtmp_type.h" +#include "dot11_base.h" + +/* HT Capability INFO field in HT Cap IE . */ +typedef struct GNU_PACKED _HT_CAP_INFO{ +#ifdef RT_BIG_ENDIAN + UINT16 LSIGTxopProSup:1; + UINT16 Forty_Mhz_Intolerant:1; + UINT16 PSMP:1; + UINT16 CCKmodein40:1; + UINT16 AMsduSize:1; + UINT16 DelayedBA:1; + UINT16 RxSTBC:2; + UINT16 TxSTBC:1; + UINT16 ShortGIfor40:1; + UINT16 ShortGIfor20:1; + UINT16 GF:1; + UINT16 MimoPs:2; + UINT16 ChannelWidth:1; + UINT16 ht_rx_ldpc:1; +#else + UINT16 ht_rx_ldpc:1; + UINT16 ChannelWidth:1; + UINT16 MimoPs:2; /* mimo power safe */ + UINT16 GF:1; /* green field */ + UINT16 ShortGIfor20:1; + UINT16 ShortGIfor40:1; /* for40MHz */ + UINT16 TxSTBC:1; /* 0:not supported, 1:if supported */ + UINT16 RxSTBC:2; + UINT16 DelayedBA:1; + UINT16 AMsduSize:1; /* only support as zero */ + UINT16 CCKmodein40:1; + UINT16 PSMP:1; + UINT16 Forty_Mhz_Intolerant:1; + UINT16 LSIGTxopProSup:1; +#endif /* RT_BIG_ENDIAN */ +} HT_CAP_INFO; + + +/* HT Capability INFO field in HT Cap IE . */ +typedef struct GNU_PACKED _HT_CAP_PARM{ +#ifdef RT_BIG_ENDIAN + UINT8 rsv:3;/*momi power safe */ + UINT8 MpduDensity:3; + UINT8 MaxRAmpduFactor:2; +#else + UINT8 MaxRAmpduFactor:2; + UINT8 MpduDensity:3; + UINT8 rsv:3;/*momi power safe */ +#endif /* RT_BIG_ENDIAN */ +} HT_CAP_PARM, *PHT_CAP_PARM; + + +typedef struct GNU_PACKED _HT_MCS_SET_TX_SUBFIELD{ +#ifdef RT_BIG_ENDIAN + UINT8 TxMCSSetDefined:1; + UINT8 TxRxNotEqual:1; + UINT8 TxMaxStream:2; + UINT8 TxUnqualModulation:1; + UINT8 rsv:3; +#else + UINT8 rsv:3; + UINT8 TxUnqualModulation:1; + UINT8 TxMaxStream:2; + UINT8 TxRxNotEqual:1; + UINT8 TxMCSSetDefined:1; +#endif /* RT_BIG_ENDIAN */ +}HT_MCS_SET_TX_SUBFIELD, *PHT_MCS_SET_TX_SUBFIELD; + + +/* HT Capability INFO field in HT Cap IE . */ +typedef struct GNU_PACKED _HT_MCS_SET{ + UINT8 MCSSet[10]; + UINT8 SupRate[2]; /* unit : 1Mbps */ +#ifdef RT_BIG_ENDIAN + UINT8 rsv:3; + UINT8 MpduDensity:1; + UINT8 TxStream:2; + UINT8 TxRxNotEqual:1; + UINT8 TxMCSSetDefined:1; +#else + UINT8 TxMCSSetDefined:1; + UINT8 TxRxNotEqual:1; + UINT8 TxStream:2; + UINT8 MpduDensity:1; + UINT8 rsv:3; +#endif /* RT_BIG_ENDIAN */ + UINT8 rsv3[3]; +} HT_MCS_SET, *PHT_MCS_SET; + +/* HT Capability INFO field in HT Cap IE . */ +typedef struct GNU_PACKED _EXT_HT_CAP_INFO{ +#ifdef RT_BIG_ENDIAN + UINT16 rsv2:4; + UINT16 RDGSupport:1; /*reverse Direction Grant support */ + UINT16 PlusHTC:1; /*+HTC control field support */ + UINT16 MCSFeedback:2; /*0:no MCS feedback, 2:unsolicited MCS feedback, 3:Full MCS feedback, 1:rsv. */ + UINT16 rsv:5;/*momi power safe */ + UINT16 TranTime:2; + UINT16 Pco:1; +#else + UINT16 Pco:1; + UINT16 TranTime:2; + UINT16 rsv:5;/*momi power safe */ + UINT16 MCSFeedback:2; /*0:no MCS feedback, 2:unsolicited MCS feedback, 3:Full MCS feedback, 1:rsv. */ + UINT16 PlusHTC:1; /*+HTC control field support */ + UINT16 RDGSupport:1; /*reverse Direction Grant support */ + UINT16 rsv2:4; +#endif /* RT_BIG_ENDIAN */ +} EXT_HT_CAP_INFO, *PEXT_HT_CAP_INFO; + + +/* HT Explicit Beamforming Feedback Capable */ +#define HT_ExBF_FB_CAP_NONE 0 +#define HT_ExBF_FB_CAP_DELAYED 1 +#define HT_ExBF_FB_CAP_IMMEDIATE 2 +#define HT_ExBF_FB_CAP_BOTH 3 + +/* HT Beamforming field in HT Cap IE */ +typedef struct GNU_PACKED _HT_BF_CAP{ +#ifdef RT_BIG_ENDIAN + UINT32 rsv:3; + UINT32 ChanEstimation:2; + UINT32 CSIRowBFSup:2; + UINT32 ComSteerBFAntSup:2; + UINT32 NoComSteerBFAntSup:2; + UINT32 CSIBFAntSup:2; + UINT32 MinGrouping:2; + UINT32 ExpComBF:2; + UINT32 ExpNoComBF:2; + UINT32 ExpCSIFbk:2; + UINT32 ExpComSteerCapable:1; + UINT32 ExpNoComSteerCapable:1; + UINT32 ExpCSICapable:1; + UINT32 Calibration:2; + UINT32 ImpTxBFCapable:1; + UINT32 TxNDPCapable:1; + UINT32 RxNDPCapable:1; + UINT32 TxSoundCapable:1; + UINT32 RxSoundCapable:1; + UINT32 TxBFRecCapable:1; +#else + UINT32 TxBFRecCapable:1; + UINT32 RxSoundCapable:1; + UINT32 TxSoundCapable:1; + UINT32 RxNDPCapable:1; + UINT32 TxNDPCapable:1; + UINT32 ImpTxBFCapable:1; + UINT32 Calibration:2; + UINT32 ExpCSICapable:1; + UINT32 ExpNoComSteerCapable:1; + UINT32 ExpComSteerCapable:1; + UINT32 ExpCSIFbk:2; + UINT32 ExpNoComBF:2; + UINT32 ExpComBF:2; + UINT32 MinGrouping:2; + UINT32 CSIBFAntSup:2; + UINT32 NoComSteerBFAntSup:2; + UINT32 ComSteerBFAntSup:2; + UINT32 CSIRowBFSup:2; + UINT32 ChanEstimation:2; + UINT32 rsv:3; +#endif /* RT_BIG_ENDIAN */ +} HT_BF_CAP, *PHT_BF_CAP; + +/* HT antenna selection field in HT Cap IE . */ +typedef struct GNU_PACKED _HT_AS_CAP{ +#ifdef RT_BIG_ENDIAN + UINT8 rsv:1; + UINT8 TxSoundPPDU:1; + UINT8 RxASel:1; + UINT8 AntIndFbk:1; + UINT8 ExpCSIFbk:1; + UINT8 AntIndFbkTxASEL:1; + UINT8 ExpCSIFbkTxASEL:1; + UINT8 AntSelect:1; +#else + UINT8 AntSelect:1; + UINT8 ExpCSIFbkTxASEL:1; + UINT8 AntIndFbkTxASEL:1; + UINT8 ExpCSIFbk:1; + UINT8 AntIndFbk:1; + UINT8 RxASel:1; + UINT8 TxSoundPPDU:1; + UINT8 rsv:1; +#endif /* RT_BIG_ENDIAN */ +} HT_AS_CAP, *PHT_AS_CAP; + + +/* Draft 1.0 set IE length 26, but is extensible.. */ +#define SIZE_HT_CAP_IE 26 +/* The structure for HT Capability IE. */ +typedef struct GNU_PACKED _HT_CAPABILITY_IE{ + HT_CAP_INFO HtCapInfo; + HT_CAP_PARM HtCapParm; +/* HT_MCS_SET HtMCSSet; */ + UCHAR MCSSet[16]; + EXT_HT_CAP_INFO ExtHtCapInfo; + HT_BF_CAP TxBFCap; /* beamforming cap. rt2860c not support beamforming. */ + HT_AS_CAP ASCap; /*antenna selection. */ +} HT_CAPABILITY_IE, *PHT_CAPABILITY_IE; + + +/* field in Addtional HT Information IE . */ +typedef struct GNU_PACKED _ADD_HTINFO{ +#ifdef RT_BIG_ENDIAN + UCHAR SerInterGranu:3; + UCHAR S_PSMPSup:1; + UCHAR RifsMode:1; + UCHAR RecomWidth:1; + UCHAR ExtChanOffset:2; +#else + UCHAR ExtChanOffset:2; + UCHAR RecomWidth:1; + UCHAR RifsMode:1; + UCHAR S_PSMPSup:1; /*Indicate support for scheduled PSMP */ + UCHAR SerInterGranu:3; /*service interval granularity */ +#endif +} ADD_HTINFO, *PADD_HTINFO; + + +typedef struct GNU_PACKED _ADD_HTINFO2{ +#ifdef RT_BIG_ENDIAN + USHORT rsv2:11; + USHORT OBSS_NonHTExist:1; + USHORT rsv:1; + USHORT NonGfPresent:1; + USHORT OperaionMode:2; +#else + USHORT OperaionMode:2; + USHORT NonGfPresent:1; + USHORT rsv:1; + USHORT OBSS_NonHTExist:1; + USHORT rsv2:11; +#endif +} ADD_HTINFO2, *PADD_HTINFO2; + + +/* TODO: Need sync with spec about the definition of StbcMcs. In Draft 3.03, it's reserved. */ +typedef struct GNU_PACKED _ADD_HTINFO3{ +#ifdef RT_BIG_ENDIAN + USHORT rsv:4; + USHORT PcoPhase:1; + USHORT PcoActive:1; + USHORT LsigTxopProt:1; + USHORT STBCBeacon:1; + USHORT DualCTSProtect:1; + USHORT DualBeacon:1; + USHORT StbcMcs:6; +#else + USHORT StbcMcs:6; + USHORT DualBeacon:1; + USHORT DualCTSProtect:1; + USHORT STBCBeacon:1; + USHORT LsigTxopProt:1; /* L-SIG TXOP protection full support */ + USHORT PcoActive:1; + USHORT PcoPhase:1; + USHORT rsv:4; +#endif /* RT_BIG_ENDIAN */ +} ADD_HTINFO3, *PADD_HTINFO3; + +#define SIZE_ADD_HT_INFO_IE 22 +typedef struct GNU_PACKED _ADD_HT_INFO_IE{ + UCHAR ControlChan; + ADD_HTINFO AddHtInfo; + ADD_HTINFO2 AddHtInfo2; + ADD_HTINFO3 AddHtInfo3; + UCHAR MCSSet[16]; /* Basic MCS set */ +} ADD_HT_INFO_IE, *PADD_HT_INFO_IE; + + +/* 802.11n draft3 related structure definitions. */ +/* 7.3.2.60 */ +#define dot11OBSSScanPassiveDwell 20 /* in TU. min amount of time that the STA continously scans each channel when performing an active OBSS scan. */ +#define dot11OBSSScanActiveDwell 10 /* in TU.min amount of time that the STA continously scans each channel when performing an passive OBSS scan. */ +#define dot11BSSWidthTriggerScanInterval 300 /* in sec. max interval between scan operations to be performed to detect BSS channel width trigger events. */ +#define dot11OBSSScanPassiveTotalPerChannel 200 /* in TU. min total amount of time that the STA scans each channel when performing a passive OBSS scan. */ +#define dot11OBSSScanActiveTotalPerChannel 20 /*in TU. min total amount of time that the STA scans each channel when performing a active OBSS scan */ +#define dot11BSSWidthChannelTransactionDelayFactor 5 /* min ratio between the delay time in performing a switch from 20MHz BSS to 20/40 BSS operation and the maximum */ + /* interval between overlapping BSS scan operations. */ +#define dot11BSSScanActivityThreshold 25 /* in %%, max total time that a STA may be active on the medium during a period of */ + /* (dot11BSSWidthChannelTransactionDelayFactor * dot11BSSWidthTriggerScanInterval) seconds without */ + /* being obligated to perform OBSS Scan operations. default is 25(== 0.25%) */ + +typedef struct GNU_PACKED _OVERLAP_BSS_SCAN_IE{ + USHORT ScanPassiveDwell; + USHORT ScanActiveDwell; + USHORT TriggerScanInt; /* Trigger scan interval */ + USHORT PassiveTalPerChannel; /* passive total per channel */ + USHORT ActiveTalPerChannel; /* active total per channel */ + USHORT DelayFactor; /* BSS width channel transition delay factor */ + USHORT ScanActThre; /* Scan Activity threshold */ +}OVERLAP_BSS_SCAN_IE, *POVERLAP_BSS_SCAN_IE; + + +/* 7.3.2.56. 20/40 Coexistence element used in Element ID = 72 = IE_2040_BSS_COEXIST */ +typedef union GNU_PACKED _BSS_2040_COEXIST_IE{ + struct GNU_PACKED { + #ifdef RT_BIG_ENDIAN + UCHAR rsv:3; + UCHAR ObssScanExempGrant:1; + UCHAR ObssScanExempReq:1; + UCHAR BSS20WidthReq:1; + UCHAR Intolerant40:1; + UCHAR InfoReq:1; + #else + UCHAR InfoReq:1; + UCHAR Intolerant40:1; /* Inter-BSS. set 1 when prohibits a receiving BSS from operating as a 20/40 Mhz BSS. */ + UCHAR BSS20WidthReq:1; /* Intra-BSS set 1 when prohibits a receiving AP from operating its BSS as a 20/40MHz BSS. */ + UCHAR ObssScanExempReq:1; + UCHAR ObssScanExempGrant:1; + UCHAR rsv:3; +#endif /* RT_BIG_ENDIAN */ + } field; + UCHAR word; +} BSS_2040_COEXIST_IE, *PBSS_2040_COEXIST_IE; + + +#endif /* _DOT11N_HT_H_ */ +#endif /* DOT11_N_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11r_ft.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11r_ft.h new file mode 100644 index 000000000..2b0667bb7 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11r_ft.h @@ -0,0 +1,343 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + dot11r_ft.h + + Abstract: + Defined status code, IE and frame structures that FT (802.11rD9.0) needed. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Fonchi Wu 12-02-2008 created for 11r soft-AP + */ + + +#ifndef __DOT11R_FT_H +#define __DOT11R_FT_H + +#include "rtmp_type.h" + + +#if defined(DOT11R_FT_SUPPORT) || defined(DOT11K_RRM_SUPPORT) + +/* + Fast BSS transition auth algorithm in 802.11rD9.0 specification. + All other algorithms are defined in rtmp_def.h +*/ +#define FT_MDID_LEN 2 +#define FT_ROKH_ID_LEN 48 +#define FT_R1KH_ID_LEN 6 +#endif /* DOT11R_FT_SUPPORT */ + +#if defined(DOT11R_FT_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) +#define FT_MIC_LEN 16 +#define FT_NONCE_LEN 32 +#endif + +#ifdef DOT11R_FT_SUPPORT +#define FT_CATEGORY_BSS_TRANSITION 6 +#define FT_ACTION_BT_REQ 1 +#define FT_ACTION_BT_RSP 2 +#define FT_ACTION_BT_CONFIRM 3 +#define FT_ACTION_BT_ACK 4 + +/* Status codes defined in 802.11rD9.0 specification. */ +#define FT_STATUS_CODE_RESERVED 27 +#define FT_STATUS_CODE_R0KH_UNREACHABLE 28 +#define FT_STATUS_CODE_INVALID_FME_COUNT 52 +#define FT_STATUS_CODE_INVALID_PMKID 53 +#define FT_STATUS_CODE_INVALID_MDIE 54 +#define FT_STATUS_CODE_INVALID_FTIE 55 +#endif /* DOT11R_FT_SUPPORT */ + +#if defined(DOT11R_FT_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) +/* Information element ID defined in 802.11rD9.0 specification. */ +#define IE_FT_MDIE 54 +#define IE_FT_FTIE 55 +#define IE_FT_TIMEOUT_INTERVAL 56 +#define IE_FT_RIC_DATA 57 +#define IE_FT_RIC_DESCRIPTOR 75 + + +/* RIC Type */ +#define FT_RIC_TYPE_BA 1 + +/* AKM SUITE */ +#define FT_AKM_SUITE_1X 3 +#define FT_AKM_SUITE_PSK 4 +#endif + +#if defined(DOT11R_FT_SUPPORT) || defined(DOT11K_RRM_SUPPORT) +/* +** MDIE: Mobile Domain IE. +*/ +typedef union GNU_PACKED _FT_CAP_AND_POLICY +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT8 :6; + UINT8 RsrReqCap:1; + UINT8 FtOverDs:1; +#else + UINT8 FtOverDs:1; + UINT8 RsrReqCap:1; + UINT8 :6; +#endif + } field; + UINT8 word; +} FT_CAP_AND_POLICY, *PFT_CAP_AND_POLICY; + +typedef struct GNU_PACKED _FT_MDIE +{ + UINT8 MdId[FT_MDID_LEN]; + FT_CAP_AND_POLICY FtCapPlc; +} FT_MDIE, *PFT_MDIE; +#endif /* DOT11R_FT_SUPPORT */ + +#if defined(DOT11R_FT_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) +typedef union GNU_PACKED _FT_MIC_CTR_FIELD +{ + /* + IECnt: contains the number of IEs + that are included int eht MIC calculation. + */ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT16 IECnt:8; + UINT16 :8; +#else + UINT16 :8; + UINT16 IECnt:8; +#endif + } field; + UINT16 word; +} FT_MIC_CTR_FIELD, *PFT_MIC_CTR_FIELD; + +/* +** FTIE: Fast Transition IE. +*/ +typedef struct GNU_PACKED _FT_FTIE +{ + FT_MIC_CTR_FIELD MICCtr; /* 2 Octects. */ + UINT8 MIC[FT_MIC_LEN]; /* 16 Octects. */ + UINT8 ANonce[FT_NONCE_LEN]; /* 32 Octects. */ + UINT8 SNonce[FT_NONCE_LEN]; /* 32 Octects. */ + UINT8 Option[0]; /* 1:R1KHID, 2:GTK, 3:ROKHId, else:Res */ +} FT_FTIE, *PFT_FTIE; +#endif + +#ifdef DOT11R_FT_SUPPORT +/* Sub-element IDs */ +typedef enum _FT_SUB_ELEMENT_ID +{ + FT_R1KH_ID = 1, + FT_GTK, + FT_R0KH_ID, +#ifdef DOT11W_PMF_SUPPORT + FT_IGTK_ID, +#endif /* DOT11W_PMF_SUPPORT */ + FT_RESERVED_ID +} FT_SUB_ELEMENT_ID, *PFT_SUB_ELEMENT_ID; + +typedef struct GNU_PACKED _FT_OPTION_FIELD +{ + UINT8 SubElementId; + UINT8 Len; + UINT8 Oct[0]; +} FT_OPTION_FIELD, *PFT_OPTION_FIELD; + +/* Sub element frame of FTIE. */ +typedef union GNU_PACKED _FT_GTK_KEY_INFO +{ + struct GNU_PACKED{ +#ifdef RT_BIG_ENDIAN + UINT16 :14; + UINT16 KeyId:2; +#else + UINT16 KeyId:2; + UINT16 :14; +#endif + } field; + UINT16 word; +} FT_GTK_KEY_INFO, *PFT_GTK_KEY_INFO; + +typedef struct GNU_PACKED _FT_GTK_SUB_ELEMENT +{ + FT_GTK_KEY_INFO KeyInfo; /* 2 octects. */ + UINT8 KeyLen; + UINT8 RSC[8]; /* Receive seq counter. */ + UINT8 Key[0]; /* 5 to 32 octects. */ +} FT_GTK_SUB_ELEMENT, *PFT_GTK_SUB_ELEMENT; +#endif /* DOT11R_FT_SUPPORT */ + +#if defined(DOT11R_FT_SUPPORT) || defined(DOT11Z_TDLS_SUPPORT) +/* +** Timeout Interval IE. +*/ +typedef enum _FT_TIMEOUT_INTERVAL_TYPE +{ + REASSOC_DEADLINE_INTERVAL = 1, /* TUs */ + KEY_LIFETIME_INTERVAL, /* seconds. */ +#ifdef DOT11W_PMF_SUPPORT + ASSOC_COMEBACK_TIME, /* TUs */ +#endif /* DOT11W_PMF_SUPPORT */ + RESERVED_INTERVAL +} FT_TIMEOUT_INTERVAL_TYPE, *PFT_TIMEOUT_INTERVAL_TYPE; + +typedef struct GNU_PACKED _FT_TIMEOUT_INTERVAL_IE +{ + UINT8 TimeoutIntervalType; + UINT32 TimeoutIntervalValue; +} FT_TIMEOUT_INTERVAL_IE, *PFT_TIMEOUT_INTERVAL_IE; +#endif + +#ifdef DOT11R_FT_SUPPORT +/* ----- Fast BSS Transition Action ----- */ +#define FT_OVER_DS_CATEGORY 0x06 + +typedef struct _FT_OVER_DS_ACTION_REQ_CONFIRM { + + /* must be 6 */ + UCHAR Category; + +#define FT_OVER_DS_ACTION_REQ 0x01 +#define FT_OVER_DS_ACTION_CON 0x03 + /* must be 1 or 3 */ + UCHAR Action; + + /* the STA¡¦s MAC address */ + UCHAR STA_Addr[ETH_ALEN]; + + /* the BSSID value of the target AP */ + UCHAR TargetAP_Addr[ETH_ALEN]; + + /* REQ: RSN, Mobility Domain, or Fast BSS Transition element */ + /* CONFIRM: RSN, Mobility Domain, Fast BSS Transition, or RIC element */ + UCHAR InfoElm[0];/*[1024 - 14]; */ +} GNU_PACKED FT_OVER_DS_ACTION_REQ_FONFIRM; + +typedef struct _FT_OVER_DS_ACTION_RSP_ACK { + + /* must be 6 */ + UCHAR Category; + +#define FT_OVER_DS_ACTION_RSP 0x02 +#define FT_OVER_DS_ACTION_ACK 0x04 + /* must be 2 or 4 */ + UCHAR Action; + + /* the STA¡¦s MAC address */ + UCHAR STA_Addr[ETH_ALEN]; + + /* the BSSID value of the target AP */ + UCHAR TargetAP_Addr[ETH_ALEN]; + + /* FT_STATUS_CODE_R0KH_UNREACHABLE ~ FT_STATUS_CODE_INVALID_FTIE */ + UINT16 StatusCode; + + /* RSP: RSN, Mobility Domain, or Fast BSS Transition element */ + /* ACK: RSN, Mobility Domain, Fast BSS Transition, Timeout, or RIC element */ + UCHAR InfoElm[0];/*[1024 - 16]; */ +} GNU_PACKED FT_OVER_DS_ACTION_RSP_ACK; + + +/* ----- RIC(Resource Information Container) ----- */ + +/* element ID and element length */ +#define FT_ELM_HDR_LEN 2 + +/* Resource Information Container Data information element */ +typedef struct _FT_ELM_RIC_DATA_INFO { + +#define FT_ELM_ID_RIC_DATA_INFO 57 + UCHAR ElmID; + +#define FT_ELM_LEN_RIC_DATA_INFO 4 + UCHAR ElmLen; + + /* + RDIE: RIC Data information Element + An arbitrary 8-bit value, chosen by the resource requestor to + uniquely identify the RDIE within the RIC. + */ + UCHAR RDIE_Identifier; + + /* + Resource Descriptor Count + Number of alternative Resource Descriptors that follow this RDIE. + */ + UCHAR RD_Count; + + /* the result of the request */ + /* FT_STATUS_CODE_R0KH_UNREACHABLE ~ FT_STATUS_CODE_INVALID_FTIE */ + UINT16 StatusCode; + +} GNU_PACKED FT_ELM_RIC_DATA_INFO; + +/* Resource Information Container descriptor information element */ +#define FT_ELM_RIC_DESCP_INFO_LEN (FT_ELM_HDR_LEN+7) + +typedef struct GNU_PACKED _FT_RIC_DESCP_BLOCK_ACK { + UINT16 BaParm; /* Block Ack Parameter Set */ + UINT16 TimeOutValue; /* Block Ack Timeout Value */ + UINT16 BaStartSeq; /* Block Ack Starting Sequence Control */ +} FT_RIC_DESCP_BLOCK_ACK; + +typedef struct GNU_PACKED _FT_ELM_RIC_DESCP_INFO { +#define FT_ELM_ID_RIC_DESCP_INFO 75 + UCHAR ElmID; + +#define FT_ELM_LEN_RIC_DESCP_INFO_RSC_BLOCK_ACK 7 + UCHAR ElmLen; + +#define FT_ELM_RIC_DESCP_INFO_RSC_TYPE_BLOCK_ACK 1 + UCHAR ResourceType; + + /* negotiated resources */ + /* + For FT_ELM_RIC_DESCP_INFO_RSC_TYPE_BLOCK_ACK: + Block Ack Parameter Set (2B), + Block Ack Timeout Value (2B), and + Block Ack Starting Sequence Control (2B) + */ + UCHAR Container[6]; + +} FT_ELM_RIC_DESCP_INFO; + +typedef struct GNU_PACKED __FT_ACTION +{ + UINT8 Category; + UINT8 Action; + UINT8 StaMac[MAC_ADDR_LEN]; + UINT8 TargetApAddr[MAC_ADDR_LEN]; + UINT8 Oct[0]; +} FT_ACTION, *PFT_ACTION; + +typedef struct GNU_PACKED __FT_RRB +{ + UINT8 RemoteFrTyp; + UINT8 FTPktType; + UINT16 FTActLen; + UINT8 APAdr[MAC_ADDR_LEN]; + UINT8 Oct[0]; +} FT_RRB, *PFT_RRB; +#endif /* DOT11R_FT_SUPPORT */ + +#endif /* __DOT11R_FT_H */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11u_interworking.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11u_interworking.h new file mode 100644 index 000000000..d80f251f6 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11u_interworking.h @@ -0,0 +1,117 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 5F., No.36 Taiyuan St., Jhubei City, + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2011, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + dot11u_hotspot.h + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + +*/ + +#ifndef __DOT11U_HOTSPOT_H__ +#define __DOT11U_HOTSPOT_H__ + +#include "rtmp_type.h" + +/* unit ms */ +#define dot11GASResponseTimeout 5120 +#define dotGASResponseBufferingTime 5120 + + +enum GAS_ACTION_FIELD { + ACTION_GAS_INIT_REQ = 10, + ACTION_GAS_INIT_RSP = 11, + ACTION_GAS_CB_REQ = 12, + ACTION_GAS_CB_RSP = 13, +}; + +typedef struct GNU_PACKED _GAS_FRAME +{ + HEADER_802_11 Hdr; + UCHAR Category; + union { + struct { + UCHAR Action; + UCHAR DialogToken; + /* + * Following are advertisement protocol element, + * query request length, and query request + */ + UCHAR Variable[0]; + } GNU_PACKED GAS_INIT_REQ; + struct { + UCHAR Action; + UCHAR DialogToken; + UINT16 StatusCode; + UINT16 GASComebackDelay; + /* + * Following are advertisement protocol element, + * query response length, and query response(optional) + */ + UCHAR Variable[0]; + } GNU_PACKED GAS_INIT_RSP; + struct { + UCHAR Action; + UCHAR DialogToken; + } GNU_PACKED GAS_CB_REQ; + struct { + UCHAR Action; + UCHAR DialogToken; + UINT16 StatusCode; + UCHAR GASRspFragID; + UINT16 GASComebackDelay; + /* + * Following are advertisment protocol element, + * query response length, and query response(optional) + */ + UCHAR Variable[0]; + } GNU_PACKED GAS_CB_RSP; + }u; +}GAS_FRAME, *PGAS_FRAME; + + +/* Status Code */ +enum DOT11U_STATUS_CODE { + ADVERTISEMENT_PROTOCOL_NOT_SUPPORTED = 59, + UNSPECIFIED_FAILURE = 60, + RESPONSE_NOT_RECEIVED_FROM_SERVER = 61, + TIMEOUT = 62, + QUERY_RESPONSE_TOO_LARGE = 63, + REQUEST_REFUSED_HOME_NETWORK_NOT_SUPPORT = 64, + SERVER_UNREACHABLE = 65, + REQUEST_REFUSED_PERMISSIONS_RECEIVED_FROM_SSPN = 67, + REQUEST_REFUSED_AP_NOT_SUPPORT_UNAUTH_ACCESS = 68, + TRANSMISSION_FAILURE = 79, +}; + +/* Advertismenet Protocol ID definitions */ +enum DOT11U_ADVERTISMENT_PROTOCOL_ID { + ACCESS_NETWORK_QUERY_PROTOCOL = 0, + MIH_INFORMATION_SERVICE = 1, + MIH_COMMAND_AND_EVENT_SERVICES_CAPBILITY_DISCOVERY = 2, + EMERGENCY_ALERT_SYSTEM = 3, + VENDOR_SPECIFIC = 221 +}; + +struct anqp_frame { + UINT16 info_id; + UINT16 length; + char variable[0]; +} __packed; +#endif /* __DOT11U_HOTSPOT_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11v_wnm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11v_wnm.h new file mode 100644 index 000000000..3d6c9cb5a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11v_wnm.h @@ -0,0 +1,106 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 5F., No.36 Taiyuan St., Jhubei City, + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2011, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + dot11v_wnm.h + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + +*/ + +#ifndef __DOT11V_WNM_H__ +#define __DOT11V_WNM_H__ + +#define WNM_BSS_PERFERENCE_SUBIE 3 +#define WNM_BSS_TERMINATION_SUBIE 4 + + +enum WNM_ACTION_FIELD { + EVENT_REQUEST, + EVENT_REPORT, + DIAGNOSTIC_REQ, + DIAGNOSTIC_REPORT, + LOCATION_CONF_REQ, + LOCATION_CONF_RSP, + BSS_TRANSITION_QUERY, + BSS_TRANSITION_REQ, + BSS_TRANSITION_RSP, + FMS_REQ, + FMS_RSP, + COLLOCATED_INTERFERENCE_REQ, + COLLOCATED_INTERFERENCE_REPORT, + TFS_REQ, + TFS_RSP, + TFS_NOTIFY, + WNM_SLEEP_MODE_REQ, + WNM_SLEEP_MODE_RSP, + TIM_BROADCAST_REQ, + TIM_BROADCAST_RSP, + QOS_TRAFFIC_CAPABILITY_UPDATE, + CHANNEL_USAGE_REQ, + CHANNEL_USAGE_RSP, + DMS_REQ, + DMS_RSP, + TIMING_MEASUREMENT_REQ, + WNM_NOTIFICATION_REQ, + WNM_NOTIFICATION_RSP, +}; + +typedef struct GNU_PACKED _WNM_FRAME +{ + HEADER_802_11 Hdr; + UCHAR Category; + union { + struct { + UCHAR Action; + UCHAR DialogToken; + UCHAR Variable[0]; + } GNU_PACKED BTM_QUERY; + + struct { + UCHAR Action; + UCHAR DialogToken; + UCHAR Variable[0]; + } GNU_PACKED BTM_REQ; + + struct { + UCHAR Action; + UCHAR DialogToken; + UCHAR Variable[0]; + } GNU_PACKED BTM_RSP; + + struct { + UCHAR Action; + UCHAR DialogToken; + UCHAR Type; + UCHAR Variable[0]; + } GNU_PACKED WNM_NOTIFY_REQ; + + struct { + UCHAR Action; + UCHAR DialogToken; + UCHAR RespStatus; + UCHAR Variable[0]; + } GNU_PACKED WNM_NOTIFY_RSP; + }u; +} WNM_FRAME, *PWNM_FRAME; + +void PeerWNMAction(IN struct _RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +#endif /* __DOT11V_WNM_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11w_pmf.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11w_pmf.h new file mode 100644 index 000000000..e776dadc5 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/dot11w_pmf.h @@ -0,0 +1,112 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + dot11w_pmf.h + + Abstract: + Defined status code, IE and frame structures that PMF (802.11w) needed. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + Albert Yang 4-02-2009 created for IEEE802.11W PMF + */ + +#ifndef __DOT11W_PMF_H +#define __DOT11W_PMF_H + +#ifdef DOT11W_PMF_SUPPORT + +#include "rtmp_type.h" + + +#define LEN_PMF_MMIE 16 +#define PMF_CIPHER_SUITE_LEN 4 +#define LEN_PMF_BIP_AAD_HDR 20 +#define LEN_PMF_BIP_MIC 8 +#define LEN_PMF_IGTK_KDE 24 + +/* PMF Action filed value */ +#define PMF_ACTION_QA_QUERY_REQ 0 +#define PMF_ACTION_QA_QUERY_RESP 1 + +/* Information element ID defined in 802.11w specification. */ +#define IE_PMF_MMIE 76 + +/* The definition in IEEE 802.11w - Table 7-32 Cipher suite selectors */ +extern UCHAR OUI_PMF_BIP_CIPHER[]; + +/* The definition in IEEE 802.11w - Table 7-34 AKM suite selectors */ +extern UCHAR OUI_PMF_8021X_AKM[]; +extern UCHAR OUI_PMF_PSK_AKM[]; + +/* The Key ID filed */ +typedef union GNU_PACKED _PMF_IGTK_KEY_ID +{ + struct GNU_PACKED{ +#ifdef RT_BIG_ENDIAN + UINT16 :4; + UINT16 KeyId:12; +#else + UINT16 KeyId:12; + UINT16 :4; +#endif + } field; + UINT16 word; +} PMF_IGTK_KEY_ID, *PPMF_IGTK_KEY_ID; + +/* The SubIE of Fast BSS transition information element */ +typedef struct GNU_PACKED _FT_IGTK_SUB_ELEMENT +{ + UINT8 KeyID[2]; /* indicates the value of the BIP key ID */ + UINT8 IPN[6]; /* indicates the receive sequence counter for the IGTK being installed */ + UINT8 KeyLen; /* the length of IGTK in octets */ + UINT8 Key[24]; /* The length of the resulting AES-Keywrapped IGTK in the Key field */ +} FT_IGTK_SUB_ELEMENT, *PFT_IGTK_SUB_ELEMENT; + +/* Management MIC information element */ +typedef struct GNU_PACKED _PMF_MMIE +{ + UINT8 KeyID[2]; /* identifies the IGTK used to compute the MIC */ + UINT8 IPN[6]; /* indicates the receive sequence counter for the IGTK being installed */ + UINT8 MIC[LEN_PMF_BIP_MIC]; /* The length of the resulting AES-Keywrapped IGTK in the Key field */ +} PMF_MMIE, *PPMF_MMIE; + +/* IGTK KDE format */ +typedef struct GNU_PACKED _PMF_IGTK_KDE +{ + UINT8 KeyID[2]; /* identifies the IGTK used to compute the MIC */ + UINT8 IPN[6]; /* indicates the receive sequence counter for the IGTK being installed */ + UINT8 IGTK[0]; /* The length of the IGTK */ +} PMF_IGTK_KDE, *PPMF_IGTK_KDE; + + +/* ===================== + * PMF SA Query Action + * ===================== */ +typedef struct GNU_PACKED _PMF_SA_QUERY_ACTION +{ + UCHAR Category; + UCHAR Action; + + /* a 16-bit non-negative counter value */ + UINT8 TransactionID[2]; +} PMF_SA_QUERY_ACTION, *PPMF_SA_QUERY_ACTION; + +#endif /* DOT11W_PMF_SUPPORT */ + +#endif /* __DOT11W_PMF_H */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/drs_extr.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/drs_extr.h new file mode 100644 index 000000000..34d3b67d0 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/drs_extr.h @@ -0,0 +1,453 @@ +/**************************************************************************** + * 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__ + +#define SWIFT_TRAIN_UP 1 +#define CCK_TRAIN_UP 1 + +struct _RTMP_ADAPTER; +struct _MAC_TABLE_ENTRY; + +#define TX_RATE_INDEX_1 0 +#define TX_RATE_INDEX_2 1 +#define TX_RATE_INDEX_3 2 +#define TX_RATE_INDEX_4 3 +#define TX_RATE_INDEX_5 4 +#define TX_RATE_INDEX_678 5 +#define TX_COUNTER_OVERFLOW 0xFF + +#define RA_PROBING_ABORT_TX_CNT 15 +#define RA_PROBING_ABORT_CCK_TX_CNT 3 + +typedef struct _RTMP_TX_RATE { + UCHAR mode; + UCHAR bw; + UCHAR mcs; + UCHAR nss; + UCHAR sgi; + UCHAR stbc; +}RTMP_TX_RATE; + + +typedef struct _RTMP_RA_LEGACY_TB +{ + UCHAR ItemNo; +#ifdef RT_BIG_ENDIAN + UCHAR Rsv2:1; + UCHAR Mode:3; + UCHAR BW:2; + UCHAR ShortGI:1; + UCHAR STBC:1; +#else + UCHAR STBC:1; + UCHAR ShortGI:1; + UCHAR BW:2; + UCHAR Mode:3; + UCHAR Rsv2:1; +#endif + UCHAR CurrMCS; + UCHAR TrainUp; + UCHAR TrainDown; +} RTMP_RA_LEGACY_TB; + +#define PTX_RA_LEGACY_ENTRY(pTable, idx) ((RTMP_RA_LEGACY_TB *)&(pTable[(idx+1)*5])) + + +#ifdef NEW_RATE_ADAPT_SUPPORT +typedef struct _RTMP_RA_GRP_TB +{ + UCHAR ItemNo; +#ifdef RT_BIG_ENDIAN + UCHAR Rsv2:1; + UCHAR Mode:3; + UCHAR BW:2; + UCHAR ShortGI:1; + UCHAR STBC:1; +#else + UCHAR STBC:1; + UCHAR ShortGI:1; + UCHAR BW:2; + UCHAR Mode:3; + UCHAR Rsv2:1; +#endif + UCHAR CurrMCS; + UCHAR TrainUp; + UCHAR TrainDown; + UCHAR downMcs; + UCHAR upMcs3; + UCHAR upMcs2; + UCHAR upMcs1; + UCHAR dataRate; +} RTMP_RA_GRP_TB; + +#ifdef MT_MAC +typedef struct _MT_TX_COUNTER +{ + UINT32 TxCount; + UINT32 TxFailCount; + UINT16 Rate1TxCnt; + UINT16 Rate1FailCnt; + UCHAR Rate2TxCnt; + UCHAR Rate3TxCnt; + UCHAR Rate4TxCnt; + UCHAR Rate5TxCnt; + UCHAR RateIndex; +} MT_TX_COUNTER; +#endif /* MT_MAC */ + +#define PTX_RA_GRP_ENTRY(pTable, idx) ((RTMP_RA_GRP_TB *)&(pTable[(idx+1)*10])) +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#define RATE_TABLE_SIZE(pTable) ((pTable)[0]) /* Byte 0 is number of rate indices */ +#define RATE_TABLE_INIT_INDEX(pTable) ((pTable)[1]) /* Byte 1 is initial rate index */ + + +/* Values of LastSecTxRateChangeAction */ +#define RATE_NO_CHANGE 0 /* No change in rate */ +#define RATE_UP 1 /* Trying higher rate or same rate with different BF */ +#define RATE_DOWN 2 /* Trying lower rate */ + +enum RATE_ADAPT_ALG{ + RATE_ALG_LEGACY = 1, + RATE_ALG_GRP = 2, + RATE_ALG_AGS = 3, + RATE_ALG_MAX_NUM +}; + + +typedef enum { + RAL_OLD_DRS, + RAL_NEW_DRS, + RAL_QUICK_DRS +}RA_LOG_TYPE; + +#define HIGH_TRAFFIC_THRESHOLD 15 +#define RATE_ADAPT_HOLD_TIME 30 + +enum RATE_ADAPT_TRAFFIC_LOADING { + RA_INIT_STATE, + ZERO_TRAFFIC, + LOW_TRAFFIC, + HIGH_TRAFFIC, +}; + +#define RATE_ADAPT_HOLD_TX_RATE(_traffic_loading_old, _traffic_loading_new, _buffer_time) \ + ((_traffic_loading_old == HIGH_TRAFFIC || _traffic_loading_old == LOW_TRAFFIC) && (_traffic_loading_new == ZERO_TRAFFIC)) || \ + ((_traffic_loading_new == ZERO_TRAFFIC) && (_buffer_time > 0)) + +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 RateSwitchTableAdapt11B[]; +extern UCHAR RateSwitchTableAdapt11G[]; +extern UCHAR RateSwitchTableAdapt11BG[]; +extern UCHAR RateSwitchTableAdapt11N1S[]; +extern UCHAR RateSwitchTableAdapt11N2S[]; +#ifdef MULTI_CLIENT_SUPPORT +extern UCHAR RateSwitchTableAdapt11N1SForMultiClients[]; +extern UCHAR RateSwitchTableAdapt11N2SForMultiClients[]; +#endif +#ifdef INTERFERENCE_RA_SUPPORT +extern UCHAR RateSwitchTableAdapt11N1SForInterference[]; +extern UCHAR RateSwitchTableAdapt11N2SForInterference[]; +#endif +extern UCHAR RateSwitchTableAdapt11N3S[]; + +#define PER_THRD_ADJ 1 + +/* ADAPT_RATE_TABLE - true if pTable is one of the Adaptive Rate Switch tables */ +#ifdef DOT11_VHT_AC +extern UCHAR RateTableVht1S[]; +extern UCHAR RateTableVht1S_MCS9[]; +extern UCHAR RateTableVht2S[]; +extern UCHAR RateTableVht2S_MCS7[]; +extern UCHAR RateTableVht2S_BW20[]; +extern UCHAR RateTableVht2S_BW40[]; + +#define ADAPT_RATE_TABLE(pTable) ((pTable)==RateSwitchTableAdapt11B || \ + (pTable)==RateSwitchTableAdapt11G || \ + (pTable)==RateSwitchTableAdapt11BG || \ + (pTable)==RateSwitchTableAdapt11N1S ||\ + (pTable)==RateSwitchTableAdapt11N2S ||\ + (pTable)==RateSwitchTableAdapt11N3S ||\ + (pTable)==RateTableVht1S ||\ + (pTable)==RateTableVht1S_MCS9 ||\ + (pTable)==RateTableVht2S || \ + (pTable)==RateTableVht2S_MCS7 || \ + (pTable)==RateTableVht2S_BW20 ||\ + (pTable)==RateTableVht2S_BW40) +#else +#if defined(INTERFERENCE_RA_SUPPORT) && defined(MULTI_CLIENT_SUPPORT) +#define ADAPT_RATE_TABLE(pTable) ((pTable)==RateSwitchTableAdapt11B || \ + (pTable)==RateSwitchTableAdapt11G || \ + (pTable)==RateSwitchTableAdapt11BG || \ + (pTable)==RateSwitchTableAdapt11N1S || \ + (pTable)==RateSwitchTableAdapt11N2S || \ + (pTable)==RateSwitchTableAdapt11N1SForMultiClients ||\ + (pTable)==RateSwitchTableAdapt11N2SForMultiClients ||\ + (pTable)==RateSwitchTableAdapt11N1SForInterference ||\ + (pTable)==RateSwitchTableAdapt11N2SForInterference ||\ + (pTable)==RateSwitchTableAdapt11N3S) +#elif defined(MULTI_CLIENT_SUPPORT) +#define ADAPT_RATE_TABLE(pTable) ((pTable)==RateSwitchTableAdapt11B || \ + (pTable)==RateSwitchTableAdapt11G || \ + (pTable)==RateSwitchTableAdapt11BG || \ + (pTable)==RateSwitchTableAdapt11N1S || \ + (pTable)==RateSwitchTableAdapt11N2S || \ + (pTable)==RateSwitchTableAdapt11N1SForMultiClients ||\ + (pTable)==RateSwitchTableAdapt11N2SForMultiClients ||\ + (pTable)==RateSwitchTableAdapt11N3S) +#elif defined(INTERFERENCE_RA_SUPPORT) +#define ADAPT_RATE_TABLE(pTable) ((pTable)==RateSwitchTableAdapt11B || \ + (pTable)==RateSwitchTableAdapt11G || \ + (pTable)==RateSwitchTableAdapt11BG || \ + (pTable)==RateSwitchTableAdapt11N1S || \ + (pTable)==RateSwitchTableAdapt11N2S || \ + (pTable)==RateSwitchTableAdapt11N1SForInterference ||\ + (pTable)==RateSwitchTableAdapt11N2SForInterference ||\ + (pTable)==RateSwitchTableAdapt11N3S) +#else +#define ADAPT_RATE_TABLE(pTable) ((pTable)==RateSwitchTableAdapt11B || \ + (pTable)==RateSwitchTableAdapt11G || \ + (pTable)==RateSwitchTableAdapt11BG || \ + (pTable)==RateSwitchTableAdapt11N1S || \ + (pTable)==RateSwitchTableAdapt11N2S || \ + (pTable)==RateSwitchTableAdapt11N3S) +#endif +#endif /* DOT11_VHT_AC */ +#endif /* NEW_RATE_ADAPT_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ + + +/* FUNCTION */ +VOID MlmeGetSupportedMcs( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR *pTable, + OUT CHAR mcs[]); + +UCHAR MlmeSelectTxRate( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN CHAR mcs[], + IN CHAR Rssi, + IN CHAR RssiOffset); + +VOID MlmeClearTxQuality(struct _MAC_TABLE_ENTRY *pEntry); +VOID MlmeClearAllTxQuality(struct _MAC_TABLE_ENTRY *pEntry); +VOID MlmeDecTxQuality(struct _MAC_TABLE_ENTRY *pEntry, UCHAR rateIndex); +USHORT MlmeGetTxQuality(struct _MAC_TABLE_ENTRY *pEntry, UCHAR rateIndex); +VOID MlmeSetTxQuality( + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR rateIndex, + IN USHORT txQuality); + + + +VOID MlmeOldRateAdapt( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR CurrRateIdx, + IN UCHAR UpRateIdx, + IN UCHAR DownRateIdx, + IN ULONG TrainUp, + IN ULONG TrainDown, + IN ULONG TxErrorRatio); + +VOID MlmeRestoreLastRate( + IN struct _MAC_TABLE_ENTRY *pEntry); + +VOID MlmeCheckRDG( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry); + +VOID RTMPSetSupportMCS( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR OpMode, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, +#ifdef DOT11_VHT_AC + IN UCHAR vht_cap_len, + IN VHT_CAP_IE *vht_cap, +#endif /* DOT11_VHT_AC */ + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen); + +#ifdef NEW_RATE_ADAPT_SUPPORT +VOID MlmeSetMcsGroup(struct _RTMP_ADAPTER *pAd, struct _MAC_TABLE_ENTRY *pEnt); + +UCHAR MlmeSelectUpRate( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN RTMP_RA_GRP_TB *pCurrTxRate); + +UCHAR MlmeSelectDownRate( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR CurrRateIdx); + +VOID MlmeGetSupportedMcsAdapt( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR mcs23GI, + OUT CHAR mcs[]); + +UCHAR MlmeSelectTxRateAdapt( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN CHAR mcs[], + IN CHAR Rssi, + IN CHAR RssiOffset); + +BOOLEAN MlmeRAHybridRule( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN RTMP_RA_GRP_TB *pCurrTxRate, + IN ULONG NewTxOkCount, + IN ULONG TxErrorRatio); + +VOID MlmeNewRateAdapt( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR UpRateIdx, + IN UCHAR DownRateIdx, + IN ULONG TrainUp, + IN ULONG TrainDown, + IN ULONG TxErrorRatio); + +#ifdef MT_MAC +VOID NewRateAdaptMT( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR UpRateIdx, + IN UCHAR DownRateIdx, + IN UCHAR TrainUp, + IN UCHAR TrainDown, + IN UCHAR Rate1ErrorRatio, + IN UCHAR HwAggRateIndex); +#endif /* MT_MAC */ +#ifdef DBG +INT Set_PerThrdAdj_Proc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_LowTrafficThrd_Proc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_TrainUpRule_Proc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_TrainUpRuleRSSI_Proc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_TrainUpLowThrd_Proc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_TrainUpHighThrd_Proc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_RateTable_Proc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* DBG */ +#ifdef AGS_SUPPORT +INT Show_AGS_Proc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + +#ifdef CONFIG_AP_SUPPORT +VOID ApMlmeDynamicTxRateSwitchingAGS( + IN RTMP_ADAPTER *pAd, + IN INT idx); + +VOID ApQuickResponeForRateUpExecAGS( + IN RTMP_ADAPTER *pAd, + IN INT idx); +#endif /* CONFIG_AP_SUPPORT */ +#endif /* AGS_SUPPORT */ + +#ifdef MT_MAC +VOID DynamicTxRateSwitchingAdaptMT(struct _RTMP_ADAPTER *pAd, UINT idx); +VOID QuickResponeForRateUpExecAdaptMT(struct _RTMP_ADAPTER *pAd, UINT idx); +VOID DynamicRaInterval(struct _RTMP_ADAPTER *pAd); +#endif /* MT_MAC */ + +#ifdef CONFIG_AP_SUPPORT +VOID APMlmeDynamicTxRateSwitchingAdapt(struct _RTMP_ADAPTER *pAd, UINT idx); +VOID APQuickResponeForRateUpExecAdapt(struct _RTMP_ADAPTER *pAd, UINT idx); +#endif /* CONFIG_AP_SUPPORT */ + +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +VOID APMlmeDynamicTxRateSwitching( + IN struct _RTMP_ADAPTER *pAd); + +VOID APQuickResponeForRateUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID APMlmeSetTxRate( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN RTMP_RA_LEGACY_TB *pTxRate); +#endif /* CONFIG_AP_SUPPORT */ + + +VOID MlmeRAInit(struct _RTMP_ADAPTER *pAd, struct _MAC_TABLE_ENTRY *pEntry); +VOID MlmeNewTxRate(struct _RTMP_ADAPTER *pAd, struct _MAC_TABLE_ENTRY *pEntry); + +VOID MlmeRALog( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN RA_LOG_TYPE raLogType, + IN ULONG TxErrorRatio, + IN ULONG TxTotalCnt); + +VOID MlmeSelectTxRateTable( + IN struct _RTMP_ADAPTER *pAd, + IN struct _MAC_TABLE_ENTRY *pEntry, + IN UCHAR **ppTable, + IN UCHAR *pTableSize, + IN UCHAR *pInitTxRateIdx); + +void ra_swift_train_up_table_reset(struct _MAC_TABLE_ENTRY *pEntry); + +/* normal rate switch */ +#define RTMP_DRS_ALG_INIT(__pAd, __Alg) \ + (__pAd)->rateAlg = __Alg; + +#ifdef NEW_RATE_ADAPT_SUPPORT +UCHAR ra_get_lowest_rate(struct _RTMP_ADAPTER *pAd, struct _MAC_TABLE_ENTRY *pEntry); +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#endif /* __DRS_EXTR_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/ez_cmm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/ez_cmm.h new file mode 100644 index 000000000..ae60eb079 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/ez_cmm.h @@ -0,0 +1,547 @@ +#ifndef __EZ_CMM_H__ +#define __EZ_CMM_H__ + + +#define EZ_PMK_LEN 32 + +#define EZ_MAX_STA_NUM 8 + +#define EZ_AES_KEY_ENCRYPTION_EXTEND 8 /* 8B for AES encryption extend size */ + +#define EZ_RAW_KEY_LEN 192 + +#define EZ_NONCE_LEN 32 + +#define EZ_DH_KEY_LEN 32 + +#define MAX_EZ_BANDS 2 +#define MAX_NON_EZ_BANDS 2 + +#define MAX_EZ_PEERS_PER_BAND 8 +#define EZDEV_NUM_MAX 6 + +#define EZ_PTK_LEN 80 + + + +typedef struct ez_chipops_s{ + unsigned char (*RandomByte)(void * ezdev); + void (*GenRandom)(void * ezdev, UCHAR *macAddr, UCHAR *random); + void (*DH_PublicKey_Generate) (void * ezdev, UINT8 *GValue, UINT GValueLength,UINT8 *PValue,UINT PValueLength, + UINT8 *PrivateKey,UINT PrivateKeyLength,UINT8 *PublicKey,UINT *PublicKeyLength); + void (*RT_DH_SecretKey_Generate) (void * ezdev, UINT8 PublicKey[], UINT PublicKeyLength, UINT8 PValue[], UINT PValueLength, + UINT8 PrivateKey[],UINT PrivateKeyLength, UINT8 SecretKey[], UINT *SecretKeyLength); + void (*RT_SHA256)(void *ezdev, const UINT8 Message[], UINT MessageLen, UINT8 DigestMessage[]); + VOID (*WpaDerivePTK)(void * ezdev, UCHAR *PMK, UCHAR *ANonce, UCHAR *AA, UCHAR *SNonce, UCHAR *SA, UCHAR *output, UINT len); + INT (*AES_Key_Unwrap)(void * ezdev, UINT8 CipherText[],UINT CipherTextLength, UINT8 Key[],UINT KeyLength,UINT8 PlainText[],UINT *PlainTextLength); + void (*ez_install_pairwise_key)(void * ezdev, char *peer_mac, unsigned char *pmk, unsigned char *ptk, unsigned char authenticator); + void (*ez_apcli_install_group_key)(void * ezdev, char *peer_mac, char *peer_gtk, unsigned char ptk_len); + int (*wlan_config_get_ht_bw)(void +*ezdev); + int (*wlan_config_get_vht_bw)(void +*ezdev); + int (*wlan_operate_get_ht_bw)(void +*ezdev); + int (*wlan_operate_get_vht_bw)(void +*ezdev); + int (*wlan_config_get_ext_cha)(void +*ezdev); + int (*wlan_operate_get_ext_cha)(void +*ezdev); + int (*get_cli_aid)(void * ezdev, char * peer_mac); + void (*ez_cancel_timer)(void * ezdev, void * timer_struct); + void (* ez_set_timer)(void * ezdev, void * timer_struct, unsigned long time); + int (* ez_is_timer_running)(void * ezdev, void * timer_struct); + + + int (* get_apcli_enable)(void *ezdev); + int (* ApScanRunning)(void *ezdev); + + void (*ez_send_unicast_deauth)(void *ezdev, char *peer_mac); + void (*ez_restore_channel_config)(void *ezdev); + void (*UpdateBeaconHandler)(void *ezdev, int reason); + void (*ez_initiate_new_scan)(void *ezdev); + void (*ez_update_security_setting)(void *ezdev, unsigned char *pmk); + void (*ez_update_ap_wsc_profile)(void *ezdev); + void (*APScanCnclAction)(void *ezdev); + void (*ez_send_loop_detect_pkt)(void *ezdev, unsigned char *pOtherCliMac); + + + INT (*ez_update_ap)(void *ezdev, void *updated_configs, int gid_different, int band_switched); + INT (*ez_update_cli)(void *ezdev, void *updated_configs, int gid_different, int band_switched); + void (*ez_update_ap_peer_record)(void *ezdev, BOOLEAN band_switched, unsigned char *peer_mac); + void (*ez_update_cli_peer_record)(void *ezdev, BOOLEAN band_switched, unsigned char *peer_mac); + void (* MiniportMMRequest)(void *ezdev, char *out_buf,int frame_len); + void (*NdisGetSystemUpTime)(void * ezdev, ULONG *time); + INT (*AES_Key_Wrap )(void * ezdev, UINT8 PlainText[],UINT PlainTextLength,UINT8 Key[],UINT KeyLength,UINT8 CipherText[],UINT *CipherTextLength); + INT (*RtmpOSWrielessEventSendExt)(void* ezdev,UINT32 eventType,INT flags,PUCHAR pSrcMac,PUCHAR pData,UINT32 dataLen); + void (*ez_send_broadcast_deauth)(void *ezdev); + void (*MgtMacHeaderInit)(void *ezdev, HEADER_802_11_EZ *pHdr80211,UCHAR SubType,UCHAR ToDs,UCHAR *pDA,UCHAR *pSA,UCHAR *pBssid); + void (*apcli_stop_auto_connect)(void *ezdev, BOOLEAN enable); + void (*timer_init)(void *ezdev, void* timer, void *callback); + void (*set_ap_ssid_null)(void *ezdev); + void (*ez_set_entry_apcli)(void *ezdev, UCHAR *mac_addr, BOOLEAN is_apcli); + void *(*ez_get_pentry)(void *ezdev, UCHAR *mac_addr); + void (*ez_mark_entry_duplicate)(void *ezdev, UCHAR *mac_addr); + void (*ez_restore_cli_config)(void *ezdev); + void (*ScanTableInit)(void *ezdev); + void (*RT_HMAC_SHA1)(void * ezdev, UINT8 Key[], UINT KeyLen, UINT8 Message[], UINT MessageLen, UINT8 MAC[], UINT MACLen); + BOOLEAN (*is_mlme_running)(void *ezdev); + void (*ApSiteSurvey)(void *ezdev, int scan_one_channel); + void (*ez_ApSiteSurvey_by_wdev)(void * ad_obj,void * pSsid,UCHAR ScanType,BOOLEAN ChannelSel,void *wdev_obj); + void (*ez_BssTableSsidSort)(void * ad_obj,void *wdev_obj,EZ_BSS_TABLE *OutTab, + CHAR Ssid[],UCHAR SsidLen); + void (*ez_get_scan_table)(void * ad_obj,EZ_BSS_TABLE *ez_scan_tab); + void (*ez_add_entry_in_apcli_tab)(void * ad_obj, void* wdev_obj, ULONG bss_idx); + void (*ez_ApCliBssTabInit)(void * ad_obj, void* wdev_obj); + BOOLEAN (*ez_update_cli_conn)(void * ad_obj, void * ezdev, EZ_BSS_ENTRY *bss_entry); + void (*ez_update_partial_scan)(void * ez_ad,void * wdev_obj); + void (*ez_rtmp_set_channel)(void * ad_obj, void * wdev_obj, UINT8 channel); + +}ez_chipops_t; + + +typedef struct __non_ez_band_psk_info_tag{ + unsigned char encrypted_psk[LEN_PSK + EZ_AES_KEY_ENCRYPTION_EXTEND]; +}NON_EZ_BAND_PSK_INFO_TAG; + + +//! Levarage from MP.1.0 CL #170037 +typedef struct __non_man_info{ + unsigned char ssid[MAX_LEN_OF_SSID]; + unsigned char ssid_len; + unsigned char psk[LEN_PSK]; +//! Leverage form MP.1.0 CL 170364 + unsigned char encryptype[32]; + unsigned char authmode[32]; + +#ifdef DOT11R_FT_SUPPORT + UINT8 FtMdId[FT_MDID_LEN]; // share MDID info so that all devices use same MDID, irrespective of FT enabled or not. +#else + UINT8 rsvd[2]; +#endif + +} NON_MAN_INFO; + + +//! Leverage form MP.1.0 CL 170037 +typedef struct __non_man_info_tag{ + unsigned char ssid[MAX_LEN_OF_SSID]; + unsigned char ssid_len; + unsigned char encrypted_psk[LEN_PSK + EZ_AES_KEY_ENCRYPTION_EXTEND]; +//! Leverage form MP.1.0 CL 170364 + unsigned char encryptype[32]; + unsigned char authmode[32]; + +#ifdef DOT11R_FT_SUPPORT + UINT8 FtMdId[FT_MDID_LEN]; // share MDID info so that all devices use same MDID, irrespective of FT enabled or not. +#else + UINT8 rsvd[2]; +#endif + +} NON_MAN_INFO_TAG; + + +typedef enum _enum_loop_chk_role{ + NONE, + SOURCE, + DEST +}enum_loop_chk_role; + +struct _ez_roam_info +{ + unsigned char ez_apcli_roam_bssid[MAC_ADDR_LEN]; + unsigned char roam_channel; + unsigned long timestamp; +}; + +typedef struct GNU_PACKED _loop_chk_info { + enum_loop_chk_role loop_chk_role; + UCHAR source_mac[MAC_ADDR_LEN]; +}LOOP_CHK_INFO; + + +typedef struct GNU_PACKED channel_info_s{ + unsigned char channel; +#ifdef EZ_PUSH_BW_SUPPORT + unsigned char ht_bw; + unsigned char vht_bw; +#else + unsigned char rsvd1; + unsigned char rsvd2; +#endif + unsigned char extcha; +}channel_info_t; + + +typedef struct ez_init_params_s{ + void * ad_obj; + void * wdev_obj; + char func_idx; + enum EZDEV_TYPE ezdev_type; + UCHAR mac_add[MAC_ADDR_LEN]; + UCHAR ssid[MAX_LEN_OF_SSID]; + unsigned char ssid_len; + UCHAR pmk[PMK_LEN]; + + unsigned int group_id_len; + unsigned int ez_group_id_len; //for localy maintain EzGroupID + unsigned int gen_group_id_len; //for localy maintain EzGenGroupID + + unsigned char *group_id; + unsigned char *ez_group_id; //for localy maintain EzGroupID + unsigned char *gen_group_id; //for localy maintain EzGenGroupID + + unsigned int open_group_id_len; + unsigned char open_group_id[OPEN_GROUP_MAX_LEN]; + + void *chipops_lut; + char channel; + UINT32 os_hz; + void *ez_scan_timer; + void *ez_stop_scan_timer; + void *ez_scan_pause_timer; + void *ez_group_merge_timer; + void *ez_loop_chk_timer; + void *ez_connect_wait_timer; + + channel_info_t channel_info; +} ez_init_params_t; + +typedef struct GNU_PACKED interface_info_tag_s +{ + unsigned char ssid[MAX_LEN_OF_SSID]; + unsigned char ssid_len; + channel_info_t channel_info; + unsigned char ap_mac_addr[MAC_ADDR_LEN];//! this band AP MAC + unsigned char cli_mac_addr[MAC_ADDR_LEN];//! this band CLI MAC + unsigned char link_duplicate;//! when seen in CLI context it meens that other band CLI is also connected to same repeater, if seen in AP context(ez_peer) it means that both CLIs of other repeater are connected to me +#ifdef DOT11R_FT_SUPPORT + UINT8 FtMdId[FT_MDID_LEN]; // share MDID info so that all devices use same MDID, irrespective of FT enabled or not. +#else + UINT8 rsvd[2]; +#endif +} interface_info_tag_t; + +typedef struct GNU_PACKED interface_info_s{ + interface_info_tag_t shared_info; + unsigned char cli_peer_ap_mac[MAC_ADDR_LEN];//! mac address of AP to which my cli connects, will be mostly used in CLI wdev context + BOOLEAN non_easy_connection; + unsigned char interface_activated; + unsigned char pmk[EZ_PMK_LEN]; +}interface_info_t; + + +struct _ez_security { + void *ad; + void *ezdev; +#ifdef EZ_API_SUPPORT + enum_ez_api_mode ez_api_mode; +#endif + spinlock_t ez_apcli_list_sem_lock; + + void * ez_scan_timer; + void * ez_stop_scan_timer; + void * ez_scan_pause_timer; + void * ez_group_merge_timer; + + spinlock_t ez_scan_pause_timer_lock; + signed char best_ap_rssi_threshold; + unsigned int capability; + unsigned int group_id_len; + unsigned int ez_group_id_len; //for localy maintain EzGroupID + unsigned int gen_group_id_len; //for localy maintain EzGenGroupID + unsigned char *group_id; + unsigned char *ez_group_id; //for localy maintain EzGroupID + unsigned char *gen_group_id; //for localy maintain EzGenGroupID + unsigned char self_dh_random_seed[EZ_RAW_KEY_LEN]; /* do NOT change after configured */ + unsigned char self_pke[EZ_RAW_KEY_LEN]; + unsigned char self_pkr[EZ_RAW_KEY_LEN]; + unsigned char self_nonce[EZ_NONCE_LEN]; + unsigned char keep_finding_provider; + unsigned char first_scan; + unsigned char scan_one_channel; + unsigned char client_count; + unsigned char go_internet; + unsigned char user_configured; + signed char rssi_threshold; +#ifdef EZ_NETWORK_MERGE_SUPPORT + + unsigned char merge_peer_addr[MAC_ADDR_LEN]; +#ifdef DISCONNECT_ON_CONFIG_UPDATE + unsigned char force_connect_bssid[MAC_ADDR_LEN]; + unsigned long force_bssid_timestamp; +#endif + unsigned char weight_update_going_on; //! flag will be set when force weight is pushed, normal action frame will not be processed in this case + unsigned char do_not_restart_interfaces;//! flag will be set while calling rtmp_set_channel to avoid CLI down/up + unsigned char delay_disconnect_count;//! to increase beacon miss duration + interface_info_t this_band_info;//! ssid, pmk, mac address, and CLI peer MAC address, information of wdev to which wdev correspond + interface_info_t other_band_info_backup;//! ssid, pmk, mac address, and CLI peer MAC address, information of wdev to which wdev correspond + BOOLEAN ap_did_fallback; + unsigned char fallback_channel; + +#endif +#ifdef NEW_CONNECTION_ALGO + + BOOLEAN ez_apcli_immediate_connect; + BOOLEAN ez_connection_permission_backup; + BOOLEAN ez_is_connection_allowed; + unsigned char ez_apcli_force_ssid[MAX_LEN_OF_SSID]; + unsigned char ez_apcli_force_ssid_len; + unsigned char ez_apcli_force_bssid[MAC_ADDR_LEN]; + unsigned char ez_apcli_force_channel; + + unsigned int open_group_id_len; + unsigned char open_group_id[OPEN_GROUP_MAX_LEN]; +#ifdef EZ_ROAM_SUPPORT + struct _ez_roam_info ez_roam_info; + UCHAR ez_ap_roam_blocked_mac[MAC_ADDR_LEN]; +#endif + +#ifdef EZ_DUAL_BAND_SUPPORT + BOOLEAN internal_force_connect_bssid; + BOOLEAN internal_force_connect_bssid_timeout; + unsigned long force_connect_bssid_time_stamp; + LOOP_CHK_INFO loop_chk_info; + void * ez_loop_chk_timer; + unsigned char ez_loop_chk_timer_running; + BOOLEAN first_loop_check; + BOOLEAN dest_loop_detect; +#endif + unsigned char ez_action_type; + UINT32 ez_scan_delay; + UINT32 ez_max_scan_delay; + BOOLEAN ez_scan; + BOOLEAN ez_scan_same_channel; + ULONG ez_scan_same_channel_timestamp; +#endif + BOOLEAN ez_wps_reconnect; + unsigned char ez_wps_bssid[6]; + ULONG ez_wps_reconnect_timestamp; + BOOLEAN disconnect_by_ssid_update; + + unsigned char default_ssid[MAX_LEN_OF_SSID]; + unsigned char default_ssid_len; + unsigned char default_pmk[EZ_PMK_LEN]; + unsigned char default_pmk_valid; + ULONG partial_scan_time_stamp; + BOOLEAN bPartialScanRunning; +}; + +typedef struct ez_dev_s{ + void *ad; + void *wdev; + enum EZDEV_TYPE ezdev_type; + char channel; + char own_mac_addr[MAC_ADDR_LEN]; + char if_addr[MAC_ADDR_LEN]; + char bssid[MAC_ADDR_LEN]; + unsigned char ez_band_idx; + struct _ez_security ez_security; + char non_ez_connection; + spinlock_t ez_peer_table_lock; + unsigned int os_hz; + ez_chipops_t *chipops; +} ez_dev_t; + + +typedef struct GNU_PACKED weight_defining_link_s { + void *ezdev; + ULONG time_stamp; + ULONG ap_time_stamp; + UCHAR peer_mac[MAC_ADDR_LEN]; + UCHAR peer_ap_mac[MAC_ADDR_LEN]; +}weight_defining_link_t; + + +typedef struct GNU_PACKED device_info_s{ + + unsigned char network_weight[NETWORK_WEIGHT_LEN]; + weight_defining_link_t weight_defining_link; + EZ_NODE_NUMBER ez_node_number; +} device_info_t; + + + + +typedef struct __ez_triband_sec_config +{ + UINT32 PairwiseCipher; + UINT32 GroupCipher; + UINT32 AKMMap; + +} EZ_TRIBAND_SEC_CONFIG; + + +typedef struct __non_ez_band_info_tag{ + unsigned char ssid[MAX_LEN_OF_SSID]; + unsigned char ssid_len; + EZ_TRIBAND_SEC_CONFIG triband_sec; + unsigned char encrypted_pmk[EZ_PMK_LEN + EZ_AES_KEY_ENCRYPTION_EXTEND]; + //unsigned char encrypted_psk[LEN_PSK + EZ_AES_KEY_ENCRYPTION_EXTEND]; +#ifdef DOT11R_FT_SUPPORT + UINT8 FtMdId[FT_MDID_LEN]; // share MDID info so that all devices use same MDID, irrespective of FT enabled or not. +#else + UINT8 rsvd[2]; +#endif + +}NON_EZ_BAND_INFO_TAG; + +struct _ez_peer_security_info { + void *ad; + void *ezdev; + unsigned char ez_band_idx; + unsigned int capability; + unsigned int group_id_len; + unsigned int gtk_len; + unsigned char *group_id; + unsigned char *gtk; + unsigned char mac_addr[MAC_ADDR_LEN]; + unsigned char peer_pke[EZ_RAW_KEY_LEN]; + unsigned char peer_nonce[EZ_NONCE_LEN]; + unsigned char dh_key[EZ_DH_KEY_LEN]; + unsigned char sw_key[EZ_PTK_LEN]; + //unsigned char pmk[EZ_PMK_LEN]; + unsigned char valid; + +#if defined (NEW_CONNECTION_ALGO) || defined (EZ_NETWORK_MERGE_SUPPORT) + unsigned char port_secured; + unsigned int open_group_id_len; + unsigned char open_group_id[OPEN_GROUP_MAX_LEN]; + +#endif + +#ifdef EZ_NETWORK_MERGE_SUPPORT +#ifdef EZ_DUAL_BAND_SUPPORT + device_info_t device_info;// when device info is used in ez_peer, only node number is expected to give correct information, others are session variable which does not hold any significance after comparision + interface_info_t this_band_info; + interface_info_t other_band_info; +#else + unsigned char ssid_len; + unsigned char ssid[MAX_LEN_OF_SSID]; + unsigned char other_band_ssid_len; + unsigned char other_band_ssid[MAX_LEN_OF_SSID]; + unsigned char other_band_pmk[PMK_LEN]; + unsigned char network_weight[NETWORK_WEIGHT_LEN]; + unsigned char ap_mac_addr[MAC_ADDR_LEN]; + unsigned char target_channel; + unsigned char ht_bw; + unsigned char vht_bw; + unsigned char ext_cha_offset; +#endif +#endif + +#ifdef NEW_CONNECTION_ALGO + unsigned long creation_time; + unsigned char ez_peer_table_index; +#endif + BOOLEAN delete_in_differred_context; + BOOLEAN ez_disconnect_due_roam; + NON_EZ_BAND_INFO_TAG non_ez_band_info[MAX_NON_EZ_BANDS]; + NON_EZ_BAND_PSK_INFO_TAG non_ez_psk_info[MAX_NON_EZ_BANDS]; + //! Levarage from MP1.0 CL#170037 + NON_MAN_INFO_TAG non_man_info; + ez_chipops_t *chipops; +}; + + +typedef struct __ez_band_info{ + void *pAd; + CHAR func_idx; + ez_dev_t ap_ezdev; + ez_dev_t cli_ezdev; + struct _ez_peer_security_info ez_peer_table[MAX_EZ_PEERS_PER_BAND]; + ez_chipops_t lut_chipops; +} EZ_BAND_INFO; + + +typedef struct non_ez_chipops_s{ + //unsigned char (*RandomByte)(void *); + int (*RtmpOSWrielessEventSendExt)( void *ad,int band_id,UINT32 eventType,INT flags,PUCHAR pSrcMac,PUCHAR pData,UINT32 dataLen); + void (*ez_update_non_ez_ap)(void * ad_obj, void *non_ez_and_info_tag, void *non_ez_band_info, void *updated_configs); + void (*HwCtrlWifiSysRestart)(void * ez_ad, INT band_id); + void (*ez_send_broadcast_deauth)(void *ad, void *wdev); + void (*ez_init_non_ez_ap)(void *ad, void *wdev); +}non_ez_chipops_t; + + +typedef struct __non_ez_band_info{ + void *ez_ad; + void *pAd; + CHAR func_idx; + void *non_ez_ap_wdev; + void *non_ez_cli_wdev; + non_ez_chipops_t lut_chipops; + unsigned char ssid[MAX_LEN_OF_SSID]; + unsigned char ssid_len; + EZ_TRIBAND_SEC_CONFIG triband_sec; + BOOLEAN need_restart; + unsigned char pmk[EZ_PMK_LEN]; + char channel; + unsigned char psk[EZ_PMK_LEN]; +#ifdef DOT11R_FT_SUPPORT + UINT8 FtMdId[FT_MDID_LEN]; // share MDID info so that all devices use same MDID, irrespective of FT enabled or not. +#else + UINT8 rsvd[2]; +#endif + +} NON_EZ_BAND_INFO; + +typedef struct __ez_adapter{ + unsigned char band_count; + EZ_BAND_INFO ez_band_info[MAX_EZ_BANDS]; + unsigned char non_ez_band_count; + NON_EZ_BAND_INFO non_ez_band_info[MAX_NON_EZ_BANDS]; + unsigned int backhaul_channel; + unsigned int front_end_channel; + +#ifdef EZ_PUSH_BW_SUPPORT + BOOLEAN push_bw_config; +#endif +#ifdef EZ_API_SUPPORT + enum_ez_api_mode ez_api_mode; +#endif + + UINT8 ez_roam_time; + unsigned char ez_delay_disconnect_count; + UINT8 ez_wait_for_info_transfer; + UINT8 ez_wdl_missing_time; + UINT32 ez_force_connect_bssid_time; + UINT8 ez_peer_entry_age_out_time; + UINT8 ez_scan_same_channel_time; + UINT32 ez_partial_scan_time; + signed char best_ap_rssi_threshld[10]; + unsigned char best_ap_rssi_threshld_max; + UINT32 max_scan_delay; + + void *ez_connect_wait_timer; + unsigned char ez_connect_wait_timer_running; + unsigned long ez_connect_wait_timer_value; + unsigned long ez_connect_wait_timer_timestamp; + unsigned char configured_status; /* 0x01 - un-configured, 0x02 - configured */ + device_info_t device_info;//! network weight, node number and weight defining link info, all interface should have same content in htis structure + char Peer2p4mac[MAC_ADDR_LEN]; + //! Levarage from MP1.0 CL#170037 + unsigned char is_man_nonman; + NON_MAN_INFO non_man_info; + +#ifdef DUAL_CHIP + spinlock_t ez_handle_disconnect_lock; + spinlock_t ez_beacon_update_lock; + spinlock_t ez_miniport_lock; + spinlock_t ez_set_channel_lock; + spinlock_t ez_set_peer_lock; + spinlock_t ez_conn_perm_lock; + spinlock_t ez_mlme_sync_lock; +#endif + + ez_dev_t *ezdev_list[EZDEV_NUM_MAX]; + BOOLEAN SingleChip; + int debug; +//! Levarage from MP1.0 CL 170210 +//! repeater device flag removed from ez_adapter +} EZ_ADAPTER; + + + +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/ez_hooks.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/ez_hooks.h new file mode 100644 index 000000000..0355f87e7 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/ez_hooks.h @@ -0,0 +1,342 @@ +#ifndef __EZ_HOOK_H__ +#define __EZ_HOOK_H__ + +#ifdef WH_EZ_SETUP +#include "ez_common_structs.h" +#define EZ_STATUS_CODE_SUCCESS 0x0000 +#define EZ_STATUS_CODE_MIC_ERROR 0x0001 +#define EZ_STATUS_CODE_INVALID_DATA 0x0002 +#define EZ_STATUS_CODE_NO_RESOURCE 0x0003 +#define EZ_STATUS_CODE_PEER_CONNECTED 0x0004 +#define EZ_STATUS_CODE_LOOP 0x0005 +#define EZ_STATUS_CODE_UNKNOWN 0xFFFF + +#define MTK_VENDOR_CAPABILITY_SIZE 4 +#define MTK_VENDOR_EASY_SETUP 0x40 +#define MTK_OUI_LEN 3 +#define RALINK_OUI_LEN 3 + +#define MLME_SYNC_LOCK 0x1 +#define BEACON_UPDATE_LOCK 0x2 +#define EZ_MINIPORT_LOCK 0x3 +#define SCAN_PAUSE_TIMER_LOCK 0x4 + +#define EZ_CLEAR_ACTION 0 +#define EZ_SET_ACTION 1 + +#define EZ_CAP_HAS_APCLI_INF (1 << 10) +#define EZ_SET_CAP_HAS_APCLI_INF(__cap) (__cap |= EZ_CAP_HAS_APCLI_INF) + +#define EZ_INDEX_NOT_FOUND 0xFF + +#define EZ_TAG_NON_EZ_BEACON 0x16 +#define EZ_TAG_CAPABILITY_INFO 0x06 + +#define EZ_PMK_LEN 32 + + +#define EZ_TLV_TAG_SIZE 1 +#define EZ_TLV_LEN_SIZE 1 + +#define EZ_TAG_OFFSET (MTK_OUI_LEN+MTK_VENDOR_CAPABILITY_SIZE) +#define EZ_TAG_LEN_OFFSET (MTK_OUI_LEN+MTK_VENDOR_CAPABILITY_SIZE+EZ_TLV_TAG_SIZE) +#define EZ_TAG_DATA_OFFSET (MTK_OUI_LEN+MTK_VENDOR_CAPABILITY_SIZE+EZ_TLV_TAG_SIZE+EZ_TLV_LEN_SIZE) + +#define EZ_CAPABILITY_LEN 4 +#define EZ_GROUP_ID_LEN 4 +#define EZ_TAG_BEACON_INFO 0x14 +#define EZ_TAG_OPEN_GROUP_ID 0x22 + + + +#ifdef EZ_DUAL_BAND_SUPPORT +#define IS_SINGLE_CHIP_DBDC(_pAd) ((_pAd)->SingleChip && *(_pAd)->SingleChip == TRUE) +#define IS_DUAL_CHIP_DBDC(_pAd) !(IS_SINGLE_CHIP_DBDC(_pAd)) +#else +#define IS_SINGLE_CHIP_DBDC(_pAd) 1 +#define IS_DUAL_CHIP_DBDC(_pAd) 0 +#endif + + +#define OPEN_GROUP_MAX_LEN 20 +#define AUTH_MODE_EZ 0xFF01 + +#define EZ_MAX_STA_NUM 8 +#define IS_CONF_EZ_SETUP_ENABLED(_wdev) ((_wdev)?(((_wdev)->ez_driver_params.enable_easy_setup) == TRUE):FALSE) +#define IS_EZ_SETUP_ENABLED(_wdev) ((_wdev)?(((_wdev)->ez_driver_params.ez_started) == TRUE):FALSE) +#define IS_ADPTR_EZ_SETUP_ENABLED(pAd) (pAd->ApCfg.MBSSID[0].wdev.ez_driver_params.ez_started == TRUE) + +#ifdef DUAL_CHIP +#define EZ_ACQUIRE_DUAL_CHIP_DBDC_MLME_LOCK(pAd) \ + do { \ + if (IS_CONF_EZ_SETUP_ENABLED(&pAd->ApCfg.MBSSID[0].wdev)) \ + if (IS_DUAL_CHIP_DBDC(pAd) && !ez_is_triband()) \ + ez_acquire_lock(pAd, NULL, MLME_SYNC_LOCK); \ + } while(0) + +#define EZ_RELEASE_DUAL_CHIP_DBDC_MLME_LOCK(pAd) \ + do { \ + if (IS_CONF_EZ_SETUP_ENABLED(&pAd->ApCfg.MBSSID[0].wdev)) \ + if (IS_DUAL_CHIP_DBDC(pAd) && !ez_is_triband()) \ + ez_release_lock(pAd, NULL, MLME_SYNC_LOCK); \ + } while(0) +#else +#define EZ_ACQUIRE_DUAL_CHIP_DBDC_MLME_LOCK(pAd) \ + do { \ + } while(0) + +#define EZ_RELEASE_DUAL_CHIP_DBDC_MLME_LOCK(pAd) \ + do { \ + } while(0) +#endif + +#ifdef EZ_REGROUP_SUPPORT +#define IS_REGRP_SUPP(_wdev) (((_wdev)->ez_driver_params.en_regrp_supp) == TRUE) +#define REGRP_MODE_TIME_OUT 300000 /* 300 second recheck with app for sync in all places (app time + 5sec) */ +#define REGRP_UNBLOCK_MODE_TIME_OUT 15000 /* 15 second recheck with app for sync in all places (app time + 5sec)*/ + +#define HAS_DIRECT_INTERNET_BIT 2 +#define EZ_CAP_DIRECT_INTERNET (1 << 14) + +#define EZ_GET_CAP_DIRECT_INTERNET(__cap) (__cap & EZ_CAP_DIRECT_INTERNET) +#define EZ_SET_CAP_DIRECT_INTERNET(__cap) (__cap |= EZ_CAP_DIRECT_INTERNET) +#define EZ_CLEAR_CAP_DIRECT_INTERNET(__cap) (__cap &= 0xFFFFBFFF) + +#endif +#define EZ_DROP_GROUP_DATA_BAND24G 0 +#define EZ_DROP_GROUP_DATA_BAND5G 1 + + +#define EZ_TIMER_INIT(__ad, __data, __time_var, __time_flg, __time_fn) \ + do{ \ + RTMPInitTimer((__ad), (__time_var), GET_TIMER_FUNCTION(__time_fn), (__data), FALSE); \ + (__time_flg) = FALSE; \ + }while(0) + +#define EZ_CANCEL_TIMER(__time_var, __time_flg) \ + do{ \ + unsigned char __cancelled; \ + RTMPCancelTimer(__time_var, &__cancelled); \ + (__time_flg) = FALSE; \ + }while(0) + +#define EZ_RELEASE_TIMER(__time_var, __time_flg) \ + do{ \ + unsigned char __cancelled; \ + RTMPReleaseTimer(__time_var, &__cancelled); \ + (__time_flg) = FALSE; \ + }while(0) + + + + +typedef struct web_conf_info_s{ + unsigned char data_len; + char data[250]; +} web_conf_info_t; + + +typedef struct GNU_PACKED ez_custom_data_cmd_s { + UINT8 data_len; + UINT8 data_body[0]; +}ez_custom_data_cmd_t, *p_ez_custom_data_cmd_t; + +typedef enum enum_group_merge_action +{ + EXIT_SWITCH_NOT_GROUP_MERGE, + TERMINATE_LOOP_MULTIPLE_AP_FOUND, + TERMINATE_LOOP_TARGET_AP_FOUND, + CONTINUE_LOOP_TARGET_AP_FOUND, + CONTINUE_LOOP +}enum_group_merge_action_t; + + +enum EZ_CONN_ACTION +{ + EZ_ALLOW_ALL, + EZ_DISALLOW_ALL, + EZ_ADD_DISALLOW, + EZ_ADD_ALLOW, + EZ_DISALLOW_ALL_ALLOW_ME, + EZ_ALLOW_ALL_TIMEOUT, + EZ_ENQUEUE_PERMISSION, + EZ_DEQUEUE_PERMISSION, +}; + +extern int EzDebugLevel; +#define EZ_DEBUG(__debug_cat, __debug_sub_cat, __debug_level, __fmt) \ +do{ \ + if (__debug_level <= EzDebugLevel) { \ + printk __fmt;\ + } \ +}while(0) +typedef struct ez_timer_s{ + RALINK_TIMER_STRUCT ez_timer; + BOOLEAN ez_timer_running; +}ez_timer_t; + + +typedef struct ez_driver_params_s{ + void *ez_ad; + void *ezdev; + unsigned int group_id_len; + unsigned int ez_group_id_len; //for localy maintain EzGroupID + unsigned int gen_group_id_len; //for localy maintain EzGenGroupID + unsigned char *group_id; + unsigned char *ez_group_id; //for localy maintain EzGroupID + unsigned char *gen_group_id; //for localy maintain EzGenGroupID + char ez_api_mode; + + //!timers + ez_timer_t ez_scan_timer; +// ez_timer_t ez_stop_scan_timer; + ez_timer_t ez_scan_pause_timer; + ez_timer_t ez_group_merge_timer; + ez_timer_t ez_loop_chk_timer; + ez_timer_t ez_connect_wait_timer; + BOOLEAN do_not_restart_interfaces; + BOOLEAN ez_wps_reconnect; + BOOLEAN need_tx_satus; + BOOLEAN ez_scan; + BOOLEAN scan_one_channel; + UCHAR ez_wps_bssid[MAC_ADDR_LEN]; + ULONG ez_wps_reconnect_timestamp; + + unsigned int open_group_id_len; + unsigned char open_group_id[OPEN_GROUP_MAX_LEN]; + + unsigned char default_ssid[MAX_LEN_OF_SSID]; + unsigned char default_ssid_len; + unsigned char default_pmk[EZ_PMK_LEN]; + unsigned char default_pmk_valid; + int rssi_threshold; +#ifdef EZ_REGROUP_SUPPORT + BOOLEAN en_regrp_supp; + UINT8 regrp_mode; // rename to avoid confusion with regrp supp + NDIS_SPIN_LOCK regrp_mode_lock; + RALINK_TIMER_STRUCT regrp_mode_tmr; // regrp_mode_exit_tmr + RALINK_TIMER_STRUCT regrp_unblock_mode_tmr; // regrp_unblock_mode_exit_tmr + UINT32 regrp_mode_time; // time to remain in this mode + unsigned char regrp_mode_tmr_running; + unsigned char regrp_unblock_mode_tmr_running; // time to remain in this mode + UINT32 regrp_unblock_mode_time; + UCHAR ap_entry_count; + struct _drvr_cand_list ap_list[MAX_AP_CANDIDATES]; + BOOLEAN regrp_triggrd; +#endif + UCHAR enable_easy_setup; + ULONG partial_scan_time_stamp; + BOOLEAN bPartialScanRunning; + unsigned char default_group_data_band; + BOOLEAN ez_started; +#ifdef IF_UP_DOWN + UINT8 ez_intf_count_config_ap; + UINT8 ez_intf_count_config_cli; + UINT8 ez_apcli_peer_ap_config_cnt; +#endif +} ez_driver_params_t; + +#ifdef EZ_REGROUP_SUPPORT + +typedef struct GNU_PACKED _ntw_info { + BOOLEAN Non_MAN; + UINT8 ssid[32]; + CHAR rssi; // unsigned? + UINT8 bssid[MAC_ADDR_LEN]; + unsigned char internet_status; + UINT8 nw_wt[NETWORK_WEIGHT_LEN]; + EZ_NODE_NUMBER node_number; + //BOOLEAN processed; + // channel ?? +}ntw_info,*pntw_info; + +typedef struct vr_ap_info { + //UINT8 mode; // singleband, dualBand, triband etc. + UINT8 ssid_len; + UINT8 ssid[33]; + UINT8 intf_prefix[8]; + UINT8 mac_addr[MAC_ADDR_LEN]; + UINT8 wdev_id;//! a non zero value means a virtual repeater is created on wdev_index + //UINT32 ip_addr; + //INT8 rssi; + /*Add More*/ +} vr_ap_info_struct, *p_vr_ap_info_struct; + +typedef struct _node_num_wt +{ + EZ_NODE_NUMBER node_number; + UINT8 network_wt[NETWORK_WEIGHT_LEN]; +}node_num_wt, *p_node_num_wt; + + +typedef struct GNU_PACKED _regrp_ap_info_struct { + UINT8 valid; + BOOLEAN Non_MAN; + //UINT8 ssid[32]; + //UINT8 ssid_len; + INT32 avg_rssi; // unsigned? + INT32 rssi_sum; + CHAR last_rssi; + UINT8 bssid[MAC_ADDR_LEN]; + unsigned char internet_status; + UINT8 nw_wt[NETWORK_WEIGHT_LEN]; + EZ_NODE_NUMBER node_number; + ULONG last_rx_time; + INT32 rx_cnt; + //BOOLEAN processed; + // channel ?? +}regrp_ap_info_struct,*p_regrp_ap_info_struct; + +typedef struct GNU_PACKED _apcli_info{ + BOOLEAN is_enabled; + BOOLEAN is_connected; + unsigned char internet_status; + //BOOLEAN is_duplicate_link; + struct _ntw_info ntw_info; +} apcli_info, *papcli_info; + +#endif + + +//#include "ez_hooks_proto.h" + + +//##################################################### +void ez_send_unicast_deauth(void *ad_obj, UCHAR *peer_addr); + +void ez_wait_for_connection_allow_timeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +VOID ez_scan_pause_timeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID ez_group_merge_timeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +VOID ez_loop_chk_timeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID ez_scan_timeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +#ifdef EZ_REGROUP_SUPPORT +regrp_ap_info_struct * ez_add_regrp_ap(regrp_ap_info_struct *p_ap_info_list); +regrp_ap_info_struct * ez_find_regrp_ap_by_bssid(regrp_ap_info_struct *p_ap_info_list, UINT8 * bssid); +#endif + + +#endif /* __EZ_CMM_H__ */ +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/ez_hooks_proto.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/ez_hooks_proto.h new file mode 100644 index 000000000..bead2f911 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/ez_hooks_proto.h @@ -0,0 +1,384 @@ + +unsigned long ez_build_beacon_ie( + void *wdev_obj, + unsigned char *frame_buf); + + +unsigned long ez_build_probe_request_ie( + void *wdev_obj, + unsigned char *frame_buf); + +unsigned long ez_build_probe_response_ie( + void *wdev_obj, + unsigned char *frame_buf); + +unsigned long ez_build_auth_request_ie( + void *wdev_obj, + unsigned char *peer_addr, + unsigned char *frame_buf); + +unsigned long ez_build_auth_response_ie( + void *wdev_obj, + unsigned char *peer_addr, + unsigned char *frame_buf); + +unsigned long ez_build_assoc_request_ie( + void *ad_obj, + void *wdev_obj, + unsigned char *peer_addr, + unsigned char *frame_buf, + unsigned int frame_buf_len); + +unsigned long ez_build_assoc_response_ie( + void *wdev_obj, + unsigned char *peer_addr, + unsigned char *ap_gtk, + unsigned int ap_gtk_len, + unsigned char *frame_buf); + + +unsigned char ez_process_probe_request( + void *ad_obj, + void *wdev_obj, + unsigned char *peer_addr, + void *msg, + unsigned long msg_len); + +void ez_process_beacon_probe_response( + void *wdev_obj, + void *msg, + unsigned long msg_len); + +unsigned char ez_process_auth_request( + void *ad_obj, + void *wdev_obj, + void *auth_info_obj, + void *msg, + unsigned long msg_len); + +void ez_process_auth_response( + void *ad_obj, + void *wdev_obj, + unsigned char *peer_addr, + unsigned long *current_state, + void *msg, + unsigned long msg_len); + +unsigned short ez_process_assoc_request( + void *wdev_obj, + void *entry_obj, + unsigned char isReassoc, + void *msg, + unsigned long msg_len); + + +unsigned short ez_process_assoc_response( + void *wdev_obj, + unsigned char *peer_addr, + void *msg, + unsigned long msg_len); + +INT Show_EasySetupInfo_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + + + +INT Set_EasySetup_Debug_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + +INT Set_EasySetup_RoamTime_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_Delay_Disconnect_Count_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_Wait_For_Info_Transfer_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_WDL_Missing_Time_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_Force_Connect_Bssid_Time_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_Peer_Entry_Age_Out_time_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_Scan_Same_Channel_Time_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + +INT Set_EasySetup_Partial_Scan_Time_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT ez_send_broadcast_deauth_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + +INT Set_EasySetup_GroupID_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + + +INT Set_EasySetup_GenGroupID_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + + +INT Set_EasySetup_RssiThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_EasySetup_MaxScanDelay( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT set_EasySetup_Api_Mode( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + + +INT set_EasySetup_MergeGroup_proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + + +INT Set_EasySetup_ForceSsid_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + + +INT Set_EasySetup_ForceBssid_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_EasySetup_BWPushConfig(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +BOOLEAN ez_is_loop_pkt_rcvd(void * wdev_obj,void *pRxBlk); + + +void ez_handle_action_txstatus(void *ad_obj, unsigned int wcid); + + +INT Set_EasySetup_ssid_psk_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + +INT Set_EasySetup_conf_ssid_psk_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + +void ez_apcli_link_down( + void *ad_obj, + void *apcli_obj, + unsigned char if_idx); + + +BOOLEAN ez_update_connection_permission( + void *ad_obj, + struct wifi_dev *wdev, + enum EZ_CONN_ACTION action); + + +BOOLEAN ez_is_connection_allowed(struct wifi_dev *wdev); + +BOOLEAN ez_probe_rsp_join_action(void *ad_obj, void *wdev_obj, OUT BCN_IE_LIST *ie_list, unsigned long Bssidx); + +void ez_update_connection(void *ad_obj, void *wdev_obj); + + +void ez_handle_pairmsg4(void *ad_obj, IN MAC_TABLE_ENTRY *pEntry); + + + +void ez_roam(struct wifi_dev *wdev,BSS_ENTRY *pBssEntry); + + +ULONG +BssTableSearchWithBssId( + IN BSS_TABLE *Tab, + IN PUCHAR Bssid, + IN UCHAR Channel); + + +BSS_ENTRY *ez_find_roam_candidate(void * ad_obj, unsigned char *bssid, struct wifi_dev *wdev); + + + +INT Set_EasySetup_RoamBssid_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + + +void ez_prepare_security_key( + void *wdev_obj, + unsigned char *peer_addr, + unsigned char authenticator); + +enum_group_merge_action_t is_group_merge_candidate(void *bss_entry_obj,void *temp_bss_entry_obj ,struct wifi_dev *wdev); + + +BOOLEAN ez_is_channel_same(struct wifi_dev *wdev); + + +void ez_process_action_frame( + void *ad_obj, + void *elem_obj); + +void ez_read_parms_from_file( + void *ad_obj, + char *tmpbuf, + char *buffer); + + +int ez_parse_set_command(void *ad_obj, RTMP_IOCTL_INPUT_STRUCT *wrq, IN int cmd); + + +int ez_parse_query_command(void *ad_obj, RTMP_IOCTL_INPUT_STRUCT *wrq, IN int cmd); + + +BOOLEAN check_best_ap_rssi_threshold(struct wifi_dev *wdev, BSS_ENTRY *bss_entry); + + + +void ez_vendor_ie_parse(struct _vendor_ie_cap *vendor_ie, PEID_STRUCT info_elem); + +void ez_set_ap_fallback_context(struct wifi_dev *wdev, BOOLEAN fallback, unsigned char fallback_channel); + +void *ez_peer_table_search_by_addr( + struct wifi_dev *wdev, + unsigned char *addr); + +void ez_set_delete_peer_in_differed_context(struct wifi_dev *wdev, void *ez_peer, BOOLEAN set); + +BOOLEAN ez_probe_count_handle(PAPCLI_STRUCT pApCliEntry); + +BOOLEAN ez_ApCliAutoConnectBWAdjust( + IN void *ad_obj, + IN struct wifi_dev *wdev, + IN void *bss_entry_obj); + +BOOLEAN ez_is_triband(void); +void * ez_get_otherband_ad(void *wdev_obj); + + +unsigned short ez_check_for_ez_enable( + struct wifi_dev *wdev, + void *msg, + unsigned long msg_len + ); + + +void ez_apcli_check_partial_scan(void *ad_obj, CHAR apcli_idx); + +void ez_peer_table_delete( + void *wdev_obj, + unsigned char *addr); + +BOOLEAN ez_is_roam_blocked_mac(struct wifi_dev *wdev, UCHAR *mac_addr); + + +BOOLEAN ez_ap_scan_timeout_action(struct wifi_dev *wdev); + + +void ez_peer_table_maintenance(PRTMP_ADAPTER ad); + + +BOOLEAN ez_port_secured( + void *ad_obj, + void *entry_obj, + unsigned char if_idx, + unsigned char ap_mode); + + +void increment_best_ap_rssi_threshold(struct wifi_dev *wdev); + + + +void ez_ap_peer_beacon_action(struct wifi_dev *ez_wdev, unsigned char * mac_addr, int capability, CHAR *RealRssi, BCN_IE_LIST *ie_list); + + +BOOLEAN ez_ap_scan_complete_handle(struct wifi_dev *wdev); + + +void ez_start( + void *wdev_obj, + unsigned char ap_mode); + +///////////////////will be removed//////////////// +void ez_allocate_or_update_non_ez_band(void *wdev_obj); + +void ez_exit( + void *wdev_obj); +void ez_init( + void *ad_obj, + void *wdev_obj, + unsigned char ap_mode); + +void ez_stop( + void *wdev_obj); + + +void ez_update_ap_cap(struct wifi_dev *wdev, BOOLEAN set, unsigned int capability); + + +BOOLEAN ez_apcli_search_best_ap( + void *ad_obj, + void *apcli_entry_obj, + unsigned char inf_idx); + +void ez_restore_channel_config(struct wifi_dev *wdev); + + +unsigned char ez_get_delay_disconnect_count(struct wifi_dev *wdev); + + +void ez_set_delay_disconnect_count(struct wifi_dev *wdev, unsigned char count); + + +void ez_acquire_lock(PRTMP_ADAPTER pAd, struct wifi_dev *wdev,unsigned char lock_id); + +void ez_release_lock(PRTMP_ADAPTER pAd, struct wifi_dev *wdev,unsigned char lock_id); + + +BOOLEAN ez_is_weight_same(struct wifi_dev *wdev, UCHAR * weight); + + +BOOLEAN ez_is_other_band_mlme_running(struct wifi_dev *wdev); + + +BOOLEAN ez_handle_scan_channel_restore(struct wifi_dev *wdev); + + +void ez_triband_insert_tlv(PRTMP_ADAPTER pAd, unsigned int tag_ID, UCHAR * buffer, ULONG* tag_len); + +void ez_handle_peer_disconnection(struct wifi_dev *wdev, unsigned char * mac_addr); + +BOOLEAN ez_need_drop_tx_multicast_packet(struct wifi_dev *wdev); + +BOOLEAN ez_sta_rx_pkt_handle(struct wifi_dev *wdev, RX_BLK *pRxBlk); + + +BOOLEAN ez_apcli_rx_grp_pkt_drop( + IN struct wifi_dev *wdev, + IN struct sk_buff *pSkb); + +BOOLEAN ez_apcli_tx_grp_pkt_drop(struct wifi_dev *wdev,struct sk_buff *pSkb); + + +void ez_apcli_uni_tx_on_dup_link(struct wifi_dev *wdev,struct sk_buff *pSkb); + +void ez_send_delay_disconnect_for_pbc(struct wifi_dev *wdev); +int ez_handle_send_packets(struct wifi_dev *wdev, PNDIS_PACKET pPacket); + +BOOLEAN EzMlmeEnqueue( + IN RTMP_ADAPTER *pAd, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg, + IN ULONG Priv); + + BOOLEAN ez_ap_tx_grp_pkt_drop_to_ez_apcli( + IN struct wifi_dev *wdev, + IN struct sk_buff *pSkb); + +BOOLEAN ez_need_bypass_rx_fwd(struct wifi_dev *wdev); +#ifdef IF_UP_DOWN +BOOLEAN ez_check_valid(void); +BOOLEAN ez_all_intf_up(void *ez_ad); +void ez_update_non_ez_intf_cnt(RTMP_ADAPTER *pAd, void *wdev_obj, BOOLEAN add); +BOOLEAN ez_apcli_check_beacon_params(struct wifi_dev *wdev, beacon_info_tag_t beacon_info); +void ez_apcli_disconnect_both_intf(struct wifi_dev *wdev); +#endif + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/ez_mod_hooks.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/ez_mod_hooks.h new file mode 100644 index 000000000..cd3f3dfd3 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/ez_mod_hooks.h @@ -0,0 +1,293 @@ +#ifndef __EZ_MOD_HOOKS__ +#define __EZ_MOD_HOOKS__ +#include "shared_structs.h" + +extern EZ_ADAPTER * ez_init_hook(void *driver_ad, void *wdev, unsigned char ap_mode); +extern void *ez_get_adapter_hook(void); + +extern unsigned long ez_build_beacon_ie_hook( + ez_dev_t *ezdev, + unsigned char *frame_buf); + +extern unsigned long ez_build_probe_request_ie_hook( + ez_dev_t *ezdev, + unsigned char *frame_buf); + + +extern unsigned long ez_build_probe_response_ie_hook( + ez_dev_t *ezdev, + unsigned char *frame_buf); + +extern unsigned long ez_build_auth_request_ie_hook( + ez_dev_t *ezdev, + unsigned char *peer_addr, + unsigned char *frame_buf); + +extern unsigned long ez_build_auth_response_ie_hook( + ez_dev_t *ezdev, + unsigned char *peer_addr, + unsigned char *frame_buf); + +extern unsigned long ez_build_assoc_request_ie_hook( + ez_dev_t *ezdev, + unsigned char *peer_addr, + unsigned char *frame_buf, + unsigned int frame_buf_len); + +extern unsigned long ez_build_assoc_response_ie_hook( + ez_dev_t *ezdev, + unsigned char *peer_addr, + unsigned char *ap_gtk, + unsigned int ap_gtk_len, + unsigned char *frame_buf); + +extern unsigned char ez_process_probe_request_hook( + ez_dev_t *ezdev, + unsigned char *peer_addr, + void *msg, + unsigned long msg_len); + +extern void ez_process_beacon_probe_response_hook( + ez_dev_t *ezdev, + void *msg, + unsigned long msg_len); + +extern unsigned char ez_process_auth_request_hook( + ez_dev_t *ezdev, + void *auth_info_obj, + void *msg, + unsigned long msg_len); + + +extern USHORT ez_process_auth_response_hook( + ez_dev_t *ezdev, + unsigned char *peer_addr, + void *msg, + unsigned long msg_len); + +extern unsigned short ez_process_assoc_request_hook( + ez_dev_t *ezdev, + unsigned char *peer_addr, + UCHAR *easy_setup_mic_valid, + unsigned char isReassoc, + void *msg, + unsigned long msg_len); + +extern unsigned short ez_process_assoc_response_hook( + ez_dev_t *ezdev, + unsigned char *peer_addr, + void *msg, + unsigned long msg_len); + +extern void ez_show_information_hook( + ez_dev_t *ezdev); + + +extern INT ez_send_broadcast_deauth_proc_hook + (ez_dev_t *ezdev); + +extern unsigned char ez_set_ezgroup_id_hook( + ez_dev_t *ezdev, + unsigned char *ez_group_id, + unsigned int ez_group_id_len, + unsigned char inf_idx); + +extern unsigned char ez_set_group_id_hook( + ez_dev_t *ezdev, + unsigned char *group_id, + unsigned int group_id_len, + unsigned char inf_idx); + +extern unsigned char ez_set_gen_group_id_hook( + ez_dev_t *ezdev, + unsigned char *gen_group_id, + unsigned int gen_group_id_len, + unsigned char inf_idx); + +extern void ez_set_rssi_threshold_hook( + ez_dev_t *ezdev, + char rssi_threshold); + +extern void ez_set_max_scan_delay_hook( + ez_dev_t *ezdev, + UINT32 max_scan_delay); + + +extern void ez_set_api_mode_hook( + ez_dev_t *ezdev, + char ez_api_mode); + +extern INT ez_merge_group_hook( + ez_dev_t *ezdev, + UCHAR *macAddress); + + +extern void ez_apcli_force_ssid_hook( + ez_dev_t *ezdev, + unsigned char *ssid, + unsigned char ssid_len); + +extern void ez_set_force_bssid_hook( + ez_dev_t *ezdev, + UCHAR *mac_addr); + +extern void ez_set_push_bw_hook(ez_dev_t *ezdev, UINT8 same_bw_push); + +extern void ez_handle_action_txstatus_hook(ez_dev_t *ezdev, UINT8 * Addr); + +extern void set_ssid_psk_hook(ez_dev_t *ezdev, + char *ssid1, char *pmk1, char *psk1, + char *ssid2, char *pmk2, char *psk2, + char *ssid3, char *pmk3, char *psk3, + char *EncrypType1, char *EncrypType2, + char *AuthMode1, char *AuthMode2); + + +extern void ez_apcli_link_down_hook(ez_dev_t *ezdev,unsigned long Disconnect_Sub_Reason); + +extern BOOLEAN ez_update_connection_permission_hook( + ez_dev_t *ezdev, enum EZ_CONN_ACTION action); + +extern BOOLEAN ez_is_connection_allowed_hook(ez_dev_t *ezdev); + +extern BOOLEAN ez_probe_rsp_join_action_hook(ez_dev_t *ezdev, + char *network_weight); + +extern void ez_update_connection_hook(ez_dev_t *ezdev); + +//extern void ez_handle_pairmsg4_hook(ez_dev_t *ezdev); +void ez_handle_pairmsg4_hook(ez_dev_t *ezdev, UCHAR *peer_mac); + +extern void ez_roam_hook(ez_dev_t *ezdev, + unsigned char bss_support_easy_setup, + beacon_info_tag_t* bss_beacon_info, + char* bss_bssid, + UCHAR bss_channel); + +extern BOOLEAN ez_set_roam_bssid_hook(ez_dev_t *ezdev, UCHAR *roam_bssid); + +extern void ez_reset_roam_bssid_hook(ez_dev_t *ezdev); + +extern BOOLEAN ez_get_push_bw_hook(ez_dev_t *ezdev); + +extern channel_info_t * ez_get_channel_hook(ez_dev_t *ezdev); + +extern BOOLEAN ez_did_ap_fallback_hook(ez_dev_t *ezdev); + + +extern BOOLEAN ez_ap_fallback_channel(ez_dev_t *ezdev); + +extern void ez_prepare_security_key_hook( + ez_dev_t *ezdev, + unsigned char *peer_addr, + unsigned char authenticator); + +extern enum_group_merge_action_t is_group_merge_candidate_hook(unsigned int easy_setup_capability, + ez_dev_t *ezdev, + void *temp_bss_entry, + UCHAR *Bssid); + +extern void ez_process_action_frame_hook( + ez_dev_t *ezdev, + UCHAR *peer_mac, + UCHAR *Msg, + UINT msg_len); + +extern BOOLEAN check_best_ap_rssi_threshold_hook(ez_dev_t *ezdev, char rssi); + +extern void ez_set_ap_fallback_context_hook(ez_dev_t *ezdev, BOOLEAN fallback, unsigned char fallback_channel); + +extern struct _ez_peer_security_info *ez_peer_table_search_by_addr_hook( + ez_dev_t *ezdev, + unsigned char *addr); + +extern void ez_set_delete_peer_in_differed_context_hook( + void * ezdev, + struct _ez_peer_security_info *ez_peer, + BOOLEAN set); + +extern BOOLEAN ez_is_triband_hook(void); + +extern void * ez_get_otherband_ad_hook(ez_dev_t *ezdev); + +extern unsigned short ez_check_for_ez_enable_hook( + void *msg, + unsigned long msg_len + ); + +extern void ez_update_ap_cap_hook(ez_dev_t *ezdev, BOOLEAN set, unsigned int capability); + +extern void ez_set_delay_disconnect_count_hook(ez_dev_t *ezdev, unsigned char count); + +extern void ez_acquire_lock_hook(EZ_ADAPTER *ez_ad, ez_dev_t *ezdev,unsigned char lock_id); + +extern void ez_release_lock_hook(EZ_ADAPTER *ez_ad, ez_dev_t *ezdev,unsigned char lock_id); + +extern BOOLEAN ez_is_weight_same_hook(ez_dev_t *ezdev, UCHAR *peer_weight); + +extern BOOLEAN ez_is_other_band_mlme_running_hook(ez_dev_t *ezdev); + +extern BOOLEAN ez_handle_scan_channel_restore_hook(ez_dev_t *ezdev); + +extern void ez_triband_insert_tlv_hook(void *ez_ad, + unsigned int tag_ID, UCHAR * buffer, ULONG* tag_len); + +extern void ez_handle_peer_disconnection_hook(ez_dev_t *ezdev, unsigned char * mac_addr); + +extern BOOLEAN ez_sta_rx_pkt_handle_hook(ez_dev_t *ezdev, UCHAR *pPayload, UINT MPDUtotalByteCnt); + +extern BOOLEAN ez_apcli_rx_grp_pkt_drop_hook(ez_dev_t *ezdev,unsigned char * dest); + +extern BOOLEAN ez_apcli_tx_grp_pkt_drop_hook(ez_dev_t *ezdev,struct sk_buff *pSkb); + +extern void send_delay_disconnect_to_peers_hook(void *ap_ezdev); +extern BOOLEAN ez_internet_msghandle_hook(ez_dev_t *ezdev, p_internet_command_t p_internet_command); +extern void ez_custom_data_handle_hook(EZ_ADAPTER *ez_ad, p_ez_custom_data_cmd_t p_custom_data, int length); +extern BOOLEAN ez_is_roaming_ongoing_hook(EZ_ADAPTER *ez_ad); +extern void ez_peer_table_maintenance_hook(EZ_ADAPTER *ez_ad); +extern BOOLEAN ez_port_secured_hook( + ez_dev_t *ezdev, + UCHAR *peer_mac, + unsigned char ap_mode); +extern void ez_ap_peer_beacon_action_hook(ez_dev_t *ezdev, unsigned char * mac_addr, int peer_capability); +extern int ez_handle_send_packets_hook(ez_dev_t *ezdev, NDIS_PACKET *pPacket); + +extern BOOLEAN ez_set_open_group_id_hook( + ez_dev_t *ezdev, + unsigned char *open_group_id, + unsigned int open_group_id_len, + unsigned char inf_idx); + +extern void APTribandRestartNonEzReqAction_hook(EZ_ADAPTER *ez_ad); +extern BOOLEAN ez_ap_tx_grp_pkt_drop_to_ez_apcli_hook(ez_dev_t *ezdev, struct sk_buff *pSkb); + +extern ez_dev_t * ez_start_hook(ez_init_params_t *ez_init_params); +extern void ez_exit_hook(void *driver_ad); +extern VOID ez_connection_alllow_all_hook(EZ_ADAPTER *ez_ad); +extern void ez_stop_hook( + ez_dev_t * ezdev); + +VOID ez_connection_allow_all_hook(EZ_ADAPTER *ez_ad, unsigned char default_pmk_valid); + + +extern VOID ez_scan_timeout_hook(ez_dev_t *ezdev); + +//extern void ez_stop_scan_timeout_hook(ez_dev_t *ezdev); + +extern void ez_group_merge_timeout_hook(ez_dev_t *ezdev); + +extern VOID ez_loop_chk_timeout_hook( + ez_dev_t *ezdev); + +extern BOOLEAN ez_need_bypass_rx_fwd_hook(ez_dev_t *ezdev); +extern void increment_best_ap_rssi_threshold_hook(ez_dev_t *ezdev); + +void ez_allocate_or_update_non_ez_band_hook(void *wdev, void *ad, UINT32 ezdev_type, CHAR func_idx, non_ez_driver_ops_t *driver_ops, UCHAR *channel); +extern void ez_initiate_new_scan_hook(EZ_ADAPTER *ez_ad); +#ifdef IF_UP_DOWN +BOOLEAN ez_check_valid_hook(void); +BOOLEAN ez_all_intf_up_hook(EZ_ADAPTER *ez_ad); +void ez_apcli_disconnect_both_intf_hook(ez_dev_t *ezdev, PUCHAR bssid); +#endif + +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/mt7603_chip_ops.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/mt7603_chip_ops.h new file mode 100644 index 000000000..88dd150d6 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/mt7603_chip_ops.h @@ -0,0 +1,369 @@ +/* + *************************************************************************** + * 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_ez.c + + Abstract: + Easy Setup APIs + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#ifndef __EZ_chip_ops_H__ +#define __EZ_chip_ops_H__ + +#ifdef WH_EZ_SETUP +#include "rt_config.h" + +//ez_chipops_t ez_chipops; + +//int EzDebugLevel = DBG_LVL_ERROR; + +//---------------------------------------------------------------------------------------------------------- +// Arvind code +//----------------------------------------------------------------------------------------------------------- + +#define SET_AUTHMODE_WPA2PSK(_Auth) (_Auth = Ndis802_11AuthModeWPA2PSK) +#define SET_CIPHER_CCMP128(_encry) (_encry) = Ndis802_11AESEnable +#define IS_ADPTR_EZ_SETUP_ENABLED(pAd) (pAd->ApCfg.MBSSID[0].wdev.enable_easy_setup) +#define IS_EZ_SETUP_ENABLED(_wdev) (((_wdev)->enable_easy_setup) == TRUE) +#define IS_EZ_SETUP_STARTED(_wdev) (((_wdev)->ez_driver_params.ez_started) == TRUE) + +#ifdef EZ_DUAL_BAND_SUPPORT +#define IS_SINGLE_CHIP_DBDC(_pAd) ((PRTMP_ADAPTER)_pAd)->SingleChip +#define IS_DUAL_CHIP_DBDC(_pAd) !(IS_SINGLE_CHIP_DBDC(_pAd)) +#else +#define IS_SINGLE_CHIP_DBDC(_pAd) 1 +#define IS_DUAL_CHIP_DBDC(_pAd) 0 +#endif + +int EzDebugLevel = DBG_LVL_ERROR; + +#define EZ_DEBUG(__debug_cat, __debug_sub_cat, __debug_level, __fmt) \ +do{ \ + if (__debug_level <= EzDebugLevel) { \ + printk __fmt;\ + } \ +}while(0) + +#define EZ_TIMER_INIT(__ad, __data, __time_var, __time_flg, __time_fn) \ + do{ \ + RTMPInitTimer((__ad), (__time_var), GET_TIMER_FUNCTION(__time_fn), (__data), FALSE); \ + (__time_flg) = FALSE; \ + }while(0) + +#define EZ_CANCEL_TIMER(__time_var, __time_flg) \ + do{ \ + unsigned char __cancelled; \ + RTMPCancelTimer(__time_var, &__cancelled); \ + (__time_flg) = FALSE; \ + }while(0) + +typedef struct ez_timer_s{ + RALINK_TIMER_STRUCT ez_timer; + BOOLEAN ez_timer_running; +}ez_timer_t; + +VOID UpdateBeaconHandler( + void *ad_obj, + struct wifi_dev *wdev, + UCHAR BCN_UPDATE_REASON); + +void ez_hex_dump( + char *str, + unsigned char *pSrcBufVA, + unsigned int SrcBufLen); + +void ez_install_pairwise_key_mt7603( + RTMP_ADAPTER *pAd, + struct wifi_dev *wdev, + char *peer_mac, + unsigned char *pmk, + unsigned char *ptk, + unsigned char authenticator); + +unsigned char ez_RandomByte_mt7603(RTMP_ADAPTER *pAd); + +void ez_DH_PublicKey_Generate_mt7603( + UINT8 GValue[], + UINT GValueLength, + UINT8 PValue[], + UINT PValueLength, + UINT8 PrivateKey[], + UINT PrivateKeyLength, + UINT8 PublicKey[], + UINT *PublicKeyLength); + +void ez_RT_DH_SecretKey_Generate_mt7603( + UINT8 PublicKey[], + UINT PublicKeyLength, + UINT8 PValue[], + UINT PValueLength, + UINT8 PrivateKey[], + UINT PrivateKeyLength, + UINT8 SecretKey[], + UINT *SecretKeyLength); + +void ez_RT_SHA256_mt7603( + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 DigestMessage[]); + +VOID ez_WpaDerivePTK_mt7603( + RTMP_ADAPTER *pAd, + UCHAR *PMK, + UCHAR *ANonce, + UCHAR *AA, + UCHAR *SNonce, + UCHAR *SA, + UCHAR *output, + UINT len); + +INT ez_AES_Key_Unwrap_mt7603( + UINT8 CipherText[], + UINT CipherTextLength, + UINT8 Key[], + UINT KeyLength, + UINT8 PlainText[], + UINT *PlainTextLength); + + +#ifdef APCLI_SUPPORT +void ez_apcli_install_group_key_mt7603( + RTMP_ADAPTER *pAd, + char *peer_gtk, + unsigned char gtk_len, + MAC_TABLE_ENTRY *entry); +#endif /* APCLI_SUPPORT */ + +INT ez_wlan_config_get_ht_bw_mt7603(RTMP_ADAPTER *pAd); + +#ifdef DOT11_VHT_AC +INT ez_wlan_config_get_vht_bw_mt7603(RTMP_ADAPTER *pAd); +#endif + +INT ez_wlan_operate_get_ht_bw_mt7603(RTMP_ADAPTER *pAd); + +INT ez_wlan_operate_get_ext_cha_mt7603(RTMP_ADAPTER *pAd); + +INT ez_wlan_config_get_ext_cha_mt7603(RTMP_ADAPTER *pAd); + +int ez_get_cli_aid_mt7603( + RTMP_ADAPTER *pAd, + char *peer_mac); + +void ez_cancel_timer_mt7603( + RTMP_ADAPTER *pAd, + void * timer_struct); + +void ez_set_timer_mt7603( + RTMP_ADAPTER *pAd, + void * timer_struct, + unsigned long time); + +int ez_is_timer_running_mt7603( + RTMP_ADAPTER *pAd, + void * timer_struct); + +#ifdef APCLI_SUPPORT +int get_apcli_enable_mt7603( + RTMP_ADAPTER *pAd, + int ifIndex); +#endif + +int ez_ApScanRunning_mt7603(RTMP_ADAPTER *pAd); + +void ez_send_unicast_deauth_mt7603( + void *ad_obj, + UCHAR *peer_addr); + +//void ez_ChipOps_restore_channel_config_mt7603( RTMP_ADAPTER *pAd); + +void ez_UpdateBeaconHandler_mt7603( + RTMP_ADAPTER *ez_ad, + struct wifi_dev *wdev, + UCHAR reason); + +//void ez_ChipOps_initiate_new_scan_mt7603(RTMP_ADAPTER *pAd,); + +void ez_update_security_setting_mt7603( + RTMP_ADAPTER *pAd, + struct wifi_dev *wdev, + unsigned char *pmk); + +#ifdef WSC_AP_SUPPORT +void ez_updage_ap_wsc_profile_mt7603( + RTMP_ADAPTER *pAd, + struct wifi_dev *wdev, + unsigned char if_idx); +#endif /* WSC_AP_SUPPORT */ + +//void ez_APScanCnclAction_mt7603(void *pAd); + +//void ez_ChipOps_send_loop_detect_pkt_mt7603(RTMP_ADAPTER *pAd,); + +/*INT ez_ChipOps_update_ap_mt7603( + void *ez_ad, + void *updated_configs, + int gid_different, + int band_switched); + +INT ez_ChipOp_ez_update_cli_mt7603( + void *ez_ad, + void *updated_configs, + int gid_different, + int band_switched); + +void ez_ChipOps_update_ap_peer_record_mt7603( + void *ez_ad, + int band_switched); + +void ez_ChipOps_update_cli_peer_record_mt7603( + void *ez_ad, + int band_switched); +*/ + +void ez_MiniportMMRequest_mt7603( + RTMP_ADAPTER *pAd, + UCHAR QueIdx, + UCHAR *out_buf, + UINT frame_len); + +void ez_NdisGetSystemUpTime_mt7603(ULONG *time); + +INT ez_AES_Key_Wrap_mt7603( + UINT8 PlainText[], + UINT PlainTextLength, + UINT8 Key[], + UINT KeyLength, + UINT8 CipherText[], + UINT *CipherTextLength); + +INT ez_RtmpOSWrielessEventSendExt_mt7603( + PNET_DEV pNetDev, + UINT32 eventType, + INT flags, + PUCHAR pSrcMac, + PUCHAR pData, + UINT32 dataLen); + +void ez_send_broadcast_deauth_mt7603( + RTMP_ADAPTER *pAd, + struct wifi_dev *wdev); + +void ez_ChipOp_MgtMacHeaderInit_mt7603( + void *pAd, + HEADER_802_11 *pHdr80211, + UCHAR SubType, + UCHAR ToDs, + UCHAR *pDA, + UCHAR *pSA, + UCHAR *pBssid); + +void ez_ChipOp_apcli_stop_auto_connect_mt7603( + void *pAd, + BOOLEAN enable); + +void ez_timer_init_mt7603( + RTMP_ADAPTER *pAd, + void* timer, + void *callback); + +void ez_set_ap_ssid_null_mt7603( + RTMP_ADAPTER *pAd, + INT apidx); + +void ez_set_entry_apcli_mt7603( + RTMP_ADAPTER *pAd, + UCHAR *mac_addr, + BOOLEAN is_apcli); + +void* ez_get_pentry_mt7603( + RTMP_ADAPTER *pAd, + UCHAR *mac_addr); + +void ez_mark_entry_duplicate_mt7603( + RTMP_ADAPTER *pAd, + UCHAR *mac_addr); + +void ez_restore_cli_config_mt7603(void *pAd); + +void ez_ScanTableInit_mt7603(RTMP_ADAPTER *pAd); + +//--------------------------------------------------------- +// raghav +//----------------------------------------------------------k + +void ez_wlan_operate_set_ht_bw_mt7603( + RTMP_ADAPTER *pAd, + UINT8 ht_bw); + +void ez_wlan_operate_set_ext_cha_mt7603( + RTMP_ADAPTER *pAd, + UINT8 ext_cha); + +INT rtmp_set_channel_mt7603( + RTMP_ADAPTER *pAd, + struct wifi_dev *wdev, + UCHAR Channel); + +void ez_APScanCnclAction_mt7603(RTMP_ADAPTER *pAd); + +/* Form and transmit Custom loop detect Pkt*/ + void ez_send_loop_detect_pkt_mt7603( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pMacEntry, + IN PUCHAR pOtherCliMac); + + +#ifdef DOT11_N_SUPPORT + +/* + ======================================================================== + Rakesh: based on ApCliCheckHt + + ======================================================================== +*/ +BOOLEAN ez_ApCliSetHt_mt7603( + IN APCLI_STRUCT *pApCliEntry, + MAC_TABLE_ENTRY *pEntry); + +#endif + +void ez_update_cli_peer_record_mt7603( + void * ad_obj, + void * wdev_obj, + BOOLEAN band_switched, + PUCHAR peer_addr); + + +void ez_update_ap_peer_record_mt7603( + void * ad_obj, + void * wdev_obj, + BOOLEAN band_switched, + PUCHAR peer_addr); + + +//---------------------------------------------------------------------------------------------------------- +// chip ops +//----------------------------------------------------------------------------------------------------------- + +#endif +#endif + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/mt7603_chip_ops_api.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/mt7603_chip_ops_api.h new file mode 100644 index 000000000..0084caf05 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/mt7603_chip_ops_api.h @@ -0,0 +1,277 @@ +/* + *************************************************************************** + * 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_ez.c + + Abstract: + Easy Setup APIs + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +//#ifndef __EZ_chip_ops_api_H__ +//#define __EZ_chip_ops_api_H__ + +#ifdef WH_EZ_SETUP + +#include "shared_structs.h" + +unsigned char ez_driver_ops_RandomByte_mt7603(void *ezdev); + +void ez_driver_ops_GenRandom_mt7603( + void *ezdev, + UCHAR *macAddr, + UCHAR *random); + +void ez_driver_ops_DH_PublicKey_Generate_mt7603( + void * ezdev, + UINT8 GValue[], + UINT GValueLength, + UINT8 PValue[], + UINT PValueLength, + UINT8 PrivateKey[], + UINT PrivateKeyLength, + UINT8 PublicKey[], + UINT *PublicKeyLength); + +void ez_driver_ops_RT_DH_SecretKey_Generate_mt7603( + void * ezdev, + UINT8 PublicKey[], + UINT PublicKeyLength, + UINT8 PValue[], + UINT PValueLength, + UINT8 PrivateKey[], + UINT PrivateKeyLength, + UINT8 SecretKey[], + UINT *SecretKeyLength); + +void ez_driver_ops_RT_SHA256_mt7603( + void * ezdev, + IN const UINT8 Message[], + IN UINT MessageLen, + OUT UINT8 DigestMessage[]); + +VOID ez_driver_ops_WpaDerivePTK_mt7603( + void *ezdev, + UCHAR *PMK, + UCHAR *ANonce, + UCHAR *AA, + UCHAR *SNonce, + UCHAR *SA, + UCHAR *output, + UINT len); + +INT ez_driver_ops_AES_Key_Unwrap_mt7603( + void * ezdev, + UINT8 CipherText[], + UINT CipherTextLength, + UINT8 Key[], + UINT KeyLength, + UINT8 PlainText[], + UINT *PlainTextLength); + +void ez_driver_ops_install_pairwise_key_mt7603( + void *ezdev, + char *peer_mac, + unsigned char *pmk, + unsigned char *ptk, + unsigned char authenticator); + +#ifdef APCLI_SUPPORT +void ez_driver_ops_apcli_install_group_key_mt7603( + void * ezdev, + char *peer_mac, + char *peer_gtk, + unsigned char gtk_len); +#endif + +int ez_driver_ops_wlan_config_get_ht_bw_mt7603(void *ezdev); + +int ez_driver_ops_wlan_config_get_vht_bw_mt7603(void *ezdev); + +int ez_driver_ops_wlan_operate_get_ht_bw_mt7603(void *ezdev); + +int ez_driver_ops_wlan_operate_get_vht_bw_mt7603(void *ezdev); + +int ez_driver_ops_wlan_config_get_ext_cha_mt7603(void *ezdev); + +int ez_driver_ops_wlan_operate_get_ext_cha_mt7603(void *ezdev); + +int ez_driver_ops_get_cli_aid_mt7603( + void *ezdev, + char * peer_mac); + +void ez_driver_ops_ez_cancel_timer_mt7603( + void * ezdev, + void * timer_struct); + +void ez_driver_ops_ez_set_timer_mt7603( + void * ezdev, + void * timer_struct, + unsigned long time); + +BOOLEAN ez_driver_ops_is_timer_running_mt7603( + void *ezdev, + void * timer_struct); + +int ez_driver_ops_get_apcli_enable_mt7603(void *ezdev); + +int ez_driver_ops_ApScanRunning_mt7603(void *ezdev); + +void ez_driver_ops_send_unicast_deauth_mt7603( + void *ezdev, + char *peer_mac); + +void ez_driver_ops_UpdateBeaconHandler_mt7603( + void *ezdev, + int reason); + +void ez_driver_ops_update_security_setting_mt7603( + void *ezdev, + unsigned char *pmk); + +void ez_driver_ops_update_ap_wsc_profile_mt7603(void *ezdev); + +void ez_driver_ops_MiniportMMRequest_mt7603( + void *ezdev, + char *out_buf, + int frame_len, + BOOLEAN need_tx_status); + +void ez_driver_ops_NdisGetSystemUpTime_mt7603( + void *ezdev, + ULONG *time); + + +INT ez_driver_ops_AES_Key_Wrap_mt7603( + void *ezdev, + UINT8 PlainText[], + UINT PlainTextLength, + UINT8 Key[], + UINT KeyLength, + UINT8 CipherText[], + UINT *CipherTextLength); + +INT ez_driver_ops_RtmpOSWrielessEventSendExt_mt7603( + void *ezdev, + UINT32 eventType, + INT flags, + PUCHAR pSrcMac, + PUCHAR pData, + UINT32 dataLen); + +void ez_driver_ops_send_broadcast_deauth_mt7603(void *ezdev); + +void ez_driver_ops_apcli_stop_auto_connect_mt7603( + void *ezdev, + BOOLEAN enable); + +void ez_driver_ops_timer_init_mt7603( + void *ezdev, + void* timer, + void *callback); + +void ez_driver_ops_set_ap_ssid_null_mt7603(void *ezdev); +void* ez_driver_ops_get_pentry_mt7603( + void *ezdev, + UCHAR *mac_addr); + +void ez_driver_ops_mark_entry_duplicate_mt7603( + void *ezdev, + UCHAR *mac_addr); + +void ez_driver_ops_restore_cli_config_mt7603(void *ezdev); + +void ez_driver_ops_ScanTableInit_mt7603(void *ezdev); + +void ez_driver_ops_RT_HMAC_SHA1_mt7615( + void * ezdev, + UINT8 Key[], + UINT KeyLen, + UINT8 Message[], + UINT MessageLen, + UINT8 MAC[], + UINT MACLen); + +void ez_driver_ops_wlan_config_set_ht_bw_mt7603(void *ezdev, UINT8 ht_bw); + +void ez_driver_ops_wlan_config_set_ext_cha_mt7603(void *ezdev, UINT8 ext_cha); + +// +// raghav +// +void ez_driver_ops_wlan_operate_set_ht_bw_mt7603( + void *ezdev, + UINT8 ht_bw); + +void ez_driver_ops_wlan_operate_set_ext_cha_mt7603( + void *ezdev, + UINT8 ext_cha); + +void ez_driver_ops_rtmp_set_channel_mt7603( + void *ad_obj, + void * wdev_obj, + UCHAR Channel); + +void ez_driver_ops_APScanCnclAction_mt7603(void *ezdev); + +void ez_driver_ops_send_loop_detect_pkt_mt7603( + void *ezdev, + PUCHAR pOtherCliMac); + +void ez_driver_ops_update_ap_peer_record_mt7603( + void *ezdev, + BOOLEAN band_switched, + PUCHAR peer_addr); + +void ez_driver_ops_update_cli_peer_record_mt7603( + void *ezdev, + BOOLEAN band_switched, + PUCHAR peer_addr); + +void ez_driver_ops_MgtMacHeaderInit_mt7603( + void *ezdev, + HEADER_802_11_EZ *pHdr80211, + UCHAR SubType, + UCHAR ToDs, + UCHAR *pDA, + UCHAR *pSA, + UCHAR *pBssid); + +// prakhar ::: + +BOOLEAN ez_driver_ops_update_ap_mt7603( + void *ezdev, + void *updated_configs); + +BOOLEAN ez_driver_ops_update_cli_mt7603( + void *ezdev, + void *updated_configs); + +void ez_driver_ops_ApSiteSurvey_mt7603( + void *ezdev, + int scan_one_channel); + +void ez_driver_ops_wlan_config_set_vht_bw_mt7603(void *ezdev, UINT8 vht_bw); + +INT ez_driver_ops_SetCommonHtVht_mt7603(void *ezdev); + +#endif +//#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/mt7603_driver_specific_func.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/mt7603_driver_specific_func.h new file mode 100644 index 000000000..b7a88074a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/easy_setup/mt7603_driver_specific_func.h @@ -0,0 +1,206 @@ +/* + *************************************************************************** + * 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_ez.c + + Abstract: + Easy Setup APIs + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#ifndef __EZ_driver_specific_fun_H__ +#define __EZ_driver_specific_fun_H__ +#ifdef WH_EZ_SETUP + +#define SET_AUTHMODE_WPA2PSK(_Auth) (_Auth = Ndis802_11AuthModeWPA2PSK) +#define SET_ENCRYTYPE_AES(_encry) (_encry = Ndis802_11AESEnable) +/*#define IS_ADPTR_EZ_SETUP_ENABLED(pAd) (pAd->ApCfg.MBSSID[0].wdev.ez_driver_params.enable_easy_setup)*/ +/*#define VALID_UCAST_ENTRY_WCID(_wcid) (_wcid < MAX_LEN_OF_MAC_TABLE) move to rtmp_def.h, mbo also used.*/ + +#define CLEAR_SEC_AKM(_AKMMap) (_AKMMap = 0x0) +#define SET_AKM_OPEN(_AKMMap) (_AKMMap |= (1 << SEC_AKM_OPEN)) +#define SET_AKM_SHARED(_AKMMap) (_AKMMap |= (1 << SEC_AKM_SHARED)) +#define SET_AKM_AUTOSWITCH(_AKMMap) (_AKMMap |= (1 << SEC_AKM_AUTOSWITCH)) +#define SET_AKM_WPA1(_AKMMap) (_AKMMap |= (1 << SEC_AKM_WPA1)) +#define SET_AKM_WPA1PSK(_AKMMap) (_AKMMap |= (1 << SEC_AKM_WPA1PSK)) +#define SET_AKM_WPANONE(_AKMMap) (_AKMMap |= (1 << SEC_AKM_WPANone)) +#define SET_AKM_WPA2(_AKMMap) (_AKMMap |= (1 << SEC_AKM_WPA2)) +#define SET_AKM_WPA2PSK(_AKMMap) (_AKMMap |= (1 << SEC_AKM_WPA2PSK)) +#define SET_AKM_FT_WPA2(_AKMMap) (_AKMMap |= (1 << SEC_AKM_FT_WPA2)) +#define SET_AKM_FT_WPA2PSK(_AKMMap) (_AKMMap |= (1 << SEC_AKM_FT_WPA2PSK)) +#define SET_AKM_WPA2_SHA256(_AKMMap) (_AKMMap |= (1 << SEC_AKM_WPA2_SHA256)) +#define SET_AKM_WPA2PSK_SHA256(_AKMMap) (_AKMMap |= (1 << SEC_AKM_WPA2PSK_SHA256)) +#define SET_AKM_TDLS(_AKMMap) (_AKMMap |= (1 << SEC_AKM_TDLS)) +#define SET_AKM_SAE_SHA256(_AKMMap) (_AKMMap |= (1 << SEC_AKM_SAE_SHA256)) +#define SET_AKM_FT_SAE_SHA256(_AKMMap) (_AKMMap |= (1 << SEC_AKM_FT_SAE_SHA256)) +#define SET_AKM_SUITEB_SHA256(_AKMMap) (_AKMMap |= (1 << SEC_AKM_SUITEB_SHA256)) +#define SET_AKM_SUITEB_SHA384(_AKMMap) (_AKMMap |= (1 << SEC_AKM_SUITEB_SHA384)) +#define SET_AKM_FT_WPA2_SHA384(_AKMMap) (_AKMMap |= (1 << SEC_AKM_FT_WPA2_SHA384)) +#ifdef WAPI_SUPPORT +#define SET_AKM_WAICERT(_AKMMap) (_AKMMap |= (1 << SEC_AKM_WAICERT)) +#define SET_AKM_WPIPSK(_AKMMap) (_AKMMap |= (1 << SEC_AKM_WAIPSK)) +#endif /* WAPI_SUPPORT */ + + +#define IS_CIPHER_NONE(_Cipher) (((_Cipher) & (1 << SEC_CIPHER_NONE)) > 0) +#define IS_CIPHER_WEP40(_Cipher) (((_Cipher) & (1 << SEC_CIPHER_WEP40)) > 0) +#define IS_CIPHER_WEP104(_Cipher) (((_Cipher) & (1 << SEC_CIPHER_WEP104)) > 0) +#define IS_CIPHER_WEP128(_Cipher) (((_Cipher) & (1 << SEC_CIPHER_WEP128)) > 0) +#define IS_CIPHER_WEP(_Cipher) (((_Cipher) & ((1 << SEC_CIPHER_WEP40) | (1 << SEC_CIPHER_WEP104) | (1 << SEC_CIPHER_WEP128))) > 0) +#define IS_CIPHER_TKIP(_Cipher) (((_Cipher) & (1 << SEC_CIPHER_TKIP)) > 0) +#define IS_CIPHER_WEP_TKIP_ONLY(_Cipher) ((IS_CIPHER_WEP(_Cipher) || IS_CIPHER_TKIP(_Cipher)) && (_Cipher < (1 << SEC_CIPHER_CCMP128))) +#define IS_CIPHER_CCMP128(_Cipher) (((_Cipher) & (1 << SEC_CIPHER_CCMP128)) > 0) +#define IS_CIPHER_CCMP256(_Cipher) (((_Cipher) & (1 << SEC_CIPHER_CCMP256)) > 0) +#define IS_CIPHER_GCMP128(_Cipher) (((_Cipher) & (1 << SEC_CIPHER_GCMP128)) > 0) +#define IS_CIPHER_GCMP256(_Cipher) (((_Cipher) & (1 << SEC_CIPHER_GCMP256)) > 0) +#define IS_CIPHER_BIP_CMAC128(_Cipher) (((_Cipher) & (1 << SEC_CIPHER_BIP_CMAC128)) > 0) + + +#define IS_AKM_OPEN(_AKMMap) ((_AKMMap & (1 << SEC_AKM_OPEN)) > 0) +#define IS_AKM_SHARED(_AKMMap) ((_AKMMap & (1 << SEC_AKM_SHARED)) > 0) +#define IS_AKM_AUTOSWITCH(_AKMMap) ((_AKMMap & (1 << SEC_AKM_AUTOSWITCH)) > 0) +#define IS_AKM_WPA1(_AKMMap) ((_AKMMap & (1 << SEC_AKM_WPA1)) > 0) +#define IS_AKM_WPA1PSK(_AKMMap) ((_AKMMap & (1 << SEC_AKM_WPA1PSK)) > 0) +#define IS_AKM_WPANONE(_AKMMap) ((_AKMMap & (1 << SEC_AKM_WPANone)) > 0) +#define IS_AKM_WPA2(_AKMMap) ((_AKMMap & (1 << SEC_AKM_WPA2)) > 0) +#define IS_AKM_WPA2PSK(_AKMMap) ((_AKMMap & (1 << SEC_AKM_WPA2PSK)) > 0) +#define IS_AKM_FT_WPA2(_AKMMap) ((_AKMMap & (1 << SEC_AKM_FT_WPA2)) > 0) +#define IS_AKM_FT_WPA2PSK(_AKMMap) ((_AKMMap & (1 << SEC_AKM_FT_WPA2PSK)) > 0) +#define IS_AKM_WPA2_SHA256(_AKMMap) ((_AKMMap & (1 << SEC_AKM_WPA2_SHA256)) > 0) +#define IS_AKM_WPA2PSK_SHA256(_AKMMap) ((_AKMMap & (1 << SEC_AKM_WPA2PSK_SHA256)) > 0) +#define IS_AKM_TDLS(_AKMMap) ((_AKMMap & (1 << SEC_AKM_TDLS)) > 0) +#define IS_AKM_SAE_SHA256(_AKMMap) ((_AKMMap & (1 << SEC_AKM_SAE_SHA256)) > 0) +#define IS_AKM_FT_SAE_SHA256(_AKMMap) ((_AKMMap & (1 << SEC_AKM_FT_SAE_SHA256)) > 0) +#define IS_AKM_SUITEB_SHA256(_AKMMap) ((_AKMMap & (1 << SEC_AKM_SUITEB_SHA256)) > 0) +#define IS_AKM_SUITEB_SHA384(_AKMMap) ((_AKMMap & (1 << SEC_AKM_SUITEB_SHA384)) > 0) +#define IS_AKM_FT_WPA2_SHA384(_AKMMap) ((_AKMMap & (1 << SEC_AKM_FT_WPA2_SHA384)) > 0) +#ifdef WAPI_SUPPORT +#define IS_AKM_WAICERT(_AKMMap) ((_AKMMap & (1 << SEC_AKM_WAICERT)) > 0) +#define IS_AKM_WPIPSK(_AKMMap) ((_AKMMap & (1 << SEC_AKM_WAIPSK)) > 0) +#endif /* WAPI_SUPPORT */ + +#define IS_AKM_PSK(_AKMMap) (IS_AKM_WPA1PSK(_AKMMap) \ + || IS_AKM_WPA2PSK(_AKMMap)) + +#define IS_AKM_1X(_AKMMap) (IS_AKM_WPA1(_AKMMap) \ + || IS_AKM_WPA2(_AKMMap)) + +#define IS_AKM_WPA_CAPABILITY(_AKMMap) (IS_AKM_WPA1(_AKMMap) \ + || IS_AKM_WPA1PSK(_AKMMap) \ + || IS_AKM_WPANONE(_AKMMap) \ + || IS_AKM_WPA2(_AKMMap) \ + || IS_AKM_WPA2PSK(_AKMMap) \ + || IS_AKM_WPA2_SHA256(_AKMMap) \ + || IS_AKM_WPA2PSK_SHA256(_AKMMap)) +typedef enum _SEC_CIPHER_MODE { + SEC_CIPHER_NONE, + SEC_CIPHER_WEP40, + SEC_CIPHER_WEP104, + SEC_CIPHER_WEP128, + SEC_CIPHER_TKIP, + SEC_CIPHER_CCMP128, + SEC_CIPHER_CCMP256, + SEC_CIPHER_GCMP128, + SEC_CIPHER_GCMP256, + SEC_CIPHER_BIP_CMAC128, + SEC_CIPHER_BIP_CMAC256, + SEC_CIPHER_BIP_GMAC128, + SEC_CIPHER_BIP_GMAC256, + SEC_CIPHER_WPI_SMS4, /* WPI SMS4 support */ + SEC_CIPHER_MAX /* Not a real mode, defined as upper bound */ +} SEC_CIPHER_MODE; + + +#define CLEAR_PAIRWISE_CIPHER(_SecConfig) ((_SecConfig)->PairwiseCipher = 0x0) +#define CLEAR_GROUP_CIPHER(_SecConfig) ((_SecConfig)->GroupCipher = 0x0) +#define GET_PAIRWISE_CIPHER(_SecConfig) ((_SecConfig)->PairwiseCipher) +#define GET_GROUP_CIPHER(_SecConfig) ((_SecConfig)->GroupCipher) +#define CLEAR_CIPHER(_cipher) (_cipher = 0x0) +#define SET_CIPHER_NONE(_cipher) (_cipher |= (1 << SEC_CIPHER_NONE)) +#define SET_CIPHER_WEP40(_cipher) (_cipher |= (1 << SEC_CIPHER_WEP40)) +#define SET_CIPHER_WEP104(_cipher) (_cipher |= (1 << SEC_CIPHER_WEP104)) +#define SET_CIPHER_WEP128(_cipher) (_cipher |= (1 << SEC_CIPHER_WEP128)) +#define SET_CIPHER_WEP(_cipher) (_cipher |= (1 << SEC_CIPHER_WEP40) | (1 << SEC_CIPHER_WEP104) | (1 << SEC_CIPHER_WEP128)) +#define SET_CIPHER_TKIP(_cipher) (_cipher |= (1 << SEC_CIPHER_TKIP)) +#define SET_CIPHER_CCMP128(_cipher) (_cipher |= (1 << SEC_CIPHER_CCMP128)) +#define SET_CIPHER_CCMP256(_cipher) (_cipher |= (1 << SEC_CIPHER_CCMP256)) +#define SET_CIPHER_GCMP128(_cipher) (_cipher |= (1 << SEC_CIPHER_GCMP128)) +#define SET_CIPHER_GCMP256(_cipher) (_cipher |= (1 << SEC_CIPHER_GCMP256)) +#ifdef WAPI_SUPPORT +#define SET_CIPHER_WPI_SMS4(_cipher) (_cipher |= (1 << SEC_CIPHER_WPI_SMS4)) +#endif /* WAPI_SUPPORT */ + + +/* 802.11 authentication and key management */ +typedef enum _SEC_AKM_MODE { + SEC_AKM_OPEN, + SEC_AKM_SHARED, + SEC_AKM_AUTOSWITCH, + SEC_AKM_WPA1, /* Enterprise security over 802.1x */ + SEC_AKM_WPA1PSK, + SEC_AKM_WPANone, /* For Win IBSS, directly PTK, no handshark */ + SEC_AKM_WPA2, /* Enterprise security over 802.1x */ + SEC_AKM_WPA2PSK, + SEC_AKM_FT_WPA2, + SEC_AKM_FT_WPA2PSK, + SEC_AKM_WPA2_SHA256, + SEC_AKM_WPA2PSK_SHA256, + SEC_AKM_TDLS, + SEC_AKM_SAE_SHA256, + SEC_AKM_FT_SAE_SHA256, + SEC_AKM_SUITEB_SHA256, + SEC_AKM_SUITEB_SHA384, + SEC_AKM_FT_WPA2_SHA384, + SEC_AKM_WAICERT, /* WAI certificate authentication */ + SEC_AKM_WAIPSK, /* WAI pre-shared key */ + SEC_AKM_MAX /* Not a real mode, defined as upper bound */ +} SEC_AKM_MODE, *PSEC_AKM_MODE; + +typedef enum{ + RUNNING = 0, + PASS, + FAIL +}LOOPBACK_STATUS; + +enum BCN_UPDATE_REASON +{ + INTERFACE_STATE_CHANGE = 0, /*there is interface up or down, check related TXD handle*/ + IE_CHANGE = 1, /* simple IE change, just update the corresponding interface content. */ + AP_RENEW = 2, /* prepared All beacon for All active interface. */ + PRETBTT_UPDATE = 3, /* update function routine, source could from INT isr or timer or event notify. */ +}; + +VOID UpdateBeaconHandler( + void *ad_obj, + struct wifi_dev *wdev, + UCHAR BCN_UPDATE_REASON); + +INT rtmp_set_channel( + RTMP_ADAPTER *pAd, + struct wifi_dev *wdev, + UCHAR Channel); + +UINT32 AuthMode_to_AKM_map(NDIS_802_11_AUTHENTICATION_MODE authMode); +NDIS_802_11_AUTHENTICATION_MODE AKM_map_to_AuthMode(UINT32 _AKMMap); +UINT32 WepStatus_to_PairwiseCipher(NDIS_802_11_WEP_STATUS WepStatus); +NDIS_802_11_WEP_STATUS PairwiseCipher_to_WepStatus(UINT32 PairwiseCipher); + +#endif /* WH_EZ_SETUP */ +#endif /* __EZ_chip_ops_api_H__*/ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ecc.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ecc.h new file mode 100644 index 000000000..4be7d4239 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ecc.h @@ -0,0 +1,149 @@ +#ifndef __ECC_H__ +#define __ECC_H__ + +#include "bn.h" +#include "sae_cmm.h" + +typedef struct __EC_GROUP_INFO_BI { + INT32 group_id; + SAE_BN *prime; + SAE_BN *order; + SAE_BN *a; + SAE_BN *b; + SAE_BN *gx; + SAE_BN *gy; + SAE_BN *cofactor; + MONT_STRUC *mont; + UCHAR is_minus_3; + UCHAR is_init; +} EC_GROUP_INFO_BI, *PEC_GROUP_INFO_BI; + +typedef struct __EC_GROUP_INFO { + INT32 group_id; + const UCHAR *prime; + UINT32 prime_len; + const UCHAR *order; + UINT32 order_len; + const UCHAR *a; + UINT32 a_len; + const UCHAR *b; + UINT32 b_len; + const UCHAR *X; + UINT32 X_len; + const UCHAR *R; + UINT32 R_len; + const UCHAR *PInverse; + UINT32 PInverse_len; + UINT16 bits_of_R; +} EC_GROUP_INFO, *PEC_GROUP_INFO; + +struct __EC_GROUP_INFO *get_ecc_group_info( + IN INT32 group); + +EC_GROUP_INFO_BI *get_ecc_group_info_bi( + IN INT32 group); + +VOID group_info_bi_deinit( + VOID); + +VOID ecc_point_init( + IN BIG_INTEGER_EC_POINT * *ec_point_res); + +VOID ecc_point_free( + IN BIG_INTEGER_EC_POINT * *ec_point_res); + +VOID ecc_point_copy( + IN BIG_INTEGER_EC_POINT * point, + OUT BIG_INTEGER_EC_POINT * *ec_point_res); + +/* if (x1, y2) != (x2, y2), but x1 = x2 => result is infinity */ +/* if point1 + point2 and point1 is infinity => result is point2 */ +VOID ecc_point_add( + IN BIG_INTEGER_EC_POINT * point, + IN BIG_INTEGER_EC_POINT * point2, + IN struct __EC_GROUP_INFO_BI *ec_group_bi, + OUT BIG_INTEGER_EC_POINT * *ec_point_res); +/* if point is infinity, result is infinity */ +VOID ecc_point_double( + IN BIG_INTEGER_EC_POINT * point, + IN struct __EC_GROUP_INFO_BI *ec_group_bi, + OUT BIG_INTEGER_EC_POINT * *ec_point_res); + +VOID ecc_point_add_3d( + IN BIG_INTEGER_EC_POINT * point, + IN BIG_INTEGER_EC_POINT * point2, + IN struct __EC_GROUP_INFO_BI *ec_group_bi, + OUT BIG_INTEGER_EC_POINT * *ec_point_res); + +VOID ecc_point_double_3d( + IN BIG_INTEGER_EC_POINT * point, + IN struct __EC_GROUP_INFO_BI *ec_group_bi, + OUT BIG_INTEGER_EC_POINT * *ec_point_res); + +VOID ecc_point_3d_to_2d( + IN struct __EC_GROUP_INFO_BI *ec_group_bi, + INOUT BIG_INTEGER_EC_POINT * ec_point_res); + +VOID ecc_point_set_z_to_one( + INOUT BIG_INTEGER_EC_POINT * ec_point_res); + +/* https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication */ +/* double and add */ +VOID ecc_point_mul_dblandadd( + IN BIG_INTEGER_EC_POINT * point, + IN SAE_BN *scalar, + IN struct __EC_GROUP_INFO_BI *ec_group_bi, + OUT BIG_INTEGER_EC_POINT * *ec_point_res); + +/* https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication */ +/* w-ary non-adjacent form (wNAF) method */ +VOID ecc_point_mul_wNAF( + IN BIG_INTEGER_EC_POINT * point, + IN SAE_BN *scalar, + IN struct __EC_GROUP_INFO_BI *ec_group_bi, + OUT BIG_INTEGER_EC_POINT * *ec_point_res); + +/* https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication */ +/* w-ary non-adjacent form (wNAF) method */ +VOID ecc_point_mul_windowed( + IN BIG_INTEGER_EC_POINT * point, + IN SAE_BN *scalar, + IN struct __EC_GROUP_INFO_BI *ec_group_bi, + OUT BIG_INTEGER_EC_POINT * *ec_point_res); + +/* (x,y) => (x, p-y) */ +VOID ecc_point_inverse( + IN BIG_INTEGER_EC_POINT * point, + IN SAE_BN *prime, + OUT BIG_INTEGER_EC_POINT * *point_res); + +UCHAR ecc_point_is_on_curve( + IN struct __EC_GROUP_INFO_BI *ec_group_bi, + IN BIG_INTEGER_EC_POINT * point); + +UCHAR ecc_point_is_on_curve_3d( + IN EC_GROUP_INFO_BI *ec_group_bi, + IN BIG_INTEGER_EC_POINT * point); + +/* y^2 = x^3 + ax + b */ +UCHAR ecc_point_find_by_x( + IN struct __EC_GROUP_INFO_BI *ec_group_bi, + IN SAE_BN *x, + IN SAE_BN **res_y, + IN UCHAR need_res_y); + +VOID ecc_point_dump_time( + VOID); + +BIG_INTEGER_EC_POINT *ecc_point_add_cmm( + IN BIG_INTEGER_EC_POINT *point, + IN BIG_INTEGER_EC_POINT *point2, + IN SAE_BN *lamda, + IN EC_GROUP_INFO_BI *ec_group_bi); + +INT ecc_gen_key(EC_GROUP_INFO *ec_group, + EC_GROUP_INFO_BI *ec_group_bi, + INOUT SAE_BN **priv_key, + BIG_INTEGER_EC_POINT *generator, + INOUT VOID **pub_key); +#endif /* __ECC_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom.h new file mode 100644 index 000000000..6c1f872df --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom.h @@ -0,0 +1,764 @@ +/* + *************************************************************************** + * 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__ + +#ifdef MT_MAC +#include "eeprom/mt_e2p_def.h" +#endif + +/* For ioctl check usage */ +#define EEPROM_IS_PROGRAMMED 0x80 + +#define E2P_NONE 0x00 +#define E2P_EFUSE_MODE 0x01 +#define E2P_FLASH_MODE 0x02 +#define E2P_EEPROM_MODE 0x03 +#define E2P_BIN_MODE 0x04 +#define NUM_OF_E2P_MODE 0x05 + +#ifdef RTMP_MAC_PCI +#define MAX_EEPROM_BIN_FILE_SIZE 512 +#else +#define MAX_EEPROM_BIN_FILE_SIZE 1024 +#endif /* !RTMP_MAC_PCI */ + +#define EEPROM_SIZE 0x200 + +#define EEPROM_DEFULT_BIN_FILE "RT30xxEEPROM.bin" +#ifdef BB_SOC +#define BIN_FILE_PATH "/etc/RT30xxEEPROM.bin" +#else +//#define BIN_FILE_PATH "/tmp/RT30xxEEPROM.bin" +#define BIN_FILE_PATH "/etc/RT30xxEEPROM.bin" +#endif /* BB_SOC */ + +#define EEPROM_1ST_FILE_DIR "/etc_ro/Wireless/iNIC/" +#define EEPROM_2ND_FILE_DIR "/etc_ro/Wireless/iNIC/" + +#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 */ + + + +#ifdef RTMP_FLASH_SUPPORT +#define NVRAM_OFFSET 0x30000 + +#if defined (CONFIG_RT2880_FLASH_32M) +#define DEFAULT_RF_OFFSET 0x1FE0000 +#else +#define DEFAULT_RF_OFFSET 0x40000 +#endif + +#define SECOND_RF_OFFSET 0x48000 +#endif /* RTMP_FLASH_SUPPORT */ + +typedef struct eeprom_flash_info_t { + UINT32 offset; + UINT32 size; + + RTMP_STRING bin_name[L1PROFILE_ATTRNAME_LEN]; + +} eeprom_flash_info; + + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_WORD_STRUC { + struct { + UCHAR Byte1; // High Byte + UCHAR Byte0; // Low Byte + } field; + USHORT word; +} EEPROM_WORD_STRUC; +#else +typedef union _EEPROM_WORD_STRUC { + struct { + UCHAR Byte0; + UCHAR Byte1; + } field; + USHORT word; +} EEPROM_WORD_STRUC; +#endif + + +/* ------------------------------------------------------------------- */ +/* E2PROM data layout */ +/* ------------------------------------------------------------------- */ + +/* Board type */ + +#define BOARD_TYPE_MINI_CARD 0 /* Mini card */ +#define BOARD_TYPE_USB_PEN 1 /* USB pen */ + +/* + EEPROM antenna select format +*/ + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_NIC_CINFIG2_STRUC { + struct { + USHORT DACTestBit:1; /* control if driver should patch the DAC issue */ + USHORT CoexBit:1; + USHORT bInternalTxALC:1; /* Internal Tx ALC */ + USHORT AntOpt:1; /* Fix Antenna Option: 0:Main; 1: Aux */ + USHORT AntDiversity:1; /* Antenna diversity */ + 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; /* external LNA enable for 2.4G */ + USHORT ExternalLNAForA:1; /* external LNA enable for 5G */ + USHORT CardbusAcceleration:1; /* !!! NOTE: 0 - enable, 1 - disable */ + USHORT BW40MSidebandForG:1; + USHORT BW40MSidebandForA:1; + USHORT EnableWPSPBC:1; /* WPS PBC Control bit */ + USHORT BW40MAvailForG:1; /* 0:enable, 1:disable */ + USHORT BW40MAvailForA:1; /* 0:enable, 1:disable */ + 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 */ + +#define NIC_CONFIGURE_0 0x34 +#define EXTERNAL_PA_MASK (0x3 << 8) +#define GET_PA_TYPE(p) (((p) & EXTERNAL_PA_MASK) >> 8) + +#define NIC_CONFIGURE_1 0x36 +#define INTERNAL_TX_ALC_EN (1 << 13) + +#define XTAL_TRIM1 0x3A +#define XTAL_TRIM1_DIP_SELECTION (1 << 7) +#define XTAL_TRIM1_MASK (0x7F) + +#define G_BAND_20_40_BW_PWR_DELTA 0x50 +#define G_BAND_20_40_BW_PWR_DELTA_MASK (0x3f) +#define G_BAND_20_40_BW_PWR_DELTA_SIGN (1 << 6) +#define G_BAND_20_40_BW_PWR_DELTA_EN (1 << 7) +#define A_BAND_20_40_BW_PWR_DELTA_MASK (0x3f << 8) +#define A_BAND_20_40_BW_PWR_DELTA_SIGN (1 << 14) +#define A_BAND_20_40_BW_PWR_DELTA_EN (1 << 15) + +enum EEPROM_STORAGE_TYPE{ + EEPROM_PROM = 0, + EEPROM_EFUSE = 1, + EEPROM_FLASH = 2, +}; + +#define A_BAND_20_80_BW_PWR_DELTA 0x52 +#define A_BAND_20_80_BW_PWR_DELTA_MASK (0x3f) +#define A_BAND_20_80_BW_PWR_DELTA_SIGN (1 << 6) +#define A_BAND_20_80_BW_PWR_DELTA_EN (1 << 7) +#define G_BAND_EXT_PA_SETTING_MASK (0x7f << 8) +#define G_BAND_EXT_PA_SETTING_EN (1 << 15) + +#define A_BAND_EXT_PA_SETTING 0x54 +#define A_BAND_EXT_PA_SETTING_MASK (0x7f) +#define A_BAND_EXT_PA_SETTING_EN (1 << 7) +#define TEMP_SENSOR_CAL_MASK (0x7f << 8) +#define TEMP_SENSOR_CAL_EN (1 << 15) + +#define TX0_G_BAND_TSSI_SLOPE 0x56 +#define TX0_G_BAND_TSSI_SLOPE_MASK (0xff) +#define TX0_G_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define TX0_G_BAND_TARGET_PWR 0x58 +#define TX0_G_BAND_TARGET_PWR_MASK (0xff) +#define TX0_G_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define TX0_G_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define TX0_G_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define TX0_G_BAND_CHL_PWR_DELTA_MID 0x5A +#define TX0_G_BAND_CHL_PWR_DELTA_MID_MASK (0x3f) +#define TX0_G_BAND_CHL_PWR_DELTA_MID_SIGN (1 << 6) +#define TX0_G_BAND_CHL_PWR_DELTA_MID_EN (1 << 7) +#define TX0_G_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define TX0_G_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define TX0_G_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define TX1_G_BAND_TSSI_SLOPE 0x5C +#define TX1_G_BAND_TSSI_SLOPE_MASK (0xff) +#define TX1_G_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define TX1_G_BAND_TARGET_PWR 0x5E +#define TX1_G_BAND_TARGET_PWR_MASK (0xff) +#define TX1_G_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define TX1_G_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define TX1_G_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define TX1_G_BAND_CHL_PWR_DELTA_MID 0x60 +#define TX1_G_BAND_CHL_PWR_DELTA_MID_MASK (0x3f) +#define TX1_G_BAND_CHL_PWR_DELTA_MID_SIGN (1 << 6) +#define TX1_G_BAND_CHL_PWR_DELTA_MID_EN (1 << 7) +#define TX1_G_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define TX1_G_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define TX1_G_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define GRP0_TX0_A_BAND_TSSI_SLOPE 0x62 +#define GRP0_TX0_A_BAND_TSSI_SLOPE_MASK (0xff) +#define GRP0_TX0_A_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define GRP0_TX0_A_BAND_TARGET_PWR 0x64 +#define GRP0_TX0_A_BAND_TARGET_PWR_MASK (0xff) +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI 0x66 +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f) +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 6) +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 7) +#define GRP1_TX0_A_BAND_TSSI_SLOPE_MASK (0xff << 8) + +#define GRP1_TX0_A_BAND_TSSI_OFFSET 0x68 +#define GRP1_TX0_A_BAND_TSSI_OFFSET_MASK (0xff) +#define GRP1_TX0_A_BAND_TARGET_PWR_MASK (0xff << 8) + +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_LOW 0x6A +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f) +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 6) +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 7) +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define GRP2_TX0_A_BAND_TSSI_SLOPE 0x6C +#define GRP2_TX0_A_BAND_TSSI_SLOPE_MASK (0xff) +#define GRP2_TX0_A_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define GRP2_TX0_A_BAND_TARGET_PWR 0x6E +#define GRP2_TX0_A_BAND_TARGET_PWR_MASK (0xff) +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI 0x70 +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f) +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 6) +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 7) +#define GRP3_TX0_A_BAND_TSSI_SLOPE_MASK (0xff << 8) + +#define GRP3_TX0_A_BAND_TSSI_OFFSET 0x72 +#define GRP3_TX0_A_BAND_TSSI_OFFSET_MASK (0xff) +#define GRP3_TX0_A_BAND_TARGET_PWR_MASK (0xff << 8) + +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_LOW 0x74 +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f) +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 6) +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 7) +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define GRP4_TX0_A_BAND_TSSI_SLOPE 0x76 +#define GRP4_TX0_A_BAND_TSSI_SLOPE_MASK (0xff) +#define GRP4_TX0_A_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define GRP4_TX0_A_BAND_TARGET_PWR 0x78 +#define GRP4_TX0_A_BAND_TARGET_PWR_MASK (0xff) +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI 0x7A +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f) +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 6) +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 7) +#define GRP5_TX0_A_BAND_TSSI_SLOPE_MASK (0xff << 8) + +#define GRP5_TX0_A_BAND_TSSI_OFFSET 0x7C +#define GRP5_TX0_A_BAND_TSSI_OFFSET_MASK (0xff) +#define GRP5_TX0_A_BAND_TARGET_PWR_MASK (0xff << 8) + +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_LOW 0X7E +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f) +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 6) +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 7) +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define GRP0_TX1_A_BAND_TSSI_SLOPE 0x80 +#define GRP0_TX1_A_BAND_TSSI_SLOPE_MASK (0xff) +#define GRP0_TX1_A_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define GRP0_TX1_A_BAND_TARGET_PWR 0x82 +#define GRP0_TX1_A_BAND_TARGET_PWR_MASK (0xff) +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI 0x84 +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f) +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 6) +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 7) +#define GRP1_TX1_A_BAND_TSSI_SLOPE_MASK (0xff << 8) + +#define GRP1_TX1_A_BAND_TSSI_OFFSET 0x86 +#define GRP1_TX1_A_BAND_TSSI_OFFSET_MASK (0xff) +#define GRP1_TX1_A_BAND_TARGET_PWR_MASK (0xff << 8) + +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_LOW 0x88 +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f) +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 6) +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 7) +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define GRP2_TX1_A_BAND_TSSI_SLOPE 0x8A +#define GRP2_TX1_A_BAND_TSSI_SLOPE_MASK (0xff) +#define GRP2_TX1_A_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define GRP2_TX1_A_BAND_TARGET_PWR 0x8C +#define GRP2_TX1_A_BAND_TARGET_PWR_MASK (0xff) +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI 0x8E +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f) +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 6) +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 7) +#define GRP3_TX1_A_BAND_TSSI_SLOPE_MASK (0xff << 8) + +#define GRP3_TX1_A_BAND_TSSI_OFFSET 0x90 +#define GRP3_TX1_A_BAND_TSSI_OFFSET_MASK (0xff) +#define GRP3_TX1_A_BAND_TARGET_PWR_MASK (0xff << 8) + +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_LOW 0x92 +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f) +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 6) +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 7) +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define GRP4_TX1_A_BAND_TSSI_SLOPE 0x94 +#define GRP4_TX1_A_BAND_TSSI_SLOPE_MASK (0xff) +#define GRP4_TX1_A_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define GRP4_TX1_A_BAND_TARGET_PWR 0x96 +#define GRP4_TX1_A_BAND_TARGET_PWR_MASK (0xff) +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI 0x98 +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f) +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 6) +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 7) +#define GRP5_TX1_A_BAND_TSSI_SLOPE_MASK (0xff << 8) + +#define GRP5_TX1_A_BAND_TSSI_OFFSET 0x9A +#define GRP5_TX1_A_BAND_TSSI_OFFSET_MASK (0xff) +#define GRP5_TX1_A_BAND_TARGET_PWR_MASK (0xff << 8) + +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_LOW 0x9C +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f) +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 6) +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 7) +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define G_BAND_BANDEDGE_PWR_BACK_OFF 0x9E +#define G_BAND_BANDEDGE_PWR_BACK_OFF_MASK (0x7f) +#define G_BAND_BANDEDGE_PWR_BACK_OFF_EN (1 << 7) +#define XTAL_TRIM2_MASK (0x7f << 8) +#define XTAL_TRIM2_DIP_SELECTION (1 << 15) + +#define TX_PWR_CCK_1_2M 0xA0 +#define TX_PWR_CCK_1_2M_MASK (0x3f) +#define TX_PWR_CCK_1_2M_SIGN (1 << 6) +#define TX_PWR_CCK_1_2M_EN (1 << 7) +#define TX_PWR_CCK_5_11M_MASK (0x3f << 8) +#define TX_PWR_CCK_5_11M_SIGN (1 << 14) +#define TX_PWR_CCK_5_11M_EN (1 << 15) + +#define TX_PWR_G_BAND_OFDM_6_9M 0xA2 +#define TX_PWR_G_BAND_OFDM_6_9M_MASK (0x3f) +#define TX_PWR_G_BAND_OFDM_6_9M_SIGN (1 << 6) +#define TX_PWR_G_BAND_OFDM_6_9M_EN (1 << 7) +#define TX_PWR_G_BAND_OFDM_12_18M_MASK (0x3f << 8) +#define TX_PWR_G_BAND_OFDM_12_18M_SIGN (1 << 14) +#define TX_PWR_G_BAND_OFDM_12_18M_EN (1 << 15) + +#define TX_PWR_G_BAND_OFDM_24_36M 0xA4 +#define TX_PWR_G_BAND_OFDM_24_36M_MASK (0x3f) +#define TX_PWR_G_BAND_OFDM_24_36M_SIGN (1 << 6) +#define TX_PWR_G_BAND_OFDM_24_36M_EN (1 << 7) +#define TX_PWR_G_BAND_OFDM_48_54M_MASK (0x3f << 8) +#define TX_PWR_G_BAND_OFDM_48_54M_SIGN (1 << 14) +#define TX_PWR_G_BAND_OFDM_48_54M_EN (1 << 15) + +#define TX_PWR_HT_MCS_0_1 0xA6 +#define TX_PWR_HT_MCS_0_1_MASK (0x3f) +#define TX_PWR_HT_MCS_0_1_SIGN (1 << 6) +#define TX_PWR_HT_MCS_0_1_EN (1 << 7) +#define TX_PWR_HT_MCS_2_3_MASK (0x3f << 8) +#define TX_PWR_HT_MCS_2_3_SIGN (1 << 14) +#define TX_PWR_HT_MCS_2_3_EN (1 << 15) + +#define TX_PWR_HT_MCS_4_5 0xA8 +#define TX_PWR_HT_MCS_4_5_MASK (0x3f) +#define TX_PWR_HT_MCS_4_5_SIGN (1 << 6) +#define TX_PWR_HT_MCS_4_5_EN (1 << 7) +#define TX_PWR_HT_MCS_6_7_MASK (0x3f << 8) +#define TX_PWR_HT_MCS_6_7_SIGN (1 << 14) +#define TX_PWR_HT_MCS_6_7_EN (1 << 15) + +#define TX_PWR_HT_MCS_8_9 0xAA +#define TX_PWR_HT_MCS_8_9_MASK (0x3f) +#define TX_PWR_HT_MCS_8_9_SIGN (1 << 6) +#define TX_PWR_HT_MCS_8_9_EN (1 << 7) +#define TX_PWR_HT_MCS_10_11_MASK (0x3f << 8) +#define TX_PWR_HT_MCS_10_11_SIGN (1 << 14) +#define TX_PWR_HT_MCS_10_11_EN (1 << 15) + +#define TX_PWR_HT_MCS_12_13 0xAC +#define TX_PWR_HT_MCS_12_13_MASK (0x3f) +#define TX_PWR_HT_MCS_12_13_SIGN (1 << 6) +#define TX_PWR_HT_MCS_12_13_EN (1 << 7) +#define TX_PWR_HT_MCS_14_15_MASK (0x3f << 8) +#define TX_PWR_HT_MCS_14_15_SIGN (1 << 14) +#define TX_PWR_HT_MCS_14_15_EN (1 << 15) + +#define CONFIG_G_BAND_CHL 0xB0 +#define CONFIG_G_BAND_CHL_GRP1_MASK (0xff) +#define CONFIG_G_BAND_CHL_GRP2_MASK (0xff << 8) + +#define TX_PWR_A_BAND_OFDM_6_9M 0xB2 +#define TX_PWR_A_BAND_OFDM_6_9M_MASK (0x3f) +#define TX_PWR_A_BAND_OFDM_6_9M_SIGN (1 << 6) +#define TX_PWR_A_BAND_OFDM_6_9M_EN (1 << 7) +#define TX_PWR_A_BAND_OFDM_12_18M_MASK (0x3f << 8) +#define TX_PWR_A_BAND_OFDM_12_18M_SIGN (1 << 14) +#define TX_PWR_A_BAND_OFDM_12_18M_EN (1 << 15) + +#define TX_PWR_A_BAND_OFDM_24_36M 0xB4 +#define TX_PWR_A_BAND_OFDM_24_36M_MASK (0x3f) +#define TX_PWR_A_BAND_OFDM_24_36M_SIGN (1 << 6) +#define TX_PWR_A_BAND_OFDM_24_36M_EN (1 << 7) +#define TX_PWR_A_BAND_OFDM_48_54M_MASK (0x3f << 8) +#define TX_PWR_A_BAND_OFDM_48_54M_SIGN (1 << 14) +#define TX_PWR_A_BAND_OFDM_48_54M_EN (1 << 15) + +#define CONFIG1_A_BAND_CHL 0xB6 +#define CONFIG1_A_BAND_CHL_GRP1_MASK 0xff +#define CONFIG1_A_BAND_CHL_GRP2_MASK (0xff << 8) + +#define CONFIG2_A_BAND_CHL 0xB8 +#define CONFIG2_A_BAND_CHL_GRP1_MASK (0xff) +#define CONFIG2_A_BAND_CHL_GRP2_MASK (0xff << 8) + +#define TX_PWR_VHT_MCS_0_1 0xBA +#define TX_PWR_VHT_MCS_0_1_MASK (0x3f) +#define TX_PWR_VHT_MCS_0_1_SIGN (1 << 6) +#define TX_PWR_VHT_MCS_0_1_EN (1 << 7) +#define TX_PWR_VHT_MCS_2_3_MASK (0x3f << 8) +#define TX_PWR_VHT_MCS_2_3_SIGN (1 << 14) +#define TX_PWR_VHT_MCS_2_3_EN (1 << 15) + +#define TX_PWR_VHT_MCS_4_5 0xBC +#define TX_PWR_VHT_MCS_4_5_MASK (0x3f) +#define TX_PWR_VHT_MCS_4_5_SIGN (1 << 6) +#define TX_PWR_VHT_MCS_4_5_EN (1 << 7) +#define TX_PWR_VHT_MCS_6_7_MASK (0x3f << 8) +#define TX_PWR_VHT_MCS_6_7_SIGN (1 << 14) +#define TX_PWR_VHT_MCS_6_7_EN (1 << 15) + +#define TX_PWR_5G_VHT_MCS_8_9 0xBE +#define TX_PWR_5G_VHT_MCS_8_9_MASK (0x3f) +#define TX_PWR_5G_VHT_MCS_8_9_SIGN (1 << 6) +#define TX_PWR_5G_VHT_MCS_8_9_EN (1 << 7) +#define TX_PWR_2G_VHT_MCS_8_9_MASK (0x3f << 8) +#define TX_PWR_2G_VHT_MCS_8_9_SIGN (1 << 14) +#define TX_PWR_2G_VHT_MCS_8_9_EN (1 << 15) + +#define RF_2G_RX_HIGH_GAIN 0xF8 +#define RF0_2G_RX_HIGH_GAIN_MASK (0x07 << 8) +#define RF0_2G_RX_HIGH_GAIN_SIGN (1 << 11) +#define RF1_2G_RX_HIGH_GAIN_MASK (0x07 << 12) +#define RF1_2G_RX_HIGH_GAIN_SIGN (1 << 15) + +#define RF_5G_GRP0_1_RX_HIGH_GAIN 0xFA +#define RF0_5G_GRP0_RX_HIGH_GAIN_MASK (0x07) +#define RF0_5G_GRP0_RX_HIGH_GAIN_SIGN (1 << 3) +#define RF1_5G_GRP0_RX_HIGH_GAIN_MASK (0x07 << 4) +#define RF1_5G_GRP0_RX_HIGH_GAIN_SIGN (1 << 7) +#define RF0_5G_GRP1_RX_HIGH_GAIN_MASK (0x07 << 8) +#define RF0_5G_GRP1_RX_HIGH_GAIN_SIGN (1 << 11) +#define RF1_5G_GRP1_RX_HIGH_GAIN_MASK (0x07 << 12) +#define RF1_5G_GRP1_RX_HIGH_GAIN_SIGN (1 << 15) + +#define RF_5G_GRP2_3_RX_HIGH_GAIN 0xFC +#define RF0_5G_GRP2_RX_HIGH_GAIN_MASK (0x07) +#define RF0_5G_GRP2_RX_HIGH_GAIN_SIGN (1 << 3) +#define RF1_5G_GRP2_RX_HIGH_GAIN_MASK (0x07 << 4) +#define RF1_5G_GRP2_RX_HIGH_GAIN_SIGN (1 << 7) +#define RF0_5G_GRP3_RX_HIGH_GAIN_MASK (0x07 << 8) +#define RF0_5G_GRP3_RX_HIGH_GAIN_SIGN (1 << 11) +#define RF1_5G_GRP3_RX_HIGH_GAIN_MASK (0x07 << 12) +#define RF1_5G_GRP3_RX_HIGH_GAIN_SIGN (1 << 15) + +#define RF_5G_GRP4_5_RX_HIGH_GAIN 0xFE +#define RF0_5G_GRP4_RX_HIGH_GAIN_MASK (0x07) +#define RF0_5G_GRP4_RX_HIGH_GAIN_SIGN (1 << 3) +#define RF1_5G_GRP4_RX_HIGH_GAIN_MASK (0x07 << 4) +#define RF1_5G_GRP4_RX_HIGH_GAIN_SIGN (1 << 7) +#define RF0_5G_GRP5_RX_HIGH_GAIN_MASK (0x07 << 8) +#define RF0_5G_GRP5_RX_HIGH_GAIN_SIGN (1 << 11) +#define RF1_5G_GRP5_RX_HIGH_GAIN_MASK (0x07 << 12) +#define RF1_5G_GRP5_RX_HIGH_GAIN_SIGN (1 << 15) + +#define BT_RCAL_RESULT 0x138 +#define BT_VCDL_CALIBRATION 0x13C +#define BT_PMUCFG 0x13E + +struct _RTMP_ADAPTER; + +#ifdef RTMP_PCI_SUPPORT +/************************************************************************* + * Public function declarations for prom-based chipset + ************************************************************************/ +BOOLEAN rtmp_ee_prom_read16(struct _RTMP_ADAPTER *pAd, UINT16 Offset, UINT16 *pVal); +int rtmp_ee_prom_write16(struct _RTMP_ADAPTER *pAd, USHORT Offset, USHORT val); +#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(struct _RTMP_ADAPTER *pAd); +RTMP_STRING *get_dev_eeprom_binary(VOID *pvAd); +UINT get_dev_eeprom_offset(VOID *pvAd); +UINT32 get_dev_eeprom_size(VOID *pvAd); +BOOLEAN rtmp_ee_flash_read(struct _RTMP_ADAPTER *pAd, USHORT Offset, USHORT *pVal); +int rtmp_ee_flash_write(struct _RTMP_ADAPTER *pAd, USHORT Offset, USHORT data); +VOID rtmp_ee_flash_read_all(struct _RTMP_ADAPTER *pAd, USHORT *Data); +VOID rtmp_ee_flash_write_all(struct _RTMP_ADAPTER *pAd, USHORT *Data); +#endif /* defined(RTMP_RBUS_SUPPORT) || defined(RTMP_FLASH_SUPPORT) */ + + +#ifdef RTMP_EFUSE_SUPPORT +/************************************************************************* + * Public function declarations for efuse-based chipset + ************************************************************************/ +BOOLEAN rtmp_ee_efuse_read16(struct _RTMP_ADAPTER *pAd, USHORT Offset, USHORT *pVal); +int rtmp_ee_efuse_write16(struct _RTMP_ADAPTER *pAd, USHORT Offset, USHORT data); +INT rtmp_ee_write_to_efuse(struct _RTMP_ADAPTER *pAd); + +NTSTATUS eFuseRead(struct _RTMP_ADAPTER *pAd, USHORT Offset, USHORT *pData, USHORT len); +NTSTATUS eFuseWrite(struct _RTMP_ADAPTER *pAd, USHORT Offset, USHORT *pData, USHORT len); + +VOID eFuseGetFreeBlockCount(struct _RTMP_ADAPTER *pAd, UINT *EfuseFreeBlock); + +INT eFuse_init(struct _RTMP_ADAPTER *pAd); +INT efuse_probe(struct _RTMP_ADAPTER *pAd); +#endif /* RTMP_EFUSE_SUPPORT */ + +/************************************************************************* + * Public function declarations for using BIN buffer mode to access eeprom contents + ************************************************************************/ +BOOLEAN rtmp_ee_bin_read16(struct _RTMP_ADAPTER *pAd, UINT16 Offset, UINT16 *pValue); + +INT rtmp_ee_bin_write16( + IN struct _RTMP_ADAPTER *pAd, + IN USHORT Offset, + IN USHORT data); + +INT rtmp_ee_load_from_bin( + IN struct _RTMP_ADAPTER *pAd); + +INT rtmp_ee_write_to_bin( + IN struct _RTMP_ADAPTER *pAd); + +INT rtmp_ee_write_to_prom(struct _RTMP_ADAPTER *pAd); + +INT Set_LoadEepromBufferFromBin_Proc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EepromBufferWriteBack_Proc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + +/************************************************************************* + * Public function declarations for prom operation callback functions setting + ************************************************************************/ +INT RtmpChipOpsEepromHook(struct _RTMP_ADAPTER *pAd, INT infType,INT forceMode); + +INT NICReadEEPROMParameters(struct _RTMP_ADAPTER *pAd, RTMP_STRING *mac_addr); +BOOLEAN rt28xx_eeprom_read16(struct _RTMP_ADAPTER *pAd, USHORT offset, USHORT *value); + +#endif /* __EEPROM_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom/mt7601_e2p.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom/mt7601_e2p.h new file mode 100644 index 000000000..0ebba5ff1 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom/mt7601_e2p.h @@ -0,0 +1,37 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR MT7601_E2PImage[] = { +0x01, 0x76, 0x00, 0x0d, 0x00, 0x0c, 0x43, 0x26, 0x60, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x01, 0x02, 0x8f, 0x14, 0x01, 0x76, 0x00, 0x00, 0x4a, 0x00, 0x01, 0x00, 0x80, 0x50, 0x08, 0x00, +0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0x01, 0x40, 0x60, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0x11, 0xff, 0x04, 0x28, 0xff, 0xff, 0x2c, 0x01, 0xff, 0xff, 0x99, 0x99, +0x8c, 0x88, 0xff, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x20, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05, +0x03, 0x03, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x12, 0x03, 0x4d, 0x00, 0x65, 0x00, 0x64, 0x00, 0x69, 0x00, 0x61, 0x00, 0x54, 0x00, 0x65, 0x00, +0x6b, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x1e, 0x03, 0x38, 0x00, 0x30, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x31, 0x00, 0x20, 0x00, +0x6e, 0x00, 0x20, 0x00, 0x57, 0x00, 0x4c, 0x00, 0x41, 0x00, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, +0x08, 0x03, 0x31, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, } ; diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom/mt7603_e2p.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom/mt7603_e2p.h new file mode 100644 index 000000000..5f6fb0cf5 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom/mt7603_e2p.h @@ -0,0 +1,37 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR MT7603_E2PImage[] = { +0x03, 0x76, 0x0b, 0x00, 0x00, 0x0c, 0x43, 0x26, 0x60, 0x40, 0x03, 0x76, 0xc3, 0x14, 0xff, 0xff, +0xff, 0xff, 0x03, 0x76, 0xc3, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xb0, 0x07, 0x80, 0x00, 0x60, 0x7f, 0xfd, 0x9b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0x22, 0x34, 0x00, 0x20, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, +0x81, 0x00, 0x00, 0x94, 0x40, 0xb0, 0x40, 0xc9, 0x0c, 0x00, 0x00, 0x00, 0x40, 0xc9, 0x0c, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xc6, 0xc6, 0xc4, 0xc4, 0xc4, 0xc0, 0xc0, 0xc4, 0xc4, 0xc4, 0xc4, 0xc0, 0xc0, 0xc0, 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, +0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x20, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, } ; diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom/mt76x2_e2p.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom/mt76x2_e2p.h new file mode 100644 index 000000000..106c8b9b9 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom/mt76x2_e2p.h @@ -0,0 +1,37 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR MT76x2_E2PImage[] = { +0x62, 0x76, 0x00, 0x00, 0x00, 0x0c, 0x43, 0x76, 0x62, 0x00, 0x62, 0x76, 0xc3, 0x14, 0x00, 0x00, +0x00, 0x00, 0x62, 0x76, 0xc3, 0x14, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0x37, 0xd8, 0x9d, 0x00, 0x60, 0x7f, 0xfd, 0x9b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0x22, 0xff, 0x00, 0x20, 0xff, 0xff, 0xba, 0x01, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x0a, 0x1a, 0x00, 0x00, 0x00, 0x83, 0x0b, 0x1a, 0x00, +0x00, 0x00, 0x7a, 0x06, 0x1a, 0x00, 0x00, 0x7a, 0x06, 0x1a, 0x00, 0x00, 0x78, 0x08, 0x1a, 0x00, +0x00, 0x7e, 0x02, 0x1a, 0x00, 0x00, 0x76, 0x16, 0x1a, 0x00, 0x00, 0x75, 0x1c, 0x1a, 0x00, 0x00, +0x79, 0x0a, 0x1a, 0x00, 0x00, 0x79, 0x0a, 0x1a, 0x00, 0x00, 0x7b, 0x06, 0x1a, 0x00, 0x00, 0x77, +0x14, 0x1a, 0x00, 0x00, 0x7e, 0x05, 0x1a, 0x00, 0x00, 0x79, 0x11, 0x1a, 0x00, 0x00, 0x00, 0x00, +0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0xc2, 0xc2, 0x82, 0x82, 0xc2, 0xc2, 0x82, 0x82, 0x00, 0x00, +0x00, 0x00, 0xc2, 0xc2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc2, 0x82, 0x82, 0x83, 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, +0x0f, 0xca, 0x74, 0xc5, 0xe8, 0x07, 0x30, 0x3d, 0x01, 0xb0, 0x08, 0x26, 0x00, 0x0e, 0x04, 0x15, +0x00, 0x8a, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x9d, 0x08, 0x00, 0x12, 0xc0, 0x00, 0x00, +0x08, 0x20, 0x04, 0x2a, 0x90, 0x00, 0x00, 0x24, 0x01, 0x04, 0x54, 0x08, 0xd0, 0xa0, 0x28, 0x20, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xc0, 0x81, 0x82, 0xc3, 0x04, 0x45, 0x46, 0x07, 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, } ; diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom/mt_e2p_def.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom/mt_e2p_def.h new file mode 100644 index 000000000..1ab7b7209 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/eeprom/mt_e2p_def.h @@ -0,0 +1,436 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of MediaTek. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + mt_e2p_def.h +*/ + +#ifndef __MT_E2P_DEF_H__ +#define __MT_E2P_DEF_H__ + + +#define NIC_CONFIGURE_0 0x34 +#define EXTERNAL_PA_MASK (0x3 << 8) +#define GET_PA_TYPE(p) (((p) & EXTERNAL_PA_MASK) >> 8) + +#define NIC_CONFIGURE_0_TOP 0x35 + +#define NIC_CONFIGURE_1 0x36 +#define INTERNAL_TX_ALC_EN (1 << 13) + +#define NIC_CONFIGURE_1_TOP 0x37 + + +#define XTAL_TRIM1 0x3A +#define XTAL_TRIM1_DIP_SELECTION (1 << 7) +#define XTAL_TRIM1_MASK (0x7F) + +#define WIFI_RF_SETTING 0x48 + +#define G_BAND_20_40_BW_PWR_DELTA 0x50 +#define G_BAND_20_40_BW_PWR_DELTA_MASK (0x3f) +#define G_BAND_20_40_BW_PWR_DELTA_SIGN (1 << 6) +#define G_BAND_20_40_BW_PWR_DELTA_EN (1 << 7) +#define A_BAND_20_40_BW_PWR_DELTA_MASK (0x3f << 8) +#define A_BAND_20_40_BW_PWR_DELTA_SIGN (1 << 14) +#define A_BAND_20_40_BW_PWR_DELTA_EN (1 << 15) + +#define A_BAND_20_80_BW_PWR_DELTA 0x52 +#define A_BAND_20_80_BW_PWR_DELTA_MASK (0x3f) +#define A_BAND_20_80_BW_PWR_DELTA_SIGN (1 << 6) +#define A_BAND_20_80_BW_PWR_DELTA_EN (1 << 7) +#define G_BAND_EXT_PA_SETTING_MASK (0x7f << 8) +#define G_BAND_EXT_PA_SETTING_EN (1 << 15) + +#define A_BAND_20_80_BW_PWR_DELTA_ANALOG 0x53 + +#define THADC_ANALOG_PART 0x53 +#define THADC_SLOP 0x54 +#define THERMO_SLOPE_VARIATION_MASK (0x1f) +#define A_BAND_EXT_PA_SETTING 0x54 +#define A_BAND_EXT_PA_SETTING_MASK (0x7f) +#define A_BAND_EXT_PA_SETTING_EN (1 << 7) +#define TEMP_SENSOR_CAL_MASK (0x7f << 8) +#define TEMP_SENSOR_CAL_EN (1 << 15) + +#define TEMP_SENSOR_CAL 0x55 +#define TEMPERATURE_SENSOR_CALIBRATION 0x55 +#define THERMO_REF_ADC_VARIATION_MASK (0x7f) + +#define TX0_G_BAND_TSSI_SLOPE 0x56 +#define TX0_G_BAND_TSSI_SLOPE_MASK (0xff) +#define TX0_G_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define TX0_G_BAND_TSSI_SLOPE_TOP 0x57 + +#define TX0_G_BAND_TARGET_PWR 0x58 +#define TX0_G_BAND_TARGET_PWR_MASK (0xff) +#define TX0_G_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define TX0_G_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define TX0_G_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define TX0_G_BAND_OFFSET_LOW 0x59 + +#define TX0_G_BAND_CHL_PWR_DELTA_MID 0x5A +#define TX0_G_BAND_CHL_PWR_DELTA_MID_MASK (0x3f) +#define TX0_G_BAND_CHL_PWR_DELTA_MID_SIGN (1 << 6) +#define TX0_G_BAND_CHL_PWR_DELTA_MID_EN (1 << 7) +#define TX0_G_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define TX0_G_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define TX0_G_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define TX0_G_BAND_OFFSET_HIGH 0x5B + +#define TX1_G_BAND_TSSI_SLOPE 0x5C +#define TX1_G_BAND_TSSI_SLOPE_MASK (0xff) +#define TX1_G_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define TX1_G_BAND_TSSI_SLOPE_TOP 0x5D + +#define TX1_G_BAND_TARGET_PWR 0x5E +#define TX1_G_BAND_TARGET_PWR_MASK (0xff) +#define TX1_G_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define TX1_G_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define TX1_G_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define TX1_G_BAND_CHL_PWR_DELATE_LOW 0x5F + +#define TX1_G_BAND_CHL_PWR_DELTA_MID 0x60 +#define TX1_G_BAND_CHL_PWR_DELTA_MID_MASK (0x3f) +#define TX1_G_BAND_CHL_PWR_DELTA_MID_SIGN (1 << 6) +#define TX1_G_BAND_CHL_PWR_DELTA_MID_EN (1 << 7) +#define TX1_G_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define TX1_G_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define TX1_G_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define TX1_G_BAND_CHL_PWR_DELTA_HIGH 0x61 + + +#define GRP0_TX0_A_BAND_TSSI_SLOPE 0x62 +#define GRP0_TX0_A_BAND_TSSI_SLOPE_MASK (0xff) +#define GRP0_TX0_A_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define GRP0_TX0_A_BAND_TARGET_PWR 0x64 +#define GRP0_TX0_A_BAND_TARGET_PWR_MASK (0xff) +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI 0x66 +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f) +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 6) +#define GRP0_TX0_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 7) +#define GRP1_TX0_A_BAND_TSSI_SLOPE_MASK (0xff << 8) + +#define GRP1_TX0_A_BAND_TSSI_OFFSET 0x68 +#define GRP1_TX0_A_BAND_TSSI_OFFSET_MASK (0xff) +#define GRP1_TX0_A_BAND_TARGET_PWR_MASK (0xff << 8) + +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_LOW 0x6A +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f) +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 6) +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 7) +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define GRP1_TX0_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define GRP2_TX0_A_BAND_TSSI_SLOPE 0x6C +#define GRP2_TX0_A_BAND_TSSI_SLOPE_MASK (0xff) +#define GRP2_TX0_A_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define GRP2_TX0_A_BAND_TARGET_PWR 0x6E +#define GRP2_TX0_A_BAND_TARGET_PWR_MASK (0xff) +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI 0x70 +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f) +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 6) +#define GRP2_TX0_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 7) +#define GRP3_TX0_A_BAND_TSSI_SLOPE_MASK (0xff << 8) + +#define GRP3_TX0_A_BAND_TSSI_OFFSET 0x72 +#define GRP3_TX0_A_BAND_TSSI_OFFSET_MASK (0xff) +#define GRP3_TX0_A_BAND_TARGET_PWR_MASK (0xff << 8) + +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_LOW 0x74 +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f) +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 6) +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 7) +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define GRP3_TX0_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define GRP4_TX0_A_BAND_TSSI_SLOPE 0x76 +#define GRP4_TX0_A_BAND_TSSI_SLOPE_MASK (0xff) +#define GRP4_TX0_A_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define GRP4_TX0_A_BAND_TARGET_PWR 0x78 +#define GRP4_TX0_A_BAND_TARGET_PWR_MASK (0xff) +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI 0x7A +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f) +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 6) +#define GRP4_TX0_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 7) +#define GRP5_TX0_A_BAND_TSSI_SLOPE_MASK (0xff << 8) + +#define GRP5_TX0_A_BAND_TSSI_OFFSET 0x7C +#define GRP5_TX0_A_BAND_TSSI_OFFSET_MASK (0xff) +#define GRP5_TX0_A_BAND_TARGET_PWR_MASK (0xff << 8) + +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_LOW 0X7E +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f) +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 6) +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 7) +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define GRP5_TX0_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define GRP0_TX1_A_BAND_TSSI_SLOPE 0x80 +#define GRP0_TX1_A_BAND_TSSI_SLOPE_MASK (0xff) +#define GRP0_TX1_A_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define GRP0_TX1_A_BAND_TARGET_PWR 0x82 +#define GRP0_TX1_A_BAND_TARGET_PWR_MASK (0xff) +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI 0x84 +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f) +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 6) +#define GRP0_TX1_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 7) +#define GRP1_TX1_A_BAND_TSSI_SLOPE_MASK (0xff << 8) + +#define GRP1_TX1_A_BAND_TSSI_OFFSET 0x86 +#define GRP1_TX1_A_BAND_TSSI_OFFSET_MASK (0xff) +#define GRP1_TX1_A_BAND_TARGET_PWR_MASK (0xff << 8) + +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_LOW 0x88 +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f) +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 6) +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 7) +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define GRP1_TX1_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define GRP2_TX1_A_BAND_TSSI_SLOPE 0x8A +#define GRP2_TX1_A_BAND_TSSI_SLOPE_MASK (0xff) +#define GRP2_TX1_A_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define GRP2_TX1_A_BAND_TARGET_PWR 0x8C +#define GRP2_TX1_A_BAND_TARGET_PWR_MASK (0xff) +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI 0x8E +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f) +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 6) +#define GRP2_TX1_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 7) +#define GRP3_TX1_A_BAND_TSSI_SLOPE_MASK (0xff << 8) + +#define GRP3_TX1_A_BAND_TSSI_OFFSET 0x90 +#define GRP3_TX1_A_BAND_TSSI_OFFSET_MASK (0xff) +#define GRP3_TX1_A_BAND_TARGET_PWR_MASK (0xff << 8) + +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_LOW 0x92 +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f) +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 6) +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 7) +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define GRP3_TX1_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define GRP4_TX1_A_BAND_TSSI_SLOPE 0x94 +#define GRP4_TX1_A_BAND_TSSI_SLOPE_MASK (0xff) +#define GRP4_TX1_A_BAND_TSSI_OFFSET_MASK (0xff << 8) + +#define GRP4_TX1_A_BAND_TARGET_PWR 0x96 +#define GRP4_TX1_A_BAND_TARGET_PWR_MASK (0xff) +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f << 8) +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 14) +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 15) + +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI 0x98 +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f) +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 6) +#define GRP4_TX1_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 7) +#define GRP5_TX1_A_BAND_TSSI_SLOPE_MASK (0xff << 8) + +#define GRP5_TX1_A_BAND_TSSI_OFFSET 0x9A +#define GRP5_TX1_A_BAND_TSSI_OFFSET_MASK (0xff) +#define GRP5_TX1_A_BAND_TARGET_PWR_MASK (0xff << 8) + +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_LOW 0x9C +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_LOW_MASK (0x3f) +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_LOW_SIGN (1 << 6) +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_LOW_EN (1 << 7) +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_HI_MASK (0x3f << 8) +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_HI_SIGN (1 << 14) +#define GRP5_TX1_A_BAND_CHL_PWR_DELTA_HI_EN (1 << 15) + +#define G_BAND_BANDEDGE_PWR_BACK_OFF 0x9E +#define G_BAND_BANDEDGE_PWR_BACK_OFF_MASK (0x7f) +#define G_BAND_BANDEDGE_PWR_BACK_OFF_EN (1 << 7) +#define XTAL_TRIM2_MASK (0x7f << 8) +#define XTAL_TRIM2_DIP_SELECTION (1 << 15) + +#define TX_PWR_CCK_1_2M 0xA0 +#define TX_PWR_CCK_1_2M_MASK (0x3f) +#define TX_PWR_CCK_1_2M_SIGN (1 << 6) +#define TX_PWR_CCK_1_2M_EN (1 << 7) +#define TX_PWR_CCK_5_11M_MASK (0x3f << 8) +#define TX_PWR_CCK_5_11M_SIGN (1 << 14) +#define TX_PWR_CCK_5_11M_EN (1 << 15) + +#define TX_PWR_CCK_5_11M 0xA1 + +#define TX_PWR_G_BAND_OFDM_6_9M 0xA2 +#define TX_PWR_G_BAND_OFDM_6_9M_MASK (0x3f) +#define TX_PWR_G_BAND_OFDM_6_9M_SIGN (1 << 6) +#define TX_PWR_G_BAND_OFDM_6_9M_EN (1 << 7) +#define TX_PWR_G_BAND_OFDM_12_18M_MASK (0x3f << 8) +#define TX_PWR_G_BAND_OFDM_12_18M_SIGN (1 << 14) +#define TX_PWR_G_BAND_OFDM_12_18M_EN (1 << 15) + +#define TX_PWR_OFDM_12_18M 0xA3 + +#define TX_PWR_G_BAND_OFDM_24_36M 0xA4 +#define TX_PWR_G_BAND_OFDM_24_36M_MASK (0x3f) +#define TX_PWR_G_BAND_OFDM_24_36M_SIGN (1 << 6) +#define TX_PWR_G_BAND_OFDM_24_36M_EN (1 << 7) +#define TX_PWR_G_BAND_OFDM_48M_MASK (0x3f << 8) +#define TX_PWR_G_BAND_OFDM_48M_SIGN (1 << 14) +#define TX_PWR_G_BAND_OFDM_48M_EN (1 << 15) + + +#define TX_PWR_G_BNAD_OFDM_48 0xA5 + +#ifdef MT_MAC +#define TX_PWR_G_BAND_OFDM_54M 0xA6 +#define TX_PWR_G_BAND_OFDM_54M_MASK (0x3f) +#define TX_PWR_G_BAND_OFDM_54M_SIGN (1 << 6) +#define TX_PWR_G_BAND_OFDM_54M_EN (1 << 7) +#define TX_PWR_HT_BPSK_MCS_0_8_MASK (0x3f << 8) +#define TX_PWR_HT_BPSK_MCS_0_8_SIGN (1 << 14) +#define TX_PWR_HT_BPSK_MCS_0_8_EN (1 << 15) + +#define TX_PWR_HT_BPSK_MCS_0_8 0xA7 + +#define TX_PWR_HT_BPSK_MCS_32 0xA8 +#define TX_PWR_HT_BPSK_MCS_32_MASK (0x3f) +#define TX_PWR_HT_BPSK_MCS_32_SIGN (1 << 6) +#define TX_PWR_HT_BPSK_MCS_32_EN (1 << 7) +#define TX_PWR_HT_QPSK_MCS_1_2_9_10_MASK (0x3f << 8) +#define TX_PWR_HT_QPSK_MCS_1_2_9_10_SIGN (1 << 14) +#define TX_PWR_HT_QPSK_MCS_1_2_9_10_EN (1 << 15) + +#define TX_PWR_HT_QPSK_MCS_1_2_9_10 0xA9 + + +#define TX_PWR_HT_16QAM_MCS_3_4_11_12 0xAA +#define TX_PWR_HT_16QAM_MCS_3_4_11_12_MASK (0x3f) +#define TX_PWR_HT_16QAM_MCS_3_4_11_12_SIGN (1 << 6) +#define TX_PWR_HT_16QAM_MCS_3_4_11_12_EN (1 << 7) +#define TX_PWR_HT_64QAM_MCS_5_13_MASK (0x3f << 8) +#define TX_PWR_HT_64QAM_MCS_5_13_SIGN (1 << 14) +#define TX_PWR_HT_64QAM_MCS_5_13_EN (1 << 15) + +#define TX_PWR_HT_64QAM_MCS_5_13 0xAB + + +#define TX_PWR_HT_64QAM_MCS_6_14 0xAC +#define TX_PWR_HT_64QAM_MCS_6_14_MASK (0x3f) +#define TX_PWR_HT_64QAM_MCS_6_14_SIGN (1 << 6) +#define TX_PWR_HT_64QAM_MCS_6_14_EN (1 << 7) +#define TX_PWR_HT_64QAM_MCS_7_15_MASK (0x3f << 8) +#define TX_PWR_HT_64QAM_MCS_7_15_SIGN (1 << 14) +#define TX_PWR_HT_64QAM_MCS_7_15_EN (1 << 15) + +#define TX_PWR_HT_64QAM_MCS_7_15 0xAD + +#endif + + + +#define CONFIG_G_BAND_CHL 0xB0 +#define CONFIG_G_BAND_CHL_GRP1_MASK (0xff) +#define CONFIG_G_BAND_CHL_GRP2_MASK (0xff << 8) + +#define TX_PWR_A_BAND_OFDM_6_9M 0xB2 +#define TX_PWR_A_BAND_OFDM_6_9M_MASK (0x3f) +#define TX_PWR_A_BAND_OFDM_6_9M_SIGN (1 << 6) +#define TX_PWR_A_BAND_OFDM_6_9M_EN (1 << 7) +#define TX_PWR_A_BAND_OFDM_12_18M_MASK (0x3f << 8) +#define TX_PWR_A_BAND_OFDM_12_18M_SIGN (1 << 14) +#define TX_PWR_A_BAND_OFDM_12_18M_EN (1 << 15) + +#define TX_PWR_A_BAND_OFDM_24_36M 0xB4 +#define TX_PWR_A_BAND_OFDM_24_36M_MASK (0x3f) +#define TX_PWR_A_BAND_OFDM_24_36M_SIGN (1 << 6) +#define TX_PWR_A_BAND_OFDM_24_36M_EN (1 << 7) +#define TX_PWR_A_BAND_OFDM_48_54M_MASK (0x3f << 8) +#define TX_PWR_A_BAND_OFDM_48_54M_SIGN (1 << 14) +#define TX_PWR_A_BAND_OFDM_48_54M_EN (1 << 15) + +#define CONFIG1_A_BAND_CHL 0xB6 +#define CONFIG1_A_BAND_CHL_GRP1_MASK 0xff +#define CONFIG1_A_BAND_CHL_GRP2_MASK (0xff << 8) + +#define CONFIG2_A_BAND_CHL 0xB8 +#define CONFIG2_A_BAND_CHL_GRP1_MASK (0xff) +#define CONFIG2_A_BAND_CHL_GRP2_MASK (0xff << 8) + +#define ELAN_RX_MODE_GAIN 0xC0 +#define ELAN_RX_MODE_NF 0xC1 +#define ELAN_RX_MODE_P1DB 0xC2 +#define ELAN_BYPASS_MODE_GAIN 0xC3 +#define ELAN_BYPASS_MODE_NF 0xC4 +#define ELAN_BYPASS_MODE_P1DB 0xC5 + +#define STEP_NUM_NEG_7 0xC6 +#define STEP_NUM_NEG_6 0xC7 +#define STEP_NUM_NEG_5 0xC8 +#define STEP_NUM_NEG_4 0xC9 +#define STEP_NUM_NEG_3 0xCA +#define STEP_NUM_NEG_2 0xCB +#define STEP_NUM_NEG_1 0xCC +#define STEP_NUM_NEG_0 0xCD + +#define REF_STEP_24G 0xCE +#define REF_TEMP_24G 0xCF + +#define STEP_NUM_PLUS_1 0xD0 +#define STEP_NUM_PLUS_2 0xD1 +#define STEP_NUM_PLUS_3 0xD2 +#define STEP_NUM_PLUS_4 0xD3 +#define STEP_NUM_PLUS_5 0xD4 +#define STEP_NUM_PLUS_6 0xD5 +#define STEP_NUM_PLUS_7 0xD6 + +#define CP_FT_VERSION 0xF0 +#define XTAL_CALIB_FREQ_OFFSET 0xF4 +#define XTAL_TRIM_2_COMP 0xF5 +#define XTAL_TRIM_3_COMP 0xF6 +#define WF_RCAL 0xF7 +#define PCIE_RECAL 0xF8 + +#define THERMAL_COMPENSATION_OFFSET 0xF8 + + + +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/efuse.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/efuse.h new file mode 100644 index 000000000..c87efdbf1 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/efuse.h @@ -0,0 +1,86 @@ +/* + *************************************************************************** + * 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: + efuse.h +*/ +#ifndef __EFUSE_H__ +#define __EFUSE_H__ + +/* eFuse registers */ +#define EFUSE_CTRL 0x0580 +#define EFUSE_DATA0 0x0590 +#define EFUSE_DATA1 0x0594 +#define EFUSE_DATA2 0x0598 +#define EFUSE_DATA3 0x059c + +#define EFUSE_CTRL_3290 0x24 +#define EFUSE_DATA0_3290 0x28 +#define EFUSE_DATA1_3290 0x2c +#define EFUSE_DATA2_3290 0x30 +#define EFUSE_DATA3_3290 0x34 + +#define EFUSE_TAG 0x2fe + + +#define MT_EEF_BASE 0x81070000 +#define MT_EE_CTRL (MT_EEF_BASE) +#define MT_EFUSE_CTRL (MT_EEF_BASE + 0x8) +#define MT_EFUSE_WDATA0 (MT_EEF_BASE + 0x10) +#define MT_EFUSE_WDATA1 (MT_EEF_BASE + 0x14) +#define MT_EFUSE_WDATA2 (MT_EEF_BASE + 0x18) +#define MT_EFUSE_WDATA3 (MT_EEF_BASE + 0x1C) +#define MT_EFUSE_RDATA0 (MT_EEF_BASE + 0x30) +#define MT_EFUSE_RDATA1 (MT_EEF_BASE + 0x34) +#define MT_EFUSE_RDATA2 (MT_EEF_BASE + 0x38) +#define MT_EFUSE_RDATA3 (MT_EEF_BASE + 0x3C) + +#ifdef RT_BIG_ENDIAN +typedef union _EFUSE_CTRL_STRUC { + struct { + UINT32 SEL_EFUSE:1; + UINT32 EFSROM_KICK:1; + UINT32 EFSROM_DOUT_VLD:1; + UINT32 RESERVED:3; + UINT32 EFSROM_AIN:10; + UINT32 EFSROM_LDO_ON_TIME:2; + UINT32 EFSROM_LDO_OFF_TIME:6; + UINT32 EFSROM_MODE:2; + UINT32 EFSROM_AOUT:6; + } field; + UINT32 word; +} EFUSE_CTRL_STRUC, *PEFUSE_CTRL_STRUC; +#else +typedef union _EFUSE_CTRL_STRUC { + struct { + UINT32 EFSROM_AOUT:6; + UINT32 EFSROM_MODE:2; + UINT32 EFSROM_LDO_OFF_TIME:6; + UINT32 EFSROM_LDO_ON_TIME:2; + UINT32 EFSROM_AIN:10; + UINT32 RESERVED:3; + UINT32 EFSROM_DOUT_VLD:1; + UINT32 EFSROM_KICK:1; + UINT32 SEL_EFUSE:1; + } field; + UINT32 word; +} EFUSE_CTRL_STRUC, *PEFUSE_CTRL_STRUC; +#endif /* RT_BIG_ENDIAN */ + +VOID eFuseReadPhysical( + IN PRTMP_ADAPTER pAd, + IN PUSHORT lpInBuffer, + IN ULONG nInBufferSize, + OUT PUSHORT lpOutBuffer, + IN ULONG nOutBufferSize); + +#endif /* __EFUSE_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/event_notifier.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/event_notifier.h new file mode 100644 index 000000000..b59fe02e5 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/event_notifier.h @@ -0,0 +1,202 @@ +#ifdef WH_EVENT_NOTIFIER +#ifndef __EVENT_NOTIFIER_H__ +#define __EVENT_NOTIFIER_H__ + +/* Wireless Capability Flag */ +#define WHC_WLCAP_80211_N (0x00000001) +#define WHC_WLCAP_80211_AC (0x00000002) +#define WHC_WLCAP_RESERVE_1 (0x00000004) +#define WHC_WLCAP_RESERVE_2 (0x00000008) +#define WHC_WLCAP_HT40 (0x00000010) +#define WHC_WLCAP_HT80 (0x00000020) +#define WHC_WLCAP_HT160 (0x00000040) +#define WHC_WLCAP_RESERVE_3 (0x00000080) +#define WHC_WLCAP_RX_2_STREAMS (0x00000100) +#define WHC_WLCAP_RX_3_STREAMS (0x00000200) +#define WHC_WLCAP_RX_4_STREAMS (0x00000400) +#define WHC_WLCAP_TX_2_STREAMS (0x00000800) +#define WHC_WLCAP_TX_3_STREAMS (0x00001000) +#define WHC_WLCAP_TX_4_STREAMS (0x00002000) +#define WHC_WLCAP_RESERVE_4 (0x00004000) +#define WHC_WLCAP_RESERVE_5 (0x00008000) + +#define WHC_UPLINK_STAT_DISCONNECT (0) +#define WHC_UPLINK_STAT_CONNECTED (1) + +enum { + DRVEVNT_FIRST_ID = 0, + WHC_DRVEVNT_STA_PROBE_REQ, + WHC_DRVEVNT_AP_PROBE_RSP, + WHC_DRVEVNT_STA_JOIN, + WHC_DRVEVNT_STA_LEAVE, + WHC_DRVEVNT_EXT_UPLINK_STAT, + WHC_DRVEVNT_STA_TIMEOUT, + WHC_DRVEVNT_STA_AUTH_REJECT, + WHC_DRVEVNT_CHANNEL_LOAD_REPORT, + WHC_DRVEVNT_STA_RSSI_TOO_LOW, + WHC_DRVEVNT_STA_ACTIVITY_STATE, + DRVEVNT_END_ID, +}; + +enum { + WHC_STA_STATE_IDLE = 0, + WHC_STA_STATE_ACTIVE, +}; + +struct Custom_IE_Header { + UCHAR eid; + UINT8 len; +}; + +struct Custom_VIE { + struct Custom_IE_Header ie_hdr; + UCHAR custom_ie[CUSTOM_IE_TOTAL_LEN]; +}; + +typedef NTSTATUS (*EventHdlr)(IN RTMP_ADAPTER *pAd, ...); + +typedef struct { + UINT32 EventID; + EventHdlr EventHandler; +}EVENT_TABLE_T; +typedef struct _RxInfo{ + UCHAR channel; /* Wireless channel that receive this frame. */ + ULONG rate; /* RX data rate when recv frame */ + CHAR rssi; /* RSSI when recv frame */ +}RxInfo, *PRxInfo; + +typedef struct _ChLoadItem { + BOOLEAN bValid; /* Check if it is an valid reference info */ + UCHAR Channel; /* Which channel */ + UINT32 ChannelBusyTime; /* Channel busy Time */ +}ChLoadItem, *PChLoadItem; + +typedef struct _StaActivityItem { + ULONG PacketCount; /* Packet count */ + UCHAR CurrentState; /* Station's current state */ +}StaActivityItem, *PStaActivityItem; +struct drvevnt_sta_probe_req { + USHORT type; /* WHC_DRVEVNT_STA_PROBE_REQ */ + UCHAR sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + BOOLEAN is_ucast; /* If unicast frame */ + UINT32 cap; /* Refer to Wireless Capability Flag */ + RxInfo rx_info; + UCHAR custom_ie_len; /* Length of custom vendor information element */ + UCHAR custom_ie[CUSTOM_IE_TOTAL_LEN]; /* Content of custom vendor information element */ +}; + +struct drvevnt_ap_probe_rsp { + USHORT type; /* WHC_DRVEVNT_AP_PROBE_RSP */ + UCHAR ap_mac[MAC_ADDR_LEN]; /* AP's MAC address */ + UINT32 cap; /* Refer to Wireless Capability Flag */ + RxInfo rx_info; + UCHAR custom_ie_len; /* Length of custom vendor information element */ + UCHAR custom_ie[CUSTOM_IE_TOTAL_LEN]; /* Content of custom vendor information element */ +}; + +struct drvevnt_sta_join { + USHORT type; /* WHC_DRVEVNT_STA_JOIN */ + UCHAR sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + UCHAR channel; /* Wireless channel that receive this frame. */ + UINT32 aid; /* Station's association ID */ + UCHAR custom_ie_len; /* Length of custom vendor information element */ + UCHAR custom_ie[CUSTOM_IE_TOTAL_LEN]; /* Content of custom vendor information element */ + UINT32 capability; +}; + +struct drvevnt_sta_leave { + USHORT type; /* WHC_DRVEVNT_STA_LEAVE */ + UCHAR sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + UCHAR channel; /* Wireless channel that receive this frame. */ +}; + +struct drvevnt_ext_uplink_stat { + USHORT type; /* WHC_DRVEVNT_EXT_UPLINK_STAT */ + UCHAR ap_mac[MAC_ADDR_LEN]; /* AP's MAC address */ + UCHAR channel; /* Wireless channel that receive this frame. */ + UINT32 link_state; /* Station's link status*/ +}; + +struct drvevnt_sta_timeout { + USHORT type; /* WHC_DRVEVNT_STA_LEAVE */ + UCHAR sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + UCHAR channel; /* Current Wireless channel. */ +}; + +struct drvevnt_sta_auth_reject { + USHORT type; /* WHC_DRVEVNT_STA_AUTH_REJECT */ + UCHAR sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + RxInfo rx_info; +}; + +struct drvevnt_channel_load_report { + USHORT type; /* WHC_DRVEVNT_CHANNEL_LOAD_REPORT */ + ChLoadItem ch_load_2g; /* Channel Load Item for 2GHz */ + ChLoadItem ch_load_5g; /* Channel Load Item for 5GHz */ +}; + +struct drvevnt_sta_rssi_too_low { + USHORT type; /* WHC_DRVEVNT_STA_RSSI_TOO_LOW */ + UCHAR sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + CHAR rssi; /* Station's Rssi */ +}; + +struct drvevnt_sta_activity_stat { + USHORT type; /* WHC_DRVEVNT_STA_ACTIVITY_STATE */ + UCHAR sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + BOOLEAN bTx; /* Check if it is for tx record */ + StaActivityItem sta_state; /* Station's state record */ +}; + +struct EventNotifierCfg { + UCHAR CustomOUILen; + UCHAR CustomOUI[8]; + + /* For WHC_DRVEVNT_CHANNEL_LOAD_REPORT */ + BOOLEAN bChLoadDetect; + UINT32 ChLoadRound; + UINT32 ChLoadDetectPeriod; /* unit: second */ + struct drvevnt_channel_load_report Chload; + + /* For WHC_DRVEVNT_STA_RSSI_TOO_LOW */ + BOOLEAN bStaRssiDetect; + CHAR StaRssiDetectThreshold; + + /* WHC_DRVEVNT_STA_ACTIVITY_STATE */ + UINT32 StaTxPktDetectRound; /* Record current Tx round, per second */ + UINT32 StaTxPktDetectPeriod; /* unit: second */ + BOOLEAN bStaStateTxDetect; + UINT32 StaStateTxThreshold; + UINT32 StaRxPktDetectRound; /* Record current Tx round, per second */ + UINT32 StaRxPktDetectPeriod; /* unit: second */ + BOOLEAN bStaStateRxDetect; + UINT32 StaStateRxThreshold; +}; + +struct drvevnt_type_buf { + union { + struct drvevnt_sta_probe_req probereq; + struct drvevnt_ap_probe_rsp probersp; + struct drvevnt_sta_join join; + struct drvevnt_sta_leave leave; + struct drvevnt_ext_uplink_stat link_state; + struct drvevnt_sta_timeout timeout; + struct drvevnt_sta_auth_reject auth_reject; + struct drvevnt_sta_rssi_too_low sta_rssi; + struct drvevnt_sta_activity_stat sta_activity_stat; + } data; +}; + +EventHdlr GetEventNotiferHook(IN UINT32 EventID); +INT SetCustomOUIProc(PRTMP_ADAPTER pAd, PSTRING arg); +INT SetCustomVIEProc(PRTMP_ADAPTER pAd, PSTRING arg); +INT SetChannelLoadDetectPeriodProc(PRTMP_ADAPTER pAd, PSTRING arg); +INT SetStaRssiDetectThresholdProc(PRTMP_ADAPTER pAd, PSTRING arg); +INT SetStaTxPktDetectPeriodProc(PRTMP_ADAPTER pAd, PSTRING arg); +INT SetStaTxPacketDetectThresholdProc(PRTMP_ADAPTER pAd, PSTRING arg); +INT SetStaRxPktDetectPeriodProc(PRTMP_ADAPTER pAd, PSTRING arg); +INT SetStaRxPacketDetectThresholdProc(PRTMP_ADAPTER pAd, PSTRING arg); +VOID WHCMlmePeriodicExec(PRTMP_ADAPTER pAd); + +#endif /* __EVENT_NOTIFIER_H__ */ +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/event_notifier_old.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/event_notifier_old.h new file mode 100644 index 000000000..5a4122d45 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/event_notifier_old.h @@ -0,0 +1,110 @@ +#ifndef __EVENT_NOTIFIER_H__ +#define __EVENT_NOTIFIER_H__ + +#define CUSTOM_IE_TOTAL_LEN 128 + +enum { + DRVEVNT_FIRST_ID = 0, + WHC_DRVEVNT_STA_JOIN = 3, + WHC_DRVEVNT_STA_LEAVE, + DRVEVNT_END_ID, +}; + +typedef NTSTATUS (*EventHdlr)(IN RTMP_ADAPTER *pAd, ...); + +typedef struct { + UINT32 EventID; + EventHdlr EventHandler; +}EVENT_TABLE_T; +typedef struct _RxInfo{ + UCHAR channel; /* Wireless channel that receive this frame. */ + ULONG rate; /* RX data rate when recv frame */ + CHAR rssi; /* RSSI when recv frame */ +}RxInfo, *PRxInfo; +typedef struct _StaActivityItem { + ULONG PacketCount; /* Packet count */ + UCHAR CurrentState; /* Station's current state */ +}StaActivityItem, *PStaActivityItem; +struct drvevnt_sta_probe_req { + USHORT type; /* WHC_DRVEVNT_STA_PROBE_REQ */ + UCHAR sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + BOOLEAN is_ucast; /* If unicast frame */ + UINT32 cap; /* Refer to Wireless Capability Flag */ + RxInfo rx_info; + UCHAR custom_ie_len; /* Length of custom vendor information element */ + UCHAR custom_ie[CUSTOM_IE_TOTAL_LEN]; /* Content of custom vendor information element */ +}; + +struct drvevnt_ap_probe_rsp { + USHORT type; /* WHC_DRVEVNT_AP_PROBE_RSP */ + UCHAR ap_mac[MAC_ADDR_LEN]; /* AP's MAC address */ + UINT32 cap; /* Refer to Wireless Capability Flag */ + RxInfo rx_info; + UCHAR custom_ie_len; /* Length of custom vendor information element */ + UCHAR custom_ie[CUSTOM_IE_TOTAL_LEN]; /* Content of custom vendor information element */ +}; + +struct drvevnt_sta_join { + USHORT type; /* WHC_DRVEVNT_STA_JOIN */ + UCHAR sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + UCHAR channel; /* Wireless channel that receive this frame. */ + UINT32 aid; /* Station's association ID */ + UCHAR custom_ie_len; /* Length of custom vendor information element */ + UCHAR custom_ie[CUSTOM_IE_TOTAL_LEN]; /* Content of custom vendor information element */ + UINT32 capability; +}; + +struct drvevnt_sta_leave { + USHORT type; /* WHC_DRVEVNT_STA_LEAVE */ + UCHAR sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + UCHAR channel; /* Wireless channel that receive this frame. */ +}; + +struct drvevnt_ext_uplink_stat { + USHORT type; /* WHC_DRVEVNT_EXT_UPLINK_STAT */ + UCHAR ap_mac[MAC_ADDR_LEN]; /* AP's MAC address */ + UCHAR channel; /* Wireless channel that receive this frame. */ + UINT32 link_state; /* Station's link status*/ +}; + +struct drvevnt_sta_timeout { + USHORT type; /* WHC_DRVEVNT_STA_LEAVE */ + UCHAR sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + UCHAR channel; /* Current Wireless channel. */ +}; + +struct drvevnt_sta_auth_reject { + USHORT type; /* WHC_DRVEVNT_STA_AUTH_REJECT */ + UCHAR sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + RxInfo rx_info; +}; +struct drvevnt_sta_rssi_too_low { + USHORT type; /* WHC_DRVEVNT_STA_RSSI_TOO_LOW */ + UCHAR sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + CHAR rssi; /* Station's Rssi */ +}; + +struct drvevnt_sta_activity_stat { + USHORT type; /* WHC_DRVEVNT_STA_ACTIVITY_STATE */ + UCHAR sta_mac[MAC_ADDR_LEN]; /* Station's MAC address */ + BOOLEAN bTx; /* Check if it is for tx record */ + StaActivityItem sta_state; /* Station's state record */ +}; + +struct drvevnt_type_buf { + union { + struct drvevnt_sta_probe_req probereq; + struct drvevnt_ap_probe_rsp probersp; + struct drvevnt_sta_join join; + struct drvevnt_sta_leave leave; + struct drvevnt_ext_uplink_stat link_state; + struct drvevnt_sta_timeout timeout; + struct drvevnt_sta_auth_reject auth_reject; + struct drvevnt_sta_rssi_too_low sta_rssi; + struct drvevnt_sta_activity_stat sta_activity_stat; + } data; +}; + +EventHdlr GetEventNotiferHook(IN UINT32 EventID); + +#endif /* __EVENT_NOTIFIER_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/firmware.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/firmware.h new file mode 100644 index 000000000..27588bbf8 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/firmware.h @@ -0,0 +1,517 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR FirmwareImage [] = { +0x02, 0x02, 0xa3, 0x02, 0x02, 0x2e, 0x22, 0xff, 0xff, 0xff, 0xff, 0x02, 0x01, 0x2c, 0xff, 0xff, +0xff, 0xff, 0xff, 0x02, 0x00, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0xdd, 0xc0, 0xe0, +0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x18, 0xc2, 0xaf, 0x30, 0x45, 0x03, +0x12, 0x10, 0x09, 0x90, 0x04, 0x16, 0xe0, 0x30, 0xe3, 0x03, 0x74, 0x08, 0xf0, 0x90, 0x04, 0x14, +0xe0, 0x20, 0xe7, 0x03, 0x02, 0x00, 0xcb, 0x74, 0x80, 0xf0, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x24, +0x90, 0x04, 0x04, 0xe0, 0x24, 0xcf, 0x60, 0x30, 0x14, 0x60, 0x42, 0x24, 0xe2, 0x60, 0x47, 0x14, +0x60, 0x55, 0x24, 0x21, 0x70, 0x60, 0xe5, 0x55, 0x24, 0xfe, 0x60, 0x07, 0x14, 0x60, 0x08, 0x24, +0x02, 0x70, 0x08, 0x7d, 0x01, 0x80, 0x28, 0x7d, 0x02, 0x80, 0x24, 0x90, 0x70, 0x10, 0xe0, 0xf5, +0x50, 0x85, 0x24, 0x40, 0xd2, 0x01, 0x80, 0x3e, 0xe5, 0x55, 0x64, 0x03, 0x60, 0x04, 0xe5, 0x55, +0x70, 0x04, 0x7d, 0x02, 0x80, 0x09, 0x85, 0x24, 0x41, 0xd2, 0x02, 0x80, 0x29, 0xad, 0x55, 0xaf, +0x24, 0x12, 0x02, 0x0a, 0x80, 0x20, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x47, 0x90, 0x70, 0x11, 0xe0, +0xf5, 0x44, 0x12, 0x10, 0x25, 0x80, 0x06, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x45, 0xe4, 0xfd, 0xaf, +0x24, 0x12, 0x02, 0x0a, 0xd2, 0x04, 0x90, 0x70, 0x13, 0xe4, 0xf0, 0x90, 0x70, 0x13, 0xe4, 0xf0, +0xd2, 0xaf, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0xc0, 0xe0, 0xc0, +0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0xe8, 0xc0, 0xe0, 0xe9, 0xc0, 0xe0, 0xea, 0xc0, 0xe0, +0xeb, 0xc0, 0xe0, 0xec, 0xc0, 0xe0, 0xed, 0xc0, 0xe0, 0xee, 0xc0, 0xe0, 0xef, 0xc0, 0xe0, 0xc2, +0xaf, 0x30, 0x45, 0x03, 0x12, 0x10, 0x12, 0xd2, 0xaf, 0xd0, 0xe0, 0xff, 0xd0, 0xe0, 0xfe, 0xd0, +0xe0, 0xfd, 0xd0, 0xe0, 0xfc, 0xd0, 0xe0, 0xfb, 0xd0, 0xe0, 0xfa, 0xd0, 0xe0, 0xf9, 0xd0, 0xe0, +0xf8, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0xc0, 0xe0, 0xc0, 0xf0, +0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0xc2, 0xaf, 0x30, 0x45, 0x03, 0x12, 0x10, +0x0c, 0x30, 0x58, 0x0a, 0xe5, 0x54, 0x60, 0x04, 0x15, 0x54, 0x80, 0x02, 0xc2, 0x58, 0x30, 0x59, +0x0a, 0xe5, 0x50, 0x60, 0x04, 0x15, 0x50, 0x80, 0x02, 0xc2, 0x59, 0xd5, 0x53, 0x07, 0x30, 0x60, +0x04, 0x15, 0x46, 0xd2, 0x04, 0x30, 0x45, 0x03, 0x12, 0x10, 0x0f, 0xc2, 0x8d, 0xd2, 0xaf, 0xd0, +0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x12, 0x02, 0x50, 0x30, 0x45, 0x03, +0x12, 0x10, 0x03, 0x30, 0x01, 0x06, 0x20, 0x09, 0x03, 0x12, 0x10, 0x1c, 0x30, 0x02, 0x06, 0x20, +0x0a, 0x03, 0x12, 0x10, 0x1f, 0x30, 0x03, 0x06, 0x20, 0x0b, 0x03, 0x12, 0x10, 0x1f, 0x30, 0x04, +0x06, 0x20, 0x0c, 0x03, 0x12, 0x10, 0x22, 0x20, 0x13, 0x09, 0x20, 0x11, 0x06, 0xe5, 0x2b, 0x45, +0x2c, 0x60, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0xa9, 0x12, 0x02, 0x80, 0x80, 0xbf, 0xc2, 0x43, +0xd2, 0x45, 0xe4, 0xf5, 0x20, 0xf5, 0x21, 0xf5, 0x53, 0xf5, 0x46, 0xf5, 0x2b, 0xf5, 0x2c, 0xc2, +0x42, 0xf5, 0x51, 0xf5, 0x52, 0xf5, 0x55, 0x90, 0x04, 0x18, 0x74, 0x80, 0xf0, 0x90, 0x04, 0x1a, +0x74, 0x08, 0xf0, 0x22, 0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, +0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, +0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0xef, 0xf4, 0x60, 0x1f, 0xe4, 0xfe, +0x12, 0x02, 0xaf, 0xe0, 0xb4, 0xff, 0x12, 0x12, 0x02, 0xaf, 0xef, 0xf0, 0x74, 0x1c, 0x2e, 0xf5, +0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xe3, 0x22, 0xc0, 0xe0, +0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x08, 0xc2, 0xaf, 0x30, 0x45, 0x03, +0x12, 0x10, 0x06, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, +0xc2, 0xaf, 0x12, 0x00, 0x06, 0x12, 0x01, 0xbe, 0x12, 0x02, 0x69, 0xe4, 0xf5, 0x22, 0xf5, 0x47, +0x90, 0x04, 0x00, 0x74, 0x80, 0xf0, 0xd2, 0xaf, 0x22, 0x75, 0x89, 0x02, 0xe4, 0xf5, 0x8c, 0xf5, +0x8a, 0xf5, 0x88, 0xf5, 0xb8, 0xf5, 0xe8, 0x75, 0x90, 0x18, 0xd2, 0x8c, 0x75, 0xa8, 0x05, 0x22, +0x30, 0x45, 0x03, 0x12, 0x10, 0x15, 0xe5, 0x20, 0x70, 0x03, 0x20, 0x10, 0x03, 0x30, 0x11, 0x03, +0x43, 0x87, 0x01, 0x22, 0xce, 0xef, 0xce, 0xee, 0x60, 0x08, 0x7f, 0xff, 0x12, 0x02, 0xc5, 0x1e, +0x80, 0xf5, 0x22, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x5f, 0x02, 0x01, 0x7a, 0x74, +0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0x22, 0xef, 0x90, 0x02, 0xc3, 0x93, 0x90, +0x03, 0x00, 0x73, 0x0a, 0x18, 0xef, 0x60, 0x03, 0x1f, 0x80, 0xfa, 0x22, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xc0, 0x26, 0x74, 0x03, 0xc0, 0xe0, 0xc0, 0x82, 0xc0, 0x83, 0x75, 0x26, 0x0a, 0x22, 0xc0, 0x26, +0x74, 0x03, 0xc0, 0xe0, 0xc0, 0x82, 0xc0, 0x83, 0x75, 0x26, 0x18, 0x22, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x32, 0x02, 0x10, 0x33, 0x02, 0x14, 0xc2, 0x02, +0x14, 0xc3, 0x02, 0x15, 0x8f, 0x02, 0x15, 0x90, 0xc3, 0x22, 0xff, 0xff, 0x02, 0x1a, 0x6f, 0x02, +0x1b, 0xec, 0x02, 0x16, 0xbc, 0x02, 0x15, 0xf7, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x1d, +0x19, 0x22, 0x22, 0x90, 0x04, 0x14, 0xe0, 0x20, 0xe7, 0x03, 0x02, 0x14, 0xc1, 0x90, 0x70, 0x12, +0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0, 0x12, 0x01, 0xe4, 0x10, 0xda, 0x30, 0x10, 0xb1, 0x31, +0x10, 0x93, 0x35, 0x10, 0x8a, 0x36, 0x10, 0xe7, 0x40, 0x10, 0xfe, 0x41, 0x11, 0x15, 0x50, 0x11, +0x5a, 0x51, 0x11, 0x63, 0x52, 0x11, 0x63, 0x53, 0x11, 0x63, 0x54, 0x11, 0x9f, 0x55, 0x11, 0xfc, +0x56, 0x12, 0x4f, 0x64, 0x12, 0x6a, 0x72, 0x13, 0x1e, 0x73, 0x13, 0x42, 0x74, 0x14, 0x35, 0x80, +0x14, 0xa5, 0x83, 0x14, 0x5c, 0x91, 0x00, 0x00, 0x14, 0xc1, 0x90, 0x70, 0x11, 0xe0, 0xf5, 0x3c, +0x02, 0x14, 0xbb, 0xe5, 0x55, 0xb4, 0x02, 0x0f, 0xe5, 0x58, 0x30, 0xe0, 0x06, 0x90, 0x01, 0x0d, +0x74, 0x08, 0xf0, 0x7d, 0x01, 0x80, 0x02, 0x7d, 0x02, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0x02, 0x14, +0xbb, 0x20, 0x02, 0x03, 0x30, 0x03, 0x0a, 0x7d, 0x02, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0x02, 0x14, +0xbb, 0xe5, 0x30, 0xd3, 0x94, 0x01, 0x40, 0x0c, 0x90, 0x01, 0x0c, 0xe0, 0x44, 0x02, 0xf0, 0xa3, +0xe0, 0x44, 0x04, 0xf0, 0x85, 0x56, 0x41, 0xd2, 0x02, 0x22, 0x90, 0x70, 0x11, 0xe0, 0xb4, 0x5a, +0x03, 0xc2, 0x4f, 0x22, 0xd2, 0x4f, 0x22, 0xe5, 0x30, 0xd3, 0x94, 0x01, 0x50, 0x03, 0x02, 0x14, +0xc1, 0x90, 0x01, 0x0c, 0xe0, 0x44, 0x02, 0xf0, 0xa3, 0xe0, 0x44, 0x04, 0xf0, 0x22, 0xe5, 0x30, +0xd3, 0x94, 0x01, 0x50, 0x03, 0x02, 0x14, 0xc1, 0x90, 0x01, 0x0c, 0xe0, 0x54, 0xfd, 0xf0, 0xa3, +0xe0, 0x54, 0xfb, 0xf0, 0x22, 0xe5, 0x30, 0xd3, 0x94, 0x01, 0x40, 0x07, 0xe5, 0x55, 0x60, 0x03, +0x02, 0x14, 0xc1, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0xff, 0xbf, 0x0a, 0x0d, 0x90, 0x70, 0x11, +0xe0, 0xb4, 0x08, 0x06, 0x75, 0x4e, 0x01, 0x75, 0x4f, 0x84, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, +0xff, 0xbf, 0x02, 0x12, 0x90, 0x70, 0x11, 0xe0, 0x64, 0x08, 0x60, 0x04, 0xe0, 0xb4, 0x20, 0x06, +0x75, 0x4e, 0x03, 0x75, 0x4f, 0x20, 0xe4, 0xf5, 0x3f, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, +0x92, 0x47, 0x22, 0xe5, 0x30, 0xd3, 0x94, 0x01, 0x40, 0x07, 0xe5, 0x55, 0x60, 0x03, 0x02, 0x13, +0x29, 0x90, 0x04, 0x04, 0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, 0x10, 0xe0, 0xff, +0x74, 0x47, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, 0x74, 0x48, 0x25, +0x57, 0xf8, 0xc6, 0xef, 0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0x02, 0x14, 0xbb, 0xe5, +0x30, 0xd3, 0x94, 0x01, 0x40, 0x07, 0xe5, 0x55, 0x60, 0x03, 0x02, 0x13, 0x29, 0xe5, 0x47, 0x64, +0x07, 0x60, 0x1d, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x17, 0xe5, 0x47, 0x64, 0x09, 0x60, 0x11, 0xe5, +0x47, 0x64, 0x0a, 0x60, 0x0b, 0xe5, 0x47, 0x64, 0x0b, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x0c, 0x08, +0x90, 0x70, 0x11, 0xe0, 0x54, 0x0f, 0xf5, 0x3a, 0xe5, 0x47, 0xb4, 0x09, 0x08, 0xe5, 0x3a, 0xb4, +0x03, 0x03, 0xe4, 0xf5, 0x46, 0xe5, 0x47, 0xb4, 0x0a, 0x08, 0xe5, 0x3a, 0xb4, 0x01, 0x03, 0xe4, +0xf5, 0x46, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0xd2, 0x04, 0x22, 0x90, 0x70, 0x11, 0xe0, +0xf4, 0xff, 0x90, 0x70, 0x10, 0xe0, 0x5f, 0xff, 0x90, 0x70, 0x11, 0xe0, 0x55, 0x3f, 0x4f, 0x90, +0x70, 0x18, 0xf0, 0x90, 0x70, 0x11, 0xe0, 0x90, 0x70, 0x19, 0xf0, 0xe4, 0xfd, 0xaf, 0x56, 0x12, +0x02, 0x0a, 0x30, 0x15, 0x03, 0xd2, 0x14, 0x22, 0x90, 0x70, 0x18, 0xe0, 0xf5, 0x3f, 0x90, 0x02, +0x29, 0xe0, 0xff, 0x90, 0x70, 0x19, 0xe0, 0xfe, 0xef, 0x5e, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, +0x04, 0xaf, 0x3f, 0x80, 0x04, 0xe5, 0x3f, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0x90, +0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x1a, 0x75, 0x32, 0x03, 0x75, 0x33, 0x1f, 0xe4, 0xf5, 0x31, +0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0x02, 0x14, 0xbb, 0x90, 0x10, 0x00, 0xe0, 0xf5, 0x57, +0xe4, 0xf5, 0x58, 0xf5, 0x59, 0x90, 0x10, 0x03, 0xe0, 0xb4, 0x28, 0x05, 0x75, 0x58, 0x01, 0x80, +0x3c, 0x90, 0x10, 0x03, 0xe0, 0xb4, 0x30, 0x05, 0x75, 0x58, 0x02, 0x80, 0x30, 0x90, 0x10, 0x03, +0xe0, 0xb4, 0x33, 0x05, 0x75, 0x58, 0x04, 0x80, 0x24, 0x90, 0x10, 0x03, 0xe0, 0xb4, 0x35, 0x0c, +0x90, 0x10, 0x02, 0xe0, 0xb4, 0x72, 0x05, 0x75, 0x58, 0x08, 0x80, 0x11, 0x90, 0x10, 0x03, 0xe0, +0xb4, 0x35, 0x0a, 0x90, 0x10, 0x02, 0xe0, 0xb4, 0x93, 0x03, 0x75, 0x58, 0x10, 0xe5, 0x58, 0x30, +0xe1, 0x19, 0x90, 0x05, 0x08, 0xe0, 0x44, 0x01, 0xf0, 0xfd, 0x90, 0x05, 0x05, 0xe0, 0x54, 0xfb, +0xf0, 0x44, 0x04, 0xf0, 0xed, 0x54, 0xfe, 0x90, 0x05, 0x08, 0xf0, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, +0x75, 0x3a, 0xff, 0xf5, 0x30, 0x90, 0x05, 0xa4, 0x74, 0x11, 0xf0, 0xa3, 0x74, 0xff, 0xf0, 0xa3, +0x74, 0x03, 0xf0, 0xd2, 0x4f, 0x90, 0x01, 0x0d, 0xe0, 0x44, 0x40, 0xf0, 0x75, 0x3c, 0xff, 0xad, +0x57, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0x90, 0x70, 0x36, 0x74, 0x37, 0xf0, 0xa3, 0x74, 0x32, 0xf0, +0x90, 0x04, 0x01, 0xe0, 0x44, 0x01, 0xf0, 0xc2, 0x1a, 0xc2, 0x17, 0x02, 0x14, 0xbb, 0xe5, 0x30, +0xd3, 0x94, 0x01, 0x40, 0x0b, 0xe5, 0x55, 0x60, 0x07, 0x7d, 0x03, 0xaf, 0x56, 0x02, 0x02, 0x0a, +0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x93, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0x02, +0x14, 0xbb, 0x90, 0x10, 0x00, 0xe0, 0x90, 0x10, 0x2c, 0xf0, 0x90, 0x10, 0x2f, 0x74, 0x40, 0xf0, +0x90, 0x70, 0x11, 0xe0, 0x54, 0x7f, 0xf5, 0x57, 0xe0, 0x54, 0x80, 0x90, 0x70, 0x32, 0xf0, 0x90, +0x70, 0x10, 0xe0, 0xff, 0xe5, 0x57, 0xd3, 0x9f, 0x40, 0x43, 0x90, 0x70, 0x33, 0xe5, 0x57, 0xf0, +0x90, 0x70, 0x10, 0xe0, 0xff, 0x90, 0x70, 0x33, 0xe0, 0xc3, 0x9f, 0xd3, 0x94, 0x04, 0x40, 0x73, +0xe0, 0x24, 0xfc, 0xf0, 0xe0, 0xff, 0x90, 0x70, 0x32, 0xe0, 0x4f, 0x90, 0x05, 0x00, 0xf0, 0xe5, +0x58, 0x54, 0x0f, 0x60, 0x04, 0x7f, 0x17, 0x80, 0x02, 0x7f, 0x11, 0x90, 0x05, 0x01, 0xef, 0xf0, +0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, 0xff, 0x12, 0x02, 0x94, 0x80, 0xc3, 0x90, 0x70, 0x33, +0xe5, 0x57, 0xf0, 0x90, 0x70, 0x33, 0xe0, 0xff, 0x90, 0x70, 0x10, 0xe0, 0xc3, 0x9f, 0xd3, 0x94, +0x04, 0x40, 0x30, 0x90, 0x70, 0x33, 0xe0, 0x24, 0x04, 0xf0, 0xe0, 0xff, 0x90, 0x70, 0x32, 0xe0, +0x4f, 0x90, 0x05, 0x00, 0xf0, 0xe5, 0x58, 0x54, 0x0f, 0x60, 0x04, 0x7f, 0x17, 0x80, 0x02, 0x7f, +0x11, 0x90, 0x05, 0x01, 0xef, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, 0xff, 0x12, 0x02, +0x94, 0x80, 0xc0, 0x90, 0x70, 0x10, 0xe0, 0xff, 0x90, 0x70, 0x32, 0xe0, 0x4f, 0x90, 0x05, 0x00, +0xf0, 0xe5, 0x58, 0x54, 0x0f, 0x60, 0x04, 0x7f, 0x17, 0x80, 0x02, 0x7f, 0x11, 0x90, 0x05, 0x01, +0xef, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, 0xff, 0x12, 0x02, 0x94, 0x90, 0x10, 0x00, +0xe0, 0x90, 0x10, 0x2c, 0xf0, 0x90, 0x10, 0x2f, 0x74, 0x7f, 0xf0, 0xe4, 0xfd, 0xaf, 0x56, 0x12, +0x02, 0x0a, 0x02, 0x14, 0xbb, 0xe5, 0x30, 0xd3, 0x94, 0x01, 0x40, 0x0d, 0xe5, 0x55, 0x60, 0x09, +0x7d, 0x03, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0x80, 0x72, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, +0x4a, 0xd2, 0x05, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0x80, 0x5f, 0x90, 0x70, 0x11, 0xe0, +0x24, 0xff, 0x92, 0x17, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x5d, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, +0x0a, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0x30, 0x17, 0x13, 0x90, 0x10, 0x00, 0xe0, 0x90, 0x10, +0x2c, 0xf0, 0x90, 0x10, 0x2f, 0xe0, 0x54, 0xf0, 0xf5, 0x57, 0x45, 0x5d, 0xf0, 0xe4, 0x90, 0x70, +0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x2a, 0x90, 0x70, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x02, +0x2c, 0x74, 0xff, 0xf0, 0x22, 0xe4, 0xf5, 0x30, 0xd2, 0x4f, 0x90, 0x70, 0x10, 0xe0, 0xf4, 0x60, +0x03, 0xe0, 0xf5, 0x30, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x0a, 0x90, 0x04, 0x14, 0x74, 0x80, +0xf0, 0x22, 0x22, 0xe5, 0x33, 0x45, 0x32, 0x60, 0x0a, 0xe5, 0x33, 0x15, 0x33, 0x70, 0x0a, 0x15, +0x32, 0x80, 0x06, 0x75, 0x32, 0x03, 0x75, 0x33, 0x1f, 0xe5, 0x33, 0x45, 0x32, 0x60, 0x03, 0x02, +0x15, 0x70, 0x20, 0x1a, 0x03, 0x02, 0x15, 0x70, 0x74, 0xa0, 0x25, 0x31, 0xf5, 0x82, 0xe4, 0x34, +0x4c, 0xf5, 0x83, 0xe0, 0x60, 0x7a, 0x7f, 0x7e, 0x12, 0x15, 0xde, 0xef, 0x54, 0xfe, 0x44, 0x02, +0xfd, 0x7f, 0x7e, 0x12, 0x15, 0xc4, 0xe5, 0x31, 0x7f, 0x00, 0x25, 0xe0, 0xfe, 0xef, 0x24, 0x00, +0xf5, 0x82, 0x74, 0x4d, 0x3e, 0xaf, 0x82, 0x90, 0x4c, 0xa8, 0xf0, 0xa3, 0xef, 0xf0, 0xe4, 0xf5, +0x56, 0xf5, 0x57, 0x7f, 0x7f, 0x12, 0x15, 0xde, 0x90, 0x4c, 0xa8, 0xe0, 0xfa, 0xa3, 0xe0, 0x25, +0x57, 0xf5, 0x82, 0xea, 0x35, 0x56, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x57, 0xe5, 0x57, 0x70, 0x02, +0x05, 0x56, 0xc3, 0x94, 0x80, 0xe5, 0x56, 0x94, 0x01, 0x40, 0xd8, 0x7f, 0x7e, 0x12, 0x15, 0xde, +0xef, 0x44, 0x03, 0xfd, 0x7f, 0x7e, 0x12, 0x15, 0xc4, 0x74, 0xa0, 0x25, 0x31, 0xf5, 0x82, 0xe4, +0x34, 0x4c, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x31, 0xe5, 0x31, 0xb4, 0x08, 0x03, 0xe4, 0xf5, 0x31, +0xe5, 0x53, 0x70, 0x1a, 0x30, 0x60, 0x09, 0xb2, 0x4d, 0x30, 0x4d, 0x04, 0x05, 0x46, 0xc2, 0x04, +0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f, 0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0x22, 0x22, +0x30, 0x14, 0x30, 0x90, 0x70, 0x19, 0xe0, 0x55, 0x3f, 0xff, 0x90, 0x70, 0x18, 0xe0, 0x4f, 0xf5, +0x3f, 0x90, 0x02, 0x29, 0xe0, 0xff, 0x90, 0x70, 0x19, 0xe0, 0xfe, 0xef, 0x5e, 0x90, 0x02, 0x29, +0xf0, 0x30, 0x47, 0x04, 0xaf, 0x3f, 0x80, 0x04, 0xe5, 0x3f, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, +0xf0, 0xc2, 0x14, 0x22, 0x90, 0x10, 0x1c, 0xed, 0xf0, 0xa3, 0xef, 0xf0, 0xa3, 0x74, 0x0a, 0xf0, +0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x58, 0x90, 0x10, 0x1e, 0xe0, 0x20, 0xe1, 0xf3, 0x22, 0x90, 0x10, +0x1d, 0xef, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x58, 0x90, 0x10, 0x1e, +0xe0, 0x20, 0xe1, 0xf3, 0xaf, 0x58, 0x22, 0xc2, 0x4b, 0xc2, 0x4c, 0xe5, 0x44, 0x12, 0x01, 0xe4, +0x16, 0x19, 0x00, 0x16, 0xa7, 0x04, 0x16, 0xa3, 0x08, 0x16, 0x83, 0x10, 0x16, 0x2d, 0x20, 0x16, +0x4d, 0x60, 0x16, 0x5e, 0xa0, 0x00, 0x00, 0x16, 0xa9, 0x85, 0x48, 0x43, 0x85, 0x4a, 0x42, 0x85, +0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60, 0x03, 0x02, 0x16, 0xa9, 0x80, 0x1b, 0xe5, 0x48, 0xc4, +0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4c, 0xc4, 0x54, 0x0f, +0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x61, 0x53, 0x43, 0x0f, 0x80, 0x5c, 0x85, 0x49, 0x43, +0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x4d, 0x80, 0x1b, 0xe5, 0x49, +0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b, 0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4d, 0xc4, 0x54, +0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x30, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x10, 0xf5, +0x43, 0x80, 0x26, 0xe5, 0x47, 0x64, 0x04, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43, 0x5e, +0x04, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30, 0xf5, +0x43, 0x80, 0x06, 0xd2, 0x4b, 0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x27, 0xe5, 0x42, 0xc4, 0x54, +0xf0, 0xff, 0xe5, 0x43, 0x54, 0x0f, 0x4f, 0xf5, 0x5f, 0xd2, 0x60, 0x22, 0xd2, 0x15, 0xe5, 0x47, +0x24, 0xf5, 0x60, 0x0b, 0x24, 0xcb, 0x60, 0x07, 0x24, 0x40, 0x70, 0x06, 0xc2, 0x15, 0x22, 0x12, +0x1a, 0x3a, 0x12, 0x16, 0xde, 0xc2, 0x15, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, +0x90, 0x04, 0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x18, 0x80, 0x08, 0xe5, 0x4e, 0x45, 0x4f, +0x24, 0xff, 0x92, 0x18, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x19, 0x74, 0x1e, +0xf0, 0xe5, 0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x27, 0x70, 0x13, 0x30, 0x18, 0x05, 0xe5, 0x5f, +0x20, 0xe5, 0x0b, 0x30, 0x19, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5, 0x27, +0x70, 0x05, 0x75, 0x27, 0x0c, 0x80, 0x02, 0x15, 0x27, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f, 0xe5, +0x5f, 0x30, 0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5, 0x47, +0x64, 0x03, 0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x27, 0x70, +0x03, 0x30, 0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x27, 0x70, 0x05, 0x75, 0x27, 0x07, 0x80, 0x02, 0x15, +0x27, 0xd2, 0x6c, 0xd2, 0x6d, 0xe5, 0x47, 0xb4, 0x09, 0x14, 0xe5, 0x44, 0x20, 0xe3, 0x0b, 0xe5, +0x3a, 0x64, 0x02, 0x60, 0x05, 0xe5, 0x3a, 0xb4, 0x03, 0x04, 0xc2, 0x6c, 0xd2, 0x6d, 0xe5, 0x47, +0xb4, 0x0a, 0x13, 0xe5, 0x3a, 0xb4, 0x01, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x08, 0xe5, 0x3a, +0x70, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0x20, 0x69, 0x07, 0xe5, 0x5e, 0x20, 0xe0, 0x02, 0xb2, 0x68, +0x20, 0x6b, 0x07, 0xe5, 0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a, 0x20, 0x6d, 0x07, 0xe5, 0x5e, 0x20, +0xe2, 0x02, 0xb2, 0x6c, 0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x26, 0x30, 0x68, +0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe0, 0x04, 0x7f, 0x01, 0x80, 0x02, +0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, +0xee, 0x6f, 0x24, 0xff, 0x92, 0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80, 0x26, 0x30, +0x6a, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe1, 0x04, 0x7f, 0x01, 0x80, +0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, +0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x75, 0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c, 0x80, 0x26, +0xe5, 0x47, 0x64, 0x0a, 0x70, 0x22, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe3, 0x80, 0x17, 0xe5, +0x3a, 0xb4, 0x01, 0x06, 0xe5, 0x46, 0xa2, 0xe3, 0x80, 0x34, 0xe5, 0x46, 0x20, 0xe4, 0x03, 0x30, +0xe5, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x80, 0x26, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, +0x1d, 0xe5, 0x5e, 0x20, 0xe2, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, +0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x71, +0x92, 0x70, 0x90, 0x10, 0x00, 0xe0, 0x90, 0x10, 0x2c, 0xf0, 0x90, 0x10, 0x03, 0xe0, 0xc3, 0x94, +0x30, 0x40, 0x19, 0xe0, 0x64, 0x32, 0x60, 0x14, 0xa2, 0x71, 0x92, 0x77, 0xa2, 0x70, 0x92, 0x76, +0xe5, 0x2e, 0x13, 0x13, 0x54, 0x3f, 0xf5, 0x2e, 0xc2, 0x77, 0xd2, 0x76, 0x30, 0x17, 0x0d, 0x53, +0x2e, 0xf0, 0xe5, 0x2e, 0x45, 0x5d, 0x90, 0x10, 0x2f, 0xf0, 0x80, 0x06, 0x90, 0x10, 0x2f, 0xe5, +0x2e, 0xf0, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x47, 0x90, 0x02, 0x28, 0xe0, 0x30, 0x47, 0x03, 0xff, +0x80, 0x02, 0xf4, 0xff, 0x8f, 0x3f, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, +0x54, 0x0f, 0x14, 0x60, 0x0c, 0x24, 0xfe, 0x60, 0x0c, 0x24, 0x03, 0x70, 0x13, 0xc2, 0xf8, 0x80, +0x0f, 0xd2, 0xf8, 0x80, 0x0b, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0xf8, +0x30, 0x47, 0x05, 0xaf, 0x3f, 0x02, 0x1a, 0x34, 0xe5, 0x3f, 0xf4, 0xff, 0x02, 0x1a, 0x34, 0xe5, +0x47, 0x64, 0x07, 0x60, 0x0f, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x09, 0xe5, 0x47, 0x64, 0x09, 0x60, +0x03, 0x02, 0x19, 0xa2, 0x90, 0x02, 0x28, 0xe0, 0x30, 0x47, 0x03, 0xff, 0x80, 0x02, 0xf4, 0xff, +0x8f, 0x3f, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x22, 0x14, 0x60, +0x25, 0x14, 0x60, 0x2d, 0x24, 0xfc, 0x60, 0x49, 0x24, 0xf9, 0x60, 0x14, 0x24, 0x0e, 0x70, 0x50, +0xe5, 0x46, 0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xe5, 0xf0, 0x24, 0xff, 0x80, 0x3a, +0xd2, 0xf9, 0xc2, 0xf8, 0x80, 0x3e, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x1d, 0xc3, 0x80, +0x1a, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, +0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xee, 0x4f, 0x24, 0xff, 0x92, 0xf8, 0xc2, 0xf9, 0x80, +0x13, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0xf9, 0xc2, 0xf8, 0x80, 0x04, +0xc2, 0xf8, 0xc2, 0xf9, 0x30, 0x47, 0x04, 0xaf, 0x3f, 0x80, 0x04, 0xe5, 0x3f, 0xf4, 0xff, 0x02, +0x1a, 0x34, 0xe5, 0x47, 0x64, 0x0c, 0x60, 0x09, 0xe5, 0x47, 0x64, 0x0b, 0x60, 0x03, 0x02, 0x1a, +0x39, 0x90, 0x02, 0x28, 0xe0, 0x30, 0x47, 0x03, 0xff, 0x80, 0x02, 0xf4, 0xff, 0x8f, 0x3f, 0x90, +0x02, 0x29, 0xe0, 0x54, 0xfd, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x20, 0x14, 0x60, 0x21, 0x14, 0x60, +0x2b, 0x24, 0xfc, 0x60, 0x45, 0x24, 0xf9, 0x60, 0x12, 0x24, 0x0e, 0x70, 0x4a, 0xe5, 0x46, 0x13, +0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xe5, 0xf0, 0x80, 0x29, 0xd2, 0xf9, 0x80, 0x3a, 0xe5, +0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0xf9, 0x80, 0x2d, 0xe5, 0x46, 0x30, 0xe2, +0x0d, 0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, +0x7f, 0x00, 0xee, 0x4f, 0x24, 0xff, 0x92, 0xf9, 0x80, 0x0f, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, +0x80, 0x01, 0xc3, 0x92, 0xf9, 0x80, 0x02, 0xc2, 0xf9, 0x30, 0x47, 0x04, 0xaf, 0x3f, 0x80, 0x04, +0xe5, 0x3f, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0xe5, 0x47, 0xb4, 0x0b, 0x10, 0x90, +0x02, 0x29, 0xe0, 0x54, 0xeb, 0xf0, 0xe5, 0x3f, 0x54, 0xeb, 0x45, 0x45, 0xf5, 0x3f, 0x22, 0xe4, +0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x45, 0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, +0x02, 0x28, 0xef, 0xf0, 0x22, 0x8f, 0x50, 0xd2, 0x59, 0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, +0xf5, 0x25, 0xc2, 0xaf, 0xe5, 0x51, 0x14, 0x60, 0x4a, 0x14, 0x60, 0x6b, 0x24, 0x02, 0x60, 0x03, +0x02, 0x1b, 0xd0, 0xd2, 0x59, 0x75, 0x55, 0x01, 0x90, 0x02, 0x08, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, +0x20, 0xe1, 0x23, 0x90, 0x04, 0x34, 0xe0, 0xb4, 0x02, 0x1c, 0xa3, 0xe0, 0xb4, 0x02, 0x17, 0xa3, +0xe0, 0xb4, 0x02, 0x12, 0x7f, 0x20, 0x12, 0x1a, 0x65, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0, +0x75, 0x51, 0x01, 0x02, 0x1b, 0xd0, 0xe5, 0x50, 0x60, 0x03, 0x02, 0x1b, 0xd0, 0x75, 0x25, 0x03, +0x02, 0x1b, 0xd0, 0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, 0x70, 0x12, 0x7f, 0x20, 0x12, 0x1a, 0x65, +0x90, 0x02, 0x08, 0xe0, 0x54, 0xfb, 0xf0, 0x75, 0x51, 0x02, 0x02, 0x1b, 0xd0, 0xe5, 0x50, 0x60, +0x03, 0x02, 0x1b, 0xd0, 0x02, 0x1b, 0xcb, 0x90, 0x02, 0x08, 0xe0, 0x30, 0xe3, 0x03, 0x02, 0x1b, +0xc7, 0x90, 0x04, 0x37, 0xe0, 0x64, 0x22, 0x60, 0x03, 0x02, 0x1b, 0xc7, 0x90, 0x12, 0x04, 0x74, +0x0a, 0xf0, 0xe5, 0x58, 0x30, 0xe3, 0x1c, 0x90, 0x00, 0x02, 0xe0, 0x30, 0xe0, 0x15, 0xe4, 0x90, +0x05, 0x00, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, 0x7f, 0x01, +0x12, 0x02, 0x94, 0x90, 0x13, 0x28, 0xe0, 0x90, 0x70, 0x1a, 0xf0, 0x90, 0x13, 0x29, 0xe0, 0x90, +0x70, 0x1b, 0xf0, 0x90, 0x13, 0x2b, 0xe0, 0x90, 0x70, 0x22, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x54, +0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xf0, 0xf0, 0x90, 0x13, 0x2b, 0xe0, 0x54, 0xcc, 0xf0, 0xe5, 0x58, +0x30, 0xe3, 0x17, 0xe5, 0x30, 0x70, 0x13, 0xe5, 0x3c, 0xf4, 0x90, 0x13, 0x2a, 0x60, 0x05, 0xe0, +0x54, 0xf3, 0x80, 0x11, 0xe0, 0x54, 0xfb, 0xf0, 0x80, 0x14, 0xe5, 0x3c, 0xf4, 0x90, 0x13, 0x2a, +0x60, 0x08, 0xe0, 0x54, 0xf2, 0x45, 0x3c, 0xf0, 0x80, 0x04, 0xe0, 0x54, 0xfa, 0xf0, 0x90, 0x04, +0x01, 0xe0, 0x44, 0x10, 0xf0, 0x75, 0x8c, 0x80, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x12, 0x04, 0xe0, +0x44, 0x04, 0xf0, 0xe5, 0x58, 0x30, 0xe0, 0x06, 0x90, 0x01, 0x0d, 0xe0, 0xf5, 0x2f, 0xe5, 0x30, +0xd3, 0x94, 0x01, 0x40, 0x17, 0x20, 0x02, 0x14, 0x20, 0x03, 0x11, 0x30, 0x4f, 0x0e, 0x90, 0x01, +0x0d, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0x01, 0x0c, 0xe0, 0x54, 0xfd, 0xf0, 0x75, 0x25, 0x01, 0x75, +0x55, 0x02, 0xe4, 0xf5, 0x51, 0x80, 0x09, 0xe5, 0x50, 0x70, 0x05, 0x75, 0x25, 0x03, 0xf5, 0x51, +0xe5, 0x25, 0x60, 0x15, 0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0xad, 0x25, 0xaf, 0x40, 0x12, +0x1c, 0xe5, 0xe5, 0x25, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0x30, 0x01, +0x0e, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0xc2, 0x01, 0x7d, 0x02, 0xaf, 0x40, 0x12, 0x1c, 0xe5, 0xe5, +0x52, 0x14, 0x60, 0x48, 0x14, 0x60, 0x25, 0x24, 0x02, 0x60, 0x03, 0x02, 0x1c, 0xe2, 0xe5, 0x30, +0xd3, 0x94, 0x01, 0x40, 0x11, 0x90, 0x01, 0x0c, 0xe0, 0x44, 0x02, 0xf0, 0xa3, 0xe0, 0x44, 0x04, +0xf0, 0x7f, 0x0a, 0x12, 0x02, 0x94, 0x75, 0x52, 0x02, 0x75, 0x55, 0x03, 0xe5, 0x58, 0x30, 0xe0, +0x06, 0x90, 0x01, 0x0d, 0xe5, 0x2f, 0xf0, 0x90, 0x12, 0x04, 0xe0, 0x54, 0xfb, 0xf0, 0x7f, 0x20, +0x12, 0x1a, 0x6a, 0x75, 0x52, 0x01, 0x75, 0x55, 0x03, 0x02, 0x1c, 0xe2, 0xe5, 0x54, 0x60, 0x03, +0x02, 0x1c, 0xe2, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x0e, 0xf0, 0xe0, 0x54, 0xef, 0xf0, 0xe4, 0xf5, +0x8c, 0xe5, 0x58, 0x54, 0x18, 0x60, 0x1e, 0x90, 0x70, 0x1a, 0xe0, 0x90, 0x13, 0x28, 0xf0, 0x90, +0x70, 0x1b, 0xe0, 0x90, 0x13, 0x29, 0xf0, 0xa3, 0x74, 0x05, 0xf0, 0x90, 0x70, 0x22, 0xe0, 0x90, +0x13, 0x2b, 0xf0, 0x80, 0x11, 0x90, 0x13, 0x28, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x0f, +0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x12, 0x04, 0x74, 0x03, 0xf0, 0xe5, 0x58, 0x30, 0xe3, +0x1d, 0x90, 0x00, 0x02, 0xe0, 0x30, 0xe0, 0x16, 0x90, 0x05, 0x00, 0x74, 0xe2, 0xf0, 0xa3, 0x74, +0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, 0x7f, 0x01, 0x12, 0x02, 0x94, 0x90, 0x02, +0x08, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44, 0x0c, 0xf0, 0xe4, 0xf5, 0x52, 0xf5, +0x55, 0x30, 0x02, 0x09, 0xc2, 0x02, 0x7d, 0x01, 0xaf, 0x41, 0x12, 0x1c, 0xe5, 0x30, 0x03, 0x02, +0xc2, 0x03, 0xd2, 0xaf, 0x22, 0xef, 0xf4, 0x60, 0x2d, 0xe4, 0xfe, 0x74, 0x14, 0x2e, 0xf5, 0x82, +0xe4, 0x34, 0x70, 0xf5, 0x83, 0xe0, 0xb4, 0xff, 0x19, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, +0x70, 0xf5, 0x83, 0xef, 0xf0, 0x74, 0x1c, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, +0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xd5, 0x22, 0x22, 0x22, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x43, +0xc2, 0xaf, 0x90, 0x70, 0x28, 0xe0, 0x90, 0x10, 0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, +0x1d, 0xf0, 0x90, 0x70, 0x2a, 0xe0, 0x90, 0x10, 0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x25, +0x90, 0x10, 0x1e, 0xe0, 0x20, 0xe1, 0xf3, 0x90, 0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, +0x10, 0x1d, 0xe0, 0x90, 0x70, 0x29, 0xf0, 0x90, 0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0xc2, +0x05, 0xd2, 0xaf, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x5b, 0xd2, } ; diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/fpga/fpga_ctl.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/fpga/fpga_ctl.h new file mode 100644 index 000000000..02abf8c88 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/fpga/fpga_ctl.h @@ -0,0 +1,62 @@ + +#ifndef __FPGA_CTL_H__ +#define __FPGA_CTL_H__ + + +#ifdef MT_MAC +typedef enum _MT_MAC_TXS_TYPE{ + TXS_NONE = 0x0, + + TXS_DATA = 0x1ff, + TXS_QDATA = 0x101, + TXS_NON_QDATA = 0x102, + + TXS_MGMT = 0x2ff, + TXS_BCN = 0x201, + TXS_MGMT_OTHER = 0x202, + + TXS_CTRL = 0x4ff, + TXS_ALL = 0xfff, +}MT_MAC_TXS_TYPE; +#endif /* MT_MAC */ + +struct fpga_ctrl { + int tx_kick_cnt; + int phy_rates; + int tx_data_phy; + UINT8 tx_data_bw; + UINT8 tx_data_ldpc; + UINT8 tx_data_mcs; + UINT8 tx_data_gi; + UINT8 tx_data_stbc; + int rx_data_phy; + UINT8 rx_data_bw; + UINT8 rx_data_ldpc; + UINT8 rx_data_mcs; + UINT8 rx_data_gi; + UINT8 rx_data_stbc; + UINT8 data_basize; + UINT8 fpga_on; + UINT8 fpga_tr_stop; + UINT8 vco_cal; + + UINT8 dma_mode; + +#ifdef MT_MAC + MT_MAC_TXS_TYPE txs_type; + UCHAR no_bcn; +#endif /* MT_MAC */ + +#ifdef CAPTURE_MODE + BOOLEAN cap_support; /* 0: no cap mode; 1: cap mode enable */ + UCHAR cap_type; /* 1: ADC6, 2: ADC8, 3: FEQ */ + UCHAR cap_trigger; /* 1: manual trigger, 2: auto trigger */ + BOOLEAN do_cap; /* 1: start to do cap, if auto, will triggered depends on trigger condition, if manual, start immediately */ + BOOLEAN cap_done; /* 1: capture done, 0: capture not finish yet */ + UINT32 trigger_offset; /* in unit of bytes */ + UCHAR *cap_buf; +#endif /* CAPTURE_MODE */ +}; + +#endif + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/frame_hdr.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/frame_hdr.h new file mode 100644 index 000000000..9211c6146 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/frame_hdr.h @@ -0,0 +1,81 @@ +#ifndef __FRAME_HDR_H__ +#define __FRAME_HDR_H__ + +#define HDR_TRANS_LEN 50 + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _WIFI_INFO_STRUCT{ + UINT32 more_data:1; + UINT32 wep:1; + UINT32 ps:1; + UINT32 qos:1; + UINT32 eosp:1; + UINT32 tid:4; + UINT32 mode:2; + UINT32 vlan:1; + UINT32 rev:3; + UINT32 bssidx:4; + UINT32 seq_num:12; +}WIFI_INFO_STRUCT; +#else +typedef struct GNU_PACKED _WIFI_INFO_STRUCT{ + UINT32 seq_num:12; + UINT32 bssidx:4; + UINT32 rev:3; + UINT32 vlan:1; + UINT32 mode:2; + UINT32 tid:4; + UINT32 eosp:1; + UINT32 qos:1; + UINT32 rdg:1; + UINT32 ps:1; + UINT32 wep:1; + UINT32 more_data:1; +}WIFI_INFO_STRUCT; +#endif /* RT_BIG_ENDIAN */ + +WIFI_INFO_STRUCT wifi_info[] = { + /* mode 1 -> AP, mode 2 --> STA */ + /* seq_num, bssidx, rsv, vlan, mode, tid, eosp, qos, rdg, ps, wep, more_data*/ + {0xff, 5, 0, 1, 1, 3, 0, 1, 0, 0, 0, 0}, +}; + + +UINT8 Input_Frame_Hdr[][HDR_TRANS_LEN] = { +/*type, len, vlan, wcid */ +/************************************ AP LLC/SNAP *********************************/ +/************************************ WDS LLC/SNAP ******************************/ +{0, 34, 0, 1, 0x08, 0x03, 0x00, 0x00, 0x33, 0x33, 0x00, 0x00, 0x00, 0x02, 0x00, 0x11, 0x22, 0x33, + 0x44, 0x50, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x50, 0x02, 0x00, 0xee, 0xee, 0xee, + 0xee, 0xee, 0x00, 0x00, 0x08, 0x00}, /* AP w/o LLC - Ether II*/ + +}; + +UINT8 Hdr_Bssid[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; + +UINT8 Hdr_Wcid[][6] = { + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, //0 + {0x00, 0x77, 0x77, 0x77, 0x77, 0x77}, //1 + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x01}, //2 + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x02}, //3 + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x03}, //4 + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x04}, //5 + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x05}, //6 + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x06}, //7 + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x07}, //8 + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x08}, //9 + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x09}, //a + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x0a}, //b + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x0b}, //c + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x0c}, //d + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x0d}, //e + {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x0e}, //f + }; +UINT8 MAC_WCID[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + +//UINT32 RX_Black_List[] = {0x0d898e88}; /* EAPOL 888E, TDLS 890D */ +//UINT32 RX_Black_List[] = {0x888e0800}; /* EAPOL 888E, TDLS 890D */ +UINT32 RX_Black_List[] = {}; /* EAPOL 888E, TDLS 890D */ +UINT32 TCI[] = {0x10021001, 0x10041003, 0x10061005, 0x10081007}; +UINT32 RX_WCID_En[] = {0xFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/frq_cal.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/frq_cal.h new file mode 100644 index 000000000..f5c41a507 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/frq_cal.h @@ -0,0 +1,77 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + eeprom.h + + Abstract: + Miniport header file for eeprom related information + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#ifndef __FRQCAL_H__ +#define __FRQCAL_H__ + +/* The frequency calibration control */ +typedef struct _FREQUENCY_CALIBRATION_CONTROL +{ + BOOLEAN bEnableFrequencyCalibration; /* Enable the frequency calibration algorithm */ + + BOOLEAN bSkipFirstFrequencyCalibration; /* Avoid calibrating frequency at the time the STA is just link-up */ + BOOLEAN bApproachFrequency; /* Approach the frequency */ + CHAR AdaptiveFreqOffset; /* Adaptive frequency offset */ + CHAR LatestFreqOffsetOverBeacon; /* Latest frequency offset from the beacon */ + CHAR BeaconPhyMode; /* Latest frequency offset from the beacon */ + +} FREQUENCY_CALIBRATION_CONTROL, *PFREQUENCY_CALIBRATION_CONTROL; + +#define RTMP_FREQ_CAL_DISABLE(__pAd) \ + __pAd->FreqCalibrationCtrl.bEnableFrequencyCalibration = FALSE; + +/* Invalid frequency offset */ +#define INVALID_FREQUENCY_OFFSET -128 + +/* The upperbound/lowerbound of the frequency offset */ +#define UPPERBOUND_OF_FREQUENCY_OFFSET 127 +#define LOWERBOUND_OF_FREQUENCY_OFFSET -127 + + +/*#ifdef RT5390 */ +/* The trigger point of the high/low frequency */ +#define HIGH_FREQUENCY_TRIGGER_POINT_OFDM 20 +#define LOW_FREQUENCY_TRIGGER_POINT_OFDM -20 +#define HIGH_FREQUENCY_TRIGGER_POINT_CCK 4 +#define LOW_FREQUENCY_TRIGGER_POINT_CCK -4 + + +/* The trigger point of decreasng/increasing the frequency offset */ +#define DECREASE_FREQUENCY_OFFSET_OFDM 10 +#define INCREASE_FREQUENCY_OFFSET_OFDM -10 +#define DECREASE_FREQUENCY_OFFSET_CCK 2 +#define INCREASE_FREQUENCY_OFFSET_CCK -2 +/*#endif // RT5390 */ + +/* The trigger point of decreasng/increasing the frequency offset */ +#define DECREASE_FREQUENCY_OFFSET 3 +#define INCREASE_FREQUENCY_OFFSET -3 + +/* Frequency calibration period */ +#define FREQUENCY_CALIBRATION_PERIOD 100 + +#endif /* __FRQCAL_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ft.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ft.h new file mode 100644 index 000000000..fbdfa162e --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ft.h @@ -0,0 +1,1259 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Abstract: + + + */ + +#ifdef DOT11R_FT_SUPPORT + + +#ifndef __FT_H +#define __FT_H + +#include "link_list.h" +#include "ft_cmm.h" + +#define IN +#define OUT +#define INOUT + +/* Macro */ +#define IS_FT_STA(__A) ((__A)->MdIeInfo.Len != 0) +#define IS_FT_ACTION_FRAME(__A) ((*(__A + 13) == 0x89)&&(*(__A + 14) == 0x0d)) + +/* ASCII to Integer */ +#define FT_ARG_ATOI(__pArgv) simple_strtol((RTMP_STRING *) __pArgv, 0, 10) + +extern UINT32 FT_KDP_MemAllocNum, FT_KDP_MemFreeNum; +#define FT_MEM_ALLOC(__pAd, __pMem, __Size) \ + os_alloc_mem(__pAd, (UCHAR **)(__pMem), __Size); \ + FT_KDP_MemAllocNum++; +#define FT_MEM_FREE(__pAd, __Mem) \ + { os_free_mem(__pAd, __Mem); \ + FT_KDP_MemFreeNum++; } + +/* atoi & atoh */ +#define FT_ARG_ATOI(__pArgv) simple_strtol((RTMP_STRING *) __pArgv, 0, 10) +#define FT_ARG_ATOH(__Buf, __Hex) AtoH((RTMP_STRING *) __Buf, __Hex, 1) + +#ifdef CONFIG_AP_SUPPORT +/* linked list, please reference to link_list.h */ +#define FT_KDP_SIGNAL RT_SIGNAL_STRUC + +#define FT_KDP_IOCTL_KEY_REQ(__pAd, __pInfo, __InfoLen) \ +{ \ + UINT32 __PeerIP; \ + memcpy(&__PeerIP, __pInfo, FT_IP_ADDRESS_SIZE); \ + FT_KDP_KeyRequestToUs(__pAd, __PeerIP, \ + (__pInfo)+FT_IP_ADDRESS_SIZE, \ + (FT_KDP_EVT_KEY_ELM *) \ + ((__pInfo)+FT_IP_ADDRESS_SIZE+FT_NONCE_SIZE)); \ +} + +/* Macros relative to R1KH Table. */ +#define FT_R1NAME_HASH(_Data) (_Data[0] ^ _Data[1] ^ _Data[2] ^_Data[3] \ + ^ _Data[4] ^ _Data[5] ^_Data[6] ^ _Data[7] \ + ^ _Data[8] ^_Data[9] ^ _Data[10] ^ _Data[11] \ + ^_Data[12] ^ _Data[13] ^ _Data[14] ^_Data[15]) +#define FT_R1KH_HASH_INDEX(_Data) (FT_R1NAME_HASH(_Data) \ + % (FT_R1KH_ENTRY_HASH_TABLE_SIZE)) + +typedef struct GNU_PACKED _FT_KDP_PMK_KEY_INFO { + + UCHAR R0KHID[FT_KDP_R0KHID_MAX_SIZE]; + UCHAR R0KHIDLen; + UCHAR PMKR0Name[FT_KDP_WPA_NAME_MAX_SIZE]; /* an ID that names the PMK-R0 */ + + UCHAR R1KHID[FT_KDP_R1KHID_MAX_SIZE]; + UCHAR S1KHID[FT_KDP_S1KHID_MAX_SIZE]; + + /* reserved field */ + UCHAR RSV[4]; + +} FT_KDP_PMK_KEY_INFO; + +#ifdef IAPP_SUPPORT +typedef struct GNU_PACKED _RT_SIGNAL_STRUC { + + /* IEEE80211R_SUPPORT */ + VOID *pNext; /* point to next signal */ + + UINT16 Sequence; + UCHAR MacAddr[ETH_ALEN]; + UCHAR CurrAPAddr[ETH_ALEN]; + /* YF_FT */ +#ifdef R1KH_HARD_RETRY + /* sw retry counts */ +#define FT_R1KH_CACHE_MISS_THRESHOLD 1 + /* hard retry counts */ +#define FT_R1KH_CACHE_MISS_HARD_RETRY_THRESHOLD 1 +#else /* R1KH_HARD_RETRY */ +#define FT_R1KH_CACHE_MISS_THRESHOLD 7 +#endif /* !R1KH_HARD_RETRY */ +#define FT_KDP_SIG_NOTHING 0x00 /* no signal */ +#define FT_KDP_SIG_IAPP_ASSOCIATION 0x01 /* a station has associated */ +#define FT_KDP_SIG_IAPP_REASSOCIATION 0x02 /* a station has re-associated */ +#define FT_KDP_SIG_TERMINATE 0x03 /* terminate the daemon */ + +#define FT_KDP_SIG_FT_ASSOCIATION 0x50 /* a FT station has associated */ +#define FT_KDP_SIG_FT_REASSOCIATION 0x51 /* a FT station has re-associated */ +#define FT_KDP_SIG_KEY_TIMEOUT 0x52 /* PMK-R1 KEY Timeout */ +#define FT_KDP_SIG_KEY_REQ 0x53 /* request PMK-R1 KEY from R0KH */ +#define FT_KDP_SIG_ACTION 0x54 /* forward FT Action frame to DS */ + +#define FT_KDP_SIG_AP_INFO_REQ 0x70 /* request neighbor AP info. */ +#define FT_KDP_SIG_AP_INFO_RSP 0x71 /* response my AP info. */ + +/* FT KDP internal use */ +#define FT_KDP_SIG_KEY_REQ_AUTO 0xA0 /* request PMK-R1 KEY from R0KH */ +#define FT_KDP_SIG_KEY_RSP_AUTO 0xA1 /* response PMK-R1 KEY to R1KH */ +#define FT_KDP_SIG_INFO_BROADCAST 0xB0 /* broadcast our AP information */ + +#define FT_KSP_SIG_DEBUG_TRACE 0xC0 /* enable debug flag to TRACE */ + UCHAR Sig; + + UCHAR MacAddrSa[ETH_ALEN]; + + /* IEEE80211R_SUPPORT */ + /* the first 6B are FT_KDP_EVT_HEADER */ + /* + For FT_KDP_SIG_NOTHING: nothing + For FT_KDP_SIG_IAPP_ASSOCIATION:nothing + For FT_KDP_SIG_REASSOCIATION: nothing + For FT_KDP_SIG_TERMINATE: nothing + For FT_KDP_SIG_FT_ASSOCIATION: nothing + FT_KDP_SIG_FT_REASSOCIATION: nothing + For FT_KDP_SIG_KEY_TIMEOUT: it is + For FT_KDP_SIG_KEY_REQ_AUTO: it is FT_KDP_EVT_KEY_REQ + For FT_KDP_SIG_KEY_RSP_AUTO: it is FT_KDP_SIG_KEY_RSP + */ + UCHAR Reserved[3]; /* let address of Content[] 4B align */ + UCHAR Content[1024]; /* signal content */ + +/* 1024 means size of Content[] */ +#define RT_SIGNAL_STRUC_HDR_SIZE (sizeof(RT_SIGNAL_STRUC)-1024) +} RT_SIGNAL_STRUC, *PRT_SIGNAL_STRUC; + +/* definition of signal */ +#define SIG_NONE 0 /* same as FT_KDP_SIG_NOTHING */ +#define SIG_ASSOCIATION 1 /* same as FT_KDP_SIG_ASSOCIATION */ +#define SIG_REASSOCIATION 2 /* same as FT_KDP_SIG_REASSOCIATION */ +#endif /* IAPP_SUPPORT */ + + +/* event */ +#define FT_KDP_EVENT_INFORM(__pAd, __ApIdx, __EventId, __pEvent, __EventLen, __CB) \ + FT_KDP_EventInform(__pAd, __ApIdx, __EventId, (VOID *)__pEvent, __EventLen, 0, __CB) + +/* ----- KDP Linked List ----- */ +#define FT_KDP_EVT_LIST_INSERT_TAIL(__pAd, __pList, __pEntry) \ + { \ + RTMP_SEM_LOCK(&(__pAd)->ApCfg.FtTab.FT_KdpLock); \ + insertTailList((__pList), (RT_LIST_ENTRY *)(__pEntry)); \ + RTMP_SEM_UNLOCK(&(__pAd)->ApCfg.FtTab.FT_KdpLock); \ + } + +#define FT_KDP_EVT_LIST_REMOVE_HEAD(__pAd, __pList, __pEntry) \ + { \ + RTMP_SEM_LOCK(&(__pAd)->ApCfg.FtTab.FT_KdpLock); \ + __pEntry = (FT_KDP_SIGNAL *)removeHeadList((__pList)); \ + RTMP_SEM_UNLOCK(&(__pAd)->ApCfg.FtTab.FT_KdpLock); \ + } + +#define FT_KDP_EVT_LIST_SIZE_GET(__pAd, __pList, __Size) \ + { \ + RTMP_SEM_LOCK(&(__pAd)->ApCfg.FtTab.FT_KdpLock); \ + __Size = getListSize((__pList)); \ + RTMP_SEM_UNLOCK(&(__pAd)->ApCfg.FtTab.FT_KdpLock); \ + } + +#define FT_KDP_EVT_LIST_EMPTY(__pAd, __pList) \ + { \ + FT_KDP_SIGNAL *__pEntry; \ + RTMP_SEM_LOCK(&(__pAd)->ApCfg.FtTab.FT_KdpLock); \ + __pEntry = (FT_KDP_SIGNAL *)removeHeadList((__pList)); \ + while(__pEntry != NULL) \ + { \ + FT_MEM_FREE(__pAd, __pEntry); \ + __pEntry = (FT_KDP_SIGNAL *)removeHeadList((__pList)); \ + } \ + RTMP_SEM_UNLOCK(&(__pAd)->ApCfg.FtTab.FT_KdpLock); \ + } + +/* general */ +#define FT_KDP_CB ((FT_KDP_CTRL_BLOCK *)pAd->ApCfg.FtTab.pFT_KDP_Ctrl_BK) + +typedef struct GNU_PACKED _FT_KDP_EVT_HEADER +{ + UINT32 EventLen; + UINT32 PeerIpAddr; /* used in daemon, open TCP/IP socket to the IP */ +} FT_KDP_EVT_HEADER; + +typedef struct GNU_PACKED _FT_KDP_EVT_ASSOC +{ + /* same as IEEE802.11f IAPP */ + UINT16 SeqNum; + UCHAR MacAddr[ETH_ALEN]; +} FT_KDP_EVT_ASSOC; + +typedef struct GNU_PACKED _FT_KDP_EVT_REASSOC +{ + UINT16 SeqNum; + UCHAR MacAddr[ETH_ALEN]; + UCHAR OldApMacAddr[ETH_ALEN]; +} FT_KDP_EVT_REASSOC; + +typedef struct GNU_PACKED _FT_KDP_EVT_KEY_ELM +{ + /* must be 65535, Proprietary Information */ +#define FT_KDP_ELM_ID_PRI 65535 + UINT16 ElmId; + +#define FT_KDP_ELM_PRI_LEN (sizeof(FT_KDP_EVT_KEY_ELM)-4) + UINT16 ElmLen; + + /* must be 0x00 0x0E 0x2E, RALINK */ +#define FT_KDP_ELM_PRI_OUI_0 0x00 +#define FT_KDP_ELM_PRI_OUI_1 0x0E +#define FT_KDP_ELM_PRI_OUI_2 0x2E +#define FT_KDP_ELM_PRI_OUI_SIZE 3 + UCHAR OUI[3]; + + /* station MAC */ + UCHAR MacAddr[ETH_ALEN]; + UCHAR RSV[3]; + + /* used in request */ + FT_KDP_PMK_KEY_INFO KeyInfo; + + /* used in response */ + UCHAR PMKR1Name[FT_KDP_WPA_NAME_MAX_SIZE]; /* an ID that names the PMK-R1 */ + UCHAR PMKR1[FT_KDP_PMKR1_MAX_SIZE]; /* PMK R1 Key */ + UCHAR R0KH_MAC[ETH_ALEN]; /* MAC of R0KH */ + + /* + During a Fast BSS Transition a non-AP STA shall negotiate the same + pairwise cipher suite with Target APs as was negotiated in the FT + Initial Mobility Domain association. The target AP shall verify + that the same pairwise cipher suite selector is used, using the + pairwise cipher suite selector value in the PMK-R1 SA received from + the R0KH. + */ + UCHAR PairwisChipher[4]; + UCHAR AkmSuite[4]; + + UINT32 KeyLifeTime; + UINT32 ReassocDeadline; +} FT_KDP_EVT_KEY_ELM; + +typedef struct _FT_KDP_EVT_ACTION +{ + UCHAR RequestType; + UCHAR MacDa[ETH_ALEN]; + UCHAR MacSa[ETH_ALEN]; + UCHAR MacAp[ETH_ALEN]; +} FT_KDP_EVT_ACTION; + +/* global function prototype for non-11r modules */ +/* +======================================================================== +Routine Description: + Initialize FT KDP Module. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID FT_KDP_Init( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + Release FT KDP Module. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID FT_KDP_Release( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + Get a event. + +Arguments: + pAd - WLAN control block pointer + **pFtKdp - the queued event; if NULL, no event is queued. + +Return Value: + None + +Note: + Used in IOCTL from FT KDP daemon. +======================================================================== +*/ +VOID FT_KDP_EventGet( + IN PRTMP_ADAPTER pAd, + OUT FT_KDP_SIGNAL **pFtKdp); + +/* +======================================================================== +Routine Description: + Inform us a event occurs. + +Arguments: + pAd - WLAN control block pointer + ApIdx - MBSS ID + EventId - which event, such as FT_KDP_SIG_FT_ASSOCIATION + *pEvent - event body + EventLen - event body length + PeerIP - peer IP address + pCB - for special use (such as FT_KDP_SIG_ACTION) + +Return Value: + None + +Note: + EventId *pEvent + -------------------------------------------------------------------- + FT_KDP_SIG_FT_ASSOCIATION FT_KDP_EVT_ASSOC + FT_KDP_SIG_FT_REASSOCIATION FT_KDP_EVT_REASSOC + FT_KDP_SIG_KEY_TIMEOUT yet implement + FT_KDP_SIG_KEY_REQ FT_KDP_EVT_KEY_ELM + FT_KDP_SIG_ACTION WLAN Frame Body (Start from Category field) + pCB == FT_KDP_EVT_ACTION + +======================================================================== +*/ +VOID FT_KDP_EventInform( + IN PRTMP_ADAPTER pAd, + IN UINT32 ApIdx, + IN UCHAR EventId, + IN VOID *pEvent, + IN UINT16 EventLen, + IN UINT32 PeerIP, + IN VOID *pCB); + +/* +======================================================================== +Routine Description: + Inform us a AP request the key. + +Arguments: + pAd - WLAN control block pointer + PeerIP - the IP of R0KH + *pNonce - the nonce for key request + *pEvtKeyReq - information for key request + +Return Value: + TRUE - request ok + FALSE - can not find the IP of R0KH + +Note: + If PeerIP == 0, search its IP from our information record. +======================================================================== +*/ +BOOLEAN FT_KDP_KeyRequestToUs( + IN PRTMP_ADAPTER pAd, + IN UINT32 PeerIP, + IN UCHAR *pNonce, + IN FT_KDP_EVT_KEY_ELM *pEvtKeyReq); + +/* +======================================================================== +Routine Description: + Inform us a AP response the key. + +Arguments: + pAd - WLAN control block pointer + *pInfo - key information + InfoLen - information length + +Return Value: + None + +Note: + pInfo format is PeerIP (4B) + Nonce (8B) + FT_KDP_EVT_KEY_ELM structure +======================================================================== +*/ +VOID FT_KDP_KeyResponseToUs( + IN PRTMP_ADAPTER pAd, + IN UINT8 *pInfo, + IN INT32 InfoLen); + +/* +======================================================================== +Routine Description: + Inform us a FT station joins the BSS domain. + +Arguments: + pAd - WLAN control block pointer + *pInfo - station information + InfoLen - information length + +Return Value: + None + +Note: + pInfo format is PeerIP (4B) + Station MAC (6B) +======================================================================== +*/ +VOID FT_KDP_StationInform( + IN PRTMP_ADAPTER pAd, + IN UINT8 *pInfo, + IN INT32 InfoLen); + +/* +======================================================================== +Routine Description: + Set the encryption/decryption key. + +Arguments: + pAd - WLAN control block pointer + *pKey - the key + KeyLen - the key length + +Return Value: + None + +Note: + Key length can be 8B ~ 64B. +======================================================================== +*/ +VOID FT_KDP_CryptKeySet( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pKey, + IN INT32 KeyLen); + +/* +======================================================================== +Routine Description: + Encrypt the data. + +Arguments: + pAd - WLAN control block pointer + *pData - data buffer + *pDataLen - data buffer length + +Return Value: + None + +Note: +======================================================================== +*/ +VOID FT_KDP_DataEncrypt( + IN PRTMP_ADAPTER pAd, + INOUT UCHAR *pData, + IN UINT32 *pDataLen); + +/* +======================================================================== +Routine Description: + Decrypt the data. + +Arguments: + pAd - WLAN control block pointer + *pData - data buffer + *pDataLen - data buffer length + +Return Value: + None + +Note: +======================================================================== +*/ +VOID FT_KDP_DataDecrypt( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pData, + IN UINT32 *pDataLen); + +/* +======================================================================== +Routine Description: + Broadcast our AP information. + +Arguments: + SystemSpecific1 - no use + FunctionContext - WLAN control block pointer + SystemSpecific2 - no use + SystemSpecific3 - no use + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID FT_KDP_InfoBroadcast( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +#ifdef FT_KDP_FUNC_INFO_BROADCAST +/* +======================================================================== +Routine Description: + Receive a neighbor report from another AP. + +Arguments: + pAd - WLAN control block pointer + *pInfo - report information + InfoLen - information length + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID TYPE_FUNC FT_KDP_NeighborReportHandle( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen); +#endif /* FT_KDP_FUNC_INFO_BROADCAST */ + +/* +======================================================================== +Routine Description: + Receive a neighbor request from another AP. + +Arguments: + pAd - WLAN control block pointer + *pInfo - report information + InfoLen - information length + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID FT_KDP_NeighborRequestHandle( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen); + +/* +======================================================================== +Routine Description: + Receive a neighbor response from another AP. + +Arguments: + pAd - WLAN control block pointer + *pInfo - report information + InfoLen - information length + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID FT_KDP_NeighborResponseHandle( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen); + +/* +======================================================================== +Routine Description: + Handle a RRB frame from DS. + +Arguments: + pAd - WLAN control block pointer + *pInfo - report information + InfoLen - information length + +Return Value: + NONE + +Note: +======================================================================== +*/ +VOID FT_RRB_ActionHandle( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen); + +BOOLEAN FT_QueryKeyInfoForKDP( + IN PRTMP_ADAPTER pAd, + IN UINT32 ApIdx, + OUT FT_KDP_EVT_KEY_ELM *pEvtKeyReq); + +#endif /* CONFIG_AP_SUPPORT */ + +/* +======================================================================== +Routine Description: + Initialize FT RIC Module. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID FT_RIC_Init( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + Release FT RIC Module. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: +======================================================================== +*/ +VOID FT_RIC_Release( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + IO control handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + pArgvIn - the data flow information + +Return Value: + None + +Note: + All test commands are listed as follows: + iwpriv ra0 set ft=[cmd id]_[arg1]_[arg2]_......_[argn] + [cmd id] = xx, such as 00, 01, 02, 03, ... +======================================================================== +*/ +INT FT_Ioctl(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +/* +======================================================================== +Routine Description: + FT insert MDIE to packet frame for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +VOID FT_InsertMdIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUINT8 pMdId, + IN FT_CAP_AND_POLICY FtCapPlc); + +/* +======================================================================== +Routine Description: + FT configuration handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ + VOID FT_CfgInitial( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + FT function initialization for IEEE802.11r. + FT_Init'll allocate tables, control blocks that FT needed. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +VOID FT_Init( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + FT function release for IEEE802.11r. + Free all tables, control blocks which FT_Init allocated. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +VOID FT_Release( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + FT Peer Auth-Req handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +USHORT FT_AuthReqHandler( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pFtInfo, + OUT PFT_INFO pFtInfoBuf); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + None + +Note: + +======================================================================== +*/ +VOID FT_EnqueueAuthReply( + IN PRTMP_ADAPTER pAd, + IN PHEADER_802_11 pRcvHdr, + IN USHORT Alg, + IN USHORT Seq, + IN USHORT StatusCode, + IN PFT_MDIE_INFO pMdIeInfo, + IN PFT_FTIE_INFO pFtIeInfo, + IN PFT_RIC_INFO pRicInfo, + IN PUCHAR pRsnIe, + IN UCHAR RsnIeLen); + +/* +======================================================================== +Routine Description: + FT Peer Auth-Confirm handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +USHORT FT_AuthConfirmHandler( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pFtInfo, + OUT PFT_INFO pFtInfoBuf); + +/* +======================================================================== +Routine Description: + FT Peer Association Request handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +USHORT FT_AssocReqHandler( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN isReassoc, + IN PFT_CFG pFtCfg, + IN PMAC_TABLE_ENTRY pEntry, + IN PFT_INFO pPeer_FtInfo, + OUT PFT_INFO pFtInfoBuf); + +/* +======================================================================== +Routine Description: + FT Peer Auth-Confirm handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +VOID FT_KDP_KeyResponse( + IN PRTMP_ADAPTER pAd, + IN UCHAR *pInfo, + IN INT32 InfoLen); + +/* +======================================================================== +Routine Description: + FT Peer Resource Request handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +UINT32 FT_RIC_ResourceRequestHandle( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pCdb, + IN UCHAR *pBufReq, + IN UINT32 ReqLen, + OUT UCHAR *pBufRsp, + OUT UINT32 *pRspLen); + + +/* +======================================================================== +Routine Description: + FT Peer Resource Request handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +UINT32 BA_ResourceAllocate( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pMacEntry, + IN UCHAR *pBufRscReq, + OUT UCHAR *pBufRscRsp, + OUT ULONG *pBufRspLen); + +/* +======================================================================== +Routine Description: + FT Peer Auth-Confirm handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +VOID FT_InsertFTIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Length, + IN FT_MIC_CTR_FIELD MICCtr, + IN PUINT8 pMic, + IN PUINT8 pANonce, + IN PUINT8 pSNonce); + +/* +======================================================================== +Routine Description: + FT Peer Auth-Confirm handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +VOID FT_FTIE_InsertKhIdSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN FT_SUB_ELEMENT_ID SubId, + IN PUINT8 pKhId, + IN UINT8 KhIdLen); + +/* +======================================================================== +Routine Description: + FT Peer Auth-Confirm handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +VOID FT_FTIE_InsertGTKSubIE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUINT8 pGtkSubIe, + IN UINT8 GtkSubIe_len); + +/* +======================================================================== +Routine Description: + FT Peer Auth-Confirm handler for IEEE802.11r. + +Arguments: + pAd - WLAN control block pointer + +Return Value: + None + +Note: + +======================================================================== +*/ +VOID FT_InsertTimeoutIntervalIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN FT_TIMEOUT_INTERVAL_TYPE Type, + IN UINT32 TimeOutValue); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_R1khEntryTabInit( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +INT FT_R1khEntryInsert( + IN PRTMP_ADAPTER pAd, + IN PUINT8 pPmkR0Name, + IN PUINT8 pPmkR1Name, + IN PUINT8 pPmkR1Key, + IN PUINT8 pPairwisChipher, + IN PUINT8 pAkmSuite, + IN UINT32 KeyLifeTime, + IN UINT32 RassocDeadline, + IN PUINT8 pR0khId, + IN UINT8 R0khIdLen, + IN PUINT8 pStaMac); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_R1khEntryDelete( + IN PRTMP_ADAPTER pAd, + IN PFT_R1HK_ENTRY pEntry); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_R1khEntryTabDestroy( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +PFT_R1HK_ENTRY FT_R1khEntryTabLookup( + IN PRTMP_ADAPTER pAd, + IN PUINT8 pPMKR1Name); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_FillMdIeInfo( + PEID_STRUCT eid_ptr, + PFT_MDIE_INFO pMdIeInfo); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_FillFtIeInfo( + PEID_STRUCT eid_ptr, + PFT_FTIE_INFO pFtIeInfo); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_FtAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_RrbHandler( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pPktSrc, + IN INT32 PktLen); + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID FT_R1KHInfoMaintenance( + IN PRTMP_ADAPTER pAd); + +/* +======================================================================== +Routine Description: + Display all R0KH information. + +Arguments: + pAd - WLAN control block pointer + *pArgv - input parameters + +Return Value: + TRUE + +Note: +======================================================================== +*/ +INT FT_KDP_CMD_R0KH_InfoShow(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +VOID FT_MakeFtActFrame( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 ActType, + IN PUCHAR pStaMac, + IN PUCHAR pTargetApMac, + IN UINT16 StatusCode, + IN PFT_INFO pFtInfo); + +VOID FT_DerivePMKR0( + IN PUINT8 xxkey, + IN INT xxkey_len, + IN PUINT8 ssid, + IN INT ssid_len, + IN PUINT8 mdid, + IN PUINT8 r0khid, + IN INT r0khid_len, + IN PUINT8 s0khid, + OUT PUINT8 pmkr0, + OUT PUINT8 pmkr0_name); + +VOID FT_DerivePMKR1Name( + IN PUINT8 pmkr0_name, + IN PUINT8 r1khid, + IN PUINT8 s1khid, + OUT PUINT8 pmkr1_name); + +VOID FT_DerivePMKR1( + IN PUINT8 pmkr0, + IN PUINT8 pmkr0_name, + IN PUINT8 r1khid, + IN PUINT8 s1khid, + OUT PUINT8 pmkr1, + OUT PUINT8 pmkr1_name); + +VOID FT_DerivePTK( + IN PUINT8 pmkr1, + IN PUINT8 pmkr1_name, + IN PUINT8 a_nonce, + IN PUINT8 s_nonce, + IN PUINT8 bssid, + IN PUINT8 sta_mac, + IN UINT key_len, + OUT PUINT8 ptk, + OUT PUINT8 ptk_name); + +VOID FT_CalculateMIC( + IN PUINT8 sta_addr, + IN PUINT8 ap_addr, + IN PUINT8 kck, + IN UINT8 seq, + IN PUINT8 rsnie, + IN UINT8 rsnie_len, + IN PUINT8 mdie, + IN UINT8 mdie_len, + IN PUINT8 ftie, + IN UINT8 ftie_len, + IN PUINT8 ric, + IN UINT8 ric_len, + OUT PUINT8 mic); + + +void FT_rtmp_read_parameters_from_file( + IN PRTMP_ADAPTER pAd, + RTMP_STRING *tmpbuf, + RTMP_STRING *pBuffer); + +INT Set_FT_Enable(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_FT_Mdid(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_FT_R0khid(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_FT_RIC(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_FT_OTD(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Show_FTConfig_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#endif /* __FT_H */ +#endif /* DOT11R_FT_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ft_cmm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ft_cmm.h new file mode 100644 index 000000000..c0bd0011b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ft_cmm.h @@ -0,0 +1,249 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + + Abstract: + + Define all structures, data types that rtmp.h needed in this file. Don't + put any sturctures and functions definition which refer to RTMP_ADAPTER + Here. + + +***************************************************************************/ + +#ifdef DOT11R_FT_SUPPORT + + +#ifndef __FT_CMM_H__ +#define __FT_CMM_H__ + +#include "dot11r_ft.h" +#include "dot11i_wpa.h" + + +/* ========================================================================== */ +/* Definition */ +#define IS_FT_RSN_STA(_pEntry) \ + ((_pEntry) && IS_ENTRY_CLIENT(_pEntry) && (_pEntry->MdIeInfo.Len != 0) && (_pEntry->RSNIE_Len > 0)) + +#define FT_SET_MDID(__D, __S) \ + NdisMoveMemory((PUCHAR)(__D), (PUCHAR)(__S), FT_MDID_LEN) + +#define FT_MDID_EQU(__D, __S) (memcmp((__D), (__S), FT_MDID_LEN) == 0) + + +/* ----- General ----- */ +#define FT_KDP_FUNC_SOCK_COMM /* used socket to communicate with driver */ +#define FT_KDP_FUNC_R0KH_IP_RECORD /* used to keep IP of any R0KH */ +/*#define FT_KDP_FUNC_INFO_BROADCAST broadcast my AP information periodically */ +#define FT_KDP_TEST + +#define FT_KDP_RALINK_PASSPHRASE "Ralink" +#define FT_KDP_KEY_DEFAULT "12345678" +#define FT_KDP_KEY_ENCRYPTION_EXTEND 8 /* 8B for AES encryption extend size */ +#define FT_DEFAULT_MDID "RT" + +#define FT_REASSOC_DEADLINE 20 + +#define FT_KDP_INFO_BC_PERIOD_TIME 1000 /* 1s */ + +#define IAPP_ETH_PRO 0xEEEE + +/* key information */ +#define FT_IP_ADDRESS_SIZE 4 +#define FT_NONCE_SIZE 8 + +#define FT_KDP_WPA_NAME_MAX_SIZE 16 +#define FT_KDP_R0KHID_MAX_SIZE 48 +#define FT_KDP_R1KHID_MAX_SIZE 6 +#define FT_KDP_S1KHID_MAX_SIZE 6 +#define FT_KDP_PMKR1_MAX_SIZE 32 /* 256-bit key */ + +#define FT_R1KH_ENTRY_TABLE_SIZE 64 +#define FT_R1KH_ENTRY_HASH_TABLE_SIZE FT_R1KH_ENTRY_TABLE_SIZE + +/* ----- FT KDP ----- */ +#define FT_KDP_EVENT_MAX 10 /* queue max 10 events */ + +/* ----- FT RIC ----- */ +#define MAX_RICIES_LEN 255 + + +/* ========================================================================== */ +/* FT user configuration. */ + +/* ethernet header */ +typedef struct _FT_DRV_ETH_HEADER { + + UCHAR DA[ETH_ALEN]; + UCHAR SA[ETH_ALEN]; + UINT16 Len; + +} GNU_PACKED FT_DRV_ETH_HEADER; + +/* R0KH information record */ +typedef struct _FT_KDP_R0KH_INFO { + + struct _FT_KDP_R0KH_INFO *pNext; + + UCHAR R0KHID[FT_KDP_R0KHID_MAX_SIZE]; + UCHAR MAC[ETH_ALEN]; + UINT32 IP; + + ULONG TimeUpdate; + +} FT_KDP_R0KH_INFO; + +/* FT KDP Control Block */ +typedef struct _FT_KDP_CTRL_BLOCK { + + /* used to record all known R0KH information in the DS */ +#ifdef FT_KDP_FUNC_R0KH_IP_RECORD +#define FT_KDP_R0KH_INFO_MAX_SIZE 256 + FT_KDP_R0KH_INFO *R0KH_InfoHead; + FT_KDP_R0KH_INFO *R0KH_InfoTail; + UINT32 R0KH_Size; +#endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ + +#ifndef FT_KDP_FUNC_SOCK_COMM + /* if the signal context is got from FT KDP daemon */ + struct _LIST_HEADER EventList; +#endif /* FT_KDP_SOCK_COMM */ + +#ifdef FT_KDP_FUNC_INFO_BROADCAST + RALINK_TIMER_STRUCT TimerReport; +#endif /* FT_KDP_FUNC_INFO_BROADCAST */ + + /* used to encrypt/decrypt the DS packet */ + UCHAR CryptKey[100]; +} FT_KDP_CTRL_BLOCK; + +/* FT RIC Control Block */ + +typedef struct _FT_CAP_CFG +{ + UINT8 FtOverDs:1; /* 1: Enable FT over the DS. */ + UINT8 RsrReqCap:1; /* 1: Enable FT resource request. */ + UINT8 Dot11rFtEnable:1; /* 1: FT enable , 0: FT disable. */ + UINT8 :5; /* reserve. */ +} FT_CAP_CFG, *PFT_CAP_CFG; + +typedef struct GNU_PACKED _FT_CFG +{ + UINT8 FtMdId[FT_MDID_LEN]; /* Mobility domain ID of Fast Bss. */ + UINT32 AssocDeadLine; /* 100ms */ + UINT8 FtR0khId[FT_ROKH_ID_LEN + 1]; /* Lenght of ROKHID can be 1 to 48 chars. */ + UINT8 FtR0khIdLen; + FT_CAP_CFG FtCapFlag; /* FT capability Configuration. */ +} FT_CFG, *PFT_CFG; + +typedef struct __FT_R1KH_ENTRY +{ + struct __FT_R1KH_ENTRY *pNext; + UINT32 KeyLifeTime; + UINT32 RassocDeadline; + UINT8 PmkR0Name[16]; + UINT8 PmkR1Name[16]; + UINT8 PmkR1Key[32]; + UINT8 PairwisChipher[4]; + UINT8 AkmSuite[4]; + UINT8 R0khId[FT_ROKH_ID_LEN + 1]; + UINT8 R0khIdLen; + UINT8 StaMac[6]; +} FT_R1HK_ENTRY, *PFT_R1HK_ENTRY; + +typedef struct __FT_TAB +{ + /* KDP. */ + PVOID pFT_KDP_Ctrl_BK; + NDIS_SPIN_LOCK FT_KdpLock; + BOOLEAN FlgIsFtKdpInit; + + /* R1KH. */ + LIST_HEADER FT_R1khEntryTab[FT_R1KH_ENTRY_HASH_TABLE_SIZE]; + NDIS_SPIN_LOCK FT_R1khEntryTabLock; + ULONG FT_R1khEntryTabSize; + + BOOLEAN FT_R1khEntryTabReady; + #ifdef FT_R1KH_KEEP + /* + Keep the R1KH catch table on Radio Off state for MBO-4.2.6(E) + case to meet the R1KH miss case. + */ + BOOLEAN FT_RadioOff; +#endif /* FT_R1KH_KEEP */ +} FT_TAB, *PFT_TAB; + +typedef struct __FT_MDIE_INFO +{ + INT Len; + UINT8 MdId[FT_MDID_LEN]; + FT_CAP_AND_POLICY FtCapPlc; + + PVOID pMdIe; +} FT_MDIE_INFO, *PFT_MDIE_INFO; + +typedef struct __FT_FTIE_INFO +{ + INT Len; + FT_MIC_CTR_FIELD MICCtr; + UINT8 MIC[16]; + UINT8 ANonce[32]; + UINT8 SNonce[32]; + UINT8 R0khIdLen; + UINT8 R0khId[FT_ROKH_ID_LEN + 1]; + UINT8 R1khIdLen; + UINT8 R1khId[FT_R1KH_ID_LEN + 1]; + UINT8 GtkLen; + UINT8 GtkSubIE[64]; + + PVOID pFtIe; +} FT_FTIE_INFO, *PFT_FTIE_INFO; + +typedef struct __FT_RIC_INFO +{ + INT Len; + VOID *pRicInfo; + UINT8 RicIEs[MAX_RICIES_LEN]; + UINT8 RicIEsLen; +} FT_RIC_INFO, *PFT_RIC_INFO; + +typedef struct __FT_INFO +{ + FT_MDIE_INFO MdIeInfo; + FT_FTIE_INFO FtIeInfo; + FT_RIC_INFO RicInfo; + UCHAR RSNIE_Len; + UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; +} FT_INFO, *PFT_INFO; + +typedef struct __FT_MIC_CONTENT +{ + PUINT8 rsnie_ptr; + UINT rsnie_len; + PUINT8 mdie_ptr; + UINT mdie_len; + PUINT8 ftie_ptr; + UINT ftie_len; + PUINT8 ric_ptr; + UINT ric_len; +} FT_MIC_CONTENT, *PFT_MIC_CONTENT; + + + +#endif /* __FT_CMM_H__ */ +#endif /* DOT11R_FT_SUPPORT */ + +/* End of ft_cmm.h */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/gas.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/gas.h new file mode 100644 index 000000000..aa8139131 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/gas.h @@ -0,0 +1,201 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2011, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + gas.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#ifndef __GAS_H__ +#define __GAS_H__ + +#include "link_list.h" + +#define GAS_MACHINE_BASE 0 + +/* gas states */ +enum GAS_STATE { + WAIT_GAS_REQ, + WAIT_GAS_RSP, + WAIT_PEER_GAS_REQ, + WAIT_PEER_GAS_RSP, + WAIT_GAS_CB_REQ, + WAIT_GAS_CB_RSP, + GAS_UNKNOWN, + MAX_GAS_STATE, +}; + +/* gas events */ +enum GAS_EVENT { + GAS_REQ, + GAS_RSP, + GAS_RSP_MORE, + PEER_GAS_REQ, + PEER_GAS_RSP, + PEER_GAS_RSP_MORE, + GAS_CB_REQ, + GAS_CB_REQ_MORE, + GAS_CB_RSP, + GAS_CB_RSP_MORE, + MAX_GAS_MSG, +}; + +#define GAS_FUNC_SIZE (MAX_GAS_STATE * MAX_GAS_MSG) + +typedef struct _GAS_QUERY_RSP_FRAGMENT +{ + DL_LIST List; + UCHAR GASRspFragID; + UINT16 FragQueryRspLen; + UCHAR *FragQueryRsp; +}GAS_QUERY_RSP_FRAGMENT, *PGAS_QUERY_RSP_FRAGMENT; + +typedef struct _GAS_PEER_ENTRY { + DL_LIST List; + enum GAS_STATE CurrentState; + UCHAR ControlIndex; + UCHAR PeerMACAddr[MAC_ADDR_LEN]; + UCHAR DialogToken; + UCHAR AdvertisementProID; + void *Priv; +#ifdef CONFIG_AP_SUPPORT + RALINK_TIMER_STRUCT PostReplyTimer; + BOOLEAN PostReplyTimerRunning; + RALINK_TIMER_STRUCT GASRspBufferingTimer; + BOOLEAN GASRspBufferingTimerRunning; +#endif /* CONFIG_AP_SUPPORT */ + + UCHAR GASRspFragNum; + UCHAR CurrentGASFragNum; + UINT32 AllocResource; + UINT32 FreeResource; + UCHAR QueryNum; + DL_LIST GASQueryRspFragList; +}GAS_PEER_ENTRY, *PGAS_PEER_ENTRY; + +typedef struct _GAS_CTRL { + DL_LIST GASPeerList; + NDIS_SPIN_LOCK GASPeerListLock; + UINT8 ExternalANQPServerTest; + UINT32 cb_delay; /* Come Back Delay */ + UINT32 MMPDUSize; + BOOLEAN b11U_enable; + UINT32 InterWorkingIELen; + UINT32 AdvertisementProtoIELen; + PUCHAR InterWorkingIE; + PUCHAR AdvertisementProtoIE; +} GAS_CTRL, *PGAS_CTRL; + +/* + * gas events data + * GASComebackDelay : unit(TU) + */ +typedef struct GNU_PACKED _GAS_EVENT_DATA { + UCHAR ControlIndex; + UCHAR PeerMACAddr[MAC_ADDR_LEN]; + UINT16 EventType; + union{ + +#ifdef CONFIG_AP_SUPPORT + struct { + UCHAR DialogToken; + UINT16 StatusCode; + UINT16 GASComebackDelay; + UCHAR AdvertisementProID; + UINT16 QueryRspLen; + UCHAR QueryRsp[0]; + } GNU_PACKED GAS_RSP_DATA; + struct { + UCHAR DialogToken; + UINT16 StatusCode; + UINT16 GASComebackDelay; + UCHAR AdvertisementProID; + } GNU_PACKED GAS_RSP_MORE_DATA; + struct { + UCHAR DialogToken; + UCHAR AdvertisementProID; + UINT16 QueryReqLen; + UCHAR QueryReq[0]; + } GNU_PACKED PEER_GAS_REQ_DATA; + struct { + UCHAR DialogToken; + UCHAR AdvertisementProID; + UINT16 StatusCode; + } GNU_PACKED GAS_CB_REQ_DATA; + struct { + UCHAR DialogToken; + UCHAR AdvertisementProID; + UINT16 StatusCode; + } GNU_PACKED GAS_CB_REQ_MORE_DATA; +#endif /* CONFIG_AP_SUPPORT */ + }u; +}GAS_EVENT_DATA, *PGAS_EVENT_DATA; + +VOID GASStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +enum GAS_STATE GASPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID GASSetPeerCurrentState( + IN PRTMP_ADAPTER pAd, + //IN MLME_QUEUE_ELEM *Elem, + PGAS_EVENT_DATA Event, + IN enum GAS_STATE State); + +VOID SendGASRsp( + IN PRTMP_ADAPTER pAd, + GAS_EVENT_DATA *Event); + +VOID GASCtrlExit(IN PRTMP_ADAPTER pAd); + + +#ifdef CONFIG_AP_SUPPORT +DECLARE_TIMER_FUNCTION(PostReplyTimeout); +DECLARE_TIMER_FUNCTION(GASRspBufferingTimeout); + +void SendAnqpReqEvent(PNET_DEV net_dev, const char *peer_mac_addr, + const char *anqp_req, UINT16 anqp_req_len); + +VOID ReceiveGASInitReq( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ReceiveGASCBReq( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif /* CONFIG_AP_SUPPORT */ + +#if defined(WAPP_SUPPORT) && defined(DOT11U_INTERWORKING) +INT Send_ANQP_Rsp( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *PeerMACAddr, + IN RTMP_STRING *ANQPRsp, + IN UINT32 ANQPRspLen); +#endif + +BOOLEAN GasEnable( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif /* __GAS_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/hotspot.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/hotspot.h new file mode 100644 index 000000000..dfa865bcb --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/hotspot.h @@ -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-2011, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + hotspot.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#ifndef __HOTSPOT_H__ +#define __HOTSPOT_H__ + +#ifndef CONFIG_DOT11V_WNM +#error "For HOTSPOT2.0 feature, you must define the compile flag -DCONFIG_DOT11V_WNM" +#endif + +#ifndef DOT11U_INTERWORKING +#error "For HOTSPOT2.0 feature, you must define the compile flag -DCONFIG_DOT11U_INTERWORKING" +#endif + +#include "rtmp.h" + +#define HSCTRL_MACHINE_BASE 0 + +enum HSCTRL_STATE { + WAIT_HSCTRL_OFF, + WAIT_HSCTRL_ON, + HSCTRL_IDLE, + MAX_HSCTRL_STATE, +}; + +enum HSCTRL_EVENT { + HSCTRL_OFF, + HSCTRL_ON, + MAX_HSCTRL_MSG, +}; + +typedef struct GNU_PACKED _HSCTRL_EVENT_DATA { + UCHAR ControlIndex; + UCHAR EventTrigger; + UCHAR EventType; +} HSCTRL_EVENT_DATA, *PHSCTRL_EVENT_DATA; + +typedef struct _HOTSPOT_CTRL { + UINT32 HSIndicationIELen; + UINT32 P2PIELen; + /*UINT32 InterWorkingIELen; + UINT32 AdvertisementProtoIELen; + */ + UINT32 QosMapSetIELen; + UINT32 RoamingConsortiumIELen; + /*PUCHAR InterWorkingIE; + PUCHAR AdvertisementProtoIE; + */ + PUCHAR QosMapSetIE; + USHORT DscpRange[8]; + USHORT DscpException[21]; + PUCHAR RoamingConsortiumIE; + PUCHAR HSIndicationIE; + PUCHAR P2PIE; + BOOLEAN HSDaemonReady; + BOOLEAN HotSpotEnable; + enum HSCTRL_STATE HSCtrlState; + BOOLEAN IsHessid; + UCHAR Hessid[MAC_ADDR_LEN]; + UINT8 AccessNetWorkType; + BOOLEAN DGAFDisable; + UINT8 L2Filter; + BOOLEAN ICMPv4Deny; + BOOLEAN QosMapEnable; +/* BOOLEAN bNonTX; 0:enable TX, 1:disable TX*/ + BOOLEAN bASANEnable; /* 1:enable ASAN IE, 1:disable ASAN IE*/ + UCHAR QLoadTestEnable; /* for BSS Load IE Test */ + UCHAR QLoadCU; /* for BSS Load IE Test */ + USHORT QLoadStaCnt; /* for BSS Load IE Test */ +} HOTSPOT_CTRL, *PHOTSPOT_CTRL; + +enum { + L2FilterDisable, + L2FilterBuiltIn, + L2FilterExternal, +}; + +/*enum { + PARAM_DGAF_DISABLED, + PARAM_PROXY_ARP, + PARAM_L2_FILTER, + PARAM_ICMPV4_DENY, + PARAM_MMPDU_SIZE, + PARAM_EXTERNAL_ANQP_SERVER_TEST, + PARAM_GAS_COME_BACK_DELAY, + PARAM_WNM_NOTIFICATION, + PARAM_QOSMAP, +}; move to wapp_cmm_type.h +*/ + +BOOLEAN L2FilterInspection( + IN PRTMP_ADAPTER pAd, + IN PHOTSPOT_CTRL pHSCtrl, + IN PUCHAR pData); + +VOID HSCtrlStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +INT Set_STAHotSpot_OnOff( + IN PRTMP_ADAPTER pAd, + IN UINT8 OnOff); + +enum HSCTRL_STATE HSCtrlCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +BOOLEAN HotSpotEnable( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem, + IN INT Type); + +VOID HSCtrlExit( + IN PRTMP_ADAPTER pAd); + +VOID HSCtrlHalt( + IN PRTMP_ADAPTER pAd); + +INT Set_HotSpot_OnOff( + IN PRTMP_ADAPTER pAd, + IN UINT8 OnOff, + IN UINT8 EventTrigger, + IN UINT8 EventType); + +struct _PEER_PROBE_REQ_PARAM; + +BOOLEAN ProbeReqforHSAP( + IN PRTMP_ADAPTER pAd, + IN UCHAR APIndex, + IN struct _PEER_PROBE_REQ_PARAM *ProbeReqParam); + +VOID Clear_Hotspot_All_IE(IN PRTMP_ADAPTER PAd); + +#define isBcastEtherAddr(addr) ((addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5])== 0xff) + +#define GAS_STATE_MESSAGES 0 +#define ACTION_STATE_MESSAGES 1 + +void HotspotOnOffEvent(PNET_DEV net_dev, int onoff); +void HotspotAPReload(PNET_DEV net_dev); + +INT Set_HotSpot_Param( + IN PRTMP_ADAPTER pAd, + UINT32 Param, + UINT32 Value); + +enum { + HS_ON_OFF_BASE, + HS_AP_RELOAD, +}; + +#ifdef CONFIG_AP_SUPPORT +BOOLEAN HSIPv4Check( + IN PRTMP_ADAPTER pAd, + PUSHORT pWcid, + PNDIS_PACKET pPacket, + PUCHAR pSrcBUf, + UINT16 srcPort, + UINT16 dscPort); +#endif + +#ifdef CONFIG_HOTSPOT_R2 +struct _sta_hs_info { + //UCHAR addr[6]; + UCHAR version; + UCHAR ppsmo_exist; + USHORT ppsmo_id; +}; +#endif +#endif /* __HOTSPOT_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/iface.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/iface.h new file mode 100644 index 000000000..3bb37c19e --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/iface.h @@ -0,0 +1,13 @@ + +#ifndef __IFACE_H__ +#define __IFACE_H__ + +#ifdef MT_MAC +#if defined(RTMP_MAC_PCI) || defined(RTMP_MAC_USB) +#include "mt_hif_pci_usb.h" +#endif + +#endif + +#endif /* __IFACE_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/iface_util.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/iface_util.h new file mode 100644 index 000000000..46f6ab236 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/iface_util.h @@ -0,0 +1,66 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering 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_RTMP_MlmeUp RtmpOsMlmeUp + +#endif /* __RTMP_UTIL_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/mt_hif_pci_usb.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/mt_hif_pci_usb.h new file mode 100644 index 000000000..1830c49d0 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/mt_hif_pci_usb.h @@ -0,0 +1,472 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of MediaTek. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + mt_hif.h +*/ + +#ifndef __MT_HIF_H__ +#define __MT_HIF_H__ + +#define HIF_BASE 0x4000 +#define MT_HIF_BASE 0x4000 +#define HIF_SYS_REV (MT_HIF_BASE + 0x0000) +#define MT_INT_SOURCE_CSR (MT_HIF_BASE + 0x0200) +#define MT_INT_MASK_CSR (MT_HIF_BASE + 0x0204) + +#define MT_WPDMA_GLO_CFG (MT_HIF_BASE + 0x0208) +#define TX_DMA_EN (1 << 0) +#define TX_DMA_BUSY (1 << 1) +#define RX_DMA_EN (1 << 2) +#define RX_DMA_BUSY (1 << 3) +#define SW_RST (1 << 24) +#define FORCE_TX_EOF (1 << 25) + +#define WPDMA_RST_PTR (MT_HIF_BASE + 0x020c) +#define MT_DELAY_INT_CFG (MT_HIF_BASE + 0x0210) + +#define SCH_REG4 (MT_HIF_BASE + 0x0594) +#define SCH_REG4_FORCE_QID_MASK (0x0f) +#define SCH_REG4_FORCE_QID(p) (((p) & 0x0f)) +#define SCH_REG4_BYPASS_MODE_MASK (0x1 << 5) +#define SCH_REG4_BYPASS_MODE(p) (((p) & 0x1) << 5) + +/* UDMA register */ +#define UDMA_BASE 0x50029000 +#define UDMA_WLCFG_1 (0x) +#define UDMA_RESET (UDMA_BASE + 0x14) +#define UDMA_WLCFG_0 (UDMA_BASE + 0x18) +#define UDMA_WLCFG_0_TX_BT_SIZE_MASK (0x07 << 27) +#define UDMA_WLCFG_0_TX_BT_SIZE(p) (((p) & 0x07) << 27) +#define UDMA_WLCFG_0_RX_BT_SIZE_MASK (0x07 << 24) +#define UDMA_WLCFG_0_RX_BT_SIZE(p) (((p) & 0x07) << 24) +#define UDMA_WLCFG_0_TX_EN_MASK (0x1 << 23) +#define UDMA_WLCFG_0_TX_EN(p) (((p) & 0x1) << 23) +#define UDMA_WLCFG_0_RX_EN_MASK (0x1 << 22) +#define UDMA_WLCFG_0_RX_EN(p) (((p) & 0x1) << 22) +#define UDMA_WLCFG_0_RX_AGG_EN_MASK (0x1 << 21) +#define UDMA_WLCFG_0_RX_AGG_EN(p) (((p) & 0x1) << 21) +#define UDMA_WLCFG_0_LPK_EN_MASK (0x1 << 20) +#define UDMA_WLCFG_0_LPK_EN(p) (((p) & 0x1) << 20) +#define UDMA_WLCFG_0_RX_MPSZ_PAD0_MASK (0x1 << 18) +#define UDMA_WLCFG_0_RX_MPSZ_PAD0(p) (((p) & 0x1) << 18) +#define UDMA_WLCFG_0_RX_AGG_LMT_MASK (0xff << 8) +#define UDMA_WLCFG_0_RX_AGG_LMT(p) (((p) & 0xff) << 8) +#define UDMA_WLCFG_0_RX_AGG_TO_MASK (0xff << 0) +#define UDMA_WLCFG_0_RX_AGG_TO(p) (((p) & 0xff) << 0) + +#define STOP_DROP_EPOUT (0x80) + +#define MT_TXTIME_THD_0 (HIF_BASE + 0x500) +#define MT_TXTIME_THD_1 (HIF_BASE + 0x504) +#define MT_TXTIME_THD_2 (HIF_BASE + 0x508) +#define MT_TXTIME_THD_3 (HIF_BASE + 0x50c) +#define MT_TXTIME_THD_4 (HIF_BASE + 0x510) +#define MT_TXTIME_THD_5 (HIF_BASE + 0x514) +#define MT_TXTIME_THD_6 (HIF_BASE + 0x518) +#define MT_TXTIME_THD_7 (HIF_BASE + 0x51c) +#define MT_TXTIME_THD_8 (HIF_BASE + 0x520) +#define MT_TXTIME_THD_9 (HIF_BASE + 0x524) +#define MT_TXTIME_THD_10 (HIF_BASE + 0x528) +#define MT_TXTIME_THD_11 (HIF_BASE + 0x52c) +#define MT_TXTIME_THD_12 (HIF_BASE + 0x530) +#define MT_TXTIME_THD_13 (HIF_BASE + 0x534) +#define MT_TXTIME_THD_14 (HIF_BASE + 0x538) +#define MT_TXTIME_THD_15 (HIF_BASE + 0x53c) + +#define MT_PAGE_CNT_0 (HIF_BASE + 0x540) +#define PAGE_CNT_0_MASK (0xfffff) +#define GET_PAGE_CNT_0(p) (((p) & PAGE_CNT_0_MASK)) +#define MT_PAGE_CNT_1 (HIF_BASE + 0x544) +#define PAGE_CNT_1_MASK (0xfffff) +#define GET_PAGE_CNT_1(p) (((p) & PAGE_CNT_1_MASK)) +#define MT_PAGE_CNT_2 (HIF_BASE + 0x548) +#define PAGE_CNT_2_MASK (0xfffff) +#define GET_PAGE_CNT_2(p) (((p) & PAGE_CNT_2_MASK)) +#define MT_PAGE_CNT_3 (HIF_BASE + 0x54c) +#define PAGE_CNT_3_MASK (0xfffff) +#define GET_PAGE_CNT_3(p) (((p) & PAGE_CNT_3_MASK)) +#define MT_PAGE_CNT_4 (HIF_BASE + 0x550) +#define PAGE_CNT_4_MASK (0xfffff) +#define GET_PAGE_CNT_4(p) (((p) & PAGE_CNT_4_MASK)) +#define MT_PAGE_CNT_5 (HIF_BASE + 0x554) +#define PAGE_CNT_5_MASK (0xfffff) +#define GET_PAGE_CNT_5(p) (((p) & PAGE_CNT_5_MASK)) +#define MT_PAGE_CNT_6 (HIF_BASE + 0x558) +#define PAGE_CNT_6_MASK (0xfffff) +#define GET_PAGE_CNT_6(p) (((p) & PAGE_CNT_6_MASK)) +#define MT_PAGE_CNT_7 (HIF_BASE + 0x55c) +#define PAGE_CNT_7_MASK (0xfffff) +#define GET_PAGE_CNT_7(p) (((p) & PAGE_CNT_7_MASK)) +#define MT_PAGE_CNT_8 (HIF_BASE + 0x560) +#define PAGE_CNT_8_MASK (0xfffff) +#define GET_PAGE_CNT_8(p) (((p) & PAGE_CNT_8_MASK)) +#define MT_PAGE_CNT_9 (HIF_BASE + 0x564) +#define PAGE_CNT_9_MASK (0xfffff) +#define GET_PAGE_CNT_9(p) (((p) & PAGE_CNT_9_MASK)) +#define MT_PAGE_CNT_10 (HIF_BASE + 0x568) +#define PAGE_CNT_10_MASK (0xfffff) +#define GET_PAGE_CNT_10(p) (((p) & PAGE_CNT_10_MASK)) +#define MT_PAGE_CNT_11 (HIF_BASE + 0x56c) +#define PAGE_CNT_11_MASK (0xfffff) +#define GET_PAGE_CNT_11(p) (((p) & PAGE_CNT_11_MASK)) +#define MT_PAGE_CNT_12 (HIF_BASE + 0x570) +#define PAGE_CNT_12_MASK (0xfffff) +#define GET_PAGE_CNT_12(p) (((p) & PAGE_CNT_12_MASK)) +#define MT_PAGE_CNT_13 (HIF_BASE + 0x574) +#define PAGE_CNT_13_MASK (0xfffff) +#define GET_PAGE_CNT_13(p) (((p) & PAGE_CNT_13_MASK)) +#define MT_PAGE_CNT_14 (HIF_BASE + 0x578) +#define PAGE_CNT_14_MASK (0xfffff) +#define GET_PAGE_CNT_14(p) (((p) & PAGE_CNT_14_MASK)) +#define MT_PAGE_CNT_15 (HIF_BASE + 0x57c) +#define PAGE_CNT_15_MASK (0xfffff) +#define GET_PAGE_CNT_15(p) (((p) & PAGE_CNT_15_MASK)) + +#define MT_QUEUE_PRIORITY_1 (HIF_BASE + 0x580) +#define RG_QUEUE_PRIORITY_0_MASK (0xf) +#define RG_QUEUE_PRIORITY_0(p) (((p) & 0xf)) +#define GET_RG_QUEUE_PRIORITY_0(p) (((p) & RG_QUEUE_PRIORITY_0_MASK)) +#define RG_QUEUE_PRIORITY_1_MASK (0xf << 4) +#define RG_QUEUE_PRIORITY_1(p) (((p) & 0xf) << 4) +#define GET_RG_QUEUE_PRIORITY_1(p) (((p) & RG_QUEUE_PRIORITY_1_MASK) >> 4) +#define RG_QUEUE_PRIORITY_2_MASK (0xf << 8) +#define RG_QUEUE_PRIORITY_2(p) (((p) & 0xf) << 8) +#define GET_RG_QUEUE_PRIORITY_2(p) (((p) & RG_QUEUE_PRIORITY_2_MASK) >> 8) +#define RG_QUEUE_PRIORITY_3_MASK (0xf << 12) +#define RG_QUEUE_PRIORITY_3(p) (((p) & 0xf) << 12) +#define GET_RG_QUEUE_PRIORITY_3(p) (((p) & RG_QUEUE_PRIORITY_3_MASK) >> 12) +#define RG_QUEUE_PRIORITY_4_MASK (0xf << 16) +#define RG_QUEUE_PRIORITY_4(p) (((p) & 0xf) << 16) +#define GET_RG_QUEUE_PRIORITY_4(p) (((p) & RG_QUEUE_PRIORITY_4_MASK) >> 16) +#define RG_QUEUE_PRIORITY_5_MASK (0xf << 20) +#define RG_QUEUE_PRIORITY_5(p) (((p) & 0xf) << 20) +#define GET_RG_QUEUE_PRIORITY_5(p) (((p) & RG_QUEUE_PRIORITY_5_MASK) >> 20) +#define RG_QUEUE_PRIORITY_6_MASK (0xf << 24) +#define RG_QUEUE_PRIORITY_6(p) (((p) & 0xf) << 24) +#define GET_RG_QUEUE_PRIORITY_6(p) (((p) & RG_QUEUE_PRIORITY_6_MASK) >> 24) +#define RG_QUEUE_PRIORITY_7_MASK (0xf << 28) +#define RG_QUEUE_PRIORITY_7(p) (((p) & 0xf) << 28) +#define GET_RG_QUEUE_PRIORITY_7(p) (((p) & RG_QUEUE_PRIORITY_7_MASK) >> 28) + + +#define MT_QUEUE_PRIORITY_2 (HIF_BASE + 0x584) +#define RG_QUEUE_PRIORITY_8_MASK (0xf) +#define RG_QUEUE_PRIORITY_8(p) (((p) & 0xf)) +#define GET_RG_QUEUE_PRIORITY_8(p) (((p) & RG_QUEUE_PRIORITY_8_MASK)) +#define RG_QUEUE_PRIORITY_9_MASK (0xf << 4) +#define RG_QUEUE_PRIORITY_9(p) (((p) & 0xf) << 4) +#define GET_RG_QUEUE_PRIORITY_9(p) (((p) & RG_QUEUE_PRIORITY_9_MASK) >> 4) +#define RG_QUEUE_PRIORITY_10_MASK (0xf << 8) +#define RG_QUEUE_PRIORITY_10(p) (((p) & 0xf) << 8) +#define GET_RG_QUEUE_PRIORITY_10(p) (((p) & RG_QUEUE_PRIORITY_10_MASK) >> 8) +#define RG_QUEUE_PRIORITY_11_MASK (0xf << 12) +#define RG_QUEUE_PRIORITY_11(p) (((p) & 0xf) << 12) +#define GET_RG_QUEUE_PRIORITY_11(p) (((p) & RG_QUEUE_PRIORITY_11_MASK) >> 12) +#define RG_QUEUE_PRIORITY_12_MASK (0xf << 16) +#define RG_QUEUE_PRIORITY_12(p) (((p) & 0xf) << 16) +#define GET_RG_QUEUE_PRIORITY_12(p) (((p) & RG_QUEUE_PRIORITY_12_MASK) >> 16) +#define RG_QUEUE_PRIORITY_13_MASK (0xf << 20) +#define RG_QUEUE_PRIORITY_13(p) (((p) & 0xf) << 20) +#define GET_RG_QUEUE_PRIORITY_13(p) (((p) & RG_QUEUE_PRIORITY_13_MASK) >> 20) +#define RG_QUEUE_PRIORITY_14_MASK (0xf << 24) +#define RG_QUEUE_PRIORITY_14(p) (((p) & 0xf) << 24) +#define GET_RG_QUEUE_PRIORITY_14(p) (((p) & RG_QUEUE_PRIORITY_14_MASK) >> 24) +#define RG_QUEUE_PRIORITY_15_MASK (0xf << 28) +#define RG_QUEUE_PRIORITY_15(p) (((p) & 0xf) << 28) +#define GET_RG_QUEUE_PRIORITY_15(p) (((p) & RG_QUEUE_PRIORITY_15_MASK) >> 28) + +#define MT_SCH_REG_1 (HIF_BASE + 0x588) +#define RG_FFA_THD_MASK (0xfffff) +#define RG_FFA_THD(p) (((p) & 0xfffff)) +#define GET_RG_FFA_THD(p) (((p) & RG_FFA_THD_MASK)) +#define RG_PAGE_SIZE_MASK (0xf << 28) +#define RG_PAGE_SIZE(p) (((p) & 0xf) << 28) +#define GET_RG_PAGE_SIZE(p) (((p) & RG_PAGE_SIZE_MASK) >> 28) + +#define MT_SCH_REG_2 (HIF_BASE + 0x58c) +#define RG_MAX_PKT_SIZE_MASK (0xfffff) +#define RG_MAX_PKT_SIZE(p) (((p) & 0xfffff)) +#define GET_RG_MAX_PKT_SIZE(p) (((p) & RG_MAX_PKT_SIZE_MASK)) + +#define MT_SCH_REG_3 (HIF_BASE + 0x590) +#define MT_SCH_REG_4 (HIF_BASE + 0x594) + +#define MT_SCH_REG_4 (HIF_BASE + 0x594) +#define FORCE_QID_MASK (0Xf) +#define FORCE_QID(p) (((p) & 0xf)) +#define GET_FORCE_QID(p) (((p) & FORCE_QID_MASK)) +#define FORCE_MODE (1 << 4) +#define GET_FORCE_MODE(p) (((p) & FORCE_MODE) >> 4) +#define BYPASS_MODE (1 << 5) +#define GET_BYPASS_MODE(p) (((p) & BYPASS_MODE) >> 5) +#define HYBIRD_MODE (1 << 6) +#define GET_HYBIRD_MODE(p) (((p) & HYBIRD_MODE) >> 6) +#define RG_PREDICT_NO_MASK (1 << 7) +#define GET_RG_PREDICT_NO_MASK(p) (((p) & RG_PREDICT_NO_MASK) >> 7) +#define SW_MODE (1 << 10) +#define GET_SW_MODE(p) (((p) & SW_MODE) >> 10) +#define RG_RATE_MAP_MASK (0x3fff << 16) +#define RG_RATE_MAP(p) (((p) & 0x3fff) << 16) +#define GET_RG_RATE_MAP(p) (((p) & RG_RATE_MAP_MASK) >> 16) + +#define MT_GROUP_THD_0 (HIF_BASE + 0x598) +#define GROUP_THD_0_MASK (0xfffff) +#define GROUP_THD_0(p) (((p) & 0xfffff)) +#define GET_GROUP_THD_0(p) (((p) & GROUP_THD_0_MASK)) + +#define MT_GROUP_THD_1 (HIF_BASE + 0x59c) + +#define GROUP_THD_1_MASK (0xfffff) +#define GROUP_THD_1(p) (((p) & 0xfffff)) +#define GET_GROUP_THD_1(p) (((p) & GROUP_THD_1_MASK)) + +#define MT_GROUP_THD_2 (HIF_BASE + 0x5a0) +#define GROUP_THD_2_MASK (0xfffff) +#define GROUP_THD_2(p) (((p) & 0xfffff)) +#define GET_GROUP_THD_2(p) (((p) & GROUP_THD_2_MASK)) + +#define MT_GROUP_THD_3 (HIF_BASE + 0x5a4) +#define GROUP_THD_3_MASK (0xfffff) +#define GROUP_THD_3(p) (((p) & 0xfffff)) +#define GET_GROUP_THD_3(p) (((p) & GROUP_THD_3_MASK)) + +#define MT_GROUP_THD_4 (HIF_BASE + 0x5a8) +#define GROUP_THD_4_MASK (0xfffff) +#define GROUP_THD_4(p) (((p) & 0xfffff)) +#define GET_GROUP_THD_4(p) (((p) & GROUP_THD_4_MASK)) + +#define MT_GROUP_THD_5 (HIF_BASE + 0x5ac) +#define GROUP_THD_5_MASK (0xfffff) +#define GROUP_THD_5(p) (((p) & 0xfffff)) +#define GET_GROUP_THD_5(p) (((p) & GROUP_THD_5_MASK)) + +#define MT_BMAP_0 (HIF_BASE + 0x5b0) +#define RG_BMAP_0_MASK (0xffff) +#define RG_BMAP_0(p) (((p) & 0xffff)) +#define GET_RG_BMAP_0(p) (((p) & RG_BMAP_0_MASK)) +#define RG_BMAP_1_MASK (0xffff << 16) +#define RG_BMAP_1(p) (((p) & 0xffff) << 16) +#define GET_RG_BMAP_1(p) (((p) & RG_BMAP_1_MASK) >> 16) + +#define MT_BMAP_1 (HIF_BASE + 0x5b4) +#define RG_BMAP_2_MASK (0xffff) +#define RG_BMAP_2(p) (((p) & 0xffff)) +#define GET_RG_BMAP_2(p) (((p) & RG_BMAP_2_MASK)) +#define RG_BMAP_3_MASK (0xffff << 16) +#define RG_BMAP_3(p) (((p) & 0xffff) << 16) +#define GET_RG_BMAP_3(p) (((p) & RG_BMAP_3_MASK) >> 16) + +#define MT_BMAP_2 (HIF_BASE + 0x5b8) +#define RG_BMAP_4_MASK (0xffff) +#define RG_BMAP_4(p) (((p) & 0xffff)) +#define GET_RG_BMAP_4(p) (((p) & RG_BMAP_4_MASK)) +#define RG_BMAP_5_MASK (0xffff << 16) +#define RG_BMAP_5(p) (((p) & 0xffff) << 16) +#define GET_RG_BMAP_5(p) (((p) & RG_BMAP_5_MASK) >> 16) + +#define MT_HIGH_PRIORITY_1 (HIF_BASE + 0x5bc) +#define RG_HIGH_PRIORITY_0_MASK (0xf) +#define RG_HIGH_PRIORITY_0(p) (((p) & 0xf)) +#define GET_RG_HIGH_PRIORITY_0(p) (((p) & RG_HIGH_PRIORITY_0_MASK)) +#define RG_HIGH_PRIORITY_1_MASK (0xf << 4) +#define RG_HIGH_PRIORITY_1(p) (((p) & 0xf) << 4) +#define GET_RG_HIGH_PRIORITY_1(p) (((p) & RG_HIGH_PRIORITY_1_MASK) >> 4) +#define RG_HIGH_PRIORITY_2_MASK (0xf << 8) +#define RG_HIGH_PRIORITY_2(p) (((p) & 0xf) << 8) +#define GET_RG_HIGH_PRIORITY_2(p) (((p) & RG_HIGH_PRIORITY_2_MASK) >> 8) +#define RG_HIGH_PRIORITY_3_MASK (0xf << 12) +#define RG_HIGH_PRIORITY_3(p) (((p) & 0xf) << 12) +#define GET_RG_HIGH_PRIORITY_3(p) (((p) & RG_HIGH_PRIORITY_3_MASK) >> 12) +#define RG_HIGH_PRIORITY_4_MASK (0xf << 16) +#define RG_HIGH_PRIORITY_4(p) (((p) & 0xf) << 16) +#define GET_RG_HIGH_PRIORITY_4(p) (((p) & RG_HIGH_PRIORITY_4_MASK) >> 16) +#define RG_HIGH_PRIORITY_5_MASK (0xf << 20) +#define RG_HIGH_PRIORITY_5(p) (((p) & 0xf) << 20) +#define GET_RG_HIGH_PRIORITY_5(p) (((p) & RG_HIGH_PRIORITY_5_MASK) >> 20) +#define RG_HIGH_PRIORITY_6_MASK (0xf << 24) +#define RG_HIGH_PRIORITY_6(p) (((p) & 0xf) << 24) +#define GET_RG_HIGH_PRIORITY_6(p) (((p) & RG_HIGH_PRIORITY_6_MASK) >> 24) +#define RG_HIGH_PRIORITY_7_MASK (0xf << 28) +#define RG_HIGH_PRIORITY_7(p) (((p) & 0xf) << 28) +#define GET_RG_HIGH_PRIORITY_7(p) (((p) & RG_HIGH_PRIORITY_7_MASK) >> 28) + +#define MT_HIGH_PRIORITY_2 (HIF_BASE + 0x5c0) +#define RG_HIGH_PRIORITY_8_MASK (0xf) +#define RG_HIGH_PRIORITY_8(p) (((p) & 0xf)) +#define GET_RG_HIGH_PRIORITY_8(p) (((p) & RG_HIGH_PRIORITY_8_MASK)) +#define RG_HIGH_PRIORITY_9_MASK (0xf << 4) +#define RG_HIGH_PRIORITY_9(p) (((p) & 0xf) << 4) +#define GET_RG_HIGH_PRIORITY_9(p) (((p) & RG_HIGH_PRIORITY_9_MASK) >> 4) +#define RG_HIGH_PRIORITY_10_MASK (0xf << 8) +#define RG_HIGH_PRIORITY_10(p) (((p) & 0xf) << 8) +#define GET_RG_HIGH_PRIORITY_10(p) (((p) & RG_HIGH_PRIORITY_10_MASK) >> 8) +#define RG_HIGH_PRIORITY_11_MASK (0xf << 12) +#define RG_HIGH_PRIORITY_11(p) (((p) & 0xf) << 12) +#define GET_RG_HIGH_PRIORITY_11(p) (((p) & RG_HIGH_PRIORITY_11_MASK) >> 12) +#define RG_HIGH_PRIORITY_12_MASK (0xf << 16) +#define RG_HIGH_PRIORITY_12(p) (((p) & 0xf) << 16) +#define GET_RG_HIGH_PRIORITY_12(p) (((p) & RG_HIGH_PRIORITY_12_MASK) >> 16) +#define RG_HIGH_PRIORITY_13_MASK (0xf << 20) +#define RG_HIGH_PRIORITY_13(p) (((p) & 0xf) << 20) +#define GET_RG_HIGH_PRIORITY_13(p) (((p) & RG_HIGH_PRIORITY_13_MASK) >> 20) +#define RG_HIGH_PRIORITY_14_MASK (0xf << 24) +#define RG_HIGH_PRIORITY_14(p) (((p) & 0xf) << 24) +#define GET_RG_HIGH_PRIORITY_14(p) (((p) & RG_HIGH_PRIORITY_14_MASK) >> 24) +#define RG_HIGH_PRIORITY_15_MASK (0xf << 28) +#define RG_HIGH_PRIORITY_15(p) (((p) & 0xf) << 28) +#define GET_RG_HIGH_PRIORITY_15(p) (((p) & RG_HIGH_PRIORITY_15_MASK) >> 28) + +#define MT_PRIORITY_MASK (HIF_BASE + 0x5c4) +#define RG_QUEUE_PRIORITY_MASK (0xffff) +#define RG_QUEUE_PRIORITY(p) (((p) & 0xffff)) +#define GET_RG_QUEUE_PRIORITY(p) (((p) & RG_QUEUE_PRIORITY_MASK)) +#define RG_HIGH_PRIORITY_MASK (0xffff << 16) +#define RG_HIGH_PRIORITY(p) (((p) & 0xffff) << 16) +#define GET_RG_HIGH_PRIORITY(p) (((p) & RG_HIGH_PRIORITY_MASK) >> 16) + +#define MT_RSV_MAX_THD (HIF_BASE + 0x5c8) +#define RG_RSV_MAX_THD_MASK (0xfffff) +#define RG_RSV_MAX_THD(p) (((p) & 0xfffff)) +#define GET_RG_RSV_MAX_THD(p) (((p) & RG_RSV_MAX_THD_MASK)) + +#define RSV_AC_CNT_0 (HIF_BASE + 0x5d0) +#define RSV_AC_CNT_0_MASK (0xfffff) +#define GET_RSV_AC_CNT_0(p) (((p) & RSV_AC_CNT_0_MASK)) + +#define RSV_AC_CNT_1 (HIF_BASE + 0x5d4) +#define RSV_AC_CNT_1_MASK (0xfffff) +#define GET_RSV_AC_CNT_1(p) (((p) & RSV_AC_CNT_1_MASK)) + +#define RSV_AC_CNT_2 (HIF_BASE + 0x5d8) +#define RSV_AC_CNT_2_MASK (0xfffff) +#define GET_RSV_AC_CNT_2(p) (((p) & RSV_AC_CNT_2_MASK)) + +#define RSV_AC_CNT_3 (HIF_BASE + 0x5dc) +#define RSV_AC_CNT_3_MASK (0xfffff) +#define GET_RSV_AC_CNT_3(p) (((p) & RSV_AC_CNT_3_MASK)) + +#define RSV_AC_CNT_4 (HIF_BASE + 0x5e0) +#define RSV_AC_CNT_4_MASK (0xfffff) +#define GET_RSV_AC_CNT_4(p) (((p) & RSV_AC_CNT_4_MASK)) + +#define RSV_AC_CNT_5 (HIF_BASE + 0x5e4) +#define RSV_AC_CNT_5_MASK (0xfffff) +#define GET_RSV_AC_CNT_5(p) (((p) & RSV_AC_CNT_5_MASK)) + +#define RSV_AC_CNT_6 (HIF_BASE + 0x5e8) +#define RSV_AC_CNT_6_MASK (0xfffff) +#define GET_RSV_AC_CNT_6(p) (((p) & RSV_AC_CNT_6_MASK)) + +#define RSV_AC_CNT_7 (HIF_BASE + 0x5ec) +#define RSV_AC_CNT_7_MASK (0xfffff) +#define GET_RSV_AC_CNT_7(p) (((p) & RSV_AC_CNT_7_MASK)) + +#define RSV_AC_CNT_8 (HIF_BASE + 0x5f0) +#define RSV_AC_CNT_8_MASK (0xfffff) +#define GET_RSV_AC_CNT_8(p) (((p) & RSV_AC_CNT_8_MASK)) + +#define RSV_AC_CNT_9 (HIF_BASE + 0x5f4) +#define RSV_AC_CNT_9_MASK (0xfffff) +#define GET_RSV_AC_CNT_9(p) (((p) & RSV_AC_CNT_9_MASK)) + +#define RSV_AC_CNT_10 (HIF_BASE + 0x5f8) +#define RSV_AC_CNT_10_MASK (0xfffff) +#define GET_RSV_AC_CNT_10(p) (((p) & RSV_AC_CNT_10_MASK)) + +#define RSV_AC_CNT_11 (HIF_BASE + 0x5fc) +#define RSV_AC_CNT_11_MASK (0xfffff) +#define GET_RSV_AC_CNT_11(p) (((p) & RSV_AC_CNT_11_MASK)) + +#define RSV_AC_CNT_12 (HIF_BASE + 0x600) +#define RSV_AC_CNT_12_MASK (0xfffff) +#define GET_RSV_AC_CNT_12(p) (((p) & RSV_AC_CNT_12_MASK)) + +#define RSV_AC_CNT_13 (HIF_BASE + 0x604) +#define RSV_AC_CNT_13_MASK (0xfffff) +#define GET_RSV_AC_CNT_13(p) (((p) & RSV_AC_CNT_13_MASK)) + +#define RSV_AC_CNT_14 (HIF_BASE + 0x608) +#define RSV_AC_CNT_14_MASK (0xfffff) +#define GET_RSV_AC_CNT_14(p) (((p) & RSV_AC_CNT_14_MASK)) + +#define RSV_AC_CNT_15 (HIF_BASE + 0x60c) +#define RSV_AC_CNT_15_MASK (0xfffff) +#define GET_RSV_AC_CNT_15(p) (((p) & RSV_AC_CNT_15_MASK)) + +#define SCH_DBG0_0 (HIF_BASE + 0x650) +#define RSV_ENOUGH_MASK (0xffff) +#define GET_RSV_ENOUGH(p) (((p) & 0xffff)) +#define GROUP_ENOUGH (1 << 20) +#define GET_GROUP_ENOUGH(p) (((p) & GROUP_ENOUGH) >> 20) +#define QUEUE_ENOUGH (1 << 21) +#define GET_QUEUE_ENOUGH(p) (((p) & QUEUE_ENOUGH) >> 21) +#define PREDICT_MODE (1 << 22) +#define GET_PREDICT_MODE(p) (((p) & PREDICT_MODE) >> 22) +#define REST_QUEUE_EN (1 << 28) +#define GET_REST_QUEUE_EN(p) (((p) & REST_QUEUE_EN) >> 28) +#define ENOUGH_TXTIME (1 << 30) +#define GET_ENOUGH_TXTIME(p) (((p) & ENOUGH_TXTIME) >> 30) +#define ENOUGH_BUF (1 << 31) +#define GET_ENOUGH_BUF(p) (((p) & ENOUGH_BUF) >> 31) + +#define SCH_DBG_1 (HIF_BASE + 0x654) +#define FFA_PAGE_CNT_MASK (0xfffff) +#define GET_FFA_PAGE_CNT(p) (((p) & FFA_PAGE_CNT_MASK)) + + +#define SCH_DBG_2 (HIF_BASE + 0x658) +#define PKT_TX_TIME_MASK (0xffffffff) +#define GET_PKT_TX_TIME(p) (((p) & PKT_TX_TIME_MASK)) + +#define SCH_DBG_3 (HIF_BASE + 0x65c) +#define TX_TIME_PER_BYTE_MASK (0x1fff) +#define GET_TX_TIME_PER_BYTE(p) (((p) & TX_TIME_PER_BYTE_MASK)) + +#define SCH_DBG_4 (HIF_BASE + 0x660) +#define PSE_RSV_SPACE_MASK (0xfff) +#define GET_PSE_RSV_SPACE(p) (((p) & PSE_RSV_SPACE_MASK)) +#define HIF_RSV_PCNT_MASK (0xfff << 16) +#define GET_HIF_RSV_PCNT(p) (((p) & HIF_RSV_PCNT_MASK) >> 16) +#define HIF_RSV_PCNT_UPDT_MASK (1 << 31) +#define GET_HIF_RSV_PCNT_UPDT(p) (((p) & HIF_RSV_PCNT_UPDT_MASK) >> 31) + +#define SCH_DBG_5 (HIF_BASE + 0x664) +#define GROUP_EN_MASK (0xffff) +#define GET_GROUP_EN(p) (((p) & GROUP_EN_MASK)) + +#define SCH_DBG_6 (HIF_BASE + 0x668) +#define USED_GROUP_0_MASK (0xfffff) +#define GET_USED_GROUP_0(p) (((p) & USED_GROUP_0_MASK)) + +#define SCH_DBG_7 (HIF_BASE + 0x66c) +#define USED_GROUP_1_MASK (0xfffff) +#define GET_USED_GROUP_1(p) (((p) & USED_GROUP_1_MASK)) + +#define SCH_DBG_8 (HIF_BASE + 0x670) +#define USED_GROUP_2_MASK (0xfffff) +#define GET_USED_GROUP_2(p) (((p) & USED_GROUP_2_MASK)) + +#define SCH_DBG_9 (HIF_BASE + 0x674) +#define USED_GROUP_3_MASK (0xfffff) +#define GET_USED_GROUP_3(p) (((p) & USED_GROUP_3_MASK)) + +#define SCH_DBG_10 (HIF_BASE + 0x678) +#define USED_GROUP_4_MASK (0xfffff) +#define GET_USED_GROUP_4(p) (((p) & USED_GROUP_4_MASK)) + +#define SCH_DBG_11 (HIF_BASE + 0x67c) +#define USED_GROUP_5_MASK (0xfffff) +#define GET_USED_GROUP_5(p) (((p) & USED_GROUP_5_MASK)) + + +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/mt_hif_sdio.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/mt_hif_sdio.h new file mode 100644 index 000000000..e1f8f82d7 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/mt_hif_sdio.h @@ -0,0 +1,132 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of MediaTek. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + mt_hif_sdio.h +*/ + +#ifndef __MT_HIF_SDIO_H__ +#define __MT_HIF_SDIO_H__ + +#define WCIR 0x0000 +#define CHIP_ID_MASK (0xffff) +#define GET_CHIP_ID(p) (((p) & CHIP_ID_MASK)) +#define REVISION_ID_MASK (0xf << 16) +#define GET_REVISION_ID(p) (((p) & REVISION_ID_MASK) >> 16) +#define POR_INDICATOR (1 << 20) +#define GET_POR_INDICATOR(p) (((p) & POR_INDICATOR) >> 20) +#define W_FUNC_RDY (1 << 21) +#define GET_W_FUNC_RDY(p) (((p) & W_FUNC_RDY) >> 21) +#define DEVICE_STATUS_MASK (0xff << 24) +#define GET_DEVICE_STATUS(p) (((p) & DEVICE_STATUS_MASK) >> 24) + +#define WHLPCR 0x0004 +#define W_INT_EN_SET (1 << 0) +#define W_INT_EN_CLR (1 << 1) +#define W_FW_OWN_REQ_SET (1 << 8) +#define GET_W_FW_OWN_REQ_SET(p) (((p) & W_FW_OWN_REQ_SET) >> 8) +#define W_FW_OWN_REQ_CLR (1 << 9) + +#define WSDIOCSR 0x0008 + +#define WHCR 0x000C +#define W_INT_CLR_CTRL (1 << 1) +#define RECV_MAILBOX_RD_CLR_EN (1 << 2) +#define RPT_OWN_RX_PACKET_LEN (1 << 3) +#define MAX_HIF_RX_LEN_NUM_MASK (0x3f << 8) +#define MAX_HIF_RX_LEN_NUM(p) (((p) & 0x3f) << 8) +#define GET_MAX_HIF_RX_LEN_NUM(p) (((p) & MAX_HIF_RX_LEN_NUM_MASK) >> 8) +#define RX_ENHANCE_MODE (1 << 16) + +#define WHISR 0x0010 +#define TX_DONE_INT (1 << 0) +#define RX0_DONE_INT (1 << 1) +#define RX1_DONE_INT (1 << 2) +#define ABNORMAL_INT (1 << 6) +#define FW_OWN_BACK_INT (1 << 7) +#define D2H_SW_INT (0xffffff << 8) +#define D2H_SW_INT_MASK (0xffffff << 8) +#define GET_D2H_SW_INT(p) (((p) & D2H_SW_INT_MASK) >> 8) + +#define WHIER 0x0014 +#define TX_DONE_INT_EN (1 << 0) +#define RX0_DONE_INT_EN (1 << 1) +#define RX1_DONE_INT_EN (1 << 2) +#define ABNORMAL_INT_EN (1 << 6) +#define FW_OWN_BACK_INT_EN (1 << 7) +#define D2H_SW_INT_EN_MASK (0xffffff << 8) +#define D2H_SW_INT_EN(p) (((p) & 0xffffff) << 8) +#define GET_D2H_SW_INT_EN(p) (((p) & D2H_SW_INT_EN_MASK) >> 8) + +#define WHIER_DEFAULT (TX_DONE_INT_EN | RX0_DONE_INT_EN | RX1_DONE_INT_EN\ + | ABNORMAL_INT_EN\ + | D2H_SW_INT_EN_MASK) + + +#define WASR 0x0020 +#define TX1_OVERFLOW (1 << 1) +#define RX0_UNDERFLOW (1 << 8) +#define RX1_UNDERFLOW (1 << 9) +#define FW_OWN_INVALID_ACCESS (1 << 16) + +#define WSICR 0x0024 +#define WTDR1 0x0034 +#define WRDR0 0x0050 +#define WRDR1 0x0054 +#define H2DSM0R 0x0070 +#define H2DSM1R 0x0074 +#define D2HRM0R 0x0078 +#define D2HRM1R 0x007c + +#define WRPLR 0x0090 +#define RX0_PACKET_LENGTH_MASK (0xffff) +#define GET_RX0_PACKET_LENGTH(p) (((p) & RX0_PACKET_LENGTH_MASK)) +#define RX1_PACKET_LENGTH_MASK (0xffff << 16) +#define GET_RX1_PACKET_LENGTH(p) (((p) & RX1_PACKET_LENGTH_MASK) >> 16) + +#define WTMDR 0x00b0 +#define WTMCR 0x00b4 +#define WTMDPCR0 0x00b8 +#define WTMDPCR1 0x00bc + +#define WPLRCR 0x00d4 +#define RX0_RPT_PKT_LEN_MASK (0x3f) +#define RX0_RPT_PKT_LEN(p) (((p) & 0x3f)) +#define GET_RPT_PKT_LEN(p) (((p) & RX0_RPT_PKT_LEN_MASK)) +#define RX1_RPT_PKT_LEN_MASK (0x3f << 8) +#define RX1_RPT_PKT_LEN(p) (((p) & 0x3f) << 8) +#define GET_RX1_RPT_PKT_LEN(p) (((p) & RX1_RPT_PKT_LEN_MASK) >> 8) + +#define WSR 0x00D8 +#define CLKIOCR 0x0100 +#define CMDIOCR 0x0104 +#define DAT0IOCR 0x0108 +#define DAT1IOCR 0x010C +#define DAT2IOCR 0x0110 +#define DAT3IOCR 0x0114 +#define CLKDLYCR 0x0118 +#define CMDDLYCR 0x011C +#define ODATDLYCR 0x0120 +#define IDATDLYCR1 0x0124 +#define IDATDLYCR2 0x0128 +#define ILCHCR 0x012C +#define WTQCR0 0x0130 +#define WTQCR1 0x0134 +#define WTQCR2 0x0138 +#define WTQCR3 0x013C +#define WTQCR4 0x0140 +#define WTQCR5 0x0144 +#define WTQCR6 0x0148 +#define WTQCR7 0x014C + +#endif + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/mt_sdio.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/mt_sdio.h new file mode 100644 index 000000000..5c013e105 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/mt_sdio.h @@ -0,0 +1,43 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of MediaTek. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + mt_sdio.h +*/ + + +#ifndef __MT_SDIO_H__ +#define __MT_SDIO_H__ + +#include "rt_config.h" +#include "mtsdio_io.h" +#include "mtsdio_data.h" + +struct _RTMP_ADAPTER; +struct _TX_BLK; + +void rt_sdio_interrupt(struct sdio_func *func); +void InitSDIODevice(VOID *ad_src); + +USHORT MtSDIO_WriteSubTxResource(struct _RTMP_ADAPTER *pAd, struct _TX_BLK *pTxBlk, BOOLEAN bIsLast, USHORT *freeCnt); +USHORT MtSDIO_WriteSingleTxResource(struct _RTMP_ADAPTER *pAd, struct _TX_BLK *pTxBlk, BOOLEAN bIsLast, USHORT *freeCnt); +USHORT MtSDIO_WriteFragTxResource(struct _RTMP_ADAPTER *pAd, struct _TX_BLK *pTxBlk, UCHAR fragNum, USHORT *freeCnt); +USHORT MtSDIO_WriteMultiTxResource(struct _RTMP_ADAPTER *pAd, struct _TX_BLK *pTxBlk, UCHAR frmNum, USHORT *freeCnt); +VOID MtSDIO_FinalWriteTxResource(struct _RTMP_ADAPTER *pAd, struct _TX_BLK *pTxBlk, USHORT mpdu_len, USHORT TxIdx); + +VOID MtSDIODataLastTxIdx(struct _RTMP_ADAPTER *pAd, UCHAR QueIdx, USHORT TxIdx); +VOID MtSDIODataKickOut(struct _RTMP_ADAPTER *pAd, struct _TX_BLK *pTxBlk, UCHAR QueIdx); +int MtSDIOMgmtKickOut(struct _RTMP_ADAPTER *pAd, UCHAR QIdx, PNDIS_PACKET pkt, UCHAR *pSrcBufVA, UINT SrcBufLen); +VOID MtSDIONullFrameKickOut(struct _RTMP_ADAPTER *pAd, UCHAR QIdx, UCHAR *pNullFrm, UINT32 frmLen); + +#endif + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/rtmp_inf_pcirbs.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/rtmp_inf_pcirbs.h new file mode 100644 index 000000000..51833e2de --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/rtmp_inf_pcirbs.h @@ -0,0 +1,171 @@ +/* + +*/ + +#ifndef __RTMP_INF_PCIRBS_H__ +#define __RTMP_INF_PCIRBS_H__ + +#define fRTMP_ADAPTER_NEED_STOP_TX 0 + +#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 */ + + +/* ----------------- TX Related MACRO ----------------- */ +#define RTMP_START_DEQUEUE(pAd, QueIdx, irqFlags) do{}while(0) +#define RTMP_STOP_DEQUEUE(pAd, QueIdx, irqFlags) do{}while(0) + + +#define RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, freeNum, pPacket) \ + ((freeNum) >= (ULONG)(pTxBlk->TotalFragNum + RTMP_GET_PACKET_FRAGMENTS(pPacket) + 3)) /* rough estimate we will use 3 more descriptor. */ +#define RTMP_RELEASE_DESC_RESOURCE(pAd, QueIdx) \ + do{}while(0) + +#ifdef WFA_VHT_PF +#define NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, freeNum, _TxFrameType) \ + ((((pAd->force_amsdu && (_TxFrameType == TX_AMSDU_FRAME)) || (freeNum != (TX_RING_SIZE-1))) && (pAd->TxSwQueue[QueIdx].Number == 0)) || \ + (freeNum<3)\ + ) +#else +#if defined(MT7603_FPGA) || defined(MT7628_FPGA) +#define NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, freeNum, _TxFrameType) \ + ((((pAd->force_amsdu && (_TxFrameType == TX_RALINK_FRAME)) || (freeNum != (TX_RING_SIZE-1))) && (pAd->TxSwQueue[QueIdx].Number == 0)) || \ + (freeNum<3)\ + ) +#else +#define NEED_QUEUE_BACK_FOR_AGG(pAd, QueIdx, freeNum, _TxFrameType) \ + (((freeNum != (TX_RING_SIZE-1)) && (pAd->TxSwQueue[QueIdx].Number == 0)) || (freeNum<3)) + /*(((freeNum) != (TX_RING_SIZE-1)) && (pAd->TxSwQueue[QueIdx].Number == 1)) */ +#endif +#endif /* WFA_VHT_PF */ + +#define HAL_KickOutMgmtTx(_pAd, _QueIdx, _pPacket, _pSrcBufVA, _SrcBufLen) \ + RtmpPCIMgmtKickOut(_pAd, _QueIdx, _pPacket, _pSrcBufVA, _SrcBufLen) + +#define HAL_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) \ + /* RtmpPCI_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber)*/ + +#define HAL_WriteTxResource(pAd, pTxBlk,bIsLast, pFreeNumber) \ + RtmpPCI_WriteSingleTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) + +#define HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) \ + RtmpPCI_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) + +#define HAL_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber) \ + RtmpPCI_WriteMultiTxResource(pAd, pTxBlk, frameNum, pFreeNumber) + +#define HAL_FinalWriteTxResource(_pAd, _pTxBlk, _TotalMPDUSize, _FirstTxIdx) \ + RtmpPCI_FinalWriteTxResource(_pAd, _pTxBlk, _TotalMPDUSize, _FirstTxIdx) + +#define HAL_LastTxIdx(_pAd, _QueIdx,_LastTxIdx) \ + /*RtmpPCIDataLastTxIdx(_pAd, _QueIdx,_LastTxIdx)*/ + +#define HAL_KickOutTx(_pAd, _pTxBlk, _QueIdx) \ + { \ + if (_QueIdx == QID_BMC) { \ + RTMP_IO_WRITE32((_pAd), (_pAd)->TxBmcRing.hw_cidx_addr, (_pAd)->TxBmcRing.TxCpuIdx); \ + AsicSetBmcQCR(_pAd, BMC_CNT_UPDATE, CR_WRITE, _pAd->wdev_list[_pTxBlk->wdev_idx]->func_idx, NULL ); \ + } \ + else \ + RTMP_IO_WRITE32((_pAd), (_pAd)->TxRing[(_QueIdx)].hw_cidx_addr, (_pAd)->TxRing[(_QueIdx)].TxCpuIdx); \ + } + +#define HAL_KickOutTxBMC(_pAd, _pTxBlk, _QueIdx) \ + RTMP_IO_WRITE32((_pAd), (_pAd)->TxBmcRing.hw_cidx_addr, (_pAd)->TxBmcRing.TxCpuIdx) + +#define HAL_KickOutNullFrameTx(_pAd, _QueIdx, _pNullFrame, _frameLen) \ + MiniportMMRequest(_pAd, _QueIdx, _pNullFrame, _frameLen) + +#define GET_TXRING_FREENO(_pAd, _QueIdx) \ + (_pAd->TxRing[_QueIdx].TxSwFreeIdx > _pAd->TxRing[_QueIdx].TxCpuIdx) ? \ + (_pAd->TxRing[_QueIdx].TxSwFreeIdx - _pAd->TxRing[_QueIdx].TxCpuIdx - 1) \ + : \ + (_pAd->TxRing[_QueIdx].TxSwFreeIdx + TX_RING_SIZE - _pAd->TxRing[_QueIdx].TxCpuIdx - 1); + +#define IS_TXRING_EMPTY(_pAd, _QueIdx) \ + (_pAd->TxRing[_QueIdx].TxDmaIdx == _pAd->TxRing[_QueIdx].TxCpuIdx) ? 1: 0; + +#define IS_RXRING_FULL(_pAd, _QueIdx)\ + (_pAd->RxRing[_QueIdx].RxDmaIdx == _pAd->RxRing[_QueIdx].RxCpuIdx) ? 1: 0; + +#define GET_MGMTRING_FREENO(_pAd) \ + (_pAd->MgmtRing.TxSwFreeIdx > _pAd->MgmtRing.TxCpuIdx) ? \ + (_pAd->MgmtRing.TxSwFreeIdx - _pAd->MgmtRing.TxCpuIdx - 1) \ + : \ + (_pAd->MgmtRing.TxSwFreeIdx + MGMT_RING_SIZE - _pAd->MgmtRing.TxCpuIdx - 1); + +#ifdef MT_MAC +#define GET_BCNRING_FREENO(_pAd) \ + (_pAd->BcnRing.TxSwFreeIdx > _pAd->BcnRing.TxCpuIdx) ? \ + (_pAd->BcnRing.TxSwFreeIdx - _pAd->BcnRing.TxCpuIdx - 1) \ + : \ + (_pAd->BcnRing.TxSwFreeIdx + BCN_RING_SIZE - _pAd->BcnRing.TxCpuIdx - 1); +#endif /* MT_MAC */ + + +#ifdef USE_BMC +//DATA_QUEUE_RESERVE +#define GET_BMCRING_FREENO(_pAd) \ + (_pAd->TxBmcRing.TxSwFreeIdx > _pAd->TxBmcRing.TxCpuIdx) ? \ + (_pAd->TxBmcRing.TxSwFreeIdx - _pAd->TxBmcRing.TxCpuIdx - 1) \ + : \ + (_pAd->TxBmcRing.TxSwFreeIdx + TX_RING_SIZE - _pAd->TxBmcRing.TxCpuIdx - 1); +#endif /* USE_MBC */ + + +#ifdef CONFIG_ANDES_SUPPORT +#define GET_CTRLRING_FREENO(_pAd) \ + (_pAd->CtrlRing.TxSwFreeIdx > _pAd->CtrlRing.TxCpuIdx) ? \ + (_pAd->CtrlRing.TxSwFreeIdx - _pAd->CtrlRing.TxCpuIdx - 1) \ + : \ + (_pAd->CtrlRing.TxSwFreeIdx + MGMT_RING_SIZE - _pAd->CtrlRing.TxCpuIdx - 1); +#endif /* CONFIG_ANDES_SUPPORT */ + + +struct _RTMP_ADAPTER; +struct _TX_BLK; + +USHORT RtmpPCI_WriteSingleTxResource( + IN struct _RTMP_ADAPTER *pAd, + IN struct _TX_BLK *pTxBlk, + IN BOOLEAN bIsLast, + OUT USHORT *FreeNumber); + +USHORT RtmpPCI_WriteMultiTxResource( + IN struct _RTMP_ADAPTER *pAd, + IN struct _TX_BLK *pTxBlk, + IN UCHAR frameNum, + OUT USHORT *FreeNumber); + +USHORT RtmpPCI_WriteFragTxResource( + IN struct _RTMP_ADAPTER *pAd, + IN struct _TX_BLK *pTxBlk, + IN UCHAR fragNum, + OUT USHORT *FreeNumber); + +VOID RtmpPCI_FinalWriteTxResource( + IN struct _RTMP_ADAPTER *pAd, + IN struct _TX_BLK *pTxBlk, + IN USHORT totalMPDUSize, + IN USHORT FirstTxIdx); + +int RtmpPCIMgmtKickOut( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket, + IN PUCHAR pSrcBufVA, + IN UINT SrcBufLen); + +#endif /* __RTMP_INF_PCIRBS_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/rtmp_pci.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/rtmp_pci.h new file mode 100644 index 000000000..652d68213 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/rtmp_pci.h @@ -0,0 +1,93 @@ +/**************************************************************************** + * 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__ + +#include "iface/rtmp_inf_pcirbs.h" + +/* + Device ID & Vendor ID related definitions, + NOTE: you should not add the new VendorID/DeviceID here unless you + not sure it belongs to what chip. +*/ + +#define PCIBUS_INTEL_VENDOR 0x8086 + +#if !defined(PCI_CAP_ID_EXP) +#define PCI_CAP_ID_EXP 0x10 +#endif +#if !defined(PCI_EXP_LNKCTL) +#define PCI_EXP_LNKCTL 0x10 +#endif +#if !defined(PCI_CLASS_BRIDGE_PCI) +#define PCI_CLASS_BRIDGE_PCI 0x0604 +#endif + + +#define SYSCFG0 0x10 + +/* + PCI registers - base address 0x0000 +*/ +#define PCI_CFG 0x0000 +#define PCI_EECTRL 0x0004 +#define PCI_MCUCTRL 0x0008 +#define AUX_CTRL 0x10c + +#define OPT_14 0x114 + + +#define RT28XX_HANDLE_DEV_ASSIGN(handle, dev_p) \ + ((POS_COOKIE)handle)->pci_dev = dev_p; + + +#ifdef LINUX +/* set driver data */ +#define RT28XX_DRVDATA_SET(_a) pci_set_drvdata(_a, net_dev); + +#define RT28XX_PUT_DEVICE(dev_p) + + +#define RTMP_PCI_DEV_UNMAP() \ +{ if (net_dev->base_addr) { \ + iounmap((void *)(net_dev->base_addr)); \ + release_mem_region(pci_resource_start(dev_p, 0), \ + pci_resource_len(dev_p, 0)); } \ + if (net_dev->irq) pci_release_regions(dev_p); } + + +#define PCI_REG_READ_WORD(pci_dev, offset, Configuration) \ + if (pci_read_config_word(pci_dev, offset, ®16) == 0) \ + Configuration = le2cpu16(reg16); \ + else \ + Configuration = 0; + +#define PCI_REG_WIRTE_WORD(pci_dev, offset, Configuration) \ + reg16 = cpu2le16(Configuration); \ + pci_write_config_word(pci_dev, offset, reg16); +#endif /* LINUX */ + +#endif /* __RTMP_PCI_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/rtmp_reg_pcirbs.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/rtmp_reg_pcirbs.h new file mode 100644 index 000000000..11fe6874d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/iface/rtmp_reg_pcirbs.h @@ -0,0 +1,456 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + rtmp_reg_pcirbus.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- +*/ + +#ifndef __RTMP_REG_PCIRBUS_H__ +#define __RTMP_REG_PCIRBUS_H__ + + +#ifdef RTMP_MAC_PCI + +// TODO: shiang, for RT3290, make sure following definition is correct to put as here + +#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; +#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; +#endif /* RT_BIG_ENDIAN */ + + +#define COEXCFG0 0x40 +#define COEXCFG0_COEX_EN (1 << 0) +#define COEXCFG0_FIX_WL_DI_ANT (1 << 1) +#define COEXCFG0_FIX_WL_ANT_EN (1 << 2) +#define COEXCFG0_FIX_WL_TX_PWR_MASK (0x3 << 6) +#define COEXCFG0_FIX_WL_GCRF_EN (1 << 8) +#define COEXCFG0_FIX_WL_RF_LNA0_MASK (0x3 << 12) +#define COEXCFG0_FIX_WL_RF_LNA1_MASK (0x3 << 14) +#define COEXCFG0_COEX_CFG0_MASK (0xff << 16) +#define COEXCFG0_COEX_CFG1_MASK (0xff << 24) + +#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; +#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; +#endif /* RT_BIG_ENDIAN */ + + +#define COEXCFG1 0x44 +#define COEXCFG1_DIS_WL_TR_DELAY_MASK (0xff << 0) +#define COEXCFG1_DIS_WL_PA_DELAY_MASK (0xff << 8) +#define COEXCFG1_DIS_WL_RF_DELAY_MASK (0xff << 16) +#define COEXCFG1_FIX_WL_TX_GCRF0_MASK (0xf << 24) +#define COEXCFG1_FIX_WL_TX_GCRF1_MASK (0xf << 28) + +#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; +#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; +#endif + + +#define COEXCFG2 0x48 +#define COEXCFG2_WL_COEX_CFG0_MASK (0xff << 0) +#define COEXCFG2_WL_COEX_CFG1_MASK (0xff << 8) +#define COEXCFG2_BT_COEX_CFG0_MASK (0xff << 16) +#define COEXCFG2_BT_COEX_CFG1_MASK (0xff << 24) + +#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; +#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; +#endif + + +#define COEXCFG3 0x004c +#define COEXCFG3_COEX_VER (1 << 0) +#define COEXCFG3_TDM_EN (1 << 1) +#define COEXCFG3_IO_TR_SW0_MODE (1 << 2) +#define COEXCFG3_CSR_FRC_TR_SW0 (1 << 3) +#define COEXCFG3_FIX_IO_ANT_SEL_EN (1 << 4) +#define COEXCFG3_REG_IO_ANT_SEL_EN (1 << 5) +#define COEXCFG3_PTA_CNT_CLEAR (1 << 6) +#define COEXCFG3_PTA_CNT_EN (1 << 7) +#define COEXCFG3_BT_TX_STATUS (1 << 16) + + +#define PLL_CTRL 0x50 +#ifdef RT_BIG_ENDIAN +typedef union _PLL_CTRL_STRUC { + struct { + UINT32 VBGBK_EN:1; + UINT32 LOCK_DETECT_WINDOW_CTRL:3; + UINT32 PFD_DELAY_CTRL:2; + UINT32 CP_CURRENT_CTRL:2; + UINT32 LPF_C2_CTRL:2; + UINT32 LPF_C1_CTRL:2; + UINT32 LPF_R1:1; + UINT32 VCO_FIXED_CURRENT_CONTROL:3; + UINT32 RESERVED_INPUT2:8; + UINT32 RESERVED_INPUT1:8; + } field; + UINT32 word; +} PLL_CTRL_STRUC; +#else +typedef union _PLL_CTRL_STRUC { + struct { + UINT32 RESERVED_INPUT1:8; + UINT32 RESERVED_INPUT2:8; + UINT32 VCO_FIXED_CURRENT_CONTROL:3; + UINT32 LPF_R1:1; + UINT32 LPF_C1_CTRL:2; + UINT32 LPF_C2_CTRL:2; + UINT32 CP_CURRENT_CTRL:2; + UINT32 PFD_DELAY_CTRL:2; + UINT32 LOCK_DETECT_WINDOW_CTRL:3; + UINT32 VBGBK_EN:1; + } field; + UINT32 word; +} PLL_CTRL_STRUC; +#endif /* RT_BIG_ENDIAN */ + + + +#if defined(RTMP_MAC) || defined(RLT_MAC) +/* INT_SOURCE_CSR: Interrupt source register. Write one to clear corresponding bit */ +#define INT_SOURCE_CSR 0x200 +/* INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF */ +#define INT_MASK_CSR 0x204 +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + +#if defined(RTMP_MAC) || defined(RLT_MAC) +#define WPDMA_GLO_CFG 0x208 +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ +#ifdef RT_BIG_ENDIAN +typedef union _WPDMA_GLO_CFG_STRUC { + struct { + UINT32 rx_2b_offset:1; + UINT32 clk_gate_dis:1; + UINT32 rsv:14; +#ifdef DESC_32B_SUPPORT + UINT32 RXHdrScater:7; + UINT32 Desc32BEn:1; +#else + UINT32 HDR_SEG_LEN:8; +#endif /* DESC_32B_SUPPORT */ + UINT32 BigEndian:1; + UINT32 EnTXWriteBackDDONE:1; + UINT32 WPDMABurstSIZE:2; + UINT32 RxDMABusy:1; + UINT32 EnableRxDMA:1; + UINT32 TxDMABusy:1; + UINT32 EnableTxDMA:1; + } field; + UINT32 word; +}WPDMA_GLO_CFG_STRUC; +#else +typedef union _WPDMA_GLO_CFG_STRUC { + struct { + UINT32 EnableTxDMA:1; + UINT32 TxDMABusy:1; + UINT32 EnableRxDMA:1; + UINT32 RxDMABusy:1; + UINT32 WPDMABurstSIZE:2; + UINT32 EnTXWriteBackDDONE:1; + UINT32 BigEndian:1; +#ifdef DESC_32B_SUPPORT + UINT32 Desc32BEn:1; + UINT32 RXHdrScater:7; +#else + UINT32 HDR_SEG_LEN:8; +#endif /* DESC_32B_SUPPORT */ + UINT32 rsv:14; + UINT32 clk_gate_dis:1; + UINT32 rx_2b_offset:1; + } field; + UINT32 word; +} WPDMA_GLO_CFG_STRUC; +#endif /* RT_BIG_ENDIAN */ + + +#if defined(RTMP_MAC) || defined(RLT_MAC) +#define WPDMA_RST_IDX 0x20c +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ +#ifdef RT_BIG_ENDIAN +typedef union _WPDMA_RST_IDX_STRUC { + struct { + UINT32 :14; + UINT32 RST_DRX_IDX1:1; + UINT32 RST_DRX_IDX0:1; + UINT32 rsv:2; + UINT32 RST_DTX_IDX13:1; + UINT32 RST_DTX_IDX12:1; + UINT32 RST_DTX_IDX11:1; + UINT32 RST_DTX_IDX10:1; + UINT32 RST_DTX_IDX9:1; + UINT32 RST_DTX_IDX8:1; + UINT32 RST_DTX_IDX7:1; + UINT32 RST_DTX_IDX6:1; + UINT32 RST_DTX_IDX5:1; + UINT32 RST_DTX_IDX4:1; + UINT32 RST_DTX_IDX3:1; + UINT32 RST_DTX_IDX2:1; + UINT32 RST_DTX_IDX1:1; + UINT32 RST_DTX_IDX0:1; + } field; + UINT32 word; +}WPDMA_RST_IDX_STRUC; +#else +typedef union _WPDMA_RST_IDX_STRUC { + struct { + UINT32 RST_DTX_IDX0:1; + UINT32 RST_DTX_IDX1:1; + UINT32 RST_DTX_IDX2:1; + UINT32 RST_DTX_IDX3:1; + UINT32 RST_DTX_IDX4:1; + UINT32 RST_DTX_IDX5:1; + UINT32 RST_DTX_IDX6:1; + UINT32 RST_DTX_IDX7:1; + UINT32 RST_DTX_IDX8:1; + UINT32 RST_DTX_IDX9:1; + UINT32 RST_DTX_IDX10:1; + UINT32 RST_DTX_IDX11:1; + UINT32 RST_DTX_IDX12:1; + UINT32 RST_DTX_IDX13:1; + UINT32 rsv:2; + UINT32 RST_DRX_IDX0:1; + UINT32 RST_DRX_IDX1:1; + UINT32 :14; + } field; + UINT32 word; +} WPDMA_RST_IDX_STRUC; +#endif /* RT_BIG_ENDIAN */ + + +#if defined(RTMP_MAC) || defined(RLT_MAC) +#define DELAY_INT_CFG 0x0210 +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ +#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; +#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; +#endif /* RT_BIG_ENDIAN */ + + +/* + 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 */ + + +#endif /* __RTMP_REG_PCIRBUS_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/igmp_snoop.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/igmp_snoop.h new file mode 100644 index 000000000..66ef69bd9 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/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 IP_UDP 0x11 +#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_IPV6_MULTICAST_MAC_ADDR(Addr) ((((Addr[0]) & 0x01) == 0x01) && ((Addr[0]) == 0x33)) + +#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(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_IgmpSn_AddEntry_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_IgmpSn_DelEntry_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_IgmpSn_TabDisplay_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +void rtmp_read_igmp_snoop_from_file( + IN PRTMP_ADAPTER pAd, + RTMP_STRING *tmpbuf, + RTMP_STRING *buffer); + +NDIS_STATUS IgmpPktInfoQuery( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSrcBufVA, + IN PNDIS_PACKET pPacket, + IN struct wifi_dev *wdev, + OUT INT *pInIgmpGroup, + OUT PMULTICAST_FILTER_TABLE_ENTRY *ppGroupEntry); + +NDIS_STATUS IgmpProtocolPktClone( + 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); + +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/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ipv6.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ipv6.h new file mode 100644 index 000000000..16c9b8ea9 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/ipv6.h @@ -0,0 +1,205 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + ipv6.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __IPV6_HDR_H_ +#define __IPV6_HDR_H_ + +#define IPV6_ADDR_LEN 16 +#define IPV6_HDR_LEN 40 + +/* IPv6 address definition */ +#define IPV6_LINK_LOCAL_ADDR_PREFIX 0xFE8 +#define IPV6_SITE_LOCAL_ADDR_PREFIX 0xFEC +#define IPV6_LOCAL_ADDR_PREFIX 0xFE8 +#define IPV6_MULTICAST_ADDR_PREFIX 0xFF +#define IPV6_LOOPBACK_ADDR 0x1 +#define IPV6_UNSPECIFIED_ADDR 0x0 + +/* defined as sequence in IPv6 header */ +#define IPV6_NEXT_HEADER_HOP_BY_HOP 0x00 /* 0 */ +#define IPV6_NEXT_HEADER_DESTINATION 0x3c /* 60 */ +#define IPV6_NEXT_HEADER_ROUTING 0x2b /* 43 */ +#define IPV6_NEXT_HEADER_FRAGMENT 0x2c /* 44 */ +#define IPV6_NEXT_HEADER_AUTHENTICATION 0x33 /* 51 */ +#define IPV6_NEXT_HEADER_ENCAPSULATION 0x32 /* 50, RFC-2406 */ +#define IPV6_NEXT_HEADER_NONE 0x3b /* 59 */ + +#define IPV6_NEXT_HEADER_TCP 0x06 +#define IPV6_NEXT_HEADER_UDP 0x11 +#define IPV6_NEXT_HEADER_ICMPV6 0x3a +#define IPV6_NEXT_HEADER_PIM 0x67 + +/* ICMPv6 msg type definition */ +#define ICMPV6_MSG_TYPE_ROUTER_SOLICITATION 0x85 /* 133 */ +#define ROUTER_SOLICITATION_FIXED_LEN 8 + +#define ICMPV6_MSG_TYPE_ROUTER_ADVERTISEMENT 0x86 /* 134 */ +#define ROUTER_ADVERTISEMENT_FIXED_LEN 16 + +#define ICMPV6_MSG_TYPE_NEIGHBOR_SOLICITATION 0x87 /* 135 */ +#define NEIGHBOR_SOLICITATION_FIXED_LEN 24 + +#define ICMPV6_MSG_TYPE_NEIGHBOR_ADVERTISEMENT 0x88 /* 136 */ +#define NEIGHBOR_ADVERTISEMENT_FIXED_LEN 24 + +#define ICMPV6_MSG_TYPE_REDIRECT 0x89 /* 137 */ +#define REDIRECT_FIXED_LEN 40 + +/* IPv6 Address related structures */ +typedef struct rt_ipv6_addr_ +{ + union + { + UCHAR ipv6Addr8[16]; + USHORT ipv6Addr16[8]; + UINT32 ipv6Addr32[4]; + }addr; +#define ipv6_addr addr.ipv6Addr8 +#define ipv6_addr16 addr.ipv6Addr16 +#define ipv6_addr32 addr.ipv6Addr32 +}RT_IPV6_ADDR, *PRT_IPV6_ADDR; + + +#define PRINT_IPV6_ADDR(ipv6Addr) \ + OS_NTOHS((ipv6Addr).ipv6_addr16[0]), \ + OS_NTOHS((ipv6Addr).ipv6_addr16[1]), \ + OS_NTOHS((ipv6Addr).ipv6_addr16[2]), \ + OS_NTOHS((ipv6Addr).ipv6_addr16[3]), \ + OS_NTOHS((ipv6Addr).ipv6_addr16[4]), \ + OS_NTOHS((ipv6Addr).ipv6_addr16[5]), \ + OS_NTOHS((ipv6Addr).ipv6_addr16[6]), \ + OS_NTOHS((ipv6Addr).ipv6_addr16[7]) + + +/*IPv6 Header related structures */ +typedef struct GNU_PACKED _rt_ipv6_hdr_ +{ + UINT32 ver:4, + trafficClass:8, + flowLabel:20; + USHORT payload_len; + UCHAR nextHdr; + UCHAR hopLimit; + RT_IPV6_ADDR srcAddr; + RT_IPV6_ADDR dstAddr; +}RT_IPV6_HDR, *PRT_IPV6_HDR; + + +typedef struct GNU_PACKED _rt_ipv6_ext_hdr_ +{ + UCHAR nextProto; /* Indicate the protocol type of next extension header. */ + UCHAR extHdrLen; /* optional field for msg length of this extension header which didn't include the first "nextProto" field. */ + UCHAR octets[1]; /* hook to extend header message body. */ +}RT_IPV6_EXT_HDR, *PRT_IPV6_EXT_HDR; + + +/* ICMPv6 related structures */ +typedef struct GNU_PACKED _rt_ipv6_icmpv6_hdr_ +{ + UCHAR type; + UCHAR code; + USHORT chksum; + UCHAR octets[1]; /*hook to extend header message body. */ +}RT_ICMPV6_HDR, *PRT_ICMPV6_HDR; + + +typedef struct GNU_PACKED _rt_icmp6_option_hdr_ +{ + UCHAR type; + UCHAR len; + UCHAR octet[1]; +}RT_ICMPV6_OPTION_HDR, *PRT_ICMPV6_OPTION_HDR; + +typedef enum{ +/* Defined ICMPv6 Option Types. */ + TYPE_SRC_LL_ADDR = 1, + TYPE_TGT_LL_ADDR = 2, + TYPE_PREFIX_INFO = 3, + TYPE_REDIRECTED_HDR = 4, + TYPE_MTU = 5, +}ICMPV6_OPTIONS_TYPE_DEF; + + +static inline BOOLEAN IPv6ExtHdrHandle( + RT_IPV6_EXT_HDR *pExtHdr, + UCHAR *pProto, + UINT32 *pOffset) +{ + UCHAR nextProto = 0xff; + UINT32 extLen = 0; + BOOLEAN status = TRUE; + + /*printk("%s(): parsing the Extension Header with Protocol(0x%x):\n", __FUNCTION__, *pProto); */ + switch (*pProto) + { + case IPV6_NEXT_HEADER_HOP_BY_HOP: + /* IPv6ExtHopByHopHandle(); */ + nextProto = pExtHdr->nextProto; + extLen = (pExtHdr->extHdrLen + 1) * 8; + break; + + case IPV6_NEXT_HEADER_DESTINATION: + /* IPv6ExtDestHandle(); */ + nextProto = pExtHdr->nextProto; + extLen = (pExtHdr->extHdrLen + 1) * 8; + break; + + case IPV6_NEXT_HEADER_ROUTING: + /* IPv6ExtRoutingHandle(); */ + nextProto = pExtHdr->nextProto; + extLen = (pExtHdr->extHdrLen + 1) * 8; + break; + + case IPV6_NEXT_HEADER_FRAGMENT: + /* IPv6ExtFragmentHandle(); */ + nextProto = pExtHdr->nextProto; + extLen = 8; /* The Fragment header length is fixed to 8 bytes. */ + break; + + case IPV6_NEXT_HEADER_AUTHENTICATION: + /* IPV6_NEXT_HEADER_ENCAPSULATION: */ + /* + TODO: Not support. For encryption issue. + */ + nextProto = 0xFF; + status = FALSE; + break; + + default: + nextProto = 0xFF; + status = FALSE; + break; + } + + *pProto = nextProto; + *pOffset += extLen; + /*printk("%s(): nextProto = 0x%x!, offset=0x%x!\n", __FUNCTION__, nextProto, offset); */ + + return status; + +} + +#endif /* __IPV6_HDR_H_ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/link_list.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/link_list.h new file mode 100644 index 000000000..f0440f79c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/link_list.h @@ -0,0 +1,174 @@ + +#ifndef __LINK_LIST_H__ +#define __LINK_LIST_H__ + +typedef struct _RT_LIST_ENTRY +{ + struct _RT_LIST_ENTRY *pNext; +} RT_LIST_ENTRY; + +typedef struct _LIST_HEADER +{ + RT_LIST_ENTRY *pHead; + RT_LIST_ENTRY *pTail; + UCHAR size; +} LIST_HEADER, *PLIST_HEADER; + +static inline void initList(LIST_HEADER *pList) +{ + pList->pHead = pList->pTail = NULL; + pList->size = 0; + return; +} + +static inline void insertTailList(LIST_HEADER *pList, RT_LIST_ENTRY *pEntry) +{ + pEntry->pNext = NULL; + if (pList->pTail) + pList->pTail->pNext = pEntry; + else + pList->pHead = pEntry; + pList->pTail = pEntry; + pList->size++; + + return; +} + +static inline RT_LIST_ENTRY *removeHeadList(LIST_HEADER *pList) +{ + RT_LIST_ENTRY *pNext; + RT_LIST_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(LIST_HEADER *pList) +{ + return pList->size; +} + +static inline RT_LIST_ENTRY *delEntryList(LIST_HEADER *pList, RT_LIST_ENTRY *pEntry) +{ + RT_LIST_ENTRY *pCurEntry; + RT_LIST_ENTRY *pPrvEntry; + + if(pList->pHead == NULL) + return NULL; + + if(pEntry == pList->pHead) + { + pCurEntry = pList->pHead; + pList->pHead = pCurEntry->pNext; + + if(pList->pHead == NULL) + pList->pTail = NULL; + + pList->size--; + return pCurEntry; + } + + pPrvEntry = pList->pHead; + pCurEntry = pPrvEntry->pNext; + while(pCurEntry != NULL) + { + if (pEntry == pCurEntry) + { + pPrvEntry->pNext = pCurEntry->pNext; + + if(pEntry == pList->pTail) + pList->pTail = pPrvEntry; + + pList->size--; + break; + } + pPrvEntry = pCurEntry; + pCurEntry = pPrvEntry->pNext; + } + + return pCurEntry; +} + + +typedef struct _DL_LIST +{ + struct _DL_LIST *Next; + struct _DL_LIST *Prev; +}DL_LIST, *PDL_LIST; + +static inline void DlListInit(struct _DL_LIST *List) +{ + List->Next = List; + List->Prev = List; +} + +static inline void DlListAdd(struct _DL_LIST *List, struct _DL_LIST *Item) +{ + Item->Next = List->Next; + Item->Prev = List; + List->Next->Prev = Item; + List->Next = Item; +} + +static inline void DlListAddTail(struct _DL_LIST *List, struct _DL_LIST *Item) +{ + DlListAdd(List->Prev, Item); +} + +static inline void DlListDel(struct _DL_LIST *Item) +{ + Item->Next->Prev = Item->Prev; + Item->Prev->Next = Item->Next; + Item->Next = NULL; + Item->Prev = NULL; +} + +static inline int DlListEmpty(struct _DL_LIST *List) +{ + return List->Next == List; +} + +static inline unsigned int DlListLen(struct _DL_LIST *List) +{ + struct _DL_LIST *Item; + unsigned int Count = 0; + + for (Item = List->Next; Item != List; Item = Item->Next) + Count++; + + return Count; +} + + +#ifndef Offsetof +#define Offsetof(type, member) ((long) &((type *) 0)->member) +#endif + +#define DlListEntry(item, type, member) \ + ((type *) ((char *) item - offsetof(type, member))) + +#define DlListFirst(list, type, member) \ + (DlListEmpty((list)) ? NULL : \ + DlListEntry((list)->Next, type, member)) + +#define DlListForEach(item, list, type, member) \ + for (item = DlListEntry((list)->Next, type, member); \ + &item->member != (list); \ + item = DlListEntry(item->member.Next, type, member)) + +#define DlListForEachSafe(item, n, list, type, member) \ + for (item = DlListEntry((list)->Next, type, member), \ + n = DlListEntry(item->member.Next, type, member); \ + &item->member != (list); \ + item = n, n = DlListEntry(n->member.Next, type, member)) + +#endif /* ___LINK_LIST_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac.h new file mode 100644 index 000000000..0dd885ca5 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac.h @@ -0,0 +1,177 @@ +/* + *************************************************************************** + * 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: + mac.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifndef __MAC_H__ +#define __MAC_H__ + +#ifdef MT_MAC +#include "mac/mac_mt/mt_mac.h" +#endif /* MT_MAC */ + +#if defined(RTMP_MAC) || defined(RLT_MAC) +#include "mac/mac_ral/pbf.h" +#include "mac/mac_ral/rf_ctrl.h" +#include "mac/mac_ral/rtmp_mac.h" +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + + +#define TXINFO_SIZE 4 +typedef union GNU_PACKED _TXINFO_STRUC{ +#ifdef RTMP_MAC + struct _TXINFO_OMAC txinfo_omac; +#endif /* RTMP_MAC */ +#ifdef RLT_MAC + struct _TXINFO_NMAC_PKT txinfo_nmac_pkt; + struct _TXINFO_NMAC_CMD txinfo_nmac_cmd; +#endif /* RLT_MAC */ + UINT32 word; +}TXINFO_STRUC; + +#define SHORT_PREAMBLE 0 +#define LONG_PREAMBLE 1 + +/* + bit31 =>802.3 if set 1, implay you hav did header translation + bit30 => put VLAN field + +*/ +#define RAL_RXINFO_SIZE 4 +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXINFO_STRUC { + UINT32 hdr_trans_ip_sum_err:1; /* IP checksum error */ + UINT32 vlan_taged_tcp_sum_err:1; /* TCP checksum error */ + UINT32 rsv:1; + UINT32 action_wanted:1; + UINT32 deauth:1; + UINT32 disasso:1; + UINT32 beacon:1; + UINT32 probe_rsp:1; + UINT32 sw_fc_type1:1; + UINT32 sw_fc_type0:1; + UINT32 pn_len:3; + UINT32 wapi_kidx:1; + UINT32 BssIdx3:1; + UINT32 Decrypted:1; + UINT32 AMPDU:1; + UINT32 L2PAD:1; + UINT32 RSSI:1; + UINT32 HTC:1; + UINT32 AMSDU:1; /* rx with 802.3 header, not 802.11 header. obsolete. */ + UINT32 CipherErr:2; /* 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid */ + UINT32 Crc:1; /* 1: CRC error */ + UINT32 MyBss:1; /* 1: this frame belongs to the same BSSID */ + UINT32 Bcast:1; /* 1: this is a broadcast frame */ + UINT32 Mcast:1; /* 1: this is a multicast frame */ + UINT32 U2M:1; /* 1: this RX frame is unicast to me */ + UINT32 FRAG:1; + UINT32 NULLDATA:1; + UINT32 DATA:1; + UINT32 BA:1; +} RXINFO_STRUC; +#else +typedef struct GNU_PACKED _RXINFO_STRUC { + UINT32 BA:1; + UINT32 DATA:1; + UINT32 NULLDATA:1; + UINT32 FRAG:1; + UINT32 U2M:1; + UINT32 Mcast:1; + UINT32 Bcast:1; + UINT32 MyBss:1; + UINT32 Crc:1; + UINT32 CipherErr:2; + UINT32 AMSDU:1; + UINT32 HTC:1; + UINT32 RSSI:1; + UINT32 L2PAD:1; + UINT32 AMPDU:1; + UINT32 Decrypted:1; + UINT32 BssIdx3:1; + UINT32 wapi_kidx:1; + UINT32 pn_len:3; + UINT32 sw_fc_type0:1; + UINT32 sw_fc_type1:1; + UINT32 probe_rsp:1; + UINT32 beacon:1; + UINT32 disasso:1; + UINT32 deauth:1; + UINT32 action_wanted:1; + UINT32 rsv:1; + UINT32 vlan_taged_tcp_sum_err:1; + UINT32 hdr_trans_ip_sum_err:1; +}RXINFO_STRUC; +#endif + + +typedef struct _MAC_TX_INFO{ + UCHAR WCID; + BOOLEAN FRAG; + BOOLEAN InsTimestamp; + BOOLEAN NSeq; + BOOLEAN Ack; + BOOLEAN BM; + BOOLEAN CFACK; + BOOLEAN AMPDU; + UCHAR BASize; + UCHAR PID; + UCHAR TID; + UCHAR TxRate; + UCHAR Txopmode; + ULONG Length; + UCHAR hdr_len; + UCHAR hdr_pad; + UCHAR eth_type_offset; + UCHAR bss_idx; + UCHAR q_idx; + UCHAR prot; + UCHAR AntPri; + UCHAR SpeEn; + UCHAR Preamble; +#ifdef MT_MAC + UINT32 TxSPriv; + UCHAR PsmBySw; /* PSM bit controlled by SW */ +#endif /* MT_MAC */ +}MAC_TX_INFO; + + +struct _RTMP_ADAPTER; +#ifdef DBG +VOID dump_txinfo(struct _RTMP_ADAPTER *pAd, TXINFO_STRUC *pTxInfo); +VOID dump_rxinfo(struct _RTMP_ADAPTER *pAd, RXINFO_STRUC *pRxInfo); + +VOID dump_tmac_info(struct _RTMP_ADAPTER *pAd, UCHAR *tmac_info); +VOID dump_rmac_info(struct _RTMP_ADAPTER *pAd, UCHAR *rmac_info); + +#ifdef RTMP_PCI_SUPPORT +VOID dump_txd(struct _RTMP_ADAPTER *pAd, struct _TXD_STRUC *pTxD); +VOID dump_rxd(struct _RTMP_ADAPTER *pAd, struct _RXD_STRUC *pRxD); +#endif +#endif /* DBG */ +#endif /* __MAC_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/client.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/client.h new file mode 100644 index 000000000..f48089723 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/client.h @@ -0,0 +1,33 @@ +/* + *************************************************************************** + * 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: + client.h +*/ + +#ifndef __CLIENT_H__ +#define __CLIENT_H__ + +#define CLIENT_BASE 0x800C0000 +#define RXINF (CLIENT_BASE + 0x0068) +#define RXSH_GROUP1_EN (1 << 0) +#define RXSH_GROUP2_EN (1 << 1) +#define RXSH_GROUP3_EN (1 << 2) + +#define RST (CLIENT_BASE + 0x0070) +#define TX_R_E_1 (1 << 16) +#define TX_R_E_2 (1 << 17) +#define TX_R_E_1_S (1 << 20) +#define TX_R_E_2_S (1 << 21) + +#endif + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/gpio.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/gpio.h new file mode 100644 index 000000000..ce90f1ed6 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/gpio.h @@ -0,0 +1,127 @@ +/* + *************************************************************************** + * 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: + gpio.h +*/ + +#ifndef __GPIO_H__ +#define __GPIO_H__ + +#define GPIO_BASE 0x80023000 +#define GPIO_PU1 (GPIO_BASE + 0x00) +#define GPIO_PU1_SET (GPIO_BASE +0x04) +#define GPIO_PU1_RESET (GPIO_BASE + 0x8) +#define GPIO_PD1 (GPIO_BASE + 0x10) +#define GPIO_PD1_SET (GPIO_BASE + 0x14) +#define GPIO_PD1_RESET (GPIO_BASE + 0x18) +#define GPIO_DOUT1 (GPIO_BASE + 0x20) +#define GPIO_DOUT1_SET (GPIO_BASE + 0x24) +#define GPIO_DOUT1_RESET (GPIO_BASE + 0x28) +#define GPIO_OE1 (GPIO_BASE + 0x30) +#define GPIO_OE1_SET (GPIO_BASE + 0x34) +#define GPIO_OE1_RESET (GPIO_BASE + 0x38) +#define GPIO_DIN1 (GPIO_BASE + 0x40) +#define PINMUX_SEL1 (GPIO_BASE + 0x80) +#define PINMUX_SEL2 (GPIO_BASE + 0x84) +#define PINMUX_SEL3 (GPIO_BASE + 0X88) + +#define GPIO0_SEL_MASK (0x7) +#define GPIO0_SEL(p) (((p) & 0x7)) +#define GPIO0_SEL_VALUE 0x0 +#define GPIO1_SEL_MASK (0x7 << 4) +#define GPIO1_SEL(p) (((p) & 0x7) << 4) +#define GPIO1_SEL_VALUE 0x2 +#define GPIO2_SEL_MASK (0x7 << 8) +#define GPIO2_SEL(p) (((p) & 0x7) << 8) +#define GPIO2_SEL_VALUE 0x2 +#define GPIO3_SEL_MASK (0x7 << 12) +#define GPIO3_SEL(p) (((p) & 0x7) << 12) +#define GPIO3_SEL_VALUE 0x2 +#define GPIO4_SEL_MASK (0x7 << 16) +#define GPIO4_SEL(p) (((p) & 0x7) << 16) +#define GPIO4_SEL_VALUE 0x2 +#define GPIO5_SEL_MASK (0x7 << 20) +#define GPIO5_SEL(p) (((p) & 0x7) << 20) +#define GPIO5_SEL_VALUE 0x2 +#define GPIO6_SEL_MASK (0x7 << 24) +#define GPIO6_SEL(p) (((p) & 0x7) << 24) +#define GPIO6_SEL_VALUE 0x0 +#define GPIO7_SEL_MASK (0x7 << 28) +#define GPIO7_SEL(p) (((p) & 0x7) << 28) +#define GPIO7_SEL_VALUE 0x0 +#define GPIO8_SEL_MASK (0x7) +#define GPIO8_SEL(p) (((p) & 0x7)) +#define GPIO8_SEL_VALUE 0x0 +#define GPIO9_SEL_MASK (0x7 << 4) +#define GPIO9_SEL(p) (((p) & 0x7) << 4) +#define GPIO9_SEL_VALUE 0x0 +#define GPIO10_SEL_MASK (0x7 << 8) +#define GPIO10_SEL(p) (((p) & 0x7) << 8) +#define GPIO10_SEL_VALUE 0x0 +#define GPIO11_SEL_MASK (0x7 << 12) +#define GPIO11_SEL(p) (((p) & 0x7) << 12) +#define GPIO11_SEL_VALUE 0x2 +#define GPIO12_SEL_MASK (0x7 << 16) +#define GPIO12_SEL(p) (((p) & 0x7) << 16) +#define GPIO12_SEL_VALUE 0x2 +#define GPIO13_SEL_MASK (0x7 << 20) +#define GPIO13_SEL(p) (((p) & 0x7) << 20) +#define GPIO13_SEL_VALUE 0x2 +#define GPIO14_SEL_MASK (0x7 << 24) +#define GPIO14_SEL(p) (((p) & 0x7) << 24) +#define GPIO14_SEL_VALUE 0x2 +#define GPIO15_SEL_MASK (0x7 << 28) +#define GPIO15_SEL(p) (((p) & 0x7) << 28) +#define GPIO15_SEL_VALUE 0x2 +#define GPIO16_SEL_MASK (0x7) +#define GPIO16_SEL(p) (((p) & 0x7)) +#define GPIO16_SEL_VALUE 0x2 + +#define OUTPUT_HIGH 1 +#define OUTPUT_LOW 0 +#define INPUT_HIGH 1 +#define INPUT_LOW 0 +#define GPIO_OUTPUT 1 +#define GPIO_INPUT 0 +#define PULL_UP 1 +#define NO_PULL_UP 0 +#define PULL_DOWN 1 +#define NO_PULL_DOWN 0 + +#define GPIO0 0 +#define GPIO1 1 +#define GPIO2 2 +#define GPIO3 3 +#define GPIO4 4 +#define GPIO5 5 +#define GPIO6 6 +#define GPIO7 7 +#define GPIO8 8 +#define GPIO9 9 +#define GPIO10 10 +#define GPIO11 11 +#define GPIO12 12 +#define GPIO13 13 +#define GPIO14 14 +#define GPIO15 15 +#define GPIO16 16 + +INT32 GPIODirectionInput(struct _RTMP_ADAPTER *pAd, UINT32 GPIO); +INT32 GPIODirectionOuput(struct _RTMP_ADAPTER *pAd, UINT32 GPIO, UINT8 Value); +UINT32 GPIOGetValue(struct _RTMP_ADAPTER *pAd, UINT32 GPIO); +VOID GPIOSetValue(struct _RTMP_ADAPTER *pAd, UINT32 GPIO, UINT8 Value); +UINT32 GPIOGetMode(struct _RTMP_ADAPTER *pAd, UINT32 GPIO); +INT32 GPIOPullUp(struct _RTMP_ADAPTER *pAd, UINT32 GPIO, UINT8 Value); +INT32 GPIOPullDown(struct _RTMP_ADAPTER *pAd, UINT32 GPIO, UINT8 Value); + +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/mt_mac.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/mt_mac.h new file mode 100644 index 000000000..30de2ef29 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/mt_mac.h @@ -0,0 +1,1734 @@ +/* + *************************************************************************** + * 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: + mt_mac.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __MT_MAC_H__ +#define __MT_MAC_H__ + +#include "mac/mac_mt/top.h" +#include "mac/mac_mt/gpio.h" +#include "mac/mac_mt/wf_agg.h" +#include "mac/mac_mt/wf_aon.h" +#include "mac/mac_mt/wf_arb.h" +#include "mac/mac_mt/wf_cfgoff.h" +#include "mac/mac_mt/wf_dma.h" +#include "mac/mac_mt/wf_lpon_top.h" +#include "mac/mac_mt/wf_mib.h" +#include "mac/mac_mt/wf_pf.h" +#include "mac/mac_mt/wf_rmac.h" +#include "mac/mac_mt/wf_sec.h" +#include "mac/mac_mt/wf_tmac.h" +#include "mac/mac_mt/wf_trb.h" +#include "mac/mac_mt/wf_wtbloff.h" +#include "mac/mac_mt/wf_wtblon.h" +#include "mac/mac_mt/wf_int_wakeup_top.h" +#include "mac/mac_mt/client.h" +#include "mac/mac_mt/wf_wtbl.h" +#include "mac/mac_mt/wf_phy.h" +#include "mac/mac_mt/pse.h" +#ifdef RTMP_MAC_PCI +#include "mac/mac_mt/mt_mac_pci.h" +#endif /* RTMP_MAC_PCI */ + + + + +/* + TX / RX descriptor format + + TX: + PCI/RBUS_DMA_Descriptor + TXD + 802.11 + + Rx: + PCI/RBUS/USB_DMA_Descripotr + RXD + 802.11 + RX_CSO_INFO +*/ + +/* 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 + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED tmac_txd_0 { + /* DWORD 0 */ + UINT32 p_idx:1; /* P_IDX_XXX */ + UINT32 q_idx:4; /* Q_IDX_XXX */ + UINT32 UTxB:1; + UINT32 UNxV:1; + UINT32 ut_sum:1; + UINT32 ip_sum:1; + UINT32 eth_type_offset:7; + UINT32 tx_byte_cnt:16; +} TMAC_TXD_0; +#else +typedef struct GNU_PACKED tmac_txd_0 { + /* DWORD 0 */ + UINT32 tx_byte_cnt:16; /* in unit of bytes */ + UINT32 eth_type_offset:7; /* in unit of WORD(2 bytes) */ + UINT32 ip_sum:1; + UINT32 ut_sum:1; + UINT32 UNxV:1; + UINT32 UTxB:1; + UINT32 q_idx:4; /* Q_IDX_XXX */ + UINT32 p_idx:1; /* P_IDX_XXX */ +} TMAC_TXD_0; +#endif + +/* TMAC_TXD_0.p_idx */ +#define P_IDX_LMAC 0 +#define P_IDX_MCU 1 + +/* TMAC_TXD_0.q_idx */ +#define Q_IDX_AC0 0x00 +#define Q_IDX_AC1 0x01 +#define Q_IDX_AC2 0x02 +#define Q_IDX_AC3 0x03 +#define Q_IDX_AC4 0x04 +#define Q_IDX_AC5 0x05 +#define Q_IDX_AC6 0x06 +#define Q_IDX_BCN 0x07 +#define Q_IDX_BMC 0x08 +#define Q_IDX_AC10 0x09 +#define Q_IDX_AC11 0x0a +#define Q_IDX_AC12 0x0b +#define Q_IDX_AC13 0x0c +#define Q_IDX_AC14 0x0d + +#define Q_IDX_RQ0 0x00 +#define Q_IDX_RQ1 0x01 +#define Q_IDX_RQ2 0x02 +#define Q_IDX_RQ3 0x03 + +/* TMAC_TXD_0.p_idx + TMAC_TXD_0.q_idx */ +#define PQ_IDX_LMAC_AC0 (P_IDX_LMAC << 4) | (Q_IDX_AC0) +#define PQ_IDX_LMAC_AC1 (P_IDX_LMAC << 4) | (Q_IDX_AC1) +#define PQ_IDX_LMAC_AC2 (P_IDX_LMAC << 4) | (Q_IDX_AC2) +#define PQ_IDX_LMAC_AC3 (P_IDX_LMAC << 4) | (Q_IDX_AC3) +#define PQ_IDX_LMAC_AC4 (P_IDX_LMAC << 4) | (Q_IDX_AC4) +#define PQ_IDX_LMAC_AC5 (P_IDX_LMAC << 4) | (Q_IDX_AC5) +#define PQ_IDX_LMAC_AC6 (P_IDX_LMAC << 4) | (Q_IDX_AC6) +#define PQ_IDX_LMAC_BCN (P_IDX_LMAC << 4) | (Q_IDX_BCN) +#define PQ_IDX_LMAC_BMC (P_IDX_LMAC << 4) | (Q_IDX_BMC) +#define PQ_IDX_LMAC_AC10 (P_IDX_LMAC << 4) | (Q_IDX_AC10) +#define PQ_IDX_LMAC_AC11 (P_IDX_LMAC << 4) | (Q_IDX_AC11) +#define PQ_IDX_LMAC_AC12 (P_IDX_LMAC << 4) | (Q_IDX_AC12) +#define PQ_IDX_LMAC_AC13 (P_IDX_LMAC << 4) | (Q_IDX_AC13) +#define PQ_IDX_LMAC_AC14 (P_IDX_LMAC << 4) | (Q_IDX_AC14) + +#define PQ_IDX_MCU_RQ0 (P_IDX_MCU << 4) | (Q_IDX_RQ0) +#define PQ_IDX_MCU_RQ1 (P_IDX_MCU << 4) | (Q_IDX_RQ1) +#define PQ_IDX_MCU_RQ2 (P_IDX_MCU << 4) | (Q_IDX_RQ2) +#define PQ_IDX_MCU_RQ3 (P_IDX_MCU << 4) | (Q_IDX_RQ3) + +#ifdef MAC_REPEATER_SUPPORT +#define MAX_EXT_MAC_ADDR_SIZE 16 +//TODO: Carter, single driver case? +#endif /* MAC_REPEATER_SUPPORT */ + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED tmac_txd_1 { + /* DWORD 1 */ + UINT32 own_mac:6; + UINT32 rsv_1_24:2; + UINT32 protect_frm:1; + UINT32 tid:3; + UINT32 no_ack:1; + UINT32 hdr_pad:3; + UINT32 ft:1; /* TMI_FT_XXXX */ + UINT32 hdr_format:2; /* TMI_HDR_FT_XXX */ + UINT32 hdr_info:5; /* in unit of WORD(2 bytes) */ + UINT32 wlan_idx:8; +} TMAC_TXD_1; +#else +typedef struct GNU_PACKED tmac_txd_1 { + /* DWORD 1 */ + UINT32 wlan_idx:8; + UINT32 hdr_info:5; /* in unit of WORD(2 bytes) */ + UINT32 hdr_format:2; /* TMI_HDR_FT_XXX */ + UINT32 ft:1; /* TMI_FT_XXXX */ + UINT32 hdr_pad:3; + UINT32 no_ack:1; + UINT32 tid:3; + UINT32 protect_frm:1; + UINT32 rsv_1_24:2; + UINT32 own_mac:6; +} TMAC_TXD_1; +#endif + +/* TMAC_TXD_1.hdr_format */ +#define TMI_HDR_FT_NON_80211 0x0 +#define TMI_HDR_FT_CMD 0x1 +#define TMI_HDR_FT_NOR_80211 0x2 +#define TMI_HDR_FT_ENH_80211 0x3 + +/* + TMAC_TXD_1.hdr_info +*/ +/* if TMAC_TXD_1.hdr_format == HDR_FORMAT_NON_80211 */ +#define TMI_HDR_INFO_0_BIT_MRD 0 +#define TMI_HDR_INFO_0_BIT_EOSP 1 +#define TMI_HDR_INFO_0_BIT_RMVL 2 +#define TMI_HDR_INFO_0_BIT_VLAN 3 +#define TMI_HDR_INFO_0_BIT_ETYP 4 +#define TMI_HDR_INFO_0_VAL(_mrd, _eosp, _rmvl, _vlan, _etyp) \ + ((((_mrd) ? 1 : 0) << TMI_HDR_INFO_0_BIT_MRD) | \ + (((_eosp) ? 1 : 0) << TMI_HDR_INFO_0_BIT_EOSP) |\ + (((_rmvl) ? 1 : 0) << TMI_HDR_INFO_0_BIT_RMVL) |\ + (((_vlan) ? 1 : 0) << TMI_HDR_INFO_0_BIT_VLAN) |\ + (((_etyp) ? 1 : 0) << TMI_HDR_INFO_0_BIT_ETYP)) + + +/* if TMAC_TXD_1.hdr_format == HDR_FORMAT_CMD */ +#define TMI_HDR_INFO_1_MASK_RSV (0x1f) +#define TMI_HDR_INFO_1_VAL 0 + +/* if TMAC_TXD_1.hdr_format == HDR_FORMAT_NOR_80211 */ +#define TMI_HDR_INFO_2_MASK_LEN (0x1f) +#define TMI_HDR_INFO_2_VAL(_len) (_len >> 1) + +/* if TMAC_TXD_1.hdr_format == HDR_FORMAT_ENH_80211 */ +#define TMI_HDR_INFO_3_BIT_EOSP 1 +#define TMI_HDR_INFO_3_BIT_AMS 2 +#define TMI_HDR_INFO_3_VAL(_eosp, _ams) \ + ((((_eosp) ? 1 : 0) << TMI_HDR_INFO_3_BIT_EOSP) | \ + (((_ams) ? 1 : 0) << TMI_HDR_INFO_3_BIT_AMS)) + +#define TMI_HDR_INFO_VAL(_fmt, _mrd, _eosp, _rmvl, _vlan, _etype, _len, _ams, _val) \ + do{\ + switch (_fmt) {\ + case TMI_HDR_FT_NON_80211:\ + (_val) = TMI_HDR_INFO_0_VAL((_mrd), (_eosp), (_rmvl), (_vlan), (_etype));\ + break;\ + case TMI_HDR_FT_CMD:\ + (_val) = TMI_HDR_INFO_1_VAL;\ + break;\ + case TMI_HDR_FT_NOR_80211:\ + ASSERT((((_len) & 1) == 0));\ + (_val) = TMI_HDR_INFO_2_VAL((_len));\ + break;\ + case TMI_HDR_FT_ENH_80211:\ + (_val) = TMI_HDR_INFO_3_VAL((_eosp), (_ams));\ + default:\ + (_val) = 0;\ + }\ + }while(0) + + +/* TMAC_TXD_1.ft */ +#define TMI_FT_SHORT 0 +#define TMI_FT_LONG 1 + + +/* TMAC_TXD_1.hdr_pad */ +#define TMI_HDR_PAD_BIT_MODE 2 +#define TMI_HDR_PAD_MODE_TAIL 0 +#define TMI_HDR_PAD_MODE_HEAD 1 +#define TMI_HDR_PAD_BIT_LEN 0 +#define TMI_HDR_PAD_MASK_LEN 0x3 + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED tmac_txd_2 { + /* DWORD 2 */ + UINT32 fix_rate:1; + UINT32 timing_measure:1; + UINT32 ba_disable:1; + UINT32 pwr_offset:5; + UINT32 max_tx_time:8; + UINT32 frag:2; + UINT32 htc_vld:1; + UINT32 duration:1; + UINT32 bip:1; + UINT32 bc_mc_pkt:1; + UINT32 rts:1; + UINT32 sounding:1; + UINT32 ndpa:1; + UINT32 ndp:1; + UINT32 frm_type:2; + UINT32 sub_type:4; +} TMAC_TXD_2; +#else +typedef struct GNU_PACKED tmac_txd_2 { + /* DWORD 2 */ + UINT32 sub_type:4; + UINT32 frm_type:2; + UINT32 ndp:1; + UINT32 ndpa:1; + UINT32 sounding:1; + UINT32 rts:1; + UINT32 bc_mc_pkt:1; + UINT32 bip:1; + UINT32 duration:1; + UINT32 htc_vld:1; + UINT32 frag:2; + UINT32 max_tx_time:8; + UINT32 pwr_offset:5; + UINT32 ba_disable:1; + UINT32 timing_measure:1; + UINT32 fix_rate:1; +} TMAC_TXD_2; +#endif + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED tmac_txd_3 { + /* DWORD 3 */ + UINT32 sn_vld:1; + UINT32 pn_vld:1; + UINT32 rsv3_28:2; + UINT32 sn:12; + UINT32 remain_tx_cnt:5; + UINT32 tx_cnt:5; + UINT32 rsv3_0:6; +} TMAC_TXD_3; +#else +typedef struct GNU_PACKED tmac_txd_3 { + /* DWORD 3 */ + UINT32 rsv3_0:6; + UINT32 tx_cnt:5; + UINT32 remain_tx_cnt:5; + UINT32 sn:12; + UINT32 rsv3_28:2; + UINT32 pn_vld:1; + UINT32 sn_vld:1; +} TMAC_TXD_3; +#endif + +typedef struct GNU_PACKED tmac_txd_4 { + /* DWORD 4 */ + UINT32 pn_low; +} TMAC_TXD_4; + + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED tmac_txd_5 { + /* DWORD 5 */ + UINT32 pn_high:16; + UINT32 rsv5_14:2; + UINT32 pwr_mgmt:1; + UINT32 bar_sn_ctrl:1; + UINT32 da_select:1; + UINT32 tx_status_2_host:1; + UINT32 tx_status_2_mcu:1; + UINT32 tx_status_fmt:1; + UINT32 pid:8; +} TMAC_TXD_5; +#else +typedef struct GNU_PACKED tmac_txd_5 { + /* DWORD 5 */ + UINT32 pid:8; + UINT32 tx_status_fmt:1; + UINT32 tx_status_2_mcu:1; + UINT32 tx_status_2_host:1; + UINT32 da_select:1; + UINT32 bar_sn_ctrl:1; + UINT32 pwr_mgmt:1; + UINT32 rsv5_14:2; + UINT32 pn_high:16; +} TMAC_TXD_5; +#endif + +/* TMAC_TXD_5.da_select */ +#define TMI_DAS_FROM_MPDU 0 +#define TMI_DAS_FROM_WTBL 1 + +/* TMAC_TXD_5.bar_sn_ctrl */ +#define TMI_BSN_CFG_BY_HW 0 +#define TMI_BSN_CFG_BY_SW 1 + +/* TMAC_TXD_5.pwr_mgmt */ +#define TMI_PM_BIT_CFG_BY_HW 0 +#define TMI_PM_BIT_CFG_BY_SW 1 + + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED tmac_txd_6 { + /* DWORD 6 */ + UINT32 gi:1; + UINT32 ldpc:1; + UINT32 tx_rate:12; + UINT32 ITxBF:1; + UINT32 ETxBF:1; + UINT32 dyn_bw:1; + UINT32 ant_pri:3; + UINT32 spe_en:1; + UINT32 bw:3; + UINT32 ant_id:6; + UINT32 rsv_6_1:1; + UINT32 fix_rate_mode:1; +} TMAC_TXD_6; +#else +typedef struct GNU_PACKED tmac_txd_6 { + /* DWORD 6 */ + UINT32 fix_rate_mode:1; + UINT32 rsv_6_1:1; + UINT32 ant_id:6; + UINT32 bw:3; + UINT32 spe_en:1; + UINT32 ant_pri:3; + UINT32 dyn_bw:1; + UINT32 ETxBF:1; + UINT32 ITxBF:1; + UINT32 tx_rate:12; + UINT32 ldpc:1; + UINT32 gi:1; +} TMAC_TXD_6; +#endif + +/* TXD_L_STRUC.fix_rate_mode */ +#define TMI_FIX_RATE_BY_TXD 0 +#define TMI_FIX_RATE_BY_CR 1 + +#define TMI_TX_RATE_BIT_STBC 11 +#define TMI_TX_RATE_BIT_NSS 9 +#define TMI_TX_RATE_MASK_NSS 0x3 + +#define TMI_TX_RATE_BIT_MODE 6 +#define TMI_TX_RATE_MASK_MODE 0x7 +#define TMI_TX_RATE_MODE_CCK 0 +#define TMI_TX_RATE_MODE_OFDM 1 +#define TMI_TX_RATE_MODE_HTMIX 2 +#define TMI_TX_RATE_MODE_HTGF 3 +#define TMI_TX_RATE_MODE_VHT 4 + +#define SHORT_PREAMBLE 0 +#define LONG_PREAMBLE 1 + +#define TMI_TX_RATE_BIT_MCS 0 +#define TMI_TX_RATE_MASK_MCS 0x3f +#define TMI_TX_RATE_CCK_1M_LP 0 +#define TMI_TX_RATE_CCK_2M_LP 1 +#define TMI_TX_RATE_CCK_5M_LP 2 +#define TMI_TX_RATE_CCK_11M_LP 3 + +#define TMI_TX_RATE_CCK_2M_SP 5 +#define TMI_TX_RATE_CCK_5M_SP 6 +#define TMI_TX_RATE_CCK_11M_SP 7 + +#define TMI_TX_RATE_OFDM_6M 11 +#define TMI_TX_RATE_OFDM_9M 15 +#define TMI_TX_RATE_OFDM_12M 10 +#define TMI_TX_RATE_OFDM_18M 14 +#define TMI_TX_RATE_OFDM_24M 9 +#define TMI_TX_RATE_OFDM_36M 13 +#define TMI_TX_RATE_OFDM_48M 8 +#define TMI_TX_RATE_OFDM_54M 12 + +#define TMI_TX_RATE_HT_MCS0 0 +#define TMI_TX_RATE_HT_MCS1 1 +#define TMI_TX_RATE_HT_MCS2 2 +#define TMI_TX_RATE_HT_MCS3 3 +#define TMI_TX_RATE_HT_MCS4 4 +#define TMI_TX_RATE_HT_MCS5 5 +#define TMI_TX_RATE_HT_MCS6 6 +#define TMI_TX_RATE_HT_MCS7 7 +#define TMI_TX_RATE_HT_MCS8 8 +#define TMI_TX_RATE_HT_MCS9 9 +#define TMI_TX_RATE_HT_MCS10 10 +#define TMI_TX_RATE_HT_MCS11 11 +#define TMI_TX_RATE_HT_MCS12 12 +#define TMI_TX_RATE_HT_MCS13 13 +#define TMI_TX_RATE_HT_MCS14 14 +#define TMI_TX_RATE_HT_MCS15 15 +#define TMI_TX_RATE_HT_MCS16 16 +#define TMI_TX_RATE_HT_MCS17 17 +#define TMI_TX_RATE_HT_MCS18 18 +#define TMI_TX_RATE_HT_MCS19 19 +#define TMI_TX_RATE_HT_MCS20 20 +#define TMI_TX_RATE_HT_MCS21 21 +#define TMI_TX_RATE_HT_MCS22 22 +#define TMI_TX_RATE_HT_MCS23 23 + +#define TMI_TX_RATE_HT_MCS32 32 + +#define TMI_TX_RATE_VHT_MCS0 0 +#define TMI_TX_RATE_VHT_MCS1 1 +#define TMI_TX_RATE_VHT_MCS2 2 +#define TMI_TX_RATE_VHT_MCS3 3 +#define TMI_TX_RATE_VHT_MCS4 4 +#define TMI_TX_RATE_VHT_MCS5 5 +#define TMI_TX_RATE_VHT_MCS6 6 +#define TMI_TX_RATE_VHT_MCS7 7 +#define TMI_TX_RATE_VHT_MCS8 8 +#define TMI_TX_RATE_VHT_MCS9 9 + + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED tmac_txd_7 { + /* DWORD 7 */ + UINT32 sw_field:16; + UINT32 sch_tx_time:16; +} TMAC_TXD_7; +#else +typedef struct GNU_PACKED tmac_txd_7 { + /* DWORD 7 */ + UINT32 sch_tx_time:16; + UINT32 sw_field:16; +} TMAC_TXD_7; +#endif + +/* + TX Descriptor in Long Format (TMAC_TXD_1.FT = 1) +*/ +typedef struct GNU_PACKED _TMAC_TXD_L { + TMAC_TXD_0 txd_0; + TMAC_TXD_1 txd_1; + TMAC_TXD_2 txd_2; + TMAC_TXD_3 txd_3; + TMAC_TXD_4 txd_4; + TMAC_TXD_5 txd_5; + TMAC_TXD_6 txd_6; +#if defined(MT7603) || defined(MT7628) || defined(MT7636) + TMAC_TXD_7 txd_7; +#endif /* MT7603 */ +} TMAC_TXD_L; + + +/* + TX Descriptor in Short Format (TMAC_TXD_1.FT = 0) +*/ +typedef struct GNU_PACKED _TMAC_TXD_S { + TMAC_TXD_0 txd_0; + TMAC_TXD_1 txd_1; +#if defined(MT7603) || defined(MT7628) || defined(MT7636) + TMAC_TXD_7 txd_7; +#endif /* MT7603 */ +} TMAC_TXD_S; + + + + +#define RMAC_RXD_0_PKT_TYPE_MASK 0xe0000000 +#define RMAC_RX_PKT_TYPE_RX_TXS 0x00 +#define RMAC_RX_PKT_TYPE_RX_TXRXV 0x01 +#define RMAC_RX_PKT_TYPE_RX_NORMAL 0x02 +#define RMAC_RX_PKT_TYPE_RX_DUP_RFB 0x03 +#define RMAC_RX_PKT_TYPE_RX_TMR 0x04 +#define RMAC_RX_PKT_TYPE_RETRIEVE 0x05 +#define RMAC_RX_PKT_TYPE_RX_EVENT 0x07 +#define RMAC_RX_PKT_TYPE(_x) (((_x) & RMAC_RXD_0_PKT_TYPE_MASK) >> 29) +#define RMAC_RXD_0_PKT_RX_BYTE_COUNT_MASK 0x0000ffff +#define RMAC_RX_PKT_RX_BYTE_COUNT(_x) (((_x) & RMAC_RXD_0_PKT_RX_BYTE_COUNT_MASK)) + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED rmac_rxd_0_txs { + UINT32 pkt_type:3; + UINT32 rsv:8; + UINT32 txs_cnt:5; + UINT32 rx_byte_cnt:16; +} RMAC_RXD_0_TXS; +#else +typedef struct GNU_PACKED rmac_rxd_0_txs { + UINT32 rx_byte_cnt:16; + UINT32 txs_cnt:5; + UINT32 rsv:8; + UINT32 pkt_type:3; +} RMAC_RXD_0_TXS; +#endif + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED rmac_rxd_0_txrxv { + UINT32 pkt_type:3; + UINT32 rsv:8; + UINT32 rxv_cnt:5; + UINT32 rx_byte_cnt:16; +} RMAC_RXD_0_TXRXV; +#else +typedef struct GNU_PACKED rmac_rxd_0_txrxv { + UINT32 rx_byte_cnt:16; + UINT32 rxv_cnt:5; + UINT32 rsv:8; + UINT32 pkt_type:3; +} RMAC_RXD_0_TXRXV; +#endif + + +typedef struct _RXV_INFO { + INT32 Rssi0; + INT32 Rssi1; +} RXV_INFO; + +typedef struct GNU_PACKED _RXV_DWORD0 { + UINT32 TA_0_31; +} RXV_DWORD0; + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXV_DWORD1 { + UINT32 Reserved:7; + UINT32 TR:1; + UINT32 RxvSn:8; + UINT32 TA_32_47:16; +} RXV_DWORD1; +#else +typedef struct GNU_PACKED _RXV_DWORD1 { + UINT32 TA_32_47:16; + UINT32 RxvSn:8; + UINT32 TR:1; + UINT32 Reserved:7; +} RXV_DWORD1; +#endif + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RX_VECTOR1_1ST_CYCLE { + UINT32 VHTA1_B5_B4:2; + UINT32 VHTA2_B8_B1:8; + UINT32 HtNoSound:1; + UINT32 HtSmooth:1; + UINT32 HtShortGi:1; + UINT32 HtAggregation:1; + UINT32 VHTA1_B22:1; + UINT32 FrMode:2; + UINT32 TxMode:3; + UINT32 HtExtltf:2; + UINT32 HtAdCode:1; + UINT32 HtStbc:2; + UINT32 TxRate:7; +} RX_VECTOR1_1ST_CYCLE; +#else +typedef struct GNU_PACKED _RX_VECTOR1_1ST_CYCLE { + UINT32 TxRate:7; + UINT32 HtStbc:2; + UINT32 HtAdCode:1; + UINT32 HtExtltf:2; + UINT32 TxMode:3; + UINT32 FrMode:2; + UINT32 VHTA1_B22:1; + UINT32 HtAggregation:1; + UINT32 HtShortGi:1; + UINT32 HtSmooth:1; + UINT32 HtNoSound:1; + UINT32 VHTA2_B8_B1:8; + UINT32 VHTA1_B5_B4:2; +} RX_VECTOR1_1ST_CYCLE; +#endif + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RX_VECTOR1_2ND_CYCLE { + UINT32 VHTA1_B16_B6:11; + UINT32 Length:21; +} RX_VECTOR1_2ND_CYCLE; +#else +typedef struct GNU_PACKED _RX_VECTOR1_2ND_CYCLE { + UINT32 Length:21; + UINT32 VHTA1_B16_B6:11; +} RX_VECTOR1_2ND_CYCLE; +#endif + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RX_VECTOR1_3TH_CYCLE { + UINT32 Fagc1CalGain:3; + UINT32 Fgac1EqCal:1; + UINT32 Rcpi1:8; + UINT32 Fagc0CalGain:3; + UINT32 Fagc0EqCal:1; + UINT32 Rcpi0:8; + UINT32 SelAnt:1; + UINT32 ACI_DETx:1; + UINT32 OFDMFreqTransDet:1; + UINT32 VHTA1_B21_B17:5; +} RX_VECTOR1_3TH_CYCLE; +#else +typedef struct GNU_PACKED _RX_VECTOR1_3TH_CYCLE { + UINT32 VHTA1_B21_B17:5; + UINT32 OFDMFreqTransDet:1; + UINT32 ACI_DETx:1; + UINT32 SelAnt:1; + UINT32 Rcpi0:8; + UINT32 Fagc0EqCal:1; + UINT32 Fgac0CalGain:3; + UINT32 Rcpi1:8; + UINT32 Fagc1EqCal:1; + UINT32 Fgac1CalGain:3; +} RX_VECTOR1_3TH_CYCLE; +#endif + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RX_VECTOR1_4TH_CYCLE { + UINT32 FgacCalGain:3; + UINT32 Fagc2EqCal:1; + UINT32 IBRssi1:8; + UINT32 FagcLpfGainx:4; + UINT32 WBRssix:8; + UINT32 IBRssi0:8; +} RX_VECTOR1_4TH_CYCLE; +#else +typedef struct GNU_PACKED _RX_VECTOR1_4TH_CYCLE { + UINT32 IBRssi0:8; + UINT32 WBRssix:8; + UINT32 FagcLpfGainx:4; + UINT32 IBRssi1:8; + UINT32 Fagc2EqCal:1; + UINT32 FgacCalGain:3; +} RX_VECTOR1_4TH_CYCLE; +#endif + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RX_VECTOR1_5TH_CYCLE { + UINT32 LTF_SNR0:6; + UINT32 LTF_ProcTime:7; + UINT32 FoE:12; //FreqOffSer from Rx + UINT32 CagcState:3; + UINT32 FagcLnaGain1:2; + UINT32 FagcLnaGain0:2; +} RX_VECTOR1_5TH_CYCLE; +#else +typedef struct GNU_PACKED _RX_VECTOR1_5TH_CYCLE { + UINT32 FagcLnaGain0:2; + UINT32 FagcLnaGain1:2; + UINT32 CagcState:3; + UINT32 FoE:12; //FreqOffSer from Rx + UINT32 LTF_ProcTime:7; + UINT32 LTF_SNR0:6; +} RX_VECTOR1_5TH_CYCLE; +#endif + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RX_VECTOR1_6TH_CYCLE { + UINT32 Reserved:1; + UINT32 CagcState:3; + UINT32 NsTsField:3; + UINT32 RxValidIndicator:1; + UINT32 Nf2:8; + UINT32 Nf1:8; + UINT32 Nf0:8; +} RX_VECTOR1_6TH_CYCLE; +#else +typedef struct GNU_PACKED _RX_VECTOR1_6TH_CYCLE { + UINT32 Nf0:8; + UINT32 Nf1:8; + UINT32 Nf2:8; + UINT32 RxValidIndicator:1; + UINT32 NsTsField:3; + UINT32 CagcState:3; + UINT32 Reserved:1; +} RX_VECTOR1_6TH_CYCLE; +#endif + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RX_VECTOR2_1ST_CYCLE { + UINT32 Ofdm:28; + UINT32 Sec40ItfrEnv:1; + UINT32 SecItfrEnv:1; + UINT32 PrimItfrEnv:1; +} RX_VECTOR2_1ST_CYCLE; +#else +typedef struct GNU_PACKED _RX_VECTOR2_1ST_CYCLE { + UINT32 PrimItfrEnv:1; + UINT32 SecItfrEnv:1; + UINT32 Sec40ItfrEnv:1; + UINT32 BtEnv:1; + UINT32 Ofdm:28; +} RX_VECTOR2_1ST_CYCLE; +#endif + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RX_VECTOR2_2ND_CYCLE { + UINT32 RxScramblingSeed:3; + //UINT32 DumpSelect:8; + UINT32 Reserved2:2; + UINT32 OfdmLtfSNR1:6; + UINT32 BtdNoTchLoc:7; + UINT32 Ofdm:14; +} RX_VECTOR2_2ND_CYCLE; +#else +typedef struct GNU_PACKED _RX_VECTOR2_2ND_CYCLE { + UINT32 Ofdm:14; + UINT32 BtdNoTchLoc:7; + //UINT32 DumpSelect:8; + UINT32 OfdmLtfSNR1:6; + UINT32 Reserved2:2; + UINT32 RxScramblingSeed:3; +} RX_VECTOR2_2ND_CYCLE; +#endif + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RX_VECTOR2_3TH_CYCLE { + UINT32 FcsErr:1; + UINT32 OfdmDewModeDet:1; + UINT32 OfdmCeLtfComb:1; + UINT32 OfdmCeGicEnb:1; + UINT32 OfdmCeRmsdId:3; + UINT32 Reserved1:1; + UINT32 BgAgcWbRssix:8; + UINT32 BfAgcIbRssix:8; + UINT32 BfAgcLpfGain:4; + UINT32 Reserved0:1; + UINT32 BfAgcLnaGainx:2; + UINT32 HtStfDet:1; +} RX_VECTOR2_3TH_CYCLE; +#else +typedef struct GNU_PACKED _RX_VECTOR2_3TH_CYCLE { + UINT32 HtStfDet:1; + UINT32 BfAgcLnaGainx:2; + UINT32 Reserved0:1; + UINT32 BfAgcLpfGain:4; + UINT32 BfAgcIbRssix:8; + UINT32 BgAgcWbRssix:8; + UINT32 Reserved1:1; + UINT32 OfdmCeRmsdId:3; + UINT32 OfdmCeGicEnb:1; + UINT32 OfdmCeLtfComb:1; + UINT32 OfdmDewModeDet:1; + UINT32 FcsErr:1; +} RX_VECTOR2_3TH_CYCLE; +#endif + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED rmac_rxd_0_normal { + UINT32 pkt_type:3; + UINT32 grp_vld:4; + UINT32 ut_sum:1; + UINT32 ip_sum:1; + UINT32 eth_type_offset:7; + UINT32 rx_byte_cnt:16; +} RMAC_RXD_0_NORMAL; +#else +typedef struct GNU_PACKED rmac_rxd_0_normal { + UINT32 rx_byte_cnt:16; + UINT32 eth_type_offset:7; + UINT32 ip_sum:1; + UINT32 ut_sum:1; + UINT32 grp_vld:4; + UINT32 pkt_type:3; +} RMAC_RXD_0_NORMAL; +#endif + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED rmac_rxd_1_normal { + UINT32 bssid:6; + UINT32 payload_format:2; + UINT32 hdr_trans:1; + UINT32 hdr_offset:1; + UINT32 mac_hdr_len:6; + UINT32 ch_freq:8; + UINT32 key_id:2; + UINT32 beacon_uc:1; + UINT32 beacon_mc:1; + UINT32 bcast:1; + UINT32 mcast:1; + UINT32 u2m:1; + UINT32 htc_vld:1; +} RMAC_RXD_1_NORMAL; +#else +typedef struct GNU_PACKED rmac_rxd_1_normal { + UINT32 htc_vld:1; + UINT32 u2m:1; + UINT32 mcast:1; + UINT32 bcast:1; + UINT32 beacon_mc:1; + UINT32 beacon_uc:1; + UINT32 key_id:2; + UINT32 ch_freq:8; + UINT32 mac_hdr_len:6; + UINT32 hdr_offset:1; + UINT32 hdr_trans:1; + UINT32 payload_format:2; + UINT32 bssid:6; +} RMAC_RXD_1_NORMAL; +#endif + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED rmac_rxd_2_normal { + UINT32 non_ampdu:1; + UINT32 non_ampdu_sub_frm:1; + UINT32 ndata:1; + UINT32 null_frm:1; + UINT32 frag:1; + UINT32 UDF_VLT:1; + UINT32 llc_mis:1; + UINT32 exceed_max_rx_len:1; + UINT32 de_amsdu_err:1; + UINT32 len_mismatch:1; + UINT32 tkip_mic_err:1; + UINT32 icv_err:1; + UINT32 clm:1; + UINT32 cm:1; + UINT32 fcs_err:1; + UINT32 sw_bit:1; + UINT32 sec_mode:4; + UINT32 tid:4; + UINT32 wlan_idx:8; +} RMAC_RXD_2_NORMAL; +#else +typedef struct GNU_PACKED rmac_rxd_2_normal { + UINT32 wlan_idx:8; + UINT32 tid:4; + UINT32 sec_mode:4; + UINT32 sw_bit:1; + UINT32 fcs_err:1; + UINT32 cm:1; + UINT32 clm:1; + UINT32 icv_err:1; + UINT32 tkip_mic_err:1; + UINT32 len_mismatch:1; + UINT32 de_amsdu_err:1; + UINT32 exceed_max_rx_len:1; + UINT32 llc_mis:1; + UINT32 UDF_VLT:1; + UINT32 frag:1; + UINT32 null_frm:1; + UINT32 ndata:1; + UINT32 non_ampdu_sub_frm:1; + UINT32 non_ampdu:1; +} RMAC_RXD_2_NORMAL; +#endif + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED rmac_rxd_3_normal { + UINT32 pf_sts:2; + UINT32 pf_mode:1; + UINT32 cls_bitmap:10; + UINT32 wol:5; + UINT32 magic_pkt:1; + UINT32 OFLD:2; + UINT32 cls:1; + UINT32 pattern_drop_bit:1; + UINT32 tsf_compare_loss:1; + UINT32 rx_vector_seq:8; +} RMAC_RXD_3_NORMAL; +#else +typedef struct GNU_PACKED rmac_rxd_3_normal { + UINT32 rx_vector_seq:8; + UINT32 tsf_compare_loss:1; + UINT32 pattern_drop_bit:1; + UINT32 cls:1; + UINT32 OFLD:2; + UINT32 magic_pkt:1; + UINT32 wol:5; + UINT32 cls_bitmap:10; + UINT32 pf_mode:1; + UINT32 pf_sts:2; +} RMAC_RXD_3_NORMAL; +#endif + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED rmac_rxd_0_tmr { + UINT32 pkt_type:3; + UINT32 ir:1; + UINT32 tod_vld:1; + UINT32 toa_vld:1; + UINT32 type:2; + UINT32 sub_type:4; + UINT32 tmf:1; + UINT32 nc:1; + UINT32 rsv_16:2; + UINT32 rx_byte_cnt:16; +} RMAC_RXD_0_TMR; +#else +typedef struct GNU_PACKED rmac_rxd_0_tmr { + UINT32 rx_byte_cnt:16; + UINT32 rsv_16:2; + UINT32 nc:1; + UINT32 tmf:1; + UINT32 sub_type:4; + UINT32 type:2; + UINT32 toa_vld:1; + UINT32 tod_vld:1; + UINT32 ir:1; + UINT32 pkt_type:3; +} RMAC_RXD_0_TMR; +#endif + +union GNU_PACKED rmac_rxd_0 { + struct rmac_rxd_0_txs txs_d0; + struct rmac_rxd_0_normal rxd_d0; + struct rmac_rxd_0_txrxv rxv_d0; + struct rmac_rxd_0_tmr tmr_d0; + UINT32 word; +}; + + +/* + Rx Normal Data frame Format +*/ +struct GNU_PACKED rxd_base_struct { + /* DWORD 0 */ + struct rmac_rxd_0_normal rxd_0; + /* DWORD 1 */ + struct rmac_rxd_1_normal rxd_1; + /* DWORD 2 */ + struct rmac_rxd_2_normal rxd_2; + /* DWORD 3 */ + struct rmac_rxd_3_normal rxd_3; +}; + +#define RXS_GROUP1 (1 << 0) +#define RXS_GROUP2 (1 << 1) +#define RXS_GROUP3 (1 << 2) +#define RXS_GROUP4 (1 << 3) + +#define RMAC_INFO_BASE_SIZE 16 +#define RMAC_INFO_GRP_1_SIZE 16 +#define RMAC_INFO_GRP_2_SIZE 8 +#define RMAC_INFO_GRP_3_SIZE 24 +#define RMAC_INFO_GRP_4_SIZE 16 + + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXD_GRP4_STRUCT{ + /* DWORD 4 */ + UINT32 frm_ctrl:16; + UINT32 ta_low:16; + + /* DWORD 5 */ + UINT32 ta_high; + + /* DWORD 6 */ + UINT32 frag_num:4; + UINT32 seq_num:12; + UINT32 qos_ctrl:16; + + /* DWORD 7 */ + UINT32 htc_ctrl; +} RXD_GRP4_STRUCT; +#else +typedef struct GNU_PACKED _RXD_GRP4_STRUCT{ + /* DWORD 4 */ + UINT32 ta_low:16; + UINT32 frm_ctrl:16; + + /* DWORD 5 */ + UINT32 ta_high; + + /* DWORD 6 */ + UINT32 qos_ctrl:16; + UINT32 seq_num:12; + UINT32 frag_num:4; + + /* DWORD 7 */ + UINT32 htc_ctrl; +} RXD_GRP4_STRUCT; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXD_GRP1_STRUCT{ + /* DWORD 8 */ + UINT32 sec_pn_32; + + /* DWORD 9 */ + UINT32 sec_pn_48:16; + UINT32 wpi_pn_64:16; + + /* DWORD 10 */ + UINT32 wpi_pn_96; + + /* DWORD 11 */ + UINT32 wpi_pn_128; +} RXD_GRP1_STRUCT; +#else +typedef struct GNU_PACKED _RXD_GRP1_STRUCT{ + /* DWORD 8 */ + UINT32 sec_pn_32; + + /* DWORD 9 */ + UINT32 wpi_pn_64:16; + UINT32 sec_pn_48:16; + + /* DWORD 10 */ + UINT32 wpi_pn_96; + + /* DWORD 11 */ + UINT32 wpi_pn_128; +} RXD_GRP1_STRUCT; +#endif + + +typedef struct GNU_PACKED _RXD_GRP2_STRUCT{ + /* DWORD 12 */ + UINT32 timestamp; + + /* DWORD 13 */ + UINT32 crc; +} RXD_GRP2_STRUCT; + +typedef struct GNU_PACKED _RXD_GRP3_STRUCT{ + /* DWORD 14 */ + UINT32 rxv_1; + + /* DWORD 15 */ + UINT32 rxv_2; + + /* DWORD 16 */ + UINT32 rxv_3; + + /* DWORD 17 */ + UINT32 rxv_4; + + /* DWORD 18 */ + UINT32 rxv_5; + + /* DWORD 18 */ + UINT32 rxv_6; + + /* DWORD 19 */ + UINT32 rxv_7; +}RXD_GRP3_STRUCT; + + + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RX_CSO_STRUCT { + UINT32 cs_status:4; + UINT32 cs_type:4; + UINT32 ip_len_mismatch:1; + UINT32 ip_frag:1; + UINT32 un_next_hdr:1; + UINT32 rsv_11:21; +} RX_CSO_STRUCT; +#else +typedef struct GNU_PACKED _RX_CSO_STRUCT { + UINT32 rsv_11:21; + UINT32 un_next_hdr:1; + UINT32 ip_frag:1; + UINT32 ip_len_mismatch:1; + UINT32 cs_type:4; + UINT32 cs_status:4; +} RX_CSO_STRUCT; +#endif + +/* TX Status Report Format */ +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED txs_d_0 { + UINT32 ant_id:6; + UINT32 tid:3; + UINT32 baf:1; + UINT32 ps:1; + UINT32 txop:1; + UINT32 BE:1; + UINT32 LE:1; + UINT32 RE:1; + UINT32 ME:1; + UINT32 txs2h:1; + UINT32 txs2m:1; + UINT32 txsfm:1; + UINT32 fr:1; + UINT32 tx_rate:12; +} TXS_D_0; +#else +typedef struct GNU_PACKED txs_d_0 { + UINT32 tx_rate:12; + UINT32 fr:1; + UINT32 txsfm:1; + UINT32 txs2m:1; + UINT32 txs2h:1; + UINT32 ME:1; + UINT32 RE:1; + UINT32 LE:1; + UINT32 BE:1; + UINT32 txop:1; + UINT32 ps:1; + UINT32 baf:1; + UINT32 tid:3; + UINT32 ant_id:6; +} TXS_D_0; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED txs_d_1 { + struct { + UINT32 rsv:8; + UINT32 noise_2:8; + UINT32 noise_1:8; + UINT32 noise_0:8; + } field_noise; + + UINT32 timestamp; + + UINT32 word; +} TXS_D_1; +#else +typedef union GNU_PACKED txs_d_1 { + struct { + UINT32 noise_0:8; + UINT32 noise_1:8; + UINT32 noise_2:8; + UINT32 rsv:8; + } field_noise; + + UINT32 timestamp; + + UINT32 word; +} TXS_D_1; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED txs_d_2 { + struct { + UINT32 tx_pwr_dBm:7; + UINT32 front_time:25; + } field_ft; + + struct { + UINT32 tx_pwr_dBm:7; + UINT32 rsv:1; + UINT32 rcpi_2:8; + UINT32 rcpi_1:8; + UINT32 rcpi_0:8; + } field_rcpi; + + UINT32 word; +} TXS_D_2; +#else +typedef union GNU_PACKED txs_d_2 { + struct { + UINT32 front_time:25; + UINT32 tx_pwr_dBm:7; + } field_ft; + + struct { + UINT32 rcpi_0:8; + UINT32 rcpi_1:8; + UINT32 rcpi_2:8; + UINT32 rsv:1; + UINT32 tx_pwr_dBm:7; + } field_rcpi; + + UINT32 word; +} TXS_D_2; +#endif + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED txs_d_3 { + UINT32 wlan_idx:8; + UINT32 rxv_sn:8; + UINT32 transmission_delay:16; +} TXS_D_3; +#else +typedef struct GNU_PACKED txs_d_3 { + UINT32 transmission_delay:16; + UINT32 rxv_sn:8; + UINT32 wlan_idx:8; +} TXS_D_3; +#endif + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED txs_d_4 { + UINT32 last_tx_rate_idx:3; + UINT32 mpdu_tx_cnt:5; + UINT32 am:1; + UINT32 fm:1; + UINT32 pid:8; + UINT32 tbw:2; + UINT32 sn:12; +} TXS_D_4; +#else +typedef struct GNU_PACKED txs_d_4 { + UINT32 sn:12; + UINT32 tbw:2; + UINT32 pid:8; + UINT32 fm:1; + UINT32 am:1; + UINT32 mpdu_tx_cnt:5; + UINT32 last_tx_rate_idx:3; +} TXS_D_4; +#endif + +typedef struct GNU_PACKED _TXS_STRUC{ + TXS_D_0 txs_d0; + TXS_D_1 txs_d1; + TXS_D_2 txs_d2; + TXS_D_3 txs_d3; + TXS_D_4 txs_d4; +} TXS_STRUC; + + +typedef struct GNU_PACKED _TXS_FRM_STRUC{ + struct rmac_rxd_0_txs txs_d0; + TXS_STRUC txs_info[0]; +} TXS_FRM_STRUC; + + +/* RX/TX-Status Vector Format */ +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXV_STRUC{ + UINT32 ta_0; + UINT32 rsv_1_25:7; + UINT32 tr:1; + UINT32 rxv_sn:8; + UINT32 ta_32:16; + UINT32 vector1[6]; + UINT32 vector2[3]; +} RXV_STRUC; +#else +typedef struct GNU_PACKED _RXV_STRUC{ + UINT32 ta_0; + UINT32 ta_32:16; + UINT32 rxv_sn:8; + UINT32 tr:1; + UINT32 rsv_1_25:7; + UINT32 vector1[6]; + UINT32 vector2[3]; +} RXV_STRUC; +#endif + +typedef struct GNU_PACKED _RXV_FRM_STRUC{ + struct rmac_rxd_0_txrxv rxv_d0; + RXV_STRUC rxv_info[0]; +} RXV_FRM_STRUC; + + +/* + Timing Measurement Report Format +*/ +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED tmr_d_1 { + struct { + UINT32 rsv_29:3; + UINT32 rxv_fr_mode:2; + UINT32 rxv_tx_mode:3; + UINT32 rsv_21:3; + UINT32 txv_fr_mode:2; + UINT32 txv_tx_mode:3; + UINT32 rsv_8:8; + UINT32 pid:8; + } field_init; + + struct { + UINT32 rsv_29:3; + UINT32 rxv_fr_mode:2; + UINT32 rxv_tx_mode:3; + UINT32 rsv_21:3; + UINT32 txv_fr_mode:2; + UINT32 txv_tx_mode:3; + UINT32 rsv_8:8; + UINT32 rxv_sn:8; + } field_resp; + + UINT32 word; +} TMR_D_1; +#else +typedef union GNU_PACKED tmr_d_1 { + struct { + UINT32 pid:8; + UINT32 rsv_8:8; + UINT32 txv_tx_mode:3; + UINT32 txv_fr_mode:2; + UINT32 rsv_21:3; + UINT32 rxv_tx_mode:3; + UINT32 rxv_fr_mode:2; + UINT32 rsv_29:3; + } field_init; + + struct { + UINT32 rxv_sn:8; + UINT32 rsv_8:8; + UINT32 txv_tx_mode:3; + UINT32 txv_fr_mode:2; + UINT32 rsv_21:3; + UINT32 rxv_tx_mode:3; + UINT32 rxv_fr_mode:2; + UINT32 rsv_29:3; + } field_resp; + + UINT32 word; +} TMR_D_1; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED tmr_d_2 { + struct { + UINT32 sn:16; + UINT32 ta_0:16; + } field; + + UINT32 word; +} TMR_D_2; +#else +typedef union GNU_PACKED tmr_d_2 { + struct { + UINT32 ta_0:16; + UINT32 sn:16; + } field; + + UINT32 word; +} TMR_D_2; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED tmr_d_6 { + struct { + UINT32 toa_32:16; + UINT32 tod_32:16; + } field; + + UINT32 word; +} TMR_D_6; +#else +typedef union GNU_PACKED tmr_d_6 { + struct { + UINT32 tod_32:16; + UINT32 toa_32:16; + } field; + + UINT32 word; +} TMR_D_6; +#endif + +typedef struct GNU_PACKED _TMR_FRM_STRUC{ + struct rmac_rxd_0_tmr tmr_d0; + TMR_D_1 tmr_d1; + TMR_D_2 tmr_d2; + UINT32 ta_16; + UINT32 tod_0; + UINT32 toa_0; + TMR_D_6 tmr_d6; +}TMR_FRM_STRUC; + + +typedef struct wtbl_entry { + UINT8 wtbl_idx; + + struct wtbl_1_struc wtbl_1; + struct wtbl_2_struc wtbl_2; + union wtbl_3_struc wtbl_3; + struct wtbl_4_struc wtbl_4; + + UINT32 wtbl_addr[4]; + UINT16 wtbl_fid[4]; + UINT16 wtbl_eid[4]; +}WTBL_ENTRY; + + + +#define MT_PSE_WTBL_2_ADDR 0xa5000000 /* get from CR setting of PSE.BUFS_DAA (0x164) */ +#define MT_PSE_BASE_ADDR 0xa0000000 + +#define MT_TOP_REMAP_ADDR 0x80000000 //TOP start address 8002-0000, but only can remap to 8000-0000 +#define MT_TOP_REMAP_ADDR_THEMAL 0xa2000 //Get Thermal sensor adc cal value: 0x80022000 bits(8,14), Offset 0x80000 + 0x22000 = 0xa2000 +#define MT_TOP_THEMAL_ADC 0x80022000 //Get Thermal sensor adc cal value: 0x80022000 bits(8,14) + +#define MCU_CFG_BASE 0x2000 +#define MCU_PCIE_REMAP_1 (MCU_CFG_BASE + 0x500) +#define REMAP_1_OFFSET_MASK (0x3ffff) +#define GET_REMAP_1_OFFSET(p) (((p) & REMAP_1_OFFSET_MASK)) +#define REMAP_1_BASE_MASK (0x3fff << 18) +#define GET_REMAP_1_BASE(p) (((p) & REMAP_1_BASE_MASK) >> 18) +#define MCU_PCIE_REMAP_2 (MCU_CFG_BASE + 0x504) +#define REMAP_2_OFFSET_MASK (0x7ffff) +#define GET_REMAP_2_OFFSET(p) (((p) & REMAP_2_OFFSET_MASK)) +#define REMAP_2_BASE_MASK (0x1fff << 19) +#define GET_REMAP_2_BASE(p) (((p) & REMAP_2_BASE_MASK) >> 19) + +#define TOP_CFG_BASE 0x0000 + +#define XTAL_CTL4 (TOP_CFG_BASE + 0x1210) +#define XTAL_CTL13 (TOP_CFG_BASE + 0x1234) +#define XTAL_CTL14 (TOP_CFG_BASE + 0x1238) +#define DA_XO_C2_MASK (0x7f << 8) +#define DA_XO_C2(p) (((p) & 0x7f) << 8) + + +#if defined(MT7603_FPGA) || defined(MT7628_FPGA) || defined(MT7636_FPGA) +#define MT_PSE_PAGE_SIZE 256 +#else +#define MT_PSE_PAGE_SIZE 128 +#endif /* MT7603_FPGA */ + +#define MT_WTBL_SIZE 128 + +#ifdef MT7628_FPGA +#undef MT_WTBL_SIZE +#define MT_WTBL_SIZE 20 +#endif /* MT7628_FPGA */ + +#ifdef MT7636_FPGA +#undef MT_WTBL_SIZE +#define MT_WTBL_SIZE 20 +#endif /* MT7636_FPGA */ + +#if defined(MT7603) || defined(MT7628) || defined(MT7636) +#define DMA_SCH_LMAC 0 +#define DMA_SCH_BYPASS 1 +#define DMA_SCH_HYBRID 2 +#endif /* defined(MT7603) || defined(MT7628) || defined(MT7636) */ + +#define MT_PCI_REMAP_ADDR_1 0x40000 +#define MT_PCI_REMAP_ADDR_2 0x80000 + + + +// TODO: shiang-7603, this is a dummy data structure and need to revise to adapative for MT7603 series + +#define WMM_QUE_NUM 4 /* each sta has 4 Queues to mapping to each WMM AC */ + +/* 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 4 +/* USB need 5 , PCI only 4 */ + +#define NUM_OF_WMM1_TX_RING 1 + +#define QID_BMC 8 + +#define NUM_OF_RX_RING 1 +#ifdef CONFIG_ANDES_SUPPORT +#undef NUM_OF_RX_RING +#define NUM_OF_RX_RING 2 +#endif /* CONFIG_ANDES_SUPPORT */ + +#define QID_MGMT 13 +#define QID_RX 14 +#define QID_OTHER 15 +#ifdef CONFIG_ANDES_SUPPORT +#define QID_CTRL 16 +#endif /* CONFIG_ANDES_SUPPORT */ + +#define QID_BCN 17 + +#define SHAREDKEYTABLE 0 +#define PAIRWISEKEYTABLE 1 + +/* Per Packet PID */ +enum { + PID_DATA_NORMALUCAST, + PID_DATA_NOT_NORM_ACK, + PID_DATA_AMPDU, + PID_MGMT, + PID_DATA_NO_ACK, + PID_CTL_BAR, + PID_PS_DATA, + PID_TDLS, + PID_UAPSD, + PID_WSC_EAP, + PID_NULL_FRAME_PWR_ACTIVE, + PID_NULL_FRAME_PWR_SAVE, + PID_QOS_NULL_FRAME, + PID_MGMT_ASSOC_RSP, +#ifdef WH_EZ_SETUP + PID_EZ_ACTION, +#endif + PID_MAX = 0x40, +}; + +/* Indicate the txs report to Host or MCU */ +typedef enum { + TXS2MCU, + TXS2HOST, +} TXS_TARGET_PORT; + +#define TXS2MCU_AGGNUMS 31 +#define TXS2HOST_AGGNUMS 31 + +enum { + TXS2M_QID0, + TXS2M_QID1, + TXS2M_QID2, + TXS2M_QID3, +}; + +enum { + TXS2H_QID0, + TXS2H_QID1, +}; + +enum { + TXS_FORMAT0, + TXS_FORMAT1, +}; + +enum { + TXS_UNUSED, + TXS_USED, +}; + +typedef struct _TXS_STATUS { + UINT8 TxSPid; + UINT8 State; + UINT8 Type; + UINT8 PktPid; + UINT8 PktType; + UINT8 PktSubType; + UINT16 TxRate; + UINT32 Priv; +} TXS_STATUS, *PTXS_STATYS; + +#define TOTAL_PID_HASH_NUMS 0x10 +#define TOTAL_PID_HASH_NUMS_PER_PKT_TYPE 0x8 +#define TXS_WLAN_IDX_ALL 128 +#define TXS_STATUS_NUM 256 +typedef struct _TXS_CTL { + /* TXS type hash table per pkt */ + DL_LIST TxSTypePerPkt[TOTAL_PID_HASH_NUMS]; + NDIS_SPIN_LOCK TxSTypePerPktLock[TOTAL_PID_HASH_NUMS]; + /* TXS type hash table per pkt type and subtype */ + DL_LIST TxSTypePerPktType[3][TOTAL_PID_HASH_NUMS_PER_PKT_TYPE]; + NDIS_SPIN_LOCK TxSTypePerPktTypeLock[3][TOTAL_PID_HASH_NUMS_PER_PKT_TYPE]; + ULONG TxS2McUStatusPerPkt; + ULONG TxS2HostStatusPerPkt; + ULONG TxS2McUStatusPerPktType[3]; + ULONG TxS2HostStatusPerPktType[3]; + ULONG TxSFormatPerPkt; + ULONG TxSFormatPerPktType[3]; + ULONG TxSStatusPerWlanIdx[2]; + ULONG TxSFailCount; + UINT8 TxSPid; + TXS_STATUS TxSStatus[TXS_STATUS_NUM]; + BOOLEAN TxSValid; +} TXS_CTL, *PTXS_CTL; + +#define TXS_TYPE0 0 /* Per Pkt */ +#define TXS_TYPE1 1 /* Per Pkt Type */ +#define TXS_DUMP_REPEAT 0xffffffff +typedef struct _TXS_TYPE { + DL_LIST List; + UINT8 Type; + UINT8 PktPid; + UINT8 PktType; + UINT8 PktSubType; + UINT8 Format; + INT32 (*TxSHandler)(struct _RTMP_ADAPTER *pAd, CHAR *Data, UINT32 Priv); + BOOLEAN DumpTxSReport; + ULONG DumpTxSReportTimes; +} TXS_TYPE, *PTXS_TYPE; + +typedef INT32 (*TXS_HANDLER)(struct _RTMP_ADAPTER *pAd, CHAR *Data, UINT32 Priv); + +INT32 InitTxSTypeTable(struct _RTMP_ADAPTER *pAd); +INT32 ExitTxSTypeTable(struct _RTMP_ADAPTER *pAd); +INT32 AddTxSTypePerPkt(struct _RTMP_ADAPTER *pAd, UINT32 Pid, UINT8 Format, + TXS_HANDLER TxSHandler); +INT32 RemoveTxSTypePerPkt(struct _RTMP_ADAPTER *pAd, UINT32 Pid, UINT8 Format); +INT32 TxSTypeCtlPerPkt(struct _RTMP_ADAPTER *pAd, UINT32 Pid, UINT8 Format, + BOOLEAN TxS2Mcu, BOOLEAN TxS2Host, + BOOLEAN DumpTxSReport, ULONG DumpTxSReportTimes); +INT32 ParseTxSPacket(struct _RTMP_ADAPTER *pAd, UINT32 Pid, UINT8 Format, CHAR *Data); +INT32 BcnTxSHandler(struct _RTMP_ADAPTER *pAd, CHAR *Data, UINT32 Priv); +INT32 APAssocRespTxSHandler(struct _RTMP_ADAPTER *pAd, CHAR *Data, UINT32 Priv); +INT32 NullFramePM1TxSHandler(struct _RTMP_ADAPTER *pAd, CHAR *Data); +INT32 NullFramePM0TxSHandler(struct _RTMP_ADAPTER *pAd, CHAR *Data); +#ifdef CFG_TDLS_SUPPORT +INT32 TdlsTxSHandler(struct _RTMP_ADAPTER *pAd, CHAR *Data, UINT32 Priv); +#endif //CFG_TDLS_SUPPORT +#ifdef UAPSD_SUPPORT +INT32 UAPSDTxSHandler(struct _RTMP_ADAPTER *pAd, CHAR *Data, UINT32 Priv); +#endif +INT32 AddTxSTypePerPktType(struct _RTMP_ADAPTER *pAd, UINT8 Type, UINT8 Subtype, + UINT8 Format, TXS_HANDLER TxSHandler); +INT32 RemoveTxSTypePerPktType(struct _RTMP_ADAPTER *pAd, UINT8 Type, UINT8 Subtype, + UINT8 Format); +INT32 TxSTypeCtlPerPktType(struct _RTMP_ADAPTER *pAd, UINT8 Type, UINT8 Subtype, UINT16 WlanIdx, + UINT8 Format, BOOLEAN TxS2Mcu, BOOLEAN TxS2Host, + BOOLEAN DumpTxSReport, ULONG DumpTxSReportTimes); +UINT8 AddTxSStatus(struct _RTMP_ADAPTER *pAd, UINT8 Type, UINT8 PktPid, UINT8 PktType, + UINT8 PktSubType, UINT16 TxRate, UINT32 Priv); +INT32 RemoveTxSStatus(struct _RTMP_ADAPTER *pAd, UINT8 TxSPid, UINT8 *Type, UINT8 *PktPid, + UINT8 *PktType, UINT8 *PktSubType, UINT16 *TxRate, UINT32 *Priv); + +#define TSO_SIZE 0 + +#define EXP_ACK_TIME 0x1380 + +typedef union GNU_PACKED _TXWI_STRUC { + UINT32 word; +}TXWI_STRUC; + + +typedef union GNU_PACKED _RXWI_STRUC { + UINT32 word; +}RXWI_STRUC; + +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _TX_STA_CNT0_STRUC { + struct { + UINT16 TxBeaconCount; + UINT16 TxFailCount; + } field; + UINT32 word; +} TX_STA_CNT0_STRUC; +#else +typedef union GNU_PACKED _TX_STA_CNT0_STRUC { + struct { + UINT16 TxFailCount; + UINT16 TxBeaconCount; + } field; + UINT32 word; +} TX_STA_CNT0_STRUC; +#endif + +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _TX_STA_CNT1_STRUC { + struct { + UINT16 TxRetransmit; + UINT16 TxSuccess; + } field; + UINT32 word; +} TX_STA_CNT1_STRUC; +#else +typedef union GNU_PACKED _TX_STA_CNT1_STRUC { + struct { + UINT16 TxSuccess; + UINT16 TxRetransmit; + } field; + UINT32 word; +} TX_STA_CNT1_STRUC; +#endif + +typedef struct __TX_CNT_INFO { + union WTBL_2_DW5 wtbl_2_d5; + union WTBL_2_DW6 wtbl_2_d6; + union WTBL_2_DW7 wtbl_2_d7; + union WTBL_2_DW8 wtbl_2_d8; + union WTBL_2_DW9 wtbl_2_d9; +} TX_CNT_INFO; + + +#define E2PROM_CSR 0x0004 +#define GPIO_CTRL_CFG 0x0228 + +#define LEGACY_BASIC_RATE 0x1408 + +#define HW_BEACON_OFFSET 0x0200 +#define HW_BEACON_MAX_SIZE(__pAd) ((__pAd)->chipCap.BcnMaxHwSize) + +struct _RTMP_ADAPTER; +#ifdef DBG +VOID dump_mt_mac_cr(struct _RTMP_ADAPTER *pAd); +VOID dump_wtbl_entry(struct _RTMP_ADAPTER *pAd, struct wtbl_entry *ent); +VOID dump_wtbl_info(struct _RTMP_ADAPTER *pAd, UINT wtbl_idx); +VOID dump_wtbl_base_info(struct _RTMP_ADAPTER *pAd); +#endif /* DBG */ +INT mt_mac_init(struct _RTMP_ADAPTER *pAd); +INT mt_hw_tb_init(struct _RTMP_ADAPTER *pAd, BOOLEAN bHardReset); +INT mt_wtbl_get_entry234(struct _RTMP_ADAPTER *pAd, UCHAR idx, struct wtbl_entry *ent); +INT mt_mac_set_ctrlch(struct _RTMP_ADAPTER *pAd, UINT8 extch); + +USHORT tx_rate_to_tmi_rate(UCHAR mode, UCHAR mcs, UCHAR nss, BOOLEAN stbc, UCHAR preamble); +UCHAR get_nss_by_mcs(UCHAR phy_mode, UCHAR mcs, BOOLEAN stbc); + +#define HIF_PORT 1 +#define MCU_PORT 2 +#define MT_TX_RETRY_UNLIMIT 0x1f +#define MT_TX_SHORT_RETRY 0x0f +#define MT_TX_LONG_RETRY 0x0f +#define MT_RTS_RETRY 0x0f + +#endif /* __MT_MAC_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/mt_mac_pci.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/mt_mac_pci.h new file mode 100644 index 000000000..42a9be66a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/mt_mac_pci.h @@ -0,0 +1,661 @@ +/**************************************************************************** + * 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: + mt_mac_pci.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __MAC_PCI_H__ +#define __MAC_PCI_H__ + +#include "rtmp_type.h" +#include "phy/phy.h" +#include "rtmp_iface.h" +#include "rtmp_dot11.h" + + + +/* ================================================================================= + PCI/RBUS TX / RX Frame Descriptors format + + Memory Layout + + 1. Tx Descriptor + TxD (12 bytes) + TXINFO (4 bytes) + 2. Packet Buffer + TXWI + 802.11 + 31 0 + +--------------------------------------------------------------------------+ + | SDP0[31:0] | + +-+--+---------------------+-+--+-----------------------------------------+ + |D |L0| SDL0[13:0] |B|L1| SDL1[13:0] | + +-+--+---------------------+-+--+-----------------------------------------+ + | SDP1[31:0] | + +--------------------------------------------------------------------------+ + | TXINFO | + +--------------------------------------------------------------------------+ +================================================================================= */ +/* + TX descriptor format for Tx Data/Mgmt Rings +*/ +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _TXD_STRUC { + /* Word 0 */ + UINT32 SDPtr0; + /* Word 1 */ + UINT32 DMADONE:1; + UINT32 LastSec0:1; + UINT32 SDLen0:14; + UINT32 Burst:1; + UINT32 LastSec1:1; + UINT32 SDLen1:14; + /* Word 2 */ + UINT32 SDPtr1; +} TXD_STRUC; +#else +typedef struct GNU_PACKED _TXD_STRUC { + /* Word 0 */ + UINT32 SDPtr0; + /* Word 1 */ + UINT32 SDLen1:14; + UINT32 LastSec1:1; + UINT32 Burst:1; + UINT32 SDLen0:14; + UINT32 LastSec0:1; + UINT32 DMADONE:1; + /*Word2 */ + UINT32 SDPtr1; +} TXD_STRUC; +#endif /* RT_BIG_ENDIAN */ + + +/* + Rx descriptor format for Rx Rings +*/ +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXD_STRUC{ + /* Word 0 */ + UINT32 SDP0; + /* Word 1 */ + UINT32 DDONE:1; + UINT32 LS0:1; + UINT32 SDL0:14; + UINT32 BURST:1; + UINT32 LS1:1; + UINT32 SDL1:14; + /* Word 2 */ + UINT32 SDP1; +}RXD_STRUC; +#else +typedef struct GNU_PACKED _RXD_STRUC{ + /* Word 0 */ + UINT32 SDP0; + /* Word 1 */ + UINT32 SDL1:14; + UINT32 LS1:1; + UINT32 BURST:1; + UINT32 SDL0:14; + UINT32 LS0:1; + UINT32 DDONE:1; + /* Word 2 */ + UINT32 SDP1; +}RXD_STRUC; +#endif /* RT_BIG_ENDIAN */ + + +#define HIF_BASE 0x4000 + + +/* + CR definitions +*/ +#define MT_INT_R0_DONE (1<<0) +#define MT_INT_R1_DONE (1<<1) + +#define MT_INT_ERR_DET0 (1<<2) +#define MT_INT_ERR_DET1 (1<<3) + +#define MT_INT_T0_DONE (1<<4) +#define MT_INT_T1_DONE (1<<5) +#define MT_INT_T2_DONE (1<<6) +#define MT_INT_T3_DONE (1<<7) +#define MT_INT_T4_DONE (1<<8) +#define MT_INT_T5_DONE (1<<9) +#define MT_INT_T6_DONE (1<<10) +#define MT_INT_T7_DONE (1<<11) +#define MT_INT_T8_DONE (1<<12) +#define MT_INT_T9_DONE (1<<13) +#define MT_INT_T10_DONE (1<<14) +#define MT_INT_T11_DONE (1<<15) +#define MT_INT_T12_DONE (1<<16) +#define MT_INT_T13_DONE (1<<17) + +#define MT_INT_RESVD (1<<18) + +#define MT_INT_T15_DONE (1<<19) + +#define MT_INT_RX_COHE (1<<20) +#define MT_INT_TX_COHE (1<<21) + +#define MT_INT_RX_DLY (1<<22) +#define MT_INT_TX_DLY (1<<23) + +#define WF_MAC_INT_0 (1<<24) +#define WF_MAC_INT_1 (1<<25) +#define WF_MAC_INT_2 (1<<26) +#define WF_MAC_INT_3 (1<<27) +#define WF_MAC_INT_4 (1<<28) +#define WF_MAC_INT_5 (1<<29) + +#define MT_INT_MCU_CMD (1<<30) + +#define MT_INT_RESVD_2 (1<<31) + + +#define MT_RxINT (MT_INT_R0_DONE | MT_INT_R1_DONE /* | MT_INT_RX_DLY */) /* Delayed Rx or indivi rx */ +#define MT_TxDataInt (MT_INT_T0_DONE | \ + MT_INT_T1_DONE | \ + MT_INT_T2_DONE | \ + MT_INT_T3_DONE /*| MT_INT_TX_DLY*/) /* Delayed Tx or indivi tx */ + +#define MT_TxMgmtInt (MT_INT_T4_DONE /*| INT_TX_DLY*/) + +#define MT_TxCoherent MT_INT_TX_COHE +#define MT_RxCoherent MT_INT_RX_COHE +#define MT_TxRxCoherent (MT_INT_TX_COHE | MT_INT_RX_COHE) + +#define MT_McuCommand MT_INT_MCU_CMD /* mcu */ + + +#define MT_INT_RX (MT_INT_R0_DONE | MT_INT_R1_DONE) +#define MT_INT_RX_DATA (MT_INT_R0_DONE) +#define MT_INT_RX_CMD (MT_INT_R1_DONE) + +#define MT_INT_AC0_DLY (MT_INT_T0_DONE) +#define MT_INT_AC1_DLY (MT_INT_T1_DONE) +#define MT_INT_AC2_DLY (MT_INT_T2_DONE) +#define MT_INT_AC3_DLY (MT_INT_T3_DONE) +#define MT_INT_CMD (MT_INT_T5_DONE) + +#define MT_INT_MGMT_DLY (MT_INT_T4_DONE) +#define MT_INT_BMC_DLY (MT_INT_T8_DONE) /* (MT_INT_T6_DONE) */ +#define MT_INT_BCN_DLY (MT_INT_T7_DONE) /* (MT_INT_T15_DONE) */ + +#define MT_DELAYINTMASK 0x3FFBFFFF +#define MT_INTMASK 0x3FFBFFFF + + +/* + INT_SOURCE_CSR: Interrupt source register. Write one to clear corresponding bit + Refer to MT_INT_SOURCE_CSR(0x4000) +*/ +#ifdef RT_BIG_ENDIAN +typedef union _MT_INT_SOURCE_CSR_STRUC { + struct { + UINT32 rsv_31:1; + UINT32 mcu_cmd_int:1; + UINT32 wf_mac_int_5:1; + UINT32 wf_mac_int_4:1; + UINT32 wf_mac_int_3:1; + UINT32 wf_mac_int_2:1; + UINT32 wf_mac_int_1:1; + UINT32 wf_mac_int_0:1; + UINT32 tx_dly_int:1; + UINT32 rx_dly_int:1; + UINT32 tx_coherent:1; + UINT32 rx_coherent:1; + UINT32 tx_done_15:1; + UINT32 rsv_18:1; + UINT32 tx_done_13:1; + UINT32 tx_done_12:1; + UINT32 tx_done_11:1; + UINT32 tx_done_10:1; + UINT32 tx_done_9:1; + UINT32 tx_done_8:1; + UINT32 tx_done_7:1; + UINT32 tx_done_6:1; + UINT32 tx_done_5:1; + UINT32 tx_done_4:1; + UINT32 tx_done_3:1; + UINT32 tx_done_2:1; + UINT32 tx_done_1:1; + UINT32 tx_done_0:1; + UINT32 err_det_int_1:1; + UINT32 err_det_int_0:1; + UINT32 rx_done_1:1; + UINT32 rx_done_0:1; + }field; + UINT32 word; +}MT_INT_SOURCE_CSR_STRUC; +#else +typedef union _MT_INT_SOURCE_CSR_STRUC { + struct { + UINT32 rx_done_0:1; + UINT32 rx_done_1:1; + UINT32 err_det_int_0:1; + UINT32 err_det_int_1:1; + UINT32 tx_done_0:1; + UINT32 tx_done_1:1; + UINT32 tx_done_2:1; + UINT32 tx_done_3:1; + UINT32 tx_done_4:1; + UINT32 tx_done_5:1; + UINT32 tx_done_6:1; + UINT32 tx_done_7:1; + UINT32 tx_done_8:1; + UINT32 tx_done_9:1; + UINT32 tx_done_10:1; + UINT32 tx_done_11:1; + UINT32 tx_done_12:1; + UINT32 tx_done_13:1; + UINT32 rsv_18:1; + UINT32 tx_done_15:1; + UINT32 rx_coherent:1; + UINT32 tx_coherent:1; + UINT32 rx_dly_int:1; + UINT32 tx_dly_int:1; + UINT32 wf_mac_int_0:1; + UINT32 wf_mac_int_1:1; + UINT32 wf_mac_int_2:1; + UINT32 wf_mac_int_3:1; + UINT32 wf_mac_int_4:1; + UINT32 wf_mac_int_5:1; + UINT32 mcu_cmd_int:1; + UINT32 rsv_31:1; + }field; + UINT32 word; +}MT_INT_SOURCE_CSR_STRUC; +#endif /* RT_BIG_ENDIAN */ + + +/* INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF */ +#define WPDMA_INT_MSK (HIF_BASE + 0x204) +#ifdef RT_BIG_ENDIAN +typedef union _MT_WPDMA_INT_MASK{ + struct { + UINT32 rsv_31:1; + UINT32 mcu_cmd_int:1; + UINT32 wf_mac_int_5:1; + UINT32 wf_mac_int_4:1; + UINT32 wf_mac_int_3:1; + UINT32 wf_mac_int_2:1; + UINT32 wf_mac_int_1:1; + UINT32 wf_mac_int_0:1; + UINT32 tx_dly_int:1; + UINT32 rx_dly_int:1; + UINT32 tx_coherent:1; + UINT32 rx_coherent:1; + UINT32 tx_done_15:1; + UINT32 rsv_18:1; + UINT32 tx_done_13:1; + UINT32 tx_done_12:1; + UINT32 tx_done_11:1; + UINT32 tx_done_10:1; + UINT32 tx_done_9:1; + UINT32 tx_done_8:1; + UINT32 tx_done_7:1; + UINT32 tx_done_6:1; + UINT32 tx_done_5:1; + UINT32 tx_done_4:1; + UINT32 tx_done_3:1; + UINT32 tx_done_2:1; + UINT32 tx_done_1:1; + UINT32 tx_done_0:1; + UINT32 err_det_int_1:1; + UINT32 err_det_int_0:1; + UINT32 rx_done_1:1; + UINT32 rx_done_0:1; + }field; + UINT32 word; +}MT_WPMDA_INT_MASK; +#else +typedef union _MT_WPDMA_INT_MASK{ + struct { + UINT32 rx_done_0:1; + UINT32 rx_done_1:1; + UINT32 err_det_int_0:1; + UINT32 err_det_int_1:1; + UINT32 tx_done_0:1; + UINT32 tx_done_1:1; + UINT32 tx_done_2:1; + UINT32 tx_done_3:1; + UINT32 tx_done_4:1; + UINT32 tx_done_5:1; + UINT32 tx_done_6:1; + UINT32 tx_done_7:1; + UINT32 tx_done_8:1; + UINT32 tx_done_9:1; + UINT32 tx_done_10:1; + UINT32 tx_done_11:1; + UINT32 tx_done_12:1; + UINT32 tx_done_13:1; + UINT32 rsv_18:1; + UINT32 tx_done_15:1; + UINT32 rx_coherent:1; + UINT32 tx_coherent:1; + UINT32 rx_dly_int:1; + UINT32 tx_dly_int:1; + UINT32 wf_mac_int_0:1; + UINT32 wf_mac_int_1:1; + UINT32 wf_mac_int_2:1; + UINT32 wf_mac_int_3:1; + UINT32 wf_mac_int_4:1; + UINT32 wf_mac_int_5:1; + UINT32 mcu_cmd_int:1; + UINT32 rsv_31:1; + }field; + UINT32 word; +}MT_WPMDA_INT_MASK; +#endif /* RT_BIG_ENDIAN */ + + +//#define WPDMA_RST_PTR (HIF_BASE + 0x00c) /* WPDMA_RST_IDX */ + + +/*@!Release + Tx Ring Layout and assignments + + Totally we have 10 Tx Rings and assigned as following usage: + 1. RT85592 + TxRing 0~3: for TxQ Channel 1 with AC_BK/BE/VI/VO + TxRing 4 : for TxQ CTRL + TxRing 5 : for TxQ MGMT + TxRing 6~9: for TxQ Channel 2 with AC_BK/BE/VI/VO + + 2. MT7650 + TxRing 0~3: for TxQ Channel 1 with AC_BK/BE/VI/VO + TxRing 4~7: for TxQ Channel 2 with AC_BK/BE/VI/VO + TxRing 8 : for TxQ CTRL + TxRing 9 : for TxQ MGMT + + For each TxRing, we have four register to control it + TX_RINGn_CTRL0 (0x0): base address of this ring(4-DWORD aligned address) + TX_RINGn_CTRL1 (0x4): maximum number of TxD count in this ring + TX_RINGn_CTRL2 (0x8): Point to the next TxD CPU wants to use + TX_RINGn_CTRL3 (0xc): Point to the next TxD DMA wants to use +*/ +#define MT_RINGREG_DIFF 0x10 + +#define MT_TX_RING_BASE (HIF_BASE + 0x0300) +#define MT_TX_RING_NUM 13 +#define MT_TX_RING_PTR (MT_TX_RING_BASE + 0x0) +#define MT_TX_RING_CNT (MT_TX_RING_BASE + 0x4) +#define MT_TX_RING_CIDX (MT_TX_RING_BASE + 0x8) +#define MT_TX_RING_DIDX (MT_TX_RING_BASE + 0xc) + +#define TX_CHAN_BASE_1 (MT_TX_RING_BASE + MT_RINGREG_DIFF * 0) +#define TX_CHAN_BASE_2 (MT_TX_RING_BASE + MT_RINGREG_DIFF * 6) + +/* following address is base on TX_CHAN_BASE_X */ +#define MT_TX_RING_BK_BASE 0x0 +#define MT_TX_RING_BK_CNT (MT_TX_RING_BK_BASE + 0x04) +#define MT_TX_RING_BK_CIDX (MT_TX_RING_BK_BASE + 0x08) +#define MT_TX_RING_BK_DIDX (MT_TX_RING_BK_BASE + 0x0c) + +#define MT_TX_RING_BE_BASE (MT_TX_RING_BK_BASE + MT_RINGREG_DIFF) +#define MT_TX_RING_BE_CNT (MT_TX_RING_BE_BASE + 0x04) +#define MT_TX_RING_BE_CIDX (MT_TX_RING_BE_BASE + 0x08) +#define MT_TX_RING_BE_DIDX (MT_TX_RING_BE_BASE + 0x0c) + +#define MT_TX_RING_VI_BASE (MT_TX_RING_BE_BASE + MT_RINGREG_DIFF) +#define MT_TX_RING_VI_CNT (MT_TX_RING_VI_BASE + 0x04) +#define MT_TX_RING_VI_CIDX (MT_TX_RING_VI_BASE + 0x08) +#define MT_TX_RING_VI_DIDX (MT_TX_RING_VI_BASE + 0x0c) + +#define MT_TX_RING_VO_BASE (MT_TX_RING_VI_BASE + MT_RINGREG_DIFF) +#define MT_TX_RING_VO_CNT (MT_TX_RING_VO_BASE + 0x04) +#define MT_TX_RING_VO_CIDX (MT_TX_RING_VO_BASE + 0x08) +#define MT_TX_RING_VO_DIDX (MT_TX_RING_VO_BASE + 0x0c) + + +#define MT_TX_RING_BCN_IDX 7 + +/* + Rx Ring Layput and assignments + + Totally we have 2 Rx Rings and assigned as following usage: + RxRing 0: for all received data packets + RxRing 1: for internal ctrl/info packets generated by on-chip CPU. + + For each TxRing, we have four register to control it + RX_RING_CTRL0 (0x0): base address of this ring(4-DWORD aligned address) + RX_RING_CTRL1 (0x4): maximum number of RxD count in this ring + RX_RING_CTRL2 (0x8): Point to the next RxD CPU wants to use + RX_RING_CTRL3 (0xc): Point to the next RxD DMA wants to use +*/ +#define MT_RX_RING_BASE (HIF_BASE + 0x0400) +#define MT_RX_RING1_BASE (HIF_BASE + 0x0410) +#define MT_RX_RING_NUM 2 +#define MT_RX_RING_PTR (MT_RX_RING_BASE + 0x00) +#define MT_RX_RING_CNT (MT_RX_RING_BASE + 0x04) +#define MT_RX_RING_CIDX (MT_RX_RING_BASE + 0x08) +#define MT_RX_RING_DIDX (MT_RX_RING_BASE + 0x0c) + +#define MT_RX_RING1_PTR (MT_RX_RING_BASE + MT_RINGREG_DIFF * 1) +#define MT_RX_RING1_CNT (MT_RX_RING_BASE + MT_RINGREG_DIFF * 1 + 0x04) +#define MT_RX_RING1_CIDX (MT_RX_RING_BASE + MT_RINGREG_DIFF * 1 + 0x08) +#define MT_RX_RING1_DIDX (MT_RX_RING_BASE + MT_RINGREG_DIFF * 1 + 0x0c) + +#define MT_TXTIME_THD_0 (HIF_BASE + 0x500) +#define MT_TXTIME_THD_1 (HIF_BASE + 0x504) +#define MT_TXTIME_THD_2 (HIF_BASE + 0x508) +#define MT_TXTIME_THD_3 (HIF_BASE + 0x50c) +#define MT_TXTIME_THD_4 (HIF_BASE + 0x510) +#define MT_TXTIME_THD_5 (HIF_BASE + 0x514) +#define MT_TXTIME_THD_6 (HIF_BASE + 0x518) +#define MT_TXTIME_THD_7 (HIF_BASE + 0x51c) +#define MT_TXTIME_THD_8 (HIF_BASE + 0x520) +#define MT_TXTIME_THD_9 (HIF_BASE + 0x524) +#define MT_TXTIME_THD_10 (HIF_BASE + 0x528) +#define MT_TXTIME_THD_11 (HIF_BASE + 0x52c) +#define MT_TXTIME_THD_12 (HIF_BASE + 0x530) +#define MT_TXTIME_THD_13 (HIF_BASE + 0x534) +#define MT_TXTIME_THD_14 (HIF_BASE + 0x538) +#define MT_TXTIME_THD_15 (HIF_BASE + 0x53c) + +#define MT_PAGE_CNT_0 (HIF_BASE + 0x540) +#define MT_PAGE_CNT_1 (HIF_BASE + 0x544) +#define MT_PAGE_CNT_2 (HIF_BASE + 0x548) +#define MT_PAGE_CNT_3 (HIF_BASE + 0x54c) +#define MT_PAGE_CNT_4 (HIF_BASE + 0x550) +#define MT_PAGE_CNT_5 (HIF_BASE + 0x554) +#define MT_PAGE_CNT_6 (HIF_BASE + 0x558) +#define MT_PAGE_CNT_7 (HIF_BASE + 0x55c) +#define MT_PAGE_CNT_8 (HIF_BASE + 0x560) +#define MT_PAGE_CNT_9 (HIF_BASE + 0x564) +#define MT_PAGE_CNT_10 (HIF_BASE + 0x568) +#define MT_PAGE_CNT_11 (HIF_BASE + 0x56c) +#define MT_PAGE_CNT_12 (HIF_BASE + 0x570) +#define MT_PAGE_CNT_13 (HIF_BASE + 0x574) +#define MT_PAGE_CNT_14 (HIF_BASE + 0x578) +#define MT_PAGE_CNT_15 (HIF_BASE + 0x57c) + +#define MT_QUEUE_PRIORITY_1 (HIF_BASE + 0x580) +#define MT_QUEUE_PRIORITY_2 (HIF_BASE + 0x584) + +#define MT_SCH_REG_1 (HIF_BASE + 0x588) +#define MT_SCH_REG_2 (HIF_BASE + 0x58c) +#define MT_SCH_REG_3 (HIF_BASE + 0x590) +#define MT_SCH_REG_4 (HIF_BASE + 0x594) + +#define MT_GROUP_THD_0 (HIF_BASE + 0x598) +#define MT_GROUP_THD_1 (HIF_BASE + 0x59c) +#define MT_GROUP_THD_2 (HIF_BASE + 0x5a0) +#define MT_GROUP_THD_3 (HIF_BASE + 0x5a4) +#define MT_GROUP_THD_4 (HIF_BASE + 0x5a8) +#define MT_GROUP_THD_5 (HIF_BASE + 0x5ac) + +#define MT_BMAP_0 (HIF_BASE + 0x5b0) +#define MT_BMAP_1 (HIF_BASE + 0x5b4) +#define MT_BMAP_2 (HIF_BASE + 0x5b8) + +#define MT_HIGH_PRIORITY_1 (HIF_BASE + 0x5bc) +#define MT_HIGH_PRIORITY_2 (HIF_BASE + 0x5c0) +#define MT_PRIORITY_MASK (HIF_BASE + 0x5c4) + +#define MT_RSV_MAX_THD (HIF_BASE + 0x5c8) + + + +/* ----------------- ASIC Related MACRO ----------------- */ +/* reset MAC of a station entry to 0x000000000000 */ +#define RTMP_STA_ENTRY_MAC_RESET(pAd, Wcid) \ + AsicDelWcidTab(pAd, Wcid); + +/* add this entry into ASIC RX WCID search table */ +#define RTMP_STA_ENTRY_ADD(pAd, pEntry) \ + AsicUpdateRxWCIDTable(pAd, pEntry->wcid, pEntry->Addr); + +#define RTMP_UPDATE_PROTECT(_pAd, _OperationMode, _SetMask, _bDisableBGProtect, _bNonGFExist) \ + AsicUpdateProtect(pAd, _OperationMode, _SetMask, _bDisableBGProtect, _bNonGFExist); + +#ifdef CONFIG_AP_SUPPORT +#define RTMP_AP_UPDATE_CAPABILITY_AND_ERPIE(pAd) \ + APUpdateCapabilityAndErpIe(pAd); +#endif /* CONFIG_AP_SUPPORT */ + +/* Insert the BA bitmap to ASIC for the Wcid entry */ +#define RTMP_ADD_BA_SESSION_TO_ASIC(_pAd, _wcid, _TID, _SN, _basize, _type) \ + AsicUpdateBASession(_pAd, _wcid, _TID, _SN, _basize, 1, _type); + + +/* 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, _type) \ + AsicUpdateBASession(_pAd, _wcid, _TID, 0, 0, 0, _type); + + +/* ----------------- Interface Related MACRO ----------------- */ + +typedef enum _RTMP_TX_DONE_MASK{ + TX_AC0_DONE = 0x1, + TX_AC1_DONE = 0x2, + TX_AC2_DONE = 0x4, + TX_AC3_DONE = 0x8, + TX_HCCA_DONE = 0x10, + TX_MGMT_DONE = 0x20, + TX_BMC_DONE = 0x40, +}RTMP_TX_DONE_MASK; + + +/* + Enable & Disable NIC interrupt via writing interrupt mask register + Since it use ADAPTER structure, it have to be put after structure definition. +*/ +#define RTMP_ASIC_INTERRUPT_DISABLE(_pAd) \ + do{ \ + RTMP_IO_WRITE32((_pAd), MT_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), MT_INT_MASK_CSR, (_pAd)->int_enable_reg); /* 1:enable */ \ + RTMP_SET_FLAG((_pAd), fRTMP_ADAPTER_INTERRUPT_ACTIVE); \ + }while(0) + +#define RTMP_IRQ_ENABLE(pAd) \ + do{ \ + unsigned long _irqFlags;\ + RTMP_INT_LOCK(&pAd->irq_lock, _irqFlags);\ + /* clear garbage ints */\ + RTMP_IO_WRITE32(pAd, MT_INT_SOURCE_CSR, 0xffffffff); \ + RTMP_ASIC_INTERRUPT_ENABLE(pAd); \ + RTMP_INT_UNLOCK(&pAd->irq_lock, _irqFlags);\ + } while(0) + + + +/* ----------------- MLME Related MACRO ----------------- */ +#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 + + + + +/* ----------------- 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) + + +/* Remove Pairwise Key table */ +#define RTMP_REMOVE_PAIRWISE_KEY_ENTRY(_pAd, _Wcid)\ + AsicRemovePairwiseKeyEntry(_pAd, _Wcid) + +#define MT_ADDREMOVE_KEY(_pAd, _AddRemove, _BssIdx, _KeyIdx, _Wcid, _KeyTabFlag, _pCipherKey, _PeerAddr)\ + CmdProcAddRemoveKey(_pAd, _AddRemove, _BssIdx, _KeyIdx, _Wcid, _KeyTabFlag, _pCipherKey, _PeerAddr) + +struct _RTMP_ADAPTER; +enum _RTMP_TX_DONE_MASK; + +BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(struct _RTMP_ADAPTER *pAd, enum _RTMP_TX_DONE_MASK tx_mask); +VOID RTMPHandleMgmtRingDmaDoneInterrupt(struct _RTMP_ADAPTER *pAd); +VOID RTMPHandleTBTTInterrupt(struct _RTMP_ADAPTER *pAd); +VOID RTMPHandlePreTBTTInterrupt(struct _RTMP_ADAPTER *pAd); +VOID RTMPHandleRxCoherentInterrupt(struct _RTMP_ADAPTER *pAd); + +VOID RTMPHandleMcuInterrupt(struct _RTMP_ADAPTER *pAd); +void RTMPHandleTwakeupInterrupt(struct _RTMP_ADAPTER *pAd); + +VOID mt_asic_init_txrx_ring(struct _RTMP_ADAPTER *pAd); + +#endif /*__MAC_PCI_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/mt_mac_sdio.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/mt_mac_sdio.h new file mode 100644 index 000000000..7d1843262 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/mt_mac_sdio.h @@ -0,0 +1,203 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of MediaTek. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + mt_mac_sdio.h +*/ + +#ifndef __MAC_SDIO_H__ +#define __MAC_SDIO_H__ + +#include "rtmp_type.h" +#include "phy/phy.h" +#include "rtmp_iface.h" +#include "rtmp_dot11.h" + +#define RTMP_START_DEQUEUE(pAd, QueIdx, irqFlags) \ + { \ + RTMP_IRQ_LOCK(&pAd->DeQueueLock[QueIdx], irqFlags); \ + if (pAd->DeQueueRunning[QueIdx]) \ + { \ + RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags);\ + DBGPRINT(RT_DEBUG_TRACE, ("DeQueueRunning[%d]= TRUE!\n", QueIdx)); \ + continue; \ + } \ + else \ + { \ + pAd->DeQueueRunning[QueIdx] = TRUE; \ + RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags);\ + } \ + } + +#define RTMP_STOP_DEQUEUE(pAd, QueIdx, irqFlags) \ + do{ \ + RTMP_IRQ_LOCK(&pAd->DeQueueLock[QueIdx], irqFlags); \ + pAd->DeQueueRunning[QueIdx] = FALSE; \ + RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags); \ + }while(0) + +#define RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, freeNum, pPacket) 1 + +#define RTMP_RELEASE_DESC_RESOURCE(pAd, QueIdx) \ + do{}while(0) + +#define NEED_QUEUE_BACK_FOR_AGG(_pAd, _QueIdx, _freeNum, _TxFrameType) 0 + +#define HAL_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) \ + MtSDIO_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) + +#define HAL_WriteTxResource(pAd, pTxBlk,bIsLast, pFreeNumber) \ + MtSDIO_WriteSingleTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) + + +#define HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) \ + MtSDIO_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) + +#define HAL_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber) \ + MtSDIO_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber) + +#define HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, TxIdx) \ + MtSDIO_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, TxIdx) + +#define HAL_LastTxIdx(pAd, QueIdx,TxIdx) \ + MtSDIODataLastTxIdx(pAd, QueIdx,TxIdx) + +#define HAL_KickOutTx(pAd, pTxBlk, QueIdx) \ + MtSDIODataKickOut(pAd, pTxBlk, QueIdx) + +#define HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen) \ + MtSDIOMgmtKickOut(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen) + +#define HAL_KickOutNullFrameTx(_pAd, _QueIdx, _pNullFrame, _frameLen) \ + do{}while(0) + +#define GET_TXRING_FREENO(_pAd, _QueIdx) (_QueIdx) /*(_pAd->TxRing[_QueIdx].TxSwFreeIdx) */ +#define GET_MGMTRING_FREENO(_pAd) (_pAd->MgmtRing.TxSwFreeIdx) + +/* Insert the BA bitmap to ASIC for the Wcid entry */ +#define RTMP_ADD_BA_SESSION_TO_ASIC(_pAd, _Aid, _TID, _SN, _basize, _type) \ + do{ \ + }while(0) + +/* Remove the BA bitmap from ASIC for the Wcid entry */ +#define RTMP_DEL_BA_SESSION_FROM_ASIC(_pAd, _Wcid, _TID, _type) \ + do{ \ + }while(0) + + +/* + * MLME Related MACRO +*/ + +#define RTMP_MLME_PRE_SANITY_CHECK(pAd) \ + do{}while(0) +/* + { if ((pAd->StaCfg.bHardwareRadio == TRUE) && \ + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && \ + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) { \ + RTEnqueueInternalCmd(pAd, CMDTHREAD_CHECK_GPIO, NULL, 0); } } +*/ +#define RTMP_MLME_RESET_STATE_MACHINE(pAd) \ + do{}while(0) +/* + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_RESET_CONF, 0, NULL, 0); \ + RTMP_MLME_HANDLER(pAd); +*/ +#define RTMP_HANDLE_COUNTER_MEASURE(_pAd, _pEntry)\ + do{}while(0) +/* + { RTEnqueueInternalCmd(_pAd, CMDTHREAD_802_11_COUNTER_MEASURE, _pEntry, sizeof(MAC_TABLE_ENTRY)); \ + RTMP_MLME_HANDLER(_pAd); \ + } +*/ + +/* + * Power Save Related MACRO + */ + +#define RTMP_MLME_RADIO_ON(pAd) \ + do{}while(0) + +#define RTMP_MLME_RADIO_OFF(pAd) \ + do{}while(0) + +#define RTMP_STA_ENTRY_MAC_RESET(pAd, Wcid) \ + do{}while(0) + +/* MAC Search table */ +/* add this entry into ASIC RX WCID search table */ +#define RTMP_STA_ENTRY_ADD(pAd, pEntry) \ + do{}while(0) +/* \ +{ \ + RT_SET_ASIC_WCID Info; \ + \ + Info.WCID = pEntry->wcid; \ + NdisMoveMemory(Info.Addr, pEntry->Addr, MAC_ADDR_LEN); \ + \ + RTEnqueueInternalCmd(pAd, CMDTHREAD_SET_CLIENT_MAC_ENTRY, \ + &Info, sizeof(RT_SET_ASIC_WCID)); \ +} +*/ + +/* ----------------- Security Related MACRO ----------------- */ + +/* Set Asic WCID Attribute table */ +#define RTMP_SET_WCID_SEC_INFO(_pAd, _BssIdx, _KeyIdx, _CipherAlg, _Wcid, _KeyTabFlag) \ + do{}while(0) +/* Set Asic WCID IV/EIV table */ +#define RTMP_ASIC_WCID_IVEIV_TABLE(_pAd, _Wcid, _uIV, _uEIV) \ + do{}while(0) +/* +{ \ + RT_ASIC_WCID_IVEIV_ENTRY Info; \ + \ + Info.Wcid = _Wcid; \ + Info.Iv = _uIV; \ + Info.Eiv = _uEIV; \ + \ + RTEnqueueInternalCmd(_pAd, CMDTHREAD_SET_ASIC_WCID_IVEIV, \ + &Info, \ + sizeof(RT_ASIC_WCID_IVEIV_ENTRY)); \ +} +*/ +/* Set Asic WCID Attribute table */ +#define RTMP_ASIC_WCID_ATTR_TABLE(_pAd, _BssIdx, _KeyIdx, _CipherAlg, _Wcid, _KeyTabFlag)\ + do{}while(0) +/* Set Asic Pairwise key table */ +#define RTMP_ASIC_PAIRWISE_KEY_TABLE(_pAd, _WCID, _pCipherKey) \ + do{}while(0) +/* Set Asic Shared key table */ +#define RTMP_ASIC_SHARED_KEY_TABLE(_pAd, _BssIndex, _KeyIdx, _pCipherKey) \ + do{}while(0) + +#define RTMP_UPDATE_PROTECT(_pAd, _OperationMode, _SetMask, _bDisableBGProtect, _bNonGFExist) \ + do{}while(0) + + +/* Remove Pairwise Key table */ +#define RTMP_REMOVE_PAIRWISE_KEY_ENTRY(_pAd, _Wcid)\ + do{}while(0) +#define MT_ADDREMOVE_KEY(_pAd, _AddRemove, _BssIdx, _KeyIdx, _Wcid, _KeyTabFlag, _pCipherKey, _PeerAddr)\ + do{}while(0) + + +#define RTMP_OS_IRQ_RELEASE(_pAd, _NetDev) + +VOID BeaconUpdateExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +#endif /*__MAC_SDIO_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/mt_mac_usb.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/mt_mac_usb.h new file mode 100644 index 000000000..86d93dd75 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/mt_mac_usb.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: + mac_usb.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __MAC_USB_H__ +#define __MAC_USB_H__ + +#include "rtmp_type.h" +#include "phy/phy.h" +#include "rtmp_iface.h" +#include "rtmp_dot11.h" + + +#define USB_CYC_CFG 0x02a4 + + +#ifdef RTMP_MAC +#define RTMP_USB_DMA_CFG 0x02a0 +#endif /* RTMP_MAC */ + + +#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; +#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; +#endif + + + +/*#define BEACON_RING_SIZE 2 */ +#define MGMTPIPEIDX 5//Carter change 0-->5 /* EP6 is highest priority */ + +/* os abl move */ +/*#define RTMP_PKT_TAIL_PADDING 11 // 3(max 4 byte padding) + 4 (last packet padding) + 4 (MaxBulkOutsize align padding) */ + +#define fRTMP_ADAPTER_NEED_STOP_TX \ + (fRTMP_ADAPTER_NIC_NOT_EXIST | fRTMP_ADAPTER_HALT_IN_PROGRESS | \ + fRTMP_ADAPTER_RESET_IN_PROGRESS | fRTMP_ADAPTER_BULKOUT_RESET | \ + fRTMP_ADAPTER_RADIO_OFF | fRTMP_ADAPTER_REMOVE_IN_PROGRESS) + + +/* ================================================================================= + USB TX / RX Frame Descriptors format + + Tx Memory Layout + 1. Packet Buffer + TxINFO(4 bytes) + TXWI( 16 bytes) + 802.11 + 31 0 + +--------------------------------------------------------------------------+ + | TXINFO[31:0] | + +--------------------------------------------------------------------------+ + | TxWI | + + + + | | + + + + | | + + + + | | + +--------------------------------------------------------------------------+ + | 802.11 | + | ......... | + +--------------------------------------------------------------------------+ + + + Rx Memory Layout + 1. Packet Buffer + RxDMALen(4 bytes) + RXWI(16 bytes) + 802.11 + RXINFO (4 bytes) + 31 0 + +--------------------------------------------------------------------------+ + | RXDMALen[31:0] | + +--------------------------------------------------------------------------+ + | RxWI | + + + + | | + + + + | | + + + + | | + +--------------------------------------------------------------------------+ + | 802.11 | + | ......... | + +--------------------------------------------------------------------------+ + | RXINFO | + +--------------------------------------------------------------------------+ + +================================================================================= */ + + +/* + RXINFO appends at the end of each rx packet +*/ +#define RXDMA_FIELD_SIZE 4 + + +/* + Rx descriptor format, Rx Ring +*/ +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXD_STRUC{ + UINT32 dma_len; +}RXD_STRUC; +#else +typedef struct GNU_PACKED _RXD_STRUC{ + UINT32 dma_len; +}RXD_STRUC; +#endif + + +/* + Management ring buffer format +*/ +typedef struct _MGMT_STRUC { + BOOLEAN Valid; + PUCHAR pBuffer; + ULONG Length; +} MGMT_STRUC, *PMGMT_STRUC; + + +/*////////////////////////////////////////////////////////////////////////*/ +/* The TX_BUFFER structure forms the transmitted USB packet to the device */ +/*////////////////////////////////////////////////////////////////////////*/ +typedef struct __TX_BUFFER{ + union{ + UCHAR WirelessPacket[TX_BUFFER_NORMSIZE]; + HEADER_802_11 NullFrame; + PSPOLL_FRAME PsPollPacket; + RTS_FRAME RTSFrame; + }field; + UCHAR Aggregation[4]; /*Buffer for save Aggregation size. */ +} TX_BUFFER, *PTX_BUFFER; + +typedef struct __HTTX_BUFFER{ + union{ + UCHAR WirelessPacket[MAX_TXBULK_SIZE]; + HEADER_802_11 NullFrame; + PSPOLL_FRAME PsPollPacket; + RTS_FRAME RTSFrame; + }field; + UCHAR Aggregation[4]; /*Buffer for save Aggregation size. */ +} HTTX_BUFFER, *PHTTX_BUFFER; + + +#define EDCA_AC0_PIPE 0 /* Bulk EP1 OUT */ +#define EDCA_AC1_PIPE 1 /* Bulk EP2 OUT */ +#define EDCA_AC2_PIPE 2 /* Bulk EP3 OUT */ +#define EDCA_AC3_PIPE 3 /* Bulk EP4 OUT */ +#ifndef MT_MAC +#define HCCA_PIPE 4 /* Bulk EP5 OUT */ +#endif /*not MT_MAC*/ +#ifdef USE_BMC +#define EDCA_BMC_PIPE 4 /* Bulk EP8 OUT */ +#endif /* USE_BMC */ +#define EDCA_WMM1_AC0_PIPE 9 /* Bulk EP9 OUT */ + +/* used to track driver-generated write irps */ +typedef struct _TX_CONTEXT +{ + PVOID pAd; /*Initialized in MiniportInitialize */ + PURB pUrb; /*Initialized in MiniportInitialize */ +#ifdef USB_IOT_WORKAROUND2 + UINT8 *usb_iot_w2_buf; + ra_dma_addr_t usb_iot_w2_data_dma; /* urb dma on linux */ +#endif + PIRP pIrp; /*used to cancel pending bulk out. */ + /*Initialized in MiniportInitialize */ + PTX_BUFFER TransferBuffer; /*Initialized in MiniportInitialize */ + ULONG BulkOutSize; + UCHAR BulkOutPipeId; + UCHAR SelfIdx; + BOOLEAN InUse; + BOOLEAN bWaitingBulkOut; /* at least one packet is in this TxContext, ready for making IRP anytime. */ + BOOLEAN bFullForBulkOut; /* all tx buffer are full , so waiting for tx bulkout. */ + BOOLEAN IRPPending; + BOOLEAN LastOne; + BOOLEAN bAggregatible; + UCHAR Header_802_3[LENGTH_802_3]; + UCHAR Rsv[2]; + ULONG DataOffset; + UINT TxRate; + ra_dma_addr_t data_dma; + UCHAR *ppkt_tail_before_padding; + +#ifdef UAPSD_SUPPORT + USHORT Wcid; +#endif /* UAPSD_SUPPORT */ +} TX_CONTEXT, *PTX_CONTEXT, **PPTX_CONTEXT; + + +/* used to track driver-generated write irps */ +typedef struct _HT_TX_CONTEXT +{ + PVOID pAd; /*Initialized in MiniportInitialize */ +#ifdef USB_BULK_BUF_ALIGMENT + PURB pUrb[BUF_ALIGMENT_RINGSIZE]; /*Initialized in MiniportInitialize */ +#else + PURB pUrb; /*Initialized in MiniportInitialize */ +#ifdef USB_IOT_WORKAROUND2 + UINT8 *usb_iot_w2_buf; + ra_dma_addr_t usb_iot_w2_data_dma; /* urb dma on linux */ +#endif +#endif /* USB_BULK_BUF_ALIGMENT */ + + PIRP pIrp; /*used to cancel pending bulk out. */ + /*Initialized in MiniportInitialize */ +#ifdef USB_BULK_BUF_ALIGMENT + PHTTX_BUFFER TransferBuffer[BUF_ALIGMENT_RINGSIZE]; /*Initialized in MiniportInitialize */ +#else + PHTTX_BUFFER TransferBuffer; /*Initialized in MiniportInitialize */ +#endif /* USB_BULK_BUF_ALIGMENT */ + + ULONG BulkOutSize; /* Indicate the total bulk-out size in bytes in one bulk-transmission */ + UCHAR BulkOutPipeId; + BOOLEAN IRPPending; + BOOLEAN LastOne; + BOOLEAN bCurWriting; + BOOLEAN bRingEmpty; + BOOLEAN bCopySavePad; + UCHAR SavedPad[8]; + UCHAR Header_802_3[LENGTH_802_3]; + ULONG CurWritePosition; /* Indicate the buffer offset which packet will be inserted start from. */ + ULONG CurWriteRealPos; /* Indicate the buffer offset which packet now are writing to. */ + ULONG NextBulkOutPosition; /* Indicate the buffer start offset of a bulk-transmission */ + ULONG ENextBulkOutPosition; /* Indicate the buffer end offset of a bulk-transmission */ + UINT TxRate; +#ifdef USB_BULK_BUF_ALIGMENT + ra_dma_addr_t data_dma[BUF_ALIGMENT_RINGSIZE]; /* urb dma on linux */ +#else + ra_dma_addr_t data_dma; /* urb dma on linux */ +#endif /* USB_BULK_BUF_ALIGMENT */ + +#ifdef USB_BULK_BUF_ALIGMENT + ULONG CurWriteIdx; /* pointer to next 32k bytes position when wirte tx resource or when bulk out sizze not > 0x6000 */ + ULONG NextBulkIdx; /* pointer to next alignment section when bulk ot */ + ULONG CurtBulkIdx; /* pointer to next alignment section when bulk ot */ +#endif /* USB_BULK_BUF_ALIGMENT */ + +} HT_TX_CONTEXT, *PHT_TX_CONTEXT, **PPHT_TX_CONTEXT; + + +typedef struct _CMD_CONTEXT +{ + PVOID pAd; + PURB pUrb; + ra_dma_addr_t data_dma; + PUCHAR TransferBuffer; + BOOLEAN IRPPending; +} CMD_CONTEXT, *PCMD_CONTEXT, **PPCMD_CONTEXT; + +/* */ +/* Structure to keep track of receive packets and buffers to indicate */ +/* receive data to the protocol. */ +/* */ +typedef struct _RX_CONTEXT +{ + DL_LIST list; + UINT8 Id; + BOOLEAN URBCancel; + ULONG ReadPosition; + PUCHAR TransferBuffer; + PVOID pAd; + PURB pUrb; + ULONG BulkInOffset; + NDIS_SPIN_LOCK RxContextLock; + ra_dma_addr_t data_dma; +} RX_CONTEXT, *PRX_CONTEXT; + + +typedef struct _CMD_RSP_CONTEXT +{ + PUCHAR CmdRspBuffer; + PVOID pAd; + PURB pUrb; + BOOLEAN IRPPending; + BOOLEAN InUse; + BOOLEAN Readable; + ra_dma_addr_t data_dma; +} CMD_RSP_CONTEXT, *PCMD_RSP_CONTEXT; + +/****************************************************************************** + + USB Frimware Related MACRO + +******************************************************************************/ +/* 8051 firmware image for usb - use last-half base address = 0x3000 */ +#define FIRMWARE_IMAGE_BASE 0x3000 +#define MAX_FIRMWARE_IMAGE_SIZE 0x1000 /* 4kbyte */ + +#define RTMP_WRITE_FIRMWARE(_pAd, _pFwImage, _FwLen) \ + RTUSBFirmwareWrite(_pAd, _pFwImage, _FwLen) + + + +/****************************************************************************** + + USB TX Related MACRO + +******************************************************************************/ +#define RTMP_START_DEQUEUE(pAd, QueIdx, irqFlags) \ + { \ + RTMP_IRQ_LOCK(&pAd->DeQueueLock[QueIdx], irqFlags); \ + if (pAd->DeQueueRunning[QueIdx]) \ + { \ + RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags);\ + DBGPRINT(RT_DEBUG_TRACE, ("DeQueueRunning[%d]= TRUE!\n", QueIdx)); \ + continue; \ + } \ + else \ + { \ + pAd->DeQueueRunning[QueIdx] = TRUE; \ + RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags);\ + } \ + } + +#define RTMP_STOP_DEQUEUE(pAd, QueIdx, irqFlags) \ + do{ \ + RTMP_IRQ_LOCK(&pAd->DeQueueLock[QueIdx], irqFlags); \ + pAd->DeQueueRunning[QueIdx] = FALSE; \ + RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags); \ + }while(0) + +#define RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, freeNum, pPacket) \ + (RTUSBFreeDescRequest(pAd, pTxBlk->QueIdx, (pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))) == NDIS_STATUS_SUCCESS) + +#define RTMP_RELEASE_DESC_RESOURCE(pAd, QueIdx) \ + do{}while(0) + +#define NEED_QUEUE_BACK_FOR_AGG(_pAd, _QueIdx, _freeNum, _TxFrameType) \ + ((_TxFrameType == TX_RALINK_FRAME) && (RTUSBNeedQueueBackForAgg(_pAd, _QueIdx))) + +#define HAL_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) \ + RtmpUSB_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) + +#define HAL_WriteTxResource(pAd, pTxBlk,bIsLast, pFreeNumber) \ + RtmpUSB_WriteSingleTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) + +#define HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) \ + RtmpUSB_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) + +#define HAL_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber) \ + RtmpUSB_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber) + +#define HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, TxIdx) \ + RtmpUSB_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, TxIdx) + +#define HAL_LastTxIdx(pAd, QueIdx,TxIdx) \ + /*RtmpUSBDataLastTxIdx(pAd, QueIdx,TxIdx)*/ + +#define HAL_KickOutTx(pAd, pTxBlk, QueIdx) \ + RtmpUSBDataKickOut(pAd, pTxBlk, QueIdx) + +#define HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen) \ + RtmpUSBMgmtKickOut(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen) + +#define HAL_KickOutNullFrameTx(_pAd, _QueIdx, _pNullFrame, _frameLen) \ + RtmpUSBNullFrameKickOut(_pAd, _QueIdx, _pNullFrame, _frameLen) + +#define GET_TXRING_FREENO(_pAd, _QueIdx) (_QueIdx) /*(_pAd->TxRing[_QueIdx].TxSwFreeIdx) */ +#define GET_MGMTRING_FREENO(_pAd) (_pAd->MgmtRing.TxSwFreeIdx) + + +/* ----------------- RX Related MACRO ----------------- */ + + +/* + * MLME Related MACRO + */ + +#define RTMP_MLME_PRE_SANITY_CHECK(pAd) \ + { if ((pAd->StaCfg.bHardwareRadio == TRUE) && \ + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && \ + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) { \ + RTEnqueueInternalCmd(pAd, CMDTHREAD_CHECK_GPIO, NULL, 0); } } + +#define RTMP_MLME_RESET_STATE_MACHINE(pAd) \ + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_RESET_CONF, 0, NULL, 0); \ + RTMP_MLME_HANDLER(pAd); + +#define RTMP_HANDLE_COUNTER_MEASURE(_pAd, _pEntry) \ + { RTEnqueueInternalCmd(_pAd, CMDTHREAD_802_11_COUNTER_MEASURE, _pEntry, sizeof(MAC_TABLE_ENTRY)); \ + RTMP_MLME_HANDLER(_pAd); \ + } + + +/* + * Power Save Related MACRO + */ + +#define RTMP_MLME_RADIO_ON(pAd) \ + UsbMlmeRadioOn(pAd); + +#define RTMP_MLME_RADIO_OFF(pAd) \ + UsbMlmeRadioOFF(pAd); + +/* MAC Search table */ +/* add this entry into ASIC RX WCID search table */ +#define RTMP_STA_ENTRY_ADD(pAd, pEntry) \ +{ \ + RT_SET_ASIC_WCID Info; \ + \ + Info.WCID = pEntry->wcid; \ + NdisMoveMemory(Info.Addr, pEntry->Addr, MAC_ADDR_LEN); \ + \ + RTEnqueueInternalCmd(pAd, CMDTHREAD_SET_CLIENT_MAC_ENTRY, \ + &Info, sizeof(RT_SET_ASIC_WCID)); \ +} + +/* Host got update event from fw, update new beacon */ +#define RTMP_UPDATE_BCN(pAd) \ +{ \ + RTEnqueueInternalCmd(pAd, HWCMD_ID_BCN_UPDATE, NULL, 0); \ +} + +#define RTMP_UPDATE_BMC_CNT(_pAd, _func_idx) \ +{ \ + RTEnqueueInternalCmd(pAd, HWCMD_ID_BMC_CNT_UPDATE, &_func_idx, sizeof(CHAR)); \ +} + +/* ----------------- Security Related MACRO ----------------- */ + +/* Set Asic WCID Attribute table */ +#define RTMP_SET_WCID_SEC_INFO(_pAd, _BssIdx, _KeyIdx, _CipherAlg, _Wcid, _KeyTabFlag) \ +{ \ + RT_ASIC_WCID_SEC_INFO Info; \ + \ + Info.BssIdx = _BssIdx; \ + Info.KeyIdx = _KeyIdx; \ + Info.CipherAlg = _CipherAlg; \ + Info.Wcid = _Wcid; \ + Info.KeyTabFlag = _KeyTabFlag; \ + \ + RTEnqueueInternalCmd(_pAd, CMDTHREAD_SET_WCID_SEC_INFO, \ + &Info, sizeof(RT_ASIC_WCID_SEC_INFO)); \ +} + +/* Set Asic WCID IV/EIV table */ +#define RTMP_ASIC_WCID_IVEIV_TABLE(_pAd, _Wcid, _uIV, _uEIV) \ +{ \ + RT_ASIC_WCID_IVEIV_ENTRY Info; \ + \ + Info.Wcid = _Wcid; \ + Info.Iv = _uIV; \ + Info.Eiv = _uEIV; \ + \ + RTEnqueueInternalCmd(_pAd, CMDTHREAD_SET_ASIC_WCID_IVEIV, \ + &Info, \ + sizeof(RT_ASIC_WCID_IVEIV_ENTRY)); \ +} + +/* Set Asic WCID Attribute table */ +#define RTMP_ASIC_WCID_ATTR_TABLE(_pAd, _BssIdx, _KeyIdx, _CipherAlg, _Wcid, _KeyTabFlag) \ +{ \ + RT_ASIC_WCID_ATTR_ENTRY Info; \ + \ + Info.BssIdx = _BssIdx; \ + Info.KeyIdx = _KeyIdx; \ + Info.CipherAlg = _CipherAlg; \ + Info.Wcid = _Wcid; \ + Info.KeyTabFlag = _KeyTabFlag; \ + \ + RTEnqueueInternalCmd(_pAd, CMDTHREAD_SET_ASIC_WCID_ATTR, \ + &Info, sizeof(RT_ASIC_WCID_ATTR_ENTRY)); \ +} + +/* Set Asic Pairwise key table */ +#define RTMP_ASIC_PAIRWISE_KEY_TABLE(_pAd, _WCID, _pCipherKey) \ +{ \ + RT_ASIC_PAIRWISE_KEY Info; \ + \ + Info.WCID = _WCID; \ + NdisMoveMemory(&Info.CipherKey, _pCipherKey, sizeof(CIPHER_KEY)); \ + \ + RTEnqueueInternalCmd(_pAd, CMDTHREAD_SET_ASIC_PAIRWISE_KEY, \ + &Info, sizeof(RT_ASIC_PAIRWISE_KEY)); \ +} + +/* Set Asic Shared key table */ +#define RTMP_ASIC_SHARED_KEY_TABLE(_pAd, _BssIndex, _KeyIdx, _pCipherKey) \ +{ \ + RT_ASIC_SHARED_KEY Info; \ + \ + Info.BssIndex = _BssIndex; \ + Info.KeyIdx = _KeyIdx; \ + NdisMoveMemory(&Info.CipherKey, _pCipherKey, sizeof(CIPHER_KEY)); \ + \ + RTEnqueueInternalCmd(_pAd, CMDTHREAD_SET_ASIC_SHARED_KEY, \ + &Info, sizeof(RT_ASIC_SHARED_KEY)); \ +} + + +/* Remove Pairwise Key table */ +#define RTMP_REMOVE_PAIRWISE_KEY_ENTRY(_pAd, _Wcid) \ +{ \ + UCHAR _tWcid =_Wcid; \ + RTEnqueueInternalCmd(_pAd, CMDTHREAD_REMOVE_PAIRWISE_KEY, &(_tWcid), sizeof(UCHAR));\ +} + +#define MT_ADDREMOVE_KEY(_pAd, _AddRemove, _BssIdx, _KeyIdx, _Wcid, _KeyTabFlag, _pCipherKey, _PeerAddr) \ +{ \ + MT_ASIC_SEC_INFO Info; \ + \ + Info.AddRemove = _AddRemove; \ + Info.BssIdx = _BssIdx; \ + Info.KeyIdx = _KeyIdx; \ + Info.Wcid = _Wcid; \ + Info.KeyTabFlag = _KeyTabFlag; \ + Info.AddRemove = _AddRemove; \ + NdisMoveMemory(&Info.CipherKey, _pCipherKey, sizeof(CIPHER_KEY)); \ + NdisMoveMemory(Info.Addr, _PeerAddr, MAC_ADDR_LEN); \ + \ + RTEnqueueInternalCmd(_pAd, CMDTHREAD_ADDREMOVE_ASIC_KEY, \ + &Info, sizeof(MT_ASIC_SEC_INFO)); \ +} + +#define RTMP_OS_IRQ_RELEASE(_pAd, _NetDev) + +VOID BeaconUpdateExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +#endif /*__MAC_USB_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/pse.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/pse.h new file mode 100644 index 000000000..6de6da085 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/pse.h @@ -0,0 +1,193 @@ +#ifndef __PSE_H__ +#define __PSE_H__ + +#define PSE_BASE 0x8000 + +/* PSE Global Control Register */ +#define GC (PSE_BASE + 0x00) +#define PSE_ALL_RST (1 << 0) +#define PSE_LOGICAL_RST (1 << 1) +#define PSE_INIT_DONE (1 << 2) +#define GET_PSE_INIT_DONE(p) (((p) & PSE_INIT_DONE) >> 2) + +/* PSE Buffer Control Register */ +#define BC (PSE_BASE + 0x14) +#define TOTAL_PAGE_NUM_MASK (0xfff) +#define GET_TOTAL_PAGE_NUM(p) (((p) & 0xfff)) +#define PAGE_NUM_LMT_EN (1 << 12) +#define GET_PAGE_NUM_LMT_EN(p) (((p) & PAGE_NUM_LMT_EN) >> 12) +#define PAGE_SIZE_CFG_MASK (0x3 << 14) +#define GET_PAGE_SIZE_CFG(p) (((p) & PAGE_SIZE_CFG_MASK) >> 14) + +/* CPU Interface Get First Frame ID Control Regitser */ +#define C_GFF (PSE_BASE + 0x24) +#define GET_FIRST_FID_MASK (0xfff) +#define GET_FIRST_FID(p) (((p) & GET_FIRST_FID_MASK)) +#define GET_QID_MASK (0x1f << 16) +#define SET_GET_QID(p) (((p) & 0x1f) << 16) +#define GET_QID(p) (((p) & GET_QID_MASK) >> 16) +#define GET_PID_MASK (0x3 << 21) +#define SET_GET_PID(p) (((p) & 0x3) << 21) +#define GET_PID(p) (((p) & GET_PID_MASK) >> 21) +#define GET_RVSE_MASK (1 << 23) +#define SET_GET_RVSE(p) (((p) & 0x1) << 23) +#define GET_RVSE(p) (((p) & GET_RVSE_MASK) >> 23) + +/* CPU Interface Get Frame ID Control Register */ +#define C_GF (PSE_BASE + 0x28) +#define GET_RETURN_FID_MASK (0xfff) +#define GET_RETURN_FID(p) (((p) & GET_RETURN_FID_MASK)) +#define CURR_FID_MASK (0xfff << 16) +#define SET_CURR_FID(p) (((p) & 0xfff) << 16) +#define GET_CURR_FID(p) (((p) & CURR_FID_MASK) >> 16) +#define GET_PREV_MASK (1 << 28) +#define SET_GET_PREV(p) (((p) & 0x1) << 28) +#define GET_PREV(p) (((p) & GET_PREV_MASK) >> 28) +#define GET_AUTO_MASK (1 << 29) +#define SET_GET_AUTO(p) (((p) & 0x1) >> 29) +#define GET_AUTO(p) (((p) & GET_AUTO_MASK) >> 29) + +/* Get Queue Length Control Register */ +#define GQC (PSE_BASE + 0x118) +#define QLEN_RETURN_VALUE_MASK (0xfff) +#define GET_QLEN_RETURN_VALUE(p) (((p) & QLEN_RETURN_VALUE_MASK)) +#define GET_QLEN_QID_MASK (0x1f << 16) +#define SET_GET_QLEN_QID(p) (((p) & 0x1f) << 16) +#define GET_QLEN_QID(p) (((p) & GET_QLEN_QID_MASK) >> 16) +#define GET_QLEN_PID_MASK (0x3 << 21) +#define SET_GET_QLEN_PID(p) (((p) & 0x3) << 21) +#define GET_QLEN_PID(p) (((p) & GET_QLEN_PID_MASK) >> 21) +#define QLEN_IN_PAGE (1 << 23) +#define GET_QLEN_IN_PAGE(p) (((p) & QLEN_IN_PAGE) >> 23) + +/* Flow Control P0 Control Register */ +#define FC_P0 (PSE_BASE + 0x120) +#define MIN_RSRV_P0_MASK (0xfff) +#define MIN_RSRV_P0(p) (((p) & 0xfff)) +#define GET_MIN_RSRV_P0(p) (((p) & MIN_RSRV_P0_MASK)) +#define MAX_QUOTA_P0_MASK (0xfff << 16) +#define MAX_QUOTA_P0(p) (((p) & 0xfff) << 16) +#define GET_MAX_QUOTA_P0(p) (((p) & MAX_QUOTA_P0_MASK) >> 16) + +/* Flow Control P1 Control Register */ +#define FC_P1 (PSE_BASE + 0x124) +#define MIN_RSRV_P1_MASK (0xfff) +#define MIN_RSRV_P1(p) (((p) & 0xfff)) +#define GET_MIN_RSRV_P1(p) (((p) & MIN_RSRV_P1_MASK)) +#define MAX_QUOTA_P1_MASK (0xfff << 16) +#define MAX_QUOTA_P1(p) (((p) & 0xfff) << 16) +#define GET_MAX_QUOTA_P1(p) (((p) & MAX_QUOTA_P1_MASK) >> 16) + +/* Flow Control P2_RQ0 Control Register */ +#define FC_P2Q0 (PSE_BASE + 0x128) +#define MIN_RSRV_P2_RQ0_MASK (0xfff) +#define MIN_RSRV_P2_RQ0(p) (((p) & 0xfff)) +#define GET_MIN_RSRV_P2_RQ0(p) (((p) & MIN_RSRV_P2_RQ0_MASK)) +#define MAX_QUOTA_P2_RQ0_MASK (0xfff << 16) +#define MAX_QUOTA_P2_RQ0(p) (((p) & 0xfff) << 16) +#define GET_MAX_QUOTA_P2_RQ0(p) (((p) & MAX_QUOTA_P2_RQ0_MASK) >> 16) + +/* Flow Control P2_RQ1 Control Register */ +#define FC_P2Q1 (PSE_BASE + 0x12c) +#define MIN_RSRV_P2_RQ1_MASK (0xfff) +#define MIN_RSRV_P2_RQ1(p) (((p) & 0xfff)) +#define GET_MIN_RSRV_P2_RQ1(p) (((p) & MIN_RSRV_P2_RQ1_MASK)) +#define MAX_QUOTA_P2_RQ1_MASK (0xfff << 16) +#define MAX_QUOTA_P2_RQ1(p) (((p) & 0xfff) << 16) +#define GET_MAX_QUOTA_P2_RQ1(p) (((p) & MAX_QUOTA_P2_RQ1_MASK) >> 16) + +/* Flow Control P2_RQ2 Control Register */ +#define FC_P2Q2 (PSE_BASE + 0x130) +#define MIN_RSRV_P2_RQ2_MASK (0xfff) +#define MIN_RSRV_P2_RQ2(p) (((p) & 0xfff)) +#define GET_MIN_RSRV_P2_RQ2(p) (((p) & MIN_RSRV_P2_RQ2_MASK)) +#define MAX_QUOTA_P2_RQ2_MASK (0xfff << 16) +#define MAX_QUOTA_P2_RQ2(p) (((p) & 0xfff) << 16) +#define GET_MAX_QUOTA_P2_RQ2(p) (((p) & MAX_QUOTA_P2_RQ2_MASK) >> 16) + +/* Flow Control Free for All and Free Page Counter Register */ +#define FC_FFC (PSE_BASE + 0x134) +#define FREE_PAGE_CNT_MASK (0xfff) +#define GET_FREE_PAGE_CNT(p) (((p) & FREE_PAGE_CNT_MASK)) +#define FFA_CNT_MASK (0xfff << 16) +#define GET_FFA_CNT(p) (((p) & FFA_CNT_MASK) >> 16) + +/* Flow Control Reserve from FFA priority Control Register */ +#define FC_FRP (PSE_BASE + 0x138) +#define RSRV_PRI_P0_MASK (0x7) +#define RSRV_PRI_P0(p) (((p) & 0x7)) +#define GET_RSRV_PRI_P0(p) (((p) & RSRV_PRI_P0_MASK)) +#define RSRV_PRI_P1_MASK (0x7 << 3) +#define RSRV_PRI_P1(p) (((p) & 0x7) << 3) +#define GET_RSRV_PRI_P1(p) (((p) & RSRV_PRI_P1_MASK) >> 3) +#define RSRV_PRI_P2_RQ0_MASK (0x7 << 6) +#define RSRV_PRI_P2_RQ0(p) (((p) & 0x7) << 6) +#define GET_RSRV_PRI_P2_RQ0(p) (((p) & RSRV_PRI_P2_RQ0_MASK) >> 6) +#define RSRV_PRI_P2_RQ1_MASK (0x7 << 9) +#define RSRV_PRI_P2_RQ1(p) (((p) & 0x7) << 9) +#define GET_RSRV_PRI_P2_RQ1(p) (((p) & RSRV_PRI_P2_RQ1_MASK) >> 9) +#define RSRV_PRI_P2_RQ2_MASK (0x7 << 12) +#define RSRV_PRI_P2_RQ2(p) (((p) & 0x7) << 12) +#define GET_RSRV_PRI_P2_RQ2(p) (((p) & RSRV_PRI_P2_RQ2_MASK) >> 12) + +/* Flow Control P0 and P1 Reserve Counter Register */ +#define FC_RP0P1 (PSE_BASE + 0x13c) +#define RSRV_CNT_P0_MASK (0xfff) +#define RSRV_CNT_P0(p) (((p) & 0xfff)) +#define GET_RSRV_CNT_P0(p) (((p) & RSRV_CNT_P0_MASK)) +#define RSRV_CNT_P1_MASK (0xfff << 16) +#define RSRV_CNT_P1(p) (((p) & 0xfff) << 16) +#define GET_RSRV_CNT_P1(p) (((p) & RSRV_CNT_P1_MASK) >> 16) + +/* Flow Control P2_RQ0 and P2_RQ1 Reserve Counter Register */ +#define FC_RP2Q0Q1 (PSE_BASE + 0x140) +#define RSRV_CNT_P2_RQ0_MASK (0xfff) +#define RSRV_CNT_P2_RQ0(p) (((p) & 0xfff)) +#define GET_RSRV_CNT_P2_RQ0(p) (((p) & RSRV_CNT_P2_RQ0_MASK)) +#define RSRV_CNT_P2_RQ1_MASK (0xfff << 16) +#define RSRV_CNT_P2_RQ1(p) (((p) & 0xfff) << 16) +#define GET_RSRV_CNT_P2_RQ1(p) (((p) & RSRV_CNT_P2_RQ1_MASK) >> 16) + +/* Flow Control P2_RQ2 Reserve Counter Register */ +#define FC_RP2Q2 (PSE_BASE + 0x144) +#define RSRV_CNT_P2_RQ2_MASK (0xfff) +#define RSRV_CNT_P2_RQ2(p) (((p) & 0xfff)) +#define GET_RSRV_CNT_P2_RQ2(p) (((p) & RSRV_CNT_P2_RQ2_MASK)) + +/* Flow Control P0 and P1 Source Counter Register */ +#define FC_SP0P1 (PSE_BASE + 0x148) +#define SRC_CNT_P0_MASK (0xfff) +#define GET_SRC_CNT_P0(p) (((p) & SRC_CNT_P0_MASK)) +#define SRC_CNT_P1_MASK (0xfff << 16) +#define GET_SRC_CNT_P1(p) (((p) & SRC_CNT_P1_MASK) >> 16) + +/* FLow Control P2_RQ0 and P2_RQ1 Source Counter Register */ +#define FC_SP2Q0Q1 (PSE_BASE + 0x14c) +#define SRC_CNT_P2_RQ0_MASK (0xfff) +#define GET_SRC_CNT_P2_RQ0(p) (((p) & SRC_CNT_P2_RQ0_MASK)) +#define SRC_CNT_P2_RQ1_MASK (0xfff << 16) +#define GET_SRC_CNT_P2_RQ1(p) (((p) & SRC_CNT_P2_RQ1_MASK) >> 16) + +/* Flow Control P2_RQ2 Source Counter Register */ +#define FC_SP2Q2 (PSE_BASE + 0x150) +#define SRC_CNT_P2_RQ2_MASK (0xfff) +#define GET_SRC_CNT_P2_RQ2(p) (((p) & 0xfff)) + +#define PSE_RTA (PSE_BASE + 0x194) +#define PSE_RTA_RD_RULE_QID_MASK (0x1f) +#define PSE_RTA_RD_RULE_QID(p) (((p) & 0x1f)) +#define GET_PSE_RTA_RD_RULE_QID(p) (((p) & PSE_RTA_RD_RULE_QID_MASK)) +#define PSE_RTA_RD_RULE_PID_MASK (0x3 << 5) +#define PSE_RTA_RD_RULE_PID(p) (((p) & 0x3) << 5) +#define GET_PSE_RTA_RD_RULE_PID(p) (((p) & PSE_RTA_RD_RULE_PID_MASK) >> 5) +#define PSE_RTA_RD_RULE_F (1 << 7) +#define GET_PSE_RTA_RD_RULE_F(p) (((p) & PSE_RTA_RD_RULE_F) >> 7) +#define PSE_RTA_TAG_MASK (0xff << 8) +#define PSE_RTA_TAG(p) (((p) & 0xff) << 8) +#define GET_PSE_RTA_TAG(p) (((p) & PSE_RTA_TAG_MASK) >> 8) +#define PSE_RTA_RD_RW (1 << 16) +#define PSE_RTA_RD_KICK_BUSY (1 << 31) +#define GET_PSE_RTA_RD_KICK_BUSY(p) (((p) & PSE_RTA_RD_KICK_BUSY) >> 31) + + +#endif /* _PSE */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/ral_nmac_usb.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/ral_nmac_usb.h new file mode 100644 index 000000000..83d82c44a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/ral_nmac_usb.h @@ -0,0 +1,33 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + ral_nmac_usb.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RAL_NMAC_USB_H__ +#define __RAL_NMAC_USB_H__ + +#define RLT_USB_DMA_CFG 0x0238 +#define U3DMA_WLCFG 0x9018 + +#endif /*__RAL_NMAC_USB_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/top.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/top.h new file mode 100644 index 000000000..3ef73b697 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/top.h @@ -0,0 +1,48 @@ +/* + *************************************************************************** + * 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: + top.h +*/ + +#ifndef __TOP_H__ +#define __TOP_H__ + +#define TOP_CFG_BASE 0x0000 + +#define TOP_HVR (TOP_CFG_BASE + 0x1000) +#define HW_VER_MASK (0xffff) +#define GET_HW_VER(p) (((p) & HW_VER_MASK)) +#define RESC_CID_MASK (0xf << 28) +#define GET_RESC_CID(p) (((p) & RESC_CID_MASK) >> 28) + +#define TOP_FVR (TOP_CFG_BASE + 0x1004) +#define FW_VER_MASK (0xffff) +#define GET_FW_VER(p) (((p) & FW_VER_MASK)) + +#define TOP_HCR (TOP_CFG_BASE + 0x1008) +#define HW_CODE_MASK (0xffff) +#define GET_HW_CODE(p) (((p) & HW_CODE_MASK)) + +#define STRAP_STA (TOP_CFG_BASE + 0x1010) +#define XTAL_SEL_MASK (0x3) +#define GET_XTAL_SEL(p) (((p) & XTAL_SEL_MASK)) +#define EEPROM_SEL (1 << 2) +#define GET_EEPROM_SEL(p) (((p) & EEPROM_SEL) >> 2) +#define CO_CLOCK_SEL (1 << 8) +#define GET_CO_CLOCK_SEL(p) (((p) & CO_CLOCK_SEL) >> 8) +#define ONE_ANT (1 << 24) +#define GET_ONE_ANT(p) (((p) & ONE_ANT) >> 24) +#define USB_MODE (1 << 25) +#define GET_USB_MODE(p) (((p) & USB_MODE) >> 25 + +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_agg.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_agg.h new file mode 100644 index 000000000..68716fa13 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_agg.h @@ -0,0 +1,207 @@ +/* + *************************************************************************** + * 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: + wf_agg.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifndef __WF_AGG_H__ +#define __WF_AGG_H__ + +#define WF_AGG_BASE 0x21200 + +#define AGG_ARCR (WF_AGG_BASE + 0x010) /* 0x21210 */ +#define INI_RATE1 (0x1 << 0) +#define FB_SGI_DIS (0x1 << 1) +#define RTS_RATE_DOWN_TH_MASK (0x1F << 8) +#define RTS_RATE_DOWN_TH(p) (((p) & 0x1F) << 8) +#define RATE_DOWN_EXTRA_RATIO_MASK (0x3 << 16) +#define RATE_DOWN_EXTRA_RATIO(p) (((p) & 0x3) << 16) +#define RATE_DOWN_EXTRA_RATIO_EN (0x1 << 19) +#define RATE_UP_EXTRA_TH_MASK (0x07 << 20) +#define RATE_UP_EXTRA_TH(p) (((p) & 0x7) << 20) +#define SPE_DIS_TH_MASK (0x0F << 24) +#define SPE_DIS_TH(p) (((p) & 0xF) << 24) + + +#define AGG_ARUCR (WF_AGG_BASE + 0x014) /* 0x21214 */ +#define RATE1_UP_MPDU_LIMIT_MASK (0x7) +#define RATE1_UP_MPDU_LINIT(p) (((p) & 0x7)) +#define RATE2_UP_MPDU_LIMIT_MASK (0x7 << 4) +#define RATE2_UP_MPDU_LIMIT(p) (((p) & 0x7) << 4) +#define RATE3_UP_MPDU_LIMIT_MASK (0x7 << 8) +#define RATE3_UP_MPDU_LIMIT(p) (((p) & 0x7) << 8) +#define RATE4_UP_MPDU_LIMIT_MASK (0x7 << 12) +#define RATE4_UP_MPDU_LIMIT(p) (((p) & 0x7) << 12) +#define RATE5_UP_MPDU_LIMIT_MASK (0x7 << 16) +#define RATE5_UP_MPDU_LIMIT(p) (((p) & 0x7) << 16) +#define RATE6_UP_MPDU_LIMIT_MASK (0x7 << 20) +#define RATE6_UP_MPDU_LIMIT(p) (((p) & 0x7) << 20) +#define RATE7_UP_MPDU_LIMIT_MASK (0x7 << 24) +#define RATE7_UP_MPDU_LIMIT(p) (((p) & 0x7) << 24) +#define RATE8_UP_MPDU_LIMIT_MASK (0X7 << 28) +#define RATE8_UP_MPDU_LIMIT(p) (((p) & 0x7) << 28) + +#define AGG_ARDCR (WF_AGG_BASE + 0x018) /* 0x21218 */ +#define RATE1_DOWN_MPDU_LIMIT_MASK (0x7) +#define RATE1_DOWN_MPDU_LIMIT(p) (((p) & 0x7)) +#define RATE2_DOWN_MPDU_LIMIT_MASK (0x7 << 4) +#define RATE2_DOWN_MPDU_LIMIT(p) (((p) & 0x7) << 4) +#define RATE3_DOWN_MPDU_LIMIT_MASK (0x7 << 8) +#define RATE3_DOWN_MPDU_LIMIT(p) (((p) & 0x7) << 8) +#define RATE4_DOWN_MPDU_LIMIT_MASK (0x7 << 12) +#define RATE4_DOWN_MPDU_LIMIT(p) (((p) & 0x7) << 12) +#define RATE5_DOWN_MPDU_LIMIT_MASK (0x7 << 16) +#define RATE5_DOWN_MPDU_LIMIT(p) (((p) & 0x7) << 16) +#define RATE6_DOWN_MPDU_LIMIT_MASK (0x7 << 20) +#define RATE6_DOWN_MPDU_LIMIT(p) (((p) & 0x7) << 20) +#define RATE7_DOWN_MPDU_LIMIT_MASK (0x7 << 24) +#define RATE7_DOWN_MPDU_LIMIT(p) (((p) & 0x7) << 24) +#define RATE8_DOWN_MPDU_LIMIT_MASK (0x7 << 28) +#define RATE8_DOWN_MPDU_LIMIT(p) (((p) & 0x7) << 28) + +#define AGG_AALCR (WF_AGG_BASE + 0x040) /* 0x21240 */ +#define AC0_AGG_LIMIT_MASK (0x3f) +#define AC0_AGG_LIMIT(p) (((p) & 0x3f)) +#define GET_AC0_AGG_LIMIT(p) (((p) & AC0_AGG_LIMIT_MASK)) +#define AC1_AGG_LIMIT_MASK (0x3f << 8) +#define AC1_AGG_LIMIT(p) (((p) & 0x3f) << 8) +#define GET_AC1_AGG_LIMIT(p) (((p) & AC1_AGG_LIMIT_MASK) >> 8) +#define AC2_AGG_LIMIT_MASK (0x3f << 16) +#define AC2_AGG_LIMIT(p) (((p) & 0x3f) << 16) +#define GET_AC2_AGG_LIMIT(p) (((p) & AC2_AGG_LIMIT_MASK) >> 16) +#define AC3_AGG_LIMIT_MASK (0x3f << 24) +#define AC3_AGG_LIMIT(p) (((p) & 0x3f) << 24) +#define GET_AC3_AGG_LIMIT(p) (((p) & AC3_AGG_LIMIT_MASK) >> 24) + +#define AGG_AALCR1 (WF_AGG_BASE + 0x044) /* 0x21244 */ +#define AC10_AGG_LIMIT_MASK (0x3f) +#define AC10_AGG_LIMIT(p) (((p) & 0x3f)) +#define GET_AC10_AGG_LIMIT(p) (((p) & AC10_AGG_LIMIT_MASK)) +#define AC11_AGG_LIMIT_MASK (0x3f << 8) +#define AC11_AGG_LIMIT(p) (((p) & 0x3f) << 8) +#define GET_AC11_AGG_LIMIT(p) (((p) & AC11_AGG_LIMIT_MASK) >> 8) +#define AC12_AGG_LIMIT_MASK (0x3f << 16) +#define AC12_AGG_LIMIT(p) (((p) & 0x3f) << 16) +#define GET_AC12_AGG_LIMIT(p) (((p) & AC12_AGG_LIMIT_MASK) >> 16) +#define AC13_AGG_LIMIT_MASK (0x3f << 24) +#define AC13_AGG_LIMIT(p) (((p) & 0x3f) << 24) +#define GET_AC13_AGG_LIMIT(p) (((p) & AC13_AGG_LIMIT_MASK) >> 24) + +#define AGG_AWSCR (WF_AGG_BASE + 0x048) /* 0x21248 */ +#define WINSIZE0_MASK (0x3f) +#define WINSIZE0(p) (((p) & 0x3f)) +#define GET_WINSIZE0(p) (((p) & WINSIZE0_MASK)) +#define WINSIZE1_MASK (0x3f << 8) +#define WINSIZE1(p) (((p) & 0x3f) << 8) +#define GET_WINSIZE1(p) (((p) & WINSIZE1_MASK) >> 8) +#define WINSIZE2_MASK (0x3f << 16) +#define WINSIZE2(p) (((p) & 0x3f) << 16) +#define GET_WINSIZE2(p) (((p) & WINSIZE2_MASK) >> 16) +#define WINSIZE3_MASK (0x3f << 24) +#define WINSIZE3(p) (((p) & 0x3f) << 24) +#define GET_WINSIZE3(p) (((p) & WINSIZE3_MASK) >> 24) + +#define AGG_AWSCR1 (WF_AGG_BASE + 0x04c) /* 0x2124c */ +#define WINSIZE4_MASK (0x3f) +#define WINSIZE4(p) (((p) & 0x3f)) +#define GET_WINSIZE4(p) (((p) & WINSIZE4_MASK)) +#define WINSIZE5_MASK (0x3f << 8) +#define WINSIZE5(p) (((p) & 0x3f) << 8) +#define GET_WINSIZE5(p) (((p) & WINSIZE5_MASK) >> 8) +#define WINSIZE6_MASK (0x3f << 16) +#define WINSIZE6(p) (((p) & 0x3f) << 16) +#define GET_WINSIZE6(p) (((p) & WINSIZE6_MASK) >> 16) +#define WINSIZE7_MASK (0x3f << 24) +#define WINSIZE7(p) (((p) & 0x3f) << 24) +#define GET_WINSIZE7(p) (((p) & WINSIZE7_MASK) >> 24) + +#define AGG_PCR (WF_AGG_BASE + 0x050) /* 0x21250 */ +#define MM_PROTECTION (1 << 16) +#define GET_MM_PROTECTION(p) (((p) & MM_PROTECTION) >> 16) +#define GF_PROTECTION (1 << 17) +#define GET_GF_PROTECTION(p) (((p) & GF_PROTECTION) >> 17) +#define PROTECTION_MODE (1 << 19) +#define GET_PROTECTION_MODE(p) (((p) & PROTECTION_MODE) >> 19) +#define BW40_PROTECTION (1 << 20) +#define GET_BW40_PROTECTION(p) (((p) & BW40_PROTECTION) >> 20) +#define RIFS_PROTECTION (1 << 21) +#define GET_RIFS_PROTECTION(p) (((p) & RIFS_PROTECTION) >> 21) +#define BW80_PROTECTION (1 << 22) +#define GET_BW80_PROTECTION(p) (((p) & BW80_PROTECTION) >> 22) +#define BW160_PROTECTION (1 << 23) +#define GET_BW160_PROTECTION(p) (((p) & BW160_PROTECTION) >> 23) +#define ERP_PROTECTION_MASK (0x1f << 24) +#define ERP_PROTECTION(p) (((p) & 0x1f) << 24) +#define GET_ERP_PROTECTION(p) (((p) & ERP_PROTECTION_MASK) >> 24) + + +#define AGG_PCR1 (WF_AGG_BASE + 0x054) /* 0x21254 */ +#define RTS_THRESHOLD_MASK (0xfffff) +#define RTS_THRESHOLD(p) (((p) & 0xfffff)) +#define GET_RTS_THRESHOLD(p) (((p) & RTS_THRESHOLD_MASK)) +#define RTS_PKT_NUM_THRESHOLD_MASK (0x7f << 25) +#define RTS_PKT_NUM_THRESHOLD(p) (((p) & 0x7f) << 25) +#define GET_RTS_PKT_NUM_THRESHOLD(p) (((p) & RTS_PKT_NUM_THRESHOLD_MASK) >> 25) + + +#define AGG_ASRCR (WF_AGG_BASE + 0x060) /* 0x21260 */ +#define AGG_BQCR (WF_AGG_BASE + 0x064) /* 0x21264 */ +#define AGG_BCR (WF_AGG_BASE + 0x068) /* 0x21268 */ + +#define AGG_ACR (WF_AGG_BASE + 0x070) /* 0x21270 */ +#define AMPDU_NO_BA_RULE (1 << 0) +#define GET_AMPDU_NO_BA_RULE(p) (((p) & AMPDU_NO_BA_RULE)) +#define AGG_ACR_AMPDU_NO_BA_AR_RULE_MASK (1 << 1) +#define AGG_ACR_AMPDU_NO_BA_AR_RULE(p) (((p) & 0x1) << 1) +#define GET_AGG_ACR_AMPDU_NO_BA_AR_RULE(p) (((p) & AGG_ACR_AMPDU_NO_BA_AR_RULE_MASK) >> 1) + +#define BAR_RATE_TX_RATE_MASK (0x3f << 20) +#define BAR_RATE_TX_RATE(p) (((p) & 0x3f) << 20) +#define GET_BAR_RATE_TX_RATE(p) (((p) & BAR_RATE_TX_RATE_MASK) >> 20) +#define BAR_RATE_TX_MODE_MASK (0x7 << 26) +#define BAR_RATE_TX_MODE(p) (((p) & 0x7) << 26) +#define GET_BAR_RATE_TX_MODE(p) (((p) & BAR_RATE_TX_MODE_MASK) >> 26) +#define BAR_RATE_NSTS_MASK (0x3 << 29) +#define BAR_RATE_NSTS(p) (((p) & 0x3) << 29) +#define GET_BAR_RATE_NSTS(p) (((p) & BAR_RATE_NSTS_MASK) >> 29) +#define BAR_RATE_STBC (1 << 31) +#define GET_BAR_RATE_STBC(p) (((p) & BAR_RATE_STBC) >> 31) + +#define AGG_ACR1 (WF_AGG_BASE + 0x074) /* 0x21274 */ +#define AGG_BWCR (WF_AGG_BASE + 0x0ec) /* 0x212ec */ +#define AGG_MRCR (WF_AGG_BASE + 0x0f4) /* 0x212f4 */ +#define RTS_RTY_CNT_LIMIT_MASK (0x1f << 7) +#define RTS_RTY_CNT_LIMIT(p) (((p) & 0x1f) << 7) +#define GET_RTS_RTY_CNT_LIMIT(p) (((p) & RTS_RTY_CNT_LIMIT_MASK) >> 7) +#define BAR_TX_CNT_LIMIT_MASK (0x0f << 12) +#define BAR_TX_CNT_LIMIT(p) (((p) & 0x0f) << 12) +#define GET_BAR_TX_CNT_LIMIT(p) (((p) & BAR_TX_CNT_LIMIT_MASK) >> 12) +#define AGG_DSCR1 (WF_AGG_BASE + 0xb4) /* 0x212b4 */ +#define AGG_TEMP (WF_AGG_BASE + 0xd8) + +#endif /* __WF_AGG_H__ */ + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_aon.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_aon.h new file mode 100644 index 000000000..671232633 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_aon.h @@ -0,0 +1,37 @@ +/* + *************************************************************************** + * 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: + wf_aon.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifndef __WF_AON_H__ +#define __WF_AON_H__ + +#define WF_AON_BASE 0x2D000 + + +#endif /* __WF_AON_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_arb.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_arb.h new file mode 100644 index 000000000..42fe0fecb --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_arb.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-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: + wf_arb.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifndef __WF_ARB_H__ +#define __WF_ARB_H__ + +#define WF_ARB_BASE 0x21400 + + + +/********************************************************* + Tx Control Registers +**********************************************************/ + +#define ARB_TQCR0 WF_ARB_BASE + 0x100 /* 0x21500 */ +#define ARB_TQCR1 WF_ARB_BASE + 0x104 /* 0x21504 */ +#define ARB_TQCR2 WF_ARB_BASE + 0x108 /* 0x21508 */ +#define ARB_TQCR3 WF_ARB_BASE + 0x10c /* 0x2150c */ +#define ARB_TQCR4 WF_ARB_BASE + 0x110 /* 0x21510 */ +#define ARB_TQCR5 WF_ARB_BASE + 0x114 /* 0x21514 */ +#define ARB_BCNQCR0 (WF_ARB_BASE + 0x118) /* 0x21518 */ +#define ARB_BCNQCR1 (WF_ARB_BASE + 0x11c) /* 0x2151c */ +#define ARB_BMCQCR0 (WF_ARB_BASE + 0x120) /* 0x21520 */ +#define ARB_BMCQCR1 (WF_ARB_BASE + 0x124) /* 0x21524 */ +#define ARB_BMCQCR2 (WF_ARB_BASE + 0x128) /* 0x21528 */ +#define ARB_BMCQCR3 (WF_ARB_BASE + 0x12c) /* 0x2152c */ +#define ARB_BMCQCR4 (WF_ARB_BASE + 0x130) /* 0x21530 */ +#define ARB_TXENTRYR (WF_ARB_BASE + 0x134) /* 0x21534 */ +#define ARB_BTIMCR0 (WF_ARB_BASE + 0x138) /* 0x21538 */ +#define ARB_BTIMCR1 (WF_ARB_BASE + 0x13c) /* 0x2153c */ +#define ARB_GTQR0 (WF_ARB_BASE + 0x010) /* 0x21410 */ +#define ARB_GTQR1 (WF_ARB_BASE + 0x014) /* 0x21414 */ +#define ARB_GTQR2 (WF_ARB_BASE + 0x018) /* 0x21418 */ +#define ARB_GTQR3 (WF_ARB_BASE + 0x01c) /* 0x2141c */ +#define ARB_AIFSR0 (WF_ARB_BASE + 0x020) /* 0x21420 */ +#define ARB_AIFSR1 (WF_ARB_BASE + 0x024) /* 0x21424 */ +#define ARB_ACCWXR0 (WF_ARB_BASE + 0x028) /* 0x21428 */ +#define ARB_ACCWXR1 (WF_ARB_BASE + 0x02c) /* 0x2142c */ +#define ARB_ACCWXR2 (WF_ARB_BASE + 0x030) /* 0x21430 */ +#define ARB_ACCWXR3 (WF_ARB_BASE + 0x034) /* 0x21434 */ +#define ARB_ACCWXR4 (WF_ARB_BASE + 0x038) /* 0x21438 */ +#define ARB_ACCWXR5 (WF_ARB_BASE + 0x03c) /* 0x2143c */ +#define ARB_ACCWIR0 (WF_ARB_BASE + 0x040) /* 0x21440 */ +#define ARB_ACCWIR1 (WF_ARB_BASE + 0x044) /* 0x21444 */ +#define ARB_ACCWIR2 (WF_ARB_BASE + 0x048) /* 0x21448 */ +#define ARB_ACCWIR3 (WF_ARB_BASE + 0x04c) /* 0x2144c */ +#define ARB_ACCCWR0 (WF_ARB_BASE + 0x050) /* 0x21450 */ +#define ARB_ACCCWR1 (WF_ARB_BASE + 0x054) /* 0x21454 */ +#define ARB_ACCCWR2 (WF_ARB_BASE + 0x058) /* 0x21458 */ +#define ARB_ACCCWR3 (WF_ARB_BASE + 0x05c) /* 0x2145c */ +#define ARB_ACCCWR4 (WF_ARB_BASE + 0x060) /* 0x21460 */ +#define ARB_ACCCWR5 (WF_ARB_BASE + 0x064) /* 0x21464 */ + +/********************************************************* + Rx Cotnrol Registers +**********************************************************/ +#define ARB_RQCR (WF_ARB_BASE + 0x070) /* 0x21470 */ +#define ARB_RQCR_RX_START 0x01 +#define ARB_RQCR_RXV_START 0x10 +#define ARB_RQCR_RXV_R_EN 0x80 +#define ARB_RQCR_RXV_T_EN 0x100 + + +/********************************************************* + System Cotnrol Registers +**********************************************************/ +#define ARB_SCR (WF_ARB_BASE + 0x080) /* 0x21480 */ +#define MT_ARB_SCR_TXDIS BIT8 +#define MT_ARB_SCR_RXDIS BIT9 +#define ARB_SCR_BCNQ_EMPTY_CTRL BIT28 +#define ARB_SCR_TBTT_BTIM_CTRL BIT29 +#define ARB_SCR_TBTT_BCN_CTRL BIT30 +#define ARB_SCR_TBTT_BM_CTRL BIT31 + +//ARB_SCR_BCNQ_OP_MODE +#define BCNQ_OP_MODE_STA 0x0 +#define BCNQ_OP_MODE_AP 0x1 +#define BCNQ_OP_MODE_ADHOC 0x2 +#define ARB_SXCR0 (WF_ARB_BASE + 0x084) /* 0x21484 */ +#define ARB_SXCR1 (WF_ARB_BASE + 0x088) /* 0x21488 */ +#define ARB_SXCR2 (WF_ARB_BASE + 0x08c) /* 0x2148c */ + + + +/********************************************************* + PTA Control Registers +**********************************************************/ + + + +/********************************************************* + PTA Test Registers +**********************************************************/ + + + +#endif /* __WF_ARB_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_cfgoff.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_cfgoff.h new file mode 100644 index 000000000..b5c88205a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_cfgoff.h @@ -0,0 +1,37 @@ +/* + *************************************************************************** + * 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: + wf_cfgoff.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifndef __WF_CFG_OFF_H__ +#define __WF_CFG_OFF_H__ + +#define WF_CFG_OFF_BASE 0x21E00 + + +#endif /* __WF_CFG_OFF_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_dma.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_dma.h new file mode 100644 index 000000000..a1b3a7c65 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_dma.h @@ -0,0 +1,76 @@ +/* + *************************************************************************** + * 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: + wf_dma.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifndef __WF_DMA_H__ +#define __WF_DMA_H__ + +#define WF_DMA_BASE 0x21C00 +#define DMA_DCR0 (WF_DMA_BASE + 0x000) +#define DMA_DCR1 (WF_DMA_BASE + 0x004) /* 0x21c04 */ +#define RXSM_GROUP1_EN (1 << 11) +#define RXSM_GROUP2_EN (1 << 12) +#define RXSM_GROUP3_EN (1 << 13) +#define DMA_RCFR0 (WF_DMA_BASE + 0x070) /* 0x21c70 */ +#define DMA_VCFR0 (WF_DMA_BASE + 0x07c) /* 0x21c7c */ + +#define TXS_ME (1 << 0) +#define TXS_RE (1 << 1) +#define TXS_LE (1 << 2) +#define TXS_BE (1 << 3) +#define TXS_TXOP (1 << 4) +#define TXS_PS (1 << 5) +#define TXS_BAF (1 << 6) +#define DMA_TCFR0 (WF_DMA_BASE + 0x080) /* 0x21c80 */ +#define TXS2M_BIT_MAP_MASK (0x7f) +#define TXS2M_BIT_MAP(p) (((p) & 0x7f)) +#define GET_TXS2M_BIT_MAP(p) (((p) & TXS2M_BIT_MAP_MASK)) +#define TXS2M_AGG_CNT_MASK (0x1f << 8) +#define TXS2M_AGG_CNT(p) (((p) & 0x1f) << 8) +#define GET_TXS2M_AGG_CNT(p) (((p) & TXS2M_AGG_CNT_MASK) >> 8) +#define TXS2M_QID_MASK (0x3 << 14) +#define TXS2M_QID(p) (((p) & 0x3) << 14) +#define GET_TXS2M_QID(p) (((p) & TXS2M_QID_MASK) >> 14) +#define TXS2M_TOUT_MASK (0xfff << 16) +#define TXS2M_TOUT(p) (((p) & 0xfff) << 16) +#define GET_TXS2M_TOUT(p) (((p) & TXS2M_TOUT_MASK) >> 16) +#define DMA_TCFR1 (WF_DMA_BASE + 0x084) /* 0x21c84 */ +#define TXS2H_BIT_MAP_MASK (0x7f) +#define TXS2H_BIT_MAP(p) (((p) & 0x7f)) +#define GET_TXS2H_BIT_MAP(p) (((p) & TXS2H_BIT_MAP_MASK)) +#define TXS2H_AGG_CNT_MASK (0x1f << 8) +#define TXS2H_AGG_CNT(p) (((p) & 0x1f) << 8) +#define GET_TXS2H_AGG_CNT(p) (((p) & TXS2H_AGG_CNT_MASK) >> 8) +#define TXS2H_QID (1 << 14) +#define TXS2H_TOUT_MASK (0xfff << 16) +#define TXS2H_TOUT(p) (((p) & 0xfff) << 16) +#define GET_TXS2H_TOUT(p) (((p) & TXS2H_TOUT_MASK) >> 16) +#define DMA_TMCFR0 (WF_DMA_BASE + 0x088) /* 0x21c88 */ + +#endif /* __WF_DMA_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_int_wakeup_top.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_int_wakeup_top.h new file mode 100644 index 000000000..634f5934d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_int_wakeup_top.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-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: + wf_int_wakeup_top.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- +---------------------------------------------- +*/ +#ifndef __WF_INT_WAKEUP_TOP_H__ +#define __WF_INT_WAKEUP_TOP_H__ + +/* In range of 0x24000 ~ 0x24400 */ +#define WF_INT_WAKEUP_TOP_BASE 0x24400 +#define WISR0 (WF_INT_WAKEUP_TOP_BASE + 0x00) +#define WISR1 (WF_INT_WAKEUP_TOP_BASE + 0x04) +#define WIER0 (WF_INT_WAKEUP_TOP_BASE + 0x08) +#define WIER1 (WF_INT_WAKEUP_TOP_BASE + 0x0c) +#define AHB_CLK_CTL (WF_INT_WAKEUP_TOP_BASE + 0x20) /* 0x24420 */ +#define WISR2 (WF_INT_WAKEUP_TOP_BASE + 0x24) +#define WIER2 (WF_INT_WAKEUP_TOP_BASE + 0x28) +#define WISR3 (WF_INT_WAKEUP_TOP_BASE + 0x2c) +#define WIER3 (WF_INT_WAKEUP_TOP_BASE + 0x30) /* 0x24430 */ +#define WISR4 (WF_INT_WAKEUP_TOP_BASE + 0x34) +#define WIER4 (WF_INT_WAKEUP_TOP_BASE + 0x38) +#define HWISR0 (WF_INT_WAKEUP_TOP_BASE + 0x3c) +#define HWIER0 (WF_INT_WAKEUP_TOP_BASE + 0x40) +#define HWISR1 (WF_INT_WAKEUP_TOP_BASE + 0x44) +#define HWIER1 (WF_INT_WAKEUP_TOP_BASE + 0x48) +#define HWISR2 (WF_INT_WAKEUP_TOP_BASE + 0x4c) /* 0x2444c */ +#define HWIER2 (WF_INT_WAKEUP_TOP_BASE + 0x50) /* 0x24450 */ +#define HWISR3 (WF_INT_WAKEUP_TOP_BASE + 0x54) /* 0x24454 */ +#define TBTT0 (1 << 15) +#define PRETBTT0 (1 << 31) +#define HWIER3 (WF_INT_WAKEUP_TOP_BASE + 0x58) +#define HWISR4 (WF_INT_WAKEUP_TOP_BASE + 0x5c) +#define HWIER4 (WF_INT_WAKEUP_TOP_BASE + 0x60) /* 0x24460 */ + +#endif /* __WF_INT_WAKEUP_TOP_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_lpon_top.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_lpon_top.h new file mode 100644 index 000000000..b262b0f09 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_lpon_top.h @@ -0,0 +1,148 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-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: + wf_lpon_top.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifndef __WF_LPON_TOP_H__ +#define __WF_LPON_TOP_H__ + +/* In range of 0x24000 ~ 0x24400 */ +#define WF_LPON_TOP_BASE 0x24000 +#define LPON_TT0SBOR1 (WF_LPON_TOP_BASE + 0x00) +#define LPON_TT0SBOR2 (WF_LPON_TOP_BASE + 0x04) +#define LPON_TT0SBOR3 (WF_LPON_TOP_BASE + 0x08) +#define LPON_TT0SBOR4 (WF_LPON_TOP_BASE + 0x0c) +#define LPON_TT0SBOR5 (WF_LPON_TOP_BASE + 0x54) +#define LPON_TT0SBOR6 (WF_LPON_TOP_BASE + 0x58) +#define LPON_TT0SBOR7 (WF_LPON_TOP_BASE + 0x64) +#define LPON_TT0SBOR8 (WF_LPON_TOP_BASE + 0x68) +#define LPON_TT0SBOR9 (WF_LPON_TOP_BASE + 0x6c) +#define LPON_TT0SBOR10 (WF_LPON_TOP_BASE + 0x70) +#define LPON_TT0SBOR11 (WF_LPON_TOP_BASE + 0x74) +#define LPON_TT0SBOR12 (WF_LPON_TOP_BASE + 0x78) +#define LPON_TT0SBOR13 (WF_LPON_TOP_BASE + 0x80) +#define LPON_TT0SBOR14 (WF_LPON_TOP_BASE + 0x84) +#define LPON_TT0SBOR15 (WF_LPON_TOP_BASE + 0x8c) +#define LPON_T0CR (WF_LPON_TOP_BASE + 0x10) /* 0x24010 */ +#define LPON_T1CR (WF_LPON_TOP_BASE + 0x14) /* 0x24014 */ +#define LPON_UTTR0 (WF_LPON_TOP_BASE + 0x18) /* 0x24018 */ +#define LPON_UTTR1 (WF_LPON_TOP_BASE + 0x1c) /* 0x2401c */ +#define LPON_BTEIR (WF_LPON_TOP_BASE + 0x20) /* 0x24020 */ +#define LPON_TIMTR (WF_LPON_TOP_BASE + 0x24) /* 0x24024 */ +#define LPON_T0STR (WF_LPON_TOP_BASE + 0x28) /* 0x24028 */ +#define LPON_T1STR (WF_LPON_TOP_BASE + 0x2c) /* 0x2402c */ +#define LPON_PISR (WF_LPON_TOP_BASE + 0x30) /* 0x24030 */ + +#define LPON_T0TPCR (WF_LPON_TOP_BASE + 0x34) /* 0x24034 */ +#define LPON_T1TPCR (WF_LPON_TOP_BASE + 0x38) /* 0x24038 */ +#define BEACONPERIODn_MASK (0xffff) +#define BEACONPERIODn(p) (((p) & 0xffff)) +#define DTIMPERIODn_MASK (0xff << 16) +#define DTIMPERIODn(p) (((p) & 0xff) << 16) +#define TBTTWAKEPERIODn_MASK (0xf << 24) +#define TBTTWAKEPERIODn(p) (((p) & 0xf) << 24) +#define DTIMWAKEPERIODn_MASK (0x7 << 28) +#define DTIMWAKEPERIODn(p) (((p) & 0x7) << 28) +#define TBTTn_CAL_EN (1 << 31) + +#define LPON_TTSR (WF_LPON_TOP_BASE + 0x3c) /* 0x2403c */ +#define LPON_TFRSR (WF_LPON_TOP_BASE + 0x40) /* 0x24040 */ +#define LPON_TSELR (WF_LPON_TOP_BASE + 0x44) /* 0x24044 */ +#define LPON_SPCR (WF_LPON_TOP_BASE + 0x48) /* 0x24048 */ +#define LPON_BCNTR (WF_LPON_TOP_BASE + 0x4c) /* 0x2404c */ +#define LPON_TCLCR (WF_LPON_TOP_BASE + 0x50) /* 0x24050 */ +#define LPON_MPTCR0 (WF_LPON_TOP_BASE + 0x5c) /* 0x2405c */ +#define LPON_MPTCR1 (WF_LPON_TOP_BASE + 0x60) /* 0x24060 */ +#define LPON_FRCR (WF_LPON_TOP_BASE + 0x7c) /* 0x2407c */ +#define LPON_WLANCKCR (WF_LPON_TOP_BASE + 0x88) /* 0x24088 */ + + +#define LPON_SBTOR1 (WF_LPON_TOP_BASE + 0xa0) +#define LPON_SBTOR2 (WF_LPON_TOP_BASE + 0xa4) +#define LPON_SBTOR3 (WF_LPON_TOP_BASE + 0xa8) +#define LPON_SBTOR4 (WF_LPON_TOP_BASE + 0xac) +#define LPON_SBTOR5 (WF_LPON_TOP_BASE + 0xb0) +#define LPON_SBTOR6 (WF_LPON_TOP_BASE + 0xb4) +#define LPON_SBTOR7 (WF_LPON_TOP_BASE + 0xb8) +#define LPON_SBTOR8 (WF_LPON_TOP_BASE + 0xbc) +#define LPON_SBTOR9 (WF_LPON_TOP_BASE + 0xc0) +#define LPON_SBTOR10 (WF_LPON_TOP_BASE + 0xc4) +#define LPON_SBTOR11 (WF_LPON_TOP_BASE + 0xc8) +#define LPON_SBTOR12 (WF_LPON_TOP_BASE + 0xcc) +#define LPON_SBTOR13 (WF_LPON_TOP_BASE + 0xd0) +#define LPON_SBTOR14 (WF_LPON_TOP_BASE + 0xd4) +#define LPON_SBTOR15 (WF_LPON_TOP_BASE + 0xd8) +#define SUB_BSSID0_TIME_OFFSET_n_MASK (0xfffff) +#define SUB_BSSID0_TIME_OFFSET_n(p) (((p) & 0xfffff)) +#define SBSS_TBTT0_TSF0_EN (1 << 29) +#define TBTT0_n_INT_EN (1 << 30) +#define PRE_TBTT0_n_INT_EN (1 << 31) + +#define LPON_MPTCR4 (WF_LPON_TOP_BASE + 0x128) /* 0x24128 */ +#define TTTT0_PERIODTIMER_EN (1 << 0) +#define PRETTTT0_TRIG_EN (1 << 1) +#define TTTT0_TIMEUP_EN (1 << 3) +#define PRETTTT0TIMEUP_EN (1 << 4) +#define TIM_TIMEOUT0_EN (1 << 5) +#define TIM_BMC_TIMEOUT0_EN (1 << 6) +#define PRETTTT0INT_EN (1 << 7) +#define TTTT1PERIODTIMER_EN (1 << 8) +#define PRETTTT1_TRIG_EN (1 << 9) +#define TTTT1_TIMEUP_EN (1 << 11) +#define PRETTTT1TIMEUP_EN (1 << 12) +#define TIM_TIMEOUT1_EN (1 << 13) +#define TIM_BMC_TIMEOUT1_EN (1 << 14) +#define PRETTTT1INT_EN (1 << 15) +#define TIM_PARSE_TIM0_EN (1 << 27) +#define TIM_BMC0_EN (1 << 28) +#define TIM_PARSE_TIM1_EN (1 << 29) +#define TIM_BMC1_EN (1 << 30) + +#define LPON_MPTCR5 (WF_LPON_TOP_BASE + 0x12c) /* 0x2412c */ +#define LPON_PTTISR (WF_LPON_TOP_BASE + 0xdc) /* 0x240dc */ +#define LPON_TT0TPCR (WF_LPON_TOP_BASE + 0xe8) /* 0x240e8 */ +#define LPON_TT1TPCR (WF_LPON_TOP_BASE + 0xec) /* 0x240ec */ +#define LPON_TT2TPCR (WF_LPON_TOP_BASE + 0xf0) /* 0x240f0 */ +#define LPON_TT3TPCR (WF_LPON_TOP_BASE + 0xf4) /* 0x240f4 */ +#define TTTTn_OFFSET_OF_TBTTn_MASK (0x3ffff) +#define TTTTn_OFFSET_OF_TBTTn(p) (((p) & 0x3ffff)) +#define TTTTn_CAL_EN (1 << 31) + +#define LPON_TT4TPCR (WF_LPON_TOP_BASE + 0x1b8) /* 0x241b8 */ +#define LPON_TT5TPCR (WF_LPON_TOP_BASE + 0x1bc) /* 0x241bc */ +#define LPON_TT6TPCR (WF_LPON_TOP_BASE + 0x1c0) /* 0x241c0 */ +#define LPON_TT7TPCR (WF_LPON_TOP_BASE + 0x1c4) /* 0x241c4 */ +#define TIM_PERIODn_MASK (0xffffff) +#define TIM_PERIODn(p) (((p) & 0xffffff)) + +//TSF_TIMER_SW_MODE +#define TSF_TIMER_VALUE_CHANGE 0x1 +#define TSF_TIMER_VALUE_ADJUST 0x2 +#define TSF_TIMER_VALUE_READ 0x3 + +#endif /* __WF_LPON_TOP_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_mib.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_mib.h new file mode 100644 index 000000000..ec3eb6661 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_mib.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-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: + wf_mib.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifndef __WF_MIB_H__ +#define __WF_MIB_H__ + +#define WF_MIB_BASE 0x2C000 + +#define MIB_MSCR (WF_MIB_BASE + 0x00) +#define MIB_MPBSCR (WF_MIB_BASE + 0x04) +#define MIB_MSDR0 (WF_MIB_BASE + 0x08) +#define MIB_MSDR4 (WF_MIB_BASE + 0x18) +#define MIB_MSDR5 (WF_MIB_BASE + 0x1c) +#define MIB_MSDR6 (WF_MIB_BASE + 0x20) +#define MIB_MSDR7 (WF_MIB_BASE + 0x24) +#define MIB_MSDR8 (WF_MIB_BASE + 0x28) +#define MIB_MSDR9 (WF_MIB_BASE + 0x2c) +#define MIB_MSDR10 (WF_MIB_BASE + 0x30) +#define MIB_MSDR11 (WF_MIB_BASE + 0x34) +#define MIB_MSDR12 (WF_MIB_BASE + 0x38) +#define MIB_MSDR14 (WF_MIB_BASE + 0x40) +#define MIB_MSDR15 (WF_MIB_BASE + 0x44) +#define MIB_MSDR16 (WF_MIB_BASE + 0x48) +#define MIB_MSDR17 (WF_MIB_BASE + 0x4c) +#define MIB_MSDR18 (WF_MIB_BASE + 0x50) +#define MIB_MSDR22 (WF_MIB_BASE + 0x60) +#define MIB_MSDR23 (WF_MIB_BASE + 0x64) +#define MIB_MDR0 (WF_MIB_BASE + 0xa0) +#define MIB_MDR1 (WF_MIB_BASE + 0xa4) +#define MIB_MDR2 (WF_MIB_BASE + 0xa8) +#define MIB_MDR3 (WF_MIB_BASE + 0xac) +#define MIB_MB0SDR0 (WF_MIB_BASE + 0x100) +#define MIB_MB1SDR0 (WF_MIB_BASE + 0x110) +#define MIB_MB2SDR0 (WF_MIB_BASE + 0x120) +#define MIB_MB3SDR0 (WF_MIB_BASE + 0x130) +#define MIB_MB0SDR1 (WF_MIB_BASE + 0x104) +#define MIB_MB1SDR1 (WF_MIB_BASE + 0x114) +#define MIB_MB2SDR1 (WF_MIB_BASE + 0x124) +#define MIB_MB3SDR1 (WF_MIB_BASE + 0x134) +#define MIB_MB0SDR2 (WF_MIB_BASE + 0x108) +#define MIB_MB1SDR2 (WF_MIB_BASE + 0x118) +#define MIB_MB2SDR2 (WF_MIB_BASE + 0x128) +#define MIB_MB3SDR2 (WF_MIB_BASE + 0x138) + +#endif /* __WF_SEC_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_pf.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_pf.h new file mode 100644 index 000000000..bdec297c0 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_pf.h @@ -0,0 +1,37 @@ +/* + *************************************************************************** + * 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: + wf_pf.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifndef __WF_PF_H__ +#define __WF_PF_H__ + +#define WF_PF_BASE 0x22000 + + +#endif /* __WF_PF_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_phy.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_phy.h new file mode 100644 index 000000000..42deb095b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_phy.h @@ -0,0 +1,93 @@ +//lala: WF_PHY header +#ifndef __WF_PHY_H__ +#define __WF_PHY_H__ + +#define WF_PHY_BASE 0x10000 + +/* WF_PHY_FRONT */ +#define CR_PHYCK_CTRL WF_PHY_BASE + 0x0000 +#define CR_FR_CKG_CTRL WF_PHY_BASE + 0x0004 +#define CR_FR_RST_CTRL WF_PHY_BASE + 0x0008 + +#define CR_TXPTN_00 WF_PHY_BASE + 0x01A0 +#define CR_TXPTN_01 WF_PHY_BASE + 0x01A4 + +#define CR_RFINTF_00 WF_PHY_BASE + 0x0200 +#define CR_RFINTF_CAL_NSS_MASK (0x3 << 28) +#define CR_RFINTF_CAL_NSS(p) (((p) & 0x3) << 28) +#define CR_RFINTF_01 WF_PHY_BASE + 0x0204 + +#define CR_RFINTF_02 WF_PHY_BASE + 0x0208 +#define CR_RFINTF_03 WF_PHY_BASE + 0x020C +#define CR_AGC_0 WF_PHY_BASE + 0x0500 +#define CR_AGC_0_RX1 WF_PHY_BASE + 0x1500 + +#define CR_AGC_3 WF_PHY_BASE + 0x050c +#define CR_AGC_3_RX1 WF_PHY_BASE + 0x150c + +#define RO_AGC_DEBUG_2 WF_PHY_BASE + 0x05A4 + +#define CR_RXTD_39 WF_PHY_BASE + 0x06F8 +#define CR_FFT_MANU_CTRL WF_PHY_BASE + 0x0704 + +#define CR_DPD_CAL_03 WF_PHY_BASE + 0x090C + +#define CR_TXFE_3 WF_PHY_BASE + 0x0A08 +#define CR_TXFE_4 WF_PHY_BASE + 0x0A0C + +#define CR_TSSI_0 WF_PHY_BASE + 0x0D00 +#define CR_TSSI_1 WF_PHY_BASE + 0x0D04 +#define CR_TSSI_3 WF_PHY_BASE + 0x0D14 +#define CR_TSSI_6 WF_PHY_BASE + 0x0D18 +#define CR_TSSI_9 WF_PHY_BASE + 0x0D24 +#define CR_TSSI_13 WF_PHY_BASE + 0x0D34 + +#define CR_WF1_RFINTF_01 WF_PHY_BASE + 0x1204 +#define CR_WF1_RFINTF_02 WF_PHY_BASE + 0x1208 + +#define CR_TXFE1_3 WF_PHY_BASE + 0x1A08 +#define CR_TXFE1_4 WF_PHY_BASE + 0x1A0C + +#define CR_WF1_TSSI_0 WF_PHY_BASE + 0x1D00 +#define CR_WF1_TSSI_1 WF_PHY_BASE + 0x1D04 +#define CR_WF1_TSSI_3 WF_PHY_BASE + 0x1D14 +#define CR_WF1_TSSI_6 WF_PHY_BASE + 0x1D18 +#define CR_WF1_TSSI_9 WF_PHY_BASE + 0x1D24 +#define CR_WF1_TSSI_13 WF_PHY_BASE + 0x1D34 + +/* WF_PHY_BACK */ +#define CR_BK_RST_CTRL WF_PHY_BASE + 0x4004 + +#define CR_PHYCTRL_0 WF_PHY_BASE + 0x4100 +#define CR_PHYCTRL_2 WF_PHY_BASE + 0x4108 +#define RO_PHYCTRL_STS0 WF_PHY_BASE + 0x410C +#define RO_PHYCTRL_STS1 WF_PHY_BASE + 0x4110 +#define RO_PHYCTRL_STS2 WF_PHY_BASE + 0x4114 +#define RO_PHYCTRL_STS4 WF_PHY_BASE + 0x411C +#define RO_PHYCTRL_STS5 WF_PHY_BASE + 0x4120 + +#define CR_PHYCTRL_DBGCTRL WF_PHY_BASE + 0x4140 + +#define CR_PHYMUX_3 WF_PHY_BASE + 0x420C +#define CR_PHYMUX_5 WF_PHY_BASE + 0x4214 +#define CR_PHYMUX_10 WF_PHY_BASE + 0x4228 +#define CR_PHYMUX_11 WF_PHY_BASE + 0x422C +#define CR_PHYMUX_24 WF_PHY_BASE + 0x4260 +#define CR_PHYMUX_25 WF_PHY_BASE + 0x4264 +#define CR_PHYMUX_26 WF_PHY_BASE + 0x4268 +#define CR_PHYMUX_27 WF_PHY_BASE + 0x426C + +#define CR_TXFD_0 WF_PHY_BASE + 0x4700 +#define CR_TXFD_1 WF_PHY_BASE + 0x4704 +#define CR_TXFD_3 WF_PHY_BASE + 0x470C + +#define CR_PHYMUX_WF1_3 WF_PHY_BASE + 0x520C +#define CR_PHYMUX_WF1_5 WF_PHY_BASE + 0x5214 + + + +#define PHYBACK_CR_PHYMUX_27 (WF_PHY_BASE + 0x426C) +#define PHYBACK_CR_PHYMUX_27_MSK (0xf << 4) +#define SET_CR_PHYMUX_RXV_SEL_G2(mode) (((mode) & 0xf) << 4) + +#endif /* __WF_PHY_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_rmac.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_rmac.h new file mode 100644 index 000000000..a9700bf35 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_rmac.h @@ -0,0 +1,194 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + wf_rmac.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + + +#ifndef __WF_RMAC_H__ +#define __WF_RMAC_H__ + +#define WF_RMAC_BASE 0x21800 + +// TODO: shiang-7603, un-finished yet! + + +/* + Current BSSID 0 Register 0/1 +*/ +#define RMAC_RFCR (WF_RMAC_BASE + 0x00) +#define DROP_STBC_BCN_BC_MC (1 << 0) +#define DROP_FCS_ERROR_FRAME (1 << 1) +#define RX_PROMISCUOUS_MODE (1 << 2) +#define DROP_VERSION_NO_0 (1 << 3) +#define DROP_PROBE_REQ (1 << 4) +#define DROP_MC_FRAME (1 << 5) +#define DROP_BC_FRAME (1 << 6) +#define DROP_NOT_IN_MC_TABLE (1 << 7) +#define DROP_ADDR3_OWN_MAC (1 << 8) +#define DROP_DIFF_BSSID_A3 (1 << 9) +#define DROP_DIFF_BSSID_A2 (1 << 10) +#define DROP_DIFF_BSSID_BCN (1 << 11) +#define RM_FRAME_REPORT_EN (1 << 12) +#define DROP_CTRL_RSV (1 << 13) +#define DROP_CTS (1 << 14) +#define DROP_RTS (1 << 15) +#define DROP_DUPLICATE (1 << 16) +#define DROP_NOT_MY_BSSID (1 << 17) +#define DROP_NOT_UC2ME (1 << 18) +#define DROP_DIFF_BSSID_BTIM (1 << 19) +#define DROP_NDPA (1 << 20) + +/* + Current BSSID 0 Register 0/1 +*/ +#define RMAC_CB0R0 (WF_RMAC_BASE + 0x04) +#define RMAC_CB0R1 (WF_RMAC_BASE + 0x08) +#define RMAC_CB1R0 (WF_RMAC_BASE + 0x0c) +#define RMAC_CB1R1 (WF_RMAC_BASE + 0x10) +#define RMAC_CB2R0 (WF_RMAC_BASE + 0x14) +#define RMAC_CB2R1 (WF_RMAC_BASE + 0x18) +#define RMAC_CB3R0 (WF_RMAC_BASE + 0x1c) +#define RMAC_CB3R1 (WF_RMAC_BASE + 0x20) +#define RMAC_RFCR1 (WF_RMAC_BASE + 0xa4) + +typedef struct _RMAC_CBxR0_STRUC { + UINT32 addr_31_0; +}RMAC_CBxR0_STRUC; + +typedef union _RMAC_CBxR1_STRUC { + struct { + UINT32 addr_47_32: 16; + UINT32 bssid_en:1; + UINT32 rsv_17: 15; + } field; + UINT32 word; +}RMAC_CBxR1_STRUC; + + +/* + OWN MAC Address 0 Register 0/1 +*/ +#define RMAC_OMA0R0 (WF_RMAC_BASE + 0x024) +#define RMAC_OMA0R1 (WF_RMAC_BASE + 0x028) +#define RMAC_OMA1R0 (WF_RMAC_BASE + 0x02c) +#define RMAC_OMA1R1 (WF_RMAC_BASE + 0x030) +#define RMAC_OMA2R0 (WF_RMAC_BASE + 0x034) +#define RMAC_OMA2R1 (WF_RMAC_BASE + 0x038) +#define RMAC_OMA3R0 (WF_RMAC_BASE + 0x03c) +#define RMAC_OMA3R1 (WF_RMAC_BASE + 0x040) +#define RMAC_OMA4R0 (WF_RMAC_BASE + 0x044) +#define RMAC_OMA4R1 (WF_RMAC_BASE + 0x048) +#define RMAC_B01AR_B1AR (WF_RMAC_BASE + 0x04c) +#define RMAC_B23AR_B1AR (WF_RMAC_BASE + 0x050) +#define RMAC_ACBEN (WF_RMAC_BASE + 0x054) + +#define RMAC_MAR0 (WF_RMAC_BASE + 0x060) +#define RMAC_MAR1 (WF_RMAC_BASE + 0x064) +typedef struct _RMAC_MAR0_STRUC{ + UINT32 addr_31_0; +}RMAC_MAR0_STRUC; + +typedef union _RMAC_MAR1_STRUC{ + struct { + UINT32 addr_39_32:8; + UINT32 addr_47_40:8; + UINT32 access_start:1; + UINT32 readwrite:1; + UINT32 rsv18_23:6; + UINT32 multicast_addr_index:5; + UINT32 rsv29:1; + UINT32 multicast_addr_group:2; + } field; + UINT32 word; +}RMAC_MAR1_STRUC; + + +#define BSCR0 (WF_RMAC_BASE + 0x068) + +#define BSCR1 (WF_RMAC_BASE + 0x06c) +#define BA_MAC_ADDR_47_32_MASK (0xffff) +#define BA_MAC_ADDR_47_32(p) (((p) & 0xffff)) +#define RST_BA_TID_MASK (0xf << 16) +#define RST_BA_TID(p) (((p) & 0xf) << 16) +#define RST_BA_SEL_MASK (0x3 << 20) +#define RST_BA_MAC_TID_MATCH 0 +#define RST_BA_MAC_MATCH 1 +#define RST_BA_WITHOUT_MATCH 2 +#define RST_BA_SEL(p) (((p) & 0x3) << 20) +#define START_RST_BA_SB (1 << 22) + +#define RMAC_RMACDR (WF_RMAC_BASE + 0x078) +#define DISABLE_TSF_PROBE_RSP (1 << 0) +#define ENABLE_TSF_TIM (1 << 4) +#define RMACDR_MBSSID_MASK (0x3 << 24) +#define RMACDR_MBSSID(p) (((p) & 0x3) << 24) +#define CHK_HTC_BY_RATE (1 << 26) +#define SELECT_RXMAXLEN_20BIT (1 << 30) + +#define RMAC_RMCR (WF_RMAC_BASE + 0x080) +#define RMAC_RMCR_SMPS_MODE_MASK (0x3 << 20) +#define RMAC_RMCR_SMPS_MODE(p) (((p) & 0x3) << 20) +#define DISABLE_SMPS_RX_BYPASS_SETTING 0 +#define STATIC_SMPS 1 +#define DYNAMIC_SMPS 2 +#define DISABLE_SMPS_RX_BYSETTING 3 +#define RMAC_RMCR_RX_STREAM_0 (1 << 22) +#define RMAC_RMCR_RX_STREAM_1 (1 << 23) +#define RMAC_RMCR_RX_STREAM_2 (1 << 24) +#define RMAC_RMCR_SMPS_BY_RTS (1 << 25) + +#define RMAC_MORE (WF_RMAC_BASE + 0x084) +typedef union _RMAC_MORE_STRUC { + struct { + UINT32 mpdu_len_compare:14; + UINT32 rsv1415:2; + UINT32 rmac_cr_smps_slot_idle:2; + UINT32 rsv1823:8; + UINT32 drop_ndp:1; + UINT32 drop_uc2me_bssid_unmatch:1; + UINT32 rsv2829:2; + UINT32 muar_mode_sel:2; + } field; + + UINT32 word; +}RMAC_MORE_STRUC; + +#define RMAC_CHFREQ (WF_RMAC_BASE + 0x090) +#define RMAC_MISC (WF_RMAC_BASE + 0x094) +#define RMAC_MAXMINLEN (WF_RMAC_BASE + 0x098) +#define RMAC_DROP_MIN_LEN 0xe +#define RMAC_DROP_MIN_LEN_MASK (0xff << 24) +#define RMAC_DROP_MAX_LEN 0x19000 +#define RMAC_DROP_MAX_LEN_MASK (0xfffff) +#define RMAC_PHY_DELAY (WF_RMAC_BASE + 0x0a8) +#define RMAC_TMR_PA (WF_RMAC_BASE + 0x0e0) +#ifdef AIR_MONITOR +#define RMAC_SMESH (WF_RMAC_BASE + 0x114) +#endif +#endif /* __WF_RMAC_H__*/ + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_sec.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_sec.h new file mode 100644 index 000000000..c7a83f76e --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_sec.h @@ -0,0 +1,37 @@ +/* + *************************************************************************** + * 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: + wf_sec.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifndef __WF_SEC_H__ +#define __WF_SEC_H__ + +#define WF_SEC_BASE 0x21A00 +#define SEC_SCR (WF_SEC_BASE + 0x004) + +#endif /* __WF_SEC_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_tmac.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_tmac.h new file mode 100644 index 000000000..5373c1ba1 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_tmac.h @@ -0,0 +1,238 @@ +/* + *************************************************************************** + * 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: + wf_tmac.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __WF_TMAC_H__ +#define __WF_TMAC_H__ + +#define WF_TMAC_BASE 0x21600 + +#define TMAC_TCR (WF_TMAC_BASE + 0x00) +#define TX_BLINK_SEL_MASK (0x3 << 6) +#define TX_BLINK_SEL(p) (((p) & 0x3) << 6) +#define PRE_RTS_DET_GUARD_TIME_MASK (0xf << 8) +#define PRE_RTS_DET_GUARD_TIME(p) (((p) & 0xf) << 8) +#define PRE_RTS_SEC_IDLE_SEL_MASK (0x3 << 12) +#define PRE_RTS_SEC_IDLE_SEL(p) (((p) & 0x3) << 12) +#define RTS_SIGTA_EN (1 << 14) +#define LDPC_OFST_EN (1 << 15) +#define TMAC_TCR_TX_STREAM_NUM_MASK (0x3 << 16) +#define TMAC_TCR_TX_STREAM_NUM(p) (((p) & 0x3) << 16) +#define GET_TMAC_TCR_TX_STREAM_NUM(p) (((p) & TMAC_TCR_TX_STREAM_NUM_MASK) >> 16) +#define SCH_IDLE_SEL_MASK (0x3 << 18) +#define SCH_IDLE_SEL(p) (((p) & 0x3) << 18) +#define SCH_DET_PER_IOD (1 << 20) +#define DCH_DET_DIS (1 << 21) +#define TX_RIFS_EN (1 << 22) +#define GET_TX_RIFS_EN(p) (((p) & TX_RIFS_EN) >> 22) +#define RX_RIFS_MODE (1 << 23) +#define GET_RX_RIFS_MODE(p) (((p) & RX_RIFS_MODE) >> 23) +#define TXOP_TBTT_CONTROL (1 << 24) +#define GET_TXOP_TBTT_CONTROL(p) (((p) & TXOP_TBTT_CONTROL) >> 24) +#define TBTT_TX_STOP_CONTROL (1 << 25) +#define GET_TBTT_TX_STOP_CONTROL(p) (((p) & TBTT_TX_STOP_CONTROL) >> 25) +#define TXOP_BURST_STOP (1 << 26) +#define GET_TXOP_BURST_STOP(p) (((p) & TXOP_BURST_STOP) >> 26) +#define RDG_RA_MODE (1 << 27) +#define GET_RDG_RA_MODE(p) (((p) & RDG_RA_MODE) >> 27) +#define RDG_RESP_EN (1 << 29) +#define GET_RDG_RESP_EN(p) (((p) & RDG_RESP_EN) >> 29) +#define GRANT_REVERSE_WHEN_NO_PENDING_FRM (1 << 30) +#define SMOOTHING (1 << 31) +#define GET_SMOOTHING(p) (((p) & SMOOTHING) >> 31) + +#define TMAC_PSCR (WF_TMAC_BASE + 0x04) +#define APS_OFF_TIME_MASK (0xff << 1) +#define APS_OFF_TIME(p) (((p) & 0xff) << 1) +#define GET_APS_OFF_TIME(p) (((p) & APS_OFF_TIME_MASK) >> 1) +#define APS_ON_TIME_MASK (0x3f << 10) +#define APS_ON_TIME(p) (((p) & 0x3f) << 10) +#define GET_APS_ON_TIME(p) (((p) & APS_ON_TIME_MASK) >> 10) +#define APS_HALT_TIME_MASK (0x3ff << 16) +#define APS_HALT_TIME(p) (((p) & 0x3ff) << 16) +#define GET_APS_HALT_TIME(p) (((p) & APS_HALT_TIME_MASK) >> 16) +#define APS_EN (1 << 28) +#define GET_APS_EN(p) (((p) & APS_EN) >> 28) + +#define TMAC_ACTXOPLR0 (WF_TMAC_BASE + 0x10) +#define AC2LIMIT_MASK (0xffff) +#define AC2LIMIT(p) (((p) & 0xffff)) +#define GET_AC2LIMIT(p) (((p) & AC2LIMIT_MASK)) +#define AC3LIMIT_MASK (0xffff << 16) +#define AC3LIMIT(p) (((p) & 0xffff) << 16) +#define GET_AC3LIMIT(p) (((p) & AC3LIMIT_MASK) >> 16) + +#define TMAC_ACTXOPLR1 (WF_TMAC_BASE + 0x14) +#define AC0LIMIT_MASK (0xffff) +#define AC0LIMIT(p) (((p) & 0xffff)) +#define GET_AC0LIMIT(p) (((p) & AC0LIMIT_MASK)) +#define AC1LIMIT_MASK (0xffff << 16) +#define AC1LIMIT(p) (((p) & 0xffff) << 16) +#define GET_AC1LIMIT(p) (((p) & AC1LIMIT_MASK) >> 16) + +#define TMAC_ACTXOPLR2 (WF_TMAC_BASE + 0x18) +#define AC12LIMIT_MASK (0xffff) +#define AC12LIMIT(p) (((p) & 0xffff)) +#define GET_AC12LIMIT(p) (((p) & AC12LIMIT_MASK)) +#define AC13LIMIT_MASK (0xffff << 16) +#define AC13LIMIT(p) (((p) & 0xffff) << 16) +#define GET_AC13LIMIT(p) (((p) & AC13LIMIT_MASK) >> 16) + +#define TMAC_ACTXOPLR3 (WF_TMAC_BASE + 0x1c) +#define AC10LIMIT_MASK (0xffff) +#define AC10LIMIT(p) (((p) & 0xffff)) +#define GET_AC10LIMIT(p) (((p) & AC10LIMIT_MASK)) +#define AC11LIMIT_MASK (0xffff << 16) +#define AC11LIMIT(p) (((p) & 0xffff) << 16) +#define GET_AC11LIMIT(p) (((p) & AC11LIMIT_MASK) >> 16) + +#define TMAC_FP0R0 (WF_TMAC_BASE + 0x20) +#define LG_OFDM0_FRAME_POWER0_DBM_MASK (0x7f) +#define LG_OFDM0_FRAME_POWER0_DBM(p) (((p) & 0x7f)) +#define LG_OFDM1_FRAME_POWER0_DBM_MASK (0x7f << 8) +#define LG_OFDM1_FRAME_POWER0_DBM(p) (((p) & 0x7f) << 8) +#define LG_OFDM2_FRAME_POWER0_DBM_MASK (0x7f << 16) +#define LG_OFDM2_FRAME_POWER0_DBM(p) (((p) & 0x7f) << 16) +#define LG_OFDM3_FRAME_POWER0_DBM_MASK (0x7f << 24) +#define LG_OFDM3_FRAME_POWER0_DBM(p) (((p) & 0x7f) << 24) + +#define TMAC_FP0R1 (WF_TMAC_BASE + 0x24) +#define HT20_0_FRAME_POWER0_DBM_MASK (0x7f) +#define HT20_0_FRAME_POWER0_DBM(p) (((p) & 0x7f)) +#define HT20_1_FRAME_POWER0_DBM_MASK (0x7f << 8) +#define HT20_1_FRAME_POWER0_DBM(p) (((p) & 0x7f) << 8) +#define HT20_2_FRAME_POWER0_DBM_MASK (0x7f << 16) +#define HT20_2_FRAME_POWER0_DBM(p) (((p) & 0x7f) << 16) +#define HT20_3_FRAME_POWER0_DBM_MASK (0x7f << 24) +#define HT20_3_FRAME_POWER0_DBM(p) (((p) & 0x7f) << 24) + +#define TMAC_FP0R2 (WF_TMAC_BASE + 0x28) +#define HT40_0_FRAME_POWER0_DBM_MASK (0x7f) +#define HT40_0_FRAME_POWER0_DBM(p) (((p) & 0x7f)) +#define HT40_1_FRAME_POWER0_DBM_MASK (0x7f << 8) +#define HT40_1_FRAME_POWER0_DBM(p) (((p) & 0x7f) << 8) +#define HT40_2_FRAME_POWER0_DBM_MASK (0x7f << 16) +#define HT40_2_FRAME_POWER0_DBM(p) (((p) & 0x7f) << 16) +#define HT40_3_FRAME_POWER0_DBM_MASK (0x7f << 24) +#define HT40_3_FRAME_POWER0_DBM(p) (((p) & 0x7f) << 24) + +#define TMAC_FP0R3 (WF_TMAC_BASE + 0x2C) +#define CCK0_FRAME_POWER0_DBM_MASK (0x7f) +#define CCK0_FRAME_POWER0_DBM(p) (((p) & 0x7f)) +#define LG_OFDM4_FRAME_POWER0_DBM_MASK (0x7f << 8) +#define LG_OFDM4_FRAME_POWER0_DBM(p) (((p) & 0x7f) << 8) +#define CCK1_FRAME_POWER0_DBM_MASK (0x7f << 16) +#define CCK1_FRAME_POWER0_DBM(p) (((p) & 0x7f) << 16) +#define HT40_6_FRAME_POWER0_DBM_MASK (0x7f << 24) +#define HT40_6_FRAME_POWER0_DBM(p) (((p) & 0x7f) << 24) + +#define TMAC_FP0R4 (WF_TMAC_BASE + 0x30) +#define HT20_4_FRAME_POWER0_DBM_MASK (0x7f) +#define HT20_4_FRAME_POWER0_DBM(p) (((p) & 0x7f)) +#define HT20_5_FRAME_POWER0_DBM_MASK (0x7f << 8) +#define HT20_5_FRAME_POWER0_DBM(p) (((p) & 0x7f) << 8) +#define HT40_4_FRAME_POWER0_DBM_MASK (0x7f << 16) +#define HT40_4_FRAME_POWER0_DBM(p) (((p) & 0x7f) << 16) +#define HT40_5_FRAME_POWER0_DBM_MASK (0x7f << 24) +#define HT40_5_FRAME_POWER0_DBM(p) (((p) & 0x7f) << 24) + +#define TMAC_CDTR (WF_TMAC_BASE + 0x90) +#define TMAC_ODTR (WF_TMAC_BASE + 0x94) + +#define ATCR (WF_TMAC_BASE + 0x98) +#define TXV_TOUT_MASK (0xff) +#define TXV_TOUT(p) (((p) & 0xff)) +#define GET_TXV_TOUT(p) (((p) & TXV_TOUT_MASK)) +#define RIFS_TXV_TOUT_MASK (0xff << 8) +#define RIFS_TXV_TOUT(p) (((p) & 0xff) << 8) +#define GET_RIFS_TXV_TOUT(p) (((p) & RIFS_TXV_TOUT_MASK) >> 8) +#define AGG_TOUT_MASK (0xff << 16) +#define AGG_TOUT(p) (((p) & 0xff) << 16) +#define GET_AGG_TOUT(p) (((p) & AGG_TOUT_MASK) >> 16) + +#define TMAC_TRCR (WF_TMAC_BASE + 0x9C) +#define CCA_SRC_SEL_MASK (0x3 << 30) +#define CCA_SRC_SEL(p) (((p) & 0x3) << 30) +#define CCA_SEC_SRC_SEL_MASK (0x3 << 28) +#define CCA_SEC_SRC_SEL(p) (((p) & 0x3) << 28) +#define I2T_CHK_EN BIT25 + +#define TMAC_RRCR (WF_TMAC_BASE + 0xA0) + +#define TMAC_ICR (WF_TMAC_BASE + 0xa4) +#define ICR_EIFS_TIME_MASK (0x1ff) +#define ICR_EIFS_TIME(p) (((p) & 0x1ff)) +#define GET_ICR_EIFS_TIME(p) (((p) & ICR_EIFS_TIME_MASK)) +#define ICR_RIFS_TIME_MASK (0x1f << 10) +#define ICR_RIFS_TIME(p) (((p) & 0x1f) << 10) +#define GET_ICR_RIFS_TIME(p) (((p) & ICR_RIFS_TIME_MASK) >> 10) +#define ICR_SIFS_TIME_MASK (0x7f << 16) +#define ICR_SIFS_TIME(p) (((p) & 0x7f) << 16) +#define GET_ICR_SIFS_TIME(p) (((p) & ICR_SIFS_TIME_MASK) >> 16) +#define ICR_SLOT_TIME_MASK (0x7f << 24) +#define ICR_SLOT_TIME(p) (((p) & 0x7f) << 24) +#define GET_ICR_SLOT_TIME(p) (((p) & ICR_SLOT_TIME_MASK) >> 24) + +#define TMAC_PCR (WF_TMAC_BASE + 0xb4) +#define PTEC_FIX_RATE_MASK (0x1ff) +#define PTEC_FIX_RATE(p) (((p) & 0x1ff)) +#define GET_PTEC_FIX_RATE(p) (((p) & PTEC_FIX_RATE_MASK)) +#define PTEC_RATE_SEL (1 << 15) +#define GET_PTEC_RATE_SEL(p) (((p) & PTEC_RATE_SEL) >> 15) +#define PTEC_ANT_ID_MASK (0x3f << 16) +#define PTEC_ANT_ID(p) (((p) & 0x3f) << 16) +#define GET_PTEC_ANT_ID(p) (((p) & PTEC_ANT_ID_MASK) >> 16) +#define PTEC_ANT_ID_SEL (1 << 22) +#define GET_PTEC_ANT_ID_SEL(p) (((p) & PTEC_ANT_ID_SEL) >> 22) +#define PTEC_SPE_EN (1 << 23) +#define GET_PTEC_SPE_EN(p) (((p) & PTEC_SPE_EN) >> 23) +#define PTEC_ANT_PRI_MASK (0x7 << 24) +#define PTEC_ANT_PRI(p) (((p) & 0x7) << 24) +#define GET_PTEC_ANT_PRI(p) (((p) & PTEC_ANT_PRI_MASK) >> 24) +#define PTEC_ANT_PRI_SEL (1 << 27) +#define GET_PTEC_ANT_PRI_SEL(p) (((p) & PTEC_ANT_PRI_SEL) >> 27) + +#define TMAC_B0BRR0 (WF_TMAC_BASE + 0xc0) +#define TMAC_B1BRR0 (WF_TMAC_BASE + 0xc8) +#define TMAC_B2BRR0 (WF_TMAC_BASE + 0xd0) +#define TMAC_B3BRR0 (WF_TMAC_BASE + 0xd8) +#define BSSID00_RESP_SPE_EN (1 << 16) + +#define TMAC_B0BRR1 (WF_TMAC_BASE + 0xc4) +#define TMAC_B1BRR1 (WF_TMAC_BASE + 0xcc) +#define TMAC_B2BRR1 (WF_TMAC_BASE + 0xd4) +#define TMAC_B3BRR1 (WF_TMAC_BASE + 0xdc) +#define TMAC_QNCR0 (WF_TMAC_BASE + 0xe0) +#define TMAC_QNCR1 (WF_TMAC_BASE + 0xe4) +#define TMAC_QNCR2 (WF_TMAC_BASE + 0xe8) +#define TMAC_QNCR3 (WF_TMAC_BASE + 0xec) +#define TMAC_QNCR4 (WF_TMAC_BASE + 0xf0) + +#define TMAC_PCTSR (WF_TMAC_BASE + 0x108) + +#endif /* __WF_TMAC_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_trb.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_trb.h new file mode 100644 index 000000000..8065fe173 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_trb.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-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: + wf_trb.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifndef __WF_TRB_H__ +#define __WF_TRB_H__ + +#define WF_TRB_BASE 0x21000 +#define TRB_GCR (WF_TRB_BASE + 0x000) +#define TRB_TXBSR (WF_TRB_BASE + 0x020) +#define TRB_RXBSR (WF_TRB_BASE + 0x040) + +#endif /* __WF_TRB_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_wtbl.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_wtbl.h new file mode 100644 index 000000000..027bb5be3 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_wtbl.h @@ -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: + wf_wtbl.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifndef __WF_WTBL_H__ +#define __WF_WTBL_H__ + +/* + WTBL segment 1 definitions +*/ +typedef struct GNU_PACKED wtbl_1_struc { + union WTBL_1_DW0 wtbl_1_d0; + union WTBL_1_DW1 wtbl_1_d1; + union WTBL_1_DW2 wtbl_1_d2; + union WTBL_1_DW3 wtbl_1_d3; + union WTBL_1_DW4 wtbl_1_d4; + UINT32 dummy[3]; +}WTBL_1_STRUC; + + +/* + WTBL segment 2 definitions +*/ +union WTBL_2_DW0 { + UINT32 pn_0; + UINT32 word; +}; + +#ifdef RT_BIG_ENDIAN +union WTBL_2_DW1 { + struct { + UINT32 rsv_1_28:4; + UINT32 com_sn:12; + UINT32 pn_32:16; + } field; + UINT32 word; +}; +#else +union WTBL_2_DW1 { + struct { + UINT32 pn_32:16; + UINT32 com_sn:12; + UINT32 rsv_1_28:4; + } field; + UINT32 word; +}; +#endif + +#ifdef RT_BIG_ENDIAN +union WTBL_2_DW2 { + struct { + UINT32 tid_ac_2_sn_0:8; + UINT32 tid_ac_1_sn:12; + UINT32 tid_ac_0_sn:12; + } field; + UINT32 word; +}; +#else +union WTBL_2_DW2 { + struct { + UINT32 tid_ac_0_sn:12; + UINT32 tid_ac_1_sn:12; + UINT32 tid_ac_2_sn_0:8; + } field; + UINT32 word; +}; +#endif + +#ifdef RT_BIG_ENDIAN +union WTBL_2_DW3 { + struct { + UINT32 tid_5_sn_0:4; + UINT32 tid_4_sn:12; + UINT32 tid_ac_3_sn:12; + UINT32 tid_ac_2_sn_9:4; + } field; + UINT32 word; +}; +#else +union WTBL_2_DW3 { + struct { + UINT32 tid_ac_2_sn_9:4; + UINT32 tid_ac_3_sn:12; + UINT32 tid_4_sn:12; + UINT32 tid_5_sn_0:4; + } field; + UINT32 word; +}; +#endif + +#ifdef RT_BIG_ENDIAN +union WTBL_2_DW4 { + struct { + UINT32 tid_7_sn:12; + UINT32 tid_6_sn:12; + UINT32 tid_5_sn_5:8; + } field; + UINT32 word; +}; +#else +union WTBL_2_DW4 { + struct { + UINT32 tid_5_sn_5:8; + UINT32 tid_6_sn:12; + UINT32 tid_7_sn:12; + } field; + UINT32 word; +}; +#endif + +#ifdef RT_BIG_ENDIAN +union WTBL_2_DW5 { + struct { + UINT32 rate_1_fail_cnt:16; + UINT32 rate_1_tx_cnt:16; + } field; + UINT32 word; +}; +#else +union WTBL_2_DW5 { + struct { + UINT32 rate_1_tx_cnt:16; + UINT32 rate_1_fail_cnt:16; + } field; + UINT32 word; +}; +#endif + +#ifdef RT_BIG_ENDIAN +union WTBL_2_DW6 { + struct { + UINT32 rate_5_tx_cnt:8; + UINT32 rate_4_tx_cnt:8; + UINT32 rate_3_tx_cnt:8; + UINT32 rate_2_tx_cnt:8; + } field; + UINT32 word; +}; +#else +union WTBL_2_DW6 { + struct { + UINT32 rate_2_tx_cnt:8; + UINT32 rate_3_tx_cnt:8; + UINT32 rate_4_tx_cnt:8; + UINT32 rate_5_tx_cnt:8; + } field; + UINT32 word; +}; +#endif + +#ifdef RT_BIG_ENDIAN +union WTBL_2_DW7 { + struct { + UINT32 current_bw_fail_cnt:16; + UINT32 current_bw_tx_cnt:16; + } field; + UINT32 word; +}; +#else +union WTBL_2_DW7 { + struct { + UINT32 current_bw_tx_cnt:16; + UINT32 current_bw_fail_cnt:16; + } field; + UINT32 word; +}; +#endif + +#ifdef RT_BIG_ENDIAN +union WTBL_2_DW8 { + struct { + UINT32 other_bw_fail_cnt:16; + UINT32 other_bw_tx_cnt:16; + } field; + UINT32 word; +}; +#else +union WTBL_2_DW8 { + struct { + UINT32 other_bw_tx_cnt:16; + UINT32 other_bw_fail_cnt:16; + } field; + UINT32 word; +}; +#endif + +#ifdef RT_BIG_ENDIAN +union WTBL_2_DW9 { + struct { + UINT32 rate_idx:3; + UINT32 mpdu_ok_cnt:3; + UINT32 mpdu_fail_cnt:3; + UINT32 rsv_9_20:3; + UINT32 g16:1; + UINT32 g8:1; + UINT32 g4:1; + UINT32 g2:1; + UINT32 fcap:2; + UINT32 cbrn:3; + UINT32 ccbw_sel:2; + UINT32 ant_pri:3; + UINT32 spe_en:1; + UINT32 tx_pwr_offset:5; + } field; + UINT32 word; +}; +#else +union WTBL_2_DW9 { + struct { + UINT32 tx_pwr_offset:5; + UINT32 spe_en:1; + UINT32 ant_pri:3; + UINT32 ccbw_sel:2; + UINT32 cbrn:3; + UINT32 fcap:2; + UINT32 g2:1; + UINT32 g4:1; + UINT32 g8:1; + UINT32 g16:1; + UINT32 rsv_9_20:3; + UINT32 mpdu_fail_cnt:3; + UINT32 mpdu_ok_cnt:3; + UINT32 rate_idx:3; + } field; + UINT32 word; +}; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED wtbl_tx_rate { + UINT16 rsv_12:4; + UINT16 stbc:1; + UINT16 n_sts:2; + UINT16 tx_mode:3; + UINT16 tx_rate:6; +} WTBL_TX_RATE; +#else +typedef struct GNU_PACKED wtbl_tx_rate { + UINT16 tx_rate:6; + UINT16 tx_mode:3; + UINT16 n_sts:2; + UINT16 stbc:1; + UINT16 rsv_12:4; +} WTBL_TX_RATE; +#endif + + +#ifdef RT_BIG_ENDIAN +union WTBL_2_DW10 { + struct { + UINT32 rate_3_0:8; + UINT32 rate_2:12; + UINT32 rate_1:12; /* format refer to WTBL_TX_RATE */ + } field; + UINT32 word; +}; +#else +union WTBL_2_DW10 { + struct { + UINT32 rate_1:12; /* format refer to WTBL_TX_RATE */ + UINT32 rate_2:12; + UINT32 rate_3_0:8; + } field; + UINT32 word; +}; +#endif + +#ifdef RT_BIG_ENDIAN +union WTBL_2_DW11 { + struct { + UINT32 rate_6_0:4; + UINT32 rate_5:12; + UINT32 rate_4:12; + UINT32 rate_3_8:4; + } field; + UINT32 word; +}; +#else +union WTBL_2_DW11 { + struct { + UINT32 rate_3_8:4; + UINT32 rate_4:12; + UINT32 rate_5:12; + UINT32 rate_6_0:4; + } field; + UINT32 word; +}; +#endif + +#ifdef RT_BIG_ENDIAN +union WTBL_2_DW12 { + struct { + UINT32 rate_8:12; + UINT32 rate_7:12; + UINT32 rate_6_4:8; + } field; + UINT32 word; +}; +#else +union WTBL_2_DW12 { + struct { + UINT32 rate_6_4:8; + UINT32 rate_7:12; + UINT32 rate_8:12; + } field; + UINT32 word; +}; +#endif + +#ifdef RT_BIG_ENDIAN +union WTBL_2_DW13 { + struct { + UINT32 rsv_13_24:8; + UINT32 resp_rcpi_2:8; + UINT32 resp_rcpi_1:8; + UINT32 resp_rcpi_0:8; + } field; + UINT32 word; +}; +#else +union WTBL_2_DW13 { + struct { + UINT32 resp_rcpi_0:8; + UINT32 resp_rcpi_1:8; + UINT32 resp_rcpi_2:8; + UINT32 rsv_13_24:8; + } field; + UINT32 word; +}; +#endif + +#ifdef RT_BIG_ENDIAN +union WTBL_2_DW14 { + struct { + UINT32 ant_sel:6; + UINT32 cc_noise_sel:1; + UINT32 ce_rmsd:4; + UINT32 sts_3_ch_cap_noise:7; + UINT32 sts_2_ch_cap_noise:7; + UINT32 sts_1_ch_cap_noise:7; + } field; + UINT32 word; +}; +#else +union WTBL_2_DW14 { + struct { + UINT32 sts_1_ch_cap_noise:7; + UINT32 sts_2_ch_cap_noise:7; + UINT32 sts_3_ch_cap_noise:7; + UINT32 ce_rmsd:4; + UINT32 cc_noise_sel:1; + UINT32 ant_sel:6; + } field; + UINT32 word; +}; +#endif + +#ifdef RT_BIG_ENDIAN +union WTBL_2_DW15 { + struct { + UINT32 ba_en:8; + UINT32 ba_win_size_tid:24; + } field; + UINT32 word; +}; +#else +union WTBL_2_DW15 { + struct { + UINT32 ba_win_size_tid:24; + UINT32 ba_en:8; + } field; + UINT32 word; +}; +#endif + +typedef struct GNU_PACKED wtbl_2_struc { + union WTBL_2_DW0 wtbl_2_d0; + union WTBL_2_DW1 wtbl_2_d1; + union WTBL_2_DW2 wtbl_2_d2; + union WTBL_2_DW3 wtbl_2_d3; + union WTBL_2_DW4 wtbl_2_d4; + union WTBL_2_DW5 wtbl_2_d5; + union WTBL_2_DW6 wtbl_2_d6; + union WTBL_2_DW7 wtbl_2_d7; + union WTBL_2_DW8 wtbl_2_d8; + union WTBL_2_DW9 wtbl_2_d9; + union WTBL_2_DW10 wtbl_2_d10; + union WTBL_2_DW11 wtbl_2_d11; + union WTBL_2_DW12 wtbl_2_d12; + union WTBL_2_DW13 wtbl_2_d13; + union WTBL_2_DW14 wtbl_2_d14; + union WTBL_2_DW15 wtbl_2_d15; +}WTBL_2_STRUC; + + +/* + WTBL segment 3 definitions +*/ + +/* Used for Cipher Suit != (WEP_xx | WPI) */ +struct GNU_PACKED wtbl_cipher_128 { + UINT32 cipher_key_0; + UINT32 cipher_key_32; + UINT32 cipher_key_64; + UINT32 cipher_key_96; + + UINT32 rx_mic_bip_key_0; + UINT32 rx_mic_bip_key_32; + + UINT32 tx_mic_bip_key_0; + UINT32 tx_mic_bip_key_32; +}; + + +/* Used for CCMP-256 /GCMP-256, store cipher or MIC key only */ +struct GNU_PACKED wtbl_cipher_256 { + UINT32 key_0; + UINT32 key_1; + UINT32 key_2; + UINT32 key_3; + UINT32 key_4; + UINT32 key_5; + UINT32 key_6; + UINT32 key_7; +}; + + +/* Used for Cipher Suit == WPI */ +struct GNU_PACKED wtbl_cipher_wpi { + UINT32 cipher_key0_0; + UINT32 cipher_key0_1; + UINT32 cipher_key0_2; + UINT32 cipher_key0_3; + + UINT32 mic_key0_0; + UINT32 mic_key0_1; + UINT32 mic_key0_2; + UINT32 mic_key0_3; + + UINT32 cipher_key1_0; + UINT32 cipher_key1_1; + UINT32 cipher_key1_2; + UINT32 cipher_key1_3; + + UINT32 mic_key1_0; + UINT32 mic_key1_1; + UINT32 mic_key1_2; + UINT32 mic_key1_3; +}; + + +/* Used for Cipher Suit == WEP */ +struct GNU_PACKED wtbl_cipher_wep { + UINT32 cipher_key0_0; + UINT32 cipher_key0_1; + UINT32 cipher_key0_2; + UINT32 cipher_key0_3; + + UINT32 cipher_key1_0; + UINT32 cipher_key1_1; + UINT32 cipher_key1_2; + UINT32 cipher_key1_3; + + UINT32 cipher_key2_0; + UINT32 cipher_key2_1; + UINT32 cipher_key2_2; + UINT32 cipher_key2_3; + + UINT32 cipher_key3_0; + UINT32 cipher_key3_1; + UINT32 cipher_key3_2; + UINT32 cipher_key3_3; +}; + + +typedef union GNU_PACKED wtbl_3_struc { + struct wtbl_cipher_wep cipher_wep; + struct wtbl_cipher_wpi cipher_wpi; + struct wtbl_cipher_128 cipher_128; + struct wtbl_cipher_256 cipher_256; +}WTBL_3_STRUC; + + +/* + WTBL segment 4 definitions +*/ +#ifdef RT_BIG_ENDIAN +union wtbl_4_ac{ + struct { + /* DWORD 0 */ + UINT32 rsv_0_24:8; + UINT32 ac_ctt:24; + + /* DWORD 1 */ + UINT32 ac_ctb; + }field; + UINT32 word[2]; +}; +#else +union wtbl_4_ac{ + struct { + /* DWORD 0 */ + UINT32 ac_ctt:24; + UINT32 rsv_0_24:8; + + /* DWORD 1 */ + UINT32 ac_ctb; + }field; + UINT32 word[2]; +}; +#endif + +typedef struct GNU_PACKED wtbl_4_struc { + union wtbl_4_ac ac0; + union wtbl_4_ac ac1; + union wtbl_4_ac ac2; + union wtbl_4_ac ac3; +}WTBL_4_STRUC; + +#endif /* __WF_WTBL_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_wtbloff.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_wtbloff.h new file mode 100644 index 000000000..176fcc730 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_wtbloff.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-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: + wf_wtbloff.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifndef __WF_WTBL_OFF_H__ +#define __WF_WTBL_OFF_H__ + +#define WF_WTBL_OFF_BASE 0x23000 +#define WTBL_OFF_WIUCR (WF_WTBL_OFF_BASE + 0x0) /* 0x23000 */ +#define WLAN_IDX_MASK (0xff) +#define WLAN_IDX(p) (((p) & 0xff)) +#define WTBL2_UPDATE_FLAG (1 << 11) +#define ADM_CNT_CLEAR (1 << 12) +#define RATE_UPDATE (1 << 13) +#define TX_CNT_CLEAR (1 << 14) +#define RX_CNT_CLEAR (1 << 15) +#define IU_BUSY (1 << 16) + +#define WTBL_OFF_RMVTCR (WF_WTBL_OFF_BASE + 0x8) /* 0x23008 */ +#define RX_MV_MODE (BIT23) +#define RCPI_AVG_PARAM_MASK (0x3 << 20) +#define RCPI_AVG_PARAM(p) (((p) & 0x3) << 20) + +#endif /* __WF_WTBL_OFF_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_wtblon.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_wtblon.h new file mode 100644 index 000000000..c630c51d9 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_mt/wf_wtblon.h @@ -0,0 +1,236 @@ +/* + *************************************************************************** + * 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: + wf_wtblon.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __WF_WTBL_ON_H__ +#define __WF_WTBL_ON_H__ + +#define WF_WTBL_ON_BASE 0x28000 + +#define WTBL_WTBL1DW0 (WF_WTBL_ON_BASE + 0x00) +#define WTBL_ON_RIUCR0 (WF_WTBL_ON_BASE + 0x2200) /* 0x2A200 */ +#define WTBL_ON_RIUCR1 (WF_WTBL_ON_BASE + 0x2204) /* 0x2A204 */ +#define WTBL_ON_RIUCR2 (WF_WTBL_ON_BASE + 0x2208) /* 0x2A208 */ +#define WTBL_ON_RIUCR3 (WF_WTBL_ON_BASE + 0x220C) /* 0x2A20C */ + +#ifdef RT_BIG_ENDIAN +union WTBL_1_DW0 { + struct { + UINT32 wm:1; + UINT32 sw:1; + UINT32 rc_a2:1; + UINT32 rv:1; + UINT32 ikv:1; + UINT32 rkv:1; + UINT32 rc_id:1; + UINT32 kid:2; + UINT32 rc_a1:1; + UINT32 muar_idx:6; + UINT32 addr_5:8; + UINT32 addr_4:8; + } field; + UINT32 word; +}; +#else +union WTBL_1_DW0 { + struct { + UINT32 addr_4:8; + UINT32 addr_5:8; + UINT32 muar_idx:6; + UINT32 rc_a1:1; + UINT32 kid:2; + UINT32 rc_id:1; + UINT32 rkv:1; + UINT32 ikv:1; + UINT32 rv:1; + UINT32 rc_a2:1; + UINT32 sw:1; + UINT32 wm:1; + } field; + UINT32 word; +}; +#endif + + +#define WTBL_WTBL1DW1 (WF_WTBL_ON_BASE + 0x04) /* 0x28004 */ +union WTBL_1_DW1 { + struct { + UINT32 addr_0; + }field; + UINT32 word; +}; + + +enum WTBL_CIPHER_SUIT{ + WTBL_CIPHER_NONE = 0, + WTBL_CIPHER_WEP_40 = 1, + WTBL_CIPHER_TKIP_MIC = 2, + WTBL_CIPHER_TKIP_NO_MIC = 3, + WTBL_CIPHER_CCMP_128_PMF = 4, + WTBL_CIPHER_WEP_104 = 5, + WTBL_CIPHER_BIP_CMAC_128 = 6, + WTBL_CIPHER_WEP_128 = 7, + WTBL_CIPHER_WPI_128 = 8, + WTBL_CIPHER_CCMP_128_CCX = 9, + WTBL_CIPHER_CCMP_256 = 10, + WTBL_CIPHER_GCMP_128 = 11, + WTBL_CIPHER_GCMP_256 = 12, +}; + + +#define WTBL_WTBL1DW2 (WF_WTBL_ON_BASE + 0x08) /* 0x28008 */ +#ifdef RT_BIG_ENDIAN +union WTBL_1_DW2 { + struct { + UINT32 gid:1; + UINT32 adm:1; + UINT32 vht:1; + UINT32 ht:1; + UINT32 qos:1; + UINT32 mesh:1; + UINT32 txop_ps_cap:1; + UINT32 tebf:1; + UINT32 tibf:1; + UINT32 ldpc:1; + UINT32 dyn_bw:1; + UINT32 baf_en:1; + UINT32 smps:1; + UINT32 rdg_ba:1; + UINT32 cf_ack:1; + UINT32 rts:1; + UINT32 r:1; + UINT32 tx_ps:1; + UINT32 af:3; + UINT32 dis_rhtr:1; + UINT32 fd:1; + UINT32 td:1; + UINT32 wpi_even:1; + UINT32 cipher_suit:4; + UINT32 mm:3; + } field; + UINT32 word; +}; +#else +union WTBL_1_DW2 { + struct { + UINT32 mm:3; + UINT32 cipher_suit:4; + UINT32 wpi_even:1; + UINT32 td:1; + UINT32 fd:1; + UINT32 dis_rhtr:1; + UINT32 af:3; + UINT32 tx_ps:1; + UINT32 r:1; + UINT32 rts:1; + UINT32 cf_ack:1; + UINT32 rdg_ba:1; + UINT32 smps:1; + UINT32 baf_en:1; + UINT32 dyn_bw:1; + UINT32 ldpc:1; + UINT32 tibf:1; + UINT32 tebf:1; + UINT32 txop_ps_cap:1; + UINT32 mesh:1; + UINT32 qos:1; + UINT32 ht:1; + UINT32 vht:1; + UINT32 adm:1; + UINT32 gid:1; + } field; + UINT32 word; +}; +#endif + +#define WTBL_WTBL1DW3 (WF_WTBL_ON_BASE + 0x0c) /* 0x2800c */ +#ifdef RT_BIG_ENDIAN +union WTBL_1_DW3 { + struct { + UINT32 skip_tx:1; + UINT32 psm:1; + UINT32 i_psm:1; + UINT32 du_i_psm:1; + UINT32 chk_per:1; + UINT32 wtbl4_fid:11; + UINT32 wtbl2_eid:5; + UINT32 wtbl2_fid:11; + } field; + UINT32 word; +}; +#else +union WTBL_1_DW3 { + struct { + UINT32 wtbl2_fid:11; + UINT32 wtbl2_eid:5; + UINT32 wtbl4_fid:11; + UINT32 chk_per:1; + UINT32 du_i_psm:1; + UINT32 i_psm:1; + UINT32 psm:1; + UINT32 skip_tx:1; + } field; + UINT32 word; +}; +#endif + +#define WTBL_WTBL1DW4 (WF_WTBL_ON_BASE + 0x10) /* 0x28010 */ +#ifdef RT_BIG_ENDIAN +union WTBL_1_DW4 { + struct { + UINT32 partial_aid:9; + UINT32 wtbl4_eid:6; + UINT32 wtbl3_eid:6; + UINT32 wtbl3_fid:11; + } field; + UINT32 word; +}; +#else +union WTBL_1_DW4 { + struct { + UINT32 wtbl3_fid:11; + UINT32 wtbl3_eid:6; + UINT32 wtbl4_eid:6; + UINT32 partial_aid:9; + } field; + UINT32 word; +}; +#endif + +#define WTBL_BTCRn (WF_WTBL_ON_BASE + 0x2000) +#define WTBL_MBTCRn (WF_WTBL_ON_BASE + 0x2010) +#define WTBL_BTBCRn (WF_WTBL_ON_BASE + 0x2030) +#define WTBL_MBTBCRn (WF_WTBL_ON_BASE + 0x2040) +#define WTBL_BRCRn (WF_WTBL_ON_BASE + 0x2100) +#define WTBL_MBRCRn (WF_WTBL_ON_BASE + 0x2110) +#define WTBL_BRBCRn (WF_WTBL_ON_BASE + 0x2130) +#define WTBL_MBRBCRn (WF_WTBL_ON_BASE + 0x2140) + +#define WTBL1OR (WF_WTBL_ON_BASE + 0x2300) +#define PSM_W_FLAG (1 << 31) +#endif /* __WF_WTBL_ON_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/fce.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/fce.h new file mode 100644 index 000000000..7997c9ba4 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/fce.h @@ -0,0 +1,94 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __FCE_H__ +#define __FCE_H__ + +#include "rt_config.h" + +#define FCE_PSE_CTRL 0x0800 +#define FCE_PARAMETERS 0x0804 +#define FCE_CSO 0x0808 +#define FCE_L2_STUFF 0x080c +#define TX_CPU_PORT_FROM_FCE_BASE_PTR 0x09A0 +#define TX_CPU_PORT_FROM_FCE_MAX_COUNT 0x09A4 +#define FCE_PDMA_GLOBAL_CONF 0x09C4 +#define TX_CPU_PORT_FROM_FCE_CPU_DESC_INDEX 0x09A8 +#define FCE_SKIP_FS 0x0A6C +#define PER_PORT_PAUSE_ENABLE_CONTROL1 0x0A38 + +#ifdef RT_BIG_ENDIAN +typedef union _L2_STUFFING_STRUC +{ + struct { + UINT32 RSV:6; + UINT32 OTHER_PORT:2; + UINT32 TS_LENGTH_EN:8; + UINT32 TS_CMD_QSEL_EN:8; + UINT32 RSV2:2; + UINT32 MVINF_BYTE_SWP:1; + UINT32 FS_WR_MPDU_LEN_EN:1; + UINT32 TX_L2_DE_STUFFING_EN:1; + UINT32 RX_L2_STUFFING_EN:1; + UINT32 QoS_L2_EN:1; + UINT32 HT_L2_EN:1; + } field; + + UINT32 word; +} L2_STUFFING_STRUC, *PL2_STUFFING_STRUC; +#else +typedef union _L2_STUFFING_STRUC +{ + struct { + UINT32 HT_L2_EN:1; + UINT32 QoS_L2_EN:1; + UINT32 RX_L2_STUFFING_EN:1; + UINT32 TX_L2_DE_STUFFING_EN:1; + UINT32 FS_WR_MPDU_LEN_EN:1; + UINT32 MVINF_BYTE_SWP:1; + UINT32 RSV2:2; + UINT32 TS_CMD_QSEL_EN:8; + UINT32 TS_LENGTH_EN:8; + UINT32 OTHER_PORT:2; + UINT32 RSV:6; + } field; + + UINT32 word; +} L2_STUFFING_STRUC, *PL2_STUFFING_STRUC; +#endif + +#define NORMAL_PKT 0x0 +#define CMD_PKT 0x1 + +#define FCE_WLAN_PORT 0x0 +#define FCE_CPU_RX_PORT 0x1 +#define FCE_CPU_TX_PORT 0x2 +#define FCE_HOST_PORT 0x3 +#define FCE_VIRTUAL_CPU_RX_PORT 0x4 +#define FCE_VIRTUAL_CPU_TX_PORT 0x5 +#define FCE_DISCARD 0x6 +#endif /*__FCE_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/mac_pci.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/mac_pci.h new file mode 100644 index 000000000..f27456d07 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/mac_pci.h @@ -0,0 +1,303 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + mac_pci.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __MAC_PCI_H__ +#define __MAC_PCI_H__ + +#include "rtmp_type.h" + +#ifdef RLT_MAC +#include "mac/mac_ral/nmac/ral_nmac_pci.h" +#endif /* RLT_MAC */ +#ifdef RTMP_MAC +#include "mac/mac_ral/omac/ral_omac_pci.h" +#endif /* RTMP_MAC */ + +#include "mac/mac_ral/rtmp_mac.h" +#include "phy/phy.h" +#include "rtmp_iface.h" +#include "rtmp_dot11.h" + + + +/* ================================================================================= + PCI/RBUS TX / RX Frame Descriptors format + + Memory Layout + + 1. Tx Descriptor + TxD (12 bytes) + TXINFO (4 bytes) + 2. Packet Buffer + TXWI + 802.11 + 31 0 + +--------------------------------------------------------------------------+ + | SDP0[31:0] | + +-+--+---------------------+-+--+-----------------------------------------+ + |D |L0| SDL0[13:0] |B|L1| SDL1[13:0] | + +-+--+---------------------+-+--+-----------------------------------------+ + | SDP1[31:0] | + +--------------------------------------------------------------------------+ + | TXINFO | + +--------------------------------------------------------------------------+ +================================================================================= */ +/* + TX descriptor format for Tx Data/Mgmt Rings +*/ +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _TXD_STRUC { + /* Word 0 */ + UINT32 SDPtr0; + /* Word 1 */ + UINT32 DMADONE:1; + UINT32 LastSec0:1; + UINT32 SDLen0:14; + UINT32 Burst:1; + UINT32 LastSec1:1; + UINT32 SDLen1:14; + /* Word 2 */ + UINT32 SDPtr1; +} TXD_STRUC; +#else +typedef struct GNU_PACKED _TXD_STRUC { + /* Word 0 */ + UINT32 SDPtr0; + /* Word 1 */ + UINT32 SDLen1:14; + UINT32 LastSec1:1; + UINT32 Burst:1; + UINT32 SDLen0:14; + UINT32 LastSec0:1; + UINT32 DMADONE:1; + /*Word2 */ + UINT32 SDPtr1; +} TXD_STRUC; +#endif + + +/* + Rx descriptor format, Rx Ring +*/ +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXD_STRUC{ + /* Word 0 */ + UINT32 SDP0; + /* Word 1 */ + UINT32 DDONE:1; + UINT32 LS0:1; + UINT32 SDL0:14; + UINT32 BURST:1; + UINT32 LS1:1; + UINT32 SDL1:14; + /* Word 2 */ + UINT32 SDP1; +}RXD_STRUC; +#else +typedef struct GNU_PACKED _RXD_STRUC{ + /* Word 0 */ + UINT32 SDP0; + /* Word 1 */ + UINT32 SDL1:14; + UINT32 LS1:1; + UINT32 BURST:1; + UINT32 SDL0:14; + UINT32 LS0:1; + UINT32 DDONE:1; + /* Word 2 */ + UINT32 SDP1; +}RXD_STRUC; +#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) + + +/* ----------------- ASIC Related MACRO ----------------- */ +/* reset MAC of a station entry to 0x000000000000 */ +#define RTMP_STA_ENTRY_MAC_RESET(pAd, Wcid) \ + AsicDelWcidTab(pAd, Wcid); + +/* add this entry into ASIC RX WCID search table */ +#define RTMP_STA_ENTRY_ADD(pAd, pEntry) \ + AsicUpdateRxWCIDTable(pAd, pEntry->wcid, pEntry->Addr); + +#define RTMP_UPDATE_PROTECT(_pAd, _OperationMode, _SetMask, _bDisableBGProtect, _bNonGFExist) \ + AsicUpdateProtect(pAd, _OperationMode, _SetMask, _bDisableBGProtect, _bNonGFExist); + +#ifdef CONFIG_AP_SUPPORT +#define RTMP_AP_UPDATE_CAPABILITY_AND_ERPIE(pAd) \ + APUpdateCapabilityAndErpIe(pAd); +#endif /* CONFIG_AP_SUPPORT */ + +/* Insert the BA bitmap to ASIC for the Wcid entry */ +#define RTMP_ADD_BA_SESSION_TO_ASIC(_pAd, _wcid, _TID, _SN, _basize, _type) \ + AsicUpdateBASession(_pAd, _wcid, _TID, _SN, _basize, 1, _type) + + +/* 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, _type) \ + AsicUpdateBASession(_pAd, _Wcid, _TID, 0, 0, 0, _type) + + +/* ----------------- Interface Related MACRO ----------------- */ + +typedef enum _RTMP_TX_DONE_MASK{ + TX_AC0_DONE = 0x1, + TX_AC1_DONE = 0x2, + TX_AC2_DONE = 0x4, + TX_AC3_DONE = 0x8, + TX_HCCA_DONE = 0x10, + TX_MGMT_DONE = 0x20, +}RTMP_TX_DONE_MASK; + + +/* + Enable & Disable NIC interrupt via writing interrupt mask register + Since it use ADAPTER structure, it have to be put after structure definition. +*/ +#define RTMP_ASIC_INTERRUPT_DISABLE(_pAd) \ + do{ \ + RTMP_IO_WRITE32((_pAd), INT_MASK_CSR, 0x0); /* 0: disable */ \ + RTMP_CLEAR_FLAG((_pAd), fRTMP_ADAPTER_INTERRUPT_ACTIVE); \ + }while(0) + +#define RTMP_ASIC_INTERRUPT_ENABLE(_pAd)\ + do{ \ + RTMP_IO_WRITE32((_pAd), INT_MASK_CSR, (_pAd)->int_enable_reg); /* 1:enable */ \ + RTMP_SET_FLAG((_pAd), fRTMP_ADAPTER_INTERRUPT_ACTIVE); \ + }while(0) + +#define RTMP_IRQ_ENABLE(pAd) \ + do{ \ + unsigned long _irqFlags;\ + RTMP_INT_LOCK(&pAd->irq_lock, _irqFlags);\ + /* clear garbage ints */\ + RTMP_IO_WRITE32(pAd, INT_SOURCE_CSR, 0xffffffff); \ + RTMP_ASIC_INTERRUPT_ENABLE(pAd); \ + RTMP_INT_UNLOCK(&pAd->irq_lock, _irqFlags);\ + } while(0) + + + +/* ----------------- MLME Related MACRO ----------------- */ +#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 + + + + +/* ----------------- 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) + + +/* Remove Pairwise Key table */ +#define RTMP_REMOVE_PAIRWISE_KEY_ENTRY(_pAd, _Wcid)\ + AsicRemovePairwiseKeyEntry(_pAd, _Wcid) + + +struct _RTMP_ADAPTER; +enum _RTMP_TX_DONE_MASK; + +BOOLEAN RTMPHandleTxRingDmaDoneInterrupt(struct _RTMP_ADAPTER *pAd, enum _RTMP_TX_DONE_MASK tx_mask); +VOID RTMPHandleMgmtRingDmaDoneInterrupt(struct _RTMP_ADAPTER *pAd); +VOID RTMPHandleTBTTInterrupt(struct _RTMP_ADAPTER *pAd); +VOID RTMPHandlePreTBTTInterrupt(struct _RTMP_ADAPTER *pAd); +VOID RTMPHandleRxCoherentInterrupt(struct _RTMP_ADAPTER *pAd); + +VOID RTMPHandleMcuInterrupt(struct _RTMP_ADAPTER *pAd); +void RTMPHandleTwakeupInterrupt(struct _RTMP_ADAPTER *pAd); + +#endif /*__MAC_PCI_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/mac_usb.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/mac_usb.h new file mode 100644 index 000000000..912ba8085 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/mac_usb.h @@ -0,0 +1,518 @@ +/**************************************************************************** + * 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_usb.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __MAC_USB_H__ +#define __MAC_USB_H__ + +#include "rtmp_type.h" +#ifdef RLT_MAC +#include "mac/mac_ral/nmac/ral_nmac_usb.h" +#endif /* RLT_MAC */ +#ifdef RTMP_MAC +#include "mac/mac_ral/omac/ral_omac_usb.h" +#endif /* RTMP_MAC */ + +#include "mac/mac_ral/rtmp_mac.h" +#include "phy/phy.h" +#include "rtmp_iface.h" +#include "rtmp_dot11.h" + + +#ifdef RTMP_MAC +#define RTMP_USB_DMA_CFG 0x02a0 +#endif /* RTMP_MAC */ + + +#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; +#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; +#endif + + + +/*#define BEACON_RING_SIZE 2 */ +#define MGMTPIPEIDX 0 /* EP6 is highest priority */ + +/* os abl move */ +/*#define RTMP_PKT_TAIL_PADDING 11 // 3(max 4 byte padding) + 4 (last packet padding) + 4 (MaxBulkOutsize align padding) */ + + + +/* ================================================================================= + USB TX / RX Frame Descriptors format + + Tx Memory Layout + 1. Packet Buffer + TxINFO(4 bytes) + TXWI( 16 bytes) + 802.11 + 31 0 + +--------------------------------------------------------------------------+ + | TXINFO[31:0] | + +--------------------------------------------------------------------------+ + | TxWI | + + + + | | + + + + | | + + + + | | + +--------------------------------------------------------------------------+ + | 802.11 | + | ......... | + +--------------------------------------------------------------------------+ + + + Rx Memory Layout + 1. Packet Buffer + RxDMALen(4 bytes) + RXWI(16 bytes) + 802.11 + RXINFO (4 bytes) + 31 0 + +--------------------------------------------------------------------------+ + | RXDMALen[31:0] | + +--------------------------------------------------------------------------+ + | RxWI | + + + + | | + + + + | | + + + + | | + +--------------------------------------------------------------------------+ + | 802.11 | + | ......... | + +--------------------------------------------------------------------------+ + | RXINFO | + +--------------------------------------------------------------------------+ + +================================================================================= */ + + +/* + RXINFO appends at the end of each rx packet +*/ +#define RXDMA_FIELD_SIZE 4 + + +/* + Rx descriptor format, Rx Ring +*/ +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXD_STRUC{ + UINT32 dma_len; +}RXD_STRUC; +#else +typedef struct GNU_PACKED _RXD_STRUC{ + UINT32 dma_len; +}RXD_STRUC; +#endif + + +/* + Management ring buffer format +*/ +typedef struct _MGMT_STRUC { + BOOLEAN Valid; + PUCHAR pBuffer; + ULONG Length; +} MGMT_STRUC, *PMGMT_STRUC; + + +/*////////////////////////////////////////////////////////////////////////*/ +/* The TX_BUFFER structure forms the transmitted USB packet to the device */ +/*////////////////////////////////////////////////////////////////////////*/ +typedef struct __TX_BUFFER{ + union{ + UCHAR WirelessPacket[TX_BUFFER_NORMSIZE]; + HEADER_802_11 NullFrame; + PSPOLL_FRAME PsPollPacket; + RTS_FRAME RTSFrame; + }field; + UCHAR Aggregation[4]; /*Buffer for save Aggregation size. */ +} TX_BUFFER, *PTX_BUFFER; + +typedef struct __HTTX_BUFFER{ + union{ + UCHAR WirelessPacket[MAX_TXBULK_SIZE]; + HEADER_802_11 NullFrame; + PSPOLL_FRAME PsPollPacket; + RTS_FRAME RTSFrame; + }field; + UCHAR Aggregation[4]; /*Buffer for save Aggregation size. */ +} HTTX_BUFFER, *PHTTX_BUFFER; + + +#define EDCA_AC0_PIPE 0 /* Bulk EP1 OUT */ +#define EDCA_AC1_PIPE 1 /* Bulk EP2 OUT */ +#define EDCA_AC2_PIPE 2 /* Bulk EP3 OUT */ +#define EDCA_AC3_PIPE 3 /* Bulk EP4 OUT */ +#define HCCA_PIPE 4 /* Bulk EP5 OUT */ + +/* used to track driver-generated write irps */ +typedef struct _TX_CONTEXT +{ + PVOID pAd; /*Initialized in MiniportInitialize */ + PURB pUrb; /*Initialized in MiniportInitialize */ + PIRP pIrp; /*used to cancel pending bulk out. */ + /*Initialized in MiniportInitialize */ + PTX_BUFFER TransferBuffer; /*Initialized in MiniportInitialize */ + ULONG BulkOutSize; + UCHAR BulkOutPipeId; + UCHAR SelfIdx; + BOOLEAN InUse; + BOOLEAN bWaitingBulkOut; /* at least one packet is in this TxContext, ready for making IRP anytime. */ + BOOLEAN bFullForBulkOut; /* all tx buffer are full , so waiting for tx bulkout. */ + BOOLEAN IRPPending; + BOOLEAN LastOne; + BOOLEAN bAggregatible; + UCHAR Header_802_3[LENGTH_802_3]; + UCHAR Rsv[2]; + ULONG DataOffset; + UINT TxRate; + ra_dma_addr_t data_dma; + +#ifdef UAPSD_SUPPORT + USHORT Wcid; +#endif /* UAPSD_SUPPORT */ +} TX_CONTEXT, *PTX_CONTEXT, **PPTX_CONTEXT; + + +/* used to track driver-generated write irps */ +typedef struct _HT_TX_CONTEXT +{ + PVOID pAd; /*Initialized in MiniportInitialize */ + PURB pUrb; /*Initialized in MiniportInitialize */ + PIRP pIrp; /*used to cancel pending bulk out. */ + /*Initialized in MiniportInitialize */ + PHTTX_BUFFER TransferBuffer; /*Initialized in MiniportInitialize */ + ULONG BulkOutSize; /* Indicate the total bulk-out size in bytes in one bulk-transmission */ + UCHAR BulkOutPipeId; + BOOLEAN IRPPending; + BOOLEAN LastOne; + BOOLEAN bCurWriting; + BOOLEAN bRingEmpty; + BOOLEAN bCopySavePad; + UCHAR SavedPad[8]; + UCHAR Header_802_3[LENGTH_802_3]; + ULONG CurWritePosition; /* Indicate the buffer offset which packet will be inserted start from. */ + ULONG CurWriteRealPos; /* Indicate the buffer offset which packet now are writing to. */ + ULONG NextBulkOutPosition; /* Indicate the buffer start offset of a bulk-transmission */ + ULONG ENextBulkOutPosition; /* Indicate the buffer end offset of a bulk-transmission */ + UINT TxRate; + ra_dma_addr_t data_dma; /* urb dma on linux */ +#ifdef USB_BULK_BUF_ALIGMENT + ULONG CurWriteIdx; /* pointer to next 32k bytes position when wirte tx resource or when bulk out sizze not > 0x6000 */ + ULONG NextBulkIdx; /* pointer to next alignment section when bulk ot */ +#endif /* USB_BULK_BUF_ALIGMENT */ + +} HT_TX_CONTEXT, *PHT_TX_CONTEXT, **PPHT_TX_CONTEXT; + + +typedef struct _CMD_CONTEXT +{ + PVOID pAd; + PURB pUrb; + ra_dma_addr_t data_dma; + PUCHAR TransferBuffer; + BOOLEAN IRPPending; +} CMD_CONTEXT, *PCMD_CONTEXT, **PPCMD_CONTEXT; + +/* + Structure to keep track of receive packets and buffers to indicate + receive data to the protocol. +*/ +typedef struct _RX_CONTEXT +{ + DL_LIST list; + PUCHAR TransferBuffer; + PVOID pAd; + PIRP pIrp;/*used to cancel pending bulk in. */ + PURB pUrb; + /*These 2 Boolean shouldn't both be 1 at the same time. */ + ULONG BulkInOffset; /* number of packets waiting for reordering . */ +/* BOOLEAN ReorderInUse; // At least one packet in this buffer are in reordering buffer and wait for receive indication */ + BOOLEAN bRxHandling; /* Notify this packet is being process now. */ + BOOLEAN InUse; /* USB Hardware Occupied. Wait for USB HW to put packet. */ + BOOLEAN Readable; /* Receive Complete back. OK for driver to indicate receiving packet. */ + BOOLEAN IRPPending; /* TODO: To be removed */ + /*atomic_t IrpLock; */ + NDIS_SPIN_LOCK RxContextLock; + ra_dma_addr_t data_dma; /* urb dma on linux */ +} RX_CONTEXT, *PRX_CONTEXT; + + +typedef struct _CMD_RSP_CONTEXT +{ + PUCHAR CmdRspBuffer; + PVOID pAd; + PURB pUrb; + BOOLEAN IRPPending; + BOOLEAN InUse; + BOOLEAN Readable; + ra_dma_addr_t data_dma; +} CMD_RSP_CONTEXT, *PCMD_RSP_CONTEXT; + +/****************************************************************************** + + USB Frimware Related MACRO + +******************************************************************************/ +/* 8051 firmware image for usb - use last-half base address = 0x3000 */ +#define FIRMWARE_IMAGE_BASE 0x3000 +#define MAX_FIRMWARE_IMAGE_SIZE 0x1000 /* 4kbyte */ + +#define RTMP_WRITE_FIRMWARE(_pAd, _pFwImage, _FwLen) \ + RTUSBFirmwareWrite(_pAd, _pFwImage, _FwLen) + + + +/****************************************************************************** + + USB TX Related MACRO + +******************************************************************************/ +#define RTMP_START_DEQUEUE(pAd, QueIdx, irqFlags) \ + { \ + RTMP_IRQ_LOCK(&pAd->DeQueueLock[QueIdx], irqFlags); \ + if (pAd->DeQueueRunning[QueIdx]) \ + { \ + RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags);\ + DBGPRINT(RT_DEBUG_INFO, ("DeQueueRunning[%d]= TRUE!\n", QueIdx)); \ + continue; \ + } \ + else \ + { \ + pAd->DeQueueRunning[QueIdx] = TRUE; \ + RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags);\ + } \ + } + +#define RTMP_STOP_DEQUEUE(pAd, QueIdx, irqFlags) \ + do{ \ + RTMP_IRQ_LOCK(&pAd->DeQueueLock[QueIdx], irqFlags); \ + pAd->DeQueueRunning[QueIdx] = FALSE; \ + RTMP_IRQ_UNLOCK(&pAd->DeQueueLock[QueIdx], irqFlags); \ + }while(0) + +#define RTMP_HAS_ENOUGH_FREE_DESC(pAd, pTxBlk, freeNum, pPacket) \ + (RTUSBFreeDescRequest(pAd, pTxBlk->QueIdx, (pTxBlk->TotalFrameLen + GET_OS_PKT_LEN(pPacket))) == NDIS_STATUS_SUCCESS) + +#define RTMP_RELEASE_DESC_RESOURCE(pAd, QueIdx) \ + do{}while(0) + +#define NEED_QUEUE_BACK_FOR_AGG(_pAd, _QueIdx, _freeNum, _TxFrameType) \ + ((_TxFrameType == TX_RALINK_FRAME) && (RTUSBNeedQueueBackForAgg(_pAd, _QueIdx))) + +#define HAL_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) \ + RtmpUSB_WriteSubTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) + +#define HAL_WriteTxResource(pAd, pTxBlk,bIsLast, pFreeNumber) \ + RtmpUSB_WriteSingleTxResource(pAd, pTxBlk, bIsLast, pFreeNumber) + +#define HAL_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) \ + RtmpUSB_WriteFragTxResource(pAd, pTxBlk, fragNum, pFreeNumber) + +#define HAL_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber) \ + RtmpUSB_WriteMultiTxResource(pAd, pTxBlk,frameNum, pFreeNumber) + +#define HAL_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, TxIdx) \ + RtmpUSB_FinalWriteTxResource(pAd, pTxBlk, totalMPDUSize, TxIdx) + +#define HAL_LastTxIdx(pAd, QueIdx,TxIdx) \ + /*RtmpUSBDataLastTxIdx(pAd, QueIdx,TxIdx)*/ + +#define HAL_KickOutTx(pAd, pTxBlk, QueIdx) \ + RtmpUSBDataKickOut(pAd, pTxBlk, QueIdx) + +#define HAL_KickOutMgmtTx(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen) \ + RtmpUSBMgmtKickOut(pAd, QueIdx, pPacket, pSrcBufVA, SrcBufLen) + +#define HAL_KickOutNullFrameTx(_pAd, _QueIdx, _pNullFrame, _frameLen) \ + RtmpUSBNullFrameKickOut(_pAd, _QueIdx, _pNullFrame, _frameLen) + +#define GET_TXRING_FREENO(_pAd, _QueIdx) (_QueIdx) /*(_pAd->TxRing[_QueIdx].TxSwFreeIdx) */ +#define GET_MGMTRING_FREENO(_pAd) (_pAd->MgmtRing.TxSwFreeIdx) + + +/* ----------------- RX Related MACRO ----------------- */ + + +/* + * MLME Related MACRO + */ +#define RTMP_MLME_PRE_SANITY_CHECK(pAd) \ + { if ((pAd->StaCfg.bHardwareRadio == TRUE) && \ + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)) && \ + (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS))) { \ + RTEnqueueInternalCmd(pAd, CMDTHREAD_CHECK_GPIO, NULL, 0); } } + +#define RTMP_MLME_RESET_STATE_MACHINE(pAd) \ + MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_RESET_CONF, 0, NULL, 0); \ + RTMP_MLME_HANDLER(pAd); + +#define RTMP_HANDLE_COUNTER_MEASURE(_pAd, _pEntry) \ + { RTEnqueueInternalCmd(_pAd, CMDTHREAD_802_11_COUNTER_MEASURE, _pEntry, sizeof(MAC_TABLE_ENTRY)); \ + RTMP_MLME_HANDLER(_pAd); \ + } + + +/* + * Power Save Related MACRO + */ + + +/* MAC Search table */ +/* add this entry into ASIC RX WCID search table */ +#define RTMP_STA_ENTRY_ADD(pAd, pEntry) \ +{ \ + RT_SET_ASIC_WCID Info; \ + \ + Info.WCID = pEntry->wcid; \ + NdisMoveMemory(Info.Addr, pEntry->Addr, MAC_ADDR_LEN); \ + \ + RTEnqueueInternalCmd(pAd, CMDTHREAD_SET_CLIENT_MAC_ENTRY, \ + &Info, sizeof(RT_SET_ASIC_WCID)); \ +} + + +/* ----------------- Security Related MACRO ----------------- */ + +/* Set Asic WCID Attribute table */ +#define RTMP_SET_WCID_SEC_INFO(_pAd, _BssIdx, _KeyIdx, _CipherAlg, _Wcid, _KeyTabFlag) \ +{ \ + RT_ASIC_WCID_SEC_INFO Info; \ + \ + Info.BssIdx = _BssIdx; \ + Info.KeyIdx = _KeyIdx; \ + Info.CipherAlg = _CipherAlg; \ + Info.Wcid = _Wcid; \ + Info.KeyTabFlag = _KeyTabFlag; \ + \ + RTEnqueueInternalCmd(_pAd, CMDTHREAD_SET_WCID_SEC_INFO, \ + &Info, sizeof(RT_ASIC_WCID_SEC_INFO)); \ +} + +/* Set Asic WCID IV/EIV table */ +#define RTMP_ASIC_WCID_IVEIV_TABLE(_pAd, _Wcid, _uIV, _uEIV) \ +{ \ + RT_ASIC_WCID_IVEIV_ENTRY Info; \ + \ + Info.Wcid = _Wcid; \ + Info.Iv = _uIV; \ + Info.Eiv = _uEIV; \ + \ + RTEnqueueInternalCmd(_pAd, CMDTHREAD_SET_ASIC_WCID_IVEIV, \ + &Info, \ + sizeof(RT_ASIC_WCID_IVEIV_ENTRY)); \ +} + +/* Set Asic WCID Attribute table */ +#define RTMP_ASIC_WCID_ATTR_TABLE(_pAd, _BssIdx, _KeyIdx, _CipherAlg, _Wcid, _KeyTabFlag) \ +{ \ + RT_ASIC_WCID_ATTR_ENTRY Info; \ + \ + Info.BssIdx = _BssIdx; \ + Info.KeyIdx = _KeyIdx; \ + Info.CipherAlg = _CipherAlg; \ + Info.Wcid = _Wcid; \ + Info.KeyTabFlag = _KeyTabFlag; \ + \ + RTEnqueueInternalCmd(_pAd, CMDTHREAD_SET_ASIC_WCID_ATTR, \ + &Info, sizeof(RT_ASIC_WCID_ATTR_ENTRY)); \ +} + +/* Set Asic Pairwise key table */ +#define RTMP_ASIC_PAIRWISE_KEY_TABLE(_pAd, _WCID, _pCipherKey) \ +{ \ + RT_ASIC_PAIRWISE_KEY Info; \ + \ + Info.WCID = _WCID; \ + NdisMoveMemory(&Info.CipherKey, _pCipherKey, sizeof(CIPHER_KEY)); \ + \ + RTEnqueueInternalCmd(_pAd, CMDTHREAD_SET_ASIC_PAIRWISE_KEY, \ + &Info, sizeof(RT_ASIC_PAIRWISE_KEY)); \ +} + +/* Set Asic Shared key table */ +#define RTMP_ASIC_SHARED_KEY_TABLE(_pAd, _BssIndex, _KeyIdx, _pCipherKey) \ +{ \ + RT_ASIC_SHARED_KEY Info; \ + \ + Info.BssIndex = _BssIndex; \ + Info.KeyIdx = _KeyIdx; \ + NdisMoveMemory(&Info.CipherKey, _pCipherKey, sizeof(CIPHER_KEY)); \ + \ + RTEnqueueInternalCmd(_pAd, CMDTHREAD_SET_ASIC_SHARED_KEY, \ + &Info, sizeof(RT_ASIC_SHARED_KEY)); \ +} + + +/* Remove Pairwise Key table */ +#define RTMP_REMOVE_PAIRWISE_KEY_ENTRY(_pAd, _Wcid) \ +{ \ + UCHAR _tWcid =_Wcid; \ + RTEnqueueInternalCmd(_pAd, CMDTHREAD_REMOVE_PAIRWISE_KEY, &(_tWcid), sizeof(UCHAR));\ +} + +#define RTMP_OS_IRQ_RELEASE(_pAd, _NetDev) + +VOID BeaconUpdateExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +#endif /*__MAC_USB_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac.h new file mode 100644 index 000000000..0c62841ff --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac.h @@ -0,0 +1,1171 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + ral_nmac.h + + Abstract: + Ralink Wireless Chip RAL MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RAL_NMAC_H__ +#define __RAL_NMAC_H__ + +enum INFO_TYPE { + NORMAL_PACKET, + CMD_PACKET, +}; + +enum D_PORT { + WLAN_PORT, + CPU_RX_PORT, + CPU_TX_PORT, + HOST_PORT, + VIRTUAL_CPU_RX_PORT, + VIRTUAL_CPU_TX_PORT, + DISCARD, +}; + +#include "rtmp_type.h" + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _TXINFO_NMAC_PKT{ + UINT32 info_type:2; + UINT32 d_port:3; + UINT32 QSEL:2; + UINT32 wiv:1; + UINT32 rsv1:2; + UINT32 cso:1; + UINT32 tso:1; + UINT32 pkt_80211:1; + UINT32 rsv0:1; + UINT32 tx_burst:1; + UINT32 next_vld:1; + UINT32 pkt_len:16; +}TXINFO_NMAC_PKT; +#else +typedef struct GNU_PACKED _TXINFO_NMAC_PKT { + UINT32 pkt_len:16; + UINT32 next_vld:1; + UINT32 tx_burst:1; + UINT32 rsv0:1; + UINT32 pkt_80211:1; + UINT32 tso:1; + UINT32 cso:1; + UINT32 rsv1:2; + UINT32 wiv:1; + UINT32 QSEL:2; + UINT32 d_port:3; + UINT32 info_type:2; +}TXINFO_NMAC_PKT; +#endif /* RT_BIG_ENDIAN */ + + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _TXINFO_NMAC_CMD{ + UINT32 info_type:2; + UINT32 d_port:3; + UINT32 cmd_type:7; + UINT32 cmd_seq:4; + UINT32 pkt_len:16; +}TXINFO_NMAC_CMD; +#else +typedef struct GNU_PACKED _TXINFO_NMAC_CMD{ + UINT32 pkt_len:16; + UINT32 cmd_seq:4; + UINT32 cmd_type:7; + UINT32 d_port:3; + UINT32 info_type:2; +}TXINFO_NMAC_CMD; +#endif /* RT_BIG_ENDIAN */ + + +typedef union GNU_PACKED _TXINFO_NMAC{ + struct _TXINFO_NMAC_PKT txinfo_pkt; + struct _TXINFO_NMAC_CMD txinfo_cmd; +}TXINFO_NMAC; + + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _TXWI_NMAC { + /* Word 0 */ + UINT32 PHYMODE:3; + UINT32 iTxBF:1; + UINT32 eTxBF:1; + UINT32 STBC:1; + UINT32 ShortGI:1; + UINT32 BW:2; /* channel bandwidth 20/40/80 MHz */ + UINT32 LDPC:1; + UINT32 MCS:6; + + UINT32 lut_en:1; + UINT32 Sounding:1; + UINT32 NDPSndBW:2; /* NDP sounding BW */ + UINT32 RTSBWSIG:1; + UINT32 NDPSndRate:1; /* 0 : MCS0, 1: MCS8, 2: MCS16, 3: reserved */ + UINT32 txop:2; + + UINT32 MpduDensity:3; + UINT32 AMPDU:1; + UINT32 TS:1; + UINT32 CFACK:1; + UINT32 MIMOps:1; /* the remote peer is in dynamic MIMO-PS mode */ + UINT32 FRAG:1; /* 1 to inform TKIP engine this is a fragment. */ + + /* Word 1 */ + UINT32 TIM:1; + UINT32 TXBF_PT_SCA:1; + UINT32 MPDUtotalByteCnt:14; + UINT32 wcid:8; + UINT32 BAWinSize:6; + UINT32 NSEQ:1; + UINT32 ACK:1; + + /* Word 2 */ + UINT32 IV; + /* Word 3 */ + UINT32 EIV; + + /* Word 4 */ + UINT32 TxPktId:8; + UINT32 GroupID:1; + UINT32 Rsv4:3; + //UINT32 Rsv4:4; + UINT32 TxPwrAdj:4; + UINT32 TxStreamMode:8; + UINT32 TxEAPId:8; +} TXWI_NMAC; +#else +typedef struct GNU_PACKED _TXWI_NMAC { + /* Word 0 */ + /* ex: 00 03 00 40 means txop = 3, PHYMODE = 1 */ + UINT32 FRAG:1; /* 1 to inform TKIP engine this is a fragment. */ + UINT32 MIMOps:1; /* the remote peer is in dynamic MIMO-PS mode */ + UINT32 CFACK:1; + UINT32 TS:1; + UINT32 AMPDU:1; + UINT32 MpduDensity:3; + + UINT32 txop:2; + UINT32 NDPSndRate:1; /* 0 : MCS0, 1: MCS8, 2: MCS16, 3: reserved */ + UINT32 RTSBWSIG:1; + UINT32 NDPSndBW:2; /* NDP sounding BW */ + UINT32 Sounding:1; + UINT32 lut_en:1; + + UINT32 MCS:6; + UINT32 LDPC:1; + UINT32 BW:2; /*channel bandwidth 20/40/80 MHz */ + UINT32 ShortGI:1; + UINT32 STBC:1; + UINT32 eTxBF:1; + UINT32 iTxBF:1; + UINT32 PHYMODE:3; + + /* Word1 */ + /* ex: 1c ff 38 00 means ACK=0, BAWinSize=7, MPDUtotalByteCnt = 0x38 */ + UINT32 ACK:1; + UINT32 NSEQ:1; + UINT32 BAWinSize:6; + UINT32 wcid:8; + UINT32 MPDUtotalByteCnt:14; + UINT32 TXBF_PT_SCA:1; + UINT32 TIM:1; + + /*Word2 */ + UINT32 IV; + + /*Word3 */ + UINT32 EIV; + + /* Word 4 */ + UINT32 TxEAPId:8; + UINT32 TxStreamMode:8; + UINT32 TxPwrAdj:4; + //UINT32 Rsv4:4; + UINT32 Rsv4:3; + UINT32 GroupID:1; + UINT32 TxPktId:8; +} TXWI_NMAC; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _TXWI_XMAC { + /* Word 0 */ + UINT32 PHYMODE:2; + UINT32 rsv0_27:3; + UINT32 STBC:2; /*channel bandwidth 20MHz or 40 MHz */ + UINT32 ShortGI:1; + UINT32 BW:1; /*channel bandwidth 20MHz or 40 MHz */ + UINT32 MCS:7; + + UINT32 TXLUT:1; + UINT32 TXRPT:1; + UINT32 Autofallback:1; /* TX rate auto fallback disable */ + UINT32 NDPSndBW:1; /* NDP sounding BW */ + UINT32 NDPSndRate:2; /* 0 : MCS0, 1: MCS8, 2: MCS16, 3: reserved */ + UINT32 txop:2; + UINT32 MpduDensity:3; + UINT32 AMPDU:1; + + UINT32 TS:1; + UINT32 CFACK:1; + UINT32 MIMOps:1; /* the remote peer is in dynamic MIMO-PS mode */ + UINT32 FRAG:1; /* 1 to inform TKIP engine this is a fragment. */ + + /* Word 1 */ + UINT32 PacketId:4; + UINT32 MPDUtotalByteCnt:12; + UINT32 wcid:8; + UINT32 BAWinSize:6; + UINT32 NSEQ:1; + UINT32 ACK:1; + + /* Word 2 */ + UINT32 IV; + + /* Word 3 */ + UINT32 EIV; + + /* Word 4 */ + UINT32 rsv4_23:9; + UINT32 PIFSREV:1; + UINT32 rsv4_21:1; + UINT32 CCP:1; + UINT32 TxPwrAdj:4; + UINT32 TxStreamMode:8; + UINT32 EncodedAntID:8; +} TXWI_XMAC; +#else +typedef struct GNU_PACKED _TXWI_XMAC { + /* Word 0 */ + /* ex: 00 03 00 40 means txop = 3, PHYMODE = 1 */ + UINT32 FRAG:1; /* 1 to inform TKIP engine this is a fragment. */ + UINT32 MIMOps:1; /* the remote peer is in dynamic MIMO-PS mode */ + UINT32 CFACK:1; + UINT32 TS:1; + + UINT32 AMPDU:1; + UINT32 MpduDensity:3; + UINT32 txop:2; /*FOR "THIS" frame. 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs only when previous frame exchange is successful. */ + UINT32 NDPSndRate:2; /* 0 : MCS0, 1: MCS8, 2: MCS16, 3: reserved */ + UINT32 NDPSndBW:1; /* NDP sounding BW */ + UINT32 Autofallback:1; /* TX rate auto fallback disable */ + UINT32 TXRPT:1; + UINT32 TXLUT:1; + + UINT32 MCS:7; + UINT32 BW:1; /*channel bandwidth 20MHz or 40 MHz */ + UINT32 ShortGI:1; + UINT32 STBC:2; /* 1: STBC support MCS =0-7, 2,3 : RESERVE */ + UINT32 rsv0_27:3; + UINT32 PHYMODE:2; + + /* Word1 */ + /* ex: 1c ff 38 00 means ACK=0, BAWinSize=7, MPDUtotalByteCnt = 0x38 */ + UINT32 ACK:1; + UINT32 NSEQ:1; + UINT32 BAWinSize:6; + UINT32 wcid:8; + UINT32 MPDUtotalByteCnt:12; + UINT32 PacketId:4; + + /*Word2 */ + UINT32 IV; + + /*Word3 */ + UINT32 EIV; + + /* Word 4 */ + UINT32 EncodedAntID:8; + UINT32 TxStreamMode:8; + UINT32 TxPwrAdj:4; + UINT32 rsv4_21:1; + UINT32 CCP:1; + UINT32 PIFSREV:1; + UINT32 rsv4_23:9; +} TXWI_XMAC; +#endif + + + +#ifdef HDR_TRANS_SUPPORT +#define TX_WIFI_INFO_SIZE 4 +#define RX_WIFI_INFO_SIZE 36 +#define RX_WIFI_INFO_PAD 2 +#else +#define TX_WIFI_INFO_SIZE 0 +#define RX_WIFI_INFO_SIZE 0 +#define RX_WIFI_INFO_PAD 0 +#endif +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _TX_WIFI_INFO { + struct { + UINT32 More_Data:1; + UINT32 WEP:1; + UINT32 PS:1; + UINT32 RDG:1; + UINT32 QoS:1; + UINT32 EOSP:1; + UINT32 TID:4; + UINT32 Mode:2; + UINT32 VLAN:1; + UINT32 Rsv:3; + UINT32 BssIdx:4; + UINT32 Seq_Num:12; + } field; + UINT32 word; +} TX_WIFI_INFO; +#else +typedef union GNU_PACKED _TX_WIFI_INFO { + struct { + UINT32 Seq_Num:12; + UINT32 BssIdx:4; + UINT32 Rsv:3; + UINT32 VLAN:1; + UINT32 Mode:2; + UINT32 TID:4; + UINT32 EOSP:1; + UINT32 QoS:1; + UINT32 RDG:1; + UINT32 PS:1; + UINT32 WEP:1; + UINT32 More_Data:1; + } field; + UINT32 word; +} TX_WIFI_INFO; +#endif /* RT_BIG_ENDIAN */ + + +typedef struct GNU_PACKED _RX_WIFI_INFO{ + UINT8 wifi_hdr[36]; +}RX_WIFI_INFO; + + + + +/* + Rx Memory layout: + + 1. Rx Descriptor + Rx Descriptor(12 Bytes) + RX_FCE_Info(4 Bytes) + 2. Rx Buffer + RxInfo(4 Bytes) + RXWI() + 802.11 packet +*/ + + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXFCE_INFO{ + UINT32 info_type:2; + UINT32 s_port:3; + UINT32 qsel:2; + UINT32 pcie_intr:1; + + UINT32 mac_len:3; + UINT32 l3l4_done:1; + UINT32 pkt_80211:1; + UINT32 ip_err:1; + UINT32 tcp_err:1; + UINT32 udp_err:1; + + UINT32 rsv:2; + UINT32 pkt_len:14; +}RXFCE_INFO; +#else +typedef struct GNU_PACKED _RXFCE_INFO{ + UINT32 pkt_len:14; + UINT32 rsv:2; + + UINT32 udp_err:1; + UINT32 tcp_err:1; + UINT32 ip_err:1; + UINT32 pkt_80211:1; + UINT32 l3l4_done:1; + UINT32 mac_len:3; + + UINT32 pcie_intr:1; + UINT32 qsel:2; + UINT32 s_port:3; + UINT32 info_type:2; +}RXFCE_INFO; +#endif /* RT_BIG_ENDIAN */ + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXFCE_INFO_CMD{ + UINT32 info_type:2; + UINT32 d_port:3; + UINT32 qsel:2; + UINT32 pcie_intr:1; + UINT32 evt_type:4; + UINT32 cmd_seq:4; + UINT32 self_gen:1; + UINT32 rsv:1; + UINT32 pkt_len:14; +}RXFCE_INFO_CMD; +#else +typedef struct GNU_PACKED _RXFCE_INFO_CMD{ + UINT32 pkt_len:14; + UINT32 rsv:1; + UINT32 self_gen:1; + UINT32 cmd_seq:4; + UINT32 evt_type:4; + UINT32 pcie_intr:1; + UINT32 qsel:2; + UINT32 d_port:3; + UINT32 info_type:2; +}RXFCE_INFO_CMD; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXINFO_NMAC{ + UINT32 hdr_trans:1; + UINT32 vlan_tag:1; + UINT32 rsv:1; + UINT32 action_wanted:1; + UINT32 deauth:1; + UINT32 disasso:1; + UINT32 beacon:1; + UINT32 probe_rsp:1; + UINT32 sw_fc_type1:1; + UINT32 sw_fc_type0:1; + UINT32 pn_len:3; + UINT32 wapi_kid:1; + UINT32 bssid_idx3:1; + UINT32 dec:1; + UINT32 ampdu:1; + UINT32 l2pad:1; + UINT32 rssi:1; + UINT32 htc:1; + UINT32 amsdu:1; + UINT32 mic_err:1; + UINT32 icv_err:1; + UINT32 crc_err:1; + UINT32 mybss:1; + UINT32 bc:1; + UINT32 mc:1; + UINT32 u2me:1; + UINT32 frag:1; + UINT32 null:1; + UINT32 data:1; + UINT32 ba:1; +}RXINFO_NMAC; +#else +typedef struct GNU_PACKED _RXINFO_NMAC{ + UINT32 ba:1; + UINT32 data:1; + UINT32 null:1; + UINT32 frag:1; + UINT32 u2me:1; + UINT32 mcast:1; + UINT32 bcast:1; + UINT32 mybss:1; + UINT32 crc_err:1; + UINT32 icv_err:1; + UINT32 mic_err:1; + UINT32 amsdu:1; + UINT32 htc:1; + UINT32 rssi:1; + UINT32 l2pad:1; + UINT32 ampdu:1; + UINT32 dec:1; + UINT32 bssid_idx3:1; + UINT32 wapi_kid:1; + UINT32 pn_len:3; + UINT32 sw_fc_type0:1; + UINT32 sw_fc_type1:1; + UINT32 probe_rsp:1; + UINT32 beacon:1; + UINT32 disasso:1; + UINT32 deauth:1; + UINT32 action_wanted:1; + UINT32 rsv:1; + UINT32 vlan_tag:1; + UINT32 hdr_trans:1; +}RXINFO_NMAC; +#endif /* RT_BIG_ENDIAN */ + + +/* + RXWI wireless information format. +*/ +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXWI_NMAC{ + /* Word 0 */ + UINT32 eof:1; + UINT32 rsv:1; + UINT32 MPDUtotalByteCnt:14; /* = rxfceinfo_len - rxwi_len- rxinfo_len - l2pad */ + UINT32 udf:3; + UINT32 bss_idx:3; + UINT32 key_idx:2; + UINT32 wcid:8; + + /* Word 1 */ + UINT32 phy_mode:3; + UINT32 rsv_1:1; + UINT32 ldpc_ex_sym:1; + UINT32 stbc:1; + UINT32 sgi:1; + UINT32 bw:2; + UINT32 ldpc:1; + UINT32 mcs:6; + UINT32 sn:12; + UINT32 tid:4; + + /* Word 2 */ + UINT8 rssi[4]; + + /* Word 3~6 */ + UINT8 bbp_rxinfo[16]; +} RXWI_NMAC; +#else +typedef struct GNU_PACKED _RXWI_NMAC { + /* Word 0 */ + UINT32 wcid:8; + UINT32 key_idx:2; + UINT32 bss_idx:3; + UINT32 udf:3; + UINT32 MPDUtotalByteCnt:14; + UINT32 rsv:1; + UINT32 eof:1; + + /* Word 1 */ + UINT32 tid:4; + UINT32 sn:12; + UINT32 mcs:6; + UINT32 ldpc:1; + UINT32 bw:2; + UINT32 sgi:1; + UINT32 stbc:1; + UINT32 ldpc_ex_sym:1; + UINT32 rsv_1:1; + UINT32 phy_mode:3; + + /* Word 2 */ + UINT8 rssi[4]; + + /* Word 3~6 */ + UINT8 bbp_rxinfo[16]; +} RXWI_NMAC; +#endif /* RT_BIG_ENDIAN */ + + + + +typedef struct GNU_PACKED _NMAC_HW_RATE_CTRL_STRUCT{ +#ifdef RT_BIG_ENDIAN + UINT16 PHYMODE:3; + UINT16 iTxBF:1; + UINT16 eTxBF:1; + UINT16 STBC:1; + UINT16 ShortGI:1; + UINT16 BW:2; /* channel bandwidth 20/40/80 MHz */ + UINT16 ldpc:1; + UINT16 MCS:6; +#else + UINT16 MCS:6; + UINT16 ldpc:1; + UINT16 BW:2; + UINT16 ShortGI:1; + UINT16 STBC:1; + UINT16 eTxBF:1; + UINT16 iTxBF:1; + UINT16 PHYMODE:3; +#endif /* RT_BIG_ENDIAN */ +}NMAC_HW_RATE_CTRL_STRUCT; + + + + +/* ================================================================================= */ +/* Register format */ +/* ================================================================================= */ +#define CMB_CTRL 0x0020 +#define CMB_CTRL_AUX_OPT_MASK (0xffff) +#define CMB_CTRL_AUX_OPT_ANTSEL (1 << 12) +#define CMB_CTRL_AUX_OPT_GPIO_SETTING (1 << 14) +#define CMB_CTRL_CSR_UART_MODE (1 << 16) +#define CMB_CTRL_GPIO_MODE_LED1 (1 << 17) +#define CMB_CTRL_GPIO_MODE_LED2 (1 << 18) +#define CMB_CTRL_FOR_CLK_XTAL (1 << 19) +#define CMB_CTRL_CSR_UART_NFC (1 << 20) +#define CMB_CTRL_XTAL_RDY (1 << 22) +#define CMB_CTRL_PLL_LD (1 << 23) + +#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; +#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; +#endif + +#define COEXCFG0 0x0040 +#define COEXCFG0_COEX_EN (1 << 0) +#define COEXCFG0_FIX_WL_DI_ANT (1 << 1) +#define COEXCFG0_FIX_WL_ANT_EN (1 << 2) +#define COEXCFG0_FIX_WL_TX_PWR_MASK (0x3 << 6) +#define COEXCFG0_FIX_WL_GCRF_EN (1 << 8) +#define COEXCFG0_FIX_WL_RF_LNA0_MASK (0x3 << 12) +#define COEXCFG0_FIX_WL_RF_LNA1_MASK (0x3 << 14) +#define COEXCFG0_COEX_CFG0_MASK (0xff << 16) +#define COEXCFG0_COEX_CFG1_MASK (0xff << 24) + +#define COEXCFG1 0x0044 +#define COEXCFG1_DIS_WL_TR_DELAY_MASK (0xff << 0) +#define COEXCFG1_DIS_WL_PA_DELAY_MASK (0xff << 8) +#define COEXCFG1_DIS_WL_RF_DELAY_MASK (0xff << 16) +#define COEXCFG1_FIX_WL_TX_GCRF0_MASK (0xf << 24) +#define COEXCFG1_FIX_WL_TX_GCRF1_MASK (0xf << 28) + +#define COEXCFG2 0x0048 +#define COEXCFG2_WL_COEX_CFG0_MASK (0xff << 0) +#define COEXCFG2_WL_COEX_CFG1_MASK (0xff << 8) +#define COEXCFG2_BT_COEX_CFG0_MASK (0xff << 16) +#define COEXCFG2_BT_COEX_CFG1_MASK (0xff << 24) + +#define COEXCFG3 0x004c +#define COEXCFG3_COEX_VER (1 << 0) +#define COEXCFG3_TDM_EN (1 << 1) +#define COEXCFG3_IO_TR_SW0_MODE (1 << 2) +#define COEXCFG3_CSR_FRC_TR_SW0 (1 << 3) +#define COEXCFG3_FIX_IO_ANT_SEL_EN (1 << 4) +#define COEXCFG3_REG_IO_ANT_SEL_EN (1 << 5) +#define COEXCFG3_PTA_CNT_CLEAR (1 << 6) +#define COEXCFG3_PTA_CNT_EN (1 << 7) +#define COEXCFG3_BT_TX_STATUS (1 << 16) + +#define MISC_CTRL 0x64 + +#define WLAN_FUN_CTRL 0x80 +#define WLAN_FUN_CTRL_WLAN_EN (1 << 0) +#define WLAN_FUN_CTRL_WLAN_CLK_EN (1 << 1) +#define WLAN_FUN_CTRL_WLAN_RESET_RF (1 << 2) + +/* MT76x0 definition */ +#define WLAN_FUN_CTRL_WLAN_RESET (1 << 3) + +/* MT76x2 definition */ +#define WLAN_FUN_CTRL_CSR_F20M_CKEN (1 << 3) + +#define WLAN_FUN_CTRL_PCIE_APP0_CLK_REQ (1 << 4) +#define WLAN_FUN_CTRL_FRC_WL_ANT_SEL (1 << 5) +#define WLAN_FUN_CTRL_INV_ANT_SEL (1 << 6) +#define WLAN_FUN_CTRL_WAKE_HOST_F0 (1 << 7) + +/* MT76x0 definition */ +#define WLAN_FUN_CTRL_GPIO0_IN_MASK (0xff << 8) +#define WLAN_FUN_CTRL_GPIO0_OUT_MASK (0xff << 16) +#define WLAN_FUN_CTRL_GPIO0_OUT_OE_N_MASK (0xff << 24) + +/* MT76x2 definition */ +#define WLAN_FUN_CTRL_THERM_RST (1 << 8) +#define WLAN_FUN_CTRL_THERM_CKEN (1 << 9) + +#ifdef RT_BIG_ENDIAN +typedef union _WLAN_FUN_CTRL_STRUC{ + struct{ + UINT32 GPIO0_OUT_OE_N:8; + UINT32 GPIO0_OUT:8; + UINT32 GPIO0_IN:8; + UINT32 WLAN_ACC_BT:1; + UINT32 INV_TR_SW0:1; + UINT32 FRC_WL_ANT_SET:1; + UINT32 PCIE_APP0_CLK_REQ:1; + UINT32 WLAN_RESET:1; + UINT32 WLAN_RESET_RF:1; + UINT32 WLAN_CLK_EN:1; + UINT32 WLAN_EN:1; + }field; + UINT32 word; +}WLAN_FUN_CTRL_STRUC, *PWLAN_FUN_CTRL_STRUC; +#else +typedef union _WLAN_FUN_CTRL_STRUC{ + struct{ + UINT32 WLAN_EN:1; + UINT32 WLAN_CLK_EN:1; + UINT32 WLAN_RESET_RF:1; + UINT32 WLAN_RESET:1; + UINT32 PCIE_APP0_CLK_REQ:1; + UINT32 FRC_WL_ANT_SET:1; + UINT32 INV_TR_SW0:1; + UINT32 WLAN_ACC_BT:1; + UINT32 GPIO0_IN:8; + UINT32 GPIO0_OUT:8; + UINT32 GPIO0_OUT_OE_N:8; + }field; + UINT32 word; +}WLAN_FUN_CTRL_STRUC, *PWLAN_FUN_CTRL_STRUC; +#endif + + +#define WLAN_FUN_INFO 0x84 +#ifdef RT_BIG_ENDIAN +typedef union _WLAN_FUN_INFO_STRUC{ + struct{ + UINT32 BT_EEP_BUSY:1; /* Read-only for WLAN Driver */ + UINT32 Rsv1:26; + UINT32 COEX_MODE:5; /* WLAN function enable */ + }field; + UINT32 word; +}WLAN_FUN_INFO_STRUC, *PWLAN_FUN_INFO_STRUC; +#else +typedef union _WLAN_FUN_INFO_STRUC{ + struct{ + UINT32 COEX_MODE:5; /* WLAN function enable */ + UINT32 Rsv1:26; + UINT32 BT_EEP_BUSY:1; /* Read-only for WLAN Driver */ + }field; + UINT32 word; +}WLAN_FUN_INFO_STRUC, *PWLAN_FUN_INFO_STRUC; +#endif + + +#define BT_FUN_CTRL 0xC0 +#ifdef RT_BIG_ENDIAN +typedef union _BT_FUN_CTRL_STRUC{ + struct{ + UINT32 GPIO1_OUT_OE_N:8; + UINT32 GPIO1_OUT:8; + UINT32 GPIO1_IN:8; + UINT32 BT_ACC_WLAN:1; + UINT32 INV_TR_SW1:1; + UINT32 URXD_GPIO_MODE:1; + UINT32 PCIE_APP1_CLK_REQ:1; + UINT32 BT_RESET:1; + UINT32 BT_RF_EN:1; + UINT32 BT_CLK_EN:1; + UINT32 BT_EN:1; + }field; + UINT32 word; +}BT_FUN_CTRL_STRUC, *PBT_FUN_CTRL_STRUC; +#else +typedef union _BT_FUN_CTRL_STRUC { + struct{ + UINT32 BT_EN:1; + UINT32 BT_CLK_EN:1; + UINT32 BT_RF_EN:1; + UINT32 BT_RESET:1; + UINT32 PCIE_APP1_CLK_REQ:1; + UINT32 URXD_GPIO_MODE:1; + UINT32 INV_TR_SW1:1; + UINT32 BT_ACC_WLAN:1; + UINT32 GPIO1_IN:8; + UINT32 GPIO1_OUT:8; + UINT32 GPIO1_OUT_OE_N:8; + }field; + UINT32 word; +}BT_FUN_CTRL_STRUC, *PBT_FUN_CTRL_STRUC; +#endif + + +#define BT_FUN_INFO 0xC4 +#ifdef RT_BIG_ENDIAN +typedef union _BT_FUN_INFO_STRUC{ + struct{ + UINT32 WLAN_EEP_BUSY:1; + UINT32 BTPower1:7; /* Peer */ + UINT32 BTPower0:8; /* Self */ + UINT32 AFH_END_CH:8; + UINT32 AFH_START_CH:8; + }field; + UINT32 word; +} BT_FUN_INFO_STRUC, *PBT_FUN_INFO_STRUC; +#else +typedef union _BT_FUN_INFO_STRUC { + struct{ + UINT32 AFH_START_CH:8; + UINT32 AFH_END_CH:8; + UINT32 BTPower0:8; /* Self */ + UINT32 BTPower1:7; /* Peer */ + UINT32 WLAN_EEP_BUSY:1; + }field; + UINT32 word; +}BT_FUN_INFO_STRUC, *PBT_FUN_INFO_STRUC; +#endif + +// TODO: shiang, this data structure is not defined for register. may can move to other place +typedef struct _WLAN_BT_COEX_SETTING +{ + BOOLEAN ampduOff; + BOOLEAN coexSettingRunning; + BOOLEAN RateSelectionForceToUseRSSI; + UCHAR TxQualityFlag; + ULONG alc; + ULONG slna; +}WLAN_BT_COEX_SETTING, *PWLAN_BT_COEX_SETTING; + +#define XO_CTRL0 0x0100 +#define XO_CTRL1 0x0104 +#define XO_CTRL2 0x0108 +#define XO_CTRL3 0x010C +#define XO_CTRL4 0x0110 +#define XO_CTRL5 0x0114 +#define XO_CTRL6 0x0118 + +#define CLK_ENABLE 0x014C + +#define MCU_CMD_CFG 0x0234 + + +#define TSO_CTRL 0x0250 +#ifdef RT_BIG_ENDIAN +typedef union _TSO_CTRL_STRUC { + struct { + UINT32 rsv:13; + UINT32 TSO_WR_LEN_EN:1; + UINT32 TSO_SEG_EN:1; + UINT32 TSO_EN:1; + UINT32 RXWI_LEN:4; + UINT32 RX_L2_FIX_LEN:4; + UINT32 TXWI_LEN:4; + UINT32 TX_L2_FIX_LEN:4; + } field; + UINT32 word; +} TSO_CTRL_STRUC; +#else +typedef union _TSO_CTRL_STRUC { + struct { + UINT32 TX_L2_FIX_LEN:4; + UINT32 TXWI_LEN:4; + UINT32 RX_L2_FIX_LEN:4; + UINT32 RXWI_LEN:4; + UINT32 TSO_EN:1; + UINT32 TSO_SEG_EN:1; + UINT32 TSO_WR_LEN_EN:1; + UINT32 rsv:13; + } field; + UINT32 word; +} TSO_CTRL_STRUC; +#endif /* RT_BIG_ENDIAN */ + + +#define TX_PROT_CFG6 0x13E0 // VHT 20 Protection +#define TX_PROT_CFG7 0x13E4 // VHT 40 Protection +#define TX_PROT_CFG8 0x13E8 // VHT 80 Protection +#define PIFS_TX_CFG 0x13EC // PIFS setting + +//---------------------------------------------------------------- +// Header Translation +//---------------------------------------------------------------- + +/* + header translation control register + bit0 --> TX translation enable + bit1 --> RX translation enable +*/ +#define HEADER_TRANS_CTRL_REG 0x0260 +#define HT_TX_ENABLE 0x1 +#define HT_RX_ENABLE 0x2 + +#define HT_MAC_ADDR_DW0 0x02A4 +#define HT_MAC_ADDR_DW1 0x02A8 +#define HT_MAC_BSSID_DW0 0x02AC +#define HT_MAC_BSSID_DW1 0x02B0 + +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _HDR_TRANS_CTRL_STRUC { + struct { + UINT32 Rsv:30; + UINT32 Rx_En:1; + UINT32 Tx_En:1; + } field; + UINT32 word; +} HDR_TRANS_CTRL_STRUC, *PHDR_TRANS_CTRL_STRUC; +#else +typedef union GNU_PACKED _HDR_TRANS_CTRL_STRUC { + struct { + UINT32 Tx_En:1; + UINT32 Rx_En:1; + UINT32 Rsv:30; + } field; + UINT32 word; +} HDR_TRANS_CTRL_STRUC, *PHDR_TRANS_CTRL_STRUC; +#endif /* RT_BIG_ENDIAN */ + +/* RX header translation enable by WCID */ +#define HT_RX_WCID_EN_BASE 0x0264 +#define HT_RX_WCID_OFFSET 32 +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _HT_RX_WCID_EN_STRUC { + struct { + UINT32 RX_WCID31_TRAN_EN:1; + UINT32 RX_WCID30_TRAN_EN:1; + UINT32 RX_WCID29_TRAN_EN:1; + UINT32 RX_WCID28_TRAN_EN:1; + UINT32 RX_WCID27_TRAN_EN:1; + UINT32 RX_WCID26_TRAN_EN:1; + UINT32 RX_WCID25_TRAN_EN:1; + UINT32 RX_WCID24_TRAN_EN:1; + UINT32 RX_WCID23_TRAN_EN:1; + UINT32 RX_WCID22_TRAN_EN:1; + UINT32 RX_WCID21_TRAN_EN:1; + UINT32 RX_WCID20_TRAN_EN:1; + UINT32 RX_WCID19_TRAN_EN:1; + UINT32 RX_WCID18_TRAN_EN:1; + UINT32 RX_WCID17_TRAN_EN:1; + UINT32 RX_WCID16_TRAN_EN:1; + UINT32 RX_WCID15_TRAN_EN:1; + UINT32 RX_WCID14_TRAN_EN:1; + UINT32 RX_WCID13_TRAN_EN:1; + UINT32 RX_WCID12_TRAN_EN:1; + UINT32 RX_WCID11_TRAN_EN:1; + UINT32 RX_WCID10_TRAN_EN:1; + UINT32 RX_WCID9_TRAN_EN:1; + UINT32 RX_WCID8_TRAN_EN:1; + UINT32 RX_WCID7_TRAN_EN:1; + UINT32 RX_WCID6_TRAN_EN:1; + UINT32 RX_WCID5_TRAN_EN:1; + UINT32 RX_WCID4_TRAN_EN:1; + UINT32 RX_WCID3_TRAN_EN:1; + UINT32 RX_WCID2_TRAN_EN:1; + UINT32 RX_WCID1_TRAN_EN:1; + UINT32 RX_WCID0_TRAN_EN:1; + } field; + UINT32 word; +} HT_RX_WCID_EN_STRUC, *PHT_RX_WCID_EN_STRUC; +#else +typedef union GNU_PACKED _HT_RX_WCID_EN_STRUC { + struct { + UINT32 RX_WCID0_TRAN_EN:1; + UINT32 RX_WCID1_TRAN_EN:1; + UINT32 RX_WCID2_TRAN_EN:1; + UINT32 RX_WCID3_TRAN_EN:1; + UINT32 RX_WCID4_TRAN_EN:1; + UINT32 RX_WCID5_TRAN_EN:1; + UINT32 RX_WCID6_TRAN_EN:1; + UINT32 RX_WCID7_TRAN_EN:1; + UINT32 RX_WCID8_TRAN_EN:1; + UINT32 RX_WCID9_TRAN_EN:1; + UINT32 RX_WCID10_TRAN_EN:1; + UINT32 RX_WCID11_TRAN_EN:1; + UINT32 RX_WCID12_TRAN_EN:1; + UINT32 RX_WCID13_TRAN_EN:1; + UINT32 RX_WCID14_TRAN_EN:1; + UINT32 RX_WCID15_TRAN_EN:1; + UINT32 RX_WCID16_TRAN_EN:1; + UINT32 RX_WCID17_TRAN_EN:1; + UINT32 RX_WCID18_TRAN_EN:1; + UINT32 RX_WCID19_TRAN_EN:1; + UINT32 RX_WCID20_TRAN_EN:1; + UINT32 RX_WCID21_TRAN_EN:1; + UINT32 RX_WCID22_TRAN_EN:1; + UINT32 RX_WCID23_TRAN_EN:1; + UINT32 RX_WCID24_TRAN_EN:1; + UINT32 RX_WCID25_TRAN_EN:1; + UINT32 RX_WCID26_TRAN_EN:1; + UINT32 RX_WCID27_TRAN_EN:1; + UINT32 RX_WCID28_TRAN_EN:1; + UINT32 RX_WCID29_TRAN_EN:1; + UINT32 RX_WCID30_TRAN_EN:1; + UINT32 RX_WCID31_TRAN_EN:1; + } field; + UINT32 word; +} HT_RX_WCID_EN_STRUC, *PHT_RX_WCID_EN_STRUC; +#endif /* RT_BIG_ENDIAN */ + +/* RX header translation - black list */ +#define HT_RX_BL_BASE 0x0284 +#define HT_RX_BL_OFFSET 2 +#define HT_RX_BL_SIZE 8 +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _HT_RX_BLACK_LIST_STRUC { + struct { + UINT32 BLACK_ETHER_TYPE1:16; + UINT32 BLACK_ETHER_TYPE0:16; + } field; + UINT32 word; +} HT_RX_BLACK_LIST_STRUC, *PHT_RX_BLACK_LIST_STRUC; +#else +typedef union GNU_PACKED _HT_RX_BLACK_LIST_STRUC { + struct { + UINT32 BLACK_ETHER_TYPE0:16; + UINT32 BLACK_ETHER_TYPE1:16; + } field; + UINT32 word; +} HT_RX_BLACK_LIST_STRUC, *PHT_RX_BLACK_LIST_STRUC; +#endif /* RT_BIG_ENDIAN */ + +/* RX VLAN Mapping (TCI) */ +#define HT_BSS_VLAN_BASE 0x0294 +#define HT_BSS_VLAN_OFFSET 2 +#define HT_BSS_VLAN_SIZE 8 +#ifdef RT_BIG_ENDIAN +typedef union GNU_PACKED _HT_BSS_VLAN_STRUC { + struct { + UINT32 TCI1_VID:12; + UINT32 TCI1_CFI:1; + UINT32 TCI1_PCP:3; + UINT32 TCI0_VID:12; + UINT32 TCI0_CFI:1; + UINT32 TCI0_PCP:3; + } field; + UINT32 word; +} HT_BSS_VLAN_STRUC, *PHT_BSS_VLAN_STRUC; +#else +typedef union GNU_PACKED _HT_BSS_VLAN_STRUC { + struct { + UINT32 TCI0_PCP:3; + UINT32 TCI0_CFI:1; + UINT32 TCI0_VID:12; + UINT32 TCI1_PCP:3; + UINT32 TCI1_CFI:1; + UINT32 TCI1_VID:12; + } field; + UINT32 word; +} HT_BSS_VLAN_STRUC, *PHT_BSS_VLAN_STRUC; +#endif /* RT_BIG_ENDIAN */ + + +// TODO: shiang-6590, following definitions are dummy and not used for RT6590, shall remove/correct these! +#define GPIO_CTRL_CFG 0x0228 +#define RLT_PBF_MAX_PCNT 0x0408 //TX_MAX_PCNT +// TODO:shiang-6590 -------------------------- + + +#define RF_MISC 0x0518 +#ifdef RT_BIG_ENDIAN +typedef union _RF_MISC_STRUC{ + struct{ + UINT32 Rsv1:29; + UINT32 EXT_PA_EN:1; + UINT32 ADDAC_LDO_ADC9_EN:1; + UINT32 ADDAC_LDO_ADC6_EN:1; + }field; + UINT32 word; +}RF_MISC_STRUC, *PRF_MISC_STRUC; +#else +typedef union _RF_MISC_STRUC{ + struct{ + UINT32 ADDAC_LDO_ADC6_EN:1; + UINT32 ADDAC_LDO_ADC9_EN:1; + UINT32 EXT_PA_EN:1; + UINT32 Rsv1:29; + }field; + UINT32 word; +}RF_MISC_STRUC, *PRF_MISC_STRUC; +#endif + +#define PAMODE_PWR_ADJ0 0x1228 +#define PAMODE_PWR_ADJ1 0x122c +#define DACCLK_EN_DLY_CFG 0x1264 + +#define RLT_PAIRWISE_KEY_TABLE_BASE 0x8000 /* 32-byte * 256-entry = -byte */ +#define RLT_HW_KEY_ENTRY_SIZE 0x20 + +#define RLT_PAIRWISE_IVEIV_TABLE_BASE 0xa000 /* 8-byte * 256-entry = -byte */ +#define RLT_MAC_IVEIV_TABLE_BASE 0xa000 /* 8-byte * 256-entry = -byte */ +#define RLT_HW_IVEIV_ENTRY_SIZE 8 + +#define RLT_MAC_WCID_ATTRIBUTE_BASE 0xa800 /* 4-byte * 256-entry = -byte */ +#define RLT_HW_WCID_ATTRI_SIZE 4 + +#define RLT_SHARED_KEY_TABLE_BASE 0xac00 /* 32-byte * 16-entry = 512-byte */ +#define RLT_SHARED_KEY_MODE_BASE 0xb000 /* 32-byte * 16-entry = 512-byte */ + +#define RLT_HW_SHARED_KEY_MODE_SIZE 4 + +#define RLT_SHARED_KEY_TABLE_BASE_EXT 0xb400 /* for BSS_IDX=8~15, 32-byte * 16-entry = 512-byte */ +#define RLT_SHARED_KEY_MODE_BASE_EXT 0xb3f0 /* for BSS_IDX=8~15, 32-byte * 16-entry = 512-byte */ + +/* This resgiser is ONLY be supported for RT3883 or later. + It conflicted with BCN#0 offset of previous chipset. */ +#define RLT_WAPI_PN_TABLE_BASE 0xb800 +#define RLT_WAPI_PN_ENTRY_SIZE 8 + +struct _RTMP_ADAPTER; +struct _RXINFO_STRUC; +union _TXINFO_STRUC; +union _TXWI_STRUC; +union _RXWI_STRUC; + +VOID dump_rlt_rxinfo(struct _RTMP_ADAPTER *pAd, struct _RXINFO_STRUC *pRxInfo); +VOID dump_rlt_txinfo(struct _RTMP_ADAPTER *pAd, union _TXINFO_STRUC *pTxInfo); +VOID dump_rlt_txwi(struct _RTMP_ADAPTER *pAd, union _TXWI_STRUC *pTxWI); +VOID dump_rlt_rxwi(struct _RTMP_ADAPTER *pAd, union _RXWI_STRUC *pRxWI); +VOID dumpRxFCEInfo(struct _RTMP_ADAPTER *pAd, RXFCE_INFO *pRxFceInfo); + +VOID rlt_asic_init_txrx_ring(struct _RTMP_ADAPTER *pAd); + +INT rlt_wlan_chip_onoff(struct _RTMP_ADAPTER *pAd, BOOLEAN bOn, BOOLEAN bResetWLAN); + + +#endif /* __RAL_NMAC_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac_pbf.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac_pbf.h new file mode 100644 index 000000000..29f929715 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac_pbf.h @@ -0,0 +1,99 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + ral_nmac_pbf.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RAL_NMAC_PBF_H__ +#define __RAL_NMAC_PBF_H__ + + + +/* ================================================================================= */ +/* Register format for PBF */ +/* ================================================================================= */ + + +/* Most are for debug. Driver doesn't touch PBF register. */ +#ifdef RT_BIG_ENDIAN +typedef union _RLT_PBF_SYS_CTRL_STRUC { + struct { + UINT32 rsv5:7; /* Reserved */ + UINT32 CSR_TEST_EN:1; + UINT32 MAC_CLKSEL:2; /* MAC clock selection */ + UINT32 PWRSV_EN:2; + UINT32 SHRM_SEL:1; /* Shared memory access selection */ + UINT32 PBF_MSEL:2; /* Packet buffer memory access selection */ + UINT32 rsv4:5; + UINT32 PBF_CLK_EN:1; /* PBF clock enable */ + UINT32 MAC_CLK_EN:1; /* MAC clock enable */ + UINT32 rsv3:6; + UINT32 PBF_RESET:1; /* PBF hardware reset */ + UINT32 MAC_RESET:1; /* MAC hardware reset */ + UINT32 rsv:2; + } field; + UINT32 word; +} RLT_PBF_SYS_CTRL_STRUC; +#else +typedef union _RLT_PBF_SYS_CTRL_STRUC{ + struct { + UINT32 rsv5:7; /* Reserved */ + UINT32 CSR_TEST_EN:1; + UINT32 MAC_CLKSEL:2; /* MAC clock selection */ + UINT32 PWRSV_EN:2; + UINT32 SHRM_SEL:1; /* Shared memory access selection */ + UINT32 PBF_MSEL:2; /* Packet buffer memory access selection */ + UINT32 rsv4:5; + UINT32 PBF_CLK_EN:1; /* PBF clock enable */ + UINT32 MAC_CLK_EN:1; /* MAC clock enable */ + UINT32 rsv3:6; + UINT32 PBF_RESET:1; /* PBF hardware reset */ + UINT32 MAC_RESET:1; /* MAC hardware reset */ + UINT32 rsv:2; + }field; + UINT32 word; +} RLT_PBF_SYS_CTRL_STRUC; +#endif + + +#define RLT_PBF_CFG 0x0404 +#define RX_DROP_MODE (1 << 8) +#define TX_MAX_PCNT 0x0408 +#define RX_MAX_PCNT 0x040c +#define RXQ_STA 0x0430 +#define TXQ_STA 0x0434 + +#define RLT_BCN_OFFSET0 0x041c +#define RLT_BCN_OFFSET1 0x0420 +#define RLT_BCN_OFFSET2 0x0424 +#define RLT_BCN_OFFSET3 0x0428 + + +#define FCE_CTRL 0x0800 +#define FCE_PARAM 0x0804 +#define CHECKSUM_OFFLOAD 0x0808 + +#endif /* __RAL_NMAC_PBF_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac_pci.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac_pci.h new file mode 100644 index 000000000..e7b6d4958 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac_pci.h @@ -0,0 +1,326 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + ral_nmac_pci.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RAL_NMAC_PCI_H__ +#define __RAL_NMAC_PCI_H__ + + +#define INT_R0_DONE (1<<0) +#define INT_R1_DONE (1<<1) +#define INT_T0_DONE (1<<4) +#define INT_T1_DONE (1<<5) +#define INT_T2_DONE (1<<6) +#define INT_T3_DONE (1<<7) +#define INT_T4_DONE (1<<8) +#define INT_T5_DONE (1<<9) +#define INT_T6_DONE (1<<10) +#define INT_T7_DONE (1<<11) +#define INT_T8_DONE (1<<12) +#define INT_T9_DONE (1<<13) +#define INT_RESVD ((1<<14) | (1<<15)) +#define INT_RX_COHE (1<<16) +#define INT_TX_COHE (1<<17) +#define INT_ANY_COH (1<<18) +#define INT_MCU_CMD (1<<19) +#define INT_TBTT_ISR (1<<20) +#define INT_PRE_TBTT (1<<21) +#define INT_TX_STAT (1<<22) +#define INT_AUTO_WAKE (1<<23) +#define INT_GP_TIMER (1<<24) +#define INT_RESVD_2 (1<<25) +#define INT_RX_DLY (1<<26) +#define INT_TX_DLY (1<<27) + +// TODO: shiang-6590, for 6590, what's the interrupt bit for TONE_RADAR?? now just give a reseved bit +#define RLT_INT_TONE_RADAR (1<<29) + + +#define RLT_RxINT (INT_R0_DONE | INT_R1_DONE /* | INT_RX_DLY */) /* Delayed Rx or indivi rx */ +#define RLT_TxDataInt (INT_T0_DONE | \ + INT_T1_DONE | \ + INT_T2_DONE | \ + INT_T3_DONE /*| INT_TX_DLY*/) /* Delayed Tx or indivi tx */ + +#define RLT_TxMgmtInt (INT_T9_DONE /*| INT_TX_DLY*/) + +#define RLT_TxCoherent INT_TX_COHE +#define RLT_RxCoherent INT_RX_COHE +#define RLT_TxRxCoherent INT_ANY_COH +#define RLT_McuCommand INT_MCU_CMD /* mcu */ +#define RLT_PreTBTTInt INT_PRE_TBTT +#define RLT_TBTTInt INT_TBTT_ISR +#define RLT_GPTimeOutInt INT_GP_TIMER /* GPtimeout interrupt */ +#define RLT_AutoWakeupInt INT_AUTO_WAKE /* AutoWakeupInt interrupt */ +#define RLT_FifoStaFullInt INT_TX_STAT /* fifo statistics full interrupt */ +#define RLT_RadarInt (RLT_INT_TONE_RADAR) + +#define RLT_INT_RX (INT_R0_DONE | INT_R1_DONE) +#define RLT_INT_RX_DATA (INT_R0_DONE) +#define RLT_INT_RX_CMD (INT_R1_DONE) +#define RLT_INT_AC0_DLY (INT_T0_DONE) +#define RLT_INT_AC1_DLY (INT_T1_DONE) +#define RLT_INT_AC2_DLY (INT_T2_DONE) +#define RLT_INT_AC3_DLY (INT_T3_DONE) +#define RLT_INT_HCCA_DLY (INT_T8_DONE) +#define RLT_INT_MGMT_DLY (INT_T9_DONE) + +#ifdef CARRIER_DETECTION_SUPPORT +#define RLT_DELAYINTMASK (0x0DFF3FF3 | (RLT_RadarInt)) +#define RLT_INTMASK (0x0DFF3FF3 | (RLT_RadarInt)) +#else +#define RLT_DELAYINTMASK 0x0DFF3FF3 +#define RLT_INTMASK 0x0DFF3FF3 +#endif /* CARRIER_DETECTION_SUPPORT */ + + +/* + INT_SOURCE_CSR: Interrupt source register. Write one to clear corresponding bit + Refer to INT_SOURCE_CSR(0x200) +*/ +#ifdef RT_BIG_ENDIAN +typedef union _RLT_INT_SOURCE_CSR_STRUC { + struct { + UINT32 rsv1:4; + UINT32 TxDelayINT:1; + UINT32 RxDelayINT:1; + UINT32 rsv2:1; + UINT32 GPTimer:1; + UINT32 AutoWakeup:1; + UINT32 TXFifoStatusInt:1; + UINT32 PreTBTT:1; + UINT32 tbttInt:1; + UINT32 MCUCommandINT:1; + UINT32 trCoherent:1; + UINT32 txCoherent:1; + UINT32 rxCoherent:1; + UINT32 rsv3:2; + UINT32 TxDone9:1; + UINT32 TxDone8:1; + UINT32 TxDone7:1; + UINT32 TxDone6:1; + UINT32 MgmtDmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac0DmaDone:1; + UINT32 rsv4:2; + UINT32 RxDone1:1; + UINT32 RxDone:1; + }field; + UINT32 word; +}RLT_INT_SOURCE_CSR_STRUC; +#else +typedef union _RLT_INT_SOURCE_CSR_STRUC { + struct { + UINT32 RxDone:1; + UINT32 RxDone1:1; + UINT32 rsv4:2; + UINT32 Ac0DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 MgmtDmaDone:1; + UINT32 TxDone6:1; + UINT32 TxDone7:1; + UINT32 TxDone8:1; + UINT32 TxDone9:1; + UINT32 rsv3:2; + UINT32 rxCoherent:1; + UINT32 txCoherent:1; + UINT32 trCoherent:1; + UINT32 MCUCommandINT:1; + UINT32 tbttInt:1; + UINT32 PreTBTT:1; + UINT32 TXFifoStatusInt:1; + UINT32 AutoWakeup:1; + UINT32 GPTimer:1; + UINT32 rsv2:1; + UINT32 RxDelayINT:1; + UINT32 TxDelayINT:1; + UINT32 rsv1:4; + }field; + UINT32 word; +}RLT_INT_SOURCE_CSR_STRUC; +#endif /* RT_BIG_ENDIAN */ + + +/* + INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF + Refer to INT_MASK_CSR(0x204) +*/ +#ifdef RT_BIG_ENDIAN +typedef union _PDMA_INT_MASK{ + struct { + UINT32 rsv1:4; + UINT32 TxDelayINT:1; + UINT32 RxDelayINT:1; + UINT32 rsv2:1; + UINT32 GPTimer:1; + UINT32 AutoWakeup:1; + UINT32 TXFifoStatusInt:1; + UINT32 PreTBTT:1; + UINT32 tbttInt:1; + UINT32 MCUCommandINT:1; + UINT32 trCoherent:1; + UINT32 txCoherent:1; + UINT32 rxCoherent:1; + UINT32 rsv3:2; + UINT32 TxDone9:1; + UINT32 TxDone8:1; + UINT32 TxDone7:1; + UINT32 TxDone6:1; + UINT32 MgmtDmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac0DmaDone:1; + UINT32 rsv4:2; + UINT32 RxDone1:1; + UINT32 RxDone:1; + }field; + UINT32 word; +}PMDA_INT_MASK; +#else +typedef union _PDMA_INT_MASK{ + struct { + UINT32 RxDone:1; + UINT32 RxDone1:1; + UINT32 rsv4:2; + UINT32 Ac0DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 MgmtDmaDone:1; + UINT32 TxDone6:1; + UINT32 TxDone7:1; + UINT32 TxDone8:1; + UINT32 TxDone9:1; + UINT32 rsv3:2; + UINT32 rxCoherent:1; + UINT32 txCoherent:1; + UINT32 trCoherent:1; + UINT32 MCUCommandINT:1; + UINT32 tbttInt:1; + UINT32 PreTBTT:1; + UINT32 TXFifoStatusInt:1; + UINT32 AutoWakeup:1; + UINT32 GPTimer:1; + UINT32 rsv2:1; + UINT32 RxDelayINT:1; + UINT32 TxDelayINT:1; + UINT32 rsv1:4; + }field; + UINT32 word; +}PMDA_INT_MASK; +#endif /* RT_BIG_ENDIAN */ + + +/*@!Release + Tx Ring Layout and assignments + + Totally we have 10 Tx Rings and assigned as following usage: + 1. RT85592 + TxRing 0~3: for TxQ Channel 1 with AC_BK/BE/VI/VO + TxRing 4 : for TxQ CTRL + TxRing 5 : for TxQ MGMT + TxRing 6~9: for TxQ Channel 2 with AC_BK/BE/VI/VO + + 2. MT7650 + TxRing 0~3: for TxQ Channel 1 with AC_BK/BE/VI/VO + TxRing 4~7: for TxQ Channel 2 with AC_BK/BE/VI/VO + TxRing 8 : for TxQ CTRL + TxRing 9 : for TxQ MGMT + + For each TxRing, we have four register to control it + TX_RINGn_CTRL0 (0x0): base address of this ring(4-DWORD aligned address) + TX_RINGn_CTRL1 (0x4): maximum number of TxD count in this ring + TX_RINGn_CTRL2 (0x8): Point to the next TxD CPU wants to use + TX_RINGn_CTRL3 (0xc): Point to the next TxD DMA wants to use +*/ +#define RLT_RINGREG_DIFF 0x10 +#define TX_RING_BASE 0x0300 +#define TX_RING_NUM 10 +#define TX_RING_PTR 0x0300 +#define TX_RING_CNT 0x0304 +#define TX_RING_CIDX 0x0308 +#define TX_RING_DIDX 0x030c + +#define TX_CHAN_BASE_1 (TX_RING_BASE + RLT_RINGREG_DIFF * 0) +#define TX_CHAN_BASE_2 (TX_RING_BASE + RLT_RINGREG_DIFF * 6) + +/* following address is base on TX_CHAN_BASE_X */ +#define TX_RING_BK_BASE 0x0 +#define TX_RING_BK_CNT (TX_RING_BK_BASE + 0x04) +#define TX_RING_BK_CIDX (TX_RING_BK_BASE + 0x08) +#define TX_RING_BK_DIDX (TX_RING_BK_BASE + 0x0c) + +#define TX_RING_BE_BASE (TX_RING_BK_BASE + RLT_RINGREG_DIFF) +#define TX_RING_BE_CNT (TX_RING_BE_BASE + 0x04) +#define TX_RING_BE_CIDX (TX_RING_BE_BASE + 0x08) +#define TX_RING_BE_DIDX (TX_RING_BE_BASE + 0x0c) + +#define TX_RING_VI_BASE (TX_RING_BE_BASE + RLT_RINGREG_DIFF) +#define TX_RING_VI_CNT (TX_RING_VI_BASE + 0x04) +#define TX_RING_VI_CIDX (TX_RING_VI_BASE + 0x08) +#define TX_RING_VI_DIDX (TX_RING_VI_BASE + 0x0c) + +#define TX_RING_VO_BASE (TX_RING_VI_BASE + RLT_RINGREG_DIFF) +#define TX_RING_VO_CNT (TX_RING_VO_BASE + 0x04) +#define TX_RING_VO_CIDX (TX_RING_VO_BASE + 0x08) +#define TX_RING_VO_DIDX (TX_RING_VO_BASE + 0x0c) + + +/* + Rx Ring Layput and assignments + + Totally we have 2 Rx Rings and assigned as following usage: + RxRing 0: for all received data packets + RxRing 1: for internal ctrl/info packets generated by on-chip CPU. + + For each TxRing, we have four register to control it + RX_RING_CTRL0 (0x0): base address of this ring(4-DWORD aligned address) + RX_RING_CTRL1 (0x4): maximum number of RxD count in this ring + RX_RING_CTRL2 (0x8): Point to the next RxD CPU wants to use + RX_RING_CTRL3 (0xc): Point to the next RxD DMA wants to use +*/ +#define RX_RING_BASE 0x03c0 +#define RX_RING1_BASE 0x03d0 +#define RX_RING_NUM 2 +#define RX_RING_PTR RX_RING_BASE +#define RX_RING_CNT (RX_RING_BASE + 0x04) +#define RX_RING_CIDX (RX_RING_BASE + 0x08) +#define RX_RING_DIDX (RX_RING_BASE + 0x0c) + +#define RX_RING1_PTR (RX_RING_BASE + RLT_RINGREG_DIFF * 1) +#define RX_RING1_CNT (RX_RING_BASE + RLT_RINGREG_DIFF * 1 + 0x04) +#define RX_RING1_CIDX (RX_RING_BASE + RLT_RINGREG_DIFF * 1 + 0x08) +#define RX_RING1_DIDX (RX_RING_BASE + RLT_RINGREG_DIFF * 1 + 0x0c) + +#endif /*__RAL_NMAC_PCI_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac_rf_ctrl.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac_rf_ctrl.h new file mode 100644 index 000000000..b69a614db --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac_rf_ctrl.h @@ -0,0 +1,43 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + ral_nmac_rf_ctrl.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RAL_NMAC_RF_CTRL_H__ +#define __RAL_NMAC_RF_CTRL_H__ + + + +/* ================================================================================= */ +/* Register format for RFCTRL */ +/* ================================================================================= */ + +#define RLT_RF_BYPASS_0 0x0504 +#define RLT_RF_SETTING_0 0x050C + + +#endif /* __RAL_OMAC_RF_CTRL_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac_usb.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac_usb.h new file mode 100644 index 000000000..83d82c44a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/nmac/ral_nmac_usb.h @@ -0,0 +1,33 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + ral_nmac_usb.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RAL_NMAC_USB_H__ +#define __RAL_NMAC_USB_H__ + +#define RLT_USB_DMA_CFG 0x0238 +#define U3DMA_WLCFG 0x9018 + +#endif /*__RAL_NMAC_USB_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac.h new file mode 100644 index 000000000..707f681f1 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac.h @@ -0,0 +1,348 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + ral_omac.h + + Abstract: + Ralink Wireless Chip RAL MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RAL_OMAC_H__ +#define __RAL_OMAC_H__ + + + +/* + TXINFO +*/ + +/* + TXINFO fields defintion: + + USBDMATxPktLen[b0~b14]: + Total bytes of all sub-frame. ONLY for USB bulk Aggregation + IPOffset[b15~b18]: + Start byte of IP packet. The base address is from TXINFO. + 0: header will be parsed by hardware. + This field is like backdoor. + For AMSDU, this field is useless + + TCPOffset[b19~b23]: + Start byte of TCP packet from IP packet The base address is IP header. + 0: header will be parsed by hardware. + This field is like backdoor. + For AMSDU, this field is useless + + WIV[b24]: + Wireless Info Valid. + 1: if Driver already fill WI + 0: if DMA needs to copy WI to correctposition + + QSEL[b25~b26]: + Select on-chip FIFO ID for 2nd-stage output scheduler. + 0:MGMT, 1:HCCA 2:EDCA + + SwUseLastRound[b27]: + Software used for USB-based chipset, reserved for other interfaces. + + uso[b28]: + UDP checksum enable. + 1: indicate this packet needs to do UDP checksum + + cso[b29]: + Checksum offload. + 1: indicate this packet needs to do checksum + + USBDMANextVLD[b30]: + Used for USB-based chipset, reserved for other interfaces. + Used ONLY in USB bulk Aggregation, host driver info DMA current + frame is not he last frame in current Tx queue + + USBDMATxburst[b31]: + force DMA transmit frame from current selected endpoint +*/ +#ifdef RT_BIG_ENDIAN +typedef struct _TXINFO_OMAC { + UINT32 USBDMATxburst:1; + UINT32 USBDMANextVLD:1; + UINT32 cso:1; + UINT32 uso:1; +#ifdef USB_BULK_BUF_ALIGMENT + UINT32 bFragLasAlignmentsectiontRound:1; +#else + UINT32 SwUseLastRound:1; +#endif /* USB_BULK_BUF_ALIGMENT */ + UINT32 QSEL:2; + UINT32 WIV:1; + UINT32 TCPOffset:5; + UINT32 IPOffset:4; + UINT32 USBDMATxPktLen:15; +}TXINFO_OMAC; +#else +typedef struct _TXINFO_OMAC { + UINT32 USBDMATxPktLen:15; + UINT32 IPOffset:4; + UINT32 TCPOffset:5; + UINT32 WIV:1; + UINT32 QSEL:2; +#ifdef USB_BULK_BUF_ALIGMENT + UINT32 bFragLasAlignmentsectiontRound:1; +#else + UINT32 SwUseLastRound:1; +#endif /* USB_BULK_BUF_ALIGMENT */ + UINT32 uso:1; + UINT32 cso:1; + UINT32 USBDMANextVLD:1; + UINT32 USBDMATxburst:1; +}TXINFO_OMAC; +#endif /* RT_BIG_ENDIAN */ + + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _TXWI_OMAC { + /* Word 0 */ + UINT32 PHYMODE:2; + UINT32 iTxBF:1; /* iTxBF enable */ + UINT32 Sounding:1; /* Sounding enable */ + UINT32 eTxBF:1; /* eTxBF enable */ + UINT32 STBC:2; /*channel bandwidth 20MHz or 40 MHz */ + UINT32 ShortGI:1; + UINT32 BW:1; /*channel bandwidth 20MHz or 40 MHz */ + UINT32 MCS:7; + + UINT32 TXLUT:1; + UINT32 TXRPT:1; + UINT32 Autofallback:1; /* TX rate auto fallback disable */ + UINT32 NDPSndBW:1; /* NDP sounding BW */ + UINT32 NDPSndRate:2; /* 0 : MCS0, 1: MCS8, 2: MCS16, 3: reserved */ + UINT32 txop:2; + UINT32 MpduDensity:3; + UINT32 AMPDU:1; + + UINT32 TS:1; + UINT32 CFACK:1; + UINT32 MIMOps:1; /* the remote peer is in dynamic MIMO-PS mode */ + UINT32 FRAG:1; /* 1 to inform TKIP engine this is a fragment. */ + /* Word 1 */ + UINT32 PacketId:4; + UINT32 MPDUtotalByteCnt:12; + UINT32 wcid:8; + UINT32 BAWinSize:6; + UINT32 NSEQ:1; + UINT32 ACK:1; + /* Word 2 */ + UINT32 IV; + /* Word 3 */ + UINT32 EIV; + +} TXWI_OMAC; +#else +typedef struct GNU_PACKED _TXWI_OMAC { + /* Word 0 */ + /* ex: 00 03 00 40 means txop = 3, PHYMODE = 1 */ + UINT32 FRAG:1; /* 1 to inform TKIP engine this is a fragment. */ + UINT32 MIMOps:1; /* the remote peer is in dynamic MIMO-PS mode */ + UINT32 CFACK:1; + UINT32 TS:1; + + UINT32 AMPDU:1; + UINT32 MpduDensity:3; + UINT32 txop:2; /*FOR "THIS" frame. 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs only when previous frame exchange is successful. */ + UINT32 NDPSndRate:2; /* 0 : MCS0, 1: MCS8, 2: MCS16, 3: reserved */ + UINT32 NDPSndBW:1; /* NDP sounding BW */ + UINT32 Autofallback:1; /* TX rate auto fallback disable */ + UINT32 TXRPT:1; + UINT32 TXLUT:1; + + UINT32 MCS:7; + UINT32 BW:1; /*channel bandwidth 20MHz or 40 MHz */ + UINT32 ShortGI:1; + UINT32 STBC:2; /* 1: STBC support MCS =0-7, 2,3 : RESERVE */ + UINT32 eTxBF:1; /* eTxBF enable */ + UINT32 Sounding:1; /* Sounding enable */ + UINT32 iTxBF:1; /* iTxBF enable */ + UINT32 PHYMODE:2; + /* Word1 */ + /* ex: 1c ff 38 00 means ACK=0, BAWinSize=7, MPDUtotalByteCnt = 0x38 */ + UINT32 ACK:1; + UINT32 NSEQ:1; + UINT32 BAWinSize:6; + UINT32 wcid:8; + UINT32 MPDUtotalByteCnt:12; + UINT32 PacketId:4; + /*Word2 */ + UINT32 IV; + /*Word3 */ + UINT32 EIV; + +} TXWI_OMAC; +#endif + + + + +/* + RXWI wireless information format, in PBF. invisible in driver. +*/ +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _RXWI_OMAC{ + /* Word 0 */ + UINT32 tid:4; + UINT32 MPDUtotalByteCnt:12; + UINT32 UDF:3; + UINT32 bss_idx:3; + UINT32 key_idx:2; + UINT32 wcid:8; + + /* Word 1 */ + UINT32 phy_mode:2; /* 1: this RX frame is unicast to me */ + UINT32 iTxBF:1; /* iTxBF enable */ + UINT32 Sounding:1; /* Sounding enable */ + UINT32 eTxBF:1; /* eTxBF enable */ + UINT32 stbc:2; + UINT32 sgi:1; + UINT32 bw:1; + UINT32 mcs:7; + UINT32 SEQUENCE:12; + UINT32 FRAG:4; + + /* Word 2 */ + UINT32 rsv1:8; + UINT32 RSSI2:8; + UINT32 RSSI1:8; + UINT32 RSSI0:8; + + /* Word 3 */ + UINT32 FOFFSET:8; + UINT32 SNR2:8; + UINT32 SNR1:8; + UINT32 SNR0:8; + + +} RXWI_OMAC; +#else +typedef struct GNU_PACKED _RXWI_OMAC{ + /* Word 0 */ + UINT32 wcid:8; + UINT32 key_idx:2; + UINT32 bss_idx:3; + UINT32 UDF:3; + UINT32 MPDUtotalByteCnt:12; + UINT32 tid:4; + + /* Word 1 */ + UINT32 FRAG:4; + UINT32 SEQUENCE:12; + UINT32 mcs:7; + UINT32 bw:1; + UINT32 sgi:1; + UINT32 stbc:2; + UINT32 eTxBF:1; /* eTxBF enable */ + UINT32 Sounding:1; /* Sounding enable */ + UINT32 iTxBF:1; /* iTxBF enable */ + UINT32 phy_mode:2; /* 1: this RX frame is unicast to me */ + + /*Word2 */ + UINT32 RSSI0:8; + UINT32 RSSI1:8; + UINT32 RSSI2:8; + UINT32 rsv1:8; + + /*Word3 */ + UINT32 SNR0:8; + UINT32 SNR1:8; + UINT32 SNR2:8; + UINT32 FOFFSET:8; + + +} RXWI_OMAC; +#endif + + +typedef struct GNU_PACKED _OMAC_HW_RATE_CTRL_STRUCT{ +#ifdef RT_BIG_ENDIAN + UINT16 PHYMODE:2; + UINT16 iTxBF:1; + UINT16 Sounding:1; /* Sounding enable */ + UINT16 eTxBF:1; + UINT16 STBC:2; + UINT16 ShortGI:1; + UINT16 BW:1; /* channel bandwidth 20/40 */ + UINT16 MCS:7; +#else + UINT16 MCS:7; + UINT16 BW:1; + UINT16 ShortGI:1; + UINT16 STBC:2; + UINT16 eTxBF:1; + UINT16 Sounding:1; + UINT16 iTxBF:1; + UINT16 PHYMODE:2; +#endif /* RT_BIG_ENDIAN */ +}OMAC_HW_RATE_CTRL_STRUCT; + + +/* ================================================================================= */ +/* Register format */ +/* ================================================================================= */ + +#define GPIO_CTRL_CFG 0x0228 +#define RLT_MCU_CMD_CFG 0x022c + + +#define PAIRWISE_KEY_TABLE_BASE 0x4000 /* 32-byte * 256-entry = -byte */ +#define HW_KEY_ENTRY_SIZE 0x20 + +#define PAIRWISE_IVEIV_TABLE_BASE 0x6000 /* 8-byte * 256-entry = -byte */ +#define MAC_IVEIV_TABLE_BASE 0x6000 /* 8-byte * 256-entry = -byte */ +#define HW_IVEIV_ENTRY_SIZE 8 + +#define MAC_WCID_ATTRIBUTE_BASE 0x6800 /* 4-byte * 256-entry = -byte */ +#define HW_WCID_ATTRI_SIZE 4 + +#define SHARED_KEY_TABLE_BASE 0x6c00 /* 32-byte * 16-entry = 512-byte */ +#define SHARED_KEY_MODE_BASE 0x7000 /* 32-byte * 16-entry = 512-byte */ + +#define HW_SHARED_KEY_MODE_SIZE 4 + +#define SHARED_KEY_TABLE_BASE_EXT 0x7400 /* for BSS_IDX=8~15, 32-byte * 16-entry = 512-byte */ +#define SHARED_KEY_MODE_BASE_EXT 0x73F0 /* for BSS_IDX=8~15, 32-byte * 16-entry = 512-byte */ + +/* This resgiser is ONLY be supported for RT3883 or later. + It conflicted with BCN#0 offset of previous chipset. */ +#define WAPI_PN_TABLE_BASE 0x7800 +#define WAPI_PN_ENTRY_SIZE 8 + + +struct _RTMP_ADAPTER; +struct _RXINFO_STRUC; +union _RXWI_STRUC; +union _TXWI_STRUC; + +VOID dump_rtmp_rxwi(struct _RTMP_ADAPTER *pAd, union _RXWI_STRUC *pRxWI); +VOID dump_rtmp_txwi(struct _RTMP_ADAPTER *pAd, union _TXWI_STRUC *pTxWI); +VOID dump_rtmp_rxinfo(struct _RTMP_ADAPTER *pAd, struct _RXINFO_STRUC *pRxInfo); + +VOID rtmp_asic_init_txrx_ring(struct _RTMP_ADAPTER *pAd); + +#endif /* __RAL_OMAC_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac_pbf.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac_pbf.h new file mode 100644 index 000000000..8b6d9dc52 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac_pbf.h @@ -0,0 +1,102 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + ral_omac_pbf.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RAL_OMAC_PBF_H__ +#define __RAL_OMAC_PBF_H__ + + +#include "rtmp_type.h" + +/* ================================================================================= */ +/* Register format for PBF */ +/* ================================================================================= */ + + +#ifdef RT_BIG_ENDIAN +typedef union _RTMP_PBF_SYS_CTRL_STRUC { + struct { + UINT32 Reserved5:12; /* Reserved */ + UINT32 SHR_MSEL:1; /* Shared memory access selection */ + UINT32 PBF_MSEL:2; /* Packet buffer memory access selection */ + UINT32 HST_PM_SEL:1; /* The write selection of the host program RAM */ + UINT32 Reserved4:1; /* Reserved */ + UINT32 CAP_MODE:1; /* Packet buffer capture mode */ + UINT32 Reserved3:1; /* Reserved */ + UINT32 CLK_SEL:1; /* MAC/PBF clock source selection */ + UINT32 PBF_CLK_EN:1; /* PBF clock enable */ + UINT32 MAC_CLK_EN:1; /* MAC clock enable */ + UINT32 DMA_CLK_EN:1; /* DMA clock enable */ + UINT32 Reserved2:1; /* Reserved */ + UINT32 MCU_READY:1; /* MCU ready */ + UINT32 Reserved1:2; /* Reserved */ + UINT32 ASY_RESET:1; /* ASYNC interface reset */ + UINT32 PBF_RESET:1; /* PBF hardware reset */ + UINT32 MAC_RESET:1; /* MAC hardware reset */ + UINT32 DMA_RESET:1; /* DMA hardware reset */ + UINT32 MCU_RESET:1; /* MCU hardware reset */ + } field; + UINT32 word; +} RTMP_PBF_SYS_CTRL_STRUC; +#else +typedef union _RTMP_PBF_SYS_CTRL_STRUC { + struct { + UINT32 MCU_RESET:1; + UINT32 DMA_RESET:1; + UINT32 MAC_RESET:1; + UINT32 PBF_RESET:1; + UINT32 ASY_RESET:1; + UINT32 Reserved1:2; + UINT32 MCU_READY:1; + UINT32 Reserved2:1; + UINT32 DMA_CLK_EN:1; + UINT32 MAC_CLK_EN:1; + UINT32 PBF_CLK_EN:1; + UINT32 CLK_SEL:1; + UINT32 Reserved3:1; + UINT32 CAP_MODE:1; + UINT32 Reserved4:1; + UINT32 HST_PM_SEL:1; + UINT32 PBF_MSEL:2; + UINT32 SHR_MSEL:1; + UINT32 Reserved5:12; + }field; + UINT32 word; +} RTMP_PBF_SYS_CTRL_STRUC; +#endif + + +#define PBF_CFG 0x0408 +#define PBF_MAX_PCNT 0x040C +#define PBF_CAP_CTRL 0x0440 + +#define BCN_OFFSET0 0x042C +#define BCN_OFFSET1 0x0430 +#define TXRXQ_STA 0x0434 + +#endif /* __RAL_OMAC_PBF_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac_pci.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac_pci.h new file mode 100644 index 000000000..54e382e8d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac_pci.h @@ -0,0 +1,233 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + ral_omac_pci.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RAL_OMAC_PCI_H__ +#define __RAL_OMAC_PCI_H__ + + +#define RTMP_INT_RX_DLY (1<<0) /* bit 0 */ +#define RTMP_INT_TX_DLY (1<<1) /* bit 1 */ +#define RTMP_INT_RX_DONE (1<<2) /* bit 2 */ +#define RTMP_INT_AC0_DMA_DONE (1<<3) /* bit 3 */ +#define RTMP_INT_AC1_DMA_DONE (1<<4) /* bit 4 */ +#define RTMP_INT_AC2_DMA_DONE (1<<5) /* bit 5 */ +#define RTMP_INT_AC3_DMA_DONE (1<<6) /* bit 6 */ +#define RTMP_INT_HCCA_DMA_DONE (1<<7) /* bit 7 */ +#define RTMP_INT_MGMT_DONE (1<<8) /* bit 8 */ +#define RTMP_INT_MCU_CMD (1<<9) +#define RTMP_INT_ANY_COHERENT (1<<10) +#define RTMP_INT_TBTT (1<<11) +#define RTMP_INT_PRE_TBTT (1<<12) +#define RTMP_INT_FIFO_STAT (1<<13) +#define RTMP_INT_AUTO_WAKEUP (1<<14) +#define RTMP_INT_GPIO_TIMER (1<<15) +#define RTMP_INT_RX_COHERENT (1<<16) +#define RTMP_INT_TX_COHERENT (1<<17) +#define RTMP_INT_TONE_RADAR (1<<20) /* bit 20 */ + +#define RTMP_RxINT (RTMP_INT_RX_DLY | RTMP_INT_RX_DONE) /* 0x00000005 */ /* Delayed Rx or indivi rx */ +#define RTMP_TxDataInt (RTMP_INT_TX_DLY |\ + RTMP_INT_AC0_DMA_DONE | \ + RTMP_INT_AC1_DMA_DONE | \ + RTMP_INT_AC2_DMA_DONE | \ + RTMP_INT_AC3_DMA_DONE | \ + RTMP_INT_HCCA_DMA_DONE) /* 0x000000fa */ /* Delayed Tx or indivi tx */ +#define RTMP_TxMgmtInt (RTMP_INT_TX_DLY | RTMP_INT_MGMT_DONE) /* 0x00000102 */ /* Delayed Tx or indivi tx */ +#define RTMP_TxCoherent (RTMP_INT_TX_COHERENT) /* 0x00020000 */ /* tx coherent */ +#define RTMP_RxCoherent (RTMP_INT_RX_COHERENT) /* 0x00010000 */ /* rx coherent */ +#define RTMP_TxRxCoherent (RTMP_INT_ANY_COHERENT) /* 0x00000400 */ /* tx rx coherent */ +#define RTMP_McuCommand (RTMP_INT_MCU_CMD) /* 0x00000200 */ /* mcu */ +#define RTMP_PreTBTTInt (RTMP_INT_PRE_TBTT) /* 0x00001000 */ /* Pre-TBTT interrupt */ +#define RTMP_TBTTInt (RTMP_INT_TBTT) /* 0x00000800 */ /* TBTT interrupt */ +#define RTMP_GPTimeOutInt (RTMP_INT_GPIO_TIMER) /* 0x00008000 */ /* GPtimeout interrupt */ +#define RTMP_AutoWakeupInt (RTMP_INT_AUTO_WAKEUP) /* 0x00004000 */ /* AutoWakeupInt interrupt */ +#define RTMP_FifoStaFullInt (RTMP_INT_FIFO_STAT) /* 0x00002000 */ /* fifo statistics full interrupt */ +#define RTMP_RadarInt (RTMP_INT_TONE_RADAR) /* 0x00100000 */ + +#define RTMP_INT_RX RTMP_INT_RX_DONE + +#define RTMP_INT_AC0_DLY (RTMP_INT_AC0_DMA_DONE) /*| RTMP_INT_TX_DLY) */ +#define RTMP_INT_AC1_DLY (RTMP_INT_AC1_DMA_DONE) /*| RTMP_INT_TX_DLY) */ +#define RTMP_INT_AC2_DLY (RTMP_INT_AC2_DMA_DONE) /*| RTMP_INT_TX_DLY) */ +#define RTMP_INT_AC3_DLY (RTMP_INT_AC3_DMA_DONE) /*| RTMP_INT_TX_DLY) */ +#define RTMP_INT_HCCA_DLY (RTMP_INT_HCCA_DMA_DONE) /*| RTMP_INT_TX_DLY) */ +#define RTMP_INT_MGMT_DLY (RTMP_INT_MGMT_DONE) + + +#ifdef CARRIER_DETECTION_SUPPORT +#define RTMP_DELAYINTMASK (0x0003FFFB | (RTMP_RadarInt)) +#define RTMP_INTMASK (0x0003FFFB | (RTMP_RadarInt)) +#else +#define RTMP_DELAYINTMASK 0x0003FFFB +#define RTMP_INTMASK 0x0003FFFB +#endif /* CARRIER_DETECTION_SUPPORT */ + + +/* + INT_SOURCE_CSR: Interrupt source register. Write one to clear corresponding bit + Refer to INT_SOURCE_CSR(0x200) +*/ +#ifdef RT_BIG_ENDIAN +typedef union _RTMP_INT_SOURCE_CSR_STRUC { + struct { + UINT32 rsv21:11; + UINT32 RadarINT:1; + UINT32 rsv18:2; + UINT32 TxCoherent:1; + UINT32 RxCoherent:1; + UINT32 GPTimer:1; + UINT32 AutoWakeup:1;/*bit14 */ + UINT32 TXFifoStatusInt:1;/*FIFO Statistics is full, sw should read 0x171c */ + UINT32 PreTBTT:1; + UINT32 TBTTInt:1; + UINT32 RxTxCoherent:1; + UINT32 MCUCommandINT:1; + UINT32 MgmtDmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac0DmaDone:1; + UINT32 RxDone:1; + UINT32 TxDelayINT:1; /*delayed interrupt, not interrupt until several int or time limit hit */ + UINT32 RxDelayINT:1; /*dealyed interrupt */ + } field; + UINT32 word; +} RTMP_INT_SOURCE_CSR_STRUC; +#else +typedef union _RTMP_INT_SOURCE_CSR_STRUC { + struct { + UINT32 RxDelayINT:1; + UINT32 TxDelayINT:1; + UINT32 RxDone:1; + UINT32 Ac0DmaDone:1;/*4 */ + UINT32 Ac1DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 HccaDmaDone:1; /* bit7 */ + UINT32 MgmtDmaDone:1; + UINT32 MCUCommandINT:1;/*bit 9 */ + UINT32 RxTxCoherent:1; + UINT32 TBTTInt:1; + UINT32 PreTBTT:1; + UINT32 TXFifoStatusInt:1;/*FIFO Statistics is full, sw should read 0x171c */ + UINT32 AutoWakeup:1;/*bit14 */ + UINT32 GPTimer:1; + UINT32 RxCoherent:1;/*bit16 */ + UINT32 TxCoherent:1; + UINT32 rsv18:2; + UINT32 RadarINT:1; + UINT32 rsv21:11; + } field; + UINT32 word; +} RTMP_INT_SOURCE_CSR_STRUC; +#endif + + +/* + INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF + Refer to INT_MASK_CSR(0x204) +*/ +#ifdef RT_BIG_ENDIAN +typedef union _INT_MASK_CSR_STRUC { + struct { + UINT32 TxCoherent:1; + UINT32 RxCoherent:1; + UINT32 :9; + UINT32 RadarINT:1; + UINT32 rsv:10; + UINT32 MCUCommandINT:1; + UINT32 MgmtDmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac0DmaDone:1; + UINT32 RxDone:1; + UINT32 TxDelay:1; + UINT32 RXDelay_INT_MSK:1; + } field; + UINT32 word; +}INT_MASK_CSR_STRUC; +#else +typedef union _INT_MASK_CSR_STRUC { + struct { + UINT32 RXDelay_INT_MSK:1; + UINT32 TxDelay:1; + UINT32 RxDone:1; + UINT32 Ac0DmaDone:1; + UINT32 Ac1DmaDone:1; + UINT32 Ac2DmaDone:1; + UINT32 Ac3DmaDone:1; + UINT32 HccaDmaDone:1; + UINT32 MgmtDmaDone:1; + UINT32 MCUCommandINT:1; + UINT32 rsv:10; + UINT32 RadarINT:1; + UINT32 :9; + UINT32 RxCoherent:1; + UINT32 TxCoherent:1; + } field; + UINT32 word; +} INT_MASK_CSR_STRUC; +#endif + + +#define RINGREG_DIFF 0x10 +#define TX_BASE_PTR0 0x0230 /*AC_BK base address */ +#define TX_MAX_CNT0 0x0234 +#define TX_CTX_IDX0 0x0238 +#define TX_DTX_IDX0 0x023c +#define TX_BASE_PTR1 0x0240 /*AC_BE base address */ +#define TX_MAX_CNT1 0x0244 +#define TX_CTX_IDX1 0x0248 +#define TX_DTX_IDX1 0x024c +#define TX_BASE_PTR2 0x0250 /*AC_VI base address */ +#define TX_MAX_CNT2 0x0254 +#define TX_CTX_IDX2 0x0258 +#define TX_DTX_IDX2 0x025c +#define TX_BASE_PTR3 0x0260 /*AC_VO base address */ +#define TX_MAX_CNT3 0x0264 +#define TX_CTX_IDX3 0x0268 +#define TX_DTX_IDX3 0x026c +#define TX_BASE_PTR4 0x0270 /*HCCA base address */ +#define TX_MAX_CNT4 0x0274 +#define TX_CTX_IDX4 0x0278 +#define TX_DTX_IDX4 0x027c +#define TX_BASE_PTR5 0x0280 /*MGMT base address */ +#define TX_MAX_CNT5 0x0284 +#define TX_CTX_IDX5 0x0288 +#define TX_DTX_IDX5 0x028c +#define TX_MGMTMAX_CNT TX_MAX_CNT5 +#define TX_MGMTCTX_IDX TX_CTX_IDX5 +#define TX_MGMTDTX_IDX TX_DTX_IDX5 +#define RX_BASE_PTR 0x0290 /*RX base address */ +#define RX_MAX_CNT 0x0294 +#define RX_CRX_IDX 0x0298 +#define RX_DRX_IDX 0x029c + + +#endif /*__RAL_OMAC_PCI_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac_rf_ctrl.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac_rf_ctrl.h new file mode 100644 index 000000000..6d609db1f --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac_rf_ctrl.h @@ -0,0 +1,103 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + ral_omac_rf_ctrl.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RAL_OMAC_RF_CTRL_H__ +#define __RAL_OMAC_RF_CTRL_H__ + + + +/* ================================================================================= */ +/* Register format for RFCTRL */ +/* ================================================================================= */ + +#define OSC_CTRL 0x5a4 +#define PCIE_PHY_TX_ATTENUATION_CTRL 0x05C8 +#define INTERNAL_1 0x05C8 + +#ifdef RT_BIG_ENDIAN +typedef union _INTERNAL_1_STRUCT +{ + struct + { + UINT32 Reserve1:10; + UINT32 CSO_RX_IPV6_CHKSUM_EN:1; + UINT32 CSO_TX_IPV6_CHKSUM_EN:1; + UINT32 CSO_HW_PARSE_TCP:1; + UINT32 CSO_HW_PARSE_IP:1; + UINT32 CSO_RX_CHKSUM_EN:1; + UINT32 CSO_TX_CHKSUM_EN:1; + UINT32 CSO_TIMEOUT_VALUE:4; + UINT32 PCIE_PHY_TX_ATTEN_EN:1; + UINT32 PCIE_PHY_TX_ATTEN_VALUE:3; + UINT32 Reserve2:7; + UINT32 RF_ISOLATION_ENABLE:1; + } field; + + UINT32 word; +} INTERNAL_1_STRUCT; +#else +typedef union _INTERNAL_1_STRUCT { + struct + { + UINT32 RF_ISOLATION_ENABLE:1; + UINT32 Reserve2:7; + UINT32 PCIE_PHY_TX_ATTEN_VALUE:3; + UINT32 PCIE_PHY_TX_ATTEN_EN:1; + UINT32 CSO_TIMEOUT_VALUE:4; + UINT32 CSO_TX_CHKSUM_EN:1; + UINT32 CSO_RX_CHKSUM_EN:1; + UINT32 CSO_HW_PARSE_IP:1; + UINT32 CSO_HW_PARSE_TCP:1; + UINT32 CSO_TX_IPV6_CHKSUM_EN:1; + UINT32 CSO_RX_IPV6_CHKSUM_EN:1; + UINT32 Reserve1:10; + } field; + + UINT32 word; +} INTERNAL_1_STRUCT; +#endif + +#define RF_DBG1 0x050C +#define RF_CONTROL0 0x0518 +#define RTMP_RF_BYPASS0 0x051C +#define RF_CONTROL1 0x0520 +#define RF_BYPASS1 0x0524 +#define RF_CONTROL2 0x0528 +#define RF_BYPASS2 0x052C +#define RF_CONTROL3 0x0530 +#define RF_BYPASS3 0x0534 + +#define LDO_CFG0 0x05d4 +#define GPIO_SWITCH 0x05dc + +#define DEBUG_INDEX 0x05e8 + + + +#endif /* __RAL_OMAC_RF_CTRL_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac_usb.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac_usb.h new file mode 100644 index 000000000..bc664a84f --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/omac/ral_omac_usb.h @@ -0,0 +1,30 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + ral_omac_usb.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RAL_OMAC_USB_H__ +#define __RAL_OMAC_USB_H__ + +#endif /*__RAL_OMAC_USB_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/pbf.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/pbf.h new file mode 100644 index 000000000..74ae5f667 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/pbf.h @@ -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: + pbf.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __PBF_H__ +#define __PBF_H__ + + +#ifdef RLT_MAC +#include "mac/mac_ral/nmac/ral_nmac_pbf.h" +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC +#include "mac/mac_ral/omac/ral_omac_pbf.h" +#endif /* RTMP_MAC */ + + +/* ================================================================================= */ +/* Register format for PBF */ +/* ================================================================================= */ + + +#define US_CYC_CNT 0x02a4 +#ifdef RT_BIG_ENDIAN +typedef union _US_CYC_CNT_STRUC { + struct { + UINT32 rsv2:7; + UINT32 TestEn:1; + UINT32 TestSel:8; + UINT32 rsv1:7; + UINT32 MiscModeEn:1; + UINT32 UsCycCnt:8; + } field; + UINT32 word; +} US_CYC_CNT_STRUC; +#else +typedef union _US_CYC_CNT_STRUC { + struct { + UINT32 UsCycCnt:8; + UINT32 MiscModeEn:1; + UINT32 rsv1:7; + UINT32 TestSel:8; + UINT32 TestEn:1; + UINT32 rsv2:7; + } field; + UINT32 word; +} US_CYC_CNT_STRUC; +#endif + + +#define PBF_SYS_CTRL 0x0400 + + +#define PBF_CTRL 0x0410 +#define MCU_INT_STA 0x0414 +#define MCU_INT_ENA 0x0418 +#define TXRXQ_PCNT 0x0438 +#define PBF_DBG 0x043c + + +#endif /* __PBF_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/rf_ctrl.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/rf_ctrl.h new file mode 100644 index 000000000..621d4f072 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/rf_ctrl.h @@ -0,0 +1,151 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + rf_ctrl.h + + Abstract: + Ralink wireless chip RF related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RF_CTRL_H__ +#define __RF_CTRL_H__ + +#ifdef RTMP_MAC +#include "mac/mac_ral/omac/ral_omac_rf_ctrl.h" +#endif /* RTMP_MAC */ + +#ifdef RLT_MAC +#include "mac/mac_ral/nmac/ral_nmac_rf_ctrl.h" +#endif /* RLT_MAC */ + + +/* ================================================================================= */ +/* Register format for RFCTRL */ +/* ================================================================================= */ + +#define RF_CSR_CFG 0x500 + +#ifdef RLT_RF + +#define RF_BANK0 0 +#define RF_BANK1 1 +#define RF_BANK2 2 +#define RF_BANK3 3 +#define RF_BANK4 4 +#define RF_BANK5 5 +#define RF_BANK6 6 +#define RF_BANK7 7 +#define RF_BANK8 8 +#define RF_BANK9 9 +#define RF_BANK10 10 +#define RF_BANK11 11 +#define RF_BANK12 12 +#define RF_BANK13 13 +#define RF_BANK14 14 +#define RF_BANK15 15 + +#define MAX_RF_ID 127 +#define MAC_RF_BANK 7 + + +/* @!Release + RF_CSR_KICK:1 + Write - kick RF register read/write + 0: do nothing + 1: kick read/write process + Read - Polling RF register read/write + 0: idle + 1: busy + RF_CSR_RW:1 + 0: read 1: write + rsv:12 + RF_CSR_REG_ID:10 + RF register ID, 0 for R0, 1 for R1 and so on + Bits [17:15] 3 bits, indicates the bank number + Bits [14:08] 7 bits, indicates the register number + + RF_CSR_DATA:8 + DATA written to/read from RF +*/ +#endif /* RLT_RF */ + + +typedef union _RF_CSR_CFG_STRUC { +#ifdef RT_BIG_ENDIAN + struct { + UINT32 Rsvd18:14; /* Reserved */ + UINT32 RF_CSR_KICK:1; /* kick RF register read/write */ + UINT32 RF_CSR_WR:1; /* 0: read 1: write */ + UINT32 TESTCSR_RFACC_REGNUM:8; /* RF register ID */ + UINT32 RF_CSR_DATA:8; /* DATA */ + } non_bank; +#ifdef RLT_RF +#endif /* RLT_RF */ +#else + struct { + UINT32 RF_CSR_DATA:8; + UINT32 TESTCSR_RFACC_REGNUM:8; + UINT32 RF_CSR_WR:1; + UINT32 RF_CSR_KICK:1; + UINT32 Rsvd18:14; + } non_bank; +#ifdef RLT_RF +#endif /* RLT_RF */ +#endif /* RT_BIG_ENDIAN */ + UINT32 word; +}RF_CSR_CFG_STRUC; + + +#define RF_PA_MODE_CCK_1M (pAd->chipCap.PAModeCCK[0]) +#define RF_PA_MODE_CCK_2M (pAd->chipCap.PAModeCCK[1]) +#define RF_PA_MODE_CCK_5M (pAd->chipCap.PAModeCCK[2]) +#define RF_PA_MODE_CCK_11M (pAd->chipCap.PAModeCCK[3]) + +#define RF_PA_MODE_OFDM_6M (pAd->chipCap.PAModeOFDM[0]) +#define RF_PA_MODE_OFDM_9M (pAd->chipCap.PAModeOFDM[1]) +#define RF_PA_MODE_OFDM_12M (pAd->chipCap.PAModeOFDM[2]) +#define RF_PA_MODE_OFDM_18M (pAd->chipCap.PAModeOFDM[3]) +#define RF_PA_MODE_OFDM_24M (pAd->chipCap.PAModeOFDM[4]) +#define RF_PA_MODE_OFDM_36M (pAd->chipCap.PAModeOFDM[5]) +#define RF_PA_MODE_OFDM_48M (pAd->chipCap.PAModeOFDM[6]) +#define RF_PA_MODE_OFDM_54M (pAd->chipCap.PAModeOFDM[7]) + +#define RF_PA_MODE_HT_MCS0 (pAd->chipCap.PAModeHT[0]) +#define RF_PA_MODE_HT_MCS1 (pAd->chipCap.PAModeHT[1]) +#define RF_PA_MODE_HT_MCS2 (pAd->chipCap.PAModeHT[2]) +#define RF_PA_MODE_HT_MCS3 (pAd->chipCap.PAModeHT[3]) +#define RF_PA_MODE_HT_MCS4 (pAd->chipCap.PAModeHT[4]) +#define RF_PA_MODE_HT_MCS5 (pAd->chipCap.PAModeHT[5]) +#define RF_PA_MODE_HT_MCS6 (pAd->chipCap.PAModeHT[6]) +#define RF_PA_MODE_HT_MCS7 (pAd->chipCap.PAModeHT[7]) +#define RF_PA_MODE_HT_MCS8 (pAd->chipCap.PAModeHT[8]) +#define RF_PA_MODE_HT_MCS9 (pAd->chipCap.PAModeHT[9]) +#define RF_PA_MODE_HT_MCS10 (pAd->chipCap.PAModeHT[10]) +#define RF_PA_MODE_HT_MCS11 (pAd->chipCap.PAModeHT[11]) +#define RF_PA_MODE_HT_MCS12 (pAd->chipCap.PAModeHT[12]) +#define RF_PA_MODE_HT_MCS13 (pAd->chipCap.PAModeHT[13]) +#define RF_PA_MODE_HT_MCS14 (pAd->chipCap.PAModeHT[14]) +#define RF_PA_MODE_HT_MCS15 (pAd->chipCap.PAModeHT[15]) + + +#endif /* __RF_CTRL_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/rtmp_mac.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/rtmp_mac.h new file mode 100644 index 000000000..d5e1aa734 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mac/mac_ral/rtmp_mac.h @@ -0,0 +1,2466 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + rtmp_mac.h + + Abstract: + Ralink Wireless Chip MAC related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RTMP_MAC_H__ +#define __RTMP_MAC_H__ + + +#ifdef RLT_MAC +#include "mac/mac_ral/nmac/ral_nmac.h" +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC +#include "mac/mac_ral/omac/ral_omac.h" +#endif /* RTMP_MAC */ + +#include "mac/mac_ral/rtmp_mac.h" +#ifdef RTMP_MAC_PCI +#include "mac/mac_ral/mac_pci.h" +#endif /* RTMP_MAC_PCI */ + + +/* + TX / RX ring descriptor format + + TX: + PCI/RBUS_Descriptor + TXINFO + TXWI + 802.11 + + Rx: + PCI/RBUS/USB_Descripotr + (PCI/RBUS RXFCE_INFO) + (PCI/RBUS RXINFO) + RXWI + 802.11 + (USB RXINFO) + +*/ + +/* the first 24-byte in TXD is called TXINFO and will be DMAed to MAC block through TXFIFO. */ +/* MAC block use this TXINFO to control the transmission behavior of this frame. */ +#define FIFO_MGMT 0 +#define FIFO_HCCA 1 +#define FIFO_EDCA 2 + +#ifndef MT_MAC +typedef union GNU_PACKED _TXWI_STRUC { +#ifdef RLT_MAC + struct _TXWI_NMAC TXWI_N; +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + struct _TXWI_OMAC TXWI_O; +#endif /* RTMP_MAC */ + UINT32 word; +}TXWI_STRUC; + + +/* + RXWI wireless information format, in PBF. invisible in driver. +*/ +typedef union GNU_PACKED _RXWI_STRUC { +#ifdef RLT_MAC + struct _RXWI_NMAC RXWI_N; +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + struct _RXWI_OMAC RXWI_O; +#endif /* RTMP_MAC */ +}RXWI_STRUC; +#endif /* !MT_MAC */ + +typedef union GNU_PACKED _HW_RATE_CTRL_STRUCT_ { +#ifdef RLT_MAC + struct _NMAC_HW_RATE_CTRL_STRUCT RATE_CTRL_N; +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + struct _OMAC_HW_RATE_CTRL_STRUCT RATE_CTRL_O; +#endif /* RTMP_MAC */ + UINT16 word; +}HW_RATE_CTRL_STRUCT; + + +#define TSO_SIZE 0 + + +/* ================================================================================= */ +/* Register format */ +/* ================================================================================= */ + +#define ASIC_VERSION 0x0000 + + +/* + SCH/DMA registers - base address 0x0200 +*/ +#define WMM_AIFSN_CFG 0x0214 +#ifdef RT_BIG_ENDIAN +typedef union _AIFSN_CSR_STRUC{ + struct { + UINT32 Aifsn7:4; /* for AC_VO */ + UINT32 Aifsn6:4; /* for AC_VI */ + UINT32 Aifsn5:4; /* for AC_BK */ + UINT32 Aifsn4:4; /* for AC_BE */ + UINT32 Aifsn3:4; /* for AC_VO */ + UINT32 Aifsn2:4; /* for AC_VI */ + UINT32 Aifsn1:4; /* for AC_BK */ + UINT32 Aifsn0:4; /* for AC_BE */ + }field; + UINT32 word; +} AIFSN_CSR_STRUC; +#else +typedef union _AIFSN_CSR_STRUC { + struct { + UINT32 Aifsn0:4; + UINT32 Aifsn1:4; + UINT32 Aifsn2:4; + UINT32 Aifsn3:4; + UINT32 Aifsn4:4; + UINT32 Aifsn5:4; + UINT32 Aifsn6:4; + UINT32 Aifsn7:4; + } field; + UINT32 word; +} AIFSN_CSR_STRUC; +#endif + +/* CWMIN_CSR: CWmin for each EDCA AC */ +#define WMM_CWMIN_CFG 0x0218 +#ifdef RT_BIG_ENDIAN +typedef union _CWMIN_CSR_STRUC { + struct { + UINT32 Cwmin7:4; /* for AC_VO */ + UINT32 Cwmin6:4; /* for AC_VI */ + UINT32 Cwmin5:4; /* for AC_BK */ + UINT32 Cwmin4:4; /* for AC_BE */ + UINT32 Cwmin3:4; /* for AC_VO */ + UINT32 Cwmin2:4; /* for AC_VI */ + UINT32 Cwmin1:4; /* for AC_BK */ + UINT32 Cwmin0:4; /* for AC_BE */ + } field; + UINT32 word; +} CWMIN_CSR_STRUC; +#else +typedef union _CWMIN_CSR_STRUC { + struct { + UINT32 Cwmin0:4; + UINT32 Cwmin1:4; + UINT32 Cwmin2:4; + UINT32 Cwmin3:4; + UINT32 Cwmin4:4; + UINT32 Cwmin5:4; + UINT32 Cwmin6:4; + UINT32 Cwmin7:4; + } field; + UINT32 word; +} CWMIN_CSR_STRUC; +#endif + + +/* CWMAX_CSR: CWmin for each EDCA AC */ +#define WMM_CWMAX_CFG 0x021c +#ifdef RT_BIG_ENDIAN +typedef union _CWMAX_CSR_STRUC { + struct { + UINT32 Cwmax7:4; /* for AC_VO */ + UINT32 Cwmax6:4; /* for AC_VI */ + UINT32 Cwmax5:4; /* for AC_BK */ + UINT32 Cwmax4:4; /* for AC_BE */ + UINT32 Cwmax3:4; /* for AC_VO */ + UINT32 Cwmax2:4; /* for AC_VI */ + UINT32 Cwmax1:4; /* for AC_BK */ + UINT32 Cwmax0:4; /* for AC_BE */ + } field; + UINT32 word; +} CWMAX_CSR_STRUC; +#else +typedef union _CWMAX_CSR_STRUC { + struct { + UINT32 Cwmax0:4; + UINT32 Cwmax1:4; + UINT32 Cwmax2:4; + UINT32 Cwmax3:4; + UINT32 Cwmax4:4; + UINT32 Cwmax5:4; + UINT32 Cwmax6:4; + UINT32 Cwmax7:4; + } field; + UINT32 word; +} CWMAX_CSR_STRUC; +#endif + + +/* AC_TXOP_CSR0: AC_BK/AC_BE TXOP register */ +#define WMM_TXOP0_CFG 0x0220 +#ifdef RT_BIG_ENDIAN +typedef union _AC_TXOP_CSR0_STRUC { + struct { + UINT16 Ac1Txop; /* for AC_BE, in unit of 32us */ + UINT16 Ac0Txop; /* for AC_BK, in unit of 32us */ + } field; + UINT32 word; +} AC_TXOP_CSR0_STRUC; +#else +typedef union _AC_TXOP_CSR0_STRUC { + struct { + UINT16 Ac0Txop; + UINT16 Ac1Txop; + } field; + UINT32 word; +} AC_TXOP_CSR0_STRUC; +#endif + + +/* AC_TXOP_CSR1: AC_VO/AC_VI TXOP register */ +#define WMM_TXOP1_CFG 0x0224 +#ifdef RT_BIG_ENDIAN +typedef union _AC_TXOP_CSR1_STRUC { + struct { + UINT16 Ac3Txop; /* for AC_VO, in unit of 32us */ + UINT16 Ac2Txop; /* for AC_VI, in unit of 32us */ + } field; + UINT32 word; +} AC_TXOP_CSR1_STRUC; +#else +typedef union _AC_TXOP_CSR1_STRUC { + struct { + UINT16 Ac2Txop; + UINT16 Ac3Txop; + } field; + UINT32 word; +} AC_TXOP_CSR1_STRUC; +#endif + + +#define WMM_TXOP2_CFG 0x0228 +#define WMM_TXOP3_CFG 0x022c + +#define WMM_CTRL 0x0230 + + +/*================================================================================= */ +/* MAC registers */ +/*================================================================================= */ +/* 4.1 MAC SYSTEM configuration registers (offset:0x1000) */ +#define MAC_CSR0 0x1000 +#ifdef RT_BIG_ENDIAN +typedef union _ASIC_VER_ID_STRUC { + struct { + UINT16 ASICVer; /* version */ + UINT16 ASICRev; /* reversion */ + } field; + UINT32 word; +} ASIC_VER_ID_STRUC; +#else +typedef union _ASIC_VER_ID_STRUC { + struct { + UINT16 ASICRev; + UINT16 ASICVer; + } field; + UINT32 word; +} ASIC_VER_ID_STRUC; +#endif + +#define MAC_SYS_CTRL 0x1004 +#define PBF_LOOP_EN (1 << 5) +#define MAC_SYS_CTRL_TXEN (1 << 2) +#define MAC_SYS_CTRL_RXEN (1 << 3) + +#define MAC_ADDR_DW0 0x1008 +#define MAC_ADDR_DW1 0x100c + +/* MAC_CSR2: STA MAC register 0 */ +#ifdef RT_BIG_ENDIAN +typedef union _MAC_DW0_STRUC { + struct { + UINT8 Byte3; /* MAC address byte 3 */ + UINT8 Byte2; /* MAC address byte 2 */ + UINT8 Byte1; /* MAC address byte 1 */ + UINT8 Byte0; /* MAC address byte 0 */ + } field; + UINT32 word; +} MAC_DW0_STRUC; +#else +typedef union _MAC_DW0_STRUC { + struct { + UINT8 Byte0; + UINT8 Byte1; + UINT8 Byte2; + UINT8 Byte3; + } field; + UINT32 word; +} MAC_DW0_STRUC; +#endif + + +/* MAC_CSR3: STA MAC register 1 */ +#ifdef RT_BIG_ENDIAN +typedef union _MAC_DW1_STRUC { + struct { + UINT8 Rsvd1; + UINT8 U2MeMask; + UINT8 Byte5; /* MAC address byte 5 */ + UINT8 Byte4; /* MAC address byte 4 */ + } field; + UINT32 word; +} MAC_DW1_STRUC; +#else +typedef union _MAC_DW1_STRUC { + struct { + UINT8 Byte4; + UINT8 Byte5; + UINT8 U2MeMask; + UINT8 Rsvd1; + } field; + UINT32 word; +} MAC_DW1_STRUC; +#endif + +#define MAC_BSSID_DW0 0x1010 +#define MAC_BSSID_DW1 0x1014 +/* MAC_CSR5: BSSID register 1 */ +#ifdef RT_BIG_ENDIAN +typedef union _MAC_BSSID_DW1_STRUC { + struct { + UINT32 NMBssMode3:1; + UINT32 NMBssMode2:1; + UINT32 NMBssMode:1; + UINT32 MBssBcnNum:3; + UINT32 MBssMode:2; /* 0: one BSSID, 10: 4 BSSID, 01: 2 BSSID , 11: 8BSSID */ + UINT32 Byte5:8; /* BSSID byte 5 */ + UINT32 Byte4:8; /* BSSID byte 4 */ + } field; + UINT32 word; +} MAC_BSSID_DW1_STRUC; +#else +typedef union _MAC_BSSID_DW1_STRUC { + struct { + UINT32 Byte4:8; + UINT32 Byte5:8; + UINT32 MBssMode:2; + UINT32 MBssBcnNum:3; + UINT32 NMBssMode:1; + UINT32 NMBssMode2:1; + UINT32 NMBssMode3:1; + } field; + UINT32 word; +} MAC_BSSID_DW1_STRUC; +#endif + +/* rt2860b max 16k bytes. bit12:13 Maximum PSDU length (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16 */ +#define MAX_LEN_CFG 0x1018 + + +/* BBP_CSR_CFG: BBP serial control register */ +#define BBP_CSR_CFG 0x101c +#ifdef RT_BIG_ENDIAN +typedef union _BBP_CSR_CFG_STRUC { + struct { + UINT32 :12; + UINT32 BBP_RW_MODE:1; /* 0: use serial mode 1:parallel */ + UINT32 BBP_PAR_DUR:1; /* 0: 4 MAC clock cycles 1: 8 MAC clock cycles */ + UINT32 Busy:1; /* 1: ASIC is busy execute BBP programming. */ + UINT32 fRead:1; /* 0: Write BBP, 1: Read BBP */ + UINT32 RegNum:8; /* Selected BBP register */ + UINT32 Value:8; /* Register value to program into BBP */ + } field; + UINT32 word; +} BBP_CSR_CFG_STRUC; +#else +typedef union _BBP_CSR_CFG_STRUC { + struct { + UINT32 Value:8; + UINT32 RegNum:8; + UINT32 fRead:1; + UINT32 Busy:1; + UINT32 BBP_PAR_DUR:1; + UINT32 BBP_RW_MODE:1; + UINT32 :12; + } field; + UINT32 word; +} BBP_CSR_CFG_STRUC; +#endif + + +/* RF_CSR_CFG: RF control register */ +#define RF_CSR_CFG0 0x1020 +#ifdef RT_BIG_ENDIAN +typedef union _RF_CSR_CFG0_STRUC { + struct { + UINT32 Busy:1; /* 0: idle 1: 8busy */ + UINT32 Sel:1; /* 0:RF_LE0 activate 1:RF_LE1 activate */ + UINT32 StandbyMode:1; /* 0: high when stand by 1: low when standby */ + UINT32 bitwidth:5; /* Selected BBP register */ + UINT32 RegIdAndContent:24; /* Register value to program into BBP */ + } field; + UINT32 word; +} RF_CSR_CFG0_STRUC; +#else +typedef union _RF_CSR_CFG0_STRUC { + struct { + UINT32 RegIdAndContent:24; + UINT32 bitwidth:5; + UINT32 StandbyMode:1; + UINT32 Sel:1; + UINT32 Busy:1; + } field; + UINT32 word; +} RF_CSR_CFG0_STRUC; +#endif + + +#define RF_CSR_CFG1 0x1024 +#ifdef RT_BIG_ENDIAN +typedef union _RF_CSR_CFG1_STRUC { + struct { + UINT32 rsv:7; /* 0: idle 1: 8busy */ + UINT32 RFGap:5; /* Gap between BB_CONTROL_RF and RF_LE. 0: 3 system clock cycle (37.5usec) 1: 5 system clock cycle (62.5usec) */ + UINT32 RegIdAndContent:24; /* Register value to program into BBP */ + } field; + UINT32 word; +} RF_CSR_CFG1_STRUC; +#else +typedef union _RF_CSR_CFG1_STRUC { + struct { + UINT32 RegIdAndContent:24; + UINT32 RFGap:5; + UINT32 rsv:7; + } field; + UINT32 word; +} RF_CSR_CFG1_STRUC; +#endif + + +#define RF_CSR_CFG2 0x1028 +#ifdef RT_BIG_ENDIAN +typedef union _RF_CSR_CFG2_STRUC { + struct { + UINT32 rsv:8; /* 0: idle 1: 8busy */ + UINT32 RegIdAndContent:24; /* Register value to program into BBP */ + } field; + UINT32 word; +} RF_CSR_CFG2_STRUC; +#else +typedef union _RF_CSR_CFG2_STRUC { + struct { + UINT32 RegIdAndContent:24; + UINT32 rsv:8; + } field; + UINT32 word; +} RF_CSR_CFG2_STRUC; +#endif + + +#define LED_CFG 0x102c +#ifdef RT_BIG_ENDIAN +typedef union _LED_CFG_STRUC { + struct { + UINT32 :1; + UINT32 LedPolar:1; /* Led Polarity. 0: active low1: active high */ + UINT32 YLedMode:2; /* yellow Led Mode */ + UINT32 GLedMode:2; /* green Led Mode */ + UINT32 RLedMode:2; /* red Led Mode 0: off1: blinking upon TX2: periodic slow blinking3: always on */ + UINT32 rsv:2; + UINT32 SlowBlinkPeriod:6; /* slow blinking period. unit:1ms */ + UINT32 OffPeriod:8; /* blinking off period unit 1ms */ + UINT32 OnPeriod:8; /* blinking on period unit 1ms */ + } field; + UINT32 word; +} LED_CFG_STRUC; +#else +typedef union _LED_CFG_STRUC { + struct { + UINT32 OnPeriod:8; + UINT32 OffPeriod:8; + UINT32 SlowBlinkPeriod:6; + UINT32 rsv:2; + UINT32 RLedMode:2; + UINT32 GLedMode:2; + UINT32 YLedMode:2; + UINT32 LedPolar:1; + UINT32 :1; + } field; + UINT32 word; +} LED_CFG_STRUC; +#endif + + +#define AMPDU_MAX_LEN_20M1S 0x1030 +#define AMPDU_MAX_LEN_20M2S 0x1034 +#define AMPDU_MAX_LEN_20M1S_MCS0_7 0x1030 +#define AMPDU_MAX_LEN_20M1S_MCS8_9 0x1034 +#define AMPDU_MAX_LEN_40M1S 0x1038 +#define AMPDU_MAX_LEN_40M2S 0x103c +#define AMPDU_MAX_LEN 0x1040 + + +/* The number of the Tx chains */ +#define NUM_OF_TX_CHAIN 4 + +#define TX_CHAIN_ADDR0_L 0x1044 /* Stream mode MAC address registers */ +#define TX_CHAIN_ADDR0_H 0x1048 +#define TX_CHAIN_ADDR1_L 0x104C +#define TX_CHAIN_ADDR1_H 0x1050 +#define TX_CHAIN_ADDR2_L 0x1054 +#define TX_CHAIN_ADDR2_H 0x1058 +#define TX_CHAIN_ADDR3_L 0x105C +#define TX_CHAIN_ADDR3_H 0x1060 + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR0_L_STRUC { + struct { + UINT8 TxChainAddr0L_Byte3; /* Destination MAC address of Tx chain0 (byte 3) */ + UINT8 TxChainAddr0L_Byte2; /* Destination MAC address of Tx chain0 (byte 2) */ + UINT8 TxChainAddr0L_Byte1; /* Destination MAC address of Tx chain0 (byte 1) */ + UINT8 TxChainAddr0L_Byte0; /* Destination MAC address of Tx chain0 (byte 0) */ + } field; + UINT32 word; +} TX_CHAIN_ADDR0_L_STRUC; +#else +typedef union _TX_CHAIN_ADDR0_L_STRUC { + struct { + UINT8 TxChainAddr0L_Byte0; + UINT8 TxChainAddr0L_Byte1; + UINT8 TxChainAddr0L_Byte2; + UINT8 TxChainAddr0L_Byte3; + } field; + UINT32 word; +} TX_CHAIN_ADDR0_L_STRUC; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR0_H_STRUC { + struct { + UINT16 Reserved:12; /* Reserved */ + UINT16 TxChainSel0:4; /* Selection value of Tx chain0 */ + UINT8 TxChainAddr0H_Byte5; /* Destination MAC address of Tx chain0 (byte 5) */ + UINT8 TxChainAddr0H_Byte4; /* Destination MAC address of Tx chain0 (byte 4) */ + } field; + UINT32 word; +} TX_CHAIN_ADDR0_H_STRUC; +#else +typedef union _TX_CHAIN_ADDR0_H_STRUC { + struct { + UINT8 TxChainAddr0H_Byte4; /* Destination MAC address of Tx chain0 (byte 4) */ + UINT8 TxChainAddr0H_Byte5; /* Destination MAC address of Tx chain0 (byte 5) */ + UINT16 TxChainSel0:4; /* Selection value of Tx chain0 */ + UINT16 Reserved:12; /* Reserved */ + } field; + UINT32 word; +} TX_CHAIN_ADDR0_H_STRUC; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR1_L_STRUC { + struct { + UINT8 TxChainAddr1L_Byte3; /* Destination MAC address of Tx chain1 (byte 3) */ + UINT8 TxChainAddr1L_Byte2; /* Destination MAC address of Tx chain1 (byte 2) */ + UINT8 TxChainAddr1L_Byte1; /* Destination MAC address of Tx chain1 (byte 1) */ + UINT8 TxChainAddr1L_Byte0; /* Destination MAC address of Tx chain1 (byte 0) */ + } field; + UINT32 word; +} TX_CHAIN_ADDR1_L_STRUC, *PTX_CHAIN_ADDR1_L_STRUC; +#else +typedef union _TX_CHAIN_ADDR1_L_STRUC { + struct { + UINT8 TxChainAddr1L_Byte0; + UINT8 TxChainAddr1L_Byte1; + UINT8 TxChainAddr1L_Byte2; + UINT8 TxChainAddr1L_Byte3; + } field; + UINT32 word; +} TX_CHAIN_ADDR1_L_STRUC, *PTX_CHAIN_ADDR1_L_STRUC; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR1_H_STRUC { + struct { + UINT16 Reserved:12; /* Reserved */ + UINT16 TxChainSel0:4; /* Selection value of Tx chain0 */ + UINT8 TxChainAddr1H_Byte5; /* Destination MAC address of Tx chain1 (byte 5) */ + UINT8 TxChainAddr1H_Byte4; /* Destination MAC address of Tx chain1 (byte 4) */ + } field; + UINT32 word; +} TX_CHAIN_ADDR1_H_STRUC ; +#else +typedef union _TX_CHAIN_ADDR1_H_STRUC { + struct { + UINT8 TxChainAddr1H_Byte4; + UINT8 TxChainAddr1H_Byte5; + UINT16 TxChainSel0:4; + UINT16 Reserved:12; + } field; + UINT32 word; +} TX_CHAIN_ADDR1_H_STRUC ; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR2_L_STRUC { + struct { + UINT8 TxChainAddr2L_Byte3; /* Destination MAC address of Tx chain2 (byte 3) */ + UINT8 TxChainAddr2L_Byte2; /* Destination MAC address of Tx chain2 (byte 2) */ + UINT8 TxChainAddr2L_Byte1; /* Destination MAC address of Tx chain2 (byte 1) */ + UINT8 TxChainAddr2L_Byte0; /* Destination MAC address of Tx chain2 (byte 0) */ + } field; + UINT32 word; +} TX_CHAIN_ADDR2_L_STRUC; +#else +typedef union _TX_CHAIN_ADDR2_L_STRUC { + struct { + UINT8 TxChainAddr2L_Byte0; + UINT8 TxChainAddr2L_Byte1; + UINT8 TxChainAddr2L_Byte2; + UINT8 TxChainAddr2L_Byte3; + } field; + UINT32 word; +} TX_CHAIN_ADDR2_L_STRUC; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR2_H_STRUC { + struct { + UINT16 Reserved:12; /* Reserved */ + UINT16 TxChainSel0:4; /* Selection value of Tx chain0 */ + UINT8 TxChainAddr2H_Byte5; /* Destination MAC address of Tx chain2 (byte 5) */ + UINT8 TxChainAddr2H_Byte4; /* Destination MAC address of Tx chain2 (byte 4) */ + } field; + UINT32 word; +} TX_CHAIN_ADDR2_H_STRUC; +#else +typedef union _TX_CHAIN_ADDR2_H_STRUC { + struct { + UINT8 TxChainAddr2H_Byte4; + UINT8 TxChainAddr2H_Byte5; + UINT16 TxChainSel0:4; + UINT16 Reserved:12; + } field; + UINT32 word; +} TX_CHAIN_ADDR2_H_STRUC; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR3_L_STRUC { + struct { + UINT8 TxChainAddr3L_Byte3; /* Destination MAC address of Tx chain3 (byte 3) */ + UINT8 TxChainAddr3L_Byte2; /* Destination MAC address of Tx chain3 (byte 2) */ + UINT8 TxChainAddr3L_Byte1; /* Destination MAC address of Tx chain3 (byte 1) */ + UINT8 TxChainAddr3L_Byte0; /* Destination MAC address of Tx chain3 (byte 0) */ + } field; + UINT32 word; +} TX_CHAIN_ADDR3_L_STRUC, *PTX_CHAIN_ADDR3_L_STRUC; +#else +typedef union _TX_CHAIN_ADDR3_L_STRUC { + struct { + UINT8 TxChainAddr3L_Byte0; + UINT8 TxChainAddr3L_Byte1; + UINT8 TxChainAddr3L_Byte2; + UINT8 TxChainAddr3L_Byte3; + } field; + UINT32 word; +} TX_CHAIN_ADDR3_L_STRUC, *PTX_CHAIN_ADDR3_L_STRUC; +#endif + + +#ifdef RT_BIG_ENDIAN +typedef union _TX_CHAIN_ADDR3_H_STRUC { + struct { + UINT16 Reserved:12; /* Reserved */ + UINT16 TxChainSel0:4; /* Selection value of Tx chain0 */ + UINT8 TxChainAddr3H_Byte5; /* Destination MAC address of Tx chain3 (byte 5) */ + UINT8 TxChainAddr3H_Byte4; /* Destination MAC address of Tx chain3 (byte 4) */ + } field; + UINT32 word; +} TX_CHAIN_ADDR3_H_STRUC, *PTX_CHAIN_ADDR3_H_STRUC; +#else +typedef union _TX_CHAIN_ADDR3_H_STRUC { + struct { + UINT8 TxChainAddr3H_Byte4; + UINT8 TxChainAddr3H_Byte5; + UINT16 TxChainSel0:4; + UINT16 Reserved:12; + } field; + UINT32 word; +} TX_CHAIN_ADDR3_H_STRUC; +#endif + +#define TX_BCN_BYPASS_MASK 0x108C +typedef union _BCN_BYPASS_MASK_STRUC { + struct { + UINT32 BeaconDropMask:16; + } field; + UINT32 word; +} BCN_BYPASS_MASK_STRUC; + +/* 4.2 MAC TIMING configuration registers (offset:0x1100) */ +#define XIFS_TIME_CFG 0x1100 +#define XIFS_TIME_OFDM_SIFS_MASK (0xff << 8) +#define XIFS_TIME_OFDM_SIFS(p) (((p) & 0xff) << 8) +#ifdef RT_BIG_ENDIAN +typedef union _IFS_SLOT_CFG_STRUC { + struct { + UINT32 rsv:2; + UINT32 BBRxendEnable:1; /* reference RXEND signal to begin XIFS defer */ + UINT32 EIFS:9; /* unit 1us */ + UINT32 OfdmXifsTime:4; /*OFDM SIFS. unit 1us. Applied after OFDM RX when MAC doesn't reference BBP signal BBRXEND */ + UINT32 OfdmSifsTime:8; /* unit 1us. Applied after OFDM RX/TX */ + UINT32 CckmSifsTime:8; /* unit 1us. Applied after CCK RX/TX */ + } field; + UINT32 word; +} IFS_SLOT_CFG_STRUC; +#else +typedef union _IFS_SLOT_CFG_STRUC { + struct { + UINT32 CckmSifsTime:8; + UINT32 OfdmSifsTime:8; + UINT32 OfdmXifsTime:4; + UINT32 EIFS:9; + UINT32 BBRxendEnable:1; + UINT32 rsv:2; + } field; + UINT32 word; +} IFS_SLOT_CFG_STRUC; +#endif + +#define BKOFF_SLOT_CFG 0x1104 +#define BKOFF_SLOT_CFG_CC_DELAY_TIME_MASK (0x0f << 8) +#define BKOFF_SLOT_CFG_CC_DELAY_TIME(p) (((p) & 0x0f) << 8) + +#define NAV_TIME_CFG 0x1108 +#define CH_TIME_CFG 0x110C +#define PBF_LIFE_TIMER 0x1110 /*TX/RX MPDU timestamp timer (free run)Unit: 1us */ + + +/* BCN_TIME_CFG : Synchronization control register */ +#define BCN_TIME_CFG 0x1114 +#ifdef RT_BIG_ENDIAN +typedef union _BCN_TIME_CFG_STRUC { + struct { + UINT32 TxTimestampCompensate:8; + UINT32 :3; + UINT32 bBeaconGen:1; /* Enable beacon generator */ + UINT32 bTBTTEnable:1; + UINT32 TsfSyncMode:2; /* Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode */ + UINT32 bTsfTicking:1; /* Enable TSF auto counting */ + UINT32 BeaconInterval:16; /* in unit of 1/16 TU */ + } field; + UINT32 word; +} BCN_TIME_CFG_STRUC; +#else +typedef union _BCN_TIME_CFG_STRUC { + struct { + UINT32 BeaconInterval:16; + UINT32 bTsfTicking:1; + UINT32 TsfSyncMode:2; + UINT32 bTBTTEnable:1; + UINT32 bBeaconGen:1; + UINT32 :3; + UINT32 TxTimestampCompensate:8; + } field; + UINT32 word; +} BCN_TIME_CFG_STRUC; +#endif + + +#define TBTT_SYNC_CFG 0x1118 +#define TSF_TIMER_DW0 0x111c /* Local TSF timer lsb 32 bits. Read-only */ +#define TSF_TIMER_DW1 0x1120 /* msb 32 bits. Read-only. */ +#define TBTT_TIMER 0x1124 /* TImer remains till next TBTT. Read-only */ +#define INT_TIMER_CFG 0x1128 +#define INT_TIMER_EN 0x112c /* GP-timer and pre-tbtt Int enable */ +#define INT_TIMER_EN_PRE_TBTT 0x1 +#define INT_TIMER_EN_GP_TIMER 0x2 + +#define CH_IDLE_STA 0x1130 /* channel idle time */ +#define CH_BUSY_STA 0x1134 /* channle busy time */ +#define CH_BUSY_STA_SEC 0x1138 /* channel busy time for secondary channel */ + + +/* 4.2 MAC POWER configuration registers (offset:0x1200) */ +#define MAC_STATUS_CFG 0x1200 +#define PWR_PIN_CFG 0x1204 + + +/* AUTO_WAKEUP_CFG: Manual power control / status register */ +#define AUTO_WAKEUP_CFG 0x1208 +#ifdef RT_BIG_ENDIAN +typedef union _AUTO_WAKEUP_STRUC { + struct { + UINT32 :16; + UINT32 EnableAutoWakeup:1; /* 0:sleep, 1:awake */ + UINT32 NumofSleepingTbtt:7; /* ForceWake has high privilege than PutToSleep when both set */ + UINT32 AutoLeadTime:8; + } field; + UINT32 word; +} AUTO_WAKEUP_STRUC; +#else +typedef union _AUTO_WAKEUP_STRUC { + struct { + UINT32 AutoLeadTime:8; + UINT32 NumofSleepingTbtt:7; + UINT32 EnableAutoWakeup:1; + UINT32 :16; + } field; + UINT32 word; +} AUTO_WAKEUP_STRUC; +#endif + +#define AUX_CLK_CFG 0x120C +#define MIMO_PS_CFG 0x1210 + + + +/* 4.3 MAC TX configuration registers (offset:0x1300) */ +#define EDCA_AC0_CFG 0x1300 +#define EDCA_AC1_CFG 0x1304 +#define EDCA_AC2_CFG 0x1308 +#define EDCA_AC3_CFG 0x130c +#ifdef RT_BIG_ENDIAN +typedef union _EDCA_AC_CFG_STRUC { + struct { + UINT32 :12; + UINT32 Cwmax:4; /* unit power of 2 */ + UINT32 Cwmin:4; + UINT32 Aifsn:4; /* # of slot time */ + UINT32 AcTxop:8; /* in unit of 32us */ + } field; + UINT32 word; +} EDCA_AC_CFG_STRUC; +#else +typedef union _EDCA_AC_CFG_STRUC { + struct { + UINT32 AcTxop:8; + UINT32 Aifsn:4; + UINT32 Cwmin:4; + UINT32 Cwmax:4; + UINT32 :12; + } field; + UINT32 word; +} EDCA_AC_CFG_STRUC; +#endif + +#define EDCA_TID_AC_MAP 0x1310 + + +/* Default Tx power */ +#define DEFAULT_TX_POWER 0x6 + +#define TX_PWR_CFG_0 0x1314 +#define TX_PWR_CCK_1_2_MASK (0x3f) +#define TX_PWR_CCK_1_2(p) (((p) & 0x3f)) +#define TX_PWR_CCK_5_11_MASK (0x3f << 8) +#define TX_PWR_CCK_5_11(p) (((p) & 0x3f) << 8) +#define TX_PWR_OFDM_6_9_MASK (0x3f << 16) +#define TX_PWR_OFDM_6_9(p) (((p) & 0x3f) << 16) +#define TX_PWR_OFDM_12_18_MASK (0x3f << 24) +#define TX_PWR_OFDM_12_18(p) (((p) & 0x3f) << 24) + +#define TX_PWR_CFG_0_EXT 0x1390 + +#define TX_PWR_CFG_1 0x1318 +#define TX_PWR_OFDM_24_36_MASK (0x3f) +#define TX_PWR_OFDM_24_36(p) (((p) & 0x3f)) +#define TX_PWR_OFDM_48_MASK (0x3f << 8) +#define TX_PWR_OFDM_48(p) (((p) & 0x3f) << 8) +#define TX_PWR_HT_VHT_1SS_MCS_0_1_MASK (0x3f << 16) +#define TX_PWR_HT_VHT_1SS_MCS_0_1(p) (((p) & 0x3f) << 16) +#define TX_PWR_HT_VHT_1SS_MCS_2_3_MASK (0x3f << 24) +#define TX_PWR_HT_VHT_1SS_MCS_2_3(p) (((p) & 0x3f) << 16) + +#define TX_PWR_CFG_1_EXT 0x1394 + +#define TX_PWR_CFG_2 0x131C +#define TX_PWR_HT_VHT_1SS_MCS_4_5_MASK (0x3f) +#define TX_PWR_HT_VHT_1SS_MCS_4_5(p) (((p) & 0x3f)) +#define TX_PWR_HT_VHT_1SS_MCS_6_MASK (0x3f << 8) +#define TX_PWR_HT_VHT_1SS_MCS_6(p) (((p) & 0x3f) << 8) +#define TX_PWR_HT_MCS_8_9_VHT_2SS_0_1_MASK (0x3f << 16) +#define TX_PWR_HT_MCS_8_9_VHT_2SS_0_1(p) (((p) & 0x3f) << 16) +#define TX_PWR_HT_MCS_10_11_VHT_2SS_MCS_2_3_MASK (0x3f << 24) +#define TX_PWR_HT_MCS_10_11_VHT_2SS_MCS_2_3(p) (((p) & 0x3f) << 24) + +#define TX_PWR_CFG_2_EXT 0x1398 + +#define TX_PWR_CFG_3 0x1320 +#define TX_PWR_HT_MCS_12_13_VHT_2SS_MCS_4_5_MASK (0x3f) +#define TX_PWR_HT_MCS_12_13_VHT_2SS_MCS_4_5(p) (((p) & 0x3f)) +#define TX_PWR_HT_MCS_14_VHT_2SS_MCS_6_MASK (0x3f << 8) +#define TX_PWR_HT_MCS_14_VHT_2SS_MCS_6(p) (((p) & 0x3f) << 8) +#define TX_PWR_HT_VHT_STBC_MCS_0_1_MASK (0x3f << 16) +#define TX_PWR_HT_VHT_STBC_MCS_0_1(p) (((p) & 0x3f) << 16) +#define TX_PWR_HT_VHT_STBC_MCS_2_3_MASK (0x3f << 24) +#define TX_PWR_HT_VHT_STBC_MCS_2_3(p) (((p) & 0x3f) << 24) + +#define GF20_PORT_CFG 0x1374 +#define TX_PWR_CFG_3_EXT 0x139C + +#define TX_PWR_CFG_4 0x1324 +#define TX_PWR_HT_VHT_STBC_MCS_4_5_MASK (0x3f) +#define TX_PWR_HT_VHT_STBC_MCS_4_5(p) (((p) & 0x3f)) +#define TX_PWR_HT_VHT_STBC_MCS_6_MASK (0x3f << 8) +#define TX_PWR_HT_VHT_STBC_MCS_6(p) (((p) & 0x3f) << 8) + +#define TX_PWR_CFG_0_EXT 0x1390 +#define TX_PWR_CFG_1_EXT 0x1394 +#define TX_PWR_CFG_2_EXT 0x1398 +#define TX_PWR_CFG_3_EXT 0x139C +#define TX_PWR_CFG_4_EXT 0x13A0 + +#define TX_PWR_CFG_5 0x1384 +#define TX_PWR_CFG_6 0x1388 + +#define TX_PWR_CFG_7 0x13D4 +#define TX_PWR_OFDM_54_MASK (0x3f) +#define TX_PWR_OFDM_54(p) (((p) & 0x3f)) +#define TX_PWR_VHT_2SS_MCS_8_MASK (0x3f << 8) +#define TX_PWR_VHT_2SS_MCS_8(p) (((p) & 0x3f) << 8) +#define TX_PWR_HT_MCS_7_VHT_1SS_MCS_7_MASK (0x3f << 16) +#define TX_PWR_HT_MCS_7_VHT_1SS_MCS_7(p) (((p) & 0x3f) << 16) +#define TX_PWR_VHT_2SS_MCS_9_MASK (0X3f << 24) +#define TX_PWR_VHT_2SS_MCS_9(p) (((p) & 0x3f) << 24) + +#define TX_PWR_CFG_8 0x13D8 +#define TX_PWR_HT_MCS_15_VHT_2SS_MCS7_MASK (0x3f) +#define TX_PWR_HT_MCS_15_VHT_2SS_MCS7(p) (((p) & 0x3f)) +#define TX_PWR_VHT_1SS_MCS_8_MASK (0x3f << 16) +#define TX_PWR_VHT_1SS_MCS_8(p) (((p) & 0x3f) << 16) +#define TX_PWR_VHT_1SS_MCS_9_MASK (0X3f << 24) +#define TX_PWR_VHT_1SS_MCS_9(p) (((p) & 0x3f) << 24) + +#define TX_PWR_CFG_9 0x13DC +#define TX_PWR_HT_VHT_STBC_MCS_7_MASK (0x3f) +#define TX_PWR_HT_VHT_STBC_MCS_7(p) (((p) & 0x3f)) +#define TX_PWR_VHT_STBC_MCS_8_MASK (0x3f << 16) +#define TX_PWR_VHT_STBC_MCS_8(p) (((p) & 0x3f) << 16) +#define TX_PWR_VHT_STBC_MCS_9_MASK (0x3f << 24) +#define TX_PWR_VHT_STBC_MCS_9(p) (((p) & 0x3f) << 24) + +#ifdef RT_BIG_ENDIAN +typedef union _TX_PWR_CFG_STRUC { + struct { + UINT32 Byte3:8; + UINT32 Byte2:8; + UINT32 Byte1:8; + UINT32 Byte0:8; + } field; + UINT32 word; +} TX_PWR_CFG_STRUC; +#else +typedef union _TX_PWR_CFG_STRUC { + struct { + UINT32 Byte0:8; + UINT32 Byte1:8; + UINT32 Byte2:8; + UINT32 Byte3:8; + } field; + UINT32 word; +} TX_PWR_CFG_STRUC; +#endif + + +#define TX_PIN_CFG 0x1328 +#define TX_BAND_CFG 0x132c /* 0x1 use upper 20MHz. 0 juse lower 20MHz */ +#define TX_SW_CFG0 0x1330 +#define TX_SW_CFG1 0x1334 +#define TX_SW_CFG2 0x1338 + + +#define TXOP_THRES_CFG 0x133c +#ifdef RT_BIG_ENDIAN +typedef union _TXOP_THRESHOLD_CFG_STRUC { + struct { + UINT32 TXOP_REM_THRES:8; /* Remaining TXOP threshold (unit: 32us) */ + UINT32 CF_END_THRES:8; /* CF-END threshold (unit: 32us) */ + UINT32 RDG_IN_THRES:8; /* Rx RDG threshold (unit: 32us) */ + UINT32 RDG_OUT_THRES:8; /* Tx RDG threshold (unit: 32us) */ + } field; + UINT32 word; +} TXOP_THRESHOLD_CFG_STRUC; +#else +typedef union _TXOP_THRESHOLD_CFG_STRUC { + struct { + UINT32 RDG_OUT_THRES:8; + UINT32 RDG_IN_THRES:8; + UINT32 CF_END_THRES:8; + UINT32 TXOP_REM_THRES:8; + } field; + UINT32 word; +} TXOP_THRESHOLD_CFG_STRUC; +#endif + +#define TXOP_CTRL_CFG 0x1340 + + +#define TX_RTS_CFG 0x1344 +#ifdef RT_BIG_ENDIAN +typedef union _TX_RTS_CFG_STRUC { + struct { + UINT32 rsv:7; + UINT32 RtsFbkEn:1; /* enable rts rate fallback */ + UINT32 RtsThres:16; /* unit:byte */ + UINT32 AutoRtsRetryLimit:8; + } field; + UINT32 word; +} TX_RTS_CFG_STRUC; +#else +typedef union _TX_RTS_CFG_STRUC { + struct { + UINT32 AutoRtsRetryLimit:8; + UINT32 RtsThres:16; + UINT32 RtsFbkEn:1; + UINT32 rsv:7; + } field; + UINT32 word; +} TX_RTS_CFG_STRUC; +#endif + + + +#define TX_TXBF_CFG_0 0x138c +#define TX_TXBF_CFG_1 0x13A4 +#define TX_TXBF_CFG_2 0x13A8 +#define TX_TXBF_CFG_3 0x13AC +typedef union _TX_TXBF_CFG_0_STRUC { + struct { +#ifdef RT_BIG_ENDIAN + UINT32 EtxbfFbkRate:16; + UINT32 EtxbfFbkEn:1; + UINT32 EtxbfFbkSeqEn:1; + UINT32 EtxbfFbkCoef:2; + UINT32 EtxbfFbkCode:2; + UINT32 EtxbfFbkNg:2; + UINT32 CsdBypass:1; + UINT32 EtxbfForce:1; + UINT32 EtxbfEnable:1; + UINT32 AutoTxbfEn:3; + UINT32 ItxbfForce:1; + UINT32 ItxbfEn:1; +#else + UINT32 ItxbfEn:1; + UINT32 ItxbfForce:1; + UINT32 AutoTxbfEn:3; + UINT32 EtxbfEnable:1; + UINT32 EtxbfForce:1; + UINT32 CsdBypass:1; + UINT32 EtxbfFbkNg:2; + UINT32 EtxbfFbkCode:2; + UINT32 EtxbfFbkCoef:2; + UINT32 EtxbfFbkSeqEn:1; + UINT32 EtxbfFbkEn:1; + UINT32 EtxbfFbkRate:16; +#endif + } field; + UINT32 word; +} TX_TXBF_CFG_0_STRUC; + + +#define TX_TIMEOUT_CFG 0x1348 +#ifdef RT_BIG_ENDIAN +typedef union _TX_TIMEOUT_CFG_STRUC { + struct { + UINT32 rsv2:8; + UINT32 TxopTimeout:8; /*TXOP timeout value for TXOP truncation. It is recommended that (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) */ + UINT32 RxAckTimeout:8; /* unit:slot. Used for TX precedure */ + UINT32 MpduLifeTime:4; /* expiration time = 2^(9+MPDU LIFE TIME) us */ + UINT32 rsv:4; + } field; + UINT32 word; +} TX_TIMEOUT_CFG_STRUC; +#else +typedef union _TX_TIMEOUT_CFG_STRUC { + struct { + UINT32 rsv:4; + UINT32 MpduLifeTime:4; + UINT32 RxAckTimeout:8; + UINT32 TxopTimeout:8; + UINT32 rsv2:8; + } field; + UINT32 word; +} TX_TIMEOUT_CFG_STRUC; +#endif + + +#define TX_RTY_CFG 0x134c +#define TX_RTY_CFG_RTY_LIMIT_SHORT 0x1 +#define TX_RTY_CFG_RTY_LIMIT_LONG 0x2 + +#ifdef RT_BIG_ENDIAN +typedef union _TX_RTY_CFG_STRUC { + struct { + UINT32 rsv:1; + UINT32 TxautoFBEnable:1; /* Tx retry PHY rate auto fallback enable */ + UINT32 AggRtyMode:1; /* Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer */ + UINT32 NonAggRtyMode:1; /* Non-Aggregate MPDU retry mode. 0:expired by retry limit, 1: expired by mpdu life timer */ + UINT32 LongRtyThre:12; /* Long retry threshoold */ + UINT32 LongRtyLimit:8; /*long retry limit */ + UINT32 ShortRtyLimit:8; /* short retry limit */ + } field; + UINT32 word; +} TX_RTY_CFG_STRUC; +#else +typedef union _TX_RTY_CFG_STRUC { + struct { + UINT32 ShortRtyLimit:8; + UINT32 LongRtyLimit:8; + UINT32 LongRtyThre:12; + UINT32 NonAggRtyMode:1; + UINT32 AggRtyMode:1; + UINT32 TxautoFBEnable:1; + UINT32 rsv:1; + } field; + UINT32 word; +} TX_RTY_CFG_STRUC; +#endif + + +#define TX_LINK_CFG 0x1350 +#ifdef RT_BIG_ENDIAN +typedef union _TX_LINK_CFG_STRUC { + struct { + UINT32 RemotMFS:8; /*remote MCS feedback sequence number */ + UINT32 RemotMFB:8; /* remote MCS feedback */ + UINT32 rsv:3; /* */ + UINT32 TxCFAckEn:1; /* Piggyback CF-ACK enable */ + UINT32 TxRDGEn:1; /* RDG TX enable */ + UINT32 TxMRQEn:1; /* MCS request TX enable */ + UINT32 RemoteUMFSEnable:1; /* remote unsolicit MFB enable. 0: not apply remote remote unsolicit (MFS=7) */ + UINT32 MFBEnable:1; /* TX apply remote MFB 1:enable */ + UINT32 RemoteMFBLifeTime:8; /*remote MFB life time. unit : 32us */ + } field; + UINT32 word; +} TX_LINK_CFG_STRUC; +#else +typedef union _TX_LINK_CFG_STRUC { + struct { + UINT32 RemoteMFBLifeTime:8; + UINT32 MFBEnable:1; + UINT32 RemoteUMFSEnable:1; + UINT32 TxMRQEn:1; + UINT32 TxRDGEn:1; + UINT32 TxCFAckEn:1; + UINT32 rsv:3; + UINT32 RemotMFB:8; + UINT32 RemotMFS:8; + } field; + UINT32 word; +} TX_LINK_CFG_STRUC; +#endif + + +#define HT_FBK_CFG0 0x1354 +#ifdef RT_BIG_ENDIAN +typedef union _HT_FBK_CFG0_STRUC { + struct { + UINT32 HTMCS7FBK:4; + UINT32 HTMCS6FBK:4; + UINT32 HTMCS5FBK:4; + UINT32 HTMCS4FBK:4; + UINT32 HTMCS3FBK:4; + UINT32 HTMCS2FBK:4; + UINT32 HTMCS1FBK:4; + UINT32 HTMCS0FBK:4; + } field; + UINT32 word; +} HT_FBK_CFG0_STRUC; +#else +typedef union _HT_FBK_CFG0_STRUC { + struct { + UINT32 HTMCS0FBK:4; + UINT32 HTMCS1FBK:4; + UINT32 HTMCS2FBK:4; + UINT32 HTMCS3FBK:4; + UINT32 HTMCS4FBK:4; + UINT32 HTMCS5FBK:4; + UINT32 HTMCS6FBK:4; + UINT32 HTMCS7FBK:4; + } field; + UINT32 word; +} HT_FBK_CFG0_STRUC; +#endif + + +#define HT_FBK_CFG1 0x1358 +#ifdef RT_BIG_ENDIAN +typedef union _HT_FBK_CFG1_STRUC { + struct { + UINT32 HTMCS15FBK:4; + UINT32 HTMCS14FBK:4; + UINT32 HTMCS13FBK:4; + UINT32 HTMCS12FBK:4; + UINT32 HTMCS11FBK:4; + UINT32 HTMCS10FBK:4; + UINT32 HTMCS9FBK:4; + UINT32 HTMCS8FBK:4; + } field; + UINT32 word; +} HT_FBK_CFG1_STRUC; +#else +typedef union _HT_FBK_CFG1_STRUC { + struct { + UINT32 HTMCS8FBK:4; + UINT32 HTMCS9FBK:4; + UINT32 HTMCS10FBK:4; + UINT32 HTMCS11FBK:4; + UINT32 HTMCS12FBK:4; + UINT32 HTMCS13FBK:4; + UINT32 HTMCS14FBK:4; + UINT32 HTMCS15FBK:4; + } field; + UINT32 word; +} HT_FBK_CFG1_STRUC; +#endif + + +#define LG_FBK_CFG0 0x135c +#ifdef RT_BIG_ENDIAN +typedef union _LG_FBK_CFG0_STRUC { + struct { + UINT32 OFDMMCS7FBK:4; + UINT32 OFDMMCS6FBK:4; + UINT32 OFDMMCS5FBK:4; + UINT32 OFDMMCS4FBK:4; + UINT32 OFDMMCS3FBK:4; + UINT32 OFDMMCS2FBK:4; + UINT32 OFDMMCS1FBK:4; + UINT32 OFDMMCS0FBK:4; + } field; + UINT32 word; +} LG_FBK_CFG0_STRUC; +#else +typedef union _LG_FBK_CFG0_STRUC { + struct { + UINT32 OFDMMCS0FBK:4; + UINT32 OFDMMCS1FBK:4; + UINT32 OFDMMCS2FBK:4; + UINT32 OFDMMCS3FBK:4; + UINT32 OFDMMCS4FBK:4; + UINT32 OFDMMCS5FBK:4; + UINT32 OFDMMCS6FBK:4; + UINT32 OFDMMCS7FBK:4; + } field; + UINT32 word; +} LG_FBK_CFG0_STRUC; +#endif + + +#define LG_FBK_CFG1 0x1360 +#ifdef RT_BIG_ENDIAN +typedef union _LG_FBK_CFG1_STRUC { + struct { + UINT32 rsv:16; + UINT32 CCKMCS3FBK:4; + UINT32 CCKMCS2FBK:4; + UINT32 CCKMCS1FBK:4; + UINT32 CCKMCS0FBK:4; + } field; + UINT32 word; +} LG_FBK_CFG1_STRUC; +#else +typedef union _LG_FBK_CFG1_STRUC { + struct { + UINT32 CCKMCS0FBK:4; + UINT32 CCKMCS1FBK:4; + UINT32 CCKMCS2FBK:4; + UINT32 CCKMCS3FBK:4; + UINT32 rsv:16; + } field; + UINT32 word; +} LG_FBK_CFG1_STRUC; +#endif + + +/*======================================================= */ +/* Protection Paramater */ +/*======================================================= */ +#define ASIC_SHORTNAV 1 +#define ASIC_LONGNAV 2 +#define ASIC_RTS 1 +#define ASIC_CTS 2 + +#define CCK_PROT_CFG 0x1364 /* CCK Protection */ +#define OFDM_PROT_CFG 0x1368 /* OFDM Protection */ +#define MM20_PROT_CFG 0x136C /* MM20 Protection */ +#define MM40_PROT_CFG 0x1370 /* MM40 Protection */ +#define GF20_PROT_CFG 0x1374 /* GF20 Protection */ +#define GF40_PROT_CFG 0x1378 /* GR40 Protection */ +#ifdef RT_BIG_ENDIAN +typedef union _PROT_CFG_STRUC { + struct { +#ifdef DOT11_VHT_AC + UINT32 ProtectTxop:3; /* TXOP allowance */ + UINT32 DynCbw:1; /* RTS use dynamic channel bandwidth when TX signaling mode is turned on */ + UINT32 RtsTaSignal:1; /* RTS TA signaling mode */ +#else + UINT32 rsv:5; +#endif + UINT32 RTSThEn:1; /*RTS threshold enable on CCK TX */ + UINT32 TxopAllowGF40:1; /*CCK TXOP allowance.0:disallow. */ + UINT32 TxopAllowGF20:1; /*CCK TXOP allowance.0:disallow. */ + UINT32 TxopAllowMM40:1; /*CCK TXOP allowance.0:disallow. */ + UINT32 TxopAllowMM20:1; /*CCK TXOP allowance. 0:disallow. */ + UINT32 TxopAllowOfdm:1; /*CCK TXOP allowance.0:disallow. */ + UINT32 TxopAllowCck:1; /*CCK TXOP allowance.0:disallow. */ + UINT32 ProtectNav:2; /*TXOP protection type for CCK TX. 0:None, 1:ShortNAVprotect, 2:LongNAVProtect, 3:rsv */ + UINT32 ProtectCtrl:2; /*Protection control frame type for CCK TX. 1:RTS/CTS, 2:CTS-to-self, 0:None, 3:rsv */ + UINT32 ProtectRate:16; /*Protection control frame rate for CCK TX(RTS/CTS/CFEnd). */ + } field; + UINT32 word; +} PROT_CFG_STRUC; +#else +typedef union _PROT_CFG_STRUC { + struct { + UINT32 ProtectRate:16; + UINT32 ProtectCtrl:2; + UINT32 ProtectNav:2; + UINT32 TxopAllowCck:1; + UINT32 TxopAllowOfdm:1; + UINT32 TxopAllowMM20:1; + UINT32 TxopAllowMM40:1; + UINT32 TxopAllowGF20:1; + UINT32 TxopAllowGF40:1; + UINT32 RTSThEn:1; +#ifdef DOT11_VHT_AC + UINT32 RtsTaSignal:1; /* RTS TA signaling mode */ + UINT32 DynCbw:1; /* RTS use dynamic channel bandwidth when TX signaling mode is turned on */ + UINT32 ProtectTxop:3; /* TXOP allowance */ +#else + UINT32 rsv:5; +#endif /* !DOT11_VHT_AC */ + } field; + UINT32 word; +} PROT_CFG_STRUC; +#endif + +#define EXP_CTS_TIME 0x137C +#define EXP_ACK_TIME 0x1380 + + +#define HT_FBK_TO_LEGACY 0x1384 + +#define TX_FBK_LIMIT 0x1398 + +#ifdef DOT11N_SS3_SUPPORT +#define TX_FBK_CFG_3S_0 0x13c4 +#ifdef RT_BIG_ENDIAN +typedef union _TX_FBK_CFG_3S_0_STRUC { + struct { + UINT32 rsv0:3; + UINT32 HTMCS19FBK:5; + UINT32 rsv1:3; + UINT32 HTMCS18FBK:5; + UINT32 rsv2:3; + UINT32 HTMCS17FBK:5; + UINT32 rsv3:3; + UINT32 HTMCS16FBK:5; + } field; + UINT32 word; +} TX_FBK_CFG_3S_0_STRUC; +#else +typedef union _TX_FBK_CFG_3S_0_STRUC { + struct { + UINT32 HTMCS16FBK:5; + UINT32 rsv3:3; + UINT32 HTMCS17FBK:5; + UINT32 rsv2:3; + UINT32 HTMCS18FBK:5; + UINT32 rsv1:3; + UINT32 HTMCS19FBK:5; + UINT32 rsv0:4; + } field; + UINT32 word; +} TX_FBK_CFG_3S_0_STRUC; +#endif + +#define TX_FBK_CFG_3S_1 0x13c8 +#ifdef RT_BIG_ENDIAN +typedef union _TX_FBK_CFG_3S_1_STRUC { + struct { + UINT32 rsv0:3; + UINT32 HTMCS23FBK:5; + UINT32 rsv1:3; + UINT32 HTMCS22FBK:5; + UINT32 rsv2:3; + UINT32 HTMCS21FBK:5; + UINT32 rsv3:3; + UINT32 HTMCS20FBK:5; + } field; + UINT32 word; +} TX_FBK_CFG_3S_1_STRUC; +#else +typedef union _TX_FBK_CFG_3S_1_STRUC { + struct { + UINT32 HTMCS20FBK:5; + UINT32 rsv3:3; + UINT32 HTMCS21FBK:5; + UINT32 rsv2:3; + UINT32 HTMCS22FBK:5; + UINT32 rsv1:3; + UINT32 HTMCS23FBK:5; + UINT32 rsv0:3; + } field; + UINT32 word; +} TX_FBK_CFG_3S_1_STRUC; +#endif +#endif /* DOT11N_SS3_SUPPORT */ + +#define TX_AC_RTY_LIMIT 0x13cc +#define TX_AC_FBK_SPEED 0x13d0 + + + +/* 4.4 MAC RX configuration registers (offset:0x1400) */ + +/* RX_FILTR_CFG: RX configuration register */ +#define RX_FILTR_CFG 0x1400 +#ifdef RT_BIG_ENDIAN +typedef union _RX_FILTR_CFG_STRUC { + struct { + UINT32 rsv:15; + UINT32 DropRsvCntlType:1; + UINT32 DropBAR:1; + UINT32 DropBA:1; + UINT32 DropPsPoll:1; /* Drop Ps-Poll */ + UINT32 DropRts:1; /* Drop Ps-Poll */ + UINT32 DropCts:1; /* Drop Ps-Poll */ + UINT32 DropAck:1; /* Drop Ps-Poll */ + UINT32 DropCFEnd:1; /* Drop Ps-Poll */ + UINT32 DropCFEndAck:1; /* Drop Ps-Poll */ + UINT32 DropDuplicate:1; /* Drop duplicate frame */ + UINT32 DropBcast:1; /* Drop broadcast frames */ + UINT32 DropMcast:1; /* Drop multicast frames */ + UINT32 DropVerErr:1; /* Drop version error frame */ + UINT32 DropNotMyBSSID:1; /* Drop fram ToDs bit is true */ + UINT32 DropNotToMe:1; /* Drop not to me unicast frame */ + UINT32 DropPhyErr:1; /* Drop physical error */ + UINT32 DropCRCErr:1; /* Drop CRC error */ + } field; + UINT32 word; +} RX_FILTR_CFG_STRUC; +#else +typedef union _RX_FILTR_CFG_STRUC { + struct { + UINT32 DropCRCErr:1; + UINT32 DropPhyErr:1; + UINT32 DropNotToMe:1; + UINT32 DropNotMyBSSID:1; + UINT32 DropVerErr:1; + UINT32 DropMcast:1; + UINT32 DropBcast:1; + UINT32 DropDuplicate:1; + UINT32 DropCFEndAck:1; + UINT32 DropCFEnd:1; + UINT32 DropAck:1; + UINT32 DropCts:1; + UINT32 DropRts:1; + UINT32 DropPsPoll:1; + UINT32 DropBA:1; + UINT32 DropBAR:1; + UINT32 DropRsvCntlType:1; + UINT32 rsv:15; + } field; + UINT32 word; +} RX_FILTR_CFG_STRUC; +#endif + + +/* AUTO_RSP_CFG: Auto-Responder */ +#define AUTO_RSP_CFG 0x1404 +#ifdef RT_BIG_ENDIAN +typedef union _AUTO_RSP_CFG_STRUC { + struct { + UINT32 :24; + UINT32 AckCtsPsmBit:1; /* Power bit value in conrtrol frame */ + UINT32 DualCTSEn:1; /* Power bit value in conrtrol frame */ + UINT32 rsv:1; /* Power bit value in conrtrol frame */ + UINT32 AutoResponderPreamble:1; /* 0:long, 1:short preamble */ + UINT32 CTS40MRef:1; /* Response CTS 40MHz duplicate mode */ + UINT32 CTS40MMode:1; /* Response CTS 40MHz duplicate mode */ + UINT32 BACAckPolicyEnable:1; /* 0:long, 1:short preamble */ + UINT32 AutoResponderEnable:1; + } field; + UINT32 word; +} AUTO_RSP_CFG_STRUC; +#else +typedef union _AUTO_RSP_CFG_STRUC { + struct { + UINT32 AutoResponderEnable:1; + UINT32 BACAckPolicyEnable:1; + UINT32 CTS40MMode:1; + UINT32 CTS40MRef:1; + UINT32 AutoResponderPreamble:1; + UINT32 rsv:1; + UINT32 DualCTSEn:1; + UINT32 AckCtsPsmBit:1; + UINT32 :24; + } field; + UINT32 word; +} AUTO_RSP_CFG_STRUC; +#endif + + +#define LEGACY_BASIC_RATE 0x1408 +#define HT_BASIC_RATE 0x140c +#define HT_CTRL_CFG 0x1410 +#define SIFS_COST_CFG 0x1414 +#define RX_PARSER_CFG 0x1418 /*Set NAV for all received frames */ + +#define EXT_CCA_CFG 0x141c + +#ifdef MAC_APCLI_SUPPORT +#define APCLI_BSSID_IDX 8 +#define MAC_APCLI_BSSID_DW0 0x1090 +#define MAC_APCLI_BSSID_DW1 0x1094 +#endif /* MAC_APCLI_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT +#define MAC_ADDR_EXT_EN 0x147C +#define MAC_ADDR_EXT0_31_0 0x1480 +#define MAC_ADDR_EXT0_47_32 0x1484 +#define MAX_EXT_MAC_ADDR_SIZE 16 + +#define UNKOWN_APCLI_IDX 0xFF +#define CLIENT_APCLI 0x00 +#define CLIENT_STA 0x01 +#define CLIENT_ETH 0x02 +#define EXTERNDER_CLI 0x08 +#endif /* MAC_REPEATER_SUPPORT */ + + +/* 4.5 MAC Security configuration (offset:0x1500) */ +#define TX_SEC_CNT0 0x1500 +#define RX_SEC_CNT0 0x1504 +#define CCMP_FC_MUTE 0x1508 + + +/* 4.6 HCCA/PSMP (offset:0x1600) */ +#define TXOP_HLDR_ADDR0 0x1600 +#define TXOP_HLDR_ADDR1 0x1604 +#define TXOP_HLDR_ET 0x1608 +#define QOS_CFPOLL_RA_DW0 0x160c +#define QOS_CFPOLL_A1_DW1 0x1610 +#define QOS_CFPOLL_QC 0x1614 + + +/* 4.7 MAC Statistis registers (offset:0x1700) */ +/* RX_STA_CNT0_STRUC: RX PLCP error count & RX CRC error count */ +#define RX_STA_CNT0 0x1700 +#ifdef RT_BIG_ENDIAN +typedef union _RX_STA_CNT0_STRUC { + struct { + UINT16 PhyErr; + UINT16 CrcErr; + } field; + UINT32 word; +} RX_STA_CNT0_STRUC; +#else +typedef union _RX_STA_CNT0_STRUC { + struct { + UINT16 CrcErr; + UINT16 PhyErr; + } field; + UINT32 word; +} RX_STA_CNT0_STRUC; +#endif + + +/* RX_STA_CNT1_STRUC: RX False CCA count & RX LONG frame count */ +#define RX_STA_CNT1 0x1704 +#ifdef RT_BIG_ENDIAN +typedef union _RX_STA_CNT1_STRUC { + struct { + UINT16 PlcpErr; + UINT16 FalseCca; + } field; + UINT32 word; +} RX_STA_CNT1_STRUC; +#else +typedef union _RX_STA_CNT1_STRUC { + struct { + UINT16 FalseCca; + UINT16 PlcpErr; + } field; + UINT32 word; +} RX_STA_CNT1_STRUC; +#endif + + +/* RX_STA_CNT2_STRUC: */ +#define RX_STA_CNT2 0x1708 +#ifdef RT_BIG_ENDIAN +typedef union _RX_STA_CNT2_STRUC { + struct { + UINT16 RxFifoOverflowCount; + UINT16 RxDupliCount; + } field; + UINT32 word; +} RX_STA_CNT2_STRUC; +#else +typedef union _RX_STA_CNT2_STRUC { + struct { + UINT16 RxDupliCount; + UINT16 RxFifoOverflowCount; + } field; + UINT32 word; +} RX_STA_CNT2_STRUC; +#endif + +#ifndef MT_MAC +/* STA_CSR3: TX Beacon count */ +#define TX_STA_CNT0 0x170C +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_CNT0_STRUC { + struct { + UINT16 TxBeaconCount; + UINT16 TxFailCount; + } field; + UINT32 word; +} TX_STA_CNT0_STRUC; +#else +typedef union _TX_STA_CNT0_STRUC { + struct { + UINT16 TxFailCount; + UINT16 TxBeaconCount; + } field; + UINT32 word; +} TX_STA_CNT0_STRUC; +#endif + + + +/* TX_STA_CNT1: TX tx count */ +#define TX_STA_CNT1 0x1710 +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_CNT1_STRUC { + struct { + UINT16 TxRetransmit; + UINT16 TxSuccess; + } field; + UINT32 word; +} TX_STA_CNT1_STRUC; +#else +typedef union _TX_STA_CNT1_STRUC { + struct { + UINT16 TxSuccess; + UINT16 TxRetransmit; + } field; + UINT32 word; +} TX_STA_CNT1_STRUC; +#endif + + +/* TX_STA_CNT2: TX tx count */ +#define TX_STA_CNT2 0x1714 +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_CNT2_STRUC { + struct { + UINT16 TxUnderFlowCount; + UINT16 TxZeroLenCount; + } field; + UINT32 word; +} TX_STA_CNT2_STRUC; +#else +typedef union _TX_STA_CNT2_STRUC { + struct { + UINT16 TxZeroLenCount; + UINT16 TxUnderFlowCount; + } field; + UINT32 word; +} TX_STA_CNT2_STRUC; +#endif + + +/* TX_STA_FIFO_STRUC: TX Result for specific PID status fifo register */ +#define TX_STA_FIFO 0x1718 +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_FIFO_STRUC { + struct { + UINT32 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; +#else +typedef union _TX_STA_FIFO_STRUC { + struct { + UINT32 bValid:1; + UINT32 PidType:4; + UINT32 TxSuccess:1; + UINT32 TxAggre:1; + UINT32 TxAckRequired:1; + UINT32 wcid:8; + UINT32 SuccessRate:11; + UINT32 eTxBF:1; + UINT32 Sounding:1; + UINT32 iTxBF:1; + UINT32 Reserve:2; + } field; + UINT32 word; +} TX_STA_FIFO_STRUC; +#endif +#endif /* !MT_MAC */ + +/* + Debug counters +*/ +#define TX_AGG_CNT 0x171c +#ifdef RT_BIG_ENDIAN +typedef union _TX_NAG_AGG_CNT_STRUC { + struct { + UINT16 AggTxCount; + UINT16 NonAggTxCount; + } field; + UINT32 word; +} TX_NAG_AGG_CNT_STRUC; +#else +typedef union _TX_NAG_AGG_CNT_STRUC { + struct { + UINT16 NonAggTxCount; + UINT16 AggTxCount; + } field; + UINT32 word; +} TX_NAG_AGG_CNT_STRUC; +#endif + + +#define TX_AGG_CNT0 0x1720 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT0_STRUC { + struct { + UINT16 AggSize2Count; + UINT16 AggSize1Count; + } field; + UINT32 word; +} TX_AGG_CNT0_STRUC; +#else +typedef union _TX_AGG_CNT0_STRUC { + struct { + UINT16 AggSize1Count; + UINT16 AggSize2Count; + } field; + UINT32 word; +} TX_AGG_CNT0_STRUC; +#endif + + +#define TX_AGG_CNT1 0x1724 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT1_STRUC { + struct { + UINT16 AggSize4Count; + UINT16 AggSize3Count; + } field; + UINT32 word; +} TX_AGG_CNT1_STRUC; +#else +typedef union _TX_AGG_CNT1_STRUC { + struct { + UINT16 AggSize3Count; + UINT16 AggSize4Count; + } field; + UINT32 word; +} TX_AGG_CNT1_STRUC; +#endif + + +#define TX_AGG_CNT2 0x1728 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT2_STRUC { + struct { + UINT16 AggSize6Count; + UINT16 AggSize5Count; + } field; + UINT32 word; +} TX_AGG_CNT2_STRUC; +#else +typedef union _TX_AGG_CNT2_STRUC { + struct { + UINT16 AggSize5Count; + UINT16 AggSize6Count; + } field; + UINT32 word; +} TX_AGG_CNT2_STRUC; +#endif + + +#define TX_AGG_CNT3 0x172c +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT3_STRUC { + struct { + UINT16 AggSize8Count; + UINT16 AggSize7Count; + } field; + UINT32 word; +} TX_AGG_CNT3_STRUC; +#else +typedef union _TX_AGG_CNT3_STRUC { + struct { + UINT16 AggSize7Count; + UINT16 AggSize8Count; + } field; + UINT32 word; +} TX_AGG_CNT3_STRUC; +#endif + + +#define TX_AGG_CNT4 0x1730 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT4_STRUC { + struct { + UINT16 AggSize10Count; + UINT16 AggSize9Count; + } field; + UINT32 word; +} TX_AGG_CNT4_STRUC; +#else +typedef union _TX_AGG_CNT4_STRUC { + struct { + UINT16 AggSize9Count; + UINT16 AggSize10Count; + } field; + UINT32 word; +} TX_AGG_CNT4_STRUC; +#endif + + +#define TX_AGG_CNT5 0x1734 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT5_STRUC { + struct { + UINT16 AggSize12Count; + UINT16 AggSize11Count; + } field; + UINT32 word; +} TX_AGG_CNT5_STRUC; +#else +typedef union _TX_AGG_CNT5_STRUC { + struct { + UINT16 AggSize11Count; + UINT16 AggSize12Count; + } field; + UINT32 word; +} TX_AGG_CNT5_STRUC; +#endif + + +#define TX_AGG_CNT6 0x1738 +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT6_STRUC { + struct { + UINT16 AggSize14Count; + UINT16 AggSize13Count; + } field; + UINT32 word; +} TX_AGG_CNT6_STRUC; +#else +typedef union _TX_AGG_CNT6_STRUC { + struct { + UINT16 AggSize13Count; + UINT16 AggSize14Count; + } field; + UINT32 word; +} TX_AGG_CNT6_STRUC; +#endif + + +#define TX_AGG_CNT7 0x173c +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT7_STRUC { + struct { + UINT16 AggSize16Count; + UINT16 AggSize15Count; + } field; + UINT32 word; +} TX_AGG_CNT7_STRUC; +#else +typedef union _TX_AGG_CNT7_STRUC { + struct { + UINT16 AggSize15Count; + UINT16 AggSize16Count; + } field; + UINT32 word; +} TX_AGG_CNT7_STRUC; +#endif + + +#define TX_AGG_CNT8 0x174c /* AGG_SIZE = 17,18 */ +#define TX_AGG_CNT9 0x1750 /* AGG_SIZE = 19,20 */ +#define TX_AGG_CNT10 0x1754 /* AGG_SIZE = 21,22 */ +#define TX_AGG_CNT11 0x1758 /* AGG_SIZE = 23,24 */ +#define TX_AGG_CNT12 0x175c /* AGG_SIZE = 25,26 */ +#define TX_AGG_CNT13 0x1760 /* AGG_SIZE = 27,28 */ +#define TX_AGG_CNT14 0x1764 /* AGG_SIZE = 29,30 */ +#define TX_AGG_CNT15 0x1768 /* AGG_SIZE = 31,32 */ +#define TX_AGG_CNT16 0x179C /* AGG_SIZE = 33, 34 */ +#define TX_AGG_CNT17 0x17a0 /* AGG_SIZE = 35, 36 */ +#define TX_AGG_CNT18 0x17a4 /* AGG_SIZE = 37, 38 */ +#define TX_AGG_CNT19 0x17a8 /* AGG_SIZE = 39, 40 */ +#define TX_AGG_CNT20 0x17ac /* AGG_SIZE = 41, 42 */ +#define TX_AGG_CNT21 0x17b0 /* AGG_SIZE = 43, 44 */ +#define TX_AGG_CNT22 0x17b4 /* AGG_SIZE = 45, 46 */ +#define TX_AGG_CNT23 0x17b8 /* AGG_SIZE = 47, 48 */ +#ifdef RT_BIG_ENDIAN +typedef union _TX_AGG_CNT_STRUC { + struct { + UINT16 AggCnt_y; /* the count of aggregation size = x + 1 */ + UINT16 AggCnt_x; /* the count of aggregation size = x */ + } field; + UINT32 word; +} TX_AGG_CNT_STRUC; +#else +typedef union _TX_AGG_CNT_STRUC { + struct { + UINT16 AggCnt_x; + UINT16 AggCnt_y; + } field; + UINT32 word; +} TX_AGG_CNT_STRUC; +#endif + +typedef union _TX_AGG_CNTN_STRUC { + struct { +#ifdef RT_BIG_ENDIAN + UINT16 AggSizeHighCount; + UINT16 AggSizeLowCount; +#else + UINT16 AggSizeLowCount; + UINT16 AggSizeHighCount; +#endif + } field; + UINT32 word; +} TX_AGG_CNTN_STRUC; + + +#define MPDU_DENSITY_CNT 0x1740 +#ifdef RT_BIG_ENDIAN +typedef union _MPDU_DEN_CNT_STRUC { + struct { + UINT16 RXZeroDelCount; /*RX zero length delimiter count */ + UINT16 TXZeroDelCount; /*TX zero length delimiter count */ + } field; + UINT32 word; +} MPDU_DEN_CNT_STRUC; +#else +typedef union _MPDU_DEN_CNT_STRUC { + struct { + UINT16 TXZeroDelCount; + UINT16 RXZeroDelCount; + } field; + UINT32 word; +} MPDU_DEN_CNT_STRUC; +#endif + + +/* TX_STA_FIFO_EXT_STRUC: TX retry cnt for specific frame */ +#define TX_STA_FIFO_EXT 0x1798 /* Only work after RT53xx */ +#ifdef RT_BIG_ENDIAN +typedef union _TX_STA_FIFO_EXT_STRUC { + struct { + UINT32 rsv:16; + UINT32 pkt_id_65xx:8; /* pkt_id when run as rt65xx based chips */ + UINT32 txRtyCnt:8; /* frame Tx retry cnt */ + } field; + UINT32 word; +} TX_STA_FIFO_EXT_STRUC; +#else +typedef union _TX_STA_FIFO_EXT_STRUC { + struct { + UINT32 txRtyCnt:8; + UINT32 pkt_id_65xx:8; + UINT32 rsv:16; + } field; + UINT32 word; +} TX_STA_FIFO_EXT_STRUC; +#endif + + +#ifdef FIFO_EXT_SUPPORT +#define WCID_TX_CNT_0 0x176c +#define WCID_TX_CNT_1 0x1770 +#define WCID_TX_CNT_2 0x1774 +#define WCID_TX_CNT_3 0x1778 +#define WCID_TX_CNT_4 0x177c +#define WCID_TX_CNT_5 0x1780 +#define WCID_TX_CNT_6 0x1784 +#define WCID_TX_CNT_7 0x1788 +#ifdef RT_BIG_ENDIAN +typedef union _WCID_TX_CNT_STRUC { + struct { + UINT32 reTryCnt:16; + UINT32 succCnt:16; + } field; + UINT32 word; +} WCID_TX_CNT_STRUC; +#else +typedef union _WCID_TX_CNT_STRUC { + struct { + UINT32 succCnt:16; + UINT32 reTryCnt:16; + } field; + UINT32 word; +} WCID_TX_CNT_STRUC; +#endif + + +#define WCID_MAPPING_0 0x178c +#define WCID_MAPPING_1 0x1790 +#ifdef RT_BIG_ENDIAN +typedef union _WCID_MAPPING_STRUC { + struct { + UINT32 wcid3:8; + UINT32 wcid2:8; + UINT32 wcid1:8; + UINT32 wcid0:8; + } field; + UINT32 word; +} WCID_MAPPING_STRUC; +#else +typedef union _WCID_MAPPING_STRUC { + struct { + UINT32 wcid0:8; + UINT32 wcid1:8; + UINT32 wcid2:8; + UINT32 wcid3:8; + } field; + UINT32 word; +} WCID_MAPPINGT_STRUC; +#endif +#endif /* FIFO_EXT_SUPPORT */ + +#define TX_REPORT_CNT 0x1794 + + +/* Security key table memory, base address = 0x1000 */ +#define MAC_WCID_BASE 0x1800 /*8-bytes(use only 6-bytes) * 256 entry = */ +#define HW_WCID_ENTRY_SIZE 8 + +#ifdef MCS_LUT_SUPPORT +#define MAC_MCS_LUT_BASE 0x1c00 +#endif /* MCS_LUT_SUPPORT */ + +#ifdef RT_BIG_ENDIAN +typedef union _SHAREDKEY_MODE_STRUC { + struct { + UINT32 Bss1Key3CipherAlg:4; + UINT32 Bss1Key2CipherAlg:4; + UINT32 Bss1Key1CipherAlg:4; + UINT32 Bss1Key0CipherAlg:4; + UINT32 Bss0Key3CipherAlg:4; + UINT32 Bss0Key2CipherAlg:4; + UINT32 Bss0Key1CipherAlg:4; + UINT32 Bss0Key0CipherAlg:4; + } field; + UINT32 word; +} SHAREDKEY_MODE_STRUC; +#else +typedef union _SHAREDKEY_MODE_STRUC { + struct { + UINT32 Bss0Key0CipherAlg:4; + UINT32 Bss0Key1CipherAlg:4; + UINT32 Bss0Key2CipherAlg:4; + UINT32 Bss0Key3CipherAlg:4; + UINT32 Bss1Key0CipherAlg:4; + UINT32 Bss1Key1CipherAlg:4; + UINT32 Bss1Key2CipherAlg:4; + UINT32 Bss1Key3CipherAlg:4; + } field; + UINT32 word; +} SHAREDKEY_MODE_STRUC; +#endif + + +/* 64-entry for pairwise key table, 8-byte per entry */ +typedef struct _HW_WCID_ENTRY { + UINT8 Address[6]; + UINT8 Rsv[2]; +} HW_WCID_ENTRY; + + +/* ================================================================================= */ +/* WCID format */ +/* ================================================================================= */ +/*7.1 WCID ENTRY format : 8bytes */ +typedef struct _WCID_ENTRY_STRUC { + UINT8 RXBABitmap7; /* bit0 for TID8, bit7 for TID 15 */ + UINT8 RXBABitmap0; /* bit0 for TID0, bit7 for TID 7 */ + UINT8 MAC[6]; /* 0 for shared key table. 1 for pairwise key table */ +} WCID_ENTRY_STRUC; + + +/*8.1.1 SECURITY KEY format : 8DW */ +/* 32-byte per entry, total 16-entry for shared key table, 64-entry for pairwise key table */ +typedef struct _HW_KEY_ENTRY { + UINT8 Key[16]; + UINT8 TxMic[8]; + UINT8 RxMic[8]; +} HW_KEY_ENTRY; + + +/*8.1.2 IV/EIV format : 2DW */ + +/* RX attribute entry format : 1DW */ +#ifdef RT_BIG_ENDIAN +typedef union _WCID_ATTRIBUTE_STRUC { + struct { + UINT32 WAPIKeyIdx:8; + UINT32 WAPI_rsv:8; + UINT32 WAPI_MCBC:1; + UINT32 rsv:3; + UINT32 BSSIdxExt:1; + UINT32 PairKeyModeExt:1; + UINT32 RXWIUDF:3; + UINT32 BSSIdx:3; /*multipleBSS index for the WCID */ + UINT32 PairKeyMode:3; + UINT32 KeyTab:1; /* 0 for shared key table. 1 for pairwise key table */ + } field; + UINT32 word; +} WCID_ATTRIBUTE_STRUC; +#else +typedef union _WCID_ATTRIBUTE_STRUC { + struct { + UINT32 KeyTab:1; /* 0 for shared key table. 1 for pairwise key table */ + UINT32 PairKeyMode:3; + UINT32 BSSIdx:3; /*multipleBSS index for the WCID */ + UINT32 RXWIUDF:3; + UINT32 PairKeyModeExt:1; + UINT32 BSSIdxExt:1; + UINT32 rsv:3; + UINT32 WAPI_MCBC:1; + UINT32 WAPI_rsv:8; + UINT32 WAPIKeyIdx:8; + } field; + UINT32 word; +} WCID_ATTRIBUTE_STRUC; +#endif + + +/* ================================================================================= */ +/* HOST-MCU communication data structure */ +/* ================================================================================= */ + +/* H2M_MAILBOX_CSR: Host-to-MCU Mailbox */ +#ifdef RT_BIG_ENDIAN +typedef union _H2M_MAILBOX_STRUC { + struct { + UINT32 Owner:8; + UINT32 CmdToken:8; /* 0xff tells MCU not to report CmdDoneInt after excuting the command */ + UINT32 HighByte:8; + UINT32 LowByte:8; + } field; + UINT32 word; +} H2M_MAILBOX_STRUC; +#else +typedef union _H2M_MAILBOX_STRUC { + struct { + UINT32 LowByte:8; + UINT32 HighByte:8; + UINT32 CmdToken:8; + UINT32 Owner:8; + } field; + UINT32 word; +} H2M_MAILBOX_STRUC; +#endif + + +/* M2H_CMD_DONE_CSR: MCU-to-Host command complete indication */ +#ifdef RT_BIG_ENDIAN +typedef union _M2H_CMD_DONE_STRUC { + struct { + UINT32 CmdToken3; + UINT32 CmdToken2; + UINT32 CmdToken1; + UINT32 CmdToken0; + } field; + UINT32 word; +} M2H_CMD_DONE_STRUC; +#else +typedef union _M2H_CMD_DONE_STRUC { + struct { + UINT32 CmdToken0; + UINT32 CmdToken1; + UINT32 CmdToken2; + UINT32 CmdToken3; + } field; + UINT32 word; +} M2H_CMD_DONE_STRUC; +#endif + + +/* HOST_CMD_CSR: For HOST to interrupt embedded processor */ +#ifdef RT_BIG_ENDIAN +typedef union _HOST_CMD_CSR_STRUC { + struct { + UINT32 Rsv:24; + UINT32 HostCommand:8; + } field; + UINT32 word; +} HOST_CMD_CSR_STRUC; +#else +typedef union _HOST_CMD_CSR_STRUC { + struct { + UINT32 HostCommand:8; + UINT32 Rsv:24; + } field; + UINT32 word; +} HOST_CMD_CSR_STRUC; +#endif + + +// TODO: shiang-6590, Need to check following definitions are useful or not!!! +/* AIFSN_CSR: AIFSN for each EDCA AC */ + + +/* E2PROM_CSR: EEPROM control register */ +#ifdef RT_BIG_ENDIAN +typedef union _E2PROM_CSR_STRUC { + struct { + UINT32 Rsvd:25; + UINT32 LoadStatus:1; /* 1:loading, 0:done */ + UINT32 Type:1; /* 1: 93C46, 0:93C66 */ + UINT32 EepromDO:1; + UINT32 EepromDI:1; + UINT32 EepromCS:1; + UINT32 EepromSK:1; + UINT32 Reload:1; /* Reload EEPROM content, write one to reload, self-cleared. */ + } field; + UINT32 word; +} E2PROM_CSR_STRUC; +#else +typedef union _E2PROM_CSR_STRUC { + struct { + UINT32 Reload:1; + UINT32 EepromSK:1; + UINT32 EepromCS:1; + UINT32 EepromDI:1; + UINT32 EepromDO:1; + UINT32 Type:1; + UINT32 LoadStatus:1; + UINT32 Rsvd:25; + } field; + UINT32 word; +} E2PROM_CSR_STRUC; +#endif + + +/* QOS_CSR0: TXOP holder address0 register */ +#ifdef RT_BIG_ENDIAN +typedef union _QOS_CSR0_STRUC { + struct { + UINT8 Byte3; /* MAC address byte 3 */ + UINT8 Byte2; /* MAC address byte 2 */ + UINT8 Byte1; /* MAC address byte 1 */ + UINT8 Byte0; /* MAC address byte 0 */ + } field; + UINT32 word; +} QOS_CSR0_STRUC; +#else +typedef union _QOS_CSR0_STRUC { + struct { + UINT8 Byte0; + UINT8 Byte1; + UINT8 Byte2; + UINT8 Byte3; + } field; + UINT32 word; +} QOS_CSR0_STRUC; +#endif + + +/* QOS_CSR1: TXOP holder address1 register */ +#ifdef RT_BIG_ENDIAN +typedef union _QOS_CSR1_STRUC { + struct { + UINT8 Rsvd1; + UINT8 Rsvd0; + UINT8 Byte5; /* MAC address byte 5 */ + UINT8 Byte4; /* MAC address byte 4 */ + } field; + UINT32 word; +} QOS_CSR1_STRUC; +#else +typedef union _QOS_CSR1_STRUC { + struct { + UINT8 Byte4; /* MAC address byte 4 */ + UINT8 Byte5; /* MAC address byte 5 */ + UINT8 Rsvd0; + UINT8 Rsvd1; + } field; + UINT32 word; +} QOS_CSR1_STRUC; +#endif + +// TODO: shiang-6590, check upper definitions are useful or not! + + + +/* Other on-chip shared memory space, base = 0x2000 */ + +/* CIS space - base address = 0x2000 */ +#define HW_CIS_BASE 0x2000 + +/* Carrier-sense CTS frame base address. It's where mac stores carrier-sense frame for carrier-sense function. */ +#define HW_CS_CTS_BASE 0x7700 +/* DFS CTS frame base address. It's where mac stores CTS frame for DFS. */ +#define HW_DFS_CTS_BASE 0x7780 +#define HW_CTS_FRAME_SIZE 0x80 + + +/* + On-chip BEACON frame space - + 1. HW_BEACON_OFFSET/64B must be 0; + 2. BCN_OFFSETx(0~) must also be changed in MACRegTable(common/rtmp_init.c) + */ +#define HW_BEACON_OFFSET 0x0200 + +/* NullFrame buffer */ +#define HW_NULL_BASE 0x7700 +#define HW_NULL2_BASE 0x7780 + + + +/* In order to support maximum 8 MBSS and its maximum length is 512 for each beacon + Three section discontinue memory segments will be used. + 1. The original region for BCN 0~3 + 2. Extract memory from FCE table for BCN 4~5 + 3. Extract memory from Pair-wise key table for BCN 6~7 + It occupied those memory of wcid 238~253 for BCN 6 + and wcid 222~237 for BCN 7 */ +/*#define HW_BEACON_MAX_COUNT 8 */ +#define HW_BEACON_MAX_SIZE(__pAd) ((__pAd)->chipCap.BcnMaxHwSize) +#define HW_BEACON_BASE0(__pAd) ((__pAd)->chipCap.BcnBase[0]) +/*#define HW_BEACON_BASE1 0x7A00 */ +/*#define HW_BEACON_BASE2 0x7C00 */ +/*#define HW_BEACON_BASE3 0x7E00 */ +/*#define HW_BEACON_BASE4 0x7200 */ +/*#define HW_BEACON_BASE5 0x7400 */ +/*#define HW_BEACON_BASE6 0x5DC0 */ +/*#define HW_BEACON_BASE7 0x5BC0 */ + + +/* Higher 8KB shared memory */ +#define HW_BEACON_BASE0_REDIRECTION 0x4000 +#define HW_BEACON_BASE1_REDIRECTION 0x4200 +#define HW_BEACON_BASE2_REDIRECTION 0x4400 +#define HW_BEACON_BASE3_REDIRECTION 0x4600 +#define HW_BEACON_BASE4_REDIRECTION 0x4800 +#define HW_BEACON_BASE5_REDIRECTION 0x4A00 +#define HW_BEACON_BASE6_REDIRECTION 0x4C00 +#define HW_BEACON_BASE7_REDIRECTION 0x4E00 + + +/* HOST-MCU shared memory - base address = 0x2100 */ +#define HOST_CMD_CSR 0x404 +#define H2M_MAILBOX_CSR 0x7010 +#define H2M_MAILBOX_CID 0x7014 +#define H2M_MAILBOX_STATUS 0x701c +#define H2M_INT_SRC 0x7024 +#define H2M_BBP_AGENT 0x7028 +#define M2H_CMD_DONE_CSR 0x000c +#define MCU_TXOP_ARRAY_BASE 0x000c /* TODO: to be provided by Albert */ +#define MCU_TXOP_ENTRY_SIZE 32 /* TODO: to be provided by Albert */ +#define MAX_NUM_OF_TXOP_ENTRY 16 /* TODO: must be same with 8051 firmware */ +#define MCU_MBOX_VERSION 0x01 /* TODO: to be confirmed by Albert */ +#define MCU_MBOX_VERSION_OFFSET 5 /* TODO: to be provided by Albert */ + + +#define E2PROM_CSR 0x0004 +#define IO_CNTL_CSR 0x77d0 + + + +/* ================================================================ */ +/* Tx / Rx / Mgmt ring descriptor definition */ +/* ================================================================ */ + +/* Host DMA registers - base address 0x200 . TX0-3=EDCAQid0-3, TX4=HCCA, TX5=MGMT, */ +/* DMA RING DESCRIPTOR */ + +/* 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 WMM_QUE_NUM 4 /* each sta has 4 Queues to mapping to each WMM AC */ + +/* value domain of pTxD->HostQId (4-bit: 0~15) */ +#define QID_AC_BK 1 /* meet ACI definition in 802.11e */ +#define QID_AC_BE 0 /* meet ACI definition in 802.11e */ +#define QID_AC_VI 2 +#define QID_AC_VO 3 +#define QID_HCCA 4 +#define NUM_OF_TX_RING 5 + +#define NUM_OF_RX_RING 1 +#ifdef CONFIG_ANDES_SUPPORT +#undef NUM_OF_RX_RING +#define NUM_OF_RX_RING 2 +#endif /* CONFIG_ANDES_SUPPORT */ + +#define QID_MGMT 13 +#define QID_RX 14 +#define QID_OTHER 15 +#ifdef CONFIG_ANDES_SUPPORT +#define QID_CTRL 16 +#endif /* CONFIG_ANDES_SUPPORT */ + + + + +#define RTMP_MAC_SHR_MSEL_PROTECT_LOCK(__pAd, __IrqFlags) __IrqFlags = __IrqFlags; +#define RTMP_MAC_SHR_MSEL_PROTECT_UNLOCK(__pAd, __IrqFlags) __IrqFlags = __IrqFlags; + + +#define SHAREDKEYTABLE 0 +#define PAIRWISEKEYTABLE 1 + + + +struct _RTMP_ADAPTER; + +VOID ReSyncBeaconTime(struct _RTMP_ADAPTER *pAd); + + +INT rtmp_mac_fifo_stat_update(struct _RTMP_ADAPTER *pAd); + +INT rtmp_mac_set_band(struct _RTMP_ADAPTER *pAd, int band); +INT rtmp_mac_set_ctrlch(struct _RTMP_ADAPTER *pAd, UINT8 extch); +INT rtmp_mac_set_mmps(struct _RTMP_ADAPTER *pAd, INT ReduceCorePower); + +INT rtmp_hw_tb_init(struct _RTMP_ADAPTER *pAd, BOOLEAN bHardReset); +VOID rtmp_mac_bcn_buf_init(struct _RTMP_ADAPTER *pAd, BOOLEAN bHardReset); + +INT rtmp_mac_sys_reset(struct _RTMP_ADAPTER *pAd, BOOLEAN bHardReset); + +INT rtmp_mac_init(struct _RTMP_ADAPTER *pAd); +#endif /* __RTMP_MAC_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/map.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/map.h new file mode 100644 index 000000000..380491dd4 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/map.h @@ -0,0 +1,184 @@ + +#ifndef __MAP_H__ +#define __MAP_H__ + +#include "rtmp_type.h" + +#define ASSOC_REQ_LEN 154 +#define BLOCK_LIST_NUM 16 +#define VENDOR_SPECIFIC_LEN 128 +#define MAX_BH_PROFILE_CNT 4 + +/* For rssi steering*/ +#define RCPI_TOLLENACE 8 /* 2dB */ + +#define IS_MAP_ENABLE(pAd) \ + (pAd->bMAPEnable == TRUE) + +#define IS_MAP_TURNKEY_ENABLE(pAd) \ + ((pAd->bMAPTurnKeyEnable == TRUE) && (pAd->bMAPEnable == TRUE)) + +typedef enum { + BELOW_THRESHOLD = 0, + ABOVE_THRESHOLD, +} RSSI_STATUS; + +typedef enum { + AGENT_INIT_STEER_DISALLOW = 0, + AGENT_INIT_RSSI_STEER_MANDATE, + AGENT_INIT_RSSI_STEER_ALLOW, +} STEERING_POLICY; + +struct GNU_PACKED map_policy_setting { + unsigned char steer_policy; + unsigned char cu_thr; + unsigned char rcpi_thr; +}; + +#define MAX_PROFILE_CNT 4 +struct scan_SSID { + char ssid[32 + 1]; + unsigned char SsidLen; +}; + +struct GNU_PACKED scan_BH_ssids +{ + unsigned long scan_cookie; + unsigned char scan_channel_count; + unsigned char scan_channel_list[32]; + unsigned char profile_cnt; + struct scan_SSID scan_SSID_val[MAX_PROFILE_CNT]; +}; + +typedef struct _MAP_CONFIG { + /*Support Unassociated STA link metric report on current operating Bss*/ + BOOLEAN bUnAssocStaLinkMetricRptOpBss; + /*Support Unassociated STA link metric report on currently non operating Bss */ + BOOLEAN bUnAssocStaLinkMetricRptNonOpBss; + /*Support Agent-initiated Rssi-based steering */ + BOOLEAN bAgentInitRssiSteering; + UCHAR DevOwnRole; + UCHAR vendor_ie_buf[VENDOR_SPECIFIC_LEN]; + UCHAR vendor_ie_len; + struct scan_BH_ssids scan_bh_ssids; + BOOLEAN FireProbe_on_DFS; +} MAP_CONFIG, *PMAP_CONFIG; + +/* spec v171027 */ +enum MAPRole { + MAP_ROLE_TEARDOWN = 4, + MAP_ROLE_FRONTHAUL_BSS = 5, + MAP_ROLE_BACKHAUL_BSS = 6, + MAP_ROLE_BACKHAUL_STA = 7, +}; + +#define NON_PREF 0 +#define PREF_SCORE_1 BIT(4) +#define PREF_SCORE_2 BIT(5) +#define PREF_SCORE_3 (BIT(4)|BIT(5)) +#define PREF_SCORE_4 BIT(6) +#define PREF_SCORE_5 (BIT(4)|BIT(6)) +#define PREF_SCORE_6 (BIT(5)|BIT(6)) +#define PREF_SCORE_7 (BIT(4)|BIT(5)|BIT(6)) +#define PREF_SCORE_8 (BIT(7)) +#define PREF_SCORE_9 (BIT(4)|BIT(7)) +#define PREF_SCORE_10 (BIT(5)|BIT(7)) +#define PREF_SCORE_11 (BIT(4)|BIT(5)|BIT(6)) +#define PREF_SCORE_12 (BIT(6)|BIT(7)) +#define PREF_SCORE_13 (BIT(4)|BIT(6)|BIT(7)) +#define PREF_SCORE_14 (BIT(5)|BIT(6)|BIT(7)) + +#define UNSPECIFICIED 0 +#define NON80211_INTERFERER_IN_LOCAL_ENV BIT(0) +#define INTRA_NETWORK_80211_OBSS_INTERFERENCE BIT(1) +#define ENTERNAL_NETWORK_80211_OBSS_INTERFERENCE (BIT(0)|BIT(1)) +#define REDUCED_COVERAGE BIT(2) +#define REDUCED_TP (BIT(0)|BIT(2)) +#define INDEVICE_INTERFERER (BIT(1)|BIT(2)) +#define OP_DISALLOWED_DUE_TO_DFS (BIT(0)|BIT(1)|BIT(2)) +#define OP_PREVENT_BACKHAUL_OP (BIT(3)) +#define IMMEDIATE_OP_POSSIBLE_ON_DFS_CHN (BIT(0)|BIT(3)) +#define DFS_CHN_STATE_UNKNOWN (BIT(1)|BIT(3)) + +extern UCHAR multicast_mac_1905[MAC_ADDR_LEN]; + +VOID MAP_Init( + IN PRTMP_ADAPTER pAd, + struct wifi_dev *wdev, + IN IN UCHAR wdev_type +); + +VOID MAP_InsertMapCapIE( + IN PRTMP_ADAPTER pAd, + IN struct wifi_dev *wdev, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen +); + +INT MAP_InsertMapWscAttr( + IN PRTMP_ADAPTER pAd, + IN struct wifi_dev *wdev, + OUT PUCHAR pFrameBuf +); + +BOOLEAN map_check_cap_ie( + IN PEID_STRUCT eid, + OUT unsigned char *cap +); + +UCHAR getNonOpChnNum( + IN PRTMP_ADAPTER pAd, + IN struct wifi_dev *wdev, + IN UCHAR op_class +); + +VOID setNonOpChnList( + IN PRTMP_ADAPTER pAd, + IN struct wifi_dev *wdev, + IN PCHAR nonOpChnList, + IN UCHAR op_class, + IN UCHAR nonOpChnNum +); + +INT map_send_bh_sta_wps_done_event( + IN PRTMP_ADAPTER adapter, + IN struct _MAC_TABLE_ENTRY *mac_entry, + IN BOOLEAN is_ap +); + +VOID map_rssi_status_check( + IN PRTMP_ADAPTER pAd); + +INT ReadMapParameterFromFile( + PRTMP_ADAPTER pAd, + RTMP_STRING *tmpbuf, + RTMP_STRING *pBuffer); + +#ifdef A4_CONN +BOOLEAN map_a4_peer_enable( + IN PRTMP_ADAPTER adapter, + IN struct _MAC_TABLE_ENTRY *entry, + IN BOOLEAN is_ap +); + +BOOLEAN map_a4_peer_disable( + IN PRTMP_ADAPTER adapter, + IN struct _MAC_TABLE_ENTRY *entry, + IN BOOLEAN is_ap +); + +BOOLEAN map_a4_init( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN BOOLEAN is_ap +); + +BOOLEAN map_a4_deinit( + IN PRTMP_ADAPTER adapter, + IN UCHAR if_index, + IN BOOLEAN is_ap +); +#endif /*A4_CONN*/ +BOOLEAN MapNotRequestedChannel(struct wifi_dev *wdev, unsigned char channel); +#endif + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mat.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mat.h new file mode 100644 index 000000000..651c188d0 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mat.h @@ -0,0 +1,211 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + mat.h + + Abstract: + Support AP-Client function. + + Revision History: + Who When What + -------------- ---------- ---------------------------------------------- + Shiang 02-26-2007 created +*/ + +#ifndef _MAT_H_ +#define _MAT_H_ + + + + +/*#if defined(LINUX) || defined (VXWORKS) */ + +/*#else */ +/*Currently support upper layer protocols */ +#ifndef ETH_P_IP +#define ETH_P_IP 0x0800 /* Internet Protocol packet */ +#endif +#ifndef ETH_P_ARP +#define ETH_P_ARP 0x0806 /* Address Resolution packet */ +#endif +#ifndef ETH_P_PPP_DISC +#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ +#endif +#ifndef ETH_P_PPP_SES +#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */ +#endif + +/* ARP protocol HARDWARE identifiers. */ +#ifndef ARPHRD_ETHER +#define ARPHRD_ETHER 1 /* Ethernet 10Mbps */ +#endif + +/* ARP protocol opcodes. */ +#ifndef ARPOP_REQUEST +#define ARPOP_REQUEST 1 /* ARP request */ +#endif +#ifndef ARPOP_REPLY +#define ARPOP_REPLY 2 /* ARP reply */ +#endif + +typedef struct _NET_PRO_ARP_HDR{ + unsigned short ar_hrd; /* format of hardware address */ + unsigned short ar_pro; /* format of protocol address */ + unsigned char ar_hln; /* length of hardware address */ + unsigned char ar_pln; /* length of protocol address */ + unsigned short ar_op; /* ARP opcode (command) */ +} NET_PRO_ARP_HDR; + +typedef struct _NET_PRO_IP_HDR{ +#ifndef RT_BIG_ENDIAN + UCHAR ihl:4, + version:4; +#else + UCHAR version:4, + ihl:4; +#endif + UCHAR tos; + UINT16 tot_len; + UINT16 id; + UINT16 frag_off; + UCHAR ttl; + UCHAR protocol; + UINT16 check; + UINT16 saddr; + UINT32 daddr; +} NET_PRO_IP_HDR; +/*#endif //endif of __LINUX__ */ + +//#ifndef MAT_SUPPORT +//#error "You should define MAT_SUPPORT if you want to compile MAT related functions!" +//#endif + + +/* MAT relate definition */ +#define MAT_MAX_HASH_ENTRY_SUPPORT 64 +#define MAT_TB_ENTRY_AGEOUT_TIME (5 * 60 * OS_HZ) /* 30000, 5min. MAT convert table entry age-out time interval. now set it as 5min. */ + + +/* 802.3 Ethernet related definition */ +#define MAT_ETHER_HDR_LEN 14 /* dstMac(6) + srcMac(6) + protoType(2) */ +#define MAT_VLAN_ETH_HDR_LEN (MAT_ETHER_HDR_LEN + 4) /* 4 for h_vlan_TCI and h_vlan_encapsulated_proto */ + +#define MAT_MAC_ADDR_HASH(Addr) (Addr[0] ^ Addr[1] ^ Addr[2] ^ Addr[3] ^ Addr[4] ^ Addr[5]) +#define MAT_MAC_ADDR_HASH_INDEX(Addr) (MAT_MAC_ADDR_HASH(Addr) % MAT_MAX_HASH_ENTRY_SUPPORT) + +#define isMcastEtherAddr(addr) (addr[0] & 0x1) +#define isBcastEtherAddr(addr) ((addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5])== 0xff) +#define isZeroEtherAddr(addr) (!(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5])) + +#define IS_GROUP_MAC(Addr) ((Addr[0]) & 0x01) +#define IS_UCAST_MAC(addr) (!(isMcastEtherAddr(addr) || isZeroEtherAddr(addr))) /* isUcastMac = !(00:00:00:00:00:00 || mcastMac); */ +#define IS_EQUAL_MAC(a, b) (((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) | (a[4] ^ b[4]) | (a[5] ^ b[5])) == 0) + +#define IS_VLAN_PACKET(pkt) ((((pkt)[12] << 8) | (pkt)[13]) == 0x8100) + +/* IPv4 related definition */ +#define IPMAC_TB_HASH_ENTRY_NUM (MAT_MAX_HASH_ENTRY_SUPPORT+1) /* One entry for broadcast address */ +#define IPMAC_TB_HASH_INDEX_OF_BCAST MAT_MAX_HASH_ENTRY_SUPPORT /* cause hash index start from 0. */ + +#define MAT_IP_ADDR_HASH(Addr) (((Addr>>24)&0xff)^((Addr>>16) & 0xff) ^((Addr>>8) & 0xff) ^ (Addr & 0xff)) +#define MAT_IP_ADDR_HASH_INDEX(Addr) (MAT_IP_ADDR_HASH(Addr) % MAT_MAX_HASH_ENTRY_SUPPORT) + +#define IS_GOOD_IP(IP) (IP!= 0) +#define IS_MULTICAST_IP(IP) (((UINT32)(IP) & 0xf0000000) == 0xe0000000) + +/* IPv6 related definition */ +#define IPV6MAC_TB_HASH_ENTRY_NUM (MAT_MAX_HASH_ENTRY_SUPPORT+1) /* One entry for broadcast address */ +#define IPV6MAC_TB_HASH_INDEX_OF_BCAST MAT_MAX_HASH_ENTRY_SUPPORT /* cause hash index start from 0. */ + +/*We just use byte 10,13,14,15 to calculate the IPv6 hash, because the byte 11,12 usually are 0xff, 0xfe for link-local address. */ +#define MAT_IPV6_ADDR_HASH(Addr) ((Addr[10]&0xff) ^ (Addr[13] & 0xff) ^(Addr[14] & 0xff) ^ (Addr[15] & 0xff)) +#define MAT_IPV6_ADDR_HASH_INDEX(Addr) (MAT_IPV6_ADDR_HASH(Addr) % MAT_MAX_HASH_ENTRY_SUPPORT) + +#define IS_UNSPECIFIED_IPV6_ADDR(_addr) \ + (!((_addr).ipv6_addr32[0] | (_addr).ipv6_addr32[1] | (_addr).ipv6_addr32[2] | (_addr).ipv6_addr32[3])) + +#define IS_LOOPBACK_IPV6_ADDR(_addr) \ + (NdisEqualMemory((UCHAR *)(&((_addr).ipv6_addr[0])), &IPV6_LOOPBACKADDR[0], IPV6_ADDR_LEN)) +#define IS_MULTICAST_IPV6_ADDR(_addr) \ + (((_addr).ipv6_addr[0] & 0xff) == 0xff) + +/* The MAT_TABLE used for MacAddress <-> UpperLayer Address Translation. */ +typedef struct _MAT_TABLE_ +{ + VOID *IPMacTable; /* IPv4 Address, Used for IP, ARP protocol */ + VOID *IPv6MacTable; /* IPv6 Address, Used for IPv6 related protocols */ + VOID *SesMacTable; /* PPPoE Session */ + VOID *UidMacTable; /* PPPoE Discovery */ +}MAT_TABLE, *PMAT_TABLE; + + +typedef enum _MAT_ENGINE_STATUS_ +{ + MAT_ENGINE_STAT_UNKNOWN = 0, + MAT_ENGINE_STAT_INITED = 1, + MAT_ENGINE_STAT_EXITED = 2, +}MAT_ENGINE_STATUS; + + +typedef struct _MAT_STRUCT_ +{ + MAT_ENGINE_STATUS status; + NDIS_SPIN_LOCK MATDBLock; + MAT_TABLE MatTableSet; +#ifdef KMALLOC_BATCH + UCHAR *pMATNodeEntryPoll; +#endif +#ifdef MAC_REPEATER_SUPPORT + BOOLEAN bMACRepeaterEn; +#endif /* MAC_REPEATER_SUPPORT */ + UINT32 nodeCount; /* the number of nodes which connect to Internet via us. */ + VOID *pPriv; +}MAT_STRUCT; + + +typedef struct _MATProtoOps +{ + NDIS_STATUS (*init)(MAT_STRUCT *pMatCfg); + PUCHAR (*tx)(MAT_STRUCT *pMatCfg, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pMacAddr); + PUCHAR (*rx)(MAT_STRUCT *pMatCfg, PNDIS_PACKET pSkb, PUCHAR pLayerHdr, PUCHAR pMacAddr); + NDIS_STATUS (*exit)(MAT_STRUCT *pMatCfg); +}MATProtoOps, *PMATProtoOps; + + +typedef struct _MATProtoTable +{ + USHORT protocol; + MATProtoOps *pHandle; +}MATProtoTable, *PMATProtoTable; + + +VOID dumpPkt(PUCHAR pHeader, int len); + +/*#define KMALLOC_BATCH */ + +PUCHAR MATDBEntryAlloc( + IN MAT_STRUCT *pMatStruct, + IN UINT32 size); + +NDIS_STATUS MATDBEntryFree( + IN MAT_STRUCT *pMatStruct, + IN PUCHAR NodeEntry); + + +#endif /* _MAT_H_ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mbo.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mbo.h new file mode 100644 index 000000000..2d5b6a242 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mbo.h @@ -0,0 +1,296 @@ +#ifndef __MBO_H +#define __MBO_H + +#ifdef MBO_SUPPORT +#include "rtmp_type.h" +#include "rt_config.h" +/* 0xDD */ +#define IE_MBO_ELEMENT_ID 221 +/* spec 0.0.23 - IE LEN is 256 = OUI 4 + ATTR 252 */ +#define MBO_ATTR_MAX_LEN 252 +/* 11v spec define BTM candidate list max len = 2304 */ +#define MBO_NEIGHBOR_REPORT_MAX_LEN 2304 +#define MBO_RRM_SUBID_BSS_TRANSITION_CANDIDATE_PREFERENCE 3 + +#define MBO_OUI_NON_PREFERRED_CHANNEL_REPORT 0x2 +#define MBO_OUI_CELLULAR_DATA_CAPABILITY 0x3 + +/* MBO Country IE Country String field definition */ +#define MBO_AP_USE_GLOBAL_OPERATING_CLASS 0x04 +#define MBO_AP_USE_LOCAL_OPERATING_CLASS 0x20 + +/* MBO Attribute Id List */ +#define MBO_ATTR_AP_CAP_INDCATION 1 +#define MBO_ATTR_STA_NOT_PREFER_CH_REP 2 +/* Cellular Data Capability */ +#define MBO_ATTR_STA_CDC 3 +#define MBO_ATTR_AP_ASSOC_DISALLOW 4 +/* Cellular Data Connection Preference */ +#define MBO_ATTR_AP_CDCP 5 +#define MBO_ATTR_AP_TRANS_REASON 6 +#define MBO_ATTR_STA_TRANS_REJ_REASON 7 +#define MBO_ATTR_AP_ASSOC_RETRY_DELAY 8 +/* Should be updated according to ID list */ +#define MBO_WDEV_ATTR_MAX_NUM 8 +/* enable sta to insert 2nd NPC attr in assoc, +need to mark attr id valid check for test +*/ +#define MBO_ATTR_STA_NOT_PREFER_CH_REP_2ND 99 + +/* MBO_ATTR_AP_CAP_INDCATION field value */ +#define MBO_AP_CAP_NOT_SUPPORT 0x0 +/* indicates supporting MBO */ +#define MBO_AP_CAP_CELLULAR_AWARE 0x40 + +/* MBO_ATTR_AP_ASSOC_DISALLOW Reason field value */ +/* allow assoc , no disallow attr in MBO IE */ +#define MBO_AP_DISALLOW_REASON_RESERVED 0x0 +#define MBO_AP_DISALLOW_REASON_UNSPECIFIED 0x1 +#define MBO_AP_DISALLOW_MAX_STA_NUM_REACHED 0x2 +#define MBO_AP_DISALLOW_AIR_OVERLOADED 0x3 +#define MBO_AP_DISALLOW_AUTH_SERVER_OVERLOADED 0x4 +#define MBO_AP_DISALLOW_RSSI_TOO_LOW 0x5 + +/* MBO_ATTR_AP_CDCP field value */ +#define MBO_AP_CDCP_FORBID_STA_USE_CDC 0x0 +#define MBO_AP_CDCP_PREFER_STA_NOT_USE_CDC 0x1 +/* 255 - prefer cellular data connection */ +#define MBO_AP_CDCP_PREFER_STA_USE_CDC 0xFF + +/* MBO_ATTR_AP_TRANS_REASON field value */ +#define MBO_AP_TRANS_REASON_UNSPECIFIED 0x0 +/* excessive frame loss rate */ +#define MBO_AP_TRANS_REASON_TX_PER_TOO_HIGH 0x1 +#define MBO_AP_TRANS_REASON_TRAFFIC_DELAY 0x2 +#define MBO_AP_TRANS_REASON_INSUFFICIENT_BW 0x3 +#define MBO_AP_TRANS_REASON_LOAD_BALACING 0x4 +#define MBO_AP_TRANS_REASON_RSSI_LOW 0x5 +/* Received excessive number of retransmissions */ +#define MBO_AP_TRANS_REASON_TOO_MANY_RETRY 0x6 +#define MBO_AP_TRANS_REASON_HIGH_INTRFERENCE 0x7 +#define MBO_AP_TRANS_REASON_GRAY_ZONE 0x8 +#define MBO_AP_TRANS_REASON_TO_PREMIUM_AP 0x9 + +#define MAX_NOT_PREFER_CH_NUM 16 +#define MAX_NOT_PREFER_CH_REG_NUM 2 + +/* A default pref value of the auto-populated NR entries */ +#define MBO_AP_DEFAULT_CAND_PREF 255 + +typedef enum { + MBO_FRAME_TYPE_BEACON, + MBO_FRAME_TYPE_PROBE_REQ, + MBO_FRAME_TYPE_PROBE_RSP, + MBO_FRAME_TYPE_ASSOC_REQ, + MBO_FRAME_TYPE_ASSOC_RSP, + MBO_FRAME_TYPE_BTM_REQ, + MBO_FRAME_TYPE_WNM_REQ, +} MBO_FRAME_TYPE, *P_MBO_FRAME_TYPE; + +typedef enum { + MBO_SUCCESS = 0, + MBO_INVALID_ARG, + MBO_RESOURCE_ALLOC_FAIL, + MBO_NOT_INITIALIZED, + MBO_UNEXP, +} MBO_ERR_CODE; + +typedef enum { + MBO_MSG_NEIGHBOR_REPORT = 0, + MBO_MSG_STA_PREF_UPDATE, + MBO_MSG_CDC_UPDATE, + MBO_MSG_STA_STEERING, + MBO_MSG_DISASSOC_STA, + MBO_MSG_AP_TERMINATION, + MBO_MSG_BSSID_UPDATE, + MBO_MSG_REMOVE_STA, +/* MBO_MSG_STA_SEC_INFO_UPDATE, */ +} MBO_MSG_TYPE; + + +typedef enum { + PARAM_MBO_AP_ASSOC_DISALLOW, + PARAM_MBO_AP_CAP, + PARAM_MBO_AP_CDCP, + PARAM_MBO_AP_BSS_TERM, +} MBO_PARAM; + +#define PER_EVENT_LIST_MAX_NUM 10 + +typedef struct GNU_PACKED _DAEMON_NEIGHBOR_REP_INFO +{ + UINT8 Bssid[MAC_ADDR_LEN]; + UINT32 BssidInfo; + UINT8 RegulatoryClass; + UINT8 ChNum; + UINT8 PhyType; + UINT8 CandidatePrefSubID; + UINT8 CandidatePrefSubLen; + UINT8 CandidatePref; + /* extra information */ + UINT32 akm; + UINT32 cipher; +} DAEMON_NEIGHBOR_REP_INFO, *P_DAEMON_NEIGHBOR_REP_INFO; + +typedef struct GNU_PACKED daemon_neighbor_report_list { + UINT8 Newlist; + UINT8 TotalNum; + UINT8 CurrNum; + UINT8 reserved; + DAEMON_NEIGHBOR_REP_INFO EvtNRInfo[PER_EVENT_LIST_MAX_NUM]; +} DAEMON_EVENT_NR_LIST, *P_DAEMON_EVENT_NR_LIST; + +typedef struct GNU_PACKED neighbor_report_msg { + DAEMON_EVENT_NR_LIST evt_nr_list; +} DAEMON_NR_MSG, *P_DAEMON_NR_MSG; + + +typedef struct GNU_PACKED _MBO_EVENT_STA_DISASSOC +{ + UINT8 mac_addr[MAC_ADDR_LEN]; +} MBO_EVENT_STA_DISASSOC, *P_MBO_EVENT_STA_DISASSOC; + +typedef struct GNU_PACKED _MBO_EVENT_STA_AKM_CIPHER +{ + UINT8 mac_addr[MAC_ADDR_LEN]; + UINT32 akm; + UINT32 cipher; +} MBO_EVENT_STA_AKM_CIPHER, *P_MBO_EVENT_STA_AKM_CIPHER; + +typedef struct GNU_PACKED _MBO_EVENT_BSS_TERM +{ + UINT32 TsfLowPart; + UINT32 TsfHighPart; +} MBO_EVENT_BSS_TERM, *P_MBO_EVENT_BSS_TERM; + +typedef union GNU_PACKED _msg_body { + MBO_STA_CH_PREF_CDC_INFO MboEvtStaInfo; + MBO_EVENT_STA_DISASSOC MboEvtStaDisassoc; + MBO_EVENT_BSS_TERM MboEvtBssTermTsf; + /* MBO_EVENT_STA_AKM_CIPHER MboEvtStaSecInfo; */ +} MBO_MSG_BODY; + +typedef struct mbo_msg { + UINT32 ifindex; + UINT8 MboMsgLen; + UINT8 MboMsgType; + MBO_MSG_BODY MboMsgBody; +} MBO_MSG, *P_MBO_MSG; + + + +typedef struct _MBO_ATTR_STRUCT { + UCHAR AttrID; + UCHAR AttrLen; + /* CHAR AttrBody[1]; */ + CHAR AttrBody[MBO_ATTR_MAX_LEN]; +} MBO_ATTR_STRUCT, *P_MBO_ATTR_STRUCT; + + + +#define IS_MBO_ENABLE(_wdev) \ + ((_wdev)->MboCtrl.bMboEnable == TRUE) + +#define VALID_MBO_ATTR_ID(_I) \ + (_I <= MBO_WDEV_ATTR_MAX_NUM) + +#define MBO_AP_ALLOW_ASSOC(_wdev) \ + ((_wdev)->MboCtrl.AssocDisallowReason == MBO_AP_DISALLOW_REASON_RESERVED) + + +VOID MakeMboOceIE( + PRTMP_ADAPTER pAd, + struct wifi_dev *wdev, + PUINT8 pFrameBuf, + PULONG pFrameLen, + UINT8 FrameType); +MBO_ERR_CODE ReadMboParameterFromFile(PRTMP_ADAPTER pAd, + RTMP_STRING *tmpbuf, + RTMP_STRING *pBuffer); + +MBO_ERR_CODE MboInit( + PRTMP_ADAPTER pAd); + +RTMP_STRING *MboAttrValueToString( + UINT8 AttrID, + UINT8 AttrValue); + +RTMP_STRING *MboMsgTypeToString( + MBO_MSG_TYPE MsgType); + + +INT32 ShowMboStatProc( + RTMP_ADAPTER *pAd, + RTMP_STRING *arg); + +INT MboIndicateNeighborReportToDaemon( + PRTMP_ADAPTER pAd, + struct wifi_dev *pWdev, + BOOLEAN AppendMode, + UINT8 ReportNum); + + +INT SetMboNRIndicateProc( + PRTMP_ADAPTER pAd, + RTMP_STRING *arg); + +INT MBO_MsgHandle( + IN PRTMP_ADAPTER pAd, + UINT32 Param, + UINT32 Value); + + +VOID MboBssTermCountDownStart( + UINT8 validity_intvl); + +VOID MboParseStaNPCElement( + PRTMP_ADAPTER pAd, + struct wifi_dev *pWdev, + UCHAR *PktContent, + UINT8 ElementLen, + P_MBO_STA_CH_PREF_CDC_INFO pMboStaCHInfo, + MBO_FRAME_TYPE MboFrameType); + + +INT MboIndicateStaInfoToDaemon( + PRTMP_ADAPTER pAd, + P_MBO_STA_CH_PREF_CDC_INFO pStaInfo, + MBO_MSG_TYPE MsgType); + +VOID MboParseStaMboIE( + PRTMP_ADAPTER pAd, + struct wifi_dev *pWdev, + struct _MAC_TABLE_ENTRY *pEntry, + UCHAR *buf, + UCHAR len, + MBO_FRAME_TYPE MboFrameType); + + +INT MboIndicateStaDisassocToDaemon( + PRTMP_ADAPTER pAd, + P_MBO_EVENT_STA_DISASSOC pStaDisassocInfo, + MBO_MSG_TYPE MsgType); + +VOID MboWaitAllStaGone( + PRTMP_ADAPTER pAd, + INT apidx); + +VOID MboIndicateStaBssidInfo( + PRTMP_ADAPTER pAd, + struct wifi_dev *pWdev, + UCHAR *mac_addr); + +VOID MboIndicateOneNRtoDaemonByBssEntry( + PRTMP_ADAPTER pAd, + struct wifi_dev *pWdev, + BSS_ENTRY *pBssEntry); + +VOID MboBssTermStart( + PRTMP_ADAPTER pAd, + UINT8 countdown); + +VOID MboCheckBssTermination( + PRTMP_ADAPTER pAd); +#endif /* MBO_SUPPORT */ +#endif /* __MBO_H */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/andes_core.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/andes_core.h new file mode 100644 index 000000000..ddd27a9ca --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/andes_core.h @@ -0,0 +1,281 @@ +/* + *************************************************************************** + * 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: + andes_core.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __ANDES_CORE_H__ +#define __ANDES_CORE_H__ + +#include "mcu.h" + +#ifdef LINUX +#ifndef WORKQUEUE_BH +#include +#endif +#endif /* LINUX */ + +#ifdef RLT_MAC +#include "mcu/andes_rlt.h" +#endif + +#ifdef MT_MAC +#include "mcu/andes_mt.h" +#endif + +#include "link_list.h" + +struct _RTMP_ADAPTER; +struct _RXFCE_INFO; +struct _BANK_RF_REG_PAIR; +struct _R_M_W_REG; +struct _RF_R_M_W_REG; + +enum cmd_msg_state { + illegal, + tx_start, + tx_kickout_fail, + tx_timeout_fail, + tx_retransmit, + tx_done, + wait_cmd_out, + wait_cmd_out_and_ack, + wait_ack, + rx_start, + rx_receive_fail, + rx_done, +#ifdef RTMP_SDIO_SUPPORT + tx_sdio_ok, + tx_sdio_fail, +#endif +}; + +enum { + MCU_INIT, + MCU_TX_HALT, + MCU_RX_HALT, +}; + +enum { + CMD_ACK, +}; + +enum cmd_msg_error_type { + error_tx_kickout_fail, + error_tx_timeout_fail, + error_rx_receive_fail, +}; + +/* + * Command response RX Ring selection + */ +enum RX_RING_ID { + RX_RING0, + RX_RING1, +}; + +struct MCU_CTRL { + UINT8 cmd_seq; + ULONG flags; +#ifdef LINUX +#ifndef WORKQUEUE_BH + RTMP_NET_TASK_STRUCT cmd_msg_task; +#else + struct tasklet_struct cmd_msg_task; +#endif +#endif /* LINUX */ + NDIS_SPIN_LOCK txq_lock; + DL_LIST txq; + NDIS_SPIN_LOCK rxq_lock; + DL_LIST rxq; + NDIS_SPIN_LOCK ackq_lock; + DL_LIST ackq; + NDIS_SPIN_LOCK kickq_lock; + DL_LIST kickq; + NDIS_SPIN_LOCK tx_doneq_lock; + DL_LIST tx_doneq; + NDIS_SPIN_LOCK rx_doneq_lock; + DL_LIST rx_doneq; +#ifdef RTMP_SDIO_SUPPORT + NDIS_SPIN_LOCK txq_sdio_lock; + DL_LIST txq_sdio; + UINT32 SDIOPadSize; +#endif + ULONG tx_kickout_fail_count; + ULONG tx_timeout_fail_count; + ULONG rx_receive_fail_count; + ULONG alloc_cmd_msg; + ULONG free_cmd_msg; + BOOLEAN power_on; + BOOLEAN dpd_on; + UINT8 RxStream0, RxStream1; +#ifdef MT_MAC +#define FW_NO_INIT 0 +#define FW_DOWNLOAD 1 +#define FW_RUN_TIME 2 +#define ROM_PATCH_DOWNLOAD 3 + UINT16 Stage; + UINT8 SemStatus; +#endif + struct _RTMP_ADAPTER *ad; +}; + + +struct cmd_msg; +typedef VOID (*MSG_RSP_HANDLER)(struct cmd_msg *msg, char *payload, UINT16 payload_len); +typedef VOID (*MSG_EVENT_HANDLER)(struct _RTMP_ADAPTER *ad, char *payload, UINT16 payload_len); + +struct cmd_msg_cb { + struct cmd_msg *msg; +}; + +#define CMD_MSG_CB(pkt) ((struct cmd_msg_cb *)(GET_OS_PKT_CB(pkt))) +#define CMD_MSG_RETRANSMIT_TIMES 3 +#define CMD_MSG_TIMEOUT 3000 + +struct cmd_msg { + DL_LIST list; + UINT16 pq_id; + UINT8 cmd_type; + UINT8 set_query; + UINT8 ext_cmd_type; + UINT8 seq; + UINT16 timeout; + UINT16 rsp_payload_len; + BOOLEAN need_wait; + BOOLEAN need_rsp; + BOOLEAN need_retransmit; + RTMP_OS_COMPLETION ack_done; + char *rsp_payload; + MSG_RSP_HANDLER rsp_handler; + enum cmd_msg_state state; + VOID *priv; + PNDIS_PACKET net_pkt; + INT retransmit_times; +#ifdef RTMP_SDIO_SUPPORT + RTMP_OS_COMPLETION tx_sdio_done; + UINT16 tx_sdio_timeout; +#endif + UINT32 wcid; /* Index of MacTableEntry */ +}; + +enum BW_SETTING { + BW20 = 1, + BW40 = 2, + BW10 = 4, + BW80 = 8, +}; + +enum mcu_skb_state { + ILLEAGAL = 0, + MCU_CMD_START, + MCU_CMD_DONE, + MCU_RSP_START, + MCU_RSP_DONE, + MCU_RSP_CLEANUP, + UNLINK_START, +}; + +#define CMD_QUERY 0 +#define CMD_SET 1 +#define CMD_NA 3 + +#define EXT_CMD_NA 0 + +#define P1_Q0 0x8000 + +#define USB_END_PADDING 4 +#define SDIO_END_PADDING 4 +#define PATCH_INFO_SIZE 30 + +struct mcu_skb_data { + enum mcu_skb_state state; +}; + +#ifdef LED_CONTROL_SUPPORT +#ifdef RT_BIG_ENDIAN +typedef union _LED_ENHANCE { + struct { + UINT32 rsv:8; + UINT32 on_time:8; + UINT32 off_time:8; + UINT32 idx:8; + } field; + UINT32 word; +} LED_ENHANCE; +#else +typedef union _LED_ENHANCE { + struct { + UINT32 idx:8; + UINT32 off_time:8; + UINT32 on_time:8; + UINT32 rsv:8; + } field; + UINT32 word; +} LED_ENHANCE; +#endif /* RT_BIG_ENDIAN */ +#endif /*LED_CONTROL_SUPPORT*/ + + +VOID AndesCtrlInit(struct _RTMP_ADAPTER *pAd); +VOID AndesCtrlExit(struct _RTMP_ADAPTER *pAd); +INT32 AndesSendCmdMsg(struct _RTMP_ADAPTER *pAd, struct cmd_msg *msg); +BOOLEAN IsInbandCmdProcessing(struct _RTMP_ADAPTER *pAd); +VOID AndesCmdMsgBh(unsigned long param); +INT32 UsbRxCmdMsgSubmit(struct _RTMP_ADAPTER *pAd); +INT32 UsbRxCmdMsgsReceive(struct _RTMP_ADAPTER *pAd); +VOID AndesBhSchedule(struct _RTMP_ADAPTER *pAd); + +struct cmd_msg *AndesAllocCmdMsg(struct _RTMP_ADAPTER *pAd, unsigned int length); + +VOID AndesInitCmdMsg(struct cmd_msg *msg, UINT16 pq_id, UINT8 cmd_type, + UINT8 set_query, UINT8 ExtCmdType, BOOLEAN need_wait, + UINT16 timeout, BOOLEAN need_retransmit, BOOLEAN need_rsp, + UINT16 rsp_payload_len, char *rsp_payload, + MSG_RSP_HANDLER rsp_handler); + +VOID AndesAppendCmdMsg(struct cmd_msg *msg, char *data, unsigned int len); +VOID AndesFreeCmdMsg(struct cmd_msg *msg); +VOID AndesQueueTailCmdMsg(DL_LIST *list, struct cmd_msg *msg, + enum cmd_msg_state state); +VOID AndesIncErrorCount(struct MCU_CTRL *ctl, enum cmd_msg_error_type type); +VOID _AndesUnlinkCmdMsg(struct cmd_msg *msg, DL_LIST *list); +VOID AndesUnlinkCmdMsg(struct cmd_msg *msg, DL_LIST *list); +struct cmd_msg *AndesDequeueCmdMsg(struct MCU_CTRL *ctl, DL_LIST *list); +VOID AndesQueueHeadCmdMsg(DL_LIST *list, struct cmd_msg *msg, + enum cmd_msg_state state); +VOID AndesQueueHeadCmdMsg(DL_LIST *list, struct cmd_msg *msg, + enum cmd_msg_state state); +UINT32 AndesQueueLen(struct MCU_CTRL *ctl, DL_LIST *list); + +#ifdef RTMP_PCI_SUPPORT +VOID PciKickOutCmdMsgComplete(PNDIS_PACKET net_pkt); +#endif + + +#ifdef RTMP_SDIO_SUPPORT +INT32 AndesWaitForSdioCompleteTimeout(struct cmd_msg *msg, long timeout); +#endif +#endif /* __ANDES_CORE_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/andes_mt.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/andes_mt.h new file mode 100644 index 000000000..2a413a391 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/andes_mt.h @@ -0,0 +1,971 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 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: + andes_mt.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __ANDES_MT_H__ +#define __ANDES_MT_H__ + +#include "mcu.h" + +#ifdef LINUX +#ifndef WORKQUEUE_BH +#include +#endif +#endif /* LINUX */ + +struct _RTMP_ADAPTER; +struct cmd_msg; + +#ifdef RT_BIG_ENDIAN +typedef union _FW_TXD_0 { + struct { + UINT32 pq_id:16; + UINT32 length:16; + } field; + UINT32 word; +} FW_TXD_0; +#else +typedef union _FW_TXD_0 { + struct { + UINT32 length:16; + UINT32 pq_id:16; + } field; + UINT32 word; +} FW_TXD_0; +#endif + +#define PKT_ID_CMD 0xA0 +#define PKT_ID_EVENT 0xE000 + +#ifdef RT_BIG_ENDIAN +typedef union _FW_TXD_1 { + struct { + UINT32 seq_num:8; + UINT32 set_query:8; + UINT32 pkt_type_id:8; + UINT32 cid:8; + } field; + UINT32 word; +} FW_TXD_1; +#else +typedef union _FW_TXD_1 { + struct { + UINT32 cid:8; + UINT32 pkt_type_id:8; + UINT32 set_query:8; + UINT32 seq_num:8; + } field; + UINT32 word; +} FW_TXD_1; +#endif + + +#define EXT_CID_OPTION_NEED_ACK 1 +#define EXT_CID_OPTION_NO_NEED_ACK 0 + + +#ifdef RT_BIG_ENDIAN +typedef union _FW_TXD_2 { + struct { + UINT32 ext_cid_option:8; + UINT32 ucD2B2Rev:8; + UINT32 ext_cid:8; + UINT32 ucD2B0Rev:8; + } field; + UINT32 word; +} FW_TXD_2; +#else +typedef union _FW_TXD_2 { + struct { + UINT32 ucD2B0Rev:8; + UINT32 ext_cid:8; + UINT32 ucD2B2Rev:8; + UINT32 ext_cid_option:8; + } field; + UINT32 word; +} FW_TXD_2; +#endif /* RT_BIG_ENDIAN */ + + +/* + * FW TX descriptor + */ +typedef struct GNU_PACKED _FW_TXD_ { + FW_TXD_0 fw_txd_0; + FW_TXD_1 fw_txd_1; + FW_TXD_2 fw_txd_2; + UINT32 au4D3toD7rev[5]; +} FW_TXD; + +/* + * Command type table + */ +enum MT_CMD_TYPE { + MT_TARGET_ADDRESS_LEN_REQ = 0x01, + MT_FW_START_REQ = 0x02, + INIT_CMD_ACCESS_REG = 0x3, + MT_PATCH_START_REQ = 0x05, + MT_PATCH_FINISH_REQ = 0x07, + MT_PATCH_SEM_CONTROL = 0x10, + MT_HIF_LOOPBACK = 0x20, + CMD_CH_PRIVILEGE = 0x20, + CMD_ACCESS_REG = 0xC2, + EXT_CID = 0xED, + MT_FW_SCATTER = 0xEE, + MT_RESTART_DL_REQ = 0xEF, +}; + +/* + * Extension Command + */ +enum EXT_CMD_TYPE { + EXT_CMD_RF_REG_ACCESS = 0x02, + EXT_CMD_RF_TEST = 0x04, + EXT_CMD_RADIO_ON_OFF_CTRL = 0x05, + EXT_CMD_WIFI_RX_DISABLE = 0x06, + EXT_CMD_PM_STATE_CTRL = 0x07, + EXT_CMD_CHANNEL_SWITCH = 0x08, + EXT_CMD_NIC_CAPABILITY = 0x09, + EXT_CMD_PWR_SAVING = 0x0A, + EXT_CMD_MULTIPLE_REG_ACCESS = 0x0E, + EXT_CMD_AP_PWR_SAVING_CAPABILITY = 0xF, + EXT_CMD_SEC_ADDREMOVE_KEY = 0x10, + EXT_CMD_SET_TX_POWER_CTRL=0x11, + EXT_CMD_FW_LOG_2_HOST = 0x13, + EXT_CMD_PS_RETRIEVE_START = 0x14, + EXT_CMD_LED_CTRL=0x17, + EXT_CMD_ID_PACKET_FILTER = 0x18, + EXT_CMD_ID_PWR_MGT_BIT_WIFI = 0x1B, + EXT_CMD_EFUSE_BUFFER_MODE = 0x21, + EXT_CMD_THERMAL_PROTECT = 0x23, + EXT_CMD_ID_EDCA_SET = 0x27, + EXT_CMD_ID_SLOT_TIME_SET = 0x28, + EXT_CMD_ID_CONFIG_INTERNAL_SETTING = 0x29, + EXT_CMD_ID_NOA_OFFLOAD_CTRL = 0x2B, + EXT_CMD_GET_THEMAL_SENSOR=0x2C, + EXT_CMD_ID_WAKEUP_OPTION = 0x2E, + EXT_CMD_ID_AC_QUEUE_CONTROL = 0x31, + EXT_CMD_ID_BCN_UPDATE = 0x33, + EXT_CMD_FLUSH_FRAME_WCID = 0x34 +}; + +/* + * Extension Event + */ +enum EXT_EVENT_TYPE { + EXT_EVENT_CMD_RESULT = 0x0, + EXT_EVENT_RF_REG_ACCESS = 0x2, + EXT_EVENT_MULTI_CR_ACCESS = 0x0E, + EXT_EVENT_FW_LOG_2_HOST = 0x13, + EXT_EVENT_BEACON_LOSS = 0x1A, + EXT_EVENT_THERMAL_PROTECT = 0x22, + EXT_EVENT_BCN_UPDATE = 0x31, +}; + +/* + * DownLoad Type + */ +enum { + DownLoadTypeA, + DownLoadTypeB, +}; + +#ifdef RT_BIG_ENDIAN +typedef union _FW_RXD_0 { + struct { + UINT32 pkt_type_id:16; + UINT32 length:16; + } field; + UINT32 word; +} FW_RXD_0; +#else +typedef union _FW_RXD_0 { + struct { + UINT32 length:16; + UINT32 pkt_type_id:16; + } field; + UINT32 word; +} FW_RXD_0; +#endif /* RT_BIG_ENDIAN */ + +#ifdef RT_BIG_ENDIAN +typedef union _FW_RXD_1 { + struct { + UINT32 rsv:16; + UINT32 seq_num:8; + UINT32 eid:8; + } field; + UINT32 word; +} FW_RXD_1; +#else +typedef union _FW_RXD_1 { + struct { + UINT32 eid:8; + UINT32 seq_num:8; + UINT32 rsv:16; + } field; + UINT32 word; +} FW_RXD_1; +#endif /* RT_BIG_ENDIAN */ + +#ifdef RT_BIG_ENDIAN +typedef union _FW_RXD_2 { + struct { + UINT32 rsv:24; + UINT32 ext_eid:8; + } field; + UINT32 word; +} FW_RXD_2; +#else +typedef union _FW_RXD_2 { + struct { + UINT32 ext_eid:8; + UINT32 rsv:24; + } field; + UINT32 word; +} FW_RXD_2; +#endif /* RT_BIG_ENDIAN */ + +/* + * Event structure + */ +typedef struct GNU_PACKED _EVENT_RXD_ { + FW_RXD_0 fw_rxd_0; + FW_RXD_1 fw_rxd_1; + FW_RXD_2 fw_rxd_2; +} EVENT_RXD; + +/* + * Event type table + */ +enum MT_EVENT_TYPE { + MT_TARGET_ADDRESS_LEN_RSP = 0x01, + MT_FW_START_RSP = 0x01, + MT_PATCH_SEM_RSP = 0x04, + EVENT_CH_PRIVILEGE = 0x18, + EXT_EVENT = 0xED, + MT_RESTART_DL_RSP = 0xEF, +}; + +#define FW_CODE_START_ADDRESS1 0x100000 +#define FW_CODE_START_ADDRESS2 0x000000 +#define ROM_PATCH_START_ADDRESS 0x8C000 + +#define REL_PATCH_SEM 0 +#define GET_PATCH_SEM 1 + +#define ROM_PATCH_START_ADDRESS 0x8C000 + +#define REL_PATCH_SEM 0 +#define GET_PATCH_SEM 1 + +/* + * CMD w/ target address/length data mode + */ +#define TARGET_ADDR_LEN_NO_RSP 0 +#define ENABLE_ENCRY (1 << 0) +#define RESET_SEC_IV (1 << 3) +#define TARGET_ADDR_LEN_NEED_RSP (1 << 31) +#define ENABLE_ENCRY (1 << 0) +#define RESET_SEC_IV (1 << 3) + +/* + * FW feature set + */ +#define FW_FEATURE_SET_ENCRY (1 << 0) +#define FW_FEATURE_SET_KEY_MASK (0x3 << 1) +#define FW_FEATURE_SET_KEY(p) (((p) & 0x03) << 1) +#define FW_FEATURE_RESET_IV (1 << 3) +#define GET_FEATURE_SET_KEY(p) (((p) & FW_FEATURE_SET_KEY_MASK) >> 1) + +/* + * Erro code for target address/length response + */ +enum { + TARGET_ADDRESS_LEN_SUCCESS, +}; + +/* + * Error code for cmd(event) firmware start response + */ +enum { + WIFI_FW_DOWNLOAD_SUCCESS, + WIFI_FW_DOWNLOAD_INVALID_PARAM, + WIFI_FW_DOWNLOAD_INVALID_CRC, + WIFI_FW_DOWNLOAD_DECRYPTION_FAIL, + WIFI_FW_DOWNLOAD_UNKNOWN_CMD, + WIFI_FW_DOWNLOAD_TIMEOUT, +}; + +struct _INIT_CMD_ACCESS_REG { + UINT8 ucSetQuery; + UINT8 aucReserved[3]; + UINT32 u4Address; + UINT32 u4Data; +}; + +#define CMD_CH_PRIV_ACTION_REQ 0 +#define CMD_CH_PRIV_ACTION_ABORT 1 +#define CMD_CH_PRIV_ACTION_BW_REQ 2 + +#define CMD_CH_PRIV_SCO_SCN 0 +#define CMD_CH_PRIV_SCO_SCA 1 +#define CMD_CH_PRIV_SCO_SCB 3 + +#define CMD_CH_PRIV_BAND_G 1 +#define CMD_CH_PRIV_BAND_A 2 + +#define CMD_CH_PRIV_CH_WIDTH_20_40 0 +#define CMD_CH_PRIV_CH_WIDTH_80 1 +#define CMD_CH_PRIV_CH_WIDTH_160 2 +#define CMD_CH_PRIV_CH_WIDTH_80_80 3 + +#define CMD_CH_PRIV_REQ_JOIN 0 +#define CMD_CH_PRIV_REQ_P2P_LISTEN 1 + +typedef struct _EXT_CMD_AC_QUEUE_CONTROL_T +{ + UINT8 ucAction; // 0: stop; 1: flush; 2: start + UINT8 ucBssidIdx; + UINT8 aucReserve[2]; // 4-bytes alignment + UINT32 u4AcQueueMap; +} EXT_CMD_AC_QUEUE_CONTROL_T, *P_EXT_CMD_AC_QUEUE_CONTROL_T; + + +typedef struct _CMD_SEC_ADDREMOVE_KEY_STRUC_T { + UINT8 ucAddRemove; + UINT8 ucTxKey; + UINT8 ucKeyType; + UINT8 ucIsAuthenticator; + UINT8 aucPeerAddr[6]; + UINT8 ucBssIndex; + UINT8 ucAlgorithmId; + UINT8 ucKeyId; + UINT8 ucKeyLen; + UINT8 ucWlanIndex; + UINT8 ucReverved; + UINT8 aucKeyRsc[16]; + UINT8 aucKeyMaterial[32]; +} CMD_SEC_ADDREMOVE_KEY_STRUC_T, *P_CMD_ADDREMOVE_KEY_STRUC_T; + +typedef struct _EVENT_SEC_ADDREMOVE_STRUC_T { + UINT32 u4WlanIdx; + UINT32 u4Status; + UINT32 u4Resv; +} EVENT_SEC_ADDREMOVE_STRUC_T, *P_EVENT_SEC_ADDREMOVE_STRUC_T; + +typedef struct _EXT_CMD_AP_PWS_START_T { + UINT32 u4WlanIdx; + UINT32 u4Resv; + UINT32 u4Resv2; +} EXT_CMD_AP_PWS_START_T, *P_EXT_CMD_AP_PWS_START_T; + + +typedef struct _CMD_AP_PS_CLEAR_STRUC_T { + UINT32 u4WlanIdx; + UINT32 u4Status; + UINT32 u4Resv; +} CMD_AP_PS_CLEAR_STRUC_T, *P_CMD_AP_PS_CLEAR_STRUC_T; + +typedef struct _CMD_CH_PRIVILEGE_T { + UINT8 ucBssIndex; + UINT8 ucTokenID; + UINT8 ucAction; + UINT8 ucPrimaryChannel; + UINT8 ucRfSco; + UINT8 ucRfBand; + UINT8 ucRfChannelWidth; /* To support 80/160MHz bandwidth */ + UINT8 ucRfCenterFreqSeg1; /* To support 80/160MHz bandwidth */ + UINT8 ucRfCenterFreqSeg2; /* To support 80/160MHz bandwidth */ + UINT8 ucReqType; + UINT8 aucReserved[2]; + UINT32 u4MaxInterval; /* In unit of ms */ +} CMD_CH_PRIVILEGE_T, *P_CMD_CH_PRIVILEGE_T; + + +typedef struct _CMD_RF_REG_ACCESS_T { + UINT32 WiFiStream; + UINT32 Address; + UINT32 Data; +} CMD_RF_REG_ACCESS_T; + + +typedef struct _CMD_ACCESS_REG_T { + UINT32 u4Address; + UINT32 u4Data; +} CMD_ACCESS_REG_T; + + +#define WIFI_RADIO_ON 1 +#define WIFI_RADIO_OFF 2 +typedef struct _EXT_CMD_RADIO_ON_OFF_CTRL_T { + UINT8 ucWiFiRadioCtrl; + UINT8 aucReserve[3]; +} EXT_CMD_RADIO_ON_OFF_CTRL_T; + +/* EXT_CMD_RF_TEST */ +/* ACTION */ +#define ACTION_SWITCH_TO_RFTEST 0 /* to switch firmware mode between normal mode or rf test mode */ +#define ACTION_IN_RFTEST 1 +/* OPMODE */ +#define OPERATION_NORMAL_MODE 0 +#define OPERATION_RFTEST_MODE 1 +#define OPERATION_ICAP_OVERLAP 3 + +typedef struct _PARAM_MTK_WIFI_TEST_STRUC_T { + UINT32 u4FuncIndex; + UINT32 u4FuncData; +} PARAM_MTK_WIFI_TEST_STRUC_T, *P_PARAM_MTK_WIFI_TEST_STRUC_T; + +typedef struct _CMD_TEST_CTRL_T { + UINT8 ucAction; + UINT8 ucIcapLen; + UINT8 aucReserved[2]; + union { + UINT32 u4OpMode; + UINT32 u4ChannelFreq; + PARAM_MTK_WIFI_TEST_STRUC_T rRfATInfo; + } u; +} CMD_TEST_CTRL_T, *P_CMD_TEST_CTRL_T; + + +#define WIFI_RX_DISABLE 1 +typedef struct _EXT_CMD_WIFI_RX_DISABLE_T { + UINT8 ucWiFiRxDisableCtrl; + UINT8 aucReserve[3]; +} EXT_CMD_WIFI_RX_DISABLE_T; + + +enum { + PM4 = 0x04, + PM5 = 0x05, + PM6 = 0x06, + PM7 = 0x07, +}; + +enum { + ENTER_PM_STATE = 1, + EXIT_PM_STATE = 2, +}; + + +typedef struct _EXT_CMD_PM_STATE_CTRL_T +{ + UINT8 ucPmNumber; + UINT8 ucPmState; + UINT8 aucBssid[6]; + UINT8 ucDtimPeriod; + UINT8 ucWlanIdx; + UINT16 u2BcnInterval; + UINT32 u4Aid; + UINT32 u4RxFilter; + UINT8 aucReserve0[4]; + UINT32 u4Feature; + UINT8 ucOwnMacIdx; + UINT8 ucWmmIdx; + UINT8 ucBcnLossCount; + UINT8 ucBcnSpDuration; +} EXT_CMD_PM_STATE_CTRL_T, *P_EXT_CMD_PM_STATE_CTRL_T; + +#define SKU_SIZE 21 +typedef struct _EXT_CMD_CHAN_SWITCH_T { + UINT8 ucCtrlCh; + UINT8 ucCentralCh; + UINT8 ucBW; + UINT8 ucTxStreamNum; + UINT8 ucRxStreamNum; + UINT8 aucReserve0[7]; + UINT8 aucTxPowerSKU[SKU_SIZE]; + UINT8 aucReserve1[3]; +} EXT_CMD_CHAN_SWITCH_T, *P_EXT_CMD_CHAN_SWITCH_T; + +typedef struct _EXT_CMD_FLUSH_FRAME_BY_WCID_INFO_T { + UINT8 ucWlanIdx; + UINT8 aucReserve1[3]; +}EXT_CMD_FLUSH_FRAME_BY_WCID_INFO_T; + +typedef struct _EXT_CMD_TX_POWER_CTRL_T { + UINT8 ucCenterChannel; + UINT8 ucTSSIEnable; + UINT8 ucTempCompEnable; + UINT8 aucTargetPower[2]; + UINT8 aucRatePowerDelta[14]; + UINT8 ucBWPowerDelta; + UINT8 aucCHPowerDelta[6]; + UINT8 aucTempCompPower[17]; + UINT8 ucReserved; +} EXT_CMD_TX_POWER_CTRL_T, *P_EXT_CMD_TX_POWER_CTRL_T; + +typedef struct _INIT_EVENT_ACCESS_REG { + UINT32 u4Address; + UINT32 u4Data; +} INIT_EVENT_ACCESS_REG, *P_INIT_EVENT_ACCESS_REG; + +#define EVENT_EXT_CMD_RESULT_SUCCESS 0 +typedef struct _EVENT_EXT_CMD_RESULT_T { + UINT8 ucExTenCID; + UINT8 aucReserve[3]; + UINT32 u4Status; +} EVENT_EXT_CMD_RESULT_T; + +typedef struct _EXT_EVENT_NIC_CAPABILITY_T { + UINT8 aucDateCode[16]; + UINT8 aucVersionCode[12]; +} EXT_EVENT_NIC_CAPABILITY; + +enum { + MAC_CR, + RF_CR, +}; + +typedef struct _CMD_MULTI_CR_ACCESS_T { + UINT32 u4Type; + UINT32 u4Addr; + UINT32 u4Data; +} CMD_MULTI_CR_ACCESS_T; + +typedef struct _EXT_EVENT_MULTI_CR_ACCESS_WR_T { + UINT32 u4Status; + UINT32 u4Resv; + UINT32 u4Resv2; +} EXT_EVENT_MULTI_CR_ACCESS_WR_T; + +typedef struct _EXT_EVENT_MULTI_CR_ACCESS_RD_T { + UINT32 u4Type; + UINT32 u4Addr; + UINT32 u4Data; +} EXT_EVENT_MULTI_CR_ACCESS_RD_T; + +enum { + ANDES_LOG_DISABLE, + ANDES_LOG_TO_UART, + ANDES_LOG_TO_EVENT, +}; + +typedef struct _EXT_CMD_FW_LOG_2_HOST_CTRL_T { + UINT8 ucFwLog2HostCtrl; + UINT8 ucReserve[3]; +} EXT_CMD_FW_LOG_2_HOST_CTRL_T; + +typedef struct _EXT_CMD_NOA_CTRL_T { + UINT8 ucMode0; + UINT8 acuReserved0[3]; + + UINT8 ucMode1; + UINT8 acuReserved1[3]; + + UINT8 ucMode2; + UINT8 acuReserved2[3]; + + UINT8 ucMode3; + UINT8 acuReserved3[3]; +} EXT_CMD_NOA_CTRL_T, *P_EXT_CMD_NOA_CTRL_T; + +typedef struct _CMD_AP_PS_RETRIEVE_T { + UINT32 u4Option; /* 0: AP_PWS enable, 1: redirect disable */ + UINT32 u4Param1; /* for 0: enable/disable. for 1: wlan idx */ + UINT32 u4Resv; +} CMD_AP_PS_RETRIEVE_STRUC_T, *P_CMD_AP_PS_RETRIEVE_STRUC_T; + +typedef struct _EXT_EVENT_AP_PS_RETRIEVE_T { + UINT32 u4Param1; /* for 0: enable/disable. for 1: wlan idx */ + UINT32 u4Resv; + UINT32 u4Resv2; +} EXT_EVENT_AP_PS_RETRIEVE_T, *P_EXT_EVENT_AP_PS_RETRIEVE_T; + + +typedef struct _BIN_CONTENT_T { + UINT16 u2Addr; + UINT8 ucValue; + UINT8 ucReserved; +} BIN_CONTENT_T, *P_BIN_CONTENT_T; + +#define EFUSE_CONTENT_BUFFER_SIZE 0xff +typedef struct _EXT_CMD_EFUSE_BUFFER_MODE_T { +UINT8 ucSourceMode; +UINT8 ucCount; +UINT8 aucReserved[2]; + BIN_CONTENT_T aBinContent[EFUSE_CONTENT_BUFFER_SIZE]; +} EXT_CMD_EFUSE_BUFFER_MODE_T, *P_EXT_CMD_EFUSE_BUFFER_MODE_T; + +typedef enum _EXT_ENUM_PM_FEATURE_T +{ + PM_CMD_FEATURE_PSPOLL_OFFLOAD = 0x00000001, + PM_CMD_FEATURE_PS_TX_REDIRECT = 0x00000002, + PM_CMD_FEATURE_SMART_BCN_SP = 0x00000004 +} EXT_ENUM_PM_FEATURE_T; + +typedef struct _EXT_CMD_PWR_MGT_BIT_T +{ + UINT8 ucWlanIdx; + UINT8 ucPwrMgtBit; + UINT8 aucReserve[2]; +} EXT_CMD_PWR_MGT_BIT_T, *P_EXT_CMD_PWR_MGT_BIT_T; + +typedef struct _EXT_EVENT_BEACON_LOSS_T +{ + UINT8 aucBssid[6]; + UINT8 aucReserves[2]; +} EXT_EVENT_BEACON_LOSS_T, *P_EXT_EVENT_BEACON_LOSS_T; + +enum { + EEPROM_MODE_EFUSE=0, + EEPROM_MODE_BUFFER=1, +}; + +typedef struct _EXT_CMD_GET_SENSOR_RESULT_T { + UINT8 ucActionIdx; + UINT8 aucReserved[3]; +} EXT_CMD_GET_SENSOR_RESULT_T, *P_EXT_CMD_GET_SENSOR_RESULT_T; + +typedef struct _EXT_EVENT_GET_SENSOR_RESULT_T +{ + UINT32 u4SensorResult; + UINT32 u4Reserved; +} EXT_EVENT_GET_SENSOR_RESULT_T, *P_EXT_EVENT_GET_SENSOR_RESULT_T; + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _LED_NMAC_CMD{ + UINT32 rsv:8; + UINT32 CmdID:8; + UINT32 Arg0:8; + UINT32 Arg1:8; +}LED_NMAC_CMD; +#else +typedef struct GNU_PACKED _LED_NMAC_CMD{ + UINT32 Arg1:8; + UINT32 Arg0:8; + UINT32 CmdID:8; + UINT32 rsv:8; +}LED_NMAC_CMD; +#endif /* RT_BIG_ENDIAN */ + +enum { + HIGH_TEMP_THD = 0, + LOW_TEMP_THD = 1, +}; + +typedef struct _EXT_CMD_THERMAL_PROTECT_T { + UINT8 ucHighEnable; + CHAR cHighTempThreshold; + UINT8 ucLowEnable; + CHAR cLowTempThreshold; +} EXT_CMD_THERMAL_PROTECT_T, *P_EXT_CMD_THERMAL_PROTECT_T; + +typedef struct _EXT_EVENT_THERMAL_PROTECT_T { + UINT8 ucHLType; + CHAR cCurrentTemp; + UINT8 aucReserve[2]; +} EXT_EVENT_THERMAL_PROTECT_T, *P_EXT_EVENT_THERMAL_PROTECT_T; + +#define CMD_EDCA_AIFS_BIT 1 << 0 +#define CMD_EDCA_WIN_MIN_BIT 1<<1 +#define CMD_EDCA_WIN_MAX_BIT 1 <<2 +#define CMD_EDCA_TXOP_BIT 1<<3 +#define CMD_EDCA_ALL_BITS CMD_EDCA_AIFS_BIT | CMD_EDCA_WIN_MIN_BIT | CMD_EDCA_WIN_MAX_BIT |CMD_EDCA_TXOP_BIT + +#define CMD_EDCA_AC_MAX 4 + +typedef struct _TX_AC_PARAM_T +{ + UINT8 ucAcNum; + UINT8 ucVaildBit; + UINT8 ucAifs; + UINT8 ucWinMin; + UINT16 u2WinMax; + UINT16 u2Txop; + +}TX_AC_PARAM_T,*P_TX_AC_PARAM_T; + + +typedef struct _CMD_EDCA_SET_T { + + UINT8 ucTotalNum; + UINT8 aucReserve[3]; + TX_AC_PARAM_T rAcParam[CMD_EDCA_AC_MAX]; + +} CMD_EDCA_SET_T, *P_CMD_EDCA_SET_T; + +#ifdef BCN_OFFLOAD_SUPPORT +typedef struct _EXT_CMD_BCN_UPDATE_T { + UINT8 ucHwBssidIdx; + UINT8 ucExtBssidIdx; + UINT8 ucEnable; + UINT8 aucReserved1[1]; + + UINT16 u2BcnPeriod; + UINT8 aucReserved2[2]; + +} CMD_BCN_UPDATE_T, *P_CMD_BCN_UPDATE_T; +#endif + +typedef struct _CMD_SLOT_TIME_SET_T +{ + UINT8 ucSlotTime; + UINT8 ucSifs; + UINT8 ucRifs; + UINT8 ucReserve1; + UINT16 u2Eifs; + UINT16 u2Reserve2; +}CMD_SLOT_TIME_SET_T,*P_CMD_SLOT_TIME_SET_T; + + + +#ifdef MT_WOW_SUPPORT +enum ENUM_PACKETFILTER_TYPE +{ + _ENUM_TYPE_MAGIC = 0, + _ENUM_TYPE_BITMAP = 1, + _ENUM_TYPE_ARPNS = 2, + _ENUM_TYPE_GTK_REKEY = 3, + _ENUM_TYPE_CF = 4, + _ENUM_TYPE_GLOBAL_EN = 5, + _ENUM_TYPE_TCP_SYN = 6, + _ENUM_TYPE_DETECTION_MASK = 7, +}; + +enum ENUM_FUNCTION_SELECT +{ + _ENUM_PF = 0, + _ENUM_GLOBAL_MAGIC = 1, + _ENUM_GLOBAL_BITMAP = 2, + _ENUM_GLOBAL_EAPOL = 3, + _ENUM_GLOBAL_TDLS = 4, + _ENUM_GLOBAL_ARPNS = 5, + _ENUM_GLOBAL_CF = 6, + _ENUM_GLOBAL_MODE = 7, + _ENUM_GLOBAL_BSSID = 8, + _ENUM_GLOBAL_MGMT = 9, + _ENUM_GLOBAL_BMC_DROP = 10, + _ENUM_GLOBAL_UC_DROP = 11, + _ENUM_GLOBAL_ALL_TOMCU = 12, + _ENUM_GLOBAL_WOW_EN = 16, +}; + +enum ENUM_PF_MODE_T +{ + PF_MODE_WHITE_LIST = 0, + PF_MODE_BLACK_LIST = 1, + PF_MODE_NUM +}; + + +typedef struct _CMD_PACKET_FILTER_WAKEUP_OPTION_T { + UINT32 WakeupInterface; + UINT32 GPIONumber; + UINT32 GPIOTimer; + UINT32 GpioParameter; +} CMD_PACKET_FILTER_WAKEUP_OPTION_T, *P_CMD_PACKET_FILTER_WAKEUP_OPTION_T; + +typedef struct _CMD_PACKET_FILTER_GLOBAL_T { + UINT32 PFType; + UINT32 FunctionSelect; + UINT32 Enable; +} CMD_PACKET_FILTER_GLOBAL_T, *P_CMD_PACKET_FILTER_GLOBAL_T; + +typedef struct _CMD_PACKET_FILTER_MAGIC_PACKET_T { + UINT32 PFType; + UINT32 BssidEnable; +} CMD_PACKET_FILTER_MAGIC_PACKET_T, *P_CMD_PACKET_FILTER_MAGIC_PACKET_T; + +typedef struct _CMD_PACKET_FILTER_BITMAP_PATTERN_T { + UINT32 PFType; + UINT32 Index; + UINT32 Enable; + UINT32 BssidEnable; + UINT32 Offset; + UINT32 FeatureBits; + UINT32 Resv; + UINT32 PatternLength; + UINT32 Mask[4]; + UINT32 Pattern[32]; +} CMD_PACKET_FILTER_BITMAP_PATTERN_T, *P_CMD_PACKET_FILTER_BITMAP_PATTERN_T; + +typedef struct _CMD_PACKET_FILTER_ARPNS_T { + UINT32 PFType; + UINT32 IPIndex; + UINT32 Enable; + UINT32 BssidEnable; + UINT32 Offload; + UINT32 Type; + UINT32 FeatureBits; + UINT32 Resv; + UINT32 IPAddress[4]; +} CMD_PACKET_FILTER_ARPNS_T, *P_CMD_PACKET_FILTER_ARPNS_T; + +typedef struct _CMD_PACKET_FILTER_GTK_T { + UINT32 PFType; + UINT32 WPAVersion; + UINT32 PTK[16]; + UINT32 ReplayCounter[2]; + UINT32 PairKeyIndex; + UINT32 GroupKeyIndex; + UINT32 BssidIndex; + UINT32 OwnMacIndex; + UINT32 WmmIndex; + UINT32 Resv1; +} CMD_PACKET_FILTER_GTK_T, *P_CMD_PACKET_FILTER_GTK_T; + +typedef struct _CMD_PACKET_FILTER_COALESCE_T { + UINT32 PFType; + UINT32 FilterID; + UINT32 Enable; + UINT32 BssidEnable; + UINT32 PacketType; + UINT32 CoalesceOP; + UINT32 FeatureBits; + UINT8 Resv; + UINT8 FieldLength; + UINT8 CompareOP; + UINT8 FieldID; + UINT32 Mask[2]; + UINT32 Pattern[4]; +} CMD_PACKET_FILTER_COALESCE_T, *P_CMD_PACKET_FILTER_COALESCE_T; + +typedef struct _CMD_PACKET_TCPSYN_T { + UINT32 PFType; + UINT32 AddressType; + UINT32 Enable; + UINT32 BssidEnable; + UINT32 PacketType; + UINT32 FeatureBits; + UINT32 TCPSrcPort; + UINT32 TCPDstPort; + UINT32 SourceIP[4]; + UINT32 DstIP[4]; +} CMD_PACKET_FILTER_TCPSYN_T, *P_CMD_PACKET_FILTER_TCPSYN_T; + + +typedef struct _EXT_EVENT_PF_GENERAL_T { + UINT32 u4PfCmdType; + UINT32 u4Status; + UINT32 u4Resv; +} EXT_EVENT_PF_GENERAL_T, *P_EXT_EVENT_PF_GENERAL_T; + +typedef struct _EXT_EVENT_WAKEUP_OPTION_T { + UINT32 u4PfCmdType; + UINT32 u4Status; +} EXT_EVENT_WAKEUP_OPTION_T, *P_EXT_EVENT_WAKEUP_OPTION_T; +#endif + +enum { + DPD_CONF = 1, +}; + +#define DPD_OFF 0 +#define DPD_ON 1 + +typedef struct _CMD_CONFIG_INTERNAL_SETTING_T { + UINT8 ucSubOpcode; + UINT8 aucPara[3]; +} CMD_CONFIG_INTERNAL_SETTING_T, *P_CMD_CONFIG_INTERNAL_SETTING_T; + +#define MT_UPLOAD_FW_UNIT (1024 * 4) + +VOID AndesMTFillCmdHeader(struct cmd_msg *msg, PNDIS_PACKET net_pkt); +VOID AndesMTRxEventHandler(struct _RTMP_ADAPTER *pAd, UCHAR *data); +INT32 AndesMTLoadFw(struct _RTMP_ADAPTER *pAd); +INT32 AndesMTEraseFw(struct _RTMP_ADAPTER *pAd); + +#ifdef RTMP_PCI_SUPPORT +INT32 AndesMTPciKickOutCmdMsg(struct _RTMP_ADAPTER *pAd, struct cmd_msg *msg); +VOID AndesMTPciFwInit(struct _RTMP_ADAPTER *pAd); +VOID AndesMTPciFwExit(struct _RTMP_ADAPTER *pAd); +#endif /* RTMP_PCI_SUPPORT */ + + +#ifdef RTMP_SDIO_SUPPORT +INT32 AndesMTSdioKickOutCmdMsg(struct _RTMP_ADAPTER *pAd, struct cmd_msg *msg); +VOID AndesMTSdioFwInit(struct _RTMP_ADAPTER *pAd); +VOID AndesMTSdioFwExit(struct _RTMP_ADAPTER *pAd); +INT32 AndesMTSendCmdMsgToSdio(struct _RTMP_ADAPTER *pAd); +INT32 AndesMTSdioChkCrc(struct _RTMP_ADAPTER *pAd, UINT32 checksum_len); +UINT16 AndesMTSdioGetCrc(struct _RTMP_ADAPTER *pAd); +#endif + +INT32 CmdInitAccessRegWrite(struct _RTMP_ADAPTER *pAd, UINT32 address, UINT32 data); +INT32 CmdInitAccessRegRead(struct _RTMP_ADAPTER *pAd, UINT32 address, UINT32 *data); +INT32 CmdChPrivilege(struct _RTMP_ADAPTER *pAd, UINT8 Action, UINT8 control_chl, UINT8 central_chl, + UINT8 BW, UINT8 TXStream, UINT8 RXStream); +INT32 CmdAccessRegWrite(struct _RTMP_ADAPTER *pAd, UINT32 address, UINT32 data); +INT32 CmdAccessRegRead(struct _RTMP_ADAPTER *pAd, UINT32 address, UINT32 *data); +INT32 CmdRFRegAccessWrite(struct _RTMP_ADAPTER *pAd, UINT32 RFIdx, UINT32 Offset, UINT32 Value); +INT32 CmdRFRegAccessRead(struct _RTMP_ADAPTER *pAd, UINT32 RFIdx, UINT32 Offset, UINT32 *Value); +INT32 CmdRadioOnOffCtrl(struct _RTMP_ADAPTER *pAd, UINT8 On); +INT32 CmdWiFiRxDisable(struct _RTMP_ADAPTER *pAd, UINT RxDisable); +INT32 CmdChannelSwitch(struct _RTMP_ADAPTER *pAd, UINT8 control_chl, UINT8 central_chl, + UINT8 BW, UINT8 TXStream, UINT8 RXStream); +INT32 CmdFlushFrameByWlanIdx(struct _RTMP_ADAPTER *pAd, UINT8 WlanIdx); +INT32 CmdNicCapability(struct _RTMP_ADAPTER *pAd); +INT32 CmdPsRetrieveReq(struct _RTMP_ADAPTER *pAd, UINT32 enable); + +#ifdef MT_PS +INT32 CmdPsRetrieveStartReq(struct _RTMP_ADAPTER *pAd, UINT32 WlanIdx); +INT32 CmdPsClearReq(struct _RTMP_ADAPTER *pAd, UINT32 wlanidx, BOOLEAN p_wait); +VOID AndesPsRetrieveStartRsp(struct _RTMP_ADAPTER *pAd, char *Data, UINT16 Len); +#endif /* MT_PS */ +INT32 CmdSecKeyReq(struct _RTMP_ADAPTER *pAd, UINT8 AddRemove, UINT8 Keytype, UINT8 *pAddr, UINT8 Alg, UINT8 KeyID, UINT8 KeyLen, UINT8 WlanIdx, UINT8 *KeyMaterial); +INT32 CmdRfTest(struct _RTMP_ADAPTER *pAd, UINT8 Action, UINT8 Mode, UINT8 CalItem); +INT32 CmdIcapOverLap(struct _RTMP_ADAPTER *pAd, UINT32 IcapLen); +NDIS_STATUS AndesMTLoadRomPatch(struct _RTMP_ADAPTER *ad); +INT32 CmdMultipleMacRegAccessWrite(struct _RTMP_ADAPTER *pAd, RTMP_REG_PAIR *RegPair, UINT32 Num); +INT32 CmdMultiPleMacRegAccessRead(struct _RTMP_ADAPTER *pAd, RTMP_REG_PAIR *RegPair, UINT32 Num); +INT32 CmdMultipleRfRegAccessWrite(struct _RTMP_ADAPTER *pAd, MT_RF_REG_PAIR *RegPair, UINT32 Num); +INT32 CmdMultiPleRfRegAccessRead(struct _RTMP_ADAPTER *pAd, MT_RF_REG_PAIR *RegPair, UINT32 Num); +INT32 CmdFwLog2Host(struct _RTMP_ADAPTER *pAd, UINT8 FWLog2HostCtrl); +VOID CmdIOWrite32(struct _RTMP_ADAPTER *pAd, UINT32 Offset, UINT32 Value); +VOID CmdIORead32(struct _RTMP_ADAPTER *pAd, UINT32 Offset, UINT32 *Value); +VOID CmdEfusBufferModeSet(struct _RTMP_ADAPTER *pAd); +VOID CmdSetTxPowerCtrl(struct _RTMP_ADAPTER *pAd, UINT8 central_chl); +VOID CmdGetThemalSensorResult(struct _RTMP_ADAPTER *pAd, UINT8 option); +#ifdef LED_CONTROL_SUPPORT +INT AndesLedOP(struct _RTMP_ADAPTER *pAd,UCHAR LedIdx,UCHAR LinkStatus); +INT AndesLedEnhanceOP(struct _RTMP_ADAPTER *pAd,UCHAR LedIdx,UCHAR on_time, UCHAR off_time, UCHAR led_parameter); +#endif /*LED_CONTROL_SUPPORT*/ +INT32 CmdExtPwrMgtBitWifi(struct _RTMP_ADAPTER *pAd, UINT8 ucWlanIdx, UINT8 ucPwrMgtBit, UINT8 ucDirectCall); +INT32 CmdExtPmStateCtrl(struct _RTMP_ADAPTER *pAd, UINT8 ucWlanIdx, UINT8 ucPmNumber, UINT8 ucPmState); + +#ifdef BCN_OFFLOAD_SUPPORT +VOID RT28xx_UpdateBeaconToMcu( + IN struct _RTMP_ADAPTER *pAd, + IN INT apidx, + IN UCHAR HWBssidIdx, + IN BOOLEAN Enable, + IN ULONG FrameLen, + IN ULONG UpdatePos); + +INT32 CmdBcnUpdateSet(struct _RTMP_ADAPTER *pAd, CMD_BCN_UPDATE_T bcn_update); +#endif + +INT32 CmdThermalProtect(struct _RTMP_ADAPTER *ad, UINT8 HighEn, CHAR HighTempTh, UINT8 LowEn, CHAR LowTempTh); +INT32 CmdEdcaParameterSet(struct _RTMP_ADAPTER *pAd, CMD_EDCA_SET_T EdcaParam); +INT32 CmdSlotTimeSet(struct _RTMP_ADAPTER *pAd, UINT8 SlotTime,UINT8 SifsTime,UINT8 RifsTime,UINT16 EifsTime); +INT32 CmdIdConfigInternalSetting(struct _RTMP_ADAPTER *pAd, UINT8 SubOpCode, UINT8 Param); +INT32 CmdACQueue_Control(struct _RTMP_ADAPTER *ad, UINT8 ucation, UINT8 BssidIdx, UINT32 u4AcQueueMap); + +INT32 CmdP2pNoaOffloadCtrl(struct _RTMP_ADAPTER *pAd, UINT8 enable); +#endif /* __ANDES_MT_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/andes_rlt.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/andes_rlt.h new file mode 100644 index 000000000..01be74fce --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/andes_rlt.h @@ -0,0 +1,319 @@ +/* + *************************************************************************** + * 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: + andes_rlt.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __ANDES_RLT_H__ +#define __ANDES_RLT_H__ + +#include "mcu.h" + +#ifndef WORKQUEUE_BH +#include +#endif + +struct _RTMP_ADAPTER; +struct _RXFCE_INFO; +struct _BANK_RF_REG_PAIR; +struct _R_M_W_REG; +struct _RF_R_M_W_REG; +struct cmd_msg; + +#define CPU_CTL 0x0704 +#define CLOCK_CTL 0x0708 +#define RESET_CTL 0x070C +#define INT_LEVEL 0x0718 +#define COM_REG0 0x0730 +#define COM_REG1 0x0734 +#define COM_REG2 0x0738 +#define COM_REG3 0x073C +#define PCIE_REMAP_BASE1 0x0740 +#define PCIE_REMAP_BASE2 0x0744 +#define PCIE_REMAP_BASE3 0x0748 +#define PCIE_REMAP_BASE4 0x074C +#define LED_CTRL 0x0770 +#define LED_TX_BLINK_0 0x0774 +#define LED_TX_BLINK_1 0x0778 +#define LED0_S0 0x077C +#define LED0_S1 0x0780 +#define SEMAPHORE_00 0x07B0 +#define SEMAPHORE_01 0x07B4 +#define SEMAPHORE_02 0x07B8 +#define SEMAPHORE_03 0x07BC + +#define MCU_WAIT_ACK_CMD_THRESHOLD 0x0f +#define MCU_RX_CMD_THRESHOLD 0x0f + + +#ifdef RTMP_MAC_PCI +#define ANDES_FIRMWARE_IMAGE_BASE 0x80000 +#endif /* RTMP_MAC_PCI */ + +#ifdef RT_BIG_ENDIAN +typedef struct GNU_PACKED _TXINFO_NMAC_CMD_PKT{ + UINT32 info_type:2; + UINT32 d_port:3; + UINT32 cmd_type:7; + UINT32 cmd_seq:4; + UINT32 pkt_len:16; +}TXINFO_NMAC_CMD_PKT; +#else +typedef struct GNU_PACKED _TXINFO_NMAC_CMD_PKT { + UINT32 pkt_len:16; + UINT32 cmd_seq:4; + UINT32 cmd_type:7; + UINT32 d_port:3; + UINT32 info_type:2; +}TXINFO_NMAC_CMD_PKT; +#endif /* RT_BIG_ENDIAN */ + +#define UPLOAD_PATCH_UNIT 2048 +#define PATCH_INFO_SIZE 30 +#define FW_INFO_SIZE 32 +#define IV_SIZE 0x40 +#define GET_SEMAPHORE_RETRY_MAX 600 +#define UPLOAD_FW_UNIT 14592 +#define UPLOAD_FW_TIMEOUT 1000 + +/* + * Calibration ID + */ +enum CALIBRATION_ID { + R_CALIBRATION = 1, + RXDCOC_CALIBRATION = 2, + LC_CALIBRATION = 3, + LOFT_CALIBRATION = 4, + TXIQ_CALIBRATION = 5, + BW_CALIBRATION = 6, + DPD_CALIBRATION = 7, + RXIQ_CALIBRATION = 8, + TXDCOC_CALIBRATION = 9, + RX_GROUP_DELAY_CALIBRATION = 10, + TX_GROUP_DELAY_CALIBRATION = 11, + FULL_CALIBRATION_ID = 0xFF, +}; + +enum CALIBRATION_ID_7662 { + R_CALIBRATION_7662 = 1, + TEMP_SENSOR_CALIBRATION_7662, + RXDCOC_CALIBRATION_7662, + RC_CALIBRATION_7662, + SX_LOGEN_CALIBRATION_7662, + LC_CALIBRATION_7662, + TX_LOFT_CALIBRATION_7662, + TXIQ_CALIBRATION_7662, + TSSI_CALIBRATION_7662, + TSSI_COMPENSATION_7662, + DPD_CALIBRATION_7662, + RXIQC_FI_CALIBRATION_7662, + RXIQC_FD_CALIBRATION_7662, +}; + +enum CALIBRATION_TYPE { + FULL_CALIBRATION, + PARTIAL_CALIBRATION, +}; + +enum SWITCH_CHANNEL_STAGE { + NORMAL_OPERATING = 0x01, + SCANNING = 0x02, + TEMPERATURE_CHANGE = 0x04, +}; + +/* + * Function set ID + */ +enum FUN_ID { + Q_SELECT = 1, + BW_SETTING = 2, + USB2_SW_DISCONNECT = 2, + USB3_SW_DISCONNECT = 3, + LOG_FW_DEBUG_MSG = 4, + GET_FW_VERSION = 5, +}; + + +/* + * FW debug message parameters + */ +enum FW_DEBUG_SETTING { + DISABLE_DEBUG_MSG = 0, + DEBUG_MSG_TO_UART, + DEBUG_MSG_TO_HOST, +}; + +enum CR_TYPE { + RF_CR, + BBP_CR, + RF_BBP_CR, + HL_TEMP_CR_UPDATE, +}; + +enum TEMPERATURE_LEVEL_7662 { + NORMAL_TEMP_7662, /* 0~60 */ + LOW_TEMP_7662, /* < 0 */ + HIGH_TEMP_7662, /* > 60 */ +}; + +#define LOAD_CR_MODE_MASK (0xff) +#define LOAD_CR_MODE(p) (((p) & 0xff)) +#define LOAD_CR_TEMP_LEVEL_MASK (0xff << 8) +#define LOAD_CR_TEMP_LEVEL(p) (((p) & 0xff) << 8) +#define LOAD_CR_CHL_MASK (0xff << 16) +#define LOAD_CR_CHL(p) (((p) & 0xff) << 16) + +#define SC_PARAM1_CHL_MASK (0xff) +#define SC_PARAM1_CHL(p) (((p) & 0xff)) +#define SC_PARAM1_SCAN_MASK (0xff << 8) +#define SC_PARAM1_SCAN(p) (((p) & 0xff) << 8) +#define SC_PARAM1_BW_MASK (0xff << 16) +#define SC_PARAM1_BW(p) (((p) & 0xff) << 16) + +#define SC_PARAM2_TR_SETTING_MASK (0xffff) +#define SC_PARAM2_TR_SETTING(p) (((p) & 0xffff)) +#define SC_PARAM2_EXTENSION_CHL_MASK (0xff << 16) +#define SC_PARAM2_EXTENSION_CHL(p) (((p) & 0xff) << 16) + +#define TSSI_PARAM2_SLOPE0_MASK (0xff) +#define TSSI_PARAM2_SLOPE0(p) (((p) & 0xff)) +#define TSSI_PARAM2_SLOPE1_MASK (0xff << 8) +#define TSSI_PARAM2_SLOPE1(p) (((p) & 0xff) << 8) +#define TSSI_PARAM2_OFFSET0_MASK (0xff << 16) +#define TSSI_PARAM2_OFFSET0(p) (((p) & 0xff) << 16) +#define TSSI_PARAM2_OFFSET1_MASK (0xff << 24) +#define TSSI_PARAM2_OFFSET1(p) (((p) & 0xff) << 24) + +/* + * Command type table + */ +enum RLT_CMD_TYPE { + CMD_FUN_SET_OP = 1, + CMD_LOAD_CR, + CMD_BURST_WRITE = 8, + CMD_READ_MODIFY_WRITE, + CMD_RANDOM_READ, + CMD_BURST_READ, + CMD_RANDOM_WRITE = 12, + CMD_LED_MODE_OP = 16, + CMD_POWER_SAVING_OP = 20, + CMD_WOW_CONFIG, + CMD_WOW_QUERY, + CMD_WOW_FEATURE = 24, + CMD_CARRIER_DETECT_OP = 28, + CMD_RADOR_DETECT_OP, + CMD_SWITCH_CHANNEL_OP, + CMD_CALIBRATION_OP, + CMD_BEACON_OP, + CMD_ANTENNA_OP +}; + +/* + * Event type table + */ +enum RLT_EVENT_TYPE { + CMD_DONE, + CMD_ERROR, + CMD_RETRY, + EVENT_PWR_RSP, + EVENT_WOW_RSP, + EVENT_CARRIER_DETECT_RSP, + EVENT_DFS_DETECT_RSP, +}; + +typedef union _ANDES_CALIBRATION_PARAM { + UINT32 generic; +} ANDES_CALIBRATION_PARAM; + +enum CALIBRATION_TEST_TYPE { + CAL_ROBUST_TEST=0, + +}; + +#ifdef RTMP_PCI_SUPPORT +INT32 AndesRltPciLoadRomPatch(struct _RTMP_ADAPTER *pAd); +INT32 AndesRltPciEraseRomPatch(struct _RTMP_ADAPTER *pAd); +INT32 AndesRltPciLoadFw(struct _RTMP_ADAPTER *pAd); +INT32 AndesRltPciEraseFw(struct _RTMP_ADAPTER *pAd); +VOID PciRxCmdMsgComplete(struct _RTMP_ADAPTER *pAd, struct _RXFCE_INFO *fce_info); +VOID AndesRltPciFwInit(struct _RTMP_ADAPTER *pAd); +#endif /* RTMP_PCI_SUPPORT */ +INT32 AndesRltBurstWrite(struct _RTMP_ADAPTER *pAd, UINT32 offset, UINT32 *data, UINT32 cnt); +INT32 AndesRltBurstRead(struct _RTMP_ADAPTER *pAd, UINT32 offset, UINT32 cnt, UINT32 *data); +INT32 AndesRltRandomRead(struct _RTMP_ADAPTER *pAd, RTMP_REG_PAIR *reg_pair, UINT32 num); +INT32 AndesRltRfRandomRead(struct _RTMP_ADAPTER *pAd, struct _BANK_RF_REG_PAIR *reg_pair, UINT32 num); +INT32 AndesRltReadModifyWrite(struct _RTMP_ADAPTER *pAd, struct _R_M_W_REG *reg_pair, UINT32 num); +INT32 AndesRltRfReadModifyWrite(struct _RTMP_ADAPTER *pAd, struct _RF_R_M_W_REG *reg_pair, UINT32 num); +INT32 AndesRltRandomWrite(struct _RTMP_ADAPTER *pAd, RTMP_REG_PAIR *reg_pair, UINT32 num); +INT32 AndesRltRfRandomWrite(struct _RTMP_ADAPTER *pAd, struct _BANK_RF_REG_PAIR *reg_pair, UINT32 num); +#ifdef CONFIG_ANDES_BBP_RANDOM_WRITE_SUPPORT +INT32 AndesBbpRandomWrite(struct _RTMP_ADAPTER *pAd, RTMP_REG_PAIR *reg_pair, UINT32 num); +#endif /* CONFIG_ANDES_BBP_RANDOM_WRITE_SUPPORT */ +INT32 AndesRltScRandomWrite(struct _RTMP_ADAPTER *pAd, CR_REG *table, UINT32 nums, UINT32 flags); +INT32 AndesRltScRfRandomWrite(struct _RTMP_ADAPTER *pAd, BANK_RF_CR_REG *table, UINT32 nums, UINT32 flags); +INT32 AndesRltFunSet(struct _RTMP_ADAPTER *pAd, UINT32 fun_id, UINT32 param); +INT32 AndesRltPwrSaving(struct _RTMP_ADAPTER *pAd, UINT32 op, UINT32 level, + UINT32 listen_interval, UINT32 pre_tbtt_lead_time, + UINT8 tim_byte_offset, UINT8 tim_byte_pattern); +INT32 AndesRltCalibration(struct _RTMP_ADAPTER *pAd, UINT32 cal_id, ANDES_CALIBRATION_PARAM *param); +VOID PciKickOutCmdMsgComplete(PNDIS_PACKET net_pkt); +VOID AndesRltFillCmdHeader(struct cmd_msg *msg, PNDIS_PACKET net_pkt); +INT32 AndesRltPciKickOutCmdMsg(struct _RTMP_ADAPTER *pAd, struct cmd_msg *msg); +INT32 AndesRltLoadCr(struct _RTMP_ADAPTER *pAd, UINT32 cr_type, UINT8 temp_level, UINT8 channel); +INT32 AndesRltSwitchChannel(struct _RTMP_ADAPTER *pAd, u8 channel, BOOLEAN scan, UINT32 bw, UINT32 tx_rx_setting, UINT8 bbp_ch_idx); +struct cmd_msg *andes_alloc_cmd_msg(struct _RTMP_ADAPTER *pAd, UINT32 length); + +VOID AndesRltRxProcessCmdMsg(struct _RTMP_ADAPTER *ad, struct cmd_msg *rx_msg); + +#define MAX_CALIBRATION_WAIT_TIME 100 +#ifdef RTMP_PCI_SUPPORT +#define ANDES_CALIBRATION_START(_pAd) \ +{ \ + UINT32 _value; \ + RTMP_IO_READ32(_pAd, COM_REG0, &_value); \ + _value &= 0x7FFFFFFF; \ + _RTMP_IO_WRITE32(_pAd, COM_REG0, _value); \ +} + + +#define ANDES_WAIT_CALIBRATION_DONE(_pAd) \ +{ \ + UINT32 _value; \ + INT32 _i; \ + RtmpOsMsDelay(1); \ + for ( _i = 0 ; _i < MAX_CALIBRATION_WAIT_TIME; _i ++ ) { \ + RTMP_IO_READ32(_pAd, COM_REG0, &_value); \ + if ( _value & 0x80000000 ) \ + break; \ + RtmpOsMsDelay(5); \ + } \ + if ( _i == MAX_CALIBRATION_WAIT_TIME ) \ + DBGPRINT(RT_DEBUG_ERROR,("ANDES_WAIT_CALIBRATION_DONE timeout!\n")); \ + else \ + DBGPRINT(RT_DEBUG_INFO,("ANDES_WAIT_CALIBRATION_DONE %d\n", _i)); \ +} +#endif /* RTMP_PCI_SUPPORT */ + +#endif /* __ANDES_RLT_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/btcoex.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/btcoex.h new file mode 100644 index 000000000..11feb5680 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/btcoex.h @@ -0,0 +1,344 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + mcu.h + + Abstract: + MCU related information + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __BTCOEX_H__ +#define __BTCOEX_H__ + +struct _RTMP_ADAPTER; +struct _MAC_TABLE_ENTRY; + +/* Woody add for BT COEX*/ +#define BIT0 (1 << 0) +#define BIT1 (1 << 1) +#define BIT2 (1 << 2) +#define BIT3 (1 << 3) +#define BIT4 (1 << 4) +#define BIT5 (1 << 5) +#define BIT6 (1 << 6) +#define BIT7 (1 << 7) +#define BIT8 (1 << 8) +#define BIT9 (1 << 9) +#define BIT10 (1 << 10) +#define BIT11 (1 << 11) +#define BIT12 (1 << 12) +#define BIT13 (1 << 13) +#define BIT14 (1 << 14) +#define BIT15 (1 << 15) +#define BIT16 (1 << 16) +#define BIT17 (1 << 17) +#define BIT18 (1 << 18) +#define BIT19 (1 << 19) +#define BIT20 (1 << 20) +#define BIT21 (1 << 21) +#define BIT22 (1 << 22) +#define BIT23 (1 << 23) +#define BIT24 (1 << 24) +#define BIT25 (1 << 25) +#define BIT26 (1 << 26) +#define BIT27 (1 << 27) +#define BIT28 (1 << 28) +#define BIT29 (1 << 29) +#define BIT30 (1 << 30) +#define BIT31 (1 << 31) + +#define IS_MT76XXBTCOMBO(_pAd) (IS_MT7650(_pAd) || IS_MT7630(_pAd) || IS_MT7662(_pAd)) +// +// Antenna mode (ANT_MODE_XXX) +// +#define ANT_MODE_DUAL (0x01) // Chip is in dual antenna mode +#define ANT_MODE_SINGLE (0x02) // Chip is in single antenna mode + +#define TypeTFSwitch 0x1 +#define TypeProtectionFrame 0x2 +#define TypeAFH 0x3 +#define TypeWiFiStatus 0x4 +#define TypeHostLoopBackTFSwitch 0xFFF1 +#define TypeCoexCCUForceMode 0xFFF2 + +#define COEX_MODE_RESET 0 +#define COEX_MODE_TDD 1 +#define COEX_MODE_HYBRID 2 +#define COEX_MODE_FDD 3 + +#define COEX_OPMODE_STA 1 +#define COEX_OPMODE_AP 2 +#define COEX_OPMODE_GC 3 +#define COEX_OPMODE_GO 4 +#define COEX_OPMODE_BT 5 +#define COEX_OPMODE_AD_HOC 6 + + +#define COEX_BARXSIZE_A2DP 8 +#define COEX_BARXSIZE_SCO_ESCO 2 +#define COEX_BARXSIZE_OPP 32 + + + +#define WLAN_NO_BSSID 0x0 +#define WLAN_Device_OFF 0x1 +#define WLAN_Device_ON 0x2 +#define WLAN_SCANREQEST 0x3 +#define WLAN_SCANDONE 0x4 +#define WLAN_SCANCANCEL 0x5 +#define WLAN_SCAN2GREQUET 0x6 +#define WLAN_SCAN5GREQUET 0x7 +#define WLAN_CONNECTION_START 0x14 +#define WLAN_CONNECTION_COMPLETION 0x15 +#define WLAN_CONNECTION_CANCEL_IND 0x16 +#define WLAN_CONNECTION_JOIN_FAIL 0x17 +#define WLAN_CONNECTION_AUTH_FAIL 0x18 +#define WLAN_CONNECTION_ASSOC_FAIL 0x19 +#define WLAN_DISCONNECT 0x1A +#define WLAN_ROAMING_START 0x1B +#define WLAN_ROAMING_COMPLETE 0x1C +#define WLAN_DeAuthConfirm 0x8 +#define WLAN_AssocRequest 0x9 +#define WLAN_AssocConfirm 0xA +#define WLAN_ReAssocRequest 0xB +#define WLAN_ReAssocConfirm 0xC +#define WLAN_DisAssocRequest 0xD +#define WLAN_INVINCIBLE_REQ 0xF1 +#define WLAN_INVINCIBLE_ABORT 0xF2 +#define WLAN_BEACON_SERVICE_REQ 0xF3 +#define WLAN_BEACON_SERVICE_CONF 0xF4 + +#define fBTSTATUS_BT_DISABLE 0x00000001 +#define fBTSTATUS_BT_INACTIVE 0x00000002 +#define fBTSTATUS_BT_SCANONLY 0x00000004 +#define fBTSTATUS_BT_HOLD 0x00000008 +#define fBTSTATUS_BT_ACTIVE 0x00000010 + +#define BT_STATUS_SET_FLAG(_pAd, _F) ((_pAd)->BTStatusFlags |= (_F)) +#define BT_STATUS_CLEAR_FLAG(_pAd, _F) ((_pAd)->BTStatusFlags &= ~(_F)) +#define BT_STATUS_TEST_FLAG(_pAd, _F) (((_pAd)->BTStatusFlags & (_F)) != 0) + +#define NULLFRAMESPACE 10 +#define COEXNOZEROSHIFT 1 +#define CTSTOSELF 1 +#define CFEND 2 +#define POWERSAVE0 3 +#define POWERSAVE1 4 +#define PROTECTIONFRAMEREADY 1 +#define PROTECTIONFRAMECANCEL 2 + +#define COEX_WIFI_LINK_UP 1 +#define COEX_WIFI_LINK_DOWN 2 + +typedef struct PROTECTION_FRAME_STRUCT { + BOOLEAN Occupied; + ULONG Triggernumber; + ULONG Valid; + ULONG NodeType; + ULONG BssHashID; + ULONG FrameType; +} PROTECTION_FRAME_STRUCT, *PPROTECTION_FRAME_STRUCT; + +typedef struct _COEX_RX_MANUAL_AGC_GAIN { + BOOLEAN bEnable; + BOOLEAN bStopAGC; + CHAR LMthreshold; + CHAR MHthreshold; +} COEX_RX_MANUAL_AGC_GAIN, *PCOEX_RX_MANUAL_AGC_GAIN; + +typedef struct _COEX_MODE_STRUCTURE { + BOOLEAN bForce; + BOOLEAN FDDRequest; + BOOLEAN TDDRequest; + ULONG TDD_Power; + ULONG FDD_Power; + ULONG DefaultMode; + ULONG CurrentMode; + ULONG UpdateMode; + CHAR CoexTDDRSSITreshold; + CHAR CoexFDDRSSITreshold; + UCHAR RxBAWinLimit; /* 0 = not set, use original value */ + UCHAR TxBAWinLimit; /* 0 = not set, use origianl value */ +} COEX_MODE_STRUCTURE, *PCOEX_MODE_STRUCTURE; + + +typedef struct _COEX_PROTECTION_FRAME_INFO +{ + ULONG CoexOperation; + ULONG Triggernumber; + ULONG Valid; + ULONG NodeType; + ULONG BssHashID; + ULONG FrameType; +} COEX_PROTECTION_FRAME_INFO, *PCOEX_PROTECTION_FRAME_INFO; + +typedef struct _COEX_AFH +{ + ULONG CoexOperation; + ULONG LinkStatus; + ULONG BW; + ULONG Channel; + ULONG BssHashID; + } COEX_AFH, *PCOEX_AFH; + +typedef struct _COEX_TF_SWITCH +{ + ULONG CoexOperation; + ULONG CoexMode; + + } COEX_TF_SWITCH, *PCOEX_TF_SWITCH; + + +typedef struct _COEX_WLAN_STATUS +{ + ULONG CoexOperation; + ULONG WLANStatus; + ULONG PrivilegeTime; + ULONG BssHashID; + + } COEX_WLAN_STATUS, *PCOEX_WLAN_STATUS; + +#define PKT_CMD_TYPE_COEX_OP (17) + +#define BTCOEX_BB_BITWISE_WRITE(_BbReg, _BitLocation, _BitValue) \ + (_BbReg = (((_BbReg) & ~(_BitLocation)) | (_BitValue))) + +#define BTCOEX_BB_BITMASK_READ(_BbReg, _BitLocation) \ + ((_BbReg) & (_BitLocation)) + +#define MAC_BITWISE_WRITE(_MacReg, _BitLocation, _BitValue) \ + (_MacReg = (((_MacReg) & ~(_BitLocation)) | (_BitValue))) + +#define MAC_BITMASK_READ(_MacReg, _BitLocation) \ + ((_MacReg) & (_BitLocation)) + +#define BT_STATUS_SET_FLAG(_pAd, _F) ((_pAd)->BTStatusFlags |= (_F)) +#define BT_STATUS_CLEAR_FLAG(_pAd, _F) ((_pAd)->BTStatusFlags &= ~(_F)) +#define BT_STATUS_TEST_FLAG(_pAd, _F) (((_pAd)->BTStatusFlags & (_F)) != 0) + +typedef union _BT_STATUS_REPORT_STRUC { + struct { + ULONG BT_DISABLE:1; + ULONG BT_INACTIVE:1; + ULONG BT_SCANONLY:1; + ULONG BT_HOLD:1; + ULONG BT_ACTIVE:1; + ULONG RESERVE1:3; + ULONG BT_TRANSPORT:5; + ULONG RESERVE2:3; + ULONG BT_LINK_CNT:3; + ULONG BLE_LINK_CNT:2; + ULONG RESERVE3:3; + ULONG BT_SLAVE_IND:7; + ULONG RESERVE4:1; + } field; + ULONG word; +} BT_STATUS_REPORT_STRUC, *PBT_STATUS_REPORT_STRUC; + +VOID BtAFHCtl( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR BBPCurrentBW, + IN UCHAR Channel, + IN UCHAR CentralChannel, + IN BOOLEAN Disable); + +VOID TDDFDDExclusiveRequest(IN struct _RTMP_ADAPTER *pAd, UCHAR CoexMode); + +VOID EstablishFrameBundle( + IN struct _RTMP_ADAPTER *pAd, + IN PUCHAR pAddr, + IN ULONG OPMode, + IN struct _MAC_TABLE_ENTRY *pEntry +); + +VOID UpdateAndesNullFrameSpace( + IN struct _RTMP_ADAPTER *pAd); + +VOID InvalidProtectionFrameSpace( + IN struct _RTMP_ADAPTER *pAd, + IN PUCHAR pAddr +); + +VOID RemoveProtectionFrameSpace( + IN struct _RTMP_ADAPTER *pAd, + IN PUCHAR pAddr +); + +VOID TDDFDDCoexBACapability( + IN struct _RTMP_ADAPTER *pAd, + UCHAR CoexMode ); + +VOID SendAndesTFSWITCH( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR CoexMode + ); + +VOID CoexFDDRXAGCGain( + IN struct _RTMP_ADAPTER *pAd, + IN CHAR rssi); + +VOID CoexTDDRXAGCGain(IN struct _RTMP_ADAPTER *pAd); + +VOID SendAndesWLANStatus( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR WlanStatus, + IN ULONG PrivilegeTime, + IN ULONG BssHashID + ); + +VOID InitBTCoexistence( + IN struct _RTMP_ADAPTER *pAd); + +VOID SendAndesAFH( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR BBPCurrentBW, + IN UCHAR Channel, + IN UCHAR CentralChannel, + IN BOOLEAN Disable, + IN ULONG BssHashID); + + +VOID MLMEHook( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR WlanStatus, + IN ULONG BssHashID + ); + +VOID CoexistencePeriodicRoutine( + IN struct _RTMP_ADAPTER *pAd + ); + +VOID COEXLinkDown( + IN struct _RTMP_ADAPTER *pAd, + PUCHAR pAddr +); + +ULONG QueryHashID( + IN struct _RTMP_ADAPTER *pAd, + PUCHAR pAddr, + BOOLEAN RemoveBSS); + +VOID CoexParseBTStatus( + IN PRTMP_ADAPTER pAd + ) ; + +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mcu.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mcu.h new file mode 100644 index 000000000..47aa85df9 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mcu.h @@ -0,0 +1,66 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + mcu.h + + Abstract: + MCU related information + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __MCU_H__ +#define __MCU_H__ + +enum MCU_TYPE { + SWMCU, + M8051, + ANDES, +}; + +/* + * Power opration + */ +enum PWR_OP { + RADIO_OFF = 0x30, + RADIO_ON, + RADIO_OFF_AUTO_WAKEUP, + RADIO_OFF_ADVANCE, + RADIO_ON_ADVANCE, +}; + +/* + * Load code method + */ +enum LOAD_CODE_METHOD { + HEADER_METHOD, + BIN_FILE_METHOD, +}; + +struct _RTMP_ADAPTER; + +VOID ChipOpsMCUHook(struct _RTMP_ADAPTER *pAd, enum MCU_TYPE MCUType); +VOID MCUCtrlInit(struct _RTMP_ADAPTER *pAd); +VOID MCUCtrlExit(struct _RTMP_ADAPTER *pAd); + +INT32 MCUSysInit(struct _RTMP_ADAPTER *pAd); +INT32 MCUSysExit(struct _RTMP_ADAPTER *pAd); + +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7601_firmware.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7601_firmware.h new file mode 100644 index 000000000..15805845e --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7601_firmware.h @@ -0,0 +1,2945 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR MT7601_FirmwareImage[] = { +0x98, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x76, 0x00, 0x01, 0x41, 0x76, 0x08, 0x02, +0x32, 0x30, 0x31, 0x33, 0x30, 0x38, 0x32, 0x32, 0x32, 0x31, 0x35, 0x33, 0x5f, 0x5f, 0x5f, 0x5f, +0x48, 0x00, 0x00, 0x52, 0x48, 0x00, 0x00, 0x1e, 0x48, 0x00, 0x00, 0x1c, 0x48, 0x00, 0x00, 0x1a, +0x48, 0x00, 0x00, 0x18, 0x48, 0x00, 0x00, 0x16, 0x48, 0x00, 0x00, 0x14, 0x48, 0x00, 0x00, 0x12, +0x48, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x0e, 0x48, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x0a, +0x48, 0x00, 0x00, 0x08, 0x48, 0x00, 0x00, 0x06, 0x48, 0x00, 0x00, 0x04, 0x48, 0x00, 0x00, 0x02, +0x92, 0x00, 0x48, 0x00, 0x00, 0x00, 0x92, 0x00, 0x3a, 0x0f, 0xab, 0xbc, 0x3a, 0xff, 0xbc, 0x3c, +0x64, 0x62, 0x04, 0x02, 0x64, 0x72, 0xa4, 0x02, 0x64, 0x82, 0x00, 0x02, 0x3a, 0x6f, 0xa0, 0x3c, +0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x07, 0xa8, 0xb4, 0x00, 0x15, 0xf0, 0x00, 0x00, 0x46, 0x10, +0x00, 0x05, 0x58, 0x10, 0x8d, 0xbc, 0xdd, 0x21, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x07, 0xa8, +0xb4, 0x00, 0x05, 0xf0, 0x00, 0x00, 0x3a, 0x6f, 0xa0, 0x04, 0x64, 0x62, 0x04, 0x03, 0x64, 0x72, +0xa4, 0x03, 0x64, 0x82, 0x00, 0x03, 0x3a, 0xff, 0xbc, 0x04, 0x3a, 0x0f, 0xab, 0x84, 0x64, 0x00, +0x00, 0x04, 0x92, 0x00, 0x84, 0x0a, 0x64, 0x02, 0x00, 0x03, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, +0x02, 0x00, 0x44, 0x10, 0x04, 0x01, 0xa8, 0x41, 0x84, 0x00, 0x64, 0x02, 0x24, 0x03, 0x46, 0x0c, +0x00, 0x00, 0x58, 0x00, 0x00, 0x02, 0x64, 0x03, 0x00, 0x03, 0x47, 0xf0, 0x00, 0x0f, 0x59, 0xff, +0x8f, 0x00, 0x46, 0x00, 0x00, 0x0a, 0x58, 0x00, 0x0d, 0x30, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, +0x85, 0x30, 0x84, 0x40, 0xd5, 0x02, 0xaa, 0x81, 0x4c, 0x10, 0x7f, 0xff, 0x46, 0x00, 0x00, 0x0b, +0x58, 0x00, 0x07, 0xa0, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x88, 0x0c, 0x84, 0x40, 0xd5, 0x02, +0xaa, 0x81, 0x4c, 0x10, 0x7f, 0xff, 0x48, 0x00, 0x2d, 0xd5, 0x92, 0x00, 0x84, 0x80, 0xa8, 0xc5, +0xa9, 0x01, 0xa8, 0x46, 0xa8, 0x84, 0xb6, 0x80, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0xb4, 0x20, 0xc1, 0x17, 0xa1, 0x41, 0x84, 0x80, 0xa9, 0x49, 0xb6, 0x25, 0xb6, 0x80, +0xa9, 0x01, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0x90, 0xa0, 0xc2, 0xb4, 0x20, 0x9e, 0x99, +0xa8, 0x82, 0x4c, 0x10, 0x40, 0x08, 0xa0, 0x0b, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x82, 0xc4, +0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, +0xef, 0xfc, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x27, 0x81, 0x27, 0x80, 0xe0, 0xc2, 0x11, 0x80, 0x02, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, +0x81, 0x27, 0x80, 0x27, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x83, 0x4c, 0xdd, 0x2f, 0xec, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x82, 0x64, 0xdd, 0x2f, 0x46, 0x17, 0xff, 0xff, 0x58, 0x10, 0x8f, 0xff, +0x46, 0x20, 0x00, 0x0e, 0x58, 0x21, 0x04, 0x90, 0x81, 0x00, 0x40, 0xa0, 0x04, 0x00, 0x44, 0x00, +0xea, 0x60, 0x14, 0xa1, 0x00, 0x04, 0x80, 0xe2, 0xb4, 0xc2, 0x41, 0xc4, 0x00, 0x00, 0xd5, 0x2e, +0xa0, 0x32, 0x40, 0x34, 0x00, 0x01, 0x4e, 0x35, 0x00, 0x21, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x00, +0x58, 0xf7, 0x81, 0x1c, 0xdd, 0x2f, 0xa4, 0x36, 0xc0, 0x10, 0x9e, 0x01, 0xac, 0x36, 0x15, 0xc3, +0x00, 0x02, 0x05, 0xe3, 0x80, 0x01, 0xa9, 0xb9, 0xb6, 0xe6, 0x15, 0xe3, 0x00, 0x01, 0xb6, 0xde, +0xa1, 0x7a, 0x9d, 0x29, 0xa9, 0x3a, 0xd5, 0x06, 0xa0, 0xb6, 0xc2, 0x04, 0xa0, 0x75, 0xa0, 0x34, +0xdd, 0x22, 0x14, 0xa3, 0x80, 0x04, 0xd5, 0x09, 0xa0, 0xbc, 0x40, 0x90, 0x08, 0x01, 0x4e, 0x95, +0x00, 0x03, 0xd5, 0x02, 0xa8, 0x3c, 0x81, 0x26, 0xb4, 0xc9, 0x46, 0x90, 0x00, 0x0e, 0x58, 0x94, +0x84, 0x90, 0x4c, 0x64, 0xff, 0xcf, 0xb4, 0xa6, 0xd6, 0x09, 0xa0, 0xf4, 0x40, 0x01, 0xa0, 0x01, +0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x81, 0x5c, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x80, 0xe1, 0x44, 0x10, 0xea, 0x60, +0x80, 0xc0, 0xe2, 0x27, 0xe8, 0x0e, 0x40, 0x03, 0x84, 0x57, 0x44, 0x2f, 0x15, 0xa0, 0x96, 0x01, +0x42, 0x70, 0x08, 0x73, 0xac, 0x36, 0xcf, 0x07, 0x9e, 0xc1, 0xac, 0xf6, 0x80, 0xe1, 0xd5, 0x03, +0x84, 0x20, 0xac, 0x46, 0x46, 0x80, 0x00, 0x0e, 0x58, 0x84, 0x04, 0x90, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x82, 0x64, 0xdd, 0x2f, 0xb4, 0x88, 0x40, 0x90, 0x1c, 0x00, 0x4c, 0x44, 0x00, 0x08, +0x05, 0xe4, 0x00, 0x04, 0x40, 0x54, 0xf8, 0x01, 0x4e, 0x54, 0x00, 0x0c, 0x46, 0xf0, 0x00, 0x0e, +0x14, 0x97, 0x81, 0x28, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x81, 0x5c, 0xdd, 0x2f, +0xb4, 0x06, 0x14, 0x93, 0x00, 0x02, 0xc8, 0x0f, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x47, 0x81, 0x25, +0x14, 0x64, 0x00, 0x01, 0xb7, 0x06, 0xa9, 0x31, 0xb6, 0xc4, 0x04, 0x14, 0x00, 0x02, 0x9c, 0xc9, +0x14, 0x34, 0x00, 0x02, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, +0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x04, 0x90, 0xa0, 0x33, 0x84, 0x20, 0xa8, 0x72, 0xb6, 0xc6, +0xa9, 0xb1, 0xc8, 0x08, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0x54, 0xdd, 0x2f, 0xa8, 0x33, +0xd5, 0x06, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x80, 0xc0, 0x50, 0x0f, 0x80, 0x04, +0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0x3c, 0xdd, 0x2f, 0xa0, 0x32, 0xc8, 0x02, 0xd5, 0x09, +0x9e, 0x01, 0xa8, 0x32, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8f, 0xc4, 0xdd, 0x2f, +0x80, 0xc0, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0x50, 0xdd, 0x2f, 0x80, 0x06, +0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x80, 0xc0, +0x50, 0x0f, 0x80, 0x04, 0x80, 0xe1, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0x3c, 0xdd, 0x2f, +0xa0, 0xb2, 0x80, 0x06, 0x9c, 0x51, 0xa8, 0x72, 0x80, 0x27, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, +0x8f, 0xb8, 0xdd, 0x2f, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0x50, 0xdd, 0x2f, +0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x04, 0xa4, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8f, 0xb0, 0xdd, 0x2f, 0x46, 0x70, +0x00, 0x0b, 0x58, 0x73, 0x87, 0xc0, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x01, 0xf0, 0x46, 0x80, +0x00, 0x00, 0x58, 0x84, 0x03, 0x68, 0xa9, 0xf2, 0x80, 0x26, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, +0x04, 0xa4, 0x4b, 0xe0, 0x20, 0x01, 0x50, 0x73, 0x86, 0x40, 0x46, 0x50, 0x00, 0x0d, 0x58, 0x52, +0x8d, 0x40, 0x8c, 0xd8, 0xdf, 0xf1, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0xb4, 0x46, 0xf0, +0x00, 0x05, 0x58, 0xf7, 0x8f, 0xb0, 0xdd, 0x2f, 0x46, 0x70, 0x00, 0x0d, 0x58, 0x73, 0x8d, 0x40, +0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x02, 0x80, 0x46, 0x80, 0x00, 0x00, 0x58, 0x84, 0x03, 0x68, +0xa9, 0xf2, 0x80, 0x26, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0xb4, 0x4b, 0xe0, 0x20, 0x01, +0x50, 0x73, 0x80, 0xc8, 0x46, 0x50, 0x00, 0x0e, 0x58, 0x52, 0x81, 0xf0, 0x8c, 0xd8, 0xdf, 0xf1, +0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x30, 0x04, 0x00, +0xb4, 0x43, 0x44, 0x50, 0x76, 0x10, 0x40, 0x01, 0x40, 0x09, 0xd8, 0x07, 0x83, 0xc3, 0x04, 0x5f, +0x00, 0x41, 0x42, 0x42, 0xd0, 0x0b, 0xc4, 0x0f, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x83, 0x44, +0xdd, 0x2f, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x07, 0x87, 0xb4, 0x46, 0xf0, 0x00, 0x0b, +0x10, 0x07, 0x87, 0xb3, 0x46, 0x60, 0x00, 0x03, 0x58, 0x63, 0x05, 0x24, 0x44, 0x00, 0x00, 0x10, +0x46, 0x10, 0x00, 0x03, 0x58, 0x10, 0x87, 0x64, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x11, 0x46, 0x10, +0x00, 0x03, 0x58, 0x10, 0x87, 0x74, 0xdd, 0x26, 0x84, 0x00, 0x46, 0x10, 0x00, 0x03, 0x58, 0x10, +0x87, 0x84, 0xdd, 0x26, 0x84, 0x01, 0x46, 0x10, 0x00, 0x03, 0x58, 0x10, 0x87, 0x94, 0xdd, 0x26, +0x44, 0x00, 0x00, 0x19, 0x46, 0x10, 0x00, 0x03, 0x58, 0x10, 0x87, 0xa4, 0xdd, 0x26, 0x46, 0x10, +0x00, 0x03, 0x58, 0x10, 0x88, 0xa0, 0x44, 0x00, 0x00, 0x18, 0xdd, 0x26, 0x46, 0xf0, 0x00, 0x00, +0x58, 0xf7, 0x83, 0xa8, 0xdd, 0x2f, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0xc4, 0x46, 0xf0, +0x00, 0x03, 0x58, 0xf7, 0x86, 0x70, 0xdd, 0x2f, 0x84, 0xc0, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, +0x8f, 0x74, 0xdd, 0x2f, 0x46, 0x30, 0x00, 0x0e, 0x58, 0x31, 0x84, 0xc4, 0x84, 0x80, 0x10, 0x41, +0x82, 0xac, 0x14, 0x61, 0x80, 0x2d, 0x50, 0x01, 0x82, 0xae, 0x80, 0x26, 0x84, 0x48, 0x46, 0xf0, +0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0x46, 0x30, 0x04, 0x10, 0x58, 0x31, 0x88, 0x00, +0xa9, 0x9c, 0x46, 0x00, 0x30, 0x00, 0xa1, 0x5b, 0x40, 0x42, 0x80, 0x04, 0xa9, 0x1b, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0x3c, 0x96, 0x00, 0x96, 0x48, 0x95, 0x82, 0x99, 0x71, +0x44, 0x32, 0x0d, 0x60, 0x99, 0x2b, 0x00, 0x31, 0x00, 0x40, 0x95, 0x25, 0x84, 0xa0, 0x38, 0x71, +0x14, 0x00, 0x99, 0xac, 0xaf, 0xf0, 0x9d, 0x69, 0x44, 0x70, 0x00, 0x10, 0xdf, 0xf9, 0x9b, 0x94, +0x50, 0x52, 0x00, 0x18, 0x50, 0x22, 0x00, 0x10, 0x38, 0x73, 0x08, 0x00, 0x18, 0x71, 0x00, 0x01, +0xda, 0xfc, 0x50, 0x42, 0x00, 0x20, 0x38, 0x23, 0x14, 0x00, 0x18, 0x22, 0x80, 0x01, 0xdc, 0xfc, +0x46, 0x40, 0x01, 0x06, 0x40, 0x20, 0x04, 0x09, 0x58, 0x42, 0x0c, 0x00, 0x99, 0x54, 0x94, 0xaa, +0x97, 0x04, 0xb4, 0x02, 0xcc, 0x1d, 0xc9, 0x05, 0x54, 0x31, 0x80, 0x0f, 0x84, 0xd0, 0xd5, 0x39, +0x84, 0xa1, 0xd9, 0x07, 0x54, 0x11, 0x80, 0x0f, 0x94, 0xcc, 0x44, 0x6f, 0xff, 0x0f, 0xd5, 0x31, +0x84, 0x82, 0x54, 0x31, 0x80, 0x0f, 0x4c, 0x12, 0x40, 0x07, 0x40, 0x31, 0xa0, 0x08, 0x44, 0x6f, +0xf0, 0xff, 0xd5, 0x27, 0x40, 0x31, 0xb0, 0x08, 0x44, 0x1f, 0x0f, 0xff, 0xd5, 0x2b, 0xc9, 0x0c, +0x46, 0x5f, 0xff, 0x0f, 0x54, 0x31, 0x80, 0x0f, 0x58, 0x52, 0x8f, 0xff, 0x40, 0x31, 0xc0, 0x08, +0x40, 0x00, 0x14, 0x02, 0xd5, 0x21, 0x84, 0xa1, 0xd9, 0x0a, 0x54, 0x11, 0x80, 0x0f, 0x40, 0x30, +0xd0, 0x08, 0x46, 0x1f, 0xf0, 0xff, 0x58, 0x10, 0x8f, 0xff, 0xd5, 0x14, 0x84, 0xa2, 0xd9, 0x0c, +0x54, 0x61, 0x80, 0x0f, 0x40, 0x33, 0x60, 0x08, 0x46, 0x6f, 0x0f, 0xff, 0x58, 0x63, 0x0f, 0xff, +0x40, 0x00, 0x18, 0x02, 0xd5, 0x09, 0x46, 0x10, 0xff, 0xff, 0x40, 0x31, 0xf0, 0x08, 0x58, 0x10, +0x8f, 0xff, 0x40, 0x00, 0x04, 0x02, 0x40, 0x00, 0x0c, 0x04, 0xb6, 0x02, 0x3a, 0x6f, 0x9c, 0x04, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x02, 0x10, 0x00, 0x0a, 0xa1, 0x84, +0x5c, 0xf0, 0x80, 0x66, 0xe9, 0x2a, 0x51, 0xc0, 0xff, 0x9a, 0x84, 0xe0, 0x46, 0xa0, 0x01, 0x02, +0x58, 0xa5, 0x06, 0xd4, 0x80, 0x06, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x86, 0x64, 0x84, 0x46, +0x4b, 0xe0, 0x28, 0x01, 0xc8, 0x15, 0x81, 0x20, 0x50, 0x83, 0x00, 0x06, 0x80, 0x08, 0x46, 0x10, +0x00, 0x0e, 0x58, 0x10, 0x87, 0x7c, 0x84, 0x46, 0x8d, 0x21, 0x4b, 0xe0, 0x28, 0x01, 0xc8, 0x09, +0x44, 0x50, 0x00, 0x10, 0x8d, 0x06, 0x4c, 0x92, 0xff, 0xf3, 0x84, 0x01, 0xd5, 0x07, 0x9d, 0xb1, +0x9d, 0xf9, 0x40, 0xfe, 0x1c, 0x06, 0xe8, 0xdf, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x44, 0x30, 0x01, 0x0c, 0x54, 0xa0, +0x80, 0xff, 0x42, 0x65, 0x0c, 0x24, 0x54, 0x91, 0x00, 0xff, 0x44, 0x20, 0x00, 0x43, 0x42, 0x64, +0x88, 0x73, 0x97, 0xc0, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x05, 0xf4, 0x99, 0xb0, 0x84, 0x20, +0x97, 0x20, 0x80, 0x06, 0x81, 0x05, 0xf4, 0x81, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, +0xdd, 0x2f, 0x84, 0x24, 0x4c, 0x70, 0xc0, 0x04, 0x84, 0x03, 0xd5, 0x09, 0x84, 0x46, 0x4c, 0x71, +0x40, 0x04, 0x84, 0x04, 0xd5, 0x04, 0x84, 0xab, 0xdf, 0x04, 0x84, 0x02, 0x10, 0x03, 0x00, 0x40, +0x41, 0xe0, 0x88, 0x08, 0x11, 0xe3, 0x00, 0x41, 0x80, 0x28, 0x46, 0x70, 0x01, 0x02, 0x58, 0x73, +0x86, 0xa4, 0x80, 0x06, 0x80, 0x5e, 0xdd, 0x27, 0x01, 0xc3, 0x00, 0x40, 0x84, 0x23, 0x4d, 0xc0, +0xc0, 0x1b, 0xf4, 0x01, 0x50, 0x54, 0x00, 0x18, 0x50, 0x33, 0x00, 0x10, 0x8d, 0x10, 0x51, 0xc3, +0x00, 0x18, 0xc4, 0x09, 0xb6, 0xbf, 0x80, 0x03, 0x80, 0x28, 0x84, 0x48, 0xdd, 0x27, 0xb4, 0x3f, +0x80, 0x1c, 0xd5, 0x07, 0x80, 0x25, 0x80, 0x03, 0x84, 0x48, 0xdd, 0x27, 0x80, 0x1c, 0x80, 0x28, +0x84, 0x48, 0xdd, 0x27, 0x80, 0x0a, 0x80, 0x29, 0x80, 0x46, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, +0x85, 0x44, 0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, +0x44, 0x30, 0x01, 0x0c, 0x97, 0x00, 0x42, 0x62, 0x0c, 0x24, 0x46, 0x20, 0x00, 0x0e, 0x58, 0x21, +0x05, 0xf4, 0x99, 0xb2, 0x81, 0x01, 0x80, 0x06, 0x84, 0x20, 0x44, 0x20, 0x00, 0x43, 0x46, 0xf0, +0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x07, 0x87, 0x01, +0x84, 0xa4, 0xd8, 0x03, 0x84, 0x03, 0xd5, 0x04, 0x84, 0xa6, 0xd8, 0x24, 0x84, 0x04, 0x45, 0xe0, +0x00, 0x10, 0x10, 0x03, 0x00, 0x40, 0x11, 0xe3, 0x00, 0x41, 0x50, 0x14, 0x00, 0x20, 0x46, 0x70, +0x01, 0x02, 0x58, 0x73, 0x86, 0xa4, 0x80, 0x06, 0x80, 0x5e, 0x4b, 0xe0, 0x1c, 0x01, 0x00, 0x03, +0x00, 0x40, 0x84, 0xa3, 0xd8, 0x0f, 0x50, 0x14, 0x00, 0x38, 0x84, 0x48, 0x50, 0x03, 0x00, 0x10, +0x4b, 0xe0, 0x1c, 0x01, 0x50, 0x03, 0x00, 0x18, 0x50, 0x14, 0x00, 0x30, 0x84, 0x48, 0x4b, 0xe0, +0x1c, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xdc, 0x97, 0x20, +0x55, 0xc0, 0x80, 0xff, 0x54, 0x91, 0x00, 0xff, 0x96, 0xd8, 0xc4, 0x44, 0x84, 0x23, 0x4c, 0x30, +0x80, 0x05, 0x84, 0x45, 0x4c, 0x31, 0x40, 0x70, 0x85, 0x40, 0x80, 0xe0, 0x81, 0x2a, 0x81, 0x0a, +0x80, 0xdf, 0xd5, 0x30, 0xa6, 0x38, 0x44, 0x30, 0x00, 0xdd, 0x4c, 0x01, 0xc0, 0x26, 0x9c, 0x3a, +0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x86, 0x40, 0x84, 0x43, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, +0x86, 0xd4, 0xdd, 0x2f, 0xc8, 0x19, 0xa7, 0x7d, 0x87, 0xc1, 0x4c, 0x5f, 0x40, 0x16, 0xa7, 0x39, +0x00, 0x93, 0x80, 0x06, 0x50, 0x82, 0x7f, 0xfa, 0x54, 0x84, 0x00, 0xff, 0x50, 0x13, 0x80, 0x08, +0x80, 0x1f, 0x80, 0x48, 0x54, 0x94, 0x80, 0x03, 0xe7, 0x10, 0xe9, 0x40, 0x46, 0xf0, 0x01, 0x02, +0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0xa6, 0xb9, 0x9c, 0x52, 0x89, 0x41, 0x99, 0xf9, 0x54, 0xa5, +0x00, 0xff, 0xa7, 0x79, 0x9c, 0xea, 0x40, 0x01, 0xa8, 0x00, 0x40, 0xfe, 0x00, 0x07, 0xe8, 0xcb, +0xd5, 0x0f, 0x84, 0xc5, 0x4c, 0x33, 0x40, 0x30, 0x80, 0x20, 0x80, 0x5c, 0x80, 0x1f, 0x46, 0xf0, +0x01, 0x02, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0xe7, 0x24, 0xe8, 0x20, 0x81, 0x1c, 0x46, 0x60, +0x00, 0x0e, 0x58, 0x63, 0x04, 0xc4, 0x80, 0x48, 0x80, 0x3f, 0x50, 0x03, 0x01, 0x10, 0x46, 0xf0, +0x01, 0x02, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0x84, 0x20, 0x00, 0x03, 0x02, 0x3e, 0x10, 0x93, +0x02, 0x3c, 0x80, 0x49, 0x50, 0x53, 0x01, 0x10, 0x80, 0x61, 0x80, 0x81, 0x46, 0xf0, 0x00, 0x00, +0x58, 0xf7, 0x86, 0xb4, 0xdd, 0x2f, 0x84, 0x01, 0xd5, 0x02, 0x84, 0x00, 0xec, 0x24, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x85, 0x20, 0x81, 0x09, 0xd5, 0xdb, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0x94, 0x85, 0x40, 0x80, 0xc2, 0x55, 0xc0, 0x00, 0xff, 0x44, 0x00, 0x02, 0x00, 0x81, 0x21, +0x14, 0xaf, 0x80, 0x19, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8f, 0xe0, 0xdd, 0x2f, 0xa7, 0x32, +0xa6, 0x73, 0x40, 0x32, 0x20, 0x08, 0x40, 0x21, 0x84, 0x04, 0x9c, 0x94, 0x50, 0x1f, 0x80, 0x64, +0x80, 0x66, 0x84, 0x9f, 0x50, 0x8f, 0x80, 0x54, 0x80, 0xe0, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, +0x8d, 0x94, 0xdd, 0x2f, 0x80, 0x2a, 0x80, 0x08, 0x44, 0x20, 0x00, 0x10, 0x46, 0xf0, 0x01, 0x02, +0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0x84, 0x02, 0x4d, 0xc0, 0x40, 0x1a, 0x50, 0xaf, 0x80, 0x04, +0xf3, 0x19, 0x80, 0x09, 0x80, 0x47, 0x80, 0x8a, 0x44, 0x50, 0x00, 0x14, 0x9e, 0x6c, 0x46, 0xf0, +0x00, 0x01, 0x58, 0xf7, 0x82, 0x90, 0xdd, 0x2f, 0x80, 0x08, 0x80, 0x2a, 0x44, 0x20, 0x00, 0x10, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0xd5, 0x0d, 0x44, 0x10, 0x00, 0x10, +0xf3, 0x19, 0x80, 0x09, 0x80, 0x88, 0x80, 0x47, 0x80, 0xa1, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, +0x81, 0x4c, 0xdd, 0x2f, 0x50, 0x1f, 0x80, 0x54, 0x44, 0x20, 0x00, 0x10, 0x50, 0x03, 0x00, 0x51, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x8f, 0xf4, 0xdd, 0x2f, 0xec, 0x6c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x87, 0x87, 0x03, 0xf6, 0x0c, +0x84, 0xe3, 0x85, 0x21, 0x84, 0xa0, 0x44, 0x00, 0x00, 0x5f, 0xaf, 0xf1, 0x10, 0x93, 0x00, 0x00, +0xaf, 0x72, 0xae, 0x33, 0x83, 0x83, 0xf4, 0x81, 0x97, 0xc8, 0x96, 0x90, 0x4e, 0x82, 0x00, 0x04, +0x84, 0x02, 0xd5, 0x02, 0x84, 0x1e, 0xae, 0x34, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x17, 0x87, 0x04, +0xc1, 0x03, 0x85, 0x23, 0xd5, 0x0d, 0x46, 0xf0, 0x00, 0x0e, 0x01, 0xe7, 0x87, 0x01, 0x84, 0x81, +0x56, 0x3f, 0x00, 0x06, 0x85, 0x42, 0x40, 0x95, 0x0c, 0x1a, 0x40, 0x92, 0x0c, 0x1b, 0xa7, 0x76, +0x40, 0x02, 0x8c, 0x09, 0x94, 0x03, 0x40, 0x00, 0x24, 0x04, 0xae, 0x36, 0xe6, 0xe5, 0xe9, 0x04, +0x42, 0x00, 0x0c, 0x09, 0xd5, 0x03, 0x58, 0x00, 0x00, 0x08, 0xae, 0x36, 0x4e, 0x83, 0x00, 0x14, +0xe6, 0xe5, 0xe9, 0x11, 0xa7, 0x76, 0x54, 0x11, 0x00, 0x03, 0x44, 0x3f, 0xff, 0xcf, 0x94, 0x0c, +0x41, 0xe2, 0x8c, 0x02, 0x40, 0xaf, 0x00, 0x04, 0x84, 0x43, 0x10, 0xa3, 0x00, 0x06, 0x4c, 0x71, +0x40, 0x0f, 0xd5, 0x0f, 0x84, 0x83, 0x4c, 0x72, 0x40, 0x08, 0x00, 0xa3, 0x00, 0x06, 0x58, 0x25, +0x00, 0x40, 0xae, 0xb6, 0xd5, 0x06, 0x87, 0xc1, 0x4c, 0x7f, 0x00, 0x04, 0x84, 0xa5, 0xdf, 0x09, +0xa7, 0x36, 0x44, 0x1f, 0xff, 0x80, 0x40, 0x32, 0x04, 0x04, 0x84, 0xa1, 0xae, 0xf6, 0xd7, 0x06, +0x00, 0xa3, 0x00, 0x05, 0x58, 0x25, 0x00, 0x01, 0xae, 0xb5, 0x4e, 0x82, 0x00, 0x05, 0xe6, 0xe3, +0xe8, 0x04, 0xd5, 0x0c, 0xe6, 0xe5, 0xe9, 0x17, 0xa6, 0x35, 0x59, 0xe0, 0x00, 0x02, 0x11, 0xe3, +0x00, 0x05, 0x4e, 0x82, 0x00, 0x11, 0x84, 0xa3, 0xd7, 0x03, 0x84, 0xa5, 0xdf, 0x05, 0xa6, 0x75, +0x58, 0x40, 0x80, 0x10, 0xaf, 0x35, 0x4e, 0x82, 0x00, 0x07, 0x84, 0x41, 0x4c, 0x71, 0x00, 0x04, +0x84, 0xa3, 0xdf, 0x10, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x47, 0x87, 0x01, 0x44, 0x00, 0x00, 0x10, +0x56, 0x32, 0x00, 0x04, 0x95, 0x41, 0x41, 0xe2, 0x8c, 0x1a, 0x41, 0xe0, 0x0c, 0x1b, 0x11, 0xe3, +0x00, 0x08, 0x50, 0x03, 0x00, 0x09, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x85, 0x8c, 0x84, 0x48, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0xe6, 0xe4, 0xe9, 0x05, 0x4e, 0x83, +0x00, 0x26, 0x84, 0xa5, 0xdf, 0x23, 0x46, 0xa0, 0x01, 0x02, 0x58, 0xa5, 0x06, 0xa4, 0x50, 0x03, +0x00, 0x11, 0x80, 0x3c, 0x44, 0x20, 0x00, 0x20, 0x4b, 0xe0, 0x28, 0x01, 0x4e, 0x83, 0x00, 0x12, +0x84, 0xa5, 0xdf, 0x0f, 0x50, 0x1e, 0x00, 0x10, 0x50, 0x03, 0x00, 0x31, 0x44, 0x20, 0x00, 0x10, +0x4b, 0xe0, 0x28, 0x01, 0x00, 0x53, 0x00, 0x40, 0x9c, 0x2a, 0x10, 0x03, 0x00, 0x40, 0xd5, 0x08, +0x84, 0xa3, 0xdf, 0x04, 0x4e, 0x83, 0x00, 0x05, 0xd5, 0x0c, 0x84, 0xa5, 0xdf, 0x0a, 0xf1, 0x01, +0x50, 0x03, 0x00, 0x41, 0x84, 0x46, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, +0x84, 0x20, 0x50, 0x03, 0x00, 0x51, 0x44, 0x20, 0x00, 0x10, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, +0x87, 0x08, 0xdd, 0x2f, 0x84, 0xa1, 0xd7, 0x0c, 0x80, 0x09, 0x80, 0x46, 0x46, 0x10, 0x00, 0x0e, +0x58, 0x10, 0x85, 0x94, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x89, 0x0c, 0xdd, 0x2f, 0xec, 0x0c, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xee, 0x84, 0x46, 0x80, +0x01, 0x02, 0x58, 0x84, 0x07, 0x08, 0x50, 0x60, 0x00, 0x5b, 0x84, 0x20, 0x97, 0xd0, 0x50, 0x0f, +0x81, 0x60, 0x44, 0x20, 0x00, 0x10, 0xdd, 0x28, 0x84, 0x20, 0x44, 0x20, 0x00, 0x50, 0x50, 0x0f, +0x81, 0x00, 0xdd, 0x28, 0x50, 0x9f, 0x81, 0x74, 0x84, 0x20, 0x44, 0x20, 0x00, 0xff, 0x80, 0x1f, +0xdd, 0x28, 0x84, 0x20, 0x84, 0x42, 0x80, 0x09, 0xdd, 0x28, 0x50, 0x13, 0x7f, 0xaa, 0x80, 0x09, +0x84, 0x42, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0x84, 0x01, 0x46, 0xf0, +0x00, 0x0e, 0x00, 0x87, 0x87, 0x03, 0x4c, 0x70, 0x00, 0x08, 0x84, 0x43, 0x4c, 0x71, 0x00, 0x05, +0x84, 0x65, 0x4c, 0x71, 0xc0, 0x26, 0x51, 0xcf, 0x81, 0x50, 0x84, 0x20, 0x84, 0x48, 0x80, 0x1c, +0x50, 0xa3, 0x7f, 0xae, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0x46, 0x90, +0x00, 0x02, 0x58, 0x94, 0x89, 0xf8, 0x80, 0x0a, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x85, 0x8c, +0x84, 0x48, 0x4b, 0xe0, 0x24, 0x01, 0x84, 0x81, 0x4c, 0x02, 0x00, 0x09, 0x80, 0x0a, 0x80, 0x3c, +0x84, 0x48, 0x4b, 0xe0, 0x24, 0x01, 0x4e, 0x03, 0x00, 0xcc, 0x84, 0xa1, 0xd7, 0x6a, 0x00, 0xa3, +0x7f, 0xa7, 0x00, 0x93, 0x7f, 0xa8, 0x41, 0xe5, 0x20, 0x08, 0x50, 0xa3, 0x7f, 0xf6, 0x41, 0xcf, +0x24, 0x04, 0x80, 0x2a, 0x44, 0x20, 0x00, 0x10, 0x46, 0x90, 0x01, 0x02, 0x58, 0x94, 0x86, 0xa4, +0x50, 0x0f, 0x81, 0x50, 0x4b, 0xe0, 0x24, 0x01, 0x84, 0x20, 0x80, 0x0a, 0x44, 0x20, 0x00, 0x10, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0x00, 0x0f, 0x81, 0x75, 0x84, 0x21, +0x54, 0x00, 0x00, 0x07, 0x51, 0xce, 0x00, 0x04, 0x4c, 0x00, 0xc0, 0x18, 0x46, 0x90, 0x00, 0x0e, +0x58, 0x94, 0x84, 0xc4, 0x85, 0x44, 0x8c, 0x2f, 0x10, 0xa4, 0x82, 0x3d, 0x50, 0x04, 0x80, 0xd0, +0x80, 0x7c, 0x50, 0x23, 0x7f, 0xa5, 0x50, 0x4f, 0x81, 0x60, 0x80, 0xa1, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x81, 0x4c, 0xdd, 0x2f, 0xd5, 0x21, 0x84, 0x42, 0x4c, 0x01, 0x40, 0x1f, 0x46, 0xa0, +0x00, 0x0e, 0x58, 0xa5, 0x04, 0xc4, 0x80, 0x7c, 0x87, 0x86, 0x11, 0xc5, 0x02, 0x3d, 0x50, 0x05, +0x00, 0xd0, 0x8c, 0x2f, 0x50, 0x23, 0x7f, 0xa5, 0x50, 0x4f, 0x81, 0x00, 0x9d, 0x4c, 0x46, 0xf0, +0x00, 0x01, 0x58, 0xf7, 0x82, 0x90, 0xdd, 0x2f, 0x50, 0x1f, 0x81, 0x00, 0x50, 0x0f, 0x81, 0x60, +0x44, 0x20, 0x00, 0x10, 0x4b, 0xe0, 0x24, 0x01, 0x50, 0x0f, 0x81, 0x50, 0x50, 0x1f, 0x81, 0x60, +0x44, 0x20, 0x00, 0x10, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xd4, 0xdd, 0x2f, 0xc8, 0x60, +0xa7, 0x76, 0xa7, 0x37, 0x40, 0x32, 0xa0, 0x08, 0x40, 0x31, 0x90, 0x04, 0x4e, 0x36, 0x00, 0x04, +0x84, 0x01, 0xd5, 0x57, 0x84, 0x23, 0x4c, 0x70, 0xc0, 0x05, 0x4e, 0x83, 0x00, 0x06, 0xd5, 0x42, +0x84, 0x05, 0x4c, 0x70, 0x40, 0x40, 0x00, 0x5f, 0x81, 0x75, 0x84, 0x42, 0x55, 0xe2, 0x80, 0x07, +0x80, 0x9f, 0x50, 0x03, 0x00, 0x08, 0x4d, 0xe1, 0x40, 0x1e, 0xa6, 0x76, 0x01, 0xe3, 0x00, 0x07, +0x40, 0x90, 0xa0, 0x08, 0x40, 0x14, 0xf8, 0x04, 0x94, 0xd3, 0x46, 0x20, 0x00, 0x0e, 0x58, 0x21, +0x05, 0xa4, 0x50, 0x5f, 0x81, 0x70, 0x85, 0x20, 0x14, 0x9f, 0x80, 0x5c, 0x46, 0xf0, 0x00, 0x00, +0x58, 0xf7, 0x8f, 0xd4, 0xdd, 0x2f, 0xf3, 0x5c, 0x00, 0x4f, 0x81, 0x71, 0xae, 0xf7, 0xaf, 0x36, +0xd5, 0x0d, 0x80, 0x40, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x05, 0xa4, 0x50, 0x13, 0x7f, 0xd6, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x8c, 0xdd, 0x2f, 0x4e, 0x83, 0x00, 0x0c, 0x84, 0x05, +0x4c, 0x70, 0x40, 0x09, 0x00, 0x5f, 0x81, 0x75, 0x40, 0x22, 0x90, 0x09, 0x54, 0x21, 0x00, 0x03, +0xd5, 0x02, 0x84, 0x40, 0xa6, 0x77, 0x80, 0x67, 0x80, 0x88, 0x80, 0x1f, 0x46, 0xf0, 0x00, 0x00, +0x58, 0xf7, 0x88, 0x08, 0xdd, 0x2f, 0x84, 0x60, 0x40, 0x01, 0x80, 0x06, 0xd5, 0x02, 0x84, 0x00, +0xed, 0x7c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xd4, 0x46, 0x70, +0x00, 0x0e, 0x58, 0x73, 0x84, 0xc4, 0x00, 0x33, 0x82, 0x3d, 0x80, 0xc1, 0x81, 0x00, 0x80, 0x22, +0x80, 0x06, 0x84, 0x45, 0xf3, 0x85, 0x01, 0xc3, 0x82, 0x3c, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, +0x8b, 0xc8, 0xdd, 0x2f, 0x80, 0x60, 0xc8, 0x10, 0x04, 0x13, 0x80, 0x97, 0x54, 0x00, 0x84, 0x00, +0xc0, 0x75, 0x46, 0x02, 0x00, 0x00, 0x80, 0x23, 0x80, 0x48, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, +0x81, 0xa8, 0xdd, 0x2f, 0xd5, 0x6b, 0x50, 0x13, 0x00, 0x09, 0x84, 0x48, 0x46, 0x90, 0x01, 0x02, +0x58, 0x94, 0x86, 0xa4, 0x50, 0x03, 0x80, 0xc8, 0xdd, 0x29, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, +0x8a, 0xc0, 0xdd, 0x2f, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0xa4, 0x46, 0xf0, 0x00, 0x00, +0x58, 0xf7, 0x83, 0x24, 0xdd, 0x2f, 0x81, 0x40, 0xc0, 0x51, 0x04, 0x80, 0x00, 0x02, 0x4e, 0x82, +0x00, 0x4e, 0x84, 0xc0, 0x80, 0x26, 0x44, 0x20, 0x04, 0x00, 0x80, 0x08, 0x46, 0xf0, 0x01, 0x02, +0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0xf0, 0x05, 0x80, 0x66, 0x80, 0x86, 0x80, 0xa6, 0x80, 0x5c, +0x84, 0x26, 0x51, 0xc4, 0x00, 0x0e, 0xb6, 0xdf, 0xf6, 0x81, 0x15, 0xcf, 0x80, 0x02, 0x46, 0xf0, +0x00, 0x00, 0x58, 0xf7, 0x89, 0xe0, 0xdd, 0x2f, 0x50, 0x13, 0x82, 0x41, 0x84, 0x46, 0x50, 0x0f, +0x80, 0x18, 0xdd, 0x29, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x87, 0x7c, 0x84, 0x46, 0x50, 0x0f, +0x80, 0x1e, 0xdd, 0x29, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x86, 0x58, 0x84, 0x42, 0x50, 0x0f, +0x80, 0x24, 0xdd, 0x29, 0x00, 0x5e, 0x00, 0x02, 0x00, 0x4e, 0x00, 0x03, 0x40, 0x72, 0xa0, 0x08, +0x40, 0x73, 0x90, 0x04, 0x50, 0x1f, 0x80, 0x18, 0x84, 0x4e, 0x80, 0x08, 0x46, 0xf0, 0x01, 0x02, +0x58, 0xf7, 0x86, 0xf0, 0xdd, 0x2f, 0x50, 0x23, 0x80, 0x12, 0x96, 0x51, 0x80, 0x0a, 0x80, 0x46, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x85, 0x68, 0xdd, 0x2f, 0xec, 0x2c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x50, 0x6f, 0x80, 0x04, 0x80, 0xe1, +0x81, 0x00, 0x84, 0x20, 0x81, 0x22, 0x80, 0x06, 0x84, 0x42, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, +0x87, 0x08, 0xdd, 0x2f, 0x80, 0x06, 0x9c, 0x7d, 0x84, 0x42, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, +0x86, 0xa4, 0xdd, 0x2f, 0xa6, 0xf1, 0x54, 0x01, 0x80, 0x80, 0xc0, 0x29, 0xa7, 0x30, 0x54, 0x12, +0x00, 0x0e, 0xc9, 0x16, 0x54, 0x21, 0x80, 0x08, 0xc2, 0x13, 0x96, 0x64, 0xc9, 0x20, 0x46, 0xf0, +0x00, 0x0e, 0x04, 0x47, 0x81, 0xc8, 0x54, 0x32, 0x02, 0x00, 0xc3, 0x19, 0x46, 0x04, 0x00, 0x00, +0x80, 0x48, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0xa8, 0xdd, 0x2f, 0xd5, 0x10, 0x54, 0x02, +0x00, 0x0f, 0x84, 0xa3, 0xd8, 0x0c, 0x54, 0x11, 0x80, 0x08, 0xc9, 0x09, 0x80, 0x08, 0x80, 0x27, +0x80, 0x49, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x8e, 0x18, 0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x9c, 0x80, 0xc0, 0x44, 0x00, 0x00, 0x10, +0xf3, 0x83, 0xf2, 0x88, 0xf4, 0x89, 0xf5, 0x8a, 0x4c, 0x30, 0x00, 0x0d, 0x44, 0x20, 0x00, 0x18, +0x4c, 0x31, 0x00, 0x09, 0x41, 0xe0, 0x04, 0x08, 0x4c, 0x3f, 0x00, 0x05, 0x84, 0x1f, 0x48, 0x00, +0x00, 0xa2, 0x8e, 0x28, 0x80, 0x01, 0x84, 0xe0, 0xf1, 0x81, 0xf7, 0x97, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x8f, 0xe0, 0xdd, 0x2f, 0xf0, 0x82, 0xc8, 0x04, 0x84, 0x1e, 0x48, 0x00, 0x00, 0x93, +0x50, 0x0f, 0x80, 0x54, 0x46, 0xa0, 0x01, 0x02, 0x58, 0xa5, 0x06, 0xa4, 0x80, 0x26, 0x84, 0x48, +0x4b, 0xe0, 0x28, 0x01, 0xf2, 0x01, 0xf0, 0x02, 0x40, 0x91, 0x0c, 0x09, 0x50, 0x13, 0x00, 0x08, +0x4b, 0xe0, 0x28, 0x01, 0x84, 0xe5, 0x54, 0x04, 0x80, 0xff, 0x80, 0x89, 0x42, 0x40, 0x1c, 0x73, +0x40, 0x24, 0x8c, 0x08, 0x05, 0xef, 0x80, 0x02, 0x50, 0x31, 0x7f, 0xf8, 0x52, 0x50, 0x00, 0x00, +0x54, 0x82, 0x80, 0xff, 0x55, 0xc2, 0x00, 0xff, 0x40, 0xaf, 0x0c, 0x00, 0x50, 0x64, 0xff, 0xff, +0x14, 0x8f, 0x80, 0x07, 0x15, 0xcf, 0x80, 0x04, 0xf7, 0x85, 0x14, 0xaf, 0x80, 0x0b, 0xf6, 0x86, +0xf6, 0x06, 0x04, 0xaf, 0x80, 0x0b, 0x05, 0xcf, 0x80, 0x04, 0x46, 0x90, 0x01, 0x02, 0x58, 0x94, +0x86, 0xa4, 0x50, 0x8f, 0x80, 0x5c, 0x50, 0x7f, 0x80, 0x4c, 0xd5, 0x2f, 0xa7, 0x0f, 0x9f, 0xb1, +0x40, 0x3e, 0x10, 0x03, 0xae, 0xcf, 0xdd, 0x29, 0x80, 0x2a, 0x84, 0x48, 0x50, 0x0f, 0x80, 0x3c, +0xdd, 0x29, 0xf3, 0x03, 0x46, 0xf0, 0x00, 0x0b, 0x04, 0x17, 0x81, 0x4c, 0xf2, 0x08, 0x45, 0xe0, +0x00, 0x10, 0x50, 0x4f, 0x80, 0x44, 0x80, 0xa8, 0x50, 0x0f, 0x80, 0x34, 0x15, 0xef, 0x80, 0x17, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x88, 0xac, 0xdd, 0x2f, 0x50, 0x1f, 0x80, 0x44, 0x84, 0x48, +0x50, 0x0f, 0x80, 0x54, 0xdd, 0x29, 0x80, 0x0a, 0x80, 0x27, 0x84, 0x48, 0xdd, 0x29, 0x50, 0x1e, +0x7f, 0xff, 0x55, 0xc0, 0x80, 0xff, 0x8f, 0x48, 0x84, 0x48, 0x50, 0x0f, 0x80, 0x34, 0x50, 0x1f, +0x80, 0x54, 0x4e, 0x64, 0xff, 0xcd, 0x05, 0xef, 0x80, 0x04, 0xf4, 0x07, 0xf1, 0x05, 0x40, 0x3f, +0x10, 0x00, 0x9e, 0x89, 0x96, 0x18, 0x84, 0xbf, 0xf2, 0x85, 0xf0, 0x84, 0xda, 0xb2, 0xf2, 0x01, +0xf5, 0x0a, 0xb6, 0x45, 0xf2, 0x01, 0xf1, 0x02, 0xf0, 0x09, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, +0x86, 0xa4, 0xdd, 0x2f, 0xf0, 0x02, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8f, 0xf4, 0xdd, 0x2f, +0x84, 0x00, 0xec, 0x64, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, +0xee, 0xe4, 0xb6, 0x5f, 0xf3, 0x81, 0x80, 0xc1, 0x46, 0x70, 0x01, 0x02, 0x58, 0x73, 0x87, 0x08, +0x84, 0x20, 0x44, 0x20, 0x00, 0x60, 0x83, 0x80, 0x50, 0x0f, 0x80, 0x68, 0x81, 0x44, 0x81, 0x25, +0x50, 0x8f, 0x80, 0xc8, 0x4b, 0xe0, 0x1c, 0x01, 0x84, 0x20, 0x44, 0x20, 0x00, 0x60, 0x50, 0x0f, +0x80, 0x08, 0x4b, 0xe0, 0x1c, 0x01, 0x80, 0x08, 0x84, 0x20, 0x44, 0x20, 0x00, 0x40, 0x4b, 0xe0, +0x1c, 0x01, 0x5c, 0xf3, 0x00, 0x41, 0xe8, 0x0f, 0x80, 0x08, 0x80, 0x3c, 0x80, 0x46, 0x46, 0xf0, +0x01, 0x02, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0x50, 0x6f, 0x80, 0xc8, 0x51, 0xcf, 0x81, 0x08, +0x80, 0xe6, 0xd5, 0x0a, 0x80, 0x1c, 0x80, 0x26, 0x80, 0x48, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, +0x8e, 0x98, 0xdd, 0x2f, 0xd5, 0xf2, 0xa6, 0x78, 0x56, 0x00, 0x80, 0x36, 0x18, 0x03, 0x80, 0x01, +0x4c, 0x7e, 0x7f, 0xfb, 0x50, 0x7f, 0x80, 0x68, 0x80, 0x07, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, +0x8e, 0x54, 0xdd, 0x2f, 0x46, 0x80, 0x01, 0x03, 0x58, 0x84, 0x0d, 0xc0, 0x80, 0x07, 0x50, 0x1f, +0x80, 0xc8, 0x44, 0x20, 0x00, 0x40, 0x4b, 0xe0, 0x20, 0x01, 0xb4, 0x3f, 0xf2, 0x01, 0x80, 0x07, +0x4b, 0xe0, 0x20, 0x01, 0x80, 0x07, 0x50, 0x1f, 0x81, 0x08, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, +0x8d, 0x48, 0xdd, 0x2f, 0xa6, 0xf0, 0x56, 0x21, 0x80, 0x6a, 0x18, 0x23, 0x00, 0x01, 0x4c, 0x6e, +0x7f, 0xfb, 0x50, 0x7f, 0x80, 0x08, 0x80, 0x07, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x8e, 0x54, +0xdd, 0x2f, 0x46, 0x80, 0x01, 0x03, 0x58, 0x84, 0x0d, 0xc0, 0x80, 0x07, 0x50, 0x1f, 0x80, 0xc8, +0x44, 0x20, 0x00, 0x40, 0x50, 0x6f, 0x81, 0x08, 0x4b, 0xe0, 0x20, 0x01, 0x44, 0x20, 0x00, 0x10, +0x80, 0x07, 0x80, 0x26, 0x4b, 0xe0, 0x20, 0x01, 0x80, 0x07, 0x80, 0x26, 0x46, 0xf0, 0x01, 0x03, +0x58, 0xf7, 0x8d, 0x48, 0xdd, 0x2f, 0x46, 0x30, 0x01, 0x02, 0x58, 0x31, 0x86, 0xa4, 0xe7, 0x31, +0xe9, 0x06, 0x80, 0x0a, 0x80, 0x26, 0x44, 0x20, 0x00, 0x10, 0xd5, 0x04, 0x80, 0x0a, 0x80, 0x26, +0x80, 0x49, 0x4b, 0xe0, 0x0c, 0x01, 0xed, 0x1c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xee, 0xcc, 0xb6, 0x5f, 0xf3, 0x81, 0x80, 0xc1, 0x46, 0x70, 0x01, 0x02, +0x58, 0x73, 0x87, 0x08, 0x84, 0x20, 0x44, 0x20, 0x00, 0x68, 0x83, 0x80, 0x50, 0x0f, 0x80, 0x70, +0x81, 0x44, 0x81, 0x25, 0x50, 0x8f, 0x80, 0xdc, 0x4b, 0xe0, 0x1c, 0x01, 0x84, 0x20, 0x44, 0x20, +0x00, 0x68, 0x50, 0x0f, 0x80, 0x08, 0x4b, 0xe0, 0x1c, 0x01, 0x80, 0x08, 0x84, 0x20, 0x44, 0x20, +0x00, 0x40, 0x4b, 0xe0, 0x1c, 0x01, 0x5c, 0xf3, 0x00, 0x41, 0xe8, 0x0f, 0x80, 0x08, 0x80, 0x3c, +0x80, 0x46, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0x50, 0x6f, 0x80, 0xdc, +0x51, 0xcf, 0x81, 0x1c, 0x80, 0xe6, 0xd5, 0x0a, 0x80, 0x1c, 0x80, 0x26, 0x80, 0x48, 0x46, 0xf0, +0x01, 0x03, 0x58, 0xf7, 0x81, 0xbc, 0xdd, 0x2f, 0xd5, 0xf2, 0xa6, 0x78, 0x56, 0x00, 0x80, 0x36, +0x18, 0x03, 0x80, 0x01, 0x4c, 0x7e, 0x7f, 0xfb, 0x50, 0x7f, 0x80, 0x70, 0x80, 0x07, 0x46, 0xf0, +0x01, 0x03, 0x58, 0xf7, 0x81, 0x78, 0xdd, 0x2f, 0x46, 0x80, 0x01, 0x03, 0x58, 0x84, 0x00, 0xe4, +0x80, 0x07, 0x50, 0x1f, 0x80, 0xdc, 0x44, 0x20, 0x00, 0x40, 0x4b, 0xe0, 0x20, 0x01, 0xb4, 0x3f, +0xf2, 0x01, 0x80, 0x07, 0x4b, 0xe0, 0x20, 0x01, 0x80, 0x07, 0x50, 0x1f, 0x81, 0x1c, 0x46, 0xf0, +0x01, 0x02, 0x58, 0xf7, 0x8f, 0xd8, 0xdd, 0x2f, 0xa6, 0xf0, 0x56, 0x21, 0x80, 0x6a, 0x18, 0x23, +0x00, 0x01, 0x4c, 0x6e, 0x7f, 0xfb, 0x50, 0x7f, 0x80, 0x08, 0x80, 0x07, 0x46, 0xf0, 0x01, 0x03, +0x58, 0xf7, 0x81, 0x78, 0xdd, 0x2f, 0x46, 0x80, 0x01, 0x03, 0x58, 0x84, 0x00, 0xe4, 0x80, 0x07, +0x50, 0x1f, 0x80, 0xdc, 0x44, 0x20, 0x00, 0x40, 0x50, 0x6f, 0x81, 0x1c, 0x4b, 0xe0, 0x20, 0x01, +0x44, 0x20, 0x00, 0x14, 0x80, 0x07, 0x80, 0x26, 0x4b, 0xe0, 0x20, 0x01, 0x80, 0x07, 0x80, 0x26, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x8f, 0xd8, 0xdd, 0x2f, 0x46, 0x30, 0x01, 0x02, 0x58, 0x31, +0x86, 0xa4, 0xe7, 0x35, 0xe9, 0x06, 0x80, 0x0a, 0x80, 0x26, 0x44, 0x20, 0x00, 0x14, 0xd5, 0x04, +0x80, 0x0a, 0x80, 0x26, 0x80, 0x49, 0x4b, 0xe0, 0x0c, 0x01, 0xed, 0x34, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x46, 0x20, 0x00, 0x80, 0x58, 0x21, 0x00, 0x50, 0x46, 0x50, 0x04, 0x00, +0x98, 0xc2, 0x58, 0x52, 0x82, 0x7c, 0x94, 0x03, 0x84, 0x40, 0x99, 0x05, 0x94, 0xdb, 0xb6, 0x44, +0xb6, 0x43, 0x50, 0x22, 0xff, 0xf4, 0x44, 0x30, 0x00, 0xff, 0x40, 0x51, 0x80, 0x0c, 0xb4, 0x82, +0x40, 0x32, 0x94, 0x05, 0x40, 0x51, 0x90, 0x02, 0x96, 0x48, 0x84, 0x61, 0xb6, 0xa2, 0x4c, 0x11, +0xc0, 0x06, 0xb4, 0x22, 0x44, 0x30, 0x00, 0x82, 0xd5, 0x03, 0xb4, 0x22, 0x94, 0xdf, 0x40, 0x41, +0x80, 0x0c, 0x40, 0x02, 0x04, 0x04, 0xb6, 0x02, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x50, 0x00, 0x80, +0x58, 0x52, 0x80, 0x50, 0x46, 0x40, 0x04, 0x00, 0x98, 0x85, 0x58, 0x42, 0x02, 0x7c, 0x94, 0x03, +0x99, 0x44, 0x94, 0x93, 0x44, 0x31, 0x00, 0x00, 0x84, 0x80, 0xb6, 0x65, 0xb6, 0x82, 0x46, 0x20, +0x04, 0x00, 0x58, 0x21, 0x02, 0x70, 0x44, 0x30, 0x00, 0xff, 0x40, 0x51, 0x80, 0x0c, 0xb4, 0x82, +0x40, 0x32, 0x94, 0x05, 0x40, 0x51, 0x90, 0x02, 0x96, 0x48, 0x84, 0x61, 0xb6, 0xa2, 0x4c, 0x11, +0xc0, 0x06, 0xb4, 0x22, 0x44, 0x30, 0x00, 0x82, 0xd5, 0x03, 0xb4, 0x22, 0x94, 0xdf, 0x40, 0x41, +0x80, 0x0c, 0x40, 0x02, 0x04, 0x04, 0xb6, 0x02, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x40, 0x04, 0x00, +0x46, 0x20, 0x30, 0x70, 0x80, 0xa4, 0x58, 0x21, 0x03, 0x07, 0x14, 0x22, 0x00, 0x9d, 0x14, 0x22, +0x80, 0x9e, 0x46, 0x20, 0x04, 0x00, 0x58, 0x21, 0x02, 0x70, 0x44, 0x30, 0x00, 0xff, 0x94, 0x03, +0x40, 0x51, 0x80, 0x0c, 0xb4, 0x82, 0x40, 0x32, 0x94, 0x05, 0x40, 0x51, 0x90, 0x02, 0x96, 0x48, +0x84, 0x61, 0xb6, 0xa2, 0x4c, 0x11, 0xc0, 0x06, 0xb4, 0x22, 0x44, 0x30, 0x00, 0x86, 0xd5, 0x04, +0xb4, 0x22, 0x44, 0x30, 0x00, 0x84, 0x40, 0x51, 0x80, 0x0c, 0x40, 0x02, 0x84, 0x04, 0xb6, 0x02, +0xdd, 0x9e, 0x92, 0x00, 0x40, 0x31, 0xe0, 0x08, 0x40, 0x41, 0x90, 0x04, 0x40, 0x21, 0x40, 0x08, +0x46, 0x50, 0x00, 0x80, 0x40, 0x22, 0x08, 0x04, 0x58, 0x52, 0x80, 0x50, 0x46, 0x40, 0x04, 0x00, +0x98, 0xc5, 0x58, 0x42, 0x02, 0x7c, 0x94, 0x03, 0x99, 0x44, 0xb6, 0x45, 0x94, 0xdb, 0x84, 0x40, +0xb6, 0x43, 0x50, 0x22, 0x7f, 0xf4, 0x44, 0x50, 0x00, 0xff, 0x40, 0x32, 0x80, 0x0c, 0xb4, 0x82, +0x40, 0x51, 0x8c, 0x05, 0x40, 0x32, 0x90, 0x02, 0x96, 0x48, 0x84, 0xa1, 0xb6, 0x62, 0xd9, 0x05, +0xb4, 0x22, 0x44, 0x30, 0x00, 0x82, 0xd5, 0x03, 0xb4, 0x22, 0x94, 0xef, 0x40, 0x41, 0x80, 0x0c, +0x40, 0x02, 0x04, 0x04, 0xb6, 0x02, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x44, 0x20, +0x00, 0x19, 0x96, 0x48, 0x80, 0x62, 0x84, 0x81, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x84, 0xe4, +0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x44, 0x20, 0x00, 0x32, 0x96, 0x48, 0x84, 0x6a, 0x84, 0x81, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x84, 0xe4, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x10, 0x04, 0x00, 0x04, 0x00, 0x80, 0x20, 0x54, 0x00, +0x01, 0x00, 0xc0, 0x09, 0x84, 0x00, 0x80, 0x20, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x84, 0x2c, +0xdd, 0x2f, 0xd5, 0x07, 0x80, 0x20, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x83, 0xd4, 0xdd, 0x2f, +0x46, 0x20, 0x04, 0x00, 0x58, 0x21, 0x00, 0x20, 0xb4, 0x22, 0x59, 0xe0, 0x88, 0x00, 0x15, 0xe1, +0x00, 0x00, 0x84, 0x01, 0xb4, 0xa2, 0x80, 0x20, 0x42, 0x32, 0xc4, 0x09, 0xb6, 0x62, 0x46, 0xf0, +0x00, 0x01, 0x58, 0xf7, 0x83, 0xd4, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x84, 0x48, 0x96, 0x49, 0x4c, 0x11, 0x40, 0x04, 0x84, 0x81, +0xd5, 0x07, 0x95, 0x51, 0xd1, 0x04, 0x84, 0x01, 0x48, 0x00, 0x00, 0xc4, 0x84, 0x82, 0x46, 0xa0, +0x10, 0x00, 0x58, 0xa5, 0x00, 0x01, 0x85, 0x20, 0x47, 0xc1, 0x11, 0x10, 0x46, 0x70, 0x04, 0x00, +0xb6, 0x9f, 0x14, 0xaf, 0x80, 0x01, 0x59, 0xce, 0x01, 0x90, 0x81, 0x49, 0x58, 0x73, 0x82, 0x70, +0x46, 0x80, 0x00, 0x01, 0x58, 0x84, 0x04, 0x2c, 0x81, 0x20, 0x80, 0x29, 0xa3, 0x89, 0xb4, 0x21, +0xe6, 0xc4, 0x4e, 0xf2, 0x00, 0xa0, 0x84, 0xa4, 0xd1, 0x34, 0xe6, 0x25, 0xe8, 0x0a, 0x84, 0xa1, +0xd1, 0x1d, 0xc1, 0x17, 0x84, 0xa2, 0xd1, 0x21, 0x84, 0xa3, 0x4c, 0x12, 0xc0, 0x94, 0xd5, 0x25, +0x8c, 0xac, 0xd1, 0x42, 0xe6, 0x31, 0xe8, 0x07, 0x84, 0xa5, 0xd1, 0x2a, 0x84, 0xa6, 0x4c, 0x12, +0xc0, 0x8a, 0xd5, 0x32, 0x9d, 0x69, 0xd1, 0x59, 0x9d, 0x69, 0x4c, 0x12, 0xc0, 0x84, 0xd5, 0x64, +0x80, 0x06, 0x84, 0x21, 0x4b, 0xe0, 0x20, 0x01, 0xd5, 0x7d, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x83, 0xd4, 0xdd, 0x2f, 0xd5, 0x76, 0x80, 0x06, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x84, 0x8c, 0xdd, 0x2f, 0xd5, 0x6e, 0x84, 0x21, 0x44, 0x20, 0x00, 0x32, 0xd5, 0x0b, +0x80, 0x06, 0x84, 0x21, 0x46, 0x20, 0x00, 0x01, 0x58, 0x21, 0x05, 0x48, 0xd5, 0x62, 0x84, 0x21, +0x44, 0x20, 0x00, 0x11, 0x80, 0x06, 0x80, 0x62, 0x80, 0x81, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, +0x84, 0xe4, 0xdd, 0x2f, 0xd5, 0x57, 0x80, 0x06, 0x84, 0x21, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, +0x85, 0x6c, 0xdd, 0x2f, 0xd5, 0x4f, 0x46, 0x50, 0x00, 0x80, 0x58, 0x52, 0x80, 0x50, 0x46, 0x20, +0x04, 0x00, 0x98, 0xf5, 0x58, 0x21, 0x02, 0x7c, 0x95, 0x73, 0x98, 0x6a, 0x15, 0xc0, 0x80, 0x00, +0x41, 0xe1, 0x8c, 0x08, 0xf4, 0x01, 0xb6, 0x9e, 0x44, 0x00, 0x00, 0x82, 0xb4, 0x47, 0x40, 0x60, +0x14, 0x0c, 0x41, 0xe1, 0x20, 0x09, 0x41, 0xef, 0x20, 0x08, 0x15, 0xe3, 0x80, 0x00, 0xb4, 0x27, +0x40, 0x63, 0x04, 0x04, 0xb6, 0xc7, 0xd5, 0x2e, 0x80, 0x06, 0x84, 0x21, 0x4b, 0xe0, 0x20, 0x01, +0x80, 0x46, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x10, 0x46, 0x10, 0x00, 0x01, 0x58, 0x10, +0x87, 0x98, 0x84, 0x61, 0xd5, 0x0f, 0x80, 0x06, 0x84, 0x21, 0x4b, 0xe0, 0x20, 0x01, 0x80, 0x46, +0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x10, 0x46, 0x10, 0x00, 0x01, 0x58, 0x10, 0x87, 0x98, +0x84, 0x63, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x81, 0x0c, 0xdd, 0x2f, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x03, 0x10, 0x44, 0x10, 0x13, 0x88, 0x46, 0x20, 0x00, 0x00, 0x58, 0x21, 0x02, 0x54, +0xdd, 0x22, 0xb4, 0x1f, 0x8d, 0x41, 0x8d, 0x28, 0xe3, 0x40, 0x4e, 0xf3, 0xff, 0x58, 0x84, 0x00, +0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x84, 0xa2, 0x80, 0xc0, +0xd1, 0x25, 0x84, 0xa3, 0xd1, 0x2a, 0x84, 0xa1, 0xd9, 0x2e, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, +0x83, 0xd4, 0xdd, 0x2f, 0x80, 0x46, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x10, 0x46, 0x10, +0x00, 0x01, 0x58, 0x10, 0x87, 0x98, 0x84, 0x62, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x81, 0x0c, +0xdd, 0x2f, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x10, 0x44, 0x10, 0x0b, 0xb8, 0x46, 0xf0, +0x00, 0x00, 0x58, 0xf7, 0x82, 0x54, 0xdd, 0x2f, 0xd5, 0x0e, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x84, 0x8c, 0xdd, 0x2f, 0xd5, 0x07, 0x84, 0x21, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, +0x83, 0xd4, 0xdd, 0x2f, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, +0xef, 0xf8, 0x46, 0x10, 0x04, 0x00, 0x04, 0x60, 0x80, 0x97, 0x96, 0x34, 0xc0, 0x15, 0x80, 0x61, +0x04, 0x21, 0x80, 0x20, 0x54, 0x01, 0x01, 0x00, 0xc0, 0x09, 0x84, 0x00, 0x80, 0x20, 0x46, 0xf0, +0x00, 0x01, 0x58, 0xf7, 0x84, 0x2c, 0xdd, 0x2f, 0xd5, 0x07, 0x80, 0x20, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x83, 0xd4, 0xdd, 0x2f, 0x40, 0x43, 0x40, 0x08, 0x92, 0x9f, 0xc4, 0x06, 0x46, 0xf0, +0x00, 0x05, 0x58, 0xf7, 0x80, 0xc8, 0xdd, 0x2f, 0x55, 0xe3, 0x10, 0x00, 0x4f, 0xe2, 0x00, 0x07, +0x84, 0x21, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x17, 0x84, 0x88, 0x54, 0x23, 0x20, 0x00, 0xc2, 0x11, +0x46, 0xf0, 0x00, 0x0e, 0x00, 0x17, 0x87, 0xdc, 0x84, 0xa1, 0xd9, 0x0b, 0x46, 0xf0, 0x00, 0x0e, +0x00, 0x07, 0x87, 0xe1, 0x4c, 0x00, 0xc0, 0x06, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x07, 0x87, 0xbb, +0x47, 0xe0, 0x04, 0x00, 0x14, 0x6f, 0x00, 0x97, 0x04, 0x5f, 0x00, 0x97, 0xf5, 0x81, 0xec, 0x08, +0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x96, 0x49, 0x54, 0x20, 0x80, 0x03, 0x40, 0x30, +0x88, 0x09, 0xca, 0x10, 0x5c, 0xf0, 0x80, 0xc8, 0xe8, 0x0d, 0x80, 0x20, 0xb4, 0x40, 0x84, 0x01, +0xd5, 0x04, 0xb4, 0x81, 0x9c, 0x01, 0xab, 0x11, 0x9c, 0x4c, 0xe2, 0x03, 0xe9, 0xfb, 0x84, 0x00, +0xd5, 0x02, 0x84, 0x01, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0x3c, 0xa4, 0x88, 0x5c, 0xf1, +0x00, 0xc8, 0xe8, 0x16, 0x80, 0x60, 0xa2, 0x99, 0xb4, 0xa3, 0x5c, 0xf2, 0x80, 0x40, 0xe8, 0x10, +0x84, 0x60, 0xd5, 0x04, 0xa3, 0x91, 0x80, 0x64, 0xb6, 0xc0, 0x40, 0x21, 0x20, 0x08, 0x92, 0x48, +0x9c, 0x04, 0x9d, 0x19, 0xdb, 0xf8, 0x94, 0x22, 0xac, 0x08, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, +0x3a, 0x6f, 0x98, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x96, 0x49, 0xe6, 0x28, 0xe8, 0x03, 0x84, 0x01, +0xd5, 0x29, 0x80, 0x40, 0xa2, 0xd1, 0x8c, 0x08, 0xb4, 0x22, 0xb4, 0x40, 0xc3, 0x02, 0xd5, 0x21, +0x46, 0x44, 0x00, 0x04, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x80, 0xdc, 0x40, 0x51, 0x10, 0x04, +0xb6, 0xa1, 0x80, 0x03, 0xd5, 0x09, 0x92, 0x00, 0x84, 0x67, 0x9c, 0x49, 0x4c, 0x11, 0xff, 0xfd, +0x9c, 0x01, 0x84, 0xaa, 0xd0, 0x03, 0x84, 0x20, 0xd5, 0xf7, 0x46, 0x1b, 0xff, 0xfb, 0x46, 0x00, +0x04, 0x00, 0x58, 0x10, 0x8f, 0xff, 0x40, 0x21, 0x04, 0x02, 0x58, 0x00, 0x00, 0xdc, 0xb6, 0x40, +0x84, 0x00, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x80, 0xe4, 0x81, 0x42, 0x81, 0x03, +0x81, 0x25, 0x55, 0xc0, 0x00, 0xff, 0x97, 0x08, 0x5c, 0xf3, 0x80, 0xc1, 0xe8, 0x4e, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x04, 0xb4, 0xf4, 0x81, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x83, 0x24, +0xdd, 0x2f, 0x80, 0xc0, 0xf4, 0x01, 0xc0, 0x41, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x37, 0x83, 0x2c, +0x54, 0x22, 0x00, 0x0f, 0x54, 0x5e, 0x00, 0x0f, 0x41, 0xe1, 0x40, 0x08, 0x40, 0x02, 0xd0, 0x08, +0x46, 0x25, 0x80, 0x00, 0xa1, 0x72, 0x40, 0x4f, 0x00, 0x04, 0x54, 0x11, 0x80, 0x03, 0x41, 0xe2, +0x08, 0x04, 0x14, 0x82, 0x80, 0x01, 0x40, 0x00, 0xe4, 0x08, 0xb7, 0x45, 0x50, 0x83, 0x80, 0x08, +0x40, 0x3f, 0x00, 0x04, 0x80, 0x47, 0x54, 0x84, 0x3f, 0xff, 0x80, 0x29, 0x50, 0x02, 0x80, 0x08, +0x40, 0x71, 0xa0, 0x04, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xf0, 0xdd, 0x2f, 0x84, 0x21, +0x84, 0x00, 0x10, 0x13, 0x00, 0x0f, 0x10, 0x03, 0x00, 0x14, 0x12, 0x83, 0x00, 0x06, 0xa9, 0xf4, +0x80, 0x26, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0xc4, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, +0x8a, 0xcc, 0xdd, 0x2f, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x96, 0x89, 0x97, 0xd8, 0xe6, 0x44, +0xe8, 0x03, 0x84, 0x01, 0xd5, 0x22, 0xb4, 0x00, 0x84, 0x21, 0x4c, 0x00, 0x80, 0x03, 0xd5, 0x1c, +0x46, 0xf0, 0x00, 0x0e, 0x04, 0x57, 0x81, 0xdb, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x37, 0x81, 0xda, +0xf5, 0x81, 0xb6, 0x7f, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x8a, 0x68, 0xdd, 0x2f, 0x84, 0x40, +0x80, 0x27, 0x80, 0xbf, 0x84, 0x05, 0x80, 0x62, 0x84, 0x88, 0x80, 0xdf, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x89, 0x74, 0xdd, 0x2f, 0x84, 0x05, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x97, 0x82, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0xb4, +0x97, 0xc8, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x83, 0x24, 0xdd, 0x2f, 0xc8, 0x03, 0x84, 0x01, +0xd5, 0x2b, 0x46, 0xf0, 0x00, 0x0e, 0x01, 0xe7, 0x83, 0x2c, 0x54, 0x53, 0x80, 0x0f, 0x54, 0x4f, +0x00, 0x03, 0x40, 0x32, 0xc0, 0x08, 0x40, 0x12, 0x64, 0x08, 0x46, 0x25, 0x88, 0x08, 0x41, 0xe1, +0x84, 0x04, 0xa1, 0x42, 0x58, 0x21, 0x00, 0x08, 0x40, 0x1f, 0x08, 0x04, 0x84, 0x88, 0x84, 0x61, +0x84, 0x40, 0xb6, 0xc5, 0xa8, 0x44, 0xad, 0x06, 0x10, 0x30, 0x00, 0x0f, 0x10, 0x20, 0x00, 0x14, +0x80, 0x20, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0xc4, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, +0x8a, 0xcc, 0xdd, 0x2f, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0xf0, 0x00, 0x0e, 0x20, 0x27, 0x83, 0x2f, 0x84, 0xa1, 0xda, 0x58, +0x46, 0x60, 0x04, 0x10, 0x04, 0x53, 0x01, 0x0e, 0x40, 0x82, 0xc0, 0x09, 0x46, 0xf0, 0x00, 0x0b, +0x00, 0x37, 0x86, 0x6d, 0x54, 0x84, 0x00, 0xff, 0xe3, 0x03, 0xe9, 0x22, 0x46, 0x70, 0x00, 0x0e, +0x20, 0x63, 0x83, 0x32, 0xce, 0x1d, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x67, 0x83, 0x31, 0x10, 0x23, +0x83, 0x32, 0x80, 0x02, 0x80, 0x26, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x8a, 0x90, 0xdd, 0x2f, +0xc0, 0x03, 0x10, 0x63, 0x83, 0x32, 0x84, 0x01, 0x80, 0x20, 0x46, 0x60, 0x00, 0x01, 0x58, 0x63, +0x0a, 0x90, 0x4b, 0xe0, 0x18, 0x01, 0x84, 0x01, 0x84, 0x22, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0xf0, +0x00, 0x0e, 0x00, 0x27, 0x83, 0x30, 0xe2, 0x48, 0xe9, 0x23, 0x46, 0x70, 0x00, 0x0e, 0x20, 0x63, +0x83, 0x31, 0xce, 0x1e, 0x84, 0x61, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x67, 0x83, 0x32, 0x10, 0x33, +0x83, 0x31, 0x80, 0x06, 0x80, 0x26, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x8a, 0x90, 0xdd, 0x2f, +0xc0, 0x03, 0x10, 0x63, 0x83, 0x31, 0x84, 0x21, 0x46, 0x60, 0x00, 0x01, 0x58, 0x63, 0x0a, 0x90, +0x84, 0x00, 0x4b, 0xe0, 0x18, 0x01, 0x84, 0x00, 0x84, 0x22, 0x4b, 0xe0, 0x18, 0x01, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0xa2, 0x41, 0x84, 0x41, 0xb4, 0x00, +0x4c, 0x11, 0x40, 0x07, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x07, 0x87, 0x18, 0xd5, 0x61, 0x84, 0xa3, +0xd9, 0x49, 0x97, 0xc0, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x04, 0xc4, 0x10, 0x73, 0x02, 0xac, +0x46, 0x10, 0x04, 0x10, 0x04, 0x00, 0x82, 0x03, 0x42, 0x00, 0x60, 0x09, 0x42, 0x00, 0x64, 0x09, +0xcf, 0x1a, 0x46, 0x20, 0x30, 0x00, 0x41, 0xe0, 0x08, 0x04, 0x15, 0xe0, 0x82, 0x03, 0x50, 0x03, +0x02, 0x68, 0x46, 0x60, 0x00, 0x00, 0x58, 0x63, 0x01, 0x1c, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x07, 0xf0, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x77, +0x87, 0xbb, 0xd5, 0x36, 0x42, 0x30, 0x60, 0x08, 0x14, 0x30, 0x82, 0x03, 0x84, 0x20, 0x10, 0x13, +0x02, 0x64, 0x14, 0x13, 0x00, 0xa9, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8d, 0xf8, 0xdd, 0x2f, +0x84, 0x01, 0x80, 0x20, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x85, 0x48, 0xdd, 0x2f, 0x50, 0x03, +0x02, 0x68, 0x44, 0x10, 0x27, 0x10, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x82, 0x54, 0xdd, 0x2f, +0xd5, 0x17, 0x84, 0xa4, 0xd9, 0x0b, 0x5c, 0x50, 0x00, 0x03, 0x84, 0x80, 0x40, 0x02, 0x14, 0x1a, +0x46, 0xf0, 0x00, 0x0e, 0x10, 0x07, 0x87, 0x29, 0xd5, 0x0b, 0x84, 0xa5, 0xd9, 0x09, 0x56, 0x10, +0x00, 0x01, 0x5c, 0x00, 0x80, 0x01, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x07, 0x87, 0xed, 0x84, 0x00, +0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x94, 0x80, 0xc0, +0xb4, 0x00, 0x84, 0x21, 0x4c, 0x00, 0xc0, 0x24, 0x9c, 0xb4, 0xb4, 0x22, 0x50, 0x33, 0x00, 0x0c, +0x97, 0x0c, 0x8c, 0xc8, 0xb4, 0x46, 0xb4, 0x63, 0xc4, 0x05, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x07, +0x87, 0x19, 0x54, 0x00, 0x80, 0x02, 0xc0, 0x0a, 0x85, 0x01, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x87, +0x87, 0x1b, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x87, 0x87, 0x1a, 0x46, 0xf0, 0x00, 0x0e, 0x14, 0x37, +0x81, 0xc9, 0x46, 0xf0, 0x00, 0x0e, 0x14, 0x27, 0x81, 0xc8, 0xd5, 0x4e, 0x84, 0xa2, 0xd8, 0x4e, +0x01, 0xe3, 0x00, 0x50, 0x00, 0x43, 0x00, 0x51, 0x00, 0x33, 0x00, 0x53, 0x51, 0xc3, 0x00, 0x04, +0xb5, 0x3c, 0x01, 0xc3, 0x00, 0x52, 0x15, 0xef, 0x80, 0x01, 0xf3, 0x83, 0xf4, 0x82, 0x46, 0x80, +0x01, 0x02, 0x58, 0x84, 0x06, 0xf0, 0x50, 0x13, 0x00, 0x08, 0x94, 0xad, 0x50, 0xaf, 0x80, 0x50, +0x50, 0x0f, 0x80, 0x10, 0x46, 0x70, 0x00, 0x0e, 0x58, 0x73, 0x84, 0xc4, 0xdd, 0x28, 0x50, 0x13, +0x00, 0x48, 0x84, 0x48, 0x42, 0x64, 0x84, 0x0b, 0x80, 0x0a, 0x54, 0x94, 0x80, 0x01, 0xdd, 0x28, +0x10, 0x93, 0x82, 0x3f, 0x10, 0x63, 0x82, 0x40, 0x50, 0x1f, 0x80, 0x10, 0xf5, 0x01, 0x44, 0x20, +0x00, 0x40, 0x10, 0x53, 0x82, 0x3c, 0x50, 0x03, 0x80, 0xd0, 0xf3, 0x02, 0x10, 0x33, 0x82, 0x3d, +0xf4, 0x03, 0x13, 0xc3, 0x81, 0x26, 0x10, 0x43, 0x82, 0x3e, 0xdd, 0x28, 0x80, 0x2a, 0x84, 0x48, +0x50, 0x03, 0x80, 0xc8, 0xdd, 0x28, 0x50, 0x13, 0x80, 0xd0, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x00, +0x58, 0xf7, 0x87, 0x7c, 0xdd, 0x2f, 0x84, 0x00, 0xd5, 0x2a, 0x84, 0xa3, 0xd0, 0x02, 0xd5, 0x26, +0x50, 0x9f, 0x80, 0x60, 0x46, 0x70, 0x01, 0x02, 0x58, 0x73, 0x86, 0xf0, 0x9c, 0x74, 0x84, 0x46, +0x50, 0x8f, 0x80, 0x58, 0x80, 0x09, 0xdd, 0x27, 0x50, 0x13, 0x00, 0x0a, 0x84, 0x46, 0x80, 0x08, +0xdd, 0x27, 0x80, 0x29, 0x84, 0x46, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x07, 0x7c, 0xdd, 0x27, +0x8c, 0xd0, 0x84, 0x46, 0x80, 0x28, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x07, 0x05, 0xdd, 0x27, +0xb4, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x14, 0x07, 0x81, 0xd9, 0x84, 0x01, 0xec, 0x6c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x96, 0x49, 0x54, 0x70, 0x80, 0x07, 0x40, 0xa0, +0x88, 0x09, 0xcf, 0x2e, 0x9d, 0x84, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, 0x82, 0xc4, 0x46, 0x80, +0x00, 0x06, 0x58, 0x84, 0x01, 0x84, 0xd5, 0x1f, 0xb4, 0x20, 0x40, 0x00, 0xa0, 0x08, 0x92, 0x08, +0x40, 0x20, 0xf8, 0x09, 0x4e, 0x14, 0x00, 0x0a, 0x40, 0x00, 0xc0, 0x09, 0x84, 0x40, 0x96, 0x48, +0x96, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0xd5, 0x0a, 0x84, 0xa1, 0xda, 0x09, 0x40, 0x40, 0xc0, 0x09, +0x96, 0x20, 0x96, 0x48, 0x84, 0x40, 0x4b, 0xe0, 0x24, 0x01, 0xc8, 0x0a, 0xb4, 0xa0, 0x9d, 0xfa, +0xb6, 0xa6, 0x8c, 0xc8, 0x9e, 0x34, 0xe2, 0xea, 0xe9, 0xe0, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, +0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x96, 0x49, +0x54, 0x70, 0x80, 0x07, 0x41, 0xc0, 0x88, 0x09, 0xcf, 0x35, 0x9d, 0x84, 0x46, 0xa0, 0x00, 0x06, +0x58, 0xa5, 0x03, 0x38, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, 0x82, 0x3c, 0xd5, 0x26, 0xb4, 0x20, +0x9d, 0xfa, 0x40, 0x00, 0xa0, 0x08, 0x92, 0x08, 0x40, 0x80, 0xf8, 0x09, 0x4e, 0x14, 0x00, 0x0c, +0x40, 0x00, 0xc0, 0x09, 0xb4, 0x46, 0x96, 0x00, 0x96, 0x48, 0x4b, 0xe0, 0x24, 0x01, 0x84, 0xa1, +0xd0, 0x13, 0xd5, 0x18, 0x84, 0xa1, 0x4c, 0x82, 0xc0, 0x0c, 0x40, 0x50, 0xc0, 0x09, 0xb4, 0x46, +0x96, 0x28, 0x96, 0x48, 0x4b, 0xe0, 0x28, 0x01, 0x4c, 0x04, 0x00, 0x07, 0xd5, 0x0b, 0x05, 0xe3, +0x00, 0x00, 0x15, 0xe0, 0x00, 0x00, 0x8c, 0xc8, 0x9e, 0x34, 0xe2, 0xfc, 0xe9, 0xd9, 0x84, 0x00, +0xd5, 0x02, 0x84, 0x01, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xf4, 0x85, 0x0c, 0x96, 0xc9, 0x40, 0x21, 0xa1, 0x17, 0x40, 0x11, 0x88, 0x09, 0xf1, 0x81, +0x4e, 0x83, 0x00, 0x6a, 0x50, 0x70, 0x00, 0x08, 0x9d, 0x84, 0x47, 0xc0, 0x00, 0x06, 0x59, 0xce, +0x02, 0x3c, 0xd5, 0x5a, 0xb4, 0x20, 0x40, 0x00, 0xa0, 0x08, 0x92, 0x08, 0x8d, 0x03, 0x40, 0x20, +0xf8, 0x09, 0x4e, 0x14, 0x00, 0x20, 0x40, 0x90, 0xc0, 0x09, 0x54, 0x94, 0x80, 0xff, 0x54, 0xa0, +0x80, 0xff, 0x80, 0x2a, 0x84, 0x40, 0x80, 0x09, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0x84, +0xdd, 0x2f, 0x80, 0x40, 0x80, 0x2a, 0x80, 0x09, 0xca, 0x46, 0xb4, 0x66, 0xb4, 0x82, 0x05, 0xe3, +0x80, 0x00, 0x40, 0x21, 0x8c, 0x05, 0x40, 0x51, 0x10, 0x02, 0x40, 0x22, 0xf8, 0x04, 0xdd, 0x3c, +0xd5, 0x23, 0x84, 0xa1, 0xda, 0x24, 0x40, 0x00, 0xc0, 0x09, 0x54, 0x90, 0x00, 0xff, 0x54, 0xa0, +0x80, 0xff, 0x80, 0x2a, 0x84, 0x40, 0x80, 0x09, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, +0xdd, 0x2f, 0x80, 0x40, 0x80, 0x2a, 0x80, 0x09, 0xca, 0x26, 0xb4, 0xa6, 0xb4, 0x82, 0xb4, 0x67, +0x40, 0x22, 0x94, 0x05, 0x41, 0xe1, 0x10, 0x02, 0x40, 0x2f, 0x0c, 0x04, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x83, 0x38, 0xdd, 0x2f, 0x84, 0xa1, 0xd0, 0x0d, 0xd5, 0x15, 0xb4, 0x60, 0xb4, 0x26, +0xb4, 0x47, 0x40, 0x50, 0x84, 0x05, 0x40, 0x41, 0x94, 0x02, 0x41, 0xe2, 0x08, 0x04, 0x15, 0xe0, +0x00, 0x00, 0x8c, 0xcc, 0x8c, 0xec, 0x05, 0xef, 0x80, 0x01, 0x9e, 0x34, 0xe3, 0x1e, 0xe9, 0xa3, +0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x96, 0x49, 0x80, 0x40, 0xe6, 0x24, 0xe8, 0x03, 0x84, 0x01, +0xd5, 0x6f, 0xb4, 0x00, 0x84, 0xa5, 0xd0, 0x3e, 0xe6, 0x06, 0xe8, 0x08, 0x84, 0xa3, 0xd0, 0x1a, +0xe6, 0x04, 0xe8, 0x29, 0x84, 0xa1, 0xd8, 0x63, 0xd5, 0x09, 0x84, 0x27, 0x4c, 0x00, 0x80, 0x51, +0xe2, 0x01, 0xe9, 0x3a, 0x84, 0xa8, 0xd8, 0x5b, 0xd5, 0x52, 0x9c, 0x14, 0xb4, 0x20, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x03, 0x2c, 0x96, 0x88, 0xae, 0x80, 0xe6, 0x42, 0xe9, 0x50, 0x84, 0x20, +0xd5, 0x4d, 0x9d, 0x14, 0xb4, 0x64, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x86, 0x6c, 0x54, 0x01, +0x80, 0x0f, 0xae, 0x08, 0xe6, 0x04, 0xe9, 0x03, 0x84, 0x05, 0xd5, 0x30, 0xc8, 0x40, 0x84, 0xa1, +0xaf, 0x48, 0xd5, 0x3e, 0x9c, 0x94, 0xb4, 0x22, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x2e, +0x55, 0xe0, 0x80, 0x0f, 0x11, 0xe0, 0x00, 0x00, 0x5c, 0xff, 0x00, 0x04, 0xe9, 0x30, 0x84, 0x23, +0xd5, 0x2d, 0x9c, 0xd4, 0xb4, 0x03, 0x54, 0x00, 0x00, 0x0f, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x8c, 0x30, 0xdd, 0x2f, 0xd5, 0x24, 0x9c, 0x94, 0xb4, 0x02, 0x40, 0x50, 0x40, 0x09, 0x40, 0x10, +0x7c, 0x09, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x57, 0x86, 0x6d, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x17, +0x83, 0x2f, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x83, 0x30, 0xae, 0x08, 0xd5, 0x10, 0x46, 0xf0, +0x00, 0x0b, 0x04, 0x37, 0x81, 0x9c, 0x84, 0x00, 0xb6, 0x62, 0xd5, 0x0a, 0x9d, 0x54, 0xb4, 0x85, +0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0x2d, 0x96, 0x64, 0xae, 0x40, 0x84, 0x00, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x04, 0x80, +0x80, 0x04, 0x80, 0xc1, 0x40, 0x14, 0x50, 0x09, 0x81, 0x20, 0x54, 0x10, 0x80, 0x7f, 0x44, 0x00, +0x00, 0x10, 0x84, 0xe4, 0x4c, 0x10, 0x00, 0x60, 0xe4, 0x31, 0xe8, 0x18, 0x84, 0xa9, 0xd1, 0x35, +0xe4, 0x2a, 0xe8, 0x0b, 0x84, 0xa2, 0x4c, 0x12, 0x80, 0x9d, 0x84, 0xa8, 0xd1, 0x26, 0x84, 0xa1, +0x4c, 0x12, 0xc0, 0xf7, 0x48, 0x00, 0x00, 0x8e, 0x84, 0x0b, 0x4c, 0x10, 0x00, 0x41, 0xe0, 0x20, +0xe9, 0x2c, 0x84, 0xac, 0x4c, 0x12, 0xc0, 0xed, 0xd5, 0x32, 0x44, 0x50, 0x00, 0x18, 0xd1, 0x5b, +0xe4, 0x39, 0xe8, 0x09, 0x9d, 0x45, 0xd1, 0x4f, 0x9d, 0x46, 0xd1, 0x0d, 0x9d, 0x44, 0x4c, 0x12, +0xc0, 0xe0, 0xd5, 0x41, 0x9d, 0x6e, 0xd1, 0x65, 0x9d, 0x69, 0xd1, 0x6b, 0x9f, 0x6e, 0x4c, 0x12, +0xc0, 0xd8, 0xd5, 0x51, 0x84, 0x01, 0xd5, 0x7c, 0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x88, 0xa8, 0xdd, 0x2f, 0xd5, 0x74, 0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x8e, 0xfc, 0xdd, 0x2f, 0xd5, 0x6c, 0xa0, 0x32, 0xa4, 0x76, 0x54, 0x74, 0x3f, 0xff, +0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x8e, 0x04, 0xdd, 0x2f, 0xd5, 0x62, 0xa0, 0x32, 0xa4, 0x76, +0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x8e, 0x78, 0xdd, 0x2f, 0xd5, 0x5a, 0xa0, 0x32, 0x50, 0x13, +0x00, 0x0c, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x88, 0xd8, 0xdd, 0x2f, 0xa5, 0xf6, 0x54, 0x73, +0xbf, 0xff, 0xd5, 0x4e, 0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x85, 0xf0, +0xdd, 0x2f, 0xd5, 0x46, 0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x88, 0xcc, +0xdd, 0x2f, 0xd5, 0x3e, 0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x8c, 0xb8, +0xdd, 0x2f, 0xd5, 0x36, 0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x8b, 0xd4, +0xdd, 0x2f, 0xd5, 0x2e, 0x40, 0x24, 0x40, 0x09, 0xa4, 0x76, 0xa0, 0x32, 0x54, 0x31, 0x00, 0x0f, +0x50, 0x2f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x8a, 0x34, 0xdd, 0x2f, 0xd5, 0x78, +0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x08, 0x58, 0xf7, 0x86, 0x58, 0xdd, 0x2f, 0xd5, 0x18, +0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x80, 0x40, 0xdd, 0x2f, 0xd5, 0x10, +0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x8f, 0xf0, 0xdd, 0x2f, 0xd5, 0x08, +0xa0, 0x32, 0xa4, 0x76, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x89, 0x18, 0xdd, 0x2f, 0x93, 0x10, +0x54, 0x84, 0x00, 0x0f, 0x4e, 0x82, 0x00, 0x55, 0x46, 0x3f, 0xff, 0x0f, 0x58, 0x31, 0x8f, 0xff, +0x40, 0x73, 0x8c, 0x02, 0x40, 0x84, 0x40, 0x08, 0x41, 0xe3, 0xa0, 0x04, 0x42, 0x5f, 0x78, 0x09, +0x42, 0x52, 0xfc, 0x09, 0x46, 0x4f, 0xf0, 0xff, 0x42, 0x32, 0xf8, 0x08, 0x54, 0x10, 0x00, 0x0f, +0x58, 0x42, 0x0f, 0xff, 0x40, 0x71, 0x90, 0x02, 0x40, 0x00, 0xd0, 0x08, 0x47, 0xec, 0x6f, 0xff, +0x40, 0x53, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x37, 0x83, 0x2c, 0x59, 0xef, 0x0f, 0xff, +0x46, 0x11, 0x80, 0x00, 0x40, 0x42, 0xf8, 0x02, 0x40, 0x72, 0x04, 0x04, 0x54, 0x01, 0x80, 0x03, +0x42, 0x53, 0xe4, 0x09, 0x42, 0x52, 0xe8, 0x09, 0x41, 0xe0, 0x64, 0x08, 0x40, 0x32, 0xf8, 0x04, +0x42, 0x71, 0xbc, 0x09, 0x54, 0x13, 0xbf, 0xff, 0xe4, 0x28, 0xe8, 0x07, 0x40, 0x03, 0xb8, 0x09, +0x40, 0x00, 0x38, 0x08, 0x58, 0x70, 0x00, 0x08, 0x55, 0xe3, 0xbf, 0xff, 0x84, 0xa1, 0x13, 0xe3, +0x00, 0x06, 0x10, 0x53, 0x00, 0x0f, 0xa9, 0xf4, 0x80, 0x26, 0x80, 0x09, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x8a, 0xcc, 0xdd, 0x2f, 0x84, 0x20, 0x40, 0x00, 0x80, 0x06, 0xd5, 0x02, 0x84, 0x00, +0xec, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x44, 0x20, +0x00, 0x14, 0x80, 0xc0, 0x80, 0xe1, 0x84, 0x20, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, +0xdd, 0x2f, 0xa6, 0x70, 0xa6, 0xb4, 0xa6, 0x31, 0x84, 0x7e, 0x40, 0x40, 0x8c, 0x02, 0x92, 0x02, +0x94, 0x02, 0x40, 0x51, 0x0c, 0x02, 0xaf, 0x30, 0xaf, 0x74, 0xae, 0x31, 0xa7, 0x37, 0x00, 0x33, +0x80, 0x9d, 0x54, 0x21, 0x00, 0x02, 0xae, 0xf5, 0xa6, 0xf3, 0xa1, 0x7b, 0x00, 0x03, 0x80, 0x9e, +0x54, 0x31, 0x80, 0x38, 0x98, 0x28, 0x96, 0x01, 0x40, 0x70, 0x20, 0x09, 0x54, 0x53, 0x80, 0x0f, +0x92, 0x84, 0x95, 0x24, 0x40, 0x42, 0x14, 0x04, 0x58, 0x21, 0x00, 0x1c, 0x54, 0x50, 0x80, 0x08, +0x58, 0x31, 0x80, 0x40, 0x84, 0x20, 0xaf, 0x70, 0xaf, 0x37, 0xae, 0xb4, 0xae, 0x72, 0xae, 0xf3, +0xae, 0x36, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, +0xef, 0xfc, 0x44, 0x20, 0x00, 0x14, 0x80, 0xc0, 0x80, 0xe1, 0x84, 0x20, 0x46, 0xf0, 0x01, 0x02, +0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0xa6, 0x70, 0xa6, 0xb4, 0xa6, 0x31, 0x84, 0x7e, 0x40, 0x40, +0x8c, 0x02, 0x92, 0x02, 0x94, 0x02, 0x40, 0x51, 0x0c, 0x02, 0xaf, 0x30, 0xaf, 0x74, 0xae, 0x31, +0xa7, 0x37, 0x00, 0x33, 0x80, 0x9d, 0x54, 0x21, 0x00, 0x02, 0xae, 0xf5, 0xa6, 0xf3, 0xa1, 0x7b, +0x00, 0x03, 0x80, 0x9e, 0x58, 0x21, 0x00, 0x1c, 0x98, 0x28, 0x96, 0x01, 0x40, 0x70, 0x20, 0x09, +0x54, 0x53, 0x80, 0x0f, 0x92, 0x84, 0x95, 0x24, 0x40, 0x42, 0x14, 0x04, 0x54, 0x31, 0x80, 0x38, +0x54, 0x50, 0x80, 0x08, 0x84, 0x20, 0xaf, 0x70, 0xaf, 0x37, 0xae, 0xb4, 0xae, 0x72, 0xae, 0xf3, +0xae, 0x36, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, +0x44, 0x60, 0x00, 0x18, 0x10, 0x60, 0x00, 0x9e, 0x50, 0x60, 0x00, 0x24, 0x80, 0xe0, 0x84, 0x20, +0x44, 0x20, 0x00, 0x18, 0x80, 0x06, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, +0xa6, 0xf0, 0x00, 0x83, 0x00, 0x01, 0x44, 0x0f, 0xff, 0xd8, 0x40, 0x44, 0x00, 0x02, 0x54, 0x51, +0x80, 0x03, 0x58, 0x22, 0x80, 0x08, 0x58, 0x12, 0x00, 0x01, 0x84, 0x60, 0x10, 0x33, 0x00, 0x16, +0x10, 0x33, 0x00, 0x17, 0xae, 0xb0, 0xae, 0x71, 0x46, 0x80, 0x01, 0x02, 0x58, 0x84, 0x06, 0xf0, +0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x87, 0x05, 0x84, 0x46, 0x50, 0x03, 0x80, 0x28, 0x4b, 0xe0, +0x20, 0x01, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x87, 0x7c, 0x84, 0x46, 0x50, 0x03, 0x80, 0x2e, +0x4b, 0xe0, 0x20, 0x01, 0xa0, 0x79, 0x50, 0x03, 0x80, 0x34, 0x84, 0x46, 0x4b, 0xe0, 0x20, 0x01, +0x00, 0x03, 0x80, 0x94, 0xc0, 0x06, 0xa6, 0x71, 0x59, 0xe0, 0x80, 0x40, 0x11, 0xe3, 0x00, 0x01, +0xa7, 0x31, 0x42, 0x22, 0x10, 0x09, 0xae, 0xb1, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x80, 0x20, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0xc4, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x89, 0xa8, 0xdd, 0x2f, 0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0x60, 0x81, 0x01, 0x80, 0xe2, 0x50, 0x9f, +0x80, 0x24, 0x84, 0x20, 0x44, 0x20, 0x00, 0xa0, 0x80, 0x1f, 0x81, 0x43, 0x46, 0xf0, 0x01, 0x02, +0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0x84, 0x80, 0x80, 0x28, 0x80, 0x47, 0x84, 0x7f, 0x80, 0x09, +0xf4, 0x83, 0x10, 0x3f, 0x80, 0x9d, 0xf4, 0x82, 0xb7, 0x5f, 0x14, 0x8f, 0x80, 0x01, 0x46, 0xf0, +0x01, 0x02, 0x58, 0xf7, 0x86, 0xf0, 0xdd, 0x2f, 0x96, 0xb8, 0x40, 0x04, 0x88, 0x00, 0x9d, 0x43, +0x40, 0x42, 0x88, 0x09, 0x95, 0x22, 0x9a, 0xe0, 0x80, 0x3f, 0x50, 0x0f, 0x80, 0x10, 0x10, 0x3f, +0x80, 0x9f, 0x10, 0x2f, 0x80, 0x9e, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x83, 0x9c, 0xdd, 0x2f, +0x80, 0x1f, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0xc0, 0xdd, 0x2f, 0x80, 0xdf, 0x84, 0x01, +0xec, 0xa0, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0x5c, 0x81, 0x00, +0x97, 0x90, 0x40, 0x90, 0x80, 0x13, 0x80, 0x1f, 0x84, 0x20, 0x44, 0x20, 0x00, 0xa0, 0x04, 0x74, +0x00, 0x02, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0xce, 0x13, 0x46, 0x30, +0x00, 0x0e, 0x58, 0x31, 0x84, 0xc4, 0x00, 0x41, 0x81, 0x70, 0xcc, 0x05, 0x80, 0x64, 0x44, 0x20, +0x00, 0xff, 0xd5, 0x0c, 0x00, 0x01, 0x81, 0x71, 0xc0, 0x05, 0x50, 0x31, 0x81, 0x30, 0x80, 0x46, +0xd5, 0x05, 0x84, 0x60, 0x44, 0x20, 0x00, 0xff, 0x80, 0x83, 0x87, 0xc1, 0x50, 0x53, 0x80, 0x0e, +0x50, 0x14, 0xff, 0xf2, 0x80, 0x1f, 0x11, 0xef, 0x80, 0x9d, 0xf3, 0xa6, 0xb7, 0x1f, 0xf5, 0x82, +0xf1, 0x83, 0x10, 0x4f, 0x80, 0x94, 0x10, 0x2f, 0x80, 0x9c, 0xf7, 0x81, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x84, 0x1c, 0xdd, 0x2f, 0x00, 0x0f, 0x80, 0x9e, 0x50, 0x2f, 0x80, 0x24, 0x99, 0x50, +0x9d, 0xeb, 0x92, 0xe2, 0x95, 0xfa, 0x9b, 0x3d, 0x10, 0x4f, 0x80, 0x9f, 0x46, 0x80, 0x01, 0x02, +0x58, 0x84, 0x06, 0xf0, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x86, 0x44, 0x84, 0x46, 0x80, 0x07, +0x4b, 0xe0, 0x20, 0x01, 0xf1, 0x01, 0x9c, 0x3e, 0x8c, 0x2c, 0x84, 0x42, 0x4b, 0xe0, 0x20, 0x01, +0x00, 0x3f, 0x80, 0x9e, 0x80, 0x3f, 0x50, 0x21, 0x80, 0x08, 0x50, 0x0f, 0x80, 0x10, 0x10, 0x2f, +0x80, 0x9e, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x83, 0x18, 0xdd, 0x2f, 0x80, 0x1f, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x84, 0xc0, 0xdd, 0x2f, 0x80, 0xdf, 0x84, 0x00, 0xec, 0xa4, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xec, 0xa0, 0x42, 0x80, 0xc0, 0xa6, 0xc8, +0x44, 0x20, 0x00, 0x80, 0x54, 0x01, 0x80, 0xf0, 0x4c, 0x01, 0x40, 0x9d, 0x8c, 0x2a, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x07, 0x05, 0x84, 0x46, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xd4, +0xdd, 0x2f, 0x4e, 0x03, 0x00, 0x90, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x80, 0xee, 0x46, 0x70, +0x00, 0x0e, 0x58, 0x73, 0x84, 0xc4, 0x14, 0x13, 0x80, 0x92, 0x80, 0x5f, 0x02, 0x13, 0x00, 0x0a, +0xa0, 0x34, 0x50, 0x3f, 0x80, 0x08, 0x50, 0x4f, 0x80, 0x0e, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, +0x8a, 0xa4, 0xdd, 0x2f, 0x4e, 0x02, 0x00, 0xa5, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x57, 0x87, 0xdc, +0x84, 0x41, 0xda, 0x26, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x07, 0x87, 0xe1, 0xc8, 0x21, 0x03, 0xe3, +0x81, 0x28, 0x4f, 0xe2, 0x00, 0x0d, 0x00, 0x53, 0x82, 0xac, 0xda, 0x09, 0x00, 0x23, 0x82, 0x51, +0xc2, 0x06, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x80, 0x9c, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x0e, +0x00, 0x57, 0x87, 0x14, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x17, 0x87, 0x15, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x07, 0xdc, 0x87, 0xc0, 0x11, 0xe0, 0x00, 0x03, 0xaf, 0x41, 0xae, 0x42, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x07, 0xdc, 0xb4, 0x20, 0x40, 0x30, 0xa0, 0x08, 0x92, 0x68, 0x84, 0xa1, +0xdb, 0x6f, 0xa6, 0x85, 0xca, 0x6d, 0xa6, 0x44, 0x84, 0x01, 0x4c, 0x10, 0x00, 0x68, 0x84, 0xa2, +0xd9, 0x04, 0x44, 0x00, 0x00, 0xc8, 0xd5, 0x10, 0x84, 0xa3, 0xd1, 0x0c, 0x84, 0xa4, 0xd1, 0x0a, +0x56, 0x40, 0x80, 0x05, 0x44, 0x50, 0x15, 0x7c, 0x40, 0x01, 0x10, 0x1b, 0x40, 0x02, 0x90, 0x1a, +0xd5, 0x03, 0x44, 0x00, 0x07, 0xd0, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x37, 0x87, 0x12, 0xcb, 0x05, +0x46, 0xf0, 0x00, 0x0e, 0x00, 0x37, 0x87, 0x13, 0x46, 0x20, 0x04, 0x11, 0x05, 0xe1, 0x00, 0x49, +0x46, 0xf0, 0x00, 0x0e, 0x04, 0x57, 0x81, 0xfa, 0x40, 0x2f, 0x18, 0x08, 0x44, 0x40, 0x03, 0xe8, +0x43, 0xe2, 0x90, 0x24, 0x50, 0x21, 0x51, 0x20, 0x9a, 0x90, 0x9e, 0x19, 0x42, 0x2f, 0x00, 0x73, +0x4e, 0x27, 0x00, 0x37, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x87, 0x34, 0xdd, 0x2f, +0xd5, 0x2f, 0xa0, 0x32, 0x44, 0x50, 0x00, 0xd0, 0xa6, 0xc0, 0x54, 0x71, 0x80, 0xf0, 0xdf, 0x28, +0xa1, 0x74, 0x00, 0x12, 0x80, 0x18, 0x00, 0x02, 0x80, 0x19, 0xc9, 0x13, 0x87, 0xc4, 0x4c, 0x0f, +0x40, 0x20, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8e, 0x08, 0xdd, 0x2f, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x07, 0x2c, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x81, 0x1c, 0xdd, 0x2f, 0xd5, 0x10, +0x84, 0x83, 0x4c, 0x12, 0x40, 0x0e, 0xc8, 0x0c, 0x80, 0x06, 0x44, 0x10, 0x00, 0x25, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x8c, 0x68, 0xdd, 0x2f, 0xd5, 0x03, 0x84, 0x02, 0xd5, 0xad, 0xec, 0x14, +0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0xf0, +0x00, 0x0e, 0x00, 0x17, 0x87, 0x18, 0x80, 0xc0, 0xc1, 0x06, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, +0x82, 0x74, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x07, 0x87, 0x28, 0x84, 0xa1, 0x4c, 0x02, +0x80, 0x8d, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x87, 0xdc, 0xa7, 0x48, 0x4e, 0x52, 0x00, 0x86, +0xa7, 0xcd, 0x84, 0xa1, 0x4c, 0x72, 0x80, 0x82, 0xb4, 0x06, 0xa6, 0x00, 0x54, 0x20, 0x00, 0x60, +0xca, 0x0b, 0x54, 0x30, 0x00, 0x10, 0xc3, 0x08, 0xa1, 0x72, 0xa7, 0x29, 0x54, 0x62, 0x00, 0x20, +0x96, 0x30, 0xc8, 0x02, 0xae, 0x0a, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x17, 0x87, 0x15, 0xc1, 0x0d, +0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x07, 0xdc, 0x01, 0xe0, 0x00, 0x02, 0x4f, 0xe2, 0x00, 0x06, +0xa6, 0x81, 0xc2, 0x03, 0x84, 0x20, 0xd5, 0x06, 0x84, 0x21, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, +0x07, 0xdc, 0xae, 0x43, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x07, 0xdc, 0xb4, 0x86, 0x46, 0x5f, +0xf0, 0x00, 0x58, 0x52, 0x80, 0xff, 0x46, 0x30, 0x10, 0x00, 0x40, 0x02, 0x14, 0x02, 0x58, 0x31, +0x80, 0x01, 0x4c, 0x01, 0xc0, 0x4b, 0xa7, 0xf5, 0xcf, 0x48, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x80, 0x9c, 0xdd, 0x2f, 0xa6, 0x74, 0x84, 0xa1, 0xd1, 0x3d, 0x84, 0xa2, 0xd9, 0x04, +0x44, 0x00, 0x00, 0xc8, 0xd5, 0x11, 0x84, 0x03, 0x4c, 0x10, 0x00, 0x0d, 0x84, 0xa4, 0xd1, 0x0a, +0x56, 0x50, 0x80, 0x05, 0x44, 0x40, 0x15, 0x7c, 0x40, 0x03, 0x94, 0x1b, 0x40, 0x02, 0x14, 0x1a, +0xd5, 0x03, 0x44, 0x00, 0x07, 0xd0, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x37, 0x87, 0x12, 0xcb, 0x05, +0x46, 0xf0, 0x00, 0x0e, 0x00, 0x37, 0x87, 0x13, 0x46, 0x40, 0x04, 0x11, 0x04, 0x22, 0x00, 0x49, +0x46, 0xf0, 0x00, 0x0e, 0x04, 0x57, 0x81, 0xfa, 0x44, 0x40, 0x03, 0xe8, 0x41, 0xe1, 0x18, 0x08, +0x50, 0x2f, 0x51, 0x20, 0x42, 0x42, 0x90, 0x24, 0x9a, 0x90, 0x51, 0xe1, 0xff, 0xff, 0x42, 0x22, +0x78, 0x73, 0x4e, 0x27, 0x00, 0x0b, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x87, 0x34, +0xdd, 0x2f, 0xd5, 0x03, 0x84, 0x02, 0xd5, 0xd8, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xe0, 0x80, 0x60, 0xa4, 0x06, 0x5c, 0xf0, 0x00, 0x35, 0xe9, 0x2e, +0xa0, 0x5a, 0x9c, 0x8c, 0xa7, 0x97, 0x40, 0x43, 0x18, 0x09, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x47, +0x87, 0x71, 0xc1, 0x24, 0xa7, 0x89, 0x55, 0xe3, 0x00, 0x01, 0x4f, 0xe3, 0x00, 0x20, 0x54, 0x63, +0x00, 0x06, 0xce, 0x1c, 0xd5, 0x20, 0x12, 0x20, 0x00, 0x0a, 0x12, 0x60, 0x00, 0x0b, 0xa6, 0xa0, +0x40, 0x11, 0x08, 0x09, 0x54, 0x10, 0x80, 0x03, 0xc1, 0x0b, 0x84, 0xa2, 0xd1, 0x02, 0xd5, 0x06, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x88, 0x08, 0xdd, 0x2f, 0x84, 0x01, 0xd5, 0x08, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x86, 0x54, 0xdd, 0x2f, 0xd5, 0xf9, 0x84, 0x00, 0xec, 0x20, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x50, 0x0f, 0x80, 0x04, 0x50, 0x40, 0x80, 0x1c, 0xb6, 0x20, 0xa8, 0x81, +0xa8, 0xc3, 0xa9, 0x02, 0xa9, 0x04, 0x46, 0xf0, 0x00, 0x0e, 0x01, 0xe7, 0x87, 0x28, 0xa7, 0x53, +0xa6, 0xd2, 0x54, 0x22, 0x80, 0x0f, 0x40, 0x11, 0x20, 0x08, 0x84, 0xa1, 0x40, 0x20, 0x8c, 0x04, +0x4d, 0xe2, 0xff, 0xcb, 0xd5, 0xe3, 0x92, 0x00, 0x84, 0x60, 0xd5, 0x0e, 0x38, 0x50, 0x0c, 0x00, +0x38, 0x40, 0x8c, 0x00, 0x9c, 0xd9, 0xe2, 0x85, 0xe8, 0x03, 0x84, 0x01, 0xd5, 0x08, 0xe2, 0xa4, +0xe8, 0x03, 0x84, 0x02, 0xd5, 0x04, 0xe2, 0x62, 0xe9, 0xf2, 0x84, 0x00, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0x98, 0x3c, 0x9c, 0x01, 0x08, 0x60, 0x00, 0x01, 0x96, 0x49, 0xaf, 0x90, 0x08, 0x60, +0x00, 0x01, 0xaf, 0xa0, 0x08, 0x60, 0x00, 0x01, 0xaf, 0xa8, 0xa7, 0xa0, 0xa7, 0x40, 0xf4, 0x01, +0xce, 0x05, 0x97, 0xac, 0xc6, 0x03, 0x84, 0xc1, 0xd5, 0x02, 0x84, 0xc0, 0xaf, 0x98, 0x54, 0x32, +0x80, 0xfe, 0x95, 0x5b, 0xa6, 0x90, 0xe0, 0x25, 0xe9, 0x08, 0x9e, 0x94, 0x99, 0x5a, 0x96, 0xa8, +0x9d, 0x51, 0x94, 0xab, 0xe0, 0x22, 0xe9, 0x03, 0x84, 0x00, 0xd5, 0x16, 0x40, 0x50, 0x8c, 0x09, +0x9a, 0xeb, 0x96, 0x98, 0x98, 0x02, 0x96, 0xd4, 0x84, 0xa8, 0x40, 0x21, 0x8c, 0x1a, 0x40, 0x22, +0x8c, 0x1b, 0x20, 0x00, 0x00, 0x01, 0x54, 0x50, 0x80, 0x0f, 0x9a, 0xea, 0x40, 0x10, 0x0c, 0x0e, +0x96, 0x4c, 0xc1, 0x04, 0x84, 0x01, 0xae, 0x20, 0xd5, 0x02, 0xae, 0x60, 0x84, 0x01, 0x3a, 0x6f, +0x98, 0x04, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xdc, 0x85, 0x20, 0xf4, 0x83, 0x12, 0x92, +0x00, 0x00, 0x80, 0xa0, 0x08, 0x82, 0x80, 0x0a, 0xf3, 0x82, 0x93, 0x04, 0xf1, 0x85, 0x14, 0x8f, +0x80, 0x04, 0x80, 0xc0, 0x80, 0x25, 0x46, 0x70, 0x01, 0x02, 0x58, 0x73, 0x86, 0xf0, 0x80, 0x02, +0x84, 0x46, 0x4b, 0xe0, 0x1c, 0x01, 0xf0, 0x02, 0x50, 0x13, 0x00, 0x10, 0x84, 0x46, 0x47, 0xc0, +0x00, 0x0e, 0x59, 0xce, 0x04, 0xc4, 0x4b, 0xe0, 0x1c, 0x01, 0x50, 0x63, 0x00, 0x24, 0x44, 0xa0, +0x00, 0x24, 0x50, 0x7f, 0x80, 0x1f, 0x50, 0x9e, 0x02, 0x51, 0xd5, 0x59, 0xf0, 0x03, 0xa4, 0xc0, +0x98, 0x5a, 0x5e, 0xf0, 0x81, 0x7e, 0xe8, 0x5a, 0xa6, 0x70, 0x84, 0x85, 0x4c, 0x12, 0x00, 0x1e, +0x45, 0xe0, 0x00, 0x25, 0x4c, 0x1f, 0x40, 0x46, 0x85, 0x03, 0x4c, 0x24, 0x40, 0x43, 0xa7, 0xb3, +0x46, 0xf0, 0x00, 0x0e, 0x10, 0x67, 0x87, 0xec, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8e, 0x08, +0xdd, 0x2f, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x07, 0x2c, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, +0x81, 0x1c, 0xdd, 0x2f, 0x84, 0x00, 0xd5, 0x3b, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x57, 0x87, 0xdc, +0x84, 0x21, 0xd9, 0x27, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x37, 0x87, 0xe1, 0xcb, 0x22, 0xf0, 0x04, +0x85, 0x08, 0x4c, 0x04, 0x40, 0x1f, 0xf0, 0x02, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x87, 0x05, +0x84, 0x46, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xd4, 0xdd, 0x2f, 0xc8, 0x12, 0x02, 0x1e, +0x01, 0x26, 0xb7, 0x3f, 0x80, 0x06, 0x80, 0x47, 0x50, 0x34, 0xff, 0xff, 0x50, 0x44, 0xff, 0xfd, +0x50, 0x54, 0xff, 0xfe, 0x46, 0x80, 0x00, 0x02, 0x58, 0x84, 0x0a, 0x20, 0x4b, 0xe0, 0x20, 0x01, +0x01, 0xe3, 0x00, 0x01, 0x50, 0x4f, 0x00, 0x02, 0x99, 0xb4, 0x89, 0x44, 0xa6, 0xb1, 0xf5, 0x05, +0x9c, 0xd2, 0x40, 0x11, 0xa8, 0x00, 0xe2, 0xa1, 0xe8, 0xa2, 0x84, 0x01, 0xec, 0x24, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x80, 0xc0, 0x80, 0xe1, 0x81, 0x22, +0x84, 0x20, 0x44, 0x20, 0x00, 0x18, 0x81, 0x03, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, +0xdd, 0x2f, 0xa7, 0x30, 0x44, 0x2f, 0xff, 0xd0, 0x54, 0x32, 0x00, 0x03, 0x40, 0x11, 0x88, 0x04, +0x80, 0x06, 0x18, 0x10, 0x00, 0x04, 0x84, 0x46, 0x80, 0x27, 0x46, 0x70, 0x01, 0x02, 0x58, 0x73, +0x86, 0xf0, 0x4b, 0xe0, 0x1c, 0x01, 0x80, 0x29, 0x84, 0x46, 0x50, 0x03, 0x00, 0x0a, 0x4b, 0xe0, +0x1c, 0x01, 0x80, 0x28, 0x84, 0x46, 0x50, 0x03, 0x00, 0x10, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x04, 0xc4, 0x00, 0x10, 0x02, 0x66, 0x00, 0x43, 0x00, 0x16, 0x54, 0x50, +0x80, 0x0f, 0x94, 0xec, 0x54, 0x22, 0x00, 0x0f, 0x40, 0x41, 0x0c, 0x04, 0x40, 0x50, 0x90, 0x09, +0x10, 0x53, 0x00, 0x17, 0x10, 0x43, 0x00, 0x16, 0x44, 0x20, 0x00, 0xff, 0x00, 0x10, 0x02, 0x66, +0x9c, 0xc9, 0x10, 0x30, 0x02, 0x66, 0x4c, 0x11, 0x40, 0x05, 0x87, 0xc0, 0x11, 0xe0, 0x02, 0x66, +0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x81, 0x20, +0x40, 0x80, 0x80, 0x13, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x8a, 0xc0, 0xdd, 0x2f, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x04, 0xa4, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x83, 0x24, 0xdd, 0x2f, +0x80, 0xe0, 0xc0, 0x41, 0xa1, 0x82, 0x8c, 0xd8, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x87, 0x05, +0x80, 0x61, 0x50, 0x03, 0x7f, 0xe8, 0x46, 0x20, 0x00, 0x0e, 0x58, 0x21, 0x07, 0x7c, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x8b, 0xc4, 0xdd, 0x2f, 0x84, 0x63, 0x84, 0x21, 0x04, 0x04, 0x80, 0x04, +0xa6, 0xb5, 0xae, 0xf0, 0xae, 0x71, 0x58, 0x21, 0x00, 0x02, 0x00, 0x40, 0x00, 0x1a, 0x42, 0x31, +0x00, 0x09, 0x40, 0x14, 0x20, 0x09, 0xae, 0xf5, 0xaf, 0x32, 0xae, 0x74, 0x10, 0x83, 0x00, 0x03, +0x54, 0x31, 0x00, 0x02, 0x00, 0x50, 0x00, 0x1b, 0x44, 0x10, 0x00, 0x10, 0x54, 0x42, 0x80, 0x3c, +0x40, 0x21, 0x90, 0x04, 0x84, 0x00, 0xae, 0xb5, 0xae, 0x76, 0xae, 0x37, 0x10, 0x03, 0x00, 0x08, +0x50, 0x13, 0x7f, 0xe8, 0x80, 0x67, 0x44, 0x20, 0x00, 0x21, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, +0x84, 0xe4, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, +0x80, 0xc0, 0x54, 0xa0, 0x80, 0xff, 0x54, 0x91, 0x00, 0xff, 0x84, 0x20, 0x44, 0x20, 0x00, 0x18, +0x80, 0xe3, 0x81, 0x04, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, 0xa7, 0x30, +0xa6, 0x31, 0x54, 0x32, 0x00, 0x03, 0x40, 0x55, 0x10, 0x08, 0x42, 0x40, 0x00, 0x09, 0x54, 0x24, +0x80, 0x01, 0x40, 0x02, 0x08, 0x04, 0x40, 0x11, 0x94, 0x04, 0xae, 0x70, 0xae, 0x31, 0x80, 0x27, +0x84, 0x46, 0x46, 0x70, 0x01, 0x02, 0x58, 0x73, 0x86, 0xf0, 0x9c, 0x34, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x87, 0x7c, 0x84, 0x46, 0x50, 0x03, 0x00, 0x0a, 0x4b, 0xe0, +0x1c, 0x01, 0x50, 0x03, 0x00, 0x10, 0x80, 0x28, 0x84, 0x46, 0x4b, 0xe0, 0x1c, 0x01, 0x3a, 0x6f, +0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x2f, 0x94, 0x3c, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x81, 0x20, +0x50, 0x0f, 0x80, 0x20, 0xf0, 0x81, 0x80, 0xe1, 0x84, 0xc0, 0x46, 0x80, 0x01, 0x02, 0x58, 0x84, +0x06, 0xa4, 0xf2, 0x01, 0x84, 0xbf, 0x9d, 0x14, 0xf4, 0x81, 0x40, 0x04, 0x98, 0x00, 0xb4, 0x62, +0x9c, 0x64, 0x80, 0x43, 0xd3, 0x07, 0xf1, 0x81, 0x99, 0xb3, 0xb4, 0x24, 0x4b, 0xe0, 0x20, 0x01, +0xd5, 0xf1, 0x80, 0x06, 0xb6, 0xc7, 0xec, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, 0xec, 0x10, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x82, 0xa8, 0xdd, 0x2f, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x46, 0x00, 0x04, 0x11, 0xa0, 0x81, 0x58, 0x11, +0x00, 0x0c, 0xa8, 0x41, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0x3c, 0x46, 0x40, 0x04, 0x10, +0x46, 0x30, 0x04, 0x10, 0x46, 0x20, 0x04, 0x10, 0x58, 0x42, 0x04, 0x38, 0x58, 0x31, 0x8a, 0x30, +0x58, 0x21, 0x0a, 0x34, 0x84, 0x20, 0xb4, 0xc4, 0xb4, 0xa3, 0x5c, 0x63, 0x00, 0x01, 0x96, 0x28, +0xc0, 0x02, 0x84, 0xc0, 0xb4, 0xa2, 0x46, 0x7f, 0xf0, 0x0f, 0x58, 0x73, 0x8f, 0x00, 0x40, 0x02, +0x9c, 0x02, 0x9c, 0x49, 0xc8, 0x02, 0xce, 0x08, 0x84, 0x1f, 0x4c, 0x50, 0x00, 0x92, 0x44, 0x50, +0x07, 0xd0, 0xd9, 0xea, 0xd5, 0x6b, 0x46, 0x10, 0x04, 0x11, 0x58, 0x10, 0x82, 0x00, 0xb4, 0x81, +0x96, 0xa4, 0xc2, 0x17, 0x84, 0x40, 0xd5, 0x0b, 0x92, 0x00, 0x84, 0xc7, 0x9c, 0xd9, 0x4c, 0x33, +0x7f, 0xfd, 0x9c, 0x91, 0x44, 0x70, 0x00, 0x32, 0x4c, 0x23, 0x80, 0x04, 0x84, 0x60, 0xd5, 0xf5, +0x84, 0x7f, 0x4c, 0x41, 0x80, 0x76, 0x9c, 0x01, 0x44, 0x40, 0x07, 0xd0, 0x4c, 0x02, 0x7f, 0xe9, +0x46, 0x60, 0x04, 0x11, 0x58, 0x63, 0x00, 0x04, 0xb4, 0x06, 0x84, 0xb7, 0x40, 0x10, 0x14, 0x02, +0x46, 0x40, 0x04, 0x10, 0x46, 0x30, 0x04, 0x10, 0x46, 0x20, 0x04, 0x10, 0xb6, 0x26, 0x58, 0x42, +0x04, 0x38, 0x58, 0x31, 0x8a, 0x30, 0x58, 0x21, 0x0a, 0x34, 0x84, 0x20, 0xb4, 0xa4, 0x46, 0x60, +0x0f, 0xf0, 0xb4, 0x03, 0x40, 0x52, 0x98, 0x02, 0xc0, 0x03, 0x84, 0xa0, 0xd5, 0x03, 0x5c, 0x52, +0x80, 0x01, 0xb4, 0x02, 0x9c, 0x49, 0xc8, 0x03, 0xc5, 0x05, 0xd5, 0x09, 0x84, 0xff, 0x4c, 0x03, +0x80, 0x48, 0x44, 0x00, 0x07, 0xd0, 0x4c, 0x10, 0x7f, 0xeb, 0xd5, 0x31, 0x46, 0x10, 0x04, 0x11, +0x58, 0x10, 0x82, 0x00, 0xb4, 0x81, 0x54, 0x22, 0x00, 0x02, 0xc2, 0x3a, 0x84, 0x40, 0xd5, 0x0b, +0x92, 0x00, 0x84, 0xe7, 0x9c, 0xd9, 0x4c, 0x33, 0xff, 0xfd, 0x9c, 0x91, 0x44, 0x60, 0x00, 0x32, +0x4c, 0x23, 0x00, 0x04, 0x84, 0x60, 0xd5, 0xf5, 0x84, 0xff, 0x4c, 0x43, 0x80, 0x2a, 0x9c, 0x01, +0x44, 0x30, 0x07, 0xd0, 0x4c, 0x01, 0xff, 0xe8, 0xd5, 0x23, 0x46, 0x10, 0x04, 0x10, 0x46, 0x60, +0x04, 0x10, 0x46, 0x40, 0x04, 0x10, 0x58, 0x10, 0x8a, 0x30, 0x58, 0x63, 0x0a, 0x34, 0x58, 0x42, +0x04, 0x38, 0xb4, 0x41, 0xb4, 0x26, 0xb4, 0x04, 0x84, 0x00, 0xd5, 0x86, 0x46, 0x20, 0x04, 0x10, +0x46, 0x00, 0x04, 0x10, 0x46, 0x50, 0x04, 0x10, 0x58, 0x00, 0x0a, 0x34, 0x58, 0x21, 0x0a, 0x30, +0x58, 0x52, 0x84, 0x38, 0xb4, 0x42, 0xb4, 0x20, 0xb4, 0x05, 0x84, 0x00, 0xd5, 0xc0, 0x3a, 0x6f, +0x9c, 0x04, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x07, 0x18, +0x46, 0x70, 0x01, 0x02, 0x58, 0x73, 0x87, 0x08, 0x84, 0x20, 0x44, 0x20, 0x00, 0x10, 0x80, 0x06, +0x4b, 0xe0, 0x1c, 0x01, 0x84, 0x20, 0x44, 0x20, 0x01, 0x8c, 0x50, 0x03, 0x7e, 0x74, 0x4b, 0xe0, +0x1c, 0x01, 0x84, 0x20, 0x84, 0x46, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x07, 0x7c, 0x4b, 0xe0, +0x1c, 0x01, 0x84, 0x40, 0x46, 0x70, 0x00, 0x00, 0x58, 0x73, 0x81, 0x0c, 0x80, 0x62, 0x50, 0x03, +0x00, 0x14, 0x46, 0x10, 0x00, 0x03, 0x58, 0x10, 0x81, 0x60, 0x4b, 0xe0, 0x1c, 0x01, 0x84, 0x40, +0x50, 0x03, 0x00, 0x30, 0x80, 0x62, 0x46, 0x10, 0x00, 0x03, 0x58, 0x10, 0x80, 0x30, 0x4b, 0xe0, +0x1c, 0x01, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x04, 0xc4, 0x84, 0x80, 0x46, 0x50, 0x00, 0x0e, +0x58, 0x52, 0x87, 0xdc, 0x44, 0x80, 0x00, 0x1e, 0x84, 0x40, 0x10, 0x42, 0x80, 0x11, 0x10, 0x43, +0x02, 0x65, 0x14, 0x82, 0x80, 0x02, 0x10, 0x43, 0x02, 0x66, 0x10, 0x43, 0x02, 0x64, 0xaf, 0x28, +0xaf, 0x2d, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x07, 0xf0, 0x46, 0x10, 0x00, 0x0a, 0x58, 0x10, +0x87, 0xdc, 0x80, 0x62, 0x4b, 0xe0, 0x1c, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0xc4, 0x04, 0x20, +0x00, 0xa8, 0x96, 0x54, 0xc1, 0x1c, 0x04, 0x50, 0x00, 0x92, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x47, +0x80, 0xee, 0x50, 0x32, 0x83, 0xe8, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x83, 0x34, 0xe2, 0x64, +0xe8, 0x0c, 0xb4, 0x81, 0x9c, 0xa1, 0xb6, 0x41, 0xe4, 0x4a, 0xe9, 0x09, 0x04, 0x50, 0x00, 0xa9, +0x42, 0x32, 0xf0, 0x08, 0x14, 0x30, 0x00, 0xa9, 0x84, 0x00, 0xb6, 0x01, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x07, 0x48, 0x44, 0x10, 0x03, 0xe8, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x82, 0x54, +0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, +0x81, 0x00, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x8a, 0xc0, 0xdd, 0x2f, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x04, 0xa4, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x83, 0x24, 0xdd, 0x2f, 0x80, 0xe0, +0xc0, 0x4c, 0xa1, 0x82, 0x46, 0x30, 0x00, 0x0e, 0x58, 0x31, 0x87, 0x05, 0x80, 0x83, 0x80, 0x06, +0x84, 0x24, 0x84, 0x41, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8d, 0x1c, 0xdd, 0x2f, 0x84, 0x40, +0xae, 0xb2, 0xae, 0xb3, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x84, 0xc4, 0x00, 0x30, 0x82, 0x66, +0xa7, 0x30, 0x00, 0x53, 0x00, 0x16, 0xa6, 0x31, 0x85, 0x53, 0x54, 0x91, 0x80, 0x0f, 0x40, 0x42, +0x28, 0x02, 0x54, 0x84, 0x00, 0x01, 0x40, 0x94, 0x90, 0x08, 0x54, 0x52, 0x80, 0x0f, 0x40, 0x84, +0x10, 0x08, 0x42, 0x00, 0x10, 0x09, 0x40, 0x00, 0x20, 0x04, 0x92, 0x64, 0x58, 0x42, 0x00, 0x08, +0x40, 0x52, 0xa4, 0x04, 0x10, 0x33, 0x00, 0x17, 0xaf, 0x30, 0x10, 0x53, 0x00, 0x16, 0xae, 0x31, +0x44, 0x30, 0x00, 0xff, 0x00, 0x00, 0x82, 0x66, 0x9d, 0x01, 0x10, 0x40, 0x82, 0x66, 0x4c, 0x01, +0xc0, 0x04, 0x10, 0x20, 0x82, 0x66, 0x80, 0x26, 0x80, 0x67, 0x84, 0x00, 0x8c, 0x58, 0x46, 0xf0, +0x00, 0x02, 0x58, 0xf7, 0x84, 0xe4, 0xdd, 0x2f, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x07, 0x87, 0xdc, 0x84, 0xa1, +0xd8, 0x07, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x17, 0x87, 0xe1, 0xc9, 0x13, 0xd5, 0x02, 0xc8, 0x11, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x80, 0x9c, 0xdd, 0x2f, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, +0x07, 0x2c, 0x44, 0x10, 0x27, 0x10, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x82, 0x54, 0xdd, 0x2f, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x80, 0xe0, +0x80, 0xc1, 0x84, 0x01, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x84, 0x8c, 0xdd, 0x2f, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8e, 0x08, 0xdd, 0x2f, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, +0x07, 0x2c, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x81, 0x1c, 0xdd, 0x2f, 0x46, 0x20, 0x00, 0x0e, +0x58, 0x21, 0x04, 0xc4, 0x00, 0x31, 0x02, 0x65, 0x84, 0x01, 0x14, 0x71, 0x00, 0xa9, 0x14, 0x61, +0x00, 0xaa, 0x10, 0x01, 0x02, 0x64, 0xcb, 0x14, 0x46, 0x40, 0x04, 0x00, 0x05, 0xe2, 0x00, 0x19, +0x42, 0x5f, 0x00, 0x09, 0x14, 0x52, 0x00, 0x19, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x02, 0x34, +0xb4, 0x60, 0x96, 0x59, 0xb6, 0x20, 0x46, 0x31, 0x23, 0x40, 0xb4, 0x20, 0xd5, 0x1d, 0x84, 0xa1, +0xdb, 0x1e, 0x46, 0x00, 0x04, 0x10, 0x04, 0x10, 0x00, 0x8e, 0x46, 0x40, 0x04, 0x00, 0x42, 0x20, +0xc4, 0x08, 0x14, 0x20, 0x00, 0x8e, 0x05, 0xe2, 0x00, 0x20, 0x46, 0x00, 0x04, 0x00, 0x58, 0x5f, +0x00, 0x80, 0x14, 0x52, 0x00, 0x20, 0x58, 0x00, 0x02, 0x34, 0xb4, 0x60, 0x96, 0x59, 0xb6, 0x20, +0x46, 0x35, 0x67, 0x80, 0xb4, 0x20, 0x40, 0x10, 0x8c, 0x04, 0xd5, 0x08, 0x46, 0x00, 0x04, 0x00, +0x58, 0x00, 0x00, 0x80, 0xb4, 0x60, 0x42, 0x11, 0xc0, 0x08, 0xb6, 0x20, 0xec, 0x04, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0xa0, 0x42, 0x50, 0x60, 0x00, 0x08, +0xa6, 0xc8, 0x40, 0x21, 0x90, 0x09, 0x54, 0x01, 0x00, 0x04, 0x4e, 0x03, 0x01, 0x0e, 0x04, 0x73, +0x7f, 0xfe, 0xa7, 0x78, 0x54, 0x42, 0x80, 0x60, 0xc4, 0x0e, 0x8c, 0x2a, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x07, 0x05, 0x84, 0x46, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xd4, 0xdd, 0x2f, +0x4e, 0x03, 0x00, 0xfb, 0xb5, 0x26, 0x00, 0x84, 0x80, 0x01, 0x54, 0x14, 0x00, 0x40, 0xc1, 0x08, +0x04, 0x23, 0x7f, 0xfe, 0xa6, 0x12, 0x55, 0xe0, 0x00, 0x01, 0x4f, 0xe2, 0x00, 0xee, 0x04, 0x43, +0x7f, 0xfe, 0xa6, 0x20, 0x54, 0x30, 0x00, 0x40, 0xc3, 0x03, 0x84, 0xe3, 0xd5, 0x0f, 0x54, 0x50, +0x00, 0x10, 0xc5, 0x03, 0x84, 0xe1, 0xd5, 0x0a, 0x54, 0x70, 0x00, 0x20, 0x54, 0x83, 0x80, 0xff, +0x84, 0x22, 0x40, 0x74, 0x20, 0x1a, 0x40, 0x70, 0xa0, 0x1b, 0xa0, 0xb2, 0xa5, 0x36, 0x8c, 0x58, +0x50, 0x32, 0x7f, 0xe8, 0xb4, 0x06, 0xac, 0xf6, 0xa8, 0xb2, 0x01, 0xe0, 0x00, 0x00, 0x40, 0x9f, +0x10, 0x09, 0x54, 0x04, 0x80, 0x08, 0xc0, 0x19, 0xa4, 0x77, 0x58, 0x80, 0x80, 0x40, 0x40, 0x14, +0x00, 0x13, 0xac, 0x77, 0xa6, 0x10, 0x97, 0x42, 0x4e, 0x54, 0x00, 0x06, 0x58, 0x90, 0x80, 0x02, +0x12, 0x93, 0x00, 0x07, 0xa0, 0xb2, 0xa5, 0x36, 0x9c, 0xd2, 0x51, 0xe2, 0x7f, 0xfe, 0xa8, 0xf2, +0x13, 0xe3, 0x00, 0x06, 0x54, 0x00, 0x00, 0x0f, 0x10, 0x03, 0x00, 0x10, 0xb5, 0x06, 0x00, 0x54, +0x00, 0x01, 0x54, 0x02, 0x80, 0x80, 0xc0, 0x0e, 0xa4, 0xb7, 0xa1, 0x32, 0xa4, 0xf6, 0x59, 0xe1, +0x00, 0x08, 0x9c, 0x64, 0x50, 0x91, 0xff, 0xfc, 0x13, 0xe3, 0x00, 0x07, 0xa8, 0x72, 0x12, 0x93, +0x00, 0x06, 0x04, 0x83, 0x7f, 0xfe, 0x00, 0x54, 0x00, 0x01, 0x54, 0x02, 0x80, 0x40, 0xc0, 0x0b, +0xa4, 0xf7, 0x05, 0xe3, 0x00, 0x02, 0x58, 0x11, 0x80, 0x10, 0x50, 0x9f, 0x00, 0x02, 0xac, 0x77, +0x14, 0x93, 0x00, 0x02, 0xa0, 0x32, 0x46, 0x80, 0x01, 0x02, 0x58, 0x84, 0x06, 0xd4, 0x46, 0x10, +0x00, 0x0b, 0x58, 0x10, 0x86, 0x44, 0x84, 0x46, 0x4b, 0xe0, 0x20, 0x01, 0xc0, 0x0a, 0xa0, 0x32, +0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x86, 0x4c, 0x84, 0x46, 0x4b, 0xe0, 0x20, 0x01, 0xc8, 0x74, +0xa0, 0x72, 0xa4, 0xf6, 0x9c, 0x4e, 0x51, 0xe1, 0xff, 0xfa, 0x13, 0xe3, 0x00, 0x06, 0xa8, 0x72, +0x84, 0x42, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x86, 0xf0, 0xdd, 0x2f, +0x04, 0x93, 0x00, 0x02, 0xa4, 0x36, 0x50, 0x54, 0x80, 0x02, 0x9e, 0x82, 0x84, 0x82, 0xa9, 0x72, +0xac, 0xb6, 0x4c, 0x72, 0x00, 0x1a, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x27, 0x81, 0xc8, 0x97, 0x14, +0xc4, 0x13, 0x50, 0x03, 0x7f, 0xf8, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x86, 0x44, 0xdd, 0x2f, +0x84, 0xa1, 0xd8, 0x0a, 0x50, 0x23, 0x7f, 0xf8, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, +0x81, 0xa8, 0xdd, 0x2f, 0xd5, 0x41, 0x50, 0x9f, 0x80, 0x04, 0x46, 0x80, 0x01, 0x02, 0x58, 0x84, +0x06, 0xd4, 0x80, 0x09, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x86, 0x54, 0x84, 0x42, 0x4b, 0xe0, +0x20, 0x01, 0xc0, 0x32, 0x80, 0x09, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x86, 0x5c, 0x84, 0x42, +0x4b, 0xe0, 0x20, 0x01, 0xc8, 0x03, 0x84, 0xa2, 0xdf, 0x27, 0x50, 0x8f, 0x80, 0x04, 0x46, 0x70, +0x01, 0x02, 0x58, 0x73, 0x86, 0xd4, 0x80, 0x08, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x86, 0x60, +0x84, 0x42, 0x4b, 0xe0, 0x1c, 0x01, 0xc0, 0x18, 0x80, 0x08, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, +0x86, 0x58, 0x84, 0x42, 0x4b, 0xe0, 0x1c, 0x01, 0xc8, 0x0f, 0xa0, 0x72, 0x84, 0xa3, 0x01, 0xe0, +0x80, 0x01, 0x4d, 0xe2, 0xc0, 0x0a, 0xa4, 0xb6, 0x50, 0x03, 0x7f, 0xf8, 0x46, 0xf0, 0x00, 0x00, +0x58, 0xf7, 0x8f, 0x44, 0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x88, 0x0c, 0x46, 0xf0, +0x00, 0x0b, 0x14, 0x17, 0x81, 0xe8, 0x46, 0x40, 0x04, 0x00, 0x05, 0xe2, 0x00, 0x08, 0x42, 0x5f, +0x40, 0x09, 0x14, 0x52, 0x00, 0x08, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x82, 0x00, 0xdd, 0x2f, +0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x07, 0x8c, 0xb4, 0x60, 0xb6, 0x60, 0xa0, 0x81, 0xa8, 0x81, +0xa0, 0x42, 0xa8, 0x42, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x82, 0x4c, 0xdd, 0x2f, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x82, 0x70, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x82, 0xec, +0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x85, 0x90, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x46, 0x40, 0x00, 0x0e, 0x58, 0x42, 0x03, 0x38, 0x38, 0x12, 0x02, 0x0a, +0x46, 0x10, 0x04, 0x10, 0x58, 0x10, 0x88, 0x00, 0x04, 0x50, 0x80, 0x78, 0x84, 0x41, 0x40, 0x41, +0x00, 0x0c, 0x40, 0x32, 0x14, 0x04, 0x14, 0x30, 0x80, 0x78, 0x04, 0x20, 0x80, 0x7a, 0x40, 0x02, +0x08, 0x04, 0x14, 0x00, 0x80, 0x7a, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, 0x46, 0x00, +0x04, 0x10, 0x58, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00, 0x78, 0x96, 0x40, 0x96, 0x8c, 0xc2, 0x07, +0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x80, 0xce, 0x84, 0x01, 0xd5, 0x68, 0x54, 0x10, 0x80, 0x02, +0xc1, 0x07, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x80, 0xcf, 0x84, 0x02, 0xd5, 0x5f, 0x41, 0xe0, +0x40, 0x09, 0x54, 0x1f, 0x00, 0xff, 0x54, 0x50, 0x80, 0x02, 0xc5, 0x08, 0x46, 0xf0, 0x00, 0x0e, +0x04, 0x17, 0x80, 0xdf, 0x44, 0x02, 0x00, 0x00, 0xd5, 0x51, 0x96, 0xcc, 0xc3, 0x08, 0x46, 0xf0, +0x00, 0x0e, 0x04, 0x17, 0x80, 0xde, 0x44, 0x01, 0x00, 0x00, 0xd5, 0x48, 0x40, 0x10, 0x60, 0x09, +0x97, 0x0c, 0xc4, 0x08, 0x46, 0x00, 0x10, 0x00, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x80, 0xe6, +0xd5, 0x3d, 0x54, 0x50, 0x80, 0x02, 0xc5, 0x08, 0x46, 0x00, 0x20, 0x00, 0x46, 0xf0, 0x00, 0x0e, +0x04, 0x17, 0x80, 0xe7, 0xd5, 0x33, 0x54, 0x20, 0x80, 0x04, 0xc2, 0x08, 0x46, 0x00, 0x40, 0x00, +0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x80, 0xe8, 0xd5, 0x29, 0x54, 0x40, 0x80, 0x10, 0xc4, 0x08, +0x46, 0x01, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x80, 0xea, 0xd5, 0x1f, 0x54, 0x50, +0x80, 0x20, 0xc5, 0x08, 0x46, 0x02, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x80, 0xeb, +0xd5, 0x15, 0x54, 0x20, 0x80, 0x40, 0xc2, 0x08, 0x46, 0x04, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x0e, +0x04, 0x17, 0x80, 0xec, 0xd5, 0x0b, 0x54, 0x40, 0x80, 0x80, 0x96, 0x60, 0xc1, 0x07, 0x46, 0xf0, +0x00, 0x0e, 0x04, 0x17, 0x80, 0xed, 0x46, 0x08, 0x00, 0x00, 0x47, 0xe0, 0x04, 0x10, 0x59, 0xef, +0x08, 0x00, 0x14, 0x0f, 0x00, 0x78, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0xc4, 0x04, 0x5f, +0x00, 0x78, 0xf5, 0x81, 0xdd, 0x21, 0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x44, 0x40, 0x00, 0x40, 0x84, 0xa0, 0xf5, 0x81, 0x46, 0x10, +0x04, 0x10, 0x10, 0x4f, 0x80, 0x04, 0x10, 0x4f, 0x80, 0x07, 0x58, 0x10, 0x88, 0x00, 0xb4, 0x61, +0x50, 0x60, 0x00, 0x9c, 0x58, 0x01, 0x80, 0x02, 0xb6, 0x01, 0x80, 0x01, 0xf2, 0x01, 0x14, 0x20, +0x80, 0x71, 0x04, 0x70, 0x00, 0x71, 0x42, 0x93, 0x8c, 0x0b, 0xf7, 0x81, 0x81, 0x01, 0x4e, 0x93, +0xff, 0xfa, 0x42, 0x73, 0x84, 0x0b, 0xcf, 0xf6, 0x46, 0x90, 0x00, 0x03, 0x58, 0x94, 0x8e, 0x68, +0x50, 0x13, 0x7f, 0x64, 0x50, 0x23, 0x7f, 0xe4, 0x50, 0x04, 0x01, 0xa0, 0x84, 0x62, 0x4b, 0xe0, +0x24, 0x01, 0x46, 0x00, 0x04, 0x10, 0x50, 0x13, 0x7f, 0x84, 0x50, 0x23, 0x7f, 0xec, 0x58, 0x00, +0x09, 0xb0, 0x84, 0x62, 0x4b, 0xe0, 0x24, 0x01, 0x46, 0x00, 0x04, 0x10, 0x46, 0x90, 0x00, 0x03, +0x58, 0x94, 0x8e, 0x1c, 0x50, 0x13, 0x7f, 0xa4, 0x50, 0x23, 0x7f, 0xf4, 0x58, 0x00, 0x09, 0x80, +0x84, 0x62, 0x4b, 0xe0, 0x24, 0x01, 0x46, 0x00, 0x04, 0x10, 0x50, 0x13, 0x7f, 0xc4, 0x9e, 0xb4, +0x58, 0x00, 0x09, 0x90, 0x84, 0x62, 0x4b, 0xe0, 0x24, 0x01, 0x84, 0x61, 0xaf, 0xf5, 0xaf, 0xf4, +0x10, 0x34, 0x01, 0xa8, 0x10, 0x34, 0x01, 0xb8, 0x14, 0x73, 0x00, 0x09, 0xaf, 0xf7, 0xaf, 0xf6, +0xa9, 0xf4, 0xa9, 0xf5, 0xa9, 0xf2, 0xa9, 0xf3, 0x50, 0x03, 0x00, 0x1c, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x8f, 0xb0, 0xdd, 0x2f, 0x04, 0x04, 0x00, 0x71, 0x58, 0x20, 0x00, 0x05, 0xf0, 0x81, +0x10, 0x2f, 0x80, 0x04, 0xf1, 0x01, 0x14, 0x14, 0x00, 0x71, 0xec, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x04, 0x20, 0x00, 0x2d, 0x42, 0x11, 0x40, 0x08, 0x14, 0x10, 0x00, 0x2d, +0xdd, 0x9e, 0x92, 0x00, 0x04, 0x20, 0x00, 0x2d, 0x42, 0x11, 0x44, 0x08, 0x14, 0x10, 0x00, 0x2d, +0xdd, 0x9e, 0x92, 0x00, 0x04, 0x20, 0x00, 0x2d, 0x58, 0x11, 0x00, 0x01, 0x14, 0x10, 0x00, 0x2d, +0xdd, 0x9e, 0x92, 0x00, 0x04, 0x20, 0x00, 0x2d, 0x58, 0x11, 0x00, 0x02, 0x14, 0x10, 0x00, 0x2d, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0x3c, 0xef, 0xf4, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, +0x08, 0x00, 0x50, 0x10, 0x00, 0x80, 0x85, 0x20, 0x04, 0x40, 0x00, 0x43, 0x40, 0x32, 0x40, 0x09, +0x54, 0x31, 0x80, 0x0f, 0x80, 0x40, 0xc3, 0x64, 0x84, 0x40, 0x97, 0x5c, 0xc5, 0x5c, 0x54, 0x61, +0x00, 0x03, 0x14, 0x60, 0x00, 0x43, 0x84, 0xc0, 0x04, 0x80, 0x00, 0x43, 0x40, 0x44, 0x20, 0x09, +0x54, 0x42, 0x00, 0x7f, 0x40, 0x72, 0x20, 0x08, 0x40, 0x53, 0x90, 0x04, 0x14, 0x50, 0x00, 0x1d, +0x44, 0x7f, 0xff, 0xc7, 0x04, 0xa0, 0x80, 0x02, 0xb5, 0x01, 0x14, 0xaf, 0x80, 0x01, 0x8d, 0x04, +0x00, 0xaf, 0x80, 0x07, 0x80, 0xa4, 0x40, 0xa5, 0x1c, 0x02, 0x58, 0xa5, 0x00, 0x20, 0x10, 0xaf, +0x80, 0x07, 0x54, 0x74, 0x00, 0x7f, 0x40, 0xa4, 0x1c, 0x09, 0x40, 0x74, 0x9c, 0x06, 0x04, 0x8f, +0x80, 0x01, 0x88, 0xea, 0x14, 0x80, 0x80, 0x02, 0x50, 0x83, 0xff, 0xff, 0xd5, 0x08, 0x14, 0xa0, +0x00, 0x1b, 0x9d, 0xb1, 0x04, 0xa0, 0x00, 0x1b, 0x54, 0x55, 0x00, 0x7f, 0x40, 0xa2, 0xa0, 0x08, +0xe2, 0xc8, 0xe9, 0xf6, 0x54, 0x63, 0x80, 0x7f, 0x40, 0x63, 0x20, 0x08, 0x40, 0x52, 0xc0, 0x08, +0x58, 0x73, 0x00, 0x02, 0x58, 0x63, 0x00, 0x18, 0x40, 0x73, 0x94, 0x04, 0x40, 0x53, 0x14, 0x04, +0x46, 0x68, 0x0f, 0xff, 0x58, 0x63, 0x0f, 0xff, 0x40, 0x42, 0x60, 0x08, 0x40, 0x52, 0x98, 0x02, +0x40, 0x73, 0x98, 0x02, 0x40, 0x73, 0x90, 0x04, 0x40, 0x42, 0x90, 0x04, 0x14, 0x40, 0x00, 0x44, +0x14, 0x70, 0x00, 0x45, 0x9c, 0x91, 0x84, 0xa4, 0xd2, 0x98, 0x92, 0x61, 0xd5, 0x9f, 0x46, 0x00, +0x20, 0x00, 0x14, 0x01, 0x00, 0x78, 0xec, 0x0c, 0x3a, 0x6f, 0xa8, 0x04, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa8, 0x3c, 0xef, 0xf4, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x08, 0x00, 0x50, 0x10, +0x00, 0x80, 0x85, 0x20, 0x04, 0x40, 0x00, 0x40, 0x40, 0x32, 0x40, 0x09, 0x54, 0x31, 0x80, 0x0f, +0x80, 0x40, 0xc3, 0x6a, 0x84, 0x40, 0x97, 0x5c, 0xc5, 0x62, 0x54, 0x61, 0x00, 0x03, 0x14, 0x60, +0x00, 0x40, 0x84, 0xc0, 0x04, 0x80, 0x00, 0x40, 0x40, 0x44, 0x20, 0x09, 0x54, 0x42, 0x00, 0x7f, +0x40, 0x72, 0x20, 0x08, 0x40, 0x53, 0x90, 0x04, 0x14, 0x50, 0x00, 0x1d, 0x44, 0x7f, 0xff, 0xc7, +0x04, 0xa0, 0x80, 0x02, 0xb5, 0x01, 0x14, 0xaf, 0x80, 0x01, 0x8d, 0x04, 0x00, 0xaf, 0x80, 0x07, +0x80, 0xa4, 0x40, 0xa5, 0x1c, 0x02, 0x58, 0xa5, 0x00, 0x28, 0x10, 0xaf, 0x80, 0x07, 0x54, 0x74, +0x00, 0x7f, 0x40, 0xa4, 0x1c, 0x09, 0x40, 0x74, 0x9c, 0x06, 0x04, 0x8f, 0x80, 0x01, 0x88, 0xea, +0x14, 0x80, 0x80, 0x02, 0x50, 0x83, 0xff, 0xff, 0xd5, 0x08, 0x14, 0xa0, 0x00, 0x1b, 0x9d, 0xb1, +0x04, 0xa0, 0x00, 0x1b, 0x54, 0x55, 0x00, 0x7f, 0x40, 0xa2, 0xa0, 0x08, 0xe2, 0xc8, 0xe9, 0xf6, +0x00, 0x8f, 0x80, 0x07, 0x54, 0x63, 0x80, 0x7f, 0x40, 0x74, 0x04, 0x09, 0x40, 0x63, 0x20, 0x08, +0x54, 0x73, 0x80, 0x03, 0x40, 0x82, 0xc0, 0x08, 0x40, 0x73, 0x98, 0x04, 0x40, 0x53, 0xa0, 0x04, +0x58, 0x63, 0x00, 0x02, 0x46, 0x78, 0x0f, 0xff, 0x40, 0x63, 0x20, 0x04, 0x58, 0x73, 0x8f, 0xff, +0x40, 0x82, 0x60, 0x08, 0x40, 0x52, 0x9c, 0x02, 0x40, 0x63, 0x1c, 0x02, 0x40, 0x63, 0x20, 0x04, +0x40, 0x42, 0xa0, 0x04, 0x14, 0x40, 0x00, 0x41, 0x14, 0x60, 0x00, 0x42, 0x9c, 0x91, 0x84, 0xa4, +0xd2, 0x92, 0x92, 0x61, 0xd5, 0x99, 0x46, 0x00, 0x10, 0x00, 0x14, 0x01, 0x00, 0x78, 0xec, 0x0c, +0x3a, 0x6f, 0xa8, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0x3c, 0x04, 0x50, 0x00, 0x29, +0x04, 0x30, 0x00, 0x2a, 0x9d, 0x2a, 0x9a, 0xa3, 0xe4, 0x42, 0x4e, 0xf3, 0x00, 0x85, 0x00, 0x30, +0x00, 0xa2, 0x9c, 0x9c, 0x40, 0x81, 0x10, 0x08, 0x40, 0x20, 0x20, 0x00, 0xa7, 0xd7, 0x54, 0x63, +0x80, 0x80, 0xc6, 0x79, 0xb5, 0x01, 0x50, 0x41, 0x80, 0x24, 0x38, 0x80, 0x12, 0x0a, 0x00, 0x70, +0x80, 0x9f, 0x00, 0x50, 0x80, 0x9e, 0xa1, 0x0b, 0x99, 0xbd, 0x50, 0x73, 0x00, 0x14, 0x50, 0x50, +0x80, 0x10, 0x02, 0x81, 0x00, 0x03, 0x95, 0x9c, 0xc4, 0x22, 0x93, 0x0e, 0x40, 0x84, 0x38, 0x08, +0x40, 0x74, 0x1c, 0x04, 0xad, 0xd3, 0xb6, 0xa2, 0xa7, 0x17, 0x42, 0x42, 0x18, 0x09, 0xaf, 0x17, +0x99, 0x86, 0xa1, 0x4a, 0x14, 0x53, 0x00, 0x12, 0xa1, 0x0b, 0xa4, 0x52, 0x54, 0x42, 0x3f, 0xff, +0x92, 0x2e, 0x40, 0x10, 0xb8, 0x08, 0x40, 0x50, 0x90, 0x04, 0xad, 0x52, 0xa7, 0x17, 0xa6, 0x55, +0x54, 0x52, 0x00, 0x7f, 0x58, 0x10, 0x80, 0x40, 0xaf, 0x57, 0xd5, 0x1b, 0x93, 0x0e, 0x40, 0x84, +0x38, 0x08, 0x40, 0x74, 0x1c, 0x04, 0xad, 0xd3, 0x99, 0x86, 0xa6, 0x57, 0xb6, 0xa2, 0x58, 0x10, +0x80, 0x40, 0xae, 0x57, 0x14, 0x43, 0x00, 0x12, 0xa4, 0x52, 0xa7, 0x17, 0x92, 0x2e, 0x40, 0x10, +0xb8, 0x08, 0xac, 0x52, 0x54, 0x42, 0x00, 0x7f, 0xa6, 0x55, 0xaf, 0x17, 0x42, 0x10, 0x98, 0x09, +0x95, 0x1c, 0xae, 0x55, 0x98, 0x44, 0x50, 0x10, 0x80, 0x48, 0xa6, 0x8e, 0x44, 0x5f, 0xff, 0xcf, +0x40, 0x41, 0x14, 0x02, 0x58, 0x22, 0x00, 0x08, 0x9c, 0xdc, 0x84, 0x84, 0xaf, 0x0f, 0xae, 0x8e, +0x40, 0x51, 0x90, 0x0c, 0x99, 0x05, 0xa4, 0xa3, 0xb4, 0x61, 0x54, 0x51, 0x3f, 0xff, 0x99, 0x1d, +0xad, 0x0a, 0x46, 0x40, 0x04, 0x10, 0x00, 0x20, 0x00, 0xa2, 0x04, 0x50, 0x00, 0x2a, 0x9c, 0x51, +0x96, 0x8c, 0x9c, 0xe9, 0x58, 0x42, 0x08, 0x00, 0x14, 0x30, 0x00, 0x2a, 0x10, 0x20, 0x00, 0xa2, +0x10, 0x22, 0x01, 0x88, 0x3a, 0x6f, 0xa0, 0x04, 0xdd, 0x9e, 0x92, 0x00, 0x04, 0x50, 0x00, 0x2b, +0x04, 0x30, 0x00, 0x2c, 0x9d, 0x2a, 0x9a, 0xa3, 0xe4, 0x42, 0xe9, 0x40, 0x00, 0x30, 0x00, 0xa3, +0x9d, 0x1e, 0x94, 0xa4, 0x98, 0x82, 0xa7, 0x57, 0x54, 0x42, 0x80, 0x80, 0xc4, 0x37, 0x50, 0x51, +0x80, 0x26, 0x38, 0x10, 0x16, 0x0a, 0x94, 0xdc, 0xa1, 0x0a, 0x98, 0xc3, 0xb6, 0x82, 0xa1, 0x4c, +0x14, 0x51, 0x80, 0x1b, 0xa5, 0x0e, 0xa4, 0xd3, 0x54, 0x42, 0x3f, 0xff, 0x92, 0x6e, 0x40, 0x31, +0xb8, 0x08, 0x40, 0x51, 0x90, 0x04, 0xad, 0x53, 0xa7, 0x55, 0x00, 0x40, 0x80, 0x0f, 0xa6, 0xd7, +0x96, 0x64, 0x95, 0x0e, 0x54, 0x11, 0x80, 0x3f, 0x40, 0x30, 0x90, 0x04, 0x54, 0x12, 0x80, 0x7f, +0xae, 0xd7, 0xae, 0x55, 0x46, 0x10, 0x04, 0x10, 0x00, 0x50, 0x00, 0xa3, 0x04, 0x40, 0x00, 0x2c, +0x9c, 0xa9, 0x97, 0x54, 0x9c, 0xe1, 0x58, 0x10, 0x88, 0x00, 0x14, 0x30, 0x00, 0x2c, 0x10, 0x50, +0x00, 0xa3, 0x10, 0x50, 0x81, 0x98, 0x84, 0x01, 0xd5, 0x02, 0x84, 0x00, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x85, 0x20, 0x80, 0xc0, 0x46, 0x80, 0x00, 0x00, 0x58, 0x84, +0x03, 0x68, 0xd5, 0x22, 0xa7, 0x1f, 0x54, 0x22, 0x00, 0x80, 0xc2, 0x30, 0x38, 0x23, 0x06, 0x02, +0x38, 0x93, 0x06, 0x0a, 0x80, 0x22, 0x00, 0x31, 0x00, 0x14, 0xcb, 0x02, 0xd5, 0x05, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x04, 0xa4, 0x4b, 0xe0, 0x20, 0x01, 0x9c, 0x3e, 0x94, 0xc4, 0x99, 0xf3, +0xa6, 0xbf, 0x44, 0x4f, 0xff, 0xc0, 0x40, 0x51, 0x10, 0x04, 0xaf, 0x7f, 0x04, 0x13, 0x00, 0x2b, +0x9c, 0x09, 0x14, 0x03, 0x00, 0x2b, 0x04, 0x23, 0x00, 0x2b, 0x04, 0x53, 0x00, 0x2c, 0x97, 0xd4, +0x9c, 0x7e, 0x95, 0x0c, 0x41, 0xe2, 0x88, 0x01, 0x50, 0x13, 0x80, 0x26, 0x98, 0xf4, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x04, 0xb4, 0x4f, 0xe6, 0xff, 0xcf, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x85, 0x20, 0x80, 0xc0, 0x46, 0x80, +0x00, 0x00, 0x58, 0x84, 0x03, 0x68, 0xd5, 0x1a, 0xa6, 0xff, 0x54, 0x11, 0x80, 0x80, 0xc1, 0x28, +0x38, 0x13, 0x0a, 0x02, 0x38, 0x93, 0x0a, 0x0a, 0x4b, 0xe0, 0x20, 0x01, 0xa6, 0x7f, 0xa6, 0xfd, +0x44, 0x0f, 0xff, 0xc0, 0x40, 0x50, 0x80, 0x04, 0x58, 0x41, 0x80, 0x40, 0xaf, 0x7f, 0xaf, 0x3d, +0x04, 0x23, 0x00, 0x29, 0x9c, 0x11, 0x14, 0x03, 0x00, 0x29, 0x04, 0x43, 0x00, 0x29, 0x04, 0x53, +0x00, 0x2a, 0x96, 0x64, 0x9c, 0xcc, 0x95, 0xdc, 0x41, 0xe2, 0x90, 0x01, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x04, 0xa4, 0x50, 0x20, 0x80, 0x24, 0x99, 0xf7, 0x4f, 0xe6, 0xff, 0xd7, 0xec, 0x04, +0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x83, 0x80, +0x50, 0x00, 0x00, 0xb8, 0x46, 0x40, 0x04, 0x10, 0xf0, 0x81, 0x58, 0x42, 0x08, 0x00, 0x00, 0x7e, +0x00, 0xa1, 0x00, 0x12, 0x01, 0xbc, 0x9d, 0x7a, 0x94, 0xac, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, +0x04, 0xa4, 0x50, 0xa3, 0x80, 0x22, 0x40, 0x6e, 0x08, 0x00, 0x4c, 0x70, 0x80, 0x55, 0xa6, 0x77, +0x55, 0xe0, 0x80, 0x80, 0x4f, 0xe2, 0x00, 0x50, 0x02, 0x83, 0x00, 0x03, 0xb6, 0x9f, 0x46, 0xf0, +0x00, 0x00, 0x58, 0xf7, 0x83, 0x24, 0xdd, 0x2f, 0x54, 0x94, 0x3f, 0xff, 0x95, 0x3c, 0x81, 0x00, +0x40, 0x3e, 0x10, 0x00, 0xf0, 0x01, 0xb4, 0x9f, 0x4e, 0x83, 0x00, 0x07, 0xbb, 0x2d, 0x42, 0x01, +0xc4, 0x08, 0xb8, 0xad, 0xd5, 0x38, 0x39, 0xee, 0x2a, 0x02, 0x84, 0x41, 0x12, 0x9f, 0x00, 0x06, +0x80, 0x3e, 0x04, 0x51, 0x80, 0x0b, 0x10, 0x2f, 0x00, 0x14, 0x14, 0x5f, 0x00, 0x04, 0xb6, 0x9f, +0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x83, 0x68, 0xdd, 0x2f, 0x38, 0x8e, 0x2a, 0x0a, 0x80, 0x06, +0x84, 0x20, 0x44, 0x20, 0x00, 0x10, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, +0xa6, 0xf7, 0x04, 0x84, 0x00, 0x02, 0x58, 0x01, 0x80, 0x40, 0xae, 0x37, 0xa4, 0x73, 0xb7, 0x06, +0x40, 0x50, 0xb8, 0x09, 0x40, 0x52, 0xb8, 0x08, 0x58, 0x22, 0x86, 0x40, 0xac, 0xb3, 0xb4, 0x9f, +0x10, 0x72, 0x01, 0xb8, 0x00, 0xae, 0x00, 0xa1, 0x50, 0x75, 0x00, 0x01, 0x97, 0xbc, 0x10, 0x6e, +0x00, 0xa1, 0xd5, 0x9e, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xf4, 0x83, 0x80, 0x50, 0x00, 0x00, 0xb8, 0x46, 0x40, 0x04, 0x10, 0xf0, 0x81, 0x58, 0x42, +0x08, 0x00, 0x00, 0x7e, 0x00, 0xa0, 0x00, 0x52, 0x01, 0xac, 0x94, 0xbc, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x04, 0xb4, 0x50, 0xa3, 0x80, 0x20, 0x40, 0x6e, 0x08, 0x00, 0xd7, 0x54, 0x01, 0xe3, +0x00, 0x07, 0x54, 0x5f, 0x00, 0x80, 0xc5, 0x4f, 0x02, 0x83, 0x00, 0x03, 0xb6, 0x9f, 0x46, 0xf0, +0x00, 0x00, 0x58, 0xf7, 0x83, 0x24, 0xdd, 0x2f, 0x98, 0x7f, 0x54, 0x94, 0x3f, 0xff, 0x81, 0x00, +0x9c, 0x09, 0x95, 0x03, 0x40, 0x3e, 0x10, 0x00, 0xf0, 0x01, 0xb4, 0x9f, 0x4e, 0x83, 0x00, 0x06, +0x44, 0x31, 0x00, 0x00, 0xbb, 0xad, 0xd5, 0x37, 0x39, 0xee, 0x2a, 0x02, 0x84, 0x40, 0x12, 0x9f, +0x00, 0x06, 0x80, 0x3e, 0xa1, 0x59, 0x10, 0x2f, 0x00, 0x14, 0x14, 0x5f, 0x00, 0x04, 0xb6, 0x9f, +0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x83, 0x68, 0xdd, 0x2f, 0x38, 0x8e, 0x2a, 0x0a, 0x80, 0x06, +0x84, 0x20, 0x44, 0x20, 0x00, 0x10, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x87, 0x08, 0xdd, 0x2f, +0xa6, 0xf7, 0x04, 0x84, 0x00, 0x02, 0x58, 0x11, 0x80, 0x40, 0xae, 0x77, 0xa5, 0x33, 0xb7, 0x06, +0x40, 0x52, 0x38, 0x09, 0x40, 0x52, 0xb8, 0x08, 0x58, 0x22, 0x80, 0xc8, 0xac, 0xb3, 0xb4, 0x9f, +0x10, 0x72, 0x01, 0xa8, 0x00, 0xae, 0x00, 0xa0, 0x50, 0x75, 0x00, 0x01, 0x97, 0xbc, 0x10, 0x6e, +0x00, 0xa0, 0xd5, 0xa0, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xfc, 0xb6, 0x20, 0xa8, 0xc1, 0x80, 0xc1, 0xa0, 0x43, 0x84, 0xe0, 0x81, 0x23, 0x81, 0x02, +0xa8, 0x42, 0x47, 0xc0, 0x01, 0x02, 0x59, 0xce, 0x07, 0x08, 0x81, 0x47, 0xd5, 0x0c, 0xdd, 0x3c, +0xa6, 0xb7, 0x44, 0x3f, 0xff, 0xc0, 0x40, 0x01, 0x0c, 0x04, 0xae, 0x37, 0x1c, 0xa4, 0x00, 0x01, +0x9d, 0xf9, 0x8c, 0xd0, 0x80, 0x06, 0x84, 0x20, 0x44, 0x20, 0x00, 0x10, 0xe2, 0xe9, 0xe9, 0xf0, +0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0xb6, 0x20, +0xa8, 0xc1, 0x46, 0x80, 0x04, 0x10, 0x04, 0x90, 0x00, 0x03, 0x58, 0x84, 0x09, 0xb0, 0x14, 0x90, +0x00, 0x02, 0x44, 0x70, 0x06, 0x40, 0x83, 0x83, 0x80, 0xc1, 0x46, 0x30, 0x00, 0x0e, 0x58, 0x31, +0x84, 0xa4, 0x40, 0x10, 0x20, 0x03, 0x44, 0x50, 0x00, 0xc8, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, +0x04, 0xb4, 0x40, 0x41, 0x84, 0x1a, 0x40, 0x40, 0x04, 0x1b, 0x40, 0x82, 0x84, 0x1b, 0x40, 0x83, +0x84, 0x1a, 0x84, 0xe0, 0xf4, 0x83, 0x81, 0x42, 0x46, 0x40, 0x01, 0x02, 0x58, 0x42, 0x07, 0x08, +0x81, 0x27, 0x54, 0x34, 0x3f, 0xff, 0xd5, 0x26, 0xf3, 0x81, 0xf4, 0x82, 0xdd, 0x24, 0xf0, 0x03, +0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x83, 0x24, 0xdd, 0x2f, 0xf3, 0x01, 0xf4, 0x02, 0xc0, 0x20, +0x12, 0x80, 0x00, 0x06, 0x10, 0x90, 0x00, 0x0e, 0x10, 0x90, 0x00, 0x0f, 0xa6, 0x77, 0x9d, 0xf9, +0x55, 0xe0, 0x80, 0x3f, 0x11, 0xe3, 0x00, 0x07, 0xa5, 0x73, 0x40, 0x12, 0xb8, 0x09, 0x40, 0x10, +0xb8, 0x08, 0x41, 0xe0, 0x8c, 0x04, 0x13, 0xe3, 0x00, 0x03, 0xa0, 0x82, 0xaa, 0xb4, 0x1c, 0x05, +0x00, 0x01, 0x80, 0x06, 0x84, 0x20, 0x44, 0x20, 0x00, 0x10, 0xe2, 0xfc, 0xe9, 0xd6, 0xec, 0x14, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x01, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0xc4, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, +0x87, 0xb9, 0x84, 0xa1, 0xd8, 0x0b, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x04, 0xb4, 0x80, +0x54, 0x32, 0x01, 0xfd, 0x58, 0x11, 0x80, 0x02, 0xd5, 0x08, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, +0x00, 0x04, 0xb4, 0xa0, 0x54, 0x12, 0x81, 0xfd, 0xb6, 0x20, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x86, 0xc4, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x46, 0x60, 0x04, 0x00, 0x58, 0x63, 0x00, 0x04, 0x84, 0xe0, +0x85, 0x08, 0x46, 0x90, 0x00, 0x04, 0x58, 0x94, 0x86, 0xc4, 0x84, 0x01, 0x4b, 0xe0, 0x24, 0x01, +0xb4, 0x46, 0x99, 0xff, 0x54, 0x11, 0x00, 0x08, 0x84, 0x01, 0x97, 0xf8, 0xc1, 0x03, 0x40, 0x73, +0x80, 0x04, 0x05, 0xe3, 0x00, 0x00, 0x8f, 0x01, 0x54, 0x5f, 0x01, 0xfe, 0x58, 0x42, 0x80, 0x01, +0xb6, 0x86, 0x54, 0x84, 0x00, 0xff, 0x4b, 0xe0, 0x24, 0x01, 0xb4, 0x66, 0x54, 0x01, 0x81, 0xfe, +0xb6, 0x06, 0x4e, 0x83, 0xff, 0xe4, 0x84, 0x08, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0xc4, +0xdd, 0x2f, 0x80, 0x07, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, +0xef, 0xfc, 0x46, 0x60, 0x04, 0x00, 0x97, 0xc0, 0x58, 0x63, 0x00, 0x04, 0x85, 0x28, 0x46, 0x80, +0x00, 0x04, 0x58, 0x84, 0x06, 0xc4, 0xb4, 0x46, 0x40, 0x33, 0x9c, 0x09, 0x94, 0x5a, 0x55, 0xe1, +0x01, 0xfb, 0x40, 0x00, 0xf8, 0x04, 0xb6, 0x06, 0x84, 0x01, 0x4b, 0xe0, 0x20, 0x01, 0xb4, 0xa6, +0x84, 0x01, 0x54, 0x42, 0x81, 0xfe, 0x40, 0x32, 0x00, 0x04, 0xb6, 0x66, 0x8f, 0x21, 0x4b, 0xe0, +0x20, 0x01, 0xb4, 0x46, 0x84, 0x01, 0x54, 0x11, 0x01, 0xfe, 0xb6, 0x26, 0x99, 0xff, 0x54, 0x94, +0x80, 0xff, 0x4b, 0xe0, 0x20, 0x01, 0x97, 0xf8, 0x4e, 0x93, 0xff, 0xdf, 0x84, 0x0a, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x86, 0xc4, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x98, 0xbc, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x87, 0xb9, 0x84, 0xa1, 0xd8, 0x16, +0x46, 0x60, 0x04, 0x00, 0x58, 0x63, 0x00, 0x04, 0x05, 0xe3, 0x00, 0x00, 0x54, 0x5f, 0x01, 0xfd, +0x58, 0x42, 0x80, 0x02, 0xb6, 0x86, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0xc4, 0xdd, 0x2f, +0xb4, 0x66, 0x54, 0x21, 0x81, 0xfd, 0xb6, 0x46, 0xd5, 0x09, 0x46, 0x60, 0x04, 0x00, 0xa0, 0xb1, +0x54, 0x01, 0x01, 0xfd, 0x58, 0x10, 0x00, 0x02, 0xa8, 0x71, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x86, 0xc4, 0xdd, 0x2f, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x80, 0x60, 0xdd, 0x2f, 0x84, 0x05, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x8f, 0xec, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8f, 0x80, 0xdd, 0x2f, +0x80, 0xc0, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8f, 0x28, 0xdd, 0x2f, 0x96, 0x34, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x97, 0x81, 0x97, 0xca, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x80, 0x60, 0xdd, 0x2f, 0x84, 0x03, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, +0x8f, 0xec, 0xdd, 0x2f, 0xcf, 0x05, 0x44, 0x00, 0xfc, 0x00, 0x40, 0x63, 0x00, 0x04, 0x46, 0x70, +0x00, 0x03, 0x58, 0x73, 0x8f, 0xec, 0x40, 0x03, 0x20, 0x09, 0x4b, 0xe0, 0x1c, 0x01, 0x96, 0x30, +0x4b, 0xe0, 0x1c, 0x01, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8f, 0x80, 0xdd, 0x2f, 0x80, 0xc0, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8f, 0x28, 0xdd, 0x2f, 0x80, 0x06, 0xec, 0x04, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x60, 0x00, 0x03, 0x58, 0x63, 0x0f, 0xec, +0x54, 0x80, 0x80, 0xff, 0x97, 0xc1, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x80, 0x60, 0xdd, 0x2f, +0x84, 0x02, 0xdd, 0x26, 0x40, 0x03, 0xa0, 0x09, 0xdd, 0x26, 0x96, 0x38, 0xdd, 0x26, 0x80, 0x08, +0xdd, 0x26, 0x46, 0x60, 0x00, 0x04, 0x58, 0x63, 0x00, 0xbc, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, +0x8f, 0x28, 0xdd, 0x2f, 0x4b, 0xe0, 0x18, 0x01, 0xc8, 0xfe, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x80, 0x60, 0xdd, 0x2f, +0x84, 0x04, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8f, 0xec, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x8f, 0x28, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x80, 0x60, 0xdd, 0x2f, +0x84, 0x06, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8f, 0xec, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x8f, 0x28, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x46, 0x10, 0x04, 0x00, 0x80, 0x01, 0x84, 0x48, 0x14, 0x20, 0x81, 0x06, 0x14, 0x20, 0x01, 0x0a, +0xdd, 0x9e, 0x92, 0x00, 0xef, 0xf8, 0x46, 0x10, 0x00, 0x0e, 0x04, 0x40, 0x80, 0xee, 0x46, 0x30, +0x04, 0x00, 0x9c, 0xa1, 0x14, 0x20, 0x80, 0xee, 0x58, 0x31, 0x84, 0x00, 0xb4, 0x03, 0x46, 0x10, +0x04, 0x00, 0x58, 0x50, 0x00, 0x11, 0xb6, 0xa3, 0x04, 0x40, 0x81, 0x06, 0x58, 0x22, 0x00, 0x80, +0x14, 0x20, 0x81, 0x06, 0xb4, 0x03, 0xf0, 0x81, 0xec, 0x08, 0xdd, 0x9e, 0x46, 0x30, 0x04, 0x00, +0x80, 0x03, 0x44, 0x20, 0x00, 0x4e, 0x44, 0x10, 0x00, 0x98, 0x14, 0x21, 0x81, 0x04, 0x14, 0x10, +0x01, 0x06, 0xdd, 0x9e, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xee, 0xdd, 0x9e, 0x92, 0x00, +0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x07, 0x98, 0x84, 0x80, 0xb6, 0x80, 0x84, 0x21, 0xb4, 0x60, +0xa8, 0xc1, 0xa8, 0x42, 0xb4, 0x40, 0xa1, 0x42, 0x9f, 0x29, 0x40, 0x32, 0x08, 0x02, 0x9c, 0x5a, +0x95, 0x4a, 0x98, 0xc5, 0x46, 0x40, 0x00, 0x0e, 0x58, 0x42, 0x07, 0x84, 0xa9, 0x19, 0xb4, 0x40, +0x9c, 0x51, 0xb6, 0x20, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x83, 0xb8, +0xb4, 0x41, 0x98, 0x02, 0xd5, 0x03, 0x64, 0x00, 0x00, 0x00, 0xb4, 0x81, 0x9a, 0xe0, 0x4e, 0x35, +0xff, 0xfc, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x80, 0xc0, 0x50, 0x0f, 0x80, 0x04, +0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0x3c, 0xdd, 0x2f, 0xa0, 0x32, 0xc0, 0x2d, 0x84, 0xa2, +0xd0, 0x2b, 0x84, 0xa3, 0xd8, 0x02, 0xd5, 0x28, 0xa0, 0x33, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x57, +0x80, 0xef, 0xd0, 0x07, 0xa0, 0x41, 0x05, 0xe3, 0x00, 0x01, 0x40, 0x50, 0xf8, 0x00, 0xa9, 0x41, +0xa0, 0x73, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0xbc, 0x4c, 0x13, 0x40, 0x05, 0x84, 0x40, +0xb6, 0x40, 0xd5, 0x0d, 0x05, 0xe3, 0x00, 0x04, 0x14, 0x1f, 0x00, 0x03, 0xa1, 0x33, 0xa1, 0x74, +0xa9, 0x64, 0xb4, 0x60, 0x4c, 0x33, 0x40, 0x04, 0xa0, 0x73, 0xb6, 0x20, 0x84, 0x00, 0x84, 0x43, +0xa8, 0x34, 0xa8, 0xb2, 0xa8, 0x33, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0x50, +0xdd, 0x2f, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, +0xef, 0xf4, 0x80, 0xe1, 0x80, 0xc0, 0xc1, 0x7a, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x8e, 0x3c, 0xdd, 0x2f, 0x84, 0x01, 0xa8, 0x32, 0x46, 0x30, 0x00, 0x0e, 0x04, 0x21, +0x80, 0xef, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0xc4, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, +0x83, 0xb8, 0xca, 0x0b, 0xa9, 0xb3, 0xa9, 0xb4, 0x14, 0x61, 0x80, 0xef, 0x46, 0xf0, 0x00, 0x0e, +0x14, 0x77, 0x80, 0xf0, 0xa9, 0xf1, 0xd5, 0x39, 0xb4, 0x21, 0xb4, 0x00, 0xe2, 0x20, 0xe8, 0x03, +0x9a, 0x01, 0xd5, 0x02, 0x9a, 0x08, 0x44, 0x10, 0x00, 0x21, 0x40, 0x00, 0x04, 0x37, 0xa0, 0x51, +0xe2, 0x01, 0xe8, 0x03, 0x9a, 0x08, 0xd5, 0x02, 0x84, 0x00, 0xa8, 0x11, 0xa0, 0xd1, 0x46, 0xf0, +0x00, 0x0e, 0x04, 0x17, 0x80, 0xef, 0x46, 0xf0, 0x00, 0x0e, 0x14, 0x37, 0x80, 0xf0, 0xa0, 0x11, +0xe2, 0xe0, 0xe8, 0x0b, 0x9a, 0x07, 0xa8, 0x11, 0x46, 0x00, 0x00, 0x0e, 0x04, 0x50, 0x00, 0xef, +0xda, 0x20, 0x14, 0x60, 0x00, 0xef, 0xd5, 0x1d, 0xa0, 0x93, 0x9b, 0xf8, 0x4c, 0x20, 0xff, 0xf1, +0xd5, 0x18, 0x14, 0x00, 0x80, 0xf0, 0xc0, 0x0c, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x83, 0xb8, +0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x03, 0xc4, 0xb4, 0x41, 0xb6, 0x40, 0xd5, 0x03, 0x84, 0x22, +0xa8, 0x72, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0x50, 0xdd, 0x2f, 0xd5, 0x16, +0xa8, 0xb3, 0xa0, 0x14, 0x46, 0x10, 0x00, 0x0e, 0xa8, 0x34, 0x05, 0xe1, 0x00, 0x04, 0x14, 0x6f, +0x00, 0x03, 0xa9, 0x94, 0xa9, 0xf1, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x37, 0x80, 0xef, 0x04, 0x40, +0x80, 0xf0, 0xa0, 0x19, 0xe2, 0x80, 0xe8, 0xd6, 0xd5, 0xe5, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, +0x00, 0x05, 0x58, 0xf7, 0x8e, 0x3c, 0xdd, 0x2f, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x87, 0x98, +0xa0, 0xc9, 0xa1, 0x4a, 0xf0, 0x01, 0x9f, 0x29, 0x40, 0x22, 0x0c, 0x02, 0x9d, 0x92, 0x95, 0x72, +0x99, 0x0d, 0xa1, 0xa1, 0xa0, 0xc9, 0x9c, 0x99, 0xa8, 0x89, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, +0x8e, 0x50, 0xdd, 0x2f, 0x84, 0x00, 0xa8, 0x34, 0xb6, 0x06, 0xa8, 0x31, 0xa8, 0x32, 0xa8, 0x33, +0x80, 0x06, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x80, 0xee, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x27, +0x81, 0x28, 0x9a, 0x0a, 0x4e, 0x05, 0x00, 0x07, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, 0x81, 0x98, +0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x00, 0x04, 0x01, +0x84, 0x21, 0xa8, 0x42, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x00, 0x04, 0x01, 0x84, 0x20, 0xb6, 0x20, +0xdd, 0x9e, 0x92, 0x00, 0x46, 0x10, 0x04, 0x01, 0x96, 0x00, 0xa8, 0x09, 0xdd, 0x9e, 0x92, 0x00, +0x46, 0x00, 0x04, 0x01, 0x84, 0x22, 0xa8, 0x42, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x10, 0x04, 0x01, +0x04, 0x00, 0x81, 0x8a, 0x96, 0x04, 0xc0, 0x04, 0x84, 0x41, 0x14, 0x20, 0x81, 0x8a, 0xdd, 0x9e, +0x46, 0x20, 0x04, 0x01, 0xa0, 0x52, 0x56, 0x00, 0x80, 0x04, 0x42, 0x00, 0x08, 0x0b, 0xdd, 0x9e, +0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x50, 0x04, 0x00, 0x46, 0x60, 0x04, 0x01, 0x58, 0x63, 0x06, 0x8c, +0x04, 0x82, 0x80, 0x80, 0xb4, 0x86, 0x46, 0x70, 0x00, 0x04, 0x58, 0x73, 0x86, 0xd0, 0x58, 0x02, +0x00, 0x40, 0xb6, 0x06, 0x44, 0x00, 0x00, 0xff, 0xdd, 0x27, 0x44, 0x00, 0x00, 0xff, 0xdd, 0x27, +0x44, 0x00, 0x00, 0xff, 0xdd, 0x27, 0x44, 0x00, 0x00, 0xff, 0xdd, 0x27, 0xb4, 0x66, 0x42, 0x11, +0x98, 0x09, 0x54, 0x04, 0x00, 0x03, 0xb6, 0x26, 0xc8, 0x14, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, +0x02, 0x04, 0xb4, 0x80, 0x46, 0x3f, 0xf0, 0xff, 0x58, 0x22, 0x00, 0x01, 0xb6, 0x40, 0x05, 0xe0, +0x00, 0x00, 0x58, 0x31, 0x8f, 0xff, 0x50, 0x10, 0x00, 0x08, 0x40, 0x2f, 0x0c, 0x02, 0xd5, 0x19, +0x84, 0xa1, 0xd8, 0x1c, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x02, 0x04, 0xb4, 0xa0, 0x42, 0x42, +0x80, 0x09, 0xb6, 0x80, 0x46, 0x3f, 0xf0, 0xff, 0xb4, 0x40, 0x58, 0x31, 0x8f, 0xff, 0x41, 0xe1, +0x0c, 0x02, 0x15, 0xe0, 0x00, 0x00, 0xb4, 0xa0, 0x50, 0x10, 0x00, 0x08, 0x42, 0x22, 0xd0, 0x08, +0xb6, 0x40, 0xb4, 0x41, 0x58, 0x01, 0x03, 0x00, 0xb6, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa8, 0x3c, 0x96, 0xd8, 0x96, 0x90, 0xcb, 0x38, 0x54, 0x50, 0x80, 0x03, 0x9a, 0x4d, +0xb4, 0xe1, 0x80, 0x82, 0x52, 0x62, 0x80, 0x04, 0xd5, 0x07, 0x38, 0xa0, 0x0e, 0x0a, 0x54, 0x44, +0x80, 0xff, 0x54, 0x34, 0x00, 0xff, 0x40, 0x81, 0x94, 0x00, 0x40, 0xa4, 0x0c, 0x08, 0x40, 0xa3, +0xa8, 0x0d, 0x50, 0x92, 0x7f, 0xff, 0x50, 0x81, 0x80, 0x01, 0xe2, 0x66, 0xe9, 0xef, 0x95, 0x6a, +0x40, 0x71, 0x08, 0x09, 0x9a, 0x05, 0x84, 0x41, 0xd5, 0x14, 0x95, 0x94, 0x38, 0x50, 0x8a, 0x02, +0x99, 0xb0, 0x84, 0x60, 0x40, 0x82, 0x8c, 0x0d, 0x9f, 0x21, 0xb7, 0x06, 0x44, 0x80, 0x00, 0x18, +0x97, 0x20, 0x4c, 0x34, 0x00, 0x05, 0x8c, 0x68, 0x9d, 0xb4, 0xcc, 0xf5, 0x9c, 0x91, 0x96, 0x90, +0xe0, 0xe2, 0xe9, 0x26, 0xcc, 0xeb, 0xd5, 0x24, 0x84, 0xa1, 0xdb, 0x22, 0x54, 0x30, 0x00, 0x03, +0xcb, 0x1f, 0x54, 0x31, 0x00, 0x03, 0xcb, 0x1c, 0x54, 0x21, 0x00, 0xfc, 0xd5, 0x17, 0x04, 0x90, +0x80, 0x02, 0xa1, 0xc9, 0xb4, 0x81, 0x04, 0x80, 0x80, 0x03, 0x40, 0x64, 0xc0, 0x08, 0x40, 0x73, +0xa0, 0x08, 0x40, 0x63, 0x98, 0x04, 0x40, 0xa3, 0x10, 0x04, 0x40, 0x54, 0x60, 0x08, 0x40, 0x95, +0x14, 0x04, 0x38, 0x91, 0x80, 0x0a, 0x8c, 0x30, 0x9c, 0xdc, 0x4c, 0x31, 0x7f, 0xea, 0x3a, 0x6f, +0xa8, 0x04, 0xdd, 0x9e, 0x96, 0x01, 0x96, 0x89, 0xe2, 0x02, 0xe8, 0x02, 0x80, 0x20, 0x96, 0x09, +0xdd, 0x9e, 0x92, 0x00, 0x96, 0x00, 0x96, 0x88, 0xe2, 0x02, 0xe8, 0x02, 0x80, 0x20, 0x96, 0x08, +0xdd, 0x9e, 0x92, 0x00, 0xd5, 0x03, 0x92, 0x00, 0x9e, 0x01, 0x96, 0x00, 0xc8, 0xfd, 0xdd, 0x9e, +0xd5, 0x08, 0x44, 0x10, 0x00, 0xff, 0x92, 0x00, 0x9e, 0x49, 0x96, 0x48, 0xc9, 0xfd, 0x9e, 0x01, +0x96, 0x00, 0xc8, 0xf8, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x20, 0x00, 0x0e, 0x58, 0x21, 0x03, 0xc8, +0xb4, 0x22, 0xc1, 0x08, 0xd5, 0x09, 0x84, 0x2a, 0x92, 0x00, 0x9e, 0xc9, 0x96, 0x58, 0xc9, 0xfd, +0x9e, 0x01, 0xc8, 0xfa, 0xd5, 0x0b, 0x8c, 0x1f, 0x92, 0x05, 0xd5, 0x07, 0x84, 0x28, 0x92, 0x00, +0x9f, 0x09, 0x96, 0x60, 0xc9, 0xfd, 0x9e, 0x01, 0xc8, 0xfa, 0xdd, 0x9e, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa8, 0xbc, 0x96, 0x00, 0x54, 0xa0, 0x80, 0xff, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, +0x86, 0x74, 0x97, 0xd1, 0x40, 0x80, 0x04, 0x00, 0x84, 0xc0, 0x46, 0x90, 0x00, 0x04, 0x58, 0x94, +0x80, 0xf4, 0xd5, 0x09, 0x4b, 0xe0, 0x24, 0x01, 0x9d, 0xb1, 0x9d, 0xf9, 0x18, 0x04, 0x00, 0x01, +0x97, 0xb0, 0x97, 0xf9, 0x80, 0x07, 0x84, 0x20, 0xe2, 0xca, 0xe9, 0xf5, 0x3a, 0x6f, 0xa8, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0x09, +0x4e, 0x14, 0x00, 0x04, 0x84, 0x21, 0xd5, 0x02, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x17, +0x87, 0xb9, 0x44, 0x00, 0x00, 0x11, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x80, 0xf4, +0xdd, 0x2f, 0x54, 0x30, 0x00, 0x0f, 0x84, 0xa2, 0xdb, 0x0e, 0x54, 0x40, 0x00, 0x10, 0xc4, 0x09, +0x46, 0x50, 0x04, 0x00, 0x05, 0xe2, 0x80, 0x08, 0x42, 0x6f, 0x2c, 0x09, 0x14, 0x62, 0x80, 0x08, +0x84, 0x20, 0xd5, 0x02, 0x84, 0x21, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x17, 0x87, 0xb8, 0x46, 0xf0, +0x00, 0x0b, 0x00, 0x07, 0x87, 0xb8, 0xc8, 0x47, 0x46, 0x60, 0x00, 0x04, 0x58, 0x63, 0x07, 0x20, +0x84, 0x02, 0x84, 0x21, 0x94, 0x83, 0xdd, 0x26, 0x84, 0x08, 0x84, 0x26, 0x44, 0x20, 0x00, 0x12, +0xdd, 0x26, 0x44, 0x00, 0x00, 0x24, 0x84, 0x22, 0x9e, 0x82, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x2a, +0x84, 0x23, 0x94, 0x8b, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x2e, 0x84, 0x23, 0x44, 0x20, 0x00, 0x1b, +0xdd, 0x26, 0x44, 0x00, 0x00, 0x35, 0x84, 0x21, 0x44, 0x20, 0x00, 0x1e, 0xdd, 0x26, 0x44, 0x00, +0x00, 0x39, 0x84, 0x21, 0x44, 0x20, 0x00, 0x1f, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x76, 0x84, 0x21, +0x94, 0x8d, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x7a, 0x84, 0x21, 0x44, 0x20, 0x00, 0x21, 0xdd, 0x26, +0x44, 0x00, 0x00, 0x78, 0x84, 0x21, 0x44, 0x20, 0x00, 0x26, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x96, +0x84, 0x21, 0x44, 0x20, 0x00, 0x24, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x9d, 0x84, 0x21, 0x44, 0x20, +0x00, 0x25, 0xdd, 0x26, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xec, 0x46, 0x80, 0x04, 0x01, 0x97, 0x81, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x06, 0x74, +0x97, 0x08, 0x96, 0x92, 0x96, 0xda, 0x58, 0x84, 0x04, 0x00, 0x40, 0x93, 0x00, 0x00, 0x84, 0xe0, +0x47, 0xc0, 0x00, 0x04, 0x59, 0xce, 0x00, 0xf4, 0x85, 0x47, 0xd5, 0x1a, 0xc3, 0x0b, 0xf2, 0x82, +0xf3, 0x81, 0xf4, 0x83, 0x80, 0x06, 0x84, 0x20, 0xdd, 0x3c, 0xf2, 0x02, 0xf3, 0x01, 0xf4, 0x03, +0xd5, 0x03, 0x00, 0x04, 0x80, 0x00, 0x9c, 0x79, 0x9d, 0xb1, 0x56, 0x73, 0x80, 0x01, 0xc2, 0x03, +0x40, 0x05, 0x1c, 0x1a, 0x1c, 0x04, 0x00, 0x01, 0x97, 0xc8, 0x97, 0xb1, 0x8d, 0x21, 0xe2, 0xe4, +0xe9, 0xe6, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0x00, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x0b, 0x02, 0x07, +0x83, 0xd6, 0xc8, 0x02, 0xd5, 0x03, 0x84, 0xa1, 0xd8, 0x0b, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x07, +0x87, 0xb2, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0x00, 0xdd, 0x2f, 0xd5, 0x06, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x84, 0xdc, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x87, 0xb5, 0xc8, 0x1c, +0x46, 0xf0, 0x00, 0x0b, 0x02, 0x07, 0x83, 0xd6, 0x84, 0xa1, 0xd8, 0x13, 0x46, 0x40, 0x04, 0x01, +0x04, 0x12, 0x01, 0xa3, 0x46, 0x00, 0x04, 0x10, 0x59, 0xe0, 0x80, 0x08, 0x54, 0x5f, 0x00, 0xff, +0x14, 0x52, 0x01, 0xa3, 0x58, 0x00, 0x02, 0x38, 0xb4, 0x60, 0x42, 0x11, 0xc4, 0x08, 0xd5, 0x36, +0x84, 0xa2, 0xd8, 0x50, 0xd5, 0x49, 0x84, 0xa2, 0xd8, 0x4d, 0x46, 0xf0, 0x00, 0x0b, 0x02, 0x07, +0x83, 0xd6, 0xc8, 0x48, 0x46, 0xf0, 0x00, 0x0b, 0x02, 0x07, 0x83, 0xd7, 0x44, 0x50, 0x00, 0x81, +0xd0, 0x1d, 0x5c, 0xf0, 0x00, 0x82, 0xe8, 0x08, 0xe6, 0x0a, 0xe8, 0x03, 0xc8, 0x0f, 0xd5, 0x34, +0x9f, 0x69, 0xd8, 0x38, 0xd5, 0x31, 0x9c, 0x6a, 0x4c, 0x00, 0x80, 0x20, 0xe2, 0x01, 0xe9, 0x18, +0x9d, 0x49, 0xd0, 0x20, 0x9d, 0x4a, 0xd8, 0x2e, 0xd5, 0x22, 0x97, 0x40, 0x46, 0x40, 0x04, 0x01, +0x94, 0x2d, 0x58, 0x42, 0x00, 0x08, 0x98, 0x04, 0xd5, 0x05, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, +0x00, 0x38, 0x05, 0xe0, 0x00, 0x00, 0x58, 0x1f, 0x00, 0x40, 0xb6, 0x20, 0xd5, 0x15, 0x46, 0x00, +0x04, 0x01, 0x58, 0x00, 0x00, 0x58, 0xd5, 0xf6, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, 0x00, 0x78, +0xd5, 0xf1, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, 0x00, 0x98, 0xd5, 0xec, 0x46, 0x00, 0x04, 0x01, +0x58, 0x00, 0x00, 0xb8, 0xd5, 0xe7, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0x00, 0xdd, 0x2f, +0xd5, 0x06, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xdc, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, +0x87, 0xb5, 0xc0, 0x05, 0x84, 0xa2, 0x4c, 0x02, 0xc0, 0xa3, 0xd5, 0x1a, 0x46, 0xf0, 0x00, 0x0b, +0x02, 0x37, 0x83, 0xd6, 0x84, 0xa1, 0x4c, 0x32, 0xc0, 0x9b, 0x46, 0x30, 0x04, 0x01, 0x04, 0x41, +0x81, 0xa3, 0x46, 0x50, 0x04, 0x10, 0x54, 0x22, 0x00, 0xf7, 0x14, 0x21, 0x81, 0xa3, 0x04, 0x02, +0x80, 0x8e, 0x43, 0xe0, 0x44, 0x09, 0x15, 0xe2, 0x80, 0x8e, 0x48, 0x00, 0x00, 0x83, 0x46, 0xf0, +0x00, 0x0b, 0x02, 0x57, 0x83, 0xd6, 0x4e, 0x53, 0x00, 0x83, 0x46, 0x20, 0x00, 0x0b, 0x02, 0x01, +0x03, 0xd7, 0x44, 0x50, 0x00, 0x82, 0xd0, 0x3b, 0x5c, 0xf0, 0x00, 0x83, 0xe8, 0x07, 0xc0, 0x71, +0xe6, 0x0a, 0xe9, 0x0c, 0x9f, 0x69, 0xd8, 0x6d, 0xd5, 0x25, 0x9c, 0x6a, 0x4c, 0x00, 0x80, 0x4a, +0xe2, 0x01, 0xe9, 0x3a, 0x9d, 0x49, 0xd8, 0x65, 0xd5, 0x51, 0x55, 0xe0, 0x00, 0xff, 0x46, 0x50, +0x04, 0x01, 0x58, 0x52, 0x86, 0x88, 0x58, 0x3f, 0x00, 0x60, 0x15, 0xe2, 0x80, 0x00, 0x40, 0x0f, +0x14, 0x08, 0xb6, 0x65, 0x50, 0x12, 0xf9, 0x80, 0x41, 0xe0, 0x04, 0x00, 0xb4, 0x7e, 0x42, 0x11, +0x98, 0x09, 0xb6, 0x3e, 0x00, 0x01, 0x07, 0xae, 0x58, 0x40, 0x00, 0x60, 0xb6, 0x05, 0xb6, 0x85, +0xd5, 0x48, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, 0x06, 0x88, 0x44, 0x30, 0x00, 0x11, 0x44, 0x20, +0x00, 0x71, 0xb6, 0x60, 0x50, 0x10, 0x79, 0xb0, 0xb6, 0x40, 0xd5, 0x34, 0x46, 0x00, 0x04, 0x01, +0x58, 0x00, 0x06, 0x88, 0x44, 0x30, 0x00, 0x12, 0x44, 0x20, 0x00, 0x72, 0xb6, 0x60, 0x50, 0x10, +0x79, 0xd0, 0xb6, 0x40, 0xd5, 0x27, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, 0x06, 0x88, 0x44, 0x30, +0x00, 0x13, 0x44, 0x20, 0x00, 0x73, 0xb6, 0x60, 0x50, 0x10, 0x79, 0xf0, 0xb6, 0x40, 0xd5, 0x1a, +0x46, 0x00, 0x04, 0x01, 0x58, 0x00, 0x06, 0x88, 0x44, 0x30, 0x00, 0x14, 0x44, 0x20, 0x00, 0x74, +0xb6, 0x60, 0x50, 0x10, 0x7a, 0x10, 0xb6, 0x40, 0xd5, 0x0d, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, +0x06, 0x88, 0x44, 0x30, 0x00, 0x15, 0x44, 0x20, 0x00, 0x75, 0xb6, 0x60, 0xb6, 0x40, 0x50, 0x10, +0x7a, 0x30, 0x05, 0xe0, 0x80, 0x00, 0x42, 0x4f, 0x18, 0x09, 0xb6, 0x81, 0xb6, 0x60, 0xb6, 0x40, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0x00, 0xdd, 0x2f, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x84, 0xdc, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x96, 0x92, 0x97, 0xc1, 0x97, 0x8b, 0xf2, 0x81, 0x47, 0xc0, +0x00, 0x04, 0x59, 0xce, 0x08, 0x5c, 0x46, 0xa0, 0x00, 0x04, 0x58, 0xa5, 0x04, 0xf4, 0x46, 0x90, +0x00, 0x04, 0x58, 0x94, 0x85, 0x00, 0xd5, 0x20, 0x96, 0x30, 0x44, 0x10, 0x00, 0x40, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x86, 0xb4, 0xdd, 0x2f, 0x81, 0x00, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, +0x85, 0x20, 0xdd, 0x2f, 0xc0, 0xfb, 0xf3, 0x01, 0x80, 0x28, 0x84, 0x40, 0x80, 0x07, 0xdd, 0x3c, +0x50, 0x63, 0x7f, 0xc0, 0x80, 0x08, 0x50, 0x73, 0x80, 0x40, 0x4b, 0xe0, 0x28, 0x01, 0x97, 0xb3, +0x4b, 0xe0, 0x24, 0x01, 0x97, 0xf9, 0x4e, 0x64, 0xff, 0xe1, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x57, 0x87, 0xb4, +0x40, 0x80, 0x00, 0x10, 0x4c, 0x54, 0x40, 0x31, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x06, 0x74, +0x44, 0x40, 0x00, 0x40, 0x84, 0x60, 0x10, 0x30, 0x00, 0x8e, 0x10, 0x40, 0x00, 0x8d, 0x10, 0x40, +0x00, 0x3e, 0x10, 0x30, 0x00, 0x3f, 0x10, 0x40, 0x00, 0x45, 0x10, 0x30, 0x00, 0x46, 0x10, 0x40, +0x00, 0x4c, 0x10, 0x30, 0x00, 0x4d, 0x10, 0x40, 0x00, 0x53, 0x10, 0x30, 0x00, 0x54, 0x10, 0x40, +0x00, 0x5a, 0x10, 0x30, 0x00, 0x5b, 0x10, 0x40, 0x00, 0x61, 0x10, 0x30, 0x00, 0x62, 0x10, 0x40, +0x00, 0x68, 0x10, 0x30, 0x00, 0x69, 0x10, 0x40, 0x00, 0x6f, 0x10, 0x30, 0x00, 0x70, 0x10, 0x40, +0x00, 0x86, 0x10, 0x30, 0x00, 0x87, 0x46, 0x60, 0x00, 0x0b, 0x00, 0x03, 0x07, 0xb0, 0x44, 0x10, +0x00, 0x40, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0xb4, 0xdd, 0x2f, 0x80, 0x20, 0x80, 0x48, +0x84, 0x60, 0x80, 0xe0, 0x44, 0x00, 0x00, 0x28, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x88, 0x5c, +0xdd, 0x2f, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xf4, 0xdd, 0x2f, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x85, 0x00, 0xdd, 0x2f, 0x00, 0x53, 0x07, 0xb0, 0x5c, 0xf2, 0x80, 0x41, +0xe9, 0x37, 0x46, 0x60, 0x00, 0x04, 0x58, 0x63, 0x05, 0x20, 0x4b, 0xe0, 0x18, 0x01, 0xc0, 0xfe, +0x46, 0xf0, 0x00, 0x0b, 0x00, 0x67, 0x86, 0xa0, 0x84, 0xa1, 0x46, 0x00, 0x00, 0x0b, 0x46, 0x20, +0x00, 0x04, 0x58, 0x21, 0x06, 0xb4, 0xde, 0x05, 0x00, 0x00, 0x07, 0xb0, 0x84, 0x2a, 0xd5, 0x05, +0x00, 0x00, 0x07, 0xb0, 0x44, 0x10, 0x00, 0x36, 0x50, 0x00, 0x7f, 0xc0, 0x96, 0x00, 0x4b, 0xe0, +0x08, 0x01, 0x84, 0x40, 0x80, 0x20, 0x80, 0xc0, 0x80, 0x62, 0x44, 0x00, 0x00, 0x68, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x88, 0x5c, 0xdd, 0x2f, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, +0x84, 0xf4, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0x00, 0xdd, 0x2f, 0x46, 0x30, +0x00, 0x0b, 0x58, 0x31, 0x86, 0x74, 0x84, 0x40, 0x84, 0x82, 0x10, 0x41, 0x80, 0x8e, 0x10, 0x21, +0x80, 0x8d, 0x10, 0x21, 0x80, 0x3e, 0x10, 0x41, 0x80, 0x3f, 0x10, 0x21, 0x80, 0x45, 0x10, 0x41, +0x80, 0x46, 0x10, 0x21, 0x80, 0x4c, 0x10, 0x41, 0x80, 0x4d, 0x10, 0x21, 0x80, 0x53, 0x10, 0x41, +0x80, 0x54, 0x10, 0x21, 0x80, 0x5a, 0x10, 0x41, 0x80, 0x5b, 0x10, 0x21, 0x80, 0x61, 0x10, 0x41, +0x80, 0x62, 0x10, 0x21, 0x80, 0x68, 0x10, 0x41, 0x80, 0x69, 0x10, 0x21, 0x80, 0x6f, 0x10, 0x41, +0x80, 0x70, 0x10, 0x21, 0x80, 0x86, 0x10, 0x41, 0x80, 0x87, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x46, 0x80, 0x00, 0x0b, 0x02, 0x04, 0x03, 0xd6, 0x84, 0xa3, +0x40, 0x10, 0x20, 0x09, 0xd1, 0x45, 0xe6, 0x24, 0xe8, 0x07, 0x84, 0xa1, 0xd1, 0x0d, 0x84, 0xa2, +0x4c, 0x12, 0xc0, 0x98, 0xd5, 0x34, 0x84, 0xa7, 0xd1, 0x34, 0x84, 0xaf, 0xd1, 0x14, 0x84, 0xa6, +0x4c, 0x12, 0xc0, 0x90, 0xd5, 0x1e, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x87, 0xb0, 0x44, 0x10, +0x00, 0x12, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0xb4, 0xdd, 0x2f, 0x80, 0x20, 0x84, 0x00, +0x80, 0x40, 0xd5, 0x79, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x87, 0xb0, 0x84, 0x2c, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x86, 0xb4, 0xdd, 0x2f, 0x80, 0x20, 0x44, 0x00, 0x00, 0x1c, 0xd5, 0x51, +0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x87, 0xb0, 0x84, 0x2a, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, +0x86, 0xb4, 0xdd, 0x2f, 0x80, 0x20, 0x44, 0x00, 0x00, 0x12, 0xd5, 0x43, 0x84, 0x00, 0xd5, 0x02, +0x84, 0x01, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x8b, 0xf4, 0xdd, 0x2f, 0xd5, 0x5f, 0x46, 0xf0, +0x00, 0x0b, 0x00, 0x67, 0x87, 0xb8, 0xce, 0x03, 0x96, 0x00, 0xc8, 0x05, 0x44, 0x00, 0x00, 0x9e, +0x84, 0x24, 0xd5, 0x2f, 0x46, 0x70, 0x00, 0x04, 0x58, 0x73, 0x80, 0xf4, 0x80, 0x26, 0x50, 0x00, +0x00, 0x27, 0x4b, 0xe0, 0x1c, 0x01, 0x81, 0x20, 0x80, 0x26, 0x44, 0x00, 0x00, 0x27, 0x4b, 0xe0, +0x1c, 0x01, 0x44, 0x50, 0x00, 0xff, 0x80, 0x20, 0xd0, 0x05, 0x00, 0x04, 0x07, 0xac, 0xe6, 0x0d, +0xe9, 0x1a, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x87, 0xac, 0x84, 0xa1, 0xd8, 0x06, 0x44, 0x00, +0x00, 0xa2, 0x44, 0x10, 0x00, 0x12, 0xd5, 0x0d, 0x84, 0xa2, 0xd8, 0x06, 0x44, 0x00, 0x00, 0xb4, +0x44, 0x10, 0x00, 0x1c, 0xd5, 0x06, 0x84, 0xa3, 0xd8, 0x24, 0x44, 0x00, 0x00, 0xd0, 0x84, 0x28, +0x84, 0x40, 0xd5, 0x19, 0x40, 0x00, 0xa0, 0x08, 0x55, 0xe4, 0x80, 0xff, 0x40, 0x8f, 0x00, 0x04, +0x40, 0x84, 0x00, 0x13, 0x80, 0x26, 0x80, 0x08, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0xf0, 0x00, 0x0b, +0x00, 0x17, 0x87, 0xb0, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0xb4, 0xdd, 0x2f, 0x80, 0x20, +0x84, 0x41, 0x80, 0x08, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x8b, 0x80, 0xdd, 0x2f, 0xd5, 0x06, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xdc, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x40, 0x04, 0x01, 0x80, 0x64, +0x96, 0x48, 0x96, 0x00, 0x14, 0x02, 0x01, 0x00, 0x14, 0x11, 0x81, 0x01, 0x96, 0x10, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x84, 0xf4, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0x00, +0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x84, 0x00, 0x80, 0x20, 0x84, 0x41, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x8e, 0xe4, +0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x87, 0xb2, 0x84, 0x20, 0x84, 0x41, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x8e, 0xe4, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x87, 0xb5, 0x44, 0x50, +0x00, 0x81, 0xd0, 0x50, 0x9d, 0x69, 0xd0, 0x0b, 0x9f, 0x6a, 0xd8, 0x44, 0x47, 0xe0, 0x04, 0x01, +0x04, 0x5f, 0x01, 0xa3, 0x54, 0x42, 0x80, 0x08, 0xcc, 0x43, 0xd5, 0x44, 0x46, 0xf0, 0x00, 0x0b, +0x00, 0x07, 0x87, 0xae, 0x9f, 0x69, 0xd0, 0x12, 0x5c, 0xf0, 0x00, 0x82, 0xe8, 0x05, 0xc0, 0x3a, +0xe6, 0x0a, 0xe8, 0x30, 0xd5, 0x24, 0x9c, 0x6a, 0x4c, 0x00, 0x80, 0x13, 0xe2, 0x01, 0xe9, 0x0b, +0x9d, 0x49, 0xd0, 0x13, 0x9d, 0x4a, 0xd8, 0x26, 0xd5, 0x15, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, +0x00, 0x38, 0xd5, 0x1b, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, 0x00, 0x58, 0xd5, 0x16, 0x46, 0x00, +0x04, 0x01, 0x58, 0x00, 0x00, 0x78, 0xd5, 0x11, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, 0x00, 0x98, +0xd5, 0x0c, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, 0x00, 0xb8, 0xd5, 0x07, 0x46, 0x50, 0x04, 0x01, +0x95, 0x05, 0x58, 0x52, 0x80, 0x08, 0x98, 0x25, 0x05, 0xe0, 0x00, 0x00, 0x42, 0x0f, 0x18, 0x0b, +0xd5, 0x0a, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xdc, 0xdd, 0x2f, 0xd5, 0x0b, 0x84, 0x02, +0xd5, 0x02, 0x84, 0x00, 0x84, 0x20, 0x84, 0x42, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x8e, 0xe4, +0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x30, 0x04, 0x01, +0x04, 0x51, 0x81, 0x80, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x57, 0x87, 0xb5, 0x80, 0x83, 0x04, 0x12, +0x01, 0x81, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x17, 0x87, 0xb6, 0x80, 0xa3, 0x04, 0x21, 0x81, 0x82, +0x04, 0x42, 0x81, 0x83, 0x96, 0x10, 0x96, 0x60, 0x40, 0x30, 0xa0, 0x08, 0x40, 0x51, 0x80, 0x04, +0x46, 0xf0, 0x00, 0x0b, 0x12, 0x57, 0x83, 0xd6, 0x46, 0x20, 0x04, 0x01, 0x80, 0x02, 0x04, 0x11, +0x01, 0x84, 0x04, 0x30, 0x01, 0x85, 0x97, 0x08, 0x97, 0x58, 0x40, 0x22, 0xa0, 0x08, 0x40, 0x51, +0x10, 0x04, 0x46, 0xf0, 0x00, 0x0b, 0x12, 0x57, 0x83, 0xd7, 0x80, 0x20, 0x04, 0x40, 0x81, 0x86, +0x04, 0x30, 0x01, 0x87, 0x96, 0x60, 0x96, 0x18, 0x40, 0x40, 0x20, 0x08, 0x40, 0x32, 0x04, 0x04, +0x46, 0x00, 0x04, 0x01, 0x46, 0xf0, 0x00, 0x0b, 0x12, 0x37, 0x83, 0xd8, 0x84, 0x41, 0x84, 0x21, +0x46, 0xf0, 0x00, 0x0b, 0x14, 0x57, 0x81, 0xe9, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x27, 0x87, 0xb3, +0x14, 0x10, 0x01, 0x8c, 0xdd, 0x9e, 0x92, 0x00, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x17, +0x83, 0xcc, 0xdd, 0x9e, 0x46, 0x30, 0x04, 0x01, 0x44, 0x50, 0x00, 0xff, 0x80, 0x43, 0x14, 0x51, +0x81, 0x8a, 0x44, 0x30, 0x00, 0x39, 0x46, 0x10, 0x04, 0x01, 0x14, 0x31, 0x01, 0x98, 0x58, 0x10, +0x86, 0x88, 0x84, 0x80, 0x44, 0x50, 0x00, 0x10, 0x44, 0x30, 0x00, 0x70, 0x44, 0x20, 0x00, 0x60, +0xb6, 0xa1, 0x50, 0x00, 0x80, 0x18, 0xb6, 0x61, 0xb6, 0x81, 0xb6, 0x41, 0x44, 0x10, 0x00, 0x31, +0xb6, 0x20, 0x9d, 0x49, 0x9c, 0x4c, 0x9e, 0xca, 0x9e, 0x89, 0xb6, 0xa0, 0xb6, 0x60, 0xb6, 0x40, +0xb6, 0x20, 0x80, 0x24, 0x50, 0x20, 0x80, 0x21, 0x84, 0xa9, 0x9c, 0x49, 0xb6, 0x40, 0xd9, 0xfb, +0x46, 0x00, 0x04, 0x01, 0x44, 0x10, 0x00, 0x3f, 0x14, 0x10, 0x01, 0x8c, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xe4, 0x84, 0x41, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x27, 0x87, 0xb4, +0x47, 0xe0, 0x04, 0x01, 0x04, 0x1f, 0x01, 0xa3, 0x46, 0x40, 0x04, 0x00, 0x58, 0x50, 0x80, 0x01, +0x14, 0x5f, 0x01, 0xa3, 0x83, 0x9e, 0x81, 0x5c, 0x81, 0x2a, 0x04, 0x02, 0x00, 0x8f, 0x15, 0xcf, +0x80, 0x00, 0x14, 0xaf, 0x80, 0x01, 0x14, 0x9f, 0x80, 0x02, 0xb4, 0x7f, 0xf2, 0x01, 0xf1, 0x02, +0x81, 0x09, 0x80, 0xe8, 0x80, 0xc7, 0x14, 0x8f, 0x80, 0x03, 0xf7, 0x84, 0xf6, 0x85, 0x58, 0x31, +0x80, 0x38, 0x58, 0x21, 0x00, 0x58, 0x58, 0x10, 0x80, 0x78, 0xb6, 0x7f, 0xf2, 0x81, 0xf1, 0x82, +0xf3, 0x03, 0xf2, 0x04, 0xf1, 0x05, 0x58, 0x00, 0x02, 0x00, 0x58, 0x31, 0x80, 0x98, 0x58, 0x21, +0x00, 0xb8, 0x58, 0x10, 0x80, 0x48, 0xf3, 0x83, 0xf2, 0x84, 0xf1, 0x85, 0x14, 0x02, 0x00, 0x8f, +0x44, 0x00, 0x00, 0x8c, 0xb4, 0x9f, 0x9e, 0x84, 0xb6, 0x04, 0x9e, 0xd4, 0xf4, 0x01, 0x9e, 0x43, +0xb6, 0x44, 0x83, 0xc6, 0xf0, 0x02, 0x83, 0x86, 0xb6, 0x60, 0x81, 0x46, 0xf4, 0x03, 0x81, 0x26, +0xb6, 0x24, 0x81, 0x06, 0xf0, 0x04, 0x80, 0xe6, 0xb6, 0x40, 0xf4, 0x05, 0x80, 0xa6, 0x44, 0x00, +0x00, 0x20, 0xb6, 0x44, 0x14, 0x3f, 0x00, 0x1a, 0xb9, 0xa2, 0x14, 0x15, 0x00, 0x2a, 0x14, 0x14, +0x80, 0x32, 0x14, 0x14, 0x00, 0x3a, 0x14, 0x23, 0x80, 0x42, 0x14, 0x13, 0x00, 0x4a, 0x14, 0x02, +0x81, 0x8c, 0xec, 0x1c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, +0xef, 0xf8, 0x46, 0x10, 0x04, 0x01, 0x04, 0x60, 0x81, 0x8c, 0x96, 0x34, 0xc0, 0x06, 0x46, 0xf0, +0x00, 0x05, 0x58, 0xf7, 0x80, 0x2c, 0xdd, 0x2f, 0x54, 0x23, 0x00, 0x08, 0xc2, 0x17, 0x46, 0x40, +0x04, 0x01, 0x80, 0x64, 0x84, 0x48, 0x84, 0x20, 0x84, 0x01, 0x14, 0x22, 0x01, 0x8c, 0x14, 0x11, +0x81, 0xa7, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x07, 0x83, 0xcc, 0x46, 0x30, 0x04, 0x00, 0x04, 0x51, +0x80, 0x96, 0x42, 0x42, 0xfc, 0x08, 0x14, 0x41, 0x80, 0x96, 0x54, 0x53, 0x00, 0x10, 0xc5, 0x06, +0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x80, 0xd4, 0xdd, 0x2f, 0x54, 0x63, 0x00, 0x20, 0xc6, 0x06, +0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x81, 0x40, 0xdd, 0x2f, 0x46, 0x00, 0x04, 0x01, 0x05, 0xe0, +0x01, 0x8c, 0x15, 0xef, 0x80, 0x01, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, +0x8e, 0x3c, 0xdd, 0x2f, 0x46, 0x40, 0x04, 0x01, 0x44, 0x50, 0x00, 0x80, 0x14, 0x52, 0x01, 0xa8, +0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x87, 0xb5, 0x46, 0x60, 0x00, 0x0b, 0x84, 0x40, 0x54, 0x00, +0x00, 0x60, 0x44, 0x10, 0x00, 0x20, 0x10, 0x23, 0x07, 0xb3, 0x4c, 0x00, 0x80, 0x20, 0x95, 0x49, +0xd0, 0x14, 0xc8, 0x1c, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x87, 0xb6, 0x84, 0x2c, 0x46, 0xf0, +0x00, 0x04, 0x58, 0xf7, 0x86, 0xb4, 0xdd, 0x2f, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x85, 0x38, +0x38, 0x20, 0x82, 0x02, 0xdd, 0x22, 0xd5, 0x0f, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x87, 0x6c, +0xdd, 0x2f, 0x96, 0xc0, 0x10, 0x33, 0x07, 0xb3, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, +0x84, 0xdc, 0xdd, 0x2f, 0x46, 0x40, 0x04, 0x01, 0x84, 0xa0, 0x14, 0x52, 0x01, 0xa8, 0xf0, 0x01, +0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0x50, 0xdd, 0x2f, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, +0x87, 0x64, 0xdd, 0x2f, 0x46, 0x50, 0x04, 0x01, 0x04, 0x02, 0x81, 0xa3, 0x54, 0x00, 0x00, 0x02, +0xc8, 0x66, 0x80, 0xe5, 0xb6, 0xff, 0x80, 0xc5, 0xb4, 0x3f, 0xf6, 0x81, 0x58, 0x10, 0x80, 0xb8, +0xb6, 0x3f, 0xf1, 0x01, 0x80, 0x45, 0x58, 0x10, 0x80, 0x88, 0xf1, 0x81, 0x44, 0x10, 0x00, 0x8b, +0x14, 0x11, 0x00, 0x26, 0x83, 0xc2, 0xb4, 0x5f, 0x83, 0x85, 0xb6, 0x22, 0x81, 0x45, 0xf2, 0x01, +0x81, 0x25, 0x81, 0x05, 0x80, 0xe5, 0xb6, 0x22, 0x80, 0xc5, 0x44, 0x20, 0x00, 0xff, 0x46, 0x40, +0x04, 0x01, 0x14, 0x1f, 0x00, 0x2a, 0x58, 0x42, 0x06, 0x88, 0xb9, 0xb2, 0x14, 0x15, 0x00, 0x3a, +0x14, 0x14, 0x80, 0x42, 0x14, 0x14, 0x00, 0x4a, 0x14, 0x23, 0x81, 0x8a, 0x44, 0x10, 0x00, 0x39, +0x44, 0x20, 0x00, 0x10, 0x14, 0x13, 0x01, 0x98, 0xb6, 0x44, 0x44, 0x10, 0x00, 0x70, 0x44, 0x20, +0x00, 0x60, 0xb6, 0x24, 0x50, 0x32, 0x00, 0x18, 0xb6, 0x04, 0x84, 0x22, 0xb6, 0x44, 0x44, 0x20, +0x00, 0x31, 0x14, 0x12, 0x81, 0xa3, 0x9d, 0x12, 0xb6, 0x43, 0x9c, 0x53, 0x9f, 0x4a, 0x9c, 0x89, +0xb6, 0xa3, 0xb6, 0x83, 0xb6, 0x23, 0xb6, 0x43, 0x80, 0x23, 0x50, 0x50, 0x00, 0x21, 0x84, 0x69, +0x9c, 0x01, 0xb6, 0xa1, 0x4c, 0x01, 0xff, 0xfb, 0x80, 0xa6, 0x44, 0x00, 0x00, 0x3f, 0x84, 0x20, +0x14, 0x02, 0x81, 0x8c, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x17, 0x87, 0xb4, 0x80, 0x05, 0x04, 0x20, +0x01, 0xa3, 0x54, 0x41, 0x00, 0xfe, 0x14, 0x40, 0x01, 0xa3, 0xd5, 0x38, 0x46, 0x40, 0x04, 0x00, +0x04, 0x32, 0x00, 0x85, 0x80, 0xe5, 0x46, 0x00, 0x04, 0x01, 0x58, 0x00, 0x06, 0xa0, 0x58, 0x21, +0x80, 0x04, 0x44, 0x60, 0x00, 0x39, 0x45, 0xe0, 0x00, 0x31, 0x45, 0xc0, 0x00, 0x32, 0x44, 0xa0, +0x00, 0x33, 0x44, 0x90, 0x00, 0x34, 0x44, 0x80, 0x00, 0x35, 0x14, 0x22, 0x00, 0x85, 0x14, 0x63, +0x81, 0x98, 0x15, 0xe0, 0x00, 0x00, 0x15, 0xc0, 0x00, 0x00, 0xb7, 0x40, 0xb7, 0x20, 0xb7, 0x00, +0x84, 0x20, 0x50, 0x80, 0x80, 0x21, 0x84, 0xa9, 0x9c, 0x49, 0xb7, 0x00, 0xd9, 0xfb, 0x81, 0x27, +0x8d, 0x4c, 0x14, 0xa4, 0x81, 0x8c, 0x80, 0x07, 0x04, 0x10, 0x01, 0xa3, 0x96, 0x4c, 0xc1, 0x02, +0x84, 0x21, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x17, 0x87, 0xb4, 0x46, 0x00, 0x04, 0x01, 0x84, 0xa0, +0x84, 0x40, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x27, 0x87, 0xba, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x27, +0x87, 0xb3, 0x46, 0xf0, 0x00, 0x0b, 0x14, 0x57, 0x81, 0xea, 0x14, 0x50, 0x01, 0xa8, 0x46, 0xf0, +0x00, 0x0b, 0x00, 0x37, 0x87, 0xb4, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x07, 0x87, 0xb8, 0x46, 0xf0, +0x00, 0x0b, 0x00, 0x47, 0x87, 0xb9, 0x40, 0x11, 0xa4, 0x08, 0x40, 0x00, 0x28, 0x08, 0x40, 0x30, +0x80, 0x04, 0x58, 0x01, 0x80, 0x02, 0x40, 0x12, 0x2c, 0x08, 0x46, 0x40, 0x04, 0x00, 0x40, 0x20, +0x04, 0x04, 0x46, 0xf0, 0x00, 0x0b, 0x10, 0x57, 0x87, 0xb7, 0x14, 0x22, 0x00, 0x8f, 0xec, 0x0c, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x60, 0x00, 0x04, +0x58, 0x63, 0x05, 0x0c, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xe8, 0xdd, 0x2f, 0x4b, 0xe0, +0x18, 0x01, 0xc0, 0xfe, 0x46, 0x00, 0x04, 0x01, 0xb4, 0x40, 0x46, 0x00, 0x04, 0x01, 0x96, 0x90, +0x58, 0x00, 0x05, 0x00, 0x84, 0x20, 0xd5, 0x05, 0xa3, 0x01, 0x96, 0xe0, 0x18, 0x30, 0x80, 0x01, +0xe0, 0x22, 0xe9, 0xfb, 0x47, 0xe0, 0x00, 0x0b, 0x02, 0x3f, 0x03, 0xd8, 0x84, 0x20, 0x9a, 0x1a, +0x97, 0x41, 0x40, 0x00, 0x94, 0x06, 0x12, 0x5f, 0x03, 0xd8, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x60, 0x00, 0x04, 0x58, 0x63, 0x05, 0x0c, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x84, 0xe8, 0xdd, 0x2f, 0x4b, 0xe0, 0x18, 0x01, 0xc0, 0xfe, 0x47, 0xe0, 0x04, 0x01, +0xb4, 0xde, 0x97, 0xb0, 0x46, 0xf0, 0x00, 0x0b, 0x04, 0x07, 0x81, 0xe9, 0x46, 0x10, 0x04, 0x01, +0x80, 0x46, 0x58, 0x10, 0x85, 0x00, 0x84, 0x61, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0xe0, +0xdd, 0x2f, 0x46, 0x10, 0x00, 0x0b, 0x02, 0x40, 0x83, 0xd8, 0x84, 0x00, 0x9a, 0xe6, 0x96, 0x99, +0x40, 0x00, 0x08, 0x06, 0x12, 0x20, 0x83, 0xd8, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, 0x07, 0xb0, 0xa4, 0x30, 0x44, 0x10, +0x00, 0x40, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0xa4, 0xdd, 0x2f, 0x46, 0x80, 0x00, 0x0b, +0x58, 0x84, 0x07, 0xa4, 0x97, 0xc0, 0xb4, 0x28, 0x46, 0x00, 0x04, 0x01, 0x80, 0x47, 0x58, 0x00, +0x04, 0x00, 0x84, 0x60, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0xe0, 0xdd, 0x2f, 0xb4, 0x68, +0x80, 0x07, 0x98, 0xbb, 0xb6, 0x48, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xf4, 0xdd, 0x2f, +0xa4, 0x70, 0x84, 0x00, 0x9b, 0xcf, 0x97, 0xf9, 0x40, 0x00, 0x1c, 0x06, 0xad, 0xf0, 0x3a, 0x6f, +0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x96, 0x02, 0xf0, 0x81, 0x84, 0xc0, +0x46, 0xa0, 0x00, 0x04, 0x58, 0xa5, 0x06, 0xa4, 0x46, 0x70, 0x00, 0x0b, 0x58, 0x73, 0x87, 0xa4, +0x46, 0x90, 0x00, 0x04, 0x58, 0x94, 0x80, 0xf4, 0xd5, 0x12, 0x00, 0x83, 0x80, 0x01, 0xa7, 0x78, +0x40, 0x44, 0x20, 0x08, 0x40, 0x02, 0x14, 0x04, 0xb6, 0x7f, 0x4b, 0xe0, 0x24, 0x01, 0xb4, 0x7f, +0x9d, 0xb1, 0xb6, 0x03, 0x97, 0xb0, 0xb4, 0x47, 0x9c, 0x51, 0xb6, 0x27, 0x46, 0xf0, 0x00, 0x0b, +0x02, 0x07, 0x83, 0xd8, 0x44, 0x10, 0x00, 0x40, 0x4b, 0xe0, 0x28, 0x01, 0x46, 0x10, 0x01, 0x00, +0x58, 0x10, 0x85, 0x00, 0x98, 0xb1, 0x46, 0x80, 0x00, 0x0b, 0xf1, 0x01, 0x94, 0xd2, 0xe2, 0xc0, +0xe9, 0xdd, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xf4, 0xdd, 0x2f, 0x02, 0x34, +0x03, 0xd8, 0x84, 0x00, 0x9b, 0x9e, 0x97, 0xb1, 0x40, 0x00, 0x18, 0x06, 0x12, 0x64, 0x03, 0xd8, +0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x46, 0x70, +0x00, 0x04, 0x58, 0x73, 0x85, 0x0c, 0x97, 0x82, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xe8, +0xdd, 0x2f, 0x4b, 0xe0, 0x1c, 0x01, 0xc0, 0xfe, 0x46, 0x20, 0x04, 0x01, 0xb5, 0x22, 0x85, 0x00, +0x44, 0x10, 0x00, 0xfc, 0x40, 0x04, 0x18, 0x1b, 0x40, 0x00, 0x98, 0x1a, 0x46, 0x70, 0x04, 0x01, +0xf0, 0x81, 0x54, 0x94, 0x80, 0xff, 0x58, 0x73, 0x85, 0x00, 0x47, 0xc0, 0x00, 0x04, 0x59, 0xce, +0x01, 0xd0, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, 0x07, 0xa4, 0x46, 0xa0, 0x00, 0x04, 0x58, 0xa5, +0x01, 0x54, 0xd5, 0x15, 0xdd, 0x3c, 0xa7, 0x31, 0xf2, 0x01, 0xa6, 0x70, 0x40, 0x31, 0x10, 0x04, +0xa3, 0x79, 0x40, 0x01, 0xa0, 0x08, 0x40, 0x00, 0x04, 0x04, 0x96, 0x68, 0x4b, 0xe0, 0x28, 0x01, +0xb4, 0x86, 0x8d, 0x01, 0x9c, 0xe1, 0xb6, 0x66, 0x54, 0x84, 0x00, 0xff, 0xe3, 0x09, 0xe9, 0xeb, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x81, 0xa0, 0xdd, 0x2f, 0x46, 0x30, 0x00, 0x0b, 0x02, 0x41, +0x83, 0xd8, 0x84, 0x20, 0x40, 0x02, 0x24, 0x01, 0x97, 0x41, 0x40, 0x00, 0x94, 0x06, 0x12, 0x51, +0x83, 0xd8, 0xec, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, +0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x07, 0xb6, 0xa6, 0x00, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, +0x07, 0xba, 0x84, 0x40, 0x44, 0x10, 0x00, 0x26, 0xae, 0xb0, 0x4c, 0x00, 0x81, 0xeb, 0x5c, 0xf0, +0x00, 0x27, 0xe8, 0x35, 0x84, 0x68, 0x4c, 0x01, 0x82, 0x52, 0xe6, 0x09, 0xe8, 0x15, 0x84, 0x83, +0x4c, 0x02, 0x01, 0x88, 0xe6, 0x04, 0xe8, 0x08, 0x84, 0xa1, 0xd0, 0x6e, 0x87, 0xc2, 0x4c, 0x0f, +0x42, 0x6c, 0x48, 0x00, 0x01, 0x69, 0x84, 0x26, 0x4c, 0x00, 0x81, 0x74, 0x84, 0x47, 0x4c, 0x01, +0x42, 0x64, 0x48, 0x00, 0x01, 0x77, 0x84, 0x6b, 0x4c, 0x01, 0x82, 0x42, 0xe6, 0x0c, 0xe8, 0x09, +0x84, 0x89, 0x4c, 0x02, 0x02, 0x3d, 0x84, 0xaa, 0x4c, 0x02, 0xc2, 0x57, 0x48, 0x00, 0x02, 0x31, +0x45, 0xe0, 0x00, 0x22, 0x4c, 0x0f, 0x01, 0xae, 0x44, 0x10, 0x00, 0x23, 0x4c, 0x00, 0x81, 0xc5, +0x44, 0x20, 0x00, 0x20, 0x4c, 0x01, 0x42, 0x49, 0x48, 0x00, 0x01, 0x96, 0x44, 0x30, 0x00, 0x43, +0x4c, 0x01, 0x81, 0x86, 0x5c, 0xf0, 0x00, 0x44, 0xe8, 0x20, 0x44, 0x40, 0x00, 0x33, 0x4c, 0x02, +0x01, 0xd9, 0x5c, 0xf0, 0x00, 0x34, 0xe8, 0x0b, 0x44, 0x50, 0x00, 0x27, 0x4c, 0x02, 0x81, 0xad, +0x45, 0xe0, 0x00, 0x32, 0x4c, 0x0f, 0x42, 0x31, 0x48, 0x00, 0x01, 0xb7, 0x44, 0x10, 0x00, 0x37, +0x4c, 0x00, 0x81, 0xc8, 0x44, 0x20, 0x00, 0x42, 0x4c, 0x01, 0x01, 0x49, 0x44, 0x30, 0x00, 0x36, +0x4c, 0x01, 0xc2, 0x23, 0x48, 0x00, 0x01, 0xb6, 0x44, 0x40, 0x00, 0x52, 0x4c, 0x02, 0x01, 0xc6, +0x5c, 0xf0, 0x00, 0x53, 0xe8, 0x0b, 0x44, 0x50, 0x00, 0x46, 0x4c, 0x02, 0x81, 0x49, 0x45, 0xe0, +0x00, 0x47, 0x4c, 0x0f, 0x42, 0x12, 0x48, 0x00, 0x01, 0x53, 0x44, 0x10, 0x00, 0x56, 0x4c, 0x00, +0x81, 0xc3, 0x44, 0x20, 0x00, 0x57, 0x4c, 0x01, 0x01, 0xc8, 0x44, 0x30, 0x00, 0x53, 0x4c, 0x01, +0xc2, 0x04, 0x48, 0x00, 0x01, 0xc2, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x07, 0xac, 0xa6, 0x00, +0x84, 0x88, 0x4c, 0x02, 0x00, 0x99, 0xe6, 0x09, 0xe8, 0x08, 0x84, 0xa1, 0xd0, 0x10, 0x87, 0xc2, +0x4c, 0x0f, 0x41, 0xf9, 0x48, 0x00, 0x00, 0x84, 0x44, 0x10, 0x00, 0x10, 0x4c, 0x00, 0x80, 0x95, +0x44, 0x20, 0x00, 0x12, 0x4c, 0x01, 0x41, 0xef, 0x48, 0x00, 0x00, 0xaf, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x85, 0x00, 0xdd, 0x2f, 0x46, 0x50, 0x04, 0x10, 0x46, 0x00, 0x04, 0x10, 0x84, 0x20, +0x58, 0x52, 0x89, 0xc4, 0x58, 0x00, 0x08, 0x00, 0xb6, 0x25, 0x46, 0x40, 0x04, 0x00, 0xb6, 0x20, +0x58, 0x42, 0x02, 0x0c, 0xb4, 0x44, 0x58, 0x31, 0x00, 0x10, 0xb6, 0x64, 0x92, 0x00, 0x87, 0xc7, +0x9c, 0x49, 0x4c, 0x1f, 0x7f, 0xfd, 0x46, 0x00, 0x04, 0x00, 0x44, 0x3f, 0xff, 0xef, 0x40, 0x41, +0x0c, 0x02, 0x58, 0x00, 0x02, 0x0c, 0xb6, 0x80, 0x46, 0x20, 0x04, 0x00, 0x58, 0x21, 0x02, 0x00, +0xb4, 0x22, 0x54, 0x10, 0x80, 0x03, 0xc9, 0x11, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x82, 0x04, +0xb4, 0x81, 0x47, 0xef, 0xf0, 0xff, 0x58, 0x22, 0x00, 0x01, 0xb6, 0x41, 0x59, 0xef, 0x0f, 0xff, +0xb4, 0xa1, 0x40, 0x22, 0xf8, 0x02, 0xd5, 0x35, 0x84, 0x61, 0x4c, 0x11, 0xc0, 0x03, 0xd5, 0x03, +0x84, 0xa2, 0xd9, 0x18, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x82, 0x04, 0x05, 0xe0, 0x80, 0x00, +0x84, 0x7e, 0x40, 0x5f, 0x0c, 0x02, 0xb6, 0xa1, 0x46, 0x4f, 0xf0, 0xff, 0xb4, 0x41, 0x58, 0x42, +0x0f, 0xff, 0x41, 0xe1, 0x10, 0x02, 0x15, 0xe0, 0x80, 0x00, 0x46, 0x30, 0x01, 0x00, 0xb4, 0x41, +0xd5, 0x16, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x82, 0x04, 0xb4, 0x41, 0x84, 0x7e, 0x41, 0xe1, +0x0c, 0x02, 0x15, 0xe0, 0x80, 0x00, 0x46, 0x5f, 0xf0, 0xff, 0xb4, 0x81, 0x58, 0x52, 0x8f, 0xff, +0x40, 0x22, 0x14, 0x02, 0xb6, 0x41, 0x46, 0x30, 0x05, 0x00, 0xb4, 0x41, 0x40, 0x21, 0x0c, 0x04, +0xb6, 0x41, 0xb4, 0x20, 0x58, 0x10, 0x83, 0x00, 0x48, 0x00, 0x00, 0xc9, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x85, 0x00, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0x30, 0xdd, 0x2f, +0x48, 0x00, 0x01, 0x69, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x04, 0x00, 0xb4, 0x80, 0x58, 0x12, +0x0c, 0x00, 0x48, 0x00, 0x00, 0xb4, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0x20, 0xdd, 0x2f, +0xc8, 0x09, 0x84, 0xa1, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x07, 0xba, 0xaf, 0x40, 0x48, 0x00, +0x01, 0x52, 0x46, 0x30, 0x00, 0x0b, 0x58, 0x31, 0x85, 0x34, 0xa6, 0x98, 0x47, 0xe0, 0x04, 0x01, +0x59, 0xef, 0x04, 0x00, 0xb6, 0x5e, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xf4, +0xdd, 0x2f, 0x48, 0x00, 0x01, 0x40, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0x00, 0xdd, 0x2f, +0x46, 0x50, 0x04, 0x01, 0x58, 0x52, 0x86, 0x60, 0x84, 0x80, 0xb6, 0x85, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x85, 0x08, 0xdd, 0x2f, 0x46, 0x10, 0x00, 0x0b, 0x58, 0x10, 0x87, 0xba, 0xae, 0x08, +0x46, 0x50, 0x04, 0x00, 0x58, 0x52, 0x82, 0x04, 0xb4, 0x45, 0x44, 0x3f, 0x00, 0xff, 0x40, 0x01, +0x0c, 0x02, 0x58, 0x40, 0x44, 0x00, 0xb6, 0x85, 0x46, 0x3f, 0xf0, 0xff, 0xb4, 0x45, 0x58, 0x31, +0x8f, 0xff, 0x58, 0x01, 0x00, 0x01, 0xb6, 0x05, 0x46, 0x10, 0x04, 0x00, 0xb4, 0x85, 0x58, 0x10, +0x82, 0x0c, 0x40, 0x22, 0x0c, 0x02, 0xb6, 0x45, 0xb4, 0x01, 0x58, 0x40, 0x03, 0x00, 0xb6, 0x81, +0x48, 0x00, 0x01, 0x09, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x07, 0xa4, 0x47, 0xe0, 0x00, 0x0b, +0x59, 0xef, 0x07, 0xac, 0x46, 0x30, 0x04, 0x10, 0xb4, 0x20, 0x02, 0x2f, 0x00, 0x00, 0xd5, 0x22, +0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x07, 0xa4, 0x46, 0x20, 0x04, 0x10, 0xb4, 0x20, 0xd5, 0x26, +0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x07, 0xa4, 0x46, 0x30, 0x04, 0x10, 0xb4, 0x20, 0x46, 0x60, +0x00, 0x0b, 0x58, 0x63, 0x07, 0xba, 0x48, 0x00, 0x00, 0xab, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, +0x07, 0xa4, 0x46, 0x20, 0x00, 0x0b, 0x58, 0x21, 0x07, 0xac, 0x46, 0x30, 0x04, 0x00, 0xb4, 0x20, +0xa4, 0x90, 0x98, 0x4b, 0xb6, 0x20, 0xac, 0x88, 0x48, 0x00, 0x00, 0xd5, 0x46, 0x00, 0x00, 0x0b, +0x58, 0x00, 0x07, 0xa4, 0x46, 0x20, 0x04, 0x00, 0xb4, 0x20, 0x98, 0xca, 0xb6, 0x60, 0x46, 0xf0, +0x00, 0x05, 0x58, 0xf7, 0x85, 0x60, 0xdd, 0x2f, 0x48, 0x00, 0x00, 0xbd, 0x46, 0x00, 0x00, 0x0b, +0x58, 0x00, 0x07, 0xa4, 0x46, 0x30, 0x04, 0x00, 0xb4, 0x20, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, +0x07, 0xba, 0xd5, 0x7d, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x07, 0xa4, 0xb4, 0xa0, 0x46, 0x00, +0x00, 0x0b, 0x58, 0x00, 0x07, 0xa8, 0x40, 0x12, 0xc0, 0x08, 0xb6, 0x20, 0x48, 0x00, 0x00, 0xab, +0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x07, 0xa4, 0x47, 0xe0, 0x00, 0x0b, 0x59, 0xef, 0x07, 0xa8, +0x46, 0x40, 0x00, 0x0b, 0x58, 0x42, 0x07, 0xac, 0xb4, 0x3e, 0xb4, 0x60, 0xa4, 0xa0, 0xd5, 0xc2, +0x46, 0x20, 0x00, 0x0b, 0x58, 0x21, 0x07, 0xa8, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x07, 0xa4, +0xb4, 0x22, 0xb4, 0x40, 0xd5, 0xc3, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, 0x07, 0xa8, 0x46, 0x00, +0x00, 0x0b, 0x58, 0x00, 0x07, 0xa4, 0xb4, 0x26, 0xb4, 0x60, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, +0x07, 0xba, 0x98, 0x4b, 0xd5, 0x45, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x07, 0xa4, 0x46, 0x50, +0x00, 0x0b, 0x58, 0x52, 0x87, 0xac, 0x46, 0x30, 0x04, 0x20, 0xb4, 0x20, 0xa4, 0xa8, 0xd5, 0x9a, +0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x07, 0xa4, 0x46, 0x20, 0x04, 0x20, 0xb4, 0x20, 0xd5, 0x9e, +0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x07, 0xa4, 0x46, 0x30, 0x04, 0x20, 0xb4, 0x20, 0x46, 0x60, +0x00, 0x0b, 0x58, 0x63, 0x07, 0xba, 0xd5, 0x23, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x07, 0xa4, +0x46, 0x40, 0x00, 0x0b, 0x58, 0x42, 0x07, 0xac, 0x46, 0x30, 0x05, 0x00, 0xb4, 0x20, 0xa4, 0xa0, +0x48, 0xff, 0xff, 0x79, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x07, 0xa4, 0x46, 0x20, 0x05, 0x00, +0xb4, 0x20, 0x48, 0xff, 0xff, 0x7c, 0x46, 0x00, 0x00, 0x0b, 0x58, 0x00, 0x07, 0xa4, 0x46, 0x30, +0x05, 0x00, 0xb4, 0x20, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, 0x07, 0xba, 0x98, 0x4b, 0xb6, 0x20, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0x20, 0xdd, 0x2f, 0xc8, 0x02, 0xd5, 0x1a, 0x46, 0xf0, +0x00, 0x05, 0x58, 0xf7, 0x85, 0xc0, 0xdd, 0x2f, 0xd5, 0x25, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, +0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x86, 0xb8, 0xdd, 0x2f, 0xd5, 0x1c, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x85, 0x20, 0xdd, 0x2f, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, 0x07, 0xba, 0xc8, 0x03, +0x84, 0x01, 0xd5, 0x10, 0x46, 0x20, 0x00, 0x0b, 0x58, 0x21, 0x07, 0xb6, 0x01, 0xe1, 0x00, 0x00, +0x56, 0x0f, 0x00, 0x0b, 0x5c, 0x00, 0x00, 0x01, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x86, 0x24, +0xdd, 0x2f, 0xae, 0x30, 0xd5, 0x07, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xdc, 0xdd, 0x2f, +0xd5, 0x06, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x85, 0x00, 0xdd, 0x2f, 0x46, 0x10, 0x00, 0x0b, +0x58, 0x10, 0x87, 0xba, 0x20, 0x00, 0x80, 0x00, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0x98, 0xbc, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x84, 0xb0, 0xdd, 0x2f, 0x46, 0xf0, +0x00, 0x00, 0x58, 0xf7, 0x84, 0x48, 0xdd, 0x2f, 0x46, 0x40, 0x04, 0x10, 0x04, 0x62, 0x02, 0x01, +0x40, 0x53, 0x20, 0x08, 0x92, 0xa8, 0x14, 0x52, 0x02, 0x01, 0x84, 0x0a, 0x46, 0x10, 0x00, 0x06, +0x58, 0x10, 0x80, 0x2c, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8d, 0xd4, 0xdd, 0x2f, 0x46, 0x30, +0x04, 0x00, 0xb4, 0x43, 0x44, 0x50, 0x76, 0x10, 0x40, 0x01, 0x40, 0x09, 0xd8, 0x07, 0x04, 0x01, +0x80, 0x41, 0x43, 0xe0, 0x50, 0x0b, 0x4f, 0xe2, 0x00, 0x0c, 0x84, 0x02, 0x46, 0x10, 0x00, 0x05, +0x58, 0x10, 0x82, 0x1c, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x80, 0x08, 0xdd, 0x2f, 0x46, 0x60, +0x00, 0x06, 0x58, 0x63, 0x00, 0x08, 0x84, 0x01, 0x46, 0x10, 0x00, 0x03, 0x58, 0x10, 0x85, 0x58, +0xdd, 0x26, 0x84, 0x0c, 0x46, 0x10, 0x00, 0x04, 0x58, 0x10, 0x82, 0x14, 0xdd, 0x26, 0x84, 0x0f, +0x46, 0x10, 0x00, 0x01, 0x58, 0x10, 0x88, 0x0c, 0xdd, 0x26, 0x46, 0x10, 0x00, 0x0a, 0x58, 0x10, +0x81, 0x18, 0x84, 0x00, 0xdd, 0x26, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x07, 0xcc, 0x46, 0xf0, +0x00, 0x05, 0x58, 0xf7, 0x8f, 0xb0, 0xdd, 0x2f, 0x84, 0x20, 0x80, 0x81, 0x46, 0x20, 0x00, 0x0a, +0x58, 0x21, 0x0d, 0x30, 0x44, 0x30, 0x08, 0x00, 0x46, 0x00, 0x00, 0x05, 0x58, 0x00, 0x0e, 0x68, +0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8f, 0x64, 0xdd, 0x2f, 0x84, 0x00, 0x46, 0x10, 0x00, 0x0a, +0x58, 0x10, 0x8b, 0xa8, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8f, 0x28, 0xdd, 0x2f, 0x46, 0x40, +0x04, 0x00, 0x84, 0xa1, 0x14, 0x52, 0x00, 0x8c, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0x24, +0xdd, 0x2f, 0x84, 0x00, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x46, 0xf0, 0x00, 0x0b, 0x04, 0x07, 0x81, 0xdd, 0xdd, 0x20, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x46, 0x20, 0x00, 0x0b, 0x58, 0x21, 0x07, 0x4c, 0x94, 0xc2, 0x98, 0x1a, +0xb6, 0x20, 0xdd, 0x9e, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, +0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, +0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, +0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, +0xdd, 0x9e, 0x92, 0x00, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x07, 0xa8, 0x46, 0x10, 0x00, 0x0e, +0x58, 0x10, 0x87, 0xb0, 0xb6, 0x20, 0x48, 0xff, 0xd1, 0x21, 0xdd, 0x9e, 0x64, 0x12, 0x00, 0x02, +0x96, 0x4c, 0x64, 0x02, 0x00, 0x43, 0x64, 0x00, 0x00, 0x08, 0xb6, 0x20, 0xdd, 0x9e, 0x92, 0x00, +0x64, 0x12, 0x00, 0x02, 0x42, 0x10, 0x80, 0x09, 0x40, 0x10, 0x80, 0x04, 0x64, 0x12, 0x00, 0x03, +0x64, 0x00, 0x00, 0x08, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x64, 0x12, 0x00, 0x43, +0x64, 0x00, 0x00, 0x08, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x07, 0xa8, 0x04, 0x03, 0x00, 0x0b, +0xc0, 0x02, 0xdd, 0x20, 0x04, 0x03, 0x00, 0x0c, 0xc0, 0x02, 0xdd, 0x20, 0x04, 0x23, 0x00, 0x08, +0x44, 0x10, 0x03, 0x00, 0x54, 0x01, 0x03, 0x00, 0x4c, 0x00, 0xff, 0xf2, 0x64, 0x00, 0x00, 0x00, +0xd5, 0xee, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x80, 0xc0, 0x50, 0x0f, 0x80, 0x04, +0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0x3c, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x37, +0x81, 0xf2, 0x40, 0x43, 0x18, 0x05, 0x40, 0x22, 0x0c, 0x02, 0xf0, 0x01, 0x46, 0xf0, 0x00, 0x0e, +0x14, 0x27, 0x81, 0xf2, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0x50, 0xdd, 0x2f, 0xec, 0x08, +0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x80, 0xc0, +0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0x3c, 0xdd, 0x2f, 0x46, 0xf0, +0x00, 0x0e, 0x04, 0x37, 0x81, 0xf2, 0xf0, 0x01, 0x40, 0x23, 0x0c, 0x04, 0x46, 0xf0, 0x00, 0x0e, +0x14, 0x27, 0x81, 0xf2, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0x50, 0xdd, 0x2f, 0xec, 0x08, +0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x80, 0xc1, 0x46, 0xf0, +0x00, 0x0e, 0x14, 0x07, 0x81, 0xf5, 0x46, 0xf0, 0x00, 0x0e, 0x14, 0x67, 0x81, 0xf6, 0xc8, 0x08, +0x44, 0x00, 0x01, 0x00, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0xe8, 0xdd, 0x2f, 0xce, 0x08, +0x44, 0x00, 0x02, 0x00, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0xe8, 0xdd, 0x2f, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0x44, 0x50, 0x00, 0x14, 0x46, 0x60, 0x00, 0x0e, +0x58, 0x63, 0x07, 0xb0, 0x42, 0x60, 0x94, 0x73, 0x80, 0xe0, 0x81, 0x43, 0x50, 0x03, 0x00, 0x0c, +0xa8, 0x71, 0x84, 0x20, 0x81, 0x22, 0x81, 0x04, 0xa8, 0x72, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, +0x8f, 0xb0, 0xdd, 0x2f, 0x50, 0x35, 0x7f, 0xb8, 0x40, 0x24, 0x8c, 0x00, 0x58, 0x44, 0x00, 0x08, +0x84, 0x0a, 0xb6, 0x46, 0xa9, 0xd1, 0xb6, 0x82, 0xa8, 0x12, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, +0xa8, 0x01, 0xb6, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0xa0, 0x81, 0xb6, 0x01, 0xa8, 0x89, 0xb6, 0x22, +0xa8, 0x41, 0xdd, 0x9e, 0xb4, 0x20, 0x4c, 0x10, 0x40, 0x04, 0x84, 0x20, 0xd5, 0x07, 0xa0, 0xc9, +0xb4, 0x81, 0xb6, 0x83, 0xb4, 0x01, 0xa0, 0x89, 0xa8, 0x81, 0x80, 0x01, 0xdd, 0x9e, 0x92, 0x00, +0x46, 0x20, 0x00, 0x0b, 0x04, 0x11, 0x01, 0xe8, 0x98, 0x01, 0x14, 0x01, 0x01, 0xe8, 0x80, 0x01, +0xdd, 0x9e, 0x92, 0x00, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x88, 0x0c, 0x46, 0xf0, 0x00, 0x0b, +0x14, 0x17, 0x81, 0xe8, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x50, 0x00, 0x0e, 0x58, 0x52, 0x83, 0xd0, +0x38, 0x12, 0x82, 0x0a, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x82, 0x00, 0xa0, 0x8d, 0x84, 0x61, +0x40, 0x41, 0x80, 0x0c, 0x40, 0x02, 0x08, 0x04, 0xa8, 0x0d, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x46, 0x30, 0x04, 0x00, 0x58, 0x31, 0x82, 0x00, 0xa0, 0x5c, 0x46, 0xf0, 0x00, 0x0e, +0x00, 0x07, 0x84, 0x8a, 0xc0, 0x0e, 0x47, 0xe0, 0x04, 0x00, 0x46, 0x08, 0x00, 0x00, 0x58, 0x00, +0x03, 0xe8, 0x84, 0xa1, 0x14, 0x0f, 0x00, 0x22, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x57, 0x84, 0x8b, +0x96, 0x08, 0x54, 0x20, 0x00, 0x08, 0xc2, 0x07, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xf7, +0x48, 0x00, 0x00, 0x84, 0x54, 0x30, 0x00, 0x10, 0xc3, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, +0x80, 0xf8, 0xd5, 0x7b, 0x54, 0x50, 0x00, 0x20, 0xc5, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, +0x80, 0xf9, 0xd5, 0x73, 0x54, 0x20, 0x00, 0x02, 0xc2, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, +0x80, 0xf5, 0xd5, 0x6b, 0x96, 0xc4, 0xc3, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xf4, +0xd5, 0x64, 0x54, 0x40, 0x00, 0x04, 0xc4, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xf6, +0xd5, 0x5c, 0x40, 0x20, 0xa0, 0x09, 0x96, 0x10, 0x55, 0xe0, 0x00, 0x01, 0x4f, 0xe2, 0x00, 0x07, +0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xfc, 0xd5, 0x50, 0x54, 0x30, 0x00, 0x02, 0xc3, 0x06, +0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xfd, 0xd5, 0x48, 0x54, 0x40, 0x00, 0x04, 0xc4, 0x06, +0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xfe, 0xd5, 0x40, 0x55, 0xe0, 0x00, 0x08, 0x4f, 0xe2, +0x00, 0x07, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x80, 0xff, 0xd5, 0x37, 0x54, 0x30, 0x00, 0x10, +0xc3, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x81, 0x00, 0xd5, 0x2f, 0x54, 0x40, 0x00, 0x20, +0xc4, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x81, 0x01, 0xd5, 0x27, 0x54, 0x50, 0x00, 0x40, +0xc5, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x81, 0x02, 0xd5, 0x1f, 0x54, 0x20, 0x00, 0x80, +0xc2, 0x06, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x81, 0x03, 0xd5, 0x17, 0x40, 0x40, 0xc0, 0x09, +0x96, 0x60, 0x96, 0x0c, 0xc0, 0x02, 0xd5, 0x04, 0x54, 0x10, 0x80, 0x02, 0xc1, 0x06, 0x46, 0xf0, +0x00, 0x0e, 0x04, 0x07, 0x81, 0x04, 0xd5, 0x09, 0x47, 0xe0, 0x04, 0x00, 0x04, 0x3f, 0x00, 0x8d, +0x9c, 0x99, 0x14, 0x2f, 0x00, 0x8d, 0xd5, 0x02, 0xdd, 0x20, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xa8, 0x3c, 0xef, 0xf4, 0x46, 0x30, 0x04, 0x10, 0x54, 0x80, +0x00, 0x0f, 0x58, 0x31, 0x85, 0x00, 0x40, 0x84, 0x38, 0x08, 0x84, 0x80, 0x54, 0x70, 0x80, 0x3f, +0xb4, 0xa3, 0xf5, 0x81, 0x00, 0x5f, 0x80, 0x07, 0x54, 0x52, 0x80, 0x80, 0x97, 0x68, 0xcd, 0x3c, +0xf5, 0x81, 0x00, 0x9f, 0x80, 0x07, 0x42, 0x94, 0x98, 0x09, 0x00, 0x6f, 0x80, 0x05, 0x92, 0xc6, +0x95, 0xb6, 0x44, 0xaf, 0xff, 0x80, 0x40, 0x94, 0xa8, 0x04, 0x40, 0x63, 0x1c, 0x04, 0x10, 0x9f, +0x80, 0x07, 0x10, 0x6f, 0x80, 0x05, 0x44, 0x9c, 0x3f, 0xff, 0xf6, 0x01, 0x40, 0x63, 0x24, 0x02, +0x40, 0x63, 0x20, 0x04, 0xf6, 0x81, 0xb6, 0xc3, 0xb4, 0xc3, 0x9d, 0x69, 0xf6, 0x81, 0x00, 0x6f, +0x80, 0x07, 0x54, 0x63, 0x00, 0x80, 0xc6, 0x05, 0x44, 0xa0, 0x00, 0x64, 0x4c, 0x55, 0x7f, 0xf6, +0x00, 0x5f, 0x80, 0x07, 0x54, 0x52, 0x80, 0x80, 0xcd, 0x0f, 0x00, 0x5f, 0x80, 0x05, 0x54, 0x52, +0x80, 0x3f, 0xd9, 0x0a, 0xf5, 0x01, 0x92, 0xae, 0x54, 0x52, 0x80, 0x0f, 0xd8, 0x05, 0x00, 0x0f, +0x80, 0x04, 0xb6, 0x02, 0xd5, 0x05, 0x9d, 0x21, 0x44, 0x50, 0x00, 0x64, 0xdc, 0xba, 0xf1, 0x01, +0x40, 0x00, 0xfc, 0x09, 0xec, 0x0c, 0x3a, 0x6f, 0xa8, 0x04, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, +0xef, 0xf8, 0x46, 0x30, 0x04, 0x10, 0x84, 0x80, 0x05, 0xe1, 0x81, 0x40, 0x9d, 0x21, 0x15, 0xef, +0x80, 0x01, 0x00, 0x6f, 0x80, 0x07, 0x54, 0x53, 0x00, 0x80, 0xc5, 0x04, 0x44, 0x50, 0x00, 0x64, +0xdc, 0xf4, 0x00, 0x5f, 0x80, 0x07, 0x44, 0x3f, 0xff, 0xc0, 0x41, 0xe2, 0x8c, 0x04, 0x11, 0xef, +0x80, 0x07, 0x54, 0x40, 0x00, 0x0f, 0xf3, 0x01, 0x44, 0x6c, 0x3f, 0xff, 0x40, 0x52, 0x38, 0x08, +0x41, 0xe1, 0x98, 0x02, 0x40, 0x3f, 0x14, 0x04, 0xf3, 0x81, 0x01, 0xef, 0x80, 0x05, 0x54, 0x40, +0x80, 0x3f, 0x40, 0x6f, 0x18, 0x09, 0x95, 0xb6, 0x40, 0x33, 0x10, 0x04, 0x10, 0x2f, 0x80, 0x04, +0x10, 0x3f, 0x80, 0x05, 0x46, 0x20, 0x04, 0x10, 0xf6, 0x01, 0x14, 0x61, 0x01, 0x40, 0x80, 0x5f, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0x84, 0xdd, 0x2f, 0x84, 0x01, 0xec, 0x08, 0x3a, 0x6f, +0x98, 0x84, 0xdd, 0x9e, 0xef, 0xf8, 0x46, 0x00, 0x04, 0x11, 0x58, 0x00, 0x00, 0x1c, 0x84, 0x60, +0xb4, 0x80, 0xf4, 0x81, 0x00, 0x5f, 0x80, 0x06, 0x54, 0x42, 0x80, 0x02, 0x97, 0x20, 0xcc, 0x23, +0xf4, 0x81, 0x10, 0x1f, 0x80, 0x05, 0x00, 0x5f, 0x80, 0x06, 0x58, 0x52, 0x80, 0x03, 0x10, 0x5f, +0x80, 0x06, 0xf5, 0x01, 0xb6, 0xa0, 0xb4, 0xa0, 0x9d, 0x21, 0xf5, 0x81, 0x00, 0x5f, 0x80, 0x06, +0x54, 0x52, 0x80, 0x02, 0xc5, 0x04, 0x44, 0x50, 0x00, 0x64, 0xdc, 0xf6, 0x00, 0x5f, 0x80, 0x06, +0x54, 0x42, 0x80, 0x02, 0xcc, 0x08, 0x00, 0x5f, 0x80, 0x05, 0xd9, 0x05, 0x00, 0x0f, 0x80, 0x04, +0xb6, 0x02, 0xd5, 0x05, 0x9c, 0xd9, 0x44, 0x50, 0x00, 0x64, 0xdb, 0xd3, 0xf1, 0x01, 0x42, 0x00, +0xc4, 0x0b, 0xec, 0x08, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, 0x46, 0x30, +0x04, 0x11, 0x84, 0x80, 0xa1, 0x5f, 0x9d, 0x21, 0xf5, 0x81, 0x01, 0xef, 0x80, 0x06, 0x54, 0x5f, +0x00, 0x02, 0xc5, 0x04, 0x44, 0x50, 0x00, 0x64, 0xdc, 0xf6, 0x84, 0xa0, 0x84, 0x82, 0xf5, 0x81, +0x10, 0x2f, 0x80, 0x04, 0x10, 0x4f, 0x80, 0x06, 0x10, 0x1f, 0x80, 0x05, 0x80, 0x43, 0xf3, 0x01, +0xa8, 0xd7, 0x80, 0x5f, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0x84, 0x01, +0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xf8, 0x46, 0x10, +0x04, 0x10, 0x46, 0x00, 0x04, 0x10, 0x46, 0x20, 0x00, 0xff, 0x58, 0x10, 0x85, 0x0c, 0x58, 0x00, +0x05, 0x04, 0x44, 0x40, 0xe0, 0x10, 0x58, 0x21, 0x0f, 0xf8, 0xb5, 0x21, 0xb5, 0x00, 0xb6, 0x81, +0xb6, 0x40, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x01, 0x84, 0x84, 0x21, 0x50, 0x2f, 0x80, 0x04, +0x84, 0x05, 0xdd, 0x26, 0x84, 0x64, 0x80, 0x43, 0x84, 0x05, 0x84, 0x21, 0xb6, 0x7f, 0x81, 0x46, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0x3c, 0xdd, 0x2f, 0x80, 0xdf, 0xd5, 0x0a, 0x84, 0x00, +0x92, 0x00, 0x84, 0xa7, 0x9c, 0x01, 0xd8, 0xfd, 0x84, 0x05, 0x84, 0x21, 0x80, 0x5f, 0xdd, 0x2a, +0xb4, 0xff, 0x54, 0x73, 0x80, 0x04, 0xcf, 0xf4, 0xf2, 0x01, 0x84, 0x21, 0x84, 0x05, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x82, 0x3c, 0xdd, 0x2f, 0x46, 0x30, 0x04, 0x10, 0x46, 0x00, 0x04, 0x10, +0x58, 0x31, 0x85, 0x04, 0x58, 0x00, 0x05, 0x0c, 0xb6, 0xe3, 0xb7, 0x20, 0xb7, 0x03, 0xec, 0x08, +0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x84, 0x21, 0x80, 0x40, 0x44, 0x00, 0x02, 0x58, +0x40, 0x51, 0x00, 0x97, 0x9c, 0x49, 0x96, 0x48, 0x84, 0x6b, 0x98, 0x28, 0x92, 0x01, 0x4c, 0x11, +0xff, 0xf9, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, 0x46, 0x20, 0x04, 0x11, 0x80, 0x80, +0x84, 0x60, 0x05, 0xe1, 0x00, 0x07, 0x9c, 0xd9, 0x15, 0xef, 0x80, 0x01, 0x00, 0x5f, 0x80, 0x06, +0x54, 0x02, 0x80, 0x02, 0xc0, 0x04, 0x44, 0x50, 0x00, 0x64, 0xdb, 0xf4, 0x84, 0x62, 0x84, 0x00, +0xf0, 0x81, 0x10, 0x3f, 0x80, 0x06, 0x10, 0x1f, 0x80, 0x04, 0x10, 0x4f, 0x80, 0x05, 0xf1, 0x01, +0xa8, 0x57, 0x80, 0x24, 0x80, 0x5f, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, +0x84, 0x01, 0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xa4, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x81, 0x84, 0x84, 0x22, 0x50, 0x2f, 0x80, 0x50, +0x84, 0x04, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x1c, 0x50, 0x2f, 0x80, 0x4c, 0x84, 0x04, 0xdd, 0x27, +0x44, 0x10, 0x00, 0x1d, 0x50, 0x2f, 0x80, 0x48, 0x84, 0x04, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x13, +0x50, 0x2f, 0x80, 0x44, 0x84, 0x04, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x11, 0x50, 0x2f, 0x80, 0x40, +0x84, 0x05, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x12, 0x50, 0x2f, 0x80, 0x3c, 0x84, 0x05, 0xdd, 0x27, +0x44, 0x10, 0x00, 0x13, 0x50, 0x2f, 0x80, 0x38, 0x84, 0x05, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x14, +0x50, 0x2f, 0x80, 0x34, 0x84, 0x05, 0xdd, 0x27, 0x46, 0x00, 0x04, 0x10, 0x58, 0x00, 0x00, 0x80, +0xb4, 0x80, 0x46, 0x10, 0x04, 0x10, 0xf4, 0x87, 0x58, 0x10, 0x84, 0x00, 0xb4, 0x41, 0x46, 0xa0, +0x04, 0x11, 0xf2, 0x86, 0x58, 0xa5, 0x02, 0x04, 0xb4, 0x6a, 0x46, 0x90, 0x04, 0x10, 0xf3, 0x85, +0x58, 0x94, 0x85, 0x0c, 0xb4, 0xa9, 0x46, 0x60, 0x04, 0x10, 0xf5, 0x84, 0x58, 0x63, 0x05, 0x04, +0xb4, 0x86, 0x47, 0xcf, 0xf0, 0x00, 0x46, 0x80, 0x00, 0x80, 0x84, 0x43, 0x59, 0xce, 0x00, 0x03, +0x58, 0x84, 0x0c, 0x00, 0xf4, 0x83, 0x15, 0xc0, 0x00, 0x00, 0xb7, 0x01, 0xb6, 0x4a, 0x47, 0xc0, +0x00, 0x04, 0x59, 0xce, 0x02, 0xa8, 0x84, 0x01, 0xdd, 0x3c, 0x46, 0x50, 0x18, 0xca, 0x44, 0x30, +0x00, 0x1f, 0x58, 0x52, 0x80, 0x0f, 0x84, 0x9f, 0x44, 0xa0, 0x00, 0x17, 0xb7, 0x49, 0xb6, 0x66, +0xb6, 0xa9, 0xb6, 0x86, 0x44, 0x10, 0x00, 0x11, 0x50, 0x2f, 0x80, 0x30, 0x84, 0x00, 0xdd, 0x27, +0x44, 0x10, 0x00, 0x12, 0x50, 0x2f, 0x80, 0x2c, 0x84, 0x00, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x13, +0x50, 0x2f, 0x80, 0x28, 0x84, 0x00, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x14, 0x50, 0x2f, 0x80, 0x24, +0x84, 0x00, 0xdd, 0x27, 0x84, 0x24, 0x50, 0x2f, 0x80, 0x20, 0x84, 0x00, 0x46, 0x80, 0x00, 0x06, +0x58, 0x84, 0x02, 0x3c, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x11, 0x44, 0x20, 0x00, 0x99, 0x84, 0x00, +0xdd, 0x28, 0x44, 0x10, 0x00, 0x12, 0x44, 0x20, 0x00, 0x99, 0x84, 0x00, 0xdd, 0x28, 0x44, 0x10, +0x00, 0x13, 0x84, 0x49, 0x84, 0x00, 0xdd, 0x28, 0x44, 0x10, 0x00, 0x14, 0x44, 0x20, 0x00, 0x51, +0x84, 0x00, 0xdd, 0x28, 0x84, 0x24, 0x44, 0x20, 0x00, 0x8e, 0x84, 0x00, 0xdd, 0x28, 0x84, 0x21, +0x80, 0x41, 0x84, 0x05, 0xdd, 0x28, 0x84, 0x01, 0xdd, 0x3c, 0x46, 0x06, 0x00, 0x42, 0x58, 0x00, +0x00, 0x3f, 0xb6, 0x09, 0x44, 0x10, 0x00, 0x13, 0x44, 0x20, 0x00, 0x27, 0x84, 0x04, 0xdd, 0x28, +0x44, 0x10, 0x00, 0x11, 0x44, 0x20, 0x00, 0x80, 0x84, 0x05, 0xdd, 0x28, 0x44, 0x10, 0x00, 0x12, +0x44, 0x20, 0x00, 0xf1, 0x84, 0x05, 0xdd, 0x28, 0x44, 0x10, 0x00, 0x13, 0x44, 0x20, 0x00, 0xa1, +0x84, 0x05, 0xdd, 0x28, 0x84, 0x41, 0x44, 0x10, 0x00, 0x14, 0x84, 0x05, 0xdd, 0x28, 0x46, 0x10, +0x00, 0x82, 0x58, 0x10, 0x80, 0x3f, 0xb6, 0x29, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x04, 0x44, +0x80, 0x0a, 0x84, 0x24, 0xdd, 0x26, 0x84, 0x2a, 0x44, 0x00, 0x00, 0xf1, 0xdd, 0x26, 0x84, 0x20, +0x44, 0x00, 0x00, 0xf2, 0xdd, 0x26, 0x84, 0x20, 0x84, 0x04, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x31, +0x44, 0x00, 0x00, 0xf4, 0xdd, 0x26, 0x46, 0x20, 0x04, 0x10, 0xf2, 0x82, 0x84, 0x01, 0x84, 0x24, +0xdd, 0x26, 0xf3, 0x02, 0x85, 0x40, 0x58, 0x31, 0x80, 0x7c, 0xf3, 0x82, 0x14, 0xaf, 0x80, 0x01, +0x83, 0x8a, 0x50, 0x9f, 0x80, 0x54, 0x05, 0xef, 0x80, 0x01, 0x54, 0x75, 0x00, 0x07, 0x41, 0xe3, +0x9c, 0x1a, 0x54, 0x85, 0x00, 0xff, 0x15, 0xef, 0x80, 0x01, 0x41, 0xc3, 0x9c, 0x1a, 0xe7, 0x08, +0xe8, 0x19, 0x80, 0x49, 0x44, 0x10, 0x00, 0x2b, 0x84, 0x04, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x81, 0x84, 0xdd, 0x2f, 0xf0, 0x15, 0x44, 0x10, 0x00, 0x2b, 0x54, 0x50, 0x00, 0xf8, 0x40, 0x25, +0x14, 0x04, 0x84, 0x04, 0xf5, 0x95, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0x3c, 0xdd, 0x2f, +0xd5, 0x19, 0x44, 0x10, 0x00, 0x11, 0x80, 0x49, 0x84, 0x04, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x81, 0x84, 0xdd, 0x2f, 0xf2, 0x15, 0x94, 0x7b, 0x54, 0x31, 0x00, 0xc7, 0x40, 0x20, 0x8c, 0x04, +0x84, 0x04, 0x44, 0x10, 0x00, 0x11, 0xf3, 0x95, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0x3c, +0xdd, 0x2f, 0x84, 0x21, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9f, +0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x9b, 0x44, 0x00, +0x00, 0x9f, 0xdd, 0x26, 0x84, 0x20, 0xd5, 0x0b, 0x92, 0x00, 0x84, 0x87, 0x9c, 0x01, 0x4c, 0x02, +0x7f, 0xfd, 0x9c, 0x49, 0x45, 0xe0, 0x01, 0x2c, 0x4c, 0x1f, 0x00, 0x04, 0x84, 0x00, 0xd5, 0xf5, +0x84, 0x21, 0x44, 0x00, 0x00, 0x15, 0xdd, 0x26, 0x84, 0x20, 0xd5, 0x09, 0x92, 0x00, 0x84, 0xa7, +0x9c, 0x01, 0xd8, 0xfd, 0x9c, 0x49, 0x84, 0x0a, 0x4c, 0x10, 0x00, 0x04, 0x84, 0x00, 0xd5, 0xf7, +0x84, 0x20, 0x44, 0x00, 0x00, 0x15, 0xdd, 0x26, 0x44, 0x10, 0x00, 0xba, 0x44, 0x00, 0x00, 0x9e, +0xdd, 0x26, 0x44, 0x10, 0x00, 0x10, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x26, 0xf3, 0x02, 0xb4, 0x23, +0x40, 0x00, 0xc0, 0x09, 0x4e, 0x14, 0x00, 0x05, 0x44, 0x2f, 0x00, 0x00, 0x98, 0x02, 0x45, 0xe0, +0x80, 0x00, 0x40, 0x40, 0xf8, 0x02, 0x96, 0x49, 0xc4, 0x04, 0x44, 0x5f, 0x00, 0x00, 0x98, 0x4d, +0x42, 0x00, 0x00, 0x24, 0x42, 0x00, 0x84, 0x73, 0xf1, 0x01, 0xe2, 0x20, 0xe8, 0x04, 0xf0, 0x81, +0x55, 0xc4, 0x00, 0x07, 0x84, 0x07, 0x4c, 0x70, 0x40, 0x6a, 0x4c, 0x83, 0xc0, 0x4b, 0x80, 0x49, +0x44, 0x10, 0x00, 0x2b, 0x84, 0x04, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0x84, 0xdd, 0x2f, +0xf5, 0x15, 0x44, 0x10, 0x00, 0x2b, 0x54, 0x22, 0x80, 0xf8, 0x40, 0x4e, 0x08, 0x04, 0x80, 0x44, +0x84, 0x04, 0xf4, 0x95, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0x3c, 0xdd, 0x2f, 0x80, 0x49, +0x44, 0x10, 0x00, 0x2c, 0x84, 0x04, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0x84, 0xdd, 0x2f, +0xf3, 0x15, 0x44, 0x10, 0x00, 0x2c, 0x54, 0x01, 0x80, 0xf8, 0x40, 0x5e, 0x00, 0x04, 0x80, 0x45, +0x84, 0x04, 0xf5, 0x95, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0x3c, 0xdd, 0x2f, 0x80, 0x49, +0x44, 0x10, 0x00, 0x2d, 0x84, 0x04, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0x84, 0xdd, 0x2f, +0xf4, 0x15, 0x44, 0x10, 0x00, 0x2d, 0x54, 0x22, 0x00, 0xf8, 0x40, 0x3e, 0x08, 0x04, 0x80, 0x43, +0x84, 0x04, 0xf3, 0x95, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0x3c, 0xdd, 0x2f, 0xd5, 0x1e, +0x87, 0xcf, 0x4c, 0x8f, 0x40, 0x1c, 0x44, 0x10, 0x00, 0x11, 0x80, 0x49, 0x84, 0x04, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x81, 0x84, 0xdd, 0x2f, 0xf4, 0x15, 0x40, 0x1e, 0x0c, 0x08, 0x54, 0x02, +0x00, 0xc7, 0x40, 0x30, 0x80, 0x04, 0x80, 0x43, 0x84, 0x04, 0x44, 0x10, 0x00, 0x11, 0xf3, 0x95, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0x3c, 0xdd, 0x2f, 0x8d, 0x41, 0x44, 0x20, 0x00, 0x10, +0x4c, 0xa1, 0x7e, 0xfb, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x84, 0x20, 0x44, 0x00, +0x00, 0xf4, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, +0x00, 0x9f, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x15, 0x84, 0x21, 0xdd, 0x26, 0x84, 0x00, 0xd5, 0x09, +0x92, 0x00, 0x84, 0xa7, 0x9c, 0x49, 0xd9, 0xfd, 0x9c, 0x01, 0x87, 0xca, 0x4c, 0x0f, 0x00, 0x04, +0x84, 0x20, 0xd5, 0xf7, 0x84, 0x20, 0x44, 0x00, 0x00, 0x15, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x84, 0x44, 0xdd, 0x2f, 0xf2, 0x0c, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x02, 0x3c, 0x44, 0x10, +0x00, 0x11, 0x84, 0x00, 0xdd, 0x26, 0xf2, 0x0b, 0x44, 0x10, 0x00, 0x12, 0x84, 0x00, 0xdd, 0x26, +0xf2, 0x0a, 0x44, 0x10, 0x00, 0x13, 0x84, 0x00, 0xdd, 0x26, 0xf2, 0x09, 0x44, 0x10, 0x00, 0x14, +0x84, 0x00, 0xdd, 0x26, 0xf2, 0x08, 0x84, 0x24, 0x84, 0x00, 0xdd, 0x26, 0xf2, 0x11, 0x44, 0x10, +0x00, 0x13, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x10, 0x44, 0x10, 0x00, 0x11, 0x84, 0x05, 0xdd, 0x26, +0xf2, 0x0f, 0x44, 0x10, 0x00, 0x12, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x0e, 0x44, 0x10, 0x00, 0x13, +0x84, 0x05, 0xdd, 0x26, 0xf2, 0x0d, 0x44, 0x10, 0x00, 0x14, 0x84, 0x05, 0xdd, 0x26, 0xf5, 0x07, +0x46, 0x40, 0x04, 0x10, 0x58, 0x42, 0x00, 0x80, 0xb6, 0xa4, 0x46, 0x30, 0x04, 0x10, 0xf4, 0x06, +0x58, 0x31, 0x84, 0x00, 0xb6, 0x83, 0x46, 0x20, 0x04, 0x11, 0xf5, 0x05, 0x58, 0x21, 0x02, 0x04, +0xb6, 0xa2, 0x46, 0x10, 0x04, 0x10, 0xf4, 0x03, 0x58, 0x10, 0x85, 0x04, 0xb6, 0x81, 0x46, 0x00, +0x04, 0x10, 0xf3, 0x04, 0x58, 0x00, 0x05, 0x0c, 0xb6, 0x60, 0xec, 0x5c, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xc4, 0x46, 0x40, 0x04, 0x11, 0x58, 0x42, +0x00, 0x04, 0xb4, 0xa4, 0x84, 0xc0, 0xf5, 0x81, 0x46, 0x20, 0x04, 0x10, 0xb6, 0xc4, 0x44, 0x30, +0x18, 0x30, 0x58, 0x21, 0x05, 0x04, 0x05, 0xc1, 0x00, 0x00, 0x46, 0x00, 0x04, 0x10, 0xb6, 0x62, +0x58, 0x00, 0x05, 0x0c, 0x44, 0x10, 0x20, 0x00, 0xb5, 0x40, 0xb6, 0x20, 0x46, 0x80, 0x00, 0x06, +0x58, 0x84, 0x01, 0x84, 0x50, 0x2f, 0x80, 0x34, 0x84, 0x24, 0x84, 0x05, 0x46, 0x70, 0x00, 0x06, +0x58, 0x73, 0x82, 0x3c, 0xdd, 0x28, 0x84, 0x24, 0x44, 0x20, 0x00, 0x27, 0x84, 0x05, 0xdd, 0x27, +0x50, 0x2f, 0x80, 0x30, 0x44, 0x10, 0x00, 0x11, 0x84, 0x05, 0xdd, 0x28, 0x44, 0x10, 0x00, 0x11, +0x44, 0x20, 0x00, 0x80, 0x84, 0x05, 0xdd, 0x27, 0x50, 0x2f, 0x80, 0x2c, 0x44, 0x10, 0x00, 0x12, +0x84, 0x05, 0xdd, 0x28, 0x44, 0x10, 0x00, 0x12, 0x44, 0x20, 0x00, 0x83, 0x84, 0x05, 0xdd, 0x27, +0x50, 0x2f, 0x80, 0x28, 0x44, 0x10, 0x00, 0x13, 0x84, 0x05, 0xdd, 0x28, 0x50, 0x2f, 0x80, 0x24, +0x44, 0x10, 0x00, 0x14, 0x84, 0x05, 0xdd, 0x28, 0x80, 0x46, 0x44, 0x10, 0x00, 0x13, 0x84, 0x05, +0xdd, 0x27, 0x44, 0x10, 0x00, 0x14, 0x44, 0x20, 0x00, 0x20, 0x84, 0x05, 0xdd, 0x27, 0x50, 0x2f, +0x80, 0x20, 0x80, 0x06, 0x84, 0x21, 0xdd, 0x28, 0x80, 0x46, 0x80, 0x06, 0x84, 0x21, 0xdd, 0x27, +0x50, 0x2f, 0x80, 0x1c, 0x80, 0x06, 0x44, 0x10, 0x00, 0x22, 0xdd, 0x28, 0x80, 0x06, 0x44, 0x10, +0x00, 0x22, 0x44, 0x20, 0x00, 0x13, 0xdd, 0x27, 0x50, 0x2f, 0x80, 0x18, 0x80, 0x06, 0x44, 0x10, +0x00, 0x23, 0xdd, 0x28, 0x80, 0x46, 0x80, 0x06, 0x44, 0x10, 0x00, 0x23, 0xdd, 0x27, 0x46, 0x90, +0x00, 0x06, 0x58, 0x94, 0x82, 0xc4, 0x50, 0x2f, 0x80, 0x14, 0x44, 0x10, 0x00, 0x2f, 0x80, 0x06, +0x4b, 0xe0, 0x24, 0x01, 0x46, 0x80, 0x00, 0x06, 0x58, 0x84, 0x04, 0x44, 0x84, 0x24, 0x44, 0x00, +0x00, 0x2f, 0xdd, 0x28, 0x44, 0x10, 0x00, 0x80, 0x44, 0x00, 0x00, 0x16, 0xdd, 0x28, 0x84, 0x01, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x82, 0xa8, 0xdd, 0x2f, 0x50, 0x2f, 0x80, 0x10, 0x80, 0x06, +0x44, 0x10, 0x00, 0x31, 0x4b, 0xe0, 0x24, 0x01, 0x80, 0x26, 0x44, 0x00, 0x00, 0x16, 0x04, 0x9f, +0x80, 0x04, 0xdd, 0x28, 0x80, 0x06, 0x44, 0x10, 0x00, 0x23, 0x84, 0x41, 0xdd, 0x27, 0x44, 0x10, +0x00, 0x80, 0x44, 0x00, 0x00, 0x16, 0xdd, 0x28, 0xd5, 0x0b, 0x92, 0x00, 0x87, 0xc7, 0x9c, 0x49, +0x4c, 0x1f, 0x7f, 0xfd, 0x9d, 0xb1, 0x44, 0x70, 0x00, 0x3c, 0x4c, 0x63, 0x80, 0x04, 0x84, 0x20, +0xd5, 0xf5, 0x44, 0x10, 0x00, 0x31, 0x50, 0x2f, 0x80, 0x10, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0x20, 0x7f, 0x80, 0x10, 0x40, 0x54, 0x80, 0x10, 0x9a, 0xfd, +0x44, 0x40, 0x03, 0xe8, 0x42, 0x01, 0x90, 0x24, 0x44, 0x20, 0x00, 0x2b, 0x40, 0x00, 0x08, 0x36, +0x84, 0x2a, 0x40, 0x20, 0x04, 0xd6, 0xe4, 0xc5, 0xe9, 0x02, 0x8c, 0x0a, 0x87, 0xca, 0x40, 0x20, +0x78, 0x16, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x02, 0x3c, 0x84, 0x27, 0x84, 0x00, 0x46, 0x70, +0x00, 0x06, 0x58, 0x73, 0x84, 0x44, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, 0x00, 0x16, 0xdd, 0x27, +0x84, 0x21, 0x44, 0x00, 0x00, 0x15, 0xdd, 0x27, 0x84, 0x20, 0x44, 0x00, 0x00, 0x15, 0xdd, 0x27, +0xf2, 0x0d, 0x84, 0x24, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x0c, 0x44, 0x10, 0x00, 0x11, 0x84, 0x05, +0xdd, 0x26, 0xf2, 0x0b, 0x44, 0x10, 0x00, 0x12, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x0a, 0x44, 0x10, +0x00, 0x13, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x09, 0x44, 0x10, 0x00, 0x14, 0x84, 0x05, 0xdd, 0x26, +0xf2, 0x08, 0x84, 0x21, 0x84, 0x00, 0xdd, 0x26, 0xf2, 0x07, 0x44, 0x10, 0x00, 0x22, 0x84, 0x00, +0xdd, 0x26, 0xf2, 0x06, 0x44, 0x10, 0x00, 0x23, 0x84, 0x00, 0xdd, 0x26, 0xf1, 0x05, 0x44, 0x00, +0x00, 0x2f, 0xdd, 0x27, 0xf3, 0x01, 0x46, 0x20, 0x04, 0x11, 0x46, 0x10, 0x04, 0x10, 0x46, 0x00, +0x04, 0x10, 0x58, 0x21, 0x00, 0x04, 0x58, 0x10, 0x85, 0x04, 0x58, 0x00, 0x05, 0x0c, 0xb6, 0x62, +0x15, 0xc0, 0x80, 0x00, 0xb7, 0x40, 0x84, 0x27, 0x50, 0x2f, 0x80, 0x0c, 0x84, 0x00, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x81, 0x84, 0xdd, 0x2f, 0xec, 0x3c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf8, 0x84, 0x21, 0x96, 0x00, 0x50, 0x2f, 0x80, 0x04, 0x46, 0x30, +0x00, 0x06, 0x58, 0x31, 0x81, 0x84, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x02, 0x3c, 0x4c, 0x00, +0xc0, 0x10, 0x84, 0x23, 0x84, 0x05, 0x4b, 0xe0, 0x0c, 0x01, 0xf2, 0x01, 0x40, 0x31, 0x14, 0x09, +0x94, 0xdd, 0x58, 0x31, 0x80, 0x11, 0x84, 0x23, 0x80, 0x43, 0x84, 0x05, 0xd5, 0x0e, 0x84, 0x23, +0x84, 0x05, 0x4b, 0xe0, 0x0c, 0x01, 0xf7, 0x01, 0x40, 0x53, 0x94, 0x09, 0x95, 0x6d, 0x58, 0x32, +0x80, 0x08, 0x84, 0x05, 0x80, 0x43, 0x84, 0x23, 0xf3, 0x81, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, +0x82, 0xc4, 0x4b, 0xe0, 0x18, 0x01, 0x80, 0x5f, 0x44, 0x10, 0x00, 0x2f, 0x84, 0x00, 0x4b, 0xe0, +0x1c, 0x01, 0xb4, 0x5f, 0x44, 0x0f, 0xff, 0x9f, 0x40, 0x31, 0x00, 0x02, 0x58, 0x51, 0x80, 0x40, +0xb6, 0xbf, 0x80, 0x25, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x44, 0x00, 0x00, 0x2f, +0x4b, 0xe0, 0x18, 0x01, 0x84, 0x20, 0x44, 0x00, 0x00, 0x3a, 0x4b, 0xe0, 0x18, 0x01, 0x80, 0x5f, +0x44, 0x10, 0x00, 0x2f, 0x84, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0xb4, 0x9f, 0x40, 0x22, 0x1c, 0x09, +0x94, 0x97, 0x58, 0x31, 0x00, 0x50, 0xb6, 0x7f, 0x80, 0x23, 0x44, 0x00, 0x00, 0x2f, 0x81, 0x1f, +0x4b, 0xe0, 0x18, 0x01, 0xec, 0x08, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, +0xef, 0xf8, 0x84, 0x80, 0x84, 0x24, 0x40, 0x2f, 0x84, 0x00, 0x97, 0x80, 0x80, 0x04, 0xf4, 0x81, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf0, 0x01, 0x44, 0x3f, 0xff, 0xe7, +0x84, 0x41, 0x40, 0x10, 0x0c, 0x02, 0x4c, 0x61, 0x00, 0x06, 0xc6, 0x09, 0x84, 0xa3, 0xde, 0x07, +0xd5, 0x04, 0x58, 0x10, 0x80, 0x10, 0xd5, 0x03, 0x58, 0x10, 0x80, 0x08, 0x4c, 0x10, 0x00, 0x08, +0x84, 0x04, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0x84, 0x01, 0xec, 0x08, +0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0x46, 0x60, +0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x44, 0x10, 0x00, 0x10, 0x81, 0x20, 0x84, 0x04, 0xdd, 0x26, +0x44, 0x00, 0x00, 0xba, 0x84, 0x21, 0xdd, 0x26, 0x84, 0xe0, 0x80, 0x66, 0x50, 0xaf, 0x80, 0x0c, +0x84, 0xc3, 0x47, 0xc0, 0x00, 0x06, 0x59, 0xce, 0x02, 0xc4, 0xf3, 0x81, 0x80, 0x26, 0x44, 0x00, +0x00, 0xbb, 0xdd, 0x23, 0x44, 0x10, 0x00, 0xbc, 0x84, 0x00, 0x80, 0x4a, 0xdd, 0x3c, 0xf1, 0x03, +0x9d, 0xb4, 0x44, 0x50, 0x00, 0x2f, 0x99, 0xf9, 0x46, 0x80, 0x00, 0x06, 0x58, 0x84, 0x04, 0x44, +0xf3, 0x01, 0xde, 0xec, 0x9e, 0x6c, 0x44, 0x00, 0x00, 0xbb, 0x4b, 0xe0, 0x20, 0x01, 0x80, 0x4a, +0x44, 0x10, 0x00, 0xbc, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, +0xf6, 0x03, 0x84, 0x20, 0x84, 0x04, 0x4b, 0xe0, 0x20, 0x01, 0x44, 0x50, 0x00, 0x37, 0x42, 0x33, +0x14, 0x24, 0x84, 0x96, 0x40, 0x21, 0x90, 0x36, 0x99, 0xfa, 0xe1, 0x27, 0xe8, 0x03, 0x84, 0x00, +0xd5, 0x05, 0x5e, 0x73, 0xff, 0xf6, 0x56, 0x03, 0x80, 0x01, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x2c, 0x46, 0x40, 0x00, 0x0b, 0x58, 0x42, +0x05, 0xf8, 0xf0, 0x81, 0x3a, 0x02, 0x0c, 0x04, 0x50, 0x8f, 0x80, 0x80, 0x84, 0xc0, 0x47, 0xc0, +0x04, 0x11, 0x3a, 0x04, 0x0c, 0x24, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x84, 0x44, 0x80, 0x26, +0x44, 0x00, 0x00, 0xba, 0xb4, 0x64, 0x40, 0x91, 0xc0, 0x09, 0x12, 0x34, 0x00, 0x00, 0x10, 0x9f, +0x80, 0x92, 0xf6, 0xb2, 0x81, 0x5c, 0x05, 0xee, 0x00, 0x01, 0x15, 0xef, 0x80, 0x0f, 0x50, 0x8f, +0x80, 0xcc, 0xdd, 0x27, 0x80, 0x26, 0x44, 0x00, 0x00, 0xbb, 0xdd, 0x27, 0x80, 0x26, 0x44, 0x00, +0x00, 0xbc, 0xdd, 0x27, 0x04, 0x55, 0x00, 0xca, 0x80, 0x26, 0xf5, 0x8e, 0x44, 0x00, 0x00, 0x1b, +0xdd, 0x27, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, 0x82, 0xc4, 0x80, 0x48, 0x44, 0x10, 0x00, 0x41, +0x80, 0x06, 0xdd, 0x29, 0xf4, 0x33, 0x80, 0x48, 0xf4, 0x8d, 0x44, 0x10, 0x00, 0x42, 0x80, 0x06, +0xdd, 0x29, 0xf3, 0x33, 0x44, 0x10, 0x00, 0x8c, 0xf3, 0x8c, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x27, +0x80, 0x48, 0x44, 0x10, 0x00, 0x9f, 0x80, 0x06, 0xdd, 0x29, 0xf2, 0x33, 0x84, 0x23, 0xf2, 0x8b, +0x44, 0x00, 0x00, 0x9e, 0x47, 0xc0, 0x04, 0x10, 0xdd, 0x27, 0x80, 0x48, 0x44, 0x10, 0x00, 0x9f, +0x80, 0x06, 0xdd, 0x29, 0x04, 0xae, 0x01, 0x41, 0x46, 0x90, 0x04, 0x10, 0x14, 0xaf, 0x80, 0x0a, +0x04, 0x84, 0x81, 0x43, 0x46, 0x58, 0x1f, 0xff, 0x58, 0x52, 0x8e, 0x7f, 0x46, 0x30, 0xa0, 0x00, +0x46, 0x00, 0x80, 0x00, 0x40, 0x74, 0x14, 0x02, 0xf4, 0x33, 0x40, 0x13, 0x8c, 0x04, 0x40, 0x23, +0x80, 0x04, 0x14, 0x8f, 0x80, 0x06, 0xf6, 0x83, 0xf7, 0x84, 0xf4, 0x89, 0xf6, 0x85, 0xf6, 0x82, +0xf1, 0x87, 0xf2, 0x88, 0x44, 0x00, 0x00, 0x9f, 0x44, 0x10, 0x00, 0x60, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0x46, 0x50, 0x04, 0x10, 0x04, 0xa2, 0x81, 0x41, 0x47, 0xc0, +0x00, 0xc0, 0x59, 0xce, 0x00, 0x80, 0x40, 0x65, 0x70, 0x04, 0x14, 0x62, 0x81, 0x41, 0xf0, 0x02, +0xc8, 0x13, 0x05, 0xef, 0x80, 0x01, 0x5e, 0xff, 0x01, 0x5f, 0xe9, 0x03, 0xf3, 0x07, 0xd5, 0x1d, +0x04, 0x9f, 0x80, 0x01, 0x5e, 0xf4, 0xff, 0x06, 0xe8, 0x05, 0xf2, 0x04, 0x42, 0x31, 0x68, 0x08, +0xd5, 0x14, 0xf3, 0x08, 0xd5, 0x12, 0xf3, 0x01, 0x5e, 0xf1, 0x81, 0x5f, 0xe9, 0x07, 0xf4, 0x04, +0x46, 0x80, 0xc0, 0x00, 0x40, 0x32, 0x20, 0x04, 0xd5, 0x08, 0xf0, 0x01, 0xf3, 0x08, 0xf7, 0x07, +0x5e, 0x10, 0x7f, 0x06, 0x40, 0x33, 0x84, 0x1a, 0x80, 0x85, 0x46, 0x20, 0x04, 0x11, 0x51, 0xee, +0x7f, 0xa0, 0x14, 0x32, 0x01, 0x43, 0x15, 0xe1, 0x00, 0xca, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, +0x81, 0x84, 0x84, 0x21, 0x50, 0x2f, 0x80, 0xc4, 0x84, 0x05, 0xdd, 0x29, 0x84, 0x21, 0x50, 0x2f, +0x80, 0xc0, 0x84, 0x00, 0xdd, 0x29, 0x84, 0x20, 0x50, 0x2f, 0x80, 0xbc, 0x84, 0x04, 0xdd, 0x29, +0x84, 0x2b, 0x50, 0x2f, 0x80, 0xb8, 0x84, 0x04, 0xdd, 0x29, 0x84, 0x2d, 0x50, 0x2f, 0x80, 0xb4, +0x84, 0x04, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x13, 0x50, 0x2f, 0x80, 0xb0, 0x84, 0x04, 0xdd, 0x29, +0x44, 0x10, 0x00, 0x15, 0x50, 0x2f, 0x80, 0xac, 0x84, 0x04, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x16, +0x50, 0x2f, 0x80, 0xa8, 0x84, 0x04, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x11, 0x50, 0x2f, 0x80, 0xa4, +0x84, 0x05, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x12, 0x50, 0x2f, 0x80, 0xa0, 0x84, 0x05, 0xdd, 0x29, +0x44, 0x10, 0x00, 0x13, 0x50, 0x2f, 0x80, 0x9c, 0x84, 0x05, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x14, +0x50, 0x2f, 0x80, 0x98, 0x84, 0x05, 0xdd, 0x29, 0x84, 0x21, 0x47, 0xc0, 0x00, 0x06, 0x59, 0xce, +0x02, 0x3c, 0x80, 0x41, 0x84, 0x05, 0xdd, 0x3c, 0x84, 0x21, 0x44, 0x20, 0x00, 0xe1, 0x84, 0x00, +0xdd, 0x3c, 0x84, 0x20, 0x44, 0x20, 0x00, 0x83, 0x84, 0x04, 0xdd, 0x3c, 0x84, 0x2b, 0x44, 0x20, +0x00, 0x51, 0x84, 0x04, 0xdd, 0x3c, 0x84, 0x2d, 0x44, 0x20, 0x00, 0x3c, 0x84, 0x04, 0xdd, 0x3c, +0x44, 0x10, 0x00, 0x13, 0x44, 0x20, 0x00, 0x24, 0x84, 0x04, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x15, +0x9e, 0x8b, 0x84, 0x04, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x16, 0x44, 0x20, 0x00, 0xa1, 0x84, 0x04, +0xdd, 0x3c, 0x44, 0x10, 0x00, 0x11, 0x44, 0x20, 0x00, 0x80, 0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, +0x00, 0x12, 0x44, 0x20, 0x00, 0xf1, 0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x13, 0x44, 0x20, +0x00, 0xa1, 0x84, 0x05, 0xdd, 0x3c, 0x84, 0x41, 0x44, 0x10, 0x00, 0x14, 0x84, 0x05, 0xdd, 0x3c, +0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x44, 0x10, 0x00, 0x10, 0x9c, 0x0f, 0xdd, 0x26, +0x84, 0x20, 0x44, 0x00, 0x00, 0x6d, 0xdd, 0x26, 0x46, 0xa0, 0x04, 0x11, 0x84, 0x20, 0x44, 0x00, +0x00, 0x6e, 0xdd, 0x26, 0x84, 0xa8, 0x14, 0x55, 0x00, 0x01, 0x44, 0x10, 0x00, 0x8c, 0x44, 0x00, +0x00, 0x9e, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x40, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x26, 0x84, 0x20, +0x44, 0x00, 0x00, 0x1b, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x39, 0x44, 0x00, 0x00, 0x41, 0xdd, 0x26, +0x44, 0x00, 0x00, 0x9e, 0x44, 0x10, 0x00, 0x8c, 0xdd, 0x26, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, +0x82, 0xc4, 0x84, 0xc0, 0x84, 0x00, 0x44, 0x10, 0x00, 0x8c, 0x50, 0x2f, 0x80, 0xcc, 0x4b, 0xe0, +0x1c, 0x01, 0xf3, 0x33, 0x9d, 0xb1, 0xc3, 0x05, 0x44, 0x80, 0x00, 0x64, 0x4c, 0x64, 0x7f, 0xf4, +0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x84, 0x20, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, +0x84, 0x22, 0x44, 0x00, 0x00, 0xbb, 0xdd, 0x26, 0x84, 0x2a, 0x44, 0x00, 0x00, 0xbc, 0xdd, 0x26, +0x84, 0x23, 0x44, 0x00, 0x00, 0xbb, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x41, 0x44, 0x00, 0x00, 0xbc, +0xdd, 0x26, 0x84, 0x24, 0x44, 0x00, 0x00, 0xf1, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, 0x00, 0xf2, +0xdd, 0x26, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x82, 0xc4, 0x84, 0x00, 0x84, 0x24, 0x50, 0x2f, +0x80, 0xc8, 0x4b, 0xe0, 0x1c, 0x01, 0x81, 0x06, 0x85, 0x25, 0x87, 0x88, 0x85, 0x40, 0x50, 0x7f, +0x80, 0x94, 0x84, 0x20, 0x44, 0x00, 0x00, 0x1b, 0xdd, 0x28, 0x50, 0x5f, 0x80, 0x80, 0x38, 0x12, +0xa4, 0x00, 0x44, 0x00, 0x00, 0x42, 0xdd, 0x28, 0xf1, 0x32, 0x54, 0x00, 0x80, 0x10, 0xc8, 0x05, +0x58, 0x10, 0x80, 0x10, 0x84, 0x04, 0xdd, 0x28, 0x44, 0x10, 0x00, 0x11, 0x44, 0x00, 0x00, 0xf4, +0xdd, 0x28, 0x84, 0x21, 0x44, 0x00, 0x00, 0x15, 0xdd, 0x28, 0x84, 0x20, 0x44, 0x00, 0x00, 0x15, +0xdd, 0x28, 0x84, 0x20, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x28, 0x84, 0x21, 0x44, 0x00, 0x00, 0xbb, +0xdd, 0x28, 0xf1, 0x02, 0xc9, 0x06, 0x44, 0x10, 0x00, 0x80, 0x44, 0x00, 0x00, 0xbc, 0xd5, 0x05, +0x44, 0x00, 0x00, 0xbc, 0x44, 0x10, 0x00, 0x81, 0xdd, 0x28, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x04, +0x58, 0xf7, 0x82, 0xa8, 0xdd, 0x2f, 0x84, 0xc0, 0x50, 0x2f, 0x80, 0xcc, 0x84, 0x00, 0x44, 0x10, +0x00, 0xbc, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf4, 0x33, 0x9d, 0xb1, +0x54, 0x22, 0x00, 0x80, 0xc2, 0x04, 0x44, 0x50, 0x00, 0x64, 0xde, 0xef, 0xf1, 0x32, 0x84, 0x04, +0xdd, 0x28, 0x84, 0x20, 0x44, 0x00, 0x00, 0xf4, 0xdd, 0x28, 0x84, 0x21, 0x44, 0x00, 0x00, 0x15, +0xdd, 0x28, 0x84, 0x20, 0x44, 0x00, 0x00, 0x15, 0xdd, 0x28, 0x84, 0x21, 0x44, 0x00, 0x00, 0xba, +0xdd, 0x28, 0x44, 0x10, 0x00, 0xff, 0x44, 0x00, 0x00, 0xbb, 0xdd, 0x28, 0x44, 0x10, 0x00, 0xbc, +0x84, 0x00, 0x80, 0x47, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf1, 0x25, +0x5c, 0xf0, 0x80, 0xb4, 0xe8, 0x05, 0x8d, 0x21, 0xe5, 0x33, 0xe9, 0x8c, 0xd5, 0x1f, 0x5c, 0xf0, +0x80, 0xf6, 0xe9, 0x05, 0x8f, 0x21, 0x4e, 0x94, 0xff, 0x86, 0xd5, 0x18, 0x84, 0x05, 0x40, 0x25, +0x00, 0xd6, 0x84, 0xa4, 0xde, 0x03, 0x51, 0xce, 0x00, 0x0a, 0x84, 0xa5, 0x4c, 0xa2, 0x80, 0x0f, +0x80, 0x1c, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x8d, 0x58, 0xdd, 0x2f, 0x84, 0xa1, 0xd8, 0x03, +0x85, 0x00, 0xd5, 0x05, 0x8d, 0x41, 0x48, 0xff, 0xff, 0x6e, 0x85, 0x01, 0xf3, 0x32, 0x54, 0x71, +0x80, 0x10, 0xcf, 0x09, 0x58, 0x11, 0x80, 0x10, 0x84, 0x04, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x84, 0x44, 0xdd, 0x2f, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x84, 0x24, 0x44, 0x00, +0x00, 0xba, 0xdd, 0x26, 0x84, 0x24, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x84, 0x2f, 0x44, 0x00, +0x00, 0xbd, 0xdd, 0x26, 0x84, 0x25, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x84, 0x25, 0x44, 0x00, +0x00, 0xba, 0xdd, 0x26, 0x84, 0x2f, 0x44, 0x00, 0x00, 0xbd, 0xdd, 0x26, 0x84, 0x26, 0x44, 0x00, +0x00, 0xba, 0xdd, 0x26, 0x84, 0x26, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x84, 0x2f, 0x44, 0x00, +0x00, 0xbd, 0xdd, 0x26, 0x84, 0x27, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x84, 0x27, 0x44, 0x00, +0x00, 0xba, 0xdd, 0x26, 0x44, 0x00, 0x00, 0xbd, 0x84, 0x2f, 0xdd, 0x26, 0xf2, 0x02, 0x46, 0x70, +0x00, 0x06, 0x58, 0x73, 0x82, 0xc4, 0xca, 0x30, 0x84, 0x22, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, +0x84, 0x22, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0xf0, 0x02, 0x50, 0x2f, 0x80, 0xcc, 0x44, 0x10, +0x00, 0xbd, 0x4b, 0xe0, 0x1c, 0x01, 0xf3, 0x33, 0xf4, 0x01, 0x40, 0x21, 0x98, 0x09, 0x94, 0x96, +0x5e, 0xf2, 0x01, 0x5f, 0xe9, 0x04, 0x58, 0x21, 0x00, 0x14, 0xd5, 0x0b, 0x05, 0xef, 0x80, 0x01, +0x5e, 0xff, 0x7f, 0x06, 0xe8, 0x04, 0x58, 0x21, 0x00, 0x08, 0xd5, 0x03, 0x58, 0x21, 0x00, 0x10, +0xf2, 0xb3, 0x84, 0x22, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x44, 0x00, 0x00, 0xba, +0xdd, 0x26, 0x84, 0x22, 0xd5, 0x2e, 0x84, 0x23, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x84, 0x23, +0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x44, 0x10, 0x00, 0xbd, 0x50, 0x2f, 0x80, 0xcc, 0x84, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0xf5, 0x33, 0xf0, 0x01, 0x40, 0x22, 0x98, 0x09, 0x94, 0x96, 0x5e, 0xf0, +0x01, 0x5f, 0xe9, 0x04, 0x58, 0x21, 0x00, 0x18, 0xd5, 0x0a, 0xf7, 0x01, 0x5e, 0xf3, 0xff, 0x06, +0xe8, 0x04, 0x58, 0x21, 0x00, 0x10, 0xd5, 0x03, 0x58, 0x21, 0x00, 0x14, 0xf2, 0xb3, 0x84, 0x23, +0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x84, 0x23, +0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0xf1, 0x33, 0x44, 0x00, 0x00, 0xbd, 0xdd, 0x26, 0x84, 0xa1, +0x4c, 0x82, 0xc0, 0x27, 0xf4, 0x02, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0xcc, 0x11, +0x84, 0x22, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x84, 0x22, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, +0x44, 0x00, 0x00, 0xbd, 0x84, 0x2f, 0xdd, 0x26, 0x14, 0x8f, 0x80, 0x05, 0x48, 0x00, 0x00, 0x90, +0x84, 0x23, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, 0x84, 0x23, 0x44, 0x00, 0x00, 0xba, 0xdd, 0x26, +0x44, 0x00, 0x00, 0xbd, 0x84, 0x2f, 0xdd, 0x26, 0x14, 0x8f, 0x80, 0x03, 0xd5, 0x03, 0xf3, 0x02, +0xc3, 0x7e, 0xf7, 0x05, 0x84, 0xa1, 0xdf, 0x03, 0xf5, 0x03, 0xd7, 0x79, 0x46, 0xa0, 0x00, 0x0b, +0x58, 0xa5, 0x05, 0xb8, 0x81, 0x0a, 0x3a, 0x04, 0x0c, 0x04, 0x50, 0x9f, 0x80, 0x40, 0x85, 0x40, +0x47, 0xc0, 0x00, 0x06, 0x59, 0xce, 0x04, 0x44, 0x3a, 0x04, 0x8c, 0x24, 0x3a, 0x04, 0x0c, 0x04, +0x3a, 0x04, 0x8c, 0x24, 0x3a, 0x04, 0x0c, 0x04, 0x3a, 0x04, 0x8c, 0x24, 0x3a, 0x04, 0x0c, 0x00, +0x3a, 0x04, 0x8c, 0x20, 0x44, 0x00, 0x00, 0xba, 0x50, 0x15, 0x00, 0x02, 0xdd, 0x3c, 0x50, 0x7f, +0x80, 0x40, 0x84, 0xc3, 0x85, 0x0a, 0x80, 0x26, 0x44, 0x00, 0x00, 0xbb, 0xdd, 0x3c, 0x44, 0x10, +0x00, 0xbc, 0x50, 0x2f, 0x80, 0xcc, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, +0xdd, 0x2f, 0xf0, 0x33, 0x50, 0x00, 0x7f, 0x80, 0x4e, 0x06, 0x00, 0x05, 0x44, 0x10, 0x00, 0x80, +0xd5, 0x08, 0xa6, 0xb8, 0x42, 0x10, 0x08, 0x24, 0x40, 0x40, 0xa0, 0x56, 0x50, 0x12, 0x00, 0x80, +0x44, 0x00, 0x00, 0xbc, 0xdd, 0x3c, 0x9d, 0xb4, 0x44, 0x50, 0x01, 0x03, 0x9d, 0xf9, 0x46, 0x90, +0x00, 0x06, 0x58, 0x94, 0x84, 0x44, 0xde, 0xd8, 0x8d, 0x41, 0x84, 0xa2, 0x4c, 0xa2, 0xff, 0xcc, +0x84, 0x20, 0x44, 0x00, 0x00, 0xba, 0x4b, 0xe0, 0x24, 0x01, 0x44, 0x00, 0x00, 0xbb, 0x84, 0x24, +0x4b, 0xe0, 0x24, 0x01, 0xf6, 0x01, 0x5e, 0xf3, 0x7f, 0x06, 0xe8, 0x05, 0x84, 0x2e, 0x44, 0x00, +0x00, 0xbc, 0xd5, 0x05, 0x44, 0x00, 0x00, 0xbc, 0x44, 0x10, 0x00, 0x1c, 0x4b, 0xe0, 0x24, 0x01, +0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x84, 0x44, 0x84, 0x20, 0x44, 0x00, 0x00, 0xbb, 0x4b, 0xe0, +0x1c, 0x01, 0x44, 0x00, 0x00, 0xbc, 0x9c, 0x44, 0x4b, 0xe0, 0x1c, 0x01, 0xf6, 0x0e, 0x47, 0xe0, +0x04, 0x11, 0x14, 0x6f, 0x00, 0xca, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x84, 0x44, 0xf1, 0x32, +0x84, 0x04, 0xdd, 0x27, 0x84, 0x20, 0x44, 0x00, 0x00, 0x1b, 0xdd, 0x27, 0xf1, 0x0d, 0x44, 0x00, +0x00, 0x41, 0xdd, 0x27, 0xf1, 0x0c, 0x44, 0x00, 0x00, 0x42, 0xdd, 0x27, 0x44, 0x10, 0x00, 0x8c, +0x44, 0x00, 0x00, 0x9e, 0xdd, 0x27, 0xf1, 0x0b, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x27, 0xf2, 0x31, +0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x02, 0x3c, 0x84, 0x21, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x30, +0x84, 0x21, 0x84, 0x00, 0xdd, 0x26, 0xf2, 0x2f, 0x84, 0x20, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x2e, +0x84, 0x2b, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x2d, 0x84, 0x2d, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x2c, +0x44, 0x10, 0x00, 0x13, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x2b, 0x44, 0x10, 0x00, 0x15, 0x84, 0x04, +0xdd, 0x26, 0xf2, 0x2a, 0x44, 0x10, 0x00, 0x16, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x29, 0x44, 0x10, +0x00, 0x11, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x28, 0x44, 0x10, 0x00, 0x12, 0x84, 0x05, 0xdd, 0x26, +0xf2, 0x27, 0x44, 0x10, 0x00, 0x13, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x26, 0x44, 0x10, 0x00, 0x14, +0x84, 0x05, 0xdd, 0x26, 0xf3, 0x0f, 0x46, 0x20, 0x04, 0x11, 0xa8, 0xd1, 0x84, 0x23, 0x44, 0x00, +0x00, 0x9e, 0xdd, 0x27, 0xf1, 0x09, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x27, 0xf4, 0x0a, 0x46, 0x10, +0x04, 0x10, 0x14, 0x40, 0x81, 0x41, 0x80, 0xa1, 0xf0, 0x06, 0x14, 0x02, 0x81, 0x43, 0xf7, 0x02, +0xcf, 0x06, 0x87, 0x81, 0x15, 0xcf, 0x80, 0x02, 0x48, 0xff, 0xfc, 0x66, 0xec, 0xd4, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x8c, 0x96, 0x00, 0x96, 0x48, 0x96, 0xd0, +0xb6, 0x1f, 0xf1, 0x83, 0x4e, 0x33, 0x05, 0x91, 0xc8, 0x09, 0x46, 0x40, 0x00, 0x0e, 0x58, 0x42, +0x03, 0x2d, 0xa6, 0xa0, 0x84, 0x01, 0x4c, 0x20, 0x05, 0x63, 0x84, 0x24, 0x50, 0x2f, 0x80, 0x40, +0x84, 0x00, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x01, 0x84, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x82, 0xc4, 0xdd, 0x2f, 0x84, 0x23, 0x50, 0x2f, 0x80, 0x64, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x24, +0x50, 0x2f, 0x80, 0x60, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x05, 0x80, 0x20, 0x50, 0x2f, 0x80, 0x5c, +0xdd, 0x26, 0x84, 0x20, 0x50, 0x2f, 0x80, 0x58, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x26, 0x50, 0x2f, +0x80, 0x54, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x05, 0x84, 0x27, 0x50, 0x2f, 0x80, 0x50, 0xdd, 0x26, +0x81, 0x26, 0x44, 0x80, 0x00, 0x25, 0x50, 0x6f, 0x80, 0x18, 0x80, 0x28, 0x80, 0x46, 0x84, 0x05, +0xdd, 0x29, 0x8d, 0x01, 0x44, 0x50, 0x00, 0x2f, 0x9d, 0xb4, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, +0x81, 0x84, 0x4c, 0x82, 0xff, 0xf4, 0x44, 0x10, 0x00, 0x3a, 0x50, 0x2f, 0x80, 0x48, 0x84, 0x05, +0xdd, 0x27, 0x44, 0x10, 0x00, 0x3b, 0x50, 0x2f, 0x80, 0x44, 0x84, 0x05, 0xdd, 0x27, 0x50, 0x9f, +0x80, 0x6c, 0x44, 0x10, 0x00, 0x17, 0x50, 0x2f, 0x80, 0x4c, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0x84, 0x20, 0x80, 0x49, 0x84, 0x05, 0xdd, 0x27, 0x05, 0xcf, +0x80, 0x1b, 0x46, 0x80, 0x00, 0x06, 0x58, 0x84, 0x02, 0x3c, 0x58, 0x2e, 0x00, 0x03, 0x84, 0x20, +0x84, 0x05, 0x4b, 0xe0, 0x20, 0x01, 0x84, 0x21, 0x80, 0x49, 0x84, 0x05, 0xdd, 0x27, 0x04, 0xaf, +0x80, 0x1b, 0x84, 0x05, 0x58, 0x25, 0x00, 0x01, 0x84, 0x21, 0x4b, 0xe0, 0x20, 0x01, 0x84, 0xc0, +0x81, 0x09, 0x84, 0x00, 0xd5, 0x0b, 0x92, 0x00, 0x87, 0xc7, 0x9c, 0x49, 0x4c, 0x1f, 0x7f, 0xfd, +0x9c, 0x01, 0x44, 0x30, 0x00, 0x64, 0x4c, 0x01, 0x80, 0x04, 0x84, 0x20, 0xd5, 0xf5, 0x84, 0x21, +0x84, 0x05, 0x80, 0x48, 0xdd, 0x27, 0xf0, 0x1b, 0x9d, 0xb1, 0x96, 0x04, 0x44, 0x10, 0x00, 0x28, +0xf0, 0x9b, 0x4c, 0x60, 0x80, 0x03, 0xc8, 0xe6, 0x51, 0xef, 0x80, 0x6c, 0x80, 0x5e, 0x84, 0x20, +0x84, 0x05, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0x84, 0xdd, 0x2f, 0xf0, 0x1b, 0x84, 0x5c, +0x40, 0x60, 0x08, 0x02, 0x58, 0x23, 0x00, 0x01, 0x84, 0x20, 0x50, 0x7f, 0x80, 0x68, 0x84, 0x05, +0xf6, 0x9b, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0x3c, 0xdd, 0x2f, 0x80, 0x47, 0x44, 0x10, +0x00, 0x17, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf3, 0x1a, +0x44, 0x1f, 0xff, 0xe0, 0x40, 0x91, 0x84, 0x02, 0x58, 0x14, 0x80, 0x10, 0x44, 0x00, 0x00, 0x17, +0x14, 0x9f, 0x80, 0x1a, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0xb4, 0xdf, +0x44, 0x50, 0x00, 0x27, 0x84, 0x89, 0x44, 0xa0, 0x00, 0x31, 0x87, 0x82, 0x40, 0x22, 0x18, 0x1b, +0x40, 0x22, 0x98, 0x1a, 0x40, 0x8e, 0x18, 0x1b, 0x40, 0x85, 0x18, 0x1a, 0x85, 0x20, 0xf2, 0x85, +0xb5, 0x5f, 0x14, 0x8f, 0x80, 0x04, 0x83, 0x89, 0x81, 0x09, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, +0x81, 0x84, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x02, 0x3c, 0x4e, 0x93, 0x00, 0x57, 0x84, 0x28, +0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, 0x4b, 0xe0, 0x1c, 0x01, 0xf3, 0x1b, 0x84, 0x28, 0x54, 0x21, +0x80, 0xfb, 0x84, 0x05, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x10, 0x00, 0x15, 0x50, 0x2f, 0x80, 0x68, +0x80, 0x09, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf4, 0x1a, 0x44, 0x00, +0x00, 0x15, 0x58, 0x12, 0x00, 0x01, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, +0xf5, 0x05, 0x80, 0x29, 0xf5, 0x82, 0xd5, 0x0a, 0x92, 0x00, 0x84, 0xe7, 0x9c, 0x01, 0x4c, 0x03, +0xff, 0xfd, 0x9c, 0x49, 0x84, 0xca, 0x4c, 0x13, 0x00, 0x04, 0x84, 0x00, 0xd5, 0xf6, 0x84, 0x24, +0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, +0xf1, 0x1a, 0x84, 0x04, 0x54, 0x10, 0x80, 0xe7, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, +0xdd, 0x2f, 0x84, 0x20, 0xd5, 0x0a, 0x92, 0x00, 0x84, 0x47, 0x9c, 0x01, 0x4c, 0x01, 0x7f, 0xfd, +0x9c, 0x49, 0x84, 0x0a, 0x4c, 0x10, 0x00, 0x04, 0x84, 0x00, 0xd5, 0xf6, 0x44, 0x10, 0x00, 0x15, +0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, 0xd5, 0x58, 0x84, 0x28, 0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, +0x4b, 0xe0, 0x1c, 0x01, 0xf3, 0x1b, 0x84, 0x28, 0x58, 0x21, 0x80, 0x04, 0x84, 0x05, 0x4b, 0xe0, +0x18, 0x01, 0x44, 0x10, 0x00, 0x15, 0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf4, 0x1a, 0x44, 0x00, 0x00, 0x15, 0x58, 0x12, 0x00, 0x01, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0xf5, 0x04, 0x84, 0x20, 0xf5, 0x82, +0xd5, 0x0a, 0x92, 0x00, 0x87, 0xc7, 0x9c, 0x01, 0x4c, 0x0f, 0x7f, 0xfd, 0x9c, 0x49, 0x84, 0xea, +0x4c, 0x13, 0x80, 0x04, 0x84, 0x00, 0xd5, 0xf6, 0x84, 0x24, 0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf1, 0x1a, 0x84, 0x04, 0x54, 0x60, +0x80, 0xe7, 0x58, 0x13, 0x00, 0x10, 0xf6, 0x9a, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, +0xdd, 0x2f, 0x84, 0x20, 0xd5, 0x0a, 0x92, 0x00, 0x84, 0x47, 0x9c, 0x01, 0x4c, 0x01, 0x7f, 0xfd, +0x9c, 0x49, 0x84, 0x0a, 0x4c, 0x10, 0x00, 0x04, 0x84, 0x00, 0xd5, 0xf6, 0x44, 0x10, 0x00, 0x15, +0x84, 0x00, 0x50, 0x2f, 0x80, 0x68, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, +0xf5, 0x1a, 0x44, 0x00, 0x00, 0x15, 0x54, 0x12, 0x80, 0xfe, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x84, 0x44, 0xdd, 0x2f, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x81, 0x84, 0x46, 0x60, 0x00, 0x06, +0x58, 0x63, 0x02, 0x3c, 0x4e, 0xa2, 0x00, 0x7a, 0x46, 0x40, 0x04, 0x10, 0x47, 0xe0, 0x04, 0x10, +0x59, 0xef, 0x05, 0x04, 0x58, 0x42, 0x05, 0x0c, 0x44, 0x30, 0x00, 0x10, 0x44, 0x10, 0x00, 0x18, +0xb6, 0x64, 0xb6, 0x3e, 0x50, 0x2f, 0x80, 0x6c, 0x44, 0x10, 0x00, 0x11, 0x84, 0x05, 0xdd, 0x27, +0x05, 0xcf, 0x80, 0x1b, 0x44, 0x10, 0x00, 0x11, 0x58, 0x2e, 0x00, 0x80, 0x84, 0x05, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x12, 0x44, 0x20, 0x00, 0xc1, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x13, +0x44, 0x20, 0x00, 0x20, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x14, 0x84, 0x42, 0x84, 0x05, +0xdd, 0x26, 0x84, 0x23, 0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, 0xdd, 0x27, 0xf2, 0x1b, 0x44, 0x0f, +0xff, 0xc0, 0x40, 0x51, 0x00, 0x02, 0xf5, 0x9b, 0x58, 0x22, 0x80, 0x3f, 0x84, 0x23, 0x84, 0x05, +0xdd, 0x26, 0x84, 0x24, 0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, 0xdd, 0x27, 0xf3, 0x1b, 0x44, 0x4f, +0xff, 0xc0, 0x41, 0xc1, 0x90, 0x02, 0x15, 0xcf, 0x80, 0x1b, 0x58, 0x2e, 0x00, 0x3f, 0x84, 0x24, +0x84, 0x05, 0xdd, 0x26, 0x84, 0x05, 0x80, 0x20, 0x44, 0x20, 0x00, 0x31, 0xdd, 0x26, 0x44, 0x10, +0x00, 0x3a, 0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, 0xdd, 0x27, 0xf2, 0x1b, 0x44, 0x0f, 0xff, 0x80, +0x40, 0x51, 0x00, 0x02, 0xf5, 0x9b, 0x80, 0x45, 0x44, 0x10, 0x00, 0x3a, 0x84, 0x05, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x3b, 0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, 0xdd, 0x27, 0xf4, 0x1b, 0x44, 0x3f, +0xff, 0x80, 0x41, 0xc2, 0x0c, 0x02, 0x15, 0xcf, 0x80, 0x1b, 0x80, 0x5c, 0x84, 0x05, 0x44, 0x10, +0x00, 0x3b, 0xdd, 0x26, 0x87, 0x80, 0xd5, 0x6c, 0x46, 0x10, 0x04, 0x10, 0x47, 0xe0, 0x04, 0x10, +0x59, 0xef, 0x05, 0x04, 0x84, 0xa8, 0x44, 0x80, 0x00, 0x18, 0x58, 0x10, 0x85, 0x0c, 0xb6, 0xa1, +0xb7, 0x1e, 0x44, 0x10, 0x00, 0x11, 0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, 0xdd, 0x27, 0xf3, 0x1b, +0x44, 0x10, 0x00, 0x11, 0x58, 0x21, 0x80, 0x80, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x12, +0x44, 0x20, 0x00, 0xf1, 0x84, 0x05, 0xdd, 0x26, 0x80, 0x48, 0x44, 0x10, 0x00, 0x13, 0x84, 0x05, +0xdd, 0x26, 0x44, 0x10, 0x00, 0x14, 0x44, 0x20, 0x00, 0xc2, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x23, +0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, 0xdd, 0x27, 0xf2, 0x1b, 0x44, 0x0f, 0xff, 0xc0, 0x40, 0x41, +0x00, 0x02, 0xf4, 0x9b, 0x58, 0x22, 0x00, 0x34, 0x84, 0x23, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x24, +0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, 0xdd, 0x27, 0xf5, 0x1b, 0x44, 0x8f, 0xff, 0xc0, 0x40, 0x32, +0xa0, 0x02, 0xf3, 0x9b, 0x58, 0x21, 0x80, 0x34, 0x84, 0x24, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x26, +0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, 0xdd, 0x27, 0xf2, 0x1b, 0x44, 0x0f, 0xff, 0x80, 0x40, 0x41, +0x00, 0x02, 0xf4, 0x9b, 0x80, 0x44, 0x84, 0x26, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x27, 0x50, 0x2f, +0x80, 0x6c, 0x84, 0x05, 0xdd, 0x27, 0xf7, 0x1b, 0x44, 0x5f, 0xff, 0x80, 0x40, 0x83, 0x94, 0x02, +0x14, 0x8f, 0x80, 0x1b, 0x80, 0x48, 0x84, 0x05, 0x84, 0x27, 0xdd, 0x26, 0x81, 0x0a, 0x84, 0x20, +0xd5, 0x0a, 0x92, 0x00, 0x84, 0xc7, 0x9c, 0x01, 0x4c, 0x03, 0x7f, 0xfd, 0x9c, 0x49, 0x84, 0xea, +0x4c, 0x13, 0x80, 0x04, 0x84, 0x00, 0xd5, 0xf6, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x04, 0x44, +0x84, 0x22, 0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, +0x82, 0xc4, 0x50, 0x2f, 0x80, 0x68, 0x44, 0x10, 0x00, 0x9f, 0x84, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0xf3, 0x1a, 0x84, 0x59, 0x40, 0x11, 0x88, 0x02, 0x44, 0x00, 0x00, 0x9f, 0x4b, 0xe0, 0x18, 0x01, +0x44, 0x10, 0x00, 0x15, 0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0xf4, 0x1a, +0x44, 0x00, 0x00, 0x15, 0x58, 0x12, 0x00, 0x01, 0x4b, 0xe0, 0x18, 0x01, 0x84, 0x20, 0xd5, 0x0a, +0x92, 0x00, 0x87, 0xc7, 0x9c, 0x01, 0x4c, 0x0f, 0x7f, 0xfd, 0x9c, 0x49, 0x84, 0x0a, 0x4c, 0x10, +0x00, 0x04, 0x84, 0x00, 0xd5, 0xf6, 0x44, 0x10, 0x00, 0x15, 0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf1, 0x1a, 0x44, 0x00, 0x00, 0x15, +0x54, 0x10, 0x80, 0xfe, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0x84, 0x20, +0xd5, 0x09, 0x92, 0x00, 0x84, 0xa7, 0x9c, 0x01, 0xd8, 0xfd, 0x9c, 0x49, 0x84, 0xca, 0x4c, 0x13, +0x00, 0x04, 0x84, 0x00, 0xd5, 0xf7, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x84, 0x44, 0x84, 0x20, +0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0x9f, 0x44, 0x10, 0x00, 0x82, +0x4b, 0xe0, 0x1c, 0x01, 0x84, 0xc0, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x82, 0xc4, 0x84, 0x20, +0xd5, 0x0b, 0x92, 0x00, 0x84, 0x87, 0x9c, 0x01, 0x4c, 0x02, 0x7f, 0xfd, 0x9c, 0x49, 0x44, 0x30, +0x00, 0x64, 0x4c, 0x11, 0x80, 0x04, 0x84, 0x00, 0xd5, 0xf5, 0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, +0x44, 0x10, 0x00, 0x9f, 0x4b, 0xe0, 0x1c, 0x01, 0xf2, 0x1a, 0x84, 0x02, 0x4c, 0x20, 0x00, 0x08, +0x45, 0xe0, 0x00, 0x14, 0x4c, 0x6f, 0x00, 0x04, 0x9d, 0xb1, 0xd5, 0xe2, 0x44, 0x10, 0x00, 0x39, +0x44, 0x00, 0x00, 0x9e, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0x44, 0x10, +0x00, 0x9f, 0x84, 0x00, 0x50, 0x2f, 0x80, 0x68, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, +0xdd, 0x2f, 0x00, 0x1f, 0x80, 0x68, 0x54, 0x10, 0x80, 0x7f, 0xf1, 0x81, 0x5e, 0xf0, 0x80, 0x40, +0xe9, 0x06, 0x44, 0x6f, 0xff, 0x80, 0x40, 0x50, 0x98, 0x04, 0xf5, 0x81, 0x46, 0x70, 0x00, 0x06, +0x58, 0x73, 0x84, 0x44, 0x84, 0x22, 0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x30, +0x00, 0x06, 0x58, 0x31, 0x82, 0xc4, 0x44, 0x10, 0x00, 0x9f, 0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, +0x4b, 0xe0, 0x0c, 0x01, 0xf4, 0x1a, 0x44, 0x00, 0x00, 0x9f, 0x58, 0x12, 0x00, 0x06, 0x4b, 0xe0, +0x1c, 0x01, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x82, 0x3c, 0x4e, 0xa2, 0x00, 0x2a, 0x50, 0x2f, +0x80, 0x6c, 0x44, 0x10, 0x00, 0x3a, 0x84, 0x05, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0x84, +0xdd, 0x2f, 0xf0, 0x1b, 0x44, 0x10, 0x00, 0x3a, 0x54, 0x50, 0x00, 0x80, 0xf5, 0x9b, 0x40, 0x2e, +0x14, 0x00, 0x84, 0x05, 0x4b, 0xe0, 0x1c, 0x01, 0x50, 0x2f, 0x80, 0x6c, 0x44, 0x10, 0x00, 0x3b, +0x84, 0x05, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0x84, 0xdd, 0x2f, 0xf2, 0x1b, 0x44, 0x10, +0x00, 0x3b, 0x54, 0x31, 0x00, 0x80, 0x40, 0x2e, 0x0c, 0x00, 0x84, 0x00, 0xd5, 0x24, 0x84, 0x26, +0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0x84, 0xdd, 0x2f, +0xf4, 0x1b, 0x84, 0x26, 0x54, 0x62, 0x00, 0x80, 0xf6, 0x9b, 0x40, 0x24, 0x18, 0x00, 0x84, 0x05, +0x4b, 0xe0, 0x1c, 0x01, 0x84, 0x27, 0x50, 0x2f, 0x80, 0x6c, 0x84, 0x05, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x81, 0x84, 0xdd, 0x2f, 0xf1, 0x1b, 0x84, 0x05, 0x54, 0x30, 0x80, 0x80, 0x40, 0x24, +0x0c, 0x00, 0x84, 0x27, 0xf3, 0x9b, 0x4b, 0xe0, 0x1c, 0x01, 0x84, 0x20, 0xd5, 0x0a, 0x92, 0x00, +0x87, 0xc7, 0x9c, 0x01, 0x4c, 0x0f, 0x7f, 0xfd, 0x9c, 0x49, 0x84, 0x6a, 0x4c, 0x11, 0x80, 0x04, +0x84, 0x00, 0xd5, 0xf6, 0x44, 0x10, 0x00, 0x15, 0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf2, 0x1a, 0x44, 0x00, 0x00, 0x15, 0x58, 0x11, +0x00, 0x01, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0x84, 0x20, 0xd5, 0x09, +0x92, 0x00, 0x84, 0xa7, 0x9c, 0x01, 0xd8, 0xfd, 0x9c, 0x49, 0x84, 0x0a, 0x4c, 0x10, 0x00, 0x04, +0x84, 0x00, 0xd5, 0xf7, 0x44, 0x10, 0x00, 0x15, 0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf1, 0x1a, 0x44, 0x00, 0x00, 0x15, 0x54, 0x10, +0x80, 0xfe, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0x84, 0x20, 0xd5, 0x0a, +0x92, 0x00, 0x84, 0xc7, 0x9c, 0x01, 0x4c, 0x03, 0x7f, 0xfd, 0x9c, 0x49, 0x84, 0x8a, 0x4c, 0x12, +0x00, 0x04, 0x84, 0x00, 0xd5, 0xf6, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x84, 0x20, +0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x00, 0x00, 0x9f, 0x44, 0x10, 0x00, 0x82, +0x4b, 0xe0, 0x18, 0x01, 0x84, 0xc0, 0x84, 0x20, 0xd5, 0x0b, 0x92, 0x00, 0x87, 0xc7, 0x9c, 0x01, +0x4c, 0x0f, 0x7f, 0xfd, 0x9c, 0x49, 0x44, 0x30, 0x00, 0x64, 0x4c, 0x11, 0x80, 0x04, 0x84, 0x00, +0xd5, 0xf5, 0x50, 0x2f, 0x80, 0x68, 0x84, 0x00, 0x44, 0x10, 0x00, 0x9f, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf2, 0x1a, 0x84, 0xa2, 0xd2, 0x07, 0x44, 0x00, 0x00, 0x14, +0x4c, 0x60, 0x00, 0x04, 0x9d, 0xb1, 0xd5, 0xe0, 0x44, 0x10, 0x00, 0x39, 0x44, 0x00, 0x00, 0x9e, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0x44, 0x10, 0x00, 0x9f, 0x84, 0x00, +0x50, 0x2f, 0x80, 0x68, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0x00, 0x1f, +0x80, 0x68, 0x54, 0x10, 0x80, 0x7f, 0x5e, 0xf0, 0x80, 0x40, 0xe9, 0x05, 0x44, 0x4f, 0xff, 0x80, +0x40, 0x10, 0x90, 0x04, 0x05, 0xef, 0x80, 0x01, 0xf6, 0x02, 0x40, 0x1f, 0x04, 0x01, 0x40, 0x2e, +0x28, 0x1b, 0x40, 0x24, 0x28, 0x1a, 0xe0, 0xc1, 0xe8, 0x22, 0xca, 0x2d, 0x4e, 0x93, 0x00, 0x12, +0x4e, 0xa2, 0x00, 0x09, 0x46, 0x70, 0x00, 0x0e, 0x58, 0x73, 0x84, 0x6d, 0x10, 0x93, 0x80, 0x00, +0xd5, 0x4e, 0x46, 0x90, 0x00, 0x0e, 0x58, 0x94, 0x84, 0x6c, 0x10, 0xa4, 0x80, 0x00, 0xd5, 0x47, +0x4e, 0xa2, 0x00, 0x07, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x84, 0x6f, 0xd5, 0x4a, 0x46, 0x30, +0x00, 0x0e, 0x58, 0x31, 0x84, 0x6e, 0x10, 0xa1, 0x80, 0x00, 0xd5, 0x4b, 0x5e, 0xf1, 0x00, 0x3f, +0xe8, 0x0a, 0x4e, 0xa2, 0x00, 0x06, 0x51, 0xce, 0x00, 0x01, 0x48, 0xff, 0xfe, 0xe0, 0x8d, 0x01, +0x48, 0xff, 0xfe, 0xdd, 0xf5, 0x02, 0xe0, 0x25, 0xe8, 0x19, 0x44, 0x00, 0x00, 0x3f, 0x4c, 0x20, +0x40, 0x16, 0x4e, 0x93, 0x00, 0x0b, 0x4e, 0xa2, 0x00, 0x1d, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, +0x84, 0x6d, 0x11, 0xc0, 0x80, 0x00, 0xd5, 0x1b, 0x4e, 0xa2, 0x00, 0x26, 0x46, 0x40, 0x00, 0x0e, +0x58, 0x42, 0x04, 0x6f, 0x11, 0xc2, 0x00, 0x00, 0xd5, 0x24, 0x4e, 0x93, 0x00, 0x14, 0x4e, 0xa2, +0x00, 0x09, 0x47, 0xe0, 0x00, 0x0e, 0x59, 0xef, 0x04, 0x6d, 0x11, 0xcf, 0x00, 0x00, 0xd5, 0x07, +0x46, 0x90, 0x00, 0x0e, 0x58, 0x94, 0x84, 0x6c, 0x10, 0x84, 0x80, 0x00, 0x85, 0x21, 0x48, 0xff, +0xfc, 0x26, 0x4e, 0xa2, 0x00, 0x09, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x84, 0x6f, 0x80, 0x5c, +0xae, 0x88, 0xd5, 0x07, 0x46, 0x30, 0x00, 0x0e, 0x58, 0x31, 0x84, 0x6e, 0x10, 0x81, 0x80, 0x00, +0x8d, 0x21, 0x84, 0xa2, 0x4c, 0x92, 0xfc, 0x13, 0x46, 0x20, 0x04, 0x10, 0x46, 0x10, 0x04, 0x10, +0x85, 0x00, 0x58, 0x21, 0x05, 0x04, 0x58, 0x10, 0x85, 0x0c, 0xb7, 0x02, 0xb7, 0x01, 0x50, 0x2f, +0x80, 0x6c, 0x44, 0x10, 0x00, 0x11, 0x84, 0x05, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x81, 0x84, +0xdd, 0x2f, 0xf0, 0x1b, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x02, 0x3c, 0x54, 0x20, 0x00, 0x7f, +0x44, 0x10, 0x00, 0x11, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x12, 0x80, 0x48, 0x84, 0x05, +0xdd, 0x26, 0x44, 0x10, 0x00, 0x13, 0x80, 0x48, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x14, +0x80, 0x48, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x19, 0x84, 0x23, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x18, +0x84, 0x24, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x05, 0xf2, 0x17, 0x80, 0x20, 0xdd, 0x26, 0xf2, 0x16, +0x80, 0x28, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x15, 0x84, 0x26, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x14, +0x84, 0x05, 0x84, 0x27, 0xdd, 0x26, 0x50, 0x9f, 0x80, 0x18, 0x44, 0x70, 0x00, 0x25, 0x0c, 0x24, +0x80, 0x01, 0x80, 0x27, 0x84, 0x05, 0xdd, 0x26, 0x9d, 0xf9, 0x44, 0x40, 0x00, 0x2f, 0x46, 0x80, +0x00, 0x06, 0x58, 0x84, 0x02, 0x3c, 0x4c, 0x72, 0x7f, 0xf4, 0xf2, 0x12, 0x44, 0x10, 0x00, 0x3a, +0x84, 0x05, 0x4b, 0xe0, 0x20, 0x01, 0xf2, 0x11, 0x44, 0x10, 0x00, 0x3b, 0x84, 0x05, 0x4b, 0xe0, +0x20, 0x01, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, 0x84, 0x44, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9e, +0xdd, 0x29, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x29, 0x50, 0x8f, 0x80, 0x68, 0x84, 0x22, +0x44, 0x00, 0x00, 0x9e, 0xdd, 0x29, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x02, 0xc4, 0x80, 0x48, +0x44, 0x10, 0x00, 0x9f, 0x84, 0x00, 0x4b, 0xe0, 0x18, 0x01, 0xf3, 0x1a, 0x44, 0x00, 0x00, 0x9f, +0x54, 0x11, 0x80, 0xf9, 0xdd, 0x29, 0x80, 0x48, 0x84, 0x24, 0x84, 0x00, 0x4b, 0xe0, 0x18, 0x01, +0xf7, 0x1a, 0x84, 0x04, 0x54, 0x13, 0x80, 0xf3, 0xdd, 0x29, 0xf1, 0x13, 0x44, 0x00, 0x00, 0x17, +0xdd, 0x29, 0xf1, 0x10, 0x84, 0x04, 0xdd, 0x29, 0xb4, 0xdf, 0xce, 0x26, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x03, 0x2d, 0x01, 0xe0, 0x00, 0x00, 0x84, 0xa1, 0x4d, 0xe2, 0xc0, 0x1e, 0x46, 0x10, +0x00, 0x0e, 0x58, 0x10, 0x84, 0x6d, 0xa6, 0x08, 0x46, 0x30, 0x00, 0x0e, 0x58, 0x31, 0x84, 0x6c, +0x5c, 0xf0, 0x00, 0xf6, 0xe8, 0x02, 0x8c, 0x0a, 0x46, 0x20, 0x00, 0x0e, 0x58, 0x21, 0x04, 0x6f, +0xae, 0x18, 0xa6, 0x10, 0x46, 0x30, 0x00, 0x0e, 0x58, 0x31, 0x84, 0x6e, 0x5c, 0xf0, 0x00, 0xf2, +0xe8, 0x02, 0x8c, 0x0e, 0xae, 0x18, 0xf4, 0x03, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x81, 0x84, +0x50, 0x8f, 0x80, 0x6c, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x02, 0x3c, 0xcc, 0x4b, 0x80, 0x48, +0x84, 0x26, 0x84, 0x05, 0xdd, 0x27, 0xf1, 0x1b, 0x46, 0x90, 0x00, 0x0e, 0x58, 0x94, 0x84, 0x6c, +0x54, 0x40, 0x80, 0xc0, 0x00, 0x04, 0x80, 0x00, 0xf4, 0x9b, 0x98, 0x84, 0x84, 0x26, 0x84, 0x05, +0xdd, 0x26, 0x80, 0x48, 0x84, 0x27, 0x84, 0x05, 0xdd, 0x27, 0xf3, 0x1b, 0x00, 0x54, 0x80, 0x00, +0x54, 0x91, 0x80, 0xc0, 0x14, 0x9f, 0x80, 0x1b, 0x40, 0x22, 0xa4, 0x00, 0x84, 0x27, 0x84, 0x05, +0xdd, 0x26, 0x80, 0x48, 0x44, 0x10, 0x00, 0x3a, 0x84, 0x05, 0xdd, 0x27, 0xf2, 0x1b, 0x46, 0x90, +0x00, 0x0e, 0x58, 0x94, 0x84, 0x6d, 0x54, 0x41, 0x00, 0xc0, 0x00, 0x14, 0x80, 0x00, 0xf4, 0x9b, +0x98, 0x8c, 0x84, 0x05, 0x44, 0x10, 0x00, 0x3a, 0xdd, 0x26, 0x80, 0x48, 0x44, 0x10, 0x00, 0x3b, +0x84, 0x05, 0xdd, 0x27, 0xf0, 0x1b, 0x00, 0x54, 0x80, 0x00, 0x54, 0x30, 0x00, 0xc0, 0xf3, 0x9b, +0x98, 0xab, 0x44, 0x10, 0x00, 0x3b, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x03, 0x84, 0x28, 0x84, 0x05, +0xd5, 0x4a, 0x84, 0x26, 0x80, 0x48, 0x84, 0x05, 0xdd, 0x27, 0xf0, 0x1b, 0x46, 0x90, 0x00, 0x0e, +0x58, 0x94, 0x84, 0x6e, 0x54, 0x30, 0x00, 0xc0, 0x00, 0x44, 0x80, 0x00, 0xf3, 0x9b, 0x98, 0xa3, +0x84, 0x26, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x27, 0x80, 0x48, 0x84, 0x05, 0xdd, 0x27, 0xf2, 0x1b, +0x00, 0x54, 0x80, 0x00, 0x54, 0x91, 0x00, 0xc0, 0x14, 0x9f, 0x80, 0x1b, 0x40, 0x22, 0xa4, 0x00, +0x84, 0x27, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x3a, 0x80, 0x48, 0x84, 0x05, 0xdd, 0x27, +0xf1, 0x1b, 0x46, 0x90, 0x00, 0x0e, 0x58, 0x94, 0x84, 0x6f, 0x54, 0x40, 0x80, 0xc0, 0x00, 0x04, +0x80, 0x00, 0xf4, 0x9b, 0x98, 0x84, 0x44, 0x10, 0x00, 0x3a, 0x84, 0x05, 0xdd, 0x26, 0x80, 0x48, +0x44, 0x10, 0x00, 0x3b, 0x84, 0x05, 0xdd, 0x27, 0xf3, 0x1b, 0x00, 0x24, 0x80, 0x00, 0x54, 0x51, +0x80, 0xc0, 0xf5, 0x9b, 0x98, 0x95, 0x44, 0x10, 0x00, 0x3b, 0x84, 0x05, 0xdd, 0x26, 0x84, 0x05, +0x84, 0x28, 0x84, 0x44, 0xdd, 0x26, 0xec, 0x74, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x84, 0x40, 0xf2, 0x81, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x97, +0x84, 0x78, 0x54, 0x80, 0x00, 0xff, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, 0x05, 0x70, 0x46, 0x70, +0x00, 0x06, 0x58, 0x73, 0x82, 0x3c, 0xa7, 0x70, 0x4c, 0x54, 0x40, 0x16, 0xa6, 0xb1, 0x44, 0x10, +0x00, 0x11, 0x84, 0x00, 0xdd, 0x27, 0xa6, 0xb2, 0x44, 0x10, 0x00, 0x12, 0x84, 0x00, 0xdd, 0x27, +0xa6, 0xb3, 0x44, 0x10, 0x00, 0x13, 0x84, 0x00, 0xdd, 0x27, 0xa6, 0xb4, 0x84, 0x00, 0x44, 0x10, +0x00, 0x14, 0xdd, 0x27, 0x9d, 0xb5, 0x46, 0x50, 0x00, 0x0b, 0x58, 0x52, 0x85, 0xb6, 0xde, 0xe4, +0x46, 0x50, 0x04, 0x11, 0x05, 0xe2, 0x80, 0xec, 0x44, 0x1f, 0xc0, 0xc0, 0x54, 0x74, 0x80, 0x3f, +0x40, 0x6f, 0x04, 0x02, 0x40, 0x43, 0x98, 0x04, 0x14, 0x42, 0x80, 0xec, 0xe7, 0x0f, 0xe8, 0x1a, +0x46, 0xf0, 0x00, 0x0e, 0x04, 0x27, 0x81, 0x1f, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x04, 0x44, +0x52, 0x71, 0x00, 0x37, 0x80, 0x27, 0x44, 0x00, 0x00, 0x3e, 0x4b, 0xe0, 0x18, 0x01, 0x80, 0x27, +0x44, 0x00, 0x00, 0x3f, 0x4b, 0xe0, 0x18, 0x01, 0x80, 0x27, 0x44, 0x00, 0x00, 0x40, 0x4b, 0xe0, +0x18, 0x01, 0x84, 0x24, 0x40, 0x2f, 0x84, 0x00, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x81, 0x84, 0xdd, 0x2f, 0xf1, 0x01, 0x84, 0x00, 0x58, 0x50, 0x80, 0x80, 0x80, 0x45, 0x84, 0x24, +0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x04, 0x70, 0xf5, 0x81, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x82, 0x3c, 0xdd, 0x2f, 0xa7, 0x32, 0x40, 0x32, 0x04, 0x09, 0x54, 0x71, 0x80, 0x07, 0x80, 0x07, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x8c, 0xfc, 0xdd, 0x2f, 0xc7, 0x06, 0x84, 0xa1, 0x4c, 0x72, +0xc1, 0x3a, 0x48, 0x00, 0x00, 0x86, 0x00, 0x83, 0x00, 0x01, 0x84, 0xa4, 0x54, 0x84, 0x00, 0x0e, +0x4c, 0x82, 0xc0, 0x07, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0xd5, 0x4a, 0x84, 0xa2, +0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x4c, 0x82, 0xc0, 0x44, 0x44, 0x10, 0x00, 0x12, +0x44, 0x00, 0x00, 0x45, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x5e, 0x44, 0x00, 0x00, 0x4b, 0xdd, 0x26, +0x84, 0x27, 0x44, 0x00, 0x00, 0x5b, 0xdd, 0x26, 0x80, 0x28, 0x44, 0x00, 0x00, 0x5c, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x23, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x17, 0x44, 0x00, +0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x24, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x84, 0x26, +0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x81, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x12, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x83, 0x44, 0x00, +0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x17, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, +0x00, 0x88, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x5e, 0x48, 0x00, 0x00, 0xb0, +0x44, 0x10, 0x00, 0x12, 0x44, 0x00, 0x00, 0x45, 0xdd, 0x26, 0x84, 0x27, 0x44, 0x00, 0x00, 0x5b, +0xdd, 0x26, 0x44, 0x10, 0x00, 0x23, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x17, +0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x24, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, +0x84, 0x26, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x81, 0x44, 0x00, 0x00, 0xc3, +0xdd, 0x26, 0x44, 0x10, 0x00, 0x12, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x83, +0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x17, 0x48, 0x00, 0x00, 0x81, 0xa6, 0xf1, +0x84, 0x04, 0x54, 0x81, 0x80, 0x0e, 0x4c, 0x80, 0x40, 0x34, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, +0x04, 0x44, 0x44, 0x10, 0x00, 0x15, 0x44, 0x00, 0x00, 0x45, 0xdd, 0x26, 0x80, 0x28, 0x44, 0x00, +0x00, 0x5b, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x23, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, +0x00, 0x12, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x24, 0x44, 0x00, 0x00, 0xc3, +0xdd, 0x26, 0x84, 0x28, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x81, 0x44, 0x00, +0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x15, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, +0x00, 0x83, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x16, 0xd5, 0x48, 0x84, 0xa2, +0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x4c, 0x82, 0xc0, 0x45, 0x44, 0x10, 0x00, 0x15, +0x44, 0x00, 0x00, 0x45, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x5c, 0x44, 0x00, 0x00, 0x4b, 0xdd, 0x26, +0x84, 0x24, 0x44, 0x00, 0x00, 0x5b, 0xdd, 0x26, 0x84, 0x23, 0x44, 0x00, 0x00, 0x5c, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x23, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x10, 0x44, 0x00, +0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x24, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x84, 0x28, +0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x81, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x15, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x83, 0x44, 0x00, +0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x16, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, +0x00, 0x88, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x5b, 0x44, 0x00, 0x00, 0xc4, +0xd5, 0x30, 0x44, 0x10, 0x00, 0x15, 0x44, 0x00, 0x00, 0x45, 0xdd, 0x26, 0x84, 0x24, 0x44, 0x00, +0x00, 0x5b, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x23, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, +0x00, 0x12, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x24, 0x44, 0x00, 0x00, 0xc3, +0xdd, 0x26, 0x84, 0x28, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x81, 0x44, 0x00, +0x00, 0xc3, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x15, 0x44, 0x00, 0x00, 0xc4, 0xdd, 0x26, 0x44, 0x10, +0x00, 0x83, 0x44, 0x00, 0x00, 0xc3, 0xdd, 0x26, 0x44, 0x00, 0x00, 0xc4, 0x44, 0x10, 0x00, 0x16, +0xdd, 0x26, 0x84, 0x01, 0x80, 0x40, 0x80, 0x27, 0x46, 0x60, 0x00, 0x07, 0x58, 0x63, 0x06, 0x44, +0x4b, 0xe0, 0x18, 0x01, 0x80, 0x27, 0x84, 0x00, 0x84, 0x41, 0x4b, 0xe0, 0x18, 0x01, 0xec, 0x0c, +0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x96, 0x49, +0xe6, 0x38, 0xe9, 0x36, 0x80, 0x60, 0xa2, 0x59, 0x47, 0xe0, 0x00, 0x0e, 0x14, 0x1f, 0x01, 0x1c, +0xb4, 0xa3, 0x50, 0x20, 0x00, 0x08, 0x46, 0xf0, 0x00, 0x0e, 0x14, 0x57, 0x81, 0x1d, 0xb4, 0x62, +0x50, 0x20, 0x00, 0x0c, 0x46, 0xf0, 0x00, 0x0e, 0x14, 0x37, 0x81, 0x1e, 0xb4, 0xa2, 0x50, 0x20, +0x00, 0x10, 0x46, 0xf0, 0x00, 0x0e, 0x14, 0x57, 0x81, 0x1f, 0x50, 0x50, 0x00, 0x14, 0xb4, 0x82, +0x46, 0xf0, 0x00, 0x0e, 0x14, 0x47, 0x81, 0x20, 0x00, 0x0f, 0x04, 0x70, 0xb4, 0x65, 0x46, 0xf0, +0x00, 0x0e, 0x14, 0x37, 0x81, 0x21, 0x5c, 0xf0, 0x00, 0x37, 0xe8, 0x0a, 0x42, 0x10, 0xa0, 0x0b, +0x46, 0xf0, 0x00, 0x08, 0x58, 0xf7, 0x82, 0xc0, 0xdd, 0x2f, 0x84, 0x00, 0xd5, 0x02, 0x84, 0x01, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x46, 0x60, +0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x54, 0x90, 0x00, 0xff, 0x54, 0x80, 0x80, 0xff, 0x44, 0x00, +0x00, 0x9e, 0x44, 0x10, 0x00, 0xb0, 0x97, 0xd0, 0x4b, 0xe0, 0x18, 0x01, 0x80, 0x29, 0x44, 0x00, +0x00, 0x9f, 0x4b, 0xe0, 0x18, 0x01, 0x4e, 0x83, 0x00, 0x07, 0x44, 0x10, 0x00, 0xb1, 0x44, 0x00, +0x00, 0x9e, 0xd5, 0x05, 0x44, 0x00, 0x00, 0x9e, 0x44, 0x10, 0x00, 0xb2, 0x4b, 0xe0, 0x18, 0x01, +0x80, 0x27, 0x44, 0x00, 0x00, 0x9f, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, +0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xf4, 0x46, 0x60, +0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x54, 0x90, 0x00, 0xff, 0x97, 0xc8, 0x44, 0x00, 0x00, 0x9e, +0x44, 0x10, 0x00, 0xb0, 0x81, 0x02, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x80, 0x44, 0x00, 0x00, 0x9f, +0xdd, 0x26, 0x44, 0x30, 0x00, 0xb2, 0x44, 0x40, 0x00, 0xb1, 0x40, 0x12, 0x24, 0x1a, 0x40, 0x11, +0xa4, 0x1b, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0x80, 0x27, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x26, +0x44, 0x00, 0x00, 0x15, 0x84, 0x21, 0xdd, 0x26, 0x84, 0x00, 0x92, 0x00, 0x84, 0x27, 0x9c, 0x01, +0x4c, 0x00, 0xff, 0xfd, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x84, 0x20, 0x44, 0x00, +0x00, 0x15, 0x4b, 0xe0, 0x18, 0x01, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, 0x18, 0x01, +0x44, 0x00, 0x00, 0x9f, 0x44, 0x10, 0x00, 0x9b, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x00, 0x00, 0x9b, +0xf0, 0x81, 0x84, 0xe0, 0x50, 0x6f, 0x80, 0x04, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, 0x82, 0xc4, +0xd5, 0x27, 0x44, 0x20, 0x00, 0x65, 0x4c, 0x71, 0x00, 0x04, 0x84, 0x00, 0xd5, 0x18, 0x46, 0x60, +0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, 0x18, 0x01, +0x84, 0x20, 0x44, 0x00, 0x00, 0x9f, 0x4b, 0xe0, 0x18, 0x01, 0xd5, 0x17, 0x92, 0x00, 0x84, 0xa7, +0x9c, 0x49, 0xd9, 0xfd, 0x9c, 0x01, 0x87, 0xca, 0x4c, 0x0f, 0x00, 0x04, 0x84, 0x20, 0xd5, 0xf7, +0x84, 0x00, 0x44, 0x10, 0x00, 0x9f, 0x80, 0x46, 0x9d, 0xf9, 0x4b, 0xe0, 0x24, 0x01, 0xf4, 0x01, +0x44, 0x30, 0x00, 0x9b, 0x4c, 0x41, 0xbf, 0xd7, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x04, 0x44, +0x44, 0x10, 0x00, 0xba, 0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, 0x18, 0x01, 0x84, 0x2a, 0x44, 0x00, +0x00, 0x9f, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x10, 0x04, 0x10, 0x58, 0x10, 0x80, 0x7c, 0xb4, 0x01, +0x40, 0x10, 0x40, 0x09, 0x4e, 0x04, 0x00, 0x05, 0x44, 0x2f, 0x00, 0x00, 0x98, 0x4a, 0x45, 0xe0, +0x80, 0x00, 0x40, 0x50, 0x78, 0x02, 0x96, 0x01, 0xc5, 0x04, 0x44, 0x4f, 0x00, 0x00, 0x98, 0x04, +0x42, 0x30, 0x84, 0x24, 0x42, 0x30, 0x00, 0x73, 0xb6, 0x68, 0xec, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x6c, 0x96, 0x00, 0xf0, 0x82, 0xc0, 0x08, +0x84, 0x20, 0xf1, 0x84, 0xf1, 0x89, 0xf1, 0x8a, 0xf1, 0x8b, 0x48, 0x00, 0x02, 0x7f, 0x46, 0x30, +0x04, 0x11, 0x58, 0x31, 0x80, 0x04, 0xb5, 0x23, 0x47, 0xe0, 0x04, 0x11, 0x14, 0x9f, 0x80, 0x0b, +0x59, 0xef, 0x03, 0xb8, 0xb4, 0x5e, 0x46, 0x70, 0x04, 0x10, 0xf2, 0x8a, 0x58, 0x73, 0x85, 0x04, +0xb4, 0x87, 0x46, 0x80, 0x04, 0x10, 0xf4, 0x89, 0x58, 0x84, 0x05, 0x0c, 0xb4, 0x28, 0xf0, 0x02, +0x44, 0xa0, 0x00, 0x10, 0xf1, 0x84, 0xb6, 0x03, 0xb7, 0x5e, 0x50, 0x2f, 0x80, 0x48, 0xf0, 0x02, +0x84, 0x24, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf5, 0x12, 0x46, 0x90, +0x00, 0x06, 0x58, 0x94, 0x84, 0x44, 0x54, 0x12, 0x80, 0xe7, 0x84, 0x04, 0x4b, 0xe0, 0x24, 0x01, +0xf0, 0x02, 0x47, 0xc0, 0x00, 0x06, 0x59, 0xce, 0x01, 0x84, 0x84, 0x21, 0x50, 0x2f, 0x80, 0x7c, +0xdd, 0x3c, 0xf0, 0x02, 0x84, 0x22, 0x50, 0x2f, 0x80, 0x78, 0xdd, 0x3c, 0xf0, 0x02, 0x44, 0x10, +0x00, 0x23, 0x50, 0x2f, 0x80, 0x74, 0xdd, 0x3c, 0xf0, 0x02, 0x44, 0x10, 0x00, 0x2a, 0x50, 0x2f, +0x80, 0x70, 0xdd, 0x3c, 0xf1, 0x02, 0x50, 0x2f, 0x80, 0x6c, 0x84, 0x04, 0xdd, 0x3c, 0x84, 0x22, +0x50, 0x2f, 0x80, 0x68, 0x84, 0x04, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x22, 0x50, 0x2f, 0x80, 0x64, +0x84, 0x04, 0xdd, 0x3c, 0x84, 0x23, 0x50, 0x2f, 0x80, 0x60, 0x84, 0x05, 0xdd, 0x3c, 0x84, 0x24, +0x50, 0x2f, 0x80, 0x5c, 0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x11, 0x50, 0x2f, 0x80, 0x58, +0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x12, 0x50, 0x2f, 0x80, 0x54, 0x84, 0x05, 0xdd, 0x3c, +0x44, 0x10, 0x00, 0x13, 0x50, 0x2f, 0x80, 0x50, 0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x14, +0x50, 0x2f, 0x80, 0x4c, 0x84, 0x05, 0xdd, 0x3c, 0xf0, 0x02, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, +0x02, 0x3c, 0x84, 0x21, 0x44, 0x20, 0x00, 0x21, 0xdd, 0x26, 0xf0, 0x02, 0x80, 0x4a, 0x84, 0x22, +0xdd, 0x26, 0xf0, 0x02, 0x44, 0x10, 0x00, 0x23, 0x80, 0x40, 0xdd, 0x26, 0xf0, 0x02, 0x44, 0x10, +0x00, 0x2a, 0x44, 0x20, 0x00, 0x1b, 0xdd, 0x26, 0xf1, 0x02, 0x44, 0x20, 0x00, 0x81, 0x84, 0x04, +0xdd, 0x26, 0x84, 0x22, 0x44, 0x20, 0x00, 0x81, 0x84, 0x04, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x22, +0x44, 0x20, 0x00, 0xee, 0x84, 0x04, 0xdd, 0x26, 0x84, 0x23, 0x44, 0x20, 0x00, 0x30, 0x84, 0x05, +0xdd, 0x26, 0x84, 0x24, 0x44, 0x20, 0x00, 0x30, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x11, +0x44, 0x20, 0x00, 0x80, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x12, 0x44, 0x20, 0x00, 0xd7, +0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x13, 0x44, 0x20, 0x00, 0xa2, 0x84, 0x05, 0xdd, 0x26, +0x44, 0x20, 0x00, 0x20, 0x44, 0x10, 0x00, 0x14, 0x84, 0x05, 0xdd, 0x26, 0xf1, 0x02, 0x44, 0x00, +0x00, 0x17, 0x4b, 0xe0, 0x24, 0x01, 0xf2, 0x02, 0x46, 0x30, 0x00, 0xcf, 0x58, 0x31, 0x88, 0xb0, +0x44, 0x45, 0x20, 0x00, 0xb6, 0x47, 0xb6, 0x88, 0xb6, 0x67, 0xf3, 0x02, 0x92, 0x00, 0x84, 0xe7, +0x9c, 0xd9, 0x4c, 0x33, 0xff, 0xfd, 0x46, 0x80, 0x04, 0x10, 0x58, 0x84, 0x05, 0x0c, 0x44, 0x65, +0x20, 0x1e, 0xb6, 0xc8, 0x84, 0x60, 0x92, 0x00, 0x85, 0x47, 0x9c, 0xd9, 0x4c, 0x35, 0x7f, 0xfd, +0x47, 0xc0, 0x04, 0x10, 0x59, 0xce, 0x05, 0x0c, 0x44, 0x55, 0x20, 0x3e, 0xb6, 0xbc, 0x84, 0x60, +0x92, 0x00, 0x87, 0xc7, 0x9c, 0xd9, 0x4c, 0x3f, 0x7f, 0xfd, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, +0x84, 0x44, 0x84, 0x20, 0x44, 0x00, 0x00, 0x17, 0xdd, 0x29, 0x44, 0x10, 0x00, 0xaa, 0x44, 0x00, +0x00, 0x9e, 0xdd, 0x29, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x29, 0x44, 0x10, 0x00, 0xab, +0x44, 0x00, 0x00, 0x9e, 0xdd, 0x29, 0x84, 0x2a, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x29, 0x44, 0x10, +0x00, 0xac, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x3f, 0x44, 0x00, 0x00, 0x9f, +0xdd, 0x29, 0x44, 0x10, 0x00, 0xad, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x3f, +0x44, 0x00, 0x00, 0x9f, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x40, 0x44, 0x00, 0x00, 0xf4, 0xdd, 0x29, +0x50, 0x2f, 0x80, 0x88, 0x44, 0x10, 0x00, 0x1f, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x82, 0xc4, 0xdd, 0x2f, 0xf7, 0x22, 0x44, 0x00, 0x00, 0x1f, 0x58, 0x23, 0x80, 0x60, 0xf2, 0xa2, +0x80, 0x22, 0xdd, 0x29, 0x84, 0x25, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x29, 0x84, 0x20, 0x44, 0x00, +0x00, 0x9f, 0xdd, 0x29, 0x46, 0x40, 0x00, 0x0e, 0x58, 0x42, 0x04, 0x50, 0x22, 0x12, 0x00, 0x00, +0x46, 0x30, 0x00, 0x0e, 0x58, 0x31, 0x84, 0x60, 0x84, 0x00, 0xf1, 0x88, 0xf3, 0x86, 0xf0, 0x83, +0x46, 0x80, 0x00, 0x0b, 0x58, 0x84, 0x06, 0x28, 0x3a, 0x04, 0x04, 0x00, 0x46, 0x70, 0x00, 0x0b, +0x58, 0x73, 0x86, 0x20, 0xf0, 0x90, 0x12, 0x1f, 0x80, 0x22, 0xf1, 0x03, 0x50, 0x0f, 0x80, 0x40, +0x38, 0x20, 0x04, 0x00, 0x44, 0x31, 0x20, 0x3e, 0x40, 0x91, 0x64, 0x08, 0x3a, 0x03, 0x84, 0x00, +0x46, 0x40, 0x04, 0x10, 0x41, 0xe4, 0x8c, 0x04, 0x58, 0x42, 0x05, 0x0c, 0x51, 0xcf, 0x80, 0x38, +0xb6, 0x1c, 0x12, 0x1f, 0x80, 0x1e, 0x15, 0xe2, 0x00, 0x00, 0x46, 0xa0, 0x00, 0x06, 0x58, 0xa5, +0x04, 0x44, 0xf5, 0x03, 0x44, 0x00, 0x00, 0x17, 0x38, 0x1e, 0x14, 0x00, 0xdd, 0x2a, 0x44, 0x10, +0x00, 0xb0, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x2a, 0x44, 0x10, 0x00, 0x80, 0x44, 0x00, 0x00, 0x9f, +0xdd, 0x2a, 0x44, 0x10, 0x00, 0xb2, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x2a, 0x44, 0x00, 0x00, 0x9f, +0x84, 0x20, 0xdd, 0x2a, 0xf6, 0x03, 0x54, 0x83, 0x00, 0xff, 0x4e, 0x83, 0x00, 0x3b, 0x46, 0x80, +0x2e, 0xba, 0x58, 0x84, 0x0e, 0x3f, 0x44, 0x70, 0x00, 0x12, 0x47, 0xc0, 0x00, 0x0b, 0x59, 0xce, +0x06, 0x0c, 0x46, 0xa0, 0x00, 0x06, 0x58, 0xa5, 0x02, 0x3c, 0x46, 0x90, 0x00, 0x08, 0x58, 0x94, +0x87, 0x38, 0xd5, 0x22, 0xf5, 0x08, 0x9f, 0xfa, 0x38, 0x6e, 0x14, 0x00, 0x80, 0x46, 0x4b, 0xe0, +0x28, 0x01, 0x80, 0x46, 0x84, 0x24, 0x84, 0x05, 0x4b, 0xe0, 0x28, 0x01, 0x84, 0x00, 0x80, 0x20, +0x50, 0x2f, 0x80, 0x84, 0x4b, 0xe0, 0x24, 0x01, 0x84, 0x00, 0x44, 0x10, 0x00, 0x21, 0x50, 0x2f, +0x80, 0x80, 0x4b, 0xe0, 0x24, 0x01, 0xf6, 0x21, 0xe3, 0x06, 0xe9, 0x05, 0x05, 0xef, 0x80, 0x20, +0xe3, 0x1e, 0xe8, 0x07, 0x97, 0xf9, 0x97, 0x3b, 0x84, 0x23, 0x84, 0x05, 0xf4, 0x88, 0xcf, 0xdb, +0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x84, 0x44, 0x44, 0x10, 0x00, 0xb1, 0x44, 0x00, 0x00, 0x9e, +0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0x9f, 0x84, 0x20, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x90, +0x00, 0x20, 0x84, 0x60, 0x85, 0x40, 0x87, 0x85, 0x14, 0x9f, 0x80, 0x05, 0x10, 0x3f, 0x80, 0x8d, +0x10, 0x3f, 0x80, 0x8c, 0x15, 0xcf, 0x80, 0x07, 0x81, 0x2a, 0xd5, 0x63, 0x81, 0x49, 0xf1, 0x05, +0xa7, 0x98, 0x44, 0x80, 0x00, 0x20, 0x9a, 0xb1, 0x54, 0x71, 0x00, 0x3f, 0x80, 0x1c, 0x80, 0x27, +0x50, 0x2f, 0x80, 0x84, 0x4c, 0x64, 0x40, 0x06, 0x14, 0x9f, 0x80, 0x21, 0x80, 0xe6, 0xd5, 0x08, +0xf3, 0x81, 0x46, 0xf0, 0x00, 0x08, 0x58, 0xf7, 0x87, 0x38, 0xdd, 0x2f, 0xf3, 0x01, 0x05, 0xef, +0x80, 0x0c, 0x80, 0x1c, 0x40, 0x5f, 0x18, 0x00, 0x54, 0x82, 0x80, 0x3f, 0x80, 0x28, 0x50, 0x2f, +0x80, 0x80, 0xf3, 0x81, 0x46, 0xf0, 0x00, 0x08, 0x58, 0xf7, 0x87, 0x38, 0xdd, 0x2f, 0x04, 0x9f, +0x80, 0x21, 0xf5, 0x20, 0x40, 0x04, 0xa8, 0x06, 0xf1, 0x0d, 0x56, 0x20, 0x00, 0x01, 0x40, 0x31, +0x04, 0x02, 0x40, 0x45, 0x14, 0x06, 0x40, 0x01, 0x90, 0x02, 0xf3, 0x01, 0xc0, 0x04, 0xaf, 0x98, +0x81, 0x2a, 0xd5, 0x08, 0xe3, 0x25, 0xe8, 0x03, 0xaf, 0xd8, 0xd5, 0x04, 0x10, 0x81, 0x80, 0x00, +0x81, 0x25, 0x08, 0x21, 0x80, 0x01, 0x80, 0x3c, 0x84, 0x00, 0x51, 0xce, 0x00, 0x01, 0x84, 0xc2, +0xf3, 0x81, 0x46, 0xf0, 0x00, 0x08, 0x58, 0xf7, 0x86, 0xd8, 0xdd, 0x2f, 0xf3, 0x01, 0x4d, 0xc3, +0x7f, 0xaf, 0xf3, 0x07, 0x84, 0xff, 0x50, 0x81, 0xff, 0xff, 0x40, 0xa4, 0x00, 0x10, 0x14, 0xaf, +0x80, 0x07, 0x4c, 0xa3, 0x80, 0x18, 0xf4, 0x05, 0x41, 0xc2, 0x04, 0x09, 0x15, 0xcf, 0x80, 0x05, +0xf6, 0x07, 0x87, 0x80, 0xf0, 0x05, 0x56, 0x23, 0x00, 0x05, 0x87, 0xc0, 0x80, 0x3c, 0x40, 0x5f, +0x08, 0x06, 0x40, 0x10, 0x08, 0x1b, 0xf5, 0x8d, 0x50, 0x3f, 0x80, 0x8c, 0x81, 0x49, 0xf1, 0x8c, +0xd5, 0x8f, 0x04, 0x8f, 0x80, 0x06, 0xf1, 0x03, 0x00, 0x4f, 0x80, 0x8c, 0x00, 0x3f, 0x80, 0x8d, +0x50, 0x90, 0x80, 0x01, 0x50, 0x74, 0x00, 0x02, 0x85, 0x43, 0x14, 0x9f, 0x80, 0x03, 0x10, 0x44, +0x00, 0x00, 0x10, 0x34, 0x00, 0x01, 0xf7, 0x86, 0x4c, 0x95, 0x7e, 0xdc, 0xf2, 0x08, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x04, 0x50, 0xac, 0x80, 0x85, 0x20, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, +0x84, 0x44, 0xd5, 0x37, 0x44, 0x10, 0x00, 0xb0, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x27, 0x80, 0x2a, +0x44, 0x00, 0x00, 0x9f, 0xdd, 0x27, 0x00, 0x24, 0x00, 0x00, 0x44, 0x10, 0x00, 0xb1, 0x54, 0x41, +0x00, 0x3f, 0xf4, 0xa2, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x27, 0xf1, 0x22, 0x44, 0x00, 0x00, 0x9f, +0xdd, 0x27, 0x00, 0x34, 0x00, 0x01, 0x44, 0x10, 0x00, 0xb2, 0x54, 0x61, 0x80, 0x3f, 0xf6, 0xa2, +0x44, 0x00, 0x00, 0x9e, 0xdd, 0x27, 0xf1, 0x22, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x27, 0x8d, 0x02, +0x46, 0x50, 0x00, 0x0e, 0x58, 0x52, 0x84, 0x66, 0x8d, 0x41, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, +0x04, 0x44, 0x4c, 0x82, 0xff, 0xd1, 0x8d, 0x24, 0x45, 0xe0, 0x00, 0x10, 0x4c, 0x9f, 0x00, 0x08, +0x46, 0x80, 0x00, 0x0e, 0x58, 0x84, 0x04, 0x60, 0x81, 0x49, 0xd5, 0xc5, 0xf1, 0x02, 0x4e, 0x13, +0x00, 0x95, 0xf3, 0x0b, 0x46, 0x40, 0x04, 0x11, 0x58, 0x42, 0x00, 0x04, 0xb6, 0x64, 0x46, 0x50, +0x04, 0x11, 0xf0, 0x0a, 0x58, 0x52, 0x83, 0xb8, 0xb6, 0x05, 0x44, 0x00, 0x00, 0xf4, 0xf1, 0x02, +0xdd, 0x26, 0xf0, 0x02, 0x50, 0x2f, 0x80, 0x88, 0x44, 0x10, 0x00, 0x1f, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0x04, 0x8f, 0x80, 0x22, 0x44, 0x00, 0x00, 0x1f, 0x54, 0x74, +0x00, 0x9f, 0xf7, 0xa2, 0x80, 0x27, 0xdd, 0x26, 0x84, 0x28, 0x44, 0x00, 0x00, 0x1f, 0xdd, 0x26, +0xf1, 0x02, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0xf1, 0x02, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x26, +0x44, 0x00, 0x00, 0x15, 0x84, 0x21, 0xdd, 0x26, 0xf0, 0x02, 0x92, 0x00, 0x84, 0xc7, 0x9c, 0x01, +0x4c, 0x03, 0x7f, 0xfd, 0x84, 0x20, 0x46, 0x80, 0x00, 0x06, 0x58, 0x84, 0x04, 0x44, 0x44, 0x00, +0x00, 0x15, 0x4b, 0xe0, 0x20, 0x01, 0x46, 0x20, 0x04, 0x10, 0x84, 0xe0, 0x58, 0x21, 0x05, 0x04, +0xb6, 0xe2, 0x46, 0x00, 0x04, 0x10, 0xf5, 0x04, 0x58, 0x00, 0x05, 0x0c, 0xb6, 0xa0, 0x46, 0x60, +0x00, 0x06, 0x58, 0x63, 0x02, 0x3c, 0xf1, 0x09, 0x80, 0x07, 0xb6, 0x22, 0x84, 0x21, 0xf2, 0x1f, +0xdd, 0x26, 0xf2, 0x1e, 0x84, 0x22, 0x80, 0x07, 0xdd, 0x26, 0xf2, 0x1d, 0x44, 0x10, 0x00, 0x23, +0x80, 0x07, 0xdd, 0x26, 0xf2, 0x1c, 0x44, 0x10, 0x00, 0x2a, 0x80, 0x07, 0xdd, 0x26, 0xf2, 0x1b, +0x80, 0x27, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x1a, 0x84, 0x22, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x19, +0x44, 0x10, 0x00, 0x22, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x18, 0x84, 0x23, 0x84, 0x05, 0xdd, 0x26, +0xf2, 0x17, 0x84, 0x24, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x16, 0x44, 0x10, 0x00, 0x11, 0x84, 0x05, +0xdd, 0x26, 0xf2, 0x15, 0x44, 0x10, 0x00, 0x12, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x14, 0x44, 0x10, +0x00, 0x13, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x13, 0x44, 0x10, 0x00, 0x14, 0x84, 0x05, 0xdd, 0x26, +0xf1, 0x12, 0x84, 0x04, 0x4b, 0xe0, 0x20, 0x01, 0xec, 0x94, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3a, 0x6f, 0xa0, 0xbc, 0xef, 0xf8, 0x84, 0x21, 0x80, 0xe0, 0x44, 0x00, 0x00, 0x15, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0x84, 0x20, 0xd5, 0x0a, 0x92, 0x00, 0x84, 0x07, +0x9c, 0x91, 0x4c, 0x20, 0x7f, 0xfd, 0x9c, 0x49, 0x84, 0x6a, 0x4c, 0x11, 0x80, 0x04, 0x84, 0x40, +0xd5, 0xf6, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x84, 0x20, 0x44, 0x00, 0x00, 0x15, +0x4b, 0xe0, 0x18, 0x01, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x10, +0x00, 0x9b, 0x44, 0x00, 0x00, 0x9f, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x10, 0x00, 0x9b, 0xf1, 0x81, +0x50, 0x6f, 0x80, 0x04, 0x46, 0x80, 0x00, 0x06, 0x58, 0x84, 0x02, 0xc4, 0xd5, 0x12, 0x92, 0x00, +0x84, 0x87, 0x9c, 0x91, 0x4c, 0x22, 0x7f, 0xfd, 0x9c, 0x49, 0x84, 0x4a, 0x4c, 0x11, 0x00, 0x04, +0x84, 0x40, 0xd5, 0xf6, 0x84, 0x00, 0x44, 0x10, 0x00, 0x9f, 0x80, 0x46, 0x4b, 0xe0, 0x20, 0x01, +0xf5, 0x01, 0x45, 0xe0, 0x00, 0x9b, 0x4c, 0x5f, 0x40, 0x04, 0x84, 0x20, 0xd5, 0xf2, 0x46, 0x60, +0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x44, 0x10, 0x00, 0xba, 0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, +0x18, 0x01, 0x44, 0x10, 0x00, 0x14, 0x44, 0x00, 0x00, 0x9f, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x00, +0x04, 0x10, 0x58, 0x00, 0x00, 0x7c, 0xb4, 0x20, 0x40, 0x20, 0xc0, 0x09, 0x4e, 0x14, 0x00, 0x05, +0x44, 0x3f, 0x00, 0x00, 0x98, 0x93, 0x44, 0x50, 0x80, 0x00, 0x40, 0x40, 0x94, 0x02, 0x96, 0x49, +0xc4, 0x04, 0x45, 0xef, 0x00, 0x00, 0x88, 0x3e, 0x42, 0x21, 0x08, 0x24, 0x42, 0x20, 0x84, 0x73, +0xb6, 0x47, 0xec, 0x08, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0x7c, 0x96, 0x00, 0xf0, 0x83, 0xc0, 0x08, 0x84, 0x20, 0xf1, 0x87, 0xf1, 0x8a, 0xf1, 0x8b, +0xf1, 0x8c, 0x48, 0x00, 0x03, 0x9d, 0x46, 0x40, 0x04, 0x11, 0x58, 0x42, 0x00, 0x04, 0xb5, 0x24, +0x46, 0x30, 0x04, 0x11, 0x14, 0x9f, 0x80, 0x0a, 0x58, 0x31, 0x83, 0xb8, 0xb4, 0x43, 0x46, 0x70, +0x04, 0x10, 0xf2, 0x87, 0x58, 0x73, 0x85, 0x04, 0xb4, 0x27, 0x46, 0x80, 0x04, 0x10, 0xf1, 0x8c, +0x58, 0x84, 0x05, 0x0c, 0x05, 0xef, 0x80, 0x03, 0xb4, 0x08, 0x44, 0xa0, 0x00, 0x10, 0xf0, 0x8b, +0x15, 0xe2, 0x00, 0x00, 0xb7, 0x43, 0x50, 0x2f, 0x80, 0x44, 0xf0, 0x03, 0x84, 0x24, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf5, 0x11, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, +0x84, 0x44, 0x54, 0x12, 0x80, 0xe7, 0x84, 0x04, 0x4b, 0xe0, 0x24, 0x01, 0xf0, 0x03, 0x47, 0xc0, +0x00, 0x06, 0x59, 0xce, 0x01, 0x84, 0x84, 0x21, 0x50, 0x2f, 0x80, 0x78, 0xdd, 0x3c, 0xf0, 0x03, +0x84, 0x22, 0x50, 0x2f, 0x80, 0x74, 0xdd, 0x3c, 0xf0, 0x03, 0x44, 0x10, 0x00, 0x23, 0x50, 0x2f, +0x80, 0x70, 0xdd, 0x3c, 0xf0, 0x03, 0x44, 0x10, 0x00, 0x2a, 0x50, 0x2f, 0x80, 0x6c, 0xdd, 0x3c, +0xf1, 0x03, 0x50, 0x2f, 0x80, 0x68, 0x84, 0x04, 0xdd, 0x3c, 0x84, 0x22, 0x50, 0x2f, 0x80, 0x64, +0x84, 0x04, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x22, 0x50, 0x2f, 0x80, 0x60, 0x84, 0x04, 0xdd, 0x3c, +0x84, 0x23, 0x50, 0x2f, 0x80, 0x5c, 0x84, 0x05, 0xdd, 0x3c, 0x84, 0x24, 0x50, 0x2f, 0x80, 0x58, +0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x11, 0x50, 0x2f, 0x80, 0x54, 0x84, 0x05, 0xdd, 0x3c, +0x44, 0x10, 0x00, 0x12, 0x50, 0x2f, 0x80, 0x50, 0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x13, +0x50, 0x2f, 0x80, 0x4c, 0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x14, 0x50, 0x2f, 0x80, 0x48, +0x84, 0x05, 0xdd, 0x3c, 0xf0, 0x03, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x02, 0x3c, 0x84, 0x21, +0x44, 0x20, 0x00, 0x21, 0xdd, 0x26, 0xf0, 0x03, 0x80, 0x4a, 0x84, 0x22, 0xdd, 0x26, 0xf0, 0x03, +0x44, 0x10, 0x00, 0x23, 0x80, 0x40, 0xdd, 0x26, 0xf0, 0x03, 0x44, 0x10, 0x00, 0x2a, 0x44, 0x20, +0x00, 0x1b, 0xdd, 0x26, 0xf1, 0x03, 0x44, 0x20, 0x00, 0x81, 0x84, 0x04, 0xdd, 0x26, 0x84, 0x22, +0x44, 0x20, 0x00, 0x81, 0x84, 0x04, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x22, 0x44, 0x20, 0x00, 0xee, +0x84, 0x04, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x11, 0x44, 0x20, 0x00, 0x80, 0x84, 0x05, 0xdd, 0x26, +0x44, 0x10, 0x00, 0x12, 0x44, 0x20, 0x00, 0xd7, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x13, +0x44, 0x20, 0x00, 0xa2, 0x84, 0x05, 0xdd, 0x26, 0x44, 0x20, 0x00, 0x20, 0x44, 0x10, 0x00, 0x14, +0x84, 0x05, 0xdd, 0x26, 0xf1, 0x03, 0x44, 0x00, 0x00, 0x17, 0x4b, 0xe0, 0x24, 0x01, 0xf2, 0x03, +0x46, 0x30, 0x00, 0xcf, 0x58, 0x31, 0x88, 0xb0, 0x44, 0x45, 0x20, 0x00, 0xb6, 0x47, 0xb6, 0x88, +0xb6, 0x67, 0xf3, 0x03, 0x92, 0x00, 0x84, 0xe7, 0x9c, 0xd9, 0x4c, 0x33, 0xff, 0xfd, 0x46, 0x80, +0x04, 0x10, 0x58, 0x84, 0x05, 0x0c, 0x44, 0x65, 0x20, 0x1e, 0xb6, 0xc8, 0x84, 0x60, 0x92, 0x00, +0x85, 0x47, 0x9c, 0xd9, 0x4c, 0x35, 0x7f, 0xfd, 0x47, 0xc0, 0x04, 0x10, 0x59, 0xce, 0x05, 0x0c, +0x44, 0x55, 0x20, 0x3e, 0xb6, 0xbc, 0x84, 0x60, 0x92, 0x00, 0x84, 0x87, 0x9c, 0xd9, 0x4c, 0x32, +0x7f, 0xfd, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, 0x84, 0x44, 0x84, 0x24, 0x44, 0x00, 0x00, 0x17, +0xdd, 0x29, 0x44, 0x10, 0x00, 0x14, 0x44, 0x00, 0x00, 0xf1, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x80, +0x44, 0x00, 0x00, 0xf2, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x31, 0x44, 0x00, 0x00, 0xf4, 0xdd, 0x29, +0x44, 0x10, 0x00, 0xb0, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x80, 0x44, 0x00, +0x00, 0x9f, 0xdd, 0x29, 0x46, 0x80, 0x00, 0x06, 0x58, 0x84, 0x02, 0xc4, 0x50, 0x2f, 0x80, 0x40, +0x44, 0x10, 0x00, 0x1f, 0x84, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0xf1, 0x10, 0x44, 0x00, 0x00, 0x1f, +0x58, 0x20, 0x80, 0x60, 0xf2, 0x9f, 0x80, 0x22, 0xdd, 0x29, 0x84, 0x25, 0x44, 0x00, 0x00, 0x9e, +0xdd, 0x29, 0x84, 0x24, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x29, 0x84, 0x23, 0x44, 0x00, 0x00, 0x9e, +0xdd, 0x29, 0x50, 0x2f, 0x80, 0x7c, 0x44, 0x10, 0x00, 0x9f, 0x84, 0x00, 0x4b, 0xe0, 0x20, 0x01, +0xf3, 0x1f, 0x44, 0x00, 0x00, 0x9f, 0x58, 0x11, 0x80, 0x60, 0xdd, 0x29, 0x46, 0x70, 0x00, 0x06, +0x58, 0x73, 0x82, 0x3c, 0x84, 0x23, 0x44, 0x20, 0x00, 0x3c, 0x84, 0x05, 0x4b, 0xe0, 0x1c, 0x01, +0x44, 0x20, 0x00, 0x3c, 0x84, 0x24, 0x84, 0x05, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x10, 0x00, 0x28, +0x44, 0x00, 0x00, 0x9e, 0xdd, 0x29, 0x44, 0x00, 0x00, 0x9f, 0x84, 0x20, 0xdd, 0x29, 0x46, 0x30, +0x00, 0x0e, 0x58, 0x31, 0x84, 0x50, 0x22, 0x41, 0x80, 0x00, 0x4e, 0x44, 0x00, 0x04, 0x84, 0x80, +0xd5, 0x05, 0xe4, 0x93, 0xe9, 0x42, 0x44, 0x40, 0x00, 0x12, 0xad, 0x18, 0xd5, 0x3e, 0x46, 0x40, +0x00, 0x0b, 0x58, 0x42, 0x06, 0x0c, 0x38, 0x22, 0x08, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x82, 0x3c, 0xdd, 0x2f, 0x22, 0x54, 0x00, 0x00, 0x47, 0xe0, 0x00, 0x0b, 0x59, 0xef, 0x06, 0x0c, +0x38, 0x2f, 0x14, 0x00, 0x84, 0x24, 0x84, 0x05, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0x3c, +0xdd, 0x2f, 0x44, 0x10, 0x00, 0x29, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x21, +0x44, 0x00, 0x00, 0x9f, 0xdd, 0x29, 0x80, 0x07, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x29, 0x44, 0x00, +0x00, 0x9e, 0xdd, 0x29, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x29, 0x80, 0x06, 0xdd, 0x3c, +0xf0, 0x0f, 0xe3, 0x40, 0xe9, 0x24, 0xf3, 0x0e, 0xe3, 0x43, 0xe9, 0x21, 0x02, 0x14, 0x00, 0x00, +0x9c, 0x8a, 0x12, 0x24, 0x00, 0x00, 0xd5, 0x15, 0x46, 0xa0, 0x05, 0xf5, 0x58, 0xa5, 0x0e, 0x10, +0x46, 0x80, 0x00, 0x0e, 0x58, 0x84, 0x04, 0x50, 0x46, 0x90, 0x00, 0x06, 0x58, 0x94, 0x84, 0x44, +0x50, 0x7f, 0x80, 0x3c, 0x47, 0xc0, 0x00, 0x08, 0x59, 0xce, 0x0f, 0x50, 0x50, 0x6f, 0x80, 0x38, +0x22, 0x24, 0x00, 0x00, 0x84, 0x23, 0x84, 0x05, 0xe4, 0x53, 0xe9, 0xaa, 0x85, 0x40, 0x85, 0x25, +0x45, 0xc0, 0x00, 0x20, 0x84, 0x00, 0x46, 0x70, 0x00, 0x0e, 0x58, 0x73, 0x84, 0x5c, 0x14, 0x9f, +0x80, 0x05, 0x15, 0xcf, 0x80, 0x06, 0x14, 0xaf, 0x80, 0x04, 0xae, 0x38, 0x50, 0x2f, 0x80, 0x38, +0x50, 0x5f, 0x80, 0x3c, 0x81, 0x2a, 0x83, 0x8a, 0x48, 0x00, 0x00, 0xf4, 0x14, 0x9f, 0x80, 0x04, +0x84, 0x61, 0x4c, 0xa1, 0x80, 0x17, 0x05, 0xef, 0x80, 0x05, 0x5e, 0xff, 0x00, 0x04, 0x4e, 0xf2, +0x00, 0xd7, 0x46, 0x80, 0x00, 0x0e, 0x58, 0x84, 0x04, 0x5c, 0x00, 0x94, 0x00, 0x00, 0x04, 0x8f, +0x80, 0x09, 0x54, 0x14, 0x80, 0x0f, 0x56, 0x40, 0x80, 0x08, 0x40, 0x02, 0x0c, 0x06, 0xd5, 0x09, +0x54, 0x64, 0x80, 0x3f, 0x56, 0x33, 0x00, 0x20, 0x04, 0x8f, 0x80, 0x08, 0x5c, 0x01, 0x80, 0x01, +0xc0, 0x05, 0x15, 0xcf, 0x80, 0x0f, 0x80, 0xe9, 0xd5, 0x39, 0xf0, 0x06, 0x40, 0x74, 0x80, 0x01, +0x96, 0xf8, 0x4e, 0xa3, 0x00, 0x12, 0x44, 0x10, 0x00, 0x28, 0x44, 0x00, 0x00, 0x9e, 0xf2, 0x81, +0xb6, 0xbf, 0x54, 0x71, 0x80, 0x0f, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, +0xf2, 0x01, 0xb4, 0xbf, 0xd5, 0x10, 0x44, 0x00, 0x00, 0x9e, 0x44, 0x10, 0x00, 0x29, 0xf2, 0x81, +0xb6, 0xbf, 0x54, 0x71, 0x80, 0x3f, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, +0xb4, 0xbf, 0xf2, 0x01, 0x80, 0x27, 0x44, 0x00, 0x00, 0x9f, 0xf2, 0x81, 0xb6, 0xbf, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0xb4, 0xbf, 0x80, 0x05, 0x46, 0xf0, 0x00, 0x08, +0x58, 0xf7, 0x8f, 0x50, 0xdd, 0x2f, 0xb4, 0xbf, 0xf2, 0x01, 0xf1, 0x06, 0x84, 0x80, 0x40, 0x40, +0xa0, 0x1a, 0x41, 0xe2, 0x24, 0x00, 0x54, 0x3f, 0x00, 0xff, 0x4e, 0xa3, 0x00, 0x12, 0x44, 0x10, +0x00, 0x28, 0x44, 0x00, 0x00, 0x9e, 0xf2, 0x81, 0xb6, 0xbf, 0x54, 0x61, 0x80, 0x0f, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0xf2, 0x01, 0xb4, 0xbf, 0xd5, 0x10, 0x44, 0x00, +0x00, 0x9e, 0x44, 0x10, 0x00, 0x29, 0xf2, 0x81, 0xb6, 0xbf, 0x54, 0x61, 0x80, 0x3f, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0xb4, 0xbf, 0xf2, 0x01, 0x80, 0x26, 0x44, 0x00, +0x00, 0x9f, 0xb6, 0xbf, 0xf2, 0x81, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, +0xf2, 0x01, 0x80, 0x02, 0x46, 0xf0, 0x00, 0x08, 0x58, 0xf7, 0x8f, 0x50, 0xdd, 0x2f, 0xf2, 0x01, +0xb4, 0xbf, 0x4e, 0x83, 0x00, 0x09, 0xf3, 0x0f, 0xe2, 0x7c, 0xe9, 0x05, 0xf0, 0x0e, 0x40, 0xfe, +0x00, 0x06, 0xe9, 0x0a, 0xf3, 0x0f, 0x05, 0xcf, 0x80, 0x0e, 0xe2, 0x7c, 0xe8, 0x04, 0x83, 0x83, +0x81, 0x27, 0xd5, 0x02, 0x81, 0x26, 0x4e, 0xa3, 0x00, 0x10, 0x44, 0x10, 0x00, 0x28, 0x44, 0x00, +0x00, 0x9e, 0xf2, 0x81, 0xb6, 0xbf, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, +0xf2, 0x01, 0xb4, 0xbf, 0xd5, 0x0e, 0x44, 0x00, 0x00, 0x9e, 0x44, 0x10, 0x00, 0x29, 0xf2, 0x81, +0xb6, 0xbf, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0xb4, 0xbf, 0xf2, 0x01, +0x44, 0x00, 0x00, 0x9f, 0x80, 0x29, 0xf2, 0x81, 0xb6, 0xbf, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x84, 0x44, 0xdd, 0x2f, 0xf2, 0x01, 0xb4, 0xbf, 0x4e, 0xa3, 0x00, 0x0a, 0x46, 0x60, 0x00, 0x0e, +0x58, 0x63, 0x04, 0x5c, 0x10, 0x93, 0x00, 0x00, 0x04, 0x9f, 0x80, 0x04, 0x8d, 0x41, 0x54, 0xa5, +0x00, 0xff, 0x84, 0xe2, 0x4c, 0xa3, 0xff, 0x1c, 0xf1, 0x05, 0x9f, 0x09, 0x41, 0xe2, 0x00, 0x10, +0x15, 0xef, 0x80, 0x05, 0x4f, 0xe2, 0x00, 0x18, 0xf0, 0x06, 0x40, 0x30, 0x04, 0x09, 0xf3, 0x86, +0x05, 0xef, 0x80, 0x05, 0x14, 0x9f, 0x80, 0x04, 0x56, 0x4f, 0x00, 0x05, 0x56, 0x7f, 0x00, 0x03, +0x5c, 0xa2, 0x00, 0x01, 0x5c, 0x63, 0x80, 0x01, 0x14, 0xaf, 0x80, 0x08, 0xf6, 0x89, 0x85, 0x40, +0x48, 0xff, 0xff, 0x00, 0x44, 0x00, 0x00, 0x17, 0x84, 0x27, 0x14, 0x9f, 0x80, 0x04, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0x46, 0x20, 0x00, 0x0e, 0x58, 0x21, 0x04, 0x5c, +0xa7, 0x50, 0x80, 0xdc, 0x55, 0xc2, 0x80, 0x08, 0x54, 0x32, 0x80, 0x0f, 0x4f, 0xc2, 0x00, 0x05, +0x50, 0x11, 0xff, 0xf0, 0x96, 0xca, 0x84, 0x04, 0x42, 0x31, 0x80, 0x01, 0x5e, 0xf1, 0xff, 0xf9, +0xe8, 0x04, 0x84, 0x78, 0xf3, 0x86, 0xd5, 0x04, 0x9f, 0x19, 0x97, 0xe2, 0xf7, 0x86, 0x05, 0xcf, +0x80, 0x04, 0x55, 0xee, 0x00, 0x20, 0x54, 0x3e, 0x00, 0x3f, 0x4f, 0xe2, 0x00, 0x05, 0x50, 0x51, +0xff, 0xc0, 0x96, 0xea, 0x44, 0x20, 0x00, 0x1c, 0x42, 0x31, 0x88, 0x01, 0x5e, 0xf1, 0xff, 0xe1, +0xe8, 0x04, 0x44, 0x3f, 0xff, 0xe0, 0xd5, 0x03, 0x9e, 0x59, 0x96, 0xca, 0xf3, 0x85, 0xf3, 0x06, +0xf7, 0x05, 0x87, 0xc0, 0x9d, 0x1b, 0x9c, 0x3b, 0x15, 0xef, 0x80, 0x08, 0xf4, 0x89, 0xf0, 0x8d, +0x50, 0x2f, 0x80, 0x3c, 0x83, 0x83, 0xd5, 0x5f, 0xf2, 0x81, 0xf4, 0x82, 0xb6, 0xbf, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0x80, 0x2a, 0x44, 0x00, 0x00, 0x9f, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0x44, 0x10, 0x00, 0x29, 0x44, 0x00, 0x00, 0x9e, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0x80, 0x26, 0x44, 0x00, 0x00, 0x9f, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0xf5, 0x01, 0x80, 0x05, 0x46, 0xf0, +0x00, 0x08, 0x58, 0xf7, 0x8f, 0x50, 0xdd, 0x2f, 0xb4, 0xbf, 0xf1, 0x06, 0xf2, 0x01, 0xf4, 0x02, +0xd9, 0x09, 0xf3, 0x05, 0x4c, 0x81, 0xc0, 0x07, 0x10, 0xa2, 0x00, 0x00, 0xf6, 0x84, 0xf0, 0x0f, +0xd5, 0x0c, 0xf0, 0x0f, 0xe2, 0x09, 0xe9, 0x03, 0x80, 0x09, 0xd5, 0x07, 0x54, 0x93, 0x80, 0x3f, +0x10, 0xa2, 0x00, 0x00, 0x14, 0x9f, 0x80, 0x04, 0x8d, 0x01, 0x40, 0x84, 0x00, 0x10, 0x51, 0xce, +0x00, 0x01, 0x81, 0x20, 0x05, 0xef, 0x80, 0x05, 0x54, 0x74, 0x00, 0xff, 0x40, 0x3e, 0x78, 0x00, +0x05, 0xef, 0x80, 0x0d, 0x44, 0x10, 0x00, 0x28, 0x44, 0x00, 0x00, 0x9e, 0x54, 0x63, 0x80, 0x3f, +0x40, 0xff, 0x0c, 0x07, 0xe8, 0xaa, 0xf7, 0x08, 0x9d, 0x29, 0x9c, 0x39, 0xf0, 0x88, 0x80, 0xc9, +0x41, 0xc2, 0x00, 0x10, 0x05, 0xef, 0x80, 0x08, 0xf3, 0x06, 0xf1, 0x09, 0x40, 0x5f, 0x0c, 0x00, +0xe0, 0x25, 0xe9, 0x0f, 0x54, 0x9e, 0x00, 0x0f, 0x85, 0x40, 0x80, 0xbc, 0x04, 0x8f, 0x80, 0x05, +0x83, 0x8a, 0x46, 0x40, 0x00, 0x0e, 0x58, 0x42, 0x04, 0x5c, 0x81, 0x49, 0x81, 0x26, 0xd5, 0xd3, +0xf6, 0x04, 0x46, 0x20, 0x00, 0x0e, 0x58, 0x21, 0x04, 0x5d, 0xaf, 0x90, 0x46, 0x60, 0x00, 0x06, +0x58, 0x63, 0x04, 0x44, 0x44, 0x10, 0x00, 0x28, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0x46, 0x50, +0x00, 0x0e, 0x58, 0x52, 0x84, 0x5c, 0xa7, 0x28, 0x44, 0x00, 0x00, 0x9f, 0x54, 0x12, 0x00, 0x0f, +0xdd, 0x26, 0x44, 0x10, 0x00, 0x29, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0x46, 0x00, 0x00, 0x0e, +0x58, 0x00, 0x04, 0x5d, 0xa7, 0xc0, 0x44, 0x00, 0x00, 0x9f, 0x54, 0x13, 0x80, 0x3f, 0xdd, 0x26, +0x84, 0x20, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x26, +0x84, 0x20, 0x44, 0x00, 0x00, 0xf4, 0xdd, 0x26, 0x44, 0x00, 0x00, 0x15, 0x84, 0x21, 0xdd, 0x26, +0x84, 0x60, 0x92, 0x00, 0x84, 0x27, 0x9c, 0xd9, 0x4c, 0x30, 0xff, 0xfd, 0x46, 0x70, 0x00, 0x06, +0x58, 0x73, 0x84, 0x44, 0x44, 0x00, 0x00, 0x15, 0x84, 0x20, 0xdd, 0x27, 0xf3, 0x03, 0xcb, 0x6e, +0x05, 0xef, 0x80, 0x0a, 0x46, 0x30, 0x04, 0x11, 0x58, 0x31, 0x80, 0x04, 0x15, 0xe1, 0x80, 0x00, +0x46, 0x50, 0x04, 0x11, 0xf1, 0x07, 0x58, 0x52, 0x83, 0xb8, 0xb6, 0x25, 0x46, 0x20, 0x04, 0x10, +0xf0, 0x03, 0x58, 0x21, 0x05, 0x04, 0xb6, 0x02, 0x46, 0x40, 0x04, 0x10, 0xf6, 0x0b, 0x58, 0x42, +0x05, 0x0c, 0xb6, 0xc4, 0x44, 0x10, 0x00, 0xb0, 0x05, 0xef, 0x80, 0x0c, 0x44, 0x00, 0x00, 0x9e, +0x15, 0xe1, 0x00, 0x00, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x02, 0x3c, 0xdd, 0x27, 0xf1, 0x03, +0x44, 0x00, 0x00, 0x9f, 0xdd, 0x27, 0xf1, 0x10, 0x44, 0x00, 0x00, 0x1f, 0xdd, 0x27, 0xf2, 0x1e, +0xf0, 0x03, 0x84, 0x21, 0xdd, 0x26, 0xf2, 0x1d, 0xf0, 0x03, 0x84, 0x22, 0xdd, 0x26, 0xf2, 0x1c, +0xf0, 0x03, 0x44, 0x10, 0x00, 0x23, 0xdd, 0x26, 0xf2, 0x1b, 0xf0, 0x03, 0x44, 0x10, 0x00, 0x2a, +0xdd, 0x26, 0xf2, 0x1a, 0xf1, 0x03, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x19, 0x84, 0x22, 0x84, 0x04, +0xdd, 0x26, 0xf2, 0x18, 0x44, 0x10, 0x00, 0x22, 0x84, 0x04, 0xdd, 0x26, 0xf2, 0x17, 0x84, 0x23, +0x84, 0x05, 0xdd, 0x26, 0xf2, 0x16, 0x84, 0x24, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x15, 0x44, 0x10, +0x00, 0x11, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x14, 0x44, 0x10, 0x00, 0x12, 0x84, 0x05, 0xdd, 0x26, +0xf2, 0x13, 0x44, 0x10, 0x00, 0x13, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x12, 0x44, 0x10, 0x00, 0x14, +0x84, 0x05, 0xdd, 0x26, 0xf1, 0x11, 0x84, 0x04, 0xdd, 0x27, 0xec, 0x84, 0x3a, 0x6f, 0xaa, 0x84, +0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0x94, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, +0x06, 0x30, 0x96, 0x40, 0xf1, 0x82, 0x3a, 0x03, 0x08, 0x00, 0x50, 0x5f, 0x80, 0x2c, 0x80, 0x65, +0x3a, 0x01, 0x84, 0x24, 0x40, 0x41, 0x40, 0x09, 0xf0, 0x02, 0xac, 0x98, 0x10, 0x4f, 0x80, 0x36, +0xc0, 0x06, 0x84, 0x40, 0xf2, 0x87, 0xf2, 0x89, 0x48, 0x00, 0x02, 0xa3, 0x46, 0x70, 0x04, 0x10, +0x58, 0x73, 0x85, 0x0c, 0xb4, 0x87, 0x46, 0x80, 0x04, 0x10, 0xf4, 0x89, 0x58, 0x84, 0x05, 0x04, +0x05, 0xe4, 0x00, 0x00, 0xf1, 0x02, 0x15, 0xef, 0x80, 0x07, 0x47, 0xc0, 0x00, 0x06, 0x59, 0xce, +0x01, 0x84, 0x50, 0x2f, 0x80, 0x64, 0x84, 0x04, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x13, 0x50, 0x2f, +0x80, 0x60, 0x84, 0x04, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x11, 0x50, 0x2f, 0x80, 0x5c, 0x84, 0x05, +0xdd, 0x3c, 0x44, 0x10, 0x00, 0x12, 0x50, 0x2f, 0x80, 0x58, 0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, +0x00, 0x13, 0x50, 0x2f, 0x80, 0x54, 0x84, 0x05, 0xdd, 0x3c, 0x44, 0x10, 0x00, 0x14, 0x50, 0x2f, +0x80, 0x50, 0x84, 0x05, 0xdd, 0x3c, 0x84, 0x23, 0x50, 0x2f, 0x80, 0x4c, 0x84, 0x05, 0xdd, 0x3c, +0x84, 0x24, 0x50, 0x2f, 0x80, 0x48, 0x84, 0x05, 0xdd, 0x3c, 0xf1, 0x02, 0x46, 0xa0, 0x00, 0x06, +0x58, 0xa5, 0x02, 0x3c, 0x44, 0x20, 0x00, 0x87, 0x84, 0x04, 0xdd, 0x2a, 0x44, 0x10, 0x00, 0x13, +0x44, 0x20, 0x00, 0x24, 0x84, 0x04, 0xdd, 0x2a, 0x44, 0x10, 0x00, 0x11, 0x44, 0x20, 0x00, 0x80, +0x84, 0x05, 0xdd, 0x2a, 0x44, 0x10, 0x00, 0x12, 0x44, 0x20, 0x00, 0xc1, 0x84, 0x05, 0xdd, 0x2a, +0x44, 0x10, 0x00, 0x13, 0x44, 0x20, 0x00, 0x60, 0x84, 0x05, 0xdd, 0x2a, 0xf2, 0x02, 0x44, 0x10, +0x00, 0x14, 0x84, 0x05, 0xdd, 0x2a, 0x84, 0x23, 0x44, 0x20, 0x00, 0x3c, 0x84, 0x05, 0xdd, 0x2a, +0x84, 0x24, 0x44, 0x20, 0x00, 0x3c, 0x84, 0x05, 0xdd, 0x2a, 0xf0, 0x02, 0x46, 0x90, 0x00, 0x06, +0x58, 0x94, 0x82, 0xc4, 0x44, 0x10, 0x00, 0x17, 0x50, 0x2f, 0x80, 0x40, 0x4b, 0xe0, 0x24, 0x01, +0xf0, 0x02, 0x50, 0x2f, 0x80, 0x44, 0x84, 0x24, 0x4b, 0xe0, 0x24, 0x01, 0xf1, 0x02, 0x46, 0x60, +0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x84, 0x04, 0x4b, 0xe0, 0x18, 0x01, 0xf1, 0x02, 0x44, 0x00, +0x00, 0x17, 0x4b, 0xe0, 0x18, 0x01, 0x47, 0xc0, 0x00, 0x92, 0xf0, 0x02, 0x46, 0xa0, 0x00, 0xdf, +0x46, 0x90, 0x00, 0x92, 0x58, 0xa5, 0x08, 0x38, 0x58, 0x94, 0x80, 0x10, 0xb6, 0x08, 0x15, 0xc3, +0x80, 0x00, 0xb7, 0x48, 0xb7, 0x27, 0xf3, 0x02, 0x92, 0x00, 0x84, 0xa7, 0x9c, 0xd9, 0xdb, 0xfd, +0x46, 0x30, 0x04, 0x10, 0x46, 0x10, 0x00, 0x92, 0x58, 0x31, 0x85, 0x0c, 0x58, 0x10, 0x80, 0x30, +0xb6, 0x23, 0x84, 0x60, 0x92, 0x00, 0x84, 0x47, 0x9c, 0xd9, 0x4c, 0x31, 0x7f, 0xfd, 0x46, 0x70, +0x04, 0x10, 0x46, 0x80, 0x00, 0x92, 0x58, 0x73, 0x85, 0x0c, 0x58, 0x84, 0x00, 0x38, 0xb7, 0x07, +0x84, 0x60, 0x92, 0x00, 0x84, 0x07, 0x9c, 0xd9, 0x4c, 0x30, 0x7f, 0xfd, 0x46, 0x90, 0x00, 0x06, +0x58, 0x94, 0x84, 0x44, 0x84, 0x22, 0x44, 0x00, 0x00, 0x17, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x14, +0x44, 0x00, 0x00, 0xf1, 0xdd, 0x29, 0x44, 0x10, 0x00, 0x80, 0x44, 0x00, 0x00, 0xf2, 0xdd, 0x29, +0x44, 0x10, 0x00, 0x31, 0x44, 0x00, 0x00, 0xf4, 0xdd, 0x29, 0x84, 0x25, 0x44, 0x00, 0x00, 0x9e, +0xdd, 0x29, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x29, 0x85, 0x40, 0x84, 0x23, 0x44, 0x00, +0x00, 0x9e, 0xdd, 0x29, 0x14, 0xaf, 0x80, 0x03, 0x44, 0x00, 0x00, 0x9f, 0x44, 0x10, 0x00, 0x60, +0xdd, 0x29, 0xf6, 0x03, 0x50, 0x5f, 0x80, 0x38, 0xf6, 0x88, 0xf6, 0x86, 0xf6, 0x85, 0xf6, 0x84, +0x81, 0x26, 0x51, 0xef, 0x80, 0x2c, 0x38, 0x8f, 0x24, 0x00, 0x84, 0x23, 0x80, 0x48, 0x84, 0x05, +0xb6, 0xbf, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0x3c, 0xdd, 0x2f, 0x80, 0x48, 0x84, 0x24, +0x84, 0x05, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0x3c, 0xdd, 0x2f, 0x46, 0x70, 0x00, 0x06, +0x58, 0x73, 0x84, 0x44, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, 0x1c, 0x01, 0x45, 0xc0, +0x00, 0x93, 0x44, 0x00, 0x00, 0x9f, 0x44, 0x10, 0x00, 0x93, 0x4b, 0xe0, 0x1c, 0x01, 0x84, 0xc0, +0x15, 0xcf, 0x80, 0x0f, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x82, 0xc4, 0xd5, 0x1b, 0x9d, 0xb1, +0x44, 0x40, 0x03, 0xe9, 0x4c, 0x62, 0x00, 0x1d, 0x84, 0x20, 0xd5, 0x0a, 0x92, 0x00, 0x84, 0x67, +0x9c, 0x01, 0x4c, 0x01, 0xff, 0xfd, 0x9c, 0x49, 0x84, 0x4a, 0x4c, 0x11, 0x00, 0x04, 0x84, 0x00, +0xd5, 0xf6, 0xb6, 0xbf, 0x84, 0x00, 0x44, 0x10, 0x00, 0x9f, 0x50, 0x2f, 0x80, 0x3c, 0x4b, 0xe0, +0x1c, 0x01, 0xf0, 0x0f, 0x44, 0x10, 0x00, 0x93, 0xb4, 0xbf, 0x4c, 0x00, 0xbf, 0xe2, 0x87, 0x80, +0x46, 0xa0, 0x00, 0x06, 0x58, 0xa5, 0x04, 0x44, 0x44, 0x40, 0x10, 0x00, 0x87, 0xc0, 0x15, 0xef, +0x80, 0x0e, 0xf4, 0x81, 0xb6, 0xbf, 0x44, 0x10, 0x00, 0x1e, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x2a, +0x80, 0x3c, 0x44, 0x00, 0x00, 0x9f, 0xdd, 0x2a, 0x44, 0x10, 0x00, 0x22, 0x44, 0x00, 0x00, 0x9e, +0xdd, 0x2a, 0x46, 0x50, 0x00, 0x0b, 0x58, 0x52, 0x85, 0x6c, 0xb5, 0x1f, 0xb4, 0x05, 0x80, 0x48, +0x44, 0x10, 0x00, 0x9f, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf2, 0x0e, +0x44, 0x10, 0x00, 0x21, 0x44, 0x00, 0x00, 0x9e, 0x40, 0x81, 0x60, 0x08, 0xdd, 0x2a, 0x46, 0x30, +0x00, 0x0b, 0x58, 0x31, 0x85, 0x6c, 0xb4, 0xff, 0xb4, 0x03, 0x80, 0x47, 0x44, 0x10, 0x00, 0x9f, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf4, 0x0e, 0x44, 0x10, 0x00, 0x20, +0x44, 0x00, 0x00, 0x9e, 0x40, 0x72, 0x40, 0x08, 0x46, 0x60, 0x00, 0x0b, 0x58, 0x63, 0x05, 0x6c, +0xdd, 0x2a, 0xb4, 0x3f, 0xb4, 0x06, 0x80, 0x41, 0x44, 0x10, 0x00, 0x9f, 0x46, 0xf0, 0x00, 0x06, +0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf5, 0x0e, 0x44, 0x10, 0x00, 0x1f, 0x44, 0x00, 0x00, 0x9e, +0x40, 0x62, 0xa0, 0x08, 0xdd, 0x2a, 0xb4, 0x7f, 0x46, 0x20, 0x00, 0x0b, 0x58, 0x21, 0x05, 0x6c, +0xb4, 0x02, 0x44, 0x10, 0x00, 0x9f, 0x80, 0x43, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, +0xdd, 0x2f, 0x40, 0x44, 0x1c, 0x00, 0x04, 0x8f, 0x80, 0x0e, 0x54, 0x3e, 0x00, 0xff, 0x40, 0x52, +0x20, 0x00, 0x98, 0xae, 0xf4, 0x01, 0xb4, 0xbf, 0xe6, 0x62, 0xe8, 0x10, 0x46, 0x10, 0x08, 0x00, +0x40, 0x01, 0x04, 0x02, 0xc0, 0x10, 0x46, 0x80, 0x0f, 0xff, 0x58, 0x84, 0x0f, 0xff, 0x46, 0x7f, +0xf0, 0x00, 0x40, 0x61, 0x20, 0x02, 0x98, 0x37, 0xd5, 0x07, 0x87, 0xc4, 0x4c, 0x3f, 0x40, 0x04, +0x80, 0x02, 0xd5, 0x1d, 0x80, 0x02, 0xcb, 0x05, 0x40, 0x30, 0x10, 0x16, 0xf3, 0x84, 0xd5, 0x1b, +0x84, 0x21, 0x4c, 0x30, 0xc0, 0x06, 0x40, 0x20, 0x10, 0x16, 0xf2, 0x85, 0xd5, 0x14, 0x84, 0xc2, +0x4c, 0x33, 0x40, 0x06, 0x40, 0x01, 0x30, 0x09, 0xf0, 0x86, 0xd5, 0x0d, 0x84, 0xe3, 0x4c, 0x33, +0xc0, 0x07, 0x40, 0x81, 0x30, 0x09, 0x14, 0x8f, 0x80, 0x08, 0xd5, 0x05, 0x41, 0xe0, 0x10, 0x16, +0x15, 0xef, 0x80, 0x03, 0x51, 0xce, 0x00, 0x01, 0x84, 0x65, 0x4d, 0xc1, 0xff, 0x59, 0xf1, 0x06, +0xf4, 0x04, 0x42, 0x12, 0x10, 0x75, 0xf1, 0x8f, 0x5c, 0xf0, 0xa7, 0x10, 0xe8, 0x38, 0x5c, 0xf0, +0x80, 0x65, 0xe8, 0x04, 0x50, 0x04, 0x80, 0x09, 0xd5, 0x2d, 0x5c, 0xf0, 0x80, 0x9f, 0xe8, 0x04, +0x50, 0x04, 0x80, 0x08, 0xd5, 0x27, 0x5c, 0xf0, 0x80, 0xfc, 0xe8, 0x04, 0x50, 0x04, 0x80, 0x07, +0xd5, 0x21, 0x5c, 0xf0, 0x81, 0x8f, 0xe8, 0x04, 0x50, 0x04, 0x80, 0x06, 0xd5, 0x1b, 0x5c, 0xf0, +0x82, 0x77, 0xe8, 0x04, 0x50, 0x04, 0x80, 0x05, 0xd5, 0x15, 0x5c, 0xf0, 0x83, 0xe9, 0xe8, 0x04, +0x50, 0x04, 0x80, 0x04, 0xd5, 0x0f, 0x5c, 0xf0, 0x86, 0x31, 0xe8, 0x04, 0x50, 0x04, 0x80, 0x03, +0xd5, 0x09, 0x5c, 0xf0, 0x89, 0xd0, 0xe8, 0x04, 0x50, 0x04, 0x80, 0x02, 0xd5, 0x03, 0x50, 0x04, +0x80, 0x01, 0x54, 0x90, 0x00, 0xff, 0xe7, 0x2b, 0x4e, 0xf3, 0xfe, 0xc5, 0xf0, 0x04, 0xf6, 0x06, +0x44, 0x80, 0x00, 0x64, 0x42, 0x60, 0x00, 0x75, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x84, 0x28, +0x42, 0x03, 0x20, 0x24, 0x4b, 0xe0, 0x1c, 0x01, 0xf1, 0x08, 0xf2, 0x05, 0x80, 0xc0, 0x42, 0x11, +0x08, 0x75, 0x42, 0x00, 0xa0, 0x24, 0x4b, 0xe0, 0x1c, 0x01, 0x50, 0x53, 0x7c, 0x18, 0x80, 0x60, +0x5c, 0xf2, 0x81, 0x91, 0xe8, 0x48, 0x9b, 0x30, 0x5e, 0xf2, 0x00, 0x71, 0xe8, 0x44, 0x5e, 0xf2, +0x7f, 0x90, 0xe9, 0x41, 0xf0, 0x04, 0x51, 0xe0, 0x00, 0x20, 0x5c, 0xff, 0x00, 0x41, 0xe8, 0x3b, +0xf1, 0x05, 0x50, 0x40, 0x80, 0x20, 0x5c, 0xf2, 0x00, 0x41, 0xe8, 0x35, 0x44, 0x70, 0x03, 0xe8, +0x42, 0x21, 0x9c, 0x24, 0x04, 0x8f, 0x80, 0x03, 0x44, 0x50, 0x59, 0x88, 0x42, 0x80, 0x80, 0x75, +0x40, 0x01, 0x18, 0x96, 0x42, 0x84, 0x14, 0x24, 0x42, 0x41, 0x98, 0x24, 0x46, 0x50, 0x00, 0x0e, +0x58, 0x52, 0x84, 0x58, 0x46, 0x30, 0x00, 0x0e, 0x58, 0x31, 0x84, 0x54, 0x51, 0xe0, 0x7c, 0x18, +0x40, 0x24, 0x10, 0xd6, 0x50, 0x70, 0x03, 0xe8, 0x40, 0x6f, 0x20, 0x08, 0x40, 0x43, 0x1c, 0xf6, +0x50, 0x11, 0x00, 0x0c, 0xb6, 0x45, 0xb6, 0x83, 0xe6, 0x39, 0xe9, 0x03, 0x84, 0x20, 0xb6, 0x25, +0x9c, 0xe7, 0xe6, 0x6f, 0xe9, 0x15, 0x84, 0x00, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x04, 0x54, +0xb6, 0x06, 0xd5, 0x0e, 0x87, 0xc0, 0x46, 0x50, 0x00, 0x0e, 0x58, 0x52, 0x84, 0x58, 0x46, 0x40, +0x00, 0x0e, 0x58, 0x42, 0x04, 0x54, 0x15, 0xe2, 0x80, 0x00, 0x15, 0xe2, 0x00, 0x00, 0x46, 0x60, +0x00, 0x06, 0x58, 0x63, 0x04, 0x44, 0x84, 0x23, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0x50, 0x2f, +0x80, 0x3c, 0x44, 0x10, 0x00, 0x9f, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, +0xdd, 0x2f, 0xf5, 0x0f, 0x44, 0x00, 0x00, 0x9f, 0x58, 0x12, 0x80, 0x07, 0xdd, 0x26, 0x44, 0x10, +0x00, 0x37, 0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0x54, +0xb4, 0x80, 0x44, 0x00, 0x00, 0x9f, 0x54, 0x12, 0x00, 0x3f, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x35, +0x44, 0x00, 0x00, 0x9e, 0xdd, 0x26, 0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x84, 0x58, 0xb4, 0x61, +0x44, 0x00, 0x00, 0x9f, 0x54, 0x11, 0x80, 0x3f, 0xdd, 0x26, 0x84, 0x20, 0x44, 0x00, 0x00, 0x9e, +0xdd, 0x26, 0x44, 0x00, 0x00, 0x9f, 0x84, 0x20, 0xdd, 0x26, 0xf2, 0x02, 0x4e, 0x23, 0x00, 0x9e, +0x46, 0x60, 0x04, 0x10, 0x47, 0xe0, 0x00, 0x92, 0x58, 0x63, 0x05, 0x0c, 0x59, 0xef, 0x00, 0x18, +0x15, 0xe3, 0x00, 0x00, 0xf1, 0x02, 0x92, 0x00, 0x84, 0x47, 0x9c, 0x49, 0x4c, 0x11, 0x7f, 0xfd, +0x46, 0x30, 0x04, 0x10, 0x46, 0x10, 0x00, 0x92, 0x58, 0x31, 0x85, 0x0c, 0x58, 0x10, 0x80, 0x08, +0xb6, 0x23, 0x84, 0x00, 0x92, 0x00, 0x84, 0x87, 0x9c, 0x01, 0x4c, 0x02, 0x7f, 0xfd, 0x46, 0x00, +0x04, 0x10, 0x46, 0x50, 0x00, 0x92, 0x58, 0x00, 0x05, 0x0c, 0xb6, 0xa0, 0x84, 0x00, 0x92, 0x00, +0x84, 0xc7, 0x9c, 0x01, 0x4c, 0x03, 0x7f, 0xfd, 0xf1, 0x10, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, +0x04, 0x44, 0x44, 0x00, 0x00, 0x17, 0xdd, 0x26, 0xf1, 0x11, 0x84, 0x04, 0xdd, 0x26, 0x84, 0x20, +0x44, 0x00, 0x00, 0xf4, 0xdd, 0x26, 0x44, 0x10, 0x00, 0x15, 0x50, 0x2f, 0x80, 0x3c, 0x84, 0x00, +0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x82, 0xc4, 0xdd, 0x2f, 0xf3, 0x0f, 0x44, 0x00, 0x00, 0x15, +0x58, 0x21, 0x80, 0x01, 0xf2, 0x8f, 0x80, 0x22, 0xdd, 0x26, 0x84, 0x00, 0xd5, 0x0a, 0x92, 0x00, +0x87, 0xc7, 0x9c, 0x49, 0x4c, 0x1f, 0x7f, 0xfd, 0x9c, 0x01, 0x84, 0x2a, 0x4c, 0x00, 0x80, 0x04, +0x84, 0x20, 0xd5, 0xf6, 0xf3, 0x0f, 0x44, 0x00, 0x00, 0x15, 0x54, 0x21, 0x80, 0xfe, 0x80, 0x22, +0xf2, 0x8f, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x84, 0x44, 0xdd, 0x2f, 0x46, 0x40, 0x04, 0x10, +0x58, 0x42, 0x05, 0x04, 0x84, 0x20, 0xb6, 0x24, 0x46, 0x50, 0x04, 0x10, 0xf6, 0x09, 0x58, 0x52, +0x85, 0x0c, 0xb6, 0xc5, 0x46, 0x60, 0x00, 0x06, 0x58, 0x63, 0x02, 0x3c, 0xf0, 0x07, 0xb6, 0x04, +0x84, 0x04, 0xf2, 0x19, 0xdd, 0x26, 0xf2, 0x18, 0x44, 0x10, 0x00, 0x13, 0x84, 0x04, 0xdd, 0x26, +0xf2, 0x17, 0x44, 0x10, 0x00, 0x11, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x16, 0x44, 0x10, 0x00, 0x12, +0x84, 0x05, 0xdd, 0x26, 0xf2, 0x15, 0x44, 0x10, 0x00, 0x13, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x14, +0x44, 0x10, 0x00, 0x14, 0x84, 0x05, 0xdd, 0x26, 0xf2, 0x13, 0x84, 0x23, 0x84, 0x05, 0xdd, 0x26, +0xf2, 0x12, 0x84, 0x05, 0x84, 0x24, 0xdd, 0x26, 0xec, 0x6c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x96, 0x49, 0xe6, 0x24, 0xe8, 0x03, 0x84, 0x01, 0xd5, 0x61, +0xb4, 0x20, 0x84, 0xa5, 0xd1, 0x2c, 0xe4, 0x26, 0xe8, 0x09, 0x84, 0xa3, 0xd1, 0x17, 0xe4, 0x24, +0xe8, 0x1b, 0x84, 0x01, 0x4c, 0x10, 0x40, 0x55, 0xd5, 0x0b, 0x84, 0x47, 0x4c, 0x11, 0x00, 0x3b, +0xe0, 0x22, 0xe9, 0x26, 0x84, 0xa8, 0xd1, 0x3e, 0x84, 0xa9, 0xd1, 0x45, 0xd5, 0x49, 0x46, 0xf0, +0x00, 0x06, 0x58, 0xf7, 0x89, 0xb4, 0xdd, 0x2f, 0xd5, 0x43, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x84, 0x9c, 0xdd, 0x2f, 0xd5, 0x3d, 0x9c, 0x44, 0x05, 0xe0, 0x80, 0x00, 0x54, 0x0f, 0x00, 0x01, +0x46, 0xf0, 0x00, 0x08, 0x58, 0xf7, 0x88, 0x84, 0xdd, 0x2f, 0xd5, 0x32, 0x9c, 0xc4, 0xb4, 0x43, +0x96, 0x14, 0x46, 0xf0, 0x00, 0x09, 0x58, 0xf7, 0x80, 0x4c, 0xdd, 0x2f, 0xd5, 0x29, 0x9c, 0x04, +0x05, 0xe0, 0x00, 0x00, 0xb4, 0x20, 0xb4, 0x80, 0x40, 0x50, 0xa0, 0x09, 0x54, 0x0f, 0x00, 0xff, +0x96, 0x68, 0x42, 0x22, 0x40, 0x0b, 0x46, 0xf0, 0x00, 0x07, 0x58, 0xf7, 0x86, 0x44, 0xdd, 0x2f, +0xd5, 0x17, 0x9c, 0x84, 0xb4, 0x02, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x8e, 0x04, 0xdd, 0x2f, +0xd5, 0x0f, 0x9d, 0x04, 0xb4, 0x64, 0x96, 0x1c, 0x46, 0xf0, 0x00, 0x09, 0x58, 0xf7, 0x89, 0x04, +0xdd, 0x2f, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, 0x83, 0x88, 0xdd, 0x2f, 0x84, 0x00, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x46, 0x20, +0x04, 0x10, 0x04, 0x61, 0x01, 0x05, 0x40, 0x03, 0x38, 0x08, 0x92, 0x1f, 0xc0, 0x14, 0x46, 0xf0, +0x00, 0x0e, 0x00, 0x37, 0x87, 0xe1, 0x84, 0xa1, 0xdb, 0x0e, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, +0x81, 0xf9, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x07, 0xf0, 0x46, 0xf0, 0x00, 0x00, 0x58, 0xf7, +0x82, 0x54, 0xdd, 0x2f, 0x47, 0xe0, 0x04, 0x10, 0x14, 0x6f, 0x01, 0x05, 0x04, 0x5f, 0x01, 0x05, +0xf5, 0x81, 0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, +0xef, 0xc4, 0x84, 0xa1, 0x46, 0x40, 0x00, 0x0e, 0x58, 0x42, 0x04, 0x8a, 0x84, 0x60, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x04, 0x8b, 0xaf, 0x60, 0x46, 0x60, 0x04, 0x00, 0xae, 0xc0, 0x58, 0x63, +0x02, 0x14, 0x05, 0xc3, 0x00, 0x00, 0x45, 0xef, 0xef, 0xff, 0x40, 0xae, 0x78, 0x02, 0xb7, 0x46, +0x46, 0x70, 0x04, 0x00, 0x58, 0x73, 0x84, 0x18, 0xb5, 0x27, 0x44, 0x6f, 0xff, 0x7f, 0x40, 0x84, +0x98, 0x02, 0xb7, 0x07, 0x46, 0x30, 0x04, 0x00, 0x58, 0x31, 0x82, 0x58, 0xb4, 0xa3, 0x46, 0x7f, +0x0f, 0xff, 0x58, 0x73, 0x8f, 0xff, 0x47, 0xe0, 0xa0, 0x00, 0x54, 0xa0, 0x80, 0xff, 0x40, 0x12, +0x9c, 0x02, 0x40, 0x40, 0xf8, 0x04, 0x84, 0x05, 0xb6, 0x83, 0x4c, 0xa0, 0x41, 0x64, 0x47, 0xc0, +0x04, 0x10, 0x15, 0xcf, 0x80, 0x04, 0x47, 0xe0, 0x0c, 0x2d, 0x15, 0xef, 0x80, 0x01, 0x05, 0xef, +0x80, 0x04, 0x46, 0x00, 0x04, 0x10, 0x59, 0xef, 0x07, 0x20, 0x15, 0xef, 0x80, 0x04, 0x05, 0xef, +0x80, 0x01, 0x58, 0x00, 0x00, 0x80, 0x59, 0xef, 0x0f, 0xc0, 0x15, 0xef, 0x80, 0x01, 0x46, 0x10, +0x04, 0x10, 0x05, 0xe0, 0x00, 0x00, 0x58, 0x10, 0x80, 0xc0, 0x15, 0xef, 0x80, 0x0b, 0x46, 0x50, +0x04, 0x10, 0x05, 0xe0, 0x80, 0x00, 0x58, 0x52, 0x80, 0x04, 0x15, 0xef, 0x80, 0x0a, 0x46, 0x60, +0x04, 0x10, 0x05, 0xe2, 0x80, 0x00, 0x58, 0x63, 0x07, 0x08, 0x15, 0xef, 0x80, 0x09, 0x46, 0x90, +0x04, 0x10, 0x05, 0xe3, 0x00, 0x00, 0x58, 0x94, 0x80, 0x20, 0x15, 0xef, 0x80, 0x08, 0x46, 0x30, +0x04, 0x10, 0x05, 0xe4, 0x80, 0x00, 0x58, 0x31, 0x80, 0x78, 0x15, 0xef, 0x80, 0x07, 0x46, 0x4f, +0x02, 0x10, 0x05, 0xe1, 0x80, 0x00, 0x15, 0xef, 0x80, 0x06, 0x05, 0xef, 0x80, 0x04, 0x46, 0x7f, +0xf0, 0x00, 0x05, 0xef, 0x00, 0x00, 0x46, 0x80, 0x04, 0x10, 0x47, 0xc0, 0x18, 0x00, 0x15, 0xef, +0x80, 0x05, 0x58, 0x84, 0x00, 0x3c, 0xb6, 0x80, 0x44, 0x40, 0x00, 0x10, 0x44, 0x00, 0x00, 0xc8, +0x59, 0xce, 0x00, 0x80, 0xb6, 0xe1, 0xb6, 0x85, 0xb6, 0x06, 0x15, 0xc4, 0x00, 0x00, 0x47, 0xe0, +0x00, 0x0e, 0x59, 0xef, 0x03, 0xc8, 0xf7, 0x01, 0x84, 0xc1, 0xb6, 0xe9, 0xb6, 0xde, 0xf2, 0x82, +0xf3, 0x83, 0x46, 0x70, 0x00, 0x04, 0x58, 0x73, 0x86, 0xe8, 0x80, 0x0a, 0xdd, 0x27, 0x46, 0x10, +0x0c, 0x2d, 0x58, 0x10, 0x8f, 0x80, 0xb6, 0x29, 0x46, 0x28, 0x00, 0x00, 0xf5, 0x03, 0xb6, 0x45, +0x46, 0x00, 0x19, 0xc0, 0xf3, 0x04, 0x84, 0x84, 0x58, 0x00, 0x00, 0x80, 0xb6, 0x83, 0x46, 0x60, +0x19, 0xc0, 0xb6, 0x08, 0x58, 0x63, 0x00, 0x90, 0x80, 0x0a, 0xdd, 0x27, 0xb6, 0xc8, 0x84, 0x0a, +0xdd, 0x27, 0x46, 0x10, 0x19, 0x40, 0x58, 0x10, 0x80, 0x90, 0xb6, 0x28, 0x84, 0x0a, 0xdd, 0x27, +0x46, 0x20, 0x18, 0x40, 0x58, 0x21, 0x00, 0x90, 0xb6, 0x48, 0x84, 0x0a, 0xdd, 0x27, 0x46, 0x00, +0x04, 0x00, 0xf2, 0x02, 0x58, 0x00, 0x00, 0x88, 0xb4, 0x20, 0xc2, 0x09, 0x46, 0x3f, 0xf0, 0x00, +0x40, 0x60, 0x8c, 0x02, 0x98, 0x96, 0x42, 0x81, 0x7c, 0x08, 0xb7, 0x00, 0x64, 0x00, 0x00, 0x00, +0x84, 0x00, 0x46, 0x40, 0x00, 0x0e, 0x58, 0x42, 0x04, 0x8a, 0x46, 0x80, 0x00, 0x0e, 0x58, 0x84, +0x04, 0x8b, 0xae, 0x20, 0x46, 0x30, 0x04, 0x00, 0x10, 0x04, 0x00, 0x00, 0x58, 0x31, 0x82, 0x14, +0xb4, 0x23, 0x47, 0xe0, 0x04, 0x00, 0x58, 0x50, 0x90, 0x00, 0xb6, 0xa3, 0x59, 0xef, 0x04, 0x18, +0xb4, 0xde, 0x46, 0x80, 0x04, 0x10, 0x46, 0x70, 0x19, 0x40, 0x58, 0x84, 0x00, 0x3c, 0x58, 0x23, +0x00, 0x80, 0x58, 0x73, 0x80, 0x90, 0xb6, 0x5e, 0xb6, 0xe8, 0x44, 0x00, 0x08, 0x98, 0x46, 0x70, +0x00, 0x04, 0x58, 0x73, 0x86, 0xe8, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x40, 0x19, 0xc0, 0x58, 0x42, +0x00, 0x90, 0xb6, 0x88, 0x84, 0x0a, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x00, 0x19, 0x80, 0x46, 0x50, +0x04, 0x10, 0x46, 0x10, 0x0c, 0x0d, 0x58, 0x00, 0x00, 0x90, 0x58, 0x52, 0x80, 0x20, 0x58, 0x10, +0x8f, 0xc0, 0xb6, 0x08, 0x46, 0x80, 0x04, 0x00, 0xb6, 0x25, 0x58, 0x84, 0x00, 0x20, 0x84, 0xc0, +0xb4, 0xa8, 0x46, 0x30, 0x04, 0x00, 0xf5, 0x8d, 0xf2, 0x0d, 0x84, 0x04, 0x41, 0xe1, 0x0c, 0x02, +0x4f, 0xe3, 0x00, 0x0a, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x10, 0x07, 0xd1, 0x4c, 0x60, 0x80, 0x04, +0x9d, 0xb1, 0xd5, 0xef, 0x46, 0x70, 0x04, 0x10, 0x46, 0x60, 0x0c, 0x0d, 0x58, 0x73, 0x80, 0x20, +0x58, 0x63, 0x0f, 0xc8, 0xb6, 0xc7, 0x46, 0x70, 0x04, 0x00, 0x58, 0x73, 0x80, 0x20, 0x84, 0xc0, +0x46, 0x80, 0x00, 0x04, 0x58, 0x84, 0x06, 0xe8, 0xb4, 0x67, 0x46, 0x20, 0x08, 0x00, 0xf3, 0x8d, +0x05, 0xef, 0x80, 0x0d, 0x84, 0x04, 0x40, 0x4f, 0x08, 0x02, 0xcc, 0x09, 0x4b, 0xe0, 0x20, 0x01, +0x44, 0x00, 0x0b, 0xb9, 0x4c, 0x60, 0x00, 0x04, 0x9d, 0xb1, 0xd5, 0xef, 0x46, 0x70, 0x04, 0x10, +0x58, 0x73, 0x80, 0x3c, 0x84, 0x20, 0xb6, 0x27, 0x46, 0x80, 0x04, 0x10, 0x05, 0xef, 0x80, 0x0b, +0x58, 0x84, 0x00, 0x80, 0x15, 0xe4, 0x00, 0x00, 0x46, 0x60, 0x04, 0x10, 0xf7, 0x0a, 0x58, 0x63, +0x00, 0xc0, 0xb6, 0xe6, 0x46, 0x50, 0x04, 0x10, 0xf6, 0x09, 0x58, 0x52, 0x80, 0x04, 0xb6, 0xc5, +0x46, 0x40, 0x04, 0x10, 0xf7, 0x08, 0x58, 0x42, 0x07, 0x08, 0xb6, 0xe4, 0x46, 0x30, 0x04, 0x10, +0x05, 0xef, 0x80, 0x07, 0x58, 0x31, 0x80, 0x20, 0x15, 0xe1, 0x80, 0x00, 0x46, 0x20, 0x04, 0x10, +0xf3, 0x06, 0x58, 0x21, 0x00, 0x78, 0xb6, 0x62, 0x46, 0x00, 0x04, 0x10, 0xf4, 0x05, 0x58, 0x00, +0x07, 0x20, 0x46, 0x50, 0x00, 0x0e, 0x58, 0x52, 0x83, 0xc8, 0xb6, 0x80, 0xb6, 0x25, 0x48, 0x00, +0x01, 0x34, 0x51, 0xc5, 0x7f, 0xff, 0x54, 0x9e, 0x00, 0xff, 0xe7, 0x24, 0x4e, 0xf2, 0x01, 0x2d, +0x46, 0x40, 0x04, 0x00, 0x58, 0x42, 0x00, 0x64, 0x46, 0x60, 0x04, 0x00, 0xb4, 0xa4, 0x58, 0x63, +0x00, 0x38, 0x46, 0x31, 0x00, 0x00, 0xb4, 0x26, 0x44, 0x0f, 0xe0, 0x00, 0x40, 0x82, 0x8c, 0x02, +0x40, 0x40, 0x80, 0x02, 0x4e, 0x82, 0x00, 0x05, 0x58, 0x42, 0x00, 0x13, 0xd5, 0x03, 0x58, 0x42, +0x00, 0x27, 0x46, 0x80, 0x04, 0x00, 0x58, 0x84, 0x00, 0x38, 0xb6, 0x88, 0x46, 0x70, 0x04, 0x00, +0x58, 0x73, 0x82, 0x08, 0xb5, 0x07, 0x05, 0xc3, 0x80, 0x00, 0x45, 0xef, 0xef, 0x37, 0x40, 0x9e, +0x78, 0x02, 0xb7, 0x27, 0xe7, 0x43, 0xe9, 0x13, 0x46, 0x50, 0x04, 0x00, 0x58, 0x52, 0x80, 0x80, +0xb4, 0xc5, 0x44, 0x1f, 0xff, 0xef, 0x40, 0x33, 0x04, 0x02, 0xb6, 0x65, 0x84, 0x05, 0xf2, 0x82, +0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0xe8, 0xdd, 0x2f, 0xf2, 0x02, 0x47, 0xc0, 0x04, 0x00, +0x46, 0x60, 0x04, 0x00, 0x59, 0xce, 0x00, 0xc0, 0x58, 0x63, 0x00, 0x80, 0xb5, 0x3c, 0xb4, 0xe6, +0x84, 0x3d, 0x40, 0x43, 0x84, 0x02, 0xb6, 0x86, 0x84, 0x05, 0xb4, 0xbc, 0x41, 0xe2, 0x84, 0x02, +0x15, 0xee, 0x00, 0x00, 0xf2, 0x82, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x86, 0xe8, 0xdd, 0x2f, +0xb4, 0x46, 0x87, 0xde, 0x40, 0x31, 0x78, 0x02, 0xb6, 0x66, 0x46, 0x10, 0x04, 0x00, 0xb4, 0xfc, +0x58, 0x10, 0x82, 0x14, 0x40, 0x73, 0xf8, 0x02, 0xb6, 0xfc, 0x46, 0x20, 0x04, 0x00, 0xb4, 0x81, +0x58, 0x21, 0x02, 0x58, 0x42, 0x02, 0x3c, 0x08, 0xb6, 0x01, 0x46, 0x6f, 0x0f, 0xff, 0xb4, 0xa2, +0x58, 0x63, 0x0f, 0xff, 0x47, 0xc0, 0xa0, 0x00, 0x40, 0x42, 0x98, 0x02, 0x40, 0x02, 0x70, 0x04, +0xb6, 0x02, 0x46, 0x30, 0x04, 0x00, 0xf2, 0x02, 0x58, 0x31, 0x80, 0x88, 0xb4, 0x83, 0xc2, 0x0c, +0x46, 0x7f, 0xf0, 0x00, 0x40, 0x62, 0x1c, 0x02, 0x47, 0xe8, 0x00, 0x00, 0x41, 0xc1, 0x18, 0x00, +0x40, 0x0e, 0x78, 0x04, 0xb6, 0x03, 0x47, 0xc0, 0x04, 0x00, 0x59, 0xce, 0x00, 0x80, 0xb4, 0x3c, +0x46, 0x50, 0x04, 0x00, 0x58, 0x30, 0x80, 0x40, 0xb6, 0x7c, 0x58, 0x52, 0x80, 0x04, 0xb4, 0xc5, +0x84, 0x1b, 0x40, 0x43, 0x00, 0x02, 0xb6, 0x85, 0x46, 0x30, 0x04, 0x00, 0x58, 0x31, 0x80, 0x20, +0xb4, 0x23, 0x46, 0x00, 0x04, 0x00, 0x58, 0x50, 0x90, 0x00, 0xb6, 0xa3, 0x58, 0x00, 0x00, 0x3c, +0xb4, 0xdc, 0x46, 0x1f, 0x00, 0x00, 0x58, 0x43, 0x00, 0x20, 0xb6, 0x9c, 0xb4, 0x60, 0x84, 0xa3, +0x40, 0x31, 0x84, 0x02, 0x4c, 0xa2, 0x80, 0x0d, 0x87, 0x84, 0x4c, 0xae, 0x00, 0x06, 0x84, 0xa2, +0x4c, 0xa2, 0xc0, 0x0f, 0xd5, 0x09, 0x44, 0x70, 0xef, 0x01, 0x98, 0xdf, 0xd5, 0x0c, 0x45, 0xe0, +0xe3, 0x01, 0x88, 0x7e, 0xd5, 0x08, 0x44, 0x40, 0xc0, 0x01, 0x98, 0xdc, 0xd5, 0x04, 0x44, 0x60, +0x80, 0x01, 0x98, 0xde, 0x46, 0x10, 0x04, 0x00, 0x58, 0x10, 0x80, 0x3c, 0x46, 0x50, 0x00, 0x0e, +0x58, 0x52, 0x84, 0x88, 0x84, 0x00, 0xb6, 0x61, 0xae, 0x28, 0xa6, 0xe8, 0xcb, 0x04, 0x64, 0x00, +0x00, 0x20, 0xd5, 0xfc, 0x44, 0x60, 0x03, 0xe8, 0x40, 0x21, 0x18, 0x77, 0x46, 0x50, 0x00, 0x0e, +0x58, 0x52, 0x83, 0xb8, 0xb4, 0xc5, 0x46, 0x40, 0x04, 0x00, 0x58, 0x42, 0x02, 0x14, 0x47, 0xc0, +0x04, 0x00, 0x59, 0xce, 0x04, 0x18, 0x98, 0xd6, 0xb6, 0x65, 0xb4, 0x24, 0x58, 0x00, 0x90, 0x00, +0xb6, 0x04, 0xb4, 0xbc, 0x58, 0x22, 0x80, 0x80, 0xb6, 0x5c, 0xe7, 0x43, 0xe9, 0x09, 0x47, 0xc0, +0x04, 0x00, 0x59, 0xce, 0x00, 0x80, 0xb4, 0x9c, 0x58, 0x02, 0x00, 0x10, 0xb6, 0x1c, 0x47, 0xc0, +0x04, 0x00, 0x59, 0xce, 0x00, 0x80, 0xb4, 0x1c, 0x46, 0x20, 0x04, 0x00, 0x58, 0x10, 0x00, 0x02, +0xb6, 0x3c, 0x58, 0x21, 0x00, 0xc0, 0xb4, 0x7c, 0x46, 0x10, 0x04, 0x00, 0x58, 0x51, 0x80, 0x01, +0xb6, 0xbc, 0xb7, 0x22, 0x58, 0x10, 0x80, 0x20, 0xb4, 0x01, 0x44, 0x4f, 0xef, 0xff, 0x40, 0x30, +0x10, 0x02, 0xb6, 0x61, 0x46, 0x20, 0x04, 0x00, 0xb4, 0x9c, 0x46, 0x10, 0x04, 0x00, 0x44, 0x5f, +0xff, 0xdf, 0x58, 0x21, 0x00, 0x3c, 0x40, 0x02, 0x14, 0x02, 0x58, 0x10, 0x82, 0x08, 0x84, 0x60, +0xb6, 0x1c, 0xb6, 0x62, 0xb7, 0x01, 0x84, 0x60, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0x8a, +0x46, 0x10, 0x00, 0x0e, 0x58, 0x10, 0x84, 0x8b, 0xae, 0xc0, 0x46, 0x40, 0x04, 0x00, 0xae, 0xc8, +0x58, 0x42, 0x00, 0x20, 0xb4, 0xa4, 0x58, 0x22, 0x80, 0x40, 0xb6, 0x44, 0xec, 0x3c, 0x3a, 0x6f, +0xaa, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, +0x02, 0x14, 0x84, 0xa0, 0xb4, 0xc0, 0xb6, 0xa0, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x37, 0x87, 0xed, +0x96, 0x48, 0xc3, 0x04, 0x44, 0x30, 0x80, 0x02, 0xd5, 0x03, 0x44, 0x30, 0x80, 0x06, 0xb6, 0x60, +0x46, 0x70, 0x04, 0x00, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x81, 0x6c, 0xdd, 0x2f, +0x14, 0x63, 0x80, 0x85, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x07, 0x87, 0xdc, 0x84, 0xa1, 0xd8, 0x2a, +0x84, 0xc0, 0xf6, 0x81, 0x46, 0x70, 0x00, 0x06, 0x58, 0x73, 0x82, 0x3c, 0x84, 0x24, 0x84, 0x4a, +0x80, 0x06, 0x4b, 0xe0, 0x1c, 0x01, 0x84, 0x25, 0x44, 0x20, 0x00, 0x20, 0x80, 0x06, 0x4b, 0xe0, +0x1c, 0x01, 0x84, 0x24, 0x40, 0x2f, 0x84, 0x00, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x06, 0x58, 0xf7, +0x81, 0x84, 0xdd, 0x2f, 0xf4, 0x01, 0x80, 0x06, 0x58, 0x32, 0x00, 0x80, 0xf3, 0x81, 0x80, 0x43, +0x84, 0x24, 0x4b, 0xe0, 0x1c, 0x01, 0x84, 0x02, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8d, 0xe0, +0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, +0xef, 0xfc, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x17, 0x87, 0xdc, 0xc1, 0x1a, 0x46, 0xf0, 0x00, 0x0e, +0x00, 0x37, 0x87, 0x28, 0x84, 0xa1, 0xd3, 0x14, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, 0x81, 0xf9, +0x44, 0x00, 0x03, 0xe8, 0x42, 0x50, 0x80, 0x24, 0x45, 0xe1, 0x73, 0x16, 0x84, 0x00, 0x40, 0x2f, +0x14, 0x01, 0x84, 0x21, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x87, 0x34, 0xdd, 0x2f, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x44, 0x20, 0x00, 0x34, +0x96, 0x00, 0x96, 0x48, 0x4c, 0x01, 0x40, 0x49, 0x46, 0xf0, 0x00, 0x0e, 0x00, 0x07, 0x87, 0xe1, +0xc8, 0x06, 0x46, 0x10, 0x04, 0x11, 0x04, 0x00, 0x80, 0x49, 0xd5, 0x3e, 0x84, 0x81, 0x4c, 0x02, +0x40, 0x3c, 0x4c, 0x10, 0x00, 0x38, 0x84, 0xa2, 0xd9, 0x04, 0x44, 0x00, 0x00, 0xc8, 0xd5, 0x11, +0x84, 0xa3, 0xd1, 0x0d, 0x84, 0xa4, 0xd1, 0x0b, 0x56, 0x10, 0x80, 0x05, 0x44, 0x20, 0x15, 0x7c, +0x84, 0x60, 0x40, 0x01, 0x84, 0x1b, 0x40, 0x01, 0x04, 0x1a, 0xd5, 0x03, 0x44, 0x00, 0x07, 0xd0, +0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x07, 0xdc, 0xa0, 0xb2, 0x44, 0x10, 0x03, 0xe8, 0x42, 0x51, +0x04, 0x24, 0x45, 0xe1, 0x73, 0x18, 0x40, 0x4f, 0x14, 0x01, 0xa6, 0x74, 0x9a, 0xa0, 0x84, 0x00, +0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x87, 0x34, 0xdd, 0x2f, 0x00, 0x03, 0x00, 0x11, 0xc0, 0x0c, +0x46, 0x30, 0x04, 0x01, 0x04, 0x41, 0x81, 0xa3, 0x58, 0x02, 0x00, 0x40, 0x14, 0x01, 0x81, 0xa3, +0xd5, 0x03, 0x84, 0x02, 0xd5, 0xde, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, +0xef, 0xfc, 0x96, 0x49, 0xe6, 0x28, 0xe8, 0x04, 0x84, 0x01, 0x48, 0x00, 0x00, 0xc0, 0x80, 0x60, +0xa2, 0x99, 0x44, 0x40, 0x00, 0x30, 0xb4, 0x23, 0x4c, 0x22, 0x40, 0x06, 0x80, 0x02, 0x96, 0x48, +0x84, 0x40, 0xd5, 0x4b, 0x44, 0x50, 0x00, 0x31, 0xda, 0x0b, 0x46, 0x00, 0x04, 0x00, 0x04, 0x30, +0x00, 0x20, 0x58, 0x21, 0x80, 0x13, 0x14, 0x20, 0x00, 0x20, 0x48, 0x00, 0x00, 0xa7, 0x9d, 0x62, +0xda, 0x42, 0x84, 0x81, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x47, 0x84, 0x89, 0x50, 0x80, 0x00, 0x0c, +0x50, 0x90, 0x00, 0x08, 0x84, 0xe1, 0xb4, 0x89, 0xb4, 0x68, 0x4c, 0x13, 0x80, 0x9c, 0x84, 0xa2, +0xd9, 0x04, 0x44, 0x00, 0x00, 0xc8, 0xd5, 0x13, 0x84, 0x03, 0x4c, 0x10, 0x00, 0x0f, 0x84, 0x44, +0x4c, 0x11, 0x00, 0x0c, 0x56, 0x60, 0x80, 0x05, 0x44, 0x70, 0x15, 0x7c, 0x85, 0x00, 0x40, 0x04, +0x18, 0x1b, 0x40, 0x03, 0x98, 0x1a, 0xd5, 0x03, 0x44, 0x00, 0x07, 0xd0, 0x46, 0x80, 0x04, 0x11, +0x04, 0x24, 0x00, 0x49, 0x44, 0x70, 0x03, 0xe8, 0x43, 0xe1, 0x9c, 0x24, 0x95, 0x56, 0x50, 0x92, +0xd1, 0x20, 0x50, 0x3f, 0x7c, 0x18, 0x42, 0x91, 0x90, 0x73, 0x40, 0x24, 0x80, 0x01, 0x4e, 0x27, +0x00, 0x6d, 0x96, 0x48, 0x44, 0x00, 0x00, 0x32, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x87, 0x34, +0xdd, 0x2f, 0xd5, 0x63, 0x44, 0x10, 0x00, 0x33, 0x4c, 0x20, 0xc0, 0x08, 0x84, 0x80, 0x46, 0xf0, +0x00, 0x0e, 0x10, 0x47, 0x84, 0x89, 0xd5, 0x59, 0x9d, 0x49, 0xda, 0x3d, 0x50, 0x70, 0x00, 0x0c, +0x50, 0x50, 0x00, 0x08, 0x50, 0x20, 0x00, 0x10, 0x51, 0xe0, 0x00, 0x14, 0xb5, 0x23, 0xb5, 0x05, +0xb4, 0x67, 0xb4, 0x82, 0xb4, 0xfe, 0xe6, 0xe2, 0xe9, 0x02, 0xd5, 0x04, 0x84, 0x21, 0x4c, 0x70, +0x80, 0x05, 0x84, 0xa0, 0x80, 0xe5, 0xd5, 0x0f, 0x8c, 0x18, 0xb4, 0xa0, 0x5c, 0xf2, 0x80, 0x3d, +0xe9, 0x04, 0x44, 0x50, 0x00, 0x3c, 0xd5, 0x07, 0x5d, 0xe2, 0x80, 0x14, 0x44, 0x60, 0x00, 0x14, +0x40, 0x53, 0x78, 0x1b, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x07, 0xdc, 0x54, 0x94, 0x80, 0xff, +0xa9, 0x72, 0x84, 0xa1, 0xaf, 0x70, 0xaf, 0xf5, 0x10, 0x93, 0x00, 0x04, 0x14, 0x83, 0x00, 0x03, +0x80, 0x29, 0x80, 0x48, 0x44, 0x00, 0x00, 0x34, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x88, 0x28, +0xdd, 0x2f, 0xd5, 0x1b, 0x44, 0x50, 0x00, 0x35, 0xd2, 0x02, 0xd5, 0x17, 0x85, 0x00, 0x46, 0xf0, +0x00, 0x0b, 0x10, 0x87, 0x87, 0xbb, 0x46, 0xf0, 0x00, 0x0e, 0x10, 0x87, 0x87, 0xe0, 0x46, 0xf0, +0x00, 0x0e, 0x10, 0x87, 0x87, 0xdc, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x07, 0xf0, 0x46, 0xf0, +0x00, 0x00, 0x58, 0xf7, 0x81, 0x1c, 0xdd, 0x2f, 0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, +0xdd, 0x9e, 0x84, 0x02, 0x48, 0xff, 0xff, 0x7c, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x50, 0x0f, +0x80, 0x04, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0x3c, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x0e, +0x04, 0x17, 0x81, 0x5e, 0x54, 0x70, 0x80, 0x02, 0xc7, 0x04, 0x42, 0x10, 0x80, 0x09, 0x84, 0xe1, +0xf0, 0x01, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x04, 0xc4, 0x14, 0x13, 0x00, 0x2d, 0x46, 0xf0, +0x00, 0x05, 0x58, 0xf7, 0x8e, 0x50, 0xdd, 0x2f, 0xc7, 0x07, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x8b, 0x60, 0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, +0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, 0x04, 0xc4, 0x50, 0x0f, +0x80, 0x04, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0x3c, 0xdd, 0x2f, 0x04, 0x73, 0x00, 0x2d, +0xf0, 0x01, 0x97, 0xfc, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0x50, 0xdd, 0x2f, 0xc7, 0x07, +0x80, 0x06, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8b, 0xe4, 0xdd, 0x2f, 0xec, 0x0c, 0x3a, 0x6f, +0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0xef, 0xf8, 0x46, 0x60, 0x00, 0x0e, 0x58, 0x63, +0x04, 0xc4, 0x50, 0x0f, 0x80, 0x04, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0x3c, 0xdd, 0x2f, +0x04, 0x33, 0x00, 0x2d, 0xf0, 0x01, 0x84, 0x40, 0xb6, 0x7f, 0x14, 0x23, 0x00, 0x2d, 0x46, 0xf0, +0x00, 0x05, 0x58, 0xf7, 0x8e, 0x50, 0xdd, 0x2f, 0xb4, 0x3f, 0x96, 0x0c, 0xc0, 0x07, 0x80, 0x06, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8b, 0xe4, 0xdd, 0x2f, 0xb4, 0xbf, 0x54, 0x42, 0x80, 0x02, +0xc4, 0x0a, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0xc4, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, +0x8b, 0x60, 0xdd, 0x2f, 0xb4, 0x1f, 0x41, 0xe0, 0x3c, 0x08, 0x41, 0xef, 0x7c, 0x09, 0x4f, 0xe2, +0x00, 0x0b, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0xc4, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, +0x8d, 0x3c, 0xdd, 0x2f, 0xb4, 0x7f, 0x40, 0x21, 0xb8, 0x08, 0x92, 0x5f, 0xc2, 0x0a, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x04, 0xc4, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8c, 0x58, 0xdd, 0x2f, +0xec, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0x44, 0x00, +0x02, 0x00, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x8e, 0xa4, 0xdd, 0x2f, 0x46, 0x30, 0x04, 0x00, +0xb4, 0x43, 0x44, 0x50, 0x76, 0x10, 0x40, 0x01, 0x40, 0x09, 0xd8, 0x07, 0x80, 0xe3, 0x04, 0x53, +0x80, 0x41, 0x42, 0x42, 0xd0, 0x0b, 0xc4, 0x23, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x87, 0x87, 0xb3, +0x84, 0xa1, 0x4c, 0x82, 0xc0, 0x07, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x82, 0xa0, 0xdd, 0x2f, +0x46, 0xf0, 0x00, 0x0e, 0x00, 0x07, 0x87, 0x18, 0xc8, 0x12, 0x46, 0xf0, 0x00, 0x0e, 0x01, 0xe7, +0x83, 0xcc, 0x84, 0xa1, 0x4d, 0xe2, 0xc0, 0x0c, 0x46, 0xf0, 0x00, 0x0b, 0x00, 0x17, 0x86, 0x6c, +0x80, 0x40, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x87, 0x34, 0xdd, 0x2f, 0x46, 0x20, 0x00, 0x0b, +0x00, 0x01, 0x07, 0xbb, 0x84, 0xa1, 0xd8, 0x11, 0x84, 0xa0, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x17, +0x81, 0xf9, 0x10, 0x51, 0x07, 0xbb, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x07, 0xf0, 0x46, 0xf0, +0x00, 0x00, 0x58, 0xf7, 0x82, 0x54, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x04, 0x58, 0xf7, 0x84, 0xac, +0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x0a, 0x58, 0xf7, 0x8b, 0x04, 0xdd, 0x2f, 0x46, 0xa0, 0x00, 0x00, +0x58, 0xa5, 0x03, 0x24, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x8b, 0x10, 0xdd, 0x2f, 0x46, 0x90, +0x00, 0x02, 0x58, 0x94, 0x89, 0x50, 0x46, 0x70, 0x00, 0x00, 0x58, 0x73, 0x83, 0x68, 0x46, 0x80, +0x00, 0x02, 0x58, 0x84, 0x00, 0xe8, 0xd5, 0x20, 0x4b, 0xe0, 0x28, 0x01, 0x00, 0x10, 0x00, 0x14, +0x80, 0xc0, 0xc9, 0x0f, 0x80, 0x20, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0xc4, 0x4b, 0xe0, +0x20, 0x01, 0xc8, 0x12, 0x80, 0x26, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, 0x04, 0xb4, 0xd5, 0x0a, +0x84, 0xa1, 0xd9, 0x0a, 0x4b, 0xe0, 0x24, 0x01, 0x80, 0x26, 0x46, 0x00, 0x00, 0x0e, 0x58, 0x00, +0x04, 0xa4, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x27, 0x81, 0x61, 0x46, 0x00, +0x00, 0x0e, 0x58, 0x00, 0x05, 0x7c, 0xca, 0xd9, 0x46, 0xf0, 0x00, 0x0e, 0x04, 0x07, 0x81, 0x23, +0x44, 0x30, 0x03, 0xe8, 0x40, 0x20, 0x0c, 0x36, 0xc9, 0x06, 0x46, 0x40, 0x04, 0x00, 0x9d, 0x51, +0x14, 0x52, 0x00, 0x8e, 0x46, 0x10, 0x00, 0x0e, 0x51, 0xe0, 0x00, 0x01, 0x15, 0xe0, 0x81, 0x23, +0x5e, 0xf0, 0x13, 0x89, 0xe9, 0x04, 0x84, 0x40, 0x14, 0x20, 0x81, 0x23, 0x46, 0xf0, 0x00, 0x0e, +0x04, 0x17, 0x81, 0x5e, 0xc9, 0x08, 0x44, 0x00, 0x02, 0x00, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, +0x8e, 0xe8, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x60, 0x4f, 0x00, 0x00, 0x14, 0x4a, 0x00, 0x00, +0xdc, 0x44, 0x00, 0x00, 0x20, 0x49, 0x00, 0x00, 0xdc, 0x44, 0x00, 0x00, 0x1c, 0x47, 0x00, 0x00, +0x80, 0x4d, 0x00, 0x00, 0xdc, 0x44, 0x00, 0x00, 0x3c, 0x4f, 0x00, 0x00, 0xe4, 0x48, 0x00, 0x00, +0x1c, 0x4f, 0x00, 0x00, 0xcc, 0x48, 0x00, 0x00, 0xdc, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x01, 0x99, 0x99, 0x09, 0x50, 0x02, 0x46, 0x44, 0x0a, 0x50, 0x03, 0xec, 0xee, 0x0a, 0x50, 0x04, +0x99, 0x99, 0x0b, 0x50, 0x05, 0x46, 0x44, 0x08, 0x51, 0x06, 0xec, 0xee, 0x08, 0x51, 0x07, 0x99, +0x99, 0x09, 0x51, 0x08, 0x46, 0x44, 0x0a, 0x51, 0x09, 0xec, 0xee, 0x0a, 0x51, 0x0a, 0x99, 0x99, +0x0b, 0x51, 0x0b, 0x46, 0x44, 0x08, 0x52, 0x0c, 0xec, 0xee, 0x08, 0x52, 0x0d, 0x99, 0x99, 0x09, +0x52, 0x0e, 0x33, 0x33, 0x0b, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, +0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, +0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x30, 0x34, 0x38, +0x3c, 0x40, 0x44, 0x60, 0x64, 0x68, 0x6c, 0x70, 0x74, 0x78, 0x7c, 0x00, 0x24, 0x25, 0x26, 0x27, +0x28, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x00, +0x16, 0x14, 0x12, 0x10, 0x08, 0x04, 0x00, 0x00, 0x00, 0x01, 0x02, 0x14, 0x18, 0x1c, 0x00, 0x00, +0x20, 0x21, 0x22, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0f, 0xac, 0x00, 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x03, 0x00, +0x00, 0xf8, 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, 0x88, 0x8e, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, +0x86, 0xdd, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x05, 0xff, 0x00, 0x00, +0x41, 0x76, 0x08, 0x02, 0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x8f, 0x14, 0x01, 0x76, +0x01, 0x00, 0x01, 0x02, 0x03, 0x01, 0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, +0x05, 0x0f, 0x0c, 0x00, 0x01, 0x07, 0x10, 0x02, 0x02, 0x00, 0x00, 0x00, 0x09, 0x02, 0x4a, 0x00, +0x01, 0x01, 0x00, 0xa0, 0x50, 0x09, 0x04, 0x00, 0x00, 0x08, 0xff, 0xff, 0xff, 0x00, 0x07, 0x05, +0x84, 0x02, 0x00, 0x02, 0x00, 0x07, 0x05, 0x85, 0x02, 0x00, 0x02, 0x00, 0x07, 0x05, 0x08, 0x02, +0x00, 0x02, 0x00, 0x07, 0x05, 0x04, 0x02, 0x00, 0x02, 0x00, 0x07, 0x05, 0x05, 0x02, 0x00, 0x02, +0x00, 0x07, 0x05, 0x06, 0x02, 0x00, 0x02, 0x00, 0x07, 0x05, 0x07, 0x02, 0x00, 0x02, 0x00, 0x07, +0x05, 0x09, 0x02, 0x00, 0x02, 0x00, 0x09, 0x04, 0x01, 0x00, 0x05, 0xff, 0xff, 0xff, 0x00, 0x07, +0x05, 0x81, 0x03, 0x40, 0x00, 0x00, 0x07, 0x05, 0x82, 0x02, 0x00, 0x02, 0x00, 0x07, 0x05, 0x02, +0x02, 0x00, 0x02, 0x00, 0x07, 0x05, 0x83, 0x01, 0x40, 0x00, 0x00, 0x07, 0x05, 0x03, 0x01, 0x40, +0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x12, 0x03, 0x4d, 0x00, 0x65, 0x00, 0x64, 0x00, 0x69, 0x00, +0x61, 0x00, 0x54, 0x00, 0x65, 0x00, 0x6b, 0x00, 0x1c, 0x03, 0x38, 0x00, 0x30, 0x00, 0x32, 0x00, +0x2e, 0x00, 0x31, 0x00, 0x31, 0x00, 0x20, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x57, 0x00, 0x4c, 0x00, +0x41, 0x00, 0x4e, 0x00, 0x08, 0x03, 0x31, 0x00, 0x2e, 0x00, 0x30, 0x00, 0xe4, 0x5d, 0x00, 0x00, +0xe8, 0x5d, 0x00, 0x00, 0xec, 0x5d, 0x00, 0x00, 0xf0, 0x5d, 0x00, 0x00, 0xf4, 0x5d, 0x00, 0x00, +0xf8, 0x5d, 0x00, 0x00, 0xfc, 0x5d, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x04, 0x5e, 0x00, 0x00, +0x08, 0x5e, 0x00, 0x00, 0x0c, 0x5e, 0x00, 0x00, 0x10, 0x5e, 0x00, 0x00, 0x14, 0x5e, 0x00, 0x00, +0x18, 0x5e, 0x00, 0x00, 0x1c, 0x5e, 0x00, 0x00, 0x20, 0x5e, 0x00, 0x00, 0x56, 0x65, 0x72, 0x73, +0xb1, 0x00, 0x00, 0x00, 0x40, 0x76, 0x00, 0x01, } ; diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7603_e2_firmware.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7603_e2_firmware.h new file mode 100644 index 000000000..697a925cf --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7603_e2_firmware.h @@ -0,0 +1,4654 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR MT7603_e2_FirmwareImage[] = { +0x46, 0x00, 0x01, 0x00, 0x58, 0x00, 0x02, 0x30, 0x4a, 0x00, 0x00, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, +0x46, 0x6a, 0x00, 0x00, 0x58, 0x63, 0x01, 0x7c, 0x04, 0x83, 0x00, 0x00, 0x54, 0x84, 0x00, 0xff, +0x40, 0x04, 0x00, 0x10, 0x4e, 0x05, 0x00, 0x4c, 0x58, 0x04, 0x00, 0x00, 0x49, 0x00, 0x21, 0x3e, +0x10, 0x80, 0x00, 0x02, 0x44, 0x10, 0x00, 0x01, 0x49, 0x00, 0x25, 0x8c, 0x44, 0x00, 0x00, 0x18, +0x49, 0xf8, 0x16, 0x7c, 0x44, 0x50, 0x0f, 0xff, 0x58, 0xa0, 0x00, 0x00, 0x4c, 0x02, 0xc0, 0x0a, +0x44, 0x20, 0xee, 0xee, 0x14, 0x23, 0x00, 0x00, 0x44, 0x00, 0x01, 0x03, 0x48, 0x00, 0x00, 0x36, +0x49, 0xf8, 0x16, 0x3e, 0x44, 0x70, 0x00, 0x00, 0x58, 0x90, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, +0x44, 0x20, 0x00, 0x18, 0x49, 0xf8, 0x10, 0xaa, 0x58, 0x04, 0x80, 0x00, 0x44, 0x10, 0x00, 0x18, +0x50, 0x94, 0x80, 0x0c, 0x58, 0x23, 0x80, 0x00, 0x50, 0x30, 0xff, 0xfc, 0x49, 0x00, 0x2f, 0x56, +0x14, 0x84, 0x80, 0x00, 0x14, 0x74, 0x80, 0x02, 0x14, 0x74, 0x80, 0x01, 0x14, 0x73, 0x00, 0x00, +0x58, 0x25, 0x00, 0x00, 0x58, 0x03, 0x80, 0x00, 0x44, 0x10, 0x00, 0x01, 0x58, 0x33, 0x80, 0x00, +0x49, 0xf8, 0x1a, 0x48, 0x58, 0x03, 0x80, 0x00, 0x48, 0x00, 0x00, 0x08, 0x44, 0x30, 0xdd, 0xdd, +0x14, 0x33, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xa0, 0xbc, 0x44, 0x10, 0x00, 0x6a, 0x4c, 0x00, 0x80, 0x26, 0x5c, 0xf0, 0x00, 0x6b, +0x4e, 0xf2, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0x80, 0x1a, 0x50, 0x50, 0xff, 0xfa, +0x4c, 0x02, 0xc0, 0x7c, 0x48, 0x00, 0x00, 0x10, 0x44, 0x50, 0x00, 0x77, 0x4c, 0x02, 0x80, 0x2a, +0x50, 0x52, 0x80, 0x01, 0x4c, 0x02, 0x80, 0x70, 0x50, 0x52, 0xff, 0xfd, 0x4c, 0x02, 0xc0, 0x6e, +0x48, 0x00, 0x00, 0x24, 0x49, 0xf8, 0x15, 0x9e, 0x48, 0x00, 0x00, 0x68, 0x49, 0x00, 0x4e, 0x02, +0x48, 0x00, 0x00, 0x64, 0x44, 0x00, 0x00, 0x02, 0x49, 0x00, 0x2d, 0x14, 0x2e, 0x07, 0xb4, 0x61, +0x4e, 0x02, 0x00, 0x5c, 0x3e, 0x8f, 0xb4, 0x62, 0x2e, 0x07, 0xb4, 0x63, 0x00, 0x14, 0x00, 0x00, +0x44, 0x70, 0x00, 0x00, 0x49, 0x00, 0x32, 0x2a, 0x3e, 0x77, 0xb4, 0x61, 0x48, 0x00, 0x00, 0x4e, +0x49, 0x00, 0x4b, 0x04, 0x48, 0x00, 0x00, 0x4a, 0x2e, 0x27, 0xb0, 0xd4, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x22, 0xc0, 0x20, 0x46, 0x08, 0x00, 0x21, 0x04, 0x50, 0x00, 0x44, 0x40, 0x42, 0xb4, 0x08, +0x40, 0x42, 0x7c, 0x09, 0x4e, 0x43, 0x00, 0x3a, 0x3e, 0x8f, 0xb4, 0x50, 0x00, 0x74, 0x00, 0x00, +0x4e, 0x72, 0x00, 0x34, 0x46, 0x35, 0x00, 0x25, 0x04, 0x11, 0x81, 0xf1, 0x44, 0x50, 0x00, 0x90, +0x55, 0xe0, 0x80, 0x90, 0x4d, 0xe2, 0x80, 0x24, 0x3e, 0x0f, 0xb4, 0x53, 0x48, 0x00, 0x00, 0x1c, +0x2e, 0x40, 0x02, 0x88, 0x4e, 0x42, 0x00, 0x08, 0x2e, 0x67, 0xb0, 0xd5, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x62, 0xc0, 0x1c, 0x46, 0x15, 0x00, 0x25, 0x04, 0x20, 0x81, 0xf1, 0x44, 0x50, 0x00, 0x90, +0x54, 0x81, 0x00, 0x90, 0x4c, 0x82, 0x80, 0x06, 0x2e, 0x37, 0xb4, 0x53, 0x4e, 0x32, 0x00, 0x0e, +0x3e, 0x0f, 0xb4, 0x50, 0x00, 0x50, 0x00, 0x00, 0x4e, 0x52, 0x00, 0x08, 0x49, 0xf8, 0x37, 0x86, +0x48, 0x00, 0x00, 0x04, 0x49, 0x00, 0x04, 0x48, 0x49, 0x00, 0x1e, 0x5c, 0x49, 0x00, 0x4f, 0x8a, +0x44, 0x2f, 0xff, 0xff, 0x44, 0x10, 0x00, 0x00, 0x58, 0x60, 0x00, 0x00, 0x44, 0x00, 0x00, 0x02, +0x40, 0x80, 0x98, 0x1b, 0x40, 0x81, 0x18, 0x1a, 0x49, 0xf8, 0x07, 0x18, 0x44, 0x00, 0x00, 0x02, +0x49, 0xf8, 0x06, 0xec, 0x44, 0x00, 0x00, 0x08, 0x49, 0xf8, 0x07, 0x10, 0x44, 0x00, 0x00, 0x08, +0x49, 0xf8, 0x06, 0xe4, 0x58, 0x04, 0x00, 0x00, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x49, 0x00, 0x8e, 0x9c, 0x46, 0x28, 0x00, 0x21, +0x04, 0x01, 0x00, 0x04, 0x46, 0x10, 0x20, 0x00, 0x40, 0x00, 0x04, 0x02, 0x4e, 0x02, 0x00, 0x26, +0x47, 0xc5, 0x00, 0x29, 0x44, 0x00, 0x00, 0x02, 0x44, 0x10, 0x00, 0x00, 0x3e, 0x2e, 0x9c, 0x38, +0x49, 0xf8, 0x2d, 0x80, 0x04, 0x1e, 0x00, 0x08, 0x46, 0x85, 0x00, 0x29, 0x58, 0x00, 0x84, 0x00, +0x14, 0x0e, 0x00, 0x08, 0x04, 0xa4, 0x00, 0x84, 0x46, 0x75, 0x00, 0x22, 0x58, 0x95, 0x00, 0x01, +0x44, 0x50, 0xff, 0xff, 0x3e, 0x4f, 0x37, 0xc0, 0x14, 0x94, 0x00, 0x84, 0x14, 0x53, 0x82, 0x08, +0x3c, 0x4f, 0xff, 0xb9, 0x44, 0x00, 0x00, 0x01, 0x3e, 0x07, 0xb3, 0x58, 0x49, 0x00, 0x00, 0x74, +0x49, 0x00, 0x05, 0x0c, 0x44, 0x00, 0x00, 0x01, 0x49, 0x00, 0x4f, 0x28, 0x49, 0x00, 0x00, 0xa8, +0x46, 0x58, 0x00, 0x21, 0x58, 0x52, 0x81, 0x34, 0x04, 0x82, 0x80, 0x00, 0x3e, 0x0f, 0x98, 0x9c, +0x58, 0x74, 0x00, 0x02, 0x14, 0x72, 0x80, 0x00, 0x04, 0x12, 0x80, 0x00, 0x49, 0x00, 0x00, 0xce, +0x46, 0x48, 0x00, 0x21, 0x04, 0x32, 0x00, 0x04, 0x42, 0x61, 0xe4, 0x0b, 0x4e, 0x63, 0x00, 0x04, +0x49, 0x00, 0x03, 0x88, 0x46, 0x78, 0x00, 0x00, 0x3f, 0xce, 0x91, 0xac, 0x2e, 0x17, 0xb3, 0x5c, +0x50, 0x00, 0x80, 0x01, 0x55, 0xe0, 0x00, 0xff, 0x3f, 0xe7, 0xb3, 0x5c, 0x4f, 0xe3, 0x00, 0x12, +0x05, 0xe3, 0x80, 0x80, 0x04, 0x53, 0x80, 0x80, 0x50, 0x22, 0x80, 0x01, 0x40, 0x4f, 0x20, 0x09, +0x40, 0x42, 0x20, 0x08, 0x54, 0x31, 0x00, 0xff, 0x40, 0x61, 0x90, 0x04, 0x14, 0x63, 0x80, 0x80, +0x49, 0xf8, 0x0b, 0xba, 0x58, 0x60, 0x00, 0x00, 0x4e, 0x02, 0xff, 0xe2, 0x04, 0x10, 0x00, 0x01, +0x04, 0x00, 0x00, 0x00, 0x4b, 0xe0, 0x70, 0x01, 0x4e, 0x04, 0x00, 0x16, 0x58, 0x03, 0x00, 0x00, +0x49, 0xf8, 0x0c, 0x3c, 0x48, 0x00, 0x00, 0x08, 0x49, 0xf8, 0x0b, 0xa6, 0x4e, 0x02, 0x00, 0x04, +0x49, 0xf8, 0x0c, 0x34, 0x49, 0xf8, 0x0b, 0x84, 0x58, 0x60, 0x00, 0x00, 0x4e, 0x03, 0xff, 0xf6, +0x48, 0x00, 0x00, 0x08, 0x58, 0x03, 0x00, 0x00, 0x49, 0xf8, 0x0c, 0x28, 0x48, 0xff, 0xff, 0xc0, +0x49, 0xf8, 0x14, 0x70, 0x58, 0x03, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x3e, 0x2f, 0x98, 0xbc, +0x44, 0x00, 0x00, 0x02, 0x3e, 0x1e, 0x94, 0x98, 0x49, 0xf8, 0x05, 0xac, 0x44, 0x10, 0x00, 0x00, +0x44, 0x00, 0x00, 0x02, 0x49, 0xf8, 0x05, 0xce, 0x44, 0x00, 0x00, 0x02, 0x49, 0xf8, 0x06, 0x1e, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x44, 0x00, 0x00, 0x02, 0x49, 0xf8, 0x05, 0xe8, 0x3e, 0x0f, 0x98, 0xc4, +0x49, 0x00, 0x00, 0x4c, 0x2e, 0x27, 0xb3, 0x5d, 0x4e, 0x23, 0x00, 0x0c, 0x44, 0x40, 0x00, 0x01, +0x3e, 0x47, 0xb3, 0x5d, 0x44, 0x00, 0x00, 0x01, 0x44, 0x10, 0x00, 0x64, 0x49, 0xf8, 0x34, 0x02, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x14, 0x3e, 0x0f, 0xc4, 0x3c, +0x49, 0xf8, 0x0e, 0xdc, 0x49, 0x00, 0x2c, 0xc8, 0x44, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x04, 0x20, 0x80, 0x00, 0x18, 0x01, 0x00, 0x01, +0x44, 0x00, 0x00, 0x00, 0x14, 0x20, 0x80, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, +0x58, 0x60, 0x00, 0x00, 0x58, 0x33, 0x00, 0x00, 0x58, 0x00, 0x80, 0x00, 0x58, 0x11, 0x00, 0x00, +0x3e, 0x2e, 0x95, 0x04, 0x49, 0xf8, 0x0c, 0x3c, 0x44, 0x20, 0x00, 0x00, 0x38, 0x23, 0x00, 0x08, +0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x1f, 0x94, 0x3c, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xf8, 0x2e, 0x27, 0xb0, 0x80, 0x44, 0x30, 0x00, 0x01, 0x58, 0x10, 0x00, 0x00, +0x4c, 0x21, 0xc0, 0x0a, 0x50, 0x1f, 0x80, 0x0c, 0x14, 0x1f, 0x80, 0x01, 0x49, 0xf8, 0x0e, 0x58, +0x48, 0x00, 0x00, 0x18, 0x44, 0x00, 0x00, 0x02, 0x4c, 0x20, 0x40, 0x14, 0x50, 0x2f, 0x80, 0x0c, +0x3e, 0x0f, 0xb3, 0x6c, 0x14, 0x2f, 0x80, 0x01, 0x49, 0xff, 0xff, 0xca, 0x3e, 0x0f, 0xb3, 0x6c, +0x49, 0xf8, 0x0f, 0x3e, 0x58, 0x10, 0x00, 0x00, 0x3e, 0x0f, 0xb3, 0x6c, 0x49, 0x00, 0x2d, 0xec, +0x51, 0xff, 0x80, 0x08, 0x3b, 0xff, 0xfc, 0x84, 0x51, 0xff, 0x80, 0x14, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xec, 0x44, 0x60, 0x00, 0x00, 0x54, 0x21, 0x00, 0xff, +0x54, 0x70, 0x80, 0xff, 0x54, 0x41, 0x80, 0xff, 0x58, 0x13, 0x00, 0x00, 0x58, 0x31, 0x00, 0x00, +0x58, 0x53, 0x00, 0x00, 0x58, 0x23, 0x00, 0x00, 0x14, 0x7f, 0x80, 0x03, 0x14, 0x6f, 0x80, 0x00, +0x14, 0x6f, 0x80, 0x01, 0x14, 0x6f, 0x80, 0x02, 0x49, 0x00, 0x19, 0x26, 0x51, 0xff, 0x80, 0x14, +0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xec, +0x44, 0x60, 0x00, 0x00, 0x54, 0x70, 0x80, 0xff, 0x58, 0x23, 0x00, 0x00, 0x58, 0x13, 0x00, 0x00, +0x44, 0x30, 0x00, 0x0a, 0x44, 0x40, 0x00, 0x32, 0x58, 0x53, 0x00, 0x00, 0x14, 0x7f, 0x80, 0x03, +0x14, 0x6f, 0x80, 0x00, 0x14, 0x6f, 0x80, 0x01, 0x14, 0x6f, 0x80, 0x02, 0x49, 0x00, 0x19, 0x04, +0x51, 0xff, 0x80, 0x14, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, +0x51, 0xff, 0xff, 0xf0, 0x44, 0x60, 0x00, 0x00, 0x44, 0x30, 0x00, 0x11, 0x54, 0x80, 0x80, 0xff, +0x44, 0x70, 0x00, 0x02, 0x58, 0x23, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x58, 0x41, 0x80, 0x00, +0x44, 0x50, 0x01, 0x90, 0x14, 0x7f, 0x80, 0x02, 0x14, 0x8f, 0x80, 0x03, 0x14, 0x7f, 0x80, 0x00, +0x14, 0x6f, 0x80, 0x01, 0x49, 0x00, 0x18, 0xe0, 0x51, 0xff, 0x80, 0x10, 0x3a, 0x6f, 0xa0, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xec, 0x44, 0x60, 0x00, 0x00, +0x44, 0x30, 0x00, 0x11, 0x54, 0x70, 0x80, 0xff, 0x58, 0x23, 0x00, 0x00, 0x58, 0x13, 0x00, 0x00, +0x58, 0x41, 0x80, 0x00, 0x58, 0x53, 0x00, 0x00, 0x14, 0x7f, 0x80, 0x03, 0x14, 0x6f, 0x80, 0x00, +0x14, 0x6f, 0x80, 0x01, 0x14, 0x6f, 0x80, 0x02, 0x49, 0x00, 0x18, 0xbe, 0x51, 0xff, 0x80, 0x14, +0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xec, +0x44, 0x60, 0x00, 0x00, 0x44, 0x30, 0x00, 0x19, 0x54, 0x70, 0x80, 0xff, 0x58, 0x23, 0x00, 0x00, +0x58, 0x13, 0x00, 0x00, 0x58, 0x41, 0x80, 0x00, 0x58, 0x53, 0x00, 0x00, 0x14, 0x7f, 0x80, 0x03, +0x14, 0x6f, 0x80, 0x00, 0x14, 0x6f, 0x80, 0x01, 0x14, 0x6f, 0x80, 0x02, 0x49, 0x00, 0x18, 0x9c, +0x51, 0xff, 0x80, 0x14, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, +0x51, 0xff, 0xff, 0xec, 0x44, 0x60, 0x00, 0x00, 0x44, 0x30, 0x00, 0x32, 0x54, 0x70, 0x80, 0xff, +0x58, 0x23, 0x00, 0x00, 0x58, 0x13, 0x00, 0x00, 0x58, 0x41, 0x80, 0x00, 0x58, 0x53, 0x00, 0x00, +0x14, 0x7f, 0x80, 0x03, 0x14, 0x6f, 0x80, 0x00, 0x14, 0x6f, 0x80, 0x01, 0x14, 0x6f, 0x80, 0x02, +0x49, 0x00, 0x18, 0x7a, 0x51, 0xff, 0x80, 0x14, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xec, 0x44, 0x60, 0x00, 0x00, 0x44, 0x30, 0x00, 0x02, +0x54, 0x70, 0x80, 0xff, 0x58, 0x23, 0x00, 0x00, 0x58, 0x13, 0x00, 0x00, 0x58, 0x43, 0x00, 0x00, +0x58, 0x51, 0x80, 0x00, 0x14, 0x7f, 0x80, 0x03, 0x14, 0x6f, 0x80, 0x00, 0x14, 0x6f, 0x80, 0x01, +0x14, 0x6f, 0x80, 0x02, 0x49, 0x00, 0x18, 0x58, 0x51, 0xff, 0x80, 0x14, 0x3a, 0x6f, 0x9c, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xec, 0x44, 0x60, 0x00, 0x00, +0x44, 0x40, 0x00, 0x02, 0x54, 0x70, 0x80, 0xff, 0x58, 0x23, 0x00, 0x00, 0x58, 0x13, 0x00, 0x00, +0x58, 0x33, 0x00, 0x00, 0x58, 0x52, 0x00, 0x00, 0x14, 0x7f, 0x80, 0x03, 0x14, 0x6f, 0x80, 0x00, +0x14, 0x6f, 0x80, 0x01, 0x14, 0x6f, 0x80, 0x02, 0x49, 0x00, 0x18, 0x36, 0x51, 0xff, 0x80, 0x14, +0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x58, 0x60, 0x00, 0x00, +0x54, 0x10, 0x80, 0xff, 0x49, 0xff, 0xff, 0xd8, 0x42, 0x23, 0x40, 0x08, 0x3e, 0x0f, 0xb4, 0x34, +0x3e, 0x1e, 0x9a, 0x08, 0x49, 0x00, 0x4a, 0x8e, 0x3e, 0x0f, 0xb4, 0x34, 0x44, 0x10, 0x13, 0x88, +0x49, 0x00, 0x4b, 0x98, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, +0x54, 0x10, 0x80, 0xff, 0x58, 0x60, 0x00, 0x00, 0x49, 0xff, 0xff, 0xbe, 0x44, 0x03, 0x00, 0x00, +0x40, 0x23, 0x00, 0x04, 0x3e, 0x1e, 0x9a, 0x08, 0x3e, 0x0f, 0xb4, 0x34, 0x49, 0x00, 0x4a, 0x72, +0x3e, 0x0f, 0xb4, 0x34, 0x44, 0x10, 0x13, 0x88, 0x49, 0x00, 0x4b, 0x7c, 0x3a, 0x6f, 0x98, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x54, 0x30, 0x80, 0xff, +0x54, 0x41, 0x00, 0xff, 0x44, 0x10, 0x00, 0x03, 0x44, 0x20, 0x00, 0x07, 0x49, 0x00, 0x18, 0x84, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xf4, 0x04, 0x50, 0x00, 0x02, 0x44, 0x00, 0x00, 0x03, 0x02, 0x42, 0x80, 0x00, +0x50, 0x62, 0x80, 0x20, 0x00, 0x13, 0x00, 0x07, 0x50, 0x32, 0x7f, 0xe0, 0x40, 0x21, 0x8c, 0x09, +0x54, 0x10, 0x80, 0x03, 0x14, 0x2f, 0x80, 0x01, 0x4c, 0x10, 0x40, 0x06, 0x44, 0x70, 0x00, 0x00, +0x48, 0x00, 0x00, 0xa6, 0x46, 0x86, 0x01, 0x30, 0x05, 0xe4, 0x00, 0x00, 0x44, 0x0f, 0xff, 0x3f, +0x40, 0x7f, 0x00, 0x02, 0x14, 0x74, 0x00, 0x00, 0x40, 0xa0, 0x98, 0x08, 0x05, 0xc4, 0x00, 0x00, +0x44, 0x70, 0x00, 0x00, 0x40, 0x95, 0x70, 0x04, 0x14, 0x94, 0x00, 0x00, 0x48, 0x00, 0x00, 0x90, +0x04, 0x03, 0x00, 0x00, 0x04, 0x53, 0x00, 0x01, 0x5c, 0xf0, 0x00, 0x04, 0x4e, 0xf2, 0x00, 0x82, +0x42, 0x42, 0xf8, 0x0b, 0x56, 0x12, 0x00, 0x01, 0x3e, 0x17, 0xb4, 0x4d, 0x40, 0x22, 0xfc, 0x09, +0x3e, 0x47, 0xb4, 0x4c, 0x3e, 0x27, 0xb4, 0x4e, 0x54, 0x32, 0x80, 0xff, 0x45, 0xe0, 0x00, 0x05, +0x4c, 0x3f, 0x00, 0x52, 0x5c, 0xf1, 0x80, 0x06, 0x4e, 0xf2, 0x00, 0x1c, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x32, 0x80, 0x3c, 0x5c, 0xf1, 0x80, 0x03, 0x4e, 0xf2, 0x00, 0x0a, 0x4e, 0x32, 0x00, 0x2e, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x32, 0xc0, 0x5e, 0x48, 0x00, 0x00, 0x2c, 0x44, 0x50, 0x00, 0x03, +0x4c, 0x32, 0x80, 0x32, 0x44, 0x50, 0x00, 0x04, 0x4c, 0x32, 0xc0, 0x54, 0x48, 0x00, 0x00, 0x30, +0x45, 0xe0, 0x00, 0x11, 0x4c, 0x3f, 0x00, 0x3c, 0x5c, 0xf1, 0x80, 0x12, 0x4e, 0xf2, 0x00, 0x0c, +0x44, 0x50, 0x00, 0x06, 0x4c, 0x32, 0x80, 0x2c, 0x50, 0x52, 0x80, 0x0a, 0x4c, 0x32, 0xc0, 0x42, +0x48, 0x00, 0x00, 0x2a, 0x45, 0xe0, 0x00, 0x12, 0x4c, 0x3f, 0x00, 0x2e, 0x44, 0x40, 0x00, 0x1f, +0x4c, 0x32, 0x40, 0x38, 0x48, 0x00, 0x00, 0x2c, 0x49, 0xff, 0xff, 0x0e, 0x48, 0x00, 0x00, 0x32, +0x49, 0xff, 0xfe, 0xe8, 0x48, 0x00, 0x00, 0x2e, 0x58, 0x12, 0x00, 0x00, 0x49, 0xff, 0xff, 0x5c, +0x48, 0x00, 0x00, 0x28, 0x49, 0xff, 0xfe, 0xbc, 0x48, 0x00, 0x00, 0x24, 0x49, 0xff, 0xfe, 0x96, +0x48, 0x00, 0x00, 0x20, 0x49, 0xff, 0xfe, 0x70, 0x48, 0x00, 0x00, 0x1c, 0x49, 0xff, 0xfe, 0x26, +0x48, 0x00, 0x00, 0x18, 0x49, 0xff, 0xfe, 0x44, 0x48, 0x00, 0x00, 0x14, 0x4b, 0xe0, 0x70, 0x01, +0x48, 0x00, 0x00, 0x10, 0x49, 0xff, 0xff, 0x24, 0x48, 0x00, 0x00, 0x0c, 0x40, 0x32, 0xc0, 0x08, +0x40, 0x22, 0xa0, 0x08, 0x40, 0x21, 0x60, 0x09, 0x40, 0x31, 0xe0, 0x09, 0x49, 0xff, 0xfd, 0xea, +0x50, 0x73, 0x80, 0x01, 0x50, 0x63, 0x00, 0x08, 0x48, 0x00, 0x00, 0x04, 0x3f, 0xce, 0x97, 0xd4, +0x04, 0x1f, 0x80, 0x01, 0x40, 0xf3, 0x84, 0x06, 0x4e, 0xf3, 0xff, 0x6c, 0x44, 0x00, 0x00, 0x00, +0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, +0x40, 0x10, 0x40, 0x09, 0x40, 0x60, 0x00, 0x13, 0x54, 0x10, 0x80, 0xff, 0x44, 0x00, 0x00, 0x02, +0x4c, 0x10, 0x00, 0x20, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x12, 0x80, 0x26, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x12, 0xc0, 0x28, 0x2e, 0x17, 0xb4, 0x4d, 0x58, 0x03, 0x00, 0x00, 0x49, 0xff, 0xfe, 0x8a, +0x42, 0x23, 0x44, 0x08, 0x3e, 0x0f, 0xb4, 0x34, 0x3e, 0x1e, 0x9a, 0x08, 0x49, 0x00, 0x49, 0x62, +0x3e, 0x0f, 0xb4, 0x34, 0x44, 0x10, 0x0b, 0xb8, 0x49, 0x00, 0x4a, 0x6c, 0x48, 0x00, 0x00, 0x12, +0x2e, 0x17, 0xb4, 0x4c, 0x2e, 0x27, 0xb4, 0x4e, 0x58, 0x03, 0x00, 0x00, 0x49, 0xff, 0xfe, 0xec, +0x48, 0x00, 0x00, 0x08, 0x2e, 0x17, 0xb4, 0x4d, 0x58, 0x03, 0x00, 0x00, 0x49, 0xff, 0xfe, 0x6a, +0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x46, 0x68, 0x00, 0x23, 0x58, 0x63, 0x00, 0x80, 0x04, 0x13, 0x00, 0x00, 0x3e, 0x0f, 0x98, 0xd0, +0x49, 0xff, 0xfd, 0x54, 0x04, 0x33, 0x00, 0x00, 0x46, 0x2f, 0xf8, 0xff, 0x58, 0x21, 0x0f, 0xff, +0x40, 0x11, 0x88, 0x02, 0x14, 0x13, 0x00, 0x00, 0x3e, 0x0f, 0x98, 0xe8, 0x04, 0x13, 0x00, 0x00, +0x49, 0xff, 0xfd, 0x44, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x3e, 0x0f, 0x98, 0xfc, 0x49, 0xff, 0xfd, 0x36, +0x46, 0x18, 0x00, 0x21, 0x04, 0x30, 0x80, 0x4c, 0x44, 0x00, 0x00, 0x00, 0x42, 0x21, 0xbc, 0x08, +0x14, 0x20, 0x80, 0x4c, 0x58, 0x40, 0x00, 0x00, 0x58, 0x20, 0x00, 0x00, 0x3e, 0x3e, 0x9b, 0x24, +0x58, 0x10, 0x00, 0x00, 0x49, 0xf8, 0x04, 0xb2, 0x44, 0x00, 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, +0x49, 0xf8, 0x04, 0x76, 0x44, 0x00, 0x00, 0x00, 0x49, 0xf8, 0x03, 0xd6, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x44, 0x00, 0x00, 0x00, 0x49, 0xf8, 0x03, 0xbe, 0x44, 0x10, 0x00, 0x78, 0x44, 0x20, 0x00, 0x00, +0x44, 0x00, 0x00, 0x01, 0x49, 0xf8, 0x30, 0xc6, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x3e, 0x0f, 0x99, 0x20, +0x49, 0xff, 0xfc, 0xf4, 0x49, 0x00, 0x29, 0x7a, 0x44, 0x00, 0x00, 0x00, 0x49, 0x00, 0x4b, 0x36, +0x46, 0x08, 0x00, 0x21, 0x04, 0x20, 0x00, 0x4d, 0x42, 0x41, 0x04, 0x09, 0x14, 0x40, 0x00, 0x4d, +0x58, 0x10, 0x00, 0x00, 0x04, 0x30, 0x80, 0x40, 0x40, 0x21, 0x88, 0x09, 0x40, 0x21, 0x08, 0x08, +0x14, 0x20, 0x80, 0x40, 0x04, 0x40, 0x00, 0x4c, 0x46, 0x58, 0x10, 0x80, 0x42, 0x32, 0x78, 0x08, +0x58, 0x22, 0x80, 0x00, 0x58, 0x11, 0x00, 0x00, 0x14, 0x30, 0x00, 0x4c, 0x44, 0x40, 0x00, 0x28, +0x44, 0x30, 0x22, 0x01, 0x44, 0x00, 0x19, 0x71, 0x14, 0x42, 0x80, 0x0d, 0x14, 0x31, 0x00, 0x0c, +0x14, 0x00, 0x80, 0x0e, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x46, 0x1a, 0x00, 0x00, 0x54, 0x00, 0x00, 0xff, 0x04, 0x20, 0x80, 0x00, 0x4e, 0x02, 0x00, 0x2a, +0x58, 0x21, 0x00, 0x01, 0x14, 0x20, 0x80, 0x00, 0x2e, 0x07, 0xb3, 0x58, 0x4e, 0x03, 0x00, 0x04, +0x48, 0x00, 0x00, 0x0a, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x20, 0x2e, 0x47, 0xb0, 0x81, +0x4c, 0x40, 0x40, 0x14, 0x46, 0x05, 0x00, 0x00, 0x58, 0x00, 0x05, 0x94, 0x04, 0x50, 0x00, 0x00, +0x58, 0x42, 0x81, 0x00, 0x14, 0x40, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x42, 0x11, 0xa0, 0x09, +0x14, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0a, 0x3e, 0x07, 0xb4, 0x4f, 0x48, 0x00, 0x00, 0x06, +0x42, 0x31, 0x00, 0x09, 0x14, 0x30, 0x80, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x05, 0x00, 0x29, +0x04, 0x20, 0x00, 0x84, 0x58, 0x11, 0x00, 0x01, 0x14, 0x10, 0x00, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x98, 0x3c, 0x46, 0x05, 0x00, 0x22, 0x58, 0x00, 0x08, 0x04, 0x44, 0x10, 0x00, 0x00, +0x44, 0x20, 0x00, 0x01, 0x04, 0x60, 0x00, 0x00, 0x50, 0x30, 0x80, 0x11, 0x40, 0x51, 0x0c, 0x0c, +0x40, 0x42, 0x98, 0x04, 0x14, 0x40, 0x00, 0x00, 0x40, 0x62, 0x94, 0x05, 0x04, 0x50, 0x00, 0x00, +0x50, 0x30, 0x80, 0x01, 0x40, 0x31, 0x0c, 0x0c, 0x40, 0x53, 0x14, 0x02, 0x40, 0x41, 0x8c, 0x05, +0x14, 0x50, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x0e, 0x04, 0x50, 0x00, 0x00, 0x40, 0x31, 0x94, 0x04, +0x14, 0x30, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x40, 0x52, 0x0c, 0x02, 0x14, 0x50, 0x00, 0x00, +0x50, 0x10, 0x80, 0x01, 0x44, 0x40, 0x00, 0x03, 0x4c, 0x12, 0x7f, 0xd6, 0x46, 0x05, 0x00, 0x22, +0x58, 0x00, 0x08, 0x04, 0x04, 0x40, 0x00, 0x00, 0x42, 0x12, 0x50, 0x08, 0x14, 0x10, 0x00, 0x00, +0x04, 0x30, 0x00, 0x00, 0x58, 0x20, 0x00, 0x00, 0x42, 0x31, 0xd0, 0x09, 0x14, 0x30, 0x00, 0x00, +0x44, 0x10, 0x00, 0x04, 0x04, 0x50, 0x00, 0x00, 0x44, 0x40, 0x00, 0x01, 0x42, 0x32, 0xd4, 0x08, +0x14, 0x30, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x42, 0x31, 0xd4, 0x09, 0x14, 0x30, 0x00, 0x00, +0x04, 0x31, 0x00, 0x00, 0x40, 0x52, 0x04, 0x0c, 0x40, 0x02, 0x8c, 0x04, 0x14, 0x01, 0x00, 0x00, +0x40, 0x02, 0x94, 0x05, 0x04, 0x31, 0x00, 0x00, 0x50, 0x10, 0x80, 0x01, 0x40, 0x50, 0x0c, 0x02, +0x44, 0x00, 0x00, 0x0a, 0x14, 0x51, 0x00, 0x00, 0x4c, 0x10, 0x7f, 0xec, 0x3a, 0x6f, 0x98, 0x04, +0x4a, 0x00, 0x78, 0x20, 0x46, 0x45, 0x00, 0x22, 0x04, 0x22, 0x00, 0x40, 0x46, 0x30, 0x04, 0x00, +0x40, 0x21, 0x0c, 0x02, 0x4e, 0x22, 0x00, 0x04, 0x44, 0x20, 0x00, 0x01, 0x14, 0x20, 0x80, 0x00, +0x2e, 0x10, 0x00, 0x03, 0x4e, 0x12, 0x00, 0x0a, 0x44, 0x50, 0x00, 0x01, 0x14, 0x50, 0x00, 0x00, +0x3e, 0x57, 0xb4, 0x51, 0x48, 0x00, 0x00, 0x04, 0x14, 0x10, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, +0x02, 0x30, 0x80, 0x03, 0x02, 0x20, 0x80, 0x01, 0x02, 0x00, 0x80, 0x02, 0x44, 0x10, 0x00, 0x01, +0x3c, 0x3e, 0x00, 0x04, 0x4c, 0x20, 0xc0, 0x08, 0x5c, 0xf0, 0x00, 0x02, 0x4e, 0xf2, 0x00, 0x04, +0x3e, 0x07, 0xb4, 0x52, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xb4, +0x3e, 0x5e, 0xa0, 0xe4, 0x45, 0xc0, 0x54, 0xd0, 0x40, 0x42, 0xf0, 0x01, 0x14, 0x4f, 0x80, 0x0e, +0x3e, 0x8e, 0xa1, 0x60, 0x44, 0x90, 0x6a, 0x4c, 0x46, 0x40, 0x20, 0x00, 0x14, 0x4f, 0x80, 0x02, +0x40, 0x74, 0x24, 0x01, 0x3e, 0x1e, 0x9b, 0xcc, 0x44, 0x20, 0x31, 0x5c, 0x3e, 0x3e, 0xa1, 0xe4, +0x44, 0x60, 0x6a, 0xd0, 0x14, 0x7f, 0x80, 0x0a, 0x40, 0x00, 0x88, 0x01, 0x3f, 0xee, 0x9f, 0xc8, +0x40, 0x21, 0x98, 0x01, 0x44, 0xa0, 0x6a, 0xb8, 0x3e, 0x3e, 0xa0, 0x34, 0x44, 0x10, 0x59, 0x1c, +0x3f, 0xce, 0x9d, 0x6c, 0x44, 0x70, 0x5c, 0xd4, 0x40, 0x6f, 0x28, 0x01, 0x40, 0x5e, 0x1c, 0x01, +0x41, 0xe1, 0x84, 0x01, 0x05, 0xcf, 0x80, 0x02, 0x58, 0x32, 0x00, 0x00, 0x14, 0x3f, 0x80, 0x03, +0x59, 0xce, 0x00, 0x20, 0x15, 0xef, 0x80, 0x0f, 0x15, 0xcf, 0x80, 0x02, 0x58, 0x11, 0x80, 0x00, +0x05, 0xcf, 0x80, 0x03, 0x59, 0xe0, 0x80, 0x00, 0x14, 0x1f, 0x80, 0x04, 0x15, 0xef, 0x80, 0x05, +0x3e, 0x9e, 0x9d, 0x30, 0x44, 0xa0, 0x60, 0x20, 0x40, 0x00, 0x04, 0x0a, 0x59, 0xce, 0x00, 0x24, +0x40, 0x84, 0xa8, 0x01, 0x14, 0x0f, 0x80, 0x0d, 0x15, 0xcf, 0x80, 0x03, 0x04, 0x0f, 0x80, 0x04, +0x41, 0xc1, 0x04, 0x0a, 0x58, 0xa0, 0x80, 0x00, 0x04, 0x2f, 0x80, 0x05, 0x58, 0x90, 0x80, 0x00, +0x14, 0xaf, 0x80, 0x06, 0x14, 0x9f, 0x80, 0x07, 0x58, 0x00, 0x00, 0x28, 0x58, 0x21, 0x00, 0x2c, +0x14, 0x8f, 0x80, 0x10, 0x14, 0x0f, 0x80, 0x04, 0x14, 0x2f, 0x80, 0x05, 0x04, 0x0f, 0x80, 0x06, +0x04, 0x2f, 0x80, 0x07, 0x58, 0x80, 0x80, 0x00, 0x58, 0x70, 0x80, 0x00, 0x14, 0x8f, 0x80, 0x08, +0x14, 0x7f, 0x80, 0x09, 0x58, 0x00, 0x00, 0x30, 0x58, 0x21, 0x00, 0x34, 0x15, 0xcf, 0x80, 0x0c, +0x14, 0x0f, 0x80, 0x06, 0x41, 0xc3, 0x04, 0x0a, 0x04, 0x0f, 0x80, 0x08, 0x04, 0x6f, 0x80, 0x0a, +0x14, 0x2f, 0x80, 0x07, 0x04, 0x2f, 0x80, 0x09, 0x15, 0xcf, 0x80, 0x0b, 0x58, 0x00, 0x00, 0x38, +0x41, 0xc3, 0x04, 0x0a, 0x58, 0x21, 0x00, 0x3c, 0x14, 0x5f, 0x80, 0x11, 0x14, 0x0f, 0x80, 0x08, +0x15, 0xcf, 0x80, 0x0a, 0x14, 0x2f, 0x80, 0x09, 0x04, 0x0f, 0x80, 0x0e, 0x05, 0xcf, 0x80, 0x0f, +0x40, 0x60, 0x04, 0x0a, 0x14, 0x6f, 0x80, 0x01, 0x04, 0x0f, 0x80, 0x10, 0x04, 0x6f, 0x80, 0x11, +0x40, 0x2e, 0x04, 0x0a, 0x05, 0xcf, 0x80, 0x02, 0x14, 0x2f, 0x80, 0x0e, 0x40, 0x20, 0x04, 0x0a, +0x40, 0x03, 0x04, 0x0a, 0x44, 0x60, 0x31, 0x5c, 0x14, 0x6e, 0x00, 0x00, 0x59, 0xe0, 0x80, 0x00, +0x04, 0x6f, 0x80, 0x0d, 0x05, 0xcf, 0x80, 0x03, 0x14, 0x6e, 0x00, 0x00, 0x44, 0x60, 0x6a, 0xd0, +0x05, 0xcf, 0x80, 0x04, 0x58, 0xa0, 0x80, 0x00, 0x14, 0x6e, 0x00, 0x00, 0x58, 0x90, 0x80, 0x00, +0x04, 0x6f, 0x80, 0x0c, 0x05, 0xcf, 0x80, 0x05, 0x14, 0x6e, 0x00, 0x00, 0x44, 0x60, 0x6a, 0xb8, +0x05, 0xcf, 0x80, 0x06, 0x14, 0x6e, 0x00, 0x00, 0x58, 0x80, 0x80, 0x00, 0x04, 0x6f, 0x80, 0x0b, +0x05, 0xcf, 0x80, 0x07, 0x58, 0x70, 0x80, 0x00, 0x14, 0x6e, 0x00, 0x00, 0x44, 0x60, 0x6a, 0x4c, +0x05, 0xcf, 0x80, 0x08, 0x58, 0x50, 0x80, 0x00, 0x14, 0x6e, 0x00, 0x00, 0x04, 0x6f, 0x80, 0x0a, +0x05, 0xcf, 0x80, 0x09, 0x14, 0x6e, 0x00, 0x00, 0x45, 0xc0, 0x54, 0xd0, 0x15, 0xcf, 0x00, 0x10, +0x45, 0xc0, 0x59, 0x1c, 0x04, 0x6f, 0x80, 0x01, 0x14, 0x65, 0x00, 0x11, 0x15, 0xc4, 0x80, 0x12, +0x58, 0x40, 0x80, 0x00, 0x04, 0x6f, 0x80, 0x0e, 0x45, 0xc0, 0x60, 0x20, 0x58, 0x30, 0x80, 0x00, +0x14, 0x64, 0x00, 0x13, 0x15, 0xc3, 0x80, 0x14, 0x14, 0x22, 0x80, 0x15, 0x44, 0x20, 0x5c, 0xd4, +0x14, 0x22, 0x00, 0x16, 0x14, 0x01, 0x80, 0x17, 0x44, 0x00, 0x00, 0xff, 0x14, 0x00, 0x80, 0x00, +0x51, 0xff, 0x80, 0x4c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x44, 0x60, 0x00, 0x00, 0x3e, 0x67, 0xb0, 0x81, 0x49, 0xf8, 0x2d, 0xa8, +0x46, 0x45, 0x00, 0x29, 0x04, 0x02, 0x00, 0x09, 0x46, 0x10, 0x01, 0x12, 0x58, 0x50, 0x04, 0x00, +0x14, 0x52, 0x00, 0x09, 0x44, 0x30, 0x00, 0x01, 0x2e, 0x07, 0xb4, 0x4f, 0x44, 0x50, 0x00, 0x01, +0x3e, 0x37, 0xb0, 0x81, 0x4c, 0x02, 0xc0, 0x14, 0x47, 0xe5, 0x00, 0x00, 0x59, 0xef, 0x05, 0x94, +0x04, 0x0f, 0x00, 0x00, 0x58, 0x50, 0x01, 0x00, 0x14, 0x5f, 0x00, 0x00, 0x04, 0x4f, 0x00, 0x00, +0x42, 0x22, 0x20, 0x09, 0x14, 0x2f, 0x00, 0x00, 0x3e, 0x67, 0xb4, 0x4f, 0x51, 0xff, 0x80, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x44, 0x00, 0x00, 0x00, 0x44, 0x10, 0x00, 0x08, 0x3e, 0x28, 0x07, 0x00, 0x49, 0xf8, 0x27, 0x62, +0x2e, 0x07, 0xb4, 0x51, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x1a, 0x46, 0x55, 0x00, 0x22, +0x58, 0x52, 0x81, 0x00, 0x05, 0xe2, 0x80, 0x00, 0x04, 0x02, 0x80, 0x00, 0x42, 0x30, 0x7c, 0x08, +0x14, 0x32, 0x80, 0x00, 0x04, 0x22, 0x80, 0x00, 0x44, 0x30, 0x00, 0x00, 0x42, 0x01, 0x7c, 0x09, +0x14, 0x02, 0x80, 0x00, 0x15, 0xe2, 0x80, 0x00, 0x3e, 0x37, 0xb4, 0x51, 0x3e, 0x08, 0x07, 0x00, +0x00, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x00, 0x54, 0x10, 0x80, 0x60, 0x14, 0x20, 0x00, 0x0e, +0x4e, 0x12, 0x00, 0x08, 0x44, 0x50, 0x00, 0x40, 0x4c, 0x12, 0xc0, 0x14, 0x48, 0x00, 0x00, 0x0a, +0x58, 0x10, 0x00, 0x00, 0x50, 0x00, 0x00, 0x28, 0x49, 0xf8, 0x24, 0x02, 0x48, 0x00, 0x00, 0x10, +0x58, 0x10, 0x00, 0x00, 0x50, 0x00, 0x00, 0x28, 0x49, 0xf8, 0x1f, 0xce, 0x48, 0x00, 0x00, 0x08, +0x44, 0x00, 0x00, 0x03, 0x44, 0x10, 0x00, 0x01, 0x49, 0xf8, 0x2c, 0x48, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x3e, 0x68, 0x07, 0x00, +0x44, 0x80, 0x00, 0x00, 0x58, 0x70, 0x80, 0x00, 0x49, 0xf8, 0x16, 0xec, 0x14, 0x83, 0x00, 0x06, +0x04, 0x03, 0x00, 0x03, 0x02, 0x73, 0x80, 0x01, 0x4e, 0x02, 0x00, 0x28, 0x54, 0x73, 0x80, 0xff, +0x5c, 0xf3, 0x80, 0x02, 0x4e, 0xf2, 0x00, 0x22, 0x4e, 0x73, 0x00, 0x0e, 0x49, 0xff, 0xfd, 0x9a, +0x44, 0x10, 0x00, 0x02, 0x14, 0x13, 0x00, 0x03, 0x10, 0x73, 0x00, 0x20, 0x58, 0x03, 0x80, 0x00, +0x48, 0x00, 0x00, 0x16, 0x49, 0xff, 0xfd, 0x8e, 0x49, 0xf8, 0x2c, 0x6a, 0x44, 0x20, 0x00, 0x01, +0x44, 0x30, 0x00, 0x03, 0x10, 0x23, 0x00, 0x20, 0x14, 0x33, 0x00, 0x03, 0x14, 0x23, 0x00, 0x06, +0x58, 0x04, 0x00, 0x00, 0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x01, 0x3a, 0x6f, 0xa0, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x46, 0x00, 0x01, 0x12, +0x2e, 0x17, 0xb4, 0x50, 0x4e, 0x12, 0x00, 0x34, 0x44, 0x40, 0x00, 0x00, 0x3e, 0x47, 0xb4, 0x50, +0x49, 0xf8, 0x2f, 0xfa, 0x49, 0xf8, 0x30, 0x3c, 0x46, 0x38, 0x00, 0x21, 0x04, 0x21, 0x80, 0x4d, +0x54, 0x01, 0x00, 0x02, 0x4e, 0x02, 0x00, 0x12, 0x2e, 0x57, 0xb0, 0xd4, 0x44, 0x10, 0x00, 0x01, +0x4c, 0x50, 0x80, 0x0e, 0x2e, 0x57, 0xb0, 0xd5, 0x4c, 0x50, 0x80, 0x0a, 0x3c, 0x1d, 0xff, 0xb9, +0x4b, 0xe0, 0x04, 0x01, 0x48, 0x00, 0x00, 0x04, 0x49, 0xf8, 0x0e, 0xc8, 0x46, 0x48, 0x00, 0x21, +0x58, 0x42, 0x01, 0x00, 0x04, 0x22, 0x00, 0x00, 0x58, 0x01, 0x00, 0x10, 0x14, 0x02, 0x00, 0x00, +0x05, 0xe2, 0x00, 0x00, 0x58, 0x5f, 0x02, 0x00, 0x14, 0x52, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x2e, 0x07, 0xb4, 0x50, +0x4e, 0x03, 0x00, 0xa6, 0x2e, 0x20, 0x00, 0x26, 0x4e, 0x22, 0x00, 0xa2, 0x44, 0x00, 0x00, 0x04, +0x49, 0xf7, 0xff, 0x3c, 0x46, 0x85, 0x00, 0x25, 0x58, 0x34, 0x00, 0x00, 0x58, 0x11, 0x80, 0x00, +0x46, 0x20, 0x01, 0x20, 0x46, 0x00, 0x20, 0x20, 0x58, 0x70, 0x80, 0x00, 0x58, 0x21, 0x00, 0x12, +0x58, 0x00, 0x02, 0x02, 0x44, 0x60, 0x00, 0x0f, 0x44, 0x50, 0x00, 0x05, 0x14, 0x61, 0x81, 0xec, +0x14, 0x20, 0x81, 0xed, 0x14, 0x04, 0x01, 0xef, 0x14, 0x53, 0x81, 0xf0, 0x2e, 0x77, 0xb4, 0x53, +0x4e, 0x73, 0x00, 0x1e, 0x58, 0x60, 0x80, 0x00, 0x48, 0x00, 0x00, 0x10, 0x44, 0x50, 0x00, 0x05, +0x4c, 0x72, 0xc0, 0x06, 0x44, 0x00, 0x00, 0x04, 0x48, 0x00, 0x00, 0x70, 0x49, 0xf8, 0x03, 0x24, +0x50, 0x43, 0x80, 0x01, 0x54, 0x72, 0x00, 0xff, 0x04, 0x13, 0x01, 0xf1, 0x44, 0x20, 0x00, 0x90, +0x54, 0x50, 0x80, 0x90, 0x44, 0x00, 0x00, 0x01, 0x4c, 0x51, 0x7f, 0xea, 0x47, 0xe8, 0x00, 0x21, +0x59, 0xef, 0x01, 0x00, 0x04, 0x0f, 0x00, 0x00, 0x42, 0x10, 0x24, 0x09, 0x14, 0x1f, 0x00, 0x00, +0x04, 0x2f, 0x00, 0x00, 0x42, 0x51, 0x10, 0x09, 0x14, 0x5f, 0x00, 0x00, 0x49, 0x00, 0x00, 0x78, +0x44, 0x00, 0x00, 0x01, 0x44, 0x10, 0x00, 0x75, 0x44, 0x20, 0x00, 0x00, 0x49, 0xf8, 0x2d, 0x12, +0x2e, 0x07, 0xb4, 0x52, 0x4e, 0x02, 0x00, 0x3c, 0x2f, 0xe7, 0xb4, 0x53, 0x4f, 0xe3, 0x00, 0x38, +0x46, 0x15, 0x00, 0x29, 0x05, 0xe0, 0x80, 0x84, 0x42, 0x3f, 0x00, 0x09, 0x14, 0x30, 0x80, 0x84, +0x46, 0x05, 0x00, 0x25, 0x58, 0x00, 0x08, 0x68, 0x04, 0x50, 0x00, 0x00, 0x43, 0xe2, 0xc4, 0x08, +0x15, 0xe0, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x42, 0x11, 0x88, 0x09, 0x14, 0x10, 0x00, 0x00, +0x44, 0x4f, 0xff, 0xcf, 0x04, 0x50, 0x00, 0x00, 0x43, 0xe2, 0xcc, 0x08, 0x15, 0xe0, 0x00, 0x00, +0x04, 0x30, 0x00, 0x00, 0x40, 0x11, 0x90, 0x02, 0x14, 0x10, 0x00, 0x00, 0x04, 0x50, 0x00, 0x00, +0x43, 0xe2, 0xc8, 0x08, 0x15, 0xe0, 0x00, 0x00, 0x44, 0x50, 0x00, 0x01, 0x04, 0x30, 0x00, 0x00, +0x42, 0x11, 0x8c, 0x09, 0x14, 0x10, 0x00, 0x00, 0x3e, 0x57, 0xb4, 0x53, 0x44, 0x20, 0x00, 0x01, +0x3e, 0x27, 0xb4, 0x50, 0x44, 0x00, 0x00, 0x04, 0x49, 0xf7, 0xfe, 0xc8, 0x3a, 0x6f, 0xa0, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x2e, 0x00, 0x02, 0x85, 0x4e, 0x03, 0x00, 0x1c, +0x2e, 0x20, 0x02, 0x86, 0x4e, 0x23, 0x00, 0x18, 0x2e, 0x60, 0x02, 0x87, 0x4e, 0x63, 0x00, 0x14, +0x44, 0x00, 0x00, 0x01, 0x49, 0xf8, 0x0f, 0x6c, 0x44, 0x00, 0x00, 0x04, 0x49, 0xf8, 0x02, 0x9c, +0x3e, 0x60, 0x02, 0x88, 0x46, 0x58, 0x00, 0x21, 0x04, 0x12, 0x80, 0x40, 0x42, 0x00, 0x9c, 0x09, +0x14, 0x02, 0x80, 0x40, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x2e, 0x07, 0xb0, 0xd4, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x08, +0x2e, 0x57, 0xb0, 0xd5, 0x4c, 0x50, 0x40, 0x04, 0x49, 0xff, 0xff, 0xce, 0x2e, 0x40, 0x02, 0x88, +0x4e, 0x42, 0x00, 0x0c, 0x2e, 0x57, 0xb0, 0xd4, 0x44, 0x10, 0x00, 0x01, 0x4c, 0x50, 0x80, 0x06, +0x2e, 0x57, 0xb0, 0xd5, 0x4c, 0x50, 0xc0, 0x04, 0x49, 0xf8, 0x2e, 0xb6, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x2e, 0x17, 0xb1, 0x11, 0x40, 0x20, 0x80, 0x10, +0x4e, 0x25, 0x00, 0x06, 0x44, 0x00, 0x00, 0x3c, 0x48, 0x00, 0x00, 0x1c, 0x2e, 0x07, 0xb1, 0x12, +0x40, 0x30, 0x00, 0x10, 0x4e, 0x34, 0x00, 0x14, 0x54, 0x40, 0x00, 0x40, 0x54, 0x10, 0x80, 0x7f, +0x54, 0x00, 0x00, 0x3f, 0x4e, 0x43, 0x00, 0x06, 0x40, 0x00, 0x04, 0x00, 0x48, 0x00, 0x00, 0x0a, +0x40, 0x00, 0x80, 0x01, 0x54, 0x00, 0x00, 0xff, 0x48, 0x00, 0x00, 0x04, 0x54, 0x00, 0x80, 0x7f, +0x2e, 0x27, 0xb1, 0x13, 0x40, 0x11, 0x00, 0x10, 0x4e, 0x14, 0x00, 0x36, 0x46, 0x18, 0x00, 0x21, +0x04, 0x30, 0x80, 0x8d, 0x44, 0x5f, 0x80, 0xff, 0x40, 0x40, 0x20, 0x08, 0x54, 0x42, 0x7f, 0x00, +0x40, 0x31, 0x94, 0x02, 0x40, 0x32, 0x0c, 0x04, 0x14, 0x30, 0x80, 0x8d, 0x04, 0x50, 0x80, 0x8e, +0x54, 0x31, 0x00, 0x40, 0x58, 0x42, 0xff, 0x00, 0x14, 0x40, 0x80, 0x8e, 0x54, 0x21, 0x00, 0x3f, +0x4e, 0x33, 0x00, 0x06, 0x40, 0x00, 0x08, 0x00, 0x48, 0x00, 0x00, 0x04, 0x40, 0x00, 0x08, 0x01, +0x46, 0x18, 0x00, 0x21, 0x54, 0x50, 0x00, 0xff, 0x04, 0x40, 0x80, 0x8d, 0x40, 0x02, 0xa0, 0x08, +0x44, 0x3f, 0x80, 0xff, 0x54, 0x50, 0x7f, 0x00, 0x40, 0x22, 0x0c, 0x02, 0x40, 0x02, 0x88, 0x04, +0x14, 0x00, 0x80, 0x8d, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x36, 0x03, 0x10, 0x04, 0x51, 0x80, 0x02, +0x58, 0x41, 0x80, 0x00, 0x40, 0x00, 0x14, 0x04, 0x14, 0x01, 0x80, 0x02, 0x04, 0x02, 0x00, 0x03, +0x40, 0x50, 0x80, 0x04, 0x14, 0x52, 0x00, 0x03, 0x04, 0x11, 0x80, 0x0a, 0x44, 0x00, 0x00, 0x00, +0x40, 0x21, 0x04, 0x04, 0x14, 0x21, 0x80, 0x0a, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x36, 0x03, 0x10, +0x04, 0x41, 0x80, 0x02, 0x40, 0x00, 0x00, 0x05, 0x40, 0x50, 0x10, 0x02, 0x14, 0x51, 0x80, 0x02, +0x58, 0x41, 0x80, 0x00, 0x04, 0x32, 0x00, 0x03, 0x40, 0x00, 0x84, 0x05, 0x40, 0x50, 0x0c, 0x02, +0x14, 0x52, 0x00, 0x03, 0x58, 0x02, 0x00, 0x00, 0x04, 0x10, 0x00, 0x0a, 0x40, 0x31, 0x08, 0x05, +0x40, 0x21, 0x84, 0x02, 0x14, 0x20, 0x00, 0x0a, 0x44, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, +0x46, 0x36, 0x03, 0x30, 0x44, 0x4e, 0x0f, 0xff, 0x04, 0x51, 0x80, 0x00, 0x40, 0x00, 0x10, 0x02, +0x44, 0x41, 0xf0, 0x00, 0x40, 0x32, 0x90, 0x02, 0x54, 0x21, 0x00, 0xff, 0x40, 0x30, 0x0c, 0x04, +0x4e, 0x22, 0x00, 0x06, 0x42, 0x31, 0xfc, 0x09, 0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xfc, 0x08, +0x46, 0x56, 0x03, 0x30, 0x58, 0x02, 0x80, 0x00, 0x14, 0x32, 0x80, 0x00, 0x14, 0x10, 0x00, 0x01, +0x44, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x54, 0x00, 0x00, 0xff, 0x54, 0x10, 0x80, 0xff, +0x5c, 0xf0, 0x00, 0x04, 0x4e, 0xf2, 0x00, 0x1c, 0x46, 0x26, 0x01, 0x60, 0x04, 0x31, 0x00, 0x1c, +0x5c, 0xf0, 0x80, 0x02, 0x4e, 0xf2, 0x00, 0x14, 0x40, 0x31, 0x8c, 0x08, 0x40, 0x31, 0x8c, 0x09, +0x40, 0x50, 0x78, 0x08, 0x40, 0x01, 0x94, 0x04, 0x40, 0x30, 0xf4, 0x08, 0x40, 0x10, 0x0c, 0x04, +0x14, 0x11, 0x00, 0x1c, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x01, +0x4a, 0x00, 0x78, 0x20, 0x46, 0x16, 0x01, 0x60, 0x04, 0x40, 0x80, 0x1c, 0x46, 0x3f, 0x08, 0x00, +0x40, 0x22, 0x0c, 0x02, 0x40, 0x00, 0x08, 0x04, 0x14, 0x00, 0x80, 0x1c, 0x44, 0x00, 0x00, 0x00, +0x4a, 0x00, 0x78, 0x20, 0x54, 0x00, 0x00, 0xff, 0x54, 0x10, 0x80, 0xff, 0x54, 0x21, 0x00, 0xff, +0x54, 0x31, 0x80, 0xff, 0x54, 0x42, 0x00, 0xff, 0x4e, 0x02, 0x00, 0x0c, 0x40, 0x52, 0x00, 0x10, +0x4e, 0x55, 0x00, 0x38, 0x40, 0x02, 0x20, 0x08, 0x54, 0x40, 0x3f, 0x00, 0x42, 0x42, 0x74, 0x08, +0x5c, 0xf1, 0x00, 0x04, 0x4e, 0xf2, 0x00, 0x2e, 0x5c, 0xf1, 0x80, 0x0e, 0x4e, 0xf2, 0x00, 0x2a, +0x46, 0x01, 0xf0, 0x00, 0x40, 0x10, 0xe0, 0x08, 0x40, 0x50, 0x80, 0x02, 0x46, 0x00, 0x0c, 0x00, +0x40, 0x21, 0x58, 0x08, 0x42, 0x12, 0xfc, 0x08, 0x40, 0x51, 0x00, 0x02, 0x46, 0x00, 0x01, 0xf0, +0x40, 0x31, 0xc0, 0x08, 0x40, 0x20, 0x94, 0x04, 0x40, 0x51, 0x80, 0x02, 0x40, 0x31, 0x14, 0x04, +0x46, 0x06, 0x01, 0x60, 0x40, 0x11, 0x90, 0x04, 0x14, 0x10, 0x00, 0x02, 0x04, 0x30, 0x00, 0x02, +0x42, 0x41, 0xf8, 0x0b, 0x4e, 0x42, 0xff, 0xfc, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x04, +0x44, 0x00, 0x00, 0x01, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x36, 0x01, 0x60, 0x04, 0x31, 0x80, 0x03, +0x40, 0x51, 0xa0, 0x08, 0x54, 0x41, 0x8f, 0xff, 0x40, 0x31, 0xe0, 0x09, 0x10, 0x30, 0x00, 0x00, +0x40, 0x52, 0xd0, 0x09, 0x44, 0x00, 0x00, 0x00, 0x12, 0x50, 0x80, 0x00, 0x12, 0x41, 0x00, 0x00, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0x3c, 0x5c, 0xf0, 0x00, 0x02, 0x4e, 0xf3, 0x00, 0x06, +0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x01, 0x60, 0x46, 0x56, 0x01, 0x30, 0x58, 0x52, 0x80, 0x40, +0x50, 0x72, 0xff, 0xf0, 0x50, 0x62, 0x80, 0x10, 0x50, 0x83, 0xff, 0xf0, 0x40, 0x44, 0x00, 0x1a, +0x40, 0x42, 0x80, 0x1b, 0x40, 0x53, 0x80, 0x1a, 0x40, 0x53, 0x00, 0x1b, 0x44, 0x00, 0x00, 0x01, +0x4c, 0x10, 0x00, 0x12, 0x4e, 0x12, 0x00, 0x0c, 0x44, 0x00, 0x00, 0x02, 0x4c, 0x10, 0x00, 0x14, +0x44, 0x00, 0x00, 0x03, 0x4c, 0x10, 0x40, 0x1e, 0x48, 0x00, 0x00, 0x12, 0x50, 0x42, 0x00, 0x0c, +0x48, 0x00, 0x00, 0x18, 0x44, 0x00, 0x00, 0x05, 0x4c, 0x20, 0x40, 0x14, 0x50, 0x42, 0x00, 0x0c, +0x48, 0x00, 0x00, 0xfc, 0x50, 0x42, 0x00, 0x04, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x00, 0x00, 0x06, +0x4c, 0x20, 0x40, 0x06, 0x50, 0x42, 0x00, 0x0c, 0x48, 0x00, 0x01, 0x0c, 0x50, 0x42, 0x00, 0x08, +0x44, 0x00, 0x00, 0x03, 0x4c, 0x20, 0x00, 0x6c, 0x5c, 0xf1, 0x00, 0x04, 0x4e, 0xf2, 0x00, 0x0c, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x22, 0x80, 0x2e, 0x5c, 0xf1, 0x00, 0x02, 0x4e, 0xf2, 0x00, 0x48, +0x48, 0x00, 0x00, 0x10, 0x44, 0x00, 0x00, 0x05, 0x4c, 0x20, 0x00, 0x9a, 0x40, 0xf1, 0x00, 0x06, +0x4e, 0xf3, 0x00, 0x64, 0x44, 0x00, 0x00, 0x06, 0x4c, 0x20, 0x41, 0x04, 0x48, 0x00, 0x00, 0xe6, +0x4e, 0x13, 0x00, 0x0e, 0x04, 0x22, 0x00, 0x00, 0x46, 0x5f, 0xf8, 0x0f, 0x58, 0x52, 0x8f, 0xff, +0x58, 0x00, 0x80, 0x00, 0x40, 0x11, 0x14, 0x02, 0x48, 0x00, 0x00, 0x36, 0x04, 0x12, 0x00, 0x00, +0x44, 0x00, 0x00, 0x00, 0x40, 0x10, 0x9c, 0x09, 0x40, 0x10, 0x9c, 0x08, 0x48, 0x00, 0x00, 0x0c, +0x4e, 0x13, 0x00, 0x14, 0x04, 0x22, 0x00, 0x00, 0x58, 0x00, 0x80, 0x00, 0x40, 0x11, 0x1c, 0x09, +0x40, 0x10, 0x9c, 0x08, 0x14, 0x12, 0x00, 0x00, 0x00, 0x11, 0x80, 0x00, 0x04, 0x22, 0x00, 0x00, +0x54, 0x10, 0x80, 0x7f, 0x48, 0x00, 0x00, 0xb4, 0x04, 0x52, 0x00, 0x00, 0x44, 0x2f, 0x80, 0xff, +0x44, 0x00, 0x00, 0x00, 0x40, 0x12, 0x88, 0x02, 0x48, 0x00, 0x00, 0xa0, 0x4e, 0x12, 0x00, 0xca, +0x04, 0x12, 0x00, 0x00, 0x46, 0x5f, 0xf8, 0x0f, 0x58, 0x52, 0x8f, 0xff, 0x44, 0x00, 0x00, 0x00, +0x40, 0x10, 0x94, 0x02, 0x14, 0x12, 0x00, 0x00, 0x00, 0x11, 0x80, 0x00, 0x46, 0x30, 0x07, 0xf0, +0x04, 0x22, 0x00, 0x00, 0x40, 0x10, 0xc0, 0x08, 0x48, 0x00, 0x00, 0xb0, 0x4e, 0x12, 0x00, 0xb2, +0x04, 0x22, 0x00, 0x00, 0x46, 0x58, 0x0f, 0xff, 0x58, 0x52, 0x8f, 0xff, 0x44, 0x00, 0x00, 0x00, +0x40, 0x11, 0x14, 0x02, 0x48, 0x00, 0x00, 0x98, 0x44, 0x40, 0x00, 0x02, 0x4c, 0x12, 0x00, 0x08, +0x44, 0x00, 0x00, 0x03, 0x4c, 0x10, 0x40, 0x9e, 0x48, 0x00, 0x00, 0x14, 0x04, 0x12, 0x80, 0x00, +0x40, 0x40, 0x9c, 0x09, 0x40, 0x42, 0x1c, 0x08, 0x14, 0x42, 0x80, 0x00, 0x44, 0x00, 0x00, 0x00, +0x00, 0x11, 0x80, 0x00, 0x04, 0x22, 0x80, 0x00, 0x54, 0x10, 0x80, 0x7f, 0x48, 0x00, 0x00, 0x38, +0x04, 0x42, 0x80, 0x00, 0x46, 0x2f, 0xf8, 0x0f, 0x58, 0x21, 0x0f, 0xff, 0x40, 0x12, 0x08, 0x02, +0x14, 0x12, 0x80, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x41, 0x80, 0x00, 0x46, 0x30, 0x07, 0xf0, +0x04, 0x22, 0x80, 0x00, 0x40, 0x12, 0x40, 0x08, 0x48, 0x00, 0x00, 0x3c, 0x44, 0x00, 0x00, 0x02, +0x4c, 0x10, 0x00, 0x0c, 0x44, 0x20, 0x00, 0x03, 0x4c, 0x11, 0x00, 0x20, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x12, 0xc0, 0x68, 0x48, 0x00, 0x00, 0x32, 0x04, 0x12, 0x80, 0x00, 0x44, 0x2f, 0x80, 0xff, +0x40, 0x40, 0x88, 0x02, 0x14, 0x42, 0x80, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x11, 0x80, 0x00, +0x04, 0x22, 0x80, 0x00, 0x40, 0x30, 0xa0, 0x08, 0x54, 0x11, 0xff, 0x00, 0x40, 0x31, 0x04, 0x04, +0x14, 0x32, 0x80, 0x00, 0x48, 0x00, 0x00, 0x50, 0x04, 0x42, 0x80, 0x00, 0x46, 0x28, 0x0f, 0xff, +0x58, 0x21, 0x0f, 0xff, 0x40, 0x12, 0x08, 0x02, 0x14, 0x12, 0x80, 0x00, 0x44, 0x00, 0x00, 0x00, +0x00, 0x41, 0x80, 0x00, 0x04, 0x22, 0x80, 0x00, 0x46, 0x37, 0xf0, 0x00, 0x40, 0x12, 0x60, 0x08, +0x40, 0x10, 0x8c, 0x02, 0x48, 0xff, 0xff, 0xe4, 0x04, 0x12, 0x00, 0x00, 0x44, 0x5f, 0x80, 0xff, +0x44, 0x00, 0x00, 0x00, 0x40, 0x10, 0x94, 0x02, 0x14, 0x12, 0x00, 0x00, 0x00, 0x11, 0x80, 0x00, +0x04, 0x22, 0x00, 0x00, 0x40, 0x30, 0xa0, 0x08, 0x54, 0x11, 0xff, 0x00, 0x40, 0x51, 0x04, 0x04, +0x14, 0x52, 0x00, 0x00, 0x48, 0x00, 0x00, 0x20, 0x44, 0x00, 0x00, 0x03, 0x4c, 0x10, 0x40, 0x1a, +0x04, 0x12, 0x00, 0x00, 0x46, 0x28, 0x0f, 0xff, 0x58, 0x21, 0x0f, 0xff, 0x44, 0x00, 0x00, 0x00, +0x40, 0x10, 0x88, 0x02, 0x14, 0x12, 0x00, 0x00, 0x00, 0x51, 0x80, 0x00, 0x04, 0x22, 0x00, 0x00, +0x46, 0x37, 0xf0, 0x00, 0x40, 0x12, 0xe0, 0x08, 0x40, 0x10, 0x8c, 0x02, 0x48, 0xff, 0xff, 0xe0, +0x44, 0x00, 0x00, 0x00, 0x3a, 0x6f, 0xa0, 0x04, 0x4a, 0x00, 0x78, 0x20, 0x54, 0x00, 0x00, 0xff, +0x54, 0x10, 0x80, 0xff, 0x5c, 0xf0, 0x00, 0x0e, 0x4e, 0xf2, 0x00, 0x12, 0x44, 0x20, 0x00, 0x01, +0x40, 0x21, 0x00, 0x0c, 0x54, 0x31, 0x3e, 0x00, 0x4e, 0x33, 0x00, 0x18, 0x54, 0x41, 0x01, 0x80, +0x4e, 0x43, 0x00, 0x0a, 0x54, 0x51, 0x00, 0x3f, 0x4e, 0x53, 0x00, 0x08, 0x44, 0x00, 0x00, 0x02, +0x48, 0x00, 0x00, 0x2c, 0x50, 0x00, 0x7f, 0xff, 0x46, 0x26, 0x01, 0x20, 0x40, 0x00, 0x08, 0x08, +0x58, 0x21, 0x00, 0x20, 0x48, 0x00, 0x00, 0x0a, 0x50, 0x00, 0x7f, 0xf7, 0x46, 0x26, 0x01, 0x20, +0x40, 0x00, 0x08, 0x08, 0x58, 0x21, 0x00, 0x24, 0x44, 0x30, 0x00, 0x0f, 0x04, 0x41, 0x00, 0x00, +0x40, 0x31, 0x80, 0x0c, 0x40, 0x51, 0x8c, 0x05, 0x40, 0x42, 0x90, 0x02, 0x14, 0x41, 0x00, 0x00, +0x40, 0x50, 0x80, 0x0c, 0x04, 0x41, 0x00, 0x00, 0x40, 0x32, 0x8c, 0x02, 0x40, 0x11, 0x90, 0x04, +0x14, 0x11, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x44, 0x20, 0x00, 0x07, +0x54, 0x00, 0x00, 0xff, 0x54, 0x10, 0x80, 0xff, 0x4c, 0x01, 0x00, 0x2a, 0x5c, 0xf0, 0x00, 0x08, +0x4e, 0xf2, 0x00, 0x0c, 0x5c, 0xf0, 0x00, 0x04, 0x4e, 0xf3, 0x00, 0x2a, 0x5c, 0xf0, 0x00, 0x06, +0x4e, 0xf2, 0x00, 0x12, 0x48, 0x00, 0x00, 0x2e, 0x5c, 0xf0, 0x00, 0x0d, 0x4e, 0xf2, 0x00, 0x08, +0x5c, 0xf0, 0x00, 0x09, 0x4e, 0xf2, 0x00, 0x30, 0x48, 0x00, 0x00, 0x0a, 0x44, 0x50, 0x00, 0x0d, +0x4c, 0x02, 0x80, 0x36, 0x44, 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x50, 0x46, 0x06, 0x01, 0x20, +0x58, 0x00, 0x00, 0x44, 0x50, 0x21, 0x00, 0x11, 0x48, 0x00, 0x00, 0x30, 0x46, 0x06, 0x01, 0x20, +0x58, 0x00, 0x00, 0x44, 0x50, 0x21, 0x00, 0x09, 0x48, 0x00, 0x00, 0x28, 0x40, 0x40, 0x0c, 0x08, +0x46, 0x06, 0x01, 0x20, 0x54, 0x22, 0x00, 0x1f, 0x58, 0x00, 0x00, 0x40, 0x48, 0x00, 0x00, 0x1e, +0x50, 0x50, 0x7f, 0xfc, 0x46, 0x06, 0x01, 0x20, 0x40, 0x22, 0x8c, 0x08, 0x58, 0x00, 0x00, 0x44, +0x48, 0x00, 0x00, 0x14, 0x50, 0x30, 0x7f, 0xf7, 0x40, 0x21, 0x8c, 0x08, 0x46, 0x06, 0x01, 0x20, +0x54, 0x21, 0x00, 0x1f, 0x58, 0x00, 0x00, 0x48, 0x48, 0x00, 0x00, 0x08, 0x46, 0x06, 0x01, 0x20, +0x58, 0x00, 0x00, 0x4c, 0x44, 0x20, 0x00, 0x00, 0x44, 0x30, 0x00, 0xff, 0x04, 0x40, 0x00, 0x00, +0x40, 0x31, 0x88, 0x0c, 0x40, 0x51, 0x8c, 0x05, 0x40, 0x42, 0x90, 0x02, 0x14, 0x40, 0x00, 0x00, +0x40, 0x20, 0x88, 0x0c, 0x04, 0x40, 0x00, 0x00, 0x40, 0x51, 0x0c, 0x02, 0x40, 0x12, 0x90, 0x04, +0x14, 0x10, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0x3c, +0x54, 0x20, 0x00, 0xff, 0x40, 0x10, 0x80, 0x13, 0x5c, 0xf1, 0x00, 0x0e, 0x4e, 0xf3, 0x00, 0x06, +0x44, 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x2a, 0x3e, 0x0f, 0x9a, 0x38, 0x38, 0x00, 0x0a, 0x02, +0x3e, 0x3f, 0x9a, 0x70, 0x38, 0x31, 0x8a, 0x02, 0x4e, 0x03, 0x00, 0x20, 0x54, 0x21, 0x00, 0x01, +0x44, 0x50, 0x00, 0x10, 0x40, 0x42, 0x88, 0x1b, 0x40, 0x40, 0x08, 0x1a, 0x44, 0x60, 0xff, 0xff, +0x40, 0x23, 0x10, 0x0c, 0x04, 0x51, 0x80, 0x00, 0x40, 0x61, 0x08, 0x05, 0x40, 0x53, 0x14, 0x02, +0x14, 0x51, 0x80, 0x00, 0x40, 0x40, 0x90, 0x0c, 0x04, 0x51, 0x80, 0x00, 0x40, 0x12, 0x08, 0x02, +0x40, 0x20, 0x94, 0x04, 0x14, 0x21, 0x80, 0x00, 0x3a, 0x6f, 0x98, 0x04, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x98, 0x3c, 0x54, 0x20, 0x00, 0xff, 0x40, 0x10, 0x80, 0x13, 0x5c, 0xf1, 0x00, 0x0d, +0x4e, 0xf3, 0x00, 0x06, 0x44, 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x2a, 0x3e, 0x0f, 0x9a, 0xa8, +0x38, 0x00, 0x0a, 0x02, 0x3e, 0x3f, 0x9a, 0xdc, 0x38, 0x31, 0x8a, 0x02, 0x4e, 0x03, 0x00, 0x20, +0x54, 0x21, 0x00, 0x01, 0x44, 0x50, 0x00, 0x10, 0x40, 0x42, 0x88, 0x1b, 0x40, 0x40, 0x08, 0x1a, +0x44, 0x60, 0xff, 0xff, 0x40, 0x23, 0x10, 0x0c, 0x04, 0x51, 0x80, 0x00, 0x40, 0x61, 0x08, 0x05, +0x40, 0x53, 0x14, 0x02, 0x14, 0x51, 0x80, 0x00, 0x40, 0x40, 0x90, 0x0c, 0x04, 0x51, 0x80, 0x00, +0x40, 0x12, 0x08, 0x02, 0x40, 0x20, 0x94, 0x04, 0x14, 0x21, 0x80, 0x00, 0x3a, 0x6f, 0x98, 0x04, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x44, 0x20, 0x00, 0x01, +0x40, 0x10, 0x80, 0x13, 0x4c, 0x01, 0x00, 0x22, 0x4e, 0x02, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x02, 0x80, 0x32, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x56, 0x48, 0x00, 0x00, 0x3e, +0x46, 0x06, 0x01, 0x30, 0x58, 0x00, 0x00, 0xa4, 0x05, 0xe0, 0x00, 0x00, 0x46, 0x28, 0x0f, 0xff, +0x58, 0x21, 0x0f, 0xff, 0x40, 0x5f, 0x08, 0x02, 0x46, 0x27, 0xf0, 0x00, 0x40, 0x10, 0xe0, 0x08, +0x14, 0x50, 0x00, 0x00, 0x48, 0x00, 0x00, 0x14, 0x46, 0x06, 0x01, 0x30, 0x58, 0x00, 0x00, 0xa4, +0x04, 0x50, 0x00, 0x00, 0x46, 0x3f, 0xf8, 0x0f, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x42, 0x8c, 0x02, +0x46, 0x20, 0x07, 0xf0, 0x14, 0x40, 0x00, 0x00, 0x40, 0x10, 0xc0, 0x08, 0x40, 0x10, 0x88, 0x02, +0x48, 0x00, 0x00, 0x22, 0x46, 0x06, 0x01, 0x30, 0x58, 0x00, 0x00, 0xa4, 0x04, 0x20, 0x00, 0x00, +0x44, 0x4f, 0x83, 0xff, 0x40, 0x10, 0xa8, 0x08, 0x41, 0xe1, 0x10, 0x02, 0x15, 0xe0, 0x00, 0x00, +0x54, 0x10, 0xfc, 0x00, 0x48, 0x00, 0x00, 0x10, 0x46, 0x06, 0x01, 0x30, 0x58, 0x00, 0x00, 0xa4, +0x05, 0xe0, 0x00, 0x00, 0x40, 0x5f, 0x24, 0x09, 0x40, 0x52, 0xa4, 0x08, 0x14, 0x50, 0x00, 0x00, +0x54, 0x10, 0x81, 0xff, 0x04, 0x20, 0x00, 0x00, 0x40, 0x10, 0x88, 0x04, 0x14, 0x10, 0x00, 0x00, +0x48, 0x00, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x99, 0x50, 0x44, 0x20, 0x2e, 0x38, +0x49, 0xf8, 0x02, 0xce, 0x48, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x54, 0x00, 0x00, 0xff, 0x54, 0x10, 0x80, 0xff, 0x5c, 0xf0, 0x00, 0x0e, 0x4e, 0xf2, 0x00, 0xb4, +0x5c, 0xf0, 0x80, 0x04, 0x4e, 0xf2, 0x00, 0xb0, 0x50, 0x30, 0x7f, 0xf9, 0x54, 0x21, 0x80, 0xff, +0x5c, 0xf1, 0x00, 0x02, 0x4e, 0xf3, 0x00, 0xa8, 0x44, 0x50, 0x00, 0x05, 0x4c, 0x02, 0x80, 0x58, +0x5c, 0xf0, 0x00, 0x06, 0x4e, 0xf2, 0x00, 0x1c, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0x80, 0x3e, +0x5c, 0xf0, 0x00, 0x03, 0x4e, 0xf2, 0x00, 0x0a, 0x4e, 0x02, 0x00, 0x88, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0xc0, 0x7a, 0x48, 0x00, 0x00, 0x2c, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0x80, 0x34, +0x44, 0x50, 0x00, 0x04, 0x4c, 0x02, 0xc0, 0x70, 0x48, 0x00, 0x00, 0x34, 0x44, 0x50, 0x00, 0x0a, +0x4c, 0x02, 0x80, 0x4a, 0x5c, 0xf0, 0x00, 0x0b, 0x4e, 0xf2, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x06, +0x4c, 0x02, 0x80, 0x36, 0x44, 0x50, 0x00, 0x09, 0x4c, 0x02, 0xc0, 0x5e, 0x48, 0x00, 0x00, 0x36, +0x44, 0x20, 0x00, 0x0c, 0x4c, 0x01, 0x00, 0x48, 0x40, 0xf0, 0x08, 0x06, 0x4e, 0xf3, 0x00, 0x3c, +0x44, 0x50, 0x00, 0x0d, 0x4c, 0x02, 0xc0, 0x50, 0x48, 0x00, 0x00, 0x46, 0x46, 0x06, 0x01, 0x20, +0x58, 0x00, 0x01, 0x10, 0x48, 0x00, 0x00, 0x2c, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x10, +0x48, 0x00, 0x00, 0x2e, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x10, 0x48, 0x00, 0x00, 0x30, +0x46, 0x20, 0x02, 0x00, 0x46, 0x06, 0x01, 0x20, 0x48, 0x00, 0x00, 0x06, 0x46, 0x20, 0x40, 0x00, +0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x10, 0x48, 0x00, 0x00, 0x3e, 0x46, 0x20, 0x40, 0x00, +0x46, 0x06, 0x01, 0x20, 0x48, 0x00, 0x00, 0x24, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x14, +0x48, 0x00, 0x00, 0x30, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x14, 0x44, 0x20, 0x00, 0x20, +0x48, 0x00, 0x00, 0x2a, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x14, 0x44, 0x20, 0x04, 0x00, +0x48, 0x00, 0x00, 0x22, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x14, 0x44, 0x21, 0x00, 0x00, +0x48, 0x00, 0x00, 0x1a, 0x46, 0x20, 0x02, 0x00, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x14, +0x48, 0x00, 0x00, 0x12, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x99, 0x50, 0x44, 0x20, 0x1e, 0x4a, +0x49, 0xf8, 0x02, 0x16, 0x48, 0x00, 0x00, 0x00, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x10, +0x44, 0x20, 0x00, 0x01, 0x40, 0x31, 0x04, 0x0c, 0x14, 0x30, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, +0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x54, 0x10, 0x80, 0xff, 0x54, 0x00, 0x00, 0xff, 0x5c, 0xf0, 0x80, 0x03, +0x4e, 0xf2, 0x00, 0x20, 0x50, 0x30, 0x7f, 0xf9, 0x54, 0x21, 0x80, 0xff, 0x5c, 0xf1, 0x00, 0x02, +0x4e, 0xf2, 0x00, 0x18, 0x46, 0x36, 0x01, 0x20, 0x56, 0x50, 0x00, 0x08, 0x58, 0x31, 0x81, 0x20, +0x44, 0x00, 0x00, 0x01, 0x50, 0x21, 0xff, 0xf8, 0x40, 0x10, 0x04, 0x0c, 0x40, 0x41, 0x94, 0x1a, +0x40, 0x41, 0x14, 0x1b, 0x14, 0x12, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x04, +0x44, 0x00, 0x00, 0x01, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x54, 0x00, 0x00, 0xff, 0x54, 0x10, 0x80, 0xff, 0x5c, 0xf0, 0x00, 0x0e, 0x4e, 0xf2, 0x00, 0xb4, +0x5c, 0xf0, 0x80, 0x04, 0x4e, 0xf2, 0x00, 0xb0, 0x50, 0x30, 0x7f, 0xf9, 0x54, 0x21, 0x80, 0xff, +0x5c, 0xf1, 0x00, 0x02, 0x4e, 0xf3, 0x00, 0xa8, 0x44, 0x50, 0x00, 0x05, 0x4c, 0x02, 0x80, 0x58, +0x5c, 0xf0, 0x00, 0x06, 0x4e, 0xf2, 0x00, 0x1c, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0x80, 0x3e, +0x5c, 0xf0, 0x00, 0x03, 0x4e, 0xf2, 0x00, 0x0a, 0x4e, 0x02, 0x00, 0x88, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0xc0, 0x7a, 0x48, 0x00, 0x00, 0x2c, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0x80, 0x34, +0x44, 0x50, 0x00, 0x04, 0x4c, 0x02, 0xc0, 0x70, 0x48, 0x00, 0x00, 0x34, 0x44, 0x50, 0x00, 0x0a, +0x4c, 0x02, 0x80, 0x4a, 0x5c, 0xf0, 0x00, 0x0b, 0x4e, 0xf2, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x06, +0x4c, 0x02, 0x80, 0x36, 0x44, 0x50, 0x00, 0x09, 0x4c, 0x02, 0xc0, 0x5e, 0x48, 0x00, 0x00, 0x36, +0x44, 0x20, 0x00, 0x0c, 0x4c, 0x01, 0x00, 0x48, 0x40, 0xf0, 0x08, 0x06, 0x4e, 0xf3, 0x00, 0x3c, +0x44, 0x50, 0x00, 0x0d, 0x4c, 0x02, 0xc0, 0x50, 0x48, 0x00, 0x00, 0x46, 0x46, 0x06, 0x01, 0x20, +0x58, 0x00, 0x01, 0x00, 0x48, 0x00, 0x00, 0x2c, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x00, +0x48, 0x00, 0x00, 0x2e, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x00, 0x48, 0x00, 0x00, 0x30, +0x46, 0x20, 0x02, 0x00, 0x46, 0x06, 0x01, 0x20, 0x48, 0x00, 0x00, 0x06, 0x46, 0x20, 0x40, 0x00, +0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x00, 0x48, 0x00, 0x00, 0x3e, 0x46, 0x20, 0x40, 0x00, +0x46, 0x06, 0x01, 0x20, 0x48, 0x00, 0x00, 0x24, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x04, +0x48, 0x00, 0x00, 0x30, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x04, 0x44, 0x20, 0x00, 0x20, +0x48, 0x00, 0x00, 0x2a, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x04, 0x44, 0x20, 0x04, 0x00, +0x48, 0x00, 0x00, 0x22, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x04, 0x44, 0x21, 0x00, 0x00, +0x48, 0x00, 0x00, 0x1a, 0x46, 0x20, 0x02, 0x00, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x04, +0x48, 0x00, 0x00, 0x12, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x99, 0x50, 0x44, 0x20, 0x1d, 0xa9, +0x49, 0xf8, 0x01, 0x26, 0x48, 0x00, 0x00, 0x00, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x00, +0x44, 0x20, 0x00, 0x01, 0x40, 0x31, 0x04, 0x0c, 0x14, 0x30, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, +0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x46, 0x26, 0x03, 0x22, +0x46, 0x38, 0x00, 0x00, 0x46, 0x06, 0x03, 0x20, 0x44, 0x10, 0x00, 0x00, 0x14, 0x31, 0x00, 0xc0, +0x58, 0x50, 0x80, 0x00, 0x48, 0x00, 0x00, 0x20, 0x44, 0x20, 0x00, 0x00, 0x41, 0xe1, 0x00, 0x00, +0x14, 0x5f, 0x00, 0x00, 0x50, 0x21, 0x00, 0x04, 0x04, 0x4f, 0x00, 0x00, 0x4e, 0x42, 0x00, 0x0c, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x99, 0x50, 0x44, 0x20, 0x1d, 0x1f, 0x49, 0xf8, 0x00, 0xe8, +0x48, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x14, 0x4c, 0x22, 0x7f, 0xea, 0x50, 0x10, 0x80, 0x01, +0x50, 0x00, 0x00, 0x20, 0x3c, 0x2d, 0xec, 0x21, 0x40, 0xf0, 0x88, 0x06, 0x4e, 0xf3, 0xff, 0xde, +0x46, 0x06, 0x03, 0x22, 0x04, 0x50, 0x00, 0xc0, 0x42, 0x12, 0xfc, 0x09, 0x14, 0x10, 0x00, 0xc0, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, +0x54, 0x00, 0x00, 0xff, 0x5c, 0xf0, 0x00, 0x03, 0x4e, 0xf3, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, +0x48, 0x00, 0x00, 0x4a, 0x4e, 0x23, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x99, 0x50, +0x44, 0x20, 0x04, 0xcc, 0x49, 0xf8, 0x00, 0xb4, 0x48, 0x00, 0x00, 0x00, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0x80, 0x0e, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0x80, 0x12, 0x46, 0x06, 0x01, 0x40, +0x58, 0x00, 0x00, 0x04, 0x50, 0x30, 0x00, 0x04, 0x48, 0x00, 0x00, 0x10, 0x46, 0x06, 0x01, 0x40, +0x58, 0x00, 0x00, 0x0c, 0x50, 0x30, 0x00, 0x04, 0x48, 0x00, 0x00, 0x08, 0x46, 0x06, 0x01, 0x40, +0x58, 0x00, 0x00, 0x14, 0x50, 0x30, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x05, 0xe1, 0x80, 0x00, +0x40, 0x40, 0x60, 0x09, 0x40, 0x60, 0x20, 0x09, 0x40, 0x50, 0x40, 0x09, 0x40, 0x7f, 0x20, 0x09, +0x42, 0x8f, 0x40, 0x0b, 0x10, 0x80, 0x80, 0x00, 0x10, 0x71, 0x00, 0x05, 0x10, 0x61, 0x00, 0x01, +0x10, 0x51, 0x00, 0x02, 0x10, 0x41, 0x00, 0x03, 0x11, 0xe1, 0x00, 0x04, 0x10, 0x01, 0x00, 0x00, +0x44, 0x00, 0x00, 0x00, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x54, 0x10, 0x80, 0xff, 0x58, 0x71, 0x80, 0x00, 0x54, 0x00, 0x00, 0xff, +0x54, 0x21, 0x00, 0xff, 0x5c, 0xf0, 0x80, 0x03, 0x4e, 0xf2, 0x00, 0x36, 0x50, 0x40, 0x7f, 0xf9, +0x54, 0x32, 0x00, 0xff, 0x5c, 0xf1, 0x80, 0x02, 0x4e, 0xf2, 0x00, 0x2e, 0x46, 0x96, 0x01, 0x20, +0x58, 0x94, 0x81, 0x24, 0x50, 0x54, 0xff, 0xf8, 0x56, 0x00, 0x00, 0x08, 0x44, 0x80, 0x00, 0x01, +0x40, 0x64, 0x80, 0x1a, 0x40, 0x62, 0x80, 0x1b, 0x40, 0x84, 0x04, 0x0c, 0x14, 0x83, 0x00, 0x00, +0x4e, 0x22, 0x00, 0x1e, 0x04, 0x23, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0e, 0x4e, 0x73, 0x00, 0x06, +0x44, 0x00, 0x00, 0x04, 0x48, 0x00, 0x00, 0x16, 0x49, 0x00, 0x02, 0xd2, 0x04, 0x23, 0x00, 0x00, +0x50, 0x73, 0xff, 0xff, 0x40, 0x21, 0x20, 0x02, 0x44, 0x00, 0x00, 0x01, 0x4e, 0x23, 0xff, 0xf0, +0x48, 0x00, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, +0x54, 0x00, 0x00, 0xff, 0x58, 0x71, 0x80, 0x00, 0x54, 0x10, 0x80, 0xff, 0x54, 0x21, 0x00, 0xff, +0x5c, 0xf0, 0x00, 0x0e, 0x4e, 0xf2, 0x00, 0xce, 0x5c, 0xf0, 0x80, 0x04, 0x4e, 0xf2, 0x00, 0xca, +0x50, 0x40, 0x7f, 0xf9, 0x54, 0x32, 0x00, 0xff, 0x5c, 0xf1, 0x80, 0x02, 0x4e, 0xf3, 0x00, 0xc2, +0x44, 0x50, 0x00, 0x05, 0x4c, 0x02, 0x80, 0x58, 0x5c, 0xf0, 0x00, 0x06, 0x4e, 0xf2, 0x00, 0x1c, +0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0x80, 0x3e, 0x5c, 0xf0, 0x00, 0x03, 0x4e, 0xf2, 0x00, 0x0a, +0x4e, 0x02, 0x00, 0x88, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x7a, 0x48, 0x00, 0x00, 0x2c, +0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0x80, 0x34, 0x44, 0x50, 0x00, 0x04, 0x4c, 0x02, 0xc0, 0x70, +0x48, 0x00, 0x00, 0x34, 0x44, 0x50, 0x00, 0x0a, 0x4c, 0x02, 0x80, 0x4a, 0x5c, 0xf0, 0x00, 0x0b, +0x4e, 0xf2, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x06, 0x4c, 0x02, 0x80, 0x36, 0x44, 0x50, 0x00, 0x09, +0x4c, 0x02, 0xc0, 0x5e, 0x48, 0x00, 0x00, 0x36, 0x44, 0x30, 0x00, 0x0c, 0x4c, 0x01, 0x80, 0x48, +0x40, 0xf0, 0x0c, 0x06, 0x4e, 0xf3, 0x00, 0x3c, 0x44, 0x50, 0x00, 0x0d, 0x4c, 0x02, 0xc0, 0x50, +0x48, 0x00, 0x00, 0x46, 0x46, 0x66, 0x01, 0x20, 0x58, 0x63, 0x01, 0x08, 0x48, 0x00, 0x00, 0x2c, +0x46, 0x66, 0x01, 0x20, 0x58, 0x63, 0x01, 0x08, 0x48, 0x00, 0x00, 0x2e, 0x46, 0x66, 0x01, 0x20, +0x58, 0x63, 0x01, 0x08, 0x48, 0x00, 0x00, 0x30, 0x46, 0x40, 0x02, 0x00, 0x46, 0x66, 0x01, 0x20, +0x48, 0x00, 0x00, 0x06, 0x46, 0x40, 0x40, 0x00, 0x46, 0x66, 0x01, 0x20, 0x58, 0x63, 0x01, 0x08, +0x48, 0x00, 0x00, 0x3e, 0x46, 0x40, 0x40, 0x00, 0x46, 0x66, 0x01, 0x20, 0x48, 0x00, 0x00, 0x24, +0x46, 0x66, 0x01, 0x20, 0x58, 0x63, 0x01, 0x0c, 0x48, 0x00, 0x00, 0x30, 0x46, 0x66, 0x01, 0x20, +0x58, 0x63, 0x01, 0x0c, 0x44, 0x40, 0x00, 0x20, 0x48, 0x00, 0x00, 0x2a, 0x46, 0x66, 0x01, 0x20, +0x58, 0x63, 0x01, 0x0c, 0x44, 0x40, 0x04, 0x00, 0x48, 0x00, 0x00, 0x22, 0x46, 0x66, 0x01, 0x20, +0x58, 0x63, 0x01, 0x0c, 0x44, 0x41, 0x00, 0x00, 0x48, 0x00, 0x00, 0x1a, 0x46, 0x40, 0x02, 0x00, +0x46, 0x66, 0x01, 0x20, 0x58, 0x63, 0x01, 0x0c, 0x48, 0x00, 0x00, 0x12, 0x3e, 0x0f, 0x99, 0x3c, +0x3e, 0x1f, 0x99, 0x50, 0x44, 0x20, 0x1f, 0x21, 0x49, 0xf7, 0xff, 0x72, 0x48, 0x00, 0x00, 0x00, +0x46, 0x66, 0x01, 0x20, 0x58, 0x63, 0x01, 0x08, 0x44, 0x40, 0x00, 0x01, 0x40, 0x82, 0x04, 0x0c, +0x14, 0x83, 0x00, 0x00, 0x4e, 0x22, 0x00, 0x22, 0x44, 0x00, 0x00, 0x01, 0x04, 0xa3, 0x00, 0x00, +0x4e, 0x73, 0x00, 0x0e, 0x2e, 0x00, 0x00, 0x15, 0x4e, 0x03, 0x00, 0x18, 0x3e, 0x0f, 0x9a, 0x04, +0x49, 0xf7, 0xff, 0x56, 0x58, 0x03, 0x80, 0x00, 0x48, 0x00, 0x00, 0x12, 0x49, 0x00, 0x01, 0xe8, +0x40, 0x25, 0x20, 0x02, 0x50, 0x73, 0xff, 0xff, 0x4e, 0x23, 0xff, 0xe8, 0x48, 0x00, 0x00, 0x06, +0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x3a, 0x6f, 0xa8, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, 0x3c, 0x4d, 0xec, 0x21, 0x54, 0xa0, 0x00, 0xff, +0x58, 0x60, 0x80, 0x00, 0x58, 0x81, 0x00, 0x00, 0x58, 0x71, 0x80, 0x00, 0x40, 0xf5, 0x10, 0x06, +0x4e, 0xf3, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x01, 0xb8, 0x4e, 0x13, 0x00, 0x0c, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x99, 0x50, 0x44, 0x20, 0x1b, 0xa8, 0x49, 0xf7, 0xff, 0x20, +0x48, 0x00, 0x00, 0x00, 0x4e, 0x23, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x99, 0x50, +0x44, 0x20, 0x1b, 0xa9, 0x49, 0xf7, 0xff, 0x14, 0x48, 0x00, 0x00, 0x00, 0x4e, 0x33, 0x00, 0x0c, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x99, 0x50, 0x44, 0x20, 0x1b, 0xaa, 0x49, 0xf7, 0xff, 0x08, +0x48, 0x00, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x23, 0x58, 0x03, 0x00, 0x00, +0x49, 0xf7, 0xff, 0x34, 0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x0c, 0x58, 0x04, 0x00, 0x00, +0x49, 0xf7, 0xff, 0x2c, 0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x0a, 0x58, 0x03, 0x80, 0x00, +0x49, 0xf7, 0xff, 0x24, 0x46, 0x10, 0x30, 0x19, 0x40, 0x25, 0x04, 0x00, 0x40, 0x21, 0x14, 0x08, +0x04, 0x11, 0x00, 0x00, 0x42, 0x00, 0xf8, 0x0b, 0x4e, 0x02, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, +0x11, 0xe3, 0x00, 0x1f, 0x42, 0x50, 0xf4, 0x0b, 0x4e, 0x52, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, +0x10, 0x03, 0x80, 0x00, 0x43, 0xe0, 0xf0, 0x0b, 0x4f, 0xe2, 0x00, 0x06, 0x44, 0x50, 0x00, 0x01, +0x10, 0x53, 0x80, 0x01, 0x42, 0x00, 0xec, 0x0b, 0x4e, 0x02, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, +0x11, 0xe3, 0x80, 0x02, 0x42, 0x50, 0xe8, 0x0b, 0x4e, 0x52, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, +0x10, 0x03, 0x80, 0x03, 0x43, 0xe0, 0xe4, 0x0b, 0x4f, 0xe2, 0x00, 0x06, 0x44, 0x50, 0x00, 0x01, +0x10, 0x53, 0x80, 0x04, 0x40, 0x40, 0x9c, 0x08, 0x40, 0x32, 0x78, 0x09, 0x42, 0x00, 0xd8, 0x0b, +0x10, 0x33, 0x80, 0x07, 0x4e, 0x02, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, 0x10, 0x03, 0x80, 0x05, +0x40, 0x40, 0xa8, 0x08, 0x40, 0x32, 0x68, 0x09, 0x41, 0xe0, 0xa0, 0x09, 0x10, 0x33, 0x80, 0x08, +0x10, 0x13, 0x00, 0x04, 0x11, 0xe3, 0x00, 0x05, 0x50, 0x01, 0x00, 0x04, 0x05, 0xe0, 0x00, 0x00, +0x50, 0x11, 0x00, 0x08, 0x40, 0x3f, 0x60, 0x09, 0x40, 0x5f, 0x20, 0x09, 0x40, 0x4f, 0x40, 0x09, +0x10, 0x33, 0x00, 0x03, 0x10, 0x53, 0x00, 0x01, 0x10, 0x43, 0x00, 0x02, 0x11, 0xe3, 0x00, 0x00, +0x04, 0x10, 0x80, 0x00, 0x54, 0x30, 0x80, 0x80, 0x4e, 0x32, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, +0x10, 0x03, 0x80, 0x06, 0x54, 0x40, 0x80, 0x78, 0x40, 0x32, 0x0c, 0x09, 0x55, 0xe0, 0x82, 0x00, +0x10, 0x33, 0x80, 0x09, 0x4f, 0xe2, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, 0x10, 0x73, 0x00, 0x07, +0x54, 0x50, 0x81, 0x00, 0x4e, 0x52, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, 0x10, 0x03, 0x00, 0x06, +0x55, 0xe0, 0xc0, 0x00, 0x4f, 0xe2, 0x00, 0x06, 0x44, 0x30, 0x00, 0x01, 0x10, 0x33, 0x00, 0x09, +0x54, 0x40, 0x84, 0x00, 0x4e, 0x42, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, 0x10, 0x73, 0x00, 0x08, +0x40, 0x50, 0xc0, 0x08, 0x40, 0x52, 0xfc, 0x09, 0x4e, 0x52, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, +0x11, 0xe3, 0x00, 0x0a, 0x40, 0x30, 0xbc, 0x08, 0x40, 0x31, 0xfc, 0x09, 0x4e, 0x32, 0x00, 0x06, +0x44, 0x70, 0x00, 0x01, 0x10, 0x73, 0x00, 0x0b, 0x40, 0x50, 0xb8, 0x08, 0x40, 0x52, 0xfc, 0x09, +0x4e, 0x52, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x00, 0x0c, 0x40, 0x40, 0xb4, 0x08, +0x40, 0x42, 0x7c, 0x09, 0x4e, 0x42, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, 0x10, 0x73, 0x00, 0x0d, +0x42, 0x50, 0xcc, 0x0b, 0x4e, 0x52, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x00, 0x0e, +0x42, 0x40, 0xd0, 0x0b, 0x4e, 0x42, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, 0x10, 0x73, 0x00, 0x0f, +0x42, 0x50, 0xd4, 0x0b, 0x4e, 0x52, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x00, 0x10, +0x42, 0x30, 0xd8, 0x0b, 0x4e, 0x32, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, 0x10, 0x73, 0x00, 0x11, +0x42, 0x50, 0xdc, 0x0b, 0x4e, 0x52, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x00, 0x12, +0x42, 0x40, 0xe0, 0x0b, 0x4e, 0x42, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, 0x10, 0x73, 0x00, 0x13, +0x42, 0x50, 0xe4, 0x0b, 0x4e, 0x52, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x00, 0x14, +0x42, 0x40, 0xec, 0x0b, 0x4e, 0x42, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, 0x10, 0x73, 0x00, 0x15, +0x42, 0x50, 0xf0, 0x0b, 0x4e, 0x52, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x00, 0x16, +0x42, 0x30, 0xf4, 0x0b, 0x4e, 0x32, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, 0x10, 0x73, 0x00, 0x17, +0x42, 0x50, 0xf8, 0x0b, 0x4e, 0x52, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x00, 0x18, +0x4e, 0x14, 0x00, 0x06, 0x44, 0x30, 0x00, 0x01, 0x10, 0x33, 0x00, 0x1a, 0x54, 0x30, 0xb8, 0x00, +0x40, 0x51, 0xac, 0x09, 0x54, 0x70, 0x80, 0x07, 0x10, 0x73, 0x00, 0x21, 0x10, 0x53, 0x00, 0x22, +0x50, 0x01, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x41, 0xe0, 0x40, 0x08, 0x40, 0x30, 0x14, 0x08, +0x40, 0x4f, 0x6c, 0x09, 0x54, 0x50, 0x07, 0xff, 0x41, 0xe1, 0xd4, 0x09, 0x42, 0x10, 0x6c, 0x0b, +0x12, 0x54, 0x00, 0x00, 0x10, 0x44, 0x00, 0x08, 0x13, 0xe4, 0x00, 0x02, 0x4e, 0x12, 0x00, 0x06, +0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x00, 0x19, 0x42, 0x10, 0x70, 0x0b, 0x4e, 0x12, 0x00, 0x06, +0x44, 0x50, 0x00, 0x01, 0x10, 0x53, 0x00, 0x1b, 0x42, 0x70, 0x74, 0x0b, 0x4e, 0x72, 0x00, 0x06, +0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x00, 0x1c, 0x42, 0x10, 0x78, 0x0b, 0x4e, 0x12, 0x00, 0x06, +0x44, 0x40, 0x00, 0x01, 0x10, 0x43, 0x00, 0x1d, 0x4e, 0x04, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, +0x10, 0x03, 0x00, 0x1e, 0x50, 0x01, 0x00, 0x10, 0x04, 0x10, 0x00, 0x00, 0x40, 0x30, 0xbc, 0x08, +0x40, 0x20, 0xa4, 0x08, 0x40, 0x21, 0x68, 0x09, 0x40, 0x51, 0xe8, 0x09, 0x40, 0x40, 0xdc, 0x09, +0x55, 0xe0, 0x87, 0xff, 0x12, 0x44, 0x00, 0x03, 0x13, 0xe4, 0x00, 0x01, 0x10, 0x54, 0x00, 0x09, +0x10, 0x24, 0x00, 0x0a, 0x44, 0x00, 0x00, 0x00, 0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x46, 0x06, 0x03, 0x00, 0x04, 0x00, 0x00, 0x1f, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x16, 0x03, 0x00, +0x04, 0x20, 0x80, 0x1f, 0x40, 0x41, 0x08, 0x05, 0x04, 0x30, 0x80, 0x1f, 0x40, 0xf1, 0x88, 0x06, +0x4e, 0xf3, 0x00, 0x06, 0x40, 0x31, 0x88, 0x01, 0x48, 0x00, 0x00, 0x04, 0x40, 0x32, 0x0c, 0x00, +0x40, 0xf1, 0x80, 0x06, 0x4e, 0xf3, 0xff, 0xf2, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x06, 0x04, 0x00, +0x46, 0x10, 0x08, 0x00, 0x14, 0x10, 0x00, 0x01, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x16, 0x04, 0x00, +0x04, 0x00, 0x80, 0x00, 0x42, 0x00, 0x5c, 0x0b, 0x4a, 0x00, 0x78, 0x20, 0x54, 0x10, 0x80, 0xff, +0x4e, 0x03, 0x00, 0x18, 0x4e, 0x12, 0x00, 0x0c, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, +0x04, 0x10, 0x00, 0x00, 0x58, 0x10, 0x80, 0x11, 0x48, 0x00, 0x00, 0x5c, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x48, 0x04, 0x10, 0x00, 0x00, 0x44, 0x2f, 0xff, 0xfe, 0x48, 0x00, 0x00, 0x50, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x18, 0x4e, 0x12, 0x00, 0x0c, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x48, 0x04, 0x30, 0x00, 0x00, 0x58, 0x11, 0x80, 0x44, 0x48, 0x00, 0x00, 0x42, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, 0x04, 0x10, 0x00, 0x00, 0x44, 0x2f, 0xff, 0xfb, +0x48, 0x00, 0x00, 0x36, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x18, 0x4e, 0x12, 0x00, 0x0c, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, 0x46, 0x20, 0x01, 0x10, 0x04, 0x10, 0x00, 0x00, +0x48, 0x00, 0x00, 0x1a, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, 0x04, 0x10, 0x00, 0x00, +0x44, 0x2e, 0xff, 0xff, 0x48, 0x00, 0x00, 0x1c, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x1c, +0x4e, 0x12, 0x00, 0x0e, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, 0x46, 0x20, 0x04, 0x40, +0x04, 0x10, 0x00, 0x00, 0x40, 0x10, 0x88, 0x04, 0x48, 0x00, 0x00, 0x0c, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x48, 0x04, 0x10, 0x00, 0x00, 0x44, 0x2b, 0xff, 0xff, 0x40, 0x10, 0x88, 0x02, +0x14, 0x10, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x54, 0x10, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x18, +0x4e, 0x12, 0x00, 0x0c, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, 0x04, 0x10, 0x00, 0x00, +0x58, 0x10, 0x80, 0x22, 0x48, 0x00, 0x00, 0x5e, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, +0x04, 0x10, 0x00, 0x00, 0x44, 0x2f, 0xff, 0xfd, 0x48, 0x00, 0x00, 0x52, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0xc0, 0x18, 0x4e, 0x12, 0x00, 0x0c, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, +0x04, 0x30, 0x00, 0x00, 0x58, 0x11, 0x80, 0x88, 0x48, 0x00, 0x00, 0x44, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x48, 0x04, 0x10, 0x00, 0x00, 0x44, 0x2f, 0xff, 0xf7, 0x48, 0x00, 0x00, 0x38, +0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x18, 0x4e, 0x12, 0x00, 0x0c, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x48, 0x46, 0x20, 0x02, 0x20, 0x04, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x1a, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, 0x04, 0x10, 0x00, 0x00, 0x44, 0x2d, 0xff, 0xff, +0x48, 0x00, 0x00, 0x1e, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x1e, 0x4e, 0x12, 0x00, 0x0e, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, 0x46, 0x20, 0x08, 0x80, 0x04, 0x10, 0x00, 0x00, +0x40, 0x10, 0x88, 0x04, 0x48, 0x00, 0x00, 0x0e, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, +0x46, 0x2f, 0xff, 0x7f, 0x04, 0x10, 0x00, 0x00, 0x58, 0x21, 0x0f, 0xff, 0x40, 0x10, 0x88, 0x02, +0x14, 0x10, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x54, 0x10, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x0a, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x60, 0x44, 0x20, 0x00, 0x40, 0x48, 0x00, 0x00, 0x0c, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x12, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x60, +0x44, 0x20, 0x40, 0x00, 0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x28, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x5c, 0x48, 0x00, 0x00, 0x20, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x0a, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x14, 0x40, 0x22, 0x94, 0x08, 0x48, 0x00, 0x00, 0x0c, +0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x12, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x14, +0x44, 0x20, 0x40, 0x00, 0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x08, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x01, 0x10, 0x14, 0x20, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x54, 0x10, 0x80, 0xff, +0x4e, 0x03, 0x00, 0x0a, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x60, 0x44, 0x20, 0x00, 0x20, +0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x12, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x60, 0x44, 0x20, 0x20, 0x00, 0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x28, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x5c, 0x48, 0x00, 0x00, 0x20, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x02, 0xc0, 0x0a, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x14, 0x40, 0x22, 0x90, 0x08, +0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x12, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x01, 0x14, 0x44, 0x20, 0x20, 0x00, 0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x08, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x10, 0x14, 0x20, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x9c, 0x3c, 0x46, 0x56, 0x03, 0x00, 0x58, 0x52, 0x80, 0x4c, 0x04, 0x62, 0x80, 0x00, +0x40, 0x63, 0x40, 0x09, 0x40, 0x63, 0x40, 0x08, 0x14, 0x62, 0x80, 0x00, 0x40, 0x31, 0x80, 0x13, +0x04, 0x72, 0x80, 0x00, 0x50, 0x61, 0x80, 0x03, 0x40, 0x33, 0x08, 0x09, 0x54, 0x10, 0x80, 0xff, +0x40, 0x61, 0xa0, 0x08, 0x40, 0x10, 0x9c, 0x04, 0x54, 0x00, 0x00, 0xff, 0x44, 0x70, 0x00, 0x40, +0x40, 0x30, 0x00, 0x1a, 0x40, 0x33, 0x80, 0x1b, 0x40, 0x10, 0x98, 0x04, 0x54, 0x21, 0x00, 0xff, +0x40, 0x63, 0x84, 0x08, 0x40, 0x01, 0x08, 0x1a, 0x40, 0x03, 0x08, 0x1b, 0x40, 0x10, 0x8c, 0x04, +0x40, 0x30, 0x80, 0x04, 0x14, 0x32, 0x80, 0x00, 0x50, 0x02, 0x80, 0x04, 0x04, 0x10, 0x00, 0x00, +0x44, 0x2f, 0xf0, 0xff, 0x40, 0x50, 0x88, 0x02, 0x14, 0x50, 0x00, 0x00, 0x54, 0x32, 0x00, 0xff, +0x04, 0x10, 0x00, 0x00, 0x40, 0x21, 0xa0, 0x08, 0x40, 0x41, 0x04, 0x04, 0x14, 0x40, 0x00, 0x00, +0x3a, 0x6f, 0x9c, 0x04, 0x4a, 0x00, 0x78, 0x20, 0x54, 0x10, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x0a, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x60, 0x44, 0x20, 0x00, 0x02, 0x48, 0x00, 0x00, 0x0c, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x12, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x60, +0x44, 0x20, 0x02, 0x00, 0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x2a, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x5c, 0x48, 0x00, 0x00, 0x22, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x0e, +0x46, 0x46, 0x03, 0x00, 0x14, 0x02, 0x00, 0x45, 0x4e, 0x12, 0x00, 0x1a, 0x58, 0x12, 0x00, 0x00, +0x14, 0x00, 0x80, 0x44, 0x48, 0x00, 0x00, 0x14, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x10, +0x46, 0x06, 0x03, 0x00, 0x44, 0x20, 0x02, 0x00, 0x14, 0x20, 0x00, 0x45, 0x4e, 0x12, 0x00, 0x08, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x10, 0x14, 0x20, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, +0x54, 0x10, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x0a, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x60, +0x44, 0x20, 0x00, 0x04, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x12, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x60, 0x44, 0x20, 0x04, 0x00, 0x14, 0x20, 0x00, 0x00, +0x4e, 0x12, 0x00, 0x28, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x5c, 0x48, 0x00, 0x00, 0x20, +0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x0a, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x14, +0x44, 0x20, 0x00, 0x04, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x12, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x14, 0x44, 0x20, 0x04, 0x00, 0x14, 0x20, 0x00, 0x00, +0x4e, 0x12, 0x00, 0x08, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x10, 0x14, 0x20, 0x00, 0x00, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0x3c, 0x4e, 0x03, 0x00, 0x28, 0x46, 0x26, 0x03, 0x00, +0x58, 0x11, 0x00, 0x00, 0x04, 0x51, 0x00, 0x0a, 0x42, 0x32, 0xf4, 0x0b, 0x4e, 0x32, 0x00, 0x1a, +0x04, 0x30, 0x80, 0x1f, 0x40, 0x61, 0x8c, 0x05, 0x04, 0x40, 0x80, 0x1f, 0x40, 0xf2, 0x0c, 0x06, +0x4e, 0xf3, 0x00, 0x06, 0x40, 0x42, 0x0c, 0x01, 0x48, 0x00, 0x00, 0x04, 0x40, 0x43, 0x10, 0x00, +0x4e, 0x42, 0xff, 0xf4, 0x50, 0x00, 0x00, 0x01, 0x44, 0x30, 0x00, 0x14, 0x4c, 0x01, 0xff, 0xe4, +0x40, 0x02, 0x80, 0x13, 0x48, 0x00, 0x00, 0x84, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x28, +0x46, 0x36, 0x03, 0x00, 0x58, 0x11, 0x80, 0x00, 0x44, 0x20, 0x00, 0x00, 0x04, 0x01, 0x80, 0x0b, +0x42, 0x40, 0x74, 0x0b, 0x4e, 0x42, 0x00, 0x72, 0x04, 0x40, 0x80, 0x1f, 0x40, 0x62, 0x10, 0x05, +0x04, 0x50, 0x80, 0x1f, 0x40, 0xf2, 0x90, 0x06, 0x4e, 0xf3, 0x00, 0x06, 0x40, 0x52, 0x90, 0x01, +0x48, 0x00, 0x00, 0x04, 0x40, 0x53, 0x14, 0x00, 0x4e, 0x52, 0xff, 0xf4, 0x50, 0x21, 0x00, 0x01, +0x44, 0x40, 0x00, 0x14, 0x4c, 0x22, 0x7f, 0xe4, 0x48, 0x00, 0x00, 0x58, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x02, 0xc0, 0x28, 0x46, 0x36, 0x03, 0x00, 0x58, 0x11, 0x80, 0x00, 0x44, 0x20, 0x00, 0x00, +0x04, 0x01, 0x80, 0x40, 0x42, 0x40, 0x74, 0x0b, 0x4e, 0x42, 0x00, 0x48, 0x04, 0x40, 0x80, 0x1f, +0x40, 0x62, 0x10, 0x05, 0x04, 0x50, 0x80, 0x1f, 0x40, 0xf2, 0x90, 0x06, 0x4e, 0xf3, 0x00, 0x06, +0x40, 0x52, 0x90, 0x01, 0x48, 0x00, 0x00, 0x04, 0x40, 0x53, 0x14, 0x00, 0x4e, 0x52, 0xff, 0xf4, +0x50, 0x21, 0x00, 0x01, 0x44, 0x40, 0x00, 0x14, 0x4c, 0x22, 0x7f, 0xe4, 0x48, 0x00, 0x00, 0x2e, +0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0x80, 0x06, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x28, +0x46, 0x36, 0x03, 0x00, 0x58, 0x11, 0x80, 0x00, 0x44, 0x20, 0x00, 0x00, 0x04, 0x01, 0x80, 0x41, +0x42, 0x40, 0x74, 0x0b, 0x4e, 0x42, 0x00, 0x1a, 0x04, 0x40, 0x80, 0x1f, 0x40, 0x62, 0x10, 0x05, +0x04, 0x50, 0x80, 0x1f, 0x40, 0xf2, 0x90, 0x06, 0x4e, 0xf3, 0x00, 0x06, 0x40, 0x52, 0x90, 0x01, +0x48, 0x00, 0x00, 0x04, 0x40, 0x53, 0x14, 0x00, 0x4e, 0x52, 0xff, 0xf4, 0x50, 0x21, 0x00, 0x01, +0x44, 0x40, 0x00, 0x14, 0x4c, 0x22, 0x7f, 0xe4, 0x40, 0x00, 0x00, 0x13, 0x3a, 0x6f, 0x98, 0x04, +0x4a, 0x00, 0x78, 0x20, 0x54, 0x10, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x0c, 0x40, 0x10, 0xc0, 0x08, +0x46, 0x06, 0x03, 0x00, 0x42, 0x10, 0xfc, 0x08, 0x58, 0x00, 0x00, 0x28, 0x48, 0x00, 0x00, 0x2a, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x0c, 0x40, 0x30, 0xc0, 0x08, 0x46, 0x06, 0x03, 0x00, +0x42, 0x11, 0xfc, 0x08, 0x58, 0x00, 0x00, 0x2c, 0x48, 0x00, 0x00, 0x1c, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x02, 0xc0, 0x0c, 0x40, 0x50, 0xc0, 0x08, 0x46, 0x06, 0x03, 0x00, 0x42, 0x12, 0xfc, 0x08, +0x58, 0x00, 0x01, 0x00, 0x48, 0x00, 0x00, 0x0e, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x0c, +0x40, 0x10, 0xc0, 0x08, 0x46, 0x06, 0x03, 0x00, 0x42, 0x10, 0xfc, 0x08, 0x58, 0x00, 0x01, 0x04, +0x14, 0x10, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x54, 0x10, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x0a, +0x46, 0x26, 0x03, 0x00, 0x46, 0x01, 0x00, 0x00, 0x58, 0x21, 0x00, 0x60, 0x48, 0x00, 0x00, 0x0c, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x12, 0x46, 0x26, 0x03, 0x00, 0x46, 0x04, 0x00, 0x00, +0x58, 0x21, 0x00, 0x60, 0x14, 0x01, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x28, 0x46, 0x16, 0x03, 0x00, +0x58, 0x10, 0x80, 0x5c, 0x48, 0x00, 0x00, 0x20, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x0a, +0x46, 0x26, 0x03, 0x00, 0x46, 0x01, 0x00, 0x00, 0x58, 0x21, 0x01, 0x14, 0x48, 0x00, 0x00, 0x0c, +0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x12, 0x46, 0x26, 0x03, 0x00, 0x46, 0x04, 0x00, 0x00, +0x58, 0x21, 0x01, 0x14, 0x14, 0x01, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x08, 0x46, 0x16, 0x03, 0x00, +0x58, 0x10, 0x81, 0x10, 0x14, 0x00, 0x80, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x54, 0x10, 0x80, 0xff, +0x4e, 0x03, 0x00, 0x14, 0x46, 0x06, 0x01, 0x40, 0x58, 0x00, 0x00, 0x80, 0x04, 0x40, 0x00, 0x00, +0x42, 0x22, 0x08, 0x09, 0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x4c, 0x04, 0x10, 0x00, 0x00, +0x58, 0x10, 0x80, 0x04, 0x48, 0x00, 0x00, 0x44, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x14, +0x46, 0x06, 0x01, 0x40, 0x58, 0x00, 0x00, 0x80, 0x04, 0x40, 0x00, 0x00, 0x42, 0x22, 0x10, 0x09, +0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x36, 0x04, 0x10, 0x00, 0x00, 0x58, 0x10, 0x80, 0x10, +0x48, 0x00, 0x00, 0x2e, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x14, 0x46, 0x06, 0x01, 0x40, +0x58, 0x00, 0x00, 0x80, 0x04, 0x40, 0x00, 0x00, 0x42, 0x22, 0x40, 0x09, 0x14, 0x20, 0x00, 0x00, +0x4e, 0x12, 0x00, 0x20, 0x04, 0x10, 0x00, 0x00, 0x44, 0x21, 0x00, 0x00, 0x48, 0x00, 0x00, 0x16, +0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x16, 0x46, 0x06, 0x01, 0x40, 0x58, 0x00, 0x00, 0x80, +0x04, 0x40, 0x00, 0x00, 0x42, 0x22, 0x48, 0x09, 0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x0a, +0x04, 0x10, 0x00, 0x00, 0x44, 0x24, 0x00, 0x00, 0x40, 0x10, 0x88, 0x04, 0x14, 0x10, 0x00, 0x00, +0x4a, 0x00, 0x78, 0x20, 0x40, 0x10, 0x80, 0x13, 0x4e, 0x03, 0x00, 0x0a, 0x46, 0x06, 0x01, 0x40, +0x04, 0x00, 0x00, 0x13, 0x44, 0x2f, 0xf0, 0x00, 0x48, 0x00, 0x00, 0x10, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0xc0, 0x12, 0x46, 0x36, 0x01, 0x40, 0x46, 0x2f, 0x00, 0x0f, 0x04, 0x01, 0x80, 0x13, +0x40, 0x10, 0xc0, 0x08, 0x58, 0x21, 0x0f, 0xff, 0x40, 0x40, 0x08, 0x02, 0x40, 0x10, 0x90, 0x04, +0x48, 0x00, 0x00, 0x28, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x0a, 0x46, 0x06, 0x01, 0x40, +0x04, 0x00, 0x00, 0x14, 0x44, 0x2f, 0xf0, 0x00, 0x48, 0x00, 0x00, 0x10, 0x44, 0x50, 0x00, 0x03, +0x4c, 0x02, 0xc0, 0x12, 0x46, 0x36, 0x01, 0x40, 0x46, 0x2f, 0x00, 0x0f, 0x04, 0x01, 0x80, 0x14, +0x40, 0x10, 0xc0, 0x08, 0x58, 0x21, 0x0f, 0xff, 0x40, 0x40, 0x08, 0x02, 0x40, 0x10, 0x90, 0x04, +0x48, 0x00, 0x00, 0x14, 0x5c, 0xf0, 0x00, 0x02, 0x4e, 0xf2, 0x00, 0x0a, 0x44, 0x10, 0x00, 0x00, +0x46, 0x06, 0x01, 0x40, 0x58, 0x00, 0x00, 0x4c, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x10, 0x00, 0x00, +0x5c, 0xf0, 0x00, 0x04, 0x4e, 0xf2, 0x00, 0x08, 0x46, 0x06, 0x01, 0x40, 0x58, 0x00, 0x00, 0x50, +0x14, 0x10, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x54, 0x10, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x0a, 0x46, 0x26, 0x03, 0x00, 0x46, 0x00, 0x80, 0x00, +0x58, 0x21, 0x00, 0x60, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x12, +0x46, 0x26, 0x03, 0x00, 0x46, 0x02, 0x00, 0x00, 0x58, 0x21, 0x00, 0x60, 0x14, 0x01, 0x00, 0x00, +0x4e, 0x12, 0x00, 0x34, 0x46, 0x16, 0x03, 0x00, 0x58, 0x10, 0x80, 0x5c, 0x48, 0x00, 0x00, 0x20, +0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x0a, 0x46, 0x26, 0x03, 0x00, 0x46, 0x00, 0x80, 0x00, +0x58, 0x21, 0x01, 0x14, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x14, +0x46, 0x26, 0x03, 0x00, 0x46, 0x02, 0x00, 0x00, 0x58, 0x21, 0x01, 0x14, 0x14, 0x01, 0x00, 0x00, +0x4e, 0x12, 0x00, 0x14, 0x46, 0x16, 0x03, 0x00, 0x58, 0x10, 0x81, 0x10, 0x14, 0x00, 0x80, 0x00, +0x48, 0x00, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0x10, 0x44, 0x20, 0x13, 0x45, +0x49, 0xf7, 0xf8, 0xde, 0x48, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x5c, 0xf0, 0x00, 0x04, +0x4e, 0xf3, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0x10, 0x44, 0x20, 0x12, 0x81, +0x49, 0xf7, 0xf8, 0xc6, 0x48, 0x00, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x08, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x1a, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x08, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x14, 0x48, 0x00, 0x00, 0x10, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x02, 0xc0, 0x08, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0xf8, 0x48, 0x00, 0x00, 0x06, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0xfc, 0x04, 0x40, 0x00, 0x00, 0x47, 0xe6, 0x03, 0x00, +0x54, 0x32, 0x00, 0x0c, 0x58, 0x21, 0x80, 0x03, 0x14, 0x20, 0x00, 0x00, 0x04, 0x5f, 0x00, 0x06, +0x58, 0x4f, 0x00, 0x00, 0x14, 0x50, 0x80, 0x00, 0x04, 0x02, 0x00, 0x07, 0x14, 0x00, 0x80, 0x01, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x5c, 0xf0, 0x00, 0x04, 0x4e, 0xf3, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, +0x3e, 0x1f, 0x9b, 0x10, 0x44, 0x20, 0x11, 0xf1, 0x49, 0xf7, 0xf8, 0x7a, 0x48, 0x00, 0x00, 0x00, +0x4e, 0x03, 0x00, 0x2a, 0x44, 0x00, 0x00, 0x01, 0x4c, 0x10, 0x00, 0x1a, 0x4e, 0x12, 0x00, 0x0c, +0x44, 0x50, 0x00, 0x02, 0x4c, 0x12, 0x80, 0x1a, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x12, 0xc0, 0x9e, +0x48, 0x00, 0x00, 0x08, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x94, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x7c, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x7e, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x10, +0x48, 0x00, 0x00, 0x80, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x28, 0x4c, 0x10, 0x00, 0x1a, +0x4e, 0x12, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x12, 0x80, 0x1a, 0x44, 0x50, 0x00, 0x03, +0x4c, 0x12, 0xc0, 0x74, 0x48, 0x00, 0x00, 0x08, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x14, +0x48, 0x00, 0x00, 0x6a, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x14, 0x48, 0x00, 0x00, 0x52, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x14, 0x48, 0x00, 0x00, 0x54, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x14, 0x48, 0x00, 0x00, 0x56, 0x44, 0x20, 0x00, 0x02, 0x4c, 0x01, 0x40, 0x28, +0x44, 0x00, 0x00, 0x01, 0x4c, 0x10, 0x00, 0x18, 0x4e, 0x12, 0x00, 0x0a, 0x4c, 0x11, 0x00, 0x1a, +0x44, 0x50, 0x00, 0x03, 0x4c, 0x12, 0xc0, 0x4a, 0x48, 0x00, 0x00, 0x08, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0xf8, 0x48, 0x00, 0x00, 0x40, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0xf8, +0x48, 0x00, 0x00, 0x28, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0xf8, 0x48, 0x00, 0x00, 0x2a, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0xf8, 0x48, 0x00, 0x00, 0x2c, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x12, 0x80, 0x1c, 0x4e, 0x12, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x12, 0x80, 0x1e, +0x44, 0x50, 0x00, 0x03, 0x4c, 0x12, 0xc0, 0x22, 0x48, 0x00, 0x00, 0x08, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0xfc, 0x48, 0x00, 0x00, 0x18, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0xfc, +0x44, 0x10, 0x00, 0x0c, 0x48, 0x00, 0x00, 0x10, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0xfc, +0x44, 0x10, 0x00, 0x04, 0x48, 0x00, 0x00, 0x08, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0xfc, +0x44, 0x10, 0x00, 0x08, 0x14, 0x10, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x54, 0x10, 0x80, 0xff, +0x4e, 0x03, 0x00, 0x1e, 0x46, 0x26, 0x03, 0x00, 0x58, 0x21, 0x00, 0x34, 0x04, 0x51, 0x00, 0x00, +0x42, 0x32, 0xfc, 0x09, 0x14, 0x31, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x80, 0x05, 0xe1, 0x00, 0x00, +0x40, 0x1f, 0x00, 0x13, 0x4e, 0x13, 0x00, 0x6c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0x10, +0x44, 0x20, 0x10, 0x3b, 0x49, 0xf7, 0xf7, 0xa4, 0x48, 0x00, 0x00, 0x00, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0xc0, 0x1e, 0x46, 0x26, 0x03, 0x00, 0x58, 0x21, 0x00, 0x38, 0x04, 0x51, 0x00, 0x00, +0x42, 0x32, 0xfc, 0x09, 0x14, 0x31, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x60, 0x05, 0xe1, 0x00, 0x00, +0x40, 0x1f, 0x00, 0x13, 0x4e, 0x13, 0x00, 0x4c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0x10, +0x44, 0x20, 0x10, 0x42, 0x49, 0xf7, 0xf7, 0x84, 0x48, 0x00, 0x00, 0x00, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x02, 0xc0, 0x1e, 0x46, 0x26, 0x03, 0x00, 0x58, 0x21, 0x01, 0x08, 0x04, 0x51, 0x00, 0x00, +0x42, 0x32, 0xfc, 0x09, 0x14, 0x31, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x40, 0x05, 0xe1, 0x00, 0x00, +0x40, 0x1f, 0x00, 0x13, 0x4e, 0x13, 0x00, 0x2c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0x10, +0x44, 0x20, 0x10, 0x49, 0x49, 0xf7, 0xf7, 0x64, 0x48, 0x00, 0x00, 0x00, 0x44, 0x50, 0x00, 0x03, +0x4c, 0x02, 0xc0, 0x26, 0x46, 0x26, 0x03, 0x00, 0x58, 0x21, 0x01, 0x0c, 0x04, 0x51, 0x00, 0x00, +0x42, 0x32, 0xfc, 0x09, 0x14, 0x31, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x20, 0x05, 0xe1, 0x00, 0x00, +0x40, 0x1f, 0x00, 0x13, 0x4e, 0x13, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0x10, +0x44, 0x20, 0x10, 0x50, 0x49, 0xf7, 0xf7, 0x44, 0x48, 0x00, 0x00, 0x00, 0x04, 0x51, 0x00, 0x00, +0x42, 0x32, 0xfc, 0x08, 0x14, 0x31, 0x00, 0x00, 0x48, 0x00, 0x00, 0x04, 0x4e, 0x12, 0x00, 0x06, +0x49, 0xff, 0xfc, 0x2a, 0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x54, 0x60, 0x80, 0xff, +0x54, 0x21, 0x00, 0xff, 0x4e, 0x03, 0x00, 0x14, 0x46, 0x36, 0x03, 0x00, 0x44, 0x10, 0x00, 0x01, +0x14, 0x11, 0x80, 0x18, 0x4e, 0x22, 0x00, 0x04, 0x49, 0xff, 0xff, 0x56, 0x4e, 0x62, 0x00, 0x4e, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x5c, 0x48, 0x00, 0x00, 0x2c, 0x44, 0x10, 0x00, 0x01, +0x4c, 0x00, 0xc0, 0x16, 0x46, 0x16, 0x03, 0x00, 0x44, 0x40, 0x01, 0x00, 0x14, 0x40, 0x80, 0x18, +0x4e, 0x22, 0x00, 0x06, 0x58, 0x10, 0x00, 0x00, 0x49, 0xff, 0xff, 0x3e, 0x4e, 0x62, 0x00, 0x36, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x5c, 0x48, 0x00, 0x00, 0x2c, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x02, 0xc0, 0x14, 0x47, 0xe6, 0x03, 0x00, 0x14, 0x1f, 0x00, 0x45, 0x4e, 0x22, 0x00, 0x04, +0x49, 0xff, 0xff, 0x2a, 0x4e, 0x62, 0x00, 0x22, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x10, +0x44, 0x10, 0x00, 0x01, 0x48, 0x00, 0x00, 0x18, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x16, +0x46, 0x36, 0x03, 0x00, 0x44, 0x50, 0x01, 0x00, 0x14, 0x51, 0x80, 0x45, 0x4e, 0x22, 0x00, 0x04, +0x49, 0xff, 0xff, 0x12, 0x4e, 0x62, 0x00, 0x0a, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x10, +0x44, 0x10, 0x01, 0x00, 0x14, 0x10, 0x00, 0x00, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xa8, 0xbc, 0x54, 0x31, 0x80, 0xff, 0x58, 0x60, 0x00, 0x00, 0x40, 0x70, 0x80, 0x13, +0x54, 0x91, 0x00, 0xff, 0x54, 0x82, 0x00, 0xff, 0x54, 0xa2, 0x80, 0xff, 0x5c, 0xf1, 0x80, 0x10, +0x4e, 0xf3, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0x10, 0x44, 0x20, 0x0f, 0xc1, +0x49, 0xf7, 0xf6, 0xae, 0x48, 0x00, 0x00, 0x00, 0x5c, 0xf4, 0x00, 0x08, 0x4e, 0xf3, 0x00, 0x0c, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0x10, 0x44, 0x20, 0x0f, 0xc2, 0x49, 0xf7, 0xf6, 0xa0, +0x48, 0x00, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x08, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x34, +0x48, 0x00, 0x00, 0x1e, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x08, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x38, 0x48, 0x00, 0x00, 0x14, 0x44, 0x00, 0x00, 0x02, 0x4c, 0x60, 0x40, 0x08, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x08, 0x48, 0x00, 0x00, 0x0a, 0x44, 0x10, 0x00, 0x03, +0x4c, 0x60, 0xc0, 0x24, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x0c, 0x40, 0x54, 0xc0, 0x08, +0x46, 0x20, 0xf0, 0x00, 0x40, 0x42, 0x9c, 0x04, 0x41, 0xe1, 0xe0, 0x08, 0x46, 0x57, 0x00, 0x00, +0x40, 0x1f, 0x08, 0x02, 0x41, 0xe4, 0x70, 0x08, 0x40, 0x12, 0x04, 0x04, 0x40, 0x4f, 0x14, 0x02, +0x04, 0x20, 0x00, 0x00, 0x41, 0xe0, 0x90, 0x04, 0x40, 0x21, 0x7c, 0x09, 0x40, 0x21, 0x7c, 0x08, +0x14, 0x20, 0x00, 0x00, 0x15, 0xe0, 0x00, 0x00, 0x4e, 0x32, 0x00, 0x0c, 0x4e, 0x72, 0x00, 0x0a, +0x4e, 0xa2, 0x00, 0x08, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x48, 0x00, 0x00, 0x06, +0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x49, 0xff, 0xfa, 0xb8, 0x4e, 0x82, 0x00, 0x0e, +0x4e, 0x92, 0x00, 0x0c, 0x4e, 0x72, 0x00, 0x0a, 0x4e, 0xa2, 0x00, 0x08, 0x58, 0x03, 0x00, 0x00, +0x44, 0x10, 0x00, 0x01, 0x48, 0x00, 0x00, 0x06, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, +0x49, 0xff, 0xfa, 0xe8, 0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, +0x54, 0x10, 0x80, 0xff, 0x54, 0x00, 0x00, 0xff, 0x54, 0x21, 0x00, 0xff, 0x40, 0x31, 0x80, 0x13, +0x54, 0x42, 0x00, 0xff, 0x5c, 0xf0, 0x80, 0x40, 0x4e, 0xf3, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, +0x3e, 0x1f, 0x9b, 0x10, 0x44, 0x20, 0x0f, 0x1b, 0x49, 0xf7, 0xf6, 0x1a, 0x48, 0x00, 0x00, 0x00, +0x50, 0x61, 0x80, 0x03, 0x40, 0x63, 0x08, 0x09, 0x5c, 0xf3, 0x01, 0x00, 0x4e, 0xf3, 0x00, 0x0c, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0x10, 0x44, 0x20, 0x0f, 0x1c, 0x49, 0xf7, 0xf6, 0x08, +0x48, 0x00, 0x00, 0x00, 0x5c, 0xf2, 0x00, 0x40, 0x4e, 0xf3, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, +0x3e, 0x1f, 0x9b, 0x10, 0x44, 0x20, 0x0f, 0x1d, 0x49, 0xf7, 0xf5, 0xfa, 0x48, 0x00, 0x00, 0x00, +0x47, 0xe6, 0x03, 0x00, 0x59, 0xef, 0x00, 0x4c, 0x04, 0x5f, 0x00, 0x00, 0x40, 0x30, 0xc0, 0x08, +0x40, 0x82, 0x80, 0x13, 0x14, 0x8f, 0x00, 0x00, 0x46, 0x50, 0x04, 0x00, 0x04, 0x7f, 0x00, 0x00, +0x40, 0x81, 0x9c, 0x04, 0x40, 0x63, 0x60, 0x08, 0x46, 0x10, 0x08, 0x00, 0x40, 0x70, 0x00, 0x1a, +0x40, 0x72, 0x80, 0x1b, 0x40, 0x34, 0x18, 0x04, 0x40, 0x01, 0x08, 0x1a, 0x40, 0x00, 0x88, 0x1b, +0x40, 0x61, 0x9c, 0x04, 0x40, 0x63, 0x00, 0x04, 0x14, 0x6f, 0x00, 0x00, 0x50, 0x0f, 0x00, 0x04, +0x04, 0x50, 0x00, 0x00, 0x40, 0x32, 0x98, 0x09, 0x40, 0x31, 0x98, 0x08, 0x14, 0x30, 0x00, 0x00, +0x04, 0x10, 0x00, 0x00, 0x40, 0x42, 0x04, 0x04, 0x14, 0x40, 0x00, 0x00, 0x3a, 0x6f, 0xa0, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x3c, 0x2d, 0xec, 0xcf, +0x46, 0x36, 0x04, 0x00, 0x46, 0x10, 0x08, 0x00, 0x14, 0x2f, 0x80, 0x01, 0x14, 0x11, 0x80, 0x02, +0x44, 0x00, 0x16, 0xe8, 0x58, 0x81, 0x80, 0x00, 0x4b, 0xe0, 0x00, 0x01, 0x44, 0x60, 0x00, 0x1e, +0x45, 0xc0, 0x03, 0xe8, 0x44, 0xa0, 0x00, 0x07, 0x58, 0x90, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, +0x46, 0x76, 0x04, 0x00, 0x42, 0x50, 0x5c, 0x0b, 0x4e, 0x52, 0x00, 0x3a, 0x49, 0xf7, 0xf0, 0x5e, +0x40, 0x00, 0x24, 0x01, 0x44, 0x40, 0x00, 0x64, 0x40, 0x20, 0x10, 0x37, 0x05, 0xef, 0x80, 0x01, +0x02, 0x1f, 0x00, 0x00, 0x45, 0xe0, 0x27, 0x10, 0x50, 0x10, 0x93, 0x88, 0x40, 0x50, 0x70, 0x77, +0x42, 0x20, 0x18, 0x73, 0x42, 0x22, 0xa8, 0x73, 0x44, 0x50, 0x00, 0x0a, 0x40, 0x30, 0x78, 0x97, +0x40, 0x00, 0x14, 0x97, 0x44, 0x40, 0x00, 0x05, 0x40, 0x51, 0x80, 0x00, 0x42, 0x22, 0x90, 0x73, +0x40, 0xf0, 0x88, 0x06, 0x4e, 0xf2, 0xff, 0xd4, 0x04, 0x23, 0x80, 0x00, 0x47, 0xe0, 0x08, 0x00, +0x40, 0x01, 0x78, 0x02, 0x4e, 0x02, 0x00, 0x0e, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0x10, +0x44, 0x20, 0x0c, 0x97, 0x49, 0xf7, 0xf5, 0x64, 0x48, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, +0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x54, 0x00, 0x00, 0xff, +0x40, 0x00, 0x20, 0x08, 0x54, 0x10, 0x80, 0xff, 0x40, 0x20, 0x00, 0x13, 0x4e, 0x12, 0x00, 0x06, +0x58, 0x11, 0x00, 0x01, 0x48, 0x00, 0x00, 0x06, 0x44, 0x20, 0xff, 0xfe, 0x40, 0x10, 0x08, 0x02, +0x46, 0x36, 0x01, 0x20, 0x44, 0x00, 0x00, 0x00, 0x14, 0x11, 0x80, 0x4d, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x98, 0x3c, 0x46, 0x58, 0x00, 0x22, 0x54, 0x00, 0x00, 0xff, 0x40, 0x00, 0x40, 0x08, +0x54, 0x10, 0x80, 0xff, 0x04, 0x62, 0x80, 0x01, 0x40, 0x10, 0x04, 0x04, 0x46, 0x08, 0x0f, 0xc8, +0x58, 0x00, 0x00, 0x80, 0x40, 0x63, 0x00, 0x02, 0x40, 0x10, 0x98, 0x04, 0x54, 0x31, 0x80, 0xff, +0x40, 0x01, 0x60, 0x08, 0x40, 0x20, 0x80, 0x04, 0x40, 0x11, 0xa0, 0x08, 0x40, 0x01, 0x04, 0x04, +0x14, 0x02, 0x80, 0x01, 0x46, 0x08, 0x00, 0x22, 0x04, 0x50, 0x00, 0x02, 0x46, 0x2f, 0xfc, 0x0f, +0x54, 0x32, 0x00, 0xff, 0x58, 0x21, 0x0f, 0xff, 0x40, 0x12, 0x88, 0x02, 0x40, 0x21, 0xc0, 0x08, +0x40, 0x41, 0x04, 0x04, 0x14, 0x40, 0x00, 0x02, 0x44, 0x00, 0x00, 0x00, 0x3a, 0x6f, 0x98, 0x04, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x54, 0x10, 0x80, 0xff, 0x54, 0x21, 0x00, 0xff, +0x54, 0x31, 0x80, 0xff, 0x54, 0x42, 0x00, 0xff, 0x40, 0x52, 0x80, 0x13, 0x00, 0x9f, 0x80, 0x1c, +0x00, 0xaf, 0x80, 0x20, 0x03, 0xcf, 0x80, 0x12, 0x00, 0x7f, 0x80, 0x28, 0x5c, 0xf0, 0x00, 0x04, +0x4e, 0xf3, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x7a, 0x40, 0x82, 0x40, 0x08, +0x46, 0x48, 0x00, 0x24, 0x40, 0x60, 0x0c, 0x08, 0x58, 0x42, 0x00, 0x10, 0x51, 0xe2, 0x00, 0x04, +0x40, 0x01, 0xe0, 0x08, 0x40, 0x33, 0x10, 0x00, 0x40, 0x43, 0x78, 0x00, 0x45, 0xe0, 0x00, 0x01, +0x4c, 0x1f, 0x40, 0x3c, 0x40, 0x54, 0x14, 0x04, 0x40, 0xa5, 0x40, 0x08, 0x40, 0x02, 0x80, 0x04, +0x40, 0xa5, 0x70, 0x04, 0x40, 0x94, 0xe0, 0x08, 0x14, 0x01, 0x80, 0x00, 0x40, 0x95, 0x24, 0x04, +0x40, 0x13, 0x84, 0x03, 0x44, 0x00, 0x00, 0x02, 0x44, 0x50, 0x00, 0x00, 0x40, 0x32, 0x84, 0x1b, +0x40, 0x30, 0x04, 0x1a, 0x14, 0x92, 0x00, 0x00, 0x4c, 0x2f, 0x40, 0x04, 0x40, 0x31, 0xf8, 0x04, +0x46, 0x48, 0x00, 0x24, 0x44, 0x10, 0x00, 0x2f, 0x40, 0x20, 0x98, 0x0c, 0x04, 0x52, 0x00, 0x00, +0x40, 0x01, 0x08, 0x05, 0x40, 0x10, 0x14, 0x02, 0x14, 0x12, 0x00, 0x00, 0x58, 0x31, 0x80, 0x80, +0x04, 0x22, 0x00, 0x00, 0x40, 0x61, 0x98, 0x0c, 0x40, 0x63, 0x08, 0x04, 0x14, 0x62, 0x00, 0x00, +0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x2c, 0x40, 0x24, 0x14, 0x04, 0x40, 0x11, 0x00, 0x04, +0x44, 0x00, 0x00, 0x00, 0x14, 0x11, 0x80, 0x00, 0x14, 0x02, 0x00, 0x00, 0x46, 0x48, 0x00, 0x24, +0x44, 0x50, 0x00, 0x2f, 0x04, 0x32, 0x00, 0x00, 0x40, 0x22, 0x98, 0x0c, 0x40, 0x11, 0x08, 0x05, +0x40, 0x50, 0x8c, 0x02, 0x14, 0x52, 0x00, 0x00, 0x56, 0x73, 0x80, 0x01, 0x44, 0x20, 0x00, 0x02, +0x40, 0x10, 0x1c, 0x1b, 0x40, 0x11, 0x1c, 0x1a, 0x04, 0x52, 0x00, 0x00, 0x58, 0x30, 0x80, 0x80, +0x40, 0x61, 0x98, 0x0c, 0x40, 0x63, 0x14, 0x04, 0x14, 0x62, 0x00, 0x00, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0x3c, 0x54, 0x10, 0x80, 0xff, 0x54, 0x21, 0x00, 0xff, +0x54, 0x31, 0x80, 0xff, 0x54, 0x42, 0x00, 0xff, 0x5c, 0xf0, 0x00, 0x04, 0x4e, 0xf3, 0x00, 0x06, +0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x94, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0x80, 0x32, +0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0x80, 0x42, 0x40, 0x50, 0xa0, 0x08, 0x44, 0x10, 0x00, 0x01, +0x4c, 0x00, 0x80, 0x12, 0x46, 0x18, 0x00, 0x24, 0x58, 0x10, 0x80, 0x04, 0x04, 0x60, 0x80, 0x00, +0x40, 0x21, 0x14, 0x04, 0x40, 0x53, 0x40, 0x09, 0x40, 0x52, 0xc0, 0x08, 0x14, 0x50, 0x80, 0x00, +0x48, 0x00, 0x00, 0x10, 0x46, 0x18, 0x00, 0x24, 0x58, 0x10, 0x80, 0x04, 0x04, 0x60, 0x80, 0x00, +0x40, 0x21, 0x14, 0x04, 0x40, 0x53, 0x00, 0x13, 0x14, 0x50, 0x80, 0x00, 0x40, 0x21, 0x40, 0x08, +0x04, 0x60, 0x80, 0x00, 0x40, 0x21, 0x18, 0x04, 0x14, 0x20, 0x80, 0x00, 0x48, 0x00, 0x00, 0x2c, +0x46, 0x58, 0x00, 0x24, 0x58, 0x52, 0x80, 0x08, 0x04, 0x62, 0x80, 0x00, 0x40, 0x63, 0x40, 0x09, +0x40, 0x63, 0x40, 0x08, 0x14, 0x62, 0x80, 0x00, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x21, 0x04, 0x04, +0x04, 0x62, 0x80, 0x00, 0x48, 0x00, 0x00, 0x14, 0x46, 0x58, 0x00, 0x24, 0x58, 0x52, 0x80, 0x08, +0x04, 0x62, 0x80, 0x00, 0x40, 0x63, 0x00, 0x13, 0x14, 0x62, 0x80, 0x00, 0x40, 0x10, 0xa0, 0x08, +0x40, 0x21, 0x04, 0x04, 0x04, 0x62, 0x80, 0x00, 0x40, 0x21, 0x40, 0x08, 0x40, 0x21, 0x18, 0x04, +0x14, 0x22, 0x80, 0x00, 0x56, 0x31, 0x80, 0x01, 0x44, 0x10, 0x00, 0x02, 0x44, 0x50, 0x00, 0x00, +0x40, 0x22, 0x8c, 0x1b, 0x40, 0x20, 0x8c, 0x1a, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x42, 0xc0, 0x08, +0x58, 0x41, 0x00, 0x20, 0x42, 0x22, 0x08, 0x09, 0x48, 0x00, 0x00, 0x06, 0x58, 0x21, 0x00, 0x04, +0x42, 0x21, 0x14, 0x09, 0x46, 0x58, 0x00, 0x24, 0x40, 0x10, 0x0c, 0x08, 0x44, 0x40, 0x00, 0x2f, +0x40, 0x32, 0x04, 0x0c, 0x04, 0x42, 0x80, 0x00, 0x40, 0x31, 0x8c, 0x05, 0x40, 0x31, 0x90, 0x02, +0x14, 0x32, 0x80, 0x00, 0x58, 0x21, 0x00, 0x80, 0x04, 0x32, 0x80, 0x00, 0x40, 0x41, 0x04, 0x0c, +0x40, 0x02, 0x0c, 0x04, 0x14, 0x02, 0x80, 0x00, 0x44, 0x00, 0x00, 0x00, 0x3a, 0x6f, 0x9c, 0x04, +0x4a, 0x00, 0x78, 0x20, 0x46, 0x26, 0x01, 0x10, 0x04, 0x11, 0x00, 0x2d, 0x40, 0x00, 0x84, 0x05, +0x40, 0x00, 0x7c, 0x09, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xec, +0x14, 0x0f, 0x80, 0x01, 0x4e, 0x02, 0x00, 0x3e, 0x46, 0x76, 0x01, 0x40, 0x58, 0x73, 0x80, 0x04, +0x44, 0x80, 0x00, 0x00, 0x50, 0x6f, 0x80, 0x08, 0x58, 0x13, 0x80, 0x00, 0x0c, 0x30, 0x80, 0x01, +0x04, 0x0f, 0x80, 0x01, 0x04, 0x40, 0x80, 0x00, 0x40, 0x91, 0xe0, 0x09, 0x40, 0x52, 0x20, 0x09, +0x41, 0xc1, 0xa0, 0x09, 0x40, 0xa1, 0xc0, 0x09, 0x58, 0x13, 0x00, 0x00, 0x44, 0x20, 0x00, 0x06, +0x11, 0xc3, 0x00, 0x01, 0x10, 0xa3, 0x00, 0x02, 0x10, 0x93, 0x00, 0x03, 0x10, 0x53, 0x00, 0x05, +0x10, 0x33, 0x00, 0x00, 0x10, 0x43, 0x00, 0x04, 0x49, 0xf7, 0xf4, 0x5a, 0x50, 0x14, 0x00, 0x01, +0x4e, 0x03, 0x00, 0x06, 0x58, 0x04, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0e, 0x54, 0x80, 0x80, 0xff, +0x44, 0x50, 0x00, 0x03, 0x4c, 0x82, 0x80, 0x06, 0x50, 0x73, 0x80, 0x08, 0x48, 0xff, 0xff, 0xce, +0x44, 0x00, 0x00, 0x0f, 0x51, 0xff, 0x80, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x44, 0x20, 0x00, 0x01, 0x54, 0x00, 0x00, 0xff, +0x54, 0x10, 0x80, 0xff, 0x4c, 0x01, 0x00, 0x30, 0x4e, 0x02, 0x00, 0x1c, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x02, 0x80, 0x08, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x1c, 0x48, 0x00, 0x00, 0x0a, +0x46, 0x20, 0x04, 0x00, 0x46, 0x06, 0x03, 0x10, 0x58, 0x00, 0x00, 0x0c, 0x48, 0x00, 0x00, 0x22, +0x46, 0x06, 0x03, 0x10, 0x58, 0x00, 0x00, 0x28, 0x44, 0x20, 0x08, 0x00, 0x48, 0x00, 0x00, 0x1a, +0x46, 0x20, 0x04, 0x00, 0x46, 0x06, 0x03, 0x10, 0x58, 0x00, 0x00, 0x08, 0x48, 0x00, 0x00, 0x12, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0x48, 0x44, 0x20, 0x01, 0xcf, 0x49, 0xff, 0xe4, 0xbe, +0x48, 0x00, 0x00, 0x00, 0x46, 0x06, 0x03, 0x10, 0x58, 0x00, 0x00, 0x0c, 0x44, 0x20, 0x02, 0x00, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x12, 0xc0, 0x08, 0x04, 0x10, 0x00, 0x00, 0x40, 0x20, 0x88, 0x04, +0x48, 0x00, 0x00, 0x08, 0x04, 0x30, 0x00, 0x00, 0x41, 0xe1, 0x08, 0x05, 0x40, 0x21, 0xf8, 0x02, +0x14, 0x20, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x54, 0x30, 0x00, 0xff, +0x44, 0x00, 0x00, 0x01, 0x54, 0x20, 0x80, 0xff, 0x4c, 0x30, 0x00, 0x1e, 0x4e, 0x32, 0x00, 0x08, +0x44, 0x50, 0x00, 0x02, 0x4c, 0x32, 0xc0, 0x3c, 0x48, 0x00, 0x00, 0x1e, 0x46, 0x46, 0x03, 0x10, +0x46, 0x00, 0x08, 0x00, 0x14, 0x02, 0x00, 0x00, 0x4e, 0x22, 0x00, 0x08, 0x58, 0x11, 0x80, 0x00, +0x58, 0x21, 0x80, 0x00, 0x48, 0x00, 0x00, 0x20, 0x58, 0x11, 0x00, 0x00, 0x58, 0x31, 0x00, 0x00, +0x48, 0x00, 0x00, 0x22, 0x46, 0x06, 0x03, 0x10, 0x58, 0x00, 0x00, 0x04, 0x44, 0x10, 0x04, 0x00, +0x48, 0x00, 0x00, 0x08, 0x46, 0x06, 0x03, 0x10, 0x46, 0x10, 0x08, 0x00, 0x58, 0x00, 0x00, 0x04, +0x14, 0x10, 0x00, 0x00, 0x4e, 0x22, 0x00, 0x0c, 0x44, 0x00, 0x00, 0x00, 0x58, 0x20, 0x00, 0x00, +0x58, 0x30, 0x00, 0x00, 0x49, 0xff, 0xec, 0x02, 0x48, 0x00, 0x00, 0x14, 0x58, 0x01, 0x00, 0x00, +0x58, 0x31, 0x00, 0x00, 0x49, 0xff, 0xec, 0x14, 0x48, 0x00, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, +0x3e, 0x1f, 0x9b, 0x48, 0x44, 0x20, 0x01, 0xad, 0x49, 0xff, 0xe4, 0x48, 0x48, 0x00, 0x00, 0x00, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, +0x51, 0xff, 0xff, 0xf4, 0x54, 0x00, 0x00, 0xff, 0x4e, 0x03, 0x00, 0x04, 0x48, 0x00, 0x00, 0x28, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x1a, 0x54, 0x60, 0x84, 0x00, 0x4e, 0x62, 0x00, 0x06, +0x10, 0x0f, 0x80, 0x04, 0x58, 0x60, 0x00, 0x00, 0x42, 0x10, 0xdc, 0x0b, 0x4e, 0x12, 0x00, 0x20, +0x50, 0x33, 0x00, 0x01, 0x44, 0x40, 0x00, 0x02, 0x50, 0x5f, 0x80, 0x04, 0x38, 0x42, 0x98, 0x08, +0x54, 0x61, 0x80, 0xff, 0x48, 0x00, 0x00, 0x14, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x0e, +0x54, 0x70, 0x90, 0x00, 0x4e, 0x72, 0x00, 0x0a, 0x44, 0x00, 0x00, 0x03, 0x10, 0x0f, 0x80, 0x04, +0x44, 0x60, 0x00, 0x01, 0x48, 0x00, 0x00, 0x04, 0x44, 0x60, 0x00, 0x00, 0x3c, 0x8c, 0x01, 0xd2, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x82, 0xc0, 0x06, 0x44, 0x00, 0x00, 0x03, 0x49, 0xf8, 0x13, 0xe0, +0x50, 0x9f, 0x80, 0x04, 0x44, 0x70, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0a, 0x08, 0x04, 0x80, 0x01, +0x49, 0x00, 0x31, 0xe0, 0x50, 0x23, 0x80, 0x01, 0x54, 0x71, 0x00, 0xff, 0x40, 0xf3, 0x98, 0x06, +0x4e, 0xf3, 0xff, 0xf6, 0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x54, 0x00, 0x00, 0xff, 0x40, 0x40, 0x08, 0x08, +0x3e, 0x2f, 0xb3, 0x60, 0x40, 0x32, 0x08, 0x00, 0x00, 0x11, 0x80, 0x00, 0x4e, 0x12, 0x00, 0x04, +0x49, 0x00, 0x11, 0x4c, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x54, 0x00, 0x00, 0xff, 0x4e, 0x03, 0x00, 0x04, +0x48, 0x00, 0x00, 0x28, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x1a, 0x54, 0x60, 0x82, 0x00, +0x4e, 0x62, 0x00, 0x06, 0x10, 0x0f, 0x80, 0x04, 0x58, 0x60, 0x00, 0x00, 0x42, 0x10, 0xd8, 0x0b, +0x4e, 0x12, 0x00, 0x20, 0x50, 0x33, 0x00, 0x01, 0x44, 0x40, 0x00, 0x02, 0x50, 0x5f, 0x80, 0x04, +0x38, 0x42, 0x98, 0x08, 0x54, 0x61, 0x80, 0xff, 0x48, 0x00, 0x00, 0x14, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x02, 0xc0, 0x0e, 0x54, 0x70, 0x88, 0x00, 0x4e, 0x72, 0x00, 0x0a, 0x44, 0x00, 0x00, 0x03, +0x10, 0x0f, 0x80, 0x04, 0x44, 0x60, 0x00, 0x01, 0x48, 0x00, 0x00, 0x04, 0x44, 0x60, 0x00, 0x00, +0x50, 0x9f, 0x80, 0x04, 0x44, 0x70, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0a, 0x08, 0x04, 0x80, 0x01, +0x49, 0xff, 0xff, 0xa8, 0x50, 0x23, 0x80, 0x01, 0x54, 0x71, 0x00, 0xff, 0x40, 0xf3, 0x98, 0x06, +0x4e, 0xf3, 0xff, 0xf6, 0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xa8, 0xbc, 0x54, 0xa0, 0x00, 0xff, 0x48, 0x00, 0x00, 0x08, 0x49, 0xf7, 0xf7, 0xb0, +0x58, 0x03, 0x00, 0x00, 0x49, 0x00, 0x03, 0x34, 0x58, 0x15, 0x00, 0x00, 0x44, 0x20, 0x00, 0x00, +0x44, 0x00, 0x00, 0x01, 0x49, 0xf7, 0xfb, 0x46, 0x44, 0x50, 0x0f, 0xff, 0x58, 0x60, 0x00, 0x00, +0x4c, 0x02, 0xff, 0xee, 0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xf4, 0x54, 0x00, 0x00, 0xff, 0x14, 0x0f, 0x80, 0x01, 0x45, 0xc0, 0x34, 0x20, +0x48, 0x00, 0x00, 0x12, 0x2e, 0x17, 0xb0, 0xc8, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x12, 0xc0, 0x0a, +0x49, 0x00, 0x03, 0xf6, 0x58, 0x03, 0x00, 0x00, 0x49, 0x00, 0x04, 0xe0, 0x48, 0x00, 0x00, 0x04, +0x49, 0x00, 0x03, 0x06, 0x04, 0x1f, 0x80, 0x01, 0x44, 0x20, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, +0x4b, 0xe0, 0x70, 0x01, 0x44, 0x50, 0x0f, 0xff, 0x58, 0x60, 0x00, 0x00, 0x4c, 0x02, 0xff, 0xe4, +0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x58, 0x80, 0x00, 0x00, 0x54, 0x70, 0x00, 0xff, 0x3f, 0xce, 0xd4, 0xe4, +0x48, 0x00, 0x00, 0x26, 0x2e, 0x20, 0x02, 0x88, 0x4e, 0x22, 0x00, 0x36, 0x49, 0x00, 0x02, 0x88, +0x44, 0x10, 0x00, 0x01, 0x4e, 0x03, 0x00, 0x0e, 0x58, 0x00, 0x80, 0x00, 0x58, 0x23, 0x00, 0x00, +0x58, 0x13, 0x80, 0x00, 0x58, 0x30, 0x00, 0x00, 0x49, 0xf7, 0xfb, 0x7c, 0x48, 0x00, 0x00, 0x24, +0x04, 0x50, 0x00, 0x02, 0x44, 0x30, 0x00, 0xa0, 0x00, 0x42, 0x80, 0x05, 0x4c, 0x41, 0xc0, 0x06, +0x49, 0x00, 0x10, 0x22, 0x48, 0x00, 0x00, 0x04, 0x4b, 0xe0, 0x70, 0x01, 0x2f, 0xe0, 0x02, 0x88, +0x44, 0x20, 0x00, 0x00, 0x58, 0x13, 0x80, 0x00, 0x44, 0x00, 0x00, 0x01, 0x4f, 0xe2, 0x00, 0x0c, +0x49, 0xf7, 0xfa, 0xd0, 0x44, 0x50, 0x0f, 0xff, 0x58, 0x60, 0x00, 0x00, 0x58, 0x14, 0x00, 0x00, +0x4c, 0x02, 0xff, 0xca, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xdc, 0x46, 0xa6, 0x03, 0x10, 0x58, 0x95, 0x00, 0x00, +0x45, 0xc0, 0x00, 0x00, 0x50, 0x6f, 0x80, 0x10, 0x58, 0x8f, 0x80, 0x00, 0x48, 0x00, 0x00, 0xe0, +0x44, 0x00, 0x00, 0x00, 0x14, 0x04, 0x00, 0x02, 0x14, 0x03, 0x00, 0x00, 0x14, 0x04, 0x00, 0x00, +0x14, 0x03, 0x00, 0x01, 0x14, 0x04, 0x00, 0x01, 0x14, 0x03, 0x00, 0x02, 0x44, 0x00, 0x00, 0x00, +0x38, 0x43, 0x00, 0x02, 0x38, 0x24, 0x00, 0x02, 0x44, 0x10, 0x00, 0x10, 0x40, 0x31, 0x10, 0x02, +0x38, 0x33, 0x00, 0x0a, 0x50, 0x00, 0x00, 0x04, 0x4c, 0x00, 0xff, 0xf4, 0x04, 0x53, 0x00, 0x01, +0x4e, 0x53, 0x00, 0x0e, 0x05, 0xe3, 0x00, 0x00, 0x4f, 0xe3, 0x00, 0x0a, 0x04, 0x03, 0x00, 0x02, +0x4e, 0x03, 0x00, 0x06, 0x04, 0x13, 0x00, 0x03, 0x4e, 0x12, 0x00, 0xe8, 0x04, 0x13, 0x00, 0x03, +0x54, 0x30, 0x80, 0x01, 0x4e, 0x32, 0x00, 0x10, 0x46, 0x5a, 0x00, 0x00, 0x45, 0xe0, 0x00, 0x01, +0x15, 0xe2, 0x80, 0x02, 0x42, 0x40, 0x80, 0x09, 0x44, 0x00, 0x00, 0x00, 0x14, 0x43, 0x00, 0x03, +0x49, 0xff, 0xff, 0x66, 0x04, 0x13, 0x00, 0x03, 0x54, 0x00, 0x80, 0x02, 0x4e, 0x02, 0x00, 0x10, +0x46, 0x4a, 0x00, 0x00, 0x44, 0x20, 0x00, 0x02, 0x14, 0x22, 0x00, 0x02, 0x42, 0x10, 0x84, 0x09, +0x44, 0x00, 0x00, 0x01, 0x14, 0x13, 0x00, 0x03, 0x49, 0xff, 0xff, 0x22, 0x04, 0x13, 0x00, 0x03, +0x54, 0x50, 0x80, 0x04, 0x4e, 0x52, 0x00, 0x10, 0x46, 0x3a, 0x00, 0x00, 0x44, 0x40, 0x00, 0x04, +0x14, 0x41, 0x80, 0x02, 0x43, 0xe0, 0x88, 0x09, 0x44, 0x00, 0x00, 0x02, 0x15, 0xe3, 0x00, 0x03, +0x49, 0xff, 0xfe, 0xf0, 0x04, 0x13, 0x00, 0x03, 0x54, 0x20, 0x80, 0x08, 0x4e, 0x22, 0x00, 0x10, +0x47, 0xea, 0x00, 0x00, 0x44, 0x00, 0x00, 0x08, 0x14, 0x0f, 0x00, 0x02, 0x42, 0x10, 0x8c, 0x09, +0x44, 0x00, 0x00, 0x03, 0x14, 0x13, 0x00, 0x03, 0x49, 0x00, 0x0a, 0xfa, 0x04, 0x33, 0x00, 0x01, +0x4e, 0x33, 0x00, 0x0a, 0x04, 0x43, 0x00, 0x00, 0x4e, 0x43, 0x00, 0x06, 0x04, 0x23, 0x00, 0x02, +0x4e, 0x22, 0x00, 0x34, 0x3e, 0x7f, 0xb0, 0x88, 0x04, 0x03, 0x80, 0x00, 0x04, 0x13, 0x80, 0x01, +0x39, 0xe3, 0x02, 0x02, 0x40, 0x50, 0xf8, 0x02, 0x4e, 0x52, 0x00, 0x20, 0x3e, 0x3f, 0x9b, 0x8c, +0x38, 0x01, 0x83, 0x02, 0x14, 0x10, 0x00, 0x00, 0x04, 0x23, 0x80, 0x02, 0x4e, 0x22, 0x00, 0x0a, +0x04, 0x43, 0x80, 0x00, 0x38, 0x13, 0x12, 0x02, 0x54, 0x02, 0x00, 0xff, 0x4b, 0xe0, 0x08, 0x01, +0x04, 0x53, 0x80, 0x00, 0x04, 0x03, 0x80, 0x01, 0x38, 0x23, 0x16, 0x02, 0x41, 0xe0, 0x00, 0x05, +0x40, 0x1f, 0x08, 0x02, 0x38, 0x13, 0x16, 0x0a, 0x3e, 0x5f, 0xb0, 0xb8, 0x4c, 0x72, 0x80, 0x06, +0x50, 0x73, 0x80, 0x0c, 0x48, 0xff, 0xff, 0xd2, 0x04, 0x43, 0x00, 0x01, 0x4e, 0x43, 0x00, 0x0e, +0x04, 0x53, 0x00, 0x00, 0x4e, 0x53, 0x00, 0x0a, 0x04, 0x13, 0x00, 0x02, 0x4e, 0x13, 0x00, 0x06, +0x05, 0xe3, 0x00, 0x03, 0x4f, 0xe2, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0x70, +0x44, 0x20, 0x03, 0x03, 0x49, 0xff, 0xe2, 0x02, 0x48, 0x00, 0x00, 0x00, 0x51, 0xce, 0x00, 0x01, +0x55, 0xce, 0x00, 0xff, 0x44, 0x50, 0x00, 0x03, 0x4d, 0xc2, 0x80, 0x38, 0x04, 0x55, 0x00, 0x00, +0x46, 0x46, 0x03, 0x10, 0x14, 0x53, 0x00, 0x00, 0x04, 0x04, 0x80, 0x02, 0x58, 0x32, 0x00, 0x00, +0x14, 0x04, 0x00, 0x00, 0x04, 0x22, 0x00, 0x01, 0x58, 0x11, 0x80, 0x00, 0x14, 0x23, 0x00, 0x01, +0x05, 0xe1, 0x80, 0x03, 0x58, 0x00, 0x80, 0x00, 0x15, 0xe4, 0x00, 0x01, 0x04, 0x50, 0x80, 0x09, +0x46, 0x3a, 0x00, 0x00, 0x14, 0x53, 0x00, 0x02, 0x04, 0x40, 0x00, 0x0a, 0x59, 0xe1, 0x80, 0x00, +0x14, 0x44, 0x00, 0x02, 0x04, 0x21, 0x80, 0x02, 0x46, 0x56, 0x04, 0x00, 0x14, 0x23, 0x00, 0x03, +0x04, 0x1f, 0x00, 0x01, 0x14, 0x14, 0x00, 0x03, 0x04, 0x32, 0x80, 0x00, 0x42, 0x01, 0xdc, 0x0b, +0x4e, 0x03, 0xfe, 0xf0, 0x48, 0xff, 0xfe, 0xfc, 0x51, 0xff, 0x80, 0x24, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xa4, 0x44, 0x40, 0x00, 0x80, +0x54, 0x30, 0x00, 0xff, 0x44, 0x50, 0x00, 0x01, 0x40, 0x62, 0x8c, 0x1b, 0x40, 0x62, 0x0c, 0x1a, +0x50, 0x0f, 0x80, 0x1c, 0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x23, 0x45, 0xc0, 0x00, 0x00, +0x14, 0x6f, 0x80, 0x05, 0x49, 0xf7, 0xf0, 0x52, 0x15, 0xcf, 0x80, 0x04, 0x50, 0x6f, 0x80, 0x40, +0x50, 0xaf, 0x80, 0x48, 0x50, 0x9f, 0x80, 0x54, 0x50, 0x8f, 0x80, 0x42, 0x50, 0x7f, 0x80, 0x49, +0x04, 0x3f, 0x80, 0x04, 0x51, 0xcf, 0x80, 0x4c, 0x51, 0xef, 0x80, 0x50, 0x54, 0x01, 0x80, 0xff, +0x58, 0x13, 0x00, 0x00, 0x58, 0x25, 0x00, 0x00, 0x15, 0xcf, 0x80, 0x03, 0x15, 0xef, 0x80, 0x00, +0x51, 0xcf, 0x80, 0x44, 0x51, 0xef, 0x80, 0x4a, 0x58, 0x34, 0x80, 0x00, 0x58, 0x44, 0x00, 0x00, +0x58, 0x53, 0x80, 0x00, 0x15, 0xcf, 0x80, 0x01, 0x15, 0xef, 0x80, 0x02, 0x49, 0x00, 0x30, 0xa6, +0x05, 0xcf, 0x80, 0x04, 0x44, 0x00, 0x00, 0x00, 0x50, 0x2e, 0x00, 0x01, 0x14, 0x2f, 0x80, 0x04, +0x05, 0xcf, 0x80, 0x05, 0x04, 0x1f, 0x80, 0x04, 0x12, 0x03, 0x00, 0x03, 0x40, 0xf0, 0xf0, 0x06, +0x4e, 0xf3, 0xff, 0xd0, 0x51, 0xff, 0x80, 0x5c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x49, 0x00, 0x32, 0x96, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3e, 0x0f, 0xbf, 0x1c, 0x44, 0x20, 0x00, 0x00, +0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x01, 0x14, 0x20, 0x00, 0x02, 0x50, 0x10, 0x00, 0x10, +0x58, 0x40, 0x00, 0x00, 0x14, 0x20, 0x80, 0x02, 0x04, 0x52, 0x00, 0x01, 0x14, 0x10, 0x00, 0x01, +0x14, 0x50, 0x80, 0x01, 0x14, 0x00, 0x80, 0x00, 0x14, 0x12, 0x80, 0x00, 0x50, 0x10, 0x80, 0x68, +0x04, 0x30, 0x00, 0x02, 0x50, 0x51, 0x80, 0x01, 0x50, 0x30, 0x01, 0xb0, 0x14, 0x50, 0x00, 0x02, +0x4c, 0x11, 0xff, 0xea, 0x3e, 0x0f, 0xbc, 0x7c, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x01, +0x14, 0x20, 0x00, 0x02, 0x50, 0x10, 0x00, 0x0c, 0x58, 0x40, 0x00, 0x00, 0x14, 0x20, 0x80, 0x02, +0x04, 0x52, 0x00, 0x01, 0x14, 0x10, 0x00, 0x01, 0x14, 0x50, 0x80, 0x01, 0x14, 0x00, 0x80, 0x00, +0x14, 0x12, 0x80, 0x00, 0x50, 0x10, 0x80, 0x44, 0x04, 0x30, 0x00, 0x02, 0x50, 0x51, 0x80, 0x01, +0x50, 0x30, 0x01, 0x1c, 0x14, 0x50, 0x00, 0x02, 0x4c, 0x11, 0xff, 0xea, 0x3e, 0x0f, 0xb6, 0xa4, +0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x01, 0x14, 0x20, 0x00, 0x02, 0x50, 0x10, 0x00, 0x10, +0x58, 0x40, 0x00, 0x00, 0x14, 0x20, 0x80, 0x02, 0x04, 0x52, 0x00, 0x01, 0x14, 0x10, 0x00, 0x01, +0x14, 0x50, 0x80, 0x01, 0x14, 0x00, 0x80, 0x00, 0x14, 0x12, 0x80, 0x00, 0x50, 0x10, 0x80, 0x68, +0x04, 0x30, 0x00, 0x02, 0x50, 0x51, 0x80, 0x01, 0x50, 0x30, 0x01, 0xb0, 0x14, 0x50, 0x00, 0x02, +0x4c, 0x11, 0xff, 0xea, 0x4a, 0x00, 0x78, 0x20, 0x54, 0x00, 0x00, 0xff, 0x40, 0x10, 0x00, 0x10, +0x4e, 0x14, 0x00, 0x06, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0a, 0x44, 0x30, 0x00, 0x03, +0x42, 0x00, 0x0c, 0x24, 0x3e, 0x2f, 0xbd, 0x98, 0x40, 0x00, 0x08, 0x00, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x3e, 0x1f, 0xbc, 0x7c, 0x04, 0x60, 0x80, 0x00, +0x40, 0x70, 0x00, 0x13, 0x4c, 0x60, 0xc0, 0x06, 0x44, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0x20, +0x04, 0x53, 0x00, 0x01, 0x04, 0x33, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x14, 0x51, 0x80, 0x01, +0x14, 0x32, 0x80, 0x00, 0x14, 0x43, 0x00, 0x01, 0x14, 0x43, 0x00, 0x00, 0x04, 0x20, 0x80, 0x02, +0x50, 0x01, 0x7f, 0xff, 0x14, 0x00, 0x80, 0x02, 0x4e, 0x62, 0x00, 0x0a, 0x58, 0x03, 0x80, 0x00, +0x49, 0xf7, 0xf4, 0xde, 0x14, 0x03, 0x00, 0x02, 0x12, 0x73, 0x00, 0x06, 0x58, 0x03, 0x00, 0x00, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x3e, 0x3f, 0xbf, 0x1c, 0x56, 0x10, 0x80, 0x01, 0x3e, 0x4f, 0xb6, 0xa4, +0x40, 0x22, 0x04, 0x1a, 0x40, 0x21, 0x84, 0x1b, 0x04, 0x61, 0x00, 0x00, 0x40, 0x70, 0x00, 0x13, +0x4c, 0x61, 0x40, 0x06, 0x44, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0x20, 0x04, 0x13, 0x00, 0x01, +0x04, 0x33, 0x00, 0x00, 0x45, 0xe0, 0x00, 0x00, 0x14, 0x11, 0x80, 0x01, 0x14, 0x30, 0x80, 0x00, +0x15, 0xe3, 0x00, 0x01, 0x15, 0xe3, 0x00, 0x00, 0x04, 0x51, 0x00, 0x02, 0x50, 0x02, 0xff, 0xff, +0x14, 0x01, 0x00, 0x02, 0x4e, 0x62, 0x00, 0x0a, 0x58, 0x03, 0x80, 0x00, 0x49, 0xf7, 0xf4, 0xa0, +0x14, 0x03, 0x00, 0x02, 0x12, 0x73, 0x00, 0x06, 0x58, 0x03, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x28, 0x3e, 0x0f, 0xb8, 0x54, 0x49, 0xf7, 0xee, 0xfe, +0x44, 0x2f, 0xff, 0xff, 0x3e, 0x1f, 0xb8, 0x7c, 0x3c, 0x2f, 0xee, 0x16, 0x3c, 0x1f, 0xee, 0x15, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x40, 0x00, 0x00, 0x13, 0x49, 0xf7, 0xf4, 0x8c, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x58, 0x60, 0x00, 0x00, 0x54, 0x10, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, +0x3e, 0x1f, 0x9b, 0xac, 0x44, 0x20, 0x02, 0x11, 0x49, 0xff, 0xe0, 0x20, 0x48, 0x00, 0x00, 0x00, +0x3e, 0x0f, 0xbf, 0x2c, 0x40, 0xf3, 0x00, 0x06, 0x4e, 0xf3, 0x00, 0x0c, 0x50, 0x00, 0x01, 0x38, +0x40, 0xf0, 0x18, 0x06, 0x4e, 0xf3, 0x00, 0x06, 0x3e, 0x7f, 0xbf, 0x1c, 0x48, 0x00, 0x00, 0x14, +0x3e, 0x0f, 0xbc, 0x88, 0x40, 0xf3, 0x00, 0x06, 0x4e, 0xf3, 0x00, 0x0c, 0x50, 0x20, 0x00, 0xcc, +0x40, 0xf1, 0x18, 0x06, 0x4e, 0xf3, 0x00, 0x06, 0x50, 0x70, 0x7f, 0xf4, 0x48, 0x00, 0x00, 0x04, +0x3e, 0x7f, 0xb6, 0xa4, 0x4e, 0x12, 0x00, 0x18, 0x04, 0x13, 0x00, 0x02, 0x4e, 0x12, 0x00, 0x14, +0x02, 0x03, 0x00, 0x06, 0x44, 0x50, 0x0f, 0xff, 0x4c, 0x02, 0xc0, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, +0x3e, 0x1f, 0x9b, 0xac, 0x44, 0x20, 0x02, 0x25, 0x49, 0xff, 0xdf, 0xe8, 0x48, 0x00, 0x00, 0x00, +0x49, 0xf7, 0xf4, 0x38, 0x44, 0x00, 0x00, 0x00, 0x14, 0x03, 0x00, 0x02, 0x05, 0xe3, 0x80, 0x01, +0x14, 0x63, 0x80, 0x01, 0x14, 0x73, 0x00, 0x00, 0x15, 0xe3, 0x00, 0x01, 0x14, 0x6f, 0x00, 0x00, +0x04, 0x53, 0x80, 0x02, 0x50, 0x42, 0x80, 0x01, 0x14, 0x43, 0x80, 0x02, 0x51, 0xff, 0x80, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x51, 0xff, 0xff, 0xc0, +0x54, 0x70, 0x00, 0xff, 0x40, 0x03, 0x80, 0x10, 0x54, 0x80, 0x80, 0xff, 0x4e, 0x05, 0x00, 0x2e, +0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x23, 0x50, 0x0f, 0x80, 0x04, 0x49, 0xf7, 0xee, 0x66, +0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x0c, 0x50, 0x0f, 0x80, 0x28, 0x49, 0xf7, 0xee, 0x5e, +0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x0a, 0x50, 0x0f, 0x80, 0x34, 0x49, 0xf7, 0xee, 0x56, +0x46, 0x16, 0x03, 0x20, 0x58, 0x10, 0x80, 0x0c, 0x40, 0x23, 0x94, 0x08, 0x40, 0x01, 0x04, 0x00, +0x04, 0x10, 0x00, 0x00, 0x4e, 0x82, 0x00, 0x06, 0x42, 0x10, 0xfc, 0x08, 0x48, 0x00, 0x00, 0x04, +0x42, 0x10, 0xfc, 0x09, 0x14, 0x10, 0x00, 0x00, 0x51, 0xff, 0x80, 0x40, 0x3a, 0x6f, 0xa0, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x54, 0x60, 0x00, 0xff, +0x40, 0x03, 0x00, 0x10, 0x54, 0x70, 0x80, 0xff, 0x4e, 0x05, 0x00, 0x24, 0x58, 0x03, 0x00, 0x00, +0x50, 0x1f, 0x80, 0x05, 0x50, 0x2f, 0x80, 0x06, 0x50, 0x3f, 0x80, 0x07, 0x49, 0x00, 0x31, 0x5a, +0x00, 0x0f, 0x80, 0x05, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x0a, 0x00, 0x2f, 0x80, 0x06, +0x4c, 0x20, 0x40, 0x06, 0x00, 0x3f, 0x80, 0x07, 0x4c, 0x33, 0x80, 0x0c, 0x44, 0x10, 0x00, 0x01, +0x58, 0x03, 0x00, 0x00, 0x58, 0x33, 0x80, 0x00, 0x58, 0x20, 0x80, 0x00, 0x49, 0x00, 0x32, 0x62, +0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x40, 0x00, 0x00, 0x13, 0x49, 0xf7, 0xf3, 0x8a, 0x00, 0x40, 0x00, 0x03, +0x44, 0x2f, 0xff, 0xa0, 0x54, 0x32, 0x00, 0x1f, 0x40, 0x11, 0x88, 0x04, 0x10, 0x10, 0x00, 0x03, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xf4, 0x54, 0x21, 0x00, 0xff, 0x59, 0xc0, 0x00, 0x00, 0x54, 0x70, 0x80, 0xff, +0x14, 0x2f, 0x80, 0x01, 0x4e, 0x02, 0x00, 0x5a, 0x50, 0x33, 0x80, 0x04, 0x40, 0xa1, 0x8c, 0x00, +0x44, 0x60, 0x00, 0x00, 0x44, 0x90, 0x00, 0x01, 0x40, 0x0e, 0x18, 0x0d, 0x54, 0x10, 0x00, 0x01, +0x50, 0x03, 0x7f, 0xf9, 0x4e, 0x12, 0x00, 0x44, 0x5c, 0xf0, 0x00, 0x02, 0x4e, 0xf2, 0x00, 0x12, +0x5c, 0xf3, 0x80, 0x03, 0x4e, 0xf2, 0x00, 0x3c, 0x54, 0x03, 0x00, 0xff, 0x58, 0x13, 0x80, 0x00, +0x44, 0x20, 0x00, 0x01, 0x44, 0x30, 0x4e, 0x20, 0x3e, 0x4e, 0xb1, 0x58, 0x48, 0x00, 0x00, 0x16, +0x04, 0x5f, 0x80, 0x01, 0x54, 0x43, 0x00, 0xff, 0x58, 0x13, 0x80, 0x00, 0x44, 0x20, 0x00, 0x01, +0x44, 0x30, 0x4e, 0x20, 0x58, 0x02, 0x00, 0x00, 0x4e, 0x52, 0x00, 0x06, 0x49, 0xff, 0xea, 0xb6, +0x48, 0x00, 0x00, 0x06, 0x3e, 0x4e, 0xb1, 0xf8, 0x4b, 0xe0, 0x10, 0x01, 0x3c, 0x2d, 0xec, 0x31, +0x40, 0x14, 0x98, 0x0c, 0x41, 0xe1, 0x28, 0x00, 0x02, 0x4f, 0x00, 0x02, 0x40, 0x30, 0x90, 0x04, +0x12, 0x3f, 0x00, 0x02, 0x4e, 0x02, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0xcc, +0x44, 0x20, 0x12, 0x92, 0x49, 0xff, 0xde, 0xe2, 0x48, 0x00, 0x00, 0x00, 0x50, 0x63, 0x00, 0x01, +0x44, 0x00, 0x00, 0x0e, 0x4c, 0x60, 0x7f, 0xb2, 0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x59, 0xc0, 0x00, 0x00, +0x54, 0x70, 0x80, 0xff, 0x4e, 0x02, 0x00, 0x46, 0x50, 0xa3, 0x80, 0x04, 0x40, 0xa5, 0x28, 0x00, +0x44, 0x60, 0x00, 0x00, 0x44, 0x90, 0x00, 0x01, 0x40, 0x1e, 0x18, 0x0d, 0x54, 0x00, 0x80, 0x01, +0x50, 0x23, 0x7f, 0xf9, 0x4e, 0x02, 0x00, 0x30, 0x54, 0x03, 0x00, 0xff, 0x58, 0x13, 0x80, 0x00, +0x5c, 0xf1, 0x00, 0x02, 0x4e, 0xf2, 0x00, 0x0a, 0x5c, 0xf3, 0x80, 0x03, 0x4e, 0xf2, 0x00, 0x24, +0x3e, 0x2e, 0xae, 0x40, 0x48, 0x00, 0x00, 0x04, 0x3e, 0x2e, 0xae, 0x94, 0x4b, 0xe0, 0x08, 0x01, +0x3c, 0x1d, 0xec, 0x31, 0x40, 0x24, 0x98, 0x0c, 0x40, 0x40, 0xa8, 0x00, 0x02, 0x32, 0x00, 0x02, +0x40, 0x51, 0x08, 0x05, 0x40, 0x22, 0x8c, 0x02, 0x12, 0x22, 0x00, 0x02, 0x4e, 0x02, 0x00, 0x0c, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0xcc, 0x44, 0x20, 0x12, 0x52, 0x49, 0xff, 0xde, 0x8e, +0x48, 0x00, 0x00, 0x00, 0x50, 0x63, 0x00, 0x01, 0x44, 0x50, 0x00, 0x0e, 0x4c, 0x62, 0xff, 0xc6, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x54, 0x00, 0x00, 0xff, 0x49, 0xff, 0xfd, 0x98, 0x4e, 0x03, 0x00, 0x06, +0x44, 0x00, 0x00, 0xff, 0x48, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x40, 0x20, 0x00, 0x13, 0x44, 0x00, 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x58, 0x30, 0x00, 0x00, +0x49, 0xf7, 0xf6, 0xc8, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x45, 0xc0, 0x2c, 0xdc, 0x54, 0x70, 0x00, 0xff, +0x58, 0x13, 0x80, 0x00, 0x44, 0x20, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, 0x49, 0x00, 0x31, 0xb2, +0x44, 0x50, 0x0f, 0xff, 0x58, 0x13, 0x80, 0x00, 0x44, 0x20, 0x00, 0x00, 0x4c, 0x02, 0x80, 0x1e, +0x44, 0x00, 0x00, 0x01, 0x49, 0xf7, 0xf6, 0x16, 0x58, 0x60, 0x00, 0x00, 0x4b, 0xe0, 0x70, 0x01, +0x00, 0x10, 0x00, 0x05, 0x44, 0x50, 0x00, 0xa0, 0x58, 0x03, 0x00, 0x00, 0x4c, 0x12, 0x80, 0x0a, +0x49, 0xff, 0xfe, 0xd6, 0x58, 0x03, 0x00, 0x00, 0x49, 0xff, 0xff, 0xc0, 0x48, 0xff, 0xff, 0xda, +0x49, 0xff, 0xfd, 0xe6, 0x48, 0xff, 0xff, 0xd6, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x58, 0x70, 0x00, 0x00, 0x49, 0xff, 0xef, 0x22, +0x04, 0x63, 0x80, 0x02, 0x00, 0x83, 0x00, 0x20, 0x40, 0x04, 0x00, 0x10, 0x4e, 0x04, 0x00, 0x06, +0x44, 0x10, 0xff, 0xff, 0x48, 0x00, 0x00, 0x14, 0x44, 0x20, 0x00, 0x00, 0x3e, 0x1f, 0xc0, 0xe0, +0x38, 0x20, 0xa0, 0x08, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0xff, 0xac, 0x44, 0x10, 0x00, 0x00, +0x58, 0x04, 0x00, 0x00, 0x49, 0xff, 0xfe, 0x70, 0x44, 0x10, 0x00, 0x00, 0x00, 0x33, 0x00, 0x0b, +0x54, 0x01, 0x80, 0x01, 0x4e, 0x02, 0x00, 0x2e, 0x00, 0x23, 0x00, 0x07, 0x50, 0x43, 0x00, 0x0c, +0x14, 0x12, 0x00, 0x01, 0x44, 0x30, 0x00, 0x18, 0x44, 0x1f, 0xff, 0xed, 0x44, 0x50, 0x00, 0x00, +0x44, 0x00, 0x00, 0x0a, 0x14, 0x52, 0x00, 0x02, 0x14, 0x82, 0x00, 0x00, 0x12, 0x33, 0x00, 0x00, +0x10, 0x13, 0x00, 0x04, 0x10, 0x03, 0x00, 0x08, 0x10, 0x23, 0x00, 0x05, 0x45, 0xe0, 0x00, 0x01, +0x04, 0x53, 0x80, 0x02, 0x44, 0x4f, 0xe0, 0x00, 0x11, 0xe3, 0x80, 0x10, 0x12, 0x42, 0x80, 0x01, +0x58, 0x03, 0x80, 0x00, 0x49, 0x00, 0x03, 0x64, 0x49, 0xff, 0xee, 0xd4, 0x44, 0x00, 0x00, 0x01, +0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x55, 0xc0, 0x00, 0xff, 0x54, 0xa0, 0x80, 0xff, 0x48, 0x00, 0x00, 0x08, 0x49, 0xff, 0xfe, 0x60, +0x58, 0x03, 0x00, 0x00, 0x49, 0xff, 0xff, 0x4a, 0x58, 0x15, 0x00, 0x00, 0x44, 0x20, 0x00, 0x00, +0x58, 0x0e, 0x00, 0x00, 0x49, 0xf7, 0xf5, 0x86, 0x44, 0x50, 0x0f, 0xff, 0x58, 0x60, 0x00, 0x00, +0x4c, 0x02, 0xff, 0xee, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xdc, 0x54, 0x21, 0x00, 0xff, 0x54, 0x31, 0x80, 0xff, +0x14, 0x1f, 0x80, 0x01, 0x14, 0x0f, 0x80, 0x02, 0x14, 0x2f, 0x80, 0x03, 0x14, 0x3f, 0x80, 0x04, +0x4e, 0x12, 0x00, 0x0a, 0x44, 0x00, 0x00, 0x01, 0x4c, 0x10, 0x00, 0x06, 0x44, 0xa0, 0x00, 0x00, +0x48, 0x00, 0x00, 0x44, 0x54, 0x42, 0x00, 0xff, 0x44, 0x90, 0x00, 0x00, 0x47, 0xcc, 0x00, 0x00, +0x14, 0x4f, 0x80, 0x05, 0x59, 0xce, 0x00, 0x01, 0x58, 0xa4, 0x80, 0x00, 0x50, 0x8f, 0x80, 0x1f, +0x50, 0x7f, 0x80, 0x1c, 0x50, 0x6f, 0x80, 0x1a, 0x04, 0x1f, 0x80, 0x02, 0x41, 0xe0, 0xa4, 0x0d, +0x54, 0x5f, 0x00, 0x01, 0x4e, 0x52, 0x00, 0x24, 0x58, 0x14, 0x80, 0x00, 0x44, 0x20, 0x00, 0x00, +0x44, 0x00, 0x00, 0x02, 0x49, 0x00, 0x30, 0xce, 0x44, 0x50, 0x0f, 0xff, 0x04, 0x1f, 0x80, 0x03, +0x04, 0x2f, 0x80, 0x04, 0x58, 0x34, 0x80, 0x00, 0x04, 0x4f, 0x80, 0x05, 0x4c, 0x02, 0x80, 0x10, +0x04, 0x0f, 0x80, 0x01, 0x49, 0xff, 0xe5, 0x90, 0x40, 0xae, 0x00, 0x1b, 0x58, 0x13, 0x80, 0x00, +0x58, 0x04, 0x00, 0x00, 0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xe5, 0xd0, 0x50, 0x94, 0x80, 0x01, +0x44, 0x50, 0x00, 0x0e, 0x4c, 0x92, 0xff, 0xd2, 0x58, 0x05, 0x00, 0x00, 0x51, 0xff, 0x80, 0x24, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x54, 0x81, 0x80, 0xff, 0x50, 0x44, 0x00, 0x04, 0x3c, 0x3d, 0xec, 0x31, 0x40, 0x02, 0x10, 0x00, +0x44, 0x50, 0x00, 0x00, 0x58, 0x70, 0x80, 0x00, 0x40, 0x01, 0x80, 0x00, 0x54, 0x61, 0x00, 0xff, +0x58, 0x92, 0x80, 0x00, 0x44, 0x10, 0x00, 0x01, 0x40, 0xa3, 0x94, 0x0d, 0x54, 0x25, 0x00, 0x01, +0x4e, 0x22, 0x00, 0x0e, 0x02, 0x30, 0x00, 0x02, 0x40, 0x20, 0x94, 0x0c, 0x41, 0xe1, 0x94, 0x0e, +0x55, 0xcf, 0x00, 0x01, 0x4f, 0xc3, 0x00, 0x04, 0x40, 0x94, 0x88, 0x04, 0x50, 0x52, 0x80, 0x01, +0x44, 0x40, 0x00, 0x0e, 0x4c, 0x52, 0x7f, 0xea, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, +0x49, 0xff, 0xfd, 0x3c, 0x3f, 0xce, 0xc7, 0x88, 0x44, 0x10, 0x00, 0x01, 0x58, 0x03, 0x00, 0x00, +0x4b, 0xe0, 0x70, 0x01, 0x44, 0x20, 0x00, 0x00, 0x58, 0x03, 0x80, 0x00, 0x58, 0x14, 0x00, 0x00, +0x49, 0xff, 0xfd, 0xb6, 0x58, 0x04, 0x80, 0x00, 0x58, 0x14, 0x00, 0x00, 0x49, 0xff, 0xfe, 0x1c, +0x44, 0x10, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x70, 0x01, 0x44, 0x10, 0x00, 0x00, +0x58, 0x20, 0x80, 0x00, 0x58, 0x03, 0x80, 0x00, 0x44, 0x30, 0x00, 0x03, 0x58, 0x43, 0x00, 0x00, +0x49, 0xff, 0xff, 0x40, 0x58, 0x10, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, +0x3e, 0x1f, 0x9b, 0xcc, 0x44, 0x20, 0x0d, 0x76, 0x49, 0xff, 0xdc, 0xd0, 0x48, 0x00, 0x00, 0x00, +0x58, 0x03, 0x00, 0x00, 0x49, 0xff, 0xfd, 0x02, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x58, 0x80, 0x80, 0x00, 0x58, 0x60, 0x00, 0x00, +0x4e, 0x12, 0x00, 0x2c, 0x44, 0x50, 0x00, 0x05, 0x4c, 0x62, 0x80, 0x22, 0x44, 0x10, 0x00, 0x06, +0x4c, 0x60, 0xc0, 0x14, 0x54, 0x71, 0x00, 0xff, 0x58, 0x03, 0x80, 0x00, 0x49, 0xff, 0xfe, 0x30, +0x58, 0x30, 0x00, 0x00, 0x58, 0x14, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x58, 0x23, 0x80, 0x00, +0x49, 0xff, 0xff, 0x6c, 0x48, 0x00, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0xcc, +0x44, 0x20, 0x0d, 0xb9, 0x49, 0xff, 0xdc, 0x9a, 0x48, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x03, +0x44, 0x10, 0x00, 0x00, 0x49, 0xff, 0xfe, 0xd2, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x98, 0xbc, 0x00, 0x60, 0x00, 0x02, 0x54, 0x10, 0x80, 0xff, 0x40, 0x03, 0x00, 0x10, +0x4e, 0x04, 0x00, 0x06, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x14, 0x4e, 0x13, 0x00, 0x04, +0x48, 0x00, 0x00, 0x0e, 0x58, 0x03, 0x00, 0x00, 0x49, 0xff, 0xfc, 0xee, 0x58, 0x23, 0x00, 0x00, +0x44, 0x00, 0x00, 0x06, 0x44, 0x10, 0x00, 0x0f, 0x49, 0xff, 0xff, 0xae, 0x44, 0x00, 0x00, 0x01, +0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x04, 0x60, 0x00, 0x02, +0x58, 0x70, 0x00, 0x00, 0x00, 0x83, 0x00, 0x20, 0x40, 0x04, 0x00, 0x10, 0x4e, 0x04, 0x00, 0x06, +0x44, 0x10, 0xff, 0xff, 0x48, 0x00, 0x00, 0x0e, 0x58, 0x04, 0x00, 0x00, 0x49, 0xff, 0xfb, 0x76, +0x10, 0x80, 0x00, 0x02, 0x44, 0x10, 0x00, 0x01, 0x49, 0xff, 0xff, 0xc4, 0x44, 0x10, 0x00, 0x00, +0x00, 0x23, 0x00, 0x0b, 0x54, 0x01, 0x00, 0x01, 0x4e, 0x02, 0x00, 0x2c, 0x00, 0x53, 0x00, 0x07, +0x50, 0x43, 0x00, 0x0c, 0x44, 0x30, 0x00, 0x00, 0x44, 0x20, 0x00, 0x18, 0x44, 0x0f, 0xff, 0xed, +0x45, 0xe0, 0x00, 0x14, 0x14, 0x32, 0x00, 0x02, 0x14, 0x82, 0x00, 0x00, 0x14, 0x12, 0x00, 0x01, +0x10, 0x03, 0x00, 0x04, 0x12, 0x23, 0x00, 0x00, 0x11, 0xe3, 0x00, 0x08, 0x10, 0x53, 0x00, 0x05, +0x44, 0x40, 0x00, 0x01, 0x04, 0x13, 0x80, 0x02, 0x44, 0x3f, 0xe0, 0x00, 0x10, 0x43, 0x80, 0x10, +0x12, 0x30, 0x80, 0x01, 0x58, 0x03, 0x80, 0x00, 0x49, 0x00, 0x01, 0xba, 0x44, 0x00, 0x00, 0x01, +0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x54, 0x81, 0x80, 0xff, 0x50, 0x44, 0x00, 0x04, 0x3c, 0x3d, 0xec, 0x31, 0x40, 0x02, 0x10, 0x00, +0x44, 0x50, 0x00, 0x00, 0x58, 0x70, 0x80, 0x00, 0x40, 0x01, 0x80, 0x00, 0x54, 0x61, 0x00, 0xff, +0x58, 0x92, 0x80, 0x00, 0x44, 0x10, 0x00, 0x01, 0x40, 0xa3, 0x94, 0x0d, 0x54, 0x25, 0x00, 0x01, +0x4e, 0x22, 0x00, 0x0e, 0x02, 0x30, 0x00, 0x02, 0x40, 0x20, 0x94, 0x0c, 0x41, 0xe1, 0x94, 0x0e, +0x55, 0xcf, 0x00, 0x01, 0x4f, 0xc3, 0x00, 0x04, 0x40, 0x94, 0x88, 0x04, 0x50, 0x52, 0x80, 0x01, +0x44, 0x40, 0x00, 0x0e, 0x4c, 0x52, 0x7f, 0xea, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, +0x49, 0xff, 0xfc, 0x1c, 0x3f, 0xce, 0xc7, 0x88, 0x44, 0x10, 0x00, 0x01, 0x58, 0x03, 0x00, 0x00, +0x4b, 0xe0, 0x70, 0x01, 0x44, 0x20, 0x00, 0x00, 0x58, 0x03, 0x80, 0x00, 0x58, 0x14, 0x00, 0x00, +0x49, 0xff, 0xfc, 0x96, 0x58, 0x04, 0x80, 0x00, 0x58, 0x14, 0x00, 0x00, 0x49, 0xff, 0xfc, 0xfc, +0x44, 0x10, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x70, 0x01, 0x44, 0x10, 0x00, 0x00, +0x58, 0x03, 0x80, 0x00, 0x44, 0x20, 0x00, 0x08, 0x44, 0x30, 0x00, 0x03, 0x58, 0x43, 0x00, 0x00, +0x49, 0xff, 0xfe, 0x20, 0x58, 0x10, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, +0x3e, 0x1f, 0x9b, 0xcc, 0x44, 0x20, 0x0d, 0x28, 0x49, 0xff, 0xdb, 0xb0, 0x48, 0x00, 0x00, 0x00, +0x58, 0x03, 0x00, 0x00, 0x49, 0xff, 0xfb, 0xe2, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x3e, 0x3f, 0xb0, 0xc4, +0x04, 0x11, 0x80, 0x00, 0x44, 0x00, 0x00, 0x00, 0x14, 0x00, 0x80, 0x00, 0x58, 0x20, 0x00, 0x00, +0x58, 0x10, 0x00, 0x00, 0x04, 0x51, 0x80, 0x00, 0x41, 0xe0, 0x84, 0x00, 0x40, 0x42, 0xf8, 0x00, +0x12, 0x22, 0x00, 0x02, 0x51, 0xe0, 0x80, 0x04, 0x04, 0x51, 0x80, 0x00, 0x40, 0x4f, 0x78, 0x00, +0x41, 0xe2, 0x90, 0x00, 0x50, 0x00, 0x00, 0x01, 0x44, 0x40, 0x00, 0x04, 0x12, 0x2f, 0x00, 0x02, +0x50, 0x10, 0x80, 0x01, 0x4c, 0x02, 0x7f, 0xe8, 0x3e, 0x0f, 0xc0, 0xe0, 0x18, 0x20, 0x00, 0x01, +0x3e, 0x5f, 0xc1, 0x60, 0x4c, 0x02, 0xff, 0xfc, 0x44, 0x10, 0x00, 0x01, 0x44, 0x00, 0x00, 0x00, +0x49, 0x00, 0x2d, 0x92, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xa4, 0x3c, 0x54, 0x10, 0x80, 0xff, 0x54, 0x21, 0x00, 0xff, 0x4e, 0x13, 0x00, 0x06, +0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x40, 0x46, 0x46, 0x01, 0x20, 0x58, 0x42, 0x01, 0x14, +0x50, 0x62, 0x7f, 0xfc, 0x50, 0x53, 0x7f, 0xf4, 0x50, 0x72, 0xff, 0xfc, 0x44, 0x30, 0x00, 0x00, +0x40, 0x83, 0x88, 0x1b, 0x40, 0x83, 0x08, 0x1a, 0x40, 0x62, 0x88, 0x1b, 0x40, 0x62, 0x08, 0x1a, +0x58, 0x21, 0x80, 0x00, 0x44, 0x40, 0x00, 0x01, 0x48, 0x00, 0x00, 0x1c, 0x38, 0x50, 0x0c, 0x00, +0x50, 0x31, 0x80, 0x01, 0x50, 0x92, 0x80, 0x05, 0x50, 0x72, 0x80, 0x0a, 0x40, 0x72, 0x1c, 0x0c, +0x40, 0x92, 0x24, 0x0c, 0x40, 0x94, 0x9c, 0x04, 0x50, 0x72, 0x80, 0x10, 0x40, 0x52, 0x14, 0x0c, +0x40, 0x54, 0x94, 0x04, 0x40, 0x72, 0x1c, 0x0c, 0x40, 0x52, 0x9c, 0x04, 0x40, 0x21, 0x14, 0x04, +0x40, 0xf1, 0x84, 0x06, 0x4e, 0xf3, 0xff, 0xe4, 0x14, 0x24, 0x00, 0x00, 0x14, 0x23, 0x00, 0x00, +0x44, 0x00, 0x00, 0x00, 0x3a, 0x6f, 0xa4, 0x04, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, +0x00, 0x10, 0x00, 0x2d, 0x50, 0x60, 0x00, 0x27, 0x54, 0x00, 0x80, 0x01, 0x4e, 0x02, 0x00, 0x0a, +0x44, 0x10, 0x00, 0x01, 0x50, 0x03, 0x00, 0x08, 0x58, 0x20, 0x80, 0x00, 0x49, 0xff, 0xff, 0xa2, +0x44, 0x20, 0x00, 0x00, 0x10, 0x23, 0x00, 0x07, 0x10, 0x23, 0x00, 0x05, 0x10, 0x23, 0x00, 0x06, +0x50, 0x03, 0x7f, 0xed, 0x49, 0x00, 0x26, 0xfe, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xa0, 0xbc, 0x50, 0x70, 0x00, 0x14, 0x50, 0x60, 0x00, 0x27, 0x58, 0x03, 0x80, 0x00, +0x49, 0x00, 0x26, 0xf0, 0x00, 0x23, 0x00, 0x06, 0x40, 0x01, 0x00, 0x10, 0x4e, 0x05, 0x00, 0x0c, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0xe8, 0x44, 0x20, 0x0b, 0xca, 0x49, 0xff, 0xda, 0xde, +0x48, 0x00, 0x00, 0x00, 0x54, 0x21, 0x00, 0x01, 0x50, 0x03, 0x00, 0x08, 0x4e, 0x23, 0x00, 0x16, +0x44, 0x10, 0x00, 0x01, 0x49, 0xff, 0xff, 0x6e, 0x00, 0x53, 0x00, 0x06, 0x50, 0x33, 0x7f, 0xdf, +0x58, 0x42, 0x80, 0x01, 0x10, 0x43, 0x00, 0x06, 0x44, 0x10, 0x03, 0xe8, 0x3a, 0x21, 0x88, 0x00, +0x40, 0x11, 0x04, 0x17, 0x48, 0x00, 0x00, 0x32, 0x44, 0x10, 0x00, 0x01, 0x58, 0x20, 0x80, 0x00, +0x49, 0xff, 0xff, 0x58, 0x00, 0x03, 0x00, 0x07, 0x44, 0x50, 0x00, 0xff, 0x4c, 0x02, 0x80, 0x12, +0x51, 0xe0, 0x7f, 0xff, 0x54, 0x0f, 0x00, 0xff, 0x10, 0x03, 0x00, 0x07, 0x4e, 0x03, 0x00, 0x0a, +0x10, 0x03, 0x00, 0x06, 0x58, 0x03, 0x80, 0x00, 0x49, 0x00, 0x26, 0xac, 0x48, 0x00, 0x00, 0x1a, +0x00, 0x13, 0x00, 0x06, 0x42, 0x50, 0x80, 0x09, 0x10, 0x53, 0x00, 0x06, 0x50, 0x43, 0x7f, 0xdf, +0x50, 0x63, 0x7f, 0xe3, 0x3a, 0x22, 0x08, 0x00, 0x3a, 0x63, 0x18, 0x00, 0x40, 0x33, 0x08, 0x01, +0x44, 0x00, 0x03, 0xe8, 0x40, 0x11, 0x80, 0x57, 0x58, 0x03, 0x80, 0x00, 0x49, 0x00, 0x27, 0x82, +0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x44, 0x1f, 0xff, 0xff, +0x58, 0x60, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x10, 0x13, 0x00, 0x2f, 0x10, 0x03, 0x00, 0x2e, +0x10, 0x03, 0x00, 0x2d, 0x58, 0x23, 0x00, 0x00, 0x50, 0x03, 0x00, 0x14, 0x3e, 0x1e, 0xdf, 0x5c, +0x49, 0x00, 0x26, 0x58, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x12, +0x49, 0xf7, 0xe9, 0x1c, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, +0x58, 0x60, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0xe8, +0x44, 0x20, 0x06, 0xd7, 0x49, 0xff, 0xda, 0x5a, 0x48, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, +0x4e, 0x03, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0xe8, 0x44, 0x20, 0x06, 0xd8, +0x49, 0xff, 0xda, 0x4c, 0x48, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x10, 0x5c, 0xf0, 0x80, 0x02, +0x4e, 0xf3, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0xe8, 0x44, 0x20, 0x06, 0xda, +0x49, 0xff, 0xda, 0x3c, 0x48, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x02, 0x23, 0x00, 0x06, +0x58, 0x30, 0x00, 0x00, 0x49, 0xf7, 0xf2, 0x9e, 0x4e, 0x03, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, +0x3e, 0x1f, 0x9b, 0xe8, 0x44, 0x20, 0x06, 0xe4, 0x49, 0xff, 0xda, 0x28, 0x48, 0x00, 0x00, 0x00, +0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x49, 0xff, 0xf9, 0xf0, 0x3a, 0x6f, 0x98, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x58, 0x60, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x0c, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0xe8, 0x44, 0x20, 0x05, 0xfc, 0x49, 0xff, 0xda, 0x0e, +0x48, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x10, 0x02, 0x23, 0x00, 0x06, +0x58, 0x30, 0x00, 0x00, 0x49, 0xf7, 0xf2, 0x6e, 0x4e, 0x03, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, +0x3e, 0x1f, 0x9b, 0xe8, 0x44, 0x20, 0x06, 0x07, 0x49, 0xff, 0xd9, 0xf8, 0x48, 0x00, 0x00, 0x00, +0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x49, 0xff, 0xf9, 0xc0, 0x3a, 0x6f, 0x98, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x4e, 0x03, 0x00, 0x0c, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0xe8, 0x44, 0x20, 0x09, 0x4f, 0x49, 0xff, 0xd9, 0xde, +0x48, 0x00, 0x00, 0x00, 0x44, 0x20, 0x00, 0x00, 0x10, 0x20, 0x00, 0x10, 0x49, 0xff, 0xff, 0xbc, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, +0x58, 0x60, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0xe8, +0x44, 0x20, 0x05, 0x57, 0x49, 0xff, 0xd9, 0xc2, 0x48, 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x0b, +0x4e, 0x13, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0xe8, 0x44, 0x20, 0x05, 0x58, +0x49, 0xff, 0xd9, 0xb4, 0x48, 0x00, 0x00, 0x00, 0x04, 0x20, 0x00, 0x0c, 0x4e, 0x23, 0x00, 0x0c, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0xe8, 0x44, 0x20, 0x05, 0x59, 0x49, 0xff, 0xd9, 0xa6, +0x48, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x00, 0x3e, 0x1f, 0x9c, 0x2c, 0x40, 0x32, 0x10, 0x09, +0x38, 0x10, 0x8e, 0x02, 0x4e, 0x12, 0x00, 0x08, 0x4b, 0xe0, 0x04, 0x01, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0x80, 0x06, 0x58, 0x03, 0x00, 0x00, 0x49, 0xff, 0xff, 0xa6, 0x3a, 0x6f, 0x98, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x58, 0x70, 0x00, 0x00, +0x49, 0xff, 0xf4, 0x3a, 0x58, 0xa0, 0x00, 0x00, 0x44, 0x20, 0x00, 0x2c, 0x50, 0x01, 0x00, 0x04, +0x40, 0x91, 0x28, 0x1a, 0x40, 0x90, 0x28, 0x1b, 0x58, 0x04, 0x80, 0x00, 0x49, 0xf7, 0xed, 0xde, +0x44, 0x50, 0x0f, 0xff, 0x58, 0x80, 0x00, 0x00, 0x4c, 0x02, 0xc0, 0x08, 0x46, 0x0c, 0x00, 0x00, +0x58, 0x00, 0x00, 0x9a, 0x48, 0x00, 0x00, 0xf2, 0x49, 0xf7, 0xed, 0xa2, 0x50, 0x60, 0x00, 0x04, +0x58, 0x24, 0x80, 0x00, 0x44, 0x10, 0x00, 0x00, 0x49, 0xf7, 0xe8, 0x10, 0x02, 0x03, 0x00, 0x0b, +0x00, 0x53, 0x00, 0x04, 0x44, 0x3f, 0xc0, 0x03, 0x40, 0x52, 0x98, 0x09, 0x40, 0x52, 0x98, 0x08, +0x40, 0x10, 0x0c, 0x02, 0x02, 0x23, 0x00, 0x04, 0x01, 0xe3, 0x7f, 0xff, 0x01, 0xc3, 0x00, 0x02, +0x00, 0x43, 0x00, 0x05, 0x14, 0x1f, 0x80, 0x01, 0x44, 0x1f, 0xff, 0x80, 0x00, 0x03, 0x00, 0x07, +0x54, 0x21, 0x00, 0x3f, 0x40, 0x30, 0x04, 0x04, 0x00, 0x03, 0x00, 0x11, 0x55, 0xef, 0x00, 0x7f, +0x58, 0x10, 0x00, 0x20, 0x04, 0x0f, 0x80, 0x01, 0x59, 0xce, 0x00, 0x08, 0x58, 0x00, 0x00, 0x04, +0x14, 0x0f, 0x80, 0x01, 0x12, 0x93, 0x7f, 0xfe, 0x44, 0x9f, 0xff, 0xff, 0x58, 0x52, 0x80, 0x1e, +0x58, 0x42, 0x00, 0x14, 0x58, 0x21, 0x28, 0x00, 0x10, 0x93, 0x00, 0x00, 0x44, 0x9f, 0xff, 0xc8, +0x11, 0xe3, 0x7f, 0xff, 0x10, 0x93, 0x00, 0x01, 0x11, 0xc3, 0x00, 0x02, 0x10, 0x53, 0x00, 0x04, +0x10, 0x43, 0x00, 0x05, 0x10, 0x33, 0x00, 0x07, 0x12, 0x23, 0x00, 0x04, 0x10, 0x13, 0x00, 0x11, +0x12, 0x03, 0x00, 0x0b, 0x4e, 0xa2, 0x00, 0x06, 0x50, 0x13, 0x00, 0x1c, 0x48, 0x00, 0x00, 0x04, +0x50, 0x13, 0x00, 0x18, 0x45, 0xef, 0xff, 0xff, 0x44, 0x30, 0x00, 0xe4, 0x44, 0x00, 0x00, 0x00, +0x12, 0x00, 0x80, 0x01, 0x12, 0x30, 0x80, 0x00, 0x11, 0xe0, 0x80, 0x09, 0x11, 0xe0, 0x80, 0x04, +0x11, 0xe0, 0x80, 0x05, 0x11, 0xe0, 0x80, 0x06, 0x11, 0xe0, 0x80, 0x07, 0x11, 0xe0, 0x80, 0x08, +0x50, 0x00, 0x80, 0x0a, 0x00, 0x43, 0x80, 0x04, 0x10, 0x40, 0x80, 0x0a, 0x00, 0x53, 0x80, 0x05, +0x10, 0x50, 0x80, 0x0b, 0x00, 0x23, 0x80, 0x06, 0x10, 0x20, 0x80, 0x0c, 0x00, 0x33, 0x80, 0x07, +0x10, 0x30, 0x80, 0x0d, 0x01, 0xe3, 0x80, 0x08, 0x11, 0xe0, 0x80, 0x0e, 0x00, 0x73, 0x80, 0x09, +0x10, 0x70, 0x80, 0x0f, 0x49, 0xff, 0xf3, 0x9a, 0x44, 0x50, 0x00, 0x0f, 0x58, 0x10, 0x00, 0x00, +0x4c, 0x02, 0xc0, 0x04, 0x48, 0x00, 0x00, 0x56, 0x00, 0x23, 0x00, 0x03, 0x40, 0x50, 0x08, 0x08, +0x54, 0x31, 0x00, 0x03, 0x40, 0x02, 0x8c, 0x04, 0x10, 0x03, 0x00, 0x03, 0x47, 0xe6, 0x01, 0x20, +0x46, 0x40, 0x02, 0x00, 0x04, 0x2f, 0x00, 0x40, 0x40, 0x12, 0x04, 0x0c, 0x40, 0x50, 0x88, 0x02, +0x4c, 0x50, 0xc0, 0x0e, 0x01, 0xe3, 0x7f, 0xff, 0x44, 0x0f, 0xff, 0x87, 0x40, 0x4f, 0x00, 0x02, +0x44, 0x10, 0x00, 0x04, 0x58, 0x02, 0x00, 0x20, 0x48, 0x00, 0x00, 0x14, 0x46, 0x26, 0x01, 0x20, +0x04, 0x51, 0x00, 0x41, 0x40, 0x30, 0x94, 0x02, 0x4c, 0x30, 0xc0, 0x10, 0x01, 0xe3, 0x7f, 0xff, +0x44, 0x0f, 0xff, 0x87, 0x40, 0x4f, 0x00, 0x02, 0x44, 0x10, 0x00, 0x0d, 0x58, 0x02, 0x00, 0x68, +0x10, 0x03, 0x7f, 0xff, 0x48, 0x00, 0x00, 0x08, 0x3e, 0x0f, 0x9c, 0x04, 0x49, 0xff, 0xd8, 0x96, +0x48, 0x00, 0x00, 0x18, 0x44, 0x00, 0x00, 0x02, 0x58, 0x24, 0x00, 0x00, 0x44, 0x30, 0x00, 0x01, +0x49, 0xf7, 0xf0, 0xf8, 0x4e, 0x02, 0x00, 0x06, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0e, +0x3e, 0x0f, 0x9c, 0x18, 0x49, 0xff, 0xd8, 0x82, 0x58, 0x04, 0x00, 0x00, 0x49, 0xf7, 0xec, 0xd2, +0x46, 0x0c, 0x00, 0x00, 0x58, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x58, 0x60, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x0c, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0xe8, 0x44, 0x20, 0x05, 0xac, 0x49, 0xff, 0xd8, 0x66, +0x48, 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x0b, 0x4e, 0x13, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, +0x3e, 0x1f, 0x9b, 0xe8, 0x44, 0x20, 0x05, 0xad, 0x49, 0xff, 0xd8, 0x58, 0x48, 0x00, 0x00, 0x00, +0x02, 0x30, 0x80, 0x00, 0x44, 0x20, 0x00, 0xa4, 0x54, 0x01, 0x80, 0xfc, 0x4c, 0x01, 0x40, 0x06, +0x58, 0x00, 0x80, 0x00, 0x49, 0xff, 0xfe, 0xc0, 0x58, 0x03, 0x00, 0x00, 0x49, 0xff, 0xfe, 0x5c, +0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xe4, +0x58, 0x70, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9b, 0xe8, +0x44, 0x20, 0x03, 0xc5, 0x49, 0xff, 0xd8, 0x32, 0x48, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x40, +0x44, 0x50, 0x00, 0x30, 0x42, 0x35, 0x14, 0x24, 0x3e, 0x4f, 0xb5, 0xdc, 0x40, 0x21, 0x90, 0x00, +0x00, 0x11, 0x00, 0x2c, 0x54, 0x00, 0x80, 0x02, 0x4e, 0x02, 0x00, 0xba, 0x44, 0x60, 0x00, 0x00, +0x04, 0x83, 0x80, 0x0c, 0x10, 0x6f, 0x80, 0x17, 0x50, 0x84, 0x00, 0x0c, 0x02, 0x23, 0x80, 0x09, +0x44, 0x90, 0x00, 0x00, 0x50, 0x6f, 0x80, 0x17, 0x3f, 0xce, 0xe9, 0x00, 0x48, 0x00, 0x00, 0x40, +0x01, 0xe4, 0x00, 0x00, 0x44, 0x50, 0x00, 0xdd, 0x4d, 0xe2, 0xc0, 0x30, 0x14, 0x2f, 0x80, 0x01, +0x58, 0x04, 0x00, 0x00, 0x58, 0x13, 0x00, 0x00, 0x4b, 0xe0, 0x70, 0x01, 0x04, 0x2f, 0x80, 0x01, +0x4e, 0x02, 0x00, 0x24, 0x00, 0x1f, 0x80, 0x17, 0x44, 0x50, 0x00, 0x09, 0x4c, 0x12, 0xc0, 0x1e, +0x50, 0x14, 0x00, 0x06, 0x00, 0x40, 0x80, 0x00, 0x44, 0x50, 0x00, 0x0c, 0x4c, 0x42, 0xc0, 0x16, +0x40, 0x02, 0x88, 0x08, 0x42, 0x65, 0x00, 0x24, 0x3f, 0xef, 0xb5, 0xdc, 0x40, 0x63, 0x78, 0x00, +0x50, 0x22, 0x80, 0x06, 0x58, 0x03, 0x00, 0x00, 0x49, 0xf7, 0xe6, 0x7c, 0x20, 0x23, 0x00, 0x2d, +0x4e, 0x24, 0x00, 0x26, 0x48, 0x00, 0x00, 0x12, 0x00, 0x34, 0x00, 0x01, 0x50, 0x11, 0x80, 0x02, +0x40, 0x94, 0x84, 0x00, 0x40, 0x84, 0x04, 0x00, 0x40, 0x94, 0x80, 0x13, 0x40, 0xf4, 0x88, 0x06, +0x4e, 0xf3, 0xff, 0xc0, 0x48, 0x00, 0x00, 0x64, 0x50, 0x03, 0x00, 0x14, 0x49, 0x00, 0x23, 0xca, +0x00, 0x53, 0x00, 0x2d, 0x54, 0x42, 0x80, 0x01, 0x4e, 0x42, 0x00, 0x0a, 0x44, 0x10, 0x00, 0x01, +0x50, 0x03, 0x80, 0x40, 0x58, 0x20, 0x80, 0x00, 0x49, 0xff, 0xfc, 0x54, 0x00, 0x03, 0x00, 0x05, +0x10, 0x03, 0x00, 0x2e, 0x4e, 0x03, 0x00, 0x04, 0x48, 0x00, 0x00, 0x3a, 0x00, 0x03, 0x80, 0x40, +0x50, 0x7f, 0x80, 0x0c, 0x58, 0x13, 0x80, 0x00, 0x49, 0xff, 0xed, 0x4e, 0x50, 0x03, 0x00, 0x0e, +0x04, 0x23, 0x80, 0x00, 0x3a, 0x10, 0x04, 0x00, 0x40, 0x10, 0x88, 0x01, 0x4e, 0x14, 0x00, 0x2c, +0x51, 0xe3, 0x00, 0x0a, 0x3a, 0x3f, 0x0c, 0x00, 0x3a, 0x10, 0x04, 0x00, 0x40, 0x41, 0x84, 0x00, +0x3a, 0x40, 0x10, 0x20, 0x00, 0x23, 0x00, 0x05, 0x44, 0x50, 0x00, 0xff, 0x04, 0x13, 0x80, 0x00, +0x50, 0x41, 0x7f, 0xff, 0x4c, 0x22, 0x80, 0x04, 0x10, 0x43, 0x00, 0x05, 0x3b, 0xf0, 0x7c, 0x80, +0x40, 0x1f, 0x04, 0x01, 0x4e, 0x14, 0x00, 0x06, 0x00, 0x23, 0x00, 0x05, 0x4e, 0x23, 0xff, 0xe6, +0x00, 0x03, 0x00, 0x05, 0x10, 0x03, 0x00, 0x2e, 0x4e, 0x03, 0x00, 0x06, 0x10, 0x03, 0x00, 0x2d, +0x48, 0x00, 0x00, 0x0e, 0x44, 0x00, 0x03, 0xe8, 0x40, 0x10, 0x80, 0x17, 0x44, 0x3f, 0xff, 0x80, +0x10, 0x33, 0x00, 0x2d, 0x50, 0x03, 0x00, 0x14, 0x49, 0x00, 0x24, 0x5c, 0x44, 0x00, 0x00, 0x00, +0x51, 0xff, 0x80, 0x1c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xec, 0x54, 0x00, 0x00, 0xff, 0x14, 0x0f, 0x80, 0x01, 0x44, 0x30, 0x00, 0x00, +0x04, 0x1f, 0x80, 0x01, 0x44, 0x00, 0x00, 0x01, 0x50, 0x2f, 0x80, 0x0e, 0x44, 0x90, 0x00, 0x00, +0x12, 0x31, 0x00, 0x00, 0x59, 0xc4, 0x80, 0x00, 0x49, 0xf7, 0xf1, 0x16, 0x50, 0x8f, 0x80, 0x08, +0x48, 0x00, 0x01, 0x00, 0x49, 0xff, 0xe8, 0x4e, 0x04, 0x1f, 0x80, 0x01, 0x44, 0x00, 0x00, 0x01, +0x44, 0x20, 0x00, 0x00, 0x49, 0xf7, 0xef, 0x16, 0x44, 0x50, 0x0f, 0xff, 0x4c, 0x02, 0x80, 0xf8, +0x49, 0xff, 0xf6, 0x68, 0x50, 0x60, 0x00, 0x10, 0x4e, 0x03, 0x00, 0x0e, 0x3c, 0x0d, 0xec, 0x33, +0x04, 0x20, 0x00, 0x00, 0x4e, 0x23, 0x00, 0xec, 0x44, 0x10, 0x00, 0x0a, 0x49, 0x00, 0x24, 0x1a, +0x48, 0x00, 0x00, 0xe6, 0x04, 0x70, 0x00, 0x02, 0x44, 0x10, 0x00, 0x10, 0x12, 0x10, 0x00, 0x0b, +0x14, 0x70, 0x00, 0x06, 0x02, 0x03, 0x80, 0x01, 0x41, 0xe0, 0x34, 0x09, 0x50, 0x3f, 0x7f, 0xfe, +0x54, 0x51, 0x80, 0xff, 0x11, 0xe3, 0x00, 0x04, 0x5c, 0xf2, 0x80, 0x02, 0x4e, 0xf2, 0x00, 0x44, +0x03, 0xe3, 0x80, 0x01, 0x54, 0x5f, 0x1e, 0x00, 0x40, 0x42, 0xa4, 0x09, 0x54, 0x22, 0x00, 0x08, +0x10, 0x43, 0x00, 0x05, 0x4e, 0x23, 0x00, 0x06, 0x58, 0x20, 0x80, 0x00, 0x48, 0x00, 0x00, 0x08, +0x50, 0x93, 0x80, 0x10, 0x14, 0x93, 0x00, 0x06, 0x40, 0x20, 0x84, 0x08, 0x00, 0x03, 0x00, 0x05, +0x54, 0x30, 0x00, 0x01, 0x4e, 0x32, 0x00, 0x0a, 0x40, 0x43, 0x88, 0x00, 0x50, 0x11, 0x00, 0x10, +0x14, 0x43, 0x00, 0x03, 0x40, 0x20, 0x80, 0x13, 0x01, 0xe3, 0x00, 0x05, 0x54, 0x5f, 0x00, 0x02, +0x4e, 0x52, 0x00, 0x0a, 0x40, 0x33, 0x88, 0x00, 0x14, 0x33, 0x00, 0x04, 0x50, 0x21, 0x00, 0x08, +0x40, 0x21, 0x00, 0x13, 0x00, 0x13, 0x00, 0x05, 0x54, 0x00, 0x80, 0x04, 0x4e, 0x02, 0x00, 0x0a, +0x40, 0x53, 0x88, 0x00, 0x50, 0x41, 0x00, 0x18, 0x14, 0x53, 0x00, 0x05, 0x40, 0x22, 0x00, 0x13, +0x12, 0x23, 0x00, 0x03, 0x00, 0x23, 0x00, 0x04, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x22, 0xc0, 0x4c, +0x01, 0xe3, 0x80, 0x06, 0x02, 0x03, 0x00, 0x03, 0x54, 0x5f, 0x00, 0x40, 0x40, 0x12, 0x94, 0x1a, +0x40, 0x11, 0x14, 0x1b, 0x40, 0x33, 0x80, 0x00, 0x40, 0x21, 0x84, 0x00, 0x42, 0x31, 0x00, 0x09, +0x14, 0x33, 0x00, 0x07, 0x01, 0xe3, 0x80, 0x06, 0x54, 0x4f, 0x00, 0x3f, 0x40, 0x51, 0x90, 0x00, +0x41, 0xe2, 0x88, 0x09, 0x41, 0xef, 0x08, 0x08, 0x10, 0x43, 0x00, 0x01, 0x15, 0xe3, 0x00, 0x08, +0x44, 0x40, 0x00, 0x00, 0x02, 0x03, 0x80, 0x00, 0x40, 0x23, 0x80, 0x00, 0x40, 0x51, 0x78, 0x01, +0x12, 0x53, 0x00, 0x01, 0x00, 0x13, 0x80, 0x07, 0x10, 0x43, 0x00, 0x2f, 0x40, 0x00, 0x88, 0x09, +0x10, 0x03, 0x00, 0x30, 0x02, 0x21, 0x80, 0x00, 0x54, 0x01, 0x00, 0x0c, 0x12, 0x23, 0x00, 0x15, +0x4e, 0x03, 0x00, 0x08, 0x50, 0x03, 0x7f, 0xf0, 0x49, 0xff, 0xfc, 0xba, 0x48, 0x00, 0x00, 0x40, +0x44, 0x20, 0x00, 0x04, 0x4c, 0x01, 0x40, 0x36, 0x50, 0x03, 0x7f, 0xf0, 0x49, 0xff, 0xfe, 0x0c, +0x48, 0x00, 0x00, 0x36, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x22, 0xc0, 0x2c, 0x04, 0x03, 0x00, 0x06, +0x44, 0x20, 0x00, 0x06, 0x50, 0x10, 0x00, 0x02, 0x58, 0x04, 0x00, 0x00, 0x49, 0xf7, 0xe5, 0x0a, +0x00, 0x03, 0x80, 0x08, 0x49, 0xff, 0xf5, 0x8a, 0x14, 0x03, 0x00, 0x09, 0x50, 0x03, 0x7f, 0xf0, +0x02, 0x54, 0x80, 0x00, 0x12, 0x53, 0x00, 0x15, 0x02, 0x14, 0x80, 0x04, 0x12, 0x13, 0x00, 0x14, +0x02, 0x34, 0x80, 0x05, 0x12, 0x33, 0x00, 0x16, 0x49, 0x00, 0x24, 0x7c, 0x50, 0x03, 0x7f, 0xf0, +0x44, 0x10, 0x00, 0x01, 0x49, 0xff, 0xf6, 0x22, 0x49, 0xff, 0xe7, 0x5c, 0x48, 0x00, 0x00, 0x08, +0x50, 0x03, 0x7f, 0xf0, 0x44, 0x10, 0x00, 0x01, 0x49, 0xff, 0xf6, 0x18, 0x51, 0xce, 0x00, 0x01, +0x03, 0xef, 0x80, 0x07, 0x40, 0xfe, 0x78, 0x06, 0x4e, 0xf3, 0xfe, 0xfe, 0x51, 0xff, 0x80, 0x14, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x44, 0x10, 0x00, 0x00, 0x44, 0x00, 0x00, 0x03, 0x49, 0xff, 0xde, 0x38, 0x46, 0x00, 0x02, 0x10, +0x58, 0x00, 0x00, 0x04, 0x49, 0xff, 0xde, 0x58, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x4e, 0x03, 0x00, 0x0c, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9c, 0x6c, 0x44, 0x20, 0x01, 0x93, 0x49, 0xff, 0xd6, 0x16, +0x48, 0x00, 0x00, 0x00, 0x4e, 0x13, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9c, 0x6c, +0x44, 0x20, 0x01, 0x94, 0x49, 0xff, 0xd6, 0x0a, 0x48, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x01, +0x5c, 0xf1, 0x00, 0x07, 0x4e, 0xf3, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x02, 0x44, 0x50, 0x00, 0x50, +0x4c, 0x42, 0xc0, 0x16, 0x00, 0x50, 0x00, 0x03, 0x45, 0xe0, 0x00, 0x6f, 0x4c, 0x5f, 0x40, 0x10, +0x00, 0x20, 0x00, 0x04, 0x44, 0x50, 0x00, 0x9a, 0x4c, 0x22, 0xc0, 0x0a, 0x00, 0x00, 0x00, 0x05, +0x10, 0x00, 0x80, 0x00, 0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3e, 0x5f, 0xb0, 0xd0, +0x04, 0x12, 0x80, 0x00, 0x44, 0x20, 0x00, 0x00, 0x14, 0x20, 0x80, 0x00, 0x58, 0x32, 0x80, 0x00, +0x04, 0x42, 0x80, 0x00, 0x58, 0x11, 0x00, 0x00, 0x10, 0x22, 0x00, 0x04, 0x58, 0x41, 0x00, 0x00, +0x04, 0x02, 0x80, 0x00, 0x10, 0x20, 0x00, 0x05, 0x04, 0x21, 0x80, 0x00, 0x40, 0x00, 0x8c, 0x08, +0x40, 0x51, 0x00, 0x00, 0x10, 0x12, 0x80, 0x06, 0x50, 0x10, 0x80, 0x01, 0x04, 0x21, 0x80, 0x00, +0x40, 0x51, 0x00, 0x00, 0x44, 0x00, 0x00, 0x08, 0x10, 0x42, 0x80, 0x07, 0x4c, 0x10, 0x7f, 0xee, +0x4a, 0x00, 0x78, 0x20, 0x2e, 0x00, 0x02, 0x85, 0x4e, 0x02, 0x00, 0x4e, 0x46, 0x36, 0x04, 0x00, +0x04, 0x41, 0x80, 0x02, 0x58, 0x11, 0x80, 0x00, 0x42, 0x22, 0x5c, 0x08, 0x14, 0x21, 0x80, 0x02, +0x04, 0x50, 0x80, 0x00, 0x46, 0x00, 0x08, 0x00, 0x40, 0x32, 0x80, 0x02, 0x4e, 0x33, 0xff, 0xfa, +0x46, 0x56, 0x04, 0x00, 0x58, 0x52, 0x80, 0x08, 0x04, 0x02, 0x80, 0x00, 0x46, 0x18, 0x00, 0x21, +0x58, 0x20, 0x00, 0x04, 0x14, 0x22, 0x80, 0x00, 0x58, 0x10, 0x81, 0x00, 0x04, 0x42, 0x80, 0x00, +0x46, 0x28, 0x00, 0x20, 0x58, 0x02, 0x00, 0x08, 0x14, 0x02, 0x80, 0x00, 0x04, 0x42, 0x80, 0x00, +0x58, 0x02, 0x00, 0x10, 0x14, 0x02, 0x80, 0x00, 0x04, 0x42, 0x80, 0x00, 0x58, 0x02, 0x00, 0x03, +0x14, 0x02, 0x80, 0x00, 0x44, 0x4f, 0xff, 0x9f, 0x04, 0x00, 0x80, 0x00, 0x40, 0x50, 0x10, 0x02, +0x14, 0x50, 0x80, 0x00, 0x04, 0x00, 0x80, 0x00, 0x42, 0x50, 0x18, 0x09, 0x14, 0x50, 0x80, 0x00, +0x04, 0x51, 0x00, 0x00, 0x40, 0x42, 0x88, 0x09, 0x40, 0x42, 0x08, 0x08, 0x14, 0x41, 0x00, 0x00, +0x3e, 0x30, 0x02, 0x85, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, 0x04, 0x10, 0x00, 0x02, +0x00, 0x60, 0x80, 0x06, 0x50, 0x80, 0x80, 0x20, 0x4e, 0x62, 0x00, 0x0c, 0x04, 0x24, 0x00, 0x01, +0x04, 0x14, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x14, 0x20, 0x80, 0x00, 0x48, 0x00, 0x00, 0x42, +0x44, 0x00, 0x00, 0x14, 0x00, 0xa0, 0x80, 0x07, 0x49, 0xf7, 0xe9, 0xb0, 0x44, 0x50, 0x0f, 0xff, +0x58, 0x90, 0x00, 0x00, 0x4c, 0x02, 0xc0, 0x06, 0x44, 0x00, 0x01, 0x03, 0x48, 0x00, 0x00, 0x32, +0x49, 0xf7, 0xe9, 0x76, 0x58, 0x13, 0x00, 0x00, 0x44, 0x20, 0x00, 0x14, 0x58, 0x70, 0x00, 0x00, +0x49, 0xf7, 0xe3, 0xe4, 0x44, 0x30, 0x00, 0x14, 0x44, 0x2f, 0xe0, 0x00, 0x44, 0x10, 0x00, 0x06, +0x12, 0x33, 0x80, 0x00, 0x12, 0x23, 0x80, 0x01, 0x10, 0x13, 0x80, 0x04, 0x10, 0xa3, 0x80, 0x05, +0x50, 0x73, 0x80, 0x0c, 0x04, 0x54, 0x00, 0x00, 0x58, 0x24, 0x80, 0x00, 0x14, 0x53, 0x80, 0x00, +0x44, 0x10, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x58, 0x33, 0x00, 0x00, 0x04, 0x40, 0x00, 0x00, +0x58, 0x03, 0x00, 0x00, 0x14, 0x43, 0x80, 0x01, 0x49, 0xf7, 0xed, 0x7c, 0x58, 0x03, 0x00, 0x00, +0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, 0x2e, 0x50, 0x02, 0x85, +0x44, 0x90, 0x00, 0x01, 0x4c, 0x54, 0x80, 0x72, 0x46, 0x28, 0x00, 0x20, 0x04, 0x71, 0x00, 0x00, +0x47, 0xe8, 0x00, 0x21, 0x58, 0x83, 0x80, 0x03, 0x14, 0x81, 0x00, 0x00, 0x59, 0xef, 0x01, 0x00, +0x04, 0x0f, 0x00, 0x00, 0x46, 0x76, 0x04, 0x00, 0x58, 0x60, 0x00, 0x40, 0x14, 0x6f, 0x00, 0x00, +0x44, 0x80, 0x17, 0xc4, 0x04, 0x1f, 0x00, 0x00, 0x58, 0x50, 0x80, 0x60, 0x14, 0x5f, 0x00, 0x00, +0x58, 0x04, 0x80, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0x04, 0x43, 0x80, 0x02, 0x46, 0x66, 0x04, 0x00, +0x58, 0x32, 0x00, 0x10, 0x14, 0x33, 0x80, 0x02, 0x58, 0x63, 0x00, 0x04, 0x04, 0x23, 0x00, 0x00, +0x44, 0x00, 0x00, 0x0a, 0x40, 0x11, 0x24, 0x04, 0x14, 0x13, 0x00, 0x00, 0x46, 0x78, 0x00, 0x20, +0x04, 0x53, 0x00, 0x00, 0x58, 0x73, 0x80, 0xfc, 0x58, 0x42, 0x80, 0x02, 0x14, 0x43, 0x00, 0x00, +0x4b, 0xe0, 0x20, 0x01, 0x04, 0x33, 0x00, 0x00, 0x44, 0x00, 0x00, 0x04, 0x58, 0x21, 0x80, 0x10, +0x14, 0x23, 0x00, 0x00, 0x04, 0x13, 0x00, 0x00, 0x40, 0x50, 0x80, 0x04, 0x14, 0x53, 0x00, 0x00, +0x4b, 0xe0, 0x20, 0x01, 0x04, 0x43, 0x00, 0x00, 0x58, 0x32, 0x00, 0x08, 0x14, 0x33, 0x00, 0x00, +0x58, 0x04, 0x80, 0x00, 0x04, 0x23, 0x80, 0x00, 0x58, 0x11, 0x00, 0x0f, 0x14, 0x13, 0x80, 0x00, +0x04, 0x43, 0x80, 0x00, 0x40, 0x32, 0x10, 0x09, 0x40, 0x31, 0x90, 0x08, 0x14, 0x33, 0x80, 0x00, +0x4b, 0xe0, 0x20, 0x01, 0x04, 0x23, 0x80, 0x00, 0x58, 0x11, 0x00, 0x0f, 0x14, 0x13, 0x80, 0x00, +0x49, 0xff, 0xe2, 0x02, 0x3e, 0x90, 0x02, 0x85, 0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x3e, 0xaf, 0xb3, 0x40, 0x3e, 0x6f, 0xb0, 0x7c, +0x3e, 0x7f, 0xb4, 0x54, 0x3f, 0xce, 0xe0, 0x34, 0x04, 0x25, 0x00, 0x00, 0x44, 0x50, 0x00, 0x02, +0x3c, 0x2f, 0xec, 0xd1, 0x14, 0x05, 0x00, 0x00, 0x4c, 0x02, 0x80, 0x08, 0x44, 0x50, 0x00, 0x05, +0x4c, 0x02, 0xc0, 0x74, 0x48, 0x00, 0x00, 0x5a, 0x04, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, +0x44, 0x20, 0x00, 0xa4, 0x49, 0xf7, 0xe3, 0x1a, 0x00, 0x03, 0x80, 0x00, 0x3e, 0x9f, 0xb5, 0xdc, +0x49, 0xff, 0xf3, 0x08, 0x00, 0x03, 0x80, 0x00, 0x44, 0x80, 0x00, 0x00, 0x49, 0xff, 0xf2, 0xa4, +0x49, 0xff, 0xff, 0x54, 0x04, 0x03, 0x00, 0x00, 0x44, 0x30, 0x00, 0x01, 0x10, 0x30, 0x00, 0x9c, +0x44, 0x00, 0x00, 0x00, 0x04, 0x53, 0x00, 0x00, 0x10, 0x32, 0x80, 0x9e, 0x04, 0x43, 0x00, 0x00, +0x10, 0x32, 0x00, 0x9d, 0x04, 0x23, 0x00, 0x00, 0x10, 0x01, 0x00, 0x9f, 0x04, 0x13, 0x00, 0x00, +0x10, 0x30, 0x80, 0xa0, 0x04, 0x53, 0x00, 0x00, 0x10, 0x02, 0x80, 0xa1, 0x49, 0xff, 0xf3, 0xe6, +0x49, 0xff, 0xf2, 0xec, 0x44, 0x00, 0x00, 0x01, 0x49, 0x00, 0x21, 0xf4, 0x49, 0xff, 0xf8, 0x94, +0x49, 0xff, 0xfd, 0xfc, 0x49, 0xff, 0xd6, 0xd2, 0x49, 0xff, 0xfe, 0x52, 0x49, 0x00, 0x0f, 0xde, +0x58, 0x04, 0x80, 0x00, 0x4b, 0xe0, 0x70, 0x01, 0x50, 0x14, 0x00, 0x01, 0x10, 0x84, 0x80, 0x2f, +0x44, 0x30, 0x00, 0x04, 0x54, 0x80, 0x80, 0xff, 0x50, 0x94, 0x80, 0x30, 0x4c, 0x81, 0xff, 0xf2, +0x44, 0x00, 0x00, 0x05, 0x48, 0x00, 0x00, 0x1a, 0x01, 0xe3, 0x80, 0x00, 0x4f, 0xe2, 0x00, 0x16, +0x3c, 0x5d, 0xed, 0x16, 0x44, 0x20, 0x00, 0x00, 0x50, 0x42, 0xff, 0xff, 0x10, 0x23, 0x80, 0x00, +0x5c, 0xf2, 0x00, 0x03, 0x4e, 0xf3, 0x00, 0x04, 0x48, 0x00, 0x00, 0x06, 0x44, 0x30, 0x00, 0x00, +0x3c, 0x3f, 0xed, 0x16, 0x44, 0x00, 0x00, 0x04, 0x04, 0x55, 0x00, 0x00, 0x4c, 0x02, 0xff, 0x7e, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x04, 0x70, 0x00, 0x02, 0x58, 0x60, 0x00, 0x00, 0x50, 0x13, 0x80, 0x20, +0x00, 0x20, 0x80, 0x00, 0x4e, 0x23, 0x00, 0x36, 0x05, 0xe0, 0x80, 0x01, 0x40, 0x51, 0x78, 0x06, +0x3e, 0x57, 0xb4, 0x54, 0x04, 0x00, 0x80, 0x01, 0x44, 0x20, 0x00, 0x03, 0x3c, 0x0f, 0xed, 0x16, +0x4c, 0x01, 0x40, 0x06, 0x00, 0x10, 0x80, 0x01, 0x3e, 0x17, 0xb4, 0x5c, 0x3c, 0x0d, 0xec, 0xd0, +0x44, 0x50, 0x00, 0x04, 0x4c, 0x02, 0xc0, 0x0a, 0x44, 0x10, 0x00, 0x6a, 0x44, 0x20, 0x00, 0x00, +0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x05, 0x4c, 0x02, 0xc0, 0x0a, +0x44, 0x00, 0x00, 0x01, 0x44, 0x10, 0x00, 0x6a, 0x44, 0x20, 0x00, 0x00, 0x49, 0xf8, 0x07, 0x82, +0x44, 0x00, 0x00, 0x03, 0x49, 0xff, 0xff, 0x2e, 0x44, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x12, +0x3c, 0x5d, 0xec, 0xd0, 0x45, 0xe0, 0x00, 0x04, 0x4c, 0x5f, 0x00, 0x08, 0x46, 0x1c, 0x00, 0x00, +0x58, 0x10, 0x80, 0x01, 0x48, 0x00, 0x00, 0x06, 0x49, 0x00, 0x18, 0xc2, 0x58, 0x10, 0x00, 0x00, +0x00, 0x23, 0x80, 0x0b, 0x54, 0x01, 0x00, 0x01, 0x4e, 0x02, 0x00, 0x08, 0x58, 0x03, 0x00, 0x00, +0x49, 0x00, 0x02, 0x12, 0x58, 0x10, 0x00, 0x00, 0x58, 0x00, 0x80, 0x00, 0x51, 0xff, 0x80, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x3c, 0x2d, 0xec, 0xd0, 0x4e, 0x23, 0x00, 0x0c, 0x44, 0x00, 0x00, 0x01, 0x44, 0x10, 0x00, 0x6a, +0x49, 0xf8, 0x07, 0x48, 0x44, 0x00, 0x00, 0x03, 0x49, 0xff, 0xfe, 0xf4, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x49, 0x00, 0x0f, 0x84, 0x49, 0x00, 0x20, 0xfa, 0x49, 0x00, 0x0f, 0x32, 0x49, 0xff, 0xfd, 0xbc, +0x44, 0x00, 0x00, 0x00, 0x49, 0xff, 0xfe, 0xde, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x44, 0x10, 0x00, 0x00, +0x44, 0x50, 0x00, 0x00, 0x3e, 0x57, 0xb4, 0x54, 0x3c, 0x1f, 0xec, 0xd1, 0x3c, 0x1f, 0xec, 0xd0, +0x44, 0x00, 0x00, 0x02, 0x49, 0xff, 0xfe, 0xc6, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x51, 0xff, 0xff, 0xf8, 0x44, 0x60, 0x00, 0x00, +0x50, 0x0f, 0x80, 0x04, 0x14, 0x6f, 0x80, 0x01, 0x49, 0xf7, 0xd6, 0xd2, 0x46, 0x00, 0x20, 0x00, +0x14, 0x60, 0x00, 0x00, 0x44, 0x20, 0x2d, 0x0c, 0x04, 0x0f, 0x80, 0x01, 0x3c, 0x2f, 0xff, 0xb9, +0x49, 0xf7, 0xd6, 0xd2, 0x51, 0xff, 0x80, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xa0, 0xbc, 0x58, 0x60, 0x00, 0x00, 0x49, 0xff, 0xff, 0xb0, 0x44, 0x00, 0x00, 0x0c, +0x04, 0x83, 0x00, 0x02, 0x49, 0xf7, 0xe7, 0x8a, 0x44, 0x50, 0x0f, 0xff, 0x58, 0x70, 0x00, 0x00, +0x4c, 0x02, 0xc0, 0x0a, 0x3e, 0x0f, 0x9c, 0x8c, 0x49, 0xff, 0xd3, 0x18, 0x44, 0x00, 0x01, 0x03, +0x48, 0x00, 0x00, 0x2e, 0x49, 0xf7, 0xe7, 0x4c, 0x44, 0x50, 0x00, 0x0c, 0x44, 0x4f, 0xe0, 0x00, +0x44, 0x3f, 0xff, 0xef, 0x12, 0x50, 0x00, 0x00, 0x12, 0x40, 0x00, 0x01, 0x10, 0x30, 0x00, 0x04, +0x50, 0x20, 0x00, 0x08, 0x00, 0x84, 0x00, 0x07, 0x44, 0x60, 0x00, 0x00, 0x10, 0x80, 0x00, 0x05, +0x10, 0x61, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x58, 0x23, 0x80, 0x00, 0x58, 0x10, 0x00, 0x00, +0x44, 0x30, 0x00, 0x01, 0x49, 0xf7, 0xeb, 0x5e, 0x44, 0x00, 0x00, 0x00, 0x49, 0x00, 0x21, 0x36, +0x3e, 0x67, 0xb4, 0x60, 0x49, 0xff, 0xff, 0xa0, 0x44, 0x00, 0x00, 0x00, 0x3a, 0x6f, 0xa0, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x04, 0x10, 0x00, 0x02, 0x58, 0x60, 0x00, 0x00, +0x00, 0x20, 0x80, 0x04, 0x3e, 0x0f, 0x9c, 0xb0, 0x44, 0x80, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, +0x50, 0x34, 0x00, 0x01, 0x4c, 0x51, 0x40, 0x1e, 0x04, 0x10, 0x00, 0x01, 0x4e, 0x12, 0x00, 0x1a, +0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x04, 0x01, 0x58, 0x70, 0x00, 0x00, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x72, 0x80, 0x1c, 0x46, 0x2c, 0x00, 0x00, 0x58, 0x51, 0x00, 0x9a, 0x4c, 0x72, 0x80, 0x16, +0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x49, 0xff, 0xf2, 0x88, 0x48, 0x00, 0x00, 0x0e, +0x54, 0x81, 0x80, 0xff, 0x44, 0x50, 0x00, 0x04, 0x50, 0x00, 0x00, 0x08, 0x4c, 0x82, 0xff, 0xd8, +0x44, 0x70, 0x00, 0x00, 0x48, 0x00, 0x00, 0x06, 0x5c, 0xf4, 0x00, 0x04, 0x4e, 0xf3, 0x00, 0x08, +0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x49, 0xff, 0xf2, 0x70, 0x58, 0x03, 0x80, 0x00, +0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x10, 0x30, 0x00, 0x08, 0x12, 0x10, 0x00, 0x00, +0x44, 0x3f, 0xe0, 0x00, 0x44, 0x1f, 0xff, 0xed, 0x12, 0x30, 0x00, 0x01, 0x10, 0x10, 0x00, 0x04, +0x10, 0x20, 0x00, 0x05, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x51, 0xff, 0xff, 0xf8, +0x10, 0x0f, 0x80, 0x04, 0x44, 0x00, 0x00, 0x0d, 0x49, 0xf7, 0xe6, 0xe8, 0x44, 0x50, 0x0f, 0xff, +0x58, 0x60, 0x00, 0x00, 0x4c, 0x02, 0xc0, 0x06, 0x44, 0x00, 0x01, 0x03, 0x48, 0x00, 0x00, 0x2c, +0x49, 0xf7, 0xe6, 0xae, 0x44, 0x5f, 0xe0, 0x00, 0x44, 0x4f, 0xff, 0xed, 0x44, 0x30, 0x00, 0x00, +0x44, 0x10, 0x00, 0x10, 0x44, 0x20, 0x00, 0x31, 0x12, 0x10, 0x00, 0x00, 0x12, 0x50, 0x00, 0x01, +0x10, 0x40, 0x00, 0x04, 0x10, 0x30, 0x00, 0x05, 0x10, 0x20, 0x00, 0x08, 0x50, 0x1f, 0x80, 0x04, +0x44, 0x20, 0x00, 0x01, 0x50, 0x00, 0x00, 0x0c, 0x49, 0xf7, 0xe0, 0xf4, 0x44, 0x00, 0x00, 0x00, +0x58, 0x23, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x58, 0x30, 0x00, 0x00, 0x49, 0xf7, 0xea, 0xba, +0x44, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x54, 0x90, 0x00, 0xff, 0x44, 0x00, 0x00, 0x10, +0x40, 0x80, 0x80, 0x10, 0x49, 0xf7, 0xe6, 0xa2, 0x44, 0x50, 0x0f, 0xff, 0x58, 0x70, 0x00, 0x00, +0x4c, 0x02, 0xc0, 0x06, 0x44, 0x00, 0x01, 0x03, 0x48, 0x00, 0x00, 0x40, 0x49, 0xf7, 0xe6, 0x68, +0x58, 0x60, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x10, 0x49, 0xf7, 0xe0, 0xd6, +0x50, 0x33, 0x00, 0x0c, 0x4e, 0x92, 0x00, 0x06, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x04, +0x44, 0x00, 0x00, 0x01, 0x10, 0x01, 0x80, 0x00, 0x10, 0x81, 0x80, 0x01, 0x2e, 0x07, 0xb4, 0x5f, +0x44, 0x50, 0x00, 0x22, 0x50, 0x10, 0x00, 0x01, 0x54, 0x00, 0x80, 0xff, 0x44, 0x40, 0x00, 0x10, +0x44, 0x3f, 0xe0, 0x00, 0x44, 0x2f, 0xff, 0xed, 0x3e, 0x07, 0xb4, 0x5f, 0x12, 0x33, 0x00, 0x01, +0x10, 0x23, 0x00, 0x04, 0x10, 0x03, 0x00, 0x05, 0x10, 0x53, 0x00, 0x08, 0x44, 0x00, 0x00, 0x00, +0x12, 0x43, 0x00, 0x00, 0x58, 0x23, 0x80, 0x00, 0x44, 0x10, 0x00, 0x01, 0x58, 0x30, 0x00, 0x00, +0x49, 0xf7, 0xea, 0x60, 0x44, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xa4, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, 0x50, 0x20, 0x80, 0x0c, 0x58, 0xa0, 0x00, 0x00, +0x40, 0x01, 0x00, 0x13, 0x58, 0x70, 0x80, 0x00, 0x49, 0xf7, 0xe6, 0x48, 0x44, 0x50, 0x0f, 0xff, +0x58, 0x80, 0x00, 0x00, 0x4c, 0x02, 0xc0, 0x06, 0x44, 0x00, 0x01, 0x03, 0x48, 0x00, 0x00, 0x48, +0x49, 0xf7, 0xe6, 0x0e, 0x58, 0x60, 0x00, 0x00, 0x54, 0x03, 0x80, 0x03, 0x4e, 0x02, 0x00, 0x08, +0x40, 0x73, 0x88, 0x09, 0x40, 0x73, 0x88, 0x08, 0x50, 0x73, 0x80, 0x04, 0x50, 0x93, 0x80, 0x0c, +0x44, 0x10, 0x00, 0x00, 0x58, 0x24, 0x80, 0x00, 0x58, 0x03, 0x00, 0x00, 0x49, 0xf7, 0xe0, 0x6e, +0x58, 0x23, 0x80, 0x00, 0x58, 0x15, 0x00, 0x00, 0x3e, 0x7f, 0xb4, 0x5e, 0x50, 0x03, 0x00, 0x0c, +0x49, 0xf7, 0xe0, 0x50, 0x00, 0x23, 0x80, 0x00, 0x44, 0x30, 0x00, 0x13, 0x44, 0x0f, 0xe0, 0x00, +0x44, 0x1f, 0xff, 0xed, 0x10, 0x33, 0x00, 0x08, 0x12, 0x03, 0x00, 0x01, 0x10, 0x13, 0x00, 0x04, +0x10, 0x23, 0x00, 0x05, 0x44, 0x00, 0x00, 0x00, 0x12, 0x93, 0x00, 0x00, 0x58, 0x24, 0x00, 0x00, +0x44, 0x10, 0x00, 0x01, 0x58, 0x30, 0x00, 0x00, 0x49, 0xf7, 0xea, 0x04, 0x00, 0x53, 0x80, 0x00, +0x44, 0x00, 0x00, 0x00, 0x50, 0x42, 0x80, 0x01, 0x10, 0x43, 0x80, 0x00, 0x3a, 0x6f, 0xa8, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, 0x04, 0x80, 0x00, 0x02, 0x44, 0x00, 0x00, 0x14, +0x58, 0x90, 0x80, 0x00, 0x00, 0xa4, 0x00, 0x07, 0x49, 0xf7, 0xe5, 0xe8, 0x44, 0x50, 0x0f, 0xff, +0x58, 0x70, 0x00, 0x00, 0x4c, 0x02, 0xc0, 0x06, 0x44, 0x00, 0x01, 0x03, 0x48, 0x00, 0x00, 0x32, +0x49, 0xf7, 0xe5, 0xae, 0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x14, 0x58, 0x60, 0x00, 0x00, +0x49, 0xf7, 0xe0, 0x1c, 0x44, 0x40, 0x00, 0x14, 0x44, 0x3f, 0xe0, 0x00, 0x44, 0x2f, 0xff, 0xed, +0x44, 0x00, 0x00, 0x00, 0x10, 0x23, 0x00, 0x04, 0x12, 0x43, 0x00, 0x00, 0x12, 0x33, 0x00, 0x01, +0x10, 0xa3, 0x00, 0x05, 0x10, 0x03, 0x00, 0x08, 0x50, 0x63, 0x00, 0x0c, 0x00, 0x84, 0x00, 0x09, +0x44, 0x00, 0x00, 0x00, 0x10, 0x83, 0x00, 0x00, 0x14, 0x93, 0x00, 0x01, 0x58, 0x23, 0x80, 0x00, +0x44, 0x10, 0x00, 0x01, 0x58, 0x30, 0x00, 0x00, 0x49, 0xf7, 0xe9, 0xb4, 0x44, 0x00, 0x00, 0x00, +0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x04, 0x20, 0x00, 0x02, +0x50, 0x61, 0x00, 0x20, 0x04, 0x33, 0x00, 0x00, 0x04, 0x43, 0x00, 0x01, 0x04, 0x53, 0x00, 0x02, +0x04, 0x61, 0x80, 0x00, 0x41, 0xe2, 0x10, 0x05, 0x40, 0x13, 0x78, 0x02, 0x41, 0xe2, 0x14, 0x02, +0x40, 0x40, 0xf8, 0x04, 0x14, 0x41, 0x80, 0x00, 0x00, 0x11, 0x00, 0x0b, 0x54, 0x10, 0x80, 0x01, +0x4e, 0x13, 0x00, 0x06, 0x58, 0x00, 0x80, 0x00, 0x48, 0x00, 0x00, 0x06, 0x44, 0x10, 0x00, 0x00, +0x49, 0xff, 0xff, 0x92, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x04, 0x70, 0x00, 0x02, 0x58, 0x60, 0x00, 0x00, 0x50, 0x23, 0x80, 0x20, +0x00, 0x01, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x06, 0x00, 0x11, 0x00, 0x01, 0x4e, 0x12, 0x00, 0x04, +0x00, 0x01, 0x00, 0x01, 0x00, 0x11, 0x00, 0x02, 0x3e, 0x3f, 0xb3, 0x60, 0x41, 0xe0, 0x08, 0x08, +0x40, 0x4f, 0x0c, 0x00, 0x10, 0x12, 0x00, 0x00, 0x02, 0x51, 0x00, 0x02, 0x44, 0x20, 0x00, 0x01, +0x12, 0x52, 0x00, 0x01, 0x4c, 0x11, 0x40, 0x04, 0x48, 0x00, 0x00, 0x04, 0x44, 0x10, 0x00, 0x00, +0x49, 0xff, 0xeb, 0xf8, 0x00, 0x13, 0x80, 0x0b, 0x54, 0x00, 0x80, 0x01, 0x4e, 0x02, 0x00, 0x08, +0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x49, 0xff, 0xff, 0x56, 0x44, 0x00, 0x00, 0x00, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x04, 0x80, 0x00, 0x02, 0x3e, 0x3f, 0xb5, 0xdc, 0x50, 0x54, 0x00, 0x20, +0x00, 0x42, 0x80, 0x00, 0x58, 0x70, 0x00, 0x00, 0x10, 0x41, 0x80, 0x2c, 0x00, 0x12, 0x80, 0x04, +0x10, 0x11, 0x80, 0x5c, 0x00, 0x02, 0x80, 0x08, 0x10, 0x01, 0x80, 0x8c, 0x01, 0xe2, 0x80, 0x0c, +0x11, 0xe1, 0x80, 0xbc, 0x00, 0x92, 0x80, 0x04, 0x00, 0x62, 0x80, 0x00, 0x00, 0x22, 0x80, 0x08, +0x00, 0x12, 0x80, 0x0c, 0x40, 0x44, 0x98, 0x00, 0x40, 0x32, 0x08, 0x00, 0x40, 0x01, 0x84, 0x00, +0x3e, 0x1e, 0xa5, 0xa0, 0x4e, 0x03, 0x00, 0x06, 0x46, 0x00, 0x02, 0x10, 0x48, 0x00, 0x00, 0x06, +0x46, 0x00, 0x02, 0x10, 0x58, 0x00, 0x00, 0x04, 0x4b, 0xe0, 0x04, 0x01, 0x3e, 0x6f, 0xb5, 0xdc, +0x00, 0x23, 0x00, 0x2c, 0x4e, 0x23, 0x00, 0x06, 0x58, 0x03, 0x00, 0x00, 0x49, 0xff, 0xf5, 0x80, +0x50, 0x63, 0x00, 0x30, 0x3e, 0x5f, 0xb6, 0x9c, 0x4c, 0x62, 0xff, 0xf4, 0x00, 0x34, 0x00, 0x0b, +0x55, 0xe1, 0x80, 0x01, 0x4f, 0xe2, 0x00, 0x08, 0x58, 0x03, 0x80, 0x00, 0x44, 0x10, 0x00, 0x00, +0x49, 0xff, 0xfe, 0xfa, 0x44, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xa4, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x04, 0x30, 0x00, 0x02, +0x44, 0x40, 0x00, 0x01, 0x50, 0x11, 0x80, 0x20, 0x00, 0x50, 0x80, 0x00, 0x4c, 0x52, 0x00, 0x06, +0x44, 0x11, 0x00, 0x03, 0x48, 0x00, 0x00, 0x16, 0x00, 0x10, 0x80, 0x01, 0x3e, 0x2f, 0xb0, 0xd8, +0x4e, 0x12, 0x00, 0x0a, 0x01, 0xe1, 0x00, 0x45, 0x44, 0x10, 0x00, 0x00, 0x42, 0x4f, 0x18, 0x09, +0x48, 0x00, 0x00, 0x06, 0x00, 0x41, 0x00, 0x45, 0x58, 0x42, 0x00, 0x40, 0x10, 0x41, 0x00, 0x45, +0x00, 0x21, 0x80, 0x0b, 0x54, 0x31, 0x00, 0x01, 0x4e, 0x32, 0x00, 0x06, 0x49, 0xff, 0xfe, 0xc4, +0x58, 0x10, 0x00, 0x00, 0x58, 0x00, 0x80, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x04, 0x90, 0x00, 0x02, +0x58, 0x80, 0x00, 0x00, 0x50, 0x74, 0x80, 0x20, 0x49, 0x00, 0x36, 0xea, 0x00, 0x13, 0x80, 0x00, +0x3e, 0x6e, 0xab, 0xc0, 0x44, 0x00, 0x00, 0x00, 0x4b, 0xe0, 0x18, 0x01, 0x00, 0x13, 0x80, 0x01, +0x44, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x18, 0x01, 0x00, 0x13, 0x80, 0x02, 0x44, 0x00, 0x00, 0x02, +0x4b, 0xe0, 0x18, 0x01, 0x02, 0x13, 0x80, 0x02, 0x44, 0x00, 0x00, 0x03, 0x4b, 0xe0, 0x18, 0x01, +0x49, 0x00, 0x36, 0x82, 0x00, 0x04, 0x80, 0x0b, 0x54, 0x00, 0x00, 0x01, 0x4e, 0x02, 0x00, 0x08, +0x58, 0x04, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x49, 0xff, 0xfe, 0x86, 0x51, 0xff, 0x80, 0x04, +0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x04, 0x70, 0x00, 0x02, 0x58, 0x90, 0x00, 0x00, 0x50, 0xa3, 0x80, 0x20, 0x00, 0x55, 0x00, 0x00, +0x02, 0x33, 0x80, 0x00, 0x40, 0x42, 0x94, 0x00, 0x50, 0x22, 0x00, 0x01, 0x50, 0x11, 0xff, 0xe0, +0x40, 0x01, 0x08, 0x08, 0x4c, 0x10, 0x00, 0x08, 0x46, 0x1c, 0x00, 0x10, 0x58, 0x10, 0x80, 0x14, +0x48, 0x00, 0x00, 0x4a, 0x50, 0x63, 0x80, 0x24, 0x49, 0x00, 0x36, 0x9a, 0x44, 0x80, 0x00, 0x00, +0x3f, 0xce, 0xab, 0x4c, 0x48, 0x00, 0x00, 0x36, 0x00, 0x03, 0x00, 0x01, 0x50, 0x84, 0x00, 0x01, +0x55, 0xe0, 0x00, 0x01, 0x4f, 0xe2, 0x00, 0x08, 0x00, 0x13, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, +0x49, 0xff, 0xd9, 0xde, 0x00, 0x23, 0x00, 0x01, 0x54, 0x11, 0x00, 0x02, 0x4e, 0x12, 0x00, 0x08, +0x00, 0x13, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x49, 0xff, 0xda, 0x1a, 0x00, 0x43, 0x00, 0x01, +0x54, 0x32, 0x00, 0x04, 0x4e, 0x32, 0x00, 0x08, 0x02, 0x13, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, +0x49, 0xff, 0xda, 0x86, 0x01, 0xe3, 0x00, 0x01, 0x54, 0x5f, 0x00, 0x08, 0x4e, 0x52, 0x00, 0x08, +0x00, 0x03, 0x00, 0x00, 0x02, 0x13, 0x00, 0x03, 0x4b, 0xe0, 0x70, 0x01, 0x50, 0x63, 0x00, 0x08, +0x00, 0x05, 0x00, 0x00, 0x40, 0xf4, 0x00, 0x06, 0x4e, 0xf3, 0xff, 0xc8, 0x49, 0x00, 0x36, 0x0c, +0x44, 0x10, 0x00, 0x00, 0x00, 0x33, 0x80, 0x0b, 0x54, 0x21, 0x80, 0x01, 0x4e, 0x22, 0x00, 0x08, +0x58, 0x04, 0x80, 0x00, 0x49, 0xff, 0xfe, 0x10, 0x58, 0x10, 0x00, 0x00, 0x58, 0x00, 0x80, 0x00, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x04, 0x20, 0x00, 0x02, 0x00, 0x11, 0x00, 0x20, 0x5c, 0xf0, 0x80, 0x03, +0x4e, 0xf3, 0x00, 0x06, 0x44, 0x11, 0x00, 0x03, 0x48, 0x00, 0x00, 0x06, 0x3e, 0x17, 0xb0, 0x80, +0x44, 0x10, 0x00, 0x00, 0x00, 0x41, 0x00, 0x0b, 0x54, 0x22, 0x00, 0x01, 0x4e, 0x22, 0x00, 0x06, +0x49, 0xff, 0xfd, 0xea, 0x58, 0x10, 0x00, 0x00, 0x58, 0x00, 0x80, 0x00, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0x74, +0x50, 0x2f, 0x80, 0x68, 0x10, 0x11, 0x00, 0x07, 0x10, 0x01, 0x00, 0x09, 0x44, 0x10, 0x00, 0x00, +0x58, 0x0f, 0x80, 0x00, 0x14, 0x2f, 0x80, 0x02, 0x49, 0xff, 0xfd, 0xce, 0x51, 0xff, 0x80, 0x8c, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x04, 0x70, 0x00, 0x02, 0x58, 0x60, 0x00, 0x00, 0x50, 0x23, 0x80, 0x20, 0x00, 0x31, 0x00, 0x00, +0x3e, 0x1f, 0xb1, 0xa0, 0x4e, 0x32, 0x00, 0x2c, 0x44, 0x00, 0x00, 0x01, 0x44, 0x40, 0x00, 0x00, +0x10, 0x00, 0x80, 0x26, 0x10, 0x40, 0x80, 0x25, 0x2f, 0xef, 0xb3, 0x5a, 0x20, 0x31, 0x00, 0x01, +0x40, 0x51, 0xf8, 0x01, 0x50, 0x42, 0x00, 0x1e, 0x2f, 0xef, 0xb3, 0x5b, 0x42, 0x32, 0x90, 0x24, +0x50, 0x4f, 0x00, 0x38, 0x41, 0xe1, 0x90, 0x16, 0x2e, 0x57, 0xb3, 0x59, 0x2e, 0x4f, 0xc4, 0x3a, +0x40, 0x3f, 0x14, 0x00, 0x40, 0x31, 0x80, 0x10, 0x10, 0x30, 0x80, 0x28, 0x40, 0xf1, 0x90, 0x07, +0x4e, 0xf2, 0x00, 0x0a, 0x3e, 0x37, 0xc4, 0x3a, 0x48, 0x00, 0x00, 0x06, 0x10, 0x30, 0x80, 0x25, +0x10, 0x30, 0x80, 0x26, 0x00, 0x31, 0x00, 0x02, 0x4e, 0x32, 0x00, 0x2c, 0x44, 0x30, 0x00, 0x00, +0x44, 0x50, 0x00, 0x01, 0x10, 0x30, 0x80, 0x32, 0x10, 0x50, 0x80, 0x31, 0x2e, 0x0f, 0xb3, 0x5a, +0x20, 0x21, 0x00, 0x03, 0x2f, 0xef, 0xb3, 0x5b, 0x40, 0x51, 0x00, 0x01, 0x50, 0x31, 0x80, 0x1e, +0x42, 0x22, 0x8c, 0x24, 0x50, 0x0f, 0x00, 0x38, 0x41, 0xe1, 0x00, 0x16, 0x2e, 0x57, 0xb3, 0x59, +0x2e, 0x3f, 0xc4, 0x39, 0x40, 0x2f, 0x14, 0x00, 0x40, 0x21, 0x00, 0x10, 0x10, 0x20, 0x80, 0x33, +0x40, 0xf1, 0x88, 0x07, 0x4e, 0xf2, 0x00, 0x0a, 0x3e, 0x27, 0xc4, 0x39, 0x48, 0x00, 0x00, 0x06, +0x10, 0x30, 0x80, 0x31, 0x10, 0x30, 0x80, 0x32, 0x2e, 0x37, 0xc4, 0x39, 0x2e, 0x27, 0xc4, 0x3a, +0x44, 0x10, 0x00, 0x7f, 0x44, 0x40, 0x00, 0x1e, 0x44, 0x00, 0x00, 0x02, 0x49, 0xff, 0xe8, 0x12, +0x46, 0x48, 0x00, 0x22, 0x04, 0x52, 0x00, 0x07, 0x46, 0x30, 0x11, 0x10, 0x40, 0x22, 0x8c, 0x04, +0x14, 0x22, 0x00, 0x07, 0x44, 0x00, 0x00, 0x01, 0x49, 0xf7, 0xd4, 0xb0, 0x44, 0x00, 0x00, 0x01, +0x49, 0xf7, 0xd4, 0x84, 0x00, 0x13, 0x80, 0x0b, 0x54, 0x00, 0x80, 0x01, 0x4e, 0x02, 0x00, 0x08, +0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x49, 0xff, 0xfd, 0x2e, 0x51, 0xff, 0x80, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0x44, +0x3e, 0x1f, 0x9d, 0xf0, 0x58, 0x70, 0x00, 0x00, 0x44, 0x20, 0x00, 0xb6, 0x58, 0x0f, 0x80, 0x00, +0x49, 0xf7, 0xdd, 0x40, 0x2e, 0x17, 0xb4, 0x60, 0x58, 0x6f, 0x80, 0x00, 0x04, 0x83, 0x80, 0x02, +0x4e, 0x12, 0x00, 0x04, 0x48, 0x00, 0x00, 0xa8, 0x50, 0x24, 0x00, 0x20, 0x00, 0x31, 0x00, 0x00, +0x4e, 0x32, 0x00, 0x06, 0x58, 0x0f, 0x80, 0x00, 0x48, 0x00, 0x00, 0xb0, 0x44, 0x60, 0x6f, 0x4c, +0x3e, 0x1f, 0xb0, 0xd8, 0x44, 0x20, 0x00, 0x03, 0x44, 0x00, 0x00, 0x35, 0x4b, 0xe0, 0x18, 0x01, +0x3e, 0x1f, 0xb0, 0xdb, 0x44, 0x20, 0x00, 0x01, 0x44, 0x00, 0x00, 0x48, 0x4b, 0xe0, 0x18, 0x01, +0x3e, 0x1f, 0xb0, 0xdc, 0x44, 0x20, 0x00, 0x01, 0x44, 0x00, 0x00, 0x50, 0x4b, 0xe0, 0x18, 0x01, +0x3e, 0x1f, 0xb0, 0xdd, 0x44, 0x20, 0x00, 0x0f, 0x44, 0x00, 0x00, 0x53, 0x4b, 0xe0, 0x18, 0x01, +0x3e, 0x1f, 0xb0, 0xec, 0x44, 0x20, 0x00, 0x0e, 0x44, 0x00, 0x00, 0xa0, 0x4b, 0xe0, 0x18, 0x01, +0x3e, 0x1f, 0xb0, 0xfa, 0x44, 0x20, 0x00, 0x10, 0x44, 0x00, 0x00, 0xc0, 0x4b, 0xe0, 0x18, 0x01, +0x3e, 0x1f, 0xb1, 0x0a, 0x44, 0x20, 0x00, 0x07, 0x44, 0x00, 0x00, 0xd0, 0x4b, 0xe0, 0x18, 0x01, +0x3e, 0x1f, 0xb1, 0x11, 0x44, 0x20, 0x00, 0x04, 0x44, 0x00, 0x00, 0xf4, 0x4b, 0xe0, 0x18, 0x01, +0x3e, 0x1f, 0xb1, 0x15, 0x44, 0x20, 0x00, 0x02, 0x44, 0x00, 0x00, 0x24, 0x4b, 0xe0, 0x18, 0x01, +0x3e, 0x1f, 0xb1, 0x17, 0x44, 0x20, 0x00, 0x01, 0x44, 0x00, 0x00, 0x34, 0x4b, 0xe0, 0x18, 0x01, +0x3e, 0x1f, 0xb1, 0x18, 0x44, 0x20, 0x00, 0x01, 0x44, 0x00, 0x00, 0x39, 0x4b, 0xe0, 0x18, 0x01, +0x3e, 0x1f, 0xb1, 0x19, 0x44, 0x20, 0x00, 0x01, 0x44, 0x00, 0x00, 0x3b, 0x4b, 0xe0, 0x18, 0x01, +0x3e, 0x1f, 0xb1, 0x1a, 0x44, 0x20, 0x00, 0x02, 0x44, 0x00, 0x00, 0x42, 0x4b, 0xe0, 0x18, 0x01, +0x3e, 0x1f, 0xb1, 0x1c, 0x44, 0x20, 0x00, 0x02, 0x44, 0x00, 0x00, 0x9e, 0x4b, 0xe0, 0x18, 0x01, +0x3e, 0x1f, 0xb1, 0x1e, 0x44, 0x20, 0x00, 0x01, 0x44, 0x00, 0x00, 0xf2, 0x4b, 0xe0, 0x18, 0x01, +0x3e, 0x1f, 0xb1, 0x1f, 0x44, 0x20, 0x00, 0x03, 0x44, 0x00, 0x00, 0xf8, 0x4b, 0xe0, 0x18, 0x01, +0x3e, 0x1f, 0xb1, 0x22, 0x44, 0x20, 0x00, 0x01, 0x44, 0x00, 0x01, 0x2e, 0x4b, 0xe0, 0x18, 0x01, +0x3e, 0x1f, 0xb1, 0x23, 0x44, 0x20, 0x00, 0x10, 0x44, 0x00, 0x01, 0x30, 0x4b, 0xe0, 0x18, 0x01, +0x48, 0x00, 0x00, 0x42, 0x38, 0x90, 0x05, 0x01, 0x02, 0x41, 0x80, 0x02, 0x54, 0x13, 0x00, 0xff, +0x4c, 0x92, 0x00, 0x10, 0x00, 0x24, 0x00, 0x0b, 0x54, 0x11, 0x00, 0x01, 0x4e, 0x12, 0x00, 0x7a, +0x58, 0x03, 0x80, 0x00, 0x44, 0x11, 0x00, 0x03, 0x49, 0xff, 0xfc, 0x5e, 0x48, 0x00, 0x00, 0x72, +0x00, 0x61, 0x80, 0x06, 0x10, 0x62, 0x80, 0x00, 0x01, 0xe1, 0x00, 0x01, 0x40, 0x50, 0x88, 0x08, +0x3e, 0x9f, 0xb0, 0xd8, 0x40, 0x31, 0x14, 0x00, 0x50, 0x60, 0x80, 0x01, 0x40, 0x50, 0xa4, 0x00, +0x40, 0xf0, 0xf8, 0x06, 0x4e, 0xf3, 0xff, 0xd8, 0x58, 0x04, 0x80, 0x00, 0x00, 0x94, 0x80, 0x44, +0x44, 0x30, 0x00, 0xff, 0x4c, 0x91, 0xc0, 0x06, 0x44, 0x40, 0x00, 0x00, 0x10, 0x40, 0x00, 0x44, +0x2e, 0x17, 0xb1, 0x1d, 0x58, 0x21, 0x80, 0x00, 0x4c, 0x11, 0x40, 0x06, 0x45, 0xe0, 0x00, 0x00, +0x3f, 0xe7, 0xb1, 0x1d, 0x3e, 0x3f, 0xb0, 0xd8, 0x00, 0x91, 0x80, 0x31, 0x00, 0x01, 0x80, 0x2f, +0x50, 0x11, 0x80, 0x28, 0x40, 0x54, 0x80, 0x01, 0x54, 0x22, 0x80, 0xff, 0x00, 0x00, 0x80, 0x00, +0x44, 0x50, 0x00, 0x7f, 0x4c, 0x02, 0x80, 0x08, 0x40, 0x31, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x04, +0x10, 0x30, 0x80, 0x00, 0x50, 0x10, 0x80, 0x01, 0x3e, 0x5f, 0xb1, 0x08, 0x4c, 0x12, 0xff, 0xf0, +0x50, 0x10, 0x80, 0x02, 0x00, 0x00, 0x80, 0x00, 0x44, 0x50, 0x00, 0x7f, 0x4c, 0x02, 0x80, 0x08, +0x40, 0x31, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x04, 0x10, 0x30, 0x80, 0x00, 0x50, 0x10, 0x80, 0x01, +0x3e, 0x5f, 0xb1, 0x11, 0x4c, 0x12, 0xff, 0xf0, 0x49, 0x00, 0x12, 0x3e, 0x44, 0x00, 0x00, 0x01, +0x3e, 0x07, 0xb4, 0x60, 0x00, 0x14, 0x00, 0x0b, 0x54, 0x00, 0x80, 0x01, 0x4e, 0x02, 0x00, 0x0c, +0x58, 0x03, 0x80, 0x00, 0x44, 0x10, 0x00, 0x00, 0x49, 0xff, 0xfb, 0xee, 0x48, 0x00, 0x00, 0x04, +0x44, 0x01, 0x00, 0x03, 0x51, 0xff, 0x80, 0xbc, 0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x04, 0x10, 0x00, 0x02, 0x00, 0x60, 0x80, 0x20, +0x40, 0x03, 0x00, 0x10, 0x4e, 0x05, 0x00, 0x1a, 0x58, 0x03, 0x00, 0x00, 0x49, 0xff, 0xec, 0x7e, +0x00, 0x70, 0x00, 0x00, 0x10, 0x60, 0x00, 0x02, 0x44, 0x10, 0x00, 0x01, 0x58, 0x03, 0x00, 0x00, +0x49, 0xff, 0xed, 0xca, 0x58, 0x33, 0x80, 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x10, 0x00, 0x0f, +0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xf1, 0x32, 0x3e, 0x0f, 0x9c, 0xd0, 0x58, 0x13, 0x00, 0x00, +0x49, 0xff, 0xcd, 0x44, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xb4, 0x3e, 0x7f, 0x9e, 0xa8, 0x54, 0x10, 0x00, 0xff, +0x14, 0x1f, 0x80, 0x05, 0x3a, 0x03, 0x8c, 0x04, 0x50, 0x5f, 0x80, 0x2c, 0x3e, 0x6f, 0xb0, 0xd8, +0x3a, 0x02, 0x8c, 0x24, 0x3a, 0x03, 0x88, 0x00, 0x2e, 0x47, 0xb4, 0xf2, 0x3a, 0x02, 0x88, 0x20, +0x00, 0x03, 0x00, 0x0a, 0x14, 0x0f, 0x80, 0x07, 0x4e, 0x43, 0x00, 0x06, 0x58, 0x12, 0x00, 0x00, +0x48, 0x00, 0x00, 0x3e, 0x49, 0x00, 0x15, 0x26, 0x50, 0x23, 0x00, 0x28, 0x44, 0x10, 0x00, 0x00, +0x00, 0x61, 0x00, 0x00, 0x50, 0x30, 0x80, 0x01, 0x50, 0x21, 0x00, 0x01, 0x40, 0xf0, 0x18, 0x06, +0x4e, 0xf3, 0x00, 0x0a, 0x54, 0x11, 0x80, 0xff, 0x44, 0x50, 0x00, 0x08, 0x4c, 0x12, 0xff, 0xf2, +0x48, 0x00, 0x00, 0x08, 0x2e, 0x27, 0xb1, 0x08, 0x50, 0x10, 0xff, 0xf9, 0x48, 0x00, 0x00, 0x18, +0x3e, 0x2f, 0xb1, 0x0a, 0x44, 0x10, 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x50, 0x30, 0x80, 0x01, +0x50, 0x21, 0x00, 0x01, 0x40, 0xf0, 0x24, 0x06, 0x4e, 0xf3, 0x00, 0x08, 0x54, 0x11, 0x80, 0xff, +0x44, 0x50, 0x00, 0x07, 0x4c, 0x12, 0xff, 0xf2, 0x2e, 0x27, 0xb1, 0x08, 0x55, 0xe1, 0x00, 0x01, +0x4f, 0xe2, 0x00, 0x04, 0x40, 0x10, 0x84, 0x00, 0x40, 0x10, 0x80, 0x10, 0x2e, 0x27, 0xb0, 0xdc, +0x44, 0x50, 0x00, 0x02, 0x40, 0x31, 0x18, 0x09, 0x4c, 0x32, 0xc0, 0x0e, 0x54, 0x51, 0x00, 0x3f, +0x52, 0x72, 0x80, 0x00, 0x40, 0x43, 0x80, 0x10, 0x14, 0x4f, 0x80, 0x04, 0x45, 0xc0, 0x00, 0x01, +0x48, 0x00, 0x00, 0x12, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x32, 0x80, 0x08, 0x45, 0xc0, 0x00, 0x00, +0x15, 0xcf, 0x80, 0x04, 0x48, 0x00, 0x00, 0x08, 0x54, 0x81, 0x00, 0x3f, 0x14, 0x8f, 0x80, 0x04, +0x45, 0xc0, 0x00, 0x00, 0x05, 0xef, 0x80, 0x07, 0x54, 0x00, 0x80, 0xff, 0x42, 0xaf, 0x18, 0x0b, +0x3e, 0x9f, 0xb0, 0xec, 0x3e, 0x2f, 0xb1, 0x34, 0x50, 0x1f, 0x80, 0x2c, 0x14, 0x0f, 0x80, 0x08, +0x14, 0xaf, 0x80, 0x09, 0x14, 0x9f, 0x80, 0x03, 0x14, 0x2f, 0x80, 0x02, 0x14, 0x1f, 0x80, 0x01, +0x15, 0xcf, 0x80, 0x06, 0x04, 0x3f, 0x80, 0x03, 0x45, 0xc0, 0x00, 0x02, 0x00, 0x01, 0x80, 0x00, +0x40, 0x10, 0x18, 0x09, 0x4c, 0x1e, 0x40, 0x0c, 0x54, 0x70, 0x00, 0x3f, 0x52, 0x43, 0x80, 0x00, +0x40, 0x02, 0x00, 0x10, 0x44, 0x20, 0x00, 0x01, 0x48, 0x00, 0x00, 0x10, 0x44, 0x50, 0x00, 0x03, +0x4c, 0x12, 0x80, 0x08, 0x44, 0x20, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00, 0x48, 0x00, 0x00, 0x06, +0x54, 0x00, 0x00, 0x3f, 0x44, 0x20, 0x00, 0x00, 0x04, 0x1f, 0x80, 0x07, 0x04, 0x6f, 0x80, 0x09, +0x40, 0x80, 0x80, 0x00, 0x54, 0x74, 0x00, 0xff, 0x42, 0x13, 0x98, 0x0b, 0x4c, 0x60, 0x80, 0x10, +0x4c, 0x11, 0x00, 0x0e, 0x44, 0x90, 0x00, 0x01, 0x4c, 0x24, 0xc0, 0x06, 0x40, 0x74, 0x98, 0x08, +0x48, 0x00, 0x00, 0x06, 0x44, 0xa0, 0x00, 0x3f, 0x40, 0x75, 0x08, 0x1a, 0x05, 0xef, 0x80, 0x01, +0x04, 0x2f, 0x80, 0x02, 0x55, 0xc3, 0x80, 0x40, 0x00, 0x8f, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x01, +0x00, 0x51, 0x00, 0x00, 0x4f, 0xc3, 0x00, 0x20, 0x40, 0xf3, 0x94, 0x06, 0x4e, 0xf2, 0x00, 0x0e, +0x44, 0x30, 0x00, 0x07, 0x58, 0x05, 0x00, 0x00, 0x42, 0x04, 0x0c, 0x73, 0x3e, 0x4f, 0xc3, 0x5c, +0x40, 0x30, 0x10, 0x00, 0x48, 0x00, 0x00, 0x1a, 0x58, 0x15, 0x00, 0x00, 0x44, 0x20, 0x00, 0x07, +0x42, 0x14, 0x08, 0x73, 0x3e, 0x9f, 0xc3, 0x5c, 0x40, 0x60, 0xa4, 0x00, 0x10, 0x53, 0x00, 0x00, +0x48, 0x00, 0x00, 0x0e, 0x58, 0x55, 0x00, 0x00, 0x44, 0x00, 0x00, 0x07, 0x42, 0x54, 0x00, 0x73, +0x3f, 0xef, 0xc3, 0x5c, 0x40, 0x32, 0xf8, 0x00, 0x10, 0x71, 0x80, 0x00, 0x44, 0x40, 0x00, 0x07, +0x59, 0xe5, 0x00, 0x00, 0x2e, 0x27, 0xb4, 0x5d, 0x43, 0xe4, 0x10, 0x73, 0x3e, 0x0f, 0xc3, 0x5c, +0x04, 0x1f, 0x80, 0x08, 0x40, 0x61, 0x08, 0x00, 0x40, 0x5f, 0x00, 0x00, 0x00, 0x22, 0x80, 0x00, +0x40, 0x90, 0x98, 0x01, 0x54, 0x64, 0x80, 0xff, 0x40, 0x33, 0x08, 0x00, 0x54, 0x91, 0x80, 0xff, +0x42, 0x41, 0x18, 0x0b, 0x42, 0x54, 0x98, 0x0b, 0x4c, 0x42, 0x80, 0x12, 0x40, 0x63, 0x1c, 0x09, +0x4c, 0x53, 0x00, 0x0e, 0x44, 0x10, 0x00, 0x01, 0x4c, 0x60, 0xc0, 0x06, 0x40, 0x90, 0x98, 0x08, +0x48, 0x00, 0x00, 0x06, 0x44, 0x50, 0x00, 0x3f, 0x40, 0x92, 0x98, 0x1a, 0x44, 0x00, 0x00, 0x07, +0x58, 0x25, 0x00, 0x00, 0x42, 0x24, 0x00, 0x73, 0x3e, 0x4f, 0xc3, 0x5c, 0x41, 0xe1, 0x10, 0x00, +0x10, 0x9f, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x58, 0x3f, 0x00, 0x00, 0x58, 0x14, 0x00, 0x00, +0x58, 0x25, 0x00, 0x00, 0x44, 0x60, 0x00, 0x02, 0x49, 0xff, 0xd4, 0x86, 0x4c, 0x83, 0x40, 0x7c, +0x04, 0x3f, 0x80, 0x04, 0x04, 0x5f, 0x80, 0x02, 0x40, 0x13, 0x8c, 0x00, 0x54, 0x30, 0x80, 0xff, +0x40, 0x7e, 0x18, 0x09, 0x42, 0x11, 0x98, 0x0b, 0x00, 0x22, 0x80, 0x07, 0x4c, 0x70, 0x80, 0x16, +0x04, 0x6f, 0x80, 0x06, 0x4c, 0x13, 0x00, 0x12, 0x45, 0xe0, 0x00, 0x01, 0x4c, 0x6f, 0x40, 0x06, +0x40, 0x3f, 0x18, 0x08, 0x48, 0x00, 0x00, 0x1e, 0x04, 0x6f, 0x80, 0x06, 0x4e, 0x63, 0x00, 0x06, +0x44, 0x30, 0x00, 0x3f, 0x48, 0x00, 0x00, 0x06, 0x54, 0x41, 0x80, 0x40, 0x4e, 0x43, 0x00, 0x12, +0x3e, 0x0f, 0xc3, 0x5c, 0x40, 0x15, 0x00, 0x00, 0x40, 0xf1, 0x88, 0x06, 0x4e, 0xf2, 0x00, 0x06, +0x10, 0x30, 0x80, 0x15, 0x48, 0x00, 0x00, 0x0c, 0x10, 0x20, 0x80, 0x15, 0x48, 0x00, 0x00, 0x08, +0x3e, 0x7f, 0xc3, 0x5c, 0x40, 0x25, 0x1c, 0x00, 0x10, 0x31, 0x00, 0x15, 0x2e, 0x37, 0xb4, 0x5d, +0x04, 0x1f, 0x80, 0x08, 0x3e, 0x2f, 0xc3, 0x5c, 0x40, 0x45, 0x08, 0x00, 0x40, 0x01, 0x8c, 0x00, +0x01, 0xe2, 0x00, 0x15, 0x40, 0x50, 0x80, 0x01, 0x54, 0x12, 0x80, 0xff, 0x40, 0x60, 0xf8, 0x00, +0x54, 0x53, 0x00, 0xff, 0x42, 0x3f, 0x18, 0x0b, 0x42, 0x42, 0x98, 0x0b, 0x4c, 0x32, 0x00, 0x12, +0x40, 0x10, 0x9c, 0x09, 0x4c, 0x40, 0x80, 0x0e, 0x45, 0xe0, 0x00, 0x01, 0x4c, 0x1f, 0x40, 0x06, +0x40, 0x5f, 0x18, 0x08, 0x48, 0x00, 0x00, 0x06, 0x44, 0x70, 0x00, 0x3f, 0x40, 0x53, 0x84, 0x1a, +0x58, 0x01, 0x00, 0x00, 0x40, 0x65, 0x00, 0x00, 0x50, 0x15, 0x00, 0x15, 0x10, 0x53, 0x00, 0x15, +0x40, 0x30, 0x80, 0x00, 0x58, 0x25, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x10, 0x00, 0x03, +0x49, 0xff, 0xd4, 0x0a, 0x04, 0x0f, 0x80, 0x03, 0x04, 0x6f, 0x80, 0x02, 0x04, 0x2f, 0x80, 0x01, +0x50, 0x50, 0x00, 0x01, 0x51, 0xe3, 0x00, 0x01, 0x50, 0x31, 0x00, 0x02, 0x3e, 0x4f, 0xb0, 0xfa, +0x14, 0x5f, 0x80, 0x03, 0x15, 0xef, 0x80, 0x02, 0x14, 0x3f, 0x80, 0x01, 0x4c, 0x52, 0x7e, 0xb4, +0x04, 0x6f, 0x80, 0x05, 0x50, 0x53, 0x7f, 0xff, 0x54, 0x12, 0x80, 0xff, 0x5c, 0xf0, 0x80, 0x05, +0x4e, 0xf2, 0x00, 0x1c, 0x2e, 0x07, 0xb0, 0xe3, 0x40, 0x40, 0x00, 0x10, 0x4e, 0x45, 0x00, 0x06, +0x44, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0e, 0x42, 0x50, 0x18, 0x0b, 0x40, 0x12, 0x94, 0x00, +0x51, 0xe0, 0xff, 0xff, 0x54, 0x60, 0x00, 0x3f, 0x42, 0x2f, 0x18, 0x24, 0x40, 0x11, 0x00, 0x10, +0x2e, 0x07, 0xb0, 0xe9, 0x48, 0x00, 0x00, 0x4e, 0x04, 0x7f, 0x80, 0x05, 0x50, 0x33, 0xff, 0xfa, +0x54, 0x41, 0x80, 0xff, 0x5c, 0xf2, 0x00, 0x05, 0x4e, 0xf2, 0x00, 0x1c, 0x2e, 0x07, 0xb0, 0xe4, +0x40, 0x20, 0x00, 0x10, 0x4e, 0x25, 0x00, 0x06, 0x44, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0e, +0x42, 0x30, 0x18, 0x0b, 0x40, 0x41, 0x8c, 0x00, 0x50, 0x12, 0x7f, 0xff, 0x54, 0x50, 0x00, 0x3f, +0x42, 0x60, 0x94, 0x24, 0x40, 0x13, 0x00, 0x10, 0x2e, 0x07, 0xb0, 0xea, 0x48, 0x00, 0x00, 0x2a, +0x04, 0x1f, 0x80, 0x05, 0x51, 0xe0, 0xff, 0xf5, 0x54, 0x2f, 0x00, 0xff, 0x5c, 0xf1, 0x00, 0x04, +0x4e, 0xf3, 0x00, 0x08, 0x46, 0x0c, 0x00, 0x00, 0x58, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x8c, +0x2e, 0x07, 0xb0, 0xe5, 0x40, 0x60, 0x00, 0x10, 0x4e, 0x65, 0x00, 0x06, 0x44, 0x10, 0x00, 0x00, +0x48, 0x00, 0x00, 0x0e, 0x43, 0xe0, 0x18, 0x0b, 0x40, 0x2f, 0x78, 0x00, 0x50, 0x31, 0x7f, 0xff, +0x54, 0x00, 0x00, 0x3f, 0x42, 0x41, 0x80, 0x24, 0x40, 0x12, 0x00, 0x10, 0x2e, 0x07, 0xb0, 0xeb, +0x40, 0x50, 0x00, 0x10, 0x4e, 0x54, 0x00, 0x10, 0x43, 0xe0, 0x18, 0x0b, 0x40, 0x2f, 0x78, 0x00, +0x50, 0x31, 0x7f, 0xff, 0x54, 0x00, 0x00, 0x3f, 0x42, 0x41, 0x80, 0x24, 0x40, 0x22, 0x00, 0x10, +0x48, 0x00, 0x00, 0x04, 0x44, 0x20, 0x00, 0x00, 0x2e, 0x67, 0xb0, 0xda, 0x54, 0x03, 0x00, 0x20, +0x4e, 0x02, 0x00, 0x30, 0x44, 0x4f, 0xff, 0xf8, 0x42, 0x50, 0x90, 0x00, 0x44, 0x30, 0x00, 0x07, +0x46, 0x06, 0x02, 0x00, 0x42, 0x12, 0x8c, 0x01, 0x05, 0xe0, 0x03, 0x43, 0x40, 0x60, 0x90, 0x08, +0x54, 0x13, 0x00, 0xff, 0x44, 0x6f, 0xff, 0x00, 0x40, 0x5f, 0x18, 0x02, 0x41, 0xe0, 0x94, 0x04, +0x15, 0xe0, 0x03, 0x43, 0x46, 0x06, 0x02, 0x01, 0x42, 0x11, 0x10, 0x00, 0x42, 0x50, 0x8c, 0x01, +0x04, 0x20, 0x03, 0x43, 0x41, 0xe2, 0x90, 0x08, 0x54, 0x3f, 0x00, 0xff, 0x40, 0x11, 0x18, 0x02, +0x40, 0x41, 0x84, 0x04, 0x14, 0x40, 0x03, 0x43, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x2c, +0x44, 0x5f, 0xff, 0xc0, 0x42, 0x10, 0x94, 0x00, 0x44, 0x40, 0x00, 0x3f, 0x46, 0x36, 0x02, 0x00, +0x43, 0xe0, 0x90, 0x01, 0x04, 0x61, 0x83, 0x46, 0x40, 0x7f, 0x78, 0x00, 0x54, 0x13, 0x80, 0xff, +0x44, 0x7f, 0xff, 0x00, 0x40, 0x63, 0x1c, 0x02, 0x41, 0xe0, 0x98, 0x04, 0x15, 0xe1, 0x83, 0x46, +0x47, 0xe6, 0x02, 0x01, 0x42, 0x31, 0x14, 0x00, 0x42, 0x21, 0x90, 0x01, 0x04, 0x1f, 0x03, 0x46, +0x40, 0x51, 0x08, 0x00, 0x54, 0x42, 0x80, 0xff, 0x40, 0x30, 0x9c, 0x02, 0x40, 0x22, 0x0c, 0x04, +0x14, 0x2f, 0x03, 0x46, 0x51, 0xff, 0x80, 0x4c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x04, 0x70, 0x00, 0x02, 0x3e, 0x2f, 0xb0, 0xd8, +0x50, 0x13, 0x80, 0x20, 0x00, 0x40, 0x80, 0x01, 0x58, 0x60, 0x00, 0x00, 0x10, 0x41, 0x00, 0x02, +0x00, 0x30, 0x80, 0x02, 0x10, 0x31, 0x00, 0x01, 0x01, 0xe0, 0x80, 0x03, 0x11, 0xe1, 0x00, 0x0a, +0x00, 0x50, 0x80, 0x04, 0x10, 0x51, 0x00, 0x10, 0x00, 0x00, 0x80, 0x05, 0x10, 0x01, 0x00, 0x14, +0x00, 0x40, 0x80, 0x06, 0x10, 0x41, 0x00, 0x15, 0x00, 0x30, 0x80, 0x07, 0x10, 0x31, 0x00, 0x16, +0x01, 0xe0, 0x80, 0x08, 0x11, 0xe1, 0x00, 0x17, 0x00, 0x50, 0x80, 0x09, 0x10, 0x51, 0x00, 0x18, +0x00, 0x00, 0x80, 0x0a, 0x10, 0x01, 0x00, 0x19, 0x00, 0x40, 0x80, 0x0b, 0x10, 0x41, 0x00, 0x1a, +0x00, 0x30, 0x80, 0x0c, 0x10, 0x31, 0x00, 0x1b, 0x01, 0xe0, 0x80, 0x0d, 0x11, 0xe1, 0x00, 0x1c, +0x00, 0x50, 0x80, 0x0e, 0x10, 0x51, 0x00, 0x1d, 0x00, 0x00, 0x80, 0x0f, 0x10, 0x01, 0x00, 0x1e, +0x00, 0x40, 0x80, 0x10, 0x10, 0x41, 0x00, 0x1f, 0x00, 0x30, 0x80, 0x11, 0x10, 0x31, 0x00, 0x20, +0x01, 0xe0, 0x80, 0x12, 0x11, 0xe1, 0x00, 0x21, 0x00, 0x50, 0x80, 0x13, 0x10, 0x51, 0x00, 0x04, +0x00, 0x00, 0x80, 0x14, 0x10, 0x01, 0x00, 0x0b, 0x00, 0x40, 0x80, 0x15, 0x10, 0x41, 0x00, 0x0c, +0x00, 0x30, 0x80, 0x16, 0x10, 0x31, 0x00, 0x0d, 0x01, 0xe0, 0x80, 0x17, 0x11, 0xe1, 0x00, 0x11, +0x00, 0x50, 0x80, 0x18, 0x10, 0x51, 0x00, 0x12, 0x00, 0x00, 0x80, 0x19, 0x10, 0x01, 0x00, 0x13, +0x00, 0x40, 0x80, 0x1a, 0x10, 0x41, 0x00, 0x28, 0x00, 0x30, 0x80, 0x1b, 0x10, 0x31, 0x00, 0x29, +0x01, 0xe0, 0x80, 0x1c, 0x11, 0xe1, 0x00, 0x2a, 0x00, 0x50, 0x80, 0x1d, 0x10, 0x51, 0x00, 0x2b, +0x00, 0x00, 0x80, 0x1e, 0x10, 0x01, 0x00, 0x2c, 0x00, 0x40, 0x80, 0x1f, 0x10, 0x41, 0x00, 0x2d, +0x00, 0x30, 0x80, 0x20, 0x10, 0x31, 0x00, 0x2e, 0x50, 0x31, 0x00, 0x28, 0x00, 0x00, 0x80, 0x21, +0x10, 0x01, 0x00, 0x2f, 0x01, 0xe0, 0x80, 0x22, 0x11, 0xe1, 0x00, 0x30, 0x00, 0x50, 0x80, 0x23, +0x10, 0x51, 0x00, 0x31, 0x40, 0x02, 0x80, 0x01, 0x00, 0x40, 0x80, 0x24, 0x54, 0x00, 0x00, 0xff, +0x10, 0x41, 0x00, 0x32, 0x01, 0xe0, 0x80, 0x25, 0x11, 0xe1, 0x00, 0x33, 0x00, 0x50, 0x80, 0x26, +0x10, 0x51, 0x00, 0x34, 0x00, 0x40, 0x80, 0x27, 0x10, 0x41, 0x00, 0x35, 0x01, 0xe0, 0x80, 0x28, +0x11, 0xe1, 0x00, 0x36, 0x00, 0x50, 0x80, 0x29, 0x10, 0x51, 0x00, 0x37, 0x00, 0x40, 0x80, 0x2a, +0x10, 0x41, 0x00, 0x38, 0x00, 0x21, 0x80, 0x00, 0x44, 0x50, 0x00, 0x7f, 0x4c, 0x22, 0x80, 0x08, +0x40, 0x40, 0x08, 0x00, 0x4e, 0x22, 0x00, 0x04, 0x10, 0x41, 0x80, 0x00, 0x50, 0x31, 0x80, 0x01, +0x3e, 0x2f, 0xb1, 0x08, 0x4c, 0x31, 0x7f, 0xf0, 0x50, 0x31, 0x80, 0x02, 0x00, 0x21, 0x80, 0x00, +0x44, 0x50, 0x00, 0x7f, 0x4c, 0x22, 0x80, 0x08, 0x40, 0x40, 0x08, 0x00, 0x4e, 0x22, 0x00, 0x04, +0x10, 0x41, 0x80, 0x00, 0x50, 0x31, 0x80, 0x01, 0x3e, 0x5f, 0xb1, 0x11, 0x4c, 0x32, 0xff, 0xf0, +0x00, 0x30, 0x80, 0x2b, 0x3e, 0x37, 0xb4, 0x5d, 0x00, 0x00, 0x80, 0x00, 0x3e, 0x1f, 0xb1, 0x34, +0x49, 0xff, 0xfc, 0x48, 0x00, 0x13, 0x80, 0x0b, 0x54, 0x00, 0x80, 0x01, 0x4e, 0x02, 0x00, 0x08, +0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x49, 0xff, 0xf7, 0xee, 0x51, 0xff, 0x80, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x04, 0x80, 0x00, 0x02, +0x58, 0x70, 0x00, 0x00, 0x50, 0x64, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x1c, +0x49, 0x00, 0x0f, 0x2e, 0x4e, 0x02, 0x00, 0x08, 0x46, 0x0c, 0x00, 0x00, 0x58, 0x00, 0x00, 0x01, +0x48, 0x00, 0x00, 0x20, 0x20, 0x43, 0x00, 0x06, 0x00, 0x03, 0x00, 0x02, 0x00, 0x13, 0x00, 0x03, +0x00, 0x23, 0x00, 0x04, 0x20, 0x33, 0x00, 0x05, 0x49, 0x00, 0x0e, 0xf4, 0x49, 0x00, 0x13, 0xfc, +0x48, 0x00, 0x00, 0x04, 0x49, 0x00, 0x11, 0x60, 0x00, 0x14, 0x00, 0x0b, 0x54, 0x00, 0x80, 0x01, +0x4e, 0x02, 0x00, 0x08, 0x58, 0x03, 0x80, 0x00, 0x44, 0x10, 0x00, 0x00, 0x49, 0xff, 0xf7, 0xb4, +0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x04, 0x70, 0x00, 0x02, 0x58, 0x90, 0x00, 0x00, 0x02, 0x13, 0x80, 0x00, 0x50, 0x03, 0x80, 0x20, +0x5c, 0xf0, 0x80, 0x44, 0x4e, 0xf2, 0x00, 0x08, 0x3e, 0x1f, 0xb1, 0x34, 0x44, 0x2f, 0xff, 0xff, +0x48, 0x00, 0x00, 0x3e, 0x3e, 0x1f, 0xb1, 0x34, 0x50, 0x33, 0x80, 0x2c, 0x58, 0x20, 0x80, 0x00, +0x48, 0x00, 0x00, 0x06, 0x08, 0x41, 0x80, 0x01, 0x18, 0x41, 0x00, 0x01, 0x50, 0x50, 0x80, 0x15, +0x4c, 0x22, 0xff, 0xfa, 0x2e, 0x27, 0xb4, 0xf4, 0x4e, 0x22, 0x00, 0x2e, 0x2e, 0x87, 0xb0, 0xe2, +0x2e, 0xa7, 0xb1, 0x1e, 0x44, 0x40, 0x00, 0x00, 0x40, 0x65, 0x20, 0x01, 0x54, 0x33, 0x00, 0xff, +0x48, 0x00, 0x00, 0x16, 0x00, 0x20, 0x80, 0x00, 0x45, 0xe0, 0x00, 0xff, 0x4c, 0x2f, 0x00, 0x0e, +0x40, 0x51, 0x0c, 0x01, 0x40, 0xf1, 0x0c, 0x06, 0x4e, 0xf2, 0x00, 0x06, 0x10, 0x40, 0x80, 0x00, +0x48, 0x00, 0x00, 0x04, 0x10, 0x50, 0x80, 0x00, 0x50, 0x10, 0x80, 0x01, 0x3e, 0x5f, 0xb1, 0x49, +0x4c, 0x12, 0xff, 0xea, 0x48, 0x00, 0x00, 0x08, 0x18, 0x20, 0x80, 0x01, 0x3e, 0x4f, 0xb1, 0x49, +0x4c, 0x12, 0x7f, 0xfc, 0x00, 0x10, 0x00, 0x00, 0x00, 0x80, 0x00, 0x01, 0x3e, 0x28, 0x02, 0x85, +0x40, 0xa4, 0x04, 0x06, 0x44, 0x00, 0x00, 0x03, 0x01, 0xe1, 0x00, 0x00, 0x46, 0x40, 0x02, 0x4b, +0x46, 0x50, 0x04, 0xc4, 0x44, 0x60, 0x00, 0x00, 0x40, 0x23, 0x28, 0x1a, 0x40, 0x20, 0x28, 0x1b, +0x58, 0x42, 0x0a, 0x58, 0x58, 0x52, 0x8b, 0x40, 0x5d, 0xc0, 0x80, 0x0f, 0x40, 0xa0, 0xa0, 0x06, +0x44, 0x30, 0x00, 0x01, 0x40, 0x02, 0x70, 0x1b, 0x40, 0x02, 0xf0, 0x1a, 0x40, 0x21, 0xa8, 0x1b, +0x4f, 0xe2, 0x00, 0x14, 0x2f, 0xe0, 0x02, 0x86, 0x4f, 0xe2, 0x00, 0x10, 0x2e, 0x50, 0x02, 0x87, +0x4e, 0x52, 0x00, 0x0c, 0x58, 0x33, 0x00, 0x00, 0x58, 0x43, 0x00, 0x00, 0x58, 0x53, 0x00, 0x00, +0x49, 0x00, 0x0d, 0x4a, 0x48, 0x00, 0x00, 0x06, 0x46, 0x6c, 0x00, 0x00, 0x58, 0x63, 0x00, 0x01, +0x3e, 0x1f, 0xb1, 0x34, 0x58, 0x04, 0x00, 0x00, 0x49, 0xff, 0xfb, 0x64, 0x00, 0x03, 0x80, 0x0b, +0x54, 0x10, 0x00, 0x01, 0x4e, 0x12, 0x00, 0x0a, 0x58, 0x13, 0x00, 0x00, 0x58, 0x04, 0x80, 0x00, +0x49, 0xff, 0xf7, 0x0a, 0x58, 0x60, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xf4, +0x54, 0x60, 0x00, 0xff, 0x44, 0x00, 0x00, 0x14, 0x49, 0xf7, 0xdc, 0xe8, 0x44, 0x50, 0x0f, 0xff, +0x58, 0x70, 0x00, 0x00, 0x4c, 0x02, 0xc0, 0x06, 0x44, 0x00, 0x01, 0x03, 0x48, 0x00, 0x00, 0x3a, +0x49, 0xf7, 0xdc, 0xae, 0x44, 0x10, 0x00, 0x14, 0x44, 0x5f, 0xe0, 0x00, 0x44, 0x4f, 0xff, 0xed, +0x44, 0x20, 0x00, 0x00, 0x58, 0x30, 0x00, 0x00, 0x12, 0x10, 0x00, 0x00, 0x10, 0x20, 0x00, 0x05, +0x12, 0x50, 0x00, 0x01, 0x10, 0x40, 0x00, 0x04, 0x50, 0x00, 0x80, 0x06, 0x10, 0x01, 0x80, 0x08, +0x50, 0x21, 0x80, 0x0c, 0x58, 0x03, 0x00, 0x00, 0x50, 0x1f, 0x80, 0x07, 0x49, 0xff, 0xd6, 0x08, +0x58, 0x60, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0x9d, 0x0c, +0x44, 0x20, 0x06, 0x91, 0x49, 0xff, 0xc8, 0x4a, 0x48, 0x00, 0x00, 0x00, 0x58, 0x23, 0x80, 0x00, +0x44, 0x10, 0x00, 0x01, 0x58, 0x30, 0x00, 0x00, 0x49, 0xf7, 0xe0, 0xac, 0x58, 0x03, 0x00, 0x00, +0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xd4, 0x14, 0x0f, 0x80, 0x03, 0x44, 0x40, 0x00, 0x01, 0x04, 0x00, 0x00, 0x02, +0x14, 0x0f, 0x80, 0x02, 0x50, 0x70, 0x00, 0x20, 0x00, 0x63, 0x80, 0x01, 0x00, 0x83, 0x80, 0x00, +0x4c, 0x62, 0x40, 0x06, 0x49, 0x00, 0x04, 0x32, 0x48, 0x00, 0x00, 0x08, 0x44, 0x10, 0x00, 0x02, +0x4c, 0x60, 0xc0, 0x04, 0x49, 0x00, 0x04, 0x46, 0x44, 0x20, 0x00, 0x04, 0x4c, 0x81, 0x41, 0x42, +0x44, 0x30, 0x00, 0x01, 0x4c, 0x61, 0xc1, 0x16, 0x2e, 0x57, 0xb0, 0xd4, 0x44, 0x90, 0x00, 0x02, +0x4c, 0x54, 0xc1, 0x6c, 0x00, 0xa3, 0x80, 0x1e, 0x01, 0xe3, 0x80, 0x08, 0x40, 0x55, 0x28, 0x00, +0x40, 0x92, 0xf8, 0x00, 0x40, 0x3f, 0x78, 0x00, 0x40, 0x44, 0x8c, 0xb6, 0x02, 0x23, 0x80, 0x05, +0x44, 0x10, 0x00, 0x0a, 0x14, 0x2f, 0x80, 0x04, 0x50, 0x9f, 0x80, 0x27, 0x05, 0xc3, 0x80, 0x03, +0x3e, 0x3e, 0xb0, 0xa8, 0x15, 0xcf, 0x80, 0x06, 0x58, 0x5f, 0x00, 0x00, 0x04, 0x83, 0x80, 0x04, +0x50, 0x73, 0x80, 0x02, 0x14, 0x8f, 0x80, 0x05, 0x14, 0x7f, 0x80, 0x07, 0x45, 0xc0, 0x00, 0x00, +0x50, 0x8f, 0x80, 0x20, 0x54, 0x62, 0x00, 0xff, 0x5c, 0x03, 0x00, 0x0a, 0x40, 0x60, 0x80, 0x1b, +0x58, 0xa3, 0x00, 0x00, 0x14, 0x3f, 0x80, 0x01, 0x14, 0x5f, 0x80, 0x00, 0x58, 0x0e, 0x00, 0x00, +0x58, 0x24, 0x00, 0x00, 0x58, 0x14, 0x80, 0x00, 0x4b, 0xe0, 0x0c, 0x01, 0x04, 0x1f, 0x80, 0x07, +0x58, 0x04, 0x00, 0x00, 0x44, 0x20, 0x00, 0x06, 0x49, 0xf7, 0xd7, 0x12, 0x54, 0x6e, 0x00, 0xff, +0x04, 0x3f, 0x80, 0x01, 0x51, 0xce, 0x00, 0x01, 0x04, 0x5f, 0x80, 0x00, 0x4e, 0x03, 0x00, 0x08, +0x58, 0x45, 0x00, 0x00, 0x58, 0xa2, 0x80, 0x00, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x60, 0x00, 0x03, +0x4d, 0xc3, 0x7f, 0xda, 0x58, 0x45, 0x00, 0x00, 0x44, 0x60, 0x00, 0x00, 0x58, 0xa2, 0x80, 0x00, +0x04, 0x7f, 0x80, 0x05, 0x46, 0x86, 0x01, 0x40, 0x14, 0x74, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, +0x05, 0xef, 0x80, 0x06, 0x14, 0x4f, 0x80, 0x01, 0x40, 0x1f, 0x00, 0x13, 0x49, 0xff, 0xdc, 0x94, +0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x49, 0xff, 0xdc, 0xe8, 0x58, 0x03, 0x00, 0x00, +0x44, 0x10, 0x00, 0x01, 0x49, 0xff, 0xdb, 0xea, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, +0x49, 0xff, 0xdc, 0x26, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x49, 0xff, 0xdd, 0x78, +0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x49, 0xff, 0xd8, 0xba, 0x44, 0x10, 0x00, 0x00, +0x58, 0x03, 0x00, 0x00, 0x49, 0xff, 0xd9, 0xd4, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, +0x49, 0xff, 0xd8, 0xae, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x49, 0xff, 0xd9, 0xc8, +0x04, 0x4f, 0x80, 0x01, 0x44, 0x20, 0x00, 0x01, 0x44, 0x30, 0x00, 0x64, 0x44, 0x10, 0x00, 0x05, +0x44, 0x00, 0x00, 0x00, 0x49, 0xff, 0xdf, 0xac, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, +0x49, 0xff, 0xd9, 0x04, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x49, 0xff, 0xd9, 0x6e, +0x44, 0x00, 0x00, 0x01, 0x58, 0x20, 0x00, 0x00, 0x44, 0x30, 0x00, 0x64, 0x44, 0x40, 0x00, 0x00, +0x44, 0x10, 0x00, 0x05, 0x49, 0xff, 0xd9, 0xe6, 0x44, 0x40, 0x00, 0x01, 0x04, 0x1f, 0x80, 0x04, +0x58, 0x52, 0x00, 0x00, 0x44, 0x30, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x58, 0x25, 0x00, 0x00, +0x49, 0xff, 0xde, 0xf0, 0x50, 0x25, 0x7f, 0xff, 0x54, 0x11, 0x00, 0xff, 0x58, 0x03, 0x00, 0x00, +0x49, 0xff, 0xdb, 0x52, 0x44, 0x10, 0x00, 0x01, 0x58, 0x20, 0x80, 0x00, 0x58, 0x03, 0x00, 0x00, +0x49, 0xff, 0xde, 0x7c, 0x46, 0x16, 0x03, 0x00, 0x04, 0x00, 0x80, 0x17, 0x46, 0x26, 0x03, 0x00, +0x58, 0x50, 0x00, 0x01, 0x14, 0x50, 0x80, 0x17, 0x58, 0x21, 0x00, 0x30, 0x04, 0x31, 0x00, 0x00, +0x40, 0x01, 0xa0, 0x09, 0x40, 0x00, 0x20, 0x08, 0x14, 0x01, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, +0x04, 0x51, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x58, 0x32, 0x80, 0x50, 0x14, 0x31, 0x00, 0x00, +0x49, 0xff, 0xdd, 0xc2, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x49, 0xff, 0xe2, 0x6c, +0x49, 0xff, 0xd8, 0x2e, 0x44, 0x10, 0x00, 0x01, 0x3e, 0x17, 0xb0, 0xd4, 0x48, 0x00, 0x00, 0x5a, +0x45, 0xc0, 0x00, 0x02, 0x4c, 0x6e, 0x40, 0x5a, 0x2e, 0x97, 0xb0, 0xd4, 0x44, 0xa0, 0x00, 0x01, +0x4c, 0x95, 0x40, 0x54, 0x04, 0x73, 0x80, 0x04, 0x49, 0xff, 0xdf, 0xae, 0x49, 0xff, 0xd8, 0x20, +0x44, 0x00, 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x49, 0xff, 0xe2, 0x4e, 0x46, 0x16, 0x01, 0x40, +0x14, 0x70, 0x80, 0x00, 0x58, 0x40, 0x80, 0x00, 0x04, 0x52, 0x00, 0x20, 0x42, 0x32, 0x88, 0x09, +0x14, 0x32, 0x00, 0x20, 0x44, 0x10, 0x00, 0x00, 0x3e, 0x67, 0xb0, 0xd4, 0x48, 0x00, 0x00, 0x3a, +0x44, 0x20, 0x00, 0x05, 0x4c, 0x81, 0x40, 0x22, 0x45, 0xe0, 0x00, 0x01, 0x4c, 0x6f, 0x40, 0x0c, +0x3e, 0x7f, 0xb0, 0xd5, 0x45, 0xc0, 0x00, 0x02, 0x11, 0xc3, 0x80, 0x00, 0x49, 0xff, 0xd7, 0xf0, +0x48, 0x00, 0x00, 0x10, 0x44, 0x90, 0x00, 0x02, 0x4c, 0x64, 0xc0, 0x20, 0x3e, 0x7f, 0xb0, 0xd5, +0x44, 0xa0, 0x00, 0x01, 0x10, 0xa3, 0x80, 0x00, 0x49, 0xff, 0xdf, 0x76, 0x49, 0xff, 0xd7, 0xe8, +0x10, 0x63, 0x80, 0x00, 0x48, 0x00, 0x00, 0x0e, 0x44, 0x40, 0x00, 0x06, 0x4c, 0x82, 0x40, 0x0e, +0x44, 0x30, 0x00, 0x01, 0x4c, 0x61, 0x80, 0x06, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x62, 0xc0, 0x06, +0x44, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x06, 0x46, 0x1c, 0x00, 0x00, 0x58, 0x10, 0x80, 0xbb, +0x05, 0xef, 0x80, 0x02, 0x00, 0x2f, 0x00, 0x0b, 0x54, 0x01, 0x00, 0x01, 0x4e, 0x02, 0x00, 0x08, +0x04, 0x0f, 0x80, 0x03, 0x49, 0xff, 0xf5, 0x08, 0x58, 0x10, 0x00, 0x00, 0x58, 0x00, 0x80, 0x00, +0x51, 0xff, 0x80, 0x2c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, +0x04, 0x10, 0x00, 0x02, 0x58, 0x60, 0x00, 0x00, 0x00, 0x20, 0x80, 0x09, 0x3e, 0x0f, 0x9d, 0x38, +0x44, 0x70, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x50, 0x33, 0x80, 0x01, 0x4c, 0x51, 0x40, 0x12, +0x04, 0x10, 0x00, 0x01, 0x4e, 0x12, 0x00, 0x0e, 0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x04, 0x01, +0x58, 0x80, 0x00, 0x00, 0x5c, 0xf3, 0x80, 0x17, 0x4e, 0xf3, 0x00, 0x14, 0x48, 0x00, 0x00, 0x0c, +0x40, 0x71, 0x80, 0x13, 0x44, 0x50, 0x00, 0x17, 0x50, 0x00, 0x00, 0x08, 0x4c, 0x72, 0xff, 0xe4, +0x44, 0x80, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x49, 0xff, 0xe6, 0x26, +0x58, 0x04, 0x00, 0x00, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, +0x04, 0x60, 0x00, 0x02, 0x58, 0x70, 0x00, 0x00, 0x50, 0x83, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x06, 0x49, 0xff, 0xf2, 0xb0, 0x48, 0x00, 0x00, 0x0c, +0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0x80, 0x06, 0x44, 0x11, 0x00, 0x03, 0x48, 0x00, 0x00, 0x06, +0x49, 0xff, 0xf2, 0xbc, 0x44, 0x10, 0x00, 0x00, 0x00, 0x33, 0x00, 0x0b, 0x54, 0x01, 0x80, 0x01, +0x4e, 0x02, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x00, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x0e, +0x3e, 0x07, 0xb4, 0x61, 0x00, 0x23, 0x00, 0x07, 0x3e, 0x27, 0xb4, 0x62, 0x00, 0x63, 0x00, 0x09, +0x3e, 0x67, 0xb4, 0x63, 0x48, 0x00, 0x00, 0x08, 0x58, 0x03, 0x80, 0x00, 0x49, 0xff, 0xf4, 0x8c, +0x58, 0x10, 0x00, 0x00, 0x58, 0x00, 0x80, 0x00, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x04, 0xa0, 0x00, 0x02, 0x44, 0x00, 0x00, 0x24, +0x00, 0x25, 0x00, 0x07, 0x14, 0x2f, 0x80, 0x01, 0x04, 0x85, 0x00, 0x08, 0x49, 0xf7, 0xda, 0x66, +0x44, 0x50, 0x0f, 0xff, 0x59, 0xc0, 0x00, 0x00, 0x4c, 0x02, 0xc0, 0x06, 0x44, 0x00, 0x01, 0x03, +0x48, 0x00, 0x00, 0x60, 0x49, 0xf7, 0xda, 0x2c, 0x50, 0x70, 0x00, 0x0c, 0x44, 0x10, 0x00, 0x00, +0x44, 0x20, 0x00, 0x24, 0x54, 0x94, 0x00, 0x0f, 0x58, 0x60, 0x00, 0x00, 0x49, 0xf7, 0xd4, 0x96, +0x14, 0x83, 0x80, 0x00, 0x4e, 0x92, 0x00, 0x06, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x16, +0x00, 0xa5, 0x00, 0x06, 0x44, 0x50, 0x00, 0x01, 0x4c, 0xa2, 0xc0, 0x14, 0x3c, 0x4d, 0xff, 0xff, +0x58, 0x04, 0x00, 0x00, 0x50, 0x13, 0x00, 0x14, 0x4b, 0xe0, 0x10, 0x01, 0x40, 0x34, 0x80, 0x1b, +0x40, 0x35, 0x00, 0x1a, 0x58, 0x01, 0x80, 0x00, 0x14, 0x03, 0x80, 0x01, 0x48, 0x00, 0x00, 0x12, +0x4e, 0xa3, 0x00, 0x0e, 0x58, 0x04, 0x00, 0x00, 0x50, 0x13, 0x00, 0x14, 0x50, 0x23, 0x00, 0x10, +0x44, 0x30, 0x00, 0x01, 0x49, 0xf7, 0xfa, 0x1a, 0x48, 0x00, 0x00, 0x04, 0x14, 0x93, 0x80, 0x01, +0x44, 0x30, 0x00, 0x01, 0x44, 0x00, 0x00, 0x24, 0x44, 0x2f, 0xe0, 0x00, 0x44, 0x1f, 0xff, 0xed, +0x10, 0x33, 0x00, 0x08, 0x12, 0x03, 0x00, 0x00, 0x12, 0x23, 0x00, 0x01, 0x10, 0x13, 0x00, 0x04, +0x44, 0x00, 0x00, 0x00, 0x05, 0xef, 0x80, 0x01, 0x58, 0x2e, 0x00, 0x00, 0x11, 0xe3, 0x00, 0x05, +0x44, 0x10, 0x00, 0x01, 0x58, 0x30, 0x00, 0x00, 0x49, 0xf7, 0xde, 0x04, 0x44, 0x00, 0x00, 0x00, +0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x04, 0x70, 0x00, 0x02, 0x00, 0x03, 0x80, 0x06, 0x50, 0x63, 0x80, 0x20, +0x4e, 0x02, 0x00, 0x10, 0x04, 0x03, 0x00, 0x01, 0x04, 0x13, 0x00, 0x02, 0x04, 0x23, 0x00, 0x00, +0x49, 0x00, 0x21, 0x56, 0x00, 0x13, 0x80, 0x0b, 0x54, 0x00, 0x80, 0x01, 0x4e, 0x02, 0x00, 0x56, +0x00, 0x23, 0x80, 0x06, 0x4e, 0x22, 0x00, 0x08, 0x00, 0x33, 0x80, 0x0b, 0x54, 0x01, 0x80, 0x01, +0x4e, 0x02, 0x00, 0x4c, 0x44, 0x00, 0x00, 0x18, 0x00, 0x93, 0x80, 0x07, 0x49, 0xf7, 0xd9, 0xce, +0x44, 0x50, 0x0f, 0xff, 0x58, 0x80, 0x00, 0x00, 0x4c, 0x02, 0xc0, 0x06, 0x44, 0x00, 0x01, 0x03, +0x48, 0x00, 0x00, 0x3c, 0x49, 0xf7, 0xd9, 0x94, 0x44, 0x20, 0x00, 0x18, 0x44, 0x10, 0x00, 0x00, +0x58, 0x70, 0x00, 0x00, 0x49, 0xf7, 0xd4, 0x02, 0x44, 0x40, 0x00, 0x18, 0x44, 0x3f, 0xe0, 0x00, +0x44, 0x2f, 0xff, 0xed, 0x44, 0x10, 0x00, 0x02, 0x12, 0x43, 0x80, 0x00, 0x12, 0x33, 0x80, 0x01, +0x10, 0x23, 0x80, 0x04, 0x10, 0x93, 0x80, 0x05, 0x10, 0x13, 0x80, 0x08, 0x50, 0x73, 0x80, 0x0c, +0x04, 0x03, 0x00, 0x00, 0x14, 0x03, 0x80, 0x00, 0x04, 0x53, 0x00, 0x01, 0x14, 0x53, 0x80, 0x01, +0x04, 0x13, 0x00, 0x00, 0x04, 0x03, 0x00, 0x01, 0x49, 0x00, 0x21, 0x28, 0x14, 0x03, 0x80, 0x02, +0x44, 0x00, 0x00, 0x00, 0x58, 0x24, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x58, 0x30, 0x00, 0x00, +0x49, 0xf7, 0xdd, 0x90, 0x44, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xa4, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xec, 0x04, 0x60, 0x00, 0x02, +0x44, 0x10, 0x00, 0x0c, 0x03, 0xc3, 0x00, 0x00, 0x58, 0x80, 0x00, 0x00, 0x51, 0xce, 0x7f, 0xe0, +0x40, 0x3e, 0x05, 0x57, 0x00, 0x03, 0x00, 0x07, 0x50, 0x73, 0x00, 0x20, 0x14, 0x0f, 0x80, 0x03, +0x14, 0x3f, 0x80, 0x02, 0x4e, 0xa2, 0x00, 0x0e, 0x44, 0x40, 0x00, 0x00, 0x44, 0x20, 0xff, 0xff, +0x14, 0x43, 0x80, 0x02, 0x14, 0x23, 0x80, 0x00, 0x14, 0x43, 0x80, 0x01, 0x48, 0x00, 0x00, 0x76, +0x00, 0x03, 0x00, 0x06, 0x50, 0x93, 0x00, 0x28, 0x4e, 0x02, 0x00, 0x3c, 0x3f, 0xcf, 0x4c, 0xf8, +0x48, 0x00, 0x00, 0x24, 0x04, 0x23, 0x80, 0x00, 0x54, 0x01, 0x00, 0xff, 0x4e, 0x03, 0x00, 0x0a, +0x04, 0x53, 0x80, 0x01, 0x04, 0x14, 0x80, 0x00, 0x14, 0x12, 0x80, 0x00, 0x48, 0x00, 0x00, 0x0e, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x0a, 0x04, 0x03, 0x80, 0x01, 0x04, 0x14, 0x80, 0x00, +0x40, 0x21, 0x20, 0x09, 0x4b, 0xe0, 0x70, 0x01, 0x50, 0xa5, 0x00, 0x01, 0x50, 0x73, 0x80, 0x0c, +0x40, 0xa5, 0x00, 0x13, 0x50, 0x94, 0x80, 0x0c, 0x04, 0x3f, 0x80, 0x02, 0x40, 0xf5, 0x0c, 0x06, +0x4e, 0xf3, 0xff, 0xda, 0x50, 0x03, 0x00, 0x20, 0x44, 0x40, 0x00, 0x00, 0x14, 0x40, 0x00, 0x02, +0x14, 0x40, 0x00, 0x00, 0x14, 0x40, 0x00, 0x01, 0x44, 0x10, 0x00, 0x0c, 0x48, 0x00, 0x00, 0x36, +0x58, 0xa0, 0x00, 0x00, 0x3e, 0x2f, 0x4d, 0x34, 0x48, 0x00, 0x00, 0x28, 0x04, 0x13, 0x80, 0x00, +0x54, 0x00, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x0a, 0x04, 0x13, 0x80, 0x01, 0x04, 0x50, 0x80, 0x00, +0x14, 0x54, 0x80, 0x00, 0x48, 0x00, 0x00, 0x12, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x0e, +0x04, 0x03, 0x80, 0x01, 0x14, 0x2f, 0x80, 0x01, 0x40, 0x10, 0xa0, 0x09, 0x4b, 0xe0, 0x08, 0x01, +0x14, 0x04, 0x80, 0x00, 0x04, 0x2f, 0x80, 0x01, 0x50, 0xa5, 0x00, 0x01, 0x50, 0x73, 0x80, 0x0c, +0x40, 0xa5, 0x00, 0x13, 0x50, 0x94, 0x80, 0x0c, 0x04, 0x3f, 0x80, 0x02, 0x40, 0xf5, 0x0c, 0x06, +0x4e, 0xf3, 0xff, 0xd6, 0x58, 0x1e, 0x00, 0x00, 0x00, 0x23, 0x00, 0x06, 0x4e, 0x22, 0x00, 0x08, +0x00, 0x03, 0x00, 0x0b, 0x54, 0x00, 0x00, 0x01, 0x4e, 0x02, 0x00, 0x22, 0x50, 0x00, 0x80, 0x20, +0x44, 0x2f, 0xff, 0xed, 0x44, 0x30, 0x00, 0x0e, 0x12, 0x03, 0x00, 0x00, 0x10, 0x23, 0x00, 0x04, +0x10, 0x33, 0x00, 0x08, 0x44, 0x10, 0x00, 0x01, 0x05, 0xef, 0x80, 0x03, 0x44, 0x4f, 0xe0, 0x00, +0x11, 0xe3, 0x00, 0x05, 0x10, 0x14, 0x00, 0x10, 0x04, 0x54, 0x00, 0x02, 0x58, 0x04, 0x00, 0x00, +0x12, 0x42, 0x80, 0x01, 0x49, 0xff, 0xe9, 0xf4, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x14, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x49, 0x00, 0x00, 0x1a, 0x2e, 0x07, 0xb4, 0x60, 0x4e, 0x02, 0x00, 0x04, 0x49, 0x00, 0x08, 0xfc, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x49, 0x00, 0x09, 0x20, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x3e, 0x7f, 0xc3, 0x78, +0x00, 0x63, 0x80, 0x00, 0x4e, 0x63, 0x00, 0x12, 0x58, 0x13, 0x00, 0x00, 0x44, 0x20, 0x00, 0xa0, +0x50, 0x03, 0x80, 0x08, 0x49, 0xf7, 0xd2, 0xd2, 0x44, 0x20, 0x00, 0x01, 0x10, 0x23, 0x80, 0x00, +0x3c, 0x6f, 0xec, 0xd4, 0x3c, 0x6f, 0xec, 0xd3, 0x46, 0x07, 0xff, 0xff, 0x44, 0x10, 0x00, 0x00, +0x44, 0x20, 0x00, 0x01, 0x58, 0x00, 0x0f, 0xff, 0x49, 0xff, 0xcb, 0xf4, 0x49, 0xf7, 0xcd, 0x4e, +0x3c, 0x0f, 0xf0, 0xdf, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x54, 0x00, 0x80, 0xff, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x22, 0xc0, 0x06, 0x50, 0x00, 0x00, 0x02, +0x48, 0x00, 0x00, 0x08, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x22, 0xc0, 0x06, 0x50, 0x00, 0x7f, 0xfe, +0x54, 0x00, 0x00, 0xff, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x46, 0x10, 0x01, 0x12, 0x2e, 0x07, 0xb4, 0x64, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x0c, +0x44, 0x40, 0x00, 0x00, 0x3e, 0x47, 0xb4, 0x6e, 0x3e, 0x47, 0xb4, 0x64, 0x3e, 0x0f, 0xc4, 0x20, +0x49, 0x00, 0x0f, 0xe0, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x46, 0x00, 0x01, 0x12, 0x2e, 0x27, 0xb4, 0x64, +0x4e, 0x23, 0x00, 0x3e, 0x44, 0x30, 0x00, 0x01, 0x3e, 0x37, 0xb4, 0x64, 0x3e, 0x27, 0xb4, 0x6d, +0x3e, 0x27, 0xb4, 0x6c, 0x46, 0x06, 0x01, 0x00, 0x04, 0x10, 0x00, 0x13, 0x40, 0x50, 0x80, 0x13, +0x46, 0x06, 0x02, 0x04, 0x3c, 0x5f, 0xed, 0x1a, 0x58, 0x00, 0x01, 0x08, 0x40, 0x11, 0x9c, 0x08, +0x44, 0x40, 0x00, 0xc0, 0x3e, 0x27, 0xb4, 0x72, 0x3c, 0x2b, 0xda, 0x38, 0x14, 0x10, 0x00, 0x00, +0x14, 0x40, 0x00, 0x00, 0x14, 0x10, 0x00, 0x00, 0x46, 0x06, 0x01, 0x70, 0x05, 0xe0, 0x00, 0x01, +0x46, 0x1a, 0x00, 0x00, 0x58, 0x5f, 0x00, 0x10, 0x14, 0x50, 0x00, 0x01, 0x14, 0x20, 0x80, 0x5f, +0x3e, 0x37, 0xb4, 0x6e, 0x3e, 0x0f, 0xc4, 0x20, 0x3e, 0x1f, 0x14, 0xf0, 0x49, 0x00, 0x0f, 0x7a, +0x3e, 0x0f, 0xc4, 0x20, 0x44, 0x10, 0x00, 0x65, 0x49, 0x00, 0x10, 0x84, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, +0x2e, 0x17, 0xb3, 0x58, 0x54, 0x90, 0x00, 0xff, 0x4e, 0x13, 0x00, 0x0e, 0x46, 0x15, 0x00, 0x00, +0x58, 0x10, 0x82, 0x08, 0x04, 0x00, 0x80, 0x00, 0x40, 0x00, 0x10, 0x09, 0x40, 0x00, 0x10, 0x08, +0x48, 0x00, 0x00, 0x10, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x12, 0xc0, 0x0e, 0x46, 0x15, 0x00, 0x29, +0x58, 0x10, 0x80, 0x18, 0x04, 0x50, 0x80, 0x00, 0x42, 0x02, 0xd8, 0x09, 0x42, 0x00, 0x5c, 0x09, +0x14, 0x00, 0x80, 0x00, 0x46, 0x88, 0x00, 0xc0, 0x58, 0x84, 0x00, 0x70, 0x05, 0xe4, 0x00, 0x00, +0x46, 0xa6, 0x03, 0x00, 0x58, 0x6f, 0x00, 0x20, 0x14, 0x64, 0x00, 0x00, 0x58, 0xa5, 0x00, 0x7c, +0x05, 0xc4, 0x00, 0x00, 0x46, 0x6a, 0x00, 0x00, 0x42, 0x7e, 0x40, 0x08, 0x14, 0x74, 0x00, 0x00, +0x58, 0x45, 0x00, 0x00, 0x04, 0x75, 0x00, 0x00, 0x59, 0xc4, 0x00, 0x00, 0x44, 0x80, 0x00, 0x00, +0x14, 0x4f, 0x80, 0x01, 0x44, 0x00, 0x00, 0x64, 0x49, 0xff, 0xd4, 0x52, 0x04, 0x4f, 0x80, 0x01, +0x04, 0x32, 0x00, 0x00, 0x04, 0x2e, 0x00, 0x00, 0x42, 0x01, 0x50, 0x0b, 0x46, 0x26, 0x03, 0x00, +0x50, 0x84, 0x00, 0x01, 0x58, 0x21, 0x00, 0x7c, 0x4e, 0x03, 0x00, 0x14, 0x04, 0x53, 0x00, 0x00, +0x58, 0x12, 0x80, 0x02, 0x14, 0x13, 0x00, 0x00, 0x44, 0x50, 0x00, 0x06, 0x04, 0x03, 0x00, 0x00, +0x43, 0xe0, 0x04, 0x09, 0x15, 0xe3, 0x00, 0x00, 0x4c, 0x82, 0xff, 0xdc, 0x48, 0x00, 0x00, 0x4e, +0x46, 0x8a, 0x00, 0x00, 0x04, 0x74, 0x00, 0x00, 0x58, 0xa3, 0x80, 0x02, 0x14, 0xa4, 0x00, 0x00, +0x59, 0xc1, 0x00, 0x00, 0x04, 0x64, 0x00, 0x00, 0x58, 0xa4, 0x00, 0x00, 0x42, 0x43, 0x04, 0x09, +0x14, 0x44, 0x00, 0x00, 0x44, 0x70, 0x00, 0x00, 0x04, 0x61, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0e, +0x04, 0x20, 0x80, 0x00, 0x40, 0x41, 0x9c, 0x01, 0x40, 0x52, 0x40, 0x08, 0x41, 0xe2, 0x88, 0x04, +0x15, 0xe0, 0x80, 0x00, 0x48, 0x00, 0x00, 0x24, 0x44, 0x00, 0x00, 0x05, 0x49, 0xff, 0xd4, 0x08, +0x04, 0x2e, 0x00, 0x00, 0x04, 0x15, 0x00, 0x00, 0x50, 0x73, 0x80, 0x01, 0x54, 0x00, 0x80, 0x04, +0x4e, 0x02, 0x00, 0x06, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x12, 0x44, 0x50, 0x00, 0x64, +0x4c, 0x72, 0xff, 0xec, 0x48, 0x00, 0x00, 0x28, 0x04, 0x40, 0x80, 0x00, 0x40, 0x21, 0x18, 0x01, +0x40, 0x51, 0x40, 0x08, 0x41, 0xe2, 0x90, 0x04, 0x15, 0xe0, 0x80, 0x00, 0x51, 0xff, 0x80, 0x0c, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x1a, 0x00, 0x00, 0x58, 0x10, 0x81, 0x70, +0x04, 0x40, 0x80, 0x00, 0x44, 0x00, 0x00, 0x01, 0x40, 0x90, 0x24, 0x0c, 0x40, 0x94, 0x90, 0x04, +0x14, 0x90, 0x80, 0x00, 0x04, 0x50, 0x80, 0x00, 0x41, 0xe2, 0x80, 0x13, 0x15, 0xe0, 0x80, 0x00, +0x48, 0xff, 0xff, 0xb8, 0x46, 0x1a, 0x00, 0x00, 0x58, 0x10, 0x81, 0x70, 0x04, 0x40, 0x80, 0x00, +0x44, 0x00, 0x00, 0x01, 0x40, 0x50, 0x24, 0x0c, 0x40, 0x92, 0x90, 0x04, 0x14, 0x90, 0x80, 0x00, +0x05, 0xe0, 0x80, 0x00, 0x40, 0x3f, 0x00, 0x13, 0x14, 0x30, 0x80, 0x00, 0x48, 0xff, 0xff, 0xc6, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xec, 0x47, 0xc6, 0x01, 0x20, 0x58, 0xae, 0x00, 0x00, +0x58, 0x95, 0x00, 0x00, 0x58, 0x84, 0x80, 0x00, 0x58, 0x74, 0x00, 0x00, 0x54, 0x10, 0x80, 0xff, +0x40, 0x30, 0x08, 0x09, 0x44, 0x60, 0x00, 0x00, 0x3e, 0x2e, 0xb7, 0x68, 0x48, 0x00, 0x00, 0x28, +0x14, 0x1f, 0x80, 0x02, 0x14, 0x2f, 0x80, 0x01, 0x14, 0x3f, 0x80, 0x03, 0x50, 0x63, 0x00, 0x01, +0x4b, 0xe0, 0x08, 0x01, 0x04, 0x0e, 0x00, 0x42, 0x04, 0x1f, 0x80, 0x02, 0x04, 0x2f, 0x80, 0x01, +0x04, 0x3f, 0x80, 0x03, 0x4e, 0x03, 0x00, 0x14, 0x04, 0x45, 0x00, 0x43, 0x4e, 0x43, 0x00, 0x10, +0x04, 0x54, 0x80, 0x47, 0x4e, 0x53, 0x00, 0x0c, 0x05, 0xe4, 0x00, 0x49, 0x4f, 0xe3, 0x00, 0x08, +0x04, 0x03, 0x80, 0x1c, 0x54, 0x00, 0x00, 0x04, 0x4e, 0x02, 0x00, 0x3e, 0x44, 0x00, 0x00, 0x04, +0x40, 0xf3, 0x0c, 0x06, 0x4e, 0xf3, 0xff, 0xd6, 0x48, 0x00, 0x00, 0x3c, 0x46, 0x4a, 0x00, 0x00, +0x04, 0x32, 0x00, 0x5c, 0x45, 0xe0, 0x00, 0x01, 0x40, 0x5f, 0x04, 0x0c, 0x40, 0x22, 0x8c, 0x04, +0x14, 0x22, 0x00, 0x5c, 0x46, 0x46, 0x01, 0x20, 0x04, 0x02, 0x00, 0x42, 0x4e, 0x03, 0x00, 0x16, +0x58, 0x52, 0x00, 0x00, 0x04, 0x22, 0x80, 0x43, 0x4e, 0x23, 0x00, 0x10, 0x59, 0xe2, 0x00, 0x00, +0x04, 0x3f, 0x00, 0x47, 0x4e, 0x33, 0x00, 0x0a, 0x04, 0x02, 0x00, 0x49, 0x4e, 0x03, 0x00, 0x06, +0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x10, 0x46, 0x2a, 0x00, 0x00, 0x51, 0xe0, 0x80, 0x01, +0x04, 0x31, 0x00, 0x5c, 0x44, 0x00, 0x00, 0x01, 0x40, 0x50, 0x78, 0x0c, 0x40, 0x12, 0x8c, 0x04, +0x14, 0x11, 0x00, 0x5c, 0x51, 0xff, 0x80, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x46, 0x26, 0x01, 0x20, 0x04, 0x41, 0x00, 0x1c, 0x54, 0x02, 0x00, 0x04, 0x4e, 0x03, 0xff, 0xc0, +0x48, 0xff, 0xff, 0xca, 0x3a, 0x6f, 0xa0, 0xbc, 0x51, 0xff, 0xff, 0xb8, 0x46, 0x3f, 0xfe, 0x0f, +0x04, 0x20, 0x80, 0x00, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x41, 0x0c, 0x02, 0x14, 0x40, 0x80, 0x00, +0x58, 0x70, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x05, 0xe0, 0x80, 0x00, 0x40, 0x80, 0x40, 0x08, +0x40, 0x6f, 0x20, 0x04, 0x14, 0x60, 0x80, 0x00, 0x46, 0x4a, 0x00, 0x00, 0x04, 0x50, 0x80, 0x00, +0x14, 0x52, 0x00, 0x09, 0x04, 0x32, 0x00, 0x09, 0x54, 0x21, 0x8f, 0xff, 0x12, 0x2f, 0x80, 0x23, +0x02, 0x0f, 0x80, 0x23, 0x02, 0x13, 0x80, 0x00, 0x4c, 0x10, 0x00, 0x10, 0x02, 0x13, 0x80, 0x00, +0x4e, 0x12, 0x00, 0x0c, 0x02, 0x6f, 0x80, 0x23, 0x44, 0x50, 0x00, 0x00, 0x12, 0x63, 0x80, 0x00, +0x10, 0x53, 0x80, 0x0c, 0x48, 0x00, 0x00, 0xa4, 0x03, 0xe3, 0x80, 0x00, 0x4f, 0xe2, 0x00, 0x96, +0x02, 0x0f, 0x80, 0x23, 0x4e, 0x02, 0x00, 0x8e, 0x02, 0x1f, 0x80, 0x23, 0x04, 0x63, 0x80, 0x01, +0x58, 0x00, 0x80, 0x00, 0x49, 0xf7, 0xd6, 0x0c, 0x00, 0x00, 0x00, 0x04, 0x50, 0x2f, 0x80, 0x28, +0x50, 0x3f, 0x80, 0x34, 0x50, 0x1f, 0x80, 0x04, 0x49, 0xff, 0xd1, 0x06, 0x46, 0x36, 0x01, 0x20, +0x04, 0x21, 0x80, 0x40, 0x44, 0x40, 0x00, 0x02, 0x14, 0x2f, 0x80, 0x10, 0x4c, 0x62, 0x00, 0x32, +0x5e, 0xf3, 0x00, 0x03, 0x4e, 0xf2, 0x00, 0x0a, 0x4e, 0x62, 0x00, 0x12, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x62, 0xc0, 0x52, 0x48, 0x00, 0x00, 0x18, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x62, 0x80, 0x2e, +0x44, 0x50, 0x00, 0x04, 0x4c, 0x62, 0xc0, 0x48, 0x48, 0x00, 0x00, 0x36, 0x04, 0x2f, 0x80, 0x10, +0x54, 0x41, 0x00, 0x0f, 0x14, 0x4f, 0x80, 0x10, 0x04, 0x0f, 0x80, 0x10, 0x56, 0x00, 0x00, 0x0f, +0x48, 0x00, 0x00, 0x0c, 0x04, 0x5f, 0x80, 0x10, 0x54, 0x12, 0x81, 0xe0, 0x14, 0x1f, 0x80, 0x10, +0x04, 0x3f, 0x80, 0x10, 0x56, 0x01, 0x81, 0xe0, 0x5c, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x34, +0x04, 0x0f, 0x80, 0x10, 0x55, 0xe0, 0x3c, 0x00, 0x15, 0xef, 0x80, 0x10, 0x04, 0x8f, 0x80, 0x10, +0x56, 0x04, 0x3c, 0x00, 0x48, 0xff, 0xff, 0xf2, 0x04, 0x2f, 0x80, 0x10, 0x46, 0x30, 0x00, 0xf0, +0x40, 0x41, 0x0c, 0x02, 0x14, 0x4f, 0x80, 0x10, 0x46, 0x3f, 0xff, 0x10, 0x04, 0x0f, 0x80, 0x10, +0x48, 0x00, 0x00, 0x0e, 0x04, 0x8f, 0x80, 0x10, 0x46, 0x10, 0x1e, 0x00, 0x40, 0x54, 0x04, 0x02, +0x14, 0x5f, 0x80, 0x10, 0x46, 0x3f, 0xe2, 0x00, 0x04, 0x0f, 0x80, 0x10, 0x40, 0x00, 0x0c, 0x00, +0x48, 0xff, 0xff, 0xd4, 0x3e, 0x0f, 0x9e, 0xec, 0x3e, 0x1f, 0xa2, 0xa8, 0x49, 0xff, 0xc1, 0x5e, +0x44, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x21, 0x4e, 0x13, 0x00, 0x0c, 0x40, 0xf0, 0x80, 0x06, +0x4e, 0xf2, 0x00, 0x08, 0x01, 0xe3, 0x80, 0x0c, 0x50, 0x0f, 0x00, 0x01, 0x48, 0x00, 0x00, 0x04, +0x44, 0x00, 0x00, 0x00, 0x10, 0x03, 0x80, 0x0c, 0x02, 0x2f, 0x80, 0x23, 0x00, 0x53, 0x80, 0x0c, +0x04, 0x43, 0x80, 0x02, 0x12, 0x23, 0x80, 0x00, 0x4c, 0x52, 0x00, 0x06, 0x44, 0x00, 0x00, 0x05, +0x48, 0x00, 0x01, 0x0c, 0x04, 0x23, 0x80, 0x01, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x22, 0x80, 0x2c, +0x5e, 0xf1, 0x00, 0x03, 0x4e, 0xf2, 0x00, 0x0a, 0x4e, 0x22, 0x00, 0x12, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x22, 0xc0, 0x42, 0x48, 0x00, 0x00, 0x16, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x22, 0x80, 0x26, +0x44, 0x50, 0x00, 0x04, 0x4c, 0x22, 0xc0, 0x38, 0x48, 0x00, 0x00, 0x2a, 0x46, 0x0a, 0x00, 0x00, +0x58, 0x00, 0x01, 0x6c, 0x04, 0x60, 0x00, 0x00, 0x58, 0x13, 0x00, 0x04, 0x48, 0x00, 0x00, 0x28, +0x46, 0x0a, 0x00, 0x00, 0x58, 0x00, 0x01, 0x6c, 0x04, 0x40, 0x00, 0x00, 0x58, 0x12, 0x00, 0x08, +0x48, 0x00, 0x00, 0x1e, 0x46, 0x0a, 0x00, 0x00, 0x58, 0x00, 0x01, 0x6c, 0x04, 0x20, 0x00, 0x00, +0x58, 0x11, 0x00, 0x10, 0x48, 0x00, 0x00, 0x14, 0x46, 0x0a, 0x00, 0x00, 0x58, 0x00, 0x01, 0x6c, +0x04, 0x30, 0x00, 0x00, 0x58, 0x11, 0x80, 0x20, 0x48, 0x00, 0x00, 0x0a, 0x46, 0x0a, 0x00, 0x00, +0x58, 0x00, 0x01, 0x6c, 0x04, 0x50, 0x00, 0x00, 0x58, 0x12, 0x80, 0x40, 0x14, 0x10, 0x00, 0x00, +0x48, 0x00, 0x00, 0x0c, 0x3e, 0x0f, 0x9e, 0xfc, 0x3e, 0x1f, 0xa2, 0x94, 0x49, 0xff, 0xc0, 0xe6, +0x44, 0x0f, 0xff, 0xff, 0x48, 0x00, 0x00, 0xb2, 0x02, 0x0f, 0x80, 0x23, 0x3e, 0x6e, 0x95, 0x44, +0x49, 0xf7, 0xd5, 0x16, 0x58, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x50, 0x2f, 0x80, 0x28, +0x50, 0x3f, 0x80, 0x34, 0x50, 0x1f, 0x80, 0x04, 0x49, 0xff, 0xd0, 0x0e, 0x3e, 0x0f, 0x9f, 0x1c, +0x4b, 0xe0, 0x18, 0x01, 0x02, 0x14, 0x00, 0x00, 0x3e, 0x0f, 0x9f, 0x34, 0x4b, 0xe0, 0x18, 0x01, +0x00, 0x14, 0x00, 0x02, 0x3e, 0x0f, 0x9f, 0x5c, 0x4b, 0xe0, 0x18, 0x01, 0x00, 0x14, 0x00, 0x03, +0x3e, 0x0f, 0x9f, 0x84, 0x4b, 0xe0, 0x18, 0x01, 0x00, 0x14, 0x00, 0x04, 0x3e, 0x0f, 0x9f, 0xb0, +0x4b, 0xe0, 0x18, 0x01, 0x00, 0x14, 0x00, 0x05, 0x3e, 0x0f, 0x9f, 0xd4, 0x4b, 0xe0, 0x18, 0x01, +0x00, 0x14, 0x00, 0x06, 0x3e, 0x0f, 0x9f, 0xfc, 0x4b, 0xe0, 0x18, 0x01, 0x00, 0x14, 0x00, 0x07, +0x3e, 0x0f, 0xa0, 0x24, 0x4b, 0xe0, 0x18, 0x01, 0x00, 0x14, 0x00, 0x08, 0x3e, 0x0f, 0xa0, 0x48, +0x4b, 0xe0, 0x18, 0x01, 0x00, 0x14, 0x00, 0x09, 0x3e, 0x0f, 0xa0, 0x70, 0x4b, 0xe0, 0x18, 0x01, +0x00, 0x14, 0x00, 0x0a, 0x3e, 0x0f, 0xa0, 0x90, 0x4b, 0xe0, 0x18, 0x01, 0x00, 0x14, 0x00, 0x0b, +0x3e, 0x0f, 0xa0, 0xc0, 0x4b, 0xe0, 0x18, 0x01, 0x02, 0x14, 0x00, 0x06, 0x3e, 0x0f, 0xa0, 0xe8, +0x4b, 0xe0, 0x18, 0x01, 0x02, 0x14, 0x00, 0x07, 0x3e, 0x0f, 0xa1, 0x10, 0x4b, 0xe0, 0x18, 0x01, +0x04, 0x14, 0x00, 0x04, 0x3e, 0x0f, 0xa1, 0x30, 0x4b, 0xe0, 0x18, 0x01, 0x00, 0x14, 0x00, 0x14, +0x3e, 0x0f, 0xa1, 0x50, 0x4b, 0xe0, 0x18, 0x01, 0x00, 0x14, 0x00, 0x15, 0x3e, 0x0f, 0xa1, 0x70, +0x4b, 0xe0, 0x18, 0x01, 0x02, 0x14, 0x00, 0x0b, 0x3e, 0x0f, 0xa1, 0x94, 0x4b, 0xe0, 0x18, 0x01, +0x00, 0x14, 0x00, 0x18, 0x3e, 0x0f, 0xa1, 0xb4, 0x4b, 0xe0, 0x18, 0x01, 0x00, 0x14, 0x00, 0x19, +0x3e, 0x0f, 0xa1, 0xd4, 0x4b, 0xe0, 0x18, 0x01, 0x02, 0x14, 0x00, 0x0d, 0x3e, 0x0f, 0xa1, 0xf8, +0x4b, 0xe0, 0x18, 0x01, 0x04, 0x13, 0x80, 0x01, 0x3e, 0x0f, 0xa2, 0x20, 0x4b, 0xe0, 0x18, 0x01, +0x02, 0x13, 0x80, 0x00, 0x3e, 0x0f, 0xa2, 0x34, 0x4b, 0xe0, 0x18, 0x01, 0x02, 0x1f, 0x80, 0x23, +0x3e, 0x0f, 0xa2, 0x48, 0x4b, 0xe0, 0x18, 0x01, 0x00, 0x13, 0x80, 0x0c, 0x3e, 0x0f, 0xa2, 0x5c, +0x4b, 0xe0, 0x18, 0x01, 0x3e, 0x0f, 0xa2, 0x70, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x00, 0x00, 0x00, +0x10, 0x03, 0x80, 0x0c, 0x04, 0x03, 0x80, 0x01, 0x51, 0xff, 0x80, 0x48, 0x3a, 0x6f, 0xa0, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xec, 0x49, 0x00, 0x1f, 0xec, +0x46, 0x36, 0x01, 0x10, 0x04, 0x21, 0x80, 0x36, 0x46, 0x10, 0x0f, 0xf0, 0x40, 0x51, 0x04, 0x02, +0x4c, 0x50, 0x80, 0x78, 0x46, 0x16, 0x02, 0x04, 0x46, 0x60, 0x20, 0x30, 0x58, 0x63, 0x08, 0x00, +0x14, 0x60, 0x80, 0x08, 0x58, 0x00, 0x80, 0x00, 0x04, 0x20, 0x00, 0x3f, 0x44, 0x40, 0x02, 0x00, +0x54, 0x51, 0x0f, 0x00, 0x4c, 0x52, 0x40, 0x66, 0x54, 0x71, 0x00, 0x0f, 0x44, 0x50, 0x00, 0x07, +0x4c, 0x72, 0xc0, 0x60, 0x47, 0xe8, 0x38, 0x30, 0x59, 0xef, 0x02, 0x01, 0x15, 0xe0, 0x80, 0x08, +0x44, 0xa0, 0x00, 0x02, 0x05, 0xc0, 0x00, 0x3f, 0x54, 0x5e, 0x00, 0x1f, 0x4c, 0x55, 0x40, 0x52, +0x46, 0x06, 0x01, 0x20, 0x04, 0x10, 0x00, 0x20, 0x54, 0x20, 0x81, 0x00, 0x4e, 0x22, 0x00, 0x04, +0x44, 0x20, 0x00, 0x01, 0x54, 0x10, 0x82, 0x00, 0x3e, 0x27, 0xb5, 0x13, 0x4e, 0x12, 0x00, 0x04, +0x44, 0x10, 0x00, 0x01, 0x3e, 0x17, 0xb5, 0x14, 0x46, 0x66, 0x01, 0x20, 0x58, 0x63, 0x00, 0x80, +0x04, 0x53, 0x00, 0x00, 0x58, 0x32, 0x83, 0x00, 0x14, 0x33, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, +0x49, 0xff, 0xd0, 0xe6, 0x2e, 0x17, 0xb5, 0x13, 0x4e, 0x13, 0x00, 0x0c, 0x04, 0x83, 0x00, 0x00, +0x42, 0x44, 0x20, 0x09, 0x14, 0x43, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0xd0, 0xd8, +0x2e, 0xa7, 0xb5, 0x14, 0x4e, 0xa3, 0x00, 0x0e, 0x47, 0xe6, 0x01, 0x20, 0x04, 0x2f, 0x00, 0x20, +0x42, 0x11, 0x24, 0x09, 0x14, 0x1f, 0x00, 0x20, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0xd0, 0xc8, +0x46, 0x06, 0x01, 0x20, 0x04, 0x10, 0x00, 0x3f, 0x46, 0x40, 0x0f, 0xf0, 0x40, 0x50, 0x90, 0x02, +0x4c, 0x52, 0x00, 0x08, 0x44, 0x91, 0x00, 0x00, 0x40, 0x80, 0xa4, 0x00, 0x14, 0x80, 0x00, 0x3f, +0x47, 0xc6, 0x01, 0x10, 0x04, 0xae, 0x00, 0x36, 0x44, 0x00, 0x00, 0xff, 0x40, 0x15, 0x60, 0x09, +0x4c, 0x10, 0x00, 0xc8, 0x46, 0x26, 0x01, 0x00, 0x04, 0x61, 0x00, 0x13, 0x45, 0xe0, 0x00, 0xcc, +0x40, 0x63, 0x00, 0x13, 0x4c, 0x1f, 0x00, 0x32, 0x47, 0xc6, 0x00, 0x00, 0x58, 0x0e, 0x00, 0x00, +0x46, 0xa0, 0x30, 0x30, 0x58, 0x80, 0x00, 0x00, 0x46, 0x99, 0x19, 0x19, 0x58, 0xa5, 0x03, 0x03, +0x58, 0x94, 0x81, 0x91, 0x44, 0x50, 0x00, 0x1f, 0x14, 0x5e, 0x00, 0x05, 0x14, 0xa0, 0x00, 0x06, +0x14, 0x94, 0x00, 0x13, 0x58, 0x40, 0x00, 0x00, 0x3c, 0x1d, 0xed, 0x1a, 0x04, 0x02, 0x00, 0x09, +0x4c, 0x60, 0xc0, 0x0e, 0x41, 0xe0, 0x14, 0x02, 0x4f, 0xe2, 0x00, 0x0a, 0x3e, 0x0f, 0xb4, 0x6c, +0x00, 0x50, 0x00, 0x00, 0x50, 0x12, 0x80, 0x01, 0x48, 0x00, 0x00, 0x06, 0x44, 0x10, 0x00, 0x00, +0x3e, 0x0f, 0xb4, 0x6c, 0x10, 0x10, 0x00, 0x00, 0x3c, 0x5d, 0xed, 0x1a, 0x4c, 0x62, 0xc0, 0x08, +0x2e, 0x37, 0xb4, 0x6d, 0x50, 0x11, 0x80, 0x01, 0x48, 0x00, 0x00, 0x04, 0x44, 0x10, 0x00, 0x00, +0x2e, 0x47, 0xb4, 0x6c, 0x3e, 0x17, 0xb4, 0x6d, 0x5c, 0xf2, 0x00, 0x03, 0x4e, 0xf2, 0x00, 0x08, +0x2e, 0x97, 0xb4, 0x6d, 0x5c, 0xf4, 0x80, 0x0a, 0x4e, 0xf3, 0x00, 0x72, 0x44, 0x50, 0x00, 0x00, +0x3e, 0x57, 0xb4, 0x6d, 0x3e, 0x57, 0xb4, 0x6c, 0x47, 0xe6, 0x01, 0x20, 0x05, 0xcf, 0x00, 0x20, +0x54, 0xae, 0x02, 0x00, 0x4e, 0xa3, 0x00, 0x64, 0x58, 0x0f, 0x00, 0x00, 0x04, 0x10, 0x00, 0x3f, +0x44, 0x50, 0x00, 0xff, 0x40, 0x70, 0xe0, 0x09, 0x4c, 0x72, 0x80, 0x08, 0x46, 0x80, 0x10, 0x00, +0x40, 0x40, 0xa0, 0x00, 0x14, 0x40, 0x00, 0x3f, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x00, 0x70, +0x50, 0xa0, 0x00, 0x10, 0x04, 0x90, 0x00, 0x00, 0x04, 0x85, 0x00, 0x00, 0x04, 0x15, 0x00, 0x00, +0x59, 0xc0, 0x00, 0x00, 0x58, 0x20, 0x83, 0x00, 0x14, 0x25, 0x00, 0x00, 0x44, 0x70, 0x00, 0x00, +0x04, 0x50, 0x00, 0x00, 0x59, 0xe2, 0x80, 0x04, 0x15, 0xe0, 0x00, 0x00, 0x44, 0x00, 0x00, 0x05, +0x49, 0xff, 0xd0, 0x1e, 0x04, 0x4e, 0x00, 0x00, 0x50, 0x73, 0x80, 0x01, 0x42, 0x32, 0x08, 0x0b, +0x4e, 0x32, 0x00, 0x08, 0x44, 0x50, 0x00, 0x64, 0x4c, 0x72, 0xff, 0xf2, 0x48, 0x00, 0x03, 0x56, +0x47, 0xe6, 0x01, 0x20, 0x04, 0x5f, 0x00, 0x1c, 0x54, 0x24, 0x80, 0x10, 0x58, 0x91, 0x00, 0x01, +0x40, 0x94, 0x94, 0x04, 0x54, 0x84, 0x01, 0x00, 0x14, 0x9f, 0x00, 0x1c, 0x4e, 0x82, 0x00, 0x0c, +0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x00, 0x80, 0x04, 0x10, 0x00, 0x00, 0x42, 0x10, 0xa4, 0x09, +0x48, 0x00, 0x00, 0x0c, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x00, 0x80, 0x04, 0x40, 0x00, 0x00, +0x45, 0xef, 0xfc, 0xff, 0x40, 0x12, 0x78, 0x02, 0x14, 0x10, 0x00, 0x00, 0x3c, 0x6f, 0xed, 0x1a, +0x46, 0x36, 0x01, 0x10, 0x04, 0x11, 0x80, 0x36, 0x46, 0x20, 0x0f, 0xf0, 0x40, 0x50, 0x88, 0x02, +0x4c, 0x51, 0x00, 0x6c, 0x2e, 0x47, 0xb4, 0x72, 0x4e, 0x43, 0x00, 0x68, 0x46, 0x36, 0x02, 0x04, +0x04, 0x51, 0x80, 0x44, 0x04, 0x21, 0x80, 0x44, 0x40, 0x02, 0xc0, 0x09, 0x44, 0x50, 0xff, 0xff, +0x41, 0xe1, 0x14, 0x02, 0x40, 0x2f, 0x00, 0x00, 0x5c, 0xf1, 0x03, 0xe9, 0x4e, 0xf3, 0x00, 0x56, +0x04, 0x01, 0x80, 0x48, 0x41, 0xe0, 0x14, 0x02, 0x44, 0x50, 0x00, 0x64, 0x42, 0x4f, 0x14, 0x24, +0x40, 0xf2, 0x08, 0x06, 0x4e, 0xf2, 0x00, 0x38, 0x46, 0x66, 0x01, 0x20, 0x58, 0x63, 0x00, 0x80, +0x04, 0x03, 0x00, 0x00, 0x59, 0xe1, 0x80, 0x00, 0x58, 0x30, 0x02, 0x00, 0x14, 0x33, 0x00, 0x00, +0x04, 0x5f, 0x00, 0x01, 0x44, 0x00, 0x00, 0x01, 0x58, 0x12, 0x80, 0x08, 0x14, 0x1f, 0x00, 0x01, +0x49, 0xff, 0xcf, 0xa6, 0x46, 0x06, 0x02, 0x04, 0x44, 0x40, 0x00, 0xc0, 0x44, 0x20, 0x00, 0x80, +0x14, 0x40, 0x00, 0x42, 0x14, 0x20, 0x00, 0x42, 0x04, 0x53, 0x00, 0x00, 0x46, 0x06, 0x01, 0x20, +0x42, 0x12, 0xa4, 0x09, 0x14, 0x13, 0x00, 0x00, 0x58, 0x00, 0x00, 0xfc, 0x04, 0x10, 0x00, 0x00, +0x44, 0x50, 0xff, 0x00, 0x40, 0x20, 0x94, 0x02, 0x4c, 0x22, 0x80, 0x18, 0x50, 0x10, 0x81, 0x00, +0x48, 0x00, 0x00, 0x12, 0x45, 0xe0, 0x00, 0x01, 0x3f, 0xe7, 0xb4, 0x72, 0x46, 0x06, 0x02, 0x00, +0x58, 0x00, 0x06, 0xf8, 0x04, 0x20, 0x00, 0x00, 0x46, 0x4f, 0xff, 0x0f, 0x58, 0x42, 0x0f, 0xff, +0x40, 0x11, 0x10, 0x02, 0x14, 0x10, 0x00, 0x00, 0x3c, 0x0d, 0xed, 0x1d, 0x50, 0x10, 0x00, 0x01, +0x54, 0x50, 0x80, 0x01, 0x3c, 0x1f, 0xed, 0x1d, 0x4e, 0x52, 0x00, 0xc6, 0x46, 0x0a, 0x00, 0x00, +0x58, 0x00, 0x01, 0x6c, 0x04, 0x40, 0x00, 0x00, 0x54, 0x22, 0x00, 0x04, 0x4e, 0x23, 0x00, 0xbc, +0x04, 0x50, 0x00, 0x00, 0x55, 0xe2, 0x80, 0x08, 0x4f, 0xe3, 0x00, 0xb6, 0x04, 0x10, 0x00, 0x00, +0x54, 0x30, 0x80, 0x10, 0x4e, 0x33, 0x00, 0xb0, 0x04, 0x40, 0x00, 0x00, 0x54, 0x22, 0x00, 0x20, +0x4e, 0x23, 0x00, 0xaa, 0x04, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x4e, 0x03, 0x00, 0xa4, +0x10, 0x0f, 0x80, 0x0f, 0x47, 0xea, 0x00, 0x00, 0x14, 0x0f, 0x80, 0x02, 0x04, 0x4f, 0x00, 0x88, +0x54, 0x22, 0x00, 0x1f, 0x14, 0x2f, 0x80, 0x02, 0x04, 0x1f, 0x80, 0x02, 0x56, 0x30, 0x80, 0x1f, +0x5c, 0x51, 0x80, 0x01, 0x10, 0x5f, 0x80, 0x0f, 0x01, 0xef, 0x80, 0x0f, 0x4f, 0xe3, 0x00, 0x1e, +0x46, 0x3a, 0x00, 0x00, 0x04, 0x51, 0x80, 0x09, 0x14, 0x5f, 0x80, 0x02, 0x05, 0xef, 0x80, 0x02, +0x42, 0x4f, 0x5c, 0x09, 0x14, 0x4f, 0x80, 0x02, 0x04, 0x2f, 0x80, 0x02, 0x42, 0x31, 0x54, 0x09, +0x42, 0x31, 0xd8, 0x09, 0x14, 0x3f, 0x80, 0x02, 0x04, 0x5f, 0x80, 0x02, 0x42, 0x02, 0xd8, 0x08, +0x14, 0x0f, 0x80, 0x02, 0x48, 0x00, 0x00, 0x16, 0x3c, 0x0b, 0xd8, 0xa6, 0x3e, 0x07, 0xb1, 0x98, +0x3c, 0x0b, 0xd8, 0xae, 0x3e, 0x07, 0xb1, 0x58, 0x3c, 0x0b, 0xd8, 0xb6, 0x3e, 0x07, 0xb1, 0x68, +0x3c, 0x0b, 0xd8, 0xbe, 0x3e, 0x07, 0xb1, 0x78, 0x3c, 0x0b, 0xd8, 0xc6, 0x3e, 0x07, 0xb1, 0x88, +0x46, 0x2a, 0x00, 0x00, 0x04, 0x11, 0x00, 0x88, 0x54, 0x30, 0x80, 0x01, 0x10, 0x3f, 0x80, 0x0f, +0x00, 0x0f, 0x80, 0x0f, 0x4e, 0x03, 0x00, 0x08, 0x3e, 0x0f, 0xb1, 0x4c, 0x50, 0x1f, 0x80, 0x08, +0x49, 0xff, 0xfb, 0xc2, 0x46, 0x0a, 0x00, 0x00, 0x04, 0x50, 0x00, 0x88, 0x42, 0x42, 0x84, 0x0b, +0x10, 0x4f, 0x80, 0x0f, 0x01, 0xef, 0x80, 0x0f, 0x4f, 0xe3, 0x00, 0x08, 0x3e, 0x0f, 0xb1, 0x5c, +0x50, 0x1f, 0x80, 0x08, 0x49, 0xff, 0xfb, 0xb0, 0x47, 0xea, 0x00, 0x00, 0x04, 0x2f, 0x00, 0x88, +0x42, 0x11, 0x08, 0x0b, 0x10, 0x1f, 0x80, 0x0f, 0x00, 0x3f, 0x80, 0x0f, 0x4e, 0x33, 0x00, 0x08, +0x3e, 0x0f, 0xb1, 0x6c, 0x50, 0x1f, 0x80, 0x08, 0x49, 0xff, 0xfb, 0x9e, 0x46, 0x3a, 0x00, 0x00, +0x04, 0x01, 0x80, 0x88, 0x42, 0x50, 0x0c, 0x0b, 0x10, 0x5f, 0x80, 0x0f, 0x00, 0x4f, 0x80, 0x0f, +0x4e, 0x43, 0x00, 0x08, 0x3e, 0x0f, 0xb1, 0x7c, 0x50, 0x1f, 0x80, 0x08, 0x49, 0xff, 0xfb, 0x8c, +0x46, 0x4a, 0x00, 0x00, 0x05, 0xe2, 0x00, 0x88, 0x42, 0x2f, 0x10, 0x0b, 0x10, 0x2f, 0x80, 0x0f, +0x00, 0x1f, 0x80, 0x0f, 0x4e, 0x13, 0x00, 0x08, 0x3e, 0x0f, 0xb1, 0x8c, 0x50, 0x1f, 0x80, 0x08, +0x49, 0xff, 0xfb, 0x7a, 0x46, 0x0a, 0x00, 0x00, 0x58, 0x00, 0x01, 0x6c, 0x04, 0x30, 0x00, 0x00, +0x54, 0x51, 0x80, 0x01, 0x4e, 0x52, 0x01, 0xd0, 0x04, 0x10, 0x00, 0x00, 0x46, 0xaa, 0x00, 0x00, +0x42, 0x90, 0x80, 0x09, 0x44, 0x10, 0x00, 0x00, 0x14, 0x90, 0x00, 0x00, 0x46, 0x66, 0x01, 0x20, +0x14, 0x15, 0x00, 0x5c, 0x59, 0xe3, 0x00, 0x00, 0x58, 0x63, 0x00, 0x70, 0x04, 0xa3, 0x00, 0x00, +0x04, 0x93, 0x00, 0x00, 0x04, 0x4f, 0x00, 0x20, 0x58, 0x2f, 0x00, 0x00, 0x58, 0x32, 0x03, 0x00, +0x14, 0x3f, 0x00, 0x20, 0x04, 0x53, 0x00, 0x00, 0x59, 0xe1, 0x00, 0x00, 0x58, 0x02, 0x80, 0x04, +0x14, 0x03, 0x00, 0x00, 0x46, 0x57, 0xff, 0xf7, 0x04, 0x41, 0x00, 0x42, 0x58, 0x52, 0x8f, 0xff, +0x40, 0x32, 0x14, 0x04, 0x14, 0x31, 0x00, 0x42, 0x04, 0x0f, 0x00, 0x43, 0x58, 0x61, 0x00, 0x00, +0x40, 0x40, 0x14, 0x04, 0x14, 0x4f, 0x00, 0x43, 0x04, 0x33, 0x00, 0x47, 0x46, 0x47, 0xff, 0xf0, +0x58, 0x42, 0x00, 0x0f, 0x40, 0x01, 0x90, 0x04, 0x14, 0x03, 0x00, 0x47, 0x04, 0x51, 0x00, 0x49, +0x41, 0xe2, 0x90, 0x04, 0x15, 0xe1, 0x00, 0x49, 0x44, 0x00, 0x00, 0x64, 0x49, 0xff, 0xfa, 0x9a, +0x4e, 0x02, 0x00, 0x24, 0x44, 0x00, 0x00, 0x02, 0x49, 0xff, 0xf9, 0xb0, 0x4e, 0x02, 0x00, 0x04, +0x48, 0x00, 0x01, 0x88, 0x44, 0x00, 0x00, 0x64, 0x44, 0x10, 0x00, 0x04, 0x49, 0xff, 0xfa, 0x8a, +0x4e, 0x02, 0x00, 0x14, 0x44, 0x00, 0x00, 0x06, 0x49, 0xff, 0xf9, 0xa0, 0x4e, 0x02, 0x00, 0x04, +0x48, 0x00, 0x01, 0x78, 0x44, 0x00, 0x01, 0xf4, 0x44, 0x10, 0x00, 0x08, 0x49, 0xff, 0xfa, 0x7a, +0x4e, 0x02, 0x00, 0x04, 0x48, 0x00, 0x01, 0x6e, 0x44, 0x00, 0x00, 0x0a, 0x49, 0xff, 0xf9, 0x8e, +0x4e, 0x02, 0x00, 0x04, 0x48, 0x00, 0x01, 0x66, 0x47, 0xc6, 0x03, 0x00, 0x59, 0xce, 0x00, 0x7c, +0x46, 0x78, 0x00, 0xc0, 0x04, 0x6e, 0x00, 0x00, 0x58, 0x3e, 0x00, 0x00, 0x58, 0x80, 0x00, 0x00, +0x3f, 0xce, 0xb7, 0x68, 0x14, 0x3f, 0x80, 0x01, 0x44, 0x00, 0x00, 0x05, 0x4b, 0xe0, 0x70, 0x01, +0x04, 0x3f, 0x80, 0x01, 0x04, 0x21, 0x80, 0x00, 0x04, 0x43, 0x80, 0x1c, 0x46, 0x18, 0x00, 0xc0, +0x42, 0x02, 0x50, 0x0b, 0x50, 0x84, 0x00, 0x01, 0x58, 0x10, 0x80, 0x70, 0x4e, 0x03, 0x00, 0x08, +0x45, 0xe0, 0x00, 0x64, 0x4c, 0x8f, 0x7f, 0xe8, 0x48, 0x00, 0x01, 0x46, 0x04, 0x60, 0x80, 0x00, +0x42, 0x83, 0x44, 0x08, 0x14, 0x80, 0x80, 0x00, 0x2e, 0x27, 0xb3, 0x58, 0x4e, 0x22, 0x00, 0x10, +0x48, 0x00, 0x00, 0x2c, 0x04, 0x10, 0x00, 0x00, 0x40, 0x41, 0x18, 0x01, 0x40, 0x22, 0x40, 0x08, +0x40, 0x31, 0x04, 0x04, 0x14, 0x30, 0x00, 0x00, 0x48, 0x00, 0x01, 0x24, 0x46, 0x05, 0x00, 0x00, +0x05, 0xe0, 0x00, 0x82, 0x58, 0x61, 0x00, 0x00, 0x42, 0x5f, 0x60, 0x08, 0x14, 0x50, 0x00, 0x82, +0x58, 0x80, 0x80, 0x00, 0x44, 0x00, 0x00, 0x05, 0x49, 0xff, 0xcd, 0xd2, 0x04, 0x24, 0x00, 0x00, +0x42, 0x31, 0x54, 0x0b, 0x50, 0x63, 0x00, 0x01, 0x4e, 0x33, 0x00, 0x4c, 0x44, 0x50, 0x00, 0x64, +0x4c, 0x62, 0xff, 0xf2, 0x48, 0x00, 0x01, 0x22, 0x44, 0x70, 0x00, 0x01, 0x4c, 0x23, 0xc0, 0x42, +0x46, 0x45, 0x00, 0x22, 0x44, 0x7e, 0xff, 0xfe, 0x14, 0x72, 0x02, 0x01, 0x46, 0x85, 0x00, 0x29, +0x04, 0x14, 0x00, 0x05, 0x46, 0x68, 0x00, 0xc0, 0x58, 0x20, 0x80, 0x60, 0x14, 0x24, 0x00, 0x05, +0x58, 0x63, 0x00, 0x6c, 0x05, 0xe3, 0x00, 0x00, 0x40, 0x5f, 0x20, 0x09, 0x40, 0x52, 0xa0, 0x08, +0x58, 0x02, 0x80, 0x04, 0x58, 0x83, 0x00, 0x00, 0x14, 0x03, 0x00, 0x00, 0x44, 0x60, 0x00, 0x00, +0x44, 0x00, 0x00, 0x05, 0x49, 0xff, 0xcd, 0x9c, 0x04, 0x04, 0x00, 0x00, 0x50, 0x63, 0x00, 0x01, +0x4e, 0x04, 0x00, 0x08, 0x44, 0x50, 0x00, 0x64, 0x4c, 0x62, 0xff, 0xf4, 0x48, 0x00, 0x00, 0xee, +0x46, 0x25, 0x00, 0x22, 0x44, 0x10, 0x00, 0x00, 0x14, 0x11, 0x02, 0x01, 0x46, 0x65, 0x00, 0x29, +0x04, 0x33, 0x00, 0x05, 0x44, 0x8f, 0xff, 0x9f, 0x41, 0xe1, 0xa0, 0x02, 0x15, 0xe3, 0x00, 0x05, +0x46, 0x48, 0x00, 0xc0, 0x58, 0x42, 0x00, 0x70, 0x04, 0x62, 0x00, 0x00, 0x42, 0x73, 0x40, 0x09, +0x14, 0x72, 0x00, 0x00, 0x04, 0x52, 0x00, 0x00, 0x58, 0x82, 0x00, 0x00, 0x42, 0x02, 0xc4, 0x09, +0x14, 0x02, 0x00, 0x00, 0x44, 0x60, 0x00, 0x00, 0x44, 0x00, 0x00, 0x05, 0x49, 0xff, 0xcd, 0x68, +0x04, 0x14, 0x00, 0x00, 0x46, 0x08, 0x00, 0xc0, 0x54, 0x20, 0x82, 0x00, 0x50, 0x63, 0x00, 0x01, +0x4e, 0x23, 0x00, 0x08, 0x44, 0x50, 0x00, 0x64, 0x4c, 0x62, 0xff, 0xf0, 0x48, 0x00, 0x00, 0xc2, +0x04, 0x20, 0x00, 0x1c, 0x42, 0x31, 0x14, 0x09, 0x14, 0x30, 0x00, 0x1c, 0x46, 0x75, 0x00, 0x00, +0x58, 0x73, 0x85, 0x94, 0x05, 0xe3, 0x80, 0x00, 0x58, 0x8f, 0x01, 0x00, 0x14, 0x83, 0x80, 0x00, +0x46, 0x0a, 0x00, 0x00, 0x04, 0x43, 0x80, 0x00, 0x42, 0x62, 0x20, 0x09, 0x14, 0x63, 0x80, 0x00, +0x04, 0x10, 0x00, 0x00, 0x58, 0x80, 0x00, 0x00, 0x58, 0x20, 0x80, 0x02, 0x14, 0x20, 0x00, 0x00, +0x44, 0x60, 0x00, 0x00, 0x05, 0xe0, 0x00, 0x00, 0x42, 0x5f, 0x04, 0x09, 0x14, 0x50, 0x00, 0x00, +0x44, 0x00, 0x00, 0x05, 0x49, 0xff, 0xcd, 0x2c, 0x04, 0x44, 0x00, 0x00, 0x50, 0x63, 0x00, 0x01, +0x54, 0x02, 0x00, 0x04, 0x4e, 0x03, 0x00, 0x08, 0x44, 0x50, 0x00, 0x64, 0x4c, 0x62, 0xff, 0xf2, +0x48, 0x00, 0x00, 0x94, 0x47, 0xe6, 0x01, 0x20, 0x59, 0xef, 0x00, 0x70, 0x04, 0x0f, 0x00, 0x00, +0x54, 0x55, 0x01, 0x80, 0x58, 0x10, 0x00, 0x01, 0x14, 0x1f, 0x00, 0x00, 0x54, 0x34, 0x80, 0x10, +0x04, 0x4f, 0x00, 0x00, 0x46, 0x16, 0x01, 0x20, 0x40, 0x22, 0x90, 0x04, 0x40, 0x01, 0x0c, 0x04, +0x14, 0x0f, 0x00, 0x00, 0x04, 0x50, 0x80, 0x20, 0x44, 0x4f, 0xfc, 0xff, 0x40, 0x22, 0x90, 0x02, +0x14, 0x20, 0x80, 0x20, 0x59, 0xe0, 0x80, 0x00, 0x04, 0x3f, 0x00, 0x40, 0x46, 0x57, 0xff, 0xf7, +0x58, 0x52, 0x8f, 0xff, 0x40, 0x01, 0x94, 0x04, 0x14, 0x0f, 0x00, 0x40, 0x04, 0x20, 0x80, 0x41, +0x59, 0xe0, 0x80, 0x00, 0x40, 0x41, 0x14, 0x04, 0x14, 0x40, 0x80, 0x41, 0x04, 0x0f, 0x00, 0x46, +0x46, 0x37, 0xff, 0xff, 0x58, 0x31, 0x8c, 0x0f, 0x40, 0x20, 0x0c, 0x04, 0x14, 0x2f, 0x00, 0x46, +0x04, 0x50, 0x80, 0x48, 0x46, 0x47, 0xff, 0xf0, 0x58, 0x42, 0x00, 0x0f, 0x40, 0x02, 0x90, 0x04, +0x14, 0x00, 0x80, 0x48, 0x47, 0xea, 0x00, 0x00, 0x04, 0x2f, 0x00, 0x5b, 0x58, 0x31, 0x00, 0x02, +0x14, 0x3f, 0x00, 0x5b, 0x46, 0x2a, 0x00, 0x00, 0x05, 0xe1, 0x00, 0x5f, 0x4f, 0xe2, 0x00, 0x0a, +0x2e, 0x37, 0xb4, 0x6e, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x32, 0xc0, 0x04, 0x49, 0xff, 0xb9, 0x80, +0x3e, 0x0f, 0xc4, 0x20, 0x48, 0x00, 0x00, 0x3e, 0x3e, 0x0f, 0xa2, 0x84, 0x49, 0xff, 0xbb, 0xa6, +0x48, 0xff, 0xfc, 0xa8, 0x46, 0x0a, 0x00, 0x00, 0x58, 0x00, 0x01, 0x70, 0x04, 0x50, 0x00, 0x00, +0x58, 0x32, 0x90, 0x00, 0x14, 0x30, 0x00, 0x00, 0x05, 0xe0, 0x00, 0x00, 0x40, 0x1f, 0x00, 0x13, +0x14, 0x10, 0x00, 0x00, 0x48, 0xff, 0xfe, 0xb8, 0x46, 0x1a, 0x00, 0x00, 0x58, 0x10, 0x81, 0x70, +0x04, 0x20, 0x80, 0x00, 0x3e, 0x0f, 0xc4, 0x20, 0x58, 0x21, 0x20, 0x00, 0x48, 0x00, 0x00, 0x18, +0x46, 0x1a, 0x00, 0x00, 0x58, 0x10, 0x81, 0x70, 0x04, 0x40, 0x80, 0x00, 0x3e, 0x0f, 0xc4, 0x20, +0x58, 0x22, 0x40, 0x00, 0x48, 0x00, 0x00, 0x0c, 0x46, 0x1a, 0x00, 0x00, 0x58, 0x10, 0x81, 0x70, +0x05, 0xe0, 0x80, 0x00, 0x3e, 0x0f, 0xc4, 0x20, 0x42, 0x2f, 0x3c, 0x08, 0x14, 0x20, 0x80, 0x00, +0x44, 0x10, 0x00, 0x65, 0x49, 0x00, 0x08, 0x5e, 0x51, 0xff, 0x80, 0x14, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x54, 0x00, 0x80, 0xff, +0x58, 0x11, 0x00, 0x00, 0x54, 0x21, 0x80, 0xff, 0x54, 0x32, 0x00, 0xff, 0x58, 0x42, 0x80, 0x00, +0x49, 0x00, 0x39, 0x4a, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x49, 0x00, 0x3b, 0x60, +0x2e, 0x50, 0x02, 0x87, 0x44, 0x20, 0x00, 0x01, 0x4c, 0x51, 0x00, 0x06, 0x3e, 0x20, 0x02, 0x87, +0x49, 0x00, 0x1d, 0x14, 0x49, 0x00, 0x12, 0x6c, 0x2e, 0x07, 0xb4, 0xf4, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0x80, 0x0a, 0x2e, 0x57, 0xb2, 0xea, 0x4e, 0x53, 0x00, 0x08, 0x2e, 0x17, 0xb2, 0xeb, +0x4e, 0x13, 0x00, 0x04, 0x49, 0x00, 0x16, 0xde, 0x49, 0x00, 0x2b, 0xae, 0x49, 0x00, 0x00, 0xf0, +0x49, 0x00, 0x05, 0xd2, 0x49, 0xff, 0xf7, 0x4e, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x49, 0x00, 0x0e, 0xe0, +0x46, 0x00, 0x01, 0x17, 0x2e, 0x10, 0x02, 0x87, 0x4e, 0x12, 0x00, 0x06, 0x44, 0x20, 0x00, 0x00, +0x3e, 0x20, 0x02, 0x87, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x58, 0x70, 0x80, 0x00, 0x49, 0x00, 0x16, 0xae, +0x58, 0x60, 0x00, 0x00, 0x49, 0x00, 0x21, 0xcc, 0x50, 0x63, 0x7f, 0xff, 0x58, 0x03, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x4e, 0x63, 0xff, 0xfa, 0x49, 0x00, 0x21, 0x80, 0x58, 0x03, 0x00, 0x00, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x04, 0x10, 0x00, 0x02, 0x44, 0x20, 0x00, 0x01, 0x50, 0x10, 0x80, 0x20, +0x00, 0x30, 0x80, 0x00, 0x4c, 0x31, 0x00, 0x04, 0x48, 0x00, 0x00, 0x42, 0x00, 0x40, 0x80, 0x04, +0x04, 0x20, 0x80, 0x02, 0x4c, 0x41, 0xc0, 0x6e, 0x44, 0x50, 0x00, 0x06, 0x4c, 0x22, 0x80, 0x4e, +0x5c, 0xf1, 0x00, 0x07, 0x4e, 0xf2, 0x00, 0x14, 0x44, 0x10, 0x00, 0x02, 0x4c, 0x20, 0x80, 0x34, +0x40, 0xf1, 0x04, 0x06, 0x4e, 0xf3, 0x00, 0x2c, 0x44, 0x50, 0x00, 0x04, 0x4c, 0x22, 0x80, 0x28, +0x5c, 0xf1, 0x00, 0x05, 0x4e, 0xf2, 0x00, 0x32, 0x48, 0x00, 0x00, 0x2a, 0x44, 0x50, 0x00, 0x0a, +0x4c, 0x22, 0x80, 0x3c, 0x5c, 0xf1, 0x00, 0x0b, 0x4e, 0xf2, 0x00, 0x0c, 0x44, 0x10, 0x00, 0x08, +0x4c, 0x20, 0x80, 0x16, 0x44, 0x50, 0x00, 0x09, 0x4c, 0x22, 0xc0, 0x44, 0x48, 0x00, 0x00, 0x2a, +0x44, 0x10, 0x00, 0x0c, 0x4c, 0x20, 0x80, 0x34, 0x40, 0xf1, 0x04, 0x06, 0x4e, 0xf3, 0x00, 0x2a, +0x44, 0x50, 0x00, 0x0d, 0x4c, 0x22, 0xc0, 0x36, 0x48, 0x00, 0x00, 0x2e, 0x44, 0x00, 0x00, 0x00, +0x48, 0x00, 0x00, 0x32, 0x3e, 0x1f, 0x8b, 0xc8, 0x48, 0x00, 0x00, 0x28, 0x3e, 0x1f, 0x6d, 0xd4, +0x44, 0x20, 0x00, 0x03, 0x48, 0x00, 0x00, 0x06, 0x3e, 0x1f, 0x81, 0xb4, 0x44, 0x20, 0x00, 0x05, +0x49, 0xff, 0xff, 0x80, 0x48, 0x00, 0x00, 0x20, 0x3e, 0x1f, 0x81, 0xb4, 0x48, 0x00, 0x00, 0x16, +0x3e, 0x1f, 0x63, 0x04, 0x48, 0x00, 0x00, 0x12, 0x3e, 0x1f, 0x7d, 0x04, 0x48, 0x00, 0x00, 0x0e, +0x3e, 0x1f, 0x77, 0x58, 0x44, 0x20, 0x00, 0x0b, 0x48, 0x00, 0x00, 0x08, 0x3e, 0x1f, 0x85, 0x08, +0x48, 0x00, 0x00, 0x04, 0x3e, 0x1f, 0x8a, 0x3c, 0x49, 0xff, 0xff, 0x64, 0x48, 0x00, 0x00, 0x04, +0x44, 0x01, 0x00, 0x03, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x44, 0x50, 0x00, 0xff, 0x54, 0x00, 0x00, 0xff, 0x54, 0x10, 0x80, 0xff, 0x54, 0x21, 0x00, 0xff, +0x40, 0x31, 0x80, 0x10, 0x40, 0x42, 0x00, 0x10, 0x4c, 0x02, 0x80, 0x08, 0x40, 0x00, 0x00, 0x10, +0x3e, 0x07, 0xb1, 0x9c, 0x3e, 0x07, 0xb1, 0xa4, 0x58, 0x02, 0x80, 0x00, 0x4c, 0x10, 0x00, 0x04, +0x3e, 0x17, 0xb1, 0xb0, 0x58, 0x10, 0x00, 0x00, 0x4c, 0x20, 0x80, 0x04, 0x3e, 0x27, 0xb1, 0xaf, +0x3e, 0x47, 0xb1, 0xbc, 0x3e, 0x37, 0xb1, 0xbb, 0x4a, 0x00, 0x78, 0x20, 0x3e, 0x0f, 0xb0, 0xd8, +0x00, 0x30, 0x00, 0x07, 0x00, 0x20, 0x00, 0x05, 0x40, 0x41, 0x80, 0x10, 0x00, 0x10, 0x00, 0x06, +0x4e, 0x44, 0x00, 0x06, 0x54, 0x31, 0x80, 0x7f, 0x48, 0x00, 0x00, 0x04, 0x44, 0x30, 0x00, 0x34, +0x3e, 0x37, 0xb3, 0x59, 0x2e, 0x57, 0xb1, 0x1f, 0x50, 0x42, 0x80, 0x1c, 0x40, 0x51, 0x00, 0x10, +0x3e, 0x47, 0xb3, 0x5a, 0x4e, 0x54, 0x00, 0x26, 0x46, 0x08, 0x00, 0x22, 0x54, 0x30, 0x80, 0xe0, +0x54, 0x41, 0x00, 0x38, 0x40, 0x51, 0xa4, 0x08, 0x40, 0x32, 0x50, 0x08, 0x04, 0x40, 0x00, 0x0a, +0x40, 0x32, 0x8c, 0x04, 0x54, 0x51, 0x00, 0x07, 0x40, 0x31, 0x90, 0x04, 0x40, 0x42, 0xd0, 0x08, +0x40, 0x21, 0x90, 0x04, 0x54, 0x10, 0x80, 0x1f, 0x14, 0x20, 0x00, 0x0a, 0x5c, 0xf0, 0x80, 0x11, +0x4e, 0xf3, 0x00, 0x0a, 0x50, 0x10, 0xff, 0xe0, 0x40, 0x10, 0x80, 0x10, 0x48, 0x00, 0x00, 0x04, +0x44, 0x10, 0x00, 0x00, 0x3e, 0x17, 0xb3, 0x5b, 0x44, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, +0x54, 0x00, 0x00, 0xff, 0x4e, 0x02, 0x00, 0x70, 0x2e, 0x37, 0xb2, 0xea, 0x44, 0x20, 0x00, 0x01, +0x3e, 0x27, 0xb1, 0xad, 0x4e, 0x33, 0x00, 0x06, 0x2e, 0x17, 0xb2, 0xeb, 0x4e, 0x12, 0x00, 0x2a, +0x46, 0x06, 0x02, 0x00, 0x04, 0x40, 0x01, 0x48, 0x46, 0x3f, 0xf0, 0x00, 0x40, 0x22, 0x0c, 0x02, +0x46, 0x40, 0x0a, 0xdf, 0x58, 0x42, 0x04, 0x80, 0x40, 0x51, 0x10, 0x04, 0x14, 0x50, 0x01, 0x48, +0x46, 0x16, 0x02, 0x01, 0x04, 0x20, 0x81, 0x48, 0x46, 0x06, 0x02, 0x00, 0x40, 0x51, 0x0c, 0x02, +0x40, 0x22, 0x90, 0x04, 0x14, 0x20, 0x81, 0x48, 0x58, 0x00, 0x00, 0xfc, 0x04, 0x50, 0x00, 0x00, +0x46, 0x3f, 0xff, 0x00, 0x58, 0x31, 0x80, 0xff, 0x40, 0x12, 0x8c, 0x02, 0x48, 0x00, 0x00, 0xc2, +0x46, 0x06, 0x02, 0x00, 0x04, 0x40, 0x01, 0x48, 0x3c, 0x2d, 0xf1, 0x14, 0x40, 0x12, 0x60, 0x09, +0x40, 0x10, 0xe0, 0x08, 0x40, 0x50, 0x88, 0x04, 0x14, 0x50, 0x01, 0x48, 0x46, 0x56, 0x02, 0x01, +0x04, 0x12, 0x81, 0x48, 0x40, 0x30, 0xe0, 0x09, 0x40, 0x31, 0xe0, 0x08, 0x40, 0x21, 0x88, 0x04, +0x14, 0x22, 0x81, 0x48, 0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x00, 0xfc, 0x2e, 0x17, 0xc4, 0x5c, +0x04, 0x20, 0x00, 0x00, 0x44, 0x4f, 0xc0, 0xff, 0x40, 0x30, 0xa0, 0x08, 0x40, 0x51, 0x10, 0x02, +0x40, 0x41, 0x94, 0x04, 0x14, 0x40, 0x00, 0x00, 0x46, 0x3f, 0xff, 0x03, 0x04, 0x20, 0x00, 0x00, +0x58, 0x31, 0x8f, 0xff, 0x40, 0x10, 0xb8, 0x08, 0x40, 0x51, 0x0c, 0x02, 0x40, 0x10, 0x94, 0x04, +0x48, 0x00, 0x00, 0x88, 0x2e, 0x07, 0xb2, 0xea, 0x44, 0x50, 0x00, 0x01, 0x3e, 0x57, 0xb1, 0xae, +0x4e, 0x03, 0x00, 0x06, 0x2e, 0x17, 0xb2, 0xeb, 0x4e, 0x12, 0x00, 0x2a, 0x46, 0x06, 0x02, 0x00, +0x04, 0x30, 0x01, 0x48, 0x46, 0x4f, 0xf0, 0x00, 0x40, 0x11, 0x90, 0x02, 0x46, 0x30, 0x0b, 0x20, +0x58, 0x31, 0x84, 0xc1, 0x40, 0x20, 0x8c, 0x04, 0x14, 0x20, 0x01, 0x48, 0x46, 0x56, 0x02, 0x01, +0x04, 0x12, 0x81, 0x48, 0x46, 0x06, 0x02, 0x00, 0x40, 0x20, 0x90, 0x02, 0x40, 0x11, 0x0c, 0x04, +0x14, 0x12, 0x81, 0x48, 0x58, 0x00, 0x00, 0xfc, 0x04, 0x30, 0x00, 0x00, 0x46, 0x2f, 0xff, 0x00, +0x58, 0x21, 0x00, 0xff, 0x40, 0x11, 0x88, 0x02, 0x48, 0x00, 0x00, 0x3a, 0x46, 0x06, 0x02, 0x00, +0x04, 0x40, 0x01, 0x48, 0x3c, 0x2d, 0xf1, 0x15, 0x40, 0x12, 0x60, 0x09, 0x40, 0x10, 0xe0, 0x08, +0x40, 0x50, 0x88, 0x04, 0x14, 0x50, 0x01, 0x48, 0x46, 0x56, 0x02, 0x01, 0x04, 0x12, 0x81, 0x48, +0x40, 0x30, 0xe0, 0x09, 0x40, 0x31, 0xe0, 0x08, 0x40, 0x21, 0x88, 0x04, 0x14, 0x22, 0x81, 0x48, +0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x00, 0xfc, 0x2e, 0x17, 0xc4, 0x5d, 0x04, 0x50, 0x00, 0x00, +0x44, 0x4f, 0xc0, 0xff, 0x40, 0x30, 0xa0, 0x08, 0x40, 0x22, 0x90, 0x02, 0x40, 0x51, 0x88, 0x04, +0x14, 0x50, 0x00, 0x00, 0x46, 0x3f, 0xff, 0x03, 0x04, 0x20, 0x00, 0x00, 0x58, 0x31, 0x8f, 0xff, +0x40, 0x50, 0xb8, 0x08, 0x40, 0x41, 0x0c, 0x02, 0x40, 0x12, 0x90, 0x04, 0x14, 0x10, 0x00, 0x00, +0x2e, 0x07, 0xb4, 0xf1, 0x4e, 0x02, 0x00, 0x18, 0x46, 0x36, 0x02, 0x00, 0x04, 0x51, 0x83, 0x44, +0x46, 0x40, 0x0f, 0xff, 0x58, 0x42, 0x0f, 0xff, 0x40, 0x22, 0x90, 0x02, 0x46, 0x06, 0x02, 0x01, +0x14, 0x21, 0x83, 0x44, 0x58, 0x00, 0x0d, 0x10, 0x04, 0x10, 0x00, 0x00, 0x40, 0x10, 0x90, 0x02, +0x14, 0x10, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x54, 0x00, 0x00, 0xff, 0x4e, 0x02, 0x00, 0x8a, +0x2e, 0x37, 0xb2, 0xea, 0x44, 0x20, 0x00, 0x01, 0x3e, 0x27, 0xb1, 0xb9, 0x4e, 0x33, 0x00, 0x06, +0x2e, 0x17, 0xb2, 0xeb, 0x4e, 0x12, 0x00, 0x2a, 0x46, 0x06, 0x02, 0x00, 0x04, 0x40, 0x01, 0x48, +0x46, 0x3f, 0xf0, 0x00, 0x40, 0x22, 0x0c, 0x02, 0x46, 0x40, 0x0b, 0x20, 0x58, 0x42, 0x04, 0xc1, +0x40, 0x51, 0x10, 0x04, 0x14, 0x50, 0x01, 0x48, 0x46, 0x16, 0x02, 0x01, 0x04, 0x20, 0x81, 0x48, +0x46, 0x06, 0x02, 0x00, 0x40, 0x51, 0x0c, 0x02, 0x40, 0x22, 0x90, 0x04, 0x14, 0x20, 0x81, 0x48, +0x58, 0x00, 0x00, 0xfc, 0x04, 0x50, 0x00, 0x00, 0x46, 0x3f, 0xff, 0x00, 0x58, 0x31, 0x80, 0xff, +0x40, 0x12, 0x8c, 0x02, 0x48, 0x00, 0x00, 0x3a, 0x46, 0x06, 0x02, 0x00, 0x04, 0x40, 0x01, 0x48, +0x3c, 0x2d, 0xf1, 0x15, 0x40, 0x12, 0x60, 0x09, 0x40, 0x10, 0xe0, 0x08, 0x40, 0x50, 0x88, 0x04, +0x14, 0x50, 0x01, 0x48, 0x46, 0x56, 0x02, 0x01, 0x04, 0x12, 0x81, 0x48, 0x40, 0x30, 0xe0, 0x09, +0x40, 0x31, 0xe0, 0x08, 0x40, 0x21, 0x88, 0x04, 0x14, 0x22, 0x81, 0x48, 0x46, 0x06, 0x02, 0x00, +0x58, 0x00, 0x00, 0xfc, 0x2e, 0x17, 0xc4, 0x5d, 0x04, 0x20, 0x00, 0x00, 0x44, 0x4f, 0xc0, 0xff, +0x40, 0x30, 0xa0, 0x08, 0x40, 0x51, 0x10, 0x02, 0x40, 0x41, 0x94, 0x04, 0x14, 0x40, 0x00, 0x00, +0x46, 0x3f, 0xff, 0x03, 0x04, 0x20, 0x00, 0x00, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x10, 0xb8, 0x08, +0x40, 0x51, 0x0c, 0x02, 0x40, 0x10, 0x94, 0x04, 0x14, 0x10, 0x00, 0x00, 0x2e, 0x07, 0xb4, 0xf1, +0x4e, 0x02, 0x00, 0x86, 0x46, 0x36, 0x02, 0x00, 0x04, 0x51, 0x83, 0x44, 0x46, 0x40, 0x0f, 0xff, +0x58, 0x42, 0x0f, 0xff, 0x40, 0x22, 0x90, 0x02, 0x46, 0x06, 0x02, 0x01, 0x14, 0x21, 0x83, 0x44, +0x58, 0x00, 0x0d, 0x10, 0x04, 0x10, 0x00, 0x00, 0x40, 0x10, 0x90, 0x02, 0x48, 0x00, 0x00, 0x6e, +0x2e, 0x07, 0xb2, 0xea, 0x44, 0x40, 0x00, 0x01, 0x3e, 0x47, 0xb1, 0xba, 0x4e, 0x03, 0x00, 0x06, +0x2e, 0x17, 0xb2, 0xeb, 0x4e, 0x12, 0x00, 0x2a, 0x46, 0x06, 0x02, 0x00, 0x04, 0x40, 0x01, 0x48, +0x46, 0x3f, 0xf0, 0x00, 0x40, 0x22, 0x0c, 0x02, 0x46, 0x40, 0x0b, 0x61, 0x58, 0x42, 0x05, 0x02, +0x40, 0x51, 0x10, 0x04, 0x14, 0x50, 0x01, 0x48, 0x46, 0x16, 0x02, 0x01, 0x04, 0x20, 0x81, 0x48, +0x46, 0x06, 0x02, 0x00, 0x40, 0x51, 0x0c, 0x02, 0x40, 0x32, 0x90, 0x04, 0x14, 0x30, 0x81, 0x48, +0x58, 0x00, 0x00, 0xfc, 0x04, 0x50, 0x00, 0x00, 0x46, 0x2f, 0xff, 0x00, 0x58, 0x21, 0x00, 0xff, +0x40, 0x12, 0x88, 0x02, 0x48, 0x00, 0x00, 0x3a, 0x46, 0x06, 0x02, 0x00, 0x04, 0x40, 0x01, 0x48, +0x3c, 0x2d, 0xf1, 0x16, 0x40, 0x12, 0x60, 0x09, 0x40, 0x10, 0xe0, 0x08, 0x40, 0x50, 0x88, 0x04, +0x14, 0x50, 0x01, 0x48, 0x46, 0x56, 0x02, 0x01, 0x04, 0x12, 0x81, 0x48, 0x40, 0x30, 0xe0, 0x09, +0x40, 0x31, 0xe0, 0x08, 0x40, 0x21, 0x88, 0x04, 0x14, 0x22, 0x81, 0x48, 0x46, 0x06, 0x02, 0x00, +0x58, 0x00, 0x00, 0xfc, 0x2e, 0x17, 0xc4, 0x5e, 0x04, 0x20, 0x00, 0x00, 0x44, 0x4f, 0xc0, 0xff, +0x40, 0x30, 0xa0, 0x08, 0x40, 0x51, 0x10, 0x02, 0x40, 0x41, 0x94, 0x04, 0x14, 0x40, 0x00, 0x00, +0x46, 0x3f, 0xff, 0x03, 0x04, 0x20, 0x00, 0x00, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x10, 0xb8, 0x08, +0x40, 0x51, 0x0c, 0x02, 0x40, 0x10, 0x94, 0x04, 0x14, 0x10, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, +0x46, 0x28, 0x00, 0x22, 0x04, 0x11, 0x00, 0x00, 0x54, 0x00, 0xff, 0x00, 0x40, 0x00, 0x20, 0x09, +0x4a, 0x00, 0x78, 0x20, 0x46, 0x48, 0x00, 0x22, 0x04, 0x12, 0x00, 0x00, 0x42, 0x50, 0xcc, 0x09, +0x14, 0x52, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x04, 0x30, 0x00, 0x06, 0x46, 0x2f, 0xee, 0xef, +0x58, 0x21, 0x0f, 0xff, 0x40, 0x11, 0x88, 0x02, 0x14, 0x10, 0x00, 0x06, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x46, 0x48, 0x00, 0x22, 0x04, 0x12, 0x00, 0x00, +0x2e, 0x57, 0xb3, 0x59, 0x55, 0xe0, 0xff, 0x00, 0x2e, 0x2f, 0xb3, 0x5b, 0x40, 0x4f, 0x20, 0x09, +0x40, 0x12, 0x14, 0x01, 0x50, 0x31, 0x00, 0x38, 0x42, 0x50, 0x8c, 0x24, 0x45, 0xe0, 0x00, 0x1e, +0x40, 0x32, 0xf8, 0x57, 0x2e, 0x27, 0xb3, 0x5a, 0x54, 0x00, 0x00, 0xff, 0x40, 0x11, 0x88, 0x00, +0x40, 0x10, 0x80, 0x10, 0x49, 0xff, 0xe5, 0x6e, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x2e, 0x07, 0xb4, 0xe6, +0x3e, 0x1f, 0xb1, 0x34, 0x49, 0xff, 0xea, 0x66, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xd4, 0x44, 0x70, 0x00, 0x00, +0x46, 0x68, 0x00, 0x22, 0x58, 0x83, 0x80, 0x00, 0x58, 0x93, 0x80, 0x00, 0x59, 0xcf, 0x80, 0x00, +0x04, 0x43, 0x00, 0x00, 0x46, 0x20, 0x00, 0xc0, 0x40, 0x12, 0x08, 0x04, 0x14, 0x13, 0x00, 0x00, +0x44, 0x00, 0x00, 0x01, 0x49, 0xf7, 0xc1, 0x30, 0x04, 0x13, 0x00, 0x00, 0x40, 0x00, 0xbc, 0x08, +0x40, 0x00, 0x7c, 0x09, 0x4e, 0x03, 0x00, 0x40, 0x54, 0x70, 0xff, 0x00, 0x40, 0x73, 0xa0, 0x09, +0x54, 0x00, 0x80, 0x7f, 0x40, 0xf3, 0x80, 0x06, 0x4e, 0xf2, 0x00, 0x06, 0x40, 0x20, 0x1c, 0x01, +0x48, 0x00, 0x00, 0x04, 0x40, 0x23, 0x80, 0x01, 0x54, 0x51, 0x00, 0xff, 0x5c, 0xf2, 0x80, 0x03, +0x4e, 0xf2, 0x00, 0x04, 0x4e, 0x03, 0x00, 0x3e, 0x04, 0x53, 0x00, 0x00, 0x42, 0x22, 0xc8, 0x09, +0x42, 0x21, 0x4c, 0x09, 0x14, 0x23, 0x00, 0x00, 0x40, 0x00, 0x20, 0x08, 0x04, 0x43, 0x00, 0x00, +0x42, 0x32, 0x4c, 0x08, 0x41, 0xe1, 0x80, 0x04, 0x15, 0xe3, 0x00, 0x00, 0x5c, 0xf4, 0x83, 0xde, +0x4e, 0xf3, 0x00, 0x0a, 0x5c, 0xf4, 0x00, 0x0a, 0x4e, 0xf2, 0x00, 0x06, 0x38, 0x1e, 0x22, 0x0a, +0x50, 0x84, 0x00, 0x01, 0x04, 0x33, 0x00, 0x00, 0x42, 0x01, 0xc8, 0x09, 0x42, 0x00, 0x4c, 0x09, +0x14, 0x03, 0x00, 0x00, 0x50, 0x94, 0x80, 0x01, 0x44, 0x40, 0x03, 0xe8, 0x4c, 0x92, 0x7f, 0xaa, +0x48, 0x00, 0x00, 0x18, 0x0c, 0x24, 0x80, 0x01, 0x50, 0x63, 0x00, 0x01, 0x4b, 0xe0, 0x28, 0x01, +0x58, 0x13, 0x00, 0x00, 0x3e, 0x0f, 0xa2, 0xe8, 0x40, 0xf3, 0x20, 0x06, 0x4e, 0xf3, 0xff, 0xf4, +0x58, 0x03, 0x80, 0x00, 0x51, 0xff, 0x80, 0x2c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3e, 0x6e, 0x95, 0x44, 0x3e, 0x0f, 0xa2, 0xfc, 0x4b, 0xe0, 0x18, 0x01, 0x58, 0xa3, 0x00, 0x00, +0x58, 0x9f, 0x80, 0x00, 0x44, 0x60, 0x00, 0x00, 0x48, 0xff, 0xff, 0xe4, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x40, 0x21, 0x00, 0x10, 0x54, 0x10, 0x80, 0xff, 0x4e, 0x26, 0x00, 0x0c, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0xa2, 0xbc, 0x44, 0x20, 0x07, 0x35, 0x49, 0xff, 0xb6, 0xfe, +0x48, 0x00, 0x00, 0x00, 0x2f, 0xef, 0xb3, 0x5b, 0x44, 0x40, 0x00, 0x1e, 0x42, 0x51, 0x10, 0x24, +0x50, 0x4f, 0x00, 0x38, 0x40, 0x22, 0x90, 0x76, 0x54, 0x21, 0x00, 0xff, 0x52, 0x31, 0x00, 0x7f, +0x40, 0xf1, 0x84, 0x07, 0x4e, 0xf3, 0x00, 0x0a, 0x40, 0x51, 0x04, 0x00, 0x10, 0x50, 0x00, 0x04, +0x44, 0x30, 0x00, 0x01, 0x48, 0x00, 0x00, 0x04, 0x44, 0x30, 0x00, 0x00, 0x10, 0x30, 0x00, 0x02, +0x40, 0xf0, 0x88, 0x06, 0x4e, 0xf3, 0x00, 0x0c, 0x40, 0x10, 0x88, 0x01, 0x44, 0x20, 0x00, 0x01, +0x10, 0x20, 0x00, 0x01, 0x10, 0x10, 0x00, 0x03, 0x48, 0x00, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x00, +0x11, 0xe0, 0x00, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xa0, 0xbc, 0x54, 0x00, 0x00, 0xff, 0x2e, 0x67, 0xb4, 0xed, 0x2e, 0x77, 0xb4, 0xec, +0x3c, 0x83, 0xda, 0x72, 0x4e, 0x02, 0x00, 0x06, 0x2e, 0x17, 0xb1, 0xa4, 0x48, 0x00, 0x00, 0x04, +0x2e, 0x17, 0xb1, 0xa3, 0x2e, 0x2f, 0xb1, 0x9c, 0x3e, 0x0f, 0xb1, 0xa0, 0x49, 0xff, 0xff, 0xa0, +0x3e, 0x0f, 0xa3, 0x14, 0x49, 0xff, 0xb6, 0xaa, 0x2e, 0x27, 0xb5, 0x0c, 0x44, 0x40, 0x00, 0x01, +0x4c, 0x22, 0x40, 0x0a, 0x46, 0x10, 0x10, 0x08, 0x58, 0x10, 0x82, 0xd0, 0x44, 0x00, 0x00, 0x44, +0x49, 0x00, 0x12, 0x76, 0x49, 0x00, 0x27, 0x20, 0x44, 0x20, 0x00, 0x00, 0x54, 0x04, 0x00, 0xff, +0x58, 0x13, 0x80, 0x00, 0x58, 0x43, 0x00, 0x00, 0x58, 0x31, 0x00, 0x00, 0x49, 0x00, 0x34, 0x84, +0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x46, 0x08, 0x00, 0x22, 0x04, 0x10, 0x00, 0x00, 0x3e, 0x0f, 0xc4, 0x38, 0x54, 0x70, 0xff, 0x00, +0x20, 0x10, 0x00, 0x02, 0x40, 0x73, 0xa0, 0x09, 0x40, 0xf3, 0x84, 0x07, 0x4e, 0xf3, 0x00, 0x4a, +0x3e, 0x9f, 0xb1, 0xa2, 0x44, 0x80, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x50, 0x64, 0x80, 0x06, +0x59, 0xc4, 0x00, 0x00, 0x00, 0x24, 0x80, 0x00, 0x4e, 0x22, 0x00, 0x2e, 0x20, 0x34, 0x80, 0x02, +0x2e, 0x4f, 0xc4, 0x3a, 0x50, 0x54, 0x7f, 0xfb, 0x54, 0x22, 0x80, 0xff, 0x40, 0xf2, 0x0c, 0x07, +0x4e, 0xf3, 0x00, 0x22, 0x04, 0x13, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, 0x4e, 0x12, 0x00, 0x1c, +0x5c, 0xf1, 0x00, 0x0f, 0x4e, 0xf2, 0x00, 0x04, 0x48, 0x00, 0x00, 0x4e, 0x44, 0x50, 0x00, 0x03, +0x4c, 0x82, 0xc0, 0x0c, 0x44, 0x00, 0x00, 0x01, 0x3e, 0x07, 0xb1, 0xd1, 0x3f, 0xc7, 0xb1, 0xc6, +0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x04, 0x11, 0xc4, 0x80, 0x00, 0x04, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x08, 0x01, 0x50, 0x84, 0x00, 0x01, 0x54, 0x84, 0x00, 0xff, 0x44, 0x50, 0x00, 0x14, +0x50, 0x94, 0x80, 0x0c, 0x50, 0x63, 0x00, 0x0c, 0x4c, 0x82, 0xff, 0xc6, 0x48, 0x00, 0x00, 0x50, +0x20, 0x10, 0x00, 0x01, 0x40, 0xf0, 0x9c, 0x07, 0x4e, 0xf3, 0x00, 0x4a, 0x3e, 0x9f, 0xb1, 0xa1, +0x44, 0x80, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x50, 0x64, 0x80, 0x07, 0x59, 0xc4, 0x00, 0x00, +0x00, 0x44, 0x80, 0x00, 0x4e, 0x42, 0x00, 0x30, 0x21, 0xe4, 0x80, 0x02, 0x2e, 0x5f, 0xc4, 0x39, +0x50, 0x14, 0x7f, 0xfb, 0x54, 0x20, 0x80, 0xff, 0x40, 0xff, 0x14, 0x07, 0x4e, 0xf3, 0x00, 0x24, +0x04, 0x13, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x1e, 0x5c, 0xf1, 0x00, 0x0f, +0x4e, 0xf2, 0x00, 0x06, 0x4b, 0xe0, 0x04, 0x01, 0x48, 0x00, 0x00, 0x22, 0x44, 0x50, 0x00, 0x04, +0x4c, 0x82, 0xc0, 0x0c, 0x44, 0x30, 0x00, 0x01, 0x3e, 0x37, 0xb1, 0xc6, 0x3f, 0xc7, 0xb1, 0xd1, +0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x04, 0x11, 0xc4, 0x80, 0x00, 0x04, 0x43, 0x00, 0x00, +0x4b, 0xe0, 0x10, 0x01, 0x50, 0x84, 0x00, 0x01, 0x54, 0x84, 0x00, 0xff, 0x44, 0x50, 0x00, 0x14, +0x50, 0x94, 0x80, 0x0c, 0x50, 0x63, 0x00, 0x0c, 0x4c, 0x82, 0xff, 0xc4, 0x2e, 0x47, 0xb4, 0xf2, +0x44, 0x10, 0x00, 0x00, 0x3e, 0x0f, 0xb1, 0xa3, 0x44, 0x20, 0x00, 0xfb, 0x44, 0x60, 0x00, 0x7f, +0x5c, 0xf1, 0x00, 0x0f, 0x4e, 0xf2, 0x00, 0x08, 0x4e, 0x42, 0x00, 0x40, 0x00, 0x30, 0x7f, 0xff, +0x48, 0x00, 0x00, 0x0c, 0x50, 0x31, 0x00, 0x02, 0x55, 0xe1, 0x80, 0xff, 0x00, 0x30, 0x7f, 0xff, +0x5c, 0xff, 0x00, 0x02, 0x4e, 0xf2, 0x00, 0x20, 0x4e, 0x32, 0x00, 0x0c, 0x20, 0x30, 0x00, 0x01, +0x40, 0xf1, 0x98, 0x07, 0x4e, 0xf2, 0x00, 0x06, 0x40, 0xf3, 0x8c, 0x07, 0x4e, 0xf3, 0x00, 0x04, +0x58, 0x33, 0x00, 0x00, 0x00, 0x50, 0x7f, 0xfe, 0x4e, 0x52, 0x00, 0x24, 0x20, 0x50, 0x00, 0x00, +0x40, 0xf0, 0x94, 0x07, 0x4e, 0xf2, 0x00, 0x1e, 0x40, 0xf2, 0x9c, 0x07, 0x4e, 0xf2, 0x00, 0x1a, +0x48, 0x00, 0x00, 0x1a, 0x4e, 0x32, 0x00, 0x08, 0x21, 0xe0, 0x00, 0x01, 0x42, 0x6f, 0x18, 0x01, +0x40, 0x63, 0x00, 0x10, 0x00, 0x30, 0x7f, 0xfe, 0x4e, 0x32, 0x00, 0x08, 0x20, 0x50, 0x00, 0x00, +0x40, 0xf0, 0x94, 0x07, 0x4e, 0xf3, 0x00, 0x0a, 0x58, 0x50, 0x80, 0x00, 0x48, 0x00, 0x00, 0x06, +0x58, 0x50, 0x80, 0x00, 0x58, 0x61, 0x80, 0x00, 0x50, 0x21, 0x00, 0x01, 0x54, 0x21, 0x00, 0xff, +0x44, 0x10, 0x00, 0x0f, 0x50, 0x00, 0x00, 0x0c, 0x4c, 0x20, 0x80, 0x06, 0x58, 0x12, 0x80, 0x00, +0x48, 0xff, 0xff, 0xa8, 0x3e, 0x57, 0xc4, 0x39, 0x3e, 0x67, 0xc4, 0x3a, 0x54, 0x23, 0x00, 0xff, +0x54, 0x32, 0x80, 0xff, 0x44, 0x10, 0x00, 0x7f, 0x44, 0x40, 0x00, 0x1e, 0x44, 0x00, 0x00, 0x02, +0x49, 0xff, 0xce, 0xa8, 0x46, 0x48, 0x00, 0x22, 0x04, 0x12, 0x00, 0x07, 0x46, 0x30, 0x11, 0x10, +0x40, 0x50, 0x8c, 0x04, 0x14, 0x52, 0x00, 0x07, 0x44, 0x00, 0x00, 0x01, 0x49, 0xf7, 0xbb, 0x46, +0x44, 0x00, 0x00, 0x01, 0x49, 0xf7, 0xbb, 0x1a, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x49, 0xff, 0xfd, 0xb4, +0x58, 0x90, 0x00, 0x00, 0x3e, 0x2f, 0xb1, 0x00, 0x3e, 0x3f, 0xb1, 0xdf, 0x28, 0x11, 0x00, 0x01, +0x3e, 0x0f, 0xb1, 0x08, 0x10, 0x11, 0x80, 0x01, 0x10, 0x11, 0x80, 0x00, 0x50, 0x31, 0x80, 0x0c, +0x4c, 0x20, 0x7f, 0xf6, 0x50, 0x01, 0x00, 0x02, 0x3e, 0x2f, 0xb2, 0x3f, 0x28, 0x40, 0x00, 0x01, +0x3e, 0x3f, 0xb1, 0x11, 0x10, 0x41, 0x00, 0x01, 0x10, 0x41, 0x00, 0x00, 0x50, 0x21, 0x00, 0x0c, +0x4c, 0x01, 0xff, 0xf6, 0x3e, 0x6f, 0xb1, 0xa0, 0x2f, 0xcf, 0xb3, 0x5a, 0x21, 0xe3, 0x00, 0x1c, +0x20, 0x83, 0x00, 0x0f, 0x20, 0x13, 0x00, 0x10, 0x20, 0x73, 0x00, 0x1b, 0x44, 0x20, 0x00, 0x1e, +0x40, 0xaf, 0x70, 0x01, 0x2f, 0xef, 0xb3, 0x5b, 0x40, 0x44, 0x70, 0x01, 0x40, 0x50, 0xf0, 0x01, +0x40, 0x33, 0xf0, 0x01, 0x42, 0x15, 0x08, 0x24, 0x42, 0x82, 0x08, 0x24, 0x42, 0x71, 0x88, 0x24, +0x50, 0x3f, 0x00, 0x38, 0x40, 0xa0, 0x8c, 0x16, 0x42, 0x52, 0x88, 0x24, 0x2e, 0x2f, 0xb1, 0x9c, +0x2f, 0xe7, 0xb3, 0x59, 0x58, 0x14, 0x80, 0x00, 0x58, 0x03, 0x00, 0x00, 0x40, 0x84, 0x0f, 0x96, +0x40, 0x4f, 0x28, 0x00, 0x10, 0x43, 0x00, 0x1c, 0x40, 0x42, 0x8d, 0x56, 0x40, 0xaf, 0x20, 0x00, +0x10, 0xa3, 0x00, 0x0f, 0x40, 0x83, 0x8c, 0xf6, 0x40, 0x7f, 0x10, 0x00, 0x10, 0x73, 0x00, 0x10, +0x44, 0x70, 0x00, 0x01, 0x40, 0x5f, 0x20, 0x00, 0x10, 0x53, 0x00, 0x1b, 0x44, 0x80, 0x00, 0xfb, +0x49, 0xff, 0xfd, 0xd6, 0x44, 0x30, 0x00, 0x00, 0x2e, 0xa7, 0xb4, 0xf2, 0x58, 0x01, 0x80, 0x00, +0x50, 0x23, 0x00, 0x03, 0x44, 0x60, 0x00, 0x7f, 0x5c, 0xf4, 0x00, 0x0f, 0x4e, 0xf2, 0x00, 0x20, +0x4e, 0xa2, 0x00, 0x42, 0x20, 0x41, 0x00, 0x01, 0x10, 0x71, 0x7f, 0xff, 0x10, 0x71, 0x7f, 0xfe, +0x40, 0xf2, 0x18, 0x07, 0x4e, 0xf2, 0x00, 0x06, 0x40, 0xf4, 0x90, 0x07, 0x4e, 0xf3, 0x00, 0x04, +0x58, 0x43, 0x00, 0x00, 0x20, 0x51, 0x00, 0x00, 0x40, 0xf1, 0x94, 0x07, 0x4e, 0xf2, 0x00, 0x30, +0x40, 0xf2, 0xa4, 0x07, 0x4e, 0xf2, 0x00, 0x2c, 0x48, 0x00, 0x00, 0x2c, 0x20, 0x11, 0x7f, 0xfd, +0x4e, 0x17, 0x00, 0x08, 0x10, 0x71, 0x7f, 0xff, 0x10, 0x01, 0x7f, 0xfe, 0x48, 0x00, 0x00, 0x08, +0x4e, 0x12, 0x00, 0x06, 0x10, 0x01, 0x7f, 0xff, 0x10, 0x71, 0x7f, 0xfe, 0x00, 0x51, 0x7f, 0xff, +0x4e, 0x52, 0x00, 0x08, 0x20, 0x41, 0x00, 0x01, 0x42, 0x62, 0x18, 0x01, 0x40, 0x63, 0x00, 0x10, +0x00, 0x11, 0x7f, 0xfe, 0x4e, 0x12, 0x00, 0x08, 0x20, 0x51, 0x00, 0x00, 0x40, 0xf1, 0x94, 0x07, +0x4e, 0xf3, 0x00, 0x0a, 0x58, 0x51, 0x80, 0x00, 0x48, 0x00, 0x00, 0x06, 0x58, 0x51, 0x80, 0x00, +0x58, 0x62, 0x00, 0x00, 0x50, 0x84, 0x00, 0x01, 0x54, 0x84, 0x00, 0xff, 0x45, 0xe0, 0x00, 0x0f, +0x50, 0x21, 0x00, 0x0c, 0x4c, 0x8f, 0x00, 0x06, 0x58, 0x32, 0x80, 0x00, 0x48, 0xff, 0xff, 0xa6, +0x3e, 0x57, 0xc4, 0x39, 0x3e, 0x67, 0xc4, 0x3a, 0x54, 0x32, 0x80, 0xff, 0x40, 0x4f, 0x04, 0x08, +0x54, 0x23, 0x00, 0xff, 0x44, 0x10, 0x00, 0x7f, 0x44, 0x00, 0x00, 0x02, 0x49, 0xff, 0xcd, 0xaa, +0x3e, 0x2f, 0xa3, 0x28, 0x44, 0x00, 0x00, 0x01, 0x3e, 0x1f, 0x2c, 0xd8, 0x49, 0xf7, 0xb9, 0xaa, +0x44, 0x00, 0x00, 0x01, 0x44, 0x10, 0x00, 0x00, 0x49, 0xf7, 0xb9, 0xcc, 0x46, 0x58, 0x00, 0x22, +0x04, 0x42, 0x80, 0x07, 0x46, 0x30, 0x11, 0x10, 0x40, 0x22, 0x0c, 0x04, 0x14, 0x22, 0x80, 0x07, +0x58, 0x02, 0x80, 0x00, 0x04, 0x10, 0x00, 0x06, 0x58, 0x50, 0x00, 0x00, 0x40, 0x40, 0x8c, 0x04, +0x14, 0x40, 0x00, 0x06, 0x04, 0x32, 0x80, 0x00, 0x44, 0x00, 0x00, 0x01, 0x42, 0x21, 0xcc, 0x08, +0x14, 0x22, 0x80, 0x00, 0x49, 0xf7, 0xba, 0x2a, 0x44, 0x00, 0x00, 0x01, 0x49, 0xf7, 0xb9, 0xfe, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x44, 0x00, 0x00, 0x01, 0x49, 0xf7, 0xb9, 0xc8, 0x44, 0x10, 0x00, 0x77, +0x44, 0x20, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, 0x49, 0xf7, 0xe7, 0xec, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3c, 0x0d, 0xed, 0x3f, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x4e, 0x03, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, +0x3e, 0x1f, 0xa3, 0x30, 0x44, 0x20, 0x00, 0xda, 0x49, 0xff, 0xb4, 0x10, 0x48, 0x00, 0x00, 0x00, +0x44, 0x30, 0x00, 0x00, 0x14, 0x20, 0x00, 0x04, 0x14, 0x30, 0x00, 0x01, 0x14, 0x10, 0x00, 0x05, +0x14, 0x30, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x4e, 0x03, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, +0x3e, 0x1f, 0xa3, 0x30, 0x44, 0x20, 0x01, 0x0a, 0x49, 0xff, 0xb3, 0xf0, 0x48, 0x00, 0x00, 0x00, +0x04, 0x10, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x1e, 0x04, 0x50, 0x00, 0x01, 0x44, 0x40, 0x00, 0x00, +0x14, 0x50, 0x80, 0x01, 0x14, 0x12, 0x80, 0x00, 0x14, 0x40, 0x00, 0x00, 0x14, 0x40, 0x00, 0x01, +0x3e, 0x0f, 0xc4, 0x3c, 0x04, 0x30, 0x00, 0x02, 0x04, 0x10, 0x00, 0x00, 0x50, 0x21, 0xff, 0xff, +0x14, 0x20, 0x00, 0x02, 0x4c, 0x10, 0x40, 0x06, 0x04, 0x00, 0x80, 0x03, 0x49, 0xf7, 0xbc, 0xb6, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x3c, 0x1d, 0xf1, 0x12, 0x58, 0x70, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x14, +0x58, 0x00, 0x80, 0x00, 0x49, 0xf7, 0xbc, 0xa2, 0x44, 0x00, 0x03, 0xe8, 0x42, 0x33, 0x80, 0x24, +0x44, 0x20, 0x7f, 0xff, 0x40, 0x11, 0x88, 0x00, 0x3c, 0x0d, 0xf1, 0x12, 0x40, 0x10, 0xbc, 0x09, +0x49, 0xf7, 0xbd, 0x86, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x49, 0xf7, 0xbc, 0xe0, 0x46, 0x17, 0xff, 0xff, +0x58, 0x10, 0x8f, 0xff, 0x58, 0x80, 0x00, 0x00, 0x40, 0xa0, 0x04, 0x00, 0x46, 0x00, 0x01, 0xe0, +0x3e, 0x2f, 0xc4, 0x3c, 0x14, 0xa1, 0x00, 0x04, 0x58, 0x71, 0x00, 0x00, 0x04, 0x61, 0x00, 0x00, +0x41, 0xc4, 0x00, 0x00, 0x48, 0x00, 0x00, 0x5c, 0x4e, 0x63, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, +0x3e, 0x1f, 0xa3, 0x30, 0x44, 0x20, 0x01, 0x7d, 0x49, 0xff, 0xb3, 0x80, 0x48, 0x00, 0x00, 0x00, +0x04, 0x03, 0x00, 0x02, 0x40, 0x34, 0x00, 0x01, 0x4e, 0x35, 0x00, 0x3c, 0x04, 0x43, 0x00, 0x00, +0x4e, 0x43, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0xa3, 0x30, 0x44, 0x20, 0x01, 0x81, +0x49, 0xff, 0xb3, 0x6c, 0x48, 0x00, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x49, 0xff, 0xff, 0x6a, +0x02, 0x03, 0x00, 0x06, 0x4e, 0x02, 0x00, 0x1a, 0x50, 0x00, 0x7f, 0xff, 0x12, 0x03, 0x00, 0x06, +0x15, 0xc3, 0x00, 0x02, 0x05, 0xe3, 0x80, 0x01, 0x14, 0x63, 0x80, 0x01, 0x14, 0x73, 0x00, 0x00, +0x15, 0xe3, 0x00, 0x01, 0x14, 0x6f, 0x00, 0x00, 0x04, 0x63, 0x80, 0x02, 0x50, 0x53, 0x00, 0x01, +0x14, 0x53, 0x80, 0x02, 0x48, 0x00, 0x00, 0x0a, 0x04, 0x13, 0x00, 0x05, 0x4e, 0x12, 0x00, 0x06, +0x04, 0x03, 0x00, 0x04, 0x4b, 0xe0, 0x04, 0x01, 0x14, 0xa3, 0x80, 0x04, 0x48, 0x00, 0x00, 0x0e, +0x04, 0x23, 0x80, 0x04, 0x40, 0x90, 0x08, 0x01, 0x4e, 0x95, 0x00, 0x04, 0x48, 0x00, 0x00, 0x04, +0x14, 0x03, 0x80, 0x04, 0x58, 0x93, 0x00, 0x00, 0x04, 0x64, 0x80, 0x00, 0x3e, 0x9f, 0xc4, 0x3c, +0x4c, 0x64, 0xff, 0xa4, 0x04, 0x53, 0x00, 0x00, 0x4c, 0x53, 0x00, 0x16, 0x04, 0x03, 0x00, 0x04, +0x40, 0x34, 0x00, 0x01, 0x4e, 0x35, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0xa3, 0x30, +0x44, 0x20, 0x01, 0xa0, 0x49, 0xff, 0xb3, 0x1a, 0x48, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0x01, +0x49, 0xff, 0xff, 0x4e, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x58, 0x60, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x0c, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0xa3, 0x30, 0x44, 0x20, 0x01, 0x2d, 0x49, 0xff, 0xb2, 0xfe, +0x48, 0x00, 0x00, 0x00, 0x44, 0x00, 0xea, 0x60, 0x40, 0xf0, 0x04, 0x06, 0x4e, 0xf2, 0x00, 0x28, +0x46, 0x2e, 0xa5, 0xf1, 0x58, 0x21, 0x05, 0xa0, 0x40, 0xf1, 0x04, 0x06, 0x4e, 0xf2, 0x00, 0x0c, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0xa3, 0x30, 0x44, 0x20, 0x01, 0x35, 0x49, 0xff, 0xb2, 0xe6, +0x48, 0x00, 0x00, 0x00, 0x40, 0x40, 0x80, 0x77, 0x44, 0x3f, 0x15, 0xa0, 0x40, 0x22, 0x00, 0x13, +0x42, 0x11, 0x0c, 0x73, 0x12, 0x23, 0x00, 0x06, 0x4e, 0x13, 0x00, 0x10, 0x50, 0x11, 0x7f, 0xff, +0x12, 0x13, 0x00, 0x06, 0x58, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x18, 0x44, 0x00, 0x00, 0x00, +0x12, 0x03, 0x00, 0x06, 0x48, 0x00, 0x00, 0x12, 0x44, 0x50, 0xff, 0xfe, 0x40, 0xf2, 0x84, 0x06, +0x4e, 0xf2, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0xa3, 0x30, 0x44, 0x20, 0x01, 0x48, +0x49, 0xff, 0xb2, 0xbc, 0x48, 0x00, 0x00, 0x00, 0x40, 0x30, 0xbc, 0x08, 0x50, 0x71, 0x83, 0xe7, +0x44, 0x90, 0x03, 0xe8, 0x40, 0x83, 0xa4, 0x57, 0x45, 0xe0, 0x00, 0x01, 0x3e, 0x7f, 0xc4, 0x3c, +0x40, 0x94, 0x20, 0x1b, 0x40, 0x9f, 0x20, 0x1a, 0x49, 0xf7, 0xbb, 0xe8, 0x04, 0x23, 0x80, 0x00, +0x40, 0x80, 0x24, 0x00, 0x4c, 0x23, 0x80, 0x08, 0x04, 0x13, 0x80, 0x04, 0x40, 0x44, 0x04, 0x01, +0x4e, 0x44, 0x00, 0x08, 0x3c, 0x8f, 0xf1, 0x13, 0x58, 0x04, 0x80, 0x00, 0x49, 0xff, 0xfe, 0xd0, +0x04, 0x03, 0x00, 0x00, 0x14, 0x83, 0x00, 0x02, 0x4e, 0x03, 0x00, 0x12, 0x3c, 0x3d, 0xf1, 0x10, +0x14, 0x63, 0x80, 0x01, 0x14, 0x73, 0x00, 0x00, 0x14, 0x33, 0x00, 0x01, 0x14, 0x61, 0x80, 0x00, +0x05, 0xe3, 0x80, 0x02, 0x50, 0x2f, 0x00, 0x01, 0x14, 0x23, 0x80, 0x02, 0x51, 0xff, 0x80, 0x04, +0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x46, 0x10, 0x01, 0x12, 0x2e, 0x07, 0xb4, 0x78, 0x4e, 0x02, 0x00, 0x26, 0x3e, 0x6f, 0xc4, 0x3c, +0x04, 0x03, 0x00, 0x03, 0x44, 0x70, 0x00, 0x00, 0x44, 0x20, 0x00, 0x00, 0x3e, 0x27, 0xb4, 0x78, +0x14, 0x63, 0x00, 0x00, 0x14, 0x63, 0x00, 0x01, 0x14, 0x73, 0x00, 0x02, 0x4e, 0x03, 0x00, 0x0c, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0xa3, 0x30, 0x44, 0x20, 0x00, 0xc2, 0x49, 0xff, 0xb2, 0x56, +0x48, 0x00, 0x00, 0x00, 0x49, 0xf7, 0xbb, 0x3a, 0x04, 0x03, 0x00, 0x03, 0x49, 0xf7, 0xba, 0xa8, +0x14, 0x73, 0x00, 0x03, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x10, 0x01, 0x12, 0x3e, 0x6f, 0xc4, 0x3c, 0x44, 0x20, 0x00, 0x00, +0x2e, 0x07, 0xb4, 0x78, 0x14, 0x23, 0x00, 0x02, 0x44, 0x20, 0x00, 0x01, 0x14, 0x63, 0x00, 0x00, +0x14, 0x63, 0x00, 0x01, 0x4c, 0x01, 0x00, 0x1a, 0x04, 0x03, 0x00, 0x03, 0x3e, 0x27, 0xb4, 0x78, +0x4e, 0x03, 0x00, 0x12, 0x49, 0xf7, 0xba, 0xc8, 0x14, 0x03, 0x00, 0x03, 0x4e, 0x03, 0x00, 0x0e, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0xa3, 0x30, 0x44, 0x20, 0x00, 0xa2, 0x49, 0xff, 0xb2, 0x1e, +0x48, 0x00, 0x00, 0x00, 0x49, 0xf7, 0xbb, 0x02, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x54, 0x00, 0x00, 0xff, 0x49, 0xff, 0xe9, 0x86, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x58, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0d, 0x02, 0x11, 0x00, 0x1d, +0x00, 0x30, 0x00, 0x01, 0x42, 0x10, 0xb0, 0x0b, 0x00, 0x20, 0x00, 0x02, 0x4c, 0x30, 0x80, 0x14, +0x10, 0x10, 0x00, 0x01, 0x3e, 0x3f, 0xc0, 0xe0, 0x38, 0x41, 0x88, 0x00, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x42, 0x80, 0x0a, 0x4c, 0x12, 0xc0, 0x04, 0x38, 0x11, 0x88, 0x08, 0x00, 0x10, 0x00, 0x01, +0x49, 0xff, 0xd5, 0x58, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x04, 0x50, 0x00, 0x06, 0x04, 0x30, 0x00, 0x0d, +0x00, 0x42, 0x80, 0x07, 0x40, 0x22, 0x08, 0x09, 0x10, 0x21, 0x80, 0x00, 0x05, 0xe0, 0x00, 0x06, +0x04, 0x40, 0x00, 0x0d, 0x00, 0x5f, 0x00, 0x08, 0x44, 0x20, 0x00, 0x01, 0x10, 0x52, 0x00, 0x02, +0x2e, 0x17, 0xb0, 0xc8, 0x4c, 0x11, 0x40, 0x04, 0x49, 0xff, 0xff, 0xba, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3e, 0x07, 0xb4, 0x79, 0x4a, 0x00, 0x78, 0x20, +0x2e, 0x07, 0xb4, 0x79, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x3c, 0x6d, 0xed, 0x32, 0x3c, 0x7d, 0xed, 0x25, 0x4e, 0x62, 0x00, 0x18, 0x49, 0xf7, 0xc5, 0xd8, +0x49, 0xf7, 0xc8, 0x0e, 0x42, 0x60, 0x18, 0x24, 0x44, 0x10, 0x00, 0x00, 0x40, 0x63, 0x08, 0x09, +0x58, 0x00, 0x80, 0x00, 0x48, 0x00, 0x00, 0x06, 0x1c, 0x03, 0x80, 0x01, 0x50, 0x10, 0x80, 0x01, +0x40, 0xf0, 0x98, 0x06, 0x4e, 0xf3, 0xff, 0xfa, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x58, 0x60, 0x00, 0x00, +0x49, 0xf7, 0xc5, 0xb6, 0x49, 0xf7, 0xc7, 0xec, 0x40, 0x03, 0x00, 0x37, 0x4e, 0x12, 0x00, 0x04, +0x50, 0x00, 0x00, 0x01, 0x46, 0x10, 0x01, 0x12, 0x5c, 0xf0, 0x02, 0x01, 0x4e, 0xf3, 0x00, 0x08, +0x44, 0x00, 0x00, 0x00, 0x3c, 0x0f, 0xed, 0x22, 0x48, 0x00, 0x00, 0x06, 0x3c, 0x0f, 0xed, 0x22, +0x44, 0x00, 0x00, 0x01, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, +0x58, 0x60, 0x00, 0x00, 0x49, 0xf7, 0xc5, 0x94, 0x49, 0xf7, 0xc7, 0xca, 0x40, 0x03, 0x00, 0x37, +0x4e, 0x12, 0x00, 0x04, 0x50, 0x00, 0x00, 0x01, 0x54, 0x20, 0x00, 0x01, 0x4e, 0x22, 0x00, 0x04, +0x50, 0x00, 0x00, 0x01, 0x46, 0x10, 0x01, 0x12, 0x5c, 0xf0, 0x00, 0x41, 0x4e, 0xf3, 0x00, 0x08, +0x44, 0x00, 0x00, 0x00, 0x3c, 0x0f, 0xed, 0x21, 0x48, 0x00, 0x00, 0x06, 0x3c, 0x0f, 0xed, 0x21, +0x44, 0x00, 0x00, 0x01, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xf4, 0x14, 0x5f, 0x80, 0x01, 0x58, 0x90, 0x80, 0x00, 0x58, 0x81, 0x00, 0x00, +0x58, 0x61, 0x80, 0x00, 0x58, 0xa0, 0x00, 0x00, 0x05, 0xcf, 0x80, 0x0a, 0x49, 0xf7, 0xc5, 0x60, +0x49, 0xf7, 0xc7, 0x96, 0x04, 0x5f, 0x80, 0x01, 0x4e, 0xa3, 0x00, 0x06, 0x58, 0x75, 0x00, 0x00, +0x48, 0x00, 0x00, 0x0a, 0x40, 0x70, 0x28, 0x37, 0x40, 0x73, 0x1c, 0x37, 0x4e, 0x12, 0x00, 0x04, +0x50, 0x73, 0x80, 0x01, 0x4e, 0x93, 0x00, 0x06, 0x58, 0x44, 0x80, 0x00, 0x48, 0x00, 0x00, 0x0a, +0x40, 0x40, 0x24, 0x37, 0x40, 0x43, 0x10, 0x57, 0x4e, 0x22, 0x00, 0x04, 0x50, 0x42, 0x00, 0x01, +0x4e, 0x83, 0x00, 0x06, 0x58, 0x34, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0a, 0x40, 0x30, 0x20, 0x37, +0x40, 0x33, 0x0f, 0xd7, 0x4f, 0xe2, 0x00, 0x04, 0x50, 0x31, 0x80, 0x01, 0x40, 0x02, 0x80, 0xb7, +0x40, 0x12, 0x1c, 0x00, 0x40, 0x20, 0x8c, 0x00, 0x4e, 0x52, 0x00, 0x04, 0x50, 0x00, 0x00, 0x01, +0x42, 0x10, 0x70, 0x24, 0x41, 0xe0, 0x88, 0x00, 0x3d, 0xef, 0xed, 0x32, 0x3c, 0x2f, 0xed, 0x33, +0x3c, 0x0f, 0xed, 0x34, 0x3c, 0x1f, 0xed, 0x35, 0x3c, 0x8f, 0xed, 0x30, 0x3c, 0x6f, 0xed, 0x2d, +0x3c, 0xaf, 0xed, 0x2e, 0x3c, 0x9f, 0xed, 0x2f, 0x3c, 0x3f, 0xed, 0x38, 0x44, 0x00, 0x00, 0x01, +0x3d, 0xcf, 0xed, 0x31, 0x3c, 0x7f, 0xed, 0x36, 0x3c, 0x4f, 0xed, 0x37, 0x51, 0xff, 0x80, 0x0c, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xec, +0x58, 0x91, 0x80, 0x00, 0x58, 0x82, 0x00, 0x00, 0x04, 0x3f, 0x80, 0x0d, 0x04, 0x4f, 0x80, 0x0c, +0x14, 0x2f, 0x80, 0x03, 0x14, 0x3f, 0x80, 0x00, 0x14, 0x4f, 0x80, 0x01, 0x14, 0x5f, 0x80, 0x02, +0x58, 0xa0, 0x80, 0x00, 0x54, 0x60, 0x00, 0xff, 0x05, 0xcf, 0x80, 0x0f, 0x49, 0xf7, 0xc4, 0xe8, +0x49, 0xf7, 0xc7, 0x1e, 0x04, 0x2f, 0x80, 0x03, 0x04, 0x3f, 0x80, 0x00, 0x04, 0x4f, 0x80, 0x01, +0x04, 0x5f, 0x80, 0x02, 0x4e, 0x92, 0x00, 0x1c, 0x3c, 0x7d, 0xed, 0x2e, 0x4e, 0x72, 0x00, 0x18, +0x41, 0xe0, 0x1c, 0xf7, 0x40, 0x73, 0x78, 0x37, 0x55, 0xe0, 0x80, 0xff, 0x12, 0x75, 0x00, 0x00, +0x11, 0xe1, 0x00, 0x00, 0x02, 0x25, 0x00, 0x00, 0x40, 0x7f, 0x18, 0x08, 0x3d, 0xed, 0xed, 0x25, +0x43, 0xe0, 0x08, 0x73, 0x40, 0x2f, 0x1c, 0x00, 0x14, 0x24, 0x80, 0x00, 0x4e, 0x42, 0x00, 0x22, +0x3c, 0x1d, 0xed, 0x2f, 0x4e, 0x12, 0x00, 0x1e, 0x40, 0x20, 0x04, 0x37, 0x3c, 0x7d, 0xed, 0x36, +0x40, 0x23, 0x0b, 0xd7, 0x40, 0x1f, 0x78, 0x00, 0x54, 0x10, 0x80, 0xff, 0x41, 0xe1, 0x1c, 0x00, +0x13, 0xe4, 0x00, 0x00, 0x10, 0x12, 0x80, 0x00, 0x41, 0xe0, 0x94, 0x08, 0x02, 0x24, 0x00, 0x00, +0x3c, 0x1d, 0xed, 0x25, 0x42, 0x10, 0x08, 0x73, 0x40, 0x50, 0xf8, 0x00, 0x14, 0x52, 0x00, 0x00, +0x4f, 0xc2, 0x00, 0x26, 0x3c, 0x1d, 0xed, 0x30, 0x4e, 0x12, 0x00, 0x22, 0x40, 0x10, 0x04, 0x57, +0x3c, 0x4d, 0xed, 0x37, 0x3c, 0x2d, 0xed, 0x36, 0x40, 0x52, 0x08, 0x00, 0x41, 0xe3, 0x04, 0x97, +0x40, 0x22, 0xf8, 0x00, 0x12, 0x21, 0x80, 0x00, 0x54, 0x12, 0x00, 0xff, 0x04, 0x6f, 0x80, 0x0e, +0x10, 0x13, 0x00, 0x00, 0x40, 0x60, 0x94, 0x08, 0x02, 0x51, 0x80, 0x00, 0x3c, 0x3d, 0xed, 0x25, +0x42, 0x30, 0x14, 0x73, 0x40, 0x01, 0x98, 0x00, 0x14, 0x0e, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, +0x51, 0xff, 0x80, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x44, 0x60, 0x2f, 0xc0, 0x54, 0x70, 0x00, 0xff, 0x4b, 0xe0, 0x18, 0x01, +0x46, 0x50, 0x06, 0x63, 0x4c, 0x02, 0x80, 0x1a, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x20, 0x07, 0x60, +0x58, 0x51, 0x03, 0x00, 0x4c, 0x02, 0x80, 0x12, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x30, 0x07, 0x62, +0x58, 0x51, 0x88, 0x00, 0x4c, 0x02, 0x80, 0x0a, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x40, 0x07, 0x63, +0x58, 0x52, 0x06, 0x00, 0x4c, 0x02, 0xc0, 0x04, 0x3e, 0x77, 0xb4, 0x8c, 0x44, 0x00, 0x00, 0x01, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, +0x51, 0xff, 0xff, 0xf8, 0x44, 0x00, 0x00, 0x01, 0x49, 0xf7, 0xc6, 0x94, 0x2e, 0x27, 0xb4, 0x8c, +0x4e, 0x23, 0x00, 0x10, 0x2e, 0x07, 0xb4, 0x80, 0x2e, 0x17, 0xb4, 0x7c, 0x2e, 0x47, 0xb4, 0xc8, +0x2e, 0x57, 0xb4, 0x84, 0x2e, 0x67, 0xb4, 0x88, 0x58, 0x31, 0x00, 0x00, 0x48, 0x00, 0x00, 0x30, +0x44, 0x60, 0x2f, 0xc0, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x20, 0x06, 0x63, 0x4c, 0x01, 0x00, 0x1a, +0x46, 0x70, 0x07, 0x60, 0x4b, 0xe0, 0x18, 0x01, 0x58, 0x73, 0x83, 0x00, 0x4c, 0x03, 0x80, 0x12, +0x46, 0x80, 0x07, 0x62, 0x4b, 0xe0, 0x18, 0x01, 0x58, 0x84, 0x08, 0x00, 0x4c, 0x04, 0x00, 0x0a, +0x46, 0x90, 0x07, 0x63, 0x4b, 0xe0, 0x18, 0x01, 0x58, 0x94, 0x86, 0x00, 0x4c, 0x04, 0xc0, 0x14, +0x44, 0x60, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x58, 0x13, 0x00, 0x00, 0x58, 0x23, 0x00, 0x00, +0x44, 0x30, 0x00, 0x01, 0x58, 0x43, 0x00, 0x00, 0x58, 0x53, 0x00, 0x00, 0x14, 0x6f, 0x80, 0x00, +0x49, 0x00, 0x02, 0x12, 0x46, 0x7a, 0x00, 0x00, 0x04, 0x83, 0x80, 0x59, 0x46, 0x6a, 0x00, 0x00, +0x14, 0x83, 0x00, 0x5a, 0x44, 0x70, 0x2c, 0xcc, 0x3c, 0x9d, 0xed, 0x32, 0x44, 0x60, 0x31, 0x3c, +0x4b, 0xe0, 0x1c, 0x01, 0x4b, 0xe0, 0x18, 0x01, 0x42, 0x80, 0x24, 0x73, 0x46, 0x1a, 0x00, 0x00, +0x14, 0x80, 0x80, 0x5b, 0x3c, 0xad, 0xed, 0x1f, 0x58, 0x04, 0x00, 0x00, 0x40, 0x35, 0x20, 0x08, +0x46, 0x8a, 0x00, 0x00, 0x40, 0x40, 0x0c, 0x00, 0x14, 0x44, 0x00, 0x5c, 0x3c, 0x2d, 0xed, 0x20, +0x46, 0x5a, 0x00, 0x00, 0x40, 0x11, 0x20, 0x08, 0x40, 0x92, 0x04, 0x00, 0x14, 0x92, 0x80, 0x5d, +0x3c, 0xad, 0xed, 0x21, 0x4b, 0xe0, 0x1c, 0x01, 0x4b, 0xe0, 0x18, 0x01, 0x40, 0xa5, 0x04, 0x09, +0x42, 0x90, 0x28, 0x73, 0x46, 0x3a, 0x00, 0x00, 0x14, 0x91, 0x80, 0x5e, 0x3c, 0x0d, 0xed, 0x21, +0x40, 0x80, 0x04, 0x09, 0x4b, 0xe0, 0x1c, 0x01, 0x4b, 0xe0, 0x18, 0x01, 0x42, 0x90, 0x20, 0x73, +0x58, 0x84, 0x80, 0x00, 0x46, 0x9a, 0x00, 0x00, 0x14, 0x84, 0x80, 0x5f, 0x3c, 0x9d, 0xed, 0x22, +0x4b, 0xe0, 0x1c, 0x01, 0x4b, 0xe0, 0x18, 0x01, 0x42, 0x80, 0x24, 0x73, 0x46, 0x4a, 0x00, 0x00, +0x14, 0x82, 0x00, 0x61, 0x44, 0x00, 0x00, 0x00, 0x49, 0xf7, 0xc5, 0xf4, 0x3e, 0x08, 0x02, 0x76, +0x3e, 0x18, 0x02, 0x78, 0x49, 0xf7, 0xc9, 0x44, 0x3c, 0x00, 0x01, 0x3c, 0x3c, 0x08, 0x01, 0x3a, +0x3c, 0x08, 0x01, 0x39, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x08, 0x3a, 0x6f, 0xa8, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x51, 0xff, 0xff, 0xf0, 0x04, 0x7f, 0x80, 0x08, +0x04, 0x6f, 0x80, 0x09, 0x14, 0x7f, 0x80, 0x00, 0x14, 0x6f, 0x80, 0x01, 0x04, 0x7f, 0x80, 0x0a, +0x04, 0x6f, 0x80, 0x0b, 0x00, 0x8f, 0x80, 0x38, 0x49, 0xff, 0xfe, 0x02, 0x4e, 0x02, 0x00, 0x74, +0x4e, 0x73, 0x00, 0x06, 0x3c, 0x7f, 0xed, 0x1f, 0x48, 0x00, 0x00, 0x16, 0x5c, 0xf3, 0x81, 0x01, +0x4e, 0xf2, 0x00, 0x08, 0x44, 0x10, 0x00, 0x01, 0x3c, 0x1f, 0xed, 0x1f, 0x48, 0x00, 0x00, 0x0c, +0x3e, 0x1f, 0xb4, 0x7c, 0x5c, 0xf3, 0x82, 0x01, 0x4e, 0xf2, 0x00, 0x22, 0x44, 0x30, 0x00, 0x02, +0x14, 0x30, 0x80, 0x00, 0x4e, 0x63, 0x00, 0x06, 0x3c, 0x6f, 0xed, 0x20, 0x48, 0x00, 0x00, 0x1e, +0x5c, 0xf3, 0x01, 0x01, 0x4e, 0xf2, 0x00, 0x08, 0x45, 0xe0, 0x00, 0x01, 0x3d, 0xef, 0xed, 0x20, +0x48, 0x00, 0x00, 0x14, 0x3e, 0x1f, 0xb4, 0x80, 0x5c, 0xf3, 0x02, 0x01, 0x4e, 0xf2, 0x00, 0x08, +0x44, 0x00, 0x00, 0x02, 0x14, 0x00, 0x80, 0x00, 0x48, 0x00, 0x00, 0x08, 0x44, 0x00, 0x00, 0x00, +0x14, 0x00, 0x80, 0x00, 0x48, 0x00, 0x00, 0x3a, 0x04, 0x0f, 0x80, 0x0c, 0x49, 0xff, 0xfd, 0x98, +0x4e, 0x02, 0x00, 0x32, 0x04, 0x0f, 0x80, 0x0d, 0x49, 0xff, 0xfd, 0x70, 0x4e, 0x02, 0x00, 0x2c, +0x04, 0x1f, 0x80, 0x0f, 0x58, 0x04, 0x00, 0x00, 0x49, 0xff, 0xfe, 0xb2, 0x4e, 0x02, 0x00, 0x24, +0x3e, 0x6f, 0xb4, 0xa8, 0x49, 0xff, 0xfe, 0xdc, 0x14, 0x6f, 0x80, 0x00, 0x3e, 0x6f, 0xb4, 0xac, +0x3e, 0x1f, 0xb4, 0x94, 0x3e, 0x2f, 0xb4, 0x98, 0x3e, 0x3f, 0xb4, 0x9c, 0x3e, 0x4f, 0xb4, 0xa0, +0x3e, 0x5f, 0xb4, 0xa4, 0x14, 0x6f, 0x80, 0x01, 0x3e, 0x0f, 0xb4, 0x90, 0x3e, 0x6f, 0xb4, 0xb0, +0x14, 0x6f, 0x80, 0x02, 0x49, 0x00, 0x01, 0x92, 0x49, 0xff, 0xfd, 0x20, 0x44, 0x00, 0x00, 0x01, +0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x10, 0x3a, 0x6f, 0xa0, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xdc, 0x49, 0xf7, 0xe5, 0x18, +0x44, 0x00, 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x49, 0xf7, 0xc3, 0x76, 0x44, 0x60, 0x00, 0x00, +0x44, 0x00, 0x00, 0x40, 0x58, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x20, 0x40, 0x30, 0x04, 0x08, +0x44, 0x40, 0x50, 0x00, 0x58, 0x53, 0x00, 0x00, 0x14, 0x6f, 0x80, 0x00, 0x14, 0x6f, 0x80, 0x01, +0x14, 0x6f, 0x80, 0x02, 0x14, 0x6f, 0x80, 0x03, 0x14, 0x6f, 0x80, 0x04, 0x14, 0x6f, 0x80, 0x05, +0x14, 0x6f, 0x80, 0x06, 0x14, 0x6f, 0x80, 0x07, 0x49, 0xff, 0xff, 0x46, 0x4e, 0x02, 0x00, 0x74, +0x44, 0x00, 0xff, 0xff, 0x49, 0xf7, 0xc2, 0x64, 0x44, 0x00, 0x00, 0x0f, 0x49, 0xf7, 0xc2, 0x72, +0x44, 0x00, 0x00, 0x01, 0x49, 0xf7, 0xc5, 0x16, 0x3c, 0x0d, 0xed, 0x16, 0x44, 0x10, 0x00, 0x03, +0x44, 0x70, 0x38, 0xf4, 0x4c, 0x00, 0xc0, 0x2a, 0x46, 0x45, 0x00, 0x00, 0x04, 0x32, 0x01, 0x63, +0x58, 0x13, 0x00, 0x00, 0x51, 0xe1, 0x80, 0x01, 0x40, 0x2f, 0x00, 0x13, 0x58, 0x31, 0x00, 0x00, +0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x58, 0x13, 0x00, 0x00, 0x44, 0x20, 0x0f, 0xff, +0x44, 0x30, 0x00, 0x18, 0x44, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x1c, 0x01, 0x2e, 0x17, 0xb4, 0x5c, +0x46, 0x0a, 0x50, 0x08, 0x46, 0x3a, 0x00, 0x00, 0x40, 0x50, 0xa8, 0x08, 0x40, 0x42, 0x80, 0x00, +0x14, 0x41, 0x80, 0x61, 0x48, 0x00, 0x00, 0x34, 0x44, 0x20, 0x02, 0x88, 0x58, 0x31, 0x00, 0x00, +0x58, 0x13, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x58, 0x13, 0x00, 0x00, +0x44, 0x20, 0x0f, 0xff, 0x44, 0x30, 0x00, 0x18, 0x44, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x1c, 0x01, +0x58, 0x13, 0x00, 0x00, 0x44, 0x20, 0x0f, 0xff, 0x44, 0x30, 0x00, 0x34, 0x44, 0x00, 0x00, 0x02, +0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x10, 0x00, 0x01, 0x44, 0x20, 0x0f, 0xff, 0x44, 0x30, 0x00, 0x18, +0x44, 0x00, 0x00, 0x02, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0x02, 0x58, 0x10, 0x00, 0x00, +0x44, 0x20, 0x0f, 0xff, 0x40, 0x30, 0x0c, 0x08, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0x00, +0x49, 0xf7, 0xc4, 0xb0, 0x51, 0xff, 0x80, 0x24, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x98, 0x3c, 0x51, 0xff, 0xff, 0xf4, 0x04, 0x6f, 0x80, 0x01, 0x54, 0x00, 0x00, 0xff, +0x42, 0x43, 0x7c, 0x08, 0x14, 0x4f, 0x80, 0x01, 0x04, 0x5f, 0x80, 0x01, 0x46, 0x4a, 0x00, 0x00, +0x42, 0x52, 0xc0, 0x09, 0x14, 0x5f, 0x80, 0x01, 0x10, 0x0f, 0x80, 0x05, 0x04, 0x0f, 0x80, 0x01, +0x14, 0x02, 0x00, 0x65, 0x04, 0x52, 0x00, 0x65, 0x46, 0x0a, 0x00, 0x00, 0x14, 0x5f, 0x80, 0x01, +0x04, 0x5f, 0x80, 0x01, 0x4e, 0x55, 0xff, 0xf8, 0x04, 0x00, 0x00, 0x65, 0x14, 0x0f, 0x80, 0x01, +0x04, 0x5f, 0x80, 0x01, 0x04, 0x4f, 0x80, 0x01, 0x04, 0x0f, 0x80, 0x01, 0x40, 0x42, 0x14, 0x09, +0x42, 0x52, 0x9c, 0x0b, 0x54, 0x42, 0x00, 0x03, 0x54, 0x00, 0x00, 0x1f, 0x10, 0x51, 0x80, 0x00, +0x10, 0x40, 0x80, 0x00, 0x10, 0x01, 0x00, 0x00, 0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0x98, 0x04, +0x4a, 0x00, 0x78, 0x20, 0x51, 0xff, 0xff, 0xf8, 0x44, 0x30, 0x00, 0x00, 0x14, 0x3f, 0x80, 0x01, +0x46, 0x2a, 0x00, 0x00, 0x04, 0x01, 0x00, 0x64, 0x54, 0x10, 0x80, 0xff, 0x14, 0x0f, 0x80, 0x01, +0x4e, 0x12, 0x00, 0x08, 0x04, 0x4f, 0x80, 0x01, 0x58, 0x02, 0x00, 0x10, 0x48, 0x00, 0x00, 0x06, +0x04, 0x5f, 0x80, 0x01, 0x42, 0x02, 0x90, 0x09, 0x14, 0x0f, 0x80, 0x01, 0x46, 0x0a, 0x00, 0x00, +0x04, 0x2f, 0x80, 0x01, 0x14, 0x20, 0x00, 0x64, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x08, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0x3c, 0x51, 0xff, 0xff, 0xf8, 0x04, 0x6f, 0x80, 0x01, +0x54, 0x00, 0x00, 0x03, 0x40, 0x63, 0x08, 0x09, 0x40, 0x63, 0x08, 0x08, 0x40, 0x73, 0x00, 0x04, +0x14, 0x7f, 0x80, 0x01, 0x54, 0x10, 0x80, 0x03, 0x04, 0x0f, 0x80, 0x01, 0x44, 0x6f, 0xff, 0xf3, +0x40, 0x00, 0x18, 0x02, 0x40, 0x70, 0x88, 0x08, 0x40, 0x10, 0x1c, 0x04, 0x14, 0x1f, 0x80, 0x01, +0x54, 0x61, 0x00, 0x07, 0x04, 0x1f, 0x80, 0x01, 0x44, 0x7f, 0xff, 0x8f, 0x40, 0x00, 0x9c, 0x02, +0x40, 0x23, 0x10, 0x08, 0x40, 0x60, 0x08, 0x04, 0x14, 0x6f, 0x80, 0x01, 0x54, 0x31, 0x80, 0x01, +0x04, 0x2f, 0x80, 0x01, 0x42, 0x01, 0x1c, 0x09, 0x40, 0x71, 0x9c, 0x08, 0x40, 0x60, 0x1c, 0x04, +0x14, 0x6f, 0x80, 0x01, 0x54, 0x32, 0x00, 0x7f, 0x04, 0x0f, 0x80, 0x01, 0x44, 0x2f, 0x80, 0xff, +0x40, 0x10, 0x08, 0x02, 0x40, 0x71, 0xa0, 0x08, 0x40, 0x40, 0x9c, 0x04, 0x14, 0x4f, 0x80, 0x01, +0x54, 0x62, 0x80, 0x7f, 0x04, 0x3f, 0x80, 0x01, 0x40, 0x23, 0x3c, 0x08, 0x46, 0x6f, 0xfc, 0x07, +0x58, 0x63, 0x0f, 0xff, 0x40, 0x01, 0x98, 0x02, 0x40, 0x10, 0x08, 0x04, 0x14, 0x1f, 0x80, 0x01, +0x00, 0x7f, 0x80, 0x10, 0x04, 0x5f, 0x80, 0x01, 0x40, 0x43, 0xd8, 0x08, 0x40, 0x32, 0xa8, 0x08, +0x40, 0x31, 0xa8, 0x09, 0x40, 0x21, 0x90, 0x04, 0x14, 0x2f, 0x80, 0x01, 0x46, 0x0a, 0x00, 0x00, +0x04, 0x1f, 0x80, 0x01, 0x14, 0x10, 0x00, 0x58, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x08, +0x3a, 0x6f, 0x9c, 0x04, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0x3c, 0x46, 0x6a, 0x00, 0x00, +0x04, 0x63, 0x00, 0x59, 0x14, 0x60, 0x00, 0x00, 0x46, 0x0a, 0x00, 0x00, 0x04, 0x60, 0x00, 0x5a, +0x46, 0x0a, 0x00, 0x00, 0x14, 0x60, 0x80, 0x00, 0x04, 0x10, 0x00, 0x5b, 0x46, 0x0a, 0x00, 0x00, +0x14, 0x11, 0x00, 0x00, 0x04, 0x20, 0x00, 0x5c, 0x46, 0x0a, 0x00, 0x00, 0x14, 0x21, 0x80, 0x00, +0x04, 0x10, 0x00, 0x5d, 0x58, 0x20, 0x00, 0x00, 0x14, 0x12, 0x00, 0x00, 0x04, 0x31, 0x00, 0x5e, +0x46, 0x0a, 0x00, 0x00, 0x14, 0x32, 0x80, 0x00, 0x04, 0x10, 0x00, 0x5f, 0x04, 0x2f, 0x80, 0x01, +0x58, 0x50, 0x00, 0x00, 0x14, 0x11, 0x00, 0x00, 0x04, 0x32, 0x80, 0x60, 0x04, 0x4f, 0x80, 0x02, +0x46, 0x0a, 0x00, 0x00, 0x14, 0x32, 0x00, 0x00, 0x04, 0x10, 0x00, 0x61, 0x04, 0x2f, 0x80, 0x03, +0x44, 0x00, 0x00, 0x01, 0x14, 0x11, 0x00, 0x00, 0x3a, 0x6f, 0x98, 0x04, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x54, 0x70, 0x80, 0xff, 0x54, 0x61, 0x00, 0xff, +0x58, 0x13, 0x00, 0x00, 0x54, 0x80, 0x00, 0xff, 0x58, 0x03, 0x80, 0x00, 0x54, 0x91, 0x80, 0xff, +0x49, 0xf7, 0xc2, 0xb6, 0x44, 0x50, 0x0f, 0xff, 0x4c, 0x02, 0xc0, 0x06, 0x44, 0x00, 0x00, 0x00, +0x48, 0x00, 0x00, 0x4a, 0x04, 0x5f, 0x80, 0x01, 0x54, 0x13, 0x80, 0x03, 0x42, 0x42, 0xfc, 0x08, +0x14, 0x4f, 0x80, 0x01, 0x54, 0x24, 0x80, 0x01, 0x04, 0x3f, 0x80, 0x01, 0x43, 0xe1, 0xc0, 0x08, +0x15, 0xef, 0x80, 0x01, 0x10, 0x8f, 0x80, 0x05, 0x40, 0x51, 0x1c, 0x08, 0x04, 0x7f, 0x80, 0x01, +0x41, 0xe0, 0x94, 0x08, 0x42, 0x43, 0x9c, 0x09, 0x40, 0x32, 0x14, 0x04, 0x14, 0x3f, 0x80, 0x01, +0x44, 0x1f, 0xff, 0x9f, 0x04, 0x0f, 0x80, 0x01, 0x40, 0x70, 0x04, 0x02, 0x40, 0x73, 0xf8, 0x04, +0x14, 0x7f, 0x80, 0x01, 0x54, 0x63, 0x00, 0x1f, 0x04, 0x5f, 0x80, 0x01, 0x46, 0x3a, 0x00, 0x00, +0x40, 0x42, 0x94, 0x09, 0x40, 0x42, 0x14, 0x08, 0x40, 0x62, 0x18, 0x04, 0x14, 0x6f, 0x80, 0x01, +0x58, 0x31, 0x81, 0x94, 0x04, 0x0f, 0x80, 0x01, 0x58, 0x11, 0x80, 0x00, 0x14, 0x01, 0x80, 0x00, +0x05, 0xe0, 0x80, 0x00, 0x15, 0xef, 0x80, 0x01, 0x04, 0x0f, 0x80, 0x01, 0x4e, 0x05, 0xff, 0xfa, +0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xa0, 0xbc, 0x51, 0xff, 0xff, 0xf8, 0x54, 0x60, 0x00, 0xff, 0x54, 0x70, 0x80, 0xff, +0x58, 0x13, 0x80, 0x00, 0x58, 0x03, 0x00, 0x00, 0x54, 0x81, 0x00, 0xff, 0x49, 0xf7, 0xc2, 0x50, +0x44, 0x50, 0x0f, 0xff, 0x4c, 0x02, 0xc0, 0x08, 0x4e, 0x63, 0x00, 0x42, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x72, 0xc0, 0x3e, 0x04, 0x1f, 0x80, 0x01, 0x46, 0x2f, 0xfe, 0x0f, 0x54, 0x43, 0x80, 0x1f, +0x58, 0x21, 0x0f, 0xff, 0x40, 0x32, 0x40, 0x08, 0x40, 0x70, 0x88, 0x02, 0x40, 0x73, 0x8c, 0x04, +0x14, 0x7f, 0x80, 0x01, 0x54, 0x03, 0x00, 0x03, 0x05, 0xef, 0x80, 0x01, 0x42, 0x4f, 0x54, 0x09, +0x42, 0x42, 0x58, 0x09, 0x40, 0x50, 0x54, 0x08, 0x40, 0x32, 0x14, 0x04, 0x14, 0x3f, 0x80, 0x01, +0x04, 0x0f, 0x80, 0x01, 0x54, 0x14, 0x00, 0x01, 0x42, 0x60, 0x5c, 0x09, 0x41, 0xe0, 0xdc, 0x08, +0x40, 0x53, 0x78, 0x04, 0x14, 0x5f, 0x80, 0x01, 0x46, 0x6a, 0x00, 0x00, 0x04, 0x4f, 0x80, 0x01, +0x14, 0x43, 0x00, 0x09, 0x49, 0xf7, 0xc6, 0x3c, 0x04, 0x33, 0x00, 0x09, 0x14, 0x3f, 0x80, 0x01, +0x04, 0x0f, 0x80, 0x01, 0x54, 0x00, 0x0f, 0xff, 0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x0f, 0xff, +0x51, 0xff, 0x80, 0x08, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x00, 0x01, 0x17, +0x2e, 0x10, 0x02, 0x86, 0x4e, 0x12, 0x00, 0x06, 0x44, 0x20, 0x00, 0x00, 0x3e, 0x20, 0x02, 0x86, +0x4a, 0x00, 0x78, 0x20, 0x54, 0x00, 0x00, 0xff, 0x40, 0x20, 0x08, 0x09, 0x40, 0x11, 0x00, 0x10, +0x4e, 0x16, 0x00, 0x06, 0x44, 0x0f, 0xff, 0xfd, 0x48, 0x00, 0x00, 0x56, 0x44, 0x30, 0x00, 0x01, +0x54, 0x00, 0x00, 0x03, 0x4c, 0x11, 0xc0, 0x08, 0x40, 0x01, 0x00, 0x00, 0x50, 0x00, 0x7f, 0xff, +0x48, 0x00, 0x00, 0x14, 0x5e, 0xf0, 0x80, 0x05, 0x4e, 0xf2, 0x00, 0x14, 0x44, 0x20, 0x00, 0x03, +0x42, 0x00, 0x08, 0x24, 0x42, 0x50, 0x88, 0x24, 0x50, 0x30, 0x00, 0x05, 0x40, 0x41, 0x88, 0x0e, +0x40, 0x12, 0x84, 0x0a, 0x40, 0x02, 0x04, 0x00, 0x40, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x34, +0x5e, 0xf0, 0x80, 0x09, 0x4e, 0xf2, 0x00, 0x0e, 0x44, 0x30, 0x00, 0x03, 0x42, 0x50, 0x8c, 0x24, +0x50, 0x12, 0x80, 0x02, 0x40, 0x40, 0x88, 0x0a, 0x50, 0x02, 0x00, 0x03, 0x48, 0xff, 0xff, 0xee, +0x5e, 0xf0, 0x80, 0x11, 0x4e, 0xf2, 0x00, 0x0e, 0x44, 0x50, 0x00, 0x0b, 0x42, 0x40, 0x94, 0x24, +0x50, 0x02, 0x00, 0x0f, 0x40, 0x20, 0x14, 0x0a, 0x50, 0x01, 0x00, 0x07, 0x48, 0x00, 0x00, 0x14, +0x5e, 0xf0, 0x80, 0x21, 0x4e, 0xf3, 0x00, 0x06, 0x44, 0x00, 0x00, 0x0f, 0x48, 0x00, 0x00, 0x0c, +0x44, 0x00, 0x00, 0x05, 0x42, 0x20, 0x80, 0x24, 0x50, 0x31, 0x00, 0x10, 0x40, 0x11, 0x94, 0x0a, +0x50, 0x00, 0x80, 0x0a, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xcc, +0x2e, 0x07, 0xb2, 0xea, 0x4e, 0x03, 0x02, 0xee, 0x3e, 0x0f, 0xb0, 0xd8, 0x00, 0x30, 0x00, 0x25, +0x00, 0x40, 0x00, 0x24, 0x3e, 0x1f, 0xa3, 0x5c, 0x20, 0xa0, 0x00, 0x27, 0x20, 0x90, 0x00, 0x22, +0x2e, 0x57, 0xb4, 0xf0, 0x3a, 0x00, 0x84, 0x00, 0x50, 0x8f, 0x80, 0x28, 0x3c, 0x7d, 0xe8, 0xd6, +0x52, 0x62, 0x00, 0x00, 0x53, 0xc1, 0x80, 0x00, 0x50, 0x2f, 0x80, 0x18, 0x14, 0x5f, 0x80, 0x05, +0x3a, 0x01, 0x04, 0x20, 0x14, 0x7f, 0x80, 0x09, 0x10, 0x64, 0x00, 0x03, 0x11, 0xc4, 0x00, 0x00, +0x10, 0xa4, 0x00, 0x01, 0x10, 0x94, 0x00, 0x02, 0x3c, 0x4d, 0xe8, 0xd5, 0x04, 0x2f, 0x80, 0x05, +0x44, 0x30, 0x00, 0x01, 0x14, 0x4f, 0x80, 0x08, 0x4c, 0x21, 0xc0, 0x08, 0x3e, 0x9f, 0xb2, 0xa4, +0x14, 0x9f, 0x80, 0x04, 0x48, 0x00, 0x00, 0x1c, 0x04, 0xaf, 0x80, 0x05, 0x44, 0x50, 0x00, 0x02, +0x4c, 0xa2, 0xc0, 0x08, 0x3e, 0x6f, 0xb2, 0xac, 0x14, 0x6f, 0x80, 0x04, 0x48, 0x00, 0x00, 0x10, +0x04, 0x4f, 0x80, 0x05, 0x3f, 0xef, 0xb2, 0xbc, 0x56, 0x22, 0x00, 0x03, 0x3e, 0x3f, 0xb2, 0xb4, +0x40, 0x71, 0x88, 0x1a, 0x40, 0x7f, 0x08, 0x1b, 0x14, 0x7f, 0x80, 0x04, 0x44, 0x10, 0x00, 0x00, +0x3e, 0x0f, 0xb2, 0xc4, 0x14, 0x1f, 0x80, 0x03, 0x14, 0x0f, 0x80, 0x02, 0x50, 0x8f, 0x80, 0x20, +0x3e, 0xaf, 0xb2, 0x90, 0x59, 0xc0, 0x80, 0x00, 0x04, 0x9f, 0x80, 0x05, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x92, 0x80, 0xc4, 0x04, 0x1f, 0x80, 0x04, 0x3e, 0x6f, 0xb2, 0x98, 0x00, 0x30, 0x80, 0x00, +0x00, 0x20, 0x80, 0x01, 0x40, 0x71, 0x8c, 0x00, 0x40, 0x43, 0x98, 0x00, 0x20, 0x72, 0x00, 0x01, +0x51, 0xef, 0x80, 0x28, 0x38, 0x43, 0x0d, 0x10, 0x38, 0x6f, 0x09, 0x00, 0x5e, 0xf3, 0xff, 0xf7, +0x4e, 0xf2, 0x00, 0x06, 0x44, 0x30, 0x00, 0x00, 0x48, 0x00, 0x00, 0x26, 0x5e, 0xf3, 0xff, 0xfc, +0x4e, 0xf2, 0x00, 0x06, 0x44, 0x30, 0x00, 0x01, 0x48, 0x00, 0x00, 0x1e, 0x5e, 0xf3, 0xff, 0xff, +0x4e, 0xf2, 0x00, 0x06, 0x44, 0x30, 0x00, 0x02, 0x48, 0x00, 0x00, 0x16, 0x4e, 0x76, 0x00, 0x06, +0x44, 0x30, 0x00, 0x04, 0x48, 0x00, 0x00, 0x10, 0x5e, 0xf3, 0x80, 0x13, 0x4e, 0xf3, 0x00, 0x06, +0x44, 0x30, 0x00, 0xfc, 0x48, 0x00, 0x00, 0x08, 0x3e, 0x5f, 0xb2, 0xd4, 0x40, 0x03, 0x94, 0x00, +0x00, 0x30, 0x7f, 0xff, 0x40, 0x11, 0x08, 0x00, 0x50, 0x9f, 0x80, 0x28, 0x41, 0xe4, 0x84, 0x00, +0x00, 0x9f, 0x00, 0x01, 0x40, 0x24, 0x98, 0x00, 0x40, 0x21, 0x00, 0x10, 0x5e, 0xf1, 0x7f, 0xf7, +0x4e, 0xf2, 0x00, 0x06, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x26, 0x5e, 0xf1, 0x7f, 0xfc, +0x4e, 0xf2, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x1e, 0x5e, 0xf1, 0x7f, 0xff, +0x4e, 0xf2, 0x00, 0x06, 0x44, 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x16, 0x4e, 0x26, 0x00, 0x06, +0x44, 0x00, 0x00, 0x04, 0x48, 0x00, 0x00, 0x10, 0x5e, 0xf1, 0x00, 0x13, 0x4e, 0xf3, 0x00, 0x06, +0x44, 0x00, 0x00, 0xfc, 0x48, 0x00, 0x00, 0x08, 0x3e, 0x0f, 0xb2, 0xd4, 0x40, 0x51, 0x00, 0x00, +0x00, 0x02, 0xff, 0xff, 0x41, 0xe0, 0x0c, 0x00, 0x54, 0x0f, 0x00, 0xff, 0x14, 0x4f, 0x80, 0x01, +0x49, 0xff, 0xfe, 0xb2, 0x40, 0x54, 0x9c, 0x00, 0x40, 0x12, 0x80, 0x01, 0x04, 0x9f, 0x80, 0x01, +0x00, 0x05, 0x00, 0x01, 0x3e, 0x3f, 0xb2, 0xcc, 0x3e, 0x4f, 0xb2, 0xd0, 0x00, 0x55, 0x00, 0x00, +0x40, 0x2e, 0x0c, 0x00, 0x40, 0x7e, 0x10, 0x00, 0x54, 0x10, 0x80, 0xff, 0x00, 0x41, 0x00, 0x00, +0x40, 0x63, 0x24, 0x00, 0x40, 0x30, 0x80, 0x01, 0x04, 0x9f, 0x80, 0x03, 0x00, 0x03, 0x80, 0x00, +0x40, 0x53, 0x14, 0x01, 0x54, 0x31, 0x80, 0xff, 0x50, 0x7f, 0x80, 0x18, 0x38, 0x63, 0xa4, 0x08, +0x40, 0x22, 0x90, 0x00, 0x40, 0x41, 0x80, 0x00, 0x40, 0x03, 0xa4, 0x00, 0x50, 0x7f, 0x80, 0x24, +0x10, 0x10, 0x00, 0x01, 0x38, 0x23, 0xf0, 0x08, 0x10, 0x44, 0x00, 0x00, 0x04, 0x4f, 0x80, 0x02, +0x10, 0x52, 0x00, 0x00, 0x10, 0x32, 0x00, 0x01, 0x04, 0x3f, 0x80, 0x04, 0x50, 0x61, 0x80, 0x02, +0x14, 0x6f, 0x80, 0x04, 0x48, 0x00, 0x00, 0x20, 0x05, 0xef, 0x80, 0x03, 0x3e, 0x6f, 0xb2, 0x98, +0x40, 0x5f, 0x18, 0x00, 0x20, 0x62, 0x80, 0x01, 0x20, 0x22, 0x80, 0x00, 0x00, 0x15, 0x00, 0x00, +0x00, 0x35, 0x00, 0x01, 0x04, 0x9f, 0x80, 0x02, 0x40, 0x41, 0x04, 0x01, 0x40, 0x03, 0x0c, 0x01, +0x50, 0x7f, 0x80, 0x24, 0x10, 0x44, 0x80, 0x00, 0x10, 0x04, 0x80, 0x01, 0x38, 0x23, 0xf0, 0x08, +0x10, 0x64, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x4e, 0x07, 0x00, 0x06, 0x44, 0x00, 0x00, 0x00, +0x48, 0x00, 0x00, 0x08, 0x5e, 0xf0, 0x7f, 0xc1, 0x4e, 0xf2, 0x00, 0x06, 0x44, 0x0f, 0xff, 0xc1, +0x10, 0x04, 0x00, 0x00, 0x04, 0x4f, 0x80, 0x03, 0x04, 0x0f, 0x80, 0x02, 0x50, 0x92, 0x00, 0x02, +0x50, 0x70, 0x00, 0x02, 0x51, 0xce, 0x00, 0x01, 0x44, 0x50, 0x00, 0x04, 0x50, 0x84, 0x00, 0x01, +0x14, 0x9f, 0x80, 0x03, 0x50, 0xa5, 0x00, 0x02, 0x14, 0x7f, 0x80, 0x02, 0x4d, 0xc2, 0xfe, 0xf6, +0x50, 0x8f, 0x80, 0x24, 0x20, 0x54, 0x00, 0x03, 0x3e, 0x3f, 0xc4, 0x50, 0x14, 0x5f, 0x80, 0x02, +0x44, 0x50, 0x00, 0x00, 0x20, 0xa4, 0x00, 0x00, 0x3e, 0x6f, 0xc4, 0x5c, 0x14, 0xaf, 0x80, 0x03, +0x50, 0x4f, 0x80, 0x2c, 0x20, 0x14, 0x00, 0x01, 0x21, 0xc4, 0x00, 0x02, 0x14, 0x1f, 0x80, 0x04, +0x59, 0xee, 0x00, 0x00, 0x58, 0xa2, 0x80, 0x00, 0x44, 0x90, 0x00, 0x40, 0x44, 0x80, 0x00, 0x3f, +0x59, 0xc1, 0x80, 0x00, 0x04, 0x0f, 0x80, 0x03, 0x04, 0x7f, 0x80, 0x04, 0x04, 0x2f, 0x80, 0x02, +0x10, 0x02, 0x00, 0x00, 0x11, 0xe2, 0x00, 0x02, 0x10, 0x72, 0x00, 0x01, 0x10, 0x22, 0x00, 0x03, +0x54, 0x72, 0x80, 0xff, 0x58, 0x22, 0x00, 0x00, 0x44, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x40, 0x13, 0x80, 0x00, 0x40, 0x00, 0x80, 0x10, 0x10, 0x01, 0x00, 0x00, 0x4e, 0x05, 0x00, 0x0e, +0x5e, 0xf0, 0x00, 0x40, 0x4e, 0xf3, 0x00, 0x04, 0x10, 0x81, 0x00, 0x00, 0x4e, 0x33, 0x00, 0x16, +0x10, 0x33, 0x00, 0x00, 0x48, 0x00, 0x00, 0x12, 0x52, 0x10, 0x00, 0x00, 0x54, 0x00, 0x80, 0xff, +0x4e, 0x33, 0x00, 0x0a, 0x10, 0x03, 0x00, 0x00, 0x5c, 0xf0, 0x00, 0x41, 0x4e, 0xf3, 0x00, 0x04, +0x10, 0x93, 0x00, 0x00, 0x10, 0xa1, 0x00, 0x00, 0x50, 0x31, 0x80, 0x01, 0x54, 0x31, 0x80, 0xff, +0x44, 0x00, 0x00, 0x04, 0x50, 0x21, 0x00, 0x01, 0x4c, 0x30, 0x7f, 0xd2, 0x20, 0x72, 0x00, 0x01, +0x20, 0x22, 0x00, 0x02, 0x40, 0x03, 0x98, 0x08, 0x40, 0x11, 0x30, 0x08, 0x20, 0x32, 0x00, 0x00, +0x20, 0x22, 0x00, 0x03, 0x40, 0x70, 0x04, 0x04, 0x40, 0x03, 0x8c, 0x04, 0x40, 0x11, 0x48, 0x08, +0x40, 0x70, 0x04, 0x04, 0x50, 0x52, 0x80, 0x01, 0x44, 0x20, 0x00, 0x03, 0x1c, 0x7e, 0x00, 0x01, +0x50, 0x63, 0x00, 0x01, 0x4c, 0x51, 0x7f, 0xa0, 0x46, 0x66, 0x02, 0x00, 0x04, 0x03, 0x01, 0x48, +0x3c, 0x5d, 0xf1, 0x15, 0x40, 0x90, 0x60, 0x09, 0x40, 0x94, 0xe0, 0x08, 0x40, 0x14, 0x94, 0x04, +0x14, 0x13, 0x01, 0x48, 0x46, 0x96, 0x02, 0x01, 0x04, 0x74, 0x81, 0x48, 0x40, 0x33, 0xe0, 0x09, +0x40, 0x31, 0xe0, 0x08, 0x40, 0x01, 0x94, 0x04, 0x14, 0x04, 0x81, 0x48, 0x46, 0x66, 0x02, 0x00, +0x58, 0x63, 0x00, 0xfc, 0x04, 0x23, 0x00, 0x00, 0x2e, 0x07, 0xc4, 0x5d, 0x44, 0x7f, 0xc0, 0xff, +0x40, 0x51, 0x1c, 0x02, 0x40, 0x30, 0x20, 0x08, 0x40, 0x41, 0x94, 0x04, 0x14, 0x43, 0x00, 0x00, +0x46, 0x9f, 0xff, 0x03, 0x04, 0x13, 0x00, 0x00, 0x58, 0x94, 0x8f, 0xff, 0x40, 0x70, 0xa4, 0x02, +0x40, 0x30, 0x38, 0x08, 0x40, 0x21, 0x9c, 0x04, 0x14, 0x23, 0x00, 0x00, 0x50, 0x5f, 0x80, 0x20, +0x00, 0x42, 0x80, 0x01, 0x00, 0x02, 0x80, 0x02, 0x00, 0x72, 0x80, 0x03, 0x50, 0x32, 0x7f, 0xff, +0x50, 0x90, 0x7f, 0xff, 0x54, 0x11, 0x80, 0xff, 0x54, 0x54, 0x80, 0xff, 0x40, 0x00, 0x84, 0x00, +0x40, 0x22, 0xa8, 0x08, 0x50, 0x33, 0xff, 0xff, 0x40, 0x90, 0x08, 0x04, 0x54, 0x51, 0x80, 0xff, +0x44, 0x44, 0x02, 0x01, 0x46, 0x66, 0x02, 0x00, 0x40, 0x14, 0x90, 0x04, 0x40, 0x72, 0xcc, 0x08, +0x04, 0x03, 0x01, 0x46, 0x40, 0x50, 0x9c, 0x04, 0x46, 0x7f, 0x80, 0x00, 0x40, 0x90, 0x1c, 0x02, +0x40, 0x22, 0xa4, 0x04, 0x14, 0x23, 0x01, 0x46, 0x46, 0x96, 0x02, 0x01, 0x04, 0x04, 0x81, 0x46, +0x40, 0x30, 0x1c, 0x02, 0x40, 0x42, 0x8c, 0x04, 0x14, 0x44, 0x81, 0x46, 0x2e, 0x0f, 0xb2, 0xc4, +0x5e, 0xf0, 0x7f, 0xff, 0x4e, 0xf2, 0x00, 0x0c, 0x44, 0x60, 0x00, 0x02, 0x40, 0x40, 0x18, 0x56, +0x50, 0x52, 0x00, 0x0f, 0x40, 0x12, 0x80, 0x10, 0x48, 0x00, 0x00, 0x0e, 0x5e, 0xf0, 0x00, 0x12, +0x4e, 0xf3, 0x00, 0x08, 0x44, 0x10, 0x00, 0x0f, 0x58, 0x50, 0x80, 0x00, 0x48, 0x00, 0x00, 0x0c, +0x44, 0x10, 0x00, 0x0f, 0x44, 0x20, 0x00, 0x02, 0x40, 0x30, 0x08, 0x16, 0x50, 0x91, 0x80, 0x06, +0x40, 0x54, 0x80, 0x10, 0x2e, 0x2f, 0xb2, 0xc6, 0x5e, 0xf1, 0x00, 0x10, 0x4e, 0xf3, 0x00, 0x06, +0x44, 0x40, 0x00, 0x0f, 0x48, 0x00, 0x00, 0x0a, 0x44, 0x90, 0x00, 0x02, 0x40, 0x61, 0x24, 0x56, +0x50, 0x43, 0x00, 0x07, 0x40, 0x42, 0x00, 0x10, 0x2e, 0x2f, 0xb2, 0xc8, 0x5e, 0xf1, 0x00, 0x10, +0x4e, 0xf3, 0x00, 0x06, 0x44, 0x30, 0x00, 0x0f, 0x48, 0x00, 0x00, 0x0a, 0x44, 0x60, 0x00, 0x02, +0x40, 0x01, 0x18, 0x56, 0x50, 0x20, 0x00, 0x07, 0x40, 0x31, 0x00, 0x10, 0x2e, 0x2f, 0xb2, 0xca, +0x5e, 0xf1, 0x00, 0x1e, 0x4e, 0xf3, 0x00, 0x06, 0x44, 0x20, 0x00, 0x0f, 0x48, 0x00, 0x00, 0x08, +0x44, 0x00, 0x00, 0x02, 0x40, 0x21, 0x00, 0x16, 0x40, 0x21, 0x00, 0x10, 0x44, 0x90, 0x00, 0x00, +0x42, 0x52, 0xa4, 0x00, 0x42, 0x60, 0xa4, 0x00, 0x42, 0x42, 0x24, 0x00, 0x40, 0x02, 0x90, 0x08, +0x40, 0x50, 0x18, 0x04, 0x42, 0x61, 0xa4, 0x00, 0x40, 0x02, 0x20, 0x08, 0x40, 0x42, 0x80, 0x04, +0x42, 0x21, 0x24, 0x00, 0x40, 0x03, 0x30, 0x08, 0x46, 0x16, 0x02, 0x00, 0x40, 0x32, 0x00, 0x04, +0x40, 0x91, 0x40, 0x08, 0x04, 0x60, 0x81, 0x40, 0x40, 0x41, 0xa4, 0x04, 0x46, 0x9f, 0xff, 0x00, +0x40, 0x53, 0x24, 0x02, 0x40, 0x02, 0x14, 0x04, 0x14, 0x00, 0x81, 0x40, 0x46, 0x16, 0x02, 0x01, +0x04, 0x20, 0x81, 0x40, 0x40, 0x31, 0x24, 0x02, 0x40, 0x52, 0x0c, 0x04, 0x14, 0x50, 0x81, 0x40, +0x51, 0xff, 0x80, 0x34, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xd4, 0x2e, 0x00, 0x02, 0x86, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0x84, 0x70, +0x46, 0x86, 0x02, 0x00, 0x46, 0x6b, 0xfc, 0xff, 0x14, 0x8f, 0x80, 0x02, 0x14, 0x6f, 0x80, 0x03, +0x04, 0x1f, 0x80, 0x02, 0x04, 0x0f, 0x80, 0x03, 0x58, 0x54, 0x00, 0x00, 0x58, 0x42, 0x80, 0x00, +0x58, 0x32, 0x00, 0x00, 0x14, 0x5f, 0x80, 0x04, 0x14, 0x4f, 0x80, 0x05, 0x14, 0x3f, 0x80, 0x06, +0x58, 0x10, 0x88, 0x00, 0x58, 0x00, 0x03, 0xfc, 0x14, 0x1f, 0x80, 0x02, 0x14, 0x0f, 0x80, 0x03, +0x04, 0x7f, 0x80, 0x04, 0x04, 0x1f, 0x80, 0x05, 0x04, 0x0f, 0x80, 0x06, 0x46, 0x26, 0x02, 0x04, +0x14, 0x2f, 0x80, 0x07, 0x58, 0x10, 0x80, 0x04, 0x58, 0x00, 0x01, 0x7c, 0x14, 0x7f, 0x80, 0x04, +0x14, 0x1f, 0x80, 0x05, 0x14, 0x0f, 0x80, 0x06, 0x04, 0x7f, 0x80, 0x07, 0x44, 0x10, 0x00, 0x01, +0x3e, 0x10, 0x02, 0x86, 0x04, 0x0f, 0x80, 0x03, 0x04, 0x1f, 0x80, 0x02, 0x58, 0x73, 0x82, 0x04, +0x14, 0x7f, 0x80, 0x07, 0x14, 0x00, 0x80, 0x00, 0x44, 0x00, 0x02, 0x45, 0x04, 0x1f, 0x80, 0x04, +0x44, 0x70, 0x00, 0x00, 0x14, 0x00, 0x80, 0x00, 0x47, 0xe0, 0xa5, 0xf0, 0x04, 0x1f, 0x80, 0x05, +0x59, 0xef, 0x00, 0x5f, 0x14, 0x00, 0x80, 0x00, 0x59, 0xc1, 0x00, 0x00, 0x04, 0x0f, 0x80, 0x06, +0x58, 0xa1, 0x80, 0x00, 0x14, 0x70, 0x00, 0x00, 0x46, 0x92, 0x01, 0x71, 0x04, 0x1f, 0x80, 0x07, +0x15, 0xe0, 0x80, 0x00, 0x58, 0x94, 0x87, 0x17, 0x45, 0xe1, 0x00, 0x01, 0x58, 0x81, 0x80, 0x00, +0x46, 0x61, 0x72, 0x02, 0x58, 0x51, 0x80, 0x00, 0x46, 0x42, 0x02, 0x02, 0x58, 0x31, 0x00, 0x00, +0x58, 0x22, 0x80, 0x00, 0x15, 0xee, 0x00, 0x82, 0x14, 0x95, 0x02, 0x17, 0x58, 0x63, 0x08, 0x20, +0x58, 0x42, 0x00, 0x20, 0x44, 0x94, 0xb0, 0x43, 0x14, 0x64, 0x02, 0x18, 0x14, 0x42, 0x82, 0x19, +0x58, 0x61, 0x00, 0x00, 0x14, 0x71, 0x80, 0x42, 0x14, 0x91, 0x01, 0xbe, 0x04, 0x03, 0x01, 0xb2, +0x42, 0x80, 0x78, 0x08, 0x14, 0x83, 0x01, 0xb2, 0x04, 0x01, 0x01, 0xb3, 0x58, 0x51, 0x00, 0x00, +0x14, 0x5f, 0x80, 0x02, 0x58, 0x00, 0x00, 0x01, 0x14, 0x0f, 0x80, 0x01, 0x46, 0x4d, 0xbe, 0xa2, +0x04, 0x0f, 0x80, 0x02, 0x14, 0x4f, 0x80, 0x03, 0x58, 0x00, 0x06, 0xec, 0x14, 0x0f, 0x80, 0x02, +0x04, 0x0f, 0x80, 0x03, 0x14, 0x3f, 0x80, 0x04, 0x58, 0x00, 0x0f, 0x40, 0x14, 0x0f, 0x80, 0x03, +0x46, 0x17, 0xf5, 0x55, 0x04, 0x0f, 0x80, 0x04, 0x14, 0x1f, 0x80, 0x05, 0x58, 0x00, 0x04, 0x60, +0x14, 0x0f, 0x80, 0x04, 0x59, 0xc1, 0x00, 0x00, 0x04, 0x0f, 0x80, 0x05, 0x15, 0xcf, 0x80, 0x06, +0x58, 0x00, 0x00, 0x80, 0x14, 0x0f, 0x80, 0x05, 0x47, 0xe6, 0x02, 0x01, 0x04, 0x0f, 0x80, 0x06, +0x15, 0xef, 0x80, 0x07, 0x58, 0x00, 0x05, 0x50, 0x14, 0x0f, 0x80, 0x06, 0x58, 0xa1, 0x00, 0x00, +0x04, 0x0f, 0x80, 0x07, 0x14, 0xaf, 0x80, 0x08, 0x58, 0x00, 0x05, 0x50, 0x14, 0x0f, 0x80, 0x07, +0x46, 0x90, 0x0d, 0x8b, 0x04, 0x0f, 0x80, 0x08, 0x14, 0x9f, 0x80, 0x09, 0x58, 0x00, 0x05, 0x58, +0x14, 0x0f, 0x80, 0x08, 0x04, 0x0f, 0x80, 0x09, 0x47, 0xc0, 0x48, 0x90, 0x58, 0x00, 0x0c, 0xc4, +0x14, 0x0f, 0x80, 0x09, 0x04, 0x0f, 0x80, 0x01, 0x59, 0xce, 0x0c, 0x18, 0x14, 0x01, 0x01, 0xb3, +0x04, 0x0f, 0x80, 0x03, 0x04, 0x2f, 0x80, 0x02, 0x46, 0xa1, 0x29, 0x29, 0x14, 0x01, 0x00, 0x00, +0x04, 0x0f, 0x80, 0x05, 0x04, 0x2f, 0x80, 0x04, 0x58, 0x9f, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, +0x46, 0x80, 0x2e, 0x11, 0x04, 0x2f, 0x80, 0x06, 0x58, 0x64, 0x80, 0x00, 0x15, 0xc1, 0x00, 0x00, +0x46, 0x50, 0x69, 0x8f, 0x04, 0x0f, 0x80, 0x07, 0x58, 0x43, 0x00, 0x00, 0x15, 0xc0, 0x00, 0x00, +0x46, 0x35, 0x22, 0x0c, 0x04, 0x0f, 0x80, 0x09, 0x04, 0x2f, 0x80, 0x08, 0x58, 0x52, 0x88, 0x2a, +0x58, 0x12, 0x00, 0x00, 0x58, 0xa5, 0x05, 0x15, 0x58, 0x84, 0x0d, 0x30, 0x14, 0x01, 0x00, 0x00, +0x14, 0xaf, 0x01, 0x82, 0x14, 0x84, 0x81, 0x83, 0x14, 0x53, 0x01, 0x84, 0x14, 0x32, 0x01, 0x85, +0x44, 0x30, 0x05, 0xd5, 0x14, 0x30, 0x81, 0xa5, 0x2e, 0x57, 0xb0, 0xd8, 0x2e, 0x37, 0xb1, 0x1b, +0x54, 0x42, 0x80, 0x30, 0x56, 0x02, 0x00, 0x10, 0x40, 0x41, 0x80, 0x10, 0x5c, 0x60, 0x00, 0x01, +0x4e, 0x44, 0x00, 0x26, 0x4e, 0x03, 0x00, 0x12, 0x46, 0x76, 0x02, 0x04, 0x46, 0x14, 0x00, 0xa0, +0x58, 0x10, 0x8a, 0xbf, 0x46, 0x06, 0x02, 0x04, 0x14, 0x13, 0x80, 0x98, 0x58, 0x00, 0x02, 0x70, +0x44, 0x10, 0x4f, 0x00, 0x48, 0x00, 0x00, 0x10, 0x46, 0x56, 0x02, 0x04, 0x46, 0x24, 0x01, 0x81, +0x58, 0x21, 0x08, 0xbf, 0x46, 0x06, 0x02, 0x04, 0x14, 0x22, 0x80, 0x98, 0x58, 0x00, 0x02, 0x70, +0x44, 0x10, 0x5f, 0x00, 0x14, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0e, 0x46, 0x86, 0x02, 0x04, +0x46, 0x14, 0x04, 0x04, 0x58, 0x04, 0x00, 0x00, 0x58, 0x10, 0x80, 0xbf, 0x14, 0x14, 0x00, 0x98, +0x14, 0x70, 0x00, 0x9c, 0x46, 0x26, 0x02, 0x04, 0x58, 0x71, 0x00, 0x00, 0x44, 0x50, 0xf8, 0xf8, +0x14, 0x51, 0x00, 0x99, 0x14, 0x53, 0x80, 0x9a, 0x4e, 0x44, 0x00, 0x14, 0x4e, 0x62, 0x00, 0x0a, +0x46, 0x06, 0x02, 0x04, 0x46, 0x12, 0xf0, 0xa2, 0x58, 0x00, 0x02, 0x6c, 0x48, 0x00, 0x00, 0x10, +0x46, 0x06, 0x02, 0x04, 0x46, 0x12, 0xf1, 0x82, 0x58, 0x00, 0x02, 0x6c, 0x48, 0x00, 0x00, 0x08, +0x46, 0x06, 0x02, 0x04, 0x46, 0x12, 0xf1, 0x62, 0x58, 0x00, 0x02, 0x6c, 0x54, 0x31, 0x80, 0x40, +0x14, 0x10, 0x00, 0x00, 0x4e, 0x32, 0x00, 0x0a, 0x46, 0x00, 0x03, 0xff, 0x58, 0x11, 0x00, 0x00, +0x58, 0x00, 0x08, 0xf8, 0x48, 0x00, 0x00, 0x0a, 0x46, 0x00, 0x03, 0xfb, 0x46, 0x26, 0x02, 0x04, +0x46, 0x16, 0x02, 0x04, 0x58, 0x00, 0x08, 0xb8, 0x14, 0x01, 0x01, 0xc5, 0x14, 0x00, 0x81, 0xc6, +0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x00, 0xfc, 0x04, 0x70, 0x00, 0x00, 0x46, 0x8f, 0xfe, 0x00, +0x58, 0x84, 0x00, 0x0f, 0x40, 0x73, 0xa0, 0x02, 0x58, 0x54, 0x80, 0x00, 0x46, 0x46, 0x02, 0x00, +0x46, 0x12, 0x00, 0xfc, 0x58, 0x32, 0x80, 0x00, 0x14, 0x70, 0x00, 0x00, 0x58, 0x10, 0x80, 0x0c, +0x44, 0x70, 0x00, 0x00, 0x46, 0x26, 0x02, 0x04, 0x14, 0x72, 0x80, 0x5f, 0x14, 0x12, 0x01, 0x45, +0x14, 0x11, 0x81, 0x45, 0x44, 0x10, 0xc4, 0xc6, 0x14, 0x11, 0x01, 0x23, 0x58, 0x51, 0x00, 0x00, +0x04, 0x82, 0x80, 0x64, 0x44, 0x3c, 0xff, 0xff, 0x40, 0x44, 0x0c, 0x02, 0x42, 0x22, 0x40, 0x08, +0x14, 0x22, 0x80, 0x64, 0x46, 0x7f, 0xff, 0x00, 0x04, 0x10, 0x00, 0x00, 0x58, 0x73, 0x80, 0x0f, +0x40, 0x80, 0x9c, 0x02, 0x14, 0x80, 0x00, 0x00, 0x2e, 0x47, 0xb2, 0xea, 0x4e, 0x43, 0x00, 0x06, +0x2e, 0x07, 0xb2, 0xeb, 0x4e, 0x02, 0x00, 0x54, 0x46, 0x26, 0x02, 0x00, 0x46, 0x04, 0xf1, 0x7b, +0x58, 0x84, 0x80, 0x00, 0x58, 0x00, 0x0b, 0xf5, 0x14, 0x01, 0x01, 0x46, 0x58, 0x11, 0x00, 0x00, +0x14, 0x04, 0x01, 0x46, 0x04, 0x30, 0x81, 0x40, 0x46, 0x7f, 0xff, 0x00, 0x40, 0x41, 0x9c, 0x02, +0x58, 0x52, 0x77, 0x6f, 0x14, 0x50, 0x81, 0x40, 0x58, 0x04, 0x00, 0x00, 0x04, 0x80, 0x01, 0x40, +0x40, 0x24, 0x1c, 0x02, 0x58, 0x31, 0x77, 0x6f, 0x14, 0x30, 0x01, 0x40, 0x04, 0x40, 0x81, 0x48, +0x46, 0x8f, 0xf0, 0x00, 0x46, 0x30, 0x0b, 0x20, 0x40, 0x52, 0x20, 0x02, 0x58, 0x31, 0x84, 0xc1, +0x40, 0x72, 0x8c, 0x04, 0x14, 0x70, 0x81, 0x48, 0x04, 0x20, 0x01, 0x48, 0x58, 0x70, 0x80, 0x00, +0x40, 0x41, 0x20, 0x02, 0x40, 0x52, 0x0c, 0x04, 0x14, 0x50, 0x01, 0x48, 0x04, 0x13, 0x81, 0x61, +0x44, 0x40, 0xff, 0xff, 0x46, 0x30, 0xb4, 0x90, 0x40, 0x20, 0x90, 0x02, 0x40, 0x81, 0x0c, 0x04, +0x46, 0x06, 0x02, 0x01, 0x14, 0x83, 0x81, 0x61, 0x58, 0x00, 0x05, 0x84, 0x04, 0x50, 0x00, 0x00, +0x40, 0x12, 0x90, 0x02, 0x40, 0x10, 0x8c, 0x04, 0x48, 0x00, 0x00, 0x78, 0x49, 0xff, 0xfa, 0xc6, +0x2e, 0x77, 0xb4, 0xee, 0x4e, 0x73, 0x00, 0x1c, 0x46, 0x86, 0x02, 0x00, 0x04, 0x14, 0x01, 0x61, +0x44, 0x30, 0xff, 0xff, 0x46, 0x50, 0xb4, 0x90, 0x40, 0x70, 0x8c, 0x02, 0x40, 0x23, 0x94, 0x04, +0x46, 0x06, 0x02, 0x01, 0x14, 0x24, 0x01, 0x61, 0x58, 0x00, 0x05, 0x84, 0x04, 0x40, 0x00, 0x00, +0x41, 0xe2, 0x0c, 0x02, 0x40, 0x1f, 0x14, 0x04, 0x48, 0x00, 0x00, 0x58, 0x2e, 0x0f, 0xb4, 0xef, +0x5e, 0xf0, 0x7f, 0xfb, 0x4e, 0xf3, 0x00, 0x1c, 0x46, 0x86, 0x02, 0x00, 0x04, 0x14, 0x01, 0x61, +0x44, 0x30, 0xff, 0xff, 0x46, 0x50, 0xb4, 0x90, 0x40, 0x70, 0x8c, 0x02, 0x40, 0x23, 0x94, 0x04, +0x46, 0x06, 0x02, 0x01, 0x14, 0x24, 0x01, 0x61, 0x58, 0x00, 0x05, 0x84, 0x04, 0x40, 0x00, 0x00, +0x41, 0xe2, 0x0c, 0x02, 0x40, 0x1f, 0x14, 0x04, 0x48, 0x00, 0x00, 0x38, 0x5e, 0xf0, 0x7f, 0xf7, +0x4e, 0xf3, 0x00, 0x1c, 0x46, 0x86, 0x02, 0x00, 0x04, 0x14, 0x01, 0x61, 0x44, 0x50, 0xff, 0xff, +0x46, 0x40, 0xb6, 0x90, 0x40, 0x70, 0x94, 0x02, 0x40, 0x23, 0x90, 0x04, 0x46, 0x06, 0x02, 0x01, +0x14, 0x24, 0x01, 0x61, 0x58, 0x00, 0x05, 0x84, 0x04, 0x30, 0x00, 0x00, 0x41, 0xe1, 0x94, 0x02, +0x40, 0x1f, 0x10, 0x04, 0x48, 0x00, 0x00, 0x1a, 0x46, 0x86, 0x02, 0x00, 0x04, 0x14, 0x01, 0x61, +0x44, 0x50, 0xff, 0xff, 0x46, 0x40, 0xb6, 0x90, 0x40, 0x70, 0x94, 0x02, 0x40, 0x23, 0x90, 0x04, +0x46, 0x06, 0x02, 0x01, 0x14, 0x24, 0x01, 0x61, 0x58, 0x00, 0x05, 0x84, 0x04, 0x30, 0x00, 0x00, +0x41, 0xe1, 0x94, 0x02, 0x40, 0x1f, 0x10, 0x04, 0x46, 0x56, 0x02, 0x00, 0x46, 0x4b, 0x20, 0x10, +0x46, 0x36, 0x02, 0x01, 0x14, 0x10, 0x00, 0x00, 0x14, 0x42, 0x83, 0x45, 0x14, 0x41, 0x83, 0x45, +0x2e, 0x27, 0xb0, 0xe1, 0x2e, 0x17, 0xb0, 0xe0, 0x4e, 0x62, 0x00, 0x0c, 0x46, 0x06, 0x02, 0x00, +0x46, 0x10, 0xcb, 0x00, 0x58, 0x00, 0x0d, 0x08, 0x58, 0x10, 0x80, 0x40, 0x48, 0x00, 0x00, 0x1e, +0x54, 0x00, 0x80, 0x7f, 0x4e, 0x02, 0x00, 0x12, 0x40, 0x70, 0x9c, 0x09, 0x40, 0x41, 0x50, 0x08, +0x40, 0x22, 0x00, 0x04, 0x40, 0x83, 0xcc, 0x08, 0x46, 0x06, 0x02, 0x00, 0x40, 0x11, 0x20, 0x04, +0x58, 0x00, 0x0d, 0x08, 0x48, 0x00, 0x00, 0x0a, 0x46, 0x06, 0x02, 0x00, 0x46, 0x10, 0xc9, 0xc0, +0x58, 0x00, 0x0d, 0x08, 0x58, 0x10, 0x80, 0x40, 0x14, 0x10, 0x00, 0x00, 0x2e, 0x27, 0xb0, 0xe7, +0x2e, 0x17, 0xb0, 0xe6, 0x4e, 0x62, 0x00, 0x0c, 0x46, 0x06, 0x02, 0x01, 0x46, 0x10, 0xcb, 0x80, +0x58, 0x00, 0x0d, 0x08, 0x58, 0x10, 0x80, 0x40, 0x48, 0x00, 0x00, 0x1e, 0x54, 0x00, 0x80, 0x7f, +0x4e, 0x02, 0x00, 0x12, 0x40, 0x50, 0x9c, 0x09, 0x40, 0x81, 0x50, 0x08, 0x40, 0x34, 0x00, 0x04, +0x40, 0x62, 0xcc, 0x08, 0x46, 0x06, 0x02, 0x01, 0x40, 0x11, 0x98, 0x04, 0x58, 0x00, 0x0d, 0x08, +0x48, 0x00, 0x00, 0x0a, 0x46, 0x06, 0x02, 0x01, 0x46, 0x10, 0xc9, 0xf0, 0x58, 0x00, 0x0d, 0x08, +0x58, 0x10, 0x80, 0x40, 0x14, 0x10, 0x00, 0x00, 0x2e, 0x07, 0xb4, 0xf4, 0x4e, 0x02, 0x00, 0x26, +0x46, 0x66, 0x02, 0x00, 0x04, 0x83, 0x03, 0x46, 0x44, 0x4f, 0x00, 0xff, 0x40, 0x54, 0x10, 0x02, +0x58, 0x32, 0x83, 0x00, 0x14, 0x33, 0x03, 0x46, 0x46, 0x26, 0x02, 0x01, 0x58, 0x21, 0x0d, 0x18, +0x04, 0x11, 0x00, 0x00, 0x46, 0x00, 0x30, 0x00, 0x40, 0x70, 0x90, 0x02, 0x46, 0x10, 0x20, 0x01, +0x46, 0x56, 0x02, 0x01, 0x58, 0x43, 0x00, 0x00, 0x58, 0x32, 0x80, 0x00, 0x58, 0x10, 0x86, 0x1f, +0x58, 0x73, 0x83, 0x00, 0x48, 0x00, 0x00, 0x24, 0x46, 0x06, 0x02, 0x00, 0x04, 0x40, 0x03, 0x46, +0x44, 0x6f, 0x00, 0xff, 0x40, 0x12, 0x18, 0x02, 0x14, 0x10, 0x03, 0x46, 0x46, 0x26, 0x02, 0x01, +0x58, 0x21, 0x0d, 0x18, 0x04, 0x71, 0x00, 0x00, 0x46, 0x18, 0x20, 0x01, 0x46, 0x00, 0x60, 0x20, +0x58, 0x83, 0x00, 0x00, 0x46, 0x66, 0x02, 0x00, 0x46, 0x56, 0x02, 0x01, 0x46, 0x46, 0x02, 0x00, +0x46, 0x36, 0x02, 0x01, 0x58, 0x10, 0x83, 0x1a, 0x40, 0x73, 0xa0, 0x02, 0x14, 0x71, 0x00, 0x00, +0x14, 0x13, 0x03, 0x47, 0x46, 0x76, 0x02, 0x04, 0x14, 0x12, 0x83, 0x47, 0x14, 0x02, 0x03, 0x48, +0x14, 0x01, 0x83, 0x48, 0x58, 0x73, 0x86, 0x00, 0x04, 0x03, 0x80, 0x00, 0x42, 0x40, 0x58, 0x09, +0x42, 0x42, 0x5c, 0x09, 0x42, 0x82, 0x5c, 0x08, 0x14, 0x83, 0x80, 0x00, 0x04, 0x63, 0x80, 0x00, +0x46, 0x16, 0x02, 0x00, 0x42, 0x23, 0x1c, 0x09, 0x14, 0x23, 0x80, 0x00, 0x04, 0x30, 0x81, 0x8e, +0x40, 0x41, 0x94, 0x09, 0x40, 0x42, 0x14, 0x08, 0x58, 0x62, 0x00, 0x1e, 0x14, 0x60, 0x81, 0x8e, +0x58, 0x80, 0x80, 0x00, 0x04, 0x54, 0x01, 0x83, 0x46, 0x73, 0x00, 0x00, 0x40, 0x02, 0x9c, 0x04, +0x14, 0x04, 0x01, 0x83, 0x46, 0x26, 0x02, 0x04, 0x58, 0x21, 0x02, 0x00, 0x04, 0x31, 0x00, 0x00, +0x46, 0x6f, 0xff, 0x00, 0x58, 0x41, 0x83, 0xff, 0x14, 0x41, 0x00, 0x00, 0x58, 0x63, 0x03, 0xff, +0x04, 0x51, 0x00, 0x00, 0x44, 0x81, 0x60, 0x00, 0x40, 0x72, 0x98, 0x02, 0x40, 0x33, 0xa0, 0x04, +0x14, 0x31, 0x00, 0x00, 0x46, 0x16, 0x01, 0x30, 0x58, 0x10, 0x80, 0x9c, 0x04, 0x50, 0x80, 0x00, +0x40, 0x82, 0xa4, 0x09, 0x40, 0x84, 0x24, 0x08, 0x14, 0x80, 0x80, 0x00, 0x04, 0x70, 0x80, 0x00, +0x50, 0x00, 0xff, 0xfc, 0x58, 0x23, 0x80, 0x82, 0x14, 0x20, 0x80, 0x00, 0x04, 0x80, 0x00, 0x00, +0x46, 0x46, 0x02, 0x04, 0x40, 0x14, 0x20, 0x09, 0x40, 0x10, 0xa0, 0x08, 0x14, 0x10, 0x00, 0x00, +0x04, 0x70, 0x00, 0x00, 0x58, 0x53, 0x80, 0x14, 0x14, 0x50, 0x00, 0x00, 0x46, 0x36, 0x02, 0x04, +0x04, 0x02, 0x00, 0x8a, 0x58, 0x31, 0x82, 0x0c, 0x40, 0x70, 0x14, 0x09, 0x40, 0x73, 0x94, 0x08, +0x58, 0x03, 0x80, 0x0d, 0x14, 0x02, 0x00, 0x8a, 0x46, 0x78, 0x00, 0x00, 0x04, 0x81, 0x80, 0x00, +0x58, 0x73, 0x80, 0xff, 0x40, 0x04, 0x1c, 0x02, 0x46, 0x77, 0xc9, 0x00, 0x58, 0x73, 0x84, 0x00, +0x40, 0x00, 0x1c, 0x04, 0x14, 0x01, 0x80, 0x00, 0x04, 0x71, 0x80, 0x00, 0x46, 0x66, 0x02, 0x00, +0x40, 0x73, 0xa0, 0x09, 0x40, 0x73, 0xa0, 0x08, 0x58, 0x83, 0x80, 0x01, 0x14, 0x81, 0x80, 0x00, +0x04, 0x33, 0x01, 0x86, 0x40, 0x81, 0xbc, 0x09, 0x40, 0x84, 0x3c, 0x08, 0x58, 0x34, 0x7d, 0x10, +0x14, 0x33, 0x01, 0x86, 0x46, 0x26, 0x02, 0x00, 0x58, 0x21, 0x06, 0x34, 0x04, 0x71, 0x00, 0x00, +0x42, 0x63, 0x80, 0x09, 0x14, 0x61, 0x00, 0x00, 0x04, 0x31, 0x00, 0x00, 0x46, 0x60, 0x1f, 0x80, +0x40, 0x71, 0x98, 0x04, 0x14, 0x71, 0x00, 0x00, 0x50, 0x11, 0x7f, 0xe0, 0x04, 0x20, 0x80, 0x00, +0x42, 0x81, 0x4c, 0x09, 0x14, 0x80, 0x80, 0x00, 0x44, 0x8f, 0x00, 0xff, 0x04, 0x30, 0x80, 0x00, +0x46, 0x56, 0x02, 0x01, 0x40, 0x21, 0xa0, 0x02, 0x58, 0x31, 0x4d, 0x00, 0x14, 0x30, 0x80, 0x00, +0x04, 0x22, 0x81, 0xbc, 0x46, 0x46, 0x02, 0x00, 0x40, 0x31, 0x20, 0x02, 0x58, 0x11, 0xb0, 0x00, +0x14, 0x12, 0x81, 0xbc, 0x04, 0x52, 0x01, 0xbc, 0x46, 0x33, 0x40, 0x00, 0x40, 0x12, 0xa0, 0x08, +0x40, 0x10, 0xa0, 0x09, 0x40, 0x50, 0x8c, 0x04, 0x14, 0x52, 0x01, 0xbc, 0x46, 0x06, 0x02, 0x04, +0x58, 0x00, 0x00, 0xf0, 0x04, 0x20, 0x00, 0x00, 0x58, 0x41, 0x00, 0x02, 0x14, 0x40, 0x00, 0x00, +0x04, 0x10, 0x00, 0x00, 0x58, 0x50, 0x80, 0x04, 0x14, 0x50, 0x00, 0x00, 0x2e, 0x27, 0xb4, 0xf1, +0x4e, 0x22, 0x00, 0x16, 0x46, 0x06, 0x02, 0x00, 0x04, 0x10, 0x03, 0x44, 0x46, 0x40, 0x0f, 0xff, +0x58, 0x42, 0x0f, 0xff, 0x40, 0x30, 0x90, 0x02, 0x14, 0x30, 0x03, 0x44, 0x46, 0x56, 0x02, 0x01, +0x04, 0x22, 0x83, 0x44, 0x40, 0x11, 0x10, 0x02, 0x14, 0x12, 0x83, 0x44, 0x46, 0x26, 0x02, 0x04, +0x04, 0x01, 0x00, 0x64, 0x42, 0x40, 0x1c, 0x09, 0x14, 0x41, 0x00, 0x64, 0x51, 0xff, 0x80, 0x2c, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3c, 0x0d, 0xed, 0x42, 0x4a, 0x00, 0x78, 0x20, +0x46, 0x08, 0x00, 0x23, 0x04, 0x10, 0x00, 0x20, 0x46, 0x21, 0x10, 0x00, 0x40, 0x40, 0x88, 0x04, +0x14, 0x40, 0x00, 0x20, 0x58, 0x50, 0x00, 0x00, 0x04, 0x22, 0x80, 0x21, 0x44, 0x31, 0x01, 0x11, +0x40, 0x11, 0x0c, 0x04, 0x14, 0x12, 0x80, 0x21, 0x46, 0x08, 0x00, 0x00, 0x04, 0x40, 0x00, 0x42, +0x46, 0x18, 0x10, 0x60, 0x46, 0x20, 0x48, 0x52, 0x58, 0x32, 0x40, 0x00, 0x58, 0x21, 0x03, 0x90, +0x14, 0x30, 0x00, 0x42, 0x14, 0x20, 0x80, 0x02, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x36, 0x02, 0x00, +0x14, 0x11, 0x83, 0x80, 0x4e, 0x23, 0x00, 0x08, 0x58, 0x11, 0x80, 0x00, 0x44, 0x21, 0x10, 0x00, +0x48, 0x00, 0x00, 0x06, 0x46, 0x16, 0x02, 0x00, 0x44, 0x23, 0x10, 0x00, 0x40, 0x00, 0x08, 0x00, +0x14, 0x00, 0x83, 0x81, 0x58, 0x01, 0x80, 0x00, 0x04, 0x20, 0x03, 0x84, 0x54, 0x11, 0x20, 0x00, +0x4e, 0x13, 0xff, 0xfc, 0x4a, 0x00, 0x78, 0x20, 0x4e, 0x13, 0x00, 0x0c, 0x44, 0x1e, 0xef, 0xff, +0x40, 0x00, 0x04, 0x02, 0x44, 0x21, 0x00, 0x00, 0x46, 0x16, 0x02, 0x00, 0x48, 0x00, 0x00, 0x0a, +0x44, 0x2c, 0xef, 0xff, 0x40, 0x00, 0x08, 0x02, 0x46, 0x16, 0x02, 0x00, 0x44, 0x23, 0x00, 0x00, +0x40, 0x00, 0x08, 0x04, 0x14, 0x00, 0x83, 0x81, 0x46, 0x06, 0x02, 0x00, 0x04, 0x40, 0x03, 0x84, +0x54, 0x32, 0x20, 0x00, 0x4e, 0x33, 0xff, 0xfc, 0x58, 0x50, 0x00, 0x00, 0x04, 0x02, 0x83, 0x83, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, 0x58, 0x61, 0x00, 0x00, 0x58, 0xa2, 0x00, 0x00, +0x58, 0x91, 0x80, 0x00, 0x58, 0x70, 0x80, 0x00, 0x58, 0x80, 0x00, 0x00, 0x49, 0xff, 0xff, 0xce, +0x40, 0x35, 0x24, 0x0c, 0x40, 0x13, 0x18, 0x05, 0x40, 0x50, 0x04, 0x02, 0x40, 0x61, 0x98, 0x02, +0x40, 0x12, 0x98, 0x04, 0x58, 0x04, 0x00, 0x00, 0x58, 0x23, 0x80, 0x00, 0x49, 0xff, 0xff, 0xa0, +0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x58, 0x80, 0x80, 0x00, +0x58, 0x11, 0x00, 0x00, 0x58, 0x61, 0x00, 0x00, 0x58, 0x70, 0x00, 0x00, 0x49, 0xff, 0xff, 0xae, +0x40, 0x10, 0x20, 0x04, 0x58, 0x23, 0x00, 0x00, 0x58, 0x03, 0x80, 0x00, 0x49, 0xff, 0xff, 0x88, +0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x58, 0x80, 0x80, 0x00, +0x58, 0x11, 0x00, 0x00, 0x58, 0x61, 0x00, 0x00, 0x58, 0x70, 0x00, 0x00, 0x49, 0xff, 0xff, 0x96, +0x40, 0x14, 0x20, 0x05, 0x40, 0x10, 0x04, 0x02, 0x58, 0x23, 0x00, 0x00, 0x58, 0x03, 0x80, 0x00, +0x49, 0xff, 0xff, 0x6e, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, +0x54, 0x70, 0x00, 0xff, 0x4e, 0x72, 0x00, 0x14, 0x3e, 0x6f, 0xab, 0x30, 0x04, 0x03, 0x00, 0x00, +0x04, 0x13, 0x00, 0x01, 0x04, 0x23, 0x00, 0x05, 0x50, 0x63, 0x00, 0x18, 0x49, 0xff, 0xff, 0x58, +0x3e, 0x5f, 0xac, 0x50, 0x4c, 0x62, 0xff, 0xf4, 0x48, 0x00, 0x00, 0x22, 0x3e, 0x6f, 0xab, 0x30, +0x44, 0x90, 0x00, 0x06, 0x2e, 0x17, 0xb4, 0xf0, 0x3e, 0x3f, 0xab, 0x00, 0x42, 0x13, 0xa4, 0x73, +0x04, 0x03, 0x00, 0x00, 0x51, 0xe0, 0x80, 0x0b, 0x40, 0x5f, 0x08, 0x08, 0x40, 0x42, 0x8c, 0x00, +0x04, 0x23, 0x00, 0x05, 0x04, 0x12, 0x00, 0x01, 0x50, 0x73, 0x80, 0x01, 0x49, 0xff, 0xff, 0x38, +0x44, 0x50, 0x00, 0x0c, 0x50, 0x63, 0x00, 0x18, 0x4c, 0x72, 0xff, 0xe6, 0x3a, 0x6f, 0xa8, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x58, 0x60, 0x00, 0x00, +0x44, 0x00, 0x00, 0x01, 0x4c, 0x60, 0x40, 0x1c, 0x46, 0x2f, 0x00, 0x00, 0x58, 0x43, 0x00, 0x00, +0x44, 0x00, 0x00, 0xa0, 0x44, 0x10, 0x00, 0x00, 0x44, 0x30, 0x00, 0x1c, 0x49, 0xff, 0xff, 0x5c, +0x46, 0x2f, 0x00, 0x00, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x00, 0xa0, 0x44, 0x30, 0x00, 0x1c, +0x58, 0x43, 0x00, 0x00, 0x49, 0xff, 0xff, 0x50, 0x48, 0x00, 0x00, 0x24, 0x4e, 0x62, 0x00, 0x0a, +0x44, 0x10, 0x00, 0x05, 0x4c, 0x60, 0x80, 0x06, 0x44, 0x50, 0x00, 0x04, 0x4c, 0x62, 0xc0, 0x1a, +0x44, 0x10, 0x00, 0x00, 0x46, 0x2f, 0x00, 0x00, 0x58, 0x40, 0x80, 0x00, 0x44, 0x00, 0x00, 0xa0, +0x44, 0x30, 0x00, 0x1c, 0x49, 0xff, 0xff, 0x38, 0x46, 0x2f, 0x00, 0x00, 0x44, 0x00, 0x00, 0xa0, +0x44, 0x10, 0x00, 0x01, 0x44, 0x30, 0x00, 0x1c, 0x44, 0x40, 0x00, 0x00, 0x49, 0xff, 0xff, 0x2c, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x3e, 0x0f, 0xae, 0x74, 0x44, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0c, +0x04, 0x30, 0x00, 0x00, 0x04, 0x40, 0x00, 0x01, 0x50, 0x10, 0x80, 0x01, 0x14, 0x41, 0x80, 0x00, +0x50, 0x00, 0x00, 0x08, 0x2e, 0x57, 0xb5, 0x0d, 0x40, 0xf0, 0x94, 0x06, 0x4e, 0xf3, 0xff, 0xf2, +0x44, 0x00, 0x00, 0x00, 0x49, 0xff, 0xff, 0x5c, 0x3e, 0x6f, 0xaf, 0x84, 0x44, 0x70, 0x00, 0x00, +0x48, 0x00, 0x00, 0x0c, 0x04, 0x03, 0x00, 0x00, 0x04, 0x13, 0x00, 0x01, 0x50, 0x73, 0x80, 0x01, +0x49, 0xff, 0xfe, 0xb6, 0x50, 0x63, 0x00, 0x08, 0x2e, 0x07, 0xb5, 0x0e, 0x44, 0x20, 0x00, 0x00, +0x40, 0xf3, 0x80, 0x06, 0x4e, 0xf3, 0xff, 0xf0, 0x2e, 0x77, 0xb4, 0xf0, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x72, 0xc0, 0x0a, 0x46, 0x1a, 0x88, 0x88, 0x58, 0x10, 0x88, 0x88, 0x44, 0x00, 0x00, 0x78, +0x48, 0x00, 0x00, 0x0a, 0x46, 0x18, 0x88, 0x88, 0x58, 0x10, 0x88, 0x88, 0x44, 0x00, 0x00, 0x78, +0x44, 0x20, 0x00, 0x00, 0x49, 0xff, 0xfe, 0x94, 0x2e, 0x77, 0xb2, 0xea, 0x4e, 0x72, 0x00, 0x16, +0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x00, 0x44, 0x00, 0x06, 0x10, 0x44, 0x20, 0x00, 0x00, +0x49, 0xff, 0xfe, 0x86, 0x46, 0x10, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, 0x44, 0x00, 0x00, 0x54, +0x44, 0x20, 0x00, 0x00, 0x48, 0x00, 0x00, 0x14, 0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x08, +0x44, 0x00, 0x06, 0x10, 0x58, 0x23, 0x80, 0x00, 0x49, 0xff, 0xfe, 0x72, 0x46, 0x18, 0x3f, 0xf0, +0x58, 0x10, 0x80, 0x03, 0x58, 0x23, 0x80, 0x00, 0x44, 0x00, 0x00, 0x54, 0x49, 0xff, 0xfe, 0x68, +0x2e, 0x27, 0xb4, 0xf4, 0x4e, 0x23, 0x00, 0x0a, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x81, +0x44, 0x00, 0x00, 0xe8, 0x48, 0x00, 0x00, 0x0a, 0x46, 0x10, 0x0a, 0x10, 0x58, 0x10, 0x80, 0xe1, +0x44, 0x00, 0x00, 0xe8, 0x44, 0x20, 0x00, 0x00, 0x49, 0xff, 0xfe, 0x52, 0x3c, 0x4d, 0xed, 0x42, +0x5c, 0xf2, 0x00, 0x02, 0x4e, 0xf3, 0x00, 0x1a, 0x3e, 0x6f, 0xaf, 0xd4, 0x44, 0x70, 0x00, 0x00, +0x48, 0x00, 0x00, 0x0c, 0x04, 0x03, 0x00, 0x00, 0x04, 0x13, 0x00, 0x01, 0x50, 0x73, 0x80, 0x01, +0x49, 0xff, 0xfe, 0x3e, 0x50, 0x63, 0x00, 0x08, 0x2f, 0xe7, 0xb5, 0x0f, 0x44, 0x20, 0x00, 0x01, +0x40, 0xf3, 0xf8, 0x06, 0x4e, 0xf3, 0xff, 0xf0, 0x2e, 0x27, 0xb4, 0xf0, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x22, 0xc0, 0x0a, 0x46, 0x1a, 0x88, 0x88, 0x58, 0x10, 0x88, 0x88, 0x44, 0x00, 0x00, 0x78, +0x48, 0x00, 0x00, 0x0a, 0x46, 0x18, 0x88, 0x88, 0x58, 0x10, 0x88, 0x88, 0x44, 0x00, 0x00, 0x78, +0x44, 0x20, 0x00, 0x01, 0x49, 0xff, 0xfe, 0x1c, 0x2e, 0x27, 0xb2, 0xeb, 0x4e, 0x22, 0x00, 0x12, +0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x00, 0x44, 0x00, 0x06, 0x10, 0x44, 0x20, 0x00, 0x01, +0x49, 0xff, 0xfe, 0x0e, 0x46, 0x10, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, 0x48, 0x00, 0x00, 0x10, +0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x08, 0x44, 0x00, 0x06, 0x10, 0x44, 0x20, 0x00, 0x01, +0x49, 0xff, 0xfd, 0xfe, 0x46, 0x18, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, 0x44, 0x00, 0x00, 0x54, +0x44, 0x20, 0x00, 0x01, 0x49, 0xff, 0xfd, 0xf4, 0x2e, 0x37, 0xb4, 0xf4, 0x4e, 0x32, 0x00, 0x08, +0x46, 0x10, 0x0a, 0x10, 0x58, 0x10, 0x80, 0xe1, 0x48, 0x00, 0x00, 0x06, 0x46, 0x10, 0x06, 0x10, +0x58, 0x10, 0x80, 0x81, 0x44, 0x00, 0x00, 0xe8, 0x44, 0x20, 0x00, 0x01, 0x49, 0xff, 0xfd, 0xe0, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x47, 0xe6, 0x02, 0x00, 0x04, 0x3f, 0x00, 0x00, 0x58, 0x5f, 0x00, 0x00, +0x58, 0x21, 0x80, 0x45, 0x14, 0x2f, 0x00, 0x00, 0x04, 0x42, 0x80, 0x01, 0x40, 0x10, 0x80, 0x13, +0x58, 0x32, 0x00, 0x45, 0x44, 0x20, 0x00, 0x0e, 0x14, 0x32, 0x80, 0x01, 0x4c, 0x11, 0x40, 0x12, +0x3e, 0x1f, 0xa9, 0xc0, 0x04, 0x40, 0x80, 0x00, 0x05, 0xe0, 0x80, 0x01, 0x3e, 0x5f, 0xaa, 0x60, +0x50, 0x10, 0x80, 0x08, 0x15, 0xe2, 0x00, 0x00, 0x4c, 0x12, 0xff, 0xf6, 0x48, 0x00, 0x00, 0x10, +0x3e, 0x1f, 0xaa, 0x60, 0x04, 0x50, 0x80, 0x00, 0x04, 0x30, 0x80, 0x01, 0x3e, 0x2f, 0xab, 0x00, +0x50, 0x10, 0x80, 0x08, 0x14, 0x32, 0x80, 0x00, 0x4c, 0x11, 0x7f, 0xf6, 0x2e, 0x17, 0xb4, 0xf4, +0x4e, 0x13, 0x00, 0x72, 0x2f, 0xe7, 0xb1, 0x1d, 0x54, 0x0f, 0x00, 0x40, 0x4e, 0x03, 0x00, 0x56, +0x2e, 0x57, 0xb5, 0x18, 0x44, 0x30, 0x00, 0x01, 0x4c, 0x51, 0xc0, 0x0c, 0x46, 0x06, 0x02, 0x00, +0x58, 0x00, 0x0a, 0x08, 0x46, 0x2f, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x18, +0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x0a, 0x08, 0x05, 0xe0, 0x00, 0x00, 0x40, 0x1f, 0x10, 0x08, +0x40, 0x10, 0x90, 0x09, 0x14, 0x10, 0x00, 0x00, 0x2e, 0x27, 0xc7, 0xfc, 0x05, 0xe0, 0x00, 0x00, +0x44, 0x4f, 0x00, 0xff, 0x40, 0x21, 0x20, 0x08, 0x40, 0x1f, 0x10, 0x02, 0x40, 0x51, 0x04, 0x04, +0x14, 0x50, 0x00, 0x00, 0x2e, 0x07, 0xb5, 0x19, 0x44, 0x40, 0x00, 0x01, 0x4c, 0x02, 0x40, 0x0c, +0x46, 0x06, 0x02, 0x01, 0x58, 0x00, 0x0a, 0x08, 0x46, 0x2f, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, +0x48, 0x00, 0x00, 0x18, 0x46, 0x06, 0x02, 0x01, 0x58, 0x00, 0x0a, 0x08, 0x04, 0x50, 0x00, 0x00, +0x40, 0x22, 0x90, 0x08, 0x40, 0x21, 0x10, 0x09, 0x14, 0x20, 0x00, 0x00, 0x2e, 0x37, 0xc7, 0xfd, +0x04, 0x10, 0x00, 0x00, 0x45, 0xef, 0x00, 0xff, 0x40, 0x21, 0xa0, 0x08, 0x40, 0x10, 0xf8, 0x02, +0x40, 0x11, 0x04, 0x04, 0x48, 0x00, 0x00, 0x14, 0x46, 0x46, 0x02, 0x00, 0x04, 0x52, 0x02, 0x82, +0x46, 0x3f, 0x00, 0x00, 0x40, 0x22, 0x8c, 0x04, 0x46, 0x06, 0x02, 0x01, 0x14, 0x22, 0x02, 0x82, +0x58, 0x00, 0x0a, 0x08, 0x05, 0xe0, 0x00, 0x00, 0x40, 0x1f, 0x0c, 0x04, 0x14, 0x10, 0x00, 0x00, +0x48, 0x00, 0x00, 0x1e, 0x46, 0x16, 0x02, 0x00, 0x05, 0xe0, 0x82, 0x82, 0x46, 0x4f, 0x00, 0x00, +0x40, 0x5f, 0x10, 0x04, 0x14, 0x50, 0x82, 0x82, 0x46, 0x36, 0x02, 0x01, 0x04, 0x21, 0x82, 0x82, +0x46, 0x10, 0x10, 0x00, 0x41, 0xe1, 0x10, 0x04, 0x15, 0xe1, 0x82, 0x82, 0x58, 0x20, 0x00, 0x00, +0x58, 0x10, 0x87, 0x00, 0x44, 0x00, 0x00, 0x70, 0x49, 0xff, 0xfd, 0x12, 0x2e, 0x27, 0xb5, 0x0c, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x22, 0xc0, 0x0a, 0x46, 0x18, 0x10, 0x08, 0x58, 0x10, 0x82, 0xd0, +0x44, 0x00, 0x00, 0x44, 0x49, 0xff, 0xfd, 0x04, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x58, 0x60, 0x80, 0x00, +0x4e, 0x02, 0x00, 0x06, 0x44, 0x50, 0x00, 0x05, 0x4c, 0x02, 0xc0, 0x0c, 0x40, 0x83, 0x14, 0x08, +0x3e, 0x0f, 0xc4, 0x9c, 0x40, 0x84, 0x00, 0x00, 0x44, 0x70, 0x04, 0x28, 0x48, 0x00, 0x00, 0x08, +0x44, 0x50, 0x00, 0x04, 0x4c, 0x02, 0xc0, 0x60, 0x48, 0xff, 0xff, 0xf2, 0x04, 0x14, 0x00, 0x00, +0x58, 0x03, 0x80, 0x00, 0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xfc, 0xda, 0x04, 0x14, 0x00, 0x20, +0x50, 0x03, 0x82, 0xa4, 0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xfc, 0xd2, 0x50, 0x73, 0x80, 0x04, +0x44, 0x50, 0x04, 0x48, 0x50, 0x84, 0x00, 0x04, 0x4c, 0x72, 0xff, 0xea, 0x4e, 0x63, 0x00, 0x22, +0x3e, 0x4f, 0xc4, 0x60, 0x05, 0xe2, 0x00, 0xcd, 0x46, 0x56, 0x02, 0x00, 0x15, 0xe2, 0x80, 0x56, +0x58, 0x32, 0x80, 0x00, 0x04, 0x22, 0x00, 0xce, 0x14, 0x21, 0x80, 0x57, 0x58, 0x11, 0x80, 0x00, +0x04, 0x02, 0x00, 0xcf, 0x14, 0x00, 0x80, 0x58, 0x58, 0x50, 0x80, 0x00, 0x05, 0xe2, 0x00, 0xd9, +0x15, 0xe2, 0x80, 0x62, 0x46, 0x16, 0x02, 0x00, 0x04, 0x02, 0x00, 0xda, 0x48, 0x00, 0x00, 0x66, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x8a, 0x3e, 0x0f, 0xc4, 0x60, 0x04, 0x30, 0x00, 0xd0, +0x46, 0x16, 0x02, 0x01, 0x14, 0x30, 0x80, 0x56, 0x59, 0xe0, 0x80, 0x00, 0x04, 0x40, 0x00, 0xd1, +0x14, 0x4f, 0x00, 0x57, 0x58, 0x50, 0x80, 0x00, 0x04, 0x20, 0x00, 0xd2, 0x14, 0x22, 0x80, 0x58, +0x04, 0x30, 0x00, 0xdb, 0x14, 0x30, 0x80, 0x62, 0x46, 0x16, 0x02, 0x01, 0x04, 0x00, 0x00, 0xdc, +0x48, 0x00, 0x00, 0x68, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x68, 0x40, 0x93, 0x14, 0x08, +0x3e, 0x0f, 0xc4, 0xdc, 0x40, 0x84, 0x80, 0x00, 0x44, 0x70, 0x04, 0x48, 0x04, 0x14, 0x00, 0x00, +0x58, 0x03, 0x80, 0x00, 0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xfc, 0x72, 0x04, 0x14, 0x00, 0x20, +0x50, 0x03, 0x82, 0x84, 0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xfc, 0x6a, 0x50, 0x73, 0x80, 0x04, +0x44, 0x50, 0x04, 0x68, 0x50, 0x84, 0x00, 0x04, 0x4c, 0x72, 0xff, 0xea, 0x4e, 0x63, 0x00, 0x22, +0x3c, 0x2d, 0xf1, 0xeb, 0x46, 0x46, 0x02, 0x00, 0x14, 0x22, 0x00, 0x56, 0x58, 0x02, 0x00, 0x00, +0x3c, 0x5d, 0xf1, 0xec, 0x14, 0x50, 0x00, 0x57, 0x58, 0x10, 0x00, 0x00, 0x3c, 0x3d, 0xf1, 0xed, +0x14, 0x30, 0x80, 0x58, 0x58, 0x40, 0x00, 0x00, 0x3c, 0x2d, 0xf1, 0xf5, 0x14, 0x22, 0x00, 0x62, +0x46, 0x16, 0x02, 0x00, 0x3c, 0x0d, 0xf1, 0xf6, 0x58, 0x10, 0x81, 0x8c, 0x48, 0x00, 0x00, 0x24, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x22, 0x3e, 0x3f, 0xc4, 0x60, 0x04, 0x01, 0x80, 0xd6, +0x46, 0x16, 0x02, 0x01, 0x14, 0x00, 0x80, 0x56, 0x59, 0xe0, 0x80, 0x00, 0x04, 0x21, 0x80, 0xd7, +0x14, 0x2f, 0x00, 0x57, 0x58, 0x50, 0x80, 0x00, 0x04, 0x41, 0x80, 0xd8, 0x14, 0x42, 0x80, 0x58, +0x04, 0x01, 0x80, 0xdf, 0x14, 0x00, 0x80, 0x62, 0x46, 0x16, 0x02, 0x01, 0x04, 0x01, 0x80, 0xe0, +0x58, 0x10, 0x81, 0x8c, 0x14, 0x00, 0x80, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xa4, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x2e, 0x17, 0xb0, 0xda, 0x54, 0x00, 0x80, 0x20, 0x4e, 0x02, 0x00, 0x62, +0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x0d, 0x18, 0x04, 0x10, 0x00, 0x00, 0x40, 0x50, 0xa8, 0x08, +0x40, 0x12, 0xe8, 0x09, 0x54, 0x40, 0x80, 0x20, 0x40, 0x32, 0x00, 0x10, 0x4e, 0x32, 0x00, 0x0a, +0x50, 0x30, 0xff, 0xc0, 0x5e, 0xf1, 0xff, 0xf0, 0x4e, 0xf3, 0x00, 0x12, 0x48, 0x00, 0x00, 0x1a, +0x5e, 0xf0, 0x80, 0x10, 0x4e, 0xf3, 0x00, 0x16, 0x04, 0x50, 0x00, 0x00, 0x40, 0x42, 0xa0, 0x09, +0x40, 0x42, 0x20, 0x08, 0x58, 0x12, 0x00, 0x10, 0x48, 0x00, 0x00, 0x0a, 0x04, 0x40, 0x00, 0x00, +0x40, 0x32, 0x20, 0x09, 0x40, 0x31, 0xa0, 0x08, 0x58, 0x11, 0x80, 0xf0, 0x14, 0x10, 0x00, 0x00, +0x46, 0x06, 0x02, 0x01, 0x58, 0x00, 0x0d, 0x18, 0x04, 0x40, 0x00, 0x00, 0x40, 0x12, 0x28, 0x08, +0x40, 0x10, 0xe8, 0x09, 0x54, 0x30, 0x80, 0x20, 0x40, 0x51, 0x80, 0x10, 0x4e, 0x52, 0x00, 0x0a, +0x50, 0x50, 0xff, 0xc0, 0x5e, 0xf2, 0xff, 0xf0, 0x4e, 0xf3, 0x00, 0x12, 0x48, 0x00, 0x00, 0x1a, +0x5e, 0xf0, 0x80, 0x10, 0x4e, 0xf3, 0x00, 0x16, 0x04, 0x10, 0x00, 0x00, 0x40, 0x30, 0xa0, 0x09, +0x40, 0x31, 0xa0, 0x08, 0x58, 0x11, 0x80, 0x10, 0x48, 0x00, 0x00, 0x0a, 0x04, 0x30, 0x00, 0x00, +0x40, 0x51, 0xa0, 0x09, 0x40, 0x52, 0xa0, 0x08, 0x58, 0x12, 0x80, 0xf0, 0x14, 0x10, 0x00, 0x00, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x2e, 0x27, 0xb4, 0xf1, +0x14, 0x2f, 0x80, 0x01, 0x4e, 0x03, 0x00, 0x2e, 0x47, 0xc6, 0x02, 0x00, 0x58, 0xae, 0x00, 0x00, +0x46, 0x96, 0x02, 0x04, 0x45, 0xe0, 0x02, 0x45, 0x46, 0x86, 0x02, 0x00, 0x46, 0x66, 0x02, 0x04, +0x46, 0x75, 0x57, 0x84, 0x46, 0x12, 0x00, 0xfc, 0x46, 0x35, 0x7c, 0x04, 0x15, 0xee, 0x00, 0x00, +0x58, 0x10, 0x80, 0x0c, 0x15, 0xe5, 0x00, 0x01, 0x58, 0x84, 0x03, 0x04, 0x14, 0x04, 0x80, 0x40, +0x58, 0x63, 0x04, 0x1c, 0x58, 0x73, 0x86, 0x88, 0x50, 0x54, 0x02, 0x10, 0x50, 0x42, 0x90, 0x00, +0x50, 0x23, 0x7f, 0xe8, 0x58, 0x31, 0x8e, 0x55, 0x44, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x82, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x4a, 0x46, 0x76, 0x02, 0x00, 0x58, 0x53, 0x80, 0x00, +0x44, 0x60, 0x02, 0x45, 0x14, 0x63, 0x80, 0x00, 0x14, 0x62, 0x80, 0x01, 0x4c, 0x10, 0x40, 0x0a, +0x46, 0x06, 0x02, 0x04, 0x46, 0x10, 0x10, 0x00, 0x58, 0x00, 0x01, 0x00, 0x48, 0x00, 0x00, 0x0c, +0x44, 0x00, 0x00, 0x03, 0x4c, 0x10, 0x40, 0x0a, 0x46, 0x06, 0x02, 0x04, 0x46, 0x10, 0x11, 0x00, +0x58, 0x00, 0x01, 0x00, 0x14, 0x10, 0x00, 0x00, 0x58, 0x72, 0x80, 0x00, 0x46, 0x36, 0x02, 0x04, +0x46, 0x65, 0x57, 0x84, 0x58, 0x22, 0x80, 0x00, 0x47, 0xc2, 0x00, 0xfc, 0x47, 0xe6, 0x02, 0x01, +0x58, 0x91, 0x80, 0x00, 0x46, 0xa5, 0x7c, 0x04, 0x59, 0xce, 0x00, 0x0c, 0x58, 0x63, 0x06, 0x88, +0x58, 0xa5, 0x0e, 0x55, 0x44, 0x80, 0x00, 0x10, 0x14, 0x83, 0x80, 0xc1, 0x14, 0x61, 0x81, 0x07, +0x15, 0xc1, 0x01, 0x45, 0x15, 0xcf, 0x01, 0x45, 0x14, 0xa4, 0x81, 0x01, 0x04, 0x1f, 0x80, 0x01, +0x4e, 0x12, 0x00, 0x96, 0x48, 0x00, 0x00, 0x82, 0x44, 0x50, 0x00, 0x05, 0x4c, 0x02, 0xc0, 0x42, +0x46, 0x06, 0x02, 0x00, 0x47, 0xe0, 0x00, 0x80, 0x59, 0xc0, 0x00, 0x00, 0x46, 0x96, 0x02, 0x04, +0x46, 0xa3, 0x10, 0x00, 0x59, 0xef, 0x02, 0x45, 0x15, 0xe0, 0x00, 0x00, 0x44, 0x00, 0x02, 0x45, +0x14, 0x0e, 0x00, 0x01, 0x46, 0x86, 0x02, 0x00, 0x46, 0x66, 0x02, 0x04, 0x46, 0x71, 0x55, 0x84, +0x46, 0x12, 0x00, 0xec, 0x46, 0x35, 0x7c, 0x06, 0x14, 0xa4, 0x80, 0x40, 0x58, 0x10, 0x80, 0x0c, +0x58, 0x84, 0x03, 0x04, 0x58, 0x63, 0x04, 0x1c, 0x58, 0x73, 0x86, 0x88, 0x50, 0x54, 0x02, 0x10, +0x50, 0x42, 0x90, 0x00, 0x50, 0x23, 0x7f, 0xe8, 0x58, 0x31, 0x8e, 0x55, 0x44, 0x00, 0x01, 0x10, +0x14, 0x04, 0x00, 0x00, 0x14, 0x73, 0x00, 0x00, 0x14, 0x12, 0x80, 0x00, 0x14, 0x12, 0x00, 0x00, +0x14, 0x31, 0x00, 0x00, 0x04, 0x4f, 0x80, 0x01, 0x4e, 0x42, 0x00, 0x52, 0x48, 0x00, 0x00, 0x3e, +0x44, 0x50, 0x00, 0x04, 0x4c, 0x02, 0xc0, 0x64, 0x47, 0xc6, 0x02, 0x00, 0x58, 0xae, 0x00, 0x00, +0x46, 0x86, 0x02, 0x04, 0x46, 0x92, 0x10, 0x00, 0x45, 0xe4, 0x02, 0x45, 0x15, 0xee, 0x00, 0x00, +0x58, 0x75, 0x00, 0x00, 0x58, 0x54, 0x00, 0x00, 0x46, 0x62, 0xab, 0x84, 0x58, 0x43, 0x80, 0x00, +0x46, 0x02, 0x00, 0xec, 0x46, 0x36, 0x02, 0x01, 0x58, 0x12, 0x80, 0x00, 0x46, 0x25, 0x7c, 0x06, +0x45, 0xc0, 0x02, 0x45, 0x15, 0xc5, 0x00, 0x01, 0x58, 0x00, 0x00, 0x0c, 0x14, 0x94, 0x00, 0x40, +0x58, 0x63, 0x06, 0x88, 0x58, 0x21, 0x0e, 0x55, 0x44, 0x80, 0x01, 0x10, 0x14, 0x83, 0x80, 0xc1, +0x14, 0x62, 0x81, 0x07, 0x14, 0x02, 0x01, 0x45, 0x14, 0x01, 0x81, 0x45, 0x14, 0x20, 0x81, 0x01, +0x04, 0x1f, 0x80, 0x01, 0x4e, 0x12, 0x00, 0x14, 0x46, 0x18, 0x24, 0x04, 0x46, 0x02, 0x00, 0x00, +0x46, 0x56, 0x02, 0x00, 0x46, 0x46, 0x02, 0x01, 0x58, 0x32, 0x80, 0x00, 0x58, 0x22, 0x00, 0x00, +0x58, 0x10, 0x81, 0xc0, 0x58, 0x00, 0x08, 0x00, 0x48, 0x00, 0x00, 0x12, 0x46, 0x10, 0x24, 0x04, +0x46, 0x02, 0x3f, 0x3f, 0x46, 0x56, 0x02, 0x00, 0x46, 0x46, 0x02, 0x01, 0x46, 0x36, 0x02, 0x00, +0x46, 0x26, 0x02, 0x01, 0x58, 0x10, 0x81, 0xc0, 0x58, 0x00, 0x08, 0x00, 0x14, 0x12, 0x83, 0x40, +0x14, 0x12, 0x03, 0x40, 0x14, 0x01, 0x83, 0x41, 0x14, 0x01, 0x03, 0x41, 0x51, 0xff, 0x80, 0x0c, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x2e, 0x07, 0xb0, 0xdb, +0x54, 0x10, 0x00, 0x01, 0x4e, 0x12, 0x00, 0x22, 0x54, 0x20, 0x00, 0x02, 0x4e, 0x22, 0x00, 0x1e, +0x46, 0x21, 0xe0, 0x00, 0x44, 0x30, 0x00, 0x19, 0x44, 0x40, 0x00, 0x08, 0x50, 0x01, 0x80, 0x03, +0x44, 0x10, 0x00, 0x00, 0x49, 0xff, 0xfa, 0xa8, 0x3c, 0x4d, 0xed, 0x42, 0x44, 0x30, 0x00, 0x02, +0x4c, 0x41, 0xc0, 0x0c, 0x40, 0x01, 0x90, 0x08, 0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x60, +0x44, 0x30, 0x00, 0x05, 0x49, 0xff, 0xfa, 0x98, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x40, 0x00, 0x00, 0x13, 0x4e, 0x03, 0x00, 0x0c, +0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0xa3, 0x64, 0x44, 0x20, 0x1f, 0xe5, 0x49, 0xff, 0x9e, 0x66, +0x48, 0x00, 0x00, 0x00, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x12, 0xc0, 0x0c, 0x46, 0x16, 0x02, 0x04, +0x58, 0x10, 0x84, 0x28, 0x50, 0x00, 0x7f, 0xff, 0x3e, 0x2f, 0xac, 0x6c, 0x48, 0x00, 0x00, 0x1c, +0x4e, 0x13, 0x00, 0x0c, 0x46, 0x16, 0x02, 0x04, 0x58, 0x10, 0x84, 0x28, 0x50, 0x00, 0x7f, 0xff, +0x3e, 0x2f, 0xac, 0x50, 0x48, 0x00, 0x00, 0x10, 0x50, 0x10, 0xff, 0xfc, 0x5c, 0xf0, 0x80, 0x02, +0x4e, 0xf2, 0x00, 0x16, 0x46, 0x16, 0x02, 0x04, 0x58, 0x10, 0x84, 0x28, 0x50, 0x00, 0x7f, 0xff, +0x3e, 0x2f, 0xac, 0x88, 0x39, 0xe1, 0x01, 0x01, 0x04, 0x50, 0x80, 0x00, 0x40, 0x4f, 0x40, 0x08, +0x40, 0x32, 0x80, 0x13, 0x40, 0x02, 0x0c, 0x04, 0x14, 0x00, 0x80, 0x00, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x2e, 0x77, 0xb2, 0xea, 0x4e, 0x72, 0x00, 0x16, 0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x0a, +0x44, 0x00, 0x06, 0x10, 0x44, 0x20, 0x00, 0x00, 0x49, 0xff, 0xf9, 0xf2, 0x46, 0x10, 0x3f, 0xf0, +0x58, 0x10, 0x80, 0x03, 0x44, 0x00, 0x00, 0x54, 0x44, 0x20, 0x00, 0x00, 0x48, 0x00, 0x00, 0x14, +0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x0a, 0x44, 0x00, 0x06, 0x10, 0x58, 0x23, 0x80, 0x00, +0x49, 0xff, 0xf9, 0xde, 0x46, 0x18, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, 0x58, 0x23, 0x80, 0x00, +0x44, 0x00, 0x00, 0x54, 0x49, 0xff, 0xf9, 0xd4, 0x2e, 0x17, 0xb2, 0xeb, 0x4e, 0x12, 0x00, 0x12, +0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x0a, 0x44, 0x00, 0x06, 0x10, 0x44, 0x20, 0x00, 0x01, +0x49, 0xff, 0xf9, 0xc6, 0x46, 0x10, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, 0x48, 0x00, 0x00, 0x10, +0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x0a, 0x44, 0x00, 0x06, 0x10, 0x44, 0x20, 0x00, 0x01, +0x49, 0xff, 0xf9, 0xb6, 0x46, 0x18, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, 0x44, 0x00, 0x00, 0x54, +0x44, 0x20, 0x00, 0x01, 0x49, 0xff, 0xf9, 0xac, 0x46, 0x08, 0x00, 0x21, 0x58, 0x00, 0x02, 0x44, +0x04, 0x70, 0x00, 0x00, 0x44, 0x8f, 0xff, 0xcf, 0x40, 0x63, 0xa0, 0x02, 0x14, 0x60, 0x00, 0x00, +0x2e, 0x47, 0xb1, 0x15, 0x54, 0x32, 0x00, 0x20, 0x4e, 0x32, 0x00, 0x10, 0x04, 0x20, 0x00, 0x00, +0x42, 0x11, 0x00, 0x09, 0x14, 0x10, 0x00, 0x00, 0x46, 0xa8, 0x00, 0x21, 0x05, 0xc5, 0x00, 0x44, +0x42, 0x9e, 0x64, 0x09, 0x14, 0x95, 0x00, 0x44, 0x2e, 0x17, 0xb1, 0x16, 0x54, 0x00, 0x80, 0x10, +0x4e, 0x02, 0x00, 0x12, 0x46, 0x58, 0x00, 0x21, 0x04, 0x92, 0x80, 0x91, 0x55, 0xc0, 0x80, 0x0c, +0x58, 0xa4, 0x00, 0x00, 0x40, 0x7e, 0x08, 0x08, 0x40, 0x84, 0xa8, 0x02, 0x40, 0x64, 0x1c, 0x04, +0x14, 0x62, 0x80, 0x91, 0x44, 0x10, 0x00, 0x00, 0x44, 0x00, 0x00, 0x30, 0x49, 0xff, 0xf9, 0x8e, +0x40, 0x20, 0x34, 0x08, 0x40, 0x21, 0x7c, 0x09, 0x4e, 0x22, 0x00, 0x1c, 0x44, 0x00, 0x00, 0x30, +0x44, 0x10, 0x00, 0x01, 0x49, 0xff, 0xf9, 0x82, 0x40, 0x30, 0x34, 0x08, 0x40, 0x31, 0xfc, 0x09, +0x4e, 0x32, 0x00, 0x10, 0x46, 0x58, 0x00, 0x23, 0x46, 0x60, 0x01, 0x30, 0x47, 0xe8, 0x00, 0x21, +0x58, 0x63, 0x05, 0x11, 0x44, 0x00, 0x00, 0x36, 0x14, 0x62, 0x80, 0x1b, 0x14, 0x0f, 0x00, 0xce, +0x45, 0xc0, 0x00, 0x00, 0x58, 0x9e, 0x00, 0x00, 0x3e, 0xaf, 0x4c, 0xf8, 0x48, 0x00, 0x02, 0x20, +0x3c, 0x4d, 0xed, 0x40, 0x50, 0x73, 0x80, 0x01, 0x40, 0x12, 0x08, 0x08, 0x40, 0x83, 0x04, 0x00, +0x04, 0x14, 0x00, 0x01, 0x0c, 0x03, 0x00, 0x04, 0x40, 0x73, 0x80, 0x13, 0x4b, 0xe0, 0x28, 0x01, +0x3d, 0xed, 0xed, 0x41, 0x58, 0x24, 0x80, 0x00, 0x40, 0xf3, 0xf8, 0x06, 0x4e, 0xf3, 0xff, 0xea, +0x44, 0x00, 0x06, 0x00, 0x58, 0x14, 0x80, 0x00, 0x44, 0x20, 0x03, 0x80, 0x44, 0x30, 0x00, 0x07, +0x44, 0x40, 0x00, 0x05, 0x49, 0xff, 0xf9, 0x68, 0x46, 0x50, 0x13, 0x12, 0x3c, 0x0d, 0xed, 0x3f, +0x58, 0x52, 0x8d, 0x00, 0x4c, 0x02, 0xc0, 0x06, 0x45, 0xc0, 0x00, 0x14, 0x48, 0x00, 0x00, 0x1e, +0x46, 0x60, 0x17, 0xd7, 0x58, 0x53, 0x08, 0x40, 0x4c, 0x02, 0xc0, 0x06, 0x45, 0xc0, 0x00, 0x1b, +0x48, 0x00, 0x00, 0x14, 0x46, 0x70, 0x26, 0x25, 0x58, 0x53, 0x8a, 0x00, 0x4c, 0x02, 0xc0, 0x06, +0x45, 0xc0, 0x00, 0x28, 0x48, 0x00, 0x00, 0x0a, 0x3e, 0x0f, 0xa3, 0x98, 0x3e, 0x1f, 0xad, 0x64, +0x44, 0x20, 0x1e, 0x3b, 0x49, 0xff, 0x9d, 0x22, 0x58, 0x14, 0x80, 0x00, 0x44, 0x00, 0x00, 0x58, +0x44, 0x20, 0xff, 0x00, 0x44, 0x30, 0x00, 0x08, 0x58, 0x4e, 0x00, 0x00, 0x49, 0xff, 0xf9, 0x34, +0x2e, 0x87, 0xb4, 0xf4, 0x4e, 0x83, 0x01, 0x3e, 0x3e, 0x6f, 0xa7, 0x20, 0x02, 0x03, 0x00, 0x00, +0x04, 0x13, 0x00, 0x01, 0x58, 0x24, 0x80, 0x00, 0x4b, 0xe0, 0x28, 0x01, 0x50, 0x63, 0x00, 0x08, +0x3e, 0x5f, 0xa7, 0x78, 0x4c, 0x62, 0xff, 0xf4, 0x4e, 0x93, 0x00, 0x94, 0x2e, 0x07, 0xb1, 0x1c, +0x40, 0x30, 0x00, 0x10, 0x4e, 0x34, 0x00, 0x0e, 0x54, 0x40, 0x00, 0x07, 0x58, 0x14, 0x80, 0x00, +0x44, 0x00, 0x00, 0x18, 0x44, 0x20, 0xe0, 0x00, 0x44, 0x30, 0x00, 0x0d, 0x49, 0xff, 0xf9, 0x0c, +0x3e, 0x7f, 0xb0, 0xd8, 0x00, 0x23, 0x80, 0x03, 0x54, 0x61, 0x00, 0x04, 0x4e, 0x62, 0x00, 0x66, +0x44, 0x10, 0x00, 0x00, 0x00, 0x43, 0x80, 0x4b, 0x3e, 0x6f, 0x4d, 0x80, 0x58, 0x30, 0x80, 0x00, +0x44, 0x00, 0x00, 0xdc, 0x44, 0x20, 0x00, 0xff, 0x4b, 0xe0, 0x18, 0x01, 0x00, 0x43, 0x80, 0x4c, +0x44, 0x00, 0x00, 0xdc, 0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0xff, 0x00, 0x44, 0x30, 0x00, 0x08, +0x4b, 0xe0, 0x18, 0x01, 0x00, 0x43, 0x80, 0x53, 0x46, 0x20, 0x0f, 0xf0, 0x44, 0x00, 0x00, 0xdc, +0x44, 0x10, 0x00, 0x00, 0x44, 0x30, 0x00, 0x10, 0x4b, 0xe0, 0x18, 0x01, 0x00, 0x43, 0x80, 0x54, +0x46, 0x2f, 0xf0, 0x00, 0x44, 0x00, 0x00, 0xdc, 0x44, 0x10, 0x00, 0x00, 0x44, 0x30, 0x00, 0x18, +0x4b, 0xe0, 0x18, 0x01, 0x44, 0x10, 0x00, 0x00, 0x00, 0x43, 0x80, 0x4f, 0x58, 0x30, 0x80, 0x00, +0x44, 0x00, 0x00, 0xe0, 0x44, 0x20, 0x00, 0xff, 0x4b, 0xe0, 0x18, 0x01, 0x00, 0x43, 0x80, 0x50, +0x44, 0x00, 0x00, 0xe0, 0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0xff, 0x00, 0x44, 0x30, 0x00, 0x08, +0x4b, 0xe0, 0x18, 0x01, 0x00, 0x43, 0x80, 0x57, 0x46, 0x20, 0x0f, 0xf0, 0x44, 0x00, 0x00, 0xe0, +0x44, 0x10, 0x00, 0x00, 0x44, 0x30, 0x00, 0x10, 0x4b, 0xe0, 0x18, 0x01, 0x00, 0x43, 0x80, 0x58, +0x46, 0x2f, 0xf0, 0x00, 0x44, 0x00, 0x00, 0xe0, 0x44, 0x10, 0x00, 0x00, 0x44, 0x30, 0x00, 0x18, +0x4b, 0xe0, 0x18, 0x01, 0x48, 0x00, 0x00, 0xbe, 0x46, 0x17, 0xf1, 0x71, 0x58, 0x10, 0x8d, 0x11, +0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x00, 0xdc, 0x4b, 0xe0, 0x28, 0x01, 0x46, 0x13, 0xb1, 0x17, +0x58, 0x10, 0x8f, 0x15, 0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x00, 0xe0, 0x48, 0x00, 0x00, 0x96, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x92, 0xc0, 0xa6, 0x2e, 0x07, 0xb1, 0x1c, 0x40, 0x70, 0x00, 0x10, +0x4e, 0x74, 0x00, 0x0e, 0x54, 0x40, 0x00, 0x07, 0x58, 0x14, 0x80, 0x00, 0x44, 0x00, 0x00, 0x18, +0x44, 0x20, 0xe0, 0x00, 0x44, 0x30, 0x00, 0x0d, 0x49, 0xff, 0xf8, 0x76, 0x3e, 0x6f, 0xb0, 0xd8, +0x00, 0x13, 0x00, 0x03, 0x54, 0x80, 0x80, 0x04, 0x4e, 0x82, 0x00, 0x66, 0x00, 0x43, 0x00, 0x4d, +0x3e, 0x7f, 0x4d, 0x80, 0x44, 0x00, 0x00, 0xdc, 0x44, 0x10, 0x00, 0x01, 0x44, 0x20, 0x00, 0xff, +0x44, 0x30, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x00, 0x43, 0x00, 0x4e, 0x44, 0x00, 0x00, 0xdc, +0x44, 0x10, 0x00, 0x01, 0x44, 0x20, 0xff, 0x00, 0x44, 0x30, 0x00, 0x08, 0x4b, 0xe0, 0x1c, 0x01, +0x00, 0x43, 0x00, 0x55, 0x46, 0x20, 0x0f, 0xf0, 0x44, 0x00, 0x00, 0xdc, 0x44, 0x10, 0x00, 0x01, +0x40, 0x30, 0x90, 0x08, 0x4b, 0xe0, 0x1c, 0x01, 0x00, 0x43, 0x00, 0x56, 0x46, 0x2f, 0xf0, 0x00, +0x44, 0x00, 0x00, 0xdc, 0x44, 0x10, 0x00, 0x01, 0x44, 0x30, 0x00, 0x18, 0x4b, 0xe0, 0x1c, 0x01, +0x00, 0x43, 0x00, 0x51, 0x44, 0x00, 0x00, 0xe0, 0x44, 0x10, 0x00, 0x01, 0x44, 0x20, 0x00, 0xff, +0x44, 0x30, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x00, 0x43, 0x00, 0x52, 0x44, 0x00, 0x00, 0xe0, +0x44, 0x10, 0x00, 0x01, 0x44, 0x20, 0xff, 0x00, 0x44, 0x30, 0x00, 0x08, 0x4b, 0xe0, 0x1c, 0x01, +0x00, 0x43, 0x00, 0x59, 0x46, 0x20, 0x0f, 0xf0, 0x44, 0x00, 0x00, 0xe0, 0x44, 0x10, 0x00, 0x01, +0x40, 0x30, 0x90, 0x08, 0x4b, 0xe0, 0x1c, 0x01, 0x00, 0x43, 0x00, 0x5a, 0x46, 0x2f, 0xf0, 0x00, +0x44, 0x00, 0x00, 0xe0, 0x44, 0x10, 0x00, 0x01, 0x44, 0x30, 0x00, 0x18, 0x4b, 0xe0, 0x1c, 0x01, +0x48, 0x00, 0x00, 0x28, 0x46, 0x13, 0xf1, 0x71, 0x58, 0x10, 0x8d, 0x11, 0x44, 0x00, 0x00, 0xdc, +0x44, 0x20, 0x00, 0x01, 0x4b, 0xe0, 0x28, 0x01, 0x46, 0x13, 0xb1, 0x17, 0x58, 0x10, 0x8f, 0x15, +0x44, 0x00, 0x00, 0xe0, 0x44, 0x20, 0x00, 0x01, 0x4b, 0xe0, 0x28, 0x01, 0x48, 0x00, 0x00, 0x12, +0x3e, 0x6f, 0xa7, 0x78, 0x02, 0x03, 0x00, 0x00, 0x04, 0x13, 0x00, 0x01, 0x58, 0x24, 0x80, 0x00, +0x4b, 0xe0, 0x28, 0x01, 0x50, 0x63, 0x00, 0x08, 0x3e, 0x5f, 0xa7, 0xe0, 0x4c, 0x62, 0xff, 0xf4, +0x2f, 0xe7, 0xb0, 0xdb, 0x54, 0x3f, 0x00, 0x08, 0x4e, 0x32, 0x00, 0x46, 0x2e, 0x67, 0xb1, 0x22, +0x46, 0x20, 0x03, 0xc0, 0x54, 0x83, 0x00, 0x0f, 0x3e, 0x7f, 0x4d, 0x80, 0x44, 0x00, 0x00, 0x00, +0x58, 0x14, 0x80, 0x00, 0x44, 0x30, 0x00, 0x12, 0x58, 0x44, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x44, 0x00, 0x06, 0x0c, 0x58, 0x14, 0x80, 0x00, 0x44, 0x20, 0x0f, 0x00, 0x44, 0x30, 0x00, 0x08, +0x58, 0x44, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x20, 0xf0, 0x00, 0x58, 0x44, 0x00, 0x00, +0x44, 0x00, 0x06, 0x08, 0x58, 0x14, 0x80, 0x00, 0x44, 0x30, 0x00, 0x18, 0x4b, 0xe0, 0x1c, 0x01, +0x40, 0x63, 0x10, 0x09, 0x46, 0x20, 0x0f, 0x00, 0x44, 0x00, 0x00, 0x1c, 0x58, 0x14, 0x80, 0x00, +0x44, 0x30, 0x00, 0x14, 0x58, 0x43, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x21, 0xe0, 0x00, +0x58, 0x43, 0x00, 0x00, 0x44, 0x00, 0x00, 0x1c, 0x58, 0x14, 0x80, 0x00, 0x50, 0x30, 0x7f, 0xfd, +0x4b, 0xe0, 0x1c, 0x01, 0x4e, 0x93, 0x00, 0x14, 0x3e, 0x6f, 0xa7, 0xe0, 0x02, 0x03, 0x00, 0x00, +0x04, 0x13, 0x00, 0x01, 0x44, 0x20, 0x00, 0x00, 0x4b, 0xe0, 0x28, 0x01, 0x50, 0x63, 0x00, 0x08, +0x3e, 0x5f, 0xa8, 0x50, 0x4c, 0x62, 0xff, 0xf4, 0x48, 0x00, 0x00, 0x16, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x92, 0xc0, 0x12, 0x3e, 0x6f, 0xa8, 0x50, 0x02, 0x03, 0x00, 0x00, 0x04, 0x13, 0x00, 0x01, +0x44, 0x20, 0x00, 0x01, 0x4b, 0xe0, 0x28, 0x01, 0x50, 0x63, 0x00, 0x08, 0x3e, 0x5f, 0xa8, 0xc0, +0x4c, 0x62, 0xff, 0xf4, 0x50, 0x94, 0x80, 0x01, 0x40, 0x94, 0x80, 0x13, 0x3c, 0x4d, 0xed, 0x42, +0x40, 0xf4, 0x90, 0x06, 0x4e, 0xf2, 0x00, 0x08, 0x44, 0x70, 0x00, 0x00, 0x3e, 0x6f, 0xa6, 0xb0, +0x48, 0xff, 0xfd, 0xe8, 0x2e, 0x17, 0xb4, 0xf0, 0x50, 0x30, 0xff, 0xff, 0x54, 0xa1, 0x80, 0xff, +0x5c, 0xf5, 0x00, 0x04, 0x4e, 0xf3, 0x00, 0x06, 0x3e, 0x0f, 0xa3, 0xac, 0x49, 0xff, 0x9b, 0x36, +0x3e, 0x7f, 0xab, 0x00, 0x44, 0x60, 0x00, 0x00, 0x44, 0x90, 0x00, 0x06, 0x2f, 0xe7, 0xb4, 0xf0, +0x3e, 0x3f, 0xab, 0x00, 0x43, 0xe3, 0x24, 0x73, 0x04, 0x23, 0x80, 0x05, 0x50, 0x1f, 0x7f, 0xff, +0x40, 0x40, 0x88, 0x08, 0x40, 0x52, 0x0c, 0x00, 0x04, 0x03, 0x80, 0x00, 0x04, 0x12, 0x80, 0x01, +0x50, 0x63, 0x00, 0x01, 0x49, 0xff, 0xf6, 0xf4, 0x44, 0x50, 0x00, 0x0e, 0x50, 0x73, 0x80, 0x18, +0x4c, 0x62, 0xff, 0xe6, 0x2e, 0x47, 0xb0, 0xdb, 0x40, 0x02, 0x00, 0x10, 0x4e, 0x04, 0x00, 0x10, +0x54, 0x52, 0x00, 0x70, 0x40, 0x42, 0x90, 0x09, 0x44, 0x00, 0x06, 0x00, 0x44, 0x10, 0x00, 0x00, +0x44, 0x20, 0x1c, 0x00, 0x44, 0x30, 0x00, 0x0a, 0x49, 0xff, 0xf7, 0x1e, 0x49, 0xff, 0xfc, 0x5e, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xcc, 0x46, 0x86, 0x02, 0x01, 0x46, 0x76, 0x02, 0x00, 0x14, 0x1f, 0x80, 0x0a, +0x14, 0x2f, 0x80, 0x09, 0x14, 0x3f, 0x80, 0x0b, 0x58, 0x50, 0x00, 0x00, 0x58, 0x60, 0x00, 0x00, +0x44, 0x90, 0x00, 0x00, 0x59, 0xc0, 0x00, 0x00, 0x04, 0x0f, 0x80, 0x09, 0x4e, 0x03, 0x00, 0x06, +0x04, 0x03, 0x80, 0xfe, 0x48, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00, 0xfe, 0x14, 0x03, 0x00, 0x00, +0x14, 0x5f, 0x80, 0x03, 0x44, 0x00, 0x00, 0x01, 0x50, 0x94, 0x80, 0x01, 0x49, 0xff, 0xab, 0xe0, +0x40, 0x94, 0x80, 0x13, 0x44, 0x10, 0x00, 0x20, 0x50, 0x63, 0x00, 0x04, 0x04, 0x5f, 0x80, 0x03, +0x4c, 0x90, 0xff, 0xe4, 0x50, 0x42, 0x80, 0xa4, 0x58, 0x2e, 0x00, 0x00, 0x45, 0xc0, 0x00, 0x00, +0x14, 0x4f, 0x80, 0x04, 0x15, 0xcf, 0x80, 0x05, 0x15, 0xcf, 0x80, 0x06, 0x15, 0xcf, 0x80, 0x07, +0x15, 0xcf, 0x80, 0x08, 0x59, 0xe2, 0x00, 0x00, 0x58, 0x3e, 0x00, 0x00, 0x58, 0x1e, 0x00, 0x00, +0x58, 0x0e, 0x00, 0x00, 0x58, 0x8e, 0x00, 0x00, 0x58, 0x9e, 0x00, 0x00, 0x58, 0xae, 0x00, 0x00, +0x02, 0x61, 0x00, 0x00, 0x54, 0x73, 0x00, 0x40, 0x54, 0x63, 0x00, 0x7f, 0x4e, 0x72, 0x00, 0x0c, +0x44, 0x7f, 0xff, 0x80, 0x40, 0x43, 0x1c, 0x04, 0x10, 0x4f, 0x7f, 0xe0, 0x40, 0x62, 0x00, 0x13, +0x48, 0x00, 0x00, 0x04, 0x10, 0x6f, 0x7f, 0xe0, 0x20, 0x7f, 0x7f, 0xe0, 0x4e, 0x83, 0x00, 0x08, +0x58, 0x03, 0x80, 0x00, 0x58, 0x30, 0x00, 0x00, 0x48, 0x00, 0x00, 0x16, 0x40, 0xf0, 0x1c, 0x07, +0x4e, 0xf2, 0x00, 0x08, 0x54, 0x04, 0x00, 0xff, 0x14, 0x0f, 0x80, 0x08, 0x58, 0x03, 0x80, 0x00, +0x40, 0xf3, 0x8c, 0x07, 0x4e, 0xf2, 0x00, 0x08, 0x54, 0x44, 0x00, 0xff, 0x14, 0x4f, 0x80, 0x06, +0x58, 0x33, 0x80, 0x00, 0x04, 0x41, 0x00, 0x00, 0x40, 0x63, 0x28, 0x00, 0x54, 0xa2, 0x7f, 0x00, +0x40, 0x45, 0x20, 0x09, 0x54, 0x72, 0x00, 0x40, 0x40, 0xa3, 0x00, 0x11, 0x4e, 0x72, 0x00, 0x0c, +0x44, 0x6f, 0xff, 0x80, 0x40, 0x72, 0x18, 0x04, 0x10, 0x7f, 0x00, 0x00, 0x40, 0x43, 0x80, 0x13, +0x48, 0x00, 0x00, 0x04, 0x10, 0x4f, 0x00, 0x00, 0x20, 0x7f, 0x00, 0x00, 0x4e, 0x83, 0x00, 0x08, +0x58, 0x13, 0x80, 0x00, 0x59, 0xc0, 0x80, 0x00, 0x48, 0x00, 0x00, 0x16, 0x40, 0xf0, 0x9c, 0x07, +0x4e, 0xf2, 0x00, 0x08, 0x54, 0x14, 0x00, 0xff, 0x14, 0x1f, 0x80, 0x07, 0x58, 0x13, 0x80, 0x00, +0x40, 0xf3, 0xf0, 0x07, 0x4e, 0xf2, 0x00, 0x08, 0x59, 0xc3, 0x80, 0x00, 0x54, 0x74, 0x00, 0xff, +0x14, 0x7f, 0x80, 0x05, 0x50, 0x84, 0x00, 0x01, 0x40, 0x62, 0x24, 0x00, 0x40, 0x84, 0x00, 0x13, +0x44, 0x40, 0x00, 0x20, 0x40, 0x93, 0x00, 0x11, 0x50, 0x21, 0x00, 0x04, 0x51, 0xef, 0x00, 0x01, +0x4c, 0x82, 0x7f, 0x88, 0x40, 0xa5, 0x00, 0x01, 0x40, 0x74, 0x84, 0x01, 0x40, 0x03, 0xf0, 0x01, +0x40, 0x15, 0x0c, 0x01, 0x40, 0x20, 0x80, 0x11, 0x40, 0x90, 0x00, 0x11, 0x45, 0xe0, 0x00, 0x1e, +0x41, 0xc4, 0xf9, 0x16, 0x44, 0x80, 0x00, 0x00, 0x58, 0x94, 0x00, 0x00, 0x58, 0xa4, 0x00, 0x00, +0x40, 0x31, 0x78, 0xd6, 0x04, 0x2f, 0x80, 0x04, 0x41, 0xce, 0x00, 0x11, 0x40, 0x11, 0x80, 0x11, +0x04, 0x4f, 0x80, 0x06, 0x50, 0x35, 0x00, 0x01, 0x4c, 0x45, 0x00, 0x0e, 0x04, 0x6f, 0x80, 0x08, +0x4c, 0x65, 0x00, 0x0a, 0x20, 0x71, 0x7f, 0xe0, 0x40, 0x03, 0x84, 0x01, 0x41, 0xe0, 0x00, 0x11, +0x42, 0x9f, 0x78, 0x73, 0x04, 0x4f, 0x80, 0x05, 0x4c, 0x45, 0x00, 0x0e, 0x04, 0x6f, 0x80, 0x07, +0x4c, 0x65, 0x00, 0x0a, 0x20, 0x01, 0x00, 0x00, 0x41, 0xe0, 0x70, 0x01, 0x40, 0xaf, 0x00, 0x11, +0x42, 0x85, 0x28, 0x73, 0x40, 0xa1, 0x80, 0x13, 0x44, 0x30, 0x00, 0x20, 0x50, 0x21, 0x00, 0x01, +0x4c, 0xa1, 0xff, 0xd8, 0x50, 0x21, 0xff, 0xfe, 0x40, 0x34, 0x89, 0x36, 0x40, 0x44, 0x09, 0x16, +0x5e, 0xf1, 0x80, 0x0b, 0x4e, 0xf2, 0x00, 0x1a, 0x5e, 0xf2, 0x00, 0x0b, 0x4e, 0xf2, 0x00, 0x16, +0x50, 0x60, 0x80, 0x1a, 0x40, 0x73, 0x00, 0x13, 0x5c, 0xf3, 0x80, 0x35, 0x4e, 0xf2, 0x00, 0x12, +0x5e, 0xfe, 0x00, 0x1b, 0x4e, 0xf2, 0x00, 0x0e, 0x5e, 0xfe, 0x7f, 0xe6, 0x4e, 0xf3, 0x00, 0x0a, +0x44, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0x08, 0x44, 0x60, 0x00, 0x01, 0x48, 0x00, 0x00, 0x04, +0x44, 0x60, 0x00, 0x02, 0x14, 0x42, 0x80, 0x32, 0x12, 0x12, 0x80, 0x40, 0x13, 0xc2, 0x80, 0x41, +0x14, 0x32, 0x80, 0x31, 0x58, 0x2e, 0x00, 0x00, 0x05, 0xef, 0x80, 0x09, 0x04, 0x7f, 0x80, 0x0b, +0x04, 0x5f, 0x80, 0x0a, 0x3e, 0x0f, 0xa3, 0xbc, 0x15, 0xef, 0x80, 0x00, 0x14, 0x7f, 0x80, 0x01, +0x49, 0xff, 0x99, 0xa4, 0x58, 0x03, 0x00, 0x00, 0x51, 0xff, 0x80, 0x34, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x2e, 0x07, 0xb5, 0x13, +0x4e, 0x03, 0x00, 0x0e, 0x46, 0x46, 0x01, 0x20, 0x04, 0x52, 0x00, 0x20, 0x42, 0x22, 0xa0, 0x09, +0x14, 0x22, 0x00, 0x20, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0xaa, 0x9a, 0x2f, 0xe7, 0xb5, 0x14, +0x4f, 0xe3, 0x00, 0x0e, 0x46, 0x16, 0x01, 0x20, 0x04, 0x20, 0x80, 0x20, 0x42, 0x41, 0x24, 0x09, +0x14, 0x40, 0x80, 0x20, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0xaa, 0x8a, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x49, 0xff, 0xff, 0xd2, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x46, 0x16, 0x01, 0x20, 0x04, 0x30, 0x80, 0x20, +0x44, 0x00, 0x00, 0x01, 0x58, 0x21, 0x83, 0x00, 0x14, 0x20, 0x80, 0x20, 0x49, 0xff, 0xaa, 0x68, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x46, 0x06, 0x01, 0x20, 0x04, 0x10, 0x00, 0x20, 0x54, 0x20, 0x81, 0x00, +0x4e, 0x22, 0x00, 0x04, 0x44, 0x20, 0x00, 0x01, 0x54, 0x10, 0x82, 0x00, 0x3e, 0x27, 0xb5, 0x13, +0x4e, 0x12, 0x00, 0x04, 0x44, 0x10, 0x00, 0x01, 0x3e, 0x17, 0xb5, 0x14, 0x49, 0xff, 0xff, 0xd2, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x49, 0xff, 0xff, 0xdc, 0x49, 0xff, 0xff, 0xc4, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xe4, +0x2e, 0x37, 0xb1, 0x1d, 0x59, 0xc0, 0x00, 0x00, 0x54, 0x41, 0x80, 0x40, 0x4e, 0x43, 0x04, 0xd2, +0x2e, 0x57, 0xb4, 0xf4, 0x44, 0x00, 0x00, 0x01, 0x4c, 0x50, 0x04, 0xcc, 0x54, 0xa1, 0x80, 0x20, +0x49, 0xff, 0xf5, 0x7e, 0x46, 0x18, 0x1b, 0xce, 0x3e, 0x6f, 0x4c, 0xf8, 0x58, 0x10, 0x8c, 0x3f, +0x44, 0x00, 0x00, 0x6c, 0x58, 0x2e, 0x00, 0x00, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x1f, 0xcb, 0x00, +0x58, 0x2e, 0x00, 0x00, 0x58, 0x10, 0x87, 0x27, 0x44, 0x00, 0x00, 0x48, 0x4b, 0xe0, 0x18, 0x01, +0x58, 0x1e, 0x00, 0x00, 0x44, 0x00, 0x00, 0x54, 0x49, 0xff, 0xf4, 0xe8, 0x42, 0x20, 0x74, 0x09, +0x42, 0x21, 0x78, 0x09, 0x42, 0x11, 0x78, 0x08, 0x44, 0x00, 0x00, 0x54, 0x58, 0x2e, 0x00, 0x00, +0x4b, 0xe0, 0x18, 0x01, 0x46, 0x10, 0x5a, 0x00, 0x58, 0x10, 0x8f, 0x8b, 0x44, 0x00, 0x00, 0x70, +0x58, 0x2e, 0x00, 0x00, 0x4b, 0xe0, 0x18, 0x01, 0x4e, 0xa2, 0x00, 0x30, 0x44, 0x00, 0x00, 0x70, +0x58, 0x1e, 0x00, 0x00, 0x49, 0xff, 0xf4, 0xca, 0x2e, 0x87, 0xb1, 0x1d, 0x40, 0x70, 0x20, 0x08, +0x54, 0x54, 0x00, 0x10, 0x40, 0x43, 0xf0, 0x09, 0x54, 0x34, 0x00, 0x0f, 0x4e, 0x52, 0x00, 0x06, +0x40, 0x42, 0x0c, 0x00, 0x48, 0x00, 0x00, 0x04, 0x40, 0x42, 0x0c, 0x01, 0x4e, 0x46, 0x00, 0x06, +0x44, 0x40, 0x00, 0x00, 0x48, 0x00, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x0f, 0x42, 0x42, 0x78, 0x01, +0x46, 0x20, 0x0f, 0x00, 0x54, 0x42, 0x00, 0xff, 0x44, 0x00, 0x00, 0x70, 0x58, 0x1e, 0x00, 0x00, +0x44, 0x30, 0x00, 0x14, 0x49, 0xff, 0xf4, 0xc8, 0x46, 0x19, 0x00, 0x00, 0x44, 0x00, 0x00, 0xa0, +0x58, 0x2e, 0x00, 0x00, 0x49, 0xff, 0xf4, 0x7c, 0x46, 0x38, 0x10, 0x60, 0x04, 0x01, 0x80, 0x02, +0x2e, 0x47, 0xb2, 0xea, 0x3c, 0x0f, 0xec, 0xd5, 0x4e, 0x43, 0x00, 0x18, 0x2e, 0x27, 0xb2, 0xeb, +0x4e, 0x23, 0x00, 0x14, 0x4f, 0xc3, 0x00, 0x08, 0x46, 0x40, 0x48, 0x52, 0x58, 0x42, 0x03, 0x90, +0x48, 0x00, 0x00, 0x0a, 0x44, 0x50, 0x00, 0x01, 0x4d, 0xc2, 0xc0, 0x08, 0x46, 0x40, 0x48, 0x56, +0x58, 0x42, 0x07, 0x90, 0x14, 0x41, 0x80, 0x02, 0x46, 0x46, 0x02, 0x00, 0x58, 0x92, 0x00, 0x00, +0x58, 0x32, 0x00, 0x00, 0x45, 0xe0, 0x00, 0xa7, 0x44, 0x70, 0x00, 0x02, 0x15, 0xe2, 0x00, 0x00, +0x15, 0xe4, 0x80, 0x01, 0x14, 0x71, 0x80, 0x83, 0x4f, 0xc3, 0x00, 0x22, 0x58, 0x81, 0x80, 0x00, +0x46, 0x70, 0x40, 0x00, 0x58, 0x61, 0x80, 0x00, 0x46, 0x30, 0x02, 0x74, 0x58, 0x22, 0x00, 0x00, +0x46, 0x5c, 0x00, 0x00, 0x46, 0x16, 0x02, 0x04, 0x58, 0x31, 0x80, 0x27, 0x58, 0x52, 0x84, 0x00, +0x44, 0x00, 0x05, 0x9f, 0x14, 0x74, 0x00, 0x80, 0x14, 0x33, 0x03, 0x40, 0x14, 0x51, 0x03, 0x41, +0x14, 0x00, 0x80, 0x85, 0x4e, 0xa2, 0x00, 0x2c, 0x48, 0x00, 0x00, 0x32, 0x44, 0x50, 0x00, 0x01, +0x4d, 0xc2, 0x80, 0x06, 0x44, 0x90, 0x00, 0x00, 0x48, 0x00, 0x00, 0x60, 0x46, 0x66, 0x02, 0x00, +0x46, 0x31, 0x40, 0x00, 0x46, 0x26, 0x02, 0x01, 0x46, 0x50, 0x02, 0x74, 0x58, 0x11, 0x00, 0x00, +0x46, 0x0c, 0x00, 0x00, 0x47, 0xe6, 0x02, 0x05, 0x58, 0x52, 0x80, 0x27, 0x58, 0x00, 0x04, 0x00, +0x44, 0x40, 0x05, 0x9f, 0x14, 0x33, 0x00, 0x80, 0x14, 0x51, 0x03, 0x40, 0x14, 0x00, 0x83, 0x41, +0x14, 0x4f, 0x00, 0x85, 0x4e, 0xa2, 0x00, 0x24, 0x48, 0x00, 0x00, 0x2a, 0x46, 0x36, 0x02, 0x00, +0x46, 0x44, 0x0c, 0x00, 0x58, 0x31, 0x8d, 0x24, 0x48, 0x00, 0x00, 0x08, 0x46, 0x36, 0x02, 0x00, +0x46, 0x44, 0x04, 0x00, 0x58, 0x31, 0x8d, 0x24, 0x14, 0x41, 0x80, 0x00, 0x58, 0x41, 0x00, 0x00, +0x04, 0x82, 0x03, 0x49, 0x58, 0x91, 0x00, 0x00, 0x47, 0xea, 0x30, 0x00, 0x46, 0x70, 0xff, 0x00, +0x15, 0xe4, 0x82, 0x82, 0x40, 0x94, 0x1c, 0x02, 0x48, 0x00, 0x00, 0x20, 0x46, 0x36, 0x02, 0x01, +0x46, 0x44, 0x0c, 0x00, 0x58, 0x31, 0x8d, 0x24, 0x48, 0x00, 0x00, 0x08, 0x46, 0x36, 0x02, 0x01, +0x46, 0x44, 0x04, 0x00, 0x58, 0x31, 0x8d, 0x24, 0x14, 0x41, 0x80, 0x00, 0x58, 0x50, 0x80, 0x00, +0x58, 0x20, 0x80, 0x00, 0x46, 0x6a, 0x30, 0x00, 0x04, 0x12, 0x83, 0x49, 0x46, 0x00, 0xff, 0x00, +0x14, 0x61, 0x02, 0x82, 0x40, 0x90, 0x80, 0x02, 0x46, 0x36, 0x02, 0x00, 0x14, 0x3f, 0x80, 0x01, +0x58, 0x21, 0x80, 0x00, 0x04, 0x0f, 0x80, 0x01, 0x14, 0x2f, 0x80, 0x02, 0x58, 0x00, 0x03, 0x80, +0x14, 0x0f, 0x80, 0x01, 0x46, 0x16, 0x02, 0x04, 0x04, 0x0f, 0x80, 0x02, 0x14, 0x1f, 0x80, 0x03, +0x58, 0x00, 0x03, 0x00, 0x14, 0x0f, 0x80, 0x02, 0x04, 0x0f, 0x80, 0x03, 0x58, 0x40, 0x80, 0x00, +0x58, 0x00, 0x01, 0x00, 0x14, 0x0f, 0x80, 0x03, 0x44, 0x00, 0x00, 0x03, 0x14, 0x02, 0x00, 0x50, +0x50, 0x00, 0x00, 0x0d, 0x04, 0x4f, 0x80, 0x01, 0x47, 0xe0, 0x10, 0x00, 0x14, 0x02, 0x00, 0x00, +0x44, 0x01, 0x00, 0x68, 0x04, 0x4f, 0x80, 0x02, 0x14, 0x02, 0x00, 0x00, 0x58, 0x81, 0x00, 0x00, +0x04, 0x4f, 0x80, 0x03, 0x58, 0x71, 0x00, 0x00, 0x46, 0x62, 0x03, 0xf0, 0x58, 0x50, 0x80, 0x00, +0x46, 0x30, 0x60, 0x70, 0x46, 0x10, 0x00, 0x80, 0x15, 0xe2, 0x00, 0x00, 0x58, 0x63, 0x06, 0x06, +0x58, 0x10, 0x87, 0x01, 0x45, 0xe0, 0x00, 0x06, 0x15, 0xe4, 0x02, 0x44, 0x14, 0x63, 0x82, 0x43, +0x14, 0x32, 0x80, 0x08, 0x58, 0x71, 0x00, 0x00, 0x14, 0x11, 0x02, 0x40, 0x44, 0x60, 0x00, 0x00, +0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0xa8, 0xa4, 0x04, 0x43, 0x82, 0x6c, 0x42, 0x52, 0x74, 0x0b, +0x4e, 0x53, 0x00, 0x12, 0x44, 0x50, 0x27, 0x11, 0x4c, 0x62, 0x80, 0x06, 0x50, 0x63, 0x00, 0x01, +0x48, 0xff, 0xff, 0xf0, 0x3e, 0x0f, 0xa3, 0x98, 0x3e, 0x1f, 0xad, 0x78, 0x44, 0x20, 0x16, 0xa1, +0x49, 0xff, 0x97, 0x7c, 0x46, 0x26, 0x02, 0x00, 0x46, 0x30, 0x00, 0x80, 0x58, 0x61, 0x00, 0x00, +0x58, 0x31, 0x87, 0x00, 0x40, 0x94, 0xd0, 0x09, 0x44, 0x11, 0x00, 0x06, 0x14, 0x31, 0x02, 0x40, +0x40, 0x94, 0x80, 0x10, 0x14, 0x13, 0x02, 0x44, 0x4e, 0xa3, 0x02, 0x4e, 0x46, 0x06, 0x02, 0x01, +0x58, 0x00, 0x09, 0xac, 0x50, 0x40, 0x70, 0x00, 0x50, 0x52, 0x00, 0x04, 0x14, 0xaf, 0x80, 0x02, +0x14, 0x0f, 0x80, 0x03, 0x14, 0x4f, 0x80, 0x04, 0x14, 0x5f, 0x80, 0x05, 0x14, 0xaf, 0x80, 0x01, +0x4f, 0xc3, 0x00, 0x0c, 0x05, 0xef, 0x80, 0x04, 0x46, 0xa0, 0x0f, 0xf0, 0x04, 0x0f, 0x00, 0x00, +0x40, 0x20, 0x28, 0x02, 0x48, 0x00, 0x00, 0x0e, 0x44, 0x50, 0x00, 0x01, 0x4d, 0xc2, 0xc0, 0x10, +0x04, 0x2f, 0x80, 0x03, 0x46, 0x10, 0x0f, 0xf0, 0x04, 0x01, 0x00, 0x00, 0x40, 0x20, 0x04, 0x02, +0x40, 0x31, 0x40, 0x09, 0x14, 0x3f, 0x80, 0x01, 0x54, 0xa0, 0x00, 0xff, 0x5c, 0xf5, 0x00, 0x41, +0x4e, 0xf3, 0x00, 0x06, 0x50, 0x94, 0x80, 0x0a, 0x48, 0x00, 0x00, 0xaa, 0x5c, 0xf5, 0x00, 0x08, +0x4e, 0xf2, 0x00, 0x06, 0x50, 0x94, 0x80, 0x08, 0x48, 0x00, 0x00, 0xa2, 0x5c, 0xf5, 0x00, 0x10, +0x4e, 0xf2, 0x00, 0x06, 0x50, 0x94, 0x80, 0x06, 0x48, 0x00, 0x00, 0x9a, 0x5c, 0xf5, 0x00, 0x20, +0x4e, 0xf2, 0x00, 0x06, 0x50, 0x94, 0x80, 0x04, 0x48, 0x00, 0x00, 0x92, 0x5c, 0xf5, 0x00, 0x30, +0x4e, 0xf2, 0x00, 0x06, 0x50, 0x94, 0x80, 0x02, 0x48, 0x00, 0x00, 0x8a, 0x4f, 0xc3, 0x00, 0x22, +0x46, 0x26, 0x02, 0x00, 0x58, 0x21, 0x09, 0xac, 0x58, 0x0e, 0x00, 0x00, 0x04, 0xa1, 0x00, 0x00, +0x50, 0x30, 0x00, 0x01, 0x54, 0xa5, 0x00, 0xff, 0x50, 0x45, 0x7f, 0xd0, 0x54, 0x52, 0x00, 0xff, +0x50, 0x21, 0x7f, 0xfc, 0x5c, 0xf2, 0x80, 0x10, 0x4e, 0xf2, 0x00, 0x04, 0x54, 0x01, 0x80, 0xff, +0x47, 0xe6, 0x02, 0x00, 0x59, 0xef, 0x09, 0x6c, 0x4c, 0x2f, 0x7f, 0xea, 0x48, 0x00, 0x00, 0x24, +0x44, 0x00, 0x00, 0x01, 0x4d, 0xc0, 0x40, 0x24, 0x46, 0x26, 0x02, 0x01, 0x58, 0x21, 0x09, 0xac, +0x44, 0x00, 0x00, 0x00, 0x04, 0x31, 0x00, 0x00, 0x50, 0x21, 0x7f, 0xfc, 0x54, 0xa1, 0x80, 0xff, +0x50, 0x15, 0x7f, 0xd0, 0x54, 0x60, 0x80, 0xff, 0x50, 0x30, 0x00, 0x01, 0x5c, 0xf3, 0x00, 0x10, +0x4e, 0xf2, 0x00, 0x04, 0x54, 0x01, 0x80, 0xff, 0x46, 0x56, 0x02, 0x01, 0x58, 0x52, 0x89, 0x6c, +0x4c, 0x22, 0xff, 0xea, 0x5c, 0xf0, 0x00, 0x03, 0x4e, 0xf2, 0x00, 0x10, 0x04, 0x0f, 0x80, 0x01, +0x44, 0x20, 0x00, 0x7f, 0x4c, 0x01, 0x00, 0x3e, 0x50, 0x51, 0x00, 0x02, 0x4c, 0x02, 0x80, 0x3a, +0x44, 0x50, 0x00, 0x01, 0x48, 0x00, 0x01, 0x3a, 0x44, 0x70, 0x00, 0x03, 0x4c, 0x03, 0xc0, 0x06, +0x50, 0x94, 0xff, 0xfe, 0x48, 0x00, 0x00, 0x2c, 0x44, 0x80, 0x00, 0x04, 0x4c, 0x04, 0x40, 0x06, +0x50, 0x94, 0xff, 0xfc, 0x48, 0x00, 0x00, 0x24, 0x45, 0xe0, 0x00, 0x05, 0x4c, 0x0f, 0x40, 0x06, +0x50, 0x94, 0xff, 0xf8, 0x48, 0x00, 0x00, 0x1c, 0x44, 0x60, 0x00, 0x06, 0x4c, 0x03, 0x40, 0x06, +0x50, 0x94, 0xff, 0xf4, 0x48, 0x00, 0x00, 0x14, 0x44, 0x10, 0x00, 0x07, 0x4c, 0x00, 0xc0, 0x06, +0x50, 0x94, 0xff, 0xf0, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x30, 0x00, 0x08, 0x4c, 0x01, 0xc0, 0x06, +0x50, 0x94, 0xff, 0xec, 0x48, 0x00, 0x00, 0x04, 0x50, 0x94, 0xff, 0xe8, 0x40, 0x94, 0x80, 0x10, +0x58, 0x1e, 0x00, 0x00, 0x44, 0x00, 0x00, 0x70, 0x49, 0xff, 0xf2, 0x78, 0x40, 0x50, 0x20, 0x08, +0x40, 0x02, 0xf0, 0x09, 0x54, 0x10, 0x00, 0xff, 0x40, 0x70, 0x00, 0x10, 0x44, 0x80, 0x00, 0x00, +0x54, 0x54, 0x00, 0xff, 0x50, 0x34, 0x80, 0x08, 0x50, 0x23, 0xff, 0xff, 0x4c, 0x12, 0xc0, 0x10, +0x5e, 0xf4, 0xff, 0xe1, 0x4e, 0xf3, 0x00, 0x06, 0x44, 0x70, 0x00, 0x00, 0x48, 0x00, 0x00, 0x16, +0x44, 0x70, 0x00, 0x00, 0x44, 0x9f, 0xff, 0xe1, 0x48, 0x00, 0x00, 0x10, 0x5e, 0xf4, 0xff, 0xe1, +0x4e, 0xf2, 0x00, 0x0c, 0x40, 0x91, 0x80, 0x10, 0x40, 0x71, 0x00, 0x10, 0x50, 0x84, 0x00, 0x01, +0x5e, 0xf4, 0xff, 0xe1, 0x4e, 0xf3, 0xff, 0xde, 0x44, 0x50, 0x00, 0x0f, 0x50, 0x14, 0xff, 0xf8, +0x50, 0x03, 0x80, 0x01, 0x4c, 0x72, 0xc0, 0x08, 0x45, 0xe0, 0x00, 0x1f, 0x42, 0x94, 0xf8, 0x01, +0x48, 0x00, 0x00, 0x0e, 0x5e, 0xf4, 0x80, 0x20, 0x4e, 0xf3, 0x00, 0x0a, 0x40, 0x90, 0x80, 0x10, +0x40, 0x70, 0x00, 0x10, 0x5e, 0xf4, 0x80, 0x20, 0x4e, 0xf2, 0xff, 0xe8, 0x46, 0x20, 0x0f, 0x00, +0x54, 0x43, 0x80, 0xff, 0x44, 0x00, 0x00, 0x70, 0x58, 0x1e, 0x00, 0x00, 0x50, 0x32, 0x80, 0x05, +0x49, 0xff, 0xf2, 0x4a, 0x4f, 0xc3, 0x00, 0x10, 0x46, 0x10, 0xff, 0x00, 0x40, 0x64, 0xd0, 0x08, +0x40, 0x73, 0x04, 0x02, 0x46, 0x06, 0x02, 0x00, 0x42, 0x23, 0xf8, 0x08, 0x58, 0x00, 0x0d, 0x24, +0x48, 0x00, 0x00, 0x12, 0x44, 0x50, 0x00, 0x01, 0x4d, 0xc2, 0xc0, 0x10, 0x46, 0x00, 0xff, 0x00, +0x40, 0x24, 0xd0, 0x08, 0x40, 0x51, 0x00, 0x02, 0x46, 0x06, 0x02, 0x01, 0x42, 0x22, 0xf8, 0x08, +0x58, 0x00, 0x0d, 0x24, 0x14, 0x20, 0x00, 0x00, 0x46, 0x06, 0x02, 0x04, 0x46, 0x26, 0x02, 0x00, +0x58, 0x71, 0x00, 0x00, 0x58, 0x60, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x58, 0x81, 0x00, 0x00, +0x44, 0x40, 0x00, 0x03, 0x44, 0x50, 0x00, 0x10, 0x44, 0x31, 0x00, 0x68, 0x45, 0xe0, 0x00, 0x06, +0x14, 0x40, 0x00, 0x50, 0x14, 0x51, 0x00, 0xe0, 0x14, 0x33, 0x80, 0xc0, 0x14, 0x13, 0x00, 0x40, +0x15, 0xe4, 0x02, 0x44, 0x44, 0x40, 0x00, 0x7f, 0x04, 0x2f, 0x80, 0x01, 0x4c, 0x22, 0x00, 0x10, +0x50, 0x52, 0x00, 0x02, 0x4c, 0x22, 0x80, 0x0c, 0x46, 0x06, 0x02, 0x00, 0x46, 0x22, 0x03, 0xf0, +0x58, 0x00, 0x09, 0x0c, 0x58, 0x21, 0x06, 0x06, 0x48, 0x00, 0x00, 0x0a, 0x46, 0x06, 0x02, 0x00, +0x46, 0x21, 0x03, 0xf0, 0x58, 0x00, 0x09, 0x0c, 0x58, 0x21, 0x06, 0x06, 0x58, 0x73, 0x00, 0x00, +0x46, 0x80, 0x60, 0x70, 0x47, 0xe6, 0x02, 0x00, 0x46, 0x10, 0x00, 0x80, 0x58, 0x10, 0x87, 0x01, +0x14, 0x20, 0x00, 0x00, 0x14, 0x83, 0x80, 0x08, 0x14, 0x1f, 0x02, 0x40, 0x44, 0x60, 0x00, 0x00, +0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0xa6, 0xcc, 0x04, 0x0f, 0x80, 0x05, 0x04, 0x50, 0x00, 0x00, +0x42, 0x22, 0xf4, 0x0b, 0x4e, 0x23, 0x00, 0x12, 0x44, 0x50, 0x27, 0x11, 0x4c, 0x62, 0x80, 0x06, +0x50, 0x63, 0x00, 0x01, 0x48, 0xff, 0xff, 0xee, 0x3e, 0x0f, 0xa3, 0x98, 0x3e, 0x1f, 0xad, 0x78, +0x44, 0x20, 0x17, 0xaa, 0x49, 0xff, 0x95, 0xa2, 0x04, 0x6f, 0x80, 0x02, 0x46, 0x16, 0x02, 0x00, +0x50, 0x43, 0x00, 0x01, 0x46, 0x00, 0x00, 0x80, 0x58, 0x50, 0x80, 0x00, 0x58, 0x00, 0x07, 0x00, +0x55, 0xe2, 0x00, 0xff, 0x44, 0x31, 0x00, 0x06, 0x44, 0x26, 0x07, 0x00, 0x44, 0x60, 0x00, 0x04, +0x15, 0xef, 0x80, 0x02, 0x14, 0x00, 0x82, 0x40, 0x14, 0x32, 0x82, 0x44, 0x14, 0x20, 0x82, 0x40, +0x4d, 0xe3, 0x7e, 0x30, 0x44, 0x50, 0x00, 0x00, 0x4f, 0xc3, 0x00, 0x20, 0x46, 0x46, 0x02, 0x00, +0x58, 0x42, 0x09, 0xac, 0x58, 0x3e, 0x00, 0x00, 0x04, 0x22, 0x00, 0x00, 0x50, 0x01, 0x80, 0x01, +0x50, 0x11, 0x7f, 0xd0, 0x55, 0xe0, 0x80, 0xff, 0x50, 0x42, 0x7f, 0xfc, 0x5c, 0xff, 0x00, 0x10, +0x4e, 0xf2, 0x00, 0x04, 0x54, 0x30, 0x00, 0xff, 0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x09, 0x6c, +0x4c, 0x40, 0x7f, 0xec, 0x48, 0x00, 0x00, 0x22, 0x44, 0x30, 0x00, 0x01, 0x4d, 0xc1, 0xc0, 0x4e, +0x46, 0x46, 0x02, 0x01, 0x58, 0x42, 0x09, 0xac, 0x44, 0x30, 0x00, 0x00, 0x04, 0x12, 0x00, 0x00, +0x50, 0x01, 0x80, 0x01, 0x51, 0xe0, 0xff, 0xd0, 0x54, 0x6f, 0x00, 0xff, 0x50, 0x42, 0x7f, 0xfc, +0x5c, 0xf3, 0x00, 0x10, 0x4e, 0xf2, 0x00, 0x04, 0x54, 0x30, 0x00, 0xff, 0x46, 0x26, 0x02, 0x01, +0x58, 0x21, 0x09, 0x6c, 0x4c, 0x41, 0x7f, 0xec, 0x5c, 0xf1, 0x80, 0x03, 0x4e, 0xf3, 0x00, 0x14, +0x4e, 0x53, 0x00, 0x12, 0x4f, 0xc3, 0x00, 0x08, 0x44, 0x40, 0x00, 0x01, 0x3e, 0x47, 0xb5, 0x18, +0x48, 0x00, 0x00, 0x24, 0x44, 0x00, 0x00, 0x01, 0x4d, 0xc0, 0x40, 0x20, 0x3f, 0xc7, 0xb5, 0x19, +0x48, 0x00, 0x00, 0x1c, 0x4f, 0xc3, 0x00, 0x06, 0x3f, 0xc7, 0xb5, 0x18, 0x48, 0x00, 0x00, 0x16, +0x44, 0x20, 0x00, 0x01, 0x4d, 0xc1, 0x40, 0x12, 0x44, 0x40, 0x00, 0x00, 0x3e, 0x47, 0xb5, 0x19, +0x48, 0x00, 0x00, 0x0c, 0x2e, 0x37, 0xb1, 0x1d, 0x54, 0x61, 0x80, 0x0f, 0x40, 0x03, 0x08, 0x08, +0x40, 0x94, 0x80, 0x00, 0x40, 0x94, 0x80, 0x10, 0x58, 0x1e, 0x00, 0x00, 0x44, 0x00, 0x00, 0x70, +0x49, 0xff, 0xf1, 0x04, 0x46, 0x30, 0x0f, 0x00, 0x40, 0x60, 0x0c, 0x02, 0x40, 0x03, 0x44, 0x09, +0x40, 0x44, 0x80, 0x00, 0x3e, 0x6f, 0xc4, 0x60, 0x50, 0x92, 0x7f, 0xc2, 0x40, 0x5e, 0x18, 0x00, +0x10, 0x92, 0x83, 0x9c, 0x46, 0x26, 0x02, 0x00, 0x04, 0x11, 0x02, 0x44, 0x54, 0x40, 0x80, 0x0f, +0x4f, 0xc3, 0x00, 0x38, 0x46, 0x11, 0x80, 0x80, 0x58, 0x10, 0x82, 0x48, 0x41, 0xe2, 0x04, 0x00, +0x46, 0x36, 0x02, 0x00, 0x40, 0x5f, 0x08, 0x08, 0x58, 0x31, 0x89, 0x20, 0x58, 0x1e, 0x00, 0x00, +0x05, 0xe1, 0x80, 0x00, 0x46, 0x0f, 0xf0, 0x0f, 0x58, 0x00, 0x0f, 0xff, 0x40, 0x2f, 0x00, 0x02, +0x40, 0x0f, 0x20, 0x08, 0x40, 0x00, 0x60, 0x09, 0x44, 0x60, 0x00, 0x7f, 0x4c, 0x03, 0x00, 0x06, +0x45, 0xe0, 0x00, 0x81, 0x4c, 0x0f, 0x40, 0x04, 0x14, 0x21, 0x80, 0x00, 0x40, 0xf0, 0x90, 0x06, +0x4e, 0xf2, 0x00, 0x06, 0x04, 0x22, 0x80, 0x00, 0x14, 0x21, 0x80, 0x00, 0x50, 0x10, 0x80, 0x01, +0x44, 0x60, 0x00, 0x10, 0x50, 0x31, 0x80, 0x04, 0x4c, 0x13, 0x7f, 0xdc, 0x48, 0x00, 0x00, 0x3c, +0x44, 0x50, 0x00, 0x01, 0x4d, 0xc2, 0xc0, 0x6e, 0x46, 0x11, 0x80, 0x80, 0x58, 0x10, 0x86, 0x48, +0x40, 0x32, 0x04, 0x00, 0x46, 0x06, 0x02, 0x01, 0x40, 0x31, 0x88, 0x08, 0x58, 0x00, 0x09, 0x20, +0x44, 0x10, 0x00, 0x00, 0x05, 0xe0, 0x00, 0x00, 0x46, 0x2f, 0xf0, 0x0f, 0x58, 0x21, 0x0f, 0xff, +0x40, 0x5f, 0x08, 0x02, 0x40, 0x2f, 0x20, 0x08, 0x40, 0x21, 0x60, 0x09, 0x45, 0xe0, 0x00, 0x7f, +0x4c, 0x2f, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x81, 0x4c, 0x2f, 0x40, 0x04, 0x14, 0x50, 0x00, 0x00, +0x40, 0xf0, 0x90, 0x06, 0x4e, 0xf2, 0x00, 0x06, 0x04, 0x51, 0x80, 0x00, 0x14, 0x50, 0x00, 0x00, +0x50, 0x10, 0x80, 0x01, 0x44, 0x60, 0x00, 0x10, 0x50, 0x00, 0x00, 0x04, 0x4c, 0x13, 0x7f, 0xdc, +0x48, 0x00, 0x00, 0x1e, 0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x09, 0x20, 0x3f, 0xef, 0xc4, 0x60, +0x46, 0x49, 0xfd, 0xff, 0x04, 0x20, 0x00, 0x00, 0x40, 0x10, 0x78, 0x00, 0x58, 0x42, 0x09, 0x14, +0x46, 0x66, 0x02, 0x00, 0x40, 0x30, 0x90, 0x00, 0x50, 0x00, 0x00, 0x04, 0x58, 0x63, 0x09, 0x60, +0x14, 0x21, 0x80, 0x00, 0x4c, 0x03, 0x7f, 0xec, 0x48, 0x00, 0x00, 0x1c, 0x46, 0x06, 0x02, 0x01, +0x58, 0x00, 0x09, 0x20, 0x3e, 0x1f, 0xc4, 0x60, 0x46, 0x39, 0xfd, 0xfe, 0x04, 0x60, 0x00, 0x00, +0x40, 0x20, 0x04, 0x00, 0x58, 0x31, 0x89, 0x54, 0x40, 0x51, 0x0c, 0x00, 0x14, 0x62, 0x80, 0x00, +0x46, 0x66, 0x02, 0x01, 0x50, 0x00, 0x00, 0x04, 0x58, 0x63, 0x09, 0x60, 0x4c, 0x03, 0x7f, 0xec, +0x49, 0xff, 0xf1, 0x46, 0x3c, 0x4d, 0xec, 0xd5, 0x46, 0x08, 0x10, 0x60, 0x14, 0x40, 0x00, 0x02, +0x51, 0xff, 0x80, 0x1c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, +0x46, 0x18, 0x18, 0x00, 0x44, 0x20, 0x00, 0x00, 0x58, 0x10, 0x80, 0x07, 0x44, 0x00, 0x00, 0x6c, +0x49, 0xff, 0xf0, 0x0e, 0x44, 0x10, 0x00, 0x00, 0x44, 0x00, 0x06, 0x10, 0x49, 0xff, 0xf0, 0x26, +0x42, 0x10, 0x5c, 0x08, 0x44, 0x20, 0x00, 0x00, 0x44, 0x00, 0x06, 0x10, 0x49, 0xff, 0xf0, 0x00, +0x3c, 0x6d, 0xed, 0x40, 0x44, 0x80, 0x00, 0x0c, 0x42, 0x43, 0x20, 0x24, 0x3e, 0x1f, 0xa4, 0xac, +0x40, 0x52, 0x04, 0x00, 0x04, 0x42, 0x80, 0x02, 0x46, 0x2f, 0xfc, 0x00, 0x44, 0x30, 0x00, 0x16, +0x44, 0x00, 0x00, 0xe4, 0x44, 0x10, 0x00, 0x00, 0x49, 0xff, 0xf0, 0x2e, 0x46, 0x18, 0x00, 0x00, +0x44, 0x20, 0x00, 0x00, 0x44, 0x00, 0x00, 0x70, 0x49, 0xff, 0xf0, 0x48, 0x58, 0x04, 0x00, 0x00, +0x49, 0xff, 0xa5, 0x16, 0x46, 0x18, 0x00, 0x00, 0x44, 0x00, 0x00, 0x70, 0x44, 0x20, 0x00, 0x00, +0x49, 0xff, 0xf0, 0x54, 0x44, 0x10, 0x00, 0x00, 0x58, 0x20, 0x80, 0x00, 0x44, 0x00, 0x00, 0x6c, +0x49, 0xff, 0xef, 0xce, 0x44, 0x10, 0x00, 0x00, 0x44, 0x00, 0x08, 0x34, 0x49, 0xff, 0xef, 0xe6, +0x40, 0x00, 0x1c, 0x08, 0x40, 0x30, 0x6c, 0x09, 0x3e, 0x7f, 0xc4, 0x60, 0x14, 0x33, 0x80, 0x6f, +0x46, 0x10, 0x02, 0x00, 0x44, 0x00, 0x00, 0xe4, 0x44, 0x20, 0x00, 0x01, 0x49, 0xff, 0xf0, 0x1e, +0x04, 0x43, 0x80, 0x6f, 0x44, 0x30, 0x00, 0x0b, 0x44, 0x00, 0x00, 0xe4, 0x44, 0x10, 0x00, 0x01, +0x44, 0x20, 0xf8, 0x00, 0x49, 0xff, 0xef, 0xf0, 0x44, 0x00, 0x00, 0xe4, 0x44, 0x10, 0x04, 0x00, +0x44, 0x20, 0x00, 0x01, 0x49, 0xff, 0xf0, 0x22, 0x04, 0x43, 0x80, 0x6f, 0x44, 0x00, 0x00, 0xe4, +0x44, 0x10, 0x00, 0x01, 0x44, 0x20, 0x00, 0x1f, 0x44, 0x30, 0x00, 0x00, 0x49, 0xff, 0xef, 0xdc, +0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x4e, 0x03, 0x00, 0x04, 0x49, 0xff, 0xff, 0x74, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, 0x58, 0x80, 0x80, 0x00, 0x58, 0x60, 0x00, 0x00, +0x58, 0x71, 0x00, 0x00, 0x4e, 0x13, 0x00, 0x14, 0x3e, 0x0f, 0xa8, 0xc0, 0x38, 0x10, 0x0b, 0x02, +0x3e, 0x9f, 0x4c, 0xf8, 0x44, 0x00, 0x00, 0xa0, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x24, 0x01, +0x40, 0x03, 0x8c, 0x08, 0x3e, 0x1f, 0xa8, 0xc0, 0x48, 0x00, 0x00, 0x16, 0x44, 0x10, 0x00, 0x01, +0x4c, 0x80, 0xc0, 0x1c, 0x3e, 0x2f, 0xa9, 0x40, 0x38, 0x11, 0x1f, 0x02, 0x44, 0x00, 0x00, 0xa0, +0x58, 0x23, 0x00, 0x00, 0x3e, 0x9f, 0x4c, 0xf8, 0x4b, 0xe0, 0x24, 0x01, 0x40, 0x03, 0x8c, 0x08, +0x3e, 0x1f, 0xa9, 0x40, 0x40, 0x30, 0x04, 0x00, 0x04, 0x11, 0x80, 0x01, 0x44, 0x00, 0x00, 0x70, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x24, 0x01, 0x46, 0x18, 0x20, 0x24, 0x58, 0x10, 0x80, 0xc0, +0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xef, 0x42, 0x44, 0x00, 0x00, 0x01, +0x49, 0xff, 0xa4, 0x76, 0x44, 0x00, 0x04, 0x1c, 0x58, 0x13, 0x00, 0x00, 0x49, 0xff, 0xef, 0x56, +0x40, 0x40, 0x70, 0x09, 0x4e, 0x43, 0xff, 0xf4, 0x46, 0x10, 0x20, 0x04, 0x58, 0x10, 0x80, 0xc0, +0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xef, 0x2a, 0x44, 0x00, 0x04, 0x68, +0x58, 0x13, 0x00, 0x00, 0x49, 0xff, 0xef, 0x42, 0x40, 0x40, 0x00, 0x13, 0x4e, 0x82, 0x00, 0x0a, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x82, 0xc0, 0x06, 0x44, 0x10, 0x04, 0x48, 0x48, 0x00, 0x00, 0x04, +0x44, 0x10, 0x04, 0x28, 0x40, 0x23, 0x84, 0x09, 0x40, 0x01, 0x08, 0x08, 0x54, 0x33, 0x80, 0x01, +0x40, 0x00, 0x80, 0x00, 0x4e, 0x33, 0x00, 0x08, 0x58, 0x13, 0x00, 0x00, 0x44, 0x20, 0xff, 0xff, +0x48, 0x00, 0x00, 0x08, 0x58, 0x13, 0x00, 0x00, 0x44, 0x2f, 0x00, 0x00, 0x44, 0x30, 0x00, 0x10, +0x49, 0xff, 0xef, 0x42, 0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x46, 0x18, 0x03, 0x00, 0x58, 0x20, 0x00, 0x00, 0x58, 0x70, 0x00, 0x00, +0x58, 0x10, 0x80, 0x08, 0x44, 0x00, 0x07, 0xdc, 0x49, 0xff, 0xee, 0xea, 0x44, 0x00, 0x00, 0x02, +0x49, 0xff, 0xa4, 0x1e, 0x46, 0x10, 0x03, 0x00, 0x58, 0x10, 0x80, 0x08, 0x58, 0x23, 0x80, 0x00, +0x44, 0x00, 0x07, 0xdc, 0x49, 0xff, 0xee, 0xdc, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x40, 0x00, 0x00, 0x13, +0x58, 0x60, 0x80, 0x00, 0x4e, 0x03, 0x00, 0x0c, 0x3e, 0x0f, 0x99, 0x3c, 0x3e, 0x1f, 0xa3, 0x64, +0x44, 0x20, 0x09, 0x58, 0x49, 0xff, 0x92, 0xea, 0x48, 0x00, 0x00, 0x00, 0x50, 0x90, 0x7f, 0xff, +0x49, 0xff, 0xde, 0xc4, 0x44, 0x20, 0x00, 0x0f, 0x58, 0x04, 0x80, 0x00, 0x42, 0x03, 0x08, 0x73, +0x3e, 0x7f, 0xc4, 0x60, 0x38, 0x43, 0x81, 0x01, 0x46, 0x20, 0x7f, 0x00, 0x3c, 0x8d, 0xed, 0x40, +0x3e, 0x7f, 0x4d, 0x80, 0x44, 0x00, 0x00, 0xb0, 0x58, 0x13, 0x00, 0x00, 0x44, 0x30, 0x00, 0x14, +0x4b, 0xe0, 0x1c, 0x01, 0x40, 0x44, 0x88, 0x08, 0x40, 0x32, 0x20, 0x00, 0x50, 0x91, 0x80, 0x01, +0x3e, 0x2f, 0xa4, 0xd0, 0x38, 0x41, 0x27, 0x01, 0x44, 0x00, 0x00, 0xb0, 0x58, 0x13, 0x00, 0x00, +0x44, 0x23, 0xff, 0xf0, 0x44, 0x30, 0x00, 0x04, 0x4b, 0xe0, 0x1c, 0x01, 0x40, 0x04, 0x8c, 0x08, +0x3e, 0x1f, 0xa4, 0xd0, 0x40, 0x80, 0x04, 0x00, 0x02, 0x44, 0x00, 0x01, 0x46, 0x23, 0xff, 0x00, +0x44, 0x00, 0x01, 0x0c, 0x58, 0x13, 0x00, 0x00, 0x44, 0x30, 0x00, 0x14, 0x4b, 0xe0, 0x1c, 0x01, +0x04, 0x44, 0x00, 0x01, 0x46, 0x20, 0x00, 0xff, 0x44, 0x30, 0x00, 0x00, 0x58, 0x21, 0x0f, 0xff, +0x44, 0x00, 0x01, 0x0c, 0x58, 0x13, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x1f, 0xff, 0x0c, +0x58, 0x10, 0x80, 0x10, 0x44, 0x00, 0x00, 0xb4, 0x58, 0x23, 0x00, 0x00, 0x3e, 0x7e, 0xb7, 0x68, +0x49, 0xff, 0xee, 0x66, 0x44, 0x00, 0x00, 0x64, 0x4b, 0xe0, 0x1c, 0x01, 0x58, 0x93, 0x80, 0x00, +0x44, 0x70, 0x00, 0x00, 0x44, 0x00, 0x00, 0x64, 0x4b, 0xe0, 0x24, 0x01, 0x58, 0x13, 0x00, 0x00, +0x44, 0x00, 0x04, 0x24, 0x49, 0xff, 0xee, 0x72, 0x42, 0x30, 0x68, 0x0b, 0x4e, 0x33, 0x00, 0x12, +0x44, 0x50, 0x00, 0x0b, 0x4c, 0x72, 0x80, 0x06, 0x50, 0x73, 0x80, 0x01, 0x48, 0xff, 0xff, 0xec, +0x3e, 0x0f, 0xa3, 0x98, 0x3e, 0x1f, 0xb0, 0x24, 0x44, 0x20, 0x09, 0x9b, 0x49, 0xff, 0x92, 0x66, +0x46, 0x13, 0xff, 0x0c, 0x58, 0x10, 0x80, 0x10, 0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x00, 0xb4, +0x49, 0xff, 0xee, 0x36, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xfe, 0xd4, 0x3e, 0x4f, 0xad, 0x24, 0x58, 0x80, 0x00, 0x00, +0x59, 0xc0, 0x80, 0x00, 0x3a, 0x02, 0x0c, 0x04, 0x50, 0x9f, 0x80, 0xe8, 0x59, 0xe4, 0x80, 0x00, +0x3e, 0x6f, 0xac, 0xe4, 0x50, 0x7f, 0x80, 0xa8, 0x3a, 0x0f, 0x0c, 0x24, 0x3e, 0x5f, 0xac, 0xa4, +0x50, 0x9f, 0x80, 0x68, 0x3a, 0x02, 0x0c, 0x04, 0x3a, 0x0f, 0x0c, 0x24, 0x3a, 0x02, 0x0c, 0x04, +0x3a, 0x0f, 0x0c, 0x24, 0x3a, 0x02, 0x0c, 0x00, 0x58, 0x44, 0x80, 0x00, 0x3a, 0x0f, 0x0c, 0x20, +0x3a, 0x03, 0x0c, 0x04, 0x3a, 0x03, 0x8c, 0x24, 0x3a, 0x03, 0x0c, 0x04, 0x3a, 0x03, 0x8c, 0x24, +0x3a, 0x03, 0x0c, 0x04, 0x3a, 0x03, 0x8c, 0x24, 0x3a, 0x03, 0x0c, 0x00, 0x3a, 0x03, 0x8c, 0x20, +0x3a, 0x02, 0x8c, 0x04, 0x3a, 0x02, 0x0c, 0x24, 0x3a, 0x02, 0x8c, 0x04, 0x3a, 0x02, 0x0c, 0x24, +0x3a, 0x02, 0x8c, 0x04, 0x3a, 0x02, 0x0c, 0x24, 0x3a, 0x02, 0x8c, 0x00, 0x3a, 0x02, 0x0c, 0x20, +0x49, 0xff, 0xf8, 0xa8, 0x44, 0x50, 0x00, 0x08, 0x4c, 0x82, 0xc0, 0x0e, 0x44, 0x00, 0x00, 0x0f, +0x44, 0x10, 0x00, 0x00, 0x49, 0xff, 0xff, 0x08, 0x44, 0x00, 0x00, 0x0f, 0x44, 0x10, 0x00, 0x01, +0x49, 0xff, 0xff, 0x02, 0x50, 0x7f, 0x80, 0x28, 0x58, 0x03, 0x80, 0x00, 0x44, 0x10, 0x00, 0x00, +0x44, 0x20, 0x00, 0x40, 0x49, 0xf7, 0xa0, 0xa2, 0x58, 0x03, 0x80, 0x00, 0x44, 0x30, 0x00, 0x00, +0x50, 0x4f, 0x80, 0xe8, 0x38, 0x52, 0x0c, 0x02, 0x44, 0x10, 0x00, 0x40, 0x04, 0x22, 0x80, 0x00, +0x38, 0x20, 0x0c, 0x0a, 0x50, 0x31, 0x80, 0x04, 0x4c, 0x30, 0xff, 0xf6, 0x3e, 0xaf, 0x4d, 0x34, +0x44, 0x10, 0x00, 0x00, 0x44, 0x00, 0x00, 0xa0, 0x4b, 0xe0, 0x28, 0x01, 0x14, 0x0f, 0x80, 0x09, +0x44, 0x10, 0x00, 0x00, 0x44, 0x00, 0x00, 0x48, 0x4b, 0xe0, 0x28, 0x01, 0x14, 0x0f, 0x80, 0x08, +0x44, 0x10, 0x00, 0x00, 0x44, 0x00, 0x00, 0x70, 0x4b, 0xe0, 0x28, 0x01, 0x14, 0x0f, 0x80, 0x07, +0x44, 0x10, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x4b, 0xe0, 0x28, 0x01, 0x14, 0x0f, 0x80, 0x06, +0x44, 0x10, 0x00, 0x01, 0x44, 0x00, 0x00, 0xa0, 0x4b, 0xe0, 0x28, 0x01, 0x14, 0x0f, 0x80, 0x05, +0x44, 0x10, 0x00, 0x01, 0x44, 0x00, 0x00, 0x48, 0x4b, 0xe0, 0x28, 0x01, 0x14, 0x0f, 0x80, 0x04, +0x44, 0x10, 0x00, 0x01, 0x44, 0x00, 0x00, 0x70, 0x4b, 0xe0, 0x28, 0x01, 0x14, 0x0f, 0x80, 0x03, +0x44, 0x10, 0x00, 0x01, 0x44, 0x00, 0x00, 0x44, 0x4b, 0xe0, 0x28, 0x01, 0x14, 0x0f, 0x80, 0x02, +0x44, 0x10, 0x00, 0x00, 0x44, 0x00, 0x00, 0x48, 0x4b, 0xe0, 0x28, 0x01, 0x46, 0x4f, 0xf1, 0xff, +0x58, 0x42, 0x0f, 0xff, 0x46, 0x30, 0x0a, 0x00, 0x40, 0x70, 0x10, 0x02, 0x40, 0x13, 0x8c, 0x04, +0x44, 0x20, 0x00, 0x00, 0x3e, 0x7f, 0x4c, 0xf8, 0x44, 0x00, 0x00, 0x48, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0x6f, 0xf1, 0xff, 0x44, 0x10, 0x00, 0x01, 0x44, 0x00, 0x00, 0x48, 0x4b, 0xe0, 0x28, 0x01, +0x58, 0x63, 0x0f, 0xff, 0x40, 0x50, 0x18, 0x02, 0x46, 0x00, 0x0a, 0x00, 0x46, 0x96, 0x02, 0x00, +0x40, 0x12, 0x80, 0x04, 0x44, 0x00, 0x00, 0x48, 0x44, 0x20, 0x00, 0x01, 0x4b, 0xe0, 0x1c, 0x01, +0x04, 0x14, 0x81, 0x80, 0x42, 0x80, 0xd4, 0x09, 0x42, 0x84, 0x58, 0x09, 0x14, 0x84, 0x81, 0x80, +0x46, 0x36, 0x02, 0x00, 0x04, 0x41, 0x81, 0x44, 0x46, 0x06, 0x02, 0x01, 0x58, 0xa2, 0x00, 0x08, +0x14, 0xa1, 0x81, 0x44, 0x04, 0x60, 0x01, 0x44, 0x58, 0x81, 0x80, 0x00, 0x58, 0x53, 0x00, 0x08, +0x14, 0x50, 0x01, 0x44, 0x04, 0x24, 0x00, 0xcb, 0x58, 0xa1, 0x80, 0x00, 0x58, 0x11, 0x00, 0x07, +0x14, 0x14, 0x00, 0xcb, 0x04, 0x45, 0x01, 0x84, 0x46, 0x06, 0x02, 0x04, 0x46, 0x60, 0x10, 0x10, +0x42, 0x32, 0x60, 0x09, 0x58, 0x63, 0x05, 0x05, 0x14, 0x35, 0x01, 0x84, 0x14, 0x60, 0x00, 0x08, +0x4f, 0xc3, 0x00, 0x20, 0x46, 0x18, 0x00, 0x00, 0x44, 0x00, 0x00, 0xa0, 0x58, 0x2e, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x18, 0x00, 0x00, 0x44, 0x00, 0x00, 0xa0, 0x44, 0x20, 0x00, 0x01, +0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x36, 0x02, 0x04, 0x58, 0x31, 0x81, 0x00, 0x04, 0x91, 0x80, 0x00, +0x46, 0x8f, 0x8f, 0xff, 0x58, 0x84, 0x0f, 0xff, 0x40, 0x44, 0xa0, 0x02, 0x48, 0x00, 0x00, 0x24, +0x44, 0x50, 0x00, 0x01, 0x4d, 0xc2, 0xc0, 0x22, 0x46, 0x19, 0x00, 0x00, 0x44, 0x00, 0x00, 0xa0, +0x44, 0x20, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x19, 0x00, 0x00, 0x44, 0x00, 0x00, 0xa0, +0x58, 0x2e, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x36, 0x02, 0x04, 0x58, 0x31, 0x81, 0x00, +0x04, 0x21, 0x80, 0x00, 0x46, 0x0f, 0x8f, 0xff, 0x58, 0x00, 0x0f, 0xff, 0x40, 0x11, 0x00, 0x02, +0x42, 0x40, 0xe0, 0x08, 0x14, 0x41, 0x80, 0x00, 0x46, 0xa6, 0x02, 0x00, 0x44, 0x70, 0x00, 0x02, +0x14, 0x75, 0x00, 0x02, 0x47, 0xe6, 0x01, 0x20, 0x04, 0x5f, 0x00, 0x20, 0x42, 0x02, 0xa4, 0x09, +0x14, 0x0f, 0x00, 0x20, 0x44, 0x10, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x49, 0xff, 0xec, 0xde, +0x40, 0x20, 0x14, 0x08, 0x40, 0x21, 0x14, 0x09, 0x42, 0x11, 0x78, 0x08, 0x44, 0x20, 0x00, 0x00, +0x44, 0x00, 0x00, 0x44, 0x49, 0xff, 0xec, 0xb4, 0x44, 0x10, 0x00, 0x01, 0x44, 0x00, 0x00, 0x44, +0x49, 0xff, 0xec, 0xcc, 0x46, 0x76, 0x02, 0x01, 0x46, 0x36, 0x02, 0x00, 0x40, 0x40, 0x14, 0x08, +0x40, 0x42, 0x14, 0x09, 0x14, 0x7f, 0x80, 0x01, 0x14, 0x3f, 0x80, 0x00, 0x42, 0x12, 0x78, 0x08, +0x44, 0x00, 0x00, 0x44, 0x44, 0x20, 0x00, 0x01, 0x49, 0xff, 0xec, 0x9a, 0x04, 0x6f, 0x80, 0x00, +0x04, 0x5f, 0x80, 0x01, 0x58, 0x63, 0x05, 0x7c, 0x58, 0x52, 0x85, 0x7c, 0x44, 0x80, 0x00, 0x00, +0x14, 0x6f, 0x80, 0x00, 0x14, 0x5f, 0x80, 0x01, 0x58, 0xa4, 0x00, 0x00, 0x04, 0x3f, 0x80, 0x00, +0x50, 0x2f, 0x80, 0x68, 0x04, 0x91, 0x80, 0x00, 0x38, 0x61, 0x20, 0x02, 0x46, 0x4f, 0xfe, 0x00, +0x58, 0x42, 0x00, 0x7f, 0x41, 0xe4, 0x90, 0x02, 0x04, 0x1f, 0x80, 0x00, 0x40, 0x43, 0x1c, 0x08, +0x40, 0x52, 0x78, 0x04, 0x14, 0x50, 0x80, 0x00, 0x46, 0x3f, 0xfe, 0x00, 0x04, 0x0f, 0x80, 0x01, +0x58, 0x31, 0x80, 0x7f, 0x04, 0x20, 0x00, 0x00, 0x04, 0x6f, 0x80, 0x01, 0x40, 0x91, 0x0c, 0x02, +0x41, 0xe4, 0x90, 0x04, 0x15, 0xe3, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x44, 0x00, 0x00, 0x70, +0x49, 0xff, 0xec, 0x7c, 0x50, 0x5f, 0x80, 0xa8, 0x38, 0x92, 0xa0, 0x02, 0x40, 0x00, 0x20, 0x09, +0x40, 0x00, 0x20, 0x08, 0x40, 0x10, 0x24, 0x04, 0x44, 0x20, 0x00, 0x00, 0x44, 0x00, 0x00, 0x70, +0x49, 0xff, 0xec, 0x4e, 0x44, 0x10, 0x00, 0x01, 0x44, 0x00, 0x00, 0x70, 0x49, 0xff, 0xec, 0x66, +0x40, 0x30, 0x20, 0x09, 0x40, 0x31, 0xa0, 0x08, 0x40, 0x11, 0xa4, 0x04, 0x44, 0x00, 0x00, 0x70, +0x44, 0x20, 0x00, 0x01, 0x49, 0xff, 0xec, 0x3c, 0x58, 0x35, 0x00, 0x00, 0x58, 0x1e, 0x00, 0x00, +0x44, 0x20, 0x00, 0x00, 0x3e, 0x0f, 0xc8, 0x00, 0x49, 0xff, 0xf5, 0x62, 0x58, 0x90, 0x00, 0x00, +0x44, 0x20, 0x00, 0x01, 0x44, 0x50, 0x00, 0x02, 0x58, 0x35, 0x00, 0x00, 0x3e, 0x0f, 0xc8, 0x00, +0x58, 0x1e, 0x00, 0x00, 0x40, 0xa5, 0x08, 0x00, 0x4c, 0x92, 0x80, 0x10, 0x49, 0xff, 0xf5, 0x50, +0x58, 0x90, 0x00, 0x00, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x92, 0x80, 0x08, 0x50, 0x52, 0x80, 0x0e, +0x50, 0x84, 0x00, 0x04, 0x4c, 0xa2, 0xff, 0x8c, 0x44, 0x20, 0x00, 0x00, 0x50, 0x6f, 0x80, 0xe8, +0x50, 0x5f, 0x80, 0x28, 0x38, 0x73, 0x08, 0x02, 0x38, 0x12, 0x88, 0x02, 0x44, 0x80, 0x00, 0x40, +0x50, 0x21, 0x00, 0x04, 0x14, 0x13, 0x80, 0x00, 0x4c, 0x24, 0x7f, 0xf6, 0x04, 0x1f, 0x80, 0x09, +0x3e, 0x6f, 0x4c, 0xf8, 0x44, 0x00, 0x00, 0xa0, 0x44, 0x20, 0x00, 0x00, 0x4b, 0xe0, 0x18, 0x01, +0x04, 0x1f, 0x80, 0x08, 0x44, 0x00, 0x00, 0x48, 0x44, 0x20, 0x00, 0x00, 0x4b, 0xe0, 0x18, 0x01, +0x04, 0x1f, 0x80, 0x07, 0x44, 0x00, 0x00, 0x70, 0x44, 0x20, 0x00, 0x00, 0x4b, 0xe0, 0x18, 0x01, +0x04, 0x1f, 0x80, 0x06, 0x44, 0x00, 0x00, 0x44, 0x44, 0x20, 0x00, 0x00, 0x4b, 0xe0, 0x18, 0x01, +0x04, 0x1f, 0x80, 0x05, 0x44, 0x00, 0x00, 0xa0, 0x44, 0x20, 0x00, 0x01, 0x4b, 0xe0, 0x18, 0x01, +0x04, 0x1f, 0x80, 0x04, 0x44, 0x00, 0x00, 0x48, 0x44, 0x20, 0x00, 0x01, 0x4b, 0xe0, 0x18, 0x01, +0x04, 0x1f, 0x80, 0x03, 0x44, 0x00, 0x00, 0x70, 0x44, 0x20, 0x00, 0x01, 0x4b, 0xe0, 0x18, 0x01, +0x04, 0x1f, 0x80, 0x02, 0x44, 0x20, 0x00, 0x01, 0x44, 0x00, 0x00, 0x44, 0x4b, 0xe0, 0x18, 0x01, +0x3c, 0x03, 0xda, 0x73, 0x44, 0x10, 0x00, 0x00, 0x49, 0xff, 0xfc, 0xe6, 0x46, 0x66, 0x01, 0x20, +0x3c, 0x03, 0xda, 0x73, 0x58, 0x63, 0x00, 0x80, 0x44, 0x10, 0x00, 0x01, 0x49, 0xff, 0xfc, 0xdc, +0x04, 0x53, 0x00, 0x00, 0x42, 0x02, 0xa0, 0x09, 0x14, 0x03, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, +0x49, 0xff, 0xa0, 0xde, 0x04, 0x33, 0x00, 0x00, 0x42, 0x41, 0xa4, 0x09, 0x14, 0x43, 0x00, 0x00, +0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0xa0, 0xd4, 0x58, 0x04, 0x80, 0x00, 0x51, 0xff, 0x81, 0x2c, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x58, 0x60, 0x00, 0x00, 0x40, 0x81, 0x00, 0x13, 0x58, 0x70, 0x80, 0x00, 0x58, 0x04, 0x00, 0x00, +0x58, 0x13, 0x00, 0x00, 0x58, 0x91, 0x80, 0x00, 0x49, 0xff, 0xfc, 0xae, 0x58, 0x03, 0x80, 0x00, +0x58, 0x13, 0x00, 0x00, 0x49, 0xff, 0xec, 0x50, 0x58, 0x03, 0x80, 0x00, 0x58, 0x13, 0x00, 0x00, +0x49, 0xff, 0xee, 0x7a, 0x2e, 0x07, 0xb4, 0xf4, 0x4e, 0x03, 0x00, 0x06, 0x58, 0x03, 0x00, 0x00, +0x49, 0xff, 0xf6, 0x74, 0x58, 0x03, 0x80, 0x00, 0x58, 0x13, 0x00, 0x00, 0x49, 0xff, 0xec, 0x3c, +0x58, 0x03, 0x80, 0x00, 0x58, 0x14, 0x80, 0x00, 0x49, 0xff, 0xef, 0xb6, 0x58, 0x03, 0x00, 0x00, +0x58, 0x14, 0x00, 0x00, 0x49, 0xff, 0xed, 0x84, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xa4, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x44, 0x70, 0x00, 0x00, +0x49, 0xff, 0xf6, 0x46, 0x44, 0x80, 0x00, 0x01, 0x49, 0xff, 0xfb, 0x32, 0x3e, 0x9f, 0xb2, 0xec, +0x48, 0x00, 0x00, 0x44, 0x4e, 0x73, 0x00, 0x06, 0x44, 0x80, 0x00, 0x01, 0x48, 0x00, 0x00, 0x08, +0x56, 0x03, 0x80, 0x01, 0x44, 0x10, 0x00, 0x00, 0x40, 0x80, 0x80, 0x1a, 0x44, 0x60, 0x00, 0x00, +0x48, 0x00, 0x00, 0x26, 0x2e, 0x37, 0xb4, 0xf4, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x32, 0x80, 0x0a, +0x38, 0x14, 0x9b, 0x02, 0x4e, 0x12, 0x00, 0x18, 0x00, 0x01, 0x00, 0x04, 0x48, 0x00, 0x00, 0x0e, +0x38, 0x14, 0x9b, 0x02, 0x40, 0x23, 0x0c, 0x08, 0x3e, 0x5f, 0xb2, 0xec, 0x40, 0x01, 0x14, 0x00, +0x4e, 0x12, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x05, 0x4e, 0x02, 0x00, 0x06, 0x58, 0x04, 0x00, 0x00, +0x4b, 0xe0, 0x04, 0x01, 0x50, 0x63, 0x00, 0x01, 0x54, 0x63, 0x00, 0xff, 0x2f, 0xe7, 0xb5, 0x10, +0x40, 0x13, 0x0c, 0x08, 0x3e, 0x3f, 0xb2, 0xec, 0x40, 0x20, 0x8c, 0x00, 0x40, 0xf3, 0x78, 0x06, +0x4e, 0xf3, 0xff, 0xd2, 0x50, 0x73, 0x80, 0x01, 0x3c, 0x4d, 0xed, 0x42, 0x40, 0xf3, 0x90, 0x06, +0x4e, 0xf3, 0xff, 0xba, 0x49, 0xff, 0xf5, 0x88, 0x44, 0x80, 0x00, 0x07, 0x3e, 0x7f, 0xb2, 0xe8, +0x44, 0x60, 0x00, 0x00, 0x12, 0x83, 0x80, 0x00, 0x3c, 0x8b, 0xda, 0x73, 0x3c, 0x8b, 0xda, 0x72, +0x3c, 0x6f, 0xed, 0x3a, 0x58, 0x93, 0x80, 0x00, 0x48, 0x00, 0x00, 0x08, 0x02, 0x24, 0x80, 0x00, +0x50, 0x63, 0x00, 0x01, 0x49, 0xff, 0xff, 0x52, 0x3d, 0xed, 0xed, 0x42, 0x44, 0x10, 0x00, 0x00, +0x58, 0x03, 0x00, 0x00, 0x58, 0x30, 0x80, 0x00, 0x40, 0xf3, 0x78, 0x06, 0x4e, 0xf3, 0xff, 0xf0, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xd4, 0x14, 0x0f, 0x80, 0x01, 0x3c, 0x03, 0xd9, 0x74, 0x04, 0x1f, 0x80, 0x01, +0x49, 0xff, 0xfb, 0xf2, 0x04, 0x2f, 0x80, 0x01, 0x46, 0x18, 0x1b, 0xd6, 0x58, 0x10, 0x8c, 0x7f, +0x44, 0x00, 0x00, 0x6c, 0x49, 0xff, 0xea, 0xbc, 0x04, 0x2f, 0x80, 0x01, 0x46, 0x18, 0xc0, 0x08, +0x58, 0x10, 0x82, 0xd0, 0x44, 0x00, 0x00, 0x44, 0x49, 0xff, 0xea, 0xb2, 0x04, 0x2f, 0x80, 0x01, +0x46, 0x1f, 0x8b, 0x00, 0x58, 0x10, 0x87, 0x27, 0x44, 0x00, 0x00, 0x48, 0x49, 0xff, 0xea, 0xa8, +0x04, 0x4f, 0x80, 0x01, 0x44, 0x50, 0x00, 0x0c, 0x42, 0x32, 0x14, 0x24, 0x3e, 0x1f, 0xc4, 0x60, +0x40, 0x01, 0x84, 0x00, 0x14, 0x0f, 0x80, 0x02, 0x50, 0x22, 0x00, 0x6e, 0x51, 0xc2, 0x00, 0x6c, +0x04, 0x3f, 0x80, 0x01, 0x04, 0x1f, 0x80, 0x02, 0x40, 0xa1, 0x0c, 0x08, 0x40, 0x7e, 0x0c, 0x08, +0x3e, 0x9f, 0xc4, 0x60, 0x58, 0x64, 0x80, 0x00, 0x44, 0x50, 0x00, 0x00, 0x40, 0x85, 0x24, 0x00, +0x40, 0x43, 0x98, 0x00, 0x40, 0x21, 0x8c, 0x08, 0x50, 0x00, 0x83, 0x4c, 0x14, 0x5f, 0x80, 0x05, +0x14, 0x8f, 0x80, 0x07, 0x14, 0x4f, 0x80, 0x08, 0x14, 0x5f, 0x80, 0x03, 0x14, 0x2f, 0x80, 0x04, +0x14, 0x0f, 0x80, 0x06, 0x46, 0x10, 0x06, 0x10, 0x04, 0x2f, 0x80, 0x01, 0x58, 0x10, 0x80, 0x88, +0x44, 0x00, 0x00, 0xe8, 0x49, 0xff, 0xea, 0x6c, 0x2e, 0x77, 0xb4, 0xf4, 0x4e, 0x73, 0x00, 0x08, +0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x88, 0x48, 0x00, 0x00, 0x06, 0x46, 0x10, 0x06, 0x10, +0x58, 0x10, 0x80, 0x87, 0x04, 0x2f, 0x80, 0x01, 0x44, 0x00, 0x00, 0xe8, 0x49, 0xff, 0xea, 0x58, +0x04, 0x9f, 0x80, 0x03, 0x4e, 0x93, 0x00, 0x10, 0x46, 0x10, 0x50, 0x00, 0x04, 0x2f, 0x80, 0x01, +0x58, 0x10, 0x8b, 0xb8, 0x44, 0x00, 0x00, 0x70, 0x49, 0xff, 0xea, 0x4a, 0x46, 0x18, 0x00, 0x00, +0x48, 0x00, 0x00, 0x0e, 0x46, 0x10, 0x50, 0x00, 0x04, 0x2f, 0x80, 0x01, 0x58, 0x10, 0x8b, 0xb8, +0x44, 0x00, 0x00, 0x70, 0x49, 0xff, 0xea, 0x3c, 0x46, 0x19, 0x00, 0x00, 0x04, 0x2f, 0x80, 0x01, +0x44, 0x00, 0x00, 0xa0, 0x49, 0xff, 0xea, 0x34, 0x46, 0x18, 0x20, 0x24, 0x04, 0x2f, 0x80, 0x01, +0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, 0x49, 0xff, 0xea, 0x2a, 0x44, 0x00, 0x00, 0x01, +0x49, 0xff, 0x9f, 0x5e, 0x04, 0x1f, 0x80, 0x01, 0x44, 0x00, 0x04, 0x1c, 0x49, 0xff, 0xea, 0x3e, +0x40, 0xa0, 0x04, 0x08, 0x40, 0xa5, 0x74, 0x09, 0x4e, 0xa3, 0xff, 0xf2, 0x04, 0x2f, 0x80, 0x01, +0x46, 0x10, 0x20, 0x24, 0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, 0x49, 0xff, 0xea, 0x10, +0x46, 0x46, 0x02, 0x00, 0x58, 0x32, 0x00, 0x00, 0x58, 0x01, 0x80, 0x00, 0x44, 0x50, 0x00, 0x27, +0x44, 0x10, 0x00, 0x02, 0x14, 0x52, 0x00, 0x00, 0x14, 0x51, 0x80, 0x01, 0x14, 0x10, 0x00, 0x83, +0x04, 0x2f, 0x80, 0x01, 0x4e, 0x23, 0x00, 0x20, 0x47, 0xe6, 0x02, 0x00, 0x47, 0xc0, 0x40, 0x00, +0x46, 0xa0, 0x02, 0x74, 0x46, 0x3c, 0x00, 0x00, 0x46, 0x7f, 0x00, 0x00, 0x46, 0x44, 0x38, 0x00, +0x59, 0xef, 0x02, 0x00, 0x50, 0x2f, 0x0b, 0x00, 0x58, 0xa5, 0x00, 0x27, 0x50, 0x11, 0x00, 0x04, +0x58, 0x31, 0x84, 0x00, 0x50, 0x90, 0xb5, 0x10, 0x50, 0x81, 0x7d, 0x08, 0x50, 0x60, 0x80, 0x20, +0x48, 0x00, 0x00, 0x24, 0x04, 0x6f, 0x80, 0x01, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x2c, +0x47, 0xe6, 0x02, 0x00, 0x47, 0xc1, 0x40, 0x00, 0x46, 0xa0, 0x02, 0x74, 0x46, 0x3c, 0x00, 0x00, +0x46, 0x7f, 0x00, 0x00, 0x46, 0x44, 0x38, 0x00, 0x59, 0xef, 0x02, 0x00, 0x50, 0x2f, 0x1b, 0x00, +0x58, 0xa5, 0x00, 0x27, 0x50, 0x11, 0x00, 0x04, 0x58, 0x31, 0x84, 0x00, 0x50, 0x90, 0xb5, 0x10, +0x50, 0x81, 0x7d, 0x08, 0x50, 0x60, 0x80, 0x20, 0x15, 0xcf, 0x00, 0x00, 0x14, 0xa1, 0x00, 0x00, +0x44, 0xa0, 0x05, 0x95, 0x14, 0x30, 0x80, 0x00, 0x14, 0xa4, 0x80, 0x00, 0x14, 0x74, 0x00, 0x00, +0x14, 0x43, 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x44, 0x30, 0x08, 0x00, 0x58, 0x60, 0x00, 0x00, +0x58, 0x70, 0x00, 0x00, 0x46, 0xa6, 0x02, 0x04, 0x59, 0xc0, 0x00, 0x00, 0x14, 0x30, 0x80, 0x56, +0x44, 0x40, 0x00, 0x00, 0x58, 0x50, 0x00, 0x00, 0x59, 0xe0, 0x00, 0x00, 0x46, 0x04, 0x40, 0x0c, +0x58, 0x90, 0x80, 0x00, 0x46, 0x80, 0x02, 0x20, 0x44, 0x30, 0x00, 0x33, 0x44, 0x10, 0x00, 0x10, +0x14, 0x43, 0x00, 0x57, 0x58, 0x84, 0x0d, 0xa2, 0x14, 0x43, 0x80, 0x58, 0x58, 0x22, 0x80, 0x00, +0x14, 0x35, 0x00, 0x50, 0x14, 0x1e, 0x00, 0xe0, 0x58, 0x00, 0x01, 0x00, 0x45, 0xc1, 0x50, 0x68, +0x15, 0xc2, 0x80, 0xc0, 0x14, 0x0f, 0x01, 0xc1, 0x14, 0x84, 0x81, 0xb3, 0x44, 0x80, 0x13, 0x00, +0x14, 0x81, 0x00, 0x82, 0x04, 0x7f, 0x80, 0x03, 0x4e, 0x73, 0x00, 0x18, 0x05, 0xef, 0x80, 0x03, +0x58, 0x55, 0x00, 0x00, 0x58, 0x91, 0x00, 0x00, 0x46, 0x07, 0xa8, 0x28, 0x46, 0x8a, 0x77, 0xb6, +0x58, 0x00, 0x03, 0x80, 0x58, 0x84, 0x0f, 0x71, 0x15, 0xe2, 0x80, 0x40, 0x14, 0x04, 0x80, 0x60, +0x14, 0x81, 0x00, 0x61, 0x48, 0x00, 0x00, 0x18, 0x58, 0x65, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, +0x58, 0x41, 0x00, 0x00, 0x46, 0x77, 0xa8, 0x38, 0x59, 0xc1, 0x00, 0x00, 0x46, 0xaa, 0x67, 0xb6, +0x58, 0x73, 0x84, 0x80, 0x58, 0xa5, 0x0f, 0x71, 0x14, 0x13, 0x00, 0x40, 0x14, 0x72, 0x00, 0x60, +0x14, 0xae, 0x00, 0x61, 0x46, 0x86, 0x02, 0x00, 0x46, 0x36, 0x02, 0x00, 0x47, 0xc0, 0x90, 0x70, +0x59, 0xe4, 0x00, 0x00, 0x46, 0x50, 0x14, 0x20, 0x58, 0x31, 0x81, 0x50, 0x59, 0xce, 0x00, 0x01, +0x44, 0x90, 0x04, 0x1f, 0x14, 0x94, 0x00, 0x64, 0x15, 0xc1, 0x80, 0x00, 0x14, 0x5f, 0x00, 0x55, +0x50, 0x0e, 0x00, 0x04, 0x58, 0x94, 0x00, 0x00, 0x46, 0x80, 0x21, 0x00, 0x50, 0x21, 0x80, 0x08, +0x14, 0x0f, 0x80, 0x09, 0x04, 0x7f, 0x80, 0x05, 0x58, 0xa1, 0x80, 0x00, 0x58, 0x84, 0x00, 0x01, +0x59, 0xc1, 0x00, 0x00, 0x46, 0x40, 0x90, 0x70, 0x58, 0x42, 0x00, 0x05, 0x14, 0x45, 0x00, 0x00, +0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x9e, 0x4c, 0x04, 0x14, 0x80, 0x65, 0x54, 0x60, 0x80, 0x1f, +0x4e, 0x63, 0xff, 0xf8, 0x14, 0x85, 0x00, 0x00, 0x04, 0x2f, 0x80, 0x09, 0x04, 0x6e, 0x00, 0x00, +0x14, 0x25, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x9e, 0x3a, 0x04, 0x34, 0x80, 0x65, +0x54, 0x01, 0x80, 0x1f, 0x4e, 0x03, 0xff, 0xf8, 0x14, 0x85, 0x00, 0x00, 0x54, 0x13, 0x0f, 0xfc, +0x04, 0x6e, 0x00, 0x00, 0x40, 0x20, 0x88, 0x09, 0x54, 0x43, 0x0f, 0xfc, 0x50, 0x53, 0x80, 0x01, +0x40, 0x62, 0x08, 0x09, 0x51, 0xe1, 0x00, 0x0a, 0x54, 0x72, 0x80, 0xff, 0x40, 0xff, 0x18, 0x07, +0x4e, 0xf3, 0x00, 0x10, 0x50, 0x03, 0x00, 0x0a, 0x40, 0xf0, 0x08, 0x07, 0x4e, 0xf3, 0x00, 0x0a, +0x5c, 0xf3, 0x02, 0x1f, 0x4e, 0xf2, 0x00, 0x06, 0x5c, 0xf3, 0x01, 0xe3, 0x4e, 0xf2, 0x00, 0x06, +0x5c, 0xf3, 0x80, 0x03, 0x4e, 0xf3, 0xff, 0xb8, 0x04, 0x2f, 0x80, 0x03, 0x14, 0x7f, 0x80, 0x05, +0x50, 0x03, 0x7e, 0x1d, 0x4e, 0x23, 0x00, 0x54, 0x40, 0x30, 0x00, 0x13, 0x5c, 0xf1, 0x80, 0x3c, +0x4e, 0xf3, 0x00, 0x22, 0x04, 0x3f, 0x80, 0x04, 0x3e, 0x4f, 0xc4, 0x60, 0x04, 0x1f, 0x80, 0x02, +0x50, 0x10, 0x83, 0x20, 0x40, 0x51, 0x90, 0x00, 0x04, 0x0f, 0x80, 0x03, 0x47, 0xe8, 0x08, 0x08, +0x04, 0x4f, 0x80, 0x08, 0x59, 0xef, 0x00, 0x80, 0x44, 0x20, 0x08, 0x00, 0x14, 0x20, 0x80, 0x05, +0x14, 0x00, 0x80, 0x06, 0x14, 0x00, 0x80, 0x07, 0x15, 0xe2, 0x00, 0x01, 0x15, 0xe2, 0x80, 0xda, +0x48, 0x00, 0x00, 0x82, 0x47, 0xe6, 0x02, 0x00, 0x04, 0x3f, 0x00, 0x56, 0x04, 0x5f, 0x80, 0x02, +0x50, 0x52, 0x83, 0x20, 0x58, 0x4f, 0x00, 0x00, 0x14, 0x32, 0x80, 0x05, 0x04, 0x22, 0x00, 0x57, +0x58, 0x02, 0x00, 0x00, 0x14, 0x22, 0x80, 0x06, 0x04, 0x10, 0x00, 0x58, 0x59, 0xe0, 0x00, 0x00, +0x14, 0x12, 0x80, 0x07, 0x04, 0x3f, 0x00, 0x62, 0x04, 0x4f, 0x80, 0x08, 0x58, 0x20, 0x00, 0x00, +0x14, 0x32, 0x00, 0x01, 0x04, 0x0f, 0x80, 0x04, 0x04, 0x51, 0x00, 0x63, 0x3e, 0x1f, 0xc4, 0x60, +0x41, 0xe0, 0x04, 0x00, 0x14, 0x5f, 0x00, 0xda, 0x48, 0x00, 0x00, 0x56, 0x40, 0x50, 0x00, 0x13, +0x5c, 0xf2, 0x80, 0x3c, 0x4e, 0xf3, 0x00, 0x26, 0x04, 0x5f, 0x80, 0x02, 0x05, 0xef, 0x80, 0x04, +0x3e, 0x8f, 0xc4, 0x60, 0x46, 0x08, 0x08, 0x08, 0x04, 0x2f, 0x80, 0x06, 0x04, 0x1f, 0x80, 0x07, +0x58, 0x00, 0x00, 0x80, 0x44, 0x30, 0x00, 0x00, 0x40, 0x4f, 0x20, 0x00, 0x50, 0x72, 0x83, 0x50, +0x50, 0x62, 0x83, 0x54, 0x44, 0x80, 0x08, 0x00, 0x14, 0x81, 0x00, 0x00, 0x14, 0x33, 0x80, 0x00, +0x14, 0x33, 0x00, 0x00, 0x14, 0x00, 0x80, 0x01, 0x14, 0x02, 0x00, 0xde, 0x48, 0x00, 0x00, 0x2c, +0x46, 0x16, 0x02, 0x00, 0x04, 0x40, 0x80, 0x56, 0x04, 0x2f, 0x80, 0x06, 0x58, 0x50, 0x80, 0x00, +0x14, 0x41, 0x00, 0x00, 0x05, 0xe2, 0x80, 0x57, 0x04, 0x1f, 0x80, 0x02, 0x58, 0x02, 0x80, 0x00, +0x15, 0xe0, 0x80, 0xd4, 0x04, 0x30, 0x00, 0x58, 0x58, 0x40, 0x00, 0x00, 0x14, 0x30, 0x80, 0xd5, +0x04, 0x52, 0x00, 0x62, 0x04, 0x2f, 0x80, 0x07, 0x59, 0xe0, 0x00, 0x00, 0x14, 0x51, 0x00, 0x01, +0x04, 0x0f, 0x80, 0x04, 0x04, 0x4f, 0x00, 0x63, 0x3e, 0x1f, 0xc4, 0x60, 0x40, 0x30, 0x04, 0x00, +0x14, 0x41, 0x80, 0xde, 0x04, 0x5f, 0x80, 0x03, 0x45, 0xe0, 0x00, 0x02, 0x50, 0x02, 0x80, 0x01, +0x40, 0x30, 0x00, 0x13, 0x14, 0x3f, 0x80, 0x03, 0x4c, 0x3f, 0x7d, 0xa6, 0x49, 0xff, 0xe9, 0x38, +0x04, 0x2f, 0x80, 0x01, 0x4e, 0x23, 0x00, 0x08, 0x46, 0x46, 0x02, 0x00, 0x14, 0x22, 0x00, 0x5f, +0x48, 0x00, 0x00, 0x0e, 0x04, 0x2f, 0x80, 0x01, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x22, 0xc0, 0x08, +0x46, 0x36, 0x02, 0x01, 0x45, 0xe0, 0x00, 0x00, 0x15, 0xe1, 0x80, 0x5f, 0x51, 0xff, 0x80, 0x2c, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, +0x14, 0x0f, 0x80, 0x00, 0x3c, 0x03, 0xd9, 0x74, 0x04, 0x1f, 0x80, 0x00, 0x49, 0xff, 0xf9, 0x1c, +0x04, 0x2f, 0x80, 0x00, 0x46, 0x18, 0x1b, 0xd6, 0x58, 0x10, 0x8c, 0x7f, 0x44, 0x00, 0x00, 0x6c, +0x49, 0xff, 0xe7, 0xe6, 0x04, 0x2f, 0x80, 0x00, 0x46, 0x18, 0xc0, 0x08, 0x58, 0x10, 0x82, 0xd0, +0x44, 0x00, 0x00, 0x44, 0x49, 0xff, 0xe7, 0xdc, 0x46, 0x1f, 0x8b, 0x00, 0x04, 0x2f, 0x80, 0x00, +0x44, 0x00, 0x00, 0x48, 0x58, 0x10, 0x87, 0x27, 0x49, 0xff, 0xe7, 0xd2, 0x04, 0x0f, 0x80, 0x00, +0x4e, 0x03, 0x00, 0x06, 0x3e, 0x3f, 0xb2, 0xea, 0x48, 0x00, 0x00, 0x0a, 0x04, 0x1f, 0x80, 0x00, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x12, 0xc0, 0x1c, 0x3e, 0x3f, 0xb2, 0xeb, 0x00, 0x41, 0x80, 0x00, +0x4e, 0x43, 0x00, 0x16, 0x04, 0x2f, 0x80, 0x00, 0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x08, +0x44, 0x00, 0x06, 0x10, 0x49, 0xff, 0xe7, 0xb4, 0x46, 0x18, 0x3f, 0xf0, 0x04, 0x2f, 0x80, 0x00, +0x58, 0x10, 0x80, 0x03, 0x44, 0x00, 0x00, 0x54, 0x49, 0xff, 0xe7, 0xaa, 0x46, 0x56, 0x02, 0x00, +0x58, 0x52, 0x81, 0x48, 0x14, 0x5f, 0x80, 0x01, 0x04, 0x8f, 0x80, 0x00, 0x44, 0x90, 0x00, 0x00, +0x2f, 0xe7, 0xb4, 0xf4, 0x4f, 0xe3, 0x00, 0x08, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x88, +0x48, 0x00, 0x00, 0x06, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x87, 0x44, 0x00, 0x00, 0xe8, +0x58, 0x24, 0x00, 0x00, 0x49, 0xff, 0xe7, 0x8c, 0x4e, 0x93, 0x00, 0x08, 0x46, 0x10, 0x50, 0x00, +0x58, 0x10, 0x8b, 0xb8, 0x48, 0x00, 0x00, 0x1a, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x92, 0xc0, 0x08, +0x46, 0x10, 0x50, 0x00, 0x58, 0x10, 0x8b, 0xaa, 0x48, 0x00, 0x00, 0x10, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x92, 0xc0, 0x08, 0x46, 0x10, 0x50, 0x00, 0x58, 0x10, 0x8b, 0x99, 0x48, 0x00, 0x00, 0x06, +0x46, 0x10, 0x50, 0x00, 0x58, 0x10, 0x8b, 0x8a, 0x44, 0x00, 0x00, 0x70, 0x58, 0x24, 0x00, 0x00, +0x49, 0xff, 0xe7, 0x66, 0x46, 0x18, 0x00, 0x00, 0x44, 0x00, 0x00, 0xa0, 0x58, 0x24, 0x00, 0x00, +0x49, 0xff, 0xe7, 0x5e, 0x46, 0x18, 0x20, 0x24, 0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, +0x58, 0x24, 0x00, 0x00, 0x49, 0xff, 0xe7, 0x54, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x9c, 0x88, +0x58, 0x14, 0x00, 0x00, 0x44, 0x00, 0x04, 0x1c, 0x49, 0xff, 0xe7, 0x68, 0x40, 0x10, 0x70, 0x09, +0x4e, 0x13, 0xff, 0xf4, 0x46, 0x10, 0x20, 0x24, 0x44, 0x00, 0x00, 0xc8, 0x58, 0x10, 0x80, 0xc0, +0x58, 0x24, 0x00, 0x00, 0x49, 0xff, 0xe7, 0x3c, 0x46, 0x66, 0x02, 0x00, 0x58, 0x03, 0x00, 0x00, +0x58, 0x70, 0x00, 0x00, 0x44, 0x50, 0x00, 0x27, 0x44, 0x40, 0x00, 0x02, 0x14, 0x53, 0x00, 0x00, +0x14, 0x50, 0x00, 0x01, 0x14, 0x43, 0x80, 0x83, 0x4e, 0x83, 0x00, 0x20, 0x47, 0xe6, 0x02, 0x00, +0x46, 0x70, 0x40, 0x00, 0x46, 0x60, 0x02, 0x74, 0x46, 0x0c, 0x00, 0x00, 0x46, 0x3f, 0x00, 0x00, +0x46, 0x14, 0x08, 0x00, 0x59, 0xef, 0x02, 0x00, 0x51, 0xcf, 0x0b, 0x00, 0x58, 0x63, 0x00, 0x27, +0x50, 0xae, 0x00, 0x04, 0x58, 0x00, 0x04, 0x00, 0x50, 0x55, 0x35, 0x10, 0x50, 0x4e, 0x7d, 0x08, +0x50, 0x25, 0x00, 0x20, 0x48, 0x00, 0x00, 0x22, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x82, 0xc0, 0x2c, +0x47, 0xe6, 0x02, 0x00, 0x46, 0x71, 0x40, 0x00, 0x46, 0x60, 0x02, 0x74, 0x46, 0x0c, 0x00, 0x00, +0x46, 0x3f, 0x00, 0x00, 0x46, 0x14, 0x08, 0x00, 0x59, 0xef, 0x02, 0x00, 0x51, 0xcf, 0x1b, 0x00, +0x58, 0x63, 0x00, 0x27, 0x50, 0xae, 0x00, 0x04, 0x58, 0x00, 0x04, 0x00, 0x50, 0x55, 0x35, 0x10, +0x50, 0x4e, 0x7d, 0x08, 0x50, 0x25, 0x00, 0x20, 0x14, 0x7f, 0x00, 0x00, 0x44, 0x70, 0x05, 0x95, +0x14, 0x6e, 0x00, 0x00, 0x14, 0x05, 0x00, 0x00, 0x14, 0x72, 0x80, 0x00, 0x14, 0x32, 0x00, 0x00, +0x14, 0x11, 0x00, 0x00, 0x46, 0x56, 0x02, 0x04, 0x46, 0x06, 0x02, 0x00, 0x58, 0x20, 0x00, 0x00, +0x58, 0x12, 0x80, 0x00, 0x46, 0x30, 0x20, 0x00, 0x44, 0x70, 0x00, 0x03, 0x44, 0x60, 0x00, 0x10, +0x44, 0x41, 0x00, 0x68, 0x14, 0x72, 0x80, 0x50, 0x14, 0x60, 0x00, 0xe0, 0x14, 0x41, 0x00, 0xc0, +0x14, 0x30, 0x80, 0x40, 0x4e, 0x83, 0x00, 0x06, 0x3e, 0x0f, 0xb2, 0xea, 0x48, 0x00, 0x00, 0x08, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x82, 0xc0, 0x0c, 0x3e, 0x0f, 0xb2, 0xeb, 0x00, 0x10, 0x00, 0x00, +0x4e, 0x13, 0x00, 0x06, 0x46, 0x33, 0x00, 0x00, 0x14, 0x31, 0x00, 0x51, 0x4e, 0x93, 0x00, 0x0a, +0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x02, 0x08, 0x44, 0x30, 0x13, 0x00, 0x48, 0x00, 0x00, 0x20, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x92, 0xc0, 0x0a, 0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x02, 0x08, +0x44, 0x30, 0x12, 0x00, 0x48, 0x00, 0x00, 0x14, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x92, 0xc0, 0x0a, +0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x02, 0x08, 0x44, 0x30, 0x11, 0x00, 0x48, 0x00, 0x00, 0x08, +0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x02, 0x08, 0x44, 0x30, 0x10, 0x00, 0x58, 0x51, 0x00, 0x00, +0x46, 0x10, 0x07, 0x38, 0x47, 0xe8, 0x07, 0x38, 0x14, 0x30, 0x00, 0x00, 0x14, 0x12, 0x80, 0x50, +0x15, 0xe2, 0x80, 0x50, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x9b, 0xb2, 0x04, 0x0f, 0x80, 0x01, +0x04, 0x40, 0x00, 0x00, 0x40, 0x22, 0x04, 0x08, 0x40, 0x21, 0x74, 0x09, 0x4e, 0x23, 0xff, 0xf4, +0x46, 0x56, 0x02, 0x00, 0x46, 0x10, 0x07, 0x38, 0x47, 0xe4, 0x07, 0x38, 0x14, 0x12, 0x80, 0x50, +0x15, 0xe2, 0x80, 0x50, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x9b, 0x9a, 0x04, 0x0f, 0x80, 0x01, +0x04, 0x40, 0x00, 0x00, 0x40, 0x22, 0x04, 0x08, 0x40, 0x21, 0x74, 0x09, 0x4e, 0x23, 0xff, 0xf4, +0x46, 0x56, 0x02, 0x00, 0x46, 0x10, 0x07, 0x38, 0x47, 0xe2, 0x07, 0x38, 0x14, 0x12, 0x80, 0x50, +0x15, 0xe2, 0x80, 0x50, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x9b, 0x82, 0x04, 0x0f, 0x80, 0x01, +0x04, 0x40, 0x00, 0x00, 0x40, 0x22, 0x04, 0x08, 0x40, 0x21, 0x74, 0x09, 0x4e, 0x23, 0xff, 0xf4, +0x50, 0x24, 0x80, 0x01, 0x47, 0xe6, 0x02, 0x00, 0x46, 0x10, 0x07, 0x38, 0x40, 0x91, 0x00, 0x13, +0x44, 0x50, 0x00, 0x04, 0x14, 0x1f, 0x00, 0x50, 0x4c, 0x92, 0xfe, 0x94, 0x04, 0x3f, 0x80, 0x00, +0x50, 0x51, 0x80, 0x88, 0x50, 0x41, 0x80, 0x8a, 0x4e, 0x33, 0x00, 0x06, 0x3e, 0x3f, 0xb2, 0xea, +0x48, 0x00, 0x00, 0x0a, 0x04, 0x0f, 0x80, 0x00, 0x45, 0xe0, 0x00, 0x01, 0x4c, 0x0f, 0x40, 0x30, +0x3e, 0x3f, 0xb2, 0xeb, 0x00, 0x11, 0x80, 0x00, 0x4e, 0x13, 0x00, 0x2a, 0x46, 0x26, 0x02, 0x00, +0x04, 0x11, 0x00, 0xa4, 0x40, 0x02, 0x88, 0x08, 0x3e, 0x2f, 0xc4, 0x60, 0x40, 0x50, 0x08, 0x00, +0x14, 0x12, 0x80, 0x01, 0x47, 0xe6, 0x02, 0x00, 0x04, 0x3f, 0x00, 0xa5, 0x40, 0x02, 0x08, 0x08, +0x04, 0x5f, 0x80, 0x00, 0x40, 0x40, 0x08, 0x00, 0x14, 0x32, 0x00, 0x01, 0x4e, 0x53, 0x00, 0x26, +0x05, 0xe1, 0x00, 0x89, 0x46, 0x16, 0x02, 0x00, 0x15, 0xe0, 0x80, 0xa2, 0x58, 0x30, 0x80, 0x00, +0x04, 0x41, 0x00, 0x8b, 0x14, 0x41, 0x80, 0xa3, 0x48, 0x00, 0x00, 0x18, 0x46, 0x06, 0x02, 0x00, +0x05, 0xe0, 0x00, 0xa2, 0x40, 0x52, 0x88, 0x08, 0x3e, 0x2f, 0xc4, 0x60, 0x40, 0x12, 0x88, 0x00, +0x15, 0xe0, 0x80, 0x01, 0x58, 0x30, 0x00, 0x00, 0x04, 0x51, 0x80, 0xa3, 0x40, 0x42, 0x08, 0x08, +0x40, 0x02, 0x08, 0x00, 0x14, 0x50, 0x00, 0x01, 0x49, 0xff, 0xe6, 0xfa, 0x04, 0x2f, 0x80, 0x00, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x22, 0xc0, 0x2c, 0x2e, 0x37, 0xb2, 0xea, 0x4e, 0x33, 0x00, 0x1c, +0x2e, 0x17, 0xb2, 0xeb, 0x4e, 0x13, 0x00, 0x18, 0x3c, 0x5d, 0xf1, 0xa2, 0x46, 0x16, 0x02, 0x01, +0x59, 0xe0, 0x80, 0x00, 0x14, 0x50, 0x80, 0xa4, 0x14, 0x5f, 0x00, 0xa2, 0x58, 0x30, 0x80, 0x00, +0x3c, 0x4d, 0xf1, 0xa4, 0x58, 0x00, 0x80, 0x00, 0x14, 0x41, 0x80, 0xa5, 0x14, 0x40, 0x00, 0xa3, +0x48, 0x00, 0x00, 0x0e, 0x3c, 0x2d, 0xf1, 0xa2, 0x47, 0xe6, 0x02, 0x01, 0x14, 0x2f, 0x00, 0xa2, +0x58, 0x0f, 0x00, 0x00, 0x3c, 0x4d, 0xf1, 0xa4, 0x14, 0x40, 0x00, 0xa3, 0x51, 0xff, 0x80, 0x0c, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, +0x58, 0x60, 0x00, 0x00, 0x3c, 0x03, 0xd9, 0x74, 0x58, 0x13, 0x00, 0x00, 0x49, 0xff, 0xf6, 0xc4, +0x46, 0x18, 0x1b, 0x06, 0x58, 0x10, 0x8e, 0x07, 0x44, 0x00, 0x00, 0x6c, 0x58, 0x23, 0x00, 0x00, +0x49, 0xff, 0xe5, 0x8e, 0x46, 0x1f, 0x8b, 0x00, 0x58, 0x10, 0x87, 0x27, 0x44, 0x00, 0x00, 0x48, +0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xe5, 0x84, 0x46, 0x18, 0x00, 0x6d, 0x58, 0x10, 0x85, 0xe4, +0x44, 0x00, 0x00, 0xa0, 0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xe5, 0x7a, 0x46, 0x26, 0x02, 0x00, +0x58, 0x41, 0x00, 0x00, 0x58, 0x01, 0x00, 0x00, 0x44, 0x30, 0x00, 0x27, 0x44, 0x10, 0x00, 0x02, +0x14, 0x31, 0x00, 0x00, 0x14, 0x32, 0x00, 0x01, 0x14, 0x10, 0x00, 0x83, 0x4e, 0x63, 0x00, 0x1c, +0x46, 0x86, 0x02, 0x00, 0x46, 0x90, 0x40, 0x00, 0x46, 0x70, 0x02, 0x74, 0x46, 0x4c, 0x00, 0x00, +0x46, 0x1f, 0x00, 0x00, 0x58, 0x84, 0x02, 0x00, 0x50, 0x54, 0x0b, 0x00, 0x58, 0x73, 0x80, 0x27, +0x50, 0x32, 0x80, 0x04, 0x58, 0x42, 0x04, 0x00, 0x50, 0x21, 0xb5, 0x10, 0x50, 0x02, 0xfd, 0x08, +0x48, 0x00, 0x00, 0x1e, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x26, 0x46, 0x86, 0x02, 0x00, +0x46, 0x91, 0x40, 0x00, 0x46, 0x70, 0x02, 0x74, 0x46, 0x4c, 0x00, 0x00, 0x46, 0x1f, 0x00, 0x00, +0x58, 0x84, 0x02, 0x00, 0x50, 0x54, 0x1b, 0x00, 0x58, 0x73, 0x80, 0x27, 0x50, 0x32, 0x80, 0x04, +0x58, 0x42, 0x04, 0x00, 0x50, 0x21, 0xb5, 0x10, 0x50, 0x02, 0xfd, 0x08, 0x14, 0x94, 0x00, 0x00, +0x44, 0x90, 0x05, 0x95, 0x14, 0x72, 0x80, 0x00, 0x14, 0x41, 0x80, 0x00, 0x14, 0x91, 0x00, 0x00, +0x14, 0x10, 0x00, 0x00, 0x46, 0x36, 0x02, 0x04, 0x46, 0x16, 0x02, 0x00, 0x59, 0xe0, 0x80, 0x00, +0x58, 0xa1, 0x80, 0x00, 0x47, 0xc0, 0x20, 0x00, 0x44, 0x20, 0x00, 0x03, 0x44, 0x40, 0x00, 0x10, +0x44, 0x01, 0x00, 0x68, 0x14, 0x21, 0x80, 0x50, 0x14, 0x40, 0x80, 0xe0, 0x14, 0x0f, 0x00, 0xc0, +0x46, 0x18, 0x20, 0x24, 0x15, 0xc5, 0x00, 0x40, 0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, +0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xe5, 0x04, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x9a, 0x38, +0x44, 0x00, 0x04, 0x1c, 0x58, 0x13, 0x00, 0x00, 0x49, 0xff, 0xe5, 0x18, 0x40, 0x50, 0x70, 0x09, +0x4e, 0x53, 0xff, 0xf4, 0x46, 0x86, 0x02, 0x01, 0x14, 0x8f, 0x80, 0x01, 0x46, 0x10, 0x20, 0x24, +0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xe4, 0xe8, +0x04, 0x7f, 0x80, 0x01, 0x47, 0xc6, 0x02, 0x00, 0x58, 0x73, 0x8d, 0x24, 0x46, 0x86, 0x02, 0x00, +0x14, 0x7f, 0x80, 0x01, 0x58, 0x84, 0x01, 0x24, 0x3e, 0x7f, 0xad, 0xa0, 0x50, 0x93, 0xff, 0xf4, +0x2f, 0xe7, 0xb4, 0xf4, 0x4f, 0xe3, 0x00, 0x06, 0x04, 0x14, 0x80, 0x00, 0x48, 0x00, 0x00, 0x04, +0x04, 0x14, 0x80, 0x01, 0x44, 0x00, 0x00, 0xd4, 0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xe4, 0xc8, +0x04, 0x13, 0xff, 0xff, 0x44, 0x00, 0x00, 0x14, 0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xe4, 0xc0, +0x4e, 0x63, 0x00, 0x08, 0x04, 0x13, 0x80, 0x00, 0x14, 0x1e, 0x03, 0x49, 0x48, 0x00, 0x00, 0x0c, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x08, 0x04, 0x33, 0x80, 0x00, 0x04, 0x2f, 0x80, 0x01, +0x14, 0x31, 0x00, 0x00, 0x46, 0x06, 0x02, 0x00, 0x46, 0x10, 0x50, 0x04, 0x58, 0x50, 0x00, 0x00, +0x58, 0x10, 0x80, 0xf7, 0x45, 0xe0, 0x00, 0x01, 0x14, 0x10, 0x00, 0x41, 0x15, 0xe2, 0x80, 0x40, +0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x99, 0xd4, 0x04, 0x44, 0x00, 0x00, 0x54, 0x32, 0x00, 0x08, +0x4e, 0x33, 0xff, 0xf8, 0x46, 0x56, 0x02, 0x00, 0x59, 0xe2, 0x80, 0x00, 0x46, 0x20, 0x80, 0x04, +0x14, 0x32, 0x80, 0x40, 0x58, 0x21, 0x07, 0xf7, 0x44, 0x30, 0x00, 0x02, 0x14, 0x2f, 0x00, 0x41, +0x14, 0x32, 0x80, 0x40, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x99, 0xba, 0x04, 0x04, 0x00, 0x00, +0x54, 0x10, 0x00, 0x08, 0x4e, 0x13, 0xff, 0xf8, 0x46, 0x46, 0x02, 0x00, 0x14, 0x12, 0x00, 0x40, +0x44, 0x10, 0x00, 0x04, 0x14, 0x12, 0x00, 0x40, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x99, 0xa8, +0x04, 0x54, 0x00, 0x00, 0x54, 0x12, 0x80, 0x08, 0x4e, 0x13, 0xff, 0xf8, 0x47, 0xe6, 0x02, 0x00, +0x50, 0x73, 0x80, 0x10, 0x3e, 0x5f, 0xae, 0x60, 0x14, 0x1f, 0x00, 0x40, 0x50, 0x94, 0x80, 0x10, +0x4c, 0x72, 0xff, 0x88, 0x44, 0x00, 0x00, 0x18, 0x42, 0x23, 0x00, 0x24, 0x3e, 0x4f, 0xc6, 0x24, +0x46, 0x06, 0x02, 0x00, 0x40, 0x11, 0x10, 0x00, 0x58, 0x00, 0x02, 0x64, 0x0c, 0x30, 0x00, 0x01, +0x46, 0x56, 0x02, 0x00, 0x58, 0x52, 0x82, 0x7c, 0x1c, 0x30, 0x80, 0x01, 0x4c, 0x02, 0xff, 0xf8, +0x44, 0x20, 0x00, 0x18, 0x42, 0x13, 0x08, 0x24, 0x51, 0xe2, 0x00, 0x30, 0x40, 0x10, 0xf8, 0x00, +0x50, 0x02, 0xff, 0xc4, 0x0c, 0x50, 0x00, 0x01, 0x46, 0x46, 0x02, 0x00, 0x58, 0x42, 0x02, 0x58, +0x1c, 0x50, 0x80, 0x01, 0x4c, 0x02, 0x7f, 0xf8, 0x49, 0xff, 0xe5, 0x52, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x62, 0xc0, 0x30, 0x46, 0x06, 0x02, 0x01, 0x58, 0x00, 0x02, 0x64, 0x3e, 0x5f, 0xc4, 0x60, +0x46, 0x29, 0xfd, 0xfe, 0x40, 0x40, 0x14, 0x00, 0x58, 0x21, 0x0f, 0x78, 0x41, 0xe2, 0x08, 0x00, +0x04, 0x1f, 0x00, 0x00, 0x46, 0x36, 0x02, 0x01, 0x1c, 0x10, 0x00, 0x01, 0x58, 0x31, 0x82, 0x7c, +0x4c, 0x01, 0xff, 0xee, 0x50, 0x01, 0xff, 0xc4, 0x3e, 0x5f, 0xc4, 0x60, 0x46, 0x29, 0xfd, 0xfe, +0x40, 0x40, 0x14, 0x00, 0x58, 0x21, 0x0f, 0xcc, 0x41, 0xe2, 0x08, 0x00, 0x04, 0x1f, 0x00, 0x00, +0x46, 0x36, 0x02, 0x01, 0x1c, 0x10, 0x00, 0x01, 0x58, 0x31, 0x82, 0x58, 0x4c, 0x01, 0xff, 0xee, +0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x58, 0x60, 0x00, 0x00, 0x3c, 0x03, 0xd9, 0x74, 0x58, 0x13, 0x00, 0x00, +0x49, 0xff, 0xf5, 0x1a, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0xe4, 0x82, 0x46, 0x18, 0x1b, 0xd6, +0x3e, 0x7f, 0x4c, 0xf8, 0x58, 0x10, 0x8c, 0x7f, 0x44, 0x00, 0x00, 0x6c, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x18, 0xc0, 0x08, 0x58, 0x10, 0x82, 0xd0, 0x44, 0x00, 0x00, 0x44, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x1f, 0x8b, 0x00, 0x58, 0x10, 0x87, 0x27, +0x44, 0x00, 0x00, 0x48, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0x50, 0x00, +0x58, 0x10, 0x8b, 0xb8, 0x44, 0x00, 0x00, 0x70, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0x18, 0x00, 0x00, 0x44, 0x00, 0x00, 0xa0, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0x18, 0x20, 0x24, 0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x98, 0xe2, 0x58, 0x13, 0x00, 0x00, +0x44, 0x00, 0x04, 0x1c, 0x49, 0xff, 0xe3, 0xc2, 0x40, 0x20, 0x70, 0x09, 0x4e, 0x23, 0xff, 0xf4, +0x46, 0x10, 0x20, 0x24, 0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, +0x49, 0xff, 0xe3, 0x96, 0x46, 0x96, 0x02, 0x00, 0x58, 0x54, 0x80, 0x00, 0x58, 0x42, 0x80, 0x00, +0x44, 0x80, 0x00, 0x27, 0x44, 0x30, 0x00, 0x02, 0x14, 0x84, 0x80, 0x00, 0x14, 0x82, 0x80, 0x01, +0x14, 0x32, 0x00, 0x83, 0x4e, 0x63, 0x00, 0x20, 0x46, 0xa6, 0x02, 0x00, 0x47, 0xc0, 0x40, 0x00, +0x46, 0x90, 0x02, 0x74, 0x46, 0x7c, 0x00, 0x00, 0x46, 0x34, 0x00, 0x00, 0x46, 0x1f, 0x00, 0x00, +0x58, 0xa5, 0x02, 0x00, 0x50, 0x85, 0x0b, 0x00, 0x58, 0x94, 0x80, 0x27, 0x50, 0x54, 0x00, 0x04, +0x58, 0x73, 0x84, 0x00, 0x50, 0x42, 0xb5, 0x10, 0x50, 0x22, 0x80, 0x20, 0x50, 0x04, 0x7d, 0x08, +0x48, 0x00, 0x00, 0x22, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x2c, 0x46, 0xa6, 0x02, 0x00, +0x47, 0xc1, 0x40, 0x00, 0x46, 0x90, 0x02, 0x74, 0x46, 0x7c, 0x00, 0x00, 0x46, 0x34, 0x00, 0x00, +0x46, 0x1f, 0x00, 0x00, 0x58, 0xa5, 0x02, 0x00, 0x50, 0x85, 0x1b, 0x00, 0x58, 0x94, 0x80, 0x27, +0x50, 0x54, 0x00, 0x04, 0x58, 0x73, 0x84, 0x00, 0x50, 0x42, 0xb5, 0x10, 0x50, 0x22, 0x80, 0x20, +0x50, 0x04, 0x7d, 0x08, 0x45, 0xe0, 0x05, 0x97, 0x15, 0xc5, 0x00, 0x00, 0x14, 0x94, 0x00, 0x00, +0x14, 0x72, 0x80, 0x00, 0x15, 0xe2, 0x00, 0x00, 0x14, 0x31, 0x00, 0x00, 0x14, 0x10, 0x00, 0x00, +0x46, 0x76, 0x02, 0x04, 0x44, 0x50, 0x00, 0x03, 0x46, 0x06, 0x02, 0x00, 0x58, 0x40, 0x00, 0x00, +0x58, 0x23, 0x80, 0x00, 0x46, 0x30, 0x20, 0x00, 0x59, 0xe0, 0x00, 0x00, 0x46, 0x10, 0x90, 0x04, +0x14, 0x53, 0x80, 0x50, 0x58, 0x10, 0x8f, 0xf9, 0x44, 0x80, 0x00, 0x10, 0x44, 0x51, 0x00, 0x68, +0x14, 0x80, 0x00, 0xe0, 0x14, 0x52, 0x00, 0xc0, 0x14, 0x31, 0x00, 0x40, 0x14, 0x1f, 0x00, 0x41, +0x2e, 0x77, 0xb4, 0xf4, 0x4e, 0x73, 0x00, 0x08, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x88, +0x48, 0x00, 0x00, 0x06, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x87, 0x44, 0x00, 0x00, 0xe8, +0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xe3, 0x04, 0x4e, 0x63, 0x00, 0x0a, 0x46, 0x06, 0x02, 0x00, +0x46, 0x14, 0x00, 0x00, 0x58, 0x00, 0x0d, 0x24, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x62, 0xc0, 0x0a, 0x46, 0x06, 0x02, 0x01, 0x46, 0x14, 0x00, 0x00, 0x58, 0x00, 0x0d, 0x24, +0x14, 0x10, 0x00, 0x00, 0x46, 0x46, 0x02, 0x00, 0x46, 0x27, 0x10, 0x20, 0x58, 0x32, 0x00, 0x00, +0x44, 0x10, 0x00, 0x20, 0x14, 0x22, 0x00, 0x47, 0x58, 0x71, 0x80, 0x00, 0x14, 0x11, 0x80, 0x40, +0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x98, 0x14, 0x04, 0x03, 0x80, 0x4c, 0x44, 0x51, 0x00, 0x00, +0x40, 0x30, 0x14, 0x02, 0x4e, 0x33, 0xff, 0xf6, 0x46, 0x46, 0x02, 0x00, 0x59, 0xe2, 0x00, 0x00, +0x46, 0x17, 0x10, 0x00, 0x58, 0x10, 0x80, 0x02, 0x14, 0x32, 0x00, 0x40, 0x14, 0x1f, 0x00, 0x47, +0x2e, 0x87, 0xb4, 0xf4, 0x4e, 0x83, 0x00, 0x08, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x08, +0x48, 0x00, 0x00, 0x06, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x07, 0x44, 0x00, 0x00, 0xe8, +0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xe2, 0xb4, 0x4e, 0x63, 0x00, 0x0a, 0x46, 0x06, 0x02, 0x00, +0x46, 0x14, 0x28, 0x00, 0x58, 0x00, 0x0d, 0x24, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x62, 0xc0, 0x0a, 0x46, 0x06, 0x02, 0x01, 0x46, 0x14, 0x28, 0x00, 0x58, 0x00, 0x0d, 0x24, +0x14, 0x10, 0x00, 0x00, 0x46, 0x26, 0x02, 0x00, 0x44, 0x00, 0x00, 0x20, 0x58, 0x71, 0x00, 0x00, +0x14, 0x01, 0x00, 0x40, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x97, 0xca, 0x04, 0x53, 0x80, 0x4c, +0x44, 0x41, 0x00, 0x00, 0x40, 0x12, 0x90, 0x02, 0x4e, 0x13, 0xff, 0xf6, 0x47, 0xe6, 0x02, 0x00, +0x14, 0x1f, 0x00, 0x40, 0x2e, 0x87, 0xb4, 0xf4, 0x4e, 0x83, 0x00, 0x08, 0x46, 0x10, 0x06, 0x10, +0x58, 0x10, 0x80, 0x28, 0x48, 0x00, 0x00, 0x06, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x27, +0x44, 0x00, 0x00, 0xe8, 0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xe2, 0x72, 0x4e, 0x63, 0x00, 0x0a, +0x46, 0x06, 0x02, 0x00, 0x46, 0x14, 0x30, 0x00, 0x58, 0x00, 0x0d, 0x24, 0x48, 0x00, 0x00, 0x0c, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x0a, 0x46, 0x06, 0x02, 0x01, 0x46, 0x14, 0x30, 0x00, +0x58, 0x00, 0x0d, 0x24, 0x14, 0x10, 0x00, 0x00, 0x46, 0x36, 0x02, 0x00, 0x44, 0x20, 0x00, 0x20, +0x58, 0x71, 0x80, 0x00, 0x14, 0x21, 0x80, 0x40, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x97, 0x88, +0x04, 0x03, 0x80, 0x4c, 0x44, 0x51, 0x00, 0x00, 0x40, 0x10, 0x14, 0x02, 0x4e, 0x13, 0xff, 0xf6, +0x46, 0x76, 0x02, 0x00, 0x14, 0x13, 0x80, 0x40, 0x2e, 0x47, 0xb4, 0xf4, 0x4e, 0x43, 0x00, 0x08, +0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x68, 0x48, 0x00, 0x00, 0x06, 0x46, 0x10, 0x06, 0x10, +0x58, 0x10, 0x80, 0x67, 0x44, 0x00, 0x00, 0xe8, 0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xe2, 0x30, +0x4e, 0x63, 0x00, 0x0a, 0x46, 0x06, 0x02, 0x00, 0x46, 0x14, 0x38, 0x00, 0x58, 0x00, 0x0d, 0x24, +0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x0a, 0x46, 0x06, 0x02, 0x01, +0x46, 0x14, 0x38, 0x00, 0x58, 0x00, 0x0d, 0x24, 0x14, 0x10, 0x00, 0x00, 0x46, 0x36, 0x02, 0x00, +0x44, 0x10, 0x00, 0x20, 0x58, 0x71, 0x80, 0x00, 0x14, 0x11, 0x80, 0x40, 0x44, 0x00, 0x00, 0x01, +0x49, 0xff, 0x97, 0x46, 0x04, 0x03, 0x80, 0x4c, 0x44, 0x21, 0x00, 0x00, 0x40, 0x10, 0x08, 0x02, +0x4e, 0x13, 0xff, 0xf6, 0x46, 0x86, 0x02, 0x00, 0x14, 0x14, 0x00, 0x40, 0x2e, 0x57, 0xb4, 0xf4, +0x4e, 0x53, 0x00, 0x08, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0xa8, 0x48, 0x00, 0x00, 0x06, +0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0xa7, 0x44, 0x00, 0x00, 0xe8, 0x58, 0x23, 0x00, 0x00, +0x49, 0xff, 0xe1, 0xee, 0x4e, 0x63, 0x00, 0x0a, 0x46, 0x06, 0x02, 0x00, 0x46, 0x14, 0x08, 0x00, +0x58, 0x00, 0x0d, 0x24, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x0a, +0x46, 0x06, 0x02, 0x01, 0x46, 0x14, 0x08, 0x00, 0x58, 0x00, 0x0d, 0x24, 0x14, 0x10, 0x00, 0x00, +0x47, 0xe6, 0x02, 0x00, 0x44, 0x30, 0x00, 0x20, 0x58, 0x7f, 0x00, 0x00, 0x14, 0x3f, 0x00, 0x40, +0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x97, 0x04, 0x04, 0x13, 0x80, 0x4c, 0x44, 0x01, 0x00, 0x00, +0x40, 0x10, 0x80, 0x02, 0x4e, 0x13, 0xff, 0xf6, 0x46, 0x46, 0x02, 0x00, 0x14, 0x12, 0x00, 0x40, +0x2e, 0x27, 0xb4, 0xf4, 0x4e, 0x23, 0x00, 0x08, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0xe8, +0x48, 0x00, 0x00, 0x06, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0xe7, 0x44, 0x00, 0x00, 0xe8, +0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xe1, 0xac, 0x4e, 0x63, 0x00, 0x0a, 0x46, 0x06, 0x02, 0x00, +0x46, 0x14, 0x10, 0x00, 0x58, 0x00, 0x0d, 0x24, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x62, 0xc0, 0x0a, 0x46, 0x06, 0x02, 0x01, 0x46, 0x14, 0x10, 0x00, 0x58, 0x00, 0x0d, 0x24, +0x14, 0x10, 0x00, 0x00, 0x46, 0x76, 0x02, 0x00, 0x45, 0xe0, 0x00, 0x20, 0x15, 0xe3, 0x80, 0x40, +0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x96, 0xc4, 0x04, 0x33, 0x80, 0x4c, 0x44, 0x01, 0x00, 0x00, +0x40, 0x11, 0x80, 0x02, 0x4e, 0x13, 0xff, 0xf6, 0x46, 0x56, 0x02, 0x00, 0x14, 0x12, 0x80, 0x40, +0x58, 0x02, 0x80, 0x00, 0x50, 0x33, 0x00, 0xe4, 0x04, 0x40, 0x00, 0xa1, 0x41, 0xe1, 0x88, 0x08, +0x3e, 0x2f, 0xc4, 0x60, 0x40, 0x5f, 0x08, 0x00, 0x14, 0x42, 0x80, 0x01, 0x49, 0xff, 0xe2, 0x90, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x08, 0x3c, 0x1d, 0xf1, 0xfe, 0x46, 0x46, 0x02, 0x01, +0x14, 0x12, 0x00, 0xa1, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x3c, 0x13, 0xd9, 0x74, 0x58, 0x60, 0x00, 0x00, +0x14, 0x1f, 0x80, 0x01, 0x44, 0x80, 0x00, 0x00, 0x3e, 0x7f, 0x4c, 0xf8, 0x3f, 0xcf, 0x4d, 0x34, +0x04, 0x0f, 0x80, 0x01, 0x58, 0x13, 0x00, 0x00, 0x49, 0xff, 0xf2, 0x76, 0x46, 0x18, 0xf0, 0x92, +0x58, 0x10, 0x83, 0x00, 0x44, 0x00, 0x00, 0xc0, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0x18, 0x10, 0xc6, 0x58, 0x10, 0x80, 0xfe, 0x44, 0x00, 0x00, 0x6c, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x4e, 0x83, 0x00, 0x08, 0x44, 0x00, 0x00, 0x70, 0x44, 0x10, 0x00, 0x80, +0x48, 0x00, 0x00, 0x1a, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x82, 0xc0, 0x08, 0x44, 0x00, 0x00, 0x70, +0x44, 0x10, 0x00, 0x90, 0x48, 0x00, 0x00, 0x10, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x82, 0xc0, 0x08, +0x44, 0x00, 0x00, 0x70, 0x44, 0x10, 0x00, 0xa0, 0x48, 0x00, 0x00, 0x06, 0x44, 0x00, 0x00, 0x70, +0x44, 0x10, 0x00, 0xb0, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0xcc, +0x44, 0x10, 0x80, 0x00, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0x07, +0x49, 0xff, 0x96, 0x3e, 0x44, 0x90, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x96, 0x38, +0x44, 0x00, 0x04, 0x04, 0x58, 0x13, 0x00, 0x00, 0x4b, 0xe0, 0x70, 0x01, 0x40, 0x40, 0x38, 0x08, +0x40, 0x42, 0x74, 0x09, 0x50, 0x94, 0x80, 0x01, 0x4e, 0x42, 0x00, 0x0e, 0x44, 0x50, 0x03, 0xe9, +0x4c, 0x92, 0xff, 0xec, 0x3e, 0x0f, 0xa3, 0x98, 0x3e, 0x1f, 0xae, 0x54, 0x44, 0x20, 0x0d, 0x92, +0x49, 0xff, 0x85, 0x0c, 0x44, 0x00, 0x00, 0xcc, 0x44, 0x10, 0x00, 0x00, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x18, 0xf0, 0x92, 0x44, 0x00, 0x00, 0xc0, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0x6c, 0x44, 0x10, 0x00, 0x00, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x10, 0x00, 0x00, 0x44, 0x00, 0x00, 0x70, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x50, 0x84, 0x00, 0x01, 0x44, 0x50, 0x00, 0x04, 0x4c, 0x82, 0xff, 0x72, +0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x04, 0x6c, 0x49, 0xff, 0xe0, 0xd8, 0x50, 0x13, 0x00, 0xe0, +0x40, 0x50, 0x88, 0x08, 0x3e, 0x2f, 0xc4, 0x60, 0x40, 0x42, 0x88, 0x00, 0x14, 0x02, 0x00, 0x01, +0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x04, 0x70, 0x49, 0xff, 0xe0, 0xc8, 0x50, 0x33, 0x00, 0xe2, +0x40, 0x61, 0x88, 0x08, 0x3e, 0x2f, 0xc4, 0x60, 0x40, 0x63, 0x08, 0x00, 0x14, 0x03, 0x00, 0x01, +0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x58, 0x60, 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x44, 0x00, 0x00, 0x0f, +0x49, 0xff, 0xf1, 0xba, 0x46, 0x18, 0x80, 0x08, 0x3e, 0x7f, 0x4c, 0xf8, 0x58, 0x23, 0x00, 0x00, +0x58, 0x10, 0x82, 0xd0, 0x44, 0x00, 0x00, 0x44, 0x4b, 0xe0, 0x1c, 0x01, 0x58, 0x13, 0x00, 0x00, +0x44, 0x00, 0x00, 0x48, 0x49, 0xff, 0xe0, 0x9a, 0x58, 0xa0, 0x00, 0x00, 0x58, 0x13, 0x00, 0x00, +0x44, 0x00, 0x00, 0x48, 0x49, 0xff, 0xe0, 0x92, 0x46, 0x1f, 0xf1, 0xff, 0x58, 0x10, 0x8f, 0xff, +0x40, 0x20, 0x04, 0x02, 0x46, 0x00, 0x0a, 0x00, 0x40, 0x11, 0x00, 0x04, 0x44, 0x00, 0x00, 0x48, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x0a, +0x44, 0x00, 0x06, 0x10, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0x3f, 0xf0, +0x58, 0x10, 0x80, 0x03, 0x44, 0x00, 0x00, 0x54, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x44, 0x00, 0x06, 0x1c, 0x44, 0x10, 0x00, 0x04, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0x18, 0x20, 0x04, 0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x95, 0x72, 0x44, 0x00, 0x04, 0x1c, +0x58, 0x13, 0x00, 0x00, 0x49, 0xff, 0xe0, 0x52, 0x40, 0x30, 0x70, 0x09, 0x4e, 0x33, 0xff, 0xf4, +0x46, 0x10, 0x20, 0x04, 0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, +0x49, 0xff, 0xe0, 0x26, 0x40, 0x83, 0x14, 0x08, 0x3e, 0x5f, 0xc4, 0x9c, 0x40, 0x84, 0x14, 0x00, +0x58, 0x94, 0x00, 0x00, 0x44, 0x70, 0x04, 0x28, 0x3f, 0xcf, 0x4d, 0x34, 0x58, 0x03, 0x80, 0x00, +0x58, 0x13, 0x00, 0x00, 0x4b, 0xe0, 0x70, 0x01, 0x1c, 0x04, 0x80, 0x01, 0x50, 0x73, 0x80, 0x04, +0x44, 0x50, 0x04, 0x48, 0x4c, 0x72, 0xff, 0xf4, 0x3f, 0xcf, 0xc4, 0xdc, 0x40, 0x93, 0x14, 0x08, +0x40, 0x94, 0xf0, 0x00, 0x3f, 0xcf, 0x4d, 0x34, 0x58, 0x03, 0x80, 0x00, 0x58, 0x13, 0x00, 0x00, +0x4b, 0xe0, 0x70, 0x01, 0x50, 0x73, 0x80, 0x04, 0x44, 0x50, 0x04, 0x68, 0x1c, 0x04, 0x80, 0x01, +0x4c, 0x72, 0xff, 0xf4, 0x46, 0x10, 0x24, 0x44, 0x3e, 0x7f, 0x4c, 0xf8, 0x58, 0x10, 0x84, 0x0b, +0x44, 0x00, 0x06, 0x10, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0x3f, 0xf0, +0x58, 0x10, 0x80, 0x03, 0x44, 0x00, 0x00, 0x54, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x44, 0x00, 0x06, 0x1c, 0x44, 0x10, 0x00, 0x00, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0x18, 0x20, 0x04, 0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x95, 0x02, 0x58, 0x13, 0x00, 0x00, +0x44, 0x00, 0x04, 0x1c, 0x49, 0xff, 0xdf, 0xe2, 0x40, 0x30, 0x70, 0x09, 0x4e, 0x33, 0xff, 0xf4, +0x46, 0x10, 0x20, 0x04, 0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, +0x49, 0xff, 0xdf, 0xb6, 0x40, 0x43, 0x14, 0x08, 0x3e, 0x5f, 0xc5, 0x1c, 0x40, 0x92, 0x14, 0x00, +0x44, 0x70, 0x06, 0xcc, 0x3f, 0xcf, 0x4d, 0x34, 0x58, 0x03, 0x80, 0x00, 0x58, 0x13, 0x00, 0x00, +0x4b, 0xe0, 0x70, 0x01, 0x1c, 0x04, 0x80, 0x01, 0x50, 0x73, 0x80, 0x04, 0x44, 0x50, 0x06, 0xec, +0x4c, 0x72, 0xff, 0xf4, 0x46, 0x10, 0x24, 0x44, 0x3e, 0x9f, 0x4c, 0xf8, 0x58, 0x10, 0x84, 0x0b, +0x44, 0x00, 0x06, 0x10, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x24, 0x01, 0x46, 0x10, 0x3f, 0xf0, +0x58, 0x10, 0x80, 0x03, 0x44, 0x00, 0x00, 0x54, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x24, 0x01, +0x44, 0x00, 0x06, 0x1c, 0x44, 0x10, 0x00, 0x05, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x24, 0x01, +0x46, 0x18, 0x20, 0x04, 0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x24, 0x01, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0x94, 0xaa, 0x44, 0x00, 0x04, 0x1c, +0x58, 0x13, 0x00, 0x00, 0x49, 0xff, 0xdf, 0x8a, 0x41, 0xc0, 0x70, 0x09, 0x4f, 0xc3, 0xff, 0xf4, +0x46, 0x10, 0x20, 0x04, 0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, +0x40, 0x73, 0x14, 0x08, 0x49, 0xff, 0xdf, 0x5c, 0x3e, 0x3f, 0xc5, 0x5c, 0x40, 0x93, 0x8c, 0x00, +0x3f, 0xcf, 0x4d, 0x34, 0x44, 0x70, 0x06, 0xcc, 0x58, 0x03, 0x80, 0x00, 0x58, 0x13, 0x00, 0x00, +0x4b, 0xe0, 0x70, 0x01, 0x50, 0x73, 0x80, 0x04, 0x44, 0x50, 0x06, 0xec, 0x1c, 0x04, 0x80, 0x01, +0x4c, 0x72, 0xff, 0xf4, 0x4e, 0x63, 0x00, 0x06, 0x3e, 0x0f, 0xb2, 0xea, 0x48, 0x00, 0x00, 0x08, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x56, 0x3e, 0x0f, 0xb2, 0xeb, 0x00, 0x40, 0x00, 0x00, +0x4e, 0x43, 0x00, 0x50, 0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x0a, 0x44, 0x00, 0x06, 0x10, +0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xdf, 0x2c, 0x46, 0x18, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, +0x44, 0x00, 0x00, 0x54, 0x58, 0x23, 0x00, 0x00, 0x49, 0xff, 0xdf, 0x22, 0x44, 0x70, 0x00, 0x00, +0x58, 0x23, 0x80, 0x00, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x49, 0xff, 0xef, 0x94, +0x50, 0x73, 0x80, 0x01, 0x44, 0x50, 0x00, 0x10, 0x4c, 0x72, 0xff, 0xf4, 0x44, 0x70, 0x00, 0x00, +0x58, 0x23, 0x80, 0x00, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x49, 0xff, 0xef, 0x84, +0x50, 0x73, 0x80, 0x01, 0x44, 0x50, 0x00, 0x10, 0x4c, 0x72, 0xff, 0xf4, 0x44, 0x70, 0x04, 0x28, +0x58, 0x03, 0x80, 0x00, 0x58, 0x13, 0x00, 0x00, 0x49, 0xff, 0xdf, 0x18, 0x14, 0x04, 0x00, 0x00, +0x58, 0x13, 0x00, 0x00, 0x50, 0x03, 0x80, 0x20, 0x49, 0xff, 0xdf, 0x10, 0x50, 0x73, 0x80, 0x04, +0x44, 0x50, 0x04, 0x48, 0x14, 0x04, 0x00, 0x10, 0x50, 0x84, 0x00, 0x04, 0x4c, 0x72, 0xff, 0xea, +0x58, 0x15, 0x00, 0x00, 0x44, 0x00, 0x00, 0x48, 0x58, 0x23, 0x00, 0x00, 0x3e, 0x7f, 0x4c, 0xf8, +0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0x44, 0x44, 0x10, 0x82, 0xd0, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x4e, 0x63, 0x00, 0x12, 0x2e, 0x37, 0xb2, 0xea, 0x4e, 0x32, 0x00, 0x04, +0x48, 0x00, 0x00, 0x14, 0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x08, 0x58, 0x23, 0x00, 0x00, +0x44, 0x00, 0x06, 0x10, 0x48, 0x00, 0x00, 0x22, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x2a, +0x2e, 0x47, 0xb2, 0xeb, 0x4e, 0x42, 0x00, 0x12, 0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x00, +0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x06, 0x10, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0x3f, 0xf0, +0x58, 0x10, 0x80, 0x03, 0x48, 0x00, 0x00, 0x10, 0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x08, +0x44, 0x00, 0x06, 0x10, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x18, 0x3f, 0xf0, +0x58, 0x10, 0x80, 0x03, 0x44, 0x00, 0x00, 0x54, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x00, 0xa0, 0x44, 0x16, 0xf5, 0xfe, 0x49, 0xff, 0xde, 0x90, +0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x00, 0x70, 0x44, 0x10, 0x00, 0x00, 0x49, 0xff, 0xde, 0x88, +0x46, 0x10, 0x20, 0x04, 0x58, 0x10, 0x80, 0xc0, 0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x00, 0xc8, +0x49, 0xff, 0xde, 0x7e, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x3c, 0x1d, 0xed, 0x4d, 0x44, 0xa0, 0x00, 0x01, +0x40, 0x95, 0x00, 0x0c, 0x58, 0x60, 0x00, 0x00, 0x40, 0x04, 0x84, 0x02, 0x4c, 0x04, 0x80, 0x60, +0x3d, 0xed, 0xed, 0x47, 0x56, 0x73, 0x00, 0x08, 0x44, 0x40, 0x00, 0x03, 0x44, 0x50, 0x00, 0x02, +0x41, 0xcf, 0x28, 0x00, 0x40, 0x32, 0x9c, 0x1a, 0x40, 0x32, 0x1c, 0x1b, 0x3d, 0xcf, 0xed, 0x47, +0x14, 0x3f, 0x80, 0x01, 0x47, 0xc0, 0x01, 0x12, 0x48, 0x00, 0x00, 0x46, 0x58, 0x13, 0x80, 0x00, +0x58, 0x03, 0x00, 0x00, 0x49, 0xff, 0xf0, 0x1e, 0x58, 0x80, 0x00, 0x00, 0x50, 0x13, 0x80, 0x01, +0x44, 0x50, 0x00, 0x02, 0x54, 0x70, 0x80, 0xff, 0x4c, 0x82, 0x80, 0x44, 0x04, 0x2f, 0x80, 0x01, +0x40, 0xf3, 0x88, 0x06, 0x4e, 0xf3, 0xff, 0xec, 0x4e, 0x83, 0x00, 0x26, 0x3c, 0x1d, 0xed, 0x4b, +0x3e, 0x0f, 0xa4, 0x18, 0x49, 0xff, 0x82, 0x5a, 0x3e, 0x4f, 0xb5, 0x20, 0x38, 0x02, 0x18, 0x00, +0x50, 0x50, 0x00, 0x01, 0x54, 0x32, 0x80, 0xff, 0x38, 0x32, 0x18, 0x08, 0x5c, 0xf1, 0x80, 0x03, +0x4e, 0xf3, 0x00, 0x20, 0x3c, 0x2d, 0xed, 0x4d, 0x58, 0x13, 0x00, 0x00, 0x40, 0x94, 0x88, 0x04, +0x3c, 0x9f, 0xed, 0x4d, 0x58, 0x23, 0x80, 0x00, 0x3e, 0x0f, 0xa4, 0x48, 0x49, 0xff, 0x82, 0x3e, +0x48, 0x00, 0x00, 0x10, 0x50, 0x35, 0x00, 0x01, 0x54, 0xa1, 0x80, 0xff, 0x44, 0x50, 0x00, 0x06, +0x4c, 0xa2, 0x80, 0x08, 0x44, 0x70, 0x00, 0x00, 0x48, 0xff, 0xff, 0xba, 0x44, 0x80, 0x00, 0x00, +0x58, 0x04, 0x00, 0x00, 0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3c, 0x2d, 0xed, 0x4b, 0x44, 0x50, 0x00, 0x00, 0x51, 0xe1, 0x00, 0x01, 0x3e, 0x4f, 0xb5, 0x20, +0x3d, 0xef, 0xed, 0x4b, 0x38, 0x52, 0x18, 0x08, 0x3e, 0x0f, 0xa4, 0x68, 0x49, 0xff, 0x82, 0x16, +0x44, 0x00, 0x00, 0x00, 0x49, 0xff, 0xfd, 0x54, 0x44, 0x00, 0x00, 0x01, 0x49, 0xff, 0xfd, 0x50, +0x48, 0xff, 0xff, 0xd2, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x46, 0x30, 0x02, 0x4b, +0x55, 0xc0, 0x00, 0xff, 0x46, 0x20, 0x04, 0xc4, 0x58, 0x31, 0x8a, 0x58, 0x58, 0x21, 0x0b, 0x40, +0x5c, 0x5e, 0x00, 0x0f, 0x58, 0x80, 0x80, 0x00, 0x40, 0x01, 0x94, 0x1b, 0x40, 0x01, 0x14, 0x1a, +0x58, 0x1e, 0x00, 0x00, 0x58, 0x24, 0x00, 0x00, 0x58, 0x62, 0x00, 0x00, 0x49, 0xff, 0xbd, 0xea, +0x58, 0xa0, 0x00, 0x00, 0x44, 0x50, 0x00, 0x04, 0x4c, 0x62, 0xc0, 0x04, 0x48, 0x00, 0x00, 0x06, +0x44, 0x50, 0x00, 0x05, 0x4c, 0x62, 0xc0, 0x06, 0x58, 0x73, 0x00, 0x00, 0x48, 0x00, 0x00, 0x06, +0x44, 0x70, 0x00, 0x00, 0x40, 0x73, 0xa0, 0x06, 0x49, 0xff, 0xe8, 0xaa, 0x44, 0x90, 0x00, 0x00, +0x3e, 0x4f, 0xb5, 0x08, 0x3e, 0x5f, 0x75, 0xd4, 0x48, 0x00, 0x00, 0x0e, 0x14, 0x4f, 0x80, 0x01, +0x14, 0x5f, 0x80, 0x00, 0x50, 0x94, 0x80, 0x01, 0x4b, 0xe0, 0x14, 0x01, 0x04, 0x5f, 0x80, 0x00, +0x04, 0x4f, 0x80, 0x01, 0x05, 0xe2, 0x00, 0x00, 0x58, 0x04, 0x80, 0x00, 0x58, 0x13, 0x80, 0x00, +0x58, 0x25, 0x00, 0x00, 0x58, 0x34, 0x00, 0x00, 0x40, 0xf4, 0xf8, 0x06, 0x4e, 0xf3, 0xff, 0xe8, +0x58, 0x05, 0x00, 0x00, 0x49, 0xff, 0xe3, 0x3e, 0x49, 0xff, 0xe8, 0x16, 0x3d, 0xcb, 0xda, 0x72, +0x3c, 0xab, 0xda, 0x73, 0x3c, 0x7f, 0xed, 0x3a, 0x3e, 0x87, 0xb4, 0xec, 0x3e, 0x67, 0xb4, 0xed, +0x44, 0x00, 0x00, 0x08, 0x49, 0xff, 0xff, 0x06, 0x3c, 0x0f, 0xed, 0x4c, 0x44, 0x00, 0x00, 0x01, +0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, +0x44, 0x60, 0x00, 0x00, 0x58, 0x80, 0x00, 0x00, 0x50, 0x63, 0x00, 0x01, 0x58, 0x03, 0x00, 0x00, +0x58, 0x14, 0x00, 0x00, 0x49, 0xff, 0xee, 0x90, 0x44, 0x50, 0x00, 0x0e, 0x4c, 0x62, 0xff, 0xf6, +0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x58, 0x60, 0x00, 0x00, 0x49, 0xff, 0xcd, 0x5a, 0x46, 0x10, 0x13, 0x12, 0x58, 0x50, 0x8d, 0x00, +0x4c, 0x02, 0xc0, 0x06, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x18, 0x46, 0x20, 0x17, 0xd7, +0x58, 0x51, 0x08, 0x40, 0x4c, 0x02, 0xc0, 0x06, 0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x0e, +0x46, 0x30, 0x26, 0x25, 0x58, 0x51, 0x8a, 0x00, 0x4c, 0x02, 0x80, 0x06, 0x44, 0x80, 0x00, 0x00, +0x48, 0x00, 0x00, 0x08, 0x44, 0x00, 0x00, 0x02, 0x3e, 0x4f, 0xa4, 0x94, 0x38, 0x82, 0x03, 0x02, +0x50, 0x54, 0x00, 0x01, 0x40, 0x82, 0x8c, 0x08, 0x3e, 0x0f, 0xa4, 0xd0, 0x40, 0x84, 0x00, 0x00, +0x3e, 0x7f, 0xc4, 0x60, 0x3e, 0x9f, 0x4c, 0xf8, 0x3f, 0xcf, 0x4d, 0x34, 0x02, 0x44, 0x00, 0x00, +0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x00, 0xb0, 0x44, 0x23, 0xff, 0xf0, 0x44, 0x30, 0x00, 0x04, +0x49, 0xff, 0xdd, 0x5a, 0x02, 0x44, 0x00, 0x01, 0x46, 0x23, 0xff, 0x00, 0x58, 0x13, 0x00, 0x00, +0x44, 0x00, 0x01, 0x0c, 0x44, 0x30, 0x00, 0x14, 0x49, 0xff, 0xdd, 0x4e, 0x04, 0x44, 0x00, 0x01, +0x46, 0x20, 0x00, 0xff, 0x44, 0x30, 0x00, 0x00, 0x58, 0x21, 0x0f, 0xff, 0x58, 0x13, 0x00, 0x00, +0x44, 0x00, 0x01, 0x0c, 0x49, 0xff, 0xdd, 0x40, 0x46, 0x10, 0xf8, 0x00, 0x58, 0x23, 0x00, 0x00, +0x44, 0x00, 0x01, 0x10, 0x4b, 0xe0, 0x24, 0x01, 0x46, 0x1f, 0xfe, 0x04, 0x58, 0x10, 0x80, 0x10, +0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x00, 0xb4, 0x4b, 0xe0, 0x24, 0x01, 0x44, 0x00, 0x00, 0x64, +0x49, 0xff, 0x92, 0x1e, 0x46, 0x13, 0xff, 0x0c, 0x58, 0x10, 0x80, 0x10, 0x58, 0x23, 0x00, 0x00, +0x44, 0x00, 0x00, 0xb4, 0x4b, 0xe0, 0x24, 0x01, 0x46, 0x10, 0xb0, 0x00, 0x58, 0x23, 0x00, 0x00, +0x44, 0x00, 0x01, 0x10, 0x4b, 0xe0, 0x24, 0x01, 0x4e, 0x63, 0x00, 0x10, 0x58, 0x13, 0x00, 0x00, +0x44, 0x00, 0x04, 0x20, 0x4b, 0xe0, 0x70, 0x01, 0x54, 0x20, 0x7f, 0x00, 0x40, 0x11, 0x20, 0x09, +0x12, 0x13, 0x80, 0x00, 0x48, 0x00, 0x00, 0x12, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x0e, +0x44, 0x00, 0x04, 0x20, 0x58, 0x13, 0x00, 0x00, 0x4b, 0xe0, 0x70, 0x01, 0x54, 0x40, 0x7f, 0x00, +0x40, 0x32, 0x20, 0x09, 0x12, 0x33, 0x80, 0x0f, 0x50, 0x73, 0x80, 0x02, 0x3e, 0x5f, 0xc4, 0x7e, +0x50, 0x84, 0x00, 0x20, 0x4c, 0x72, 0xff, 0x8c, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x58, 0x60, 0x00, 0x00, +0x49, 0xff, 0xcc, 0xa4, 0x46, 0x10, 0x13, 0x12, 0x58, 0x50, 0x8d, 0x00, 0x4c, 0x02, 0xc0, 0x08, +0x44, 0x40, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x20, 0x46, 0x30, 0x17, 0xd7, +0x58, 0x51, 0x88, 0x40, 0x4c, 0x02, 0xc0, 0x08, 0x44, 0x40, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, +0x48, 0x00, 0x00, 0x14, 0x46, 0x20, 0x26, 0x25, 0x58, 0x51, 0x0a, 0x00, 0x4c, 0x02, 0xc0, 0x08, +0x44, 0x40, 0x00, 0x09, 0x44, 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x08, 0x44, 0x40, 0x00, 0x00, +0x58, 0x82, 0x00, 0x00, 0x48, 0x00, 0x00, 0x06, 0x3e, 0x5f, 0xa4, 0x94, 0x38, 0x82, 0x83, 0x02, +0x3c, 0x23, 0xd9, 0x74, 0x3e, 0x1f, 0xa4, 0xd0, 0x44, 0x00, 0x00, 0x00, 0x02, 0x50, 0x80, 0x00, +0x50, 0x10, 0x80, 0x20, 0x4c, 0x51, 0x40, 0x06, 0x58, 0x90, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0a, +0x50, 0x00, 0x00, 0x01, 0x44, 0x50, 0x00, 0x0f, 0x4c, 0x02, 0xff, 0xf2, 0x44, 0x90, 0x00, 0x00, +0x3e, 0x7f, 0x4d, 0x80, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x00, 0xb0, 0x44, 0x20, 0x00, 0x0f, +0x44, 0x30, 0x00, 0x00, 0x40, 0x94, 0x88, 0x08, 0x4b, 0xe0, 0x1c, 0x01, 0x40, 0x34, 0xa0, 0x00, +0x50, 0x81, 0x80, 0x01, 0x3e, 0x1f, 0xa4, 0xd0, 0x38, 0x40, 0xa3, 0x01, 0x44, 0x00, 0x00, 0xb0, +0x58, 0x13, 0x00, 0x00, 0x44, 0x23, 0xff, 0xf0, 0x44, 0x30, 0x00, 0x04, 0x4b, 0xe0, 0x1c, 0x01, +0x40, 0x84, 0x0c, 0x08, 0x3e, 0x4f, 0xa4, 0xd0, 0x40, 0x84, 0x10, 0x00, 0x02, 0x44, 0x00, 0x01, +0x46, 0x23, 0xff, 0x00, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x01, 0x0c, 0x44, 0x30, 0x00, 0x14, +0x4b, 0xe0, 0x1c, 0x01, 0x04, 0x44, 0x00, 0x01, 0x46, 0x20, 0x00, 0xff, 0x44, 0x30, 0x00, 0x00, +0x58, 0x13, 0x00, 0x00, 0x58, 0x21, 0x0f, 0xff, 0x44, 0x00, 0x01, 0x0c, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0x10, 0x03, 0x00, 0x3e, 0x7f, 0x4c, 0xf8, 0x58, 0x23, 0x00, 0x00, 0x58, 0x10, 0x80, 0x88, +0x44, 0x00, 0x07, 0xdc, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0xf8, 0x00, 0x58, 0x23, 0x00, 0x00, +0x44, 0x00, 0x01, 0x10, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x1f, 0xfe, 0x04, 0x58, 0x23, 0x00, 0x00, +0x58, 0x10, 0x80, 0x10, 0x44, 0x00, 0x00, 0xb4, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0x64, +0x49, 0xff, 0x91, 0x2e, 0x46, 0x13, 0xfe, 0x0c, 0x58, 0x23, 0x00, 0x00, 0x58, 0x10, 0x80, 0x10, +0x44, 0x00, 0x00, 0xb4, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0xb0, 0x00, 0x58, 0x23, 0x00, 0x00, +0x44, 0x00, 0x01, 0x10, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0x03, 0x00, 0x58, 0x10, 0x80, 0x08, +0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x07, 0xdc, 0x4b, 0xe0, 0x1c, 0x01, 0x51, 0xff, 0x80, 0x04, +0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x58, 0x60, 0x00, 0x00, +0x49, 0xff, 0xff, 0x2a, 0x58, 0x03, 0x00, 0x00, 0x49, 0xff, 0xec, 0xd2, 0x58, 0x03, 0x00, 0x00, +0x49, 0xff, 0xfe, 0x6c, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x46, 0x38, 0x00, 0x21, 0x04, 0x01, 0x80, 0x04, 0x54, 0x00, 0x00, 0x03, +0x44, 0x50, 0x00, 0x02, 0x3c, 0x0f, 0xed, 0x3e, 0x4c, 0x02, 0x80, 0x0e, 0x44, 0x50, 0x00, 0x03, +0x4c, 0x02, 0x80, 0x10, 0x46, 0x00, 0x13, 0x12, 0x3e, 0x1f, 0xb4, 0xfc, 0x58, 0x00, 0x0d, 0x00, +0x48, 0x00, 0x00, 0x0e, 0x46, 0x00, 0x17, 0xd7, 0x58, 0x00, 0x08, 0x40, 0x48, 0x00, 0x00, 0x06, +0x46, 0x00, 0x26, 0x25, 0x58, 0x00, 0x0a, 0x00, 0x3e, 0x1f, 0xb4, 0xfc, 0x14, 0x00, 0x80, 0x00, +0x49, 0xff, 0x87, 0x04, 0x2e, 0x57, 0xb3, 0x58, 0x4e, 0x53, 0x00, 0x24, 0x2e, 0x7f, 0xb1, 0x16, +0x4e, 0x75, 0x00, 0x14, 0x46, 0x05, 0x00, 0x12, 0x58, 0x00, 0x00, 0x08, 0x04, 0x40, 0x00, 0x00, +0x44, 0x2f, 0xff, 0xcf, 0x40, 0x32, 0x08, 0x02, 0x14, 0x30, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, +0x58, 0x10, 0x80, 0x30, 0x48, 0x00, 0x00, 0x0c, 0x46, 0x05, 0x00, 0x12, 0x58, 0x00, 0x00, 0x08, +0x04, 0x50, 0x00, 0x00, 0x44, 0x6f, 0xff, 0xcf, 0x40, 0x12, 0x98, 0x02, 0x14, 0x10, 0x00, 0x00, +0x2f, 0xe7, 0xb0, 0xda, 0x54, 0x7f, 0x00, 0x20, 0x4e, 0x72, 0x00, 0x0a, 0x44, 0x10, 0x00, 0x01, +0x3e, 0x17, 0xb4, 0xf1, 0x44, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0a, 0x2e, 0x47, 0xb0, 0xd9, +0x54, 0x32, 0x00, 0x02, 0x4e, 0x32, 0x00, 0x06, 0x44, 0x10, 0x00, 0x01, 0x3e, 0x17, 0xb4, 0xf2, +0x2e, 0x67, 0xb0, 0xd8, 0x54, 0x53, 0x00, 0x02, 0x4e, 0x52, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, +0x3e, 0x07, 0xb4, 0xf4, 0x2e, 0x07, 0xb0, 0xd9, 0x54, 0x30, 0x00, 0x04, 0x4e, 0x32, 0x00, 0x06, +0x44, 0x20, 0x00, 0x00, 0x48, 0x00, 0x00, 0x04, 0x44, 0x20, 0x00, 0x01, 0x54, 0x40, 0x00, 0x08, +0x3e, 0x27, 0xb2, 0xea, 0x4e, 0x42, 0x00, 0x06, 0x44, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x04, +0x44, 0x10, 0x00, 0x01, 0x2e, 0x27, 0xb0, 0xfa, 0x3e, 0x17, 0xb2, 0xeb, 0x54, 0x61, 0x00, 0x1f, +0x4e, 0x62, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, 0x3f, 0xe7, 0xb4, 0xf3, 0x2e, 0x77, 0xb0, 0xfd, +0x54, 0x53, 0x80, 0x1f, 0x52, 0x12, 0x80, 0x00, 0x2e, 0x37, 0xb2, 0xea, 0x40, 0x10, 0x80, 0x10, +0x3e, 0x17, 0xb4, 0xef, 0x3e, 0x67, 0xb4, 0xee, 0x4e, 0x32, 0x00, 0x08, 0x2e, 0x37, 0xb2, 0xeb, +0x4e, 0x33, 0x00, 0x0a, 0x48, 0x00, 0x00, 0x24, 0x2e, 0x07, 0xb2, 0xeb, 0x4e, 0x03, 0x00, 0x20, +0x4e, 0x63, 0x00, 0x06, 0x44, 0x10, 0x00, 0x01, 0x48, 0x00, 0x00, 0x08, 0x5e, 0xf0, 0xff, 0xfb, +0x4e, 0xf3, 0x00, 0x08, 0x44, 0x10, 0x00, 0x02, 0x3e, 0x0f, 0xb4, 0xf0, 0x48, 0x00, 0x00, 0x0e, +0x3e, 0x0f, 0xb4, 0xf0, 0x5e, 0xf0, 0xff, 0xf7, 0x4e, 0xf3, 0x00, 0x06, 0x44, 0x10, 0x00, 0x03, +0x48, 0x00, 0x00, 0x04, 0x44, 0x10, 0x00, 0x04, 0x10, 0x10, 0x00, 0x00, 0x2e, 0x17, 0xb4, 0xf0, +0x50, 0x20, 0xff, 0xff, 0x54, 0x41, 0x00, 0xff, 0x5c, 0xf2, 0x00, 0x04, 0x4e, 0xf3, 0x00, 0x06, +0x3e, 0x0f, 0xa4, 0x88, 0x49, 0xff, 0x7f, 0x0a, 0x2e, 0x17, 0xb2, 0xea, 0x4e, 0x13, 0x00, 0x08, +0x4e, 0x62, 0x00, 0x06, 0x44, 0x30, 0x00, 0x01, 0x3e, 0x37, 0xb5, 0x11, 0x2e, 0x07, 0xb2, 0xeb, +0x4e, 0x03, 0x00, 0x04, 0x4e, 0x63, 0x00, 0x1c, 0x3e, 0x0f, 0xa4, 0x94, 0x3c, 0x1d, 0xed, 0x3f, +0x04, 0x60, 0x00, 0x01, 0x4c, 0x13, 0x40, 0x06, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x18, +0x04, 0x50, 0x00, 0x03, 0x4c, 0x12, 0xc0, 0x06, 0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x10, +0x04, 0x50, 0x00, 0x05, 0x4c, 0x12, 0xc0, 0x12, 0x48, 0x00, 0x00, 0x08, 0x44, 0x10, 0x00, 0x01, +0x3e, 0x17, 0xb5, 0x12, 0x48, 0xff, 0xff, 0xe2, 0x44, 0x00, 0x00, 0x02, 0x3e, 0x6f, 0xa4, 0x94, +0x38, 0x43, 0x03, 0x02, 0x3c, 0x4f, 0xed, 0x40, 0x44, 0x00, 0x00, 0x07, 0x44, 0x40, 0x00, 0x02, +0x45, 0xe0, 0x00, 0x00, 0x3c, 0x0f, 0xed, 0x41, 0x3c, 0x4f, 0xed, 0x42, 0x3f, 0xe7, 0xb5, 0x0c, +0x46, 0x78, 0x00, 0x21, 0x04, 0x53, 0x80, 0x04, 0x42, 0x02, 0xe0, 0x0b, 0x4e, 0x02, 0x00, 0x06, +0x44, 0x50, 0x00, 0x01, 0x3e, 0x57, 0xb5, 0x0c, 0x44, 0x40, 0x00, 0x07, 0x44, 0x50, 0x00, 0x22, +0x44, 0x00, 0x00, 0x0a, 0x3c, 0x4b, 0xda, 0x73, 0x3e, 0x57, 0xb5, 0x0d, 0x3c, 0x4b, 0xd9, 0x74, +0x3e, 0x07, 0xb5, 0x0f, 0x44, 0x70, 0x00, 0x09, 0x46, 0x18, 0x08, 0x08, 0x44, 0x20, 0x00, 0x00, +0x58, 0x10, 0x80, 0x80, 0x44, 0x30, 0x08, 0x00, 0x3e, 0x77, 0xb5, 0x10, 0x3c, 0x4b, 0xda, 0x72, +0x3c, 0x1f, 0xf1, 0xf8, 0x3c, 0x2f, 0xed, 0x3a, 0x3e, 0x07, 0xb5, 0x0e, 0x3c, 0x3f, 0xf1, 0xee, +0x3c, 0x2f, 0xf1, 0xf0, 0x3c, 0x3f, 0xf1, 0xe5, 0x3c, 0x2f, 0xf1, 0xe6, 0x3c, 0x2f, 0xf1, 0xe7, +0x3c, 0x1f, 0xf1, 0xf1, 0x3c, 0x1f, 0xf1, 0xf2, 0x3c, 0x3f, 0xf1, 0xeb, 0x3c, 0x2f, 0xf1, 0xec, +0x3c, 0x2f, 0xf1, 0xed, 0x3c, 0x1f, 0xf1, 0xf5, 0x3c, 0x1f, 0xf1, 0xf6, 0x3c, 0x3f, 0xf1, 0xe8, +0x3c, 0x2f, 0xf1, 0xe9, 0x3c, 0x2f, 0xf1, 0xea, 0x3c, 0x1f, 0xf1, 0xf3, 0x3c, 0x1f, 0xf1, 0xf4, +0x3c, 0x2f, 0xf1, 0xef, 0x3c, 0x1f, 0xf1, 0xf7, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x52, 0x41, 0x4d, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x72, 0x65, 0x63, +0x65, 0x69, 0x76, 0x65, 0x20, 0x43, 0x4d, 0x44, 0x20, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, +0x20, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x66, 0x6c, 0x6f, 0x77, 0x0a, 0x00, +0x52, 0x45, 0x47, 0x33, 0x32, 0x28, 0x53, 0x59, 0x53, 0x5f, 0x54, 0x4f, 0x50, 0x5f, 0x4d, 0x49, +0x53, 0x43, 0x32, 0x29, 0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x78, 0x20, 0x0a, 0x00, 0x00, 0x00, +0x57, 0x49, 0x46, 0x49, 0x00, 0x00, 0x00, 0x00, 0x57, 0x49, 0x46, 0x49, 0x5f, 0x4c, 0x49, 0x53, +0x52, 0x0a, 0x00, 0x00, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x50, 0x49, 0x4e, 0x5f, 0x4d, +0x55, 0x58, 0x31, 0x3d, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0a, 0x00, 0x50, 0x49, 0x4e, 0x5f, +0x4d, 0x55, 0x58, 0x31, 0x3d, 0x30, 0x78, 0x25, 0x30, 0x38, 0x78, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x50, 0x43, 0x49, 0x65, 0x5f, 0x52, 0x65, 0x73, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x61, 0x72, +0x6f, 0x75, 0x6e, 0x64, 0x49, 0x6e, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, +0x0a, 0x00, 0x00, 0x00, 0x57, 0x61, 0x74, 0x63, 0x68, 0x44, 0x6f, 0x67, 0x52, 0x65, 0x73, 0x65, +0x74, 0x41, 0x6e, 0x64, 0x65, 0x73, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x21, 0x0a, 0x00, +0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x65, 0x64, 0x21, 0x20, 0x5b, 0x25, 0x73, 0x2c, 0x20, 0x25, +0x64, 0x5d, 0x0a, 0x00, 0x73, 0x72, 0x63, 0x2f, 0x77, 0x69, 0x66, 0x69, 0x5f, 0x75, 0x6e, 0x69, +0x5f, 0x6d, 0x61, 0x63, 0x2f, 0x52, 0x4f, 0x4d, 0x2f, 0x6e, 0x69, 0x63, 0x2f, 0x68, 0x61, 0x6c, +0x2f, 0x4d, 0x54, 0x37, 0x36, 0x30, 0x33, 0x2f, 0x68, 0x61, 0x6c, 0x5f, 0x72, 0x6f, 0x6d, 0x2e, +0x63, 0x00, 0x00, 0x00, 0x68, 0x61, 0x6c, 0x54, 0x78, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x54, +0x78, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x3a, 0x20, 0x48, 0x54, 0x20, 0x72, 0x61, 0x74, +0x65, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x4f, +0x46, 0x44, 0x4d, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, +0x6e, 0x2e, 0x0a, 0x00, 0x68, 0x61, 0x6c, 0x4d, 0x61, 0x63, 0x54, 0x78, 0x53, 0x74, 0x6f, 0x70, +0x41, 0x63, 0x51, 0x75, 0x65, 0x75, 0x65, 0x57, 0x69, 0x74, 0x68, 0x50, 0x6f, 0x6c, 0x6c, 0x44, +0x6f, 0x6e, 0x65, 0x3a, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20, 0x77, 0x61, 0x69, +0x74, 0x69, 0x6e, 0x67, 0x20, 0x71, 0x75, 0x65, 0x75, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x20, +0x64, 0x6f, 0x6e, 0x65, 0x0a, 0x00, 0x00, 0x00, 0x65, 0x6d, 0x75, 0x6c, 0x54, 0x78, 0x53, 0x74, +0x6f, 0x70, 0x51, 0x75, 0x65, 0x75, 0x65, 0x3a, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, +0x20, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x71, 0x75, 0x65, 0x75, 0x65, 0x20, 0x73, +0x74, 0x6f, 0x70, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x12, 0x60, 0x28, 0x00, 0x12, 0x60, 0x2c, 0x00, 0x12, 0x60, +0x2c, 0x00, 0x12, 0x60, 0x30, 0x00, 0x12, 0x60, 0x30, 0x00, 0x12, 0x60, 0x28, 0x00, 0x12, 0x60, +0x28, 0x00, 0x12, 0x60, 0x28, 0x00, 0x12, 0x60, 0x34, 0x00, 0x12, 0x60, 0x34, 0x00, 0x12, 0x60, +0x38, 0x00, 0x12, 0x60, 0x38, 0x00, 0x12, 0x60, 0x3c, 0x00, 0x12, 0x60, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, +0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x14, 0x00, 0x13, 0x60, 0x14, 0x00, 0x13, 0x60, 0x10, 0x00, 0x13, 0x60, 0x10, 0x00, 0x13, 0x60, +0x10, 0x00, 0x13, 0x60, 0x10, 0x00, 0x13, 0x60, 0x10, 0x00, 0x13, 0x60, 0x10, 0x00, 0x13, 0x60, +0x10, 0x00, 0x13, 0x60, 0x1c, 0x00, 0x13, 0x60, 0x1c, 0x00, 0x13, 0x60, 0x18, 0x00, 0x13, 0x60, +0x18, 0x00, 0x13, 0x60, 0x73, 0x72, 0x63, 0x2f, 0x77, 0x69, 0x66, 0x69, 0x5f, 0x75, 0x6e, 0x69, +0x5f, 0x6d, 0x61, 0x63, 0x2f, 0x52, 0x4f, 0x4d, 0x2f, 0x6e, 0x69, 0x63, 0x2f, 0x68, 0x61, 0x6c, +0x2f, 0x4d, 0x54, 0x37, 0x36, 0x30, 0x33, 0x2f, 0x68, 0x61, 0x6c, 0x5f, 0x70, 0x77, 0x72, 0x5f, +0x6d, 0x67, 0x74, 0x5f, 0x72, 0x6f, 0x6d, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x73, 0x72, 0x63, 0x2f, +0x77, 0x69, 0x66, 0x69, 0x5f, 0x75, 0x6e, 0x69, 0x5f, 0x6d, 0x61, 0x63, 0x2f, 0x6e, 0x69, 0x63, +0x2f, 0x68, 0x61, 0x6c, 0x2f, 0x4d, 0x54, 0x37, 0x36, 0x30, 0x33, 0x2f, 0x68, 0x61, 0x6c, 0x2e, +0x63, 0x00, 0x00, 0x00, 0x73, 0x72, 0x63, 0x2f, 0x77, 0x69, 0x66, 0x69, 0x5f, 0x75, 0x6e, 0x69, +0x5f, 0x6d, 0x61, 0x63, 0x2f, 0x6e, 0x69, 0x63, 0x2f, 0x6e, 0x69, 0x63, 0x2e, 0x63, 0x00, 0x00, +0x00, 0x00, 0x31, 0x60, 0x08, 0x00, 0x31, 0x60, 0x04, 0x00, 0x31, 0x60, 0x0c, 0x00, 0x31, 0x60, +0x24, 0x00, 0x31, 0x60, 0x28, 0x00, 0x31, 0x60, 0x08, 0x00, 0x00, 0xa0, 0x04, 0x00, 0x00, 0xa0, +0x73, 0x72, 0x63, 0x2f, 0x77, 0x69, 0x66, 0x69, 0x5f, 0x75, 0x6e, 0x69, 0x5f, 0x6d, 0x61, 0x63, +0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x2f, 0x63, 0x6e, 0x6d, 0x5f, 0x6d, 0x65, 0x6d, 0x2e, 0x63, 0x00, +0x73, 0x72, 0x63, 0x2f, 0x77, 0x69, 0x66, 0x69, 0x5f, 0x75, 0x6e, 0x69, 0x5f, 0x6d, 0x61, 0x63, +0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x2f, 0x74, 0x78, 0x6d, 0x2e, 0x63, 0x00, 0x73, 0x72, 0x63, 0x2f, +0x77, 0x69, 0x66, 0x69, 0x5f, 0x75, 0x6e, 0x69, 0x5f, 0x6d, 0x61, 0x63, 0x2f, 0x6d, 0x67, 0x6d, +0x74, 0x2f, 0x72, 0x78, 0x6d, 0x2e, 0x63, 0x00, 0x41, 0x43, 0x20, 0x71, 0x75, 0x65, 0x75, 0x65, +0x20, 0x69, 0x73, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x0a, 0x00, 0x00, 0x00, 0x43, 0x46, 0x2d, 0x45, +0x4e, 0x44, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x0a, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xe8, 0x53, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x73, 0x72, 0x63, 0x2f, 0x77, 0x69, 0x66, 0x69, 0x5f, 0x75, 0x6e, 0x69, 0x5f, 0x6d, 0x61, 0x63, +0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x2f, 0x70, 0x32, 0x70, 0x5f, 0x66, 0x73, 0x6d, 0x2e, 0x63, 0x00, +0x64, 0x6c, 0x66, 0x6d, 0x43, 0x6d, 0x64, 0x46, 0x77, 0x52, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, +0x20, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x20, 0x50, 0x53, 0x45, 0x20, 0x62, 0x75, 0x66, 0x20, 0x45, +0x72, 0x72, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x00, 0x00, 0x00, +0x10, 0x5e, 0x10, 0x00, 0xed, 0x00, 0x00, 0x00, 0x5c, 0x77, 0x10, 0x00, 0xc2, 0x00, 0x00, 0x00, +0xa8, 0x59, 0x10, 0x00, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x20, 0x68, 0x65, 0x6d, 0x45, 0x78, 0x74, +0x43, 0x6d, 0x64, 0x46, 0x6c, 0x75, 0x73, 0x68, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x42, 0x79, 0x57, +0x6c, 0x61, 0x6e, 0x49, 0x64, 0x78, 0x20, 0x2d, 0x2d, 0x3e, 0x20, 0x77, 0x6c, 0x61, 0x6e, 0x69, +0x64, 0x78, 0x3d, 0x25, 0x64, 0x20, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x73, 0x72, 0x63, 0x2f, 0x77, 0x69, 0x66, 0x69, 0x5f, 0x75, 0x6e, 0x69, 0x5f, 0x6d, 0x61, 0x63, +0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x2f, 0x68, 0x65, 0x6d, 0x5f, 0x63, 0x6d, 0x64, 0x5f, 0x6c, 0x61, +0x79, 0x65, 0x72, 0x30, 0x65, 0x78, 0x74, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x50, 0x78, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, +0x4c, 0x79, 0x10, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x34, 0x7a, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, +0x7c, 0x5c, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0xcc, 0x77, 0x10, 0x00, 0x07, 0x00, 0x00, 0x00, +0xfc, 0x73, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0xf8, 0x71, 0x10, 0x00, 0x0a, 0x00, 0x00, 0x00, +0x34, 0x48, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x98, 0x4b, 0x10, 0x00, 0x12, 0x00, 0x00, 0x00, +0x88, 0x71, 0x10, 0x00, 0x11, 0x00, 0x00, 0x00, 0x90, 0x6f, 0x10, 0x00, 0x13, 0x00, 0x00, 0x00, +0x4c, 0x65, 0x10, 0x00, 0x34, 0x00, 0x00, 0x00, 0x90, 0x69, 0x10, 0x00, 0x17, 0x00, 0x00, 0x00, +0x8c, 0x07, 0x10, 0x00, 0x21, 0x00, 0x00, 0x00, 0x08, 0x67, 0x10, 0x00, 0x23, 0x00, 0x00, 0x00, +0xc8, 0x65, 0x10, 0x00, 0x27, 0x00, 0x00, 0x00, 0x58, 0x64, 0x10, 0x00, 0x28, 0x00, 0x00, 0x00, +0xe4, 0x63, 0x10, 0x00, 0x29, 0x00, 0x00, 0x00, 0x74, 0x63, 0x10, 0x00, 0x2b, 0x00, 0x00, 0x00, +0xbc, 0x62, 0x10, 0x00, 0x33, 0x00, 0x00, 0x00, 0x3c, 0x62, 0x10, 0x00, 0x55, 0x00, 0x00, 0x00, +0xe8, 0x61, 0x10, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, 0x48, 0x00, 0x50, 0x00, 0x53, 0x00, +0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, 0x5b, 0x00, +0x5c, 0x00, 0x5d, 0x00, 0x5e, 0x00, 0x5f, 0x00, 0x60, 0x00, 0x61, 0x00, 0xa0, 0x00, 0xa1, 0x00, +0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa5, 0x00, 0xa6, 0x00, 0xa7, 0x00, 0xa8, 0x00, 0xa9, 0x00, +0xaa, 0x00, 0xab, 0x00, 0xac, 0x00, 0xad, 0x00, 0xc0, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3, 0x00, +0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xc8, 0x00, 0xc9, 0x00, 0xca, 0x00, 0xcb, 0x00, +0xcc, 0x00, 0xcd, 0x00, 0xce, 0x00, 0xcf, 0x00, 0xd0, 0x00, 0xd1, 0x00, 0xd2, 0x00, 0xd3, 0x00, +0xd4, 0x00, 0xd5, 0x00, 0xd6, 0x00, 0xf4, 0x00, 0xf5, 0x00, 0xf6, 0x00, 0xf7, 0x00, 0x24, 0x00, +0x25, 0x00, 0x34, 0x00, 0x39, 0x00, 0x3b, 0x00, 0x42, 0x00, 0x43, 0x00, 0x9e, 0x00, 0x9f, 0x00, +0xf2, 0x00, 0xf8, 0x00, 0xf9, 0x00, 0xfa, 0x00, 0x2e, 0x01, 0x30, 0x01, 0x31, 0x01, 0x32, 0x01, +0x33, 0x01, 0x34, 0x01, 0x35, 0x01, 0x36, 0x01, 0x37, 0x01, 0x38, 0x01, 0x39, 0x01, 0x3a, 0x01, +0x3b, 0x01, 0x3c, 0x01, 0x3d, 0x01, 0x3e, 0x01, 0x3f, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x01, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x03, 0x01, 0x05, 0x02, 0x00, 0x02, 0x06, 0x02, 0x01, +0x02, 0x02, 0x02, 0x03, 0x02, 0x04, 0x02, 0x05, 0x73, 0x72, 0x63, 0x2f, 0x77, 0x69, 0x66, 0x69, +0x5f, 0x75, 0x6e, 0x69, 0x5f, 0x6d, 0x61, 0x63, 0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x2f, 0x6d, 0x74, +0x37, 0x36, 0x30, 0x33, 0x2f, 0x72, 0x6c, 0x6d, 0x5f, 0x70, 0x68, 0x79, 0x2e, 0x63, 0x00, 0x00, +0x5b, 0x25, 0x73, 0x5d, 0x20, 0x4e, 0x6f, 0x74, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x0a, 0x00, +0x5b, 0x25, 0x73, 0x5d, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x20, 0x54, 0x58, 0x20, 0x51, 0x55, 0x45, +0x55, 0x45, 0x20, 0x54, 0x59, 0x50, 0x45, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x3d, 0x3d, 0x3d, 0x20, 0x44, 0x55, 0x4d, 0x50, 0x20, 0x53, 0x54, 0x41, 0x52, 0x54, 0x20, 0x3d, +0x3d, 0x3d, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x44, 0x57, 0x30, 0x20, 0x70, 0x72, 0x48, 0x77, +0x4d, 0x61, 0x63, 0x54, 0x78, 0x44, 0x65, 0x73, 0x63, 0x2d, 0x3e, 0x75, 0x32, 0x54, 0x78, 0x42, +0x79, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x3a, 0x20, 0x25, 0x75, 0x0a, 0x00, 0x00, 0x00, +0x44, 0x57, 0x30, 0x20, 0x70, 0x72, 0x48, 0x77, 0x4d, 0x61, 0x63, 0x54, 0x78, 0x44, 0x65, 0x73, +0x63, 0x2d, 0x3e, 0x75, 0x63, 0x45, 0x74, 0x68, 0x65, 0x72, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, +0x3a, 0x20, 0x25, 0x75, 0x0a, 0x00, 0x00, 0x00, 0x44, 0x57, 0x30, 0x20, 0x70, 0x72, 0x48, 0x77, +0x4d, 0x61, 0x63, 0x54, 0x78, 0x44, 0x65, 0x73, 0x63, 0x2d, 0x3e, 0x75, 0x63, 0x50, 0x6f, 0x72, +0x74, 0x49, 0x64, 0x78, 0x5f, 0x51, 0x75, 0x65, 0x75, 0x65, 0x49, 0x64, 0x78, 0x3a, 0x20, 0x25, +0x75, 0x0a, 0x0a, 0x00, 0x44, 0x57, 0x31, 0x20, 0x70, 0x72, 0x48, 0x77, 0x4d, 0x61, 0x63, 0x54, +0x78, 0x44, 0x65, 0x73, 0x63, 0x2d, 0x3e, 0x75, 0x63, 0x57, 0x6c, 0x61, 0x6e, 0x49, 0x64, 0x78, +0x3a, 0x20, 0x25, 0x75, 0x0a, 0x00, 0x00, 0x00, 0x44, 0x57, 0x31, 0x20, 0x70, 0x72, 0x48, 0x77, +0x4d, 0x61, 0x63, 0x54, 0x78, 0x44, 0x65, 0x73, 0x63, 0x2d, 0x3e, 0x75, 0x63, 0x48, 0x65, 0x61, +0x64, 0x65, 0x72, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x3a, 0x20, 0x25, 0x75, 0x0a, 0x00, 0x00, +0x44, 0x57, 0x31, 0x20, 0x70, 0x72, 0x48, 0x77, 0x4d, 0x61, 0x63, 0x54, 0x78, 0x44, 0x65, 0x73, +0x63, 0x2d, 0x3e, 0x75, 0x63, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x61, 0x64, 0x64, 0x69, +0x6e, 0x67, 0x3a, 0x20, 0x25, 0x75, 0x0a, 0x00, 0x44, 0x57, 0x31, 0x20, 0x70, 0x72, 0x48, 0x77, +0x4d, 0x61, 0x63, 0x54, 0x78, 0x44, 0x65, 0x73, 0x63, 0x2d, 0x3e, 0x75, 0x63, 0x4f, 0x77, 0x6e, +0x4d, 0x41, 0x43, 0x3a, 0x20, 0x25, 0x75, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x44, 0x57, 0x32, 0x20, +0x70, 0x72, 0x48, 0x77, 0x4d, 0x61, 0x63, 0x54, 0x78, 0x44, 0x65, 0x73, 0x63, 0x2d, 0x3e, 0x75, +0x63, 0x54, 0x79, 0x70, 0x65, 0x5f, 0x53, 0x75, 0x62, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x25, +0x75, 0x0a, 0x00, 0x00, 0x44, 0x57, 0x32, 0x20, 0x70, 0x72, 0x48, 0x77, 0x4d, 0x61, 0x63, 0x54, +0x78, 0x44, 0x65, 0x73, 0x63, 0x2d, 0x3e, 0x75, 0x63, 0x46, 0x72, 0x61, 0x67, 0x3a, 0x20, 0x25, +0x75, 0x0a, 0x00, 0x00, 0x44, 0x57, 0x32, 0x20, 0x70, 0x72, 0x48, 0x77, 0x4d, 0x61, 0x63, 0x54, +0x78, 0x44, 0x65, 0x73, 0x63, 0x2d, 0x3e, 0x75, 0x63, 0x52, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, +0x6e, 0x67, 0x4d, 0x61, 0x78, 0x54, 0x78, 0x54, 0x69, 0x6d, 0x65, 0x3a, 0x20, 0x25, 0x75, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x44, 0x57, 0x32, 0x20, 0x70, 0x72, 0x48, 0x77, 0x4d, 0x61, 0x63, 0x54, +0x78, 0x44, 0x65, 0x73, 0x63, 0x2d, 0x3e, 0x75, 0x63, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x4f, 0x66, +0x66, 0x73, 0x65, 0x74, 0x3a, 0x20, 0x25, 0x75, 0x0a, 0x0a, 0x00, 0x00, 0x44, 0x57, 0x33, 0x20, +0x70, 0x72, 0x48, 0x77, 0x4d, 0x61, 0x63, 0x54, 0x78, 0x44, 0x65, 0x73, 0x63, 0x2d, 0x3e, 0x75, +0x32, 0x54, 0x78, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x3a, 0x20, 0x25, +0x75, 0x0a, 0x00, 0x00, 0x44, 0x57, 0x33, 0x20, 0x70, 0x72, 0x48, 0x77, 0x4d, 0x61, 0x63, 0x54, +0x78, 0x44, 0x65, 0x73, 0x63, 0x2d, 0x3e, 0x75, 0x32, 0x53, 0x4e, 0x3a, 0x20, 0x25, 0x75, 0x0a, +0x0a, 0x00, 0x00, 0x00, 0x44, 0x57, 0x34, 0x20, 0x70, 0x72, 0x48, 0x77, 0x4d, 0x61, 0x63, 0x54, +0x78, 0x44, 0x65, 0x73, 0x63, 0x2d, 0x3e, 0x75, 0x34, 0x50, 0x4e, 0x31, 0x3a, 0x20, 0x25, 0x75, +0x0a, 0x0a, 0x00, 0x00, 0x44, 0x57, 0x35, 0x20, 0x70, 0x72, 0x48, 0x77, 0x4d, 0x61, 0x63, 0x54, +0x78, 0x44, 0x65, 0x73, 0x63, 0x2d, 0x3e, 0x75, 0x63, 0x50, 0x49, 0x44, 0x3a, 0x20, 0x25, 0x75, +0x0a, 0x00, 0x00, 0x00, 0x44, 0x57, 0x35, 0x20, 0x70, 0x72, 0x48, 0x77, 0x4d, 0x61, 0x63, 0x54, +0x78, 0x44, 0x65, 0x73, 0x63, 0x2d, 0x3e, 0x75, 0x63, 0x54, 0x78, 0x53, 0x74, 0x61, 0x74, 0x75, +0x73, 0x3a, 0x20, 0x25, 0x75, 0x0a, 0x00, 0x00, 0x44, 0x57, 0x35, 0x20, 0x70, 0x72, 0x48, 0x77, +0x4d, 0x61, 0x63, 0x54, 0x78, 0x44, 0x65, 0x73, 0x63, 0x2d, 0x3e, 0x75, 0x32, 0x50, 0x4e, 0x32, +0x3a, 0x20, 0x25, 0x75, 0x0a, 0x0a, 0x00, 0x00, 0x44, 0x57, 0x36, 0x20, 0x70, 0x72, 0x48, 0x77, +0x4d, 0x61, 0x63, 0x54, 0x78, 0x44, 0x65, 0x73, 0x63, 0x2d, 0x3e, 0x75, 0x63, 0x41, 0x6e, 0x74, +0x49, 0x44, 0x3a, 0x20, 0x25, 0x75, 0x0a, 0x00, 0x44, 0x57, 0x36, 0x20, 0x70, 0x72, 0x48, 0x77, +0x4d, 0x61, 0x63, 0x54, 0x78, 0x44, 0x65, 0x73, 0x63, 0x2d, 0x3e, 0x75, 0x63, 0x42, 0x61, 0x6e, +0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x25, 0x75, 0x0a, 0x00, 0x44, 0x57, 0x36, 0x20, +0x70, 0x72, 0x48, 0x77, 0x4d, 0x61, 0x63, 0x54, 0x78, 0x44, 0x65, 0x73, 0x63, 0x2d, 0x3e, 0x75, +0x32, 0x46, 0x69, 0x78, 0x65, 0x64, 0x52, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x25, 0x75, 0x0a, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x54, 0x58, 0x20, 0x51, 0x55, 0x45, 0x55, 0x45, 0x20, 0x54, 0x59, 0x50, +0x45, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x70, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, +0x46, 0x49, 0x44, 0x20, 0x3d, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x72, +0x65, 0x6e, 0x74, 0x46, 0x49, 0x44, 0x20, 0x3d, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x70, 0x61, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x25, 0x64, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x3d, 0x3d, 0x3d, 0x20, 0x44, 0x55, 0x4d, 0x50, 0x20, 0x53, 0x54, 0x4f, +0x50, 0x20, 0x3d, 0x3d, 0x3d, 0x0a, 0x0a, 0x00, 0x52, 0x58, 0x51, 0x20, 0x52, 0x65, 0x73, 0x65, +0x74, 0x20, 0x46, 0x61, 0x69, 0x6c, 0x0a, 0x00, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x67, 0x65, +0x74, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x66, 0x69, 0x64, 0x00, 0x66, 0x69, 0x64, 0x5f, +0x6e, 0x65, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x00, 0x00, 0x00, +0x73, 0x72, 0x63, 0x2f, 0x77, 0x69, 0x66, 0x69, 0x5f, 0x75, 0x6e, 0x69, 0x5f, 0x6d, 0x61, 0x63, +0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x2f, 0x6d, 0x74, 0x37, 0x36, 0x30, 0x33, 0x2f, 0x72, 0x6c, 0x6d, +0x5f, 0x73, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x54, 0x48, 0x45, 0x52, +0x4d, 0x43, 0x52, 0x30, 0x5b, 0x25, 0x64, 0x5d, 0x3d, 0x30, 0x78, 0x25, 0x78, 0x0a, 0x00, 0x00, +0x54, 0x68, 0x65, 0x72, 0x6d, 0x6f, 0x53, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x68, 0x65, 0x63, +0x6b, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x0a, 0x00, 0x72, 0x6c, 0x6d, 0x54, 0x68, 0x65, 0x72, 0x6d, +0x6f, 0x52, 0x65, 0x43, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x0a, 0x00, 0x00, 0x54, 0x68, 0x65, 0x72, +0x6d, 0x61, 0x6c, 0x00, 0x73, 0x72, 0x63, 0x2f, 0x77, 0x69, 0x66, 0x69, 0x5f, 0x75, 0x6e, 0x69, +0x5f, 0x6d, 0x61, 0x63, 0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x2f, 0x63, 0x6e, 0x6d, 0x5f, 0x74, 0x69, +0x6d, 0x65, 0x72, 0x2e, 0x63, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x73, 0x72, 0x63, 0x2f, 0x77, 0x69, 0x66, 0x69, +0x5f, 0x75, 0x6e, 0x69, 0x5f, 0x6d, 0x61, 0x63, 0x2f, 0x62, 0x62, 0x70, 0x72, 0x66, 0x2f, 0x6d, +0x74, 0x37, 0x36, 0x30, 0x33, 0x2f, 0x72, 0x6c, 0x6d, 0x5f, 0x72, 0x66, 0x5f, 0x63, 0x61, 0x6c, +0x5f, 0x6d, 0x74, 0x37, 0x36, 0x30, 0x33, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x52, 0x4c, 0x4d, 0x20, +0x43, 0x41, 0x4c, 0x28, 0x25, 0x73, 0x29, 0x28, 0x25, 0x73, 0x29, 0x45, 0x52, 0x52, 0x0a, 0x00, +0x45, 0x4c, 0x4e, 0x41, 0x5f, 0x54, 0x42, 0x4c, 0x25, 0x64, 0x20, 0x52, 0x46, 0x0a, 0x00, 0x00, +0x52, 0x78, 0x44, 0x43, 0x4f, 0x43, 0x28, 0x66, 0x61, 0x69, 0x6c, 0x29, 0x20, 0x72, 0x6c, 0x6d, +0x43, 0x68, 0x6b, 0x44, 0x63, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x44, 0x43, 0x69, 0x3d, 0x25, +0x64, 0x2c, 0x44, 0x43, 0x71, 0x3d, 0x25, 0x64, 0x2c, 0x56, 0x61, 0x72, 0x44, 0x43, 0x69, 0x3d, +0x25, 0x64, 0x2c, 0x56, 0x61, 0x72, 0x44, 0x43, 0x71, 0x3d, 0x25, 0x64, 0x20, 0x65, 0x62, 0x77, +0x3d, 0x25, 0x64, 0x2c, 0x20, 0x75, 0x34, 0x41, 0x6e, 0x74, 0x49, 0x64, 0x78, 0x3d, 0x25, 0x64, +0x2c, 0x20, 0x67, 0x61, 0x69, 0x6e, 0x3d, 0x25, 0x64, 0x00, 0x00, 0x00, 0x21, 0x21, 0x21, 0x21, +0x20, 0x50, 0x61, 0x73, 0x73, 0x2c, 0x20, 0x64, 0x6f, 0x6e, 0x74, 0x20, 0x6e, 0x65, 0x65, 0x64, +0x20, 0x72, 0x65, 0x63, 0x61, 0x6c, 0x20, 0x28, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x20, 0x66, 0x61, +0x69, 0x6c, 0x5b, 0x25, 0x64, 0x5d, 0x29, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x52, 0x78, 0x44, 0x43, +0x4f, 0x43, 0x20, 0x53, 0x65, 0x74, 0x20, 0x44, 0x43, 0x20, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x28, +0x25, 0x64, 0x29, 0x28, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x21, 0x21, 0x21, 0x21, +0x20, 0x46, 0x61, 0x69, 0x6c, 0x2c, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x20, 0x72, 0x65, 0x63, 0x61, +0x6c, 0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x45, 0x4c, 0x4e, 0x41, +0x5f, 0x54, 0x42, 0x4c, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x31, 0x01, +0x01, 0x00, 0x00, 0x00, 0x40, 0x78, 0x7d, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x62, 0x02, +0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x31, 0x01, 0x65, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, +0x40, 0x78, 0x7d, 0x01, 0x7f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x62, 0x02, +0xcc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xcd, 0x24, 0x00, 0xea, 0x19, 0x2d, 0x01, +0x00, 0x00, 0x08, 0x00, 0x62, 0x1a, 0xf1, 0x00, 0x33, 0x33, 0x03, 0x00, 0xea, 0x19, 0x96, 0x00, +0x00, 0x00, 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x68, 0xe1, 0x24, 0x00, 0xf8, 0x19, 0x2e, 0x01, +0x00, 0x00, 0x02, 0x00, 0x70, 0x1a, 0xf1, 0x00, 0x33, 0x33, 0x0b, 0x00, 0xf8, 0x19, 0x97, 0x00, +0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf0, 0xf4, 0x24, 0x00, 0x06, 0x1a, 0x2e, 0x01, +0x00, 0x00, 0x0c, 0x00, 0x7e, 0x1a, 0xf2, 0x00, 0x33, 0x33, 0x03, 0x00, 0x06, 0x1a, 0x97, 0x00, +0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x78, 0x08, 0x25, 0x00, 0x14, 0x1a, 0x2f, 0x01, +0x00, 0x00, 0x06, 0x00, 0x8c, 0x1a, 0xf2, 0x00, 0x33, 0x33, 0x0b, 0x00, 0x14, 0x1a, 0x97, 0x00, +0x00, 0x00, 0x0b, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x25, 0x00, 0x20, 0x1a, 0x30, 0x01, +0x00, 0x00, 0x00, 0x00, 0x9a, 0x1a, 0xf3, 0x00, 0x33, 0x33, 0x03, 0x00, 0x20, 0x1a, 0x98, 0x00, +0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x88, 0x2f, 0x25, 0x00, 0x2e, 0x1a, 0x30, 0x01, +0x00, 0x00, 0x0a, 0x00, 0xa8, 0x1a, 0xf3, 0x00, 0x33, 0x33, 0x0b, 0x00, 0x2e, 0x1a, 0x98, 0x00, +0x00, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10, 0x43, 0x25, 0x00, 0x3c, 0x1a, 0x31, 0x01, +0x00, 0x00, 0x04, 0x00, 0xb6, 0x1a, 0xf4, 0x00, 0x33, 0x33, 0x03, 0x00, 0x3c, 0x1a, 0x98, 0x00, +0x00, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x00, 0x00, 0x98, 0x56, 0x25, 0x00, 0x4a, 0x1a, 0x31, 0x01, +0x00, 0x00, 0x0e, 0x00, 0xc4, 0x1a, 0xf4, 0x00, 0x33, 0x33, 0x0b, 0x00, 0x4a, 0x1a, 0x98, 0x00, +0x00, 0x00, 0x0f, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x6a, 0x25, 0x00, 0x58, 0x1a, 0x32, 0x01, +0x00, 0x00, 0x08, 0x00, 0xd2, 0x1a, 0xf5, 0x00, 0x33, 0x33, 0x03, 0x00, 0x58, 0x1a, 0x99, 0x00, +0x00, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xa8, 0x7d, 0x25, 0x00, 0x66, 0x1a, 0x33, 0x01, +0x00, 0x00, 0x02, 0x00, 0xe0, 0x1a, 0xf5, 0x00, 0x33, 0x33, 0x0b, 0x00, 0x66, 0x1a, 0x99, 0x00, +0x00, 0x00, 0x09, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x30, 0x91, 0x25, 0x00, 0x74, 0x1a, 0x33, 0x01, +0x00, 0x00, 0x0c, 0x00, 0xee, 0x1a, 0xf6, 0x00, 0x33, 0x33, 0x03, 0x00, 0x74, 0x1a, 0x99, 0x00, +0x00, 0x00, 0x0e, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xb8, 0xa4, 0x25, 0x00, 0x82, 0x1a, 0x34, 0x01, +0x00, 0x00, 0x06, 0x00, 0xfc, 0x1a, 0xf6, 0x00, 0x33, 0x33, 0x0b, 0x00, 0x82, 0x1a, 0x9a, 0x00, +0x00, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x40, 0xb8, 0x25, 0x00, 0x8e, 0x1a, 0x35, 0x01, +0x00, 0x00, 0x00, 0x00, 0x0a, 0x1b, 0xf7, 0x00, 0x33, 0x33, 0x03, 0x00, 0x8e, 0x1a, 0x9a, 0x00, +0x00, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x20, 0xe7, 0x25, 0x00, 0xb0, 0x1a, 0x36, 0x01, +0x00, 0x00, 0x08, 0x00, 0x2c, 0x1b, 0xf8, 0x00, 0x66, 0x66, 0x06, 0x00, 0xb0, 0x1a, 0x9b, 0x00, +0x00, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xc8, 0x98, 0x66, 0x01, 0x40, 0x19, 0x25, 0x01, +0x9a, 0x19, 0x0c, 0x00, 0xb6, 0x19, 0xeb, 0x00, 0x7b, 0x14, 0x00, 0x00, 0x40, 0x19, 0x92, 0x00, +0xcd, 0x0c, 0x0e, 0x00, 0x20, 0x00, 0x00, 0x00, 0x8c, 0x09, 0x80, 0x00, 0x8c, 0x09, 0x80, 0x00, +0x8c, 0x09, 0x80, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x66, 0xa4, 0x81, 0xee, 0x66, 0xa4, 0x81, 0xee, +0x66, 0xa4, 0x81, 0xee, 0xb0, 0x00, 0x00, 0x00, 0xc4, 0xa3, 0x01, 0x04, 0x66, 0xab, 0x01, 0x04, +0xc9, 0xa3, 0x01, 0x04, 0xb4, 0x00, 0x00, 0x00, 0x10, 0xc0, 0xf0, 0x3f, 0x10, 0xc0, 0xf0, 0x3f, +0x10, 0xc0, 0xf0, 0x3f, 0xbc, 0x00, 0x00, 0x00, 0xc3, 0xb6, 0x44, 0x44, 0xc3, 0xb6, 0x55, 0x55, +0xc3, 0xb6, 0x66, 0x66, 0x00, 0x06, 0x00, 0x00, 0xb3, 0x6f, 0x62, 0xc1, 0xc3, 0x6f, 0x62, 0xc1, +0xf3, 0x6f, 0x62, 0xc1, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x13, 0x33, 0x33, 0x43, 0x0f, +0x00, 0x00, 0x8a, 0x09, 0x14, 0x00, 0x00, 0x00, 0x00, 0xab, 0x84, 0x56, 0xe8, 0x00, 0x00, 0x00, +0x81, 0x00, 0x61, 0x00, 0xec, 0x00, 0x00, 0x00, 0x21, 0x00, 0x83, 0x00, 0xf0, 0x00, 0x00, 0x00, +0x63, 0x00, 0x23, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x88, 0x00, 0x68, 0x00, 0xf8, 0x00, 0x00, 0x00, +0x28, 0x00, 0x8f, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x6f, 0x00, 0xbd, 0x00, 0x00, 0x01, 0x00, 0x00, +0x9d, 0x00, 0x7d, 0x00, 0x04, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x1d, 0x00, 0x10, 0x00, 0x00, 0x00, +0x00, 0x00, 0x78, 0xbf, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, +0x00, 0x00, 0x78, 0x80, 0x14, 0x00, 0x00, 0x00, 0x00, 0xab, 0x84, 0x56, 0x18, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x11, 0x1d, 0x1e, 0x35, 0xe0, 0x00, 0x00, 0x00, +0x1c, 0x35, 0x17, 0x19, 0xe8, 0x00, 0x00, 0x00, 0xe1, 0x00, 0xa1, 0x00, 0xec, 0x00, 0x00, 0x00, +0x81, 0x00, 0x61, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x83, 0x00, 0xf4, 0x00, 0x00, 0x00, +0x63, 0x00, 0xa7, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x87, 0x00, 0x67, 0x00, 0xfc, 0x00, 0x00, 0x00, +0xae, 0x00, 0x8e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x04, 0x01, 0x00, 0x00, +0x0e, 0x00, 0x0e, 0x00, 0x00, 0x08, 0x00, 0x00, 0x66, 0x44, 0x66, 0x44, 0x04, 0x08, 0x00, 0x00, +0x66, 0x44, 0x66, 0x44, 0x08, 0x08, 0x00, 0x00, 0x00, 0x44, 0x00, 0x44, 0x0c, 0x08, 0x00, 0x00, +0x00, 0x44, 0x00, 0x44, 0x10, 0x08, 0x00, 0x00, 0x44, 0x44, 0x44, 0x41, 0x14, 0x08, 0x00, 0x00, +0x44, 0x44, 0x44, 0x41, 0x3c, 0x06, 0x00, 0x00, 0x32, 0x74, 0x32, 0x63, 0x40, 0x06, 0x00, 0x00, +0x22, 0x62, 0x32, 0x63, 0x4c, 0x06, 0x00, 0x00, 0x19, 0x19, 0x19, 0x05, 0x50, 0x06, 0x00, 0x00, +0x0a, 0x0a, 0x0a, 0x01, 0x58, 0x06, 0x00, 0x00, 0x19, 0x14, 0x14, 0x05, 0x5c, 0x06, 0x00, 0x00, +0x0a, 0x07, 0x07, 0x01, 0x64, 0x06, 0x00, 0x00, 0x19, 0x19, 0x19, 0x05, 0x68, 0x06, 0x00, 0x00, +0x19, 0x14, 0x14, 0x05, 0x00, 0x08, 0x00, 0x00, 0x66, 0x44, 0x66, 0x44, 0x04, 0x08, 0x00, 0x00, +0x66, 0x44, 0x66, 0x44, 0x08, 0x08, 0x00, 0x00, 0x00, 0x44, 0x00, 0x44, 0x0c, 0x08, 0x00, 0x00, +0x00, 0x44, 0x00, 0x44, 0x10, 0x08, 0x00, 0x00, 0x44, 0x44, 0x44, 0x41, 0x14, 0x08, 0x00, 0x00, +0x44, 0x44, 0x44, 0x41, 0x3c, 0x06, 0x00, 0x00, 0x32, 0x74, 0x32, 0x63, 0x40, 0x06, 0x00, 0x00, +0x22, 0x62, 0x32, 0x63, 0x4c, 0x06, 0x00, 0x00, 0x19, 0x19, 0x19, 0x05, 0x50, 0x06, 0x00, 0x00, +0x0a, 0x0a, 0x0a, 0x01, 0x58, 0x06, 0x00, 0x00, 0x19, 0x14, 0x14, 0x05, 0x5c, 0x06, 0x00, 0x00, +0x0a, 0x07, 0x07, 0x01, 0x64, 0x06, 0x00, 0x00, 0x19, 0x19, 0x19, 0x05, 0x68, 0x06, 0x00, 0x00, +0x19, 0x14, 0x14, 0x05, 0xfe, 0x77, 0x0d, 0x80, 0x80, 0x00, 0x00, 0x00, 0xfe, 0x77, 0x0f, 0x80, +0x80, 0x00, 0x00, 0x00, 0xfe, 0xb7, 0x0f, 0x80, 0x80, 0x00, 0x00, 0x00, 0xfe, 0xf7, 0x0f, 0x80, +0x80, 0x00, 0x00, 0x00, 0xfe, 0x77, 0x0d, 0x80, 0x90, 0x00, 0x00, 0x00, 0xfe, 0x77, 0x0f, 0x80, +0x90, 0x00, 0x00, 0x00, 0xfe, 0xb7, 0x0f, 0x80, 0x90, 0x00, 0x00, 0x00, 0xfe, 0xf7, 0x0f, 0x80, +0x90, 0x00, 0x00, 0x00, 0xfe, 0x77, 0x0d, 0x80, 0xa0, 0x00, 0x00, 0x00, 0xfe, 0x77, 0x0f, 0x80, +0xa0, 0x00, 0x00, 0x00, 0xfe, 0xb7, 0x0f, 0x80, 0xa0, 0x00, 0x00, 0x00, 0xfe, 0xf7, 0x0f, 0x80, +0xa0, 0x00, 0x00, 0x00, 0xfe, 0x77, 0x0d, 0x80, 0xb0, 0x00, 0x00, 0x00, 0xfe, 0x77, 0x0f, 0x80, +0xb0, 0x00, 0x00, 0x00, 0xfe, 0xb7, 0x0f, 0x80, 0xb0, 0x00, 0x00, 0x00, 0xfe, 0xf7, 0x0f, 0x80, +0xb0, 0x00, 0x00, 0x00, 0xfe, 0x77, 0x0d, 0x90, 0x80, 0x00, 0x00, 0x00, 0xfe, 0x77, 0x0f, 0x90, +0x80, 0x00, 0x00, 0x00, 0xfe, 0xb7, 0x0f, 0x90, 0x80, 0x00, 0x00, 0x00, 0xfe, 0xf7, 0x0f, 0x90, +0x80, 0x00, 0x00, 0x00, 0xfe, 0x77, 0x0d, 0x90, 0x90, 0x00, 0x00, 0x00, 0xfe, 0x77, 0x0f, 0x90, +0x90, 0x00, 0x00, 0x00, 0xfe, 0xb7, 0x0f, 0x90, 0x90, 0x00, 0x00, 0x00, 0xfe, 0xf7, 0x0f, 0x90, +0x90, 0x00, 0x00, 0x00, 0xfe, 0x77, 0x0d, 0x90, 0xa0, 0x00, 0x00, 0x00, 0xfe, 0x77, 0x0f, 0x90, +0xa0, 0x00, 0x00, 0x00, 0xfe, 0xb7, 0x0f, 0x90, 0xa0, 0x00, 0x00, 0x00, 0xfe, 0xf7, 0x0f, 0x90, +0xa0, 0x00, 0x00, 0x00, 0xfe, 0x77, 0x0d, 0x90, 0xb0, 0x00, 0x00, 0x00, 0xfe, 0x77, 0x0f, 0x90, +0xb0, 0x00, 0x00, 0x00, 0xfe, 0xb7, 0x0f, 0x90, 0xb0, 0x00, 0x00, 0x00, 0xfe, 0xf7, 0x0f, 0x90, +0xb0, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x20, 0x60, +0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x08, 0x20, 0x60, +0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x20, 0x60, 0xfe, 0xfb, 0xff, 0x3f, 0x14, 0x08, 0x20, 0x60, +0xfa, 0xf3, 0xdf, 0x3f, 0x18, 0x08, 0x20, 0x60, 0xf5, 0xdf, 0x9f, 0x3f, 0x1c, 0x08, 0x20, 0x60, +0xf0, 0xcb, 0x4f, 0x3f, 0x20, 0x08, 0x20, 0x60, 0xeb, 0xb3, 0xef, 0x3e, 0x24, 0x08, 0x20, 0x60, +0xe9, 0xa7, 0xaf, 0x3e, 0x28, 0x08, 0x20, 0x60, 0xef, 0xb3, 0xaf, 0x3e, 0x2c, 0x08, 0x20, 0x60, +0xff, 0xe7, 0x3f, 0x3f, 0x30, 0x08, 0x20, 0x60, 0x1c, 0x44, 0x80, 0x00, 0x34, 0x08, 0x20, 0x60, +0x46, 0xdc, 0x90, 0x02, 0x38, 0x08, 0x20, 0x60, 0x7a, 0x9c, 0x61, 0x05, 0x3c, 0x08, 0x20, 0x60, +0xb3, 0x80, 0xd2, 0x08, 0x40, 0x08, 0x20, 0x60, 0xec, 0x68, 0x73, 0x0c, 0x44, 0x08, 0x20, 0x60, +0x1d, 0x39, 0xe4, 0x0f, 0x48, 0x08, 0x20, 0x60, 0x3f, 0xd9, 0xa4, 0x12, 0x4c, 0x08, 0x20, 0x60, +0x4e, 0x2d, 0x65, 0x14, 0x00, 0x08, 0x20, 0x60, 0xfd, 0xf7, 0xdf, 0x3f, 0x04, 0x08, 0x20, 0x60, +0xfd, 0xf7, 0xdf, 0x3f, 0x08, 0x08, 0x20, 0x60, 0xfd, 0xf7, 0xdf, 0x3f, 0x0c, 0x08, 0x20, 0x60, +0xfd, 0xf7, 0xdf, 0x3f, 0x10, 0x08, 0x20, 0x60, 0xff, 0xfb, 0xef, 0x3f, 0x14, 0x08, 0x20, 0x60, +0x02, 0x04, 0xf0, 0x3f, 0x18, 0x08, 0x20, 0x60, 0x07, 0x14, 0x30, 0x00, 0x1c, 0x08, 0x20, 0x60, +0x0f, 0x30, 0x90, 0x00, 0x20, 0x08, 0x20, 0x60, 0x19, 0x54, 0x20, 0x01, 0x24, 0x08, 0x20, 0x60, +0x26, 0x88, 0xd0, 0x01, 0x28, 0x08, 0x20, 0x60, 0x36, 0xc4, 0xb0, 0x02, 0x2c, 0x08, 0x20, 0x60, +0x49, 0x0c, 0xc1, 0x03, 0x30, 0x08, 0x20, 0x60, 0x5d, 0x58, 0xf1, 0x04, 0x34, 0x08, 0x20, 0x60, +0x72, 0xac, 0x41, 0x06, 0x38, 0x08, 0x20, 0x60, 0x86, 0x00, 0x92, 0x07, 0x3c, 0x08, 0x20, 0x60, +0x99, 0x4c, 0xd2, 0x08, 0x40, 0x08, 0x20, 0x60, 0xaa, 0x94, 0xf2, 0x09, 0x44, 0x08, 0x20, 0x60, +0xb7, 0xcc, 0xe2, 0x0a, 0x48, 0x08, 0x20, 0x60, 0xbf, 0xf4, 0xa2, 0x0b, 0x4c, 0x08, 0x20, 0x60, +0xc2, 0x08, 0x13, 0x0c, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xe4, 0x00, 0x00, 0xe4, 0x94, +0x00, 0x00, 0xe4, 0x90, 0x00, 0x00, 0xe4, 0x91, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, +0x00, 0x00, 0xe4, 0xe4, 0x00, 0x00, 0xe4, 0x94, 0x00, 0x00, 0xe4, 0x90, 0x00, 0x00, 0xe4, 0x91, +0x01, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x76, 0x66, 0x66, 0x66, 0x66, +0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, +0x66, 0x66, 0x66, 0x76, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, +0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0xa8, 0x88, 0x88, 0x88, 0x88, +0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, +0x88, 0x88, 0x88, 0xa8, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x44, 0x44, 0x46, 0x41, 0x44, 0x44, 0x46, 0x11, +0x44, 0x44, 0x46, 0x11, 0x44, 0x44, 0x46, 0x11, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, +0x44, 0x44, 0x46, 0x41, 0x44, 0x44, 0x46, 0x11, 0x44, 0x44, 0x46, 0x11, 0x44, 0x44, 0x46, 0x11, +0x01, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x32, 0x52, 0x43, 0x63, 0x32, 0x52, 0x46, 0x34, +0x32, 0x52, 0x66, 0x34, 0x32, 0x52, 0x64, 0x34, 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, +0x32, 0x52, 0x42, 0x52, 0x32, 0x52, 0x45, 0x24, 0x32, 0x52, 0x55, 0x24, 0x32, 0x52, 0x54, 0x24, +0x01, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x14, 0x0f, 0x14, 0x05, 0x05, 0x0f, 0x0f, 0x14, +0x05, 0x05, 0x0f, 0x14, 0x0f, 0x05, 0x0f, 0x14, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, +0x19, 0x0f, 0x19, 0x0a, 0x0a, 0x0f, 0x0f, 0x19, 0x0a, 0x0a, 0x0f, 0x19, 0x0f, 0x0a, 0x0f, 0x19, +0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x07, 0x04, 0x07, 0x01, 0x01, 0x04, 0x04, 0x07, +0x01, 0x01, 0x04, 0x07, 0x04, 0x01, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, +0x0a, 0x04, 0x0a, 0x03, 0x03, 0x04, 0x04, 0x0a, 0x03, 0x03, 0x04, 0x0a, 0x04, 0x03, 0x04, 0x0a, +0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xa4, 0x08, 0xa4, +0x38, 0xa4, 0x28, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xa4, 0x32, 0xa4, +0x00, 0x00, 0x00, 0x00, 0x39, 0x92, 0x29, 0x92, 0x19, 0x92, 0x09, 0x92, 0x79, 0x92, 0x69, 0x92, +0x59, 0x92, 0x49, 0x92, 0x39, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0xc1, 0x64, 0x00, 0x00, +0x81, 0xc5, 0x00, 0x00, 0x41, 0x26, 0x01, 0x00, 0x11, 0x08, 0x00, 0x00, 0xd1, 0x6c, 0x00, 0x00, +0x91, 0xcd, 0x00, 0x00, 0x51, 0x2e, 0x01, 0x00, 0x21, 0x14, 0x00, 0x00, 0xe1, 0x74, 0x00, 0x00, +0xa1, 0xd5, 0x00, 0x00, 0xa1, 0xd5, 0x00, 0x00, 0x31, 0x1c, 0x00, 0x00, 0xf1, 0x7c, 0x00, 0x00, +0xb1, 0xdd, 0x00, 0x00, 0x71, 0x3e, 0x01, 0x00, 0xbf, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, +0xb9, 0x00, 0x00, 0x00, 0xb6, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, +0xa9, 0x00, 0x00, 0x00, 0xa6, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, +0x99, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, +0x89, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x64, 0x05, 0x20, 0x60, 0x00, 0x41, 0x20, 0x60, +0xc8, 0x06, 0x20, 0x60, 0x04, 0x03, 0x20, 0x60, 0x10, 0x06, 0x20, 0x60, 0x00, 0x06, 0x20, 0x60, +0x10, 0x05, 0x20, 0x60, 0x10, 0x15, 0x20, 0x60, 0x2c, 0x03, 0x20, 0x60, 0x80, 0x00, 0x12, 0x60, +0x7c, 0x05, 0x20, 0x60, 0x7c, 0x15, 0x20, 0x60, 0x20, 0x40, 0x20, 0x60, 0x08, 0x00, 0x20, 0x60, +0x7c, 0x05, 0x20, 0x60, 0x7c, 0x15, 0x20, 0x60, 0x72, 0x6c, 0x6d, 0x52, 0x46, 0x32, 0x47, 0x34, +0x5f, 0x52, 0x65, 0x67, 0x49, 0x6e, 0x69, 0x74, 0x00, 0x00, 0x00, 0x00, 0x72, 0x6c, 0x6d, 0x52, +0x46, 0x5f, 0x41, 0x46, 0x45, 0x5f, 0x43, 0x61, 0x6c, 0x32, 0x47, 0x5f, 0x54, 0x78, 0x5f, 0x44, +0x50, 0x44, 0x5f, 0x43, 0x61, 0x6c, 0x00, 0x00, 0xd0, 0x81, 0x80, 0x00, 0xd0, 0x81, 0x80, 0x00, +0x00, 0xab, 0x84, 0x56, 0x00, 0x00, 0x80, 0x43, 0xd0, 0x81, 0x81, 0x00, 0xd0, 0x81, 0x81, 0x00, +0x00, 0xab, 0x84, 0x56, 0x00, 0x00, 0x00, 0x40, 0xd0, 0x81, 0x83, 0x00, 0xd0, 0x81, 0x83, 0x00, +0x00, 0xab, 0x84, 0x56, 0x00, 0x00, 0x80, 0x40, 0xd0, 0x81, 0x84, 0x00, 0xd0, 0x81, 0x84, 0x00, +0x00, 0xa8, 0x84, 0x56, 0x00, 0x00, 0x80, 0x43, 0xd0, 0x81, 0x85, 0x00, 0xd0, 0x81, 0x85, 0x00, +0x00, 0xa8, 0x84, 0x56, 0x00, 0x00, 0x00, 0x40, 0xd0, 0x81, 0x87, 0x00, 0xd0, 0x81, 0x87, 0x00, +0x00, 0xa8, 0x84, 0x56, 0x00, 0x00, 0x80, 0x40, 0xf0, 0x80, 0x80, 0x00, 0xe0, 0x80, 0x80, 0x00, +0x00, 0xa8, 0x84, 0x56, 0x00, 0x00, 0x80, 0x43, 0xf0, 0x80, 0x81, 0x00, 0xe0, 0x80, 0x81, 0x00, +0x00, 0xa8, 0x84, 0x56, 0x00, 0x00, 0x00, 0x40, 0xf0, 0x80, 0x83, 0x00, 0xe0, 0x80, 0x83, 0x00, +0x00, 0xa8, 0x84, 0x56, 0x00, 0x00, 0x80, 0x40, 0xf0, 0x80, 0x84, 0x00, 0xe0, 0x80, 0x84, 0x00, +0x00, 0xa8, 0x84, 0x56, 0x00, 0x00, 0x00, 0x41, 0xf0, 0x80, 0x85, 0x00, 0xe0, 0x80, 0x85, 0x00, +0x00, 0xa8, 0x84, 0x56, 0x00, 0x00, 0x00, 0x41, 0xf0, 0x80, 0x87, 0x00, 0xe0, 0x80, 0x87, 0x00, +0x00, 0xa8, 0x84, 0x56, 0x00, 0x00, 0x00, 0x41, 0x72, 0x6c, 0x6d, 0x52, 0x46, 0x5f, 0x41, 0x46, +0x45, 0x5f, 0x43, 0x61, 0x6c, 0x32, 0x47, 0x5f, 0x52, 0x53, 0x53, 0x49, 0x5f, 0x44, 0x43, 0x4f, +0x43, 0x5f, 0x43, 0x61, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x60, 0x00, 0x00, 0x00, 0x04, +0x0c, 0x02, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x20, 0x60, 0xc0, 0x41, 0x40, 0x82, +0x04, 0x0d, 0x20, 0x60, 0x00, 0x08, 0x01, 0x21, 0x14, 0x42, 0x20, 0x60, 0x80, 0x05, 0x00, 0x00, +0x24, 0x0d, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0a, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, +0x40, 0x41, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, +0x00, 0x03, 0x20, 0x60, 0x48, 0x00, 0x01, 0x00, 0x00, 0x41, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, +0x04, 0x07, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x06, 0x20, 0x60, 0xa3, 0x0d, 0x22, 0x00, +0x80, 0x01, 0x20, 0x60, 0x80, 0x83, 0x82, 0x7a, 0x84, 0x01, 0x20, 0x60, 0x71, 0x6f, 0x7b, 0xa7, +0x50, 0x01, 0x20, 0x60, 0x01, 0x00, 0x10, 0x02, 0x54, 0x01, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, +0x08, 0x02, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x20, 0x60, 0x00, 0x80, 0x10, 0x00, +0x08, 0x01, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x20, 0x60, 0xf9, 0x4f, 0x00, 0x09, +0x14, 0x41, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x20, 0x60, 0xf9, 0x4f, 0x00, 0x09, +0x10, 0x01, 0x20, 0x60, 0xf9, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x20, 0x60, 0x00, 0x00, 0xf0, 0x90, +0x00, 0x00, 0x20, 0x60, 0x45, 0x00, 0x00, 0x00, 0x04, 0x00, 0x20, 0x60, 0x45, 0x00, 0x00, 0x00, +0x44, 0x01, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x20, 0x60, 0xc0, 0x41, 0x40, 0x82, +0x04, 0x1d, 0x20, 0x60, 0x00, 0x08, 0x01, 0x21, 0x24, 0x1d, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, +0x08, 0x12, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1a, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, +0x14, 0x52, 0x20, 0x60, 0x80, 0x05, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x27, 0x07, 0x30, 0x00, +0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0xd0, 0x82, 0x00, 0x01, +0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x02, +0xc0, 0x00, 0x00, 0x00, 0x00, 0x20, 0x09, 0x8f, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xd8, 0x00, 0x00, 0x00, 0xd1, 0x7e, 0x11, 0x19, 0x14, 0x00, 0x00, 0x00, 0x00, 0xab, 0x84, 0x56, +0xa0, 0x00, 0x00, 0x00, 0xfe, 0xf5, 0x06, 0x00, 0x48, 0x00, 0x00, 0x00, 0x27, 0x07, 0x30, 0x00, +0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0xd0, 0x82, 0x00, 0x01, +0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x02, +0xc0, 0x00, 0x00, 0x00, 0x00, 0x20, 0x09, 0x8f, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xd8, 0x00, 0x00, 0x00, 0xd1, 0x7e, 0x11, 0x19, 0x14, 0x00, 0x00, 0x00, 0x00, 0xab, 0x84, 0x56, +0xa0, 0x00, 0x00, 0x00, 0xfe, 0xf5, 0x06, 0x00, 0x72, 0x6c, 0x6d, 0x52, 0x46, 0x5f, 0x41, 0x46, +0x45, 0x5f, 0x43, 0x61, 0x6c, 0x32, 0x47, 0x5f, 0x53, 0x58, 0x5f, 0x47, 0x5f, 0x43, 0x61, 0x6c, +0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x43, 0x68, 0x5f, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x00, 0x00, +0x58, 0x4f, 0x00, 0x00, 0x3e, 0x0f, 0xb3, 0x3c, 0x3e, 0x2f, 0xc8, 0xcc, 0x4c, 0x01, 0x00, 0x08, +0x44, 0x10, 0x00, 0x00, 0x1c, 0x10, 0x00, 0x01, 0x4c, 0x01, 0x7f, 0xfe, 0x59, 0xe2, 0x00, 0x00, +0x4a, 0x00, 0x78, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x5c, 0x24, 0x11, 0x00, 0x01, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x80, 0x00, 0xec, 0x3b, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x00, +0xec, 0x3b, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0xd0, 0x3c, 0x10, 0x00, +0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0xd0, 0x3c, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, +0x00, 0x08, 0x00, 0x00, 0xd0, 0x3c, 0x10, 0x00, 0xf0, 0x2f, 0x11, 0x00, 0x01, 0x00, 0x00, 0x00, +0x84, 0x30, 0x11, 0x00, 0xd8, 0x31, 0x11, 0x00, 0x02, 0x02, 0x00, 0x00, 0x36, 0x0c, 0x00, 0x00, +0x81, 0x94, 0x40, 0xb0, 0x40, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x40, 0xc9, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x02, +0x00, 0x0d, 0x0d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x88, 0x80, 0x00, 0x22, 0xff, 0x01, 0x22, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0xe0, 0x96, 0x10, 0x00, +0x01, 0x00, 0x00, 0x32, 0x39, 0x00, 0x00, 0x00, 0x90, 0x90, 0x10, 0x00, 0xff, 0x00, 0x00, 0x09, +0x10, 0x00, 0x00, 0x00, 0x88, 0x92, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xc0, 0x94, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x94, 0x10, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x95, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x14, 0x95, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x14, 0x95, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x95, 0x10, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x95, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x14, 0x95, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x14, 0x95, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x95, 0x10, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x95, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x14, 0x95, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x14, 0x95, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x95, 0x10, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x95, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x14, 0x95, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x14, 0x95, 0x10, 0x00, 0x00, 0x06, 0x12, 0xfc, 0x1e, 0xf0, 0x2a, 0xe4, 0x01, 0x06, 0x12, 0xfc, +0x1e, 0xf0, 0x2a, 0xe4, 0x06, 0x06, 0x00, 0x00, 0x00, 0xff, 0x01, 0xff, 0x02, 0xff, 0x03, 0xff, +0x04, 0x00, 0x01, 0x00, 0x01, 0x01, 0x02, 0x01, 0x04, 0x00, 0x04, 0x01, 0x01, 0x01, 0x02, 0x01, +0x01, 0x00, 0x04, 0x01, 0x01, 0x01, 0x02, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x00, 0x12, 0x1f, 0x2b, 0x00, 0xfb, 0xef, 0xe3, 0x05, 0x07, 0x08, 0x0a, 0x0d, 0x10, 0x14, 0x1a, +0x20, 0x28, 0x33, 0x3e, 0x50, 0x66, 0x7c, 0xa0, 0xcc, 0xf8, 0x00, 0x00, 0x07, 0x00, 0x01, 0x01, +0x78, 0x04, 0x11, 0x00, 0x01, 0x01, 0x00, 0x00, 0x3c, 0x01, 0x11, 0x00, 0x01, 0x01, 0x00, 0x00, +0x60, 0xf9, 0x10, 0x00, 0x01, 0x01, 0x00, 0x00, 0xec, 0xfa, 0x10, 0x00, 0x01, 0x01, 0x00, 0x00, +0x2c, 0xf4, 0x10, 0x00, 0x01, 0x01, 0x00, 0x00, 0xd8, 0xf0, 0x10, 0x00, 0x01, 0x01, 0x00, 0x00, +0x28, 0xec, 0x10, 0x00, 0x01, 0x01, 0x00, 0x00, 0x7c, 0xe6, 0x10, 0x00, 0x01, 0x01, 0x00, 0x00, +0x28, 0xd2, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x14, 0x18, 0x4c, 0xbb, 0x25, 0xb4, +0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x43, 0x4c, 0x31, 0x37, 0x33, 0x37, 0x36, 0x36, 0x5f, +0x52, 0x32, 0x30, 0x31, 0x37, 0x31, 0x31, 0x31, 0x30, 0x31, 0x30, 0x35, 0x39, 0x33, 0x32, 0x00, +0x5c, 0x22, 0x01, 0x00, } ; diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7603_firmware.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7603_firmware.h new file mode 100644 index 000000000..bdb7bb93c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7603_firmware.h @@ -0,0 +1,4014 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR MT7603_FirmwareImage[] = { +0x46, 0x00, 0x01, 0x00, 0x58, 0x00, 0x01, 0xe4, 0x4a, 0x00, 0x00, 0x00, 0x3a, 0x6f, 0x98, 0xbc, +0x51, 0xff, 0xff, 0xf8, 0x46, 0x38, 0x00, 0x21, 0x04, 0x21, 0x80, 0x04, 0x42, 0x01, 0x64, 0x0b, +0x4e, 0x02, 0x00, 0x0c, 0x46, 0x68, 0x00, 0x23, 0x46, 0x40, 0x05, 0x00, 0x58, 0x53, 0x00, 0x00, +0x14, 0x43, 0x00, 0x21, 0x14, 0x42, 0x80, 0x20, 0x46, 0x08, 0x00, 0x21, 0x04, 0x20, 0x00, 0x04, +0x44, 0x50, 0x00, 0x02, 0x54, 0x11, 0x00, 0x03, 0x4c, 0x12, 0x80, 0x12, 0x46, 0x50, 0x26, 0x25, +0x46, 0x40, 0x13, 0x12, 0x58, 0x52, 0x8a, 0x00, 0x58, 0x42, 0x0d, 0x00, 0x56, 0x30, 0x80, 0x03, +0x40, 0x12, 0x8c, 0x1a, 0x40, 0x12, 0x0c, 0x1b, 0x48, 0x00, 0x00, 0x06, 0x46, 0x10, 0x17, 0xd7, +0x58, 0x10, 0x88, 0x40, 0x47, 0xe0, 0x26, 0x25, 0x59, 0xef, 0x0a, 0x00, 0x46, 0x40, 0x13, 0x12, +0x40, 0x20, 0xf8, 0x03, 0x58, 0x42, 0x0d, 0x00, 0x40, 0x12, 0x08, 0x1a, 0x44, 0x21, 0xc2, 0x00, +0x40, 0x40, 0x88, 0x17, 0x46, 0x38, 0x00, 0x00, 0x04, 0x51, 0x80, 0x42, 0x47, 0xe8, 0x00, 0xa0, +0x58, 0x02, 0x80, 0x80, 0x14, 0x01, 0x80, 0x42, 0x04, 0x6f, 0x00, 0x03, 0x58, 0x3f, 0x00, 0x00, +0x14, 0x6f, 0x80, 0x01, 0x44, 0x6f, 0xff, 0xcf, 0x04, 0x5f, 0x80, 0x01, 0x40, 0x02, 0x98, 0x02, +0x14, 0x0f, 0x80, 0x01, 0x04, 0x5f, 0x80, 0x01, 0x14, 0x5f, 0x00, 0x03, 0x14, 0x41, 0x80, 0x04, +0x46, 0xf0, 0x01, 0x16, 0x01, 0xe7, 0x8f, 0x29, 0x4f, 0xe3, 0x00, 0x0c, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x05, 0x20, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x46, 0xf0, 0x01, 0x16, 0x00, 0x17, 0x8f, 0x29, 0x4e, 0x13, 0x00, 0x14, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x05, 0x4c, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x85, 0x68, 0x46, 0x20, 0x01, 0x0e, +0x58, 0x21, 0x05, 0x74, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x51, 0xff, 0x80, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, +0x44, 0x10, 0x00, 0x64, 0x4c, 0x00, 0x80, 0x0c, 0x50, 0x50, 0x80, 0x06, 0x4c, 0x02, 0x80, 0x18, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x1c, 0x48, 0x00, 0x00, 0x0a, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x80, 0x40, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x12, 0x46, 0xf0, 0x01, 0x08, +0x58, 0xf7, 0x88, 0xfc, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x0a, 0x44, 0x00, 0x00, 0x02, +0x46, 0xf0, 0x01, 0x05, 0x58, 0xf7, 0x8c, 0x60, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x03, +0x58, 0xf7, 0x88, 0xcc, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x8e, 0x20, +0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x40, 0x00, 0x00, 0x44, 0x5f, 0xff, 0xff, 0x46, 0x70, 0x00, 0x01, +0x58, 0x73, 0x80, 0x60, 0x44, 0x00, 0x00, 0x02, 0x44, 0x60, 0x00, 0x00, 0x40, 0x83, 0x10, 0x1b, +0x40, 0x82, 0x90, 0x1a, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x60, 0x00, 0x01, 0x58, 0x63, 0x00, 0x0c, +0x44, 0x00, 0x00, 0x02, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x00, 0x00, 0x08, 0x4b, 0xe0, 0x1c, 0x01, +0x44, 0x00, 0x00, 0x08, 0x4b, 0xe0, 0x18, 0x01, 0x58, 0x04, 0x00, 0x00, 0x3a, 0x6f, 0xa0, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, 0x46, 0xf0, 0x01, 0x0f, 0x58, 0xf7, 0x89, 0x58, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x80, 0x0c, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x00, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x8e, 0x14, 0x4b, 0xe0, 0x3c, 0x01, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x82, 0xd8, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x08, 0x00, 0x21, +0x58, 0x00, 0x01, 0x34, 0x04, 0x40, 0x00, 0x00, 0x58, 0x32, 0x00, 0x02, 0x14, 0x30, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x16, 0x00, 0x17, 0x8f, 0x29, 0x4e, 0x13, 0x00, 0x0e, 0x04, 0x10, 0x00, 0x00, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x05, 0xac, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xa0, 0x00, 0x01, 0x58, 0xa5, 0x0c, 0xe4, 0x46, 0x90, 0x01, 0x00, +0x58, 0x94, 0x81, 0x2c, 0x46, 0x80, 0x00, 0x01, 0x58, 0x84, 0x0e, 0x50, 0x4b, 0xe0, 0x28, 0x01, +0x58, 0x60, 0x00, 0x00, 0x4e, 0x02, 0xff, 0xfc, 0x04, 0x10, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, +0x46, 0x70, 0x00, 0x01, 0x58, 0x73, 0x8e, 0x50, 0x4b, 0xe0, 0x24, 0x01, 0x4e, 0x04, 0x00, 0x1c, +0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x80, 0x00, 0x01, 0x58, 0x84, 0x0c, 0x94, +0x46, 0x60, 0x00, 0x01, 0x58, 0x63, 0x0c, 0xe4, 0x48, 0x00, 0x00, 0x08, 0x4b, 0xe0, 0x18, 0x01, +0x4e, 0x02, 0x00, 0x04, 0x4b, 0xe0, 0x1c, 0x01, 0x4b, 0xe0, 0x20, 0x01, 0x4e, 0x03, 0xff, 0xf8, +0x48, 0x00, 0x00, 0x08, 0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0x48, 0xff, 0xff, 0xd0, +0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x14, 0x46, 0x00, 0x01, 0x12, 0x58, 0x00, 0x0c, 0x5c, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0xe4, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x05, +0x58, 0xf7, 0x8f, 0x40, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x04, 0x20, 0x80, 0x00, 0x18, 0x01, 0x00, 0x01, +0x44, 0x00, 0x00, 0x00, 0x14, 0x20, 0x80, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, +0x58, 0x60, 0x00, 0x00, 0x58, 0x33, 0x00, 0x00, 0x58, 0x00, 0x80, 0x00, 0x58, 0x11, 0x00, 0x00, +0x46, 0x20, 0x01, 0x00, 0x58, 0x21, 0x03, 0x18, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x8f, 0xac, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x20, 0x00, 0x00, 0x38, 0x23, 0x00, 0x08, 0x3a, 0x6f, 0x98, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x1f, 0x94, 0x3c, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xf8, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x27, 0x89, 0x94, 0x44, 0x30, 0x00, 0x01, 0x58, 0x10, 0x00, 0x00, +0x4c, 0x21, 0xc0, 0x0e, 0x50, 0x1f, 0x80, 0x0c, 0x14, 0x1f, 0x80, 0x01, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x84, 0x3c, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x2a, 0x44, 0x00, 0x00, 0x02, +0x4c, 0x20, 0x40, 0x26, 0x50, 0x2f, 0x80, 0x0c, 0x46, 0x00, 0x01, 0x0f, 0x58, 0x00, 0x0a, 0x90, +0x14, 0x2f, 0x80, 0x01, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x2c, 0x4b, 0xe0, 0x3c, 0x01, +0x46, 0x00, 0x01, 0x0f, 0x58, 0x00, 0x0a, 0x90, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x86, 0x48, +0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x10, 0x00, 0x00, 0x46, 0x00, 0x01, 0x0f, 0x58, 0x00, 0x0a, 0x90, +0x46, 0xf0, 0x01, 0x06, 0x58, 0xf7, 0x82, 0x9c, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x08, +0x3b, 0xff, 0xfc, 0x84, 0x51, 0xff, 0x80, 0x14, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x08, 0x00, 0x23, +0x58, 0x00, 0x00, 0x80, 0x04, 0x30, 0x00, 0x00, 0x14, 0x30, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, +0x58, 0x11, 0x00, 0x03, 0x14, 0x10, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, +0x51, 0xff, 0xff, 0xec, 0x44, 0x60, 0x00, 0x00, 0x54, 0x70, 0x80, 0xff, 0x58, 0x23, 0x00, 0x00, +0x58, 0x13, 0x00, 0x00, 0x44, 0x30, 0x00, 0x0a, 0x44, 0x40, 0x00, 0x32, 0x58, 0x53, 0x00, 0x00, +0x14, 0x7f, 0x80, 0x03, 0x14, 0x6f, 0x80, 0x00, 0x14, 0x6f, 0x80, 0x01, 0x14, 0x6f, 0x80, 0x02, +0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x84, 0x90, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x14, +0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x51, 0xff, 0xff, 0xf0, +0x44, 0x60, 0x00, 0x00, 0x44, 0x30, 0x00, 0x11, 0x54, 0x80, 0x80, 0xff, 0x44, 0x70, 0x00, 0x02, +0x58, 0x23, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x58, 0x41, 0x80, 0x00, 0x44, 0x50, 0x01, 0x90, +0x14, 0x7f, 0x80, 0x02, 0x14, 0x8f, 0x80, 0x03, 0x14, 0x7f, 0x80, 0x00, 0x14, 0x6f, 0x80, 0x01, +0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x84, 0x90, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x10, +0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xec, +0x44, 0x60, 0x00, 0x00, 0x44, 0x30, 0x00, 0x11, 0x54, 0x70, 0x80, 0xff, 0x58, 0x23, 0x00, 0x00, +0x58, 0x13, 0x00, 0x00, 0x58, 0x41, 0x80, 0x00, 0x58, 0x53, 0x00, 0x00, 0x14, 0x7f, 0x80, 0x03, +0x14, 0x6f, 0x80, 0x00, 0x14, 0x6f, 0x80, 0x01, 0x14, 0x6f, 0x80, 0x02, 0x46, 0xf0, 0x01, 0x03, +0x58, 0xf7, 0x84, 0x90, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x14, 0x3a, 0x6f, 0x9c, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xec, 0x44, 0x60, 0x00, 0x00, +0x44, 0x30, 0x00, 0x19, 0x54, 0x70, 0x80, 0xff, 0x58, 0x23, 0x00, 0x00, 0x58, 0x13, 0x00, 0x00, +0x58, 0x41, 0x80, 0x00, 0x58, 0x53, 0x00, 0x00, 0x14, 0x7f, 0x80, 0x03, 0x14, 0x6f, 0x80, 0x00, +0x14, 0x6f, 0x80, 0x01, 0x14, 0x6f, 0x80, 0x02, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x84, 0x90, +0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x14, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xec, 0x44, 0x60, 0x00, 0x00, 0x44, 0x30, 0x00, 0x32, +0x54, 0x70, 0x80, 0xff, 0x58, 0x23, 0x00, 0x00, 0x58, 0x13, 0x00, 0x00, 0x58, 0x41, 0x80, 0x00, +0x58, 0x53, 0x00, 0x00, 0x14, 0x7f, 0x80, 0x03, 0x14, 0x6f, 0x80, 0x00, 0x14, 0x6f, 0x80, 0x01, +0x14, 0x6f, 0x80, 0x02, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x84, 0x90, 0x4b, 0xe0, 0x3c, 0x01, +0x51, 0xff, 0x80, 0x14, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, +0x51, 0xff, 0xff, 0xf0, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x27, 0x8f, 0x29, 0x58, 0x80, 0x00, 0x00, +0x54, 0x70, 0x80, 0xff, 0x4e, 0x23, 0x00, 0x10, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x05, 0xcc, +0x58, 0x14, 0x00, 0x00, 0x58, 0x23, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x60, 0x00, 0x00, 0x44, 0x30, 0x00, 0x02, 0x58, 0x13, 0x00, 0x00, +0x58, 0x04, 0x00, 0x00, 0x58, 0x23, 0x00, 0x00, 0x58, 0x43, 0x00, 0x00, 0x58, 0x51, 0x80, 0x00, +0x14, 0x7f, 0x80, 0x03, 0x14, 0x6f, 0x80, 0x00, 0x14, 0x6f, 0x80, 0x01, 0x14, 0x6f, 0x80, 0x02, +0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x84, 0x90, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x10, +0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x51, 0xff, 0xff, 0xf0, +0x46, 0xf0, 0x01, 0x16, 0x00, 0x27, 0x8f, 0x29, 0x58, 0x80, 0x00, 0x00, 0x54, 0x70, 0x80, 0xff, +0x4e, 0x23, 0x00, 0x10, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x05, 0xf8, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x85, 0xfc, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x60, 0x00, 0x00, 0x44, 0x40, 0x00, 0x02, 0x58, 0x13, 0x00, 0x00, 0x58, 0x04, 0x00, 0x00, +0x58, 0x23, 0x00, 0x00, 0x58, 0x33, 0x00, 0x00, 0x58, 0x52, 0x00, 0x00, 0x14, 0x7f, 0x80, 0x03, +0x14, 0x6f, 0x80, 0x00, 0x14, 0x6f, 0x80, 0x01, 0x14, 0x6f, 0x80, 0x02, 0x46, 0xf0, 0x01, 0x03, +0x58, 0xf7, 0x84, 0x90, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x10, 0x3a, 0x6f, 0xa0, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x58, 0x60, 0x00, 0x00, 0x54, 0x10, 0x80, 0xff, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x86, 0x18, 0x4b, 0xe0, 0x3c, 0x01, 0x42, 0x23, 0x40, 0x08, +0x46, 0x00, 0x01, 0x0f, 0x58, 0x00, 0x0b, 0x58, 0x46, 0x10, 0x01, 0x00, 0x58, 0x10, 0x89, 0xc0, +0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x87, 0xb0, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x00, 0x01, 0x0f, +0x58, 0x00, 0x0b, 0x58, 0x44, 0x10, 0x13, 0x88, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x8a, 0xa0, +0x4b, 0xe0, 0x3c, 0x01, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, +0x54, 0x10, 0x80, 0xff, 0x58, 0x60, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x86, 0x18, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x03, 0x00, 0x00, 0x40, 0x23, 0x00, 0x04, 0x46, 0x10, 0x01, 0x00, +0x58, 0x10, 0x89, 0xc0, 0x46, 0x00, 0x01, 0x0f, 0x58, 0x00, 0x0b, 0x58, 0x46, 0xf0, 0x01, 0x08, +0x58, 0xf7, 0x87, 0xb0, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x00, 0x01, 0x0f, 0x58, 0x00, 0x0b, 0x58, +0x44, 0x10, 0x13, 0x88, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x8a, 0xa0, 0x4b, 0xe0, 0x3c, 0x01, +0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x44, 0x10, 0x00, 0x03, 0x54, 0x41, 0x00, 0xff, 0x44, 0x30, 0x00, 0x00, 0x44, 0x20, 0x00, 0x07, +0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x85, 0xc0, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xec, +0x04, 0x60, 0x00, 0x02, 0x02, 0x23, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x07, 0x8f, 0x29, +0x50, 0x11, 0x7f, 0xe0, 0x40, 0x10, 0x8c, 0x09, 0x14, 0x1f, 0x80, 0x03, 0x4e, 0x03, 0x00, 0x0c, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0x14, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x40, 0x00, 0x00, 0x51, 0xc3, 0x00, 0x20, 0x14, 0x4f, 0x80, 0x02, +0x48, 0x00, 0x00, 0xf0, 0x04, 0x8e, 0x00, 0x00, 0x04, 0x5e, 0x00, 0x01, 0x5c, 0xf4, 0x00, 0x04, +0x4e, 0xf2, 0x00, 0xe0, 0x42, 0x92, 0xf8, 0x0b, 0x58, 0x12, 0x80, 0x00, 0x40, 0x62, 0x80, 0x13, +0x56, 0x74, 0x80, 0x01, 0x40, 0x52, 0xfc, 0x09, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0x24, +0x14, 0x5f, 0x80, 0x01, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, +0x04, 0x5f, 0x80, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x10, 0x77, 0x8b, 0x71, 0x46, 0xf0, 0x01, 0x0f, +0x10, 0x97, 0x8b, 0x70, 0x46, 0xf0, 0x01, 0x0f, 0x10, 0x57, 0x8b, 0x72, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x06, 0x34, 0x58, 0x14, 0x00, 0x00, 0x58, 0x23, 0x00, 0x00, 0x58, 0x33, 0x80, 0x00, +0x58, 0x44, 0x80, 0x00, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, +0x45, 0xe0, 0x00, 0x04, 0x4c, 0x6f, 0x00, 0x64, 0x5c, 0xf3, 0x00, 0x05, 0x4e, 0xf2, 0x00, 0x12, +0x44, 0x00, 0x00, 0x01, 0x4c, 0x60, 0x00, 0x36, 0x4e, 0x62, 0x00, 0x28, 0x44, 0x10, 0x00, 0x02, +0x4c, 0x60, 0x80, 0x3c, 0x44, 0x20, 0x00, 0x03, 0x4c, 0x61, 0x40, 0x94, 0x48, 0x00, 0x00, 0x44, +0x40, 0x3f, 0x08, 0x08, 0x4c, 0x61, 0x80, 0x6e, 0x5c, 0xf3, 0x00, 0x11, 0x4e, 0xf2, 0x00, 0x0c, +0x44, 0x40, 0x00, 0x05, 0x4c, 0x62, 0x00, 0x4e, 0x45, 0xe0, 0x00, 0x06, 0x4c, 0x6f, 0x40, 0x82, +0x48, 0x00, 0x00, 0x54, 0x44, 0xa0, 0x00, 0x11, 0x4c, 0x65, 0x00, 0x66, 0x50, 0x51, 0x80, 0x02, +0x4c, 0x62, 0xc0, 0x78, 0x48, 0x00, 0x00, 0x6c, 0x58, 0x04, 0x00, 0x00, 0x58, 0x13, 0x80, 0x00, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x86, 0x18, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x6a, +0x58, 0x04, 0x00, 0x00, 0x58, 0x13, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x85, 0x9c, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x5e, 0x04, 0x2f, 0x80, 0x01, 0x58, 0x04, 0x00, 0x00, +0x58, 0x14, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x87, 0x48, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x50, 0x58, 0x04, 0x00, 0x00, 0x58, 0x13, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x00, +0x58, 0xf7, 0x85, 0x50, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x44, 0x58, 0x04, 0x00, 0x00, +0x58, 0x13, 0x80, 0x00, 0x46, 0xa0, 0x01, 0x00, 0x58, 0xa5, 0x05, 0x04, 0x48, 0x00, 0x00, 0x2c, +0x58, 0x04, 0x00, 0x00, 0x58, 0x13, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x84, 0xb8, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x2e, 0x58, 0x04, 0x00, 0x00, 0x58, 0x13, 0x80, 0x00, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x84, 0x1c, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x22, +0x58, 0x04, 0x00, 0x00, 0x58, 0x13, 0x80, 0x00, 0x46, 0x20, 0x01, 0x00, 0x58, 0x21, 0x04, 0x68, +0x48, 0x00, 0x00, 0x16, 0x58, 0x04, 0x00, 0x00, 0x58, 0x13, 0x80, 0x00, 0x46, 0xa0, 0x01, 0x00, +0x58, 0xa5, 0x06, 0x94, 0x4b, 0xe0, 0x28, 0x01, 0x48, 0x00, 0x00, 0x0c, 0x58, 0x04, 0x00, 0x00, +0x58, 0x13, 0x80, 0x00, 0x46, 0x20, 0x01, 0x00, 0x58, 0x21, 0x06, 0xec, 0x4b, 0xe0, 0x08, 0x01, +0x04, 0x0f, 0x80, 0x02, 0x51, 0xce, 0x00, 0x08, 0x50, 0xa0, 0x00, 0x01, 0x14, 0xaf, 0x80, 0x02, +0x05, 0xef, 0x80, 0x02, 0x04, 0x1f, 0x80, 0x03, 0x40, 0xff, 0x04, 0x06, 0x4e, 0xf3, 0xff, 0x0c, +0x44, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x98, 0xbc, 0x40, 0x10, 0x40, 0x09, 0x40, 0x60, 0x00, 0x13, 0x54, 0x10, 0x80, 0xff, +0x44, 0x00, 0x00, 0x02, 0x4c, 0x10, 0x00, 0x3e, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x12, 0x80, 0x56, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x12, 0xc0, 0x68, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0x70, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x17, 0x8b, 0x71, 0x58, 0x03, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x85, 0x9c, +0x4b, 0xe0, 0x3c, 0x01, 0x42, 0x23, 0x44, 0x08, 0x46, 0x00, 0x01, 0x0f, 0x58, 0x00, 0x0b, 0x58, +0x46, 0x10, 0x01, 0x00, 0x58, 0x10, 0x89, 0xc0, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x87, 0xb0, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x00, 0x01, 0x0f, 0x58, 0x00, 0x0b, 0x58, 0x44, 0x10, 0x0b, 0xb8, +0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x8a, 0xa0, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x34, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0x98, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x17, 0x8b, 0x70, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x27, 0x8b, 0x72, 0x58, 0x03, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x87, 0x48, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x18, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xc8, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x17, 0x8b, 0x71, 0x58, 0x03, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x85, 0x9c, +0x4b, 0xe0, 0x3c, 0x01, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x44, 0x40, 0x00, 0x01, +0x46, 0xf0, 0x01, 0x0f, 0x10, 0x47, 0x8b, 0x76, 0x46, 0x08, 0x00, 0x21, 0x04, 0x20, 0x00, 0x40, +0x58, 0x11, 0x00, 0x80, 0x14, 0x10, 0x00, 0x40, 0x4a, 0x00, 0x78, 0x20, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x17, 0x89, 0xed, 0x40, 0x20, 0x80, 0x10, 0x4e, 0x24, 0x00, 0x4c, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x27, 0x89, 0xee, 0x46, 0x08, 0x00, 0x21, 0x40, 0x31, 0x00, 0x10, 0x04, 0x00, 0x00, 0x84, +0x4e, 0x34, 0x00, 0x1a, 0x54, 0x51, 0x00, 0x40, 0x44, 0x4f, 0x80, 0xff, 0x54, 0x21, 0x00, 0x3f, +0x54, 0x10, 0x80, 0x7f, 0x40, 0x00, 0x10, 0x02, 0x4e, 0x53, 0x00, 0x06, 0x40, 0x11, 0x04, 0x00, +0x48, 0x00, 0x00, 0x04, 0x40, 0x10, 0x88, 0x01, 0x54, 0x10, 0x80, 0x7f, 0x40, 0x10, 0xa0, 0x08, +0x48, 0x00, 0x00, 0x0a, 0x54, 0x30, 0x80, 0x7f, 0x44, 0x2f, 0x80, 0xff, 0x40, 0x11, 0xa0, 0x08, +0x40, 0x00, 0x08, 0x02, 0x40, 0x00, 0x04, 0x04, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x17, 0x89, 0xef, +0x40, 0x50, 0x80, 0x10, 0x4e, 0x54, 0x00, 0x12, 0x40, 0x20, 0x20, 0x09, 0x54, 0x40, 0x80, 0x3f, +0x40, 0x51, 0x10, 0x01, 0x54, 0x32, 0x80, 0x7f, 0x44, 0x2f, 0x80, 0xff, 0x40, 0x11, 0xa0, 0x08, +0x40, 0x00, 0x08, 0x02, 0x40, 0x00, 0x04, 0x04, 0x46, 0x18, 0x00, 0x21, 0x14, 0x00, 0x80, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x46, 0x16, 0x01, 0x40, 0x54, 0x20, 0x00, 0x04, 0x14, 0x00, 0x80, 0x00, +0x46, 0x00, 0x01, 0x0f, 0x4e, 0x22, 0x00, 0x0a, 0x04, 0x00, 0x02, 0xde, 0x44, 0x20, 0x00, 0x01, +0x10, 0x20, 0x00, 0x32, 0x48, 0x00, 0x00, 0x06, 0x04, 0x30, 0x02, 0xde, 0x10, 0x21, 0x80, 0x32, +0x44, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x26, 0x01, 0x40, 0x04, 0x11, 0x00, 0x00, +0x14, 0x10, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x36, 0x03, 0x30, +0x44, 0x4e, 0x0f, 0xff, 0x04, 0x51, 0x80, 0x00, 0x40, 0x00, 0x10, 0x02, 0x44, 0x41, 0xf0, 0x00, +0x40, 0x32, 0x90, 0x02, 0x54, 0x21, 0x00, 0xff, 0x40, 0x30, 0x0c, 0x04, 0x4e, 0x22, 0x00, 0x06, +0x42, 0x31, 0xfc, 0x09, 0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xfc, 0x08, 0x46, 0x56, 0x03, 0x30, +0x58, 0x02, 0x80, 0x00, 0x14, 0x32, 0x80, 0x00, 0x14, 0x10, 0x00, 0x01, 0x44, 0x00, 0x00, 0x00, +0x4a, 0x00, 0x78, 0x20, 0x54, 0x00, 0x00, 0xff, 0x54, 0x10, 0x80, 0xff, 0x5c, 0xf0, 0x00, 0x04, +0x4e, 0xf2, 0x00, 0x1c, 0x46, 0x26, 0x01, 0x60, 0x04, 0x31, 0x00, 0x1c, 0x5c, 0xf0, 0x80, 0x02, +0x4e, 0xf2, 0x00, 0x14, 0x40, 0x31, 0x8c, 0x08, 0x40, 0x31, 0x8c, 0x09, 0x40, 0x50, 0x78, 0x08, +0x40, 0x01, 0x94, 0x04, 0x40, 0x30, 0xf4, 0x08, 0x40, 0x10, 0x0c, 0x04, 0x14, 0x11, 0x00, 0x1c, +0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x01, 0x4a, 0x00, 0x78, 0x20, +0x54, 0x00, 0x00, 0xff, 0x54, 0x10, 0x80, 0xff, 0x54, 0x21, 0x00, 0xff, 0x54, 0x31, 0x80, 0xff, +0x54, 0x42, 0x00, 0xff, 0x4e, 0x02, 0x00, 0x0c, 0x40, 0x52, 0x00, 0x10, 0x4e, 0x55, 0x00, 0x38, +0x40, 0x02, 0x20, 0x08, 0x54, 0x40, 0x3f, 0x00, 0x42, 0x42, 0x74, 0x08, 0x5c, 0xf1, 0x00, 0x04, +0x4e, 0xf2, 0x00, 0x2e, 0x5c, 0xf1, 0x80, 0x0e, 0x4e, 0xf2, 0x00, 0x2a, 0x46, 0x01, 0xf0, 0x00, +0x40, 0x10, 0xe0, 0x08, 0x40, 0x50, 0x80, 0x02, 0x46, 0x00, 0x0c, 0x00, 0x40, 0x21, 0x58, 0x08, +0x42, 0x12, 0xfc, 0x08, 0x40, 0x51, 0x00, 0x02, 0x46, 0x00, 0x01, 0xf0, 0x40, 0x31, 0xc0, 0x08, +0x40, 0x20, 0x94, 0x04, 0x40, 0x51, 0x80, 0x02, 0x40, 0x31, 0x14, 0x04, 0x46, 0x06, 0x01, 0x60, +0x40, 0x11, 0x90, 0x04, 0x14, 0x10, 0x00, 0x02, 0x04, 0x30, 0x00, 0x02, 0x42, 0x41, 0xf8, 0x0b, +0x4e, 0x42, 0xff, 0xfc, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x01, +0x4a, 0x00, 0x78, 0x20, 0x46, 0x36, 0x01, 0x60, 0x04, 0x31, 0x80, 0x03, 0x40, 0x51, 0xa0, 0x08, +0x54, 0x41, 0x8f, 0xff, 0x40, 0x31, 0xe0, 0x09, 0x10, 0x30, 0x00, 0x00, 0x40, 0x52, 0xd0, 0x09, +0x44, 0x00, 0x00, 0x00, 0x12, 0x50, 0x80, 0x00, 0x12, 0x41, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xa0, 0x3c, 0x5c, 0xf0, 0x00, 0x02, 0x4e, 0xf3, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, +0x48, 0x00, 0x01, 0x60, 0x46, 0x56, 0x01, 0x30, 0x58, 0x52, 0x80, 0x40, 0x50, 0x72, 0xff, 0xf0, +0x50, 0x62, 0x80, 0x10, 0x50, 0x83, 0xff, 0xf0, 0x40, 0x44, 0x00, 0x1a, 0x40, 0x42, 0x80, 0x1b, +0x40, 0x53, 0x80, 0x1a, 0x40, 0x53, 0x00, 0x1b, 0x44, 0x00, 0x00, 0x01, 0x4c, 0x10, 0x00, 0x12, +0x4e, 0x12, 0x00, 0x0c, 0x44, 0x00, 0x00, 0x02, 0x4c, 0x10, 0x00, 0x14, 0x44, 0x00, 0x00, 0x03, +0x4c, 0x10, 0x40, 0x1e, 0x48, 0x00, 0x00, 0x12, 0x50, 0x42, 0x00, 0x0c, 0x48, 0x00, 0x00, 0x18, +0x44, 0x00, 0x00, 0x05, 0x4c, 0x20, 0x40, 0x14, 0x50, 0x42, 0x00, 0x0c, 0x48, 0x00, 0x00, 0xfc, +0x50, 0x42, 0x00, 0x04, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x00, 0x00, 0x06, 0x4c, 0x20, 0x40, 0x06, +0x50, 0x42, 0x00, 0x0c, 0x48, 0x00, 0x01, 0x0c, 0x50, 0x42, 0x00, 0x08, 0x44, 0x00, 0x00, 0x03, +0x4c, 0x20, 0x00, 0x6c, 0x5c, 0xf1, 0x00, 0x04, 0x4e, 0xf2, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x22, 0x80, 0x2e, 0x5c, 0xf1, 0x00, 0x02, 0x4e, 0xf2, 0x00, 0x48, 0x48, 0x00, 0x00, 0x10, +0x44, 0x00, 0x00, 0x05, 0x4c, 0x20, 0x00, 0x9a, 0x40, 0xf1, 0x00, 0x06, 0x4e, 0xf3, 0x00, 0x64, +0x44, 0x00, 0x00, 0x06, 0x4c, 0x20, 0x41, 0x04, 0x48, 0x00, 0x00, 0xe6, 0x4e, 0x13, 0x00, 0x0e, +0x04, 0x22, 0x00, 0x00, 0x46, 0x5f, 0xf8, 0x0f, 0x58, 0x52, 0x8f, 0xff, 0x58, 0x00, 0x80, 0x00, +0x40, 0x11, 0x14, 0x02, 0x48, 0x00, 0x00, 0x36, 0x04, 0x12, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, +0x40, 0x10, 0x9c, 0x09, 0x40, 0x10, 0x9c, 0x08, 0x48, 0x00, 0x00, 0x0c, 0x4e, 0x13, 0x00, 0x14, +0x04, 0x22, 0x00, 0x00, 0x58, 0x00, 0x80, 0x00, 0x40, 0x11, 0x1c, 0x09, 0x40, 0x10, 0x9c, 0x08, +0x14, 0x12, 0x00, 0x00, 0x00, 0x11, 0x80, 0x00, 0x04, 0x22, 0x00, 0x00, 0x54, 0x10, 0x80, 0x7f, +0x48, 0x00, 0x00, 0xb4, 0x04, 0x52, 0x00, 0x00, 0x44, 0x2f, 0x80, 0xff, 0x44, 0x00, 0x00, 0x00, +0x40, 0x12, 0x88, 0x02, 0x48, 0x00, 0x00, 0xa0, 0x4e, 0x12, 0x00, 0xca, 0x04, 0x12, 0x00, 0x00, +0x46, 0x5f, 0xf8, 0x0f, 0x58, 0x52, 0x8f, 0xff, 0x44, 0x00, 0x00, 0x00, 0x40, 0x10, 0x94, 0x02, +0x14, 0x12, 0x00, 0x00, 0x00, 0x11, 0x80, 0x00, 0x46, 0x30, 0x07, 0xf0, 0x04, 0x22, 0x00, 0x00, +0x40, 0x10, 0xc0, 0x08, 0x48, 0x00, 0x00, 0xb0, 0x4e, 0x12, 0x00, 0xb2, 0x04, 0x22, 0x00, 0x00, +0x46, 0x58, 0x0f, 0xff, 0x58, 0x52, 0x8f, 0xff, 0x44, 0x00, 0x00, 0x00, 0x40, 0x11, 0x14, 0x02, +0x48, 0x00, 0x00, 0x98, 0x44, 0x40, 0x00, 0x02, 0x4c, 0x12, 0x00, 0x08, 0x44, 0x00, 0x00, 0x03, +0x4c, 0x10, 0x40, 0x9e, 0x48, 0x00, 0x00, 0x14, 0x04, 0x12, 0x80, 0x00, 0x40, 0x40, 0x9c, 0x09, +0x40, 0x42, 0x1c, 0x08, 0x14, 0x42, 0x80, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x11, 0x80, 0x00, +0x04, 0x22, 0x80, 0x00, 0x54, 0x10, 0x80, 0x7f, 0x48, 0x00, 0x00, 0x38, 0x04, 0x42, 0x80, 0x00, +0x46, 0x2f, 0xf8, 0x0f, 0x58, 0x21, 0x0f, 0xff, 0x40, 0x12, 0x08, 0x02, 0x14, 0x12, 0x80, 0x00, +0x44, 0x00, 0x00, 0x00, 0x00, 0x41, 0x80, 0x00, 0x46, 0x30, 0x07, 0xf0, 0x04, 0x22, 0x80, 0x00, +0x40, 0x12, 0x40, 0x08, 0x48, 0x00, 0x00, 0x3c, 0x44, 0x00, 0x00, 0x02, 0x4c, 0x10, 0x00, 0x0c, +0x44, 0x20, 0x00, 0x03, 0x4c, 0x11, 0x00, 0x20, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x12, 0xc0, 0x68, +0x48, 0x00, 0x00, 0x32, 0x04, 0x12, 0x80, 0x00, 0x44, 0x2f, 0x80, 0xff, 0x40, 0x40, 0x88, 0x02, +0x14, 0x42, 0x80, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x11, 0x80, 0x00, 0x04, 0x22, 0x80, 0x00, +0x40, 0x30, 0xa0, 0x08, 0x54, 0x11, 0xff, 0x00, 0x40, 0x31, 0x04, 0x04, 0x14, 0x32, 0x80, 0x00, +0x48, 0x00, 0x00, 0x50, 0x04, 0x42, 0x80, 0x00, 0x46, 0x28, 0x0f, 0xff, 0x58, 0x21, 0x0f, 0xff, +0x40, 0x12, 0x08, 0x02, 0x14, 0x12, 0x80, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x41, 0x80, 0x00, +0x04, 0x22, 0x80, 0x00, 0x46, 0x37, 0xf0, 0x00, 0x40, 0x12, 0x60, 0x08, 0x40, 0x10, 0x8c, 0x02, +0x48, 0xff, 0xff, 0xe4, 0x04, 0x12, 0x00, 0x00, 0x44, 0x5f, 0x80, 0xff, 0x44, 0x00, 0x00, 0x00, +0x40, 0x10, 0x94, 0x02, 0x14, 0x12, 0x00, 0x00, 0x00, 0x11, 0x80, 0x00, 0x04, 0x22, 0x00, 0x00, +0x40, 0x30, 0xa0, 0x08, 0x54, 0x11, 0xff, 0x00, 0x40, 0x51, 0x04, 0x04, 0x14, 0x52, 0x00, 0x00, +0x48, 0x00, 0x00, 0x20, 0x44, 0x00, 0x00, 0x03, 0x4c, 0x10, 0x40, 0x1a, 0x04, 0x12, 0x00, 0x00, +0x46, 0x28, 0x0f, 0xff, 0x58, 0x21, 0x0f, 0xff, 0x44, 0x00, 0x00, 0x00, 0x40, 0x10, 0x88, 0x02, +0x14, 0x12, 0x00, 0x00, 0x00, 0x51, 0x80, 0x00, 0x04, 0x22, 0x00, 0x00, 0x46, 0x37, 0xf0, 0x00, +0x40, 0x12, 0xe0, 0x08, 0x40, 0x10, 0x8c, 0x02, 0x48, 0xff, 0xff, 0xe0, 0x44, 0x00, 0x00, 0x00, +0x3a, 0x6f, 0xa0, 0x04, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x26, 0x01, 0x20, 0x58, 0x21, 0x00, 0x80, +0x04, 0x51, 0x00, 0x00, 0x54, 0x00, 0x00, 0xff, 0x58, 0x42, 0x83, 0x00, 0x44, 0x30, 0x01, 0x00, +0x54, 0x10, 0x80, 0xff, 0x14, 0x41, 0x00, 0x00, 0x40, 0x20, 0x00, 0x1a, 0x40, 0x21, 0x80, 0x1b, +0x4e, 0x12, 0x00, 0x04, 0x58, 0x21, 0x02, 0x00, 0x46, 0x06, 0x01, 0x20, 0x04, 0x10, 0x00, 0x20, +0x40, 0x21, 0x08, 0x05, 0x40, 0x31, 0x04, 0x02, 0x14, 0x30, 0x00, 0x20, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x44, 0x30, 0x00, 0x05, 0x54, 0x00, 0x00, 0xff, +0x54, 0x10, 0x80, 0xff, 0x4c, 0x01, 0x80, 0x58, 0x5c, 0xf0, 0x00, 0x06, 0x4e, 0xf2, 0x00, 0x1c, +0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0x80, 0x3e, 0x5c, 0xf0, 0x00, 0x03, 0x4e, 0xf2, 0x00, 0x0a, +0x4e, 0x02, 0x00, 0x90, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x7a, 0x48, 0x00, 0x00, 0x2c, +0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0x80, 0x34, 0x44, 0x50, 0x00, 0x04, 0x4c, 0x02, 0xc0, 0x70, +0x48, 0x00, 0x00, 0x34, 0x44, 0x50, 0x00, 0x0a, 0x4c, 0x02, 0x80, 0x4a, 0x5c, 0xf0, 0x00, 0x0b, +0x4e, 0xf2, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x06, 0x4c, 0x02, 0x80, 0x36, 0x44, 0x50, 0x00, 0x09, +0x4c, 0x02, 0xc0, 0x5e, 0x48, 0x00, 0x00, 0x36, 0x44, 0x30, 0x00, 0x0c, 0x4c, 0x01, 0x80, 0x48, +0x40, 0xf0, 0x0c, 0x06, 0x4e, 0xf3, 0x00, 0x3c, 0x44, 0x50, 0x00, 0x0d, 0x4c, 0x02, 0xc0, 0x50, +0x48, 0x00, 0x00, 0x46, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x10, 0x48, 0x00, 0x00, 0x2c, +0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x10, 0x48, 0x00, 0x00, 0x2e, 0x46, 0x06, 0x01, 0x20, +0x58, 0x00, 0x01, 0x10, 0x48, 0x00, 0x00, 0x30, 0x46, 0x30, 0x02, 0x00, 0x46, 0x06, 0x01, 0x20, +0x48, 0x00, 0x00, 0x06, 0x46, 0x30, 0x40, 0x00, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x10, +0x48, 0x00, 0x00, 0x46, 0x46, 0x30, 0x40, 0x00, 0x46, 0x06, 0x01, 0x20, 0x48, 0x00, 0x00, 0x24, +0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x14, 0x48, 0x00, 0x00, 0x38, 0x46, 0x06, 0x01, 0x20, +0x58, 0x00, 0x01, 0x14, 0x50, 0x31, 0x80, 0x1b, 0x48, 0x00, 0x00, 0x32, 0x46, 0x06, 0x01, 0x20, +0x58, 0x00, 0x01, 0x14, 0x44, 0x30, 0x04, 0x00, 0x48, 0x00, 0x00, 0x2a, 0x46, 0x06, 0x01, 0x20, +0x58, 0x00, 0x01, 0x14, 0x44, 0x31, 0x00, 0x00, 0x48, 0x00, 0x00, 0x22, 0x46, 0x30, 0x02, 0x00, +0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x14, 0x48, 0x00, 0x00, 0x1a, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x87, 0x00, 0x44, 0x20, 0x1e, 0x62, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, +0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x10, 0x44, 0x30, 0x00, 0x01, 0x5c, 0xf0, 0x80, 0x04, +0x4e, 0xf2, 0x00, 0x06, 0x40, 0x31, 0x84, 0x0c, 0x48, 0x00, 0x00, 0x14, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x87, 0x00, 0x44, 0x20, 0x1e, 0x72, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, +0x04, 0x10, 0x00, 0x00, 0x4e, 0x23, 0x00, 0x14, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x07, 0x8f, 0x29, +0x4e, 0x03, 0x00, 0x14, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x07, 0x70, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x08, 0x40, 0x40, 0x8c, 0x02, +0x50, 0x21, 0x7f, 0xff, 0x4e, 0x43, 0xff, 0xe6, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x54, 0x00, 0x00, 0xff, 0x54, 0x10, 0x80, 0xff, 0x5c, 0xf0, 0x00, 0x0e, 0x4e, 0xf2, 0x00, 0xbc, +0x5c, 0xf0, 0x80, 0x04, 0x4e, 0xf2, 0x00, 0xb8, 0x50, 0x30, 0x7f, 0xf9, 0x54, 0x21, 0x80, 0xff, +0x5c, 0xf1, 0x00, 0x02, 0x4e, 0xf3, 0x00, 0xb0, 0x44, 0x50, 0x00, 0x05, 0x4c, 0x02, 0x80, 0x58, +0x5c, 0xf0, 0x00, 0x06, 0x4e, 0xf2, 0x00, 0x1c, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0x80, 0x3e, +0x5c, 0xf0, 0x00, 0x03, 0x4e, 0xf2, 0x00, 0x0a, 0x4e, 0x02, 0x00, 0x90, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0xc0, 0x7a, 0x48, 0x00, 0x00, 0x2c, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0x80, 0x34, +0x44, 0x50, 0x00, 0x04, 0x4c, 0x02, 0xc0, 0x70, 0x48, 0x00, 0x00, 0x34, 0x44, 0x50, 0x00, 0x0a, +0x4c, 0x02, 0x80, 0x4a, 0x5c, 0xf0, 0x00, 0x0b, 0x4e, 0xf2, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x06, +0x4c, 0x02, 0x80, 0x36, 0x44, 0x50, 0x00, 0x09, 0x4c, 0x02, 0xc0, 0x5e, 0x48, 0x00, 0x00, 0x36, +0x44, 0x20, 0x00, 0x0c, 0x4c, 0x01, 0x00, 0x48, 0x40, 0xf0, 0x08, 0x06, 0x4e, 0xf3, 0x00, 0x3c, +0x44, 0x50, 0x00, 0x0d, 0x4c, 0x02, 0xc0, 0x50, 0x48, 0x00, 0x00, 0x46, 0x46, 0x06, 0x01, 0x20, +0x58, 0x00, 0x01, 0x10, 0x48, 0x00, 0x00, 0x2c, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x10, +0x48, 0x00, 0x00, 0x2e, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x10, 0x48, 0x00, 0x00, 0x30, +0x46, 0x20, 0x02, 0x00, 0x46, 0x06, 0x01, 0x20, 0x48, 0x00, 0x00, 0x06, 0x46, 0x20, 0x40, 0x00, +0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x10, 0x48, 0x00, 0x00, 0x46, 0x46, 0x20, 0x40, 0x00, +0x46, 0x06, 0x01, 0x20, 0x48, 0x00, 0x00, 0x24, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x14, +0x48, 0x00, 0x00, 0x38, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x14, 0x44, 0x20, 0x00, 0x20, +0x48, 0x00, 0x00, 0x32, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x14, 0x44, 0x20, 0x04, 0x00, +0x48, 0x00, 0x00, 0x2a, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x14, 0x44, 0x21, 0x00, 0x00, +0x48, 0x00, 0x00, 0x22, 0x46, 0x20, 0x02, 0x00, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x14, +0x48, 0x00, 0x00, 0x1a, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x87, 0x00, 0x44, 0x20, 0x1e, 0x01, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x10, +0x44, 0x20, 0x00, 0x01, 0x40, 0x31, 0x04, 0x0c, 0x14, 0x30, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, +0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x54, 0x10, 0x80, 0xff, 0x54, 0x00, 0x00, 0xff, 0x5c, 0xf0, 0x80, 0x03, +0x4e, 0xf2, 0x00, 0x20, 0x50, 0x30, 0x7f, 0xf9, 0x54, 0x21, 0x80, 0xff, 0x5c, 0xf1, 0x00, 0x02, +0x4e, 0xf2, 0x00, 0x18, 0x46, 0x36, 0x01, 0x20, 0x56, 0x50, 0x00, 0x08, 0x58, 0x31, 0x81, 0x20, +0x44, 0x00, 0x00, 0x01, 0x50, 0x21, 0xff, 0xf8, 0x40, 0x10, 0x04, 0x0c, 0x40, 0x41, 0x94, 0x1a, +0x40, 0x41, 0x14, 0x1b, 0x14, 0x12, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x04, +0x44, 0x00, 0x00, 0x01, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x54, 0x00, 0x00, 0xff, 0x54, 0x10, 0x80, 0xff, 0x5c, 0xf0, 0x00, 0x0e, 0x4e, 0xf2, 0x00, 0xbc, +0x5c, 0xf0, 0x80, 0x04, 0x4e, 0xf2, 0x00, 0xb8, 0x50, 0x30, 0x7f, 0xf9, 0x54, 0x21, 0x80, 0xff, +0x5c, 0xf1, 0x00, 0x02, 0x4e, 0xf3, 0x00, 0xb0, 0x44, 0x50, 0x00, 0x05, 0x4c, 0x02, 0x80, 0x58, +0x5c, 0xf0, 0x00, 0x06, 0x4e, 0xf2, 0x00, 0x1c, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0x80, 0x3e, +0x5c, 0xf0, 0x00, 0x03, 0x4e, 0xf2, 0x00, 0x0a, 0x4e, 0x02, 0x00, 0x90, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0xc0, 0x7a, 0x48, 0x00, 0x00, 0x2c, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0x80, 0x34, +0x44, 0x50, 0x00, 0x04, 0x4c, 0x02, 0xc0, 0x70, 0x48, 0x00, 0x00, 0x34, 0x44, 0x50, 0x00, 0x0a, +0x4c, 0x02, 0x80, 0x4a, 0x5c, 0xf0, 0x00, 0x0b, 0x4e, 0xf2, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x06, +0x4c, 0x02, 0x80, 0x36, 0x44, 0x50, 0x00, 0x09, 0x4c, 0x02, 0xc0, 0x5e, 0x48, 0x00, 0x00, 0x36, +0x44, 0x20, 0x00, 0x0c, 0x4c, 0x01, 0x00, 0x48, 0x40, 0xf0, 0x08, 0x06, 0x4e, 0xf3, 0x00, 0x3c, +0x44, 0x50, 0x00, 0x0d, 0x4c, 0x02, 0xc0, 0x50, 0x48, 0x00, 0x00, 0x46, 0x46, 0x06, 0x01, 0x20, +0x58, 0x00, 0x01, 0x00, 0x48, 0x00, 0x00, 0x2c, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x00, +0x48, 0x00, 0x00, 0x2e, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x00, 0x48, 0x00, 0x00, 0x30, +0x46, 0x20, 0x02, 0x00, 0x46, 0x06, 0x01, 0x20, 0x48, 0x00, 0x00, 0x06, 0x46, 0x20, 0x40, 0x00, +0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x00, 0x48, 0x00, 0x00, 0x46, 0x46, 0x20, 0x40, 0x00, +0x46, 0x06, 0x01, 0x20, 0x48, 0x00, 0x00, 0x24, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x04, +0x48, 0x00, 0x00, 0x38, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x04, 0x44, 0x20, 0x00, 0x20, +0x48, 0x00, 0x00, 0x32, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x04, 0x44, 0x20, 0x04, 0x00, +0x48, 0x00, 0x00, 0x2a, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x04, 0x44, 0x21, 0x00, 0x00, +0x48, 0x00, 0x00, 0x22, 0x46, 0x20, 0x02, 0x00, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x04, +0x48, 0x00, 0x00, 0x1a, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x87, 0x00, 0x44, 0x20, 0x1d, 0x60, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x46, 0x06, 0x01, 0x20, 0x58, 0x00, 0x01, 0x00, +0x44, 0x20, 0x00, 0x01, 0x40, 0x31, 0x04, 0x0c, 0x14, 0x30, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, +0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x46, 0x26, 0x03, 0x22, +0x46, 0x38, 0x00, 0x00, 0x46, 0x06, 0x03, 0x20, 0x44, 0x10, 0x00, 0x00, 0x14, 0x31, 0x00, 0xc0, +0x58, 0x50, 0x80, 0x00, 0x48, 0x00, 0x00, 0x28, 0x44, 0x20, 0x00, 0x00, 0x41, 0xe1, 0x00, 0x00, +0x14, 0x5f, 0x00, 0x00, 0x50, 0x21, 0x00, 0x04, 0x04, 0x4f, 0x00, 0x00, 0x4e, 0x42, 0x00, 0x14, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x87, 0x00, +0x44, 0x20, 0x1c, 0xd6, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x14, 0x4c, 0x22, 0x7f, 0xe2, 0x50, 0x10, 0x80, 0x01, +0x50, 0x00, 0x00, 0x20, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x27, 0x82, 0x67, 0x40, 0xf0, 0x88, 0x06, +0x4e, 0xf3, 0xff, 0xd4, 0x46, 0x06, 0x03, 0x22, 0x04, 0x50, 0x00, 0xc0, 0x42, 0x12, 0xfc, 0x09, +0x14, 0x10, 0x00, 0xc0, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xe4, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x47, 0x82, 0x67, +0x54, 0x00, 0x00, 0xff, 0x40, 0xf0, 0x10, 0x06, 0x4e, 0xf3, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, +0x48, 0x00, 0x02, 0x24, 0x4e, 0x13, 0x00, 0x14, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, +0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x87, 0x00, 0x44, 0x20, 0x12, 0x2b, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x47, 0xc0, 0x30, 0x19, +0x01, 0xe0, 0x80, 0x05, 0x00, 0x80, 0x80, 0x04, 0x00, 0x60, 0x80, 0x1f, 0x40, 0x90, 0x70, 0x00, +0x40, 0xaf, 0x20, 0x08, 0x40, 0x74, 0x94, 0x08, 0x40, 0x55, 0x20, 0x04, 0x14, 0x7f, 0x80, 0x00, +0x4e, 0x62, 0x00, 0x04, 0x42, 0x52, 0xf8, 0x08, 0x4e, 0x32, 0x00, 0x40, 0x00, 0x41, 0x80, 0x00, +0x4e, 0x42, 0x00, 0x04, 0x42, 0x52, 0xf4, 0x08, 0x00, 0x61, 0x80, 0x01, 0x4e, 0x62, 0x00, 0x04, +0x42, 0x52, 0xf0, 0x08, 0x00, 0x71, 0x80, 0x02, 0x4e, 0x72, 0x00, 0x04, 0x42, 0x52, 0xec, 0x08, +0x00, 0x91, 0x80, 0x03, 0x4e, 0x92, 0x00, 0x04, 0x42, 0x52, 0xe8, 0x08, 0x00, 0xa1, 0x80, 0x04, +0x4e, 0xa2, 0x00, 0x04, 0x42, 0x52, 0xe4, 0x08, 0x01, 0xe1, 0x80, 0x07, 0x00, 0x81, 0x80, 0x05, +0x41, 0xcf, 0x5c, 0x08, 0x40, 0x42, 0xf0, 0x04, 0x4e, 0x82, 0x00, 0x04, 0x42, 0x42, 0x58, 0x08, +0x00, 0x91, 0x80, 0x08, 0x00, 0x81, 0x80, 0x06, 0x00, 0x71, 0x80, 0x09, 0x44, 0xa0, 0x00, 0x80, +0x40, 0x64, 0x20, 0x1a, 0x40, 0x65, 0x20, 0x1b, 0x40, 0x54, 0xc0, 0x08, 0x40, 0x33, 0x8c, 0x08, +0x40, 0x52, 0x14, 0x04, 0x40, 0x33, 0x0c, 0x04, 0x00, 0x60, 0x80, 0x00, 0x00, 0x80, 0x80, 0x22, +0x00, 0x70, 0x80, 0x21, 0x01, 0xe0, 0x80, 0x06, 0x14, 0x6f, 0x80, 0x05, 0x40, 0xa4, 0x2c, 0x08, +0x01, 0xc0, 0x80, 0x01, 0x40, 0x95, 0x1c, 0x04, 0x15, 0xcf, 0x80, 0x04, 0x40, 0x34, 0x8c, 0x04, +0x00, 0x40, 0x80, 0x03, 0x00, 0x60, 0x80, 0x02, 0x14, 0x4f, 0x80, 0x03, 0x4f, 0xe2, 0x00, 0x06, +0x58, 0x31, 0x81, 0x00, 0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xa0, 0x09, 0x00, 0x40, 0x80, 0x07, +0x4e, 0x42, 0x00, 0x06, 0x58, 0x31, 0x82, 0x00, 0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xa4, 0x09, +0x00, 0x90, 0x80, 0x09, 0x4e, 0x92, 0x00, 0x06, 0x58, 0x31, 0xc0, 0x00, 0x48, 0x00, 0x00, 0x04, +0x42, 0x31, 0xb8, 0x09, 0x00, 0x70, 0x80, 0x08, 0x4e, 0x72, 0x00, 0x06, 0x58, 0x31, 0x84, 0x00, +0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xa8, 0x09, 0x01, 0xe0, 0x80, 0x0a, 0x4f, 0xe2, 0x00, 0x06, +0x42, 0x31, 0xbc, 0x08, 0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xbc, 0x09, 0x01, 0xc0, 0x80, 0x0b, +0x4f, 0xc2, 0x00, 0x06, 0x42, 0x31, 0xc0, 0x08, 0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xc0, 0x09, +0x00, 0xa0, 0x80, 0x0c, 0x4e, 0xa2, 0x00, 0x06, 0x42, 0x31, 0xc4, 0x08, 0x48, 0x00, 0x00, 0x04, +0x42, 0x31, 0xc4, 0x09, 0x00, 0x80, 0x80, 0x0d, 0x4e, 0x82, 0x00, 0x06, 0x42, 0x31, 0xc8, 0x08, +0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xc8, 0x09, 0x00, 0x40, 0x80, 0x0e, 0x4e, 0x42, 0x00, 0x06, +0x42, 0x31, 0xcc, 0x08, 0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xcc, 0x09, 0x00, 0x90, 0x80, 0x0f, +0x4e, 0x92, 0x00, 0x06, 0x42, 0x31, 0xd0, 0x08, 0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xd0, 0x09, +0x00, 0x70, 0x80, 0x10, 0x4e, 0x72, 0x00, 0x06, 0x42, 0x31, 0xd4, 0x08, 0x48, 0x00, 0x00, 0x04, +0x42, 0x31, 0xd4, 0x09, 0x01, 0xe0, 0x80, 0x11, 0x4f, 0xe2, 0x00, 0x06, 0x42, 0x31, 0xd8, 0x08, +0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xd8, 0x09, 0x01, 0xc0, 0x80, 0x12, 0x4f, 0xc2, 0x00, 0x06, +0x42, 0x31, 0xdc, 0x08, 0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xdc, 0x09, 0x00, 0xa0, 0x80, 0x13, +0x4e, 0xa2, 0x00, 0x06, 0x42, 0x31, 0xe0, 0x08, 0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xe0, 0x09, +0x00, 0x80, 0x80, 0x14, 0x4e, 0x82, 0x00, 0x06, 0x42, 0x31, 0xe4, 0x08, 0x48, 0x00, 0x00, 0x04, +0x42, 0x31, 0xe4, 0x09, 0x00, 0x40, 0x80, 0x15, 0x4e, 0x42, 0x00, 0x06, 0x42, 0x31, 0xec, 0x08, +0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xec, 0x09, 0x00, 0x90, 0x80, 0x16, 0x4e, 0x92, 0x00, 0x06, +0x42, 0x31, 0xf0, 0x08, 0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xf0, 0x09, 0x00, 0x70, 0x80, 0x17, +0x4e, 0x72, 0x00, 0x06, 0x42, 0x31, 0xf4, 0x08, 0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xf4, 0x09, +0x01, 0xe0, 0x80, 0x18, 0x4f, 0xe2, 0x00, 0x06, 0x42, 0x31, 0xf8, 0x08, 0x48, 0x00, 0x00, 0x04, +0x42, 0x31, 0xf8, 0x09, 0x01, 0xc0, 0x80, 0x1a, 0x4f, 0xc2, 0x00, 0x06, 0x42, 0x31, 0xfc, 0x08, +0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xfc, 0x09, 0x00, 0xa0, 0x80, 0x20, 0x4e, 0xa2, 0x00, 0x0a, +0x46, 0x80, 0x40, 0x00, 0x40, 0x71, 0xa0, 0x04, 0x14, 0x7f, 0x80, 0x02, 0x48, 0x00, 0x00, 0x06, +0x43, 0xe1, 0xe8, 0x09, 0x15, 0xef, 0x80, 0x02, 0x4e, 0x23, 0x00, 0x06, 0x58, 0x31, 0x00, 0x00, +0x48, 0x00, 0x00, 0x10, 0x02, 0x91, 0x00, 0x02, 0x00, 0x71, 0x00, 0x08, 0x40, 0x34, 0xc0, 0x08, +0x41, 0xc3, 0xac, 0x08, 0x02, 0xa1, 0x00, 0x00, 0x40, 0x9e, 0x0c, 0x04, 0x40, 0x34, 0xa8, 0x04, +0x00, 0x80, 0x80, 0x19, 0x4e, 0x82, 0x00, 0x06, 0x42, 0x31, 0xec, 0x08, 0x48, 0x00, 0x00, 0x04, +0x42, 0x31, 0xec, 0x09, 0x00, 0x40, 0x80, 0x1b, 0x4e, 0x42, 0x00, 0x06, 0x42, 0x31, 0xf0, 0x08, +0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xf0, 0x09, 0x01, 0xc0, 0x80, 0x1c, 0x4f, 0xc2, 0x00, 0x06, +0x42, 0x31, 0xf4, 0x08, 0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xf4, 0x09, 0x00, 0x80, 0x80, 0x1d, +0x4e, 0x82, 0x00, 0x06, 0x42, 0x31, 0xf8, 0x08, 0x48, 0x00, 0x00, 0x04, 0x42, 0x31, 0xf8, 0x09, +0x00, 0x80, 0x80, 0x1e, 0x4e, 0x82, 0x00, 0x0a, 0x46, 0x48, 0x00, 0x00, 0x40, 0x11, 0x90, 0x04, +0x14, 0x1f, 0x80, 0x01, 0x48, 0x00, 0x00, 0x06, 0x42, 0xa1, 0xfc, 0x09, 0x14, 0xaf, 0x80, 0x01, +0x4e, 0x22, 0x00, 0x48, 0x47, 0xe0, 0x01, 0x0f, 0x59, 0xef, 0x09, 0x98, 0x02, 0x41, 0x00, 0x00, +0x04, 0x1f, 0x00, 0x00, 0x00, 0x31, 0x00, 0x0a, 0x00, 0x91, 0x00, 0x09, 0x02, 0x71, 0x00, 0x01, +0x02, 0x81, 0x00, 0x03, 0x38, 0x40, 0x81, 0x09, 0x50, 0x10, 0x00, 0x80, 0x04, 0xaf, 0x00, 0x00, +0x00, 0x41, 0x00, 0x08, 0x41, 0xc5, 0x00, 0x00, 0x10, 0x4e, 0x03, 0x00, 0x50, 0x40, 0x01, 0x00, +0x03, 0xc1, 0x00, 0x01, 0x04, 0xaf, 0x00, 0x00, 0x40, 0x94, 0xac, 0x08, 0x39, 0xc5, 0x05, 0x09, +0x40, 0x84, 0x5c, 0x08, 0x04, 0xaf, 0x00, 0x00, 0x00, 0x11, 0x00, 0x09, 0x41, 0xc5, 0x00, 0x00, +0x10, 0x1e, 0x03, 0x80, 0x40, 0x11, 0xc4, 0x08, 0x04, 0xaf, 0x00, 0x00, 0x03, 0xc1, 0x00, 0x02, +0x40, 0x94, 0x84, 0x04, 0x39, 0xc5, 0x11, 0x09, 0x40, 0x94, 0x9c, 0x04, 0x04, 0x3f, 0x00, 0x00, +0x00, 0x21, 0x00, 0x0a, 0x40, 0xa1, 0x80, 0x00, 0x10, 0x25, 0x04, 0x00, 0x40, 0x24, 0xa0, 0x04, +0x04, 0x0f, 0x80, 0x04, 0x41, 0xc3, 0x40, 0x08, 0x46, 0x38, 0x00, 0x00, 0x46, 0x66, 0x03, 0x22, +0x40, 0x70, 0x20, 0x08, 0x40, 0x43, 0xf0, 0x04, 0x05, 0xcf, 0x80, 0x00, 0x14, 0x33, 0x00, 0xc0, +0x42, 0x52, 0xfc, 0x08, 0x04, 0x1f, 0x80, 0x05, 0x1c, 0x5e, 0x00, 0x01, 0x40, 0x62, 0x04, 0x04, +0x04, 0x3f, 0x80, 0x03, 0x04, 0x4f, 0x80, 0x00, 0x40, 0x01, 0xe0, 0x08, 0x40, 0x63, 0x00, 0x04, +0x14, 0x6e, 0x00, 0x00, 0x50, 0x52, 0x00, 0x08, 0x05, 0xcf, 0x80, 0x02, 0x50, 0x32, 0x00, 0x10, +0x15, 0xc2, 0x80, 0x00, 0x50, 0x12, 0x00, 0x0c, 0x04, 0x0f, 0x80, 0x01, 0x14, 0x00, 0x80, 0x00, +0x14, 0x21, 0x80, 0x00, 0x44, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x1c, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x54, 0x00, 0x00, 0xff, 0x5c, 0xf0, 0x00, 0x03, +0x4e, 0xf3, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x52, 0x4e, 0x23, 0x00, 0x14, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x87, 0x00, +0x44, 0x20, 0x04, 0x98, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x00, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0x80, 0x0e, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x02, 0x80, 0x12, 0x46, 0x06, 0x01, 0x40, 0x58, 0x00, 0x00, 0x04, 0x50, 0x30, 0x00, 0x04, +0x48, 0x00, 0x00, 0x10, 0x46, 0x06, 0x01, 0x40, 0x58, 0x00, 0x00, 0x0c, 0x50, 0x30, 0x00, 0x04, +0x48, 0x00, 0x00, 0x08, 0x46, 0x06, 0x01, 0x40, 0x58, 0x00, 0x00, 0x14, 0x50, 0x30, 0x00, 0x04, +0x04, 0x00, 0x00, 0x00, 0x05, 0xe1, 0x80, 0x00, 0x40, 0x40, 0x60, 0x09, 0x40, 0x60, 0x20, 0x09, +0x40, 0x50, 0x40, 0x09, 0x40, 0x7f, 0x20, 0x09, 0x42, 0x8f, 0x40, 0x0b, 0x10, 0x80, 0x80, 0x00, +0x10, 0x71, 0x00, 0x05, 0x10, 0x61, 0x00, 0x01, 0x10, 0x51, 0x00, 0x02, 0x10, 0x41, 0x00, 0x03, +0x11, 0xe1, 0x00, 0x04, 0x10, 0x01, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x3a, 0x6f, 0xa0, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x54, 0x10, 0x80, 0xff, +0x58, 0x71, 0x80, 0x00, 0x54, 0x00, 0x00, 0xff, 0x54, 0x21, 0x00, 0xff, 0x5c, 0xf0, 0x80, 0x03, +0x4e, 0xf2, 0x00, 0x3a, 0x50, 0x40, 0x7f, 0xf9, 0x54, 0x32, 0x00, 0xff, 0x5c, 0xf1, 0x80, 0x02, +0x4e, 0xf2, 0x00, 0x32, 0x46, 0x96, 0x01, 0x20, 0x58, 0x94, 0x81, 0x24, 0x50, 0x54, 0xff, 0xf8, +0x56, 0x00, 0x00, 0x08, 0x44, 0x80, 0x00, 0x01, 0x40, 0x64, 0x80, 0x1a, 0x40, 0x62, 0x80, 0x1b, +0x40, 0x84, 0x04, 0x0c, 0x14, 0x83, 0x00, 0x00, 0x4e, 0x22, 0x00, 0x22, 0x04, 0x23, 0x00, 0x00, +0x46, 0x90, 0x01, 0x03, 0x58, 0x94, 0x80, 0x84, 0x48, 0x00, 0x00, 0x0e, 0x4e, 0x73, 0x00, 0x06, +0x44, 0x00, 0x00, 0x04, 0x48, 0x00, 0x00, 0x16, 0x4b, 0xe0, 0x24, 0x01, 0x04, 0x23, 0x00, 0x00, +0x50, 0x73, 0xff, 0xff, 0x40, 0x21, 0x20, 0x02, 0x44, 0x00, 0x00, 0x01, 0x4e, 0x23, 0xff, 0xf0, +0x48, 0x00, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, +0x54, 0x00, 0x00, 0xff, 0x58, 0x71, 0x80, 0x00, 0x54, 0x10, 0x80, 0xff, 0x54, 0x21, 0x00, 0xff, +0x5c, 0xf0, 0x00, 0x0e, 0x4e, 0xf2, 0x00, 0xe6, 0x5c, 0xf0, 0x80, 0x04, 0x4e, 0xf2, 0x00, 0xe2, +0x50, 0x40, 0x7f, 0xf9, 0x54, 0x32, 0x00, 0xff, 0x5c, 0xf1, 0x80, 0x02, 0x4e, 0xf3, 0x00, 0xda, +0x44, 0x50, 0x00, 0x05, 0x4c, 0x02, 0x80, 0x5a, 0x5c, 0xf0, 0x00, 0x06, 0x4e, 0xf2, 0x00, 0x1c, +0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0x80, 0x3e, 0x5c, 0xf0, 0x00, 0x03, 0x4e, 0xf2, 0x00, 0x0a, +0x4e, 0x02, 0x00, 0x94, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x7e, 0x48, 0x00, 0x00, 0x2c, +0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0x80, 0x34, 0x44, 0x50, 0x00, 0x04, 0x4c, 0x02, 0xc0, 0x74, +0x48, 0x00, 0x00, 0x34, 0x44, 0x50, 0x00, 0x0a, 0x4c, 0x02, 0x80, 0x4e, 0x5c, 0xf0, 0x00, 0x0b, +0x4e, 0xf2, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x06, 0x4c, 0x02, 0x80, 0x38, 0x44, 0x50, 0x00, 0x09, +0x4c, 0x02, 0xc0, 0x62, 0x48, 0x00, 0x00, 0x3a, 0x44, 0x30, 0x00, 0x0c, 0x4c, 0x01, 0x80, 0x4c, +0x40, 0xf0, 0x0c, 0x06, 0x4e, 0xf3, 0x00, 0x40, 0x44, 0x50, 0x00, 0x0d, 0x4c, 0x02, 0xc0, 0x54, +0x48, 0x00, 0x00, 0x4a, 0x46, 0x66, 0x01, 0x20, 0x58, 0x63, 0x01, 0x08, 0x48, 0x00, 0x00, 0x30, +0x46, 0x66, 0x01, 0x20, 0x58, 0x63, 0x01, 0x08, 0x48, 0x00, 0x00, 0x32, 0x46, 0x66, 0x01, 0x20, +0x58, 0x63, 0x01, 0x08, 0x48, 0x00, 0x00, 0x34, 0x46, 0x66, 0x01, 0x20, 0x46, 0x40, 0x02, 0x00, +0x58, 0x63, 0x01, 0x08, 0x48, 0x00, 0x00, 0x36, 0x46, 0x66, 0x01, 0x20, 0x46, 0x40, 0x40, 0x00, +0x58, 0x63, 0x01, 0x08, 0x48, 0x00, 0x00, 0x08, 0x46, 0x66, 0x01, 0x20, 0x46, 0x40, 0x40, 0x00, +0x58, 0x63, 0x01, 0x0c, 0x48, 0x00, 0x00, 0x40, 0x46, 0x66, 0x01, 0x20, 0x58, 0x63, 0x01, 0x0c, +0x48, 0x00, 0x00, 0x38, 0x46, 0x66, 0x01, 0x20, 0x58, 0x63, 0x01, 0x0c, 0x44, 0x40, 0x00, 0x20, +0x48, 0x00, 0x00, 0x32, 0x46, 0x66, 0x01, 0x20, 0x58, 0x63, 0x01, 0x0c, 0x44, 0x40, 0x04, 0x00, +0x48, 0x00, 0x00, 0x2a, 0x46, 0x66, 0x01, 0x20, 0x58, 0x63, 0x01, 0x0c, 0x44, 0x41, 0x00, 0x00, +0x48, 0x00, 0x00, 0x22, 0x46, 0x66, 0x01, 0x20, 0x46, 0x40, 0x02, 0x00, 0x58, 0x63, 0x01, 0x0c, +0x48, 0x00, 0x00, 0x1a, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x87, 0x00, 0x44, 0x20, 0x1e, 0xd8, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x46, 0x66, 0x01, 0x20, 0x58, 0x63, 0x01, 0x08, +0x44, 0x40, 0x00, 0x01, 0x40, 0x82, 0x04, 0x0c, 0x14, 0x83, 0x00, 0x00, 0x4e, 0x22, 0x00, 0x2e, +0x46, 0x90, 0x01, 0x03, 0x58, 0x94, 0x80, 0x84, 0x44, 0x00, 0x00, 0x01, 0x04, 0xa3, 0x00, 0x00, +0x4e, 0x73, 0x00, 0x16, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x07, 0x8f, 0x29, 0x4e, 0x03, 0x00, 0x1e, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x07, 0xb4, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, +0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x03, 0x80, 0x00, 0x48, 0x00, 0x00, 0x12, 0x4b, 0xe0, 0x24, 0x01, +0x40, 0x25, 0x20, 0x02, 0x50, 0x73, 0xff, 0xff, 0x4e, 0x23, 0xff, 0xe0, 0x48, 0x00, 0x00, 0x06, +0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x3a, 0x6f, 0xa8, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x47, 0x82, 0x67, +0x54, 0x70, 0x00, 0xff, 0x58, 0x81, 0x80, 0x00, 0x54, 0x60, 0x80, 0xff, 0x54, 0xa1, 0x00, 0xff, +0x40, 0xf3, 0x90, 0x06, 0x4e, 0xf3, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, 0x48, 0x00, 0x00, 0x9e, +0x4e, 0x33, 0x00, 0x14, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x87, 0x00, 0x44, 0x20, 0x1c, 0x7b, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x46, 0x90, 0x01, 0x0f, 0x04, 0x44, 0x82, 0x66, +0x51, 0xe3, 0x80, 0x80, 0x38, 0x02, 0x79, 0x01, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x0c, +0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x34, 0x82, 0x66, 0x40, 0x71, 0x9c, 0x00, 0x00, 0x23, 0x83, 0x80, +0x40, 0x11, 0x14, 0x08, 0x40, 0x10, 0x04, 0x00, 0x44, 0x50, 0x00, 0x06, 0x4c, 0x62, 0x80, 0x52, +0x5c, 0xf3, 0x00, 0x07, 0x4e, 0xf2, 0x00, 0x18, 0x5c, 0xf3, 0x00, 0x04, 0x4e, 0xf2, 0x00, 0x0a, +0x5c, 0xf3, 0x00, 0x02, 0x4e, 0xf2, 0x00, 0x2e, 0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x08, +0x44, 0x50, 0x00, 0x04, 0x4c, 0x62, 0x80, 0x2e, 0x44, 0x00, 0x00, 0x05, 0x4c, 0x60, 0x40, 0x42, +0x48, 0x00, 0x00, 0x24, 0x44, 0x50, 0x00, 0x09, 0x4c, 0x62, 0x80, 0x24, 0x5c, 0xf3, 0x00, 0x0a, +0x4e, 0xf2, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x07, 0x4c, 0x62, 0x80, 0x18, 0x44, 0x50, 0x00, 0x08, +0x4c, 0x62, 0xc0, 0x30, 0x48, 0x00, 0x00, 0x1c, 0x44, 0x00, 0x00, 0x0b, 0x4c, 0x60, 0x00, 0x12, +0x40, 0xf3, 0x00, 0x06, 0x4e, 0xf3, 0x00, 0x06, 0x44, 0x50, 0x00, 0x0c, 0x4c, 0x62, 0xc0, 0x22, +0x44, 0x20, 0x00, 0x20, 0x48, 0x00, 0x00, 0x08, 0x40, 0xa5, 0x10, 0x08, 0x40, 0x10, 0xa8, 0x00, +0x44, 0x20, 0x00, 0x10, 0x44, 0x70, 0x00, 0x00, 0x48, 0x00, 0x00, 0x18, 0x40, 0xa5, 0x14, 0x08, +0x40, 0x10, 0xa8, 0x00, 0x40, 0x22, 0x88, 0x08, 0x44, 0x70, 0x00, 0x00, 0x48, 0x00, 0x00, 0x16, +0x50, 0x10, 0x80, 0x10, 0x44, 0x20, 0x00, 0x10, 0x44, 0x70, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0a, +0x44, 0x20, 0x00, 0x00, 0x44, 0x70, 0x00, 0x01, 0x44, 0x50, 0x00, 0x06, 0x4c, 0x62, 0xc0, 0x06, +0x50, 0x04, 0x00, 0x10, 0x48, 0x00, 0x00, 0x04, 0x58, 0x04, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x84, 0xbc, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x03, 0x80, 0x00, 0x3a, 0x6f, 0xa8, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x47, 0x82, 0x67, +0x54, 0x80, 0x00, 0xff, 0x58, 0x71, 0x80, 0x00, 0x54, 0x60, 0x80, 0xff, 0x54, 0xa1, 0x00, 0xff, +0x40, 0xf4, 0x10, 0x06, 0x4e, 0xf3, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x98, +0x4e, 0x33, 0x00, 0x14, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x87, 0x00, 0x44, 0x20, 0x1c, 0x3b, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x46, 0x90, 0x01, 0x0f, 0x05, 0xe4, 0x82, 0x66, +0x50, 0x04, 0x00, 0x80, 0x38, 0x0f, 0x01, 0x01, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x0c, +0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x44, 0x82, 0x66, 0x44, 0x10, 0x00, 0x06, 0x40, 0x82, 0x20, 0x00, +0x00, 0x34, 0x03, 0x80, 0x40, 0x21, 0x94, 0x08, 0x40, 0x00, 0x08, 0x00, 0x4c, 0x60, 0x80, 0x4e, +0x5c, 0xf3, 0x00, 0x07, 0x4e, 0xf2, 0x00, 0x18, 0x5c, 0xf3, 0x00, 0x04, 0x4e, 0xf2, 0x00, 0x0a, +0x5c, 0xf3, 0x00, 0x02, 0x4e, 0xf2, 0x00, 0x2e, 0x44, 0x10, 0x00, 0x01, 0x48, 0x00, 0x00, 0x08, +0x44, 0x50, 0x00, 0x04, 0x4c, 0x62, 0x80, 0x2e, 0x44, 0x10, 0x00, 0x05, 0x4c, 0x60, 0xc0, 0x3c, +0x48, 0x00, 0x00, 0x24, 0x44, 0x50, 0x00, 0x09, 0x4c, 0x62, 0x80, 0x24, 0x5c, 0xf3, 0x00, 0x0a, +0x4e, 0xf2, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x07, 0x4c, 0x62, 0x80, 0x18, 0x44, 0x50, 0x00, 0x08, +0x4c, 0x62, 0xc0, 0x2a, 0x48, 0x00, 0x00, 0x1a, 0x44, 0x10, 0x00, 0x0b, 0x4c, 0x60, 0x80, 0x12, +0x40, 0xf3, 0x04, 0x06, 0x4e, 0xf3, 0x00, 0x06, 0x44, 0x50, 0x00, 0x0c, 0x4c, 0x62, 0xc0, 0x1c, +0x44, 0x20, 0x00, 0x20, 0x48, 0x00, 0x00, 0x1a, 0x40, 0xa5, 0x10, 0x08, 0x40, 0x00, 0x28, 0x00, +0x44, 0x20, 0x00, 0x10, 0x48, 0x00, 0x00, 0x12, 0x40, 0xa5, 0x14, 0x08, 0x40, 0x00, 0x28, 0x00, +0x40, 0x22, 0x88, 0x08, 0x48, 0x00, 0x00, 0x12, 0x50, 0x00, 0x00, 0x10, 0x44, 0x20, 0x00, 0x10, +0x48, 0x00, 0x00, 0x08, 0x44, 0x20, 0x00, 0x00, 0x44, 0x50, 0x00, 0x06, 0x4c, 0x62, 0xc0, 0x06, +0x50, 0x13, 0x80, 0x10, 0x48, 0x00, 0x00, 0x04, 0x58, 0x13, 0x80, 0x00, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x84, 0xbc, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x00, 0x3a, 0x6f, 0xa8, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x47, 0x82, 0x67, +0x54, 0xa0, 0x00, 0xff, 0x58, 0x60, 0x80, 0x00, 0x58, 0x81, 0x00, 0x00, 0x58, 0x71, 0x80, 0x00, +0x40, 0xf5, 0x10, 0x06, 0x4e, 0xf3, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x01, 0xd4, +0x4e, 0x13, 0x00, 0x14, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x87, 0x00, 0x44, 0x20, 0x1b, 0x4c, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x4e, 0x23, 0x00, 0x14, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x87, 0x00, 0x44, 0x20, 0x1b, 0x4d, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, +0x4e, 0x33, 0x00, 0x14, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x87, 0x00, 0x44, 0x20, 0x1b, 0x4e, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x46, 0x90, 0x00, 0x02, 0x58, 0x94, 0x84, 0xe4, +0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x23, 0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x24, 0x01, +0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x0c, 0x58, 0x04, 0x00, 0x00, 0x4b, 0xe0, 0x24, 0x01, +0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x0a, 0x58, 0x03, 0x80, 0x00, 0x4b, 0xe0, 0x24, 0x01, +0x46, 0x10, 0x30, 0x19, 0x40, 0x25, 0x04, 0x00, 0x40, 0x21, 0x14, 0x08, 0x04, 0x11, 0x00, 0x00, +0x42, 0x00, 0xf8, 0x0b, 0x4e, 0x02, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x00, 0x1f, +0x42, 0x50, 0xf4, 0x0b, 0x4e, 0x52, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, 0x10, 0x03, 0x80, 0x00, +0x43, 0xe0, 0xf0, 0x0b, 0x4f, 0xe2, 0x00, 0x06, 0x44, 0x50, 0x00, 0x01, 0x10, 0x53, 0x80, 0x01, +0x42, 0x00, 0xec, 0x0b, 0x4e, 0x02, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x80, 0x02, +0x42, 0x50, 0xe8, 0x0b, 0x4e, 0x52, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, 0x10, 0x03, 0x80, 0x03, +0x43, 0xe0, 0xe4, 0x0b, 0x4f, 0xe2, 0x00, 0x06, 0x44, 0x50, 0x00, 0x01, 0x10, 0x53, 0x80, 0x04, +0x40, 0x40, 0x9c, 0x08, 0x40, 0x32, 0x78, 0x09, 0x42, 0x00, 0xd8, 0x0b, 0x10, 0x33, 0x80, 0x07, +0x4e, 0x02, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, 0x10, 0x03, 0x80, 0x05, 0x40, 0x40, 0xa8, 0x08, +0x40, 0x32, 0x68, 0x09, 0x41, 0xe0, 0xa0, 0x09, 0x10, 0x33, 0x80, 0x08, 0x10, 0x13, 0x00, 0x04, +0x11, 0xe3, 0x00, 0x05, 0x50, 0x01, 0x00, 0x04, 0x05, 0xe0, 0x00, 0x00, 0x50, 0x11, 0x00, 0x08, +0x40, 0x3f, 0x60, 0x09, 0x40, 0x5f, 0x20, 0x09, 0x40, 0x4f, 0x40, 0x09, 0x10, 0x33, 0x00, 0x03, +0x10, 0x53, 0x00, 0x01, 0x10, 0x43, 0x00, 0x02, 0x11, 0xe3, 0x00, 0x00, 0x04, 0x10, 0x80, 0x00, +0x54, 0x30, 0x80, 0x80, 0x4e, 0x32, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, 0x10, 0x03, 0x80, 0x06, +0x54, 0x40, 0x80, 0x78, 0x40, 0x32, 0x0c, 0x09, 0x55, 0xe0, 0x82, 0x00, 0x10, 0x33, 0x80, 0x09, +0x4f, 0xe2, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, 0x10, 0x73, 0x00, 0x07, 0x54, 0x50, 0x81, 0x00, +0x4e, 0x52, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, 0x10, 0x03, 0x00, 0x06, 0x55, 0xe0, 0xc0, 0x00, +0x4f, 0xe2, 0x00, 0x06, 0x44, 0x30, 0x00, 0x01, 0x10, 0x33, 0x00, 0x09, 0x54, 0x40, 0x84, 0x00, +0x4e, 0x42, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, 0x10, 0x73, 0x00, 0x08, 0x40, 0x50, 0xc0, 0x08, +0x40, 0x52, 0xfc, 0x09, 0x4e, 0x52, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x00, 0x0a, +0x40, 0x30, 0xbc, 0x08, 0x40, 0x31, 0xfc, 0x09, 0x4e, 0x32, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, +0x10, 0x73, 0x00, 0x0b, 0x40, 0x50, 0xb8, 0x08, 0x40, 0x52, 0xfc, 0x09, 0x4e, 0x52, 0x00, 0x06, +0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x00, 0x0c, 0x40, 0x40, 0xb4, 0x08, 0x40, 0x42, 0x7c, 0x09, +0x4e, 0x42, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, 0x10, 0x73, 0x00, 0x0d, 0x42, 0x50, 0xcc, 0x0b, +0x4e, 0x52, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x00, 0x0e, 0x42, 0x40, 0xd0, 0x0b, +0x4e, 0x42, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, 0x10, 0x73, 0x00, 0x0f, 0x42, 0x50, 0xd4, 0x0b, +0x4e, 0x52, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x00, 0x10, 0x42, 0x30, 0xd8, 0x0b, +0x4e, 0x32, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, 0x10, 0x73, 0x00, 0x11, 0x42, 0x50, 0xdc, 0x0b, +0x4e, 0x52, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x00, 0x12, 0x42, 0x40, 0xe0, 0x0b, +0x4e, 0x42, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, 0x10, 0x73, 0x00, 0x13, 0x42, 0x50, 0xe4, 0x0b, +0x4e, 0x52, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x00, 0x14, 0x42, 0x40, 0xec, 0x0b, +0x4e, 0x42, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, 0x10, 0x73, 0x00, 0x15, 0x42, 0x50, 0xf0, 0x0b, +0x4e, 0x52, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x00, 0x16, 0x42, 0x30, 0xf4, 0x0b, +0x4e, 0x32, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, 0x10, 0x73, 0x00, 0x17, 0x42, 0x50, 0xf8, 0x0b, +0x4e, 0x52, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, 0x11, 0xe3, 0x00, 0x18, 0x4e, 0x14, 0x00, 0x06, +0x44, 0x30, 0x00, 0x01, 0x10, 0x33, 0x00, 0x1a, 0x54, 0x30, 0xb8, 0x00, 0x40, 0x51, 0xac, 0x09, +0x54, 0x70, 0x80, 0x07, 0x10, 0x73, 0x00, 0x21, 0x10, 0x53, 0x00, 0x22, 0x50, 0x01, 0x00, 0x0c, +0x04, 0x00, 0x00, 0x00, 0x41, 0xe0, 0x40, 0x08, 0x40, 0x30, 0x14, 0x08, 0x40, 0x4f, 0x6c, 0x09, +0x54, 0x50, 0x07, 0xff, 0x41, 0xe1, 0xd4, 0x09, 0x42, 0x10, 0x6c, 0x0b, 0x12, 0x54, 0x00, 0x00, +0x10, 0x44, 0x00, 0x08, 0x13, 0xe4, 0x00, 0x02, 0x4e, 0x12, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, +0x11, 0xe3, 0x00, 0x19, 0x42, 0x10, 0x70, 0x0b, 0x4e, 0x12, 0x00, 0x06, 0x44, 0x50, 0x00, 0x01, +0x10, 0x53, 0x00, 0x1b, 0x42, 0x70, 0x74, 0x0b, 0x4e, 0x72, 0x00, 0x06, 0x45, 0xe0, 0x00, 0x01, +0x11, 0xe3, 0x00, 0x1c, 0x42, 0x10, 0x78, 0x0b, 0x4e, 0x12, 0x00, 0x06, 0x44, 0x40, 0x00, 0x01, +0x10, 0x43, 0x00, 0x1d, 0x4e, 0x04, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, 0x10, 0x03, 0x00, 0x1e, +0x50, 0x01, 0x00, 0x10, 0x04, 0x10, 0x00, 0x00, 0x40, 0x30, 0xbc, 0x08, 0x40, 0x20, 0xa4, 0x08, +0x40, 0x21, 0x68, 0x09, 0x40, 0x51, 0xe8, 0x09, 0x40, 0x40, 0xdc, 0x09, 0x55, 0xe0, 0x87, 0xff, +0x12, 0x44, 0x00, 0x03, 0x13, 0xe4, 0x00, 0x01, 0x10, 0x54, 0x00, 0x09, 0x10, 0x24, 0x00, 0x0a, +0x44, 0x00, 0x00, 0x00, 0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x06, 0x03, 0x00, +0x04, 0x00, 0x00, 0x1f, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x06, 0x04, 0x00, 0x46, 0x10, 0x08, 0x00, +0x14, 0x10, 0x00, 0x01, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x16, 0x04, 0x00, 0x04, 0x00, 0x80, 0x00, +0x42, 0x00, 0x5c, 0x0b, 0x4a, 0x00, 0x78, 0x20, 0x54, 0x10, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x18, +0x4e, 0x12, 0x00, 0x0c, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, 0x04, 0x10, 0x00, 0x00, +0x58, 0x10, 0x80, 0x11, 0x48, 0x00, 0x00, 0x5c, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, +0x04, 0x10, 0x00, 0x00, 0x44, 0x2f, 0xff, 0xfe, 0x48, 0x00, 0x00, 0x50, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0xc0, 0x18, 0x4e, 0x12, 0x00, 0x0c, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, +0x04, 0x30, 0x00, 0x00, 0x58, 0x11, 0x80, 0x44, 0x48, 0x00, 0x00, 0x42, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x48, 0x04, 0x10, 0x00, 0x00, 0x44, 0x2f, 0xff, 0xfb, 0x48, 0x00, 0x00, 0x36, +0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x18, 0x4e, 0x12, 0x00, 0x0c, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x48, 0x46, 0x20, 0x01, 0x10, 0x04, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x1a, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, 0x04, 0x10, 0x00, 0x00, 0x44, 0x2e, 0xff, 0xff, +0x48, 0x00, 0x00, 0x1c, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x1c, 0x4e, 0x12, 0x00, 0x0e, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, 0x46, 0x20, 0x04, 0x40, 0x04, 0x10, 0x00, 0x00, +0x40, 0x10, 0x88, 0x04, 0x48, 0x00, 0x00, 0x0c, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, +0x04, 0x10, 0x00, 0x00, 0x44, 0x2b, 0xff, 0xff, 0x40, 0x10, 0x88, 0x02, 0x14, 0x10, 0x00, 0x00, +0x4a, 0x00, 0x78, 0x20, 0x54, 0x10, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x18, 0x4e, 0x12, 0x00, 0x0c, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, 0x04, 0x10, 0x00, 0x00, 0x58, 0x10, 0x80, 0x22, +0x48, 0x00, 0x00, 0x5e, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, 0x04, 0x10, 0x00, 0x00, +0x44, 0x2f, 0xff, 0xfd, 0x48, 0x00, 0x00, 0x52, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x18, +0x4e, 0x12, 0x00, 0x0c, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, 0x04, 0x30, 0x00, 0x00, +0x58, 0x11, 0x80, 0x88, 0x48, 0x00, 0x00, 0x44, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, +0x04, 0x10, 0x00, 0x00, 0x44, 0x2f, 0xff, 0xf7, 0x48, 0x00, 0x00, 0x38, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x02, 0xc0, 0x18, 0x4e, 0x12, 0x00, 0x0c, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, +0x46, 0x20, 0x02, 0x20, 0x04, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x1a, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x48, 0x04, 0x10, 0x00, 0x00, 0x44, 0x2d, 0xff, 0xff, 0x48, 0x00, 0x00, 0x1e, +0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x1e, 0x4e, 0x12, 0x00, 0x0e, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x48, 0x46, 0x20, 0x08, 0x80, 0x04, 0x10, 0x00, 0x00, 0x40, 0x10, 0x88, 0x04, +0x48, 0x00, 0x00, 0x0e, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x48, 0x46, 0x2f, 0xff, 0x7f, +0x04, 0x10, 0x00, 0x00, 0x58, 0x21, 0x0f, 0xff, 0x40, 0x10, 0x88, 0x02, 0x14, 0x10, 0x00, 0x00, +0x4a, 0x00, 0x78, 0x20, 0x54, 0x10, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x0a, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x60, 0x44, 0x20, 0x00, 0x40, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0xc0, 0x12, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x60, 0x44, 0x20, 0x40, 0x00, +0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x28, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x5c, +0x48, 0x00, 0x00, 0x20, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x0a, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x01, 0x14, 0x40, 0x22, 0x94, 0x08, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x03, +0x4c, 0x02, 0xc0, 0x12, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x14, 0x44, 0x20, 0x40, 0x00, +0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x08, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x10, +0x14, 0x20, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x54, 0x10, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x0a, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x60, 0x44, 0x20, 0x00, 0x20, 0x48, 0x00, 0x00, 0x0c, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x12, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x60, +0x44, 0x20, 0x20, 0x00, 0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x28, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x5c, 0x48, 0x00, 0x00, 0x20, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x0a, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x14, 0x40, 0x22, 0x90, 0x08, 0x48, 0x00, 0x00, 0x0c, +0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x12, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x14, +0x44, 0x20, 0x20, 0x00, 0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x08, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x01, 0x10, 0x14, 0x20, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0x3c, +0x46, 0x56, 0x03, 0x00, 0x58, 0x52, 0x80, 0x4c, 0x04, 0x62, 0x80, 0x00, 0x40, 0x63, 0x40, 0x09, +0x40, 0x63, 0x40, 0x08, 0x14, 0x62, 0x80, 0x00, 0x40, 0x31, 0x80, 0x13, 0x04, 0x72, 0x80, 0x00, +0x50, 0x61, 0x80, 0x03, 0x40, 0x33, 0x08, 0x09, 0x54, 0x10, 0x80, 0xff, 0x40, 0x61, 0xa0, 0x08, +0x40, 0x10, 0x9c, 0x04, 0x54, 0x00, 0x00, 0xff, 0x44, 0x70, 0x00, 0x40, 0x40, 0x30, 0x00, 0x1a, +0x40, 0x33, 0x80, 0x1b, 0x40, 0x10, 0x98, 0x04, 0x54, 0x21, 0x00, 0xff, 0x40, 0x63, 0x84, 0x08, +0x40, 0x01, 0x08, 0x1a, 0x40, 0x03, 0x08, 0x1b, 0x40, 0x10, 0x8c, 0x04, 0x40, 0x30, 0x80, 0x04, +0x14, 0x32, 0x80, 0x00, 0x50, 0x02, 0x80, 0x04, 0x04, 0x10, 0x00, 0x00, 0x44, 0x2f, 0xf0, 0xff, +0x40, 0x50, 0x88, 0x02, 0x14, 0x50, 0x00, 0x00, 0x54, 0x32, 0x00, 0xff, 0x04, 0x10, 0x00, 0x00, +0x40, 0x21, 0xa0, 0x08, 0x40, 0x41, 0x04, 0x04, 0x14, 0x40, 0x00, 0x00, 0x3a, 0x6f, 0x9c, 0x04, +0x4a, 0x00, 0x78, 0x20, 0x54, 0x10, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x0a, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x60, 0x44, 0x20, 0x00, 0x02, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0xc0, 0x12, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x60, 0x44, 0x20, 0x02, 0x00, +0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x2a, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x5c, +0x48, 0x00, 0x00, 0x22, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x0e, 0x46, 0x46, 0x03, 0x00, +0x14, 0x02, 0x00, 0x45, 0x4e, 0x12, 0x00, 0x1a, 0x58, 0x12, 0x00, 0x00, 0x14, 0x00, 0x80, 0x44, +0x48, 0x00, 0x00, 0x14, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x10, 0x46, 0x06, 0x03, 0x00, +0x44, 0x20, 0x02, 0x00, 0x14, 0x20, 0x00, 0x45, 0x4e, 0x12, 0x00, 0x08, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x01, 0x10, 0x14, 0x20, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x54, 0x10, 0x80, 0xff, +0x4e, 0x03, 0x00, 0x0a, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x60, 0x44, 0x20, 0x00, 0x04, +0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x12, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x60, 0x44, 0x20, 0x04, 0x00, 0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x28, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x5c, 0x48, 0x00, 0x00, 0x20, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x02, 0xc0, 0x0a, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x14, 0x44, 0x20, 0x00, 0x04, +0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x12, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x01, 0x14, 0x44, 0x20, 0x04, 0x00, 0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x08, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x10, 0x14, 0x20, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, +0x54, 0x10, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x0c, 0x40, 0x10, 0xc0, 0x08, 0x46, 0x06, 0x03, 0x00, +0x42, 0x10, 0xfc, 0x08, 0x58, 0x00, 0x00, 0x28, 0x48, 0x00, 0x00, 0x2a, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0xc0, 0x0c, 0x40, 0x30, 0xc0, 0x08, 0x46, 0x06, 0x03, 0x00, 0x42, 0x11, 0xfc, 0x08, +0x58, 0x00, 0x00, 0x2c, 0x48, 0x00, 0x00, 0x1c, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x0c, +0x40, 0x50, 0xc0, 0x08, 0x46, 0x06, 0x03, 0x00, 0x42, 0x12, 0xfc, 0x08, 0x58, 0x00, 0x01, 0x00, +0x48, 0x00, 0x00, 0x0e, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x0c, 0x40, 0x10, 0xc0, 0x08, +0x46, 0x06, 0x03, 0x00, 0x42, 0x10, 0xfc, 0x08, 0x58, 0x00, 0x01, 0x04, 0x14, 0x10, 0x00, 0x00, +0x4a, 0x00, 0x78, 0x20, 0x54, 0x10, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x0a, 0x46, 0x26, 0x03, 0x00, +0x46, 0x01, 0x00, 0x00, 0x58, 0x21, 0x00, 0x60, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0xc0, 0x12, 0x46, 0x26, 0x03, 0x00, 0x46, 0x04, 0x00, 0x00, 0x58, 0x21, 0x00, 0x60, +0x14, 0x01, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x28, 0x46, 0x16, 0x03, 0x00, 0x58, 0x10, 0x80, 0x5c, +0x48, 0x00, 0x00, 0x20, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x0a, 0x46, 0x26, 0x03, 0x00, +0x46, 0x01, 0x00, 0x00, 0x58, 0x21, 0x01, 0x14, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x03, +0x4c, 0x02, 0xc0, 0x12, 0x46, 0x26, 0x03, 0x00, 0x46, 0x04, 0x00, 0x00, 0x58, 0x21, 0x01, 0x14, +0x14, 0x01, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x08, 0x46, 0x16, 0x03, 0x00, 0x58, 0x10, 0x81, 0x10, +0x14, 0x00, 0x80, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x54, 0x10, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x14, +0x46, 0x06, 0x01, 0x40, 0x58, 0x00, 0x00, 0x80, 0x04, 0x40, 0x00, 0x00, 0x42, 0x22, 0x08, 0x09, +0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x4c, 0x04, 0x10, 0x00, 0x00, 0x58, 0x10, 0x80, 0x04, +0x48, 0x00, 0x00, 0x44, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x14, 0x46, 0x06, 0x01, 0x40, +0x58, 0x00, 0x00, 0x80, 0x04, 0x40, 0x00, 0x00, 0x42, 0x22, 0x10, 0x09, 0x14, 0x20, 0x00, 0x00, +0x4e, 0x12, 0x00, 0x36, 0x04, 0x10, 0x00, 0x00, 0x58, 0x10, 0x80, 0x10, 0x48, 0x00, 0x00, 0x2e, +0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x14, 0x46, 0x06, 0x01, 0x40, 0x58, 0x00, 0x00, 0x80, +0x04, 0x40, 0x00, 0x00, 0x42, 0x22, 0x40, 0x09, 0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x20, +0x04, 0x10, 0x00, 0x00, 0x44, 0x21, 0x00, 0x00, 0x48, 0x00, 0x00, 0x16, 0x44, 0x50, 0x00, 0x03, +0x4c, 0x02, 0xc0, 0x16, 0x46, 0x06, 0x01, 0x40, 0x58, 0x00, 0x00, 0x80, 0x04, 0x40, 0x00, 0x00, +0x42, 0x22, 0x48, 0x09, 0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x0a, 0x04, 0x10, 0x00, 0x00, +0x44, 0x24, 0x00, 0x00, 0x40, 0x10, 0x88, 0x04, 0x14, 0x10, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, +0x40, 0x10, 0x80, 0x13, 0x4e, 0x03, 0x00, 0x0e, 0x46, 0x46, 0x01, 0x40, 0x04, 0x32, 0x00, 0x13, +0x40, 0x21, 0xb0, 0x09, 0x40, 0x21, 0x30, 0x08, 0x40, 0x20, 0x88, 0x04, 0x48, 0x00, 0x00, 0x3e, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x12, 0x46, 0x46, 0x01, 0x40, 0x04, 0x02, 0x00, 0x13, +0x46, 0x2f, 0x00, 0x0f, 0x58, 0x21, 0x0f, 0xff, 0x40, 0x10, 0xc0, 0x08, 0x40, 0x30, 0x08, 0x02, +0x40, 0x20, 0x8c, 0x04, 0x48, 0x00, 0x00, 0x2a, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x0e, +0x46, 0x46, 0x01, 0x40, 0x04, 0x22, 0x00, 0x14, 0x40, 0x31, 0x30, 0x09, 0x40, 0x31, 0xb0, 0x08, +0x40, 0x20, 0x8c, 0x04, 0x48, 0x00, 0x00, 0x24, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x12, +0x46, 0x46, 0x01, 0x40, 0x04, 0x02, 0x00, 0x14, 0x46, 0x2f, 0x00, 0x0f, 0x58, 0x21, 0x0f, 0xff, +0x40, 0x10, 0xc0, 0x08, 0x40, 0x30, 0x08, 0x02, 0x40, 0x20, 0x8c, 0x04, 0x48, 0x00, 0x00, 0x10, +0x5c, 0xf0, 0x00, 0x02, 0x4e, 0xf2, 0x00, 0x08, 0x46, 0x06, 0x01, 0x40, 0x58, 0x00, 0x00, 0x4c, +0x48, 0x00, 0x00, 0x0a, 0x5c, 0xf0, 0x00, 0x04, 0x4e, 0xf2, 0x00, 0x08, 0x46, 0x06, 0x01, 0x40, +0x58, 0x00, 0x00, 0x50, 0x14, 0x20, 0x00, 0x00, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x54, 0x10, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x0a, 0x46, 0x26, 0x03, 0x00, +0x46, 0x00, 0x80, 0x00, 0x58, 0x21, 0x00, 0x60, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0xc0, 0x12, 0x46, 0x26, 0x03, 0x00, 0x46, 0x02, 0x00, 0x00, 0x58, 0x21, 0x00, 0x60, +0x14, 0x01, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x3c, 0x46, 0x16, 0x03, 0x00, 0x58, 0x10, 0x80, 0x5c, +0x48, 0x00, 0x00, 0x20, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x0a, 0x46, 0x26, 0x03, 0x00, +0x46, 0x00, 0x80, 0x00, 0x58, 0x21, 0x01, 0x14, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x03, +0x4c, 0x02, 0xc0, 0x14, 0x46, 0x26, 0x03, 0x00, 0x46, 0x02, 0x00, 0x00, 0x58, 0x21, 0x01, 0x14, +0x14, 0x01, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x1c, 0x46, 0x16, 0x03, 0x00, 0x58, 0x10, 0x81, 0x10, +0x14, 0x00, 0x80, 0x00, 0x48, 0x00, 0x00, 0x14, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, +0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x87, 0xe8, 0x44, 0x20, 0x13, 0x40, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x5c, 0xf0, 0x00, 0x04, 0x4e, 0xf3, 0x00, 0x14, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, +0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x87, 0xe8, 0x44, 0x20, 0x11, 0xec, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x2a, +0x44, 0x00, 0x00, 0x01, 0x4c, 0x10, 0x00, 0x1a, 0x4e, 0x12, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x12, 0x80, 0x1a, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x12, 0xc0, 0x9e, 0x48, 0x00, 0x00, 0x08, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x94, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x7c, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x10, +0x48, 0x00, 0x00, 0x7e, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x80, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x28, 0x4c, 0x10, 0x00, 0x1a, 0x4e, 0x12, 0x00, 0x0c, +0x44, 0x50, 0x00, 0x02, 0x4c, 0x12, 0x80, 0x1a, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x12, 0xc0, 0x74, +0x48, 0x00, 0x00, 0x08, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x14, 0x48, 0x00, 0x00, 0x6a, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x14, 0x48, 0x00, 0x00, 0x52, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x14, 0x48, 0x00, 0x00, 0x54, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x14, +0x48, 0x00, 0x00, 0x56, 0x44, 0x20, 0x00, 0x02, 0x4c, 0x01, 0x40, 0x28, 0x44, 0x00, 0x00, 0x01, +0x4c, 0x10, 0x00, 0x18, 0x4e, 0x12, 0x00, 0x0a, 0x4c, 0x11, 0x00, 0x1a, 0x44, 0x50, 0x00, 0x03, +0x4c, 0x12, 0xc0, 0x4a, 0x48, 0x00, 0x00, 0x08, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0xf8, +0x48, 0x00, 0x00, 0x40, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0xf8, 0x48, 0x00, 0x00, 0x28, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0xf8, 0x48, 0x00, 0x00, 0x2a, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0xf8, 0x48, 0x00, 0x00, 0x2c, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x12, 0x80, 0x1c, +0x4e, 0x12, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x12, 0x80, 0x1e, 0x44, 0x50, 0x00, 0x03, +0x4c, 0x12, 0xc0, 0x22, 0x48, 0x00, 0x00, 0x08, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0xfc, +0x48, 0x00, 0x00, 0x18, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0xfc, 0x44, 0x10, 0x00, 0x0c, +0x48, 0x00, 0x00, 0x10, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0xfc, 0x44, 0x10, 0x00, 0x04, +0x48, 0x00, 0x00, 0x08, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0xfc, 0x44, 0x10, 0x00, 0x08, +0x14, 0x10, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xa8, 0xbc, 0x54, 0x31, 0x80, 0xff, 0x58, 0x60, 0x00, 0x00, 0x40, 0x70, 0x80, 0x13, +0x54, 0x91, 0x00, 0xff, 0x54, 0x82, 0x00, 0xff, 0x54, 0xa2, 0x80, 0xff, 0x5c, 0xf1, 0x80, 0x10, +0x4e, 0xf3, 0x00, 0x14, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x87, 0xe8, 0x44, 0x20, 0x0f, 0xbc, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x5c, 0xf4, 0x00, 0x08, 0x4e, 0xf3, 0x00, 0x14, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x87, 0xe8, +0x44, 0x20, 0x0f, 0xbd, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x08, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x00, 0x34, +0x48, 0x00, 0x00, 0x1e, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x08, 0x46, 0x06, 0x03, 0x00, +0x58, 0x00, 0x00, 0x38, 0x48, 0x00, 0x00, 0x14, 0x44, 0x00, 0x00, 0x02, 0x4c, 0x60, 0x40, 0x08, +0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x08, 0x48, 0x00, 0x00, 0x0a, 0x44, 0x10, 0x00, 0x03, +0x4c, 0x60, 0xc0, 0x24, 0x46, 0x06, 0x03, 0x00, 0x58, 0x00, 0x01, 0x0c, 0x40, 0x54, 0xc0, 0x08, +0x46, 0x20, 0xf0, 0x00, 0x40, 0x42, 0x9c, 0x04, 0x41, 0xe1, 0xe0, 0x08, 0x46, 0x57, 0x00, 0x00, +0x40, 0x1f, 0x08, 0x02, 0x41, 0xe4, 0x70, 0x08, 0x40, 0x12, 0x04, 0x04, 0x40, 0x4f, 0x14, 0x02, +0x04, 0x20, 0x00, 0x00, 0x41, 0xe0, 0x90, 0x04, 0x40, 0x21, 0x7c, 0x09, 0x40, 0x21, 0x7c, 0x08, +0x14, 0x20, 0x00, 0x00, 0x15, 0xe0, 0x00, 0x00, 0x4e, 0x32, 0x00, 0x0c, 0x4e, 0x72, 0x00, 0x0a, +0x4e, 0xa2, 0x00, 0x08, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x48, 0x00, 0x00, 0x06, +0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x88, 0x44, +0x4b, 0xe0, 0x3c, 0x01, 0x4e, 0x82, 0x00, 0x0e, 0x4e, 0x92, 0x00, 0x0c, 0x4e, 0x72, 0x00, 0x0a, +0x4e, 0xa2, 0x00, 0x08, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x48, 0x00, 0x00, 0x06, +0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x88, 0xcc, +0x4b, 0xe0, 0x3c, 0x01, 0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, +0x54, 0x10, 0x80, 0xff, 0x54, 0x00, 0x00, 0xff, 0x54, 0x21, 0x00, 0xff, 0x40, 0x31, 0x80, 0x13, +0x54, 0x42, 0x00, 0xff, 0x5c, 0xf0, 0x80, 0x40, 0x4e, 0xf3, 0x00, 0x14, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x87, 0xe8, 0x44, 0x20, 0x0f, 0x16, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, +0x50, 0x61, 0x80, 0x03, 0x40, 0x63, 0x08, 0x09, 0x5c, 0xf3, 0x01, 0x00, 0x4e, 0xf3, 0x00, 0x14, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x87, 0xe8, +0x44, 0x20, 0x0f, 0x17, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x00, 0x5c, 0xf2, 0x00, 0x40, 0x4e, 0xf3, 0x00, 0x14, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x87, 0xe8, 0x44, 0x20, 0x0f, 0x18, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, +0x47, 0xe6, 0x03, 0x00, 0x59, 0xef, 0x00, 0x4c, 0x04, 0x5f, 0x00, 0x00, 0x40, 0x30, 0xc0, 0x08, +0x40, 0x82, 0x80, 0x13, 0x14, 0x8f, 0x00, 0x00, 0x46, 0x50, 0x04, 0x00, 0x04, 0x7f, 0x00, 0x00, +0x40, 0x81, 0x9c, 0x04, 0x40, 0x63, 0x60, 0x08, 0x46, 0x10, 0x08, 0x00, 0x40, 0x70, 0x00, 0x1a, +0x40, 0x72, 0x80, 0x1b, 0x40, 0x34, 0x18, 0x04, 0x40, 0x01, 0x08, 0x1a, 0x40, 0x00, 0x88, 0x1b, +0x40, 0x61, 0x9c, 0x04, 0x40, 0x63, 0x00, 0x04, 0x14, 0x6f, 0x00, 0x00, 0x50, 0x0f, 0x00, 0x04, +0x04, 0x50, 0x00, 0x00, 0x40, 0x32, 0x98, 0x09, 0x40, 0x31, 0x98, 0x08, 0x14, 0x30, 0x00, 0x00, +0x04, 0x10, 0x00, 0x00, 0x40, 0x42, 0x04, 0x04, 0x14, 0x40, 0x00, 0x00, 0x3a, 0x6f, 0xa0, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x40, 0x10, 0x78, 0x09, +0x4e, 0x12, 0x00, 0x14, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x87, 0xe8, 0x44, 0x20, 0x05, 0xc5, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x46, 0x16, 0x03, 0x00, 0x04, 0x20, 0x80, 0x1f, +0x40, 0x41, 0x08, 0x05, 0x04, 0x30, 0x80, 0x1f, 0x40, 0xf1, 0x88, 0x06, 0x4e, 0xf3, 0x00, 0x06, +0x40, 0x31, 0x88, 0x01, 0x48, 0x00, 0x00, 0x04, 0x40, 0x32, 0x0c, 0x00, 0x40, 0xf1, 0x80, 0x06, +0x4e, 0xf3, 0xff, 0xf2, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x4e, 0x03, 0x00, 0x1c, 0x46, 0x66, 0x03, 0x00, +0x58, 0x70, 0x00, 0x00, 0x46, 0x90, 0x01, 0x03, 0x58, 0x94, 0x80, 0x84, 0x04, 0x83, 0x00, 0x0a, +0x42, 0x14, 0x74, 0x0b, 0x50, 0x73, 0x80, 0x01, 0x44, 0x00, 0x00, 0x01, 0x4e, 0x12, 0x00, 0x66, +0x4b, 0xe0, 0x24, 0x01, 0x44, 0x50, 0x00, 0x14, 0x4c, 0x72, 0xff, 0xf2, 0x48, 0x00, 0x00, 0x5e, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x1c, 0x46, 0x76, 0x03, 0x00, 0x44, 0x60, 0x00, 0x00, +0x46, 0x90, 0x01, 0x03, 0x58, 0x94, 0x80, 0x84, 0x04, 0x83, 0x80, 0x0b, 0x42, 0x44, 0x74, 0x0b, +0x50, 0x63, 0x00, 0x01, 0x44, 0x00, 0x00, 0x01, 0x4e, 0x42, 0x00, 0x48, 0x4b, 0xe0, 0x24, 0x01, +0x44, 0x50, 0x00, 0x14, 0x4c, 0x62, 0xff, 0xf2, 0x48, 0x00, 0x00, 0x40, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x02, 0xc0, 0x1c, 0x46, 0x76, 0x03, 0x00, 0x44, 0x60, 0x00, 0x00, 0x46, 0x90, 0x01, 0x03, +0x58, 0x94, 0x80, 0x84, 0x04, 0x83, 0x80, 0x40, 0x43, 0xe4, 0x74, 0x0b, 0x50, 0x63, 0x00, 0x01, +0x44, 0x00, 0x00, 0x01, 0x4f, 0xe2, 0x00, 0x2a, 0x4b, 0xe0, 0x24, 0x01, 0x44, 0x50, 0x00, 0x14, +0x4c, 0x62, 0xff, 0xf2, 0x48, 0x00, 0x00, 0x22, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0x80, 0x06, +0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x1c, 0x46, 0x76, 0x03, 0x00, 0x44, 0x60, 0x00, 0x00, +0x46, 0x90, 0x01, 0x03, 0x58, 0x94, 0x80, 0x84, 0x04, 0x83, 0x80, 0x41, 0x42, 0x34, 0x74, 0x0b, +0x50, 0x63, 0x00, 0x01, 0x44, 0x00, 0x00, 0x01, 0x4e, 0x32, 0x00, 0x08, 0x4b, 0xe0, 0x24, 0x01, +0x44, 0x50, 0x00, 0x14, 0x4c, 0x62, 0xff, 0xf2, 0x40, 0x04, 0x00, 0x13, 0x51, 0xff, 0x80, 0x04, +0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x54, 0x10, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x26, 0x46, 0x26, 0x03, 0x00, 0x58, 0x21, 0x00, 0x34, +0x04, 0x51, 0x00, 0x00, 0x42, 0x32, 0xfc, 0x09, 0x14, 0x31, 0x00, 0x00, 0x4e, 0x12, 0x00, 0xa4, +0x05, 0xe1, 0x00, 0x00, 0x40, 0x1f, 0x00, 0x13, 0x4e, 0x13, 0x00, 0x8c, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x87, 0xe8, 0x44, 0x20, 0x10, 0x36, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x26, 0x46, 0x26, 0x03, 0x00, 0x58, 0x21, 0x00, 0x38, +0x04, 0x51, 0x00, 0x00, 0x42, 0x32, 0xfc, 0x09, 0x14, 0x31, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x7c, +0x05, 0xe1, 0x00, 0x00, 0x40, 0x1f, 0x00, 0x13, 0x4e, 0x13, 0x00, 0x64, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x87, 0xe8, 0x44, 0x20, 0x10, 0x3d, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, +0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0xc0, 0x26, 0x46, 0x26, 0x03, 0x00, 0x58, 0x21, 0x01, 0x08, +0x04, 0x51, 0x00, 0x00, 0x42, 0x32, 0xfc, 0x09, 0x14, 0x31, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x54, +0x05, 0xe1, 0x00, 0x00, 0x40, 0x1f, 0x00, 0x13, 0x4e, 0x13, 0x00, 0x3c, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x87, 0xe8, 0x44, 0x20, 0x10, 0x44, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, +0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x2e, 0x46, 0x26, 0x03, 0x00, 0x58, 0x21, 0x01, 0x0c, +0x04, 0x51, 0x00, 0x00, 0x42, 0x32, 0xfc, 0x09, 0x14, 0x31, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x2c, +0x05, 0xe1, 0x00, 0x00, 0x40, 0x1f, 0x00, 0x13, 0x4e, 0x13, 0x00, 0x14, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x87, 0xe8, 0x44, 0x20, 0x10, 0x4b, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, +0x04, 0x51, 0x00, 0x00, 0x42, 0x32, 0xfc, 0x08, 0x14, 0x31, 0x00, 0x00, 0x48, 0x00, 0x00, 0x04, +0x4e, 0x12, 0x00, 0x0a, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x80, 0xf0, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x46, 0xf0, 0x01, 0x0f, +0x04, 0x27, 0x82, 0x98, 0x46, 0x36, 0x04, 0x00, 0x46, 0x10, 0x08, 0x00, 0x14, 0x2f, 0x80, 0x01, +0x14, 0x11, 0x80, 0x02, 0x46, 0x00, 0x00, 0x01, 0x58, 0x00, 0x08, 0x4c, 0x58, 0x81, 0x80, 0x00, +0x4b, 0xe0, 0x00, 0x01, 0x44, 0x60, 0x00, 0x1e, 0x45, 0xc0, 0x03, 0xe8, 0x44, 0xa0, 0x00, 0x07, +0x58, 0x90, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x46, 0x76, 0x04, 0x00, 0x42, 0x50, 0x5c, 0x0b, +0x4e, 0x52, 0x00, 0x46, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x88, 0x4c, 0x4b, 0xe0, 0x3c, 0x01, +0x40, 0x00, 0x24, 0x01, 0x44, 0x40, 0x00, 0x64, 0x40, 0x20, 0x10, 0x37, 0x05, 0xef, 0x80, 0x01, +0x02, 0x1f, 0x00, 0x00, 0x45, 0xe0, 0x27, 0x10, 0x50, 0x10, 0x93, 0x88, 0x40, 0x50, 0x70, 0x77, +0x42, 0x20, 0x18, 0x73, 0x42, 0x22, 0xa8, 0x73, 0x44, 0x50, 0x00, 0x0a, 0x40, 0x30, 0x78, 0x97, +0x40, 0x00, 0x14, 0x97, 0x44, 0x40, 0x00, 0x05, 0x40, 0x51, 0x80, 0x00, 0x42, 0x22, 0x90, 0x73, +0x40, 0xf0, 0x88, 0x06, 0x4e, 0xf2, 0xff, 0xd0, 0x04, 0x23, 0x80, 0x00, 0x47, 0xe0, 0x08, 0x00, +0x40, 0x01, 0x78, 0x02, 0x4e, 0x02, 0x00, 0x16, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, +0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x87, 0xe8, 0x44, 0x20, 0x0c, 0x92, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, +0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x54, 0x00, 0x00, 0xff, +0x40, 0x00, 0x20, 0x08, 0x54, 0x10, 0x80, 0xff, 0x40, 0x20, 0x00, 0x13, 0x4e, 0x12, 0x00, 0x06, +0x58, 0x11, 0x00, 0x01, 0x48, 0x00, 0x00, 0x06, 0x44, 0x20, 0xff, 0xfe, 0x40, 0x10, 0x08, 0x02, +0x46, 0x36, 0x01, 0x20, 0x44, 0x00, 0x00, 0x00, 0x14, 0x11, 0x80, 0x4d, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x54, 0x10, 0x80, 0xff, 0x54, 0x21, 0x00, 0xff, 0x54, 0x31, 0x80, 0xff, +0x54, 0x42, 0x00, 0xff, 0x40, 0x52, 0x80, 0x13, 0x00, 0x9f, 0x80, 0x1c, 0x00, 0xaf, 0x80, 0x20, +0x03, 0xcf, 0x80, 0x12, 0x00, 0x7f, 0x80, 0x28, 0x5c, 0xf0, 0x00, 0x04, 0x4e, 0xf3, 0x00, 0x06, +0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x7a, 0x40, 0x82, 0x40, 0x08, 0x46, 0x48, 0x00, 0x24, +0x40, 0x60, 0x0c, 0x08, 0x58, 0x42, 0x00, 0x10, 0x51, 0xe2, 0x00, 0x04, 0x40, 0x01, 0xe0, 0x08, +0x40, 0x33, 0x10, 0x00, 0x40, 0x43, 0x78, 0x00, 0x45, 0xe0, 0x00, 0x01, 0x4c, 0x1f, 0x40, 0x3c, +0x40, 0x54, 0x14, 0x04, 0x40, 0xa5, 0x40, 0x08, 0x40, 0x02, 0x80, 0x04, 0x40, 0xa5, 0x70, 0x04, +0x40, 0x94, 0xe0, 0x08, 0x14, 0x01, 0x80, 0x00, 0x40, 0x95, 0x24, 0x04, 0x40, 0x13, 0x84, 0x03, +0x44, 0x00, 0x00, 0x02, 0x44, 0x50, 0x00, 0x00, 0x40, 0x32, 0x84, 0x1b, 0x40, 0x30, 0x04, 0x1a, +0x14, 0x92, 0x00, 0x00, 0x4c, 0x2f, 0x40, 0x04, 0x40, 0x31, 0xf8, 0x04, 0x46, 0x48, 0x00, 0x24, +0x44, 0x10, 0x00, 0x2f, 0x40, 0x20, 0x98, 0x0c, 0x04, 0x52, 0x00, 0x00, 0x40, 0x01, 0x08, 0x05, +0x40, 0x10, 0x14, 0x02, 0x14, 0x12, 0x00, 0x00, 0x58, 0x31, 0x80, 0x80, 0x04, 0x22, 0x00, 0x00, +0x40, 0x61, 0x98, 0x0c, 0x40, 0x63, 0x08, 0x04, 0x14, 0x62, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, +0x48, 0x00, 0x00, 0x2c, 0x40, 0x24, 0x14, 0x04, 0x40, 0x11, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, +0x14, 0x11, 0x80, 0x00, 0x14, 0x02, 0x00, 0x00, 0x46, 0x48, 0x00, 0x24, 0x44, 0x50, 0x00, 0x2f, +0x04, 0x32, 0x00, 0x00, 0x40, 0x22, 0x98, 0x0c, 0x40, 0x11, 0x08, 0x05, 0x40, 0x50, 0x8c, 0x02, +0x14, 0x52, 0x00, 0x00, 0x56, 0x73, 0x80, 0x01, 0x44, 0x20, 0x00, 0x02, 0x40, 0x10, 0x1c, 0x1b, +0x40, 0x11, 0x1c, 0x1a, 0x04, 0x52, 0x00, 0x00, 0x58, 0x30, 0x80, 0x80, 0x40, 0x61, 0x98, 0x0c, +0x40, 0x63, 0x14, 0x04, 0x14, 0x62, 0x00, 0x00, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x9c, 0x3c, 0x54, 0x10, 0x80, 0xff, 0x54, 0x21, 0x00, 0xff, 0x54, 0x31, 0x80, 0xff, +0x54, 0x42, 0x00, 0xff, 0x5c, 0xf0, 0x00, 0x04, 0x4e, 0xf3, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, +0x48, 0x00, 0x00, 0x94, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0x80, 0x32, 0x44, 0x50, 0x00, 0x03, +0x4c, 0x02, 0x80, 0x42, 0x40, 0x50, 0xa0, 0x08, 0x44, 0x10, 0x00, 0x01, 0x4c, 0x00, 0x80, 0x12, +0x46, 0x18, 0x00, 0x24, 0x58, 0x10, 0x80, 0x04, 0x04, 0x60, 0x80, 0x00, 0x40, 0x21, 0x14, 0x04, +0x40, 0x53, 0x40, 0x09, 0x40, 0x52, 0xc0, 0x08, 0x14, 0x50, 0x80, 0x00, 0x48, 0x00, 0x00, 0x10, +0x46, 0x18, 0x00, 0x24, 0x58, 0x10, 0x80, 0x04, 0x04, 0x60, 0x80, 0x00, 0x40, 0x21, 0x14, 0x04, +0x40, 0x53, 0x00, 0x13, 0x14, 0x50, 0x80, 0x00, 0x40, 0x21, 0x40, 0x08, 0x04, 0x60, 0x80, 0x00, +0x40, 0x21, 0x18, 0x04, 0x14, 0x20, 0x80, 0x00, 0x48, 0x00, 0x00, 0x2c, 0x46, 0x58, 0x00, 0x24, +0x58, 0x52, 0x80, 0x08, 0x04, 0x62, 0x80, 0x00, 0x40, 0x63, 0x40, 0x09, 0x40, 0x63, 0x40, 0x08, +0x14, 0x62, 0x80, 0x00, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x21, 0x04, 0x04, 0x04, 0x62, 0x80, 0x00, +0x48, 0x00, 0x00, 0x14, 0x46, 0x58, 0x00, 0x24, 0x58, 0x52, 0x80, 0x08, 0x04, 0x62, 0x80, 0x00, +0x40, 0x63, 0x00, 0x13, 0x14, 0x62, 0x80, 0x00, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x21, 0x04, 0x04, +0x04, 0x62, 0x80, 0x00, 0x40, 0x21, 0x40, 0x08, 0x40, 0x21, 0x18, 0x04, 0x14, 0x22, 0x80, 0x00, +0x56, 0x31, 0x80, 0x01, 0x44, 0x10, 0x00, 0x02, 0x44, 0x50, 0x00, 0x00, 0x40, 0x22, 0x8c, 0x1b, +0x40, 0x20, 0x8c, 0x1a, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x42, 0xc0, 0x08, 0x58, 0x41, 0x00, 0x20, +0x42, 0x22, 0x08, 0x09, 0x48, 0x00, 0x00, 0x06, 0x58, 0x21, 0x00, 0x04, 0x42, 0x21, 0x14, 0x09, +0x46, 0x58, 0x00, 0x24, 0x40, 0x10, 0x0c, 0x08, 0x44, 0x40, 0x00, 0x2f, 0x40, 0x32, 0x04, 0x0c, +0x04, 0x42, 0x80, 0x00, 0x40, 0x31, 0x8c, 0x05, 0x40, 0x31, 0x90, 0x02, 0x14, 0x32, 0x80, 0x00, +0x58, 0x21, 0x00, 0x80, 0x04, 0x32, 0x80, 0x00, 0x40, 0x41, 0x04, 0x0c, 0x40, 0x02, 0x0c, 0x04, +0x14, 0x02, 0x80, 0x00, 0x44, 0x00, 0x00, 0x00, 0x3a, 0x6f, 0x9c, 0x04, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x54, 0x00, 0x00, 0xff, 0x14, 0x0f, 0x80, 0x01, +0x47, 0xc0, 0x00, 0x02, 0x59, 0xce, 0x04, 0x68, 0x46, 0x90, 0x01, 0x03, 0x58, 0x94, 0x8e, 0x00, +0x46, 0x80, 0x01, 0x04, 0x58, 0x84, 0x0a, 0x38, 0x46, 0x70, 0x01, 0x04, 0x58, 0x73, 0x8a, 0x88, +0x48, 0x00, 0x00, 0x18, 0x4b, 0xe0, 0x70, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x17, 0x89, 0xa4, +0x44, 0x50, 0x00, 0x01, 0x58, 0x03, 0x00, 0x00, 0x4c, 0x12, 0xc0, 0x0a, 0x4b, 0xe0, 0x20, 0x01, +0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x48, 0x00, 0x00, 0x04, 0x4b, 0xe0, 0x24, 0x01, +0x04, 0x1f, 0x80, 0x01, 0x44, 0x20, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x89, 0x4c, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x60, 0x00, 0x00, 0x44, 0x50, 0x0f, 0xff, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x08, 0x20, 0x4c, 0x62, 0xff, 0xd6, 0x51, 0xff, 0x80, 0x0c, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x46, 0x60, 0x01, 0x0f, 0x58, 0xa0, 0x00, 0x00, 0x54, 0x90, 0x00, 0xff, 0x47, 0xc0, 0x01, 0x06, +0x59, 0xce, 0x01, 0xf4, 0x48, 0x00, 0x00, 0x6a, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x8d, 0x28, +0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x70, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x22, 0x44, 0x00, 0x00, 0x01, +0x58, 0x30, 0x00, 0x00, 0x58, 0x14, 0x80, 0x00, 0x58, 0x24, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x8a, 0x74, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x07, 0x82, 0x68, +0x04, 0x30, 0x00, 0x00, 0x4e, 0x33, 0x00, 0x5e, 0x44, 0x10, 0x00, 0x0a, 0x46, 0xf0, 0x01, 0x08, +0x58, 0xf7, 0x8a, 0xa0, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x54, 0x04, 0x40, 0x00, 0x02, +0x44, 0x50, 0x00, 0xa0, 0x00, 0x12, 0x00, 0x05, 0x4c, 0x12, 0xc0, 0x38, 0x05, 0xe3, 0x02, 0x68, +0x04, 0x8f, 0x00, 0x0c, 0x50, 0x5f, 0x00, 0x30, 0x4c, 0x82, 0xc0, 0x0a, 0x4b, 0xe0, 0x70, 0x01, +0x46, 0x3c, 0x00, 0x00, 0x58, 0x51, 0x80, 0x9a, 0x4c, 0x02, 0xc0, 0x28, 0x05, 0xe3, 0x02, 0x68, +0x04, 0x5f, 0x00, 0x0d, 0x50, 0x8f, 0x00, 0x30, 0x14, 0x74, 0x00, 0x01, 0x14, 0x83, 0x80, 0x00, +0x14, 0x53, 0x80, 0x01, 0x14, 0x72, 0x80, 0x00, 0x04, 0x23, 0x02, 0x68, 0x04, 0x41, 0x00, 0x0e, +0x50, 0x12, 0x00, 0x01, 0x14, 0x11, 0x00, 0x0e, 0x04, 0x23, 0x02, 0x68, 0x04, 0x01, 0x00, 0x06, +0x4e, 0x03, 0x00, 0x0c, 0x50, 0x01, 0x00, 0x18, 0x44, 0x10, 0x00, 0x0a, 0x46, 0xf0, 0x01, 0x08, +0x58, 0xf7, 0x8a, 0xa0, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x14, 0x80, 0x00, 0x44, 0x20, 0x00, 0x00, +0x44, 0x00, 0x00, 0x01, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x89, 0x4c, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x50, 0x0f, 0xff, 0x58, 0x80, 0x00, 0x00, 0x58, 0x15, 0x00, 0x00, 0x4c, 0x02, 0xff, 0x86, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xe4, 0x46, 0x96, 0x03, 0x10, 0x58, 0x84, 0x80, 0x00, 0x58, 0x74, 0x00, 0x00, +0x58, 0x63, 0x80, 0x00, 0x58, 0x53, 0x00, 0x00, 0x14, 0x9f, 0x80, 0x01, 0x14, 0x8f, 0x80, 0x02, +0x14, 0x7f, 0x80, 0x03, 0x14, 0x6f, 0x80, 0x04, 0x14, 0x5f, 0x80, 0x05, 0x04, 0x4f, 0x80, 0x01, +0x04, 0x3f, 0x80, 0x02, 0x04, 0x2f, 0x80, 0x03, 0x04, 0x0f, 0x80, 0x04, 0x04, 0x1f, 0x80, 0x05, +0x59, 0xc2, 0x80, 0x00, 0x46, 0x8a, 0x00, 0x00, 0x46, 0xaa, 0x00, 0x00, 0x58, 0x31, 0x80, 0x08, +0x58, 0x21, 0x00, 0x04, 0x58, 0x00, 0x00, 0x0c, 0x58, 0x10, 0x80, 0x24, 0x14, 0x4f, 0x80, 0x01, +0x14, 0x3f, 0x80, 0x02, 0x14, 0x2f, 0x80, 0x03, 0x14, 0x0f, 0x80, 0x04, 0x14, 0x1f, 0x80, 0x05, +0x58, 0x84, 0x00, 0x08, 0x44, 0x90, 0x00, 0x00, 0x48, 0x00, 0x00, 0x40, 0x4e, 0x62, 0x00, 0x68, +0x55, 0xe3, 0x00, 0x01, 0x4f, 0xe2, 0x00, 0x10, 0x44, 0x00, 0x00, 0x01, 0x14, 0x04, 0x00, 0x00, +0x44, 0x00, 0x00, 0x00, 0x42, 0x63, 0x00, 0x09, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x87, 0xa8, +0x4b, 0xe0, 0x3c, 0x01, 0x54, 0x23, 0x00, 0x02, 0x4e, 0x22, 0x00, 0x10, 0x44, 0x40, 0x00, 0x02, +0x14, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, 0x42, 0x63, 0x04, 0x09, 0x46, 0xf0, 0x01, 0x03, +0x58, 0xf7, 0x87, 0x10, 0x4b, 0xe0, 0x3c, 0x01, 0x54, 0x63, 0x00, 0x08, 0x4e, 0x62, 0x00, 0x0e, +0x44, 0x50, 0x00, 0x08, 0x14, 0x54, 0x00, 0x00, 0x44, 0x00, 0x00, 0x03, 0x46, 0xf0, 0x01, 0x05, +0x58, 0xf7, 0x86, 0x70, 0x4b, 0xe0, 0x3c, 0x01, 0x50, 0x94, 0x80, 0x01, 0x54, 0x94, 0x80, 0xff, +0x45, 0xe0, 0x00, 0x03, 0x4c, 0x9f, 0x00, 0x2c, 0x04, 0x7f, 0x80, 0x01, 0x04, 0x6f, 0x80, 0x02, +0x04, 0x2f, 0x80, 0x03, 0x04, 0x5f, 0x80, 0x04, 0x04, 0x0f, 0x80, 0x05, 0x04, 0x13, 0x80, 0x00, +0x04, 0x73, 0x00, 0x00, 0x05, 0xe1, 0x00, 0x00, 0x04, 0x42, 0x80, 0x00, 0x04, 0x50, 0x00, 0x00, +0x04, 0x0e, 0x00, 0x0a, 0x04, 0x64, 0x00, 0x00, 0x04, 0x35, 0x00, 0x01, 0x40, 0x22, 0x78, 0x02, +0x40, 0x61, 0x98, 0x02, 0x4e, 0x23, 0xff, 0xa6, 0x40, 0x13, 0x84, 0x02, 0x4e, 0x13, 0xff, 0xa2, +0x40, 0x30, 0x14, 0x02, 0x4e, 0x33, 0xff, 0x9e, 0x48, 0xff, 0xff, 0x9a, 0x44, 0x00, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x80, 0xb4, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x1c, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xa4, +0x44, 0x40, 0x00, 0x80, 0x54, 0x30, 0x00, 0xff, 0x44, 0x50, 0x00, 0x01, 0x40, 0x62, 0x8c, 0x1b, +0x40, 0x62, 0x0c, 0x1a, 0x50, 0x0f, 0x80, 0x1c, 0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x23, +0x45, 0xc0, 0x00, 0x00, 0x14, 0x6f, 0x80, 0x05, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0xe4, +0x4b, 0xe0, 0x3c, 0x01, 0x15, 0xcf, 0x80, 0x04, 0x50, 0x6f, 0x80, 0x40, 0x50, 0xaf, 0x80, 0x48, +0x50, 0x9f, 0x80, 0x54, 0x50, 0x8f, 0x80, 0x42, 0x50, 0x7f, 0x80, 0x49, 0x04, 0x3f, 0x80, 0x04, +0x51, 0xcf, 0x80, 0x4c, 0x51, 0xef, 0x80, 0x50, 0x54, 0x01, 0x80, 0xff, 0x58, 0x13, 0x00, 0x00, +0x58, 0x25, 0x00, 0x00, 0x15, 0xcf, 0x80, 0x03, 0x15, 0xef, 0x80, 0x00, 0x51, 0xcf, 0x80, 0x44, +0x51, 0xef, 0x80, 0x4a, 0x58, 0x34, 0x80, 0x00, 0x58, 0x44, 0x00, 0x00, 0x58, 0x53, 0x80, 0x00, +0x15, 0xcf, 0x80, 0x01, 0x15, 0xef, 0x80, 0x02, 0x46, 0xf0, 0x01, 0x09, 0x58, 0xf7, 0x80, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x05, 0xcf, 0x80, 0x04, 0x44, 0x00, 0x00, 0x00, 0x50, 0x2e, 0x00, 0x01, +0x14, 0x2f, 0x80, 0x04, 0x05, 0xcf, 0x80, 0x05, 0x04, 0x1f, 0x80, 0x04, 0x12, 0x03, 0x00, 0x03, +0x40, 0xf0, 0xf0, 0x06, 0x4e, 0xf3, 0xff, 0xcc, 0x51, 0xff, 0x80, 0x5c, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x46, 0xf0, 0x01, 0x09, +0x58, 0xf7, 0x85, 0x9c, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x60, 0x01, 0x0f, 0x04, 0x03, 0x02, 0x64, +0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x03, 0xdc, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0xe4, +0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x03, 0x02, 0x64, 0x50, 0x00, 0x03, 0xb0, 0x44, 0x10, 0x00, 0x00, +0x50, 0x50, 0x7c, 0xdc, 0x50, 0x40, 0x00, 0x04, 0x50, 0x30, 0x00, 0x10, 0x50, 0x20, 0x00, 0x1c, +0x14, 0x10, 0x00, 0x09, 0x14, 0x50, 0x7f, 0x38, 0x14, 0x40, 0x00, 0x02, 0x14, 0x30, 0x00, 0x05, +0x14, 0x20, 0x00, 0x08, 0x14, 0x50, 0x7f, 0x37, 0x14, 0x10, 0x7f, 0x39, 0x14, 0x40, 0x00, 0x01, +0x14, 0x10, 0x00, 0x03, 0x14, 0x30, 0x00, 0x04, 0x14, 0x10, 0x00, 0x06, 0x14, 0x20, 0x00, 0x07, +0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x00, 0x01, 0x12, 0x58, 0x00, 0x00, 0x80, +0x44, 0x20, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x01, 0x14, 0x20, 0x00, 0x02, +0x50, 0x10, 0x00, 0x10, 0x58, 0x40, 0x00, 0x00, 0x14, 0x20, 0x80, 0x02, 0x04, 0x52, 0x00, 0x01, +0x14, 0x10, 0x00, 0x01, 0x14, 0x50, 0x80, 0x01, 0x14, 0x00, 0x80, 0x00, 0x14, 0x12, 0x80, 0x00, +0x50, 0x10, 0x80, 0x68, 0x04, 0x30, 0x00, 0x02, 0x50, 0x51, 0x80, 0x01, 0x50, 0x30, 0x06, 0x90, +0x14, 0x50, 0x00, 0x02, 0x4c, 0x11, 0xff, 0xea, 0x46, 0x00, 0x01, 0x11, 0x58, 0x00, 0x04, 0xb0, +0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x01, 0x14, 0x20, 0x00, 0x02, 0x50, 0x10, 0x00, 0x0c, +0x58, 0x40, 0x00, 0x00, 0x14, 0x20, 0x80, 0x02, 0x04, 0x52, 0x00, 0x01, 0x14, 0x10, 0x00, 0x01, +0x14, 0x50, 0x80, 0x01, 0x14, 0x00, 0x80, 0x00, 0x14, 0x12, 0x80, 0x00, 0x50, 0x10, 0x80, 0x5c, +0x04, 0x30, 0x00, 0x02, 0x50, 0x51, 0x80, 0x01, 0x50, 0x30, 0x05, 0xcc, 0x14, 0x50, 0x00, 0x02, +0x4c, 0x11, 0xff, 0xea, 0x46, 0x00, 0x01, 0x10, 0x58, 0x00, 0x0d, 0x38, 0x14, 0x00, 0x00, 0x00, +0x14, 0x00, 0x00, 0x01, 0x14, 0x20, 0x00, 0x02, 0x50, 0x10, 0x00, 0x10, 0x58, 0x40, 0x00, 0x00, +0x14, 0x20, 0x80, 0x02, 0x04, 0x52, 0x00, 0x01, 0x14, 0x10, 0x00, 0x01, 0x14, 0x50, 0x80, 0x01, +0x14, 0x00, 0x80, 0x00, 0x14, 0x12, 0x80, 0x00, 0x50, 0x10, 0x80, 0x68, 0x04, 0x30, 0x00, 0x02, +0x50, 0x51, 0x80, 0x01, 0x50, 0x30, 0x03, 0x50, 0x14, 0x50, 0x00, 0x02, 0x4c, 0x11, 0xff, 0xea, +0x4a, 0x00, 0x78, 0x20, 0x54, 0x00, 0x00, 0xff, 0x40, 0x10, 0x00, 0x10, 0x4e, 0x14, 0x00, 0x06, +0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x30, 0x00, 0x0c, 0x42, 0x00, 0x0c, 0x24, +0x46, 0x20, 0x01, 0x11, 0x58, 0x21, 0x0a, 0x7c, 0x40, 0x00, 0x08, 0x00, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x46, 0x10, 0x01, 0x11, 0x58, 0x10, 0x84, 0xb0, +0x04, 0x60, 0x80, 0x00, 0x40, 0x70, 0x00, 0x13, 0x4c, 0x60, 0xc0, 0x06, 0x44, 0x60, 0x00, 0x00, +0x48, 0x00, 0x00, 0x24, 0x04, 0x53, 0x00, 0x01, 0x04, 0x33, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, +0x14, 0x51, 0x80, 0x01, 0x14, 0x32, 0x80, 0x00, 0x14, 0x43, 0x00, 0x01, 0x14, 0x43, 0x00, 0x00, +0x04, 0x20, 0x80, 0x02, 0x50, 0x01, 0x7f, 0xff, 0x14, 0x00, 0x80, 0x02, 0x4e, 0x62, 0x00, 0x0e, +0x58, 0x03, 0x80, 0x00, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x0c, 0x4b, 0xe0, 0x3c, 0x01, +0x14, 0x03, 0x00, 0x02, 0x12, 0x73, 0x00, 0x06, 0x58, 0x03, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x46, 0x30, 0x01, 0x12, 0x58, 0x31, 0x80, 0x80, 0x56, 0x10, 0x80, 0x01, 0x46, 0x40, 0x01, 0x10, +0x58, 0x42, 0x0d, 0x38, 0x40, 0x22, 0x04, 0x1a, 0x40, 0x21, 0x84, 0x1b, 0x04, 0x61, 0x00, 0x00, +0x40, 0x70, 0x00, 0x13, 0x4c, 0x61, 0x40, 0x06, 0x44, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0x24, +0x04, 0x13, 0x00, 0x01, 0x04, 0x33, 0x00, 0x00, 0x45, 0xe0, 0x00, 0x00, 0x14, 0x11, 0x80, 0x01, +0x14, 0x30, 0x80, 0x00, 0x15, 0xe3, 0x00, 0x01, 0x15, 0xe3, 0x00, 0x00, 0x04, 0x51, 0x00, 0x02, +0x50, 0x02, 0xff, 0xff, 0x14, 0x01, 0x00, 0x02, 0x4e, 0x62, 0x00, 0x0e, 0x58, 0x03, 0x80, 0x00, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x0c, 0x4b, 0xe0, 0x3c, 0x01, 0x14, 0x03, 0x00, 0x02, +0x12, 0x73, 0x00, 0x06, 0x58, 0x03, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x44, 0x10, 0x00, 0x00, +0x44, 0x20, 0x00, 0x28, 0x46, 0x00, 0x01, 0x11, 0x58, 0x00, 0x00, 0x88, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x84, 0xe4, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x2f, 0xff, 0xff, 0x46, 0x10, 0x01, 0x11, +0x58, 0x10, 0x80, 0xb0, 0x46, 0xf0, 0x01, 0x11, 0x14, 0x27, 0x80, 0x23, 0x46, 0xf0, 0x01, 0x11, +0x14, 0x17, 0x80, 0x22, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x40, 0x00, 0x00, 0x13, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x81, 0x4c, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x4e, 0x03, 0x00, 0x1a, +0x46, 0xf0, 0x01, 0x16, 0x00, 0x07, 0x8f, 0x29, 0x4e, 0x03, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x88, 0x2c, 0x44, 0x20, 0x02, 0xa5, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, +0x46, 0x10, 0x01, 0x11, 0x58, 0x10, 0x80, 0xb0, 0x40, 0xf0, 0x04, 0x06, 0x4e, 0xf3, 0x00, 0x2e, +0x50, 0x20, 0x83, 0xff, 0x40, 0xf1, 0x00, 0x06, 0x4e, 0xf3, 0x00, 0x28, 0x46, 0x10, 0x01, 0x11, +0x58, 0x10, 0x80, 0x88, 0x04, 0x40, 0x80, 0x00, 0x40, 0x30, 0x10, 0x01, 0x40, 0x01, 0x94, 0x09, +0x5c, 0xf0, 0x00, 0x20, 0x4e, 0xf3, 0x00, 0x28, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x57, 0x8f, 0x29, +0x4e, 0x53, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x88, 0x2c, 0x44, 0x20, 0x02, 0xb1, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x20, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x4c, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x3a, 0x58, 0x20, 0x80, 0x00, 0x40, 0x30, 0x08, 0x00, 0x50, 0x31, 0x80, 0x08, +0x00, 0x21, 0x80, 0x00, 0x4e, 0x23, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x07, 0x8f, 0x29, +0x4e, 0x03, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x88, 0x2c, 0x44, 0x20, 0x02, 0xbd, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x50, 0x51, 0x7f, 0xff, 0x44, 0x40, 0x00, 0x00, +0x45, 0xe0, 0x00, 0x01, 0x10, 0x41, 0x80, 0x00, 0x40, 0x4f, 0x14, 0x0c, 0x50, 0x32, 0x7f, 0xff, +0x40, 0x21, 0x90, 0x04, 0x05, 0xe0, 0x80, 0x01, 0x40, 0x51, 0x00, 0x0c, 0x40, 0x42, 0xf8, 0x04, +0x14, 0x40, 0x80, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x58, 0x60, 0x00, 0x00, 0x54, 0x10, 0x80, 0xff, +0x4e, 0x03, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x07, 0x8f, 0x29, 0x4e, 0x03, 0x00, 0x12, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x88, 0x2c, +0x44, 0x20, 0x02, 0x03, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x00, 0x46, 0x00, 0x01, 0x12, 0x58, 0x00, 0x00, 0x90, 0x40, 0xf3, 0x00, 0x06, +0x4e, 0xf3, 0x00, 0x0c, 0x50, 0x20, 0x06, 0x18, 0x40, 0xf1, 0x18, 0x06, 0x4e, 0xf3, 0x00, 0x06, +0x50, 0x70, 0x7f, 0xf0, 0x48, 0x00, 0x00, 0x18, 0x46, 0x00, 0x01, 0x11, 0x58, 0x00, 0x04, 0xbc, +0x40, 0xf3, 0x00, 0x06, 0x4e, 0xf3, 0x00, 0x0c, 0x50, 0x30, 0x05, 0x64, 0x40, 0xf1, 0x98, 0x06, +0x4e, 0xf3, 0x00, 0x06, 0x50, 0x70, 0x7f, 0xf4, 0x48, 0x00, 0x00, 0x06, 0x46, 0x70, 0x01, 0x10, +0x58, 0x73, 0x8d, 0x38, 0x4e, 0x12, 0x00, 0x2a, 0x04, 0x43, 0x00, 0x02, 0x4e, 0x42, 0x00, 0x26, +0x02, 0x03, 0x00, 0x06, 0x44, 0x50, 0x0f, 0xff, 0x4c, 0x02, 0xc0, 0x1a, 0x46, 0xf0, 0x01, 0x16, +0x00, 0x67, 0x8f, 0x29, 0x4e, 0x63, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, +0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x88, 0x2c, 0x44, 0x20, 0x02, 0x17, 0x46, 0xf0, 0x01, 0x00, +0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x81, 0x4c, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x20, 0x00, 0x00, 0x14, 0x23, 0x00, 0x02, +0x04, 0x13, 0x80, 0x01, 0x14, 0x63, 0x80, 0x01, 0x14, 0x73, 0x00, 0x00, 0x14, 0x13, 0x00, 0x01, +0x14, 0x60, 0x80, 0x00, 0x04, 0x03, 0x80, 0x02, 0x51, 0xe0, 0x00, 0x01, 0x15, 0xe3, 0x80, 0x02, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x1a, 0x46, 0xf0, 0x01, 0x16, +0x00, 0x07, 0x8f, 0x29, 0x4e, 0x03, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, +0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x88, 0x2c, 0x44, 0x20, 0x02, 0x57, 0x46, 0xf0, 0x01, 0x00, +0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x4e, 0x13, 0x00, 0x1a, +0x46, 0xf0, 0x01, 0x16, 0x00, 0x37, 0x8f, 0x29, 0x4e, 0x33, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x88, 0x2c, 0x44, 0x20, 0x02, 0x58, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, +0x4e, 0x03, 0x00, 0x22, 0x50, 0x50, 0x80, 0x1f, 0x40, 0x12, 0x94, 0x09, 0x5c, 0xf0, 0x80, 0x21, +0x4e, 0xf3, 0x00, 0x2e, 0x46, 0xf0, 0x01, 0x16, 0x01, 0xe7, 0x8f, 0x29, 0x4f, 0xe3, 0x00, 0x12, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x88, 0x2c, +0x44, 0x20, 0x02, 0x61, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x00, 0x40, 0x00, 0x80, 0x13, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x7c, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x50, 0x0f, 0xff, 0x4c, 0x02, 0x80, 0x42, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x81, 0x0c, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x3c, 0x50, 0x20, 0xff, 0xff, +0x5c, 0xf1, 0x00, 0x20, 0x4e, 0xf2, 0x00, 0x34, 0x45, 0xe0, 0x00, 0x01, 0x40, 0x4f, 0x08, 0x0c, +0x50, 0x52, 0x7f, 0xff, 0x40, 0x22, 0x90, 0x04, 0x46, 0xf0, 0x01, 0x11, 0x04, 0x37, 0x80, 0x23, +0x52, 0x40, 0x80, 0x20, 0x48, 0x00, 0x00, 0x1e, 0x4c, 0x51, 0x40, 0x18, 0x41, 0xe1, 0x08, 0x05, +0x40, 0x5f, 0x0c, 0x02, 0x46, 0x30, 0x01, 0x11, 0x58, 0x31, 0x80, 0x88, 0x40, 0x40, 0x0c, 0x00, +0x14, 0x51, 0x80, 0x01, 0x10, 0x12, 0x00, 0x08, 0x40, 0x00, 0x14, 0x08, 0x04, 0x21, 0x80, 0x00, +0x40, 0x01, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0e, 0x40, 0x21, 0x08, 0x00, 0x50, 0x00, 0x00, 0x01, +0x40, 0x51, 0x0c, 0x02, 0x40, 0xf2, 0x00, 0x06, 0x4e, 0xf2, 0xff, 0xe0, 0x44, 0x00, 0x00, 0x00, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, +0x46, 0x70, 0x01, 0x10, 0x58, 0x73, 0x8d, 0x38, 0x04, 0x63, 0x80, 0x00, 0x4c, 0x63, 0xc0, 0x06, +0x44, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0x44, 0x04, 0x33, 0x00, 0x01, 0x04, 0x43, 0x00, 0x00, +0x44, 0x80, 0x00, 0x00, 0x14, 0x32, 0x00, 0x01, 0x14, 0x41, 0x80, 0x00, 0x14, 0x83, 0x00, 0x00, +0x14, 0x83, 0x00, 0x01, 0x04, 0x23, 0x80, 0x02, 0x50, 0x11, 0x7f, 0xff, 0x14, 0x13, 0x80, 0x02, +0x4e, 0x62, 0x00, 0x2e, 0x4e, 0x02, 0x00, 0x2c, 0x40, 0x00, 0x00, 0x13, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x81, 0x7c, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x50, 0x0f, 0xff, 0x12, 0x03, 0x00, 0x06, +0x4c, 0x02, 0x80, 0x0c, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x0c, 0x4b, 0xe0, 0x3c, 0x01, +0x14, 0x03, 0x00, 0x02, 0x48, 0x00, 0x00, 0x14, 0x04, 0x23, 0x80, 0x01, 0x14, 0x63, 0x80, 0x01, +0x14, 0x73, 0x00, 0x00, 0x14, 0x23, 0x00, 0x01, 0x14, 0x61, 0x00, 0x00, 0x58, 0x64, 0x00, 0x00, +0x05, 0xe3, 0x80, 0x02, 0x50, 0x0f, 0x00, 0x01, 0x14, 0x03, 0x80, 0x02, 0x58, 0x03, 0x00, 0x00, +0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x50, 0x60, 0x00, 0x18, 0x44, 0x00, 0x00, 0x1c, 0x58, 0x71, 0x00, 0x00, +0x54, 0x80, 0x80, 0xff, 0x46, 0xf0, 0x01, 0x04, 0x58, 0xf7, 0x81, 0xdc, 0x4b, 0xe0, 0x3c, 0x01, +0x4e, 0x03, 0x00, 0x12, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x07, 0x82, 0x9b, 0x44, 0x10, 0x00, 0x0a, +0x50, 0x00, 0x00, 0x40, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x8a, 0xa0, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x5a, 0x04, 0x30, 0x00, 0x02, 0x44, 0x50, 0x00, 0x00, 0x44, 0x20, 0x00, 0x1c, +0x50, 0x11, 0x7f, 0xfc, 0x12, 0x21, 0x80, 0x00, 0x10, 0x11, 0x80, 0x04, 0x10, 0x51, 0x80, 0x05, +0x50, 0x31, 0x80, 0x0c, 0x00, 0x93, 0x7f, 0xf4, 0x10, 0x91, 0x80, 0x00, 0x01, 0xe3, 0x7f, 0xf5, +0x10, 0x81, 0x80, 0x02, 0x11, 0xe1, 0x80, 0x01, 0x46, 0x80, 0x04, 0xc4, 0x00, 0x23, 0x7f, 0xf6, +0x58, 0x84, 0x0b, 0x40, 0x10, 0x21, 0x80, 0x03, 0x45, 0xe0, 0x00, 0x01, 0x00, 0x13, 0x7f, 0xf8, +0x10, 0x11, 0x80, 0x04, 0x04, 0x93, 0x7f, 0xff, 0x40, 0x94, 0xa0, 0x03, 0x44, 0x80, 0x00, 0x02, +0x40, 0x24, 0x24, 0x1a, 0x40, 0x2f, 0x24, 0x1b, 0x10, 0x21, 0x80, 0x05, 0x00, 0x13, 0x00, 0x00, +0x10, 0x11, 0x80, 0x06, 0x00, 0x23, 0x00, 0x04, 0x10, 0x21, 0x80, 0x07, 0x44, 0x2f, 0xe0, 0x00, +0x00, 0x13, 0x00, 0x05, 0x10, 0x11, 0x80, 0x08, 0x00, 0x63, 0x00, 0x08, 0x14, 0x71, 0x80, 0x03, +0x10, 0x61, 0x80, 0x09, 0x10, 0x51, 0x80, 0x0b, 0x10, 0x51, 0x80, 0x0a, 0x11, 0xe0, 0x00, 0x10, +0x04, 0x30, 0x00, 0x02, 0x12, 0x21, 0x80, 0x01, 0x46, 0xf0, 0x01, 0x05, 0x58, 0xf7, 0x85, 0x58, +0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x98, 0xbc, 0x51, 0xff, 0xff, 0xf8, 0x58, 0x60, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, +0x4e, 0x02, 0x00, 0x06, 0x44, 0x10, 0x00, 0x02, 0x4c, 0x00, 0xc0, 0x68, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x07, 0x8b, 0x73, 0x4e, 0x02, 0x00, 0x0e, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x37, 0x8b, 0x74, +0x4e, 0x32, 0x00, 0x08, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x57, 0x8b, 0x75, 0x4e, 0x53, 0x00, 0x1e, +0x46, 0xf0, 0x01, 0x16, 0x00, 0x17, 0x8f, 0x29, 0x4e, 0x13, 0x00, 0x0c, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x08, 0x68, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x04, 0x23, 0x00, 0x09, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x04, +0x58, 0xf7, 0x82, 0x8c, 0x4b, 0xe0, 0x3c, 0x01, 0x00, 0x13, 0x00, 0x0e, 0x04, 0x23, 0x00, 0x04, +0x00, 0x33, 0x00, 0x1c, 0x00, 0x43, 0x00, 0x1d, 0x04, 0x53, 0x00, 0x06, 0x04, 0x03, 0x00, 0x05, +0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x85, 0x28, 0x4b, 0xe0, 0x3c, 0x01, 0x50, 0x0f, 0x80, 0x04, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x8b, 0xb8, 0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x4f, 0x80, 0x01, +0x44, 0x2f, 0xf7, 0xef, 0x40, 0x32, 0x08, 0x02, 0x58, 0x01, 0x80, 0x00, 0x14, 0x3f, 0x80, 0x01, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x8b, 0x84, 0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x23, 0x00, 0x09, +0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x04, 0x58, 0xf7, 0x82, 0x8c, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x6e, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0x80, 0x1a, +0x46, 0xf0, 0x01, 0x16, 0x00, 0x67, 0x8f, 0x29, 0x4e, 0x63, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x88, 0x4c, 0x44, 0x20, 0x03, 0x5e, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, +0x44, 0x10, 0x00, 0x14, 0x44, 0x00, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x04, 0x58, 0xf7, 0x80, 0x7c, +0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x10, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, +0x00, 0x17, 0x8f, 0x29, 0x4e, 0x13, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, +0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x88, 0x4c, 0x44, 0x20, 0x03, 0x6a, 0x46, 0xf0, 0x01, 0x00, +0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x44, 0x50, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x0f, 0x10, 0x57, 0x8a, 0x84, 0x44, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x0c, +0x58, 0x20, 0x00, 0x00, 0x10, 0x40, 0x80, 0x0c, 0x00, 0x33, 0x00, 0x0d, 0x10, 0x30, 0x80, 0x0d, +0x05, 0xe3, 0x00, 0x04, 0x15, 0xe0, 0x80, 0x04, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x81, 0x3c, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x50, 0x01, 0x0f, 0x04, 0x12, 0x82, 0x9b, 0x00, 0x23, 0x00, 0x08, +0x10, 0x20, 0x80, 0x73, 0x04, 0x32, 0x82, 0x9b, 0x04, 0x43, 0x00, 0x04, 0x14, 0x41, 0x80, 0x20, +0x58, 0x03, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x8e, 0x24, 0x4b, 0xe0, 0x3c, 0x01, +0x51, 0xff, 0x80, 0x08, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x04, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x06, 0x4e, 0x13, 0x00, 0x1a, +0x46, 0xf0, 0x01, 0x16, 0x00, 0x07, 0x8f, 0x29, 0x4e, 0x03, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x88, 0x4c, 0x44, 0x20, 0x01, 0xe6, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, +0x51, 0xe0, 0x00, 0x20, 0x02, 0x1f, 0x00, 0x02, 0x02, 0x0f, 0x00, 0x03, 0x46, 0xf0, 0x01, 0x05, +0x58, 0xf7, 0x85, 0x50, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x4c, 0x00, 0x00, 0x58, 0x50, 0x00, 0x00, +0x58, 0x42, 0x00, 0x01, 0x44, 0x30, 0x00, 0x00, 0x40, 0x02, 0x14, 0x1a, 0x40, 0x01, 0x94, 0x1b, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xbc, 0x54, 0x70, 0x00, 0xff, 0x40, 0x03, 0x80, 0x10, 0x55, 0xc0, 0x80, 0xff, +0x4e, 0x05, 0x00, 0x46, 0x50, 0x6f, 0x80, 0x04, 0x46, 0x80, 0x00, 0x02, 0x58, 0x84, 0x04, 0xe4, +0x50, 0xaf, 0x80, 0x28, 0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x23, 0x58, 0x03, 0x00, 0x00, +0x4b, 0xe0, 0x20, 0x01, 0x50, 0x9f, 0x80, 0x34, 0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x0c, +0x58, 0x05, 0x00, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x0a, +0x58, 0x04, 0x80, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0x58, 0x13, 0x00, 0x00, 0x58, 0x25, 0x00, 0x00, +0x58, 0x34, 0x80, 0x00, 0x58, 0x03, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x80, 0xe4, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x10, 0x00, 0x00, 0x40, 0x40, 0xf0, 0x06, 0x58, 0x03, 0x80, 0x00, +0x58, 0x13, 0x00, 0x00, 0x58, 0x25, 0x00, 0x00, 0x58, 0x34, 0x80, 0x00, 0x10, 0x43, 0x00, 0x1e, +0x46, 0xf0, 0x01, 0x01, 0x58, 0xf7, 0x86, 0x40, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x44, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xf4, +0x54, 0x60, 0x00, 0xff, 0x40, 0x03, 0x00, 0x10, 0x54, 0x70, 0x80, 0xff, 0x4e, 0x05, 0x00, 0x36, +0x46, 0xf0, 0x01, 0x0f, 0x04, 0x27, 0x82, 0x64, 0x44, 0x30, 0x00, 0x0c, 0x42, 0x23, 0x0c, 0x73, +0x58, 0x03, 0x00, 0x00, 0x10, 0x71, 0x06, 0x94, 0x50, 0x1f, 0x80, 0x05, 0x50, 0x2f, 0x80, 0x06, +0x50, 0x3f, 0x80, 0x07, 0x46, 0xf0, 0x01, 0x09, 0x58, 0xf7, 0x86, 0xec, 0x4b, 0xe0, 0x3c, 0x01, +0x00, 0x0f, 0x80, 0x05, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x0a, 0x00, 0x5f, 0x80, 0x06, +0x4c, 0x50, 0x40, 0x06, 0x01, 0xef, 0x80, 0x07, 0x4d, 0xe3, 0x80, 0x10, 0x44, 0x10, 0x00, 0x01, +0x58, 0x03, 0x00, 0x00, 0x58, 0x33, 0x80, 0x00, 0x58, 0x20, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x09, +0x58, 0xf7, 0x8a, 0x40, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x54, 0x21, 0x00, 0xff, +0x59, 0xc0, 0x00, 0x00, 0x54, 0x80, 0x80, 0xff, 0x14, 0x2f, 0x80, 0x01, 0x4e, 0x02, 0x00, 0x6e, +0x44, 0x60, 0x00, 0x00, 0x50, 0x74, 0x00, 0x24, 0x44, 0xa0, 0x00, 0x01, 0x40, 0x0e, 0x18, 0x0d, +0x54, 0x10, 0x00, 0x01, 0x50, 0x03, 0x7f, 0xf9, 0x4e, 0x12, 0x00, 0x5a, 0x5c, 0xf0, 0x00, 0x02, +0x4e, 0xf2, 0x00, 0x14, 0x5c, 0xf4, 0x00, 0x03, 0x4e, 0xf2, 0x00, 0x52, 0x54, 0x03, 0x00, 0xff, +0x58, 0x14, 0x00, 0x00, 0x44, 0x20, 0x00, 0x01, 0x44, 0x30, 0x4e, 0x20, 0x46, 0x40, 0x01, 0x01, +0x58, 0x42, 0x0b, 0x74, 0x48, 0x00, 0x00, 0x1c, 0x04, 0x5f, 0x80, 0x01, 0x54, 0x43, 0x00, 0xff, +0x58, 0x14, 0x00, 0x00, 0x44, 0x20, 0x00, 0x01, 0x44, 0x30, 0x4e, 0x20, 0x58, 0x02, 0x00, 0x00, +0x4e, 0x52, 0x00, 0x0a, 0x46, 0xf0, 0x01, 0x01, 0x58, 0xf7, 0x82, 0x18, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x08, 0x46, 0x40, 0x01, 0x01, 0x58, 0x42, 0x0c, 0x1c, 0x4b, 0xe0, 0x10, 0x01, +0x46, 0xf0, 0x01, 0x0f, 0x04, 0x37, 0x82, 0x68, 0x40, 0x25, 0x18, 0x0c, 0x38, 0x41, 0x9d, 0x01, +0x41, 0xe1, 0x10, 0x04, 0x39, 0xe1, 0x9d, 0x09, 0x4e, 0x02, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, +0x00, 0x67, 0x8f, 0x29, 0x4e, 0x63, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, +0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x88, 0x84, 0x44, 0x20, 0x11, 0xe8, 0x46, 0xf0, 0x01, 0x00, +0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x50, 0x63, 0x00, 0x01, +0x44, 0x50, 0x00, 0x0e, 0x4c, 0x62, 0xff, 0x9c, 0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x59, 0xc0, 0x00, 0x00, +0x54, 0x80, 0x80, 0xff, 0x4e, 0x02, 0x00, 0x56, 0x44, 0x60, 0x00, 0x00, 0x50, 0x74, 0x00, 0x24, +0x44, 0xa0, 0x00, 0x01, 0x40, 0x1e, 0x18, 0x0d, 0x54, 0x00, 0x80, 0x01, 0x50, 0x23, 0x7f, 0xf9, +0x4e, 0x02, 0x00, 0x42, 0x54, 0x03, 0x00, 0xff, 0x58, 0x14, 0x00, 0x00, 0x5c, 0xf1, 0x00, 0x02, +0x4e, 0xf2, 0x00, 0x0c, 0x5c, 0xf4, 0x00, 0x03, 0x4e, 0xf2, 0x00, 0x36, 0x46, 0x20, 0x01, 0x01, +0x58, 0x21, 0x03, 0xb4, 0x48, 0x00, 0x00, 0x06, 0x46, 0x20, 0x01, 0x01, 0x58, 0x21, 0x04, 0x08, +0x4b, 0xe0, 0x08, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x47, 0x82, 0x68, 0x40, 0x15, 0x18, 0x0c, +0x38, 0x32, 0x1d, 0x01, 0x40, 0x50, 0x84, 0x05, 0x40, 0x22, 0x8c, 0x02, 0x38, 0x22, 0x1d, 0x09, +0x4e, 0x02, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x67, 0x8f, 0x29, 0x4e, 0x63, 0x00, 0x12, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x88, 0x84, +0x44, 0x20, 0x11, 0xa8, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x00, 0x50, 0x63, 0x00, 0x01, 0x44, 0x50, 0x00, 0x0e, 0x4c, 0x62, 0xff, 0xb4, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x04, 0x60, 0x00, 0x02, 0x58, 0x70, 0x00, 0x00, 0x50, 0x03, 0x00, 0x20, +0x04, 0x10, 0x00, 0x00, 0x4e, 0x13, 0x00, 0x2c, 0x00, 0x23, 0x00, 0x06, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x22, 0xc0, 0x0e, 0x04, 0x10, 0x00, 0x01, 0x46, 0x00, 0x01, 0x0f, 0x4e, 0x12, 0x00, 0x06, +0x10, 0x20, 0x09, 0xa4, 0x48, 0x00, 0x00, 0x04, 0x10, 0x10, 0x09, 0xa4, 0x00, 0x03, 0x00, 0x06, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x37, 0x89, 0xa4, 0x4e, 0x02, 0x00, 0x08, 0x00, 0x53, 0x00, 0x0b, +0x54, 0x42, 0x80, 0x01, 0x4e, 0x42, 0x00, 0x58, 0x50, 0x03, 0x00, 0x0c, 0x44, 0x10, 0x00, 0x00, +0x00, 0x23, 0x00, 0x07, 0x14, 0x10, 0x00, 0x02, 0x48, 0x00, 0x00, 0x26, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x12, 0xc0, 0x4a, 0x00, 0x00, 0x00, 0x04, 0x41, 0xe0, 0x00, 0x10, 0x4f, 0xe4, 0x00, 0x06, +0x44, 0x10, 0xff, 0xff, 0x48, 0x00, 0x00, 0x0a, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x8c, 0x84, +0x4b, 0xe0, 0x3c, 0x01, 0x00, 0x10, 0x00, 0x08, 0x00, 0x23, 0x00, 0x0b, 0x54, 0x01, 0x00, 0x01, +0x4e, 0x02, 0x00, 0x32, 0x50, 0x03, 0x00, 0x0c, 0x44, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x07, +0x14, 0x30, 0x00, 0x02, 0x14, 0x30, 0x00, 0x00, 0x14, 0x10, 0x00, 0x01, 0x45, 0xef, 0xff, 0xed, +0x44, 0x00, 0x00, 0x18, 0x44, 0x30, 0x00, 0x0f, 0x12, 0x03, 0x00, 0x00, 0x11, 0xe3, 0x00, 0x04, +0x10, 0x33, 0x00, 0x08, 0x10, 0x23, 0x00, 0x05, 0x44, 0x50, 0x00, 0x01, 0x04, 0x13, 0x80, 0x02, +0x44, 0x4f, 0xe0, 0x00, 0x10, 0x53, 0x80, 0x10, 0x12, 0x40, 0x80, 0x01, 0x58, 0x03, 0x80, 0x00, +0x46, 0xf0, 0x01, 0x05, 0x58, 0xf7, 0x85, 0x58, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x01, +0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x54, 0x00, 0x00, 0xff, +0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x8c, 0x84, 0x4b, 0xe0, 0x3c, 0x01, 0x4e, 0x03, 0x00, 0x06, +0x44, 0x00, 0x00, 0xff, 0x48, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x40, 0x00, 0x00, 0x13, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x0c, 0x4b, 0xe0, 0x3c, 0x01, +0x00, 0x50, 0x00, 0x03, 0x44, 0x3f, 0xff, 0xa0, 0x54, 0x42, 0x80, 0x1f, 0x40, 0x22, 0x0c, 0x04, +0x02, 0x10, 0x00, 0x00, 0x10, 0x20, 0x00, 0x03, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x08, 0xa0, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x40, 0x20, 0x00, 0x13, 0x44, 0x00, 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x58, 0x30, 0x00, 0x00, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8a, 0x74, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x47, 0xc0, 0x00, 0x03, 0x59, 0xce, 0x01, 0x0c, 0x54, 0x70, 0x00, 0xff, 0x46, 0xa0, 0x01, 0x03, +0x58, 0xa5, 0x0e, 0x00, 0x46, 0x90, 0x01, 0x04, 0x58, 0x94, 0x8a, 0x38, 0x46, 0x80, 0x01, 0x04, +0x58, 0x84, 0x0a, 0x88, 0x58, 0x13, 0x80, 0x00, 0x44, 0x20, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, +0x46, 0xf0, 0x01, 0x09, 0x58, 0xf7, 0x8b, 0x18, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x50, 0x0f, 0xff, +0x58, 0x13, 0x80, 0x00, 0x44, 0x20, 0x00, 0x00, 0x4c, 0x02, 0x80, 0x22, 0x44, 0x00, 0x00, 0x01, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x89, 0x4c, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x60, 0x00, 0x00, +0x4b, 0xe0, 0x70, 0x01, 0x00, 0x10, 0x00, 0x05, 0x44, 0x50, 0x00, 0xa0, 0x58, 0x03, 0x00, 0x00, +0x4c, 0x12, 0x80, 0x0a, 0x4b, 0xe0, 0x24, 0x01, 0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x20, 0x01, +0x48, 0xff, 0xff, 0xd2, 0x4b, 0xe0, 0x28, 0x01, 0x48, 0xff, 0xff, 0xce, 0x51, 0xff, 0x80, 0x04, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x58, 0x70, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x84, 0xbc, 0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x63, 0x80, 0x02, +0x00, 0x83, 0x00, 0x20, 0x40, 0x04, 0x00, 0x10, 0x4e, 0x04, 0x00, 0x06, 0x44, 0x10, 0xff, 0xff, +0x48, 0x00, 0x00, 0x1e, 0x44, 0x20, 0x00, 0x00, 0x46, 0x10, 0x01, 0x12, 0x58, 0x10, 0x88, 0x70, +0x38, 0x20, 0xa0, 0x08, 0x44, 0x00, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x04, 0x58, 0xf7, 0x8a, 0xb8, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x10, 0x00, 0x00, 0x58, 0x04, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x04, +0x58, 0xf7, 0x86, 0x98, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x10, 0x00, 0x00, 0x00, 0x33, 0x00, 0x0b, +0x54, 0x01, 0x80, 0x01, 0x4e, 0x02, 0x00, 0x36, 0x00, 0x23, 0x00, 0x07, 0x50, 0x43, 0x00, 0x0c, +0x14, 0x12, 0x00, 0x01, 0x44, 0x30, 0x00, 0x18, 0x44, 0x1f, 0xff, 0xed, 0x44, 0x50, 0x00, 0x00, +0x44, 0x00, 0x00, 0x0a, 0x14, 0x52, 0x00, 0x02, 0x14, 0x82, 0x00, 0x00, 0x12, 0x33, 0x00, 0x00, +0x10, 0x13, 0x00, 0x04, 0x10, 0x03, 0x00, 0x08, 0x10, 0x23, 0x00, 0x05, 0x45, 0xe0, 0x00, 0x01, +0x04, 0x53, 0x80, 0x02, 0x44, 0x4f, 0xe0, 0x00, 0x11, 0xe3, 0x80, 0x10, 0x12, 0x42, 0x80, 0x01, +0x58, 0x03, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x05, 0x58, 0xf7, 0x85, 0x58, 0x4b, 0xe0, 0x3c, 0x01, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x84, 0xbc, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x01, +0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x46, 0x90, 0x00, 0x03, 0x58, 0x94, 0x89, 0x4c, 0x55, 0xc0, 0x00, 0xff, 0x54, 0xa0, 0x80, 0xff, +0x46, 0x80, 0x01, 0x04, 0x58, 0x84, 0x0a, 0x38, 0x46, 0x70, 0x01, 0x04, 0x58, 0x73, 0x8a, 0x88, +0x48, 0x00, 0x00, 0x08, 0x4b, 0xe0, 0x20, 0x01, 0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x58, 0x15, 0x00, 0x00, 0x44, 0x20, 0x00, 0x00, 0x58, 0x0e, 0x00, 0x00, 0x4b, 0xe0, 0x24, 0x01, +0x44, 0x50, 0x0f, 0xff, 0x58, 0x60, 0x00, 0x00, 0x4c, 0x02, 0xff, 0xee, 0x51, 0xff, 0x80, 0x04, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xdc, +0x58, 0x50, 0x80, 0x00, 0x14, 0x0f, 0x80, 0x04, 0x4e, 0x12, 0x00, 0x0a, 0x44, 0x00, 0x00, 0x01, +0x4c, 0x10, 0x00, 0x06, 0x44, 0xa0, 0x00, 0x00, 0x48, 0x00, 0x00, 0x5a, 0x47, 0xcc, 0x00, 0x00, +0x54, 0x21, 0x00, 0xff, 0x59, 0xce, 0x00, 0x01, 0x44, 0xa0, 0x00, 0x00, 0x14, 0x2f, 0x80, 0x05, +0x15, 0xcf, 0x80, 0x01, 0x58, 0x95, 0x00, 0x00, 0x50, 0x8f, 0x80, 0x1f, 0x50, 0x7f, 0x80, 0x1c, +0x50, 0x6f, 0x80, 0x1a, 0x04, 0x4f, 0x80, 0x04, 0x40, 0x32, 0x24, 0x0d, 0x54, 0x11, 0x80, 0x01, +0x4e, 0x12, 0x00, 0x38, 0x58, 0x14, 0x80, 0x00, 0x44, 0x20, 0x00, 0x00, 0x44, 0x00, 0x00, 0x02, +0x14, 0x5f, 0x80, 0x03, 0x45, 0xc0, 0x0f, 0xff, 0x46, 0xf0, 0x01, 0x09, 0x58, 0xf7, 0x8b, 0x18, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x03, 0x58, 0x34, 0x80, 0x00, +0x04, 0x4f, 0x80, 0x05, 0x04, 0x5f, 0x80, 0x03, 0x4c, 0x0e, 0x00, 0x1c, 0x58, 0x02, 0x80, 0x00, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x8c, 0x60, 0x4b, 0xe0, 0x3c, 0x01, 0x05, 0xef, 0x80, 0x01, +0x58, 0x13, 0x80, 0x00, 0x40, 0xaf, 0x00, 0x1b, 0x58, 0x23, 0x00, 0x00, 0x58, 0x04, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x8c, 0xf4, 0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x5f, 0x80, 0x03, +0x50, 0x94, 0x80, 0x01, 0x45, 0xc0, 0x00, 0x0e, 0x4c, 0x9e, 0x7f, 0xbe, 0x58, 0x05, 0x00, 0x00, +0x51, 0xff, 0x80, 0x24, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x54, 0x81, 0x80, 0xff, 0x44, 0x40, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0f, +0x04, 0x37, 0x82, 0x68, 0x58, 0x70, 0x80, 0x00, 0x54, 0x61, 0x00, 0xff, 0x58, 0x92, 0x00, 0x00, +0x50, 0x14, 0x00, 0x24, 0x44, 0x00, 0x00, 0x01, 0x40, 0x53, 0x90, 0x0d, 0x54, 0x22, 0x80, 0x01, +0x4e, 0x22, 0x00, 0x0e, 0x39, 0xe1, 0x85, 0x01, 0x40, 0x20, 0x10, 0x0c, 0x41, 0xcf, 0x10, 0x0e, +0x54, 0xae, 0x00, 0x01, 0x4e, 0xa3, 0x00, 0x04, 0x40, 0x94, 0x88, 0x04, 0x50, 0x42, 0x00, 0x01, +0x44, 0x50, 0x00, 0x0e, 0x4c, 0x42, 0xff, 0xea, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, +0x46, 0xa0, 0x01, 0x04, 0x58, 0xa5, 0x05, 0xec, 0x4b, 0xe0, 0x28, 0x01, 0x47, 0xc0, 0x01, 0x03, +0x59, 0xce, 0x04, 0x5c, 0x44, 0x10, 0x00, 0x01, 0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x70, 0x01, +0x44, 0x20, 0x00, 0x00, 0x58, 0x03, 0x80, 0x00, 0x58, 0x14, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x04, +0x58, 0xf7, 0x87, 0x24, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x04, 0x80, 0x00, 0x58, 0x14, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x04, 0x58, 0xf7, 0x88, 0x24, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x10, 0x00, 0x00, +0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x70, 0x01, 0x44, 0x10, 0x00, 0x00, 0x58, 0x03, 0x80, 0x00, +0x58, 0x23, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x04, 0x58, 0xf7, 0x8c, 0x98, 0x4b, 0xe0, 0x3c, 0x01, +0x58, 0x10, 0x00, 0x00, 0x4e, 0x02, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x17, 0x8f, 0x29, +0x4e, 0x13, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x88, 0x84, 0x44, 0x20, 0x0c, 0xeb, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x28, 0x01, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, +0x58, 0x80, 0x80, 0x00, 0x58, 0x60, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x46, 0x44, 0x50, 0x00, 0x05, +0x4c, 0x62, 0x80, 0x38, 0x44, 0x10, 0x00, 0x06, 0x4c, 0x60, 0xc0, 0x1c, 0x54, 0x71, 0x00, 0xff, +0x58, 0x03, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x04, 0x58, 0xf7, 0x8a, 0x04, 0x4b, 0xe0, 0x3c, 0x01, +0x58, 0x30, 0x00, 0x00, 0x58, 0x14, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x58, 0x23, 0x80, 0x00, +0x46, 0xf0, 0x01, 0x04, 0x58, 0xf7, 0x8d, 0x7c, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x1a, +0x46, 0xf0, 0x01, 0x16, 0x00, 0x27, 0x8f, 0x29, 0x4e, 0x23, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x88, 0x84, 0x44, 0x20, 0x0d, 0x2d, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, +0x44, 0x00, 0x00, 0x03, 0x44, 0x10, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x04, 0x58, 0xf7, 0x8c, 0x38, +0x4b, 0xe0, 0x3c, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, +0x00, 0x60, 0x00, 0x09, 0x54, 0x10, 0x80, 0xff, 0x40, 0x03, 0x00, 0x10, 0x4e, 0x04, 0x00, 0x06, +0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x1c, 0x4e, 0x13, 0x00, 0x04, 0x48, 0x00, 0x00, 0x16, +0x58, 0x03, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x04, 0x58, 0xf7, 0x86, 0x98, 0x4b, 0xe0, 0x3c, 0x01, +0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x00, 0x06, 0x44, 0x10, 0x00, 0x0f, 0x46, 0xf0, 0x01, 0x04, +0x58, 0xf7, 0x8e, 0x9c, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x01, 0x3a, 0x6f, 0x98, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x04, 0x60, 0x00, 0x02, 0x58, 0x70, 0x00, 0x00, +0x00, 0x83, 0x00, 0x20, 0x40, 0x04, 0x00, 0x10, 0x4e, 0x04, 0x00, 0x06, 0x44, 0x10, 0xff, 0xff, +0x48, 0x00, 0x00, 0x16, 0x58, 0x04, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x8c, 0x84, +0x4b, 0xe0, 0x3c, 0x01, 0x10, 0x80, 0x00, 0x09, 0x44, 0x10, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x04, +0x58, 0xf7, 0x8f, 0x3c, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x10, 0x00, 0x00, 0x00, 0x23, 0x00, 0x0b, +0x54, 0x01, 0x00, 0x01, 0x4e, 0x02, 0x00, 0x30, 0x00, 0x53, 0x00, 0x07, 0x50, 0x43, 0x00, 0x0c, +0x44, 0x30, 0x00, 0x00, 0x44, 0x20, 0x00, 0x18, 0x44, 0x0f, 0xff, 0xed, 0x45, 0xe0, 0x00, 0x14, +0x14, 0x32, 0x00, 0x02, 0x14, 0x82, 0x00, 0x00, 0x14, 0x12, 0x00, 0x01, 0x10, 0x03, 0x00, 0x04, +0x12, 0x23, 0x00, 0x00, 0x11, 0xe3, 0x00, 0x08, 0x10, 0x53, 0x00, 0x05, 0x44, 0x40, 0x00, 0x01, +0x04, 0x13, 0x80, 0x02, 0x44, 0x3f, 0xe0, 0x00, 0x10, 0x43, 0x80, 0x10, 0x12, 0x30, 0x80, 0x01, +0x58, 0x03, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x05, 0x58, 0xf7, 0x85, 0x58, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x00, 0x00, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, +0x46, 0x80, 0x01, 0x0f, 0x44, 0x90, 0x00, 0x00, 0x46, 0xa0, 0x01, 0x06, 0x58, 0xa5, 0x01, 0xf4, +0x48, 0x00, 0x00, 0x42, 0x04, 0x53, 0x00, 0x01, 0x05, 0xe3, 0x00, 0x00, 0x14, 0x5f, 0x00, 0x01, +0x15, 0xe2, 0x80, 0x00, 0x14, 0x93, 0x00, 0x00, 0x14, 0x93, 0x00, 0x01, 0x04, 0x34, 0x02, 0x68, +0x04, 0x41, 0x80, 0x0e, 0x50, 0x22, 0x7f, 0xff, 0x14, 0x21, 0x80, 0x0e, 0x4b, 0xe0, 0x28, 0x01, +0x46, 0x1c, 0x00, 0x00, 0x58, 0x50, 0x80, 0x9a, 0x4c, 0x02, 0xc0, 0x26, 0x04, 0x03, 0x80, 0x00, +0x44, 0x10, 0x00, 0x0a, 0x05, 0xe0, 0x00, 0x0c, 0x50, 0x50, 0x00, 0x30, 0x14, 0x6f, 0x00, 0x01, +0x15, 0xe3, 0x00, 0x00, 0x14, 0x53, 0x00, 0x01, 0x14, 0x62, 0x80, 0x00, 0x04, 0x33, 0x80, 0x00, +0x04, 0x41, 0x80, 0x0e, 0x50, 0x22, 0x00, 0x01, 0x14, 0x21, 0x80, 0x0e, 0x04, 0x03, 0x80, 0x00, +0x50, 0x00, 0x00, 0x18, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x8a, 0xa0, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x10, 0x04, 0x34, 0x02, 0x68, 0x46, 0x70, 0x01, 0x0f, 0x58, 0x73, 0x89, 0xa0, +0x04, 0x61, 0x80, 0x0c, 0x50, 0x11, 0x80, 0x30, 0x58, 0x03, 0x00, 0x00, 0x4c, 0x60, 0xff, 0xb4, +0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x60, 0x01, 0x03, +0x58, 0x63, 0x07, 0xa8, 0x44, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x00, 0x00, 0x00, +0x4b, 0xe0, 0x18, 0x01, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, +0x46, 0x60, 0x01, 0x0f, 0x58, 0x63, 0x09, 0xa0, 0x04, 0x23, 0x00, 0x00, 0x46, 0x10, 0x01, 0x05, +0x58, 0x10, 0x85, 0x08, 0x50, 0x01, 0x01, 0x48, 0x44, 0x20, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x08, +0x58, 0xf7, 0x87, 0xb0, 0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x13, 0x00, 0x00, 0x50, 0x00, 0x81, 0x48, +0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x88, 0x0c, 0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x03, 0x00, 0x00, +0x44, 0x10, 0x75, 0x30, 0x50, 0x00, 0x01, 0x48, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x8a, 0xa0, +0x4b, 0xe0, 0x3c, 0x01, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, +0x46, 0x30, 0x01, 0x0f, 0x04, 0x01, 0x82, 0x68, 0x44, 0x10, 0x00, 0x00, 0x14, 0x10, 0x00, 0x0f, +0x58, 0x20, 0x80, 0x00, 0x58, 0x40, 0x80, 0x00, 0x05, 0xe1, 0x82, 0x68, 0x50, 0x81, 0x00, 0x20, +0x38, 0x4f, 0x21, 0x09, 0x50, 0x61, 0x00, 0x24, 0x04, 0x71, 0x82, 0x68, 0x50, 0x10, 0x80, 0x01, +0x44, 0x50, 0x00, 0x04, 0x38, 0x43, 0x99, 0x09, 0x50, 0x21, 0x00, 0x01, 0x46, 0x00, 0x01, 0x0f, +0x58, 0x00, 0x09, 0xa0, 0x4c, 0x12, 0xff, 0xea, 0x04, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x00, +0x50, 0x30, 0x80, 0x50, 0x14, 0x30, 0x80, 0x14, 0x58, 0x11, 0x00, 0x00, 0x04, 0x70, 0x00, 0x00, +0x58, 0x30, 0x00, 0x00, 0x50, 0x63, 0x80, 0x50, 0x14, 0x63, 0x80, 0x15, 0x58, 0x71, 0x00, 0x00, +0x04, 0x40, 0x00, 0x00, 0x14, 0x22, 0x00, 0x16, 0x04, 0x80, 0x00, 0x00, 0x51, 0xe4, 0x00, 0x5c, +0x15, 0xe4, 0x00, 0x17, 0x04, 0x60, 0x00, 0x00, 0x50, 0x53, 0x00, 0x5c, 0x14, 0x53, 0x00, 0x18, +0x04, 0x40, 0x00, 0x00, 0x14, 0x22, 0x00, 0x19, 0x04, 0x80, 0x00, 0x00, 0x51, 0xe4, 0x00, 0xa4, +0x15, 0xe4, 0x00, 0x29, 0x04, 0x60, 0x00, 0x00, 0x50, 0x53, 0x00, 0xa4, 0x14, 0x53, 0x00, 0x2a, +0x04, 0x40, 0x00, 0x00, 0x14, 0x22, 0x00, 0x2b, 0x04, 0x21, 0x80, 0x00, 0x50, 0x50, 0x80, 0x1a, +0x44, 0x00, 0x00, 0x0e, 0x50, 0x10, 0x80, 0x01, 0x38, 0x71, 0x16, 0x0a, 0x46, 0x60, 0x01, 0x0f, +0x58, 0x63, 0x09, 0xa0, 0x4c, 0x10, 0x7f, 0xf2, 0x04, 0x33, 0x00, 0x00, 0x44, 0x80, 0x00, 0x0a, +0x10, 0x81, 0x80, 0xa0, 0x45, 0xef, 0xff, 0x80, 0x04, 0x43, 0x00, 0x00, 0x46, 0x80, 0x01, 0x08, +0x58, 0x84, 0x07, 0xb0, 0x11, 0xe2, 0x00, 0xa1, 0x46, 0x10, 0x01, 0x05, 0x58, 0x10, 0x81, 0x08, +0x04, 0x03, 0x00, 0x00, 0x58, 0x23, 0x80, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0x04, 0x23, 0x00, 0x00, +0x46, 0x10, 0x01, 0x05, 0x58, 0x10, 0x80, 0x4c, 0x50, 0x01, 0x00, 0x18, 0x58, 0x23, 0x80, 0x00, +0x4b, 0xe0, 0x20, 0x01, 0x04, 0x03, 0x00, 0x00, 0x50, 0x50, 0x00, 0x30, 0x14, 0x50, 0x00, 0x0c, +0x04, 0x33, 0x00, 0x00, 0x50, 0x11, 0x80, 0x30, 0x14, 0x11, 0x80, 0x0d, 0x04, 0x43, 0x00, 0x00, +0x14, 0x72, 0x00, 0x0e, 0x46, 0xf0, 0x01, 0x05, 0x58, 0xf7, 0x81, 0x2c, 0x4b, 0xe0, 0x3c, 0x01, +0x46, 0x00, 0x01, 0x12, 0x58, 0x00, 0x08, 0x70, 0x18, 0x70, 0x00, 0x01, 0x46, 0x50, 0x01, 0x12, +0x58, 0x52, 0x88, 0xf0, 0x4c, 0x02, 0xff, 0xfa, 0x44, 0x10, 0x00, 0x01, 0x44, 0x00, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x09, 0x58, 0xf7, 0x87, 0x70, 0x4b, 0xe0, 0x3c, 0x01, 0x3a, 0x6f, 0xa0, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xd4, 0x46, 0xf0, 0x01, 0x16, +0x00, 0x07, 0x8f, 0x29, 0x4e, 0x03, 0x00, 0x0c, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x08, 0xa8, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x16, +0x00, 0x27, 0x8f, 0x29, 0x4e, 0x23, 0x00, 0x14, 0x46, 0xf0, 0x01, 0x09, 0x58, 0xf7, 0x86, 0xc0, +0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x10, 0x00, 0x00, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x08, 0xc8, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x60, 0x00, 0x03, +0x58, 0x63, 0x0d, 0x4c, 0x44, 0x10, 0x00, 0x00, 0x50, 0x2f, 0x80, 0x26, 0x44, 0x00, 0x00, 0x01, +0x4b, 0xe0, 0x18, 0x01, 0x44, 0x00, 0x00, 0x01, 0x58, 0x10, 0x00, 0x00, 0x50, 0x2f, 0x80, 0x24, +0x4b, 0xe0, 0x18, 0x01, 0x44, 0x10, 0x00, 0x02, 0x50, 0x2f, 0x80, 0x22, 0x44, 0x00, 0x00, 0x01, +0x4b, 0xe0, 0x18, 0x01, 0x44, 0x00, 0x00, 0x01, 0x44, 0x10, 0x00, 0x03, 0x50, 0x2f, 0x80, 0x20, +0x4b, 0xe0, 0x18, 0x01, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x47, 0x8f, 0x29, 0x4e, 0x43, 0x00, 0x14, +0x02, 0x1f, 0x80, 0x13, 0x02, 0x2f, 0x80, 0x12, 0x02, 0x3f, 0x80, 0x11, 0x02, 0x4f, 0x80, 0x10, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x08, 0xdc, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x77, 0x8f, 0x29, 0x4e, 0x73, 0x00, 0x0c, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x08, 0xf8, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x67, 0x8f, 0x29, 0x4e, 0x63, 0x00, 0x68, +0x46, 0x80, 0x01, 0x09, 0x58, 0x84, 0x09, 0xb0, 0x58, 0x13, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, +0x4b, 0xe0, 0x20, 0x01, 0x58, 0x20, 0x00, 0x00, 0x14, 0x2f, 0x80, 0x05, 0x46, 0x70, 0x01, 0x09, +0x58, 0x73, 0x89, 0x2c, 0x58, 0x13, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x59, 0xc0, 0x00, 0x00, 0x15, 0xcf, 0x80, 0x06, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, +0x4b, 0xe0, 0x20, 0x01, 0x58, 0xa0, 0x00, 0x00, 0x14, 0xaf, 0x80, 0x07, 0x58, 0x13, 0x00, 0x00, +0x44, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x1c, 0x01, 0x59, 0xc0, 0x00, 0x00, 0x58, 0x13, 0x00, 0x00, +0x44, 0x00, 0x00, 0x02, 0x4b, 0xe0, 0x20, 0x01, 0x58, 0xa0, 0x00, 0x00, 0x58, 0x13, 0x00, 0x00, +0x44, 0x00, 0x00, 0x02, 0x4b, 0xe0, 0x1c, 0x01, 0x58, 0x90, 0x00, 0x00, 0x44, 0x00, 0x00, 0x02, +0x58, 0x10, 0x00, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0x58, 0x60, 0x00, 0x00, 0x44, 0x00, 0x00, 0x02, +0x58, 0x10, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x14, 0x0f, 0x80, 0x02, 0x04, 0x1f, 0x80, 0x05, +0x04, 0x2f, 0x80, 0x06, 0x04, 0x3f, 0x80, 0x07, 0x58, 0x4e, 0x00, 0x00, 0x58, 0x55, 0x00, 0x00, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x09, 0x14, 0x14, 0x9f, 0x80, 0x00, 0x14, 0x6f, 0x80, 0x01, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x16, +0x01, 0xe7, 0x8f, 0x29, 0x4f, 0xe3, 0x00, 0x0c, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x09, 0x54, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x2c, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x60, 0x01, 0x0f, +0x04, 0x13, 0x02, 0x68, 0x50, 0x00, 0x81, 0x48, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x88, 0x0c, +0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x03, 0x02, 0x68, 0x44, 0x10, 0x75, 0x30, 0x50, 0x00, 0x01, 0x48, +0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x8a, 0xa0, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x05, +0x58, 0xf7, 0x83, 0x14, 0x4b, 0xe0, 0x3c, 0x01, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x44, 0x00, 0x00, 0x01, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x58, 0x60, 0x00, 0x00, +0x4e, 0x03, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x07, 0x8f, 0x29, 0x4e, 0x03, 0x00, 0x12, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x89, 0x74, +0x44, 0x20, 0x04, 0x89, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x00, 0x04, 0x20, 0x00, 0x02, 0x4e, 0x23, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, +0x00, 0x37, 0x8f, 0x29, 0x4e, 0x33, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, +0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x89, 0x74, 0x44, 0x20, 0x04, 0x8a, 0x46, 0xf0, 0x01, 0x00, +0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, +0x5c, 0xf0, 0x80, 0x02, 0x4e, 0xf3, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x57, 0x8f, 0x29, +0x4e, 0x53, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x89, 0x74, 0x44, 0x20, 0x04, 0x8c, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x02, 0x23, 0x00, 0x06, +0x58, 0x30, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8a, 0x74, 0x4b, 0xe0, 0x3c, 0x01, +0x4e, 0x03, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, 0x01, 0xe7, 0x8f, 0x29, 0x4f, 0xe3, 0x00, 0x12, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x89, 0x74, +0x44, 0x20, 0x04, 0x96, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x03, +0x58, 0xf7, 0x8f, 0x60, 0x4b, 0xe0, 0x3c, 0x01, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xec, 0x54, 0x00, 0x00, 0xff, 0x14, 0x0f, 0x80, 0x01, +0x44, 0x30, 0x00, 0x00, 0x04, 0x1f, 0x80, 0x01, 0x44, 0x00, 0x00, 0x01, 0x50, 0x2f, 0x80, 0x0e, +0x12, 0x31, 0x00, 0x00, 0x44, 0xa0, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8d, 0x4c, +0x4b, 0xe0, 0x3c, 0x01, 0x47, 0xc0, 0x01, 0x02, 0x59, 0xce, 0x04, 0xbc, 0x50, 0x8f, 0x80, 0x08, +0x48, 0x00, 0x01, 0x36, 0x4b, 0xe0, 0x70, 0x01, 0x04, 0x1f, 0x80, 0x01, 0x44, 0x00, 0x00, 0x01, +0x44, 0x20, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x89, 0x4c, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x50, 0x0f, 0xff, 0x4c, 0x02, 0x81, 0x2a, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x8c, 0xb0, +0x4b, 0xe0, 0x3c, 0x01, 0x50, 0x60, 0x00, 0x0c, 0x4e, 0x03, 0x00, 0x1e, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x09, 0x90, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, +0x46, 0xf0, 0x01, 0x0f, 0x04, 0x07, 0x82, 0x6a, 0x04, 0x20, 0x00, 0x00, 0x4e, 0x23, 0x01, 0x0e, +0x44, 0x10, 0x00, 0x0a, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x8a, 0xa0, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x01, 0x04, 0x04, 0x70, 0x00, 0x02, 0x44, 0x10, 0x00, 0x10, 0x12, 0x10, 0x00, 0x0a, +0x14, 0x70, 0x00, 0x06, 0x02, 0x03, 0x80, 0x01, 0x41, 0xe0, 0x34, 0x09, 0x50, 0x3f, 0x7f, 0xfe, +0x54, 0x51, 0x80, 0xff, 0x11, 0xe3, 0x00, 0x05, 0x5c, 0xf2, 0x80, 0x02, 0x4e, 0xf2, 0x00, 0x44, +0x03, 0xe3, 0x80, 0x01, 0x54, 0x5f, 0x1e, 0x00, 0x40, 0x22, 0xa4, 0x09, 0x54, 0x41, 0x00, 0x08, +0x10, 0x23, 0x00, 0x06, 0x4e, 0x43, 0x00, 0x06, 0x58, 0x20, 0x80, 0x00, 0x48, 0x00, 0x00, 0x08, +0x50, 0x93, 0x80, 0x10, 0x14, 0x93, 0x00, 0x07, 0x44, 0x20, 0x00, 0x20, 0x00, 0x03, 0x00, 0x06, +0x54, 0x30, 0x00, 0x01, 0x4e, 0x32, 0x00, 0x0a, 0x40, 0x43, 0x88, 0x00, 0x50, 0x11, 0x00, 0x10, +0x14, 0x43, 0x00, 0x04, 0x40, 0x20, 0x80, 0x13, 0x01, 0xe3, 0x00, 0x06, 0x54, 0x5f, 0x00, 0x02, +0x4e, 0x52, 0x00, 0x0a, 0x40, 0x33, 0x88, 0x00, 0x14, 0x33, 0x00, 0x05, 0x50, 0x21, 0x00, 0x08, +0x40, 0x21, 0x00, 0x13, 0x00, 0x13, 0x00, 0x06, 0x54, 0x00, 0x80, 0x04, 0x4e, 0x02, 0x00, 0x0a, +0x40, 0x53, 0x88, 0x00, 0x50, 0x41, 0x00, 0x18, 0x14, 0x53, 0x00, 0x06, 0x40, 0x22, 0x00, 0x13, +0x12, 0x23, 0x00, 0x04, 0x00, 0x23, 0x00, 0x05, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x22, 0xc0, 0x3e, +0x00, 0x03, 0x80, 0x06, 0x02, 0x13, 0x00, 0x04, 0x55, 0xe0, 0x00, 0x40, 0x40, 0x4f, 0x78, 0x1a, +0x40, 0x41, 0x78, 0x1b, 0x40, 0x53, 0x84, 0x00, 0x40, 0x02, 0x90, 0x00, 0x42, 0x50, 0x00, 0x09, +0x14, 0x53, 0x00, 0x0a, 0x01, 0xe3, 0x80, 0x06, 0x44, 0x30, 0x00, 0x00, 0x54, 0x4f, 0x00, 0x3f, +0x40, 0x22, 0x90, 0x00, 0x41, 0xe1, 0x08, 0x09, 0x41, 0xef, 0x08, 0x08, 0x10, 0x43, 0x00, 0x24, +0x15, 0xe3, 0x00, 0x0b, 0x50, 0x03, 0x7f, 0xf4, 0x02, 0x23, 0x80, 0x00, 0x10, 0x33, 0x00, 0x4a, +0x40, 0x43, 0x88, 0x00, 0x40, 0x32, 0x78, 0x01, 0x12, 0x33, 0x00, 0x13, 0x44, 0x10, 0x00, 0x01, +0x02, 0x22, 0x80, 0x00, 0x12, 0x23, 0x00, 0x1d, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x8f, 0x60, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x62, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x22, 0xc0, 0x3c, +0x05, 0xe3, 0x00, 0x07, 0x44, 0x20, 0x00, 0x06, 0x50, 0x1f, 0x00, 0x02, 0x58, 0x04, 0x00, 0x00, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0xbc, 0x4b, 0xe0, 0x3c, 0x01, 0x00, 0x03, 0x80, 0x08, +0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x8c, 0x84, 0x4b, 0xe0, 0x3c, 0x01, 0x14, 0x03, 0x00, 0x0d, +0x50, 0x03, 0x7f, 0xf4, 0x02, 0x44, 0x80, 0x00, 0x12, 0x43, 0x00, 0x1d, 0x02, 0x54, 0x80, 0x04, +0x12, 0x53, 0x00, 0x1c, 0x02, 0x24, 0x80, 0x05, 0x12, 0x23, 0x00, 0x20, 0x46, 0xf0, 0x01, 0x08, +0x58, 0xf7, 0x8d, 0xc0, 0x4b, 0xe0, 0x3c, 0x01, 0x50, 0x03, 0x7f, 0xf4, 0x44, 0x10, 0x00, 0x01, +0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x8f, 0x60, 0x4b, 0xe0, 0x3c, 0x01, 0x4b, 0xe0, 0x70, 0x01, +0x48, 0x00, 0x00, 0x24, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x09, 0xbc, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x67, 0x8f, 0x29, +0x4e, 0x63, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x89, 0x74, 0x44, 0x20, 0x03, 0x17, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x50, 0xa5, 0x00, 0x01, 0x02, 0x14, 0x00, 0x03, +0x40, 0xf5, 0x04, 0x06, 0x4e, 0xf3, 0xfe, 0xc8, 0x51, 0xff, 0x80, 0x14, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x44, 0x10, 0x00, 0x00, +0x44, 0x00, 0x00, 0x03, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x8c, 0x14, 0x4b, 0xe0, 0x3c, 0x01, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x50, 0x01, 0x0f, +0x58, 0x52, 0x89, 0xac, 0x04, 0x12, 0x80, 0x00, 0x44, 0x20, 0x00, 0x00, 0x14, 0x20, 0x80, 0x00, +0x58, 0x32, 0x80, 0x00, 0x04, 0x42, 0x80, 0x00, 0x58, 0x11, 0x00, 0x00, 0x10, 0x22, 0x00, 0x04, +0x58, 0x41, 0x00, 0x00, 0x04, 0x02, 0x80, 0x00, 0x10, 0x20, 0x00, 0x05, 0x04, 0x21, 0x80, 0x00, +0x40, 0x00, 0x8c, 0x08, 0x40, 0x51, 0x00, 0x00, 0x10, 0x12, 0x80, 0x06, 0x50, 0x10, 0x80, 0x01, +0x04, 0x21, 0x80, 0x00, 0x40, 0x51, 0x00, 0x00, 0x44, 0x00, 0x00, 0x08, 0x10, 0x42, 0x80, 0x07, +0x4c, 0x10, 0x7f, 0xee, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, 0x04, 0x10, 0x00, 0x02, +0x00, 0x60, 0x80, 0x06, 0x50, 0x80, 0x80, 0x20, 0x4e, 0x62, 0x00, 0x0c, 0x04, 0x24, 0x00, 0x01, +0x04, 0x14, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x14, 0x20, 0x80, 0x00, 0x48, 0x00, 0x00, 0x52, +0x44, 0x00, 0x00, 0x14, 0x00, 0xa0, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x7c, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x50, 0x0f, 0xff, 0x58, 0x90, 0x00, 0x00, 0x4c, 0x02, 0xc0, 0x06, +0x44, 0x00, 0x01, 0x03, 0x48, 0x00, 0x00, 0x3e, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x0c, +0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x13, 0x00, 0x00, 0x44, 0x20, 0x00, 0x14, 0x58, 0x70, 0x00, 0x00, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0xe4, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x30, 0x00, 0x14, +0x44, 0x2f, 0xe0, 0x00, 0x44, 0x10, 0x00, 0x06, 0x12, 0x33, 0x80, 0x00, 0x12, 0x23, 0x80, 0x01, +0x10, 0x13, 0x80, 0x04, 0x10, 0xa3, 0x80, 0x05, 0x50, 0x73, 0x80, 0x0c, 0x04, 0x54, 0x00, 0x00, +0x58, 0x24, 0x80, 0x00, 0x14, 0x53, 0x80, 0x00, 0x44, 0x10, 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, +0x58, 0x33, 0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x14, 0x43, 0x80, 0x01, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8a, 0x74, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x03, 0x00, 0x00, +0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x07, 0x8b, 0x73, 0x4e, 0x02, 0x00, 0x5e, 0x46, 0x36, 0x04, 0x00, 0x04, 0x41, 0x80, 0x02, +0x58, 0x11, 0x80, 0x00, 0x42, 0x22, 0x5c, 0x08, 0x14, 0x21, 0x80, 0x02, 0x04, 0x60, 0x80, 0x00, +0x46, 0x50, 0x08, 0x00, 0x40, 0x63, 0x14, 0x02, 0x4e, 0x63, 0xff, 0xfa, 0x46, 0x26, 0x04, 0x00, +0x58, 0x21, 0x00, 0x08, 0x04, 0x11, 0x00, 0x00, 0x47, 0xe8, 0x00, 0x21, 0x58, 0x30, 0x80, 0x04, +0x14, 0x31, 0x00, 0x00, 0x59, 0xef, 0x01, 0x00, 0x04, 0x51, 0x00, 0x00, 0x46, 0x38, 0x00, 0x20, +0x58, 0x02, 0x80, 0x08, 0x14, 0x01, 0x00, 0x00, 0x04, 0x41, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, +0x58, 0x12, 0x00, 0x10, 0x14, 0x11, 0x00, 0x00, 0x44, 0x1f, 0xff, 0x9f, 0x04, 0x51, 0x00, 0x00, +0x58, 0x42, 0x80, 0x03, 0x14, 0x41, 0x00, 0x00, 0x04, 0x5f, 0x00, 0x00, 0x40, 0x22, 0x84, 0x02, +0x14, 0x2f, 0x00, 0x00, 0x04, 0x1f, 0x00, 0x00, 0x42, 0x50, 0x98, 0x09, 0x14, 0x5f, 0x00, 0x00, +0x04, 0x11, 0x80, 0x00, 0x41, 0xe0, 0x88, 0x09, 0x41, 0xef, 0x08, 0x08, 0x15, 0xe1, 0x80, 0x00, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x86, 0x7c, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x83, 0x38, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x10, 0x67, 0x8b, 0x73, +0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, 0x46, 0xa0, 0x01, 0x0f, +0x00, 0x55, 0x0b, 0x73, 0x44, 0x90, 0x00, 0x01, 0x4c, 0x54, 0x80, 0x78, 0x46, 0x28, 0x00, 0x20, +0x04, 0x71, 0x00, 0x00, 0x47, 0xe8, 0x00, 0x21, 0x58, 0x83, 0x80, 0x03, 0x14, 0x81, 0x00, 0x00, +0x59, 0xef, 0x01, 0x00, 0x04, 0x0f, 0x00, 0x00, 0x46, 0x76, 0x04, 0x00, 0x58, 0x60, 0x00, 0x40, +0x14, 0x6f, 0x00, 0x00, 0x46, 0x80, 0x00, 0x01, 0x58, 0x84, 0x09, 0x80, 0x04, 0x1f, 0x00, 0x00, +0x58, 0x50, 0x80, 0x60, 0x14, 0x5f, 0x00, 0x00, 0x58, 0x04, 0x80, 0x00, 0x4b, 0xe0, 0x20, 0x01, +0x04, 0x43, 0x80, 0x02, 0x46, 0x66, 0x04, 0x00, 0x58, 0x32, 0x00, 0x10, 0x14, 0x33, 0x80, 0x02, +0x58, 0x63, 0x00, 0x04, 0x04, 0x23, 0x00, 0x00, 0x44, 0x00, 0x00, 0x0a, 0x40, 0x11, 0x24, 0x04, +0x14, 0x13, 0x00, 0x00, 0x46, 0x78, 0x00, 0x20, 0x04, 0x53, 0x00, 0x00, 0x58, 0x73, 0x80, 0xfc, +0x58, 0x42, 0x80, 0x02, 0x14, 0x43, 0x00, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0x04, 0x33, 0x00, 0x00, +0x44, 0x00, 0x00, 0x04, 0x58, 0x21, 0x80, 0x10, 0x14, 0x23, 0x00, 0x00, 0x04, 0x13, 0x00, 0x00, +0x40, 0x50, 0x80, 0x04, 0x14, 0x53, 0x00, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0x04, 0x43, 0x00, 0x00, +0x58, 0x32, 0x00, 0x08, 0x14, 0x33, 0x00, 0x00, 0x58, 0x04, 0x80, 0x00, 0x04, 0x23, 0x80, 0x00, +0x58, 0x11, 0x00, 0x0f, 0x14, 0x13, 0x80, 0x00, 0x04, 0x43, 0x80, 0x00, 0x40, 0x32, 0x10, 0x09, +0x40, 0x31, 0x90, 0x08, 0x14, 0x33, 0x80, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0x04, 0x23, 0x80, 0x00, +0x58, 0x11, 0x00, 0x0f, 0x14, 0x13, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x01, 0x58, 0xf7, 0x85, 0xa4, +0x4b, 0xe0, 0x3c, 0x01, 0x10, 0x95, 0x0b, 0x73, 0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x46, 0x40, 0x01, 0x0f, 0x58, 0x42, 0x0a, 0x74, +0x46, 0x80, 0x01, 0x0f, 0x58, 0x84, 0x0a, 0x70, 0x46, 0x60, 0x01, 0x0f, 0x58, 0x63, 0x09, 0x90, +0x46, 0x30, 0x00, 0x02, 0x58, 0x31, 0x84, 0xe4, 0x46, 0x70, 0x01, 0x0f, 0x58, 0x73, 0x8b, 0x7c, +0x47, 0xc0, 0x01, 0x03, 0x59, 0xce, 0x0b, 0x04, 0x46, 0xa0, 0x01, 0x03, 0x58, 0xa5, 0x0a, 0x38, +0x46, 0x90, 0x01, 0x05, 0x58, 0x94, 0x8b, 0x58, 0x04, 0x24, 0x00, 0x00, 0x44, 0x50, 0x00, 0x02, +0x14, 0x22, 0x00, 0x00, 0x14, 0x04, 0x00, 0x00, 0x4c, 0x02, 0x80, 0x08, 0x44, 0x50, 0x00, 0x05, +0x4c, 0x02, 0xc0, 0x86, 0x48, 0x00, 0x00, 0x7a, 0x14, 0x3f, 0x80, 0x00, 0x14, 0x4f, 0x80, 0x01, +0x04, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x0c, 0x8c, 0x4b, 0xe0, 0x0c, 0x01, +0x00, 0x03, 0x80, 0x00, 0x4b, 0xe0, 0x70, 0x01, 0x00, 0x03, 0x80, 0x00, 0x4b, 0xe0, 0x28, 0x01, +0x4b, 0xe0, 0x24, 0x01, 0x04, 0x33, 0x00, 0x00, 0x44, 0x40, 0x00, 0x01, 0x10, 0x41, 0x86, 0x84, +0x44, 0x30, 0x00, 0x00, 0x04, 0x03, 0x00, 0x00, 0x10, 0x40, 0x06, 0x86, 0x04, 0x53, 0x00, 0x00, +0x10, 0x42, 0x86, 0x85, 0x04, 0x23, 0x00, 0x00, 0x10, 0x31, 0x06, 0x87, 0x04, 0x13, 0x00, 0x00, +0x10, 0x40, 0x86, 0x88, 0x04, 0x03, 0x00, 0x00, 0x10, 0x30, 0x06, 0x89, 0x46, 0xf0, 0x01, 0x03, +0x58, 0xf7, 0x8d, 0xb4, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x8b, 0x98, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x8c, 0xd0, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x83, 0xe4, 0x4b, 0xe0, 0x3c, 0x01, +0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x8b, 0x24, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x05, +0x58, 0xf7, 0x81, 0x8c, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x05, 0x58, 0xf7, 0x89, 0x34, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0xfc, 0x4b, 0xe0, 0x3c, 0x01, +0x46, 0xf0, 0x01, 0x05, 0x58, 0xf7, 0x89, 0x5c, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x08, +0x58, 0xf7, 0x84, 0x14, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x05, 0x04, 0x3f, 0x80, 0x00, +0x04, 0x4f, 0x80, 0x01, 0x48, 0x00, 0x00, 0x0c, 0x01, 0xe3, 0x80, 0x00, 0x4f, 0xe2, 0x00, 0x08, +0x44, 0x10, 0x00, 0x00, 0x10, 0x13, 0x80, 0x00, 0x44, 0x00, 0x00, 0x04, 0x04, 0x54, 0x00, 0x00, +0x4c, 0x02, 0xff, 0x6c, 0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x04, 0x70, 0x00, 0x02, 0x58, 0x60, 0x00, 0x00, +0x50, 0x33, 0x80, 0x20, 0x00, 0x21, 0x80, 0x00, 0x46, 0x10, 0x01, 0x0f, 0x4e, 0x23, 0x00, 0x30, +0x04, 0x51, 0x80, 0x01, 0x04, 0x00, 0x82, 0x9c, 0x40, 0x31, 0x14, 0x06, 0x44, 0x50, 0x00, 0x04, +0x46, 0xf0, 0x01, 0x0f, 0x10, 0x37, 0x8b, 0x7c, 0x4c, 0x02, 0xc0, 0x08, 0x44, 0x10, 0x00, 0x6a, +0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x0a, 0x44, 0x50, 0x00, 0x05, 0x4c, 0x02, 0xc0, 0x0c, +0x44, 0x00, 0x00, 0x01, 0x44, 0x10, 0x00, 0x6a, 0x46, 0xf0, 0x00, 0x07, 0x58, 0xf7, 0x86, 0xd0, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x03, 0x46, 0xf0, 0x01, 0x05, 0x58, 0xf7, 0x8c, 0x60, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x16, 0x04, 0x10, 0x82, 0x9c, +0x44, 0x50, 0x00, 0x04, 0x4c, 0x12, 0x80, 0x08, 0x46, 0x1c, 0x00, 0x00, 0x58, 0x10, 0x80, 0x01, +0x48, 0x00, 0x00, 0x0a, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x86, 0x5c, 0x4b, 0xe0, 0x3c, 0x01, +0x58, 0x10, 0x00, 0x00, 0x00, 0x43, 0x80, 0x0b, 0x54, 0x02, 0x00, 0x01, 0x4e, 0x02, 0x00, 0x0c, +0x58, 0x03, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x06, 0x58, 0xf7, 0x84, 0x48, 0x4b, 0xe0, 0x3c, 0x01, +0x58, 0x10, 0x00, 0x00, 0x58, 0x00, 0x80, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x46, 0xf0, 0x01, 0x0f, +0x04, 0x27, 0x82, 0x9c, 0x4e, 0x23, 0x00, 0x14, 0x44, 0x00, 0x00, 0x01, 0x44, 0x10, 0x00, 0x6a, +0x46, 0xf0, 0x00, 0x07, 0x58, 0xf7, 0x86, 0xd0, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x03, +0x46, 0xf0, 0x01, 0x05, 0x58, 0xf7, 0x8c, 0x60, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x8c, 0x38, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x08, +0x58, 0xf7, 0x84, 0x34, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x05, 0x58, 0xf7, 0x8a, 0x88, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x05, 0x58, 0xf7, 0x8c, 0x60, +0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x44, 0x10, 0x00, 0x00, 0x44, 0x50, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x0f, 0x10, 0x57, 0x8b, 0x7c, 0x46, 0xf0, 0x01, 0x0f, 0x14, 0x17, 0x82, 0x9d, +0x46, 0xf0, 0x01, 0x0f, 0x14, 0x17, 0x82, 0x9c, 0x44, 0x00, 0x00, 0x02, 0x46, 0xf0, 0x01, 0x05, +0x58, 0xf7, 0x8c, 0x60, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x58, 0x60, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x05, 0x58, 0xf7, 0x8e, 0xf8, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x0c, +0x04, 0x73, 0x00, 0x02, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x7c, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x10, 0x0f, 0xff, 0x58, 0x60, 0x00, 0x00, 0x4c, 0x00, 0xc0, 0x18, 0x46, 0xf0, 0x01, 0x16, +0x00, 0x07, 0x8f, 0x29, 0x4e, 0x02, 0x00, 0x04, 0x48, 0x00, 0x00, 0x0c, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x09, 0xd4, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x00, 0x01, 0x03, 0x48, 0x00, 0x00, 0x36, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x0c, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x5f, 0xff, 0xef, 0x44, 0x20, 0x00, 0x0c, 0x44, 0x1f, 0xe0, 0x00, +0x12, 0x20, 0x00, 0x00, 0x12, 0x10, 0x00, 0x01, 0x10, 0x50, 0x00, 0x04, 0x50, 0x40, 0x00, 0x08, +0x00, 0x73, 0x80, 0x07, 0x44, 0x30, 0x00, 0x00, 0x10, 0x70, 0x00, 0x05, 0x10, 0x32, 0x00, 0x00, +0x44, 0x00, 0x00, 0x00, 0x58, 0x23, 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x44, 0x30, 0x00, 0x01, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8a, 0x74, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x8e, 0x14, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x00, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x04, 0x60, 0x00, 0x02, 0x50, 0x63, 0x00, 0x20, 0x00, 0x03, 0x00, 0x02, +0x4e, 0x02, 0x00, 0x06, 0x44, 0x10, 0x00, 0x02, 0x4c, 0x00, 0xc0, 0x70, 0x44, 0x10, 0x00, 0x28, +0x44, 0x00, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x04, 0x58, 0xf7, 0x80, 0x7c, 0x4b, 0xe0, 0x3c, 0x01, +0x58, 0x10, 0x00, 0x00, 0x4e, 0x02, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x02, 0x4e, 0x03, 0x00, 0x04, +0x48, 0x00, 0x00, 0x06, 0x44, 0x20, 0x00, 0x02, 0x4c, 0x01, 0x40, 0x04, 0x14, 0x00, 0x80, 0x02, +0x00, 0x43, 0x00, 0x00, 0x47, 0xe0, 0x04, 0xc4, 0x10, 0x40, 0x80, 0x0c, 0x46, 0x00, 0x02, 0x4b, +0x00, 0x33, 0x00, 0x01, 0x59, 0xef, 0x0b, 0x40, 0x10, 0x30, 0x80, 0x0d, 0x58, 0x00, 0x0a, 0x58, +0x00, 0x33, 0x00, 0x03, 0x10, 0x30, 0x80, 0x0e, 0x00, 0x23, 0x00, 0x04, 0x14, 0x20, 0x80, 0x04, +0x00, 0x73, 0x00, 0x05, 0x56, 0x73, 0x80, 0x02, 0x40, 0x5f, 0x1c, 0x1a, 0x40, 0x50, 0x1c, 0x1b, +0x14, 0x50, 0x80, 0x05, 0x00, 0x23, 0x00, 0x06, 0x14, 0x20, 0x80, 0x06, 0x01, 0xe3, 0x00, 0x07, +0x11, 0xe0, 0x80, 0x1c, 0x00, 0x53, 0x00, 0x08, 0x10, 0x50, 0x80, 0x1d, 0x00, 0x03, 0x00, 0x09, +0x14, 0x00, 0x80, 0x08, 0x04, 0x63, 0x00, 0x03, 0x14, 0x60, 0x80, 0x09, 0x5c, 0xf2, 0x00, 0x04, +0x4e, 0xf2, 0x00, 0x04, 0x4e, 0x33, 0x00, 0x50, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x67, 0x8f, 0x29, +0x4e, 0x63, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x8a, 0x08, 0x44, 0x20, 0x01, 0xe2, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x44, 0x10, 0x00, 0x10, 0x44, 0x00, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x04, 0x58, 0xf7, 0x80, 0x7c, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x10, 0x00, 0x00, +0x4e, 0x02, 0x00, 0x38, 0x44, 0x50, 0x00, 0x01, 0x14, 0x50, 0x00, 0x02, 0x00, 0x43, 0x00, 0x00, +0x10, 0x40, 0x00, 0x0c, 0x00, 0x63, 0x00, 0x01, 0x10, 0x60, 0x00, 0x0d, 0x5c, 0xf2, 0x00, 0x04, +0x4e, 0xf3, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x07, 0x8f, 0x29, 0x4e, 0x03, 0x00, 0x12, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8a, 0x08, +0x44, 0x20, 0x01, 0xf4, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x58, 0x20, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x08, +0x58, 0xf7, 0x81, 0x3c, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x06, +0x46, 0x0c, 0x00, 0x00, 0x58, 0x00, 0x00, 0x9a, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x04, 0x10, 0x00, 0x02, 0x58, 0x60, 0x00, 0x00, +0x00, 0x20, 0x80, 0x04, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x0a, 0x28, 0x44, 0x80, 0x00, 0x00, +0x00, 0x50, 0x00, 0x00, 0x50, 0x34, 0x00, 0x01, 0x4c, 0x51, 0x40, 0x22, 0x04, 0x10, 0x00, 0x01, +0x4e, 0x12, 0x00, 0x1e, 0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x04, 0x01, 0x58, 0x70, 0x00, 0x00, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x72, 0x80, 0x20, 0x46, 0x2c, 0x00, 0x00, 0x58, 0x51, 0x00, 0x9a, +0x4c, 0x72, 0x80, 0x1a, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x03, +0x58, 0xf7, 0x8f, 0x60, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x0e, 0x54, 0x81, 0x80, 0xff, +0x44, 0x50, 0x00, 0x07, 0x50, 0x00, 0x00, 0x08, 0x4c, 0x82, 0xff, 0xd4, 0x44, 0x70, 0x00, 0x00, +0x48, 0x00, 0x00, 0x06, 0x5c, 0xf4, 0x00, 0x07, 0x4e, 0xf3, 0x00, 0x0c, 0x58, 0x03, 0x00, 0x00, +0x44, 0x10, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x8f, 0x60, 0x4b, 0xe0, 0x3c, 0x01, +0x58, 0x03, 0x80, 0x00, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, +0x50, 0x20, 0x80, 0x0c, 0x58, 0xa0, 0x00, 0x00, 0x40, 0x01, 0x00, 0x13, 0x58, 0x70, 0x80, 0x00, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x7c, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x50, 0x0f, 0xff, +0x58, 0x80, 0x00, 0x00, 0x4c, 0x02, 0xc0, 0x06, 0x44, 0x00, 0x01, 0x03, 0x48, 0x00, 0x00, 0x58, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x0c, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x60, 0x00, 0x00, +0x54, 0x03, 0x80, 0x03, 0x4e, 0x02, 0x00, 0x08, 0x40, 0x73, 0x88, 0x09, 0x40, 0x73, 0x88, 0x08, +0x50, 0x73, 0x80, 0x04, 0x50, 0x93, 0x80, 0x0c, 0x44, 0x10, 0x00, 0x00, 0x58, 0x24, 0x80, 0x00, +0x58, 0x03, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0xe4, 0x4b, 0xe0, 0x3c, 0x01, +0x58, 0x23, 0x80, 0x00, 0x58, 0x15, 0x00, 0x00, 0x46, 0x70, 0x01, 0x0f, 0x58, 0x73, 0x8b, 0x7d, +0x50, 0x03, 0x00, 0x0c, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0xbc, 0x4b, 0xe0, 0x3c, 0x01, +0x00, 0x23, 0x80, 0x00, 0x44, 0x30, 0x00, 0x13, 0x44, 0x0f, 0xe0, 0x00, 0x44, 0x1f, 0xff, 0xed, +0x10, 0x33, 0x00, 0x08, 0x12, 0x03, 0x00, 0x01, 0x10, 0x13, 0x00, 0x04, 0x10, 0x23, 0x00, 0x05, +0x44, 0x00, 0x00, 0x00, 0x12, 0x93, 0x00, 0x00, 0x58, 0x24, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, +0x58, 0x30, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8a, 0x74, 0x4b, 0xe0, 0x3c, 0x01, +0x00, 0x53, 0x80, 0x00, 0x50, 0x42, 0x80, 0x01, 0x10, 0x43, 0x80, 0x00, 0x3a, 0x6f, 0xa8, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x04, 0x80, 0x00, 0x02, 0x44, 0x00, 0x00, 0x28, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x7c, 0x4b, 0xe0, 0x3c, 0x01, 0x54, 0x70, 0x00, 0xff, +0x58, 0x03, 0x80, 0x00, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x81, 0x0c, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x28, 0x58, 0x60, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x02, +0x58, 0xf7, 0x84, 0xe4, 0x4b, 0xe0, 0x3c, 0x01, 0x00, 0x24, 0x00, 0x07, 0x44, 0x40, 0x00, 0x28, +0x44, 0x3f, 0xe0, 0x00, 0x44, 0x1f, 0xff, 0xed, 0x44, 0x00, 0x00, 0x09, 0x12, 0x43, 0x00, 0x00, +0x12, 0x33, 0x00, 0x01, 0x10, 0x13, 0x00, 0x04, 0x10, 0x23, 0x00, 0x05, 0x10, 0x03, 0x00, 0x08, +0x46, 0x80, 0x00, 0x02, 0x58, 0x84, 0x04, 0xbc, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8a, 0x60, +0x44, 0x20, 0x00, 0x09, 0x50, 0x03, 0x00, 0x0c, 0x4b, 0xe0, 0x20, 0x01, 0x50, 0x03, 0x00, 0x1c, +0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8a, 0x6c, 0x44, 0x20, 0x00, 0x0d, 0x4b, 0xe0, 0x20, 0x01, +0x44, 0x00, 0x00, 0x00, 0x58, 0x23, 0x80, 0x00, 0x44, 0x10, 0x00, 0x01, 0x58, 0x30, 0x00, 0x00, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8a, 0x74, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x00, +0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, 0x04, 0x80, 0x00, 0x02, +0x44, 0x00, 0x00, 0x14, 0x58, 0x90, 0x80, 0x00, 0x00, 0xa4, 0x00, 0x07, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x81, 0x7c, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x50, 0x0f, 0xff, 0x58, 0x70, 0x00, 0x00, +0x4c, 0x02, 0xc0, 0x06, 0x44, 0x00, 0x01, 0x03, 0x48, 0x00, 0x00, 0x3e, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x81, 0x0c, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x10, 0x00, 0x00, 0x44, 0x20, 0x00, 0x14, +0x58, 0x60, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0xe4, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x40, 0x00, 0x14, 0x44, 0x3f, 0xe0, 0x00, 0x44, 0x2f, 0xff, 0xed, 0x44, 0x00, 0x00, 0x00, +0x10, 0x23, 0x00, 0x04, 0x12, 0x43, 0x00, 0x00, 0x12, 0x33, 0x00, 0x01, 0x10, 0xa3, 0x00, 0x05, +0x10, 0x03, 0x00, 0x08, 0x50, 0x63, 0x00, 0x0c, 0x00, 0x84, 0x00, 0x09, 0x44, 0x00, 0x00, 0x00, +0x10, 0x83, 0x00, 0x00, 0x14, 0x93, 0x00, 0x01, 0x58, 0x23, 0x80, 0x00, 0x44, 0x10, 0x00, 0x01, +0x58, 0x30, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8a, 0x74, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x00, 0x00, 0x00, 0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x04, 0x20, 0x00, 0x02, 0x00, 0x11, 0x00, 0x0b, 0x54, 0x10, 0x80, 0x01, +0x4e, 0x13, 0x00, 0x06, 0x58, 0x00, 0x80, 0x00, 0x48, 0x00, 0x00, 0x0a, 0x44, 0x10, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x06, 0x58, 0xf7, 0x84, 0x48, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x51, 0xff, 0xff, 0xc0, +0x46, 0x50, 0x01, 0x0e, 0x58, 0x52, 0x8d, 0x6c, 0x58, 0x70, 0x00, 0x00, 0x3a, 0x02, 0x8c, 0x04, +0x58, 0x4f, 0x80, 0x00, 0x3a, 0x02, 0x0c, 0x24, 0x3a, 0x02, 0x8c, 0x04, 0x3a, 0x02, 0x0c, 0x24, +0x3a, 0x02, 0x8c, 0x04, 0x3a, 0x02, 0x0c, 0x24, 0x3a, 0x02, 0x8c, 0x00, 0x3a, 0x02, 0x08, 0x24, +0x04, 0x83, 0x80, 0x02, 0x10, 0x32, 0x00, 0x00, 0x50, 0x24, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, +0x4e, 0x03, 0x00, 0x58, 0x46, 0x60, 0x00, 0x07, 0x58, 0x63, 0x0a, 0x68, 0x46, 0x10, 0x01, 0x0f, +0x58, 0x10, 0x89, 0xb4, 0x44, 0x20, 0x00, 0x03, 0x44, 0x00, 0x00, 0x35, 0x4b, 0xe0, 0x18, 0x01, +0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x89, 0xb7, 0x44, 0x20, 0x00, 0x01, 0x44, 0x00, 0x00, 0x48, +0x4b, 0xe0, 0x18, 0x01, 0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x89, 0xb8, 0x44, 0x20, 0x00, 0x01, +0x44, 0x00, 0x00, 0x50, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x89, 0xb9, +0x44, 0x20, 0x00, 0x0f, 0x44, 0x00, 0x00, 0x53, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x10, 0x01, 0x0f, +0x58, 0x10, 0x89, 0xc8, 0x44, 0x20, 0x00, 0x0e, 0x44, 0x00, 0x00, 0xa0, 0x4b, 0xe0, 0x18, 0x01, +0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x89, 0xd6, 0x44, 0x20, 0x00, 0x10, 0x44, 0x00, 0x00, 0xc0, +0x4b, 0xe0, 0x18, 0x01, 0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x89, 0xe6, 0x44, 0x20, 0x00, 0x07, +0x44, 0x00, 0x00, 0xd0, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x89, 0xed, +0x44, 0x20, 0x00, 0x03, 0x44, 0x00, 0x00, 0xf4, 0x4b, 0xe0, 0x18, 0x01, 0x48, 0x00, 0x00, 0x34, +0x58, 0x6f, 0x80, 0x00, 0x44, 0x10, 0x00, 0x00, 0x39, 0xe3, 0x04, 0x00, 0x02, 0x31, 0x00, 0x02, +0x46, 0x40, 0x01, 0x0f, 0x58, 0x42, 0x09, 0xb4, 0x40, 0x00, 0x90, 0x00, 0x50, 0x10, 0x80, 0x01, +0x4d, 0xe1, 0x80, 0x18, 0x00, 0x24, 0x00, 0x0b, 0x54, 0x11, 0x00, 0x01, 0x4e, 0x13, 0x00, 0x04, +0x48, 0x00, 0x00, 0x0c, 0x58, 0x03, 0x80, 0x00, 0x44, 0x11, 0x00, 0x03, 0x46, 0xf0, 0x01, 0x06, +0x58, 0xf7, 0x84, 0x48, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x01, 0x00, 0x03, 0x48, 0x00, 0x00, 0x22, +0x00, 0x51, 0x00, 0x06, 0x50, 0x21, 0x00, 0x04, 0x10, 0x50, 0x00, 0x00, 0x44, 0x00, 0x00, 0x3d, +0x4c, 0x10, 0x7f, 0xd4, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x85, 0x60, 0x4b, 0xe0, 0x3c, 0x01, +0x00, 0x34, 0x00, 0x0b, 0x54, 0x01, 0x80, 0x01, 0x4e, 0x02, 0x00, 0x0c, 0x58, 0x03, 0x80, 0x00, +0x44, 0x10, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x06, 0x58, 0xf7, 0x84, 0x48, 0x4b, 0xe0, 0x3c, 0x01, +0x51, 0xff, 0x80, 0x40, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x04, 0x20, 0x00, 0x02, 0x00, 0x11, 0x00, 0x20, 0x5c, 0xf0, 0x80, 0x03, +0x4e, 0xf3, 0x00, 0x06, 0x44, 0x11, 0x00, 0x03, 0x48, 0x00, 0x00, 0x08, 0x46, 0xf0, 0x01, 0x0f, +0x10, 0x17, 0x89, 0x94, 0x44, 0x10, 0x00, 0x00, 0x00, 0x41, 0x00, 0x0b, 0x54, 0x22, 0x00, 0x01, +0x4e, 0x22, 0x00, 0x0a, 0x46, 0xf0, 0x01, 0x06, 0x58, 0xf7, 0x84, 0x48, 0x4b, 0xe0, 0x3c, 0x01, +0x58, 0x10, 0x00, 0x00, 0x58, 0x00, 0x80, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x04, 0x20, 0x00, 0x02, +0x00, 0x11, 0x00, 0x0b, 0x54, 0x10, 0x80, 0x01, 0x4e, 0x13, 0x00, 0x06, 0x58, 0x00, 0x80, 0x00, +0x48, 0x00, 0x00, 0x0a, 0x44, 0x10, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x06, 0x58, 0xf7, 0x84, 0x48, +0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xbc, 0x46, 0x40, 0x01, 0x0e, 0x58, 0x42, 0x0d, 0xac, +0x59, 0xc0, 0x00, 0x00, 0x3a, 0x02, 0x0c, 0x04, 0x50, 0x5f, 0x80, 0x24, 0x3a, 0x02, 0x8c, 0x24, +0x3a, 0x02, 0x08, 0x00, 0x3a, 0x02, 0x88, 0x20, 0x04, 0x2e, 0x00, 0x02, 0x14, 0x2f, 0x80, 0x03, +0x50, 0x91, 0x00, 0x20, 0x00, 0x04, 0x80, 0x01, 0x00, 0xa4, 0x80, 0x00, 0x54, 0x10, 0x00, 0x20, +0x00, 0x34, 0x80, 0x03, 0x4e, 0x12, 0x00, 0x06, 0x44, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x46, +0x50, 0x75, 0x7f, 0xff, 0x54, 0x63, 0x80, 0xff, 0x5c, 0xf3, 0x00, 0x05, 0x4e, 0xf2, 0x00, 0x06, +0x00, 0x24, 0x80, 0x14, 0x48, 0x00, 0x00, 0x18, 0x51, 0xe5, 0x7f, 0xfa, 0x54, 0x8f, 0x00, 0xff, +0x5c, 0xf4, 0x00, 0x05, 0x4e, 0xf2, 0x00, 0x06, 0x00, 0x24, 0x80, 0x15, 0x48, 0x00, 0x00, 0x0c, +0x50, 0x05, 0x7f, 0xf5, 0x54, 0x10, 0x00, 0xff, 0x5c, 0xf0, 0x80, 0x04, 0x4e, 0xf2, 0x01, 0x0c, +0x00, 0x24, 0x80, 0x16, 0x40, 0x41, 0x00, 0x10, 0x4e, 0x44, 0x00, 0x10, 0x42, 0x81, 0x18, 0x0b, +0x40, 0x74, 0x20, 0x00, 0x50, 0x53, 0xff, 0xff, 0x54, 0x61, 0x00, 0x3f, 0x42, 0x22, 0x98, 0x24, +0x40, 0x11, 0x00, 0x10, 0x48, 0x00, 0x00, 0x04, 0x44, 0x10, 0x00, 0x00, 0x00, 0x04, 0x80, 0x02, +0x55, 0xe0, 0x00, 0x02, 0x4f, 0xe2, 0x00, 0x0a, 0x46, 0x28, 0x00, 0x22, 0x50, 0x31, 0xff, 0xfa, +0x04, 0x41, 0x00, 0x00, 0x54, 0x31, 0x80, 0xff, 0x00, 0x24, 0x80, 0x13, 0x40, 0x61, 0x84, 0x00, +0x54, 0x53, 0x00, 0xff, 0x40, 0x41, 0x18, 0x09, 0x44, 0x10, 0x00, 0x02, 0x14, 0x5f, 0x80, 0x05, +0x4c, 0x40, 0xc0, 0x0c, 0x54, 0x81, 0x00, 0x3f, 0x52, 0x74, 0x00, 0x00, 0x40, 0x43, 0x80, 0x10, +0x14, 0x4f, 0x80, 0x04, 0x48, 0x00, 0x00, 0x0e, 0x45, 0xe0, 0x00, 0x03, 0x4c, 0x4f, 0x00, 0x06, +0x44, 0x20, 0x00, 0x00, 0x48, 0x00, 0x00, 0x04, 0x54, 0x21, 0x00, 0x3f, 0x14, 0x2f, 0x80, 0x04, +0x50, 0x2f, 0x80, 0x40, 0x58, 0x04, 0x80, 0x00, 0x50, 0x3f, 0x80, 0x24, 0x14, 0x2f, 0x80, 0x01, +0x14, 0x9f, 0x80, 0x06, 0x15, 0xcf, 0x80, 0x07, 0x58, 0x91, 0x80, 0x00, 0x59, 0xc5, 0x00, 0x00, +0x58, 0xa0, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x44, 0x50, 0x00, 0x02, 0x40, 0x10, 0x18, 0x09, +0x44, 0x30, 0x00, 0x00, 0x4c, 0x12, 0xc0, 0x0a, 0x54, 0x60, 0x00, 0x3f, 0x52, 0x13, 0x00, 0x00, +0x40, 0x30, 0x80, 0x10, 0x48, 0x00, 0x00, 0x08, 0x44, 0x40, 0x00, 0x03, 0x4c, 0x12, 0x40, 0x04, +0x54, 0x30, 0x00, 0x3f, 0x00, 0x64, 0x80, 0x01, 0x00, 0x74, 0x80, 0x00, 0x04, 0x1f, 0x80, 0x05, +0x44, 0x80, 0x00, 0x07, 0x58, 0x53, 0x00, 0x00, 0x42, 0x53, 0xa0, 0x73, 0x40, 0x20, 0x8c, 0x00, +0x46, 0x30, 0x01, 0x12, 0x58, 0x31, 0x8b, 0x98, 0x41, 0xe2, 0x8c, 0x00, 0x54, 0x81, 0x00, 0xff, +0x10, 0x8f, 0x00, 0x00, 0x58, 0x3f, 0x00, 0x00, 0x58, 0x13, 0x80, 0x00, 0x58, 0x23, 0x00, 0x00, +0x44, 0x00, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x8d, 0x20, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x50, 0x00, 0x02, 0x50, 0x94, 0x80, 0x02, 0x4c, 0x72, 0xc0, 0x1e, 0x04, 0x3f, 0x80, 0x04, +0x46, 0x00, 0x01, 0x12, 0x58, 0x00, 0x0b, 0x98, 0x41, 0xe4, 0x0c, 0x00, 0x40, 0x43, 0x00, 0x00, +0x50, 0x53, 0x00, 0x15, 0x11, 0xe2, 0x00, 0x15, 0x40, 0x32, 0x80, 0x00, 0x58, 0x23, 0x00, 0x00, +0x44, 0x00, 0x00, 0x00, 0x44, 0x10, 0x00, 0x03, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x8d, 0x20, +0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x5f, 0x80, 0x01, 0x50, 0xa5, 0x00, 0x01, 0x4c, 0x92, 0xff, 0x9c, +0x04, 0x9f, 0x80, 0x06, 0x58, 0xae, 0x00, 0x00, 0x00, 0x54, 0x80, 0x04, 0x00, 0x04, 0x80, 0x03, +0x51, 0xe5, 0x7f, 0xff, 0x40, 0x12, 0x80, 0x01, 0x54, 0x4f, 0x00, 0xff, 0x05, 0xcf, 0x80, 0x07, +0x40, 0x10, 0x84, 0x00, 0x5c, 0xf2, 0x00, 0x05, 0x4e, 0xf2, 0x00, 0x06, 0x00, 0x34, 0x80, 0x17, +0x48, 0x00, 0x00, 0x18, 0x50, 0x25, 0x7f, 0xfa, 0x54, 0x31, 0x00, 0xff, 0x5c, 0xf1, 0x80, 0x05, +0x4e, 0xf2, 0x00, 0x06, 0x00, 0x34, 0x80, 0x18, 0x48, 0x00, 0x00, 0x0c, 0x51, 0xe5, 0x7f, 0xf5, +0x54, 0x4f, 0x00, 0xff, 0x5c, 0xf2, 0x00, 0x04, 0x4e, 0xf2, 0x00, 0x1e, 0x00, 0x34, 0x80, 0x19, +0x40, 0x01, 0x80, 0x10, 0x4e, 0x05, 0x00, 0x06, 0x44, 0x20, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0e, +0x43, 0xe1, 0x98, 0x0b, 0x40, 0x4f, 0x78, 0x00, 0x50, 0x22, 0x7f, 0xff, 0x54, 0x31, 0x80, 0x3f, +0x42, 0x51, 0x0c, 0x24, 0x40, 0x22, 0x80, 0x10, 0x40, 0x01, 0x08, 0x00, 0x40, 0x20, 0x04, 0x00, +0x48, 0x00, 0x00, 0x12, 0x04, 0x2f, 0x80, 0x03, 0x00, 0x51, 0x00, 0x0b, 0x54, 0x12, 0x80, 0x01, +0x4e, 0x12, 0x00, 0x26, 0x46, 0x1c, 0x00, 0x00, 0x58, 0x0e, 0x00, 0x00, 0x58, 0x10, 0x80, 0x01, +0x48, 0x00, 0x00, 0x16, 0x47, 0xe6, 0x02, 0x01, 0x14, 0x2f, 0x03, 0x46, 0x04, 0x4f, 0x80, 0x03, +0x00, 0x32, 0x00, 0x0b, 0x54, 0x11, 0x80, 0x01, 0x4e, 0x13, 0x00, 0x06, 0x58, 0x00, 0x80, 0x00, +0x48, 0x00, 0x00, 0x12, 0x58, 0x0e, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x06, +0x58, 0xf7, 0x84, 0x48, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x06, 0x46, 0x0c, 0x00, 0x00, +0x58, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x44, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xd4, 0x46, 0x70, 0x01, 0x0e, 0x58, 0x73, 0x8d, 0xc8, +0x54, 0x90, 0x00, 0xff, 0x3a, 0x03, 0x8c, 0x04, 0x50, 0x6f, 0x80, 0x0c, 0x46, 0x40, 0x01, 0x0f, +0x58, 0x42, 0x09, 0xb4, 0x3a, 0x03, 0x0c, 0x24, 0x3a, 0x03, 0x88, 0x00, 0x58, 0x33, 0x00, 0x00, +0x00, 0x62, 0x00, 0x02, 0x3a, 0x01, 0x88, 0x20, 0x54, 0x53, 0x00, 0x20, 0x00, 0x32, 0x00, 0x0a, +0x4e, 0x52, 0x00, 0x06, 0x44, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x50, 0x04, 0xff, 0xff, +0x54, 0x10, 0x00, 0xff, 0x5c, 0xf0, 0x80, 0x05, 0x4e, 0xf2, 0x00, 0x06, 0x00, 0x22, 0x00, 0x0b, +0x48, 0x00, 0x00, 0x18, 0x50, 0x84, 0xff, 0xfa, 0x54, 0x24, 0x00, 0xff, 0x5c, 0xf1, 0x00, 0x05, +0x4e, 0xf2, 0x00, 0x06, 0x00, 0x22, 0x00, 0x0c, 0x48, 0x00, 0x00, 0x0c, 0x51, 0xc4, 0xff, 0xf5, +0x54, 0xae, 0x00, 0xff, 0x5c, 0xf5, 0x00, 0x04, 0x4e, 0xf2, 0x01, 0x0c, 0x00, 0x22, 0x00, 0x0d, +0x40, 0x41, 0x00, 0x10, 0x4e, 0x44, 0x00, 0x10, 0x42, 0x11, 0x18, 0x0b, 0x40, 0x60, 0x84, 0x00, +0x50, 0x53, 0x7f, 0xff, 0x54, 0x71, 0x00, 0x3f, 0x43, 0xe2, 0x9c, 0x24, 0x40, 0x1f, 0x00, 0x10, +0x48, 0x00, 0x00, 0x04, 0x44, 0x10, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x27, 0x89, 0xb5, +0x54, 0x01, 0x00, 0x02, 0x4e, 0x02, 0x00, 0x0a, 0x46, 0xa8, 0x00, 0x22, 0x50, 0x31, 0xff, 0xfa, +0x04, 0x05, 0x00, 0x00, 0x54, 0x31, 0x80, 0xff, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x27, 0x89, 0xb8, +0x40, 0x51, 0x84, 0x00, 0x55, 0xe2, 0x80, 0xff, 0x40, 0x41, 0x18, 0x09, 0x45, 0xc0, 0x00, 0x02, +0x15, 0xef, 0x80, 0x01, 0x4c, 0x4e, 0x40, 0x0a, 0x54, 0x61, 0x00, 0x3f, 0x52, 0x73, 0x00, 0x00, +0x40, 0x23, 0x80, 0x10, 0x48, 0x00, 0x00, 0x0e, 0x44, 0x10, 0x00, 0x03, 0x4c, 0x40, 0x80, 0x08, +0x44, 0x00, 0x00, 0x00, 0x14, 0x0f, 0x80, 0x00, 0x48, 0x00, 0x00, 0x06, 0x54, 0x21, 0x00, 0x3f, +0x14, 0x2f, 0x80, 0x00, 0x46, 0xa0, 0x01, 0x0f, 0x58, 0xa5, 0x09, 0xc8, 0x51, 0xcf, 0x80, 0x0c, +0x00, 0x15, 0x00, 0x00, 0x44, 0x80, 0x00, 0x02, 0x40, 0x20, 0x98, 0x09, 0x44, 0x00, 0x00, 0x00, +0x4c, 0x24, 0x40, 0x0a, 0x54, 0x30, 0x80, 0x3f, 0x52, 0x21, 0x80, 0x00, 0x40, 0x01, 0x00, 0x10, +0x48, 0x00, 0x00, 0x08, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x22, 0xc0, 0x04, 0x54, 0x00, 0x80, 0x3f, +0x00, 0x6e, 0x00, 0x01, 0x00, 0x7e, 0x00, 0x00, 0x04, 0x3f, 0x80, 0x01, 0x44, 0x80, 0x00, 0x07, +0x58, 0x23, 0x00, 0x00, 0x42, 0x23, 0xa0, 0x73, 0x40, 0x01, 0x80, 0x00, 0x46, 0x10, 0x01, 0x12, +0x58, 0x10, 0x8b, 0x98, 0x40, 0x41, 0x04, 0x00, 0x54, 0x80, 0x00, 0xff, 0x10, 0x82, 0x00, 0x00, +0x58, 0x32, 0x00, 0x00, 0x58, 0x13, 0x80, 0x00, 0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x8d, 0x20, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x50, 0x00, 0x02, +0x50, 0xa5, 0x00, 0x01, 0x4c, 0x72, 0xc0, 0x1e, 0x04, 0x1f, 0x80, 0x00, 0x46, 0x40, 0x01, 0x12, +0x58, 0x42, 0x0b, 0x98, 0x40, 0x54, 0x04, 0x00, 0x41, 0xe3, 0x10, 0x00, 0x50, 0x03, 0x00, 0x15, +0x10, 0x5f, 0x00, 0x15, 0x40, 0x30, 0x10, 0x00, 0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, +0x44, 0x10, 0x00, 0x03, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x8d, 0x20, 0x4b, 0xe0, 0x3c, 0x01, +0x46, 0x50, 0x01, 0x0f, 0x58, 0x52, 0x89, 0xd6, 0x51, 0xce, 0x00, 0x02, 0x4c, 0xa2, 0xff, 0x9a, +0x50, 0x12, 0xff, 0xde, 0x00, 0x20, 0x80, 0x0a, 0x00, 0x40, 0x80, 0x10, 0x50, 0x54, 0xff, 0xff, +0x40, 0x02, 0x08, 0x01, 0x41, 0xe0, 0x00, 0x00, 0x54, 0x32, 0x80, 0xff, 0x54, 0x2f, 0x00, 0xff, +0x5c, 0xf1, 0x80, 0x05, 0x4e, 0xf2, 0x00, 0x06, 0x00, 0x00, 0x80, 0x11, 0x48, 0x00, 0x00, 0x18, +0x51, 0xe4, 0xff, 0xfa, 0x54, 0x3f, 0x00, 0xff, 0x5c, 0xf1, 0x80, 0x05, 0x4e, 0xf2, 0x00, 0x06, +0x00, 0x00, 0x80, 0x12, 0x48, 0x00, 0x00, 0x0c, 0x50, 0x04, 0xff, 0xf5, 0x54, 0x50, 0x00, 0xff, +0x5c, 0xf2, 0x80, 0x04, 0x4e, 0xf2, 0x00, 0x26, 0x00, 0x00, 0x80, 0x13, 0x40, 0x10, 0x00, 0x10, +0x4e, 0x15, 0x00, 0x06, 0x44, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0e, 0x42, 0x10, 0x18, 0x0b, +0x40, 0x50, 0x84, 0x00, 0x50, 0x32, 0xff, 0xff, 0x55, 0xe0, 0x00, 0x3f, 0x42, 0x41, 0xf8, 0x24, +0x40, 0x12, 0x00, 0x10, 0x40, 0x30, 0x84, 0x00, 0x40, 0x41, 0x0c, 0x00, 0x46, 0x26, 0x02, 0x01, +0x54, 0x02, 0x00, 0xff, 0x14, 0x01, 0x03, 0x46, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x06, +0x46, 0x0c, 0x00, 0x00, 0x58, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x2c, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xe4, 0x44, 0x10, 0x00, 0x00, +0x10, 0x1f, 0x80, 0x17, 0x14, 0x1f, 0x80, 0x04, 0x12, 0x1f, 0x80, 0x0a, 0x05, 0xc0, 0x00, 0x02, +0x50, 0x2e, 0x00, 0x20, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x37, 0x82, 0x67, 0x00, 0x01, 0x00, 0x00, +0x04, 0x81, 0x00, 0x01, 0x00, 0x21, 0x00, 0x01, 0x40, 0xf0, 0x0c, 0x06, 0x4e, 0xf2, 0x00, 0xd2, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x22, 0x80, 0xce, 0x50, 0x71, 0x7f, 0xfe, 0x54, 0x63, 0x80, 0xff, +0x5c, 0xf3, 0x00, 0x03, 0x4e, 0xf2, 0x00, 0xc6, 0x44, 0x90, 0x00, 0x02, 0x4c, 0x24, 0x80, 0x06, +0x58, 0x90, 0x80, 0x00, 0x48, 0x00, 0x00, 0x14, 0x44, 0xa0, 0x01, 0x00, 0x4c, 0x85, 0x00, 0x0c, +0x56, 0x34, 0x02, 0x00, 0x45, 0xe0, 0x00, 0x14, 0x40, 0x9f, 0x0c, 0x1a, 0x40, 0x90, 0x8c, 0x1b, +0x48, 0x00, 0x00, 0x04, 0x44, 0x90, 0x00, 0x24, 0x40, 0x94, 0x80, 0x13, 0x44, 0x70, 0x00, 0x00, +0x50, 0x1f, 0x80, 0x14, 0x50, 0x2f, 0x80, 0x17, 0x50, 0x3f, 0x80, 0x10, 0x58, 0x43, 0x80, 0x00, +0x58, 0x53, 0x80, 0x00, 0x14, 0x7f, 0x80, 0x00, 0x14, 0x7f, 0x80, 0x01, 0x14, 0x7f, 0x80, 0x02, +0x14, 0x7f, 0x80, 0x03, 0x46, 0xf0, 0x01, 0x09, 0x58, 0xf7, 0x80, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x04, 0x1f, 0x80, 0x04, 0x4e, 0x13, 0x00, 0x08, 0x46, 0x0c, 0x00, 0x00, 0x58, 0x00, 0x00, 0x01, +0x48, 0x00, 0x00, 0x8c, 0x50, 0x94, 0x80, 0x0c, 0x40, 0x04, 0x80, 0x13, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x81, 0x7c, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x20, 0x0f, 0xff, 0x58, 0xa0, 0x00, 0x00, +0x4c, 0x01, 0x40, 0x06, 0x44, 0x00, 0x01, 0x03, 0x48, 0x00, 0x00, 0x78, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x81, 0x0c, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x13, 0x80, 0x00, 0x58, 0x24, 0x80, 0x00, +0x58, 0x60, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0xe4, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x00, 0x01, 0x00, 0x4c, 0x80, 0x00, 0x08, 0x40, 0x40, 0x04, 0x08, 0x4c, 0x82, 0x40, 0x5a, +0x48, 0x00, 0x00, 0x28, 0x04, 0x3f, 0x80, 0x04, 0x51, 0xe3, 0x00, 0x0c, 0x50, 0x01, 0x80, 0x14, +0x04, 0x20, 0x00, 0x00, 0x50, 0x11, 0x80, 0x18, 0x14, 0x2f, 0x00, 0x00, 0x50, 0x51, 0x80, 0x1c, +0x04, 0x40, 0x80, 0x00, 0x50, 0x01, 0x80, 0x20, 0x14, 0x4f, 0x00, 0x01, 0x50, 0x31, 0x80, 0x24, +0x04, 0x22, 0x80, 0x00, 0x14, 0x2f, 0x00, 0x02, 0x04, 0x10, 0x00, 0x00, 0x14, 0x1f, 0x00, 0x03, +0x04, 0x51, 0x80, 0x00, 0x14, 0x8f, 0x00, 0x05, 0x14, 0x5f, 0x00, 0x04, 0x48, 0x00, 0x00, 0x0e, +0x04, 0x4f, 0x80, 0x04, 0x51, 0xe3, 0x00, 0x0c, 0x50, 0x32, 0x00, 0x34, 0x04, 0x51, 0x80, 0x00, +0x14, 0x8f, 0x00, 0x01, 0x14, 0x5f, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x07, 0x45, 0xe0, 0x00, 0x0c, +0x44, 0x0f, 0xe0, 0x00, 0x44, 0x1f, 0xff, 0xed, 0x12, 0x03, 0x00, 0x01, 0x10, 0x13, 0x00, 0x04, +0x10, 0x23, 0x00, 0x05, 0x44, 0x00, 0x00, 0x00, 0x11, 0xe3, 0x00, 0x08, 0x12, 0x93, 0x00, 0x00, +0x58, 0x25, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x58, 0x30, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x8a, 0x74, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x06, +0x46, 0x0c, 0x00, 0x00, 0x58, 0x00, 0x00, 0xbb, 0x51, 0xff, 0x80, 0x1c, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0x14, 0x45, 0xc0, 0x00, 0x00, +0x44, 0x10, 0x00, 0x00, 0x14, 0x0f, 0x80, 0x05, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x0a, 0x7c, +0x14, 0x1f, 0x80, 0x34, 0x13, 0xcf, 0x80, 0x71, 0x13, 0xcf, 0x80, 0x70, 0x13, 0xcf, 0x80, 0x6f, +0x11, 0xcf, 0x80, 0xe7, 0x11, 0xcf, 0x80, 0xe6, 0x11, 0xcf, 0x80, 0xe5, 0x14, 0x1f, 0x80, 0x36, +0x14, 0x1f, 0x80, 0x35, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, +0x04, 0x0f, 0x80, 0x05, 0x04, 0xa0, 0x00, 0x02, 0x50, 0x85, 0x00, 0x20, 0x00, 0x94, 0x00, 0x0e, +0x40, 0x24, 0x80, 0x10, 0x4e, 0x24, 0x00, 0x06, 0x44, 0x40, 0xff, 0xff, 0x48, 0x00, 0x01, 0xde, +0x50, 0x6f, 0x80, 0xac, 0x50, 0x1f, 0x80, 0x3c, 0x58, 0x23, 0x00, 0x00, 0x50, 0x3f, 0x80, 0xc4, +0x50, 0x7f, 0x80, 0xd4, 0x58, 0x04, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x80, 0xe4, +0x4b, 0xe0, 0x3c, 0x01, 0x14, 0x7f, 0x80, 0x00, 0x50, 0x7f, 0x80, 0xde, 0x14, 0x7f, 0x80, 0x01, +0x50, 0x7f, 0x80, 0xe5, 0x50, 0x4f, 0x80, 0xe0, 0x14, 0x7f, 0x80, 0x02, 0x58, 0x04, 0x80, 0x00, +0x50, 0x7f, 0x80, 0xd0, 0x50, 0x1f, 0x80, 0xe2, 0x50, 0x2f, 0x80, 0xe7, 0x50, 0x3f, 0x80, 0xd8, +0x50, 0x5f, 0x80, 0xe6, 0x14, 0x7f, 0x80, 0x03, 0x46, 0xf0, 0x01, 0x09, 0x58, 0xf7, 0x80, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x02, 0x73, 0x00, 0x00, 0x02, 0x4f, 0x80, 0x71, 0x4c, 0x43, 0xc0, 0x20, +0x00, 0x5f, 0x80, 0xe7, 0x01, 0xe3, 0x00, 0x08, 0x4c, 0x5f, 0x40, 0x1a, 0x02, 0x0f, 0x80, 0x70, +0x02, 0x23, 0x00, 0x01, 0x4c, 0x01, 0x40, 0x14, 0x00, 0x3f, 0x80, 0xe6, 0x00, 0x13, 0x00, 0x09, +0x4c, 0x30, 0xc0, 0x0e, 0x03, 0xef, 0x80, 0x6f, 0x02, 0x43, 0x00, 0x02, 0x4d, 0xe2, 0x40, 0x08, +0x00, 0x53, 0x00, 0x0a, 0x00, 0x6f, 0x80, 0xe5, 0x4c, 0x62, 0x81, 0xc8, 0x50, 0x0f, 0x80, 0xac, +0x00, 0x40, 0x00, 0x09, 0x00, 0x20, 0x00, 0x08, 0x02, 0x30, 0x00, 0x01, 0x02, 0x50, 0x00, 0x02, +0x00, 0x60, 0x00, 0x0a, 0x58, 0x13, 0x80, 0x00, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x0a, 0xa4, +0x14, 0x6f, 0x80, 0x00, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x40, 0xff, 0xfe, 0x48, 0x00, 0x01, 0x6a, 0x11, 0xcf, 0x80, 0xc7, 0x11, 0xcf, 0x80, 0xc5, +0x48, 0x00, 0x00, 0x08, 0x44, 0x20, 0x00, 0x01, 0x10, 0x2f, 0x80, 0xc7, 0x10, 0x2f, 0x80, 0xc5, +0x01, 0xe4, 0x00, 0x0c, 0x50, 0x7f, 0x80, 0xc4, 0x11, 0xe3, 0x80, 0x07, 0x50, 0x6f, 0x80, 0x3c, +0x00, 0x44, 0x00, 0x0b, 0x44, 0x30, 0x00, 0x01, 0x10, 0x43, 0x80, 0x09, 0x10, 0x33, 0x00, 0x18, +0x00, 0x14, 0x00, 0x00, 0x4e, 0x13, 0x01, 0x48, 0x51, 0xcf, 0x80, 0xac, 0x58, 0x13, 0x00, 0x00, +0x58, 0x2e, 0x00, 0x00, 0x58, 0x33, 0x80, 0x00, 0x58, 0x04, 0x80, 0x00, 0x15, 0xcf, 0x80, 0x04, +0x46, 0xf0, 0x01, 0x01, 0x58, 0xf7, 0x86, 0x40, 0x4b, 0xe0, 0x3c, 0x01, 0x00, 0x14, 0x00, 0x0b, +0x00, 0x24, 0x00, 0x0c, 0x50, 0x3f, 0x80, 0x80, 0x58, 0x04, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x01, +0x58, 0xf7, 0x8f, 0x84, 0x4b, 0xe0, 0x3c, 0x01, 0x00, 0x24, 0x00, 0x0c, 0x00, 0x14, 0x00, 0x0b, +0x58, 0x34, 0x80, 0x00, 0x46, 0x80, 0x00, 0x02, 0x58, 0x84, 0x04, 0x68, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x0b, 0x14, 0x51, 0xcf, 0x80, 0xb8, 0x4b, 0xe0, 0x20, 0x01, 0x50, 0x1f, 0x80, 0x18, +0x50, 0x2f, 0x80, 0xa0, 0x58, 0x3e, 0x00, 0x00, 0x58, 0x04, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x02, +0x58, 0xf7, 0x80, 0xe4, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x03, 0x00, 0x00, 0x50, 0x1f, 0x80, 0x18, +0x46, 0x60, 0x00, 0x02, 0x58, 0x63, 0x06, 0x18, 0x44, 0x20, 0x00, 0x23, 0x4b, 0xe0, 0x18, 0x01, +0x04, 0x4f, 0x80, 0x04, 0x4e, 0x02, 0x00, 0x22, 0x58, 0x14, 0x80, 0x00, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x0b, 0x40, 0x4b, 0xe0, 0x20, 0x01, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x87, 0x8f, 0x29, +0x4e, 0x83, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x8b, 0x5c, 0x44, 0x20, 0x07, 0xa7, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x50, 0x1f, 0x80, 0xa0, +0x44, 0x20, 0x00, 0x0c, 0x4b, 0xe0, 0x18, 0x01, 0x4e, 0x02, 0x00, 0x22, 0x58, 0x14, 0x80, 0x00, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x0b, 0x88, 0x4b, 0xe0, 0x20, 0x01, 0x46, 0xf0, 0x01, 0x16, +0x00, 0xa7, 0x8f, 0x29, 0x4e, 0xa3, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, +0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8b, 0x5c, 0x44, 0x20, 0x07, 0xac, 0x46, 0xf0, 0x01, 0x00, +0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x58, 0x1e, 0x00, 0x00, +0x58, 0x03, 0x80, 0x00, 0x44, 0x20, 0x00, 0x0a, 0x4b, 0xe0, 0x18, 0x01, 0x4e, 0x02, 0x00, 0x22, +0x58, 0x14, 0x80, 0x00, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x0b, 0xa0, 0x4b, 0xe0, 0x20, 0x01, +0x46, 0xf0, 0x01, 0x16, 0x00, 0x67, 0x8f, 0x29, 0x4e, 0x63, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8b, 0x5c, 0x44, 0x20, 0x07, 0xb1, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, +0x00, 0x13, 0x80, 0x09, 0x00, 0x23, 0x80, 0x07, 0x58, 0x04, 0x80, 0x00, 0x50, 0x3f, 0x80, 0x60, +0x46, 0xf0, 0x01, 0x01, 0x58, 0xf7, 0x8e, 0x14, 0x4b, 0xe0, 0x3c, 0x01, 0x00, 0x43, 0x80, 0x09, +0x5c, 0xf2, 0x00, 0x0d, 0x4e, 0xf2, 0x00, 0x18, 0x44, 0x10, 0x00, 0x01, 0x40, 0x50, 0x90, 0x0c, +0x54, 0x22, 0x95, 0x0c, 0x4e, 0x23, 0x00, 0x0c, 0x54, 0x22, 0x8a, 0xf2, 0x4e, 0x23, 0x00, 0x30, +0x54, 0x32, 0x80, 0x01, 0x4e, 0x33, 0x00, 0x2e, 0x48, 0x00, 0x00, 0x06, 0x40, 0x20, 0x94, 0x08, +0x48, 0x00, 0x00, 0x28, 0x58, 0x12, 0x00, 0x00, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x0b, 0xbc, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x16, +0x00, 0x77, 0x8f, 0x29, 0x4e, 0x73, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, +0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8b, 0x5c, 0x44, 0x20, 0x07, 0xcd, 0x46, 0xf0, 0x01, 0x00, +0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x40, 0x20, 0x90, 0x08, +0x50, 0x0f, 0x80, 0x80, 0x50, 0x1f, 0x80, 0x60, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x86, 0x18, +0x4b, 0xe0, 0x3c, 0x01, 0x4e, 0x02, 0x00, 0x28, 0x00, 0x2f, 0x80, 0xcd, 0x58, 0x14, 0x80, 0x00, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x0b, 0xdc, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x68, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x16, 0x01, 0xc7, 0x8f, 0x29, 0x4f, 0xc3, 0x00, 0x12, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8b, 0x5c, +0x44, 0x20, 0x07, 0xd3, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x00, 0x44, 0x40, 0x00, 0x00, 0x01, 0xe5, 0x00, 0x0b, 0x54, 0x2f, 0x00, 0x01, +0x4e, 0x23, 0x00, 0x06, 0x58, 0x01, 0x00, 0x00, 0x48, 0x00, 0x00, 0x32, 0x00, 0x35, 0x00, 0x07, +0x50, 0x25, 0x00, 0x0c, 0x14, 0x41, 0x00, 0x01, 0x44, 0x50, 0x00, 0x18, 0x45, 0xef, 0xff, 0xed, +0x44, 0x40, 0x00, 0x10, 0x44, 0x60, 0x00, 0x00, 0x14, 0x91, 0x00, 0x00, 0x14, 0x61, 0x00, 0x02, +0x12, 0x55, 0x00, 0x00, 0x11, 0xe5, 0x00, 0x04, 0x10, 0x45, 0x00, 0x08, 0x10, 0x35, 0x00, 0x05, +0x44, 0x10, 0x00, 0x01, 0x04, 0x0f, 0x80, 0x05, 0x44, 0x5f, 0xe0, 0x00, 0x04, 0x20, 0x00, 0x02, +0x10, 0x10, 0x00, 0x10, 0x12, 0x51, 0x00, 0x01, 0x04, 0x0f, 0x80, 0x05, 0x46, 0xf0, 0x01, 0x05, +0x58, 0xf7, 0x85, 0x58, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0xec, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x70, 0x00, 0x02, 0x58, 0x73, 0x84, 0xbc, +0x50, 0x15, 0x00, 0x24, 0x44, 0x20, 0x00, 0x06, 0x50, 0x0f, 0x80, 0x3c, 0x4b, 0xe0, 0x1c, 0x01, +0x50, 0x14, 0x00, 0x20, 0x44, 0x20, 0x00, 0x10, 0x50, 0x0f, 0x80, 0x80, 0x4b, 0xe0, 0x1c, 0x01, +0x50, 0x15, 0x00, 0x50, 0x44, 0x20, 0x00, 0x08, 0x50, 0x0f, 0x80, 0x90, 0x4b, 0xe0, 0x1c, 0x01, +0x50, 0x0f, 0x80, 0x98, 0x50, 0x15, 0x00, 0x58, 0x44, 0x20, 0x00, 0x08, 0x4b, 0xe0, 0x1c, 0x01, +0x00, 0x64, 0x00, 0x02, 0x4e, 0x62, 0xfe, 0x32, 0x48, 0xff, 0xfe, 0x36, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xf4, 0x14, 0x0f, 0x80, 0x01, 0x04, 0x70, 0x00, 0x02, 0x00, 0x13, 0x80, 0x06, +0x4e, 0x13, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x07, 0x8f, 0x29, 0x4e, 0x03, 0x00, 0x12, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8b, 0x5c, +0x44, 0x20, 0x06, 0xde, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x00, 0x50, 0x13, 0x80, 0x20, 0x02, 0x30, 0x80, 0x04, 0x03, 0xc0, 0x80, 0x05, +0x02, 0x20, 0x80, 0x07, 0x02, 0x40, 0x80, 0x08, 0x40, 0x01, 0xa0, 0x09, 0x40, 0x6e, 0x10, 0x08, +0x55, 0xe0, 0x00, 0x0f, 0x40, 0x83, 0x00, 0x13, 0x41, 0xc1, 0x10, 0x09, 0x40, 0x62, 0x20, 0x08, +0x02, 0xa0, 0x80, 0x03, 0x02, 0x90, 0x80, 0x02, 0x02, 0x50, 0x80, 0x06, 0x55, 0xce, 0x00, 0xff, +0x40, 0x63, 0x30, 0x08, 0x40, 0x63, 0x50, 0x09, 0x40, 0x63, 0x20, 0x08, 0x02, 0x40, 0x80, 0x09, +0x40, 0x01, 0x70, 0x08, 0x40, 0x6e, 0x18, 0x04, 0x46, 0x20, 0xff, 0xf0, 0x47, 0xc0, 0x0f, 0xff, +0x40, 0x8f, 0x20, 0x04, 0x40, 0x52, 0xc0, 0x08, 0x41, 0xe5, 0x30, 0x08, 0x40, 0x31, 0xe0, 0x08, +0x54, 0x94, 0x8f, 0xff, 0x40, 0xaf, 0x70, 0x02, 0x40, 0x91, 0xa4, 0x04, 0x05, 0xe0, 0x80, 0x05, +0x41, 0xc2, 0x88, 0x02, 0x40, 0x84, 0x00, 0x04, 0x46, 0x56, 0x03, 0x22, 0x40, 0x02, 0x50, 0x08, +0x58, 0x32, 0x80, 0x00, 0x58, 0x41, 0x80, 0x00, 0x58, 0x21, 0x80, 0x00, 0x40, 0x94, 0xa8, 0x04, +0x40, 0x84, 0x70, 0x04, 0x40, 0xa3, 0x00, 0x04, 0x15, 0xe2, 0x80, 0x80, 0x14, 0x92, 0x00, 0x81, +0x14, 0x81, 0x80, 0x82, 0x14, 0xa1, 0x00, 0x83, 0x46, 0x46, 0x01, 0x90, 0x00, 0x60, 0x80, 0x00, +0x14, 0x62, 0x00, 0x00, 0x58, 0x92, 0x00, 0x00, 0x04, 0x52, 0x00, 0x00, 0x44, 0x60, 0x00, 0x00, +0x58, 0x32, 0xa0, 0x00, 0x14, 0x32, 0x00, 0x00, 0x46, 0x80, 0x01, 0x03, 0x58, 0x84, 0x00, 0x84, +0x44, 0x00, 0x00, 0x01, 0x40, 0x63, 0x00, 0x00, 0x44, 0x10, 0x03, 0xe9, 0x04, 0xa4, 0x80, 0x00, +0x4c, 0x60, 0xc0, 0x1a, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x77, 0x8f, 0x29, 0x4e, 0x73, 0x00, 0x12, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8b, 0x5c, +0x44, 0x20, 0x07, 0x06, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0x44, 0x31, 0x00, 0x00, 0x40, 0x15, 0x0c, 0x02, +0x4e, 0x13, 0xff, 0xd8, 0x00, 0x53, 0x80, 0x0b, 0x54, 0x22, 0x80, 0x01, 0x4e, 0x23, 0x00, 0x06, +0x58, 0x01, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0a, 0x04, 0x0f, 0x80, 0x01, 0x46, 0xf0, 0x01, 0x06, +0x58, 0xf7, 0x84, 0x48, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x04, 0x90, 0x00, 0x02, +0x46, 0x20, 0x01, 0x0f, 0x58, 0x21, 0x0b, 0x73, 0x50, 0x64, 0x80, 0x20, 0x00, 0x13, 0x00, 0x00, +0x00, 0x73, 0x00, 0x01, 0x58, 0x80, 0x00, 0x00, 0x40, 0xa3, 0x84, 0x06, 0x44, 0x00, 0x00, 0x03, +0x00, 0x51, 0x00, 0x00, 0x46, 0x40, 0x02, 0x4b, 0x47, 0xe0, 0x04, 0xc4, 0x44, 0x60, 0x00, 0x00, +0x40, 0x23, 0x28, 0x1a, 0x40, 0x20, 0x28, 0x1b, 0x58, 0x42, 0x0a, 0x58, 0x59, 0xef, 0x0b, 0x40, +0x5d, 0xc0, 0x80, 0x0f, 0x40, 0xa0, 0x9c, 0x06, 0x44, 0x30, 0x00, 0x01, 0x40, 0x02, 0x70, 0x1b, +0x40, 0x0f, 0x70, 0x1a, 0x40, 0x21, 0xa8, 0x1b, 0x4e, 0x52, 0x00, 0x1c, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x57, 0x8b, 0x74, 0x4e, 0x52, 0x00, 0x16, 0x46, 0xf0, 0x01, 0x0f, 0x01, 0xe7, 0x8b, 0x75, +0x4f, 0xe2, 0x00, 0x10, 0x58, 0x33, 0x00, 0x00, 0x58, 0x43, 0x00, 0x00, 0x58, 0x53, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x85, 0x28, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x06, +0x46, 0x6c, 0x00, 0x00, 0x58, 0x63, 0x00, 0x01, 0x58, 0x03, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x06, +0x58, 0xf7, 0x8a, 0x70, 0x4b, 0xe0, 0x3c, 0x01, 0x00, 0x04, 0x80, 0x0b, 0x54, 0x10, 0x00, 0x01, +0x4e, 0x12, 0x00, 0x0e, 0x58, 0x13, 0x00, 0x00, 0x58, 0x04, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x06, +0x58, 0xf7, 0x84, 0x48, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x60, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xdc, 0x04, 0xa0, 0x00, 0x02, 0x59, 0xc0, 0x00, 0x00, 0x50, 0x35, 0x00, 0x20, +0x00, 0x11, 0x80, 0x00, 0x44, 0x00, 0x00, 0x04, 0x00, 0x61, 0x80, 0x01, 0x4c, 0x10, 0x41, 0x84, +0x44, 0x40, 0x00, 0x01, 0x4c, 0x62, 0x41, 0x46, 0x04, 0x61, 0x80, 0x04, 0x44, 0x90, 0x00, 0x00, +0x14, 0x6f, 0x80, 0x02, 0x50, 0x8f, 0x80, 0x1f, 0x00, 0x51, 0x80, 0x08, 0x50, 0x7f, 0x80, 0x18, +0x14, 0x5f, 0x80, 0x01, 0x02, 0x21, 0x80, 0x05, 0x14, 0x2f, 0x80, 0x04, 0x04, 0x11, 0x80, 0x03, +0x50, 0x35, 0x00, 0x22, 0x14, 0x1f, 0x80, 0x03, 0x14, 0x3f, 0x80, 0x05, 0x46, 0x30, 0x01, 0x01, +0x58, 0x31, 0x8a, 0xb4, 0x14, 0x3f, 0x80, 0x00, 0x58, 0x04, 0x80, 0x00, 0x58, 0x23, 0x80, 0x00, +0x58, 0x14, 0x00, 0x00, 0x4b, 0xe0, 0x0c, 0x01, 0x04, 0x1f, 0x80, 0x05, 0x58, 0x03, 0x80, 0x00, +0x44, 0x20, 0x00, 0x06, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x86, 0x18, 0x4b, 0xe0, 0x3c, 0x01, +0x54, 0x64, 0x80, 0xff, 0x04, 0x3f, 0x80, 0x00, 0x50, 0x94, 0x80, 0x01, 0x4e, 0x02, 0x00, 0x08, +0x45, 0xe0, 0x00, 0x03, 0x4c, 0x9f, 0x7f, 0xe0, 0x44, 0x60, 0x00, 0x00, 0x04, 0x2f, 0x80, 0x02, +0x04, 0x1f, 0x80, 0x03, 0x58, 0x33, 0x00, 0x00, 0x46, 0x70, 0x00, 0x02, 0x58, 0x73, 0x84, 0x68, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x0c, 0x08, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x96, 0x01, 0x40, +0x04, 0x2f, 0x80, 0x02, 0x14, 0x24, 0x80, 0x00, 0x58, 0x03, 0x00, 0x00, 0x04, 0x8f, 0x80, 0x03, +0x46, 0x90, 0x01, 0x02, 0x58, 0x94, 0x84, 0xe8, 0x40, 0x14, 0x00, 0x13, 0x46, 0xf0, 0x01, 0x02, +0x58, 0xf7, 0x8b, 0x00, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x8b, 0xbc, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x03, 0x00, 0x00, +0x44, 0x10, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x89, 0xc4, 0x4b, 0xe0, 0x3c, 0x01, +0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x8a, 0x48, +0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x02, +0x58, 0xf7, 0x8c, 0x78, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, +0x4b, 0xe0, 0x24, 0x01, 0x46, 0x80, 0x01, 0x02, 0x58, 0x84, 0x07, 0x28, 0x44, 0x10, 0x00, 0x00, +0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, +0x4b, 0xe0, 0x24, 0x01, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x4b, 0xe0, 0x20, 0x01, +0x44, 0x10, 0x00, 0x01, 0x44, 0x00, 0x00, 0x00, 0x58, 0x20, 0x80, 0x00, 0x58, 0x30, 0x80, 0x00, +0x58, 0x40, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x8f, 0x6c, 0x4b, 0xe0, 0x3c, 0x01, +0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x85, 0xc4, +0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x02, +0x58, 0xf7, 0x86, 0xa4, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x01, 0x58, 0x20, 0x00, 0x00, +0x44, 0x10, 0x00, 0x05, 0x44, 0x30, 0x00, 0x64, 0x44, 0x40, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x02, +0x58, 0xf7, 0x87, 0xac, 0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x4f, 0x80, 0x04, 0x44, 0x30, 0x00, 0x64, +0x42, 0x52, 0x0c, 0x24, 0x44, 0x00, 0xff, 0xfc, 0x44, 0x40, 0x00, 0x01, 0x04, 0x2f, 0x80, 0x01, +0x40, 0x12, 0x80, 0x02, 0x44, 0x30, 0x00, 0x00, 0x58, 0x52, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x8e, 0x10, 0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x1f, 0x80, 0x01, +0x58, 0x03, 0x00, 0x00, 0x50, 0x20, 0xff, 0xff, 0x54, 0x11, 0x00, 0xff, 0x46, 0xf0, 0x01, 0x02, +0x58, 0xf7, 0x89, 0x50, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x16, 0x03, 0x00, 0x58, 0x10, 0x80, 0x5c, +0x04, 0x30, 0x80, 0x00, 0x58, 0x01, 0x80, 0x01, 0x14, 0x00, 0x80, 0x00, 0x50, 0x20, 0xff, 0xd4, +0x04, 0x51, 0x00, 0x00, 0x40, 0x32, 0xa0, 0x09, 0x40, 0x31, 0xa0, 0x08, 0x14, 0x31, 0x00, 0x00, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x0c, 0x2c, 0x04, 0x51, 0x00, 0x00, 0x58, 0x32, 0x80, 0x50, +0x14, 0x31, 0x00, 0x00, 0x04, 0x10, 0x80, 0x00, 0x04, 0x21, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x44, 0x10, 0x00, 0x01, 0x58, 0x03, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x81, 0xf8, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x84, 0xc8, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x40, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x10, 0x47, 0x89, 0xb0, 0x48, 0x00, 0x00, 0x6a, +0x44, 0x70, 0x00, 0x02, 0x4c, 0x63, 0xc0, 0x6a, 0x04, 0x81, 0x80, 0x04, 0x46, 0x70, 0x00, 0x02, +0x58, 0x73, 0x84, 0x68, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x83, 0x74, 0x4b, 0xe0, 0x3c, 0x01, +0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x84, 0xd8, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x14, 0x00, 0x00, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x0c, 0x4c, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x06, 0x01, 0x40, +0x14, 0x80, 0x00, 0x00, 0x46, 0x56, 0x01, 0x40, 0x58, 0x52, 0x80, 0x80, 0x04, 0x92, 0x80, 0x00, +0x42, 0x44, 0x88, 0x09, 0x14, 0x42, 0x80, 0x00, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x0c, 0x5c, +0x04, 0x12, 0x80, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x10, 0x67, 0x89, 0xb0, +0x48, 0x00, 0x00, 0x30, 0x45, 0xe0, 0x00, 0x05, 0x4c, 0x1f, 0x40, 0x20, 0x44, 0x80, 0x00, 0x01, +0x4c, 0x64, 0x40, 0x0a, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x84, 0xc8, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x20, 0x44, 0x20, 0x00, 0x02, 0x4c, 0x61, 0x40, 0x20, 0x46, 0xf0, 0x01, 0x03, +0x58, 0xf7, 0x83, 0x74, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x02, 0x58, 0xf7, 0x84, 0xd8, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x0e, 0x44, 0x70, 0x00, 0x06, 0x4c, 0x13, 0xc0, 0x0e, +0x44, 0x10, 0x00, 0x01, 0x4c, 0x60, 0x80, 0x06, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x62, 0xc0, 0x06, +0x44, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x06, 0x46, 0x1c, 0x00, 0x00, 0x58, 0x10, 0x80, 0xbb, +0x00, 0x35, 0x00, 0x0b, 0x54, 0x41, 0x80, 0x01, 0x4e, 0x42, 0x00, 0x0c, 0x58, 0x0e, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x06, 0x58, 0xf7, 0x84, 0x48, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x10, 0x00, 0x00, +0x58, 0x00, 0x80, 0x00, 0x51, 0xff, 0x80, 0x24, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x04, 0x70, 0x00, 0x02, 0x58, 0x60, 0x00, 0x00, +0x00, 0x13, 0x80, 0x20, 0x44, 0x00, 0x00, 0x01, 0x4c, 0x10, 0x40, 0x0c, 0x58, 0x00, 0x80, 0x00, +0x44, 0x10, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x8f, 0xf8, 0x4b, 0xe0, 0x3c, 0x01, +0x00, 0x13, 0x80, 0x0b, 0x54, 0x00, 0x80, 0x01, 0x4e, 0x02, 0x00, 0x0c, 0x58, 0x03, 0x00, 0x00, +0x44, 0x10, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x06, 0x58, 0xf7, 0x84, 0x48, 0x4b, 0xe0, 0x3c, 0x01, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, +0x04, 0x10, 0x00, 0x02, 0x58, 0x60, 0x00, 0x00, 0x00, 0x20, 0x80, 0x09, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x0c, 0xb4, 0x44, 0x70, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x50, 0x33, 0x80, 0x01, +0x4c, 0x51, 0x40, 0x12, 0x04, 0x10, 0x00, 0x01, 0x4e, 0x12, 0x00, 0x0e, 0x58, 0x03, 0x00, 0x00, +0x4b, 0xe0, 0x04, 0x01, 0x58, 0x80, 0x00, 0x00, 0x5c, 0xf3, 0x80, 0x17, 0x4e, 0xf3, 0x00, 0x18, +0x48, 0x00, 0x00, 0x0c, 0x40, 0x71, 0x80, 0x13, 0x44, 0x50, 0x00, 0x17, 0x50, 0x00, 0x00, 0x08, +0x4c, 0x72, 0xff, 0xe4, 0x44, 0x80, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, +0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x8f, 0x60, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x04, 0x00, 0x00, +0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x04, 0x70, 0x00, 0x02, 0x58, 0x60, 0x00, 0x00, 0x00, 0x03, 0x80, 0x20, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0xc0, 0x0a, 0x46, 0xf0, 0x01, 0x05, 0x58, 0xf7, 0x8e, 0xb4, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x10, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x02, 0x80, 0x06, 0x44, 0x11, 0x00, 0x03, +0x48, 0x00, 0x00, 0x0a, 0x46, 0xf0, 0x01, 0x05, 0x58, 0xf7, 0x8e, 0xf8, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x10, 0x00, 0x00, 0x00, 0x33, 0x80, 0x0b, 0x54, 0x01, 0x80, 0x01, 0x4e, 0x02, 0x00, 0x0c, +0x58, 0x03, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x06, 0x58, 0xf7, 0x84, 0x48, 0x4b, 0xe0, 0x3c, 0x01, +0x58, 0x10, 0x00, 0x00, 0x58, 0x00, 0x80, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x04, 0x60, 0x00, 0x02, 0x58, 0x70, 0x00, 0x00, +0x00, 0x03, 0x00, 0x06, 0x44, 0x80, 0x00, 0x01, 0x4c, 0x04, 0x40, 0x14, 0x50, 0x03, 0x00, 0x20, +0x04, 0x10, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x50, 0x23, 0x00, 0x28, 0x46, 0xf0, 0x00, 0x05, +0x58, 0xf7, 0x87, 0x84, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x38, +0x4e, 0x03, 0x00, 0x36, 0x51, 0xe3, 0x00, 0x20, 0x04, 0x1f, 0x00, 0x01, 0x04, 0x0f, 0x00, 0x00, +0x50, 0x23, 0x00, 0x28, 0x46, 0xf0, 0x00, 0x05, 0x58, 0xf7, 0x83, 0x80, 0x4b, 0xe0, 0x3c, 0x01, +0x00, 0x33, 0x00, 0x07, 0x44, 0x1f, 0xe0, 0x00, 0x44, 0x00, 0x00, 0x03, 0x44, 0x50, 0x00, 0x54, +0x44, 0x4f, 0xff, 0xed, 0x10, 0x03, 0x00, 0x08, 0x12, 0x53, 0x00, 0x00, 0x10, 0x43, 0x00, 0x04, +0x10, 0x33, 0x00, 0x05, 0x12, 0x13, 0x00, 0x01, 0x10, 0x83, 0x80, 0x10, 0x04, 0x23, 0x80, 0x02, +0x58, 0x03, 0x80, 0x00, 0x12, 0x11, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x05, 0x58, 0xf7, 0x85, 0x58, +0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x04, 0x00, 0x00, 0x48, 0x00, 0x00, 0x02, 0x3a, 0x6f, 0xa0, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x04, 0x60, 0x00, 0x02, 0x58, 0x80, 0x00, 0x00, +0x00, 0x03, 0x00, 0x06, 0x44, 0x70, 0x00, 0x01, 0x4c, 0x03, 0xc0, 0x30, 0x46, 0xf0, 0x01, 0x16, +0x00, 0x07, 0x8f, 0x29, 0x50, 0x63, 0x00, 0x20, 0x4e, 0x03, 0x00, 0x0c, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x0c, 0x70, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x04, 0x03, 0x00, 0x00, 0x50, 0x13, 0x00, 0x08, 0x46, 0xf0, 0x01, 0x16, 0x58, 0xf7, 0x8f, 0x10, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x77, 0x8f, 0x29, 0x4e, 0x73, 0x00, 0x42, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x0c, 0x94, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x38, 0x4e, 0x03, 0x00, 0x32, 0x04, 0x03, 0x00, 0x08, +0x50, 0x13, 0x00, 0x28, 0x58, 0x33, 0x80, 0x00, 0x50, 0x23, 0x00, 0x24, 0x46, 0xf0, 0x00, 0x07, +0x58, 0xf7, 0x88, 0x28, 0x4b, 0xe0, 0x3c, 0x01, 0x00, 0x53, 0x00, 0x07, 0x44, 0x3f, 0xe0, 0x00, +0x44, 0x10, 0x00, 0x24, 0x44, 0x0f, 0xff, 0xed, 0x10, 0x03, 0x00, 0x04, 0x12, 0x13, 0x00, 0x00, +0x10, 0x53, 0x00, 0x05, 0x10, 0x73, 0x00, 0x08, 0x12, 0x33, 0x00, 0x01, 0x10, 0x74, 0x00, 0x10, +0x04, 0x44, 0x00, 0x02, 0x58, 0x04, 0x00, 0x00, 0x12, 0x32, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x05, +0x58, 0xf7, 0x85, 0x58, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x06, 0x48, 0x00, 0x00, 0x06, +0x44, 0x70, 0x00, 0x00, 0x58, 0x03, 0x80, 0x00, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xec, 0x04, 0x60, 0x00, 0x02, 0x44, 0x10, 0x00, 0x0c, +0x03, 0xc3, 0x00, 0x00, 0x58, 0x80, 0x00, 0x00, 0x51, 0xce, 0x7f, 0xe0, 0x40, 0x3e, 0x05, 0x57, +0x00, 0x03, 0x00, 0x07, 0x50, 0x73, 0x00, 0x20, 0x14, 0x0f, 0x80, 0x03, 0x14, 0x3f, 0x80, 0x02, +0x4e, 0xa2, 0x00, 0x0e, 0x44, 0x40, 0x00, 0x00, 0x44, 0x20, 0xff, 0xff, 0x14, 0x43, 0x80, 0x02, +0x14, 0x23, 0x80, 0x00, 0x14, 0x43, 0x80, 0x01, 0x48, 0x00, 0x00, 0x7a, 0x00, 0x03, 0x00, 0x06, +0x50, 0x93, 0x00, 0x28, 0x4e, 0x02, 0x00, 0x3e, 0x47, 0xc0, 0x01, 0x0a, 0x59, 0xce, 0x04, 0x8c, +0x48, 0x00, 0x00, 0x24, 0x04, 0x23, 0x80, 0x00, 0x54, 0x01, 0x00, 0xff, 0x4e, 0x03, 0x00, 0x0a, +0x04, 0x53, 0x80, 0x01, 0x04, 0x14, 0x80, 0x00, 0x14, 0x12, 0x80, 0x00, 0x48, 0x00, 0x00, 0x0e, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x0a, 0x04, 0x03, 0x80, 0x01, 0x04, 0x14, 0x80, 0x00, +0x40, 0x21, 0x20, 0x09, 0x4b, 0xe0, 0x70, 0x01, 0x50, 0xa5, 0x00, 0x01, 0x50, 0x73, 0x80, 0x0c, +0x40, 0xa5, 0x00, 0x13, 0x50, 0x94, 0x80, 0x0c, 0x04, 0x3f, 0x80, 0x02, 0x40, 0xf5, 0x0c, 0x06, +0x4e, 0xf3, 0xff, 0xda, 0x50, 0x03, 0x00, 0x20, 0x44, 0x40, 0x00, 0x00, 0x14, 0x40, 0x00, 0x02, +0x14, 0x40, 0x00, 0x00, 0x14, 0x40, 0x00, 0x01, 0x44, 0x10, 0x00, 0x0c, 0x48, 0x00, 0x00, 0x38, +0x58, 0xa0, 0x00, 0x00, 0x46, 0x20, 0x01, 0x0a, 0x58, 0x21, 0x04, 0xc8, 0x48, 0x00, 0x00, 0x28, +0x04, 0x13, 0x80, 0x00, 0x54, 0x00, 0x80, 0xff, 0x4e, 0x03, 0x00, 0x0a, 0x04, 0x13, 0x80, 0x01, +0x04, 0x50, 0x80, 0x00, 0x14, 0x54, 0x80, 0x00, 0x48, 0x00, 0x00, 0x12, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0xc0, 0x0e, 0x04, 0x03, 0x80, 0x01, 0x14, 0x2f, 0x80, 0x01, 0x40, 0x10, 0xa0, 0x09, +0x4b, 0xe0, 0x08, 0x01, 0x14, 0x04, 0x80, 0x00, 0x04, 0x2f, 0x80, 0x01, 0x50, 0xa5, 0x00, 0x01, +0x50, 0x73, 0x80, 0x0c, 0x40, 0xa5, 0x00, 0x13, 0x50, 0x94, 0x80, 0x0c, 0x04, 0x3f, 0x80, 0x02, +0x40, 0xf5, 0x0c, 0x06, 0x4e, 0xf3, 0xff, 0xd6, 0x58, 0x1e, 0x00, 0x00, 0x00, 0x23, 0x00, 0x06, +0x4e, 0x22, 0x00, 0x08, 0x00, 0x03, 0x00, 0x0b, 0x54, 0x00, 0x00, 0x01, 0x4e, 0x02, 0x00, 0x26, +0x50, 0x00, 0x80, 0x20, 0x44, 0x2f, 0xff, 0xed, 0x44, 0x30, 0x00, 0x0e, 0x12, 0x03, 0x00, 0x00, +0x10, 0x23, 0x00, 0x04, 0x10, 0x33, 0x00, 0x08, 0x44, 0x10, 0x00, 0x01, 0x05, 0xef, 0x80, 0x03, +0x44, 0x4f, 0xe0, 0x00, 0x11, 0xe3, 0x00, 0x05, 0x10, 0x14, 0x00, 0x10, 0x04, 0x54, 0x00, 0x02, +0x58, 0x04, 0x00, 0x00, 0x12, 0x42, 0x80, 0x01, 0x46, 0xf0, 0x01, 0x05, 0x58, 0xf7, 0x85, 0x58, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x14, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x04, 0x70, 0x00, 0x02, +0x00, 0x03, 0x80, 0x06, 0x50, 0x63, 0x80, 0x20, 0x4e, 0x02, 0x00, 0x14, 0x04, 0x03, 0x00, 0x01, +0x04, 0x13, 0x00, 0x02, 0x04, 0x23, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0x8c, +0x4b, 0xe0, 0x3c, 0x01, 0x00, 0x13, 0x80, 0x0b, 0x54, 0x00, 0x80, 0x01, 0x4e, 0x02, 0x00, 0x6a, +0x00, 0x23, 0x80, 0x06, 0x4e, 0x22, 0x00, 0x08, 0x00, 0x33, 0x80, 0x0b, 0x54, 0x01, 0x80, 0x01, +0x4e, 0x02, 0x00, 0x60, 0x44, 0x00, 0x00, 0x18, 0x00, 0x93, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x81, 0x7c, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x50, 0x0f, 0xff, 0x58, 0x80, 0x00, 0x00, +0x4c, 0x02, 0xc0, 0x06, 0x44, 0x00, 0x01, 0x03, 0x48, 0x00, 0x00, 0x4c, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x81, 0x0c, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x20, 0x00, 0x18, 0x44, 0x10, 0x00, 0x00, +0x58, 0x70, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0xe4, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x40, 0x00, 0x18, 0x44, 0x3f, 0xe0, 0x00, 0x44, 0x2f, 0xff, 0xed, 0x44, 0x10, 0x00, 0x02, +0x12, 0x43, 0x80, 0x00, 0x12, 0x33, 0x80, 0x01, 0x10, 0x23, 0x80, 0x04, 0x10, 0x93, 0x80, 0x05, +0x10, 0x13, 0x80, 0x08, 0x50, 0x73, 0x80, 0x0c, 0x04, 0x03, 0x00, 0x00, 0x14, 0x03, 0x80, 0x00, +0x04, 0x53, 0x00, 0x01, 0x14, 0x53, 0x80, 0x01, 0x04, 0x13, 0x00, 0x00, 0x04, 0x03, 0x00, 0x01, +0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0xc8, 0x4b, 0xe0, 0x3c, 0x01, 0x14, 0x03, 0x80, 0x02, +0x44, 0x00, 0x00, 0x00, 0x58, 0x24, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x58, 0x30, 0x00, 0x00, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8a, 0x74, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x00, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, +0x04, 0x20, 0x00, 0x02, 0x44, 0x50, 0x00, 0x01, 0x00, 0x71, 0x00, 0x09, 0x58, 0x80, 0x00, 0x00, +0x4c, 0x72, 0xc0, 0x22, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x80, 0x7c, 0x4b, 0xe0, 0x3c, 0x01, +0x58, 0x60, 0x00, 0x00, 0x4c, 0x03, 0x80, 0x12, 0x46, 0x0c, 0x00, 0x00, 0x58, 0x50, 0x00, 0x9a, +0x4c, 0x62, 0x80, 0x0c, 0x58, 0x04, 0x00, 0x00, 0x58, 0x13, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x03, +0x58, 0xf7, 0x8f, 0x60, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x03, 0x00, 0x00, 0x3a, 0x6f, 0xa0, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x44, 0x10, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x8f, 0x60, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x60, 0x00, 0x00, 0x48, 0xff, 0xff, 0xf0, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x07, 0x8f, 0x29, 0x4e, 0x03, 0x00, 0x0c, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x0d, 0xe4, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x44, 0x10, 0x00, 0x0c, 0x42, 0x60, 0x04, 0x24, +0x46, 0x00, 0x01, 0x0f, 0x58, 0x00, 0x0b, 0x80, 0x44, 0x70, 0x00, 0x00, 0x40, 0x63, 0x00, 0x00, +0x46, 0x80, 0x01, 0x03, 0x58, 0x84, 0x0e, 0x24, 0x48, 0x00, 0x00, 0x28, 0x04, 0x40, 0x80, 0x01, +0x04, 0x30, 0x80, 0x00, 0x14, 0x41, 0x80, 0x01, 0x14, 0x32, 0x00, 0x00, 0x14, 0x70, 0x80, 0x00, +0x14, 0x70, 0x80, 0x01, 0x46, 0x30, 0x01, 0x0f, 0x58, 0x31, 0x89, 0xf4, 0x04, 0x23, 0x00, 0x02, +0x51, 0xe1, 0x7f, 0xff, 0x15, 0xe3, 0x00, 0x02, 0x04, 0x50, 0x80, 0x02, 0x40, 0x42, 0x8c, 0x08, +0x40, 0x22, 0x0c, 0x00, 0x04, 0x21, 0x00, 0x01, 0x4e, 0x22, 0x00, 0x06, 0x4b, 0xe0, 0x08, 0x01, +0x48, 0x00, 0x00, 0x04, 0x4b, 0xe0, 0x20, 0x01, 0x04, 0x13, 0x00, 0x00, 0x58, 0x00, 0x80, 0x00, +0x4c, 0x13, 0x7f, 0xd6, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x4e, 0x02, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x07, 0x8f, 0x29, +0x4e, 0x03, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x8d, 0xf4, 0x44, 0x20, 0x01, 0x30, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x4e, 0x13, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, +0x00, 0x27, 0x8f, 0x29, 0x4e, 0x23, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, +0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8d, 0xf4, 0x44, 0x20, 0x01, 0x31, 0x46, 0xf0, 0x01, 0x00, +0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x4e, 0x22, 0x00, 0x08, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x22, 0xc0, 0x38, 0x48, 0x00, 0x00, 0x18, 0x46, 0x50, 0x01, 0x0f, +0x58, 0x52, 0x8b, 0x80, 0x04, 0x22, 0x80, 0x01, 0x14, 0x12, 0x80, 0x01, 0x14, 0x50, 0x80, 0x00, +0x14, 0x20, 0x80, 0x01, 0x14, 0x11, 0x00, 0x00, 0x04, 0x02, 0x80, 0x02, 0x51, 0xe0, 0x00, 0x01, +0x15, 0xe2, 0x80, 0x02, 0x48, 0x00, 0x00, 0x38, 0x05, 0xe0, 0x80, 0x02, 0x46, 0x50, 0x01, 0x0f, +0x58, 0x52, 0x89, 0xf4, 0x40, 0x4f, 0x0c, 0x08, 0x40, 0x32, 0x14, 0x00, 0x04, 0x21, 0x80, 0x01, +0x4e, 0x22, 0x00, 0x08, 0x58, 0x00, 0x80, 0x00, 0x4b, 0xe0, 0x08, 0x01, 0x48, 0x00, 0x00, 0x24, +0x58, 0x00, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x8e, 0x24, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x17, 0x8f, 0x29, 0x4e, 0x13, 0x00, 0x12, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8d, 0xf4, +0x44, 0x20, 0x01, 0x3f, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x4e, 0x02, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, +0x00, 0x07, 0x8f, 0x29, 0x4e, 0x03, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, +0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8d, 0xf4, 0x44, 0x20, 0x01, 0x18, 0x46, 0xf0, 0x01, 0x00, +0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x46, 0x20, 0x01, 0x0f, +0x58, 0x21, 0x0b, 0x80, 0x14, 0x01, 0x00, 0x02, 0x14, 0x21, 0x00, 0x00, 0x14, 0x21, 0x00, 0x01, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x46, 0x00, 0x01, 0x0f, 0x58, 0x00, 0x09, 0xf4, 0x44, 0x10, 0x00, 0x01, +0x58, 0x30, 0x00, 0x00, 0x04, 0x50, 0x00, 0x00, 0x50, 0x60, 0xff, 0xff, 0x4c, 0x53, 0x00, 0x44, +0x46, 0x20, 0x01, 0x0f, 0x58, 0x21, 0x09, 0xf4, 0x40, 0x40, 0x8c, 0x08, 0x40, 0x42, 0x08, 0x00, +0x58, 0x20, 0x80, 0x00, 0x48, 0x00, 0x00, 0x08, 0x0c, 0x72, 0x00, 0x02, 0x4c, 0x73, 0x00, 0x0a, +0x50, 0x21, 0x00, 0x01, 0x5c, 0xf1, 0x00, 0x05, 0x4e, 0xf3, 0xff, 0xf8, 0x48, 0x00, 0x00, 0x5e, +0x46, 0x70, 0x01, 0x0f, 0x58, 0x73, 0x89, 0xf4, 0x40, 0x41, 0x0c, 0x08, 0x41, 0xe2, 0x1c, 0x00, +0x04, 0x6f, 0x00, 0x01, 0x38, 0x71, 0x8b, 0x02, 0x38, 0x51, 0x8b, 0x0a, 0x04, 0x50, 0x00, 0x01, +0x14, 0x5f, 0x00, 0x01, 0x14, 0x70, 0x00, 0x00, 0x14, 0x60, 0x00, 0x01, 0x48, 0x00, 0x00, 0x14, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8d, 0xf4, +0x44, 0x20, 0x00, 0xf1, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x00, 0x50, 0x10, 0x80, 0x01, 0x44, 0x60, 0x00, 0x06, 0x50, 0x00, 0x00, 0x08, +0x4c, 0x13, 0x7f, 0xb2, 0x44, 0x00, 0x00, 0x00, 0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x89, 0xf4, +0x38, 0x30, 0x83, 0x02, 0x4c, 0x30, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x07, 0x8f, 0x29, +0x4e, 0x03, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x8d, 0xf4, 0x44, 0x20, 0x01, 0x03, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x01, 0x5c, 0xf0, 0x00, 0x05, +0x4e, 0xf3, 0xff, 0xe0, 0x48, 0x00, 0x00, 0x0a, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x27, 0x8f, 0x29, +0x4e, 0x22, 0xff, 0xb8, 0x48, 0xff, 0xff, 0xc6, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x46, 0xf0, 0x01, 0x08, +0x58, 0xf7, 0x82, 0xbc, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x08, +0x58, 0xf7, 0x82, 0x60, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x46, 0xf0, 0x01, 0x08, +0x58, 0xf7, 0x84, 0x54, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x46, 0xf0, 0x01, 0x08, +0x58, 0xf7, 0x85, 0xd4, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x70, 0x01, 0x12, 0x58, 0x73, 0x8b, 0xb4, +0x00, 0x63, 0x80, 0x00, 0x4e, 0x63, 0x00, 0x32, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x57, 0x82, 0x68, +0x58, 0x13, 0x00, 0x00, 0x46, 0x80, 0x00, 0x02, 0x58, 0x84, 0x04, 0xe4, 0x50, 0x02, 0x80, 0xb0, +0x44, 0x20, 0x00, 0x98, 0x4b, 0xe0, 0x20, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x37, 0x82, 0x6a, +0x58, 0x13, 0x00, 0x00, 0x50, 0x01, 0x80, 0x48, 0x44, 0x20, 0x00, 0x04, 0x4b, 0xe0, 0x20, 0x01, +0x58, 0x13, 0x00, 0x00, 0x44, 0x20, 0x00, 0xa0, 0x50, 0x03, 0x80, 0x08, 0x4b, 0xe0, 0x20, 0x01, +0x44, 0x20, 0x00, 0x01, 0x10, 0x23, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x0f, 0x14, 0x67, 0x82, 0xa0, +0x46, 0xf0, 0x01, 0x0f, 0x14, 0x67, 0x82, 0x9f, 0x46, 0x07, 0xff, 0xff, 0x44, 0x10, 0x00, 0x00, +0x44, 0x20, 0x00, 0x01, 0x58, 0x00, 0x0f, 0xff, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x8b, 0xcc, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x88, 0x4c, 0x4b, 0xe0, 0x3c, 0x01, +0x46, 0xf0, 0x01, 0x12, 0x14, 0x07, 0x82, 0xee, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x54, 0x00, 0x80, 0xff, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x22, 0xc0, 0x06, 0x50, 0x00, 0x00, 0x02, +0x48, 0x00, 0x00, 0x08, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x22, 0xc0, 0x06, 0x50, 0x00, 0x7f, 0xfe, +0x54, 0x00, 0x00, 0xff, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x54, 0x00, 0x80, 0xff, 0x58, 0x11, 0x00, 0x00, 0x54, 0x21, 0x80, 0xff, 0x54, 0x32, 0x00, 0xff, +0x58, 0x42, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x0c, 0x58, 0xf7, 0x83, 0x60, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x46, 0xf0, 0x01, 0x0e, 0x58, 0xf7, 0x82, 0x24, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x00, 0x01, 0x0f, 0x00, 0x50, 0x0b, 0x75, 0x44, 0x20, 0x00, 0x01, +0x4c, 0x51, 0x00, 0x0a, 0x10, 0x20, 0x0b, 0x75, 0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x8e, 0x80, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x09, 0x58, 0xf7, 0x8b, 0xfc, 0x4b, 0xe0, 0x3c, 0x01, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, 0x8c, 0x07, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x08, +0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0x40, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x0c, +0x58, 0xf7, 0x82, 0x0c, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x46, 0xf0, 0x01, 0x09, +0x58, 0xf7, 0x8b, 0xe4, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x00, 0x01, 0x0f, 0x00, 0x10, 0x0b, 0x75, +0x4e, 0x12, 0x00, 0x06, 0x44, 0x20, 0x00, 0x00, 0x10, 0x20, 0x0b, 0x75, 0x51, 0xff, 0x80, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x58, 0x70, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0x34, 0x4b, 0xe0, 0x3c, 0x01, +0x58, 0x60, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0b, 0x58, 0xf7, 0x8e, 0xb4, 0x4b, 0xe0, 0x3c, 0x01, +0x50, 0x63, 0x7f, 0xff, 0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x4e, 0x63, 0xff, 0xfa, +0x46, 0xf0, 0x01, 0x0b, 0x58, 0xf7, 0x8d, 0xf8, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x03, 0x00, 0x00, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x04, 0x10, 0x00, 0x02, 0x44, 0x20, 0x00, 0x01, 0x50, 0x10, 0x80, 0x20, +0x00, 0x30, 0x80, 0x00, 0x4c, 0x31, 0x00, 0x04, 0x48, 0x00, 0x00, 0x46, 0x00, 0x40, 0x80, 0x04, +0x04, 0x20, 0x80, 0x02, 0x4c, 0x41, 0xc0, 0x88, 0x44, 0x50, 0x00, 0x06, 0x4c, 0x22, 0x80, 0x58, +0x5c, 0xf1, 0x00, 0x07, 0x4e, 0xf2, 0x00, 0x18, 0x44, 0x10, 0x00, 0x02, 0x4c, 0x20, 0x80, 0x38, +0x40, 0xf1, 0x04, 0x06, 0x4e, 0xf3, 0x00, 0x30, 0x44, 0x50, 0x00, 0x04, 0x4c, 0x22, 0x80, 0x2c, +0x46, 0x30, 0x01, 0x08, 0x58, 0x31, 0x86, 0x08, 0x5c, 0xf1, 0x00, 0x05, 0x4e, 0xf2, 0x00, 0x36, +0x48, 0x00, 0x00, 0x2c, 0x44, 0x50, 0x00, 0x0a, 0x4c, 0x22, 0x80, 0x46, 0x5c, 0xf1, 0x00, 0x0b, +0x4e, 0xf2, 0x00, 0x0c, 0x44, 0x10, 0x00, 0x08, 0x4c, 0x20, 0x80, 0x16, 0x44, 0x50, 0x00, 0x09, +0x4c, 0x22, 0xc0, 0x5a, 0x48, 0x00, 0x00, 0x32, 0x44, 0x10, 0x00, 0x0c, 0x4c, 0x20, 0x80, 0x42, +0x40, 0xf1, 0x04, 0x06, 0x4e, 0xf3, 0x00, 0x36, 0x44, 0x50, 0x00, 0x0d, 0x4c, 0x22, 0xc0, 0x4c, +0x48, 0x00, 0x00, 0x3e, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x46, 0x10, 0x01, 0x0d, +0x58, 0x10, 0x88, 0xf8, 0x48, 0x00, 0x00, 0x38, 0x46, 0x10, 0x01, 0x0b, 0x58, 0x10, 0x8c, 0x2c, +0x44, 0x20, 0x00, 0x03, 0x48, 0x00, 0x00, 0x08, 0x46, 0x10, 0x01, 0x0c, 0x58, 0x10, 0x8d, 0xa0, +0x44, 0x20, 0x00, 0x05, 0x4b, 0xe0, 0x0c, 0x01, 0x48, 0x00, 0x00, 0x30, 0x46, 0x10, 0x01, 0x0c, +0x58, 0x10, 0x8d, 0xa0, 0x48, 0x00, 0x00, 0x20, 0x46, 0x10, 0x01, 0x0b, 0x58, 0x10, 0x82, 0xac, +0x48, 0x00, 0x00, 0x1a, 0x46, 0x10, 0x01, 0x0c, 0x58, 0x10, 0x89, 0x14, 0x48, 0x00, 0x00, 0x14, +0x46, 0x10, 0x01, 0x0c, 0x58, 0x10, 0x84, 0x68, 0x44, 0x20, 0x00, 0x0b, 0x48, 0x00, 0x00, 0x0c, +0x46, 0x10, 0x01, 0x0d, 0x58, 0x10, 0x81, 0x6c, 0x48, 0x00, 0x00, 0x06, 0x46, 0x10, 0x01, 0x0d, +0x58, 0x10, 0x87, 0x3c, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x86, 0x08, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x04, 0x44, 0x01, 0x00, 0x03, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x07, 0x83, 0x03, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x4e, 0x03, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, +0x00, 0x07, 0x8f, 0x29, 0x4e, 0x03, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, +0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8e, 0x18, 0x44, 0x20, 0x00, 0xda, 0x46, 0xf0, 0x01, 0x00, +0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x44, 0x30, 0x00, 0x00, +0x14, 0x20, 0x00, 0x04, 0x14, 0x30, 0x00, 0x01, 0x14, 0x10, 0x00, 0x05, 0x14, 0x30, 0x00, 0x00, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x4e, 0x03, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x07, 0x8f, 0x29, +0x4e, 0x03, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x8e, 0x18, 0x44, 0x20, 0x01, 0x0a, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x24, +0x05, 0xe0, 0x00, 0x01, 0x44, 0x50, 0x00, 0x00, 0x15, 0xe0, 0x80, 0x01, 0x14, 0x1f, 0x00, 0x00, +0x14, 0x50, 0x00, 0x01, 0x14, 0x50, 0x00, 0x00, 0x46, 0x30, 0x01, 0x12, 0x58, 0x31, 0x8c, 0x5c, +0x04, 0x41, 0x80, 0x02, 0x04, 0x11, 0x80, 0x00, 0x50, 0x22, 0x7f, 0xff, 0x14, 0x21, 0x80, 0x02, +0x4c, 0x11, 0xc0, 0x0a, 0x04, 0x00, 0x80, 0x03, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x87, 0x7c, +0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x46, 0xf0, 0x01, 0x12, 0x04, 0x17, 0x83, 0x1a, +0x58, 0x70, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x1e, 0x58, 0x00, 0x80, 0x00, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x87, 0x7c, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x03, 0xe8, 0x42, 0x33, 0x80, 0x24, +0x44, 0x20, 0x7f, 0xff, 0x40, 0x11, 0x88, 0x00, 0x46, 0xf0, 0x01, 0x12, 0x04, 0x07, 0x83, 0x1a, +0x40, 0x10, 0xbc, 0x09, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x89, 0xb4, 0x4b, 0xe0, 0x3c, 0x01, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x88, 0x4c, 0x4b, 0xe0, 0x3c, 0x01, +0x46, 0x17, 0xff, 0xff, 0x58, 0x10, 0x8f, 0xff, 0x58, 0x80, 0x00, 0x00, 0x40, 0xa0, 0x04, 0x00, +0x46, 0x00, 0x01, 0xe0, 0x46, 0x20, 0x01, 0x12, 0x58, 0x21, 0x0c, 0x5c, 0x14, 0xa1, 0x00, 0x04, +0x58, 0x71, 0x00, 0x00, 0x04, 0x61, 0x00, 0x00, 0x41, 0xc4, 0x00, 0x00, 0x48, 0x00, 0x00, 0x7c, +0x4e, 0x63, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x37, 0x8f, 0x29, 0x4e, 0x33, 0x00, 0x12, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8e, 0x18, +0x44, 0x20, 0x01, 0x7d, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x00, 0x04, 0x03, 0x00, 0x02, 0x40, 0x54, 0x00, 0x01, 0x4e, 0x55, 0x00, 0x4e, +0x05, 0xe3, 0x00, 0x00, 0x4f, 0xe3, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x67, 0x8f, 0x29, +0x4e, 0x63, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x8e, 0x18, 0x44, 0x20, 0x01, 0x81, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x08, +0x58, 0xf7, 0x88, 0x0c, 0x4b, 0xe0, 0x3c, 0x01, 0x02, 0x03, 0x00, 0x06, 0x4e, 0x02, 0x00, 0x1a, +0x50, 0x30, 0x7f, 0xff, 0x12, 0x33, 0x00, 0x06, 0x15, 0xc3, 0x00, 0x02, 0x04, 0x13, 0x80, 0x01, +0x14, 0x63, 0x80, 0x01, 0x14, 0x73, 0x00, 0x00, 0x14, 0x13, 0x00, 0x01, 0x14, 0x60, 0x80, 0x00, +0x04, 0x23, 0x80, 0x02, 0x50, 0x01, 0x00, 0x01, 0x14, 0x03, 0x80, 0x02, 0x48, 0x00, 0x00, 0x0a, +0x04, 0x13, 0x00, 0x05, 0x4e, 0x12, 0x00, 0x06, 0x04, 0x03, 0x00, 0x04, 0x4b, 0xe0, 0x04, 0x01, +0x14, 0xa3, 0x80, 0x04, 0x48, 0x00, 0x00, 0x0e, 0x04, 0x43, 0x80, 0x04, 0x40, 0x90, 0x10, 0x01, +0x4e, 0x95, 0x00, 0x04, 0x48, 0x00, 0x00, 0x04, 0x14, 0x03, 0x80, 0x04, 0x58, 0x93, 0x00, 0x00, +0x04, 0x64, 0x80, 0x00, 0x46, 0x90, 0x01, 0x12, 0x58, 0x94, 0x8c, 0x5c, 0x4c, 0x64, 0xff, 0x82, +0x04, 0x53, 0x00, 0x00, 0x4c, 0x53, 0x00, 0x28, 0x04, 0x03, 0x00, 0x04, 0x41, 0xe4, 0x00, 0x01, +0x4f, 0xe5, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x87, 0x8f, 0x29, 0x4e, 0x83, 0x00, 0x12, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8e, 0x18, +0x44, 0x20, 0x01, 0xa0, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0x01, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x88, 0xa0, +0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x58, 0x60, 0x00, 0x00, 0x4e, 0x03, 0x00, 0x1a, +0x46, 0xf0, 0x01, 0x16, 0x00, 0x07, 0x8f, 0x29, 0x4e, 0x03, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8e, 0x18, 0x44, 0x20, 0x01, 0x2d, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, +0x44, 0x00, 0xea, 0x60, 0x40, 0xf0, 0x04, 0x06, 0x4e, 0xf2, 0x00, 0x36, 0x46, 0x2e, 0xa5, 0xf1, +0x58, 0x21, 0x05, 0xa0, 0x40, 0xf1, 0x04, 0x06, 0x4e, 0xf2, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, +0x00, 0x37, 0x8f, 0x29, 0x4e, 0x33, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, +0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8e, 0x18, 0x44, 0x20, 0x01, 0x35, 0x46, 0xf0, 0x01, 0x00, +0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x40, 0x70, 0x80, 0x77, +0x44, 0x5f, 0x15, 0xa0, 0x40, 0x23, 0x80, 0x13, 0x42, 0x11, 0x14, 0x73, 0x12, 0x23, 0x00, 0x06, +0x4e, 0x13, 0x00, 0x10, 0x50, 0x81, 0x7f, 0xff, 0x12, 0x83, 0x00, 0x06, 0x58, 0x10, 0x00, 0x00, +0x48, 0x00, 0x00, 0x26, 0x44, 0x90, 0x00, 0x00, 0x12, 0x93, 0x00, 0x06, 0x48, 0x00, 0x00, 0x20, +0x45, 0xe0, 0xff, 0xfe, 0x40, 0xff, 0x04, 0x06, 0x4e, 0xf2, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, +0x00, 0x67, 0x8f, 0x29, 0x4e, 0x63, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, +0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8e, 0x18, 0x44, 0x20, 0x01, 0x48, 0x46, 0xf0, 0x01, 0x00, +0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x40, 0x70, 0xbc, 0x08, +0x50, 0x43, 0x83, 0xe7, 0x44, 0x50, 0x03, 0xe8, 0x40, 0x32, 0x14, 0x57, 0x46, 0x70, 0x01, 0x12, +0x58, 0x73, 0x8c, 0x5c, 0x44, 0x20, 0x00, 0x01, 0x40, 0x91, 0x8c, 0x1b, 0x40, 0x91, 0x0c, 0x1a, +0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x88, 0x4c, 0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x13, 0x80, 0x00, +0x40, 0x80, 0x24, 0x00, 0x4c, 0x13, 0x80, 0x08, 0x04, 0x03, 0x80, 0x04, 0x41, 0xe4, 0x00, 0x01, +0x4f, 0xe4, 0x00, 0x0e, 0x46, 0xf0, 0x01, 0x12, 0x14, 0x87, 0x83, 0x1b, 0x58, 0x04, 0x80, 0x00, +0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x88, 0xa0, 0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x33, 0x00, 0x00, +0x14, 0x83, 0x00, 0x02, 0x4e, 0x33, 0x00, 0x14, 0x46, 0xf0, 0x01, 0x12, 0x04, 0x57, 0x83, 0x18, +0x14, 0x63, 0x80, 0x01, 0x14, 0x73, 0x00, 0x00, 0x14, 0x53, 0x00, 0x01, 0x14, 0x62, 0x80, 0x00, +0x04, 0x43, 0x80, 0x02, 0x50, 0x22, 0x00, 0x01, 0x14, 0x23, 0x80, 0x02, 0x51, 0xff, 0x80, 0x04, +0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x46, 0x10, 0x01, 0x0f, 0x00, 0x00, 0x8b, 0x8c, 0x4e, 0x02, 0x00, 0x3e, 0x46, 0x60, 0x01, 0x12, +0x58, 0x63, 0x0c, 0x5c, 0x04, 0x03, 0x00, 0x03, 0x44, 0x70, 0x00, 0x00, 0x44, 0x20, 0x00, 0x00, +0x10, 0x20, 0x8b, 0x8c, 0x14, 0x63, 0x00, 0x00, 0x14, 0x63, 0x00, 0x01, 0x14, 0x73, 0x00, 0x02, +0x4e, 0x03, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x17, 0x8f, 0x29, 0x4e, 0x13, 0x00, 0x12, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8e, 0x18, +0x44, 0x20, 0x00, 0xc2, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x87, 0x7c, 0x4b, 0xe0, 0x3c, 0x01, +0x04, 0x03, 0x00, 0x03, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x86, 0x18, 0x4b, 0xe0, 0x3c, 0x01, +0x14, 0x73, 0x00, 0x03, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x98, 0xbc, 0x46, 0x10, 0x01, 0x0f, 0x46, 0x60, 0x01, 0x12, 0x58, 0x63, 0x0c, 0x5c, +0x44, 0x20, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x8c, 0x14, 0x23, 0x00, 0x02, 0x44, 0x20, 0x00, 0x01, +0x14, 0x63, 0x00, 0x00, 0x14, 0x63, 0x00, 0x01, 0x4c, 0x01, 0x00, 0x30, 0x04, 0x03, 0x00, 0x03, +0x10, 0x20, 0x8b, 0x8c, 0x4e, 0x03, 0x00, 0x24, 0x46, 0xf0, 0x00, 0x01, 0x58, 0xf7, 0x86, 0xc4, +0x4b, 0xe0, 0x3c, 0x01, 0x14, 0x03, 0x00, 0x03, 0x4e, 0x03, 0x00, 0x20, 0x46, 0xf0, 0x01, 0x16, +0x00, 0x17, 0x8f, 0x29, 0x4e, 0x13, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x06, 0xec, +0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8e, 0x18, 0x44, 0x20, 0x00, 0xa2, 0x46, 0xf0, 0x01, 0x00, +0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x48, 0x00, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x01, +0x58, 0xf7, 0x87, 0x7c, 0x4b, 0xe0, 0x3c, 0x01, 0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x58, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x10, +0x02, 0x11, 0x00, 0x23, 0x00, 0x30, 0x00, 0x08, 0x42, 0x10, 0xb0, 0x0b, 0x00, 0x20, 0x00, 0x09, +0x4c, 0x30, 0x80, 0x1a, 0x10, 0x10, 0x00, 0x08, 0x46, 0x30, 0x01, 0x12, 0x58, 0x31, 0x88, 0x70, +0x38, 0x41, 0x88, 0x00, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x42, 0x80, 0x0e, 0x4c, 0x12, 0xc0, 0x04, +0x38, 0x11, 0x88, 0x08, 0x00, 0x10, 0x00, 0x08, 0x46, 0xf0, 0x01, 0x04, 0x58, 0xf7, 0x8f, 0x3c, +0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x04, 0x50, 0x00, 0x06, 0x04, 0x30, 0x00, 0x10, +0x00, 0x42, 0x80, 0x07, 0x40, 0x22, 0x08, 0x09, 0x10, 0x21, 0x80, 0x00, 0x05, 0xe0, 0x00, 0x06, +0x04, 0x40, 0x00, 0x10, 0x00, 0x5f, 0x00, 0x08, 0x44, 0x20, 0x00, 0x01, 0x10, 0x52, 0x00, 0x09, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x17, 0x89, 0xa4, 0x4c, 0x11, 0x40, 0x08, 0x46, 0xf0, 0x01, 0x08, +0x58, 0xf7, 0x8d, 0x60, 0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x46, 0xf0, 0x01, 0x0f, 0x10, 0x07, 0x8b, 0x8d, 0x4a, 0x00, 0x78, 0x20, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, 0x8b, 0x8d, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x67, 0x82, 0xf7, 0x46, 0xf0, 0x01, 0x0f, +0x04, 0x77, 0x82, 0xea, 0x4e, 0x62, 0x00, 0x20, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x80, 0xf4, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x86, 0x58, 0x4b, 0xe0, 0x3c, 0x01, +0x42, 0x60, 0x18, 0x24, 0x44, 0x10, 0x00, 0x00, 0x40, 0x63, 0x08, 0x09, 0x58, 0x00, 0x80, 0x00, +0x48, 0x00, 0x00, 0x06, 0x1c, 0x03, 0x80, 0x01, 0x50, 0x10, 0x80, 0x01, 0x40, 0xf0, 0x98, 0x06, +0x4e, 0xf3, 0xff, 0xfa, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x58, 0x60, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x80, 0xf4, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x86, 0x58, +0x4b, 0xe0, 0x3c, 0x01, 0x40, 0x03, 0x00, 0x37, 0x4e, 0x12, 0x00, 0x04, 0x50, 0x00, 0x00, 0x01, +0x46, 0x10, 0x01, 0x0f, 0x5c, 0xf0, 0x02, 0x01, 0x4e, 0xf3, 0x00, 0x08, 0x44, 0x00, 0x00, 0x00, +0x14, 0x00, 0x82, 0xe7, 0x48, 0x00, 0x00, 0x06, 0x14, 0x00, 0x82, 0xe7, 0x44, 0x00, 0x00, 0x01, +0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x58, 0x60, 0x00, 0x00, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x80, 0xf4, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x00, 0x03, +0x58, 0xf7, 0x86, 0x58, 0x4b, 0xe0, 0x3c, 0x01, 0x40, 0x03, 0x00, 0x37, 0x4e, 0x12, 0x00, 0x04, +0x50, 0x00, 0x00, 0x01, 0x54, 0x20, 0x00, 0x01, 0x4e, 0x22, 0x00, 0x04, 0x50, 0x00, 0x00, 0x01, +0x46, 0x10, 0x01, 0x0f, 0x5c, 0xf0, 0x00, 0x41, 0x4e, 0xf3, 0x00, 0x08, 0x44, 0x00, 0x00, 0x00, +0x14, 0x00, 0x82, 0xe6, 0x48, 0x00, 0x00, 0x06, 0x14, 0x00, 0x82, 0xe6, 0x44, 0x00, 0x00, 0x01, +0x3a, 0x6f, 0x98, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, +0x14, 0x5f, 0x80, 0x01, 0x58, 0x90, 0x80, 0x00, 0x58, 0x81, 0x00, 0x00, 0x58, 0x61, 0x80, 0x00, +0x58, 0xa0, 0x00, 0x00, 0x05, 0xcf, 0x80, 0x0a, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x80, 0xf4, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x86, 0x58, 0x4b, 0xe0, 0x3c, 0x01, +0x04, 0x5f, 0x80, 0x01, 0x4e, 0xa3, 0x00, 0x06, 0x58, 0x75, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0a, +0x40, 0x70, 0x28, 0x37, 0x40, 0x73, 0x1c, 0x37, 0x4e, 0x12, 0x00, 0x04, 0x50, 0x73, 0x80, 0x01, +0x4e, 0x93, 0x00, 0x06, 0x58, 0x44, 0x80, 0x00, 0x48, 0x00, 0x00, 0x0a, 0x40, 0x40, 0x24, 0x37, +0x40, 0x43, 0x10, 0x57, 0x4e, 0x22, 0x00, 0x04, 0x50, 0x42, 0x00, 0x01, 0x4e, 0x83, 0x00, 0x06, +0x58, 0x34, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0a, 0x40, 0x30, 0x20, 0x37, 0x40, 0x33, 0x0f, 0xd7, +0x4f, 0xe2, 0x00, 0x04, 0x50, 0x31, 0x80, 0x01, 0x40, 0x02, 0x80, 0xb7, 0x40, 0x12, 0x1c, 0x00, +0x40, 0x20, 0x8c, 0x00, 0x4e, 0x52, 0x00, 0x04, 0x50, 0x00, 0x00, 0x01, 0x42, 0x10, 0x70, 0x24, +0x41, 0xe0, 0x88, 0x00, 0x46, 0xf0, 0x01, 0x0f, 0x15, 0xe7, 0x82, 0xf7, 0x46, 0xf0, 0x01, 0x0f, +0x14, 0x27, 0x82, 0xf8, 0x46, 0xf0, 0x01, 0x0f, 0x14, 0x07, 0x82, 0xf9, 0x46, 0xf0, 0x01, 0x0f, +0x14, 0x17, 0x82, 0xfa, 0x46, 0xf0, 0x01, 0x0f, 0x14, 0x87, 0x82, 0xf5, 0x46, 0xf0, 0x01, 0x0f, +0x14, 0x67, 0x82, 0xf2, 0x46, 0xf0, 0x01, 0x0f, 0x14, 0xa7, 0x82, 0xf3, 0x46, 0xf0, 0x01, 0x0f, +0x14, 0x97, 0x82, 0xf4, 0x46, 0xf0, 0x01, 0x0f, 0x14, 0x37, 0x82, 0xfd, 0x44, 0x00, 0x00, 0x01, +0x46, 0xf0, 0x01, 0x0f, 0x15, 0xc7, 0x82, 0xf6, 0x46, 0xf0, 0x01, 0x0f, 0x14, 0x77, 0x82, 0xfb, +0x46, 0xf0, 0x01, 0x0f, 0x14, 0x47, 0x82, 0xfc, 0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xec, 0x58, 0x91, 0x80, 0x00, +0x58, 0x82, 0x00, 0x00, 0x04, 0x3f, 0x80, 0x0d, 0x04, 0x4f, 0x80, 0x0c, 0x14, 0x2f, 0x80, 0x03, +0x14, 0x3f, 0x80, 0x00, 0x14, 0x4f, 0x80, 0x01, 0x14, 0x5f, 0x80, 0x02, 0x58, 0xa0, 0x80, 0x00, +0x54, 0x60, 0x00, 0xff, 0x05, 0xcf, 0x80, 0x0f, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x80, 0xf4, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x86, 0x58, 0x4b, 0xe0, 0x3c, 0x01, +0x04, 0x2f, 0x80, 0x03, 0x04, 0x3f, 0x80, 0x00, 0x04, 0x4f, 0x80, 0x01, 0x04, 0x5f, 0x80, 0x02, +0x4e, 0x92, 0x00, 0x20, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x77, 0x82, 0xf3, 0x4e, 0x72, 0x00, 0x1a, +0x41, 0xe0, 0x1c, 0xf7, 0x40, 0x73, 0x78, 0x37, 0x55, 0xe0, 0x80, 0xff, 0x12, 0x75, 0x00, 0x00, +0x11, 0xe1, 0x00, 0x00, 0x02, 0x25, 0x00, 0x00, 0x40, 0x7f, 0x18, 0x08, 0x46, 0xf0, 0x01, 0x0f, +0x05, 0xe7, 0x82, 0xea, 0x43, 0xe0, 0x08, 0x73, 0x40, 0x2f, 0x1c, 0x00, 0x14, 0x24, 0x80, 0x00, +0x4e, 0x42, 0x00, 0x28, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x17, 0x82, 0xf4, 0x4e, 0x12, 0x00, 0x22, +0x40, 0x20, 0x04, 0x37, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x77, 0x82, 0xfb, 0x40, 0x23, 0x0b, 0xd7, +0x40, 0x1f, 0x78, 0x00, 0x54, 0x10, 0x80, 0xff, 0x41, 0xe1, 0x1c, 0x00, 0x13, 0xe4, 0x00, 0x00, +0x10, 0x12, 0x80, 0x00, 0x41, 0xe0, 0x94, 0x08, 0x02, 0x24, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0f, +0x04, 0x17, 0x82, 0xea, 0x42, 0x10, 0x08, 0x73, 0x40, 0x50, 0xf8, 0x00, 0x14, 0x52, 0x00, 0x00, +0x4f, 0xc2, 0x00, 0x2e, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x17, 0x82, 0xf5, 0x4e, 0x12, 0x00, 0x28, +0x40, 0x10, 0x04, 0x57, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x47, 0x82, 0xfc, 0x46, 0xf0, 0x01, 0x0f, +0x04, 0x27, 0x82, 0xfb, 0x40, 0x52, 0x08, 0x00, 0x41, 0xe3, 0x04, 0x97, 0x40, 0x22, 0xf8, 0x00, +0x12, 0x21, 0x80, 0x00, 0x54, 0x12, 0x00, 0xff, 0x04, 0x6f, 0x80, 0x0e, 0x10, 0x13, 0x00, 0x00, +0x40, 0x60, 0x94, 0x08, 0x02, 0x51, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x37, 0x82, 0xea, +0x42, 0x30, 0x14, 0x73, 0x40, 0x01, 0x98, 0x00, 0x14, 0x0e, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, +0x51, 0xff, 0x80, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x46, 0x60, 0x00, 0x03, 0x58, 0x63, 0x04, 0xcc, 0x54, 0x70, 0x00, 0xff, +0x4b, 0xe0, 0x18, 0x01, 0x46, 0x50, 0x06, 0x63, 0x4c, 0x02, 0x80, 0x1a, 0x4b, 0xe0, 0x18, 0x01, +0x46, 0x20, 0x07, 0x60, 0x58, 0x51, 0x03, 0x00, 0x4c, 0x02, 0x80, 0x12, 0x4b, 0xe0, 0x18, 0x01, +0x46, 0x30, 0x07, 0x62, 0x58, 0x51, 0x88, 0x00, 0x4c, 0x02, 0x80, 0x0a, 0x4b, 0xe0, 0x18, 0x01, +0x46, 0x40, 0x07, 0x63, 0x58, 0x52, 0x06, 0x00, 0x4c, 0x02, 0xc0, 0x06, 0x46, 0xf0, 0x01, 0x0f, +0x10, 0x77, 0x8b, 0xa0, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, 0x51, 0xff, 0xff, 0xf8, 0x44, 0x00, 0x00, 0x01, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x86, 0xa0, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x27, 0x8b, 0xa0, 0x4e, 0x23, 0x00, 0x1a, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, 0x8b, 0x94, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x17, 0x8b, 0x90, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x47, 0x8b, 0xdc, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x57, 0x8b, 0x98, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x67, 0x8b, 0x9c, +0x58, 0x31, 0x00, 0x00, 0x48, 0x00, 0x00, 0x32, 0x46, 0x60, 0x00, 0x03, 0x58, 0x63, 0x04, 0xcc, +0x4b, 0xe0, 0x18, 0x01, 0x46, 0x20, 0x06, 0x63, 0x4c, 0x01, 0x00, 0x1a, 0x46, 0x70, 0x07, 0x60, +0x4b, 0xe0, 0x18, 0x01, 0x58, 0x73, 0x83, 0x00, 0x4c, 0x03, 0x80, 0x12, 0x46, 0x80, 0x07, 0x62, +0x4b, 0xe0, 0x18, 0x01, 0x58, 0x84, 0x08, 0x00, 0x4c, 0x04, 0x00, 0x0a, 0x46, 0x90, 0x07, 0x63, +0x4b, 0xe0, 0x18, 0x01, 0x58, 0x94, 0x86, 0x00, 0x4c, 0x04, 0xc0, 0x18, 0x44, 0x60, 0x00, 0x00, +0x58, 0x03, 0x00, 0x00, 0x58, 0x13, 0x00, 0x00, 0x58, 0x23, 0x00, 0x00, 0x44, 0x30, 0x00, 0x01, +0x58, 0x43, 0x00, 0x00, 0x58, 0x53, 0x00, 0x00, 0x14, 0x6f, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x09, +0x58, 0xf7, 0x87, 0xc0, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x7a, 0x00, 0x00, 0x04, 0x83, 0x80, 0x59, +0x46, 0x6a, 0x00, 0x00, 0x14, 0x83, 0x00, 0x5a, 0x46, 0x70, 0x00, 0x03, 0x58, 0x73, 0x80, 0xf4, +0x46, 0xf0, 0x01, 0x0f, 0x04, 0x97, 0x82, 0xf7, 0x46, 0x60, 0x00, 0x03, 0x58, 0x63, 0x06, 0x58, +0x4b, 0xe0, 0x1c, 0x01, 0x4b, 0xe0, 0x18, 0x01, 0x42, 0x80, 0x24, 0x73, 0x46, 0x1a, 0x00, 0x00, +0x14, 0x80, 0x80, 0x5b, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0xa7, 0x82, 0xe4, 0x58, 0x04, 0x00, 0x00, +0x40, 0x35, 0x20, 0x08, 0x46, 0x8a, 0x00, 0x00, 0x40, 0x40, 0x0c, 0x00, 0x14, 0x44, 0x00, 0x5c, +0x46, 0xf0, 0x01, 0x0f, 0x04, 0x27, 0x82, 0xe5, 0x46, 0x5a, 0x00, 0x00, 0x40, 0x11, 0x20, 0x08, +0x40, 0x92, 0x04, 0x00, 0x14, 0x92, 0x80, 0x5d, 0x46, 0x80, 0x01, 0x0f, 0x04, 0xa4, 0x02, 0xe6, +0x4b, 0xe0, 0x1c, 0x01, 0x4b, 0xe0, 0x18, 0x01, 0x40, 0xa5, 0x04, 0x09, 0x42, 0x90, 0x28, 0x73, +0x46, 0x3a, 0x00, 0x00, 0x14, 0x91, 0x80, 0x5e, 0x04, 0x04, 0x02, 0xe6, 0x40, 0x80, 0x04, 0x09, +0x4b, 0xe0, 0x1c, 0x01, 0x4b, 0xe0, 0x18, 0x01, 0x42, 0x90, 0x20, 0x73, 0x58, 0x84, 0x80, 0x00, +0x46, 0x9a, 0x00, 0x00, 0x14, 0x84, 0x80, 0x5f, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x97, 0x82, 0xe7, +0x4b, 0xe0, 0x1c, 0x01, 0x4b, 0xe0, 0x18, 0x01, 0x42, 0x80, 0x24, 0x73, 0x46, 0x4a, 0x00, 0x00, +0x14, 0x82, 0x00, 0x61, 0x44, 0x00, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x86, 0xa0, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x00, 0x01, 0x17, 0x58, 0x00, 0x01, 0x8a, 0x46, 0x10, 0x01, 0x17, +0x58, 0x10, 0x81, 0x8c, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8d, 0x7c, 0x4b, 0xe0, 0x3c, 0x01, +0x46, 0xf0, 0x01, 0x17, 0x02, 0x07, 0x80, 0xc6, 0x46, 0xf0, 0x01, 0x17, 0x12, 0x07, 0x80, 0xc4, +0x46, 0xf0, 0x01, 0x17, 0x12, 0x07, 0x80, 0xc3, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x08, +0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x51, 0xff, 0xff, 0xf0, +0x04, 0x7f, 0x80, 0x08, 0x04, 0x6f, 0x80, 0x09, 0x14, 0x7f, 0x80, 0x00, 0x14, 0x6f, 0x80, 0x01, +0x04, 0x7f, 0x80, 0x0a, 0x04, 0x6f, 0x80, 0x0b, 0x00, 0x8f, 0x80, 0x38, 0x46, 0xf0, 0x01, 0x08, +0x58, 0xf7, 0x8f, 0x48, 0x4b, 0xe0, 0x3c, 0x01, 0x4e, 0x02, 0x00, 0xaa, 0x4e, 0x73, 0x00, 0x08, +0x46, 0xf0, 0x01, 0x0f, 0x14, 0x77, 0x82, 0xe4, 0x48, 0x00, 0x00, 0x1a, 0x5c, 0xf3, 0x81, 0x01, +0x4e, 0xf2, 0x00, 0x0a, 0x44, 0x10, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x14, 0x17, 0x82, 0xe4, +0x48, 0x00, 0x00, 0x0e, 0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x8b, 0x90, 0x5c, 0xf3, 0x82, 0x01, +0x4e, 0xf2, 0x00, 0x28, 0x44, 0x30, 0x00, 0x02, 0x14, 0x30, 0x80, 0x00, 0x4e, 0x63, 0x00, 0x08, +0x46, 0xf0, 0x01, 0x0f, 0x14, 0x67, 0x82, 0xe5, 0x48, 0x00, 0x00, 0x22, 0x5c, 0xf3, 0x01, 0x01, +0x4e, 0xf2, 0x00, 0x0a, 0x45, 0xe0, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x15, 0xe7, 0x82, 0xe5, +0x48, 0x00, 0x00, 0x16, 0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x8b, 0x94, 0x5c, 0xf3, 0x02, 0x01, +0x4e, 0xf2, 0x00, 0x08, 0x44, 0x00, 0x00, 0x02, 0x14, 0x00, 0x80, 0x00, 0x48, 0x00, 0x00, 0x08, +0x44, 0x00, 0x00, 0x00, 0x14, 0x00, 0x80, 0x00, 0x48, 0x00, 0x00, 0x64, 0x04, 0x0f, 0x80, 0x0c, +0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x8e, 0xe8, 0x4b, 0xe0, 0x3c, 0x01, 0x4e, 0x02, 0x00, 0x58, +0x04, 0x0f, 0x80, 0x0d, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x8e, 0x94, 0x4b, 0xe0, 0x3c, 0x01, +0x4e, 0x02, 0x00, 0x4e, 0x04, 0x1f, 0x80, 0x0f, 0x58, 0x04, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x09, +0x58, 0xf7, 0x81, 0xbc, 0x4b, 0xe0, 0x3c, 0x01, 0x4e, 0x02, 0x00, 0x42, 0x46, 0x60, 0x01, 0x0f, +0x58, 0x63, 0x0b, 0xbc, 0x46, 0xf0, 0x01, 0x09, 0x58, 0xf7, 0x82, 0x24, 0x4b, 0xe0, 0x3c, 0x01, +0x14, 0x6f, 0x80, 0x00, 0x46, 0x60, 0x01, 0x0f, 0x58, 0x63, 0x0b, 0xc0, 0x46, 0x10, 0x01, 0x0f, +0x58, 0x10, 0x8b, 0xa8, 0x46, 0x20, 0x01, 0x0f, 0x58, 0x21, 0x0b, 0xac, 0x46, 0x30, 0x01, 0x0f, +0x58, 0x31, 0x8b, 0xb0, 0x46, 0x40, 0x01, 0x0f, 0x58, 0x42, 0x0b, 0xb4, 0x46, 0x50, 0x01, 0x0f, +0x58, 0x52, 0x8b, 0xb8, 0x14, 0x6f, 0x80, 0x01, 0x46, 0x00, 0x01, 0x0f, 0x58, 0x00, 0x0b, 0xa4, +0x46, 0x60, 0x01, 0x0f, 0x58, 0x63, 0x0b, 0xc4, 0x14, 0x6f, 0x80, 0x02, 0x46, 0xf0, 0x01, 0x09, +0x58, 0xf7, 0x88, 0xa4, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x8e, 0x2c, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, +0x51, 0xff, 0x80, 0x10, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, +0x51, 0xff, 0xff, 0xe0, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x8a, 0xbc, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x00, 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x82, 0x58, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x60, 0x00, 0x00, 0x44, 0x00, 0x00, 0x40, 0x58, 0x10, 0x00, 0x00, +0x44, 0x20, 0x00, 0x20, 0x40, 0x30, 0x04, 0x08, 0x44, 0x40, 0x50, 0x00, 0x58, 0x53, 0x00, 0x00, +0x14, 0x6f, 0x80, 0x00, 0x14, 0x6f, 0x80, 0x01, 0x14, 0x6f, 0x80, 0x02, 0x14, 0x6f, 0x80, 0x03, +0x14, 0x6f, 0x80, 0x04, 0x14, 0x6f, 0x80, 0x05, 0x14, 0x6f, 0x80, 0x06, 0x14, 0x6f, 0x80, 0x07, +0x46, 0xf0, 0x01, 0x09, 0x58, 0xf7, 0x84, 0x08, 0x4b, 0xe0, 0x3c, 0x01, 0x4e, 0x02, 0x00, 0x54, +0x44, 0x00, 0xff, 0xff, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x8f, 0xf4, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x00, 0x00, 0x0f, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x80, 0x1c, 0x4b, 0xe0, 0x3c, 0x01, +0x46, 0x80, 0x00, 0x03, 0x58, 0x84, 0x06, 0xa0, 0x44, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x20, 0x01, +0x44, 0x20, 0x02, 0x88, 0x46, 0x70, 0x00, 0x03, 0x58, 0x73, 0x8e, 0x48, 0x58, 0x31, 0x00, 0x00, +0x58, 0x13, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x58, 0x13, 0x00, 0x00, +0x44, 0x20, 0x0f, 0xff, 0x44, 0x30, 0x00, 0x18, 0x44, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x1c, 0x01, +0x58, 0x13, 0x00, 0x00, 0x44, 0x20, 0x0f, 0xff, 0x44, 0x30, 0x00, 0x34, 0x44, 0x00, 0x00, 0x02, +0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x10, 0x00, 0x01, 0x44, 0x20, 0x0f, 0xff, 0x44, 0x30, 0x00, 0x18, +0x44, 0x00, 0x00, 0x02, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0x02, 0x58, 0x10, 0x00, 0x00, +0x44, 0x20, 0x0f, 0xff, 0x40, 0x30, 0x0c, 0x08, 0x4b, 0xe0, 0x1c, 0x01, 0x58, 0x03, 0x00, 0x00, +0x4b, 0xe0, 0x20, 0x01, 0x51, 0xff, 0x80, 0x20, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x50, 0x0f, 0x80, 0x06, 0x50, 0x1f, 0x80, 0x04, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8d, 0x7c, 0x4b, 0xe0, 0x3c, 0x01, 0x02, 0x0f, 0x80, 0x02, +0x51, 0xff, 0x80, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0x3c, +0x51, 0xff, 0xff, 0xf4, 0x04, 0x6f, 0x80, 0x01, 0x54, 0x00, 0x00, 0xff, 0x42, 0x43, 0x7c, 0x08, +0x14, 0x4f, 0x80, 0x01, 0x04, 0x5f, 0x80, 0x01, 0x46, 0x4a, 0x00, 0x00, 0x42, 0x52, 0xc0, 0x09, +0x14, 0x5f, 0x80, 0x01, 0x10, 0x0f, 0x80, 0x05, 0x04, 0x0f, 0x80, 0x01, 0x14, 0x02, 0x00, 0x65, +0x04, 0x52, 0x00, 0x65, 0x46, 0x0a, 0x00, 0x00, 0x14, 0x5f, 0x80, 0x01, 0x04, 0x5f, 0x80, 0x01, +0x4e, 0x55, 0xff, 0xf8, 0x04, 0x00, 0x00, 0x65, 0x14, 0x0f, 0x80, 0x01, 0x04, 0x5f, 0x80, 0x01, +0x04, 0x4f, 0x80, 0x01, 0x04, 0x0f, 0x80, 0x01, 0x40, 0x42, 0x14, 0x09, 0x42, 0x52, 0x9c, 0x0b, +0x54, 0x42, 0x00, 0x03, 0x54, 0x00, 0x00, 0x1f, 0x10, 0x51, 0x80, 0x00, 0x10, 0x40, 0x80, 0x00, +0x10, 0x01, 0x00, 0x00, 0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0x98, 0x04, 0x4a, 0x00, 0x78, 0x20, +0x51, 0xff, 0xff, 0xf8, 0x44, 0x30, 0x00, 0x00, 0x14, 0x3f, 0x80, 0x01, 0x46, 0x2a, 0x00, 0x00, +0x04, 0x01, 0x00, 0x64, 0x54, 0x10, 0x80, 0xff, 0x14, 0x0f, 0x80, 0x01, 0x4e, 0x12, 0x00, 0x08, +0x04, 0x4f, 0x80, 0x01, 0x58, 0x02, 0x00, 0x10, 0x48, 0x00, 0x00, 0x06, 0x04, 0x5f, 0x80, 0x01, +0x42, 0x02, 0x90, 0x09, 0x14, 0x0f, 0x80, 0x01, 0x46, 0x0a, 0x00, 0x00, 0x04, 0x2f, 0x80, 0x01, +0x14, 0x20, 0x00, 0x64, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x08, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x9c, 0x3c, 0x51, 0xff, 0xff, 0xf8, 0x04, 0x6f, 0x80, 0x01, 0x54, 0x00, 0x00, 0x03, +0x40, 0x63, 0x08, 0x09, 0x40, 0x63, 0x08, 0x08, 0x40, 0x73, 0x00, 0x04, 0x14, 0x7f, 0x80, 0x01, +0x54, 0x10, 0x80, 0x03, 0x04, 0x0f, 0x80, 0x01, 0x44, 0x6f, 0xff, 0xf3, 0x40, 0x00, 0x18, 0x02, +0x40, 0x70, 0x88, 0x08, 0x40, 0x10, 0x1c, 0x04, 0x14, 0x1f, 0x80, 0x01, 0x54, 0x61, 0x00, 0x07, +0x04, 0x1f, 0x80, 0x01, 0x44, 0x7f, 0xff, 0x8f, 0x40, 0x00, 0x9c, 0x02, 0x40, 0x23, 0x10, 0x08, +0x40, 0x60, 0x08, 0x04, 0x14, 0x6f, 0x80, 0x01, 0x54, 0x31, 0x80, 0x01, 0x04, 0x2f, 0x80, 0x01, +0x42, 0x01, 0x1c, 0x09, 0x40, 0x71, 0x9c, 0x08, 0x40, 0x60, 0x1c, 0x04, 0x14, 0x6f, 0x80, 0x01, +0x54, 0x32, 0x00, 0x7f, 0x04, 0x0f, 0x80, 0x01, 0x44, 0x2f, 0x80, 0xff, 0x40, 0x10, 0x08, 0x02, +0x40, 0x71, 0xa0, 0x08, 0x40, 0x40, 0x9c, 0x04, 0x14, 0x4f, 0x80, 0x01, 0x54, 0x62, 0x80, 0x7f, +0x04, 0x3f, 0x80, 0x01, 0x40, 0x23, 0x3c, 0x08, 0x46, 0x6f, 0xfc, 0x07, 0x58, 0x63, 0x0f, 0xff, +0x40, 0x01, 0x98, 0x02, 0x40, 0x10, 0x08, 0x04, 0x14, 0x1f, 0x80, 0x01, 0x00, 0x7f, 0x80, 0x10, +0x04, 0x5f, 0x80, 0x01, 0x40, 0x43, 0xd8, 0x08, 0x40, 0x32, 0xa8, 0x08, 0x40, 0x31, 0xa8, 0x09, +0x40, 0x21, 0x90, 0x04, 0x14, 0x2f, 0x80, 0x01, 0x46, 0x0a, 0x00, 0x00, 0x04, 0x1f, 0x80, 0x01, +0x14, 0x10, 0x00, 0x58, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x08, 0x3a, 0x6f, 0x9c, 0x04, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0x3c, 0x46, 0x6a, 0x00, 0x00, 0x04, 0x63, 0x00, 0x59, +0x14, 0x60, 0x00, 0x00, 0x46, 0x0a, 0x00, 0x00, 0x04, 0x60, 0x00, 0x5a, 0x46, 0x0a, 0x00, 0x00, +0x14, 0x60, 0x80, 0x00, 0x04, 0x10, 0x00, 0x5b, 0x46, 0x0a, 0x00, 0x00, 0x14, 0x11, 0x00, 0x00, +0x04, 0x20, 0x00, 0x5c, 0x46, 0x0a, 0x00, 0x00, 0x14, 0x21, 0x80, 0x00, 0x04, 0x10, 0x00, 0x5d, +0x58, 0x20, 0x00, 0x00, 0x14, 0x12, 0x00, 0x00, 0x04, 0x31, 0x00, 0x5e, 0x46, 0x0a, 0x00, 0x00, +0x14, 0x32, 0x80, 0x00, 0x04, 0x10, 0x00, 0x5f, 0x04, 0x2f, 0x80, 0x01, 0x58, 0x50, 0x00, 0x00, +0x14, 0x11, 0x00, 0x00, 0x04, 0x32, 0x80, 0x60, 0x04, 0x4f, 0x80, 0x02, 0x46, 0x0a, 0x00, 0x00, +0x14, 0x32, 0x00, 0x00, 0x04, 0x10, 0x00, 0x61, 0x04, 0x2f, 0x80, 0x03, 0x44, 0x00, 0x00, 0x01, +0x14, 0x11, 0x00, 0x00, 0x3a, 0x6f, 0x98, 0x04, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x54, 0x60, 0x00, 0xff, 0x54, 0x70, 0x80, 0xff, 0x58, 0x13, 0x80, 0x00, +0x58, 0x03, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x86, 0x08, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x50, 0x0f, 0xff, 0x4c, 0x02, 0x80, 0x28, 0x4e, 0x62, 0x00, 0x10, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x62, 0x80, 0x0e, 0x44, 0x10, 0x00, 0x02, 0x4c, 0x60, 0xc0, 0x08, 0x40, 0x63, 0x84, 0x00, +0x54, 0x63, 0x00, 0xff, 0x48, 0x00, 0x00, 0x04, 0x44, 0x60, 0x00, 0x00, 0x44, 0x00, 0x00, 0x14, +0x43, 0xe3, 0x00, 0x24, 0x46, 0x10, 0x00, 0x07, 0x58, 0x10, 0x8c, 0x70, 0x40, 0x6f, 0x04, 0x00, +0x04, 0x53, 0x00, 0x03, 0x04, 0x33, 0x00, 0x04, 0x04, 0x42, 0x80, 0x00, 0x40, 0x22, 0x0c, 0x0d, +0x54, 0x01, 0x0f, 0xff, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x54, 0x60, 0x00, 0xff, 0x54, 0x70, 0x80, 0xff, +0x58, 0x13, 0x80, 0x00, 0x58, 0x03, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x86, 0x08, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x50, 0x0f, 0xff, 0x4c, 0x02, 0x80, 0x2e, 0x4e, 0x62, 0x00, 0x10, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0x80, 0x0e, 0x44, 0x10, 0x00, 0x02, 0x4c, 0x60, 0xc0, 0x08, +0x40, 0x63, 0x84, 0x00, 0x54, 0x63, 0x00, 0xff, 0x48, 0x00, 0x00, 0x04, 0x44, 0x60, 0x00, 0x00, +0x44, 0x30, 0x00, 0x14, 0x42, 0x63, 0x0c, 0x24, 0x46, 0x20, 0x00, 0x07, 0x58, 0x21, 0x0c, 0x70, +0x40, 0x63, 0x08, 0x00, 0x04, 0x03, 0x00, 0x01, 0x04, 0x43, 0x00, 0x02, 0x05, 0xe0, 0x00, 0x00, +0x44, 0x10, 0xff, 0xff, 0x40, 0x50, 0x90, 0x0c, 0x40, 0x32, 0xf8, 0x02, 0x40, 0x21, 0x90, 0x0d, +0x40, 0x01, 0x00, 0x13, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x54, 0x70, 0x80, 0xff, 0x54, 0x61, 0x00, 0xff, +0x58, 0x13, 0x00, 0x00, 0x54, 0x80, 0x00, 0xff, 0x58, 0x03, 0x80, 0x00, 0x54, 0x91, 0x80, 0xff, +0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x85, 0x08, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x50, 0x0f, 0xff, +0x4c, 0x02, 0xc0, 0x06, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x4a, 0x04, 0x5f, 0x80, 0x01, +0x54, 0x13, 0x80, 0x03, 0x42, 0x42, 0xfc, 0x08, 0x14, 0x4f, 0x80, 0x01, 0x54, 0x24, 0x80, 0x01, +0x04, 0x3f, 0x80, 0x01, 0x43, 0xe1, 0xc0, 0x08, 0x15, 0xef, 0x80, 0x01, 0x10, 0x8f, 0x80, 0x05, +0x40, 0x51, 0x1c, 0x08, 0x04, 0x7f, 0x80, 0x01, 0x41, 0xe0, 0x94, 0x08, 0x42, 0x43, 0x9c, 0x09, +0x40, 0x32, 0x14, 0x04, 0x14, 0x3f, 0x80, 0x01, 0x44, 0x1f, 0xff, 0x9f, 0x04, 0x0f, 0x80, 0x01, +0x40, 0x70, 0x04, 0x02, 0x40, 0x73, 0xf8, 0x04, 0x14, 0x7f, 0x80, 0x01, 0x54, 0x63, 0x00, 0x1f, +0x04, 0x5f, 0x80, 0x01, 0x46, 0x3a, 0x00, 0x00, 0x40, 0x42, 0x94, 0x09, 0x40, 0x42, 0x14, 0x08, +0x40, 0x62, 0x18, 0x04, 0x14, 0x6f, 0x80, 0x01, 0x58, 0x31, 0x81, 0x94, 0x04, 0x0f, 0x80, 0x01, +0x58, 0x11, 0x80, 0x00, 0x14, 0x01, 0x80, 0x00, 0x05, 0xe0, 0x80, 0x00, 0x15, 0xef, 0x80, 0x01, +0x04, 0x0f, 0x80, 0x01, 0x4e, 0x05, 0xff, 0xfa, 0x44, 0x00, 0x00, 0x01, 0x51, 0xff, 0x80, 0x0c, +0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x51, 0xff, 0xff, 0xf8, +0x54, 0x60, 0x00, 0xff, 0x54, 0x70, 0x80, 0xff, 0x58, 0x13, 0x80, 0x00, 0x58, 0x03, 0x00, 0x00, +0x54, 0x81, 0x00, 0xff, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x85, 0x08, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x50, 0x0f, 0xff, 0x4c, 0x02, 0xc0, 0x08, 0x4e, 0x63, 0x00, 0x46, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x72, 0xc0, 0x42, 0x04, 0x1f, 0x80, 0x01, 0x46, 0x2f, 0xfe, 0x0f, 0x54, 0x43, 0x80, 0x1f, +0x58, 0x21, 0x0f, 0xff, 0x40, 0x32, 0x40, 0x08, 0x40, 0x70, 0x88, 0x02, 0x40, 0x73, 0x8c, 0x04, +0x14, 0x7f, 0x80, 0x01, 0x54, 0x03, 0x00, 0x03, 0x05, 0xef, 0x80, 0x01, 0x42, 0x4f, 0x54, 0x09, +0x42, 0x42, 0x58, 0x09, 0x40, 0x50, 0x54, 0x08, 0x40, 0x32, 0x14, 0x04, 0x14, 0x3f, 0x80, 0x01, +0x04, 0x0f, 0x80, 0x01, 0x54, 0x14, 0x00, 0x01, 0x42, 0x60, 0x5c, 0x09, 0x41, 0xe0, 0xdc, 0x08, +0x40, 0x53, 0x78, 0x04, 0x14, 0x5f, 0x80, 0x01, 0x46, 0x6a, 0x00, 0x00, 0x04, 0x4f, 0x80, 0x01, +0x14, 0x43, 0x00, 0x09, 0x46, 0xf0, 0x00, 0x03, 0x58, 0xf7, 0x8d, 0x9c, 0x4b, 0xe0, 0x3c, 0x01, +0x04, 0x33, 0x00, 0x09, 0x14, 0x3f, 0x80, 0x01, 0x04, 0x0f, 0x80, 0x01, 0x54, 0x00, 0x0f, 0xff, +0x48, 0x00, 0x00, 0x04, 0x44, 0x00, 0x0f, 0xff, 0x51, 0xff, 0x80, 0x08, 0x3a, 0x6f, 0xa0, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x46, 0x00, 0x01, 0x0f, 0x00, 0x10, 0x0b, 0x74, 0x4e, 0x12, 0x00, 0x06, +0x44, 0x20, 0x00, 0x00, 0x10, 0x20, 0x0b, 0x74, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xc4, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, 0x8b, 0x74, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x02, 0x84, 0x0c, 0x46, 0x66, 0x02, 0x00, 0x14, 0x6f, 0x80, 0x01, 0x46, 0x5b, 0xfc, 0xff, +0x04, 0x0f, 0x80, 0x01, 0x58, 0x43, 0x00, 0x00, 0x14, 0x5f, 0x80, 0x02, 0x14, 0x4f, 0x80, 0x03, +0x58, 0x00, 0x08, 0x00, 0x14, 0x0f, 0x80, 0x01, 0x04, 0x1f, 0x80, 0x02, 0x04, 0x0f, 0x80, 0x03, +0x58, 0x32, 0x00, 0x00, 0x58, 0x21, 0x80, 0x00, 0x14, 0x3f, 0x80, 0x04, 0x14, 0x2f, 0x80, 0x05, +0x58, 0x10, 0x83, 0xfc, 0x14, 0x1f, 0x80, 0x02, 0x14, 0x0f, 0x80, 0x03, 0x04, 0x1f, 0x80, 0x04, +0x04, 0x0f, 0x80, 0x05, 0x58, 0x10, 0x80, 0x04, 0x58, 0x00, 0x01, 0x7c, 0x14, 0x1f, 0x80, 0x04, +0x14, 0x0f, 0x80, 0x05, 0x44, 0x10, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x10, 0x17, 0x8b, 0x74, +0x04, 0x0f, 0x80, 0x02, 0x04, 0x1f, 0x80, 0x01, 0x47, 0xe6, 0x02, 0x04, 0x14, 0x00, 0x80, 0x00, +0x44, 0x00, 0x02, 0x45, 0x04, 0x1f, 0x80, 0x03, 0x47, 0xc0, 0xaa, 0xe0, 0x14, 0x00, 0x80, 0x00, +0x04, 0x1f, 0x80, 0x04, 0x59, 0xce, 0x00, 0xae, 0x14, 0x00, 0x80, 0x00, 0x58, 0xaf, 0x00, 0x00, +0x04, 0x0f, 0x80, 0x05, 0x44, 0x10, 0x00, 0x00, 0x58, 0x91, 0x00, 0x00, 0x46, 0x82, 0x01, 0x71, +0x58, 0x71, 0x00, 0x00, 0x46, 0x61, 0x72, 0x02, 0x58, 0x51, 0x00, 0x00, 0x46, 0x42, 0x02, 0x02, +0x14, 0x10, 0x00, 0x00, 0x15, 0xcf, 0x00, 0x81, 0x58, 0x84, 0x07, 0x17, 0x58, 0x63, 0x08, 0x20, +0x58, 0x42, 0x00, 0x20, 0x45, 0xc1, 0x00, 0x4d, 0x58, 0x35, 0x00, 0x00, 0x15, 0xc5, 0x00, 0x82, +0x14, 0x84, 0x82, 0x17, 0x14, 0x63, 0x82, 0x18, 0x14, 0x42, 0x82, 0x19, 0x44, 0x54, 0xba, 0x43, +0x14, 0x11, 0x80, 0x42, 0x58, 0x01, 0x00, 0x00, 0x14, 0x51, 0x01, 0xbe, 0x04, 0x40, 0x01, 0xb2, +0x58, 0x20, 0x00, 0x00, 0x42, 0x92, 0x78, 0x09, 0x59, 0xe0, 0x00, 0x00, 0x14, 0x90, 0x01, 0xb2, +0x58, 0x11, 0x80, 0x00, 0x04, 0x01, 0x01, 0xb3, 0x15, 0xef, 0x80, 0x01, 0x14, 0x1f, 0x80, 0x03, +0x42, 0x00, 0x00, 0x09, 0x47, 0xcd, 0xbe, 0xa2, 0x04, 0x1f, 0x80, 0x01, 0x15, 0xcf, 0x80, 0x02, +0x58, 0x10, 0x86, 0xec, 0x14, 0x1f, 0x80, 0x01, 0x04, 0x1f, 0x80, 0x02, 0x46, 0xa7, 0xf5, 0x55, +0x58, 0x10, 0x8f, 0x40, 0x14, 0x1f, 0x80, 0x02, 0x04, 0x1f, 0x80, 0x03, 0x14, 0xaf, 0x80, 0x04, +0x58, 0x10, 0x84, 0x60, 0x58, 0x81, 0x00, 0x00, 0x14, 0x1f, 0x80, 0x03, 0x04, 0x1f, 0x80, 0x04, +0x14, 0x8f, 0x80, 0x05, 0x58, 0x10, 0x80, 0x80, 0x46, 0x70, 0x48, 0x91, 0x14, 0x1f, 0x80, 0x04, +0x04, 0x1f, 0x80, 0x05, 0x14, 0x7f, 0x80, 0x06, 0x58, 0x10, 0x85, 0x50, 0x58, 0x61, 0x00, 0x00, +0x14, 0x1f, 0x80, 0x05, 0x04, 0x1f, 0x80, 0x06, 0x14, 0x6f, 0x80, 0x07, 0x58, 0x10, 0x81, 0xa3, +0x46, 0x50, 0x0d, 0x8b, 0x14, 0x1f, 0x80, 0x06, 0x04, 0x1f, 0x80, 0x07, 0x14, 0x5f, 0x80, 0x08, +0x58, 0x10, 0x85, 0x58, 0x46, 0x46, 0x02, 0x01, 0x14, 0x1f, 0x80, 0x07, 0x04, 0x1f, 0x80, 0x08, +0x14, 0x4f, 0x80, 0x09, 0x58, 0x10, 0x8c, 0xc4, 0x46, 0x91, 0x29, 0x29, 0x14, 0x1f, 0x80, 0x08, +0x04, 0x1f, 0x80, 0x09, 0x14, 0x9f, 0x80, 0x0a, 0x58, 0x10, 0x86, 0x08, 0x14, 0x1f, 0x80, 0x09, +0x04, 0x1f, 0x80, 0x0a, 0x58, 0x32, 0x00, 0x00, 0x47, 0xe0, 0x2e, 0x11, 0x59, 0xc1, 0x80, 0x00, +0x58, 0x10, 0x85, 0x15, 0x14, 0x3f, 0x80, 0x0b, 0x15, 0xef, 0x80, 0x0c, 0x15, 0xcf, 0x80, 0x0d, +0x14, 0x1f, 0x80, 0x0a, 0x04, 0x1f, 0x80, 0x0b, 0x47, 0xe0, 0x69, 0x8f, 0x58, 0x10, 0x86, 0x0c, +0x14, 0x1f, 0x80, 0x0b, 0x04, 0x1f, 0x80, 0x0c, 0x59, 0xc1, 0x80, 0x00, 0x58, 0x10, 0x8d, 0x30, +0x14, 0x1f, 0x80, 0x0c, 0x04, 0x1f, 0x80, 0x0d, 0x46, 0xa5, 0x22, 0x0c, 0x58, 0x10, 0x86, 0x10, +0x14, 0x1f, 0x80, 0x0d, 0x14, 0x01, 0x01, 0xb3, 0x04, 0x0f, 0x80, 0x02, 0x04, 0x2f, 0x80, 0x01, +0x58, 0x81, 0x80, 0x00, 0x14, 0x01, 0x00, 0x00, 0x59, 0xef, 0x08, 0x2a, 0x04, 0x0f, 0x80, 0x04, +0x04, 0x2f, 0x80, 0x03, 0x14, 0x01, 0x00, 0x00, 0x04, 0x0f, 0x80, 0x06, 0x04, 0x2f, 0x80, 0x05, +0x46, 0x76, 0x02, 0x04, 0x14, 0x01, 0x00, 0x00, 0x58, 0x63, 0x80, 0x00, 0x04, 0x0f, 0x80, 0x08, +0x04, 0x2f, 0x80, 0x07, 0x58, 0x53, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x58, 0x42, 0x80, 0x00, +0x04, 0x0f, 0x80, 0x0a, 0x04, 0x2f, 0x80, 0x09, 0x46, 0x90, 0x03, 0xfb, 0x14, 0x01, 0x00, 0x00, +0x58, 0x32, 0x00, 0x00, 0x04, 0x0f, 0x80, 0x0c, 0x04, 0x2f, 0x80, 0x0b, 0x58, 0x94, 0x88, 0xb8, +0x14, 0x01, 0x00, 0x00, 0x44, 0x00, 0x05, 0xd5, 0x04, 0x2f, 0x80, 0x0d, 0x44, 0x10, 0xe0, 0xe0, +0x15, 0xe1, 0x00, 0x00, 0x14, 0xae, 0x01, 0x85, 0x46, 0xa6, 0x02, 0x00, 0x14, 0x04, 0x01, 0xa5, +0x44, 0x80, 0x00, 0xbf, 0x14, 0x83, 0x80, 0x98, 0x14, 0x13, 0x00, 0x99, 0x14, 0x12, 0x80, 0x9a, +0x14, 0x92, 0x01, 0xc5, 0x46, 0x1f, 0xfe, 0x00, 0x14, 0x91, 0x81, 0xc6, 0x04, 0x25, 0x00, 0x3f, +0x58, 0x10, 0x80, 0x0f, 0x58, 0x5e, 0x00, 0x00, 0x58, 0x45, 0x00, 0x00, 0x46, 0x92, 0x00, 0xfc, +0x58, 0x02, 0x80, 0x00, 0x58, 0x81, 0x80, 0x00, 0x40, 0x61, 0x04, 0x02, 0x58, 0x94, 0x80, 0x0c, +0x44, 0x70, 0x00, 0x00, 0x44, 0x30, 0xc4, 0xc6, 0x14, 0x65, 0x00, 0x3f, 0x14, 0x72, 0x80, 0x5f, +0x14, 0x92, 0x01, 0x45, 0x14, 0x90, 0x01, 0x45, 0x14, 0x34, 0x01, 0x23, 0x58, 0x94, 0x00, 0x00, +0x04, 0x24, 0x80, 0x64, 0x44, 0x1c, 0xff, 0xff, 0x40, 0x01, 0x04, 0x02, 0x42, 0xa0, 0x40, 0x08, +0x14, 0xa4, 0x80, 0x64, 0x58, 0x52, 0x00, 0x00, 0x04, 0x82, 0x81, 0x61, 0x44, 0x4f, 0xfc, 0xff, +0x40, 0x64, 0x10, 0x02, 0x58, 0x73, 0x01, 0x00, 0x14, 0x72, 0x81, 0x61, 0x58, 0x0e, 0x00, 0x00, +0x04, 0x30, 0x01, 0x61, 0x58, 0x82, 0x80, 0x00, 0x40, 0x11, 0x90, 0x02, 0x58, 0x20, 0x81, 0x00, +0x14, 0x20, 0x01, 0x61, 0x04, 0xa4, 0x01, 0x4e, 0x44, 0x6f, 0xfd, 0xff, 0x40, 0x95, 0x18, 0x02, +0x14, 0x94, 0x01, 0x4e, 0x58, 0x40, 0x00, 0x00, 0x04, 0x72, 0x01, 0x4e, 0x40, 0x53, 0x98, 0x02, +0x14, 0x52, 0x01, 0x4e, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x27, 0x8a, 0x1e, 0x4e, 0x22, 0x00, 0x0c, +0x46, 0x06, 0x02, 0x00, 0x46, 0x14, 0xf1, 0x7b, 0x58, 0x00, 0x05, 0x18, 0x58, 0x10, 0x8b, 0xf5, +0x48, 0x00, 0x00, 0x0a, 0x46, 0x06, 0x02, 0x00, 0x46, 0x14, 0xef, 0xfa, 0x58, 0x00, 0x05, 0x18, +0x58, 0x10, 0x8f, 0xea, 0x14, 0x10, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x17, 0x8a, 0x1f, +0x4e, 0x12, 0x00, 0x0c, 0x46, 0x06, 0x02, 0x01, 0x46, 0x34, 0xf1, 0x7b, 0x58, 0x00, 0x05, 0x18, +0x58, 0x31, 0x8b, 0xf5, 0x48, 0x00, 0x00, 0x0a, 0x46, 0x06, 0x02, 0x01, 0x46, 0x34, 0xef, 0xfa, +0x58, 0x00, 0x05, 0x18, 0x58, 0x31, 0x8f, 0xea, 0x14, 0x30, 0x00, 0x00, 0x58, 0x44, 0x00, 0x00, +0x46, 0x5b, 0x20, 0x10, 0x58, 0x3e, 0x00, 0x00, 0x14, 0x52, 0x03, 0x45, 0x14, 0x51, 0x83, 0x45, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x97, 0x89, 0xbc, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0xa7, 0x89, 0xbd, +0x54, 0x84, 0x80, 0x7f, 0x40, 0x75, 0x50, 0x08, 0x40, 0x64, 0x9c, 0x09, 0x40, 0x43, 0xa0, 0x04, +0x40, 0x53, 0x4c, 0x08, 0x46, 0x36, 0x02, 0x00, 0x58, 0xae, 0x00, 0x00, 0x40, 0x02, 0x14, 0x04, +0x14, 0x01, 0x83, 0x42, 0x14, 0x05, 0x03, 0x42, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x87, 0x8c, 0x07, +0x4e, 0x82, 0x00, 0x26, 0x58, 0x81, 0x80, 0x00, 0x04, 0x54, 0x03, 0x46, 0x44, 0x7f, 0x00, 0xff, +0x40, 0x02, 0x9c, 0x02, 0x58, 0xa0, 0x03, 0x00, 0x14, 0xa4, 0x03, 0x46, 0x46, 0x46, 0x02, 0x01, +0x58, 0x42, 0x0d, 0x18, 0x04, 0x62, 0x00, 0x00, 0x46, 0x30, 0x20, 0x01, 0x40, 0x93, 0x1c, 0x02, +0x46, 0x00, 0x30, 0x00, 0x58, 0x7e, 0x00, 0x00, 0x58, 0x64, 0x00, 0x00, 0x58, 0x53, 0x80, 0x00, +0x58, 0x31, 0x86, 0x1f, 0x58, 0x94, 0x83, 0x00, 0x48, 0x00, 0x00, 0x22, 0x46, 0x66, 0x02, 0x00, +0x04, 0x73, 0x03, 0x46, 0x44, 0xaf, 0x00, 0xff, 0x40, 0x33, 0xa8, 0x02, 0x14, 0x33, 0x03, 0x46, +0x46, 0x46, 0x02, 0x01, 0x58, 0x42, 0x0d, 0x18, 0x04, 0x92, 0x00, 0x00, 0x46, 0x38, 0x20, 0x01, +0x46, 0x00, 0x50, 0x20, 0x46, 0x86, 0x02, 0x00, 0x46, 0x76, 0x02, 0x01, 0x46, 0x66, 0x02, 0x00, +0x46, 0x56, 0x02, 0x01, 0x58, 0x31, 0x83, 0x1a, 0x40, 0x94, 0xa8, 0x02, 0x14, 0x92, 0x00, 0x00, +0x14, 0x34, 0x03, 0x47, 0x14, 0x33, 0x83, 0x47, 0x14, 0x03, 0x03, 0x48, 0x14, 0x02, 0x83, 0x48, +0x46, 0x06, 0x02, 0x04, 0x58, 0x00, 0x06, 0x00, 0x04, 0xa0, 0x00, 0x00, 0x42, 0x65, 0x58, 0x09, +0x42, 0x63, 0x5c, 0x09, 0x42, 0x43, 0x5c, 0x08, 0x14, 0x40, 0x00, 0x00, 0x04, 0x50, 0x00, 0x00, +0x46, 0x36, 0x02, 0x00, 0x42, 0xa2, 0x9c, 0x09, 0x14, 0xa0, 0x00, 0x00, 0x04, 0x51, 0x81, 0x8e, +0x40, 0x72, 0x94, 0x09, 0x40, 0x73, 0x94, 0x08, 0x58, 0xa3, 0x80, 0x1e, 0x14, 0xa1, 0x81, 0x8e, +0x58, 0x41, 0x80, 0x00, 0x04, 0x52, 0x01, 0x83, 0x46, 0x63, 0x00, 0x00, 0x40, 0x72, 0x98, 0x04, +0x14, 0x72, 0x01, 0x83, 0x46, 0x06, 0x02, 0x04, 0x58, 0x00, 0x02, 0x00, 0x04, 0xa0, 0x00, 0x00, +0x46, 0x7f, 0xff, 0x00, 0x58, 0x55, 0x03, 0xff, 0x14, 0x50, 0x00, 0x00, 0x58, 0x73, 0x83, 0xff, +0x04, 0x60, 0x00, 0x00, 0x44, 0xa2, 0xe0, 0x00, 0x40, 0x63, 0x1c, 0x02, 0x40, 0x73, 0x28, 0x04, +0x14, 0x70, 0x00, 0x00, 0x46, 0x36, 0x02, 0x04, 0x04, 0x61, 0x80, 0x8a, 0x40, 0xa3, 0x14, 0x09, +0x40, 0xa5, 0x14, 0x08, 0x58, 0x41, 0x80, 0x00, 0x46, 0x57, 0xc9, 0x00, 0x58, 0x52, 0x84, 0x08, +0x58, 0x65, 0x00, 0x0d, 0x14, 0x61, 0x80, 0x8a, 0x46, 0x06, 0x02, 0x00, 0x14, 0x52, 0x00, 0x83, +0x04, 0x50, 0x01, 0x8d, 0x46, 0xa0, 0x1f, 0x80, 0x40, 0x42, 0xa8, 0x04, 0x14, 0x40, 0x01, 0x8d, +0x58, 0x30, 0x00, 0x00, 0x04, 0x41, 0x81, 0x85, 0x42, 0x42, 0x4c, 0x09, 0x14, 0x41, 0x81, 0x85, +0x46, 0x06, 0x02, 0x04, 0x04, 0x50, 0x00, 0x3c, 0x58, 0x42, 0x80, 0x02, 0x14, 0x40, 0x00, 0x3c, +0x4e, 0x22, 0x00, 0x10, 0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x05, 0x00, 0x04, 0x40, 0x00, 0x00, +0x40, 0x32, 0x50, 0x09, 0x40, 0x31, 0xd0, 0x08, 0x58, 0x31, 0xf7, 0x6f, 0x48, 0x00, 0x00, 0x10, +0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x05, 0x00, 0x04, 0xa0, 0x00, 0x00, 0x40, 0x55, 0x50, 0x09, +0x40, 0x52, 0xd0, 0x08, 0x44, 0xa1, 0x88, 0x6f, 0x40, 0x32, 0xa8, 0x04, 0x14, 0x30, 0x00, 0x00, +0x4e, 0x12, 0x00, 0x10, 0x46, 0x06, 0x02, 0x01, 0x58, 0x00, 0x05, 0x00, 0x04, 0x50, 0x00, 0x00, +0x40, 0x32, 0xd0, 0x09, 0x40, 0x31, 0xd0, 0x08, 0x58, 0x31, 0xf7, 0x6f, 0x48, 0x00, 0x00, 0x10, +0x46, 0x06, 0x02, 0x01, 0x58, 0x00, 0x05, 0x00, 0x04, 0x60, 0x00, 0x00, 0x40, 0x33, 0x50, 0x09, +0x40, 0x31, 0xd0, 0x08, 0x44, 0x61, 0x88, 0x6f, 0x40, 0x31, 0x98, 0x04, 0x14, 0x30, 0x00, 0x00, +0x4e, 0x22, 0x00, 0x14, 0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x05, 0x20, 0x04, 0xa0, 0x00, 0x00, +0x40, 0x45, 0x60, 0x09, 0x40, 0x42, 0x60, 0x08, 0x46, 0xa0, 0x0b, 0x20, 0x58, 0xa5, 0x04, 0xc1, +0x40, 0x32, 0x28, 0x04, 0x48, 0x00, 0x00, 0x12, 0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x05, 0x20, +0x04, 0x30, 0x00, 0x00, 0x46, 0x50, 0x0b, 0xe2, 0x40, 0x31, 0xe0, 0x09, 0x40, 0x31, 0xe0, 0x08, +0x58, 0x52, 0x85, 0x82, 0x40, 0x31, 0x94, 0x04, 0x14, 0x30, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x14, +0x46, 0x06, 0x02, 0x01, 0x58, 0x00, 0x05, 0x20, 0x04, 0x70, 0x00, 0x00, 0x40, 0x53, 0xe0, 0x09, +0x40, 0x52, 0xe0, 0x08, 0x46, 0x70, 0x0b, 0x20, 0x58, 0x73, 0x84, 0xc1, 0x40, 0x32, 0x9c, 0x04, +0x48, 0x00, 0x00, 0x12, 0x46, 0x06, 0x02, 0x01, 0x58, 0x00, 0x05, 0x20, 0x04, 0x50, 0x00, 0x00, +0x46, 0x40, 0x0b, 0xe2, 0x40, 0x32, 0xe0, 0x09, 0x40, 0x31, 0xe0, 0x08, 0x58, 0x42, 0x05, 0x82, +0x40, 0x31, 0x90, 0x04, 0x14, 0x30, 0x00, 0x00, 0x4e, 0x22, 0x00, 0x0e, 0x46, 0x06, 0x02, 0x00, +0x58, 0x00, 0x05, 0x84, 0x04, 0x20, 0x00, 0x00, 0x46, 0x60, 0xb4, 0x90, 0x40, 0x21, 0x00, 0x13, +0x48, 0x00, 0x00, 0x34, 0x46, 0xf0, 0x01, 0x0f, 0x20, 0x07, 0x8c, 0x03, 0x4e, 0x03, 0x00, 0x0e, +0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x05, 0x84, 0x04, 0xa0, 0x00, 0x00, 0x40, 0x25, 0x00, 0x13, +0x46, 0xa0, 0xb4, 0x90, 0x48, 0x00, 0x00, 0x30, 0x5e, 0xf0, 0x7f, 0xfb, 0x4e, 0xf3, 0x00, 0x10, +0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x05, 0x84, 0x04, 0x50, 0x00, 0x00, 0x46, 0x40, 0xb4, 0x90, +0x40, 0x32, 0x80, 0x13, 0x40, 0x21, 0x90, 0x04, 0x48, 0x00, 0x00, 0x20, 0x5e, 0xf0, 0x7f, 0xf7, +0x4e, 0xf3, 0x00, 0x10, 0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x05, 0x84, 0x04, 0x60, 0x00, 0x00, +0x40, 0x23, 0x00, 0x13, 0x46, 0x60, 0xb6, 0x90, 0x40, 0x21, 0x18, 0x04, 0x48, 0x00, 0x00, 0x0e, +0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x05, 0x84, 0x04, 0x20, 0x00, 0x00, 0x46, 0xa0, 0xb6, 0x90, +0x40, 0x21, 0x00, 0x13, 0x40, 0x21, 0x28, 0x04, 0x14, 0x20, 0x00, 0x00, 0x4e, 0x12, 0x00, 0x10, +0x46, 0x06, 0x02, 0x01, 0x58, 0x00, 0x05, 0x84, 0x04, 0x40, 0x00, 0x00, 0x46, 0x30, 0xb4, 0x90, +0x40, 0x12, 0x00, 0x13, 0x40, 0x10, 0x8c, 0x04, 0x48, 0x00, 0x00, 0x46, 0x46, 0xf0, 0x01, 0x0f, +0x20, 0x07, 0x8c, 0x03, 0x4e, 0x03, 0x00, 0x10, 0x46, 0x06, 0x02, 0x01, 0x58, 0x00, 0x05, 0x84, +0x04, 0x10, 0x00, 0x00, 0x46, 0x50, 0xb4, 0x90, 0x40, 0x20, 0x80, 0x13, 0x40, 0x11, 0x14, 0x04, +0x48, 0x00, 0x00, 0x32, 0x5e, 0xf0, 0x7f, 0xfb, 0x4e, 0xf3, 0x00, 0x10, 0x46, 0x06, 0x02, 0x01, +0x58, 0x00, 0x05, 0x84, 0x04, 0x70, 0x00, 0x00, 0x40, 0x33, 0x80, 0x13, 0x46, 0x70, 0xb4, 0x90, +0x40, 0x11, 0x9c, 0x04, 0x48, 0x00, 0x00, 0x20, 0x5e, 0xf0, 0x7f, 0xf7, 0x4e, 0xf3, 0x00, 0x10, +0x46, 0x06, 0x02, 0x01, 0x58, 0x00, 0x05, 0x84, 0x04, 0x50, 0x00, 0x00, 0x46, 0x20, 0xb6, 0x90, +0x40, 0x42, 0x80, 0x13, 0x40, 0x12, 0x08, 0x04, 0x48, 0x00, 0x00, 0x0e, 0x46, 0x06, 0x02, 0x01, +0x58, 0x00, 0x05, 0x84, 0x04, 0x40, 0x00, 0x00, 0x46, 0x30, 0xb6, 0x90, 0x40, 0x12, 0x00, 0x13, +0x40, 0x10, 0x8c, 0x04, 0x14, 0x10, 0x00, 0x00, 0x51, 0xff, 0x80, 0x3c, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x07, 0x83, 0x06, 0x4a, 0x00, 0x78, 0x20, +0x46, 0x08, 0x00, 0x23, 0x04, 0x10, 0x00, 0x20, 0x46, 0x21, 0x10, 0x00, 0x40, 0x40, 0x88, 0x04, +0x14, 0x40, 0x00, 0x20, 0x58, 0x50, 0x00, 0x00, 0x04, 0x22, 0x80, 0x21, 0x44, 0x31, 0x01, 0x11, +0x40, 0x11, 0x0c, 0x04, 0x14, 0x12, 0x80, 0x21, 0x46, 0x08, 0x00, 0x00, 0x04, 0x40, 0x00, 0x42, +0x46, 0x18, 0x10, 0x60, 0x46, 0x20, 0x48, 0x52, 0x58, 0x32, 0x40, 0x00, 0x58, 0x21, 0x03, 0x90, +0x14, 0x30, 0x00, 0x42, 0x14, 0x20, 0x80, 0x02, 0x4a, 0x00, 0x78, 0x20, 0x46, 0x36, 0x02, 0x00, +0x14, 0x11, 0x83, 0x80, 0x4e, 0x23, 0x00, 0x08, 0x58, 0x11, 0x80, 0x00, 0x44, 0x21, 0x10, 0x00, +0x48, 0x00, 0x00, 0x06, 0x46, 0x16, 0x02, 0x00, 0x44, 0x23, 0x10, 0x00, 0x40, 0x00, 0x08, 0x00, +0x14, 0x00, 0x83, 0x81, 0x58, 0x01, 0x80, 0x00, 0x04, 0x20, 0x03, 0x84, 0x54, 0x11, 0x20, 0x00, +0x4e, 0x13, 0xff, 0xfc, 0x4a, 0x00, 0x78, 0x20, 0x4e, 0x13, 0x00, 0x0c, 0x44, 0x1e, 0xef, 0xff, +0x40, 0x00, 0x04, 0x02, 0x44, 0x21, 0x00, 0x00, 0x46, 0x16, 0x02, 0x00, 0x48, 0x00, 0x00, 0x0a, +0x44, 0x2c, 0xef, 0xff, 0x40, 0x00, 0x08, 0x02, 0x46, 0x16, 0x02, 0x00, 0x44, 0x23, 0x00, 0x00, +0x40, 0x00, 0x08, 0x04, 0x14, 0x00, 0x83, 0x81, 0x46, 0x06, 0x02, 0x00, 0x04, 0x40, 0x03, 0x84, +0x54, 0x32, 0x20, 0x00, 0x4e, 0x33, 0xff, 0xfc, 0x58, 0x50, 0x00, 0x00, 0x04, 0x02, 0x83, 0x83, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x58, 0x60, 0x00, 0x00, 0x44, 0x00, 0x00, 0x01, +0x4c, 0x60, 0x40, 0x30, 0x46, 0x80, 0x01, 0x0a, 0x58, 0x84, 0x04, 0xc8, 0x44, 0x10, 0x00, 0x00, +0x44, 0x00, 0x00, 0xa0, 0x4b, 0xe0, 0x20, 0x01, 0x40, 0x30, 0x10, 0x08, 0x40, 0x31, 0x90, 0x09, +0x42, 0x11, 0xf0, 0x08, 0x44, 0x20, 0x00, 0x00, 0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x84, 0x8c, +0x44, 0x00, 0x00, 0xa0, 0x4b, 0xe0, 0x1c, 0x01, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x00, 0xa0, +0x4b, 0xe0, 0x20, 0x01, 0x40, 0x20, 0x10, 0x08, 0x40, 0x21, 0x10, 0x09, 0x42, 0x11, 0x70, 0x08, +0x44, 0x00, 0x00, 0xa0, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x48, 0x00, 0x00, 0x34, +0x4e, 0x62, 0x00, 0x0a, 0x44, 0x50, 0x00, 0x05, 0x4c, 0x62, 0x80, 0x06, 0x44, 0x50, 0x00, 0x04, +0x4c, 0x62, 0xc0, 0x2a, 0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x84, 0xc8, 0x44, 0x10, 0x00, 0x00, +0x44, 0x00, 0x00, 0xa0, 0x4b, 0xe0, 0x1c, 0x01, 0x40, 0x10, 0x10, 0x08, 0x40, 0x10, 0x90, 0x09, +0x44, 0x20, 0x00, 0x00, 0x44, 0x00, 0x00, 0xa0, 0x46, 0x60, 0x01, 0x0a, 0x58, 0x63, 0x04, 0x8c, +0x4b, 0xe0, 0x18, 0x01, 0x44, 0x10, 0x00, 0x01, 0x44, 0x00, 0x00, 0xa0, 0x4b, 0xe0, 0x1c, 0x01, +0x40, 0x10, 0x10, 0x08, 0x40, 0x10, 0x90, 0x09, 0x44, 0x20, 0x00, 0x01, 0x44, 0x00, 0x00, 0xa0, +0x4b, 0xe0, 0x18, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x46, 0x00, 0x01, 0x0f, 0x58, 0x00, 0x07, 0x88, 0x44, 0x10, 0x00, 0x00, +0x48, 0x00, 0x00, 0x0c, 0x04, 0x30, 0x00, 0x00, 0x04, 0x40, 0x00, 0x01, 0x50, 0x10, 0x80, 0x01, +0x14, 0x41, 0x80, 0x00, 0x50, 0x00, 0x00, 0x08, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x57, 0x8c, 0x1c, +0x40, 0xf0, 0x94, 0x06, 0x4e, 0xf3, 0xff, 0xf0, 0x46, 0x60, 0x01, 0x0f, 0x58, 0x63, 0x08, 0x90, +0x44, 0x70, 0x00, 0x00, 0x46, 0x80, 0x01, 0x0a, 0x58, 0x84, 0x04, 0x8c, 0x48, 0x00, 0x00, 0x0c, +0x04, 0x03, 0x00, 0x00, 0x04, 0x13, 0x00, 0x01, 0x50, 0x73, 0x80, 0x01, 0x4b, 0xe0, 0x20, 0x01, +0x50, 0x63, 0x00, 0x08, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, 0x8c, 0x1d, 0x44, 0x20, 0x00, 0x00, +0x40, 0xf3, 0x80, 0x06, 0x4e, 0xf3, 0xff, 0xee, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x77, 0x8c, 0x04, +0x44, 0x50, 0x00, 0x01, 0x46, 0x60, 0x01, 0x0a, 0x58, 0x63, 0x04, 0x8c, 0x4c, 0x72, 0xc0, 0x0a, +0x46, 0x1a, 0x88, 0x88, 0x58, 0x10, 0x88, 0x88, 0x44, 0x00, 0x00, 0x78, 0x48, 0x00, 0x00, 0x0a, +0x46, 0x18, 0x88, 0x88, 0x58, 0x10, 0x88, 0x88, 0x44, 0x00, 0x00, 0x78, 0x44, 0x20, 0x00, 0x00, +0x4b, 0xe0, 0x18, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x77, 0x8a, 0x1e, 0x46, 0x60, 0x01, 0x0a, +0x58, 0x63, 0x04, 0x8c, 0x4e, 0x72, 0x00, 0x16, 0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x00, +0x44, 0x00, 0x06, 0x10, 0x44, 0x20, 0x00, 0x00, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x10, 0x3f, 0xf0, +0x58, 0x10, 0x80, 0x03, 0x44, 0x00, 0x00, 0x54, 0x44, 0x20, 0x00, 0x00, 0x48, 0x00, 0x00, 0x14, +0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x08, 0x44, 0x00, 0x06, 0x10, 0x58, 0x23, 0x80, 0x00, +0x4b, 0xe0, 0x18, 0x01, 0x46, 0x18, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, 0x58, 0x23, 0x80, 0x00, +0x44, 0x00, 0x00, 0x54, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x27, 0x8c, 0x07, +0x46, 0x60, 0x01, 0x0a, 0x58, 0x63, 0x04, 0x8c, 0x4e, 0x23, 0x00, 0x0a, 0x46, 0x10, 0x06, 0x10, +0x58, 0x10, 0x80, 0x81, 0x44, 0x00, 0x00, 0xe8, 0x48, 0x00, 0x00, 0x0a, 0x46, 0x10, 0x0a, 0x10, +0x58, 0x10, 0x80, 0xe1, 0x44, 0x00, 0x00, 0xe8, 0x44, 0x20, 0x00, 0x00, 0x4b, 0xe0, 0x18, 0x01, +0x46, 0xf0, 0x01, 0x0f, 0x04, 0x47, 0x83, 0x06, 0x5c, 0xf2, 0x00, 0x02, 0x4e, 0xf3, 0x00, 0x22, +0x46, 0x60, 0x01, 0x0f, 0x58, 0x63, 0x08, 0xe0, 0x44, 0x70, 0x00, 0x00, 0x46, 0x80, 0x01, 0x0a, +0x58, 0x84, 0x04, 0x8c, 0x48, 0x00, 0x00, 0x0c, 0x04, 0x03, 0x00, 0x00, 0x04, 0x13, 0x00, 0x01, +0x50, 0x73, 0x80, 0x01, 0x4b, 0xe0, 0x20, 0x01, 0x50, 0x63, 0x00, 0x08, 0x46, 0xf0, 0x01, 0x0f, +0x01, 0xe7, 0x8c, 0x1e, 0x44, 0x20, 0x00, 0x01, 0x40, 0xf3, 0xf8, 0x06, 0x4e, 0xf3, 0xff, 0xee, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x27, 0x8c, 0x04, 0x44, 0x50, 0x00, 0x01, 0x46, 0x60, 0x01, 0x0a, +0x58, 0x63, 0x04, 0x8c, 0x4c, 0x22, 0xc0, 0x0a, 0x46, 0x1a, 0x88, 0x88, 0x58, 0x10, 0x88, 0x88, +0x44, 0x00, 0x00, 0x78, 0x48, 0x00, 0x00, 0x0a, 0x46, 0x18, 0x88, 0x88, 0x58, 0x10, 0x88, 0x88, +0x44, 0x00, 0x00, 0x78, 0x44, 0x20, 0x00, 0x01, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x27, 0x8a, 0x1f, 0x46, 0x60, 0x01, 0x0a, 0x58, 0x63, 0x04, 0x8c, 0x4e, 0x22, 0x00, 0x12, +0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x00, 0x44, 0x00, 0x06, 0x10, 0x44, 0x20, 0x00, 0x01, +0x4b, 0xe0, 0x18, 0x01, 0x46, 0x10, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, 0x48, 0x00, 0x00, 0x10, +0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x08, 0x44, 0x00, 0x06, 0x10, 0x44, 0x20, 0x00, 0x01, +0x4b, 0xe0, 0x18, 0x01, 0x46, 0x18, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, 0x44, 0x00, 0x00, 0x54, +0x44, 0x20, 0x00, 0x01, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x37, 0x8c, 0x07, +0x46, 0x60, 0x01, 0x0a, 0x58, 0x63, 0x04, 0x8c, 0x4e, 0x32, 0x00, 0x08, 0x46, 0x10, 0x0a, 0x10, +0x58, 0x10, 0x80, 0xe1, 0x48, 0x00, 0x00, 0x06, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x81, +0x44, 0x00, 0x00, 0xe8, 0x44, 0x20, 0x00, 0x01, 0x4b, 0xe0, 0x18, 0x01, 0x51, 0xff, 0x80, 0x04, +0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x47, 0xe6, 0x02, 0x00, 0x04, 0x3f, 0x00, 0x00, 0x58, 0x5f, 0x00, 0x00, 0x58, 0x21, 0x80, 0x45, +0x14, 0x2f, 0x00, 0x00, 0x04, 0x42, 0x80, 0x01, 0x40, 0x10, 0x80, 0x13, 0x58, 0x32, 0x00, 0x45, +0x44, 0x20, 0x00, 0x0e, 0x14, 0x32, 0x80, 0x01, 0x4c, 0x11, 0x40, 0x16, 0x46, 0x10, 0x01, 0x0f, +0x58, 0x10, 0x83, 0xe8, 0x04, 0x40, 0x80, 0x00, 0x05, 0xe0, 0x80, 0x01, 0x46, 0x50, 0x01, 0x0f, +0x58, 0x52, 0x84, 0x88, 0x50, 0x10, 0x80, 0x08, 0x15, 0xe2, 0x00, 0x00, 0x4c, 0x12, 0xff, 0xf4, +0x48, 0x00, 0x00, 0x14, 0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x84, 0x88, 0x04, 0x50, 0x80, 0x00, +0x04, 0x30, 0x80, 0x01, 0x46, 0x20, 0x01, 0x0f, 0x58, 0x21, 0x05, 0x28, 0x50, 0x10, 0x80, 0x08, +0x14, 0x32, 0x80, 0x00, 0x4c, 0x11, 0x7f, 0xf4, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x17, 0x8c, 0x07, +0x4e, 0x13, 0x00, 0x18, 0x46, 0xf0, 0x01, 0x13, 0x00, 0x47, 0x80, 0x08, 0x46, 0x36, 0x02, 0x00, +0x40, 0x12, 0x20, 0x08, 0x14, 0x11, 0x82, 0x82, 0x46, 0x06, 0x02, 0x01, 0x46, 0xf0, 0x01, 0x13, +0x00, 0x27, 0x80, 0x09, 0x41, 0xe1, 0x20, 0x08, 0x15, 0xe0, 0x02, 0x82, 0x48, 0x00, 0x00, 0x22, +0x46, 0x16, 0x02, 0x00, 0x05, 0xe0, 0x82, 0x82, 0x46, 0x3f, 0x00, 0x00, 0x40, 0x4f, 0x0c, 0x04, +0x14, 0x40, 0x82, 0x82, 0x46, 0x56, 0x02, 0x01, 0x04, 0x22, 0x82, 0x82, 0x46, 0x10, 0x10, 0x00, +0x41, 0xe1, 0x0c, 0x04, 0x15, 0xe2, 0x82, 0x82, 0x58, 0x20, 0x00, 0x00, 0x58, 0x10, 0x87, 0x00, +0x44, 0x00, 0x00, 0x70, 0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0x8c, 0x4b, 0xe0, 0x3c, 0x01, +0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x58, 0x60, 0x80, 0x00, 0x4e, 0x02, 0x00, 0x06, 0x44, 0x50, 0x00, 0x05, +0x4c, 0x02, 0xc0, 0x14, 0x40, 0x23, 0x14, 0x08, 0x50, 0x81, 0x00, 0x38, 0x46, 0x00, 0x01, 0x12, +0x58, 0x00, 0x0c, 0x70, 0x40, 0x84, 0x00, 0x00, 0x44, 0x70, 0x04, 0x28, 0x46, 0x90, 0x01, 0x0a, +0x58, 0x94, 0x84, 0x8c, 0x48, 0x00, 0x00, 0x08, 0x44, 0x50, 0x00, 0x04, 0x4c, 0x02, 0xc0, 0x66, +0x48, 0xff, 0xff, 0xea, 0x04, 0x14, 0x00, 0x00, 0x58, 0x03, 0x80, 0x00, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x24, 0x01, 0x04, 0x14, 0x00, 0x20, 0x50, 0x03, 0x82, 0xa4, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x24, 0x01, 0x50, 0x73, 0x80, 0x04, 0x44, 0x50, 0x04, 0x48, 0x50, 0x84, 0x00, 0x04, +0x4c, 0x72, 0xff, 0xea, 0x4e, 0x63, 0x00, 0x24, 0x46, 0x50, 0x01, 0x12, 0x58, 0x52, 0x8c, 0x70, +0x04, 0x12, 0x80, 0xcc, 0x47, 0xe6, 0x02, 0x00, 0x14, 0x1f, 0x00, 0x56, 0x58, 0x3f, 0x00, 0x00, +0x04, 0x42, 0x80, 0xcd, 0x14, 0x41, 0x80, 0x57, 0x58, 0x01, 0x80, 0x00, 0x04, 0x22, 0x80, 0xce, +0x14, 0x20, 0x00, 0x58, 0x59, 0xe0, 0x00, 0x00, 0x04, 0x12, 0x80, 0xd8, 0x14, 0x1f, 0x00, 0x62, +0x46, 0x16, 0x02, 0x00, 0x04, 0x02, 0x80, 0xd9, 0x48, 0x00, 0x00, 0x7c, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x62, 0xc0, 0xa2, 0x46, 0x00, 0x01, 0x12, 0x58, 0x00, 0x0c, 0x70, 0x04, 0x20, 0x00, 0xcf, +0x46, 0x36, 0x02, 0x01, 0x14, 0x21, 0x80, 0x56, 0x58, 0x11, 0x80, 0x00, 0x04, 0x50, 0x00, 0xd0, +0x14, 0x50, 0x80, 0x57, 0x58, 0x40, 0x80, 0x00, 0x05, 0xe0, 0x00, 0xd1, 0x15, 0xe2, 0x00, 0x58, +0x58, 0x30, 0x80, 0x00, 0x04, 0x20, 0x00, 0xda, 0x14, 0x21, 0x80, 0x62, 0x46, 0x16, 0x02, 0x01, +0x04, 0x00, 0x00, 0xdb, 0x48, 0x00, 0x00, 0x7c, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x7c, +0x40, 0x83, 0x14, 0x08, 0x50, 0x94, 0x00, 0x78, 0x46, 0x00, 0x01, 0x12, 0x58, 0x00, 0x0c, 0x70, +0x40, 0x84, 0x80, 0x00, 0x44, 0x70, 0x04, 0x48, 0x46, 0x90, 0x01, 0x0a, 0x58, 0x94, 0x84, 0x8c, +0x04, 0x14, 0x00, 0x00, 0x58, 0x03, 0x80, 0x00, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x24, 0x01, +0x04, 0x14, 0x00, 0x20, 0x50, 0x03, 0x82, 0x84, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x24, 0x01, +0x50, 0x73, 0x80, 0x04, 0x44, 0x50, 0x04, 0x68, 0x50, 0x84, 0x00, 0x04, 0x4c, 0x72, 0xff, 0xea, +0x4e, 0x63, 0x00, 0x2c, 0x46, 0xf0, 0x01, 0x12, 0x04, 0x57, 0x83, 0xee, 0x46, 0x16, 0x02, 0x00, +0x14, 0x50, 0x80, 0x56, 0x58, 0x00, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x12, 0x04, 0x47, 0x83, 0xef, +0x14, 0x40, 0x00, 0x57, 0x58, 0x30, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x12, 0x04, 0x27, 0x83, 0xf0, +0x14, 0x21, 0x80, 0x58, 0x58, 0x10, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x12, 0x04, 0x57, 0x83, 0xf8, +0x14, 0x50, 0x80, 0x62, 0x46, 0x16, 0x02, 0x00, 0x46, 0xf0, 0x01, 0x12, 0x04, 0x07, 0x83, 0xf9, +0x58, 0x10, 0x81, 0x8c, 0x48, 0x00, 0x00, 0x26, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x24, +0x46, 0x30, 0x01, 0x12, 0x58, 0x31, 0x8c, 0x70, 0x04, 0x21, 0x80, 0xd5, 0x46, 0x06, 0x02, 0x01, +0x14, 0x20, 0x00, 0x56, 0x58, 0x50, 0x00, 0x00, 0x05, 0xe1, 0x80, 0xd6, 0x15, 0xe2, 0x80, 0x57, +0x58, 0x40, 0x00, 0x00, 0x04, 0x11, 0x80, 0xd7, 0x14, 0x12, 0x00, 0x58, 0x04, 0x21, 0x80, 0xde, +0x14, 0x20, 0x00, 0x62, 0x46, 0x16, 0x02, 0x01, 0x04, 0x01, 0x80, 0xdf, 0x58, 0x10, 0x81, 0x8c, +0x14, 0x00, 0x80, 0x00, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x27, 0x8c, 0x05, +0x14, 0x2f, 0x80, 0x01, 0x4e, 0x03, 0x00, 0x2e, 0x47, 0xc6, 0x02, 0x00, 0x58, 0xae, 0x00, 0x00, +0x46, 0x96, 0x02, 0x04, 0x45, 0xe0, 0x02, 0x45, 0x46, 0x86, 0x02, 0x00, 0x46, 0x66, 0x02, 0x04, +0x46, 0x75, 0x57, 0x84, 0x46, 0x12, 0x00, 0xfc, 0x46, 0x35, 0x7c, 0x04, 0x15, 0xee, 0x00, 0x00, +0x58, 0x10, 0x80, 0x0c, 0x15, 0xe5, 0x00, 0x01, 0x58, 0x84, 0x03, 0x04, 0x14, 0x04, 0x80, 0x40, +0x58, 0x63, 0x04, 0x1c, 0x58, 0x73, 0x86, 0x88, 0x50, 0x54, 0x02, 0x10, 0x50, 0x42, 0x90, 0x00, +0x50, 0x23, 0x7f, 0xe8, 0x58, 0x31, 0x8e, 0x55, 0x44, 0x00, 0x00, 0x10, 0x48, 0x00, 0x00, 0x82, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x02, 0xc0, 0x4a, 0x46, 0x76, 0x02, 0x00, 0x58, 0x53, 0x80, 0x00, +0x44, 0x60, 0x02, 0x45, 0x14, 0x63, 0x80, 0x00, 0x14, 0x62, 0x80, 0x01, 0x4c, 0x10, 0x40, 0x0a, +0x46, 0x06, 0x02, 0x04, 0x46, 0x10, 0x10, 0x00, 0x58, 0x00, 0x01, 0x00, 0x48, 0x00, 0x00, 0x0c, +0x44, 0x00, 0x00, 0x03, 0x4c, 0x10, 0x40, 0x0a, 0x46, 0x06, 0x02, 0x04, 0x46, 0x10, 0x11, 0x00, +0x58, 0x00, 0x01, 0x00, 0x14, 0x10, 0x00, 0x00, 0x58, 0x72, 0x80, 0x00, 0x46, 0x36, 0x02, 0x04, +0x46, 0x65, 0x57, 0x84, 0x58, 0x22, 0x80, 0x00, 0x47, 0xc2, 0x00, 0xfc, 0x47, 0xe6, 0x02, 0x01, +0x58, 0x91, 0x80, 0x00, 0x46, 0xa5, 0x7c, 0x04, 0x59, 0xce, 0x00, 0x0c, 0x58, 0x63, 0x06, 0x88, +0x58, 0xa5, 0x0e, 0x55, 0x44, 0x80, 0x00, 0x10, 0x14, 0x83, 0x80, 0xc1, 0x14, 0x61, 0x81, 0x07, +0x15, 0xc1, 0x01, 0x45, 0x15, 0xcf, 0x01, 0x45, 0x14, 0xa4, 0x81, 0x01, 0x04, 0x1f, 0x80, 0x01, +0x4e, 0x12, 0x00, 0x96, 0x48, 0x00, 0x00, 0x82, 0x44, 0x50, 0x00, 0x05, 0x4c, 0x02, 0xc0, 0x42, +0x46, 0x06, 0x02, 0x00, 0x47, 0xe0, 0x00, 0x80, 0x59, 0xc0, 0x00, 0x00, 0x46, 0x96, 0x02, 0x04, +0x46, 0xa3, 0x10, 0x00, 0x59, 0xef, 0x02, 0x45, 0x15, 0xe0, 0x00, 0x00, 0x44, 0x00, 0x02, 0x45, +0x14, 0x0e, 0x00, 0x01, 0x46, 0x86, 0x02, 0x00, 0x46, 0x66, 0x02, 0x04, 0x46, 0x71, 0x55, 0x84, +0x46, 0x12, 0x00, 0xec, 0x46, 0x35, 0x7c, 0x06, 0x14, 0xa4, 0x80, 0x40, 0x58, 0x10, 0x80, 0x0c, +0x58, 0x84, 0x03, 0x04, 0x58, 0x63, 0x04, 0x1c, 0x58, 0x73, 0x86, 0x88, 0x50, 0x54, 0x02, 0x10, +0x50, 0x42, 0x90, 0x00, 0x50, 0x23, 0x7f, 0xe8, 0x58, 0x31, 0x8e, 0x55, 0x44, 0x00, 0x01, 0x10, +0x14, 0x04, 0x00, 0x00, 0x14, 0x73, 0x00, 0x00, 0x14, 0x12, 0x80, 0x00, 0x14, 0x12, 0x00, 0x00, +0x14, 0x31, 0x00, 0x00, 0x04, 0x4f, 0x80, 0x01, 0x4e, 0x42, 0x00, 0x52, 0x48, 0x00, 0x00, 0x3e, +0x44, 0x50, 0x00, 0x04, 0x4c, 0x02, 0xc0, 0x64, 0x47, 0xc6, 0x02, 0x00, 0x58, 0xae, 0x00, 0x00, +0x46, 0x86, 0x02, 0x04, 0x46, 0x92, 0x10, 0x00, 0x45, 0xe4, 0x02, 0x45, 0x15, 0xee, 0x00, 0x00, +0x58, 0x75, 0x00, 0x00, 0x58, 0x54, 0x00, 0x00, 0x46, 0x62, 0xab, 0x84, 0x58, 0x43, 0x80, 0x00, +0x46, 0x02, 0x00, 0xec, 0x46, 0x36, 0x02, 0x01, 0x58, 0x12, 0x80, 0x00, 0x46, 0x25, 0x7c, 0x06, +0x45, 0xc0, 0x02, 0x45, 0x15, 0xc5, 0x00, 0x01, 0x58, 0x00, 0x00, 0x0c, 0x14, 0x94, 0x00, 0x40, +0x58, 0x63, 0x06, 0x88, 0x58, 0x21, 0x0e, 0x55, 0x44, 0x80, 0x01, 0x10, 0x14, 0x83, 0x80, 0xc1, +0x14, 0x62, 0x81, 0x07, 0x14, 0x02, 0x01, 0x45, 0x14, 0x01, 0x81, 0x45, 0x14, 0x20, 0x81, 0x01, +0x04, 0x1f, 0x80, 0x01, 0x4e, 0x12, 0x00, 0x14, 0x46, 0x18, 0x24, 0x04, 0x46, 0x02, 0x10, 0x10, +0x46, 0x56, 0x02, 0x00, 0x46, 0x46, 0x02, 0x01, 0x58, 0x32, 0x80, 0x00, 0x58, 0x22, 0x00, 0x00, +0x58, 0x10, 0x81, 0xc0, 0x58, 0x00, 0x08, 0x00, 0x48, 0x00, 0x00, 0x12, 0x46, 0x10, 0x24, 0x04, +0x46, 0x02, 0x3f, 0x3f, 0x46, 0x56, 0x02, 0x00, 0x46, 0x46, 0x02, 0x01, 0x46, 0x36, 0x02, 0x00, +0x46, 0x26, 0x02, 0x01, 0x58, 0x10, 0x81, 0xc0, 0x58, 0x00, 0x08, 0x00, 0x14, 0x12, 0x83, 0x40, +0x14, 0x12, 0x03, 0x40, 0x14, 0x01, 0x83, 0x41, 0x14, 0x01, 0x03, 0x41, 0x51, 0xff, 0x80, 0x0c, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, 0x89, 0xb7, 0x54, 0x10, 0x00, 0x01, 0x4e, 0x12, 0x00, 0x3c, +0x54, 0x20, 0x00, 0x02, 0x4e, 0x22, 0x00, 0x38, 0x44, 0x10, 0x00, 0x00, 0x46, 0x70, 0x01, 0x0a, +0x58, 0x73, 0x84, 0xc8, 0x44, 0x00, 0x00, 0x1c, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x1e, 0x1f, 0xff, +0x58, 0x10, 0x8f, 0xff, 0x40, 0x60, 0x04, 0x02, 0x42, 0x13, 0x70, 0x08, 0x44, 0x00, 0x00, 0x1c, +0x46, 0x60, 0x01, 0x0a, 0x58, 0x63, 0x04, 0x8c, 0x44, 0x20, 0x00, 0x00, 0x4b, 0xe0, 0x18, 0x01, +0x46, 0xf0, 0x01, 0x0f, 0x04, 0x37, 0x83, 0x06, 0x44, 0x40, 0x00, 0x02, 0x4c, 0x32, 0x40, 0x14, +0x44, 0x10, 0x00, 0x00, 0x40, 0x02, 0x10, 0x08, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x2f, 0xff, 0x9f, +0x40, 0x00, 0x08, 0x02, 0x58, 0x10, 0x00, 0x40, 0x44, 0x20, 0x00, 0x00, 0x44, 0x00, 0x00, 0x20, +0x4b, 0xe0, 0x18, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x77, 0x8a, 0x1e, +0x46, 0x60, 0x01, 0x0a, 0x58, 0x63, 0x04, 0x8c, 0x4e, 0x72, 0x00, 0x16, 0x46, 0x10, 0x24, 0x44, +0x58, 0x10, 0x84, 0x0a, 0x44, 0x00, 0x06, 0x10, 0x44, 0x20, 0x00, 0x00, 0x4b, 0xe0, 0x18, 0x01, +0x46, 0x10, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, 0x44, 0x00, 0x00, 0x54, 0x44, 0x20, 0x00, 0x00, +0x48, 0x00, 0x00, 0x14, 0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x0a, 0x44, 0x00, 0x06, 0x10, +0x58, 0x23, 0x80, 0x00, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x18, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, +0x58, 0x23, 0x80, 0x00, 0x44, 0x00, 0x00, 0x54, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x17, 0x8a, 0x1f, 0x46, 0x60, 0x01, 0x0a, 0x58, 0x63, 0x04, 0x8c, 0x4e, 0x12, 0x00, 0x12, +0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x0a, 0x44, 0x00, 0x06, 0x10, 0x44, 0x20, 0x00, 0x01, +0x4b, 0xe0, 0x18, 0x01, 0x46, 0x10, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, 0x48, 0x00, 0x00, 0x10, +0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x0a, 0x44, 0x00, 0x06, 0x10, 0x44, 0x20, 0x00, 0x01, +0x4b, 0xe0, 0x18, 0x01, 0x46, 0x18, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, 0x44, 0x00, 0x00, 0x54, +0x44, 0x20, 0x00, 0x01, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x58, 0x00, 0x21, 0x46, 0x60, 0x0f, 0xb8, +0x58, 0x63, 0x09, 0xc1, 0x14, 0x62, 0x80, 0x91, 0x44, 0x00, 0x00, 0x30, 0x46, 0x60, 0x01, 0x0a, +0x58, 0x63, 0x04, 0xc8, 0x44, 0x10, 0x00, 0x00, 0x4b, 0xe0, 0x18, 0x01, 0x40, 0x30, 0x34, 0x08, +0x40, 0x31, 0xfc, 0x09, 0x4e, 0x32, 0x00, 0x1c, 0x44, 0x00, 0x00, 0x30, 0x44, 0x10, 0x00, 0x01, +0x4b, 0xe0, 0x18, 0x01, 0x40, 0x70, 0x34, 0x08, 0x40, 0x73, 0xfc, 0x09, 0x4e, 0x72, 0x00, 0x10, +0x47, 0xc8, 0x00, 0x23, 0x47, 0xe0, 0x01, 0x30, 0x46, 0x98, 0x00, 0x21, 0x59, 0xef, 0x05, 0x11, +0x44, 0xa0, 0x00, 0x36, 0x15, 0xee, 0x00, 0x1b, 0x14, 0xa4, 0x80, 0xce, 0x44, 0x90, 0x00, 0x00, +0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x84, 0x8c, 0x58, 0x64, 0x80, 0x00, 0x58, 0x83, 0x80, 0x00, +0x48, 0x00, 0x01, 0x18, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x47, 0x83, 0x04, 0x40, 0x12, 0x08, 0x08, +0x40, 0x35, 0x04, 0x00, 0x04, 0x11, 0x80, 0x01, 0x0c, 0x05, 0x00, 0x04, 0x4b, 0xe0, 0x1c, 0x01, +0x50, 0x0e, 0x00, 0x01, 0x41, 0xc0, 0x00, 0x13, 0x46, 0xf0, 0x01, 0x0f, 0x05, 0xe7, 0x83, 0x05, +0x58, 0x23, 0x00, 0x00, 0x40, 0xfe, 0x78, 0x06, 0x4e, 0xf3, 0xff, 0xe6, 0x58, 0x13, 0x00, 0x00, +0x44, 0x00, 0x06, 0x00, 0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0xc8, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x1f, 0xfc, 0x7f, 0x40, 0x30, 0x04, 0x02, 0x58, 0x11, 0x82, 0x80, 0x44, 0x00, 0x06, 0x00, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0x46, 0xa0, 0x13, 0x12, 0x46, 0xf0, 0x01, 0x0f, +0x04, 0x07, 0x83, 0x03, 0x58, 0x55, 0x0d, 0x00, 0x4c, 0x02, 0xc0, 0x06, 0x44, 0x90, 0x00, 0x14, +0x48, 0x00, 0x00, 0x2c, 0x46, 0x40, 0x17, 0xd7, 0x58, 0x52, 0x08, 0x40, 0x4c, 0x02, 0xc0, 0x06, +0x44, 0x90, 0x00, 0x1b, 0x48, 0x00, 0x00, 0x22, 0x46, 0x50, 0x26, 0x25, 0x58, 0x52, 0x8a, 0x00, +0x4c, 0x02, 0xc0, 0x06, 0x44, 0x90, 0x00, 0x28, 0x48, 0x00, 0x00, 0x18, 0x46, 0xf0, 0x01, 0x16, +0x01, 0xe7, 0x8f, 0x29, 0x4f, 0xe3, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x0e, 0x3c, +0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x86, 0x78, 0x44, 0x20, 0x1a, 0x03, 0x46, 0xf0, 0x01, 0x00, +0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x00, 0x58, +0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0xc8, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x1f, 0x00, 0xff, +0x40, 0x40, 0x04, 0x02, 0x40, 0x34, 0xa0, 0x08, 0x44, 0x00, 0x00, 0x58, 0x40, 0x11, 0x90, 0x04, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0xa7, 0x8c, 0x07, +0x4e, 0xa3, 0x00, 0x48, 0x46, 0xa0, 0x01, 0x0f, 0x58, 0xa5, 0x01, 0x48, 0x02, 0x05, 0x00, 0x00, +0x04, 0x15, 0x00, 0x01, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x50, 0xa5, 0x00, 0x08, +0x46, 0x50, 0x01, 0x0f, 0x58, 0x52, 0x81, 0xa0, 0x4c, 0xa2, 0xff, 0xf2, 0x4e, 0x63, 0x00, 0x18, +0x46, 0x17, 0xf1, 0x71, 0x58, 0x23, 0x00, 0x00, 0x58, 0x10, 0x8d, 0x11, 0x44, 0x00, 0x00, 0xdc, +0x4b, 0xe0, 0x20, 0x01, 0x46, 0x13, 0xb1, 0x07, 0x58, 0x10, 0x8f, 0x15, 0x44, 0x00, 0x00, 0xe0, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0x48, 0x00, 0x00, 0x32, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x62, 0xc0, 0x5c, 0x46, 0x13, 0xf1, 0x71, 0x58, 0x23, 0x00, 0x00, 0x58, 0x10, 0x8d, 0x11, +0x44, 0x00, 0x00, 0xdc, 0x4b, 0xe0, 0x20, 0x01, 0x46, 0x13, 0xb1, 0x07, 0x58, 0x10, 0x8f, 0x15, +0x44, 0x00, 0x00, 0xe0, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0x48, 0x00, 0x00, 0x32, +0x46, 0xa0, 0x01, 0x0f, 0x58, 0xa5, 0x01, 0xa0, 0x02, 0x05, 0x00, 0x00, 0x04, 0x15, 0x00, 0x01, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x50, 0xa5, 0x00, 0x08, 0x46, 0x50, 0x01, 0x0f, +0x58, 0x52, 0x82, 0x08, 0x4c, 0xa2, 0xff, 0xf2, 0x4e, 0x63, 0x00, 0x18, 0x46, 0xa0, 0x01, 0x0f, +0x58, 0xa5, 0x02, 0x08, 0x02, 0x05, 0x00, 0x00, 0x04, 0x15, 0x00, 0x01, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x50, 0xa5, 0x00, 0x08, 0x46, 0x50, 0x01, 0x0f, 0x58, 0x52, 0x82, 0x78, +0x4c, 0xa2, 0xff, 0xf2, 0x48, 0x00, 0x00, 0x1a, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x16, +0x46, 0xa0, 0x01, 0x0f, 0x58, 0xa5, 0x02, 0x78, 0x02, 0x05, 0x00, 0x00, 0x04, 0x15, 0x00, 0x01, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x50, 0xa5, 0x00, 0x08, 0x46, 0x50, 0x01, 0x0f, +0x58, 0x52, 0x82, 0xe8, 0x4c, 0xa2, 0xff, 0xf2, 0x50, 0x63, 0x00, 0x01, 0x40, 0x63, 0x00, 0x13, +0x46, 0xf0, 0x01, 0x0f, 0x04, 0x47, 0x83, 0x06, 0x40, 0xf3, 0x10, 0x06, 0x4e, 0xf2, 0x00, 0x0a, +0x45, 0xc0, 0x00, 0x00, 0x46, 0xa0, 0x01, 0x0f, 0x58, 0xa5, 0x00, 0xd8, 0x48, 0xff, 0xfe, 0xee, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x17, 0x8c, 0x04, 0x50, 0x80, 0xff, 0xff, 0x54, 0x74, 0x00, 0xff, +0x5c, 0xf3, 0x80, 0x04, 0x4e, 0xf3, 0x00, 0x12, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x57, 0x8f, 0x29, +0x4e, 0x53, 0x00, 0x0c, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x0e, 0x60, 0x46, 0xf0, 0x01, 0x00, +0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x70, 0x01, 0x0f, 0x58, 0x73, 0x85, 0x28, +0x44, 0x60, 0x00, 0x00, 0x44, 0x90, 0x00, 0x06, 0x46, 0x80, 0x01, 0x0a, 0x58, 0x84, 0x04, 0x8c, +0x46, 0xf0, 0x01, 0x0f, 0x01, 0xe7, 0x8c, 0x04, 0x46, 0x30, 0x01, 0x0f, 0x58, 0x31, 0x85, 0x28, +0x43, 0xe3, 0x24, 0x73, 0x04, 0x23, 0x80, 0x05, 0x50, 0x5f, 0x7f, 0xff, 0x40, 0x12, 0x88, 0x08, +0x40, 0x40, 0x8c, 0x00, 0x04, 0x03, 0x80, 0x00, 0x04, 0x12, 0x00, 0x01, 0x50, 0x63, 0x00, 0x01, +0x4b, 0xe0, 0x20, 0x01, 0x44, 0x50, 0x00, 0x0e, 0x50, 0x73, 0x80, 0x18, 0x4c, 0x62, 0xff, 0xe2, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xdc, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x37, 0x8c, 0x07, 0x14, 0x0f, 0x80, 0x01, +0x44, 0x00, 0x00, 0x01, 0x4c, 0x30, 0x03, 0xdc, 0x04, 0x2f, 0x80, 0x01, 0x46, 0x18, 0x1b, 0xce, +0x46, 0x90, 0x01, 0x0a, 0x58, 0x94, 0x84, 0x8c, 0x58, 0x10, 0x8c, 0x3f, 0x44, 0x00, 0x00, 0x6c, +0x4b, 0xe0, 0x24, 0x01, 0x04, 0x2f, 0x80, 0x01, 0x46, 0x1f, 0xcb, 0x00, 0x58, 0x10, 0x87, 0x27, +0x44, 0x00, 0x00, 0x48, 0x4b, 0xe0, 0x24, 0x01, 0x04, 0x1f, 0x80, 0x01, 0x44, 0x00, 0x00, 0x54, +0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0xc8, 0x4b, 0xe0, 0x3c, 0x01, 0x42, 0xa0, 0x74, 0x09, +0x42, 0xa5, 0x78, 0x09, 0x04, 0x2f, 0x80, 0x01, 0x42, 0x15, 0x78, 0x08, 0x44, 0x00, 0x00, 0x54, +0x4b, 0xe0, 0x24, 0x01, 0x04, 0x2f, 0x80, 0x01, 0x46, 0x10, 0x5a, 0x00, 0x58, 0x10, 0x8f, 0x8b, +0x44, 0x00, 0x00, 0x70, 0x4b, 0xe0, 0x24, 0x01, 0x04, 0x2f, 0x80, 0x01, 0x46, 0x19, 0x00, 0x00, +0x44, 0x00, 0x00, 0xa0, 0x4b, 0xe0, 0x24, 0x01, 0x46, 0x86, 0x02, 0x00, 0x58, 0x54, 0x00, 0x00, +0x58, 0x72, 0x80, 0x00, 0x44, 0x60, 0x00, 0xa7, 0x44, 0x40, 0x00, 0x02, 0x14, 0x62, 0x80, 0x00, +0x14, 0x64, 0x00, 0x01, 0x14, 0x43, 0x80, 0x83, 0x04, 0x2f, 0x80, 0x01, 0x4e, 0x23, 0x00, 0x32, +0x58, 0xa2, 0x80, 0x00, 0x47, 0xc0, 0x40, 0x00, 0x58, 0x82, 0x80, 0x00, 0x46, 0x90, 0x02, 0x74, +0x58, 0x62, 0x80, 0x00, 0x47, 0xec, 0x00, 0x00, 0x46, 0x56, 0x02, 0x04, 0x58, 0x23, 0x00, 0x00, +0x46, 0x44, 0x0c, 0x00, 0x59, 0xef, 0x04, 0x00, 0x58, 0x94, 0x80, 0x27, 0x44, 0x70, 0x05, 0x9f, +0x15, 0xc5, 0x00, 0x80, 0x14, 0x94, 0x03, 0x40, 0x15, 0xe3, 0x03, 0x41, 0x14, 0x72, 0x80, 0x85, +0x14, 0x41, 0x03, 0x49, 0x58, 0x11, 0x00, 0x00, 0x04, 0x01, 0x03, 0x49, 0x46, 0x3a, 0x30, 0x00, +0x47, 0xe0, 0xff, 0x00, 0x14, 0x30, 0x82, 0x82, 0x41, 0xc0, 0x78, 0x02, 0x48, 0x00, 0x00, 0x3a, +0x04, 0x3f, 0x80, 0x01, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x32, 0x80, 0x06, 0x45, 0xc0, 0x00, 0x00, +0x48, 0x00, 0x00, 0x30, 0x46, 0xa6, 0x02, 0x00, 0x47, 0xc1, 0x40, 0x00, 0x46, 0x86, 0x02, 0x01, +0x46, 0x90, 0x02, 0x74, 0x58, 0x64, 0x00, 0x00, 0x46, 0x1c, 0x00, 0x00, 0x46, 0x36, 0x02, 0x05, +0x59, 0xe3, 0x00, 0x00, 0x46, 0x04, 0x0c, 0x00, 0x58, 0x10, 0x84, 0x00, 0x58, 0x94, 0x80, 0x27, +0x44, 0x70, 0x05, 0x9f, 0x15, 0xc5, 0x00, 0x80, 0x14, 0x94, 0x03, 0x40, 0x14, 0x13, 0x03, 0x41, +0x14, 0x71, 0x80, 0x85, 0x14, 0x0f, 0x03, 0x49, 0x58, 0x43, 0x00, 0x00, 0x46, 0x5a, 0x30, 0x00, +0x04, 0x2f, 0x03, 0x49, 0x46, 0x10, 0xff, 0x00, 0x14, 0x52, 0x02, 0x82, 0x41, 0xc1, 0x04, 0x02, +0x46, 0x96, 0x02, 0x00, 0x14, 0x9f, 0x80, 0x02, 0x46, 0x06, 0x02, 0x04, 0x04, 0x4f, 0x80, 0x02, +0x58, 0x42, 0x03, 0x00, 0x14, 0x4f, 0x80, 0x02, 0x58, 0x34, 0x80, 0x00, 0x44, 0x40, 0x00, 0x03, +0x14, 0x40, 0x00, 0x50, 0x50, 0x42, 0x00, 0x0d, 0x14, 0x41, 0x80, 0xe0, 0x58, 0xa0, 0x00, 0x00, +0x04, 0x0f, 0x80, 0x02, 0x47, 0xe0, 0x10, 0x00, 0x58, 0x91, 0x80, 0x00, 0x58, 0x71, 0x80, 0x00, +0x46, 0x82, 0x03, 0xf0, 0x58, 0x55, 0x00, 0x00, 0x46, 0x60, 0x60, 0x70, 0x58, 0x11, 0x80, 0x00, +0x46, 0x20, 0x00, 0x80, 0x58, 0x84, 0x06, 0x06, 0x58, 0x21, 0x07, 0x01, 0x44, 0x31, 0x00, 0x68, +0x44, 0x40, 0x00, 0x06, 0x14, 0x30, 0x00, 0x00, 0x15, 0xe5, 0x00, 0x40, 0x14, 0x44, 0x82, 0x44, +0x14, 0x83, 0x82, 0x43, 0x14, 0x62, 0x80, 0x08, 0x58, 0x70, 0x80, 0x00, 0x14, 0x20, 0x82, 0x40, +0x44, 0x60, 0x00, 0x00, 0x46, 0x80, 0x01, 0x03, 0x58, 0x84, 0x00, 0x84, 0x44, 0x00, 0x00, 0x01, +0x4b, 0xe0, 0x20, 0x01, 0x04, 0x53, 0x82, 0x6c, 0x42, 0x22, 0xf4, 0x0b, 0x4e, 0x23, 0x00, 0x20, +0x44, 0x50, 0x27, 0x11, 0x4c, 0x62, 0x80, 0x06, 0x50, 0x63, 0x00, 0x01, 0x48, 0xff, 0xff, 0xf0, +0x46, 0xf0, 0x01, 0x16, 0x00, 0x67, 0x8f, 0x29, 0x4e, 0x63, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x0e, 0x3c, 0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x86, 0x8c, 0x44, 0x20, 0x13, 0x94, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x66, 0x02, 0x00, +0x46, 0x30, 0x00, 0x80, 0x58, 0x31, 0x87, 0x00, 0x58, 0x23, 0x00, 0x00, 0x46, 0x06, 0x02, 0x04, +0x46, 0x82, 0xf1, 0xe2, 0x14, 0x33, 0x02, 0x40, 0x44, 0x61, 0x00, 0x06, 0x14, 0x61, 0x02, 0x44, +0x14, 0x80, 0x00, 0x9b, 0x46, 0x10, 0x01, 0x12, 0x58, 0x10, 0x8c, 0x70, 0x04, 0x0f, 0x80, 0x01, +0x46, 0x46, 0x02, 0x01, 0x41, 0xe0, 0x04, 0x00, 0x58, 0x42, 0x09, 0xac, 0x50, 0x52, 0x70, 0x00, +0x50, 0x3f, 0x03, 0x98, 0x50, 0x22, 0x80, 0x04, 0x44, 0x80, 0x00, 0x00, 0x44, 0x70, 0x00, 0x00, +0x14, 0x4f, 0x80, 0x04, 0x14, 0x5f, 0x80, 0x05, 0x14, 0x3f, 0x80, 0x07, 0x14, 0x2f, 0x80, 0x06, +0x14, 0x7f, 0x80, 0x02, 0x14, 0x8f, 0x80, 0x03, 0x58, 0x74, 0x00, 0x00, 0x41, 0xce, 0x50, 0x09, +0x58, 0x80, 0x00, 0x00, 0x4e, 0x83, 0x00, 0x10, 0x04, 0x4f, 0x80, 0x05, 0x46, 0x50, 0x0f, 0xf0, +0x04, 0x12, 0x00, 0x00, 0x05, 0xe2, 0x00, 0x00, 0x54, 0x70, 0x80, 0xff, 0x40, 0x0f, 0x14, 0x02, +0x48, 0x00, 0x00, 0x12, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x82, 0xc0, 0x12, 0x04, 0x7f, 0x80, 0x04, +0x46, 0x20, 0x0f, 0xf0, 0x04, 0x33, 0x80, 0x00, 0x05, 0xe3, 0x80, 0x00, 0x54, 0x71, 0x80, 0xff, +0x40, 0x0f, 0x08, 0x02, 0x40, 0x50, 0x40, 0x09, 0x14, 0x5f, 0x80, 0x03, 0x5c, 0xf3, 0x80, 0x41, +0x4e, 0xf3, 0x00, 0x06, 0x51, 0xce, 0x00, 0x0a, 0x48, 0x00, 0x00, 0xaa, 0x5c, 0xf3, 0x80, 0x08, +0x4e, 0xf2, 0x00, 0x06, 0x51, 0xce, 0x00, 0x08, 0x48, 0x00, 0x00, 0xa2, 0x5c, 0xf3, 0x80, 0x10, +0x4e, 0xf2, 0x00, 0x06, 0x51, 0xce, 0x00, 0x06, 0x48, 0x00, 0x00, 0x9a, 0x5c, 0xf3, 0x80, 0x20, +0x4e, 0xf2, 0x00, 0x06, 0x51, 0xce, 0x00, 0x04, 0x48, 0x00, 0x00, 0x92, 0x5c, 0xf3, 0x80, 0x30, +0x4e, 0xf2, 0x00, 0x06, 0x51, 0xce, 0x00, 0x02, 0x48, 0x00, 0x00, 0x8a, 0x4e, 0x83, 0x00, 0x22, +0x46, 0x16, 0x02, 0x00, 0x58, 0x10, 0x89, 0xac, 0x58, 0x04, 0x00, 0x00, 0x04, 0x20, 0x80, 0x00, +0x50, 0x30, 0x00, 0x01, 0x54, 0x71, 0x00, 0xff, 0x51, 0xe3, 0xff, 0xd0, 0x54, 0x4f, 0x00, 0xff, +0x50, 0x10, 0xff, 0xfc, 0x5c, 0xf2, 0x00, 0x10, 0x4e, 0xf2, 0x00, 0x04, 0x54, 0x01, 0x80, 0xff, +0x46, 0x36, 0x02, 0x00, 0x58, 0x51, 0x89, 0x6c, 0x4c, 0x12, 0xff, 0xea, 0x48, 0x00, 0x00, 0x24, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x82, 0xc0, 0x24, 0x46, 0x16, 0x02, 0x01, 0x58, 0x10, 0x89, 0xac, +0x44, 0x00, 0x00, 0x00, 0x04, 0x70, 0x80, 0x00, 0x50, 0x30, 0x00, 0x01, 0x54, 0x73, 0x80, 0xff, +0x50, 0x43, 0xff, 0xd0, 0x54, 0x52, 0x00, 0xff, 0x50, 0x10, 0xff, 0xfc, 0x5c, 0xf2, 0x80, 0x10, +0x4e, 0xf2, 0x00, 0x04, 0x54, 0x01, 0x80, 0xff, 0x47, 0xe6, 0x02, 0x01, 0x59, 0xef, 0x09, 0x6c, +0x4c, 0x1f, 0x7f, 0xea, 0x5c, 0xf0, 0x00, 0x03, 0x4e, 0xf2, 0x00, 0x10, 0x04, 0x3f, 0x80, 0x03, +0x44, 0x00, 0x00, 0x7f, 0x4c, 0x30, 0x00, 0x3e, 0x50, 0x50, 0x00, 0x01, 0x4c, 0x32, 0x80, 0x3a, +0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x38, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0xc0, 0x06, +0x51, 0xce, 0x7f, 0xfe, 0x48, 0x00, 0x00, 0x2c, 0x44, 0x10, 0x00, 0x04, 0x4c, 0x00, 0xc0, 0x06, +0x51, 0xce, 0x7f, 0xfc, 0x48, 0x00, 0x00, 0x24, 0x44, 0x50, 0x00, 0x05, 0x4c, 0x02, 0xc0, 0x06, +0x51, 0xce, 0x7f, 0xf8, 0x48, 0x00, 0x00, 0x1c, 0x44, 0x50, 0x00, 0x06, 0x4c, 0x02, 0xc0, 0x06, +0x51, 0xce, 0x7f, 0xf4, 0x48, 0x00, 0x00, 0x14, 0x44, 0x50, 0x00, 0x07, 0x4c, 0x02, 0xc0, 0x06, +0x51, 0xce, 0x7f, 0xf0, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x08, 0x4c, 0x02, 0xc0, 0x06, +0x51, 0xce, 0x7f, 0xec, 0x48, 0x00, 0x00, 0x04, 0x51, 0xce, 0x7f, 0xe8, 0x55, 0xce, 0x00, 0xff, +0x44, 0x00, 0x00, 0x00, 0x04, 0x1f, 0x80, 0x07, 0x50, 0x3e, 0x00, 0x12, 0x10, 0x30, 0x80, 0x00, +0x4e, 0x03, 0x00, 0xbe, 0x4e, 0x83, 0x00, 0x0c, 0x40, 0xae, 0x50, 0x08, 0x46, 0x06, 0x02, 0x00, +0x42, 0x15, 0x78, 0x08, 0x58, 0x00, 0x0d, 0x24, 0x48, 0x00, 0x00, 0x0e, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x82, 0xc0, 0x0c, 0x40, 0x6e, 0x50, 0x08, 0x46, 0x06, 0x02, 0x01, 0x42, 0x13, 0x78, 0x08, +0x58, 0x00, 0x0d, 0x24, 0x14, 0x10, 0x00, 0x00, 0x05, 0xef, 0x80, 0x03, 0x46, 0x16, 0x02, 0x04, +0x46, 0x56, 0x02, 0x00, 0x44, 0x00, 0x00, 0x03, 0x58, 0x92, 0x80, 0x00, 0x58, 0xa0, 0x80, 0x00, +0x46, 0x60, 0x10, 0x00, 0x58, 0x42, 0x80, 0x00, 0x50, 0x2f, 0x7f, 0x81, 0x44, 0x30, 0x00, 0x10, +0x14, 0x00, 0x80, 0x50, 0x14, 0x32, 0x80, 0xe0, 0x44, 0x51, 0x00, 0x68, 0x44, 0x00, 0x00, 0x06, +0x55, 0xe1, 0x00, 0xff, 0x14, 0x54, 0x80, 0xc0, 0x14, 0x65, 0x00, 0x40, 0x14, 0x02, 0x02, 0x44, +0x5c, 0xff, 0x00, 0x02, 0x4e, 0xf3, 0x00, 0x0c, 0x46, 0x06, 0x02, 0x00, 0x46, 0x12, 0x03, 0xf0, +0x58, 0x00, 0x09, 0x0c, 0x58, 0x10, 0x86, 0x06, 0x48, 0x00, 0x00, 0x0a, 0x46, 0x06, 0x02, 0x00, +0x46, 0x11, 0x03, 0xf0, 0x58, 0x00, 0x09, 0x0c, 0x58, 0x10, 0x86, 0x06, 0x58, 0x55, 0x00, 0x00, +0x46, 0x60, 0x60, 0x70, 0x58, 0x32, 0x00, 0x00, 0x46, 0x40, 0x00, 0x80, 0x58, 0x42, 0x07, 0x01, +0x14, 0x10, 0x00, 0x00, 0x14, 0x62, 0x80, 0x08, 0x14, 0x41, 0x82, 0x40, 0x44, 0x60, 0x00, 0x00, +0x44, 0x00, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x80, 0x84, 0x4b, 0xe0, 0x3c, 0x01, +0x04, 0x3f, 0x80, 0x06, 0x04, 0x01, 0x80, 0x00, 0x42, 0x10, 0x74, 0x0b, 0x4e, 0x13, 0x00, 0x20, +0x44, 0x50, 0x27, 0x11, 0x4c, 0x62, 0x80, 0x06, 0x50, 0x63, 0x00, 0x01, 0x48, 0xff, 0xff, 0xea, +0x46, 0xf0, 0x01, 0x16, 0x00, 0x47, 0x8f, 0x29, 0x4e, 0x43, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x0e, 0x3c, 0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x86, 0x8c, 0x44, 0x20, 0x14, 0x4a, +0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x6f, 0x80, 0x02, +0x47, 0xe6, 0x02, 0x00, 0x50, 0x23, 0x00, 0x01, 0x46, 0x00, 0x00, 0x80, 0x58, 0x6f, 0x00, 0x00, +0x46, 0x56, 0x02, 0x04, 0x46, 0x42, 0xf1, 0xe2, 0x54, 0x11, 0x00, 0xff, 0x58, 0x00, 0x07, 0x00, +0x44, 0x31, 0x00, 0x06, 0x44, 0x26, 0x07, 0x00, 0x14, 0x1f, 0x80, 0x02, 0x14, 0x0f, 0x02, 0x40, +0x14, 0x33, 0x02, 0x44, 0x14, 0x42, 0x80, 0x9b, 0x14, 0x2f, 0x02, 0x40, 0x44, 0x10, 0x00, 0x04, +0x04, 0x0f, 0x80, 0x02, 0x4c, 0x00, 0xfe, 0x68, 0x48, 0x00, 0x00, 0xce, 0x46, 0x46, 0x02, 0x00, +0x05, 0xe2, 0x02, 0x44, 0x04, 0x2f, 0x80, 0x01, 0x54, 0x4f, 0x00, 0x0f, 0x4e, 0x23, 0x00, 0x3e, +0x46, 0x31, 0x80, 0x80, 0x58, 0x31, 0x82, 0x48, 0x40, 0x52, 0x0c, 0x00, 0x46, 0x36, 0x02, 0x00, +0x40, 0x52, 0x88, 0x08, 0x58, 0x31, 0x89, 0x20, 0x05, 0xe1, 0x80, 0x00, 0x46, 0x10, 0x0f, 0xf0, +0x40, 0x0f, 0x04, 0x02, 0x46, 0x10, 0x07, 0xf0, 0x4c, 0x00, 0x80, 0x0c, 0x04, 0x01, 0x80, 0x00, +0x46, 0x10, 0x0f, 0xf0, 0x47, 0xe0, 0x08, 0x00, 0x40, 0x00, 0x04, 0x02, 0x4c, 0x0f, 0x40, 0x0c, +0x04, 0x01, 0x80, 0x00, 0x46, 0x1f, 0xf0, 0x0f, 0x58, 0x10, 0x8f, 0xff, 0x41, 0xe0, 0x04, 0x02, +0x15, 0xe1, 0x80, 0x00, 0x40, 0xf1, 0x10, 0x06, 0x4e, 0xf2, 0x00, 0x06, 0x05, 0xe2, 0x80, 0x00, +0x15, 0xe1, 0x80, 0x00, 0x50, 0x21, 0x00, 0x01, 0x44, 0x00, 0x00, 0x10, 0x50, 0x31, 0x80, 0x04, +0x4c, 0x20, 0x7f, 0xd4, 0x48, 0x00, 0x00, 0x46, 0x04, 0x5f, 0x80, 0x01, 0x44, 0x20, 0x00, 0x01, +0x4c, 0x51, 0x40, 0x7a, 0x46, 0x31, 0x80, 0x80, 0x58, 0x31, 0x86, 0x48, 0x40, 0x12, 0x0c, 0x00, +0x46, 0x06, 0x02, 0x01, 0x40, 0x20, 0x88, 0x08, 0x58, 0x00, 0x09, 0x20, 0x44, 0x10, 0x00, 0x00, +0x04, 0x30, 0x00, 0x00, 0x46, 0x50, 0x0f, 0xf0, 0x41, 0xe1, 0x94, 0x02, 0x46, 0x50, 0x07, 0xf0, +0x4d, 0xe2, 0x80, 0x0c, 0x04, 0x30, 0x00, 0x00, 0x46, 0x50, 0x0f, 0xf0, 0x41, 0xe1, 0x94, 0x02, +0x46, 0x50, 0x08, 0x00, 0x4d, 0xe2, 0xc0, 0x0c, 0x04, 0x30, 0x00, 0x00, 0x46, 0x5f, 0xf0, 0x0f, +0x58, 0x52, 0x8f, 0xff, 0x41, 0xe1, 0x94, 0x02, 0x15, 0xe0, 0x00, 0x00, 0x40, 0xf0, 0x90, 0x06, +0x4e, 0xf2, 0x00, 0x06, 0x05, 0xe1, 0x00, 0x00, 0x15, 0xe0, 0x00, 0x00, 0x50, 0x10, 0x80, 0x01, +0x44, 0x50, 0x00, 0x10, 0x50, 0x00, 0x00, 0x04, 0x4c, 0x12, 0xff, 0xd4, 0x48, 0x00, 0x00, 0x20, +0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x09, 0x20, 0x46, 0x30, 0x01, 0x12, 0x58, 0x31, 0x8c, 0x70, +0x46, 0x59, 0xfd, 0xff, 0x04, 0x20, 0x00, 0x00, 0x41, 0xe0, 0x0c, 0x00, 0x58, 0x52, 0x89, 0x10, +0x46, 0x46, 0x02, 0x00, 0x40, 0x1f, 0x14, 0x00, 0x50, 0x00, 0x00, 0x04, 0x58, 0x42, 0x09, 0x60, +0x14, 0x20, 0x80, 0x00, 0x4c, 0x02, 0x7f, 0xea, 0x48, 0x00, 0x00, 0x1e, 0x46, 0x06, 0x02, 0x01, +0x58, 0x00, 0x09, 0x20, 0x46, 0x30, 0x01, 0x12, 0x58, 0x31, 0x8c, 0x70, 0x46, 0x59, 0xfd, 0xfe, +0x04, 0x20, 0x00, 0x00, 0x41, 0xe0, 0x0c, 0x00, 0x58, 0x52, 0x89, 0x50, 0x46, 0x46, 0x02, 0x01, +0x40, 0x1f, 0x14, 0x00, 0x50, 0x00, 0x00, 0x04, 0x58, 0x42, 0x09, 0x60, 0x14, 0x20, 0x80, 0x00, +0x4c, 0x02, 0x7f, 0xea, 0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x85, 0xec, 0x4b, 0xe0, 0x3c, 0x01, +0x48, 0x00, 0x00, 0x0e, 0x58, 0x13, 0x00, 0x00, 0x46, 0x0f, 0x00, 0x00, 0x46, 0x46, 0x02, 0x01, +0x14, 0x00, 0x82, 0x82, 0x14, 0x02, 0x02, 0x82, 0x48, 0xff, 0xff, 0x2a, 0x51, 0xff, 0x80, 0x24, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, 0x46, 0x18, 0x18, 0x00, +0x46, 0x60, 0x01, 0x0a, 0x58, 0x63, 0x04, 0x8c, 0x44, 0x20, 0x00, 0x00, 0x58, 0x10, 0x80, 0x07, +0x44, 0x00, 0x00, 0x6c, 0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x84, 0xc8, 0x4b, 0xe0, 0x18, 0x01, +0x44, 0x10, 0x00, 0x00, 0x44, 0x00, 0x06, 0x10, 0x4b, 0xe0, 0x1c, 0x01, 0x42, 0x10, 0x5c, 0x08, +0x44, 0x20, 0x00, 0x00, 0x44, 0x00, 0x06, 0x10, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x10, 0x00, 0x00, +0x44, 0x00, 0x00, 0xe4, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x17, 0x83, 0x04, +0x44, 0x80, 0x00, 0x0c, 0x42, 0x30, 0xa0, 0x24, 0x46, 0x20, 0x01, 0x0e, 0x58, 0x21, 0x0e, 0xd4, +0x40, 0x51, 0x88, 0x00, 0x40, 0x00, 0x28, 0x08, 0x40, 0x00, 0x28, 0x09, 0x04, 0x42, 0x80, 0x02, +0x44, 0x20, 0x00, 0x00, 0x40, 0x12, 0x58, 0x08, 0x40, 0x10, 0x04, 0x04, 0x44, 0x00, 0x00, 0xe4, +0x4b, 0xe0, 0x18, 0x01, 0x44, 0x10, 0x00, 0x00, 0x44, 0x00, 0x00, 0x70, 0x4b, 0xe0, 0x1c, 0x01, +0x42, 0x10, 0x7c, 0x08, 0x44, 0x20, 0x00, 0x00, 0x44, 0x00, 0x00, 0x70, 0x4b, 0xe0, 0x18, 0x01, +0x58, 0x04, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x80, 0x84, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x10, 0x00, 0x00, 0x44, 0x00, 0x00, 0x70, 0x4b, 0xe0, 0x1c, 0x01, 0x42, 0x10, 0x7c, 0x09, +0x44, 0x20, 0x00, 0x00, 0x44, 0x00, 0x00, 0x70, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x10, 0x00, 0x00, +0x58, 0x20, 0x80, 0x00, 0x44, 0x00, 0x00, 0x6c, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x10, 0x00, 0x00, +0x44, 0x00, 0x08, 0x34, 0x4b, 0xe0, 0x1c, 0x01, 0x40, 0x80, 0x1c, 0x08, 0x40, 0x44, 0x6c, 0x09, +0x46, 0xf0, 0x01, 0x12, 0x14, 0x47, 0x83, 0x8a, 0x44, 0x10, 0x00, 0x01, 0x44, 0x00, 0x00, 0xe4, +0x4b, 0xe0, 0x1c, 0x01, 0x42, 0x10, 0x54, 0x08, 0x44, 0x20, 0x00, 0x01, 0x44, 0x00, 0x00, 0xe4, +0x4b, 0xe0, 0x18, 0x01, 0x44, 0x10, 0x00, 0x01, 0x44, 0x00, 0x00, 0xe4, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0xf0, 0x01, 0x12, 0x04, 0x37, 0x83, 0x8a, 0x44, 0x2f, 0x07, 0xff, 0x40, 0x11, 0xac, 0x08, +0x40, 0x50, 0x80, 0x13, 0x40, 0x00, 0x08, 0x02, 0x40, 0x10, 0x14, 0x04, 0x44, 0x20, 0x00, 0x01, +0x44, 0x00, 0x00, 0xe4, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x10, 0x00, 0x01, 0x44, 0x00, 0x00, 0xe4, +0x4b, 0xe0, 0x1c, 0x01, 0x42, 0x10, 0x28, 0x09, 0x44, 0x20, 0x00, 0x01, 0x44, 0x00, 0x00, 0xe4, +0x4b, 0xe0, 0x18, 0x01, 0x44, 0x10, 0x00, 0x01, 0x44, 0x00, 0x00, 0xe4, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0xf0, 0x01, 0x12, 0x04, 0x37, 0x83, 0x8a, 0x40, 0x00, 0x14, 0x09, 0x40, 0x00, 0x14, 0x08, +0x54, 0x11, 0x80, 0x1f, 0x40, 0x10, 0x04, 0x04, 0x44, 0x20, 0x00, 0x01, 0x44, 0x00, 0x00, 0xe4, +0x4b, 0xe0, 0x18, 0x01, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3b, 0xff, 0xfc, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x4e, 0x03, 0x00, 0x08, 0x46, 0xf0, 0x01, 0x0b, 0x58, 0xf7, 0x8a, 0x88, +0x4b, 0xe0, 0x3c, 0x01, 0x51, 0xff, 0x80, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xa8, 0xbc, 0x58, 0x60, 0x00, 0x00, 0x58, 0x71, 0x00, 0x00, 0x4e, 0x13, 0x00, 0x1a, +0x46, 0x00, 0x01, 0x0f, 0x58, 0x00, 0x02, 0xe8, 0x38, 0x10, 0x0b, 0x02, 0x46, 0x80, 0x01, 0x0a, +0x58, 0x84, 0x04, 0x8c, 0x44, 0x00, 0x00, 0xa0, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x20, 0x01, +0x40, 0x03, 0x8c, 0x08, 0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x82, 0xe8, 0x48, 0x00, 0x00, 0x1c, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x12, 0xc0, 0x22, 0x46, 0x30, 0x01, 0x0f, 0x58, 0x31, 0x83, 0x68, +0x38, 0x11, 0x9f, 0x02, 0x44, 0x00, 0x00, 0xa0, 0x58, 0x23, 0x00, 0x00, 0x46, 0x80, 0x01, 0x0a, +0x58, 0x84, 0x04, 0x8c, 0x4b, 0xe0, 0x20, 0x01, 0x40, 0x03, 0x8c, 0x08, 0x46, 0x10, 0x01, 0x0f, +0x58, 0x10, 0x83, 0x68, 0x40, 0x40, 0x04, 0x00, 0x04, 0x12, 0x00, 0x01, 0x44, 0x00, 0x00, 0x70, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x20, 0x01, 0x46, 0x18, 0x20, 0x24, 0x58, 0x10, 0x80, 0xc0, +0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0x8c, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xa0, 0x01, 0x03, 0x58, 0xa5, 0x00, 0x84, 0x46, 0x80, 0x01, 0x0a, +0x58, 0x84, 0x04, 0xc8, 0x44, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x28, 0x01, 0x58, 0x13, 0x00, 0x00, +0x44, 0x00, 0x04, 0x1c, 0x4b, 0xe0, 0x20, 0x01, 0x40, 0x50, 0x70, 0x09, 0x46, 0x90, 0x01, 0x0a, +0x58, 0x94, 0x84, 0xc8, 0x4e, 0x53, 0xff, 0xf0, 0x46, 0x10, 0x20, 0x04, 0x58, 0x10, 0x80, 0xc0, +0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, 0x46, 0x80, 0x01, 0x0a, 0x58, 0x84, 0x04, 0x8c, +0x4b, 0xe0, 0x20, 0x01, 0x44, 0x00, 0x04, 0x68, 0x58, 0x13, 0x00, 0x00, 0x4b, 0xe0, 0x24, 0x01, +0x54, 0x73, 0x80, 0x01, 0x40, 0xa0, 0x00, 0x13, 0x4e, 0x73, 0x00, 0x0e, 0x58, 0x13, 0x00, 0x00, +0x44, 0x00, 0x04, 0x28, 0x4b, 0xe0, 0x24, 0x01, 0x40, 0x00, 0x40, 0x09, 0x40, 0x00, 0x40, 0x08, +0x48, 0x00, 0x00, 0x0c, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x04, 0x28, 0x4b, 0xe0, 0x24, 0x01, +0x40, 0x00, 0x00, 0x13, 0x40, 0xa5, 0x40, 0x08, 0x40, 0x10, 0x28, 0x04, 0x58, 0x23, 0x00, 0x00, +0x44, 0x00, 0x04, 0x28, 0x4b, 0xe0, 0x20, 0x01, 0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x46, 0x18, 0x03, 0x00, 0x58, 0x20, 0x00, 0x00, +0x58, 0x70, 0x00, 0x00, 0x58, 0x10, 0x80, 0x08, 0x46, 0x60, 0x01, 0x0a, 0x58, 0x63, 0x04, 0x8c, +0x44, 0x00, 0x07, 0xdc, 0x4b, 0xe0, 0x18, 0x01, 0x44, 0x00, 0x00, 0x02, 0x46, 0xf0, 0x01, 0x03, +0x58, 0xf7, 0x80, 0x84, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x10, 0x03, 0x00, 0x58, 0x10, 0x80, 0x08, +0x58, 0x23, 0x80, 0x00, 0x44, 0x00, 0x07, 0xdc, 0x4b, 0xe0, 0x18, 0x01, 0x51, 0xff, 0x80, 0x04, +0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, 0x8c, 0x22, 0x4e, 0x03, 0x00, 0x12, 0x46, 0x46, 0x01, 0x20, +0x04, 0x52, 0x00, 0x20, 0x42, 0x22, 0xa0, 0x09, 0x14, 0x22, 0x00, 0x20, 0x44, 0x00, 0x00, 0x01, +0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x80, 0x84, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x67, 0x8c, 0x23, 0x4e, 0x63, 0x00, 0x12, 0x46, 0x86, 0x01, 0x20, 0x05, 0xe4, 0x00, 0x20, +0x42, 0x9f, 0x24, 0x09, 0x14, 0x94, 0x00, 0x20, 0x44, 0x00, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x03, +0x58, 0xf7, 0x80, 0x84, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x60, 0x00, 0x00, 0x46, 0x90, 0x01, 0x01, +0x58, 0x94, 0x84, 0x08, 0x48, 0x00, 0x00, 0x1c, 0x58, 0x03, 0x80, 0x00, 0x58, 0x13, 0x00, 0x00, +0x50, 0x73, 0x80, 0x01, 0x5c, 0xf4, 0x00, 0x02, 0x4e, 0xf3, 0x00, 0x04, 0x4b, 0xe0, 0x24, 0x01, +0x50, 0x44, 0x00, 0x01, 0x44, 0x50, 0x00, 0x0d, 0x54, 0x82, 0x00, 0xff, 0x4c, 0x72, 0xff, 0xee, +0x50, 0x63, 0x00, 0x01, 0x44, 0x50, 0x00, 0x04, 0x4c, 0x62, 0x80, 0x08, 0x44, 0x80, 0x00, 0xf9, +0x44, 0x70, 0x00, 0x00, 0x48, 0xff, 0xff, 0xe2, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xa4, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x44, 0x60, 0x00, 0x00, +0x46, 0x90, 0x01, 0x01, 0x58, 0x94, 0x80, 0x40, 0x48, 0x00, 0x00, 0x1e, 0x58, 0x03, 0x80, 0x00, +0x58, 0x13, 0x00, 0x00, 0x50, 0x73, 0x80, 0x01, 0x44, 0x20, 0x00, 0x64, 0x5c, 0xf4, 0x00, 0x02, +0x4e, 0xf3, 0x00, 0x04, 0x4b, 0xe0, 0x24, 0x01, 0x50, 0x84, 0x00, 0x01, 0x44, 0x50, 0x00, 0x0e, +0x54, 0x84, 0x00, 0xff, 0x4c, 0x72, 0xff, 0xec, 0x50, 0x63, 0x00, 0x01, 0x44, 0x50, 0x00, 0x04, +0x4c, 0x62, 0x80, 0x08, 0x44, 0x80, 0x00, 0xf9, 0x44, 0x70, 0x00, 0x00, 0x48, 0xff, 0xff, 0xe0, +0x46, 0x26, 0x01, 0x20, 0x04, 0x11, 0x00, 0x20, 0x54, 0x20, 0x81, 0x00, 0x4e, 0x22, 0x00, 0x04, +0x44, 0x20, 0x00, 0x01, 0x54, 0x10, 0x82, 0x00, 0x46, 0xf0, 0x01, 0x0f, 0x10, 0x27, 0x8c, 0x22, +0x4e, 0x12, 0x00, 0x04, 0x44, 0x10, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x10, 0x17, 0x8c, 0x23, +0x46, 0x36, 0x01, 0x20, 0x04, 0x51, 0x80, 0x20, 0x44, 0x00, 0x00, 0x01, 0x58, 0x42, 0x83, 0x00, +0x14, 0x41, 0x80, 0x20, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x80, 0x84, 0x4b, 0xe0, 0x3c, 0x01, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, +0x58, 0x60, 0x80, 0x00, 0x40, 0xa0, 0x00, 0x13, 0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x84, 0xc8, +0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x87, 0xa4, 0x4b, 0xe0, 0x3c, 0x01, 0x50, 0xa5, 0x7f, 0xff, +0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x00, 0xb0, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x97, 0x83, 0x04, +0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x40, 0x00, 0x0e, 0x58, 0x35, 0x00, 0x00, 0x42, 0x33, 0x10, 0x73, +0x46, 0x10, 0x01, 0x12, 0x58, 0x10, 0x8c, 0x70, 0x38, 0x50, 0x8d, 0x01, 0x46, 0x2f, 0x80, 0xff, +0x46, 0x40, 0x7f, 0x00, 0x40, 0x32, 0xd0, 0x08, 0x58, 0x21, 0x0f, 0xff, 0x40, 0x81, 0x90, 0x02, +0x40, 0x00, 0x08, 0x02, 0x40, 0x10, 0x20, 0x04, 0x58, 0x23, 0x00, 0x00, 0x46, 0x80, 0x01, 0x0a, +0x58, 0x84, 0x04, 0x8c, 0x44, 0x00, 0x00, 0xb0, 0x40, 0xa5, 0x08, 0x08, 0x4b, 0xe0, 0x20, 0x01, +0x40, 0x95, 0x24, 0x00, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x00, 0xb0, 0x4b, 0xe0, 0x1c, 0x01, +0x50, 0x94, 0x80, 0x01, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8e, 0xf8, 0x38, 0x50, 0xa7, 0x01, +0x44, 0x43, 0xff, 0xf0, 0x40, 0x32, 0x90, 0x08, 0x44, 0x2c, 0x00, 0x0f, 0x40, 0x11, 0x90, 0x02, +0x40, 0x00, 0x08, 0x02, 0x40, 0x10, 0x04, 0x04, 0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x00, 0xb0, +0x4b, 0xe0, 0x20, 0x01, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x01, 0x0c, 0x4b, 0xe0, 0x1c, 0x01, +0x40, 0x94, 0x8c, 0x08, 0x46, 0x50, 0x01, 0x0e, 0x58, 0x52, 0x8e, 0xf8, 0x40, 0x94, 0x94, 0x00, +0x02, 0x44, 0x80, 0x01, 0x46, 0x2c, 0x00, 0xff, 0x46, 0x33, 0xff, 0x00, 0x40, 0x12, 0x50, 0x08, +0x58, 0x21, 0x0f, 0xff, 0x40, 0x50, 0x8c, 0x02, 0x40, 0x00, 0x08, 0x02, 0x40, 0x10, 0x14, 0x04, +0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x01, 0x0c, 0x4b, 0xe0, 0x20, 0x01, 0x58, 0x13, 0x00, 0x00, +0x44, 0x00, 0x01, 0x0c, 0x4b, 0xe0, 0x1c, 0x01, 0x04, 0x34, 0x80, 0x01, 0x40, 0x00, 0x50, 0x09, +0x40, 0x00, 0x50, 0x08, 0x40, 0x11, 0xb0, 0x08, 0x40, 0x10, 0xb0, 0x09, 0x40, 0x10, 0x04, 0x04, +0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x01, 0x0c, 0x4b, 0xe0, 0x20, 0x01, 0x46, 0x1f, 0xff, 0x0c, +0x58, 0x10, 0x80, 0x10, 0x44, 0x00, 0x00, 0xb4, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x20, 0x01, +0x46, 0x80, 0x01, 0x03, 0x58, 0x84, 0x00, 0x84, 0x44, 0x00, 0x00, 0x64, 0x4b, 0xe0, 0x20, 0x01, +0x58, 0x94, 0x00, 0x00, 0x44, 0x80, 0x00, 0x00, 0x44, 0x00, 0x00, 0x64, 0x4b, 0xe0, 0x24, 0x01, +0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x04, 0x24, 0x4b, 0xe0, 0x1c, 0x01, 0x42, 0x00, 0x68, 0x0b, +0x4e, 0x03, 0x00, 0x20, 0x44, 0x50, 0x00, 0x0b, 0x4c, 0x82, 0x80, 0x06, 0x50, 0x84, 0x00, 0x01, +0x48, 0xff, 0xff, 0xec, 0x46, 0xf0, 0x01, 0x16, 0x00, 0x17, 0x8f, 0x29, 0x4e, 0x13, 0x00, 0x12, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x0e, 0x3c, 0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x89, 0x30, +0x44, 0x20, 0x07, 0x9c, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, +0x46, 0x13, 0xff, 0x0c, 0x58, 0x10, 0x80, 0x10, 0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x00, 0xb4, +0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0x8c, 0x4b, 0xe0, 0x3c, 0x01, 0x3a, 0x6f, 0xa8, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x58, 0x60, 0x00, 0x00, +0x40, 0x81, 0x00, 0x13, 0x58, 0x70, 0x80, 0x00, 0x58, 0x04, 0x00, 0x00, 0x58, 0x13, 0x00, 0x00, +0x58, 0x91, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x0b, 0x58, 0xf7, 0x8f, 0x6c, 0x4b, 0xe0, 0x3c, 0x01, +0x58, 0x03, 0x80, 0x00, 0x58, 0x13, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x85, 0x14, +0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x03, 0x80, 0x00, 0x58, 0x13, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0a, +0x58, 0xf7, 0x89, 0x6c, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, 0x8c, 0x07, +0x4e, 0x03, 0x00, 0x0a, 0x58, 0x03, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0b, 0x58, 0xf7, 0x82, 0xac, +0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x03, 0x80, 0x00, 0x58, 0x13, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0a, +0x58, 0xf7, 0x85, 0x14, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x03, 0x80, 0x00, 0x58, 0x14, 0x80, 0x00, +0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x8b, 0x80, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x03, 0x00, 0x00, +0x58, 0x14, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x88, 0x68, 0x4b, 0xe0, 0x3c, 0x01, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x44, 0x70, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0b, 0x58, 0xf7, 0x8e, 0xb4, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x80, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x0b, 0x58, 0xf7, 0x8a, 0x88, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x90, 0x01, 0x0f, 0x58, 0x94, 0x8a, 0x20, 0x48, 0x00, 0x00, 0x4c, +0x4e, 0x73, 0x00, 0x06, 0x44, 0x80, 0x00, 0x01, 0x48, 0x00, 0x00, 0x08, 0x56, 0x03, 0x80, 0x01, +0x44, 0x10, 0x00, 0x00, 0x40, 0x80, 0x80, 0x1a, 0x44, 0x60, 0x00, 0x00, 0x48, 0x00, 0x00, 0x2a, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x37, 0x8c, 0x07, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x32, 0x80, 0x0a, +0x38, 0x14, 0x9b, 0x02, 0x4e, 0x12, 0x00, 0x1a, 0x00, 0x01, 0x00, 0x04, 0x48, 0x00, 0x00, 0x10, +0x38, 0x14, 0x9b, 0x02, 0x40, 0x23, 0x0c, 0x08, 0x46, 0x50, 0x01, 0x0f, 0x58, 0x52, 0x8a, 0x20, +0x40, 0x01, 0x14, 0x00, 0x4e, 0x12, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x05, 0x4e, 0x02, 0x00, 0x06, +0x58, 0x04, 0x00, 0x00, 0x4b, 0xe0, 0x04, 0x01, 0x50, 0x63, 0x00, 0x01, 0x54, 0x63, 0x00, 0xff, +0x46, 0xf0, 0x01, 0x0f, 0x01, 0xe7, 0x8c, 0x1f, 0x40, 0x13, 0x0c, 0x08, 0x46, 0x30, 0x01, 0x0f, +0x58, 0x31, 0x8a, 0x20, 0x40, 0x20, 0x8c, 0x00, 0x40, 0xf3, 0x78, 0x06, 0x4e, 0xf3, 0xff, 0xca, +0x50, 0x73, 0x80, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x47, 0x83, 0x06, 0x40, 0xf3, 0x90, 0x06, +0x4e, 0xf3, 0xff, 0xb0, 0x46, 0xf0, 0x01, 0x0b, 0x58, 0xf7, 0x8d, 0xf8, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x80, 0x00, 0x07, 0x46, 0x70, 0x01, 0x0f, 0x58, 0x73, 0x8a, 0x1c, 0x44, 0x60, 0x00, 0x00, +0x12, 0x83, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x0f, 0x12, 0x87, 0x85, 0xfd, 0x46, 0xf0, 0x01, 0x0f, +0x12, 0x87, 0x85, 0xfc, 0x46, 0xf0, 0x01, 0x0f, 0x14, 0x67, 0x82, 0xff, 0x46, 0x80, 0x01, 0x0c, +0x58, 0x84, 0x01, 0x54, 0x58, 0x93, 0x80, 0x00, 0x48, 0x00, 0x00, 0x08, 0x02, 0x24, 0x80, 0x00, +0x50, 0x63, 0x00, 0x01, 0x4b, 0xe0, 0x20, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x05, 0xe7, 0x83, 0x06, +0x44, 0x10, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0x58, 0x30, 0x80, 0x00, 0x40, 0xf3, 0x78, 0x06, +0x4e, 0xf3, 0xff, 0xee, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x46, 0x30, 0x02, 0x4b, 0x54, 0xa0, 0x00, 0xff, +0x46, 0x20, 0x04, 0xc4, 0x58, 0x31, 0x8a, 0x58, 0x58, 0x21, 0x0b, 0x40, 0x5c, 0x55, 0x00, 0x0f, +0x58, 0x70, 0x80, 0x00, 0x40, 0x01, 0x94, 0x1b, 0x40, 0x01, 0x14, 0x1a, 0x58, 0x15, 0x00, 0x00, +0x58, 0x23, 0x80, 0x00, 0x58, 0x62, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x08, 0x58, 0xf7, 0x85, 0x00, +0x4b, 0xe0, 0x3c, 0x01, 0x59, 0xc0, 0x00, 0x00, 0x44, 0x50, 0x00, 0x04, 0x4c, 0x62, 0xc0, 0x04, +0x48, 0x00, 0x00, 0x06, 0x44, 0x50, 0x00, 0x05, 0x4c, 0x62, 0xc0, 0x06, 0x58, 0x83, 0x00, 0x00, +0x48, 0x00, 0x00, 0x06, 0x44, 0x80, 0x00, 0x00, 0x40, 0x84, 0x1c, 0x06, 0x46, 0xf0, 0x01, 0x0b, +0x58, 0xf7, 0x8e, 0xb4, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x90, 0x00, 0x00, 0x46, 0x40, 0x01, 0x0f, +0x58, 0x42, 0x0c, 0x18, 0x46, 0x50, 0x01, 0x0c, 0x58, 0x52, 0x81, 0x54, 0x48, 0x00, 0x00, 0x0e, +0x14, 0x4f, 0x80, 0x01, 0x14, 0x5f, 0x80, 0x00, 0x50, 0x94, 0x80, 0x01, 0x4b, 0xe0, 0x14, 0x01, +0x04, 0x5f, 0x80, 0x00, 0x04, 0x4f, 0x80, 0x01, 0x05, 0xe2, 0x00, 0x00, 0x58, 0x04, 0x80, 0x00, +0x58, 0x14, 0x00, 0x00, 0x58, 0x2e, 0x00, 0x00, 0x58, 0x33, 0x80, 0x00, 0x40, 0xf4, 0xf8, 0x06, +0x4e, 0xf3, 0xff, 0xe8, 0x46, 0xf0, 0x01, 0x0b, 0x58, 0xf7, 0x8d, 0xf8, 0x4b, 0xe0, 0x3c, 0x01, +0x46, 0xf0, 0x01, 0x0f, 0x10, 0x77, 0x8c, 0x00, 0x44, 0x00, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x0f, +0x12, 0xa7, 0x85, 0xfc, 0x46, 0xf0, 0x01, 0x0f, 0x13, 0xc7, 0x85, 0xfd, 0x46, 0xf0, 0x01, 0x0f, +0x14, 0x87, 0x82, 0xff, 0x46, 0xf0, 0x01, 0x0f, 0x10, 0x67, 0x8c, 0x01, 0x51, 0xff, 0x80, 0x0c, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xe4, +0x14, 0x0f, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x0f, 0x02, 0x07, 0x85, 0x0e, 0x04, 0x1f, 0x80, 0x00, +0x47, 0xc0, 0x01, 0x0a, 0x59, 0xce, 0x04, 0x8c, 0x46, 0xf0, 0x01, 0x0b, 0x58, 0xf7, 0x8f, 0x6c, +0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x2f, 0x80, 0x00, 0x46, 0x18, 0x1b, 0xd6, 0x58, 0x10, 0x8c, 0x7f, +0x44, 0x00, 0x00, 0x6c, 0x4b, 0xe0, 0x70, 0x01, 0x04, 0x2f, 0x80, 0x00, 0x46, 0x18, 0xc0, 0x08, +0x58, 0x10, 0x82, 0xd0, 0x44, 0x00, 0x00, 0x44, 0x4b, 0xe0, 0x70, 0x01, 0x04, 0x2f, 0x80, 0x00, +0x46, 0x1f, 0x8b, 0x00, 0x58, 0x10, 0x87, 0x27, 0x44, 0x00, 0x00, 0x48, 0x4b, 0xe0, 0x70, 0x01, +0x04, 0x9f, 0x80, 0x00, 0x44, 0xa0, 0x00, 0x0c, 0x42, 0x84, 0xa8, 0x24, 0x46, 0x70, 0x01, 0x12, +0x58, 0x73, 0x8c, 0x70, 0x40, 0x64, 0x1c, 0x00, 0x14, 0x6f, 0x80, 0x02, 0x40, 0x54, 0x8c, 0x08, +0x04, 0x0f, 0x80, 0x02, 0x58, 0x43, 0x80, 0x00, 0x40, 0x22, 0x90, 0x00, 0x44, 0x10, 0x00, 0x00, +0x50, 0x30, 0x03, 0x48, 0x14, 0x2f, 0x80, 0x04, 0x14, 0x1f, 0x80, 0x01, 0x14, 0x3f, 0x80, 0x05, +0x04, 0x9f, 0x80, 0x00, 0x46, 0x10, 0x06, 0x10, 0x44, 0x00, 0x00, 0xe8, 0x58, 0x10, 0x80, 0x88, +0x46, 0x60, 0x01, 0x0a, 0x58, 0x63, 0x04, 0x8c, 0x58, 0x24, 0x80, 0x00, 0x4b, 0xe0, 0x18, 0x01, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x37, 0x8c, 0x07, 0x4e, 0x33, 0x00, 0x08, 0x46, 0x10, 0x06, 0x10, +0x58, 0x10, 0x80, 0x88, 0x48, 0x00, 0x00, 0x06, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x87, +0x44, 0x00, 0x00, 0xe8, 0x58, 0x24, 0x80, 0x00, 0x4b, 0xe0, 0x18, 0x01, 0x04, 0x1f, 0x80, 0x01, +0x46, 0x60, 0x01, 0x0a, 0x58, 0x63, 0x04, 0x8c, 0x4e, 0x13, 0x00, 0x10, 0x46, 0x10, 0x50, 0x00, +0x58, 0x10, 0x8b, 0xb8, 0x58, 0x24, 0x80, 0x00, 0x44, 0x00, 0x00, 0x70, 0x4b, 0xe0, 0x18, 0x01, +0x46, 0x18, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0e, 0x46, 0x10, 0x50, 0x00, 0x58, 0x10, 0x8b, 0xb8, +0x44, 0x00, 0x00, 0x70, 0x58, 0x24, 0x80, 0x00, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x19, 0x00, 0x00, +0x44, 0x00, 0x00, 0xa0, 0x58, 0x24, 0x80, 0x00, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x18, 0x20, 0x24, +0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, 0x58, 0x24, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x0a, +0x58, 0xf7, 0x84, 0x8c, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x60, 0x01, 0x0a, 0x58, 0x63, 0x04, 0xc8, +0x44, 0x00, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x80, 0x84, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x00, 0x04, 0x1c, 0x58, 0x14, 0x80, 0x00, 0x4b, 0xe0, 0x18, 0x01, 0x40, 0x20, 0x04, 0x08, +0x40, 0x21, 0x74, 0x09, 0x4e, 0x23, 0xff, 0xee, 0x46, 0x10, 0x20, 0x24, 0x58, 0x10, 0x80, 0xc0, +0x44, 0x00, 0x00, 0xc8, 0x58, 0x24, 0x80, 0x00, 0x46, 0xa6, 0x02, 0x00, 0x58, 0x75, 0x00, 0x00, +0x58, 0x63, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0x8c, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x80, 0x00, 0x27, 0x44, 0x50, 0x00, 0x02, 0x14, 0x85, 0x00, 0x00, 0x14, 0x83, 0x80, 0x01, +0x14, 0x53, 0x00, 0x83, 0x4e, 0x93, 0x00, 0x20, 0x47, 0xe6, 0x02, 0x00, 0x46, 0xa0, 0x40, 0x00, +0x46, 0x80, 0x02, 0x74, 0x46, 0x3c, 0x00, 0x00, 0x46, 0x4f, 0x00, 0x00, 0x46, 0x14, 0x38, 0x00, +0x59, 0xef, 0x02, 0x00, 0x51, 0xcf, 0x0b, 0x00, 0x58, 0x84, 0x00, 0x27, 0x50, 0x7e, 0x00, 0x04, +0x58, 0x31, 0x84, 0x00, 0x50, 0x63, 0xb5, 0x10, 0x50, 0x5e, 0x7d, 0x08, 0x50, 0x23, 0x80, 0x20, +0x48, 0x00, 0x00, 0x22, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x92, 0xc0, 0x2c, 0x47, 0xe6, 0x02, 0x00, +0x46, 0xa1, 0x40, 0x00, 0x46, 0x80, 0x02, 0x74, 0x46, 0x3c, 0x00, 0x00, 0x46, 0x4f, 0x00, 0x00, +0x46, 0x14, 0x38, 0x00, 0x59, 0xef, 0x02, 0x00, 0x51, 0xcf, 0x1b, 0x00, 0x58, 0x84, 0x00, 0x27, +0x50, 0x7e, 0x00, 0x04, 0x58, 0x31, 0x84, 0x00, 0x50, 0x63, 0xb5, 0x10, 0x50, 0x5e, 0x7d, 0x08, +0x50, 0x23, 0x80, 0x20, 0x14, 0xaf, 0x00, 0x00, 0x45, 0xe0, 0x05, 0x95, 0x14, 0x8e, 0x00, 0x00, +0x14, 0x33, 0x80, 0x00, 0x15, 0xe3, 0x00, 0x00, 0x14, 0x42, 0x80, 0x00, 0x14, 0x11, 0x00, 0x00, +0x46, 0xa6, 0x02, 0x04, 0x14, 0xaf, 0x80, 0x03, 0x46, 0x66, 0x02, 0x00, 0x04, 0x4f, 0x80, 0x03, +0x58, 0x03, 0x00, 0x00, 0x58, 0x42, 0x01, 0x40, 0x58, 0x80, 0x00, 0x00, 0x14, 0x4f, 0x80, 0x03, +0x44, 0x40, 0x00, 0x00, 0x44, 0x30, 0x08, 0x00, 0x14, 0x33, 0x00, 0x56, 0x14, 0x40, 0x00, 0x57, +0x14, 0x44, 0x00, 0x58, 0x59, 0xe0, 0x00, 0x00, 0x04, 0x6f, 0x80, 0x03, 0x59, 0xc0, 0x00, 0x00, +0x58, 0xa0, 0x00, 0x00, 0x46, 0x74, 0x40, 0x0c, 0x58, 0x50, 0x00, 0x00, 0x46, 0x20, 0x02, 0x20, +0x58, 0x10, 0x00, 0x00, 0x58, 0x73, 0x81, 0x00, 0x58, 0x21, 0x0d, 0xa2, 0x44, 0x80, 0x00, 0x33, +0x50, 0x42, 0x00, 0x10, 0x44, 0x01, 0x50, 0x68, 0x44, 0x30, 0x13, 0x00, 0x14, 0x83, 0x00, 0x00, +0x14, 0x4f, 0x00, 0xe0, 0x14, 0x0e, 0x00, 0xc0, 0x14, 0x75, 0x01, 0xc1, 0x14, 0x22, 0x81, 0xb3, +0x14, 0x30, 0x80, 0x82, 0x04, 0x1f, 0x80, 0x01, 0x4e, 0x13, 0x00, 0x16, 0x46, 0x26, 0x02, 0x04, +0x46, 0x46, 0x02, 0x00, 0x46, 0x57, 0xa8, 0x28, 0x46, 0x3a, 0x77, 0xb6, 0x58, 0x42, 0x01, 0x80, +0x58, 0x52, 0x83, 0x80, 0x50, 0x02, 0x00, 0x04, 0x58, 0x31, 0x8f, 0x71, 0x14, 0x11, 0x00, 0x40, +0x48, 0x00, 0x00, 0x16, 0x46, 0x16, 0x02, 0x04, 0x46, 0x70, 0x10, 0x00, 0x46, 0x46, 0x02, 0x00, +0x46, 0x57, 0xa8, 0x38, 0x46, 0x3a, 0x67, 0xb6, 0x14, 0x70, 0x80, 0x40, 0x58, 0x42, 0x01, 0x80, +0x58, 0x52, 0x84, 0x80, 0x50, 0x02, 0x00, 0x04, 0x58, 0x31, 0x8f, 0x71, 0x14, 0x52, 0x00, 0x00, +0x58, 0x75, 0x00, 0x00, 0x14, 0x30, 0x00, 0x00, 0x59, 0xe3, 0x80, 0x00, 0x46, 0x60, 0x90, 0x70, +0x58, 0x33, 0x80, 0x00, 0x46, 0x50, 0x14, 0x20, 0x58, 0x63, 0x00, 0x01, 0x50, 0x03, 0x00, 0x04, +0x44, 0x80, 0x04, 0x1f, 0x14, 0x83, 0x80, 0x64, 0x14, 0x6f, 0x00, 0x54, 0x14, 0x51, 0x80, 0x55, +0x58, 0x61, 0x80, 0x00, 0x14, 0x0f, 0x00, 0x54, 0x44, 0x00, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x03, +0x58, 0xf7, 0x80, 0x84, 0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x23, 0x00, 0x65, 0x54, 0x41, 0x00, 0x1f, +0x4e, 0x43, 0xff, 0xf4, 0x47, 0xe6, 0x02, 0x00, 0x46, 0x00, 0x21, 0x00, 0x58, 0x00, 0x00, 0x01, +0x14, 0x0f, 0x00, 0x54, 0x46, 0x30, 0x01, 0x12, 0x58, 0x31, 0x8c, 0x70, 0x04, 0x1f, 0x80, 0x01, +0x4e, 0x13, 0x00, 0x28, 0x58, 0x5f, 0x00, 0x00, 0x05, 0xe2, 0x80, 0x56, 0x04, 0x5f, 0x80, 0x02, +0x46, 0x16, 0x02, 0x00, 0x15, 0xe2, 0x80, 0xcc, 0x04, 0x20, 0x80, 0x57, 0x58, 0x00, 0x80, 0x00, +0x14, 0x22, 0x80, 0xcd, 0x04, 0x40, 0x00, 0x58, 0x59, 0xe0, 0x00, 0x00, 0x14, 0x42, 0x80, 0xce, +0x04, 0x1f, 0x00, 0x62, 0x50, 0x24, 0x80, 0x6c, 0x38, 0x11, 0x8b, 0x0a, 0x58, 0x40, 0x00, 0x00, +0x04, 0x32, 0x00, 0x63, 0x04, 0x5f, 0x80, 0x04, 0x14, 0x32, 0x80, 0xd9, 0x48, 0x00, 0x00, 0x26, +0x58, 0x4f, 0x00, 0x00, 0x04, 0x52, 0x00, 0x56, 0x04, 0x1f, 0x80, 0x05, 0x59, 0xe2, 0x00, 0x00, +0x14, 0x50, 0x80, 0x00, 0x04, 0x2f, 0x00, 0x57, 0x04, 0x5f, 0x80, 0x02, 0x58, 0x02, 0x00, 0x00, +0x14, 0x22, 0x80, 0xd3, 0x04, 0x40, 0x00, 0x58, 0x59, 0xe0, 0x00, 0x00, 0x14, 0x42, 0x80, 0xd4, +0x04, 0x1f, 0x00, 0x62, 0x50, 0x24, 0x80, 0x6e, 0x38, 0x11, 0x8b, 0x0a, 0x04, 0x30, 0x00, 0x63, +0x04, 0x4f, 0x80, 0x04, 0x14, 0x32, 0x00, 0xdd, 0x05, 0xef, 0x80, 0x01, 0x44, 0x50, 0x00, 0x02, +0x50, 0x2f, 0x00, 0x01, 0x40, 0x01, 0x00, 0x13, 0x14, 0x0f, 0x80, 0x01, 0x4c, 0x02, 0xfe, 0x24, +0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x85, 0xec, 0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x0f, 0x80, 0x00, +0x4e, 0x03, 0x00, 0x08, 0x46, 0x16, 0x02, 0x00, 0x14, 0x00, 0x80, 0x5f, 0x48, 0x00, 0x00, 0x0e, +0x04, 0x5f, 0x80, 0x00, 0x44, 0x40, 0x00, 0x01, 0x4c, 0x52, 0x40, 0x08, 0x46, 0x06, 0x02, 0x01, +0x44, 0x30, 0x00, 0x00, 0x14, 0x30, 0x00, 0x5f, 0x51, 0xff, 0x80, 0x1c, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x14, 0x0f, 0x80, 0x00, +0x46, 0xf0, 0x01, 0x0f, 0x02, 0x07, 0x85, 0x0e, 0x04, 0x1f, 0x80, 0x00, 0x46, 0x60, 0x01, 0x0a, +0x58, 0x63, 0x04, 0x8c, 0x46, 0xf0, 0x01, 0x0b, 0x58, 0xf7, 0x8f, 0x6c, 0x4b, 0xe0, 0x3c, 0x01, +0x04, 0x2f, 0x80, 0x00, 0x46, 0x18, 0x1b, 0xd6, 0x58, 0x10, 0x8c, 0x7f, 0x44, 0x00, 0x00, 0x6c, +0x4b, 0xe0, 0x18, 0x01, 0x04, 0x2f, 0x80, 0x00, 0x46, 0x18, 0xc0, 0x08, 0x58, 0x10, 0x82, 0xd0, +0x44, 0x00, 0x00, 0x44, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x1f, 0x8b, 0x00, 0x04, 0x2f, 0x80, 0x00, +0x44, 0x00, 0x00, 0x48, 0x58, 0x10, 0x87, 0x27, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x37, 0x8c, 0x06, 0x4e, 0x32, 0x00, 0x16, 0x04, 0x2f, 0x80, 0x00, 0x46, 0x10, 0x24, 0x44, +0x58, 0x10, 0x84, 0x08, 0x44, 0x00, 0x06, 0x10, 0x4b, 0xe0, 0x18, 0x01, 0x46, 0x18, 0x3f, 0xf0, +0x04, 0x2f, 0x80, 0x00, 0x58, 0x10, 0x80, 0x03, 0x44, 0x00, 0x00, 0x54, 0x4b, 0xe0, 0x18, 0x01, +0x46, 0x26, 0x02, 0x00, 0x58, 0x21, 0x01, 0x48, 0x14, 0x2f, 0x80, 0x01, 0x04, 0x8f, 0x80, 0x00, +0x44, 0x90, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x47, 0x8c, 0x07, 0x4e, 0x43, 0x00, 0x08, +0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x88, 0x48, 0x00, 0x00, 0x06, 0x46, 0x10, 0x06, 0x10, +0x58, 0x10, 0x80, 0x87, 0x44, 0x00, 0x00, 0xe8, 0x58, 0x24, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0a, +0x58, 0xf7, 0x84, 0x8c, 0x4b, 0xe0, 0x3c, 0x01, 0x4e, 0x93, 0x00, 0x08, 0x46, 0x10, 0x50, 0x00, +0x58, 0x10, 0x8b, 0xb8, 0x48, 0x00, 0x00, 0x1a, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x92, 0xc0, 0x08, +0x46, 0x10, 0x50, 0x00, 0x58, 0x10, 0x8b, 0xaa, 0x48, 0x00, 0x00, 0x10, 0x44, 0x50, 0x00, 0x02, +0x4c, 0x92, 0xc0, 0x08, 0x46, 0x10, 0x50, 0x00, 0x58, 0x10, 0x8b, 0x99, 0x48, 0x00, 0x00, 0x06, +0x46, 0x10, 0x50, 0x00, 0x58, 0x10, 0x8b, 0x8a, 0x44, 0x00, 0x00, 0x70, 0x58, 0x24, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0x8c, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x18, 0x00, 0x00, +0x44, 0x00, 0x00, 0xa0, 0x58, 0x24, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0x8c, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x18, 0x20, 0x24, 0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, +0x58, 0x24, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0x8c, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x00, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x80, 0x84, 0x4b, 0xe0, 0x3c, 0x01, +0x44, 0x00, 0x04, 0x1c, 0x58, 0x14, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0xc8, +0x4b, 0xe0, 0x3c, 0x01, 0x40, 0x00, 0x70, 0x09, 0x4e, 0x03, 0xff, 0xec, 0x46, 0x10, 0x20, 0x24, +0x58, 0x10, 0x80, 0xc0, 0x58, 0x24, 0x00, 0x00, 0x44, 0x00, 0x00, 0xc8, 0x46, 0xf0, 0x01, 0x0a, +0x58, 0xf7, 0x84, 0x8c, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x66, 0x02, 0x00, 0x58, 0x43, 0x00, 0x00, +0x58, 0x12, 0x00, 0x00, 0x44, 0x50, 0x00, 0x27, 0x44, 0x20, 0x00, 0x02, 0x14, 0x52, 0x00, 0x00, +0x14, 0x53, 0x00, 0x01, 0x14, 0x20, 0x80, 0x83, 0x4e, 0x83, 0x00, 0x20, 0x47, 0xe6, 0x02, 0x00, +0x46, 0x70, 0x40, 0x00, 0x46, 0x60, 0x02, 0x74, 0x46, 0x0c, 0x00, 0x00, 0x46, 0x3f, 0x00, 0x00, +0x46, 0x14, 0x08, 0x00, 0x59, 0xef, 0x02, 0x00, 0x51, 0xcf, 0x0b, 0x00, 0x58, 0x63, 0x00, 0x27, +0x50, 0xae, 0x00, 0x04, 0x58, 0x00, 0x04, 0x00, 0x50, 0x55, 0x35, 0x10, 0x50, 0x4e, 0x7d, 0x08, +0x50, 0x25, 0x00, 0x20, 0x48, 0x00, 0x00, 0x22, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x82, 0xc0, 0x2c, +0x47, 0xe6, 0x02, 0x00, 0x46, 0x71, 0x40, 0x00, 0x46, 0x60, 0x02, 0x74, 0x46, 0x0c, 0x00, 0x00, +0x46, 0x3f, 0x00, 0x00, 0x46, 0x14, 0x08, 0x00, 0x59, 0xef, 0x02, 0x00, 0x51, 0xcf, 0x1b, 0x00, +0x58, 0x63, 0x00, 0x27, 0x50, 0xae, 0x00, 0x04, 0x58, 0x00, 0x04, 0x00, 0x50, 0x55, 0x35, 0x10, +0x50, 0x4e, 0x7d, 0x08, 0x50, 0x25, 0x00, 0x20, 0x14, 0x7f, 0x00, 0x00, 0x44, 0x70, 0x05, 0x95, +0x14, 0x6e, 0x00, 0x00, 0x14, 0x05, 0x00, 0x00, 0x14, 0x72, 0x80, 0x00, 0x14, 0x32, 0x00, 0x00, +0x14, 0x11, 0x00, 0x00, 0x46, 0x06, 0x02, 0x04, 0x46, 0x56, 0x02, 0x00, 0x58, 0x42, 0x80, 0x00, +0x58, 0x10, 0x00, 0x00, 0x46, 0x20, 0x20, 0x00, 0x44, 0x70, 0x00, 0x03, 0x45, 0xe0, 0x00, 0x10, +0x44, 0x61, 0x00, 0x68, 0x14, 0x70, 0x00, 0x50, 0x15, 0xe2, 0x80, 0xe0, 0x14, 0x62, 0x00, 0xc0, +0x14, 0x20, 0x80, 0x40, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, 0x8c, 0x06, 0x4e, 0x02, 0x00, 0x08, +0x58, 0x12, 0x00, 0x00, 0x46, 0x33, 0x00, 0x00, 0x14, 0x30, 0x80, 0x51, 0x4e, 0x93, 0x00, 0x0a, +0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x02, 0x08, 0x44, 0x30, 0x13, 0x00, 0x48, 0x00, 0x00, 0x20, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x92, 0xc0, 0x0a, 0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x02, 0x08, +0x44, 0x30, 0x12, 0x00, 0x48, 0x00, 0x00, 0x14, 0x44, 0x50, 0x00, 0x02, 0x4c, 0x92, 0xc0, 0x0a, +0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x02, 0x08, 0x44, 0x30, 0x11, 0x00, 0x48, 0x00, 0x00, 0x08, +0x46, 0x06, 0x02, 0x00, 0x58, 0x00, 0x02, 0x08, 0x44, 0x30, 0x10, 0x00, 0x58, 0x62, 0x00, 0x00, +0x47, 0xe0, 0x07, 0x38, 0x46, 0x58, 0x07, 0x38, 0x14, 0x30, 0x00, 0x00, 0x15, 0xe3, 0x00, 0x50, +0x14, 0x53, 0x00, 0x50, 0x44, 0x00, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x80, 0x84, +0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x3f, 0x80, 0x01, 0x04, 0x71, 0x80, 0x00, 0x40, 0x03, 0x84, 0x08, +0x40, 0x00, 0x74, 0x09, 0x4e, 0x03, 0xff, 0xf0, 0x46, 0x26, 0x02, 0x00, 0x46, 0x40, 0x07, 0x38, +0x46, 0x64, 0x07, 0x38, 0x14, 0x41, 0x00, 0x50, 0x14, 0x61, 0x00, 0x50, 0x44, 0x00, 0x00, 0x01, +0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x80, 0x84, 0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x1f, 0x80, 0x01, +0x04, 0x00, 0x80, 0x00, 0x40, 0x50, 0x04, 0x08, 0x40, 0x52, 0xf4, 0x09, 0x4e, 0x53, 0xff, 0xf0, +0x47, 0xe6, 0x02, 0x00, 0x46, 0x20, 0x07, 0x38, 0x46, 0x32, 0x07, 0x38, 0x14, 0x2f, 0x00, 0x50, +0x14, 0x3f, 0x00, 0x50, 0x44, 0x00, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x03, 0x58, 0xf7, 0x80, 0x84, +0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x0f, 0x80, 0x01, 0x04, 0x40, 0x00, 0x00, 0x40, 0x62, 0x04, 0x08, +0x40, 0x63, 0x74, 0x09, 0x4e, 0x63, 0xff, 0xf0, 0x50, 0x34, 0x80, 0x01, 0x46, 0x16, 0x02, 0x00, +0x47, 0xe0, 0x07, 0x38, 0x40, 0x91, 0x80, 0x13, 0x44, 0x50, 0x00, 0x04, 0x15, 0xe0, 0x80, 0x50, +0x4c, 0x92, 0xfe, 0x72, 0x04, 0x4f, 0x80, 0x00, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x27, 0x8c, 0x06, +0x46, 0x30, 0x01, 0x12, 0x58, 0x31, 0x8c, 0x70, 0x50, 0x62, 0x00, 0x88, 0x50, 0x52, 0x00, 0x8a, +0x4e, 0x22, 0x00, 0x0e, 0x58, 0x00, 0x80, 0x00, 0x04, 0x70, 0x00, 0xa4, 0x46, 0x46, 0x02, 0x00, +0x38, 0x71, 0x9a, 0x0a, 0x58, 0x42, 0x02, 0x94, 0x48, 0x00, 0x00, 0x0a, 0x04, 0x70, 0x80, 0xa2, +0x46, 0x46, 0x02, 0x00, 0x38, 0x71, 0x9a, 0x0a, 0x58, 0x42, 0x02, 0x8c, 0x05, 0xe2, 0x00, 0x00, +0x39, 0xe1, 0x96, 0x0a, 0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x85, 0xec, 0x4b, 0xe0, 0x3c, 0x01, +0x04, 0x5f, 0x80, 0x00, 0x4e, 0x53, 0x00, 0x28, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x27, 0x8c, 0x06, +0x46, 0x30, 0x01, 0x12, 0x58, 0x31, 0x8c, 0x70, 0x4e, 0x22, 0x00, 0x10, 0x04, 0x01, 0x80, 0x89, +0x46, 0x46, 0x02, 0x01, 0x14, 0x02, 0x00, 0xa4, 0x46, 0x06, 0x02, 0x01, 0x04, 0x11, 0x80, 0x8b, +0x58, 0x00, 0x02, 0x94, 0x48, 0x00, 0x00, 0x0e, 0x04, 0x11, 0x80, 0x89, 0x46, 0x56, 0x02, 0x01, +0x14, 0x12, 0x80, 0xa2, 0x46, 0x06, 0x02, 0x01, 0x04, 0x11, 0x80, 0x8b, 0x58, 0x00, 0x02, 0x8c, +0x14, 0x10, 0x00, 0x00, 0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xf4, 0x58, 0x60, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0f, +0x02, 0x07, 0x85, 0x0e, 0x58, 0x13, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0b, 0x58, 0xf7, 0x8f, 0x6c, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x18, 0x1b, 0x06, 0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x84, 0x8c, +0x58, 0x10, 0x8e, 0x07, 0x44, 0x00, 0x00, 0x6c, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0x1f, 0x8b, 0x00, 0x58, 0x10, 0x87, 0x27, 0x44, 0x00, 0x00, 0x48, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x18, 0x00, 0x6d, 0x58, 0x10, 0x85, 0xe4, 0x44, 0x00, 0x00, 0xa0, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x26, 0x02, 0x00, 0x58, 0x41, 0x00, 0x00, +0x58, 0x01, 0x00, 0x00, 0x44, 0x30, 0x00, 0x27, 0x44, 0x10, 0x00, 0x02, 0x14, 0x31, 0x00, 0x00, +0x14, 0x32, 0x00, 0x01, 0x14, 0x10, 0x00, 0x83, 0x4e, 0x63, 0x00, 0x1c, 0x46, 0x86, 0x02, 0x00, +0x46, 0x90, 0x40, 0x00, 0x46, 0x70, 0x02, 0x74, 0x46, 0x4c, 0x00, 0x00, 0x46, 0x1f, 0x00, 0x00, +0x58, 0x84, 0x02, 0x00, 0x50, 0x54, 0x0b, 0x00, 0x58, 0x73, 0x80, 0x27, 0x50, 0x32, 0x80, 0x04, +0x58, 0x42, 0x04, 0x00, 0x50, 0x21, 0xb5, 0x10, 0x50, 0x02, 0xfd, 0x08, 0x48, 0x00, 0x00, 0x1e, +0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x26, 0x46, 0x86, 0x02, 0x00, 0x46, 0x91, 0x40, 0x00, +0x46, 0x70, 0x02, 0x74, 0x46, 0x4c, 0x00, 0x00, 0x46, 0x1f, 0x00, 0x00, 0x58, 0x84, 0x02, 0x00, +0x50, 0x54, 0x1b, 0x00, 0x58, 0x73, 0x80, 0x27, 0x50, 0x32, 0x80, 0x04, 0x58, 0x42, 0x04, 0x00, +0x50, 0x21, 0xb5, 0x10, 0x50, 0x02, 0xfd, 0x08, 0x14, 0x94, 0x00, 0x00, 0x44, 0x90, 0x05, 0x95, +0x14, 0x72, 0x80, 0x00, 0x14, 0x41, 0x80, 0x00, 0x14, 0x91, 0x00, 0x00, 0x14, 0x10, 0x00, 0x00, +0x46, 0x36, 0x02, 0x04, 0x46, 0x16, 0x02, 0x00, 0x59, 0xe0, 0x80, 0x00, 0x58, 0xa1, 0x80, 0x00, +0x47, 0xc0, 0x20, 0x00, 0x44, 0x20, 0x00, 0x03, 0x44, 0x40, 0x00, 0x10, 0x44, 0x01, 0x00, 0x68, +0x14, 0x21, 0x80, 0x50, 0x14, 0x40, 0x80, 0xe0, 0x14, 0x0f, 0x00, 0xc0, 0x46, 0x18, 0x20, 0x24, +0x15, 0xc5, 0x00, 0x40, 0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0x8c, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x80, 0x01, 0x03, +0x58, 0x84, 0x00, 0x84, 0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x84, 0xc8, 0x44, 0x00, 0x00, 0x01, +0x4b, 0xe0, 0x20, 0x01, 0x44, 0x00, 0x04, 0x1c, 0x58, 0x13, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x40, 0x50, 0x70, 0x09, 0x4e, 0x53, 0xff, 0xf4, 0x46, 0x86, 0x02, 0x01, 0x14, 0x8f, 0x80, 0x01, +0x46, 0x10, 0x20, 0x24, 0x46, 0xa0, 0x01, 0x0a, 0x58, 0xa5, 0x04, 0x8c, 0x58, 0x10, 0x80, 0xc0, +0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x28, 0x01, 0x04, 0x7f, 0x80, 0x01, +0x47, 0xc6, 0x02, 0x00, 0x58, 0x73, 0x8d, 0x24, 0x46, 0x86, 0x02, 0x00, 0x14, 0x7f, 0x80, 0x01, +0x58, 0x84, 0x01, 0x24, 0x46, 0x70, 0x01, 0x0f, 0x58, 0x73, 0x86, 0xb4, 0x50, 0x93, 0xff, 0xf4, +0x46, 0xa0, 0x01, 0x03, 0x58, 0xa5, 0x00, 0x84, 0x46, 0xf0, 0x01, 0x0f, 0x01, 0xe7, 0x8c, 0x07, +0x4f, 0xe3, 0x00, 0x06, 0x04, 0x14, 0x80, 0x00, 0x48, 0x00, 0x00, 0x04, 0x04, 0x14, 0x80, 0x01, +0x44, 0x00, 0x00, 0xd4, 0x58, 0x23, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0x8c, +0x4b, 0xe0, 0x3c, 0x01, 0x04, 0x13, 0xff, 0xff, 0x44, 0x00, 0x00, 0x14, 0x58, 0x23, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0x8c, 0x4b, 0xe0, 0x3c, 0x01, 0x4e, 0x63, 0x00, 0x08, +0x04, 0x13, 0x80, 0x00, 0x14, 0x1e, 0x03, 0x49, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x62, 0xc0, 0x08, 0x04, 0x33, 0x80, 0x00, 0x04, 0x2f, 0x80, 0x01, 0x14, 0x31, 0x00, 0x00, +0x46, 0x06, 0x02, 0x00, 0x46, 0x10, 0x50, 0x04, 0x58, 0x50, 0x00, 0x00, 0x58, 0x10, 0x80, 0xf7, +0x45, 0xe0, 0x00, 0x01, 0x14, 0x10, 0x00, 0x41, 0x15, 0xe2, 0x80, 0x40, 0x44, 0x00, 0x00, 0x01, +0x4b, 0xe0, 0x28, 0x01, 0x04, 0x44, 0x00, 0x00, 0x54, 0x32, 0x00, 0x08, 0x4e, 0x33, 0xff, 0xf8, +0x46, 0x56, 0x02, 0x00, 0x59, 0xe2, 0x80, 0x00, 0x46, 0x20, 0x80, 0x04, 0x14, 0x32, 0x80, 0x40, +0x58, 0x21, 0x07, 0xf7, 0x44, 0x30, 0x00, 0x02, 0x14, 0x2f, 0x00, 0x41, 0x14, 0x32, 0x80, 0x40, +0x44, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x28, 0x01, 0x04, 0x04, 0x00, 0x00, 0x54, 0x10, 0x00, 0x08, +0x4e, 0x13, 0xff, 0xf8, 0x46, 0x46, 0x02, 0x00, 0x14, 0x12, 0x00, 0x40, 0x44, 0x10, 0x00, 0x04, +0x14, 0x12, 0x00, 0x40, 0x44, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x28, 0x01, 0x04, 0x54, 0x00, 0x00, +0x54, 0x12, 0x80, 0x08, 0x4e, 0x13, 0xff, 0xf8, 0x47, 0xe6, 0x02, 0x00, 0x50, 0x73, 0x80, 0x10, +0x46, 0x50, 0x01, 0x0f, 0x58, 0x52, 0x87, 0x74, 0x14, 0x1f, 0x00, 0x40, 0x50, 0x94, 0x80, 0x10, +0x4c, 0x72, 0xff, 0x7c, 0x44, 0x00, 0x00, 0x18, 0x42, 0x13, 0x00, 0x24, 0x46, 0x40, 0x01, 0x12, +0x58, 0x42, 0x0c, 0x70, 0x46, 0x06, 0x02, 0x00, 0x50, 0x20, 0x81, 0xc0, 0x40, 0x11, 0x10, 0x00, +0x58, 0x00, 0x02, 0x64, 0x0c, 0x30, 0x00, 0x01, 0x46, 0x56, 0x02, 0x00, 0x58, 0x52, 0x82, 0x7c, +0x1c, 0x30, 0x80, 0x01, 0x4c, 0x02, 0xff, 0xf8, 0x44, 0x10, 0x00, 0x18, 0x42, 0x43, 0x04, 0x24, +0x51, 0xe2, 0x01, 0xf0, 0x46, 0x20, 0x01, 0x12, 0x58, 0x21, 0x0c, 0x70, 0x40, 0x1f, 0x08, 0x00, +0x50, 0x02, 0xff, 0xc4, 0x0c, 0x30, 0x00, 0x01, 0x46, 0x56, 0x02, 0x00, 0x58, 0x52, 0x82, 0x58, +0x1c, 0x30, 0x80, 0x01, 0x4c, 0x02, 0xff, 0xf8, 0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x85, 0xec, +0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x34, 0x46, 0x06, 0x02, 0x01, +0x58, 0x00, 0x02, 0x64, 0x46, 0x30, 0x01, 0x12, 0x58, 0x31, 0x8c, 0x70, 0x46, 0x59, 0xfd, 0xfe, +0x40, 0x10, 0x0c, 0x00, 0x58, 0x52, 0x8f, 0x74, 0x40, 0x40, 0x94, 0x00, 0x04, 0x22, 0x00, 0x00, +0x47, 0xe6, 0x02, 0x01, 0x1c, 0x20, 0x00, 0x01, 0x59, 0xef, 0x02, 0x7c, 0x4c, 0x0f, 0x7f, 0xec, +0x50, 0x0f, 0x7f, 0xc4, 0x46, 0x30, 0x01, 0x12, 0x58, 0x31, 0x8c, 0x70, 0x46, 0x59, 0xfd, 0xfe, +0x40, 0x10, 0x0c, 0x00, 0x58, 0x52, 0x8f, 0xc8, 0x40, 0x40, 0x94, 0x00, 0x04, 0x22, 0x00, 0x00, +0x47, 0xe6, 0x02, 0x01, 0x1c, 0x20, 0x00, 0x01, 0x59, 0xef, 0x02, 0x58, 0x4c, 0x0f, 0x7f, 0xec, +0x51, 0xff, 0x80, 0x0c, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xfc, 0x58, 0x60, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0f, 0x02, 0x07, 0x85, 0x0e, +0x58, 0x13, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0b, 0x58, 0xf7, 0x8f, 0x6c, 0x4b, 0xe0, 0x3c, 0x01, +0x46, 0x18, 0x1b, 0xd6, 0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x84, 0x8c, 0x58, 0x10, 0x8c, 0x7f, +0x44, 0x00, 0x00, 0x6c, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x18, 0xc0, 0x08, +0x58, 0x10, 0x82, 0xd0, 0x44, 0x00, 0x00, 0x44, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0x1f, 0x8b, 0x00, 0x58, 0x10, 0x87, 0x27, 0x44, 0x00, 0x00, 0x48, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0x50, 0x00, 0x58, 0x10, 0x8b, 0xb8, 0x44, 0x00, 0x00, 0x70, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x18, 0x00, 0x00, 0x44, 0x00, 0x00, 0xa0, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x18, 0x20, 0x24, 0x58, 0x10, 0x80, 0xc0, +0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x80, 0x01, 0x03, +0x58, 0x84, 0x00, 0x84, 0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x84, 0xc8, 0x44, 0x00, 0x00, 0x01, +0x4b, 0xe0, 0x20, 0x01, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x04, 0x1c, 0x4b, 0xe0, 0x1c, 0x01, +0x40, 0x20, 0x70, 0x09, 0x4e, 0x23, 0xff, 0xf4, 0x46, 0x10, 0x20, 0x24, 0x58, 0x10, 0x80, 0xc0, +0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x84, 0x8c, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x96, 0x02, 0x00, 0x58, 0x54, 0x80, 0x00, 0x58, 0x42, 0x80, 0x00, +0x44, 0x80, 0x00, 0x27, 0x44, 0x30, 0x00, 0x02, 0x14, 0x84, 0x80, 0x00, 0x14, 0x82, 0x80, 0x01, +0x14, 0x32, 0x00, 0x83, 0x4e, 0x63, 0x00, 0x20, 0x46, 0xa6, 0x02, 0x00, 0x47, 0xc0, 0x40, 0x00, +0x46, 0x90, 0x02, 0x74, 0x46, 0x7c, 0x00, 0x00, 0x46, 0x34, 0x00, 0x00, 0x46, 0x1f, 0x00, 0x00, +0x58, 0xa5, 0x02, 0x00, 0x50, 0x85, 0x0b, 0x00, 0x58, 0x94, 0x80, 0x27, 0x50, 0x54, 0x00, 0x04, +0x58, 0x73, 0x84, 0x00, 0x50, 0x42, 0xb5, 0x10, 0x50, 0x22, 0x80, 0x20, 0x50, 0x04, 0x7d, 0x08, +0x48, 0x00, 0x00, 0x22, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x2c, 0x46, 0xa6, 0x02, 0x00, +0x47, 0xc1, 0x40, 0x00, 0x46, 0x90, 0x02, 0x74, 0x46, 0x7c, 0x00, 0x00, 0x46, 0x34, 0x00, 0x00, +0x46, 0x1f, 0x00, 0x00, 0x58, 0xa5, 0x02, 0x00, 0x50, 0x85, 0x1b, 0x00, 0x58, 0x94, 0x80, 0x27, +0x50, 0x54, 0x00, 0x04, 0x58, 0x73, 0x84, 0x00, 0x50, 0x42, 0xb5, 0x10, 0x50, 0x22, 0x80, 0x20, +0x50, 0x04, 0x7d, 0x08, 0x45, 0xe0, 0x05, 0x97, 0x15, 0xc5, 0x00, 0x00, 0x14, 0x94, 0x00, 0x00, +0x14, 0x72, 0x80, 0x00, 0x15, 0xe2, 0x00, 0x00, 0x14, 0x31, 0x00, 0x00, 0x14, 0x10, 0x00, 0x00, +0x46, 0x76, 0x02, 0x04, 0x44, 0x50, 0x00, 0x03, 0x46, 0x06, 0x02, 0x00, 0x58, 0x40, 0x00, 0x00, +0x58, 0x23, 0x80, 0x00, 0x46, 0x30, 0x20, 0x00, 0x59, 0xe0, 0x00, 0x00, 0x46, 0x10, 0x90, 0x04, +0x14, 0x53, 0x80, 0x50, 0x58, 0x10, 0x8f, 0xf9, 0x44, 0x80, 0x00, 0x10, 0x44, 0x51, 0x00, 0x68, +0x14, 0x80, 0x00, 0xe0, 0x14, 0x52, 0x00, 0xc0, 0x14, 0x31, 0x00, 0x40, 0x14, 0x1f, 0x00, 0x41, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x77, 0x8c, 0x07, 0x46, 0x30, 0x01, 0x0a, 0x58, 0x31, 0x84, 0x8c, +0x4e, 0x73, 0x00, 0x08, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x88, 0x48, 0x00, 0x00, 0x06, +0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x87, 0x44, 0x00, 0x00, 0xe8, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x0c, 0x01, 0x4e, 0x63, 0x00, 0x0a, 0x46, 0x06, 0x02, 0x00, 0x46, 0x14, 0x00, 0x00, +0x58, 0x00, 0x0d, 0x24, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x0a, +0x46, 0x06, 0x02, 0x01, 0x46, 0x14, 0x00, 0x00, 0x58, 0x00, 0x0d, 0x24, 0x14, 0x10, 0x00, 0x00, +0x46, 0x46, 0x02, 0x00, 0x46, 0x27, 0x10, 0x20, 0x58, 0x32, 0x00, 0x00, 0x44, 0x10, 0x00, 0x20, +0x14, 0x22, 0x00, 0x47, 0x58, 0x71, 0x80, 0x00, 0x14, 0x11, 0x80, 0x40, 0x46, 0x80, 0x01, 0x03, +0x58, 0x84, 0x00, 0x84, 0x44, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x20, 0x01, 0x04, 0x53, 0x80, 0x4c, +0x44, 0x01, 0x00, 0x00, 0x40, 0x32, 0x80, 0x02, 0x4e, 0x33, 0xff, 0xf6, 0x46, 0x46, 0x02, 0x00, +0x59, 0xe2, 0x00, 0x00, 0x46, 0x17, 0x10, 0x00, 0x58, 0x10, 0x80, 0x02, 0x14, 0x32, 0x00, 0x40, +0x14, 0x1f, 0x00, 0x47, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x87, 0x8c, 0x07, 0x46, 0x30, 0x01, 0x0a, +0x58, 0x31, 0x84, 0x8c, 0x4e, 0x83, 0x00, 0x08, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x08, +0x48, 0x00, 0x00, 0x06, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x07, 0x44, 0x00, 0x00, 0xe8, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x0c, 0x01, 0x4e, 0x63, 0x00, 0x0a, 0x46, 0x06, 0x02, 0x00, +0x46, 0x14, 0x28, 0x00, 0x58, 0x00, 0x0d, 0x24, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x62, 0xc0, 0x0a, 0x46, 0x06, 0x02, 0x01, 0x46, 0x14, 0x28, 0x00, 0x58, 0x00, 0x0d, 0x24, +0x14, 0x10, 0x00, 0x00, 0x46, 0x26, 0x02, 0x00, 0x44, 0x50, 0x00, 0x20, 0x58, 0x71, 0x00, 0x00, +0x14, 0x51, 0x00, 0x40, 0x46, 0x80, 0x01, 0x03, 0x58, 0x84, 0x00, 0x84, 0x44, 0x00, 0x00, 0x01, +0x4b, 0xe0, 0x20, 0x01, 0x04, 0x13, 0x80, 0x4c, 0x44, 0x01, 0x00, 0x00, 0x40, 0x10, 0x80, 0x02, +0x4e, 0x13, 0xff, 0xf6, 0x47, 0xe6, 0x02, 0x00, 0x14, 0x1f, 0x00, 0x40, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x87, 0x8c, 0x07, 0x46, 0x30, 0x01, 0x0a, 0x58, 0x31, 0x84, 0x8c, 0x4e, 0x83, 0x00, 0x08, +0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x28, 0x48, 0x00, 0x00, 0x06, 0x46, 0x10, 0x06, 0x10, +0x58, 0x10, 0x80, 0x27, 0x44, 0x00, 0x00, 0xe8, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x0c, 0x01, +0x4e, 0x63, 0x00, 0x0a, 0x46, 0x06, 0x02, 0x00, 0x46, 0x14, 0x30, 0x00, 0x58, 0x00, 0x0d, 0x24, +0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x0a, 0x46, 0x06, 0x02, 0x01, +0x46, 0x14, 0x30, 0x00, 0x58, 0x00, 0x0d, 0x24, 0x14, 0x10, 0x00, 0x00, 0x46, 0x36, 0x02, 0x00, +0x44, 0x20, 0x00, 0x20, 0x58, 0x71, 0x80, 0x00, 0x14, 0x21, 0x80, 0x40, 0x46, 0x80, 0x01, 0x03, +0x58, 0x84, 0x00, 0x84, 0x44, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x20, 0x01, 0x04, 0x53, 0x80, 0x4c, +0x44, 0x01, 0x00, 0x00, 0x40, 0x12, 0x80, 0x02, 0x4e, 0x13, 0xff, 0xf6, 0x46, 0x76, 0x02, 0x00, +0x14, 0x13, 0x80, 0x40, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x17, 0x8c, 0x07, 0x46, 0x30, 0x01, 0x0a, +0x58, 0x31, 0x84, 0x8c, 0x4e, 0x13, 0x00, 0x08, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x68, +0x48, 0x00, 0x00, 0x06, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0x67, 0x44, 0x00, 0x00, 0xe8, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x0c, 0x01, 0x4e, 0x63, 0x00, 0x0a, 0x46, 0x06, 0x02, 0x00, +0x46, 0x14, 0x38, 0x00, 0x58, 0x00, 0x0d, 0x24, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x62, 0xc0, 0x0a, 0x46, 0x06, 0x02, 0x01, 0x46, 0x14, 0x38, 0x00, 0x58, 0x00, 0x0d, 0x24, +0x14, 0x10, 0x00, 0x00, 0x46, 0x46, 0x02, 0x00, 0x44, 0x30, 0x00, 0x20, 0x58, 0x72, 0x00, 0x00, +0x14, 0x32, 0x00, 0x40, 0x46, 0x80, 0x01, 0x03, 0x58, 0x84, 0x00, 0x84, 0x44, 0x00, 0x00, 0x01, +0x4b, 0xe0, 0x20, 0x01, 0x04, 0x23, 0x80, 0x4c, 0x44, 0x51, 0x00, 0x00, 0x40, 0x11, 0x14, 0x02, +0x4e, 0x13, 0xff, 0xf6, 0x46, 0x86, 0x02, 0x00, 0x14, 0x14, 0x00, 0x40, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x07, 0x8c, 0x07, 0x46, 0x30, 0x01, 0x0a, 0x58, 0x31, 0x84, 0x8c, 0x4e, 0x03, 0x00, 0x08, +0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0xa8, 0x48, 0x00, 0x00, 0x06, 0x46, 0x10, 0x06, 0x10, +0x58, 0x10, 0x80, 0xa7, 0x44, 0x00, 0x00, 0xe8, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x0c, 0x01, +0x4e, 0x63, 0x00, 0x0a, 0x46, 0x06, 0x02, 0x00, 0x46, 0x14, 0x08, 0x00, 0x58, 0x00, 0x0d, 0x24, +0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x0a, 0x46, 0x06, 0x02, 0x01, +0x46, 0x14, 0x08, 0x00, 0x58, 0x00, 0x0d, 0x24, 0x14, 0x10, 0x00, 0x00, 0x47, 0xe6, 0x02, 0x00, +0x44, 0x40, 0x00, 0x20, 0x58, 0x7f, 0x00, 0x00, 0x14, 0x4f, 0x00, 0x40, 0x46, 0x80, 0x01, 0x03, +0x58, 0x84, 0x00, 0x84, 0x44, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x20, 0x01, 0x04, 0x33, 0x80, 0x4c, +0x44, 0x21, 0x00, 0x00, 0x40, 0x11, 0x88, 0x02, 0x4e, 0x13, 0xff, 0xf6, 0x46, 0x86, 0x02, 0x00, +0x14, 0x14, 0x00, 0x40, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x57, 0x8c, 0x07, 0x46, 0x30, 0x01, 0x0a, +0x58, 0x31, 0x84, 0x8c, 0x4e, 0x53, 0x00, 0x08, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0xe8, +0x48, 0x00, 0x00, 0x06, 0x46, 0x10, 0x06, 0x10, 0x58, 0x10, 0x80, 0xe7, 0x44, 0x00, 0x00, 0xe8, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x0c, 0x01, 0x4e, 0x63, 0x00, 0x0a, 0x46, 0x06, 0x02, 0x00, +0x46, 0x14, 0x10, 0x00, 0x58, 0x00, 0x0d, 0x24, 0x48, 0x00, 0x00, 0x0c, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x62, 0xc0, 0x0a, 0x46, 0x06, 0x02, 0x01, 0x46, 0x14, 0x10, 0x00, 0x58, 0x00, 0x0d, 0x24, +0x14, 0x10, 0x00, 0x00, 0x46, 0x76, 0x02, 0x00, 0x45, 0xe0, 0x00, 0x20, 0x15, 0xe3, 0x80, 0x40, +0x46, 0x80, 0x01, 0x03, 0x58, 0x84, 0x00, 0x84, 0x44, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x20, 0x01, +0x04, 0x43, 0x80, 0x4c, 0x44, 0x31, 0x00, 0x00, 0x40, 0x12, 0x0c, 0x02, 0x4e, 0x13, 0xff, 0xf6, +0x46, 0x76, 0x02, 0x00, 0x14, 0x13, 0x80, 0x40, 0x58, 0x03, 0x80, 0x00, 0x04, 0x10, 0x00, 0xa1, +0x50, 0x53, 0x00, 0xe4, 0x46, 0x70, 0x01, 0x12, 0x58, 0x73, 0x8c, 0x70, 0x38, 0x13, 0x96, 0x0a, +0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x85, 0xec, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x62, 0xc0, 0x08, 0x04, 0x43, 0x80, 0xe5, 0x47, 0xe6, 0x02, 0x01, 0x14, 0x4f, 0x00, 0xa1, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xaa, 0xbc, +0x51, 0xff, 0xff, 0xf4, 0x46, 0xf0, 0x01, 0x0f, 0x02, 0x17, 0x85, 0x0e, 0x58, 0x60, 0x00, 0x00, +0x14, 0x1f, 0x80, 0x01, 0x44, 0x80, 0x00, 0x00, 0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x84, 0x8c, +0x46, 0xa0, 0x01, 0x03, 0x58, 0xa5, 0x00, 0x84, 0x47, 0xc0, 0x01, 0x0a, 0x59, 0xce, 0x04, 0xc8, +0x04, 0x0f, 0x80, 0x01, 0x58, 0x13, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0b, 0x58, 0xf7, 0x8f, 0x6c, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x18, 0xf0, 0x92, 0x58, 0x10, 0x83, 0x00, 0x44, 0x00, 0x00, 0xc0, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x18, 0x10, 0xc6, 0x58, 0x10, 0x80, 0xfe, +0x44, 0x00, 0x00, 0x6c, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x4e, 0x83, 0x00, 0x08, +0x44, 0x00, 0x00, 0x70, 0x44, 0x10, 0x00, 0x80, 0x48, 0x00, 0x00, 0x1a, 0x44, 0x50, 0x00, 0x01, +0x4c, 0x82, 0xc0, 0x08, 0x44, 0x00, 0x00, 0x70, 0x44, 0x10, 0x00, 0x90, 0x48, 0x00, 0x00, 0x10, +0x44, 0x50, 0x00, 0x02, 0x4c, 0x82, 0xc0, 0x08, 0x44, 0x00, 0x00, 0x70, 0x44, 0x10, 0x00, 0xa0, +0x48, 0x00, 0x00, 0x06, 0x44, 0x00, 0x00, 0x70, 0x44, 0x10, 0x00, 0xb0, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0xcc, 0x44, 0x10, 0x80, 0x00, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0x07, 0x4b, 0xe0, 0x28, 0x01, 0x44, 0x90, 0x00, 0x00, +0x44, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x28, 0x01, 0x44, 0x00, 0x04, 0x04, 0x58, 0x13, 0x00, 0x00, +0x4b, 0xe0, 0x70, 0x01, 0x40, 0x40, 0x38, 0x08, 0x40, 0x42, 0x74, 0x09, 0x50, 0x94, 0x80, 0x01, +0x4e, 0x42, 0x00, 0x1c, 0x44, 0x50, 0x03, 0xe9, 0x4c, 0x92, 0xff, 0xec, 0x46, 0xf0, 0x01, 0x16, +0x00, 0x17, 0x8f, 0x29, 0x4e, 0x13, 0x00, 0x12, 0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x0e, 0x3c, +0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x87, 0x68, 0x44, 0x20, 0x0b, 0x3b, 0x46, 0xf0, 0x01, 0x00, +0x58, 0xf7, 0x83, 0x64, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0xcc, 0x44, 0x10, 0x00, 0x00, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x18, 0xf0, 0x92, 0x44, 0x00, 0x00, 0xc0, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0x6c, 0x44, 0x10, 0x00, 0x00, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0x70, 0x44, 0x10, 0x00, 0x00, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x50, 0x84, 0x00, 0x01, 0x44, 0x50, 0x00, 0x04, +0x4c, 0x82, 0xff, 0x60, 0x46, 0x80, 0x01, 0x0a, 0x58, 0x84, 0x04, 0xc8, 0x58, 0x13, 0x00, 0x00, +0x44, 0x00, 0x04, 0x6c, 0x4b, 0xe0, 0x20, 0x01, 0x46, 0x70, 0x01, 0x12, 0x58, 0x73, 0x8c, 0x70, +0x50, 0x33, 0x00, 0xe0, 0x38, 0x03, 0x8e, 0x0a, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x04, 0x70, +0x4b, 0xe0, 0x20, 0x01, 0x50, 0x63, 0x00, 0xe2, 0x38, 0x03, 0x9a, 0x0a, 0x51, 0xff, 0x80, 0x0c, +0x3a, 0x6f, 0xaa, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa4, 0xbc, 0x51, 0xff, 0xff, 0xfc, +0x58, 0x60, 0x00, 0x00, 0x58, 0x10, 0x00, 0x00, 0x44, 0x00, 0x00, 0x0f, 0x46, 0xf0, 0x01, 0x0b, +0x58, 0xf7, 0x8f, 0x6c, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x18, 0x80, 0x08, 0x46, 0x70, 0x01, 0x0a, +0x58, 0x73, 0x84, 0x8c, 0x58, 0x10, 0x82, 0xd0, 0x44, 0x00, 0x00, 0x44, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x0a, 0x44, 0x00, 0x06, 0x10, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, +0x44, 0x00, 0x00, 0x54, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x06, 0x1c, +0x44, 0x10, 0x00, 0x04, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x18, 0x20, 0x04, +0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0x80, 0x01, 0x03, 0x58, 0x84, 0x00, 0x84, 0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x84, 0xc8, +0x44, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x20, 0x01, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x04, 0x1c, +0x4b, 0xe0, 0x1c, 0x01, 0x40, 0x00, 0x70, 0x09, 0x4e, 0x03, 0xff, 0xf4, 0x46, 0x10, 0x20, 0x04, +0x58, 0x23, 0x00, 0x00, 0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, 0x46, 0xf0, 0x01, 0x0a, +0x58, 0xf7, 0x84, 0x8c, 0x4b, 0xe0, 0x3c, 0x01, 0x40, 0x33, 0x14, 0x08, 0x50, 0x81, 0x80, 0x38, +0x46, 0x20, 0x01, 0x12, 0x58, 0x21, 0x0c, 0x70, 0x40, 0x84, 0x08, 0x00, 0x44, 0x70, 0x04, 0x28, +0x46, 0x90, 0x01, 0x0a, 0x58, 0x94, 0x84, 0xc8, 0x58, 0x03, 0x80, 0x00, 0x58, 0x13, 0x00, 0x00, +0x4b, 0xe0, 0x24, 0x01, 0x50, 0x73, 0x80, 0x04, 0x44, 0x50, 0x04, 0x48, 0x1c, 0x04, 0x00, 0x01, +0x4c, 0x72, 0xff, 0xf4, 0x41, 0xe3, 0x14, 0x08, 0x46, 0x90, 0x01, 0x12, 0x58, 0x94, 0x8c, 0x70, +0x50, 0x5f, 0x00, 0x78, 0x40, 0x82, 0xa4, 0x00, 0x46, 0x90, 0x01, 0x0a, 0x58, 0x94, 0x84, 0xc8, +0x58, 0x03, 0x80, 0x00, 0x58, 0x13, 0x00, 0x00, 0x4b, 0xe0, 0x24, 0x01, 0x1c, 0x04, 0x00, 0x01, +0x50, 0x73, 0x80, 0x04, 0x44, 0x50, 0x04, 0x68, 0x4c, 0x72, 0xff, 0xf4, 0x46, 0x10, 0x24, 0x44, +0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x84, 0x8c, 0x58, 0x10, 0x84, 0x0b, 0x44, 0x00, 0x06, 0x10, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, +0x44, 0x00, 0x00, 0x54, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x06, 0x1c, +0x44, 0x10, 0x00, 0x00, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x18, 0x20, 0x04, +0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0x80, 0x01, 0x03, 0x58, 0x84, 0x00, 0x84, 0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x84, 0xc8, +0x44, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x20, 0x01, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x04, 0x1c, +0x4b, 0xe0, 0x1c, 0x01, 0x40, 0x20, 0x70, 0x09, 0x4e, 0x23, 0xff, 0xf4, 0x46, 0x10, 0x20, 0x04, +0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x0a, +0x58, 0xf7, 0x84, 0x8c, 0x4b, 0xe0, 0x3c, 0x01, 0x40, 0x43, 0x14, 0x08, 0x50, 0x82, 0x00, 0xb8, +0x46, 0x30, 0x01, 0x12, 0x58, 0x31, 0x8c, 0x70, 0x40, 0x84, 0x0c, 0x00, 0x44, 0x70, 0x06, 0xcc, +0x46, 0x90, 0x01, 0x0a, 0x58, 0x94, 0x84, 0xc8, 0x58, 0x03, 0x80, 0x00, 0x58, 0x13, 0x00, 0x00, +0x4b, 0xe0, 0x24, 0x01, 0x50, 0x73, 0x80, 0x04, 0x44, 0x50, 0x06, 0xec, 0x1c, 0x04, 0x00, 0x01, +0x4c, 0x72, 0xff, 0xf4, 0x46, 0x10, 0x24, 0x44, 0x46, 0x90, 0x01, 0x0a, 0x58, 0x94, 0x84, 0x8c, +0x58, 0x10, 0x84, 0x0b, 0x44, 0x00, 0x06, 0x10, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x24, 0x01, +0x46, 0x10, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, 0x44, 0x00, 0x00, 0x54, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x24, 0x01, 0x44, 0x00, 0x06, 0x1c, 0x44, 0x10, 0x00, 0x05, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x24, 0x01, 0x46, 0x18, 0x20, 0x04, 0x58, 0x10, 0x80, 0xc0, 0x44, 0x00, 0x00, 0xc8, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x24, 0x01, 0x46, 0x80, 0x01, 0x03, 0x58, 0x84, 0x00, 0x84, +0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x84, 0xc8, 0x44, 0x00, 0x00, 0x01, 0x4b, 0xe0, 0x20, 0x01, +0x44, 0x00, 0x04, 0x1c, 0x58, 0x13, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x40, 0x00, 0x70, 0x09, +0x4e, 0x03, 0xff, 0xf4, 0x46, 0x10, 0x20, 0x04, 0x58, 0x10, 0x80, 0xc0, 0x40, 0x83, 0x14, 0x08, +0x44, 0x00, 0x00, 0xc8, 0x58, 0x23, 0x00, 0x00, 0x50, 0x74, 0x00, 0xf8, 0x46, 0xf0, 0x01, 0x0a, +0x58, 0xf7, 0x84, 0x8c, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x10, 0x01, 0x12, 0x58, 0x10, 0x8c, 0x70, +0x40, 0x83, 0x84, 0x00, 0x46, 0x90, 0x01, 0x0a, 0x58, 0x94, 0x84, 0xc8, 0x44, 0x70, 0x06, 0xcc, +0x58, 0x03, 0x80, 0x00, 0x58, 0x13, 0x00, 0x00, 0x4b, 0xe0, 0x24, 0x01, 0x50, 0x73, 0x80, 0x04, +0x44, 0x50, 0x06, 0xec, 0x1c, 0x04, 0x00, 0x01, 0x4c, 0x72, 0xff, 0xf4, 0x46, 0xf0, 0x01, 0x0f, +0x01, 0xe7, 0x8c, 0x06, 0x4f, 0xe2, 0x00, 0x6a, 0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x0a, +0x46, 0x90, 0x01, 0x0a, 0x58, 0x94, 0x84, 0x8c, 0x44, 0x00, 0x06, 0x10, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x24, 0x01, 0x46, 0x18, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, 0x44, 0x00, 0x00, 0x54, +0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x24, 0x01, 0x44, 0x70, 0x00, 0x00, 0x46, 0x80, 0x01, 0x0b, +0x58, 0x84, 0x0c, 0x50, 0x58, 0x23, 0x80, 0x00, 0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x00, +0x4b, 0xe0, 0x20, 0x01, 0x50, 0x73, 0x80, 0x01, 0x44, 0x50, 0x00, 0x10, 0x4c, 0x72, 0xff, 0xf4, +0x44, 0x70, 0x00, 0x00, 0x46, 0x80, 0x01, 0x0b, 0x58, 0x84, 0x0c, 0x50, 0x58, 0x23, 0x80, 0x00, +0x58, 0x03, 0x00, 0x00, 0x44, 0x10, 0x00, 0x01, 0x4b, 0xe0, 0x20, 0x01, 0x50, 0x73, 0x80, 0x01, +0x44, 0x50, 0x00, 0x10, 0x4c, 0x72, 0xff, 0xf4, 0x40, 0x13, 0x14, 0x08, 0x46, 0x70, 0x01, 0x12, +0x58, 0x73, 0x8c, 0x70, 0x50, 0x20, 0x81, 0x38, 0x40, 0x81, 0x1c, 0x00, 0x46, 0x90, 0x01, 0x0a, +0x58, 0x94, 0x84, 0xc8, 0x44, 0x70, 0x04, 0x28, 0x58, 0x03, 0x80, 0x00, 0x58, 0x13, 0x00, 0x00, +0x4b, 0xe0, 0x24, 0x01, 0x14, 0x04, 0x00, 0x00, 0x58, 0x13, 0x00, 0x00, 0x50, 0x03, 0x80, 0x20, +0x4b, 0xe0, 0x24, 0x01, 0x50, 0x73, 0x80, 0x04, 0x44, 0x50, 0x04, 0x48, 0x14, 0x04, 0x00, 0x10, +0x50, 0x84, 0x00, 0x04, 0x4c, 0x72, 0xff, 0xea, 0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x84, 0x8c, +0x44, 0x00, 0x00, 0x44, 0x44, 0x10, 0x82, 0xd0, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x4e, 0x63, 0x00, 0x14, 0x46, 0xf0, 0x01, 0x0f, 0x01, 0xe7, 0x8a, 0x1e, 0x4f, 0xe2, 0x00, 0x04, +0x48, 0x00, 0x00, 0x16, 0x46, 0x10, 0x24, 0x44, 0x58, 0x10, 0x84, 0x08, 0x58, 0x23, 0x00, 0x00, +0x44, 0x00, 0x06, 0x10, 0x48, 0x00, 0x00, 0x24, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x2c, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, 0x8a, 0x1f, 0x4e, 0x02, 0x00, 0x12, 0x46, 0x10, 0x24, 0x44, +0x58, 0x10, 0x84, 0x00, 0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x06, 0x10, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0x10, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, 0x48, 0x00, 0x00, 0x10, 0x46, 0x10, 0x24, 0x44, +0x58, 0x10, 0x84, 0x08, 0x44, 0x00, 0x06, 0x10, 0x58, 0x23, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0x18, 0x3f, 0xf0, 0x58, 0x10, 0x80, 0x03, 0x44, 0x00, 0x00, 0x54, 0x58, 0x23, 0x00, 0x00, +0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x84, 0x8c, 0x58, 0x23, 0x00, 0x00, +0x44, 0x00, 0x00, 0xa0, 0x44, 0x16, 0xf5, 0xfe, 0x4b, 0xe0, 0x1c, 0x01, 0x58, 0x23, 0x00, 0x00, +0x44, 0x00, 0x00, 0x70, 0x44, 0x10, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0x20, 0x04, +0x58, 0x10, 0x80, 0xc0, 0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x00, 0xc8, 0x4b, 0xe0, 0x1c, 0x01, +0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa0, 0xbc, +0x44, 0x60, 0x00, 0x00, 0x58, 0x80, 0x00, 0x00, 0x46, 0x70, 0x01, 0x0b, 0x58, 0x73, 0x8f, 0x6c, +0x50, 0x63, 0x00, 0x01, 0x58, 0x03, 0x00, 0x00, 0x58, 0x14, 0x00, 0x00, 0x4b, 0xe0, 0x1c, 0x01, +0x44, 0x50, 0x00, 0x0e, 0x4c, 0x62, 0xff, 0xf6, 0x3a, 0x6f, 0xa0, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x3a, 0x6f, 0xaa, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x58, 0x60, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x08, +0x58, 0xf7, 0x87, 0xa4, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x10, 0x13, 0x12, 0x58, 0x50, 0x8d, 0x00, +0x4c, 0x02, 0xc0, 0x06, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x18, 0x46, 0x20, 0x17, 0xd7, +0x58, 0x51, 0x08, 0x40, 0x4c, 0x02, 0xc0, 0x06, 0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x0e, +0x46, 0x30, 0x26, 0x25, 0x58, 0x51, 0x8a, 0x00, 0x4c, 0x02, 0x80, 0x06, 0x44, 0x80, 0x00, 0x00, +0x48, 0x00, 0x00, 0x0a, 0x44, 0x00, 0x00, 0x02, 0x46, 0x40, 0x01, 0x0e, 0x58, 0x42, 0x0e, 0xbc, +0x38, 0x82, 0x03, 0x02, 0x50, 0x54, 0x00, 0x01, 0x40, 0x82, 0x8c, 0x08, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x0e, 0xf8, 0x40, 0x84, 0x00, 0x00, 0x46, 0xa0, 0x01, 0x12, 0x58, 0xa5, 0x0c, 0x70, +0x46, 0x90, 0x01, 0x0a, 0x58, 0x94, 0x84, 0xc8, 0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x84, 0x8c, +0x47, 0xc0, 0x01, 0x03, 0x59, 0xce, 0x00, 0x84, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x00, 0xb0, +0x4b, 0xe0, 0x24, 0x01, 0x02, 0x54, 0x00, 0x00, 0x44, 0x43, 0xff, 0xf0, 0x40, 0x32, 0x90, 0x08, +0x44, 0x2c, 0x00, 0x0f, 0x40, 0x11, 0x90, 0x02, 0x40, 0x00, 0x08, 0x02, 0x40, 0x10, 0x04, 0x04, +0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x00, 0xb0, 0x4b, 0xe0, 0x1c, 0x01, 0x58, 0x13, 0x00, 0x00, +0x44, 0x00, 0x01, 0x0c, 0x4b, 0xe0, 0x24, 0x01, 0x02, 0x54, 0x00, 0x01, 0x46, 0x2c, 0x00, 0xff, +0x46, 0x43, 0xff, 0x00, 0x40, 0x32, 0xd0, 0x08, 0x58, 0x21, 0x0f, 0xff, 0x40, 0x11, 0x90, 0x02, +0x40, 0x00, 0x08, 0x02, 0x40, 0x10, 0x04, 0x04, 0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x01, 0x0c, +0x4b, 0xe0, 0x1c, 0x01, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x01, 0x0c, 0x4b, 0xe0, 0x24, 0x01, +0x04, 0x44, 0x00, 0x01, 0x40, 0x30, 0x50, 0x09, 0x40, 0x31, 0xd0, 0x08, 0x40, 0x12, 0x30, 0x08, +0x40, 0x10, 0xb0, 0x09, 0x40, 0x11, 0x84, 0x04, 0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x01, 0x0c, +0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0xf8, 0x00, 0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x01, 0x10, +0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x1f, 0xfe, 0x04, 0x58, 0x10, 0x80, 0x10, 0x58, 0x23, 0x00, 0x00, +0x44, 0x00, 0x00, 0xb4, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0x64, 0x4b, 0xe0, 0x70, 0x01, +0x46, 0x13, 0xff, 0x0c, 0x58, 0x10, 0x80, 0x10, 0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x00, 0xb4, +0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0xb0, 0x00, 0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x01, 0x10, +0x4b, 0xe0, 0x1c, 0x01, 0x4e, 0x63, 0x00, 0x10, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x04, 0x20, +0x4b, 0xe0, 0x24, 0x01, 0x54, 0x00, 0x7f, 0x00, 0x40, 0x10, 0x20, 0x09, 0x12, 0x15, 0x00, 0x00, +0x48, 0x00, 0x00, 0x12, 0x44, 0x50, 0x00, 0x01, 0x4c, 0x62, 0xc0, 0x0e, 0x44, 0x00, 0x04, 0x20, +0x58, 0x13, 0x00, 0x00, 0x4b, 0xe0, 0x24, 0x01, 0x54, 0x40, 0x7f, 0x00, 0x40, 0x32, 0x20, 0x09, +0x12, 0x35, 0x00, 0x0e, 0x50, 0xa5, 0x00, 0x02, 0x46, 0x50, 0x01, 0x12, 0x58, 0x52, 0x8c, 0x8e, +0x50, 0x84, 0x00, 0x20, 0x4c, 0xa2, 0xff, 0x62, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0xaa, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0xa8, 0xbc, 0x58, 0x60, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x08, +0x58, 0xf7, 0x87, 0xa4, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x10, 0x17, 0xd7, 0x58, 0x50, 0x88, 0x40, +0x4c, 0x02, 0xc0, 0x08, 0x44, 0x70, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x1e, +0x46, 0x20, 0x26, 0x25, 0x58, 0x51, 0x0a, 0x00, 0x4c, 0x02, 0xc0, 0x08, 0x44, 0x70, 0x00, 0x09, +0x44, 0x00, 0x00, 0x02, 0x48, 0x00, 0x00, 0x12, 0x46, 0x30, 0x13, 0x12, 0x58, 0x51, 0x8d, 0x00, +0x4c, 0x02, 0x80, 0x08, 0x44, 0x70, 0x00, 0x04, 0x44, 0x90, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0c, +0x44, 0x70, 0x00, 0x04, 0x44, 0x00, 0x00, 0x00, 0x46, 0x40, 0x01, 0x0e, 0x58, 0x42, 0x0e, 0xbc, +0x38, 0x92, 0x03, 0x02, 0x46, 0xf0, 0x01, 0x0f, 0x02, 0x27, 0x85, 0x0e, 0x46, 0x10, 0x01, 0x0e, +0x58, 0x10, 0x8e, 0xf8, 0x44, 0x00, 0x00, 0x00, 0x02, 0x50, 0x80, 0x00, 0x50, 0x10, 0x80, 0x20, +0x4c, 0x51, 0x40, 0x06, 0x58, 0xa0, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0a, 0x50, 0x00, 0x00, 0x01, +0x44, 0x50, 0x00, 0x0f, 0x4c, 0x02, 0xff, 0xf2, 0x44, 0xa0, 0x00, 0x00, 0x46, 0x80, 0x01, 0x0a, +0x58, 0x84, 0x04, 0xc8, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x00, 0xb0, 0x4b, 0xe0, 0x20, 0x01, +0x40, 0x00, 0x10, 0x09, 0x40, 0x00, 0x10, 0x08, 0x40, 0x10, 0x1c, 0x04, 0x58, 0x23, 0x00, 0x00, +0x46, 0x70, 0x01, 0x0a, 0x58, 0x73, 0x84, 0x8c, 0x44, 0x00, 0x00, 0xb0, 0x40, 0xa5, 0x08, 0x08, +0x4b, 0xe0, 0x1c, 0x01, 0x40, 0x95, 0x24, 0x00, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x00, 0xb0, +0x4b, 0xe0, 0x20, 0x01, 0x50, 0x94, 0x80, 0x01, 0x46, 0x40, 0x01, 0x0e, 0x58, 0x42, 0x0e, 0xf8, +0x38, 0x12, 0x27, 0x01, 0x44, 0x33, 0xff, 0xf0, 0x40, 0x50, 0x90, 0x08, 0x44, 0x2c, 0x00, 0x0f, +0x40, 0x42, 0x8c, 0x02, 0x40, 0x00, 0x08, 0x02, 0x40, 0x10, 0x10, 0x04, 0x58, 0x23, 0x00, 0x00, +0x44, 0x00, 0x00, 0xb0, 0x4b, 0xe0, 0x1c, 0x01, 0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x01, 0x0c, +0x4b, 0xe0, 0x20, 0x01, 0x40, 0x94, 0x8c, 0x08, 0x46, 0x10, 0x01, 0x0e, 0x58, 0x10, 0x8e, 0xf8, +0x40, 0x94, 0x84, 0x00, 0x02, 0x34, 0x80, 0x01, 0x46, 0x2c, 0x00, 0xff, 0x46, 0x53, 0xff, 0x00, +0x40, 0x41, 0xd0, 0x08, 0x58, 0x21, 0x0f, 0xff, 0x40, 0x12, 0x14, 0x02, 0x40, 0x00, 0x08, 0x02, +0x40, 0x10, 0x04, 0x04, 0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x01, 0x0c, 0x4b, 0xe0, 0x1c, 0x01, +0x58, 0x13, 0x00, 0x00, 0x44, 0x00, 0x01, 0x0c, 0x4b, 0xe0, 0x20, 0x01, 0x04, 0x54, 0x80, 0x01, +0x40, 0x40, 0x50, 0x09, 0x40, 0x42, 0x50, 0x08, 0x40, 0x12, 0xb0, 0x08, 0x40, 0x10, 0xb0, 0x09, +0x40, 0x12, 0x04, 0x04, 0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x01, 0x0c, 0x4b, 0xe0, 0x1c, 0x01, +0x46, 0x10, 0x03, 0x00, 0x58, 0x23, 0x00, 0x00, 0x58, 0x10, 0x80, 0x88, 0x44, 0x00, 0x07, 0xdc, +0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0xf8, 0x00, 0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x01, 0x10, +0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x1f, 0xfe, 0x04, 0x58, 0x23, 0x00, 0x00, 0x58, 0x10, 0x80, 0x10, +0x44, 0x00, 0x00, 0xb4, 0x4b, 0xe0, 0x1c, 0x01, 0x44, 0x00, 0x00, 0x64, 0x46, 0xf0, 0x01, 0x03, +0x58, 0xf7, 0x80, 0x84, 0x4b, 0xe0, 0x3c, 0x01, 0x46, 0x13, 0xfe, 0x0c, 0x58, 0x23, 0x00, 0x00, +0x58, 0x10, 0x80, 0x10, 0x44, 0x00, 0x00, 0xb4, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0xb0, 0x00, +0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x01, 0x10, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x10, 0x03, 0x00, +0x58, 0x10, 0x80, 0x08, 0x58, 0x23, 0x00, 0x00, 0x44, 0x00, 0x07, 0xdc, 0x4b, 0xe0, 0x1c, 0x01, +0x3a, 0x6f, 0xa8, 0x84, 0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x98, 0xbc, 0x58, 0x60, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x0d, 0x58, 0xf7, 0x8f, 0xc4, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x03, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x0b, 0x58, 0xf7, 0x8d, 0xa0, 0x4b, 0xe0, 0x3c, 0x01, 0x58, 0x03, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x0d, 0x58, 0xf7, 0x8d, 0xe0, 0x4b, 0xe0, 0x3c, 0x01, 0x3a, 0x6f, 0x98, 0x84, +0x4a, 0x00, 0x78, 0x20, 0x3a, 0x6f, 0x9c, 0xbc, 0x51, 0xff, 0xff, 0xfc, 0x46, 0x38, 0x00, 0x21, +0x04, 0x01, 0x80, 0x04, 0x54, 0x00, 0x00, 0x03, 0x44, 0x50, 0x00, 0x02, 0x46, 0xf0, 0x01, 0x0f, +0x14, 0x07, 0x83, 0x02, 0x4c, 0x02, 0x80, 0x10, 0x44, 0x50, 0x00, 0x03, 0x4c, 0x02, 0x80, 0x12, +0x46, 0x00, 0x13, 0x12, 0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x8c, 0x0c, 0x58, 0x00, 0x0d, 0x00, +0x48, 0x00, 0x00, 0x10, 0x46, 0x00, 0x17, 0xd7, 0x58, 0x00, 0x08, 0x40, 0x48, 0x00, 0x00, 0x06, +0x46, 0x00, 0x26, 0x25, 0x58, 0x00, 0x0a, 0x00, 0x46, 0x10, 0x01, 0x0f, 0x58, 0x10, 0x8c, 0x0c, +0x14, 0x00, 0x80, 0x00, 0x44, 0x70, 0x00, 0x00, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x8a, 0xdc, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x17, 0x89, 0xb4, 0x54, 0x50, 0x80, 0x02, +0x46, 0xf0, 0x01, 0x0f, 0x10, 0x77, 0x8c, 0x05, 0x4e, 0x52, 0x00, 0x08, 0x44, 0x00, 0x00, 0x01, +0x46, 0xf0, 0x01, 0x0f, 0x10, 0x07, 0x8c, 0x07, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x07, 0x89, 0xb5, +0x54, 0x30, 0x00, 0x04, 0x4e, 0x32, 0x00, 0x06, 0x44, 0x20, 0x00, 0x00, 0x48, 0x00, 0x00, 0x04, +0x44, 0x20, 0x00, 0x01, 0x54, 0x50, 0x00, 0x08, 0x46, 0xf0, 0x01, 0x0f, 0x10, 0x27, 0x8a, 0x1e, +0x4e, 0x52, 0x00, 0x06, 0x44, 0x10, 0x00, 0x00, 0x48, 0x00, 0x00, 0x04, 0x44, 0x10, 0x00, 0x01, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x67, 0x89, 0xd6, 0x46, 0xf0, 0x01, 0x0f, 0x10, 0x17, 0x8a, 0x1f, +0x54, 0x03, 0x00, 0x1f, 0x4e, 0x02, 0x00, 0x08, 0x44, 0x20, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x0f, +0x10, 0x27, 0x8c, 0x06, 0x46, 0xf0, 0x01, 0x0f, 0x01, 0xe7, 0x89, 0xd9, 0x44, 0x50, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x0f, 0x10, 0x57, 0x8c, 0x03, 0x46, 0xf0, 0x01, 0x0f, 0x10, 0x07, 0x8c, 0x02, +0x54, 0x6f, 0x00, 0x1f, 0x4e, 0x03, 0x00, 0x06, 0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x04, +0x44, 0x00, 0x00, 0x02, 0x46, 0xf0, 0x01, 0x0f, 0x10, 0x07, 0x8c, 0x04, 0x46, 0xf0, 0x01, 0x0f, +0x00, 0x17, 0x8c, 0x04, 0x50, 0x70, 0xff, 0xff, 0x54, 0x03, 0x80, 0xff, 0x5c, 0xf0, 0x00, 0x04, +0x4e, 0xf3, 0x00, 0x12, 0x46, 0xf0, 0x01, 0x16, 0x01, 0xe7, 0x8f, 0x29, 0x4f, 0xe3, 0x00, 0x0c, +0x46, 0x00, 0x01, 0x0e, 0x58, 0x00, 0x0e, 0x94, 0x46, 0xf0, 0x01, 0x00, 0x58, 0xf7, 0x83, 0x64, +0x4b, 0xe0, 0x3c, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x00, 0x17, 0x8a, 0x1e, 0x4e, 0x13, 0x00, 0x0a, +0x4e, 0x62, 0x00, 0x08, 0x44, 0x00, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x10, 0x07, 0x8c, 0x20, +0x46, 0xf0, 0x01, 0x0f, 0x00, 0x77, 0x8a, 0x1f, 0x4e, 0x73, 0x00, 0x0a, 0x4e, 0x62, 0x00, 0x08, +0x45, 0xe0, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x0f, 0x11, 0xe7, 0x8c, 0x21, 0x46, 0x00, 0x01, 0x0e, +0x58, 0x00, 0x0e, 0xbc, 0x46, 0xf0, 0x01, 0x0f, 0x04, 0x17, 0x83, 0x03, 0x04, 0x50, 0x00, 0x01, +0x4c, 0x12, 0xc0, 0x06, 0x44, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x10, 0x04, 0x50, 0x00, 0x03, +0x4c, 0x12, 0xc0, 0x06, 0x44, 0x00, 0x00, 0x01, 0x48, 0x00, 0x00, 0x08, 0x04, 0x50, 0x00, 0x05, +0x4c, 0x12, 0xc0, 0x0e, 0x44, 0x00, 0x00, 0x02, 0x46, 0x20, 0x01, 0x0e, 0x58, 0x21, 0x0e, 0xbc, +0x38, 0x71, 0x03, 0x02, 0x46, 0xf0, 0x01, 0x0f, 0x14, 0x77, 0x83, 0x04, 0x46, 0x00, 0x01, 0x0f, +0x58, 0x00, 0x0c, 0x18, 0x44, 0x20, 0x00, 0x02, 0x44, 0x10, 0x00, 0x07, 0x46, 0xf0, 0x01, 0x0f, +0x14, 0x17, 0x83, 0x05, 0x14, 0x20, 0x00, 0x00, 0x46, 0x48, 0x00, 0x21, 0x05, 0xe2, 0x00, 0x04, +0x42, 0x6f, 0x60, 0x0b, 0x4e, 0x62, 0x00, 0x08, 0x44, 0x70, 0x00, 0x01, 0x14, 0x70, 0x00, 0x00, +0x48, 0x00, 0x00, 0x04, 0x14, 0x20, 0x00, 0x00, 0x44, 0x60, 0x00, 0x07, 0x44, 0x70, 0x00, 0x00, +0x46, 0xf0, 0x01, 0x0f, 0x12, 0x67, 0x85, 0x0e, 0x46, 0xf0, 0x01, 0x0f, 0x12, 0x67, 0x85, 0xfc, +0x46, 0xf0, 0x01, 0x0f, 0x12, 0x67, 0x85, 0xfd, 0x46, 0xf0, 0x01, 0x0f, 0x14, 0x77, 0x82, 0xff, +0x46, 0xf0, 0x01, 0x0a, 0x58, 0xf7, 0x8d, 0xe8, 0x4b, 0xe0, 0x3c, 0x01, 0x44, 0x00, 0x00, 0x21, +0x44, 0x30, 0x00, 0x0a, 0x46, 0xf0, 0x01, 0x0f, 0x10, 0x07, 0x8c, 0x1c, 0x46, 0xf0, 0x01, 0x0f, +0x10, 0x67, 0x8c, 0x1f, 0x46, 0xf0, 0x01, 0x0f, 0x10, 0x37, 0x8c, 0x1d, 0x46, 0xf0, 0x01, 0x0f, +0x04, 0x67, 0x83, 0x06, 0x46, 0x28, 0x08, 0x08, 0x46, 0x00, 0x01, 0x12, 0x58, 0x00, 0x0f, 0xa0, +0x46, 0xf0, 0x01, 0x0f, 0x10, 0x37, 0x8c, 0x1e, 0x58, 0x21, 0x00, 0x80, 0x58, 0x33, 0x80, 0x00, +0x50, 0x10, 0x00, 0x30, 0x44, 0x50, 0x08, 0x00, 0x58, 0x43, 0x80, 0x00, 0x44, 0x70, 0x00, 0x01, +0x4c, 0x63, 0xc0, 0x04, 0x4c, 0x33, 0x00, 0x20, 0x50, 0x31, 0x80, 0x01, 0x44, 0x70, 0x00, 0x02, +0x14, 0x50, 0x00, 0x00, 0x14, 0x40, 0x00, 0x01, 0x14, 0x40, 0x00, 0x02, 0x14, 0x20, 0x80, 0x00, +0x14, 0x20, 0x80, 0x01, 0x14, 0x50, 0x00, 0x06, 0x14, 0x40, 0x00, 0x07, 0x14, 0x40, 0x00, 0x08, +0x14, 0x20, 0x80, 0x04, 0x14, 0x20, 0x80, 0x05, 0x50, 0x00, 0x00, 0x0c, 0x50, 0x10, 0x80, 0x08, +0x4c, 0x33, 0xff, 0xde, 0x51, 0xff, 0x80, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0x4a, 0x00, 0x78, 0x20, +0x0a, 0x0a, 0x0a, 0x20, 0x55, 0x41, 0x52, 0x54, 0x20, 0x58, 0x54, 0x52, 0x4c, 0x28, 0x25, 0x64, +0x29, 0x48, 0x7a, 0x20, 0x42, 0x61, 0x75, 0x64, 0x20, 0x52, 0x61, 0x74, 0x65, 0x20, 0x28, 0x25, +0x64, 0x29, 0x62, 0x70, 0x73, 0x20, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x42, 0x75, +0x69, 0x6c, 0x64, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x54, 0x49, 0x4d, 0x45, 0x20, 0x25, 0x73, +0x20, 0x25, 0x73, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x4d, 0x61, 0x72, 0x20, 0x31, 0x33, 0x20, 0x32, +0x30, 0x31, 0x34, 0x00, 0x32, 0x31, 0x3a, 0x35, 0x34, 0x3a, 0x33, 0x31, 0x00, 0x00, 0x00, 0x00, +0x52, 0x41, 0x4d, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, +0x20, 0x43, 0x4d, 0x44, 0x20, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x44, 0x6f, 0x77, +0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x66, 0x6c, 0x6f, 0x77, 0x0a, 0x00, 0x52, 0x45, 0x47, 0x33, +0x32, 0x28, 0x53, 0x59, 0x53, 0x5f, 0x54, 0x4f, 0x50, 0x5f, 0x4d, 0x49, 0x53, 0x43, 0x32, 0x29, +0x20, 0x3d, 0x20, 0x30, 0x78, 0x25, 0x78, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x2b, 0x2b, 0x2b, 0x2b, +0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x6f, 0x66, 0x66, 0x2c, 0x20, 0x4c, 0x65, 0x64, 0x4e, +0x6f, 0x3a, 0x25, 0x64, 0x2c, 0x20, 0x70, 0x6f, 0x6c, 0x61, 0x72, 0x3a, 0x25, 0x64, 0x20, 0x2b, +0x2b, 0x2b, 0x2b, 0x2b, 0x20, 0x0a, 0x00, 0x00, 0x25, 0x73, 0x0a, 0x00, 0x2b, 0x2b, 0x2b, 0x2b, +0x2b, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, +0x00, 0x00, 0x00, 0x00, 0x75, 0x34, 0x4c, 0x65, 0x64, 0x43, 0x6e, 0x74, 0x3a, 0x25, 0x64, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x4c, 0x65, 0x64, 0x43, 0x74, 0x72, 0x6c, 0x3a, 0x30, 0x78, 0x25, 0x78, +0x20, 0x0a, 0x00, 0x00, 0x4c, 0x65, 0x64, 0x4e, 0x6f, 0x3a, 0x25, 0x64, 0x2c, 0x20, 0x4c, 0x65, +0x64, 0x43, 0x74, 0x72, 0x6c, 0x3a, 0x25, 0x64, 0x2c, 0x20, 0x66, 0x69, 0x78, 0x50, 0x6f, 0x6c, +0x61, 0x72, 0x3a, 0x25, 0x64, 0x2c, 0x20, 0x74, 0x78, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x3a, 0x25, +0x64, 0x2c, 0x20, 0x4f, 0x76, 0x65, 0x72, 0x46, 0x69, 0x78, 0x3a, 0x25, 0x64, 0x20, 0x0a, 0x00, +0x4c, 0x45, 0x44, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x5f, 0x57, 0x50, 0x53, 0x5f, +0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x4f, 0x4e, 0x5f, 0x35, 0x53, 0x5f, 0x4f, 0x46, +0x46, 0x5f, 0x33, 0x53, 0x20, 0x0a, 0x00, 0x00, 0x4c, 0x45, 0x44, 0x5f, 0x54, 0x49, 0x4d, 0x45, +0x4f, 0x55, 0x54, 0x5f, 0x57, 0x50, 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, +0x4f, 0x4e, 0x5f, 0x35, 0x53, 0x5f, 0x4f, 0x46, 0x46, 0x5f, 0x33, 0x53, 0x5f, 0x54, 0x58, 0x5f, +0x42, 0x4c, 0x49, 0x4e, 0x4b, 0x20, 0x0a, 0x00, 0x4c, 0x45, 0x44, 0x5f, 0x54, 0x49, 0x4d, 0x45, +0x4f, 0x55, 0x54, 0x5f, 0x57, 0x50, 0x53, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, +0x4f, 0x4e, 0x5f, 0x35, 0x53, 0x5f, 0x4f, 0x46, 0x46, 0x20, 0x0a, 0x00, 0x61, 0x73, 0x73, 0x65, +0x72, 0x74, 0x65, 0x64, 0x21, 0x20, 0x5b, 0x25, 0x73, 0x2c, 0x20, 0x25, 0x64, 0x5d, 0x0a, 0x00, +0x73, 0x72, 0x63, 0x2f, 0x77, 0x69, 0x66, 0x69, 0x5f, 0x75, 0x6e, 0x69, 0x5f, 0x6d, 0x61, 0x63, +0x2f, 0x52, 0x4f, 0x4d, 0x2f, 0x6e, 0x69, 0x63, 0x2f, 0x68, 0x61, 0x6c, 0x2f, 0x4d, 0x54, 0x37, +0x36, 0x30, 0x33, 0x2f, 0x68, 0x61, 0x6c, 0x5f, 0x72, 0x6f, 0x6d, 0x2e, 0x63, 0x00, 0x00, 0x00, +0x68, 0x61, 0x6c, 0x54, 0x78, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x54, 0x78, 0x54, 0x69, 0x6d, +0x65, 0x6f, 0x75, 0x74, 0x3a, 0x20, 0x48, 0x54, 0x20, 0x72, 0x61, 0x74, 0x65, 0x20, 0x77, 0x6f, +0x75, 0x6c, 0x64, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x20, 0x4f, 0x46, 0x44, 0x4d, 0x20, +0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x0a, 0x00, +0x68, 0x61, 0x6c, 0x4d, 0x61, 0x63, 0x54, 0x78, 0x53, 0x74, 0x6f, 0x70, 0x41, 0x63, 0x51, 0x75, +0x65, 0x75, 0x65, 0x57, 0x69, 0x74, 0x68, 0x50, 0x6f, 0x6c, 0x6c, 0x44, 0x6f, 0x6e, 0x65, 0x3a, +0x20, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, +0x20, 0x71, 0x75, 0x65, 0x75, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x20, 0x64, 0x6f, 0x6e, 0x65, +0x0a, 0x00, 0x00, 0x00, 0x65, 0x6d, 0x75, 0x6c, 0x54, 0x78, 0x53, 0x74, 0x6f, 0x70, 0x51, 0x75, +0x65, 0x75, 0x65, 0x3a, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x20, 0x77, 0x61, 0x69, +0x74, 0x69, 0x6e, 0x67, 0x20, 0x71, 0x75, 0x65, 0x75, 0x65, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x20, +0x64, 0x6f, 0x6e, 0x65, 0x0a, 0x00, 0x00, 0x00, 0x73, 0x72, 0x63, 0x2f, 0x77, 0x69, 0x66, 0x69, +0x5f, 0x75, 0x6e, 0x69, 0x5f, 0x6d, 0x61, 0x63, 0x2f, 0x52, 0x4f, 0x4d, 0x2f, 0x6e, 0x69, 0x63, +0x2f, 0x68, 0x61, 0x6c, 0x2f, 0x4d, 0x54, 0x37, 0x36, 0x30, 0x33, 0x2f, 0x68, 0x61, 0x6c, 0x5f, +0x70, 0x77, 0x72, 0x5f, 0x6d, 0x67, 0x74, 0x5f, 0x72, 0x6f, 0x6d, 0x2e, 0x63, 0x00, 0x00, 0x00, +0x4d, 0x43, 0x55, 0x20, 0x51, 0x31, 0x20, 0x69, 0x6e, 0x0a, 0x00, 0x00, 0x73, 0x72, 0x63, 0x2f, +0x77, 0x69, 0x66, 0x69, 0x5f, 0x75, 0x6e, 0x69, 0x5f, 0x6d, 0x61, 0x63, 0x2f, 0x6d, 0x67, 0x6d, +0x74, 0x2f, 0x63, 0x6e, 0x6d, 0x5f, 0x6d, 0x65, 0x6d, 0x2e, 0x63, 0x00, 0x73, 0x72, 0x63, 0x2f, +0x77, 0x69, 0x66, 0x69, 0x5f, 0x75, 0x6e, 0x69, 0x5f, 0x6d, 0x61, 0x63, 0x2f, 0x6d, 0x67, 0x6d, +0x74, 0x2f, 0x63, 0x6e, 0x6d, 0x2e, 0x63, 0x00, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x5f, 0x43, 0x48, +0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, 0x45, 0x4a, 0x45, 0x43, 0x54, 0x20, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x73, 0x72, 0x63, 0x2f, 0x77, 0x69, 0x66, 0x69, 0x5f, 0x75, 0x6e, 0x69, +0x5f, 0x6d, 0x61, 0x63, 0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x2f, 0x74, 0x78, 0x6d, 0x2e, 0x63, 0x00, +0x54, 0x58, 0x44, 0x3a, 0x25, 0x64, 0x0a, 0x00, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x3c, +0x44, 0x75, 0x6d, 0x70, 0x20, 0x50, 0x53, 0x45, 0x20, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3e, +0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x00, 0x46, 0x72, 0x65, 0x65, 0x20, 0x51, 0x20, 0x43, +0x6e, 0x74, 0x3a, 0x20, 0x5b, 0x25, 0x75, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x43, 0x50, 0x55, 0x20, +0x51, 0x20, 0x4c, 0x65, 0x6e, 0x20, 0x5b, 0x25, 0x75, 0x3a, 0x25, 0x75, 0x3a, 0x25, 0x75, 0x3a, +0x25, 0x75, 0x5d, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, +0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, +0x2d, 0x2d, 0x0a, 0x00, 0x52, 0x53, 0x56, 0x2f, 0x53, 0x52, 0x43, 0x20, 0x48, 0x49, 0x46, 0x5b, +0x25, 0x75, 0x2f, 0x25, 0x75, 0x5d, 0x20, 0x43, 0x50, 0x55, 0x5b, 0x25, 0x75, 0x2f, 0x25, 0x75, +0x5d, 0x20, 0x52, 0x58, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x5b, 0x25, 0x75, 0x2f, 0x25, 0x75, 0x5d, +0x20, 0x52, 0x58, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5b, 0x25, 0x75, 0x2f, 0x25, 0x75, +0x5d, 0x0a, 0x00, 0x00, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, +0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x73, 0x72, 0x63, 0x2f, 0x77, 0x69, 0x66, 0x69, 0x5f, 0x75, 0x6e, 0x69, +0x5f, 0x6d, 0x61, 0x63, 0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x2f, 0x72, 0x78, 0x6d, 0x2e, 0x63, 0x00, +0x72, 0x78, 0x6d, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x4d, 0x61, 0x63, 0x52, 0x78, 0x44, 0x6f, +0x6e, 0x65, 0x20, 0x63, 0x6e, 0x6d, 0x42, 0x69, 0x6e, 0x64, 0x46, 0x69, 0x64, 0x42, 0x79, 0x53, +0x77, 0x52, 0x66, 0x62, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x0a, 0x00, 0x00, 0x67, 0x65, 0x74, 0x20, +0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x64, 0x6c, 0x66, 0x6d, 0x43, 0x6d, 0x64, 0x46, 0x77, 0x52, 0x65, 0x53, +0x74, 0x61, 0x72, 0x74, 0x20, 0x75, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x61, +0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x20, 0x50, 0x53, 0x45, 0x20, 0x62, 0x75, 0x66, 0x66, +0x65, 0x72, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x73, 0x72, 0x63, 0x2f, 0x77, 0x69, 0x66, 0x69, +0x5f, 0x75, 0x6e, 0x69, 0x5f, 0x6d, 0x61, 0x63, 0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x2f, 0x68, 0x65, +0x6d, 0x5f, 0x63, 0x6d, 0x64, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xef, 0x00, 0x00, 0x00, 0x84, 0x5f, 0x10, 0x00, 0xed, 0x00, 0x00, 0x00, 0xbc, 0x7a, 0x10, 0x00, +0xee, 0x00, 0x00, 0x00, 0x0c, 0x80, 0x10, 0x00, 0xc2, 0x00, 0x00, 0x00, 0xb8, 0x59, 0x10, 0x00, +0x20, 0x00, 0x00, 0x00, 0x5c, 0x60, 0x10, 0x00, 0x09, 0x00, 0x00, 0x00, 0x6c, 0x45, 0x10, 0x00, +0x32, 0x30, 0x31, 0x34, 0x30, 0x33, 0x31, 0x33, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x65, 0x31, 0x5f, +0x64, 0x72, 0x76, 0x5f, 0x74, 0x76, 0x30, 0x31, 0x00, 0x00, 0x00, 0x00, 0x68, 0x65, 0x6d, 0x45, +0x78, 0x74, 0x43, 0x6d, 0x64, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x41, 0x64, 0x64, +0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x20, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x5b, 0x31, 0x5d, 0x20, 0x57, 0x54, 0x42, 0x4c, 0x32, 0x5f, 0x46, 0x49, +0x44, 0x20, 0x28, 0x30, 0x78, 0x25, 0x78, 0x29, 0x2c, 0x20, 0x57, 0x54, 0x42, 0x4c, 0x32, 0x5f, +0x45, 0x49, 0x44, 0x28, 0x30, 0x78, 0x25, 0x78, 0x29, 0x2c, 0x20, 0x57, 0x54, 0x42, 0x4c, 0x33, +0x5f, 0x46, 0x49, 0x44, 0x20, 0x28, 0x30, 0x78, 0x25, 0x78, 0x29, 0x2c, 0x20, 0x57, 0x54, 0x42, +0x4c, 0x33, 0x5f, 0x45, 0x49, 0x44, 0x28, 0x30, 0x78, 0x25, 0x78, 0x29, 0x2c, 0x20, 0x57, 0x54, +0x42, 0x4c, 0x34, 0x5f, 0x46, 0x49, 0x44, 0x20, 0x28, 0x30, 0x78, 0x25, 0x78, 0x29, 0x2c, 0x20, +0x57, 0x54, 0x42, 0x4c, 0x34, 0x5f, 0x45, 0x49, 0x44, 0x28, 0x30, 0x78, 0x25, 0x78, 0x29, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x49, 0x64, 0x28, +0x25, 0x64, 0x29, 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x69, 0x64, 0x28, 0x25, 0x64, 0x29, 0x2c, 0x20, +0x57, 0x6c, 0x61, 0x6e, 0x49, 0x64, 0x78, 0x28, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x45, 0x6e, 0x74, 0x72, 0x79, 0x20, 0x25, 0x64, 0x20, 0x54, 0x58, 0x20, 0x43, 0x6f, 0x6e, 0x66, +0x69, 0x67, 0x20, 0x46, 0x61, 0x69, 0x6c, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x73, 0x72, 0x63, 0x2f, +0x77, 0x69, 0x66, 0x69, 0x5f, 0x75, 0x6e, 0x69, 0x5f, 0x6d, 0x61, 0x63, 0x2f, 0x6d, 0x67, 0x6d, +0x74, 0x2f, 0x68, 0x65, 0x6d, 0x5f, 0x63, 0x6d, 0x64, 0x5f, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x30, +0x65, 0x78, 0x74, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x20, 0x25, 0x64, +0x20, 0x46, 0x49, 0x44, 0x2f, 0x45, 0x49, 0x44, 0x20, 0x46, 0x61, 0x69, 0x6c, 0x0a, 0x00, 0x00, +0x45, 0x6e, 0x74, 0x72, 0x79, 0x20, 0x25, 0x64, 0x20, 0x53, 0x65, 0x63, 0x20, 0x43, 0x6f, 0x6e, +0x66, 0x69, 0x67, 0x20, 0x46, 0x61, 0x69, 0x6c, 0x0a, 0x00, 0x00, 0x00, 0x4e, 0x6f, 0x74, 0x20, +0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x20, 0x53, +0x75, 0x69, 0x74, 0x3a, 0x20, 0x25, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x45, 0x6e, 0x74, 0x72, +0x79, 0x20, 0x25, 0x64, 0x20, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x20, 0x53, 0x75, 0x69, 0x74, +0x3a, 0x20, 0x25, 0x64, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, +0x46, 0x61, 0x69, 0x6c, 0x0a, 0x00, 0x00, 0x00, 0x41, 0x49, 0x44, 0x28, 0x25, 0x64, 0x29, 0x2c, +0x20, 0x52, 0x78, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x28, 0x30, 0x78, 0x25, 0x78, 0x29, 0x2c, +0x20, 0x62, 0x73, 0x73, 0x69, 0x64, 0x28, 0x25, 0x64, 0x29, 0x0a, 0x00, 0x4c, 0x50, 0x20, 0x30, +0x78, 0x35, 0x43, 0x28, 0x30, 0x78, 0x25, 0x78, 0x29, 0x2c, 0x20, 0x4c, 0x50, 0x20, 0x30, 0x78, +0x33, 0x30, 0x28, 0x30, 0x78, 0x25, 0x78, 0x29, 0x20, 0x0a, 0x00, 0x00, 0x52, 0x78, 0x46, 0x69, +0x6c, 0x74, 0x65, 0x72, 0x28, 0x30, 0x78, 0x25, 0x78, 0x29, 0x0a, 0x00, 0x52, 0x4d, 0x41, 0x43, +0x5f, 0x52, 0x4d, 0x43, 0x52, 0x28, 0x30, 0x78, 0x25, 0x78, 0x29, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x72, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x6f, 0x74, 0x65, 0x20, 0x45, 0x46, 0x55, 0x53, 0x45, 0x5f, +0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, 0x52, 0x49, 0x54, +0x45, 0x0a, 0x00, 0x00, 0x72, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x6f, 0x74, 0x65, 0x20, 0x61, 0x66, +0x74, 0x65, 0x72, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20, 0x65, 0x66, 0x75, 0x73, 0x65, 0x0a, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, +0x64, 0x7c, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0xf4, 0x7e, 0x10, 0x00, 0x0e, 0x00, 0x00, 0x00, +0x50, 0x7d, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0xb4, 0x7b, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, +0xe0, 0x5d, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x38, 0x7b, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00, +0x60, 0x7a, 0x10, 0x00, 0x07, 0x00, 0x00, 0x00, 0x9c, 0x76, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, +0xb4, 0x75, 0x10, 0x00, 0x09, 0x00, 0x00, 0x00, 0x84, 0x63, 0x10, 0x00, 0x0a, 0x00, 0x00, 0x00, +0x58, 0x4b, 0x10, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xec, 0x48, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, +0x94, 0x4f, 0x10, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x74, 0x10, 0x00, 0x0c, 0x00, 0x00, 0x00, +0x24, 0x6d, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x14, 0x6f, 0x10, 0x00, 0x0d, 0x00, 0x00, 0x00, +0x24, 0x67, 0x10, 0x00, 0x11, 0x00, 0x00, 0x00, 0x60, 0x67, 0x10, 0x00, 0x13, 0x00, 0x00, 0x00, +0xcc, 0x66, 0x10, 0x00, 0x17, 0x00, 0x00, 0x00, 0x78, 0x07, 0x10, 0x00, 0x21, 0x00, 0x00, 0x00, +0x38, 0x65, 0x10, 0x00, 0x22, 0x00, 0x00, 0x00, 0xfc, 0x64, 0x10, 0x00, 0x35, 0x36, 0x37, 0x48, +0x50, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, +0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xc0, 0xc1, +0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, +0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xf4, 0xf5, 0xf6, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, +0x01, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x03, 0x01, 0x05, 0x02, 0x00, 0x02, 0x06, 0x02, 0x01, +0x02, 0x02, 0x02, 0x03, 0x02, 0x04, 0x02, 0x05, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, +0x01, 0x02, 0x01, 0x03, 0x01, 0x05, 0x02, 0x00, 0x02, 0x06, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, +0x02, 0x04, 0x02, 0x05, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x45, 0x78, 0x74, 0x5f, 0x66, 0x6e, 0x2e, +0x20, 0x29, 0x0a, 0x00, 0x73, 0x72, 0x63, 0x2f, 0x77, 0x69, 0x66, 0x69, 0x5f, 0x75, 0x6e, 0x69, +0x5f, 0x6d, 0x61, 0x63, 0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x2f, 0x68, 0x65, 0x6d, 0x5f, 0x6d, 0x62, +0x6f, 0x78, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x00, 0x73, 0x72, 0x63, 0x2f, 0x77, 0x69, 0x66, 0x69, +0x5f, 0x75, 0x6e, 0x69, 0x5f, 0x6d, 0x61, 0x63, 0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x2f, 0x63, 0x6e, +0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x63, 0x00, 0x00, 0x00, 0x3d, 0x3d, 0x20, 0x52, +0x4c, 0x4d, 0x20, 0x43, 0x41, 0x4c, 0x20, 0x28, 0x25, 0x73, 0x29, 0x20, 0x28, 0x25, 0x73, 0x29, +0x20, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x20, 0x3d, 0x3d, 0x20, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, +0x45, 0x4c, 0x4e, 0x41, 0x5f, 0x47, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x20, +0x3d, 0x20, 0x28, 0x25, 0x64, 0x29, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x72, +0x61, 0x6e, 0x67, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x52, 0x46, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x20, +0x0a, 0x00, 0x00, 0x00, 0x45, 0x4c, 0x4e, 0x41, 0x5f, 0x47, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x41, +0x42, 0x4c, 0x45, 0x20, 0x3d, 0x20, 0x28, 0x25, 0x64, 0x29, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x20, +0x6f, 0x66, 0x20, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x2d, 0x31, 0x01, 0x01, 0x00, 0x00, 0x00, 0x40, 0x78, 0x7d, 0x01, 0x02, 0x00, 0x00, 0x00, +0x00, 0x5a, 0x62, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x31, 0x01, 0x65, 0x00, 0x00, 0x00, +0x01, 0x00, 0x00, 0x00, 0x40, 0x78, 0x7d, 0x01, 0x7f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, +0x00, 0x5a, 0x62, 0x02, 0xcc, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xe0, 0xcd, 0x24, 0x00, +0xea, 0x19, 0x2d, 0x01, 0x00, 0x00, 0x08, 0x00, 0x62, 0x1a, 0xf1, 0x00, 0x33, 0x33, 0x03, 0x00, +0xea, 0x19, 0x96, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x68, 0xe1, 0x24, 0x00, +0xf8, 0x19, 0x2e, 0x01, 0x00, 0x00, 0x02, 0x00, 0x70, 0x1a, 0xf1, 0x00, 0x33, 0x33, 0x0b, 0x00, +0xf8, 0x19, 0x97, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0xf0, 0xf4, 0x24, 0x00, +0x06, 0x1a, 0x2e, 0x01, 0x00, 0x00, 0x0c, 0x00, 0x7e, 0x1a, 0xf2, 0x00, 0x33, 0x33, 0x03, 0x00, +0x06, 0x1a, 0x97, 0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, 0x00, 0x78, 0x08, 0x25, 0x00, +0x14, 0x1a, 0x2f, 0x01, 0x00, 0x00, 0x06, 0x00, 0x8c, 0x1a, 0xf2, 0x00, 0x33, 0x33, 0x0b, 0x00, +0x14, 0x1a, 0x97, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x25, 0x00, +0x20, 0x1a, 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x1a, 0xf3, 0x00, 0x33, 0x33, 0x03, 0x00, +0x20, 0x1a, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x88, 0x2f, 0x25, 0x00, +0x2e, 0x1a, 0x30, 0x01, 0x00, 0x00, 0x0a, 0x00, 0xa8, 0x1a, 0xf3, 0x00, 0x33, 0x33, 0x0b, 0x00, +0x2e, 0x1a, 0x98, 0x00, 0x00, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x10, 0x43, 0x25, 0x00, +0x3c, 0x1a, 0x31, 0x01, 0x00, 0x00, 0x04, 0x00, 0xb6, 0x1a, 0xf4, 0x00, 0x33, 0x33, 0x03, 0x00, +0x3c, 0x1a, 0x98, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x00, 0x00, 0x98, 0x56, 0x25, 0x00, +0x4a, 0x1a, 0x31, 0x01, 0x00, 0x00, 0x0e, 0x00, 0xc4, 0x1a, 0xf4, 0x00, 0x33, 0x33, 0x0b, 0x00, +0x4a, 0x1a, 0x98, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x09, 0x00, 0x00, 0x00, 0x20, 0x6a, 0x25, 0x00, +0x58, 0x1a, 0x32, 0x01, 0x00, 0x00, 0x08, 0x00, 0xd2, 0x1a, 0xf5, 0x00, 0x33, 0x33, 0x03, 0x00, +0x58, 0x1a, 0x99, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xa8, 0x7d, 0x25, 0x00, +0x66, 0x1a, 0x33, 0x01, 0x00, 0x00, 0x02, 0x00, 0xe0, 0x1a, 0xf5, 0x00, 0x33, 0x33, 0x0b, 0x00, +0x66, 0x1a, 0x99, 0x00, 0x00, 0x00, 0x09, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x30, 0x91, 0x25, 0x00, +0x74, 0x1a, 0x33, 0x01, 0x00, 0x00, 0x0c, 0x00, 0xee, 0x1a, 0xf6, 0x00, 0x33, 0x33, 0x03, 0x00, +0x74, 0x1a, 0x99, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0c, 0x00, 0x00, 0x00, 0xb8, 0xa4, 0x25, 0x00, +0x82, 0x1a, 0x34, 0x01, 0x00, 0x00, 0x06, 0x00, 0xfc, 0x1a, 0xf6, 0x00, 0x33, 0x33, 0x0b, 0x00, +0x82, 0x1a, 0x9a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x40, 0xb8, 0x25, 0x00, +0x8e, 0x1a, 0x35, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x1b, 0xf7, 0x00, 0x33, 0x33, 0x03, 0x00, +0x8e, 0x1a, 0x9a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x20, 0xe7, 0x25, 0x00, +0xb0, 0x1a, 0x36, 0x01, 0x00, 0x00, 0x08, 0x00, 0x2c, 0x1b, 0xf8, 0x00, 0x66, 0x66, 0x06, 0x00, +0xb0, 0x1a, 0x9b, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0f, 0x00, 0x00, 0x00, 0xc8, 0x98, 0x66, 0x01, +0x40, 0x19, 0x25, 0x01, 0x9a, 0x19, 0x0c, 0x00, 0xb6, 0x19, 0xeb, 0x00, 0x7b, 0x14, 0x00, 0x00, +0x40, 0x19, 0x92, 0x00, 0xcd, 0x0c, 0x0e, 0x00, 0x20, 0x00, 0x00, 0x00, 0x8c, 0x09, 0x80, 0x00, +0x8c, 0x09, 0x80, 0x00, 0x8c, 0x09, 0x80, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x66, 0xa4, 0x81, 0xee, +0x66, 0xa4, 0x81, 0xee, 0x66, 0xa4, 0x81, 0xee, 0xb0, 0x00, 0x00, 0x00, 0xc4, 0xa3, 0x01, 0x04, +0x66, 0xab, 0x01, 0x04, 0xc9, 0xa3, 0x01, 0x04, 0xb4, 0x00, 0x00, 0x00, 0x10, 0xc0, 0xf0, 0x3f, +0x10, 0xc0, 0xf0, 0x3f, 0x10, 0xc0, 0xf0, 0x3f, 0xbc, 0x00, 0x00, 0x00, 0xc3, 0xb6, 0x44, 0x44, +0xc3, 0xb6, 0x55, 0x55, 0xc3, 0xb6, 0x66, 0x66, 0x00, 0x06, 0x00, 0x00, 0xb3, 0x6f, 0x62, 0xc1, +0xc3, 0x6f, 0x62, 0xc1, 0xf3, 0x6f, 0x62, 0xc1, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x14, 0x13, +0x33, 0x33, 0x43, 0x0f, 0x00, 0x00, 0x8a, 0x09, 0x14, 0x00, 0x00, 0x00, 0x00, 0xab, 0x84, 0x56, +0xe8, 0x00, 0x00, 0x00, 0x81, 0x00, 0x61, 0x00, 0xec, 0x00, 0x00, 0x00, 0x21, 0x00, 0x83, 0x00, +0xf0, 0x00, 0x00, 0x00, 0x63, 0x00, 0x23, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x88, 0x00, 0x68, 0x00, +0xf8, 0x00, 0x00, 0x00, 0x28, 0x00, 0x8f, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x6f, 0x00, 0xbd, 0x00, +0x00, 0x01, 0x00, 0x00, 0x9d, 0x00, 0x7d, 0x00, 0x04, 0x01, 0x00, 0x00, 0x3d, 0x00, 0x1d, 0x00, +0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xbf, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x80, 0x14, 0x00, 0x00, 0x00, 0x00, 0xab, 0x84, 0x56, +0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x11, 0x1d, 0x1e, 0x35, +0xe0, 0x00, 0x00, 0x00, 0x1c, 0x35, 0x17, 0x19, 0xe8, 0x00, 0x00, 0x00, 0xe1, 0x00, 0xa1, 0x00, +0xec, 0x00, 0x00, 0x00, 0x81, 0x00, 0x61, 0x00, 0xf0, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x83, 0x00, +0xf4, 0x00, 0x00, 0x00, 0x63, 0x00, 0xa7, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x87, 0x00, 0x67, 0x00, +0xfc, 0x00, 0x00, 0x00, 0xae, 0x00, 0x8e, 0x00, 0x00, 0x01, 0x00, 0x00, 0x6e, 0x00, 0x2e, 0x00, +0x04, 0x01, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x00, 0x08, 0x00, 0x00, 0x66, 0x44, 0x66, 0x44, +0x04, 0x08, 0x00, 0x00, 0x66, 0x44, 0x66, 0x44, 0x08, 0x08, 0x00, 0x00, 0x00, 0x44, 0x00, 0x44, +0x0c, 0x08, 0x00, 0x00, 0x00, 0x44, 0x00, 0x44, 0x10, 0x08, 0x00, 0x00, 0x44, 0x44, 0x44, 0x41, +0x14, 0x08, 0x00, 0x00, 0x44, 0x44, 0x44, 0x41, 0x3c, 0x06, 0x00, 0x00, 0x32, 0x74, 0x32, 0x63, +0x40, 0x06, 0x00, 0x00, 0x22, 0x62, 0x32, 0x63, 0x4c, 0x06, 0x00, 0x00, 0x19, 0x19, 0x19, 0x05, +0x50, 0x06, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x01, 0x58, 0x06, 0x00, 0x00, 0x19, 0x14, 0x14, 0x05, +0x5c, 0x06, 0x00, 0x00, 0x0a, 0x07, 0x07, 0x01, 0x64, 0x06, 0x00, 0x00, 0x19, 0x19, 0x19, 0x05, +0x68, 0x06, 0x00, 0x00, 0x19, 0x14, 0x14, 0x05, 0x00, 0x08, 0x00, 0x00, 0x66, 0x44, 0x66, 0x44, +0x04, 0x08, 0x00, 0x00, 0x66, 0x44, 0x66, 0x44, 0x08, 0x08, 0x00, 0x00, 0x00, 0x44, 0x00, 0x44, +0x0c, 0x08, 0x00, 0x00, 0x00, 0x44, 0x00, 0x44, 0x10, 0x08, 0x00, 0x00, 0x44, 0x44, 0x44, 0x41, +0x14, 0x08, 0x00, 0x00, 0x44, 0x44, 0x44, 0x41, 0x3c, 0x06, 0x00, 0x00, 0x32, 0x74, 0x32, 0x63, +0x40, 0x06, 0x00, 0x00, 0x22, 0x62, 0x32, 0x63, 0x4c, 0x06, 0x00, 0x00, 0x19, 0x19, 0x19, 0x05, +0x50, 0x06, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x01, 0x58, 0x06, 0x00, 0x00, 0x19, 0x14, 0x14, 0x05, +0x5c, 0x06, 0x00, 0x00, 0x0a, 0x07, 0x07, 0x01, 0x64, 0x06, 0x00, 0x00, 0x19, 0x19, 0x19, 0x05, +0x68, 0x06, 0x00, 0x00, 0x19, 0x14, 0x14, 0x05, 0xfe, 0x77, 0x0d, 0x80, 0x00, 0x80, 0x00, 0x00, +0xfe, 0x77, 0x0f, 0x80, 0x00, 0x80, 0x00, 0x00, 0xfe, 0xb7, 0x0f, 0x80, 0x00, 0x80, 0x00, 0x00, +0xfe, 0xf7, 0x0f, 0x80, 0x00, 0x80, 0x00, 0x00, 0xfe, 0x77, 0x0d, 0x80, 0x00, 0x90, 0x00, 0x00, +0xfe, 0x77, 0x0f, 0x80, 0x00, 0x90, 0x00, 0x00, 0xfe, 0xb7, 0x0f, 0x80, 0x00, 0x90, 0x00, 0x00, +0xfe, 0xf7, 0x0f, 0x80, 0x00, 0x90, 0x00, 0x00, 0xfe, 0x77, 0x0d, 0x80, 0x00, 0xa0, 0x00, 0x00, +0xfe, 0x77, 0x0f, 0x80, 0x00, 0xa0, 0x00, 0x00, 0xfe, 0xb7, 0x0f, 0x80, 0x00, 0xa0, 0x00, 0x00, +0xfe, 0xf7, 0x0f, 0x80, 0x00, 0xa0, 0x00, 0x00, 0xfe, 0x77, 0x0d, 0x80, 0x00, 0xb0, 0x00, 0x00, +0xfe, 0x77, 0x0f, 0x80, 0x00, 0xb0, 0x00, 0x00, 0xfe, 0xb7, 0x0f, 0x80, 0x00, 0xb0, 0x00, 0x00, +0xfe, 0xf7, 0x0f, 0x80, 0x00, 0xb0, 0x00, 0x00, 0xfe, 0x77, 0x0d, 0x90, 0x00, 0x80, 0x00, 0x00, +0xfe, 0x77, 0x0f, 0x90, 0x00, 0x80, 0x00, 0x00, 0xfe, 0xb7, 0x0f, 0x90, 0x00, 0x80, 0x00, 0x00, +0xfe, 0xf7, 0x0f, 0x90, 0x00, 0x80, 0x00, 0x00, 0xfe, 0x77, 0x0d, 0x90, 0x00, 0x90, 0x00, 0x00, +0xfe, 0x77, 0x0f, 0x90, 0x00, 0x90, 0x00, 0x00, 0xfe, 0xb7, 0x0f, 0x90, 0x00, 0x90, 0x00, 0x00, +0xfe, 0xf7, 0x0f, 0x90, 0x00, 0x90, 0x00, 0x00, 0xfe, 0x77, 0x0d, 0x90, 0x00, 0xa0, 0x00, 0x00, +0xfe, 0x77, 0x0f, 0x90, 0x00, 0xa0, 0x00, 0x00, 0xfe, 0xb7, 0x0f, 0x90, 0x00, 0xa0, 0x00, 0x00, +0xfe, 0xf7, 0x0f, 0x90, 0x00, 0xa0, 0x00, 0x00, 0xfe, 0x77, 0x0d, 0x90, 0x00, 0xb0, 0x00, 0x00, +0xfe, 0x77, 0x0f, 0x90, 0x00, 0xb0, 0x00, 0x00, 0xfe, 0xb7, 0x0f, 0x90, 0x00, 0xb0, 0x00, 0x00, +0xfe, 0xf7, 0x0f, 0x90, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x08, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, +0x04, 0x08, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, +0x0c, 0x08, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x20, 0x60, 0xfe, 0xfb, 0xff, 0x3f, +0x14, 0x08, 0x20, 0x60, 0xfa, 0xf3, 0xdf, 0x3f, 0x18, 0x08, 0x20, 0x60, 0xf5, 0xdf, 0x9f, 0x3f, +0x1c, 0x08, 0x20, 0x60, 0xf0, 0xcb, 0x4f, 0x3f, 0x20, 0x08, 0x20, 0x60, 0xeb, 0xb3, 0xef, 0x3e, +0x24, 0x08, 0x20, 0x60, 0xe9, 0xa7, 0xaf, 0x3e, 0x28, 0x08, 0x20, 0x60, 0xef, 0xb3, 0xaf, 0x3e, +0x2c, 0x08, 0x20, 0x60, 0xff, 0xe7, 0x3f, 0x3f, 0x30, 0x08, 0x20, 0x60, 0x1c, 0x44, 0x80, 0x00, +0x34, 0x08, 0x20, 0x60, 0x46, 0xdc, 0x90, 0x02, 0x38, 0x08, 0x20, 0x60, 0x7a, 0x9c, 0x61, 0x05, +0x3c, 0x08, 0x20, 0x60, 0xb3, 0x80, 0xd2, 0x08, 0x40, 0x08, 0x20, 0x60, 0xec, 0x68, 0x73, 0x0c, +0x44, 0x08, 0x20, 0x60, 0x1d, 0x39, 0xe4, 0x0f, 0x48, 0x08, 0x20, 0x60, 0x3f, 0xd9, 0xa4, 0x12, +0x4c, 0x08, 0x20, 0x60, 0x4e, 0x2d, 0x65, 0x14, 0x00, 0x08, 0x20, 0x60, 0xfd, 0xf7, 0xdf, 0x3f, +0x04, 0x08, 0x20, 0x60, 0xfd, 0xf7, 0xdf, 0x3f, 0x08, 0x08, 0x20, 0x60, 0xfd, 0xf7, 0xdf, 0x3f, +0x0c, 0x08, 0x20, 0x60, 0xfd, 0xf7, 0xdf, 0x3f, 0x10, 0x08, 0x20, 0x60, 0xff, 0xfb, 0xef, 0x3f, +0x14, 0x08, 0x20, 0x60, 0x02, 0x04, 0xf0, 0x3f, 0x18, 0x08, 0x20, 0x60, 0x07, 0x14, 0x30, 0x00, +0x1c, 0x08, 0x20, 0x60, 0x0f, 0x30, 0x90, 0x00, 0x20, 0x08, 0x20, 0x60, 0x19, 0x54, 0x20, 0x01, +0x24, 0x08, 0x20, 0x60, 0x26, 0x88, 0xd0, 0x01, 0x28, 0x08, 0x20, 0x60, 0x36, 0xc4, 0xb0, 0x02, +0x2c, 0x08, 0x20, 0x60, 0x49, 0x0c, 0xc1, 0x03, 0x30, 0x08, 0x20, 0x60, 0x5d, 0x58, 0xf1, 0x04, +0x34, 0x08, 0x20, 0x60, 0x72, 0xac, 0x41, 0x06, 0x38, 0x08, 0x20, 0x60, 0x86, 0x00, 0x92, 0x07, +0x3c, 0x08, 0x20, 0x60, 0x99, 0x4c, 0xd2, 0x08, 0x40, 0x08, 0x20, 0x60, 0xaa, 0x94, 0xf2, 0x09, +0x44, 0x08, 0x20, 0x60, 0xb7, 0xcc, 0xe2, 0x0a, 0x48, 0x08, 0x20, 0x60, 0xbf, 0xf4, 0xa2, 0x0b, +0x4c, 0x08, 0x20, 0x60, 0xc2, 0x08, 0x13, 0x0c, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xe4, +0x00, 0x00, 0xe4, 0x94, 0x00, 0x00, 0xe4, 0x90, 0x00, 0x00, 0xe4, 0x91, 0x00, 0x00, 0x00, 0x00, +0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xe4, 0x00, 0x00, 0xe4, 0x94, 0x00, 0x00, 0xe4, 0x90, +0x00, 0x00, 0xe4, 0x91, 0x01, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x76, +0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, +0x74, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x76, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, +0x66, 0x66, 0x66, 0x66, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0xa8, +0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, +0x78, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0xa8, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, +0x88, 0x88, 0x88, 0x88, 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x44, 0x44, 0x46, 0x41, +0x44, 0x44, 0x46, 0x11, 0x44, 0x44, 0x46, 0x11, 0x44, 0x44, 0x46, 0x11, 0x00, 0x00, 0x00, 0x00, +0x7c, 0x00, 0x00, 0x00, 0x44, 0x44, 0x46, 0x41, 0x44, 0x44, 0x46, 0x11, 0x44, 0x44, 0x46, 0x11, +0x44, 0x44, 0x46, 0x11, 0x01, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x32, 0x52, 0x43, 0x63, +0x32, 0x52, 0x43, 0x34, 0x32, 0x52, 0x66, 0x34, 0x32, 0x52, 0x64, 0x34, 0x00, 0x00, 0x00, 0x00, +0x88, 0x00, 0x00, 0x00, 0x32, 0x52, 0x42, 0x52, 0x32, 0x52, 0x42, 0x24, 0x32, 0x52, 0x55, 0x24, +0x32, 0x52, 0x54, 0x24, 0x01, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x14, 0x0f, 0x14, 0x05, +0x14, 0x0f, 0x0f, 0x14, 0x05, 0x05, 0x0f, 0x14, 0x0f, 0x05, 0x0f, 0x14, 0x00, 0x00, 0x00, 0x00, +0x94, 0x00, 0x00, 0x00, 0x19, 0x0f, 0x19, 0x0a, 0x19, 0x0f, 0x0f, 0x19, 0x0a, 0x0a, 0x0f, 0x19, +0x0f, 0x0a, 0x0f, 0x19, 0x01, 0x00, 0x00, 0x00, 0x98, 0x00, 0x00, 0x00, 0x07, 0x04, 0x07, 0x01, +0x07, 0x04, 0x04, 0x07, 0x01, 0x01, 0x04, 0x07, 0x04, 0x01, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, +0x98, 0x00, 0x00, 0x00, 0x0a, 0x04, 0x0a, 0x03, 0x0a, 0x04, 0x04, 0x0a, 0x03, 0x03, 0x04, 0x0a, +0x04, 0x03, 0x04, 0x0a, 0x01, 0x00, 0x00, 0x00, 0x72, 0x6c, 0x6d, 0x52, 0x46, 0x32, 0x47, 0x34, +0x5f, 0x52, 0x65, 0x67, 0x49, 0x6e, 0x69, 0x74, 0x00, 0x00, 0x00, 0x00, 0x72, 0x6c, 0x6d, 0x52, +0x46, 0x5f, 0x41, 0x46, 0x45, 0x5f, 0x43, 0x61, 0x6c, 0x32, 0x47, 0x5f, 0x54, 0x78, 0x5f, 0x44, +0x50, 0x44, 0x5f, 0x43, 0x61, 0x6c, 0x00, 0x00, 0xd0, 0x81, 0x80, 0x00, 0xd0, 0x81, 0x80, 0x00, +0x00, 0xab, 0x84, 0x56, 0x00, 0x00, 0x80, 0x43, 0xd0, 0x81, 0x81, 0x00, 0xd0, 0x81, 0x81, 0x00, +0x00, 0xab, 0x84, 0x56, 0x00, 0x00, 0x00, 0x40, 0xd0, 0x81, 0x83, 0x00, 0xd0, 0x81, 0x83, 0x00, +0x00, 0xab, 0x84, 0x56, 0x00, 0x00, 0x80, 0x40, 0xd0, 0x81, 0x84, 0x00, 0xd0, 0x81, 0x84, 0x00, +0x00, 0xa8, 0x84, 0x56, 0x00, 0x00, 0x80, 0x43, 0xd0, 0x81, 0x85, 0x00, 0xd0, 0x81, 0x85, 0x00, +0x00, 0xa8, 0x84, 0x56, 0x00, 0x00, 0x00, 0x40, 0xd0, 0x81, 0x87, 0x00, 0xd0, 0x81, 0x87, 0x00, +0x00, 0xa8, 0x84, 0x56, 0x00, 0x00, 0x80, 0x40, 0xf0, 0x80, 0x80, 0x00, 0xe0, 0x80, 0x80, 0x00, +0x00, 0xa8, 0x84, 0x56, 0x00, 0x00, 0x80, 0x43, 0xf0, 0x80, 0x81, 0x00, 0xe0, 0x80, 0x81, 0x00, +0x00, 0xa8, 0x84, 0x56, 0x00, 0x00, 0x00, 0x40, 0xf0, 0x80, 0x83, 0x00, 0xe0, 0x80, 0x83, 0x00, +0x00, 0xa8, 0x84, 0x56, 0x00, 0x00, 0x80, 0x40, 0xf0, 0x80, 0x84, 0x00, 0xe0, 0x80, 0x84, 0x00, +0x00, 0xa8, 0x84, 0x56, 0x00, 0x00, 0x00, 0x41, 0xf0, 0x80, 0x85, 0x00, 0xe0, 0x80, 0x85, 0x00, +0x00, 0xa8, 0x84, 0x56, 0x00, 0x00, 0x00, 0x41, 0xf0, 0x80, 0x87, 0x00, 0xe0, 0x80, 0x87, 0x00, +0x00, 0xa8, 0x84, 0x56, 0x00, 0x00, 0x00, 0x41, 0x72, 0x6c, 0x6d, 0x52, 0x46, 0x5f, 0x41, 0x46, +0x45, 0x5f, 0x43, 0x61, 0x6c, 0x32, 0x47, 0x5f, 0x52, 0x53, 0x53, 0x49, 0x5f, 0x44, 0x43, 0x4f, +0x43, 0x5f, 0x43, 0x61, 0x6c, 0x00, 0x00, 0x00, 0x0c, 0x02, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0d, 0x20, 0x60, 0xc0, 0x41, 0x40, 0x82, 0x04, 0x0d, 0x20, 0x60, 0x00, 0x08, 0x01, 0x21, +0x14, 0x42, 0x20, 0x60, 0x80, 0x05, 0x00, 0x00, 0x24, 0x0d, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, +0x08, 0x0a, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x40, 0x41, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, +0x80, 0x03, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0x60, 0x48, 0x00, 0x01, 0x00, +0x00, 0x41, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x04, 0x07, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, +0xcc, 0x06, 0x20, 0x60, 0xa2, 0x0d, 0x22, 0x00, 0x80, 0x01, 0x20, 0x60, 0x80, 0x83, 0x82, 0x7a, +0x84, 0x01, 0x20, 0x60, 0x71, 0x6f, 0x7b, 0xa7, 0x50, 0x01, 0x20, 0x60, 0x01, 0x00, 0x10, 0x02, +0x54, 0x01, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, +0x40, 0x01, 0x20, 0x60, 0x00, 0x80, 0x10, 0x00, 0x08, 0x01, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, +0x04, 0x01, 0x20, 0x60, 0xf9, 0x4f, 0x00, 0x09, 0x14, 0x41, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, +0x04, 0x01, 0x20, 0x60, 0xf9, 0x4f, 0x00, 0x09, 0x10, 0x01, 0x20, 0x60, 0xf9, 0x00, 0x00, 0x00, +0x1c, 0x01, 0x20, 0x60, 0x00, 0x00, 0xf0, 0x90, 0x00, 0x00, 0x20, 0x60, 0x45, 0x00, 0x00, 0x00, +0x04, 0x00, 0x20, 0x60, 0x45, 0x00, 0x00, 0x00, 0x44, 0x01, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, +0x00, 0x1d, 0x20, 0x60, 0xc0, 0x41, 0x40, 0x82, 0x04, 0x1d, 0x20, 0x60, 0x00, 0x08, 0x01, 0x21, +0x24, 0x1d, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x12, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, +0x08, 0x1a, 0x20, 0x60, 0x00, 0x00, 0x00, 0x00, 0x14, 0x52, 0x20, 0x60, 0x80, 0x05, 0x00, 0x00, +0x48, 0x00, 0x00, 0x00, 0x27, 0x07, 0x30, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x44, 0x00, 0x00, 0x00, 0xd0, 0x82, 0x00, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xc8, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x02, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x20, 0x09, 0x8f, +0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0xd1, 0x7e, 0x11, 0x19, +0x14, 0x00, 0x00, 0x00, 0x00, 0xab, 0x84, 0x56, 0xa0, 0x00, 0x00, 0x00, 0xfe, 0xf5, 0x06, 0x00, +0x48, 0x00, 0x00, 0x00, 0x27, 0x07, 0x30, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x44, 0x00, 0x00, 0x00, 0xd0, 0x82, 0x00, 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xc8, 0x00, 0x00, 0x00, 0xc0, 0x40, 0x00, 0x02, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x20, 0x09, 0x8f, +0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0xd1, 0x7e, 0x11, 0x19, +0x14, 0x00, 0x00, 0x00, 0x00, 0xab, 0x84, 0x56, 0xa0, 0x00, 0x00, 0x00, 0xfe, 0xf5, 0x06, 0x00, +0x72, 0x6c, 0x6d, 0x52, 0x46, 0x5f, 0x41, 0x46, 0x45, 0x5f, 0x43, 0x61, 0x6c, 0x32, 0x47, 0x5f, +0x53, 0x58, 0x5f, 0x47, 0x5f, 0x43, 0x61, 0x6c, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x43, 0x68, 0x5f, +0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x00, 0x00, 0x58, 0x4f, 0x00, 0x00, 0x46, 0x00, 0x01, 0x0f, +0x58, 0x00, 0x0a, 0x60, 0x46, 0x20, 0x01, 0x13, 0x58, 0x21, 0x00, 0x0c, 0x4c, 0x01, 0x00, 0x08, +0x44, 0x10, 0x00, 0x00, 0x1c, 0x10, 0x00, 0x01, 0x4c, 0x01, 0x7f, 0xfe, 0x59, 0xe2, 0x00, 0x00, +0x4a, 0x00, 0x78, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x24, 0xfc, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0xb4, 0x08, 0x11, 0x00, 0x80, 0x00, 0x00, 0x00, +0x10, 0x27, 0x11, 0x00, 0x01, 0x00, 0x00, 0x00, 0xf0, 0x28, 0x11, 0x00, 0xf0, 0x2a, 0x11, 0x00, +0x02, 0x00, 0x00, 0x00, 0x36, 0x0e, 0x00, 0x00, 0x81, 0x94, 0x40, 0xb0, 0x40, 0xc6, 0x27, 0x00, +0x00, 0x00, 0xc0, 0xc5, 0x27, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc4, 0xc4, 0xc4, 0xc0, 0xc0, 0xc4, +0xc4, 0xc4, 0xc4, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, +0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x43, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, +0x88, 0x42, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x90, 0x43, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, +0x90, 0x43, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x88, 0x42, 0x10, 0x00, 0x07, 0x00, 0x01, 0x01, +0xe8, 0xe1, 0x10, 0x00, 0x01, 0x01, 0x00, 0x00, 0xac, 0xdd, 0x10, 0x00, 0x01, 0x01, 0x00, 0x00, +0xf8, 0xd8, 0x10, 0x00, 0x01, 0x01, 0x00, 0x00, 0x6c, 0xd1, 0x10, 0x00, 0x01, 0x01, 0x00, 0x00, +0xa0, 0xcd, 0x10, 0x00, 0x01, 0x01, 0x00, 0x00, 0x14, 0xc9, 0x10, 0x00, 0x01, 0x01, 0x00, 0x00, +0xac, 0xb2, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x14, 0x18, 0x43, 0x8c, 0x3d, 0x99, +0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x65, 0x31, 0x5f, 0x64, 0x72, 0x76, 0x5f, 0x74, +0x76, 0x32, 0x30, 0x31, 0x34, 0x30, 0x33, 0x31, 0x33, 0x32, 0x31, 0x35, 0x35, 0x34, 0x38, 0x00, +0x5c, 0xfa, 0x00, 0x00, } ; diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7636_firmware.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7636_firmware.h new file mode 100644 index 000000000..d31718fd5 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7636_firmware.h @@ -0,0 +1,14300 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR MT7636_FirmwareImage[] = { +0x04, 0xa5, 0x4b, 0x15, 0x45, 0xb4, 0x4c, 0xff, 0x52, 0x95, 0x15, 0xe2, 0xa0, 0x0f, 0xd9, 0x0d, +0x7a, 0xf6, 0x22, 0xe3, 0xc8, 0xd8, 0xf8, 0x69, 0x7b, 0x18, 0xa6, 0x56, 0xf4, 0x71, 0xfa, 0x9c, +0x39, 0xb8, 0xf4, 0x67, 0x41, 0xb2, 0xc9, 0xd1, 0x57, 0x22, 0x77, 0xa3, 0x37, 0xa0, 0xb7, 0x91, +0xa4, 0x8c, 0x65, 0x70, 0x99, 0x11, 0x00, 0xc6, 0xb3, 0x38, 0xcd, 0x57, 0xb0, 0xaf, 0x09, 0x11, +0x48, 0xe1, 0x57, 0xb8, 0x6b, 0xc8, 0x19, 0x3b, 0xc9, 0xb2, 0xd7, 0x0f, 0x88, 0x74, 0x36, 0x38, +0xb9, 0xa7, 0xd6, 0xd5, 0xc2, 0x20, 0xdf, 0x1f, 0xb8, 0xac, 0x1f, 0xb9, 0x9a, 0x80, 0x84, 0x2c, +0xee, 0x2a, 0x0c, 0x6c, 0x25, 0x72, 0xeb, 0xe2, 0x33, 0xb3, 0xd3, 0x31, 0x2a, 0xcb, 0xe7, 0x59, +0x12, 0x4d, 0xf4, 0x90, 0x94, 0xe4, 0xf9, 0xd7, 0x90, 0xc6, 0x0e, 0x6c, 0x59, 0x42, 0x4a, 0xb8, +0x76, 0x58, 0x73, 0x56, 0xd4, 0x07, 0x7f, 0x51, 0x4d, 0x96, 0x6b, 0x19, 0xeb, 0xb7, 0x1b, 0x35, +0x5b, 0x1e, 0x9b, 0x19, 0x10, 0x9a, 0xeb, 0x03, 0x8b, 0x97, 0x31, 0x70, 0x92, 0x6d, 0x9c, 0x80, +0x22, 0x6e, 0x53, 0x84, 0x36, 0xc2, 0xae, 0x49, 0x28, 0xe0, 0x43, 0x36, 0x3b, 0xd5, 0xd0, 0x9a, +0x44, 0x81, 0x11, 0x5f, 0x7a, 0xc1, 0x19, 0x4c, 0xfd, 0x46, 0x4f, 0x00, 0x65, 0x27, 0x19, 0xa2, +0x5c, 0xf5, 0xa6, 0x7f, 0x3a, 0xbd, 0x7e, 0x2a, 0xbd, 0xf8, 0x6b, 0xd5, 0x58, 0xbc, 0xb3, 0x5b, +0xef, 0xdd, 0xeb, 0x6c, 0x43, 0xd8, 0x2f, 0x6a, 0xff, 0x56, 0x27, 0x4b, 0x9b, 0xba, 0xd2, 0x2b, +0x5d, 0x78, 0xee, 0x17, 0x81, 0x67, 0x72, 0x6d, 0x7e, 0x5a, 0xac, 0x6a, 0x2a, 0x9e, 0x6f, 0xea, +0x89, 0x06, 0x4f, 0xd5, 0x25, 0xfe, 0x5c, 0xf7, 0xe0, 0x60, 0x69, 0x88, 0x33, 0x16, 0x69, 0x2f, +0x3a, 0x6e, 0x54, 0x0c, 0xac, 0xc4, 0xfd, 0x8f, 0x33, 0xff, 0xc5, 0x92, 0x68, 0x53, 0x6b, 0xd3, +0x2a, 0xd7, 0x80, 0x00, 0xbf, 0x9c, 0x4b, 0x77, 0x1f, 0xaa, 0xdd, 0xa4, 0xb8, 0x46, 0x9c, 0x5c, +0x5b, 0x72, 0x58, 0x57, 0x8b, 0xed, 0xf8, 0xb8, 0x9c, 0x39, 0x40, 0x5f, 0x2a, 0x2e, 0x4f, 0xec, +0x7b, 0x3a, 0x7d, 0x0b, 0x8d, 0xb6, 0xd3, 0x12, 0x28, 0xdc, 0x98, 0x1e, 0x8e, 0xb4, 0x18, 0x7e, +0x2c, 0xd2, 0x1c, 0xea, 0x62, 0x2b, 0x54, 0x96, 0xd9, 0x89, 0x87, 0xd2, 0xbb, 0xa5, 0xb8, 0x64, +0x6a, 0x14, 0x1c, 0x64, 0x06, 0xa9, 0x05, 0xb8, 0x99, 0x6a, 0x83, 0xcf, 0xb7, 0x0a, 0xed, 0x7d, +0xa5, 0xe6, 0xc4, 0x7c, 0x22, 0xe3, 0x02, 0xc7, 0x7b, 0x80, 0x8c, 0x0c, 0x08, 0x49, 0xdd, 0xd6, +0xd2, 0xfd, 0x42, 0x6f, 0x34, 0x8d, 0x89, 0xcf, 0x26, 0xa7, 0xeb, 0xc2, 0x81, 0x6f, 0xdc, 0xe3, +0x4a, 0x00, 0xcb, 0xb6, 0x47, 0x94, 0xbc, 0x72, 0x76, 0x8c, 0xac, 0x9a, 0x08, 0x91, 0x63, 0x58, +0x19, 0xe6, 0x8f, 0xba, 0x0f, 0x39, 0x1a, 0xae, 0x59, 0xb6, 0x92, 0xc4, 0x53, 0xa6, 0x38, 0x46, +0x9e, 0xa2, 0x21, 0xa3, 0xbb, 0x69, 0xaa, 0xd1, 0x91, 0xb9, 0x81, 0x18, 0x1d, 0xf7, 0xff, 0xbf, +0x10, 0x92, 0xae, 0x1d, 0x13, 0x5a, 0xa8, 0xf8, 0x1e, 0x76, 0xef, 0x61, 0x12, 0x4a, 0x58, 0xac, +0x3a, 0x42, 0xa1, 0x84, 0x3d, 0x2b, 0x09, 0xd3, 0x32, 0xb7, 0x47, 0xb0, 0xfb, 0x51, 0x58, 0x75, +0xc5, 0x04, 0x04, 0x42, 0xdc, 0x10, 0x8f, 0xa9, 0xe9, 0x8e, 0x8d, 0x0b, 0xe4, 0x66, 0x24, 0xb4, +0xbc, 0x06, 0xf1, 0xea, 0xb6, 0x79, 0x2a, 0xa5, 0x22, 0x08, 0x79, 0x8b, 0xf1, 0xb5, 0xbd, 0xe6, +0x2c, 0x94, 0x68, 0xcd, 0x2c, 0x46, 0xa4, 0xe8, 0x6d, 0x9c, 0x31, 0x13, 0x27, 0xf8, 0x3f, 0x6d, +0x5f, 0x58, 0xf0, 0xde, 0x5a, 0x32, 0x3d, 0x56, 0x4b, 0x5d, 0xa5, 0xf0, 0xc6, 0x45, 0x41, 0xb1, +0x8f, 0xd2, 0xcd, 0xee, 0x88, 0x7c, 0x91, 0x05, 0xbd, 0xe3, 0xc8, 0x88, 0x04, 0xf8, 0x18, 0xe7, +0xf9, 0xa0, 0x5f, 0x25, 0x05, 0x29, 0x0c, 0xab, 0x42, 0xf9, 0x2f, 0x80, 0x0a, 0x1b, 0xba, 0x71, +0x29, 0x15, 0x4c, 0x60, 0x6a, 0x21, 0x00, 0x99, 0xc4, 0xf0, 0x7c, 0x20, 0xdc, 0x16, 0xb0, 0x7b, +0xd2, 0xbd, 0x6a, 0xad, 0x54, 0x6a, 0x9d, 0xb6, 0x6a, 0x7e, 0xd9, 0x0b, 0x49, 0xe3, 0xe3, 0x1f, +0xd3, 0xf9, 0x69, 0xd5, 0x51, 0xab, 0x67, 0x37, 0xf1, 0x67, 0xd0, 0x35, 0x9b, 0xa5, 0x98, 0x3c, +0x5c, 0x0b, 0x79, 0x96, 0xaf, 0xf1, 0xae, 0xdc, 0xfb, 0x28, 0x35, 0x94, 0xd0, 0xf2, 0x24, 0x14, +0xbc, 0x3b, 0xc0, 0xea, 0x60, 0x20, 0x03, 0x35, 0x95, 0x46, 0xc9, 0xe5, 0xb7, 0x23, 0x5a, 0xd0, +0xd8, 0xf7, 0xbb, 0x7a, 0xd0, 0x3d, 0x16, 0xfa, 0xa3, 0xc5, 0x0e, 0xc0, 0x78, 0x54, 0x53, 0xb2, +0xfc, 0x22, 0x16, 0x94, 0xb3, 0x15, 0xfe, 0xa3, 0x4b, 0xc6, 0x6c, 0x99, 0x94, 0x7a, 0x30, 0x0a, +0xba, 0xbd, 0x05, 0x51, 0x60, 0xa0, 0x79, 0x5a, 0x4e, 0xb6, 0xdc, 0x4f, 0xdd, 0x01, 0xc7, 0x7a, +0x34, 0x18, 0x52, 0xb9, 0x97, 0xa6, 0x21, 0x28, 0x6b, 0x8d, 0x45, 0x9f, 0x57, 0x4c, 0x86, 0xa1, +0x64, 0xf7, 0xe1, 0x7d, 0x60, 0xef, 0xd1, 0xa6, 0x06, 0x54, 0x9e, 0xc6, 0xeb, 0x2a, 0x42, 0xca, +0xf8, 0xa3, 0x8c, 0x5d, 0x6d, 0x6e, 0x16, 0x29, 0x42, 0x8a, 0x83, 0xd8, 0x3b, 0xa7, 0x85, 0x87, +0x04, 0xef, 0xec, 0xaa, 0xb4, 0x7c, 0xbf, 0x93, 0xdb, 0xfb, 0x52, 0x06, 0x6c, 0xfd, 0x40, 0x12, +0x4c, 0x0d, 0xa8, 0xec, 0xf1, 0x6a, 0x08, 0xce, 0x5d, 0x7e, 0x6e, 0x24, 0xaa, 0x8f, 0x63, 0x66, +0x20, 0xb8, 0x28, 0xca, 0xad, 0xdd, 0x67, 0x1d, 0xd2, 0x68, 0x0c, 0x85, 0x6e, 0x5d, 0x5f, 0xdd, +0x7b, 0x55, 0xcd, 0x2d, 0xbb, 0x38, 0x0d, 0xcd, 0x1e, 0x59, 0x3c, 0x05, 0x65, 0x92, 0xc9, 0x7f, +0x03, 0x44, 0x16, 0xa3, 0x88, 0x17, 0x75, 0x93, 0x60, 0x97, 0x97, 0x71, 0x36, 0x53, 0xa8, 0x75, +0xae, 0x36, 0xe3, 0x55, 0x91, 0xa7, 0x4f, 0x6c, 0x8d, 0x05, 0x5f, 0x92, 0x14, 0xf2, 0x14, 0x11, +0xd5, 0x86, 0xa0, 0x93, 0x54, 0xe1, 0x25, 0xa6, 0x64, 0xe5, 0x1c, 0x2c, 0x4d, 0xd3, 0xd2, 0xd2, +0xec, 0xe5, 0x38, 0xb0, 0x0a, 0x90, 0xf6, 0x61, 0xf2, 0x47, 0x68, 0xfe, 0xf9, 0x65, 0x41, 0x0b, +0xd5, 0xf0, 0xfc, 0xe7, 0x62, 0xf5, 0xe7, 0xd4, 0x89, 0x8e, 0xde, 0x73, 0x0e, 0x9e, 0x00, 0x42, +0xc5, 0xfe, 0xe6, 0x22, 0x57, 0x24, 0x3c, 0xca, 0xe9, 0x61, 0x5b, 0xc3, 0x9b, 0xb5, 0x18, 0x3a, +0xea, 0x2f, 0x95, 0xf9, 0x9b, 0xa3, 0x79, 0x07, 0xa1, 0x64, 0x8c, 0x50, 0x80, 0xc6, 0x4c, 0x86, +0x70, 0xcb, 0x44, 0xc0, 0x57, 0x52, 0xad, 0x67, 0xa8, 0xd0, 0x6c, 0x68, 0xe9, 0xbf, 0x60, 0x8a, +0x6c, 0x15, 0x11, 0xbd, 0x38, 0xc8, 0xbe, 0x0a, 0xf9, 0x3f, 0x4f, 0x6c, 0xac, 0x7a, 0x4d, 0x2f, +0xec, 0x80, 0xf5, 0xa7, 0x13, 0x13, 0x54, 0x25, 0x22, 0x12, 0x92, 0xe4, 0xd7, 0x06, 0xd4, 0x0f, +0x0c, 0x3a, 0x93, 0x6c, 0x24, 0x04, 0x29, 0x9f, 0x31, 0x88, 0x36, 0xb3, 0xbf, 0xaa, 0xef, 0xf8, +0x64, 0x6f, 0x77, 0xb0, 0x49, 0xfd, 0xc6, 0xcb, 0x62, 0x91, 0x35, 0x41, 0x89, 0x69, 0xf0, 0x3e, +0xd1, 0x1f, 0xba, 0xc7, 0x5c, 0xf7, 0x54, 0xaa, 0x79, 0x0f, 0xe4, 0xf0, 0xc5, 0x98, 0xb2, 0x54, +0x11, 0x8c, 0x1d, 0xb8, 0x41, 0xd7, 0x6d, 0x85, 0x77, 0x6a, 0x73, 0x09, 0xb4, 0x34, 0xa3, 0xed, +0xf8, 0x5c, 0x31, 0xa4, 0x5b, 0x6b, 0xc4, 0xf9, 0xb5, 0x7c, 0x3e, 0x84, 0xd7, 0xb2, 0xbe, 0x6f, +0x72, 0x92, 0x29, 0x46, 0x89, 0xaa, 0xae, 0xd6, 0x6b, 0x9d, 0xc5, 0x9f, 0x57, 0x4c, 0x86, 0xa1, +0x57, 0x10, 0xfc, 0x42, 0xcf, 0x4d, 0xed, 0x62, 0x47, 0x5f, 0x86, 0xf0, 0x6c, 0x97, 0xb0, 0xd7, +0x4c, 0x65, 0x70, 0xfd, 0x2e, 0x8a, 0x62, 0x59, 0xba, 0x1a, 0xb2, 0x91, 0xd3, 0xae, 0x58, 0x3e, +0x26, 0x52, 0x3f, 0x94, 0xb0, 0xf8, 0x21, 0xd1, 0x0c, 0xda, 0x9d, 0xef, 0xb1, 0x51, 0x9c, 0xc9, +0xf3, 0xd5, 0xc5, 0xad, 0x7e, 0x20, 0x26, 0xf2, 0x23, 0x06, 0x60, 0x1d, 0xbb, 0x25, 0xf7, 0x9c, +0x54, 0xfb, 0xf0, 0x7e, 0xfe, 0x40, 0x86, 0x64, 0x15, 0x51, 0xd2, 0xec, 0x54, 0x0d, 0x77, 0x91, +0x5f, 0x03, 0x13, 0xdb, 0xf1, 0x99, 0x68, 0x98, 0x1f, 0xaa, 0x67, 0xb8, 0x71, 0xf4, 0x10, 0x8f, +0xb7, 0xfd, 0xef, 0xda, 0x94, 0xf9, 0x08, 0xbf, 0xbe, 0x35, 0x34, 0x92, 0xe4, 0x42, 0x7a, 0xfb, +0x5e, 0xe4, 0xea, 0x43, 0xbe, 0xf8, 0x46, 0x24, 0xe8, 0xe5, 0xe3, 0xd1, 0x2b, 0xa4, 0x03, 0x1b, +0x28, 0x02, 0x68, 0x1a, 0xcc, 0x82, 0x4a, 0xf7, 0x0c, 0x6c, 0x54, 0xe5, 0x18, 0xd5, 0x39, 0xcc, +0xc6, 0xcb, 0xff, 0xa7, 0x5b, 0x7b, 0xc4, 0xf9, 0xb5, 0x79, 0x12, 0x84, 0xd7, 0xb2, 0xbe, 0x6f, +0x72, 0x92, 0x29, 0x46, 0x89, 0xaa, 0xae, 0xd6, 0x6b, 0x9d, 0xc5, 0x9f, 0x57, 0x4c, 0x86, 0xa1, +0xdd, 0x84, 0x24, 0x69, 0x8a, 0x26, 0xf4, 0xab, 0xf0, 0xdc, 0xd7, 0x1b, 0xcb, 0x3e, 0x64, 0xb4, +0xe4, 0xff, 0x80, 0x50, 0x41, 0x30, 0xf9, 0xe3, 0xa8, 0xc3, 0x37, 0x80, 0x18, 0x3b, 0x8d, 0xc5, +0x4a, 0xfe, 0xfa, 0xe5, 0xba, 0x95, 0x12, 0x70, 0x5e, 0x32, 0xf4, 0xdb, 0x4e, 0x98, 0x1f, 0x6d, +0x58, 0x23, 0x16, 0xba, 0xb2, 0x39, 0x7a, 0x89, 0x23, 0xb9, 0x3f, 0xd7, 0xb0, 0x30, 0x73, 0x70, +0x1a, 0xd0, 0xf7, 0xfb, 0xd0, 0xd8, 0x76, 0xd2, 0x98, 0x3b, 0x34, 0x28, 0x2a, 0x08, 0xef, 0x1a, +0x84, 0x35, 0x94, 0xcd, 0x24, 0x54, 0x81, 0xfd, 0x01, 0x4d, 0xf9, 0x80, 0x7b, 0x5e, 0xf2, 0x1d, +0xfd, 0x3c, 0x79, 0x59, 0x5c, 0x0e, 0xc1, 0x3b, 0x2c, 0xd4, 0xe6, 0x72, 0x58, 0xb7, 0x3a, 0xca, +0x60, 0x44, 0x87, 0x30, 0xaf, 0xee, 0xae, 0xbc, 0x34, 0x8c, 0xc8, 0x3e, 0x85, 0x78, 0x59, 0xeb, +0xdf, 0x26, 0xbb, 0x2d, 0xfb, 0x3e, 0x50, 0xdf, 0xee, 0x91, 0xb8, 0x35, 0xf8, 0x85, 0x0b, 0x5f, +0x5f, 0xcf, 0x9d, 0x1c, 0xb1, 0x9c, 0xf0, 0xfe, 0x38, 0xa0, 0xc1, 0x24, 0x4e, 0x9e, 0xf7, 0x7c, +0x5d, 0xf3, 0x14, 0xf7, 0xdd, 0x88, 0x00, 0x48, 0x83, 0xde, 0x9d, 0x8e, 0xdd, 0x0d, 0xa6, 0x22, +0xd7, 0x48, 0x4d, 0xc7, 0x5f, 0x1d, 0x8b, 0x7c, 0x5f, 0x2f, 0xb5, 0xeb, 0xeb, 0x10, 0xc7, 0xd2, +0x4a, 0xc6, 0x6b, 0x76, 0x90, 0x44, 0xd8, 0xe6, 0x95, 0x6b, 0x37, 0x6e, 0xb5, 0x1b, 0xaf, 0x42, +0xca, 0x1a, 0xe4, 0x77, 0x30, 0xa1, 0x75, 0x18, 0x95, 0x86, 0xaa, 0xba, 0x4d, 0xd6, 0x1b, 0xc2, +0xea, 0x7a, 0xc5, 0x42, 0x18, 0x05, 0x3a, 0xdd, 0xe0, 0x9c, 0xfc, 0xa9, 0xff, 0x4d, 0x57, 0xaf, +0x52, 0xae, 0x96, 0x71, 0x8c, 0x62, 0xbd, 0x99, 0x62, 0xe1, 0xd8, 0x00, 0x29, 0x53, 0x88, 0x59, +0x10, 0x56, 0x2a, 0xc1, 0x86, 0x10, 0x95, 0x1f, 0x99, 0x0f, 0x3b, 0x83, 0x49, 0xfd, 0xf5, 0x7b, +0x32, 0x6b, 0xba, 0xa4, 0x65, 0x27, 0x7c, 0xfd, 0xec, 0x5a, 0x34, 0x28, 0x1a, 0xe7, 0x3e, 0x03, +0xe2, 0xb1, 0x64, 0xab, 0x2f, 0x86, 0x4c, 0xaa, 0x73, 0xc4, 0xe1, 0x6d, 0x7e, 0x90, 0x54, 0xbe, +0xd1, 0x95, 0x7e, 0x94, 0x4b, 0xa6, 0x2b, 0xec, 0x71, 0x21, 0x57, 0x6c, 0x32, 0x8b, 0x95, 0xab, +0x1a, 0xaf, 0xe5, 0x8c, 0x64, 0x29, 0x97, 0x7e, 0x6d, 0x6a, 0x25, 0x00, 0x18, 0x58, 0x91, 0x3a, +0xdc, 0xc4, 0xca, 0x49, 0xbc, 0x13, 0x7f, 0x2d, 0xcf, 0x58, 0xf0, 0x7d, 0x94, 0x8c, 0x89, 0x06, +0x57, 0xeb, 0xe0, 0xf4, 0x53, 0x5d, 0x6a, 0xc9, 0xfc, 0x92, 0xdd, 0x7e, 0x92, 0xe4, 0x43, 0x8f, +0x3a, 0xaf, 0x6f, 0x56, 0x8f, 0x5d, 0x2d, 0x34, 0x21, 0x6e, 0xa6, 0x7e, 0x42, 0xd2, 0x32, 0xc0, +0x78, 0x67, 0xf8, 0xe9, 0x0f, 0x4d, 0x68, 0x8f, 0x78, 0x5e, 0x10, 0x82, 0xfd, 0xc4, 0xe4, 0x7c, +0x07, 0x4a, 0xec, 0x14, 0x20, 0x82, 0x99, 0xcd, 0x05, 0xbe, 0xdf, 0x28, 0x63, 0xa7, 0xd5, 0xca, +0xcf, 0x64, 0x8c, 0xfc, 0x98, 0x7a, 0xd2, 0x72, 0x6c, 0x45, 0x0e, 0x01, 0x2a, 0x9c, 0xd2, 0x72, +0x84, 0x9c, 0x52, 0x9e, 0xd7, 0x74, 0x8a, 0xfe, 0xbc, 0x1c, 0x04, 0x6c, 0x82, 0x45, 0x05, 0x7d, +0x6d, 0x7e, 0x5e, 0x7b, 0x5c, 0x5e, 0xf2, 0xbd, 0xf6, 0x78, 0xd6, 0x37, 0x39, 0xc4, 0x2c, 0x74, +0x23, 0xa5, 0x90, 0x0b, 0x9f, 0xd1, 0x06, 0xa0, 0x5b, 0xc2, 0x51, 0x4c, 0xff, 0x6f, 0xa6, 0x60, +0x95, 0x01, 0x7c, 0x7c, 0xa6, 0x88, 0x86, 0x08, 0x1b, 0xbf, 0x40, 0x89, 0xfe, 0xbb, 0x3b, 0x1f, +0xeb, 0x79, 0xd8, 0xe8, 0x1e, 0x3b, 0xe5, 0x2b, 0x03, 0xb9, 0xc7, 0xfe, 0x64, 0xc9, 0x19, 0xa2, +0x57, 0xb6, 0x13, 0x3f, 0x96, 0xac, 0xc6, 0xcb, 0x7e, 0x5e, 0x1c, 0x3e, 0xc0, 0xc1, 0xfb, 0x55, +0x40, 0x56, 0x54, 0x15, 0x94, 0x21, 0x36, 0x6c, 0x04, 0x9d, 0xb1, 0x4f, 0x14, 0x83, 0xba, 0xfc, +0x03, 0xcc, 0x9e, 0x7e, 0xa8, 0x53, 0xec, 0xf8, 0x7b, 0x30, 0x77, 0x1b, 0x7d, 0xb7, 0x85, 0x39, +0x4f, 0x5d, 0xf3, 0x3d, 0xf5, 0xd2, 0x30, 0x3d, 0xfe, 0x4f, 0x97, 0xea, 0x2e, 0xdf, 0x31, 0xc9, +0xba, 0xa0, 0x0e, 0xf5, 0x98, 0x14, 0x54, 0x2f, 0x26, 0xb9, 0x62, 0x23, 0xd5, 0xf0, 0xb4, 0x29, +0x28, 0xe0, 0x1d, 0xc4, 0x7b, 0xd2, 0x1a, 0x4c, 0xf4, 0xd3, 0x3a, 0x1a, 0x98, 0x9b, 0xde, 0x6a, +0xf5, 0x61, 0x99, 0x5e, 0x16, 0x50, 0x99, 0xfd, 0xf4, 0x50, 0x80, 0x98, 0x32, 0x2d, 0xad, 0x32, +0xb4, 0x56, 0x6d, 0x1e, 0xe8, 0xa1, 0x57, 0xc4, 0x75, 0x68, 0x71, 0x89, 0xbd, 0x80, 0x31, 0xea, +0xba, 0x9e, 0xb2, 0x0b, 0xd6, 0xdc, 0xa4, 0xc7, 0xa6, 0x39, 0x8b, 0x45, 0x5e, 0xda, 0x57, 0xac, +0xa5, 0xa7, 0xea, 0x2b, 0xec, 0x0e, 0x23, 0xf9, 0x0b, 0x9a, 0xeb, 0xb2, 0x6f, 0x34, 0x35, 0xaf, +0xa1, 0x21, 0x35, 0xd9, 0xc4, 0x9a, 0xff, 0xb2, 0xdf, 0x0a, 0xf4, 0x2b, 0x4b, 0x74, 0x37, 0x1d, +0x14, 0x75, 0x45, 0xc1, 0x8e, 0x26, 0x33, 0x64, 0xc3, 0xe2, 0x23, 0x2d, 0xc3, 0xe7, 0x25, 0x12, +0xa5, 0x83, 0x96, 0x11, 0x35, 0x9b, 0x01, 0xdc, 0xc3, 0xcb, 0xc9, 0xc4, 0xaa, 0x99, 0x75, 0x47, +0xa4, 0xe4, 0x97, 0x06, 0x28, 0x7d, 0xc3, 0x40, 0x85, 0x16, 0xec, 0xb6, 0x43, 0x8b, 0x66, 0x74, +0x62, 0x52, 0xfa, 0x67, 0x75, 0x79, 0x21, 0x8b, 0x71, 0x1e, 0x33, 0x0d, 0xd6, 0x70, 0x98, 0xa0, +0x1b, 0x43, 0x23, 0x23, 0xa6, 0x7e, 0xc6, 0x18, 0x02, 0xb3, 0x69, 0xd7, 0xb9, 0x96, 0xc5, 0x92, +0x37, 0x3b, 0x2e, 0x5b, 0x30, 0x4e, 0x1d, 0xc5, 0x91, 0xda, 0x54, 0xe3, 0x47, 0xf8, 0x86, 0xe0, +0x8b, 0xcf, 0xdc, 0xad, 0x97, 0x38, 0x6b, 0xdd, 0xea, 0x1c, 0xa0, 0x8d, 0x19, 0x14, 0x7e, 0x9b, +0xa8, 0x54, 0xa6, 0xda, 0x16, 0xd0, 0x80, 0xb2, 0xdb, 0x6b, 0xd6, 0x92, 0x03, 0x84, 0x01, 0x63, +0x28, 0x26, 0x40, 0xe8, 0xfa, 0x86, 0x4f, 0x56, 0xfe, 0xcf, 0x8e, 0x1b, 0x97, 0xbe, 0x93, 0xc8, +0x1f, 0xe2, 0xd9, 0x18, 0x44, 0xbe, 0x53, 0xe9, 0xb8, 0xae, 0x5a, 0xe4, 0xd1, 0x88, 0xcd, 0xec, +0x75, 0xdb, 0xc8, 0x48, 0x66, 0x14, 0x75, 0x2e, 0x95, 0xa5, 0x67, 0x0a, 0x73, 0x85, 0xc1, 0x83, +0x31, 0x40, 0xea, 0x06, 0x6d, 0xcd, 0x3c, 0x58, 0x4b, 0xa3, 0x5f, 0x90, 0x35, 0xc4, 0x52, 0x15, +0x97, 0xd7, 0x1a, 0xce, 0xec, 0x28, 0x59, 0xd9, 0x56, 0x29, 0x62, 0xaa, 0x85, 0x04, 0xbb, 0x6f, +0x89, 0x0d, 0x1b, 0x28, 0x4f, 0xe3, 0x99, 0x88, 0xeb, 0x3a, 0x65, 0x39, 0x86, 0x78, 0x93, 0x22, +0x6f, 0x6a, 0x0b, 0x90, 0xa7, 0xcf, 0x94, 0x4a, 0x9a, 0xcc, 0xd7, 0x58, 0xe0, 0xd2, 0xb6, 0x9c, +0xc4, 0x82, 0xd5, 0xe9, 0x8a, 0x79, 0x18, 0x82, 0x66, 0xf8, 0xa4, 0xa2, 0x59, 0xf8, 0x78, 0x1e, +0x16, 0x23, 0x7f, 0x88, 0x06, 0xa0, 0x5e, 0x0a, 0x77, 0xc2, 0x2b, 0x5a, 0x31, 0xdf, 0x1e, 0xe4, +0x3e, 0x33, 0x45, 0x53, 0xc0, 0x8b, 0x3b, 0x22, 0x53, 0x04, 0x96, 0xbb, 0x9f, 0x60, 0xa2, 0x47, +0x26, 0xc3, 0x31, 0xcb, 0xe3, 0xfb, 0xc4, 0xcd, 0x84, 0x76, 0xde, 0x4f, 0x71, 0x3c, 0x1b, 0xfa, +0xef, 0xb6, 0x06, 0xc6, 0x74, 0x00, 0x81, 0x4c, 0x90, 0x21, 0xfe, 0x07, 0x88, 0xc6, 0x74, 0x2e, +0xaf, 0x28, 0xe8, 0x96, 0x69, 0xf9, 0x54, 0xfd, 0xac, 0x61, 0x9a, 0x7b, 0x32, 0xbc, 0x4a, 0x80, +0xd4, 0x5d, 0xb9, 0xfe, 0xad, 0x77, 0xf3, 0x90, 0x8c, 0xd6, 0x76, 0xfa, 0xcf, 0x95, 0xb9, 0x0f, +0x14, 0x41, 0x2f, 0xdf, 0x14, 0xd4, 0xb0, 0x54, 0xe3, 0x5c, 0xf0, 0x7f, 0xf1, 0xc9, 0xc3, 0x75, +0x2d, 0x56, 0xb2, 0xc2, 0x12, 0x81, 0xc4, 0x45, 0xe7, 0xe2, 0xa3, 0x8a, 0xe4, 0x6f, 0x3f, 0x9a, +0xe0, 0x89, 0xd6, 0x6a, 0x82, 0xaa, 0x28, 0x84, 0x33, 0xa7, 0xc7, 0x42, 0xe4, 0x2f, 0x2a, 0x17, +0xe2, 0xe1, 0x76, 0x6e, 0x82, 0x5f, 0xaf, 0x7e, 0x78, 0xa9, 0xa6, 0xa5, 0xaa, 0x35, 0x8b, 0x8a, +0xc1, 0xf4, 0xd7, 0xdb, 0xfe, 0x7a, 0x98, 0x52, 0xe5, 0x2c, 0x2f, 0x58, 0xe3, 0xa1, 0x0f, 0xca, +0xc2, 0xa8, 0xe4, 0xc4, 0x04, 0xa0, 0xc5, 0x7a, 0x02, 0x5d, 0x37, 0x90, 0xc6, 0x3e, 0x0a, 0xed, +0xc9, 0x3b, 0xcb, 0x87, 0x08, 0x2f, 0x89, 0x0e, 0x78, 0x0e, 0xeb, 0x6e, 0xb0, 0xf2, 0x6f, 0xa7, +0x70, 0xe1, 0x31, 0x0e, 0x39, 0x66, 0x22, 0xab, 0xf4, 0x94, 0xf7, 0xfc, 0x54, 0x10, 0x4f, 0x97, +0x24, 0x6d, 0xce, 0xf9, 0x60, 0x77, 0x07, 0x78, 0x04, 0xfc, 0x01, 0x53, 0x42, 0x92, 0xfe, 0x87, +0x5f, 0x43, 0xcb, 0xf9, 0x62, 0x4b, 0xfb, 0xb1, 0x00, 0xd0, 0x5f, 0xb5, 0x75, 0xa9, 0x21, 0xa8, +0xfd, 0x04, 0x84, 0x73, 0x73, 0x34, 0x51, 0x33, 0xf0, 0xdd, 0x25, 0xea, 0x93, 0x33, 0x9c, 0x0f, +0xce, 0x3e, 0xd8, 0xb7, 0xdb, 0x17, 0x7b, 0xcd, 0x06, 0x01, 0x02, 0x00, 0x71, 0x50, 0x82, 0x49, +0x29, 0x82, 0x4e, 0xfb, 0x89, 0x2b, 0xe3, 0x5f, 0x02, 0x0c, 0x50, 0xbf, 0x9e, 0x1e, 0xfb, 0x43, +0x8d, 0x67, 0xa5, 0xec, 0x1b, 0xb3, 0x75, 0x74, 0xa0, 0xed, 0x57, 0x16, 0x17, 0x5e, 0xa9, 0x32, +0xe2, 0x1f, 0x98, 0x2d, 0xfe, 0x4c, 0x5b, 0x34, 0xf2, 0x79, 0x41, 0xbf, 0x3c, 0x42, 0xc5, 0x68, +0xa5, 0xb1, 0xe1, 0x53, 0xaf, 0xc8, 0x7e, 0x34, 0x94, 0xec, 0xcf, 0x38, 0xb4, 0xc4, 0xe1, 0x1b, +0x85, 0x2e, 0xb6, 0x61, 0xc1, 0xd5, 0x40, 0x93, 0x6b, 0x19, 0xab, 0x49, 0x6e, 0xd2, 0x2e, 0x7e, +0xab, 0xdd, 0xda, 0xbd, 0x9b, 0xaf, 0xa7, 0x0c, 0x37, 0x95, 0x05, 0x2f, 0x36, 0x56, 0x51, 0x58, +0x26, 0xca, 0x31, 0xbf, 0x74, 0xb2, 0xe4, 0x5e, 0xa5, 0xe8, 0xc5, 0xfc, 0xf2, 0xb5, 0xeb, 0x10, +0x84, 0xb7, 0x7f, 0x27, 0x6e, 0x72, 0xd7, 0x6b, 0xdd, 0xc6, 0x5c, 0xe5, 0xfa, 0xb8, 0xc9, 0xe4, +0x54, 0x4b, 0x1d, 0x8f, 0x49, 0xd1, 0x4c, 0xa3, 0x62, 0x4e, 0x0b, 0xf9, 0x9a, 0x34, 0x2c, 0x33, +0xd9, 0x2f, 0x2d, 0xc5, 0x7d, 0xd9, 0x19, 0x5f, 0xd8, 0x49, 0x03, 0x05, 0xa3, 0xd4, 0x37, 0xa0, +0x32, 0x5f, 0xe9, 0x55, 0x07, 0x91, 0x5e, 0x10, 0x49, 0x09, 0xf5, 0x82, 0x9e, 0x84, 0x66, 0xa8, +0x29, 0xae, 0xec, 0x3c, 0x16, 0x38, 0x60, 0xaa, 0x73, 0xb8, 0x9b, 0x85, 0x6a, 0x4d, 0x23, 0x62, +0x37, 0x52, 0xcf, 0x26, 0x2a, 0x10, 0x5b, 0xb3, 0x12, 0xde, 0x50, 0xca, 0x2e, 0x4c, 0x78, 0xb0, +0xbe, 0x74, 0xd7, 0x79, 0xa5, 0x17, 0x0b, 0x92, 0x79, 0xa6, 0xe1, 0x81, 0x6b, 0xd8, 0xed, 0xd4, +0x2e, 0xc0, 0x31, 0x03, 0x73, 0xae, 0x50, 0xf7, 0xb0, 0x32, 0x38, 0xd3, 0xd1, 0x06, 0x11, 0x23, +0x56, 0x26, 0x75, 0x3f, 0xe1, 0x3f, 0xfa, 0x9e, 0xce, 0x3f, 0x5c, 0x69, 0x6f, 0xa5, 0x85, 0x14, +0xa1, 0x23, 0x14, 0x21, 0xc7, 0x02, 0xfb, 0x15, 0x17, 0xcf, 0x45, 0xa9, 0xd1, 0x56, 0x26, 0xc1, +0x10, 0xf0, 0x52, 0x4c, 0x88, 0xe0, 0xfb, 0xef, 0x95, 0xbf, 0x93, 0xd1, 0x1f, 0xc0, 0xbf, 0xb0, +0x99, 0x5c, 0xb8, 0x2d, 0x76, 0xa3, 0xd6, 0x31, 0x70, 0x7f, 0xa9, 0x5f, 0x05, 0x61, 0x74, 0xfe, +0xf4, 0xd4, 0xe2, 0xfb, 0x5a, 0xa4, 0x20, 0xed, 0xc5, 0xb1, 0x7b, 0x63, 0xdc, 0xc2, 0x7b, 0x87, +0x73, 0x72, 0x54, 0x57, 0x3c, 0x2e, 0xd1, 0x53, 0xe7, 0x8d, 0x14, 0xe8, 0x9d, 0x9e, 0xd1, 0xff, +0xaa, 0x3b, 0xee, 0x1d, 0x91, 0xd9, 0x55, 0xb3, 0x4b, 0x31, 0x13, 0x28, 0xd6, 0xdf, 0x19, 0xe2, +0xa4, 0x6d, 0xf4, 0x1d, 0x1c, 0xba, 0x85, 0xa5, 0xb8, 0x8e, 0xe9, 0x66, 0x72, 0x6d, 0xef, 0xdb, +0x00, 0xa6, 0x10, 0xc3, 0x13, 0x60, 0x3e, 0x46, 0x7c, 0x95, 0xca, 0xcc, 0x3c, 0x45, 0xa8, 0x99, +0x2c, 0x18, 0xd3, 0xcd, 0xeb, 0x3a, 0x7c, 0xc2, 0x78, 0xb3, 0xe0, 0x20, 0xa5, 0x72, 0x17, 0x31, +0x11, 0x98, 0x73, 0x6e, 0x2b, 0x75, 0x27, 0xaa, 0x4c, 0x84, 0xf3, 0x38, 0xc2, 0x67, 0x1e, 0xf4, +0x25, 0xd3, 0xc3, 0x6b, 0x8c, 0x09, 0xff, 0xce, 0x57, 0xdd, 0xbe, 0x82, 0xbe, 0x90, 0x0c, 0xfa, +0x3d, 0x18, 0xe2, 0xc1, 0x92, 0xbb, 0xf7, 0x91, 0xdd, 0xda, 0x92, 0x47, 0x96, 0xee, 0x93, 0x94, +0xec, 0x55, 0x64, 0x62, 0xdf, 0x2c, 0x42, 0x3e, 0x7f, 0xb9, 0x2a, 0xaf, 0x31, 0x9b, 0xa7, 0x18, +0x20, 0x7f, 0xf8, 0xf9, 0xb6, 0x61, 0x77, 0x02, 0x84, 0x3f, 0x4f, 0x8f, 0xb6, 0x60, 0xa4, 0x54, +0xa3, 0x23, 0x31, 0xb9, 0xf9, 0x74, 0xf7, 0xef, 0x57, 0xe7, 0x62, 0x3e, 0xa2, 0x8a, 0x5d, 0x25, +0x72, 0x86, 0x4e, 0xc0, 0xd2, 0xff, 0x60, 0x3f, 0x06, 0x21, 0x8c, 0xf9, 0xb8, 0x6b, 0xb8, 0xb3, +0x6e, 0xc9, 0xdb, 0xaa, 0x5b, 0xfd, 0x6b, 0x92, 0x63, 0x63, 0xaf, 0xee, 0x50, 0x1f, 0x8f, 0xcb, +0xab, 0x18, 0xaf, 0x95, 0xe1, 0x2b, 0x20, 0x7a, 0xa3, 0x26, 0x33, 0x17, 0xf5, 0x70, 0xc0, 0x42, +0x73, 0x82, 0xaf, 0x69, 0xab, 0x27, 0xf3, 0xa1, 0x8e, 0x2b, 0x70, 0x7d, 0x39, 0xcf, 0x81, 0x5c, +0xff, 0xc4, 0x7c, 0x0d, 0xee, 0xa5, 0x0c, 0x5f, 0xaf, 0x76, 0xe5, 0x19, 0xba, 0x3e, 0xf3, 0x00, +0xff, 0x70, 0x3d, 0x70, 0xd9, 0x9d, 0xef, 0x4e, 0x83, 0xda, 0xca, 0x11, 0xdf, 0x08, 0xd7, 0xb0, +0x87, 0xe3, 0x11, 0xb8, 0xde, 0xa3, 0xc1, 0x98, 0xe4, 0xd2, 0x3b, 0xb0, 0x66, 0xa5, 0x31, 0x66, +0xbb, 0x84, 0xce, 0x5e, 0x14, 0x65, 0xdd, 0xc3, 0xce, 0xb7, 0x1d, 0x13, 0x24, 0xcc, 0xb1, 0x97, +0xbb, 0x47, 0x5e, 0x5f, 0x15, 0x33, 0x84, 0xd4, 0xe0, 0xa7, 0xeb, 0x94, 0x10, 0xf0, 0xbb, 0xb8, +0x02, 0x63, 0x0e, 0xce, 0x5e, 0x0b, 0xda, 0x43, 0x0e, 0xd6, 0xbc, 0x74, 0x81, 0x30, 0x7d, 0x2d, +0xcf, 0x87, 0x8d, 0x51, 0x51, 0x8b, 0xea, 0x6d, 0x1d, 0xde, 0x33, 0xfe, 0x50, 0xdd, 0xd7, 0x57, +0xbe, 0xbc, 0x79, 0x34, 0x9b, 0x33, 0x24, 0xf7, 0x4a, 0x37, 0x4b, 0xab, 0xaf, 0x42, 0xb4, 0x64, +0xd7, 0x19, 0x6d, 0xfd, 0xde, 0xa7, 0xd6, 0x5e, 0x8c, 0x6f, 0xb7, 0xbb, 0x13, 0xbc, 0xe4, 0x09, +0x94, 0x0c, 0xe3, 0xa8, 0x5f, 0xb1, 0x26, 0x1f, 0xc6, 0x63, 0xc0, 0x85, 0x0f, 0x37, 0x4b, 0x08, +0xf6, 0xfc, 0xe8, 0x93, 0x9e, 0x15, 0xd5, 0xc3, 0xc0, 0x24, 0x30, 0x41, 0xff, 0x2e, 0x32, 0x65, +0xe7, 0xd7, 0x0e, 0xd3, 0xc7, 0x81, 0x79, 0x84, 0xdb, 0xfa, 0x45, 0x55, 0x78, 0xe3, 0xb4, 0x35, +0xa7, 0x62, 0xf4, 0x0f, 0x66, 0xb4, 0x1a, 0x3a, 0x93, 0xde, 0x79, 0x6e, 0x9a, 0xe5, 0xa5, 0xd1, +0x5e, 0x7d, 0x0a, 0x02, 0x09, 0xcd, 0xc3, 0x41, 0x2e, 0x3d, 0x98, 0xac, 0x2b, 0x2e, 0x21, 0xf9, +0xfb, 0x3d, 0x74, 0x06, 0x69, 0xf9, 0x8e, 0xa8, 0xdb, 0xf9, 0x23, 0xb6, 0x6d, 0x89, 0xc6, 0x86, +0x6b, 0x43, 0x72, 0x6b, 0x96, 0x4f, 0x96, 0xe4, 0xe6, 0xf8, 0x16, 0xd3, 0x8c, 0x75, 0xf4, 0x0a, +0x0a, 0x2b, 0x67, 0xcb, 0x9c, 0xb8, 0x31, 0x97, 0x2b, 0x9e, 0x08, 0xe1, 0xf2, 0xb4, 0x0a, 0xc7, +0x4d, 0xca, 0xed, 0xf3, 0x90, 0xf0, 0xda, 0x34, 0x53, 0xcf, 0xc9, 0xa6, 0xa0, 0xbb, 0xa2, 0x0a, +0x9a, 0x56, 0x19, 0xf4, 0x21, 0x9a, 0x60, 0x54, 0xd2, 0x5d, 0x06, 0xa6, 0x16, 0xbc, 0xa0, 0x9f, +0x82, 0x1a, 0xd1, 0xb0, 0x3d, 0xef, 0xa9, 0xf4, 0xdb, 0x49, 0xfb, 0xb7, 0xac, 0xfb, 0x4e, 0x64, +0xc4, 0x7a, 0x03, 0x5f, 0x30, 0xaf, 0x59, 0x9d, 0x1b, 0x52, 0x04, 0x7d, 0x84, 0x86, 0x5a, 0x13, +0x38, 0x45, 0xa4, 0x4d, 0x01, 0xe4, 0xdf, 0x6b, 0x77, 0xcb, 0x71, 0xe7, 0x58, 0xe7, 0x5b, 0x3a, +0x19, 0xf1, 0x69, 0xd8, 0xd9, 0xab, 0x4a, 0x45, 0x0e, 0x59, 0x1d, 0xcd, 0x97, 0xf9, 0x1a, 0xf3, +0x51, 0xb4, 0xdc, 0xcb, 0x78, 0xf6, 0x5f, 0x2e, 0x2e, 0x91, 0xcc, 0x67, 0x68, 0x00, 0x10, 0x5c, +0xa5, 0xf4, 0x6a, 0x59, 0xb8, 0xde, 0x9b, 0x2d, 0x93, 0x4e, 0x8c, 0xb4, 0x6f, 0x3c, 0xa2, 0x6d, +0x61, 0xcf, 0x11, 0xcd, 0x66, 0xc6, 0x85, 0xca, 0xad, 0xa3, 0xcb, 0xb4, 0xa7, 0x55, 0xd2, 0x2c, +0x78, 0x02, 0x59, 0x50, 0x15, 0xbd, 0x6a, 0xc4, 0x39, 0x7f, 0x5d, 0x87, 0xd2, 0x42, 0x85, 0xce, +0xfa, 0x7f, 0x93, 0xde, 0x74, 0xe0, 0x10, 0x70, 0xc7, 0x43, 0xed, 0x09, 0xf1, 0x88, 0x69, 0xfa, +0x6a, 0xa7, 0x30, 0x83, 0xda, 0xbc, 0x12, 0x89, 0xcb, 0xed, 0x12, 0x86, 0xce, 0x97, 0xe6, 0xec, +0xea, 0x2c, 0xc7, 0xb9, 0xc9, 0x26, 0x78, 0x49, 0xbb, 0xd5, 0x74, 0x37, 0x1c, 0x5d, 0x9f, 0x77, +0x34, 0x46, 0x8c, 0x12, 0xf7, 0x94, 0xea, 0xd3, 0x64, 0xc8, 0x3a, 0x1b, 0xfe, 0x4e, 0x31, 0x02, +0xbc, 0xed, 0x38, 0x1e, 0x07, 0x18, 0x2a, 0x8e, 0xa0, 0x20, 0x14, 0xfa, 0x9b, 0x40, 0xfd, 0x84, +0x7c, 0xcb, 0x6a, 0x16, 0x2a, 0xb5, 0x5f, 0x42, 0x94, 0xa8, 0xa0, 0x54, 0x8f, 0x81, 0x54, 0xf0, +0xed, 0x65, 0xa6, 0x3f, 0x08, 0xe7, 0x0e, 0x66, 0xbb, 0xbc, 0x7a, 0x88, 0xb5, 0xdf, 0x47, 0x60, +0xc4, 0x9c, 0xf0, 0xc1, 0xcf, 0xaf, 0xfd, 0x3d, 0xbb, 0x03, 0xce, 0x60, 0x04, 0xfe, 0xc0, 0x98, +0x76, 0xe5, 0xd2, 0xac, 0xb6, 0x18, 0x1c, 0x01, 0x82, 0xdf, 0xbf, 0x89, 0xec, 0x6e, 0xf6, 0xf7, +0x97, 0x59, 0xcb, 0x48, 0x75, 0x4d, 0x80, 0x56, 0x26, 0x17, 0x59, 0x58, 0xa4, 0x68, 0x7e, 0x13, +0x04, 0xf3, 0x50, 0x2a, 0x13, 0x98, 0x18, 0x95, 0x71, 0xd5, 0xb8, 0x24, 0xb3, 0x16, 0xf7, 0xc5, +0x89, 0xe1, 0x92, 0xa0, 0x20, 0xd9, 0xa5, 0x61, 0x67, 0x8a, 0x2b, 0xcb, 0xdd, 0x28, 0x4c, 0xf6, +0x0c, 0xcd, 0x54, 0xc6, 0x42, 0x1f, 0x2f, 0xb8, 0x59, 0xf8, 0x60, 0x15, 0x8e, 0x60, 0xa7, 0x31, +0xf6, 0x0a, 0x06, 0xf6, 0x77, 0x36, 0x8f, 0x11, 0xa6, 0x33, 0xd9, 0x8a, 0x50, 0x20, 0xad, 0x17, +0xea, 0x47, 0x23, 0xd4, 0x40, 0x09, 0x9e, 0xcd, 0x8a, 0x37, 0x0e, 0x1a, 0xc0, 0x05, 0x74, 0xfd, +0xfa, 0x46, 0x23, 0x34, 0x1e, 0x88, 0x24, 0x4e, 0x21, 0x4c, 0xb9, 0x67, 0x14, 0xb8, 0x78, 0xc9, +0xbe, 0x2d, 0x14, 0xff, 0xe9, 0xdc, 0x15, 0x5c, 0x98, 0x52, 0xd1, 0x50, 0x16, 0x81, 0xb7, 0x7e, +0xb2, 0xee, 0x81, 0xbd, 0xe5, 0x28, 0xc3, 0xae, 0x9d, 0x98, 0xa3, 0x61, 0xd2, 0x04, 0x70, 0x4c, +0xdd, 0x9d, 0xb8, 0x76, 0xd7, 0xee, 0x88, 0x44, 0xc2, 0x35, 0x47, 0x89, 0x55, 0x98, 0xed, 0xc6, +0x6d, 0x9c, 0x0b, 0x3f, 0x0d, 0x5c, 0xbe, 0x30, 0x80, 0x64, 0x33, 0x56, 0x92, 0x49, 0xad, 0xd2, +0xbb, 0x0f, 0xe2, 0x66, 0x96, 0xda, 0xcd, 0xe2, 0x0d, 0x27, 0xf3, 0xa6, 0xda, 0x5e, 0xb8, 0xd9, +0x91, 0xab, 0x2b, 0x9a, 0x89, 0xef, 0x5e, 0xf6, 0xdd, 0x49, 0x50, 0xd3, 0x1b, 0xd5, 0x15, 0x9c, +0x7b, 0xf8, 0x51, 0xf1, 0xb9, 0x44, 0xc7, 0xad, 0xd8, 0xc9, 0xc6, 0x70, 0x52, 0x93, 0xeb, 0xd4, +0x8e, 0x24, 0xd6, 0x23, 0xa2, 0xf8, 0x86, 0x4e, 0x01, 0x96, 0x9b, 0xfb, 0x54, 0xb4, 0xaa, 0x46, +0x8e, 0x9e, 0x27, 0x83, 0xfa, 0xc1, 0x5a, 0x3c, 0x0a, 0x0f, 0xa1, 0x41, 0xb5, 0xbe, 0x9f, 0xd6, +0x02, 0x8b, 0xfd, 0x7c, 0xb2, 0xdc, 0xeb, 0xd3, 0x27, 0x2c, 0x01, 0x43, 0xdf, 0x78, 0xbb, 0xb4, +0x12, 0xbb, 0xcc, 0x9a, 0x9e, 0x5c, 0xb8, 0x11, 0xfe, 0x38, 0x46, 0x56, 0x58, 0x91, 0xa2, 0x87, +0xb5, 0x18, 0x0a, 0x01, 0xe8, 0x52, 0xc5, 0xb2, 0x67, 0x3a, 0xa1, 0x33, 0xd1, 0x58, 0x81, 0x88, +0x13, 0xab, 0xcf, 0xf2, 0xb7, 0xb8, 0x47, 0x64, 0x92, 0x4a, 0xe7, 0xfd, 0x8f, 0xe3, 0xe8, 0xc9, +0x0b, 0x4c, 0x94, 0xf4, 0x53, 0x1f, 0x20, 0xa2, 0xfc, 0xe0, 0x5e, 0x53, 0x69, 0x28, 0x48, 0x56, +0x47, 0xda, 0xe1, 0xf5, 0xd7, 0x03, 0x02, 0xba, 0xa7, 0x2f, 0xb5, 0xb3, 0x5a, 0xe1, 0x12, 0xf3, +0x79, 0x84, 0x27, 0x62, 0xd0, 0x44, 0xc5, 0xa8, 0xf0, 0xca, 0xb8, 0xa2, 0x10, 0x49, 0x7b, 0xfc, +0xad, 0x9d, 0xfb, 0xeb, 0x51, 0x76, 0x6b, 0x5e, 0xd5, 0x1e, 0xd0, 0xc2, 0x9e, 0x87, 0xb7, 0x33, +0x7f, 0xf9, 0x7e, 0xf5, 0xaa, 0xed, 0xc0, 0x02, 0x73, 0x2c, 0x7c, 0x71, 0xf3, 0x0b, 0xdb, 0xcd, +0xdd, 0xa4, 0xd7, 0x53, 0xd5, 0x25, 0x2c, 0xde, 0xc2, 0xf1, 0x88, 0x7b, 0x34, 0x92, 0xa5, 0xb4, +0x7c, 0xbc, 0x59, 0x4f, 0x12, 0xdc, 0xd9, 0xfd, 0x92, 0x5a, 0xc2, 0xde, 0x1f, 0x7c, 0x3d, 0x69, +0x0c, 0x2c, 0xf8, 0x93, 0x39, 0x4f, 0x51, 0x50, 0x6a, 0xda, 0xb2, 0x33, 0x24, 0x0b, 0xd0, 0xe0, +0xee, 0x42, 0xd7, 0x55, 0xd6, 0xea, 0x13, 0x63, 0xb7, 0xf0, 0xac, 0x5a, 0x6b, 0x6a, 0x0d, 0xcb, +0x68, 0x30, 0x91, 0x18, 0x79, 0x2e, 0x84, 0x9c, 0x4c, 0x65, 0xab, 0xf3, 0x49, 0xf7, 0xcf, 0x79, +0xa1, 0x2b, 0x38, 0x39, 0x7a, 0xb0, 0x45, 0x59, 0xf5, 0xc5, 0x94, 0xc2, 0x94, 0x17, 0xa9, 0x28, +0x5f, 0x6e, 0x7b, 0x32, 0xda, 0x71, 0x1a, 0x7f, 0xe6, 0xea, 0x1c, 0x12, 0x34, 0x56, 0x55, 0x48, +0x53, 0xf6, 0x04, 0x0b, 0xe0, 0x34, 0xdd, 0x5b, 0x3f, 0x47, 0xcc, 0x96, 0x50, 0xd6, 0xa9, 0x03, +0xe2, 0xca, 0x2d, 0x08, 0xd7, 0xdc, 0x8a, 0x6d, 0x27, 0x41, 0x05, 0xd5, 0xc2, 0xfd, 0x40, 0xb9, +0xeb, 0x4d, 0x56, 0x85, 0x2f, 0xec, 0xe4, 0xbb, 0x20, 0x3c, 0x3d, 0xc9, 0xff, 0xbf, 0x98, 0x13, +0x4c, 0xeb, 0xab, 0x8c, 0x11, 0x60, 0xc8, 0x23, 0x1f, 0x5e, 0x0d, 0x4b, 0x76, 0x9c, 0x49, 0xad, +0xd2, 0x22, 0x2e, 0x72, 0x60, 0x34, 0x34, 0xbb, 0x92, 0xb6, 0x8f, 0x08, 0x54, 0x40, 0x50, 0xde, +0x1c, 0x43, 0x07, 0x5b, 0x45, 0x69, 0x49, 0x2b, 0x9b, 0xad, 0x1c, 0xf4, 0x09, 0x3d, 0x9a, 0x6f, +0x81, 0xae, 0xe6, 0xd3, 0x15, 0x8b, 0xb6, 0xdb, 0xd4, 0x45, 0xb1, 0xec, 0x9d, 0x17, 0x58, 0xc6, +0xf0, 0xa7, 0xc1, 0x65, 0x0d, 0x64, 0x82, 0xe4, 0xf4, 0xb0, 0x25, 0xa9, 0x1e, 0x6d, 0x5c, 0x42, +0x17, 0x9d, 0xa4, 0x3d, 0xb5, 0xf3, 0x40, 0xdf, 0xc9, 0xc3, 0xa1, 0xc6, 0xaa, 0xa0, 0x03, 0x3a, +0x65, 0x8d, 0x01, 0x6f, 0x0a, 0x70, 0xdd, 0x0d, 0x38, 0xc4, 0xe9, 0x30, 0xea, 0x7b, 0x7b, 0xce, +0xfb, 0xac, 0x0a, 0x92, 0xc0, 0x32, 0x5c, 0xcd, 0x93, 0x0f, 0xf4, 0xdb, 0x1a, 0x74, 0xbb, 0x3e, +0x09, 0x76, 0xd3, 0x5b, 0x1f, 0xb1, 0x98, 0x70, 0xda, 0x86, 0x43, 0x16, 0x99, 0x71, 0xcd, 0xd6, +0x5c, 0x4a, 0x23, 0xde, 0x7c, 0x2d, 0xba, 0x7d, 0xb8, 0x60, 0x5e, 0xea, 0x73, 0xa9, 0x00, 0x59, +0xb5, 0x29, 0x2e, 0xae, 0x78, 0xa2, 0xc7, 0x31, 0x19, 0x63, 0x34, 0x20, 0x35, 0x72, 0x21, 0x84, +0x7e, 0x80, 0x94, 0x33, 0xf9, 0x08, 0x0b, 0xc5, 0x77, 0x19, 0xc1, 0x2a, 0x6c, 0x09, 0xdf, 0xb3, +0x98, 0x4b, 0x15, 0x65, 0x44, 0x6d, 0xd0, 0xbd, 0x80, 0x41, 0xd3, 0x6b, 0xb9, 0xc8, 0x7e, 0x88, +0x82, 0xbc, 0x05, 0x6b, 0xb9, 0x08, 0x9c, 0x67, 0x1f, 0x47, 0x8c, 0x71, 0x5d, 0x15, 0x90, 0x3d, +0x0b, 0x1d, 0xbe, 0x8d, 0xb4, 0x70, 0xc0, 0x56, 0x61, 0xba, 0xe9, 0x84, 0xf9, 0xaf, 0xf1, 0x00, +0xfe, 0x92, 0x67, 0x5d, 0xd6, 0x94, 0x5e, 0xf6, 0x54, 0x83, 0x58, 0x90, 0x72, 0xaa, 0xc0, 0x24, +0x81, 0xba, 0x34, 0x92, 0x29, 0xaf, 0xc4, 0x00, 0xbf, 0x2d, 0xff, 0x14, 0x6d, 0x40, 0x70, 0x3f, +0x22, 0x09, 0x17, 0xe1, 0x3d, 0xbd, 0x16, 0x82, 0x69, 0x46, 0x76, 0xad, 0xac, 0x25, 0x34, 0x75, +0xcf, 0x7d, 0xe7, 0xc5, 0x8b, 0x00, 0x3b, 0x89, 0x38, 0xe5, 0x4c, 0xdb, 0x29, 0x60, 0x2f, 0x9d, +0x42, 0x63, 0xfa, 0xf8, 0x5a, 0x51, 0x52, 0x8d, 0x97, 0xd1, 0xae, 0x84, 0x67, 0x56, 0x55, 0x70, +0xd6, 0x47, 0xe2, 0x60, 0x00, 0x0b, 0x53, 0xc6, 0xe1, 0x43, 0x18, 0x0c, 0xb6, 0xd6, 0xc1, 0x33, +0x9d, 0xb3, 0x46, 0x31, 0xbe, 0x88, 0x6e, 0x09, 0x0a, 0x78, 0x05, 0x43, 0xb7, 0x8d, 0x8a, 0xdc, +0xba, 0xf4, 0x05, 0xab, 0x47, 0x7e, 0x94, 0x28, 0x5f, 0xf3, 0xc6, 0x9a, 0x1a, 0x1c, 0x04, 0x6f, +0x9d, 0x1c, 0xa2, 0xe8, 0x10, 0x75, 0x08, 0x36, 0x83, 0xb2, 0x7c, 0x8f, 0xae, 0xc6, 0x40, 0x2f, +0xb5, 0x77, 0xff, 0x99, 0xe9, 0x3e, 0x13, 0x31, 0x4d, 0x2c, 0x7e, 0x19, 0xf2, 0x40, 0xfa, 0x7d, +0xaa, 0x07, 0xa3, 0x38, 0x4b, 0x4f, 0xdd, 0xb4, 0x13, 0x27, 0x19, 0xf0, 0x27, 0x34, 0xc7, 0x90, +0x00, 0xc8, 0x34, 0x0f, 0xce, 0xd7, 0x3b, 0x24, 0xcb, 0x98, 0x1d, 0x10, 0xe0, 0xb3, 0x74, 0x43, +0xb2, 0x11, 0xb5, 0x28, 0xf0, 0xeb, 0x4c, 0x4f, 0x1b, 0xf7, 0xc0, 0xfd, 0xf0, 0x61, 0x1a, 0x91, +0xeb, 0xaf, 0x7a, 0x50, 0x4c, 0x6c, 0x9c, 0xfe, 0x74, 0xbf, 0x62, 0x18, 0x55, 0x58, 0xd1, 0xb9, +0xd1, 0xe9, 0x22, 0x23, 0x44, 0x2c, 0x66, 0xc0, 0x17, 0xd7, 0xc8, 0xe1, 0xe1, 0x74, 0xea, 0x42, +0xb0, 0x95, 0x27, 0xab, 0x91, 0x94, 0x42, 0xdb, 0x5c, 0xdb, 0x76, 0x14, 0x41, 0x10, 0x07, 0xac, +0x22, 0xcf, 0x17, 0x67, 0x8a, 0xd2, 0xda, 0x82, 0x2e, 0xb1, 0xe5, 0xc2, 0xd1, 0xa5, 0x63, 0x7e, +0xf9, 0x6c, 0xcf, 0x59, 0xeb, 0x37, 0xfe, 0x97, 0x1a, 0xb4, 0x77, 0x6b, 0xa7, 0x83, 0x2d, 0x51, +0x5f, 0xd4, 0x2f, 0xeb, 0xb6, 0x19, 0x1a, 0xbe, 0xda, 0x2e, 0x93, 0xf6, 0x33, 0xf6, 0x3e, 0x93, +0x20, 0x59, 0xaf, 0x42, 0xf6, 0x45, 0x14, 0xe9, 0xd4, 0x30, 0x63, 0x00, 0xbf, 0xb0, 0x4b, 0xad, +0xfe, 0x47, 0x90, 0xac, 0x6a, 0x1a, 0xcd, 0xe4, 0xba, 0x41, 0x23, 0xb3, 0x81, 0x64, 0xa2, 0x8f, +0x91, 0x49, 0xb5, 0x23, 0x82, 0x5a, 0xc7, 0xf1, 0xef, 0x0e, 0x6b, 0xca, 0xe7, 0xa8, 0xdd, 0x1b, +0xa7, 0xe2, 0x1b, 0xd5, 0x36, 0xa4, 0x78, 0xb6, 0xe9, 0xd9, 0x51, 0x2e, 0xdf, 0xad, 0x1d, 0xb1, +0xf9, 0x51, 0x86, 0x3f, 0x5b, 0x80, 0x6f, 0xd4, 0x06, 0x6c, 0xf6, 0x0d, 0xb8, 0x5e, 0xbd, 0x96, +0xba, 0x17, 0xc2, 0x0b, 0x52, 0x3e, 0x13, 0xf7, 0x55, 0x43, 0xbf, 0x1d, 0x48, 0x0c, 0xbf, 0xb0, +0xcb, 0xfa, 0x4a, 0x50, 0x14, 0xb9, 0xdd, 0xfb, 0x61, 0xeb, 0xf6, 0x31, 0x7a, 0x61, 0x1d, 0x2a, +0x3d, 0xf2, 0x1f, 0xdf, 0xfe, 0x65, 0x68, 0x8e, 0x8b, 0xa2, 0x5e, 0x91, 0xb7, 0xb1, 0xbb, 0xc8, +0xf5, 0x62, 0x41, 0x02, 0xae, 0xdb, 0x30, 0xd3, 0x73, 0xf1, 0x55, 0x79, 0x5a, 0x35, 0x14, 0x80, +0x1b, 0xb5, 0xbc, 0xb3, 0x3a, 0xa8, 0x9c, 0xce, 0xcb, 0x0b, 0xeb, 0x20, 0x68, 0x6f, 0x31, 0x0a, +0x5d, 0x91, 0xe2, 0x13, 0x13, 0xc7, 0x5a, 0x79, 0x0a, 0x3e, 0x82, 0x02, 0x4e, 0x5b, 0x17, 0xec, +0x85, 0x36, 0x2d, 0xa2, 0x0e, 0x8b, 0x2a, 0xe3, 0xd3, 0x06, 0x4a, 0x41, 0x58, 0x28, 0x1d, 0x24, +0xc4, 0xb1, 0xaf, 0xd3, 0x38, 0xf9, 0x2b, 0xbe, 0x74, 0xa4, 0x4d, 0x7d, 0x81, 0x3d, 0x8b, 0x74, +0xed, 0xdf, 0x62, 0xe5, 0xa3, 0xe3, 0x0c, 0xa6, 0x80, 0x90, 0x1f, 0xa2, 0xfc, 0x53, 0x1c, 0x1c, +0x37, 0xa8, 0x5e, 0x8c, 0xe9, 0xe0, 0x30, 0x49, 0xf0, 0x11, 0xa6, 0x37, 0xa9, 0x39, 0x9c, 0x26, +0x48, 0x2b, 0x54, 0xd6, 0x15, 0x0a, 0x65, 0x6a, 0x07, 0xc1, 0xe3, 0x9d, 0xec, 0xbd, 0x1c, 0xe3, +0xcc, 0xbe, 0x33, 0xe2, 0x5d, 0x20, 0xae, 0x8d, 0xed, 0x01, 0xaa, 0x01, 0xbd, 0x30, 0x70, 0xc0, +0x2f, 0xa8, 0xe2, 0x41, 0x2f, 0xc3, 0x50, 0x19, 0x7b, 0xd5, 0x10, 0x0e, 0x87, 0x11, 0xf6, 0x3d, +0x31, 0xfa, 0x8e, 0x71, 0x4e, 0xfd, 0x22, 0xa5, 0x19, 0x63, 0xff, 0xfd, 0x3e, 0x1f, 0xa3, 0x34, +0x2b, 0x0a, 0x69, 0xfc, 0x51, 0x1b, 0x43, 0xa2, 0x38, 0x0a, 0x15, 0x94, 0x65, 0x84, 0x65, 0xec, +0xd3, 0xb0, 0x19, 0x53, 0x36, 0x93, 0x44, 0xe4, 0x8d, 0xaf, 0x54, 0xeb, 0x58, 0x35, 0x3d, 0xa0, +0xab, 0x90, 0xf4, 0x09, 0x95, 0x96, 0xc7, 0x0f, 0x84, 0xce, 0x70, 0xaa, 0xa0, 0x98, 0x11, 0x23, +0x8f, 0x5f, 0xb1, 0xea, 0xd2, 0xe4, 0x91, 0xb7, 0x28, 0x9b, 0xaf, 0x9b, 0x26, 0xf1, 0x3b, 0xb3, +0xb1, 0xea, 0xf3, 0xb4, 0x54, 0xf4, 0x88, 0xfb, 0x91, 0x70, 0x7e, 0x74, 0x0f, 0x9c, 0x41, 0xfb, +0x5a, 0xf7, 0x5c, 0x74, 0x36, 0x37, 0x99, 0x92, 0xff, 0xbe, 0x26, 0xe7, 0x96, 0x32, 0x37, 0x48, +0x77, 0xe1, 0xa2, 0xb9, 0x09, 0x00, 0x98, 0x29, 0x7f, 0x16, 0xfa, 0x00, 0xc9, 0xc5, 0x2d, 0xa8, +0x7f, 0x31, 0x59, 0x7e, 0xa1, 0xc8, 0xdb, 0x05, 0xd9, 0x4e, 0x31, 0x86, 0xb7, 0xb8, 0x59, 0x3f, +0xa8, 0xe1, 0x1a, 0x8a, 0x8e, 0xe7, 0xf2, 0x6d, 0x29, 0x6a, 0xcb, 0x23, 0xd3, 0xe7, 0xec, 0x92, +0x11, 0xa0, 0x2b, 0x70, 0x40, 0xae, 0x9a, 0xcd, 0xc2, 0x8b, 0xa3, 0x8e, 0xaf, 0x42, 0xb4, 0xfe, +0xaa, 0x70, 0x56, 0x24, 0x34, 0x87, 0x7d, 0x4e, 0x23, 0x9e, 0x29, 0xf3, 0x62, 0xa6, 0x20, 0x2e, +0xaa, 0xd6, 0x7e, 0xe4, 0x93, 0xa5, 0xe7, 0x8f, 0xff, 0x65, 0x72, 0x54, 0x98, 0x0d, 0x78, 0x3b, +0xf9, 0xe1, 0xed, 0xa5, 0x73, 0x18, 0x7e, 0x16, 0xf5, 0x08, 0xff, 0x99, 0x73, 0x0c, 0x62, 0xd4, +0xf4, 0x21, 0x9e, 0x48, 0x88, 0x89, 0x5f, 0x09, 0xa3, 0x04, 0x00, 0x82, 0xb2, 0x0a, 0x90, 0xe8, +0xc1, 0x6f, 0x23, 0x83, 0x29, 0xd7, 0x22, 0x58, 0x83, 0x77, 0x86, 0x4c, 0x33, 0xad, 0x90, 0x76, +0xbe, 0x8e, 0x4c, 0xba, 0xb0, 0x84, 0x0c, 0x72, 0x92, 0x27, 0x40, 0xea, 0x48, 0x15, 0xf3, 0xab, +0xbb, 0x10, 0x7e, 0xd1, 0x3a, 0x2c, 0x09, 0x8c, 0x8c, 0xcd, 0xe6, 0x84, 0x20, 0x58, 0x9b, 0x74, +0x7a, 0x97, 0xca, 0x49, 0x2a, 0x20, 0xc3, 0x53, 0x04, 0x07, 0x25, 0x75, 0x70, 0x0d, 0xdf, 0x96, +0x79, 0x88, 0xa8, 0x17, 0xfe, 0xc6, 0xbb, 0xb3, 0xb9, 0x2f, 0xfe, 0xa6, 0x2e, 0xa9, 0x68, 0x8b, +0xf8, 0xab, 0x1e, 0x7f, 0xfe, 0xc2, 0x80, 0x39, 0x52, 0x2d, 0x20, 0x8e, 0x6a, 0x32, 0x5e, 0x17, +0x1a, 0x09, 0x45, 0xfb, 0xb2, 0x61, 0xee, 0x3a, 0xa2, 0xca, 0xc2, 0x76, 0x62, 0x61, 0x39, 0xda, +0xbf, 0x2f, 0x8d, 0x5a, 0x2b, 0xba, 0x55, 0x41, 0xb2, 0x63, 0x2f, 0xc1, 0x8f, 0xf6, 0xd2, 0x5c, +0x96, 0xdd, 0x93, 0x4f, 0xb4, 0x80, 0x10, 0x53, 0xba, 0x81, 0xe6, 0xd5, 0x79, 0x1a, 0x23, 0x28, +0x84, 0xe3, 0xab, 0xbc, 0xe9, 0xdf, 0xc6, 0xf9, 0x44, 0x15, 0xaa, 0x88, 0xc8, 0xf2, 0xae, 0x03, +0xa8, 0x29, 0x4a, 0x59, 0x0f, 0x5c, 0x34, 0xb3, 0x9b, 0xa5, 0x62, 0x19, 0x18, 0xb0, 0xfc, 0x00, +0xe1, 0x6d, 0x19, 0x53, 0x36, 0x93, 0x44, 0xe4, 0x8d, 0xa1, 0x54, 0xeb, 0x58, 0x35, 0x3d, 0xa0, +0xf9, 0x52, 0x49, 0x05, 0x45, 0xce, 0xec, 0x84, 0xad, 0x83, 0x14, 0x03, 0x1a, 0x9f, 0x3e, 0x93, +0xfa, 0xc9, 0x2e, 0x8c, 0xf3, 0x67, 0x5d, 0xc7, 0x55, 0xa6, 0x76, 0xd2, 0xa4, 0xe9, 0x17, 0x1a, +0x89, 0x93, 0xb1, 0xb0, 0x1e, 0xa3, 0x84, 0x2a, 0xe0, 0x38, 0xf6, 0x9c, 0xba, 0xd6, 0xe4, 0xfb, +0xe3, 0x49, 0x1c, 0x82, 0x69, 0x9b, 0x35, 0x81, 0x7f, 0x40, 0x22, 0x5b, 0x58, 0x7d, 0xc5, 0xcf, +0xbe, 0xb4, 0x53, 0xb2, 0x6d, 0xed, 0x5d, 0xf3, 0xce, 0x46, 0x85, 0xa5, 0x3b, 0xca, 0x00, 0x50, +0xa2, 0x29, 0xa0, 0x79, 0x72, 0x5c, 0x81, 0xc2, 0x62, 0x6b, 0x5d, 0xe8, 0x32, 0x26, 0x80, 0x25, +0x41, 0x4d, 0xb5, 0xbf, 0x69, 0x37, 0x4e, 0x20, 0x4c, 0x66, 0x1a, 0xa5, 0x15, 0x6d, 0x10, 0xf3, +0x68, 0x49, 0xaf, 0x83, 0xd8, 0x2f, 0x4d, 0x6e, 0x4e, 0x18, 0x8d, 0xa2, 0x0e, 0x93, 0x80, 0x0d, +0xf3, 0xc0, 0x5c, 0xa9, 0x05, 0x28, 0xfc, 0x34, 0x52, 0xc5, 0x8c, 0x43, 0x43, 0x38, 0xe2, 0x6c, +0x84, 0x07, 0xf6, 0x4c, 0x2b, 0x87, 0xae, 0x6d, 0x36, 0x30, 0x67, 0x25, 0xd8, 0x52, 0xe9, 0xeb, +0xbc, 0xe9, 0x1b, 0x18, 0xb6, 0x29, 0x60, 0xca, 0x9d, 0x09, 0x35, 0xa5, 0x2c, 0xa5, 0xce, 0x09, +0xb7, 0xc3, 0xee, 0xa0, 0x76, 0x0f, 0x52, 0x51, 0x21, 0x68, 0xd9, 0xa6, 0xb6, 0x8c, 0xc0, 0x51, +0x28, 0xc2, 0x4a, 0xc2, 0xf9, 0x2c, 0x38, 0xd0, 0xae, 0x28, 0x36, 0x90, 0xee, 0x55, 0x39, 0xc8, +0xb5, 0x51, 0x29, 0x8c, 0xc0, 0x36, 0x50, 0x8b, 0x6c, 0xea, 0x72, 0x07, 0x30, 0x6b, 0x00, 0x28, +0xcb, 0xaa, 0x19, 0xe3, 0x8b, 0x79, 0xad, 0x4e, 0xd3, 0xd8, 0xc8, 0xe0, 0x79, 0xc3, 0x30, 0x2c, +0x39, 0x9f, 0x5a, 0x26, 0x01, 0xef, 0x28, 0xf6, 0xa3, 0x95, 0x41, 0xfd, 0x80, 0xa7, 0x3e, 0xe7, +0xc1, 0xa2, 0x08, 0xd3, 0x72, 0x6f, 0x9e, 0xb2, 0xc6, 0x58, 0x18, 0xef, 0x6d, 0xc6, 0xde, 0xaf, +0xac, 0x9a, 0x3b, 0xb1, 0x1a, 0xb4, 0xca, 0xe1, 0x66, 0x62, 0xa6, 0xbd, 0xdd, 0x14, 0x85, 0x9e, +0x04, 0x3a, 0xc9, 0xbf, 0x25, 0xeb, 0x8a, 0x2d, 0x47, 0x85, 0x06, 0x30, 0x66, 0xf6, 0x68, 0x1a, +0x04, 0xb0, 0x74, 0x99, 0x3c, 0xbe, 0x63, 0x1d, 0x41, 0xee, 0xc5, 0xa5, 0xea, 0x90, 0x5c, 0x39, +0x45, 0x4e, 0x39, 0xdd, 0xd5, 0xc3, 0x0e, 0x10, 0x4e, 0x53, 0x66, 0xc6, 0xe6, 0xe4, 0x13, 0xf2, +0x57, 0x10, 0x0f, 0xac, 0x56, 0x6d, 0x4d, 0xf2, 0xee, 0x3b, 0xcd, 0x8e, 0xde, 0x3c, 0x15, 0xb4, +0x89, 0xb6, 0x4e, 0x70, 0x7c, 0x22, 0xc1, 0xb2, 0x2e, 0x22, 0xac, 0x14, 0x9d, 0xe5, 0xe6, 0x97, +0x15, 0x65, 0x37, 0xf6, 0xbc, 0xd2, 0xc2, 0xf5, 0xd4, 0x9c, 0x3d, 0x7c, 0x29, 0x73, 0x8c, 0x4a, +0xce, 0xe4, 0x2f, 0x6d, 0x13, 0xb0, 0x53, 0xb6, 0xb3, 0x05, 0xad, 0xbd, 0x60, 0xce, 0xcc, 0x7e, +0x81, 0xd7, 0xf5, 0xf3, 0xe9, 0x49, 0x6d, 0x38, 0xd5, 0x5f, 0xa7, 0x4d, 0xfe, 0x28, 0xdc, 0xe3, +0x7a, 0x64, 0x30, 0x62, 0xec, 0xb7, 0xbe, 0xc0, 0x98, 0xcd, 0x34, 0x33, 0x3f, 0x91, 0x16, 0x74, +0x0f, 0x5e, 0x56, 0x82, 0x35, 0x9d, 0x13, 0x90, 0x5b, 0x8c, 0x7f, 0xaa, 0x98, 0xbd, 0x90, 0xf2, +0x70, 0xca, 0xf9, 0x80, 0x9d, 0xe0, 0xb7, 0xbd, 0x7d, 0x6a, 0x75, 0x88, 0xb1, 0xcb, 0xc0, 0x05, +0x94, 0x45, 0x4e, 0x41, 0x9a, 0x5c, 0x27, 0x9c, 0x3a, 0x1f, 0x62, 0xef, 0x83, 0x05, 0xcd, 0xdf, +0x5b, 0xda, 0x92, 0x41, 0xc0, 0xe0, 0x14, 0x2e, 0xd9, 0x96, 0xde, 0xc4, 0xf4, 0x85, 0x91, 0x3b, +0x7d, 0x3c, 0xf5, 0xaf, 0x98, 0xf5, 0xf5, 0x6d, 0x66, 0xbe, 0x26, 0x9d, 0x97, 0xcb, 0xdf, 0x1b, +0x63, 0x57, 0x63, 0xcd, 0xc5, 0xe8, 0x4e, 0x29, 0x4f, 0x0e, 0x91, 0x1c, 0xe5, 0x8e, 0xeb, 0x9b, +0x81, 0x99, 0x43, 0xea, 0x42, 0x7c, 0xdd, 0x94, 0x8c, 0x00, 0xbc, 0x53, 0xdb, 0x98, 0x5f, 0xa4, +0x48, 0xcf, 0xfe, 0xe5, 0x82, 0x81, 0x98, 0x39, 0x1f, 0xa1, 0xf7, 0x56, 0xf1, 0xd1, 0xee, 0x86, +0xf2, 0x3c, 0x77, 0xc6, 0x5d, 0x3e, 0xaf, 0x71, 0x36, 0x1e, 0x78, 0xc7, 0xd3, 0x53, 0x29, 0x35, +0xa1, 0x14, 0xfe, 0x92, 0x38, 0x69, 0x2d, 0xd3, 0xcc, 0xa0, 0x57, 0x96, 0xc4, 0xb2, 0x46, 0x54, +0xf1, 0xfe, 0xaa, 0xed, 0x3e, 0x8e, 0xc8, 0xfe, 0x0c, 0x41, 0xe5, 0xc0, 0x7d, 0xdc, 0x85, 0x44, +0x72, 0xfe, 0x68, 0x01, 0xf7, 0x24, 0x2d, 0x4d, 0xf7, 0x75, 0x4f, 0xe3, 0x58, 0x8f, 0xf2, 0x08, +0x56, 0x61, 0x94, 0x5a, 0xa4, 0xe3, 0xa8, 0x1b, 0xd0, 0x3d, 0x66, 0x7b, 0xa1, 0x6e, 0xfa, 0x31, +0x5d, 0x13, 0x81, 0x0b, 0x7c, 0x47, 0x60, 0x31, 0x4d, 0xde, 0xbf, 0x79, 0xab, 0x93, 0xf9, 0xd0, +0x9a, 0x4a, 0x97, 0xcc, 0xdb, 0xa1, 0x98, 0x99, 0x1f, 0xa1, 0xf7, 0x56, 0xf1, 0xc3, 0xee, 0x86, +0xc1, 0xa4, 0x4a, 0x5e, 0xbc, 0x74, 0xfc, 0x79, 0xa9, 0xe6, 0x62, 0x58, 0xaf, 0x42, 0x00, 0x72, +0xa1, 0x14, 0xfe, 0x92, 0x38, 0x69, 0x2d, 0xd3, 0xcc, 0x84, 0x57, 0x96, 0xc4, 0xb2, 0x46, 0x54, +0xa4, 0x39, 0x7c, 0x2a, 0xfb, 0x2b, 0x17, 0x0d, 0xd1, 0x33, 0x9c, 0x7a, 0x14, 0x3d, 0xc1, 0xb5, +0x86, 0x78, 0x60, 0xd4, 0x50, 0x9e, 0x39, 0xf1, 0x91, 0x0e, 0xf0, 0x9a, 0x38, 0x48, 0x62, 0x20, +0xae, 0x98, 0x9b, 0x3e, 0xe0, 0x80, 0x52, 0x73, 0x93, 0xac, 0xac, 0x89, 0x08, 0xc9, 0x6e, 0xf0, +0x88, 0x73, 0x57, 0x39, 0x55, 0xcc, 0xa0, 0x7c, 0xab, 0xa3, 0xb3, 0x42, 0x20, 0x71, 0x00, 0x97, +0xd0, 0x63, 0x1a, 0x2b, 0x58, 0x4e, 0x15, 0xe3, 0x5f, 0xd7, 0x3d, 0x6c, 0x6e, 0x39, 0x28, 0x0a, +0xbb, 0x7c, 0x90, 0xc6, 0x0f, 0xd7, 0xb5, 0xe2, 0x6d, 0x6c, 0xeb, 0xc1, 0x22, 0xea, 0x88, 0x7b, +0x3c, 0x0e, 0xc5, 0x58, 0x4c, 0x79, 0x9a, 0x7a, 0xa1, 0x55, 0x6d, 0x5e, 0x33, 0xbb, 0x74, 0xf7, +0xd9, 0x70, 0x31, 0xde, 0x47, 0xfe, 0x2f, 0xaf, 0xab, 0x1a, 0x9f, 0xce, 0x24, 0x85, 0x2c, 0x55, +0x8c, 0xed, 0x68, 0x52, 0x05, 0x62, 0xb9, 0x85, 0xaa, 0x9e, 0x54, 0x03, 0xde, 0x6e, 0x8f, 0xd9, +0x1b, 0x59, 0xc9, 0x66, 0xd3, 0xa0, 0x74, 0xce, 0x45, 0x00, 0xad, 0xaf, 0x40, 0x94, 0x5e, 0x59, +0x61, 0x0c, 0x93, 0x22, 0x20, 0xf2, 0xaf, 0x57, 0x01, 0xe6, 0x5c, 0x88, 0x7e, 0xc5, 0xa4, 0xf9, +0x3f, 0xd3, 0xfc, 0xca, 0x8f, 0x34, 0xf4, 0x97, 0x4c, 0xc7, 0xdb, 0x7e, 0x7c, 0x96, 0x08, 0x07, +0x61, 0x05, 0x3b, 0xcd, 0x6c, 0xdc, 0x7c, 0xa1, 0x8b, 0xf9, 0xf1, 0x86, 0xd7, 0x20, 0x47, 0xb4, +0x1b, 0x89, 0xbc, 0x9f, 0x6d, 0x4c, 0x53, 0xe5, 0xdf, 0x94, 0x14, 0xb6, 0x34, 0x46, 0xb7, 0x72, +0x5d, 0x63, 0xe1, 0x65, 0x84, 0xe0, 0xa9, 0x24, 0x19, 0x72, 0x0a, 0x98, 0x6c, 0xc1, 0x74, 0xc9, +0xca, 0x09, 0x7d, 0x43, 0xf5, 0x8d, 0xa8, 0x6a, 0xa6, 0x59, 0x75, 0x37, 0x5a, 0x4c, 0xb5, 0x6d, +0x9b, 0xf9, 0xe8, 0xe4, 0x0a, 0xf5, 0x85, 0x24, 0x83, 0xd5, 0x20, 0x97, 0x02, 0x04, 0x5b, 0x3e, +0x5f, 0x14, 0xb9, 0x97, 0x30, 0xc1, 0xd3, 0x06, 0x02, 0xa6, 0x1d, 0x90, 0xd4, 0xfc, 0xcc, 0x35, +0xa2, 0x29, 0x23, 0x9c, 0x5a, 0xe2, 0x3d, 0x01, 0xc8, 0x20, 0xf5, 0xa1, 0x3c, 0xfe, 0x6d, 0xfc, +0x08, 0xfe, 0x11, 0x76, 0xa7, 0x20, 0xab, 0xf2, 0x6f, 0x77, 0x2d, 0x0d, 0xbb, 0x48, 0xce, 0x43, +0x0b, 0xd5, 0x37, 0xbd, 0x6d, 0x09, 0xa3, 0xa7, 0xc9, 0x0f, 0x71, 0x84, 0xf0, 0x4b, 0x89, 0x9c, +0x47, 0xfd, 0xc0, 0x46, 0x8e, 0xcc, 0xd6, 0x8a, 0xf0, 0xd3, 0xc0, 0x44, 0xf5, 0x18, 0x10, 0x2f, +0x1c, 0xc3, 0xed, 0x9d, 0xab, 0xaf, 0x30, 0x90, 0x14, 0x7d, 0xc4, 0xc0, 0xb7, 0x4f, 0x2c, 0x2b, +0x26, 0x23, 0xc7, 0xae, 0x8d, 0x75, 0x0f, 0xea, 0x44, 0xc3, 0x35, 0xd7, 0xb4, 0x93, 0x56, 0xf8, +0x48, 0x4d, 0xff, 0xb7, 0x3c, 0x9c, 0xc5, 0x0f, 0x64, 0x11, 0x23, 0x42, 0x65, 0x36, 0x65, 0x1a, +0xc5, 0x95, 0x22, 0x71, 0x10, 0xb9, 0x4b, 0x46, 0xbd, 0x60, 0x3b, 0xcb, 0x45, 0x13, 0xd4, 0xb8, +0x8b, 0xcc, 0xa6, 0xe2, 0x76, 0xe9, 0xcf, 0x8a, 0xda, 0xfb, 0xb7, 0x7a, 0x5e, 0x8d, 0x3b, 0x9e, +0x42, 0x62, 0xad, 0x78, 0x7f, 0xa6, 0x3c, 0x3e, 0x50, 0xa4, 0x34, 0x7f, 0x4f, 0x06, 0x95, 0x87, +0x78, 0x78, 0x9f, 0x97, 0xaa, 0x21, 0x54, 0x60, 0xc5, 0xf5, 0x59, 0x3a, 0x40, 0x7f, 0xb1, 0xc9, +0x1c, 0x51, 0xa9, 0x30, 0x99, 0x50, 0x17, 0x5b, 0x1d, 0xda, 0x93, 0xac, 0x84, 0xf5, 0x8f, 0x3b, +0xd3, 0x41, 0x98, 0x42, 0x0b, 0xb3, 0x36, 0x40, 0x68, 0x0d, 0xac, 0xa0, 0x1d, 0x9f, 0xdd, 0x45, +0x41, 0x22, 0x5d, 0x69, 0x75, 0xe6, 0x89, 0x20, 0x93, 0x90, 0xe6, 0x78, 0x27, 0x7c, 0x5c, 0x2e, +0xf5, 0x10, 0x45, 0x10, 0x9b, 0x72, 0x7c, 0xdf, 0xf8, 0x1f, 0xbb, 0xd5, 0x7f, 0x14, 0x5a, 0x82, +0xeb, 0x80, 0x59, 0xaa, 0xd3, 0x12, 0xb9, 0xde, 0xc1, 0xf8, 0x55, 0xca, 0x8d, 0x29, 0x75, 0x79, +0xcd, 0x73, 0x6b, 0x35, 0xe3, 0xea, 0x83, 0x40, 0xac, 0x9c, 0x91, 0xbe, 0xda, 0xb0, 0x43, 0x0c, +0xe2, 0xa1, 0xa6, 0x68, 0x18, 0x94, 0x64, 0xff, 0x90, 0x2e, 0x9d, 0x3c, 0x10, 0x25, 0xb2, 0x6b, +0x39, 0x08, 0x7b, 0x12, 0xa8, 0x0c, 0xd9, 0xb3, 0xdc, 0xb2, 0x9a, 0x7c, 0xa8, 0x21, 0x59, 0xf8, +0x87, 0x13, 0xc7, 0x87, 0xf7, 0x0a, 0x9d, 0x3b, 0xba, 0xa5, 0xc3, 0x1d, 0xb3, 0xfb, 0x9d, 0xc5, +0xbe, 0x54, 0x3c, 0x34, 0x9d, 0x47, 0x79, 0x89, 0x28, 0x94, 0x3e, 0x7e, 0xdc, 0xc7, 0x44, 0x65, +0xcd, 0x7a, 0x12, 0x21, 0x14, 0xe5, 0xe5, 0x8f, 0x94, 0x15, 0xca, 0x60, 0xca, 0xbf, 0xcc, 0x83, +0x3e, 0xad, 0x4d, 0x4c, 0x3f, 0x3c, 0x48, 0xaa, 0x47, 0x25, 0x33, 0xdf, 0x2a, 0xf2, 0x19, 0xc6, +0x21, 0x88, 0x64, 0x28, 0x8b, 0x9a, 0x4f, 0x4d, 0xcf, 0x19, 0x9d, 0xf5, 0xac, 0x5a, 0x21, 0xe5, +0xa5, 0x7b, 0x9b, 0x1d, 0x1b, 0xb5, 0x41, 0x31, 0x22, 0x65, 0x21, 0xa9, 0xb6, 0x2f, 0xcd, 0x6c, +0x46, 0x0f, 0x63, 0x6a, 0x4b, 0xa5, 0xa5, 0x00, 0x18, 0xd2, 0x1f, 0x2c, 0x32, 0x9f, 0x4b, 0x87, +0x0a, 0x94, 0x50, 0xfb, 0xaa, 0x5b, 0xc4, 0x49, 0x22, 0xb7, 0xfa, 0xc9, 0xb7, 0x11, 0x33, 0xa9, +0x8e, 0x12, 0xbe, 0x3b, 0x96, 0x98, 0x54, 0xdb, 0x27, 0x1a, 0x3b, 0xd6, 0x2c, 0xfb, 0xc1, 0xa5, +0x71, 0xaf, 0xe0, 0xbe, 0xbb, 0x43, 0x41, 0x3d, 0xb2, 0xd3, 0x17, 0x21, 0x69, 0xcf, 0xd3, 0x10, +0xaf, 0x41, 0x5a, 0x22, 0x04, 0xc3, 0x0c, 0x9b, 0x62, 0x12, 0x5d, 0xb0, 0xb3, 0x04, 0x63, 0x9b, +0xe3, 0x1a, 0xf7, 0xad, 0x27, 0x14, 0x0b, 0xa4, 0x5b, 0xec, 0x21, 0xc6, 0x49, 0xca, 0x4f, 0x53, +0xba, 0xc6, 0xa4, 0xc5, 0x61, 0xc8, 0x93, 0x83, 0xf7, 0xf2, 0x3a, 0x9d, 0x82, 0x4c, 0x23, 0xaf, +0x51, 0x50, 0x7f, 0x16, 0x28, 0x3d, 0xa2, 0xf0, 0xda, 0x1f, 0x64, 0xc4, 0xff, 0x5f, 0xf6, 0xa4, +0x03, 0xbc, 0x61, 0xe3, 0xad, 0x24, 0xad, 0x32, 0x41, 0x5a, 0x26, 0xd3, 0xf8, 0x13, 0x4d, 0x26, +0x22, 0x2c, 0xdf, 0xc7, 0x66, 0x0d, 0x76, 0x9d, 0x7e, 0x4d, 0xb7, 0xb1, 0xc2, 0x07, 0x8e, 0xdd, +0x08, 0xac, 0x65, 0xdf, 0x7b, 0x3f, 0xf4, 0x18, 0xc0, 0xc6, 0xde, 0x7c, 0x38, 0xf6, 0x9e, 0xe6, +0x07, 0x9b, 0x41, 0x0d, 0xaa, 0xb6, 0xc7, 0x35, 0x11, 0xa7, 0xa4, 0x09, 0x4c, 0xc4, 0xd7, 0x55, +0xd1, 0x05, 0xf9, 0xa4, 0xc0, 0x1d, 0x5e, 0x67, 0xbc, 0xd2, 0xc8, 0xd0, 0x5a, 0xf9, 0x9e, 0x14, +0x35, 0x9f, 0x6a, 0x3e, 0xdd, 0xb2, 0x14, 0xfa, 0xf4, 0xb2, 0x7a, 0x01, 0xae, 0x78, 0xdb, 0xd0, +0xcc, 0xcb, 0x76, 0x3a, 0x94, 0x77, 0x92, 0xe6, 0x6a, 0x5a, 0x77, 0x65, 0x2f, 0xb4, 0x25, 0x2c, +0xd8, 0x04, 0x5b, 0x09, 0x2a, 0x7e, 0x1d, 0x5d, 0xc9, 0x6b, 0x57, 0x14, 0xc8, 0x56, 0x0b, 0xbe, +0x9a, 0x38, 0x6e, 0xb7, 0x36, 0x85, 0xee, 0xbe, 0xc7, 0x80, 0x92, 0x80, 0xdb, 0x43, 0x4b, 0xbd, +0xd6, 0xdc, 0x49, 0x2c, 0x91, 0xa6, 0xa5, 0x42, 0xa1, 0x2c, 0xff, 0x8a, 0xe6, 0x4f, 0x94, 0x82, +0x76, 0xab, 0xd0, 0x42, 0x3b, 0x7d, 0x37, 0xea, 0x5b, 0x2d, 0xc5, 0x59, 0x7d, 0xc5, 0x3d, 0x42, +0x5c, 0x84, 0x25, 0x03, 0x2e, 0xda, 0xc3, 0x0d, 0x66, 0x7d, 0x52, 0x2d, 0x11, 0xe8, 0x22, 0xa2, +0xe7, 0x44, 0xa1, 0x87, 0xa4, 0xce, 0x5a, 0xde, 0xa3, 0xfb, 0x16, 0x6d, 0xc4, 0x16, 0xbf, 0xb6, +0x51, 0x7c, 0x42, 0x35, 0x26, 0xc3, 0x93, 0x84, 0xcf, 0x4f, 0xe1, 0xe5, 0x60, 0x18, 0xc2, 0x42, +0x74, 0xdf, 0x85, 0xe6, 0x7f, 0xf2, 0x62, 0x6f, 0xe2, 0x9c, 0xdc, 0x4c, 0xcb, 0x29, 0xd6, 0x93, +0xe8, 0x4c, 0xf3, 0xfc, 0x3a, 0xf9, 0x56, 0x86, 0xad, 0x1b, 0xfc, 0xaf, 0x62, 0xfc, 0xa2, 0x85, +0xd9, 0x94, 0xcb, 0x39, 0xa3, 0x7c, 0x10, 0x49, 0xc1, 0xb1, 0xe5, 0x9d, 0xff, 0xfa, 0xa5, 0x1e, +0x03, 0xb3, 0x5d, 0xe2, 0xee, 0xc3, 0xb6, 0x6a, 0x16, 0x9f, 0xbe, 0xaa, 0x61, 0xe5, 0x5b, 0xaf, +0x57, 0x4f, 0x0c, 0x1b, 0x0b, 0xf0, 0xc9, 0x3e, 0x98, 0x7f, 0xcb, 0x2e, 0x66, 0xde, 0x0a, 0x83, +0xcb, 0x74, 0x52, 0x1d, 0xce, 0x11, 0xd2, 0xcd, 0x84, 0x3e, 0x6e, 0x87, 0xda, 0x70, 0x64, 0xe8, +0x1f, 0x40, 0x2d, 0xfe, 0x28, 0xaa, 0x3a, 0xb5, 0x31, 0x93, 0x16, 0x28, 0x44, 0xbd, 0xdf, 0xcf, +0x5b, 0x46, 0xb7, 0xfe, 0xec, 0xbd, 0x81, 0x83, 0x3f, 0x8e, 0xfa, 0xf0, 0x5c, 0xeb, 0xb5, 0x7a, +0x38, 0x61, 0x76, 0x5b, 0x43, 0x36, 0xad, 0x44, 0xaf, 0x89, 0x62, 0x43, 0x67, 0x6a, 0x8c, 0x56, +0x3d, 0xc6, 0x5c, 0x3a, 0x90, 0xbb, 0x5b, 0x6a, 0x2e, 0xa5, 0x0d, 0xd5, 0x4c, 0xfa, 0xf8, 0xfe, +0x1e, 0x26, 0x85, 0x2e, 0xe0, 0x9a, 0x9e, 0xc4, 0x96, 0x9f, 0xc7, 0x67, 0x18, 0xc6, 0x38, 0x3e, +0x4d, 0x62, 0xb7, 0x65, 0xbe, 0xbd, 0xf4, 0x37, 0x5c, 0x5f, 0x85, 0xf2, 0x36, 0x3d, 0x55, 0xfb, +0xd6, 0xac, 0x6d, 0x37, 0xc0, 0x7c, 0x89, 0x39, 0xa6, 0xfa, 0xd6, 0x65, 0xb2, 0xde, 0x7c, 0x33, +0x60, 0xb8, 0x92, 0x20, 0x18, 0x8c, 0x9b, 0xe4, 0xbb, 0xe2, 0xe2, 0xfe, 0x7a, 0x6d, 0xb0, 0x38, +0x33, 0x09, 0x5c, 0xf1, 0xa2, 0xd2, 0x6c, 0xf7, 0x79, 0x2b, 0xb9, 0x71, 0x8a, 0xd6, 0xef, 0x39, +0x9a, 0x0e, 0xfd, 0x80, 0xcc, 0xe3, 0xb7, 0xc7, 0xce, 0x0e, 0x3d, 0xd3, 0x5e, 0x63, 0x29, 0x37, +0x6f, 0xf4, 0x0e, 0x31, 0x94, 0x50, 0x11, 0xe9, 0xea, 0x0d, 0xc3, 0x05, 0x07, 0x71, 0x61, 0xe0, +0xf8, 0x14, 0x40, 0x94, 0xdd, 0xca, 0x38, 0x3b, 0xc3, 0xf1, 0x9e, 0x62, 0xe2, 0x28, 0xc8, 0xa7, +0x84, 0x6c, 0x0f, 0x81, 0xa5, 0x1b, 0x80, 0x64, 0x67, 0xc7, 0x22, 0x22, 0xb5, 0x6d, 0xb2, 0x3b, +0x71, 0x17, 0xb4, 0xfd, 0xf8, 0x2e, 0xa2, 0x2a, 0xfd, 0x93, 0x0e, 0x44, 0x75, 0xaf, 0x8a, 0x9d, +0x72, 0x63, 0xa1, 0xbe, 0x7d, 0xd2, 0x67, 0x43, 0xd4, 0xf4, 0xb6, 0xcc, 0xa0, 0x18, 0x78, 0x03, +0x47, 0x57, 0x3f, 0x02, 0x8f, 0x4a, 0x31, 0x77, 0xc0, 0xbd, 0x11, 0x8b, 0xad, 0x17, 0x98, 0x62, +0xc9, 0xdd, 0xd4, 0xd2, 0x50, 0x66, 0x75, 0xef, 0x56, 0xe2, 0xc3, 0xd2, 0x56, 0x32, 0x10, 0xc9, +0xac, 0x81, 0x0f, 0xea, 0x15, 0xfd, 0x37, 0x17, 0x0d, 0xda, 0x71, 0xd8, 0xaf, 0xaf, 0x07, 0x2b, +0xe9, 0x04, 0x15, 0x93, 0xd3, 0x5b, 0xa8, 0x07, 0x95, 0xcd, 0x35, 0x0e, 0x1a, 0x63, 0x09, 0x99, +0x6b, 0x61, 0x9d, 0xe1, 0xb8, 0x15, 0x71, 0x32, 0xd8, 0x97, 0xfc, 0x6a, 0x6e, 0xac, 0x4b, 0xf5, +0x6d, 0x3f, 0xde, 0x0a, 0x1f, 0x15, 0x62, 0x07, 0x13, 0x48, 0x77, 0xb6, 0x65, 0x16, 0x24, 0x5c, +0x98, 0xd6, 0xbf, 0xa0, 0x09, 0x91, 0x0b, 0x4e, 0xfe, 0x0e, 0xe7, 0xc7, 0xba, 0x61, 0x80, 0x82, +0x4f, 0x52, 0xac, 0xc6, 0x2e, 0xb4, 0xc8, 0x44, 0xfb, 0x39, 0x49, 0xba, 0x02, 0x9f, 0xa1, 0xe1, +0x06, 0xc0, 0x08, 0x3e, 0x67, 0xe4, 0xf0, 0xa2, 0xcd, 0xc5, 0x4c, 0x59, 0xbb, 0xee, 0xd6, 0xdc, +0x19, 0x20, 0xd8, 0x1a, 0x77, 0xb4, 0xa3, 0xa1, 0x06, 0xd2, 0xa6, 0xc6, 0xb7, 0x8a, 0x1b, 0x89, +0x9c, 0x3e, 0x56, 0xa9, 0x1e, 0x3c, 0x2e, 0xcf, 0x51, 0x18, 0x22, 0x7a, 0xdf, 0x34, 0x20, 0x8f, +0xbf, 0xef, 0x4e, 0x90, 0x01, 0x2b, 0xd0, 0xd1, 0xaa, 0x35, 0x1c, 0x6a, 0xd4, 0x99, 0x28, 0x6a, +0xaa, 0x33, 0x10, 0x95, 0x48, 0x39, 0xc2, 0x63, 0xe4, 0x3f, 0x6b, 0x26, 0xc6, 0x7e, 0xbd, 0xe5, +0x94, 0x12, 0x60, 0x38, 0x1d, 0x12, 0x00, 0xac, 0xbe, 0xd2, 0xa6, 0x20, 0x2f, 0xc8, 0x52, 0xc7, +0xcc, 0x52, 0x0f, 0x9c, 0x2a, 0x25, 0x4c, 0xf7, 0x6f, 0x36, 0xa9, 0xab, 0xf3, 0x10, 0xd7, 0x2d, +0x71, 0xeb, 0x84, 0x9a, 0x68, 0x8f, 0x4d, 0xa0, 0xfb, 0x46, 0xa1, 0xf4, 0xce, 0xe5, 0x7c, 0x1a, +0x8e, 0x29, 0x58, 0x6c, 0x61, 0x8b, 0xc9, 0x10, 0x9d, 0x35, 0xe7, 0xdf, 0xfe, 0x19, 0xe3, 0x77, +0x67, 0x78, 0xba, 0xcc, 0x33, 0x10, 0x0a, 0x1d, 0x3d, 0xcb, 0xb7, 0x1a, 0xd2, 0x21, 0x04, 0xfd, +0x69, 0xa3, 0x6f, 0xb5, 0x69, 0xee, 0x89, 0xa4, 0xd1, 0x90, 0x2c, 0xd3, 0xef, 0xa1, 0xbe, 0x43, +0x4f, 0x78, 0x62, 0xbf, 0xd8, 0x30, 0xdf, 0x33, 0x42, 0xba, 0xfa, 0x12, 0x9d, 0xd9, 0x95, 0x68, +0x3c, 0xfa, 0x20, 0xfa, 0x7b, 0xa8, 0xdf, 0x2c, 0x29, 0x58, 0x82, 0x50, 0x18, 0xf4, 0x5b, 0xc4, +0x57, 0x03, 0xd9, 0x6c, 0x76, 0x0d, 0x8b, 0xc5, 0x07, 0x44, 0xac, 0x4a, 0xd7, 0xc3, 0xee, 0x18, +0x48, 0xa4, 0x1c, 0xc4, 0x67, 0x11, 0x47, 0x53, 0x58, 0x53, 0x6b, 0x11, 0x4d, 0x6f, 0xac, 0x6a, +0x9e, 0x2b, 0x8d, 0x03, 0x7b, 0x2b, 0x07, 0xff, 0x2b, 0xc6, 0x88, 0x9a, 0x78, 0x9d, 0x6b, 0x3e, +0xaf, 0xc0, 0xc0, 0x8e, 0x5e, 0xbc, 0x30, 0xef, 0x44, 0x61, 0x11, 0x0b, 0xa2, 0x3a, 0x8e, 0x08, +0x29, 0x3f, 0x97, 0x0d, 0x3f, 0x52, 0x35, 0x8f, 0x8a, 0x24, 0xfc, 0x4d, 0xa0, 0x89, 0xd5, 0xb5, +0xae, 0x5b, 0xc9, 0xb0, 0xf7, 0x94, 0x35, 0x39, 0x85, 0xaa, 0xc2, 0xc5, 0x39, 0x18, 0x90, 0x0f, +0x79, 0xa1, 0xff, 0x8a, 0xcf, 0x50, 0xc5, 0x66, 0x75, 0x09, 0x0f, 0x76, 0x27, 0x4b, 0x54, 0xb4, +0x6b, 0x36, 0x63, 0x36, 0x31, 0x88, 0x0a, 0x6c, 0xc9, 0x0d, 0x2a, 0x96, 0x38, 0xca, 0xbc, 0x83, +0xb0, 0xdf, 0xdf, 0xe6, 0x2e, 0x6f, 0x41, 0x91, 0xf8, 0x1e, 0x94, 0xfd, 0x21, 0x1f, 0x0b, 0x20, +0x5e, 0x79, 0xbe, 0x45, 0x8b, 0x6f, 0x95, 0x96, 0xc2, 0x0b, 0x2c, 0x8d, 0xda, 0xdd, 0x1b, 0xa2, +0xe8, 0x7a, 0x33, 0xb5, 0x74, 0x16, 0x25, 0xfa, 0x1c, 0x55, 0x8e, 0xce, 0x3b, 0x9d, 0x56, 0xfe, +0x5a, 0x32, 0xd7, 0xd4, 0x2c, 0xad, 0xeb, 0x8f, 0xd3, 0xa9, 0xe5, 0xc2, 0xe3, 0x76, 0x59, 0x57, +0xea, 0xa9, 0xe5, 0xde, 0x40, 0x7c, 0xb5, 0x31, 0x64, 0x33, 0x2c, 0xbd, 0xdb, 0xdb, 0x31, 0xbb, +0xa6, 0x7d, 0xfc, 0x66, 0xca, 0xe3, 0x98, 0x50, 0x5d, 0x28, 0x01, 0x6b, 0x7b, 0x26, 0x25, 0x8c, +0x34, 0x18, 0xb1, 0x4e, 0x57, 0x70, 0x98, 0x10, 0x1a, 0x22, 0x12, 0x76, 0xcd, 0xd0, 0x18, 0xec, +0x05, 0xae, 0x3e, 0xdf, 0x2b, 0xa0, 0x19, 0xeb, 0x10, 0x6a, 0x1e, 0x5f, 0x16, 0x55, 0xe5, 0x15, +0x97, 0xd8, 0xae, 0xb5, 0xff, 0x17, 0x60, 0x1e, 0x2b, 0x21, 0xaa, 0x37, 0x80, 0x3d, 0xa0, 0x68, +0xb9, 0xa2, 0xf3, 0x3c, 0x87, 0x99, 0xa9, 0xfb, 0x8b, 0xdf, 0xaf, 0x7f, 0x74, 0xa6, 0x52, 0x11, +0x2b, 0x6f, 0x39, 0xf4, 0xb7, 0xa4, 0xe7, 0xa2, 0x09, 0x46, 0xde, 0x53, 0x33, 0xbd, 0x26, 0xa4, +0x2d, 0xb1, 0xc6, 0xf6, 0x42, 0xcc, 0x85, 0x44, 0xbb, 0xdb, 0xe9, 0xdc, 0x05, 0xdd, 0x39, 0x78, +0x3a, 0x79, 0x16, 0x98, 0x6a, 0xeb, 0xc5, 0x12, 0x7d, 0xb9, 0x0f, 0xa6, 0x70, 0xff, 0x1f, 0x07, +0x24, 0x6c, 0xf1, 0x92, 0x7c, 0x70, 0x1d, 0x42, 0x58, 0x1f, 0x9b, 0x3b, 0xbe, 0xa2, 0x12, 0x79, +0xbf, 0x0c, 0xa4, 0x16, 0x4e, 0x89, 0x36, 0x3a, 0xde, 0xd7, 0x83, 0xdb, 0x0c, 0x2a, 0x6c, 0x03, +0xdf, 0x55, 0x47, 0xc9, 0x40, 0xa8, 0xe1, 0x0e, 0xae, 0x3e, 0x4c, 0xd7, 0x3c, 0x0c, 0xb0, 0xdd, +0xce, 0xe0, 0xb6, 0x96, 0x3a, 0x54, 0xef, 0xcc, 0x0a, 0x8e, 0x5b, 0x16, 0xb3, 0x5b, 0x1f, 0x01, +0x67, 0x95, 0x4b, 0x8c, 0x76, 0x87, 0xdc, 0xf3, 0x70, 0xd4, 0x22, 0xbf, 0x09, 0xe6, 0x31, 0x24, +0x76, 0xc1, 0x65, 0x9f, 0x35, 0x3b, 0x66, 0xfa, 0x23, 0xf3, 0x4f, 0x4f, 0xde, 0x31, 0x8b, 0x00, +0x90, 0x86, 0xd0, 0xb6, 0x9d, 0x9d, 0xae, 0x5d, 0x0d, 0x72, 0x33, 0x2b, 0xab, 0x68, 0x48, 0xb9, +0x86, 0x53, 0xae, 0x6e, 0xb0, 0xc2, 0x70, 0xf9, 0x49, 0xb2, 0x96, 0xc6, 0x04, 0x12, 0xcc, 0x11, +0x4f, 0x8d, 0xde, 0xe7, 0x04, 0xac, 0xad, 0xe1, 0xac, 0x88, 0x1b, 0xb5, 0x00, 0xd8, 0xb9, 0x55, +0xe3, 0xb4, 0x21, 0x0c, 0xd4, 0xb9, 0x05, 0x5e, 0xa3, 0x85, 0x28, 0x60, 0x95, 0x5b, 0x2c, 0x7f, +0x1e, 0xde, 0x4d, 0x62, 0xd3, 0xec, 0xa5, 0x35, 0x12, 0x2e, 0x6f, 0xc8, 0xd7, 0xd2, 0x54, 0xec, +0x72, 0x72, 0xd3, 0x82, 0x50, 0xc3, 0x78, 0xa8, 0x7a, 0x79, 0xc2, 0xff, 0x15, 0xac, 0xf2, 0x41, +0x92, 0xd7, 0xc3, 0x34, 0x40, 0xf3, 0x83, 0xf8, 0xf5, 0x25, 0x9f, 0x16, 0x16, 0xba, 0xf5, 0xcc, +0x2e, 0xbb, 0x42, 0xc5, 0xad, 0x89, 0x59, 0xb5, 0xe5, 0x37, 0xae, 0x3b, 0xeb, 0x37, 0x9f, 0xeb, +0x11, 0xbc, 0x11, 0xc4, 0xe6, 0x9f, 0xd0, 0x40, 0x7c, 0x3d, 0x40, 0xd2, 0xee, 0xbd, 0x67, 0x98, +0xa2, 0xab, 0x4c, 0x13, 0xf5, 0xc5, 0xdb, 0xfb, 0x37, 0x07, 0x6b, 0x6e, 0xaf, 0x47, 0x4f, 0xf2, +0xb3, 0x11, 0xc2, 0x0c, 0x4f, 0xb7, 0x97, 0x6a, 0xb2, 0xc1, 0xc6, 0x9f, 0xb8, 0xf4, 0xd4, 0x83, +0x06, 0x31, 0xbf, 0x13, 0x0c, 0xa5, 0x52, 0xd0, 0x36, 0x28, 0x6c, 0xa7, 0x3a, 0xee, 0xa3, 0xad, +0x35, 0xb4, 0x81, 0xc4, 0x6e, 0x16, 0xd3, 0xcb, 0x3a, 0x53, 0x44, 0x32, 0x29, 0xf1, 0xe3, 0x7a, +0xe2, 0x5a, 0xa6, 0x36, 0x84, 0x13, 0xeb, 0x74, 0xf8, 0x88, 0xfd, 0x9f, 0xc9, 0xcb, 0x5e, 0x8b, +0xfa, 0x4f, 0x63, 0x93, 0x46, 0xd5, 0xc6, 0x13, 0x66, 0x9d, 0x13, 0x89, 0xe3, 0x2a, 0xa6, 0xaf, +0x1f, 0xd0, 0xc5, 0xd8, 0xf8, 0xea, 0x95, 0x2d, 0x0c, 0xf5, 0x61, 0xbb, 0x05, 0x67, 0x22, 0x0e, +0xf7, 0x30, 0x0f, 0x08, 0x92, 0xd8, 0x99, 0xac, 0x1f, 0x8b, 0x40, 0x71, 0x84, 0xef, 0x88, 0x88, +0xfe, 0x20, 0xb1, 0xa2, 0x3b, 0xbe, 0x53, 0xc9, 0x2b, 0x1f, 0x2a, 0x09, 0x02, 0x62, 0xcf, 0x20, +0x30, 0x42, 0x08, 0x5c, 0xea, 0x59, 0x83, 0x8a, 0x9a, 0x1f, 0x26, 0xee, 0x5d, 0x5e, 0xa4, 0x09, +0x83, 0xeb, 0x60, 0x8d, 0xb9, 0x7f, 0x98, 0x22, 0x43, 0x75, 0xb2, 0x72, 0x0d, 0x84, 0xc7, 0x36, +0x46, 0x26, 0xa3, 0xe9, 0xed, 0x20, 0x0c, 0x11, 0x83, 0x3b, 0x8b, 0xc0, 0xab, 0x3e, 0x5b, 0x7f, +0x2c, 0xe7, 0x46, 0x14, 0x98, 0x5e, 0xd2, 0xc1, 0xa9, 0x88, 0x03, 0xd4, 0x06, 0x83, 0x42, 0x28, +0x1c, 0x2b, 0x92, 0x17, 0x76, 0x0d, 0xab, 0x1b, 0xc7, 0x01, 0xe8, 0xcd, 0x1a, 0xfb, 0x13, 0x3c, +0x2e, 0x18, 0x66, 0x80, 0x32, 0x6f, 0x6f, 0x85, 0x9d, 0x98, 0x3e, 0xe8, 0x2b, 0xa1, 0x34, 0xa6, +0xf6, 0xe8, 0x5c, 0x9f, 0xcb, 0xd8, 0x55, 0x67, 0x50, 0x94, 0x25, 0xc3, 0x17, 0xd0, 0x80, 0x0a, +0x5c, 0x16, 0xc2, 0x3a, 0xb6, 0x9d, 0x2a, 0xcd, 0x70, 0x67, 0x8a, 0xa3, 0x4e, 0x7f, 0xdf, 0xf8, +0xf0, 0xd6, 0x90, 0x06, 0x24, 0x8c, 0x3f, 0x14, 0x4c, 0x47, 0xe1, 0x4e, 0x51, 0x1b, 0xd7, 0x8e, +0x93, 0x54, 0xc0, 0xa4, 0x04, 0x1b, 0xc9, 0x02, 0x80, 0xb2, 0xa3, 0xa7, 0x5f, 0xf6, 0x97, 0xfe, +0x3d, 0x77, 0x6f, 0x70, 0x57, 0x2b, 0x05, 0x00, 0xd5, 0x7a, 0x3a, 0xb5, 0xe4, 0xc7, 0xf2, 0x57, +0xd8, 0x52, 0x1f, 0xe0, 0x6d, 0xe8, 0x73, 0x71, 0x09, 0x5a, 0x56, 0xa7, 0x4d, 0x67, 0xb9, 0x60, +0x0f, 0x26, 0x11, 0x74, 0x09, 0x37, 0x40, 0xae, 0x34, 0xcd, 0x23, 0xe7, 0xed, 0x6b, 0x4d, 0xfd, +0x78, 0x0c, 0x7d, 0xff, 0xec, 0xf3, 0x70, 0xc1, 0xa7, 0x07, 0xdd, 0xfc, 0x97, 0x3f, 0x15, 0xdd, +0xfd, 0x09, 0x43, 0xd0, 0xa1, 0x6e, 0x7a, 0xe9, 0x12, 0xc0, 0x93, 0xe7, 0x6f, 0xd6, 0xbf, 0x62, +0xe8, 0xae, 0xd3, 0xd7, 0xd1, 0xb9, 0x9e, 0x0e, 0x75, 0xa1, 0x1d, 0x21, 0x41, 0x0c, 0xa1, 0xbf, +0x5d, 0xb5, 0x42, 0xea, 0xec, 0x52, 0x99, 0xb3, 0x81, 0x01, 0xf6, 0xbf, 0x9f, 0x85, 0x6a, 0x24, +0xf8, 0x08, 0x52, 0xcc, 0x22, 0xf9, 0xd7, 0xe6, 0x66, 0x44, 0x26, 0x6f, 0xc3, 0xfc, 0xf7, 0xe1, +0x08, 0x13, 0x3e, 0x1d, 0x05, 0x78, 0x08, 0xba, 0x9a, 0x0f, 0x4f, 0x01, 0xf4, 0xdc, 0x38, 0x0c, +0xe8, 0xb5, 0x68, 0x74, 0xfd, 0x60, 0x6b, 0x65, 0x09, 0xb0, 0x2b, 0x71, 0xbc, 0xf2, 0xbf, 0xfa, +0x27, 0x39, 0x88, 0x95, 0xa2, 0xaa, 0x7d, 0x11, 0x62, 0x53, 0xc8, 0x83, 0xc5, 0x6b, 0x95, 0xd4, +0xf0, 0x17, 0x76, 0x6c, 0x1f, 0x23, 0x7d, 0xe1, 0xc4, 0x4e, 0x37, 0x51, 0xbd, 0x52, 0xec, 0xed, +0xcd, 0x32, 0x41, 0x1c, 0xf0, 0x79, 0xf5, 0xe5, 0x95, 0xa4, 0x19, 0xe8, 0x3b, 0x47, 0xa0, 0xda, +0x38, 0x2b, 0x13, 0x1a, 0x30, 0x9a, 0xaf, 0x07, 0xdb, 0x6e, 0xe5, 0xb8, 0x28, 0x9c, 0x37, 0x0b, +0xc3, 0x72, 0x5d, 0xaf, 0xc7, 0x69, 0x34, 0x2b, 0xbc, 0x84, 0xb1, 0xc2, 0xa4, 0xcf, 0x3d, 0xd8, +0x8b, 0x14, 0xf7, 0x1e, 0x05, 0x48, 0x7f, 0xdb, 0xfd, 0x92, 0xaf, 0x5d, 0xae, 0x58, 0xaf, 0x81, +0xf3, 0x44, 0x17, 0x3d, 0x68, 0xd8, 0x18, 0x99, 0x25, 0x16, 0x7d, 0xbf, 0x58, 0x73, 0xd5, 0x0e, +0xe1, 0x5a, 0x62, 0x90, 0xf6, 0xc0, 0x42, 0xab, 0x49, 0xe7, 0xa3, 0x1f, 0xcd, 0x9c, 0xc8, 0x9a, +0xcc, 0xb8, 0x59, 0x4d, 0x85, 0xcc, 0x08, 0xad, 0x1c, 0x7d, 0x06, 0x1b, 0x6b, 0x23, 0x23, 0x65, +0xc8, 0x1e, 0x06, 0x7d, 0xf4, 0xe0, 0x53, 0x01, 0x45, 0xa1, 0x6e, 0x01, 0x94, 0x27, 0x54, 0xd6, +0xd0, 0xcb, 0x4b, 0x35, 0xe9, 0x6a, 0xbc, 0x99, 0xd3, 0x7e, 0x99, 0x65, 0xce, 0x7e, 0x97, 0x7a, +0x9f, 0x3b, 0xcc, 0x89, 0xbc, 0x57, 0xae, 0xa1, 0x84, 0xb0, 0x7d, 0x13, 0x51, 0xdf, 0xee, 0x07, +0x1c, 0xf2, 0x33, 0x48, 0x86, 0x0a, 0x2e, 0x63, 0x39, 0xa4, 0x4b, 0xaf, 0xaa, 0xf7, 0x1b, 0x59, +0xe2, 0x98, 0x27, 0x93, 0x93, 0xcd, 0x2e, 0x82, 0xeb, 0xa9, 0x05, 0xca, 0xa1, 0xaa, 0x8c, 0x1a, +0x78, 0xc0, 0xa4, 0x1b, 0x03, 0x6d, 0xee, 0xdd, 0xb6, 0x44, 0xe1, 0x57, 0xef, 0x58, 0x55, 0xc1, +0xad, 0x2a, 0x90, 0xbc, 0x15, 0xf1, 0x30, 0xaa, 0x50, 0xfd, 0xad, 0xb6, 0x9d, 0x85, 0x08, 0x9c, +0x31, 0x52, 0x1d, 0xc0, 0x4f, 0x48, 0x2c, 0x4f, 0x2b, 0x41, 0x37, 0xc7, 0x7a, 0x27, 0xf8, 0xd4, +0xc3, 0x4b, 0xba, 0xa6, 0x13, 0xce, 0x6d, 0x9d, 0xc0, 0xb9, 0x02, 0x57, 0x01, 0x3a, 0x7b, 0x8b, +0xb8, 0xe7, 0x6e, 0xa3, 0xb7, 0x5f, 0xe5, 0x50, 0x73, 0xd8, 0x90, 0x9c, 0x5f, 0x6b, 0x05, 0xc8, +0x36, 0xa0, 0xef, 0x45, 0x34, 0x59, 0x6d, 0x2c, 0x68, 0xbe, 0x45, 0xed, 0x3c, 0x36, 0x1e, 0x7b, +0xed, 0x46, 0x23, 0x49, 0x75, 0x2a, 0xec, 0x12, 0x94, 0x51, 0xed, 0xec, 0xfc, 0x31, 0x19, 0xd0, +0xbb, 0x6e, 0xb6, 0xb6, 0xad, 0xad, 0xab, 0xab, 0x69, 0xac, 0x50, 0xa1, 0x34, 0x10, 0xf3, 0x6d, +0x23, 0x40, 0x64, 0xca, 0xd2, 0x54, 0xe8, 0x47, 0x91, 0x2d, 0x4e, 0xb2, 0x8a, 0x14, 0x48, 0xb7, +0xdc, 0x57, 0xca, 0xb5, 0x1b, 0x2c, 0x64, 0x09, 0x77, 0xb6, 0xbf, 0xf5, 0x6b, 0x41, 0x77, 0x53, +0x6f, 0xec, 0x06, 0x53, 0x16, 0x5b, 0xbd, 0x1c, 0x38, 0xfa, 0x5f, 0xcf, 0xb2, 0x4b, 0xbc, 0x1d, +0x43, 0xb2, 0x25, 0x08, 0x79, 0x19, 0x7a, 0x09, 0x40, 0x74, 0x1b, 0xe3, 0x16, 0x93, 0xc0, 0x4e, +0xf8, 0x63, 0x23, 0xd7, 0x0b, 0x31, 0x91, 0x23, 0x51, 0x3a, 0xbc, 0x63, 0xe9, 0x13, 0x0c, 0x86, +0x4f, 0x4f, 0x3b, 0x5f, 0xdb, 0xd9, 0x12, 0x9d, 0xb6, 0x24, 0x24, 0x68, 0x46, 0xca, 0xce, 0xe3, +0xf8, 0x3a, 0x47, 0x59, 0x85, 0xe6, 0xc6, 0x50, 0x47, 0x09, 0x19, 0xb1, 0x3c, 0x13, 0xe6, 0x1e, +0x89, 0x3a, 0x01, 0x55, 0x5e, 0x1d, 0x64, 0x82, 0xb0, 0x61, 0xfe, 0xa3, 0x18, 0x7f, 0x24, 0xea, +0x2d, 0x0b, 0xf3, 0x4a, 0x58, 0x09, 0x0b, 0x14, 0xab, 0x77, 0xd1, 0x42, 0x38, 0x8e, 0x7d, 0x2c, +0x7b, 0xba, 0xf9, 0xb3, 0x60, 0x6e, 0x10, 0x55, 0x95, 0x54, 0x66, 0x2d, 0x4b, 0xf9, 0x83, 0x6a, +0x89, 0x94, 0xc4, 0x6c, 0x16, 0x18, 0x94, 0x94, 0xbd, 0xab, 0x7d, 0x96, 0xb5, 0x57, 0x2d, 0x94, +0x3c, 0xd4, 0xef, 0x7f, 0xc2, 0x15, 0xe7, 0xe2, 0xef, 0x06, 0xdb, 0x12, 0xf2, 0xb8, 0xd3, 0x9a, +0x16, 0x2b, 0xf7, 0x2f, 0x53, 0x78, 0x8b, 0x7f, 0x6c, 0xf3, 0x4f, 0x3c, 0xa2, 0xf1, 0x78, 0x78, +0xc6, 0xcb, 0x2c, 0x92, 0x71, 0xc6, 0xb4, 0xc9, 0x86, 0x35, 0xc4, 0x90, 0xf0, 0x84, 0x72, 0xc9, +0x25, 0x40, 0xc1, 0xc0, 0x99, 0xd0, 0xbe, 0xa3, 0xee, 0xa2, 0x39, 0xfc, 0xc9, 0xc4, 0xab, 0x38, +0x28, 0xa0, 0x0d, 0x4f, 0x1a, 0xf9, 0xa9, 0x2d, 0x32, 0x44, 0x7f, 0x61, 0x3e, 0x84, 0xac, 0x29, +0xde, 0xc1, 0xb7, 0xdb, 0xaa, 0x37, 0x9c, 0xc2, 0xa9, 0x72, 0x11, 0x3e, 0xd1, 0x3f, 0x9e, 0x5e, +0x92, 0x4f, 0xa7, 0x75, 0xa2, 0xf9, 0x98, 0x0d, 0x6e, 0x35, 0xc4, 0xe0, 0x3d, 0xc8, 0xb8, 0xfb, +0xb4, 0xf4, 0xc7, 0x3b, 0xe8, 0xe6, 0x33, 0x59, 0x89, 0xa9, 0xa6, 0x71, 0x5d, 0x20, 0x63, 0xd9, +0x6d, 0x3d, 0x31, 0xdd, 0x35, 0xce, 0xac, 0x56, 0xd6, 0x67, 0xc4, 0xee, 0xb2, 0x8b, 0x28, 0x42, +0xec, 0x6a, 0x0c, 0x8f, 0x0c, 0xd9, 0xa5, 0x01, 0x20, 0x04, 0x37, 0x4f, 0xff, 0x02, 0x5d, 0x4a, +0x23, 0x83, 0x20, 0xad, 0x05, 0x44, 0x2c, 0xd6, 0x7e, 0x69, 0x12, 0x0a, 0x7d, 0x9e, 0xc3, 0xb4, +0xfd, 0x2d, 0x93, 0xbb, 0x4a, 0x1f, 0x59, 0x24, 0xc9, 0x56, 0xe8, 0x23, 0x08, 0x1c, 0x44, 0x26, +0x75, 0x5b, 0x84, 0x8f, 0xd7, 0x0d, 0x67, 0x0a, 0x16, 0x94, 0x48, 0x76, 0x8e, 0x5d, 0xb2, 0x63, +0x69, 0x1a, 0x53, 0xca, 0x0e, 0x65, 0x6b, 0x43, 0xf3, 0xf9, 0xf5, 0xf1, 0x60, 0xc7, 0x4c, 0x1c, +0xfb, 0x8d, 0xfa, 0xdf, 0xaa, 0x6f, 0x1a, 0x71, 0x94, 0xbd, 0x05, 0xe7, 0xbd, 0xcf, 0xda, 0x27, +0x37, 0x40, 0xa7, 0x98, 0xeb, 0xbe, 0x52, 0x85, 0x9b, 0xa0, 0x6f, 0x62, 0x74, 0xdd, 0xf9, 0x5b, +0xc3, 0x9a, 0x6a, 0xe8, 0x91, 0x76, 0x32, 0x16, 0x7a, 0x33, 0x39, 0x1a, 0x0b, 0x1a, 0xc6, 0xdb, +0x81, 0x61, 0xe4, 0x9f, 0xfb, 0x9e, 0xe5, 0x93, 0xd1, 0x96, 0x8f, 0xae, 0xc2, 0xaf, 0x47, 0xe7, +0x01, 0x13, 0xab, 0xe8, 0xb2, 0xa8, 0x5a, 0xd8, 0xe4, 0x42, 0x87, 0x15, 0x82, 0x58, 0x42, 0xd4, +0x82, 0x0b, 0xa2, 0xc2, 0x10, 0x48, 0x7e, 0x15, 0x45, 0x6f, 0x41, 0xc2, 0x9d, 0x65, 0xb0, 0x0e, +0x26, 0x79, 0x8d, 0xe3, 0x9f, 0x53, 0xb6, 0xcb, 0x85, 0xab, 0x71, 0x96, 0xc5, 0x8e, 0xbe, 0x35, +0xfd, 0x36, 0xd1, 0x3c, 0x4c, 0x39, 0x87, 0xf2, 0x5d, 0xa1, 0x09, 0x8e, 0xc0, 0x69, 0x9c, 0xc0, +0xc2, 0x65, 0x1f, 0x5a, 0x6b, 0x5b, 0x70, 0xfe, 0x2d, 0xef, 0x85, 0xc9, 0x79, 0x6a, 0x67, 0xc3, +0xd1, 0x4d, 0xa0, 0x35, 0xe8, 0x65, 0xf4, 0x00, 0xf2, 0x57, 0x6b, 0xa5, 0x35, 0x03, 0x48, 0x9f, +0xdf, 0xbc, 0x10, 0xbf, 0xfc, 0x43, 0xd7, 0xe3, 0x74, 0x7a, 0xba, 0x17, 0xf7, 0x4f, 0xad, 0x05, +0x25, 0x1e, 0xe3, 0x61, 0x0c, 0xf6, 0x26, 0x31, 0xea, 0x85, 0x22, 0x13, 0x3c, 0x6a, 0x20, 0x6d, +0xd2, 0xe6, 0xd6, 0xc7, 0xa5, 0x1d, 0xf7, 0xb8, 0x8d, 0x8c, 0xf8, 0x2d, 0x61, 0x8f, 0xe2, 0x1c, +0x73, 0xe4, 0x4d, 0x57, 0x01, 0xd8, 0xfc, 0xbc, 0x33, 0x0d, 0xa9, 0x7f, 0xca, 0x28, 0xd3, 0x9b, +0x71, 0xa7, 0x12, 0xcd, 0x5f, 0xb4, 0x1c, 0xd8, 0xb7, 0x01, 0xec, 0x42, 0x90, 0x49, 0x4e, 0x41, +0x21, 0x60, 0xca, 0xad, 0x1b, 0xfa, 0x28, 0x9c, 0xf0, 0xb6, 0x83, 0x65, 0x41, 0xe7, 0x76, 0x00, +0xb5, 0x6d, 0xbd, 0xc7, 0xa2, 0x89, 0x36, 0xd2, 0x59, 0x24, 0x81, 0x69, 0x21, 0xe8, 0x03, 0xb9, +0x62, 0xed, 0xa1, 0xad, 0xd7, 0xc7, 0xaa, 0x19, 0x4c, 0x0a, 0xe0, 0xbf, 0xf9, 0x00, 0xcf, 0xed, +0x0c, 0x38, 0x7f, 0xb2, 0xb5, 0x20, 0x51, 0x1a, 0x35, 0x85, 0x57, 0xec, 0x3d, 0x0e, 0xec, 0x68, +0x85, 0xb3, 0x56, 0x74, 0x76, 0x0e, 0xa0, 0xa8, 0x6b, 0x98, 0xa3, 0x11, 0x7c, 0xde, 0x88, 0xb6, +0xae, 0xfc, 0xf5, 0xbf, 0x91, 0x82, 0xfa, 0xb3, 0xc9, 0x7d, 0x6d, 0xef, 0x8b, 0x82, 0x9e, 0x4c, +0xd2, 0x13, 0x49, 0x51, 0xd9, 0x9c, 0xaa, 0x6a, 0xe1, 0xdd, 0x66, 0x81, 0x2b, 0xb5, 0x8d, 0x61, +0x71, 0x81, 0x6b, 0xd1, 0x9b, 0x64, 0x16, 0xb5, 0x19, 0x2b, 0x0c, 0x58, 0xdd, 0x36, 0xbe, 0xe9, +0xeb, 0x09, 0x70, 0x37, 0xcf, 0x1b, 0xbe, 0x6e, 0x01, 0x47, 0x4b, 0xb9, 0x3b, 0x42, 0xe7, 0xaf, +0x8e, 0xf0, 0x38, 0x08, 0x65, 0xed, 0x32, 0xb1, 0xf3, 0xa6, 0xd1, 0x98, 0xb8, 0x38, 0x45, 0x7c, +0xe8, 0x43, 0x55, 0x70, 0x95, 0x13, 0xda, 0x36, 0xcd, 0x81, 0x0a, 0x61, 0xbb, 0x37, 0xe8, 0xe6, +0x80, 0x01, 0x2b, 0x67, 0xd1, 0x96, 0x86, 0x61, 0x22, 0x6e, 0xef, 0xc1, 0xb3, 0x38, 0xa5, 0x1e, +0xb3, 0xa9, 0xc2, 0xd2, 0x6d, 0xfd, 0x9e, 0xfe, 0x2a, 0x3f, 0xb5, 0xf1, 0x9a, 0x8d, 0xb8, 0x3f, +0x1b, 0x62, 0xb3, 0xb8, 0xe8, 0x9b, 0xb4, 0x5e, 0x14, 0x79, 0x27, 0x9b, 0x2b, 0x53, 0x25, 0x6c, +0xcd, 0x80, 0x4e, 0xb1, 0x1a, 0x4c, 0x58, 0x58, 0xf4, 0x1e, 0xa1, 0x0b, 0xc3, 0xeb, 0xdd, 0x0a, +0xd7, 0xb7, 0x56, 0xd5, 0x98, 0xc0, 0x1f, 0x0d, 0xfd, 0xce, 0x9e, 0xef, 0x2a, 0xcf, 0xe0, 0x19, +0x45, 0x35, 0x35, 0x2c, 0xe9, 0x36, 0x2e, 0x94, 0xe6, 0xa3, 0xf9, 0x44, 0xdf, 0xfd, 0x15, 0xeb, +0xbb, 0x8c, 0xa0, 0xe3, 0xfd, 0x33, 0xc8, 0x71, 0xe0, 0x9d, 0x32, 0xce, 0xb0, 0x48, 0x51, 0x24, +0x53, 0xb0, 0x97, 0xc6, 0x0d, 0x82, 0xb7, 0xa8, 0x20, 0xb0, 0x74, 0xb9, 0xe6, 0x17, 0xfa, 0x5b, +0x91, 0xad, 0x11, 0x0c, 0x6a, 0xf4, 0xda, 0xee, 0x38, 0xc1, 0x90, 0x0d, 0xd9, 0x40, 0x57, 0x87, +0x41, 0x59, 0x90, 0xe3, 0x36, 0xba, 0xac, 0xa9, 0xf4, 0x60, 0xa0, 0x97, 0x08, 0x84, 0xef, 0xe7, +0x86, 0x35, 0xf3, 0x2c, 0x28, 0x6c, 0xc6, 0x9f, 0xc6, 0xea, 0x1a, 0x04, 0x6a, 0x60, 0x9a, 0xaa, +0x17, 0xde, 0xed, 0xf3, 0x17, 0x55, 0xa6, 0xc3, 0x24, 0x86, 0x23, 0xae, 0x3b, 0x3b, 0xbc, 0x68, +0xf9, 0x80, 0xbb, 0x55, 0xfa, 0x4c, 0x56, 0xac, 0x6b, 0x32, 0xed, 0x57, 0x89, 0xe2, 0x3b, 0x62, +0xd1, 0x30, 0x6f, 0xcb, 0x37, 0xce, 0x0f, 0x1d, 0x63, 0xe8, 0x23, 0xa7, 0x10, 0x7d, 0x5b, 0x65, +0xee, 0x90, 0x64, 0x68, 0xc7, 0x9b, 0xaa, 0x8f, 0x86, 0x0b, 0x23, 0x03, 0x4a, 0x4c, 0xd7, 0xef, +0x64, 0x3c, 0xf9, 0xbe, 0x72, 0xb4, 0xdb, 0x8a, 0x20, 0x12, 0x0e, 0x96, 0x7b, 0x57, 0xe2, 0x6e, +0x4d, 0xe5, 0x81, 0xd2, 0x18, 0x20, 0x5d, 0x29, 0x68, 0xd5, 0x7d, 0xfd, 0x3c, 0x67, 0xa4, 0x82, +0xa6, 0xcb, 0x76, 0x75, 0xaf, 0xd3, 0x88, 0x16, 0xc1, 0x9c, 0x20, 0xca, 0x09, 0xcf, 0xbd, 0xdf, +0x7e, 0xd6, 0xa2, 0xbc, 0x8a, 0x77, 0x8a, 0x26, 0xbb, 0xc4, 0x06, 0x41, 0x3c, 0x2d, 0x95, 0x88, +0xf4, 0x3b, 0x80, 0x2c, 0x3a, 0xad, 0xe2, 0x7a, 0x1c, 0x6a, 0xfa, 0x3c, 0x94, 0x1b, 0xcc, 0xb1, +0xfa, 0xfc, 0xb2, 0xe5, 0x90, 0xfb, 0xd0, 0x0b, 0xb1, 0x5a, 0xba, 0xae, 0x4b, 0xdd, 0x1d, 0x93, +0x5c, 0xaa, 0x4c, 0x79, 0x47, 0x31, 0xc1, 0xec, 0x59, 0x8c, 0xa5, 0xe3, 0x39, 0x30, 0xaa, 0x1b, +0x48, 0x4b, 0xeb, 0x8f, 0x6d, 0xa4, 0xa1, 0x99, 0x16, 0x97, 0x88, 0x8f, 0x5c, 0xd3, 0xd9, 0xb5, +0xd3, 0x31, 0x82, 0xf7, 0x00, 0xf0, 0xa8, 0x08, 0x43, 0x47, 0xa5, 0x0f, 0xd2, 0x2b, 0x18, 0x91, +0xa3, 0x0a, 0x8f, 0x58, 0x8c, 0x69, 0xac, 0xea, 0x70, 0x61, 0x38, 0x63, 0x23, 0xa6, 0xb2, 0xe1, +0x56, 0x9b, 0x22, 0xf4, 0x83, 0x84, 0x7b, 0xa2, 0xee, 0x55, 0x1f, 0xef, 0xf0, 0xd3, 0x14, 0x89, +0xf0, 0x7a, 0xea, 0x78, 0x37, 0xaa, 0xd0, 0x1f, 0x8c, 0x70, 0xf6, 0x68, 0x13, 0x44, 0x27, 0xd8, +0x4d, 0xfb, 0xdb, 0xe8, 0x77, 0xac, 0x60, 0x58, 0x45, 0x81, 0xe9, 0x29, 0xf8, 0xac, 0x3e, 0x80, +0x94, 0xe4, 0x40, 0xa5, 0xbd, 0x28, 0xcb, 0x2c, 0x8f, 0x5a, 0x94, 0x2a, 0x19, 0xe2, 0x64, 0xda, +0xab, 0x77, 0x2c, 0x58, 0x54, 0xb9, 0x29, 0x63, 0xae, 0x43, 0xa1, 0x85, 0x06, 0x5a, 0x41, 0x6b, +0x69, 0xe0, 0x24, 0xef, 0x8d, 0x4c, 0xfc, 0xc3, 0x90, 0x54, 0x5b, 0x56, 0xdd, 0x3b, 0x5d, 0xee, +0x83, 0xdd, 0x56, 0xb0, 0x61, 0xa6, 0x7f, 0x32, 0x05, 0xb6, 0x11, 0x3e, 0x88, 0x8b, 0x45, 0x3a, +0xe7, 0x26, 0xa4, 0xe3, 0x64, 0x71, 0x2c, 0xf1, 0xce, 0x89, 0x7a, 0x85, 0x68, 0x5a, 0x8e, 0x66, +0xf9, 0x10, 0x79, 0xa4, 0xc7, 0x36, 0x85, 0xf1, 0xb7, 0xc6, 0x6a, 0x1f, 0xb7, 0x34, 0xc7, 0xbd, +0xb3, 0x3b, 0xf1, 0x89, 0xb1, 0xaf, 0xb0, 0x0d, 0x13, 0x5a, 0x83, 0x43, 0xae, 0x3a, 0x18, 0x20, +0xdb, 0x88, 0x6f, 0x1a, 0xe8, 0x20, 0xfe, 0x78, 0x01, 0x86, 0x10, 0x63, 0xef, 0x40, 0x2b, 0xbb, +0x76, 0xce, 0x51, 0x47, 0xa7, 0xcc, 0xe2, 0x53, 0x92, 0xfd, 0xac, 0x5a, 0xd8, 0x75, 0xa9, 0x18, +0xda, 0x01, 0xfd, 0x14, 0x05, 0xf0, 0x3f, 0x2f, 0x12, 0x76, 0x27, 0xfe, 0x00, 0x2d, 0xa9, 0x38, +0x3b, 0xf7, 0x83, 0xbc, 0xcd, 0x5e, 0xe2, 0xa9, 0x4a, 0xcb, 0x70, 0x1e, 0xb8, 0xbf, 0xa2, 0xd9, +0x1b, 0x28, 0xb1, 0x02, 0x49, 0x6f, 0xe5, 0x09, 0x0f, 0x45, 0x5c, 0x4f, 0x5f, 0xcd, 0x68, 0xe9, +0x96, 0xf6, 0x77, 0x3c, 0x09, 0x09, 0x20, 0xdd, 0xc1, 0xbd, 0xfe, 0x2f, 0x69, 0x0d, 0x01, 0x2e, +0xba, 0x60, 0x25, 0x32, 0x87, 0x6c, 0x1f, 0x3f, 0xf0, 0x99, 0x83, 0x96, 0x51, 0xe7, 0x5b, 0x34, +0x49, 0x84, 0x42, 0xfb, 0xa8, 0x82, 0x0b, 0xf1, 0x26, 0x8a, 0x70, 0x9a, 0x9f, 0xc4, 0xdb, 0xae, +0x37, 0x98, 0x48, 0xc7, 0x86, 0x9e, 0xd1, 0x55, 0xdb, 0xb8, 0xda, 0xf6, 0x52, 0xc7, 0xb6, 0x5e, +0xa1, 0xac, 0x56, 0x99, 0xd0, 0x50, 0x1a, 0x74, 0x7b, 0x12, 0xda, 0x31, 0x86, 0xe8, 0x48, 0x2f, +0x4d, 0x53, 0x81, 0xe6, 0x25, 0xf3, 0x04, 0x65, 0xe7, 0xf6, 0x53, 0xdd, 0xd8, 0x40, 0xca, 0xc4, +0x9d, 0x11, 0xb6, 0xb4, 0xef, 0xd5, 0xe9, 0x83, 0xe1, 0xf3, 0x3c, 0x6e, 0x1e, 0x7a, 0xaf, 0x7f, +0x98, 0x6e, 0xf7, 0x58, 0xd7, 0x11, 0xec, 0xfd, 0x71, 0xe0, 0x03, 0xac, 0x59, 0xec, 0x09, 0x4c, +0xf2, 0x26, 0x65, 0xaf, 0x4d, 0x5d, 0xe7, 0xfb, 0xa2, 0x8e, 0x36, 0x7a, 0xb9, 0xc7, 0xc8, 0x61, +0x1f, 0xa9, 0x93, 0xc8, 0x44, 0x04, 0x71, 0x5f, 0xbb, 0x8a, 0xc1, 0x7d, 0x39, 0x06, 0xcf, 0x04, +0x2f, 0x23, 0x70, 0xda, 0x44, 0x35, 0x03, 0x48, 0xa0, 0x50, 0xbf, 0x94, 0x1f, 0x92, 0xde, 0x43, +0x08, 0xb6, 0x8f, 0x05, 0x24, 0x7a, 0xaa, 0xba, 0xe6, 0xf3, 0x3f, 0x31, 0xea, 0xb0, 0xd3, 0x2e, +0x10, 0x32, 0xe9, 0x61, 0x18, 0xe1, 0x03, 0xd1, 0xda, 0x0c, 0x2f, 0x9d, 0x6d, 0x9b, 0xd7, 0x6a, +0xb7, 0x84, 0x0a, 0x89, 0xab, 0xa8, 0x20, 0x7c, 0x4a, 0x09, 0xa5, 0x28, 0x1e, 0x27, 0xd1, 0xbc, +0x5d, 0x8f, 0xcc, 0xc4, 0xe2, 0x80, 0x0f, 0x00, 0x89, 0x3a, 0x9e, 0xe6, 0x2f, 0x41, 0xd8, 0xf0, +0x03, 0x5f, 0xf0, 0x66, 0x45, 0x2a, 0xf2, 0xb9, 0xce, 0xc1, 0x7a, 0x8c, 0xa0, 0x5d, 0x4f, 0x6e, +0xdc, 0xd5, 0x19, 0x6c, 0x86, 0x61, 0xd8, 0xbf, 0xd7, 0xd2, 0x95, 0xe8, 0x61, 0xa3, 0xc6, 0xba, +0x0d, 0x65, 0x2f, 0x0d, 0x73, 0x36, 0xc9, 0x01, 0x08, 0xca, 0xbc, 0xa0, 0xe0, 0xbc, 0x3d, 0x9b, +0xf2, 0x37, 0xaf, 0x2e, 0x4e, 0xf8, 0x85, 0x01, 0x40, 0x59, 0x14, 0xb1, 0x41, 0xc3, 0xa0, 0x88, +0x88, 0x3d, 0xbb, 0xf3, 0x2f, 0x6b, 0x3d, 0xd6, 0x53, 0x9c, 0x93, 0xa1, 0xc0, 0xb8, 0x55, 0xf1, +0x13, 0xa9, 0xde, 0xa3, 0x31, 0x7c, 0xc4, 0x9f, 0x2b, 0x86, 0x6b, 0xcb, 0x0a, 0xc0, 0xbb, 0xa5, +0x9a, 0x14, 0xa2, 0x6b, 0x71, 0xae, 0x3a, 0x38, 0xf4, 0xc4, 0xd4, 0xbb, 0x24, 0x45, 0x05, 0xa1, +0x30, 0xe0, 0x2c, 0x9c, 0x4b, 0x02, 0x13, 0x96, 0xac, 0x6c, 0xfe, 0x98, 0xd4, 0xd2, 0xa6, 0x95, +0xc7, 0xd9, 0x04, 0xae, 0x63, 0x73, 0x7d, 0xe5, 0x89, 0x78, 0xc9, 0xe6, 0x14, 0x5b, 0x2d, 0x46, +0xf7, 0xbc, 0x10, 0x36, 0xde, 0xa6, 0xc3, 0x81, 0x93, 0xf2, 0x49, 0x94, 0x35, 0xa7, 0x03, 0x98, +0x0a, 0x41, 0xea, 0x54, 0xf4, 0x8a, 0x06, 0x4e, 0xfb, 0x04, 0x7d, 0x66, 0x67, 0xee, 0xb4, 0x47, +0xaf, 0xca, 0x0c, 0x77, 0x39, 0x15, 0x80, 0x44, 0xef, 0x72, 0x41, 0x10, 0x1f, 0x89, 0xd6, 0xb2, +0xbb, 0x6a, 0x4d, 0x2c, 0x23, 0xc3, 0x0a, 0xf0, 0xab, 0x61, 0xf8, 0xf8, 0xc9, 0xf0, 0xca, 0xf5, +0xd8, 0x8e, 0xd7, 0x2b, 0xfb, 0xbf, 0x75, 0x05, 0xb7, 0x23, 0x4b, 0xff, 0x85, 0x23, 0xce, 0x9a, +0x32, 0x7d, 0x60, 0x8f, 0xfd, 0xa8, 0xf1, 0x86, 0xf3, 0xb0, 0x86, 0xb3, 0x61, 0xd4, 0x22, 0x2b, +0x33, 0x01, 0x52, 0xce, 0x02, 0xa6, 0x9f, 0xda, 0xca, 0xff, 0x44, 0x8e, 0x0f, 0xb2, 0x6b, 0x0f, +0xb6, 0x96, 0xeb, 0x40, 0xb9, 0x89, 0xfb, 0x84, 0xd9, 0x38, 0x3d, 0xb4, 0x96, 0x81, 0x22, 0xa0, +0x38, 0xda, 0xd1, 0x3f, 0x83, 0x53, 0xed, 0xa2, 0x4f, 0x64, 0x4b, 0x05, 0xe8, 0x1a, 0xab, 0xd1, +0xd4, 0x63, 0x24, 0x7b, 0xf9, 0x20, 0xf2, 0x39, 0xc5, 0x5a, 0x2a, 0x2a, 0xcc, 0x42, 0xdd, 0xe4, +0x5d, 0xb0, 0x16, 0x03, 0x63, 0xca, 0xfa, 0x6c, 0x5f, 0x96, 0x83, 0xc7, 0x76, 0x2a, 0x34, 0x06, +0xf0, 0x4f, 0xa5, 0xc1, 0xf7, 0xc2, 0x32, 0xe7, 0x77, 0x49, 0x4e, 0xfd, 0x84, 0xe4, 0x14, 0xdd, +0xd5, 0xf8, 0xa7, 0xc6, 0x62, 0xe6, 0x94, 0x64, 0x6d, 0x51, 0x48, 0xd0, 0xc0, 0xd4, 0x65, 0x08, +0x41, 0x02, 0xcd, 0x43, 0x29, 0xfb, 0x3e, 0x94, 0xf9, 0x3f, 0x09, 0x33, 0x65, 0x56, 0xf8, 0x59, +0x6a, 0x91, 0x5d, 0x73, 0x42, 0x25, 0xef, 0xb3, 0xb9, 0x6a, 0x2f, 0xc4, 0xf3, 0xdf, 0x60, 0xad, +0x73, 0x93, 0xb0, 0xf8, 0x4d, 0x46, 0x89, 0x8c, 0xd5, 0xb0, 0xee, 0x85, 0x4c, 0x57, 0x39, 0xc0, +0x92, 0xce, 0x7f, 0x35, 0x14, 0x4f, 0x66, 0x30, 0x0c, 0x3c, 0xbc, 0x91, 0x8f, 0xf7, 0x2e, 0x17, +0x0d, 0x91, 0x4d, 0x61, 0x82, 0x9b, 0x16, 0xc3, 0x31, 0x41, 0x8c, 0x66, 0x74, 0xb2, 0xed, 0x8f, +0xd5, 0xa3, 0xa2, 0xd4, 0x5d, 0x61, 0xe3, 0x0d, 0x1b, 0x41, 0xf7, 0x2b, 0x33, 0x32, 0xd5, 0xf9, +0xa7, 0x55, 0xc7, 0xf8, 0xd6, 0x69, 0xf9, 0xa1, 0xeb, 0x65, 0x4e, 0x29, 0xb2, 0x2f, 0xac, 0xdd, +0xd5, 0x92, 0xd5, 0xa1, 0x63, 0x74, 0xd5, 0x08, 0xc8, 0xa1, 0x47, 0xdb, 0xcc, 0xb5, 0x93, 0x98, +0xb8, 0xb7, 0x85, 0xf4, 0x44, 0xec, 0x2b, 0x65, 0xa1, 0xbe, 0x0e, 0x46, 0x6c, 0x66, 0xaa, 0xfb, +0x68, 0xc4, 0xdf, 0x3e, 0xdf, 0x17, 0xa2, 0x2b, 0xa9, 0xf3, 0xe5, 0xcf, 0x1f, 0x1a, 0x56, 0xdd, +0x01, 0xf3, 0xe9, 0xf7, 0x1b, 0xb1, 0x50, 0x5c, 0x5c, 0xf0, 0xf6, 0x04, 0xbb, 0xf3, 0xfe, 0x0a, +0xb3, 0x61, 0x05, 0xaf, 0x53, 0x55, 0xbe, 0xd2, 0x82, 0x2c, 0xd1, 0xf7, 0x73, 0xd4, 0x4c, 0xfd, +0x0e, 0xd6, 0xce, 0x03, 0x13, 0xc5, 0x71, 0x8b, 0x68, 0x2f, 0x4d, 0x79, 0xd5, 0x74, 0x4c, 0x30, +0x3f, 0x3b, 0x07, 0xc7, 0x98, 0x52, 0x28, 0xa1, 0x69, 0xa3, 0x11, 0x5f, 0xe9, 0x26, 0xe3, 0xc1, +0x29, 0xd1, 0x11, 0x5f, 0xdc, 0xa7, 0x62, 0x37, 0x4b, 0x87, 0x93, 0x57, 0x11, 0x21, 0x39, 0x1b, +0x80, 0x0e, 0x47, 0x67, 0xe5, 0x5a, 0xc0, 0x3a, 0xc9, 0xf2, 0x97, 0x62, 0xca, 0x70, 0x0d, 0xb6, +0x78, 0x4e, 0xb6, 0xfa, 0x70, 0x99, 0x01, 0x80, 0xf0, 0xbf, 0x25, 0x7e, 0xf8, 0x4a, 0xfd, 0x4c, +0xe1, 0x9a, 0x90, 0x96, 0x48, 0x55, 0xa6, 0x90, 0x59, 0x1a, 0xba, 0xf0, 0x3b, 0xbd, 0x9f, 0x08, +0xa3, 0x65, 0x3a, 0xe2, 0x39, 0x4a, 0xc8, 0x77, 0xb5, 0x9b, 0xc9, 0x5d, 0x13, 0xa3, 0x82, 0xa2, +0xbc, 0xd9, 0x67, 0x45, 0x7e, 0x19, 0xcc, 0x65, 0x5a, 0x0c, 0xda, 0xc0, 0x33, 0x7d, 0x12, 0x10, +0x81, 0x1b, 0xaf, 0x5b, 0xc5, 0x69, 0x7b, 0x15, 0x63, 0xf8, 0xa6, 0x3c, 0xc2, 0x20, 0xaa, 0x03, +0x28, 0x94, 0x5a, 0x69, 0x56, 0x6b, 0x55, 0x15, 0x5a, 0xe5, 0x48, 0x7e, 0x1c, 0x97, 0x82, 0x4e, +0x87, 0xd0, 0x9a, 0x46, 0x97, 0xf0, 0x13, 0xd5, 0x5b, 0x1f, 0x80, 0x47, 0x18, 0xd1, 0x46, 0x23, +0x01, 0x1d, 0x07, 0x83, 0xd6, 0xe8, 0x73, 0x57, 0x35, 0x9e, 0x86, 0xad, 0xbb, 0xb8, 0x7e, 0x12, +0x8e, 0x8e, 0x5c, 0x2b, 0x72, 0xda, 0xe1, 0x33, 0x87, 0xe2, 0x8c, 0xe8, 0xa6, 0x9e, 0x7f, 0xc4, +0x33, 0x01, 0xa2, 0xc3, 0xef, 0x6d, 0x22, 0x9c, 0xcd, 0x6c, 0xcc, 0xdb, 0xad, 0x4e, 0xbb, 0x04, +0xb3, 0x1c, 0x4f, 0xfa, 0x6b, 0x82, 0xd2, 0x5e, 0x63, 0x29, 0xb5, 0xdf, 0x3c, 0x3d, 0xf7, 0xe2, +0xb3, 0x29, 0xf0, 0x6a, 0x75, 0x09, 0x2a, 0x4d, 0x21, 0x47, 0xf5, 0x65, 0x19, 0x7d, 0xef, 0x23, +0xbd, 0x6d, 0x5a, 0x51, 0x7d, 0xef, 0x41, 0x07, 0xd0, 0xf8, 0x60, 0x6e, 0x4f, 0x39, 0x4b, 0xd8, +0x6f, 0x77, 0x9f, 0x60, 0x96, 0x43, 0x46, 0x53, 0xf2, 0xe2, 0x74, 0x2d, 0x2a, 0x2c, 0x5a, 0xce, +0x7e, 0x15, 0xdd, 0x84, 0x7a, 0xa9, 0x5c, 0xab, 0x83, 0x12, 0xa2, 0xdc, 0x47, 0x1d, 0x77, 0x19, +0x3f, 0xe6, 0x69, 0xb0, 0x73, 0xe0, 0x1a, 0xb1, 0xa8, 0x43, 0xc0, 0x8a, 0x1f, 0x6a, 0x4d, 0xf7, +0x86, 0xf7, 0x90, 0x5e, 0xf4, 0x96, 0xc3, 0x8f, 0x8e, 0x18, 0x44, 0xa5, 0x81, 0xec, 0x50, 0xd2, +0x6c, 0x21, 0x4c, 0x66, 0xd5, 0x56, 0xcc, 0x4e, 0x61, 0x1a, 0x59, 0x49, 0xa3, 0x13, 0xcb, 0x4e, +0xfd, 0x25, 0x8d, 0x98, 0xc9, 0x3f, 0xbd, 0xb1, 0x8f, 0xae, 0xa8, 0x0e, 0xc6, 0xf1, 0x57, 0xf8, +0xdf, 0x22, 0x19, 0xb4, 0xb0, 0x59, 0xce, 0x18, 0x0f, 0x54, 0xb6, 0x6b, 0x70, 0xac, 0x77, 0x00, +0xeb, 0x99, 0x4b, 0x92, 0xaf, 0xc4, 0x0e, 0xcb, 0xa5, 0x97, 0x4d, 0x88, 0x0a, 0x3d, 0x34, 0x33, +0x62, 0x7c, 0xf4, 0xe4, 0xef, 0x05, 0xb5, 0x4f, 0x47, 0x23, 0x8e, 0x0e, 0x96, 0x24, 0x75, 0x47, +0x39, 0x8a, 0x89, 0xf8, 0x26, 0x60, 0x6d, 0x9a, 0x14, 0x0d, 0x1b, 0xc1, 0x13, 0xfc, 0xcc, 0x9f, +0xd1, 0x6f, 0xb3, 0x3b, 0x49, 0xdf, 0x21, 0xd3, 0x0a, 0x0e, 0xe9, 0x59, 0x3d, 0x57, 0x2c, 0xbd, +0x12, 0x37, 0x92, 0x8b, 0x54, 0x04, 0x84, 0x93, 0xc0, 0x9d, 0xba, 0x26, 0xdc, 0x21, 0x98, 0x1a, +0x92, 0x6c, 0xc2, 0xdf, 0xde, 0x1a, 0x5b, 0xe7, 0xd9, 0xf6, 0x82, 0x35, 0x52, 0x5b, 0xc2, 0x18, +0x41, 0x6e, 0x68, 0xcc, 0x51, 0x7a, 0xfa, 0xb4, 0x26, 0xb5, 0x0b, 0xc7, 0xfa, 0x20, 0xd6, 0xd7, +0x84, 0x92, 0x46, 0x53, 0x29, 0x1a, 0xaa, 0x3e, 0x3f, 0x62, 0x04, 0x7c, 0x7c, 0xb6, 0x5e, 0x7b, +0x31, 0xd1, 0x8b, 0xad, 0xdf, 0xc4, 0xd4, 0x84, 0x31, 0x56, 0xfe, 0xf1, 0xf2, 0xda, 0xd9, 0x85, +0xc1, 0x29, 0x93, 0xe4, 0x32, 0xbb, 0x33, 0x10, 0x71, 0xf8, 0xc2, 0xc7, 0xaa, 0x62, 0x87, 0x0c, +0xdb, 0x94, 0x0d, 0x17, 0xa2, 0x44, 0xfc, 0x7b, 0x03, 0x49, 0x40, 0x96, 0x7b, 0x9c, 0x6b, 0xf4, +0xbe, 0xa4, 0x21, 0x6d, 0x2e, 0x8d, 0x1a, 0x21, 0xd2, 0xc1, 0x08, 0x3a, 0xb2, 0x6b, 0x80, 0x84, +0x86, 0x5e, 0x9d, 0x1c, 0x45, 0x84, 0x70, 0x7e, 0x9f, 0xf8, 0x78, 0xf5, 0x33, 0x5e, 0x6b, 0x2a, +0x27, 0x9f, 0x97, 0xe0, 0xec, 0x97, 0x30, 0xf8, 0x9d, 0x52, 0x58, 0x71, 0xf3, 0x7c, 0xf5, 0x0a, +0xf9, 0xa1, 0x5a, 0x98, 0x0b, 0x45, 0x2a, 0xd4, 0xff, 0xb4, 0xd4, 0x3f, 0x77, 0x89, 0x3a, 0xdf, +0xdd, 0x89, 0xde, 0x3b, 0x95, 0x37, 0x71, 0xaf, 0x50, 0x94, 0x2e, 0xdb, 0x9b, 0x63, 0xe1, 0x61, +0x50, 0xa9, 0xae, 0xdd, 0xc1, 0x0d, 0x35, 0xa7, 0x22, 0xdf, 0x12, 0x47, 0x63, 0xae, 0xc5, 0xbb, +0x8f, 0xab, 0x8f, 0x56, 0x57, 0x98, 0x3c, 0xdb, 0x66, 0x10, 0xaa, 0x75, 0x10, 0x55, 0xb3, 0x68, +0x29, 0xfb, 0x38, 0xae, 0xe7, 0x89, 0xef, 0x07, 0xbf, 0xad, 0xbb, 0xbd, 0xc7, 0x6b, 0x0a, 0x35, +0x37, 0xb7, 0xa2, 0x91, 0x09, 0x00, 0x64, 0x38, 0x7e, 0xe6, 0x5b, 0x14, 0xb2, 0x47, 0x7d, 0xdb, +0x9b, 0x71, 0xf5, 0x13, 0x65, 0x04, 0xed, 0x59, 0x55, 0xb2, 0x4a, 0x06, 0xa1, 0x70, 0xc2, 0x2e, +0x0e, 0xc3, 0x07, 0xab, 0x03, 0xed, 0x82, 0x67, 0x10, 0xf1, 0x73, 0xbf, 0x6d, 0xad, 0x69, 0x70, +0x85, 0x23, 0x42, 0x78, 0xd6, 0x80, 0xd5, 0x19, 0x95, 0xe5, 0xa0, 0x50, 0x0d, 0x80, 0xb0, 0xf3, +0xeb, 0xf6, 0x1f, 0x14, 0x99, 0xdf, 0xc1, 0xf5, 0xb1, 0x2f, 0x25, 0xcc, 0x1a, 0x6b, 0x2a, 0x02, +0x8f, 0x53, 0xf9, 0xdf, 0x4c, 0xcf, 0x64, 0x72, 0x2d, 0x85, 0xfd, 0x15, 0xe2, 0x91, 0xdb, 0x38, +0x6c, 0x0f, 0x72, 0x78, 0xad, 0x82, 0x13, 0x6a, 0x94, 0xfc, 0xea, 0xf0, 0x64, 0x87, 0x25, 0x0b, +0x8d, 0x23, 0x47, 0x19, 0xc3, 0x39, 0xea, 0xef, 0xf8, 0xc2, 0x42, 0xd9, 0x61, 0xc0, 0xfb, 0xc0, +0x7f, 0xf8, 0x25, 0x56, 0x81, 0xaa, 0x7b, 0x26, 0x3d, 0xbb, 0x31, 0x2e, 0x9e, 0x0e, 0xb6, 0x16, +0x7e, 0x87, 0xcd, 0x48, 0x75, 0x05, 0x4f, 0xff, 0x32, 0x36, 0x61, 0x6e, 0x28, 0x2a, 0x0d, 0xc8, +0xd5, 0x1f, 0x29, 0x84, 0x6f, 0x87, 0xec, 0x0e, 0xd3, 0xf2, 0x75, 0xa8, 0xea, 0xca, 0x37, 0x0c, +0xcb, 0xfd, 0xe6, 0x75, 0x78, 0x15, 0xb6, 0x21, 0xa3, 0xd3, 0x8e, 0xff, 0x3d, 0x5d, 0xe5, 0xf2, +0x8a, 0x93, 0x0f, 0x3d, 0x30, 0x1f, 0xb8, 0x0c, 0x63, 0x68, 0xdf, 0xa8, 0x25, 0x3a, 0x31, 0x4a, +0x6f, 0xe2, 0xcc, 0xb2, 0xbd, 0xeb, 0x77, 0x94, 0x43, 0x52, 0x9a, 0x5f, 0xa7, 0x6b, 0x87, 0x7f, +0x6a, 0x62, 0x0f, 0xff, 0xfd, 0x3d, 0x60, 0xad, 0xff, 0x43, 0x37, 0xc0, 0xe4, 0x97, 0xba, 0xb3, +0x61, 0xcb, 0xba, 0x82, 0x3d, 0xc1, 0xa7, 0x79, 0x29, 0x48, 0x84, 0xc8, 0xfc, 0x36, 0x77, 0x71, +0x7e, 0xbc, 0xed, 0xaf, 0x64, 0x03, 0xec, 0xd5, 0x30, 0x60, 0x3d, 0xc7, 0x43, 0x2a, 0xb8, 0x47, +0xb8, 0xf7, 0x16, 0xfa, 0xcc, 0x01, 0x59, 0x40, 0x66, 0x94, 0x98, 0xdc, 0x66, 0x39, 0x38, 0x41, +0x0f, 0x6f, 0xf5, 0x53, 0xcd, 0xcc, 0x40, 0x5c, 0x1c, 0x10, 0xc4, 0xb5, 0x27, 0xf8, 0xfe, 0x0b, +0xd5, 0x0c, 0x6c, 0x8b, 0x25, 0xbe, 0x28, 0xa0, 0x37, 0x83, 0x9a, 0xcc, 0xd2, 0xd9, 0xaf, 0x99, +0x51, 0x00, 0x58, 0xff, 0xa2, 0xc0, 0x41, 0x49, 0xa6, 0x07, 0x4f, 0x5f, 0x87, 0x4a, 0x9d, 0x0e, +0x90, 0xc7, 0xa8, 0xa0, 0x60, 0x4c, 0x30, 0xe4, 0x1b, 0x92, 0x25, 0x15, 0x57, 0x67, 0xaf, 0x5a, +0x47, 0x41, 0x16, 0x59, 0x59, 0x7a, 0xb4, 0x87, 0xad, 0x7f, 0x04, 0x39, 0xc3, 0xf2, 0xbf, 0x2f, +0x08, 0x3d, 0x22, 0x46, 0x15, 0x83, 0xc7, 0x1e, 0x56, 0xc4, 0xb8, 0x53, 0x65, 0x08, 0xb5, 0x38, +0x63, 0xa2, 0x59, 0xf4, 0x8e, 0x74, 0x32, 0xe8, 0x89, 0x45, 0x8e, 0x2c, 0xa8, 0x2d, 0x70, 0x9e, +0x03, 0x5c, 0x71, 0x92, 0x5c, 0x8d, 0x13, 0x1b, 0xc6, 0xab, 0x06, 0x58, 0xf7, 0x74, 0x91, 0x29, +0x6f, 0x64, 0xb7, 0xa6, 0xfb, 0xbf, 0xd8, 0x62, 0x27, 0x96, 0x98, 0x5b, 0xc7, 0xb5, 0xf3, 0x77, +0x05, 0x06, 0xa2, 0x7b, 0x5f, 0xbc, 0xf2, 0x37, 0x93, 0x10, 0x47, 0xd9, 0xa5, 0xcf, 0x51, 0xa4, +0x10, 0xf4, 0xf6, 0x36, 0xfb, 0x42, 0x95, 0xbd, 0x92, 0x31, 0x12, 0xbe, 0x51, 0xee, 0x62, 0x44, +0xb3, 0xd2, 0xb2, 0x83, 0xd5, 0x6f, 0xa9, 0x3d, 0x4f, 0x35, 0x49, 0x38, 0x7f, 0xd5, 0xb8, 0xbc, +0x79, 0x75, 0x6c, 0xa2, 0x78, 0x86, 0x94, 0x32, 0x0a, 0xba, 0x30, 0x0d, 0x3c, 0x1e, 0x24, 0x1e, +0xbe, 0x12, 0x65, 0xbb, 0x35, 0xa1, 0xb1, 0x18, 0xe6, 0x46, 0xd1, 0x91, 0x2c, 0xa7, 0x51, 0x41, +0xdf, 0xf2, 0x24, 0xe7, 0x6e, 0x04, 0x09, 0x52, 0x62, 0x14, 0x81, 0x22, 0x2e, 0x16, 0x94, 0x96, +0xb4, 0x3f, 0xc1, 0xc8, 0xb8, 0x1a, 0xad, 0xfb, 0xec, 0x8e, 0xf0, 0x6c, 0x59, 0x12, 0x82, 0xaa, +0x08, 0x7e, 0x11, 0x6a, 0x94, 0x90, 0xd9, 0xba, 0x79, 0xcc, 0xea, 0xd4, 0x45, 0x7a, 0x8a, 0x8d, +0x1c, 0xe6, 0x41, 0x65, 0x17, 0xc2, 0x44, 0xb4, 0xad, 0xd0, 0x32, 0x53, 0xcb, 0x6f, 0x01, 0x65, +0x20, 0xf4, 0x06, 0x5e, 0x8f, 0x02, 0x92, 0x28, 0x78, 0xc1, 0x58, 0xf8, 0xbe, 0x2c, 0x4c, 0xa5, +0x7d, 0x15, 0xab, 0x61, 0x6c, 0x93, 0xc3, 0x28, 0x19, 0x38, 0x2c, 0x54, 0x0b, 0x55, 0xeb, 0x9d, +0x2e, 0xef, 0x0e, 0xe3, 0x06, 0x99, 0x2a, 0xf8, 0x2f, 0x21, 0xac, 0xfe, 0x87, 0x09, 0xde, 0x63, +0x41, 0xcd, 0xfd, 0x36, 0x14, 0x07, 0x47, 0x7e, 0x21, 0x30, 0xe6, 0x69, 0x16, 0xca, 0xa9, 0xeb, +0x4d, 0xda, 0xc1, 0x88, 0xa6, 0xd0, 0xa6, 0x75, 0xa0, 0x21, 0xbd, 0x09, 0x07, 0x7c, 0xa7, 0x29, +0x7b, 0xf2, 0xb5, 0xb6, 0x0b, 0x71, 0x73, 0x40, 0x45, 0xd4, 0x41, 0x53, 0x9f, 0x95, 0xaa, 0xa9, +0x11, 0x88, 0x45, 0x2b, 0xe5, 0x7b, 0xd2, 0x11, 0xeb, 0xae, 0x24, 0x05, 0xbd, 0x33, 0xd0, 0xcc, +0x67, 0x95, 0x8f, 0xa2, 0x62, 0xd4, 0x1a, 0x42, 0x46, 0xde, 0x83, 0xd2, 0x09, 0x2e, 0x86, 0x70, +0x17, 0x30, 0x4c, 0x16, 0xa9, 0x85, 0xef, 0xf2, 0x2e, 0x8e, 0x68, 0x0a, 0x83, 0xcb, 0x6f, 0x3f, +0xae, 0x53, 0xbc, 0xa7, 0xcf, 0x02, 0x2f, 0x54, 0xb3, 0xc8, 0xcb, 0x94, 0x0f, 0x33, 0xd0, 0x5e, +0xe2, 0x3d, 0x4a, 0x26, 0xea, 0x88, 0x31, 0x80, 0x2e, 0xc2, 0x4c, 0x4a, 0x59, 0x8e, 0xf4, 0xad, +0xb9, 0x2d, 0x3c, 0x13, 0x31, 0x0e, 0x75, 0x79, 0x41, 0xbd, 0x92, 0xa8, 0x6b, 0x69, 0x68, 0x46, +0xec, 0xae, 0x5a, 0x1f, 0xfe, 0x71, 0x8e, 0xf2, 0x61, 0xaa, 0x70, 0xb9, 0xe2, 0x22, 0x8f, 0xb7, +0x19, 0xa5, 0x04, 0xfc, 0xfd, 0xf3, 0xf8, 0xd8, 0x3e, 0x5e, 0x3b, 0xaf, 0x86, 0x17, 0x48, 0x90, +0x75, 0x10, 0xea, 0x3c, 0x38, 0x1b, 0x48, 0x84, 0x0c, 0xa1, 0x26, 0x58, 0xcf, 0x1e, 0xe2, 0x8f, +0xbf, 0xbd, 0x0c, 0xbf, 0x3e, 0x82, 0xe2, 0x20, 0xef, 0xe7, 0x54, 0x25, 0xa2, 0xe6, 0x17, 0x27, +0xb5, 0x3f, 0x4e, 0xfa, 0x8f, 0xaa, 0xcf, 0xb0, 0x4c, 0x0f, 0x27, 0x73, 0x3b, 0x95, 0x10, 0x8f, +0xfa, 0xd5, 0xc4, 0x0b, 0x92, 0xcf, 0x67, 0xf4, 0x44, 0x7f, 0x8c, 0xe6, 0x77, 0x67, 0x66, 0x46, +0x17, 0x43, 0xd9, 0xd3, 0xd3, 0xe5, 0x61, 0x8a, 0x9c, 0x27, 0x77, 0x17, 0xe0, 0x9c, 0x59, 0x8f, +0x42, 0x63, 0x39, 0x2d, 0x83, 0xd9, 0xd0, 0x89, 0x67, 0x13, 0x28, 0xf4, 0xf7, 0xe1, 0xae, 0xfb, +0x59, 0x23, 0xcf, 0x1e, 0xc1, 0x31, 0x9d, 0xaa, 0x80, 0x33, 0x66, 0x91, 0x48, 0xc5, 0xa1, 0xf1, +0xcc, 0x49, 0xc8, 0x27, 0x54, 0x2b, 0xb1, 0x66, 0xce, 0x41, 0x58, 0x5f, 0xe5, 0x18, 0x47, 0xc8, +0x16, 0xcb, 0xdf, 0x89, 0x54, 0x08, 0xa6, 0xf6, 0x71, 0x93, 0x1d, 0xbb, 0x1f, 0x0b, 0xdf, 0x4e, +0x9e, 0x4d, 0xe9, 0x74, 0x80, 0xe4, 0x4d, 0x0f, 0xe0, 0x72, 0x9c, 0x9a, 0x60, 0xb7, 0x22, 0x86, +0x30, 0x6e, 0x3e, 0x74, 0x30, 0x80, 0x9e, 0x0d, 0x2c, 0xab, 0xe0, 0x21, 0x4c, 0x7a, 0x1c, 0xab, +0x5d, 0x64, 0x5d, 0xc7, 0xd6, 0x94, 0x24, 0x58, 0x44, 0x38, 0xaf, 0x64, 0x1c, 0x91, 0x20, 0xaa, +0xa8, 0x3d, 0x76, 0x08, 0x29, 0x21, 0xb8, 0x9b, 0x43, 0x46, 0xc6, 0x54, 0xf1, 0x23, 0x96, 0x9a, +0x2a, 0x58, 0x23, 0x87, 0x6a, 0xe5, 0xc5, 0x31, 0x4c, 0x0c, 0x55, 0xa1, 0x81, 0x7c, 0xa3, 0xbb, +0xc4, 0x7a, 0xe4, 0xf3, 0x14, 0x66, 0x43, 0xb9, 0x17, 0xe5, 0x57, 0x83, 0x39, 0xf6, 0xa8, 0x98, +0x68, 0x02, 0x27, 0x4b, 0xb1, 0xf0, 0x92, 0x68, 0xac, 0x8a, 0x22, 0x7c, 0xb9, 0xac, 0x8c, 0xd9, +0xc3, 0x0c, 0x46, 0x97, 0xdf, 0xdd, 0xab, 0x73, 0x0e, 0xd0, 0xfd, 0x92, 0xc7, 0xa7, 0x05, 0xe4, +0x39, 0x3b, 0x93, 0xba, 0xd0, 0x1b, 0x12, 0x29, 0x6c, 0xef, 0x15, 0x10, 0x61, 0x5a, 0x3a, 0xe5, +0xf3, 0xfc, 0x8d, 0x09, 0xef, 0x75, 0x61, 0x0a, 0xc5, 0xa8, 0x4b, 0xa1, 0x2e, 0x08, 0x7e, 0x98, +0xb2, 0x88, 0xe4, 0x54, 0xd8, 0x4f, 0x2b, 0xe9, 0xb6, 0xa6, 0x97, 0x9b, 0x08, 0x82, 0x77, 0x0a, +0x1e, 0xea, 0x0b, 0x17, 0x3f, 0xcd, 0x3d, 0x7f, 0x3a, 0x3c, 0x12, 0xb8, 0x4d, 0xb9, 0x7d, 0x65, +0x9f, 0x88, 0x93, 0xd2, 0xc2, 0x3b, 0xa2, 0x70, 0x36, 0xbe, 0x99, 0x59, 0xaf, 0x3b, 0x91, 0xde, +0x66, 0xac, 0xa4, 0x0d, 0x87, 0x8c, 0x92, 0x1d, 0xda, 0xae, 0x84, 0x94, 0x5a, 0x40, 0x7b, 0x32, +0x62, 0x73, 0xb5, 0xb8, 0xe1, 0x6a, 0x09, 0x13, 0xea, 0x53, 0xae, 0xcd, 0xda, 0x3b, 0xd9, 0xb8, +0x4f, 0xdf, 0x4e, 0xd5, 0xd0, 0xd8, 0x12, 0x94, 0x9c, 0x6a, 0x8e, 0xc2, 0x85, 0x41, 0xe2, 0x12, +0x72, 0x77, 0x37, 0xbc, 0xc9, 0x65, 0x9b, 0x10, 0x4e, 0xfd, 0x1b, 0x78, 0x7f, 0xea, 0x39, 0x75, +0xdc, 0xab, 0xcc, 0xed, 0x44, 0xd7, 0x8e, 0x14, 0x81, 0xcb, 0xff, 0x35, 0x2d, 0xa3, 0xd0, 0x9e, +0xf3, 0x92, 0x21, 0x2f, 0x44, 0xf2, 0x7d, 0x81, 0xdc, 0xc9, 0x04, 0x96, 0x74, 0xde, 0xea, 0x37, +0x8d, 0x6c, 0xdc, 0x2b, 0x3b, 0xd9, 0x75, 0x43, 0x5e, 0xe2, 0x52, 0x15, 0x00, 0xf1, 0x79, 0x65, +0x64, 0xb3, 0x1d, 0xd2, 0x86, 0x27, 0x76, 0x52, 0x28, 0xd5, 0x37, 0xa3, 0x81, 0xa6, 0xc5, 0xb5, +0x2b, 0xea, 0xe1, 0x52, 0xc5, 0x0c, 0x24, 0x91, 0x31, 0x5e, 0x7d, 0x38, 0x90, 0xa7, 0x97, 0x0d, +0x40, 0x05, 0xa4, 0x95, 0xe5, 0x35, 0x19, 0x17, 0x93, 0xc9, 0x3f, 0xec, 0x18, 0x17, 0x55, 0x49, +0x32, 0x03, 0xb0, 0x9b, 0xa0, 0x10, 0x98, 0x4e, 0x8c, 0x11, 0xf2, 0xd3, 0x78, 0x6e, 0x55, 0x44, +0xaf, 0x64, 0x1e, 0x86, 0xfa, 0x02, 0x76, 0x65, 0xa7, 0x1d, 0xf9, 0xf1, 0x35, 0xec, 0xf8, 0x9f, +0xe7, 0x4e, 0x40, 0x7d, 0xa8, 0x04, 0xba, 0x41, 0xba, 0x4a, 0x01, 0xcb, 0xc9, 0x02, 0xa3, 0xb6, +0x33, 0x37, 0x04, 0x3c, 0x0a, 0x96, 0x35, 0x7c, 0xc2, 0x5d, 0xee, 0xd4, 0x18, 0x15, 0xd3, 0xc8, +0xaa, 0xc5, 0xd9, 0x79, 0x10, 0xda, 0xae, 0xc1, 0x3b, 0x5b, 0x11, 0xe9, 0x95, 0x7e, 0x57, 0x79, +0x36, 0x8e, 0x98, 0xe6, 0xac, 0xe3, 0x23, 0x39, 0xd5, 0xfa, 0xe2, 0xb4, 0xf2, 0xd8, 0x4d, 0x34, +0x5a, 0xc5, 0x18, 0x8a, 0x8e, 0xe7, 0x87, 0x4a, 0xbd, 0xa5, 0x04, 0xeb, 0x59, 0x37, 0x73, 0x11, +0x13, 0xfe, 0x92, 0xc5, 0x96, 0xe2, 0x4e, 0xe9, 0xc3, 0xa0, 0xd4, 0xc0, 0x47, 0x61, 0x44, 0xa7, +0xb6, 0xfd, 0x0d, 0xaa, 0x02, 0xc2, 0xc1, 0x8d, 0x47, 0xea, 0x97, 0x90, 0xc8, 0x33, 0x11, 0x9c, +0xd0, 0x5e, 0xe3, 0x3c, 0xbb, 0x29, 0x92, 0xc6, 0x0b, 0x2d, 0xfd, 0xbe, 0xb3, 0xca, 0xb8, 0x5f, +0x9b, 0x9e, 0x31, 0x20, 0x9f, 0x96, 0x9d, 0x3f, 0xf9, 0xdf, 0x8f, 0x1b, 0x9a, 0xce, 0x20, 0x69, +0x94, 0x23, 0x07, 0x93, 0x22, 0x33, 0x5e, 0xf3, 0x40, 0x85, 0xe2, 0x45, 0xc3, 0x3a, 0x5d, 0xbe, +0x13, 0x0f, 0x18, 0x44, 0x89, 0x2c, 0x65, 0x21, 0x0b, 0x06, 0x4a, 0x51, 0xb8, 0x7c, 0x8a, 0xb5, +0xfa, 0x70, 0x3f, 0x38, 0x20, 0x2f, 0x6c, 0xdd, 0x59, 0xa3, 0xa2, 0x63, 0xd3, 0x20, 0xd4, 0xde, +0xfe, 0x8b, 0x4e, 0x44, 0x08, 0xe7, 0xf5, 0x05, 0xae, 0x14, 0x0d, 0xb1, 0xb6, 0xa9, 0xe0, 0xf2, +0x66, 0xa6, 0x65, 0x44, 0xa7, 0x78, 0x93, 0xfd, 0x69, 0x2e, 0x0a, 0xdc, 0x59, 0xe8, 0x76, 0x03, +0x63, 0xff, 0x09, 0xd5, 0x26, 0x6d, 0xa7, 0x6a, 0x53, 0xac, 0xb9, 0x6c, 0x5b, 0xd7, 0xc3, 0xa2, +0x73, 0x74, 0x7f, 0x86, 0xab, 0x48, 0xd8, 0x67, 0x32, 0xa4, 0x9c, 0x91, 0x51, 0x93, 0x4f, 0xca, +0xd2, 0xcb, 0xaa, 0xe4, 0x1e, 0x5c, 0xc8, 0x62, 0xc1, 0x58, 0xa3, 0x19, 0xeb, 0x2c, 0x48, 0x9b, +0x99, 0x81, 0xf7, 0x38, 0x98, 0xb6, 0x57, 0xfe, 0x73, 0x20, 0xe3, 0x66, 0xc6, 0x41, 0xab, 0xc7, +0xb2, 0x81, 0xf0, 0x79, 0x90, 0x08, 0x2e, 0xb5, 0xe8, 0x97, 0xa7, 0x54, 0x9e, 0xdf, 0x49, 0x60, +0x54, 0xfb, 0x8c, 0x60, 0x97, 0x8d, 0x24, 0x9d, 0x73, 0x92, 0x99, 0x3c, 0x73, 0x6a, 0xc6, 0xcf, +0xb2, 0xb8, 0xd7, 0x76, 0x36, 0xa4, 0x01, 0xb8, 0x39, 0x44, 0x97, 0x3d, 0x81, 0xe8, 0xcc, 0x4f, +0x9a, 0x7d, 0x33, 0xac, 0xe6, 0xe9, 0x7c, 0xb6, 0xcb, 0xfb, 0x6f, 0x45, 0x16, 0x19, 0xa6, 0x63, +0x62, 0x5e, 0x2e, 0x77, 0x98, 0x49, 0xd6, 0xca, 0x1c, 0x2f, 0x0c, 0x79, 0xb4, 0x19, 0x6c, 0x60, +0xc3, 0x6d, 0x48, 0xf7, 0xbd, 0x6b, 0x5c, 0x04, 0xad, 0x57, 0x76, 0x44, 0x58, 0x1d, 0xeb, 0x4e, +0x9a, 0x3a, 0xf1, 0x28, 0xc2, 0xeb, 0x08, 0xfe, 0xad, 0xd2, 0xa3, 0xcd, 0x62, 0xd6, 0xa6, 0x22, +0x5d, 0xc7, 0x7b, 0xa8, 0xfd, 0x0a, 0x8e, 0x37, 0xf8, 0xc5, 0xab, 0xbe, 0x42, 0x81, 0xd4, 0xa6, +0x12, 0x9d, 0x0d, 0x4f, 0x2b, 0xc0, 0xac, 0xc4, 0x6d, 0xa7, 0xd5, 0x52, 0xfa, 0xca, 0xae, 0xe0, +0x0d, 0xc2, 0xa3, 0x43, 0xba, 0x3e, 0xd4, 0x20, 0xbc, 0x23, 0xe4, 0xd7, 0x4d, 0x8d, 0x54, 0x37, +0x2f, 0xc4, 0xb5, 0x2a, 0x6a, 0x19, 0x6c, 0x1b, 0x26, 0xff, 0xa1, 0x8e, 0x22, 0x16, 0x7a, 0x0f, +0x19, 0x43, 0x00, 0x48, 0xdf, 0x30, 0x6f, 0xc9, 0xa6, 0x93, 0xf7, 0x47, 0xb1, 0x38, 0x4d, 0x1e, +0x13, 0x8f, 0x94, 0x4e, 0x77, 0xe0, 0x93, 0x59, 0xf4, 0x36, 0x1f, 0x7b, 0x44, 0xf5, 0xa1, 0x39, +0x2d, 0x06, 0x83, 0x4b, 0xe5, 0x37, 0x49, 0xdf, 0xa7, 0x8e, 0xf5, 0x3b, 0xcd, 0xbb, 0x3d, 0xfd, +0xc4, 0xa4, 0xf9, 0x92, 0x40, 0x28, 0x2e, 0x6c, 0x2b, 0x0c, 0x35, 0xec, 0x69, 0x11, 0x49, 0x6d, +0x40, 0xdb, 0x9d, 0xa0, 0x48, 0x10, 0x91, 0x18, 0xb6, 0x46, 0x5d, 0x68, 0xd4, 0x21, 0xa2, 0x7f, +0x17, 0xc5, 0x3a, 0x1f, 0x6d, 0xf5, 0x04, 0xaa, 0x9c, 0x5c, 0xbd, 0x15, 0x3d, 0xfb, 0x97, 0xe8, +0x01, 0xec, 0x53, 0x61, 0xeb, 0xb9, 0x94, 0x64, 0xee, 0x5d, 0xf6, 0x33, 0x0d, 0x75, 0x3b, 0xc4, +0x0e, 0x4d, 0x7f, 0x83, 0x63, 0x85, 0x76, 0x09, 0x82, 0x62, 0xcb, 0x21, 0xe3, 0xf9, 0xdb, 0x4a, +0xb5, 0xb3, 0x8f, 0xf3, 0x8f, 0xd4, 0xcf, 0x7c, 0x0d, 0x33, 0x9e, 0xe6, 0x40, 0xa9, 0x38, 0x09, +0xd9, 0xee, 0x97, 0x05, 0x45, 0x49, 0xf2, 0xc5, 0x03, 0xfc, 0xdf, 0x2e, 0x39, 0x74, 0x21, 0x91, +0xb2, 0xb2, 0x22, 0x01, 0x75, 0x21, 0x62, 0xfb, 0xe7, 0xc0, 0x05, 0xea, 0x1a, 0x77, 0x04, 0x33, +0x22, 0xb5, 0x97, 0xf4, 0x63, 0x9a, 0x39, 0x37, 0xfc, 0x25, 0x93, 0x76, 0xb2, 0x45, 0xd9, 0xf9, +0x9f, 0xa5, 0x46, 0x6b, 0x88, 0x46, 0x26, 0x06, 0xfa, 0xe0, 0xec, 0x3c, 0xd2, 0x06, 0xc7, 0x26, +0xb7, 0xea, 0x18, 0xa7, 0xdf, 0xde, 0x9b, 0x2d, 0x16, 0x79, 0xab, 0xc9, 0x4e, 0xa9, 0xf3, 0xcb, +0x6c, 0xf5, 0x59, 0xed, 0xd4, 0x73, 0x18, 0xf4, 0xce, 0x63, 0x14, 0x90, 0xc6, 0xb2, 0x0c, 0xe5, +0x36, 0x04, 0x0f, 0xf7, 0xec, 0xbd, 0x29, 0x23, 0x7d, 0xf4, 0xf5, 0xa8, 0x3b, 0x9a, 0xdb, 0x45, +0x6a, 0x0b, 0x4f, 0x18, 0x9e, 0x72, 0x1f, 0x52, 0x84, 0x80, 0xeb, 0x7f, 0x80, 0xe5, 0xbf, 0x39, +0x76, 0xb5, 0x45, 0x3c, 0x5f, 0xc0, 0x15, 0x62, 0xce, 0x51, 0x4a, 0xb8, 0xa4, 0x08, 0xb4, 0x75, +0x17, 0xac, 0xc8, 0x1a, 0x20, 0xda, 0xbc, 0x40, 0xee, 0x00, 0x9a, 0xa4, 0xb2, 0x3c, 0x4d, 0x33, +0x00, 0x6f, 0x09, 0x69, 0xa0, 0x02, 0xda, 0x64, 0x9b, 0x40, 0x37, 0xfb, 0xc5, 0xc4, 0xba, 0x19, +0x98, 0x11, 0xcc, 0x48, 0x0a, 0x63, 0xfd, 0xee, 0x0e, 0x77, 0x02, 0xb8, 0x6e, 0x8e, 0xe0, 0xa2, +0xd0, 0xdc, 0x0c, 0x30, 0x45, 0x4b, 0xb7, 0xbe, 0xd4, 0x6d, 0x9d, 0x63, 0xa7, 0xa7, 0x34, 0xd0, +0x48, 0xf9, 0x4c, 0xc1, 0x8d, 0xdb, 0x5c, 0x28, 0x2d, 0x49, 0xf9, 0x47, 0x08, 0xb7, 0xbd, 0x6a, +0xb2, 0xa0, 0xe6, 0x69, 0xab, 0x7b, 0xc3, 0x62, 0xc7, 0xda, 0xdc, 0x6e, 0x46, 0x77, 0xa6, 0xcd, +0xca, 0x1b, 0x8d, 0x0b, 0x0c, 0x17, 0xe7, 0xa0, 0x5c, 0x51, 0x2f, 0x11, 0x75, 0x4f, 0x4c, 0xfa, +0x89, 0xcb, 0xd0, 0x13, 0x17, 0xf6, 0xa1, 0x68, 0x6f, 0xe0, 0xc6, 0xa4, 0xd4, 0x56, 0xc5, 0x45, +0xcd, 0xc1, 0x4b, 0x15, 0xe1, 0x1c, 0xf1, 0xed, 0x4b, 0x3a, 0x00, 0xda, 0x68, 0x72, 0xc5, 0x94, +0xae, 0xe7, 0xbe, 0xc0, 0x70, 0x41, 0x43, 0x99, 0x30, 0xf2, 0x22, 0x37, 0x31, 0xe2, 0x5c, 0xe8, +0x49, 0x36, 0x05, 0xbc, 0x0f, 0x22, 0x60, 0xa2, 0xf0, 0xde, 0x29, 0x81, 0x11, 0x23, 0x24, 0x04, +0xd7, 0x86, 0xe4, 0x94, 0x3a, 0xea, 0xed, 0x18, 0x5d, 0x9e, 0xd2, 0x7b, 0xc4, 0x32, 0xf9, 0xde, +0xdb, 0x49, 0x3b, 0xa4, 0x65, 0xd4, 0xea, 0x2d, 0xcc, 0x3e, 0xf3, 0x9c, 0x29, 0x3f, 0x75, 0x63, +0x55, 0xf0, 0xa1, 0xf2, 0xe8, 0xb7, 0x50, 0xbf, 0x0f, 0xea, 0xab, 0xec, 0xf1, 0x5d, 0xef, 0xdf, +0x99, 0xe6, 0x74, 0x25, 0x6b, 0x6c, 0xf9, 0x07, 0x43, 0x53, 0xb1, 0x35, 0x6e, 0x5d, 0x3f, 0xf3, +0x1d, 0x11, 0x13, 0x37, 0x69, 0x29, 0x4b, 0x72, 0x60, 0x9f, 0x42, 0x73, 0x92, 0xa8, 0x6a, 0x76, +0x50, 0xac, 0xf3, 0x0c, 0x48, 0xe6, 0x16, 0x33, 0x06, 0x3a, 0x2c, 0x97, 0xc6, 0xff, 0x5c, 0xe0, +0xe2, 0xa6, 0x31, 0x67, 0x1a, 0xd5, 0x5c, 0x7b, 0xf8, 0x5b, 0x4d, 0x40, 0xe5, 0x1d, 0x05, 0xb0, +0xa5, 0xd5, 0x68, 0x11, 0x80, 0x31, 0x96, 0xb2, 0xf2, 0xe2, 0x9e, 0xc3, 0x12, 0xc1, 0x81, 0x88, +0x15, 0x52, 0xd6, 0xa8, 0x2b, 0x52, 0x65, 0xdd, 0x15, 0x68, 0xf8, 0x2b, 0x3c, 0x36, 0xc3, 0x76, +0x3a, 0xf2, 0x01, 0x2d, 0x38, 0xb4, 0xa3, 0x1e, 0x4b, 0x1f, 0xaf, 0x99, 0x2d, 0x4e, 0x16, 0x1e, +0xc1, 0x16, 0xe7, 0x52, 0x0b, 0xc1, 0x89, 0x7e, 0x2c, 0x3a, 0x0b, 0xa1, 0x48, 0xc1, 0xac, 0xa5, +0x54, 0xac, 0xb3, 0x1a, 0x41, 0x18, 0xac, 0x51, 0xa5, 0x68, 0xab, 0x99, 0x34, 0x68, 0xb6, 0xa3, +0x2a, 0x97, 0x85, 0xb5, 0xaa, 0x33, 0x2a, 0x32, 0x69, 0xf6, 0x30, 0xc3, 0x1a, 0xb6, 0x05, 0x1b, +0xd1, 0xd2, 0xfd, 0xd4, 0xa3, 0x37, 0xea, 0xa3, 0xa4, 0x3f, 0xde, 0x95, 0xa9, 0x1e, 0xde, 0xd2, +0xff, 0x36, 0xa6, 0x3e, 0x1c, 0x75, 0xbc, 0x43, 0xfa, 0xb1, 0x20, 0xb4, 0x0c, 0x95, 0x75, 0x96, +0xc8, 0x26, 0xf6, 0x80, 0x01, 0x03, 0x84, 0x4f, 0x10, 0x4d, 0x78, 0x8a, 0xdd, 0xe6, 0xc8, 0xdc, +0x8c, 0x55, 0xe2, 0xf1, 0xfc, 0xe0, 0x0d, 0x30, 0x22, 0xff, 0xad, 0x9b, 0xf7, 0xf4, 0x48, 0x37, +0x48, 0xf6, 0xa4, 0x51, 0x78, 0xf7, 0xe8, 0xc7, 0xf7, 0x07, 0xba, 0x2f, 0x35, 0xe4, 0x18, 0x1d, +0xb7, 0xbd, 0x2b, 0xe5, 0x11, 0xc5, 0x8f, 0xdb, 0x9d, 0xeb, 0xbf, 0x8f, 0x2c, 0x3d, 0x54, 0xa3, +0x2c, 0x21, 0xf9, 0x85, 0x57, 0x21, 0x13, 0x7b, 0x76, 0xbf, 0xd7, 0xa4, 0xfa, 0xe5, 0xba, 0xdf, +0xeb, 0x49, 0xa6, 0x4e, 0xa2, 0x72, 0xff, 0x62, 0x67, 0x67, 0x97, 0x8f, 0x28, 0xa6, 0x51, 0x45, +0x34, 0xb8, 0xba, 0xf2, 0x32, 0xd8, 0x74, 0x0d, 0xf0, 0xe4, 0x51, 0x90, 0xd9, 0x58, 0xe4, 0x66, +0x09, 0xcf, 0xf2, 0x36, 0x07, 0x38, 0xe1, 0x74, 0x0b, 0x8b, 0x86, 0x7d, 0xee, 0x0b, 0x8f, 0x43, +0x2c, 0xc5, 0xf4, 0xdb, 0x26, 0xb7, 0x86, 0x96, 0xe4, 0xb9, 0xa5, 0x30, 0x79, 0x88, 0xc4, 0x8c, +0x7d, 0x53, 0x01, 0x69, 0x4c, 0x63, 0x58, 0x9c, 0xc5, 0x5c, 0x63, 0x73, 0x39, 0x1f, 0x2f, 0x50, +0xf7, 0xb6, 0xf4, 0x24, 0x4f, 0x84, 0x0b, 0xc7, 0x4d, 0x5b, 0x99, 0xf7, 0xaa, 0x73, 0x63, 0x95, +0x48, 0x61, 0x2b, 0x24, 0xda, 0x98, 0xa7, 0x69, 0x03, 0x03, 0x93, 0x51, 0x5a, 0x23, 0x3c, 0x50, +0x37, 0x18, 0x20, 0x7b, 0x6a, 0xa6, 0xc8, 0x45, 0x9b, 0x97, 0x34, 0x71, 0x18, 0x76, 0x61, 0x58, +0xb6, 0x52, 0x61, 0xc6, 0xfe, 0x0d, 0x91, 0x4f, 0x47, 0x66, 0xa7, 0x9b, 0xc5, 0xe0, 0xdb, 0xd0, +0xeb, 0x1e, 0xab, 0x17, 0x99, 0x84, 0x82, 0x3a, 0x61, 0x41, 0xc1, 0x11, 0xd9, 0xfd, 0x7d, 0xfb, +0xff, 0x8a, 0x02, 0x74, 0x98, 0xfe, 0x55, 0x67, 0x73, 0xac, 0xb3, 0x8a, 0x43, 0x5f, 0xa2, 0x2e, +0x84, 0x23, 0xb3, 0x3b, 0x3d, 0x09, 0x6c, 0x5e, 0xf6, 0xd0, 0xd2, 0x1c, 0xbb, 0x63, 0xa9, 0xd3, +0x81, 0xca, 0xe7, 0x96, 0x8d, 0x18, 0x57, 0x9f, 0x43, 0x28, 0xa8, 0xc3, 0x09, 0xa5, 0xa4, 0x0e, +0xb1, 0x3f, 0x99, 0x58, 0x04, 0xfc, 0x37, 0xff, 0x75, 0x8e, 0x12, 0xf9, 0x91, 0xb8, 0xdd, 0x88, +0x30, 0xdc, 0x63, 0x7a, 0x1d, 0x80, 0xb3, 0xb0, 0x6d, 0x93, 0xb0, 0x6a, 0xf8, 0x63, 0x54, 0x1f, +0x12, 0x68, 0x7a, 0xa9, 0x85, 0x2b, 0x45, 0x2d, 0x67, 0xdf, 0xb1, 0xfd, 0x29, 0x3b, 0x0f, 0x80, +0x03, 0x58, 0x00, 0xde, 0x43, 0xd0, 0x8d, 0xe1, 0xd8, 0x53, 0xb9, 0xb1, 0xa9, 0x01, 0xdb, 0x5b, +0x3e, 0xc1, 0x81, 0xfe, 0x5a, 0xff, 0xe7, 0xf0, 0x5c, 0xfd, 0xf2, 0x15, 0x2e, 0x1d, 0xfc, 0x8b, +0x8d, 0x3a, 0x21, 0x65, 0x9b, 0xd1, 0x6c, 0x4e, 0xaf, 0x6d, 0x63, 0x98, 0xcd, 0xed, 0x3a, 0xc1, +0x5a, 0x51, 0x4d, 0x85, 0xd8, 0x49, 0xbe, 0x49, 0xa1, 0x33, 0xe1, 0x4a, 0x90, 0x69, 0x42, 0x2e, +0x33, 0x96, 0x08, 0xf8, 0x35, 0x6e, 0x18, 0x69, 0x1b, 0xbb, 0x33, 0x7f, 0xae, 0x26, 0xa7, 0xe1, +0x90, 0x2e, 0xe5, 0x21, 0x99, 0xd8, 0x0e, 0xba, 0x52, 0x4f, 0xff, 0x1e, 0x07, 0x4d, 0x6c, 0xa3, +0x76, 0xd8, 0xf2, 0xa7, 0xe9, 0xc7, 0x25, 0x2a, 0x27, 0x47, 0x5a, 0x72, 0x84, 0xae, 0x56, 0x4a, +0xa9, 0xea, 0x1e, 0x56, 0x95, 0xfc, 0x7e, 0x42, 0x11, 0x9e, 0x00, 0xfc, 0x37, 0x8b, 0x10, 0x9c, +0x3c, 0x20, 0x7b, 0xda, 0x24, 0xf8, 0x18, 0xf8, 0x25, 0xb8, 0x4e, 0x47, 0x94, 0xde, 0x62, 0x99, +0xff, 0x23, 0x7b, 0x25, 0xc0, 0xcd, 0xbf, 0xa2, 0x8b, 0x0a, 0x1c, 0x8d, 0x17, 0xe0, 0xe0, 0x63, +0x89, 0x92, 0xb9, 0x9b, 0x07, 0x6e, 0x94, 0xb1, 0x5a, 0x16, 0x96, 0x21, 0xd0, 0xad, 0xec, 0xe7, +0x66, 0x31, 0x11, 0xde, 0xf2, 0x82, 0xab, 0xed, 0xd7, 0xa6, 0xbd, 0x42, 0x6e, 0x22, 0x5f, 0xb7, +0x75, 0xe2, 0xef, 0x6a, 0x11, 0xf5, 0x36, 0x56, 0xcf, 0x92, 0xc0, 0xe3, 0x0b, 0x94, 0xaf, 0x87, +0x80, 0xf9, 0xe6, 0x5f, 0xfe, 0xf8, 0x38, 0xf3, 0x70, 0x8c, 0x14, 0x3e, 0x0e, 0x4c, 0xb6, 0x04, +0x87, 0x94, 0x5f, 0xf5, 0x5b, 0x47, 0x6d, 0x89, 0xfa, 0x94, 0x01, 0xd5, 0x03, 0x30, 0x4b, 0xfe, +0x0f, 0xf4, 0x41, 0x66, 0x1a, 0x8c, 0x5d, 0xf4, 0xfb, 0x5b, 0x9a, 0x80, 0x28, 0x05, 0xd0, 0x4e, +0xbb, 0x2c, 0xab, 0xd0, 0x29, 0xce, 0x7f, 0x1e, 0xf9, 0xc0, 0xdb, 0x8c, 0x30, 0x8a, 0x3d, 0x0a, +0x90, 0xb7, 0x43, 0xa3, 0xd1, 0x55, 0x20, 0xe8, 0x7a, 0xb0, 0x0f, 0x5e, 0x39, 0xcb, 0x2c, 0x78, +0x96, 0xcf, 0x7a, 0x65, 0x3a, 0xa0, 0xcb, 0x68, 0xb2, 0x94, 0x99, 0x20, 0x6f, 0x07, 0xba, 0x7c, +0xd4, 0xf8, 0x23, 0x09, 0x97, 0xa0, 0xfe, 0x4c, 0xbd, 0x0c, 0x93, 0x0f, 0x2f, 0xd7, 0xc6, 0xbb, +0xcd, 0x37, 0xcf, 0x4f, 0xf5, 0xc9, 0xc8, 0xc9, 0xc3, 0x16, 0xc3, 0x3a, 0x8e, 0x9b, 0xf9, 0x07, +0x11, 0xc9, 0x68, 0x46, 0x35, 0xdc, 0xac, 0x6c, 0x87, 0x31, 0x16, 0xbb, 0x7d, 0xe1, 0xca, 0xc4, +0x3a, 0x72, 0xb8, 0xd0, 0xc3, 0x84, 0x92, 0xbc, 0x0a, 0x6a, 0x6b, 0x2f, 0xbd, 0x04, 0x86, 0x2d, +0x57, 0x01, 0xa2, 0x18, 0xab, 0x31, 0x62, 0x5b, 0xa2, 0xc2, 0x3c, 0x3a, 0x62, 0x98, 0xeb, 0x12, +0x57, 0x20, 0x3f, 0x06, 0x9c, 0xd0, 0xc2, 0x3e, 0x0c, 0x1f, 0x10, 0xb3, 0x06, 0xd7, 0xf6, 0xca, +0x7e, 0x8c, 0x95, 0x8e, 0x8f, 0xa5, 0x7c, 0x6c, 0xa1, 0x7d, 0x3c, 0x20, 0x1c, 0xe4, 0x6d, 0x00, +0x0d, 0xb4, 0xe5, 0xef, 0xa7, 0x16, 0xf6, 0x73, 0x83, 0xcd, 0xe6, 0x3f, 0xf3, 0xe9, 0xf1, 0xf7, +0x93, 0x5d, 0x96, 0xfa, 0x14, 0xcc, 0xa3, 0x5e, 0x4a, 0x4c, 0xad, 0xbc, 0x65, 0x0b, 0x33, 0x3f, +0xf2, 0x8e, 0x9f, 0xe8, 0x9d, 0xfa, 0x4d, 0x11, 0x3d, 0xf8, 0xa8, 0xa0, 0xf7, 0x41, 0x34, 0xf4, +0x14, 0x22, 0xb3, 0x03, 0x33, 0xe8, 0xa5, 0x42, 0x31, 0x12, 0x0b, 0xca, 0x56, 0x01, 0x90, 0x48, +0xcf, 0xce, 0xb1, 0xca, 0x35, 0x98, 0xb6, 0xda, 0x4d, 0xbb, 0x51, 0xf4, 0xe4, 0x22, 0x3c, 0xeb, +0x5b, 0x4a, 0x59, 0xc2, 0xbc, 0x72, 0x1f, 0x46, 0xbd, 0xb8, 0x20, 0xf1, 0x74, 0xa6, 0x41, 0x96, +0x90, 0x3f, 0xc8, 0x5f, 0xe6, 0x8a, 0x4c, 0xbe, 0xea, 0xd0, 0x2a, 0xfd, 0xec, 0x76, 0xdd, 0xe4, +0xe7, 0x04, 0xb4, 0xf5, 0xbc, 0x26, 0x2c, 0xda, 0x09, 0x8b, 0x5b, 0x9e, 0xb9, 0xd0, 0x2b, 0xc1, +0x23, 0xb7, 0xe5, 0x06, 0x5e, 0x09, 0x84, 0x69, 0x61, 0x6b, 0x60, 0xa6, 0x42, 0x7f, 0x7b, 0x92, +0x74, 0xd2, 0x67, 0x7d, 0x5a, 0xf7, 0xdc, 0xed, 0xa9, 0x78, 0x5e, 0x8f, 0x31, 0xc8, 0xa8, 0x9e, +0x35, 0x60, 0xda, 0xaa, 0x60, 0x28, 0x7f, 0x87, 0x34, 0x63, 0xcc, 0x70, 0xe6, 0x07, 0x03, 0xcb, +0x75, 0x98, 0x9a, 0xd2, 0x24, 0xa2, 0x86, 0x02, 0x9d, 0x8e, 0xc8, 0x4f, 0x0d, 0xf8, 0x57, 0x43, +0x81, 0xa9, 0x22, 0xd8, 0xa9, 0x45, 0x5b, 0xcd, 0x06, 0x39, 0x47, 0x08, 0x3c, 0x29, 0xce, 0x3a, +0xd1, 0x00, 0x73, 0x69, 0x04, 0x78, 0x1d, 0x69, 0xe4, 0xe2, 0x3a, 0x49, 0x57, 0x08, 0xaf, 0x76, +0x0b, 0x71, 0x17, 0xff, 0x72, 0x42, 0x0c, 0x5c, 0xe6, 0x3b, 0x68, 0xf6, 0xcd, 0x5e, 0x8e, 0x47, +0xdf, 0xc2, 0xa4, 0x2c, 0x9e, 0x19, 0x20, 0x09, 0xd8, 0xd3, 0xb0, 0xfe, 0x36, 0x48, 0x49, 0x26, +0x17, 0x79, 0x8c, 0xed, 0xaa, 0x97, 0xb8, 0xa6, 0xe1, 0xb9, 0xd4, 0x6c, 0x8a, 0xcb, 0x75, 0x19, +0x54, 0x02, 0x00, 0x51, 0x2c, 0x96, 0xa4, 0x74, 0xf3, 0x81, 0x4e, 0xec, 0xe8, 0xd0, 0x43, 0x85, +0x5f, 0x35, 0x73, 0x9e, 0xba, 0x30, 0xea, 0x2a, 0x15, 0x9d, 0x81, 0x5e, 0xc0, 0xb7, 0x16, 0x8f, +0x27, 0x2d, 0x36, 0x91, 0x84, 0x19, 0xc8, 0x54, 0xe6, 0x01, 0x97, 0xb2, 0xf1, 0x3e, 0x5d, 0x0e, +0x13, 0xe8, 0x6e, 0xa0, 0xac, 0x74, 0xa3, 0x6c, 0x59, 0xb0, 0xb7, 0x6c, 0x0e, 0x0d, 0x9e, 0xf2, +0x22, 0x72, 0x4d, 0xd7, 0xf8, 0x25, 0x3f, 0x9e, 0xbd, 0x99, 0x36, 0xad, 0x74, 0x8c, 0x6a, 0xf2, +0xc5, 0x89, 0xd5, 0xa4, 0xad, 0xff, 0xa0, 0x40, 0xb2, 0x1c, 0x20, 0x2a, 0xb3, 0x80, 0x6d, 0x51, +0xd9, 0x2f, 0xee, 0x35, 0x4d, 0x1c, 0x4c, 0x19, 0x2b, 0x42, 0x8b, 0x26, 0xe3, 0x60, 0x15, 0xdb, +0xf0, 0x1e, 0x28, 0x58, 0x98, 0x48, 0x1c, 0x87, 0xdc, 0xe0, 0x68, 0x19, 0x0f, 0x10, 0x06, 0xef, +0xe5, 0x7f, 0x13, 0x75, 0x1f, 0xce, 0x6e, 0x8c, 0x1f, 0x25, 0x76, 0xa0, 0xf8, 0x16, 0x1d, 0x23, +0xe2, 0xdd, 0x4f, 0x92, 0x75, 0x65, 0xf7, 0x3f, 0xd7, 0x84, 0xc6, 0x25, 0x6c, 0x23, 0x6c, 0x3c, +0x4d, 0x5e, 0xc5, 0x50, 0x36, 0x79, 0x8c, 0xcf, 0x06, 0xdb, 0xf5, 0x2b, 0x2f, 0xee, 0x10, 0xa6, +0x50, 0x79, 0x72, 0xcc, 0x56, 0x5c, 0x6f, 0x05, 0x7f, 0x88, 0xd4, 0x44, 0xbf, 0x01, 0xfd, 0x9b, +0xb9, 0x43, 0xfa, 0xc0, 0xf4, 0x84, 0x5c, 0x13, 0x71, 0x20, 0x1e, 0x5d, 0x9a, 0x89, 0xbe, 0xdc, +0x14, 0x33, 0x44, 0xae, 0x74, 0x66, 0x1e, 0x1a, 0x1f, 0x36, 0x81, 0xfb, 0xd3, 0xff, 0xe1, 0x86, +0xa8, 0xf4, 0x91, 0xbb, 0x22, 0x23, 0xa9, 0x28, 0xa4, 0x95, 0x51, 0x72, 0xab, 0xb1, 0x10, 0x85, +0x15, 0x4a, 0xf2, 0x24, 0x45, 0x93, 0xc6, 0x82, 0x7c, 0xd1, 0xdc, 0x3e, 0xe8, 0x0d, 0x08, 0x5b, +0xb1, 0xac, 0xe8, 0xf7, 0x66, 0xbf, 0x8e, 0x6b, 0x65, 0x0e, 0xef, 0xbf, 0x21, 0xdc, 0xe8, 0xc7, +0x7d, 0xe8, 0xbc, 0x0a, 0xa8, 0x35, 0x40, 0x08, 0x8d, 0x74, 0xe0, 0xad, 0x76, 0xe4, 0x20, 0xf7, +0x44, 0x32, 0x57, 0xa0, 0xa8, 0x33, 0xf3, 0x6f, 0xfd, 0x1e, 0xe7, 0xb4, 0x1c, 0xd9, 0x77, 0x22, +0x6a, 0xe0, 0x1f, 0x7d, 0x2d, 0x9c, 0x05, 0xb2, 0xd6, 0xe4, 0xbc, 0xe9, 0x6e, 0x51, 0x9a, 0xf5, +0x75, 0x3d, 0x8b, 0x46, 0xec, 0x95, 0xe9, 0x11, 0xc1, 0x32, 0xaf, 0x61, 0xfc, 0xd9, 0xe1, 0xc3, +0xf4, 0x4d, 0x3b, 0x25, 0x5d, 0x46, 0x9e, 0x00, 0x5d, 0x6f, 0x43, 0x85, 0x66, 0xa9, 0xe1, 0x20, +0x07, 0x32, 0x1d, 0x59, 0xc0, 0xdb, 0x4b, 0x3c, 0x55, 0x63, 0xdf, 0xe9, 0xbd, 0x74, 0x7b, 0x1a, +0x1b, 0x80, 0x12, 0x90, 0xc3, 0x4d, 0xeb, 0x73, 0x34, 0xe1, 0xf4, 0xf7, 0xbd, 0x59, 0xe7, 0xd0, +0x88, 0xe9, 0xa9, 0x79, 0x7e, 0x21, 0x89, 0x02, 0xb5, 0xbf, 0xab, 0xf8, 0x2f, 0x13, 0xf0, 0x57, +0x9a, 0x77, 0xce, 0xa6, 0x9a, 0xfd, 0x23, 0x57, 0x63, 0xeb, 0xdd, 0xe1, 0x31, 0x9f, 0x72, 0x47, +0x3f, 0x75, 0x5f, 0x1f, 0xcd, 0xe3, 0x8a, 0x07, 0x07, 0x69, 0xa7, 0x39, 0xd0, 0x6c, 0xa8, 0xbf, +0x91, 0xb8, 0x5f, 0x77, 0xf1, 0x87, 0x67, 0x3c, 0x0d, 0x82, 0x8c, 0x8b, 0x77, 0x55, 0xd3, 0x6a, +0xd7, 0x41, 0x20, 0xad, 0x68, 0x6c, 0xc8, 0xe2, 0x40, 0x5a, 0x78, 0xb7, 0xc6, 0x0e, 0xd3, 0xc1, +0xda, 0x46, 0xe3, 0x82, 0x8e, 0x54, 0xd3, 0x11, 0x08, 0x70, 0x16, 0x99, 0x85, 0x3e, 0xf5, 0xef, +0x13, 0x74, 0xf0, 0x29, 0xde, 0xd9, 0x30, 0xa6, 0xd8, 0xc4, 0xa0, 0x72, 0xf4, 0xff, 0xc4, 0x6a, +0x72, 0x7c, 0xb5, 0xff, 0xe2, 0x29, 0x29, 0x8e, 0x6c, 0xe0, 0xa5, 0x04, 0xc3, 0x99, 0x4e, 0x18, +0x4e, 0xe0, 0xea, 0xe4, 0x9b, 0x88, 0x0b, 0x63, 0x13, 0x11, 0xf1, 0x26, 0xe6, 0x47, 0x2a, 0x33, +0xa7, 0x2c, 0x26, 0xb3, 0x74, 0x75, 0xb8, 0x40, 0x07, 0xcc, 0x26, 0x2c, 0x4b, 0xea, 0x1b, 0xd6, +0x2e, 0x53, 0xb5, 0x5d, 0xb0, 0x25, 0xf0, 0x25, 0xf7, 0x6d, 0x54, 0x17, 0xb8, 0xed, 0xca, 0xda, +0xd8, 0x26, 0x08, 0xbf, 0x1b, 0xee, 0x42, 0x0a, 0x56, 0x74, 0x53, 0x59, 0x46, 0xcf, 0xe4, 0x7e, +0x98, 0x39, 0x7b, 0xe4, 0xd2, 0x4d, 0x7b, 0x64, 0x39, 0x8d, 0xa9, 0x4f, 0x71, 0x3c, 0xb7, 0x48, +0x23, 0x3f, 0x7a, 0x28, 0x5a, 0x51, 0x28, 0xfa, 0x0f, 0x58, 0xad, 0x3e, 0x7c, 0xb1, 0x8a, 0x2e, +0xc2, 0x16, 0x9c, 0xb2, 0xf5, 0xde, 0x5b, 0xd6, 0x08, 0x67, 0x60, 0xb4, 0x4c, 0x06, 0xac, 0x5c, +0xd8, 0xcb, 0xb3, 0x0c, 0x88, 0xa0, 0x00, 0xa0, 0x26, 0x8a, 0xcb, 0x24, 0x6f, 0x7c, 0xbb, 0x73, +0xfc, 0xc9, 0x39, 0xcb, 0x30, 0x40, 0x45, 0xfb, 0x1e, 0x5b, 0x18, 0x38, 0x02, 0x9e, 0xef, 0x8a, +0xad, 0x6e, 0x3d, 0x3c, 0x24, 0xbe, 0x00, 0x23, 0x2f, 0xd4, 0x93, 0xdd, 0x18, 0x9a, 0xd4, 0x6f, +0x5b, 0x8d, 0x86, 0x96, 0x1a, 0xab, 0xda, 0x79, 0xa1, 0x20, 0x51, 0x5a, 0xd6, 0x13, 0x81, 0x0f, +0x22, 0xff, 0x7a, 0x28, 0x5a, 0x51, 0x28, 0xfa, 0x0f, 0x58, 0xad, 0x3e, 0x7c, 0xb1, 0x8a, 0x2e, +0xc2, 0x16, 0x9c, 0xb2, 0xf5, 0xde, 0x5b, 0xd6, 0x08, 0x67, 0x60, 0xb4, 0x4c, 0x06, 0xac, 0x5c, +0xc9, 0x94, 0x01, 0x78, 0xad, 0x59, 0x51, 0x5f, 0xc9, 0xff, 0x57, 0x14, 0x5a, 0x38, 0x89, 0x50, +0x69, 0xe4, 0xc0, 0xe1, 0xd1, 0x9f, 0x5a, 0x93, 0xe4, 0x05, 0x4a, 0x26, 0x1f, 0x4c, 0xca, 0x85, +0xe2, 0x93, 0x05, 0x8d, 0x43, 0x37, 0x51, 0x78, 0x06, 0x11, 0x45, 0x5d, 0xba, 0x75, 0x05, 0xe1, +0xa0, 0x13, 0x43, 0xc5, 0x47, 0x2b, 0x01, 0xe5, 0xc3, 0x65, 0x25, 0x81, 0x48, 0xf1, 0x42, 0xc2, +0xcf, 0x5c, 0xbc, 0xd2, 0x9d, 0x68, 0x57, 0x01, 0x81, 0x11, 0x86, 0x0f, 0x51, 0xb7, 0x65, 0x53, +0xa9, 0x46, 0x4c, 0x1d, 0xf7, 0xc3, 0x9f, 0xab, 0x1f, 0xa4, 0x1a, 0x8c, 0xef, 0x74, 0xc9, 0xda, +0xa5, 0x88, 0xc0, 0x8b, 0xfd, 0xbb, 0x19, 0x88, 0x52, 0xad, 0x11, 0xe1, 0x13, 0x9b, 0x40, 0xb4, +0x48, 0xaf, 0xde, 0x0a, 0xee, 0x49, 0x8c, 0xde, 0x32, 0xf9, 0xf3, 0x93, 0x30, 0x8b, 0x49, 0x42, +0xcf, 0xc5, 0x02, 0x12, 0x72, 0x6d, 0x4d, 0xca, 0x46, 0x06, 0x81, 0x9e, 0xfa, 0x77, 0xbf, 0x92, +0xe2, 0x3a, 0x7d, 0xf3, 0xb9, 0x4c, 0x82, 0x16, 0xfd, 0x3b, 0x43, 0xc2, 0x90, 0x30, 0x47, 0xe9, +0x11, 0x0d, 0x91, 0x38, 0x34, 0x50, 0x99, 0x38, 0x05, 0x09, 0xc5, 0x74, 0xe3, 0xf8, 0xd8, 0x64, +0x71, 0x5d, 0x90, 0x89, 0xb8, 0xe2, 0x0b, 0xb8, 0x00, 0xc7, 0x4e, 0x13, 0x57, 0x4b, 0xd8, 0x03, +0xf5, 0x8b, 0xcf, 0x32, 0x21, 0xc1, 0x15, 0x65, 0xb9, 0x4c, 0x5b, 0x39, 0xaf, 0x24, 0x19, 0xa6, +0x06, 0x97, 0xad, 0xf9, 0xc2, 0x8f, 0x81, 0x89, 0xbc, 0x44, 0xdf, 0x2e, 0x7e, 0xd9, 0x16, 0x23, +0xfe, 0xf6, 0x7f, 0x5c, 0xa6, 0xf6, 0x33, 0x04, 0x24, 0x12, 0x96, 0x73, 0xfa, 0xff, 0x71, 0xe5, +0x47, 0xb0, 0x8a, 0xc3, 0xee, 0xd1, 0x30, 0x12, 0xc8, 0xc7, 0x8d, 0x11, 0xb0, 0xdb, 0x26, 0x4f, +0x4d, 0x7a, 0xc7, 0xd5, 0xd0, 0xc9, 0x9c, 0x73, 0xa2, 0xe4, 0xae, 0x35, 0x1c, 0x27, 0x27, 0xd4, +0xfe, 0x42, 0x10, 0x36, 0xe5, 0x70, 0x33, 0x1d, 0xa3, 0x0e, 0xc7, 0xca, 0x23, 0xcc, 0xdf, 0x62, +0x06, 0x97, 0xa9, 0xc9, 0xc2, 0x8f, 0x81, 0xca, 0xbc, 0x44, 0xdf, 0x2e, 0x7e, 0xd9, 0x16, 0x23, +0x16, 0xc4, 0xe8, 0xe4, 0xcf, 0x2d, 0x6a, 0x1c, 0xd7, 0x09, 0x6f, 0x75, 0x64, 0xe0, 0xc3, 0x2f, +0xa8, 0xeb, 0x51, 0xc7, 0x96, 0x6f, 0x1e, 0x02, 0xf2, 0x9b, 0x00, 0x1f, 0x54, 0xc3, 0xb0, 0x68, +0xb7, 0xdc, 0x07, 0xf7, 0xc6, 0xe8, 0xc2, 0xe9, 0x0b, 0x32, 0x1b, 0x4c, 0x98, 0x0f, 0x4a, 0x1b, +0x33, 0xe3, 0x40, 0xba, 0xa2, 0x42, 0x4f, 0x6d, 0x93, 0x9a, 0x17, 0xb4, 0xa6, 0xb3, 0x75, 0x4b, +0x0d, 0x26, 0x62, 0x09, 0x93, 0x00, 0x25, 0x8c, 0x92, 0x4a, 0x54, 0xea, 0xb3, 0xc3, 0xeb, 0x67, +0x3c, 0xa6, 0xeb, 0x34, 0x1d, 0x93, 0xd8, 0xa4, 0xb6, 0x36, 0x45, 0x60, 0x04, 0x98, 0xb0, 0x64, +0x5c, 0xde, 0x74, 0xdf, 0x96, 0xcf, 0x8a, 0xbb, 0x5a, 0xf6, 0x7d, 0xdc, 0x8d, 0x97, 0xfd, 0x64, +0x54, 0xaf, 0xa4, 0x11, 0x5a, 0xb7, 0x4d, 0xce, 0x73, 0x49, 0x03, 0xa7, 0x0d, 0x3e, 0x98, 0x62, +0x2d, 0xb0, 0xe6, 0x56, 0x82, 0x9b, 0x48, 0x21, 0x24, 0x74, 0xad, 0x4c, 0xb9, 0xb0, 0xe1, 0xa3, +0x8a, 0x01, 0x1b, 0x0b, 0x0c, 0xd1, 0x7b, 0x94, 0x87, 0x1f, 0x56, 0x61, 0x0d, 0x49, 0xd2, 0x49, +0xb3, 0x64, 0xfd, 0xe3, 0x16, 0xe2, 0x9e, 0x15, 0x97, 0x34, 0xe9, 0xe7, 0x69, 0x8c, 0x5a, 0xfa, +0x33, 0x7b, 0xbe, 0xb3, 0xc8, 0xee, 0x5e, 0x36, 0x6d, 0xd7, 0xe9, 0x2c, 0x02, 0x26, 0x3b, 0x87, +0x1b, 0x2b, 0x9b, 0x6b, 0x3e, 0xa6, 0x25, 0xac, 0xea, 0xbd, 0xe1, 0x77, 0x9e, 0xb8, 0xa9, 0x27, +0xda, 0x7a, 0x17, 0x80, 0x61, 0x7d, 0xdf, 0xa1, 0x7e, 0xd1, 0x89, 0x01, 0x64, 0xac, 0xb2, 0xb2, +0xe2, 0x53, 0x0e, 0x95, 0x06, 0x05, 0xc9, 0x73, 0x5a, 0xc6, 0x9b, 0x1d, 0x75, 0x75, 0x6f, 0x70, +0x7d, 0x57, 0x3c, 0x6c, 0x99, 0x8f, 0x07, 0x61, 0x2e, 0xb2, 0xa0, 0x80, 0x34, 0xc2, 0x68, 0x64, +0x31, 0xab, 0x1b, 0xaf, 0xa4, 0x3e, 0x10, 0x6b, 0x14, 0xf2, 0xc2, 0x67, 0x61, 0xbf, 0x4d, 0xeb, +0xf2, 0x56, 0x08, 0x98, 0x3d, 0x8a, 0x19, 0xa3, 0xba, 0xc0, 0xed, 0x8b, 0xf8, 0x2d, 0x25, 0x60, +0x0e, 0x27, 0x6b, 0xc6, 0x12, 0xe8, 0x01, 0xbc, 0x44, 0x8d, 0xb6, 0x2f, 0xf2, 0xba, 0x5e, 0xa7, +0xe9, 0x77, 0x58, 0x19, 0xd6, 0x49, 0x95, 0xec, 0x22, 0xe6, 0xcd, 0x2b, 0x33, 0x70, 0x48, 0x23, +0xec, 0x36, 0xdc, 0x78, 0x20, 0xe2, 0xa3, 0xe1, 0xff, 0x97, 0x48, 0x6b, 0x3a, 0xc0, 0xed, 0x14, +0x54, 0x32, 0x11, 0x11, 0xe1, 0x34, 0x9d, 0x0c, 0x95, 0x38, 0xf7, 0x4e, 0x2c, 0xa3, 0x60, 0x4f, +0x7e, 0xa2, 0xd1, 0x1b, 0xb7, 0xb0, 0xc3, 0xdb, 0xf2, 0x8a, 0x41, 0x99, 0x58, 0xca, 0x2d, 0x3f, +0xd5, 0x6c, 0x62, 0xba, 0x9d, 0x68, 0x4a, 0x6f, 0xa7, 0xde, 0xc4, 0xd8, 0xa4, 0xba, 0xf5, 0x20, +0x6d, 0x4a, 0xb9, 0x8c, 0x84, 0x36, 0xe6, 0x41, 0xf0, 0xf8, 0x60, 0x96, 0x8e, 0xf2, 0x96, 0xd4, +0x63, 0x6c, 0xff, 0x5d, 0xd5, 0x4b, 0xda, 0xfc, 0x88, 0x98, 0x83, 0x08, 0x7b, 0x33, 0x89, 0x88, +0x52, 0xa4, 0x74, 0xd6, 0xfe, 0x25, 0x83, 0xba, 0xfb, 0xab, 0x63, 0xe5, 0x50, 0x15, 0x8c, 0xb7, +0x82, 0xeb, 0x73, 0x25, 0x09, 0x57, 0xea, 0xf1, 0x70, 0x8d, 0xd9, 0xd3, 0xb2, 0x6c, 0x29, 0xd3, +0x29, 0xfa, 0x41, 0x61, 0xa9, 0xa3, 0xde, 0x5e, 0x35, 0x0c, 0x32, 0xa5, 0x94, 0xb6, 0x06, 0x08, +0xc7, 0xba, 0xe7, 0x6b, 0xf8, 0x63, 0xbc, 0xed, 0x0e, 0x71, 0xfc, 0x80, 0x97, 0x89, 0x28, 0xae, +0x9f, 0xd1, 0xd1, 0x13, 0x23, 0x95, 0x5e, 0x58, 0x30, 0x53, 0xf9, 0xb4, 0xb0, 0x8a, 0xb9, 0x34, +0x58, 0x52, 0x89, 0x53, 0x5c, 0x24, 0x34, 0xee, 0x26, 0x80, 0x75, 0xa9, 0x33, 0x0c, 0x3b, 0x3a, +0x85, 0x6b, 0x94, 0x4a, 0x47, 0xf8, 0xf2, 0x19, 0x59, 0xe7, 0xa5, 0x28, 0x93, 0x33, 0xbc, 0xa4, +0xa4, 0xa2, 0x22, 0xc0, 0x8d, 0xc2, 0x66, 0x1a, 0x3b, 0x09, 0x3e, 0xf1, 0xc7, 0xb0, 0x43, 0xe1, +0xa7, 0x49, 0xd1, 0xe1, 0x26, 0x59, 0x6b, 0xb6, 0x4c, 0x98, 0x73, 0xb9, 0xbf, 0x19, 0xd5, 0x15, +0x95, 0xf9, 0x50, 0x41, 0x74, 0xed, 0x25, 0x9f, 0xf0, 0x6f, 0x42, 0x1e, 0x30, 0x79, 0xe2, 0x7b, +0x3e, 0x0d, 0xfd, 0x84, 0x3e, 0x79, 0x03, 0x62, 0x68, 0xa3, 0xcc, 0x66, 0x04, 0x0d, 0x13, 0x66, +0x64, 0xf1, 0x0e, 0x02, 0x51, 0x31, 0xe5, 0x32, 0x34, 0x0d, 0x7c, 0xbf, 0xb0, 0xff, 0xda, 0xed, +0xde, 0x48, 0x3b, 0x52, 0xd2, 0x28, 0x06, 0x5f, 0x14, 0x22, 0x34, 0xfc, 0xa4, 0xd4, 0xaa, 0xba, +0x10, 0xe5, 0xad, 0x9a, 0x89, 0xdd, 0x72, 0x5e, 0x12, 0xde, 0x24, 0xce, 0xb1, 0x39, 0x95, 0x7e, +0xf0, 0xe6, 0x40, 0xa9, 0xd2, 0xc0, 0x59, 0xaa, 0xe8, 0x5f, 0xf6, 0xd6, 0x11, 0x6b, 0x2c, 0xd7, +0x50, 0xb4, 0x0d, 0x1c, 0x28, 0x6a, 0x87, 0x7c, 0xe5, 0xca, 0xfc, 0x52, 0xed, 0x26, 0xe9, 0xd9, +0x84, 0x1e, 0x74, 0x89, 0x7a, 0xa0, 0x93, 0xe8, 0x7d, 0xfa, 0x6f, 0xab, 0x25, 0x9a, 0xe5, 0x7a, +0x1a, 0x03, 0x1e, 0x66, 0x55, 0xd2, 0x82, 0xcf, 0x61, 0xb7, 0x3f, 0xa5, 0xf0, 0x38, 0xc4, 0x23, +0xaf, 0xef, 0x4c, 0x36, 0x21, 0x2c, 0x41, 0x90, 0xf0, 0xe4, 0xeb, 0xc6, 0x6f, 0x2d, 0xec, 0x7a, +0xa1, 0xf1, 0x0d, 0x5d, 0x29, 0x7c, 0x7e, 0x82, 0x27, 0x85, 0xc4, 0x8c, 0xe8, 0x04, 0x49, 0xab, +0x8e, 0x65, 0x89, 0x67, 0x5c, 0x3e, 0x7b, 0x53, 0x05, 0x58, 0xa6, 0x86, 0x46, 0x56, 0x8c, 0x68, +0x05, 0xad, 0xef, 0x57, 0x2a, 0x26, 0x85, 0xaf, 0xaa, 0xac, 0x32, 0x31, 0xc4, 0x85, 0x1c, 0xd2, +0x32, 0x7b, 0x8e, 0x1d, 0x68, 0x68, 0xb9, 0xfb, 0xb8, 0x2c, 0x3f, 0xac, 0xa6, 0xfa, 0xce, 0x64, +0xd9, 0x7d, 0xcf, 0xec, 0xa6, 0x37, 0x57, 0x33, 0x39, 0x34, 0x23, 0x2a, 0xb8, 0x9d, 0x5e, 0xed, +0x21, 0xbe, 0xe6, 0xf3, 0x44, 0xbb, 0xcc, 0x76, 0xc6, 0x70, 0x21, 0x73, 0xad, 0x5b, 0xe6, 0x9a, +0xe8, 0x3e, 0x1e, 0x0b, 0x5e, 0x99, 0xad, 0xac, 0xd4, 0x0f, 0x12, 0xe0, 0x60, 0xcf, 0x6d, 0x32, +0xb5, 0xc1, 0xc7, 0x1d, 0x17, 0xe9, 0xf6, 0xac, 0x07, 0x58, 0xd1, 0x1b, 0x66, 0xa4, 0xdb, 0x12, +0x97, 0xa7, 0x6a, 0xf1, 0xea, 0x9a, 0x3b, 0xcd, 0xd3, 0x5a, 0xa1, 0x59, 0xfb, 0x2f, 0x07, 0x5f, +0x01, 0x2d, 0x1e, 0x41, 0x0b, 0x0f, 0xf5, 0x45, 0x67, 0x6e, 0xe4, 0xa4, 0xc2, 0x4b, 0xf6, 0xe1, +0x84, 0x08, 0x98, 0x5d, 0x39, 0x5f, 0xa9, 0x6a, 0xc6, 0xeb, 0x30, 0x30, 0x15, 0x1a, 0x00, 0x06, +0x29, 0x77, 0x88, 0xfc, 0xd1, 0xcb, 0x4d, 0x56, 0xde, 0xb3, 0x3a, 0x50, 0x73, 0xa6, 0x8f, 0xe7, +0x84, 0x49, 0x76, 0xd1, 0x78, 0xa0, 0x75, 0x2e, 0xb8, 0x8b, 0x35, 0x52, 0x5a, 0x9d, 0x7a, 0x69, +0x16, 0x76, 0x96, 0x3a, 0x96, 0x5d, 0x19, 0x5e, 0x59, 0x7a, 0xcc, 0xfb, 0x23, 0x68, 0xe5, 0x16, +0xb1, 0x3a, 0x0e, 0xb3, 0x22, 0x47, 0x8d, 0xaf, 0x8a, 0x39, 0xb2, 0x68, 0x05, 0xd2, 0xf3, 0x3a, +0xa0, 0x48, 0x77, 0xcc, 0xa2, 0x8f, 0x58, 0x7d, 0x1a, 0xc1, 0xb9, 0x9a, 0xe7, 0xe3, 0xc3, 0x4f, +0x7c, 0x4f, 0x11, 0x60, 0x3a, 0x83, 0xd2, 0xa1, 0x3d, 0xfd, 0x15, 0x29, 0x45, 0xfd, 0xf1, 0xdf, +0xe2, 0x20, 0x59, 0xcd, 0x66, 0x61, 0xdd, 0xae, 0x81, 0x5b, 0x63, 0x43, 0xe7, 0x5a, 0x2c, 0x16, +0xda, 0x9c, 0xbb, 0x62, 0xb1, 0xdd, 0x0c, 0x67, 0x09, 0xe5, 0xcf, 0x4e, 0x84, 0xfb, 0xf8, 0x55, +0x10, 0xe5, 0x1d, 0x71, 0x1f, 0xf7, 0x6c, 0x5b, 0x0f, 0x24, 0xaa, 0xba, 0x4e, 0x43, 0x6e, 0xce, +0xed, 0xaf, 0x1b, 0xa0, 0xd7, 0xcf, 0x02, 0xea, 0xd5, 0xa7, 0xeb, 0xe3, 0x22, 0x4c, 0xfa, 0x6d, +0x82, 0xca, 0x8d, 0x9a, 0xd9, 0x17, 0xa1, 0xde, 0xdf, 0x95, 0x63, 0xae, 0xb1, 0xfd, 0xd4, 0x86, +0xc0, 0xe7, 0x8d, 0x7d, 0xab, 0x17, 0x44, 0xd3, 0x62, 0x78, 0x79, 0xa2, 0x42, 0x29, 0x53, 0x50, +0x18, 0x37, 0x87, 0x2d, 0x1b, 0x32, 0x41, 0x28, 0x34, 0x66, 0x6b, 0xa7, 0x89, 0x50, 0xee, 0x1c, +0x9b, 0x94, 0xc2, 0xd5, 0xbe, 0x62, 0x27, 0x86, 0xc0, 0x26, 0x47, 0xb2, 0x6a, 0x30, 0xaa, 0xdb, +0xdc, 0xa6, 0x54, 0x63, 0x77, 0x73, 0x4f, 0xf7, 0x64, 0x87, 0x97, 0xc5, 0xd4, 0xff, 0x4b, 0x50, +0xe3, 0xbb, 0xc3, 0x89, 0x7e, 0xcc, 0x8d, 0x04, 0x25, 0x77, 0xe4, 0x34, 0x76, 0x9a, 0x11, 0x4c, +0x38, 0xbf, 0x4a, 0x1e, 0x8f, 0xf7, 0xb0, 0x74, 0x1b, 0xde, 0x91, 0x48, 0x22, 0x17, 0xc8, 0xda, +0xcf, 0x66, 0x70, 0x18, 0xb0, 0x7c, 0xe4, 0x45, 0xbf, 0x65, 0x1b, 0xb1, 0xcd, 0x69, 0x18, 0xb4, +0x5d, 0x4c, 0xb9, 0x17, 0x3a, 0xf1, 0x4f, 0xe7, 0x50, 0x9d, 0xe8, 0xd8, 0x8b, 0xce, 0xa9, 0xf8, +0xe1, 0x19, 0x39, 0x02, 0xdc, 0x7e, 0xc5, 0x68, 0xd5, 0xef, 0x53, 0x23, 0x85, 0x60, 0x59, 0x78, +0x18, 0xf0, 0x8c, 0x86, 0x55, 0xb1, 0x90, 0xe5, 0x6d, 0xdb, 0xd1, 0xe0, 0xfb, 0xca, 0x15, 0x17, +0x54, 0x1b, 0xa3, 0x81, 0x49, 0x2a, 0xb4, 0x2c, 0xba, 0x06, 0x15, 0xe7, 0x7d, 0x05, 0xab, 0x51, +0xc2, 0x27, 0x44, 0x94, 0x44, 0x53, 0xb9, 0xb1, 0x32, 0x1b, 0xaf, 0xe7, 0xe8, 0x5b, 0x7f, 0x39, +0xed, 0x62, 0x4f, 0xb2, 0xeb, 0x8e, 0x23, 0xe6, 0x5e, 0xf1, 0x0f, 0x0d, 0xc5, 0xaf, 0x0a, 0x42, +0x27, 0x03, 0x1a, 0x3d, 0xf4, 0xe7, 0x1e, 0xdf, 0x7c, 0x72, 0x8d, 0x21, 0x21, 0xfb, 0x8d, 0xe5, +0x92, 0x77, 0x5b, 0xd2, 0xc0, 0xee, 0xbc, 0xde, 0x5b, 0x10, 0x31, 0xab, 0x4c, 0xab, 0xc5, 0xd4, +0x1c, 0xa6, 0x52, 0x28, 0x5c, 0x10, 0xdc, 0xe7, 0x84, 0xac, 0x86, 0xe5, 0x85, 0xec, 0xcc, 0x3b, +0xe9, 0xc3, 0xc9, 0x73, 0x1b, 0x4c, 0xc9, 0x62, 0x73, 0x56, 0xd4, 0xc0, 0x6b, 0xc2, 0x0b, 0x9e, +0xd6, 0xe8, 0x4b, 0xed, 0x5f, 0x92, 0xff, 0x2a, 0x1d, 0x08, 0xa8, 0xc6, 0x6e, 0xa6, 0xd1, 0x37, +0xa1, 0xe4, 0x50, 0x69, 0xcb, 0xbe, 0xa4, 0x1c, 0xda, 0x51, 0x0f, 0x30, 0xca, 0xc4, 0x69, 0xdd, +0xbc, 0x00, 0xec, 0xa9, 0xa0, 0xd2, 0xe2, 0x77, 0x70, 0xbd, 0x45, 0xa4, 0x11, 0x00, 0x27, 0x41, +0xf9, 0x06, 0x16, 0x22, 0x9e, 0x7e, 0x43, 0x84, 0xcd, 0xc2, 0xd7, 0xfe, 0xc8, 0xe4, 0xa8, 0x80, +0x17, 0x8d, 0x83, 0x0a, 0xc8, 0xd6, 0xf9, 0xfd, 0xd2, 0x29, 0x47, 0x8b, 0x18, 0xc9, 0xbe, 0x1d, +0x1a, 0x20, 0x24, 0x5f, 0x69, 0xb6, 0x75, 0xc3, 0x81, 0xc7, 0x64, 0x87, 0xa9, 0x83, 0x9e, 0x40, +0x1a, 0x6d, 0x05, 0x55, 0xcb, 0x99, 0xab, 0x76, 0x8b, 0x80, 0x77, 0x6a, 0x70, 0x83, 0x7b, 0x62, +0xe1, 0x59, 0x50, 0x19, 0xfd, 0xc2, 0x82, 0xc2, 0x82, 0x54, 0xe4, 0x70, 0x52, 0x17, 0x03, 0xdb, +0xc9, 0x41, 0x79, 0xf2, 0xaf, 0xce, 0x30, 0x4f, 0xb0, 0x06, 0x64, 0x57, 0x3c, 0x3c, 0x37, 0xc0, +0xfa, 0xd4, 0x11, 0x68, 0xa5, 0xd6, 0x98, 0x7b, 0xf6, 0x70, 0xf9, 0xe5, 0x61, 0xb8, 0xc8, 0xef, +0x17, 0x2b, 0x5c, 0xc1, 0x3e, 0x6e, 0xe9, 0x85, 0x11, 0xc8, 0xfb, 0xb1, 0xa8, 0xef, 0xf7, 0x32, +0x03, 0x8e, 0x22, 0x23, 0x64, 0xa7, 0x7e, 0xaf, 0x56, 0xc8, 0x4a, 0x62, 0x51, 0x21, 0x74, 0x23, +0x2d, 0x80, 0x29, 0x3b, 0x4c, 0xe8, 0x0e, 0x7d, 0xde, 0x0c, 0xdf, 0x83, 0x91, 0xb7, 0xe9, 0xe0, +0x0a, 0x07, 0xbe, 0x63, 0x5f, 0xe6, 0x54, 0xff, 0xd7, 0x3e, 0x06, 0x7d, 0x8f, 0x3f, 0x0a, 0x7f, +0xa6, 0x2c, 0x6d, 0x19, 0xe0, 0xd7, 0x6b, 0x63, 0x4b, 0x4a, 0x0a, 0xa3, 0x7c, 0xe0, 0x82, 0x7c, +0xed, 0xeb, 0x49, 0x23, 0x88, 0x51, 0x9a, 0x2d, 0xdf, 0x47, 0x5e, 0xb6, 0x76, 0xdc, 0x6b, 0x2b, +0x7a, 0x00, 0x3f, 0x90, 0x48, 0x43, 0x5e, 0x51, 0x0d, 0xc3, 0xef, 0x2f, 0x6d, 0xbc, 0x0c, 0x8a, +0x36, 0x00, 0x38, 0x0c, 0x15, 0x38, 0x80, 0x74, 0x00, 0x5e, 0x9a, 0x21, 0xb5, 0xa0, 0xc0, 0xd1, +0xd4, 0xad, 0xb4, 0x35, 0x5c, 0xc5, 0x80, 0x64, 0xd9, 0xff, 0x69, 0x09, 0x74, 0xcf, 0x9f, 0x29, +0x31, 0x51, 0x0c, 0x44, 0x2b, 0x07, 0xe2, 0xa2, 0x47, 0x04, 0x8b, 0xc1, 0x9e, 0xe6, 0x50, 0xab, +0xe8, 0x87, 0x90, 0x01, 0xea, 0xe3, 0x75, 0xb5, 0x4d, 0xf1, 0x76, 0x39, 0xd9, 0x9e, 0x8e, 0x36, +0xa5, 0x20, 0x9e, 0xed, 0xb8, 0x2b, 0x8a, 0x32, 0x56, 0x74, 0x32, 0x31, 0xd1, 0x58, 0xb9, 0xa8, +0x9d, 0xaf, 0xba, 0x81, 0x8d, 0x51, 0xa6, 0xa4, 0x23, 0xee, 0xd2, 0x32, 0x88, 0xb1, 0x24, 0x32, +0xa6, 0xb0, 0x57, 0x0f, 0xba, 0x86, 0xf2, 0x14, 0x61, 0x08, 0x7e, 0x30, 0x47, 0xeb, 0xa3, 0x6f, +0x2e, 0x00, 0x97, 0xbc, 0x29, 0x87, 0xc8, 0x82, 0x03, 0x19, 0x29, 0x72, 0x4d, 0x19, 0x79, 0xa6, +0xec, 0x2b, 0xf3, 0xff, 0xbe, 0x0c, 0x9f, 0x59, 0x62, 0x5b, 0xcc, 0x43, 0xe7, 0x23, 0x3e, 0x9e, +0x7b, 0x29, 0xbd, 0x19, 0x09, 0x20, 0x17, 0x2d, 0x2c, 0x18, 0x35, 0x3c, 0x38, 0x69, 0xc3, 0x6a, +0x3f, 0x00, 0xb3, 0x39, 0x47, 0xdf, 0x40, 0xdd, 0x1d, 0xc0, 0x6d, 0xf4, 0x7a, 0x83, 0xc4, 0xdf, +0x2c, 0x15, 0x58, 0xee, 0x1a, 0x9e, 0x85, 0x45, 0xba, 0xba, 0xb2, 0x8a, 0x8b, 0x0e, 0x1c, 0x99, +0x08, 0x8a, 0x92, 0x4d, 0xe1, 0x80, 0xd0, 0xd6, 0x48, 0xd7, 0x70, 0xe5, 0xbb, 0x70, 0x90, 0x70, +0xff, 0x47, 0x24, 0xc5, 0x2b, 0x00, 0x7e, 0xe7, 0x48, 0x61, 0xe1, 0x52, 0xe8, 0xa3, 0xed, 0x08, +0x9e, 0x4d, 0xcb, 0x3e, 0xa4, 0xf1, 0x3e, 0x1d, 0xf6, 0xfc, 0x3e, 0x5a, 0xbf, 0x9a, 0x9c, 0x9b, +0xcb, 0x2a, 0x51, 0xc4, 0x96, 0x75, 0xa3, 0x56, 0xe6, 0x97, 0xae, 0x08, 0x91, 0xf2, 0x40, 0x9c, +0x13, 0x0b, 0x41, 0xce, 0xa0, 0x34, 0x7a, 0xb2, 0xe2, 0x45, 0xb1, 0x2c, 0x5a, 0x01, 0x20, 0x34, +0xbd, 0x9e, 0x7b, 0x81, 0xd4, 0x82, 0xa8, 0x10, 0x01, 0xb9, 0xad, 0x14, 0x05, 0x05, 0x92, 0x15, +0x08, 0x62, 0xd7, 0xfd, 0x16, 0x20, 0x88, 0x9c, 0xf9, 0x2d, 0x3b, 0x41, 0xd9, 0xcd, 0x46, 0x50, +0x49, 0xc3, 0x5a, 0x6f, 0x7c, 0x14, 0xc8, 0x96, 0x8d, 0x5a, 0x63, 0xc7, 0x24, 0x4a, 0x2c, 0xf6, +0xb5, 0x29, 0x17, 0xa1, 0xa1, 0xab, 0x14, 0x3f, 0x0f, 0x50, 0x35, 0x76, 0xd2, 0x21, 0x39, 0x86, +0x38, 0x7f, 0xbf, 0xff, 0x5c, 0xcd, 0x75, 0xc2, 0xb4, 0x41, 0xec, 0x81, 0xd9, 0x17, 0x0c, 0x56, +0x68, 0x27, 0xe0, 0x23, 0xdb, 0x92, 0x0d, 0x96, 0xc5, 0x46, 0xe7, 0x78, 0xd5, 0x18, 0xa0, 0xe6, +0x3f, 0x7d, 0x39, 0x55, 0xdd, 0xe6, 0xae, 0x57, 0x69, 0x60, 0xa6, 0xdd, 0xc6, 0x29, 0xa5, 0x65, +0x0e, 0xf4, 0x1e, 0x17, 0xb6, 0xf5, 0x01, 0xf2, 0x77, 0x8a, 0x64, 0x22, 0x65, 0x7c, 0xcf, 0xe1, +0xca, 0x3d, 0x63, 0xbe, 0xb0, 0x0e, 0xdb, 0x46, 0xbb, 0x5b, 0x05, 0xee, 0x6d, 0xec, 0xfc, 0x2e, +0xe7, 0x9c, 0xba, 0xb3, 0xe5, 0x8a, 0xef, 0xfd, 0x7b, 0xc2, 0x7c, 0x5e, 0x5b, 0xd5, 0xe6, 0x60, +0x50, 0x33, 0xa8, 0x2a, 0xca, 0x08, 0x17, 0x5e, 0x72, 0xc8, 0x20, 0x0a, 0xe6, 0x8f, 0x44, 0xef, +0x3f, 0xec, 0x94, 0xce, 0x3b, 0x81, 0x71, 0x49, 0xc8, 0xb2, 0x05, 0xa0, 0x45, 0x56, 0x41, 0x68, +0x5a, 0x0d, 0x28, 0xef, 0x90, 0xc1, 0x53, 0x32, 0x67, 0x95, 0x22, 0x53, 0x00, 0x96, 0x4d, 0x5e, +0x48, 0x83, 0x06, 0xf4, 0xb6, 0xc9, 0x8a, 0x73, 0x64, 0x1e, 0x88, 0x06, 0xe0, 0x1c, 0x8f, 0x57, +0x0e, 0x5a, 0xdc, 0x5a, 0x7d, 0xf9, 0xd3, 0xcf, 0x4a, 0xa3, 0x71, 0x0c, 0x3e, 0xa2, 0xf2, 0x96, +0x88, 0x21, 0xdb, 0x68, 0x5b, 0xf2, 0x73, 0xd1, 0xba, 0x3f, 0x1c, 0x1e, 0x22, 0x36, 0x1c, 0x0e, +0x5a, 0x4d, 0xcc, 0xff, 0xd3, 0x53, 0xb4, 0x6e, 0x46, 0xc2, 0x0c, 0x16, 0xe3, 0xbe, 0x55, 0xf6, +0x35, 0x0a, 0x70, 0xb3, 0x61, 0x5a, 0x5a, 0xeb, 0xd4, 0xee, 0xc2, 0x5d, 0xf0, 0x00, 0x81, 0xde, +0x83, 0xe5, 0x27, 0xd9, 0x86, 0xa3, 0xa7, 0xbe, 0x2e, 0x45, 0xf0, 0xa3, 0x9e, 0x75, 0xc4, 0xb0, +0x95, 0x7d, 0x63, 0xc2, 0x7d, 0xcb, 0xcf, 0xe9, 0xd9, 0x8f, 0x82, 0x1f, 0x7c, 0xf9, 0xc2, 0x6f, +0x28, 0x0a, 0xb7, 0x99, 0x98, 0x9c, 0xe5, 0x00, 0x67, 0x56, 0xe5, 0x7f, 0xcb, 0xbc, 0x67, 0x60, +0x73, 0x6b, 0x3e, 0x07, 0x8f, 0xb8, 0x78, 0x67, 0x87, 0x5e, 0xf3, 0x8e, 0x28, 0xd3, 0x6a, 0xc8, +0x70, 0x08, 0xaf, 0x44, 0xf7, 0x19, 0xe6, 0xbd, 0xf8, 0x51, 0x45, 0xe7, 0x69, 0xed, 0x68, 0xde, +0xda, 0xd9, 0xaa, 0x45, 0x6d, 0xac, 0x7d, 0x5d, 0xc6, 0xfd, 0xb5, 0x09, 0x91, 0x74, 0xea, 0x92, +0x26, 0x99, 0x7e, 0xe4, 0xb4, 0x87, 0x06, 0xfd, 0x00, 0x8b, 0x30, 0xc3, 0xbe, 0x44, 0xe7, 0xf2, +0xf5, 0x75, 0x49, 0x22, 0x79, 0x0d, 0x8a, 0xcd, 0x6a, 0xb1, 0xc6, 0xcc, 0x23, 0x6f, 0x82, 0x4a, +0x58, 0x16, 0xbc, 0xfc, 0x0c, 0xcc, 0x7a, 0x23, 0xea, 0x38, 0xb4, 0x4d, 0x70, 0x43, 0x53, 0x15, +0x7a, 0x5f, 0x5b, 0x11, 0xc3, 0xaf, 0xb3, 0x58, 0x8b, 0x08, 0x5c, 0x05, 0xa5, 0x3c, 0x9a, 0x56, +0x3e, 0x0f, 0xd8, 0xe9, 0x77, 0xf4, 0x68, 0xf8, 0x6b, 0xdf, 0xff, 0x25, 0xd9, 0xcc, 0xfe, 0xc6, +0x41, 0xf6, 0xd3, 0x88, 0x0e, 0x59, 0x87, 0x7d, 0x6c, 0x0d, 0xc1, 0x71, 0xc4, 0x12, 0x6d, 0x4d, +0xc6, 0x90, 0xb8, 0x13, 0xaf, 0x0d, 0xe0, 0xc6, 0x2a, 0x90, 0x35, 0x8e, 0xcd, 0x33, 0xb7, 0x1f, +0xcb, 0x99, 0x53, 0xef, 0x17, 0xec, 0x0a, 0xfb, 0x36, 0x05, 0x54, 0xe3, 0x2e, 0x56, 0xc8, 0x58, +0x0b, 0x06, 0xe5, 0xa8, 0xf5, 0x59, 0xb1, 0x36, 0xff, 0x50, 0x8d, 0x29, 0x96, 0x05, 0xcb, 0xbd, +0x3b, 0xfb, 0x7a, 0x30, 0x47, 0x0c, 0xb8, 0xdf, 0xe4, 0x21, 0x7a, 0xe4, 0x6b, 0x8b, 0xde, 0x3f, +0x7f, 0x45, 0xac, 0x79, 0xab, 0x3b, 0x4c, 0xfe, 0x58, 0xb5, 0x37, 0x4d, 0x3b, 0xb9, 0x8f, 0xcb, +0xc5, 0xd8, 0x12, 0xb8, 0x98, 0xe1, 0x61, 0xbb, 0x02, 0xfe, 0x54, 0xac, 0x4f, 0x9d, 0xef, 0x73, +0xbb, 0x6b, 0x79, 0x19, 0xc6, 0x11, 0x3a, 0xb7, 0x07, 0x7c, 0x35, 0xf7, 0x04, 0x33, 0x7f, 0x5f, +0x76, 0xc3, 0xf3, 0xdb, 0x26, 0xd0, 0xcb, 0x21, 0x0d, 0xe3, 0xc9, 0x32, 0xc7, 0x02, 0x26, 0x2c, +0x6f, 0xfd, 0xc7, 0x32, 0x2b, 0x58, 0x08, 0xdc, 0x0c, 0x8b, 0x5c, 0x13, 0xf7, 0x19, 0x1a, 0x78, +0x26, 0x1f, 0x84, 0x45, 0xf8, 0x7f, 0xb6, 0x97, 0x74, 0xff, 0xa2, 0x12, 0x01, 0x94, 0x7b, 0xab, +0x65, 0xe6, 0x66, 0x3b, 0x3d, 0x0e, 0x3a, 0x86, 0xbe, 0x02, 0x36, 0x55, 0xe7, 0x25, 0xb7, 0xf5, +0x07, 0xed, 0x94, 0xfb, 0xed, 0xfb, 0xaf, 0xb0, 0xa2, 0x82, 0xc0, 0xcb, 0xe9, 0x8d, 0xcd, 0x1d, +0x54, 0x40, 0xea, 0xac, 0xc9, 0x14, 0x54, 0x65, 0xf9, 0x66, 0xf2, 0x29, 0x81, 0x43, 0xc7, 0x83, +0x1e, 0xd4, 0x51, 0x3b, 0x47, 0xaf, 0x84, 0xd4, 0xc5, 0xd1, 0x93, 0x05, 0x1e, 0x87, 0x20, 0x26, +0xd5, 0xea, 0x4d, 0x06, 0xbc, 0x4c, 0xa3, 0x11, 0x99, 0x90, 0xec, 0x86, 0xb9, 0xae, 0xb0, 0x51, +0xe9, 0x6d, 0xf5, 0xce, 0x09, 0x26, 0x6f, 0x80, 0xba, 0x1c, 0xe3, 0xee, 0x43, 0x67, 0xf5, 0xab, +0x6a, 0x45, 0xf6, 0x35, 0xf2, 0x91, 0x2b, 0xc0, 0x04, 0x03, 0xad, 0x43, 0xa0, 0x5b, 0xfc, 0x63, +0x1d, 0x73, 0xf4, 0x00, 0xf2, 0xe6, 0xa7, 0x64, 0xd9, 0x33, 0xf9, 0xab, 0x0c, 0xa2, 0x53, 0x20, +0x3d, 0xfb, 0x78, 0x0d, 0x3a, 0xd2, 0xd0, 0xe7, 0x64, 0xb2, 0x5d, 0xd3, 0x1a, 0x48, 0xab, 0x83, +0xeb, 0xba, 0x1e, 0x19, 0x75, 0x99, 0x33, 0x75, 0x34, 0xa7, 0xba, 0x53, 0xd3, 0xfc, 0xcc, 0xdc, +0x4a, 0xd8, 0xa8, 0x86, 0x67, 0xfe, 0x5a, 0xb6, 0xcf, 0x78, 0xa8, 0x4a, 0x0c, 0x42, 0x41, 0x35, +0x20, 0x0e, 0xe4, 0xd3, 0x65, 0xb6, 0xca, 0xa7, 0xcd, 0xe4, 0x51, 0xaa, 0x58, 0x10, 0x5e, 0x95, +0x74, 0x5a, 0x3c, 0xa1, 0xb8, 0x19, 0x12, 0x74, 0x3c, 0x42, 0xd5, 0x7b, 0x72, 0x7e, 0x64, 0x9a, +0x1d, 0x84, 0xff, 0xbf, 0xe8, 0x10, 0xf5, 0x3d, 0xbf, 0xf1, 0x63, 0x8e, 0x1e, 0xc2, 0x1c, 0x39, +0x46, 0x3d, 0xae, 0xb6, 0x3a, 0x63, 0xd9, 0xe2, 0xed, 0x16, 0xa1, 0x09, 0xc4, 0x1e, 0x1c, 0x5b, +0x58, 0x42, 0x61, 0x13, 0x7d, 0xcf, 0xbb, 0xfa, 0x48, 0xc6, 0xf2, 0x05, 0x6a, 0x78, 0x50, 0xe2, +0x67, 0x5f, 0x9f, 0x7e, 0xeb, 0x32, 0x02, 0x61, 0xe7, 0x09, 0xd9, 0x9b, 0x5b, 0xb7, 0xbb, 0x65, +0x78, 0x12, 0xc0, 0xc2, 0x45, 0x28, 0xa7, 0x39, 0x6b, 0xcd, 0xb5, 0xa8, 0x6a, 0x71, 0x1c, 0x3a, +0x53, 0xa8, 0x53, 0x9a, 0xf3, 0x65, 0xaf, 0xa2, 0x0f, 0x58, 0xdd, 0xcd, 0xe2, 0xa9, 0xba, 0xad, +0xa1, 0x76, 0x46, 0xf7, 0xf5, 0x3e, 0xec, 0xda, 0x18, 0xb5, 0x09, 0xaf, 0xd1, 0x06, 0xd6, 0xca, +0xb6, 0xfa, 0xc6, 0xdb, 0x84, 0xdf, 0xe9, 0xfd, 0x7d, 0xf4, 0xe2, 0xa9, 0x30, 0xf2, 0xac, 0x80, +0xbe, 0xd1, 0x1f, 0xed, 0xcc, 0xa3, 0xf8, 0x7b, 0x0d, 0x24, 0x53, 0x19, 0xdc, 0x20, 0x7f, 0x3a, +0x97, 0x4d, 0x08, 0x4e, 0x77, 0x99, 0x9a, 0xf3, 0x9d, 0x9b, 0x3a, 0x64, 0xf2, 0xdb, 0xa3, 0xbf, +0x09, 0x2c, 0xe2, 0x68, 0x62, 0x0a, 0x5d, 0x3b, 0x24, 0xf5, 0xa8, 0x73, 0xbb, 0x53, 0xd7, 0x59, +0xb3, 0xca, 0x69, 0x0f, 0xed, 0x1f, 0xc8, 0x9e, 0x59, 0xb6, 0x94, 0xd1, 0x1e, 0x62, 0x7e, 0xdc, +0x20, 0xb6, 0xb9, 0x9c, 0x5f, 0x99, 0x99, 0x7e, 0x5b, 0x40, 0xec, 0x67, 0xd3, 0x72, 0x59, 0xf7, +0xa6, 0x10, 0x56, 0x37, 0x10, 0xf9, 0x76, 0x4d, 0xff, 0x6b, 0xef, 0xd0, 0x99, 0x96, 0x04, 0x28, +0x87, 0xc7, 0xd8, 0xba, 0xc0, 0x48, 0x96, 0xf8, 0xa1, 0xb0, 0x87, 0xb2, 0x1a, 0xa2, 0xe9, 0xfa, +0x61, 0x12, 0xd3, 0xed, 0xd0, 0xa2, 0x3f, 0x21, 0xa6, 0xa3, 0x44, 0x5b, 0x00, 0xc5, 0xd4, 0x35, +0x84, 0x48, 0xcd, 0x81, 0x23, 0x58, 0x82, 0xff, 0xc6, 0x3d, 0xc2, 0xa5, 0xdd, 0x21, 0x3f, 0xbe, +0xbf, 0x7d, 0x42, 0xd0, 0x60, 0xda, 0xde, 0xae, 0xa9, 0x37, 0xbc, 0xfb, 0xe9, 0xfb, 0xf3, 0xbc, +0xbe, 0x63, 0xf2, 0x73, 0x4d, 0x9a, 0xce, 0x6f, 0x3c, 0x33, 0xf5, 0x97, 0x06, 0x47, 0x55, 0xa9, +0x78, 0x5b, 0x44, 0xd0, 0x9e, 0x74, 0x29, 0x17, 0x45, 0x1a, 0xaf, 0x3f, 0x17, 0x60, 0x81, 0x3b, +0x6b, 0x0f, 0x11, 0xef, 0xcc, 0x75, 0x41, 0xcb, 0xe2, 0x47, 0xb4, 0xde, 0x85, 0xce, 0xaf, 0x8a, +0x93, 0x98, 0xcf, 0x33, 0xa9, 0x74, 0x93, 0x12, 0xce, 0x63, 0x14, 0x96, 0x9f, 0xf9, 0x37, 0x9a, +0x82, 0x2d, 0x23, 0x17, 0x53, 0xe1, 0x09, 0xc8, 0xe2, 0xe4, 0xc0, 0x60, 0x67, 0x2e, 0x1e, 0xe7, +0x65, 0xa8, 0x48, 0x95, 0xc0, 0xad, 0x1b, 0x6b, 0x58, 0xa0, 0xfd, 0x05, 0xac, 0xd2, 0x87, 0x77, +0x2a, 0x65, 0xa5, 0x71, 0x8e, 0xc4, 0x0f, 0x74, 0x58, 0xa4, 0xf9, 0x15, 0x56, 0x24, 0x1c, 0x08, +0x19, 0x23, 0xe7, 0xe5, 0x86, 0x7a, 0x91, 0xda, 0xd2, 0x04, 0xbc, 0x9c, 0x55, 0xc9, 0x86, 0x98, +0x50, 0x2d, 0xba, 0x1d, 0xdf, 0x5e, 0x33, 0x47, 0x58, 0x88, 0x41, 0x9f, 0x15, 0xb8, 0xfe, 0x87, +0xf1, 0x5f, 0x0d, 0x57, 0x4f, 0x9b, 0x4a, 0xe4, 0xb9, 0x2d, 0x05, 0x79, 0x9d, 0x7c, 0x58, 0x81, +0x2b, 0x5d, 0xb1, 0xca, 0x15, 0x69, 0x5a, 0x14, 0xc4, 0x62, 0xbc, 0x97, 0x7e, 0xb5, 0x14, 0x48, +0x3e, 0xf0, 0xff, 0xe8, 0xab, 0x65, 0xba, 0x38, 0x49, 0x64, 0x3d, 0x64, 0x09, 0x12, 0xd8, 0x30, +0x99, 0x88, 0x15, 0x5c, 0x4c, 0x9e, 0x4b, 0x67, 0x6d, 0x81, 0x3b, 0x49, 0xac, 0xb6, 0x38, 0xb3, +0xfc, 0x4d, 0x33, 0x2c, 0x98, 0xb5, 0x9e, 0xe0, 0xee, 0xe5, 0xd7, 0xbc, 0x5a, 0x69, 0x6b, 0xe2, +0xd8, 0x4c, 0x42, 0xd7, 0xe9, 0x6f, 0x56, 0x37, 0x9c, 0x7b, 0xe8, 0xd2, 0x7a, 0x87, 0xf2, 0x78, +0x2f, 0x7b, 0x70, 0x65, 0x6d, 0x55, 0x00, 0xed, 0x91, 0xc6, 0x41, 0xf2, 0x83, 0xbe, 0xe6, 0x14, +0x64, 0xb0, 0x20, 0xdb, 0xb3, 0x1b, 0x2b, 0x68, 0xcf, 0x6b, 0x65, 0xf8, 0x4d, 0xbb, 0x95, 0x5f, +0x00, 0x06, 0xd8, 0xd6, 0x84, 0x07, 0x48, 0x02, 0xb6, 0x0b, 0xf5, 0x13, 0x7b, 0x98, 0xc0, 0xc0, +0x3f, 0x9c, 0x5b, 0x99, 0xcb, 0x3f, 0x9f, 0x6b, 0x7d, 0xfc, 0x32, 0x23, 0xb7, 0x68, 0x7f, 0x8f, +0x59, 0x90, 0xbc, 0xce, 0x18, 0x4d, 0x0f, 0x67, 0x56, 0x1e, 0x8e, 0xff, 0xe5, 0x58, 0x07, 0xc9, +0x43, 0x98, 0xaf, 0xb4, 0x55, 0xbe, 0x42, 0xf2, 0xf7, 0xdf, 0xf2, 0x7c, 0xce, 0x6b, 0xe5, 0xe2, +0x2d, 0x6a, 0xff, 0xb0, 0xb7, 0x13, 0x46, 0xc0, 0x71, 0x8f, 0x7c, 0x20, 0x71, 0x6e, 0x37, 0x3d, +0x80, 0xc0, 0x03, 0x15, 0x97, 0xc9, 0xcb, 0x27, 0x2d, 0x33, 0x62, 0x7a, 0xa5, 0x6b, 0xb9, 0xff, +0x52, 0x32, 0xb0, 0xea, 0x9f, 0x57, 0x53, 0xfb, 0xe6, 0xee, 0x0b, 0x6c, 0x50, 0xaf, 0x52, 0xc1, +0x68, 0xd3, 0xd1, 0xea, 0x2e, 0xe9, 0x24, 0xca, 0x88, 0x54, 0x36, 0x02, 0xd5, 0x3a, 0x8d, 0xdf, +0x3b, 0xa0, 0xfc, 0x07, 0xef, 0xd8, 0x2e, 0x32, 0x1d, 0xae, 0x80, 0x45, 0x8f, 0xa1, 0x3d, 0x2f, +0x13, 0xaf, 0x49, 0x42, 0xa8, 0xc9, 0xd6, 0xec, 0x6b, 0x6a, 0xfb, 0x33, 0xa0, 0xc3, 0x3f, 0xed, +0x9a, 0x69, 0x67, 0x3a, 0xc0, 0x89, 0x28, 0x40, 0x23, 0xda, 0xe5, 0x01, 0x18, 0x56, 0xf1, 0xb7, +0x05, 0x00, 0x38, 0x32, 0x1d, 0x70, 0xc8, 0x36, 0x21, 0xe7, 0x3a, 0xf4, 0x9d, 0xe5, 0xe3, 0x55, +0x31, 0xaa, 0x80, 0x84, 0x82, 0x40, 0xc1, 0x31, 0x60, 0x50, 0x7c, 0x4b, 0x6a, 0xeb, 0x4d, 0xbd, +0x2d, 0x59, 0x3a, 0xff, 0x2f, 0x3e, 0x5a, 0x7a, 0x2a, 0x2a, 0xa9, 0xba, 0xb7, 0x3a, 0x8b, 0x9f, +0x90, 0xa5, 0x06, 0x36, 0xc5, 0x31, 0x79, 0x75, 0x50, 0xf9, 0x32, 0xb5, 0x76, 0x55, 0xc0, 0xe5, +0xf1, 0x19, 0xf1, 0xdf, 0xd9, 0x4c, 0x23, 0x24, 0x71, 0xb3, 0x5b, 0xcf, 0xc4, 0x28, 0x3e, 0x0f, +0x79, 0x3f, 0xd2, 0xcc, 0x9f, 0x7e, 0x34, 0x71, 0xc3, 0xb1, 0xbd, 0x99, 0x5a, 0x5c, 0x6a, 0xbe, +0x00, 0xbd, 0x1c, 0xd1, 0x81, 0x4d, 0x1e, 0xff, 0x8e, 0xb5, 0x85, 0xb9, 0xf6, 0xa2, 0xf3, 0xf0, +0xd1, 0xbc, 0x09, 0x0b, 0xc7, 0xca, 0x32, 0xbc, 0x4e, 0xd5, 0x23, 0xf0, 0x5c, 0x17, 0xed, 0xeb, +0xf8, 0xb9, 0x01, 0xa8, 0x7c, 0x36, 0x23, 0x22, 0xba, 0x4b, 0xf7, 0xf0, 0xd5, 0x6d, 0xd1, 0x90, +0x42, 0x16, 0x90, 0x52, 0x90, 0x85, 0x93, 0x9d, 0xce, 0x2c, 0x65, 0xab, 0x07, 0x8c, 0x07, 0xc1, +0x07, 0xa7, 0x32, 0x1a, 0x70, 0xfb, 0x6b, 0x19, 0xe0, 0x3d, 0xdb, 0x24, 0x6a, 0x65, 0xfe, 0xe0, +0xd7, 0x96, 0xa8, 0x37, 0xdb, 0x59, 0x61, 0x54, 0xc9, 0x21, 0xa2, 0x4f, 0xdc, 0xd9, 0x3b, 0xfe, +0xbb, 0x82, 0xbe, 0xe9, 0x92, 0x2d, 0xd4, 0x3a, 0x41, 0x68, 0xe7, 0xbc, 0xf5, 0x30, 0xe9, 0x52, +0x30, 0x59, 0x77, 0x83, 0x7d, 0x6b, 0x4a, 0x51, 0x03, 0x4f, 0x02, 0xd3, 0x6d, 0xc7, 0x09, 0x63, +0x10, 0xc0, 0x31, 0x34, 0x13, 0x89, 0xff, 0xcd, 0x25, 0x0a, 0xae, 0x1d, 0x99, 0x44, 0x84, 0x51, +0x2f, 0xbd, 0xc1, 0xee, 0x05, 0xfd, 0xdc, 0x0f, 0x46, 0x15, 0x39, 0xca, 0x0a, 0x05, 0xc1, 0xd1, +0x81, 0x59, 0x55, 0xf3, 0x77, 0x72, 0x21, 0x4a, 0x3a, 0x34, 0x0b, 0xf3, 0x82, 0x07, 0x79, 0x76, +0x89, 0xce, 0x8c, 0xa8, 0x48, 0x6b, 0x74, 0x78, 0xe4, 0xc8, 0x8d, 0xa0, 0xdd, 0x0e, 0xba, 0xb5, +0xb4, 0x34, 0x4a, 0x73, 0x5f, 0x5b, 0x06, 0x98, 0x7d, 0xfd, 0xff, 0x31, 0x44, 0xc2, 0x63, 0x12, +0xb5, 0x24, 0x4d, 0x00, 0x8f, 0x9d, 0x32, 0x22, 0xaf, 0xc3, 0xb7, 0xea, 0x14, 0x6a, 0xa2, 0xc5, +0xdc, 0x52, 0x14, 0x04, 0x4d, 0x61, 0x26, 0x3c, 0xf5, 0x23, 0xb4, 0x66, 0xf0, 0xf3, 0x2f, 0x5d, +0x22, 0xd2, 0x35, 0x3c, 0xdb, 0x41, 0x25, 0x2c, 0xf0, 0x05, 0x3c, 0x8f, 0x4c, 0x75, 0x05, 0x6a, +0xb3, 0x8f, 0x43, 0x6c, 0x01, 0x5f, 0x9b, 0xf7, 0x5e, 0xf1, 0xb0, 0xdc, 0x8c, 0x42, 0x7c, 0x96, +0xb8, 0x61, 0x69, 0x9a, 0x24, 0x5d, 0xe1, 0xdd, 0xfb, 0x58, 0x6a, 0x1e, 0x25, 0x8e, 0xfe, 0x14, +0xfe, 0xe2, 0x36, 0x40, 0x47, 0x3d, 0x6e, 0x10, 0x69, 0xc0, 0x5b, 0x7d, 0x96, 0xbd, 0xec, 0x33, +0xe1, 0x95, 0xc6, 0xd4, 0xc8, 0x2c, 0x22, 0x21, 0x3c, 0x7b, 0x4e, 0x7e, 0x4d, 0xa0, 0x74, 0x77, +0x39, 0x80, 0xbb, 0xd2, 0xfb, 0xa8, 0x07, 0x6a, 0x9e, 0xf0, 0x2e, 0x31, 0x28, 0xc2, 0xb1, 0x35, +0x91, 0x3b, 0xca, 0x8e, 0xb2, 0x8c, 0xb1, 0x7e, 0x2d, 0xfc, 0xf3, 0xff, 0x0c, 0xd6, 0x5b, 0x3f, +0x94, 0x37, 0xf6, 0x12, 0x7b, 0x72, 0xd3, 0x56, 0x2f, 0xb1, 0xb8, 0xf9, 0x45, 0x95, 0x60, 0x1a, +0x0f, 0xbc, 0x22, 0xc1, 0xf2, 0xaa, 0x7a, 0xa3, 0xc7, 0x62, 0xea, 0x1b, 0x60, 0x9c, 0x52, 0x69, +0xf4, 0xd7, 0x10, 0xa8, 0x78, 0xa3, 0x1b, 0x30, 0x9a, 0xc9, 0x88, 0xd8, 0x4a, 0x0d, 0x65, 0x46, +0xed, 0xe1, 0x0b, 0x87, 0x97, 0x09, 0x1d, 0x95, 0xc4, 0x9d, 0x0a, 0xf2, 0xd3, 0x6b, 0x50, 0xa8, +0x73, 0x10, 0x99, 0x75, 0xe5, 0xb5, 0x6a, 0x4a, 0xe5, 0x46, 0xfc, 0x8b, 0x31, 0x83, 0x9c, 0xfc, +0x68, 0x76, 0x1f, 0xbf, 0x02, 0x98, 0x2a, 0xbc, 0x00, 0x5e, 0xaa, 0xcc, 0xe4, 0x20, 0xd8, 0xc8, +0xb0, 0x21, 0xa9, 0x87, 0x9d, 0x59, 0xf0, 0x71, 0x9c, 0xf3, 0x02, 0x7d, 0x97, 0x87, 0x9c, 0x54, +0x2a, 0xd3, 0x7d, 0xf6, 0x9b, 0x25, 0x53, 0x82, 0x6a, 0xe3, 0xe1, 0x3d, 0x59, 0xc2, 0x89, 0xff, +0x13, 0x42, 0x8f, 0x8b, 0x7e, 0x7a, 0x43, 0x99, 0x98, 0x9b, 0x5f, 0x5c, 0xea, 0xb5, 0x85, 0xcf, +0xd4, 0xea, 0x06, 0x35, 0x35, 0x8e, 0x93, 0xf9, 0xdb, 0x81, 0x22, 0x8b, 0x5e, 0xe1, 0x72, 0x89, +0x08, 0xb8, 0xa1, 0x16, 0x73, 0xb5, 0x2e, 0x22, 0x8e, 0xf6, 0xe0, 0xe3, 0x27, 0x6f, 0xb5, 0xd0, +0x17, 0x00, 0x42, 0x4d, 0x5d, 0x8a, 0xcc, 0xdb, 0xb8, 0xcd, 0x27, 0xec, 0x0c, 0xc1, 0xbd, 0x6a, +0x2e, 0x60, 0xc1, 0x45, 0xea, 0x39, 0x31, 0xdc, 0x57, 0x3e, 0x5a, 0x04, 0x35, 0xa8, 0x23, 0x2f, +0x33, 0x69, 0xb0, 0x52, 0xfd, 0xee, 0xd0, 0xa9, 0x68, 0x9a, 0xe9, 0x8c, 0x5b, 0x69, 0xb9, 0x7f, +0xbc, 0x6f, 0x6a, 0x9a, 0x1b, 0x08, 0xb8, 0x1b, 0x97, 0x31, 0x59, 0x38, 0x75, 0x11, 0x1a, 0x7d, +0xc4, 0x61, 0x57, 0x69, 0xec, 0xc0, 0xb5, 0x81, 0xc0, 0xca, 0xbd, 0xce, 0x5a, 0x41, 0x3f, 0xe2, +0xcd, 0x39, 0x0d, 0x65, 0xa2, 0x4e, 0x33, 0xdc, 0xdd, 0xff, 0xf2, 0x7f, 0xcd, 0x18, 0x24, 0x35, +0x4d, 0x8a, 0x20, 0x31, 0xa8, 0x76, 0x59, 0x73, 0xf2, 0x05, 0xee, 0x24, 0x81, 0x93, 0xfb, 0xdf, +0x24, 0x7f, 0xe4, 0xe6, 0xc9, 0x4e, 0xc4, 0x73, 0x9b, 0x22, 0x9b, 0x2b, 0x16, 0x6c, 0x33, 0x72, +0xe0, 0x9f, 0xb6, 0xb5, 0x4f, 0xb5, 0x11, 0xe4, 0xf8, 0x70, 0xf4, 0x25, 0x16, 0x66, 0xf0, 0x79, +0x11, 0xdb, 0x9b, 0x7e, 0x4d, 0xb8, 0xfd, 0x43, 0xc8, 0xa3, 0x77, 0x24, 0xac, 0x59, 0x69, 0x31, +0x77, 0x36, 0x8d, 0xbf, 0xf7, 0xab, 0xe2, 0x04, 0x44, 0x79, 0xe4, 0x12, 0x0a, 0xc9, 0x4c, 0x6d, +0xd0, 0x1d, 0x80, 0x86, 0x12, 0x0e, 0xf2, 0xa6, 0x0c, 0xf6, 0x39, 0x50, 0xd1, 0x11, 0x7a, 0x8f, +0x42, 0xed, 0x74, 0xf0, 0x9d, 0x03, 0x46, 0x55, 0xce, 0x4c, 0x63, 0x4b, 0xf6, 0xaa, 0x78, 0xe4, +0x09, 0x98, 0xed, 0x2a, 0xcf, 0x1d, 0xdf, 0xa6, 0x89, 0x03, 0xa0, 0xbc, 0x25, 0x7d, 0x85, 0xbe, +0x09, 0x6d, 0x33, 0x52, 0x32, 0x1f, 0xac, 0x35, 0xa4, 0xa3, 0xd7, 0xf9, 0xad, 0x11, 0x58, 0xf6, +0xfb, 0xb5, 0x3a, 0xc4, 0x97, 0x09, 0x8a, 0x0a, 0x97, 0x91, 0x1d, 0x9d, 0x2e, 0x88, 0x99, 0xab, +0x2a, 0x89, 0x51, 0x6f, 0x9a, 0x2e, 0x62, 0x73, 0xd2, 0x49, 0xed, 0x55, 0x6c, 0x64, 0x82, 0xc4, +0x0e, 0xa5, 0x34, 0x03, 0xb5, 0x19, 0x10, 0x6d, 0x86, 0x8f, 0x73, 0xd0, 0xa5, 0xfd, 0x67, 0xc7, +0x28, 0xae, 0x69, 0x61, 0x7c, 0x0e, 0xae, 0xc1, 0x1b, 0x01, 0x36, 0x5d, 0xf2, 0xaf, 0x84, 0x61, +0x04, 0xc9, 0xd9, 0x79, 0xa2, 0x29, 0xd2, 0x9d, 0xb6, 0x4e, 0x1c, 0xf6, 0x26, 0xe2, 0xe0, 0x60, +0x8f, 0x59, 0x91, 0xa2, 0xa8, 0xa2, 0x5a, 0xac, 0x6f, 0x7b, 0x20, 0x1a, 0x93, 0x7a, 0x33, 0xc5, +0xfe, 0x13, 0x6e, 0xc8, 0x11, 0xe7, 0x0a, 0x26, 0x60, 0x78, 0x51, 0x4d, 0x27, 0xcb, 0x3f, 0xeb, +0xd1, 0x8a, 0x8b, 0x84, 0xfc, 0xe0, 0x58, 0x48, 0xc3, 0x93, 0x54, 0xf5, 0x1b, 0x06, 0x20, 0x69, +0x11, 0x38, 0x2b, 0x59, 0xa4, 0x6c, 0x02, 0xdc, 0x4a, 0x0f, 0xd5, 0x73, 0xfe, 0xd3, 0x87, 0xf8, +0xf8, 0xef, 0x21, 0x35, 0x1c, 0x49, 0xd3, 0x52, 0x28, 0x5b, 0x24, 0x76, 0xaf, 0x5f, 0x63, 0x54, +0xc2, 0x05, 0xed, 0x8f, 0x48, 0x12, 0xf2, 0x0c, 0x71, 0x03, 0x6f, 0xf7, 0x39, 0xb3, 0xd9, 0x08, +0x35, 0x9e, 0xac, 0x1c, 0x9e, 0xe1, 0x94, 0x2b, 0xfe, 0x7f, 0x23, 0x16, 0x22, 0xa3, 0x23, 0xd1, +0x0f, 0x72, 0xf6, 0x2d, 0xdc, 0xc4, 0x23, 0x76, 0xfe, 0xe2, 0x3a, 0x08, 0x97, 0xf8, 0x56, 0xb0, +0x56, 0x7c, 0x1e, 0x4b, 0x76, 0x28, 0xba, 0x64, 0xfd, 0x82, 0xdf, 0x81, 0xe1, 0x58, 0x46, 0x1d, +0x4f, 0x5b, 0xf5, 0xa6, 0xa9, 0x7f, 0x05, 0xa7, 0x64, 0xa8, 0x9e, 0xd4, 0x4d, 0xbf, 0x7f, 0xa0, +0x02, 0xc8, 0x0b, 0xd4, 0x1a, 0x6d, 0x68, 0x50, 0xd5, 0xa5, 0x96, 0x11, 0x7e, 0x4e, 0x97, 0x49, +0x2b, 0xe9, 0xca, 0x53, 0x61, 0x2a, 0x9e, 0xf4, 0xb6, 0xb1, 0x49, 0xb4, 0xcf, 0x7f, 0x75, 0x08, +0x4b, 0x96, 0x80, 0xec, 0x36, 0xce, 0x19, 0x1e, 0x67, 0xe8, 0x40, 0xca, 0x6d, 0x20, 0x8a, 0x3f, +0xfe, 0x21, 0xd4, 0xc1, 0x30, 0x4d, 0x8c, 0x2a, 0x08, 0xd0, 0x02, 0x46, 0x11, 0x67, 0x3d, 0x7d, +0xdb, 0x11, 0xbe, 0xf2, 0x8b, 0xcc, 0xc7, 0xb7, 0xec, 0x8a, 0x33, 0x68, 0x9a, 0xcf, 0xe7, 0xe0, +0x66, 0xc7, 0x65, 0x24, 0x59, 0x87, 0xe3, 0xd8, 0xc0, 0xe2, 0xc4, 0x5e, 0x76, 0x14, 0x99, 0xd9, +0xc7, 0xf1, 0xc7, 0x74, 0x37, 0x47, 0x02, 0xc4, 0x82, 0xf7, 0xdf, 0x4f, 0x57, 0xdf, 0xcd, 0xed, +0x2e, 0xd1, 0x04, 0x60, 0xf4, 0xc6, 0x3f, 0x77, 0x7e, 0x1a, 0xf2, 0x2f, 0xb4, 0x5e, 0xe7, 0xee, +0x42, 0x1d, 0x6e, 0x83, 0xb7, 0xe6, 0x21, 0xd5, 0xec, 0xd1, 0xd1, 0xff, 0x03, 0xdd, 0xc7, 0x53, +0xa3, 0x5c, 0xd5, 0x65, 0xc4, 0x15, 0xa5, 0x1e, 0xee, 0x7b, 0xd1, 0x18, 0xca, 0xd9, 0x40, 0x9d, +0xa8, 0x42, 0xec, 0xef, 0xeb, 0xef, 0x8d, 0xc7, 0x7c, 0xb8, 0x96, 0xba, 0x1f, 0x02, 0x20, 0x89, +0xa5, 0x37, 0x87, 0x9b, 0x3c, 0x73, 0x37, 0x6c, 0x53, 0xe1, 0xaa, 0x43, 0xff, 0xe1, 0x14, 0xd8, +0x45, 0x3e, 0xc1, 0xad, 0x66, 0x88, 0x25, 0x7e, 0x4a, 0xd2, 0x05, 0x45, 0x9b, 0xf9, 0x0c, 0x55, +0x32, 0x30, 0x76, 0x1f, 0xd8, 0x48, 0x67, 0x9d, 0x6f, 0xe4, 0x9a, 0x96, 0x4e, 0x0a, 0x80, 0xe4, +0x78, 0xac, 0xa2, 0xf4, 0x92, 0x2f, 0x8b, 0xc3, 0x88, 0xf9, 0x98, 0x9c, 0xad, 0xca, 0x8e, 0x90, +0x87, 0x37, 0xdd, 0x6e, 0xf9, 0xad, 0xd6, 0xc0, 0xdb, 0xc9, 0x36, 0xa0, 0x3b, 0xbb, 0xde, 0x4f, +0x11, 0x65, 0xe1, 0x72, 0x78, 0x16, 0x48, 0x06, 0x09, 0xde, 0x34, 0xf2, 0xcf, 0x80, 0xbb, 0x9c, +0x6d, 0xc4, 0xa4, 0xd6, 0xb1, 0x88, 0x93, 0xc1, 0x0c, 0x2b, 0xc8, 0x23, 0xe5, 0x5b, 0xe9, 0xec, +0xb8, 0x40, 0xd1, 0x80, 0x77, 0xdd, 0xf1, 0x3b, 0xc3, 0x4a, 0x1a, 0xa7, 0xc5, 0x5e, 0xed, 0x52, +0x52, 0x02, 0xe2, 0x6c, 0x8d, 0x3d, 0x2e, 0x97, 0xb3, 0x5b, 0x48, 0x28, 0xe5, 0xfd, 0x91, 0x51, +0x24, 0x5f, 0x12, 0xeb, 0xd3, 0xa3, 0xcf, 0xdb, 0x58, 0x77, 0xb5, 0x45, 0xc9, 0xa7, 0xe1, 0xe4, +0x30, 0xf4, 0xbe, 0xb4, 0xbb, 0xa2, 0x14, 0xb9, 0xee, 0xec, 0x9e, 0x6b, 0x14, 0x98, 0x4f, 0xf9, +0x52, 0xdd, 0x0a, 0x52, 0x2b, 0x5e, 0x28, 0xe7, 0x41, 0xb8, 0x36, 0x29, 0xe6, 0x6c, 0x77, 0x97, +0x95, 0x9b, 0x69, 0xd3, 0x38, 0xea, 0xa4, 0x1a, 0xb3, 0xfb, 0x8e, 0x95, 0xcf, 0x61, 0x1e, 0xe6, +0xbd, 0x5c, 0xd6, 0x02, 0xb2, 0x60, 0x9d, 0x64, 0x69, 0xa1, 0x46, 0xbd, 0x42, 0x82, 0xac, 0x5c, +0xc0, 0x94, 0x48, 0xbf, 0xab, 0x7c, 0xf4, 0xbf, 0xcd, 0x19, 0xae, 0xe1, 0x37, 0x86, 0x00, 0xd6, +0x63, 0x3c, 0x1a, 0x9f, 0x7b, 0xba, 0x79, 0xd9, 0x8c, 0xe5, 0x76, 0xb6, 0x1e, 0x8c, 0x97, 0xac, +0xd1, 0x36, 0x70, 0x68, 0x15, 0x62, 0xce, 0x5d, 0xc8, 0x89, 0x97, 0x70, 0xc6, 0x5b, 0x69, 0x25, +0x02, 0x4e, 0xe2, 0xa3, 0x1a, 0xaf, 0xe9, 0xa2, 0xc2, 0x88, 0xa6, 0x73, 0x85, 0x73, 0xb5, 0xed, +0xa0, 0x91, 0xf6, 0x56, 0xea, 0xf5, 0xd0, 0x4a, 0xda, 0x52, 0xe0, 0x21, 0xd3, 0xb8, 0x2a, 0xb0, +0xdc, 0x73, 0x21, 0x14, 0x18, 0x71, 0x1f, 0x47, 0x02, 0x39, 0x1d, 0xb2, 0xfe, 0x1c, 0xfa, 0xb4, +0x98, 0x9c, 0x6f, 0xd4, 0xf0, 0x13, 0xe5, 0xa5, 0x2b, 0x83, 0x16, 0xa4, 0x03, 0xa5, 0x8e, 0x26, +0xf5, 0x3c, 0xa3, 0x6b, 0x68, 0x60, 0x42, 0xda, 0x34, 0x1b, 0x76, 0x29, 0x8c, 0xde, 0x01, 0x68, +0x88, 0x52, 0xa2, 0xe6, 0x59, 0x6b, 0xcd, 0xfb, 0x77, 0x12, 0x25, 0x73, 0x15, 0x85, 0x68, 0x7d, +0x99, 0xdc, 0x8d, 0x81, 0xbc, 0x20, 0x8b, 0x2d, 0x23, 0x0f, 0xac, 0x44, 0xee, 0x10, 0x36, 0x9e, +0x72, 0x00, 0x1d, 0x23, 0xc8, 0x65, 0xe9, 0x21, 0xaa, 0x38, 0x69, 0x6e, 0x38, 0x7f, 0x2d, 0x56, +0x8b, 0xa8, 0x59, 0x4b, 0x33, 0xef, 0xa4, 0x2f, 0x5a, 0xd4, 0x21, 0x12, 0x27, 0x0e, 0xd9, 0x50, +0x4c, 0x7c, 0xbf, 0x76, 0xe5, 0x6c, 0x11, 0x34, 0xa5, 0x12, 0x1f, 0x6b, 0x4a, 0x70, 0xff, 0x30, +0x9d, 0x52, 0xe8, 0x0c, 0x05, 0x80, 0x29, 0x6d, 0x35, 0x5b, 0x73, 0x89, 0x3c, 0xcf, 0xb4, 0x13, +0x64, 0x44, 0xcd, 0xb4, 0x88, 0xd0, 0xe5, 0xaa, 0x9d, 0xd0, 0xda, 0x85, 0xfb, 0x19, 0x4e, 0x80, +0x73, 0x1b, 0x4c, 0x62, 0x11, 0x30, 0xbc, 0x9c, 0x95, 0x0b, 0x4d, 0xe6, 0x5b, 0x1c, 0xdb, 0x33, +0x83, 0x37, 0x69, 0x31, 0x9c, 0x04, 0x28, 0x7b, 0x17, 0x53, 0x8c, 0x9a, 0x86, 0x78, 0xb8, 0xeb, +0x4d, 0x6a, 0x7b, 0xbc, 0x72, 0x4b, 0x12, 0x3e, 0x45, 0x55, 0x3b, 0x65, 0x8c, 0xe1, 0x1a, 0x06, +0x9a, 0x23, 0x3d, 0xea, 0x9a, 0x6a, 0xdb, 0xff, 0x3e, 0xf5, 0xdc, 0x9d, 0x19, 0x6c, 0xd5, 0x23, +0xfa, 0x67, 0x7e, 0x83, 0x7e, 0xac, 0x57, 0x9e, 0xa2, 0x02, 0x7c, 0x85, 0x40, 0x3b, 0x13, 0x7f, +0x07, 0xd8, 0x14, 0x10, 0xc3, 0xcf, 0xb5, 0xeb, 0xc0, 0xd0, 0x49, 0x73, 0xf1, 0x9d, 0x54, 0xdb, +0xf0, 0x3e, 0xa0, 0xc7, 0x8e, 0xd8, 0x91, 0x8a, 0xd0, 0x56, 0xde, 0x03, 0x77, 0xcd, 0x9d, 0x5b, +0x4d, 0x86, 0xec, 0x8c, 0xc5, 0x90, 0x98, 0x8c, 0x17, 0x66, 0x3f, 0x88, 0xad, 0xcf, 0x95, 0xa9, +0xe4, 0x12, 0x2d, 0x83, 0x13, 0xc4, 0x0f, 0x19, 0x14, 0xa5, 0x2f, 0x81, 0x79, 0xd3, 0xd7, 0xfc, +0xe4, 0xba, 0xb3, 0x84, 0x06, 0xd3, 0x0a, 0x32, 0xaa, 0xd7, 0x3d, 0xb2, 0xf3, 0x9c, 0x48, 0x5d, +0x87, 0x95, 0x0e, 0xae, 0x6c, 0x80, 0x5c, 0xef, 0xc9, 0x3c, 0x4f, 0x06, 0x11, 0x0a, 0xdc, 0x6d, +0x7b, 0x2f, 0x50, 0xda, 0x8f, 0x52, 0x7c, 0x13, 0x20, 0xb5, 0xbe, 0x51, 0x7a, 0x9d, 0x93, 0x73, +0x2e, 0x8f, 0xb1, 0x62, 0x8c, 0xd9, 0x10, 0xca, 0x62, 0xb2, 0xe2, 0xbd, 0x5d, 0xa4, 0xf7, 0xb1, +0x56, 0xef, 0x72, 0x9c, 0xc4, 0xb1, 0x3a, 0xea, 0xe8, 0xf0, 0x6d, 0x30, 0xcf, 0x90, 0xd5, 0xe8, +0x4e, 0x7a, 0x2e, 0x89, 0x0e, 0x0d, 0x91, 0xec, 0xdd, 0x0f, 0xd0, 0x85, 0x69, 0xef, 0x39, 0x62, +0xd4, 0xd9, 0x3a, 0x6c, 0xa3, 0xb5, 0x10, 0x05, 0xc8, 0xa4, 0x8e, 0x0d, 0x40, 0xc5, 0xa0, 0x4d, +0x3d, 0x8f, 0x1d, 0xdd, 0xc4, 0x0b, 0xa8, 0x50, 0x7f, 0x33, 0x98, 0xb7, 0x2c, 0xc3, 0x94, 0xc6, +0xe9, 0x83, 0x95, 0x4d, 0x15, 0xb2, 0xab, 0x50, 0x40, 0x61, 0x2b, 0xd7, 0x64, 0x4d, 0x5a, 0xa7, +0x78, 0x37, 0x26, 0xa6, 0xf0, 0xbb, 0x32, 0x6e, 0x2a, 0x10, 0xac, 0x5a, 0x50, 0xb7, 0xa5, 0x04, +0xdb, 0x47, 0x43, 0x6e, 0x1e, 0x2f, 0xc1, 0x66, 0x24, 0x12, 0x23, 0x58, 0x6f, 0x2d, 0xf2, 0xc7, +0xfa, 0x38, 0x7b, 0x62, 0xbb, 0x7b, 0x22, 0x9d, 0xec, 0xbe, 0x74, 0xfc, 0xe6, 0x81, 0x1e, 0x7b, +0xee, 0x81, 0xed, 0x36, 0xa2, 0xdb, 0xe5, 0xdd, 0x57, 0xc1, 0x9c, 0xab, 0xe7, 0xba, 0x07, 0xeb, +0xe0, 0x30, 0x99, 0xc8, 0xde, 0x7a, 0x8b, 0x36, 0x7c, 0x80, 0x10, 0x25, 0x20, 0x79, 0x1c, 0xd2, +0xef, 0xc6, 0x64, 0x91, 0x2f, 0x26, 0xe6, 0xdc, 0x04, 0xa6, 0x65, 0x58, 0x6a, 0x6c, 0x6a, 0x16, +0x08, 0x5f, 0xff, 0x86, 0x6f, 0x7f, 0x53, 0x44, 0xe5, 0xbb, 0x88, 0x6f, 0x40, 0x5a, 0x96, 0xca, +0xad, 0x75, 0x54, 0x67, 0xf4, 0xc5, 0xa3, 0xfc, 0xff, 0x71, 0x0c, 0x25, 0x4b, 0xb0, 0x40, 0xae, +0xb9, 0x84, 0xe7, 0x53, 0x1e, 0x6d, 0xc7, 0x98, 0x57, 0x8e, 0x9c, 0x88, 0x3d, 0xba, 0x6a, 0x27, +0x99, 0x9f, 0x92, 0x46, 0xe3, 0x03, 0x24, 0xe6, 0x78, 0x2f, 0xaa, 0x8b, 0x6f, 0x1b, 0x39, 0xa6, +0xd7, 0x0d, 0xc3, 0xc2, 0x71, 0x54, 0xfe, 0x4d, 0xea, 0xfb, 0x4c, 0xaf, 0x8c, 0xa4, 0x41, 0xb2, +0xcc, 0x9c, 0x82, 0xc3, 0x3b, 0xf3, 0xc8, 0x04, 0x9b, 0xed, 0x87, 0x76, 0x4f, 0xf0, 0x3b, 0xb5, +0x7b, 0xde, 0x19, 0x21, 0x9a, 0x1b, 0x1a, 0xcb, 0x3a, 0x76, 0x63, 0x8e, 0x56, 0x80, 0x24, 0x31, +0x05, 0x46, 0xe8, 0x9a, 0xa1, 0x7f, 0xbf, 0x8e, 0x78, 0xc1, 0x27, 0x98, 0xa1, 0x81, 0x4f, 0xf2, +0x3b, 0x97, 0x81, 0x2d, 0xa7, 0x8d, 0x44, 0x82, 0xc6, 0x1e, 0xc3, 0x32, 0x5a, 0x21, 0xb9, 0xbf, +0x05, 0x6a, 0x66, 0x2a, 0x30, 0xe7, 0xe1, 0x8c, 0xfa, 0x7d, 0x4c, 0x3d, 0x77, 0x87, 0x94, 0x6c, +0x6c, 0xc7, 0x7e, 0x02, 0xc6, 0x24, 0xf5, 0x8f, 0x41, 0x25, 0xbf, 0x87, 0x52, 0xd6, 0x84, 0x45, +0x1d, 0xcf, 0xed, 0xc0, 0xbd, 0x76, 0x39, 0x9e, 0xc3, 0xac, 0xe1, 0x78, 0x99, 0x3a, 0xf4, 0xcc, +0x63, 0x11, 0x28, 0xa2, 0x2b, 0x32, 0xf7, 0xa6, 0x0f, 0xbe, 0xa6, 0x5a, 0x22, 0x14, 0x63, 0xcb, +0x74, 0x04, 0x86, 0x74, 0x20, 0xfa, 0xa1, 0x70, 0xa2, 0x3d, 0x67, 0x0e, 0xa4, 0xc6, 0x6e, 0xea, +0xf7, 0x9b, 0x37, 0x21, 0xfc, 0x10, 0x6d, 0x99, 0xac, 0xaa, 0xda, 0x3c, 0x82, 0xe0, 0x13, 0x76, +0xbe, 0xfb, 0xa8, 0x62, 0x82, 0x0b, 0xc5, 0x00, 0x7e, 0xf3, 0xbc, 0xc0, 0x1c, 0xce, 0xf5, 0xb2, +0x42, 0x80, 0x95, 0xe2, 0x76, 0x48, 0xb6, 0x3f, 0x91, 0xc2, 0xbd, 0x61, 0xc6, 0xf2, 0x23, 0xb1, +0x33, 0x26, 0xfc, 0xf3, 0xdf, 0x5e, 0xc0, 0xe9, 0x01, 0x0f, 0x29, 0x64, 0x70, 0x50, 0x5b, 0x7d, +0x26, 0xc4, 0xfb, 0x74, 0x26, 0x8a, 0x01, 0x35, 0x9a, 0xd8, 0x96, 0x38, 0x0e, 0x11, 0x9d, 0x53, +0x06, 0x5e, 0x80, 0xcc, 0x05, 0x50, 0x93, 0x85, 0xd5, 0x50, 0x02, 0xc5, 0xa5, 0x8b, 0xee, 0x93, +0xf6, 0xe9, 0x6f, 0xfb, 0xaa, 0xcb, 0x63, 0x17, 0xb5, 0x66, 0xde, 0x25, 0x1e, 0x9b, 0xd8, 0xfb, +0x2d, 0x14, 0xe9, 0xb3, 0x89, 0x16, 0x3f, 0xfb, 0xbc, 0x60, 0xff, 0x8f, 0xbc, 0xa9, 0x20, 0xf1, +0xfb, 0xf2, 0xe3, 0x62, 0xbd, 0x56, 0x06, 0x34, 0x78, 0x22, 0xe3, 0x5d, 0x7c, 0x8a, 0x29, 0x37, +0xfb, 0x2d, 0x3e, 0xfb, 0x0c, 0xf1, 0x78, 0x5f, 0x80, 0x4f, 0x0b, 0x79, 0x31, 0x75, 0x6f, 0x33, +0xce, 0x0b, 0x40, 0x09, 0x2d, 0xeb, 0xb0, 0x66, 0xb2, 0xb0, 0x64, 0x6c, 0x25, 0xfc, 0xa3, 0x29, +0x28, 0x2b, 0xad, 0x84, 0x9c, 0xcb, 0x0b, 0x47, 0xc8, 0x16, 0x24, 0x46, 0x5b, 0x3f, 0xd6, 0xff, +0x43, 0xe8, 0xc2, 0x2f, 0xfc, 0x42, 0x77, 0x2d, 0x60, 0xcd, 0xbe, 0x87, 0x8c, 0xf5, 0x3b, 0x2b, +0x73, 0xf8, 0x40, 0xbe, 0x61, 0xbf, 0xa0, 0xe2, 0x9e, 0xe4, 0xd2, 0xa6, 0x9e, 0x0b, 0xd4, 0xe1, +0x99, 0x88, 0xe9, 0x06, 0x18, 0xbe, 0x1a, 0x02, 0x58, 0xe9, 0x94, 0x49, 0x92, 0xc4, 0xda, 0xd3, +0x62, 0x6a, 0x54, 0x4a, 0xe1, 0x9a, 0xb4, 0x2b, 0x68, 0x19, 0x63, 0xfb, 0x98, 0x7c, 0x7e, 0xe0, +0xda, 0x0f, 0x57, 0x78, 0x58, 0x6f, 0xb3, 0x07, 0xc3, 0x59, 0x48, 0x77, 0x57, 0x05, 0x1e, 0xd9, +0xd5, 0xe3, 0x20, 0x5e, 0xde, 0x09, 0xbc, 0xe9, 0x08, 0xb0, 0xe4, 0xc2, 0x71, 0x43, 0x8f, 0x96, +0xfa, 0xf1, 0x48, 0xf4, 0x32, 0x74, 0xae, 0x6e, 0x0e, 0xf3, 0x16, 0xdb, 0xaf, 0xbc, 0xa5, 0xbc, +0xc3, 0xd5, 0xc9, 0x76, 0xc2, 0xc3, 0xb5, 0x43, 0x1c, 0xba, 0x92, 0x91, 0x39, 0x30, 0x8c, 0x49, +0x64, 0x4f, 0x46, 0x9d, 0x9f, 0x9a, 0xd3, 0x5f, 0x9a, 0xad, 0x18, 0xce, 0xab, 0x61, 0xb9, 0xe9, +0x06, 0x90, 0x85, 0xc4, 0x24, 0xca, 0x18, 0x3d, 0x28, 0xeb, 0x12, 0xbc, 0x46, 0xb5, 0x59, 0x85, +0x4b, 0xd7, 0xa5, 0x07, 0x41, 0xea, 0x55, 0x58, 0xbc, 0x2f, 0xf5, 0xba, 0x35, 0x25, 0xf8, 0xa9, +0x35, 0x04, 0x02, 0x24, 0x27, 0xb0, 0xb3, 0x96, 0x00, 0x60, 0xf0, 0xab, 0xa2, 0xe8, 0xbb, 0xaa, +0x83, 0xbb, 0x95, 0x81, 0x2f, 0xe8, 0x14, 0x7b, 0xff, 0xf6, 0x0d, 0x5d, 0xf6, 0xf7, 0x49, 0x53, +0xc3, 0x58, 0x44, 0xda, 0x7c, 0x15, 0x62, 0xe4, 0xe5, 0x26, 0xeb, 0x51, 0x41, 0x0f, 0x16, 0xc7, +0x45, 0x3f, 0x09, 0xcc, 0xb9, 0x86, 0xae, 0xd8, 0x67, 0x0a, 0x0d, 0x43, 0x57, 0x65, 0xbe, 0x4d, +0xad, 0xe1, 0x4b, 0x30, 0xf1, 0xad, 0xfe, 0x9e, 0xba, 0x6c, 0xf2, 0xe0, 0xa9, 0x72, 0x5f, 0x02, +0x57, 0xdd, 0x31, 0x18, 0x89, 0xc3, 0xa0, 0xc2, 0xf1, 0x93, 0xab, 0x39, 0xdb, 0x98, 0x9e, 0x6f, +0x3b, 0x30, 0x14, 0xc8, 0x6f, 0x9d, 0x43, 0x32, 0x93, 0xdd, 0x08, 0xda, 0xdd, 0x27, 0x2f, 0x3c, +0x6a, 0xa2, 0xd5, 0xf0, 0x81, 0x79, 0x6b, 0x54, 0xd0, 0x90, 0xb5, 0xe0, 0xaa, 0x29, 0x59, 0x6c, +0x43, 0xf5, 0x6c, 0x9f, 0x97, 0xe0, 0x70, 0xbd, 0x70, 0xad, 0x8c, 0x77, 0x72, 0x4c, 0x04, 0x35, +0x32, 0x73, 0xf3, 0x2f, 0xb9, 0x83, 0x3c, 0xec, 0xde, 0x91, 0xc1, 0x69, 0x6d, 0x16, 0xbf, 0x6a, +0x82, 0x83, 0x93, 0xfc, 0x60, 0xe8, 0x80, 0xd5, 0xd3, 0x26, 0x01, 0x99, 0xc2, 0xa7, 0x2f, 0x36, +0x10, 0xaf, 0xe3, 0xf7, 0x74, 0x30, 0xf4, 0xcc, 0x17, 0xc3, 0x6b, 0x6a, 0xd3, 0x5f, 0x01, 0x8b, +0x0e, 0x4d, 0x6b, 0xa6, 0xb6, 0x04, 0xfc, 0x82, 0x21, 0xc1, 0xfa, 0x97, 0xc4, 0x7b, 0xf1, 0x33, +0x90, 0x73, 0x42, 0x12, 0xc6, 0xb7, 0xbe, 0xbb, 0x87, 0xd3, 0x4b, 0xf7, 0x18, 0xd6, 0x5c, 0x4f, +0x3b, 0x8d, 0x75, 0x85, 0x5a, 0xfe, 0xcd, 0xb8, 0x1b, 0x69, 0x3b, 0xfe, 0x33, 0x45, 0x24, 0xe2, +0xf4, 0x0e, 0x85, 0x05, 0x6a, 0xa4, 0x76, 0x91, 0xcf, 0x57, 0xb6, 0x26, 0x62, 0x06, 0xcc, 0x1b, +0x28, 0x19, 0x80, 0xc4, 0xa9, 0x29, 0x17, 0xd8, 0x7a, 0x71, 0x29, 0xb3, 0x8e, 0x26, 0xe2, 0x6b, +0xfc, 0xe6, 0xaa, 0xe0, 0x9d, 0x02, 0x6e, 0x07, 0x48, 0xbe, 0x7f, 0xf9, 0xb0, 0x18, 0x41, 0xef, +0x7e, 0x97, 0x46, 0x05, 0x3c, 0xd5, 0x3d, 0x48, 0x6c, 0x6c, 0x7d, 0xbc, 0xe4, 0x3c, 0xea, 0x56, +0x01, 0x11, 0xb5, 0xeb, 0x3d, 0x88, 0x76, 0x85, 0xa7, 0x0f, 0x03, 0x87, 0x5d, 0x66, 0x50, 0x3e, +0x7d, 0x14, 0xc6, 0x02, 0xa1, 0xd9, 0xec, 0x77, 0x38, 0x2d, 0xdc, 0x8a, 0x06, 0x32, 0x70, 0xee, +0x1c, 0x6b, 0x50, 0x4e, 0x4b, 0x64, 0xba, 0x48, 0xf5, 0xe2, 0x17, 0xe3, 0x07, 0xa2, 0x26, 0xa8, +0xdb, 0x79, 0xf9, 0x71, 0xbf, 0xfa, 0xb2, 0x7f, 0x4b, 0x57, 0x26, 0xbf, 0x43, 0xf3, 0xea, 0x5c, +0x32, 0xbf, 0xee, 0x5c, 0xb1, 0xc5, 0xa4, 0xfc, 0x62, 0x8d, 0xa6, 0xdf, 0x23, 0xa4, 0xc6, 0x07, +0x18, 0x54, 0xb4, 0xb6, 0x71, 0xc8, 0x31, 0x0c, 0xd4, 0xab, 0xdf, 0x68, 0x02, 0xbd, 0x74, 0xff, +0x1c, 0x4e, 0x29, 0x0a, 0xe1, 0x89, 0xf8, 0x75, 0x04, 0xff, 0xe1, 0x6f, 0xa3, 0xa9, 0x1e, 0x56, +0x7a, 0x95, 0x5b, 0xd4, 0xd0, 0x4e, 0x1c, 0x64, 0x0a, 0xfa, 0xee, 0xef, 0x2b, 0x61, 0xfb, 0xe4, +0x1a, 0x06, 0xf0, 0xd5, 0x13, 0xab, 0x96, 0x57, 0x8c, 0xe4, 0x7b, 0x6e, 0xf8, 0x91, 0x9f, 0x28, +0xbc, 0x60, 0xde, 0x0b, 0x2a, 0x92, 0xdf, 0x72, 0x6a, 0x5c, 0x31, 0x58, 0xa0, 0x3b, 0xf7, 0xc4, +0x37, 0x71, 0xfc, 0x09, 0x4c, 0x8b, 0x31, 0x68, 0x55, 0x5d, 0x1f, 0xd9, 0x36, 0x56, 0xc7, 0x15, +0x8e, 0x03, 0x40, 0x01, 0x06, 0xf6, 0xc4, 0x08, 0x8d, 0xc9, 0x2c, 0xb7, 0x53, 0x32, 0x90, 0x92, +0x48, 0xd9, 0xd8, 0x19, 0xd4, 0x0d, 0x4b, 0x79, 0x9b, 0xf1, 0xed, 0xf8, 0xc9, 0xfd, 0xb6, 0x11, +0x25, 0x88, 0xdc, 0x2d, 0xfd, 0x1e, 0x31, 0x61, 0x4d, 0x36, 0x12, 0x3d, 0x62, 0xcb, 0x94, 0x91, +0x48, 0x8c, 0x82, 0x58, 0x28, 0x05, 0x7e, 0xad, 0xb4, 0x9e, 0xdf, 0xc1, 0xb8, 0xba, 0x11, 0x82, +0x33, 0x91, 0x86, 0x95, 0xe7, 0x69, 0x5a, 0x64, 0xac, 0x04, 0x89, 0x73, 0xa9, 0x87, 0x69, 0xe6, +0x4f, 0x60, 0xad, 0x0f, 0xa1, 0xed, 0x80, 0x0a, 0x81, 0x56, 0x33, 0xf2, 0x9e, 0x52, 0xfb, 0xb7, +0xfb, 0x2b, 0xd4, 0x8d, 0x45, 0xfa, 0x78, 0x3e, 0x51, 0x48, 0x72, 0x2a, 0xe2, 0x7f, 0x19, 0x72, +0x3f, 0x5c, 0x8d, 0x3b, 0x6b, 0x50, 0x35, 0x19, 0xa4, 0xcd, 0xd2, 0x5f, 0xe1, 0x0e, 0x3a, 0x58, +0xc2, 0x61, 0xbc, 0xce, 0x1b, 0xed, 0x60, 0x6c, 0x4b, 0x39, 0x02, 0x2f, 0x86, 0xf3, 0xe5, 0xc6, +0x8d, 0xcd, 0x83, 0x93, 0x25, 0x8c, 0x36, 0xab, 0x42, 0xf3, 0x90, 0xa7, 0x2e, 0x10, 0x1a, 0x74, +0xed, 0x03, 0xd1, 0x49, 0x44, 0xa3, 0x97, 0x6c, 0xe8, 0x0d, 0x10, 0x2c, 0xbd, 0xa7, 0x93, 0xfc, +0x5e, 0x85, 0x9f, 0xd0, 0x99, 0xc9, 0xc9, 0x04, 0xcf, 0x9e, 0xd8, 0xef, 0x88, 0x93, 0x3f, 0x02, +0x9c, 0x79, 0xa9, 0xb9, 0x61, 0x79, 0xd0, 0x82, 0x58, 0xae, 0x0e, 0x56, 0x76, 0xaf, 0x3c, 0xdd, +0x43, 0x96, 0x0a, 0xda, 0xaa, 0x9f, 0xc4, 0xf1, 0xd1, 0x88, 0x63, 0x32, 0xf6, 0x99, 0xf9, 0x47, +0x81, 0x8b, 0xa1, 0x0f, 0xf4, 0xdc, 0x9f, 0xc0, 0x08, 0xc1, 0xb3, 0xe5, 0x8d, 0x0d, 0x88, 0x5b, +0x59, 0xba, 0xa3, 0x6e, 0x94, 0x3e, 0xbe, 0x63, 0x29, 0xed, 0x0a, 0x62, 0x3b, 0xce, 0xa3, 0xe2, +0x77, 0xf7, 0xae, 0x2a, 0x8d, 0x89, 0xc4, 0x06, 0xd9, 0x28, 0xa1, 0x59, 0xd8, 0x9d, 0x75, 0xe4, +0xc1, 0x13, 0xb4, 0x90, 0x68, 0xa3, 0x89, 0xe6, 0x47, 0x81, 0xc8, 0x96, 0xa2, 0xd1, 0xe3, 0x9c, +0x1f, 0xee, 0xad, 0x71, 0x74, 0x07, 0xba, 0x26, 0x8f, 0x9a, 0x93, 0x2b, 0x18, 0xa3, 0x8f, 0x68, +0xde, 0xcc, 0xff, 0xc7, 0x33, 0x28, 0x6c, 0xcf, 0x75, 0x92, 0xa5, 0x63, 0x4e, 0x58, 0xb9, 0xb3, +0xf6, 0x35, 0xac, 0xe0, 0xcf, 0x81, 0x30, 0x14, 0xbd, 0xc1, 0xed, 0x2a, 0xad, 0xce, 0x52, 0xa6, +0xdc, 0x0d, 0x2a, 0xd0, 0xa0, 0x30, 0x86, 0x12, 0xb4, 0xb2, 0x25, 0xf1, 0x73, 0x42, 0x09, 0x9f, +0xb9, 0x88, 0xe1, 0x3f, 0x56, 0x56, 0x5a, 0xa5, 0x09, 0xc8, 0x53, 0xdb, 0xfa, 0x59, 0xb4, 0xf0, +0x34, 0xdf, 0xa9, 0x1e, 0x17, 0x70, 0xc4, 0xe4, 0xc6, 0x76, 0x29, 0xf9, 0x52, 0x7b, 0x91, 0xbf, +0x14, 0xe8, 0xc1, 0xef, 0x91, 0xe3, 0xa6, 0xd9, 0x16, 0x7d, 0xb9, 0x2c, 0x47, 0x94, 0x57, 0x83, +0x7d, 0x0e, 0x26, 0x4d, 0x7c, 0xd0, 0xac, 0x25, 0x82, 0x1e, 0x29, 0x3c, 0x83, 0x82, 0x04, 0xa8, +0x14, 0x2e, 0x99, 0xb5, 0x0c, 0x7a, 0x7c, 0xec, 0x82, 0x34, 0x31, 0xf6, 0xd6, 0x30, 0x17, 0x73, +0x65, 0x27, 0x57, 0xea, 0x32, 0x92, 0x35, 0x61, 0xe7, 0x71, 0x75, 0x60, 0x7f, 0xc9, 0xd3, 0xa4, +0x7d, 0x13, 0xb2, 0xdf, 0x7b, 0x2e, 0xb6, 0x4d, 0x0f, 0xd5, 0x33, 0x1a, 0xc9, 0xfe, 0xae, 0xf8, +0x9b, 0xe9, 0xae, 0xb1, 0x08, 0x86, 0x17, 0x01, 0xa5, 0x61, 0xe9, 0xbb, 0xd6, 0xa6, 0x6c, 0x0f, +0x9c, 0xa3, 0xcb, 0xc4, 0x41, 0xbc, 0xec, 0x63, 0xf7, 0x51, 0xd2, 0xbb, 0x7f, 0x28, 0x20, 0xbd, +0x75, 0x23, 0x14, 0x2a, 0x22, 0xf3, 0x19, 0xe4, 0x4c, 0x5c, 0x3c, 0x14, 0x98, 0xe9, 0xad, 0x66, +0xca, 0x0e, 0x43, 0xfa, 0xf6, 0xfe, 0x33, 0x6c, 0xa2, 0xfa, 0x9b, 0x49, 0xc2, 0xde, 0x64, 0xc3, +0x25, 0xf8, 0x9c, 0x77, 0xfd, 0xc6, 0x70, 0x63, 0x25, 0x60, 0x1f, 0x2a, 0x15, 0x8e, 0xf7, 0x22, +0xae, 0x7a, 0xce, 0xb4, 0xfe, 0x30, 0x52, 0x37, 0x02, 0x7f, 0xfc, 0x22, 0x9c, 0x8d, 0xe2, 0x69, +0x06, 0x3d, 0x7f, 0xe0, 0xd1, 0x9a, 0x95, 0x31, 0x46, 0xe6, 0x86, 0x5f, 0x51, 0x21, 0x74, 0x90, +0x66, 0x41, 0x18, 0x1b, 0x62, 0xb2, 0x50, 0xe5, 0x8d, 0x05, 0xd8, 0x80, 0xac, 0xb1, 0xf6, 0x17, +0xa3, 0x23, 0xcd, 0x76, 0xf5, 0xcf, 0xd2, 0x2a, 0xbc, 0xeb, 0x15, 0xb6, 0x55, 0xf0, 0xdd, 0xe0, +0x77, 0xf2, 0xfe, 0xc5, 0x7c, 0xb4, 0xe3, 0x62, 0x2d, 0x98, 0x40, 0x16, 0xe6, 0x21, 0xbc, 0x97, +0xea, 0x21, 0xe8, 0xfe, 0xe2, 0x15, 0x19, 0x45, 0x37, 0x2a, 0xb9, 0xb9, 0x7b, 0xdf, 0x9a, 0x5c, +0x39, 0x18, 0x06, 0x4f, 0x44, 0xaa, 0xee, 0xf9, 0x23, 0x36, 0xc2, 0x56, 0x91, 0xef, 0x7f, 0x58, +0xb7, 0xf6, 0x78, 0x4d, 0x7d, 0x09, 0x5d, 0xdf, 0x51, 0x30, 0xce, 0x99, 0xaf, 0x66, 0x25, 0x61, +0x25, 0xa5, 0x62, 0xcb, 0x02, 0x58, 0x9d, 0xc1, 0x70, 0xf8, 0x4a, 0xf7, 0xef, 0xcd, 0x1f, 0x7f, +0x6f, 0x7e, 0xa7, 0xd2, 0xde, 0x9f, 0x97, 0x99, 0xc3, 0xbf, 0x75, 0x59, 0x07, 0xf1, 0xbd, 0x1c, +0x15, 0xf9, 0xd6, 0xd1, 0x74, 0x44, 0x90, 0xef, 0xff, 0xc6, 0xaf, 0xd6, 0x54, 0xb7, 0x25, 0xd9, +0xc4, 0x0e, 0x34, 0x8c, 0x4f, 0x4c, 0xdb, 0x4b, 0x5f, 0xcd, 0x6e, 0x1c, 0xc0, 0x5e, 0x19, 0x27, +0xbc, 0x7d, 0x9d, 0x1b, 0x3f, 0x65, 0x2c, 0x44, 0xce, 0x59, 0x76, 0x1f, 0x5d, 0x70, 0x6c, 0xc7, +0xc2, 0xe0, 0xd5, 0xad, 0x83, 0x49, 0x48, 0x61, 0x22, 0xb4, 0x97, 0xdc, 0x87, 0x6f, 0xf6, 0xa3, +0x99, 0xa5, 0x9f, 0x08, 0x4e, 0xad, 0xeb, 0x7c, 0x4f, 0x19, 0x89, 0xfe, 0x56, 0xc0, 0xff, 0x6b, +0x5a, 0x48, 0xa8, 0x55, 0xb7, 0x32, 0xbe, 0x93, 0x0e, 0x80, 0xc4, 0x3c, 0x97, 0x0e, 0x05, 0xaa, +0xc1, 0xfa, 0x42, 0x97, 0xdd, 0xed, 0x08, 0x26, 0xdb, 0x2b, 0x21, 0x26, 0x6b, 0x00, 0xc7, 0x4c, +0x13, 0x18, 0xf9, 0x4a, 0xb2, 0xde, 0xe7, 0x2b, 0xb4, 0xdf, 0x82, 0x7c, 0xd3, 0xc6, 0x59, 0xb0, +0x15, 0xac, 0x47, 0x45, 0xd1, 0x8d, 0xfa, 0xbd, 0xd5, 0xf1, 0xdf, 0x2f, 0xc3, 0x62, 0xbe, 0x48, +0x9c, 0x56, 0x32, 0xad, 0xd3, 0xba, 0xd7, 0xb3, 0xb4, 0x7e, 0xde, 0x7a, 0x11, 0xd1, 0x12, 0x18, +0xff, 0xf3, 0xcf, 0x32, 0x02, 0xb0, 0x06, 0x9b, 0x81, 0xbf, 0x73, 0xe4, 0x4e, 0xe9, 0x83, 0x3d, +0xe7, 0x85, 0x2c, 0x0b, 0xd1, 0xfd, 0x43, 0x95, 0xce, 0xe1, 0xf5, 0x44, 0x86, 0xfc, 0xb6, 0xc2, +0x5b, 0xf4, 0x92, 0x5a, 0x32, 0x2f, 0x4e, 0x22, 0xd5, 0xea, 0x60, 0x5b, 0xf7, 0x60, 0xad, 0xc6, +0xdc, 0xab, 0x78, 0xb5, 0x09, 0x6c, 0x8f, 0x3e, 0xc9, 0x44, 0x90, 0xfa, 0xb2, 0x88, 0x4e, 0x67, +0x41, 0x0a, 0xeb, 0xd7, 0x53, 0x65, 0x21, 0x71, 0xda, 0xe2, 0xd3, 0x9d, 0x3d, 0x94, 0x38, 0x39, +0xa0, 0xcc, 0xd1, 0xd4, 0x26, 0x5c, 0x3c, 0x75, 0xf2, 0x89, 0x43, 0x01, 0x58, 0x0a, 0x3a, 0x82, +0x05, 0x9e, 0x36, 0xfd, 0xb4, 0xaa, 0x13, 0xd0, 0x16, 0x74, 0x90, 0xb0, 0x48, 0xe8, 0x73, 0xa8, +0xd9, 0x52, 0xbd, 0x43, 0x14, 0x34, 0xf3, 0xda, 0xe3, 0xf8, 0x14, 0x0a, 0xa5, 0x16, 0x10, 0x66, +0x2c, 0x9c, 0xb2, 0xb3, 0xf1, 0x24, 0xce, 0x22, 0x50, 0xeb, 0x17, 0xe1, 0x20, 0x47, 0xe8, 0xe1, +0xac, 0xa9, 0x58, 0x07, 0x2c, 0xa5, 0x01, 0xd0, 0x85, 0x2f, 0x02, 0x0f, 0x90, 0x3d, 0xcd, 0x72, +0xc1, 0x1b, 0xe2, 0xfb, 0x93, 0x84, 0xfb, 0xdc, 0xdd, 0x7e, 0x41, 0x44, 0x12, 0xe5, 0x4a, 0xda, +0xc8, 0x6f, 0x0e, 0x6c, 0x27, 0xfc, 0x0c, 0xe5, 0xa7, 0xd8, 0xc8, 0xea, 0x90, 0x92, 0xeb, 0x53, +0xd2, 0x2e, 0x3f, 0xba, 0x1c, 0x49, 0x70, 0x04, 0x17, 0x12, 0x28, 0xfe, 0x41, 0x5a, 0xd5, 0xa8, +0x3a, 0x1f, 0x93, 0x7f, 0xe7, 0x4f, 0x06, 0x7f, 0x49, 0x4b, 0xd9, 0x37, 0x0b, 0xde, 0x3d, 0x61, +0x9a, 0xb2, 0x2d, 0x61, 0xe3, 0x6a, 0x98, 0xed, 0xa7, 0x76, 0xbe, 0x32, 0x6a, 0x82, 0xea, 0xe9, +0x1d, 0x37, 0x75, 0xb8, 0xa3, 0x4a, 0xb8, 0x1d, 0x7f, 0xcc, 0x9c, 0x04, 0xe1, 0x3c, 0x71, 0x9a, +0x81, 0x02, 0xf0, 0xf2, 0xc0, 0x32, 0xf2, 0xe9, 0x55, 0xb3, 0x31, 0xad, 0x0f, 0xa3, 0x1a, 0x3c, +0x2e, 0xc6, 0x27, 0xf1, 0xeb, 0x52, 0x3b, 0x04, 0x0a, 0x8b, 0x61, 0x7c, 0x4f, 0x3e, 0xfb, 0x1f, +0x78, 0xd9, 0x5a, 0x2e, 0x4d, 0x6f, 0x1c, 0x04, 0x5f, 0x80, 0xee, 0x74, 0x5b, 0x42, 0x07, 0x6e, +0xcc, 0x9e, 0x2d, 0xd1, 0x5f, 0x37, 0xf9, 0xe9, 0xbc, 0xc2, 0xdb, 0xb9, 0x7f, 0xcf, 0xff, 0x1b, +0x4c, 0x12, 0xbf, 0xab, 0x02, 0x10, 0x16, 0x7b, 0x34, 0xdc, 0x7e, 0x1a, 0xdd, 0x99, 0x84, 0x28, +0x6d, 0x7b, 0x3c, 0xdc, 0xf3, 0x0e, 0x59, 0x1e, 0x69, 0x63, 0x5e, 0x77, 0x8e, 0x91, 0x38, 0x2d, +0x57, 0x33, 0x9e, 0x44, 0x7d, 0xcc, 0xf6, 0xa5, 0x51, 0x85, 0xec, 0x12, 0xe8, 0x27, 0x07, 0xdc, +0x56, 0x72, 0x1a, 0x7f, 0xe3, 0x47, 0xde, 0x7d, 0xa7, 0x94, 0x1f, 0x27, 0xc6, 0x5f, 0xd2, 0x5f, +0x57, 0x41, 0xad, 0xc8, 0x60, 0x01, 0x34, 0x4f, 0xc4, 0xeb, 0xf2, 0x08, 0x02, 0xda, 0x37, 0x03, +0xb0, 0x67, 0xab, 0x28, 0x68, 0x16, 0xbf, 0xde, 0xe1, 0x22, 0x68, 0xd5, 0xf9, 0xd7, 0x08, 0x04, +0xad, 0xbe, 0x30, 0xa6, 0x4d, 0x2d, 0x65, 0xfb, 0x9e, 0x65, 0xcf, 0x1a, 0x67, 0x15, 0xe8, 0xa9, +0xdf, 0x35, 0xf9, 0x9a, 0xa2, 0x84, 0xeb, 0x79, 0x59, 0x92, 0xeb, 0x31, 0x3f, 0xbc, 0xe9, 0x82, +0xd2, 0xfc, 0xc0, 0x36, 0x2f, 0x34, 0xab, 0x98, 0x74, 0x4e, 0x1d, 0x94, 0x2e, 0xed, 0xb1, 0xcb, +0x74, 0x9a, 0x3f, 0x36, 0xca, 0x55, 0x15, 0x79, 0xc6, 0x7e, 0xa4, 0xa4, 0x5a, 0xd0, 0xf5, 0x68, +0xe4, 0x64, 0xaa, 0x6c, 0xdf, 0x85, 0x71, 0x95, 0x7c, 0xe9, 0x1d, 0xe1, 0x83, 0x68, 0xdc, 0x90, +0x6e, 0xb7, 0xc7, 0x69, 0x5c, 0x6c, 0x80, 0xed, 0x3d, 0xfd, 0x11, 0x8f, 0x59, 0x03, 0x9d, 0x28, +0x69, 0x5e, 0xca, 0xa6, 0x98, 0xf1, 0x9e, 0x4c, 0x0e, 0x62, 0xe6, 0x7a, 0xb8, 0x6f, 0xa8, 0xee, +0x10, 0x59, 0x4e, 0xec, 0xa3, 0x95, 0x1d, 0x0d, 0x9d, 0xcd, 0x22, 0x08, 0x97, 0xcc, 0x5a, 0xbc, +0x20, 0xa3, 0x11, 0x1c, 0xbc, 0x45, 0xd8, 0x72, 0xb6, 0x52, 0xb2, 0x07, 0x3a, 0xd1, 0x9b, 0x3e, +0x49, 0x7a, 0x93, 0xde, 0x85, 0x11, 0x94, 0x78, 0xba, 0x08, 0x82, 0x9e, 0xb0, 0x0c, 0xd0, 0x4e, +0xa8, 0x50, 0xe6, 0x3f, 0xbe, 0x72, 0x8d, 0xdd, 0x32, 0x21, 0xa2, 0x7a, 0xaf, 0x1b, 0xcc, 0xc8, +0x9b, 0x45, 0x82, 0xf5, 0x3c, 0x67, 0xba, 0x66, 0xe3, 0x5e, 0xc5, 0xdf, 0x1f, 0xfc, 0x5c, 0x12, +0xeb, 0xe1, 0x13, 0x44, 0xb6, 0xcb, 0xea, 0x77, 0x9d, 0xef, 0x58, 0x7c, 0x6f, 0xaa, 0xa1, 0x87, +0xcb, 0x41, 0xdc, 0x3e, 0x05, 0x39, 0x54, 0x9c, 0xe8, 0xad, 0x09, 0x3a, 0xad, 0x9a, 0x95, 0x64, +0x2c, 0xb9, 0x6f, 0x61, 0x41, 0x40, 0x77, 0x92, 0xe3, 0x96, 0xc7, 0x33, 0x69, 0xef, 0x63, 0x3e, +0x09, 0xe2, 0x61, 0x63, 0x65, 0xf7, 0xb9, 0x15, 0x0e, 0xd9, 0x6c, 0xb5, 0x50, 0x3a, 0x60, 0xa8, +0x38, 0xa2, 0xb8, 0xc2, 0x08, 0x84, 0x9f, 0xe1, 0x64, 0x62, 0x29, 0xf0, 0x77, 0x6a, 0xd0, 0x6e, +0xdd, 0xe3, 0xcd, 0x90, 0x3a, 0x2c, 0x2d, 0xd2, 0x76, 0x0e, 0xe7, 0xd5, 0x88, 0x60, 0x6b, 0x46, +0x0c, 0x3a, 0x6c, 0xc7, 0x3a, 0x30, 0x87, 0x11, 0x43, 0xce, 0x74, 0x73, 0x7e, 0x15, 0xae, 0x88, +0xde, 0xf7, 0xf4, 0x27, 0x4d, 0xf6, 0x61, 0xb9, 0xb4, 0x98, 0x4a, 0xe5, 0x9e, 0x29, 0x2e, 0xec, +0x04, 0x2a, 0x45, 0xb9, 0xfc, 0xb0, 0x2b, 0x24, 0xc0, 0xda, 0x46, 0x54, 0xa7, 0x78, 0x9e, 0x13, +0x52, 0x8d, 0x0f, 0xfb, 0x18, 0x70, 0x7d, 0xae, 0xcc, 0x17, 0xf6, 0x60, 0x61, 0xa2, 0xec, 0xe1, +0xe6, 0xbb, 0x9c, 0x7d, 0xae, 0x8b, 0xc4, 0xf5, 0x21, 0x23, 0x2c, 0x4f, 0xc6, 0x31, 0x7e, 0x92, +0x45, 0x7d, 0x0e, 0x5b, 0x2b, 0x78, 0xee, 0x5f, 0x23, 0xa2, 0x0c, 0x9e, 0x63, 0x44, 0xcf, 0xcc, +0xd0, 0x2a, 0xb7, 0x0a, 0xee, 0x61, 0x2c, 0xcb, 0x41, 0x74, 0x09, 0x3c, 0x79, 0x20, 0xe8, 0xbc, +0xe7, 0x79, 0xd5, 0x01, 0x8f, 0xd5, 0x28, 0xa3, 0x34, 0xb1, 0x67, 0xb7, 0xc4, 0x90, 0xd3, 0x52, +0x72, 0x94, 0xc8, 0x9b, 0xb6, 0x5b, 0x11, 0x8f, 0xe7, 0xd1, 0x78, 0x5b, 0x5e, 0x45, 0x5e, 0xbc, +0x32, 0xb2, 0xe8, 0x0b, 0x43, 0x7e, 0x25, 0xa1, 0x32, 0xe2, 0x06, 0xa8, 0x93, 0x54, 0x43, 0xea, +0xf9, 0xc1, 0x9e, 0x4d, 0xad, 0xf0, 0x5d, 0x09, 0xbc, 0x61, 0xf8, 0x2f, 0xaf, 0x91, 0x05, 0xcd, +0x88, 0x61, 0xc5, 0x1b, 0x84, 0x89, 0x2b, 0x18, 0x93, 0xbf, 0xca, 0x78, 0x0c, 0x1c, 0xcc, 0x12, +0x09, 0x7d, 0xc3, 0x39, 0xbc, 0x1c, 0x55, 0x2f, 0x7a, 0x83, 0x28, 0xbd, 0xdb, 0x93, 0xe7, 0x13, +0xb9, 0x8d, 0xa0, 0xc8, 0x80, 0xfe, 0xd1, 0x4f, 0xcc, 0xef, 0x0f, 0xa9, 0xeb, 0x7e, 0x47, 0xb7, +0xf1, 0xd0, 0x31, 0x5a, 0x77, 0x6d, 0x16, 0xca, 0x53, 0x68, 0xed, 0x85, 0x4a, 0xa1, 0xb6, 0x81, +0xff, 0x94, 0x95, 0xac, 0xc9, 0xaf, 0xa5, 0x38, 0x4a, 0xb9, 0x48, 0x18, 0x24, 0x8a, 0x5d, 0x04, +0x44, 0xfe, 0x41, 0x93, 0x47, 0x00, 0x6b, 0x62, 0xfa, 0x2a, 0x64, 0xd0, 0x85, 0x43, 0x1f, 0x7a, +0xd4, 0x26, 0xe9, 0x9a, 0x05, 0x8e, 0x07, 0x60, 0x00, 0x64, 0x72, 0x5f, 0xbf, 0x01, 0x53, 0x11, +0x7b, 0x82, 0x5b, 0xf3, 0x26, 0x29, 0xda, 0xaa, 0x69, 0x3e, 0x8e, 0x76, 0x18, 0x31, 0x73, 0x9f, +0xa7, 0x5e, 0x06, 0x31, 0x57, 0xd7, 0x17, 0xde, 0x3c, 0x8b, 0xaa, 0xc7, 0xf7, 0x63, 0x3d, 0x26, +0xfb, 0x01, 0x9b, 0xee, 0xc3, 0xd9, 0xf1, 0xb1, 0xae, 0xe2, 0xf2, 0x80, 0x1d, 0x7c, 0x83, 0x49, +0xec, 0x76, 0x18, 0x82, 0xc6, 0x4a, 0x9e, 0xfb, 0x92, 0x32, 0x38, 0xd4, 0xeb, 0xe9, 0x59, 0x2e, +0x33, 0x71, 0x43, 0x54, 0x48, 0x45, 0x2d, 0x7b, 0x11, 0x79, 0xc5, 0x16, 0xaa, 0xcd, 0x62, 0x4d, +0x25, 0xda, 0xbf, 0x85, 0xe9, 0x62, 0x74, 0xcb, 0xd6, 0x1b, 0x29, 0xee, 0x78, 0x03, 0x0a, 0xb7, +0x51, 0xe5, 0x7e, 0x9e, 0x5f, 0x37, 0xae, 0xbe, 0x8b, 0x40, 0xdb, 0x5e, 0xd4, 0x6c, 0xdc, 0xcd, +0xb5, 0x33, 0xf5, 0xc0, 0xb4, 0x02, 0x17, 0x17, 0x16, 0x06, 0x4a, 0xf2, 0xcf, 0xae, 0xb3, 0x54, +0x3d, 0xb1, 0x16, 0xec, 0x18, 0x02, 0xb5, 0x4a, 0xa4, 0x81, 0x20, 0xf8, 0x6e, 0x51, 0x90, 0xa8, +0xe5, 0x75, 0x7c, 0xff, 0xfc, 0x0c, 0xa2, 0xd1, 0x16, 0x98, 0x46, 0x19, 0x93, 0xec, 0x0f, 0x1e, +0x9c, 0x69, 0xae, 0xa1, 0x95, 0x3e, 0xcf, 0xd2, 0x43, 0x33, 0x32, 0xff, 0x85, 0xdb, 0x31, 0xdf, +0x8b, 0x4c, 0x5e, 0xbd, 0x38, 0xd8, 0x6e, 0x66, 0x9c, 0xe7, 0x2f, 0x82, 0x16, 0x27, 0x86, 0x7b, +0x9a, 0xce, 0xdf, 0x51, 0xee, 0xf0, 0xc7, 0xf9, 0xb1, 0x2b, 0x01, 0x8e, 0xa6, 0xb2, 0x30, 0xa1, +0xf1, 0xd7, 0x4b, 0x30, 0x23, 0x5c, 0x55, 0x13, 0xdb, 0x4d, 0x76, 0x47, 0x95, 0x78, 0x84, 0x95, +0x34, 0x47, 0xb6, 0xb1, 0x1a, 0x40, 0xc4, 0xa6, 0x65, 0xde, 0xc4, 0xa9, 0x25, 0x96, 0xcd, 0xf6, +0x60, 0x72, 0x09, 0x04, 0xce, 0xaa, 0xda, 0x67, 0x79, 0x1d, 0x17, 0x0f, 0xdf, 0x45, 0xbd, 0xa8, +0x91, 0x4e, 0x89, 0x43, 0xb4, 0x84, 0xf9, 0xf9, 0xee, 0xc3, 0x4d, 0x6a, 0x2e, 0xaa, 0x1a, 0xc3, +0x5f, 0x3c, 0x0e, 0x0d, 0x48, 0xf4, 0x34, 0x31, 0xf7, 0x3a, 0x37, 0xe1, 0x38, 0xa5, 0x79, 0x86, +0x01, 0x0f, 0xfa, 0x04, 0x4a, 0x5c, 0xa6, 0x17, 0xed, 0xb5, 0x0e, 0x15, 0xbf, 0xe9, 0x55, 0xcb, +0xcb, 0xa3, 0x8b, 0xcb, 0xe8, 0x4a, 0xc1, 0xec, 0xd7, 0x30, 0xe4, 0x66, 0x79, 0xcb, 0xd6, 0x86, +0x1f, 0xec, 0xfa, 0x16, 0x39, 0x20, 0xdc, 0x1f, 0x8d, 0x15, 0x87, 0x9a, 0x27, 0x08, 0xdc, 0xcd, +0x9e, 0xfb, 0xf7, 0x3a, 0xd6, 0xa9, 0x14, 0xd9, 0xbd, 0xda, 0x45, 0xf6, 0xf0, 0xaf, 0x89, 0x0e, +0xd4, 0xb3, 0x84, 0xa7, 0xa2, 0x8a, 0x68, 0x0f, 0xc9, 0x5c, 0xe0, 0xdd, 0x7d, 0x48, 0x08, 0x2b, +0x89, 0x31, 0xea, 0x5c, 0xa1, 0xac, 0x42, 0x95, 0x2b, 0x74, 0x42, 0xac, 0x75, 0xb7, 0x1b, 0x92, +0x3f, 0x74, 0xf5, 0xc3, 0x9f, 0x3f, 0xa2, 0x9e, 0x02, 0xfa, 0x11, 0x5f, 0xd9, 0xa9, 0x3c, 0xb5, +0xb9, 0xf5, 0x54, 0x6e, 0x5d, 0x10, 0xb2, 0x04, 0x56, 0x73, 0x05, 0x37, 0x98, 0x60, 0x59, 0x16, +0xbf, 0xe9, 0xf9, 0x87, 0xed, 0x7f, 0xe7, 0xa5, 0x24, 0xde, 0xa8, 0x0e, 0xbb, 0xe7, 0xb7, 0x0f, +0xd3, 0xeb, 0xfb, 0x59, 0x84, 0xb1, 0x9a, 0x37, 0xde, 0x74, 0xd7, 0xad, 0x67, 0xf6, 0xdc, 0x34, +0x46, 0x41, 0xe6, 0xff, 0x2e, 0x85, 0xc9, 0x6c, 0xe2, 0xf6, 0x94, 0x7a, 0x0c, 0x77, 0xad, 0x1e, +0x52, 0x5d, 0xd3, 0xef, 0xa2, 0xa2, 0x5f, 0xa1, 0x5c, 0xed, 0x80, 0x59, 0xf7, 0x64, 0x23, 0x59, +0x35, 0xf1, 0x7b, 0x99, 0x6a, 0x07, 0xeb, 0x5c, 0x33, 0x1b, 0xfc, 0x46, 0x12, 0x26, 0xab, 0x16, +0x85, 0xeb, 0xde, 0xec, 0x15, 0x33, 0xf8, 0xe5, 0x0d, 0x92, 0x9f, 0x41, 0x44, 0x0b, 0x2e, 0x3f, +0xc3, 0xe3, 0x56, 0x91, 0x1c, 0x4b, 0x85, 0x38, 0xf8, 0x54, 0x17, 0xa5, 0x4b, 0x7c, 0xbf, 0x98, +0x52, 0xd8, 0xdd, 0xd6, 0x87, 0xfd, 0xfb, 0xa5, 0x32, 0x8b, 0x4e, 0x01, 0xe1, 0x6c, 0x5d, 0x28, +0x0b, 0xa2, 0xfc, 0xe5, 0x6e, 0xb3, 0x5f, 0xa2, 0xc0, 0xaf, 0xd9, 0x1a, 0xc6, 0x8e, 0x3d, 0xc6, +0xaa, 0x6f, 0xa1, 0x93, 0xa0, 0xb6, 0xbb, 0xf9, 0x65, 0x67, 0x66, 0x99, 0xee, 0x7c, 0x0a, 0x1a, +0x8a, 0xf7, 0xdb, 0x40, 0x08, 0xc4, 0x2d, 0x3e, 0x80, 0x36, 0xaf, 0x7d, 0x6e, 0x83, 0x4b, 0x8b, +0x96, 0xd5, 0x38, 0x97, 0x1b, 0x18, 0x6b, 0xde, 0x94, 0x1b, 0x18, 0x98, 0x7f, 0x42, 0xef, 0x48, +0xf9, 0xa6, 0x9f, 0x2e, 0xf8, 0x31, 0xbf, 0xc6, 0xcc, 0xde, 0x78, 0xf3, 0x62, 0xbf, 0x6b, 0x28, +0x57, 0xb0, 0x34, 0xd0, 0xc0, 0x03, 0x40, 0x07, 0x1e, 0x49, 0x2a, 0x09, 0x1e, 0x05, 0xe5, 0xcd, +0x0c, 0x9b, 0xa4, 0xe8, 0x99, 0x91, 0xf2, 0xe1, 0xaf, 0x3c, 0x85, 0x0d, 0x89, 0x38, 0x11, 0x08, +0xdd, 0x08, 0x90, 0xee, 0x49, 0xdd, 0x9a, 0xe3, 0x9f, 0x0b, 0x2b, 0xa8, 0x22, 0x0f, 0x74, 0xa9, +0x44, 0x1c, 0x08, 0xbf, 0x4e, 0x4f, 0x1f, 0x2b, 0x55, 0x2d, 0xbb, 0xf8, 0x28, 0x86, 0xa8, 0x39, +0x1a, 0x71, 0xaa, 0xc3, 0x6c, 0x30, 0x5c, 0xa8, 0x57, 0x8a, 0x0a, 0x6f, 0xcf, 0xfd, 0x4e, 0xe9, +0xa0, 0xed, 0x15, 0x7a, 0xed, 0x7f, 0xcc, 0xda, 0x96, 0x4d, 0x0a, 0x86, 0x4c, 0x7d, 0xe2, 0x04, +0xcd, 0x94, 0x80, 0x5e, 0x73, 0x46, 0x9f, 0x07, 0x5e, 0x1d, 0x8f, 0x2d, 0x47, 0x7c, 0xea, 0xed, +0xe2, 0x30, 0x5e, 0x48, 0x30, 0xf1, 0x1f, 0x68, 0x5a, 0xb7, 0xcb, 0xda, 0x5a, 0x20, 0x84, 0x51, +0x48, 0x24, 0xdd, 0xd8, 0x06, 0x6e, 0xe7, 0x8a, 0x16, 0x59, 0xf8, 0x02, 0x2e, 0x90, 0x61, 0x82, +0x12, 0x93, 0xc4, 0xb7, 0xb0, 0xe4, 0x51, 0x76, 0x64, 0x2f, 0xfe, 0x3a, 0xb6, 0xd5, 0x6e, 0xdf, +0x68, 0xe2, 0x28, 0xa2, 0xc4, 0xe3, 0x16, 0xda, 0xb1, 0x31, 0x16, 0x46, 0xae, 0xd7, 0x72, 0x25, +0x3e, 0x01, 0x36, 0x07, 0xee, 0x98, 0x05, 0x96, 0xd1, 0xe7, 0xa5, 0x91, 0xe3, 0x1d, 0x8e, 0xee, +0x63, 0x7b, 0xce, 0xca, 0x43, 0x94, 0xaa, 0x65, 0xe1, 0x0d, 0xe1, 0xf5, 0x4e, 0xc3, 0x09, 0xdc, +0xe0, 0x81, 0x26, 0xfa, 0x8e, 0x7e, 0xb6, 0xe0, 0x9f, 0xa8, 0xb0, 0x3d, 0xa9, 0x6d, 0x54, 0x43, +0xa6, 0x50, 0x44, 0x2a, 0x61, 0x16, 0x08, 0xe1, 0x75, 0xf0, 0xc0, 0x47, 0x0b, 0x71, 0x52, 0xc9, +0xab, 0xa8, 0x64, 0xe0, 0xcb, 0x6c, 0x7c, 0x74, 0x09, 0xf7, 0xf1, 0xc9, 0xdd, 0xf0, 0x5c, 0xe3, +0x33, 0x0c, 0x17, 0x69, 0x02, 0xef, 0x3d, 0xbd, 0xd1, 0x3d, 0xfa, 0x3e, 0x41, 0xc3, 0x65, 0xf1, +0x13, 0x34, 0x67, 0xd8, 0x87, 0x0b, 0x4d, 0xc3, 0x68, 0x67, 0x66, 0x3c, 0x8e, 0xfa, 0xf6, 0x68, +0x99, 0xa3, 0xbf, 0x85, 0x47, 0x05, 0xd9, 0x0b, 0x76, 0xdd, 0x67, 0xad, 0xda, 0x64, 0x98, 0xee, +0x98, 0x75, 0x64, 0x89, 0x82, 0xfe, 0x9f, 0x6a, 0x24, 0xb9, 0xda, 0xb1, 0xac, 0xf0, 0xdd, 0xa4, +0x38, 0x99, 0xd7, 0xf6, 0x0e, 0x47, 0x77, 0x34, 0xc9, 0x69, 0x93, 0xd5, 0x68, 0xcf, 0x2d, 0xa5, +0xfc, 0x44, 0xe6, 0x58, 0x3b, 0x86, 0x23, 0x24, 0xb6, 0x7b, 0x70, 0x84, 0x43, 0x07, 0xe8, 0x58, +0xcb, 0x72, 0x6f, 0x5d, 0xee, 0x22, 0xc2, 0x0d, 0xdb, 0x2e, 0x5f, 0x69, 0x49, 0x41, 0xeb, 0x44, +0xf4, 0x2a, 0x2a, 0x6c, 0xc8, 0xc6, 0x10, 0x32, 0x89, 0x96, 0x52, 0xca, 0x7e, 0x22, 0x6d, 0x62, +0x9f, 0x9c, 0x7e, 0x4e, 0x4b, 0x82, 0x66, 0x61, 0xf7, 0x04, 0xee, 0x5a, 0x0b, 0x14, 0xac, 0x2a, +0x50, 0xb1, 0x77, 0x38, 0xff, 0x87, 0x3d, 0xee, 0x96, 0x28, 0x47, 0x62, 0x95, 0x02, 0xf6, 0x9d, +0xbd, 0x43, 0x1a, 0xa7, 0x93, 0x5d, 0xfd, 0x96, 0x36, 0xc1, 0xaa, 0x77, 0x85, 0xe1, 0x92, 0xc4, +0xe3, 0x39, 0x3c, 0x22, 0x25, 0x2a, 0xc0, 0x4d, 0xb0, 0xf3, 0x5a, 0x7c, 0xdd, 0xfd, 0x30, 0xcf, +0x2c, 0xb0, 0x23, 0x75, 0x5e, 0xb9, 0xcf, 0xb2, 0x4f, 0xf3, 0x58, 0x5e, 0x34, 0x93, 0xab, 0xfa, +0xa6, 0x1b, 0x3f, 0xf1, 0xf9, 0x60, 0x80, 0xbf, 0x2f, 0xc8, 0x3d, 0xe6, 0xd3, 0x48, 0x31, 0x36, +0xdb, 0xfa, 0x6e, 0xd7, 0x80, 0x33, 0x73, 0xb7, 0x22, 0x1b, 0x7c, 0x1d, 0xcb, 0xb6, 0xe8, 0xf9, +0x2b, 0x30, 0x67, 0x8d, 0xc3, 0x0f, 0x68, 0x91, 0x08, 0xf7, 0x9b, 0x8c, 0xbc, 0xf6, 0x94, 0x99, +0x2b, 0xe8, 0xb1, 0x5e, 0x7a, 0xd1, 0xf0, 0x37, 0xfe, 0x63, 0x99, 0xeb, 0x0b, 0xbb, 0xa9, 0x3f, +0xfc, 0x8b, 0x1c, 0x93, 0x4b, 0xf9, 0xbf, 0xb1, 0x31, 0x4d, 0xfd, 0x70, 0xea, 0x13, 0xcf, 0x97, +0xcc, 0xc9, 0x5e, 0x57, 0xf0, 0xd9, 0xd7, 0x51, 0x28, 0x6b, 0xac, 0x9e, 0x33, 0xce, 0x77, 0x38, +0xab, 0xc1, 0x9f, 0x1e, 0xa9, 0x03, 0x0b, 0xfb, 0x7e, 0xb7, 0x3a, 0x1d, 0x22, 0xf7, 0xdf, 0xec, +0x92, 0x0f, 0x69, 0xb4, 0x6b, 0xed, 0x4e, 0x11, 0x0d, 0xd0, 0x86, 0xfb, 0xe3, 0x1b, 0x32, 0xfa, +0xf7, 0x7b, 0x9d, 0xa7, 0x68, 0x56, 0x43, 0x70, 0x23, 0x08, 0x8b, 0xca, 0x27, 0x54, 0x13, 0xa4, +0xbc, 0xf5, 0x11, 0xf4, 0xd8, 0x7d, 0xd7, 0xe3, 0xe4, 0xf1, 0x78, 0xfb, 0x20, 0x3a, 0x91, 0x10, +0x20, 0xdc, 0x8a, 0xae, 0x09, 0x6c, 0xf1, 0x48, 0x9a, 0xea, 0x05, 0xe3, 0x37, 0x5f, 0xb6, 0xa3, +0x5a, 0x7c, 0xa9, 0xe9, 0xa1, 0xfb, 0xff, 0xe8, 0xa6, 0x09, 0x8f, 0x6d, 0x5f, 0x86, 0x28, 0xd4, +0x6f, 0xbb, 0x08, 0xd2, 0xea, 0x56, 0xc7, 0xed, 0x5b, 0xca, 0xb4, 0xf5, 0xdd, 0x79, 0x9f, 0x92, +0x9d, 0xbc, 0x5b, 0x36, 0x19, 0xad, 0x1f, 0x7a, 0xfe, 0xca, 0xc3, 0x25, 0x11, 0x71, 0x94, 0x0c, +0x69, 0x3d, 0x91, 0xb1, 0x2b, 0xa6, 0x06, 0x43, 0xa3, 0xba, 0x88, 0xb0, 0x3a, 0xcb, 0x71, 0xc1, +0x92, 0x67, 0x6c, 0x18, 0x4a, 0xb8, 0x49, 0x8f, 0x8e, 0x0d, 0x5a, 0xa8, 0x37, 0x01, 0x06, 0x0a, +0xf1, 0xfa, 0x55, 0xcc, 0x76, 0xbe, 0xb1, 0x2c, 0xa5, 0xeb, 0x08, 0x7a, 0x2e, 0xf5, 0xe5, 0xa8, +0x75, 0x9b, 0xbd, 0xb6, 0xfb, 0x57, 0x60, 0x28, 0x35, 0x7f, 0x50, 0xf7, 0xb9, 0x42, 0x18, 0xcb, +0x57, 0xf7, 0x6a, 0x6d, 0x44, 0x8f, 0x87, 0x71, 0x4a, 0xb8, 0x66, 0x1e, 0x70, 0x3d, 0x96, 0x74, +0xc4, 0xbb, 0x10, 0x6b, 0x5f, 0x28, 0x11, 0x71, 0xa5, 0xb3, 0x8f, 0xbc, 0x80, 0xd6, 0x08, 0xfc, +0xaa, 0x39, 0x2b, 0x31, 0x30, 0x3c, 0xbb, 0xf1, 0x29, 0x69, 0xed, 0x1d, 0xd8, 0x3d, 0xa6, 0x47, +0x22, 0x55, 0xb3, 0x55, 0x17, 0x11, 0x2d, 0x9d, 0xf0, 0xae, 0xde, 0x50, 0xd3, 0xd3, 0xb1, 0x7a, +0x6e, 0xcb, 0x7d, 0x72, 0x76, 0xcc, 0x07, 0x8f, 0x5e, 0x2e, 0x9c, 0x80, 0x2c, 0xc1, 0x1e, 0xc4, +0xd0, 0x96, 0xb7, 0x5a, 0x55, 0x63, 0x5d, 0x96, 0x67, 0x84, 0xa3, 0x89, 0xfc, 0xc5, 0xc8, 0x17, +0x5c, 0xe0, 0xf2, 0xab, 0x57, 0x8f, 0xc5, 0xa3, 0x6a, 0xb5, 0xbc, 0xe1, 0x3d, 0xc5, 0x47, 0x84, +0xf5, 0x29, 0x0f, 0x45, 0x1c, 0xc3, 0x73, 0x87, 0x47, 0x46, 0xaa, 0x82, 0xc7, 0xe0, 0xdb, 0xc8, +0x82, 0xe1, 0x8c, 0xd0, 0x65, 0x9e, 0xb3, 0xb2, 0xdf, 0x23, 0xf6, 0xb5, 0xd0, 0x9c, 0xd3, 0x02, +0x33, 0xca, 0xd7, 0xb2, 0x80, 0xe1, 0x33, 0x3b, 0x8d, 0xe7, 0xc5, 0x90, 0x69, 0x64, 0x07, 0xcc, +0x45, 0x41, 0xee, 0x4c, 0x83, 0x3e, 0xac, 0xe5, 0x90, 0xf1, 0x59, 0x46, 0xee, 0x0a, 0x5b, 0x65, +0xf8, 0x4e, 0x36, 0x0c, 0xb3, 0x39, 0xd6, 0x21, 0xbb, 0x3a, 0x8b, 0xe7, 0x2f, 0xc2, 0x7c, 0xc6, +0x81, 0xad, 0x5f, 0x49, 0x21, 0xff, 0x9a, 0xf7, 0x0e, 0x68, 0xe1, 0xbf, 0x23, 0x15, 0xb6, 0xf3, +0x9e, 0x5f, 0x4f, 0x1b, 0x37, 0xb5, 0x39, 0xf1, 0xb6, 0xcf, 0xbb, 0x2f, 0x4b, 0x52, 0x38, 0x49, +0x6d, 0x95, 0x70, 0xdb, 0x19, 0xdc, 0xa9, 0x42, 0x38, 0xc3, 0x90, 0x8f, 0x18, 0x9a, 0x54, 0xb3, +0x20, 0x07, 0x23, 0x9b, 0x75, 0xc6, 0x8c, 0xfe, 0x04, 0x20, 0x17, 0x5e, 0x1c, 0x93, 0xb2, 0x2a, +0x43, 0x41, 0xff, 0x81, 0xe0, 0x45, 0xed, 0x98, 0x26, 0xff, 0xda, 0x05, 0x41, 0x33, 0x96, 0x03, +0x07, 0xec, 0x78, 0x0b, 0xf9, 0x00, 0xc8, 0xbc, 0x23, 0x05, 0xaf, 0x71, 0xae, 0x62, 0x86, 0x4d, +0x24, 0x7b, 0xe1, 0x9e, 0x2e, 0xf0, 0x35, 0x13, 0x57, 0x59, 0x3f, 0x96, 0x58, 0x1d, 0x10, 0x0b, +0x40, 0x53, 0x8b, 0xfe, 0x76, 0xb7, 0x96, 0xa8, 0xfb, 0xcc, 0x9b, 0x62, 0xdf, 0x90, 0x86, 0xf7, +0xbc, 0x23, 0x9d, 0xb5, 0x1a, 0xc3, 0xc9, 0x2c, 0x53, 0x32, 0xca, 0x41, 0xd2, 0xc2, 0x63, 0x0a, +0xcd, 0x25, 0xd4, 0xd9, 0x0d, 0x8e, 0xd2, 0x1c, 0xed, 0x39, 0x4a, 0x79, 0x84, 0x97, 0x06, 0x55, +0x95, 0x2b, 0xe5, 0xb3, 0x25, 0xeb, 0xe1, 0xd3, 0x5d, 0x8a, 0x1e, 0x21, 0xe1, 0x05, 0xd6, 0xd9, +0x44, 0x3e, 0xfc, 0x3b, 0x74, 0xbb, 0x0d, 0xe1, 0xc3, 0xdf, 0x58, 0x00, 0x7c, 0x2c, 0xd6, 0x06, +0xc4, 0xa1, 0x8e, 0x19, 0x4e, 0xde, 0x63, 0xd4, 0x61, 0xda, 0x42, 0xac, 0x22, 0x96, 0xd6, 0xd2, +0x6c, 0x4c, 0x71, 0x4a, 0x4a, 0xc3, 0xd7, 0x99, 0x4e, 0x4e, 0xab, 0x08, 0xe9, 0xe9, 0x70, 0xc5, +0x50, 0x15, 0xc0, 0x09, 0x52, 0xd4, 0x10, 0x0f, 0x00, 0x5c, 0xc0, 0x11, 0x95, 0xef, 0xa1, 0x93, +0x8a, 0xf2, 0x0b, 0xe1, 0x76, 0x07, 0x0c, 0x94, 0x66, 0x00, 0x0b, 0x65, 0x2f, 0x96, 0x1d, 0x93, +0x42, 0x79, 0xdc, 0x4d, 0xf4, 0x94, 0xea, 0x8a, 0x85, 0xe3, 0xd8, 0x16, 0xc9, 0x08, 0xef, 0x63, +0xac, 0xac, 0xfe, 0x8e, 0xdb, 0x86, 0x09, 0xad, 0xb9, 0x2e, 0x93, 0x6f, 0x10, 0x9d, 0xb0, 0xca, +0xdf, 0xdd, 0x9f, 0x2a, 0xfc, 0x32, 0xc3, 0xc0, 0x46, 0xbc, 0x72, 0xc4, 0x11, 0xf4, 0x11, 0x29, +0x7a, 0xbf, 0x8f, 0x29, 0x37, 0xc5, 0x98, 0xc2, 0x59, 0x40, 0x78, 0xd4, 0xb2, 0x0e, 0x0a, 0x47, +0xb5, 0xad, 0xa4, 0x7a, 0x7b, 0x9e, 0x5d, 0x17, 0x80, 0x75, 0x0c, 0x47, 0x96, 0xa2, 0xc2, 0x6b, +0xb8, 0xb6, 0xcc, 0x15, 0xa5, 0x4a, 0x27, 0xae, 0xe3, 0x9e, 0xe1, 0xc2, 0xcc, 0x12, 0x66, 0x4e, +0xdd, 0x74, 0x19, 0xd0, 0x48, 0x70, 0xa7, 0x19, 0x93, 0x12, 0xf9, 0x81, 0xf7, 0x1e, 0xe0, 0x95, +0x64, 0xc5, 0x92, 0x9d, 0x6b, 0xa2, 0x6f, 0xce, 0x57, 0x24, 0xd8, 0x71, 0xe5, 0x34, 0xad, 0x8c, +0xc4, 0xa1, 0x30, 0x37, 0xdc, 0x5b, 0xd1, 0xdb, 0xec, 0x9d, 0x7e, 0x38, 0x18, 0x38, 0xdb, 0x85, +0xe0, 0x4c, 0x50, 0xf4, 0x5d, 0x8c, 0xb1, 0x3d, 0xc7, 0x11, 0xd1, 0x26, 0x75, 0xb3, 0x86, 0x69, +0x5d, 0xa5, 0x44, 0x05, 0x93, 0x6a, 0x36, 0x63, 0x12, 0x15, 0x94, 0x84, 0x15, 0xc8, 0x73, 0x63, +0xc4, 0xfc, 0xa4, 0x37, 0x75, 0x56, 0x2d, 0xbf, 0x95, 0x54, 0x84, 0xb1, 0x3c, 0xb1, 0xa7, 0x2b, +0x01, 0x20, 0xce, 0xab, 0xe4, 0x79, 0x26, 0x66, 0x84, 0x60, 0xf7, 0x50, 0x81, 0x59, 0x0a, 0x75, +0x32, 0x68, 0xe5, 0x66, 0x4e, 0xc0, 0x8c, 0xe3, 0x81, 0x1a, 0xd5, 0x34, 0x0b, 0x2e, 0x37, 0x6d, +0x4d, 0x4b, 0x0e, 0xef, 0xb8, 0x5e, 0x08, 0x25, 0xea, 0x86, 0x3b, 0x4d, 0xd9, 0x88, 0x6d, 0x1d, +0x93, 0x68, 0x3a, 0x50, 0xba, 0xf0, 0x2f, 0x24, 0x19, 0x39, 0xcd, 0xe6, 0xcc, 0x78, 0xb7, 0x47, +0x91, 0x1a, 0x6e, 0xbf, 0x7f, 0x72, 0xa2, 0xe9, 0x04, 0xfa, 0xcb, 0xca, 0x8b, 0x04, 0xb8, 0x7e, +0x91, 0xc9, 0x9e, 0x0b, 0x63, 0x00, 0xa4, 0xd9, 0x3a, 0xac, 0x15, 0x91, 0xc5, 0x6a, 0xa4, 0x31, +0x34, 0x89, 0xa3, 0x77, 0x5d, 0x73, 0x6e, 0x14, 0xbe, 0x10, 0xf6, 0x40, 0x94, 0x4e, 0xd8, 0xad, +0x5c, 0x64, 0x07, 0x87, 0xd5, 0x73, 0xf2, 0x6b, 0x49, 0x43, 0xae, 0x9d, 0xca, 0x5e, 0x63, 0x65, +0x1b, 0xeb, 0xc3, 0x84, 0x55, 0x77, 0x72, 0xf8, 0x68, 0xc6, 0xcb, 0xb2, 0xcf, 0xdf, 0x08, 0x74, +0xf0, 0xa2, 0xd9, 0xfa, 0x07, 0x2d, 0x07, 0xd6, 0x71, 0x03, 0x22, 0x01, 0x09, 0x34, 0xd8, 0xfd, +0x21, 0xd8, 0x68, 0x5c, 0x42, 0x16, 0x6a, 0x9f, 0xbe, 0x6e, 0xa5, 0xcc, 0xa9, 0x49, 0x81, 0x77, +0xd5, 0x46, 0x8d, 0x3d, 0x47, 0x2e, 0x7d, 0x90, 0x79, 0x5b, 0xab, 0x9c, 0xb2, 0x38, 0x1f, 0x09, +0x46, 0x1b, 0xc6, 0x85, 0x09, 0x69, 0xf5, 0x35, 0x51, 0x3c, 0xbc, 0x17, 0xb3, 0xa4, 0x89, 0x12, +0x2d, 0xa8, 0xd2, 0x3c, 0xe3, 0xd2, 0x07, 0xd7, 0x5c, 0x2f, 0xc6, 0xdb, 0xc4, 0x69, 0x7c, 0xeb, +0x7c, 0xe3, 0x4c, 0xbd, 0x8d, 0x2e, 0xb1, 0xce, 0x37, 0x34, 0xf1, 0x41, 0x58, 0x69, 0xba, 0x9d, +0x99, 0x49, 0x08, 0x16, 0x67, 0x7c, 0xc0, 0x8a, 0xbb, 0x0a, 0x66, 0x3e, 0x81, 0x06, 0xcb, 0x3a, +0x34, 0x1e, 0x0a, 0x46, 0x10, 0x96, 0xdf, 0x8e, 0xcd, 0x39, 0x60, 0x63, 0x4e, 0xe8, 0x92, 0x0a, +0xce, 0xb2, 0x12, 0xe1, 0xa7, 0x73, 0x27, 0x11, 0x22, 0x32, 0x16, 0xaa, 0xcc, 0x6b, 0xb4, 0xf7, +0x28, 0x60, 0x72, 0x59, 0x93, 0x28, 0xf5, 0x81, 0x00, 0x9e, 0x50, 0x41, 0x16, 0x67, 0x9e, 0xce, +0x73, 0x78, 0x1b, 0x72, 0x73, 0xad, 0x25, 0xab, 0xbc, 0x4d, 0x41, 0x43, 0xcc, 0x67, 0x96, 0x3e, +0xfd, 0x67, 0x8d, 0x5a, 0xd2, 0x66, 0x0c, 0x66, 0xa9, 0xd6, 0x72, 0xab, 0x7d, 0x73, 0xb3, 0xa8, +0xc9, 0xf7, 0xde, 0x51, 0x76, 0xc4, 0x3b, 0xc6, 0xb5, 0x91, 0xa8, 0x71, 0x9a, 0xa1, 0x6e, 0xea, +0x84, 0x93, 0x25, 0x60, 0x84, 0x48, 0x08, 0x43, 0x86, 0x9c, 0x58, 0xcc, 0xb0, 0xe0, 0xbb, 0x15, +0xe1, 0xad, 0x31, 0x62, 0x6f, 0x24, 0xc1, 0xbb, 0x7d, 0x26, 0x89, 0xb4, 0xc5, 0xc9, 0x68, 0xe3, +0x4a, 0x49, 0x32, 0xc6, 0x55, 0xd3, 0x77, 0x18, 0x0a, 0x9c, 0xce, 0x4d, 0x2a, 0x3b, 0xc7, 0x6c, +0x4b, 0xd9, 0x06, 0xa7, 0x00, 0xc8, 0x5b, 0x05, 0x4d, 0x73, 0x5a, 0x0e, 0xba, 0x06, 0x00, 0xad, +0x74, 0xa5, 0x38, 0xba, 0xe9, 0x35, 0xa9, 0x6e, 0xe4, 0x1c, 0x7b, 0x27, 0xec, 0x8d, 0x4c, 0xd7, +0xe9, 0xef, 0x77, 0x3a, 0xb7, 0xb9, 0xf2, 0x79, 0xec, 0x8b, 0xf7, 0xda, 0x3e, 0x16, 0x6e, 0x22, +0x82, 0xf4, 0x8d, 0x10, 0x8a, 0x67, 0xa9, 0x81, 0x04, 0x37, 0xd0, 0xa3, 0x78, 0x71, 0x6a, 0xe1, +0xec, 0x9c, 0x6b, 0xc3, 0xe9, 0x18, 0xf4, 0x63, 0x2c, 0x4e, 0x25, 0xcc, 0x06, 0xc4, 0xa6, 0xe7, +0x69, 0x87, 0x40, 0x11, 0x50, 0xaa, 0xd4, 0x90, 0x73, 0xc1, 0x7a, 0xe6, 0x7b, 0x13, 0x7c, 0xdc, +0xfe, 0xe9, 0x8c, 0xec, 0x68, 0x2e, 0xdf, 0xe8, 0x0e, 0x81, 0x64, 0x71, 0x25, 0x1c, 0x8b, 0x24, +0x5b, 0x16, 0x01, 0x16, 0x8e, 0x30, 0x55, 0xec, 0x7d, 0x74, 0x8e, 0x89, 0x91, 0x19, 0xf0, 0x33, +0x2d, 0xed, 0x72, 0xc4, 0xcf, 0x39, 0x7d, 0x78, 0xd4, 0x26, 0x65, 0xcd, 0x2b, 0x11, 0xad, 0x5d, +0x40, 0x13, 0x97, 0x66, 0xb5, 0xfc, 0xad, 0x9f, 0x32, 0x7b, 0xfd, 0x5b, 0xa4, 0xb4, 0xe9, 0x3a, +0x04, 0x40, 0xb1, 0xcc, 0x6a, 0x5e, 0x14, 0x88, 0x80, 0xeb, 0xcf, 0xd8, 0x7f, 0x99, 0x39, 0x87, +0x73, 0x2d, 0xe1, 0x11, 0x7e, 0x98, 0x6a, 0x7a, 0x14, 0xf1, 0x21, 0xeb, 0xad, 0xfc, 0xa9, 0xef, +0x2a, 0x23, 0x93, 0xa1, 0x83, 0xa6, 0x1b, 0xe9, 0x13, 0xf6, 0x22, 0xe5, 0x49, 0xc8, 0x40, 0x91, +0xf8, 0x8a, 0x52, 0x92, 0xb7, 0x7e, 0xeb, 0xd0, 0x76, 0xcb, 0x0f, 0x26, 0xc4, 0xb2, 0x46, 0x54, +0xb7, 0x85, 0x16, 0xba, 0x35, 0x43, 0xd3, 0xda, 0x13, 0x55, 0x81, 0xd1, 0xc1, 0x70, 0x95, 0x30, +0xf3, 0xbf, 0x4a, 0xa8, 0x29, 0xdf, 0x3c, 0x4a, 0xaf, 0x63, 0x09, 0xb9, 0x87, 0x1f, 0xe6, 0xad, +0xf6, 0x62, 0xc7, 0x16, 0x12, 0xbb, 0xc5, 0x8d, 0xa5, 0x17, 0xfb, 0x2f, 0xd7, 0x14, 0xea, 0x39, +0x68, 0x8f, 0x9a, 0x66, 0x92, 0x23, 0x89, 0xd1, 0x29, 0x58, 0x06, 0xd5, 0x6f, 0xf9, 0xf8, 0xd9, +0x67, 0xa8, 0x64, 0xfe, 0x60, 0x82, 0x16, 0xd2, 0xe2, 0x4d, 0xbb, 0xe6, 0x53, 0x8d, 0xdd, 0xb2, +0xac, 0x4b, 0x9e, 0x8e, 0x1b, 0x0c, 0x97, 0xcc, 0x2c, 0xe8, 0x22, 0xc4, 0xb4, 0xd7, 0xb1, 0x7f, +0xe9, 0x57, 0x83, 0x5a, 0x6f, 0xe5, 0xc5, 0xb1, 0xf2, 0x47, 0x7d, 0x5c, 0x9e, 0x00, 0xd2, 0x22, +0xf5, 0xc2, 0x23, 0x58, 0x4d, 0x62, 0x80, 0xe1, 0x63, 0x5c, 0x2a, 0x41, 0x12, 0x22, 0x23, 0x4f, +0xe9, 0xdf, 0xa5, 0x6b, 0xd7, 0x69, 0x34, 0x90, 0x2c, 0xa4, 0xfe, 0x27, 0xed, 0x62, 0xfb, 0x4b, +0x4f, 0x33, 0xc5, 0x89, 0x87, 0xb1, 0xf4, 0x86, 0x93, 0xa1, 0x48, 0xdd, 0xd5, 0xa3, 0x6f, 0xd3, +0x08, 0x4e, 0x9f, 0x1a, 0xdd, 0xce, 0x27, 0x27, 0xc7, 0x50, 0x85, 0x2b, 0xe5, 0xf4, 0xea, 0x20, +0x52, 0xdf, 0xe6, 0xc7, 0x5a, 0xe5, 0xa9, 0x6c, 0x4b, 0xbc, 0x4e, 0xd4, 0x8b, 0xb1, 0xa9, 0xcc, +0x13, 0x95, 0x50, 0xd0, 0x74, 0x08, 0xd0, 0x9e, 0x9a, 0xe8, 0xf7, 0xf1, 0x8d, 0x15, 0x1d, 0xdc, +0xe1, 0x78, 0xc7, 0x8e, 0xd6, 0x14, 0x7c, 0xa7, 0x28, 0x6c, 0xd2, 0x4e, 0x78, 0x5d, 0x0c, 0x25, +0xe8, 0x8e, 0xeb, 0xae, 0xcf, 0xfa, 0xb6, 0x3b, 0x6d, 0x50, 0x33, 0xca, 0xdd, 0x78, 0x81, 0xed, +0xfc, 0x93, 0x7d, 0x87, 0x76, 0x89, 0x25, 0xd6, 0xfb, 0xd1, 0x4c, 0x7b, 0x50, 0x39, 0x13, 0xd0, +0x46, 0xc3, 0x0f, 0x21, 0x6e, 0x2c, 0x53, 0xa1, 0x5a, 0x11, 0x98, 0xea, 0x71, 0x83, 0x2f, 0x7a, +0xda, 0x45, 0x7d, 0x48, 0xaa, 0x2b, 0x8e, 0x19, 0xdd, 0x71, 0x18, 0x3c, 0x2a, 0x90, 0xf4, 0x4a, +0x90, 0xbd, 0x3a, 0xdf, 0x2f, 0x36, 0xc4, 0x81, 0xe0, 0xe5, 0x17, 0xff, 0xc8, 0x4e, 0x8b, 0x76, +0x86, 0x00, 0xba, 0x21, 0x80, 0x5a, 0xdd, 0x49, 0x7d, 0x54, 0x5f, 0xc5, 0x7c, 0x02, 0xb1, 0x5c, +0x03, 0xf7, 0x8a, 0xc3, 0xab, 0xb5, 0xb3, 0x10, 0x58, 0x3c, 0xac, 0xc3, 0xa1, 0x4b, 0x0f, 0x4b, +0xda, 0x6f, 0xb3, 0xcf, 0xd7, 0x2a, 0xf8, 0x8e, 0x2b, 0xf8, 0x56, 0xb1, 0x0e, 0xb7, 0x41, 0x75, +0x1c, 0xb9, 0x6c, 0x76, 0x8e, 0xa8, 0x80, 0x2f, 0xb6, 0x64, 0x24, 0x4e, 0xd3, 0x23, 0xb1, 0x05, +0x1f, 0xe6, 0x6e, 0x07, 0x1d, 0x6e, 0x7f, 0xcc, 0xc9, 0xba, 0x58, 0x76, 0xad, 0x90, 0x61, 0x6a, +0x03, 0x76, 0x14, 0xc3, 0x51, 0x9f, 0xb4, 0xaa, 0xe2, 0xe1, 0xd2, 0xf0, 0xdc, 0x83, 0xf4, 0x07, +0xad, 0x03, 0xe5, 0x36, 0xa7, 0x64, 0x95, 0xc3, 0xce, 0x98, 0xac, 0xff, 0x5e, 0xeb, 0x85, 0xb9, +0xdd, 0x57, 0x16, 0xed, 0xc0, 0x9c, 0xab, 0x75, 0x85, 0x23, 0x9d, 0xb4, 0xea, 0xaf, 0xad, 0x5f, +0x88, 0xc0, 0x97, 0x52, 0x6d, 0xde, 0x31, 0x1a, 0xfe, 0x78, 0x6b, 0x8e, 0x0f, 0x70, 0xf8, 0xf5, +0xcc, 0x9f, 0xa3, 0x9b, 0xbe, 0x54, 0x04, 0xac, 0xcc, 0x78, 0x49, 0xb2, 0xcb, 0x2a, 0x99, 0x7d, +0xce, 0x4b, 0x2f, 0xcc, 0xa7, 0xa1, 0x72, 0x53, 0x95, 0x95, 0x10, 0xd1, 0x6b, 0x69, 0xd7, 0x89, +0xaf, 0xb8, 0xe6, 0xba, 0xa3, 0x26, 0x92, 0x8b, 0x01, 0x92, 0x6f, 0x72, 0x64, 0x24, 0x08, 0x9b, +0x99, 0x32, 0x08, 0xe5, 0x29, 0x27, 0xb2, 0x01, 0xec, 0xa7, 0x1d, 0xbe, 0xeb, 0xa4, 0x08, 0x4f, +0x84, 0xe2, 0x90, 0x32, 0x5a, 0x91, 0xf0, 0xa1, 0x91, 0x70, 0x65, 0xa7, 0xd1, 0x00, 0xa2, 0x65, +0x41, 0x77, 0xcb, 0xef, 0x91, 0x42, 0x2f, 0x49, 0x2b, 0x29, 0x6c, 0x5b, 0xf1, 0xc8, 0x17, 0xa1, +0x6e, 0xd5, 0x7c, 0xab, 0x56, 0xf9, 0x0d, 0x22, 0xae, 0x4d, 0x9d, 0xd1, 0x1a, 0xa7, 0x75, 0x01, +0xde, 0x55, 0x6a, 0x5d, 0xcc, 0x71, 0xc9, 0x63, 0x23, 0xdf, 0xc7, 0x44, 0x51, 0x5b, 0x77, 0x44, +0xfe, 0x9f, 0x58, 0x09, 0x2e, 0x7a, 0x1e, 0xfc, 0xae, 0xf1, 0xf6, 0x4b, 0xa0, 0xaf, 0x12, 0x57, +0x17, 0xa6, 0xdb, 0x10, 0x2e, 0x4b, 0x7e, 0x39, 0x65, 0xd0, 0x51, 0xd4, 0xf3, 0x21, 0x27, 0xcd, +0x07, 0x43, 0x06, 0x75, 0x0a, 0xb3, 0xf8, 0x2a, 0x3a, 0xa4, 0xdd, 0x87, 0xc7, 0xc7, 0x90, 0x56, +0xcc, 0x1d, 0x19, 0x63, 0xcd, 0xfa, 0x8b, 0xc1, 0x21, 0xef, 0xea, 0x99, 0x4e, 0x30, 0x9c, 0xec, +0xf2, 0x81, 0x43, 0xec, 0x95, 0x6d, 0x02, 0xef, 0x09, 0x87, 0xce, 0xde, 0xc9, 0xaa, 0xbb, 0xc3, +0x16, 0xc5, 0x40, 0x3b, 0x6e, 0xa2, 0x8a, 0xb2, 0x3c, 0xdc, 0xc0, 0x38, 0x41, 0x2a, 0xad, 0x0f, +0x54, 0x14, 0xa4, 0xeb, 0xdf, 0x3a, 0x25, 0x87, 0x70, 0x1c, 0xe0, 0xfc, 0x5f, 0xe3, 0x11, 0x34, +0x66, 0x37, 0x3d, 0xbe, 0xde, 0xcf, 0xcb, 0x4c, 0x37, 0x6a, 0x94, 0xaa, 0xcf, 0xe3, 0x51, 0xde, +0x32, 0xea, 0xbc, 0x40, 0x8f, 0xd2, 0x80, 0x76, 0x31, 0xc3, 0x41, 0xc0, 0xe8, 0x4a, 0x04, 0x8f, +0x4b, 0xa0, 0xa0, 0xd3, 0x19, 0x4b, 0x15, 0x8d, 0x41, 0xc1, 0x57, 0x06, 0x66, 0xe6, 0xca, 0x93, +0x05, 0x4d, 0x42, 0xeb, 0xb6, 0x8c, 0xf1, 0x06, 0x92, 0x4c, 0x97, 0x86, 0x8a, 0x98, 0x99, 0x6e, +0xf9, 0xa4, 0x64, 0x29, 0xe2, 0x5d, 0xb5, 0x4f, 0x02, 0x48, 0x19, 0x3c, 0x82, 0x46, 0xc1, 0x01, +0x33, 0xb1, 0x16, 0xe2, 0x6a, 0xda, 0x4e, 0x02, 0xcd, 0x95, 0x73, 0x34, 0x34, 0xc0, 0xa1, 0x2d, +0xb4, 0xb9, 0xc3, 0x9c, 0x62, 0xe2, 0x6a, 0x88, 0xcc, 0xbf, 0xd2, 0xc2, 0xe3, 0xd6, 0x88, 0x26, +0x4e, 0xbe, 0xc3, 0x0d, 0xf5, 0x5b, 0x8f, 0x9a, 0xb8, 0xc4, 0xf6, 0xa6, 0x2c, 0x8d, 0x6f, 0x6c, +0xb4, 0xa4, 0xcd, 0x2d, 0xa4, 0x60, 0x4c, 0xa9, 0x6f, 0x9d, 0x15, 0x01, 0xf0, 0x17, 0xcb, 0x72, +0x21, 0x32, 0x01, 0x54, 0x70, 0xe4, 0xef, 0x59, 0x78, 0x3e, 0xba, 0xe6, 0xb6, 0x68, 0x0d, 0xdf, +0x3b, 0x58, 0xe5, 0x74, 0xfd, 0x35, 0x49, 0xd4, 0x96, 0x0b, 0xf4, 0x99, 0x2e, 0x34, 0x37, 0xf2, +0xf0, 0x5f, 0x0a, 0x94, 0x2d, 0x71, 0x16, 0xef, 0x41, 0xc8, 0x32, 0x1f, 0xd4, 0x08, 0x02, 0xfc, +0x53, 0xa3, 0xcf, 0x5c, 0xb0, 0xf1, 0x55, 0x13, 0x54, 0xff, 0xe9, 0x55, 0x51, 0xdf, 0x9a, 0xff, +0x61, 0xc7, 0x10, 0xe7, 0xd8, 0xf8, 0x7b, 0x04, 0xdf, 0x00, 0xd8, 0x23, 0xc9, 0x33, 0x08, 0xf8, +0x79, 0x0a, 0x6e, 0xb9, 0x5a, 0x0c, 0xce, 0x9e, 0x7c, 0x5e, 0xc3, 0xb0, 0x6e, 0xfd, 0x66, 0xcd, +0xab, 0x82, 0x73, 0xe4, 0xd2, 0xc3, 0xbc, 0x52, 0xfc, 0xc1, 0x43, 0xfd, 0xd7, 0x8c, 0xba, 0xe2, +0xde, 0x7d, 0x75, 0xfa, 0x65, 0x52, 0x16, 0xa5, 0xee, 0xe0, 0x61, 0x8f, 0x2e, 0xcf, 0x78, 0xd1, +0xff, 0x14, 0x60, 0xd0, 0xc1, 0x45, 0xe1, 0x0a, 0x71, 0x51, 0xd9, 0xd7, 0xa3, 0x53, 0x1a, 0x7d, +0x56, 0xe9, 0x0a, 0x9f, 0xea, 0xea, 0x79, 0xe5, 0x53, 0x84, 0xa1, 0xcc, 0xe0, 0xfb, 0x1b, 0x84, +0x2f, 0x84, 0x90, 0xcc, 0x64, 0x18, 0x3e, 0xef, 0xaf, 0xc5, 0xe0, 0x1f, 0x8c, 0x8b, 0xf1, 0xc9, +0x09, 0xc9, 0x5d, 0x39, 0x04, 0x74, 0x96, 0x32, 0xab, 0x7a, 0x51, 0x1f, 0xd6, 0xb0, 0x31, 0x76, +0xaa, 0x25, 0xb8, 0xd6, 0x9d, 0xcb, 0x79, 0x89, 0x5c, 0xfa, 0x05, 0x2a, 0xb6, 0x54, 0x67, 0x7b, +0x5f, 0x41, 0x6c, 0xac, 0xbf, 0xdf, 0x03, 0xdf, 0x18, 0xe6, 0x63, 0x53, 0xa6, 0x10, 0x24, 0x69, +0xcf, 0x26, 0x4a, 0x5e, 0x89, 0x8c, 0x77, 0xd1, 0xd9, 0x6d, 0x2d, 0xfb, 0xda, 0xf0, 0xa2, 0xef, +0x6b, 0x33, 0xe5, 0xe6, 0x7a, 0x9c, 0xfe, 0x13, 0x79, 0x04, 0x8e, 0x7c, 0xa3, 0x6a, 0xb4, 0xc0, +0x64, 0x5e, 0xed, 0x71, 0xf4, 0x3d, 0x47, 0x9f, 0xc4, 0xa6, 0x31, 0x0b, 0xed, 0x0d, 0x8a, 0xd2, +0x09, 0x01, 0x14, 0x34, 0x4e, 0x3d, 0x2b, 0x09, 0x45, 0x96, 0xed, 0x41, 0x41, 0x8c, 0x24, 0x18, +0x90, 0x5d, 0xd8, 0x21, 0x4c, 0x45, 0x3f, 0xf7, 0x17, 0xc9, 0xfb, 0x20, 0x57, 0x13, 0xb1, 0xcc, +0x3a, 0xa4, 0x35, 0xd8, 0x80, 0xe9, 0x31, 0xc9, 0x42, 0xc9, 0xf2, 0x5d, 0xa9, 0x1c, 0xf5, 0x6f, +0x82, 0x4b, 0x7d, 0xb0, 0xd8, 0x93, 0x3f, 0xff, 0x4d, 0x6c, 0x39, 0x3c, 0xbd, 0xc3, 0x7d, 0x7e, +0xb6, 0x44, 0xb6, 0x6f, 0x89, 0xdc, 0x6f, 0x5b, 0xd7, 0x4b, 0x73, 0x46, 0x31, 0x33, 0xe2, 0x4c, +0x7c, 0x2c, 0xa0, 0x16, 0x55, 0x3e, 0x13, 0xf4, 0xfe, 0x84, 0x3e, 0x78, 0x34, 0xbc, 0x4c, 0x24, +0x9f, 0x1c, 0xd1, 0x66, 0xcf, 0xc3, 0x02, 0xf2, 0xa8, 0xe5, 0xcf, 0xe7, 0xf0, 0xf5, 0x55, 0x47, +0xad, 0xf7, 0x40, 0xde, 0x04, 0x27, 0x3a, 0x8b, 0x31, 0x68, 0xae, 0xa2, 0x8c, 0xae, 0xd9, 0x4a, +0x65, 0xf9, 0x9e, 0x28, 0x4f, 0xce, 0xa2, 0x78, 0x3b, 0x9a, 0xba, 0x3c, 0x31, 0x6e, 0x8a, 0x7a, +0x6f, 0x85, 0x5f, 0x33, 0xb3, 0x6d, 0xee, 0x6a, 0xb1, 0x0a, 0x64, 0x27, 0x53, 0x9f, 0xf9, 0x94, +0x81, 0x4c, 0xe5, 0x71, 0x74, 0x00, 0xff, 0xcf, 0x64, 0xf7, 0x12, 0x0e, 0x05, 0x89, 0xdf, 0x8c, +0x12, 0xef, 0xe8, 0x8a, 0x57, 0x4d, 0x16, 0x55, 0x3b, 0x4d, 0x93, 0xe5, 0x87, 0xbd, 0x72, 0x1b, +0x16, 0xaa, 0x8b, 0xf6, 0xd1, 0x12, 0xef, 0xec, 0x3d, 0x8c, 0x59, 0xef, 0xcc, 0x2c, 0x19, 0xfa, +0xc2, 0x95, 0x88, 0xf4, 0xcf, 0x2d, 0x6c, 0x6e, 0x90, 0x78, 0x24, 0xdc, 0x27, 0x63, 0x59, 0x89, +0x33, 0x3d, 0x31, 0x58, 0x3c, 0xb4, 0x86, 0x20, 0xeb, 0xc7, 0x1e, 0xc9, 0x1e, 0xef, 0x8b, 0x98, +0x7a, 0xc2, 0x0a, 0x12, 0x50, 0xe9, 0x2d, 0x20, 0x6e, 0x0a, 0xd4, 0x69, 0xb7, 0xdd, 0xac, 0x96, +0xbc, 0xfc, 0xc0, 0xa3, 0xc6, 0xbd, 0x3f, 0xbe, 0x91, 0x1b, 0x9d, 0xda, 0x1b, 0xe6, 0x89, 0x84, +0xfd, 0xcf, 0x5b, 0x1b, 0x7c, 0xf6, 0xa3, 0xe9, 0xe5, 0x10, 0xeb, 0xd9, 0xab, 0x23, 0xe7, 0x09, +0x26, 0xa6, 0x27, 0x0a, 0x67, 0xfe, 0x2d, 0xab, 0x0e, 0x11, 0x6f, 0x04, 0x07, 0x5c, 0x4e, 0x86, +0x28, 0x5c, 0xd7, 0x79, 0xb6, 0x88, 0x77, 0x63, 0x25, 0x1c, 0x86, 0x28, 0xf1, 0x07, 0x95, 0x51, +0x34, 0xff, 0x93, 0x81, 0xe6, 0xe4, 0x66, 0xf6, 0xcd, 0x4b, 0xd3, 0x9a, 0x27, 0x6f, 0xaa, 0xcc, +0x10, 0x01, 0xff, 0x3c, 0x85, 0xad, 0x3a, 0x15, 0x0b, 0x32, 0x50, 0x40, 0x29, 0x4a, 0xaa, 0xf4, +0x26, 0xe3, 0x16, 0x63, 0x9b, 0x0b, 0x79, 0xf7, 0x89, 0xa8, 0xa4, 0x6c, 0x92, 0x5d, 0x8b, 0xc7, +0x47, 0xab, 0xc3, 0x80, 0x12, 0x76, 0xd9, 0xca, 0x8c, 0x90, 0xb5, 0x74, 0x6c, 0x8d, 0x7b, 0x74, +0xb0, 0xf4, 0x29, 0xad, 0x81, 0xec, 0xbb, 0x62, 0x19, 0x69, 0x23, 0xbb, 0xe1, 0x42, 0x04, 0x2a, +0xa1, 0xb7, 0xaa, 0xd1, 0x70, 0xb2, 0x7e, 0xc4, 0x13, 0x61, 0xf8, 0xdc, 0x18, 0x88, 0x6d, 0x3d, +0x68, 0x7d, 0xba, 0x27, 0x5d, 0x8a, 0x73, 0x90, 0x4f, 0x1f, 0x31, 0xe7, 0x37, 0x95, 0x35, 0xb7, +0x21, 0xc4, 0x0a, 0x77, 0xe4, 0x7c, 0x13, 0x4d, 0x10, 0xae, 0x02, 0xaf, 0xd7, 0xeb, 0x8f, 0x14, +0x83, 0x2a, 0xc6, 0x75, 0x53, 0xac, 0xdc, 0x56, 0x9f, 0x6f, 0xad, 0xbd, 0x44, 0xa2, 0x37, 0x75, +0x55, 0x50, 0xe8, 0xa3, 0xb6, 0xb7, 0x0c, 0x4b, 0x38, 0x57, 0xb5, 0x4b, 0x09, 0xe0, 0xa7, 0xcb, +0xa2, 0xb0, 0x48, 0x0b, 0x5f, 0x62, 0xe4, 0xa7, 0xa1, 0xe2, 0x63, 0xe9, 0x07, 0xc0, 0x1b, 0x0c, +0x14, 0x61, 0x1e, 0xbb, 0x35, 0x0a, 0x24, 0x31, 0x78, 0x7b, 0xb8, 0x2f, 0x98, 0x6f, 0xdc, 0xa0, +0x39, 0x5f, 0xe7, 0x9c, 0x48, 0xba, 0x76, 0x6f, 0x10, 0x17, 0xc9, 0x6a, 0x52, 0x34, 0xee, 0x1e, +0x40, 0x8a, 0x93, 0x75, 0xcc, 0x8f, 0x8c, 0x62, 0xab, 0xfe, 0xff, 0x1f, 0xf2, 0xc4, 0x53, 0xbd, +0xe0, 0x7e, 0xec, 0xd3, 0x60, 0xef, 0xde, 0xa6, 0xd5, 0xdb, 0x5e, 0x4a, 0x9c, 0xf1, 0x19, 0xac, +0xd4, 0x19, 0xa3, 0xfd, 0x3f, 0x8f, 0x30, 0xeb, 0xa6, 0x5a, 0x53, 0x24, 0x09, 0x16, 0x1b, 0xd9, +0x51, 0x99, 0x01, 0xec, 0xaf, 0x75, 0xd8, 0xf5, 0xc9, 0x54, 0x3b, 0x35, 0xb6, 0x62, 0x4c, 0x6f, +0x74, 0xaa, 0x97, 0xe8, 0x41, 0x2f, 0xd9, 0x8e, 0x49, 0xc2, 0x50, 0x6d, 0x76, 0xb3, 0x4b, 0x2b, +0xa4, 0x6c, 0xa2, 0x5d, 0x5a, 0x5b, 0x39, 0xed, 0xac, 0x23, 0xe2, 0x19, 0x19, 0x3c, 0xe4, 0x78, +0xb9, 0xfa, 0xd1, 0x44, 0x03, 0xfe, 0x25, 0x88, 0x9e, 0xfc, 0x94, 0x4a, 0x02, 0x7d, 0x62, 0x84, +0xcf, 0x85, 0x9a, 0xc3, 0xd3, 0x3d, 0xdd, 0x01, 0x73, 0x15, 0xd1, 0x04, 0xb4, 0x67, 0xa8, 0x9f, +0x3a, 0x2f, 0xe2, 0x0f, 0xe2, 0xb2, 0x8d, 0x4c, 0xc3, 0x54, 0xbf, 0xff, 0x28, 0xfa, 0xfe, 0x27, +0xe6, 0x90, 0x58, 0xf3, 0x8a, 0x60, 0x64, 0xb0, 0x21, 0xba, 0xc3, 0x16, 0x52, 0xd7, 0xd8, 0x60, +0xd9, 0x67, 0xe9, 0xea, 0x77, 0x05, 0x03, 0xd0, 0x98, 0x40, 0xc7, 0xc7, 0x72, 0xc5, 0x17, 0x4f, +0x31, 0x50, 0xb2, 0xca, 0x66, 0xdb, 0x62, 0xb7, 0x60, 0xac, 0xd7, 0x92, 0x27, 0x79, 0xa5, 0x3e, +0x5a, 0xe9, 0xfd, 0xa4, 0xc1, 0x01, 0x10, 0x52, 0x12, 0x5b, 0xdd, 0xc4, 0x4a, 0x7e, 0x61, 0xfc, +0x33, 0x28, 0xd5, 0xbc, 0xaf, 0x9d, 0xaf, 0xd9, 0xc2, 0x42, 0x73, 0xd7, 0x03, 0x05, 0xec, 0xed, +0x29, 0xa3, 0x87, 0x03, 0xe0, 0x9e, 0xcc, 0x5c, 0xda, 0x88, 0x0d, 0xcf, 0x88, 0x39, 0x3d, 0x36, +0x78, 0xf5, 0x41, 0x66, 0x19, 0x1b, 0x66, 0xbd, 0xf8, 0x6a, 0xff, 0x16, 0xb5, 0xf9, 0xea, 0x20, +0x64, 0x82, 0xf8, 0x1b, 0xd0, 0x93, 0x40, 0x30, 0x8c, 0x6c, 0xae, 0x13, 0xc6, 0x0e, 0xf7, 0x42, +0xe1, 0x6a, 0x16, 0x08, 0x0b, 0x62, 0xca, 0xe0, 0x12, 0x1a, 0x82, 0x1c, 0x00, 0xb4, 0xc7, 0xcd, +0xaf, 0xb7, 0xc3, 0xd9, 0xad, 0x77, 0x2c, 0x97, 0x67, 0x95, 0xa7, 0xcd, 0xc1, 0x3c, 0xb4, 0xc1, +0x51, 0xa1, 0xc4, 0x8f, 0x50, 0xc1, 0x02, 0x72, 0xd0, 0xa8, 0x68, 0xa3, 0x9f, 0xa8, 0x4e, 0xac, +0x17, 0xa5, 0x4c, 0x65, 0x07, 0xaa, 0x6c, 0x17, 0x7f, 0xb0, 0x42, 0xdf, 0x69, 0x0c, 0x59, 0xfa, +0x7c, 0x88, 0x36, 0x7f, 0x87, 0xd1, 0xc2, 0xfc, 0x43, 0xa8, 0x89, 0x87, 0xcc, 0x41, 0xb5, 0xa7, +0x73, 0xc4, 0x5c, 0x13, 0xa1, 0x5e, 0x56, 0xc7, 0x86, 0x0c, 0xf7, 0xcb, 0xc7, 0x0c, 0xa0, 0x2d, +0x77, 0x14, 0xca, 0xfb, 0x5b, 0x71, 0x37, 0xdc, 0x02, 0x70, 0xfa, 0xf8, 0xff, 0x8a, 0xf3, 0x5e, +0x67, 0x9c, 0xd9, 0xd8, 0xe7, 0x12, 0xd6, 0x2a, 0x9f, 0x63, 0x06, 0xea, 0xaa, 0x52, 0x35, 0xe5, +0x22, 0xc5, 0x6c, 0xc9, 0x54, 0xd2, 0x56, 0xfd, 0x78, 0xe1, 0xf3, 0x47, 0xe8, 0x91, 0x8c, 0x33, +0xee, 0x45, 0x23, 0xd0, 0x91, 0xca, 0x6d, 0xf3, 0x63, 0x20, 0xeb, 0x83, 0x4b, 0x46, 0x08, 0x6c, +0x18, 0x3c, 0x4f, 0x67, 0x53, 0x72, 0xa8, 0x58, 0x93, 0x33, 0x63, 0x5a, 0x42, 0xe3, 0xf6, 0x65, +0x82, 0x74, 0xf7, 0x6a, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x00, 0xc5, 0x85, 0x4e, 0xd3, 0xfc, 0x93, 0xd9, 0x57, 0x3d, 0xce, 0x6f, 0xfd, 0x73, 0xae, 0x69, +0xa6, 0xdd, 0xe9, 0xf3, 0xf5, 0x85, 0x8c, 0x41, 0x2a, 0x7f, 0x53, 0x0f, 0xfc, 0xc7, 0xd6, 0xf0, +0x13, 0xc9, 0xc4, 0x2f, 0xab, 0xa1, 0x97, 0x23, 0xab, 0x99, 0x3d, 0x73, 0x9c, 0xd8, 0xb9, 0x56, +0xdf, 0x96, 0xee, 0x18, 0xdc, 0xf8, 0xb2, 0x8b, 0x80, 0x6c, 0x70, 0x3b, 0xf5, 0x36, 0x1b, 0x3a, +0xde, 0x97, 0xef, 0x19, 0xdd, 0xf9, 0xb3, 0x8a, 0x81, 0x6d, 0x71, 0x3a, 0xf4, 0x37, 0x1a, 0x3b, +0xc2, 0x1e, 0xbb, 0xf4, 0xd8, 0x3f, 0xcc, 0x3d, 0x9b, 0x11, 0x0c, 0x26, 0x2f, 0xe5, 0xb2, 0xbe, +0xc1, 0x1d, 0xb8, 0xf7, 0xdb, 0x3c, 0xcf, 0x3e, 0x98, 0x12, 0x0f, 0x25, 0x2c, 0xe6, 0xb1, 0xbd, +0xc1, 0x1d, 0xb8, 0xf7, 0xdb, 0x3c, 0xcf, 0x3e, 0x98, 0x12, 0x0f, 0x25, 0x2c, 0xe6, 0xb1, 0xbd, +0xc1, 0x1d, 0xb8, 0xf7, 0xdb, 0x3c, 0xcf, 0x3e, 0x98, 0x12, 0x0f, 0x25, 0x2c, 0xe6, 0xb1, 0xbd, +0x1b, 0xf1, 0x2b, 0xf5, 0x2e, 0x0e, 0xb8, 0x66, 0x7a, 0xbb, 0x99, 0x09, 0xd6, 0x96, 0xfe, 0xcf, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x9e, 0xda, 0xd7, 0x94, 0x2e, 0x74, 0xba, 0x20, 0x43, 0x19, 0x20, 0x20, 0xda, 0x18, 0xd2, 0xed, +0x1a, 0xf0, 0x2a, 0xf4, 0xff, 0xd4, 0xb0, 0x65, 0xaf, 0x61, 0x91, 0x0a, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x19, 0x40, 0x8d, 0xd5, 0x07, 0xec, 0xa8, 0xa2, 0x63, 0x3a, 0x9a, 0x74, 0xb9, 0x96, 0xb1, 0xcf, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x17, 0xa8, 0x92, 0x0a, 0xd7, 0x97, 0xff, 0xce, +0x66, 0x11, 0xc1, 0x17, 0x37, 0xc3, 0x05, 0x7c, 0xd5, 0xa9, 0x91, 0xa0, 0x0b, 0x98, 0x53, 0xc3, +0x7b, 0xd8, 0xc1, 0x80, 0x23, 0x49, 0x11, 0xf8, 0x8e, 0x14, 0x91, 0x0e, 0x99, 0xc7, 0x18, 0x47, +0xa2, 0x2a, 0x45, 0x19, 0x06, 0xe7, 0xf4, 0xac, 0x7b, 0x34, 0xc3, 0x7a, 0x63, 0x75, 0x5c, 0xc9, +0x1d, 0x61, 0xeb, 0x1a, 0xa4, 0xb6, 0x1f, 0x66, 0xd5, 0xb2, 0xaa, 0xb0, 0xc1, 0x56, 0xa3, 0x07, +0x97, 0x31, 0xad, 0xa1, 0x1d, 0x2e, 0x8f, 0x73, 0xf8, 0x87, 0x3c, 0x82, 0x56, 0x52, 0xc7, 0xc8, +0xa9, 0xfe, 0xa2, 0x02, 0x09, 0x3e, 0x27, 0xe7, 0xe4, 0xfb, 0x41, 0xbc, 0x21, 0x40, 0x42, 0x2f, +0xd9, 0x55, 0x7e, 0xe5, 0x79, 0x52, 0xc0, 0x31, 0xb7, 0x87, 0x7c, 0x59, 0x7b, 0x09, 0xfd, 0xcb, +0x67, 0x93, 0x67, 0xdd, 0x2b, 0xc6, 0x42, 0x78, 0xee, 0x83, 0xd3, 0x8d, 0xe4, 0xc8, 0x5b, 0x89, +0x7d, 0x3c, 0xe1, 0xcd, 0xff, 0xef, 0xc3, 0x23, 0xce, 0xfb, 0x94, 0xd1, 0x76, 0x41, 0x3c, 0xb1, +0x27, 0x17, 0xeb, 0x54, 0x71, 0xc2, 0x95, 0xda, 0x21, 0xb2, 0x92, 0x52, 0x7a, 0x75, 0xc4, 0x5b, +0xb2, 0x06, 0xf4, 0xb2, 0x56, 0x98, 0xce, 0xa1, 0xa1, 0x19, 0x3a, 0x53, 0xd1, 0x82, 0xe2, 0x5e, +0xf5, 0x74, 0x54, 0x0c, 0x57, 0xc6, 0x62, 0x13, 0x0c, 0xec, 0x62, 0x1a, 0x3b, 0xdb, 0xbb, 0x97, +0xab, 0xe0, 0x99, 0x81, 0xa3, 0xd3, 0xfc, 0x26, 0x00, 0xb3, 0x18, 0x9a, 0x5d, 0x59, 0xe6, 0x3b, +0xb1, 0x5c, 0xfd, 0xfe, 0x91, 0xb1, 0xfd, 0x5a, 0xc0, 0x58, 0xc7, 0x3f, 0x98, 0x21, 0x55, 0x6b, +0x09, 0x94, 0x62, 0xac, 0x3f, 0xef, 0x6b, 0xaf, 0x88, 0x91, 0x77, 0x66, 0xdf, 0xa3, 0x89, 0x20, +0x90, 0x8d, 0xac, 0x7f, 0x24, 0x68, 0xe6, 0x21, 0xfd, 0x4f, 0xf5, 0x08, 0x46, 0x96, 0xdf, 0xab, +0xe0, 0x04, 0xf9, 0x10, 0x7b, 0xad, 0x8c, 0x0d, 0x3d, 0xfe, 0x99, 0x84, 0x93, 0xd6, 0x9e, 0x6d, +0x66, 0x5f, 0x8c, 0x86, 0xe1, 0x7c, 0xf0, 0xfb, 0x58, 0x1d, 0xf0, 0x56, 0xb6, 0x6c, 0x1f, 0x77, +0xcd, 0xd6, 0x7c, 0x1e, 0x72, 0x8c, 0xa2, 0x23, 0x86, 0x2a, 0xfa, 0x48, 0x58, 0x8a, 0x3d, 0x83, +0x14, 0xb7, 0xec, 0x68, 0xbd, 0xfe, 0x6b, 0xe9, 0xca, 0x4a, 0x3c, 0xf2, 0x42, 0xd2, 0x1a, 0x64, +0x98, 0x60, 0xe8, 0x93, 0x98, 0x27, 0x08, 0x4a, 0xf2, 0xac, 0x21, 0xa8, 0x51, 0x26, 0xcd, 0x1b, +0x43, 0x4e, 0x15, 0x53, 0x97, 0xd7, 0x18, 0x37, 0xd0, 0x12, 0x77, 0x8c, 0x94, 0x33, 0xcf, 0x5f, +0x4f, 0x4e, 0x15, 0x53, 0x83, 0xd7, 0x18, 0x37, 0xd4, 0x12, 0x77, 0x8c, 0xa4, 0x33, 0xcf, 0x5f, +0x4f, 0x4e, 0x15, 0x53, 0x83, 0xd7, 0x18, 0x37, 0xd4, 0x12, 0x77, 0x8c, 0xa4, 0x33, 0xcf, 0x5f, +0x4f, 0x4e, 0x15, 0x53, 0x83, 0xd7, 0x18, 0x37, 0xd4, 0x12, 0x77, 0x8c, 0xa4, 0x33, 0xcf, 0x5f, +0x4f, 0x4e, 0x15, 0x53, 0x83, 0xd7, 0x18, 0x37, 0xd4, 0x12, 0x77, 0x8c, 0xa4, 0x33, 0xcf, 0x5f, +0x4f, 0x4e, 0x15, 0x53, 0x83, 0xd7, 0x18, 0x37, 0xd4, 0x12, 0x77, 0x8c, 0xa4, 0x33, 0xcf, 0x5f, +0x4f, 0x4e, 0x15, 0x53, 0x83, 0xd7, 0x18, 0x37, 0xd4, 0x12, 0x77, 0x8c, 0xa4, 0x33, 0xcf, 0x5f, +0x4f, 0x4e, 0x15, 0x53, 0x83, 0xd7, 0x18, 0x37, 0xd4, 0x12, 0x77, 0x8c, 0xa4, 0x33, 0xcf, 0x5f, +0x4f, 0x4e, 0x15, 0x53, 0x83, 0xd7, 0x18, 0x37, 0xd4, 0x12, 0x77, 0x8c, 0xa4, 0x33, 0xcf, 0x5f, +0x4f, 0x4e, 0x15, 0x53, 0x83, 0xd7, 0x18, 0x37, 0xd4, 0x12, 0x77, 0x8c, 0xa4, 0x33, 0xcf, 0x5f, +0x4f, 0x4e, 0x15, 0x53, 0x83, 0xd7, 0x18, 0x37, 0xd4, 0x12, 0x77, 0x8c, 0xa4, 0x33, 0xcf, 0x5f, +0x4f, 0x4e, 0x15, 0x53, 0x83, 0xd7, 0x18, 0x37, 0xd4, 0x12, 0x77, 0x8c, 0xa4, 0x33, 0xcf, 0x5f, +0x4f, 0x4e, 0x15, 0x53, 0x83, 0xd7, 0x18, 0x37, 0xd4, 0x12, 0x77, 0x8c, 0xa4, 0x33, 0xcf, 0x5f, +0x4f, 0x4e, 0x15, 0x53, 0x83, 0xd7, 0x18, 0x37, 0xd4, 0x12, 0x77, 0x8c, 0xa4, 0x33, 0xcf, 0x5f, +0x4f, 0x4e, 0x15, 0x53, 0x83, 0xd7, 0x18, 0x37, 0xd4, 0x12, 0x77, 0x8c, 0xa4, 0x33, 0xcf, 0x5f, +0x4f, 0x4e, 0x15, 0x53, 0x83, 0xd7, 0x18, 0x37, 0xd4, 0x12, 0x77, 0x8c, 0xa4, 0x33, 0xcf, 0x5f, +0x85, 0x05, 0x13, 0x50, 0x3f, 0x56, 0x87, 0x43, 0x90, 0xd4, 0xbd, 0x7e, 0x40, 0xed, 0xc5, 0xb4, +0x5b, 0xb3, 0x9e, 0x72, 0xe2, 0xf1, 0x8d, 0x93, 0xd4, 0x78, 0xc7, 0xfc, 0x1d, 0xd9, 0xed, 0xa1, +0xe1, 0x34, 0xf0, 0x63, 0xae, 0xd6, 0xfb, 0xf0, 0x39, 0x44, 0x0b, 0x4d, 0xd5, 0x7e, 0x23, 0xda, +0x6e, 0xc1, 0x4e, 0xa6, 0x6f, 0x8f, 0xfc, 0x22, 0x1f, 0xa8, 0x0d, 0x0d, 0xe0, 0x55, 0x22, 0x58, +0xf9, 0x50, 0x82, 0x1c, 0x3d, 0x64, 0xd4, 0x43, 0xff, 0xf2, 0x49, 0x59, 0x70, 0xf6, 0xdf, 0x7a, +0x5c, 0xc0, 0xbe, 0x57, 0x3a, 0xe3, 0x3d, 0x3a, 0x0e, 0xbc, 0xc9, 0x80, 0x49, 0xa7, 0x6c, 0x1c, +0x68, 0x37, 0x3a, 0xc1, 0x77, 0xec, 0x7b, 0x15, 0x84, 0x4f, 0x6e, 0xb9, 0x2b, 0xdd, 0xb8, 0xfd, +0x9b, 0x75, 0x28, 0x4b, 0xba, 0xbd, 0x9f, 0xd4, 0xa9, 0x22, 0x86, 0x63, 0x0a, 0x6c, 0x8a, 0x5c, +0x8f, 0x6a, 0x41, 0xfa, 0x5c, 0x63, 0x83, 0xa2, 0x8f, 0x5f, 0xe6, 0x16, 0xf5, 0x61, 0xca, 0x50, +0x09, 0xb3, 0xf8, 0x39, 0xde, 0x50, 0x50, 0xcd, 0x76, 0x16, 0x5f, 0x81, 0x07, 0x5b, 0xfa, 0xa3, +0xa8, 0x8d, 0xcd, 0x4e, 0x27, 0xcd, 0x95, 0xec, 0xe8, 0xcf, 0x42, 0x76, 0x27, 0xd6, 0xa0, 0xe5, +0xf3, 0xdb, 0x93, 0xc1, 0x95, 0x3d, 0x82, 0x6b, 0xd8, 0x12, 0x55, 0xc2, 0x73, 0x3b, 0x8f, 0x3e, +0x56, 0x6f, 0x99, 0x43, 0x2c, 0x19, 0x4a, 0xdd, 0x3e, 0x09, 0x59, 0xdc, 0x77, 0x9f, 0xc6, 0x0b, +0xc4, 0x25, 0xb7, 0x65, 0x1b, 0x29, 0xdc, 0x3e, 0x23, 0x19, 0xc7, 0x89, 0x7c, 0x36, 0xaf, 0x44, +0x8d, 0xad, 0x15, 0x1b, 0x00, 0x81, 0x16, 0xcc, 0x83, 0x1c, 0x2c, 0xab, 0xf9, 0xe6, 0xc2, 0x88, +0xe6, 0xc5, 0xfb, 0xfa, 0x89, 0x23, 0xb4, 0x03, 0x1e, 0x8a, 0x06, 0xfc, 0x40, 0xd3, 0x1f, 0x04, +0xa7, 0x64, 0x8a, 0x62, 0x54, 0x00, 0x46, 0xc7, 0xe0, 0xb4, 0xc0, 0xc4, 0x7c, 0x93, 0x46, 0xb9, +0x8b, 0x4c, 0xea, 0x1c, 0x01, 0xf5, 0xcb, 0xe5, 0x85, 0x5d, 0xd8, 0x90, 0x97, 0x9c, 0x6f, 0xf7, +0x94, 0x89, 0x67, 0x0b, 0x8f, 0x12, 0x39, 0x48, 0xac, 0x10, 0xe4, 0xf0, 0x36, 0x26, 0x2e, 0xba, +0xf5, 0x5f, 0x36, 0xf5, 0x31, 0xc8, 0xe3, 0xdf, 0x12, 0xd1, 0xbd, 0x32, 0x03, 0x10, 0x93, 0xb5, +0x4f, 0xcb, 0xf9, 0xd8, 0xe2, 0x94, 0xd7, 0xaf, 0xb2, 0x02, 0xee, 0xb2, 0x0f, 0xea, 0x25, 0x09, +0xa6, 0xfa, 0xcd, 0xe9, 0x8f, 0x94, 0x80, 0x1e, 0xc7, 0xe1, 0x3b, 0x4b, 0xb5, 0x79, 0x3b, 0xfe, +0x41, 0x3d, 0xe1, 0x82, 0x7e, 0xa2, 0x7d, 0xc9, 0x4a, 0x33, 0xe0, 0xbe, 0xc2, 0x50, 0x45, 0x9b, +0xae, 0x78, 0x69, 0x80, 0xd9, 0xce, 0x2a, 0x85, 0x12, 0x4e, 0xe0, 0xc1, 0xdc, 0x41, 0xd7, 0x73, +0x34, 0x10, 0x54, 0xc7, 0x49, 0x76, 0x26, 0x47, 0xb3, 0x70, 0xf5, 0xe1, 0x96, 0xb5, 0x6b, 0x35, +0x66, 0x8e, 0x78, 0xdf, 0x6f, 0x20, 0x52, 0x37, 0x4b, 0x41, 0x4f, 0xed, 0x9c, 0x19, 0x63, 0xed, +0xbd, 0x9b, 0xab, 0x55, 0x18, 0xc5, 0x81, 0x55, 0xb7, 0xf3, 0x2a, 0xdf, 0xc1, 0x3e, 0xbe, 0x00, +0xb3, 0x14, 0x20, 0x86, 0xcc, 0x5c, 0x39, 0xd7, 0x6b, 0x25, 0xc1, 0x5f, 0xa5, 0xc3, 0x85, 0xbc, +0x6f, 0xa3, 0xd8, 0x71, 0x08, 0x19, 0x8c, 0xac, 0xc3, 0xee, 0x97, 0xdb, 0x08, 0xa7, 0xee, 0xa2, +0x7f, 0xde, 0xa4, 0x08, 0x6e, 0x6a, 0x83, 0xf2, 0x6b, 0x8b, 0x05, 0x49, 0x31, 0xb9, 0xee, 0x1f, +0x26, 0x26, 0x41, 0xcb, 0x06, 0x78, 0x1b, 0xe7, 0xc3, 0x24, 0xb9, 0x3a, 0x75, 0x5f, 0xb6, 0xcf, +0xa8, 0x75, 0xae, 0x96, 0xfd, 0x5b, 0x17, 0x4e, 0xad, 0xb4, 0x6f, 0xfc, 0x4e, 0xe4, 0xb7, 0x11, +0x6c, 0x45, 0xe0, 0xe5, 0xe3, 0x59, 0x3f, 0xe0, 0xf7, 0x56, 0x8a, 0x3b, 0xf2, 0xc5, 0x6d, 0xc7, +0x8e, 0x57, 0x7e, 0x73, 0xf9, 0x09, 0x2a, 0xc5, 0x34, 0xee, 0xdc, 0x1f, 0xd9, 0x9f, 0x38, 0xc3, +0x4d, 0x01, 0x65, 0xb7, 0x74, 0x03, 0xdf, 0x96, 0xa1, 0x6b, 0x24, 0x09, 0x74, 0xc8, 0x88, 0x2d, +0x2d, 0x83, 0xf1, 0x2b, 0x14, 0x02, 0x64, 0x33, 0x37, 0x5e, 0x4c, 0x6d, 0x34, 0x67, 0x95, 0x6f, +0x92, 0xc5, 0xb6, 0xf1, 0x46, 0x48, 0x9a, 0x03, 0x1c, 0x21, 0xe2, 0x30, 0x0a, 0x02, 0x0a, 0xbc, +0x0c, 0xcd, 0x89, 0x6e, 0x45, 0x52, 0x62, 0xbc, 0x5a, 0x43, 0xed, 0x72, 0x8d, 0x60, 0x0b, 0xd5, +0x1b, 0xaf, 0xe8, 0xcd, 0x1f, 0x30, 0x36, 0x03, 0x0c, 0x8b, 0x89, 0x14, 0x83, 0x36, 0xc3, 0x71, +0x1e, 0x36, 0xe4, 0x1c, 0xd4, 0x24, 0x8f, 0x8b, 0x28, 0xa9, 0x5e, 0x37, 0xaf, 0xfd, 0x01, 0x76, +0x4f, 0x19, 0x81, 0x88, 0x44, 0x4d, 0xb8, 0xaf, 0xd9, 0xab, 0x4b, 0x4a, 0x8d, 0xfc, 0xba, 0xe5, +0x48, 0x1e, 0x70, 0x69, 0x32, 0x94, 0x4a, 0xcf, 0xd3, 0xd8, 0x2c, 0xb7, 0x8e, 0x3d, 0x86, 0xe0, +0xb9, 0xe0, 0x84, 0xbe, 0x5e, 0xd1, 0x9c, 0x3a, 0x25, 0x27, 0xb1, 0xe4, 0x58, 0xa1, 0x40, 0x59, +0x55, 0x1b, 0x2b, 0x4b, 0x44, 0x03, 0xa8, 0xc8, 0x39, 0x85, 0x79, 0xaa, 0x22, 0x5c, 0xcc, 0xaf, +0xef, 0xf7, 0x32, 0xd5, 0x57, 0x6b, 0xfc, 0x7f, 0x4c, 0xdd, 0xb5, 0x11, 0xd0, 0x7b, 0xeb, 0x9d, +0x4a, 0xee, 0x6a, 0x4f, 0x72, 0xfb, 0x6c, 0x08, 0x4c, 0x05, 0x85, 0x2e, 0x58, 0x90, 0x95, 0xb0, +0x73, 0x6d, 0x75, 0x38, 0x80, 0x63, 0xd5, 0x89, 0x1f, 0x9c, 0x71, 0x10, 0x56, 0xec, 0x71, 0x3c, +0xb8, 0xec, 0xf9, 0x04, 0x4a, 0xa4, 0x42, 0x90, 0x90, 0x4f, 0xe7, 0xc9, 0x1b, 0x3e, 0xa2, 0x11, +0x66, 0xac, 0xef, 0x2a, 0xfa, 0x17, 0x82, 0xd6, 0xd5, 0x45, 0x71, 0xc8, 0xbd, 0x84, 0x4a, 0x2c, +0x95, 0x2c, 0x17, 0xe8, 0x9c, 0xd3, 0xab, 0x0f, 0x0d, 0xb6, 0xb7, 0xde, 0xd9, 0xc6, 0x38, 0x43, +0x18, 0x97, 0x5e, 0x54, 0x44, 0xc2, 0x7a, 0xfe, 0x19, 0x68, 0xca, 0xb7, 0x95, 0x0a, 0xc8, 0x74, +0x80, 0x39, 0x51, 0x10, 0xf3, 0xbb, 0xd6, 0x29, 0x7a, 0x10, 0xd1, 0x8b, 0xa1, 0x2e, 0xf0, 0x46, +0x9f, 0x83, 0x61, 0x75, 0x63, 0x01, 0xa0, 0x74, 0xd8, 0xb0, 0x42, 0xc0, 0x82, 0xd8, 0x63, 0x0c, +0x19, 0x54, 0x41, 0x43, 0x61, 0x0b, 0x38, 0xd8, 0xf9, 0xca, 0x1c, 0x57, 0x81, 0x5b, 0x7e, 0x86, +0x21, 0x9b, 0xde, 0xb9, 0x53, 0x14, 0x51, 0xe5, 0xa2, 0xc8, 0x0f, 0xf7, 0xdd, 0xd2, 0x9c, 0xff, +0x02, 0x5f, 0x5a, 0x58, 0x22, 0xfe, 0xbb, 0x23, 0x41, 0xa0, 0x04, 0xff, 0x10, 0xce, 0xec, 0x0b, +0xcf, 0x7b, 0x47, 0xc7, 0x25, 0x01, 0xee, 0x3e, 0x36, 0x6d, 0xe6, 0x03, 0x81, 0xad, 0x4d, 0x4a, +0x19, 0x88, 0xe4, 0xad, 0x8e, 0x37, 0xef, 0x63, 0xcc, 0xf3, 0x49, 0xa9, 0xd0, 0xa4, 0x2b, 0x82, +0x59, 0xc6, 0x81, 0xa5, 0x93, 0x0d, 0x6e, 0x1d, 0x00, 0xa2, 0xdf, 0x2b, 0xe1, 0x6d, 0xd8, 0xd3, +0xeb, 0x88, 0xde, 0xb9, 0xbc, 0x71, 0x76, 0xa1, 0x37, 0xd3, 0x76, 0x65, 0xff, 0x0c, 0xbd, 0x7f, +0xeb, 0x37, 0xe6, 0x5c, 0x12, 0x82, 0xb8, 0x40, 0xc6, 0x37, 0x3d, 0x60, 0x78, 0xf0, 0xe1, 0xe8, +0x45, 0xd8, 0xb7, 0xef, 0x84, 0x96, 0x9e, 0xdb, 0x47, 0xf5, 0x8d, 0x00, 0x6a, 0x49, 0x75, 0x09, +0x29, 0x96, 0x64, 0x94, 0x72, 0xbb, 0xea, 0x10, 0xbb, 0x98, 0x2e, 0x81, 0x52, 0xc3, 0x46, 0x6e, +0xe4, 0x61, 0xb9, 0x75, 0x06, 0x72, 0xed, 0x0d, 0xb6, 0x8a, 0x55, 0x1d, 0x93, 0x3c, 0x8e, 0x43, +0xb7, 0x5b, 0x9a, 0x3d, 0x2d, 0x75, 0x24, 0x2e, 0x81, 0xbf, 0x0e, 0x80, 0xa8, 0x4a, 0x24, 0x72, +0x80, 0x2f, 0x72, 0xda, 0xd1, 0xcc, 0x36, 0xb3, 0xe7, 0xb6, 0xfe, 0x57, 0x89, 0xc2, 0x7e, 0xdb, +0x1a, 0x17, 0x17, 0xe7, 0x73, 0xbe, 0x15, 0xec, 0x78, 0x32, 0xa7, 0x18, 0x4b, 0x9a, 0xc3, 0x2c, +0x6e, 0x8d, 0xb3, 0x4c, 0xa4, 0x85, 0x72, 0x31, 0xda, 0x97, 0x46, 0x82, 0x64, 0xfe, 0x05, 0x8c, +0x2c, 0xc6, 0x12, 0xf3, 0xdf, 0x68, 0xda, 0xf6, 0x3d, 0x6b, 0x57, 0x9a, 0x47, 0xa0, 0xe5, 0x9e, +0xdf, 0x86, 0x5d, 0xa5, 0x9d, 0x09, 0x8c, 0xfc, 0xe7, 0x6b, 0xff, 0x78, 0x80, 0x4a, 0x43, 0x8f, +0x73, 0x27, 0x26, 0x84, 0xd0, 0x3f, 0xa7, 0x88, 0x0d, 0x66, 0xa1, 0x08, 0x21, 0xfd, 0x59, 0xde, +0xe0, 0x3d, 0x8a, 0x36, 0xa9, 0x5e, 0x1e, 0xba, 0xef, 0x9b, 0xd0, 0x21, 0xa4, 0xa5, 0x35, 0xda, +0x5d, 0x7b, 0x76, 0xb5, 0x8b, 0xee, 0xc2, 0xa7, 0xad, 0x78, 0x43, 0x35, 0xc1, 0x18, 0x6d, 0xad, +0x7f, 0xb6, 0xa0, 0xd0, 0x26, 0x34, 0x11, 0x02, 0x78, 0xcd, 0x1e, 0x16, 0x5a, 0xd8, 0x00, 0xc3, +0xa2, 0x45, 0x37, 0xcf, 0xf3, 0x6a, 0x1a, 0xf8, 0xac, 0xc1, 0x75, 0x3a, 0x17, 0xff, 0xc9, 0xfc, +0x6a, 0x74, 0x6c, 0x66, 0x85, 0x9d, 0x8d, 0x99, 0x7a, 0xb1, 0xd0, 0xe1, 0xe7, 0x20, 0x82, 0xb0, +0x2c, 0xe6, 0x84, 0x70, 0x02, 0xfd, 0x2e, 0xcf, 0x5e, 0x15, 0x76, 0x0e, 0x8d, 0x62, 0x93, 0xdd, +0x1a, 0x2c, 0xf9, 0x7e, 0x73, 0xc1, 0xc8, 0x11, 0xa5, 0x63, 0xc0, 0xe9, 0xe7, 0x46, 0x8a, 0xd5, +0x01, 0x30, 0xf6, 0xde, 0xa6, 0x13, 0x96, 0x21, 0x23, 0xe0, 0x60, 0x2f, 0xeb, 0x48, 0x91, 0x53, +0x9c, 0x8d, 0x25, 0x5c, 0x17, 0x42, 0xf9, 0x1d, 0x8b, 0xb4, 0x27, 0x3f, 0x9b, 0xaf, 0xb8, 0x24, +0x1a, 0x0e, 0x25, 0xe6, 0x53, 0xe6, 0x21, 0x63, 0xf7, 0x9a, 0xc3, 0x20, 0x71, 0x2e, 0x86, 0x3c, +0x25, 0x74, 0x69, 0x56, 0xaf, 0x9a, 0x66, 0x66, 0xf7, 0x8b, 0xeb, 0xe1, 0x6a, 0xc4, 0x9f, 0x79, +0xa0, 0x80, 0x33, 0xbc, 0xee, 0x76, 0xcd, 0xc0, 0x2d, 0x61, 0xdd, 0xf8, 0xdc, 0x1d, 0xb4, 0x58, +0xb8, 0x79, 0x58, 0xb9, 0x1e, 0x21, 0x2a, 0x7c, 0xfc, 0xf7, 0xee, 0xcb, 0x31, 0x16, 0xe3, 0x19, +0x00, 0xca, 0xf0, 0x91, 0x23, 0xfd, 0x46, 0x1a, 0x36, 0xee, 0x9b, 0x93, 0xda, 0x62, 0x0f, 0x50, +0x40, 0x0f, 0xe8, 0x7e, 0x93, 0xad, 0x40, 0xa7, 0x9a, 0xc7, 0xc8, 0x35, 0xd3, 0xec, 0x07, 0xb7, +0x4b, 0x57, 0x6c, 0x1b, 0x7a, 0x32, 0x7e, 0xa2, 0x14, 0x5a, 0x22, 0xe8, 0xb5, 0x53, 0x43, 0x4a, +0x22, 0x71, 0xbc, 0x28, 0xc2, 0x1c, 0xf1, 0x9b, 0x7e, 0x74, 0x4e, 0xc3, 0x1f, 0x65, 0x91, 0xf9, +0x5b, 0xa3, 0xe8, 0x34, 0x47, 0xd2, 0x7c, 0x2a, 0x0e, 0xe2, 0x64, 0xf5, 0x65, 0xbf, 0xfe, 0xaf, +0x4c, 0x8b, 0xbb, 0x63, 0x0e, 0x9e, 0x4e, 0x95, 0x44, 0x91, 0x25, 0x37, 0xc0, 0x55, 0xf3, 0x08, +0xb5, 0x59, 0x0f, 0xee, 0x52, 0x39, 0x45, 0xa6, 0x5a, 0xd9, 0x82, 0x5e, 0xcb, 0xc6, 0x84, 0x29, +0x1b, 0x0d, 0x02, 0x33, 0x8f, 0x0d, 0x67, 0x2f, 0xbe, 0xa1, 0x91, 0x82, 0x90, 0x44, 0x7a, 0xec, +0x97, 0x93, 0x87, 0xa7, 0x7e, 0x26, 0x5c, 0x46, 0xc1, 0x91, 0x65, 0x3f, 0xc9, 0xe0, 0x12, 0x43, +0x1a, 0xf0, 0x2a, 0xf4, 0x63, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x4c, 0xd4, 0xc5, 0x01, 0x60, 0x35, 0x9f, 0x13, 0x00, 0x70, 0x9d, 0xa5, 0x1f, 0xc1, 0xa2, 0x88, +0x3d, 0x9d, 0x8f, 0xe6, 0x80, 0x86, 0x13, 0x2e, 0x6a, 0xd7, 0xd6, 0x55, 0xdd, 0x9f, 0x65, 0x15, +0x88, 0x4b, 0xd8, 0x4f, 0xd4, 0x5c, 0xc4, 0xf8, 0x68, 0x53, 0x39, 0x37, 0xa0, 0xb2, 0x31, 0xda, +0xd7, 0x34, 0x89, 0x8f, 0x20, 0x0d, 0x0e, 0x4d, 0x9f, 0xe0, 0xfa, 0x78, 0x19, 0x4e, 0xfc, 0x0b, +0xfe, 0x75, 0xd8, 0xb6, 0x98, 0x67, 0x7b, 0x5c, 0x37, 0xb5, 0xde, 0x44, 0xd3, 0xef, 0xb2, 0xe5, +0xdf, 0x84, 0xa4, 0x50, 0x31, 0xc7, 0x6e, 0x09, 0x58, 0xca, 0x51, 0x6b, 0x02, 0x52, 0x74, 0xd0, +0x24, 0xcf, 0x23, 0x58, 0x79, 0x8f, 0x62, 0x4e, 0x42, 0x75, 0x53, 0x8c, 0x26, 0x57, 0x0e, 0x55, +0x89, 0xda, 0x69, 0xea, 0x8c, 0xbd, 0x40, 0x47, 0xd9, 0xfc, 0xf5, 0x76, 0x1d, 0x7c, 0x7d, 0xb3, +0xbb, 0x3c, 0x48, 0xfb, 0xbd, 0x6d, 0xfd, 0x11, 0xe4, 0x31, 0xd5, 0x1b, 0x4d, 0x3d, 0xc8, 0xee, +0x09, 0xa5, 0x7d, 0x57, 0x2d, 0xb3, 0x46, 0xe1, 0xe8, 0xcd, 0x27, 0x21, 0xa1, 0xad, 0x93, 0xb9, +0x6b, 0x73, 0x3e, 0x14, 0x16, 0x63, 0x82, 0xf6, 0xb9, 0x65, 0xcc, 0xd2, 0x49, 0xd1, 0x16, 0xe1, +0x1f, 0xb9, 0x36, 0xbb, 0x8f, 0x34, 0x8d, 0x62, 0x34, 0x96, 0x62, 0x97, 0x25, 0x10, 0x7c, 0xa1, +0xf4, 0x52, 0x76, 0xba, 0x04, 0xab, 0x50, 0x05, 0x97, 0x01, 0x01, 0xa6, 0x92, 0x9e, 0x28, 0x56, +0x30, 0xd2, 0x62, 0x9c, 0x0c, 0x74, 0xd0, 0x10, 0xf0, 0x58, 0x05, 0xab, 0x33, 0xc0, 0x1b, 0x8d, +0xa9, 0x0b, 0x00, 0xb2, 0xb4, 0xc8, 0xc4, 0x9b, 0xf7, 0x2d, 0x33, 0xdf, 0xac, 0xf4, 0x8b, 0x2e, +0xc3, 0xbd, 0x19, 0x8d, 0xf8, 0xc5, 0x1e, 0x45, 0xc6, 0x86, 0xc5, 0xab, 0x7e, 0xc3, 0x76, 0xf8, +0x82, 0x49, 0x1a, 0x20, 0xb2, 0x8c, 0x7d, 0x17, 0x03, 0x90, 0x11, 0xc7, 0x03, 0x52, 0x2f, 0x83, +0x54, 0x23, 0x65, 0x48, 0xfe, 0xd4, 0x75, 0x46, 0xd9, 0x3d, 0x8d, 0xb8, 0x93, 0x46, 0xcb, 0x80, +0xdf, 0x02, 0x6c, 0xa3, 0xf4, 0xcc, 0xd7, 0xc0, 0xc4, 0x95, 0xe1, 0x4f, 0x74, 0xa5, 0x53, 0xc5, +0xa5, 0x11, 0xe9, 0x99, 0x48, 0xa2, 0x41, 0xa2, 0x36, 0x08, 0x8d, 0xbd, 0xb5, 0x87, 0x1b, 0xbb, +0x14, 0xfc, 0xfd, 0x88, 0xf3, 0x18, 0x6a, 0xf2, 0xa1, 0xbb, 0xc7, 0x89, 0x4f, 0x6d, 0x41, 0xce, +0x9e, 0x28, 0x87, 0x6d, 0xfa, 0x88, 0xf7, 0x81, 0xac, 0x8e, 0xed, 0xfe, 0x3c, 0x9e, 0x52, 0xa1, +0xf3, 0x1a, 0xe3, 0x68, 0x4d, 0x20, 0xda, 0xcf, 0x3c, 0x10, 0x1a, 0xe5, 0x46, 0x6c, 0xf7, 0xdc, +0x5d, 0xf6, 0xa8, 0xd0, 0xdd, 0x4a, 0xfb, 0x28, 0x04, 0x64, 0xef, 0x70, 0xa0, 0x5b, 0xf2, 0xc4, +0xc3, 0x74, 0x83, 0x83, 0x92, 0x03, 0x7c, 0x0f, 0x39, 0x9c, 0xc7, 0x9f, 0x95, 0xb5, 0xbf, 0xae, +0xb1, 0x8a, 0xe9, 0x6c, 0xa1, 0x3f, 0xf8, 0x5b, 0xab, 0x6b, 0xf7, 0xd6, 0x19, 0xd0, 0xcb, 0x54, +0x71, 0x40, 0xe1, 0x7f, 0xc4, 0xac, 0xcd, 0x09, 0x78, 0x1e, 0x61, 0x12, 0xff, 0xa1, 0x2c, 0x27, +0x33, 0x48, 0x54, 0x11, 0xef, 0x2d, 0xd0, 0x5f, 0xb1, 0x31, 0xa5, 0xa4, 0xf8, 0x0c, 0xa0, 0x06, +0x92, 0xf8, 0x7b, 0xf6, 0xa8, 0xde, 0x40, 0x47, 0xd9, 0xfc, 0xf5, 0x76, 0x1d, 0x7c, 0x7d, 0xb3, +0x7b, 0x18, 0xd6, 0xe4, 0xae, 0xa0, 0x06, 0x4c, 0xde, 0xda, 0x65, 0x55, 0x8b, 0x1d, 0xb4, 0x3c, +0x09, 0xd0, 0xd0, 0x84, 0x5d, 0x43, 0x56, 0x0d, 0x7c, 0xe9, 0x61, 0x85, 0x8a, 0x77, 0xa6, 0x82, +0x0b, 0x09, 0x6d, 0x04, 0x71, 0xd6, 0x79, 0x06, 0x6f, 0xd1, 0xd2, 0xb2, 0x57, 0x1b, 0x2e, 0xdf, +0x8f, 0xda, 0x61, 0xf9, 0xcc, 0xba, 0x4a, 0x47, 0xd9, 0xfc, 0xf5, 0x76, 0x1d, 0x7c, 0x7d, 0xb3, +0xcc, 0x95, 0x7a, 0xa7, 0x88, 0xc6, 0x2a, 0x09, 0x00, 0xbe, 0xf7, 0x2a, 0xdc, 0x27, 0x29, 0xbc, +0xcf, 0x7a, 0x0a, 0xd8, 0x99, 0x54, 0x84, 0x16, 0x9b, 0xc8, 0x6e, 0x4f, 0x90, 0x8d, 0x78, 0x58, +0x71, 0xf8, 0x61, 0x77, 0x83, 0x40, 0xce, 0xdd, 0xf9, 0x9d, 0x72, 0xd2, 0xcb, 0x51, 0x13, 0x05, +0xbc, 0x0b, 0xbb, 0x2c, 0x6c, 0x6c, 0x90, 0x83, 0xca, 0xd6, 0x27, 0x81, 0xa1, 0x7a, 0xa6, 0x70, +0xc9, 0x6e, 0xb6, 0xad, 0xb9, 0xfe, 0x11, 0x20, 0x66, 0x28, 0x19, 0x7d, 0xa9, 0xfb, 0x21, 0xb2, +0x85, 0xff, 0xc0, 0x80, 0x19, 0xc5, 0xca, 0x19, 0x1d, 0xa8, 0x8f, 0x57, 0x1c, 0xc3, 0x80, 0xae, +0xdf, 0xb8, 0xd8, 0xfb, 0x57, 0x66, 0xa0, 0xb3, 0xd1, 0x9b, 0xf8, 0x4c, 0xea, 0xf9, 0xe5, 0xfe, +0xb4, 0x01, 0x1e, 0x24, 0xe1, 0xc1, 0x31, 0xaf, 0x28, 0x86, 0x3c, 0xfe, 0x4f, 0x14, 0xe4, 0xbb, +0x0f, 0xb7, 0x0c, 0x98, 0x9e, 0x2c, 0x49, 0x47, 0xd9, 0xfc, 0xf5, 0x76, 0x1d, 0x7c, 0x7d, 0xb3, +0x43, 0xc4, 0xf4, 0xf7, 0x4d, 0xff, 0xa3, 0x95, 0xa1, 0xd0, 0x1d, 0x1c, 0xa6, 0xcb, 0xe6, 0xf6, +0x23, 0xc8, 0x66, 0xec, 0xa0, 0xa7, 0x06, 0x1b, 0x69, 0x67, 0x37, 0xcf, 0x5f, 0x0c, 0x15, 0x37, +0xfb, 0x06, 0xdb, 0x63, 0x7b, 0x84, 0xee, 0x7a, 0xcf, 0x45, 0xa9, 0x9d, 0x73, 0x8a, 0x40, 0x46, +0x07, 0xd2, 0xd2, 0xab, 0x3b, 0x98, 0xea, 0x76, 0x5a, 0x78, 0x4e, 0xbc, 0xc5, 0x78, 0x15, 0xbb, +0x71, 0xfe, 0x7a, 0x67, 0x83, 0x40, 0xce, 0xdd, 0xf9, 0x9d, 0x72, 0xd2, 0xcb, 0x51, 0x13, 0x05, +0xd6, 0x9f, 0x4d, 0x59, 0xac, 0x26, 0xfc, 0x99, 0x6f, 0xb8, 0x63, 0x1e, 0x68, 0x2e, 0xd6, 0x7b, +0x93, 0x0a, 0xce, 0xd3, 0xb1, 0xc6, 0xfa, 0xaa, 0xa7, 0x27, 0x73, 0xba, 0xfa, 0xc0, 0x85, 0x83, +0xaf, 0x83, 0xff, 0xa1, 0xa9, 0x66, 0xf2, 0xb1, 0xbf, 0xb1, 0xeb, 0xfb, 0x53, 0xe1, 0x8c, 0xee, +0x9a, 0xd2, 0xcd, 0xa4, 0xa2, 0x5b, 0xd0, 0xee, 0x85, 0x3d, 0x66, 0xb3, 0xdc, 0x2d, 0xb8, 0x53, +0x98, 0x95, 0x1c, 0x2b, 0x53, 0x36, 0x6a, 0x2f, 0x84, 0xde, 0x1b, 0x2b, 0xd6, 0x74, 0x88, 0xf2, +0x1d, 0x89, 0x74, 0x0e, 0xf9, 0x33, 0x4f, 0x90, 0x55, 0xc1, 0x3a, 0x29, 0x9b, 0x41, 0xf6, 0xa8, +0x6c, 0x1c, 0x0d, 0x46, 0xa4, 0xe5, 0xd2, 0x55, 0x57, 0xe5, 0x3e, 0xb8, 0xdc, 0x34, 0xbc, 0x47, +0x49, 0x64, 0x85, 0x20, 0x7e, 0x45, 0x5d, 0x08, 0xc8, 0xfa, 0x75, 0x70, 0x89, 0xb9, 0xb9, 0x66, +0x0c, 0x3e, 0x03, 0xe3, 0xb0, 0xdb, 0x83, 0xd7, 0x96, 0xc0, 0x87, 0x01, 0x19, 0x22, 0x65, 0x71, +0x22, 0x42, 0x62, 0x64, 0xd8, 0x70, 0xaf, 0x44, 0x75, 0x3b, 0x8b, 0xd2, 0xb2, 0x1e, 0x50, 0x16, +0x2b, 0x18, 0xd7, 0x04, 0x43, 0xad, 0x22, 0x5c, 0x4d, 0x26, 0x8a, 0x2f, 0x3d, 0x94, 0x6a, 0xd0, +0x3b, 0x25, 0x12, 0x34, 0xb4, 0x83, 0xe9, 0x1a, 0x71, 0xd1, 0x55, 0xc8, 0x34, 0x6d, 0xf2, 0xd1, +0x62, 0xd1, 0x44, 0x8f, 0x7f, 0x25, 0xea, 0x69, 0x73, 0xce, 0x6e, 0x8e, 0x39, 0xc5, 0x5b, 0x9e, +0x8f, 0xdc, 0xaf, 0x0d, 0x38, 0x7a, 0x51, 0xd0, 0xbf, 0xfe, 0x36, 0x08, 0x05, 0x5b, 0xf1, 0x7e, +0xbc, 0x4a, 0x63, 0x2c, 0xac, 0x58, 0x45, 0xdb, 0x1b, 0x93, 0xa5, 0xa2, 0xd6, 0x5e, 0x95, 0x19, +0xe5, 0xd0, 0x44, 0xc1, 0x59, 0xcc, 0x76, 0x05, 0x44, 0x4b, 0x3a, 0x3f, 0x9f, 0x98, 0xbf, 0x94, +0x24, 0x20, 0x46, 0x59, 0xf9, 0xad, 0xb1, 0xd5, 0x36, 0x16, 0xd3, 0x06, 0x22, 0x01, 0x21, 0x54, +0x90, 0xce, 0xa1, 0x0d, 0x26, 0x61, 0x5c, 0xd0, 0xbf, 0xfe, 0x36, 0x08, 0x05, 0x5b, 0xf1, 0x7e, +0xbc, 0x4a, 0x63, 0x2c, 0xac, 0x58, 0x45, 0xdb, 0x1b, 0x93, 0xa5, 0xa2, 0xd6, 0x5e, 0x95, 0x19, +0xe5, 0xd0, 0x44, 0xc1, 0x59, 0xcc, 0x76, 0x05, 0x44, 0x4b, 0x3a, 0x3f, 0x9f, 0x98, 0xbf, 0x94, +0xc2, 0x76, 0x97, 0xee, 0xed, 0x9e, 0x49, 0xaa, 0xc1, 0x0b, 0xdc, 0x68, 0x75, 0xf1, 0xf0, 0xf5, +0xda, 0xca, 0xc1, 0x44, 0x85, 0x60, 0xd2, 0xe3, 0xc8, 0x70, 0x79, 0x11, 0xd9, 0xe9, 0xfa, 0x95, +0xc6, 0x17, 0xc7, 0x74, 0x74, 0xfd, 0xe8, 0x6e, 0x7b, 0x44, 0x0d, 0x17, 0x8b, 0x71, 0x17, 0x13, +0xe4, 0x15, 0x86, 0x07, 0x8b, 0x05, 0xc9, 0x95, 0x65, 0x5b, 0x40, 0x07, 0x85, 0xc7, 0x3b, 0xda, +0x16, 0x45, 0x19, 0x69, 0xce, 0xe6, 0x54, 0xe0, 0x36, 0xc7, 0x60, 0x18, 0x18, 0xf9, 0x8d, 0x4f, +0xbc, 0x78, 0x41, 0x7d, 0x7c, 0xc9, 0x51, 0xed, 0xe3, 0x14, 0x74, 0xf4, 0x29, 0x84, 0xdd, 0x0f, +0x8a, 0x20, 0x55, 0xb0, 0x7e, 0xbb, 0x98, 0x8a, 0xcd, 0x4c, 0x45, 0x5c, 0xb4, 0x72, 0xf3, 0x73, +0xd3, 0x9f, 0xde, 0xd9, 0x36, 0x5a, 0xae, 0x48, 0x9e, 0xd0, 0x98, 0x91, 0xf0, 0x14, 0x4a, 0xbc, +0x87, 0x26, 0x4a, 0x00, 0xdd, 0xee, 0x20, 0x44, 0x3d, 0xea, 0xe9, 0xc6, 0x85, 0xc7, 0x19, 0x4b, +0x75, 0xa4, 0x84, 0x99, 0xe5, 0x81, 0xf0, 0xd9, 0xe9, 0x71, 0x23, 0xd4, 0xc0, 0xfc, 0x81, 0x4e, +0xae, 0x74, 0xe6, 0xd4, 0x8f, 0xbe, 0x2d, 0x67, 0x62, 0x62, 0x33, 0xba, 0x6f, 0xc0, 0xe2, 0x13, +0x87, 0x80, 0x93, 0xe7, 0xc5, 0x14, 0x8c, 0xaa, 0x32, 0x33, 0x0d, 0x51, 0xbf, 0x55, 0x9b, 0x90, +0x45, 0x3e, 0x98, 0x12, 0xdb, 0x16, 0x0f, 0x00, 0x5a, 0x3b, 0xcb, 0xcc, 0x78, 0x57, 0xd2, 0x17, +0x2f, 0x80, 0x1a, 0x5f, 0x2f, 0x3b, 0x3d, 0x34, 0xd9, 0x1a, 0x23, 0x7c, 0x6f, 0xdb, 0x07, 0xcc, +0x94, 0x9d, 0x42, 0xbc, 0xd0, 0x14, 0x4d, 0xe4, 0x20, 0x27, 0xe5, 0xca, 0xe6, 0x79, 0x6c, 0xdb, +0xde, 0x75, 0x6f, 0x3a, 0xdd, 0xee, 0x5a, 0x89, 0xe5, 0x42, 0xb0, 0x77, 0xe6, 0x54, 0x98, 0xd8, +0x1e, 0x48, 0x2d, 0x2b, 0xa3, 0xe8, 0x09, 0x71, 0x57, 0xde, 0x64, 0xb3, 0xbe, 0x87, 0x79, 0xe3, +0x1f, 0x65, 0x12, 0xa6, 0x4b, 0x72, 0x9c, 0xf1, 0x4b, 0x59, 0xaa, 0x6a, 0xaf, 0x20, 0xe0, 0xea, +0xb6, 0xe7, 0x71, 0xa1, 0x38, 0x02, 0x79, 0xd0, 0xc8, 0x99, 0x46, 0xd3, 0x81, 0xd1, 0x69, 0x9f, +0x12, 0xf4, 0x8b, 0x31, 0x86, 0x26, 0x66, 0xcb, 0x07, 0x8b, 0x6c, 0x4d, 0xbe, 0xcb, 0xcd, 0x3b, +0xab, 0x76, 0xac, 0x78, 0x7e, 0xed, 0xc7, 0x47, 0x46, 0x01, 0xf5, 0xd6, 0xf9, 0xd1, 0xf1, 0x25, +0xa2, 0xae, 0xd9, 0x17, 0x83, 0x82, 0x14, 0x12, 0xe2, 0x62, 0xff, 0x1a, 0x40, 0x3f, 0x15, 0x29, +0x71, 0xc1, 0x11, 0xd4, 0x9f, 0x22, 0x9b, 0xa6, 0x8d, 0xca, 0x3e, 0x33, 0x2d, 0x19, 0x06, 0x19, +0xf2, 0xb7, 0x95, 0x16, 0x7a, 0xc0, 0xd3, 0x46, 0x2b, 0x48, 0x1b, 0x87, 0xba, 0x44, 0xdf, 0xc9, +0xbc, 0x0d, 0xb1, 0xda, 0x0a, 0x03, 0xf9, 0xac, 0xb3, 0xa7, 0xf4, 0x95, 0x44, 0xc8, 0x1e, 0xa8, +0x1f, 0xf7, 0x44, 0x34, 0xcf, 0x6a, 0xcd, 0xda, 0x4d, 0xa7, 0x92, 0x46, 0xc0, 0x1d, 0xda, 0xec, +0x29, 0x3a, 0x37, 0x6a, 0xa2, 0x61, 0x0b, 0x95, 0x9d, 0xa5, 0x36, 0xff, 0x4f, 0x3f, 0x6b, 0x1c, +0x76, 0xdd, 0xe2, 0xf3, 0xbf, 0x45, 0x17, 0xaf, 0x27, 0xf4, 0x5d, 0x6c, 0x02, 0xf3, 0x8b, 0xd7, +0x6c, 0x92, 0xcc, 0xd7, 0xce, 0xf0, 0xb7, 0x6f, 0xc6, 0x3e, 0x15, 0xbb, 0xbc, 0xb3, 0x85, 0xe7, +0xae, 0x68, 0x46, 0xc0, 0x90, 0x7b, 0xe5, 0xf4, 0x12, 0xbc, 0x95, 0x9a, 0x62, 0x1e, 0x5e, 0x8c, +0x79, 0x5f, 0x4e, 0x19, 0x77, 0xf2, 0xd4, 0xa9, 0xfa, 0x2d, 0x0d, 0x01, 0x3e, 0x47, 0x21, 0x1b, +0x14, 0xd5, 0x0d, 0xae, 0x3e, 0xbd, 0x94, 0x7c, 0x67, 0xc8, 0xd5, 0xbb, 0x1f, 0x2d, 0xc7, 0xf5, +0x8d, 0x46, 0xc5, 0x2a, 0xee, 0xab, 0x39, 0xa0, 0xfd, 0x7f, 0x8c, 0x7c, 0x94, 0x21, 0xee, 0x86, +0x75, 0x44, 0x20, 0x3d, 0x7b, 0xca, 0x9c, 0xc9, 0xa1, 0xc9, 0x96, 0x14, 0x41, 0x1a, 0xd3, 0xe9, +0xe9, 0x33, 0xb8, 0x6a, 0xac, 0xf2, 0x36, 0xf3, 0xef, 0xbb, 0xba, 0x40, 0x37, 0xe3, 0xcb, 0x20, +0xcc, 0xf3, 0x12, 0xde, 0x69, 0x33, 0x8e, 0xee, 0x10, 0xad, 0x12, 0x47, 0xd0, 0x5b, 0x3c, 0xe9, +0xcd, 0x24, 0x6b, 0x7c, 0xe4, 0x4e, 0x70, 0x6e, 0xde, 0x79, 0x98, 0x48, 0xda, 0x03, 0xe2, 0x03, +0xb7, 0xf3, 0xd3, 0x82, 0xd4, 0xb4, 0x0f, 0x77, 0x5a, 0xf8, 0x13, 0xa3, 0x83, 0x89, 0x74, 0x19, +0x27, 0x0d, 0x91, 0xc5, 0xa5, 0xc2, 0x4c, 0x22, 0xb1, 0xe2, 0x22, 0x8f, 0x31, 0x87, 0x4b, 0xee, +0x66, 0xc9, 0x90, 0x85, 0x5b, 0xad, 0x42, 0x61, 0x4a, 0xe5, 0x84, 0x78, 0x6e, 0x35, 0xa9, 0x8b, +0xc4, 0x81, 0x31, 0x3d, 0xce, 0xab, 0x8a, 0xba, 0x47, 0x2d, 0x1b, 0x17, 0x5d, 0x29, 0xb8, 0x06, +0x9d, 0x79, 0x64, 0xa8, 0xf6, 0x88, 0x17, 0xce, 0xdd, 0xe8, 0x85, 0xfd, 0x88, 0xa2, 0xc6, 0x25, +0x0f, 0xdd, 0x32, 0xc4, 0x1a, 0xf4, 0xcf, 0xff, 0xfe, 0xd2, 0x4b, 0x35, 0x68, 0x1d, 0x5b, 0x5e, +0x12, 0x8a, 0x6b, 0x3a, 0x33, 0x1d, 0xde, 0x3f, 0x04, 0xe1, 0x7e, 0x3b, 0x66, 0x6c, 0x10, 0xe0, +0xba, 0x22, 0x58, 0x74, 0xa5, 0x98, 0x4c, 0xca, 0xca, 0xfc, 0x18, 0xaa, 0x22, 0xfe, 0x75, 0x36, +0xd3, 0xe5, 0x43, 0x33, 0x54, 0xd9, 0xd5, 0xa0, 0x99, 0xff, 0xea, 0x14, 0x7a, 0x7d, 0xde, 0x79, +0xeb, 0x75, 0x33, 0xea, 0xd6, 0xb6, 0xd6, 0x17, 0x88, 0x8e, 0xdd, 0x17, 0xb9, 0xd4, 0xe7, 0xd9, +0x88, 0xe8, 0x84, 0x36, 0x73, 0x8f, 0x8f, 0x5e, 0xd6, 0x6c, 0xcb, 0x78, 0x50, 0xd5, 0x33, 0xb0, +0x16, 0xca, 0x70, 0x66, 0xc3, 0x05, 0x8e, 0x0d, 0x91, 0x50, 0xe9, 0xf5, 0x4b, 0x9c, 0xfe, 0x5c, +0x2d, 0x6f, 0xd3, 0xd8, 0x4d, 0xec, 0x64, 0x66, 0x5c, 0x9c, 0x8e, 0x3d, 0x4f, 0x38, 0xf4, 0x97, +0x88, 0x15, 0xda, 0x63, 0x0f, 0x37, 0x34, 0xca, 0x68, 0xdf, 0x5e, 0xbc, 0x3e, 0xc3, 0x59, 0x62, +0x1e, 0x63, 0xbd, 0x09, 0x61, 0xef, 0x1a, 0x33, 0xdb, 0xab, 0xec, 0x85, 0x8a, 0x65, 0x1d, 0xd6, +0xb9, 0x1f, 0x4f, 0x9c, 0xf2, 0x3d, 0x20, 0xc0, 0x6c, 0xf3, 0x8c, 0xd9, 0x74, 0x29, 0x11, 0x0c, +0x3a, 0xfb, 0x3e, 0xcb, 0x2e, 0x53, 0xb0, 0xf9, 0x6d, 0xe3, 0x8b, 0x47, 0xa1, 0x0e, 0x54, 0xcb, +0x2e, 0x38, 0x3f, 0xe8, 0xc0, 0x69, 0x8c, 0x19, 0x8d, 0xaf, 0x05, 0x3b, 0xa9, 0x90, 0xfb, 0x57, +0xa3, 0x77, 0xf7, 0xbc, 0x8a, 0xee, 0x61, 0xfd, 0xee, 0x34, 0x35, 0xf1, 0xfc, 0x28, 0x24, 0xf8, +0xf0, 0x3a, 0x68, 0xc7, 0x03, 0x88, 0xa7, 0x17, 0x0d, 0x3c, 0x3a, 0x21, 0xd1, 0xa1, 0xce, 0xfa, +0xc8, 0x3c, 0xf5, 0x80, 0x73, 0xec, 0x0a, 0xbe, 0xe6, 0x18, 0xba, 0xa4, 0xe4, 0x53, 0x2f, 0x70, +0xfb, 0x90, 0x11, 0x4d, 0x3b, 0xef, 0x08, 0x39, 0x2d, 0x9c, 0xbd, 0x4f, 0x9e, 0xe0, 0xbe, 0x25, +0xf3, 0x9c, 0x77, 0x58, 0xa9, 0xb1, 0x27, 0x77, 0x9b, 0x9d, 0x6d, 0xbf, 0xce, 0x1b, 0x48, 0x35, +0x5e, 0x85, 0xf3, 0x3b, 0xe4, 0x79, 0x30, 0x77, 0xc6, 0x97, 0xad, 0x07, 0xc8, 0xba, 0x1b, 0xef, +0x83, 0x6d, 0xbd, 0x75, 0x32, 0xd5, 0x0e, 0xea, 0x23, 0xb7, 0xee, 0xf7, 0x68, 0x84, 0x61, 0x93, +0x32, 0xfd, 0xa1, 0xb1, 0xf3, 0x8d, 0x1e, 0x76, 0x8d, 0x1f, 0xb0, 0x4f, 0xaf, 0xf9, 0xbc, 0x14, +0x24, 0xcc, 0x4c, 0xf1, 0x29, 0xae, 0xb3, 0xf8, 0x9c, 0x21, 0x5b, 0x50, 0xd1, 0x98, 0x3d, 0x57, +0xc1, 0x65, 0x93, 0xea, 0x7f, 0xab, 0xf1, 0x60, 0x79, 0xe0, 0xcb, 0x0a, 0xe6, 0x9a, 0xe4, 0x46, +0x9f, 0xd0, 0x44, 0x42, 0xd7, 0x4e, 0xd0, 0xd6, 0x83, 0xf0, 0xf5, 0x66, 0x52, 0x82, 0xa7, 0x62, +0x94, 0xc1, 0x50, 0x35, 0x8f, 0x85, 0x14, 0xb2, 0xd9, 0x44, 0xd5, 0xa5, 0x72, 0xa8, 0x1e, 0xf3, +0xa7, 0xa1, 0x1a, 0xce, 0xc0, 0x3a, 0xf0, 0xfc, 0xd4, 0xc3, 0x10, 0x32, 0x76, 0xc4, 0x60, 0xd4, +0x63, 0x5a, 0x49, 0xc4, 0x2b, 0x65, 0x48, 0xdb, 0x8f, 0xf0, 0x57, 0x23, 0x22, 0x8b, 0xed, 0x76, +0x62, 0x87, 0x25, 0x20, 0xf5, 0x05, 0x4c, 0xce, 0x58, 0x00, 0x8f, 0x37, 0x73, 0x59, 0x60, 0xec, +0x6c, 0x74, 0x13, 0xcf, 0x75, 0x1a, 0xde, 0x6e, 0xca, 0xd5, 0xfd, 0x2a, 0x15, 0x19, 0xfc, 0x63, +0xd0, 0x6e, 0x30, 0xc2, 0xc8, 0xf3, 0x12, 0xcb, 0x1d, 0xe8, 0x3a, 0x8c, 0x4d, 0xbe, 0x3f, 0x55, +0xdb, 0x35, 0xbd, 0x10, 0xa6, 0x08, 0xe2, 0x33, 0xd9, 0x49, 0x8b, 0x84, 0xd4, 0xe1, 0xb0, 0x52, +0x87, 0x47, 0xd8, 0x6a, 0x83, 0x11, 0xbd, 0xa4, 0xf1, 0x5a, 0xdb, 0xec, 0xfe, 0x5a, 0x15, 0xa4, +0xa5, 0x75, 0x4e, 0x13, 0x2c, 0x6e, 0x00, 0xed, 0x18, 0xa1, 0xb9, 0x9d, 0x77, 0xbc, 0xd5, 0x5f, +0xb2, 0x1b, 0x3e, 0xef, 0xf9, 0x5b, 0x02, 0x61, 0x05, 0x66, 0xf7, 0xb8, 0x37, 0x08, 0xbb, 0x35, +0x87, 0x99, 0xa4, 0x13, 0xd6, 0xed, 0xc7, 0x49, 0xab, 0x0e, 0x31, 0xae, 0xd4, 0x49, 0x4f, 0xc4, +0xaf, 0x18, 0xdf, 0xce, 0xc3, 0x57, 0x39, 0x77, 0xc9, 0xd1, 0x4a, 0xf9, 0x3a, 0x11, 0x4b, 0x34, +0x10, 0x22, 0x4b, 0x97, 0x01, 0xb8, 0x38, 0xd4, 0xff, 0x12, 0x1f, 0xa2, 0x62, 0xaa, 0x0f, 0x71, +0x3d, 0x84, 0xfa, 0xf5, 0x7d, 0xd7, 0x6e, 0x43, 0x78, 0xdb, 0xeb, 0x3f, 0x8b, 0x3e, 0x55, 0xb5, +0xcc, 0xe1, 0xb0, 0x0d, 0x9c, 0x46, 0xb4, 0x54, 0x1a, 0xb6, 0xa2, 0x9b, 0xac, 0x5a, 0xda, 0x1f, +0x04, 0xe8, 0x43, 0xca, 0x06, 0x37, 0xf8, 0xc3, 0x27, 0x37, 0xbe, 0x46, 0x46, 0x19, 0xe0, 0x26, +0x70, 0xa2, 0xce, 0xbe, 0x59, 0xb5, 0x2e, 0xef, 0xe2, 0xae, 0xb5, 0x2c, 0xa6, 0x89, 0x76, 0x91, +0xb1, 0x6c, 0x45, 0x1e, 0xd3, 0x55, 0x72, 0xb5, 0xb5, 0xfe, 0x37, 0x81, 0x98, 0x62, 0x79, 0xb5, +0x56, 0xc6, 0xea, 0x97, 0xfd, 0x3f, 0x6c, 0x4b, 0x40, 0x8c, 0xb7, 0x5b, 0x8b, 0x77, 0x00, 0x0d, +0xf1, 0xb3, 0xd1, 0xc6, 0xe7, 0xd0, 0x5a, 0xc5, 0xeb, 0x91, 0xae, 0xe0, 0x99, 0x2a, 0xb0, 0xb2, +0x00, 0xbe, 0xca, 0x3f, 0x6a, 0xea, 0x72, 0xf3, 0xfd, 0xbc, 0x40, 0x36, 0x77, 0x03, 0x28, 0x5a, +0x77, 0xa8, 0xa4, 0x5c, 0x6a, 0x51, 0x9a, 0x3e, 0x0e, 0x93, 0x40, 0x9d, 0x9f, 0x68, 0xf4, 0x47, +0x16, 0xa6, 0xf1, 0x57, 0xdc, 0x9d, 0x96, 0xd7, 0x02, 0x55, 0xf4, 0x56, 0x5c, 0x81, 0xf1, 0x6e, +0x74, 0x45, 0xea, 0xbe, 0x16, 0x7d, 0x21, 0x31, 0xa2, 0x19, 0x51, 0x7b, 0x61, 0xe6, 0xb0, 0xc2, +0xf8, 0xf3, 0xce, 0x1f, 0x5c, 0xad, 0xc5, 0xbf, 0x23, 0x82, 0x38, 0x35, 0xa0, 0x95, 0xa5, 0x95, +0xb9, 0x94, 0x40, 0xe9, 0x8b, 0x4b, 0xd7, 0xe8, 0x62, 0x18, 0x75, 0x67, 0x23, 0xe3, 0x52, 0xb9, +0xa3, 0xf5, 0xc0, 0x1e, 0xb1, 0xfb, 0x56, 0x1c, 0xa7, 0x46, 0x00, 0xaa, 0xa1, 0x96, 0xb3, 0xab, +0x81, 0xdf, 0x7c, 0x9c, 0x59, 0xbd, 0x47, 0x2c, 0x8a, 0x18, 0xb5, 0x98, 0x9e, 0xb7, 0x60, 0xfd, +0x97, 0xfa, 0x9d, 0x92, 0x7b, 0xcc, 0x4c, 0x2a, 0xa5, 0x6d, 0x42, 0x18, 0x48, 0xbd, 0xfd, 0x28, +0xcd, 0xc0, 0x05, 0xc6, 0x88, 0xee, 0x1b, 0xc4, 0xb1, 0x52, 0xe0, 0xb5, 0x1e, 0x2f, 0xbb, 0x1f, +0x41, 0xad, 0x61, 0xa8, 0x8c, 0xdd, 0x4a, 0x40, 0xd6, 0x9c, 0xea, 0x3f, 0x9e, 0xb2, 0x9c, 0xca, +0x18, 0xed, 0x95, 0x02, 0xe6, 0xeb, 0xef, 0xe1, 0xfa, 0xe2, 0x54, 0x8f, 0x95, 0x52, 0x00, 0x4c, +0xb1, 0xdf, 0x88, 0x72, 0x31, 0x7f, 0xc8, 0x2c, 0xe5, 0x1f, 0x44, 0xe3, 0x92, 0xde, 0xed, 0x0d, +0xd6, 0x58, 0x25, 0x73, 0x87, 0x82, 0xd4, 0x28, 0xcc, 0x73, 0xd6, 0x16, 0x43, 0xc1, 0x25, 0xb1, +0x99, 0x6e, 0x89, 0x94, 0xb3, 0xad, 0x90, 0xb5, 0xfb, 0x54, 0x20, 0xb7, 0xb5, 0xdf, 0xe3, 0x05, +0x31, 0xc9, 0x02, 0x78, 0x33, 0x88, 0x82, 0xb9, 0xd9, 0x39, 0xed, 0x38, 0x53, 0xe9, 0xde, 0x2a, +0x6b, 0x48, 0xb4, 0x94, 0x43, 0x6a, 0x5c, 0x33, 0x26, 0xdb, 0x79, 0x8a, 0x09, 0xfb, 0x07, 0x35, +0x7b, 0x82, 0x08, 0x58, 0x96, 0x90, 0x40, 0xa1, 0xb5, 0xcb, 0x92, 0xcc, 0x0d, 0x3b, 0xd1, 0x47, +0x6d, 0x05, 0x40, 0xf7, 0x66, 0x7c, 0x8b, 0x5b, 0xe6, 0xc7, 0xdd, 0x6e, 0x11, 0xcc, 0x21, 0xbf, +0xfe, 0x77, 0x75, 0x4a, 0xcf, 0x3c, 0xf1, 0x86, 0x1d, 0x32, 0x15, 0xe4, 0xf4, 0x5a, 0x0d, 0x5f, +0xfe, 0x71, 0x26, 0xa2, 0x70, 0xd6, 0xdd, 0xd7, 0xe3, 0xd1, 0x5c, 0x8b, 0xbf, 0x5d, 0x2e, 0xee, +0xe9, 0x74, 0xe2, 0x79, 0xf4, 0x08, 0x8c, 0xd9, 0x26, 0x12, 0x26, 0x68, 0xf7, 0xc7, 0x3b, 0xda, +0xbe, 0x2f, 0x81, 0xb6, 0x81, 0xd9, 0xd5, 0x7c, 0x18, 0xf1, 0x7e, 0x2c, 0xad, 0xb9, 0xfd, 0x47, +0x29, 0xd5, 0x1a, 0x4f, 0x7f, 0x8f, 0x10, 0x05, 0x98, 0x53, 0x46, 0xc4, 0xa0, 0xa4, 0x54, 0x40, +0xfc, 0xfc, 0xf6, 0x26, 0xad, 0x40, 0xf7, 0x96, 0xcd, 0x15, 0x2e, 0x15, 0xfe, 0xc4, 0xd7, 0xb8, +0x4b, 0xc6, 0x80, 0xd1, 0xa6, 0x7c, 0x1d, 0x17, 0x16, 0xbf, 0x01, 0xdb, 0xd0, 0x7d, 0x88, 0x63, +0xbf, 0xb8, 0xaf, 0x25, 0xe3, 0x6d, 0xa3, 0xd3, 0xb3, 0x6c, 0x39, 0x18, 0xf6, 0x91, 0xda, 0xb8, +0x45, 0x11, 0x8e, 0x14, 0x7d, 0x19, 0x79, 0xd8, 0xb3, 0x02, 0x1d, 0xa5, 0x9c, 0xd5, 0x39, 0xda, +0xe4, 0x15, 0x86, 0x07, 0x8b, 0x05, 0xc9, 0x95, 0x65, 0x5b, 0x67, 0x20, 0x8f, 0xc7, 0x3b, 0xda, +0xc1, 0x08, 0xec, 0x8f, 0xd4, 0x9f, 0xa2, 0x15, 0x61, 0xe1, 0xfa, 0x79, 0x30, 0x51, 0x11, 0xab, +0xf3, 0x85, 0xe8, 0x5c, 0xb4, 0x26, 0x01, 0xf4, 0x82, 0x52, 0x6b, 0xd8, 0x97, 0x72, 0x60, 0x36, +0xaf, 0xc3, 0x5e, 0xa1, 0x40, 0x71, 0x67, 0x29, 0xce, 0x65, 0xa4, 0x6d, 0x10, 0xc0, 0xb6, 0xbf, +0x53, 0xea, 0x9b, 0x36, 0xee, 0xd4, 0x6e, 0x78, 0xb0, 0x44, 0x29, 0xd4, 0x00, 0x25, 0xbf, 0xa0, +0x81, 0x3a, 0xf0, 0xce, 0xba, 0x29, 0x2c, 0xd8, 0x90, 0x36, 0x90, 0x66, 0x35, 0x66, 0xad, 0x8e, +0x90, 0xf3, 0x3f, 0x9d, 0xb1, 0x6f, 0xd1, 0x86, 0xf2, 0xc9, 0x1d, 0xab, 0xfa, 0x32, 0x5e, 0x80, +0xb3, 0xaf, 0x08, 0x2a, 0xe5, 0x52, 0x2a, 0xd2, 0xeb, 0xf1, 0x62, 0x59, 0x2a, 0x62, 0xbd, 0x29, +0x07, 0x26, 0x27, 0x03, 0x09, 0xd5, 0xbf, 0xe9, 0xd4, 0x78, 0x22, 0x3d, 0xb3, 0xf7, 0x27, 0xcf, +0x79, 0x2b, 0x65, 0x73, 0x40, 0xbd, 0xbd, 0x55, 0x74, 0xb4, 0xf8, 0x2b, 0xba, 0x91, 0x27, 0x81, +0x00, 0x5c, 0xea, 0x17, 0x07, 0x8e, 0xef, 0x9b, 0x7d, 0x1f, 0xc1, 0x23, 0x15, 0xa8, 0x4d, 0x21, +0x38, 0x71, 0x62, 0xd6, 0xff, 0x36, 0x08, 0x27, 0x46, 0x82, 0xf3, 0xc2, 0xd9, 0x65, 0x4c, 0x0b, +0xc2, 0xd9, 0x1c, 0xaf, 0xef, 0x28, 0xa7, 0x6f, 0x70, 0x02, 0x25, 0x36, 0x2e, 0xc2, 0xe0, 0xfa, +0xb7, 0xf0, 0x28, 0xf1, 0x23, 0xd2, 0xb0, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0x1a, 0xf0, 0x2a, 0xf4, 0x2f, 0x0f, 0xb9, 0x67, 0x7b, 0xba, 0x98, 0x08, 0xd7, 0x97, 0xff, 0xce, +0xb6, 0x39, 0xdf, 0x59, 0xa4, 0x70, 0x97, 0xa3, 0xe1, 0x95, 0x29, 0x1d, 0x06, 0x8a, 0x55, 0x24, +0x2c, 0x63, 0x21, 0x95, 0xb6, 0xa8, 0xf0, 0x91, 0x8d, 0x62, 0x0b, 0x7d, 0x4d, 0x84, 0x5b, 0x28, +0x22, 0xea, 0xf9, 0xb6, 0x3d, 0x70, 0x8c, 0xc7, 0x1a, 0x4d, 0x41, 0x1a, 0x52, 0xed, 0x1e, 0xbb, +0xc7, 0x7e, 0xd0, 0xdb, 0x7a, 0xe3, 0xa1, 0x27, 0xeb, 0x11, 0x73, 0x49, 0x03, 0xba, 0x0c, 0xfd, +0x86, 0x6a, 0x36, 0x99, 0x39, 0xb7, 0xc9, 0x25, 0xd8, 0xf1, 0xf9, 0xad, 0x79, 0xfc, 0xa1, 0xac, +0x7b, 0xfd, 0x31, 0x5e, 0x2d, 0x8b, 0x92, 0x99, 0x26, 0x60, 0xdd, 0x85, 0x0a, 0x34, 0x5a, 0x6e, +0xa3, 0x31, 0xab, 0x62, 0xf7, 0xa0, 0x7b, 0xfa, 0xcf, 0xbd, 0x7b, 0x32, 0xf9, 0x88, 0xfe, 0x26, +0xfe, 0xde, 0xf3, 0x82, 0x28, 0xe3, 0xcd, 0x84, 0xcc, 0x74, 0x8b, 0xb4, 0x00, 0x1c, 0x64, 0x28, +0xf7, 0x6d, 0x60, 0xf1, 0xfe, 0x2d, 0xc5, 0xe6, 0x97, 0x80, 0x2a, 0xe2, 0xb9, 0xeb, 0x94, 0x90, +0xfe, 0x6d, 0x34, 0xed, 0xe6, 0x63, 0xa6, 0xae, 0xe9, 0x9b, 0x47, 0x11, 0x8d, 0x7d, 0xb6, 0x05, +0x39, 0x48, 0xd5, 0x73, 0x93, 0x80, 0x3a, 0x87, 0xd2, 0xa8, 0x03, 0xc3, 0x1b, 0x96, 0xe8, 0xfa, +0x46, 0x93, 0x3d, 0xe1, 0x9c, 0xb4, 0x0d, 0x21, 0x55, 0x78, 0x6d, 0x5c, 0x34, 0x28, 0x9b, 0xb8, +0x00, 0xc0, 0x09, 0x00, 0x02, 0x01, 0x30, 0x30, 0x5f, 0x30, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, +0x32, 0x30, 0x31, 0x34, 0x30, 0x33, 0x30, 0x36, 0x2d, 0x32, 0x31, 0x31, 0x33, 0x33, 0x34, 0x00, +0x0c, 0x60, 0x03, 0x00, 0x00, 0xcc, 0x09, 0x02, 0x02, 0x01, 0x30, 0x30, 0x5f, 0x30, 0x31, 0x00, +0x00, 0x00, 0x00, 0x00, 0x32, 0x30, 0x31, 0x34, 0x30, 0x33, 0x30, 0x36, 0x2d, 0x32, 0x31, 0x31, +0x33, 0x33, 0x34, 0x00, 0x0c, 0x1d, 0x00, 0x00, } ; diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7636_rom_patch.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7636_rom_patch.h new file mode 100644 index 000000000..81511427a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7636_rom_patch.h @@ -0,0 +1,97 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR mt7636_rom_patch[] = { +0x32, 0x30, 0x31, 0x34, 0x30, 0x32, 0x31, 0x34, 0x31, 0x36, 0x32, 0x35, 0x31, 0x35, 0x61, 0x0a, +0x41, 0x4c, 0x50, 0x53, 0x8a, 0x10, 0x8a, 0x10, 0x00, 0x00, 0x00, 0x10, 0x30, 0x4d, 0x01, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0xc2, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x20, 0x9a, 0x58, 0x00, 0x0c, 0x00, 0x46, 0x10, +0x00, 0x8c, 0x58, 0x10, 0x85, 0xa0, 0x46, 0x20, 0x20, 0x9a, 0x58, 0x21, 0x0c, 0x00, 0xd5, 0x03, +0xa2, 0xc9, 0xaa, 0xc1, 0xe2, 0x02, 0xe9, 0xfd, 0xdd, 0x9e, 0x46, 0x00, 0x20, 0x9a, 0x58, 0x00, +0x0c, 0x00, 0x46, 0x20, 0x20, 0x9a, 0x58, 0x21, 0x0c, 0x0a, 0x84, 0x20, 0xd5, 0x02, 0xaa, 0x41, +0xe2, 0x02, 0xe9, 0xfe, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x20, 0x90, +0x04, 0x27, 0x82, 0x0b, 0x84, 0x22, 0x84, 0x01, 0xdd, 0x22, 0x84, 0x00, 0xec, 0x04, 0x3b, 0xff, +0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x46, 0x05, 0x00, 0x29, 0xa0, 0x06, 0x42, 0x00, 0x78, 0x0b, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x84, 0x21, 0x96, 0x00, 0x4c, 0x00, 0x80, 0x06, +0x84, 0xa2, 0xd0, 0x09, 0x84, 0x00, 0xd5, 0x0c, 0x46, 0xf0, 0x00, 0x8c, 0x58, 0xf7, 0x82, 0x48, +0xdd, 0x2f, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x8c, 0x58, 0xf7, 0x82, 0x68, 0xdd, 0x2f, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, 0x46, 0xf0, 0x00, 0x8c, +0x58, 0xf7, 0x82, 0x08, 0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x8c, 0x58, 0xf7, 0x82, 0x2c, 0xdd, 0x2f, +0x46, 0x08, 0x10, 0x70, 0x04, 0x00, 0x00, 0x18, 0x42, 0x00, 0x30, 0x0b, 0xc8, 0x0c, 0x46, 0xf0, +0x20, 0x90, 0x04, 0x07, 0x81, 0x1f, 0xdd, 0x20, 0x46, 0x08, 0x10, 0x20, 0xa0, 0x44, 0x42, 0x10, +0xc4, 0x08, 0xa8, 0x44, 0x46, 0x18, 0x10, 0x21, 0x04, 0x20, 0x81, 0x07, 0x46, 0x37, 0xff, 0xff, +0x58, 0x31, 0x8f, 0xff, 0x40, 0x21, 0x0c, 0x02, 0x14, 0x20, 0x81, 0x07, 0x46, 0x08, 0x10, 0x21, +0x04, 0x20, 0x01, 0x09, 0x46, 0x18, 0x10, 0x21, 0x40, 0x21, 0x0c, 0x02, 0x14, 0x20, 0x01, 0x09, +0x04, 0x20, 0x81, 0x0c, 0x44, 0x00, 0x00, 0x3d, 0x40, 0x21, 0x0c, 0x02, 0x14, 0x20, 0x81, 0x0c, +0x50, 0x1f, 0x80, 0x07, 0x84, 0x41, 0x46, 0xf0, 0x00, 0x13, 0x58, 0xf7, 0x86, 0x44, 0xdd, 0x2f, +0x00, 0x0f, 0x80, 0x07, 0x54, 0x00, 0x00, 0x04, 0xc0, 0x17, 0x46, 0x18, 0x10, 0x23, 0xa0, 0x8d, +0x44, 0x3f, 0xff, 0x8f, 0x40, 0x21, 0x0c, 0x02, 0x58, 0x21, 0x00, 0x10, 0xa8, 0x8d, 0x46, 0x08, +0x10, 0x21, 0x58, 0x00, 0x01, 0x00, 0xb4, 0x20, 0x44, 0x2c, 0xff, 0xff, 0x40, 0x10, 0x88, 0x02, +0x44, 0x31, 0x00, 0x00, 0xd5, 0x0c, 0x46, 0x08, 0x10, 0x21, 0x58, 0x00, 0x01, 0x00, 0xb4, 0x20, +0x44, 0x2c, 0xff, 0xff, 0x40, 0x10, 0x88, 0x02, 0x44, 0x32, 0x00, 0x00, 0x40, 0x10, 0x8c, 0x04, +0xb6, 0x20, 0x46, 0x08, 0x10, 0x21, 0x04, 0x20, 0x00, 0x81, 0x92, 0x54, 0x40, 0x21, 0x50, 0x08, +0x46, 0x30, 0x00, 0xbb, 0x58, 0x31, 0x82, 0x61, 0x40, 0x21, 0x0c, 0x04, 0x14, 0x20, 0x00, 0x81, +0x46, 0x18, 0x10, 0x21, 0x04, 0x20, 0x80, 0x82, 0x92, 0x54, 0x40, 0x21, 0x50, 0x08, 0x46, 0x30, +0x00, 0xbb, 0x58, 0x31, 0x82, 0x61, 0x40, 0x21, 0x0c, 0x04, 0x14, 0x20, 0x80, 0x82, 0x46, 0x08, +0x10, 0x21, 0x04, 0x10, 0x00, 0x83, 0x46, 0x2f, 0xff, 0x00, 0x40, 0x10, 0x88, 0x02, 0x40, 0x10, +0x8c, 0x04, 0x14, 0x10, 0x00, 0x83, 0x46, 0x68, 0x10, 0x21, 0x58, 0x63, 0x02, 0x10, 0xb4, 0x26, +0x46, 0x08, 0x10, 0x21, 0x40, 0x10, 0x88, 0x02, 0x40, 0x10, 0x8c, 0x04, 0xb6, 0x26, 0x04, 0x20, +0x00, 0x85, 0x92, 0x54, 0x40, 0x21, 0x50, 0x08, 0x46, 0x30, 0x00, 0xaa, 0x58, 0x31, 0x88, 0x61, +0x40, 0x21, 0x0c, 0x04, 0x14, 0x20, 0x00, 0x85, 0x46, 0x18, 0x10, 0x21, 0x04, 0x20, 0x80, 0x86, +0x92, 0x54, 0x40, 0x21, 0x50, 0x08, 0x46, 0x30, 0x00, 0x9a, 0x58, 0x31, 0x88, 0x4b, 0x40, 0x21, +0x0c, 0x04, 0x14, 0x20, 0x80, 0x86, 0x46, 0x08, 0x10, 0x21, 0x04, 0x20, 0x00, 0x87, 0x92, 0x54, +0x40, 0x21, 0x50, 0x08, 0x46, 0x30, 0x00, 0x89, 0x58, 0x31, 0x8e, 0x2d, 0x40, 0x21, 0x0c, 0x04, +0x14, 0x20, 0x00, 0x87, 0x46, 0x18, 0x10, 0x21, 0x04, 0x20, 0x80, 0x88, 0x92, 0x54, 0x40, 0x21, +0x50, 0x08, 0x46, 0x30, 0x00, 0x81, 0x58, 0x31, 0x8e, 0x0f, 0x40, 0x21, 0x0c, 0x04, 0x14, 0x20, +0x80, 0x88, 0x46, 0x08, 0x10, 0x21, 0x04, 0x20, 0x00, 0x89, 0x92, 0x54, 0x40, 0x21, 0x50, 0x08, +0x46, 0x30, 0x00, 0x81, 0x58, 0x31, 0x8e, 0x0f, 0x40, 0x21, 0x0c, 0x04, 0x14, 0x20, 0x00, 0x89, +0x46, 0x18, 0x10, 0x21, 0x04, 0x20, 0x80, 0x8a, 0x92, 0x54, 0x40, 0x21, 0x50, 0x08, 0x46, 0x30, +0x00, 0x91, 0x58, 0x31, 0x8e, 0x2d, 0x40, 0x21, 0x0c, 0x04, 0x14, 0x20, 0x80, 0x8a, 0x46, 0x08, +0x10, 0x21, 0x04, 0x10, 0x00, 0x8b, 0x46, 0x30, 0x00, 0xa2, 0x92, 0x34, 0x40, 0x10, 0xd0, 0x08, +0x58, 0x31, 0x88, 0x4b, 0x40, 0x10, 0x8c, 0x04, 0x14, 0x10, 0x00, 0x8b, 0x46, 0x70, 0x00, 0x13, +0x58, 0x73, 0x86, 0x44, 0x44, 0x00, 0x00, 0xbb, 0x50, 0x1f, 0x80, 0x06, 0x84, 0x41, 0x4b, 0xe0, +0x1c, 0x01, 0xc8, 0x43, 0x20, 0x0f, 0x80, 0x06, 0x4e, 0x04, 0x00, 0x40, 0x44, 0x00, 0x00, 0xbc, +0x50, 0x1f, 0x80, 0x05, 0x84, 0x41, 0x4b, 0xe0, 0x1c, 0x01, 0xc8, 0x37, 0x00, 0x0f, 0x80, 0x05, +0x96, 0x42, 0x4e, 0x14, 0x00, 0x25, 0x54, 0x20, 0x00, 0x40, 0x00, 0x1f, 0x80, 0x06, 0x54, 0x00, +0x00, 0x3f, 0xc2, 0x0e, 0x54, 0x10, 0x80, 0x7f, 0x9a, 0x08, 0xb4, 0x46, 0x40, 0x00, 0x20, 0x08, +0x44, 0x1f, 0x80, 0xff, 0x54, 0x00, 0x7f, 0x00, 0x40, 0x21, 0x04, 0x02, 0xd5, 0x0d, 0x54, 0x10, +0x80, 0x7f, 0x98, 0x01, 0xb4, 0x46, 0x40, 0x00, 0x20, 0x08, 0x44, 0x3f, 0x80, 0xff, 0x54, 0x00, +0x7f, 0x00, 0x40, 0x21, 0x0c, 0x02, 0x40, 0x00, 0x08, 0x04, 0xd5, 0x0e, 0x00, 0x1f, 0x80, 0x06, +0xb4, 0x06, 0x54, 0x10, 0x80, 0x7f, 0x44, 0x2f, 0x80, 0xff, 0x40, 0x10, 0xa0, 0x08, 0x40, 0x00, +0x08, 0x02, 0x40, 0x00, 0x80, 0x04, 0xb6, 0x06, 0x46, 0x18, 0x10, 0x21, 0x04, 0x20, 0x80, 0x80, +0x46, 0x08, 0x00, 0x21, 0x42, 0x21, 0x78, 0x08, 0x14, 0x20, 0x80, 0x80, 0x04, 0x10, 0x00, 0x42, +0x58, 0x10, 0x80, 0x04, 0x14, 0x10, 0x00, 0x42, 0x46, 0x10, 0x00, 0x8c, 0x58, 0x10, 0x82, 0x74, +0x46, 0xf0, 0x20, 0x90, 0x14, 0x17, 0x82, 0xff, 0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, } ; diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7662_rom_patch.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7662_rom_patch.h new file mode 100644 index 000000000..b30aae993 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mcu/mt7662_rom_patch.h @@ -0,0 +1,731 @@ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ +/* AUTO GEN PLEASE DO NOT MODIFY IT */ + + +UCHAR mt7662_rom_patch[] = { +0x32, 0x30, 0x31, 0x33, 0x30, 0x39, 0x30, 0x35, 0x30, 0x36, 0x30, 0x37, 0x30, 0x33, 0x61, 0x0a, +0x41, 0x4c, 0x50, 0x53, 0x8a, 0x10, 0x8a, 0x10, 0x00, 0x00, 0x00, 0x10, 0x26, 0x5f, 0xff, 0x03, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x48, 0x00, 0x00, 0x58, 0x1d, 0x00, 0x00, 0x0c, 0x83, +0x05, 0x00, 0xc0, 0xee, 0x03, 0x00, 0xd8, 0x78, 0x02, 0x00, 0x58, 0xf9, 0x04, 0x00, 0x9c, 0xda, +0x02, 0x00, 0x70, 0xfe, 0x04, 0x00, 0xf4, 0x64, 0x02, 0x00, 0xb8, 0xe6, 0x03, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x09, 0x09, 0x00, 0xb8, 0x07, 0x09, 0x00, 0xb4, 0x08, +0x09, 0x00, 0xac, 0x09, 0x09, 0x00, 0x58, 0x1a, 0x09, 0x00, 0x10, 0x2a, 0x09, 0x00, 0x4c, 0x17, +0x09, 0x00, 0xe8, 0x14, 0x09, 0x00, 0x14, 0x14, 0x09, 0x00, 0xe0, 0x0e, 0x09, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x01, 0x20, 0x58, 0x00, 0x08, 0x00, 0x46, 0x10, +0x00, 0x92, 0x58, 0x10, 0x8d, 0x28, 0x46, 0x20, 0x01, 0x20, 0x58, 0x21, 0x08, 0x0c, 0xd5, 0x03, +0xa2, 0xc9, 0xaa, 0xc1, 0xe2, 0x02, 0xe9, 0xfd, 0xdd, 0x9e, 0x46, 0x00, 0x01, 0x20, 0x58, 0x00, +0x08, 0x0c, 0x46, 0x20, 0x01, 0x20, 0x58, 0x21, 0x08, 0xfc, 0x84, 0x20, 0xd5, 0x02, 0xaa, 0x41, +0xe2, 0x02, 0xe9, 0xfe, 0xdd, 0x9e, 0xdd, 0x9e, 0x92, 0x00, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0x7c, 0x10, 0x0f, 0x80, 0x04, 0x84, 0x02, 0x10, 0x0f, 0x80, 0x00, 0x84, 0x07, +0x10, 0x0f, 0x80, 0x01, 0x84, 0x01, 0x10, 0x0f, 0x80, 0x02, 0x84, 0x00, 0x10, 0x0f, 0x80, 0x03, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x80, 0x65, 0x84, 0x25, 0x80, 0x1f, 0xdd, 0x22, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x07, 0x80, 0x67, 0xdd, 0x20, 0xec, 0x84, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x96, 0x00, 0xc0, 0x0d, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x4c, 0xb4, 0x20, +0x58, 0x10, 0x80, 0x30, 0xb6, 0x20, 0xb4, 0x20, 0x42, 0x10, 0x84, 0x09, 0xd5, 0x0e, 0x46, 0x00, +0x04, 0x00, 0x58, 0x00, 0x00, 0x4c, 0xb4, 0x20, 0x44, 0x2f, 0xff, 0xcf, 0x40, 0x10, 0x88, 0x02, +0xb6, 0x20, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x02, 0xb6, 0x20, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x00, 0x00, 0x07, 0x83, 0x00, 0x84, 0xa4, 0xd0, 0x0b, +0x84, 0xa6, 0xd0, 0x07, 0x84, 0xa7, 0xd0, 0x05, 0x84, 0xa8, 0x4c, 0x02, 0xc1, 0x38, 0xd5, 0x03, +0x84, 0xc0, 0xd5, 0x02, 0x84, 0xc1, 0x46, 0xf0, 0x01, 0x02, 0x04, 0x07, 0x83, 0xdc, 0x44, 0x50, +0x00, 0xc0, 0x54, 0x20, 0x00, 0xc0, 0xda, 0x6b, 0x46, 0xf0, 0x01, 0x02, 0x00, 0x17, 0x8f, 0x85, +0x54, 0x10, 0x80, 0x10, 0xc1, 0x64, 0xce, 0x37, 0x46, 0xf0, 0x01, 0x00, 0x02, 0x57, 0x81, 0x78, +0x84, 0x81, 0xd4, 0x06, 0x46, 0xf0, 0x01, 0x00, 0x02, 0x57, 0x81, 0x79, 0xdc, 0x2c, 0x46, 0x10, +0x04, 0x00, 0x04, 0x30, 0x80, 0x10, 0x96, 0xd9, 0x14, 0x30, 0x80, 0x10, 0x44, 0x1f, 0xc8, 0x30, +0x46, 0xf0, 0x01, 0x02, 0x04, 0x67, 0x83, 0xda, 0x40, 0x00, 0x04, 0x02, 0x54, 0x63, 0x06, 0xc6, +0x40, 0x03, 0x00, 0x04, 0x46, 0xf0, 0x01, 0x02, 0x14, 0x07, 0x83, 0xdc, 0x42, 0x63, 0x40, 0x08, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x80, 0x9c, 0x80, 0x26, 0x44, 0x00, 0x00, 0x2e, 0xdd, 0x22, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x80, 0x9d, 0x80, 0x26, 0x44, 0x00, 0x00, 0x2d, 0xdd, 0x22, +0x48, 0x00, 0x00, 0x81, 0x46, 0x10, 0x04, 0x00, 0x04, 0x30, 0x80, 0x10, 0x46, 0x46, 0xf0, 0x00, +0x40, 0x31, 0x90, 0x04, 0x14, 0x30, 0x80, 0x10, 0x46, 0xf0, 0x01, 0x02, 0x04, 0x77, 0x83, 0xda, +0x44, 0x1f, 0xc8, 0x30, 0x40, 0x00, 0x04, 0x02, 0x54, 0x73, 0x91, 0xc9, 0x40, 0x03, 0x80, 0x04, +0x46, 0xf0, 0x01, 0x02, 0x14, 0x07, 0x83, 0xdc, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x80, 0x9c, +0x42, 0x73, 0xc0, 0x08, 0x80, 0x27, 0x44, 0x00, 0x00, 0x2e, 0xdd, 0x22, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x27, 0x80, 0x9d, 0x80, 0x27, 0x44, 0x00, 0x00, 0x2d, 0xd5, 0x52, 0x46, 0x10, 0x04, 0x00, +0x04, 0x30, 0x80, 0x10, 0x96, 0xd9, 0x14, 0x30, 0x80, 0x10, 0x44, 0x50, 0x00, 0xc0, 0xda, 0x1d, +0x44, 0x2f, 0xc8, 0x30, 0x40, 0x00, 0x08, 0x02, 0x58, 0x00, 0x00, 0xc1, 0x46, 0xf0, 0x01, 0x02, +0x14, 0x07, 0x83, 0xdc, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x80, 0x9c, 0x44, 0x11, 0x00, 0xc1, +0x44, 0x00, 0x00, 0x2e, 0xdd, 0x22, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x80, 0x9d, 0x44, 0x11, +0x00, 0xc1, 0x44, 0x00, 0x00, 0x2d, 0xd5, 0x2c, 0x54, 0x10, 0x00, 0x80, 0xc1, 0x14, 0x44, 0x3f, +0xc8, 0x30, 0x40, 0x00, 0x0c, 0x02, 0x58, 0x00, 0x04, 0x81, 0x46, 0xf0, 0x01, 0x02, 0x14, 0x07, +0x83, 0xdc, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x80, 0x9c, 0x44, 0x11, 0x04, 0x81, 0x44, 0x00, +0x00, 0x2e, 0xd5, 0x16, 0x54, 0x10, 0x00, 0x40, 0xc1, 0x14, 0x44, 0x4f, 0xc8, 0x30, 0x40, 0x00, +0x10, 0x02, 0x58, 0x00, 0x00, 0x41, 0x46, 0xf0, 0x01, 0x02, 0x14, 0x07, 0x83, 0xdc, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x27, 0x80, 0x9d, 0x44, 0x11, 0x00, 0x41, 0x44, 0x00, 0x00, 0x2d, 0xdd, 0x22, +0xce, 0x10, 0x46, 0xf0, 0x01, 0x02, 0x04, 0x17, 0x83, 0xdc, 0x96, 0x0c, 0xc0, 0x05, 0x54, 0x10, +0x80, 0x40, 0xc1, 0x07, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x90, 0x58, 0xf7, 0x82, 0x94, 0xdd, 0x2f, +0x46, 0x00, 0x01, 0x02, 0x58, 0x00, 0x0f, 0x68, 0xa0, 0x42, 0x54, 0x10, 0x81, 0x00, 0xc1, 0x16, +0x20, 0x10, 0x00, 0x19, 0x84, 0xbf, 0xd9, 0x05, 0x00, 0x30, 0x00, 0x3b, 0x10, 0x30, 0x00, 0x19, +0x46, 0xf0, 0x01, 0x02, 0x00, 0x17, 0x8f, 0x81, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x80, 0x9d, +0x42, 0x10, 0xc4, 0x08, 0x44, 0x00, 0x00, 0x2d, 0xdd, 0x22, 0x46, 0x00, 0x01, 0x02, 0x58, 0x00, +0x0f, 0x68, 0xa0, 0x42, 0x54, 0x10, 0x90, 0x00, 0xc1, 0x16, 0x20, 0x10, 0x00, 0x1b, 0x84, 0xbf, +0xd9, 0x05, 0x00, 0x30, 0x00, 0x41, 0x10, 0x30, 0x00, 0x1b, 0x46, 0xf0, 0x01, 0x02, 0x00, 0x17, +0x8f, 0x83, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x80, 0x9c, 0x42, 0x10, 0xe0, 0x08, 0x44, 0x00, +0x00, 0x2e, 0xdd, 0x22, 0x46, 0xf0, 0x01, 0x02, 0x04, 0x07, 0x83, 0xdc, 0x54, 0x10, 0x00, 0x04, +0x54, 0x00, 0x00, 0x80, 0xc1, 0x0e, 0xc0, 0x1a, 0x46, 0x00, 0x04, 0x11, 0x58, 0x00, 0x02, 0x3c, +0xb4, 0x20, 0x58, 0x10, 0x80, 0x01, 0xb6, 0x20, 0xb4, 0x20, 0x58, 0x10, 0x80, 0x04, 0xd5, 0x0d, +0xc0, 0x0d, 0x46, 0x00, 0x04, 0x11, 0x58, 0x00, 0x02, 0x3c, 0xb4, 0x20, 0x42, 0x10, 0x88, 0x09, +0xb6, 0x20, 0xb4, 0x20, 0x42, 0x10, 0x80, 0x09, 0xb6, 0x20, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0x3c, 0x46, 0x20, 0x04, 0x00, 0x80, 0x02, 0x80, 0x20, 0x04, 0x21, +0x00, 0x0e, 0x04, 0x60, 0x00, 0x08, 0x04, 0x70, 0x80, 0x13, 0x46, 0x00, 0x04, 0x00, 0x46, 0x48, +0x08, 0x00, 0x58, 0x00, 0x00, 0xf4, 0x40, 0x21, 0x40, 0x08, 0x84, 0xa3, 0x58, 0x73, 0x80, 0x01, +0x58, 0x42, 0x00, 0x03, 0x84, 0x60, 0x54, 0x63, 0x08, 0x00, 0x14, 0x70, 0x80, 0x13, 0x92, 0x5d, +0xb6, 0xa0, 0xb6, 0x80, 0xb6, 0xa0, 0xb6, 0x60, 0xce, 0x06, 0x46, 0x1f, 0x0f, 0xff, 0x44, 0x30, +0x0f, 0xff, 0xd5, 0x02, 0x80, 0x23, 0x84, 0x82, 0x4c, 0x22, 0x00, 0x40, 0xe4, 0x43, 0xe8, 0x05, +0x84, 0xa1, 0x4c, 0x22, 0xc0, 0xb9, 0xd5, 0x06, 0x9e, 0x15, 0xe6, 0x02, 0x4e, 0xf2, 0x00, 0xb4, +0xd5, 0x6e, 0x46, 0x00, 0x04, 0x00, 0x84, 0x40, 0x14, 0x20, 0x00, 0x48, 0x46, 0x00, 0x04, 0x00, +0x58, 0x00, 0x00, 0x4c, 0xb4, 0x40, 0x44, 0x6f, 0xff, 0xc5, 0x40, 0x21, 0x18, 0x02, 0xb6, 0x40, +0x46, 0x50, 0x04, 0x00, 0xb4, 0x40, 0x58, 0x21, 0x00, 0x10, 0xb6, 0x40, 0x04, 0x02, 0x80, 0x08, +0x80, 0x85, 0x42, 0x00, 0x30, 0x09, 0x14, 0x02, 0x80, 0x08, 0x04, 0x52, 0x00, 0x20, 0x42, 0x52, +0x98, 0x09, 0x14, 0x52, 0x00, 0x20, 0x46, 0x20, 0x04, 0x00, 0x58, 0x21, 0x01, 0x24, 0xb4, 0x82, +0x40, 0x10, 0x90, 0x02, 0xb6, 0x22, 0x9c, 0x14, 0xb4, 0x20, 0x40, 0x31, 0x84, 0x02, 0xb6, 0x60, +0xb4, 0x22, 0xb6, 0x22, 0xb4, 0x20, 0xd5, 0x37, 0x46, 0x00, 0x04, 0x00, 0x84, 0x40, 0x14, 0x20, +0x00, 0x48, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x4c, 0xb4, 0x40, 0x44, 0x4f, 0xff, 0xc5, +0x40, 0x21, 0x10, 0x02, 0xb6, 0x40, 0x46, 0x50, 0x04, 0x00, 0xb4, 0x40, 0x58, 0x21, 0x00, 0x10, +0xb6, 0x40, 0x04, 0x02, 0x80, 0x08, 0x80, 0x85, 0x42, 0x00, 0x30, 0x09, 0x14, 0x02, 0x80, 0x08, +0x04, 0x52, 0x00, 0x20, 0x42, 0x52, 0x98, 0x09, 0x14, 0x52, 0x00, 0x20, 0x46, 0x20, 0x04, 0x00, +0x58, 0x21, 0x01, 0x24, 0xb4, 0x82, 0x40, 0x10, 0x90, 0x02, 0xb6, 0x22, 0x9c, 0x14, 0xb4, 0x20, +0x40, 0x31, 0x84, 0x02, 0xb6, 0x60, 0xb4, 0x22, 0xb6, 0x22, 0x44, 0x27, 0x70, 0x00, 0xb4, 0x20, +0x40, 0x10, 0x88, 0x04, 0xb6, 0x20, 0x84, 0x25, 0x48, 0x00, 0x00, 0x80, 0x46, 0x00, 0x04, 0x00, +0x84, 0x80, 0x14, 0x40, 0x00, 0x48, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x00, 0x4c, 0xb4, 0x80, +0x44, 0x5f, 0xff, 0xc5, 0x40, 0x42, 0x14, 0x02, 0x84, 0xc5, 0xb6, 0x80, 0x4c, 0x23, 0x40, 0x06, +0xb4, 0x80, 0x58, 0x42, 0x00, 0x30, 0xd5, 0x04, 0xb4, 0x80, 0x58, 0x42, 0x00, 0x10, 0xb6, 0x80, +0x46, 0x40, 0x04, 0x00, 0x04, 0x52, 0x00, 0x08, 0x42, 0x52, 0xb0, 0x09, 0x14, 0x52, 0x00, 0x08, +0x80, 0x04, 0x04, 0x50, 0x00, 0x20, 0x42, 0x52, 0x98, 0x09, 0x14, 0x50, 0x00, 0x20, 0x46, 0x40, +0x04, 0x00, 0x58, 0x42, 0x01, 0x24, 0xb4, 0xa4, 0x40, 0x10, 0x94, 0x02, 0xb6, 0x24, 0x9c, 0x24, +0xb4, 0xa0, 0x40, 0x31, 0x94, 0x02, 0xb6, 0x60, 0xb4, 0x64, 0xb6, 0x64, 0xb4, 0x60, 0xb6, 0x60, +0x84, 0xa5, 0xda, 0x03, 0x84, 0x04, 0xd5, 0x02, 0x84, 0x08, 0x46, 0xf0, 0x01, 0x00, 0x10, 0x07, +0x83, 0x00, 0xd5, 0x3f, 0x46, 0x00, 0x04, 0x00, 0x84, 0x40, 0x14, 0x20, 0x00, 0x48, 0x80, 0x40, +0x04, 0x41, 0x00, 0x10, 0x46, 0x00, 0x04, 0x00, 0x97, 0x21, 0x14, 0x41, 0x00, 0x10, 0x58, 0x00, +0x00, 0x4c, 0xb4, 0x40, 0x44, 0x6f, 0xff, 0xc5, 0x40, 0x21, 0x18, 0x02, 0xb6, 0x40, 0x46, 0x50, +0x04, 0x00, 0xb4, 0x40, 0x58, 0x21, 0x00, 0x02, 0xb6, 0x40, 0x04, 0x02, 0x80, 0x08, 0x80, 0x85, +0x42, 0x00, 0x30, 0x09, 0x14, 0x02, 0x80, 0x08, 0x04, 0x52, 0x00, 0x20, 0x42, 0x52, 0x98, 0x09, +0x14, 0x52, 0x00, 0x20, 0x46, 0x20, 0x04, 0x00, 0x58, 0x21, 0x01, 0x24, 0xb4, 0x82, 0x40, 0x10, +0x90, 0x02, 0xb6, 0x22, 0x9c, 0x14, 0xb4, 0x20, 0x40, 0x31, 0x84, 0x02, 0xb6, 0x60, 0xb4, 0x22, +0xb6, 0x22, 0xb4, 0x20, 0xb6, 0x20, 0x84, 0x26, 0x46, 0xf0, 0x01, 0x00, 0x10, 0x17, 0x83, 0x00, +0x3a, 0x6f, 0x9c, 0x04, 0xdd, 0x9e, 0x46, 0x00, 0x00, 0x90, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x07, +0x80, 0x4a, 0x46, 0x10, 0x00, 0x92, 0x58, 0x10, 0x86, 0x34, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x17, +0x80, 0x45, 0x46, 0x10, 0x00, 0x92, 0x58, 0x10, 0x85, 0xa0, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x17, +0x80, 0x46, 0x46, 0x10, 0x00, 0x90, 0x58, 0x10, 0x88, 0x10, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x17, +0x80, 0x47, 0x84, 0x23, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x17, 0x87, 0xa2, 0x46, 0x10, 0x00, 0x92, +0x58, 0x10, 0x81, 0x50, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x17, 0x81, 0xdf, 0xdd, 0x9e, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x97, 0x81, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x80, 0xa6, +0x96, 0x49, 0x80, 0x06, 0xdd, 0x22, 0x46, 0xf0, 0x01, 0x0b, 0x00, 0x07, 0x8f, 0x3c, 0xc0, 0x2b, +0x44, 0x50, 0x00, 0x20, 0xde, 0x03, 0x84, 0x0f, 0xd5, 0x02, 0x96, 0x30, 0x46, 0x10, 0x01, 0x0b, +0x58, 0x10, 0x8e, 0x84, 0x10, 0x00, 0x80, 0x1b, 0x10, 0x00, 0x80, 0x0c, 0x10, 0x00, 0x80, 0x0d, +0x10, 0x00, 0x80, 0x0e, 0x10, 0x00, 0x80, 0x0f, 0x10, 0x00, 0x80, 0x10, 0x10, 0x00, 0x80, 0x11, +0x10, 0x00, 0x80, 0x12, 0x10, 0x00, 0x80, 0x13, 0x10, 0x00, 0x80, 0x14, 0x10, 0x00, 0x80, 0x15, +0x10, 0x00, 0x80, 0x16, 0x10, 0x00, 0x80, 0x17, 0x10, 0x00, 0x80, 0x18, 0x10, 0x00, 0x80, 0x19, +0x10, 0x00, 0x80, 0x1a, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x42, 0x00, 0x00, 0x09, 0x9c, 0x02, +0xdd, 0x9e, 0x96, 0x00, 0x54, 0x10, 0x00, 0x08, 0x46, 0xf0, 0x01, 0x0b, 0x14, 0x07, 0x83, 0xc5, +0xc9, 0x02, 0xc8, 0x06, 0x46, 0x00, 0x04, 0xa0, 0x84, 0x20, 0x14, 0x10, 0x00, 0x92, 0xdd, 0x9e, +0x92, 0x00, 0x46, 0x00, 0x04, 0x02, 0x04, 0x00, 0x02, 0x00, 0x84, 0xa3, 0x54, 0x00, 0x00, 0x07, +0xd0, 0x16, 0x84, 0xa4, 0xd0, 0x04, 0x84, 0xa1, 0xd8, 0x24, 0xd5, 0x11, 0x46, 0x10, 0x04, 0x05, +0x04, 0x20, 0x81, 0xd4, 0x46, 0x00, 0x04, 0x05, 0x58, 0x21, 0x00, 0x01, 0x14, 0x20, 0x81, 0xd4, +0x58, 0x00, 0x08, 0x18, 0xb4, 0x20, 0x42, 0x10, 0xec, 0x09, 0xd5, 0x12, 0x46, 0x10, 0x04, 0x05, +0x04, 0x20, 0x81, 0xcc, 0x46, 0x00, 0x04, 0x05, 0x58, 0x21, 0x00, 0x02, 0x14, 0x20, 0x81, 0xcc, +0x58, 0x00, 0x09, 0x08, 0xb4, 0x20, 0x46, 0x26, 0x00, 0x00, 0x40, 0x10, 0x88, 0x04, 0xb6, 0x20, +0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x00, 0x90, 0x58, 0xf7, 0x82, 0x08, +0xdd, 0x2f, 0x46, 0xf0, 0x00, 0x90, 0x58, 0xf7, 0x82, 0x2c, 0xdd, 0x2f, 0x46, 0x00, 0x04, 0x00, +0x04, 0x10, 0x00, 0x82, 0x46, 0x30, 0x00, 0x90, 0x58, 0x31, 0x82, 0xd0, 0x58, 0x10, 0x80, 0x01, +0x14, 0x10, 0x00, 0x82, 0x46, 0x10, 0x00, 0x90, 0x58, 0x10, 0x85, 0x64, 0x46, 0xf0, 0x01, 0x00, +0x14, 0x37, 0x80, 0x99, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x17, 0x80, 0xa8, 0x46, 0xf0, 0x01, 0x00, +0x00, 0x07, 0x83, 0x00, 0xdd, 0x21, 0x46, 0xf0, 0x00, 0x90, 0x58, 0xf7, 0x88, 0xb4, 0xdd, 0x2f, +0x46, 0x00, 0x04, 0x00, 0x04, 0x10, 0x00, 0x0e, 0x84, 0xa1, 0x92, 0x34, 0x54, 0x10, 0x80, 0x03, +0xd1, 0x08, 0x04, 0x00, 0x00, 0x0e, 0x84, 0xa2, 0x92, 0x14, 0x54, 0x00, 0x00, 0x03, 0xd8, 0x09, +0x46, 0x00, 0x04, 0x05, 0x04, 0x10, 0x02, 0x42, 0x58, 0x10, 0xa0, 0x00, 0x14, 0x10, 0x02, 0x42, +0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x00, 0x10, 0x00, 0x20, 0x9e, 0x8e, +0x96, 0x90, 0x46, 0xf0, 0x01, 0x09, 0x04, 0x07, 0x81, 0xda, 0xe6, 0x44, 0xe9, 0x0b, 0x46, 0xf0, +0x01, 0x0e, 0x00, 0x57, 0x8d, 0x7a, 0xd9, 0x12, 0x84, 0xa1, 0xd0, 0x10, 0x54, 0x00, 0x00, 0x02, +0xc8, 0x0d, 0x46, 0xf0, 0x01, 0x09, 0x04, 0x07, 0x81, 0xe2, 0x46, 0x10, 0x00, 0xff, 0x40, 0x00, +0x04, 0x02, 0x84, 0x20, 0x40, 0x00, 0x80, 0x06, 0xd5, 0x02, 0x84, 0x00, 0xdd, 0x9e, 0x46, 0xf0, +0x01, 0x0e, 0x00, 0x37, 0x8d, 0x7a, 0x44, 0x10, 0x00, 0x30, 0x42, 0x31, 0x84, 0x24, 0x80, 0x20, +0x08, 0x40, 0x80, 0x04, 0x46, 0x20, 0x01, 0x01, 0x58, 0x21, 0x06, 0x58, 0x10, 0x41, 0x00, 0xc9, +0xa7, 0x08, 0x10, 0x41, 0x01, 0x51, 0x46, 0x40, 0x01, 0x08, 0x58, 0x42, 0x0c, 0x80, 0xa6, 0x48, +0x98, 0xdc, 0x10, 0x11, 0x80, 0x25, 0xa6, 0x05, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x17, 0x85, 0x24, +0x94, 0xc2, 0x98, 0xd9, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x37, 0x85, 0x23, 0x10, 0x01, 0x00, 0xcd, +0xdd, 0x9e, 0xa6, 0x40, 0x44, 0x50, 0x00, 0xff, 0xd1, 0x05, 0x46, 0xf0, 0x01, 0x10, 0x10, 0x17, +0x82, 0xe0, 0xa6, 0x41, 0xd1, 0x05, 0x46, 0xf0, 0x01, 0x10, 0x10, 0x17, 0x82, 0xe1, 0xa6, 0x02, +0xd0, 0x05, 0x46, 0xf0, 0x01, 0x10, 0x10, 0x07, 0x82, 0xe2, 0xdd, 0x9e, 0x92, 0x00, 0xa6, 0x40, +0x84, 0xa2, 0xd1, 0x0c, 0x84, 0xa3, 0xd1, 0x0c, 0x84, 0x01, 0x4c, 0x10, 0x40, 0x19, 0x84, 0x20, +0x46, 0xf0, 0x01, 0x01, 0x10, 0x17, 0x85, 0x07, 0xd5, 0x12, 0x84, 0x20, 0xd5, 0x0c, 0xa6, 0x81, +0x46, 0xf0, 0x01, 0x01, 0x10, 0x27, 0x85, 0x07, 0xa6, 0x43, 0xa6, 0x02, 0x40, 0x10, 0xa0, 0x08, +0x40, 0x10, 0x80, 0x04, 0x46, 0xf0, 0x01, 0x07, 0x12, 0x17, 0x87, 0xa3, 0xdd, 0x9e, 0x46, 0xf0, +0x01, 0x0b, 0x04, 0x17, 0x83, 0xa1, 0x96, 0x8c, 0xca, 0x07, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x27, +0x85, 0x82, 0x84, 0xa1, 0xda, 0x29, 0x54, 0x10, 0x80, 0x80, 0xc1, 0x26, 0xc0, 0x25, 0xa6, 0x80, +0x96, 0x94, 0xca, 0x04, 0x44, 0x20, 0x00, 0x4e, 0xd5, 0x02, 0x84, 0x40, 0x46, 0xf0, 0x01, 0x09, +0x10, 0x27, 0x80, 0x58, 0xa6, 0x83, 0x96, 0x94, 0xca, 0x04, 0x44, 0x20, 0x00, 0x4e, 0xd5, 0x03, +0x44, 0x20, 0x00, 0x18, 0x46, 0xf0, 0x01, 0x09, 0x10, 0x27, 0x80, 0x59, 0x00, 0x00, 0x00, 0x09, +0x54, 0x00, 0x00, 0x40, 0xc8, 0x02, 0xd5, 0x03, 0x44, 0x00, 0x00, 0x4e, 0x46, 0xf0, 0x01, 0x09, +0x10, 0x07, 0x80, 0x5a, 0xd5, 0x0c, 0x46, 0x00, 0x01, 0x09, 0x58, 0x00, 0x00, 0x58, 0x44, 0x10, +0x00, 0x4e, 0xae, 0x42, 0x84, 0x20, 0xae, 0x40, 0x8c, 0x38, 0xae, 0x41, 0xdd, 0x9e, 0x3a, 0x6f, +0x98, 0xbc, 0x96, 0x48, 0x9e, 0x89, 0x96, 0x90, 0xe6, 0x4e, 0xe9, 0x07, 0x46, 0x60, 0x00, 0x5b, +0x58, 0x63, 0x01, 0x48, 0x84, 0x20, 0xd5, 0x19, 0xe6, 0x25, 0xe8, 0x06, 0x46, 0x60, 0x00, 0x92, +0x58, 0x63, 0x0c, 0xe0, 0xd5, 0x12, 0xe6, 0x2a, 0xe9, 0x06, 0x46, 0x60, 0x00, 0x92, 0x58, 0x63, +0x0d, 0x1c, 0xd5, 0x0b, 0x84, 0xca, 0x42, 0x60, 0x98, 0x24, 0x46, 0x20, 0x00, 0x92, 0x58, 0x21, +0x0c, 0xe0, 0x50, 0x63, 0x7f, 0xd8, 0x99, 0xb2, 0x54, 0x20, 0x00, 0x80, 0xc2, 0x1b, 0x96, 0x04, +0xc8, 0x06, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x85, 0x82, 0xc0, 0x14, 0xc1, 0x13, 0x46, 0xf0, +0x01, 0x01, 0x00, 0x07, 0x85, 0x81, 0xc0, 0x06, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x57, 0x80, 0xb5, +0xd6, 0x2c, 0x84, 0x21, 0x80, 0x06, 0x84, 0x61, 0x46, 0x20, 0x01, 0x01, 0x58, 0x21, 0x05, 0x81, +0xd5, 0x0b, 0x46, 0x20, 0x01, 0x01, 0x58, 0x21, 0x05, 0x81, 0xa6, 0x50, 0x84, 0x01, 0x4c, 0x10, +0x40, 0x1d, 0x80, 0x06, 0x84, 0x60, 0xae, 0xd0, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x67, 0x80, 0xb5, +0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x84, 0xf4, 0xdd, 0x2f, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x90, +0x58, 0xf7, 0x8a, 0xb0, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x37, 0x80, 0xb0, 0x80, 0x46, +0x44, 0x00, 0x00, 0x46, 0x84, 0x20, 0xdd, 0x23, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x0e, 0x04, 0x17, 0x83, 0xb6, 0x96, 0x4c, 0xc1, 0x62, +0x46, 0xf0, 0x01, 0x0b, 0x04, 0x27, 0x83, 0xa1, 0x54, 0x21, 0x00, 0x80, 0xc2, 0x5b, 0x46, 0xf0, +0x01, 0x0b, 0x00, 0x17, 0x8f, 0x24, 0xc1, 0x56, 0xe6, 0x1a, 0xe8, 0x54, 0x84, 0x21, 0x46, 0x30, +0x24, 0x80, 0x40, 0x10, 0x80, 0x0c, 0x40, 0x20, 0x8c, 0x02, 0xca, 0x05, 0x54, 0x10, 0x80, 0x82, +0xc9, 0x21, 0xd5, 0x48, 0x46, 0x10, 0x04, 0xa0, 0x04, 0x20, 0x80, 0x92, 0x54, 0x31, 0x02, 0x00, +0xc3, 0x41, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x47, 0x80, 0xb0, 0x46, 0x30, 0x0c, 0x00, 0x58, 0x31, +0x88, 0x00, 0x96, 0x90, 0x50, 0x21, 0x01, 0x00, 0x40, 0x42, 0x0c, 0x04, 0x40, 0x42, 0x08, 0x04, +0x14, 0x40, 0x80, 0x92, 0x96, 0xc1, 0x44, 0x10, 0x10, 0x00, 0x84, 0x07, 0x44, 0x20, 0x90, 0x72, +0xd5, 0x24, 0x46, 0x10, 0x04, 0xa0, 0x04, 0x10, 0x80, 0x92, 0x54, 0x20, 0x82, 0x00, 0xc2, 0x22, +0x96, 0x48, 0xc1, 0x03, 0x9e, 0x49, 0x96, 0x48, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x47, 0x80, 0xb0, +0x46, 0x20, 0x0c, 0x00, 0x58, 0x21, 0x08, 0x00, 0x50, 0x10, 0x81, 0x00, 0x40, 0x42, 0x08, 0x04, +0x46, 0x20, 0x04, 0xa0, 0x40, 0x42, 0x04, 0x04, 0x14, 0x41, 0x00, 0x92, 0x96, 0xc1, 0x44, 0x10, +0x10, 0x00, 0x84, 0x07, 0x44, 0x20, 0x90, 0x73, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x86, 0xfc, +0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x80, 0xc0, +0xc0, 0x14, 0x00, 0x10, 0x00, 0x20, 0x9e, 0x4e, 0x96, 0x48, 0xe6, 0x24, 0xe8, 0x0e, 0x84, 0x41, +0x46, 0xf0, 0x01, 0x09, 0x10, 0x27, 0x87, 0xa2, 0x46, 0xf0, 0x00, 0x3e, 0x58, 0xf7, 0x8d, 0x5c, +0xdd, 0x2f, 0x80, 0xe0, 0x48, 0x00, 0x00, 0xd8, 0x46, 0x80, 0x00, 0x32, 0x58, 0x84, 0x0c, 0x0c, +0x4b, 0xe0, 0x20, 0x01, 0x84, 0xa1, 0x80, 0xe0, 0xd8, 0x62, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, +0x83, 0xb9, 0xdd, 0x21, 0x4b, 0xe0, 0x20, 0x01, 0x4c, 0x03, 0xc0, 0x18, 0xc6, 0x0f, 0x46, 0xf0, +0x00, 0x32, 0x58, 0xf7, 0x8c, 0x14, 0xdd, 0x2f, 0x4c, 0x03, 0x40, 0x57, 0x46, 0xf0, 0x01, 0x09, +0x14, 0x67, 0x81, 0xe0, 0x44, 0x70, 0x00, 0x60, 0xd5, 0x4c, 0x46, 0xf0, 0x00, 0x32, 0x58, 0xf7, +0x8c, 0x1c, 0xdd, 0x2f, 0x48, 0x00, 0x00, 0xc2, 0x46, 0xf0, 0x01, 0x08, 0x04, 0x17, 0x83, 0xb1, +0x80, 0x07, 0xdd, 0x21, 0x80, 0xc0, 0xc0, 0x27, 0x00, 0x30, 0x00, 0x20, 0x46, 0x80, 0x00, 0x34, +0x58, 0x84, 0x06, 0xfc, 0x9e, 0x5e, 0x96, 0x48, 0xe6, 0x24, 0xe8, 0x15, 0x46, 0xf0, 0x01, 0x09, +0x10, 0x77, 0x87, 0xa2, 0x46, 0xf0, 0x00, 0x3e, 0x58, 0xf7, 0x8d, 0x5c, 0xdd, 0x2f, 0x80, 0xe0, +0x84, 0x22, 0x84, 0x03, 0x44, 0x20, 0x10, 0x50, 0x44, 0x30, 0xff, 0xff, 0x80, 0x87, 0x4b, 0xe0, +0x20, 0x01, 0xd5, 0x21, 0x80, 0x87, 0x84, 0x03, 0x84, 0x22, 0x44, 0x20, 0x10, 0x50, 0x4b, 0xe0, +0x20, 0x01, 0xd5, 0x1a, 0x46, 0xf0, 0x01, 0x09, 0x10, 0x77, 0x87, 0x9d, 0x46, 0xf0, 0x01, 0x09, +0x10, 0x67, 0x87, 0x9e, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xbe, 0x80, 0x66, 0x84, 0x03, +0x84, 0x22, 0x44, 0x20, 0x10, 0x50, 0xdd, 0x24, 0x48, 0x00, 0x00, 0x80, 0x80, 0x06, 0x84, 0xe0, +0xc0, 0x64, 0x80, 0xc0, 0xcf, 0x61, 0x00, 0x13, 0x00, 0x22, 0x00, 0x03, 0x00, 0x20, 0xc9, 0x35, +0x46, 0x70, 0x01, 0x09, 0x58, 0x73, 0x87, 0x7c, 0x00, 0x13, 0x80, 0x22, 0x4c, 0x10, 0x40, 0x03, +0xd5, 0x29, 0x04, 0x23, 0x00, 0x0a, 0xa0, 0x53, 0xc1, 0x22, 0x02, 0x21, 0x00, 0x11, 0xa0, 0xf3, +0x46, 0xf0, 0x00, 0x33, 0x58, 0xf7, 0x80, 0x78, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, +0x83, 0xb9, 0x84, 0x01, 0xdd, 0x21, 0x84, 0x01, 0x10, 0x03, 0x80, 0x26, 0x44, 0x20, 0x10, 0x4f, +0x04, 0x13, 0x00, 0x0a, 0xa1, 0x33, 0xa4, 0xce, 0x84, 0x03, 0x84, 0x22, 0x46, 0xf0, 0x00, 0x34, +0x58, 0xf7, 0x86, 0xfc, 0xdd, 0x2f, 0x44, 0x70, 0x00, 0x60, 0xd5, 0x23, 0x84, 0x01, 0x10, 0x03, +0x80, 0x26, 0x44, 0x70, 0x00, 0x50, 0xd5, 0x1d, 0x46, 0xf0, 0x01, 0x0e, 0x04, 0x17, 0x83, 0x8c, +0xc1, 0x0c, 0x00, 0x10, 0x81, 0xae, 0x4c, 0x10, 0x40, 0x09, 0x84, 0x21, 0x46, 0xf0, 0x01, 0x09, +0x10, 0x17, 0x87, 0xa2, 0x84, 0xe7, 0xd5, 0x0d, 0x46, 0xf0, 0x01, 0x09, 0x00, 0x57, 0x87, 0x9e, +0xd8, 0x02, 0xd5, 0x06, 0x84, 0x01, 0x46, 0xf0, 0x01, 0x09, 0x10, 0x07, 0x87, 0xa2, 0x84, 0xe5, +0x46, 0xf0, 0x01, 0x09, 0x14, 0x67, 0x81, 0xe0, 0x00, 0x13, 0x00, 0x20, 0x46, 0xf0, 0x01, 0x09, +0x10, 0x17, 0x87, 0x9e, 0xd5, 0x08, 0x80, 0x06, 0x84, 0x40, 0x46, 0xf0, 0x01, 0x09, 0x10, 0x27, +0x87, 0x9e, 0x80, 0xc0, 0x46, 0xf0, 0x01, 0x09, 0x04, 0x07, 0x81, 0xe1, 0x84, 0xa2, 0xd8, 0x09, +0xc7, 0x08, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x83, 0xb2, 0x80, 0x27, 0x80, 0x06, 0xdd, 0x22, +0x80, 0x07, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x84, 0x00, 0x80, 0xe0, 0xd5, 0xe6, 0x3a, 0x6f, +0xa4, 0xbc, 0xef, 0xc4, 0x50, 0x6f, 0x80, 0x34, 0x46, 0xf0, 0x01, 0x0b, 0x04, 0x07, 0x81, 0x61, +0x80, 0x26, 0x46, 0xf0, 0x00, 0x3b, 0x58, 0xf7, 0x88, 0xe8, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x47, 0x83, 0xbe, 0xa6, 0xf0, 0x84, 0x04, 0x94, 0x47, 0x44, 0x20, 0x30, 0x74, 0xdd, 0x24, +0xa6, 0x30, 0x84, 0xa1, 0xd0, 0x09, 0xc0, 0x0d, 0x84, 0xa2, 0xd0, 0x05, 0x84, 0xa6, 0x4c, 0x02, +0xc1, 0x28, 0xd5, 0x06, 0x84, 0x03, 0x10, 0x0f, 0x80, 0x08, 0x84, 0xc0, 0xd5, 0x05, 0x84, 0x02, +0x10, 0x0f, 0x80, 0x08, 0x84, 0xc1, 0x50, 0x7f, 0x80, 0x34, 0xa6, 0x7b, 0x50, 0x8f, 0x80, 0x0c, +0x80, 0x08, 0x46, 0xf0, 0x00, 0x3b, 0x58, 0xf7, 0x89, 0x5c, 0xdd, 0x2f, 0xa6, 0xfb, 0x50, 0x2f, +0x80, 0x04, 0x9e, 0xde, 0xa6, 0x79, 0xa6, 0x38, 0xae, 0xd6, 0x84, 0xa1, 0xae, 0x55, 0xd8, 0x0a, +0x46, 0xf0, 0x01, 0x0b, 0x04, 0x57, 0x81, 0x1a, 0xa6, 0xfa, 0x80, 0x48, 0x50, 0x4f, 0x80, 0x12, +0xd5, 0x08, 0x84, 0x60, 0x46, 0xf0, 0x01, 0x0b, 0x04, 0x57, 0x81, 0x1a, 0x80, 0x83, 0x80, 0x48, +0xdd, 0x25, 0x80, 0xe0, 0x84, 0xa1, 0xdf, 0x42, 0x50, 0x0f, 0x80, 0x10, 0x00, 0x10, 0x7f, 0xf8, +0xc9, 0x3d, 0xa6, 0x42, 0x8c, 0xb6, 0xd9, 0x3a, 0xa6, 0x43, 0x44, 0x50, 0x00, 0xff, 0xd9, 0x36, +0xa6, 0x44, 0x44, 0x50, 0x00, 0x46, 0xd9, 0x32, 0xa6, 0x45, 0xc9, 0x30, 0xa6, 0x47, 0x8c, 0xae, +0xd9, 0x2d, 0x00, 0x50, 0x00, 0x19, 0xd9, 0x2a, 0x46, 0x10, 0x01, 0x20, 0xa6, 0xc6, 0x00, 0x50, +0x88, 0x0a, 0xd3, 0x1a, 0x10, 0x30, 0x88, 0x0a, 0x46, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x6f, +0x42, 0x00, 0x4c, 0x0b, 0xc0, 0x09, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0xbc, 0xb4, 0x20, +0x42, 0x10, 0xcc, 0x09, 0xd5, 0x08, 0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0xbc, 0xb4, 0x20, +0x42, 0x10, 0xcc, 0x08, 0xb6, 0x20, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xbe, 0x84, 0x21, +0x84, 0x04, 0x44, 0x20, 0x30, 0xab, 0x48, 0x00, 0x00, 0xb3, 0x84, 0xa1, 0xde, 0x67, 0x4c, 0x73, +0x40, 0x66, 0x46, 0x60, 0x01, 0x0b, 0x58, 0x63, 0x05, 0x70, 0xa7, 0x70, 0xdf, 0x5f, 0x02, 0x93, +0x00, 0x04, 0x8f, 0x21, 0x40, 0x94, 0x80, 0x13, 0x12, 0x93, 0x00, 0x04, 0x4e, 0x93, 0x00, 0x57, +0x46, 0x00, 0x04, 0x90, 0x04, 0x80, 0x00, 0x4f, 0x40, 0x84, 0x1c, 0x08, 0x93, 0x17, 0x46, 0xf0, +0x00, 0x44, 0x58, 0xf7, 0x82, 0xc0, 0xdd, 0x2f, 0xe2, 0x08, 0xe9, 0x03, 0x4e, 0x83, 0x00, 0x0d, +0x46, 0xf0, 0x01, 0x0b, 0x04, 0x27, 0x81, 0x46, 0x84, 0x00, 0x9c, 0x91, 0x46, 0xf0, 0x01, 0x0b, +0x14, 0x27, 0x81, 0x46, 0xd5, 0x35, 0x46, 0xf0, 0x01, 0x09, 0x00, 0x07, 0x87, 0x9d, 0xc0, 0x03, +0x80, 0x09, 0xd5, 0x2e, 0x00, 0x3f, 0x80, 0x35, 0xa0, 0x36, 0x84, 0x46, 0xae, 0xf2, 0x98, 0x02, +0x50, 0x1f, 0x80, 0x0c, 0x46, 0xf0, 0x00, 0x5a, 0x58, 0xf7, 0x83, 0x84, 0xdd, 0x2f, 0xa0, 0x35, +0x44, 0x10, 0x20, 0x00, 0x46, 0xf0, 0x00, 0x3c, 0x58, 0xf7, 0x82, 0x3c, 0xdd, 0x2f, 0x84, 0x03, +0x44, 0x10, 0x20, 0x00, 0xa8, 0x37, 0x46, 0xf0, 0x01, 0x09, 0x14, 0x17, 0x81, 0xda, 0x46, 0xf0, +0x00, 0x3b, 0x58, 0xf7, 0x8d, 0xc4, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xbe, +0x80, 0x68, 0x84, 0x04, 0x94, 0x47, 0x44, 0x20, 0x30, 0x72, 0xdd, 0x24, 0x80, 0x07, 0x84, 0x41, +0x46, 0xf0, 0x01, 0x0b, 0x12, 0x27, 0x82, 0xbc, 0xc8, 0x1e, 0x46, 0xf0, 0x00, 0x3b, 0x58, 0xf7, +0x85, 0x64, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x80, 0x54, 0x84, 0x00, 0xdd, 0x21, +0x84, 0x22, 0x46, 0xf0, 0x01, 0x0b, 0x14, 0x17, 0x81, 0x63, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, +0x83, 0xbe, 0x44, 0x10, 0x02, 0x00, 0x84, 0x04, 0x44, 0x20, 0x30, 0x73, 0x80, 0x67, 0xdd, 0x24, +0x84, 0xa1, 0xdf, 0x18, 0x46, 0xf0, 0x01, 0x0b, 0x04, 0x07, 0x81, 0x61, 0x46, 0xf0, 0x00, 0x3b, +0x58, 0xf7, 0x8c, 0xe4, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x0b, 0x04, 0x17, 0x81, 0x61, 0x50, 0x0f, +0x80, 0x04, 0x00, 0x10, 0x80, 0x24, 0xae, 0x47, 0x46, 0xf0, 0x01, 0x0b, 0x04, 0x17, 0x81, 0x16, +0xdd, 0x21, 0x46, 0xf0, 0x01, 0x0b, 0x04, 0x17, 0x81, 0x41, 0x44, 0x20, 0x30, 0x75, 0x9c, 0x49, +0x46, 0xf0, 0x01, 0x0b, 0x14, 0x17, 0x81, 0x41, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xbe, +0x46, 0xf0, 0x01, 0x0b, 0x04, 0x37, 0x81, 0x63, 0x84, 0x22, 0x84, 0x04, 0xdd, 0x24, 0xec, 0x3c, +0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xec, 0x46, 0xf0, 0x01, 0x07, +0x04, 0x97, 0x83, 0xcd, 0x84, 0x40, 0x10, 0x2f, 0x80, 0x0f, 0x81, 0x40, 0x46, 0xf0, 0x01, 0x07, +0x00, 0x77, 0x8f, 0x41, 0x4e, 0x92, 0x00, 0xac, 0x46, 0xf0, 0x01, 0x0e, 0x04, 0x07, 0x83, 0x8c, +0xc8, 0x04, 0x44, 0x00, 0x00, 0xff, 0xd5, 0x03, 0x00, 0x00, 0x01, 0xae, 0x4c, 0x70, 0x40, 0x1e, +0x46, 0xf0, 0x01, 0x01, 0x04, 0x67, 0x81, 0xae, 0x44, 0x00, 0x00, 0x30, 0x42, 0x63, 0x80, 0x73, +0x46, 0xf0, 0x01, 0x08, 0x02, 0x77, 0x86, 0x2e, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, +0x88, 0x84, 0xdd, 0x2f, 0x80, 0x40, 0x80, 0x27, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x1b, 0x58, 0xf7, +0x8d, 0xe4, 0xdd, 0x2f, 0x48, 0x00, 0x00, 0x83, 0x46, 0xf0, 0x01, 0x0e, 0x04, 0x87, 0x83, 0x82, +0x4e, 0x82, 0x00, 0x63, 0x84, 0x01, 0xf0, 0x81, 0x50, 0x6f, 0x80, 0x0f, 0x47, 0xc0, 0x00, 0x35, +0x59, 0xce, 0x0d, 0xa0, 0xb4, 0x28, 0x46, 0xf0, 0x01, 0x07, 0x04, 0x57, 0x83, 0xcd, 0xd9, 0x06, +0x84, 0x00, 0x04, 0x24, 0x00, 0x04, 0xf0, 0x81, 0xd5, 0x48, 0x00, 0x04, 0x00, 0x06, 0xe6, 0x03, +0xe8, 0x42, 0x00, 0x90, 0x80, 0x20, 0x84, 0xa2, 0xd0, 0x0c, 0xf3, 0x01, 0xcb, 0x0a, 0x80, 0x09, +0xdd, 0x3c, 0x80, 0x20, 0xb6, 0x3f, 0x80, 0x07, 0xdd, 0x3c, 0xb4, 0x3f, 0xe2, 0x20, 0xe9, 0x33, +0x80, 0x09, 0x80, 0x26, 0x80, 0x47, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x88, 0x1c, 0xdd, 0x2f, +0xc0, 0x2a, 0x46, 0xf0, 0x01, 0x0e, 0x04, 0x07, 0x83, 0x8c, 0xc0, 0x0f, 0x00, 0x50, 0x01, 0xae, +0x4c, 0x54, 0xc0, 0x0c, 0x46, 0x00, 0x01, 0x07, 0x58, 0x00, 0x0f, 0x30, 0x80, 0x27, 0x46, 0xf0, +0x00, 0x1d, 0x58, 0xf7, 0x81, 0x4c, 0xdd, 0x2f, 0x80, 0x67, 0x84, 0x06, 0x84, 0x21, 0x44, 0x20, +0x70, 0x7c, 0x80, 0x89, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x86, 0xfc, 0xdd, 0x2f, 0x46, 0xf0, +0x01, 0x08, 0x04, 0x17, 0x81, 0x3b, 0x80, 0xe9, 0x9c, 0x49, 0x46, 0xf0, 0x01, 0x08, 0x14, 0x17, +0x81, 0x3b, 0xd5, 0x50, 0x04, 0x24, 0x00, 0x04, 0x4c, 0x24, 0x00, 0x07, 0xc2, 0x05, 0xb4, 0x02, +0xc0, 0x03, 0x81, 0x02, 0xd5, 0xa8, 0x9e, 0x3e, 0x96, 0x00, 0xe6, 0x04, 0xe9, 0x43, 0x46, 0xf0, +0x01, 0x07, 0x04, 0x07, 0x83, 0xcd, 0x00, 0x00, 0x00, 0x22, 0xc0, 0x08, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x17, 0x83, 0x82, 0x80, 0x07, 0xdd, 0x21, 0xd5, 0x08, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, +0x83, 0x83, 0x80, 0x2a, 0x80, 0x07, 0xdd, 0x22, 0xc8, 0x2d, 0x85, 0x21, 0x4e, 0xa3, 0x00, 0x87, +0x46, 0xf0, 0x01, 0x0e, 0x04, 0x87, 0x83, 0x82, 0x4e, 0x82, 0x00, 0x81, 0x50, 0x6f, 0x80, 0x0f, +0x47, 0xc0, 0x00, 0x1c, 0x59, 0xce, 0x08, 0x1c, 0x00, 0x04, 0x00, 0x06, 0x80, 0x26, 0x84, 0x40, +0xe6, 0x03, 0xe8, 0x0f, 0x4e, 0x92, 0x00, 0x08, 0xb4, 0xa8, 0x46, 0xf0, 0x01, 0x07, 0x04, 0x07, +0x83, 0xcd, 0xd0, 0x07, 0xb4, 0x08, 0x00, 0x70, 0x00, 0x20, 0x80, 0x07, 0xdd, 0x3c, 0xc8, 0x0a, +0x04, 0x04, 0x00, 0x04, 0x4c, 0x04, 0x00, 0x63, 0xc0, 0x61, 0xb4, 0x20, 0xc1, 0x5f, 0x81, 0x00, +0xd5, 0xe4, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x07, 0x81, 0xae, 0x44, 0x10, 0x00, 0x30, 0x42, 0x03, +0x84, 0x73, 0x46, 0x60, 0x01, 0x07, 0x58, 0x63, 0x0f, 0x30, 0xa8, 0x31, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x17, 0x83, 0x78, 0x10, 0x73, 0x00, 0x11, 0x80, 0x07, 0xdd, 0x21, 0x84, 0x00, 0x84, 0x3f, +0x46, 0xf0, 0x00, 0x27, 0x58, 0xf7, 0x89, 0xc4, 0xdd, 0x2f, 0xa0, 0x72, 0x80, 0x07, 0x5c, 0x10, +0x80, 0x01, 0x46, 0xf0, 0x00, 0x27, 0x58, 0xf7, 0x88, 0x88, 0xdd, 0x2f, 0x84, 0x02, 0xa8, 0x32, +0xa0, 0x31, 0x00, 0x33, 0x00, 0x11, 0xa1, 0x03, 0x84, 0x21, 0x84, 0x06, 0x44, 0x20, 0x70, 0x76, +0xd5, 0x20, 0x46, 0xf0, 0x00, 0x1b, 0x58, 0xf7, 0x8c, 0xbc, 0xdd, 0x2f, 0xc0, 0x0c, 0x00, 0x03, +0x00, 0x14, 0xc8, 0x09, 0x84, 0x21, 0x10, 0x13, 0x00, 0x14, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, +0x83, 0x87, 0xdd, 0x21, 0x84, 0x00, 0x84, 0x3f, 0x46, 0xf0, 0x00, 0x27, 0x58, 0xf7, 0x89, 0xc4, +0xdd, 0x2f, 0x84, 0x06, 0x84, 0x28, 0x44, 0x20, 0x70, 0x77, 0x84, 0x60, 0x44, 0x40, 0x00, 0xff, +0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x86, 0xfc, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x07, 0x04, 0x07, +0x83, 0xcd, 0xec, 0x14, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x00, 0x1f, 0x80, 0x0f, 0x46, 0x60, +0x01, 0x07, 0x58, 0x63, 0x0f, 0x30, 0x84, 0x00, 0xa8, 0x32, 0xa8, 0x31, 0xc9, 0xdc, 0xd5, 0xca, +0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x27, 0x85, 0x81, 0x80, 0xc0, +0x96, 0x08, 0xc2, 0x02, 0xc0, 0x5e, 0x46, 0x10, 0x00, 0x2d, 0x58, 0x10, 0x88, 0x30, 0xce, 0x06, +0x46, 0x00, 0x01, 0x08, 0x58, 0x00, 0x0c, 0x08, 0xd5, 0x02, 0x80, 0x06, 0xdd, 0x21, 0x80, 0xe0, +0xe6, 0x14, 0xe8, 0x04, 0x44, 0x00, 0x00, 0x12, 0xd5, 0x4c, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x93, +0x00, 0x03, 0x00, 0x83, 0x00, 0x09, 0xc6, 0x16, 0x80, 0x26, 0x46, 0x00, 0x01, 0x08, 0x58, 0x00, +0x0c, 0x08, 0x84, 0x4a, 0x46, 0xf0, 0x00, 0x40, 0x58, 0xf7, 0x83, 0xf4, 0xdd, 0x2f, 0x46, 0xf0, +0x01, 0x08, 0x00, 0x17, 0x8c, 0x11, 0x54, 0x10, 0x80, 0x7f, 0x46, 0xf0, 0x01, 0x08, 0x10, 0x17, +0x8c, 0x11, 0x54, 0x05, 0x00, 0x01, 0x9b, 0xf8, 0x54, 0x04, 0x80, 0x01, 0x9b, 0xf8, 0x42, 0x04, +0x18, 0x0b, 0x9b, 0xf8, 0xe6, 0xf4, 0xe9, 0x0a, 0x46, 0x00, 0x01, 0x08, 0x58, 0x00, 0x0c, 0x08, +0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, 0x8c, 0x20, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x0e, 0x04, 0x07, +0x83, 0x8c, 0x46, 0x10, 0x01, 0x08, 0x58, 0x10, 0x8c, 0x08, 0x46, 0xf0, 0x00, 0x26, 0x58, 0xf7, +0x83, 0x9c, 0xdd, 0x2f, 0x46, 0x00, 0x01, 0x0e, 0x00, 0x10, 0x0d, 0x49, 0x58, 0x10, 0x80, 0x01, +0x10, 0x10, 0x0d, 0x49, 0x84, 0x3f, 0x46, 0xf0, 0x01, 0x0e, 0x10, 0x17, 0x8d, 0x46, 0x84, 0x00, +0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa0, 0xbc, 0x84, 0xe0, 0x80, 0xc0, 0x80, 0x27, +0x40, 0x03, 0x80, 0x06, 0x46, 0x80, 0x00, 0x04, 0x58, 0x84, 0x01, 0x3c, 0x46, 0x20, 0x00, 0x92, +0x58, 0x21, 0x0c, 0xb4, 0x44, 0x30, 0x02, 0x4c, 0x4b, 0xe0, 0x20, 0x01, 0xa0, 0x36, 0x80, 0x27, +0x40, 0x03, 0x80, 0x06, 0x46, 0x20, 0x00, 0x92, 0x58, 0x21, 0x0c, 0xb4, 0x44, 0x30, 0x02, 0x4d, +0x4b, 0xe0, 0x20, 0x01, 0xa0, 0x36, 0x00, 0x70, 0x00, 0x08, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, +0x83, 0xfe, 0x84, 0x03, 0xdd, 0x21, 0xc7, 0x3d, 0x84, 0xa1, 0xdf, 0x02, 0xd5, 0x33, 0x04, 0x03, +0x00, 0x0a, 0x00, 0x10, 0x00, 0x53, 0xc9, 0x2a, 0x84, 0x41, 0x10, 0x20, 0x00, 0x37, 0x84, 0x42, +0x80, 0x06, 0x46, 0xf0, 0x00, 0x4f, 0x58, 0xf7, 0x8d, 0x08, 0xdd, 0x2f, 0x80, 0x27, 0x80, 0x06, +0x46, 0xf0, 0x00, 0x2a, 0x58, 0xf7, 0x8f, 0xdc, 0xdd, 0x2f, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x2a, +0x58, 0xf7, 0x8e, 0x7c, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x0b, 0x00, 0x17, 0x8e, 0xbd, 0xc1, 0x1f, +0x46, 0xf0, 0x01, 0x0b, 0x04, 0x57, 0x83, 0xb1, 0xde, 0x1a, 0x46, 0x00, 0x01, 0x20, 0x04, 0x10, +0x02, 0x00, 0x9c, 0x49, 0x14, 0x10, 0x02, 0x00, 0xd5, 0x12, 0x00, 0x03, 0x00, 0x22, 0x84, 0xa1, +0xd8, 0x08, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x4f, 0x58, 0xf7, 0x8e, 0x18, 0xdd, 0x2f, 0xd5, 0x07, +0x80, 0x06, 0x46, 0xf0, 0x00, 0x4f, 0x58, 0xf7, 0x8e, 0x44, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x09, +0x14, 0x67, 0x80, 0x4e, 0x3a, 0x6f, 0xa0, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x46, 0xf0, 0x01, 0x0b, 0x00, 0x27, 0x8e, 0xbd, 0x96, 0x00, 0xc2, 0x0f, 0x46, 0xf0, 0x01, 0x0b, +0x04, 0x17, 0x83, 0xb1, 0x00, 0x50, 0x80, 0x20, 0xd8, 0x08, 0x46, 0x10, 0x01, 0x20, 0x04, 0x20, +0x82, 0x01, 0x9c, 0x91, 0x14, 0x20, 0x82, 0x01, 0x46, 0xf0, 0x00, 0x1e, 0x58, 0xf7, 0x89, 0x70, +0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, +0x97, 0x88, 0x81, 0x00, 0x81, 0x22, 0x84, 0x01, 0x84, 0x20, 0x9c, 0xb6, 0x97, 0xd9, 0x46, 0xf0, +0x00, 0x36, 0x58, 0xf7, 0x80, 0x2c, 0xdd, 0x2f, 0xc0, 0x1d, 0xb4, 0x80, 0x9c, 0x74, 0x40, 0x03, +0xa0, 0x09, 0x84, 0x4e, 0xae, 0x61, 0x84, 0x21, 0xae, 0xa0, 0xae, 0x62, 0xae, 0x24, 0x10, 0x92, +0x00, 0x05, 0xaf, 0xe3, 0x80, 0x28, 0x9c, 0x26, 0x80, 0x46, 0x46, 0xf0, 0x00, 0x40, 0x58, 0xf7, +0x83, 0xf4, 0xdd, 0x2f, 0x84, 0x01, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, 0x87, 0x68, +0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xe8, +0x81, 0x00, 0xa6, 0x00, 0x84, 0xa1, 0xd8, 0x5b, 0x46, 0xf0, 0x01, 0x0b, 0x00, 0x67, 0x8e, 0xbd, +0xce, 0x04, 0x81, 0x46, 0x80, 0x26, 0xd5, 0x26, 0x46, 0xf0, 0x01, 0x0b, 0x04, 0x07, 0x83, 0xb1, +0x00, 0x00, 0x00, 0x20, 0x46, 0xf0, 0x00, 0x1b, 0x58, 0xf7, 0x89, 0x84, 0xdd, 0x2f, 0x04, 0x60, +0x00, 0x6d, 0x46, 0xf0, 0x01, 0x20, 0x04, 0x17, 0x82, 0x00, 0x46, 0xf0, 0x01, 0x20, 0x04, 0xa7, +0x82, 0x01, 0xe6, 0xc3, 0xe9, 0x06, 0x9f, 0xb2, 0x97, 0xb0, 0x84, 0xa3, 0xd6, 0x04, 0xd5, 0x0a, +0x97, 0xb0, 0xd5, 0x08, 0x00, 0x20, 0x01, 0x1f, 0x84, 0x02, 0x54, 0x21, 0x00, 0x04, 0x40, 0x60, +0x08, 0x1a, 0x50, 0x7f, 0x80, 0x04, 0x46, 0x90, 0x00, 0x0c, 0x58, 0x94, 0x89, 0x04, 0x80, 0x07, +0x4b, 0xe0, 0x24, 0x01, 0x80, 0x2a, 0x50, 0x0f, 0x80, 0x08, 0x4b, 0xe0, 0x24, 0x01, 0x80, 0x07, +0x84, 0x29, 0x84, 0x40, 0x44, 0x30, 0xfc, 0x4d, 0x10, 0x63, 0x80, 0x08, 0x46, 0xf0, 0x00, 0x91, +0x58, 0xf7, 0x86, 0x0c, 0xdd, 0x2f, 0x00, 0x04, 0x00, 0x01, 0x84, 0xa1, 0xd0, 0x06, 0x46, 0xf0, +0x01, 0x0b, 0x00, 0x07, 0x8e, 0xbd, 0xc8, 0x15, 0x84, 0x00, 0x46, 0xf0, 0x01, 0x20, 0x14, 0x07, +0x82, 0x01, 0x46, 0xf0, 0x01, 0x20, 0x14, 0x07, 0x82, 0x00, 0xd5, 0x0b, 0x84, 0x00, 0x80, 0x20, +0x84, 0x41, 0x44, 0x30, 0xfc, 0x4d, 0x46, 0xf0, 0x00, 0x91, 0x58, 0xf7, 0x86, 0x0c, 0xdd, 0x2f, +0xec, 0x18, 0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, +0x96, 0xc8, 0x46, 0xf0, 0x01, 0x0e, 0x04, 0x47, 0x83, 0x8c, 0x95, 0x9b, 0x46, 0x10, 0x01, 0x09, +0x58, 0x10, 0x82, 0x98, 0x99, 0xb1, 0x84, 0x20, 0xae, 0x74, 0x84, 0x28, 0xae, 0x75, 0x80, 0xe2, +0x96, 0x00, 0xc4, 0x09, 0x00, 0x52, 0x01, 0xae, 0xdb, 0x06, 0x46, 0x00, 0x01, 0x20, 0x58, 0x00, +0x08, 0x18, 0xd5, 0x13, 0xe6, 0x05, 0xe9, 0x08, 0x84, 0x09, 0x46, 0xf0, 0x00, 0x0d, 0x58, 0xf7, +0x86, 0xa0, 0xdd, 0x2f, 0x84, 0x00, 0x44, 0x10, 0x00, 0xe4, 0x42, 0x00, 0x04, 0x24, 0x46, 0x10, +0x01, 0x09, 0x58, 0x10, 0x82, 0xd0, 0x98, 0x01, 0xb6, 0x06, 0x80, 0x27, 0xb4, 0x06, 0x46, 0xf0, +0x00, 0x29, 0x58, 0xf7, 0x83, 0xac, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa8, 0xbc, 0xef, 0xf0, 0x97, 0xa0, 0x52, 0x23, 0x00, 0x10, 0x54, 0x81, +0x80, 0xff, 0x96, 0x90, 0x81, 0x41, 0x81, 0x20, 0xe2, 0x48, 0xe9, 0x20, 0x80, 0x3f, 0x84, 0x41, +0x46, 0xf0, 0x00, 0x50, 0x58, 0xf7, 0x8e, 0x58, 0xdd, 0x2f, 0x44, 0x50, 0x00, 0xff, 0x80, 0xff, +0xd0, 0x15, 0x89, 0x1f, 0x89, 0x06, 0x80, 0x2a, 0x40, 0x2f, 0x98, 0x00, 0xd5, 0x05, 0x08, 0x00, +0x80, 0x01, 0x18, 0x01, 0x00, 0x01, 0x4c, 0x24, 0x7f, 0xfc, 0x80, 0x09, 0x80, 0x3f, 0x46, 0xf0, +0x00, 0x50, 0x58, 0xf7, 0x8f, 0xa0, 0xdd, 0x2f, 0xc0, 0x02, 0x84, 0x0c, 0xec, 0x10, 0x3a, 0x6f, +0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xfc, 0xa7, 0xc0, 0x00, 0x80, +0x00, 0x01, 0xe6, 0xf1, 0xe9, 0x03, 0x84, 0x8c, 0xd5, 0x24, 0x54, 0x44, 0x00, 0x0f, 0x52, 0x62, +0x00, 0x10, 0x50, 0xa0, 0x00, 0x02, 0x97, 0xb0, 0x55, 0xc4, 0x00, 0xf0, 0x46, 0x90, 0x00, 0x91, +0x58, 0x94, 0x87, 0xc4, 0x80, 0x1c, 0x80, 0x2a, 0x84, 0x41, 0x80, 0x66, 0x4b, 0xe0, 0x24, 0x01, +0x80, 0x80, 0xc8, 0x0f, 0x9e, 0x39, 0x89, 0x00, 0x54, 0x04, 0x00, 0xf0, 0x4d, 0xc0, 0x00, 0x0a, +0x9a, 0xfe, 0x40, 0x15, 0x18, 0x00, 0x96, 0xd8, 0x84, 0x41, 0x4b, 0xe0, 0x24, 0x01, 0x80, 0x80, +0x80, 0x24, 0x44, 0x00, 0xfc, 0x6b, 0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, 0x82, 0x3c, 0xdd, 0x2f, +0xec, 0x04, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0xa6, 0x01, 0x84, 0xa4, 0xd0, 0x3f, 0xe6, 0x05, 0xe8, 0x08, 0x84, 0xa2, 0xd0, 0x1f, 0xe6, 0x03, +0xe8, 0x2b, 0x84, 0xa1, 0xd8, 0x72, 0xd5, 0x0c, 0x84, 0x26, 0x4c, 0x00, 0x80, 0x4f, 0xe2, 0x01, +0xe9, 0x3f, 0x84, 0xa8, 0xd0, 0x5d, 0x44, 0x50, 0x00, 0xff, 0xd8, 0x67, 0xd5, 0x53, 0x46, 0x00, +0x01, 0x0b, 0x58, 0x00, 0x0e, 0x84, 0x44, 0x10, 0x00, 0x18, 0x12, 0x10, 0x00, 0x57, 0x84, 0x20, +0x14, 0x10, 0x00, 0x2d, 0x44, 0x10, 0x01, 0xb0, 0xd5, 0x65, 0x46, 0x00, 0x01, 0x0b, 0x58, 0x00, +0x0e, 0x84, 0x44, 0x10, 0x00, 0x18, 0x12, 0x10, 0x00, 0x57, 0x84, 0x20, 0x14, 0x10, 0x00, 0x2d, +0x44, 0x10, 0x01, 0x20, 0xd5, 0x57, 0x46, 0x00, 0x01, 0x0b, 0x58, 0x00, 0x0e, 0x84, 0x44, 0x10, +0x00, 0x18, 0x12, 0x10, 0x00, 0x57, 0x84, 0x20, 0x14, 0x10, 0x00, 0x2d, 0x44, 0x10, 0x00, 0xd8, +0xd5, 0x49, 0x46, 0x00, 0x01, 0x0b, 0x58, 0x00, 0x0e, 0x84, 0x44, 0x10, 0x00, 0x18, 0x12, 0x10, +0x00, 0x57, 0x84, 0x20, 0x14, 0x10, 0x00, 0x2d, 0x44, 0x10, 0x00, 0xb4, 0xd5, 0x3b, 0x46, 0x00, +0x01, 0x0b, 0x58, 0x00, 0x0e, 0x84, 0x8c, 0x32, 0x12, 0x10, 0x00, 0x57, 0x84, 0x20, 0x14, 0x10, +0x00, 0x2d, 0x44, 0x10, 0x00, 0x90, 0xd5, 0x2e, 0x46, 0x00, 0x01, 0x0b, 0x58, 0x00, 0x0e, 0x84, +0x8c, 0x32, 0x12, 0x10, 0x00, 0x57, 0x84, 0x20, 0x14, 0x10, 0x00, 0x2d, 0x44, 0x10, 0x00, 0x6c, +0xd5, 0x21, 0x84, 0x24, 0x46, 0xf0, 0x01, 0x0b, 0x14, 0x17, 0x83, 0xce, 0xd5, 0x1d, 0x46, 0x00, +0x01, 0x0b, 0x58, 0x00, 0x0e, 0x84, 0x8c, 0x3e, 0x12, 0x10, 0x00, 0x57, 0x84, 0x20, 0x14, 0x10, +0x00, 0x2d, 0x44, 0x10, 0x00, 0x48, 0xd5, 0x0e, 0x46, 0x00, 0x01, 0x0b, 0x58, 0x00, 0x0e, 0x84, +0x44, 0x10, 0x00, 0x24, 0x12, 0x10, 0x00, 0x57, 0x84, 0x20, 0x14, 0x10, 0x00, 0x2d, 0x44, 0x10, +0x00, 0x60, 0x12, 0x10, 0x00, 0x56, 0x44, 0x00, 0xfc, 0x22, 0x84, 0x20, 0x46, 0xf0, 0x00, 0x0f, +0x58, 0xf7, 0x82, 0x3c, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xa8, 0xbc, 0xef, 0xf8, 0x84, 0x40, 0x38, 0x10, 0x08, 0x00, 0x9c, 0x91, 0xc9, 0x04, 0x84, 0xa6, +0xda, 0xfb, 0xd5, 0x36, 0x80, 0x20, 0x08, 0x70, 0x80, 0x01, 0x46, 0x30, 0x01, 0x01, 0x58, 0x31, +0x86, 0x58, 0x08, 0x60, 0x80, 0x01, 0x50, 0x21, 0x80, 0x08, 0x08, 0x50, 0x80, 0x01, 0x40, 0x03, +0x20, 0x08, 0x08, 0x80, 0x80, 0x01, 0x40, 0x42, 0xc0, 0x08, 0x00, 0xa0, 0x80, 0x01, 0x00, 0x90, +0x80, 0x00, 0x98, 0x20, 0x10, 0x81, 0x80, 0x03, 0x10, 0x91, 0x80, 0x04, 0x10, 0xa1, 0x80, 0x05, +0xaf, 0xd8, 0xaf, 0x99, 0xaf, 0x5a, 0x98, 0x07, 0x50, 0x11, 0x80, 0x0c, 0x10, 0x7f, 0x80, 0x00, +0x10, 0xaf, 0x80, 0x05, 0x10, 0x9f, 0x80, 0x04, 0x10, 0x8f, 0x80, 0x03, 0x10, 0x5f, 0x80, 0x02, +0x10, 0x6f, 0x80, 0x01, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x9c, 0xdd, 0x2f, 0xec, 0x08, +0x3a, 0x6f, 0xa8, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0x70, 0x01, 0x01, +0x58, 0x73, 0x86, 0x58, 0x04, 0x63, 0x80, 0x18, 0x96, 0x00, 0x44, 0x20, 0x00, 0x30, 0x42, 0x60, +0x08, 0x73, 0x96, 0x08, 0xce, 0x03, 0x84, 0x02, 0xd5, 0x2d, 0xc8, 0x03, 0xa8, 0x31, 0xd5, 0x2a, +0x84, 0x01, 0x10, 0x03, 0x00, 0x22, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x33, 0x58, 0xf7, 0x85, 0xf4, +0xdd, 0x2f, 0x84, 0x02, 0xa8, 0x31, 0x04, 0x43, 0x00, 0x0a, 0xa6, 0xfa, 0xa6, 0x39, 0xa6, 0xb8, +0xa6, 0x7b, 0x40, 0x31, 0xc0, 0x08, 0x40, 0x00, 0x20, 0x08, 0x98, 0x18, 0x98, 0x02, 0x40, 0x10, +0xe0, 0x08, 0x40, 0x00, 0x04, 0x04, 0xa8, 0x22, 0x80, 0x06, 0xa0, 0xba, 0x04, 0x13, 0x00, 0x0a, +0xa1, 0xfb, 0xb6, 0x41, 0xa9, 0xc9, 0x46, 0xf0, 0x00, 0x28, 0x58, 0xf7, 0x8e, 0xf8, 0xdd, 0x2f, +0x84, 0x00, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, +0x84, 0x20, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x17, 0x87, 0x40, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x17, +0x85, 0x1c, 0x96, 0x00, 0x46, 0xf0, 0x00, 0x4d, 0x58, 0xf7, 0x8f, 0xec, 0xdd, 0x2f, 0xec, 0x04, +0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x84, 0xa6, 0x80, 0xc0, +0xd8, 0x1d, 0x46, 0x00, 0x04, 0x80, 0x04, 0x30, 0x00, 0x0a, 0x46, 0x60, 0x01, 0x0e, 0x04, 0x43, +0x03, 0x90, 0x54, 0x31, 0x80, 0x03, 0x84, 0x03, 0x84, 0x21, 0x44, 0x20, 0x10, 0x0d, 0x46, 0xf0, +0x00, 0x34, 0x58, 0xf7, 0x86, 0xfc, 0xdd, 0x2f, 0x84, 0x02, 0x14, 0x03, 0x03, 0x90, 0x46, 0xf0, +0x00, 0x2c, 0x58, 0xf7, 0x8d, 0x00, 0xdd, 0x2f, 0xd5, 0x1c, 0xc8, 0x16, 0x46, 0x70, 0x01, 0x0e, +0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xbe, 0x04, 0x33, 0x83, 0x90, 0x84, 0x03, 0x84, 0x21, +0x44, 0x20, 0x10, 0x0b, 0xdd, 0x24, 0x14, 0x63, 0x83, 0x90, 0x46, 0xf0, 0x00, 0x2c, 0x58, 0xf7, +0x88, 0xd8, 0xdd, 0x2f, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x2d, 0x58, 0xf7, 0x80, 0x34, 0xdd, 0x2f, +0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, 0x98, 0xbc, 0x80, 0xc0, +0xa6, 0x00, 0x46, 0xf0, 0x01, 0x01, 0x14, 0x07, 0x81, 0xca, 0x46, 0x10, 0x00, 0x34, 0x58, 0x10, +0x8f, 0x7c, 0xc8, 0x02, 0xd5, 0x02, 0x84, 0x01, 0x4b, 0xe0, 0x04, 0x01, 0xa6, 0x72, 0xa6, 0x31, +0x40, 0x10, 0xa0, 0x08, 0x98, 0x48, 0x46, 0x00, 0x01, 0x01, 0x58, 0x00, 0x06, 0x58, 0x12, 0x10, +0x00, 0x6a, 0xa6, 0x74, 0xa6, 0xb3, 0x40, 0x10, 0xa0, 0x08, 0x98, 0x4a, 0x12, 0x10, 0x00, 0x6b, +0xa6, 0x75, 0x10, 0x10, 0x00, 0xd8, 0xa7, 0xb6, 0x10, 0x60, 0x00, 0xd9, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x96, 0x00, 0x80, 0xc1, 0x98, 0x48, 0x00, 0x50, 0xff, 0xff, +0xd0, 0x03, 0x84, 0x01, 0xd5, 0x24, 0x9c, 0x32, 0x46, 0xf0, 0x00, 0x91, 0x58, 0xf7, 0x89, 0xd0, +0xdd, 0x2f, 0x50, 0x03, 0x00, 0x08, 0x46, 0xf0, 0x00, 0x90, 0x58, 0xf7, 0x89, 0xf0, 0xdd, 0x2f, +0x50, 0x03, 0x00, 0x0e, 0x46, 0xf0, 0x00, 0x90, 0x58, 0xf7, 0x8a, 0x44, 0xdd, 0x2f, 0x50, 0x03, +0x00, 0x11, 0x46, 0xf0, 0x00, 0x91, 0x58, 0xf7, 0x8b, 0x8c, 0xdd, 0x2f, 0x50, 0x03, 0x00, 0x27, +0x46, 0xf0, 0x00, 0x90, 0x58, 0xf7, 0x8a, 0x70, 0xdd, 0x2f, 0x84, 0x00, 0x3a, 0x6f, 0x98, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x44, 0x20, 0x14, 0x0d, 0x96, 0x49, 0x80, 0xe0, +0x4c, 0x11, 0x40, 0x26, 0x84, 0x01, 0x84, 0x20, 0x84, 0x46, 0x46, 0xf0, 0x00, 0x36, 0x58, 0xf7, +0x80, 0x2c, 0xdd, 0x2f, 0xc0, 0x21, 0xb4, 0xc0, 0x84, 0x0e, 0xae, 0x30, 0x84, 0x04, 0xae, 0x31, +0x84, 0x01, 0xae, 0x32, 0x84, 0x0d, 0xae, 0x33, 0x9c, 0x07, 0xae, 0x34, 0x9c, 0x3b, 0x46, 0xf0, +0x00, 0x27, 0x58, 0xf7, 0x84, 0xf4, 0xdd, 0x2f, 0xae, 0x35, 0x84, 0x20, 0x84, 0x01, 0x46, 0xf0, +0x00, 0x36, 0x58, 0xf7, 0x87, 0x68, 0xdd, 0x2f, 0x84, 0x00, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x0a, +0x58, 0xf7, 0x81, 0x04, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0xfc, 0x96, 0x00, 0x96, 0x90, 0x4c, 0x01, 0x00, 0x04, 0x84, 0x00, 0xd5, 0x0b, +0x80, 0x01, 0x84, 0x46, 0x80, 0x23, 0x46, 0xf0, 0x00, 0x40, 0x58, 0xf7, 0x84, 0x28, 0xdd, 0x2f, +0x5c, 0x00, 0x00, 0x01, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0xa4, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x0b, 0x04, 0x67, 0x80, 0xff, 0x54, 0x80, 0x00, 0xff, +0x81, 0x22, 0x97, 0xc8, 0x96, 0x18, 0xc6, 0x62, 0x46, 0x50, 0x01, 0x01, 0x58, 0x52, 0x86, 0x58, +0x00, 0x23, 0x00, 0xbe, 0x50, 0x12, 0x81, 0x34, 0x40, 0x32, 0x88, 0x1a, 0x40, 0x30, 0x88, 0x1b, +0x84, 0x21, 0x4c, 0x80, 0xc0, 0x11, 0x80, 0x24, 0x46, 0xf0, 0x00, 0x91, 0x58, 0xf7, 0x8c, 0xb0, +0xdd, 0x2f, 0x80, 0xc0, 0xc8, 0x08, 0x80, 0x67, 0x80, 0x88, 0x84, 0x06, 0x84, 0x28, 0x44, 0x20, +0x70, 0x2f, 0xd5, 0x3f, 0x46, 0xf0, 0x01, 0x0a, 0x00, 0x07, 0x8e, 0xce, 0x54, 0x10, 0x00, 0x40, +0xc1, 0x11, 0x46, 0x30, 0x01, 0x0b, 0x58, 0x31, 0x83, 0xfc, 0x00, 0x21, 0x80, 0x17, 0x80, 0x07, +0x80, 0x29, 0x8c, 0x70, 0x46, 0xf0, 0x00, 0x91, 0x58, 0xf7, 0x8c, 0xb0, 0xdd, 0x2f, 0x80, 0xc0, +0xd5, 0x22, 0x96, 0x02, 0x4e, 0x04, 0x00, 0x1f, 0x80, 0x29, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x36, +0x58, 0xf7, 0x89, 0xe0, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x57, 0x85, 0x3a, 0xd0, 0x12, +0x46, 0x30, 0x01, 0x0b, 0x58, 0x31, 0x83, 0xfc, 0x10, 0x71, 0x80, 0x17, 0x50, 0x01, 0x80, 0x10, +0x80, 0x29, 0x84, 0x46, 0x46, 0xf0, 0x00, 0x40, 0x58, 0xf7, 0x83, 0xf4, 0xdd, 0x2f, 0x84, 0xc1, +0xd5, 0x02, 0x84, 0xc0, 0x80, 0x88, 0x84, 0x06, 0x84, 0x28, 0x44, 0x20, 0x70, 0x2e, 0x80, 0x66, +0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x86, 0xfc, 0xdd, 0x2f, 0x80, 0x06, 0xec, 0x04, 0x3a, 0x6f, +0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x46, 0x10, 0x01, 0x06, +0x58, 0x10, 0x8f, 0x38, 0x00, 0x20, 0x80, 0x2c, 0xca, 0x0c, 0xa0, 0x8b, 0x4c, 0x20, 0x00, 0x0a, +0xc8, 0x08, 0x84, 0xa1, 0xd2, 0x06, 0x00, 0x20, 0x80, 0x36, 0xc2, 0x03, 0x10, 0x00, 0x80, 0x36, +0x46, 0xf0, 0x00, 0x13, 0x58, 0xf7, 0x8e, 0xbc, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x46, 0x60, 0x01, 0x06, 0x58, 0x63, 0x0f, 0x38, +0x00, 0x13, 0x00, 0x30, 0x96, 0x00, 0x4e, 0x12, 0x00, 0x9f, 0x50, 0x10, 0x7f, 0xf1, 0x84, 0x42, +0xe2, 0x41, 0x4e, 0xf3, 0x00, 0x94, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x07, 0x85, 0xdb, 0xc8, 0x52, +0x00, 0x13, 0x00, 0x33, 0xc1, 0x4f, 0x00, 0x53, 0x00, 0x34, 0xd9, 0x4c, 0x46, 0xf0, 0x00, 0x35, +0x58, 0xf7, 0x88, 0x84, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x17, 0x81, 0x0a, 0x80, 0xe0, +0xdd, 0x21, 0x81, 0x20, 0x46, 0x10, 0x00, 0x25, 0x58, 0x10, 0x88, 0xc8, 0xc8, 0x14, 0x00, 0x03, +0x00, 0x2e, 0x4b, 0xe0, 0x04, 0x01, 0x80, 0xe0, 0x84, 0xbf, 0xdf, 0x3e, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x47, 0x83, 0xc0, 0x00, 0x33, 0x00, 0x2e, 0xa0, 0xb3, 0x80, 0x29, 0x44, 0x00, 0x70, 0x1b, +0xdd, 0x24, 0xd5, 0x32, 0x00, 0x03, 0x00, 0x2e, 0x4b, 0xe0, 0x04, 0x01, 0x84, 0x3f, 0x81, 0x00, +0x4c, 0x00, 0xc0, 0x0d, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x47, 0x83, 0xc0, 0x00, 0x33, 0x00, 0x2e, +0xa0, 0xb3, 0x44, 0x00, 0x70, 0x1b, 0x84, 0x21, 0xdd, 0x24, 0x80, 0x07, 0x80, 0x29, 0x46, 0xf0, +0x00, 0x33, 0x58, 0xf7, 0x88, 0xc8, 0xdd, 0x2f, 0x84, 0x3f, 0x80, 0xe0, 0x4c, 0x80, 0x80, 0x15, +0x80, 0x28, 0x46, 0xf0, 0x00, 0x33, 0x58, 0xf7, 0x89, 0x8c, 0xdd, 0x2f, 0x40, 0x74, 0x00, 0x1b, +0xd5, 0x0b, 0x46, 0xf0, 0x01, 0x06, 0x00, 0x07, 0x8f, 0x66, 0x46, 0xf0, 0x00, 0x25, 0x58, 0xf7, +0x88, 0xc8, 0xdd, 0x2f, 0x80, 0xe0, 0x46, 0xf0, 0x01, 0x06, 0x04, 0x07, 0x83, 0xd1, 0x46, 0x10, +0x00, 0x27, 0x58, 0x10, 0x88, 0x8c, 0x8e, 0x0f, 0xe6, 0x03, 0xe8, 0x0a, 0x84, 0x01, 0x4b, 0xe0, +0x04, 0x01, 0x84, 0x3f, 0x46, 0xf0, 0x01, 0x07, 0x14, 0x17, 0x83, 0xcf, 0xd5, 0x04, 0x84, 0x00, +0x4b, 0xe0, 0x04, 0x01, 0x46, 0xf0, 0x01, 0x06, 0x02, 0x37, 0x87, 0xa2, 0x84, 0x06, 0x44, 0x11, +0x00, 0x00, 0x44, 0x20, 0x70, 0x95, 0x80, 0x87, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x8a, 0xa4, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x37, 0x80, 0xba, 0x46, 0xf0, 0x01, 0x06, 0x04, 0x07, +0x83, 0xd1, 0x80, 0x47, 0x84, 0x20, 0xdd, 0x23, 0xd5, 0x06, 0x46, 0xf0, 0x00, 0x14, 0x58, 0xf7, +0x88, 0x3c, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0xfc, 0x96, 0x48, 0xe6, 0x02, 0xe8, 0x0b, 0x46, 0xf0, 0x01, 0x06, 0x00, 0x37, +0x8f, 0x6e, 0xc3, 0x06, 0x84, 0x60, 0x46, 0xf0, 0x01, 0x06, 0x10, 0x37, 0x8f, 0x6e, 0x46, 0xf0, +0x00, 0x14, 0x58, 0xf7, 0x80, 0x68, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xaa, 0xbc, 0xef, 0xf4, 0x50, 0x60, 0x00, 0x98, 0x00, 0x00, 0x01, 0xae, +0x54, 0xa1, 0x00, 0xff, 0xf1, 0x81, 0x46, 0xf0, 0x00, 0x27, 0x58, 0xf7, 0x8a, 0x84, 0xdd, 0x2f, +0x81, 0x00, 0x00, 0x03, 0x01, 0x16, 0x80, 0x28, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x82, 0xf8, +0xdd, 0x2f, 0x80, 0x40, 0x04, 0x03, 0x00, 0x46, 0xc0, 0x04, 0x04, 0x93, 0x00, 0x07, 0xd5, 0x03, +0x04, 0x93, 0x00, 0x06, 0xb6, 0x5f, 0x46, 0x70, 0x00, 0x33, 0x58, 0x73, 0x89, 0x8c, 0x80, 0x09, +0x80, 0x28, 0x4b, 0xe0, 0x1c, 0x01, 0x83, 0x80, 0xb4, 0x5f, 0xc0, 0x0b, 0x04, 0x23, 0x00, 0x46, +0x84, 0x03, 0x84, 0x21, 0x40, 0x90, 0x88, 0x1a, 0x40, 0x90, 0x08, 0x1b, 0x84, 0xe0, 0xd5, 0x68, +0x80, 0x02, 0x80, 0x29, 0x4b, 0xe0, 0x1c, 0x01, 0x80, 0xe0, 0x04, 0x23, 0x00, 0x0c, 0x4e, 0x03, +0x00, 0x8c, 0x4e, 0x22, 0x00, 0x8d, 0x84, 0xa2, 0x4c, 0x22, 0x80, 0x8a, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x47, 0x83, 0xc0, 0x00, 0x13, 0x01, 0x16, 0x44, 0x00, 0x70, 0x14, 0x80, 0x67, 0xdd, 0x24, +0xd5, 0x76, 0x46, 0xf0, 0x01, 0x0e, 0x00, 0x07, 0x8d, 0x34, 0x02, 0x13, 0x00, 0x7f, 0x80, 0xe2, +0x9a, 0x08, 0x12, 0x03, 0x00, 0x7f, 0x84, 0x01, 0xf3, 0x01, 0xae, 0x18, 0xd5, 0x68, 0x80, 0x2a, +0x46, 0x00, 0x01, 0x07, 0x58, 0x00, 0x0f, 0x30, 0x46, 0xf0, 0x00, 0x1d, 0x58, 0xf7, 0x81, 0x4c, +0xdd, 0x2f, 0x44, 0x10, 0x00, 0x30, 0x80, 0x1c, 0x42, 0x04, 0x84, 0x73, 0x40, 0x23, 0xa0, 0x01, +0x94, 0x94, 0x92, 0x44, 0x80, 0x27, 0x46, 0xf0, 0x00, 0x27, 0x58, 0xf7, 0x88, 0x80, 0xdd, 0x2f, +0x46, 0xf0, 0x01, 0x07, 0x00, 0x17, 0x8f, 0x45, 0x92, 0x22, 0x94, 0x4a, 0x46, 0xf0, 0x01, 0x07, +0x10, 0x17, 0x8f, 0x45, 0x84, 0xe1, 0x84, 0x21, 0x46, 0xf0, 0x01, 0x0e, 0x10, 0x17, 0x8d, 0x32, +0x14, 0x73, 0x00, 0x0c, 0x44, 0x04, 0x00, 0x00, 0x46, 0xf0, 0x00, 0x24, 0x58, 0xf7, 0x85, 0xb0, +0xdd, 0x2f, 0x02, 0x33, 0x00, 0x14, 0xa9, 0xf2, 0x12, 0x33, 0x00, 0x15, 0x46, 0xf0, 0x01, 0x01, +0x04, 0x27, 0x80, 0xaf, 0x50, 0x13, 0x7f, 0x68, 0x84, 0x02, 0xdd, 0x22, 0x81, 0x27, 0x02, 0x13, +0x00, 0x14, 0xa0, 0x36, 0x98, 0x49, 0x46, 0xf0, 0x00, 0x33, 0x58, 0xf7, 0x88, 0xc8, 0xdd, 0x2f, +0xa8, 0x35, 0x02, 0x23, 0x00, 0x11, 0xa0, 0x36, 0x80, 0x28, 0x46, 0xf0, 0x00, 0x33, 0x58, 0xf7, +0x89, 0x28, 0xdd, 0x2f, 0x93, 0x21, 0xa8, 0x36, 0x4e, 0x92, 0x00, 0x0a, 0x80, 0x28, 0x50, 0x03, +0x7f, 0x68, 0x46, 0xf0, 0x00, 0x1c, 0x58, 0xf7, 0x8f, 0xf4, 0xdd, 0x2f, 0xa8, 0x37, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x17, 0x83, 0x89, 0x00, 0x03, 0x01, 0x16, 0xdd, 0x21, 0x80, 0x07, 0xec, 0x0c, +0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, 0xc2, 0x86, 0x80, 0xfc, 0xd5, 0xf9, 0xa0, 0x36, 0x84, 0x21, +0x46, 0xf0, 0x00, 0x33, 0x58, 0xf7, 0x88, 0xd4, 0xdd, 0x2f, 0x80, 0xe0, 0x46, 0xf0, 0x01, 0x01, +0x05, 0xc7, 0x81, 0xae, 0x00, 0x93, 0x01, 0x16, 0x4e, 0xa2, 0xff, 0x8d, 0xd5, 0x81, 0x3a, 0x6f, +0xa8, 0xbc, 0x97, 0xc0, 0x44, 0x50, 0x00, 0xfe, 0x4c, 0x72, 0x80, 0xf3, 0x46, 0x10, 0x01, 0x0e, +0x04, 0x60, 0x83, 0x9f, 0x85, 0x00, 0x84, 0x1f, 0xa8, 0x33, 0x00, 0xa3, 0x00, 0xb6, 0x14, 0x80, +0x83, 0x9f, 0x14, 0x83, 0x00, 0x05, 0x00, 0x03, 0x00, 0xb6, 0x80, 0x28, 0x46, 0xf0, 0x00, 0x1c, +0x58, 0xf7, 0x81, 0xf8, 0xdd, 0x2f, 0x00, 0x33, 0x00, 0xb6, 0x84, 0x06, 0x84, 0x21, 0x44, 0x20, +0x70, 0x66, 0x80, 0x87, 0x46, 0xf0, 0x00, 0x34, 0x58, 0xf7, 0x86, 0xfc, 0xdd, 0x2f, 0x46, 0xf0, +0x01, 0x0e, 0x00, 0x97, 0x8d, 0x79, 0x84, 0xa1, 0x4c, 0x92, 0xc0, 0x17, 0x46, 0xf0, 0x00, 0x07, +0x58, 0xf7, 0x81, 0xc0, 0xdd, 0x2f, 0x4c, 0x04, 0xc0, 0x0b, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x37, +0x80, 0xb0, 0x80, 0x28, 0x44, 0x00, 0x00, 0x3d, 0x80, 0x48, 0xdd, 0x23, 0x84, 0x20, 0x46, 0xf0, +0x01, 0x0e, 0x10, 0x17, 0x8d, 0x79, 0x46, 0xf0, 0x01, 0x0e, 0x00, 0x07, 0x8d, 0x74, 0x54, 0x00, +0x00, 0x03, 0xc0, 0x0a, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x37, 0x80, 0xb0, 0x84, 0x20, 0x44, 0x00, +0x00, 0x49, 0x80, 0x41, 0xdd, 0x23, 0x44, 0x50, 0x00, 0x1a, 0xdf, 0x0a, 0x02, 0x03, 0x00, 0x51, +0x58, 0x00, 0x01, 0x00, 0x12, 0x03, 0x00, 0x51, 0x44, 0x00, 0x00, 0x3d, 0xd5, 0x21, 0x9f, 0x6a, +0xdf, 0x21, 0x00, 0x03, 0x00, 0xb4, 0x84, 0xac, 0xd8, 0x07, 0x02, 0x03, 0x00, 0x51, 0x58, 0x00, +0x01, 0x00, 0x12, 0x03, 0x00, 0x51, 0x02, 0x13, 0x00, 0x51, 0x54, 0x00, 0x80, 0x04, 0xc8, 0x12, +0x02, 0x23, 0x00, 0x52, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x87, 0x8b, 0x9c, 0x91, 0xe0, 0x40, +0xe9, 0x09, 0x58, 0x10, 0x81, 0x00, 0x12, 0x13, 0x00, 0x51, 0x44, 0x00, 0x00, 0x3e, 0x10, 0x03, +0x00, 0xbc, 0x02, 0x13, 0x00, 0x51, 0x54, 0x00, 0x81, 0x00, 0xc0, 0x25, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x27, 0x81, 0xbf, 0x00, 0x13, 0x00, 0xbc, 0x80, 0x06, 0xdd, 0x22, 0x46, 0xf0, 0x01, 0x06, +0x04, 0x07, 0x83, 0x85, 0x84, 0xa3, 0xd8, 0x4e, 0x46, 0xf0, 0x01, 0x08, 0x00, 0x07, 0x85, 0xd5, +0xc8, 0x49, 0x46, 0xf0, 0x01, 0x0b, 0x00, 0x07, 0x83, 0x30, 0x46, 0xf0, 0x01, 0x0b, 0x00, 0x17, +0x83, 0x2f, 0x98, 0x08, 0x96, 0x00, 0xc8, 0x3e, 0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, 0x89, 0x6c, +0xdd, 0x2f, 0xd5, 0x38, 0x44, 0x50, 0x00, 0x1c, 0xdf, 0x04, 0x54, 0x10, 0x90, 0x00, 0xc9, 0x15, +0x80, 0x06, 0x80, 0x27, 0x46, 0xf0, 0x00, 0x3a, 0x58, 0xf7, 0x84, 0xac, 0xdd, 0x2f, 0x46, 0xf0, +0x01, 0x00, 0x04, 0x17, 0x81, 0xe0, 0x80, 0x06, 0xdd, 0x21, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x3a, +0x58, 0xf7, 0x84, 0x30, 0xdd, 0x2f, 0x80, 0xc0, 0xc6, 0x1d, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x77, +0x81, 0xae, 0x00, 0x13, 0x00, 0xb6, 0x02, 0x83, 0x00, 0x19, 0x44, 0x00, 0x00, 0x30, 0x42, 0x70, +0x80, 0x73, 0x89, 0x08, 0x84, 0x00, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, 0x88, 0x84, 0xdd, 0x2f, +0x40, 0x14, 0x00, 0x13, 0x80, 0x40, 0x80, 0x07, 0x46, 0xf0, 0x00, 0x1b, 0x58, 0xf7, 0x8d, 0xe4, +0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, 0x04, 0x27, 0x81, 0xbd, 0x80, 0x26, 0x84, 0x04, 0xdd, 0x22, +0x84, 0x00, 0x84, 0x3f, 0x46, 0xf0, 0x00, 0x27, 0x58, 0xf7, 0x89, 0xc4, 0xdd, 0x2f, 0x46, 0xf0, +0x01, 0x01, 0x04, 0x27, 0x80, 0x92, 0x44, 0x10, 0x00, 0x20, 0x80, 0x0a, 0xdd, 0x22, 0x3a, 0x6f, +0xa8, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xfc, 0x96, 0x49, 0x46, 0xf0, +0x00, 0x0b, 0x58, 0xf7, 0x8d, 0xc0, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x3a, 0x6f, 0xa4, 0xbc, 0xef, 0xfc, 0x46, 0xf0, 0x01, 0x0e, 0x04, 0x17, 0x83, 0xb6, +0x80, 0xc0, 0x96, 0x0c, 0x4e, 0x02, 0x00, 0xe5, 0x46, 0xf0, 0x01, 0x0b, 0x04, 0x07, 0x83, 0xa1, +0x54, 0x00, 0x00, 0x80, 0x4e, 0x02, 0x00, 0xdd, 0x46, 0x70, 0x00, 0x27, 0x58, 0x73, 0x85, 0xfc, +0x4b, 0xe0, 0x1c, 0x01, 0x81, 0x00, 0x46, 0xf0, 0x01, 0x01, 0x04, 0x97, 0x81, 0xae, 0x4b, 0xe0, +0x1c, 0x01, 0x46, 0xf0, 0x00, 0x22, 0x58, 0xf7, 0x84, 0x6c, 0xdd, 0x2f, 0xc0, 0x2b, 0xb4, 0x20, +0xe6, 0x26, 0xe8, 0x07, 0x84, 0x21, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x17, 0x85, 0x71, 0xd5, 0x26, +0x80, 0x49, 0x44, 0x30, 0x00, 0x30, 0x42, 0x24, 0x0c, 0x73, 0x00, 0x01, 0x00, 0x22, 0x84, 0x41, +0x4c, 0x01, 0x40, 0x0d, 0x4c, 0x60, 0x40, 0x1b, 0x56, 0x10, 0x80, 0x09, 0x40, 0x10, 0x88, 0x06, +0x46, 0xf0, 0x01, 0x01, 0x10, 0x17, 0x85, 0x71, 0xd5, 0x14, 0x84, 0xa7, 0xde, 0x0f, 0x56, 0x00, +0x80, 0x0f, 0x5c, 0x00, 0x00, 0x01, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x07, 0x85, 0x71, 0x48, 0x00, +0x00, 0xa0, 0x46, 0xf0, 0x01, 0x01, 0x10, 0x07, 0x85, 0x71, 0x44, 0x50, 0x00, 0x13, 0xd6, 0x05, +0x44, 0x00, 0x00, 0x16, 0x4c, 0x60, 0x40, 0x4f, 0x46, 0xf0, 0x01, 0x09, 0x04, 0x07, 0x81, 0xe1, +0x54, 0x00, 0x00, 0x11, 0xc0, 0x34, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x85, 0x71, 0xc0, 0x18, +0x46, 0x00, 0x04, 0xa0, 0x04, 0x10, 0x01, 0x01, 0x46, 0x00, 0x01, 0x0b, 0x58, 0x00, 0x0a, 0xe8, +0x42, 0x10, 0xc0, 0x0b, 0xc9, 0x07, 0x04, 0x10, 0x00, 0x08, 0x9c, 0x49, 0x14, 0x10, 0x00, 0x08, +0xd5, 0x77, 0x04, 0x10, 0x00, 0x09, 0x9c, 0x49, 0x14, 0x10, 0x00, 0x09, 0xd5, 0x71, 0x46, 0x00, +0x04, 0xa0, 0x04, 0x10, 0x01, 0x01, 0x46, 0x00, 0x01, 0x0b, 0x58, 0x00, 0x0a, 0xe8, 0x42, 0x10, +0xc0, 0x0b, 0xc9, 0x07, 0x04, 0x10, 0x00, 0x0a, 0x9c, 0x49, 0x14, 0x10, 0x00, 0x0a, 0xd5, 0x60, +0x04, 0x10, 0x00, 0x0b, 0x9c, 0x49, 0x14, 0x10, 0x00, 0x0b, 0xd5, 0x5a, 0x46, 0x00, 0x04, 0xa0, +0x04, 0x10, 0x01, 0x01, 0x46, 0x00, 0x01, 0x0b, 0x58, 0x00, 0x0a, 0xe8, 0x42, 0x10, 0xc0, 0x0b, +0xc9, 0x05, 0xa0, 0x42, 0x9c, 0x49, 0xa8, 0x42, 0xd5, 0x4b, 0xa0, 0x43, 0x9c, 0x49, 0xa8, 0x43, +0xd5, 0x47, 0x9d, 0x43, 0xde, 0x45, 0x46, 0xf0, 0x01, 0x09, 0x04, 0x07, 0x81, 0xe1, 0x54, 0x00, +0x00, 0x11, 0xc0, 0x2c, 0x46, 0xf0, 0x01, 0x01, 0x00, 0x07, 0x85, 0x71, 0xc0, 0x14, 0x46, 0x00, +0x04, 0xa0, 0x04, 0x10, 0x01, 0x01, 0x46, 0x00, 0x01, 0x0b, 0x58, 0x00, 0x0a, 0xe8, 0x42, 0x10, +0xc0, 0x0b, 0xc9, 0x05, 0xa0, 0x44, 0x9c, 0x49, 0xa8, 0x44, 0xd5, 0x2a, 0xa0, 0x45, 0x9c, 0x49, +0xa8, 0x45, 0xd5, 0x26, 0x46, 0x00, 0x04, 0xa0, 0x04, 0x10, 0x01, 0x01, 0x46, 0x00, 0x01, 0x0b, +0x58, 0x00, 0x0a, 0xe8, 0x42, 0x10, 0xc0, 0x0b, 0xc9, 0x05, 0xa0, 0x46, 0x9c, 0x49, 0xa8, 0x46, +0xd5, 0x17, 0xa0, 0x47, 0x9c, 0x49, 0xa8, 0x47, 0xd5, 0x13, 0x46, 0x00, 0x04, 0xa0, 0x04, 0x10, +0x01, 0x01, 0x46, 0x00, 0x01, 0x0b, 0x58, 0x00, 0x0a, 0xe8, 0x42, 0x10, 0xc0, 0x0b, 0xc9, 0x05, +0xb4, 0x20, 0x9c, 0x49, 0xb6, 0x20, 0xd5, 0x04, 0xa0, 0x41, 0x9c, 0x49, 0xa8, 0x41, 0xec, 0x04, +0x3a, 0x6f, 0xa4, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x98, 0xbc, 0x46, 0xf0, 0x00, 0x44, 0x58, 0xf7, +0x84, 0x6c, 0xdd, 0x2f, 0x80, 0xc0, 0xc8, 0x07, 0x84, 0x01, 0x46, 0xf0, 0x00, 0x35, 0x58, 0xf7, +0x89, 0x0c, 0xdd, 0x2f, 0x80, 0x06, 0x3a, 0x6f, 0x98, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3a, 0x6f, +0x9c, 0xbc, 0xef, 0xfc, 0x84, 0xa4, 0x96, 0x00, 0xd9, 0x09, 0x46, 0x50, 0x04, 0xb0, 0x04, 0x62, +0x80, 0x20, 0x42, 0x63, 0x1c, 0x09, 0x14, 0x62, 0x80, 0x20, 0x46, 0xf0, 0x00, 0x42, 0x58, 0xf7, +0x8c, 0xc0, 0xdd, 0x2f, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, +0xfc, 0xbc, 0xef, 0xfc, 0x44, 0x20, 0xfc, 0x6b, 0x96, 0x49, 0x4c, 0x11, 0x00, 0x34, 0xe2, 0x41, +0xe9, 0x05, 0x44, 0x50, 0xfc, 0x4d, 0xd9, 0x35, 0xd5, 0x1e, 0x44, 0x50, 0xfc, 0xbc, 0xd1, 0x23, +0x9d, 0x6f, 0xd9, 0x2f, 0xa6, 0x43, 0x84, 0x41, 0x4c, 0x11, 0x00, 0x04, 0x80, 0x02, 0xd5, 0x0a, +0xa6, 0x82, 0x9c, 0x44, 0x9e, 0x11, 0x96, 0x00, 0x46, 0xf0, 0x00, 0x91, 0x58, 0xf7, 0x8b, 0xe4, +0xdd, 0x2f, 0x80, 0x20, 0x44, 0x00, 0xfc, 0xc3, 0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, 0x82, 0x3c, +0xdd, 0x2f, 0xd5, 0x07, 0x9c, 0x03, 0x46, 0xf0, 0x00, 0x91, 0x58, 0xf7, 0x86, 0x6c, 0xdd, 0x2f, +0x84, 0x00, 0xd5, 0x14, 0xa6, 0x03, 0x46, 0xf0, 0x00, 0x91, 0x58, 0xf7, 0x8a, 0xdc, 0xdd, 0x2f, +0xd5, 0xf8, 0x9c, 0x03, 0x46, 0xf0, 0x00, 0x91, 0x58, 0xf7, 0x88, 0x28, 0xdd, 0x2f, 0xd5, 0xf1, +0x46, 0xf0, 0x00, 0x0e, 0x58, 0xf7, 0x85, 0x08, 0xdd, 0x2f, 0xec, 0x04, 0x3b, 0xff, 0xfc, 0x84, +0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xfc, 0x46, 0x30, 0x00, 0x90, 0x46, 0xf0, 0x01, 0x00, +0x14, 0x37, 0x80, 0x4a, 0x46, 0x50, 0x00, 0x92, 0x58, 0x52, 0x85, 0x70, 0x46, 0xf0, 0x01, 0x01, +0x14, 0x57, 0x80, 0x14, 0x46, 0x50, 0x00, 0x92, 0x58, 0x52, 0x85, 0x48, 0x46, 0xf0, 0x01, 0x01, +0x14, 0x57, 0x80, 0x5b, 0x46, 0x50, 0x00, 0x90, 0x58, 0x52, 0x88, 0x14, 0x46, 0xf0, 0x01, 0x01, +0x14, 0x57, 0x80, 0x7d, 0x46, 0x50, 0x00, 0x90, 0x58, 0x52, 0x8c, 0x00, 0x46, 0xf0, 0x01, 0x01, +0x14, 0x57, 0x80, 0x94, 0x46, 0x50, 0x00, 0x90, 0x58, 0x52, 0x88, 0x8c, 0x46, 0xf0, 0x01, 0x01, +0x14, 0x57, 0x80, 0xa0, 0x46, 0x50, 0x00, 0x92, 0x58, 0x52, 0x83, 0x64, 0x46, 0xf0, 0x01, 0x01, +0x14, 0x57, 0x80, 0x69, 0x46, 0x50, 0x00, 0x91, 0x58, 0x52, 0x88, 0x9c, 0x46, 0xf0, 0x01, 0x01, +0x14, 0x57, 0x80, 0x75, 0x46, 0x50, 0x00, 0x90, 0x58, 0x52, 0x88, 0x94, 0x46, 0xf0, 0x01, 0x01, +0x14, 0x57, 0x80, 0x9b, 0x46, 0x30, 0x00, 0x91, 0x58, 0x31, 0x8c, 0x44, 0x46, 0xf0, 0x01, 0x00, +0x14, 0x37, 0x80, 0xca, 0x46, 0x50, 0x00, 0x91, 0x58, 0x52, 0x8f, 0x94, 0x46, 0x20, 0x01, 0x00, +0x58, 0x21, 0x03, 0xf8, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x57, 0x83, 0x84, 0x46, 0x30, 0x00, 0x91, +0x58, 0x31, 0x8d, 0xc8, 0x46, 0x50, 0x00, 0x90, 0x58, 0x52, 0x8b, 0x30, 0x14, 0x31, 0x00, 0x0b, +0x46, 0xf0, 0x01, 0x01, 0x14, 0x57, 0x80, 0xb3, 0x46, 0x30, 0x00, 0x92, 0x58, 0x31, 0x83, 0x48, +0x46, 0xf0, 0x01, 0x00, 0x14, 0x37, 0x80, 0xc8, 0x46, 0x30, 0x00, 0x91, 0x58, 0x31, 0x8f, 0x60, +0xa8, 0xd2, 0x46, 0x30, 0x00, 0x91, 0x58, 0x31, 0x8e, 0x04, 0xa8, 0xd5, 0x84, 0x09, 0x46, 0x10, +0x00, 0x91, 0x58, 0x10, 0x8c, 0xe0, 0x46, 0xf0, 0x00, 0x3a, 0x58, 0xf7, 0x8d, 0xa4, 0xdd, 0x2f, +0x46, 0x40, 0x00, 0x91, 0x58, 0x42, 0x0b, 0x08, 0x46, 0x20, 0x30, 0x61, 0x46, 0xf0, 0x01, 0x00, +0x14, 0x47, 0x83, 0x9a, 0x58, 0x21, 0x01, 0xdf, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x27, 0x83, 0xa6, +0x46, 0xf0, 0x01, 0x00, 0x14, 0x27, 0x83, 0xa5, 0x84, 0xc0, 0x46, 0xf0, 0x01, 0x20, 0x14, 0x67, +0x82, 0x00, 0x46, 0xf0, 0x01, 0x20, 0x14, 0x67, 0x82, 0x01, 0x46, 0x70, 0x00, 0x27, 0x58, 0x73, +0x86, 0xfc, 0x44, 0x00, 0x00, 0x1d, 0x46, 0x10, 0x00, 0x91, 0x58, 0x10, 0x85, 0xcc, 0x4b, 0xe0, +0x1c, 0x01, 0x46, 0x00, 0x01, 0x20, 0x58, 0x00, 0x08, 0x18, 0x80, 0x26, 0x44, 0x20, 0x00, 0xe4, +0x46, 0xf0, 0x00, 0x40, 0x58, 0xf7, 0x84, 0x18, 0xdd, 0x2f, 0x46, 0x10, 0x00, 0x5a, 0x58, 0x10, +0x8e, 0xe5, 0x84, 0x4a, 0x46, 0x00, 0x01, 0x20, 0x58, 0x00, 0x08, 0x28, 0x46, 0xf0, 0x00, 0x40, +0x58, 0xf7, 0x83, 0xf4, 0xdd, 0x2f, 0x46, 0x20, 0x01, 0x20, 0x58, 0x21, 0x08, 0x18, 0x50, 0x31, +0x00, 0x3b, 0x50, 0x41, 0x00, 0x8a, 0x14, 0x41, 0x00, 0x38, 0x14, 0x31, 0x00, 0x37, 0x44, 0x00, +0x00, 0x19, 0x46, 0x10, 0x00, 0x91, 0x58, 0x10, 0x81, 0x78, 0x4b, 0xe0, 0x1c, 0x01, 0x46, 0x00, +0x01, 0x20, 0x00, 0x10, 0x08, 0x09, 0x44, 0x50, 0x00, 0xff, 0xd9, 0x24, 0x10, 0x60, 0x08, 0x09, +0x46, 0x00, 0x04, 0x00, 0x58, 0x00, 0x01, 0x28, 0xb4, 0x20, 0x44, 0x3f, 0x0f, 0xff, 0x40, 0x10, +0x8c, 0x02, 0xb6, 0x20, 0x46, 0x20, 0x04, 0x00, 0xb4, 0x60, 0x58, 0x31, 0x90, 0x00, 0xb6, 0x60, +0x46, 0x3f, 0xff, 0x7f, 0x04, 0x01, 0x00, 0x6e, 0x58, 0x31, 0x8f, 0xff, 0x40, 0x00, 0x0c, 0x02, +0x14, 0x01, 0x00, 0x6e, 0x80, 0x22, 0x04, 0x00, 0x80, 0x6f, 0x40, 0x00, 0x0c, 0x02, 0x14, 0x00, +0x80, 0x6f, 0x46, 0x10, 0x00, 0x90, 0x58, 0x10, 0x8c, 0xdc, 0x46, 0xf0, 0x01, 0x00, 0x14, 0x17, +0x83, 0xb0, 0xec, 0x04, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, 0x9c, 0xbc, 0xef, 0xf4, +0x44, 0x00, 0x00, 0x3a, 0x50, 0x1f, 0x80, 0x07, 0x84, 0x41, 0x46, 0xf0, 0x00, 0x51, 0x58, 0xf7, +0x80, 0xf0, 0xdd, 0x2f, 0x00, 0x0f, 0x80, 0x07, 0x96, 0x42, 0x4e, 0x15, 0x00, 0x16, 0x46, 0x40, +0x04, 0x00, 0x46, 0x10, 0x00, 0xa0, 0x80, 0x64, 0x80, 0x43, 0x9f, 0x41, 0x58, 0x10, 0x8a, 0x3f, +0x97, 0x68, 0x14, 0x12, 0x00, 0x41, 0x14, 0x11, 0x80, 0x42, 0x14, 0x11, 0x00, 0x43, 0x5c, 0xf2, +0x80, 0xfe, 0xe8, 0x53, 0xd5, 0x23, 0x46, 0x10, 0x04, 0x00, 0x04, 0x10, 0x80, 0x19, 0x42, 0x10, +0xf4, 0x0b, 0x9f, 0xc1, 0xc1, 0x26, 0x46, 0x50, 0x04, 0x00, 0x46, 0x60, 0x00, 0x80, 0x80, 0x65, +0x46, 0x40, 0x00, 0x90, 0x80, 0x43, 0x46, 0x10, 0x00, 0xa1, 0x58, 0x63, 0x00, 0x0f, 0x58, 0x42, +0x0a, 0x1e, 0x58, 0x10, 0x8e, 0x7f, 0x97, 0xf8, 0x14, 0x62, 0x80, 0x41, 0x14, 0x41, 0x80, 0x42, +0x14, 0x11, 0x00, 0x43, 0x5c, 0xf3, 0x80, 0xfe, 0xe8, 0x30, 0x54, 0x10, 0x00, 0x7f, 0x46, 0x00, +0x00, 0xb8, 0x40, 0x10, 0xa0, 0x08, 0x58, 0x00, 0x00, 0x7f, 0x40, 0x10, 0x80, 0x04, 0xd5, 0x25, +0x46, 0x50, 0x04, 0x00, 0x46, 0x60, 0x00, 0x80, 0x80, 0x65, 0x46, 0x40, 0x00, 0x90, 0x80, 0x43, +0x46, 0x10, 0x00, 0xa1, 0x58, 0x63, 0x00, 0x1e, 0x58, 0x42, 0x0a, 0x3c, 0x58, 0x10, 0x8e, 0x7f, +0x97, 0xf8, 0x14, 0x62, 0x80, 0x41, 0x14, 0x41, 0x80, 0x42, 0x14, 0x11, 0x00, 0x43, 0x5c, 0xf3, +0x80, 0xfe, 0xe8, 0x0b, 0x54, 0x10, 0x00, 0x7f, 0x46, 0x20, 0x00, 0xb8, 0x40, 0x10, 0xa0, 0x08, +0x58, 0x21, 0x00, 0xe0, 0x40, 0x10, 0x88, 0x04, 0x46, 0x20, 0x04, 0x00, 0x14, 0x11, 0x00, 0x44, +0xec, 0x0c, 0x3a, 0x6f, 0x9c, 0x84, 0xdd, 0x9e, 0x92, 0x00, 0x3b, 0xff, 0xfc, 0xbc, 0xef, 0xf4, +0x44, 0x00, 0x00, 0x3a, 0x50, 0x1f, 0x80, 0x07, 0x84, 0x41, 0x46, 0xf0, 0x00, 0x51, 0x58, 0xf7, +0x80, 0xf0, 0xdd, 0x2f, 0x20, 0x0f, 0x80, 0x07, 0x4e, 0x05, 0x00, 0x12, 0x46, 0x40, 0x04, 0x00, +0x80, 0x64, 0x80, 0x43, 0x80, 0x22, 0x44, 0x06, 0x0a, 0x3f, 0x14, 0x02, 0x00, 0x41, 0x14, 0x01, +0x80, 0x42, 0x14, 0x01, 0x00, 0x43, 0x14, 0x00, 0x80, 0x44, 0xd5, 0x36, 0x46, 0x00, 0x04, 0x00, +0x04, 0x00, 0x00, 0x19, 0x42, 0x00, 0x74, 0x0b, 0xc0, 0x18, 0x46, 0x30, 0x04, 0x00, 0x80, 0x43, +0x44, 0x46, 0x9e, 0x3f, 0x14, 0x41, 0x80, 0x41, 0x80, 0x22, 0x44, 0x35, 0x94, 0x2f, 0x14, 0x31, +0x00, 0x42, 0x46, 0x00, 0x04, 0x00, 0x44, 0x24, 0x8a, 0x0f, 0x14, 0x20, 0x80, 0x43, 0x58, 0x00, +0x01, 0x10, 0x44, 0x14, 0x00, 0x07, 0xd5, 0x17, 0x46, 0x30, 0x04, 0x00, 0x80, 0x43, 0x44, 0x46, +0x9e, 0xe0, 0x14, 0x41, 0x80, 0x41, 0x80, 0x22, 0x44, 0x35, 0x94, 0x7f, 0x14, 0x31, 0x00, 0x42, +0x46, 0x00, 0x04, 0x00, 0x44, 0x24, 0x8a, 0x3f, 0x14, 0x20, 0x80, 0x43, 0x58, 0x00, 0x01, 0x10, +0x44, 0x14, 0x00, 0x0f, 0xb6, 0x20, 0xec, 0x0c, 0x3b, 0xff, 0xfc, 0x84, 0xdd, 0x9e, 0x3a, 0x6f, +0xaa, 0xbc, 0xef, 0x94, 0x51, 0xc0, 0x00, 0x02, 0x81, 0x00, 0x84, 0x42, 0x80, 0x1c, 0xa6, 0x40, +0x9c, 0x91, 0x56, 0x10, 0x80, 0x55, 0x18, 0x10, 0x00, 0x01, 0x96, 0x90, 0x84, 0xab, 0xda, 0xf8, +0x46, 0x00, 0x01, 0x01, 0x58, 0x00, 0x06, 0x58, 0x46, 0xf0, 0x00, 0x1b, 0x58, 0xf7, 0x89, 0xf8, +0xdd, 0x2f, 0x80, 0xe0, 0x4e, 0x03, 0x00, 0xa4, 0x46, 0xf0, 0x00, 0x1b, 0x58, 0xf7, 0x8b, 0x0c, +0xdd, 0x2f, 0x80, 0xe0, 0x50, 0x0f, 0x80, 0x14, 0x4e, 0x72, 0x01, 0x25, 0x84, 0x20, 0x10, 0x10, +0x00, 0x0a, 0x84, 0x20, 0xb6, 0x20, 0x46, 0x20, 0x01, 0x01, 0x58, 0x21, 0x06, 0x58, 0x44, 0x10, +0x02, 0x55, 0xa8, 0x41, 0xa8, 0x84, 0x84, 0x21, 0x02, 0x33, 0x80, 0xc4, 0xac, 0xc6, 0x14, 0x13, +0x80, 0x6c, 0xb6, 0x27, 0x00, 0x03, 0x81, 0xae, 0xf0, 0x83, 0x3a, 0x01, 0x04, 0x00, 0x12, 0x13, +0x80, 0xd6, 0x14, 0x03, 0x80, 0x6a, 0x46, 0xf0, 0x00, 0x2d, 0x58, 0xf7, 0x8f, 0xf4, 0xdd, 0x2f, +0x84, 0xaa, 0xd8, 0x07, 0x84, 0x02, 0x46, 0xf0, 0x00, 0x2d, 0x58, 0xf7, 0x8d, 0x34, 0xdd, 0x2f, +0x46, 0x00, 0x01, 0x01, 0x58, 0x00, 0x06, 0x58, 0x02, 0x30, 0x00, 0x34, 0x04, 0x20, 0x00, 0x18, +0x44, 0x10, 0x00, 0x30, 0x42, 0x21, 0x84, 0x73, 0x85, 0x21, 0x84, 0x82, 0x46, 0xf0, 0x01, 0x09, +0x14, 0x47, 0x81, 0xdc, 0x14, 0x91, 0x00, 0x01, 0x50, 0xaf, 0x80, 0x60, 0x04, 0x60, 0x00, 0x18, +0xf2, 0x03, 0x46, 0x00, 0x0a, 0x5f, 0x42, 0x61, 0x04, 0x73, 0x58, 0x00, 0x00, 0xc3, 0x04, 0x13, +0x00, 0x0a, 0x14, 0x93, 0x00, 0x01, 0x10, 0x90, 0x80, 0x33, 0x80, 0x4a, 0x50, 0x1f, 0x80, 0x64, +0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x9c, 0xdd, 0x2f, 0xb4, 0x4a, 0x04, 0x13, 0x00, 0x0a, +0x04, 0xa5, 0x00, 0x01, 0xb6, 0x41, 0x14, 0xa0, 0x80, 0x01, 0x46, 0x00, 0x0a, 0x5f, 0x04, 0x13, +0x00, 0x0a, 0x85, 0x40, 0x40, 0x55, 0x18, 0x06, 0x46, 0x40, 0x00, 0x04, 0x58, 0x42, 0x01, 0x3c, +0x58, 0x00, 0x00, 0xc3, 0xa8, 0x0a, 0xf4, 0x81, 0xf5, 0x82, 0x80, 0x05, 0x80, 0x2a, 0x46, 0x20, +0x00, 0x92, 0x58, 0x21, 0x0c, 0xb4, 0x44, 0x30, 0x02, 0x9c, 0xdd, 0x24, 0x04, 0x03, 0x00, 0x0a, +0x46, 0x20, 0x00, 0x92, 0x58, 0x21, 0x0c, 0xb4, 0x10, 0x90, 0x00, 0x2e, 0x80, 0x2a, 0xf0, 0x02, +0xf4, 0x01, 0x44, 0x30, 0x02, 0x89, 0xdd, 0x24, 0x04, 0x13, 0x00, 0x0a, 0x80, 0x06, 0x10, 0x90, +0x80, 0x2d, 0x46, 0xf0, 0x00, 0x28, 0x58, 0xf7, 0x8e, 0xf8, 0xdd, 0x2f, 0x46, 0xf0, 0x01, 0x00, +0x04, 0x27, 0x83, 0x63, 0x50, 0x1f, 0x80, 0x14, 0x84, 0x03, 0xdd, 0x22, 0x00, 0x63, 0x81, 0xae, +0x80, 0x3c, 0x80, 0x06, 0x46, 0xf0, 0x00, 0x30, 0x58, 0xf7, 0x85, 0xb8, 0xdd, 0x2f, 0xf0, 0x85, +0xc0, 0x04, 0x44, 0x50, 0x00, 0x1f, 0xd8, 0x72, 0x80, 0x06, 0x46, 0x70, 0x01, 0x0e, 0x46, 0xf0, +0x00, 0x30, 0x58, 0xf7, 0x84, 0x3c, 0xdd, 0x2f, 0x04, 0x03, 0x83, 0x96, 0x84, 0xa4, 0xd8, 0x03, +0x84, 0x05, 0xd5, 0x1c, 0x84, 0xa3, 0xd8, 0x1d, 0x46, 0x00, 0x04, 0x90, 0x04, 0x20, 0x00, 0x0d, +0x46, 0xf0, 0x01, 0x01, 0x04, 0x07, 0x81, 0xae, 0x94, 0x6c, 0x44, 0x3b, 0x1e, 0x00, 0x42, 0x03, +0x04, 0x73, 0x98, 0x53, 0x94, 0x4c, 0x92, 0x24, 0xb6, 0x20, 0x80, 0x06, 0x84, 0x20, 0x46, 0xf0, +0x00, 0x27, 0x58, 0xf7, 0x8e, 0x38, 0xdd, 0x2f, 0x84, 0x06, 0x14, 0x03, 0x83, 0x96, 0xd5, 0x3f, +0x84, 0xa8, 0xd8, 0x3d, 0x00, 0x74, 0x00, 0x12, 0x00, 0x14, 0x00, 0x13, 0x40, 0x73, 0xc0, 0x08, +0x40, 0x10, 0xa0, 0x08, 0x00, 0x04, 0x00, 0x14, 0x00, 0xa4, 0x00, 0x11, 0x40, 0x73, 0x84, 0x04, +0x40, 0x73, 0x80, 0x04, 0x4e, 0xa3, 0x00, 0x03, 0xc7, 0x23, 0x50, 0x9f, 0x80, 0x60, 0x80, 0x07, +0x80, 0x49, 0x50, 0x1f, 0x80, 0x64, 0x46, 0xf0, 0x00, 0x02, 0x58, 0xf7, 0x84, 0x9c, 0xdd, 0x2f, +0x46, 0xf0, 0x01, 0x01, 0x04, 0x17, 0x81, 0xae, 0x44, 0x00, 0x00, 0x30, 0x42, 0x13, 0x00, 0x73, +0xb4, 0x49, 0x04, 0x00, 0x80, 0x0a, 0x04, 0x94, 0x80, 0x01, 0xb6, 0x40, 0x14, 0x90, 0x00, 0x01, +0x40, 0xa5, 0x60, 0x08, 0x04, 0x00, 0x80, 0x0a, 0x40, 0x73, 0xa8, 0x04, 0xa9, 0xc2, 0x80, 0x08, +0x46, 0xf0, 0x00, 0x30, 0x58, 0xf7, 0x81, 0xb4, 0xdd, 0x2f, 0xf0, 0x85, 0x80, 0x06, 0x84, 0x20, +0x46, 0xf0, 0x00, 0x27, 0x58, 0xf7, 0x85, 0xcc, 0xdd, 0x2f, 0xf1, 0x05, 0x44, 0x50, 0x00, 0x1f, +0xd1, 0x0c, 0x44, 0x00, 0xfc, 0x0d, 0x46, 0xf0, 0x00, 0x0f, 0x58, 0xf7, 0x82, 0x3c, 0xdd, 0x2f, +0xd5, 0x04, 0x84, 0x22, 0xb6, 0x20, 0xd5, 0xf2, 0xec, 0x6c, 0x3a, 0x6f, 0xaa, 0x84, 0xdd, 0x9e, +0x92, 0x00, 0x62, 0x6c, 0x75, 0x65, 0x74, 0x6f, 0x6f, 0x74, 0x68, 0x2f, 0x63, 0x6f, 0x72, 0x65, +0x2f, 0x6c, 0x63, 0x2f, 0x64, 0x6c, 0x2f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x2f, 0x64, +0x6c, 0x5f, 0x64, 0x65, 0x76, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x2e, 0x68, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x7f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, +0xff, 0x7f, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7f, +0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, +0xff, 0x00, } ; diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/misc.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/misc.h new file mode 100644 index 000000000..2248bd3e8 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/misc.h @@ -0,0 +1,32 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2009, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + misc.h + + Abstract: + + Handling Misc Problem + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Sean Wang 2009-08-12 Create + John Li 2009-12-23 Modified +*/ + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/misc_cmm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/misc_cmm.h new file mode 100644 index 000000000..aa91c8056 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/misc_cmm.h @@ -0,0 +1,32 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2009, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + misc_cmm.h + + Abstract: + + Handling Misc Problem + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Sean Wang 2009-08-12 Create + John Li 2009-12-23 Modified +*/ + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mix_mode.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mix_mode.h new file mode 100644 index 000000000..cf80469c1 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mix_mode.h @@ -0,0 +1,151 @@ +#ifndef __MIX_MODE_H__ +#define __MIX_MODE_H__ + +#define MixModeDefualtListenTime 200 + +#define RMAC_SMESH (WF_RMAC_BASE + 0x048) +#define RMAC_SMESH_B1 (WF_RMAC_BASE + 0x148) + + +#define SMESH_RX_CTL BIT(20) +#define SMESH_RX_CTL_OFFSET 20 +#define SMESH_RX_MGT BIT(19) +#define SMESH_RX_MGT_OFFSET 19 +#define SMESH_RX_DATA BIT(18) +#define SMESH_RX_DATA_OFFSET 18 +#define SMESH_RX_A1 BIT(17) +#define SMESH_RX_A2 BIT(16) + +#define MAR1_MAR_GROUP_MASK BITS(30,31) +#define MAR1_MAR_GROUP_OFFSET 30 +#define MAR1_MAR_HASH_MODE_BSSID1 BIT(30) +#define MAR1_MAR_HASH_MODE_BSSID2 BIT(31) +#define MAR1_MAR_HASH_MODE_BSSID3 BITS(30,31) + +#define MAR1_ADDR_INDEX_MASK BITS(24,29) +#define MAR1_ADDR_INDEX_OFFSET 24 +#define MAR1_READ 0 +#define MAR1_WRITE BIT(17) +#define MAR1_ACCESS_START_STATUS BIT(16) + + +#define DEFAULT_MNTR_RULE (SMESH_RX_CTL |SMESH_RX_MGT| SMESH_RX_DATA| SMESH_RX_A1| SMESH_RX_A2) + +#define MAX_NUM_OF_MONITOR_STA 8 /*0, 1~4=4, 5~8=8, 9~12=12, 13~16=16 */ +#define SMESH_OFFSET (MAX_NUM_OF_MONITOR_STA / 4) +#define MAX_NUM_OF_MONITOR_GROUP (MAX_NUM_OF_MONITOR_STA / 2) +#define MAX_NUM_PER_GROUP 2 + +#define MONITOR_MUAR_BASE_INDEX1 0x20 +#define MONITOR_MUAR_BASE_INDEX2 0x28 + +#define ENTRY_CAT_MONITOR 0x010 +#define ENTRY_MONITOR ENTRY_CAT_MONITOR + +#define IS_ENTRY_MONITOR(_x) ((_x)->EntryType == ENTRY_CAT_MONITOR) +#define SET_ENTRY_MONITOR(_x) ((_x)->EntryType = ENTRY_MONITOR) + + +#define MixMode_On(_p) (((_p)->MixModeCtrl.MixModeOn) == TRUE) + +#define MIX_MODE_OFF 0 +#define MIX_MODE_FULL 2 + +typedef enum _MNT_BAND_TYPE { + MNT_BAND0 = 1, + MNT_BAND1 = 2 +} MNT_BAND_TYPE; + + +enum MIX_MODE_STATE { + MIX_MODE_STATE_BASE = 0, + MIX_MODE_STATE_INIT = MIX_MODE_STATE_BASE, + MIX_MODE_STATE_RUNNING, + MIX_MODE_STATE_MAX +}; + +enum MIX_MODE_MSG { + MIX_MODE_MSG_LISTEN = 0, + MIX_MODE_MSG_CANCLE, + MIX_MODE_MSG_TIMEOUT, + MIX_MODE_MSG_MAX +}; + +#define MIX_MODE_FUNC_SIZE MIX_MODE_STATE_MAX * MIX_MODE_MSG_MAX + +typedef struct _MNT_MUAR_GROUP { + BOOLEAN bValid; + UCHAR Count; + UCHAR Band; + UCHAR MuarGroupBase; +} MNT_MUAR_GROUP, *PMNT_MUAR_GROUP; + +struct INFO_STA { + LONG cnt; + LONG rssi; +}; + +struct MNT_STA_INFO { + LONG Count; + struct INFO_STA frm[FC_TYPE_RSVED]; +}; + +typedef struct _MNT_STA_ENTRY { + NDIS_SPIN_LOCK MntStaLock; + BOOLEAN bValid; + UCHAR Band; + UCHAR muar_idx; + UCHAR muar_group_idx; + struct MNT_STA_INFO mnt_sta; + UCHAR addr[MAC_ADDR_LEN]; + RSSI_SAMPLE RssiSample; + VOID *pMacEntry; +} MNT_STA_ENTRY, *PMNT_STA_ENTRY; + +struct mix_peer_parameter { + UCHAR channel; /*listen channel*/ + UCHAR center_channel; + UCHAR bw; + UCHAR ch_offset; + UCHAR mac_addr[MAC_ADDR_LEN]; + USHORT duration; /*listen time*/ +// UINT32 duration; +}; +struct peer_info { + UCHAR channel; /*listen channel*/ + UCHAR center_channel; + UCHAR bw; + UCHAR ch_offset; + UCHAR mac_addr[MAC_ADDR_LEN]; + USHORT duration; /*listen time*/ +// UINT32 duration; + struct MNT_STA_INFO mnt_sta; + RSSI_SAMPLE RssiSample; + NDIS_SPIN_LOCK MntStaLock; +}; + +typedef struct _MIX_MODE_CTRL { + struct peer_info sta_info[MAX_NUM_OF_MONITOR_STA]; + RALINK_TIMER_STRUCT MixModeTimer; + STATE_MACHINE MixModeStatMachine; + STATE_MACHINE_FUNC MixModeStateFunc[MIX_MODE_FUNC_SIZE]; + struct wifi_dev *pMixModewdev; + INT ioctl_if; + BOOLEAN MixModeOn; + MNT_STA_ENTRY MntTable[MAX_NUM_OF_MONITOR_STA]; + MNT_MUAR_GROUP MntGroupTable[MAX_NUM_OF_MONITOR_GROUP]; + UCHAR MntIdx; + UCHAR current_monitor_mode; +} MIX_MODE_CTRL; + +VOID MixModeTimeout(IN PVOID SystemSpecific1,IN PVOID FunctionContext, + IN PVOID SystemSpecific2, IN PVOID SystemSpecific3); +VOID MixModeDebugInfo(IN PRTMP_ADAPTER pAd, IN int idx); +INT MixModeSet(IN PRTMP_ADAPTER pAd, struct mix_peer_parameter *sta_info, IN UCHAR idx); +INT RTMPIoctlQueryMixModeRssi(IN PRTMP_ADAPTER pAd, IN RTMP_IOCTL_INPUT_STRUCT *wrq); +VOID MixModeCancel(IN PRTMP_ADAPTER pAd); +VOID MixModeInit(IN PRTMP_ADAPTER pAd); +VOID MixModeDel(IN PRTMP_ADAPTER pAd); +VOID MixModeProcessData(RTMP_ADAPTER *pAd, void *pRxBlk); +BOOLEAN MixModeCliIdxCheck(IN void *pAd, IN UCHAR CliIdx); +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mlme.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mlme.h new file mode 100644 index 000000000..be03bef99 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mlme.h @@ -0,0 +1,1545 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + mlme.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + John Chang 2003-08-28 Created + John Chang 2004-09-06 modified for RT2600 + +*/ +#ifndef __MLME_H__ +#define __MLME_H__ + +#include "rtmp_dot11.h" + + +#ifdef DOT11R_FT_SUPPORT +#include "link_list.h" +#include "ft_cmm.h" +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT +#include "dot11r_ft.h" +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef CONFIG_OWE_SUPPORT +#include "owe_cmm.h" +#endif + +/* 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 CHN 5 +#define MAX_RD_REGION 6 +#if defined(CONFIG_MULTI_CHANNEL) || defined(DOT11Z_TDLS_SUPPORT) +#define BEACON_LOST_TIME 12 * OS_HZ /* 2048 msec = 2 sec */ +#else +#if defined(MT7603_FPGA) || defined(MT7628_FPGA) +#define BEACON_LOST_TIME 40 * OS_HZ /* 2048 msec = 2 sec */ +#else +#define BEACON_LOST_TIME 4 * OS_HZ /* 2048 msec = 2 sec */ +#endif /* MT7603_FPGA */ +#endif /* defined(CONFIG_MULTI_CHANNEL) || defined(DOT11Z_TDLS_SUPPORT) */ + +#define DLS_TIMEOUT 1200 /* unit: msec */ +#define AUTH_TIMEOUT 300 /* unit: msec */ +#define ASSOC_TIMEOUT 300 /* unit: msec */ +#if defined(MT7603_FPGA) || defined(MT7628_FPGA) +#define JOIN_TIMEOUT 2000 /* unit: msec */ +#else +#define JOIN_TIMEOUT 2000 /* unit: msec */ +#endif /* MT7603_FPGA */ +#define SHORT_CHANNEL_TIME 90 /* unit: msec */ +#define MIN_CHANNEL_TIME 110 /* unit: msec, for dual band scan */ +#define MAX_CHANNEL_TIME 140 /* unit: msec, for single band scan */ +#define FAST_ACTIVE_SCAN_TIME 30 /* Active scan waiting for probe response time */ + +#define AUTO_CHANNEL_SEL_TIMEOUT 400 /* uint: msec */ +#define LINK_DOWN_TIMEOUT 20000 /* unit: msec */ +#define AUTO_WAKEUP_TIMEOUT 70 /*unit: msec */ + +/* Note: RSSI_TO_DBM_OFFSET has been changed to variable for new RF (2004-0720). */ +/* SHould not refer to this constant anymore */ +/*#define RSSI_TO_DBM_OFFSET 120 // for RT2530 RSSI-115 = dBm */ +#define RSSI_FOR_MID_TX_POWER -55 /* -55 db is considered mid-distance */ +#define RSSI_FOR_LOW_TX_POWER -45 /* -45 db is considered very short distance and */ + /* eligible to use a lower TX power */ +#define RSSI_FOR_LOWEST_TX_POWER -30 +/*#define MID_TX_POWER_DELTA 0 // 0 db from full TX power upon mid-distance to AP */ +#define LOW_TX_POWER_DELTA 6 /* -3 db from full TX power upon very short distance. 1 grade is 0.5 db */ +#define LOWEST_TX_POWER_DELTA 16 /* -8 db from full TX power upon shortest distance. 1 grade is 0.5 db */ + +#define RSSI_TRIGGERED_UPON_BELOW_THRESHOLD 0 +#define RSSI_TRIGGERED_UPON_EXCCEED_THRESHOLD 1 +#define RSSI_THRESHOLD_FOR_ROAMING 25 +#define RSSI_DELTA 5 + +/* Channel Quality Indication */ +#define CQI_IS_GOOD(cqi) ((cqi) >= 50) +/*#define CQI_IS_FAIR(cqi) (((cqi) >= 20) && ((cqi) < 50)) */ +#define CQI_IS_POOR(cqi) (cqi < 50) /*(((cqi) >= 5) && ((cqi) < 20)) */ +#define CQI_IS_BAD(cqi) (cqi < 5) +#define CQI_IS_DEAD(cqi) (cqi == 0) + +/* weighting factor to calculate Channel quality, total should be 100% */ +#define RSSI_WEIGHTING 50 +#define TX_WEIGHTING 30 +#define RX_WEIGHTING 20 + + +#define BSS_NOT_FOUND 0xFFFFFFFF + + +#ifdef EAPOL_QUEUE_SUPPORT +#define MAX_LEN_OF_EAP_QUEUE (40) +#endif /* EAPOL_QUEUE_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +#define MAX_LEN_OF_MLME_QUEUE 64 /*20*/ /*10 */ +#endif /* CONFIG_AP_SUPPORT */ + + +enum SCAN_MODE{ + /* Active scan, send probe request, and wait beacon and probe response */ + SCAN_ACTIVE = 0x00, /* all channels */ + SCAN_CISCO_ACTIVE = 0x1, /* single channel only */ + FAST_SCAN_ACTIVE = 0x2, +#ifdef WSC_INCLUDED + SCAN_WSC_ACTIVE = 0x3, +#endif /* WSC_INCLUDED */ +#ifdef DOT11N_DRAFT3 + SCAN_2040_BSS_COEXIST = 0x4, +#endif /* DOT11N_DRAFT3 */ + SCAN_ACTIVE_MAX, + + /* Passive scan, no probe request, only wait beacon and probe response */ + SCAN_PASSIVE = 0x80, /* all channels */ + SCAN_CISCO_PASSIVE = 0x81, /* single channel only */ + SCAN_CISCO_NOISE = 0x82, /* single channel only, for noise histogram collection */ + SCAN_CISCO_CHANNEL_LOAD = 0x83, /* single channel only, for channel load collection */ + SCAN_PASSIVE_MAX, + + SCAN_TYPE_MAX +}; + +#define SCAN_MASK 0x80 +#define SCAN_MODE_ACT(_x) (((_x) & SCAN_MASK) == 0) +#define SCAN_MODE_PSV(_x) (((_x) & SCAN_MASK) == SCAN_MASK) +#define SCAN_MODE_VALID(_x) ((SCAN_MODE_ACT(_x) && ((_x) < SCAN_ACTIVE_MAX)) ||\ + (SCAN_MODE_PSV(_x) && ((_x) < SCAN_PASSIVE_MAX))) + +/*#define BSS_TABLE_EMPTY(x) ((x).BssNr == 0) */ +#define MAC_ADDR_IS_GROUP(Addr) (((Addr[0]) & 0x01)) +#define MAC_ADDR_HASH(Addr) (Addr[0] ^ Addr[1] ^ Addr[2] ^ Addr[3] ^ Addr[4] ^ Addr[5]) +#define MAC_ADDR_HASH_INDEX(Addr) (MAC_ADDR_HASH(Addr) & (HASH_TABLE_SIZE - 1)) +#define TID_MAC_HASH(Addr,TID) (TID^Addr[0] ^ Addr[1] ^ Addr[2] ^ Addr[3] ^ Addr[4] ^ Addr[5]) +#define TID_MAC_HASH_INDEX(Addr,TID) (TID_MAC_HASH(Addr,TID) & (HASH_TABLE_SIZE - 1)) + + +/* bit definition of the 2-byte pBEACON->Capability field */ +#define CAP_IS_ESS_ON(x) (((x) & 0x0001) != 0) +#define CAP_IS_IBSS_ON(x) (((x) & 0x0002) != 0) +#define CAP_IS_CF_POLLABLE_ON(x) (((x) & 0x0004) != 0) +#define CAP_IS_CF_POLL_REQ_ON(x) (((x) & 0x0008) != 0) +#define CAP_IS_PRIVACY_ON(x) (((x) & 0x0010) != 0) +#define CAP_IS_SHORT_PREAMBLE_ON(x) (((x) & 0x0020) != 0) +#define CAP_IS_PBCC_ON(x) (((x) & 0x0040) != 0) +#define CAP_IS_AGILITY_ON(x) (((x) & 0x0080) != 0) +#define CAP_IS_SPECTRUM_MGMT(x) (((x) & 0x0100) != 0) /* 802.11e d9 */ +#define CAP_IS_QOS(x) (((x) & 0x0200) != 0) /* 802.11e d9 */ +#define CAP_IS_SHORT_SLOT(x) (((x) & 0x0400) != 0) +#define CAP_IS_APSD(x) (((x) & 0x0800) != 0) /* 802.11e d9 */ +#define CAP_IS_IMMED_BA(x) (((x) & 0x1000) != 0) /* 802.11e d9 */ +#define CAP_IS_DSSS_OFDM(x) (((x) & 0x2000) != 0) +#define CAP_IS_DELAY_BA(x) (((x) & 0x4000) != 0) /* 802.11e d9 */ + +#define CAP_GENERATE(ess,ibss,priv,s_pre,s_slot,spectrum) (((ess) ? 0x0001 : 0x0000) | ((ibss) ? 0x0002 : 0x0000) | ((priv) ? 0x0010 : 0x0000) | ((s_pre) ? 0x0020 : 0x0000) | ((s_slot) ? 0x0400 : 0x0000) | ((spectrum) ? 0x0100 : 0x0000)) + +/*#define STA_QOS_CAPABILITY 0 // 1-byte. see 802.11e d9.0 for bit definition */ + +#define ERP_IS_NON_ERP_PRESENT(x) (((x) & 0x01) != 0) /* 802.11g */ +#define ERP_IS_USE_PROTECTION(x) (((x) & 0x02) != 0) /* 802.11g */ +#define ERP_IS_USE_BARKER_PREAMBLE(x) (((x) & 0x04) != 0) /* 802.11g */ + +#ifdef INTERFERENCE_RA_SUPPORT +#define DRS_TX_QUALITY_WORST_BOUND 4 +#else +#define DRS_TX_QUALITY_WORST_BOUND 8/* 3 // just test by gary */ +#define DRS_TX_QUALITY_HALF_BOUND 4 +#endif +#define DRS_PENALTY 8 + +#define BA_NOTUSE 2 +/*BA Policy subfiled value in ADDBA frame */ +#define IMMED_BA 1 +#define DELAY_BA 0 + +/* BA Initiator subfield in DELBA frame */ +#define ORIGINATOR 1 +#define RECIPIENT 0 + +/* ADDBA Status Code */ +#define ADDBA_RESULTCODE_SUCCESS 0 +#define ADDBA_RESULTCODE_REFUSED 37 +#define ADDBA_RESULTCODE_INVALID_PARAMETERS 38 + +/* DELBA Reason Code */ +#define DELBA_REASONCODE_QSTA_LEAVING 36 +#define DELBA_REASONCODE_END_BA 37 +#define DELBA_REASONCODE_UNKNOWN_BA 38 +#define DELBA_REASONCODE_TIMEOUT 39 + +/* reset all OneSecTx counters */ +#ifdef FIFO_EXT_SUPPORT +#define RESET_ONE_SEC_TX_CNT(__pEntry) \ +if (((__pEntry)) != NULL) \ +{ \ + (__pEntry)->OneSecTxRetryOkCount = 0; \ + (__pEntry)->OneSecTxFailCount = 0; \ + (__pEntry)->OneSecTxNoRetryOkCount = 0; \ + (__pEntry)->OneSecRxLGICount = 0; \ + (__pEntry)->OneSecRxSGICount = 0; \ + (__pEntry)->fifoTxSucCnt = 0;\ + (__pEntry)->fifoTxRtyCnt = 0;\ +} +#else +#define RESET_ONE_SEC_TX_CNT(__pEntry) \ +if (((__pEntry)) != NULL) \ +{ \ + (__pEntry)->OneSecTxRetryOkCount = 0; \ + (__pEntry)->OneSecTxFailCount = 0; \ + (__pEntry)->OneSecTxNoRetryOkCount = 0; \ + (__pEntry)->OneSecRxLGICount = 0; \ + (__pEntry)->OneSecRxSGICount = 0; \ +} +#endif /* FIFO_EXT_SUPPORT */ + + +/* + 802.11 frame formats +*/ + + +typedef struct _TRIGGER_EVENTA{ + BOOLEAN bValid; + UCHAR BSSID[6]; + UCHAR RegClass; /* Regulatory Class */ + USHORT Channel; +} TRIGGER_EVENTA, *PTRIGGER_EVENTA; + + +/* 20/40 trigger event table */ +/* If one Event A delete or created, or if Event B is detected or not detected, STA should send 2040BSSCoexistence to AP. */ +#define MAX_TRIGGER_EVENT 64 +typedef struct _TRIGGER_EVENT_TAB{ + UCHAR EventANo; + TRIGGER_EVENTA EventA[MAX_TRIGGER_EVENT]; + ULONG EventBCountDown; /* Count down counter for Event B. */ +} TRIGGER_EVENT_TAB, *PTRIGGER_EVENT_TAB; + + +/* + Extended capabilities information IE( ID = 127 = IE_EXT_CAPABILITY) + +*/ +typedef struct GNU_PACKED _EXT_CAP_INFO_ELEMENT{ +#ifdef RT_BIG_ENDIAN + UINT32 interworking:1; + UINT32 TDLSChSwitchSupport:1; /* bit30: TDLS Channel Switching */ + UINT32 TDLSPeerPSMSupport:1; /* bit29: TDLS Peer PSM Support */ + UINT32 UAPSDBufSTASupport:1; /* bit28: Peer U-APSD Buffer STA Support */ + UINT32 utc_tsf_offset:1; + UINT32 DMSSupport:1; + UINT32 ssid_list:1; + UINT32 channel_usage:1; + UINT32 timing_measurement:1; + UINT32 mbssid:1; + UINT32 ac_sta_cnt:1; + UINT32 qos_traffic_cap:1; + UINT32 BssTransitionManmt:1; + UINT32 tim_bcast:1; + UINT32 WNMSleepSupport:1;/*bit 17*/ + UINT32 TFSSupport:1;/*bit 16*/ + UINT32 geospatial_location:1; + UINT32 civic_location:1; + UINT32 collocated_interference_report:1; + UINT32 proxy_arp:1; + UINT32 FMSSupport:1;/*bit 11*/ + UINT32 location_tracking:1; + UINT32 mcast_diagnostics:1; + UINT32 diagnostics:1; + UINT32 event:1; + UINT32 s_psmp_support:1; + UINT32 rsv5:1; + UINT32 psmp_cap:1; + UINT32 rsv3:1; + UINT32 ExtendChannelSwitch:1; + UINT32 rsv1:1; + UINT32 BssCoexistMgmtSupport:1; +#else + UINT32 BssCoexistMgmtSupport:1; + UINT32 rsv1:1; + UINT32 ExtendChannelSwitch:1; + UINT32 rsv3:1; + UINT32 psmp_cap:1; + UINT32 rsv5:1; + UINT32 s_psmp_support:1; + UINT32 event:1; + UINT32 diagnostics:1; + UINT32 mcast_diagnostics:1; + UINT32 location_tracking:1; + UINT32 FMSSupport:1;/*bit 11*/ + UINT32 proxy_arp:1; + UINT32 collocated_interference_report:1; + UINT32 civic_location:1; + UINT32 geospatial_location:1; + UINT32 TFSSupport:1;/*bit 16*/ + UINT32 WNMSleepSupport:1;/*bit 17*/ + UINT32 tim_bcast:1; + UINT32 BssTransitionManmt:1; + UINT32 qos_traffic_cap:1; + UINT32 ac_sta_cnt:1; + UINT32 mbssid:1; + UINT32 timing_measurement:1; + UINT32 channel_usage:1; + UINT32 ssid_list:1; + UINT32 DMSSupport:1; + UINT32 utc_tsf_offset:1; + UINT32 UAPSDBufSTASupport:1; /* bit28: Peer U-APSD Buffer STA Support */ + UINT32 TDLSPeerPSMSupport:1; /* bit29: TDLS Peer PSM Support */ + UINT32 TDLSChSwitchSupport:1; /* bit30: TDLS Channel Switching */ + UINT32 interworking:1; +#endif /* RT_BIG_ENDIAN */ + +#ifdef RT_BIG_ENDIAN + UINT32 rsv63:1; + UINT32 operating_mode_notification:1; + UINT32 tdls_wider_bw:1; + UINT32 rsv49:12; + UINT32 utf8_ssid:1; + UINT32 rsv47:1; + UINT32 wnm_notification:1; + UINT32 uapsd_coex:1; + UINT32 id_location:1; + UINT32 service_interval_granularity:3; + UINT32 reject_unadmitted_frame:1; + UINT32 TDLSChSwitchProhibited:1; /* bit39: TDLS Channel Switching Prohibited */ + UINT32 TDLSProhibited:1; /* bit38: TDLS Prohibited */ + UINT32 TDLSSupport:1; /* bit37: TDLS Support */ + UINT32 msgcf_cap:1; + UINT32 rsv35:1; + UINT32 sspn_inf:1; + UINT32 ebr:1; + UINT32 qosmap:1; +#else + UINT32 qosmap:1; + UINT32 ebr:1; + UINT32 sspn_inf:1; + UINT32 rsv35:1; + UINT32 msgcf_cap:1; + UINT32 TDLSSupport:1; /* bit37: TDLS Support */ + UINT32 TDLSProhibited:1; /* bit38: TDLS Prohibited */ + UINT32 TDLSChSwitchProhibited:1; /* bit39: TDLS Channel Switching Prohibited */ + UINT32 reject_unadmitted_frame:1; + UINT32 service_interval_granularity:3; + UINT32 id_location:1; + UINT32 uapsd_coex:1; + UINT32 wnm_notification:1; + UINT32 rsv47:1; + UINT32 utf8_ssid:1; + UINT32 rsv49:12; + UINT32 tdls_wider_bw:1; + UINT32 operating_mode_notification:1; + UINT32 rsv63:1; +#endif // RT_BIG_ENDIAN // +}EXT_CAP_INFO_ELEMENT, *PEXT_CAP_INFO_ELEMENT; + + +/* 802.11n 7.3.2.61 */ +typedef struct GNU_PACKED _BSS_2040_COEXIST_ELEMENT{ + UCHAR ElementID; /* ID = IE_2040_BSS_COEXIST = 72 */ + UCHAR Len; + BSS_2040_COEXIST_IE BssCoexistIe; +}BSS_2040_COEXIST_ELEMENT, *PBSS_2040_COEXIST_ELEMENT; + + +/*802.11n 7.3.2.59 */ +typedef struct GNU_PACKED _BSS_2040_INTOLERANT_CH_REPORT{ + UCHAR ElementID; /* ID = IE_2040_BSS_INTOLERANT_REPORT = 73 */ + UCHAR Len; + UCHAR RegulatoryClass; + UCHAR ChList[0]; +}BSS_2040_INTOLERANT_CH_REPORT, *PBSS_2040_INTOLERANT_CH_REPORT; + + +/* The structure for channel switch annoucement IE. This is in 802.11n D3.03 */ +typedef struct GNU_PACKED _CHA_SWITCH_ANNOUNCE_IE{ + UCHAR SwitchMode; /*channel switch mode */ + UCHAR NewChannel; + UCHAR SwitchCount; +} CHA_SWITCH_ANNOUNCE_IE, *PCHA_SWITCH_ANNOUNCE_IE; + + +/* The structure for channel switch annoucement IE. This is in 802.11n D3.03 */ +typedef struct GNU_PACKED _SEC_CHA_OFFSET_IE{ + UCHAR SecondaryChannelOffset; /* 1: Secondary above, 3: Secondary below, 0: no Secondary */ +} SEC_CHA_OFFSET_IE, *PSEC_CHA_OFFSET_IE; + + +/* This structure is extracted from struct RT_HT_CAPABILITY and RT_VHT_CAP */ +typedef struct _RT_PHY_INFO{ + BOOLEAN bHtEnable; /* If we should use ht rate. */ + BOOLEAN bPreNHt; /* If we should use ht rate. */ + /*Substract from HT Capability IE */ + UCHAR MCSSet[16]; +#ifdef DOT11_VHT_AC + BOOLEAN bVhtEnable; + UCHAR vht_bw; + VHT_MCS_SET vht_mcs_set; +#endif /* DOT11_VHT_AC */ +} RT_PHY_INFO; + + +#ifdef DOT11_VHT_AC +typedef struct _RT_VHT_CAP{ + UINT32 vht_bw:2; + UINT32 vht_txstbc:1; + UINT32 vht_rxstbc:3; + UINT32 sgi_80m:1; + UINT32 vht_htc:1; + + UINT32 vht_mcs_ss1:2; + UINT32 vht_mcs_ss2:2; + UINT32 vht_rx_rate:2; + UINT32 vht_tx_rate:2; + + UINT32 rsv:16; +}RT_VHT_CAP; +#endif /* DOT11_VHT_AC */ + + +/* + This structure substracts ralink supports from all 802.11n-related features. + Features not listed here but contained in 802.11n spec are not supported in rt2860 +*/ +typedef struct { +#ifdef RT_BIG_ENDIAN + USHORT rsv:5; + USHORT AmsduSize:1; /* Max receiving A-MSDU size */ + USHORT AmsduEnable:1; /* Enable to transmit A-MSDU. Suggest disable. We should use A-MPDU to gain best benifit of 802.11n */ + USHORT RxSTBC:2; + USHORT TxSTBC:1; + USHORT ShortGIfor40:1; /*for40MHz */ + USHORT ShortGIfor20:1; + USHORT GF:1; /*green field */ + USHORT MimoPs:2;/*mimo power safe MMPS_ */ + USHORT ChannelWidth:1; +#else + USHORT ChannelWidth:1; + USHORT MimoPs:2;/*mimo power safe MMPS_ */ + USHORT GF:1; /*green field */ + USHORT ShortGIfor20:1; + USHORT ShortGIfor40:1; /*for 40MHz */ + USHORT TxSTBC:1; /* 0:not supported, 1:if supported */ + USHORT RxSTBC:2; /* 2 bits */ + USHORT AmsduEnable:1; /* Enable to transmit A-MSDU. Suggest disable. We should use A-MPDU to gain best benifit of 802.11n */ + USHORT AmsduSize:1; /* Max receiving A-MSDU size */ + USHORT rsv:5; +#endif + + /*Substract from Addiont HT INFO IE */ +#ifdef RT_BIG_ENDIAN + UCHAR RecomWidth:1; + UCHAR ExtChanOffset:2; /* Please not the difference with following UCHAR NewExtChannelOffset; from 802.11n */ + UCHAR MpduDensity:3; + UCHAR MaxRAmpduFactor:2; +#else + UCHAR MaxRAmpduFactor:2; + UCHAR MpduDensity:3; + UCHAR ExtChanOffset:2; /* Please not the difference with following UCHAR NewExtChannelOffset; from 802.11n */ + UCHAR RecomWidth:1; +#endif + +#ifdef RT_BIG_ENDIAN + USHORT rsv2:11; + USHORT OBSS_NonHTExist:1; + USHORT rsv3:1; + USHORT NonGfPresent:1; + USHORT OperaionMode:2; +#else + USHORT OperaionMode:2; + USHORT NonGfPresent:1; + USHORT rsv3:1; + USHORT OBSS_NonHTExist:1; + USHORT rsv2:11; +#endif + + /* New Extension Channel Offset IE */ + UCHAR NewExtChannelOffset; + /* Extension Capability IE = 127 */ + UCHAR BSSCoexist2040; +} RT_HT_CAPABILITY, *PRT_HT_CAPABILITY; + + +typedef struct GNU_PACKED _NEW_EXT_CHAN_IE{ + UCHAR NewExtChanOffset; +} NEW_EXT_CHAN_IE, *PNEW_EXT_CHAN_IE; + +typedef struct GNU_PACKED _FRAME_802_11 { + HEADER_802_11 Hdr; + UCHAR Octet[1]; +} FRAME_802_11, *PFRAME_802_11; + +/* QoSNull embedding of management action. When HT Control MA field set to 1. */ +typedef struct GNU_PACKED _MA_BODY { + UCHAR Category; + UCHAR Action; + UCHAR Octet[1]; +} MA_BODY, *PMA_BODY; + +typedef struct GNU_PACKED _HEADER_802_3 { + UCHAR DAAddr1[MAC_ADDR_LEN]; + UCHAR SAAddr2[MAC_ADDR_LEN]; + UCHAR Octet[2]; +} HEADER_802_3, *PHEADER_802_3; + + +/* Block ACK related format */ +/* 2-byte BA Parameter field in DELBA frames to terminate an already set up bA */ +typedef struct GNU_PACKED _DELBA_PARM{ +#ifdef RT_BIG_ENDIAN + USHORT TID:4; /* value of TC os TS */ + USHORT Initiator:1; /* 1: originator 0:recipient */ + USHORT Rsv:11; /* always set to 0 */ +#else + USHORT Rsv:11; /* always set to 0 */ + USHORT Initiator:1; /* 1: originator 0:recipient */ + USHORT TID:4; /* value of TC os TS */ +#endif /* RT_BIG_ENDIAN */ +} DELBA_PARM, *PDELBA_PARM; + +/* 2-byte BA Parameter Set field in ADDBA frames to signal parm for setting up a BA */ +typedef struct GNU_PACKED _BA_PARM{ +#ifdef RT_BIG_ENDIAN + USHORT BufSize:10; /* number of buffe of size 2304 octetsr */ + USHORT TID:4; /* value of TC os TS */ + USHORT BAPolicy:1; /* 1: immediately BA 0:delayed BA */ + USHORT AMSDUSupported:1; /* 0: not permitted 1: permitted */ +#else + USHORT AMSDUSupported:1; /* 0: not permitted 1: permitted */ + USHORT BAPolicy:1; /* 1: immediately BA 0:delayed BA */ + USHORT TID:4; /* value of TC os TS */ + USHORT BufSize:10; /* number of buffe of size 2304 octetsr */ +#endif /* RT_BIG_ENDIAN */ +} BA_PARM, *PBA_PARM; + +/* 2-byte BA Starting Seq CONTROL field */ +typedef union GNU_PACKED _BASEQ_CONTROL{ + struct GNU_PACKED { +#ifdef RT_BIG_ENDIAN + USHORT StartSeq:12; /* sequence number of the 1st MSDU for which this BAR is sent */ + USHORT FragNum:4; /* always set to 0 */ +#else + USHORT FragNum:4; /* always set to 0 */ + USHORT StartSeq:12; /* sequence number of the 1st MSDU for which this BAR is sent */ +#endif /* RT_BIG_ENDIAN */ + } field; + USHORT word; +} BASEQ_CONTROL, *PBASEQ_CONTROL; + +/*BAControl and BARControl are the same */ +/* 2-byte BA CONTROL field in BA frame */ +typedef struct GNU_PACKED _BA_CONTROL{ +#ifdef RT_BIG_ENDIAN + USHORT TID:4; + USHORT Rsv:9; + USHORT Compressed:1; + USHORT MTID:1; /*EWC V1.24 */ + USHORT ACKPolicy:1; /* only related to N-Delayed BA. But not support in RT2860b. 0:NormalACK 1:No ACK */ +#else + USHORT ACKPolicy:1; /* only related to N-Delayed BA. But not support in RT2860b. 0:NormalACK 1:No ACK */ + USHORT MTID:1; /*EWC V1.24 */ + USHORT Compressed:1; + USHORT Rsv:9; + USHORT TID:4; +#endif /* RT_BIG_ENDIAN */ +} BA_CONTROL, *PBA_CONTROL; + +/* 2-byte BAR CONTROL field in BAR frame */ +typedef struct GNU_PACKED _BAR_CONTROL{ +#ifdef RT_BIG_ENDIAN + USHORT TID:4; + USHORT Rsv1:9; + USHORT Compressed:1; + USHORT MTID:1; /*if this bit1, use FRAME_MTBA_REQ, if 0, use FRAME_BA_REQ */ + USHORT ACKPolicy:1; +#else + USHORT ACKPolicy:1; /* 0:normal ack, 1:no ack. */ + USHORT MTID:1; /*if this bit1, use FRAME_MTBA_REQ, if 0, use FRAME_BA_REQ */ + USHORT Compressed:1; + USHORT Rsv1:9; + USHORT TID:4; +#endif /* !RT_BIG_ENDIAN */ +} BAR_CONTROL, *PBAR_CONTROL; + +/* BARControl in MTBAR frame */ +typedef struct GNU_PACKED _MTBAR_CONTROL{ +#ifdef RT_BIG_ENDIAN + USHORT NumTID:4; + USHORT Rsv1:9; + USHORT Compressed:1; + USHORT MTID:1; + USHORT ACKPolicy:1; +#else + USHORT ACKPolicy:1; + USHORT MTID:1; + USHORT Compressed:1; + USHORT Rsv1:9; + USHORT NumTID:4; +#endif /* RT_BIG_ENDIAN */ +} MTBAR_CONTROL, *PMTBAR_CONTROL; + +typedef struct GNU_PACKED _PER_TID_INFO{ +#ifdef RT_BIG_ENDIAN + USHORT TID:4; + USHORT Rsv1:12; +#else + USHORT Rsv1:12; + USHORT TID:4; +#endif /* RT_BIG_ENDIAN */ +} PER_TID_INFO, *PPER_TID_INFO; + +typedef struct { + PER_TID_INFO PerTID; + BASEQ_CONTROL BAStartingSeq; +} EACH_TID, *PEACH_TID; + + +/* BAREQ AND MTBAREQ have the same subtype BAR, 802.11n BAR use compressed bitmap. */ +typedef struct GNU_PACKED _FRAME_BA_REQ { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + BAR_CONTROL BARControl; + BASEQ_CONTROL BAStartingSeq; +} FRAME_BA_REQ, *PFRAME_BA_REQ; + +typedef struct GNU_PACKED _FRAME_MTBA_REQ { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + MTBAR_CONTROL MTBARControl; + PER_TID_INFO PerTIDInfo; + BASEQ_CONTROL BAStartingSeq; +} FRAME_MTBA_REQ, *PFRAME_MTBA_REQ; + +/* Compressed format is mandantory in HT STA */ +typedef struct GNU_PACKED _FRAME_MTBA { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + BA_CONTROL BAControl; + BASEQ_CONTROL BAStartingSeq; + UCHAR BitMap[8]; +} FRAME_MTBA, *PFRAME_MTBA; + +typedef struct GNU_PACKED _FRAME_SMPS_ACTION { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + UCHAR smps; /* 7.3.1.22 */ +} FRAME_SMPS_ACTION; + +typedef struct GNU_PACKED _FRAME_ACTION_HDR { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; +} FRAME_ACTION_HDR, *PFRAME_ACTION_HDR; + +/*Action Frame */ +/*Action Frame Category:Spectrum, Action:Channel Switch. 7.3.2.20 */ +typedef struct GNU_PACKED _CHAN_SWITCH_ANNOUNCE { + UCHAR ElementID; /* ID = IE_CHANNEL_SWITCH_ANNOUNCEMENT = 37 */ + UCHAR Len; + CHA_SWITCH_ANNOUNCE_IE CSAnnounceIe; +} CHAN_SWITCH_ANNOUNCE, *PCHAN_SWITCH_ANNOUNCE; + + +/*802.11n : 7.3.2.20a */ +typedef struct GNU_PACKED _SECOND_CHAN_OFFSET { + UCHAR ElementID; /* ID = IE_SECONDARY_CH_OFFSET = 62 */ + UCHAR Len; + SEC_CHA_OFFSET_IE SecChOffsetIe; +} SECOND_CHAN_OFFSET, *PSECOND_CHAN_OFFSET; + + +typedef struct GNU_PACKED _FRAME_SPETRUM_CS { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + CHAN_SWITCH_ANNOUNCE CSAnnounce; + SECOND_CHAN_OFFSET SecondChannel; +} FRAME_SPETRUM_CS, *PFRAME_SPETRUM_CS; + + +typedef struct GNU_PACKED _FRAME_ADDBA_REQ { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + UCHAR Token; /* 1 */ + BA_PARM BaParm; /* 2 - 10 */ + USHORT TimeOutValue; /* 0 - 0 */ + BASEQ_CONTROL BaStartSeq; /* 0-0 */ +} FRAME_ADDBA_REQ, *PFRAME_ADDBA_REQ; + +typedef struct GNU_PACKED _FRAME_ADDBA_RSP { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + UCHAR Token; + USHORT StatusCode; + BA_PARM BaParm; /*0 - 2 */ + USHORT TimeOutValue; +} FRAME_ADDBA_RSP, *PFRAME_ADDBA_RSP; + +typedef struct GNU_PACKED _FRAME_DELBA_REQ { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + DELBA_PARM DelbaParm; + USHORT ReasonCode; +} FRAME_DELBA_REQ, *PFRAME_DELBA_REQ; + + +/*7.2.1.7 */ +typedef struct GNU_PACKED _FRAME_BAR { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + BAR_CONTROL BarControl; + BASEQ_CONTROL StartingSeq; +} FRAME_BAR, *PFRAME_BAR; + +/*7.2.1.7 */ +typedef struct GNU_PACKED _FRAME_BA { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + BAR_CONTROL BarControl; + BASEQ_CONTROL StartingSeq; + UCHAR bitmask[8]; +} FRAME_BA, *PFRAME_BA; + + +/* Radio Measuement Request Frame Format */ +typedef struct GNU_PACKED _FRAME_RM_REQ_ACTION { + HEADER_802_11 Hdr; + UCHAR Category; + UCHAR Action; + UCHAR Token; + USHORT Repetition; + UCHAR data[0]; +} FRAME_RM_REQ_ACTION, *PFRAME_RM_REQ_ACTION; + +typedef struct GNU_PACKED _HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE{ + UCHAR ID; + UCHAR Length; + UCHAR ChannelSwitchMode; + UCHAR NewRegClass; + UCHAR NewChannelNum; + UCHAR ChannelSwitchCount; +} HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE, *PHT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE; + + +/* */ +/* _Limit must be the 2**n - 1 */ +/* _SEQ1 , _SEQ2 must be within 0 ~ _Limit */ +/* */ +#define SEQ_STEPONE(_SEQ1, _SEQ2, _Limit) ((_SEQ1 == ((_SEQ2+1) & _Limit))) +#define SEQ_SMALLER(_SEQ1, _SEQ2, _Limit) (((_SEQ1-_SEQ2) & ((_Limit+1)>>1))) +#define SEQ_LARGER(_SEQ1, _SEQ2, _Limit) ((_SEQ1 != _SEQ2) && !(((_SEQ1-_SEQ2) & ((_Limit+1)>>1)))) +#define SEQ_WITHIN_WIN(_SEQ1, _SEQ2, _WIN, _Limit) (SEQ_LARGER(_SEQ1, _SEQ2, _Limit) && \ + SEQ_SMALLER(_SEQ1, ((_SEQ2+_WIN+1)&_Limit), _Limit)) + +/* + Contention-free parameter (without ID and Length) +*/ +typedef struct GNU_PACKED _CF_PARM{ + BOOLEAN bValid; /* 1: variable contains valid value */ + UCHAR CfpCount; + UCHAR CfpPeriod; + USHORT CfpMaxDuration; + USHORT CfpDurRemaining; +} CF_PARM, *PCF_PARM; + + +typedef struct _CIPHER_SUITE { + NDIS_802_11_ENCRYPTION_STATUS PairCipher; /* Unicast cipher 1, this one has more secured cipher suite */ + NDIS_802_11_ENCRYPTION_STATUS PairCipherAux; /* Unicast cipher 2 if AP announce two unicast cipher suite */ + NDIS_802_11_ENCRYPTION_STATUS GroupCipher; /* Group cipher */ + USHORT RsnCapability; /* RSN capability from beacon */ + BOOLEAN bMixMode; /* Indicate Pair & Group cipher might be different */ +} CIPHER_SUITE, *PCIPHER_SUITE; + +struct GNU_PACKED map_vendor_ie +{ + UCHAR type; + UCHAR subtype; + UCHAR root_distance; + UCHAR connectivity_to_controller; + USHORT uplink_rate; + UCHAR uplink_bssid[MAC_ADDR_LEN]; + UCHAR bssid_5g[MAC_ADDR_LEN]; + UCHAR bssid_2g[MAC_ADDR_LEN]; +}; + +#if defined(MWDS) || defined(WH_EVENT_NOTIFIER) || defined(WH_EZ_SETUP) || defined(MAP_SUPPORT) +struct _vendor_ie_cap { + ULONG ra_cap; + ULONG mtk_cap; + ULONG brcm_cap; + ULONG quant_cap; + BOOLEAN ldpc; + BOOLEAN sgi; + BOOLEAN is_rlt; + BOOLEAN is_mtk; + BOOLEAN is_quant; +#ifdef WH_EZ_SETUP + UINT ez_capability; +#ifdef NEW_CONNECTION_ALGO + UCHAR open_group_id[OPEN_GROUP_MAX_LEN]; + UCHAR open_group_id_len; + beacon_info_tag_t beacon_info; + BOOLEAN non_ez_beacon; +#endif + BOOLEAN support_easy_setup; +#endif /* WH_EZ_SETUP */ +#ifdef MWDS + BOOLEAN mtk_cap_found; + BOOLEAN support_mwds; +#endif /* MWDS */ +#ifdef WH_EVENT_NOTIFIER + UCHAR custom_ie_len; + UCHAR custom_ie[CUSTOM_IE_TOTAL_LEN]; +#endif /* WH_EVENT_NOTIFIER */ +}; +#endif + +/* EDCA configuration from AP's BEACON/ProbeRsp */ +#define WMM_AC_BK 0 +#define WMM_AC_BE 1 +#define WMM_AC_VI 2 +#define WMM_AC_VO 3 +typedef struct { + BOOLEAN bValid; /* 1: variable contains valid value */ + BOOLEAN bAdd; /* 1: variable contains valid value */ + BOOLEAN bQAck; + BOOLEAN bQueueRequest; + BOOLEAN bTxopRequest; + BOOLEAN bAPSDCapable; +/* BOOLEAN bMoreDataAck; */ + UCHAR EdcaUpdateCount; + UCHAR Aifsn[4]; /* 0:AC_BK, 1:AC_BE, 2:AC_VI, 3:AC_VO */ + UCHAR Cwmin[4]; + UCHAR Cwmax[4]; + USHORT Txop[4]; /* in unit of 32-us */ + BOOLEAN bACM[4]; /* 1: Admission Control of AC_BK is mandattory */ +} EDCA_PARM, *PEDCA_PARM; + + +/* QBSS LOAD information from QAP's BEACON/ProbeRsp */ +typedef struct { + BOOLEAN bValid; /* 1: variable contains valid value */ + USHORT StaNum; + UCHAR ChannelUtilization; + USHORT RemainingAdmissionControl; /* in unit of 32-us */ +} QBSS_LOAD_PARM, *PQBSS_LOAD_PARM; + + +/* QBSS Info field in QSTA's assoc req */ +typedef struct GNU_PACKED _QBSS_STA_INFO_PARM{ +#ifdef RT_BIG_ENDIAN + UCHAR Rsv2:1; + UCHAR MaxSPLength:2; + UCHAR Rsv1:1; + UCHAR UAPSD_AC_BE:1; + UCHAR UAPSD_AC_BK:1; + UCHAR UAPSD_AC_VI:1; + UCHAR UAPSD_AC_VO:1; +#else + UCHAR UAPSD_AC_VO:1; + UCHAR UAPSD_AC_VI:1; + UCHAR UAPSD_AC_BK:1; + UCHAR UAPSD_AC_BE:1; + UCHAR Rsv1:1; + UCHAR MaxSPLength:2; + UCHAR Rsv2:1; +#endif /* RT_BIG_ENDIAN */ +} QBSS_STA_INFO_PARM, *PQBSS_STA_INFO_PARM; + +typedef struct { + QBSS_STA_INFO_PARM QosInfo; + UCHAR Rsv; + UCHAR Q_AC_BE[4]; + UCHAR Q_AC_BK[4]; + UCHAR Q_AC_VI[4]; + UCHAR Q_AC_VO[4]; +} QBSS_STA_EDCA_PARM, *PQBSS_STA_EDCA_PARM; + +/* QBSS Info field in QAP's Beacon/ProbeRsp */ +typedef struct GNU_PACKED _QBSS_AP_INFO_PARM{ +#ifdef RT_BIG_ENDIAN + UCHAR UAPSD:1; + UCHAR Rsv:3; + UCHAR ParamSetCount:4; +#else + UCHAR ParamSetCount:4; + UCHAR Rsv:3; + UCHAR UAPSD:1; +#endif /* RT_BIG_ENDIAN */ +} QBSS_AP_INFO_PARM, *PQBSS_AP_INFO_PARM; + +/* QOS Capability reported in QAP's BEACON/ProbeRsp */ +/* QOS Capability sent out in QSTA's AssociateReq/ReAssociateReq */ +typedef struct { + BOOLEAN bValid; /* 1: variable contains valid value */ + BOOLEAN bQAck; + BOOLEAN bQueueRequest; + BOOLEAN bTxopRequest; +/* BOOLEAN bMoreDataAck; */ + UCHAR EdcaUpdateCount; +} QOS_CAPABILITY_PARM, *PQOS_CAPABILITY_PARM; + + + +typedef struct _BSS_ENTRY{ + UCHAR MacAddr[MAC_ADDR_LEN]; + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR Channel; + UCHAR CentralChannel; /*Store the wide-band central channel for 40MHz. .used in 40MHz AP. Or this is the same as Channel. */ + ULONG ClientStatusFlags; + UCHAR BssType; + USHORT AtimWin; + USHORT BeaconPeriod; + + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRateLen; + UCHAR Erp; + HT_CAPABILITY_IE HtCapability; + UCHAR HtCapabilityLen; + ADD_HT_INFO_IE AddHtInfo; /* AP might use this additional ht info IE */ + UCHAR AddHtInfoLen; + EXT_CAP_INFO_ELEMENT ExtCapInfo; /* this is the extened capibility IE appreed in MGMT frames. Doesn't need to update once set in Init. */ + UCHAR NewExtChanOffset; + CHAR Rssi; +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + UCHAR Snr0; + UCHAR Snr1; +#endif + +#ifdef DOT11_VHT_AC + UCHAR vht_cap_len; + UCHAR vht_op_len; + VHT_CAP_IE vht_cap_ie; + VHT_OP_IE vht_op_ie; +#endif /* DOT11_VHT_AC */ + + + CHAR MinSNR; + UCHAR Privacy; /* Indicate security function ON/OFF. Don't mess up with auth mode. */ + UCHAR Hidden; + BOOLEAN FromBcnReport; + USHORT DtimPeriod; + USHORT CapabilityInfo; + + USHORT CfpCount; + USHORT CfpPeriod; + USHORT CfpMaxDuration; + USHORT CfpDurRemaining; + UCHAR SsidLen; + CHAR Ssid[MAX_LEN_OF_SSID]; + + UCHAR SameRxTimeCount; + ULONG LastBeaconRxTimeA; /* OS's timestamp */ + ULONG LastBeaconRxTime; /* OS's timestamp */ + + BOOLEAN bSES; + + /* New for WPA2 */ + CIPHER_SUITE WPA; /* AP announced WPA cipher suite */ + CIPHER_SUITE WPA2; /* AP announced WPA2 cipher suite */ +#ifdef WAPI_SUPPORT + CIPHER_SUITE WAPI; /* AP announced WAPI cipher suite */ +#endif /* WAPI_SUPPORT */ + + /* New for microsoft WPA support */ + NDIS_802_11_FIXED_IEs FixIEs; + NDIS_802_11_AUTHENTICATION_MODE AuthModeAux; /* Addition mode for WPA2 / WPA capable AP */ + NDIS_802_11_AUTHENTICATION_MODE AuthMode; + NDIS_802_11_WEP_STATUS WepStatus; /* Unicast Encryption Algorithm extract from VAR_IE */ + USHORT VarIELen; /* Length of next VIE include EID & Length */ + UCHAR VarIEs[MAX_VIE_LEN]; + USHORT VarIeFromProbeRspLen; + UCHAR *pVarIeFromProbRsp; +#ifdef DOT11W_PMF_SUPPORT + BOOLEAN IsSupportSHA256KeyDerivation; +#endif /* DOT11W_PMF_SUPPORT */ + + /* CCX Ckip information */ + UCHAR CkipFlag; + + /* CCX 2 TSF */ + UCHAR PTSF[4]; /* Parent TSF */ + UCHAR TTSF[8]; /* Target TSF */ + + /* 802.11e d9, and WMM */ + EDCA_PARM EdcaParm; + QOS_CAPABILITY_PARM QosCapability; + QBSS_LOAD_PARM QbssLoad; + +#ifdef WSC_INCLUDED + UCHAR WpsAP; /* 0x00: not support WPS, 0x01: support normal WPS, 0x02: support Ralink auto WPS, 0x04: support WAC AP */ + USHORT WscDPIDFromWpsAP; +#endif /* WSC_INCLUDED */ + +#if defined(DOT11R_FT_SUPPORT) || defined(DOT11K_RRM_SUPPORT) + BOOLEAN bHasMDIE; + FT_MDIE FT_MDIE; +#endif /* DOT11R_FT_SUPPORT || DOT11K_RRM_SUPPORT */ + + + +#ifdef WH_EZ_SETUP + unsigned char support_easy_setup; + unsigned int easy_setup_capability; + BOOLEAN bConnectAttemptFailed; + BOOLEAN non_ez_beacon; +#ifdef NEW_CONNECTION_ALGO + UCHAR open_group_id[OPEN_GROUP_MAX_LEN]; + UCHAR open_group_id_len; + beacon_info_tag_t beacon_info; +#endif +#endif /* WH_EZ_SETUP */ + +#ifdef DOT11K_RRM_SUPPORT + UINT8 RegulatoryClass; + UINT8 CondensedPhyType; + UINT8 RSNI; +#endif /* DOT11K_RRM_SUPPORT */ +#ifdef MWDS + BOOLEAN bSupportMWDS; /* Determine If own MWDS capability */ +#endif /* DOT11K_RRM_SUPPORT */ +#ifdef CONFIG_OWE_SUPPORT + /* it can find a pairing OWE bss, + * hide this OPEN bss, + * skip to show it in scan result and skip to connect to it. + */ + BOOLEAN hide_owe_bss; + BOOLEAN bhas_owe_trans_ie; + + UCHAR owe_trans_ie[MAX_VIE_LEN]; + USHORT owe_trans_ie_len; + +#endif /*CONFIG_OWE_SUPPORT*/ + +} BSS_ENTRY; + +#ifdef NEIGHBORING_AP_STAT +#define OID_CUST_SCAN_DONE_EVENT 0x2001 +#define OID_CUST_SCAN_REPORT_GET 0x2002 +#define MAX_COUNT_OF_BSS_ENTRIES 128 + +INT ReportScanResult(IN void *pAdSrc, IN PRTMP_IOCTL_INPUT_STRUCT wrq); + +/* Each customer scan result item */ +typedef struct { + CHAR ssid[MAX_LEN_OF_SSID]; + UCHAR macAddr[MAC_ADDR_LEN]; + SHORT noise; + USHORT beaconPeriod; + USHORT dtimPeriod; + UCHAR channel; + UCHAR basicRate[MAX_LENGTH_OF_SUPPORT_RATES]; + UCHAR suppoRate[MAX_LENGTH_OF_SUPPORT_RATES]; +} SCAN_RPT_ITEM; + +/* All customer scan result entry*/ +typedef struct { + USHORT cnt; /* current available item count */ + SCAN_RPT_ITEM items[MAX_COUNT_OF_BSS_ENTRIES]; +} CUSTOM_SCAN_RESULT; +#endif + +typedef struct { + UCHAR BssNr; + UCHAR BssOverlapNr; + BSS_ENTRY BssEntry[MAX_LEN_OF_BSS_TABLE]; +#ifdef NEIGHBORING_AP_STAT + CUSTOM_SCAN_RESULT ScanResult; +#endif +} BSS_TABLE, *PBSS_TABLE; + + +struct raw_rssi_info{ + CHAR raw_rssi[3]; + UCHAR raw_snr; +}; + +typedef struct _MLME_QUEUE_ELEM { + UCHAR Msg[MGMT_DMA_BUFFER_SIZE]; /* move here to fix alignment issue for ARM CPU */ + ULONG Machine; + ULONG MsgType; + ULONG MsgLen; + LARGE_INTEGER TimeStamp; + struct raw_rssi_info rssi_info; +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + UCHAR Snr0; + UCHAR Snr1; +#endif + UCHAR Signal; + UCHAR Channel; + UCHAR Wcid; + BOOLEAN Occupied; + UCHAR OpMode; + ULONG Priv; +} MLME_QUEUE_ELEM, *PMLME_QUEUE_ELEM; + +#ifdef WH_EZ_SETUP +#define IMM_DISCONNECT (BIT(15)) + /* If this bit is set in 'Priv' of MLME_QUEUE_ELEM, during disconenct request to MLME, + the request will be processed immediately*/ +#endif + +#ifdef EAPOL_QUEUE_SUPPORT +typedef struct _EAP_MLME_QUEUE { + ULONG Num; + ULONG Head; + ULONG Tail; + NDIS_SPIN_LOCK Lock; + MLME_QUEUE_ELEM Entry[MAX_LEN_OF_EAP_QUEUE]; +} EAP_MLME_QUEUE, *PEAP_MLME_QUEUE; +#endif /* EAPOL_QUEUE_SUPPORT */ + +typedef struct _MLME_QUEUE { + ULONG Num; + ULONG Head; + ULONG Tail; + NDIS_SPIN_LOCK Lock; + MLME_QUEUE_ELEM Entry[MAX_LEN_OF_MLME_QUEUE]; +} MLME_QUEUE, *PMLME_QUEUE; + +typedef VOID (*STATE_MACHINE_FUNC)(VOID *pAd, MLME_QUEUE_ELEM *Elem); + +typedef struct _STATE_MACHINE { + ULONG Base; + ULONG NrState; + ULONG NrMsg; + ULONG CurrState; + STATE_MACHINE_FUNC *TransFunc; +} STATE_MACHINE, *PSTATE_MACHINE; + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +typedef VOID (*APCLI_STATE_MACHINE_FUNC)(VOID *pAd, MLME_QUEUE_ELEM *Elem, PULONG pCurrState, USHORT ifIndex); + +typedef struct _STA_STATE_MACHINE { + ULONG Base; + ULONG NrState; + ULONG NrMsg; + ULONG CurrState; + APCLI_STATE_MACHINE_FUNC *TransFunc; +} APCLI_STATE_MACHINE, *PSTA_STATE_MACHINE; +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +/* MLME AUX data structure that hold temporarliy settings during a connection attempt. */ +/* Once this attemp succeeds, all settings will be copy to pAd->StaActive. */ +/* A connection attempt (user set OID, roaming, CCX fast roaming,..) consists of */ +/* several steps (JOIN, AUTH, ASSOC or REASSOC) and may fail at any step. We purposely */ +/* separate this under-trial settings away from pAd->StaActive so that once */ +/* this new attempt failed, driver can auto-recover back to the active settings. */ +typedef struct _MLME_AUX { + UCHAR BssType; + UCHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR AutoReconnectSsid[MAX_LEN_OF_SSID]; + UCHAR AutoReconnectSsidLen; + USHORT Alg; + UCHAR ScanType; + UCHAR Channel; + + UCHAR DtimPeriod; + UCHAR CentralChannel; + UCHAR InfraChannel; + USHORT Aid; + USHORT CapabilityInfo; + USHORT BeaconPeriod; + USHORT CfpMaxDuration; + USHORT CfpPeriod; + USHORT AtimWin; + + /* Copy supported rate from desired AP's beacon. We are trying to match */ + /* AP's supported and extended rate settings. */ + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRateLen; + HT_CAPABILITY_IE HtCapability; + UCHAR HtCapabilityLen; + ADD_HT_INFO_IE AddHtInfo; /* AP might use this additional ht info IE */ + EXT_CAP_INFO_ELEMENT ExtCapInfo; /* this is the extened capibility IE appreed in MGMT frames. Doesn't need to update once set in Init. */ + UCHAR NewExtChannelOffset; + /*RT_HT_CAPABILITY SupportedHtPhy; */ + +#ifdef DOT11_VHT_AC + UCHAR vht_cap_len; + UCHAR vht_op_len; + VHT_CAP_IE vht_cap; + VHT_OP_IE vht_op; + UCHAR vht_cent_ch; +#endif /* DOT11_VHT_AC */ + + /* new for QOS */ + QOS_CAPABILITY_PARM APQosCapability; /* QOS capability of the current associated AP */ + EDCA_PARM APEdcaParm; /* EDCA parameters of the current associated AP */ + QBSS_LOAD_PARM APQbssLoad; /* QBSS load of the current associated AP */ + + /* new to keep Ralink specific feature */ + ULONG APRalinkIe; + + BSS_TABLE SsidBssTab; /* AP list for the same SSID */ + BSS_TABLE RoamTab; /* AP list eligible for roaming */ + ULONG BssIdx; + ULONG RoamIdx; + BOOLEAN CurrReqIsFromNdis; + + RALINK_TIMER_STRUCT BeaconTimer, ScanTimer; + 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; +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef DOT11W_PMF_SUPPORT + RSN_CAPABILITIES RsnCap; + BOOLEAN IsSupportSHA256KeyDerivation; +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef WH_EZ_SETUP + BOOLEAN support_easy_setup; + UINT8 attempted_candidate_index; /* with respect to entries in SsidBssTab*/ +#endif /* WH_EZ_SETUP */ +#ifdef MWDS + BOOLEAN bSupportMWDS; /* Determine If own MWDS capability */ +#endif /* MWDS */ +#ifdef APCLI_OWE_SUPPORT + BSS_TABLE owe_bss_tab; /* AP list for the same SSID */ +#endif +} MLME_AUX, *PMLME_AUX; + + +#ifdef DOT11_N_SUPPORT +/* StaActive.SupportedHtPhy.MCSSet is copied from AP beacon. Don't need to update here. */ +#define COPY_HTSETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd) \ +{ \ + _pAd->StaActive.SupportedHtPhy.ChannelWidth = _pAd->MlmeAux.HtCapability.HtCapInfo.ChannelWidth; \ + _pAd->StaActive.SupportedHtPhy.MimoPs = _pAd->MlmeAux.HtCapability.HtCapInfo.MimoPs; \ + _pAd->StaActive.SupportedHtPhy.GF = _pAd->MlmeAux.HtCapability.HtCapInfo.GF; \ + _pAd->StaActive.SupportedHtPhy.ShortGIfor20 = _pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor20; \ + _pAd->StaActive.SupportedHtPhy.ShortGIfor40 = _pAd->MlmeAux.HtCapability.HtCapInfo.ShortGIfor40; \ + _pAd->StaActive.SupportedHtPhy.TxSTBC = _pAd->MlmeAux.HtCapability.HtCapInfo.TxSTBC; \ + _pAd->StaActive.SupportedHtPhy.RxSTBC = _pAd->MlmeAux.HtCapability.HtCapInfo.RxSTBC; \ + _pAd->StaActive.SupportedHtPhy.ExtChanOffset = _pAd->MlmeAux.AddHtInfo.AddHtInfo.ExtChanOffset; \ + _pAd->StaActive.SupportedHtPhy.RecomWidth = _pAd->MlmeAux.AddHtInfo.AddHtInfo.RecomWidth; \ + _pAd->StaActive.SupportedHtPhy.OperaionMode = _pAd->MlmeAux.AddHtInfo.AddHtInfo2.OperaionMode; \ + _pAd->StaActive.SupportedHtPhy.NonGfPresent = _pAd->MlmeAux.AddHtInfo.AddHtInfo2.NonGfPresent; \ + NdisMoveMemory((_pAd)->MacTab.Content[BSSID_WCID].HTCapability.MCSSet, (_pAd)->StaActive.SupportedPhyInfo.MCSSet, sizeof(UCHAR) * 16);\ +} + +#define COPY_AP_HTSETTINGS_FROM_BEACON(_pAd, _pHtCapability) \ +{ \ + _pAd->MacTab.Content[BSSID_WCID].AMsduSize = (UCHAR)(_pHtCapability->HtCapInfo.AMsduSize); \ + _pAd->MacTab.Content[BSSID_WCID].MmpsMode= (UCHAR)(_pHtCapability->HtCapInfo.MimoPs); \ + _pAd->MacTab.Content[BSSID_WCID].MaxRAmpduFactor = (UCHAR)(_pHtCapability->HtCapParm.MaxRAmpduFactor); \ +} +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC +#define COPY_VHT_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd) \ +{ \ +} +#endif /* DOT11_VHT_AC */ + + +typedef struct _MLME_ADDBA_REQ_STRUCT{ + UCHAR Wcid; + UCHAR pAddr[MAC_ADDR_LEN]; + UCHAR BaBufSize; + USHORT TimeOutValue; + UCHAR TID; + UCHAR Token; + USHORT BaStartSeq; +} MLME_ADDBA_REQ_STRUCT, *PMLME_ADDBA_REQ_STRUCT; + + +typedef struct _MLME_DELBA_REQ_STRUCT{ + UCHAR Wcid; /* */ + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR TID; + UCHAR Initiator; +} MLME_DELBA_REQ_STRUCT, *PMLME_DELBA_REQ_STRUCT; + +/* assoc struct is equal to reassoc */ +typedef struct _MLME_ASSOC_REQ_STRUCT{ + UCHAR Addr[MAC_ADDR_LEN]; + USHORT CapabilityInfo; + USHORT ListenIntv; + ULONG Timeout; +} MLME_ASSOC_REQ_STRUCT, *PMLME_ASSOC_REQ_STRUCT, MLME_REASSOC_REQ_STRUCT, *PMLME_REASSOC_REQ_STRUCT; + +typedef struct _MLME_DISASSOC_REQ_STRUCT{ + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Reason; +} MLME_DISASSOC_REQ_STRUCT, *PMLME_DISASSOC_REQ_STRUCT; + +typedef struct _MLME_AUTH_REQ_STRUCT { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Alg; + ULONG Timeout; +#ifdef MAC_REPEATER_SUPPORT + UCHAR BssIdx; + UCHAR CliIdx; +#endif /* MAC_REPEATER_SUPPORT */ +} MLME_AUTH_REQ_STRUCT, *PMLME_AUTH_REQ_STRUCT; + +typedef struct _MLME_DEAUTH_REQ_STRUCT { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Reason; +} MLME_DEAUTH_REQ_STRUCT, *PMLME_DEAUTH_REQ_STRUCT; + +typedef struct _MLME_BROADCAST_DEAUTH_REQ_STRUCT { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Reason; + struct wifi_dev *wdev; +} MLME_BROADCAST_DEAUTH_REQ_STRUCT, *PMLME_BROADCAST_DEAUTH_REQ_STRUCT; + +typedef struct { + ULONG BssIdx; +} MLME_JOIN_REQ_STRUCT; + +typedef struct _MLME_SCAN_REQ_STRUCT { + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR BssType; + UCHAR ScanType; + UCHAR SsidLen; + CHAR Ssid[MAX_LEN_OF_SSID]; +#ifdef CONFIG_AP_SUPPORT +#endif +} MLME_SCAN_REQ_STRUCT, *PMLME_SCAN_REQ_STRUCT; + +typedef struct _MLME_START_REQ_STRUCT { + CHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; +} MLME_START_REQ_STRUCT, *PMLME_START_REQ_STRUCT; + + +typedef struct GNU_PACKED _EID_STRUCT{ + UCHAR Eid; + UCHAR Len; + UCHAR Octet[1]; +} EID_STRUCT,*PEID_STRUCT, BEACON_EID_STRUCT, *PBEACON_EID_STRUCT; + + +/* ========================== AP mlme.h =============================== */ +#define TBTT_PRELOAD_TIME 384 /* usec. LomgPreamble + 24-byte at 1Mbps */ +#define DEFAULT_DTIM_PERIOD 1 + +/* weighting factor to calculate Channel quality, total should be 100% */ +/*#define RSSI_WEIGHTING 0 */ +/*#define TX_WEIGHTING 40 */ +/*#define RX_WEIGHTING 60 */ + +#define MAC_TABLE_AGEOUT_TIME 300 /* unit: sec */ +#define MAC_TABLE_MIN_AGEOUT_TIME 60 /* unit: sec */ +#define MAC_TABLE_ASSOC_TIMEOUT 5 /* unit: sec */ +#define MAC_TABLE_FULL(Tab) ((Tab).size == MAX_LEN_OF_MAC_TABLE) + +/* AP shall drop the sta if contine Tx fail count reach it. */ +#define MAC_ENTRY_LIFE_CHECK_CNT 1024 /* packet cnt. */ + +/* Value domain of pMacEntry->Sst */ +typedef enum _Sst { + SST_NOT_AUTH, /* 0: equivalent to IEEE 802.11/1999 state 1 */ + SST_AUTH, /* 1: equivalent to IEEE 802.11/1999 state 2 */ + SST_ASSOC /* 2: equivalent to IEEE 802.11/1999 state 3 */ +} SST; + +/* value domain of pMacEntry->AuthState */ +typedef enum _AuthState { + AS_NOT_AUTH, + AS_AUTH_OPEN, /* STA has been authenticated using OPEN SYSTEM */ + AS_AUTH_KEY, /* STA has been authenticated using SHARED KEY */ + AS_AUTHENTICATING /* STA is waiting for AUTH seq#3 using SHARED KEY */ +} AUTH_STATE; + + +typedef struct _IE_lists { + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + UCHAR ApAddr[MAC_ADDR_LEN]; + USHORT CapabilityInfo; + USHORT ListenInterval; + UCHAR SsidLen; + UCHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SupportedRatesLen; + UCHAR SupportedRates[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; + UCHAR RSNIE_Len; + BOOLEAN bWmmCapable; +#ifdef WSC_AP_SUPPORT + BOOLEAN bWscCapable; +#endif /* WSC_AP_SUPPORT */ +#if defined(MWDS) || defined(WH_EVENT_NOTIFIER) || defined(MAP_SUPPORT) + struct _vendor_ie_cap vendor_ie; +#endif + ULONG RalinkIe; + EXT_CAP_INFO_ELEMENT ExtCapInfo; +#ifdef DOT11R_FT_SUPPORT + FT_INFO FtInfo; +#endif /* DOT11R_FT_SUPPORT */ +#ifdef DOT11K_RRM_SUPPORT + RRM_EN_CAP_IE RrmEnCap; +#endif /* DOT11K_RRM_SUPPORT */ + UCHAR ht_cap_len; + HT_CAPABILITY_IE HTCapability; +#ifdef DOT11_VHT_AC + VHT_CAP_IE vht_cap; + VHT_OP_IE vht_op; + UCHAR vht_cap_len; + UCHAR vht_op_len; + UCHAR operating_mode_len; + OPERATING_MODE operating_mode; +#endif /* DOT11_VHT_AC */ +#ifdef CONFIG_OWE_SUPPORT + EXT_ECDH_PARAMETER_IE ecdh_ie; +#endif /*CONFIG_OWE_SUPPORT*/ +}IE_LISTS; + + +typedef struct _bcn_ie_list { + UCHAR Addr2[MAC_ADDR_LEN]; + UCHAR Bssid[MAC_ADDR_LEN]; + CHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; + UCHAR BssType; + USHORT BeaconPeriod; + UCHAR Channel; + UCHAR NewChannel; + USHORT AtimWin; + USHORT CapabilityInfo; + UCHAR Erp; + UCHAR DtimCount; + UCHAR DtimPeriod; + UCHAR BcastFlag; + UCHAR MessageToMe; + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRateLen; + UCHAR CkipFlag; + UCHAR AironetCellPowerLimit; + LARGE_INTEGER TimeStamp; + CF_PARM CfParm; + EDCA_PARM EdcaParm; + QBSS_LOAD_PARM QbssLoad; + QOS_CAPABILITY_PARM QosCapability; +#if defined(WH_EZ_SETUP) || defined(MWDS) || defined(MAP_SUPPORT) + struct _vendor_ie_cap vendor_ie; +#endif //WH_EZ_SETUP + ULONG RalinkIe; + EXT_CAP_INFO_ELEMENT ExtCapInfo; + UCHAR HtCapabilityLen; + UCHAR PreNHtCapabilityLen; + HT_CAPABILITY_IE HtCapability; + UCHAR AddHtInfoLen; + ADD_HT_INFO_IE AddHtInfo; + UCHAR NewExtChannelOffset; +#ifdef DOT11_VHT_AC + VHT_CAP_IE vht_cap_ie; + VHT_OP_IE vht_op_ie; + UCHAR vht_cap_len; + UCHAR vht_op_len; +#endif /* DOT11_VHT_AC */ + BOOLEAN FromBcnReport; +}BCN_IE_LIST; + +#define RTMP_MLME_HANDLER(pAd) RtmpMLMEUp(&((pAd)->mlmeTask)) + +#define ACTION_QOSMAP_CONFIG 4 + +typedef struct _QOSMAP_SET { + UCHAR DSCP_Field_Len; + USHORT DSCP_Field[29]; /* Use to time out while slience, unit: second , set by UI */ +} QOSMAP_SET, *PQOSMAP_SET; + +typedef struct _MLME_QOS_ACTION_STRUCT{ + UCHAR ActionField; + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR apidx; + QOSMAP_SET QOSMap; +} MLME_QOS_ACTION_STRUCT, *PMLME_QOS_ACTION_STRUCT; + +#endif /* MLME_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mlme_sys.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mlme_sys.h new file mode 100644 index 000000000..f36fabaaf --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mlme_sys.h @@ -0,0 +1,9 @@ +/* + +*/ + + +#include "rtmp_type.h" + + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mt_io.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mt_io.h new file mode 100644 index 000000000..9938e6f45 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mt_io.h @@ -0,0 +1,22 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of MediaTek. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + mt_io.h +*/ + +#ifndef __MT_WIFI_IO_H__ +#define __MT_WIFI_IO_H__ + +UINT32 mt_physical_addr_map(UINT32 addr); +BOOLEAN mt_mac_cr_range_mapping(UINT32 *mac_addr); +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mt_ps.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mt_ps.h new file mode 100644 index 000000000..6e4223c3f --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mt_ps.h @@ -0,0 +1,57 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of MediaTek. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + mt_io.h +*/ + +#ifndef __MT_PS_H__ +#define __MT_PS_H__ + +VOID MtHandleRxPsPoll(RTMP_ADAPTER *pAd, UCHAR *pAddr, USHORT wcid, BOOLEAN isActive); +BOOLEAN MtPsIndicate(RTMP_ADAPTER *pAd, UCHAR *pAddr, UCHAR wcid, UCHAR Psm); + +#ifdef MT_PS +VOID MtPsRedirectDisableCheck(RTMP_ADAPTER *pAd, UCHAR wcid); +VOID MtPsSendToken(RTMP_ADAPTER *pAd, UINT32 WlanIdx); +VOID MtSetIgnorePsm(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, UCHAR value); +VOID CheckSkipTX(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry); +void MtEnqTxSwqFromPsQueue(RTMP_ADAPTER *pAd, UCHAR qidx, STA_TR_ENTRY *tr_entry); + +#ifdef RTMP_PCI_SUPPORT +#define MT_SET_IGNORE_PSM(__pAd, __pEntry, __value) \ + MtSetIgnorePsm(__pAd, __pEntry, __value) +#endif /* RTMP_PCI_SUPPORT */ + +#if defined(RTMP_USB_SUPPORT) || defined(RTMP_SDIO_SUPPORT) +#define MT_SET_IGNORE_PSM(__pAd, __pEntry, __value) \ +{ \ + UCHAR *__pData = NULL; \ + UCHAR __ps_en = __value; \ + os_alloc_mem(NULL, (UCHAR **)&__pData, sizeof(UCHAR)+sizeof(MAC_TABLE_ENTRY)); \ + if (__pData) \ + { \ + NdisMoveMemory(__pData , &__ps_en, sizeof(UCHAR)); \ + NdisMoveMemory(__pData+sizeof(UCHAR) , __pEntry, sizeof(MAC_TABLE_ENTRY)); \ + RTEnqueueInternalCmd(__pAd, CMDTHREAD_PS_IGNORE_PSM_SET, __pData, sizeof(UCHAR)+sizeof(MAC_TABLE_ENTRY)); \ + os_free_mem(NULL, __pData); \ + } \ + else \ + { \ + DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("%s(%d): os_alloc_mem fail.\n", __FUNCTION__, __LINE__)); \ + } \ +} +#endif /* defined(RTMP_USB_SUPPORT) || defined(RTMP_SDIO_SUPPORT) */ +#endif /* MT_PS */ + +#endif + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mt_tx_pwr.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mt_tx_pwr.h new file mode 100644 index 000000000..e1793561b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mt_tx_pwr.h @@ -0,0 +1,59 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of MediaTek. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + mt_tx_pwr.h +*/ +#ifndef __MT_TX_PWR_H__ +#define __MT_TX_PWR_H__ + +struct MT_TX_PWR_CAP { +#define INTERNAL_PA 0 +#define EXTERNAL_PA 1 + UINT8 pa_type; +#define TSSI_TRIGGER_STAGE 0 +#define TSSI_COMP_STAGE 1 +#define TSSI_CAL_STAGE 2 + UINT8 tssi_stage; +#define TSSI_0_SLOPE_G_BAND_DEFAULT_VALUE 0x84 +#define TSSI_1_SLOPE_G_BAND_DEFAULT_VALUE 0x83 + UINT8 tssi_0_slope_g_band; + UINT8 tssi_1_slope_g_band; +#define TSSI_0_OFFSET_G_BAND_DEFAULT_VALUE 0x0A +#define TSSI_1_OFFSET_G_BAND_DEFAULT_VALUE 0x0B + UINT8 tssi_0_offset_g_band; + UINT8 tssi_1_offset_g_band; +#define TX_TARGET_PWR_DEFAULT_VALUE 0x26 + CHAR tx_0_target_pwr_g_band; + CHAR tx_1_target_pwr_g_band; + CHAR tx_0_chl_pwr_delta_g_band[3]; + CHAR tx_1_chl_pwr_delta_g_band[3]; + CHAR delta_tx_pwr_bw40_g_band; + + CHAR tx_pwr_cck_1_2; + CHAR tx_pwr_cck_5_11; + CHAR tx_pwr_g_band_ofdm_6_9; + CHAR tx_pwr_g_band_ofdm_12_18; + CHAR tx_pwr_g_band_ofdm_24_36; + CHAR tx_pwr_g_band_ofdm_48; + CHAR tx_pwr_g_band_ofdm_54; + CHAR tx_pwr_ht_bpsk_mcs_0_8; + CHAR tx_pwr_ht_bpsk_mcs_32; + CHAR tx_pwr_ht_qpsk_mcs_1_2_9_10; + CHAR tx_pwr_ht_16qam_mcs_3_4_11_12; + CHAR tx_pwr_ht_64qam_mcs_5_13; + CHAR tx_pwr_ht_64qam_mcs_6_14; + CHAR tx_pwr_ht_64qam_mcs_7_15; +}; + + +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mtsdio_data.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mtsdio_data.h new file mode 100644 index 000000000..0bf9aec42 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mtsdio_data.h @@ -0,0 +1,33 @@ +/* + *************************************************************************** + * 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: + mtsdio_data.h +*/ + +typedef struct _SDIOWorkTask{ + DL_LIST List; + UINT32 Txcnt; + UINT32 RxCnt; + UINT32 CmdCnt; +} SDIOWorkTask; + +typedef struct _SDIOTxPacket{ + DL_LIST List; + PNDIS_PACKET NetPkt; +} SDIOTxPacket; + +INT32 MTSDIOCmdTx(struct _RTMP_ADAPTER *pAd, UCHAR *Buf, UINT32 Length); +INT32 MTSDIODataTx(struct _RTMP_ADAPTER *pAd, UCHAR *Buf, UINT32 Length); +VOID MTSDIOAddWorkerTaskList(struct _RTMP_ADAPTER *pAd); +VOID MTSDIODataWorkerTask(struct _RTMP_ADAPTER *pAd); +VOID MTSDIODataIsr(struct _RTMP_ADAPTER *pAd); diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mtsdio_io.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mtsdio_io.h new file mode 100644 index 000000000..7f10fd376 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mtsdio_io.h @@ -0,0 +1,28 @@ +/* + *************************************************************************** + * 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: + mtsdio_io.h +*/ + +#ifndef __MTSDIO_IO_H__ +#define __MTSDIO_IO_H__ + +INT32 MTSDIORead32(struct _RTMP_ADAPTER *pAd, UINT32 Offset, UINT32 *Value); +INT32 MTSDIOWrite32(struct _RTMP_ADAPTER *pAd, UINT32 Offset, UINT32 Value); +INT32 MTSDIOMultiRead(struct _RTMP_ADAPTER *pAd, UINT32 Offset, + UCHAR *Buf,UINT32 Length); +INT32 MTSDIOMultiWrite(struct _RTMP_ADAPTER *pAd, UINT32 Offset, + UCHAR *Buf,UINT32 Length); + +#endif + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mwds.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mwds.h new file mode 100644 index 000000000..f9f2252b8 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/mwds.h @@ -0,0 +1,81 @@ +#ifndef __MWDS_H__ +#define __MWDS_H__ +/* + *************************************************************************** + * Ralink Tech Inc. + * 5F., No.36, Taiyuan St., Jhubei City, + * Hsinchu County 302, + * Taiwan, R.O.C. + * + * (c) Copyright 2002-2009, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + + Module Name: + mwds.h + + Abstract: + This is MWDS feature used to process those 4-addr of connected APClient or STA. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ +#ifdef MWDS +#include "rtmp_def.h" + +#define MWDS_SUPPORT(B0) ((B0)&0x80) + +VOID MWDSAPPeerEnable( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID MWDSAPPeerDisable( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +#ifdef APCLI_SUPPORT +VOID MWDSAPCliPeerEnable( + IN PRTMP_ADAPTER pAd, + IN PAPCLI_STRUCT pApCliEntry, + IN MAC_TABLE_ENTRY *pEntry); + +VOID MWDSAPCliPeerDisable( + IN PRTMP_ADAPTER pAd, + IN PAPCLI_STRUCT pApCliEntry, + IN MAC_TABLE_ENTRY *pEntry); +#endif /* APCLI_SUPPORT */ +INT MWDSEnable( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex, + IN BOOLEAN isAP, + IN BOOLEAN isDevOpen); + +INT MWDSDisable( + IN PRTMP_ADAPTER pAd, + IN UCHAR ifIndex, + IN BOOLEAN isAP, + IN BOOLEAN isDevClose); + +INT Set_Ap_MWDS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +INT Set_ApCli_MWDS_Proc( + IN PRTMP_ADAPTER pAd, + IN PSTRING arg); + +VOID rtmp_read_MWDS_from_file( + IN PRTMP_ADAPTER pAd, + PSTRING tmpbuf, + PSTRING buffer); + +#endif /* MWDS */ +#endif /* __MWDS_H__*/ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/netif_block.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/netif_block.h new file mode 100644 index 000000000..3714bf069 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/netif_block.h @@ -0,0 +1,31 @@ + +#ifndef __NET_IF_BLOCK_H__ +#define __NET_IF_BLOCK_H__ + +#include "link_list.h" +#include "rtmp.h" + +#define FREE_NETIF_POOL_SIZE 32 + +typedef struct _NETIF_ENTRY +{ + struct _NETIF_ENTRY *pNext; + PNET_DEV pNetDev; +} NETIF_ENTRY, *PNETIF_ENTRY; + +void initblockQueueTab( + IN PRTMP_ADAPTER pAd); + +BOOLEAN blockNetIf( + IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry, + IN PNET_DEV pNetDev); + +VOID releaseNetIf( + IN PBLOCK_QUEUE_ENTRY pBlockQueueEntry); + +VOID StopNetIfQueue( + IN PRTMP_ADAPTER pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); +#endif /* __NET_IF_BLOCK_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/nfc.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/nfc.h new file mode 100644 index 000000000..358bbd746 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/nfc.h @@ -0,0 +1,46 @@ +#ifndef __WSC_NFC_H__ +#define __WSC_NFC_H__ + +VOID NfcParseRspCommand( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN USHORT DataLen); + +VOID NfcCommand( + IN PRTMP_ADAPTER pAd, + IN UCHAR Action, + IN UCHAR Type, + IN SHORT DataLen, + IN PUCHAR pData); + +VOID NfcGenRandomPasswd( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscCtrl); + +INT NfcBuildWscProfileTLV( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscCtrl, + OUT UCHAR *pbuf, + OUT USHORT *pBufLen); + +INT NfcBuildOOBDevPasswdTLV( + IN PRTMP_ADAPTER pAd, + IN PWSC_CTRL pWscCtrl, + IN UCHAR HandoverType, + OUT UCHAR *pbuf, + OUT USHORT *pBufLen); + +INT Set_NfcStatus_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_NfcPasswdToken_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_NfcConfigurationToken_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Get_NfcStatus_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_DoWpsByNFC_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_NfcRegenPK_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + +#endif /* __WSC_NFC_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/oid.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/oid.h new file mode 100644 index 000000000..7cabcbdfd --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/oid.h @@ -0,0 +1,2204 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + oid.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ +#ifndef _OID_H_ +#define _OID_H_ + +/*#include */ + + + +/* new types for Media Specific Indications */ +/* Extension channel offset */ +#define EXTCHA_NONE 0 +#define EXTCHA_ABOVE 0x1 +#define EXTCHA_BELOW 0x3 + +/* BW */ +#define BAND_WIDTH_20 0 +#define BAND_WIDTH_40 1 +#define BAND_WIDTH_80 2 +#define BAND_WIDTH_160 3 +#define BAND_WIDTH_10 4 /* 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field. */ +#define BAND_WIDTH_5 5 +#define BAND_WIDTH_8080 6 +#define BAND_WIDTH_BOTH 7 /* BW20 + BW40 */ +#define BAND_WIDTH_25 8 +#define BAND_WIDTH_NUM 9 + + +/* SHORTGI */ +#define GAP_INTERVAL_400 1 /* only support in HT mode */ +#define GAP_INTERVAL_800 0 +#define GAP_INTERVAL_BOTH 2 + +#define NdisMediaStateConnected 1 +#define NdisMediaStateDisconnected 0 + +#define NdisApMediaStateConnected 1 +#define NdisApMediaStateDisconnected 0 + + +#define NDIS_802_11_LENGTH_SSID 32 + +#define MAC_ADDR_LEN 6 +#define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */ +#define IEEE80211_NWID_LEN 32 + +#define NDIS_802_11_LENGTH_RATES 8 +#define NDIS_802_11_LENGTH_RATES_EX 16 + +#define OID_P2P_DEVICE_NAME_LEN 32 +/*#define MAX_NUM_OF_CHS 49 */ /* 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL terminationc */ +/*#define MAX_NUM_OF_CHS 54 */ /* 14 channels @2.4G + 12@UNII(lower/middle) + 16@HiperLAN2 + 11@UNII(upper) + 0 @Japan + 1 as NULL termination */ +#define MAX_NUMBER_OF_EVENT 10 /* entry # in EVENT table */ + +/*JDC +#if defined (CONFIG_RT_FIRST_IF_MT7603E) && defined (CONFIG_RT_SECOND_IF_MT7615E) +#define CONFIG_RT_MAX_CLIENTS 48 +#endif +#define CONFIG_MAX_CLIENTS CONFIG_RT_MAX_CLIENTS + +#define MAX_NUMBER_OF_MAC CONFIG_MAX_CLIENTS +*/ +#ifdef BB_SOC +#define MAX_NUMBER_OF_MAC 16 // if MAX_MBSSID_NUM is 8, this value can't be larger than 211 +#else +#if defined(MT7603_FPGA) || defined(MT7628_FPGA) || defined(MT7636_FPGA) +#define MAX_NUMBER_OF_MAC 4 /* if MAX_MBSSID_NUM is 8, this value can't be larger than 211 */ +#elif defined(MT7603) +#ifdef ECONET_ALPHA_RELEASE +#define MAX_NUMBER_OF_MAC 8 +#else +#ifdef MAC_REPEATER_SUPPORT +#ifdef MULTI_APCLI_SUPPORT +#define MAX_NUMBER_OF_MAC (75 - (16 + 1) * 2) +#else +#define MAX_NUMBER_OF_MAC (75 - (16 + 1) * 1) +#endif /* MULTI_APCLI_SUPPORT */ +#else +#define MAX_NUMBER_OF_MAC 75 +#endif /* MAC_REPEATER_SUPPORT */ +#endif +#elif defined(MT76x2) +#ifdef MAC_REPEATER_SUPPORT //((MAX_EXT_MAC_ADDR_SIZE + 1) * MAC_APCLI_NUM) +#define MAX_NUMBER_OF_MAC (116 - ((16 + 1) * 1)) +#else +#define MAX_NUMBER_OF_MAC 116 +#endif /* MAC_REPEATER_SUPPORT */ +#else +#define MAX_NUMBER_OF_MAC 32 /* if MAX_MBSSID_NUM is 8, this value can't be larger than 211 */ +#endif /* defined(MT7603_FPGA) || defined(MT7628_FPGA) */ +#endif /* BB_SOC */ + +#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 MAC_REPEATER_SUPPORT +/*seems different chip have different size , use 16 (minimum size) tmply */ +#define MAX_NUMBER_OF_MAC_LIST 16 /* MAX_EXT_MAC_ADDR_SIZE */ +#endif /* MAC_REPEATER_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 +#ifdef DOT11R_FT_SUPPORT +#define RT_SET_FT_STATION_NOTIFY 0x0408 +#define RT_SET_FT_KEY_REQ 0x0409 +#define RT_SET_FT_KEY_RSP 0x040a +#define RT_FT_KEY_SET 0x040b +#define RT_FT_DATA_ENCRYPT 0x040c +#define RT_FT_DATA_DECRYPT 0x040d +#define RT_FT_NEIGHBOR_REPORT 0x040e +#define RT_FT_NEIGHBOR_REQUEST 0x040f +#define RT_FT_NEIGHBOR_RESPONSE 0x0410 +#define RT_FT_ACTION_FORWARD 0x0411 +#endif /* DOT11R_FT_SUPPORT */ +/* */ +/* IEEE 802.11 OIDs */ +/* */ +#define OID_GET_SET_TOGGLE 0x8000 +#define OID_GET_SET_FROM_UI 0x4000 + +#define OID_802_11_NETWORK_TYPES_SUPPORTED 0x0103 +#define OID_802_11_NETWORK_TYPE_IN_USE 0x0104 +#define OID_802_11_RSSI_TRIGGER 0x0107 +#define RT_OID_802_11_RSSI 0x0108 /* rt2860 only */ +#define RT_OID_802_11_RSSI_1 0x0109 /* rt2860 only */ +#define RT_OID_802_11_RSSI_2 0x010A /* rt2860 only */ +#define OID_802_11_NUMBER_OF_ANTENNAS 0x010B +#define OID_802_11_RX_ANTENNA_SELECTED 0x010C +#define OID_802_11_TX_ANTENNA_SELECTED 0x010D +#define OID_802_11_SUPPORTED_RATES 0x010E +#define OID_802_11_ADD_WEP 0x0112 +#define OID_802_11_REMOVE_WEP 0x0113 +#define OID_802_11_DISASSOCIATE 0x0114 +#define OID_802_11_PRIVACY_FILTER 0x0118 +#define OID_802_11_ASSOCIATION_INFORMATION 0x011E +#define OID_802_11_TEST 0x011F + + +#define RT_OID_802_11_COUNTRY_REGION 0x0507 +#define OID_802_11_BSSID_LIST_SCAN 0x0508 +#define OID_802_11_SSID 0x0509 +#define OID_802_11_BSSID 0x050A +#define RT_OID_802_11_RADIO 0x050B +#define RT_OID_802_11_PHY_MODE 0x050C +#define RT_OID_802_11_STA_CONFIG 0x050D +#define OID_802_11_DESIRED_RATES 0x050E +#define RT_OID_802_11_PREAMBLE 0x050F +#define OID_802_11_WEP_STATUS 0x0510 +#define OID_802_11_AUTHENTICATION_MODE 0x0511 +#define OID_802_11_INFRASTRUCTURE_MODE 0x0512 +#define RT_OID_802_11_RESET_COUNTERS 0x0513 +#define OID_802_11_RTS_THRESHOLD 0x0514 +#define OID_802_11_FRAGMENTATION_THRESHOLD 0x0515 +#define OID_802_11_POWER_MODE 0x0516 +#define OID_802_11_TX_POWER_LEVEL 0x0517 +#define RT_OID_802_11_ADD_WPA 0x0518 +#define OID_802_11_REMOVE_KEY 0x0519 +#define RT_OID_802_11_QUERY_PID 0x051A +#define RT_OID_802_11_QUERY_VID 0x051B +#define OID_802_11_ADD_KEY 0x0520 +#define OID_802_11_CONFIGURATION 0x0521 +#define OID_802_11_TX_PACKET_BURST 0x0522 +#define RT_OID_802_11_QUERY_NOISE_LEVEL 0x0523 +#define RT_OID_802_11_EXTRA_INFO 0x0524 +#define RT_OID_802_11_HARDWARE_REGISTER 0x0525 +#define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS +#define OID_802_11_DEAUTHENTICATION 0x0526 +#define OID_802_11_DROP_UNENCRYPTED 0x0527 +#define OID_802_11_MIC_FAILURE_REPORT_FRAME 0x0528 +#define OID_802_11_EAP_METHOD 0x0529 +#define OID_802_11_ACL_LIST 0x052A +#define OID_802_11_FROAM_ACL_ADD_ENTRY 0x252B +#define OID_802_11_FROAM_ACL_DEL_ENTRY 0x252C + +#if (defined(VENDOR_FEATURE6_SUPPORT) || defined(MAP_SUPPORT)) +#define OID_802_11_COEXISTENCE 0x0530 +#endif + +/* For 802.1x daemin using */ +#ifdef DOT1X_SUPPORT +#define OID_802_DOT1X_CONFIGURATION 0x0540 +#define OID_802_DOT1X_PMKID_CACHE 0x0541 +#define OID_802_DOT1X_RADIUS_DATA 0x0542 +#define OID_802_DOT1X_WPA_KEY 0x0543 +#define OID_802_DOT1X_STATIC_WEP_COPY 0x0544 +#define OID_802_DOT1X_IDLE_TIMEOUT 0x0545 +#define OID_802_DOT1X_RADIUS_ACL_NEW_CACHE 0x0546 +#define OID_802_DOT1X_RADIUS_ACL_DEL_CACHE 0x0547 +#define OID_802_DOT1X_RADIUS_ACL_CLEAR_CACHE 0x0548 +#define OID_802_DOT1X_QUERY_STA_AID 0x0549 +#endif /* DOT1X_SUPPORT */ + +#define RT_OID_DEVICE_NAME 0x0607 +#define RT_OID_VERSION_INFO 0x0608 +#define OID_802_11_BSSID_LIST 0x0609 +#define OID_802_3_CURRENT_ADDRESS 0x060A +#define OID_GEN_MEDIA_CONNECT_STATUS 0x060B +#define RT_OID_802_11_QUERY_LINK_STATUS 0x060C +#define OID_802_11_RSSI 0x060D +#define OID_802_11_STATISTICS 0x060E +#define OID_GEN_RCV_OK 0x060F +#define OID_GEN_RCV_NO_BUFFER 0x0610 +#define RT_OID_802_11_QUERY_EEPROM_VERSION 0x0611 +#define RT_OID_802_11_QUERY_FIRMWARE_VERSION 0x0612 +#define RT_OID_802_11_QUERY_LAST_RX_RATE 0x0613 +#define RT_OID_802_11_TX_POWER_LEVEL_1 0x0614 +#define RT_OID_802_11_QUERY_PIDVID 0x0615 +/*for WPA_SUPPLICANT_SUPPORT */ +#define OID_SET_COUNTERMEASURES 0x0616 +#define OID_802_11_SET_IEEE8021X 0x0617 +#define OID_802_11_SET_IEEE8021X_REQUIRE_KEY 0x0618 +#define OID_802_11_PMKID 0x0620 +#define RT_OID_WPA_SUPPLICANT_SUPPORT 0x0621 +#define RT_OID_WE_VERSION_COMPILED 0x0622 +#define RT_OID_NEW_DRIVER 0x0623 +#define OID_AUTO_PROVISION_BSSID_LIST 0x0624 +#define RT_OID_WPS_PROBE_REQ_IE 0x0625 + +#define RT_OID_802_11_SNR_0 0x0630 +#define RT_OID_802_11_SNR_1 0x0631 +#define RT_OID_802_11_QUERY_LAST_TX_RATE 0x0632 +#define RT_OID_802_11_QUERY_HT_PHYMODE 0x0633 +#define RT_OID_802_11_SET_HT_PHYMODE 0x0634 +#define OID_802_11_RELOAD_DEFAULTS 0x0635 +#define RT_OID_802_11_QUERY_APSD_SETTING 0x0636 +#define RT_OID_802_11_SET_APSD_SETTING 0x0637 +#define RT_OID_802_11_QUERY_APSD_PSM 0x0638 +#define RT_OID_802_11_SET_APSD_PSM 0x0639 +#define RT_OID_802_11_QUERY_DLS 0x063A +#define RT_OID_802_11_SET_DLS 0x063B +#define RT_OID_802_11_QUERY_DLS_PARAM 0x063C +#define RT_OID_802_11_SET_DLS_PARAM 0x063D +#define RT_OID_802_11_QUERY_WMM 0x063E +#define RT_OID_802_11_SET_WMM 0x063F +#define RT_OID_802_11_QUERY_IMME_BA_CAP 0x0640 +#define RT_OID_802_11_SET_IMME_BA_CAP 0x0641 +#define RT_OID_802_11_QUERY_BATABLE 0x0642 +#define RT_OID_802_11_ADD_IMME_BA 0x0643 +#define RT_OID_802_11_TEAR_IMME_BA 0x0644 +#define RT_OID_DRIVER_DEVICE_NAME 0x0645 +#define RT_OID_802_11_QUERY_DAT_HT_PHYMODE 0x0646 +#define OID_WAPP_EVENT 0x0647 +#define OID_802_11_SET_PSPXLINK_MODE 0x0648 +/*+++ add by woody +++*/ + +#ifdef WH_EZ_SETUP +#define OID_802_11_PASSPHRASE 0x0649 +#else +#define OID_802_11_SET_PASSPHRASE 0x0649 +#endif +#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 +#define OID_802_11_MBSS_GET_STA_COUNT 0x067E + + + +#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) +#ifdef WH_EZ_SETUP +#define RT_OID_802_11_SET_PASSPHRASE (OID_GET_SET_TOGGLE | OID_802_11_PASSPHRASE) +#else +#define RT_OID_802_11_SET_PASSPHRASE (OID_GET_SET_TOGGLE | OID_802_11_SET_PASSPHRASE) +#endif + +#ifdef DOT1X_SUPPORT +#define RT_OID_802_DOT1X_PMKID_CACHE (OID_GET_SET_TOGGLE | OID_802_DOT1X_PMKID_CACHE) +#define RT_OID_802_DOT1X_RADIUS_DATA (OID_GET_SET_TOGGLE | OID_802_DOT1X_RADIUS_DATA) +#define RT_OID_802_DOT1X_WPA_KEY (OID_GET_SET_TOGGLE | OID_802_DOT1X_WPA_KEY) +#define RT_OID_802_DOT1X_STATIC_WEP_COPY (OID_GET_SET_TOGGLE | OID_802_DOT1X_STATIC_WEP_COPY) +#define RT_OID_802_DOT1X_IDLE_TIMEOUT (OID_GET_SET_TOGGLE | OID_802_DOT1X_IDLE_TIMEOUT) +#endif /* DOT1X_SUPPORT */ + +#define RT_OID_802_11_SET_TDLS_PARAM (OID_GET_SET_TOGGLE | RT_OID_802_11_QUERY_TDLS_PARAM) +#define RT_OID_802_11_SET_TDLS (OID_GET_SET_TOGGLE | RT_OID_802_11_QUERY_TDLS) + + +#ifdef WAPI_SUPPORT +#define OID_802_11_WAPI_PID 0x06A0 +#define OID_802_11_PORT_SECURE_STATE 0x06A1 +#define OID_802_11_UCAST_KEY_INFO 0x06A2 +#define OID_802_11_MCAST_TXIV 0x06A3 +#define OID_802_11_MCAST_KEY_INFO 0x06A4 +#define OID_802_11_WAPI_CONFIGURATION 0x06A5 +#define OID_802_11_WAPI_IE 0x06A6 + +#define RT_OID_802_11_WAPI_PID (OID_GET_SET_TOGGLE | OID_802_11_WAPI_PID) +#define RT_OID_802_11_PORT_SECURE_STATE (OID_GET_SET_TOGGLE | OID_802_11_PORT_SECURE_STATE) +#define RT_OID_802_11_UCAST_KEY_INFO (OID_GET_SET_TOGGLE | OID_802_11_UCAST_KEY_INFO) +#define RT_OID_802_11_MCAST_TXIV (OID_GET_SET_TOGGLE | OID_802_11_MCAST_TXIV) +#define RT_OID_802_11_MCAST_KEY_INFO (OID_GET_SET_TOGGLE | OID_802_11_MCAST_KEY_INFO) +#define RT_OID_802_11_WAPI_CONFIGURATION (OID_GET_SET_TOGGLE | OID_802_11_WAPI_CONFIGURATION) +#define RT_OID_802_11_WAPI_IE (OID_GET_SET_TOGGLE | OID_802_11_WAPI_IE) +#endif /* WAPI_SUPPORT */ +#ifdef ACL_BLK_COUNT_SUPPORT +#define OID_802_11_ACL_BLK_REJCT_COUNT_STATICS 0x069b +#endif/*ACL_BLK_COUNT_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 +#ifdef WH_EZ_SETUP +#define IS_AKM_PSK_Entry(_Entry) (((_Entry)->AuthMode == Ndis802_11AuthModeWPAPSK) || ((_Entry)->AuthMode == Ndis802_11AuthModeWPA2PSK)) +#endif +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 */ +#define MAX_MBSSID_1X_NUM 16 /* stay correspondence with 802.1x daemon */ + +/* 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 own_radius_port; + UINT32 retry_interval; + UINT32 session_timeout_interval; + UINT32 quiet_interval; + UCHAR EAPifname[MAX_MBSSID_1X_NUM][IFNAMSIZ]; + UCHAR EAPifname_len[MAX_MBSSID_1X_NUM]; + UCHAR PreAuthifname[MAX_MBSSID_1X_NUM][IFNAMSIZ]; + UCHAR PreAuthifname_len[MAX_MBSSID_1X_NUM]; + DOT1X_BSS_INFO Dot1xBssInfo[MAX_MBSSID_1X_NUM]; +#ifdef RADIUS_MAC_ACL_SUPPORT + UCHAR RadiusAclEnable[MAX_MBSSID_1X_NUM]; + UINT32 AclCacheTimeout[MAX_MBSSID_1X_NUM]; +#endif /* RADIUS_MAC_ACL_SUPPORT */ +} DOT1X_CMM_CONF, *PDOT1X_CMM_CONF; + +typedef struct GNU_PACKED _DOT1X_IDLE_TIMEOUT { + UCHAR StaAddr[6]; + UINT32 idle_timeout; +} DOT1X_IDLE_TIMEOUT, *PDOT1X_IDLE_TIMEOUT; + +typedef struct GNU_PACKED _DOT1X_QUERY_STA_AID { + UCHAR StaAddr[MAC_ADDR_LEN]; + UINT aid; +} DOT1X_QUERY_STA_AID, *PDOT1X_QUERY_STA_AID; +#endif /* DOT1X_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +typedef struct _NDIS_AP_802_11_KEY { + UINT Length; /* Length of this structure */ + UCHAR addr[6]; + UINT KeyIndex; + UINT KeyLength; /* length of key in bytes */ + UCHAR KeyMaterial[1]; /* variable length depending on above field */ +} NDIS_AP_802_11_KEY, *PNDIS_AP_802_11_KEY; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef APCLI_SUPPORT +#endif /* APCLI_SUPPORT */ + + +#if (defined(CONFIG_STA_SUPPORT) || defined(WH_EZ_SETUP)) +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 + +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_11AuthModeWPA3PSK, + Ndis802_11AuthModeWPA2PSKWPA3PSK, + Ndis802_11AuthModeOWE, + 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 _NDIS_802_11_SSID { + UINT SsidLength; /* length of SSID field below, in bytes; */ + /* this can be zero. */ + UCHAR Ssid[NDIS_802_11_LENGTH_SSID]; /* SSID information field */ +} NDIS_802_11_SSID, *PNDIS_802_11_SSID; + +typedef struct GNU_PACKED _NDIS_WLAN_BSSID { + ULONG Length; /* Length of this structure */ + NDIS_802_11_MAC_ADDRESS MacAddress; /* BSSID */ + UCHAR Reserved[2]; + NDIS_802_11_SSID Ssid; /* SSID */ + ULONG Privacy; /* WEP encryption requirement */ + NDIS_802_11_RSSI Rssi; /* receive signal strength in dBm */ + NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; + NDIS_802_11_CONFIGURATION Configuration; + NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; + NDIS_802_11_RATES SupportedRates; +} NDIS_WLAN_BSSID, *PNDIS_WLAN_BSSID; + +typedef struct GNU_PACKED _NDIS_802_11_BSSID_LIST { + UINT NumberOfItems; /* in list below, at least 1 */ + NDIS_WLAN_BSSID Bssid[1]; +} NDIS_802_11_BSSID_LIST, *PNDIS_802_11_BSSID_LIST; + +typedef struct { + BOOLEAN bValid; /* 1: variable contains valid value */ + USHORT StaNum; + UCHAR ChannelUtilization; + USHORT RemainingAdmissionControl; /* in unit of 32-us */ +} QBSS_LOAD_UI, *PQBSS_LOAD_UI; + +/* Added Capabilities, IELength and IEs for each BSSID */ +typedef struct GNU_PACKED _NDIS_WLAN_BSSID_EX { + ULONG Length; /* Length of this structure */ + NDIS_802_11_MAC_ADDRESS MacAddress; /* BSSID */ + UCHAR WpsAP; /* 0x00: not support WPS, 0x01: support normal WPS, 0x02: support Ralink auto WPS, 0x04: support Samsung WAC */ + CHAR MinSNR; + NDIS_802_11_SSID Ssid; /* SSID */ + UINT Privacy; /* WEP encryption requirement */ + NDIS_802_11_RSSI Rssi; /* receive signal */ + /* strength in dBm */ + NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; + NDIS_802_11_CONFIGURATION Configuration; + NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; + NDIS_802_11_RATES_EX SupportedRates; + ULONG IELength; + UCHAR IEs[1]; + +} NDIS_WLAN_BSSID_EX, *PNDIS_WLAN_BSSID_EX; + +typedef struct GNU_PACKED _NDIS_802_11_BSSID_LIST_EX { + UINT NumberOfItems; /* in list below, at least 1 */ + NDIS_WLAN_BSSID_EX Bssid[1]; +} NDIS_802_11_BSSID_LIST_EX, *PNDIS_802_11_BSSID_LIST_EX; + +typedef struct GNU_PACKED _NDIS_802_11_FIXED_IEs { + UCHAR Timestamp[8]; + USHORT BeaconInterval; + USHORT Capabilities; +} NDIS_802_11_FIXED_IEs, *PNDIS_802_11_FIXED_IEs; + +typedef struct _NDIS_802_11_VARIABLE_IEs { + UCHAR ElementID; + UCHAR Length; /* Number of bytes in data field */ + UCHAR data[1]; +} NDIS_802_11_VARIABLE_IEs, *PNDIS_802_11_VARIABLE_IEs; + +typedef ULONG NDIS_802_11_FRAGMENTATION_THRESHOLD; + +typedef ULONG NDIS_802_11_RTS_THRESHOLD; + +typedef ULONG NDIS_802_11_ANTENNA; + +typedef enum _NDIS_802_11_PRIVACY_FILTER { + Ndis802_11PrivFilterAcceptAll, + Ndis802_11PrivFilter8021xWEP +} NDIS_802_11_PRIVACY_FILTER, *PNDIS_802_11_PRIVACY_FILTER; + +/* Added new encryption types */ +/* Also aliased typedef to new name */ +typedef enum _NDIS_802_11_WEP_STATUS { + Ndis802_11WEPEnabled, + Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, + Ndis802_11WEPDisabled, + Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, + Ndis802_11WEPKeyAbsent, + Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, + Ndis802_11WEPNotSupported, + Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, + Ndis802_11TKIPEnable, + Ndis802_11Encryption2Enabled = Ndis802_11TKIPEnable, + Ndis802_11Encryption2KeyAbsent, + Ndis802_11AESEnable, + Ndis802_11Encryption3Enabled = Ndis802_11AESEnable, + Ndis802_11Encryption3KeyAbsent, + Ndis802_11TKIPAESMix, + Ndis802_11Encryption4Enabled = Ndis802_11TKIPAESMix, /* TKIP or AES mix */ + Ndis802_11Encryption4KeyAbsent, + Ndis802_11GroupWEP40Enabled, + Ndis802_11GroupWEP104Enabled, +#ifdef WAPI_SUPPORT + Ndis802_11EncryptionSMS4Enabled, /* WPI SMS4 support */ +#endif /* WAPI_SUPPORT */ +#ifdef CONFIG_OWE_SUPPORT + Ndis802_11CCMP128Enable, + Ndis802_11CCMP256Enable, +#endif +} 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]; + +#ifdef DOT11_SAE_SUPPORT +#define INVALID_PMKID_IDX -1 +#endif + +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) +#define LEN_MAX_PMK 64 +#endif + +#if defined(CONFIG_STA_SUPPORT) || defined(WPA_SUPPLICANT_SUPPORT) || defined(APCLI_SUPPORT)\ + || defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) +typedef struct _BSSID_INFO { + NDIS_802_11_MAC_ADDRESS BSSID; + NDIS_802_11_PMKID_VALUE PMKID; +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + UCHAR PMK[LEN_MAX_PMK]; + BOOLEAN Valid; +#endif + +} BSSID_INFO, *PBSSID_INFO; + +typedef struct _NDIS_802_11_PMKID { + UINT Length; + UINT BSSIDInfoCount; + BSSID_INFO BSSIDInfo[1]; +} NDIS_802_11_PMKID, *PNDIS_802_11_PMKID; +#endif /* defined(CONFIG_STA_SUPPORT) || defined(WPA_SUPPLICANT_SUPPORT) */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +#endif /* APCLI_SUPPORT */ + +typedef struct _AP_BSSID_INFO { + NDIS_802_11_MAC_ADDRESS MAC; + NDIS_802_11_PMKID_VALUE PMKID; + UCHAR PMK[32]; + ULONG RefreshTime; + BOOLEAN Valid; +} AP_BSSID_INFO, *PAP_BSSID_INFO; + +#define MAX_PMKID_COUNT 8 +typedef struct _NDIS_AP_802_11_PMKID { + AP_BSSID_INFO BSSIDInfo[MAX_PMKID_COUNT]; +} NDIS_AP_802_11_PMKID, *PNDIS_AP_802_11_PMKID; +#endif /* CONFIG_AP_SUPPORT */ + +typedef struct _NDIS_802_11_AUTHENTICATION_ENCRYPTION { + NDIS_802_11_AUTHENTICATION_MODE AuthModeSupported; + NDIS_802_11_ENCRYPTION_STATUS EncryptStatusSupported; +} NDIS_802_11_AUTHENTICATION_ENCRYPTION, *PNDIS_802_11_AUTHENTICATION_ENCRYPTION; + +typedef struct _NDIS_802_11_CAPABILITY { + ULONG Length; + ULONG Version; + ULONG NoOfPMKIDs; + ULONG NoOfAuthEncryptPairsSupported; + NDIS_802_11_AUTHENTICATION_ENCRYPTION + AuthenticationEncryptionSupported[1]; +} NDIS_802_11_CAPABILITY, *PNDIS_802_11_CAPABILITY; +#ifdef STA_FORCE_ROAM_SUPPORT + +enum FROAM_COMMAND { + OID_FROAM_CMD_FROAM_ENABLED = 0x1, + OID_FROAM_CMD_GET_THRESHOLD = 0x2, +}; + +typedef struct GNU_PACKED _froam_command_hdr { + UINT8 command_id; + UINT8 command_len; +}froam_command_hdr,*pfroam_command_hdr; + +typedef struct GNU_PACKED _threshold_info{ + UINT8 sta_ageout_time; + UINT8 mntr_ageout_time; + UINT8 mntr_min_pkt_count; + UINT8 mntr_min_time; + UINT8 mntr_avg_rssi_pkt_count; + char sta_detect_rssi_threshold; + UINT8 acl_ageout_time; + UINT8 acl_hold_time; +}threshold_info,*pthreshold_info; + +typedef struct GNU_PACKED _cmd_froam_en{ + struct _froam_command_hdr hdr; + UINT8 froam_en; + UINT8 channel; +}cmd_froam_en,*pcmd_froam_en; + +typedef struct GNU_PACKED _cmd_threshold{ + struct _froam_command_hdr hdr; + struct _threshold_info info; +}cmd_threshold,*pcmd_threshold; + +enum FROAM_EVENT { + FROAM_EVT_STA_RSSI_LOW = 0x01, + FROAM_EVT_STA_RSSI_GOOD = 0x02, + FROAM_EVT_STA_DISCONNECT = 0x03, + FROAM_EVT_CLEAR_MNTR_LIST = 0x04, + FROAM_EVT_CLEAR_ACL_LIST = 0x05, + FROAM_EVT_STA_AGEOUT_TIME = 0x06, + FROAM_EVT_MNTR_AGEOUT_TIME = 0x07, + FROAM_EVT_ACL_AGEOUT_TIME = 0x08, + FROAM_EVT_STA_DETECT_RSSI_THRESHOLD = 0x09, + FROAM_EVT_MNTR_MIN_PKT_COUNT = 0x0A, // all new below + FROAM_EVT_MNTR_MIN_TIME = 0x0B, + FROAM_EVT_STA_AVG_RSSI_PKT_COUNT = 0x0D, + FROAM_EVT_ACL_HOLD_TIME = 0x0C, + FROAM_EVT_FROAM_SUPP = 0x0E, +}; + +typedef struct GNU_PACKED froam_event_s { + UINT8 event_id; + UINT8 event_len; + UINT8 event_body[0]; +}froam_event_t, *p_froam_event_t; + +typedef struct GNU_PACKED _froam_event_hdr { + UINT8 event_id; + UINT8 event_len; +}froam_event_hdr,*p_froam_event_hdr; + +#define LOW_RSSI_STA_RENOTIFY_TIME 10 + +typedef struct GNU_PACKED _froam_event_sta_low_rssi { + struct _froam_event_hdr hdr; + UINT8 mac[MAC_ADDR_LEN]; + UINT8 channel; +}froam_event_sta_low_rssi, *pfroam_event_sta_low_rssi; + +typedef struct GNU_PACKED _froam_event_sta_good_rssi { + struct _froam_event_hdr hdr; + UINT8 mac[MAC_ADDR_LEN]; +}froam_event_sta_good_rssi, *pfroam_event_sta_good_rssi; + +typedef struct GNU_PACKED _froam_event_sta_disconn { + struct _froam_event_hdr hdr; + UINT8 mac[MAC_ADDR_LEN]; +}froam_event_sta_disconn, *pfroam_event_sta_disconn; + +typedef struct GNU_PACKED _froam_event_param_cfg { + struct _froam_event_hdr hdr; + UINT8 value; +}froam_event_param_cfg, *pfroam_event_param_cfg; +#endif + +#ifdef WH_EZ_SETUP + +#ifdef EZ_REGROUP_SUPPORT +enum REGROUP_COMMAND { + OID_REGROUP_CMD_CLI_INFO = 0x01, + OID_REGROUP_CMD_CONNECTED_PEER_LIST = 0x02, + //OID_REGROUP_CMD_EZ_CAP_INFO = 0x03, + OID_REGROUP_CMD_SCAN = 0x04, + OID_REGROUP_CMD_CAND_LIST = 0x05, + OID_REGROUP_CMD_CLEAR_CAND_LIST = 0x06, + OID_REGROUP_CMD_TRIGGER_REGRP = 0x07, + OID_REGROUP_CMD_TERMINATE_REGRP = 0x08, + OID_REGROUP_CMD_REGRP_SUPP = 0x09, + OID_REGROUP_CMD_EN_REGRP_MODE = 0x0A, // rename to avoid confusion with regrp supp + OID_REGROUP_QUERY_INTERFACE_DETAILS = 0x0B, + OID_REGROUP_QUERY_NODE_NUMBER_WT = 0x0C +}; + +typedef struct GNU_PACKED regrp_command_s +{ + UINT8 command_id; + UINT8 command_len; + UINT8 command_body[0]; +} regrp_command_t, *p_regrp_command_t; + +typedef struct GNU_PACKED _regrp_cmd_hdr { + UINT8 command_id; + UINT8 command_len; +}regrp_cmd_hdr,*pregrp_cmd_hdr; + +enum REGROUP_EVENT { + REGROUP_EVT_USER_REGROUP_REQ = 0x02, + REGROUP_EVT_SCAN_COMPLETE = 0x03, + REGROUP_EVT_INTF_REGRP_DONE = 0x04, + REGROUP_EVT_INTF_CONNECTED = 0x5, + REGROUP_EVT_INTF_DISCONNECTED = 0x6, +}; + +typedef struct GNU_PACKED regrp_event_s +{ + UINT8 event_id; + UINT8 event_len; + UINT8 event_body[0]; +} regrp_event_t, *p_regrp_event_t; + +typedef struct GNU_PACKED _cmd_regrp_supp{ + struct _regrp_cmd_hdr hdr; + UINT8 regrp_supp; + UINT8 ez_supp; + UINT8 channel; + UINT8 configured; +}cmd_regrp_supp,*pcmd_regrp_supp; + +enum REGRP_MODE{ + NON_REGRP_MODE = 0x0, // ensure to set this back + REGRP_MODE_BLOCKED = 0x1, + REGRP_MODE_UNBLOCKED = 0x2, + // one mroe mode thought off ?? +}; + +typedef struct GNU_PACKED _cmd_regrp_mode{ + struct _regrp_cmd_hdr hdr; + UINT8 mode; +}cmd_regrp_mode,*pcmd_regrp_mode; + +#define HAS_INTERNET_BIT 1 +#define HAS_DIRECT_INTERNET_BIT 2 + +//#define NETWORK_WEIGHT_LEN (MAC_ADDR_LEN + 1) + +//typedef struct GNU_PACKED _ez_cap_info { +// unsigned int capability; +//}ez_cap_info,*pez_cap_info; + + +#define SCAN_GENERAL 1 +#define SCAN_CONNECTED_SSID 2 +#define SCAN_SPECIFIED_SSID 3 + +typedef struct GNU_PACKED _regrp_cmd_scan { + struct _regrp_cmd_hdr hdr; + UINT8 scan_type; + UINT8 ssid[32]; +}regrp_cmd_scan,*pregrp_cmd_scan; + +#define MAX_EZ_PEERS 6 +#define MAX_AP_CANDIDATES (MAX_EZ_PEERS + 2) // considering 2 Non MAN Ap but no restriction + +typedef struct GNU_PACKED _regrp_cmd_cand_list{ + struct _regrp_cmd_hdr hdr; + u8 cand_count; + UINT8 list[0]; // one or more entries of type struct _ntw_info +}regrp_cmd_cand_list,*pregrp_cmd_cand_list; + +typedef struct GNU_PACKED _regrp_cmd_cfg_cand_list{ + struct _regrp_cmd_hdr hdr; + u8 cand_count; + u8 bssid[MAX_AP_CANDIDATES][MAC_ADDR_LEN]; +}regrp_cmd_cfg_cand_list,*pregrp_cmd_cfg_cand_list; + + +typedef struct GNU_PACKED _drvr_cand_list{ + UCHAR bssid[MAC_ADDR_LEN]; + UCHAR attempted; +}rdrvr_cand_list,*pdrvr_cand_list; + +#endif + +#endif + + + + + +#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 SNMP_SUPPORT +/*SNMP ieee 802dot11 , 2008_0220 */ +/* dot11res(3) */ +#define RT_OID_802_11_MANUFACTUREROUI 0x0700 +#define RT_OID_802_11_MANUFACTURERNAME 0x0701 +#define RT_OID_802_11_RESOURCETYPEIDNAME 0x0702 + +/* dot11smt(1) */ +#define RT_OID_802_11_PRIVACYOPTIONIMPLEMENTED 0x0703 +#define RT_OID_802_11_POWERMANAGEMENTMODE 0x0704 +#define OID_802_11_WEPDEFAULTKEYVALUE 0x0705 /* read , write */ +#define OID_802_11_WEPDEFAULTKEYID 0x0706 +#define RT_OID_802_11_WEPKEYMAPPINGLENGTH 0x0707 +#define OID_802_11_SHORTRETRYLIMIT 0x0708 +#define OID_802_11_LONGRETRYLIMIT 0x0709 +#define RT_OID_802_11_PRODUCTID 0x0710 +#define RT_OID_802_11_MANUFACTUREID 0x0711 + +/* //dot11Phy(4) */ + +#endif /* SNMP_SUPPORT */ + +#if (defined(SNMP_SUPPORT) || defined(WH_EZ_SETUP)) +/* //dot11Phy(4) */ +#define OID_802_11_CURRENTCHANNEL 0x0712 + +#endif /* SNMP_SUPPORT */ + +/*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_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 DOT11R_FT_SUPPORT +#define OID_802_11R_SUPPORT 0x0780 +#define OID_802_11R_MDID 0x0781 +#define OID_802_11R_R0KHID 0x0782 +#define OID_802_11R_RIC 0x0783 +#define OID_802_11R_OTD 0x0784 +#define OID_802_11R_INFO 0x0785 + +#define RT_OID_802_11R_SUPPORT (OID_GET_SET_TOGGLE | OID_802_11R_SUPPORT) +#define RT_OID_802_11R_MDID (OID_GET_SET_TOGGLE | OID_802_11R_MDID) +#define RT_OID_802_11R_R0KHID (OID_GET_SET_TOGGLE | OID_802_11R_R0KHID) +#define RT_OID_802_11R_RIC (OID_GET_SET_TOGGLE | OID_802_11R_RIC) +#define RT_OID_802_11R_OTD (OID_GET_SET_TOGGLE | OID_802_11R_OTD) +#define RT_OID_802_11R_INFO (OID_GET_SET_TOGGLE | OID_802_11R_INFO) +#endif /* DOT11R_FT_SUPPORT */ + + +#ifdef WSC_NFC_SUPPORT +#define RT_OID_NFC_STATUS 0x0930 +#endif /* WSC_NFC_SUPPORT */ + +/* New for MeetingHouse Api support */ +#define OID_MH_802_1X_SUPPORTED 0xFFEDC100 + +/* MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI. Don't change this definition!!! */ +typedef union _HTTRANSMIT_SETTING { +#ifdef RT_BIG_ENDIAN + struct { + USHORT MODE:3; /* Use definition MODE_xxx. */ + USHORT iTxBF:1; + USHORT eTxBF:1; + USHORT STBC:1; /* only support in HT/VHT mode with MCS0~7 */ + USHORT ShortGI:1; + USHORT BW:2; /* channel bandwidth 20MHz/40/80 MHz */ + USHORT ldpc:1; + USHORT MCS:6; /* MCS */ + } field; +#else + struct { + USHORT MCS:6; + USHORT ldpc:1; + USHORT BW:2; + USHORT ShortGI:1; + USHORT STBC:1; + USHORT eTxBF:1; + USHORT iTxBF:1; + USHORT MODE:3; + } field; +#endif + USHORT word; +} HTTRANSMIT_SETTING, *PHTTRANSMIT_SETTING; + +typedef enum _RT_802_11_PREAMBLE { + Rt802_11PreambleLong, + Rt802_11PreambleShort, + Rt802_11PreambleAuto +} RT_802_11_PREAMBLE, *PRT_802_11_PREAMBLE; + +typedef enum _RT_802_11_PHY_MODE { + PHY_11BG_MIXED = 0, + PHY_11B = 1, + PHY_11A = 2, + PHY_11ABG_MIXED = 3, + PHY_11G = 4, +#ifdef DOT11_N_SUPPORT + PHY_11ABGN_MIXED = 5, /* both band 5 */ + PHY_11N_2_4G = 6, /* 11n-only with 2.4G band 6 */ + PHY_11GN_MIXED = 7, /* 2.4G band 7 */ + PHY_11AN_MIXED = 8, /* 5G band 8 */ + PHY_11BGN_MIXED = 9, /* if check 802.11b. 9 */ + PHY_11AGN_MIXED = 10, /* if check 802.11b. 10 */ + PHY_11N_5G = 11, /* 11n-only with 5G band 11 */ +#endif /* DOT11_N_SUPPORT */ +#ifdef DOT11_VHT_AC + PHY_11VHT_N_ABG_MIXED = 12, /* 12 -> AC/A/AN/B/G/GN mixed */ + PHY_11VHT_N_AG_MIXED = 13, /* 13 -> AC/A/AN/G/GN mixed */ + PHY_11VHT_N_A_MIXED = 14, /* 14 -> AC/AN/A mixed in 5G band */ + PHY_11VHT_N_MIXED = 15, /* 15 -> AC/AN mixed in 5G band */ +#endif /* DOT11_VHT_AC */ + PHY_MODE_MAX, +} RT_802_11_PHY_MODE; + +#ifdef DOT11_VHT_AC +#define PHY_MODE_IS_5G_BAND(__Mode) \ + ((__Mode == PHY_11A) || \ + (__Mode == PHY_11ABG_MIXED) || \ + (__Mode == PHY_11ABGN_MIXED) || \ + (__Mode == PHY_11AN_MIXED) || \ + (__Mode == PHY_11AGN_MIXED) || \ + (__Mode == PHY_11N_5G) ||\ + (__Mode == PHY_11VHT_N_MIXED) ||\ + (__Mode == PHY_11VHT_N_A_MIXED)) +#elif defined(DOT11_N_SUPPORT) +#define PHY_MODE_IS_5G_BAND(__Mode) \ + ((__Mode == PHY_11A) || \ + (__Mode == PHY_11ABG_MIXED) || \ + (__Mode == PHY_11ABGN_MIXED) || \ + (__Mode == PHY_11AN_MIXED) || \ + (__Mode == PHY_11AGN_MIXED) || \ + (__Mode == PHY_11N_5G)) +#else + +#define PHY_MODE_IS_5G_BAND(__Mode) \ + ((__Mode == PHY_11A) || \ + (__Mode == PHY_11ABG_MIXED)) +#endif /* DOT11_N_SUPPORT */ + +/* put all proprietery for-query objects here to reduce # of Query_OID */ +typedef struct _RT_802_11_LINK_STATUS { + ULONG CurrTxRate; /* in units of 0.5Mbps */ + ULONG ChannelQuality; /* 0..100 % */ + ULONG TxByteCount; /* both ok and fail */ + ULONG RxByteCount; /* both ok and fail */ + ULONG CentralChannel; /* 40MHz central channel number */ +} RT_802_11_LINK_STATUS, *PRT_802_11_LINK_STATUS; + +#ifdef SYSTEM_LOG_SUPPORT +typedef struct _RT_802_11_EVENT_LOG { + LARGE_INTEGER SystemTime; /* timestammp via NdisGetCurrentSystemTime() */ + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Event; /* EVENT_xxx */ +} RT_802_11_EVENT_LOG, *PRT_802_11_EVENT_LOG; + +typedef struct _RT_802_11_EVENT_TABLE { + ULONG Num; + ULONG Rsv; /* to align Log[] at LARGE_INEGER boundary */ + RT_802_11_EVENT_LOG Log[MAX_NUMBER_OF_EVENT]; +} RT_802_11_EVENT_TABLE, *PRT_802_11_EVENT_TABLE; +#endif /* SYSTEM_LOG_SUPPORT */ + +/* MIMO Tx parameter, ShortGI, MCS, STBC, etc. these are fields in TXWI. Don't change this definition!!! */ +typedef union _MACHTTRANSMIT_SETTING { + 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_LEN]; + UCHAR Aid; + UCHAR Psm; /* 0:PWR_ACTIVE, 1:PWR_SAVE */ + UCHAR MimoPs; /* 0:MMPS_STATIC, 1:MMPS_DYNAMIC, 3:MMPS_Enabled */ + CHAR AvgRssi0; + CHAR AvgRssi1; + CHAR AvgRssi2; + UINT32 ConnectedTime; + MACHTTRANSMIT_SETTING TxRate; + UINT32 LastRxRate; +} RT_802_11_MAC_ENTRY, *PRT_802_11_MAC_ENTRY; + +typedef struct _RT_802_11_MAC_TABLE { + ULONG Num; + RT_802_11_MAC_ENTRY Entry[MAX_NUMBER_OF_MAC]; +} RT_802_11_MAC_TABLE, *PRT_802_11_MAC_TABLE; + +#ifdef DOT11_N_SUPPORT +#endif /* DOT11_N_SUPPORT */ + +/* structure for query/set hardware register - MAC, BBP, RF register */ +typedef struct _RT_802_11_HARDWARE_REGISTER { + ULONG HardwareType; /* 0:MAC, 1:BBP, 2:RF register, 3:EEPROM */ + ULONG Offset; /* Q/S register offset addr */ + ULONG Data; /* R/W data buffer */ +} RT_802_11_HARDWARE_REGISTER, *PRT_802_11_HARDWARE_REGISTER; + +typedef struct _RT_802_11_AP_CONFIG { + ULONG EnableTxBurst; /* 0-disable, 1-enable */ + ULONG EnableTurboRate; /* 0-disable, 1-enable 72/100mbps turbo rate */ + ULONG IsolateInterStaTraffic; /* 0-disable, 1-enable isolation */ + ULONG HideSsid; /* 0-disable, 1-enable hiding */ + ULONG UseBGProtection; /* 0-AUTO, 1-always ON, 2-always OFF */ + ULONG UseShortSlotTime; /* 0-no use, 1-use 9-us short slot time */ + ULONG Rsv1; /* must be 0 */ + ULONG SystemErrorBitmap; /* ignore upon SET, return system error upon QUERY */ +} RT_802_11_AP_CONFIG, *PRT_802_11_AP_CONFIG; + +/* structure to query/set STA_CONFIG */ +typedef struct _RT_802_11_STA_CONFIG { + ULONG EnableTxBurst; /* 0-disable, 1-enable */ + ULONG EnableTurboRate; /* 0-disable, 1-enable 72/100mbps turbo rate */ + ULONG UseBGProtection; /* 0-AUTO, 1-always ON, 2-always OFF */ + ULONG UseShortSlotTime; /* 0-no use, 1-use 9-us short slot time when applicable */ + ULONG AdhocMode; /* 0-11b rates only (WIFI spec), 1 - b/g mixed, 2 - g only */ + ULONG HwRadioStatus; /* 0-OFF, 1-ON, default is 1, Read-Only */ + ULONG Rsv1; /* must be 0 */ + ULONG SystemErrorBitmap; /* ignore upon SET, return system error upon QUERY */ +} RT_802_11_STA_CONFIG, *PRT_802_11_STA_CONFIG; + +/* */ +/* For OID Query or Set about BA structure */ +/* */ +typedef struct _OID_BACAP_STRUC { + UCHAR RxBAWinLimit; + UCHAR TxBAWinLimit; + UCHAR Policy; /* 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use. other value invalid */ + UCHAR MpduDensity; /* 0: DELAY_BA 1:IMMED_BA (//BA Policy subfiled value in ADDBA frame) 2:BA-not use. other value invalid */ + UCHAR AmsduEnable; /*Enable AMSDU transmisstion */ + UCHAR AmsduSize; /* 0:3839, 1:7935 bytes. UINT MSDUSizeToBytes[] = { 3839, 7935}; */ + UCHAR MMPSmode; /* MIMO power save more, 0:static, 1:dynamic, 2:rsv, 3:mimo enable */ + BOOLEAN AutoBA; /* Auto BA will automatically */ +} OID_BACAP_STRUC, *POID_BACAP_STRUC; + +typedef struct _RT_802_11_ACL_ENTRY { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Rsv; +#ifdef ACL_BLK_COUNT_SUPPORT + ULONG Reject_Count; +#endif/* ACL_BLK_COUNT_SUPPORT*/ +} 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; + +#ifdef MAC_REPEATER_SUPPORT +typedef struct _RT_802_11_REALMAC_ENTRY { + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR bSet; + UCHAR bUsed; +} RT_802_11_REALMAC_ENTRY, *PRT_802_11_REALMAC_ENTRY; + +typedef struct GNU_PACKED _RT_802_11_MACLIST { + ULONG Num; + RT_802_11_REALMAC_ENTRY Entry[MAX_NUMBER_OF_MAC_LIST]; +} RT_802_11_MACLIST, *PRT_802_11_MACLIST; +#endif /* MAC_REPEATER_SUPPORT */ + +typedef struct _RT_802_11_WDS { + ULONG Num; + NDIS_802_11_MAC_ADDRESS Entry[24 /*MAX_NUM_OF_WDS_LINK */ ]; + ULONG KeyLength; + UCHAR KeyMaterial[32]; +} RT_802_11_WDS, *PRT_802_11_WDS; + +typedef struct _RT_802_11_TX_RATES_ { + UCHAR SupRateLen; + UCHAR SupRate[MAX_LENGTH_OF_SUPPORT_RATES]; + UCHAR ExtRateLen; + UCHAR ExtRate[MAX_LENGTH_OF_SUPPORT_RATES]; +} RT_802_11_TX_RATES, *PRT_802_11_TX_RATES; + +/* Definition of extra information code */ +#define GENERAL_LINK_UP 0x0 /* Link is Up */ +#define GENERAL_LINK_DOWN 0x1 /* Link is Down */ +#define HW_RADIO_OFF 0x2 /* Hardware radio off */ +#define SW_RADIO_OFF 0x3 /* Software radio off */ +#define AUTH_FAIL 0x4 /* Open authentication fail */ +#define AUTH_FAIL_KEYS 0x5 /* Shared authentication fail */ +#define ASSOC_FAIL 0x6 /* Association failed */ +#define EAP_MIC_FAILURE 0x7 /* Deauthencation because MIC failure */ +#define EAP_4WAY_TIMEOUT 0x8 /* Deauthencation on 4-way handshake timeout */ +#define EAP_GROUP_KEY_TIMEOUT 0x9 /* Deauthencation on group key handshake timeout */ +#define EAP_SUCCESS 0xa /* EAP succeed */ +#define DETECT_RADAR_SIGNAL 0xb /* Radar signal occur in current channel */ +#define EXTRA_INFO_MAX 0xb /* Indicate Last OID */ + +#define EXTRA_INFO_CLEAR 0xffffffff + +/* This is OID setting structure. So only GF or MM as Mode. This is valid when our wirelss mode has 802.11n in use. */ +typedef struct { + RT_802_11_PHY_MODE PhyMode; /* */ + UCHAR TransmitNo; + UCHAR HtMode; /*HTMODE_GF or HTMODE_MM */ + UINT8 ExtOffset; /*extension channel above or below */ + UCHAR MCS; + UCHAR BW; + UCHAR STBC; + UCHAR SHORTGI; + UCHAR rsv; +} OID_SET_HT_PHYMODE, *POID_SET_HT_PHYMODE; + + +#ifdef LLTD_SUPPORT +typedef struct _RT_LLTD_ASSOICATION_ENTRY { + UCHAR Addr[MAC_ADDR_LEN]; + unsigned short MOR; /* maximum operational rate */ + UCHAR phyMode; +} RT_LLTD_ASSOICATION_ENTRY, *PRT_LLTD_ASSOICATION_ENTRY; + +typedef struct _RT_LLTD_ASSOICATION_TABLE { + unsigned int Num; + RT_LLTD_ASSOICATION_ENTRY Entry[MAX_NUMBER_OF_MAC]; +} RT_LLTD_ASSOICATION_TABLE, *PRT_LLTD_ASSOICATION_TABLE; +#endif /* LLTD_SUPPORT */ + + +#ifdef WSC_INCLUDED +#define RT_WSC_UPNP_EVENT_FLAG 0x109 +#endif /* WSC_INCLUDED */ + + + +/*#define MAX_CUSTOM_LEN 128 */ + + +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; + + +/* 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_LEN]; /* mandatory, AP MAC address */ + UCHAR KeyIndex; /* optional, default is 1 */ + UCHAR bFromUPnP; /* TRUE: This credential is from external UPnP registrar */ + UCHAR Rsvd[2]; /* Make alignment */ +} WSC_CREDENTIAL, *PWSC_CREDENTIAL; + +/* WSC configured profiles */ +typedef struct _WSC_PROFILE { + UINT ProfileCnt; + UINT ApplyProfileIdx; /* add by johnli, fix WPS test plan 5.1.1 */ + WSC_CREDENTIAL Profile[8]; /* Support up to 8 profiles */ +} WSC_PROFILE, *PWSC_PROFILE; + +#ifdef WAPI_SUPPORT +typedef enum _WAPI_PORT_SECURE_STATE { + WAPI_PORT_NOT_SECURED, + WAPI_PORT_SECURED, +} WAPI_PORT_SECURE_STATE, *PWAPI_PORT_SECURE_STATE; + +typedef struct _WAPI_PORT_SECURE_STRUCT { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT state; +} WAPI_PORT_SECURE_STRUCT, *PWAPI_PORT_SECURE_STRUCT; + +typedef struct _WAPI_UCAST_KEY_STRUCT { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT key_id; + UCHAR PTK[64]; /* unicast and additional key */ +} WAPI_UCAST_KEY_STRUCT, *PWAPI_UCAST_KEY_STRUCT; + +typedef struct _WAPI_MCAST_KEY_STRUCT { + UINT32 key_id; + UCHAR m_tx_iv[16]; + UCHAR key_announce[16]; + UCHAR NMK[16]; /* notify master key */ +} WAPI_MCAST_KEY_STRUCT, *PWAPI_MCAST_KEY_STRUCT; + +typedef struct _WAPI_WIE_STRUCT { + UCHAR addr[6]; + UINT32 wie_len; + UCHAR wie[90]; /* wapi information element */ +} WAPI_WIE_STRUCT, *PWAPI_WIE_STRUCT; + +#endif /* WAPI_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT +typedef struct _FT_CONFIG_INFO { + UCHAR MdId[2]; + UCHAR R0KHId[49]; + UCHAR R0KHIdLen; + BOOLEAN FtSupport; + BOOLEAN FtRicSupport; + BOOLEAN FtOtdSupport; +} FT_CONFIG_INFO, *PFT_CONFIG_INFO; +#endif /* DOT11R_FT_SUPPORT */ + + +#ifdef APCLI_SUPPORT +#endif /* APCLI_SUPPORT */ + + + + + + +#ifdef AIRPLAY_SUPPORT +#define OID_AIRPLAY_IE_INSERT (0x0872) +#define OID_AIRPLAY_ENABLE (0x0873) +#endif/* AIRPLAY_SUPPORT*/ + +enum { + OID_WIFI_TEST_BBP = 0x1000, + OID_WIFI_TEST_RF = 0x1001, + OID_WIFI_TEST_RF_BANK = 0x1002, + OID_WIFI_TEST_MEM_MAP_INFO = 0x1003, + OID_WIFI_TEST_BBP_NUM = 0x1004, + OID_WIFI_TEST_RF_NUM = 0x1005, + OID_WIFI_TEST_RF_BANK_OFFSET = 0x1006, + OID_WIFI_TEST_MEM_MAP_NUM = 0x1007, + OID_WIFI_TEST_BBP32 = 0x1008, + OID_WIFI_TEST_MAC = 0x1009, + OID_WIFI_TEST_MAC_NUM = 0x1010, + OID_WIFI_TEST_E2P = 0x1011, + OID_WIFI_TEST_E2P_NUM = 0x1012, + OID_WIFI_TEST_PHY_MODE = 0x1013, + OID_WIFI_TEST_RF_INDEX = 0x1014, + OID_WIFI_TEST_RF_INDEX_OFFSET = 0x1015, +}; + +struct bbp_info { + UINT32 bbp_start; + UINT32 bbp_end; + UINT8 bbp_value[0]; +}; + +struct bbp32_info { + UINT32 bbp_start; + UINT32 bbp_end; + UINT32 bbp_value[0]; +}; + +struct rf_info { + UINT16 rf_start; + UINT16 rf_end; + UINT8 rf_value[0]; +}; + +struct rf_bank_info { + UINT8 rf_bank; + UINT16 rf_start; + UINT16 rf_end; + UINT8 rf_value[0]; +}; + +struct rf_index_info { + UINT8 rf_index; + UINT16 rf_start; + UINT16 rf_end; + UINT32 rf_value[0]; +}; + +struct mac_info { + UINT32 mac_start; + UINT32 mac_end; + UINT32 mac_value[0]; +}; + +struct mem_map_info { + UINT32 base; + UINT16 mem_map_start; + UINT16 mem_map_end; + UINT32 mem_map_value[0]; +}; + +struct e2p_info { + UINT16 e2p_start; + UINT16 e2p_end; + UINT16 e2p_value[0]; +}; + +struct phy_mode_info { + int data_phy; + UINT8 data_bw; + UINT8 data_ldpc; + UINT8 data_mcs; + UINT8 data_gi; + UINT8 data_stbc; +}; + +struct anqp_req_data { + UINT32 ifindex; + UCHAR peer_mac_addr[6]; + UINT32 anqp_req_len; + UCHAR anqp_req[0]; +}; + +struct anqp_rsp_data { + UINT32 ifindex; + UCHAR peer_mac_addr[6]; + UINT16 status; + UINT32 anqp_rsp_len; + UCHAR anqp_rsp[0]; +}; + +struct hs_onoff { + UINT32 ifindex; + UCHAR hs_onoff; + UCHAR event_trigger; + UCHAR event_type; +}; + +struct hs_param_setting { + UINT32 param; + UINT32 value; +}; + + +struct proxy_arp_entry { + UINT32 ifindex; + UCHAR ip_type; + UCHAR from_ds; + UCHAR IsDAD; + UCHAR source_mac_addr[6]; + UCHAR target_mac_addr[6]; + UCHAR ip_addr[0]; +}; + + +struct security_type { + UINT32 ifindex; + UINT8 auth_mode; + UINT8 encryp_type; +}; + +struct wnm_req_data { + UINT32 ifindex; + UCHAR peer_mac_addr[6]; + UINT32 type; + UINT32 wnm_req_len; + UCHAR wnm_req[0]; +}; + +struct qosmap_data { + UINT32 ifindex; + UCHAR peer_mac_addr[6]; + UINT32 qosmap_len; + UCHAR qosmap[0]; +}; + +#ifdef WH_EZ_SETUP +typedef struct GNU_PACKED internet_command_s +{ + BOOLEAN Net_status; + +} internet_command_t, *p_internet_command_t; + +#endif + +#define OID_802_11_WIFI_VER 0x0920 +/*#define OID_802_11_HS_TEST 0x0921*/ +#define OID_802_11_WAPP_SUPPORT_VER 0x0921 +/*#define OID_802_11_HS_IE 0x0922*/ +#define OID_802_11_WAPP_IE 0x0922 +#define OID_802_11_HS_ANQP_REQ 0x0923 +#define OID_802_11_HS_ANQP_RSP 0x0924 +#define OID_802_11_HS_ONOFF 0x0925 +/*#define OID_802_11_HS_PARAM_SETTING 0x0927*/ +#define OID_802_11_WAPP_PARAM_SETTING 0x0927 +#define OID_802_11_WNM_BTM_REQ 0x0928 +#define OID_802_11_WNM_BTM_QUERY 0x0929 +#define OID_802_11_WNM_BTM_RSP 0x093a +#define OID_802_11_WNM_PROXY_ARP 0x093b +#define OID_802_11_WNM_IPV4_PROXY_ARP_LIST 0x093c +#define OID_802_11_WNM_IPV6_PROXY_ARP_LIST 0x093d +#define OID_802_11_SECURITY_TYPE 0x093e +#define OID_802_11_HS_RESET_RESOURCE 0x093f +#define OID_802_11_HS_AP_RELOAD 0x0940 +#define OID_802_11_HS_BSSID 0x0941 +#define OID_802_11_HS_OSU_SSID 0x0942 +//#define OID_802_11_HS_OSU_NONTX 0x0944 +#define OID_802_11_HS_SASN_ENABLE 0x0943 +#define OID_802_11_WNM_NOTIFY_REQ 0x0944 +#define OID_802_11_QOSMAP_CONFIGURE 0x0945 +#define OID_802_11_GET_STA_HSINFO 0x0946 +#define OID_802_11_BSS_LOAD 0x0947 +#define OID_802_11_INTERWORKING_ENABLE 0x0949 + +#define OID_WSC_UUID 0x0990 +#define OID_SET_SSID 0x0992 +#define OID_SET_PSK 0x0993 + +#define OID_GET_CPU_TEMPERATURE 0x09A1 + +#define OID_GET_WSC_PROFILES 0x0994 +#define OID_GET_MISC_CAP 0x0995 +#define OID_GET_HT_CAP 0x0996 +#define OID_GET_VHT_CAP 0x0997 +#define OID_GET_CHAN_LIST 0x0998 +#define OID_GET_OP_CLASS 0x0999 +#define OID_GET_BSS_INFO 0x099A +#define OID_GET_AP_METRICS 0x099B + +#ifdef STA_FORCE_ROAM_SUPPORT +#define OID_FROAM_COMMAND 0x0983 +#define OID_FROAM_EVENT 0x0984 +#endif + +#ifdef AIR_MONITOR +typedef struct GNU_PACKED _mntr_entry_info { + u8 mac[MAC_ADDR_LEN]; + u8 channel; + u8 index; +}mntr_entry_info, *pmntr_entry_info; + +#define OID_AIR_MNTR_ADD_ENTRY 0x0980 +#define OID_AIR_MNTR_DEL_ENTRY 0x0981 +#define OID_AIR_MNTR_SET_RULE 0x0982 +#endif + +#ifdef MBO_SUPPORT +#define OID_802_11_MBO_MSG 0x0953 +#define OID_NEIGHBOR_REPORT 0x0954 +#endif + +#define MAX_CANDIDATE_NUM 5 +#define OP_LEN 16 +#define CH_LEN 30 +#define REQ_LEN 30 +#define SSID_LEN 33 + +#define OID_802_11_RRM_COMMAND 0x094C +#define OID_802_11_RRM_EVENT 0x094D +#define RT_QUERY_RRM_CAPABILITY \ + (OID_GET_SET_FROM_UI|OID_802_11_RRM_COMMAND) + +enum rrm_cmd_subid { + OID_802_11_RRM_CMD_ENABLE = 0x01, + OID_802_11_RRM_CMD_CAP, + OID_802_11_RRM_CMD_SEND_BEACON_REQ, + OID_802_11_RRM_CMD_QUERY_CAP, + OID_802_11_RRM_CMD_SET_BEACON_REQ_PARAM, + OID_802_11_RRM_CMD_SEND_NEIGHBOR_REPORT, + OID_802_11_RRM_CMD_SET_NEIGHBOR_REPORT_PARAM, + OID_802_11_RRM_CMD_HANDLE_NEIGHBOR_REQUEST_BY_DAEMON, +}; + +enum rrm_event_subid { + OID_802_11_RRM_EVT_BEACON_REPORT = 0x01, + OID_802_11_RRM_EVT_NEIGHBOR_REQUEST, +}; +struct wapp_param_setting { + UINT32 param; + UINT32 value; +}; + +typedef struct GNU_PACKED rrm_command_s { + UINT8 command_id; + UINT32 command_len; + UINT8 command_body[0]; +} rrm_command_t, *p_rrm_command_t; + +typedef struct GNU_PACKED rrm_event_s { + UINT8 event_id; + UINT32 event_len; + UINT8 event_body[0]; +} rrm_event_t, *p_rrm_event_t; + +struct GNU_PACKED nr_req_data { + UINT32 ifindex; + UCHAR peer_mac_addr[6]; + UINT32 nr_req_len; + UCHAR nr_req[0]; +}; + +typedef struct GNU_PACKED nr_rsp_data_s { + UINT32 ifindex; + UINT8 dialog_token; + UINT8 peer_address[MAC_ADDR_LEN]; + UINT32 nr_rsp_len; + UINT8 nr_rsp[0]; +} nr_rsp_data_t, *p_nr_rsp_data_t; + +typedef struct GNU_PACKED bcn_req_data_s { + UINT32 ifindex; + UINT8 dialog_token; + UINT8 peer_address[MAC_ADDR_LEN]; + UINT32 bcn_req_len; + UINT8 bcn_req[0]; +} bcn_req_data_t, *p_bcn_req_data_t; + +/** @peer_address: mandatory; sta to send beacon request frame; +* @num_rpt: optional; number of repetitions; +* @regclass: only mandatory when channel is set to 0; operating class; +* @channum: mandatory; channel number; +* @random_ivl: optional; randomization interval; unit ms; +* the upper bound of the random delay to be used prior to make measurement; +* @duration: optional; measurement duration; unit ms; +* @bssid: optional; +* @mode: optional; measurement mode; +* As default value 0 is a valid value in spec, so here need remap the value and the meaning; +* 1 for passive mode; 2 for active mode; 3 for beacon table; +* @req_ssid: optional; subelement SSID; +* @timeout: optional; unit s; +* @rep_conditon: optional; subelement Beacon Reporting Information; +* @ref_value: optional; subelement Beacon Reporting Information; +* condition for report to be issued; +* driver will send timeout event after timeout value if no beacon report received; +* @detail: optional; subelement Reporting Detail; +* As default value 0 is a valid value in spec, so here need remap the value and the meaning; +* 1 for no fixed length fields or elements; +* 2 for all fixed length fields and any requested elements in the request IE; +* 3 for all fixed length fields and elements +* @op_class_len: mandatory only when channel is set to 255; +* @op_class_list: subelement Ap Channel Report; +* @ch_list_len: mandatory only when channel is set to 255; +* @ch_list: subelement Ap Channel Report; +* if you want use all the channels in operating classes then use default value +* otherwise specify all channels you want sta to do measurement +* @request_len: optional; +* @request: subelement Request; only valid when you specify request IDs +*/ +typedef struct GNU_PACKED bcn_req_info_s { + UINT8 peer_address[MAC_ADDR_LEN]; + UINT16 num_rpt; + UINT8 regclass; + UINT8 channum; + UINT16 random_ivl; + UINT16 duration; + UINT8 bssid[MAC_ADDR_LEN]; + UINT8 mode; + UINT8 req_ssid_len; + UINT8 req_ssid[SSID_LEN]; + UINT32 timeout; + UINT8 rep_conditon; + UINT8 ref_value; + UINT8 detail; + UINT8 op_class_len; + UINT8 op_class_list[OP_LEN]; + UINT8 ch_list_len; + UINT8 ch_list[CH_LEN]; + UINT8 request_len; + UINT8 request[REQ_LEN]; +} bcn_req_info, *p_bcn_req_info; + +typedef struct GNU_PACKED bcn_rsp_data_s { + UINT8 dialog_token; + UINT32 ifindex; + UINT8 peer_address[6]; + UINT32 bcn_rsp_len; + UINT8 bcn_rsp[0]; +} bcn_rsp_data_t, *p_bcn_rsp_data_t; + +/** +* @channum: optional; channel number; +* @phytype: optional; PHY type; +* @regclass: optional; operating class; +* @capinfo: optional; Same as AP's Capabilities Information field in Beacon; +* @bssid: mandatory; +* @preference: not used in neighbor report; optional in btm request; +* indicates the network preference for BSS transition to the BSS listed in this +* BSS Transition Candidate List Entries; 0 is a valid value in spec, but here +* need remap its meaning to not include preference IE in neighbor report +* response frame; +* @is_ht: optional; High Throughput; +* @is_vht: optional; Very High Throughput; +* @ap_reachability: optional; indicates whether the AP identified by this BSSID is +* reachable by the STA that requested the neighbor report. For example, +* the AP identified by this BSSID is reachable for the exchange of +* preauthentication frames; +* @security: optional; indicates whether the AP identified by this BSSID supports +* the same security provisioning as used by the STA in its current association; +* @key_scope: optional; indicates whether the AP indicated by this BSSID has the +* same authenticator as the AP sending the report; +* @Mobility: optional; indicate whether the AP represented by this BSSID is +* including an MDE in its Beacon frames and that the contents of that MDE are +* identical to the MDE advertised by the AP sending the report; +*/ +struct GNU_PACKED nr_info { + UINT8 channum; + UINT8 phytype; + UINT8 regclass; + UINT16 capinfo; + UINT8 bssid[MAC_ADDR_LEN]; + UINT8 preference; + UINT8 is_ht; + UINT8 is_vht; + UINT8 ap_reachability; + UINT8 security; + UINT8 key_scope; + UINT8 mobility; +}; + +/** +* @dialogtoken: mandatory; must the same with neighbor request from sta +* or 0 on behalf of automatic report +* @nrresp_info_count: mandatory; the num of neighbor elements;must bigger +* than 0 and not exceeds 5; +* @nrresp_info: info of neighbor elements; mandatory; +*/ +typedef struct GNU_PACKED rrm_nrrsp_info_custom_s { + UINT8 peer_address[MAC_ADDR_LEN]; + UINT8 dialogtoken; + UINT8 nrresp_info_count; + struct nr_info nrresp_info[0]; +} rrm_nrrsp_info_custom_t, *p_rrm_nrrsp_info_custom_t; + + +/*#ifdef WNM_NEW_API*/ +#define URL_LEN 40 + +#define OID_802_11_WNM_COMMAND 0x094A +#define OID_802_11_WNM_EVENT 0x094B +#define RT_QUERY_WNM_CAPABILITY \ + (OID_GET_SET_FROM_UI|OID_802_11_WNM_COMMAND) + + +enum wnm_cmd_subid { + OID_802_11_WNM_CMD_ENABLE = 0x01, + OID_802_11_WNM_CMD_CAP, + OID_802_11_WNM_CMD_SEND_BTM_REQ, + OID_802_11_WNM_CMD_QUERY_BTM_CAP, + OID_802_11_WNM_CMD_SEND_BTM_REQ_IE, + OID_802_11_WNM_CMD_SET_BTM_REQ_PARAM, +}; + +enum wnm_event_subid { + OID_802_11_WNM_EVT_BTM_QUERY = 0x01, + OID_802_11_WNM_EVT_BTM_RSP, +}; + +struct GNU_PACKED wnm_command { + UINT8 command_id; + UINT8 command_len; + UINT8 command_body[0]; +}; + +struct GNU_PACKED wnm_event { + UINT8 event_id; + UINT8 event_len; + UINT8 event_body[0]; +}; + +typedef struct GNU_PACKED btm_req_ie_data_s { + UINT32 ifindex; + UINT8 peer_mac_addr[6]; + UINT8 dialog_token; + UINT32 timeout; + UINT32 btm_req_len; + UINT8 btm_req[0]; +} btm_req_ie_data_t, *p_btm_req_ie_data_t; + +struct GNU_PACKED btm_req_data { + UINT32 ifindex; + UCHAR peer_mac_addr[6]; + UINT32 btm_req_len; + UCHAR btm_req[0]; +}; + +struct GNU_PACKED btm_query_data { + UINT32 ifindex; + UCHAR peer_mac_addr[6]; + UINT32 btm_query_len; + UCHAR btm_query[0]; +}; + +struct GNU_PACKED btm_rsp_data { + UINT32 ifindex; + UCHAR peer_mac_addr[6]; + UINT32 btm_rsp_len; + UCHAR btm_rsp[0]; +}; + +/** +* @sta_mac: mandatory; mac of sta sending the frame; +* @dialogtoken: optional; dialog token; +* @reqmode: optional; request mode; +* @disassoc_timer: optional; the time(TBTTs) after which the AP will issue +* a Disassociation frame to this STA; +* @valint: optional; the number of beacon transmission times (TBTTs) until +* the BSS transition candidate list is no longer valid; +* @timeout: optional; driver will send timeout event after timeout value +* if no beacon report received; unit s; +* @TSF: optional; BSS Termination TSF; +* @duration: optional; number of minutes for which the BSS is not present; +* @url_len: optional; +* @url: optional; only valid when you specify url; +* @num_candidates: mandatory; num of candidates; +* @candidates: mandatory; request mode; the num of candidate is no larger +* than 5; +*/ +typedef struct GNU_PACKED btm_reqinfo_s { + UINT8 sta_mac[MAC_ADDR_LEN]; + UINT8 dialogtoken; + UINT8 reqmode; + UINT16 disassoc_timer; + UINT8 valint; + UINT32 timeout; + UINT64 TSF; + UINT16 duration; + UINT8 url_len; + UINT8 url[URL_LEN]; + UINT8 num_candidates; + struct nr_info candidates[0]; +} btm_reqinfo_t, *p_btm_reqinfo_t; + + +#ifdef WH_EZ_SETUP +enum { + OID_WH_EZ_ENABLE = 0x2000, + OID_WH_EZ_CONF_STATUS = 0x2001, + OID_WH_EZ_GROUP_ID = 0x2002, + OID_WH_EZ_GEN_GROUP_ID = 0x2003, + OID_WH_EZ_RSSI_THRESHOLD = 0x2004, + OID_WH_EZ_INTERNET_COMMAND = 0x2005, + OID_WH_EZ_GET_GUI_INFO = 0x2006, +#ifdef EZ_PUSH_BW_SUPPORT + OID_WH_EZ_PUSH_BW = 0x2007, +#endif + OID_WH_EZ_CUSTOM_DATA_CMD = 0x2008, + OID_WH_EZ_CUSTOM_DATA_EVENT = 0x2009 +}; +#define OID_WH_EZ_UPDATE_STA_INFO 0x2010 +#define OID_WH_EZ_MAN_DEAMON_EVENT 0x200A +#define OID_WH_EZ_MAN_TRIBAND_EZ_DEVINFO_EVENT 0x200B +#define OID_WH_EZ_MAN_TRIBAND_NONEZ_DEVINFO_EVENT 0x200c +#define OID_WH_EZ_MAN_TRIBAND_SCAN_COMPLETE_EVENT 0x200d +#define OID_WH_EZ_MAN_PLUS_NONMAN_EZ_DEVINFO_EVENT 0x200E +#define OID_WH_EZ_MAN_PLUS_NONMAN_NONEZ_DEVINFO_EVENT 0x200F +#define OID_WH_EZ_MAN_CONF_EVENT 0x2011 +#define OID_WH_EZ_REGROUP_COMMAND 0x2012 +#define OID_WH_EZ_REGROUP_EVENT 0x2013 + + +#endif /* WH_EZ_SETUP */ + +#ifdef ACS_CTCC_SUPPORT +#define OID_802_11_GET_ACS_CHANNEL_SCORE 0x2014 +typedef struct _AUTO_CH_SEL_SCORE{ + UINT32 Score; + UINT32 Channel; +} AUTO_CH_SEL_SCORE, *PAUTO_CH_SEL_SCORE;; +typedef struct _ACS_CHANNEL_SCORE{ + AUTO_CH_SEL_SCORE AcsChannelScore[MAX_NUM_OF_CHANNELS+1]; + UINT32 AcsAlg; +} ACS_CHANNEL_SCORE, *PACS_CHANNEL_SCORE; +#endif + +#ifdef MIXMODE_SUPPORT +#define OID_MIX_MODE_BASE 0x1280 +enum mix_mode_subcmd_oid { + OID_SUBCMD_SET_MIXMODE, + OID_SUBCMD_GET_RSSI, + OID_SUBCMD_CANCEL_MIXMODE, + NUM_OID_SUBCMD_MIXMODE, + OID_SUBCMD_MIXMODE_MAX = NUM_OID_SUBCMD_MIXMODE - 1 +}; +#define OID_SET_MIXMODE (OID_MIX_MODE_BASE | OID_SUBCMD_SET_MIXMODE) +#define OID_MIXMODE_GET_RSSI (OID_MIX_MODE_BASE | OID_SUBCMD_GET_RSSI) +#define OID_CANCEL_MIXMODE (OID_MIX_MODE_BASE | OID_SUBCMD_CANCEL_MIXMODE) +#define RT_OID_SET_MIXMODE (OID_GET_SET_TOGGLE | OID_SET_MIXMODE) +#define RT_OID_CANCEL_MIXMODE (OID_GET_SET_TOGGLE | OID_CANCEL_MIXMODE) +#define RT_MIX_MODE_EVENT_FLAG 0x1810 +#endif /* MIXMODE_SUPPORT */ + +#ifdef APCLI_OWE_SUPPORT +#define OID_802_11_OWE_TRANS_COMMAND 0x0990 +#define OID_802_11_OWE_TRANS_EVENT 0x0991 + +enum owe_event_subid { + OID_802_11_OWE_EVT_DIFF_BAND = 0x01, + OID_802_11_OWE_EVT_SAME_BAND_DIFF_CHANNEL = 0x02, +}; + +struct GNU_PACKED owe_event { + UINT8 event_id; + UINT32 event_len; + UINT8 event_body[0]; +}; + +struct GNU_PACKED owe_trans_channel_change_info { + UCHAR ifname[IFNAMSIZ]; + UCHAR pair_bssid[MAC_ADDR_LEN]; + UCHAR pair_ssid[NDIS_802_11_LENGTH_SSID]; + UCHAR pair_ssid_len; + UCHAR pair_band; + UCHAR pair_ch; +}; + +#endif + + +#endif /* _OID_H_ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/bb_soc.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/bb_soc.h new file mode 100644 index 000000000..3f72aae92 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/bb_soc.h @@ -0,0 +1,55 @@ + +#ifndef __BBU_SOC_H__ +#define __BBU_SOC_H__ + + +//#include "rt_config.h" + + +#define POLLING_MODE_DETECT_INTV 300 +extern void os_TCIfQuery (unsigned short query_id, void* result, void* result2); + + +typedef struct _BBUPollingMode{ + RALINK_TIMER_STRUCT PollingModeDetect; + BOOLEAN PollingModeDetectRunning; + struct work_struct PollingDataBH; + UINT32 pAd_va; + NDIS_SPIN_LOCK PollingModeLock; +}BBUPollingMode,*PBBUPollingMode; + +extern void tc3162_enable_irq(unsigned int irq); +extern void tc3162_disable_irq(unsigned int irq); +extern VOID PeriodicPollingModeDetect( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +DECLARE_TIMER_FUNCTION(PeriodicPollingModeDetect); + +extern VOID PollingModeIsr(struct work_struct *work); +/* + ======================================================================== + + Routine Description: + Trendchip DMT Trainning status detect + + Arguments: + data Point to RTMP_ADAPTER + + Return Value: + NONE + + Note: + + ======================================================================== +*/ +extern void pcieReset(void); +extern int pcieRegInitConfig(void); +extern void BBU_PCIE_Init(void); +extern VOID BBUPollingModeClose(IN RTMP_ADAPTER *pAd); +extern VOID BBUPollingModeInit(IN RTMP_ADAPTER *pAd); +extern VOID BBUPollingModeStart(IN RTMP_ADAPTER *pAd); +extern VOID BBUPrepareMAC(IN RTMP_ADAPTER *pAd, PUCHAR macaddr ); +#endif + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/pkt_meta.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/pkt_meta.h new file mode 100644 index 000000000..2c5471641 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/pkt_meta.h @@ -0,0 +1,413 @@ +/* + +*/ + +#define MIN_NET_DEVICE_FOR_MBSSID 0x00 /*0x00,0x10,0x20,0x30 */ +#define MIN_NET_DEVICE_FOR_WDS 0x10 /*0x40,0x50,0x60,0x70 */ +#define MIN_NET_DEVICE_FOR_APCLI 0x20 +#define MIN_NET_DEVICE_FOR_MESH 0x30 + + +#define NET_DEVICE_REAL_IDX_MASK 0x0f /* for each operation mode, we maximum support 15 entities. */ + + +/****************************************************************************** + Packet Meta info fields + NOTE: the meta info may stored in some os-dependent packet buffer and may + have extra limitations. + 1. Linux: + a).re-use sk_budd->cb[] + b).Max space of skb->cb = 48B = [CB_OFF+38] + 2. VxWorks: + a). + b).Max space: 32!! +******************************************************************************/ +/* [CB_OFF + 0] */ +/* User Priority */ +#define RTMP_SET_PACKET_UP(_p, _prio) (PACKET_CB(_p, 0) = _prio) +#define RTMP_GET_PACKET_UP(_p) (PACKET_CB(_p, 0)) + +/* [CB_OFF + 1] */ +/* Fragment # */ +#define RTMP_SET_PACKET_FRAGMENTS(_p, _num) (PACKET_CB(_p, 1) = _num) +#define RTMP_GET_PACKET_FRAGMENTS(_p) (PACKET_CB(_p, 1)) + +/* [CB_OFF + 2] */ +/* + 0x0 ~ 0xff: index mapping to MAC_TABLE_ENTRY + for Tx, search by eth_hdr.addr1 + for Rx, get from ASIC(RxWI)/search by wlan_hdr.addr2 +*/ +#define RTMP_SET_PACKET_WCID(_p, _wdsidx) (PACKET_CB(_p, 2) = _wdsidx) +#define RTMP_GET_PACKET_WCID(_p) (PACKET_CB(_p, 2)) + + +/* [CB_OFF + 3] */ +/* From which Interface, wdev index */ +#define RTMP_SET_PACKET_WDEV(_p, _wdev_idx) (PACKET_CB(_p, 3) = _wdev_idx) +#define RTMP_GET_PACKET_WDEV(_p) (PACKET_CB(_p, 3)) + + + +/* [CB_OFF + 4] */ +/* If this flag is set, it indicates that this EAPoL frame MUST be clear. */ +#define RTMP_SET_PACKET_CLEAR_EAP_FRAME(_p, _flg) (PACKET_CB(_p, 4) = _flg) +#define RTMP_GET_PACKET_CLEAR_EAP_FRAME(_p) (PACKET_CB(_p, 4)) + + +/* [CB_OFF + 5] */ +#define RTMP_SET_PACKET_MOREDATA(_p, _morebit) (PACKET_CB(_p, 5) = _morebit) +#define RTMP_GET_PACKET_MOREDATA(_p) (PACKET_CB(_p, 5)) + + +/* [CB_OFF + 6] */ +/* + Sepcific Pakcet Type definition +*/ +#define RTMP_PACKET_SPECIFIC_CB_OFFSET 6 + +#define RTMP_PACKET_SPECIFIC_DHCP 0x01 +#define RTMP_PACKET_SPECIFIC_EAPOL 0x02 +#define RTMP_PACKET_SPECIFIC_IPV4 0x04 +#define RTMP_PACKET_SPECIFIC_WAI 0x08 +#define RTMP_PACKET_SPECIFIC_VLAN 0x10 +#define RTMP_PACKET_SPECIFIC_LLCSNAP 0x20 +#define RTMP_PACKET_SPECIFIC_TDLS 0x40 +#define RTMP_PACKET_SPECIFIC_DISASSOC 0x80 + +/* Specific */ +#define RTMP_SET_PACKET_SPECIFIC(_p, _flg) (PACKET_CB(_p, 6) = _flg) + +/* DHCP */ +#define RTMP_SET_PACKET_DHCP(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 6) |= (RTMP_PACKET_SPECIFIC_DHCP); \ + else \ + PACKET_CB(_p, 6) &= (~RTMP_PACKET_SPECIFIC_DHCP); \ + }while(0) +#define RTMP_GET_PACKET_DHCP(_p)\ + (PACKET_CB(_p, 6) & RTMP_PACKET_SPECIFIC_DHCP) + +/* EAPOL */ +#define RTMP_SET_PACKET_EAPOL(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 6) |= (RTMP_PACKET_SPECIFIC_EAPOL); \ + else \ + PACKET_CB(_p, 6) &= (~RTMP_PACKET_SPECIFIC_EAPOL); \ + }while(0) +#define RTMP_GET_PACKET_EAPOL(_p)\ + (PACKET_CB(_p, 6) & RTMP_PACKET_SPECIFIC_EAPOL) + +/* WAI */ +#define RTMP_SET_PACKET_WAI(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 6) |= (RTMP_PACKET_SPECIFIC_WAI); \ + else \ + PACKET_CB(_p, 6) &= (~RTMP_PACKET_SPECIFIC_WAI); \ + }while(0) +#define RTMP_GET_PACKET_WAI(_p) \ + (PACKET_CB(_p, 6) & RTMP_PACKET_SPECIFIC_WAI) + +#define RTMP_GET_PACKET_FORCE_TX(_p)\ + (PACKET_CB(_p, 6) & (RTMP_PACKET_SPECIFIC_EAPOL | \ + RTMP_PACKET_SPECIFIC_WAI)) + +#define RTMP_GET_PACKET_LOWRATE(_p) \ + (PACKET_CB(_p, 6) & (RTMP_PACKET_SPECIFIC_EAPOL |\ + RTMP_PACKET_SPECIFIC_DHCP |\ + RTMP_PACKET_SPECIFIC_WAI)) + +/* VLAN */ +#define RTMP_SET_PACKET_VLAN(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 6) |= (RTMP_PACKET_SPECIFIC_VLAN); \ + else \ + PACKET_CB(_p, 6) &= (~RTMP_PACKET_SPECIFIC_VLAN); \ + }while(0) +#define RTMP_GET_PACKET_VLAN(_p) \ + (PACKET_CB(_p, 6) & RTMP_PACKET_SPECIFIC_VLAN) + +/* LLC/SNAP */ +#define RTMP_SET_PACKET_LLCSNAP(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 6) |= (RTMP_PACKET_SPECIFIC_LLCSNAP); \ + else \ + PACKET_CB(_p, 6) &= (~RTMP_PACKET_SPECIFIC_LLCSNAP); \ + }while(0) + +#define RTMP_GET_PACKET_LLCSNAP(_p) \ + (PACKET_CB(_p, 6) & RTMP_PACKET_SPECIFIC_LLCSNAP) + +/* IP */ +#define RTMP_SET_PACKET_IPV4(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 6) |= (RTMP_PACKET_SPECIFIC_IPV4); \ + else \ + PACKET_CB(_p, 6) &= (~RTMP_PACKET_SPECIFIC_IPV4); \ + }while(0) + +#define RTMP_GET_PACKET_IPV4(_p) \ + (PACKET_CB(_p, 6) & RTMP_PACKET_SPECIFIC_IPV4) + +/* TDLS */ +#define RTMP_SET_PACKET_TDLS_MMPDU(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 6) |= (RTMP_PACKET_SPECIFIC_TDLS); \ + else \ + PACKET_CB(_p, 6) &= (~RTMP_PACKET_SPECIFIC_TDLS); \ + }while(0) + +#define RTMP_GET_PACKET_TDLS_MMPDU(_p) \ + (PACKET_CB(_p, 6) & RTMP_PACKET_SPECIFIC_TDLS) + +/* DISASSOC */ +#define RTMP_SET_PACKET_DISASSOC(_p, _flg) \ + do{ \ + if (_flg) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) |= (RTMP_PACKET_SPECIFIC_DISASSOC); \ + else \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11]) &= (~RTMP_PACKET_SPECIFIC_DISASSOC); \ + }while(0) +#define RTMP_GET_PACKET_DISASSOC(_p) \ + (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+11] & RTMP_PACKET_SPECIFIC_DISASSOC) + +#define RTMP_SET_PACKET_ICMP(_p, _flg) (PACKET_CB(_p, 7) = _flg) +#define RTMP_GET_PACKET_ICMP(_p) (PACKET_CB(_p, 7)) + +/* [CB_OFF + 7] */ + + +/* [CB_OFF + 8 ~ 9] */ +#ifdef UAPSD_SUPPORT +/* if we queue a U-APSD packet to any software queue, we will set the U-APSD + flag and its physical queue ID for it */ +#define RTMP_SET_PACKET_UAPSD(_p, _flg_uapsd, _que_id) \ + (PACKET_CB(_p, 8) = ((_flg_uapsd<<7) | _que_id)) + +#define RTMP_SET_PACKET_QOS_NULL(_p) (PACKET_CB(_p, 8) = 0xff) +#define RTMP_GET_PACKET_QOS_NULL(_p) (PACKET_CB(_p, 8)) +#define RTMP_SET_PACKET_NON_QOS_NULL(_p) (PACKET_CB(_p, 8) = 0x00) +#define RTMP_GET_PACKET_UAPSD_Flag(_p) ((PACKET_CB(_p, 8) & 0x80) >> 7) +#define RTMP_GET_PACKET_UAPSD_QUE_ID(_p) (PACKET_CB(_p, 8) & 0x7f) + +#define RTMP_SET_PACKET_EOSP(_p, _flg) (PACKET_CB(_p, 9) = _flg) +#define RTMP_GET_PACKET_EOSP(_p) (PACKET_CB(_p, 9)) +#endif /* UAPSD_SUPPORT */ + + +/* [CB_OFF + 10 ~ 11] */ +#define RTMP_SET_PACKET_PROTOCOL(_p, _protocol) {\ + (PACKET_CB(_p, 10) = (UINT8)((_protocol) & 0x00ff)); \ + (PACKET_CB(_p, 11) = (UINT8)(((_protocol) & 0xff00) >> 8)); \ +} + +#define RTMP_GET_PACKET_PROTOCOL(_p) \ + ((((UINT16)PACKET_CB(_p, 11)) << 8) \ + | ((UINT16)PACKET_CB(_p, 10))) + + +/* [CB_OFF + 12] */ +#define RTMP_SET_PACKET_TXTYPE(_p, _mode) (PACKET_CB(_p, 12) = _mode) +#define RTMP_GET_PACKET_TXTYPE(_p) (PACKET_CB(_p, 12)) + +/* [CB_OFF + 13] */ +/* TX rate index */ +#define RTMP_SET_PACKET_TXRATE(_p, _rate) (PACKET_CB(_p, 13) = _rate) +#define RTMP_GET_PACKET_TXRATE(_p) (PACKET_CB(_p, 13)) + + +/* [CB_OFF + 14] */ +#ifdef MAC_REPEATER_SUPPORT +#define RTMP_SET_PKT_MAT_FREE(_p, _flg) (PACKET_CB(_p, 14) = (_flg)) +#define RTMP_GET_PKT_MAT_FREE(_p) (PACKET_CB(_p, 14)) +#endif /* MAC_REPEATER_SUPPORT */ + + +/* [CB_OFF + 15 ~ 19] */ + +/* use bit3 of cb[CB_OFF+16] */ +#define RTMP_SET_PACKET_MGMT_PKT(_p, _flg) \ + PACKET_CB(_p, 16) = (PACKET_CB(_p, 16) & 0xF7) | ((_flg & 0x01) << 3); +#define RTMP_GET_PACKET_MGMT_PKT(_p) \ + ((PACKET_CB(_p, 16) & 0x08) >> 3) + +/* use bit0 of cb[CB_OFF+20] */ +#define RTMP_SET_PACKET_MGMT_PKT_DATA_QUE(_p, _flg) \ + PACKET_CB(_p, 20) = (PACKET_CB(_p, 20) & 0xFE) | (_flg & 0x01); +#define RTMP_GET_PACKET_MGMT_PKT_DATA_QUE(_p) \ + (PACKET_CB(_p, 20) & 0x01) + + +/* [CB_OFF+21 ~ 22] */ + + +/* [CB_OFF + 23] */ +/* + * TDLS Sepcific Pakcet Type definition +*/ +#define RTMP_TDLS_SPECIFIC_WAIT_ACK 0x01 +#define RTMP_TDLS_SPECIFIC_NOACK 0x02 +#define RTMP_TDLS_SPECIFIC_PKTQ_HCCA 0x04 +#define RTMP_TDLS_SPECIFIC_PKTQ_EDCA 0x08 + +#define RTMP_SET_PACKET_TDLS_WAIT_ACK(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 23) |= (RTMP_TDLS_SPECIFIC_WAIT_ACK); \ + else \ + PACKET_CB(_p, 23) &= (~RTMP_TDLS_SPECIFIC_WAIT_ACK); \ + }while(0) + +#define RTMP_GET_PACKET_TDLS_WAIT_ACK(_p) (PACKET_CB(_p, 23) & RTMP_TDLS_SPECIFIC_WAIT_ACK) + +#define RTMP_SET_PACKET_TDLS_NO_ACK(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 23) |= (RTMP_TDLS_SPECIFIC_NOACK); \ + else \ + PACKET_CB(_p, 23) &= (~RTMP_TDLS_SPECIFIC_NOACK); \ + }while(0) + +#define RTMP_GET_PACKET_TDLS_NO_ACK(_p) (PACKET_CB(_p, 23) & RTMP_TDLS_SPECIFIC_NOACK) + +#define RTMP_SET_TDLS_SPECIFIC_PACKET(_p, _flg) (PACKET_CB(_p, 23) = _flg) +#define RTMP_GET_TDLS_SPECIFIC_PACKET(_p) (PACKET_CB(_p, 23)) + + +/* [CB_OFF + 24] */ +#ifdef INF_AMAZON_SE +/* [CB_OFF+25], 1B, Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */ +#define RTMP_SET_PACKET_NOBULKOUT(_p, _morebit) (PACKET_CB(_p, 24) = _morebit) +#define RTMP_GET_PACKET_NOBULKOUT(_p) (PACKET_CB(_p, 24)) +#else +#define RTMP_SET_PACKET_ETHTYPE(_p, _morebit) (PACKET_CB(_p, 24) = _morebit) +#define RTMP_GET_PACKET_ETHTYPE(_p) (PACKET_CB(_p, 24)) +#endif /* INF_AMAZON_SE */ +/* Max skb->cb = 48B = [CB_OFF+38] */ + + +/* [CB_OFF + 25] */ +/* ATTENTION PLEASE: +[CB_OFF + 25] have been used for macro MAX_CONTINUOUS_TX_CNT, +this is a feature for AP to continously transmit 21 packets!!!*/ + + +/* [CB_OFF + 26] */ + + +/* [CB_OFF + 27 ~ 31] */ + + +/* [CB_OFF + 32] */ +/* RTS/CTS-to-self protection method */ +#define RTMP_SET_PACKET_RTS(_p, _num) (PACKET_CB(_p, 32) = _num) +#define RTMP_GET_PACKET_RTS(_p) (PACKET_CB(_p, 32)) +/* see RTMP_S(G)ET_PACKET_EMACTAB */ + +/* [CB_OFF + 33] */ +#ifdef CONFIG_5VT_ENHANCE +#define RTMP_SET_PACKET_5VT(_p, _flg) (PACKET_CB(_p, 33) = _flg) +#define RTMP_GET_PACKET_5VT(_p) (PACKET_CB(_p, 33)) +#endif /* CONFIG_5VT_ENHANCE */ + +/* [CB_OFF + 34] */ +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) +/* set link cover packet send by 5G or 2G */ +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +#define PACKET_BAND_CB 36 +#endif +#define RTMP_PACKET_SPECIFIC_2G 0x1 +#define RTMP_PACKET_SPECIFIC_5G 0x2 +#define RTMP_PACKET_SPECIFIC_ETHER 0x4 +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +#define RTMP_PACKET_SPECIFIC_5G_H 0x10 + +#define RTMP_CLEAN_PACKET_BAND(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+36] = 0) +#endif + +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +#define RTMP_SET_PACKET_BAND(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 36) |= (_flg); \ + else \ + PACKET_CB(_p, 36) &= (~_flg); \ + }while(0) + +#define RTMP_GET_PACKET_BAND(_p) (PACKET_CB(_p, 33)) +/* [CB_OFF + 35]: tag the packet received from which net device */ +#define RECV_FROM_CB 37 +#define H_CHANNEL_BIGGER_THAN 100 + +#else +#define RTMP_SET_PACKET_BAND(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 34) |= (_flg); \ + else \ + PACKET_CB(_p, 34) &= (~_flg); \ + }while(0) + +#define RTMP_GET_PACKET_BAND(_p) (PACKET_CB(_p, 34)) +#endif +/* [CB_OFF + 35]: tag the packet received from which net device */ +#if (MT7615_MT7603_COMBO_FORWARDING == 1) + +#define RECV_FROM_CB 37 +#define H_CHANNEL_BIGGER_THAN 100 +#define RTMP_PACKET_RECV_FROM_5G_H_CLIENT 0x10 +#define RTMP_PACKET_RECV_FROM_5G_H_AP 0x20 + +#define RTMP_CLEAN_PACKET_RECV_FROM(_p) (RTPKT_TO_OSPKT(_p)->cb[CB_OFF+37] = 0) +#endif +#define RTMP_PACKET_RECV_FROM_2G_CLIENT 0x1 +#define RTMP_PACKET_RECV_FROM_5G_CLIENT 0x2 +#define RTMP_PACKET_RECV_FROM_2G_AP 0x4 +#define RTMP_PACKET_RECV_FROM_5G_AP 0x8 + +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +#define RTMP_SET_PACKET_RECV_FROM(_p, _flg) \ + do{ \ + if (_flg)\ + PACKET_CB(_p, 37) |= (_flg);\ + else\ + PACKET_CB(_p, 37) &= (~_flg);\ + } while (0) + +#define RTMP_GET_PACKET_RECV_FROM(_p) (PACKET_CB(_p, 37)) +#define RTMP_IS_PACKET_APCLI(_p)\ + ((RTPKT_TO_OSPKT(_p)->cb[CB_OFF+37]) &\ + (RTMP_PACKET_RECV_FROM_2G_CLIENT | RTMP_PACKET_RECV_FROM_5G_CLIENT | RTMP_PACKET_RECV_FROM_5G_H_CLIENT)) +#define RTMP_IS_PACKET_AP_APCLI(_p) ((RTPKT_TO_OSPKT(_p)->cb[CB_OFF+37]) != 0) + +#else +#define RTMP_SET_PACKET_RECV_FROM(_p, _flg) \ + do{ \ + if (_flg) \ + PACKET_CB(_p, 35) |= (_flg); \ + else \ + PACKET_CB(_p, 35) &= (~_flg); \ + }while(0) + +#define RTMP_GET_PACKET_RECV_FROM(_p) (PACKET_CB(_p, 35)) +#endif + +#endif /* CONFIG_WIFI_PKT_FWD */ +#ifdef MAX_CONTINUOUS_TX_CNT +#define RTMP_SET_PACKET_SWQINDEX_LOW(_p, _flg) (PACKET_CB(_p, 25) = _flg) +#define RTMP_GET_PACKET_SWQINDEX_LOW(_p) (PACKET_CB(_p, 25)) +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +#define RTMP_SET_PACKET_SWQINDEX_HIGH(_p, _flg) (PACKET_CB(_p, 34) = _flg) +#define RTMP_GET_PACKET_SWQINDEX_HIGH(_p) (PACKET_CB(_p, 34)) +#else +#define RTMP_SET_PACKET_SWQINDEX_HIGH(_p, _flg) (PACKET_CB(_p, 37) = _flg) +#define RTMP_GET_PACKET_SWQINDEX_HIGH(_p) (PACKET_CB(_p, 37)) +#endif +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_drv.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_drv.h new file mode 100644 index 000000000..4cb83336f --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_drv.h @@ -0,0 +1,849 @@ +/**************************************************************************** + * 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 */ + + +#if defined(WSC_AP_SUPPORT) || defined(WSC_STA_SUPPORT) +#define WSC_INCLUDED +#endif + +/*#ifdef RTMP_USB_SUPPORT */ +typedef VOID *PUSB_DEV; +typedef VOID *purbb_t; +typedef VOID pregs; +/*typedef struct usb_ctrlrequest devctrlrequest; */ +/*#endif */ + +/*********************************************************************************** + * Profile related sections + ***********************************************************************************/ +#ifdef CONFIG_AP_SUPPORT +#ifdef RTMP_MAC_PCI +#define AP_PROFILE_PATH "/etc/Wireless/RT2860AP/RT2860AP.dat" +#define AP_RTMP_FIRMWARE_FILE_NAME "/etc/Wireless/RT2860AP/RT2860AP.bin" +#define AP_DRIVER_VERSION "4.1.2.0_20190222" +#ifdef MULTIPLE_CARD_SUPPORT +#define CARD_INFO_PATH "/etc/Wireless/RT2860AP/RT2860APCard.dat" +#endif /* MULTIPLE_CARD_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + + + + +#endif /* CONFIG_AP_SUPPORT */ + + + +#ifdef SINGLE_SKU_V2 +#define SINGLE_SKU_TABLE_FILE_NAME "/etc/Wireless/RT2870STA/SingleSKU.dat" +#endif /* SINGLE_SKU_V2 */ + + +/*********************************************************************************** + * Compiler related definitions + ***********************************************************************************/ +#undef __inline +#define __inline static inline +#define IN +#define OUT +#define INOUT +#define NDIS_STATUS INT + + +/*********************************************************************************** + * OS Specific definitions and data structures + ***********************************************************************************/ +typedef void * PPCI_DEV; +typedef void * PNET_DEV; +typedef void * PNDIS_PACKET; +typedef char NDIS_PACKET; +typedef PNDIS_PACKET * PPNDIS_PACKET; +typedef ra_dma_addr_t NDIS_PHYSICAL_ADDRESS; +typedef ra_dma_addr_t * PNDIS_PHYSICAL_ADDRESS; +typedef void * NDIS_HANDLE; +typedef char * PNDIS_BUFFER; + + +/*********************************************************************************** + * Network related constant definitions + ***********************************************************************************/ +#ifndef IFNAMSIZ +#define IFNAMSIZ 16 +#endif + +#define MAC_ADDR_LEN 6 + +#define NDIS_STATUS_SUCCESS 0x00 +#define NDIS_STATUS_FAILURE 0x01 +#define NDIS_STATUS_INVALID_DATA 0x02 +#define NDIS_STATUS_RESOURCES 0x03 + +#define NDIS_SET_PACKET_STATUS(_p, _status) do{} while(0) +#define NdisWriteErrorLogEntry(_a, _b, _c, _d) do{} while(0) + +/* statistics counter */ +#define STATS_INC_RX_PACKETS(_pAd, _dev) +#define STATS_INC_TX_PACKETS(_pAd, _dev) + +#define STATS_INC_RX_BYTESS(_pAd, _dev, len) +#define STATS_INC_TX_BYTESS(_pAd, _dev, len) + +#define STATS_INC_RX_ERRORS(_pAd, _dev) +#define STATS_INC_TX_ERRORS(_pAd, _dev) + +#define STATS_INC_RX_DROPPED(_pAd, _dev) +#define STATS_INC_TX_DROPPED(_pAd, _dev) + + +/*********************************************************************************** + * Ralink Specific network related constant definitions + ***********************************************************************************/ + +#ifdef LIMIT_GLOBAL_SW_QUEUE +#define MAX_PACKETS_IN_QUEUE 1024 +#else /* LIMIT_GLOBAL_SW_QUEUE */ +#ifdef DOT11_VHT_AC +#define MAX_PACKETS_IN_QUEUE 1024 /*(512)*/ +#else +#define MAX_PACKETS_IN_QUEUE (512) +#endif /* DOT11_VHT_AC */ +#endif /* !LIMIT_GLOBAL_SW_QUEUE */ + +/*********************************************************************************** + * OS signaling related constant definitions + ***********************************************************************************/ + +/*********************************************************************************** + * OS file operation related data structure definitions + ***********************************************************************************/ +typedef VOID * RTMP_OS_FD; + +#define IS_FILE_OPEN_ERR(_fd) RtmpOsFileIsErr((_fd)) + +#ifndef O_RDONLY +#define O_RDONLY RTMP_FILE_RDONLY +#endif /* O_RDONLY */ + +#ifndef O_WRONLY +#define O_WRONLY RTMP_FILE_WRONLY +#endif /* O_WRONLY */ + +#ifndef O_CREAT +#define O_CREAT RTMP_FILE_CREAT +#endif /* O_CREAT */ + +#ifndef O_TRUNC +#define O_TRUNC RTMP_FILE_TRUNC +#endif /* O_TRUNC */ + + +/*********************************************************************************** + * OS semaphore related data structure and definitions + ***********************************************************************************/ +#define RTCMDUp RtmpOsCmdUp + + +/*********************************************************************************** + * OS Memory Access related data structure and definitions + ***********************************************************************************/ +#define NdisMoveMemory(Destination, Source, Length) memmove(Destination, Source, Length) +#define NdisCopyMemory(Destination, Source, Length) memcpy(Destination, Source, Length) +#define NdisZeroMemory(Destination, Length) memset(Destination, 0, Length) +#define NdisFillMemory(Destination, Length, Fill) memset(Destination, Fill, Length) +#define NdisCmpMemory(Destination, Source, Length) memcmp(Destination, Source, Length) +#define NdisEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length)) +#define RTMPEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length)) + +#define MlmeAllocateMemory(_pAd, _ppVA) os_alloc_mem(_pAd, _ppVA, MGMT_DMA_BUFFER_SIZE) +#define MlmeFreeMemory(_pAd, _pVA) os_free_mem(_pAd, _pVA) + +#define COPY_MAC_ADDR(Addr1, Addr2) memcpy((Addr1), (Addr2), MAC_ADDR_LEN) + + +/*********************************************************************************** + * OS task related data structure and definitions + ***********************************************************************************/ +#define RTMP_OS_PID ULONG /* value or pointer */ + +#define RTMP_GET_OS_PID(_a, _b) RtmpOsGetPid(&_a, _b); +#define CHECK_TASK_LEGALITY(_task) RtmpOsCheckTaskLegality(_task) +#define ATE_KILL_THREAD_PID RtmpThreadPidKill + +typedef INT (*RTMP_OS_TASK_CALLBACK)(ULONG); + + +/*********************************************************************************** + * IOCTL related definitions and data structures. + **********************************************************************************/ +#define NET_IOCTL VOID +#define PNET_IOCTL VOID * + +/* undef them to avoid compile errors in rt_symb.c */ +#undef EINVAL +#undef EOPNOTSUPP +#undef EFAULT +#undef ENETDOWN +#undef E2BIG +#undef ENOMEM +#undef EAGAIN +#undef ENOTCONN + +#define EINVAL (-RTMP_IO_EINVAL) +#define EOPNOTSUPP (-RTMP_IO_EOPNOTSUPP) +#define EFAULT (-RTMP_IO_EFAULT) +#define ENETDOWN (-RTMP_IO_ENETDOWN) +#define E2BIG (-RTMP_IO_E2BIG) +#define ENOMEM (-RTMP_IO_ENOMEM) +#define EAGAIN (-RTMP_IO_EAGAIN) +#define ENOTCONN (-RTMP_IO_ENOTCONN) + + +/*********************************************************************************** + * Timer related definitions and data structures. + **********************************************************************************/ +#define OS_HZ RtmpOsTickUnitGet() + +typedef void (*TIMER_FUNCTION)(ULONG); + +#define OS_WAIT RtmpOsWait + +#define RTMP_TIME_AFTER RtmpOsTimerAfter +#define RTMP_TIME_BEFORE RtmpOsTimerBefore + +#define ONE_TICK 1 + +#define NdisGetSystemUpTime RtmpOsGetSystemUpTime + + +/*********************************************************************************** + * OS specific cookie data structure binding to RTMP_ADAPTER + ***********************************************************************************/ + +/* do not have compile option in the structure for UTIL module */ +struct os_cookie { +#ifdef RTMP_MAC_PCI + VOID *pci_dev; + VOID *parent_pci_dev; + USHORT DeviceID; +#endif /* RTMP_MAC_PCI */ + + +#ifdef WORKQUEUE_BH + UINT32 pAd_va; +#endif /* WORKQUEUE_BH */ + + RTMP_NET_TASK_STRUCT rx_done_task; + RTMP_NET_TASK_STRUCT cmd_rsp_event_task; + RTMP_NET_TASK_STRUCT mgmt_dma_done_task; + RTMP_NET_TASK_STRUCT ac0_dma_done_task; +#ifdef CONFIG_ATE + RTMP_NET_TASK_STRUCT ate_ac0_dma_done_task; +#endif /* CONFIG_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 wmm1_ac0_dma_done_task; + RTMP_NET_TASK_STRUCT tbtt_task; + +#ifdef MT_MAC + RTMP_NET_TASK_STRUCT mt_mac_int_0_task; + RTMP_NET_TASK_STRUCT mt_mac_int_1_task; + RTMP_NET_TASK_STRUCT mt_mac_int_2_task; + RTMP_NET_TASK_STRUCT mt_mac_int_3_task; + RTMP_NET_TASK_STRUCT mt_mac_int_4_task; + RTMP_NET_TASK_STRUCT bcn_dma_done_task; + RTMP_NET_TASK_STRUCT bmc_dma_done_task; +#endif /*MT_MAC */ + +#ifdef RTMP_MAC_PCI + RTMP_NET_TASK_STRUCT fifo_statistic_full_task; +#ifdef CONFIG_ANDES_SUPPORT + RTMP_NET_TASK_STRUCT rx1_done_task; +#endif /* CONFIG_ANDES_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + +#ifdef UAPSD_SUPPORT + RTMP_NET_TASK_STRUCT uapsd_eosp_sent_task; +#endif /* UAPSD_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef DFS_SUPPORT +#ifdef DFS_SOFTWARE_SUPPORT + RTMP_NET_TASK_STRUCT pulse_radar_detect_task; + RTMP_NET_TASK_STRUCT width_radar_detect_task; +#endif /* DFS_SOFTWARE_SUPPORT */ +#endif /* DFS_SUPPORT */ + +#ifdef CARRIER_DETECTION_SUPPORT + RTMP_NET_TASK_STRUCT carrier_sense_task; +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef DFS_SUPPORT + RTMP_NET_TASK_STRUCT dfs_task; +#endif /* DFS_SUPPORT */ + +#endif /* CONFIG_AP_SUPPORT */ + + + RTMP_OS_PID apd_pid; /*802.1x daemon pid */ + unsigned long apd_pid_nr; +#ifdef CONFIG_AP_SUPPORT +#ifdef IAPP_SUPPORT +/* RT_SIGNAL_STRUC RTSignal; */ + RTMP_OS_PID IappPid; /*IAPP daemon pid */ + unsigned long IappPid_nr; +#endif /* IAPP_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +#ifdef WAPI_SUPPORT + RTMP_OS_PID wapi_pid; /*wapi daemon pid */ + unsigned long wapi_pid_nr; +#endif /* WAPI_SUPPORT */ + INT ioctl_if_type; + INT ioctl_if; +}; + +typedef struct os_cookie * POS_COOKIE; + + +/*********************************************************************************** + * OS debugging and printing related definitions and data structure + ***********************************************************************************/ +#define PRINT_MAC(addr) \ + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] + +#ifdef DBG +extern ULONG RTDebugLevel; +extern ULONG RTDebugFunc; + +#if defined(MT7603_FPGA) || defined(MT7628_FPGA) +#define DBGPRINT_RAW(Level, Fmt) \ +do{ \ + ULONG __gLevel = (Level) & 0xff;\ + ULONG __fLevel = ((Level) & 0xffffff00);\ + if (((RTDebugLevel == RT_DEBUG_FPGA) && (__gLevel == RTDebugLevel)) || ((RTDebugLevel != RT_DEBUG_FPGA) && (__gLevel <= RTDebugLevel))) \ + { \ + if ((RTDebugFunc == 0) || \ + ((RTDebugFunc != 0) && (((__fLevel & RTDebugFunc)!= 0) || (__gLevel <= RT_DEBUG_ERROR))))\ + printk Fmt; \ + } \ +}while(0) + +#else +#define DBGPRINT_RAW(Level, Fmt) \ +do{ \ + ULONG __gLevel = (Level) & 0xff;\ + ULONG __fLevel = ((Level) & 0xffffff00);\ + if (__gLevel <= RTDebugLevel) \ + { \ + if ((RTDebugFunc == 0) || \ + ((RTDebugFunc != 0) && (((__fLevel & RTDebugFunc)!= 0) || (__gLevel <= RT_DEBUG_ERROR))))\ + printk Fmt; \ + } \ +}while(0) +#endif /* MT7603_FPGA */ + +#define DBGPRINT(Level, Fmt) DBGPRINT_RAW(Level, Fmt) + + +#define DBGPRINT_ERR(Fmt) \ +{ \ + printk("ERROR!!! "); \ + printk Fmt; \ +} + +#define DBGPRINT_S(Fmt) \ +{ \ + printk Fmt; \ +} +#else +#define DBGPRINT(Level, Fmt) +#define DBGPRINT_RAW(Level, Fmt) +#define DBGPRINT_S(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 DMA_MAPPING_ERROR(_handle, _ptr) \ + dma_mapping_error(&((struct pci_dev *)(_handle))->dev, _ptr) + +#define PCI_UNMAP_SINGLE(_pAd, _ptr, _size, _dir) \ + linux_pci_unmap_single(((POS_COOKIE)(_pAd->OS_Cookie))->pci_dev, _ptr, _size, _dir) + +#define PCI_ALLOC_CONSISTENT(_pci_dev, _size, _ptr) \ + pci_alloc_consistent(_pci_dev, _size, _ptr) + +#define PCI_FREE_CONSISTENT(_pci_dev, _size, _virtual_addr, _physical_addr) \ + pci_free_consistent(_pci_dev, _size, _virtual_addr, _physical_addr) +/*#endif RTMP_MAC_PCI*/ + +#define DEV_ALLOC_SKB(_pAd, _Pkt, _length) \ + _Pkt = RtmpOSNetPktAlloc(_pAd, _length); + +/*#ifdef RTMP_MAC_USB */ +/*#define PCI_MAP_SINGLE(_handle, _ptr, _size, _dir) (ULONG)0 */ +/*#define PCI_UNMAP_SINGLE(_handle, _ptr, _size, _dir) */ +/*#endif RTMP_MAC_USB */ + + +/* + * ULONG + * RTMP_GetPhysicalAddressLow( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + */ +#define RTMP_GetPhysicalAddressLow(phy_addr) (phy_addr) + +/* + * ULONG + * RTMP_GetPhysicalAddressHigh( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + */ +#define RTMP_GetPhysicalAddressHigh(phy_addr) (0) + +/* + * VOID + * RTMP_SetPhysicalAddressLow( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, + * IN ULONG Value); + */ +#define RTMP_SetPhysicalAddressLow(phy_addr, Value) \ + phy_addr = Value; + +/* + * VOID + * RTMP_SetPhysicalAddressHigh( + * IN NDIS_PHYSICAL_ADDRESS PhysicalAddress, + * IN ULONG Value); + */ +#define RTMP_SetPhysicalAddressHigh(phy_addr, Value) + +#define NdisMIndicateStatus(_w, _x, _y, _z) + + + +/*********************************************************************************** + * Device Register I/O Access related definitions and data structures. + **********************************************************************************/ +#define readl RTMP_PCI_Readl +#define readw RTMP_PCI_Readw +#define readb RTMP_PCI_Readb +#define writel RTMP_PCI_Writel +#define writew RTMP_PCI_Writew +#define writeb RTMP_PCI_Writeb + +/* TODO: We can merge two readl to a function to speed up or one real/writel */ + +#ifdef RTMP_MAC_PCI +#if defined(INF_TWINPASS) || defined(INF_DANUBE) || defined(INF_AR9) || defined(IKANOS_VX_1X0) +#define RTMP_IO_FORCE_READ32(_A, _R, _pV) \ +do{ \ + (*_pV = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ + (*_pV = SWAP32(*((UINT32 *)(_pV)))); \ +}while(0) + +#define RTMP_IO_READ32(_A, _R, _pV) \ +do{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + (*_pV = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ + (*_pV = SWAP32(*((UINT32 *)(_pV)))); \ + } \ +}while(0) + +#define RTMP_IO_READ8(_A, _R, _pV) \ +{ \ + (*_pV = readb((void *)((_A)->CSRBaseAddress + (_R)))); \ +} + +#define RTMP_IO_WRITE32(_A, _R, _V) \ +do{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + UINT32 _Val = SWAP32(_V);\ + writel(_Val, (void *)((_A)->CSRBaseAddress + (_R)));\ + }\ +}while(0) + +#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) \ +do{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + (*_pV = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ + } \ + else \ + *_pV = 0; \ +}while(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) \ +{ \ + /* if ((_R) != 0x404)*/ /* TODO:shiang-6590, depends on sw porting guide, don't acccess it now */\ + writel(_V, (void *)((_A)->CSRBaseAddress + (_R))); \ +} + + + +#if defined(BRCM_6358) || defined(RALINK_2880) || defined(RALINK_3052) || defined(RALINK_2883) || defined(RTMP_RBUS_SUPPORT) || defined(MT76x2) +#define RTMP_IO_WRITE8(_A, _R, _V) \ +{ \ + ULONG Val; \ + UCHAR _i; \ + _i = ((_R) & 0x3); \ + Val = readl((void *)((_A)->CSRBaseAddress + ((_R) - _i))); \ + Val = Val & (~(0x000000ff << ((_i)*8))); \ + Val = Val | ((ULONG)(_V) << ((_i)*8)); \ + writel((Val), (void *)((_A)->CSRBaseAddress + ((_R) - _i))); \ +} +#else +#define RTMP_IO_WRITE8(_A, _R, _V) \ +{ \ + writeb((_V), (PUCHAR)((_A)->CSRBaseAddress + (_R))); \ +} +#endif /* #if defined(BRCM_6358) || defined(RALINK_2880) */ + +#define RTMP_IO_WRITE16(_A, _R, _V) \ +{ \ + writew((_V), (PUSHORT)((_A)->CSRBaseAddress + (_R))); \ +} +#endif /* #if defined(INF_TWINPASS) || defined(INF_DANUBE) || defined(IKANOS_VX_1X0) */ +#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 +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +#define CB_LEN 35 +#endif + +#define PACKET_CB_ASSIGN(_p, _offset) \ + (*((UINT8 *)_p + RTPktOffsetCB + _offset)) + +#define PACKET_CB(_p, _offset) \ + (*((UINT8 *)_p + RTPktOffsetCB + CB_OFF + _offset)) + + + + +/*********************************************************************************** + * Other function prototypes definitions + ***********************************************************************************/ +void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); + + + + + + +#ifdef CONFIG_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 */ +#endif /* RTMP_MAC_PCI */ + + +#endif /* CONFIG_ATE */ + + +/* OS definition re-declaration */ +#ifndef NULL +#define NULL 0 +#endif + +#ifndef ETH_P_IPV6 +#define ETH_P_IPV6 0x86DD +#endif + +#ifndef ETH_P_IP +#define ETH_P_IP 0x0800 /* Internet Protocol packet */ +#endif + +#ifndef ETH_ALEN +#define ETH_ALEN 6 +#endif + +#undef KERN_EMERG +#define KERN_EMERG +#undef KERN_WARNING +#define KERN_WARNING + +#undef copy_from_user +#undef copy_to_user + +#define RTMP_OS_MAX_SCAN_DATA_GET RtmpOsMaxScanDataGet +#define vmalloc RtmpOsVmalloc +#define vfree RtmpOsVfree +#define copy_from_user RtmpOsCopyFromUser +#define copy_to_user RtmpOsCopyToUser +#define simple_strtol RtmpOsSimpleStrtol + +#undef atomic_read +#undef atomic_dec +#undef InterlockedExchange +#define atomic_read RtmpOsAtomicRead +#define atomic_dec RtmpOsAtomicDec +#define InterlockedExchange RtmpOsAtomicInterlockedExchange + +extern int sprintf(char * buf, const char * fmt, ...); +extern int sscanf(const char *, const char *, ...); + +#define printk pRaOsOps->ra_printk +#define snprintf pRaOsOps->ra_snprintf + +#define RA_WEXT 0 +#define RA_NETLINK 1 + +#endif /* __RT_LINUX_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_linux.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_linux.h new file mode 100644 index 000000000..59af7ade4 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_linux.h @@ -0,0 +1,1805 @@ +/**************************************************************************** + + 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 + +#ifdef RTMP_SDIO_SUPPORT +/* +#include +#include +#include +*/ +#include +#include +#include +#include +#include +#include +#endif /* RTMP_SDIO_SUPPORT */ + +#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 CONFIG_TRACE_SUPPORT +#include "os/trace_linux.h" +#endif + +#include "link_list.h" + + +#if defined(MAT_SUPPORT) || defined (PREVENT_ARP_SPOOFING) +#include +#include +#include +#endif /* MAT_SUPPORT || PREVENT_ARP_SPOOFING */ + +#ifdef PREVENT_ARP_SPOOFING +#include +#include <../net/bridge/br_private.h> +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35) +#define GET_BR_PORT(netdev) (netdev)->br_port +#else +#define GET_BR_PORT(netdev) br_port_get_rcu(netdev) +#endif +#endif /* PREVENT_ARP_SPOOFING */ + +/* 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" + + +#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 */ + + +#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 + ***********************************************************************************/ + +#define L1_PROFILE_PATH "/etc/wireless/l1profile.dat" + +#define L1PROFILE_INDEX_LEN 10 +#define L1PROFILE_ATTRNAME_LEN 30 +#define L2PROFILE_PATH_LEN 50 + +#ifdef CONFIG_AP_SUPPORT +#ifdef RTMP_MAC_PCI +#if CONFIG_RTPCI_AP_RF_OFFSET == 0x48000 +#define AP_PROFILE_PATH "/etc/Wireless/iNIC/iNIC_ap.dat" +#define AP_RTMP_FIRMWARE_FILE_NAME "/etc_ro/Wireless/iNIC/RT2860AP.bin" +#else + +#if defined(CONFIG_FIRST_IF_MT7603E) || defined(CONFIG_SECOND_IF_MT7603E) +//for SDK's PATH +#define AP_PROFILE_PATH "/etc/Wireless/RT2860/RT2860.dat" +#else /* CONFIG_FIRST_IF_MT7603E */ +//for PC's PATH +#define AP_PROFILE_PATH "/etc/Wireless/RT2860AP/RT2860AP.dat" +#endif /* !CONFIG_FIRST_IF_MT7603E */ +#define AP_RTMP_FIRMWARE_FILE_NAME "/etc/Wireless/RT2860AP/RT2860AP.bin" + +#endif + + +#define AP_DRIVER_VERSION "4.1.2.0" +#ifdef MULTIPLE_CARD_SUPPORT +#define CARD_INFO_PATH "/etc/Wireless/RT2860AP/RT2860APCard.dat" +#endif /* MULTIPLE_CARD_SUPPORT */ +#ifdef WAPP_SUPPORT +#define WAPP_SUPPORT_VERSION "2.0" +#endif/* WAPP_SUPPORT */ + +#endif /* RTMP_MAC_PCI */ + + + +#ifdef SINGLE_SKU_V2 +#define SINGLE_SKU_TABLE_FILE_NAME "/etc/Wireless/RT2860AP/SingleSKU.dat" +#endif /* SINGLE_SKU_V2 */ + +#endif /* CONFIG_AP_SUPPORT */ + + + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +extern const struct iw_handler_def rt28xx_ap_iw_handler_def; +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ + +/*********************************************************************************** + * Compiler related definitions + ***********************************************************************************/ +#undef __inline +#define __inline static inline +#define IN +#define OUT +#define INOUT +#define NDIS_STATUS INT + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) +#define DEVEXIT +#define DEVEXIT_P +#define DEVINIT +#define DEVINITDATA +#else +#define DEVEXIT __devexit +#define DEVEXIT_P __devexit_p +#define DEVINIT __devinit +#define DEVINITDATA __devinitdata +#endif + +/*********************************************************************************** + * OS Specific definitions and data structures + ***********************************************************************************/ +typedef struct net_device_stats NET_DEV_STATS; +typedef struct pci_dev * PPCI_DEV; +typedef struct net_device * PNET_DEV; +typedef struct wireless_dev * PWIRELESS_DEV; +typedef void * PNDIS_PACKET; +typedef char NDIS_PACKET; +typedef PNDIS_PACKET * PPNDIS_PACKET; +typedef ra_dma_addr_t NDIS_PHYSICAL_ADDRESS; +typedef ra_dma_addr_t * PNDIS_PHYSICAL_ADDRESS; +typedef void * NDIS_HANDLE; +typedef char * PNDIS_BUFFER; + +typedef struct ifreq NET_IOCTL; +typedef struct ifreq * PNET_IOCTL; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +typedef struct pid * RTMP_OS_PID; +#else +typedef pid_t RTMP_OS_PID; +#endif + +typedef struct semaphore OS_SEM; + +typedef int (*HARD_START_XMIT_FUNC)(struct sk_buff *skb, struct net_device *net_dev); + +#ifdef RTMP_MAC_PCI +#ifndef PCI_DEVICE +#define PCI_DEVICE(vend,dev) \ + .vendor = (vend), .device = (dev), \ + .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID +#endif /* PCI_DEVICE */ +#endif /* RTMP_MAC_PCI */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define RT_MOD_INC_USE_COUNT() \ + if (!try_module_get(THIS_MODULE)) \ + { \ + DBGPRINT(RT_DEBUG_ERROR, ("%s: cannot reserve module\n", __FUNCTION__)); \ + return -1; \ + } + +#define RT_MOD_DEC_USE_COUNT() module_put(THIS_MODULE); +#else +#define RT_MOD_INC_USE_COUNT() MOD_INC_USE_COUNT; +#define RT_MOD_DEC_USE_COUNT() MOD_DEC_USE_COUNT; +#endif + +#define RTMP_INC_REF(_A) 0 +#define RTMP_DEC_REF(_A) 0 +#define RTMP_GET_REF(_A) 0 + + +#if WIRELESS_EXT >= 12 +/* This function will be called when query /proc */ +struct iw_statistics *rt28xx_get_wireless_stats( + IN struct net_device *net_dev); +#endif + + +/*********************************************************************************** + * Network related constant definitions + ***********************************************************************************/ +#ifndef IFNAMSIZ +#define IFNAMSIZ 16 +#endif + +#define MAC_ADDR_LEN 6 + +#define NDIS_STATUS_SUCCESS 0x00 +#define NDIS_STATUS_FAILURE 0x01 +#define NDIS_STATUS_INVALID_DATA 0x02 +#define NDIS_STATUS_RESOURCES 0x03 + +#define NDIS_SET_PACKET_STATUS(_p, _status) do{} while(0) +#define NdisWriteErrorLogEntry(_a, _b, _c, _d) do{} while(0) + +/* statistics counter */ +#define STATS_INC_RX_PACKETS(_pAd, _dev) +#define STATS_INC_TX_PACKETS(_pAd, _dev) + +#define STATS_INC_RX_BYTESS(_pAd, _dev, len) +#define STATS_INC_TX_BYTESS(_pAd, _dev, len) + +#define STATS_INC_RX_ERRORS(_pAd, _dev) +#define STATS_INC_TX_ERRORS(_pAd, _dev) + +#define STATS_INC_RX_DROPPED(_pAd, _dev) +#define STATS_INC_TX_DROPPED(_pAd, _dev) + + +/*********************************************************************************** + * Ralink Specific network related constant definitions + ***********************************************************************************/ + +#ifdef LIMIT_GLOBAL_SW_QUEUE +#define MAX_PACKETS_IN_QUEUE 1024 +#else /* LIMIT_GLOBAL_SW_QUEUE */ +#ifdef DOT11_VHT_AC +#define MAX_PACKETS_IN_QUEUE 1024 /*(512)*/ +#else +#ifdef MULTI_CLIENT_SUPPORT +#define MAX_PACKETS_IN_QUEUE (8192) //MC +#else +#define MAX_PACKETS_IN_QUEUE (512) +#endif +#endif /* DOT11_VHT_AC */ +#endif /* !LIMIT_GLOBAL_SW_QUEUE */ + +/*********************************************************************************** + * OS signaling related constant definitions + ***********************************************************************************/ + + +/*********************************************************************************** + * OS file operation related data structure definitions + ***********************************************************************************/ +typedef struct file* RTMP_OS_FD; + +typedef struct _OS_FS_INFO_ +{ + int fsuid; + int fsgid; + mm_segment_t fs; +} OS_FS_INFO; + +#define IS_FILE_OPEN_ERR(_fd) ((_fd == NULL) || IS_ERR((_fd))) + + +/*********************************************************************************** + * OS semaphore related data structure and definitions + ***********************************************************************************/ +struct os_lock { + spinlock_t lock; + unsigned long flags; +}; + +typedef spinlock_t OS_NDIS_SPIN_LOCK; + +/* */ +/* spin_lock enhanced for Nested spin lock */ +/* */ +#define OS_NdisAllocateSpinLock(__lock) \ +{ \ + spin_lock_init((spinlock_t *)(__lock)); \ +} + +#define OS_NdisFreeSpinLock(lock) \ + do{}while(0) + + +#define OS_SEM_LOCK(__lock) \ +{ \ + spin_lock_bh((spinlock_t *)(__lock)); \ +} + +#define OS_SEM_UNLOCK(__lock) \ +{ \ + spin_unlock_bh((spinlock_t *)(__lock)); \ +} + + +/* sample, use semaphore lock to replace IRQ lock, 2007/11/15 */ +#ifdef MULTI_CORE_SUPPORT + +#define OS_IRQ_LOCK(__lock, __irqflags) \ +{ \ + if (__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) \ +{ \ + if (__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 = current->thread_pid; rcu_read_unlock(); } while (0) +#ifdef OS_ABL_FUNC_SUPPORT +#define RTMP_GET_OS_PID(_a, _b) RtmpOsGetPid(&_a, _b) +#else +#define RTMP_GET_OS_PID(_a, _b) RT_GET_OS_PID(_a, _b) +#endif +#define GET_PID_NUMBER(_v) pid_nr((_v)) +#define CHECK_PID_LEGALITY(_pid) if (pid_nr((_pid)) > 0) +#define KILL_THREAD_PID(_A, _B, _C) kill_pid((_A), (_B), (_C)) +#else +/*typedef pid_t THREAD_PID; // no use */ +#define THREAD_PID_INIT_VALUE -1 +#define RT_GET_OS_PID(_x, _pid) _x = _pid +#define RTMP_GET_OS_PID(_x, _pid) _x = _pid +#define GET_PID_NUMBER(_v) (_v) +#define CHECK_PID_LEGALITY(_pid) if ((_pid) >= 0) +#define KILL_THREAD_PID(_A, _B, _C) kill_proc((_A), (_B), (_C)) +#endif + +#define ATE_KILL_THREAD_PID(PID) KILL_THREAD_PID(PID, SIGTERM, 1) + +typedef int (*cast_fn)(void *); +typedef INT (*RTMP_OS_TASK_CALLBACK)(ULONG); + +#ifdef WORKQUEUE_BH +typedef struct work_struct OS_NET_TASK_STRUCT; +typedef struct work_struct *POS_NET_TASK_STRUCT; +#else +typedef struct tasklet_struct OS_NET_TASK_STRUCT; +typedef struct tasklet_struct *POS_NET_TASK_STRUCT; +#endif /* WORKQUEUE_BH */ + +/*********************************************************************************** + * Timer related definitions and data structures. + **********************************************************************************/ +#define OS_HZ HZ + +typedef struct timer_list OS_NDIS_MINIPORT_TIMER; +typedef struct timer_list OS_TIMER; + +typedef void (*TIMER_FUNCTION)(struct timer_list *); + + +#define OS_WAIT(_time) \ +{ \ + if (in_interrupt()) \ + {\ + RtmpusecDelay(_time * 1000);\ + }else \ + {\ + int _i; \ + long _loop = ((_time)/(1000/OS_HZ)) > 0 ? ((_time)/(1000/OS_HZ)) : 1;\ + wait_queue_head_t _wait; \ + init_waitqueue_head(&_wait); \ + for (_i=0; _i<(_loop); _i++) \ + wait_event_interruptible_timeout(_wait, 0, ONE_TICK); \ + }\ +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define RTMP_TIME_AFTER(a,b) \ + (typecheck(unsigned long, (unsigned long)a) && \ + typecheck(unsigned long, (unsigned long)b) && \ + ((long)(b) - (long)(a) < 0)) + +#define RTMP_TIME_AFTER_EQ(a,b) \ + (typecheck(unsigned long, (unsigned long)a) && \ + typecheck(unsigned long, (unsigned long)b) && \ + ((long)(a) - (long)(b) >= 0)) +#define RTMP_TIME_BEFORE(a,b) RTMP_TIME_AFTER_EQ(b,a) +#else +#define typecheck(type,x) \ +({ type __dummy; \ + typeof(x) __dummy2; \ + (void)(&__dummy == &__dummy2); \ + 1; \ +}) +#define RTMP_TIME_AFTER_EQ(a,b) \ + (typecheck(unsigned long, (unsigned long)a) && \ + typecheck(unsigned long, (unsigned long)b) && \ + ((long)(a) - (long)(b) >= 0)) +#define RTMP_TIME_BEFORE(a,b) RTMP_TIME_AFTER_EQ(b,a) +#define RTMP_TIME_AFTER(a,b) time_after(a, b) +#endif + +#define ONE_TICK 1 + +static inline void NdisGetSystemUpTime(ULONG *time) +{ + *time = jiffies; +} + + +/*********************************************************************************** + * OS specific cookie data structure binding to RTMP_ADAPTER + ***********************************************************************************/ + +struct os_cookie { +#ifdef RTMP_MAC_PCI + struct pci_dev *pci_dev; + struct pci_dev *parent_pci_dev; + USHORT DeviceID; +#endif /* RTMP_MAC_PCI */ + + + + UINT32 pAd_va; + +#if defined(RTMP_MAC_PCI) || defined(RTMP_MAC_USB) + RTMP_NET_TASK_STRUCT rx_done_task; + RTMP_NET_TASK_STRUCT cmd_rsp_event_task; + RTMP_NET_TASK_STRUCT mgmt_dma_done_task; + RTMP_NET_TASK_STRUCT ac0_dma_done_task; +#ifdef CONFIG_ATE + RTMP_NET_TASK_STRUCT ate_ac0_dma_done_task; +#endif /* CONFIG_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 wmm1_ac0_dma_done_task; + RTMP_NET_TASK_STRUCT tbtt_task; + +#ifdef MT_MAC + RTMP_NET_TASK_STRUCT mt_mac_int_0_task; + RTMP_NET_TASK_STRUCT mt_mac_int_1_task; + RTMP_NET_TASK_STRUCT mt_mac_int_2_task; + RTMP_NET_TASK_STRUCT mt_mac_int_3_task; + RTMP_NET_TASK_STRUCT mt_mac_int_4_task; + RTMP_NET_TASK_STRUCT bcn_dma_done_task; + RTMP_NET_TASK_STRUCT bmc_dma_done_task; +#endif /*MT_MAC */ + +#ifdef RTMP_MAC_PCI + RTMP_NET_TASK_STRUCT fifo_statistic_full_task; +#ifdef CONFIG_ANDES_SUPPORT + RTMP_NET_TASK_STRUCT rx1_done_task; +#endif /* CONFIG_ANDES_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + +#ifdef UAPSD_SUPPORT + RTMP_NET_TASK_STRUCT uapsd_eosp_sent_task; +#endif /* UAPSD_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef DFS_SUPPORT +#ifdef DFS_SOFTWARE_SUPPORT + RTMP_NET_TASK_STRUCT pulse_radar_detect_task; + RTMP_NET_TASK_STRUCT width_radar_detect_task; +#endif /* DFS_SOFTWARE_SUPPORT */ +#endif /* DFS_SUPPORT */ + +#ifdef CARRIER_DETECTION_SUPPORT + RTMP_NET_TASK_STRUCT carrier_sense_task; +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef DFS_SUPPORT + struct tasklet_struct dfs_task; +#endif /* DFS_SUPPORT */ + +#endif /* CONFIG_AP_SUPPORT */ + +#endif + + 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; + +#if defined(MT7603_FPGA) || defined(MT7628_FPGA) +#define DBGPRINT_RAW(Level, Fmt) \ +do{ \ + ULONG __gLevel = (Level) & 0xff;\ + ULONG __fLevel = ((Level) & 0xffffff00);\ + if (((RTDebugLevel == RT_DEBUG_FPGA) && (__gLevel == RTDebugLevel)) || ((RTDebugLevel != RT_DEBUG_FPGA) && (__gLevel <= RTDebugLevel))) \ + { \ + if ((RTDebugFunc == 0) || \ + ((RTDebugFunc != 0) && (((__fLevel & RTDebugFunc)!= 0) || (__gLevel <= RT_DEBUG_ERROR))))\ + printk Fmt; \ + } \ +}while(0) + +#else +#define DBGPRINT_RAW(Level, Fmt) \ +do{ \ + ULONG __gLevel = (Level) & 0xff;\ + ULONG __fLevel = ((Level) & 0xffffff00);\ + if (__gLevel <= RTDebugLevel) \ + { \ + if ((RTDebugFunc == 0) || \ + ((RTDebugFunc != 0) && (((__fLevel & RTDebugFunc)!= 0) || (__gLevel <= RT_DEBUG_ERROR))))\ + printk Fmt; \ + } \ +}while(0) +#endif /* MT7603_FPGA */ + +#define DBGPRINT(Level, Fmt) DBGPRINT_RAW(Level, Fmt) + + +#define DBGPRINT_ERR(Fmt) \ +{ \ + printk("ERROR!!! "); \ + printk Fmt; \ +} + +#define DBGPRINT_S(Fmt) \ +{ \ + printk Fmt; \ +} +#else +#define DBGPRINT(Level, Fmt) +#define DBGPRINT_RAW(Level, Fmt) +#define DBGPRINT_S(Fmt) +#define DBGPRINT_ERR(Fmt) +#endif +/* Debug Level */ +#define DBG_LVL_OFF 0 +#define DBG_LVL_ERROR 1 +#define DBG_LVL_WARN 2 +#define DBG_LVL_TRACE 3 +#define DBG_LVL_INFO 4 +#define DBG_LVL_LOUD 5 +#define DBG_LVL_NOISY 6 +#define DBG_LVL_MAX DBG_LVL_NOISY + +/* Debug Category */ +#define DBG_CAT_INIT 0x00000001u /* initialization/shutdown */ +#define DBG_CAT_HW 0x00000002u /* MAC/BBP/RF/Chip */ +#define DBG_CAT_FW 0x00000004u /* FW related command, response, CR that FW care about */ +#define DBG_CAT_HIF 0x00000008u /* Host interface: usb/sdio/pcie/rbus */ +#define DBG_CAT_FPGA 0x00000010u /* FPGA Chip verify, DVT */ +#define DBG_CAT_TEST 0x00000020u /* ATE, QA, UT, FPGA?, TDT, SLT, WHQL, and other TEST */ +#define DBG_CAT_RA 0x00000040u /* Rate Adaption/Throughput related */ +#define DBG_CAT_AP 0x00000080u /* AP, MBSS, WDS */ +#define DBG_CAT_CLIENT 0x00000100u /* STA, ApClient, AdHoc, Mesh */ +#define DBG_CAT_TX 0x00000200u /* Tx data path */ +#define DBG_CAT_RX 0x00000400u /* Rx data path */ +#define DBG_CAT_CFG 0x00000800u /* ioctl/oid/profile/cfg80211/Registry */ +#define DBG_CAT_MLME 0x00001000u /* 802.11 fundamental connection flow, auth, assoc, disconnect, etc */ +#define DBG_CAT_PROTO 0x00002000u /* protocol, ex. TDLS */ +#define DBG_CAT_SEC 0x00004000u /* security/key/WPS/WAPI/PMF/11i related*/ +#define DBG_CAT_PS 0x00008000u /* power saving/UAPSD */ +#define DBG_CAT_POWER 0x00010000u /* power Setting, Single Sku, Temperature comp, etc */ +#define DBG_CAT_COEX 0x00020000u /* BT, BT WiFi Coex, LTE, TVWS*/ +#define DBG_CAT_P2P 0x00040000u /* P2P, Miracast */ +#define DBG_CAT_TOKEN 0x00080000u +#define DBG_CAT_CMW 0x00100000u /* CMW Link Test */ +#define DBG_CAT_RSV1 0x40000000u /* reserved index for code development */ +#define DBG_CAT_RSV2 0x80000000u /* reserved index for code development */ +#define DBG_CAT_ALL 0xFFFFFFFFu + +/* Debug SubCategory */ +#define DBG_SUBCAT_ALL 0xFFFFFFFFu +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +#define CATSEC_SAE 0x00000020u +#define CATSEC_SUITEB 0x00000040u +#define CATSEC_OWE 0x00000080u +#define CATSEC_ECC 0x00000100u +#endif + +#define MTWF_PRINT printk + +#define MTWF_LOG(Category, SubCategory, Level, Fmt) \ +do{ \ + if ((Level) <= RTDebugLevel) \ + MTWF_PRINT Fmt; \ + else { \ + } \ +}while(0) + + +#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); + +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + +void hex_dump_with_lvl(char *str, UCHAR *pSrcBufVA, UINT SrcBufLen, INT dbglvl); + +extern int DebugLevel; + +#endif + +/********************************************************************************************************* + 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 DMA_MAPPING_ERROR(_handle, _ptr) \ + dma_mapping_error(&((struct pci_dev *)(_handle))->dev, _ptr) + +#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) \ +do{ \ + (*(_pV) = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ + (*(_pV) = SWAP32(*((UINT32 *)(_pV)))); \ +}while(0) + +#define RTMP_IO_READ32(_A, _R, _pV) \ +do{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + (*(_pV) = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ + (*(_pV) = SWAP32(*((UINT32 *)(_pV)))); \ + } \ +}while(0) + +#define RTMP_IO_READ8(_A, _R, _pV) \ +{ \ + (*(_pV) = readb((void *)((_A)->CSRBaseAddress + (_R)))); \ +} + +#define _RTMP_IO_WRITE32(_A, _R, _V) \ +do{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + UINT32 _Val; \ + _Val = SWAP32(_V); \ + writel(_Val, (void *)((_A)->CSRBaseAddress + (_R))); \ + } \ +}while(0) + +#ifdef INF_VR9 +#define RTMP_IO_WRITE8(_A, _R, _V) \ +do{ \ + 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))); \ +}while(0) +#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) \ +do{ \ + if ((_A)->bPCIclkOff == FALSE) \ + { \ + (*(_pV) = readl((void *)((_A)->CSRBaseAddress + (_R)))); \ + } \ + else \ + *(_pV) = 0; \ +}while(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) || defined(BB_SOC) +#define RTMP_IO_READ8(_A, _R, _V) \ +do{ \ + ULONG Val; \ + UCHAR _i; \ + _i = ((_R) & 0x3); \ + Val = readl((void *)((_A)->CSRBaseAddress + ((_R) - _i))); \ + Val = (Val >> ((_i)*8)) & (0x000000ff); \ + *((PUCHAR)_V) = (UCHAR) Val; \ +}while(0) +#else +#define RTMP_IO_READ8(_A, _R, _pV) \ +{ \ + (*(_pV) = readb((void *)((_A)->CSRBaseAddress + (_R)))); \ +} +#endif /* #if defined(BRCM_6358) || defined(RALINK_2880) */ + +#define _RTMP_IO_WRITE32(_A, _R, _V) \ +do{ \ + if ((_A)->bPCIclkOff == FALSE) \ + writel((_V), (void *)((_A)->CSRBaseAddress + (_R))); \ +}while(0) + +#define RTMP_IO_FORCE_WRITE32(_A, _R, _V) \ +{ \ + writel(_V, (void *)((_A)->CSRBaseAddress + (_R))); \ +} + +/* This is actually system IO */ +#define RTMP_SYS_IO_READ32(_R, _pV) \ +{ \ + (*_pV = readl((void *)(_R))); \ +} + +#define RTMP_SYS_IO_WRITE32(_R, _V) \ +{ \ + writel(_V, (void *)(_R)); \ +} + + + +#if defined(BRCM_6358) || defined(RALINK_2880) || defined(RALINK_3052) || defined(RALINK_2883) || defined(RTMP_RBUS_SUPPORT) || defined(MT76x2) || defined(BB_SOC) +#define RTMP_IO_WRITE8(_A, _R, _V) \ +do{ \ + 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))); \ +}while(0) +#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 */ + +#ifdef MT_MAC +#define RTMP_MCU_IO_READ32(_A, _R, _pV) \ +do { \ + CmdIORead32((_A), (_R), (_pV)); \ +} while (0) +#define RTMP_MCU_IO_WRITE32(_A, _R, _V) \ +do { \ + CmdIOWrite32((_A), (_R), (_V)); \ +} while (0) + +#endif /* MT_MAC */ + + + + + +#define RTMP_USB_URB_DATA_GET(__pUrb) ((purbb_t)__pUrb)->context +#define RTMP_USB_URB_STATUS_GET(__pUrb) ((purbb_t)__pUrb)->status +#define RTMP_USB_URB_LEN_GET(__pUrb) ((purbb_t)__pUrb)->actual_length + +/*********************************************************************************** + * Network Related data structure and marco definitions + ***********************************************************************************/ +#define PKTSRC_NDIS 0x7f +#define PKTSRC_DRIVER 0x0f + +#define RTMP_OS_NETDEV_STATE_RUNNING(_pNetDev) ((_pNetDev)->flags & IFF_UP) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) +#define _RTMP_OS_NETDEV_GET_PRIV(_pNetDev) (NULL /*(_pNetDev)->ml_priv*/) +#else +#define _RTMP_OS_NETDEV_GET_PRIV(_pNetDev) ((_pNetDev)->priv) +#endif + +#define RTMP_OS_NETDEV_GET_DEVNAME(_pNetDev) ((_pNetDev)->name) +#define RTMP_OS_NETDEV_GET_PHYADDR(_pNetDev) ((_pNetDev)->dev_addr) + +/* Get & Set NETDEV interface hardware type */ +#define RTMP_OS_NETDEV_GET_TYPE(_pNetDev) ((_pNetDev)->type) +#define RTMP_OS_NETDEV_SET_TYPE(_pNetDev, _type) ((_pNetDev)->type = (_type)) +#define RTMP_OS_NETDEV_SET_TYPE_MONITOR(_pNetDev) RTMP_OS_NETDEV_SET_TYPE(_pNetDev, ARPHRD_IEEE80211_PRISM) + +#define RTMP_OS_NETDEV_START_QUEUE(_pNetDev) netif_start_queue((_pNetDev)) +#define RTMP_OS_NETDEV_STOP_QUEUE(_pNetDev) netif_stop_queue((_pNetDev)) +#define RTMP_OS_NETDEV_WAKE_QUEUE(_pNetDev) netif_wake_queue((_pNetDev)) +#define RTMP_OS_NETDEV_CARRIER_OFF(_pNetDev) netif_carrier_off((_pNetDev)) +#define RTMP_OS_NETDEV_CARRIER_ON(_pNetDev) netif_carrier_on((_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) + +#if (KERNEL_VERSION(2, 6, 22) >= LINUX_VERSION_CODE) +#define GET_OS_PKT_DATATAIL(_pkt) \ + skb_tail_pointer(RTPKT_TO_OSPKT(_pkt)) +#define SET_OS_PKT_DATATAIL(_pkt, _len) \ + skb_set_tail_pointer(RTPKT_TO_OSPKT(_pkt), _len) +#else +#define GET_OS_PKT_DATATAIL(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->tail) +#define SET_OS_PKT_DATATAIL(_pkt, _len) \ + ((RTPKT_TO_OSPKT(_pkt)->tail) = (PUCHAR)((RTPKT_TO_OSPKT(_pkt)->data) + (_len))) +#endif + +#define GET_OS_PKT_HEAD(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->head) + +#define GET_OS_PKT_END(_pkt) \ + (RTPKT_TO_OSPKT(_pkt)->end) + +#define SET_OS_PKT_MAC_HEADER(_pkt) \ + (skb_reset_mac_header(RTPKT_TO_OSPKT(_pkt))) + +#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) \ + skb_trim(RTPKT_TO_OSPKT(_pkt), GET_OS_PKT_LEN(_pkt) - _removedTagLen) + +#define OS_PKT_HEAD_BUF_EXTEND(_pkt, _offset) \ + skb_push(RTPKT_TO_OSPKT(_pkt), _offset) + +#define OS_PKT_TAIL_BUF_EXTEND(_pkt, _Len) \ + skb_put(RTPKT_TO_OSPKT(_pkt), _Len) + +#define OS_PKT_RESERVE(_pkt, _Len) \ + skb_reserve(RTPKT_TO_OSPKT(_pkt), _Len) + +#define OS_PKT_COPY_EXPAND(_pkt, headroom, tailroom) \ + skb_copy_expand(RTPKT_TO_OSPKT(_pkt), headroom, tailroom, GFP_ATOMIC) + +#define RTMP_OS_PKT_INIT(__pRxPacket, __pNetDev, __pData, __DataSize) \ +{ \ + PNDIS_PACKET __pRxPkt; \ + __pRxPkt = RTPKT_TO_OSPKT(__pRxPacket); \ + SET_OS_PKT_NETDEV(__pRxPkt, __pNetDev); \ + SET_OS_PKT_DATAPTR(__pRxPkt, __pData); \ + SET_OS_PKT_LEN(__pRxPkt, __DataSize); \ + SET_OS_PKT_DATATAIL(__pRxPkt, __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 +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +#define CB_LEN 35 +#endif +#define GET_OS_PKT_CB(_p) (RTPKT_TO_OSPKT(_p)->cb) +#define PACKET_CB(_p, _offset) ((RTPKT_TO_OSPKT(_p)->cb[CB_OFF + (_offset)])) + + + + +/*********************************************************************************** + * Other function prototypes definitions + ***********************************************************************************/ + +#ifdef CONFIG_RA_HW_NAT_WIFI_NEW_ARCH +#define RT_MOD_HNAT_DEREG(_net_dev) \ +do { \ + if (ppe_dev_unregister_hook != NULL) \ + ppe_dev_unregister_hook(_net_dev); \ +} while (0) + +#define RT_MOD_HNAT_REG(_net_dev) \ +do { \ + if (ppe_dev_register_hook != NULL) \ + ppe_dev_register_hook(_net_dev); \ +} while (0) +#endif + +#ifdef CONFIG_RAETH +#if !defined(CONFIG_RA_NAT_NONE) +extern int (*ra_sw_nat_hook_tx)(VOID *skb); +extern int (*ra_sw_nat_hook_rx)(VOID *skb); +#ifdef CONFIG_RA_HW_NAT_WIFI_NEW_ARCH +extern void (*ppe_dev_register_hook)(VOID *dev); +extern void (*ppe_dev_unregister_hook)(VOID *dev); +#endif +#endif +#endif /* CONFIG_RAETH */ + +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) +struct APCLI_BRIDGE_LEARNING_MAPPING_STRUCT { + struct net_device *rcvd_net_dev; + unsigned char src_addr[ETH_ALEN]; + unsigned char entry_from; + struct APCLI_BRIDGE_LEARNING_MAPPING_STRUCT *pBefore; + struct APCLI_BRIDGE_LEARNING_MAPPING_STRUCT *pNext; +}; + +struct APCLI_BRIDGE_LEARNING_MAPPING_MAP { + struct APCLI_BRIDGE_LEARNING_MAPPING_STRUCT *pHead; + struct APCLI_BRIDGE_LEARNING_MAPPING_STRUCT *pTail; + unsigned int entry_num; +}; + +extern int (*wf_fwd_tx_hook) (struct sk_buff *skb); +extern int (*wf_fwd_rx_hook) (struct sk_buff *skb); +extern unsigned char (*wf_fwd_entry_insert_hook) (struct net_device *src, struct net_device *dest, void *adapter); +extern unsigned char (*wf_fwd_entry_delete_hook) (struct net_device *src, struct net_device *dest, unsigned char link_down); +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +extern void (*wf_fwd_check_device_hook) ( struct net_device *net_dev, signed int type, signed int mbss_idx, unsigned char channel, unsigned char link); +extern void (*wf_fwd_set_cb_num) (unsigned int band_cb_num, unsigned int receive_cb_num); +extern bool (*wf_fwd_check_active_hook) (void); +extern void (*wf_fwd_pro_enabled_hook) (void); +extern void (*wf_fwd_pro_disabled_hook) (void); +extern void (*wf_fwd_bpdu_active_hook) (void); +extern void (*wf_fwd_bpdu_halt_hook) (void); +extern void (*wf_fwd_feedback_map_table) (void *adapter, void *peer, void *opp_peer, void *oth_peer); +extern void (*wf_fwd_probe_apcli_device_hook) (void *device); +extern void (*wf_fwd_add_entry_inform_hook) (unsigned char *addr); +extern void (*wf_fwd_probe_dev_hook) (struct net_device *net_dev_p ); +#endif +extern void (*wf_fwd_get_rep_hook) (unsigned char idx); +extern void (*wf_fwd_pro_active_hook) (void); +extern void (*wf_fwd_pro_halt_hook) (void); +extern void (*wf_fwd_access_schedule_active_hook) (void); +extern void (*wf_fwd_access_schedule_halt_hook) (void); +extern void (*wf_fwd_hijack_active_hook) (void); +extern void (*wf_fwd_hijack_halt_hook) (void); +extern void (*wf_fwd_show_entry_hook) (void); +extern void (*wf_fwd_delete_entry_hook) (unsigned char idx); +extern void (*packet_source_show_entry_hook) (void); +extern void (*packet_source_delete_entry_hook) (unsigned char idx); +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +extern void (*wf_fwd_feedback_map_table) (void *adapter, void *peer, void *opp_peer, void *oth_peer); +#else +extern void (*wf_fwd_feedback_map_table) (void *adapter, void *peer, void *opp_peer); +#endif +extern void (*wf_fwd_probe_adapter) (void *adapter); +extern void (*wf_fwd_remove_adapter)(void *adapter); +extern void (*wf_fwd_insert_bridge_mapping_hook) (struct sk_buff *skb); +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +extern void (*wf_fwd_insert_repeater_mapping_hook) (void *apcli_device, void *lock, void *cli_mapping, void *map_mapping, void *ifAddr_mapping); +#else +extern void (*wf_fwd_insert_repeater_mapping_hook) (void *adapter, void *lock, void *cli_mapping, void *map_mapping, void *ifAddr_mapping); +#endif +extern void (*wf_fwd_delete_repeater_mapping)(void *apcli_device); +extern int (*wf_fwd_search_mapping_table_hook) (struct sk_buff *skb, struct APCLI_BRIDGE_LEARNING_MAPPING_STRUCT **tbl_entry); +extern void (*wf_fwd_delete_entry_inform_hook) (unsigned char *addr); +extern BOOLEAN (*wf_fwd_needed_hook) (void); +#ifdef WH_EZ_SETUP +extern void (*wf_fwd_set_easy_setup_mode) (unsigned int easy_setup_mode); +#endif + + +#endif /* CONFIG_WIFI_PKT_FWD */ + +void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); +int rt28xx_packet_xmit(VOID *skb); + + +#if LINUX_VERSION_CODE <= 0x20402 /* Red Hat 7.1 */ +struct net_device *alloc_netdev(int sizeof_priv, const char *mask, void (*setup)(struct net_device *)); +#endif /* LINUX_VERSION_CODE */ + + +#ifdef RTMP_MAC_PCI +/* function declarations */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define IRQ_HANDLE_TYPE irqreturn_t +#else +#define IRQ_HANDLE_TYPE void +#endif + +IRQ_HANDLE_TYPE +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)) +rt2860_interrupt(int irq, void *dev_instance); +#else +rt2860_interrupt(int irq, void *dev_instance, struct pt_regs *regs); +#endif + +#endif /* RTMP_MAC_PCI */ + +INT rt28xx_ioctl(PNET_DEV net_dev, struct ifreq *rq, INT cmd); +int rt28xx_send_packets(struct sk_buff *skb, struct net_device *ndev); + +extern int ra_mtd_write(int num, loff_t to, size_t len, const u_char *buf); +extern int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf); + + +#define GET_PAD_FROM_NET_DEV(_pAd, _net_dev) \ + _pAd = RTMP_OS_NETDEV_GET_PRIV(_net_dev); +#define GET_WDEV_FROM_NET_DEV(_wdev, _net_dev) \ + _wdev = RTMP_OS_NETDEV_GET_WDEV(_net_dev); + + +/*#ifdef RTMP_USB_SUPPORT */ +/****************************************************************************** + + USB related definitions + +******************************************************************************/ + +#define RTMP_USB_PKT_COPY(__pNetDev, __pNetPkt, __Len, __pData) \ +{ \ + memcpy(skb_put(__pNetPkt, __Len), __pData, __Len); \ + GET_OS_PKT_NETDEV(__pNetPkt) = __pNetDev; \ +} + +typedef struct usb_device_id USB_DEVICE_ID; + +// TODO: shiang-usw, fine tune BULKAGGRE_SIZE, origianl is 60 +#ifdef INF_AMAZON_SE +#define BULKAGGRE_SIZE 30 +#else +#define BULKAGGRE_SIZE 100 /* 100 */ +#endif /* INF_AMAZON_SE */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + +#ifndef OS_ABL_SUPPORT +#define RTUSB_ALLOC_URB(iso) usb_alloc_urb(iso, GFP_ATOMIC) +#ifdef USB_IOT_WORKAROUND2 +void usb_iot_add_padding(struct urb *urb, UINT8 *buf, ra_dma_addr_t dma); +#endif +#define RTUSB_SUBMIT_URB(pUrb) usb_submit_urb(pUrb, GFP_ATOMIC) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) +#define RTUSB_URB_ALLOC_BUFFER(_dev, _size, _dma) usb_alloc_coherent(_dev, _size, GFP_ATOMIC, _dma) +#define RTUSB_URB_FREE_BUFFER(_dev, _size, _addr, _dma) usb_free_coherent(_dev, _size, _addr, _dma) +#else +#define RTUSB_URB_ALLOC_BUFFER(_dev, _size, _dma) usb_buffer_alloc(_dev, _size, GFP_ATOMIC, _dma) +#define RTUSB_URB_FREE_BUFFER(_dev, _size, _addr, _dma) usb_buffer_free(_dev, _size, _addr, _dma) +#endif + +#define RTUSB_FILL_BULK_URB(_urb, _dev, _pipe, _buffer, _buffer_len, _complete_fn, _context) usb_fill_bulk_urb(_urb, _dev, _pipe, _buffer, _buffer_len, _complete_fn, _context) +#else + +#define RTUSB_ALLOC_URB(iso) rausb_alloc_urb(iso) +#define RTUSB_SUBMIT_URB(pUrb) rausb_submit_urb(pUrb) +#define RTUSB_URB_ALLOC_BUFFER rausb_buffer_alloc +#define RTUSB_URB_FREE_BUFFER rausb_buffer_free +#endif /* OS_ABL_SUPPORT */ + +#else + +#define RT28XX_PUT_DEVICE(dev_p) + +#ifndef OS_ABL_SUPPORT +#define RTUSB_ALLOC_URB(iso) usb_alloc_urb(iso) +#define RTUSB_SUBMIT_URB(pUrb) usb_submit_urb(pUrb) +#else +#define RTUSB_ALLOC_URB(iso) rausb_alloc_urb(iso) +#define RTUSB_SUBMIT_URB(pUrb) rausb_submit_urb(pUrb) +#endif /* OS_ABL_SUPPORT */ + +#define RTUSB_URB_ALLOC_BUFFER(pUsb_Dev, BufSize, pDma_addr) kmalloc(BufSize, GFP_ATOMIC) +#define RTUSB_URB_FREE_BUFFER(pUsb_Dev, BufSize, pTransferBuf, Dma_addr) kfree(pTransferBuf) +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) */ + + +#ifndef OS_ABL_SUPPORT +#define RTUSB_FREE_URB(pUrb) usb_free_urb(pUrb) +#else +#define RTUSB_FREE_URB(pUrb) rausb_free_urb(pUrb) +#endif /* OS_ABL_SUPPORT */ + +/* unlink urb */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7) + +#ifndef OS_ABL_SUPPORT +#define RTUSB_UNLINK_URB(pUrb) usb_kill_urb(pUrb) +#else +#define RTUSB_UNLINK_URB(pUrb) rausb_kill_urb(pUrb) +#endif /* OS_ABL_SUPPORT */ + +#else +#define RTUSB_UNLINK_URB(pUrb) usb_unlink_urb(pUrb) +#endif /* LINUX_VERSION_CODE */ + +/* Prototypes of completion funuc. */ +#define RtmpUsbBulkOutDataPacketComplete RTUSBBulkOutDataPacketComplete +#define RtmpUsbBulkOutMLMEPacketComplete RTUSBBulkOutMLMEPacketComplete +#define RtmpUsbBulkOutNullFrameComplete RTUSBBulkOutNullFrameComplete +#define RtmpUsbBulkOutRTSFrameComplete RTUSBBulkOutRTSFrameComplete +#define RtmpUsbBulkOutPsPollComplete RTUSBBulkOutPsPollComplete +#define RtmpUsbBulkRxComplete RTUSBBulkRxComplete +#define RtmpUsbBulkCmdRspEventComplete RTUSBBulkCmdRspEventComplete +#ifdef MT_MAC +#define RtmpUsbBulkOutBCNPacketComplete RTUSBBulkOutBCNPacketComplete +#endif + +#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 51)) || (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18))) +#define RTUSBBulkOutDataPacketComplete(Status, pURB, pt_regs) RTUSBBulkOutDataPacketComplete(pURB) +#define RTUSBBulkOutMLMEPacketComplete(Status, pURB, pt_regs) RTUSBBulkOutMLMEPacketComplete(pURB) +#define RTUSBBulkOutNullFrameComplete(Status, pURB, pt_regs) RTUSBBulkOutNullFrameComplete(pURB) +#define RTUSBBulkOutRTSFrameComplete(Status, pURB, pt_regs) RTUSBBulkOutRTSFrameComplete(pURB) +#define RTUSBBulkOutPsPollComplete(Status, pURB, pt_regs) RTUSBBulkOutPsPollComplete(pURB) +#define RTUSBBulkRxComplete(Status, pURB, pt_regs) RTUSBBulkRxComplete(pURB) +#define RTUSBBulkCmdRspEventComplete(Status, pURB, pt_regs) RTUSBBulkCmdRspEventComplete(pURB) +#ifdef MT_MAC +#define RTUSBBulkOutBCNPacketComplete(Status, pURB, pt_regs) RTUSBBulkOutBCNPacketComplete(pURB) +#endif +#else +#define RTUSBBulkOutDataPacketComplete(Status, pURB, pt_regs) RTUSBBulkOutDataPacketComplete(pURB, pt_regs) +#define RTUSBBulkOutMLMEPacketComplete(Status, pURB, pt_regs) RTUSBBulkOutMLMEPacketComplete(pURB, pt_regs) +#define RTUSBBulkOutNullFrameComplete(Status, pURB, pt_regs) RTUSBBulkOutNullFrameComplete(pURB, pt_regs) +#define RTUSBBulkOutRTSFrameComplete(Status, pURB, pt_regs) RTUSBBulkOutRTSFrameComplete(pURB, pt_regs) +#define RTUSBBulkOutPsPollComplete(Status, pURB, pt_regs) RTUSBBulkOutPsPollComplete(pURB, pt_regs) +#define RTUSBBulkRxComplete(Status, pURB, pt_regs) RTUSBBulkRxComplete(pURB, pt_regs) +#define RTUSBBulkCmdRspEventComplete(Status, pURB, pt_regs) RTUSBBulkCmdRspEventComplete(pURB, pt_regs) +#ifdef MT_MAC +#define RTUSBBulkOutBCNPacketComplete(Status, pURB, pt_regs) RTUSBBulkOutBCNPacketComplete(pURB, pt_regs) +#endif +#endif + +/*extern void dump_urb(struct urb *purb); */ + +#define InterlockedIncrement atomic_inc +#define NdisInterlockedIncrement atomic_inc +#define InterlockedDecrement atomic_dec +#define NdisInterlockedDecrement atomic_dec +#define InterlockedExchange atomic_set + +typedef void USBHST_STATUS; +typedef INT32 URBCompleteStatus; +typedef struct pt_regs pregs; + +USBHST_STATUS RTUSBBulkOutDataPacketComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs); +USBHST_STATUS RTUSBBulkOutMLMEPacketComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs); +USBHST_STATUS RTUSBBulkOutNullFrameComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs); +USBHST_STATUS RTUSBBulkOutRTSFrameComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs); +USBHST_STATUS RTUSBBulkOutPsPollComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs); +USBHST_STATUS RTUSBBulkRxComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs); +USBHST_STATUS RTUSBBulkCmdRspEventComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs); +#ifdef MT_MAC +USBHST_STATUS RTUSBBulkOutBCNPacketComplete(URBCompleteStatus Status, purbb_t pURB, pregs *pt_regs); +#endif + +/* 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) +#ifdef CONFIG_PRE_ALLOC +#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; \ + }while(0) +#else +#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) +#endif + +#ifdef CONFIG_PRE_ALLOC +#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; \ + }while(0) +#else +#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; */ +#endif +#define RTUSB_URB_DMA_MAPPING(pUrb) \ + { \ + pUrb->transfer_dma = 0; \ + pUrb->transfer_flags &= (~URB_NO_TRANSFER_DMA_MAP); \ + } + +#else +#define RTUSB_FILL_TX_BULK_URB(pUrb, \ + pUsb_Dev, \ + uEndpointAddress, \ + pTransferBuf, \ + BufSize, \ + Complete, \ + pContext, \ + TransferDma) \ + do{ \ + FILL_BULK_URB(pUrb, pUsb_Dev, usb_sndbulkpipe(pUsb_Dev, uEndpointAddress), \ + pTransferBuf, BufSize, Complete, pContext); \ + }while(0) + +#define RTUSB_FILL_HTTX_BULK_URB(pUrb, \ + pUsb_Dev, \ + uEndpointAddress, \ + pTransferBuf, \ + BufSize, \ + Complete, \ + pContext, \ + TransferDma) \ + do{ \ + FILL_BULK_URB(pUrb, pUsb_Dev, usb_sndbulkpipe(pUsb_Dev, uEndpointAddress), \ + pTransferBuf, BufSize, Complete, pContext); \ + }while(0) + +#define RTUSB_FILL_RX_BULK_URB(pUrb, \ + pUsb_Dev, \ + uEndpointAddress, \ + pTransferBuf, \ + BufSize, \ + Complete, \ + pContext, \ + TransferDma) \ + do{ \ + FILL_BULK_URB(pUrb, pUsb_Dev, usb_rcvbulkpipe(pUsb_Dev, uEndpointAddress), \ + pTransferBuf, BufSize, Complete, pContext); \ + }while(0) + +#define RTUSB_URB_DMA_MAPPING(pUrb) +#endif + + +#define RTUSB_CONTROL_MSG(pUsb_Dev, uEndpointAddress, Request, RequestType, Value,Index, tmpBuf, TransferBufferLength, timeout, ret) \ + do{ \ + if ((RequestType == DEVICE_VENDOR_REQUEST_OUT) || (RequestType == DEVICE_CLASS_REQUEST_OUT)) \ + ret = USB_CONTROL_MSG(pUsb_Dev, usb_sndctrlpipe(pUsb_Dev, uEndpointAddress), Request, RequestType, Value, Index, tmpBuf, TransferBufferLength, timeout); \ + else if (RequestType == DEVICE_VENDOR_REQUEST_IN) \ + ret = USB_CONTROL_MSG(pUsb_Dev, usb_rcvctrlpipe(pUsb_Dev, uEndpointAddress), Request, RequestType, Value, Index, tmpBuf, TransferBufferLength, timeout); \ + else \ + { \ + DBGPRINT(RT_DEBUG_ERROR, ("vendor request direction is failed\n")); \ + ret = -1; \ + } \ + }while(0) + +#define rtusb_urb_context context +#define rtusb_urb_status status + +#define RTMP_OS_USB_CONTEXT_GET(__pURB) __pURB->rtusb_urb_context +#define RTMP_OS_USB_STATUS_GET(__pURB) __pURB->rtusb_urb_status + +#ifndef OS_ABL_SUPPORT +#define USB_CONTROL_MSG usb_control_msg + +#else + +#define USB_CONTROL_MSG rausb_control_msg + +/*extern int rausb_register(struct usb_driver * new_driver); */ +/*extern void rausb_deregister(struct usb_driver * driver); */ + +extern struct urb *rausb_alloc_urb(int iso_packets); +extern void rausb_free_urb(VOID *urb); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +extern void rausb_put_dev(VOID *dev); +extern struct usb_device *rausb_get_dev(VOID *dev); +#endif /* LINUX_VERSION_CODE */ + +extern int rausb_submit_urb(VOID *urb); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#ifndef gfp_t +#define gfp_t INT32 +#endif /* gfp_t */ + +extern void *rausb_buffer_alloc(VOID *dev, + size_t size, + ra_dma_addr_t *dma); +extern void rausb_buffer_free(VOID *dev, + size_t size, + void *addr, + ra_dma_addr_t dma); +#endif /* LINUX_VERSION_CODE */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7) +extern void rausb_kill_urb(VOID *urb); +#endif /* LINUX_VERSION_CODE */ + +extern int rausb_control_msg(VOID *dev, + unsigned int pipe, + __u8 request, + __u8 requesttype, + __u16 value, + __u16 index, + void *data, + __u16 size, + int timeout); + +#endif /* OS_ABL_SUPPORT */ + +/*#endif // RTMP_USB_SUPPORT */ + +#ifdef CONFIG_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 */ +#endif /* RTMP_MAC_PCI */ + + + +#endif /* CONFIG_ATE */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) +INT RtmpOSNetDevOpsAlloc( + IN PVOID *pNetDevOps); +#endif + +#define RTMP_OS_MAX_SCAN_DATA_GET() IW_SCAN_MAX_DATA + +#include "os/rt_os.h" + + +#ifdef MULTI_INF_SUPPORT + +#ifdef RTMP_PCI_SUPPORT +int __init rt_pci_init_module(void); +void __exit rt_pci_cleanup_module(void); +#endif /* RTMP_PCI_SUPPORT */ + + + +#endif /* MULTI_INF_SUPPORT */ + +VOID os_load_code_from_bin(void *pAd, unsigned char **image, char *bin_name, UINT32 *code_len); +struct device *rtmp_get_dev(void *ad); + +#ifdef RTMP_WLAN_HOOK_SUPPORT +/*define os layer hook function implementation*/ +#include +#define RTMP_OS_TXRXHOOK_CALL(hook,packet,queIdx,priv) RtmpOsTxRxHookCall(hook,packet,queIdx,priv) +#define RTMP_OS_TXRXHOOK_INIT() RtmpOsTxRxHookInit() +#else +#define RTMP_OS_TXRXHOOK_CALL(hook,packet,queIdx,priv) if (priv == NULL) ; +#define RTMP_OS_TXRXHOOK_INIT() +#endif + +#define RA_WEXT 0 +#define RA_NETLINK 1 + +#endif /* __RT_LINUX_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_linux_cmm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_linux_cmm.h new file mode 100644 index 000000000..50f144827 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_linux_cmm.h @@ -0,0 +1,498 @@ +/**************************************************************************** + * 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 +#ifdef MT_MAC +#define RTMP_DRV_NAME "mtpci" xdef_to_str(RT28xx_MODE) +#else +#define RTMP_DRV_NAME "rtpci" xdef_to_str(RT28xx_MODE) +#endif +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 + +#ifdef MT_MAC +#if defined(CONFIG_SECOND_IF_MT7615E) || defined(CONFIG_FIRST_IF_MT7615E) || defined(CONFIG_SECOND_IF_MT7663E) +#define RTMP_DRV_NAME "rlt_drv" +#else +#define RTMP_DRV_NAME "mt7603_drv" +#endif /* CONFIG_SECOND_IF_MT7615E */ +#else +#define RTMP_DRV_NAME "rt2860" +#endif /* RTMP_MAC_USB */ + +#endif /* OS_ABL_FUNC_SUPPORT */ + + +/***************************************************************************** + * OS task related data structure and definitions + ******************************************************************************/ +#define RTMP_OS_TASK_INIT(__pTask, __pTaskName, __pAd) \ + RtmpOSTaskInit(__pTask, __pTaskName, __pAd, &(__pAd)->RscTaskMemList, &(__pAd)->RscSemMemList); + +#ifndef OS_ABL_FUNC_SUPPORT + +/* rt_linux.h */ +#define RTMP_OS_TASK OS_TASK + +#define RTMP_OS_TASK_GET(__pTask) \ + (__pTask) + +#define RTMP_OS_TASK_DATA_GET(__pTask) \ + ((__pTask)->priv) + +#define RTMP_OS_TASK_IS_KILLED(__pTask) \ + ((__pTask)->task_killed) + +#ifdef KTHREAD_SUPPORT +#define RTMP_OS_TASK_WAKE_UP(__pTask) \ + WAKE_UP(pTask); +#else +#define RTMP_OS_TASK_WAKE_UP(__pTask) \ + RTMP_SEM_EVENT_UP(&(pTask)->taskSema); +#endif /* KTHREAD_SUPPORT */ + +#ifdef KTHREAD_SUPPORT +#define RTMP_OS_TASK_LEGALITY(__pTask) \ + if ((__pTask)->kthread_task != NULL) +#else +#define RTMP_OS_TASK_LEGALITY(__pTask) \ + CHECK_PID_LEGALITY((__pTask)->taskPID) +#endif /* KTHREAD_SUPPORT */ + +#else + +/* rt_linux_cmm.h */ +#define RTMP_OS_TASK OS_RSTRUC + +#define RTMP_OS_TASK_GET(__pTask) \ + ((OS_TASK *)((__pTask)->pContent)) + +#define RTMP_OS_TASK_DATA_GET(__pTask) \ + RtmpOsTaskDataGet(__pTask) + +#define RTMP_OS_TASK_IS_KILLED(__pTask) \ + RtmpOsTaskIsKilled(__pTask) + +#define RTMP_OS_TASK_WAKE_UP(__pTask) \ + RtmpOsTaskWakeUp(pTask) + +#define RTMP_OS_TASK_LEGALITY(__pTask) \ + if (RtmpOsCheckTaskLegality(__pTask)) + +#endif /* OS_ABL_FUNC_SUPPORT */ + + +/***************************************************************************** + * Timer related definitions and data structures. + ******************************************************************************/ +#ifndef OS_ABL_FUNC_SUPPORT + +/* rt_linux.h */ +#define NDIS_MINIPORT_TIMER OS_NDIS_MINIPORT_TIMER +#define RTMP_OS_TIMER OS_TIMER + +#define RTMP_OS_FREE_TIMER(__pAd) +#define RTMP_OS_FREE_LOCK(__pAd) +#define RTMP_OS_FREE_TASKLET(__pAd) +#define RTMP_OS_FREE_TASK(__pAd) +#define RTMP_OS_FREE_SEM(__pAd) +#define RTMP_OS_FREE_ATOMIC(__pAd) + +#else + +/* rt_linux_cmm.h */ +#define NDIS_MINIPORT_TIMER OS_RSTRUC +#define RTMP_OS_TIMER OS_RSTRUC + +#define RTMP_OS_FREE_TIMER(__pAd) +#define RTMP_OS_FREE_LOCK(__pAd) +#define RTMP_OS_FREE_TASKLET(__pAd) +#define RTMP_OS_FREE_TASK(__pAd) +#define RTMP_OS_FREE_SEM(__pAd) +#define RTMP_OS_FREE_ATOMIC(__pAd) + +#endif /* OS_ABL_FUNC_SUPPORT */ + + +/***************************************************************************** + * OS file operation related data structure definitions + ******************************************************************************/ +/* if you add any new type, please also modify RtmpOSFileOpen() */ +#define RTMP_FILE_RDONLY 0x0F01 +#define RTMP_FILE_WRONLY 0x0F02 +#define RTMP_FILE_CREAT 0x0F03 +#define RTMP_FILE_TRUNC 0x0F04 + +#ifndef OS_ABL_FUNC_SUPPORT + +/* rt_linux.h */ +#define RTMP_OS_FS_INFO OS_FS_INFO + +#else + +/* rt_linux_cmm.h */ +#define RTMP_OS_FS_INFO OS_RSTRUC + +#endif /* OS_ABL_FUNC_SUPPORT */ + + +/***************************************************************************** + * OS semaphore related data structure and definitions + ******************************************************************************/ + +#ifndef OS_ABL_FUNC_SUPPORT + +#define NDIS_SPIN_LOCK OS_NDIS_SPIN_LOCK +#define NdisAllocateSpinLock(__pReserved, __pLock) OS_NdisAllocateSpinLock(__pLock) +#define NdisFreeSpinLock OS_NdisFreeSpinLock +#define RTMP_SEM_LOCK OS_SEM_LOCK +#define RTMP_SEM_UNLOCK OS_SEM_UNLOCK +#define RTMP_SPIN_LOCK OS_SPIN_LOCK +#define RTMP_SPIN_UNLOCK OS_SPIN_UNLOCK +#define RTMP_SPIN_LOCK_IRQ OS_SPIN_LOCK_IRQ +#define RTMP_SPIN_UNLOCK_IRQ OS_SPIN_UNLOCK_IRQ +#define RTMP_SPIN_LOCK_IRQSAVE OS_SPIN_LOCK_IRQSAVE +#define RTMP_SPIN_UNLOCK_IRQRESTORE OS_SPIN_UNLOCK_IRQRESTORE +#define RTMP_IRQ_LOCK OS_IRQ_LOCK +#define RTMP_IRQ_UNLOCK OS_IRQ_UNLOCK +#define RTMP_INT_LOCK OS_INT_LOCK +#define RTMP_INT_UNLOCK OS_INT_UNLOCK +#define RTMP_OS_SEM OS_SEM +#define RTMP_OS_ATOMIC atomic_t + +#define NdisAcquireSpinLock RTMP_SEM_LOCK +#define NdisReleaseSpinLock RTMP_SEM_UNLOCK + +#define RTMP_SEM_EVENT_INIT_LOCKED(__pSema, __pSemaList) OS_SEM_EVENT_INIT_LOCKED(__pSema) +#define RTMP_SEM_EVENT_INIT(__pSema, __pSemaList) OS_SEM_EVENT_INIT(__pSema) +#define RTMP_SEM_EVENT_DESTORY OS_SEM_EVENT_DESTORY +#define RTMP_SEM_EVENT_WAIT OS_SEM_EVENT_WAIT +#define RTMP_SEM_EVENT_UP OS_SEM_EVENT_UP + +#define RtmpMLMEUp OS_RTMP_MlmeUp + +#define RTMP_OS_ATMOIC_INIT(__pAtomic, __pAtomicList) +#define RTMP_OS_ATMOIC_DESTROY(__pAtomic) +#define RTMP_THREAD_PID_KILL(__PID) KILL_THREAD_PID(__PID, SIGTERM, 1) + +#else + +#define NDIS_SPIN_LOCK OS_RSTRUC +#define RTMP_OS_SEM OS_RSTRUC +#define RTMP_OS_ATOMIC OS_RSTRUC + +#define RTMP_SEM_EVENT_INIT_LOCKED RtmpOsSemaInitLocked +#define RTMP_SEM_EVENT_INIT RtmpOsSemaInit +#define RTMP_SEM_EVENT_DESTORY RtmpOsSemaDestory +#define RTMP_SEM_EVENT_WAIT(_pSema, _status) ((_status) = RtmpOsSemaWaitInterruptible((_pSema))) +#define RTMP_SEM_EVENT_UP RtmpOsSemaWakeUp + +#define RtmpMLMEUp RtmpOsMlmeUp + +#define RTMP_OS_ATMOIC_INIT RtmpOsAtomicInit +#define RTMP_OS_ATMOIC_DESTROY RtmpOsAtomicDestroy +#define RTMP_THREAD_PID_KILL RtmpThreadPidKill + +/* */ +/* spin_lock enhanced for Nested spin lock */ +/* */ +#define NdisAllocateSpinLock(__pAd, __pLock) RtmpOsAllocateLock(__pLock, &(__pAd)->RscLockMemList) +#define NdisFreeSpinLock RtmpOsFreeSpinLock + +#define RTMP_SEM_LOCK(__lock) \ +{ \ + RtmpOsSpinLockBh(__lock); \ +} + +#define RTMP_SEM_UNLOCK(__lock) \ +{ \ + RtmpOsSpinUnLockBh(__lock); \ +} +#define RTMP_SPIN_LOCK_IRQ RtmpOsSpinLockIrq +#define RTMP_SPIN_UNLOCK_IRQ RtmpOsSpinUnlockIrq +#define RTMP_SPIN_LOCK_IRQSAVE RtmpOsSpinLockIrqSave +#define RTMP_SPIN_UNLOCK_IRQRESTORE RtmpOsSpinUnlockIrqRestore + +/* sample, use semaphore lock to replace IRQ lock, 2007/11/15 */ +#ifdef MULTI_CORE_SUPPORT + +#define RTMP_IRQ_LOCK(__lock, __irqflags) \ +{ \ + __irqflags = 0; \ + 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 + +typedef struct completion RTMP_OS_COMPLETION; + +#define RTMP_OS_INIT_COMPLETION(__pCompletion) \ + init_completion(__pCompletion) + +#define RTMP_OS_EXIT_COMPLETION(__pCompletion) + +#define RTMP_OS_COMPLETE(__pCompletion) \ + complete(__pCompletion) + +#define RTMP_OS_WAIT_FOR_COMPLETION_TIMEOUT(__pCompletion, __Timeout) \ + wait_for_completion_timeout(__pCompletion, __Timeout) + +#ifdef WORKQUEUE_BH +#define RTMP_OS_TASKLET_SCHE(__pTasklet) \ + schedule_work(__pTasklet) +#define RTMP_OS_TASKLET_INIT(__pAd, __pTasklet, __pFunc, __Data) \ + INIT_WORK((struct work_struct *)__pTasklet, (work_func_t)__pFunc) +#define RTMP_OS_TASKLET_KILL(__pTasklet) \ + cancel_work_sync(__pTasklet) +#else +#define RTMP_OS_TASKLET_SCHE(__pTasklet) \ + tasklet_hi_schedule(__pTasklet) +#define RTMP_OS_TASKLET_INIT(__pAd, __pTasklet, __pFunc, __Data) \ + tasklet_init(__pTasklet, __pFunc, __Data) +#define RTMP_OS_TASKLET_KILL(__pTasklet) \ + tasklet_kill(__pTasklet) +#endif /* WORKQUEUE_BH */ + +#define RTMP_NET_TASK_DATA_ASSIGN(__Tasklet, __Data) \ + (__Tasklet)->data = (unsigned long)__Data + +#else + +/* rt_linux_cmm.h */ +typedef OS_RSTRUC RTMP_NET_TASK_STRUCT; +typedef OS_RSTRUC *PRTMP_NET_TASK_STRUCT; +typedef OS_RSTRUC RTMP_OS_COMPLETION; +typedef OS_RSTRUC *PRTMP_OS_COMPLETION; + +#define RTMP_OS_INIT_COMPLETION(__pCompletion) \ + RtmpOsInitCompletion(__pCompletion) + +#define RTMP_OS_EXIT_COMPLETION(__pCompletion) \ + RtmpOsExitCompletion(__pCompletion) + +#define RTMP_OS_COMPLETE(__pCompletion) \ + RtmpOsComplete(__pCompletion) + +#define RTMP_OS_WAIT_FOR_COMPLETION_TIMEOUT(__pCompletion, __Timeout) \ + RtmpOsWaitForCompletionTimeout(__pCompletion, __Timeout) + +#define RTMP_OS_TASKLET_SCHE(__pTasklet) \ + RtmpOsTaskletSche(__pTasklet) + +#define RTMP_OS_TASKLET_INIT(__pAd, __pTasklet, __pFunc, __Data) \ + RtmpOsTaskletInit(__pTasklet, __pFunc, __Data, &(__pAd)->RscTaskletMemList) + +#define RTMP_OS_TASKLET_KILL(__pTasklet) \ + RtmpOsTaskletKill(__pTasklet) + +#define RTMP_NET_TASK_DATA_ASSIGN(__pTasklet, __Data) \ + RtmpOsTaskletDataAssign(__pTasklet, __Data) + +#endif /* OS_ABL_FUNC_SUPPORT */ + + + + +/***************************************************************************** + * OS definition related data structure and definitions + ******************************************************************************/ + +#ifdef OS_ABL_SUPPORT + +#define RTMP_USB_CONTROL_MSG_ENODEV -1 +#define RTMP_USB_CONTROL_MSG_FAIL -2 + +typedef struct __RTMP_PCI_CONFIG { + UINT32 ConfigVendorID; +} RTMP_PCI_CONFIG; + +typedef struct __RTMP_USB_CONFIG { + UINT32 Reserved; +} RTMP_USB_CONFIG; + +extern RTMP_PCI_CONFIG *pRtmpPciConfig; +extern RTMP_USB_CONFIG *pRtmpUsbConfig; + +#define RTMP_OS_PCI_VENDOR_ID pRtmpPciConfig->ConfigVendorID + +/* + Declare dma_addr_t here, can not define it in rt_drv.h + + If you define it in include/os/rt_drv.h, then the size in DRIVER module + will be 64-bit, but in UTIL/NET modules, it maybe 32-bit. + This will cause size mismatch problem when OS_ABL = yes. +*/ +/* + In big-endian & 32-bit DMA address platform, if you use long long to + record DMA address, when you call kernel function to set DMA address, + the address will be 0 because you need to do swap I think. + So if you sure your DMA address is 32-bit, do not use RTMP_DMA_ADDR_64. +*/ +#define ra_dma_addr_t unsigned long long + +#else + + +#define RTMP_OS_PCI_VENDOR_ID PCI_VENDOR_ID +#define RTMP_OS_PCI_DEVICE_ID PCI_DEVICE_ID + +#define ra_dma_addr_t dma_addr_t + +#endif /* OS_ABL_SUPPORT */ + +#define PCI_MAP_SINGLE RtmpDrvPciMapSingle + + +/*********************************************************************************** + * Others + ***********************************************************************************/ +#define APCLI_IF_UP_CHECK(pAd, ifidx) (RtmpOSNetDevIsUp((pAd)->ApCfg.ApCliTab[(ifidx)].wdev.if_dev) == TRUE) + +#ifdef RTMP_MAC_PCI +#ifdef MEMORY_OPTIMIZATION +#define TX_RING_SIZE 64 +#define MGMT_RING_SIZE 32 +#define RX_RING_SIZE 64 +#else +#ifdef DOT11_VHT_AC +#define TX_RING_SIZE 256 /* 64 */ /*64 */ +#define RX_RING_SIZE 256 /*64 */ +#else +#ifdef MEMORY_SLIM_SUPPORT +#define TX_RING_SIZE 64 /*64 */ +#else +#define TX_RING_SIZE 220 /*220,default */ +#endif +#ifdef BB_SOC +#define RX_RING_SIZE 64 +#else +#define RX_RING_SIZE 128 /*64 */ +#endif +#endif /* DOT11_VHT_AC */ +#ifdef BB_SOC +#define MGMT_RING_SIZE 64 +#else +#define MGMT_RING_SIZE 128 +#endif +#endif + +#ifdef DATA_QUEUE_RESERVE +// TX_RING_SIZE_RSV must small than TX_RING_SIZE +#define TX_RING_SIZE_RSV 16 +#endif /* DATA_QUEUE_RESERVE */ + + +#ifdef MT_MAC +#define BCN_RING_SIZE 20 +#endif /* MT_MAC */ + +#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 RTMP_OS_NETDEV_SET_WDEV RtmpOsSetNetDevWdev +#define RTMP_OS_NETDEV_GET_WDEV RtmpOsGetNetDevWdev +#define RT_DEV_PRIV_FLAGS_GET RtmpDevPrivFlagsGet +#define RT_DEV_PRIV_FLAGS_SET RtmpDevPrivFlagsSet + +#endif /* __RT_LINUX_CMM_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_linux_txrx_hook.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_linux_txrx_hook.h new file mode 100644 index 000000000..999fefc2c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_linux_txrx_hook.h @@ -0,0 +1,51 @@ +#ifndef _RT_LINUX_TXRX_HOOK_H_ +#define _RT_LINUX_TXRX_HOOK_H_ + +#include +#include +#define MT_WLAN_TXRXHOOK_NAME_MAX 128 + +/*define hook point, if you want to add a new point, please define it in here*/ +typedef enum { + + WLAN_TX_IN=0, + WLAN_TX_ENQUEUE, + WLAN_TX_DROP, + WLAN_TX_DEQUEUE, + WLAN_TX_DMA_DONE, + WLAN_TX_PRETBTT_INTR, + WLAN_TX_DEQUEUE_PROGRESS, + WLAN_TX_ENQUEUE_PROGRESS, + WLAN_TX_MLME_PERIOD, + WLAN_CALIB_TEST_RSP, + +} WLAN_HOOK_PT_T ; + + +/*hook link list will handle the order depend on below priority in the same hook point. + 0: priority low ~ 100: priority high +*/ +typedef enum { + WLAN_HOOK_PRI_LOWEST=0, + WLAN_HOOK_PRI_SOFTQ_STAT=WLAN_HOOK_PRI_LOWEST, + WLAN_HOOK_PRI_HIGHEST=100, +} WLAN_HOOK_PRI_T; + + +struct mt_wlanTxRxHookOps { + + struct list_head list; + const char name[MT_WLAN_TXRXHOOK_NAME_MAX]; + unsigned int (*hookfun)(unsigned short hook, struct sk_buff *skb,unsigned char queIdx,void *priv); + struct module *me; + unsigned short priority; + unsigned short hooks; +}; + + +void RtmpOsTxRxHookInit(void); +int RtmpOsTxRxHookCall(unsigned short hook,struct sk_buff *skb, unsigned char queldx,void *priv); +int RtmpOsTxRxHookRegister(struct mt_wlanTxRxHookOps *ops); +int RtmpOsTxRxHookUnRegister(struct mt_wlanTxRxHookOps *ops); + +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_os.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_os.h new file mode 100644 index 000000000..7e4feeb04 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/rt_os.h @@ -0,0 +1,92 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + 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_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 */ + + +#define RTPRIV_IOCTL_GET_DRIVER_INFO (SIOCIWFIRSTPRIV + 0x1D) + +#ifdef WIFI_DIAG +#define RTPRIV_IOCTL_GET_PROCESS_INFO (SIOCIWFIRSTPRIV + 0x1E) +#endif + +#endif /* _RT_OS_H_ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/trace_linux.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/trace_linux.h new file mode 100644 index 000000000..1b565b69c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/os/trace_linux.h @@ -0,0 +1,152 @@ +/* + *************************************************************************** + * 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: + trace_linux.h +*/ + + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM mtk_wifi + +#if !defined(__TRACE_LINUX_H__) || defined(TRACE_HEADER_MULTI_READ) +#define __TRACE_LINUX_H__ + +#include + +#define TRACE_MCU_CMD_INFO trace_mcu_cmd_info +TRACE_EVENT(mcu_cmd_info, + TP_PROTO(u32 Length, + u32 PQID, + u32 CID, + u32 PktTypeID, + u32 SetQuery, + u32 SeqNum, + u32 ExtCID, + u32 ExtCIDOption, + void *PayLoad, + u32 PayLoadLen + ), + + TP_ARGS(Length, PQID, CID, PktTypeID, SetQuery, SeqNum, ExtCID, ExtCIDOption, + PayLoad, PayLoadLen + ), + + TP_STRUCT__entry( + __field(u32, Length) + __field(u32, PQID) + __field(u32, CID) + __field(u32, PktTypeID) + __field(u32, SetQuery) + __field(u32, SeqNum) + __field(u32, ExtCID) + __field(u32, ExtCIDOption) + __array(u8, PayLoad, 128) + ), + + TP_fast_assign( + u8 *ptr; + u32 ofs, len, pos = 0; + __entry->Length = Length; + __entry->PQID = PQID; + __entry->CID = CID; + __entry->PktTypeID = PktTypeID; + __entry->SeqNum = SeqNum; + __entry->ExtCID = ExtCID; + __entry->ExtCIDOption = ExtCIDOption; + ptr = (u8 *)PayLoad; + + for (ofs = 0; ofs < PayLoadLen; ofs += 16) + { + hex_dump_to_buffer(ptr + ofs, 16, 16, 1, __entry->PayLoad + pos, 128 - pos, 0); + pos += strlen(__entry->PayLoad + pos); + if (128 - pos > 0) + __entry->PayLoad[pos++] = '\n'; + } + ), + + TP_printk("length = 0x%x, pq_id = 0x%x, cid = 0x%x, pkt_type_id = 0x%x, set_query = 0x%x\ + seq_num = 0x%x, ext_cid = 0x%x, ext_cid_option = 0x%x\ + , cmd payload = %s", + __entry->Length, + __entry->PQID, + __entry->CID, + __entry->PktTypeID, + __entry->SeqNum, + __entry->ExtCID, + __entry->ExtCIDOption, + __entry->PayLoad + ) +); + + +#define TRACE_MCU_EVENT_INFO trace_mcu_event_info +TRACE_EVENT(mcu_event_info, + TP_PROTO(u32 Length, + u32 PktTypeID, + u32 EID, + u32 SeqNum, + u32 ExtEID, + void *PayLoad, + u32 PayLoadLen + ), + + TP_ARGS(Length, PktTypeID, EID, SeqNum, ExtEID, + PayLoad, PayLoadLen + ), + + TP_STRUCT__entry( + __field(u32, Length) + __field(u32, PktTypeID) + __field(u32, EID) + __field(u32, SeqNum) + __field(u32, ExtEID) + __array(u8, PayLoad, 128) + ), + + TP_fast_assign( + u8 *ptr; + u32 ofs, len, pos = 0; + __entry->Length = Length; + __entry->PktTypeID = PktTypeID; + __entry->EID = EID; + __entry->SeqNum = SeqNum; + __entry->ExtEID = ExtEID; + ptr = (u8 *)PayLoad; + + for (ofs = 0; ofs < PayLoadLen; ofs += 16) + { + hex_dump_to_buffer(ptr + ofs, 16, 16, 1, __entry->PayLoad + pos, 128 - pos, 0); + pos += strlen(__entry->PayLoad + pos); + if (128 - pos > 0) + __entry->PayLoad[pos++] = '\n'; + } + ), + + TP_printk("length = 0x%x, pkt_type_id = 0x%x, eid = 0x%x\ + seq_num = 0x%x, ext_eid = 0x%x\ + , event payload = %s", + __entry->Length, + __entry->PktTypeID, + __entry->EID, + __entry->SeqNum, + __entry->ExtEID, + __entry->PayLoad + ) +); +#endif + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE trace_linux +#include diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/owe_cmm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/owe_cmm.h new file mode 100644 index 000000000..6bf884789 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/owe_cmm.h @@ -0,0 +1,92 @@ +#ifndef OWE_CMM_H +#define OWE_CMM_H + +#ifdef CONFIG_OWE_SUPPORT +#include "sae_cmm.h" + +#define ECDH_GROUP_256 19 +#define ECDH_GROUP_384 20 +#define ECDH_GROUP_521 21 + +#define OWE_TRANSITION_ORG_ID 0x506f9a +#define OWE_TRANSITION_ORG_ID_LEN 3 + +#define APCLI_MAX_SUPPORTED_OWE_GROUPS 2 + + +#ifdef APCLI_OWE_SUPPORT +extern UCHAR apcli_owe_supp_groups[]; +#endif + +typedef struct GNU_PACKED _EXT_ECDH_PARAMETER_IE { + UCHAR ext_ie_id; + UCHAR length; + UCHAR ext_id_ecdh; + UINT16 group; + UCHAR public_key[128]; +} EXT_ECDH_PARAMETER_IE, *PEXT_ECDH_PARAMETER_IE; + +typedef struct owe_info { + VOID *group_info; + VOID *group_info_bi; + VOID *peer_pub_key;/*actually, BIG_INTEGER_EC_POINT*/ + VOID *pub_key;/*actually, BIG_INTEGER_EC_POINT*/ + VOID *generator;/*actually, BIG_INTEGER_EC_POINT*/ + SAE_BN *priv_key; + UCHAR curr_group; + UCHAR last_try_group; + BOOLEAN inited; + UCHAR *pmkid; +} OWE_INFO; + +INT process_ecdh_element(struct _RTMP_ADAPTER *ad, + VOID *pEntry_v, + EXT_ECDH_PARAMETER_IE *ext_ie_ptr, + UCHAR ie_len, + UCHAR type, + BOOLEAN update_only_grp_info); + +INT build_owe_dh_ie(struct _RTMP_ADAPTER *ad, + VOID *pEntry_v, + UCHAR *buf, + UCHAR group); + +INT init_owe_group(OWE_INFO *owe, UCHAR group); + +INT deinit_owe_group(OWE_INFO *owe); + +INT owe_calculate_secret(OWE_INFO *owe, SAE_BN **secret); + +#ifdef CONFIG_AP_SUPPORT +USHORT owe_pmkid_ecdh_process(struct _RTMP_ADAPTER *pAd, + VOID *pEntry_v, + UCHAR *rsn_ie, + UCHAR rsn_ie_len, + EXT_ECDH_PARAMETER_IE *ecdh_ie, + UCHAR ecdh_ie_length, + UINT8 *pmkid, + UINT8 *pmkid_count, + UCHAR type); +#endif + +BOOLEAN extract_pair_owe_bss_info(UCHAR *owe_vendor_ie, + UCHAR owe_vendor_ie_len, + UCHAR *pair_bssid, + UCHAR *pair_ssid, + UCHAR *pair_ssid_len, + UCHAR *pair_band, + UCHAR *pair_ch); + +extern UCHAR OWE_TRANS_OUI[]; + +void wext_send_owe_trans_chan_event(PNET_DEV net_dev, + UCHAR event_id, + UCHAR *pair_bssid, + UCHAR *pair_ssid, + UCHAR *pair_ssid_len, + UCHAR *pair_band, + UCHAR *pair_ch); + +#endif /*CONFIG_OWE_SUPPORT*/ +#endif /* OWE_CMM_H */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/mt76x2_rf.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/mt76x2_rf.h new file mode 100644 index 000000000..dbbc9274d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/mt76x2_rf.h @@ -0,0 +1,143 @@ +/* + *************************************************************************** + * 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: + mt76x2_rf.h +*/ + + +#ifndef __MT76x2_RF_H__ +#define __MT76x2_RF_H__ + +enum { + CHL_GRP1 = 0x01, + CHL_GRP2, + CHL_GRP3, + CHL_GRP4, + CHL_GRP5, + CHL_GRP6, + CHL_GRP7, + CHL_GRP_MAX = CHL_GRP7, +}; + +#define RFDIGI_TOP0 0x000 +#define RFDIGI_TOP2 0x008 +#define RFDIGI_TOP3 0x00C +#define RFDIGI_TOP4 0x010 +#define A_BAND_IQM_TSSI_DIV_LPF 0x054 +#define A_BAND_PA 0x058 +#define RFDIGI_ABB_TO_AFE5 0x114 +#define RF_ABB 0x130 +#define RFDIGI_TO_SX2 0x144 +#define SX2_FCAL_TARGET_MASK (0x3fff << 11) +#define SX2_FCAL_TARGET(p) (((p) & 0x3fff) << 11) +#define RFDIGI_TO_SX5 0x150 +#define RFDIGI_TO_SX7 0x158 +#define SX7_INTCS_MASK (0x3ff) +#define SX7_INTCS(p) (((p) & 0x3ff)) +#define SX7_FRACES_MASK (0xfffff << 12) +#define SX7_FRACES(p) (((p) & 0xfffff) << 12) +#define SX5_REPA_NRBIAS_2_0_MASK (0x7 << 9) +#define SX5_REPA_NRBIAS_2_0(p) (((p) & 0x07) << 9) +#define RFDIGI_TRX0 0x200 +#define TRX0_SW_TXIQ_CANCEL_EN (0x1 << 10) +#define RFDIGI_TRX4 0x210 +#define RFDIGI_TRX17 0x244 +#define RFDIGI_TRX21 0x254 +#define TRX21_LNA_OUTCAP_A_HG_MASK (0x07 << 0) +#define TRX21_LNA_OUTCAP_A_HG(p) (((p) & 0x07) << 0) +#define TRX21_LNA_OUTCAP_A_MG_MASK (0x07 << 4) +#define TRX21_LNA_OUTCAP_A_MG(p) (((p) & 0x07) << 4) +#define TRX21_LNA_OUTCAP_A_LG_MASK (0x07 << 8) +#define TRX21_LNA_OUTCAP_A_LG(p) (((p) & 0x07) << 8) +#define TRX21_LNA_OUTCAP_A_ULG_MASK (0x07 << 12) +#define TRX21_LNA_OUTCAP_A_ULG(p) (((p) & 0x07) << 12) +#define TRX21_TZ_GCR_A_HG_MASK (0x07 << 16) +#define TRX21_TZ_GCR_A_HG(p) (((p) & 0x07) << 16) +#define TRX21_TZ_GCR_A_MG_MASK (0x07 << 20) +#define TRX21_TZ_GCR_A_MG(p) (((p) & 0x07) << 20) +#define TRX21_TZ_GCR_A_LG_MASK (0x07 << 24) +#define TRX21_TZ_GCR_A_LG(p) (((p) & 0x07) << 24) +#define TRX21_TZ_GCR_A_ULG_MASK (0x07 << 28) +#define TRX21_TZ_GCR_A_ULG(p) (((p) & 0x07) << 28) +#define RFDIGI_TRX24 0x260 +#define TRX24_GM_GC_A_HG_MASK (0x0f << 0) +#define TRX24_GM_GC_A_HG(p) (((p) & 0x0f) << 0) +#define TRX24_GM_GC_A_MG_MASK (0x0f << 4) +#define TRX24_GM_GC_A_MG(p) (((p) & 0x0f) << 4) +#define TRX24_GM_GC_A_LG_MASK (0x0f << 8) +#define TRX24_GM_GC_A_LG(p) (((p) & 0x0f) << 8) +#define TRX24_GM_GC_A_ULG_MASK (0x0f << 12) +#define TRX24_GM_GC_A_ULG(p) (((p) & 0x0f) << 12) +#define TRX24_TZ_FBC_A_HG_MASK (0x0f << 16) +#define TRX24_TZ_FBC_A_HG(p) (((p) & 0x0f) << 16) +#define TRX24_TZ_FBC_A_MG_MASK (0x0f << 20) +#define TRX24_TZ_FBC_A_MG(p) (((p) & 0x0f) << 20) +#define TRX24_TZ_FBC_A_LG_MASK (0x0f << 24) +#define TRX24_TZ_FBC_A_LG(p) (((p) & 0x0f) << 24) +#define TRX24_TZ_FBC_A_ULG_MASK (0x0f << 28) +#define TRX24_TZ_FBC_A_ULG(p) (((p) & 0x0f) << 28) +#define RFDIGI_TRX27 0x26C +#define RFDIGI_TRX28 0x270 +#define RFDIGI_TRX29 0x274 +#define RFDIGI_TRX38 0x298 +#define RFDIGI_TRX39 0x29C +#define RFDIGI_TRX42 0x2A8 +#define RFDIGI_SX7 0x31C +#define RFDIGI_SX8 0x320 + + +#define W_RFDATA 0x0524 +#define R_RFDATA 0x052C +#define RF_CTRL 0x0528 +#define RF_ADDR_MASK 0xfff +#define RF_ADDR(p) ((p) & 0xfff) +#define RF_R_W_CTRL (1 << 12) +#define RF_READY_MASK (1<< 13) +#define RF_READY(p) (((p) & RF_READY_MASK) == (0x0 << 13)) +#define RF_IDX_MASK (1 << 16) +#define RF_IDX(p) (((p) & 0x1) << 16) + +typedef struct _MT_RF_REG { + UINT8 rf_idx; + UINT16 offset; + UINT32 data; +} MT_RF_REG, *PMT_RF_REG; + +typedef struct _CHL_GRP_RF_REG { + UINT8 chl_grp; + UINT16 chl_start; + UINT16 chl_end; + UINT8 lna_outcap_a_hg; + UINT8 lna_outcap_a_mg; + UINT8 lna_outcap_a_lg; + UINT8 lna_outcap_a_ulg; + UINT8 tz_gcr_a_hg; + UINT8 tz_gcr_a_mg; + UINT8 tz_gcr_a_lg; + UINT8 tz_gcr_a_ulg; + UINT8 tz_fbc_a_hg; + UINT8 tz_fbc_a_mg; + UINT8 tz_fbc_a_lg; + UINT8 tz_fbc_a_ulg; + UINT8 gm_gc_a_hg; + UINT8 gm_gc_a_mg; + UINT8 gm_gc_a_lg; + UINT8 gm_gc_a_ulg; +} CHL_GRP_RF_REG, *PCHL_GRP_RF_REG; + +INT mt76x2_rf_write(struct _RTMP_ADAPTER *pAd, UINT8 rf_idx, UINT16 offset, UINT32 data); +INT mt76x2_rf_read(struct _RTMP_ADAPTER *pAd, UINT8 rf_idx, UINT16 offset, UINT32 *data); +INT32 MT76x2ShowAllRF(struct _RTMP_ADAPTER *pAd); +INT32 MT76x2ShowPartialRF(struct _RTMP_ADAPTER *pAd, UINT32 Start, UINT32 End); + +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/mt_bbp.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/mt_bbp.h new file mode 100644 index 000000000..ca458956b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/mt_bbp.h @@ -0,0 +1,25 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of MediaTek. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + mt_bbp.h +*/ + +#ifndef __MT_BBP_H__ +#define __MT_BBP_H__ + +INT32 MTShowAllBBP(struct _RTMP_ADAPTER *pAd); +INT32 MTShowPartialBBP(struct _RTMP_ADAPTER *pAd, UINT32 Start, UINT32 End); +INT mt_phy_probe(struct _RTMP_ADAPTER *pAd); + +#endif /* __MT_BBP_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/mt_phy.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/mt_phy.h new file mode 100644 index 000000000..139597f9c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/mt_phy.h @@ -0,0 +1,2 @@ + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/mt_rf.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/mt_rf.h new file mode 100644 index 000000000..0494b2a6c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/mt_rf.h @@ -0,0 +1,26 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of MediaTek. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + andes_mt.c +*/ + + + +#ifndef __MT_RF_H__ +#define __MT_RF_H__ + +INT32 MTShowAllRF(struct _RTMP_ADAPTER *pAd); +INT32 MTShowPartialRF(struct _RTMP_ADAPTER *pAd, UINT32 Start, UINT32 End); + +#endif /* __MT_RF_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/phy.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/phy.h new file mode 100644 index 000000000..c0b62e3d0 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/phy.h @@ -0,0 +1,281 @@ +/* + *************************************************************************** + * 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: + phy.h +*/ + +#ifndef __PHY_H__ +#define __PHY_H__ + + +#ifdef MT_BBP +#include "phy/mt_bbp.h" +#endif /* MT_BBP */ + +#ifdef RLT_BBP +#include "phy/rlt_bbp.h" +#endif /* RLT_BBP */ + +#ifdef RTMP_BBP +#include "phy/rtmp_bbp.h" +#endif /* RTMP_BBP */ + +#ifdef RLT_RF +#include "phy/rlt_rf.h" +#endif + +#ifdef MT76x2_RF +#include "phy/mt76x2_rf.h" +#endif + +#ifdef MT_RF +#include "phy/mt_rf.h" +#endif + +#define ANTI_INTERFERENCE_SUPPORT + +/* value domain of pAd->RfIcType */ +#define RFIC_2820 1 /* 2.4G 2T3R */ +#define RFIC_2850 2 /* 2.4G/5G 2T3R */ +#define RFIC_2720 3 /* 2.4G 1T2R */ +#define RFIC_2750 4 /* 2.4G/5G 1T2R */ +#define RFIC_3020 5 /* 2.4G 1T1R */ +#define RFIC_2020 6 /* 2.4G B/G */ +#define RFIC_3021 7 /* 2.4G 1T2R */ +#define RFIC_3022 8 /* 2.4G 2T2R */ +#define RFIC_3052 9 /* 2.4G/5G 2T2R */ +#define RFIC_2853 10 /* 2.4G.5G 3T3R */ +#define RFIC_3320 11 /* 2.4G 1T1R with PA (RT3350/RT3370/RT3390) */ +#define RFIC_3322 12 /* 2.4G 2T2R with PA (RT3352/RT3371/RT3372/RT3391/RT3392) */ +#define RFIC_3053 13 /* 2.4G/5G 3T3R (RT3883/RT3563/RT3573/RT3593/RT3662) */ +#define RFIC_3853 13 /* 2.4G/5G 3T3R (RT3883/RT3563/RT3573/RT3593/RT3662) */ +#define RFIC_5592 14 /* 2.4G/5G */ +#define RFIC_6352 15 /* 2.4G 2T2R */ +#define RFIC_7650 15 /* 2.4G/5G 1x1 VHT with BT*/ +#define RFIC_7610E 16 /* 5G 1x1 VHT */ +#define RFIC_7610U 17 +#define RFIC_7630 18 /* 2.4G 1x1 HT with BT */ +#define RFIC_7662 19 /* 2.4G/5G 2T2R VHT with BT */ +#define RFIC_7612 20 /* 2.4G/5G 2T2R VHT */ +#define RFIC_7602 21 /* 2.4G 2T2R VHT */ +#define RFIC_7603 22 /* 2.4G 2T2R HT */ +#define RFIC_7628 23 /* 2.4G 2T2R HT */ +#define RFIC_UNKNOWN 0xff + +#define RFIC_IS_5G_BAND(__pAd) \ + ((__pAd->RfIcType == RFIC_2850) || \ + (__pAd->RfIcType == RFIC_2750) || \ + (__pAd->RfIcType == RFIC_3052) || \ + (__pAd->RfIcType == RFIC_2853) || \ + (__pAd->RfIcType == RFIC_3053) || \ + (__pAd->RfIcType == RFIC_3853) || \ + (__pAd->RfIcType == RFIC_5592) || \ + (__pAd->RfIcType == RFIC_7650) || \ + (__pAd->RfIcType == RFIC_7610E) || \ + (__pAd->RfIcType == RFIC_7610U) || \ + (__pAd->RfIcType == RFIC_7662) || \ + (__pAd->RfIcType == RFIC_7612) || \ + (__pAd->RfIcType == RFIC_UNKNOWN)) + + +#ifdef RTMP_MAC_PCI +// TODO: shiang, what's the difference of BoardType v.s. band and interface?? +#define BOARD_2G_ONLY 1 +#define BOARD_5G_ONLY 2 + +#define BOARD_IS_2G_ONLY(__pAd) \ + (__pAd->Antenna.field.BoardType == BOARD_2G_ONLY) + +#define BOARD_IS_5G_ONLY(__pAd) \ + (__pAd->Antenna.field.BoardType == BOARD_5G_ONLY) +#else +#define BOARD_IS_2G_ONLY(__pAd) 0 +#define BOARD_IS_5G_ONLY(__pAd) 0 +#endif /* RTMP_MAC_PCI */ + +typedef enum{ + RX_CHAIN_0 = 1<<0, + RX_CHAIN_1 = 1<<1, + RX_CHAIN_2 = 1<<2, + RX_CHAIN_ALL = 0xf +}RX_CHAIN_IDX; + + +/* */ +/* BBP R49 TSSI (Transmit Signal Strength Indicator) */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _BBP_R49_STRUC { + struct + { + UCHAR adc5_in_sel:1; /* 0: TSSI (from the external components, old version), 1: PSI (internal components, new version - RT3390) */ + UCHAR bypassTSSIAverage:1; /* 0: the average TSSI (the average of the 16 samples), 1: the current TSSI */ + UCHAR Reserved:1; /* Reserved field */ + UCHAR TSSI:5; /* TSSI value */ + } field; + + UCHAR byte; +} BBP_R49_STRUC, *PBBP_R49_STRUC; +#else +typedef union _BBP_R49_STRUC { + struct + { + UCHAR TSSI:5; /* TSSI value */ + UCHAR Reserved:1; /* Reserved field */ + UCHAR bypassTSSIAverage:1; /* 0: the average TSSI (the average of the 16 samples), 1: the current TSSI */ + UCHAR adc5_in_sel:1; /* 0: TSSI (from the external components, old version), 1: PSI (internal components, new version - RT3390) */ + } field; + + UCHAR byte; +} BBP_R49_STRUC, *PBBP_R49_STRUC; +#endif + +#define MAX_BBP_MSG_SIZE 4096 + + +/* */ +/* BBP & RF are using indirect access. Before write any value into it. */ +/* We have to make sure there is no outstanding command pending via checking busy bit. */ +/* */ +#define MAX_BUSY_COUNT 100 /* Number of retry before failing access BBP & RF indirect register */ +#define MAX_BUSY_COUNT_US 2000 /* Number of retry before failing access BBP & RF indirect register */ + +/*#define PHY_TR_SWITCH_TIME 5 // usec */ + +#define RSSI_FOR_VERY_LOW_SENSIBILITY -35 +#define RSSI_FOR_LOW_SENSIBILITY -58 +#define RSSI_FOR_MID_LOW_SENSIBILITY -65 /*-80*/ +#define RSSI_FOR_MID_SENSIBILITY -90 + +struct _RTMP_ADAPTER; + + + +struct rx_signal_info{ + CHAR raw_rssi[3]; + UCHAR raw_snr[3]; + CHAR freq_offset; +}; + + +typedef struct _RSSI_SAMPLE { + CHAR LastRssi[3]; /* last received RSSI for ant 0~2 */ + CHAR AvgRssi[3]; + SHORT AvgRssiX8[3]; + CHAR LastSnr[3]; + CHAR AvgSnr[3]; + SHORT AvgSnrX8[3]; +#ifdef ANDLINK_FEATURE_SUPPORT + CHAR LastNoiseLevel[3]; +#endif + //CHAR LastNoiseLevel[3]; +} RSSI_SAMPLE; + + +/***************************************************************************** + RF register Read/Write marco definition + *****************************************************************************/ + #if defined(RT_RF) || defined(RT28xx) + INT RTMP_RF_IO_WRITE32(struct _RTMP_ADAPTER *pAd, UINT32 val); +#endif /* defined(RT_RF) || defined(RT28xx) */ + + +/***************************************************************************** + BBP register Read/Write marco definitions. + we read/write the bbp value by register's ID. + Generate PER to test BA + *****************************************************************************/ + + +#define _G_BAND 0x0 +#define _A_BAND 0x1 +#define _BAND 0x3 + +#define _BW_20 (0x0 << 2) +#define _BW_40 (0x1 << 2) +#define _BW_80 (0x2 << 2) +#define _BW_160 (0x3 << 2) +#define _BW (0x3 << 2) + +#define RF_Path0 0 +#define RF_Path1 1 + +#define _1T1R (0x0 << 4) +#define _2T1R (0x1 << 4) +#define _1T2R (0x2 << 4) +#define _2T2R (0x3 << 4) +#define _TX_RX_SETTING (0x3 << 4) + +#define _LT (0x0 << 6) +#define _HT (0x1 << 6) +#define _TEM_SETTING (0x1 << 6) + +INT bbp_set_bw(struct _RTMP_ADAPTER *pAd, UINT8 bw); +INT bbp_set_ctrlch(struct _RTMP_ADAPTER *pAd, UINT8 ext_ch); +INT bbp_set_rxpath(struct _RTMP_ADAPTER *pAd, INT rxpath); +INT bbp_get_temp(struct _RTMP_ADAPTER *pAd, CHAR *temp_val); +INT bbp_tx_comp_init(struct _RTMP_ADAPTER *pAd, INT adc_insel, INT tssi_mode); +INT bbp_set_txdac(struct _RTMP_ADAPTER *pAd, INT tx_dac); +INT bbp_set_mmps(struct _RTMP_ADAPTER *pAd, BOOLEAN ReduceCorePower); +INT bbp_is_ready(struct _RTMP_ADAPTER *pAd); +INT bbp_set_agc(struct _RTMP_ADAPTER *pAd, UCHAR agc, RX_CHAIN_IDX idx); +INT bbp_get_agc(struct _RTMP_ADAPTER *pAd, CHAR *agc, RX_CHAIN_IDX idx); +INT filter_coefficient_ctrl(struct _RTMP_ADAPTER *pAd, UCHAR Channel); +UCHAR get_random_seed_by_phy(struct _RTMP_ADAPTER *pAd); +#ifdef DYNAMIC_VGA_SUPPORT +INT dynamic_vga_enable(struct _RTMP_ADAPTER *pAd); +INT dynamic_vga_disable(struct _RTMP_ADAPTER *pAd); +INT dynamic_vga_adjust(struct _RTMP_ADAPTER *pAd); +#endif /* DYNAMIC_VGA_SUPPORT */ +#ifdef SMART_CARRIER_SENSE_SUPPORT +INT Smart_Carrier_Sense(struct _RTMP_ADAPTER *pAd); +#endif /* SMART_CARRIER_SENSE_SUPPORT */ + +NDIS_STATUS NICInitBBP(struct _RTMP_ADAPTER *pAd); +VOID InitRFRegisters(struct _RTMP_ADAPTER *pAd); +INT32 ShowAllBBP(struct _RTMP_ADAPTER *pAd); +INT32 ShowPartialBBP(struct _RTMP_ADAPTER *pAd, UINT32 Start, UINT32 End); +INT32 ShowAllRF(struct _RTMP_ADAPTER *pAd); +INT32 ShowPartialRF(struct _RTMP_ADAPTER *pAd, UINT32 Start, UINT32 End); + +typedef struct phy_ops{ + INT (*bbp_is_ready)(struct _RTMP_ADAPTER *pAd); + UCHAR (*get_random_seed_by_phy)(struct _RTMP_ADAPTER *pAd); + INT (*filter_coefficient_ctrl)(struct _RTMP_ADAPTER *pAd, UCHAR Channel); + INT (*bbp_set_agc)(struct _RTMP_ADAPTER *pAd, UCHAR agc, RX_CHAIN_IDX chain); + INT (*bbp_get_agc)(struct _RTMP_ADAPTER *pAd, CHAR *agc, RX_CHAIN_IDX chain); + INT (*bbp_set_mmps)(struct _RTMP_ADAPTER *pAd, BOOLEAN ReduceCorePower); + INT (*bbp_set_bw)(struct _RTMP_ADAPTER *pAd, UINT8 bw); + INT (*bbp_set_ctrlch)(struct _RTMP_ADAPTER *pAd, UINT8 ext_ch); + INT (*bbp_set_rxpath)(struct _RTMP_ADAPTER *pAd, INT rxpath); + INT (*bbp_set_txdac)(struct _RTMP_ADAPTER *pAd, INT tx_dac); + INT (*bbp_tx_comp_init)(struct _RTMP_ADAPTER *pAd, INT adc_insel, INT tssi_mode); + INT (*bbp_get_temp)(struct _RTMP_ADAPTER *pAd, CHAR *temp_val); + INT (*bbp_init)(struct _RTMP_ADAPTER *pAd); +#ifdef DYNAMIC_VGA_SUPPORT + INT (*dynamic_vga_enable)(struct _RTMP_ADAPTER *pAd); + INT (*dynamic_vga_disable)(struct _RTMP_ADAPTER *pAd); + INT (*dynamic_vga_adjust)(struct _RTMP_ADAPTER *pAd); +#endif /* DYNAMIC_VGA_SUPPORT */ +#ifdef SMART_CARRIER_SENSE_SUPPORT + INT (*Smart_Carrier_Sense)(struct _RTMP_ADAPTER *pAd); +#endif /* SMART_CARRIER_SENSE_SUPPORT */ + INT32 (*ShowPartialBBP)(struct _RTMP_ADAPTER *pAd, UINT32 Start, UINT32 End); + INT32 (*ShowAllBBP)(struct _RTMP_ADAPTER *pAd); + INT32 (*ShowPartialRF)(struct _RTMP_ADAPTER *pAd, UINT32 Start, UINT32 End); + INT32 (*ShowAllRF)(struct _RTMP_ADAPTER *pAd); +} PHY_OPS; + + +#endif /* __PHY_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/rlt_bbp.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/rlt_bbp.h new file mode 100644 index 000000000..debb6ac91 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/rlt_bbp.h @@ -0,0 +1,340 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + + +#ifndef __RLT_BBP_H__ +#define __RLT_BBP_H__ + + +#define BBP_CORE 0x2000 +#define BBP_IBI 0x2100 +#define BBP_AGC1 0x2300 +#define BBP_TXC 0x2400 +#define BBP_RXC 0x2500 +#define BBP_TXO 0x2600 +#define BBP_TXBE 0x2700 +#define BBP_RXFE 0x2800 +#define BBP_RXO 0x2900 +#define BBP_DFS 0x2a00 +#define BBP_TR 0x2b00 +#define BBP_CAL 0x2c00 +#define BBP_DSC 0x2e00 +#define BBP_PFMU 0x2f00 + + +/* 0x2000 ~ */ +#define CORE_R0 (BBP_CORE + 0x00) +#define CORE_R1 (BBP_CORE + 0x04) +#define CORE_R4 (BBP_CORE + 0x10) +#define CORE_R24 (BBP_CORE + 0x60) +#define CORE_R32 (BBP_CORE + 0x80) +#define CORE_R33 (BBP_CORE + 0x84) +#define CORE_R34 (BBP_CORE + 0x88) +#define CORE_R35 (BBP_CORE + 0x8c) +#define CORE_R42 (BBP_CORE + 0xa8) +#define CORE_R44 (BBP_CORE + 0xb0) + +/* 0x2100 ~ */ +#define IBI_R0 (BBP_IBI + 0x00) +#define IBI_R1 (BBP_IBI + 0x04) +#define IBI_R2 (BBP_IBI + 0x08) +#define IBI_R3 (BBP_IBI + 0x0c) +#define IBI_R4 (BBP_IBI + 0x10) +#define IBI_R5 (BBP_IBI + 0x14) +#define IBI_R6 (BBP_IBI + 0x18) +#define IBI_R7 (BBP_IBI + 0x1c) +#define IBI_R9 (BBP_IBI + 0x24) +#define IBI_R11 (BBP_IBI + 0x2c) +#define IBI_R15 (BBP_IBI + 0x3c) + +/* 0x2300 ~ */ +#define AGC1_R0 (BBP_AGC1 + 0x00) +#define AGC1_R0_PRIMARY_CHL_INDEX_MASK (0x3 << 8) +#define AGC1_R0_RPIMARY_CHL_INDEX(p) (((p) & 0x3) << 8) +#define GET_PRIMARY_CHL_INDEX(p) (((p) & AGC1_R0_PRIMARY_CHL_INDEX_MASK) >> 8) + +#define AGC1_R1 (BBP_AGC1 + 0x04) +#define AGC1_R2 (BBP_AGC1 + 0x08) +#define AGC1_R4 (BBP_AGC1 + 0x10) +#define AGC1_R5 (BBP_AGC1 + 0x14) +#define AGC1_R6 (BBP_AGC1 + 0x18) +#define AGC1_R7 (BBP_AGC1 + 0x1C) +#define AGC1_R8 (BBP_AGC1 + 0x20) +#define AGC1_R9 (BBP_AGC1 + 0x24) +#define AGC1_R11 (BBP_AGC1 + 0x2C) +#define AGC1_R12 (BBP_AGC1 + 0x30) +#define AGC1_R13 (BBP_AGC1 + 0x34) +#define AGC1_R14 (BBP_AGC1 + 0x38) +#define AGC1_R15 (BBP_AGC1 + 0x3C) +#define AGC1_R16 (BBP_AGC1 + 0x40) +#define AGC1_R18 (BBP_AGC1 + 0x48) +#define AGC1_R19 (BBP_AGC1 + 0x4c) +#define AGC1_R20 (BBP_AGC1 + 0x50) +#define AGC1_R21 (BBP_AGC1 + 0x54) +#define AGC1_R22 (BBP_AGC1 + 0x58) +#define AGC1_R23 (BBP_AGC1 + 0x5c) +#define AGC1_R24 (BBP_AGC1 + 0x60) +#define AGC1_R25 (BBP_AGC1 + 0x64) +#define AGC1_R26 (BBP_AGC1 + 0x68) +#define AGC1_R27 (BBP_AGC1 + 0x6c) +#define AGC1_R28 (BBP_AGC1 + 0x70) +#define AGC1_R30 (BBP_AGC1 + 0x78) +#define AGC1_R31 (BBP_AGC1 + 0x7c) +#define AGC1_R32 (BBP_AGC1 + 0x80) +#define AGC1_R33 (BBP_AGC1 + 0x84) +#define AGC1_R34 (BBP_AGC1 + 0x88) +#define AGC1_R35 (BBP_AGC1 + 0x8c) +#define AGC1_R37 (BBP_AGC1 + 0x94) +#define AGC1_R39 (BBP_AGC1 + 0x9c) +#define AGC1_R41 (BBP_AGC1 + 0xa4) +#define AGC1_R43 (BBP_AGC1 + 0xac) +#define AGC1_R45 (BBP_AGC1 + 0xb4) +#define AGC1_R47 (BBP_AGC1 + 0xbc) +#define AGC1_R49 (BBP_AGC1 + 0xc4) +#define AGC1_R51 (BBP_AGC1 + 0xcc) +#define AGC1_R53 (BBP_AGC1 + 0xd4) +#define AGC1_R55 (BBP_AGC1 + 0xdc) +#define AGC1_R57 (BBP_AGC1 + 0xe4) +#define AGC1_R58 (BBP_AGC1 + 0xe8) +#define AGC1_R59 (BBP_AGC1 + 0xec) +#define AGC1_R60 (BBP_AGC1 + 0xf0) +#define AGC1_R61 (BBP_AGC1 + 0xf4) +#define AGC1_R62 (BBP_AGC1 + 0xf8) +#define AGC1_R63 (BBP_AGC1 + 0xfc) + +/* 0x2400 ~ */ +#define TXC_R0 (BBP_TXC + 0x00) +#define TXC_R1 (BBP_TXC + 0x04) +#define TXC_R2 (BBP_TXC + 0x08) + +/* 0x2500 ~ */ +#define RXC_R0 (BBP_RXC + 0x00) +#define RXC_R1 (BBP_RXC + 0x04) +#define RXC_R2 (BBP_RXC + 0x08) +#define RXC_R3 (BBP_RXC + 0x0c) +#define RXC_R4 (BBP_RXC + 0x10) +#define RXC_R5 (BBP_RXC + 0x14) +#define RXC_R7 (BBP_RXC + 0x1C) +#define RXC_R9 (BBP_RXC + 0x28) + +/* 0x2600 ~ */ +#define TXO_R0 (BBP_TXO + 0x00) +#define TXO_R1 (BBP_TXO + 0x04) +#define TXO_R2 (BBP_TXO + 0x08) +#define TXO_R3 (BBP_TXO + 0x0c) +#define TXO_R4 (BBP_TXO + 0x10) +#define TXO_R5 (BBP_TXO + 0x14) +#define TXO_R6 (BBP_TXO + 0x18) +#define TXO_R7 (BBP_TXO + 0x1c) +#define TXO_R8 (BBP_TXO + 0x20) +#define TXO_R13 (BBP_TXO + 0x34) + +/* 0x2700 ~ */ +#define TXBE_R0 (BBP_TXBE + 0x00) +#define TXBE_R1 (BBP_TXBE + 0x04) +#define TXBE_R2 (BBP_TXBE + 0x08) +#define TXBE_R3 (BBP_TXBE + 0x0c) +#define TXBE_R4 (BBP_TXBE + 0x10) +#define TXBE_R5 (BBP_TXBE + 0x14) +#define TXBE_R6 (BBP_TXBE + 0x18) +#define TXBE_R8 (BBP_TXBE + 0x20) +#define TXBE_R9 (BBP_TXBE + 0x24) +#define TXBE_R10 (BBP_TXBE + 0x28) +#define TXBE_R12 (BBP_TXBE + 0x30) +#define TXBE_R13 (BBP_TXBE + 0x34) +#define TXBE_R14 (BBP_TXBE + 0x38) +#define TXBE_R15 (BBP_TXBE + 0x3c) +#define TXBE_R16 (BBP_TXBE + 0x40) +#define TXBE_R17 (BBP_TXBE + 0x44) +#define TXBE_R52 (BBP_TXBE + 0xd0) + +/* 0x2800 ~ */ +#define RXFE_R0 (BBP_RXFE + 0x00) +#define RXFE_R1 (BBP_RXFE + 0x04) +#define RXFE_R2 (BBP_RXFE + 0x08) +#define RXFE_R3 (BBP_RXFE + 0x0c) +#define RXFE_R4 (BBP_RXFE + 0x10) +#define RXFE_R17 (BBP_RXFE + 0x44) + +/* 0x2900 ~ */ +#define RXO_R0 (BBP_RXO + 0x00) +#define RXO_R9 (BBP_RXO + 0x24) +#define RXO_R13 (BBP_RXO + 0x34) +#define RXO_R14 (BBP_RXO + 0x38) +#define RXO_R15 (BBP_RXO + 0x3c) +#define RXO_R16 (BBP_RXO + 0x40) +#define RXO_R17 (BBP_RXO + 0x44) +#define RXO_R18 (BBP_RXO + 0x48) +#define RXO_R19 (BBP_RXO + 0x4C) +#define RXO_R20 (BBP_RXO + 0x50) +#define RXO_R21 (BBP_RXO + 0x54) +#define RXO_R24 (BBP_RXO + 0x60) +#define RXO_R28 (BBP_RXO + 0x70) +#define RXO_R29 (BBP_RXO + 0x74) +#define RXO_R63 (BBP_RXO + 0xfc) + +/* 0x2a00 ~ */ +#define DFS_R0 (BBP_DFS + 0x00) +#define DFS_R1 (BBP_DFS + 0x04) +#define DFS_R2 (BBP_DFS + 0x08) +#define DFS_R3 (BBP_DFS + 0x0c) +#define DFS_R4 (BBP_DFS + 0x10) +#define DFS_R5 (BBP_DFS + 0x14) +#define DFS_R7 (BBP_DFS + 0x1c) +#define DFS_R9 (BBP_DFS + 0x24) +#define DFS_R11 (BBP_DFS + 0x2c) +#define DFS_R13 (BBP_DFS + 0x34) +#define DFS_R14 (BBP_DFS + 0x38) +#define DFS_R15 (BBP_DFS + 0x3c) +#define DFS_R17 (BBP_DFS + 0x44) +#define DFS_R19 (BBP_DFS + 0x4c) +#define DFS_R20 (BBP_DFS + 0x50) +#define DFS_R22 (BBP_DFS + 0x58) +#define DFS_R23 (BBP_DFS + 0x5c) +#define DFS_R25 (BBP_DFS + 0x64) +#define DFS_R26 (BBP_DFS + 0x68) +#define DFS_R28 (BBP_DFS + 0x70) +#define DFS_R30 (BBP_DFS + 0x78) +#define DFS_R31 (BBP_DFS + 0x7c) +#define DFS_R32 (BBP_DFS + 0x80) +#define DFS_R36 (BBP_DFS + 0x90) +#define DFS_R37 (BBP_DFS + 0x94) + +/* 0x2b00 ~ */ +#define TR_R0 (BBP_TR + 0x00) +#define TR_R1 (BBP_TR + 0x04) +#define TR_R2 (BBP_TR + 0x08) +#define TR_R3 (BBP_TR + 0x0c) +#define TR_R4 (BBP_TR + 0x10) +#define TR_R5 (BBP_TR + 0x14) +#define TR_R6 (BBP_TR + 0x18) +#define TR_R9 (BBP_TR + 0x24) + +/* 0x2c00 ~ */ +#define CAL_R0 (BBP_CAL + 0x00) +#define CAL_R1 (BBP_CAL + 0x04) +#define CAL_R2 (BBP_CAL + 0x08) +#define CAL_R3 (BBP_CAL + 0x0c) +#define CAL_R4 (BBP_CAL + 0x10) +#define CAL_R5 (BBP_CAL + 0x14) +#define CAL_R6 (BBP_CAL + 0x18) +#define CAL_R7 (BBP_CAL + 0x1C) +#define CAL_R8 (BBP_CAL + 0x20) +#define CAL_R9 (BBP_CAL + 0x24) +#define CAL_R10 (BBP_CAL + 0x28) +#define CAL_R11 (BBP_CAL + 0x2C) +#define CAL_R12 (BBP_CAL + 0x30) +#define CAL_R13 (BBP_CAL + 0x34) +#define CAL_R14 (BBP_CAL + 0x38) +#define CAL_R15 (BBP_CAL + 0x3C) +#define CAL_R16 (BBP_CAL + 0x40) +#define CAL_R17 (BBP_CAL + 0x44) +#define CAL_R18 (BBP_CAL + 0x48) +#define CAL_R19 (BBP_CAL + 0x4C) +#define CAL_R20 (BBP_CAL + 0x50) +#define CAL_R21 (BBP_CAL + 0x54) +#define CAL_R22 (BBP_CAL + 0x58) +#define CAL_R23 (BBP_CAL + 0x5C) +#define CAL_R24 (BBP_CAL + 0x60) +#define CAL_R25 (BBP_CAL + 0x64) +#define CAL_R26 (BBP_CAL + 0x68) +#define CAL_R27 (BBP_CAL + 0x6C) +#define CAL_R28 (BBP_CAL + 0x70) +#define CAL_R29 (BBP_CAL + 0x74) +#define CAL_R30 (BBP_CAL + 0x78) +#define CAL_R31 (BBP_CAL + 0x7C) +#define CAL_R32 (BBP_CAL + 0x80) +#define CAL_R33 (BBP_CAL + 0x84) +#define CAL_R34 (BBP_CAL + 0x88) +#define CAL_R35 (BBP_CAL + 0x8C) +#define CAL_R36 (BBP_CAL + 0x90) +#define CAL_R37 (BBP_CAL + 0x94) +#define CAL_R38 (BBP_CAL + 0x98) +#define CAL_R39 (BBP_CAL + 0x9C) +#define CAL_R40 (BBP_CAL + 0xA0) +#define CAL_R41 (BBP_CAL + 0xA4) +#define CAL_R42 (BBP_CAL + 0xA8) +#define CAL_R43 (BBP_CAL + 0xAC) +#define CAL_R44 (BBP_CAL + 0xB0) +#define CAL_R45 (BBP_CAL + 0xB4) +#define CAL_R46 (BBP_CAL + 0xB8) +#define CAL_R47 (BBP_CAL + 0xBC) +#define CAL_R48 (BBP_CAL + 0xC0) +#define CAL_R49 (BBP_CAL + 0xC4) +#define CAL_R50 (BBP_CAL + 0xC8) +#define CAL_R51 (BBP_CAL + 0xCC) +#define CAL_R52 (BBP_CAL + 0xD0) +#define CAL_R53 (BBP_CAL + 0xD4) +#define CAL_R54 (BBP_CAL + 0xD8) +#define CAL_R55 (BBP_CAL + 0xDC) +#define CAL_R56 (BBP_CAL + 0xE0) +#define CAL_R57 (BBP_CAL + 0xE4) +#define CAL_R58 (BBP_CAL + 0xE8) +#define CAL_R59 (BBP_CAL + 0xEC) +#define CAL_R60 (BBP_CAL + 0xF0) +#define CAL_R61 (BBP_CAL + 0xF4) +#define CAL_R62 (BBP_CAL + 0xF8) +#define CAL_R63 (BBP_CAL + 0xFC) +#define CAL_R64 (BBP_CAL + 0x100) +#define CAL_R65 (BBP_CAL + 0x104) +#define CAL_R66 (BBP_CAL + 0x108) +#define CAL_R67 (BBP_CAL + 0x10C) +#define CAL_R68 (BBP_CAL + 0x110) +#define CAL_R69 (BBP_CAL + 0x114) +#define CAL_R70 (BBP_CAL + 0x118) + +/* 0x2e00 ~ */ +#define DSC_R0 (BBP_DSC + 0x00) +#define DSC_R8 (BBP_DSC + 0x20) +#define DSC_R10 (BBP_DSC + 0x28) + +/* 0x2f00 ~ */ +#define PFMU_R0 (BBP_PFMU + 0x00) +#define PFMU_R1 (BBP_PFMU + 0x04) +#define PFMU_R10 (BBP_PFMU + 0x28) +#define PFMU_R11 (BBP_PFMU + 0x2C) +#define PFMU_R12 (BBP_PFMU + 0x30) +#define PFMU_R13 (BBP_PFMU + 0x34) +#define PFMU_R14 (BBP_PFMU + 0x38) +#define PFMU_R15 (BBP_PFMU + 0x3C) +#define PFMU_R19 (BBP_PFMU + 0x4C) +#define PFMU_R20 (BBP_PFMU + 0x50) +#define PFMU_R21 (BBP_PFMU + 0x54) +#define PFMU_R22 (BBP_PFMU + 0x58) +#define PFMU_R23 (BBP_PFMU + 0x5C) +#define PFMU_R54 (BBP_PFMU + 0xD8) +#define PFMU_R57 (BBP_PFMU + 0xE4) + + +#define RTMP_BBP_IO_READ32(_p, _i, _pV) RTMP_IO_READ32(_p, _i, _pV) +#define RTMP_BBP_IO_WRITE32(_p, _i, _v) RTMP_IO_WRITE32(_p, _i, _v) + + +struct _RTMP_ADAPTER; +INT rlt_phy_probe(struct _RTMP_ADAPTER *pAd); + +#endif /* __RLT_BBP_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/rlt_rf.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/rlt_rf.h new file mode 100644 index 000000000..25eb298c7 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/rlt_rf.h @@ -0,0 +1,107 @@ +/* + *************************************************************************** + * 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: + rlt_rf.h +*/ + +#ifndef __RLT_RF_H__ +#define __RLT_RF_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 + +#define RF_R64 64 +#define RF_R65 65 +#define RF_R66 66 +#define RF_R67 67 +#define RF_R68 68 +#define RF_R69 69 +#define RF_R70 70 +#define RF_R71 71 +#define RF_R72 72 +#define RF_R73 73 +#define RF_R74 74 +#define RF_R75 75 +#define RF_R76 76 +#define RF_R77 77 +#define RF_R78 78 +#define RF_R79 79 +#define RF_R126 126 +#define RF_R127 127 + +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/rtmp_bbp.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/rtmp_bbp.h new file mode 100644 index 000000000..c7a78831a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/rtmp_bbp.h @@ -0,0 +1,542 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + rtmp_bbp.h + + Abstract: + Ralink Wireless Chip PHY(BBP) related definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __RTMP_BBP_H__ +#define __RTMP_BBP_H__ + + +/* + BBP sections +*/ +#define BBP_R0 0 /* version */ +#define BBP_R1 1 /* TSSI */ +#define BBP_R2 2 /* TX configure */ +#define BBP_R3 3 +#define BBP_R4 4 +#define BBP_R5 5 +#define BBP_R6 6 +#define BBP_R10 10 /* Rate report */ +#define BBP_R11 11 +#define BBP_R12 12 +#define BBP_R13 13 +#define BBP_R14 14 /* RX configure */ +#define BBP_R15 15 +#define BBP_R16 16 +#define BBP_R17 17 /* RX sensibility */ +#define BBP_R18 18 +#define BBP_R19 19 +#define BBP_R20 20 +#define BBP_R21 21 +#define BBP_R22 22 +#define BBP_R23 23 +#define BBP_R24 24 +#define BBP_R25 25 +#define BBP_R26 26 +#define BBP_R27 27 +#define BBP_R28 28 +#define BBP_R30 30 +#define BBP_R31 31 +#define BBP_R47 47 +#define BBP_R49 49 /*TSSI */ +#define BBP_R50 50 +#define BBP_R51 51 +#define BBP_R52 52 +#define BBP_R53 53 +#define BBP_R54 54 +#define BBP_R55 55 +#define BBP_R58 58 +#define BBP_R60 60 +#define BBP_R57 57 +#define BBP_R62 62 /* Rx SQ0 Threshold HIGH */ +#define BBP_R63 63 +#define BBP_R64 64 +#define BBP_R65 65 +#define BBP_R66 66 +#define BBP_R67 67 +#define BBP_R68 68 +#define BBP_R69 69 +#define BBP_R70 70 /* Rx AGC SQ CCK Xcorr threshold */ +#define BBP_R73 73 +#define BBP_R74 74 +#define BBP_R75 75 +#define BBP_R76 76 +#define BBP_R77 77 +#define BBP_R78 78 +#define BBP_R79 79 +#define BBP_R80 80 +#define BBP_R81 81 +#define BBP_R82 82 +#define BBP_R83 83 +#define BBP_R84 84 +#define BBP_R86 86 +#define BBP_R88 88 +#define BBP_R91 91 +#define BBP_R92 92 +#define BBP_R93 93 +#define BBP_R94 94 /* Tx Gain Control */ +#define BBP_R95 95 +#define BBP_R96 96 +#define BBP_R98 98 +#define BBP_R99 99 +#define BBP_R101 101 +#define BBP_R103 103 +#define BBP_R104 104 +#define BBP_R105 105 +#define BBP_R106 106 +#define BBP_R107 107 +#define BBP_R108 108 +#define BBP_R109 109 +#define BBP_R110 110 +#define BBP_R113 113 +#define BBP_R114 114 +#define BBP_R115 115 +#define BBP_R116 116 +#define BBP_R117 117 +#define BBP_R118 118 +#define BBP_R119 119 +#define BBP_R120 120 +#define BBP_R121 121 +#define BBP_R122 122 +#define BBP_R123 123 +#define BBP_R126 126 +#define BBP_R127 127 +#define BBP_R128 128 +#define BBP_R129 129 +#define BBP_R130 130 +#define BBP_R131 131 +#define BBP_R132 132 +#define BBP_R133 133 +#define BBP_R134 134 +#define BBP_R135 135 +#define BBP_R137 137 +#define BBP_R138 138 /* add by johnli, RF power sequence setup, ADC dynamic on/off control */ +#define BBP_R139 139 +#define BBP_R140 140 +#define BBP_R141 141 +#define BBP_R142 142 +#define BBP_R143 143 +#define BBP_R144 144 +#define BBP_R145 145 +#define BBP_R146 146 +#define BBP_R147 147 +#define BBP_R148 148 +#define BBP_R149 149 +#define BBP_R150 150 +#define BBP_R151 151 +#define BBP_R152 152 +#define BBP_R153 153 +#define BBP_R154 154 +#define BBP_R155 155 +#define BBP_R156 156 +#define BBP_R157 157 +#define BBP_R158 158 /* Calibration register are accessed through R158 and R159 */ +#define BBP_R159 159 +#define BBP_R160 160 /* Tx BF control */ +#define BBP_R161 161 +#define BBP_R162 162 +#define BBP_R163 163 +#define BBP_R164 164 +#define BBP_R165 165 +#define BBP_R166 166 +#define BBP_R167 167 +#define BBP_R168 168 +#define BBP_R169 169 +#define BBP_R170 170 +#define BBP_R171 171 +#define BBP_R172 172 +#define BBP_R173 173 +#define BBP_R174 174 +#define BBP_R175 175 +#define BBP_R176 176 +#define BBP_R177 177 +#define BBP_R178 178 +#define BBP_R179 179 +#define BBP_R180 180 +#define BBP_R181 181 +#define BBP_R182 182 +#define BBP_R183 183 +#define BBP_R184 184 +#define BBP_R185 185 +#define BBP_R186 186 +#define BBP_R187 187 +#define BBP_R188 188 +#define BBP_R189 189 +#define BBP_R190 190 +#define BBP_R191 191 +#define BBP_R195 195 +#define BBP_R196 196 +#define BBP_R200 200 +#define BBP_R201 201 +#define BBP_R202 202 +#define BBP_R203 203 +#define BBP_R204 204 +#define BBP_R205 205 +#define BBP_R206 206 +#define BBP_R207 207 +#define BBP_R208 208 +#define BBP_R209 209 +#define BBP_R210 210 +#define BBP_R211 211 + +#define BBP_R241 241 +#define BBP_R242 242 +#define BBP_R244 244 + +#define BBP_R250 250 +#define BBP_R253 253 +#define BBP_R254 254 +#define BBP_R255 255 + +#define BBPR94_DEFAULT 0x06 /* Add 1 value will gain 1db */ + + +#ifdef RT_BIG_ENDIAN +typedef union _BBP_R47_STRUC { + struct + { + UCHAR Adc6On:1; + UCHAR Reserved:2; + UCHAR TssiMode:2; + UCHAR TssiUpdateReq:1; + UCHAR TssiReportSel:2; + } field; + + UCHAR byte; +} BBP_R47_STRUC, *PBBP_R47_STRUC; +#else +typedef union _BBP_R47_STRUC { + struct + { + UCHAR TssiReportSel:2; + UCHAR TssiUpdateReq:1; + UCHAR TssiMode:2; + UCHAR Reserved:2; + UCHAR Adc6On:1; + } field; + + UCHAR byte; +} BBP_R47_STRUC, *PBBP_R47_STRUC; +#endif + + +/* */ +/* BBP R105 (FEQ control, MLD control and SIG remodulation) */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _BBP_R105_STRUC { + struct + { + UCHAR Reserve1:4; /* Reserved field */ + UCHAR EnableSIGRemodulation:1; /* Enable the channel estimation updates based on remodulation of L-SIG and HT-SIG symbols. */ + UCHAR MLDFor2Stream:1; /* Apply Maximum Likelihood Detection (MLD) for 2 stream case (reserved field if single RX) */ + UCHAR IndependentFeedForwardCompensation:1; /* Apply independent feed-forward compensation for independent stream. */ + UCHAR DetectSIGOnPrimaryChannelOnly:1; /* Under 40 MHz band, detect SIG on primary channel only. */ + } field; + + UCHAR byte; +} BBP_R105_STRUC, *PBBP_R105_STRUC; +#else +typedef union _BBP_R105_STRUC { + struct + { + UCHAR DetectSIGOnPrimaryChannelOnly:1; /* Under 40 MHz band, detect SIG on primary channel only. */ + UCHAR IndependentFeedForwardCompensation:1; /* Apply independent feed-forward compensation for independent stream. */ + UCHAR MLDFor2Stream:1; /* Apply Maximum Likelihood Detection (MLD) for 2 stream case (reserved field if single RX) */ + UCHAR EnableSIGRemodulation:1; /* Enable the channel estimation updates based on remodulation of L-SIG and HT-SIG symbols. */ + UCHAR Reserve1:4; /* Reserved field */ + } field; + + UCHAR byte; +} BBP_R105_STRUC, *PBBP_R105_STRUC; +#endif + +/* */ +/* BBP R106 (GI remover) */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _BBP_R106_STRUC { + struct + { + UCHAR EnableLowPowerFSD:1; /* enable/disable the low power FSD */ + UCHAR ShortGI_Offset40:4; /* Delay GI remover when the short GI is detected in 40MHz band (40M sampling rate) */ + UCHAR ShortGI_Offset20:3; /* Delay GI remover when the short GI is detected in 20MHz band (20M sampling rate) */ + } field; + + UCHAR byte; +} BBP_R106_STRUC, *PBBP_R106_STRUC; +#else +typedef union _BBP_R106_STRUC { + struct + { + UCHAR ShortGI_Offset20:3; /* Delay GI remover when the short GI is detected in 20MHz band (20M sampling rate) */ + UCHAR ShortGI_Offset40:4; /* Delay GI remover when the short GI is detected in 40MHz band (40M sampling rate) */ + UCHAR EnableLowPowerFSD:1; /* enable/disable the low power FSD */ + } field; + + UCHAR byte; +} BBP_R106_STRUC, *PBBP_R106_STRUC; +#endif + +/* */ +/* BBP R109 (Tx power control in 0.1dB step) */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _BBP_R109_STRUC { + struct + { + UCHAR Tx1PowerCtrl:4; /* Tx1 power control in 0.1dB step (valid: 0~10) */ + UCHAR Tx0PowerCtrl:4; /* Tx0 power control in 0.1dB step (valid: 0~10) */ + } field; + + UCHAR byte; +} BBP_R109_STRUC, *PBBP_R109_STRUC; +#else +typedef union _BBP_R109_STRUC { + struct + { + UCHAR Tx0PowerCtrl:4; /* Tx0 power control in 0.1dB step (valid: 0~10) */ + UCHAR Tx1PowerCtrl:4; /* Tx0 power control in 0.1dB step (valid: 0~10) */ + } field; + + UCHAR byte; +} BBP_R109_STRUC, *PBBP_R109_STRUC; +#endif + +/* */ +/* BBP R110 (Tx power control in 0.1dB step) */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _BBP_R110_STRUC { + struct + { + UCHAR Tx2PowerCtrl:4; /* Tx2 power control in 0.1dB step (valid: 0~10) */ + UCHAR AllTxPowerCtrl:4; /* All transmitters' fine power control in 0.1dB (valid: 0~10) */ + } field; + + UCHAR byte; +} BBP_R110_STRUC, *PBBP_R110_STRUC; +#else +typedef union _BBP_R110_STRUC { + struct + { + UCHAR AllTxPowerCtrl:4; /* All transmitters' fine power control in 0.1dB (valid: 0~10) */ + UCHAR Tx2PowerCtrl:4; /* Tx2 power control in 0.1dB step (valid: 0~10) */ + } field; + + UCHAR byte; +} BBP_R110_STRUC, *PBBP_R110_STRUC; +#endif + +/* */ +/* BBP R179 (Test config #1) */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _BBP_R179_STRUC { + struct + { + UCHAR DataIndex1:8; /* Data index #1 */ + } field; + + UCHAR byte; +} BBP_R179_STRUC, *PBBP_R179_STRUC; +#else +typedef union _BBP_R179_STRUC { + struct + { + UCHAR DataIndex1:8; /* Data index #1 */ + } field; + + UCHAR byte; +} BBP_R179_STRUC, *PBBP_R179_STRUC; +#endif /* RT_BIG_ENDIAN */ + +/* */ +/* BBP R180 (Test config #2) */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _BBP_R180_STRUC { + struct + { + UCHAR DataIndex2:8; /* Data index #2 */ + } field; + + UCHAR byte; +} BBP_R180_STRUC, *PBBP_R180_STRUC; +#else +typedef union _BBP_R180_STRUC { + struct + { + UCHAR DataIndex2:8; /* Data index #2 */ + } field; + + UCHAR byte; +} BBP_R180_STRUC, *PBBP_R180_STRUC; +#endif /* RT_BIG_ENDIAN */ + +/* */ +/* BBP R182 (Test data port) */ +/* */ +#ifdef RT_BIG_ENDIAN +typedef union _BBP_R182_STRUC { + struct + { + UCHAR DataArray:8; /* Data array indexed by BBP R179 and R180 */ + } field; + + UCHAR byte; +} BBP_R182_STRUC, *PBBP_R182_STRUC; +#else +typedef union _BBP_R182_STRUC { + struct + { + UCHAR DataArray:8; /* Data array indexed by BBP R179 and R180 */ + } field; + + UCHAR byte; +} BBP_R182_STRUC, *PBBP_R182_STRUC; +#endif /* RT_BIG_ENDIAN */ + + #define MAX_BBP_ID 136 + + + + + +/* */ +/* BBP & RF are using indirect access. Before write any value into it. */ +/* We have to make sure there is no outstanding command pending via checking busy bit. */ +/* */ +#define MAX_BUSY_COUNT 100 /* Number of retry before failing access BBP & RF indirect register */ +#define MAX_BUSY_COUNT_US 2000 /* Number of retry before failing access BBP & RF indirect register */ + +/*#define PHY_TR_SWITCH_TIME 5 // usec */ + +/*#define BBP_R17_LOW_SENSIBILITY 0x50 */ +/*#define BBP_R17_MID_SENSIBILITY 0x41 */ +/*#define BBP_R17_DYNAMIC_UP_BOUND 0x40 */ + +#define RSSI_FOR_VERY_LOW_SENSIBILITY -35 +#define RSSI_FOR_LOW_SENSIBILITY -58 +#define RSSI_FOR_MID_LOW_SENSIBILITY -65 /*-80*/ +#define RSSI_FOR_MID_SENSIBILITY -90 + + +/***************************************************************************** + 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 */ + + +#define IS_SUPPORT_PCIE_PS_L3(_pAd) FALSE +#define RTMP_PCIE_PS_L3_BBP_IO_READ8(_pAd, _bbpID, _pV, _bViaMCU) + + +/* + This marco used for the BBP read operation which didn't need via MCU. +*/ +#define BBP_IO_READ8_BY_REG_ID(_A, _I, _pV) \ + RTMP_BBP_IO_READ8((_A), (_I), (_pV), TRUE) + + +/* + basic marco for BBP write operation. + _pAd: the data structure pointer of RTMP_ADAPTER + _bbpID : the bbp register ID + _pV: data used to save the value of queried bbp register. + _bViaMCU: if we need access the bbp via the MCU. +*/ +#define RTMP_PCIE_PS_L3_BBP_IO_WRITE8(_pAd, _bbpID, _pV, _bViaMCU) + + +/* + 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) +#endif /* RTMP_MAC_PCI */ + +#ifdef CARRIER_DETECTION_SUPPORT +/*TONE_RADAR_DETECT_V2*/ +#define RTMP_CARRIER_IO_READ8(_A, _I, _V) \ +{ \ + RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, BBP_R184, _I); \ + RTMP_BBP_IO_READ8_BY_REG_ID(_A, BBP_R185, _V); \ +} +#define RTMP_CARRIER_IO_WRITE8(_A, _I, _V) \ +{ \ + RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, BBP_R184, _I); \ + RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, BBP_R185, _V); \ +} +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef DFS_SUPPORT +#define RTMP_DFS_IO_READ8(_A, _I, _V) \ +{ \ + RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, BBP_R140, _I); \ + RTMP_BBP_IO_READ8_BY_REG_ID(_A, BBP_R141, _V); \ +} + +#define RTMP_DFS_IO_WRITE8(_A, _I, _V) \ +{ \ + RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, BBP_R140, _I); \ + RTMP_BBP_IO_WRITE8_BY_REG_ID(_A, BBP_R141, _V); \ +} +#endif /*DFS_SUPPORT*/ + + + + + +struct _RMTP_ADAPTER; + +INT rtmp_phy_probe(struct _RTMP_ADAPTER *pAd); + +#ifdef RTMP_MAC_PCI +VOID RTMP_BBP_IO_READ8(struct _RTMP_ADAPTER *pAd, UCHAR Offset, UINT8 *pVal, BOOLEAN FlgValidMCR); +VOID RTMP_BBP_IO_WRITE8(struct _RTMP_ADAPTER *pAd, UCHAR Offset, UINT8 Val, BOOLEAN FlgValidMCR); +#endif /* RTMP_MAC_PCI */ +NTSTATUS RTMP_BBP_IO_READ8_BY_REG_ID(struct _RTMP_ADAPTER *pAd, UINT32 Offset, UINT8 *pVal); +NTSTATUS RTMP_BBP_IO_WRITE8_BY_REG_ID(struct _RTMP_ADAPTER *pAd, UINT32 Offset, UINT8 Val); + +#endif /* __RTMP_BBP_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/wf_phy_back.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/wf_phy_back.h new file mode 100644 index 000000000..d9e1085d8 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/phy/wf_phy_back.h @@ -0,0 +1,186 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * (c) Copyright 2013, MediaTek, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + wf_phy_back.h + + Abstract: + Unify MAC Wireless Chip related PHY CRs definition & structures + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + mtk05208 20131102 Start coding for TxV, RxV, CR_PHYMUX_11 +*/ + + +/* Ref. wf_phycr_back.doc */ +#ifndef __WF_PHY_BACK_H__ +#define __WF_PHY_BACK_H__ + +#ifndef WF_PHY_BASE +#define WF_PHY_BASE 0x00010000 +#endif + +/* ??? */ +#ifndef CR_PHYMUX_11 +#define CR_PHYMUX_11 (WF_PHY_BASE + 0x422c) +#endif +typedef union _CR_PHYMUX_11_STRUCT{ + struct { + UINT32 rsv_0:16; + UINT32 cr_phymux_num_rx:2; + UINT32 rsv_1:2; + UINT32 cr_phymux_rx1_on:1; + UINT32 cr_phymux_rx0_on:1; + UINT32 rsv_2:4; + UINT32 cr_phymux_tx1_on:1; + UINT32 cr_phymux_tx0_on:1; + UINT32 rsv_3:1; + UINT32 cr_phymux_tx_ant_man:1; + } field; + UINT32 word; +} CR_PHYMUX_11_STRUCT; + + +/* Tx Vector */ +#define CR_PHYMUX_12 (WF_PHY_BASE + 0x4230) +#define CR_PHYMUX_13 (WF_PHY_BASE + 0x4234) +#define CR_PHYMUX_14 (WF_PHY_BASE + 0x4238) +#define CR_PHYMUX_15 (WF_PHY_BASE + 0x423c) +#define CR_PHYMUX_16 (WF_PHY_BASE + 0x4240) +#define CR_PHYMUX_17 (WF_PHY_BASE + 0x4244) + +#define TXV1 CR_PHYMUX_12 +#define TXV2 CR_PHYMUX_13 +#define TXV3 CR_PHYMUX_14 +#define TXV4 CR_PHYMUX_15 +#define TXV5 CR_PHYMUX_16 +#define TXV6 CR_PHYMUX_17 + + +/* Rx Vector */ +#define CR_PHYMUX_18 (WF_PHY_BASE + 0x4248) +#define CR_PHYMUX_19 (WF_PHY_BASE + 0x425c) +#define CR_PHYMUX_20 (WF_PHY_BASE + 0x4250) +#define CR_PHYMUX_21 (WF_PHY_BASE + 0x4254) +#define CR_PHYMUX_22 (WF_PHY_BASE + 0x4258) +#define CR_PHYMUX_23 (WF_PHY_BASE + 0x425c) + +#define RXV1 CR_PHYMUX_18 +typedef union _RO_RXV1_STRUCT{ + struct { +#define LEGACY_CCK_MSK 0x7 +#define LEGACY_OFDM_MSK 0xf + UINT32 tx_rate:7; //[0..6] + UINT32 ht_stbc:2; //[7..8] +#define BCC 0x0 +#define LDPC 0x1 + UINT32 ht_adcode:1; //[9] + UINT32 ht_ext_ltf:2; //[10..11] +#define LEGACY_CCK_MODE 0x0 +#define LEGACY_OFDM_MODE 0x1 +#define MIXED_MODE 0x2 +#define GREEN_MODE 0x3 +#define VHT_MODE 0x4 + UINT32 tx_mode:3; //[12..14] +#define FEQ_20M_MODE 0x0 +#define FEQ_40M_MODE 0x1 +#define FEQ_80M_MODE 0x2 +#define FEQ_160M_MODE 0x3 + UINT32 fr_mode:2; //[15..16] + UINT32 vht_a1_b2:1; //[17] + UINT32 ht_aggregation:1; //[18] + UINT32 ht_short_gi:1; //[19] + UINT32 ht_smooth:1; //[20] + UINT32 ht_no_sound:1; //[21] + UINT32 vhta2_b8_b1:8; //[22..29] + UINT32 vhta1_b5_b4:2; //[30..31] + } field; + UINT32 word; +} RO_RXV1_STRUCT; + +#define RXV2 CR_PHYMUX_19 +typedef union _RO_RXV2_STRUCT{ + struct { +#define LEGACY_RX_LEN_MSK 0x00000fff +#define HT_RX_LEN_MSK 0x0000ffff +#define VHT_RX_LEN_MSK 0x001fffff + UINT32 length:21; + UINT32 vhta1_b16_b6:11; + } field; + UINT32 word; +} RO_RXV2_STRUCT; + +#define RXV3 CR_PHYMUX_20 +typedef union _RO_RXV3_STRUCT{ + struct { + UINT32 vhta1_b21_b17:5; + UINT32 ofdm_freq_trans_detect:1; + UINT32 aci_detect:1; + UINT32 sel_antenna:1; + UINT32 rcpi0:8; + UINT32 fagc0_eq_cal:1; + UINT32 fagc0_cal_gain:3; + UINT32 rcpi1:8; + UINT32 fagc1_eq_cal:1; + UINT32 fagc1_cal_gain:3; + } field; + UINT32 word; +} RO_RXV3_STRUCT; + +#define RXV4 CR_PHYMUX_21 +typedef union _RO_RXV4_STRUCT{ + struct { + UINT32 ib_rssi:8; + UINT32 wb_rssi:8; + UINT32 fagc_lpf_gain:4; + UINT32 rcpi2:8; + UINT32 fagc2_eq_cal:1; + UINT32 fagc2_cal_gain:3; + } field; + UINT32 word; +} RO_RXV4_STRUCT; + +#define RXV5 CR_PHYMUX_22 +typedef union _RO_RXV5_STRUCT{ + struct { + UINT32 fagc_lna_gain:2; + UINT32 rsv_0:5; +#define RXV5_MISC_OFDM_FOE 0x0fff +#define RXV5_MISC_OFDM_LTF_PROC_TIME (0x7f << 12) +#define RXV5_MISC_OFDM_LTF_SNR (0x3f << 19) +#define RXV5_MISC_CCK_FOE 0x07ff +#define RXV5_MISC_CCK_INIT_DFE_LMS_ERR (0x3ff << 11) + UINT32 misc:25; + } field; + UINT32 word; +} RO_RXV5_STRUCT; + +#define RXV6 CR_PHYMUX_23 +typedef union _RO_RXV6_STRUCT{ + struct { + UINT32 nf0:8; + UINT32 nf1:8; + UINT32 nf2:8; + UINT32 rx_valid_indicator:1; + UINT32 nsts:3; + UINT32 cags_state:3; + UINT32 rsv_0:1; + } field; + UINT32 word; +} RO_RXV6_STRUCT; + + +#endif /* __WF_PHY_BACK_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/pmf.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/pmf.h new file mode 100644 index 000000000..46c1a9e07 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/pmf.h @@ -0,0 +1,130 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Abstract: + IEEE P802.11w + + */ +#ifndef __PMF_H +#define __PMF_H +#ifdef DOT11W_PMF_SUPPORT + +VOID PMF_PeerAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PMF_MlmeSAQueryReq( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID PMF_PeerSAQueryReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PMF_PeerSAQueryRspAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PMF_DerivePTK( + IN PRTMP_ADAPTER pAd, + IN UCHAR *PMK, + IN UCHAR *ANonce, + IN UCHAR *AA, + IN UCHAR *SNonce, + IN UCHAR *SA, + OUT UCHAR *output, + IN UINT len); + +VOID PMF_DeriveIGTK( + IN PRTMP_ADAPTER pAd, + OUT UCHAR *output); + +VOID PMF_InsertIGTKKDE( + IN PRTMP_ADAPTER pAd, + IN INT apidx, + IN PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +BOOLEAN PMF_ExtractIGTKKDE( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pBuf, + IN INT buf_len +#ifdef APCLI_DOT11W_PMF_SUPPORT + , IN MAC_TABLE_ENTRY *pEntry +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + ); + +VOID PMF_MakeRsnIeGMgmtCipher( + IN PRTMP_ADAPTER pAd, + IN UCHAR ElementID, + IN UCHAR apidx, + OUT PUCHAR pRsnIe, + OUT UCHAR *rsn_len); + +NTSTATUS PMF_RsnCapableValidation( + IN PRTMP_ADAPTER pAd, + IN PUINT8 pRsnie, + IN UINT rsnie_len, + IN BOOLEAN self_MFPC, + IN BOOLEAN self_MFPR, +#ifdef CONFIG_SECURITY_IMPROVEMENT_SUPPORT + IN UCHAR end_field, +#endif +#ifdef CONFIG_OWE_SUPPORT + IN INT apidx, +#endif + IN PMAC_TABLE_ENTRY pEntry); + +BOOLEAN PMF_PerformTxFrameAction( + IN PRTMP_ADAPTER pAd, + OUT PNDIS_PACKET pPacket); + +BOOLEAN PMF_PerformRxFrameAction( + IN PRTMP_ADAPTER pAd, + IN RX_BLK *pRxBlk); + +int PMF_RobustFrameClassify( + IN PHEADER_802_11 pHdr, + IN PUCHAR pFrame, + IN UINT frame_len, + IN PUCHAR pData, + IN BOOLEAN IsRx); + +int PMF_EncapBIPAction( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pMgmtFrame, + IN UINT mgmt_len); + +void rtmp_read_pmf_parameters_from_file( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *tmpbuf, + IN RTMP_STRING *pBuffer); + +INT Set_PMFMFPC_Proc ( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_PMFMFPR_Proc ( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_PMFSHA256_Proc ( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +#endif /* DOT11W_PMF_SUPPORT */ + +#endif /* __PMF_H */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/pmf_cmm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/pmf_cmm.h new file mode 100644 index 000000000..345546fe2 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/pmf_cmm.h @@ -0,0 +1,86 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + + Abstract: + Management Frame Protection Required is defined in IEEE802.11w + + Define all structures, data types that rtmp.h needed in this file. Don't + put any sturctures and functions definition which refer to RTMP_ADAPTER + Here. + +***************************************************************************/ + + +#ifdef DOT11W_PMF_SUPPORT + +#ifndef __PMF_CMM_H__ +#define __PMF_CMM_H__ + +#include "rtmp_type.h" +#include "dot11w_pmf.h" + +#define NORMAL_FRAME 0 +#define ERROR_FRAME 1 +#define NOT_ROBUST_GROUP_FRAME 2 +#define NOT_ROBUST_UNICAST_FRAME 3 +#define UNICAST_ROBUST_FRAME 4 +#define GROUP_ROBUST_FRAME 5 + +typedef enum _PMF_STATUS_NUM +{ + PMF_STATUS_SUCCESS, + PMF_POLICY_VIOLATION, + PMF_UNICAST_ENCRYPT_FAILURE, + PMF_ENCAP_BIP_FAILURE, + PMF_UNICAST_DECRYPT_FAILURE, + PMF_EXTRACT_BIP_FAILURE, + PMF_STATUS_RESV +} PMF_STATUS_NUM; + +/* + * Management Frame Protection Required is defined in IEEE802.11w + */ +typedef struct GNU_PACKED _PMF_CFG +{ + /* + * A STA sets this bit to 1 to advertise that protection of Robust + * Management Frames is enabled. + */ + BOOLEAN MFPC; /* This is actual active */ + BOOLEAN Desired_MFPC; /* This is user desired */ + + /* + * A STA sets this bit to 1 to advertise that protection of + * Robust Management Frames is mandatory. + * If a STA sets this bit to 1, then that STA only allows RSNAs + * from STAs which provide Management Frame Protection. + */ + BOOLEAN MFPR; /* This is actual active */ + BOOLEAN Desired_MFPR; /* This is user desired */ + + BOOLEAN PMFSHA256; /* This is actual active */ + BOOLEAN Desired_PMFSHA256; /* This is user desired */ + + UINT8 IGTK_KeyIdx; /* It shall be 4 or 5 */ + UCHAR IGTK[2][LEN_AES_GTK]; + UCHAR IPN[2][LEN_WPA_TSC]; +} PMF_CFG, *PPMF_CFG; + + +#endif /* __PMF_CMM_H__ */ +#endif /* DOT11W_PMF_SUPPORT */ + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/radar.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/radar.h new file mode 100644 index 000000000..60e2bf8ab --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/radar.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, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + radar.h + + Abstract: + CS/DFS common functions. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#ifndef __RADAR_H__ +#define __RADAR_H__ + +#define DEFAULT_CAL_BUF_TIME 60 +#define DEFAULT_CAL_BUF_TIME_MAX 0x10000 + +/* RESTRICTION_BAND_1: 5600MHz ~ 5650MHz */ +#define RESTRICTION_BAND_1(_pAd) \ + (_pAd->CommonCfg.RegTransmitSetting.field.BW == BW_40 ? \ + ((_pAd->CommonCfg.Channel >= 116) && (_pAd->CommonCfg.Channel <= 128)) : \ + ((_pAd->CommonCfg.Channel >= 120) && (_pAd->CommonCfg.Channel <= 128))) + +#define IS_DOT11_H_RADAR_STATE(_pAd, _RadarState) \ + ( (_pAd->CommonCfg.Channel > 14) \ + && (_pAd->CommonCfg.bIEEE80211H == 1) \ + && RadarChannelCheck(_pAd, _pAd->CommonCfg.Channel) \ + && _pAd->Dot11_H.RDMode == _RadarState) + +/* 802.11H */ +typedef struct _DOT11_H { + /* 802.11H and DFS related params */ + UCHAR CSCount; /*Channel switch counter */ + UCHAR CSPeriod; /*Channel switch period (beacon count) */ + USHORT RDCount; /*Radar detection counter, if RDCount > ChMovingTime, start to send beacons*/ + UCHAR RDMode; /*Radar Detection mode */ + UCHAR org_ch; + UCHAR new_channel; + USHORT ChMovingTime; + BOOLEAN bDFSIndoor; + ULONG InServiceMonitorCount; /* unit: sec */ + ULONG CalBufTime; /* A Timing buffer for befroe calibrations which generates Tx signals */ +} DOT11_H, *PDOT11_H; + +BOOLEAN RadarChannelCheck( + IN PRTMP_ADAPTER pAd, + IN UCHAR Ch); + +VOID RadarStateCheck( + IN PRTMP_ADAPTER pAd); + +ULONG JapRadarType( + IN PRTMP_ADAPTER pAd); + +UCHAR get_channel_by_reference( + IN PRTMP_ADAPTER pAd, + IN UINT8 mode); + +#ifdef CONFIG_AP_SUPPORT +VOID ChannelSwitchingCountDownProc( + IN PRTMP_ADAPTER pAd); +#endif /* CONFIG_AP_SUPPORT */ + +VOID RadarDetectPeriodic( + IN PRTMP_ADAPTER pAd); + +INT Set_CSPeriod_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_ChMovingTime_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_BlockChReset_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#if defined(DFS_SUPPORT) || defined(CARRIER_DETECTION_SUPPORT) +INT Set_RadarShow_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +VOID CckMrcStatusCtrl( + IN PRTMP_ADAPTER pAd); + +VOID RadarGLRTCompensate( + IN PRTMP_ADAPTER pAd); + +#endif /*defined(DFS_SUPPORT) || defined(CARRIER_DETECTION_SUPPORT)*/ + +#endif /* __RADAR_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/routing_tab.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/routing_tab.h new file mode 100644 index 000000000..24fc8085f --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/routing_tab.h @@ -0,0 +1,468 @@ +#ifndef __ROUTING_TAB_H__ + + +#define __ROUTING_TAB_H__ + + +/* + + + *************************************************************************** + + + * Ralink Tech Inc. + + + * 5F., No.36, Taiyuan St., Jhubei City, + + + * Hsinchu County 302, + + + * Taiwan, R.O.C. + + + * + + + * (c) Copyright 2002-2009, Ralink Technology, Inc. + + + * + + + * All rights reserved. Ralink's source code is an unpublished work and the + + + * use of a copyright notice does not imply otherwise. This source code + + + * contains confidential trade secret material of Ralink Tech. Any attemp + + + * or participation in deciphering, decoding, reverse engineering or in any + + + * way altering the source code is stricitly prohibited, unless the prior + + + * written consent of Ralink Technology, Inc. is obtained. + + + *************************************************************************** + + + + + + + + + Module Name: + + + routing_tab.h + + + + + + Abstract: + + + This is a tab used to record all entries behind associated APClinet or STA/PC. + + + + + + Revision History: + + + Who When What + + + --------- ---------- ---------------------------------------------- + + + */ + + + + + +#ifdef ROUTING_TAB_SUPPORT + + +#include "rtmp_def.h" + + + + +#define ROUTING_ENTRY_AGEOUT (10*OS_HZ) /* seconds */ + + +#define ROUTING_ENTRY_RETRY_TIME (2*OS_HZ) /* seconds */ + + +#define ROUTING_ENTRY_MAX_RETRY 5 + + +#define ROUTING_POOL_SIZE 128 + + +#define ROUTING_HASH_TAB_SIZE 64 /* the legth of hash table must be power of 2. */ + + +typedef struct _RTMP_ADAPTER *PRTMP_ADAPTER; + + +enum ROUTING_ENTRY_FLAG { + + + ROUTING_ENTRY_NONE = 0x0, + + + ROUTING_ENTRY_A4 = 0x1, + + + ROUTING_ENTRY_IGMP = 0x2, + + + ROUTING_ALL_MASK = 0x3 + + +}; + + + + + +#define IS_VALID_ROUTING_ENTRY_FLAG(_x) (((_x) & ROUTING_ALL_MASK) != 0) + + +#define IS_ROUTING_ENTRY(_x) ((_x)->EntryFlag != ROUTING_ENTRY_NONE) + + +#define SET_ROUTING_ENTRY(_x, _y) ((_x)->EntryFlag |= (_y)) + + +#define CLEAR_ROUTING_ENTRY(_x, _y) ((_x)->EntryFlag &= ~(_y)) + + +#define ROUTING_ENTRY_TEST_FLAG(_x, _y) (((_x)->EntryFlag & (_y)) != 0) + + + + + +typedef struct _ROUTING_ENTRY { + + + struct _ROUTING_ENTRY *pNext; + + + UINT32 EntryFlag; + + + ULONG KeepAliveTime; + + + ULONG RetryTime; + + + UCHAR Retry; + + + UCHAR Valid; + + + UCHAR Wcid; + + + UINT32 IPAddr; + + + UCHAR Mac[MAC_ADDR_LEN]; +#ifdef A4_CONN + UCHAR NeedRefresh; +#endif +} ROUTING_ENTRY, *PROUTING_ENTRY; + + + + + + + + +VOID RoutingTabInit( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN UINT32 Flag); + + + + + +VOID RoutingTabDestory( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN UINT32 Flag); + + + + + +VOID RoutingTabClear( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN UINT32 Flag); + + + + + +PROUTING_ENTRY RoutingTabGetFree( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex); + + + + + +VOID RoutingTabSetAllFree( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN UCHAR Wcid, + + + IN UINT32 Flag); + + + + + +VOID RoutingTabSetOneFree( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN PUCHAR pMac, + + + IN UINT32 Flag); + + + + + +VOID RoutingEntryRefresh( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN PROUTING_ENTRY pRoutingEntry); + + + + + +VOID RoutingEntrySet( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN UCHAR Wcid, + + + IN PUCHAR pMac, + + + IN PROUTING_ENTRY pRoutingEntry); + + + + + +INT RoutingTabGetEntryCount( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex); + + + + + +INT32 GetHashID( + + + IN PUCHAR pMac); + + + + + +PROUTING_ENTRY GetRoutingTabHead( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN INT32 Index); + + + + + +BOOLEAN GetRoutingEntryAll( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN UCHAR Wcid, + + + IN UINT32 Flag, + + + IN INT32 BufMaxCount, + + + OUT ROUTING_ENTRY **pEntryListBuf, + + + OUT PUINT32 pCount); + + + + + +PROUTING_ENTRY RoutingTabLookup( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN PUCHAR pMac, + + + IN BOOLEAN bUpdateAliveTime, + + + OUT UCHAR* pWcid); + + + + + +VOID RoutingTabARPLookupUpdate( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN PROUTING_ENTRY pRoutingEntry, + + + IN UINT32 ARPSenderIP); + + + + + +INT RoutingEntrySendAliveCheck( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex, + + + IN PROUTING_ENTRY pRoutingEntry, + + + IN UCHAR *pSrcMAC, + + + IN UINT32 SrcIP); + + + + + +VOID RoutingTabMaintain( + + + IN PRTMP_ADAPTER pAd, + + + IN UCHAR ifIndex); + + + + + +#endif /* ROUTING_TAB_SUPPORT */ + + +#endif /* __ROUTING_TAB_H__ */ + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rrm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rrm.h new file mode 100644 index 000000000..70dc9900d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rrm.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-2006, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + Abstract: + +***************************************************************************/ + + +#ifndef __RRM_H +#define __RRM_H + +#ifdef DOT11K_RRM_SUPPORT +#include "rtmp_type.h" +#include "rrm_cmm.h" + +#define RRM_QUIET_CNT_DEC(_V, _M) \ + ((_V) == 0 ? (_V = _M) : (_V)--) + +#define IS_RRM_ENABLE(_P, _I) \ + ((_P)->ApCfg.MBSSID[(_I)].RrmCfg.bDot11kRRMEnable == TRUE) + +#define IS_RRM_CAPABLE(_P) \ + ((_P)->CapabilityInfo & RRM_CAP_BIT) + +#define IS_RRM_BEACON_MEASURE(_P) \ + ((_P)->RrmEnCap.field.BeaconActiveMeasureCap == 1) +#define IS_RRM_BEACON_PASSIVE_MEASURE(_P) \ + ((_P)->RrmEnCap.field.BeaconPassiveMeasureCap == 1) +#define IS_RRM_BEACON_TABLE_MEASURE(_P) \ +((_P)->RrmEnCap.field.BeaconTabMeasureCap == 1) + +#define IS_RRM_QUIET(_P, _I) \ + ((_P)->ApCfg.MBSSID[(_I)].RrmCfg.QuietCB.QuietState == RRM_QUIET_SILENT) + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +void RRM_ReadParametersFromFile( + IN PRTMP_ADAPTER pAd, + RTMP_STRING *tmpbuf, + RTMP_STRING *buffer); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT Set_Dot11kRRM_Enable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT Set_BeaconReq_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_BeaconReq_RandInt_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT Set_LinkMeasureReq_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT Set_TxStreamMeasureReq_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT Set_RRM_Selftest_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT RRM_InfoDisplay_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_CfgInit( + IN PRTMP_ADAPTER pAd); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_QuietUpdata( + IN PRTMP_ADAPTER pAd); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertBcnReqIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pBcnReq); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertBcnReqSsidSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pSsid, + IN UINT8 SsidLen); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertBcnReqRepCndSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 RepCnd, + IN UINT8 Threshold); + +VOID RRM_InsertBcnReqRepDetailSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Detail); + +/* + ========================================================================== + Description: + Insert RRM Enable Capabilitys IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + + Return : None. + ========================================================================== + */ +VOID RRM_InsertRRMEnCapIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN INT BssIdx); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertNeighborRepIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Len, + IN PUINT8 pBssid, + IN RRM_BSSID_INFO BssidInfo, + IN UINT8 RegClass, + IN UINT8 Channel, + IN UINT8 PhyType); + +VOID RRM_InsertNeighborRepIE_New( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Len, + IN RRM_PNEIGHBOR_REP_INFO pNeighborRepInfo); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertNeighborTSFOffsetSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT16 TSFOffset, + IN UINT16 BcnInterval); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertQuietIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 QuietCnt, + IN UINT8 QuietPeriod, + IN UINT8 QuietDuration, + IN UINT8 QuietOffset); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertBssACDelayIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertBssAvailableACIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertRequestIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 ie_num, + IN PUINT8 ie_list); + +VOID RRM_InsertRequestIE_NEW( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pRequest, + IN UINT8 RequestLen); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertTxStreamReqIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pBuf); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_InsertTxStreamReqTriggerReportSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN PUCHAR pBuf); + + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_EnqueueBcnReq( + IN PRTMP_ADAPTER pAd, + IN UINT8 Aid, + IN UINT8 IfIdx, + IN PRRM_MLME_BCN_REQ_INFO pMlmeBcnReq); + + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_EnqueueNeighborRep( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UINT8 DialogToken, + IN PCHAR pSsid, + IN UINT8 SsidLen); + +VOID RRM_EnqueueLinkMeasureReq( + IN PRTMP_ADAPTER pAd, + IN UINT8 Aid, + IN UINT8 apidx); + +VOID RRM_EnqueueTxStreamMeasureReq( + IN PRTMP_ADAPTER pAd, + IN UINT8 Aid, + IN UINT8 apidx, + IN PRRM_MLME_TRANSMIT_REQ_INFO pMlmeTxMeasureReq); +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +BOOLEAN RRM_PeerNeighborReqSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT8 pDialogToken, + OUT PCHAR *pSsid, + OUT PUINT8 pSsidLen); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +BOOLEAN RRM_PeerMeasureReportSanity( + IN PRTMP_ADAPTER pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUINT8 pDialogToken, + OUT PMEASURE_REPORT_INFO pMeasureReportInfo, + OUT PVOID *pMeasureRep); + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +VOID RRM_PeerNeighborReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem) ; + +VOID RRM_PeerMeasureRepAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +INT rrm_send_beacon_req_param( + IN PRTMP_ADAPTER pAd, + IN p_bcn_req_info pBcnReq, + IN UINT32 BcnReqLen); + +int check_rrm_BcnReq_custom_params( + IN RTMP_ADAPTER * pAd, + IN p_bcn_req_info pBcnReq); + +VOID set_rrm_BcnReq_optional_params( + IN RTMP_ADAPTER * pAd, + IN p_bcn_req_info p_beacon_req); + +void compose_rrm_BcnReq_ie( + IN RTMP_ADAPTER * pAd, + OUT PUCHAR beacon_req_ie, + OUT PUINT32 beacon_req_ie_len, + IN p_bcn_req_info p_beacon_req, + IN UINT8 measure_req_token, + IN UCHAR ifidx); + +void wext_send_bcn_rsp_event(PNET_DEV net_dev, + PUCHAR peer_mac_addr, + PUCHAR bcn_rsp, + UINT32 bcn_rsp_len, + UINT8 dia_token); + + +void init_rrm_capabilities(PRRM_CONFIG pRrmCfg, BSS_STRUCT *pMBss); + +int set_rrm_capabilities(RTMP_ADAPTER *pAd, UINT8 *rrm_capabilities); + +int rrm_MsgHandle(PRTMP_ADAPTER pAd, RTMP_IOCTL_INPUT_STRUCT *wrq); + +int RRM_EnqueueBcnReqAction( + IN PRTMP_ADAPTER pAd, + IN UINT8 IfIdx, + IN p_bcn_req_data_t p_bcn_req_data); + +int Set_Dot11kRRM_Enable(RTMP_ADAPTER *pAd, UINT8 enable); + +int rrm_send_beacon_req(RTMP_ADAPTER *pAd, + p_bcn_req_data_t p_bcn_req_data, UINT32 bcn_req_len); + +void RRM_measurement_report_to_host(RTMP_ADAPTER *pAd, MLME_QUEUE_ELEM *Elem); + +int rrm_send_nr_rsp_param(RTMP_ADAPTER *pAd, + p_rrm_nrrsp_info_custom_t p_nr_rsp_data, + UINT32 nr_rsp_data_len); + +int rrm_send_nr_rsp_ie(RTMP_ADAPTER *pAd, + p_nr_rsp_data_t p_nr_rsp_data, + UINT32 nr_rsp_data_len); + + +int check_rrm_nrrsp_custom_params(RTMP_ADAPTER *pAd, + p_rrm_nrrsp_info_custom_t p_nr_rsp_data, + UINT32 nr_rsp_data_len); + +void compose_rrm_nrrsp_ie(RTMP_ADAPTER *pAd, PUCHAR nr_rsp_ie, PUINT32 p_ie_len, + struct nr_info *p_candidate_info, UINT8 cnt); + +VOID send_nr_rsp_param_toair( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID send_nr_resp_toair( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +void wext_send_nr_req_event( + IN PNET_DEV net_dev, + IN const char *peer_mac_addr, + IN const char *nr_req, + IN UINT16 nr_req_len); + + +int rrm_send_nr_rsp( + IN RTMP_ADAPTER *pAd, + IN p_nr_rsp_data_t p_nr_rsp_data); + + +int rrm_set_handle_nr_req_flag( + IN RTMP_ADAPTER *pAd, + IN UINT8 by_daemon); + +VOID NRRspTimeout( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + + +enum NR_STATE NRPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem); + + +VOID NRStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID RRMBcnReqStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[] + ); + +enum BCN_STATE BCNPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM * Elem); + + +#endif /* DOT11K_RRM_SUPPORT */ + +#endif /* __RRM_H */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rrm_cmm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rrm_cmm.h new file mode 100644 index 000000000..e7e925456 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rrm_cmm.h @@ -0,0 +1,206 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2006, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + Abstract: + +***************************************************************************/ + + +#ifndef __RRM_CMM_H +#define __RRM_CMM_H + + +#ifdef DOT11K_RRM_SUPPORT +#include "rtmp_type.h" +#include "dot11k_rrm.h" + + +#define RRM_DEFAULT_QUIET_PERIOD 200 +#define RRM_DEFAULT_QUIET_DURATION 30 +#define RRM_DEFAULT_QUIET_OFFSET 20 + +#define RRM_QUIET_IDLE 0 +#define RRM_QUIET_SILENT 1 +#define MAX_NUM_OF_REQ_IE 13 + +typedef struct _RRM_QUIET_CB +{ + BOOLEAN QuietState; + UINT16 CurAid; + UINT8 MeasureCh; + RALINK_TIMER_STRUCT QuietOffsetTimer; + RALINK_TIMER_STRUCT QuietTimer; + + + UINT8 QuietCnt; + UINT8 QuietPeriod; + UINT8 QuietDuration; + UINT8 QuietOffset; +} RRM_QUIET_CB, *PRRM_QUIET_CB; + +typedef struct _RRM_CONFIG +{ + BOOLEAN bDot11kRRMEnable; + BOOLEAN bDot11kRRMNeighborRepTSFEnable; + RRM_QUIET_CB QuietCB; + /* FOR AP Measurement Report */ + UINT8 PeerMeasurementToken; + BOOLEAN bPeerReqLCI; + BOOLEAN bPeerReqCIVIC; + RRM_EN_CAP_IE rrm_capabilities; + RRM_EN_CAP_IE max_rrm_capabilities; +} RRM_CONFIG, *PRRM_CONFIG; + +typedef union _RRM_BCN_REQ_CAP +{ + struct + { +#ifdef RT_BIG_ENDIAN + UINT8:6; + UINT8 ChannelRep:1; + UINT8 ReportCondition:1; +#else + UINT8 ReportCondition:1; + UINT8 ChannelRep:1; + UINT8 :6; +#endif + + } field; + UINT8 word; +} RRM_BCN_REQ_CAP, *PRRM_BCN_REQ_CAP; + +typedef struct _RRM_MLME_BCN_REQ_INFO +{ + UINT16 MeasureDuration; + UINT8 Bssid[MAC_ADDR_LEN]; + UINT8 Addr[MAC_ADDR_LEN]; + PUINT8 pSsid; + UINT8 SsidLen; + UINT8 RegulatoryClass; + UINT8 MeasureCh; + UINT8 MeasureMode; + RRM_BCN_REQ_CAP BcnReqCapFlag; + UINT8 ChRepRegulatoryClass[MAX_NUM_OF_REGULATORY_CLASS]; + UINT8 ChRepList[MAX_NUM_OF_CHS]; + UINT16 RandInt; + UINT8 report_detail; + UINT8 request_ie_num; + UINT8 request_ie[MAX_NUM_OF_REQ_IE]; +} RRM_MLME_BCN_REQ_INFO, *PRRM_MLME_BCN_REQ_INFO; + +typedef struct _RRM_MLME_TRANSMIT_REQ_INFO +{ + UINT16 MeasureDuration; + UINT8 Tid; + UINT8 BinRange; + BOOLEAN bTriggerReport; + BOOLEAN ArvCondition; + BOOLEAN ConsecutiveCondition; + BOOLEAN DelayCondition; + UINT8 AvrErrorThreshold; + UINT8 ConsecutiveErrorThreshold; + UINT8 DelayThreshold; + UINT8 MeasureCnt; + UINT8 TriggerTimeout; + UINT8 bDurationMandatory; +} RRM_MLME_TRANSMIT_REQ_INFO, *PRRM_MLME_TRANSMIT_REQ_INFO; + + +#define BCN_MACHINE_BASE 0 + +/* BCN states */ +enum BCN_STATE { + BCN_IDLE, + WAIT_BCN_REQ, + WAIT_BCN_REP, + MAX_BCN_STATE, +}; + + +/* BCN events */ +enum BCN_EVENT { + BCN_REQ, + BCN_REQ_RAW, + BCN_REP_TIMEOUT, + MAX_BCN_MSG, +}; + +#define BCN_FUNC_SIZE (MAX_BCN_STATE * MAX_BCN_MSG) +#define BCN_REP_TIMEOUT_VALUE (2*60*1000) + + +#define NR_MACHINE_BASE 0 + +/* NR states */ +enum NR_STATE { + WAIT_NR_RSP, + NR_UNKNOWN, + MAX_NR_STATE, +}; + + +/* NR events */ +enum NR_EVENT { + NR_RSP, + NR_RSP_PARAM, + NR_RSP_TIMEOUT, + MAX_NR_MSG, +}; + +#define NR_FUNC_SIZE (MAX_NR_STATE * MAX_NR_MSG) +#define NR_RSP_TIMEOUT_VALUE (2*60*1000) + +typedef struct GNU_PACKED _BCN_EVENT_DATA { + UINT8 ControlIndex; + UINT8 MeasureReqToken; + UINT8 stamac[MAC_ADDR_LEN]; + UINT16 DataLen; + UCHAR Data[0]; +} BCN_EVENT_DATA, *PBCN_EVENT_DATA; + +/* +* this struct is used for mlme +*/ +typedef struct GNU_PACKED _NR_EVENT_DATA { + UINT8 ControlIndex; + UINT8 MeasureReqToken; + UINT8 stamac[MAC_ADDR_LEN]; + UINT16 DataLen; + UCHAR Data[0]; +} NR_EVENT_DATA, *PNR_EVENT_DATA; + +typedef struct GNU_PACKED _RRM_FRAME { + HEADER_802_11 Hdr; + UCHAR Category; + union { + struct { + UCHAR Action; + UCHAR DialogToken; + UCHAR Variable[0]; + } GNU_PACKED NR_RSP; + } u; +} RRM_FRAME, *PRRM_FRAME; + +DECLARE_TIMER_FUNCTION(WaitPeerBCNRepTimeout); +DECLARE_TIMER_FUNCTION(WaitNRRspTimeout); + + +#endif /* DOT11K_RRM_SUPPORT */ + +#endif /* __RRM_CMM_H */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_cal.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_cal.h new file mode 100644 index 000000000..c8320e627 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_cal.h @@ -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-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(RTMP_ADAPTER *pAd, RTMP_STRING *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(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_TestDPDCalibration_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_TestDPDCalibrationTX0_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_TestDPDCalibrationTX1_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +VOID LOFT_IQ_Calibration( + IN RTMP_ADAPTER *pAd); + +BOOLEAN BW_Filter_Calibration( + IN PRTMP_ADAPTER pAd, + IN BOOLEAN bTxCal); + +VOID RxDCOC_Calibration( + IN PRTMP_ADAPTER pAd); + +VOID RXIQ_Calibration( + IN PRTMP_ADAPTER pAd); + +VOID RF_SELF_TXDC_CAL( + IN PRTMP_ADAPTER pAd); + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_config.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_config.h new file mode 100644 index 000000000..467a417a5 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_config.h @@ -0,0 +1,342 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-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__ + + +#include "rtmp_comm.h" + +#include "rtmp_def.h" +#include "rtmp_chip.h" +#include "rtmp_timer.h" + +#ifdef WIFI_DIAG +#include "diag.h" +#endif + +#ifdef WH_EZ_SETUP +#include "easy_setup/ez_hooks.h" +#endif + + +#ifdef AGS_SUPPORT +#include "ags.h" +#endif /* AGS_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef BAND_STEERING +#include "band_steering_def.h" +#endif /* BAND_STEERING */ +#endif +#ifdef CONFIG_FPGA_MODE +#include "fpga/fpga_ctl.h" +#endif + +#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" */ +#ifdef ROUTING_TAB_SUPPORT +#include "routing_tab.h" +#endif /* ROUTING_TAB_SUPPORT */ +#include "rtmp.h" +#include "wpa.h" +#include "chlist.h" +#include "spectrum.h" +#ifdef CONFIG_AP_SUPPORT +#include "ap.h" +#include "ap_autoChSel.h" +#endif /* CONFIG_AP_SUPPORT */ +#include "rt_os_util.h" + +#include "eeprom.h" +#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT) +#include "mcu/mcu.h" +#endif + +#ifdef RTMP_EFUSE_SUPPORT +#include "efuse.h" +#endif /* RTMP_EFUSE_SUPPORT */ + +#undef AP_WSC_INCLUDED +#undef STA_WSC_INCLUDED +#undef WSC_INCLUDED + +#include "rt_os_net.h" + + +#ifdef UAPSD_SUPPORT +#include "uapsd.h" +#endif /* UAPSD_SUPPORT */ + +#include "tx_power.h" + +#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 MWDS +#include "mwds.h" +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef WH_EVENT_NOTIFIER +#include "event_notifier.h" +#endif /* WH_EVENT_NOTIFIER */ + +#ifdef MAT_SUPPORT +#include "mat.h" +#endif /* MAT_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 CONFIG_ATE +#include "ate_agent.h" +#include "ate.h" +#endif + + +#ifdef CONFIG_QA +#include "qa_agent.h" +#endif /* CONFIG_QA */ + +#ifdef CONFIG_QA +#ifndef CONFIG_ATE +#error "For supporting QA GUI, please set HAS_ATE=y and HAS_QA_SUPPORT=y." +#endif /* CONFIG_ATE */ +#endif /* CONFIG_QA */ + + + +#ifdef WAPI_SUPPORT +#include "wapi.h" +#endif /* WAPI_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT +#include "rrm.h" +#endif /* DOT11K_RRM_SUPPORT */ + + +#if defined(AP_WSC_INCLUDED) || defined(STA_WSC_INCLUDED) +#define WSC_INCLUDED +#endif + +#ifdef CONFIG_AP_SUPPORT +#ifdef WDS_SUPPORT +#define RALINK_PASSPHRASE "Ralink" +#endif /* WDS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef APCLI_WPA_SUPPLICANT_SUPPORT +#ifndef APCLI_SUPPORT +#error "Build Apcli for being controlled by NetworkManager or wext, please set HAS_APCLI_SUPPORT=y and HAS_APCLI_WPA_SUPPLICANT=y" +#endif /* APCLI_SUPPORT */ +#define WPA_SUPPLICANT_SUPPORT +#endif /* APCLI_WPA_SUPPLICANT_SUPPORT */ + + + +#ifdef WSC_INCLUDED +#include "crypt_biginteger.h" +#include "crypt_dh.h" +#include "wsc_tlv.h" + +#ifdef WSC_NFC_SUPPORT +#include "nfc.h" +#endif /* WSC_NFC_SUPPORT */ +#endif /* WSC_INCLUDED */ + + +#ifdef IKANOS_VX_1X0 +#include "vr_ikans.h" +#endif /* IKANOS_VX_1X0 */ + +#ifdef DOT11R_FT_SUPPORT +#include "ft.h" +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT +#include "rrm.h" +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT +#include "pmf.h" +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT +#include "wnm.h" +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef WAPI_SUPPORT +#include "wapi.h" +#endif /* WAPI_SUPPORT */ + + + +#include "vendor.h" +#ifdef DOT11_VHT_AC +#include "vht.h" +#endif /* DOT11_VHT_AC */ + + + + +#ifdef WORKQUEUE_BH +#include +#endif /* WORKQUEUE_BH / */ + + +#ifdef BAND_STEERING +#include "band_steering.h" +#endif /* BAND_STEERING */ + + + +#ifdef RLT_MAC +#include "mac/mac_ral/fce.h" +#endif /* RLT_MAC */ + +#ifdef MT_MAC +#include "mt_io.h" +#include "mt_ps.h" +#endif + +#ifdef CONFIG_SNIFFER_SUPPORT +#include "sniffer/sniffer.h" +#endif /* CONFIG_SNIFFER_SUPPORT */ + +#ifdef ACL_V2_SUPPORT +#include "ap_acl_v2.h" +#endif /* ACL_V2_SUPPORT */ + +#ifdef SNIFFER_MIB_CMD +#include "sniffer_mib.h" +#endif /* SNIFFER_MIB_CMD */ + +#ifdef ALL_NET_EVENT +#include "all_net_event.h" +#endif /* ALL_NET_EVENT */ + +#ifdef LINUX +#endif /* LINUX */ + +#ifdef DOT11U_INTERWORKING +#include "dot11u_interworking.h" +#include "gas.h" +#endif + +#ifdef CONFIG_DOT11V_WNM +#include "dot11v_wnm.h" +#include "wnm.h" +#endif + +#ifdef CONFIG_HOTSPOT +#include "hotspot.h" +#endif + +#ifdef CONFIG_PUSH_SUPPORT +#include "event_notifier.h" +#endif +#ifdef WH_EZ_SETUP +//#include "easy_setup/ez_hooks.h" +#include "easy_setup/mt7603_driver_specific_func.h" +#include "easy_setup/ez_hooks_proto.h" +#include "easy_setup/mt7603_chip_ops_api.h" +//#include "easy_setup/mt7603_chip_ops.h" +#endif /* WH_EZ_SETUP */ +#ifdef DOT11_SAE_SUPPORT +#include "sae_cmm.h" +#include "sae.h" +#endif /* DOT11_SAE_SUPPORT */ + +#ifdef CONFIG_OWE_SUPPORT +#include "owe_cmm.h" +#endif /* DOT11_OWE_SUPPORT */ + +#ifdef MBO_SUPPORT +#include "mbo.h" +#endif/* MBO_SUPPORT */ + + +#ifdef WAPP_SUPPORT +#include "wnm.h" +#include "wapp/wapp_cmm_type.h" +#include "wapp/wapp.h" +#endif/* WAPP_SUPPORT */ + +#ifdef A4_CONN +#include "a4_conn.h" +#endif + +#ifdef DOT11_SAE_SUPPORT +extern UCHAR OUI_WPA2_AKM_SAE_SHA256[4]; +extern UCHAR OUI_WPA2_PSK_SHA256[4]; +extern UCHAR OUI_WPA2_PSK_AKM[4]; +#endif + +#ifdef CONFIG_OWE_SUPPORT +extern UCHAR OUI_WPA2_AKM_OWE[4]; +#endif + +#endif /* __RT_CONFIG_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_led.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_led.h new file mode 100644 index 000000000..d159d126d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_led.h @@ -0,0 +1,185 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002-2010, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + rt_led.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RT_LED_H__ +#define __RT_LED_H__ + +/* LED MCU command */ +#define MCU_SET_LED_MODE 0x50 +#define MCU_SET_LED_GPIO_SIGNAL_CFG 0x51 +#define MCU_SET_LED_AG_CFG 0x52 +#define MCU_SET_LED_ACT_CFG 0x53 +#define MCU_SET_LED_POLARITY 0x54 +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT +#define MCU_SET_WPS_LED_MODE 0x55 /* Set WPS LED mode (based on WPS specification V1.0). */ +#define MCU_SET_ANT_DIVERSITY 0x73 +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ + +/* LED Mode */ +#define LED_MODE(pAd) ((pAd)->LedCntl.MCULedCntl.field.LedMode & 0x7F) +#define LED_HW_CONTROL 19 /* set LED to controll by MAC registers instead of by firmware */ +#define LED_MODE_DEFAULT 0 /* value domain of pAd->LedCntl.LedMode and E2PROM */ +#define LED_MODE_TWO_LED 1 +#define LED_MODE_8SEC_SCAN 2 /* Same as LED mode 1; except that fast blink for 8sec when doing scanning. */ +#define LED_MODE_SITE_SURVEY_SLOW_BLINK 3 /* Same as LED mode 1; except that make ACT slow blinking during site survey period and blink once at power-up. */ +#define LED_MODE_WPS_LOW_POLARITY 4 /* Same as LED mode 1; except that make ACT steady on during WPS period */ +#define LED_MODE_WPS_HIGH_POLARITY 5 /* Same as LED mode 1; except that make ACT steady on during WPS period */ +/*#define LED_MODE_SIGNAL_STREGTH 8 // EEPROM define =8 */ +#define LED_MODE_SIGNAL_STREGTH 0x40 /* EEPROM define = 64 */ +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT +#define LED_WPS_MODE10_TURN_ON 16 /* For Dlink WPS LED, turn the WPS LED on */ +#define LED_WPS_MODE10_FLASH 17 /* For Dlink WPS LED, let the WPS LED flash */ +#define LED_WPS_MODE10_TURN_OFF 18 /* For Dlink WPS LED, turn the WPS LED off */ +#define WPS_LED_MODE_7 0x07 +#define WPS_LED_MODE_8 0x08 +#define WPS_LED_MODE_9 0x09 +#define WPS_LED_MODE_10 0x0a +/* */ +/* Chungwa Telecom (WPS LED and SD/HD LEDs) use WPS LED mode #11 and it is based on mode #7 */ +/* */ +/* GPIO #1: WPS LED */ +/* GPIO #2: SD (Standard Definition) LED */ +/* GPIO #4: HD (High Definition) LED */ +/* */ +#define WPS_LED_MODE_11 0x0b +#define WPS_LED_MODE_12 0x0c +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ + +/* Driver LED Status */ +#define LED_LINK_DOWN 0 +#define LED_LINK_UP 1 +#define LED_RADIO_OFF 2 +#define LED_RADIO_ON 3 +#define LED_HALT 4 +#define LED_WPS 5 +#define LED_ON_SITE_SURVEY 6 +#define LED_POWER_UP 7 +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT +/* For LED mode = 7 only */ +#define LED_WPS_IN_PROCESS 8 /* The protocol is searching for a partner, connecting, or exchanging network parameters. */ +#define LED_WPS_ERROR 9 /* Some error occurred which was not related to security, such as failed to find any partner or protocol prematurely aborted. */ +#define LED_WPS_SESSION_OVERLAP_DETECTED 10 /* The Protocol detected overlapping operation (more than one Registrar in PBC mode): could be a security risk. */ +#define LED_WPS_SUCCESS 11 /* The protocol is finished: no uncorrectable errors occured. Normally after guard time period. */ +#define LED_WPS_TURN_LED_OFF 12 /* Turn the WPS LEDs off. */ +#define LED_WPS_TURN_ON_BLUE_LED 13 /* Turn on the WPS blue LED. */ +#define LED_NORMAL_CONNECTION_WITHOUT_SECURITY 14 /* Successful connection with an AP using OPEN-NONE. */ +#define LED_NORMAL_CONNECTION_WITH_SECURITY 15 /* Successful connection with an AP using an encryption algorithm. */ +/* For LED Share Mode */ +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ + +/* MCU Led Link Status */ +#define LINK_STATUS_LINK_DOWN 0x20 +#define LINK_STATUS_ABAND_LINK_UP 0xa0 +#define LINK_STATUS_GBAND_LINK_UP 0x60 +#define LINK_STATUS_RADIO_ON 0x20 +#define LINK_STATUS_RADIO_OFF 0x00 +#define LINK_STATUS_WPS 0x10 +#define LINK_STATUS_ON_SITE_SURVEY 0x08 +#define LINK_STATUS_POWER_UP 0x04 +#define LINK_STATUS_HW_CONTROL 0x00 +#ifdef WSC_INCLUDED +#ifdef WSC_LED_SUPPORT +/* LED mode = 7 and 8 only */ +#define LINK_STATUS_WPS_IN_PROCESS 0x00 /* The protocol is searching for a partner, connecting, or exchanging network parameters. */ +#define LINK_STATUS_WPS_SUCCESS_WITH_SECURITY 0x01 /* The protocol is finished (with security): no uncorrectable errors occured. Normally after guard time period. */ +#define LINK_STATUS_WPS_ERROR 0x02 /* Some error occurred which was not related to security, such as failed to find any partner or protocol prematurely aborted. */ +#define LINK_STATUS_WPS_SESSION_OVERLAP_DETECTED 0x03 /* The Protocol detected overlapping operation (more than one Registrar in PBC mode): could be a security risk. */ +#define LINK_STATUS_WPS_TURN_LED_OFF 0x04 /* Turn the WPS LEDs off. */ +#define LINK_STATUS_WPS_SUCCESS_WITHOUT_SECURITY 0X05 /* The protocol is finished (without security): no uncorrectable errors occured. Normally after guard time period. */ +#define LINK_STATUS_NORMAL_CONNECTION_WITHOUT_SECURITY 0x06 /* Successful connection with an AP using OPEN-NONE. */ +#define LINK_STATUS_NORMAL_CONNECTION_WITH_SECURITY 0x0E /* Successful connection with an AP using an encryption algorithm. */ +#define LINK_STATUS_WPS_BLUE_LED 0x01 /* WPS blue LED. */ +/* LED moe = 10 */ +#define LINK_STATUS_WPS_MODE10_TURN_ON 0x00 /*Use only on Dlink WPS LED (mode 10), turn the WPS LED on. */ +#define LINK_STATUS_WPS_MODE10_FLASH 0x01 /*Use only on Dlink WPS LED (mode 10), let the WPS LED flash, three times persecond. */ +#define LINK_STATUS_WPS_MODE10_TURN_OFF 0x02 /*Use only on Dlink WPS LED (mode 10), turn the WPS LED off. */ +#endif /* WSC_LED_SUPPORT */ +#endif /* WSC_INCLUDED */ + + +#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 rtmp_read_led_setting_from_eeprom(IN RTMP_ADAPTER *pAd); +void RTMPInitLEDMode(IN RTMP_ADAPTER *pAd); +void RTMPExitLEDMode(IN RTMP_ADAPTER *pAd); + +VOID RTMPSetLEDStatus(RTMP_ADAPTER *pAd, UCHAR Status); +VOID RTMPSetSignalLED(RTMP_ADAPTER *pAd, NDIS_802_11_RSSI Dbm); + +INT RTMPSetLED(RTMP_ADAPTER *pAd, UCHAR Status); + +#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 */ + + +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; + UCHAR LedConfigMethod; + UCHAR LedconnectFailCountdown; +}LED_CONTROL, *PLED_CONTROL; + +void RTMPStartLEDMode(IN RTMP_ADAPTER *pAd); + +#endif /* __RT_LED_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_os_net.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_os_net.h new file mode 100644 index 000000000..22cab0771 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_os_net.h @@ -0,0 +1,467 @@ +/**************************************************************************** + + Module Name: + rt_os_net.h + + Abstract: + All function prototypes are defined in NETIF modules. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + +***************************************************************************/ + +#ifndef __RT_OS_NET_H__ +#define __RT_OS_NET_H__ + +#include "chip/chip_id.h" + +typedef VOID *(*RTMP_NET_ETH_CONVERT_DEV_SEARCH)(VOID *net_dev, UCHAR *pData); +typedef int (*RTMP_NET_PACKET_TRANSMIT)(VOID *pPacket); + +#ifdef LINUX +#ifdef OS_ABL_FUNC_SUPPORT + +/* ========================================================================== */ +/* operators used in NETIF module */ +/* Note: No need to put any compile option here */ +typedef struct _RTMP_DRV_ABL_OPS { + +NDIS_STATUS (*RTMPAllocAdapterBlock)(PVOID handle, VOID **ppAdapter); +VOID (*RTMPFreeAdapter)(VOID *pAd); +BOOLEAN (*RtmpRaDevCtrlExit)(VOID *pAd); +INT (*RtmpRaDevCtrlInit)(VOID *pAd, RTMP_INF_TYPE infType); +VOID (*RTMPHandleInterrupt)(VOID *pAd); +INT (*RTMP_COM_IoctlHandle)( + IN VOID *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data); + +int (*RTMPSendPackets)( + IN NDIS_HANDLE MiniportAdapterContext, + IN PPNDIS_PACKET ppPacketArray, + IN UINT NumberOfPackets, + IN UINT32 PktTotalLen, + IN RTMP_NET_ETH_CONVERT_DEV_SEARCH Func); + +int (*P2P_PacketSend)( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev, + IN RTMP_NET_PACKET_TRANSMIT Func); + +INT (*RTMP_AP_IoctlHandle)( + IN VOID *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data); + +INT (*RTMP_STA_IoctlHandle)( + IN VOID *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data, + IN USHORT priv_flags); + +VOID (*RTMPDrvOpen)(VOID *pAd); +VOID (*RTMPDrvClose)(VOID *pAd, VOID *net_dev); +VOID (*RTMPInfClose)(VOID *pAd); +int (*rt28xx_init)(VOID *pAd, RTMP_STRING *pDefaultMac, RTMP_STRING *pHostName); +} RTMP_DRV_ABL_OPS; + +extern RTMP_DRV_ABL_OPS *pRtmpDrvOps; + +VOID RtmpDrvOpsInit( + OUT VOID *pDrvOpsOrg, + INOUT VOID *pDrvNetOpsOrg, + IN RTMP_PCI_CONFIG *pPciConfig, + IN RTMP_USB_CONFIG *pUsbConfig); +#endif /* OS_ABL_FUNC_SUPPORT */ +#endif /* LINUX */ + + + + +/* ========================================================================== */ +/* operators used in DRIVER module */ +typedef void (*RTMP_DRV_USB_COMPLETE_HANDLER)(VOID *pURB); + +typedef struct _RTMP_NET_ABL_OPS { + + +} RTMP_NET_ABL_OPS; + +extern RTMP_NET_ABL_OPS *pRtmpDrvNetOps; + +VOID RtmpNetOpsInit(VOID *pNetOpsOrg); +VOID RtmpNetOpsSet(VOID *pNetOpsOrg); + + +/* ========================================================================== */ +#if defined(RTMP_MODULE_OS) && defined(OS_ABL_FUNC_SUPPORT) +/* for UTIL/NETIF module in OS ABL mode */ + +#define RTMPAllocAdapterBlock (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMPAllocAdapterBlock) +#define RTMPFreeAdapter (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMPFreeAdapter) +#define RtmpRaDevCtrlExit (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RtmpRaDevCtrlExit) +#define RtmpRaDevCtrlInit (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RtmpRaDevCtrlInit) +#define RTMPHandleInterrupt (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMPHandleInterrupt) +#define RTMP_COM_IoctlHandle (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMP_COM_IoctlHandle) +#define RTMPSendPackets (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMPSendPackets) +#define P2P_PacketSend (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->P2P_PacketSend) +#define RTMP_AP_IoctlHandle (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMP_AP_IoctlHandle) +#define RTMP_STA_IoctlHandle (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMP_STA_IoctlHandle) +#define RTMPDrvOpen (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMPDrvOpen) +#define RTMPDrvClose (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMPDrvClose) +#define RTMPInfClose (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->RTMPInfClose) +#define rt28xx_init (((RTMP_DRV_ABL_OPS *)(pRtmpDrvOps))->rt28xx_init) + +#else /* RTMP_MODULE_OS && OS_ABL_FUNC_SUPPORT */ + +NDIS_STATUS RTMPAllocAdapterBlock(PVOID handle, VOID **ppAdapter); +VOID RTMPFreeAdapter(VOID *pAd); +BOOLEAN RtmpRaDevCtrlExit(VOID *pAd); +INT RtmpRaDevCtrlInit(VOID *pAd, RTMP_INF_TYPE infType); +VOID RTMPHandleInterrupt(VOID *pAd); + +INT RTMP_COM_IoctlHandle( + IN VOID *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data); + +int RTMPSendPackets( + IN NDIS_HANDLE MiniportAdapterContext, + IN PPNDIS_PACKET ppPacketArray, + IN UINT NumberOfPackets, + IN UINT32 PktTotalLen, + IN RTMP_NET_ETH_CONVERT_DEV_SEARCH Func); + +int P2P_PacketSend( + IN PNDIS_PACKET pPktSrc, + IN PNET_DEV pDev, + IN RTMP_NET_PACKET_TRANSMIT Func); + +#ifdef CONFIG_AP_SUPPORT +INT RTMP_AP_IoctlHandle( + IN VOID *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data); +#endif /* CONFIG_AP_SUPPORT */ + + +VOID RTMPDrvOpen(VOID *pAd); +VOID RTMPDrvClose(VOID *pAd, VOID *net_dev); +VOID RTMPInfClose(VOID *pAd); + +int rt28xx_init(VOID *pAd, RTMP_STRING *pDefaultMac, RTMP_STRING *pHostName); + +PNET_DEV RtmpPhyNetDevMainCreate(VOID *pAd); +#endif /* RTMP_MODULE_OS */ + +/* ========================================================================== */ +int rt28xx_close(VOID *dev); +int rt28xx_open(VOID *dev); + +__inline INT VIRTUAL_IF_UP(VOID *pAd) +{ + RT_CMD_INF_UP_DOWN InfConf = { rt28xx_open, rt28xx_close }; + if (RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_VIRTUAL_INF_UP, + 0, &InfConf, 0) != NDIS_STATUS_SUCCESS) + return -1; + return 0; +} + +__inline VOID VIRTUAL_IF_DOWN(VOID *pAd) +{ + RT_CMD_INF_UP_DOWN InfConf = { rt28xx_open, rt28xx_close }; + RTMP_COM_IoctlHandle(pAd, NULL, CMD_RTPRIV_IOCTL_VIRTUAL_INF_DOWN, + 0, &InfConf, 0); + return; +} + +#ifdef RTMP_MODULE_OS + +#ifdef CONFIG_AP_SUPPORT +INT rt28xx_ap_ioctl( + IN PNET_DEV net_dev, + IN OUT struct ifreq *rq, + IN INT cmd); +#endif /* CONFIG_AP_SUPPORT */ + + +PNET_DEV RtmpPhyNetDevInit( + IN VOID *pAd, + IN RTMP_OS_NETDEV_OP_HOOK *pNetHook); + +BOOLEAN RtmpPhyNetDevExit( + IN VOID *pAd, + IN PNET_DEV net_dev); + +#endif /* RTMP_MODULE_OS && OS_ABL_FUNC_SUPPORT */ + + +VOID RT28xx_MBSS_Init(VOID *pAd, PNET_DEV main_dev_p); +INT MBSS_VirtualIF_Open(PNET_DEV dev_p); +INT MBSS_VirtualIF_Close(PNET_DEV dev_p); +VOID RT28xx_MBSS_Remove(VOID *pAd); + + +VOID RT28xx_WDS_Init(VOID *pAd, PNET_DEV net_dev); +INT WdsVirtualIF_open(PNET_DEV dev); +INT WdsVirtualIF_close(PNET_DEV dev); +VOID RT28xx_WDS_Remove(VOID *pAd); + +VOID RT28xx_Monitor_Init(VOID *pAd, PNET_DEV main_dev_p); +VOID RT28xx_Monitor_Remove(VOID *pAd); + +VOID RT28xx_ApCli_Init(VOID *pAd, PNET_DEV main_dev_p); +INT ApCli_VirtualIF_Open(PNET_DEV dev_p); +INT ApCli_VirtualIF_Close(PNET_DEV dev_p); +VOID RT28xx_ApCli_Remove(VOID *pAd); + + +VOID RTMP_Mesh_Init(VOID *pAd, PNET_DEV main_dev_p, RTMP_STRING *pHostName); +INT Mesh_VirtualIF_Open(PNET_DEV pDev); +INT Mesh_VirtualIF_Close(PNET_DEV pDev); +VOID RTMP_Mesh_Remove(VOID *pAd); + +VOID RTMP_P2P_Init(VOID *pAd, PNET_DEV main_dev_p); + INT P2P_VirtualIF_Open(PNET_DEV dev_p); + INT P2P_VirtualIF_Close(PNET_DEV dev_p); + INT P2P_VirtualIF_PacketSend( + IN PNDIS_PACKET skb_p, + IN PNET_DEV dev_p); + VOID RTMP_P2P_Remove(VOID *pAd); + + +PNET_DEV RTMP_CFG80211_FindVifEntry_ByType( + IN VOID *pAdSrc, + IN UINT32 devType); + +PWIRELESS_DEV RTMP_CFG80211_FindVifEntryWdev_ByType( + VOID *pAdSrc, UINT32 devType); + +VOID RTMP_CFG80211_AddVifEntry( + IN VOID *pAdSrc, + IN PNET_DEV pNewNetDev, + IN UINT32 DevType); + +VOID RTMP_CFG80211_RemoveVifEntry( + IN VOID *pAdSrc, + IN PNET_DEV pNewNetDev); + +PNET_DEV RTMP_CFG80211_VirtualIF_Get( + IN VOID *pAdSrc); + +VOID RTMP_CFG80211_VirtualIF_Init( + IN VOID *pAd, + IN CHAR *pIfName, + IN UINT32 DevType); + +VOID RTMP_CFG80211_VirtualIF_Remove( + IN VOID *pAd, + IN PNET_DEV dev_p, + IN UINT32 DevType); + +VOID RTMP_CFG80211_AllVirtualIF_Remove( + IN VOID *pAdSrc); + + +#ifdef RT_CFG80211_ANDROID_PRIV_LIB_SUPPORT +INT rt_android_private_command_entry( + VOID *pAdSrc, struct net_device *net_dev, struct ifreq *ifr, int cmd); +#endif /* RT_CFG80211_ANDROID_PRIV_LIB_SUPPORT */ + + +/* FOR communication with RALINK DRIVER module in NET module */ +/* general */ +#define RTMP_DRIVER_NET_DEV_GET(__pAd, __pNetDev) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_NETDEV_GET, 0, __pNetDev, 0) + +#define RTMP_DRIVER_NET_DEV_SET(__pAd, __pNetDev) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_NETDEV_SET, 0, __pNetDev, 0) + +#define RTMP_DRIVER_OP_MODE_GET(__pAd, __pOpMode) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_OPMODE_GET, 0, __pOpMode, 0) + +#define RTMP_DRIVER_IW_STATS_GET(__pAd, __pIwStats) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_INF_IW_STATUS_GET, 0, __pIwStats, 0) + +#define RTMP_DRIVER_INF_STATS_GET(__pAd, __pInfStats) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_INF_STATS_GET, 0, __pInfStats, 0) + +#define RTMP_DRIVER_INF_TYPE_GET(__pAd, __pInfType) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_INF_TYPE_GET, 0, __pInfType, 0) + +#define RTMP_DRIVER_TASK_LIST_GET(__pAd, __pList) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_TASK_LIST_GET, 0, __pList, 0) + +#define RTMP_DRIVER_NIC_NOT_EXIST_SET(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_NIC_NOT_EXIST, 0, NULL, 0) + +#define RTMP_DRIVER_MCU_SLEEP_CLEAR(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_MCU_SLEEP_CLEAR, 0, NULL, 0) + + +#define RTMP_DRIVER_ADAPTER_RT28XX_USB_ASICRADIO_OFF(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_USB_ASICRADIO_OFF, 0, NULL, 0) + +#define RTMP_DRIVER_ADAPTER_RT28XX_USB_ASICRADIO_ON(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_RT28XX_USB_ASICRADIO_ON, 0, NULL, 0) + +#define RTMP_DRIVER_ADAPTER_SUSPEND_SET(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_SUSPEND_SET, 0, NULL, 0) + +#define RTMP_DRIVER_ADAPTER_SUSPEND_CLEAR(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_SUSPEND_CLEAR, 0, NULL, 0) + +#define RTMP_DRIVER_VIRTUAL_INF_NUM_GET(__pAd, __pIfNum) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_VIRTUAL_INF_GET, 0, __pIfNum, 0) + +#define RTMP_DRIVER_CHANNEL_GET(__pAd, __Channel) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_SIOCGIWFREQ, 0, __Channel, 0) + +#define RTMP_DRIVER_IOCTL_SANITY_CHECK(__pAd, __SetCmd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_SANITY_CHECK, 0, __SetCmd, 0) + +#define RTMP_DRIVER_BITRATE_GET(__pAd, __pBitRate) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_AP_SIOCGIWRATEQ, 0, __pBitRate, 0) + +#define RTMP_DRIVER_MAIN_INF_CREATE(__pAd, __ppNetDev) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_INF_MAIN_CREATE, 0, __ppNetDev, 0) + +#define RTMP_DRIVER_MAIN_INF_GET(__pAd, __pInfId) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_INF_MAIN_ID_GET, 0, __pInfId, 0) + +#define RTMP_DRIVER_MAIN_INF_CHECK(__pAd, __InfId) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_INF_MAIN_CHECK, 0, NULL, __InfId) + +#define RTMP_DRIVER_P2P_INF_CHECK(__pAd, __InfId) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_INF_P2P_CHECK, 0, NULL, __InfId) + +#ifdef EXT_BUILD_CHANNEL_LIST +#define RTMP_DRIVER_SET_PRECONFIG_VALUE(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_SET_PRECONFIG_VALUE, 0, NULL, 0) +#endif /* EXT_BUILD_CHANNEL_LIST */ + + + +/* mesh */ +#define RTMP_DRIVER_MESH_REMOVE(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_MESH_REMOVE, 0, NULL, 0) + +/* inf ppa */ +#define RTMP_DRIVER_INF_PPA_INIT(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_INF_PPA_INIT, 0, NULL, 0) + +#define RTMP_DRIVER_INF_PPA_EXIT(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_INF_PPA_EXIT, 0, NULL, 0) + +/* pci */ +#define RTMP_DRIVER_IRQ_INIT(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_IRQ_INIT, 0, NULL, 0) + +#define RTMP_DRIVER_IRQ_RELEASE(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_IRQ_RELEASE, 0, NULL, 0) + +#define RTMP_DRIVER_PCI_MSI_ENABLE(__pAd, __pPciDev) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_MSI_ENABLE, 0, __pPciDev, 0) + +#define RTMP_DRIVER_PCI_SUSPEND(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_PCI_SUSPEND, 0, NULL, 0) + +#define RTMP_DRIVER_PCI_RESUME(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_PCI_RESUME, 0, NULL, 0) + +#define RTMP_DRIVER_PCI_CSR_SET(__pAd, __Address) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_PCI_CSR_SET, 0, NULL, __Address) + +#define RTMP_DRIVER_PCIE_INIT(__pAd, __pPciDev) \ +{ \ + RT_CMD_PCIE_INIT __Config, *__pConfig = &__Config; \ + __pConfig->pPciDev = __pPciDev; \ + __pConfig->ConfigDeviceID = PCI_DEVICE_ID; \ + __pConfig->ConfigSubsystemVendorID = PCI_SUBSYSTEM_VENDOR_ID; \ + __pConfig->ConfigSubsystemID = PCI_SUBSYSTEM_ID; \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_PCIE_INIT, 0, __pConfig, 0);\ +} + +/* usb */ +#define RTMP_DRIVER_USB_MORE_FLAG_SET(__pAd, __pConfig) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_USB_MORE_FLAG_SET, 0, __pConfig, 0) + +#define RTMP_DRIVER_USB_CONFIG_INIT(__pAd, __pConfig) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_USB_CONFIG_INIT, 0, __pConfig, 0) + +#define RTMP_DRIVER_USB_SUSPEND(__pAd, __bIsRunning) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_USB_SUSPEND, 0, NULL, __bIsRunning) + +#define RTMP_DRIVER_USB_RESUME(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_USB_RESUME, 0, NULL, 0) + +#define RTMP_DRIVER_USB_INIT(__pAd, __pUsbDev, __driver_info) \ +do { \ + RT_CMD_USB_INIT __Config, *__pConfig = &__Config; \ + __pConfig->pUsbDev = __pUsbDev; \ + __pConfig->driver_info = __driver_info; \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_USB_INIT, 0, __pConfig, 0); \ +} while (0) + +#define RTMP_DRIVER_SDIO_INIT(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_SDIO_INIT, 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_CSO_SUPPORT_TEST(__pAd, __flag) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_CSO_SUPPORT_TEST, 0, __flag, 0) + +#define RTMP_DRIVER_ADAPTER_TSO_SUPPORT_TEST(__pAd, __flag) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_ADAPTER_TSO_SUPPORT_TEST, 0, __flag, 0) + +#ifdef CONFIG_HAS_EARLYSUSPEND +#define RTMP_DRIVER_SET_SUSPEND_FLAG(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_SET_SUSPEND_FLAG, 0, NULL, 0) + +#define RTMP_DRIVER_LOAD_FIRMWARE_CHECK(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_LOAD_FIRMWARE_CHECK, 0, NULL, 0) + +#define RTMP_DRIVER_OS_COOKIE_GET(__pAd, __os_cookie) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_OS_COOKIE_GET, 0, __os_cookie, 0) + +#define RTMP_DRIVER_ADAPTER_REGISTER_EARLYSUSPEND(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_REGISTER_EARLYSUSPEND, 0, NULL, 0) + +#define RTMP_DRIVER_ADAPTER_UNREGISTER_EARLYSUSPEND(__pAd) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_UNREGISTER_EARLYSUSPEND, 0, NULL, 0) + +#define RTMP_DRIVER_ADAPTER_CHECK_EARLYSUSPEND(__pAd, __flag) \ + RTMP_COM_IoctlHandle(__pAd, NULL, CMD_RTPRIV_IOCTL_CHECK_EARLYSUSPEND, 0, __flag, 0) +#endif /* CONFIG_HAS_EARLYSUSPEND */ + +#endif /* __RT_OS_NET_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_os_util.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_os_util.h new file mode 100644 index 000000000..e2d8747d8 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_os_util.h @@ -0,0 +1,695 @@ +/**************************************************************************** + + 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 + --------- ---------- ---------------------------------------------- + +***************************************************************************/ +#include "rt_config.h" +#ifndef __RT_OS_UTIL_H__ +#define __RT_OS_UTIL_H__ + +/* ============================ rt_linux.c ================================== */ +/* General */ +VOID RtmpUtilInit(VOID); + +/* OS Time */ +VOID RtmpusecDelay(ULONG usec); +VOID RtmpOsMsDelay(ULONG msec); + +void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time); + +ULONG RTMPMsecsToJiffies(UINT msec); +void RTMP_GetCurrentSystemTick(ULONG *pNow); + +VOID RtmpOsWait(UINT32 Time); +UINT32 RtmpOsTimerAfter(ULONG a, ULONG b); +UINT32 RtmpOsTimerBefore(ULONG a, ULONG b); +VOID RtmpOsGetSystemUpTime(ULONG *pTime); +UINT32 RtmpOsTickUnitGet(VOID); + + +/* + OS Memory +*/ +/* + Function: + allocate memory + Parameters: + + Return: + + mem shall be set as NULL if allocation failed +*/ +NDIS_STATUS os_alloc_mem(VOID *pReserved, UCHAR **mem, ULONG size); +NDIS_STATUS os_alloc_mem_suspend(VOID *pReserved, UCHAR **mem, ULONG size); +NDIS_STATUS os_move_mem(PVOID pDest, PVOID pSrc, ULONG length); +NDIS_STATUS os_free_mem(VOID *pReserved, VOID *mem); + +NDIS_STATUS os_zero_mem(PVOID ptr, ULONG length); + +NDIS_STATUS AdapterBlockAllocateMemory( + IN VOID *handle, + OUT VOID **ppAd, + IN UINT32 SizeOfpAd); + +VOID *RtmpOsVmalloc(ULONG Size); +VOID RtmpOsVfree(VOID *pMem); + +ULONG RtmpOsCopyFromUser(VOID *to, const void *from, ULONG n); +ULONG RtmpOsCopyToUser(VOID *to, const void *from, ULONG n); + +BOOLEAN RtmpOsStatsAlloc(VOID **ppStats, VOID **ppIwStats); + +/* OS Packet */ +PNDIS_PACKET RtmpOSNetPktAlloc(VOID *pReserved, int size); + +PNDIS_PACKET RTMP_AllocateFragPacketBuffer(VOID *pReserved, ULONG Length); + +NDIS_STATUS RTMPAllocateNdisPacket( + IN VOID *pReserved, + OUT PNDIS_PACKET *ppPacket, + IN PUCHAR pHeader, + IN UINT HeaderLen, + IN PUCHAR pData, + IN UINT DataLen); + +VOID RTMPFreeNdisPacket(VOID *pReserved, PNDIS_PACKET pPacket); + +void RTMP_QueryPacketInfo( + IN PNDIS_PACKET pPacket, + OUT PACKET_INFO *pPacketInfo, + OUT PUCHAR *pSrcBufVA, + OUT UINT *pSrcBufLen); + + +PNDIS_PACKET ClonePacket(PNET_DEV ndev, PNDIS_PACKET pkt, UCHAR *buf, ULONG sz); +PNDIS_PACKET CopyPacket(PNET_DEV ndev, PNDIS_PACKET pkt, ULONG sz); + +PNDIS_PACKET DuplicatePacket(PNET_DEV pNetDev, PNDIS_PACKET pPacket); + +PNDIS_PACKET duplicate_pkt_with_TKIP_MIC( + IN VOID *pReserved, + IN PNDIS_PACKET pOldPkt); + +PNDIS_PACKET duplicate_pkt_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 *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); + +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 *TPID); + +#ifdef CONFIG_SNIFFER_SUPPORT +void send_prism_monitor_packets( + PNET_DEV pNetDev, + PNDIS_PACKET pRxPacket, + VOID *dot11_hdr, + UCHAR *pData, + USHORT DataSize, + UCHAR L2PAD, + UCHAR PHYMODE, + UCHAR BW, + UCHAR ShortGI, + UCHAR MCS, + UCHAR AMPDU, + UCHAR STBC, + UCHAR RSSI1, + UCHAR BssMonitorFlag11n, + UCHAR *pDevName, + UCHAR Channel, + UCHAR CentralChannel, + UINT32 MaxRssi); + +void send_radiotap_monitor_packets( + PNET_DEV pNetDev, + PNDIS_PACKET pRxPacket, + VOID *dot11_hdr, + UCHAR *pData, + USHORT DataSize, + UCHAR L2PAD, + UCHAR PHYMODE, + UCHAR BW, + UCHAR ShortGI, + UCHAR MCS, + UCHAR LDPC, + UCHAR LDPC_EX_SYM, + UCHAR AMPDU, + UCHAR STBC, + UCHAR RSSI1, + UCHAR *pDevName, + UCHAR Channel, + UCHAR CentralChannel, + UCHAR sideband_index, + CHAR MaxRssi, + UINT32 timestamp); + +#endif /* CONFIG_SNIFFER_SUPPORT */ + +UCHAR VLAN_8023_Header_Copy( + IN USHORT VLAN_VID, + IN USHORT VLAN_Priority, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + OUT PUCHAR pData, + IN UCHAR *TPID); + +VOID RtmpOsPktBodyCopy( + IN PNET_DEV pNetDev, + IN PNDIS_PACKET pNetPkt, + IN ULONG ThisFrameLen, + IN PUCHAR pData); + +INT RtmpOsIsPktCloned(PNDIS_PACKET pNetPkt); +PNDIS_PACKET RtmpOsPktCopy(PNDIS_PACKET pNetPkt); +PNDIS_PACKET RtmpOsPktClone(PNDIS_PACKET pNetPkt); + +VOID RtmpOsPktDataPtrAssign(PNDIS_PACKET pNetPkt, UCHAR *pData); + +VOID RtmpOsPktLenAssign(PNDIS_PACKET pNetPkt, LONG Len); +VOID RtmpOsPktTailAdjust(PNDIS_PACKET pNetPkt, UINT removedTagLen); + +PUCHAR RtmpOsPktTailBufExtend(PNDIS_PACKET pNetPkt, UINT len); +PUCHAR RtmpOsPktHeadBufExtend(PNDIS_PACKET pNetPkt, UINT len); +VOID RtmpOsPktReserve(PNDIS_PACKET pNetPkt, UINT len); + +VOID RtmpOsPktProtocolAssign(PNDIS_PACKET pNetPkt); +VOID RtmpOsPktInfPpaSend(PNDIS_PACKET pNetPkt); +VOID RtmpOsPktRcvHandle(PNDIS_PACKET pNetPkt); +VOID RtmpOsPktNatMagicTag(PNDIS_PACKET pNetPkt); +VOID RtmpOsPktNatNone(PNDIS_PACKET pNetPkt); +VOID RtmpOsPktInit(PNDIS_PACKET pNetPkt, PNET_DEV pNetDev, UCHAR *buf, USHORT len); + +PNDIS_PACKET RtmpOsPktIappMakeUp(PNET_DEV pNetDev, UINT8 *pMac); + +BOOLEAN RtmpOsPktOffsetInit(VOID); + +UINT16 RtmpOsNtohs(UINT16 Value); +UINT16 RtmpOsHtons(UINT16 Value); +UINT32 RtmpOsNtohl(UINT32 Value); +UINT32 RtmpOsHtonl(UINT32 Value); + +/* OS File */ +RTMP_OS_FD RtmpOSFileOpen(char *pPath, int flag, int mode); +int RtmpOSFileClose(RTMP_OS_FD osfd); +void RtmpOSFileSeek(RTMP_OS_FD osfd, int offset); +int RtmpOSFileRead(RTMP_OS_FD osfd, char *pDataPtr, int readLen); +int RtmpOSFileWrite(RTMP_OS_FD osfd, char *pDataPtr, int writeLen); + +INT32 RtmpOsFileIsErr(VOID *pFile); + +void RtmpOSFSInfoChange(RTMP_OS_FS_INFO *pOSFSInfoOrg, BOOLEAN bSet); + +/* OS Network Interface */ +int RtmpOSNetDevAddrSet( + IN UCHAR OpMode, + IN PNET_DEV pNetDev, + IN PUCHAR pMacAddr, + IN PUCHAR dev_name); + +void RtmpOSNetDevClose(PNET_DEV pNetDev); +void RtmpOSNetDevFree(PNET_DEV pNetDev); +INT RtmpOSNetDevAlloc(PNET_DEV *new_dev_p, UINT32 privDataSize); +INT RtmpOSNetDevOpsAlloc(PVOID *pNetDevOps); + + + +PNET_DEV RtmpOSNetDevGetByName(PNET_DEV pNetDev, RTMP_STRING *pDevName); + +void RtmpOSNetDeviceRefPut(PNET_DEV pNetDev); + +INT RtmpOSNetDevDestory(VOID *pReserved, PNET_DEV pNetDev); +void RtmpOSNetDevDetach(PNET_DEV pNetDev); +int RtmpOSNetDevAttach( + IN UCHAR OpMode, + IN PNET_DEV pNetDev, + IN RTMP_OS_NETDEV_OP_HOOK *pDevOpHook); + +void RtmpOSNetDevProtect( + IN BOOLEAN lock_it); + +PNET_DEV RtmpOSNetDevCreate( + IN INT32 MC_RowID, + IN UINT32 *pIoctlIF, + IN INT devType, + IN INT devNum, + IN INT privMemSize, + IN RTMP_STRING *pNamePrefix); + +BOOLEAN RtmpOSNetDevIsUp(VOID *pDev); + +unsigned char *RtmpOsNetDevGetPhyAddr(VOID *pDev); + +VOID RtmpOsNetQueueStart(PNET_DEV pDev); +VOID RtmpOsNetQueueStop(PNET_DEV pDev); +VOID RtmpOsNetQueueWake(PNET_DEV pDev); + +VOID RtmpOsSetPktNetDev(VOID *pPkt, VOID *pDev); +PNET_DEV RtmpOsPktNetDevGet(VOID *pPkt); + +char *RtmpOsGetNetDevName(VOID *pDev); + +UINT32 RtmpOsGetNetIfIndex(IN VOID *pDev); + +VOID RtmpOsSetNetDevPriv(VOID *pDev, VOID *pPriv); +VOID *RtmpOsGetNetDevPriv(VOID *pDev); + +VOID RtmpOsSetNetDevWdev(VOID *net_dev, VOID *wdev); +VOID *RtmpOsGetNetDevWdev(VOID *pDev); + +USHORT RtmpDevPrivFlagsGet(VOID *pDev); +VOID RtmpDevPrivFlagsSet(VOID *pDev, USHORT PrivFlags); + +VOID RtmpOsSetNetDevType(VOID *pDev, USHORT Type); +VOID RtmpOsSetNetDevTypeMonitor(VOID *pDev); +UCHAR get_sniffer_mode(VOID *pDev); +VOID set_sniffer_mode(VOID *pDev, UCHAR mode); + +/* OS Semaphore */ +VOID RtmpOsCmdUp(RTMP_OS_TASK *pCmdQTask); +BOOLEAN RtmpOsSemaInitLocked(RTMP_OS_SEM *pSemOrg, LIST_HEADER *pSemList); +BOOLEAN RtmpOsSemaInit(RTMP_OS_SEM *pSemOrg, LIST_HEADER *pSemList); +BOOLEAN RtmpOsSemaDestory(RTMP_OS_SEM *pSemOrg); +INT RtmpOsSemaWaitInterruptible(RTMP_OS_SEM *pSemOrg); +VOID RtmpOsSemaWakeUp(RTMP_OS_SEM *pSemOrg); +VOID RtmpOsMlmeUp(RTMP_OS_TASK *pMlmeQTask); + +VOID RtmpOsInitCompletion(RTMP_OS_COMPLETION *pCompletion); +VOID RtmpOsExitCompletion(RTMP_OS_COMPLETION *pCompletion); +VOID RtmpOsComplete(RTMP_OS_COMPLETION *pCompletion); +ULONG RtmpOsWaitForCompletionTimeout(RTMP_OS_COMPLETION *pCompletion, ULONG Timeout); + +/* OS Task */ +BOOLEAN RtmpOsTaskletSche(RTMP_NET_TASK_STRUCT *pTasklet); + +BOOLEAN RtmpOsTaskletInit( + RTMP_NET_TASK_STRUCT *pTasklet, + VOID (*pFunc)(unsigned long data), + ULONG Data, + LIST_HEADER *pTaskletList); + +BOOLEAN RtmpOsTaskletKill(RTMP_NET_TASK_STRUCT *pTasklet); +VOID RtmpOsTaskletDataAssign(RTMP_NET_TASK_STRUCT *pTasklet, ULONG Data); + +VOID RtmpOsTaskWakeUp(RTMP_OS_TASK *pTaskOrg); +INT32 RtmpOsTaskIsKilled(RTMP_OS_TASK *pTaskOrg); + +BOOLEAN RtmpOsCheckTaskLegality(RTMP_OS_TASK *pTaskOrg); + +BOOLEAN RtmpOSTaskAlloc(RTMP_OS_TASK *pTask, LIST_HEADER *pTaskList); + +VOID RtmpOSTaskFree(RTMP_OS_TASK *pTask); + +NDIS_STATUS RtmpOSTaskKill(RTMP_OS_TASK *pTaskOrg); + +INT RtmpOSTaskNotifyToExit(RTMP_OS_TASK *pTaskOrg); + +VOID RtmpOSTaskCustomize(RTMP_OS_TASK *pTaskOrg); + +NDIS_STATUS RtmpOSTaskAttach( + IN RTMP_OS_TASK *pTaskOrg, + IN RTMP_OS_TASK_CALLBACK fn, + IN ULONG arg); + +NDIS_STATUS RtmpOSTaskInit( + IN RTMP_OS_TASK *pTaskOrg, + IN RTMP_STRING *pTaskName, + IN VOID *pPriv, + IN LIST_HEADER *pTaskList, + IN LIST_HEADER *pSemList); + +BOOLEAN RtmpOSTaskWait( + IN VOID *pReserved, + IN RTMP_OS_TASK *pTaskOrg, + IN INT32 *pStatus); + +VOID *RtmpOsTaskDataGet(RTMP_OS_TASK *pTaskOrg); + +INT32 RtmpThreadPidKill(RTMP_OS_PID PID); + +/* OS Cache */ +VOID RtmpOsDCacheFlush(ULONG AddrStart, ULONG Size); + +/* OS Timer */ +VOID RTMP_SetPeriodicTimer( + IN NDIS_MINIPORT_TIMER *pTimerOrg, + IN unsigned long timeout); + +VOID RTMP_OS_Init_Timer( + IN VOID *pReserved, + IN NDIS_MINIPORT_TIMER *pTimerOrg, + IN TIMER_FUNCTION function, + IN PVOID data, + IN LIST_HEADER *pTimerList); + +VOID RTMP_OS_Add_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, unsigned long timeout); +VOID RTMP_OS_Mod_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, unsigned long timeout); +VOID RTMP_OS_Del_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, BOOLEAN *pCancelled); +VOID RTMP_OS_Release_Timer(NDIS_MINIPORT_TIMER *pTimerOrg); + +BOOLEAN RTMP_OS_Alloc_Rsc(LIST_HEADER *pRscList, VOID *pRsc, UINT32 RscLen); +VOID RTMP_OS_Free_Rscs(LIST_HEADER *pRscList); + +/* OS Lock */ +BOOLEAN RtmpOsAllocateLock(NDIS_SPIN_LOCK *pLock, LIST_HEADER *pLockList); +VOID RtmpOsFreeSpinLock(NDIS_SPIN_LOCK *pLockOrg); +VOID RtmpOsSpinLockBh(NDIS_SPIN_LOCK *pLockOrg); +VOID RtmpOsSpinUnLockBh(NDIS_SPIN_LOCK *pLockOrg); +VOID RtmpOsIntLock(NDIS_SPIN_LOCK *pLockOrg, ULONG *pIrqFlags); +VOID RtmpOsIntUnLock(NDIS_SPIN_LOCK *pLockOrg, ULONG IrqFlags); + +/* OS PID */ +VOID RtmpOsGetPid(ULONG *pDst, ULONG PID); +VOID RtmpOsTaskPidInit(RTMP_OS_PID *pPid); + +/* OS I/O */ +VOID RTMP_PCI_Writel(ULONG Value, VOID *pAddr); +VOID RTMP_PCI_Writew(ULONG Value, VOID *pAddr); +VOID RTMP_PCI_Writeb(ULONG Value, VOID *pAddr); +ULONG RTMP_PCI_Readl(VOID *pAddr); +ULONG RTMP_PCI_Readw(VOID *pAddr); +ULONG RTMP_PCI_Readb(VOID *pAddr); + +int RtmpOsPciConfigReadWord( + IN VOID *pDev, + IN UINT32 Offset, + OUT UINT16 *pValue); + +int RtmpOsPciConfigWriteWord(VOID *pDev, UINT32 Offset, UINT16 Value); +int RtmpOsPciConfigReadDWord(VOID *pDev, UINT32 Offset, UINT32 *pValue); +int RtmpOsPciConfigWriteDWord(VOID *pDev, UINT32 Offset, UINT32 Value); + +int RtmpOsPciFindCapability(VOID *pDev, INT Cap); + +VOID *RTMPFindHostPCIDev(VOID *pPciDevSrc); + +int RtmpOsPciMsiEnable(VOID *pDev); +VOID RtmpOsPciMsiDisable(VOID *pDev); + +/* OS Wireless */ +ULONG RtmpOsMaxScanDataGet(VOID); + +/* OS Interrutp */ +INT32 RtmpOsIsInInterrupt(VOID); + +/* OS USB */ +VOID *RtmpOsUsbUrbDataGet(VOID *pUrb); +NTSTATUS RtmpOsUsbUrbStatusGet(VOID *pUrb); +ULONG RtmpOsUsbUrbLenGet(VOID *pUrb); + +/* OS Atomic */ +BOOLEAN RtmpOsAtomicInit(RTMP_OS_ATOMIC *pAtomic, LIST_HEADER *pAtomicList); +VOID RtmpOsAtomicDestroy(RTMP_OS_ATOMIC *pAtomic); +LONG RtmpOsAtomicRead(RTMP_OS_ATOMIC *pAtomic); +VOID RtmpOsAtomicDec(RTMP_OS_ATOMIC *pAtomic); +VOID RtmpOsAtomicInterlockedExchange(RTMP_OS_ATOMIC *pAtomicSrc, LONG Value); + +/* OS Utility */ +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); + +VOID RtmpDrvAllRFPrint( + IN VOID *pReserved, + IN UCHAR *pBuf, + IN UINT32 BufLen); + +int RtmpOSIRQRelease( + IN PNET_DEV pNetDev, + IN UINT32 infType, + IN PPCI_DEV pci_dev, + IN BOOLEAN *pHaveMsi); + +VOID RtmpOsWlanEventSet( + IN VOID *pReserved, + IN BOOLEAN *pCfgWEnt, + IN BOOLEAN FlgIsWEntSup); + +UINT16 RtmpOsGetUnaligned(UINT16 *pWord); + +UINT32 RtmpOsGetUnaligned32(UINT32 *pWord); + +ULONG RtmpOsGetUnalignedlong(ULONG *pWord); + +long RtmpOsSimpleStrtol( + IN const char *cp, + IN char **endp, + IN unsigned int base); + +VOID RtmpOsOpsInit(RTMP_OS_ABL_OPS *pOps); + +/* ============================ rt_os_util.c ================================ */ +VOID 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); + +RTMP_STRING *WscGetAuthTypeStr(USHORT authFlag); + +RTMP_STRING *WscGetEncryTypeStr(USHORT encryFlag); + +USHORT WscGetAuthTypeFromStr(RTMP_STRING *arg); + +USHORT WscGetEncrypTypeFromStr(RTMP_STRING *arg); + +VOID RtmpMeshDown( + IN VOID *pDrvCtrlBK, + IN BOOLEAN WaitFlag, + IN BOOLEAN (*RtmpMeshLinkCheck)(IN VOID *pAd)); + +USHORT RtmpOsNetPrivGet(PNET_DEV pDev); + +BOOLEAN RtmpOsCmdDisplayLenCheck( + IN UINT32 LenSrc, + IN UINT32 Offset); + +VOID WpaSendMicFailureToWpaSupplicant( + IN PNET_DEV pNetDev, + IN const PUCHAR src_addr, + IN BOOLEAN bUnicast, + IN INT key_id, + IN const PUCHAR tsc); + +int wext_notify_event_assoc( + IN PNET_DEV pNetDev, + IN UCHAR *ReqVarIEs, + IN UINT32 ReqVarIELen); + +VOID SendAssocIEsToWpaSupplicant( + IN PNET_DEV pNetDev, + IN UCHAR *ReqVarIEs, + IN UINT32 ReqVarIELen); + +/* ============================ rt_rbus_pci_util.c ========================== */ +void RtmpAllocDescBuf( + IN PPCI_DEV pPciDev, + IN UINT Index, + IN ULONG Length, + IN BOOLEAN Cached, + OUT VOID **VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +void RtmpFreeDescBuf( + IN PPCI_DEV pPciDev, + IN ULONG Length, + IN VOID *VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + +void RTMP_AllocateFirstTxBuffer( + IN PPCI_DEV pPciDev, + IN UINT Index, + IN ULONG Length, + IN BOOLEAN Cached, + OUT VOID **VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + +void RTMP_FreeFirstTxBuffer( + IN PPCI_DEV pPciDev, + IN ULONG Length, + IN BOOLEAN Cached, + IN PVOID VirtualAddress, + IN NDIS_PHYSICAL_ADDRESS PhysicalAddress); + +PNDIS_PACKET RTMP_AllocateRxPacketBuffer( + IN VOID *pReserved, + IN VOID *pPciDev, + IN ULONG Length, + IN BOOLEAN Cached, + OUT PVOID *VirtualAddress, + OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress); + + + + +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( + RTMP_ADAPTER *ad, + 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 */ + + + + +/* ================================ 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); + +void OS_SPIN_LOCK(NDIS_SPIN_LOCK *lock); +void OS_SPIN_UNLOCK(NDIS_SPIN_LOCK *lock); +void OS_SPIN_LOCK_IRQSAVE(NDIS_SPIN_LOCK *lock, unsigned long *flags); +void OS_SPIN_UNLOCK_IRQRESTORE(NDIS_SPIN_LOCK *lock, unsigned long *flags); +void OS_SPIN_LOCK_IRQ(NDIS_SPIN_LOCK *lock); +void OS_SPIN_UNLOCK_IRQ(NDIS_SPIN_LOCK *lock); +void RtmpOsSpinLockIrqSave(NDIS_SPIN_LOCK *lock, unsigned long *flags); +void RtmpOsSpinUnlockIrqRestore(NDIS_SPIN_LOCK *lock, unsigned long *flags); +void RtmpOsSpinLockIrq(NDIS_SPIN_LOCK *lock); +void RtmpOsSpinUnlockIrq(NDIS_SPIN_LOCK *lock); +int OS_TEST_BIT(int bit, unsigned long *flags); +void OS_SET_BIT(int bit, unsigned long *flags); +void OS_CLEAR_BIT(int bit, unsigned long *flags); +void OS_LOAD_CODE_FROM_BIN(unsigned char **image, char *bin_name, void *inf_dev, UINT32 *code_len); +VOID os_load_code_from_bin(void *pAd, unsigned char **image, char *bin_name, UINT32 *code_len); + +#endif /* __RT_OS_UTIL_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_txbf.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_txbf.h new file mode 100644 index 000000000..cd6695c7d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rt_txbf.h @@ -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: + 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_ + + +#endif // _RT_TXBF_H_ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp.h new file mode 100644 index 000000000..a6fbea494 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp.h @@ -0,0 +1,10795 @@ +/* + *************************************************************************** + * 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 + -------- ---------- ---------------------------------------------- + +*/ +#ifndef __RTMP_H__ +#define __RTMP_H__ + +#include "link_list.h" +#include "spectrum_def.h" + +#include "rtmp_dot11.h" +#include "wpa_cmm.h" + +#ifdef CONFIG_AP_SUPPORT +#include "ap_autoChSel_cmm.h" +#endif /* CONFIG_AP_SUPPORT */ + +#include "wsc.h" +#ifdef MAT_SUPPORT +#include "mat.h" +#endif /* MAT_SUPPORT */ + + +#ifdef WAPI_SUPPORT +#include "wapi_def.h" +#endif /* WAPI_SUPPORT */ + +#include "rtmp_chip.h" + +#ifdef DOT11R_FT_SUPPORT +#include "ft_cmm.h" +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT +#include "rrm_cmm.h" +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT +#include "pmf_cmm.h" +#endif /* DOT11W_PMF_SUPPORT */ + + +#ifdef CLIENT_WDS +#include "client_wds_cmm.h" +#endif /* CLIENT_WDS */ + +#ifdef DOT11V_WNM_SUPPORT +#include "wnm_cmm.h" +#endif /* DOT11V_WNM_SUPPORT */ + + + + +#include "drs_extr.h" + +struct _RTMP_RA_LEGACY_TB; + +typedef struct _RTMP_ADAPTER RTMP_ADAPTER; +typedef struct _RTMP_ADAPTER *PRTMP_ADAPTER; + +typedef struct _RTMP_CHIP_OP RTMP_CHIP_OP; +typedef struct _RTMP_CHIP_CAP RTMP_CHIP_CAP; + +#ifdef BB_SOC +#include "os/bb_soc.h" +#endif + +#include "mcu/mcu.h" + + +#ifdef CONFIG_ANDES_SUPPORT +#include "mcu/andes_core.h" +#endif + +#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 CONFIG_ATE +#include "ate.h" +#endif + +#ifdef DOT11U_INTERWORKING +#include "dot11u_interworking.h" +#include "gas.h" +#endif + +#ifdef CONFIG_DOT11V_WNM +#include "dot11v_wnm.h" +#include "wnm.h" +#endif + +#ifdef CONFIG_HOTSPOT +#include "hotspot.h" +#endif + +#ifdef CONFIG_SNIFFER_SUPPORT +#include "sniffer/sniffer.h" +#endif + +#ifdef MIXMODE_SUPPORT +#include "mix_mode.h" +#endif + +#ifdef ACL_V2_SUPPORT +#include "ap_acl_v2.h" +#endif /* ACL_V2_SUPPORT */ + +#ifdef SNIFFER_MIB_CMD +#include "sniffer_mib.h" +#endif /* SNIFFER_MIB_CMD */ + +#ifdef ALL_NET_EVENT +#include "all_net_event.h" +#endif /* ALL_NET_EVENT */ + + +#ifdef MT_MAC +#include "cmm_asic_mt.h" +#endif /* MT_MAC */ + +#ifdef WH_EVENT_NOTIFIER +#include "event_notifier.h" +#endif /* WH_EVENT_NOTIFIER */ + +#ifdef DOT11_SAE_SUPPORT +#include "sae_cmm.h" +#include "crypt_biginteger.h" +#endif /* DOT11_SAE_SUPPORT */ + +#ifdef CONFIG_OWE_SUPPORT +#include "owe_cmm.h" +#endif /* DOT11_OWE_SUPPORT */ + + + +// TODO: shiang-6590, remove it after ATE fully re-organized! copy from rtmp_bbp.h +#ifndef MAX_BBP_ID + #define MAX_BBP_ID 136 + + + +#endif +// TODO: ---End +#ifdef CONFIG_OWE_SUPPORT +/*for OWE Transition Mode*/ +typedef struct vie_struct { + ULONG vie_length;/*the total length which starts from oui until the tail.*/ + UCHAR oui_oitype[4];/*used to comparism*/ + UCHAR *ie_ctnt; + struct vie_struct *next_vie; +} VIE_STRUCT; + +typedef enum vendor_ie_in_frame_type { + VIE_BEACON = 0, /*make sure it starts from 0, for initialization.*/ + VIE_PROBE_REQ, + VIE_PROBE_RESP, + VIE_ASSOC_REQ, + VIE_ASSOC_RESP, + /*due to there is less opportunity to add vendor ie in Auth. arranage them in the bottom seq.*/ + VIE_AUTH_REQ, + VIE_AUTH_RESP, + VIE_FRM_TYPE_MAX, +} VIE_FRM_TYPE; + +typedef struct vie_ctrl_struct { + VIE_FRM_TYPE type; + UCHAR vie_num; + struct vie_struct *vie_in_frm; +} VIE_CTRL; +#endif + + +#ifdef ANDLINK_FEATURE_SUPPORT +#include +#define OID_ANDLINK_EVENT 0x2766 /* 10086 */ +#define OID_ANDLINK_POLL 0x2767 +#define OID_ANDLINK_STAINFO 0x2768 +#define OID_ANDLINK_UPLINK 0x2769 + + +#define MAX_INF_LEN 10 /* maximum length of interface name */ +#define MAX_ASSOC_NUM 32 /* the max number of STAs that AP allowed to connect */ + + +#define ANDLINK_GET_CURRENT_SEC(ptime) \ +{ \ + struct timeval tv; \ + do_gettimeofday(&tv); \ + *ptime = tv.tv_sec; \ +} + +/* Driver Event Report */ +struct wifi_event_inf_poll { + u8 channel; +}; + +struct wifi_event_inf_stats { + UINT64 BytesSent; + UINT64 BytesReceived; + UINT64 PacketsSent; + UINT64 PacketsReceived; + UINT64 ErrorSent; + UINT64 ErrorReceived; + UINT64 DropPacketsSent; + UINT64 DropPacketsReceived; +}; + +struct wifi_ioctl_up_link { + UCHAR MAC[MAC_ADDR_LEN]; + UINT8 Radio; + UINT8 SSID[MAX_LEN_OF_SSID]; + UINT8 Channel; + CHAR Noise; + CHAR SNR; + CHAR RSSI; + UINT16 TxRate;/* Mbps */ + UINT16 RxRate;/* Mbps */ +}; + + +struct wifi_ioctl_sta_info { + UINT8 sta_cnt; + struct { + UINT8 MacAddress[MAC_ADDR_LEN]; + UINT8 VMacAddr[MAC_ADDR_LEN]; + CHAR RSSI; + ULONGLONG UpTime; + ULONG TxRate;/* Mbps */ + ULONG RxRate;/* Mbps */ + } item[MAX_ASSOC_NUM]; + UINT8 rept_sta_cnt; + struct { + UINT8 MacAddress[MAC_ADDR_LEN]; + UINT8 VMacAddr[MAC_ADDR_LEN]; + CHAR RSSI; + ULONGLONG UpTime; + ULONG TxRate;/* Mbps */ + ULONG RxRate;/* Mbps */ + } rept_item[MAX_ASSOC_NUM]; +}; + +enum wifi_event_type { + EVENTTYPE_INF_POLL = 1, /* Get interface basic info */ + EVENTTYPE_UPLINK_INFO, /* Get uplink (ApCli) status */ + EVENTTYPE_INF_STATS, /* Get interface statistics */ +}; + +struct wifi_event { + UINT8 type; + CHAR inf_name[MAX_INF_LEN];/* no need to edit */ + UINT8 MAC[MAC_ADDR_LEN]; + CHAR SSID[MAX_LEN_OF_SSID]; + union { + struct wifi_event_inf_poll poll; + struct wifi_event_inf_stats inf_stats; + } data; +}; + +#endif /* ANDLINK_FEATURE_SUPPORT */ +/*+++Used for merge MiniportMMRequest() and MiniportDataMMRequest() into one function */ +#define MGMT_USE_QUEUE_FLAG 0x80 +#define MGMT_USE_PS_FLAG 0x40 +/*---Used for merge MiniportMMRequest() and MiniportDataMMRequest() into one function */ +/* The number of channels for per-channel Tx power offset */ + + +#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 */ +#ifdef AIR_MONITOR + +#define MAX_NUM_OF_MONITOR_STA 8 +#define MONITOR_MUAR_BASE_INDEX 24 +#endif /* AIR_MONITOR */ + + +#define MAX_TXPOWER_ARRAY_SIZE 5 + +#define MAX_EEPROM_BUFFER_SIZE 1024 +#define PS_RETRIEVE_TOKEN 0x76 +#ifdef BAND_STEERING +#define DBDC_BAND_NUM 1 +#endif +extern unsigned char CISCO_OUI[]; +extern UCHAR BaSizeArray[4]; + +extern UCHAR BROADCAST_ADDR[MAC_ADDR_LEN]; +extern UCHAR ZERO_MAC_ADDR[MAC_ADDR_LEN]; +extern char *CipherName[]; +extern UCHAR SNAP_802_1H[6]; +extern UCHAR SNAP_BRIDGE_TUNNEL[6]; +extern UCHAR EAPOL[2]; +extern UCHAR IPX[2]; +extern UCHAR TPID[]; +extern UCHAR APPLE_TALK[2]; +extern UCHAR OfdmRateToRxwiMCS[]; +extern UCHAR WMM_UP2AC_MAP[8]; + +extern unsigned char RateIdToMbps[]; +extern USHORT RateIdTo500Kbps[]; + +extern UCHAR CipherSuiteWpaNoneTkip[]; +extern UCHAR CipherSuiteWpaNoneTkipLen; + +extern UCHAR CipherSuiteWpaNoneAes[]; +extern UCHAR CipherSuiteWpaNoneAesLen; + +extern UCHAR SsidIe; +extern UCHAR SupRateIe; +extern UCHAR ExtRateIe; + +#ifdef DOT11_N_SUPPORT +extern UCHAR HtCapIe; +extern UCHAR AddHtInfoIe; +extern UCHAR NewExtChanIe; +extern UCHAR BssCoexistIe; +extern UCHAR ExtHtCapIe; +#endif /* DOT11_N_SUPPORT */ +extern UCHAR ExtCapIe; + +extern UCHAR ErpIe; +extern UCHAR DsIe; +extern UCHAR TimIe; +extern UCHAR WpaIe; +extern UCHAR Wpa2Ie; +extern UCHAR IbssIe; +extern UCHAR WapiIe; + +extern UCHAR WPA_OUI[]; +extern UCHAR RSN_OUI[]; +extern UCHAR WAPI_OUI[]; +extern UCHAR WME_INFO_ELEM[]; +extern UCHAR WME_PARM_ELEM[]; +extern UCHAR RALINK_OUI[]; +#if (defined(WH_EZ_SETUP) || defined(MWDS) || defined(STA_FORCE_ROAM_SUPPORT)) || defined(WAPP_SUPPORT) +extern UCHAR MTK_OUI[]; +#endif +extern UCHAR PowerConstraintIE[]; + +extern INT PingFixRate; + +struct _RX_BLK; +struct raw_rssi_info; + +#ifdef FAST_DETECT_STA_OFF +extern int Flag_fast_detect_sta_off; + +#define COUTINUE_TX_FAIL_CHECK_TIMES 16 /*500ms per time */ +#define COUTINUE_TX_FAIL_CHECK_CNT 400 +typedef struct _COUNTER_CON { + UINT8 Idx; + BOOLEAN DisconnectFlag; + UINT16 CountinueTxFailCheckTimes; + UINT32 TxFailCnt[COUTINUE_TX_FAIL_CHECK_TIMES]; +} COUNTER_CON, *PCOUNTER_CON; +#endif + +typedef struct _UAPSD_INFO { + BOOLEAN bAPSDCapable; +} UAPSD_INFO; + + +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; + +#ifdef APCLI_SUPPORT +#ifdef APCLI_AUTO_CONNECT_SUPPORT +typedef enum _APCLI_CONNECT_SCAN_TYPE { + TRIGGER_SCAN_BY_USER = 0, + TRIGGER_SCAN_BY_DRIVER = 1, +} APCLI_CONNECT_SCAN_TYPE; +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ +#ifdef WSC_AP_SUPPORT +typedef enum _APCLI_WSC_SCAN_TYPE { + TRIGGER_FULL_SCAN = 0, + TRIGGER_PARTIAL_SCAN = 1 +} APCLI_WSC_SCAN_TYPE; + + +#endif /* WSC_AP_SUPPORT */ +#endif /* APCLI_SUPPORT */ + +#ifdef AIR_MONITOR +#define RULE_CTL BIT(0) +#define RULE_CTL_OFFSET 0 +#define RULE_MGT BIT(1) +#define RULE_MGT_OFFSET 1 +#define RULE_DATA BIT(2) +#define RULE_DATA_OFFSET 2 +#define RULE_A1 BIT(3) +#define RULE_A1_OFFSET 3 +#define RULE_A2 BIT(4) +#define RULE_A2_OFFSET 4 +#define DEFAULT_MNTR_RULE (RULE_MGT | RULE_DATA | RULE_A1 | RULE_A2) + + +typedef struct _MNT_STA_ENTRY { + BOOLEAN bValid; + UCHAR Band; + UCHAR muar_idx; + UCHAR muar_group_idx; + ULONG Count; + ULONG data_cnt; + ULONG mgmt_cnt; + ULONG cntl_cnt; + UCHAR addr[MAC_ADDR_LEN]; + RSSI_SAMPLE RssiSample; + VOID *pMacEntry; +} MNT_STA_ENTRY, *PMNT_STA_ENTRY; +typedef struct _HEADER_802_11_4_ADDR { + FRAME_CONTROL FC; + USHORT Duration; + USHORT SN; + UCHAR FN; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; + UCHAR Addr3[MAC_ADDR_LEN]; + UCHAR Addr4[MAC_ADDR_LEN]; +} HEADER_802_11_4_ADDR, *PHEADER_802_11_4_ADDR; +typedef struct _AIR_RADIO_INFO{ + CHAR PHYMODE; + CHAR SS; + CHAR MCS; + CHAR BW; + CHAR ShortGI; + ULONG RATE; + CHAR RSSI[4]; + UCHAR Channel; +} AIR_RADIO_INFO, *PAIR_RADIO_INFO; +typedef struct _AIR_RAW{ + AIR_RADIO_INFO wlan_radio_tap; + HEADER_802_11_4_ADDR wlan_header; +} AIR_RAW, *PAIR_RAW; +#endif /* AIR_MONITOR */ + + +/* + 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 RemoveTailQueue(QueueHeader) \ +(QueueHeader)->Tail; \ +{ \ + PQUEUE_ENTRY pNext; \ + if ((QueueHeader)->Head != NULL) \ + { \ + pNext = (QueueHeader)->Head; \ + if (pNext->Next == NULL) { \ + (QueueHeader)->Head = NULL; \ + (QueueHeader)->Tail = NULL; \ + } else { \ + while (pNext->Next != (QueueHeader)->Tail) \ + { \ + pNext = pNext->Next; \ + } \ + (QueueHeader)->Tail = pNext; \ + pNext->Next = NULL; \ + } \ + (QueueHeader)->Number--; \ + } \ +} + + +#define InsertHeadQueue(QueueHeader, QueueEntry) \ +{ \ + ((PQUEUE_ENTRY)QueueEntry)->Next = (QueueHeader)->Head; \ + (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry); \ + if ((QueueHeader)->Tail == NULL) \ + (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Number++; \ +} + +#define InsertTailQueue(QueueHeader, QueueEntry) \ +{ \ + ((PQUEUE_ENTRY)QueueEntry)->Next = NULL; \ + if ((QueueHeader)->Tail) \ + (QueueHeader)->Tail->Next = (PQUEUE_ENTRY)(QueueEntry); \ + else \ + (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Number++; \ +} + +#define InsertTailQueueAc(pAd, pEntry, QueueHeader, QueueEntry) \ +{ \ + ((PQUEUE_ENTRY)QueueEntry)->Next = NULL; \ + if ((QueueHeader)->Tail) \ + (QueueHeader)->Tail->Next = (PQUEUE_ENTRY)(QueueEntry); \ + else \ + (QueueHeader)->Head = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Tail = (PQUEUE_ENTRY)(QueueEntry); \ + (QueueHeader)->Number++; \ +} + + +/* */ +/* Macros for flag and ref count operations */ +/* */ +#define RTMP_SET_FLAG(_M, _F) ((_M)->Flags |= (_F)) +#define RTMP_CLEAR_FLAG(_M, _F) ((_M)->Flags &= ~(_F)) +#define RTMP_CLEAR_FLAGS(_M) ((_M)->Flags = 0) +#define RTMP_TEST_FLAG(_M, _F) (((_M)->Flags & (_F)) != 0) +#define RTMP_TEST_FLAGS(_M, _F) (((_M)->Flags & (_F)) == (_F)) +/* Macro for power save flag. */ +#define RTMP_SET_PSFLAG(_M, _F) ((_M)->PSFlags |= (_F)) +#define RTMP_CLEAR_PSFLAG(_M, _F) ((_M)->PSFlags &= ~(_F)) +#define RTMP_CLEAR_PSFLAGS(_M) ((_M)->PSFlags = 0) +#define RTMP_TEST_PSFLAG(_M, _F) (((_M)->PSFlags & (_F)) != 0) +#define RTMP_TEST_PSFLAGS(_M, _F) (((_M)->PSFlags & (_F)) == (_F)) + +#define OPSTATUS_SET_FLAG(_pAd, _F) ((_pAd)->CommonCfg.OpStatusFlags |= (_F)) +#define OPSTATUS_CLEAR_FLAG(_pAd, _F) ((_pAd)->CommonCfg.OpStatusFlags &= ~(_F)) +#define OPSTATUS_TEST_FLAG(_pAd, _F) (((_pAd)->CommonCfg.OpStatusFlags & (_F)) != 0) + +#define WIFI_TEST_SET_FLAG(_pAd, _F) ((_pAd)->CommonCfg.WiFiTestFlags |= (_F)) +#define WIFI_TEST_CLEAR_FLAG(_pAd, _F) ((_pAd)->CommonCfg.WiFiTestFlags &= ~(_F)) +#define WIFI_TEST_CHECK_FLAG(_pAd, _F) (((_pAd)->CommonCfg.WiFiTestFlags & (_F)) != 0) + +#define CLIENT_STATUS_SET_FLAG(_pEntry,_F) ((_pEntry)->ClientStatusFlags |= (_F)) +#define CLIENT_STATUS_CLEAR_FLAG(_pEntry,_F) ((_pEntry)->ClientStatusFlags &= ~(_F)) +#define CLIENT_STATUS_TEST_FLAG(_pEntry,_F) (((_pEntry)->ClientStatusFlags & (_F)) != 0) + +#define CLIENT_CAP_SET_FLAG(_pEntry,_F) ((_pEntry)->cli_cap_flags |= (_F)) +#define CLIENT_CAP_CLEAR_FLAG(_pEntry,_F) ((_pEntry)->cli_cap_flags &= ~(_F)) +#define CLIENT_CAP_TEST_FLAG(_pEntry,_F) (((_pEntry)->cli_cap_flags & (_F)) != 0) + + +#define RX_FILTER_SET_FLAG(_pAd, _F) ((_pAd)->CommonCfg.PacketFilter |= (_F)) +#define RX_FILTER_CLEAR_FLAG(_pAd, _F) ((_pAd)->CommonCfg.PacketFilter &= ~(_F)) +#define RX_FILTER_TEST_FLAG(_pAd, _F) (((_pAd)->CommonCfg.PacketFilter & (_F)) != 0) + +#define RTMP_SET_MORE_FLAG(_M, _F) ((_M)->MoreFlags |= (_F)) +#define RTMP_TEST_MORE_FLAG(_M, _F) (((_M)->MoreFlags & (_F)) != 0) +#define RTMP_CLEAR_MORE_FLAG(_M, _F) ((_M)->MoreFlags &= ~(_F)) + +#define SET_ASIC_CAP(_pAd, _caps) ((_pAd)->chipCap.asic_caps |= (_caps)) +#define IS_ASIC_CAP(_pAd, _caps) (((_pAd)->chipCap.asic_caps & (_caps)) != 0) +#define CLR_ASIC_CAP(_pAd, _caps) ((_pAd)->chipCap.asic_caps &= ~(_caps)) + +#define TX_FLAG_STOP_DEQUEUE (fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS |\ + fRTMP_ADAPTER_RADIO_OFF |\ + fRTMP_ADAPTER_RESET_IN_PROGRESS |\ + fRTMP_ADAPTER_HALT_IN_PROGRESS |\ + fRTMP_ADAPTER_NIC_NOT_EXIST |\ + fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET) + +#define INC_RING_INDEX(_idx, _RingSize) \ +{ \ + (_idx) = (_idx+1) % (_RingSize); \ +} + +#ifdef LIMIT_GLOBAL_SW_QUEUE +#define TR_ENQ_COUNT_INC(tr, QueueHeader) \ +{ \ + tr->enqCount++; \ + (QueueHeader)->Number++; \ +} + +#define TR_ENQ_COUNT_DEC(tr, QueueHeader) \ +{ \ + tr->enqCount--; \ + (QueueHeader)->Number--; \ +} +#else /* LIMIT_GLOBAL_SW_QUEUE */ +#define TR_ENQ_COUNT_INC(tr) \ +{ \ + tr->enqCount++; \ +} + +#define TR_ENQ_COUNT_DEC(tr) \ +{ \ + tr->enqCount--; \ +} +#endif /*! LIMIT_GLOBAL_SW_QUEUE*/ + +#define TR_TOKEN_COUNT_INC(tr, qid) \ +{ \ + tr->TokenCount[qid]++; \ +} + +#define TR_TOKEN_COUNT_DEC(tr, qid) \ +{ \ + tr->TokenCount[qid]--; \ +} + +#ifdef MULTI_CLIENT_SUPPORT +#define SQ_ENQ_PS_MAX 768 /*1024*/ +#define SQ_ENQ_NORMAL_MAX 1024 /*2048*/ /* Per STA queue */ +#define SQ_ENQ_RESERVE_PERAC (SQ_ENQ_NORMAL_MAX/2) +#else +#define SQ_ENQ_PS_MAX 512 +#define SQ_ENQ_NORMAL_MAX 512 /* Per STA queue */ +#define SQ_ENQ_RESERVE_PERAC (SQ_ENQ_NORMAL_MAX/2) +#endif +#if defined(MAX_CONTINUOUS_TX_CNT) || defined(NEW_IXIA_METHOD) +#undef SQ_ENQ_NORMAL_MAX +#define SQ_ENQ_NORMAL_MAX 4096 /* Per STA queue */ +#endif +#ifdef DATA_QUEUE_RESERVE +#define FIFO_RSV_FOR_HIGH_PRIORITY 64 +#endif /* DATA_QUEUE_RESERVE */ + +#ifdef USB_BULK_BUF_ALIGMENT +#define CUR_WRITE_IDX_INC(_idx, _RingSize) \ +{ \ + (_idx) = (_idx+1) % (_RingSize); \ +} +#endif /* USB_BULK_BUF_ALIGMENT */ + + +/* + Common fragment list structure - Identical to the scatter gather frag list structure +*/ +#define NIC_MAX_PHYS_BUF_COUNT 8 + +typedef struct _RTMP_SCATTER_GATHER_ELEMENT { + PVOID Address; + ULONG Length; + PULONG Reserved; +} RTMP_SCATTER_GATHER_ELEMENT, *PRTMP_SCATTER_GATHER_ELEMENT; + +typedef struct _RTMP_SCATTER_GATHER_LIST { + ULONG NumberOfElements; + PULONG Reserved; + RTMP_SCATTER_GATHER_ELEMENT Elements[NIC_MAX_PHYS_BUF_COUNT]; +} RTMP_SCATTER_GATHER_LIST, *PRTMP_SCATTER_GATHER_LIST; + + +/* + Some utility macros +*/ +#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)->ApCfg.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(_buf, _pMac1, _pMac2, _pType) \ +{ \ + NdisMoveMemory(_buf, _pMac1, MAC_ADDR_LEN); \ + NdisMoveMemory((_buf + MAC_ADDR_LEN), _pMac2, MAC_ADDR_LEN); \ + NdisMoveMemory((_buf + MAC_ADDR_LEN * 2), _pType, LENGTH_802_3_TYPE); \ +} + +/* + if pData has no LLC/SNAP (neither RFC1042 nor Bridge tunnel), + keep it that way. + else if the received frame is LLC/SNAP-encaped IPX or APPLETALK, + preserve the LLC/SNAP field + else remove the LLC/SNAP field from the result Ethernet frame + + Patch for WHQL only, which did not turn on Netbios but use IPX within its payload + Note: + _pData & _DataSize may be altered (remove 8-byte LLC/SNAP) by this MACRO + _pRemovedLLCSNAP: pointer to removed LLC/SNAP; NULL is not removed +*/ +#define CONVERT_TO_802_3(_p8023hdr, _pDA, _pSA, _pData, _DataSize, _pRemovedLLCSNAP) \ +{ \ + char LLC_Len[2]; \ + \ + _pRemovedLLCSNAP = NULL; \ + if (NdisEqualMemory(SNAP_802_1H, _pData, 6) || \ + NdisEqualMemory(SNAP_BRIDGE_TUNNEL, _pData, 6)) \ + { \ + PUCHAR pProto = _pData + 6; \ + \ + if ((NdisEqualMemory(IPX, pProto, 2) || NdisEqualMemory(APPLE_TALK, pProto, 2)) && \ + NdisEqualMemory(SNAP_802_1H, _pData, 6)) \ + { \ + LLC_Len[0] = (UCHAR)(_DataSize >> 8); \ + LLC_Len[1] = (UCHAR)(_DataSize & (256 - 1)); \ + MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, LLC_Len); \ + } \ + else \ + { \ + MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, pProto); \ + _pRemovedLLCSNAP = _pData; \ + _DataSize -= LENGTH_802_1_H; \ + _pData += LENGTH_802_1_H; \ + } \ + } \ + else \ + { \ + LLC_Len[0] = (UCHAR)(_DataSize >> 8); \ + LLC_Len[1] = (UCHAR)(_DataSize & (256 - 1)); \ + MAKE_802_3_HEADER(_p8023hdr, _pDA, _pSA, LLC_Len); \ + } \ +} + +/* + Enqueue this frame to MLME engine + We need to enqueue the whole frame because MLME need to pass data type + information from 802.11 header +*/ +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) +#define REPORT_MGMT_FRAME_TO_MLME(_pAd, Wcid, _pFrame, _FrameSize, _Rssi0, _Rssi1, _Rssi2, \ + _Snr0, _Snr1, _MinSNR, _OpMode)\ +do{ \ + struct raw_rssi_info _rssi_info;\ + _rssi_info.raw_rssi[0] = _Rssi0;\ + _rssi_info.raw_rssi[1] = _Rssi1;\ + _rssi_info.raw_rssi[2] = _Rssi2;\ + _rssi_info.raw_snr = _MinSNR;\ + MlmeEnqueueForRecv(_pAd, Wcid, &_rssi_info, _Snr0, _Snr1, _FrameSize, _pFrame, _OpMode); \ +}while(0) +#else +#define REPORT_MGMT_FRAME_TO_MLME(_pAd, Wcid, _pFrame, _FrameSize, _Rssi0, _Rssi1, _Rssi2, _MinSNR, _OpMode) \ +do{ \ + struct raw_rssi_info _rssi_info;\ + _rssi_info.raw_rssi[0] = _Rssi0;\ + _rssi_info.raw_rssi[1] = _Rssi1;\ + _rssi_info.raw_rssi[2] = _Rssi2;\ + _rssi_info.raw_snr = _MinSNR;\ + MlmeEnqueueForRecv(_pAd, Wcid, &_rssi_info, _FrameSize, _pFrame, _OpMode); \ +}while(0) +#endif + +#define IPV4_ADDR_EQUAL(pAddr1, pAddr2) RTMPEqualMemory((PVOID)(pAddr1), (PVOID)(pAddr2), 4) +#define IPV6_ADDR_EQUAL(pAddr1, pAddr2) RTMPEqualMemory((PVOID)(pAddr1), (PVOID)(pAddr2), 16) +#define MAC_ADDR_EQUAL(pAddr1,pAddr2) RTMPEqualMemory((PVOID)(pAddr1), (PVOID)(pAddr2), MAC_ADDR_LEN) +#define SSID_EQUAL(ssid1, len1, ssid2, len2) ((len1==len2) && (RTMPEqualMemory(ssid1, ssid2, len1))) + + +/* + 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; + NDIS_PHYSICAL_ADDRESS PacketPa; + RTMP_DMABUF DmaBuf; /* Associated DMA buffer structure */ +#ifdef CACHE_LINE_32B + RXD_STRUC LastBDInfo; +#endif /* CACHE_LINE_32B */ +} RTMP_DMACB, *PRTMP_DMACB; + +BOOLEAN MonitorRxRing(struct _RTMP_ADAPTER *pAd); +BOOLEAN MonitorTxRing(struct _RTMP_ADAPTER *pAd); +BOOLEAN MonitorRxPse(struct _RTMP_ADAPTER *pAd); + + +typedef struct _RTMP_TX_RING { + RTMP_DMACB Cell[TX_RING_SIZE]; + UINT32 TxCpuIdx; + UINT32 TxDmaIdx; + UINT32 TxSwFreeIdx; /* software next free tx index */ + UINT32 hw_desc_base; + UINT32 hw_cidx_addr; + UINT32 hw_didx_addr; + UINT32 hw_cnt_addr; +} RTMP_TX_RING; + +typedef struct _RTMP_RX_RING { + RTMP_DMACB Cell[RX_RING_SIZE]; + UINT32 RxCpuIdx; + UINT32 RxDmaIdx; + INT32 RxSwReadIdx; /* software next read index */ + UINT32 hw_desc_base; + UINT32 hw_cidx_addr; + UINT32 hw_didx_addr; + UINT32 hw_cnt_addr; +} RTMP_RX_RING; + +typedef struct _RTMP_MGMT_RING { + RTMP_DMACB Cell[MGMT_RING_SIZE]; + UINT32 TxCpuIdx; + UINT32 TxDmaIdx; + UINT32 TxSwFreeIdx; /* software next free tx index */ + UINT32 hw_desc_base; + UINT32 hw_cidx_addr; + UINT32 hw_didx_addr; + UINT32 hw_cnt_addr; +} RTMP_MGMT_RING; + +typedef struct _RTMP_CTRL_RING { + RTMP_DMACB Cell[MGMT_RING_SIZE]; + UINT32 TxCpuIdx; + UINT32 TxDmaIdx; + UINT32 TxSwFreeIdx; /* software next free tx index */ + UINT32 hw_desc_base; + UINT32 hw_cidx_addr; + UINT32 hw_didx_addr; + UINT32 hw_cnt_addr; +} RTMP_CTRL_RING; + +#ifdef MT_MAC +typedef struct _RTMP_BCN_RING { + RTMP_DMACB Cell[BCN_RING_SIZE]; + UINT32 TxCpuIdx; + UINT32 TxDmaIdx; + UINT32 TxSwFreeIdx; /* software next free tx index */ + UINT32 hw_desc_base; + UINT32 hw_cidx_addr; + UINT32 hw_didx_addr; + UINT32 hw_cnt_addr; +} RTMP_BCN_RING; +#endif /* MT_MAC */ + +/* + Statistic counter structure +*/ +typedef struct _COUNTER_802_3 { + /* General Stats */ + ULONG GoodTransmits; + ULONG GoodReceives; + ULONG TxErrors; + ULONG RxErrors; + ULONG RxNoBuffer; +} COUNTER_802_3, *PCOUNTER_802_3; + +typedef struct _COUNTER_802_11 { + ULONG Length; +/* LARGE_INTEGER LastTransmittedFragmentCount; */ + LARGE_INTEGER TransmittedFragmentCount; + LARGE_INTEGER MulticastTransmittedFrameCount; + LARGE_INTEGER FailedCount; + LARGE_INTEGER RetryCount; + LARGE_INTEGER MultipleRetryCount; + LARGE_INTEGER RTSSuccessCount; + LARGE_INTEGER RTSFailureCount; + LARGE_INTEGER ACKFailureCount; + LARGE_INTEGER FrameDuplicateCount; + LARGE_INTEGER ReceivedFragmentCount; + LARGE_INTEGER MulticastReceivedFrameCount; + LARGE_INTEGER FCSErrorCount; + LARGE_INTEGER TransmittedFrameCount; + LARGE_INTEGER WEPUndecryptableCount; + LARGE_INTEGER TransmitCountFrmOs; +#ifdef MT_MAC + LARGE_INTEGER TxAggRange1Count; + LARGE_INTEGER TxAggRange2Count; + LARGE_INTEGER TxAggRange3Count; + LARGE_INTEGER TxAggRange4Count; + + /* for PER debug */ + LARGE_INTEGER AmpduFailCount; + LARGE_INTEGER AmpduSuccessCount; + /* for PER debug */ + +#endif /* MT_MAC */ +} COUNTER_802_11, *PCOUNTER_802_11; + + +typedef struct _ASIC_UPDATE_PROTECT +{ + USHORT OperationMode; + UCHAR SetMask; + BOOLEAN bDisableBGProtect; + BOOLEAN bNonGFExist; +} ASIC_UPDATE_PROTECT, *PASIC_UPDATE_PROTECT; + +// Wtbl2RateTableUpdate +typedef struct _WTBL2_RATE_TABLE_UPDATE +{ + UCHAR ucWcid; + UINT32 u4Wtbl2D9; + UINT32 rate[8]; +} WTBL2_RATE_TABLE_UPDATE, *PWTBL2_RATE_TABLE_UPDATE; + +typedef struct _WTBL_TX_PS_UPDATE +{ + UINT8 ucWlanIdx; + UINT8 ucPwrMgtBit; +} WTBL_TX_PS_UPDATE, *PWTBL_TX_PS_UPDATE; + + + +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 OneSecCCKFalseCCACnt; + UINT32 OneSecOFDMFalseCCACnt; + 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 OneSecTxARalinkCnt; /* Tx Ralink Aggregation frame cnt */ + UINT32 OneSecRxARalinkCnt; /* Rx Ralink Aggregation frame cnt */ + UINT32 OneSecEnd; /* for one sec count clear use */ +#ifdef ANTI_INTERFERENCE_SUPPORT + UINT32 OneSecTxAMpduCnt; + UINT32 OneSecTxBACnt; +#endif /* ANTI_INTERFERENCE_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 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 TxAMSDUCount; + LARGE_INTEGER RxAMSDUCount; + LARGE_INTEGER TransmittedAMPDUCount; + LARGE_INTEGER TransmittedMPDUsInAMPDUCount; + LARGE_INTEGER TransmittedOctetsInAMPDUCount; + LARGE_INTEGER MPDUInReceivedAMPDUCount; + + ULONG PhyErrCnt; + ULONG PlcpErrCnt; +#ifdef MAC_REPEATER_SUPPORT + ULONG BaSnResetCnt; +#endif /* MAC_REPEATER_SUPPORT */ +} 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 */ + /*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 +#endif /* DOT11_N_SUPPORT */ + + +#ifdef STREAM_MODE_SUPPORT +typedef struct _STREAM_MODE_ENTRY_{ +#define STREAM_MODE_STATIC 1 + USHORT flag; + UCHAR macAddr[MAC_ADDR_LEN]; +}STREAM_MODE_ENTRY; +#endif /* STREAM_MODE_SUPPORT */ + +/* for Microwave oven */ +#ifdef MICROWAVE_OVEN_SUPPORT +typedef struct _MO_CFG_STRUCT { + BOOLEAN bEnable; + UINT8 nPeriod_Cnt; /* measurement period 100ms, mitigate the interference period 900 ms */ + UINT16 nFalseCCACnt; + UINT16 nFalseCCATh; /* default is 100 */ +} MO_CFG_STRUCT, *PMO_CFG_STRUCT; +#endif /* MICROWAVE_OVEN_SUPPORT */ + +/* TODO: need to integrate with MICROWAVE_OVEN_SUPPORT */ +#ifdef DYNAMIC_VGA_SUPPORT +/* for dynamic vga */ +typedef struct _LNA_VGA_CTL_STRUCT { + BOOLEAN bEnable; + BOOLEAN bDyncVgaEnable; + UINT8 nPeriod_Cnt; /* measurement period 100ms, mitigate the interference period 900 ms */ + UINT16 nFalseCCACnt; + UINT16 nFalseCCATh; /* default is 100 */ + UINT16 nLowFalseCCATh; + UCHAR agc_vga_init_0; + UINT16 agc_0_vga_set1_2; + UCHAR agc_vga_init_1; + UINT16 agc_1_vga_set1_2; +} LNA_VGA_CTL_STRUCT, *PLNA_VGA_CTL_STRUCT; +#endif /* DYNAMIC_VGA_SUPPORT */ + +/*************************************************************************** + * security key related data structure + **************************************************************************/ + +/* structure to define WPA Group Key Rekey Interval */ +typedef struct GNU_PACKED _RT_802_11_WPA_REKEY { + ULONG ReKeyMethod; /* mechanism for rekeying: 0:disable, 1: time-based, 2: packet-based */ + ULONG ReKeyInterval; /* time-based: seconds, packet-based: kilo-packets */ +} RT_WPA_REKEY,*PRT_WPA_REKEY, RT_802_11_WPA_REKEY, *PRT_802_11_WPA_REKEY; + + + +typedef struct { + UCHAR Addr[MAC_ADDR_LEN]; + UCHAR ErrorCode[2]; /*00 01-Invalid authentication type */ + /*00 02-Authentication timeout */ + /*00 03-Challenge from AP failed */ + /*00 04-Challenge to AP failed */ + BOOLEAN Reported; +} ROGUEAP_ENTRY, *PROGUEAP_ENTRY; + +typedef struct { + UCHAR RogueApNr; + ROGUEAP_ENTRY RogueApEntry[MAX_LEN_OF_BSS_TABLE]; +} ROGUEAP_TABLE, *PROGUEAP_TABLE; + +/* + * Fragment Frame structure + */ +typedef struct _FRAGMENT_FRAME { + PNDIS_PACKET pFragPacket; + ULONG RxSize; + USHORT Sequence; + USHORT LastFrag; + ULONG Flags; /* Some extra frame information. bit 0: LLC presented */ +} FRAGMENT_FRAME, *PFRAGMENT_FRAME; + + +/* + Tkip Key structure which RC4 key & MIC calculation +*/ +typedef struct _TKIP_KEY_INFO { + UINT nBytesInM; /* # bytes in M for MICKEY */ + ULONG IV16; + ULONG IV32; + ULONG K0; /* for MICKEY Low */ + ULONG K1; /* for MICKEY Hig */ + ULONG L; /* Current state for MICKEY */ + ULONG R; /* Current state for MICKEY */ + ULONG M; /* Message accumulator for MICKEY */ + UCHAR RC4KEY[16]; + UCHAR MIC[8]; +} TKIP_KEY_INFO, *PTKIP_KEY_INFO; + + +/* + Private / Misc data, counters for driver internal use +*/ +typedef struct __PRIVATE_STRUC { + /* Tx ring full occurrance number */ + UINT TxRingFullCnt; + /* 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 + CHANNEL_80M_CAP: 800 BW channel group + */ +#define CHANNEL_DEFAULT_PROP 0x00 +#define CHANNEL_DISABLED 0x01 /* no use */ +#define CHANNEL_PASSIVE_SCAN 0x02 +#define CHANNEL_NO_IBSS 0x04 +#define CHANNEL_RADAR 0x08 +#define CHANNEL_NO_FAT_ABOVE 0x10 +#define CHANNEL_NO_FAT_BELOW 0x20 +#define CHANNEL_40M_CAP 0x40 +#define CHANNEL_80M_CAP 0x80 + + UCHAR Flags; + +} CHANNEL_TX_POWER, *PCHANNEL_TX_POWER; + +/* Channel list subset */ +typedef struct _CHANNEL_LIST_SUB { + UCHAR Channel; + UCHAR IdxMap; /* Index mapping to original channel list */ +} CHANNEL_LIST_SUB, *PCHANNEL_LIST_SUB; + + +typedef struct _SOFT_RX_ANT_DIVERSITY_STRUCT { + UCHAR EvaluatePeriod; /* 0:not evalute status, 1: evaluate status, 2: switching status */ + UCHAR EvaluateStableCnt; + UCHAR Pair1PrimaryRxAnt; /* 0:Ant-E1, 1:Ant-E2 */ + UCHAR Pair1SecondaryRxAnt; /* 0:Ant-E1, 1:Ant-E2 */ + 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; + +#if defined(CONFIG_STA_SUPPORT) || defined(APCLI_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 { + STATE_MACHINE_FUNC ActFunc[ACT_FUNC_SIZE]; + /* Action */ + STATE_MACHINE ActMachine; + +#ifdef WSC_INCLUDED + STATE_MACHINE WscMachine; + STATE_MACHINE_FUNC WscFunc[WSC_FUNC_SIZE]; + +#endif /* WSC_INCLUDED */ + + + +#ifdef CONFIG_HOTSPOT + STATE_MACHINE HSCtrlMachine; + STATE_MACHINE_FUNC HSCtrlFunc[GAS_FUNC_SIZE]; +#endif + +#ifdef DOT11U_INTERWORKING + STATE_MACHINE GASMachine; + STATE_MACHINE_FUNC GASFunc[GAS_FUNC_SIZE]; +#endif + +#ifdef DOT11K_RRM_SUPPORT + STATE_MACHINE BCNMachine; + STATE_MACHINE_FUNC BCNFunc[BCN_FUNC_SIZE]; + STATE_MACHINE NRMachine; + STATE_MACHINE_FUNC NRFunc[NR_FUNC_SIZE]; +#endif + +#ifdef CONFIG_DOT11V_WNM + STATE_MACHINE BTMMachine; + STATE_MACHINE_FUNC BTMFunc[BTM_FUNC_SIZE]; + STATE_MACHINE WNMNotifyMachine; + STATE_MACHINE_FUNC WNMNotifyFunc[WNM_NOTIFY_FUNC_SIZE]; +#endif + +#ifdef CONFIG_AP_SUPPORT + /* AP state machines */ + STATE_MACHINE ApAssocMachine; + STATE_MACHINE ApAuthMachine; + STATE_MACHINE ApSyncMachine; +#ifdef WH_EZ_SETUP +#ifdef EZ_MOD_SUPPORT + STATE_MACHINE EzMachine; +#else + //! Levarage from MP1.0 CL#170063 + STATE_MACHINE EzRoamMachine; + STATE_MACHINE ApTriBandMachine; +#endif +#endif + + 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 WH_EZ_SETUP +#ifdef EZ_MOD_SUPPORT + STATE_MACHINE_FUNC EzFunc[EZ_FUNC_SIZE]; +#else + //! Levarage from MP1.0 CL#170063 + STATE_MACHINE_FUNC EzRoamFunc[EZ_ROAM_FUNC_SIZE]; + STATE_MACHINE_FUNC ApTriBandFunc[AP_TRIBAND_FUNC_SIZE]; +#endif +#endif +#ifdef APCLI_SUPPORT + STATE_MACHINE ApCliAuthMachine; + STATE_MACHINE ApCliAssocMachine; + STATE_MACHINE ApCliCtrlMachine; + STATE_MACHINE ApCliSyncMachine; + STATE_MACHINE ApCliWpaPskMachine; + + STATE_MACHINE_FUNC ApCliAuthFunc[APCLI_AUTH_FUNC_SIZE]; + STATE_MACHINE_FUNC ApCliAssocFunc[APCLI_ASSOC_FUNC_SIZE]; + STATE_MACHINE_FUNC ApCliCtrlFunc[APCLI_CTRL_FUNC_SIZE]; + STATE_MACHINE_FUNC ApCliSyncFunc[APCLI_SYNC_FUNC_SIZE]; +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + /* common WPA state machine */ + STATE_MACHINE WpaMachine; + STATE_MACHINE_FUNC WpaFunc[WPA_FUNC_SIZE]; + + + ULONG ChannelQuality; /* 0..100, Channel Quality Indication for Roaming */ + ULONG Now32; /* latch the value of NdisGetSystemUpTime() */ + ULONG LastSendNULLpsmTime; + + BOOLEAN bRunning; + NDIS_SPIN_LOCK TaskLock; + +#ifdef EAPOL_QUEUE_SUPPORT + EAP_MLME_QUEUE EAP_Queue; +#endif /* EAPOL_QUEUE_SUPPORT */ + + MLME_QUEUE Queue; + + UINT ShiftReg; + + RALINK_TIMER_STRUCT PeriodicTimer; + RALINK_TIMER_STRUCT APSDPeriodicTimer; + RALINK_TIMER_STRUCT LinkDownTimer; + RALINK_TIMER_STRUCT LinkUpTimer; +#ifdef 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 _BA_SESSION_TYPE{ + BA_SESSION_INV = 0, + BA_SESSION_ORI = 1, + BA_SESSION_RECP = 2, +}BA_SESSION_TYPE; + +typedef enum _REC_BLOCKACK_STATUS { + Recipient_NONE = 0, + Recipient_USED, + Recipient_HandleRes, + Recipient_Accept +} REC_BLOCKACK_STATUS, *PREC_BLOCKACK_STATUS; + +typedef enum _ORI_BLOCKACK_STATUS { + Originator_NONE = 0, + Originator_USED, + Originator_WaitRes, + Originator_Done +} ORI_BLOCKACK_STATUS, *PORI_BLOCKACK_STATUS; + +typedef struct _BA_ORI_ENTRY { + UCHAR Wcid; + UCHAR TID; + UCHAR BAWinSize; + UCHAR Token; + UCHAR amsdu_cap; +/* Sequence is to fill every outgoing QoS DATA frame's sequence field in 802.11 header. */ + USHORT Sequence; + USHORT TimeOutValue; + ORI_BLOCKACK_STATUS ORI_BA_Status; + RALINK_TIMER_STRUCT ORIBATimer; + PVOID pAdapter; +} BA_ORI_ENTRY, *PBA_ORI_ENTRY; + +typedef struct _BA_REC_ENTRY { + UCHAR Wcid; + UCHAR TID; + UCHAR BAWinSize; /* 7.3.1.14. each buffer is capable of holding a max AMSDU or MSDU. */ + /*UCHAR NumOfRxPkt; */ + /*UCHAR Curindidx; // the head in the RX reordering buffer */ + USHORT LastIndSeq; +/* USHORT LastIndSeqAtTimer; */ + USHORT TimeOutValue; + RALINK_TIMER_STRUCT RECBATimer; + ULONG LastIndSeqAtTimer; + ULONG nDropPacket; + ULONG rcvSeq; + REC_BLOCKACK_STATUS REC_BA_Status; +/* UCHAR RxBufIdxUsed; */ + /* corresponding virtual address for RX reordering packet storage. */ + /*RTMP_REORDERDMABUF MAP_RXBuf[MAX_RX_REORDERBUF]; */ + NDIS_SPIN_LOCK RxReRingLock; /* Rx Ring spinlock */ +/* struct _BA_REC_ENTRY *pNext; */ + PVOID pAdapter; + struct reordering_list list; +} BA_REC_ENTRY, *PBA_REC_ENTRY; + + +typedef struct { + ULONG numAsRecipient; /* I am recipient of numAsRecipient clients. These client are in the BARecEntry[] */ + ULONG numAsOriginator; /* I am originator of numAsOriginator clients. These clients are in the BAOriEntry[] */ + ULONG numDoneOriginator; /* count Done Originator sessions */ + BA_ORI_ENTRY BAOriEntry[MAX_LEN_OF_BA_ORI_TABLE]; + BA_REC_ENTRY BARecEntry[MAX_LEN_OF_BA_REC_TABLE]; +#ifdef CONFIG_BA_REORDER_MONITOR + BOOLEAN ba_timeout_check; + UINT32 ba_timeout_bitmap[16]; + UINT32 ba_reordering_packet_timeout; +#endif +} BA_TABLE, *PBA_TABLE; + +/*For QureyBATableOID use; */ +typedef struct GNU_PACKED _OID_BA_REC_ENTRY { + UCHAR MACAddr[MAC_ADDR_LEN]; + UCHAR BaBitmap; /* if (BaBitmap&(1<MaxHTPhyMode.field.MODE == MODE_VHT) +#define IS_HT_STA(_pMacEntry) \ + (_pMacEntry->MaxHTPhyMode.field.MODE >= MODE_HTMIX) + +#define IS_HT_RATE(_pMacEntry) \ + (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) + +#ifdef DOT11_VHT_AC +#define IS_VHT_RATE(_pMacEntry) \ + (_pMacEntry->HTPhyMode.field.MODE == MODE_VHT) +#endif +#define PEER_IS_HT_RATE(_pMacEntry) \ + (_pMacEntry->HTPhyMode.field.MODE >= MODE_HTMIX) + +#endif /* DOT11_N_SUPPORT */ + +/*This structure is for all 802.11n card InterOptibilityTest action. Reset all Num every n second. (Details see MLMEPeriodic) */ +typedef struct _IOT_STRUC { + BOOLEAN bRTSLongProtOn; +} IOT_STRUC; + +/* This is the registry setting for 802.11n transmit setting. Used in advanced page. */ +typedef union _REG_TRANSMIT_SETTING { +#ifdef RT_BIG_ENDIAN + struct { + UINT32 rsv:13; + UINT32 EXTCHA:2; + UINT32 HTMODE:1; + UINT32 TRANSNO:2; + UINT32 STBC:1; /*SPACE */ + UINT32 ShortGI:1; + UINT32 BW:1; /*channel bandwidth 20MHz or 40 MHz */ + UINT32 TxBF:1; /* 3*3 */ + UINT32 ITxBfEn:1; + UINT32 rsv0:9; + /*UINT32 MCS:7; // MCS */ + /*UINT32 PhyMode:4; */ + } field; +#else + struct { + /*UINT32 PhyMode:4; */ + /*UINT32 MCS:7; // MCS */ + UINT32 rsv0:9; + UINT32 ITxBfEn:1; + UINT32 TxBF:1; + UINT32 BW:1; /*channel bandwidth 20MHz or 40 MHz */ + UINT32 ShortGI:1; + UINT32 STBC:1; /*SPACE */ + UINT32 TRANSNO:2; + UINT32 HTMODE:1; + UINT32 EXTCHA:2; + UINT32 rsv:13; + } field; +#endif + UINT32 word; +} REG_TRANSMIT_SETTING; + +#ifdef MBO_SUPPORT +#define MBO_NPC_MAX_LEN 50/* Non Preferred Channel List Max Len */ + +typedef struct GNU_PACKED non_pref_ch { + UINT8 ch; + UINT8 pref; + UINT8 reason_code; + +} STA_CH_PREF, *P_STA_CH_PREF; + +typedef struct _MBO_CTRL { + BOOLEAN bMboEnable; + /* BOOLEAN bHaveBTMSta;*/ + /* TRUE if this wdev still have STAs undergoing BTM disassoc procedure */ + UINT8 MboCapIndication; + UINT8 AssocDisallowReason; + UINT8 CellularPreference; + UINT8 TransitionReason; + UINT16 ReAssocDelay; /* second */ +} MBO_CTRL, *P_MBO_CTRL; + +typedef struct GNU_PACKED _MBO_STA_CH_PREF_CDC_INFO +{ + UINT8 mac_addr[MAC_ADDR_LEN]; + UINT8 bssid[MAC_ADDR_LEN]; + UINT8 cdc; /* cellular data capability */ + UINT8 npc_num; + UINT32 akm; + UINT32 cipher; + struct non_pref_ch npc[MBO_NPC_MAX_LEN]; +} MBO_STA_CH_PREF_CDC_INFO, *P_MBO_STA_CH_PREF_CDC_INFO; +#endif + +typedef union _DESIRED_TRANSMIT_SETTING { +#ifdef RT_BIG_ENDIAN + struct { + USHORT rsv:2; + USHORT FixedTxMode:3; /* If MCS isn't AUTO, fix rate in CCK, OFDM, HT or VHT mode. */ + USHORT PhyMode:4; + USHORT MCS:7; /* MCS */ + } field; +#else + struct { + USHORT MCS:7; + USHORT PhyMode:4; + USHORT FixedTxMode:3; + USHORT rsv:2; + } field; +#endif + USHORT word; + } DESIRED_TRANSMIT_SETTING; + + +struct hw_setting{ + UCHAR prim_ch; + UCHAR cent_ch; + UINT8 bbp_bw; + UCHAR rf_band; + UCHAR cur_ch_pwr[3]; + CHAR lan_gain; +}; + + +#define WDEV_TYPE_AP 0x01 +#define WDEV_TYPE_STA 0x02 +#define WDEV_TYPE_ADHOC 0x04 +#define WDEV_TYPE_WDS 0x08 +#define WDEV_TYPE_MESH 0x10 +#ifdef WH_EZ_SETUP +#define WDEV_TYPE_APCLI (1<<7) +#endif +#ifdef MAC_REPEATER_SUPPORT +typedef struct _RX_TA_TID_SEQ_MAPPING { + UINT8 RxDWlanIdx; + UINT8 MuarIdx;/* search by RMAC, which will match the first matched one, + in repeater and apcli, it will be the same one cause comes from the same rootap.*/ + UINT16 TID_SEQ[8];/*record the latest SEQ for each TID of each wlanIdx.*/ + UINT8 LatestTID;/* recode the latest rx TID.*/ + UCHAR LatestTA[MAC_ADDR_LEN];/* recode the latest rx TA.*/ +}RX_TA_TID_SEQ_MAPPING, *PRX_TA_TID_SEQ_MAPPING; + +typedef struct _RX_TRACKING_T { + //RX_TA_TID_SEQ_MAPPING RxTaTidSeqMap[MAX_LEN_OF_MAC_TABLE]; + RX_TA_TID_SEQ_MAPPING LastRxWlanIdx;/* the last entry will be taken to compare with newest Rx Pkt.*/ + UINT32 TriggerNum; +} RX_TRACKING_T, *PRX_TRACKING_T; +#endif /* MAC_REPEATER_SUPPORT */ + +struct wifi_dev{ + PNET_DEV if_dev; + VOID *func_dev; + VOID *sys_handle; + + CHAR wdev_idx; /* index refer from pAd->wdev_list[] */ + CHAR func_idx; /* index refer to func_dev which pointer to */ + UCHAR tr_tb_idx; /* index refer to BSS which this device belong */ + UCHAR wdev_type; + UCHAR PhyMode; + UCHAR channel; + UCHAR CentralChannel; + UCHAR extcha; + UCHAR bw; + UCHAR if_addr[MAC_ADDR_LEN]; + UCHAR bssid[MAC_ADDR_LEN]; + UCHAR hw_bssid_idx; + + /* security segment */ + NDIS_802_11_AUTHENTICATION_MODE AuthMode; + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_802_11_WEP_STATUS GroupKeyWepStatus; + WPA_MIX_PAIR_CIPHER WpaMixPairCipher; + UCHAR DefaultKeyId; + UCHAR PortSecured; +#if defined(DOT1X_SUPPORT) || defined(WPA_SUPPLICANT_SUPPORT) + BOOLEAN IEEE8021X; /* Only indicate if we are running in dynamic WEP mode (WEP+802.1x) */ +#endif /* DOT1X_SUPPORT */ + + /* transmit segment */ + BOOLEAN allow_data_tx; + BOOLEAN IgmpSnoopEnable; /* Only enabled for AP/WDS mode */ + RT_PHY_INFO DesiredHtPhyInfo; + DESIRED_TRANSMIT_SETTING DesiredTransmitSetting; /* Desired transmit setting. this is for reading registry setting only. not useful. */ + BOOLEAN bAutoTxRateSwitch; + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode, MinHTPhyMode; /* For transmit phy setting in TXWI. */ + + /* 802.11 protocol related characters */ + BOOLEAN bWmmCapable; /* 0:disable WMM, 1:enable WMM */ + /* UAPSD information: such as enable or disable, do not remove */ + UAPSD_INFO UapsdInfo; + + + /* VLAN related */ + BOOLEAN bVLAN_Tag; + USHORT VLAN_VID; + USHORT VLAN_Priority; + + /* operations */ + INT (*tx_pkt_allowed)(struct _RTMP_ADAPTER *pAd, struct wifi_dev *wdev, PNDIS_PACKET pPacket, UCHAR *pWcid); + INT (*tx_pkt_handle)(struct _RTMP_ADAPTER *pAd, PNDIS_PACKET pPacket); + NDIS_STATUS (*wdev_hard_tx)(struct _RTMP_ADAPTER *pAd, struct _TX_BLK *pTxBlk); + INT (*rx_pkt_allowed)(struct _RTMP_ADAPTER *pAd, struct _RX_BLK *pRxBlk); + INT (*rx_pkt_hdr_chk)(struct _RTMP_ADAPTER *pAd, struct _RX_BLK *pRxBlk); + INT (*rx_ps_handle)(struct _RTMP_ADAPTER *pAd, struct _RX_BLK *pRxBlk); + INT (*rx_pkt_foward)(struct _RTMP_ADAPTER *pAd, struct wifi_dev *wdev, PNDIS_PACKET pPacket); + + /* last received packet's SNR for each antenna */ + UCHAR LastSNR0; + UCHAR LastSNR1; +#ifdef DOT11N_SS3_SUPPORT + UCHAR LastSNR2; + INT32 BF_SNR[3]; /* Last RXWI BF SNR. Units=0.25 dB */ +#endif /* DOT11N_SS3_SUPPORT */ + RSSI_SAMPLE RssiSample; + ULONG NumOfAvgRssiSample; + +#if defined(RT_CFG80211_SUPPORT) || defined(HOSTAPD_SUPPORT) + NDIS_HOSTAPD_STATUS Hostapd; +#endif +#ifdef MT_MAC +#ifdef MAC_REPEATER_SUPPORT + RX_TRACKING_T rx_tracking; +#endif +#endif +#ifdef BAND_STEERING +#ifdef CONFIG_AP_SUPPORT + BOOLEAN bInfReady; +#endif /* CONFIG_AP_SUPPORT */ +#endif /* BAND_STEERING */ +#ifdef MWDS + BOOLEAN bDefaultMwdsStatus; // Determine the configuration status. + BOOLEAN bSupportMWDS; /* Determine If own MWDS capability */ +#endif /* MWDS */ +#ifdef WH_EZ_SETUP + ez_driver_params_t ez_driver_params; +#endif /* WH_EZ_SETUP */ +#ifdef WH_EVENT_NOTIFIER + struct Custom_VIE custom_vie; +#endif /* WH_EVENT_NOTIFIER */ +#ifdef MBO_SUPPORT + MBO_CTRL MboCtrl; +#endif/* MBO_SUPPORT */ +#ifdef CONFIG_OWE_SUPPORT + VIE_CTRL vie_ctrl[VIE_FRM_TYPE_MAX]; +#endif +}; + + +typedef struct _PWR_MGMT_STRUCT_ +{ + USHORT Psm; /* power management mode (PWR_ACTIVE|PWR_SAVE), Please use this value to replace pAd->StaCfg.Psm in the future*/ + BOOLEAN bBeaconLost; + BOOLEAN bTriggerRoaming; + BOOLEAN bEnterPsmNull; + UINT8 ucDtimPeriod; + UINT8 ucBeaconPeriod; + UINT8 ucOwnMacIdx; + BOOLEAN ucWmmPsCertification; +} PWR_MGMT_STRUCT, *PPWR_MGMT_STRUCT; + + + +/*************************************************************************** + * 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]; + +#define WLAN_MR_TIM_BCMC_GET(apidx) \ + (pAd->ApCfg.MBSSID[apidx].TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] & NUM_BIT8[0]) + +/* clear a station PS TIM bit */ +#define WLAN_MR_TIM_BIT_CLEAR(ad_p, apidx, _aid) +/* clear a station PS TIM bit */ +#define WLAN_MR_TIM_BIT_CLEAR1(ad_p, apidx, _aid) \ + { UCHAR tim_offset = _aid >> 3; \ + UCHAR bit_offset = _aid & 0x7; \ + ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] &= (~NUM_BIT8[bit_offset]); } + + +/* set a station PS TIM bit */ +#define WLAN_MR_TIM_BIT_SET(ad_p, apidx, _aid) \ + { UCHAR tim_offset = _aid >> 3; \ + UCHAR bit_offset = _aid & 0x7; \ + ad_p->ApCfg.MBSSID[apidx].TimBitmaps[tim_offset] |= NUM_BIT8[bit_offset]; } + + + +enum BCN_TX_STATE{ + BCN_TX_UNINIT = 0, + BCN_TX_IDLE = 1, + BCN_TX_WRITE_TO_DMA = 2, + BCN_TX_DMA_DONE = 3, + BCN_TX_TXS_DONE = 4, + BCN_TX_STOP = 5 +}; + +typedef struct _BCN_BUF_STRUCT { + BOOLEAN bBcnSntReq; /* used in if beacon send or stop */ + UCHAR BcnBufIdx; + enum BCN_TX_STATE bcn_state; /* Make sure if no packet pending in the Hardware */ +// NDIS_SPIN_LOCK bcn_lock; + + PNDIS_PACKET BeaconPkt; + UCHAR cap_ie_pos; +}BCN_BUF_STRUC; + +#ifdef MT_MAC +typedef struct _TIM_BUF_STRUCT { + BOOLEAN bTimSntReq; /* used in if beacon send or stop */ + UCHAR TimBufIdx; + PNDIS_PACKET TimPkt; +// PNDIS_PACKET TimPkt2; +} TIM_BUF_STRUC; + +INT wdev_tim_buf_init(RTMP_ADAPTER *pAd, TIM_BUF_STRUC *tim_info); +#endif + + +#ifdef CONFIG_AP_SUPPORT +//#ifdef DBG +#ifdef MT_MAC +#define MAX_TIME_RECORD 5 +#endif +//#endif + +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +#ifndef LEN_PSK +#define LEN_PSK 64 +#endif +#endif + +typedef struct _BSS_STRUCT { + struct wifi_dev wdev; + + INT mbss_idx; + +#ifdef HOSTAPD_SUPPORT + NDIS_HOSTAPD_STATUS Hostapd; + BOOLEAN HostapdWPS; +#endif + + CHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; + BOOLEAN bHideSsid; + + USHORT CapabilityInfo; + + UCHAR MaxStaNum; /* Limit the STA connection number per BSS */ + UCHAR StaCount; + UINT16 StationKeepAliveTime; /* unit: second */ + + /* + Security segment + */ + UCHAR RSNIE_Len[2]; + UCHAR RSN_IE[2][MAX_LEN_OF_RSNIE]; + + /* WPA */ + UCHAR WPAKeyString[65]; + UCHAR GMK[32]; +#if defined(WH_EZ_SETUP) || defined(DOT11_SAE_SUPPORT) + UCHAR PSK[LEN_PSK + 1]; /* Add "\0" length */ +#endif + UCHAR PMK[32]; + UCHAR GTK[32]; + UCHAR GNonce[32]; + NDIS_802_11_PRIVACY_FILTER PrivacyFilter; + + /* for Group Rekey, AP ONLY */ + RT_WPA_REKEY WPAREKEY; + ULONG REKEYCOUNTER; + RALINK_TIMER_STRUCT REKEYTimer; + UCHAR REKEYTimerRunning; + UINT8 RekeyCountDown; + + /* For PMK Cache using, AP ONLY */ + ULONG PMKCachePeriod; /* unit : jiffies */ + NDIS_AP_802_11_PMKID PMKIDCache; + +#ifdef DOT1X_SUPPORT + BOOLEAN PreAuth; + + /* For 802.1x daemon setting per BSS */ + UINT8 radius_srv_num; + RADIUS_SRV_INFO radius_srv_info[MAX_RADIUS_SRV_NUM]; + UINT8 NasId[IFNAMSIZ]; + UINT8 NasIdLen; +#endif /* DOT1X_SUPPORT */ + +#ifdef WAPI_SUPPORT + UCHAR WAPIPassPhrase[64]; /* WAPI PSK pass phrase */ + UINT WAPIPassPhraseLen; /* the length of WAPI PSK pass phrase */ + UINT WapiPskType; /* 0 - Hex, 1 - ASCII */ + UCHAR WAPI_BK[16]; /* WAPI base key */ + + UCHAR NMK[LEN_WAPI_NMK]; + UCHAR key_announce_flag[LEN_WAPI_TSC]; + BOOLEAN sw_wpi_encrypt; /* WPI data encrypt by SW */ +#endif /* WAPI_SUPPORT */ + + + /* + Transmitting segment + */ + UCHAR TxRate; /* RATE_1, RATE_2, RATE_5_5, RATE_11, ... */ + UCHAR DesiredRates[MAX_LEN_OF_SUPPORTED_RATES]; /* OID_802_11_DESIRED_RATES */ + UCHAR DesiredRatesIndex; + UCHAR MaxTxRate; /* RATE_1, RATE_2, RATE_5_5, RATE_11 */ + + + /* + Statistics segment + */ + /*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; + + UCHAR BANClass3Data; + ULONG IsolateInterStaTraffic; + + /* outgoing BEACON frame buffer and corresponding TXWI */ + BCN_BUF_STRUC bcn_buf; + UCHAR TimBitmaps[WLAN_MAX_NUM_OF_TIM]; + UCHAR TimIELocationInBeacon; + +#ifdef MT_MAC + TIM_BUF_STRUC tim_buf; + UCHAR TimIELocationInTim; +#endif /* MT_MAC */ + +#ifdef DOT11V_WNM_SUPPORT + UCHAR DMSEntrycount; + UCHAR totalDMScount; +#endif /* DOT11V_WNM_SUPPORT */ + + RT_802_11_ACL AccessControlList; +#ifdef STA_FORCE_ROAM_SUPPORT + RT_802_11_ACL FroamAccessControlList; +#endif +#ifdef ACL_V2_SUPPORT + ACL_V2_CTRL AccessControlList_V2; +#endif /* ACL_V2_SUPPORT */ + /* 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 */ + + + /* +` WPS segment + */ + WSC_LV_INFO WscIEBeacon; + WSC_LV_INFO WscIEProbeResp; +#ifdef WSC_AP_SUPPORT + WSC_CTRL WscControl; + WSC_SECURITY_MODE WscSecurityMode; +#endif /* WSC_AP_SUPPORT */ + +#ifdef IDS_SUPPORT + UINT32 RcvdConflictSsidCount; + UINT32 RcvdSpoofedAssocRespCount; + UINT32 RcvdSpoofedReassocRespCount; + UINT32 RcvdSpoofedProbeRespCount; + UINT32 RcvdSpoofedBeaconCount; + UINT32 RcvdSpoofedDisassocCount; + UINT32 RcvdSpoofedAuthCount; + UINT32 RcvdSpoofedDeauthCount; + UINT32 RcvdSpoofedUnknownMgmtCount; + UINT32 RcvdReplayAttackCount; + + CHAR RssiOfRcvdConflictSsid; + CHAR RssiOfRcvdSpoofedAssocResp; + CHAR RssiOfRcvdSpoofedReassocResp; + CHAR RssiOfRcvdSpoofedProbeResp; + CHAR RssiOfRcvdSpoofedBeacon; + CHAR RssiOfRcvdSpoofedDisassoc; + CHAR RssiOfRcvdSpoofedAuth; + CHAR RssiOfRcvdSpoofedDeauth; + CHAR RssiOfRcvdSpoofedUnknownMgmt; + CHAR RssiOfRcvdReplayAttack; +#endif /* IDS_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT + FT_CFG FtCfg; +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + WNM_CONFIG WnmCfg; +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT + RRM_CONFIG RrmCfg; +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT + PMF_CFG PmfCfg; +#endif /* DOT11W_PMF_SUPPORT */ + + + /* YF@20120417: Avoid connecting to AP in Poor Env, value 0 fOr disable. */ + CHAR AssocReqRssiThreshold; + CHAR RssiLowForStaKickOut; + +#ifdef DOT11U_INTERWORKING + GAS_CTRL GASCtrl; +#endif + +#ifdef CONFIG_HOTSPOT + HOTSPOT_CTRL HotSpotCtrl; +#endif + +#ifdef CONFIG_DOT11V_WNM + WNM_CTRL WNMCtrl; +#endif + +#ifdef SPECIFIC_TX_POWER_SUPPORT + CHAR TxPwrAdj; +#endif /* SPECIFIC_TX_POWER_SUPPORT */ + +//#ifdef DBG +#ifdef MT_MAC + ULONG WriteBcnDoneTime[MAX_TIME_RECORD]; + ULONG BcnDmaDoneTime[MAX_TIME_RECORD]; + UCHAR bcn_not_idle_time; + UINT32 bcn_recovery_num; + ULONG TXS_TSF[MAX_TIME_RECORD]; + ULONG TXS_SN[MAX_TIME_RECORD]; + UCHAR timer_loop; +#endif /* MT_MAC */ +//#endif + + +#ifdef BCN_OFFLOAD_SUPPORT + BOOLEAN updateEventIsTriggered; +#endif /*BCN_OFFLOAD_SUPPORT*/ + +#ifdef DYNAMIC_RX_RATE_ADJ + 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]; + + UCHAR ExpectedSuppRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExpectedSuppRateLen; + UCHAR ExpectedExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExpectedExtRateLen; + UCHAR ExpectedDesireRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExpectedSuppHTMCSSet[16]; + ULONG SuppRateBitmap; + ULONG SuppHTRateBitmap; +#endif /* DYNAMIC_RX_RATE_ADJ */ + + UCHAR ProbeRspTimes; + +#ifdef ROUTING_TAB_SUPPORT + BOOLEAN bRoutingTabInit; + UINT32 RoutingTabFlag; + NDIS_SPIN_LOCK RoutingTabLock; + ROUTING_ENTRY *pRoutingEntryPool; + LIST_HEADER RoutingEntryFreeList; + LIST_HEADER RoutingTab[ROUTING_HASH_TAB_SIZE]; +#endif /* ROUTING_TAB_SUPPORT */ +#ifdef A4_CONN + UCHAR a4_init; + NDIS_SPIN_LOCK a4_entry_lock; + DL_LIST a4_entry_list; +#endif /* A4_CONN */ +#ifdef WAPP_SUPPORT + UCHAR ESPI_AC_BE[3]; + UCHAR ESPI_AC_BK[3]; + UCHAR ESPI_AC_VO[3]; + UCHAR ESPI_AC_VI[3]; +#endif + +} BSS_STRUCT; + +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef WAPP_SUPPORT +struct BSS_LOAD_INFO { + UINT8 current_status; + UINT8 current_load; + UINT8 high_thrd; + UINT8 low_thrd; +}; +#endif /* WAPP_SUPPORT */ + + + +typedef struct _PROTECTION_STRUCT { + + USHORT OperationMode; + UCHAR SetMask; + BOOLEAN bDisableBGProtect; + BOOLEAN bNonGFExist; + +} PROTECTION_STRUCT; + + +/* configuration common to OPMODE_AP as well as OPMODE_STA */ +typedef struct _COMMON_CONFIG { + BOOLEAN bCountryFlag; + UCHAR CountryCode[4]; +#ifdef EXT_BUILD_CHANNEL_LIST + UCHAR Geography; + UCHAR DfsType; + PUCHAR pChDesp; +#endif /* EXT_BUILD_CHANNEL_LIST */ + UCHAR CountryRegion; /* Enum of country region, 0:FCC, 1:IC, 2:ETSI, 3:SPAIN, 4:France, 5:MKK, 6:MKK1, 7:Israel */ + UCHAR CountryRegionForABand; /* Enum of country region for A band */ + UCHAR PhyMode; + UCHAR cfg_wmode; + UCHAR SavedPhyMode; + USHORT Dsifs; /* in units of usec */ + ULONG PacketFilter; /* Packet filter for receiving */ + UINT8 RegulatoryClass[MAX_NUM_OF_REGULATORY_CLASS]; + + CHAR Ssid[MAX_LEN_OF_SSID]; /* NOT NULL-terminated */ + UCHAR SsidLen; /* the actual ssid length in used */ + UCHAR LastSsidLen; /* the actual ssid length in used */ + CHAR LastSsid[MAX_LEN_OF_SSID]; /* NOT NULL-terminated */ + UCHAR LastBssid[MAC_ADDR_LEN]; + + UCHAR Bssid[MAC_ADDR_LEN]; + USHORT BeaconPeriod; + UCHAR Channel; + UCHAR CentralChannel; /* Central Channel when using 40MHz is indicating. not real channel. */ + UCHAR SupRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR SupRateLen; + UCHAR ExtRate[MAX_LEN_OF_SUPPORTED_RATES]; + UCHAR ExtRateLen; + UCHAR DesireRate[MAX_LEN_OF_SUPPORTED_RATES]; /* OID_802_11_DESIRED_RATES */ + UCHAR MaxDesiredRate; + UCHAR ExpectedACKRate[MAX_LEN_OF_SUPPORTED_RATES]; + + ULONG BasicRateBitmap; /* backup basic ratebitmap */ + ULONG BasicRateBitmapOld; /* backup basic ratebitmap */ + + BOOLEAN bInServicePeriod; + + UCHAR EtherTrafficBand; +#if (MT7615_MT7603_COMBO_FORWARDING == 1) + #if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) + UCHAR WfFwdDisabled; + #endif +#endif + + BOOLEAN bAPSDAC_BE; + BOOLEAN bAPSDAC_BK; + BOOLEAN bAPSDAC_VI; + BOOLEAN bAPSDAC_VO; + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + BOOLEAN TDLS_bAPSDAC_BE; + BOOLEAN TDLS_bAPSDAC_BK; + BOOLEAN TDLS_bAPSDAC_VI; + BOOLEAN TDLS_bAPSDAC_VO; + UCHAR TDLS_MaxSPLength; +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + + /* because TSPEC can modify the APSD flag, we need to keep the APSD flag + requested in association stage from the station; + we need to recover the APSD flag after the TSPEC is deleted. */ + BOOLEAN bACMAPSDBackup[4]; /* for delivery-enabled & trigger-enabled both */ + BOOLEAN bACMAPSDTr[4]; /* no use */ + UCHAR MaxSPLength; + + BOOLEAN bNeedSendTriggerFrame; + BOOLEAN bAPSDForcePowerSave; /* Force power save mode, should only use in APSD-STAUT */ + ULONG TriggerTimerCount; + UCHAR BBPCurrentBW; /* BW_10, BW_20, BW_40, BW_80 */ + REG_TRANSMIT_SETTING RegTransmitSetting; /*registry transmit setting. this is for reading registry setting only. not useful. */ + UCHAR TxRate; /* Same value to fill in TXD. TxRate is 6-bit */ + UCHAR MaxTxRate; /* RATE_1, RATE_2, RATE_5_5, RATE_11 */ + UCHAR TxRateIndex; /* Tx rate index in Rate Switch Table */ + UCHAR MinTxRate; /* RATE_1, RATE_2, RATE_5_5, RATE_11 */ + UCHAR RtsRate; /* RATE_xxx */ + HTTRANSMIT_SETTING MlmeTransmit; /* MGMT frame PHY rate setting when operatin at Ht rate. */ + UCHAR MlmeRate; /* RATE_xxx, used to send MLME frames */ + UCHAR BasicMlmeRate; /* Default Rate for sending MLME frames */ + + USHORT RtsThreshold; /* in unit of BYTE */ + USHORT FragmentThreshold; /* in unit of BYTE */ + + UCHAR TxPower; /* in unit of mW */ + ULONG TxPowerPercentage; /* 0~100 % */ + ULONG TxPowerDefault; /* keep for TxPowerPercentage */ + UINT8 PwrConstraint; + +#ifdef DOT11_N_SUPPORT + BACAP_STRUC BACapability; /* NO USE = 0XFF ; IMMED_BA =1 ; DELAY_BA=0 */ + BACAP_STRUC REGBACapability; /* NO USE = 0XFF ; IMMED_BA =1 ; DELAY_BA=0 */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + BOOLEAN force_vht; + UCHAR vht_bw; + UCHAR vht_sgi_80; + UCHAR vht_stbc; + UCHAR vht_bw_signal; + UCHAR vht_cent_ch; + UCHAR vht_cent_ch2; + UCHAR vht_mcs_cap; + UCHAR vht_nss_cap; + USHORT vht_tx_hrate; + USHORT vht_rx_hrate; + BOOLEAN ht20_forbid; + BOOLEAN vht_ldpc; +#endif /* DOT11_VHT_AC */ + + IOT_STRUC IOTestParm; /* 802.11n InterOpbility Test Parameter; */ + ULONG TxPreamble; /* Rt802_11PreambleLong, Rt802_11PreambleShort, Rt802_11PreambleAuto */ + BOOLEAN bUseZeroToDisableFragment; /* Microsoft use 0 as disable */ + ULONG UseBGProtection; /* 0: auto, 1: always use, 2: always not use */ + BOOLEAN bUseShortSlotTime; /* 0: disable, 1 - use short slot (9us) */ + BOOLEAN bEnableTxBurst; /* 1: enble TX PACKET BURST (when BA is established or AP is not a legacy WMM AP), 0: disable TX PACKET BURST */ + BOOLEAN bAggregationCapable; /* 1: enable TX aggregation when the peer supports it */ + BOOLEAN bPiggyBackCapable; /* 1: enable TX piggy-back according MAC's version */ + BOOLEAN bIEEE80211H; /* 1: enable IEEE802.11h spec. */ + UCHAR RDDurRegion; /* Region of radar detection */ + ULONG DisableOLBCDetect; /* 0: enable OLBC detect; 1 disable OLBC detect */ + +#ifdef DOT11_N_SUPPORT + BOOLEAN bRdg; +#endif /* DOT11_N_SUPPORT */ + 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 */ + /* a bitmap of BOOLEAN flags. each bit represent an operation status of a particular */ + /* BOOLEAN control, either ON or OFF. These flags should always be accessed via */ + /* OPSTATUS_TEST_FLAG(), OPSTATUS_SET_FLAG(), OP_STATUS_CLEAR_FLAG() macros. */ + /* see fOP_STATUS_xxx in RTMP_DEF.C for detail bit definition */ + ULONG OpStatusFlags; + + BOOLEAN NdisRadioStateOff; /*For HCT 12.0, set this flag to TRUE instead of called MlmeRadioOff. */ + ABGBAND_STATE BandState; /* For setting BBP used on B/G or A mode. */ + + +#ifdef DFS_SUPPORT + /* IEEE802.11H--DFS. */ + RADAR_DETECT_STRUCT RadarDetect; +#endif /* DFS_SUPPORT */ +#ifdef CARRIER_DETECTION_SUPPORT + CARRIER_DETECTION_STRUCT CarrierDetect; +#endif /* CARRIER_DETECTION_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + /* HT */ + RT_HT_CAPABILITY DesiredHtPhy; + HT_CAPABILITY_IE HtCapability; + ADD_HT_INFO_IE AddHTInfo; /* Useful as AP. */ + /*This IE is used with channel switch announcement element when changing to a new 40MHz. */ + /*This IE is included in channel switch ammouncement frames 7.4.1.5, beacons, probe Rsp. */ + NEW_EXT_CHAN_IE NewExtChanOffset; /*7.3.2.20A, 1 if extension channel is above the control channel, 3 if below, 0 if not present */ + + EXT_CAP_INFO_ELEMENT ExtCapIE; /* this is the extened capibility IE appreed in MGMT frames. Doesn't need to update once set in Init. */ + +#ifdef DOT11N_DRAFT3 + BOOLEAN bBssCoexEnable; + /* + Following two paramters now only used for the initial scan operation. the AP only do + bandwidth fallback when BssCoexApCnt > BssCoexApCntThr + By default, the "BssCoexApCntThr" is set as 0 in "UserCfgInit()". + */ + UCHAR BssCoexApCntThr; + UCHAR BssCoexApCnt; + + UCHAR Bss2040CoexistFlag; /* bit 0: bBssCoexistTimerRunning, bit 1: NeedSyncAddHtInfo. */ + RALINK_TIMER_STRUCT Bss2040CoexistTimer; + UCHAR Bss2040NeedFallBack; /* 1: Need Fall back to 20MHz */ + + /*This IE is used for 20/40 BSS Coexistence. */ + BSS_2040_COEXIST_IE BSS2040CoexistInfo; + + USHORT Dot11OBssScanPassiveDwell; /* Unit : TU. 5~1000 */ + USHORT Dot11OBssScanActiveDwell; /* Unit : TU. 10~1000 */ + USHORT Dot11BssWidthTriggerScanInt; /* Unit : Second */ + USHORT Dot11OBssScanPassiveTotalPerChannel; /* Unit : TU. 200~10000 */ + USHORT Dot11OBssScanActiveTotalPerChannel; /* Unit : TU. 20~10000 */ + USHORT Dot11BssWidthChanTranDelayFactor; + USHORT Dot11OBssScanActivityThre; /* Unit : percentage */ + + ULONG Dot11BssWidthChanTranDelay; /* multiple of (Dot11BssWidthTriggerScanInt * Dot11BssWidthChanTranDelayFactor) */ + ULONG CountDownCtr; /* CountDown Counter from (Dot11BssWidthTriggerScanInt * Dot11BssWidthChanTranDelayFactor) */ + + BSS_2040_COEXIST_IE LastBSSCoexist2040; + BSS_2040_COEXIST_IE BSSCoexist2040; + TRIGGER_EVENT_TAB TriggerEventTab; + UCHAR ChannelListIdx; + + BOOLEAN bOverlapScanning; + BOOLEAN bBssCoexNotify; + UCHAR ori_bw_before_2040_coex; + UCHAR ori_ext_channel_before_2040_coex; +#endif /* DOT11N_DRAFT3 */ + + BOOLEAN bHTProtect; + BOOLEAN bMIMOPSEnable; + BOOLEAN bBADecline; + BOOLEAN bDisableReordering; + BOOLEAN bForty_Mhz_Intolerant; + BOOLEAN bExtChannelSwitchAnnouncement; + BOOLEAN bRcvBSSWidthTriggerEvents; + ULONG LastRcvBSSWidthTriggerEventsTime; + + UCHAR TxBASize; + + BOOLEAN bRalinkBurstMode; + UINT32 RestoreBurstMode; + BOOLEAN ht_ldpc; +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC + UINT32 cfg_vht; + VHT_CAP_INFO vht_info; + VHT_CAP_IE vht_cap_ie; + BOOLEAN bNonVhtDisallow; /* Disallow non-VHT connection */ +#endif /* DOT11_VHT_AC */ + +#ifdef SYSTEM_LOG_SUPPORT + /* Enable wireless event */ + BOOLEAN bWirelessEvent; +#endif /* SYSTEM_LOG_SUPPORT */ + + BOOLEAN bWiFiTest; /* Enable this parameter for WiFi test */ + + /* Tx & Rx Stream number selection */ + UCHAR TxStream; + UCHAR RxStream; + + /* transmit phy mode, trasmit rate for Multicast. */ +#ifdef MCAST_RATE_SPECIFIC + UCHAR McastTransmitMcs; + UCHAR McastTransmitPhyMode; +#endif /* MCAST_RATE_SPECIFIC */ + + BOOLEAN bHardwareRadio; /* Hardware controlled Radio enabled */ + + +#ifdef WSC_INCLUDED + /* WSC hardware push button function 0811 */ + UINT8 WscHdrPshBtnCheckCount; +#endif /* WSC_INCLUDED */ + + + NDIS_SPIN_LOCK MeasureReqTabLock; + PMEASURE_REQ_TAB pMeasureReqTab; + + NDIS_SPIN_LOCK TpcReqTabLock; + PTPC_REQ_TAB pTpcReqTab; + + /* transmit phy mode, trasmit rate for Multicast. */ +#ifdef MCAST_RATE_SPECIFIC + HTTRANSMIT_SETTING MCastPhyMode; +#endif /* MCAST_RATE_SPECIFIC */ + +#ifdef SINGLE_SKU + UINT16 DefineMaxTxPwr; + BOOLEAN bSKUMode; + UINT16 AntGain; + UINT16 BandedgeDelta; + UINT16 ModuleTxpower; +#endif /* SINGLE_SKU */ + +#ifdef SINGLE_SKU_V2 +#endif /* SINGLE_SKU_V2 */ + +#ifdef WAPI_SUPPORT + COMMON_WAPI_INFO comm_wapi_info; + + /* rekey related parameter */ + /* USK update parameter */ + UINT8 wapi_usk_rekey_method; /* 0:disable , 1:time, 2:packet */ + UINT32 wapi_usk_rekey_threshold; /* the rekey threshold */ + + /* MSK update parameter */ + UINT8 wapi_msk_rekey_method; /* 0:disable , 1:time, 2:packet */ + UINT32 wapi_msk_rekey_threshold; /* the rekey threshold */ + + UINT32 wapi_msk_rekey_cnt; + RALINK_TIMER_STRUCT WapiMskRekeyTimer; + UCHAR WapiMskRekeyTimerRunning; +#endif /* WAPI_SUPPORT */ + + + BOOLEAN HT_DisallowTKIP; /* Restrict the encryption type in 11n HT mode */ +#ifdef DOT11K_RRM_SUPPORT + BOOLEAN VoPwrConstraintTest; +#endif /* DOT11K_RRM_SUPPORT */ + + BOOLEAN HT_Disable; /* 1: disable HT function; 0: enable HT function */ + + +#ifdef PRE_ANT_SWITCH + BOOLEAN PreAntSwitch; /* Preamble Antenna Switch */ + SHORT PreAntSwitchRSSI; /* Preamble Antenna Switch RSSI threshold */ + SHORT PreAntSwitchTimeout; /* Preamble Antenna Switch timeout in seconds */ +#endif /* PRE_ANT_SWITCH */ + +#ifdef CFO_TRACK + SHORT CFOTrack; /* CFO Tracking. 0=>use default, 1=>track, 2-7=> track 8-n times, 8=>done tracking */ +#endif /* CFO_TRACK */ + +#ifdef NEW_RATE_ADAPT_SUPPORT + USHORT lowTrafficThrd; /* Threshold for reverting to default MCS when traffic is low */ + SHORT TrainUpRuleRSSI; /* If TrainUpRule=2 then use Hybrid rule when RSSI < TrainUpRuleRSSI */ + USHORT TrainUpLowThrd; /* QuickDRS Hybrid train up low threshold */ + USHORT TrainUpHighThrd; /* QuickDRS Hybrid train up high threshold */ + BOOLEAN TrainUpRule; /* QuickDRS train up criterion: 0=>Throughput, 1=>PER, 2=> Throughput & PER */ +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#ifdef STREAM_MODE_SUPPORT +#define STREAM_MODE_STA_NUM 4 + + UCHAR StreamMode; /* 0=disabled, 1=enable for 1SS, 2=enable for 2SS, 3=enable for 1,2SS */ + UCHAR StreamModeMac[STREAM_MODE_STA_NUM][MAC_ADDR_LEN]; + UINT16 StreamModeMCS; /* Bit map for enabling Stream Mode based on MCS */ +#endif /* STREAM_MODE_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +#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 MICROWAVE_OVEN_SUPPORT + MO_CFG_STRUCT MO_Cfg; /* data structure for mitigating microwave interference */ +#endif /* MICROWAVE_OVEN_SUPPORT */ + + +/* TODO: need to integrate with MICROWAVE_OVEN_SUPPORT */ +#ifdef DYNAMIC_VGA_SUPPORT + LNA_VGA_CTL_STRUCT lna_vga_ctl; +#endif /* DYNAMIC_VGA_SUPPORT */ + + BOOLEAN bStopReadTemperature; /* avoid race condition between FW/driver */ + BOOLEAN bTXRX_RXV_ON; +#ifdef DYNAMIC_WMM + BOOLEAN DynamicWmm; +#endif /* DYNAMIC_WMM */ +#ifdef INTERFERENCE_RA_SUPPORT + UCHAR Interfra; +#endif + BOOLEAN ManualTxop; + ULONG ManualTxopThreshold; + UCHAR ManualTxopUpBound; + UCHAR ManualTxopLowBound; +#ifdef GN_ONLY_AP_SUPPORT + BOOLEAN bExcludeBRate; +#endif + PROTECTION_STRUCT RestoreProtection; +#if defined(BAND_STEERING) || defined(WH_EZ_SETUP) + BOOLEAN dbdc_mode; +#endif + +} 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 CFG_TDLS_SUPPORT +/* CFG TDLS */ +typedef struct _CFG_TDLS_STRUCT +{ + /* 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 */ + BOOLEAN bCfgTDLSCapable; /* 0:disable TDLS, 1:enable TDLS ; using supplicant sm */ + BOOLEAN TdlsChSwitchSupp; + BOOLEAN TdlsPsmSupp; + + UINT8 TdlsLinkCount; + UINT8 TdlsDialogToken; + CFG_TDLS_ENTRY TDLSEntry[MAX_NUM_OF_CFG_TDLS_ENTRY]; +}CFG_TDLS_STRUCT,*PCFG_TDLS_STRUCT; +#endif + + + + + +#ifdef CONFIG_AP_SUPPORT +/*************************************************************************** + * AP related data structures + **************************************************************************/ +/* AUTH-RSP State Machine Aux data structure */ +typedef struct _AP_MLME_AUX { + UCHAR Addr[MAC_ADDR_LEN]; + USHORT Alg; + CHAR Challenge[CIPHER_TEXT_LEN]; +} AP_MLME_AUX, *PAP_MLME_AUX; +#endif /* CONFIG_AP_SUPPORT */ + + + + + +enum { + PS_TOKEN_STAT_IDLE=0, /*00:no ps packets for this sta*/ + PS_TOKEN_STAT_ERR = 1, /*01:not use this case */ + PS_TOKEN_STAT_PKT=2, /*02:wcid not in queue but still ps packtes in packet queue*/ + PS_TOKEN_STAT_WCID_PKT=3, /*03:wcid in queue and still ps packtet in packte queue*/ +}; + +typedef struct _DUPLICATED_FRAME { + INT prev_mgmt_frame_sn; + UCHAR prev_mgmt_src_addr[6]; +}DUPLICATED_FRAME; + +typedef struct _STA_TR_ENTRY{ + UINT32 EntryType; + struct wifi_dev *wdev; + + UCHAR wcid; + /* + func_tb_idx used to indicate following index: + in ApCfg.ApCliTab + in pAd->MeshTab + in WdsTab.MacTab + */ + // TODO:shiang-usw, need to integrate this parameter to wdev_idx or something else!! + UCHAR func_tb_idx; + UCHAR Addr[MAC_ADDR_LEN]; + + /* + Tx Info + */ + USHORT NonQosDataSeq; + USHORT TxSeq[NUM_OF_TID]; + + QUEUE_HEADER tx_queue[WMM_QUE_NUM]; + QUEUE_HEADER ps_queue; + UINT enqCount; + UINT TokenCount[WMM_QUE_NUM]; + +#ifdef DATA_QUEUE_RESERVE + UINT high_pkt_cnt; //high priority pkt cnt + UINT high_pkt_drop_cnt; //high priority pkt drop cnt! +#endif /* DATA_QUEUE_RESERVE */ + +#ifdef MT_PS + BOOLEAN bEospNullSnd; + UCHAR EospNullUp; +#endif /* MT_PS */ + INT ps_qbitmap; + UCHAR ps_state; + ULONG ps_start_time; + UCHAR retrieve_start_state; + UCHAR token_enq_all_fail; + + BOOLEAN tx_pend_for_agg[WMM_QUE_NUM]; + NDIS_SPIN_LOCK txq_lock[WMM_QUE_NUM]; + NDIS_SPIN_LOCK ps_queue_lock; + UINT deq_cnt; + UINT deq_bytes; + ULONG PsQIdleCount; + + BOOLEAN enq_cap; + BOOLEAN deq_cap; + UCHAR PsTokenFlag; + + /* + STA status + */ + + UCHAR bssid[MAC_ADDR_LEN]; + BOOLEAN bIAmBadAtheros; /* Flag if this is Atheros chip that has IOT problem. We need to turn on RTS/CTS protection. */ + BOOLEAN isCached; + UCHAR PortSecured; + UCHAR PsMode; + UCHAR FlgPsModeIsWakeForAWhile; /* wake up for a while until a condition */ + BOOLEAN LockEntryTx; /* TRUE = block to WDS Entry traffic, FALSE = not. */ + + + UCHAR CurrTxRate; + +#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; + UCHAR wifi_hdr_len; + UINT16 Protocol; +#endif /* VENDOR_FEATURE1_SUPPORT */ + +#ifdef DOT11_N_SUPPORT + UINT32 CachedBuf[16]; /* UINT (4 bytes) for alignment */ + + USHORT RXBAbitmap; /* fill to on-chip RXWI_BA_BITMASK in 8.1.3RX attribute entry format */ + USHORT TXBAbitmap; /* This bitmap as originator, only keep in software used to mark AMPDU bit in TXWI */ + USHORT TXAutoBAbitmap; + USHORT BADeclineBitmap; + USHORT BARecWcidArray[NUM_OF_TID]; /* The mapping wcid of recipient session. if RXBAbitmap bit is masked */ + USHORT BAOriWcidArray[NUM_OF_TID]; /* The mapping wcid of originator session. if TXBAbitmap bit is masked */ + USHORT BAOriSequence[NUM_OF_TID]; /* The mapping wcid of originator session. if TXBAbitmap bit is masked */ + + UCHAR MpduDensity; + UCHAR MaxRAmpduFactor; + UCHAR AMsduSize; + UCHAR MmpsMode; /* MIMO power save mode. */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef MAC_REPEATER_SUPPORT + BOOLEAN bReptCli; + BOOLEAN bReptEthCli; + UCHAR MatchReptCliIdx; + UCHAR ReptCliAddr[MAC_ADDR_LEN]; + ULONG ReptCliIdleCount; +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + + +#ifdef VHT_TXBF_SUPPORT + UINT8 snd_dialog_token; +#ifdef SOFT_SOUNDING + BOOLEAN snd_reqired; + HTTRANSMIT_SETTING snd_rate; +#endif /* SOFT_SOUNDING */ +#endif /* VHT_TXBF_SUPPORT */ + + + /* + Statistics related parameters + */ + UINT32 ContinueTxFailCnt; + ULONG TimeStamp_toTxRing; + ULONG NoDataIdleCount; + +#ifdef CONFIG_AP_SUPPORT + LARGE_INTEGER TxPackets; + LARGE_INTEGER RxPackets; + ULONG TxBytes; + ULONG RxBytes; +#endif /* CONFIG_AP_SUPPORT */ + /* + Used to ignore consecutive PS poll. + set: when we get a PS poll. + clear: when a PS data is sent or two period passed. + */ + UINT8 PsDeQWaitCnt; + INT cacheSn[NUM_OF_UP]; +}STA_TR_ENTRY; + + +#ifdef SW_ATF_SUPPORT +typedef struct _PerWCidStatus { + UINT32 wcid; + UINT32 enqCount_us; + UINT32 deqCount_100ms; + UCHAR isBadNode; + UCHAR inTxFlow; +} PerWCidStatus; +typedef struct _PerWcidThr { + UINT32 deqMaxThr; + UINT32 deqMinThr; + UINT32 enqMaxThr; + UINT32 enqMinThr; + UINT32 enqCurrentThr; +} PerWcidThr; +#endif +typedef struct _MAC_TABLE_ENTRY { + UINT32 EntryType; + struct wifi_dev *wdev; + PVOID pAd; + struct _MAC_TABLE_ENTRY *pNext; + UINT32 rxv2_cyc3[10]; + /* + 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; + ULONG cli_cap_flags; + + HTTRANSMIT_SETTING HTPhyMode, MaxHTPhyMode; /* For transmit phy setting in TXWI. */ + HTTRANSMIT_SETTING MinHTPhyMode; + +/* + wcid: + + tr_tb_idx: + + func_tb_idx used to indicate following index: + in ApCfg.ApCliTab + in pAd->MeshTab + in WdsTab.MacTab + + apidx: should remove this +*/ + UCHAR wcid; + UCHAR tr_tb_idx; + UCHAR func_tb_idx; + //UCHAR apidx; /* MBSS number */ + + BOOLEAN isRalink; + BOOLEAN bIAmBadAtheros; /* Flag if this is Atheros chip that has IOT problem. We need to turn on RTS/CTS protection. */ +#ifdef MBO_SUPPORT + BOOLEAN bIndicateNPC; + BOOLEAN bIndicateCDC; + MBO_STA_CH_PREF_CDC_INFO MboStaInfoNPC; + MBO_STA_CH_PREF_CDC_INFO MboStaInfoCDC; +#endif/* MBO_SUPPORT */ +#ifdef ANDLINK_FEATURE_SUPPORT + ULONGLONG upTime; +#endif +#ifdef A4_CONN + UCHAR a4_entry; /* Determine if this entry act which A4 role */ +#endif /* A4_CONN */ +#ifdef MWDS + UCHAR MWDSEntry; /* Determine if this entry act which MWDS role */ + BOOLEAN bSupportMWDS; /* Determine If own MWDS capability */ + /* BOOLEAN bEnableMWDS; Determine If do 3-address to 4-address; no need anymore */ +#endif /* MWDS */ + UCHAR Addr[MAC_ADDR_LEN]; +#ifdef CONFIG_AP_SUPPORT + BSS_STRUCT *pMbss; +#ifdef APCLI_SUPPORT +#ifdef ROAMING_ENHANCE_SUPPORT + BOOLEAN bRoamingRefreshDone; +#endif /* ROAMING_ENHANCE_SUPPORT */ +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + /* + STATE MACHINE Status + */ + USHORT Aid; /* in range 1~2007, with bit 14~15 = b'11, e.g., 0xc001~0xc7d7 */ + SST Sst; + AUTH_STATE AuthState; /* for SHARED KEY authentication state machine used only */ + + + + /* Rx status related parameters */ + RSSI_SAMPLE RssiSample; + UINT32 LastTxRate; + UINT32 LastRxRate; + SHORT freqOffset; /* Last RXWI FOFFSET */ + SHORT freqOffsetValid; /* Set when freqOffset field has been updated */ + + +#ifdef WAPI_SUPPORT + UCHAR usk_id; /* unicast key index for WPI */ +#endif /* WAPI_SUPPORT */ + + /* WPA/WPA2 4-way database */ + UCHAR EnqueueEapolStartTimerRunning; /* Enqueue EAPoL-Start for triggering EAP SM */ + RALINK_TIMER_STRUCT EnqueueStartForPSKTimer; /* A timer which enqueue EAPoL-Start for triggering PSK SM */ + + + /* record which entry revoke MIC Failure , if it leaves the BSS itself, AP won't update aMICFailTime MIB */ + UCHAR CMTimerRunning; +#if defined(CONFIG_OWE_SUPPORT) || defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + UCHAR RSNE_Len[2]; /* used for assoc request/response RSNIE len */ + UCHAR RSNE_Content[2][MAX_LEN_OF_RSNIE]; /* used for assoc request/response RSNIE */ +#endif + 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]; +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) + UCHAR PMK[LEN_PMK]; + UINT8 key_deri_alg; +#endif +#ifdef CONFIG_OWE_SUPPORT + OWE_INFO owe; +#endif + UCHAR ReTryCounter; + BOOLEAN AllowInsPTK; + UCHAR LastGroupKeyId; + UCHAR LastGTK[MAX_LEN_GTK]; + UCHAR LastTK[LEN_TK]; + RALINK_TIMER_STRUCT RetryTimer; + NDIS_802_11_AUTHENTICATION_MODE AuthMode; /* This should match to whatever microsoft defined */ + NDIS_802_11_WEP_STATUS WepStatus; + NDIS_802_11_WEP_STATUS GroupKeyWepStatus; + UINT8 WpaState; + UINT8 GTKState; + NDIS_802_11_PRIVACY_FILTER PrivacyFilter; /* PrivacyFilter enum for 802.1X */ + CIPHER_KEY PairwiseKey; + INT PMKID_CacheIdx; +#if defined(CONFIG_OWE_SUPPORT) || defined(DOT11_SAE_SUPPORT) + UCHAR *pmk_cache; + UCHAR *pmkid; +#endif +#ifdef APCLI_OWE_SUPPORT + BOOLEAN need_process_ecdh_ie; + EXT_ECDH_PARAMETER_IE ecdh_ie; +#endif + + UCHAR PMKID[LEN_PMKID]; + UCHAR NegotiatedAKM[LEN_OUI_SUITE]; /* It indicate the negotiated AKM suite */ + + UCHAR bssid[MAC_ADDR_LEN]; + BOOLEAN IsReassocSta; /* Indicate whether this is a reassociation procedure */ + ULONG NoDataIdleCount; + ULONG AssocDeadLine; + UINT16 StationKeepAliveCount; /* unit: second */ + USHORT CapabilityInfo; + UCHAR PsMode; + UCHAR FlgPsModeIsWakeForAWhile; /* wake up for a while until a condition */ + UCHAR VirtualTimeout; /* peer power save virtual timeout */ + +#ifdef WDS_SUPPORT + BOOLEAN LockEntryTx; /* TRUE = block to WDS Entry traffic, FALSE = not. */ +#endif /* WDS_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +#ifdef MAC_REPEATER_SUPPORT + BOOLEAN bReptCli; + BOOLEAN bReptEthCli; + UCHAR MatchReptCliIdx; + UCHAR ReptCliAddr[MAC_ADDR_LEN]; + ULONG ReptCliIdleCount; +#endif /* MAC_REPEATER_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + UINT32 StaConnectTime; /* the live time of this station since associated with AP */ + UINT32 StaIdleTimeout; /* idle timeout per entry */ + +#ifdef UAPSD_SUPPORT + /* these UAPSD states are used on the fly */ + /* 0:AC_BK, 1:AC_BE, 2:AC_VI, 3:AC_VO */ + BOOLEAN bAPSDCapablePerAC[4]; /* for trigger-enabled */ + BOOLEAN bAPSDDeliverEnabledPerAC[4]; /* for delivery-enabled */ + + + UCHAR MaxSPLength; + + BOOLEAN bAPSDAllAC; /* 1: all AC are delivery-enabled U-APSD */ + + QUEUE_HEADER UAPSDQueue[WMM_NUM_OF_AC]; /* queue for each U-APSD */ + USHORT UAPSDQIdleCount; /* U-APSD queue timeout */ + + PQUEUE_ENTRY pUAPSDEOSPFrame; /* the last U-APSD frame */ + USHORT UAPSDTxNum; /* total U-APSD frame number */ + BOOLEAN bAPSDFlagEOSPOK; /* 1: EOSP frame is tx by ASIC */ + BOOLEAN bAPSDFlagSPStart; /* 1: SP is started */ + + /* need to use unsigned long, because time parameters in OS is defined as + unsigned long */ + unsigned long UAPSDTimeStampLast; /* unit: 1000000/OS_HZ */ + BOOLEAN bAPSDFlagSpRoughUse; /* 1: use rough SP (default: accurate) */ + + /* we will set the flag when PS-poll frame is received and + clear it when statistics handle. + if the flag is set when PS-poll frame is received then calling + statistics handler to clear it. */ + BOOLEAN bAPSDFlagLegacySent; /* 1: Legacy PS sent but yet statistics handle */ + +#endif /* UAPSD_SUPPORT */ + +#ifdef STREAM_MODE_SUPPORT + UINT32 StreamModeMACReg; /* MAC reg used to control stream mode for this client. 0=>No stream mode */ +#endif /* STREAM_MODE_SUPPORT */ + + UINT FIFOCount; + UINT DebugFIFOCount; + UINT DebugTxCount; + +#ifdef DOT11_N_SUPPORT + USHORT NoBADataCountDown; +#endif /* DOT11_N_SUPPORT */ + +/* ==================================================== */ + enum RATE_ADAPT_ALG rateAlg; + // TODO: shiang-usw, use following parameters to replace "RateLen/MaxSupportedRate" + UCHAR RateLen; + UCHAR MaxSupportedRate; + + BOOLEAN bAutoTxRateSwitch; + UCHAR CurrTxRate; + UCHAR CurrTxRateIndex; + UCHAR lastRateIdx; + UCHAR *pTable; /* Pointer to this entry's Tx Rate Table */ + + UCHAR ucMaxTxRetryCnt; + + BOOLEAN fgDisableCCK; +#ifdef NEW_RATE_ADAPT_SUPPORT + UCHAR lowTrafficCount; + UCHAR fewPktsCnt; + BOOLEAN perThrdAdj; + UCHAR mcsGroup;/* the mcs group to be tried */ + UINT8 TrafficLoading; /* Zero Traffic / Low Traffic / High Traffic */ + UINT16 RaHoldTime; /* time to hold current tx rate */ +#endif /* NEW_RATE_ADAPT_SUPPORT */ + +#ifdef AGS_SUPPORT + AGS_CONTROL AGSCtrl; /* AGS control */ +#endif /* AGS_SUPPORT */ + + /* to record the each TX rate's quality. 0 is best, the bigger the worse. */ + UINT8 TxQuality[MAX_TX_RATE_INDEX + 1]; +#if (SWIFT_TRAIN_UP >= 1) + UINT8 SwiftTrainUpRate[SWIFT_TRAIN_UP_RECORD]; + CHAR SwiftTrainUpRSSI[SWIFT_TRAIN_UP_RECORD]; +#endif + 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 */ + BOOLEAN bSwiftTrain; + UINT32 SwiftTrainThrd; + UCHAR PER[MAX_TX_RATE_INDEX + 1]; + UINT32 CurrTxRateStableTime; /* # of second in current TX rate */ + UCHAR TxRateUpPenalty; /* extra # of second penalty due to last unstable condition */ + + UCHAR SupportRateMode; /* 1: CCK 2:OFDM 4: HT, 8:VHT */ + BOOLEAN SupportCCKMCS[MAX_LEN_OF_CCK_RATES]; + BOOLEAN SupportOFDMMCS[MAX_LEN_OF_OFDM_RATES]; +#ifdef DOT11_N_SUPPORT + BOOLEAN SupportHTMCS[MAX_LEN_OF_HT_RATES]; +#ifdef DOT11_VHT_AC + BOOLEAN SupportVHTMCS[MAX_LEN_OF_VHT_RATES]; +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef PEER_DELBA_TX_ADAPT + BOOLEAN bPeerDelBaTxAdaptEn; +#endif /* PEER_DELBA_TX_ADAPT */ + +#ifdef MFB_SUPPORT + UCHAR lastLegalMfb; /* last legal mfb which is used to set rate */ + BOOLEAN isMfbChanged; /* purpose: true when mfb has changed but the new mfb is not adopted for Tx */ + struct _RTMP_RA_LEGACY_TB *LegalMfbRS; + BOOLEAN fLastChangeAccordingMfb; + NDIS_SPIN_LOCK fLastChangeAccordingMfbLock; +/* Tx MRQ */ + BOOLEAN toTxMrq; + UCHAR msiToTx, mrqCnt; /*mrqCnt is used to count down the inverted-BF mrq to be sent */ +/* Rx mfb */ + UCHAR pendingMfsi; +/* Tx MFB */ + BOOLEAN toTxMfb; + UCHAR mfbToTx; + UCHAR mfb0, mfb1; +#endif /* MFB_SUPPORT */ + +#ifdef VHT_TXBF_SUPPORT + UINT8 snd_dialog_token; +#ifdef SOFT_SOUNDING + BOOLEAN snd_reqired; + HTTRANSMIT_SETTING snd_rate; +#endif /* SOFT_SOUNDING */ +#endif /* VHT_TXBF_SUPPORT */ + + UINT32 OneSecTxNoRetryOkCount; + UINT32 OneSecTxRetryOkCount; + UINT32 OneSecTxFailCount; + UINT32 OneSecRxLGICount; /* unicast-to-me Long GI count */ + UINT32 OneSecRxSGICount; /* unicast-to-me Short GI count */ + +#ifdef FIFO_EXT_SUPPORT + UINT32 fifoTxSucCnt; + UINT32 fifoTxRtyCnt; +#endif /* FIFO_EXT_SUPPORT */ + + UINT32 ContinueTxFailCnt; + UINT32 TxSucCnt; + ULONG TimeStamp_toTxRing; + +/*==================================================== */ + EXT_CAP_INFO_ELEMENT ext_cap; + +#ifdef DOT11_N_SUPPORT + HT_CAPABILITY_IE HTCapability; + + USHORT RXBAbitmap; /* fill to on-chip RXWI_BA_BITMASK in 8.1.3RX attribute entry format */ + USHORT TXBAbitmap; /* This bitmap as originator, only keep in software used to mark AMPDU bit in TXWI */ + USHORT TXAutoBAbitmap; + USHORT BADeclineBitmap; + USHORT BARecWcidArray[NUM_OF_TID]; /* The mapping wcid of recipient session. if RXBAbitmap bit is masked */ + USHORT BAOriWcidArray[NUM_OF_TID]; /* The mapping wcid of originator session. if TXBAbitmap bit is masked */ + USHORT BAOriSequence[NUM_OF_TID]; /* The mapping wcid of originator session. if TXBAbitmap bit is masked */ + + UCHAR MpduDensity; + UCHAR MaxRAmpduFactor; + UCHAR AMsduSize; + UCHAR MmpsMode; /* MIMO power save mode. */ + +#ifdef DOT11N_DRAFT3 + UCHAR BSS2040CoexistenceMgmtSupport; + BOOLEAN bForty_Mhz_Intolerant; +#endif /* DOT11N_DRAFT3 */ + +#ifdef DOT11_VHT_AC + VHT_CAP_IE vht_cap_ie; + + /* only take effect if ext_cap.operating_mode_notification = 1 */ + BOOLEAN force_op_mode; + OPERATING_MODE operating_mode; +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + +#ifdef CONFIG_DOT11V_WNM + UCHAR BssTransitionManmtSupport; +#endif /* CONFIG_DOT11V_WNM */ + + +#ifdef DOT11V_WNM_SUPPORT + UCHAR BssTransitionManmtSupport; + UCHAR DMSSupport; + BOOLEAN Beclone; +#endif /* DOT11V_WNM_SUPPORT */ + + BOOLEAN bWscCapable; + UCHAR Receive_EapolStart_EapRspId; + + UINT32 TXMCSExpected[MAX_MCS_SET]; + UINT32 TXMCSSuccessful[MAX_MCS_SET]; + UINT32 TXMCSFailed[MAX_MCS_SET]; + UINT32 TXMCSAutoFallBack[MAX_MCS_SET][MAX_MCS_SET]; + + +#ifdef WAPI_SUPPORT + BOOLEAN WapiUskRekeyTimerRunning; + RALINK_TIMER_STRUCT WapiUskRekeyTimer; + UINT32 wapi_usk_rekey_cnt; +#endif /* WAPI_SUPPORT */ + + +#ifdef DOT11R_FT_SUPPORT + FT_MDIE_INFO MdIeInfo; + FT_FTIE_INFO FtIeInfo; + + UINT8 InitialMDIE[5]; + UINT8 InitialFTIE[256]; + UINT InitialFTIE_Len; + + UCHAR FT_PMK_R0[32]; + UCHAR FT_PMK_R0_NAME[16]; + UCHAR FT_PMK_R1[32]; + UCHAR FT_PMK_R1_NAME[16]; + UCHAR PTK_NAME[16]; + + UCHAR FT_UCipher[4]; + UCHAR FT_Akm[4]; + UCHAR FT_R1kh_CacheMiss_Times; +#ifdef R1KH_HARD_RETRY + UCHAR FT_R1kh_CacheMiss_Hard; + RTMP_OS_COMPLETION ack_r1kh; +#endif/* R1KH_HARD_RETRY */ +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT + RRM_EN_CAP_IE RrmEnCap; +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef DOT11W_PMF_SUPPORT + UCHAR PmfTxTsc[LEN_WPA_TSC]; + UCHAR PmfRxTsc[LEN_WPA_TSC]; + RALINK_TIMER_STRUCT SAQueryTimer; + RALINK_TIMER_STRUCT SAQueryConfirmTimer; + UCHAR SAQueryStatus; + USHORT TransactionID; +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT +#ifdef CONFIG_AP_SUPPORT + BOOLEAN bBSSMantSTASupport; + BOOLEAN bDMSSTASupport; + UCHAR BTMQueryDialogToken; + BOOLEAN DisassociationImminent; + BOOLEAN BSSTerminationIncluded; + RALINK_TIMER_STRUCT DisassocTimer; +#endif /* CONFIG_AP_SUPPORT */ +#endif /* DOT11V_WNM_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT + LARGE_INTEGER TxPackets; + LARGE_INTEGER RxPackets; + ULONG TxBytes; + ULONG RxBytes; + ULONG OneSecTxBytes; + ULONG OneSecRxBytes; + ULONG AvgTxBytes; + ULONG AvgRxBytes; +#endif /* CONFIG_AP_SUPPORT */ + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + UINT16 TdlsTxFailCount; + UINT32 TdlsKeyLifeTimeCount; + UCHAR MatchTdlsEntryIdx; // indicate the index in pAd->StaCfg.DLSEntry +#endif // DOT11Z_TDLS_SUPPORT // + + + ULONG ChannelQuality; /* 0..100, Channel Quality Indication for Roaming */ +#ifdef CONFIG_HOTSPOT_R2 + UCHAR IsWNMReqValid; + UCHAR QosMapSupport; + UCHAR DscpExceptionCount; + USHORT DscpRange[8]; + USHORT DscpException[21]; + struct wnm_req_data *ReqData; + struct _sta_hs_info hs_info; + UCHAR OSEN_IE_Len; + UCHAR OSEN_IE[MAX_LEN_OF_RSNIE]; +#endif /* CONFIG_HOTSPOT_R2 */ +#if defined(CONFIG_HOTSPOT_R2) || defined(CONFIG_DOT11V_WNM) + UCHAR IsBTMReqValid; + UCHAR IsKeep; + UINT16 BTMDisassocCount; +#ifndef DOT11V_WNM_SUPPORT + BOOLEAN bBSSMantSTASupport; +#endif + struct btm_req_data *ReqbtmData; +#endif +#ifdef MT_PS + UCHAR i_psm; /* 0: disable, 1: enable */ +#endif /* MT_PS */ + +#ifdef MT_MAC +#ifdef WSC_INCLUDED + BOOLEAN bEapReqIdRetryTimerRunning; + RALINK_TIMER_STRUCT EapReqIdRetryTimer; /* Sometimes EapReqId cannot sendout successfully after associate completed, we need to re-send again. */ +#endif /* WSC_INCLUDED */ +#endif /* MT_MAC */ +#ifdef AIR_MONITOR + UCHAR mnt_idx; +#endif /* AIR_MONITOR */ +#ifdef WH_EZ_SETUP + unsigned char easy_setup_enabled; + unsigned char easy_setup_mic_valid; +#ifdef EZ_DUAL_BAND_SUPPORT + unsigned char link_duplicate;//! seen in AP context, it means that both CLIs of other repeater are connected to me, on respective bands +#endif + unsigned char is_apcli; /* TRUE - Peer is APCLI, FALSE - Peer is normal station. */ +#endif /* WH_EZ_SETUP */ +#ifdef WH_EVENT_NOTIFIER + UCHAR custom_ie_len; /* Length of Vendor Information Element */ + UCHAR custom_ie[CUSTOM_IE_TOTAL_LEN]; /* Vendor Information Element */ + StaActivityItem tx_state; /* Station's tx state record */ + StaActivityItem rx_state; /* Station's rx state record */ +#endif /* WH_EVENT_NOTIFIER */ + +#ifdef STA_FORCE_ROAM_SUPPORT + BOOLEAN low_rssi_notified; + UCHAR tick_sec; + unsigned char is_peer_entry_apcli; /*This will be used for Force Roam to detect the CLI and Third Party STA*/ +#endif + UINT32 AuthAssocNotInProgressFlag; +#ifdef FAST_DETECT_STA_OFF + BOOLEAN detect_deauth; + COUNTER_CON ConCounters; +#endif + UINT64 CCMP_BC_PN[SHARE_KEY_NUM]; + BOOLEAN Init_CCMP_BC_PN_Passed[SHARE_KEY_NUM]; + BOOLEAN AllowUpdateRSC; +#ifdef WIFI_DIAG + ULONG diag_tx_count; /* total tx count since STA associated, include success and failed */ + ULONG diag_tx_succ_count; /* total tx success count since STA associated */ +#endif +#ifdef SW_ATF_SUPPORT + PerWCidStatus atfPara; + PerWcidThr atfThr; +#endif +} MAC_TABLE_ENTRY, *PMAC_TABLE_ENTRY; + + +typedef enum _MAC_ENT_STATUS_{ + /* fAnyStationInPsm */ + MAC_TB_ANY_PSM = 0x1, + /* + fAnyStationBadAtheros + Check if any Station is atheros 802.11n Chip. We need to use RTS/CTS with Atheros 802,.11n chip. + */ + MAC_TB_ANY_ATH = 0x2, + /* + fAnyTxOPForceDisable + Check if it is necessary to disable BE TxOP + */ + MAC_TB_FORCE_TxOP = 0x4, + /* + fAllStationAsRalink + Check if all stations are ralink-chipset + */ + MAC_TB_ALL_RALINK = 0x8, + /* + fAnyStationIsLegacy + Check if I use legacy rate to transmit to my BSS Station + */ + MAC_TB_ANY_LEGACY = 0x10, + /* + fAnyStationNonGF + Check if any Station can't support GF + */ + MAC_TB_ANY_NON_GF = 0x20, + /* fAnyStation20Only */ + MAC_TB_ANY_HT20 = 0x40, + /* + fAnyStationMIMOPSDynamic + Check if any Station is MIMO Dynamic + */ + MAC_TB_ANY_MIMO_DYNAMIC = 0x80, + /* + fAnyBASession + Check if there is BA session. Force turn on RTS/CTS + */ + MAC_TB_ANY_BA = 0x100, + /* fAnyStaFortyIntolerant */ + MAC_TB_ANY_40_INTOlERANT = 0x200, + /* + fAllStationGainGoodMCS + Check if all stations more than MCS threshold + */ + MAC_TB_ALL_GOOD_MCS = 0x400, + /* + fAnyStationIsHT + Check if still has any station set the Intolerant bit on! + */ + MAC_TB_ANY_HT = 0x800, + /* fAnyWapiStation */ + MAC_TB_ANY_WAPI = 0x1000, +}MAC_ENT_STATUS; + +typedef struct _MAC_TABLE { + MAC_TABLE_ENTRY *Hash[HASH_TABLE_SIZE]; + MAC_TABLE_ENTRY Content[MAX_LEN_OF_MAC_TABLE]; + STA_TR_ENTRY tr_entry[MAX_LEN_OF_TR_TABLE]; + UINT16 Size; + QUEUE_HEADER McastPsQueue; + ULONG PsQIdleCount; + MAC_ENT_STATUS sta_status; + + 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 */ + +#ifdef WAPI_SUPPORT + BOOLEAN fAnyWapiStation; +#endif /* WAPI_SUPPORT */ + + USHORT MsduLifeTime; /* life time for PS packet */ +} MAC_TABLE, *PMAC_TABLE; +#ifdef CONFIG_SNIFFER_SUPPORT +#define MONITOR_MODE_OFF 0 +#define MONITOR_MODE_REGULAR_RX 1 +#define MONITOR_MODE_FULL 2 + + +typedef struct _MONITOR_STRUCT +{ + struct wifi_dev monitor_wdev; + INT current_monitor_mode; + BOOLEAN monitor_initiated; +}MONITOR_STRUCT; +#endif /*CONFIG_SNIFFER_SUPPORT*/ + +#ifndef APCLI_DISCONNECT_SUB_REASON_MNT_NO_BEACON +#define APCLI_DISCONNECT_SUB_REASON_MNT_NO_BEACON 5 +#endif + +#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 RxErrorCount; + ULONG TxErrors; + LARGE_INTEGER MulticastReceivedFrameCount; + ULONG RxNoBuffer; +} WDS_COUNTER, *PWDS_COUNTER; + +typedef struct _WDS_ENTRY { + BOOLEAN Valid; + UCHAR Addr[MAC_ADDR_LEN]; + ULONG NoDataIdleCount; + struct _WDS_ENTRY *pNext; +} WDS_ENTRY, *PWDS_ENTRY; + +typedef struct _WDS_TABLE_ENTRY { + USHORT Size; + UCHAR WdsAddr[MAC_ADDR_LEN]; + WDS_ENTRY *Hash[HASH_TABLE_SIZE]; + WDS_ENTRY Content[MAX_LEN_OF_MAC_TABLE]; + UCHAR MaxSupportedRate; + UCHAR CurrTxRate; + USHORT TxQuality[MAX_LEN_OF_SUPPORTED_RATES]; + USHORT OneSecTxOkCount; + USHORT OneSecTxRetryOkCount; + USHORT OneSecTxFailCount; + ULONG CurrTxRateStableTime; /* # of second in current TX rate */ + UCHAR TxRateUpPenalty; /* extra # of second penalty due to last unstable condition */ +} WDS_TABLE_ENTRY, *PWDS_TABLE_ENTRY; + + +typedef struct _RT_802_11_WDS_ENTRY { + struct wifi_dev wdev; + UCHAR Valid; + UCHAR PeerWdsAddr[MAC_ADDR_LEN]; + UCHAR MacTabMatchWCID; /* ASIC */ + UCHAR KeyIdx; + CIPHER_KEY WdsKey; + + WDS_COUNTER WdsCounter; +} RT_802_11_WDS_ENTRY, *PRT_802_11_WDS_ENTRY; + +typedef struct _WDS_TABLE { + UCHAR Mode; + UINT Size; + RT_802_11_WDS_ENTRY WdsEntry[MAX_WDS_ENTRY]; +} WDS_TABLE, *PWDS_TABLE; +#endif /* WDS_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT +/* +* ------------------------NOTE!!!!-------------------------- +* This structure must keep sync with partner driver. +* if new member will be added, it's better to append to end. +* ---------------------------------------------------------- +*/ +typedef struct _REPEATER_CLIENT_ENTRY { + //BOOLEAN bValid; + BOOLEAN CliEnable; + BOOLEAN CliValid; + BOOLEAN bEthCli; + UCHAR MatchApCliIdx; + UCHAR MatchLinkIdx; + UCHAR MacTabWCID; + UCHAR CliConnectState; /* 0: disconnect 1: connecting 2: connected */ + + ULONG CtrlCurrState; + ULONG SyncCurrState; + ULONG AuthCurrState; + ULONG AssocCurrState; + + RALINK_TIMER_STRUCT ApCliAssocTimer, ApCliAuthTimer; + + USHORT AuthReqCnt; + USHORT AssocReqCnt; + ULONG CliTriggerTime; + + /* For WPA countermeasures */ + ULONG LastMicErrorTime; /* record last MIC error time */ + BOOLEAN bBlockAssoc; /* Block associate attempt for 60 seconds after counter measure occurred. */ + + UCHAR OriginalAddress[MAC_ADDR_LEN]; + UCHAR CurrentAddress[MAC_ADDR_LEN]; + PVOID pAd; + struct _REPEATER_CLIENT_ENTRY *pNext; + struct wifi_dev *wdev;/*pointer to the linking Apcli interface wdev. */ + +#ifdef WH_EZ_SETUP + ULONG Disconnect_Sub_Reason; +#endif + +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + BSSID_INFO SavedPMK[PMKID_NO]; + UINT SavedPMKNum; /* Saved PMKID number */ +#endif +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + NDIS_SPIN_LOCK SavedPMK_lock; +#endif +#ifdef APCLI_SAE_SUPPORT + UCHAR sae_cfg_group; +#endif +#ifdef APCLI_OWE_SUPPORT + UCHAR curr_owe_group; +#endif + +} 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 */ +typedef struct _REPEATER_ADAPTER_DATA_TABLE { + bool Enabled; + void *EntryLock; + void **CliHash; + void **MapHash; + void *Wdev_ifAddr; +} REPEATER_ADAPTER_DATA_TABLE; + + +#ifdef MULTI_APCLI_SUPPORT +typedef struct _TIMER_INFO { + PVOID pAd; + USHORT Ifindex; +} TIMER_INFO, *PTIMER_INFO; +#endif /* MULTI_APCLI_SUPPORT */ + +/*************************************************************************** + * AP APCLI related data structures + **************************************************************************/ +typedef struct _APCLI_STRUCT { + struct wifi_dev wdev; + + BOOLEAN Enable; /* Set it as 1 if the apcli interface was configured to "1" or by iwpriv cmd "ApCliEnable" */ + BOOLEAN Valid; /* Set it as 1 if the apcli interface associated success to remote AP. */ + + MLME_AUX MlmeAux; /* temporary settings used during MLME state machine */ + + UCHAR MacTabWCID; /*WCID value, which point to the entry of ASIC Mac table. */ + UCHAR SsidLen; + CHAR Ssid[MAX_LEN_OF_SSID]; + + UCHAR CfgSsidLen; + CHAR CfgSsid[MAX_LEN_OF_SSID]; +#ifdef WH_EZ_SETUP + UCHAR CfgHideSsidLen; + CHAR CfgHideSsid[MAX_LEN_OF_SSID]; +#endif + UCHAR CfgApCliBssid[MAC_ADDR_LEN]; + + ULONG ApCliRcvBeaconTime; +#ifdef WH_EZ_SETUP + ULONG ApCliLastRcvBeaconTime; +#endif + ULONG ApCliLinkUpTime; + USHORT ApCliBeaconPeriod; + + ULONG CtrlCurrState; + ULONG SyncCurrState; + ULONG AuthCurrState; + ULONG AssocCurrState; + ULONG WpaPskCurrState; + +#ifdef APCLI_AUTO_CONNECT_SUPPORT + USHORT ProbeReqCnt; + BOOLEAN AutoConnectFlag; +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ + USHORT AuthReqCnt; + USHORT AssocReqCnt; + + UCHAR MpduDensity; + BOOLEAN OpenWEPErrPktChk; /* See if Open WEP check enabled */ + ULONG OpenWEPErrPktCnt; /* Error Unicast Packet Count */ + ULONG OpenWEPErrMCPktCnt; /* Error Multicast Packet Count */ + + + /* + Security segment + */ + /* Add to support different cipher suite for WPA2/WPA mode */ + NDIS_802_11_ENCRYPTION_STATUS GroupCipher; /* Multicast cipher suite */ + NDIS_802_11_ENCRYPTION_STATUS PairCipher; /* Unicast cipher suite */ +#ifdef CONFIG_OWE_SUPPORT + UINT32 IntegrityGroupCipher; /*security improvement*/ +#endif + 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 GTK[32]; /* GTK from authenticator */ + + /*CIPHER_KEY PairwiseKey; */ + CIPHER_KEY SharedKey[SHARE_KEY_NUM]; + + /* store RSN_IE built by driver */ + UCHAR RSN_IE[MAX_LEN_OF_RSNIE]; /* The content saved here should be convert to little-endian format. */ + UCHAR RSNIE_Len; + + /* For WPA countermeasures */ + ULONG LastMicErrorTime; /* record last MIC error time */ + BOOLEAN bBlockAssoc; /* Block associate attempt for 60 seconds after counter measure occurred. */ + + /* For WPA-PSK supplicant state */ + UCHAR SNonce[32]; /* SNonce for WPA-PSK */ + UCHAR GNonce[32]; /* GNonce for WPA-PSK from authenticator */ + +#ifdef APCLI_DOT11W_PMF_SUPPORT +#ifdef DOT11W_PMF_SUPPORT + PMF_CFG PmfCfg; +#endif /* DOT11W_PMF_SUPPORT */ +#endif /* APCLI_DOT11W_PMF_SUPPORT */ + +#if defined(WPA_SUPPLICANT_SUPPORT) || defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + BSSID_INFO SavedPMK[PMKID_NO]; + UINT SavedPMKNum; /* Saved PMKID number */ +#endif +#if defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) + MAC_TABLE_ENTRY pre_mac_entry; + NDIS_SPIN_LOCK SavedPMK_lock; +#endif +#ifdef APCLI_SAE_SUPPORT + UCHAR sae_cfg_group; +#endif +#ifdef APCLI_OWE_SUPPORT + UCHAR curr_owe_group; + UCHAR owe_trans_ssid_len; + CHAR owe_trans_ssid[MAX_LEN_OF_SSID]; + CHAR owe_trans_bssid[MAC_ADDR_LEN]; + UCHAR owe_trans_open_ssid_len; + CHAR owe_trans_open_ssid[MAX_LEN_OF_SSID]; + CHAR owe_trans_open_bssid[MAC_ADDR_LEN]; +#endif + + /* + WPS segment + */ +#ifdef WSC_AP_SUPPORT + WSC_CTRL WscControl; +#endif /* WSC_AP_SUPPORT */ + + /* + Transmitting segment + */ + UCHAR RxMcsSet[16]; + + + PSPOLL_FRAME PsPollFrame; + HEADER_802_11 NullFrame; + +#ifdef MULTI_APCLI_SUPPORT + TIMER_INFO TimerInfo; +#endif /* MULTI_APCLI_SUPPORT */ + +#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 */ +#ifdef WH_EZ_SETUP + UCHAR avoid_loop; + UCHAR stop_auto_connect; + ULONG Disconnect_Sub_Reason; +#endif + RTMP_OS_COMPLETION ifdown_complete; + RTMP_OS_COMPLETION linkdown_complete; +#ifdef MWDS + BOOLEAN bSupportMWDS; /* Determine If own MWDS capability */ + /* BOOLEAN bEnableMWDS; Determine If do 3-address to 4-address; not need anymore*/ +#endif /* MWDS */ + BOOLEAN ApCliCertTest; +#ifdef A4_CONN + UCHAR a4_init; + UCHAR a4_apcli; +#endif +} APCLI_STRUCT, *PAPCLI_STRUCT; + + +typedef struct _AP_ADMIN_CONFIG { + USHORT CapabilityInfo; + /* Multiple SSID */ + UCHAR BssidNum; + UCHAR MacMask; + BSS_STRUCT MBSSID[HW_BEACON_MAX_NUM]; + ULONG IsolateInterStaTrafficBTNBSSID; +#if defined(CONFIG_SNIFFER_SUPPORT) || defined(MIXMODE_SUPPORT) + UCHAR BssType; /* Infra mode or monitor mode */ +#endif /*CONFIG_SNIFFER_SUPPORT*/ + +#ifdef APCLI_SUPPORT + UCHAR ApCliInfRunned; /* Number of ApClient interface which was running. value from 0 to MAX_APCLI_INTERFACE */ + UINT8 ApCliNum; + BOOLEAN FlgApCliIsUapsdInfoUpdated; + APCLI_STRUCT ApCliTab[MAX_APCLI_NUM]; /*AP-client */ +#ifdef APCLI_AUTO_CONNECT_SUPPORT + BOOLEAN ApCliAutoConnectRunning; + BOOLEAN ApCliAutoConnectChannelSwitching; +#endif /* APCLI_AUTO_CONNECT_SUPPORT */ +#ifdef ROAMING_ENHANCE_SUPPORT + BOOLEAN bRoamingEnhance; +#endif /* ROAMING_ENHANCE_SUPPORT */ +#endif /* APCLI_SUPPORT */ + struct wifi_dev *ScanReqwdev; +#ifdef MAC_REPEATER_SUPPORT + NDIS_SPIN_LOCK ReptCliEntryLock; + REPEATER_CLIENT_ENTRY *ReptCliHash[HASH_TABLE_SIZE]; + REPEATER_CLIENT_ENTRY_MAP *ReptMapHash[HASH_TABLE_SIZE]; + RT_802_11_MACLIST ReptMacList; + UCHAR BridgeAddress[MAC_ADDR_LEN]; + REPEATER_CTRL_STRUCT ReptControl; +#endif /* MAC_REPEATER_SUPPORT */ +#ifdef AP_PARTIAL_SCAN_SUPPORT + BOOLEAN bPartialScanEnable; + BOOLEAN bPartialScanning; +#define DEFLAUT_PARTIAL_SCAN_CH_NUM 1 /* Must be move to other place */ + UINT8 PartialScanChannelNum; /* How many channels to scan each time */ + UINT8 LastPartialScanChannel; +#define DEFLAUT_PARTIAL_SCAN_BREAK_TIME 4 /* Period of partial scaning: unit: 100ms *//* Must be move to other place */ + UINT8 PartialScanBreakTime; /* Period of partial scaning: unit: 100ms */ +#endif /* AP_PARTIAL_SCAN_SUPPORT */ + + /* 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 */ +#ifdef ACS_CTCC_SUPPORT + BOOLEAN AutoChannelScoreFlag; /* score for Channel, and don't switch channel */ +#endif + ChannelSel_Alg AutoChannelAlg; /* Alg for selecting Channel */ +#ifdef AP_SCAN_SUPPORT + UINT32 ACSCheckTime; /* Periodic timer to trigger Auto Channel Selection (unit: second) */ + UINT32 ACSCheckCount; /* if ACSCheckCount > ACSCheckTime, then do ACS check */ +#endif /* AP_SCAN_SUPPORT */ + BOOLEAN bAvoidDfsChannel; /* 0: disable, 1: enable */ + BOOLEAN 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[MAX_NUM_OF_CHANNELS + 1]; + 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 */ + +#ifdef DOT1X_SUPPORT + /* dot1x related parameter */ + UINT32 own_ip_addr; + UINT32 retry_interval; + UINT32 session_timeout_interval; + UINT32 quiet_interval; + UCHAR EAPifname[HW_BEACON_MAX_NUM][IFNAMSIZ]; /* indicate as the binding interface for EAP negotiation. */ + UCHAR EAPifname_len[HW_BEACON_MAX_NUM]; + UCHAR PreAuthifname[HW_BEACON_MAX_NUM][IFNAMSIZ]; /* indicate as the binding interface for WPA2 Pre-authentication. */ + UCHAR PreAuthifname_len[HW_BEACON_MAX_NUM]; +#endif /* DOT1X_SUPPORT */ + + /* EDCA parameters to be announced to its local BSS */ + EDCA_PARM BssEdcaParm; + + RALINK_TIMER_STRUCT ApQuickResponeForRateUpTimer; + BOOLEAN ApQuickResponeForRateUpTimerRunning; + +#ifdef IDS_SUPPORT + /* intrusion detection parameter */ + BOOLEAN IdsEnable; + UINT32 AuthFloodThreshold; /* Authentication frame flood threshold */ + UINT32 AssocReqFloodThreshold; /* Association request frame flood threshold */ + UINT32 ReassocReqFloodThreshold; /* Re-association request frame flood threshold */ + UINT32 ProbeReqFloodThreshold; /* Probe request frame flood threshold */ + UINT32 DisassocFloodThreshold; /* Disassociation frame flood threshold */ + UINT32 DeauthFloodThreshold; /* Deauthentication frame flood threshold */ + UINT32 EapReqFloodThreshold; /* EAP request frame flood threshold */ + UINT32 DataFloodThreshold; /* Malicious data frame flood threshold */ + + UINT32 RcvdAuthCount; + UINT32 RcvdAssocReqCount; + UINT32 RcvdReassocReqCount; + UINT32 RcvdProbeReqCount; + UINT32 RcvdDisassocCount; + UINT32 RcvdDeauthCount; + UINT32 RcvdEapReqCount; + UINT32 RcvdMaliciousDataCount; /* Data Frame DDOS */ + + RALINK_TIMER_STRUCT IDSTimer; + BOOLEAN IDSTimerRunning; +#endif /* IDS_SUPPORT */ + + /* Indicate the maximum idle timeout */ + UINT32 StaIdleTimeout; + + ULONG EntryLifeCheck; + +#ifdef IGMP_SNOOP_SUPPORT + BOOLEAN IgmpSnoopEnable; /* 0: disable, 1: enable. */ +#endif /* IGMP_SNOOP_SUPPORT */ + +#ifdef PREVENT_ARP_SPOOFING + BOOLEAN ARPSpoofChk; /* 0: disable, 1: enable. */ +#endif /* PREVENT_ARP_SPOOFING */ + +#ifdef DOT11R_FT_SUPPORT + FT_TAB FtTab; +#endif /* DOT11R_FT_SUPPORT */ + +#ifdef CLIENT_WDS + NDIS_SPIN_LOCK CliWdsTabLock; + PCLIWDS_PROXY_ENTRY pCliWdsEntryPool; + LIST_HEADER CliWdsEntryFreeList; + LIST_HEADER CliWdsProxyTb[CLIWDS_HASH_TAB_SIZE]; +#endif /* CLIENT_WDS */ + +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT + UCHAR GreenAPLevel; + BOOLEAN bGreenAPEnable; + BOOLEAN bGreenAPActive; +#endif /* GREENAP_SUPPORT */ + +#endif /* DOT11_N_SUPPORT */ + + UCHAR EntryClientCount; + + +#ifdef MAC_REPEATER_SUPPORT + BOOLEAN bBaSnResetDis; + BOOLEAN bMACRepeaterEn; + UCHAR MACRepeaterOuiMode; + UINT8 EthApCliIdx; + UCHAR RepeaterCliSize; +#endif /* MAC_REPEATER_SUPPORT */ +#ifdef CONFIG_SNIFFER_SUPPORT + UCHAR bMonitorON; + USHORT OriginalType; +#endif /* CONFIG_SNIFFER_SUPPORT */ + +#ifdef SNIFFER_MIB_CMD + SNIFFER_MIB_CTRL sniffer_mib_ctrl; +#endif /* SNIFFER_MIB_CMD */ +#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; + UINT8 BndStrgBssIdx[HW_BEACON_MAX_NUM]; + UINT32 BndStrgOneSecChBusyTime; + BND_STRG_CLI_TABLE BndStrgTable[DBDC_BAND_NUM]; + UINT32 BndStrgHeartbeatCount; + UINT32 BndStrgHeartbeatMonitor; + UINT32 BndStrgHeartbeatNoChange; +#endif /* BAND_STEERING */ +#ifdef WH_EVENT_NOTIFIER + struct EventNotifierCfg EventNotifyCfg; +#endif /* WH_EVENT_NOTIFIER */ +#ifdef DOT11K_RRM_SUPPORT + BOOLEAN HandleNRReqbyUplayer; +#endif +} AP_ADMIN_CONFIG; + +#ifdef IGMP_SNOOP_SUPPORT +typedef enum _IGMP_GROUP_TYPE { + MODE_IS_INCLUDE = 1, + MODE_IS_EXCLUDE, + CHANGE_TO_INCLUDE_MODE, + CHANGE_TO_EXCLUDE_MODE, + ALLOW_NEW_SOURCES, + BLOCK_OLD_SOURCES +} IgmpGroupType; + +typedef enum _MULTICAST_FILTER_ENTRY_TYPE { + MCAT_FILTER_STATIC = 0, + MCAT_FILTER_DYNAMIC, +} MulticastFilterEntryType; + +typedef struct _MEMBER_ENTRY { + struct _MEMBER_ENTRY *pNext; + UCHAR Addr[MAC_ADDR_LEN]; +/* USHORT Aid; */ +} MEMBER_ENTRY, *PMEMBER_ENTRY; + +typedef struct _MULTICAST_FILTER_TABLE_ENTRY { + BOOLEAN Valid; + MulticastFilterEntryType type; /* 0: static, 1: dynamic. */ + UINT lastTime; + PNET_DEV net_dev; + UCHAR Addr[MAC_ADDR_LEN]; + LIST_HEADER MemberList; + struct _MULTICAST_FILTER_TABLE_ENTRY *pNext; +} MULTICAST_FILTER_TABLE_ENTRY, *PMULTICAST_FILTER_TABLE_ENTRY; + +typedef struct _MULTICAST_FILTER_TABLE { + UCHAR Size; + PMULTICAST_FILTER_TABLE_ENTRY + Hash[MAX_LEN_OF_MULTICAST_FILTER_HASH_TABLE]; + MULTICAST_FILTER_TABLE_ENTRY Content[MAX_LEN_OF_MULTICAST_FILTER_TABLE]; + NDIS_SPIN_LOCK MulticastFilterTabLock; + NDIS_SPIN_LOCK FreeMemberPoolTabLock; + MEMBER_ENTRY freeMemberPool[FREE_MEMBER_POOL_SIZE]; + LIST_HEADER freeEntryList; +} MULTICAST_FILTER_TABLE, *PMULTICAST_FILTER_TABLE; +#endif /* IGMP_SNOOP_SUPPORT */ + +#ifdef DOT11V_WNM_SUPPORT + +typedef struct _DMSID_TABLE { + struct _DMSID_TABLE *pNext; + UCHAR DMSIDs; + UINT32 DMSID_DestIP; +} DMSID_TABLE, PDMSID_TABLE; +typedef struct _DMS_ENTRY { + struct _DMS_ENTRY *pNext; + LIST_HEADER DMSIDList; + PMAC_TABLE_ENTRY pEntry; + UCHAR apidx; +} DMS_ENTRY, *PDMS_ENTRY; + + +#endif /* DOT11V_WNM_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT +typedef enum _RT_GREEN_AP_LEVEL { + GREENAP_11BGN_STAS = 0, + GREENAP_ONLY_11BG_STAS, + GREENAP_WITHOUT_ANY_STAS_CONNECT +} RT_GREEN_AP_LEVEL; +#endif /* DOT11_N_SUPPORT */ +#endif /* GREENAP_SUPPORT */ + +/* ----------- end of AP ---------------------------- */ +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef BLOCK_NET_IF +typedef struct _BLOCK_QUEUE_ENTRY { + BOOLEAN SwTxQueueBlockFlag; + LIST_HEADER NetIfList; +} BLOCK_QUEUE_ENTRY, *PBLOCK_QUEUE_ENTRY; +#endif /* BLOCK_NET_IF */ + + + +struct wificonf { + BOOLEAN bShortGI; + BOOLEAN bGreenField; +}; + +typedef struct _RTMP_DEV_INFO_ { + UCHAR chipName[16]; + RTMP_INF_TYPE infType; +} RTMP_DEV_INFO; + +#ifdef DBG_DIAGNOSE +#define MAX_VHT_MCS_SET 20 /* for 1ss~ 2ss with MCS0~9 */ + +#define DIAGNOSE_TIME 10 /* 10 sec */ + +struct dbg_diag_info{ + USHORT TxDataCnt[WMM_NUM_OF_AC]; /* Tx total data count */ + USHORT TxFailCnt; + USHORT RxDataCnt; /* Rx Total Data count. */ + USHORT RxCrcErrCnt; + +#ifdef DBG_TXQ_DEPTH + /* TxSwQ length in scale of 0, 1, 2, 3, 4, 5, 6, 7, >=8 */ + USHORT TxSWQueCnt[WMM_NUM_OF_AC][9]; + UINT32 enq_fall_cnt[WMM_NUM_OF_AC]; + UINT32 deq_fail_no_resource_cnt[WMM_NUM_OF_AC]; + UINT32 deq_called; + UINT32 deq_round; + UINT32 deq_cnt[9]; +#endif /* DBG_TXQ_DEPTH */ + +#ifdef DBG_TX_RING_DEPTH + /* TxDesc queue length in scale of 0~14, >=15 */ + USHORT TxDescCnt[WMM_NUM_OF_AC][24]; +#endif /* DBG_TX_RING_DEPTH */ + +#ifdef MT_MAC +#ifdef DBG_PSE_DEPTH + /* PSE Page buffer depth */ + USHORT pse_pg_cnt[50]; +#endif /* DBG_PSE_DEPTH */ +#endif /* MT_MAC */ + +#ifdef DBG_TX_AGG_CNT + USHORT TxAggCnt; + USHORT TxNonAggCnt; + /* TxDMA APMDU Aggregation count in range from 0 to 15, in setp of 1. */ + USHORT TxAMPDUCnt[16]; +#endif /* DBG_TX_AGG_CNT */ + +#ifdef DBG_TX_MCS + /* TxDate MCS Count in range from 0 to 15, step in 1 */ + USHORT TxMcsCnt_HT[MAX_MCS_SET]; +#ifdef DOT11_VHT_AC + UINT TxMcsCnt_VHT[MAX_VHT_MCS_SET]; +#endif /* DOT11_VHT_AC */ +#endif /* DBG_TX_MCS */ + +#ifdef DBG_RX_MCS + /* Rx HT MCS Count in range from 0 to 15, step in 1 */ + USHORT RxMcsCnt_HT[MAX_MCS_SET]; +#ifdef DOT11_VHT_AC + /* for VHT80MHz only, not calcuate 20/40 MHz packets */ + UINT RxMcsCnt_VHT[MAX_VHT_MCS_SET]; +#endif /* DOT11_VHT_AC */ +#endif /* DBG_RX_MCS */ +}; + +typedef enum{ + DIAG_COND_ALL = 0, + DIAG_COND_PSE_DEPTH = 1, + DIAG_COND_TX_RING_DEPTH = 2, + DIAG_COND_TXQ_DEPTH = 4, +} DIAG_COND_STATUS; + +typedef struct _RtmpDiagStrcut_ { /* Diagnosis Related element */ + BOOLEAN inited; + UCHAR wcid; + UCHAR qIdx; + UCHAR ArrayStartIdx; + UCHAR ArrayCurIdx; + UINT32 diag_cond; + + struct dbg_diag_info diag_info[DIAGNOSE_TIME]; +} RtmpDiagStruct; +#endif /* DBG_DIAGNOSE */ + +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) +/* + The number of channels for per-channel Tx power offset +*/ +#define NUM_OF_CH_FOR_PER_CH_TX_PWR_OFFSET 14 + +/* The Tx power control using the internal ALC */ +#define LOOKUP_TB_SIZE 33 + +typedef struct _TX_POWER_CONTROL { + BOOLEAN bInternalTxALC; /* Internal Tx ALC */ + BOOLEAN bExtendedTssiMode; /* The extended TSSI mode (each channel has different Tx power if needed) */ + CHAR PerChTxPwrOffset[NUM_OF_CH_FOR_PER_CH_TX_PWR_OFFSET + 1]; /* Per-channel Tx power offset */ + CHAR idxTxPowerTable; /* The index of the Tx power table for ant0 */ + CHAR idxTxPowerTable2; /* The index of the Tx power table for ant1 */ + CHAR RF_TX_ALC; /* 3390: RF R12[4:0]: Tx0 ALC, 3352: RF R47[4:0]: Tx0 ALC, 5390: RF R49[5:0]: Tx0 ALC */ + CHAR MAC_PowerDelta; /* Tx power control over MAC 0x1314~0x1324 */ + CHAR MAC_PowerDelta2; /* Tx power control for Tx1 */ + CHAR TotalDeltaPower2; /* Tx power control for Tx1 */ +#ifdef RTMP_TEMPERATURE_COMPENSATION + INT LookupTable[IEEE80211_BAND_NUMS][LOOKUP_TB_SIZE]; + INT RefTemp[IEEE80211_BAND_NUMS]; + UCHAR TssiGain[IEEE80211_BAND_NUMS]; + /* Index offset, -7....25. */ + INT LookupTableIndex; +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + +} TX_POWER_CONTROL, *PTX_POWER_CONTROL; +#endif /* RTMP_INTERNAL_TX_ALC || RTMP_TEMPERATURE_COMPENSATION */ + +/* */ +/* The entry of transmit power control over MAC */ +/* */ +typedef struct _TX_POWER_CONTROL_OVER_MAC_ENTRY { + USHORT MACRegisterOffset; /* MAC register offset */ + ULONG RegisterValue; /* Register value */ +} TX_POWER_CONTROL_OVER_MAC_ENTRY, *PTX_POWER_CONTROL_OVER_MAC_ENTRY; + +/* */ +/* The maximum registers of transmit power control */ +/* */ +#define MAX_TX_PWR_CONTROL_OVER_MAC_REGISTERS 5 + + + + +/* */ +/* The configuration of the transmit power control over MAC */ +/* */ +typedef struct _CONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC { + UCHAR NumOfEntries; /* Number of entries */ + TX_POWER_CONTROL_OVER_MAC_ENTRY TxPwrCtrlOverMAC[MAX_TX_PWR_CONTROL_OVER_MAC_REGISTERS]; +} CONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC, *PCONFIGURATION_OF_TX_POWER_CONTROL_OVER_MAC; + +/* */ +/* The extension of the transmit power control over MAC */ +/* */ +typedef struct _TX_POWER_CONTROL_EXT_OVER_MAC { + struct { + ULONG TxPwrCfg0; /* MAC 0x1314 */ + ULONG TxPwrCfg0Ext; /* MAC 0x1390 */ + ULONG TxPwrCfg1; /* MAC 0x1318 */ + ULONG TxPwrCfg1Ext; /* MAC 0x1394 */ + ULONG TxPwrCfg2; /* MAC 0x131C */ + ULONG TxPwrCfg2Ext; /* MAC 0x1398 */ + ULONG TxPwrCfg3; /* MAC 0x1320 */ + ULONG TxPwrCfg3Ext; /* MAC 0x139C */ + ULONG TxPwrCfg4; /* MAC 0x1324 */ + ULONG TxPwrCfg4Ext; /* MAC 0x13A0 */ + ULONG TxPwrCfg5; /* MAC 0x1384 */ + ULONG TxPwrCfg6; /* MAC 0x1388 */ + ULONG TxPwrCfg7; /* MAC 0x13D4 */ + ULONG TxPwrCfg8; /* MAC 0x13D8 */ + ULONG TxPwrCfg9; /* MAC 0x13DC */ + } BW20Over2Dot4G; + + struct { + ULONG TxPwrCfg0; /* MAC 0x1314 */ + ULONG TxPwrCfg0Ext; /* MAC 0x1390 */ + ULONG TxPwrCfg1; /* MAC 0x1318 */ + ULONG TxPwrCfg1Ext; /* MAC 0x1394 */ + ULONG TxPwrCfg2; /* MAC 0x131C */ + ULONG TxPwrCfg2Ext; /* MAC 0x1398 */ + ULONG TxPwrCfg3; /* MAC 0x1320 */ + ULONG TxPwrCfg3Ext; /* MAC 0x139C */ + ULONG TxPwrCfg4; /* MAC 0x1324 */ + ULONG TxPwrCfg4Ext; /* MAC 0x13A0 */ + ULONG TxPwrCfg5; /* MAC 0x1384 */ + ULONG TxPwrCfg6; /* MAC 0x1388 */ + ULONG TxPwrCfg7; /* MAC 0x13D4 */ + ULONG TxPwrCfg8; /* MAC 0x13D8 */ + ULONG TxPwrCfg9; /* MAC 0x13DC */ + } BW40Over2Dot4G; + + struct { + ULONG TxPwrCfg0; /* MAC 0x1314 */ + ULONG TxPwrCfg0Ext; /* MAC 0x1390 */ + ULONG TxPwrCfg1; /* MAC 0x1318 */ + ULONG TxPwrCfg1Ext; /* MAC 0x1394 */ + ULONG TxPwrCfg2; /* MAC 0x131C */ + ULONG TxPwrCfg2Ext; /* MAC 0x1398 */ + ULONG TxPwrCfg3; /* MAC 0x1320 */ + ULONG TxPwrCfg3Ext; /* MAC 0x139C */ + ULONG TxPwrCfg4; /* MAC 0x1324 */ + ULONG TxPwrCfg4Ext; /* MAC 0x13A0 */ + ULONG TxPwrCfg5; /* MAC 0x1384 */ + ULONG TxPwrCfg6; /* MAC 0x1388 */ + ULONG TxPwrCfg7; /* MAC 0x13D4 */ + ULONG TxPwrCfg8; /* MAC 0x13D8 */ + ULONG TxPwrCfg9; /* MAC 0x13DC */ + } BW20Over5G; + + struct { + ULONG TxPwrCfg0; /* MAC 0x1314 */ + ULONG TxPwrCfg0Ext; /* MAC 0x1390 */ + ULONG TxPwrCfg1; /* MAC 0x1318 */ + ULONG TxPwrCfg1Ext; /* MAC 0x1394 */ + ULONG TxPwrCfg2; /* MAC 0x131C */ + ULONG TxPwrCfg2Ext; /* MAC 0x1398 */ + ULONG TxPwrCfg3; /* MAC 0x1320 */ + ULONG TxPwrCfg3Ext; /* MAC 0x139C */ + ULONG TxPwrCfg4; /* MAC 0x1324 */ + ULONG TxPwrCfg4Ext; /* MAC 0x13A0 */ + ULONG TxPwrCfg5; /* MAC 0x1384 */ + ULONG TxPwrCfg6; /* MAC 0x1388 */ + ULONG TxPwrCfg7; /* MAC 0x13D4 */ + ULONG TxPwrCfg8; /* MAC 0x13D8 */ + ULONG TxPwrCfg9; /* MAC 0x13DC */ + } BW40Over5G; +} TX_POWER_CONTROL_EXT_OVER_MAC, *PTX_POWER_CONTROL_EXT_OVER_MAC; + +/* For Wake on Wireless LAN */ +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) || defined(MT_WOW_SUPPORT) +typedef struct _WOW_CFG_STRUCT { + BOOLEAN bEnable; /* Enable WOW function*/ + BOOLEAN bWOWFirmware; /* Enable WOW function, trigger to reload WOW-support firmware */ + BOOLEAN bInBand; /* use in-band signal to wakeup system */ + UINT8 nSelectedGPIO; /* Side band signal to wake up system */ + UINT8 nDelay; /* Delay number is multiple of 3 secs, and it used to postpone the WOW function */ + UINT32 nHoldTime; /* GPIO pulse hold time, unit: 1us, 0 means hold forever.*/ + BOOLEAN bWoWRunning; /* WOW function is working */ + UINT8 nWakeupInterface; /* PCI:0 USB:1 GPIO:2 */ + UINT8 bGPIOHighLow; /* 0: low to high, 1: high to low */ +} WOW_CFG_STRUCT, *PWOW_CFG_STRUCT; + +typedef enum { + WOW_GPIO_LOW_TO_HIGH, + WOW_GPIO_HIGH_TO_LOW +} WOW_GPIO_HIGH_LOW_T; + +typedef enum { + WOW_PKT_TO_HOST, + WOW_PKT_TO_ANDES +} WOW_PKT_FLOW_T; + +typedef enum { + WOW_WAKEUP_BY_PCIE, + WOW_WAKEUP_BY_USB, + WOW_WAKEUP_BY_GPIO +} WOW_WAKEUP_METHOD_T; + +typedef enum { + WOW_ENABLE = 1, + WOW_TRAFFIC = 3, + WOW_WAKEUP = 4 +} WOW_FEATURE_T; + +typedef enum { + WOW_MASK_CFG = 1, + WOW_SEC_CFG, + WOW_INFRA_CFG, + WOW_P2P_CFG, +} WOW_CONFIG_T; + +enum { + WOW_MAGIC_PKT, + WOW_BITMAP, + WOW_IPV4_TCP_SYNC, + WOW_IPV6_TCP_SYNC +}; + +typedef struct NEW_WOW_MASK_CFG_STRUCT { + UINT32 Config_Type; + UINT32 Function_Enable; + UINT32 Detect_Mask; + UINT32 Event_Mask; +} NEW_WOW_MASK_CFG_STRUCT, PNEW_WOW_MASK_CFG_STRUCT; + +typedef struct NEW_WOW_SEC_CFG_STRUCT { + UINT32 Config_Type; + UINT32 WPA_Ver; + UCHAR PTK[64]; + UCHAR R_COUNTER[8]; + UCHAR Key_Id; + UCHAR Cipher_Alg; + UCHAR WCID; + UCHAR Group_Cipher; +} NEW_WOW_SEC_CFG_STRUCT, PNEW_WOW_SEC_CFG_STRUCT; + +typedef struct NEW_WOW_INFRA_CFG_STRUCT { + UINT32 Config_Type; + UCHAR STA_MAC[6]; + UCHAR AP_MAC[6]; + UINT32 AP_Status; +} NEW_WOW_INFRA_CFG_STRUCT, PNEW_WOW_INFRA_CFG_STRUCT; + +typedef struct _NEW_WOW_P2P_CFG_STRUCT { + UINT32 Config_Type; + UCHAR GO_MAC[6]; + UCHAR CLI_MAC[6]; + UINT32 P2P_Status; +} NEW_WOW_P2P_CFG_STRUCT, *PNEW_WOW_P2P_CFG_STRUCT; + +typedef struct _NEW_WOW_PARAM_STRUCT { + UINT32 Parameter; + UINT32 Value; +} NEW_WOW_PARAM_STRUCT, *PNEW_WOW_PARAM_STRUCT; +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) || defined(MT_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 49 + REG_PAIR BBPRegDB[BBP_RECORD_NUM]; + BOOLEAN AsicCheckEn; +} BBP_RESET_CTL, *PBBP_RESET_CTL; + +typedef struct _PARTIAL_SCAN_ { + BOOLEAN bScanning; /* Doing partial scan or not */ + UINT8 NumOfChannels; /* How many channels to scan each time */ + UINT8 LastScanChannel; /* last scanned channel */ + UINT32 BreakTime; /* Period of partial scanning: unit: 100ms */ + struct wifi_dev *pwdev; +#ifdef WH_EZ_SETUP + BOOLEAN bPartialScanAllowed; +#endif + BOOLEAN bPeriodicPartialScan; + UINT32 TriggerPeriod; + UINT32 TriggerCount; +} PARTIAL_SCAN; + + +#ifdef WAPP_SUPPORT +struct scan_req { + INT32 scan_id; + INT32 last_bss_cnt; + INT32 if_index; +}; +#endif + +typedef struct _SCAN_CTRL_{ + UCHAR ScanType; + UCHAR BssType; + UCHAR Channel; + UCHAR SsidLen; + CHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR Bssid[MAC_ADDR_LEN]; + +#ifdef CONFIG_AP_SUPPORT + RALINK_TIMER_STRUCT APScanTimer; +#endif /* CONFIG_AP_SUPPORT */ + PARTIAL_SCAN PartialScan; +}SCAN_CTRL; + + +#ifdef MULTI_CLIENT_SUPPORT +#define TX_SWQ_FIFO_LEN 1024 /*4096*/ +#else +#define TX_SWQ_FIFO_LEN 512 +#endif +#if defined(MAX_CONTINUOUS_TX_CNT) || defined(NEW_IXIA_METHOD) +#undef TX_SWQ_FIFO_LEN +#define TX_SWQ_FIFO_LEN 4096 +#define CONTINUOUS_TX_CNT 24/* Add Max continuous Tx count*/ +#define AP_MAX_SWQIDX 0xffff +#endif +typedef struct tx_swq_fifo{ + UCHAR swq[TX_SWQ_FIFO_LEN]; // value 0 is used to indicate free to insert, value 1~127 used to incidate the WCID entry + UINT enqIdx; + UINT deqIdx; + NDIS_SPIN_LOCK swq_lock; /* spinlock for swq */ +}TX_SWQ_FIFO; + + + +typedef struct rtmp_mac_ctrl { +#ifdef MT_MAC + UINT8 wtbl_entry_cnt[4]; + UINT8 wtbl_entry_size[4]; + UINT32 wtbl_base_addr[4]; // base address for WTBL2/3/4 + UINT32 wtbl_base_fid[4]; + UINT32 page_size; +#endif /* MT_MAC */ +}RTMP_MAC_CTRL; + +typedef struct rtmp_phy_ctrl{ + UINT8 rf_band_cap; + +#ifdef CONFIG_AP_SUPPORT +#ifdef AP_QLOAD_SUPPORT + UINT8 FlgQloadEnable; /* 1: any BSS WMM is enabled */ + ULONG QloadUpTimeLast; /* last up time */ + UINT8 QloadChanUtil; /* last QBSS Load, unit: us */ + 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->phy_ctrl.FlgQloadAlarmIsSuspended == TRUE) +#define QLOAD_ALARM_EVER_OCCUR(pAd) (pAd->phy_ctrl.QloadAlarmNumber > 0) + BOOLEAN FlgQloadAlarmIsSuspended; /* 1: suspend */ + + UINT8 QloadAlarmBusyTimeThreshold; /* unit: 1/100 */ + UINT8 QloadAlarmBusyNumThreshold; /* unit: 1 */ + UINT8 QloadAlarmBusyNum; + UINT8 QloadAlarmDuration; /* unit: TBTT */ + + UINT32 QloadAlarmNumber; /* total alarm times */ + BOOLEAN FlgQloadAlarm; /* 1: alarm occurs */ + + /* speed up use */ + UINT32 QloadTimePeriodLast; + UINT32 QloadBusyTimeThreshold; +#else + +#define QLOAD_DOES_ALARM_OCCUR(pAd) 0 +#endif /* QLOAD_FUNC_BUSY_TIME_ALARM */ + +#endif /* AP_QLOAD_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ +}RTMP_PHY_CTRL; +#ifdef NEW_IXIA_METHOD +typedef enum DROP_REASON { + PKT_SUCCESS = 0, + INVALID_PKT_LEN = 1, + INVALID_TR_WCID = 2, + INVALID_TR_ENTRY = 3, + INVALID_WDEV = 4, + INVALID_ETH_TYPE = 5, + DROP_PORT_SECURE = 6, + DROP_PSQ_FULL = 7, + DROP_TXQ_FULL = 8, + DROP_TX_JAM = 9, + DROP_TXQ_ENQ_FAIL = 10, + DROP_TXQ_ENQ_PS = 11, + DROP_HW_RESET = 12, + DROP_80211H_MODE = 13, + DROP_BLK_INFO_ERROR = 14, + MAX_TDROP_RESON +} T_DROP_RESON; +typedef enum _R_DROP_REASON_ { + RPKT_SUCCESS = 0, + ALREADY_IN_ORDER = 1, + DUP_SEQ_PKT = 2, + DROP_OLD_PKT = 3, + DROP_NO_BUF = 4, + DROP_DUP_FRAME = 5, + DROP_NOT_ALLOW = 6, + DROP_RING_FULL = 7, + DROP_DATA_SIZE = 8, + DROP_INFO_NULL = 9, + DROP_RXD_ERROR = 10, + MAX_RDROP_RESON +} R_DROP_RESON; + +typedef struct WIFI_TR_COUNT { + int txfl[2]; + int tx[MAX_TDROP_RESON]; + int rx[MAX_RDROP_RESON]; +} WTRC, *pWTRC; +#endif + +#ifdef RTMP_SDIO_SUPPORT +/* Tc Resource index */ +typedef enum _ENUM_TRAFFIC_CLASS_INDEX_T { + /*First HW queue*/ + TC0_INDEX = 0, /* HIF TX: AC0 packets */ + TC1_INDEX, /* HIF TX: AC1 packets */ + TC2_INDEX, /* HIF TX: AC2 packets */ + TC3_INDEX, /* HIF TX: AC3 packets */ + TC4_INDEX, /* HIF TX: CPU packets */ + TC5_INDEX, /* HIF TX: AC4 packets */ + /* Second HW queue */ + TC6_INDEX, /* HIF TX: AC10 packets */ + TC7_INDEX, /* HIF TX: AC11 packets */ + TC8_INDEX, /* HIF TX: AC12 packets */ + TC9_INDEX, /* HIF TX: AC13 packets */ + TC10_INDEX, /* HIF TX: AC14 packets */ + TC_NUM /* Maximum number of Traffic Classes. */ +} ENUM_TRAFFIC_CLASS_INDEX_T; + +typedef struct _TX_TCQ_STATUS_T { + UINT16 au2TxDonePageCount[TC_NUM]; + UINT16 u2AvailiablePageCount; + UINT8 ucNextTcIdx; + UINT16 au2FreePageCount[TC_NUM]; + UINT16 au2MaxNumOfPage[TC_NUM]; + UINT16 au2FreeBufferCount[TC_NUM]; + UINT16 au2MaxNumOfBuffer[TC_NUM]; +} TX_TCQ_STATUS_T, *P_TX_TCQ_STATUS_T; + + +typedef struct _TX_CTRL_T { + UINT32 u4PageSize; + UINT32 u4TotalPageNum; + UINT32 u4TotalTxRsvPageNum; +/* Elements below is classified according to TC (Traffic Class) value. */ + TX_TCQ_STATUS_T rTc; + PUINT8 pucTxCoalescingBufPtr; +} TX_CTRL_T, *P_TX_CTRL_T; +#endif + +#ifdef SMART_CARRIER_SENSE_SUPPORT +typedef struct _SMART_CARRIER_SENSE_CTRL{ + BOOLEAN SCSEnable; /* 0:Disable, 1:Enable */ + UINT8 SCSStatus; /* 0: Normal, 1:Low_gain */ + CHAR SCSMinRssi; + UINT32 CR_AGC_0_default; + UINT32 CR_AGC_3_default; + UINT8 EDCCA_Status; + UINT32 PdCount; + UINT32 MdrdyCount; + UINT32 FalseCCA; + CHAR CurrSensitivity; + CHAR AdjustSensitivity; + UINT32 RtsCount; + UINT32 RtsRtyCount; + CHAR RSSIBoundary; + UINT8 SCSMinRssiTolerance; + UINT32 SCSTrafficThreshold; + UINT16 FalseCcaUpBond; + UINT16 FalseCcaLowBond; + CHAR FixedRssiBond; + BOOLEAN ForceMode; /*This mode only consider False CCA not care RTS PER.*/ + +}SMART_CARRIER_SENSE_CTRL; +#endif /* SMART_CARRIER_SENSE_SUPPORT */ + +#ifdef SW_ATF_SUPPORT +typedef struct _AtfPara { + UINT32 lastTimerCnt; + UINT32 dropDelta; + UINT32 currentTimerCnt; + UINT flagOnce; + UINT32 txWcidNum; + UINT flagATF; + UINT32 deq_goodNodeMaxThr; + UINT32 deq_goodNodeMinThr; + UINT32 deq_badNodeMinThr; + UINT32 enq_badNodeMaxThr; + UINT32 enq_badNodeMinThr; + UINT32 enq_badNodeCurrent; + UINT32 wcidTxThr; + UINT32 atfFalseCCAThr; +} AtfPara, *pAtfPara; +#endif +#define NON_CE_REGION_MAX_ED_TH 63 +/* + The miniport adapter structure +*/ +struct _RTMP_ADAPTER { + VOID *OS_Cookie; /* save specific structure relative to OS */ + PNET_DEV net_dev; +#ifdef RTMP_MAC_PCI +/*****************************************************************************************/ +/* PCI related parameters */ +/*****************************************************************************************/ + PUCHAR CSRBaseAddress; /* PCI MMIO Base Address, all access will use */ + unsigned int irq_num; + +#ifdef PCI_MSI_SUPPORT + BOOLEAN HaveMsi; +#endif /* PCI_MSI_SUPPORT */ +#ifdef SW_ATF_SUPPORT + AtfPara AtfParaSet; +#endif + USHORT RLnkCtrlConfiguration; + USHORT RLnkCtrlOffset; + USHORT HostLnkCtrlConfiguration; + USHORT HostLnkCtrlOffset; + USHORT PCIePowerSaveLevel; + USHORT DeviceID; /* Read from PCI config */ + ULONG AccessBBPFailCount; + BOOLEAN bPCIclkOff; /* flag that indicate if the PICE power status in Configuration SPace.. */ + BOOLEAN bPCIclkOffDisableTx; + + BOOLEAN brt30xxBanMcuCmd; /* when = 0xff means all commands are ok to set . */ + BOOLEAN b3090ESpecialChip; /* 3090E special chip that write EEPROM 0x24=0x9280. */ + /* ULONG CheckDmaBusyCount; // Check Interrupt Status Register Count. */ + + UINT32 int_enable_reg; + UINT32 int_disable_mask; + UINT32 int_pending; + + RTMP_DMABUF TxBufSpace[NUM_OF_TX_RING]; /* Shared memory of all 1st pre-allocated TxBuf associated with each TXD */ + RTMP_DMABUF RxDescRing[2]; /* Shared memory for RX descriptors */ + RTMP_DMABUF TxDescRing[NUM_OF_TX_RING]; /* Shared memory for Tx descriptors */ + + RTMP_RX_RING RxRing[NUM_OF_RX_RING]; + NDIS_SPIN_LOCK RxRingLock[NUM_OF_RX_RING]; /* Rx Ring spinlock */ + NDIS_SPIN_LOCK LockInterrupt; + NDIS_SPIN_LOCK tssi_lock; +#endif /* RTMP_MAC_PCI */ + + //if this flag set; the driver send B/M Pkts to air even with no sta connection + BOOLEAN BSendBMToAir; + + RTMP_TX_RING TxRing[NUM_OF_TX_RING]; /* AC0~3 + HCCA */ + + NDIS_SPIN_LOCK irq_lock; + RTMP_OS_SEM e2p_read_lock; + + /*======Cmd Thread in PCI/RBUS/USB */ + CmdQ CmdQ; + NDIS_SPIN_LOCK CmdQLock; /* CmdQLock spinlock */ + RTMP_OS_TASK cmdQTask; + RTMP_OS_SEM AutoRateLock; + +#ifdef DOT11_N_SUPPORT + BA_TABLE BATable; + NDIS_SPIN_LOCK BATabLock; + RALINK_TIMER_STRUCT RECBATimer; +#endif /* DOT11_N_SUPPORT */ + + +#ifdef RTMP_SDIO_SUPPORT + UINT32 BlockSize; + NDIS_SPIN_LOCK SdioWorkTaskLock; + DL_LIST SdioWorkTaskList; + NDIS_SPIN_LOCK IntStatusLock; + NDIS_SPIN_LOCK TcCountLock; + UINT32 IntStatus; + PNDIS_PACKET SDIORxPacket; + NDIS_SPIN_LOCK SDIOTxPacketListLock[NUM_OF_TX_RING]; + DL_LIST SDIOTxPacketList[NUM_OF_TX_RING]; + TX_CTRL_T rTxCtrl; +#endif + + /* resource for software backlog queues */ + NDIS_SPIN_LOCK page_lock; /* for nat speedup by bruce */ + +/*********************************************************/ +/* Both PCI/USB related parameters */ +/*********************************************************/ + /*RTMP_DEV_INFO chipInfo; */ + RTMP_INF_TYPE infType; + UCHAR AntMode; + +/*********************************************************/ +/* Driver Mgmt related parameters */ +/*********************************************************/ + /* OP mode: either AP or STA */ + UCHAR OpMode; /* OPMODE_STA, OPMODE_AP */ +#ifdef WH_EZ_SETUP + NDIS_SPIN_LOCK WdevListLock; +#endif + struct wifi_dev *wdev_list[WDEV_NUM_MAX]; + + RTMP_OS_TASK mlmeTask; +#ifdef RTMP_TIMER_TASK_SUPPORT + /* If you want use timer task to handle the timer related jobs, enable this. */ + RTMP_TIMER_TASK_QUEUE TimerQ; + NDIS_SPIN_LOCK TimerQLock; + RTMP_OS_TASK timerTask; +#endif /* RTMP_TIMER_TASK_SUPPORT */ + +/*********************************************************/ +/* Tx related parameters */ +/*********************************************************/ + BOOLEAN DeQueueRunning[NUM_OF_TX_RING]; /* for ensuring RTUSBDeQueuePacket get call once */ + NDIS_SPIN_LOCK DeQueueLock[NUM_OF_TX_RING]; + + + + /* 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 */ +#if defined(MT_MAC) && defined(IP_ASSEMBLY) + DL_LIST assebQueue[NUM_OF_TX_RING]; +#endif + + /* Maximum allowed tx software Queue length */ + UINT TxSwQMaxLen; + struct tx_swq_fifo tx_swq[NUM_OF_TX_RING]; + /*psTokenQueue is for PS station can keep packets status and update to tx_swq */ + DL_LIST psTokenQueue; + +#ifdef MT_PS + struct tx_swq_fifo apps_cr_q; + USHORT apps_last_wcid; +#endif + + RTMP_DMABUF MgmtDescRing; /* Shared memory for MGMT descriptors */ + RTMP_MGMT_RING MgmtRing; + NDIS_SPIN_LOCK MgmtRingLock; /* Prio Ring spinlock */ + +#ifdef MT_MAC + RTMP_DMABUF BcnDescRing; /* Shared memory for Beacon descriptors */ + RTMP_BCN_RING BcnRing; + NDIS_SPIN_LOCK BcnRingLock; /* Beacon Ring spinlock */ +#endif + +#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_RBUS_SUPPORT) +#ifdef CONFIG_ANDES_SUPPORT + RTMP_DMABUF CtrlDescRing; /* Shared memory for CTRL descriptors */ + RTMP_CTRL_RING CtrlRing; + NDIS_SPIN_LOCK CtrlRingLock; /* Ctrl Ring spinlock */ +#endif /* CONFIG_ANDES_SUPPORT */ + //NDIS_SPIN_LOCK BcnRingLock; /* Beacon Ring spinlock */ + +#ifdef MT_MAC + RTMP_DMABUF TxBmcBufSpace; /* Shared memory of all 1st pre-allocated TxBuf associated with each TXD */ + RTMP_DMABUF TxBmcDescRing; /* Shared memory for Tx descriptors */ + RTMP_TX_RING TxBmcRing; /* BMC */ +#endif /* MT_MAC */ + +#endif /* RTMP_PCI_SUPPORT */ + + UCHAR LastMCUCmd; + +/*********************************************************/ +/* Rx related parameters */ +/*********************************************************/ + +#ifdef RTMP_MAC_PCI + // TODO: shiang, check the purpose of following lock "McuCmdLock" + NDIS_SPIN_LOCK McuCmdLock; /*MCU Command Queue spinlock for RT3090/3592/3390/3593/5390/5392/5592/3290 */ +#endif /* RTMP_MAC_PCI */ + + + /* RX re-assembly buffer for fragmentation */ + FRAGMENT_FRAME FragFrame; /* Frame storage for fragment frame */ + +#ifdef MT_MAC + TXS_CTL TxSCtl; +#endif + +/***********************************************************/ +/* ASIC related parameters */ +/***********************************************************/ + RTMP_CHIP_OP chipOps; + RTMP_CHIP_CAP chipCap; + struct phy_ops *phy_op; + struct hw_setting hw_cfg; + + UINT32 MACVersion; /* MAC version. Record rt2860C(0x28600100) or rt2860D (0x28600101).. */ + UINT32 ChipID; + UINT32 HWVersion; + UINT32 FWVersion; + UINT16 ee_chipId; /* Chip version. Read from EEPROM 0x00 to identify RT5390H */ + INT dev_idx; + +#ifdef MT_MAC + struct rtmp_mac_ctrl mac_ctrl; + USHORT rx_pspoll_filter; +#endif /* MT_MAC */ + BOOLEAN iwpriv_command; + + /* --------------------------- */ + /* E2PROM */ + /* --------------------------- */ + enum EEPROM_STORAGE_TYPE eeprom_type; + + ULONG EepromVersion; /* byte 0: version, byte 1: revision, byte 2~3: unused */ + ULONG FirmwareVersion; /* byte 0: Minor version, byte 1: Major version, otherwise unused. */ + USHORT EEPROMDefaultValue[NUM_EEPROM_BBP_PARMS]; + UCHAR EEPROMAddressNum; /* 93c46=6 93c66=8 */ + BOOLEAN EepromAccess; + UCHAR EFuseTag; + +#ifdef RTMP_EFUSE_SUPPORT + BOOLEAN bUseEfuse; +#endif /* RTMP_EFUSE_SUPPORT */ + + UCHAR EEPROMImage[MAX_EEPROM_BUFFER_SIZE]; + UCHAR E2pAccessMode; /* Used to identify flash, efuse, eeprom or bin from start-up */ + UCHAR e2pCurMode; + +#ifdef RTMP_FLASH_SUPPORT + UCHAR *eebuf; + UINT32 flash_offset; +#endif /* RTMP_FLASH_SUPPORT */ + + EEPROM_ANTENNA_STRUC Antenna; /* Since ANtenna definition is different for a & g. We need to save it for future reference. */ + EEPROM_NIC_CONFIG2_STRUC NicConfig2; + + /* --------------------------- */ + /* BBP Control */ + /* --------------------------- */ +#if defined(RTMP_BBP) || defined(CONFIG_ATE) + // TODO: shiang-6590, remove "defined(CONFIG_ATE)" after ATE has fully re-organized! + UCHAR BbpWriteLatch[MAX_BBP_ID + 1]; /* record last BBP register value written via BBP_IO_WRITE/BBP_IO_WRITE_VY_REG_ID */ + UCHAR Bbp94; +#endif /* defined(RTMP_BBP) || defined(CONFIG_ATE) */ + + CHAR BbpRssiToDbmDelta; /* change from UCHAR to CHAR for high power */ + BBP_R66_TUNING BbpTuning; + + /* ---------------------------- */ + /* RFIC control */ + /* ---------------------------- */ + struct rtmp_phy_ctrl phy_ctrl; + + UCHAR RfIcType; /* RFIC_xxx */ + UCHAR RfFreqOffset; /* Frequency offset for channel switching */ + + RTMP_RF_REGS LatchRfRegs; /* latch th latest RF programming value since RF IC doesn't support READ */ + +#ifdef RTMP_MAC_PCI + UCHAR ShowRf; /* Show RF register write for 2880 */ +#endif /* RTMP_MAC_PCI */ + + /* This soft Rx Antenna Diversity mechanism is used only when user set */ + /* RX Antenna = DIVERSITY ON */ + SOFT_RX_ANT_DIVERSITY RxAnt; + + /* ---------------------------- */ + /* TxPower control */ + /* ---------------------------- */ + CHANNEL_TX_POWER TxPower[MAX_NUM_OF_CHANNELS]; /* Store Tx power value for all channels. */ + CHANNEL_TX_POWER ChannelList[MAX_NUM_OF_CHANNELS]; /* list all supported channels for site survey */ + UCHAR MaxTxPwr;/*announced in beacon*/ + + + UCHAR ChannelListNum; /* number of channel in ChannelList[] */ + BOOLEAN BbpForCCK; + ULONG Tx20MPwrCfgABand[MAX_TXPOWER_ARRAY_SIZE]; + ULONG Tx20MPwrCfgGBand[MAX_TXPOWER_ARRAY_SIZE]; + ULONG Tx40MPwrCfgABand[MAX_TXPOWER_ARRAY_SIZE]; + ULONG Tx40MPwrCfgGBand[MAX_TXPOWER_ARRAY_SIZE]; +#ifdef DOT11_VHT_AC + ULONG Tx80MPwrCfgABand[MAX_TXPOWER_ARRAY_SIZE]; // Per-rate Tx power control for VHT BW80 (5GHz only) + BOOLEAN force_vht_op_mode; +#endif /* DOT11_VHT_AC */ + + + + BOOLEAN bAutoTxAgcA; /* Enable driver auto Tx Agc control */ + UCHAR TssiRefA; /* Store Tssi reference value as 25 temperature. */ + UCHAR TssiPlusBoundaryA[2][8]; /* Tssi boundary for increase Tx power to compensate. [Group][Boundary Index]*/ + UCHAR TssiMinusBoundaryA[2][8]; /* Tssi boundary for decrease Tx power to compensate. [Group][Boundary Index]*/ + UCHAR TxAgcStepA; /* Store Tx TSSI delta increment / decrement value */ + CHAR TxAgcCompensateA; /* Store the compensation (TxAgcStep * (idx-1)) */ + CHAR TssiCalibratedOffset; /* reference temperature(e2p[D1h]) */ + UCHAR ChBndryIdx; /* 5G Channel Group Boundary Index for Temperature Compensation */ + + BOOLEAN bAutoTxAgcG; /* Enable driver auto Tx Agc control */ + UCHAR TssiRefG; /* Store Tssi reference value as 25 temperature. */ + UCHAR TssiPlusBoundaryG[8]; /* Tssi boundary for increase Tx power to compensate. */ + UCHAR TssiMinusBoundaryG[8]; /* Tssi boundary for decrease Tx power to compensate. */ + UCHAR TxAgcStepG; /* Store Tx TSSI delta increment / decrement value */ + CHAR TxAgcCompensateG; /* Store the compensation (TxAgcStep * (idx-1)) */ + CHAR mp_delta_pwr; /* calculated by MP ATE temperature */ +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) + TX_POWER_CONTROL TxPowerCtrl; /* The Tx power control using the internal ALC */ + CHAR curr_temp; + CHAR rx_temp_base[2]; /* initial VGA value for chain 0/1, used for base of rx temp compensation power base */ +/* CHAR CurrTemperature; */ + CHAR DeltaPwrBeforeTempComp; + CHAR LastTempCompDeltaPwr; +#endif /* RTMP_INTERNAL_TX_ALC || RTMP_TEMPERATURE_COMPENSATION */ + + +#ifdef THERMAL_PROTECT_SUPPORT + BOOLEAN force_one_tx_stream; + BOOLEAN fgThermalProtectToggle; + INT32 last_thermal_pro_temp; + INT32 thermal_pro_high_criteria; + BOOLEAN thermal_pro_high_en; + INT32 thermal_pro_low_criteria; + BOOLEAN thermal_pro_low_en; +#endif /* THERMAL_PROTECT_SUPPORT */ + + + signed char BGRssiOffset[3]; /* Store B/G RSSI #0/1/2 Offset value on EEPROM 0x46h */ + signed char ARssiOffset[3]; /* Store A RSSI 0/1/2 Offset value on EEPROM 0x4Ah */ + + CHAR BLNAGain; /* Store B/G external LNA#0 value on EEPROM 0x44h */ + CHAR ALNAGain0; /* Store A external LNA#0 value for ch36~64 */ + CHAR ALNAGain1; /* Store A external LNA#1 value for ch100~128 */ + CHAR ALNAGain2; /* Store A external LNA#2 value for ch132~165 */ + UCHAR TxMixerGain24G; /* Tx mixer gain value from EEPROM to improve Tx EVM / Tx DAC, 2.4G */ + UCHAR TxMixerGain5G; + + +#ifdef LED_CONTROL_SUPPORT + /* LED control */ + LED_CONTROL LedCntl; +#endif /* LED_CONTROL_SUPPORT */ + + /* ---------------------------- */ + /* MAC control */ + /* ---------------------------- */ + + UCHAR wmm_cw_min; /* CW_MIN_IN_BITS, actual CwMin = 2^CW_MIN_IN_BITS - 1 */ + UCHAR wmm_cw_max; /* CW_MAX_IN_BITS, actual CwMax = 2^CW_MAX_IN_BITS - 1 */ + + +#if defined(RT3290) || defined(RLT_MAC) +#ifdef RTMP_MAC_PCI + NDIS_SPIN_LOCK WlanEnLock; +#endif + + + WLAN_FUN_CTRL_STRUC WlanFunCtrl; +#endif /* defined(RT3290) || defined(RLT_MAC) */ + +/*****************************************************************************************/ +/* 802.11 related parameters */ +/*****************************************************************************************/ + /* outgoing BEACON frame buffer and corresponding TXD */ +#if !(defined(MT7603) || defined(MT7628)) + TXWI_STRUC BeaconTxWI; + PUCHAR BeaconBuf; +#endif /* MT7603 */ + USHORT BeaconOffset[HW_BEACON_MAX_NUM]; + + /* pre-build PS-POLL and NULL frame upon link up. for efficiency purpose. */ + HEADER_802_11 NullFrame; + + + +#ifdef UAPSD_SUPPORT + NDIS_SPIN_LOCK UAPSDEOSPLock; /* EOSP frame access lock use */ + BOOLEAN bAPSDFlagSPSuspend; /* 1: SP is suspended; 0: SP is not */ +#endif /* UAPSD_SUPPORT */ +#ifdef CONFIG_SNIFFER_SUPPORT +MONITOR_STRUCT monitor_ctrl; +#endif /* CONFIG_SNIFFER_SUPPORT */ + +#ifdef DOT11_SAE_SUPPORT + SAE_CFG SaeCfg; +#endif /* DOT11_SAE_SUPPORT */ + +#ifdef MIXMODE_SUPPORT + MIX_MODE_CTRL MixModeCtrl; +#endif /* MIXMODE_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 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 */ + + +#endif /* CONFIG_AP_SUPPORT */ + +/*=======STA=========== */ + +/*=======Common=========== */ + enum RATE_ADAPT_ALG rateAlg; /* Rate adaptation algorithm */ + + NDIS_MEDIA_STATE IndicateMediaState; /* Base on Indication state, default is NdisMediaStateDisConnected */ + +#ifdef PROFILE_STORE + RTMP_OS_TASK WriteDatTask; + BOOLEAN bWriteDat; +#endif /* PROFILE_STORE */ + +#ifdef CREDENTIAL_STORE + STA_CONNECT_INFO StaCtIf; +#endif /* CREDENTIAL_STORE */ + +#ifdef WSC_INCLUDED + RTMP_OS_TASK wscTask; + UCHAR WriteWscCfgToDatFile; + BOOLEAN WriteWscCfgToAr9DatFile; + NDIS_SPIN_LOCK WscElmeLock; + MLME_QUEUE_ELEM *pWscElme; + + /* WSC hardware push button function 0811 */ + BOOLEAN WscHdrPshBtnFlag; /* 1: support, read from EEPROM */ +#ifdef CONFIG_AP_SUPPORT + BOOLEAN bWscDriverAutoUpdateCfg; +#endif /* CONFIG_AP_SUPPORT */ +#endif /* WSC_INCLUDED */ + + + /* MAT related parameters */ +#ifdef MAT_SUPPORT + MAT_STRUCT MatCfg; +#endif /* MAT_SUPPORT */ + + + /* + Frequency setting for rate adaptation + @ra_interval: for baseline time interval + @ra_fast_interval: for quick response time interval + */ + UINT32 ra_interval; + UINT32 ra_fast_interval; + + /* configuration: read from Registry & E2PROM */ + BOOLEAN bLocalAdminMAC; /* Use user changed MAC */ + UCHAR PermanentAddress[MAC_ADDR_LEN]; /* Factory default MAC address */ + UCHAR CurrentAddress[MAC_ADDR_LEN]; /* User changed MAC address */ + + /* ------------------------------------------------------ */ + /* common configuration to both OPMODE_STA and OPMODE_AP */ + /* ------------------------------------------------------ */ + UINT VirtualIfCnt; + + COMMON_CONFIG CommonCfg; + MLME_STRUCT Mlme; + + /* AP needs those vaiables for site survey feature. */ +#if defined(AP_SCAN_SUPPORT) || defined(CONFIG_STA_SUPPORT) + SCAN_CTRL ScanCtrl; + BSS_TABLE ScanTab; /* store the latest SCAN result */ +#endif /* defined(AP_SCAN_SUPPORT) || defined(CONFIG_STA_SUPPORT) */ +#ifdef CONFIG_AP_SUPPORT +#endif + + /*About MacTab, the sta driver will use #0 and #1 for multicast and AP. */ + MAC_TABLE MacTab; /* ASIC on-chip WCID entry table. At TX, ASIC always use key according to this on-chip table. */ + NDIS_SPIN_LOCK MacTabLock; + + EXT_CAP_INFO_ELEMENT ExtCapInfo; + + /* DOT11_H */ + DOT11_H Dot11_H; + + /* encryption/decryption KEY tables */ + CIPHER_KEY SharedKey[HW_BEACON_MAX_NUM + MAX_P2P_NUM][4]; /* STA always use SharedKey[BSS0][0..3] */ + + /* various Counters */ + COUNTER_802_3 Counters8023; /* 802.3 counters */ + COUNTER_802_11 WlanCounters; /* 802.11 MIB counters */ + COUNTER_RALINK RalinkCounters; /* Ralink propriety counters */ + /* COUNTER_DRS DrsCounters; */ /* counters for Dynamic TX Rate Switching */ + 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 */ + BOOLEAN bDisableRtsProtect; + /*--- */ + + ULONG ExtraInfo; /* Extra information for displaying status of UI */ + ULONG SystemErrorBitmap; /* b0: E2PROM version error */ +#if defined(MAX_CONTINUOUS_TX_CNT) || defined(NEW_IXIA_METHOD) + UINT8 DeltaRssiTh; + UINT8 ContinousTxCnt; + UINT8 MonitorFlag; + UINT8 RateTh;/*default 104 for 2.4G 20M*/ + UCHAR TxSwqCtrl; + UCHAR chkTmr; + UCHAR tmrlogctrl; + UINT16 pktthld; + UINT8 protectpara; +#endif +#ifdef NEW_IXIA_METHOD + WTRC tr_ststic; +#endif +#ifdef SYSTEM_LOG_SUPPORT + /* --------------------------- */ + /* System event log */ + /* --------------------------- */ + RT_802_11_EVENT_TABLE EventTab; +#endif /* SYSTEM_LOG_SUPPORT */ + +#ifdef HOSTAPD_SUPPORT + UINT32 IoctlIF; +#endif /* HOSTAPD_SUPPORT */ +#ifdef INF_PPA_SUPPORT + UINT32 g_if_id; + BOOLEAN PPAEnable; + PPA_DIRECTPATH_CB *pDirectpathCb; +#endif /* INF_PPA_SUPPORT */ + + /**********************************************************/ + /* Statistic related parameters */ + /**********************************************************/ + + BOOLEAN bUpdateBcnCntDone; + + ULONG macwd; + /* ---------------------------- */ + /* DEBUG paramerts */ + /* ---------------------------- */ + + BOOLEAN bLinkAdapt; + BOOLEAN bForcePrintTX; + BOOLEAN bForcePrintRX; + BOOLEAN bStaFifoTest; + BOOLEAN bProtectionTest; + BOOLEAN bHCCATest; + BOOLEAN bGenOneHCCA; + BOOLEAN bBroadComHT; + ULONG BulkOutReq; + ULONG BulkOutComplete; + ULONG BulkOutCompleteOther; + ULONG BulkOutCompleteCancel; /* seems not use now? */ + struct wificonf WIFItestbed; + + UCHAR TssiGain; + + +#ifdef CONFIG_ATE + ATE_CTRL ATECtrl; +#endif + +#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 MULTIPLE_CARD_SUPPORT + INT32 MC_RowID; + RTMP_STRING MC_FileName[256]; + UINT32 E2P_OFFSET_IN_FLASH[MAX_NUM_OF_MULTIPLE_CARD]; +#endif /* MULTIPLE_CARD_SUPPORT */ + + ULONG TbttTickCount; /* beacon timestamp work-around */ + +#ifdef CONFIG_AP_SUPPORT + RALINK_TIMER_STRUCT PeriodicTimer; +#endif /* CONFIG_AP_SUPPORT */ + + /* for detect_wmm_traffic() BE TXOP use */ + ULONG OneSecondnonBEpackets; /* record non BE packets per second */ + UCHAR is_on; + + /* for detect_wmm_traffic() BE/BK TXOP use */ +#define TIME_BASE (1000000/OS_HZ) +#define TIME_ONE_SECOND (1000000/TIME_BASE) + UCHAR flg_be_adjust; + ULONG be_adjust_last_time; + + +#ifdef WSC_INCLUDED + /* for multiple card */ + UCHAR *pHmacData; +#endif /* WSC_INCLUDED */ + +#ifdef IKANOS_VX_1X0 + struct IKANOS_TX_INFO IkanosTxInfo; + struct IKANOS_TX_INFO IkanosRxInfo[HW_BEACON_MAX_NUM + MAX_WDS_ENTRY + + MAX_APCLI_NUM + MAX_MESH_NUM]; +#endif /* IKANOS_VX_1X0 */ + + + + UINT8 FlgCtsEnabled; + UINT8 PM_FlgSuspend; + + +#ifdef DOT11V_WNM_SUPPORT + LIST_HEADER DMSEntryList; + LIST_HEADER FMSEntryList; +#endif /* DOT11V_WNM_SUPPORT */ + + UCHAR FifoUpdateDone, FifoUpdateRx; + +#ifdef LINUX +#endif /* LINUX */ + +#ifdef OS_ABL_SUPPORT +#ifdef MAT_SUPPORT + /* used in OS_ABL */ + BOOLEAN (*MATPktRxNeedConvert) (RTMP_ADAPTER *pAd, PNET_DEV net_dev); + + PUCHAR (*MATEngineRxHandle)(RTMP_ADAPTER *pAd, PNDIS_PACKET pPkt, UINT infIdx); +#endif /* MAT_SUPPORT */ +#endif /* OS_ABL_SUPPORT */ + + UINT32 ContinueMemAllocFailCount; + + struct { + INT IeLen; + UCHAR *pIe; + } ProbeRespIE[MAX_LEN_OF_BSS_TABLE]; + + /* purpose: We free all kernel resources when module is removed */ + LIST_HEADER RscTimerMemList; /* resource timers memory */ + LIST_HEADER RscTaskMemList; /* resource tasks memory */ + LIST_HEADER RscLockMemList; /* resource locks memory */ + LIST_HEADER RscTaskletMemList; /* resource tasklets memory */ + LIST_HEADER RscSemMemList; /* resource semaphore memory */ + LIST_HEADER RscAtomicMemList; /* resource atomic memory */ + + /* purpose: Cancel all timers when module is removed */ + LIST_HEADER RscTimerCreateList; /* timers list */ + +#ifdef OS_ABL_SUPPORT +#ifdef RTMP_PCI_SUPPORT + RTMP_PCI_CONFIG PciConfig; +#endif /* RTMP_PCI_SUPPORT */ +#endif /* OS_ABL_SUPPORT */ + + + + +#ifdef CONFIG_MULTI_CHANNEL + CHAR NullFrBuf[256]; + UINT32 MultiChannelFlowCtl; + RTMP_OS_TASK MultiChannelTask; + UCHAR MultiChannelAction; +#endif /* CONFIG_MULTI_CHANNEL */ + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) || defined(MT_WOW_SUPPORT) + WOW_CFG_STRUCT WOW_Cfg; /* data structure for wake on wireless */ +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) || defined(MT_WOW_SUPPORT) */ + + TXWI_STRUC NullTxWI; + USHORT NullBufOffset[2]; + +#ifdef MULTI_MAC_ADDR_EXT_SUPPORT + BOOLEAN bUseMultiMacAddrExt; +#endif /* MULTI_MAC_ADDR_EXT_SUPPORT */ + +#ifdef HW_TX_RATE_LOOKUP_SUPPORT + BOOLEAN bUseHwTxLURate; +#endif /* HW_TX_RATE_LOOKUP_SUPPORT */ + + +#ifdef CONFIG_ANDES_SUPPORT + struct MCU_CTRL MCUCtrl; +#endif /* CONFIG_ANDES_SUPPORT */ + +#ifdef WLAN_SKB_RECYCLE + struct sk_buff_head rx0_recycle; +#endif /* WLAN_SKB_RECYCLE */ + +#ifdef CONFIG_MULTI_CHANNEL + USHORT NullBufOffset[2]; + CHAR NullFrBuf[100]; + UINT32 NullFrLen; + /* + UINT32 MultiChannelFlowCtl; + RTMP_OS_TASK MultiChannelTask; + UCHAR MultiChannelAction; + */ +#endif /* CONFIG_MULTI_CHANNEL */ + +#ifdef SINGLE_SKU_V2 + BOOLEAN SKUEn; + DL_LIST SingleSkuPwrList; + UCHAR DefaultTargetPwr; + CHAR SingleSkuRatePwrDiff[19]; + BOOLEAN bOpenFileSuccess; +#endif /* SINGLE_SKU_V2 */ + + +#if defined(WFA_VHT_PF) || defined(MT7603_FPGA) || defined(MT7628_FPGA) + BOOLEAN force_amsdu; +#endif +#ifdef WFA_VHT_PF + BOOLEAN force_noack; + BOOLEAN vht_force_sgi; + BOOLEAN vht_force_tx_stbc; + + BOOLEAN force_vht_op_mode; + UCHAR vht_pf_op_ss; + UCHAR vht_pf_op_bw; +#endif /* WFA_VHT_PF */ + +#ifdef CONFIG_FPGA_MODE + struct fpga_ctrl fpga_ctl; +#endif /* CONFIG_FPGA_MODE */ + +#ifdef DBG_DIAGNOSE + RtmpDiagStruct DiagStruct; +#endif /* DBG_DIAGNOSE */ + +#ifdef CONFIG_SNIFFER_SUPPORT + struct sniffer_control sniffer_ctl; +#endif + + + +#ifdef VHT_TXBF_SUPPORT + BOOLEAN NDPA_Request; +#endif + + BOOLEAN bPS_Retrieve; + + UINT32 rxv2_cyc3[10]; + +#ifdef DBG +#ifdef MT_MAC + UCHAR BcnCnt; //Carter debug + ULONG HandleInterruptTime; + ULONG HandlePreInterruptTime; +#endif +#endif +#ifdef RTMP_PCI_SUPPORT + UINT32 DropInvalidPacket; + UINT32 RxResetDropCount; + BOOLEAN RxReset; + BOOLEAN PDMAWatchDogEn; + BOOLEAN PDMAWatchDogDbg; + UINT8 TxDMACheckTimes; + UINT8 RxDMACheckTimes; + ULONG TxDMAResetCount; + ULONG RxDMAResetCount; + ULONG PDMAResetFailCount; + NDIS_SPIN_LOCK IndirectUpdateLock; +#endif + BOOLEAN PSEWatchDogEn; + UINT8 RxPseCheckTimes; + ULONG PSEResetCount; + ULONG PSETriggerType1Count; + ULONG PSETriggerType2Count; + ULONG PSEResetFailCount; + BOOLEAN pse_reset_exclude_flag; +#ifdef DMA_RESET_SUPPORT + UINT32 bcn_didx_val; + UCHAR bcn_not_idle_tx_dma_busy; + ULONG dma_force_reset_count; + BOOLEAN pse_reset_flag; + BOOLEAN bcn_reset_en; + + BOOLEAN PSEResetFailRecover; + ULONG PSEResetFailRetryQuota; /* max quota default is 3 */ + + ULONG ACHitCount; + ULONG AC0HitCount; + ULONG AC1HitCount; + ULONG AC2HitCount; + ULONG AC3HitCount; + ULONG MgtHitCount; + +#endif /* DMA_RESET_SUPPORT */ + + ULONG SkipTxRCount; + UINT shortretry; + BOOLEAN bDisableBGProtect; + BOOLEAN bNonGFExist; + + ULONG TxTotalByteCnt; +#ifdef DYNAMIC_WMM + ULONG TxTotalByteCnt_Dyn[CMD_EDCA_AC_MAX]; +#endif /* DYNAMIC_WMM */ + ULONG RxTotalByteCnt; +#ifdef APCLI_SUPPORT +#ifdef TRAFFIC_BASED_TXOP + UCHAR StaTxopAbledCnt; + UCHAR ApClientTxopAbledCnt; +#endif /* TRAFFIC_BASED_TXOP */ +#endif /* APCLI_SUPPORT */ + + TX_AC_PARAM_T CurrEdcaParam[CMD_EDCA_AC_MAX]; + +#ifdef LOAD_FW_ONE_TIME + BOOLEAN FWLoad; +#endif /* LOAD_FW_ONE_TIME */ + +#ifdef USB_IOT_WORKAROUND2 + BOOLEAN bUSBIOTReady; +#endif + +#ifdef AIRPLAY_SUPPORT +/* +* Value: +* 0: Disable airplay +* 1: Enable airplay +*/ + BOOLEAN bAirplayEnable; +/* +*Beacon, probe Resp(opt), Action frames(opt) need append airplay IE. +*Now above three type of frame use same IE info, +*maybe later would be modified. +*/ + PUCHAR pAirplayIe; + UCHAR AirplayIeLen; + +#endif /* AIRPLAY_SUPPORT */ + +#ifdef SMART_CARRIER_SENSE_SUPPORT + SMART_CARRIER_SENSE_CTRL SCSCtrl; +#endif /* SMART_CARRIER_SENSE_SUPPORT */ + UINT32 Cts2SelfTh; + UINT32 Cts2SelfMonitorCnt; + UINT32 RtsMonitorCnt; + + /* EDCCA related param */ + UINT32 ed_th; + BOOLEAN ed_chk; + BOOLEAN ed_on; + BOOLEAN ed_debug; + + UCHAR ed_threshold; + UINT ed_false_cca_threshold; + UINT ed_block_tx_threshold; + UINT ed_big_rssi_count; + INT ed_chk_period; // in unit of ms + + UCHAR ed_stat_sidx; + UCHAR ed_stat_lidx; + BOOLEAN ed_tx_stoped; + UINT ed_trigger_cnt; + UINT ed_silent_cnt; + UINT ed_false_cca_cnt; + BOOLEAN ed_threshold_strict; + +#define ED_STAT_CNT 20 + UINT32 ed_stat[ED_STAT_CNT]; + UINT32 ed_trigger_stat[ED_STAT_CNT]; + UINT32 ed_silent_stat[ED_STAT_CNT]; + UINT32 ed_big_rssi_stat[ED_STAT_CNT]; + UINT32 ch_idle_stat[ED_STAT_CNT]; + UINT32 ch_busy_stat[ED_STAT_CNT]; + INT32 rssi_stat[ED_STAT_CNT]; + ULONG chk_time[ED_STAT_CNT]; + /* EDCCA related param END */ +#ifdef ANTI_INTERFERENCE_SUPPORT + BOOLEAN bDynamicRaInterval; + int8_t ra_interval_extend; +#endif /* ANTI_INTERFERENCE_SUPPORT */ + UINT32 OneSecChBusyTime; + BOOLEAN bPingLog; + +#ifdef MULTI_CLIENT_SUPPORT + UINT bManualMultiClientOn; + UINT MultiClientOnMode; +#endif + +#ifdef DATA_QUEUE_RESERVE + BOOLEAN bQueueRsv; + BOOLEAN bDump; + UINT dequeu_fail_cnt; +#endif /* DATA_QUEUE_RESERVE */ + UINT32 LowerMcsValue; + UINT32 HigherMcsValue; + + +#ifdef AIR_MONITOR + UCHAR MntEnable; + MNT_STA_ENTRY MntTable[MAX_NUM_OF_MONITOR_STA]; + UCHAR MntIdx; + UCHAR curMntAddr[MAC_ADDR_LEN]; + UINT32 MonitrCnt; + UCHAR MntRuleBitMap; +#endif /* AIR_MONITOR */ +#ifdef WH_EZ_SETUP + void *ez_ad; + ULONG ez_flags; /* Represent current device status */ + UCHAR CurWdevIdx; +#ifdef NEW_CONNECTION_ALGO + UINT32 ez_allow_ifindex; +#endif + BOOLEAN *SingleChip; +#ifdef DUAL_CHIP + void *pAdOthBand; + NDIS_SPIN_LOCK ez_beacon_update_lock; + NDIS_SPIN_LOCK ez_miniport_lock; + NDIS_SPIN_LOCK ez_set_channel_lock; + NDIS_SPIN_LOCK ez_set_peer_lock; +#endif + UINT8 ez_roam_time; + unsigned char ez_delay_disconnect_count; + UINT8 ez_wait_for_info_transfer; + UINT8 ez_wdl_missing_time; + UINT32 ez_force_connect_bssid_time; + UINT8 ez_peer_entry_age_out_time; + UINT8 ez_scan_same_channel_time; + UINT32 ez_partial_scan_time; +#ifdef EZ_PUSH_BW_SUPPORT + BOOLEAN push_bw_config; +#endif +#endif +#ifdef STA_FORCE_ROAM_SUPPORT + + BOOLEAN en_force_roam_supp; + CHAR sta_low_rssi; + UINT8 low_sta_renotify; + UINT8 sta_age_time; + UINT8 mntr_age_time; + UINT8 mntr_min_pkt_count; + UINT8 mntr_min_time; + UINT8 mntr_avg_rssi_pkt_count; + CHAR sta_good_rssi; + UINT8 acl_age_time; + UINT8 acl_hold_time; +#endif +#ifdef A4_CONN + UINT32 a4_interface_count; + UINT32 a4_need_refresh; +#endif +#ifdef MBO_SUPPORT + UINT8 MboBssTermCountDown; +#endif/* MBO_SUPPORT */ +#ifdef WAPP_SUPPORT + struct BSS_LOAD_INFO bss_load_info; + struct scan_req last_scan_req; +#endif /* WAPP_SUPPORT */ + UCHAR reg_domain; + NDIS_SPIN_LOCK PSRetrieveLock; +}; + +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) +/* The offset of the Tx power tuning entry (zero-based array) */ +#define TX_POWER_TUNING_ENTRY_OFFSET 30 + +/* The lower-bound of the Tx power tuning entry */ +#define LOWERBOUND_TX_POWER_TUNING_ENTRY -30 + +/* The upper-bound of the Tx power tuning entry in G band */ +#define UPPERBOUND_TX_POWER_TUNING_ENTRY(__pAd) ((__pAd)->chipCap.TxAlcTxPowerUpperBound_2G) + +#ifdef A_BAND_SUPPORT +/* The upper-bound of the Tx power tuning entry in A band */ +#define UPPERBOUND_TX_POWER_TUNING_ENTRY_5G(__pAd) ((__pAd)->chipCap.TxAlcTxPowerUpperBound_5G) +#endif /* A_BAND_SUPPORT */ + +/* Temperature compensation lookup table */ + +#define TEMPERATURE_COMPENSATION_LOOKUP_TABLE_OFFSET 7 + +/* The lower/upper power delta index for the TSSI rate table */ + +#define LOWER_POWER_DELTA_INDEX 0 +#define UPPER_POWER_DELTA_INDEX 24 + +/* The offset of the TSSI rate table */ + +#define TSSI_RATIO_TABLE_OFFSET 12 + + +/* Get the power delta bound */ + +#define GET_TSSI_RATE_TABLE_INDEX(x) (((x) > UPPER_POWER_DELTA_INDEX) ? (UPPER_POWER_DELTA_INDEX) : (((x) < LOWER_POWER_DELTA_INDEX) ? (LOWER_POWER_DELTA_INDEX) : ((x)))) + +/* 802.11b CCK TSSI information */ + +typedef union _CCK_TSSI_INFO +{ +#ifdef RT_BIG_ENDIAN + struct + { + UCHAR Reserved:1; + UCHAR ShortPreamble:1; + UCHAR Rate:2; + UCHAR Tx40MSel:2; + UCHAR TxType:2; + } field; +#else + struct + { + UCHAR TxType:2; + UCHAR Tx40MSel:2; + UCHAR Rate:2; + UCHAR ShortPreamble:1; + UCHAR Reserved:1; + } field; +#endif /* RT_BIG_ENDIAN */ + + UCHAR value; +} CCK_TSSI_INFO, *PCCK_TSSI_INFO; + + +/* 802.11a/g OFDM TSSI information */ + +typedef union _OFDM_TSSI_INFO +{ +#ifdef RT_BIG_ENDIAN + struct + { + UCHAR Rate:4; + UCHAR Tx40MSel:2; + UCHAR TxType:2; + } field; +#else + struct + { + UCHAR TxType:2; + UCHAR Tx40MSel:2; + UCHAR Rate:4; + } field; +#endif /* RT_BIG_ENDIAN */ + + UCHAR value; +} OFDM_TSSI_INFO, *POFDM_TSSI_INFO; + + +/* 802.11n HT TSSI information */ + +typedef struct _HT_TSSI_INFO { + union { +#ifdef RT_BIG_ENDIAN + struct { + UCHAR SGI:1; + UCHAR STBC:2; + UCHAR Aggregation:1; + UCHAR Tx40MSel:2; + UCHAR TxType:2; + } field; +#else + struct { + UCHAR TxType:2; + UCHAR Tx40MSel:2; + UCHAR Aggregation:1; + UCHAR STBC:2; + UCHAR SGI:1; + } field; +#endif /* RT_BIG_ENDIAN */ + + UCHAR value; + } PartA; + + union { +#ifdef RT_BIG_ENDIAN + struct { + UCHAR BW:1; + UCHAR MCS:7; + } field; +#else + struct { + UCHAR MCS:7; + UCHAR BW:1; + } field; +#endif /* RT_BIG_ENDIAN */ + UCHAR value; + } PartB; +} HT_TSSI_INFO, *PHT_TSSI_INFO; + +typedef struct _TSSI_INFO_{ + UCHAR tssi_info_0; + union { + CCK_TSSI_INFO cck_tssi_info; + OFDM_TSSI_INFO ofdm_tssi_info; + HT_TSSI_INFO ht_tssi_info_1; + UCHAR byte; + }tssi_info_1; + HT_TSSI_INFO ht_tssi_info_2; +}TSSI_INFO; + +#endif /* RTMP_INTERNAL_TX_ALC || RTMP_TEMPERATURE_COMPENSATION */ + + +typedef struct _PEER_PROBE_REQ_PARAM { + UCHAR Addr2[MAC_ADDR_LEN]; + CHAR Ssid[MAX_LEN_OF_SSID]; + UCHAR SsidLen; + BOOLEAN bRequestRssi; +#ifdef CONFIG_HOTSPOT + BOOLEAN IsIWIE; + BOOLEAN IsIWCapability; + UCHAR Hessid[MAC_ADDR_LEN]; + BOOLEAN IsHessid; + UINT8 AccessNetWorkType; +#endif /* CONFIG_HOTSPOT */ +#ifdef BAND_STEERING + BOOLEAN IsHtSupport; + BOOLEAN IsVhtSupport; + UINT32 RxMCSBitmask; +/* WPS_BandSteering Support */ + BOOLEAN bWpsCapable; +#endif +#ifdef WH_EVENT_NOTIFIER + IE_LISTS ie_list; +#endif /* WH_EVENT_NOTIFIER */ + BOOLEAN IsFromIos; /* For IOS immediately connect */ +} PEER_PROBE_REQ_PARAM, *PPEER_PROBE_REQ_PARAM; + + +/*************************************************************************** + * Rx Path software control block related data structures + **************************************************************************/ +typedef enum RX_BLK_FLAGS{ + fRX_AMPDU = (1 << 0), + fRX_AMSDU = (1 << 1), + fRX_ARALINK = (1 << 2), + fRX_HTC = (1 << 3), + fRX_PAD = (1 << 4), + fRX_QOS = (1 << 5), + fRX_EAP = (1 << 6), + fRX_WPI = (1 << 7), + fRX_AP = (1 << 8), // Packet received from AP + fRX_STA = (1 << 9), // Packet received from Client(Infra mode) + fRX_ADHOC = (1 << 10), // packet received from AdHoc peer + fRX_WDS = (1 << 11), // Packet received from WDS + fRX_MESH = (1 << 12), // Packet received from MESH + fRX_DLS = (1 << 13), // Packet received from DLS peer + fRX_TDLS = (1 << 14), // Packet received from TDLS peer + fRX_RETRIEVE = (1 << 15), // Packet received from mcu + fRX_CMD_RSP = (1 << 16), // Pakket received from mcu command response + fRX_TXRX_RXV = (1 << 17), // RxV received from Rx Ring1 +}RX_BLK_FLAGS; + + +typedef struct _RX_BLK +{ + UCHAR hw_rx_info[RXD_SIZE]; /* include "RXD_STRUC RxD" and "RXINFO_STRUC rx_info " */ + RXINFO_STRUC *pRxInfo; /* for RLT, in head of frame buffer, for RTMP, in hw_rx_info[RXINFO_OFFSET] */ +#ifdef RLT_MAC + RXFCE_INFO *pRxFceInfo; /* for RLT, in in hw_rx_info[RXINFO_OFFSET], for RTMP, no such field */ +#endif /* RLT_MAC */ + RXWI_STRUC *pRxWI; /*in frame buffer and after "rx_info" fields */ + UCHAR *rmac_info; + HEADER_802_11 *pHeader; /* poiter of 802.11 header, pointer to frame buffer and shall not shift this pointer */ + PNDIS_PACKET pRxPacket; /* os_packet pointer, shall not change */ + UCHAR *pData; /* init to pRxPacket->data, refer to frame buffer, may changed depends on processing */ + USHORT DataSize; /* init to RXWI->MPDUtotalByteCnt, and may changes depends on processing */ + RX_BLK_FLAGS Flags; + + /* Mirror info of partial fields of RxWI and RxInfo */ + USHORT MPDUtotalByteCnt; /* Refer to RXWI->MPDUtotalByteCnt */ + UCHAR UserPriority; /* for calculate TKIP MIC using */ + UCHAR OpMode; /* 0:OPMODE_STA 1:OPMODE_AP */ + UCHAR wcid; /* copy of pRxWI->wcid */ + UCHAR U2M; + UCHAR key_idx; + UCHAR bss_idx; + UCHAR TID; + UINT32 TimeStamp; + struct rx_signal_info rx_signal; + CHAR ldpc_ex_sym; + HTTRANSMIT_SETTING rx_rate; + UINT32 rxv2_cyc1; + UINT32 rxv2_cyc2; + UINT32 rxv2_cyc3; +#ifdef HDR_TRANS_SUPPORT + BOOLEAN bHdrRxTrans; /* this packet's header is translated to 802.3 by HW */ + BOOLEAN bHdrVlanTaged; /* VLAN tag is added to this header */ + UCHAR *pTransData; + USHORT TransDataSize; +#endif /* HDR_TRANS_SUPPORT */ +#ifdef RTMP_PCI_SUPPORT + UINT32 PDMALen; +#endif + UINT64 CCMP_PN; +} RX_BLK; + + +#define RX_BLK_SET_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags |= _flag) +#define RX_BLK_TEST_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags & _flag) +#define RX_BLK_CLEAR_FLAG(_pRxBlk, _flag) (_pRxBlk->Flags &= ~(_flag)) + + +#define AMSDU_SUBHEAD_LEN 14 +#define ARALINK_SUBHEAD_LEN 14 +#define ARALINK_HEADER_LEN 2 + + +/*************************************************************************** + * Tx Path software control block related data structures + **************************************************************************/ +#define TX_UNKOWN_FRAME 0x00 +#define TX_MCAST_FRAME 0x01 +#define TX_LEGACY_FRAME 0x02 +#define TX_AMPDU_FRAME 0x04 +#define TX_AMSDU_FRAME 0x08 +#define TX_RALINK_FRAME 0x10 +#define TX_FRAG_FRAME 0x20 +// TODO: shiang-usw, revise for TX_NDPA_FRAME! +#define TX_NDPA_FRAME 0x40 + +#define TX_FRAG_ID_NO 0x0 +#define TX_FRAG_ID_FIRST 0x1 +#define TX_FRAG_ID_MIDDLE 0x2 +#define TX_FRAG_ID_LAST 0x3 + +/* 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 */ +#ifdef MT_MAC + UCHAR FragIdx; /* refer to TX_FRAG_ID_xxxx */ + UINT8 Pid; + UINT8 TxS2Host; + UINT8 TxS2Mcu; + UINT8 TxSFormat; +#endif /* MT_MAC */ + 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 */ + STA_TR_ENTRY *tr_entry; + HTTRANSMIT_SETTING *pTransmit; + + /* Following structure used for the characteristics of a specific packet. */ + PNDIS_PACKET pPacket; + UCHAR *pSrcBufHeader; /* Reference to the head of sk_buff->data */ + UCHAR *pSrcBufData; /* Reference to the sk_buff->data, will changed depends on hanlding progresss */ + UINT SrcBufLen; /* Length of packet payload which not including Layer 2 header */ + UCHAR *pExtraLlcSnapEncap; /* NULL means no extra LLC/SNAP is required */ + UCHAR hw_rsv_len; + +#ifndef VENDOR_FEATURE1_SUPPORT + /* + Note: Can not insert any other new parameters + between pExtraLlcSnapEncap & HeaderBuf; Or + the start address of HeaderBuf will not be aligned by 4. + + But we can not change HeaderBuf[128] to HeaderBuf[32] because + many codes use HeaderBuf[index]. + */ + UCHAR HeaderBuf[128]; /* TempBuffer for TX_INFO + TX_WI + TSO_INFO + 802.11 Header + padding + AMSDU SubHeader + LLC/SNAP */ +#else + UINT32 HeaderBuffer[32]; /* total 128B, use UINT32 to avoid alignment problem */ + UCHAR *HeaderBuf; +#endif /* VENDOR_FEATURE1_SUPPORT */ + UCHAR *wifi_hdr; + + UCHAR MpduHeaderLen; /* 802.11 header length NOT including the padding */ + UCHAR first_buf_len; + UCHAR wifi_hdr_len; + UCHAR HdrPadLen; /* recording Header Padding Length; */ + UCHAR UserPriority; /* priority class of packet */ + UCHAR FrameGap; /* what kind of IFS this packet use */ + UCHAR MpduReqNum; /* number of fragments of this frame */ + +// TODO: shiang-6590, potential to remove + UCHAR TxRate; /* TODO: Obsoleted? Should change to MCS? */ + UCHAR CipherAlg; /* cipher alogrithm */ + PCIPHER_KEY pKey; + UCHAR KeyIdx; /* Indicate the transmit key index */ + UCHAR OpMode; + UCHAR Wcid; /* The MAC entry associated to this packet */ + /*UCHAR apidx;*/ /* The interface associated to this packet */ + UCHAR wdev_idx; // Used to replace apidx + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT + UINT ApCliIfidx; + PAPCLI_STRUCT pApCliEntry; +#endif /* APCLI_SUPPORT */ + + BSS_STRUCT *pMbss; + +#endif /* CONFIG_AP_SUPPORT */ +// TODO: ---End + + UINT32 Flags; /*See following definitions for detail. */ + + /*YOU SHOULD NOT TOUCH IT! Following parameters are used for hardware-depended layer. */ + ULONG Priv; /* Hardware specific value saved in here. */ + + +#ifdef TX_PKT_SG + PACKET_INFO pkt_info; +#endif /* TX_PKT_SG */ + +#ifdef HDR_TRANS_SUPPORT + BOOLEAN NeedTrans; /* indicate the packet needs to do hw header translate */ +#endif /* HDR_TRANS_SUPPORT */ + UINT32 TxSPriv; + struct wifi_dev *wdev; +} TX_BLK; + + +#define fTX_bRtsRequired 0x0001 /* Indicate if need send RTS frame for protection. Not used in RT2860/RT2870. */ +#define fTX_bAckRequired 0x0002 /* the packet need ack response */ +#define fTX_bPiggyBack 0x0004 /* Legacy device use Piggback or not */ +#define fTX_bHTRate 0x0008 /* allow to use HT rate */ +#define fTX_bWMM 0x0010 /* QOS Data */ +#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_bClearEAPFrame 0x0100 + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +#define fTX_bApCliPacket 0x0200 +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#define fTX_bSwEncrypt 0x0400 /* this packet need to be encrypted by software before TX */ + +#ifdef UAPSD_SUPPORT +#define fTX_bWMM_UAPSD_EOSP 0x0800 /* Used when UAPSD_SUPPORT */ +#endif /* UAPSD_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef WDS_SUPPORT +#define fTX_bWDSEntry 0x1000 /* Used when WDS_SUPPORT */ +#endif /* WDS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + + +#ifdef WAPI_SUPPORT +#define fTX_bWPIDataFrame 0x8000 /* indicate this packet is an WPI data frame, it need to be encrypted by software */ +#endif /* WAPI_SUPPORT */ + +#ifdef CLIENT_WDS +#define fTX_bClientWDSFrame 0x10000 +#endif /* CLIENT_WDS */ + +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) +#define fTX_bTdlsEntry 0x20000 /* Used when DOT11Z_TDLS_SUPPORT */ +#endif /* defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) */ + +#ifdef WFA_VHT_PF +#define fTX_AmsduInAmpdu 0x40000 +#endif /* WFA_VHT_PF */ + +#define fTX_ForceRate 0x80000 + +#ifdef A4_CONN +#define fTX_bA4Frame 0x100000 +#endif +#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 DBG_DEQUE +struct deq_log_struct{ + UCHAR que_depth[WMM_NUM_OF_AC]; + UCHAR deq_cnt[WMM_NUM_OF_AC]; + UCHAR deq_round; +}; +#endif /* DBG_DEQUE */ + + +typedef struct dequeue_info{ + BOOLEAN inited; + UCHAR start_q; + UCHAR end_q; + CHAR cur_q; + UCHAR target_wcid; + UCHAR target_que; + UCHAR cur_wcid; + UCHAR q_max_cnt[WMM_QUE_NUM]; + INT pkt_bytes; + INT pkt_cnt; + INT deq_pkt_bytes; + INT deq_pkt_cnt; + INT status; +#ifdef DATA_QUEUE_RESERVE + INT status_2; +#endif /* DATA_QUEUE_RESERVE */ + BOOLEAN full_qid[WMM_QUE_NUM]; +#ifdef DBG_DEQUE + deq_log_struct deq_log; +#endif /* DBG_DEQUE */ +#ifdef MAX_CONTINUOUS_TX_CNT + USHORT CurSwqIdx; +#endif +}DEQUE_INFO; + + +#ifdef RT_BIG_ENDIAN +/*************************************************************************** + * Endian conversion related functions + **************************************************************************/ + +#ifdef MT_MAC +static inline VOID mt_rmac_d0_endian_change(UINT32 *rxinfo) +{ + (*rxinfo) = SWAP32(*rxinfo); +} + + +static inline VOID mt_rmac_base_info_endian_change( + IN RTMP_ADAPTER *pAd, + IN UCHAR *rxinfo) +{ + int i; + + for(i=1; i < 4; i++) { + *(((UINT32 *)rxinfo) +i) = SWAP32(*(((UINT32 *)rxinfo)+i)); + } +} +#endif /* MT_MAC */ + + +/* + ======================================================================== + + Routine Description: + Endian conversion of Tx/Rx descriptor . + + Arguments: + pAd Pointer to our adapter + pData Pointer to Tx/Rx descriptor + DescriptorType Direction of the frame + + Return Value: + None + + Note: + Call this function when read or update descriptor + ======================================================================== +*/ +static inline VOID RTMPWIEndianChange( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pData, + IN ULONG DescriptorType) +{ + int size; + int i; + UINT8 TXWISize = pAd->chipCap.TXWISize; + UINT8 RXWISize = pAd->chipCap.RXWISize; + + size = ((DescriptorType == TYPE_TXWI) ? TXWISize : RXWISize); + + if(DescriptorType == TYPE_TXWI) + { + *((UINT32 *)(pData)) = SWAP32(*((UINT32 *)(pData))); /* Byte 0~3 */ + *((UINT32 *)(pData + 4)) = SWAP32(*((UINT32 *)(pData+4))); /* Byte 4~7 */ + if (size > 16) + *((UINT32 *)(pData + 16)) = SWAP32(*((UINT32 *)(pData + 16))); /* Byte 16~19 */ + } + else + { + for(i=0; i < size/4 ; i++) + *(((UINT32 *)pData) +i) = SWAP32(*(((UINT32 *)pData)+i)); + } +} + +#ifdef MT_MAC +/* + ======================================================================== + + Routine Description: + Endian conversion of MacTxInfo/MacRxInfo descriptor . + + Arguments: + pAd Pointer to our adapter + pData Pointer to Tx/Rx descriptor + DescriptorType Direction of the frame + Length Length of MacTxInfo/MacRxInfo + + Return Value: + None + + Note: + Call this function when read or update descriptor + ======================================================================== +*/ +static inline VOID MTMacInfoEndianChange( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pData, + IN ULONG DescriptorType, + IN UINT16 Length) +{ + int i; + if(DescriptorType == TYPE_TMACINFO) + { + for(i=0; i < Length/4 ; i++) + *(((UINT32 *)pData) +i) = SWAP32(*(((UINT32 *)pData)+i)); + } + else /* TYPE_RMACINFO */ + { + for(i=1; i < Length/4 ; i++) /* i from 1, due to 1st DW had endia change already, so skip it here. */ + *(((UINT32 *)pData) +i) = SWAP32(*(((UINT32 *)pData)+i)); + } +} +#endif /* MT_MAC */ + +#ifdef RTMP_MAC_PCI +static inline VOID WriteBackToDescriptor( + IN UCHAR *Dest, + IN UCHAR *Src, + IN BOOLEAN DoEncrypt, + IN ULONG DescriptorType) +{ + UINT32 *p1, *p2; + + p1 = ((UINT32 *)Dest); + p2 = ((UINT32 *)Src); + + *p1 = *p2; + *(p1+2) = *(p2+2); + *(p1+3) = *(p2+3); + *(p1+1) = *(p2+1); /* Word 1; this must be written back last */ +} +#endif /* RTMP_MAC_PCI */ + + +/* + ======================================================================== + + Routine Description: + Endian conversion of Tx/Rx descriptor . + + Arguments: + pAd Pointer to our adapter + pData Pointer to Tx/Rx descriptor + DescriptorType Direction of the frame + + Return Value: + None + + Note: + Call this function when read or update descriptor + ======================================================================== +*/ +#ifdef RTMP_MAC_PCI +static inline VOID RTMPDescriptorEndianChange(UCHAR *pData, ULONG DescType) +{ + *((UINT32 *)(pData)) = SWAP32(*((UINT32 *)(pData))); /* Byte 0~3 */ + *((UINT32 *)(pData + 8)) = SWAP32(*((UINT32 *)(pData+8))); /* Byte 8~11 */ + *((UINT32 *)(pData +12)) = SWAP32(*((UINT32 *)(pData + 12))); /* Byte 12~15 */ + *((UINT32 *)(pData + 4)) = SWAP32(*((UINT32 *)(pData + 4))); /* Byte 4~7, this must be swapped last */ +} +#endif /* RTMP_MAC_PCI */ + +/* + ======================================================================== + + Routine Description: + Endian conversion of all kinds of 802.11 frames . + + Arguments: + pAd Pointer to our adapter + pData Pointer to the 802.11 frame structure + Dir Direction of the frame + FromRxDoneInt Caller is from RxDone interrupt + + Return Value: + None + + Note: + Call this function when read or update buffer data + ======================================================================== +*/ +static inline VOID RTMPFrameEndianChange( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pData, + IN ULONG Dir, + IN BOOLEAN FromRxDoneInt) +{ + PHEADER_802_11 pFrame; + PUCHAR pMacHdr; + + /* swab 16 bit fields - Frame Control field */ + if(Dir == DIR_READ) + { + *(USHORT *)pData = SWAP16(*(USHORT *)pData); + } + + pFrame = (PHEADER_802_11) pData; + pMacHdr = (PUCHAR) pFrame; + + /* swab 16 bit fields - Duration/ID field */ + *(USHORT *)(pMacHdr + 2) = SWAP16(*(USHORT *)(pMacHdr + 2)); + + if (pFrame->FC.Type != FC_TYPE_CNTL) + { + /* swab 16 bit fields - Sequence Control field */ + *(USHORT *)(pMacHdr + 22) = SWAP16(*(USHORT *)(pMacHdr + 22)); + } + + if(pFrame->FC.Type == FC_TYPE_MGMT) + { + switch(pFrame->FC.SubType) + { + case SUBTYPE_ASSOC_REQ: + case SUBTYPE_REASSOC_REQ: + /* swab 16 bit fields - CapabilityInfo field */ + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + /* swab 16 bit fields - Listen Interval field */ + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + break; + + case SUBTYPE_ASSOC_RSP: + case SUBTYPE_REASSOC_RSP: + /* swab 16 bit fields - CapabilityInfo field */ + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + /* swab 16 bit fields - Status Code field */ + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + /* swab 16 bit fields - AID field */ + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + break; + + case SUBTYPE_AUTH: + /* When the WEP bit is on, don't do the conversion here. + This is only shared WEP can hit this condition. + For AP, it shall do conversion after decryption. + For STA, it shall do conversion before encryption. */ + if (pFrame->FC.Wep == 1) + break; + else + { + /* swab 16 bit fields - Auth Alg No. field */ + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + /* swab 16 bit fields - Auth Seq No. field */ + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + /* swab 16 bit fields - Status Code field */ + pMacHdr += 2; + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + } + break; + + case SUBTYPE_BEACON: + case SUBTYPE_PROBE_RSP: + /* swab 16 bit fields - BeaconInterval field */ + pMacHdr += (sizeof(HEADER_802_11) + TIMESTAMP_LEN); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + + /* swab 16 bit fields - CapabilityInfo field */ + pMacHdr += sizeof(USHORT); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + break; + + case SUBTYPE_DEAUTH: + case SUBTYPE_DISASSOC: + /* If the PMF is negotiated, those frames shall be encrypted */ + if(!FromRxDoneInt && pFrame->FC.Wep == 1) + break; + else + { + /* swab 16 bit fields - Reason code field */ + pMacHdr += sizeof(HEADER_802_11); + *(USHORT *)pMacHdr = SWAP16(*(USHORT *)pMacHdr); + } + break; + } + } + else if( pFrame->FC.Type == FC_TYPE_DATA ) + { + } + else if(pFrame->FC.Type == FC_TYPE_CNTL) + { + switch(pFrame->FC.SubType) + { + case SUBTYPE_BLOCK_ACK_REQ: + { + PFRAME_BA_REQ pBAReq = (PFRAME_BA_REQ)pFrame; + *(USHORT *)(&pBAReq->BARControl) = SWAP16(*(USHORT *)(&pBAReq->BARControl)); + pBAReq->BAStartingSeq.word = SWAP16(pBAReq->BAStartingSeq.word); + } + break; + case SUBTYPE_BLOCK_ACK: + /* For Block Ack packet, the HT_CONTROL field is in the same offset with Addr3 */ + *(UINT32 *)(&pFrame->Addr3[0]) = SWAP32(*(UINT32 *)(&pFrame->Addr3[0])); + break; + + case SUBTYPE_ACK: + /*For ACK packet, the HT_CONTROL field is in the same offset with Addr2 */ + *(UINT32 *)(&pFrame->Addr2[0])= SWAP32(*(UINT32 *)(&pFrame->Addr2[0])); + break; + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR,("Invalid Frame Type!!!\n")); + } + + /* swab 16 bit fields - Frame Control */ + if(Dir == DIR_WRITE) + { + *(USHORT *)pData = SWAP16(*(USHORT *)pData); + } +} +#endif /* RT_BIG_ENDIAN */ + + +/*************************************************************************** + * Other static inline function definitions + **************************************************************************/ +static inline VOID ConvertMulticastIP2MAC( + IN PUCHAR pIpAddr, + IN PUCHAR *ppMacAddr, + IN UINT16 ProtoType) +{ + if (pIpAddr == NULL) + return; + + if (ppMacAddr == NULL || *ppMacAddr == NULL) + return; + + switch (ProtoType) + { + case ETH_P_IPV6: +/* memset(*ppMacAddr, 0, MAC_ADDR_LEN); */ + *(*ppMacAddr) = 0x33; + *(*ppMacAddr + 1) = 0x33; + *(*ppMacAddr + 2) = pIpAddr[12]; + *(*ppMacAddr + 3) = pIpAddr[13]; + *(*ppMacAddr + 4) = pIpAddr[14]; + *(*ppMacAddr + 5) = pIpAddr[15]; + break; + + case ETH_P_IP: + default: +/* memset(*ppMacAddr, 0, MAC_ADDR_LEN); */ + *(*ppMacAddr) = 0x01; + *(*ppMacAddr + 1) = 0x00; + *(*ppMacAddr + 2) = 0x5e; + *(*ppMacAddr + 3) = pIpAddr[1] & 0x7f; + *(*ppMacAddr + 4) = pIpAddr[2]; + *(*ppMacAddr + 5) = pIpAddr[3]; + break; + } + + return; +} + + +char *get_phymode_str(int phy_mode); +char *get_bw_str(int bandwidth); + + +NDIS_STATUS RTMPAllocTxRxRingMemory(RTMP_ADAPTER *pAd); + +#ifdef RESOURCE_PRE_ALLOC +NDIS_STATUS RTMPInitTxRxRingMemory(RTMP_ADAPTER *pAd); +#endif /* RESOURCE_PRE_ALLOC */ + +NDIS_STATUS load_dev_l1profile(RTMP_ADAPTER *pAd); +INT get_dev_config_idx(RTMP_ADAPTER *pAd); +UCHAR *get_dev_name_prefix(RTMP_ADAPTER *pAd, INT dev_type); +UCHAR *get_dev_profile(RTMP_ADAPTER *pAd); +INT ShowL1profile(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +void RTMPPreReadParametersHook(RTMP_ADAPTER *pAd); +NDIS_STATUS RTMPReadParametersHook(RTMP_ADAPTER *pAd); +NDIS_STATUS RTMPSetProfileParameters(RTMP_ADAPTER *pAd, RTMP_STRING *pBuffer); + +INT RTMPGetKeyParameter( + IN RTMP_STRING *key, + OUT RTMP_STRING *dest, + IN INT destsize, + IN RTMP_STRING *buffer, + IN BOOLEAN bTrimSpace); + +#ifdef WSC_INCLUDED +VOID rtmp_read_wsc_user_parms_from_file( + IN RTMP_ADAPTER *pAd, + IN char *tmpbuf, + IN char *buffer); +#endif/*WSC_INCLUDED*/ + +#ifdef SINGLE_SKU_V2 +NDIS_STATUS RTMPSetSingleSKUParameters(RTMP_ADAPTER *pAd); + +VOID InitSkuRateDiffTable(RTMP_ADAPTER *pAd ); +UCHAR GetSkuChannelBasePwr(RTMP_ADAPTER *pAd, UCHAR channel); + +VOID UpdateSkuRatePwr(RTMP_ADAPTER *pAd, UCHAR ch, UCHAR bw, CHAR base_pwr); +#endif /* SINGLE_SKU_V2 */ + + +#ifdef RTMP_RF_RW_SUPPORT +VOID RTMP_ReadRF( + IN RTMP_ADAPTER *pAd, + IN UCHAR RegID, + OUT PUCHAR pValue1, + OUT PUCHAR pValue2, + IN UCHAR BitMask); + +VOID RTMP_WriteRF( + IN RTMP_ADAPTER *pAd, + IN UCHAR RegID, + IN UCHAR Value, + IN UCHAR BitMask); + +NDIS_STATUS RT30xxWriteRFRegister( + IN RTMP_ADAPTER *pAd, + IN UCHAR regID, + IN UCHAR value); + +NDIS_STATUS RT30xxReadRFRegister( + IN RTMP_ADAPTER *pAd, + IN UCHAR regID, + IN PUCHAR pValue); + +NDIS_STATUS RT635xWriteRFRegister( + IN RTMP_ADAPTER *pAd, + IN UCHAR bank, + IN UCHAR regID, + IN UCHAR value); + +NDIS_STATUS RT635xReadRFRegister( + IN RTMP_ADAPTER *pAd, + IN UCHAR bank, + IN UCHAR regID, + IN PUCHAR pValue); + +BOOLEAN RTMPAdjustFrequencyOffset( + IN RTMP_ADAPTER *pAd, + INOUT PUCHAR pRefFreqOffset); +#endif /* RTMP_RF_RW_SUPPORT */ + +BOOLEAN RTMPCheckPhyMode( + IN RTMP_ADAPTER *pAd, + IN UINT8 BandSupported, + INOUT UCHAR *pPhyMode); + +#ifdef RLT_RF +NDIS_STATUS rlt_rf_write( + IN RTMP_ADAPTER *pAd, + IN UCHAR bank, + IN UCHAR regID, + IN UCHAR value); + +NDIS_STATUS rlt_rf_read( + IN RTMP_ADAPTER *pAd, + IN UCHAR bank, + IN UCHAR regID, + IN UCHAR *pValue); +#endif /* RLT_RF */ + + +#ifdef RTMP_MAC_PCI +INT NICInitPwrPinCfg(RTMP_ADAPTER *pAd); +#endif /* RTMP_MAC_PCI */ + +VOID NICInitAsicFromEEPROM(RTMP_ADAPTER *pAd); + +NDIS_STATUS NICInitializeAdapter(RTMP_ADAPTER *pAd, BOOLEAN bHardReset); +NDIS_STATUS NICInitializeAsic(RTMP_ADAPTER *pAd, BOOLEAN bHardReset); +INT hif_sys_init(RTMP_ADAPTER *pAd, BOOLEAN bHardReset); +INT hif_sys_exit(RTMP_ADAPTER *pAd); + + +VOID NICResetFromError(RTMP_ADAPTER *pAd); + + +VOID RTMPRingCleanUp( + IN RTMP_ADAPTER *pAd, + IN UCHAR RingType); + +VOID UserCfgExit(RTMP_ADAPTER *pAd); +VOID UserCfgInit(RTMP_ADAPTER *pAd); + +int load_patch(RTMP_ADAPTER *ad); +NDIS_STATUS NICLoadFirmware(RTMP_ADAPTER *pAd); +VOID NICEraseFirmware(RTMP_ADAPTER *pAd); + +VOID NICUpdateFifoStaCounters(RTMP_ADAPTER *pAd); +NTSTATUS MtCmdNICUpdateRawCounters(RTMP_ADAPTER *pAd, PCmdQElmt CMDQelmt); +VOID NICUpdateRawCounters(RTMP_ADAPTER *pAd); +NTSTATUS MtCmdWtbl2RateTableUpdate(RTMP_ADAPTER *pAd, PCmdQElmt CMDQelmt); +NTSTATUS MtCmdWtblTxpsUpdate(RTMP_ADAPTER *pAd, PCmdQElmt CMDQelmt); + + +UINT32 AsicGetCrcErrCnt(RTMP_ADAPTER *pAd); +UINT32 AsicGetCCACnt(RTMP_ADAPTER *pAd); +UINT32 AsicGetChBusyCnt(RTMP_ADAPTER *pAd, UCHAR ch_idx); + +#if defined(RTMP_MAC) || defined(RLT_MAC) +#ifdef FIFO_EXT_SUPPORT +BOOLEAN NicGetMacFifoTxCnt(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry); +VOID AsicFifoExtSet(RTMP_ADAPTER *pAd); +VOID AsicFifoExtEntryClean(RTMP_ADAPTER * pAd, MAC_TABLE_ENTRY *pEntry); +#endif /* FIFO_EXT_SUPPORT */ +#endif /* defined(RTMP_MAC) || defined(RLT_MAC) */ + +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(VOID *pSrc, ULONG Length); +ULONG RTMPCompareMemory(VOID *pSrc1, VOID *pSrc2, ULONG Length); +VOID RTMPMoveMemory(VOID *pDest, VOID *pSrc, ULONG Length); + +VOID AtoH(RTMP_STRING *src, UCHAR *dest, int destlen); +UCHAR BtoH(char ch); + +VOID RTMP_TimerListAdd(RTMP_ADAPTER *pAd, VOID *pRsc); +VOID RTMP_TimerListRelease(RTMP_ADAPTER *pAd, VOID *pRsc); +VOID RTMP_AllTimerListRelease(RTMP_ADAPTER *pAd); + +VOID RTMPInitTimer( + IN RTMP_ADAPTER *pAd, + IN RALINK_TIMER_STRUCT *pTimer, + IN VOID *pTimerFunc, + IN VOID *pData, + IN BOOLEAN Repeat); + +VOID RTMPSetTimer(RALINK_TIMER_STRUCT *pTimer, ULONG Value); +VOID RTMPModTimer(RALINK_TIMER_STRUCT *pTimer, ULONG Value); +VOID RTMPCancelTimer(RALINK_TIMER_STRUCT *pTimer, BOOLEAN *pCancelled); +VOID RTMPReleaseTimer(RALINK_TIMER_STRUCT *pTimer, BOOLEAN *pCancelled); + +VOID RTMPEnableRxTx(RTMP_ADAPTER *pAd); +VOID RTMPDisableRxTx(RTMP_ADAPTER *pAd); + +VOID AntCfgInit(RTMP_ADAPTER *pAd); + +/* */ +/* prototype in action.c */ +/* */ +VOID ActHeaderInit( + IN RTMP_ADAPTER *pAd, + IN OUT HEADER_802_11 *pHdr80211, + IN UCHAR *da, + IN UCHAR *sa, + IN UCHAR *bssid); + +VOID ActionStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MlmeADDBAAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDELBAAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID SendSMPSAction( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR smps); + +#ifdef CONFIG_AP_SUPPORT +VOID SendBeaconRequest( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid); +#endif /* CONFIG_AP_SUPPORT */ + + + +#ifdef DOT11_N_SUPPORT +VOID RECBATimerTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID ORIBATimerTimeout( + IN RTMP_ADAPTER *pAd); + +VOID SendRefreshBAR( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry); + +#ifdef DOT11N_DRAFT3 +VOID RTMP_11N_D3_TimerInit( + IN RTMP_ADAPTER *pAd); + +VOID SendBSS2040CoexistMgmtAction( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR apidx, + IN UCHAR InfoReq); + +VOID SendNotifyBWActionFrame( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR apidx); + +BOOLEAN ChannelSwitchSanityCheck( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR NewChannel, + IN UCHAR Secondary); + +VOID ChannelSwitchAction( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR Channel, + IN UCHAR Secondary); + +ULONG BuildIntolerantChannelRep( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pDest); + +VOID Update2040CoexistFrameAndNotify( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN BOOLEAN bAddIntolerantCha); + +VOID Send2040CoexistAction( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN BOOLEAN bAddIntolerantCha); + +VOID UpdateBssScanParm( + IN RTMP_ADAPTER *pAd, + IN OVERLAP_BSS_SCAN_IE APBssScan); +#endif /* DOT11N_DRAFT3 */ + +INT AsicSetRalinkBurstMode(RTMP_ADAPTER *pAd, BOOLEAN enable); +#endif /* DOT11_N_SUPPORT */ + +VOID AsicSetTxPreamble(RTMP_ADAPTER *pAd, USHORT TxPreamble); + +UCHAR get_channel_set_num(UCHAR *ChannelSet); + +VOID BarHeaderInit( + IN RTMP_ADAPTER *pAd, + IN OUT PFRAME_BAR pCntlBar, + IN PUCHAR pDA, + IN PUCHAR pSA); + +VOID InsertActField( + IN RTMP_ADAPTER *pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Category, + IN UINT8 ActCode); + +BOOLEAN QosBADataParse( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN bAMSDU, + IN PUCHAR p8023Header, + IN UCHAR WCID, + IN UCHAR TID, + IN USHORT Sequence, + IN UCHAR DataOffset, + IN USHORT Datasize, + IN UINT CurRxIndex); + +#ifdef DOT11_N_SUPPORT +BOOLEAN CntlEnqueueForRecv( + IN RTMP_ADAPTER *pAd, + IN ULONG Wcid, + IN ULONG MsgLen, + IN PFRAME_BA_REQ pMsg); + +VOID BaAutoManSwitch( + IN RTMP_ADAPTER *pAd); +#endif /* DOT11_N_SUPPORT */ + +VOID HTIOTCheck( + IN RTMP_ADAPTER *pAd, + IN UCHAR BatRecIdx); + + +INT rtmp_wdev_idx_find_by_p2p_ifaddr(RTMP_ADAPTER *pAd, UCHAR *ifAddr); +INT rtmp_wdev_idx_reg(RTMP_ADAPTER *pAd, struct wifi_dev *wdev); +INT rtmp_wdev_idx_unreg(RTMP_ADAPTER *pAd, struct wifi_dev *wdev); +INT wdev_init(RTMP_ADAPTER *pAd, struct wifi_dev *wdev, UINT wdev_type); +INT wdev_tx_pkts(NDIS_HANDLE dev_hnd, PPNDIS_PACKET pkt_list, UINT pkt_cnt, struct wifi_dev *wdev); +struct wifi_dev *WdevSearchByAddress(RTMP_ADAPTER *pAd, UCHAR *Address); +struct wifi_dev *wdev_search_by_address(RTMP_ADAPTER *pAd, UCHAR *Address); +REPEATER_CLIENT_ENTRY *lookup_rept_entry(RTMP_ADAPTER *pAd, PUCHAR address); + + +VOID rtmp_ps_init(RTMP_ADAPTER *pAd); +INT rtmp_psDeq_report(RTMP_ADAPTER *pAd,struct dequeue_info *info); +INT rtmp_psDeq_req(RTMP_ADAPTER *pAd); +INT rtmp_ps_enq(RTMP_ADAPTER *pAd, STA_TR_ENTRY *tr_entry); +#if defined(MAX_CONTINUOUS_TX_CNT) || defined(NEW_IXIA_METHOD) +BOOLEAN Rtmp_Set_Packet_EnqIdx(PNDIS_PACKET pkt,INT enq_idx); +INT Set_Rssi_Threshold_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ContinousTxCnt_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_Rate_Threshold_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Show_TxSwqInfo_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_TxSwqCtrl_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif +#ifdef IP_ASSEMBLY + +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; + + +typedef struct ip_assemble_data { + DL_LIST list; + QUEUE_HEADER queue; + INT32 identify; + INT32 fragSize; + ULONG createTime; +}IP_ASSEMBLE_DATA; + +INT rtmp_IpAssembleHandle(RTMP_ADAPTER *pAd,STA_TR_ENTRY *pTrEntry , PNDIS_PACKET pPacket,UCHAR queIdx,PACKET_INFO packetInfo); +#endif + + +#ifdef DOT11_N_SUPPORT +VOID RTMP_BASetup( + IN RTMP_ADAPTER *pAd, + IN STA_TR_ENTRY *tr_entry, + IN UINT8 UserPriority); +#endif /* DOT11_N_SUPPORT */ + +VOID RTMPDeQueuePacket( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN bIntContext, + IN UCHAR QueIdx, + IN INT wcid, + IN INT Max_Tx_Packets); + +INT rtmp_tx_swq_init(RTMP_ADAPTER *pAd); +INT rtmp_tx_swq_exit(RTMP_ADAPTER *pAd, UCHAR wcid); + +INT rtmp_enq_req(RTMP_ADAPTER *pAd, PNDIS_PACKET pkt, UCHAR qidx, STA_TR_ENTRY *tr_entry, BOOLEAN FlgIsLocked,QUEUE_HEADER *pPktQueue); +INT rtmp_deq_req(RTMP_ADAPTER *pAd, INT tx_cnt, struct dequeue_info *info); +VOID rtmp_tx_swq_dump(RTMP_ADAPTER *pAd, INT qidx); +VOID rtmp_sta_txq_dump(RTMP_ADAPTER *pAd, STA_TR_ENTRY *tr_entry, INT qidx); + +INT rtmp_tx_burst_set(RTMP_ADAPTER *pAd); + +INT TxOPUpdatingAlgo(RTMP_ADAPTER *pAd); +#ifdef DYNAMIC_WMM +INT DynamicWMMDetectAction(RTMP_ADAPTER *pAd); +#endif +#ifdef INTERFERENCE_RA_SUPPORT +UINT is_interference_mode_on(RTMP_ADAPTER *pAd); +#endif +#ifdef MULTI_CLIENT_SUPPORT +UINT is_multiclient_mode_on(RTMP_ADAPTER *pAd); +#endif + +NDIS_STATUS RTMPFreeTXDRequest( + IN RTMP_ADAPTER *pAd, + IN UCHAR RingType, + IN UCHAR NumberRequired, + IN PUCHAR FreeNumberIs); + +NDIS_STATUS MlmeHardTransmit( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket, + IN BOOLEAN FlgDataQForce, + IN BOOLEAN FlgIsLocked, + IN BOOLEAN FlgIsCheckPS); + +NDIS_STATUS MlmeHardTransmitMgmtRing( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); + +#ifdef RTMP_MAC_PCI +NDIS_STATUS MlmeHardTransmitTxRing( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); + +NDIS_STATUS MlmeDataHardTransmit( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN PNDIS_PACKET pPacket); + +VOID ral_write_txd( + IN RTMP_ADAPTER *pAd, + IN TXD_STRUC *pTxD, + IN TX_BLK *txblk, + IN BOOLEAN bWIV, + IN UCHAR QSEL); +#endif /* RTMP_MAC_PCI */ + +USHORT RTMPCalcDuration( + IN RTMP_ADAPTER *pAd, + IN UCHAR Rate, + IN ULONG Size); + +VOID write_tmac_info( + IN RTMP_ADAPTER *pAd, + IN UCHAR *tmac_info, + IN MAC_TX_INFO *info, + IN HTTRANSMIT_SETTING *pTransmit); + + +VOID write_tmac_info_Data(RTMP_ADAPTER *pAd, UCHAR *buf, TX_BLK *pTxBlk); +VOID write_tmac_info_Cache(RTMP_ADAPTER *pAd, UCHAR *buf, TX_BLK *pTxBlk); + +VOID RTMPSuspendMsduTransmission( + IN RTMP_ADAPTER *pAd); + +VOID RTMPResumeMsduTransmission( + IN RTMP_ADAPTER *pAd); + +NDIS_STATUS MiniportMMRequest( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx, + IN UCHAR *pData, + IN UINT Length); + +VOID RTMPSendNullFrame( + IN RTMP_ADAPTER *pAd, + IN UCHAR TxRate, + IN BOOLEAN bQosNull, + IN USHORT PwrMgmt); + +VOID RTMPOffloadPm(RTMP_ADAPTER *pAd, UINT8 ucWlanIdx, UINT8 ucPmNumber, UINT8 ucPmState); + + + +BOOLEAN RTMPFreeTXDUponTxDmaDone( + IN RTMP_ADAPTER *pAd, + IN UCHAR QueIdx); +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) +BOOLEAN is_looping_packet( + IN RTMP_ADAPTER *pAd, + IN NDIS_PACKET *pPacket); +VOID set_wf_fwd_cb( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN struct wifi_dev *wdev); +#endif /* CONFIG_WIFI_PKT_FWD */ +#endif +BOOLEAN RTMPCheckEtherType( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN STA_TR_ENTRY *tr_entry, + IN struct wifi_dev *wdev, + OUT PUCHAR pUserPriority, + OUT PUCHAR pQueIdx, + OUT PUCHAR pWcid); + +VOID RTMP_RxPacketClassify( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk, + IN MAC_TABLE_ENTRY *pEntry); + + +BOOLEAN CheckICMPPacket(RTMP_ADAPTER *pAd, UCHAR *pSrcBuf, UINT8 Direction); + +VOID RTMPCckBbpTuning( + IN RTMP_ADAPTER *pAd, + IN UINT TxRate); + + +/* + MLME routines +*/ + +/* Asic/RF/BBP related functions */ +VOID AsicGetTxPowerOffset( + IN PRTMP_ADAPTER pAd, + IN PULONG TxPwr); + +VOID AsicGetAutoAgcOffsetForExternalTxAlc( + IN PRTMP_ADAPTER pAd, + IN PCHAR pDeltaPwr, + IN PCHAR pTotalDeltaPwr, + IN PCHAR pAgcCompensate, + IN PCHAR pDeltaPowerByBbpR1); + +VOID AsicExtraPowerOverMAC(RTMP_ADAPTER *pAd); + +#ifdef RTMP_TEMPERATURE_COMPENSATION +VOID AsicGetAutoAgcOffsetForTemperatureSensor( + IN PRTMP_ADAPTER pAd, + IN PCHAR pDeltaPwr, + IN PCHAR pTotalDeltaPwr, + IN PCHAR pAgcCompensate, + IN PCHAR pDeltaPowerByBbpR1); + +BOOLEAN LoadTempCompTableFromEEPROM( + IN struct _RTMP_ADAPTER *pAd, + IN const USHORT E2P_OFFSET_START, + IN const USHORT E2P_OFFSET_END, + OUT PUCHAR TssiTable, + IN const INT StartIndex, + IN const UINT32 TABLE_SIZE); +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + +#ifdef SINGLE_SKU +VOID GetSingleSkuDeltaPower( + IN RTMP_ADAPTER *pAd, + IN PCHAR pTotalDeltaPower, + INOUT PULONG pSingleSKUTotalDeltaPwr, + INOUT PUCHAR pSingleSKUBbpR1Offset); +#endif /* SINGLE_SKU*/ + +VOID AsicPercentageDeltaPower( + IN PRTMP_ADAPTER pAd, + IN CHAR Rssi, + INOUT PCHAR pDeltaPwr, + INOUT PCHAR pDeltaPowerByBbpR1); + +VOID AsicCompensatePowerViaBBP( + IN RTMP_ADAPTER *pAd, + INOUT CHAR *pTotalDeltaPower); + +VOID AsicAdjustTxPower(RTMP_ADAPTER *pAd); + +VOID AsicUpdateProtect( + IN RTMP_ADAPTER *pAd, + IN USHORT OperaionMode, + IN UCHAR SetMask, + IN BOOLEAN bDisableBGProtect, + IN BOOLEAN bNonGFExist); + +NTSTATUS MtCmdAsicUpdateProtect(RTMP_ADAPTER *pAd, PCmdQElmt CMDQelmt); +VOID AsicWtblSetRTS(RTMP_ADAPTER *pAd, UCHAR widx, BOOLEAN bEnable); + +#if defined(RTMP_BBP) && defined(RLT_BBP) +INT AsicRltSetTxStream(RTMP_ADAPTER *pAd, UCHAR opmode, BOOLEAN up); +#define ASIC_RLT_SET_TX_STREAM(_pAd, _opmode, _up) AsicRltSetTxStream(_pAd, _opmode, _up); +#else +#define ASIC_RLT_SET_TX_STREAM(_pAd, _opmode, _up) +#endif +INT AsicSetTxStream(RTMP_ADAPTER *pAd, UINT32 StreamNums); +INT AsicSetRxStream(RTMP_ADAPTER *pAd, UINT32 StreamNums); +INT AsicSetBW(RTMP_ADAPTER *pAd, INT bw); + +VOID AsicAntennaSelect(RTMP_ADAPTER *pAd, UCHAR Channel); + +VOID AsicResetBBPAgent(RTMP_ADAPTER *pAd); +VOID AsicBBPAdjust(RTMP_ADAPTER *pAd); + +VOID AsicSwitchChannel(RTMP_ADAPTER *pAd, UCHAR ch, BOOLEAN bScan); +VOID AsicLockChannel(RTMP_ADAPTER *pAd, UCHAR Channel); + +INT AsicSetChannel(RTMP_ADAPTER *pAd, UCHAR ch, UINT8 bw, UINT8 ext_ch, BOOLEAN bScan); + +INT AsicSetRxPath(RTMP_ADAPTER *pAd, UINT32 RxPathSel); + +#ifdef CONFIG_ATE +INT AsicSetTxTonePower(RTMP_ADAPTER *pAd, INT dec0, INT dec1); +INT AsicSetRfFreqOffset(RTMP_ADAPTER *pAd, UINT32 FreqOffset); +INT AsicSetTSSI(RTMP_ADAPTER *pAd, UINT32 bOnOff, UCHAR WFSelect); +INT AsicSetDPD(RTMP_ADAPTER *pAd, UINT32 bOnOff, UCHAR WFSelect); +#ifdef CONFIG_QA +UINT32 AsicGetRxStat(RTMP_ADAPTER *pAd, UINT type); +#endif /* CONFIG_QA */ +INT AsicSetTxToneTest(RTMP_ADAPTER *pAd, UINT32 bOnOff, UCHAR Type); +INT AsicStartContinousTx(RTMP_ADAPTER *pAd, UINT32 PhyMode, UINT32 BW, UINT32 PriCh, UINT32 Mcs, UINT32 WFSel); +INT AsicStopContinousTx(RTMP_ADAPTER *pAd); +#endif /* CONFIG_ATE */ +#ifndef CONFIG_ATE +#ifndef CONFIG_QA +#endif +#endif + + +INT AsicSetDevMac(RTMP_ADAPTER *pAd, UCHAR *addr, UCHAR omac_idx); +VOID AsicSetBssid(RTMP_ADAPTER *pAd, UCHAR *pBssid, UCHAR curr_bssid_idx); + +VOID AsicDelWcidTab(RTMP_ADAPTER *pAd, UCHAR Wcid); + +#ifdef MAC_APCLI_SUPPORT +VOID AsicSetApCliBssid(RTMP_ADAPTER *pAd, UCHAR *pBssid, UCHAR index); +#endif /* MAC_APCLI_SUPPORT */ + +INT AsicSetRxFilter(RTMP_ADAPTER *pAd); +INT AsicClearRxFilter(RTMP_ADAPTER *pAd); + +#ifdef DOT11_N_SUPPORT +INT AsicSetRDG(RTMP_ADAPTER *pAd, BOOLEAN bEnable); +#ifdef MT_MAC +INT AsicWtblSetRDG(RTMP_ADAPTER *pAd, BOOLEAN bEnable); +INT AsicUpdateTxOP(RTMP_ADAPTER *pAd, UINT32 ac_num, UINT32 txop_val); +#endif /* MT_MAC */ +#endif /* DOT11_N_SUPPORT */ + +INT AsicSetPreTbtt(RTMP_ADAPTER *pAd, BOOLEAN enable); +INT AsicSetGPTimer(RTMP_ADAPTER *pAd, BOOLEAN enable, UINT32 timeout); +INT AsicSetChBusyStat(RTMP_ADAPTER *pAd, BOOLEAN enable); + +INT AsicGetTsfTime(RTMP_ADAPTER *pAd, UINT32 *high_part, UINT32 *low_part); + +VOID AsicDisableSync(RTMP_ADAPTER *pAd); +VOID AsicEnableBssSync(RTMP_ADAPTER *pAd, USHORT BeaconPeriod); +VOID AsicEnableApBssSync(RTMP_ADAPTER *pAd, USHORT BeaconPeriod); +VOID AsicEnableIbssSync(RTMP_ADAPTER *pAd); + +#define WMM_PARAM_TXOP 0 +#define WMM_PARAM_AIFSN 1 +#define WMM_PARAM_CWMIN 2 +#define WMM_PARAM_CWMAX 3 +#define WMM_PARAM_ALL 4 + +#define WMM_PARAM_AC_0 0 +#define WMM_PARAM_AC_1 1 +#define WMM_PARAM_AC_2 2 +#define WMM_PARAM_AC_3 3 +UINT32 AsicGetWmmParam(RTMP_ADAPTER *pAd, UINT32 ac, UINT32 type); +INT AsicSetWmmParam(RTMP_ADAPTER *pAd, UINT ac, UINT type, UINT val); + +VOID AsicSetEdcaParm(RTMP_ADAPTER *pAd, PEDCA_PARM pEdcaParm); + +#define TX_RTY_CFG_RTY_LIMIT_SHORT 0x1 +#define TX_RTY_CFG_RTY_LIMIT_LONG 0x2 +INT AsicSetRetryLimit(RTMP_ADAPTER *pAd, UINT32 type, UINT32 limit); + +UINT32 AsicGetRetryLimit(RTMP_ADAPTER *pAd, UINT32 type); + +VOID AsicSetSlotTime(RTMP_ADAPTER *pAd, BOOLEAN bUseShortSlotTime, UCHAR channel); +INT AsicSetMacMaxLen(RTMP_ADAPTER *pAd); + +VOID AsicAddSharedKeyEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR BssIdx, + IN UCHAR KeyIdx, + IN PCIPHER_KEY pCipherKey); + +VOID AsicRemoveSharedKeyEntry(RTMP_ADAPTER *pAd, UCHAR BssIdx, UCHAR KeyIdx); + +VOID AsicUpdateWCIDIVEIV(RTMP_ADAPTER *pAd, USHORT WCID, ULONG uIV, ULONG uEIV); +VOID AsicUpdateRxWCIDTable(RTMP_ADAPTER *pAd, USHORT WCID, UCHAR *pAddr); +VOID AsicUpdateBASession(RTMP_ADAPTER *pAd, UCHAR wcid, UCHAR tid, UINT16 sn, UCHAR basize, BOOLEAN isAdd, INT ses_type); +UINT16 AsicGetTidSn(RTMP_ADAPTER *pAd, UCHAR Wcid, UCHAR Tid); + +VOID AsicUpdateWcidAttributeEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR BssIdx, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN UINT8 Wcid, + IN UINT8 KeyTabFlag); + +VOID AsicAddPairwiseKeyEntry(RTMP_ADAPTER *pAd, UCHAR WCID, PCIPHER_KEY pCipherKey); +VOID AsicRemovePairwiseKeyEntry(RTMP_ADAPTER *pAd, UCHAR Wcid); + +#ifdef MT_MAC +VOID CmdProcAddRemoveKey( + IN PRTMP_ADAPTER pAd, + IN UCHAR AddRemove, + IN UCHAR BssIdx, + IN UCHAR key_idx, + IN UCHAR Wcid, + IN UCHAR KeyTabFlag, + IN PCIPHER_KEY pCipherKey, + IN PUCHAR PeerAddr); +#endif + +#ifdef MT_MAC +VOID AsicSetSMPS(RTMP_ADAPTER *pAd, UCHAR wcid, UCHAR smps); +#endif /* MT_MAC */ + +#ifdef MCS_LUT_SUPPORT +VOID asic_mcs_lut_update(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry); +#endif /* MCS_LUT_SUPPORT */ + +#ifdef MT_MAC +VOID AsicRssiUpdate(RTMP_ADAPTER *pAd); +VOID AsicRcpiReset(RTMP_ADAPTER *pAd, UCHAR ucWcid); + +VOID AsicTxCntUpdate(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, MT_TX_COUNTER *pTxInfo); +#endif /* MT_MAC */ + +#ifdef CONFIG_AP_SUPPORT +VOID AsicSetMbssMode(RTMP_ADAPTER *pAd, UCHAR NumOfBcns); +#endif /* CONFIG_AP_SUPPORT */ + +BOOLEAN AsicSendCommandToMcu( + IN RTMP_ADAPTER *pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN in_atomic); + +BOOLEAN AsicSendCmdToMcuAndWait( + IN RTMP_ADAPTER *pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN in_atomic); + +BOOLEAN AsicSendCommandToMcuBBP( + IN RTMP_ADAPTER *pAd, + IN UCHAR Command, + IN UCHAR Token, + IN UCHAR Arg0, + IN UCHAR Arg1, + IN BOOLEAN FlgIsNeedLocked); + + +#ifdef RTMP_MAC_PCI +BOOLEAN AsicCheckCommanOk(RTMP_ADAPTER *pAd, UCHAR Command); +#endif /* RTMP_MAC_PCI */ + +#ifdef WAPI_SUPPORT +VOID AsicUpdateWAPIPN( + IN RTMP_ADAPTER *pAd, + IN USHORT WCID, + IN ULONG pn_low, + IN ULONG pn_high); +#endif /* WAPI_SUPPORT */ + + +#ifdef STREAM_MODE_SUPPORT +UINT32 StreamModeRegVal( + IN RTMP_ADAPTER *pAd); + +VOID AsicSetStreamMode( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pMacAddr, + IN INT chainIdx, + IN BOOLEAN bEnabled); + +VOID RtmpStreamModeInit( + IN RTMP_ADAPTER *pAd); + +/* + Update the Tx chain address + Parameters + pAd: The adapter data structure + pMacAddress: The MAC address of the peer STA + + Return Value: + None +*/ +VOID AsicUpdateTxChainAddress( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pMacAddress); + +INT Set_StreamMode_Proc( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *arg); + +INT Set_StreamModeMac_Proc( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *arg); + +INT Set_StreamModeMCS_Proc( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *arg); +#endif /* STREAM_MODE_SUPPORT */ + + +VOID MacAddrRandomBssid( + IN RTMP_ADAPTER *pAd, + OUT PUCHAR pAddr); + +VOID MgtMacHeaderInit( + IN RTMP_ADAPTER *pAd, + INOUT HEADER_802_11 *pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN UCHAR *pDA, + IN UCHAR *pSA, + IN UCHAR *pBssid); + +VOID MgtMacHeaderInitExt( + IN RTMP_ADAPTER *pAd, + IN OUT PHEADER_802_11 pHdr80211, + IN UCHAR SubType, + IN UCHAR ToDs, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN PUCHAR pBssid); + +VOID MlmeRadioOff( + IN RTMP_ADAPTER *pAd); + +VOID MlmeRadioOn( + IN RTMP_ADAPTER *pAd); + + +VOID BssTableInit( + IN BSS_TABLE *Tab); + +#ifdef DOT11_N_SUPPORT +VOID BATableInit( + IN RTMP_ADAPTER *pAd, + IN BA_TABLE *Tab); + +VOID BATableExit( + IN RTMP_ADAPTER *pAd); +#endif /* DOT11_N_SUPPORT */ + +ULONG BssTableSearch( + IN BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN UCHAR Channel); + +ULONG BssSsidTableSearch( + IN BSS_TABLE *Tab, + IN PUCHAR pBssid, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR Channel); + +ULONG BssTableSearchWithSSID( + IN BSS_TABLE *Tab, + IN PUCHAR Bssid, + IN PUCHAR pSsid, + IN UCHAR SsidLen, + IN UCHAR Channel); + +ULONG BssSsidTableSearchBySSID( + IN BSS_TABLE *Tab, + IN PUCHAR pSsid, + IN UCHAR SsidLen); + +VOID BssTableDeleteEntry( + IN OUT PBSS_TABLE pTab, + IN PUCHAR pBssid, + IN UCHAR Channel); + +ULONG BssTableSetEntry( + IN RTMP_ADAPTER *pAd, + OUT BSS_TABLE *Tab, + IN BCN_IE_LIST *ie_list, + IN CHAR Rssi, + IN USHORT LengthVIE, + IN PNDIS_802_11_VARIABLE_IEs pVIE +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + , + IN UCHAR Snr0, + IN UCHAR Snr1 +#endif +); + + +#ifdef DOT11_N_SUPPORT +VOID BATableInsertEntry( + IN RTMP_ADAPTER *pAd, + IN USHORT Aid, + IN USHORT TimeOutValue, + IN USHORT StartingSeq, + IN UCHAR TID, + IN UCHAR BAWinSize, + IN UCHAR OriginatorStatus, + IN BOOLEAN IsRecipient); + +#ifdef DOT11N_DRAFT3 +VOID Bss2040CoexistTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + + +VOID TriEventInit( + IN RTMP_ADAPTER *pAd); + +INT TriEventTableSetEntry( + IN RTMP_ADAPTER *pAd, + OUT TRIGGER_EVENT_TAB *Tab, + IN PUCHAR pBssid, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN UCHAR RegClass, + IN UCHAR ChannelNo); + +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +#ifndef WH_EZ_SETUP +VOID BssTableSsidSort( + IN RTMP_ADAPTER *pAd, + OUT BSS_TABLE *OutTab, + IN CHAR Ssid[], + IN UCHAR SsidLen); +#else +VOID BssTableSsidSort( + IN RTMP_ADAPTER *pAd, + IN struct wifi_dev *wdev, + OUT BSS_TABLE *OutTab, + IN CHAR Ssid[], + IN UCHAR SsidLen); +#endif +VOID BssTableSortByRssi( + IN OUT BSS_TABLE *OutTab, + IN BOOLEAN isInverseOrder); + +VOID BssCipherParse(BSS_ENTRY *pBss); + +NDIS_STATUS MlmeQueueInit( + IN RTMP_ADAPTER *pAd, +#ifdef EAPOL_QUEUE_SUPPORT + IN EAP_MLME_QUEUE *EAP_Queue, +#endif /* EAPOL_QUEUE_SUPPORT */ + IN MLME_QUEUE *Queue); + + +VOID MlmeQueueDestroy( +#ifdef EAPOL_QUEUE_SUPPORT + IN EAP_MLME_QUEUE *EAP_Queue, +#endif /* EAPOL_QUEUE_SUPPORT */ + IN MLME_QUEUE *Queue); + +#ifdef EAPOL_QUEUE_SUPPORT +BOOLEAN EAPMlmeEnqueue( + IN PRTMP_ADAPTER pAd, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg, + IN ULONG Priv); +#endif /* EAPOL_QUEUE_SUPPORT */ + +BOOLEAN MlmeEnqueue( + IN RTMP_ADAPTER *pAd, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg, + IN ULONG Priv); + +BOOLEAN MlmeEnqueueForRecv( + IN RTMP_ADAPTER *pAd, + IN ULONG Wcid, + IN struct raw_rssi_info *rssi_info, +#if defined(CUSTOMER_DCC_FEATURE) || defined(NEIGHBORING_AP_STAT) + IN UCHAR Snr0, + IN UCHAR Snr1, +#endif + IN ULONG MsgLen, + IN PVOID Msg, + IN UCHAR OpMode); + +#ifdef WSC_INCLUDED +BOOLEAN MlmeEnqueueForWsc( + IN RTMP_ADAPTER *pAd, + IN ULONG eventID, + IN LONG senderID, + IN ULONG Machine, + IN ULONG MsgType, + IN ULONG MsgLen, + IN VOID *Msg); +#endif /* WSC_INCLUDED */ + +#ifdef EAPOL_QUEUE_SUPPORT +BOOLEAN EAPMlmeDequeue( + IN EAP_MLME_QUEUE *Queue, + OUT MLME_QUEUE_ELEM **Elem); +#endif /* EAPOL_QUEUE_SUPPORT */ + +BOOLEAN MlmeDequeue( + IN MLME_QUEUE *Queue, + OUT MLME_QUEUE_ELEM **Elem); + +VOID MlmeRestartStateMachine( + IN RTMP_ADAPTER *pAd); + +#ifdef EAPOL_QUEUE_SUPPORT +BOOLEAN EAPMlmeQueueEmpty( + IN EAP_MLME_QUEUE *Queue); +#endif /* EAPOL_QUEUE_SUPPORT */ + +BOOLEAN MlmeQueueEmpty( + IN MLME_QUEUE *Queue); + +#ifdef EAPOL_QUEUE_SUPPORT +BOOLEAN EAPMlmeQueueFull( + IN EAP_MLME_QUEUE *Queue); +#endif /* EAPOL_QUEUE_SUPPORT */ + +BOOLEAN MlmeQueueFull( + IN MLME_QUEUE *Queue, + IN UCHAR SendId); + +BOOLEAN MsgTypeSubst( + IN RTMP_ADAPTER *pAd, + IN PFRAME_802_11 pFrame, + OUT INT *Machine, + OUT INT *MsgType); + +VOID StateMachineInit( + IN STATE_MACHINE *Sm, + IN STATE_MACHINE_FUNC Trans[], + IN ULONG StNr, + IN ULONG MsgNr, + IN STATE_MACHINE_FUNC DefFunc, + IN ULONG InitState, + IN ULONG Base); + +VOID StateMachineSetAction( + IN STATE_MACHINE *S, + IN ULONG St, + ULONG Msg, + IN STATE_MACHINE_FUNC F); + +VOID StateMachinePerformAction( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem, + IN ULONG CurrState); + +VOID Drop( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID AssocStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID ReassocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID AssocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID DisassocTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +/*---------------------------------------------- */ +VOID MlmeDisassocReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeAssocReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeReassocReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDisassocReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAssocRspAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerReassocRspAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerDisassocAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID DisassocTimeoutAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID AssocTimeoutAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ReassocTimeoutAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID Cls3errAction( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pAddr); + +VOID InvalidStateWhenAssoc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenReassoc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenDisassociate( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + + +VOID ComposePsPoll( + IN RTMP_ADAPTER *pAd); + +VOID ComposeNullFrame( + IN RTMP_ADAPTER *pAd); + +VOID AssocPostProc( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pAddr2, + IN USHORT CapabilityInfo, + IN USHORT Aid, + IN UCHAR SupRate[], + IN UCHAR SupRateLen, + IN UCHAR ExtRate[], + IN UCHAR ExtRateLen, + IN PEDCA_PARM pEdcaParm, + IN IE_LISTS *ie_list, + IN HT_CAPABILITY_IE *pHtCapability, + IN UCHAR HtCapabilityLen, + IN ADD_HT_INFO_IE *pAddHtInfo); + +VOID AuthStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN PSTATE_MACHINE sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID AuthTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID MlmeAuthReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAuthRspAtSeq2Action( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAuthRspAtSeq4Action( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID AuthTimeoutAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID Cls2errAction( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pAddr); + +VOID MlmeDeauthReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenAuth( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +/*============================================= */ + +VOID AuthRspStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN PSTATE_MACHINE Sm, + IN STATE_MACHINE_FUNC Trans[]); + +VOID PeerDeauthAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerAuthSimpleRspGenAndSend( + IN RTMP_ADAPTER *pAd, + IN PHEADER_802_11 pHdr80211, + IN USHORT Alg, + IN USHORT Seq, + IN USHORT Reason, + IN USHORT Status); + +/* */ +/* Private routines in dls.c */ +/* */ +#ifdef CONFIG_AP_SUPPORT +#endif /* CONFIG_AP_SUPPORT */ + + + +BOOLEAN PeerProbeReqSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PEER_PROBE_REQ_PARAM *Param); + +/*======================================== */ + +VOID SyncStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID BeaconTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID ScanTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID MlmeScanReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenScan( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenJoin( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID InvalidStateWhenStart( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeacon( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID EnqueueProbeRequest( + IN RTMP_ADAPTER *pAd); + +BOOLEAN ScanRunning( + IN RTMP_ADAPTER *pAd); +/*========================================= */ + +VOID MlmeCntlInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID MlmeCntlMachinePerformAction( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *S, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlIdleProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlOidScanProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlOidSsidProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM * Elem); + +VOID CntlOidRTBssidProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM * Elem); + +VOID CntlMlmeRoamingProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM * Elem); + +VOID CntlWaitDisassocProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitJoinProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitReassocProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitStartProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitAuthProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitAuthProc2( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID CntlWaitAssocProc( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + + +#ifdef DOT11V_WNM_SUPPORT +#ifdef CONFIG_AP_SUPPORT +VOID APPeerWNMBTMQueryAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerWNMBTMRspAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID APPeerWNMDMSReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +#endif /* CONFIG_AP_SUPPORT */ + +#endif /* DOT11V_WNM_SUPPORT */ + +VOID LinkUp( + IN RTMP_ADAPTER *pAd, + IN UCHAR BssType); + +VOID LinkDown( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN IsReqFromAP); + +VOID IterateOnBssTab( + IN RTMP_ADAPTER *pAd); + +VOID IterateOnBssTab2( + IN RTMP_ADAPTER *pAd);; + +VOID JoinParmFill( + IN RTMP_ADAPTER *pAd, + IN OUT MLME_JOIN_REQ_STRUCT *JoinReq, + IN ULONG BssIdx); + +VOID AssocParmFill( + IN RTMP_ADAPTER *pAd, + IN OUT MLME_ASSOC_REQ_STRUCT *AssocReq, + IN PUCHAR pAddr, + IN USHORT CapabilityInfo, + IN ULONG Timeout, + IN USHORT ListenIntv); + +VOID ScanParmFill( + IN RTMP_ADAPTER *pAd, + IN OUT MLME_SCAN_REQ_STRUCT *ScanReq, + IN RTMP_STRING Ssid[], + IN UCHAR SsidLen, + IN UCHAR BssType, + IN UCHAR ScanType); + +VOID DisassocParmFill( + IN RTMP_ADAPTER *pAd, + IN OUT MLME_DISASSOC_REQ_STRUCT *DisassocReq, + IN PUCHAR pAddr, + IN USHORT Reason); + +VOID StartParmFill( + IN RTMP_ADAPTER *pAd, + IN OUT MLME_START_REQ_STRUCT *StartReq, + IN CHAR Ssid[], + IN UCHAR SsidLen); + +VOID AuthParmFill( + IN RTMP_ADAPTER *pAd, + IN OUT MLME_AUTH_REQ_STRUCT *AuthReq, + IN PUCHAR pAddr, + IN USHORT Alg); + +VOID EnqueuePsPoll( + IN RTMP_ADAPTER *pAd); + +VOID EnqueueBeaconFrame( + IN RTMP_ADAPTER *pAd); + +VOID MlmeJoinReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeScanReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeStartReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeForceJoinReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeForceScanReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ScanTimeoutAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID BeaconTimeoutAtJoinAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeaconAtScanAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeaconAtJoinAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerBeacon( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerProbeReqAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID ScanNextChannel( + IN RTMP_ADAPTER *pAd, + IN UCHAR OpMode, + IN struct wifi_dev *pwdev); + + +BOOLEAN MlmeScanReqSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT UCHAR *BssType, + OUT CHAR ssid[], + OUT UCHAR *SsidLen, + OUT UCHAR *ScanType +#ifdef CONFIG_AP_SUPPORT +#endif +); + + +BOOLEAN PeerBeaconAndProbeRspSanity_Old( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN UCHAR MsgChannel, + OUT PUCHAR pAddr2, + OUT PUCHAR pBssid, + OUT CHAR Ssid[], + OUT UCHAR *pSsidLen, + OUT UCHAR *pBssType, + OUT USHORT *pBeaconPeriod, + OUT UCHAR *pChannel, + OUT UCHAR *pNewChannel, + OUT LARGE_INTEGER *pTimestamp, + OUT CF_PARM *pCfParm, + OUT USHORT *pAtimWin, + OUT USHORT *pCapabilityInfo, + OUT UCHAR *pErp, + OUT UCHAR *pDtimCount, + OUT UCHAR *pDtimPeriod, + OUT UCHAR *pBcastFlag, + OUT UCHAR *pMessageToMe, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT UCHAR *pCkipFlag, + OUT UCHAR *pAironetCellPowerLimit, + OUT PEDCA_PARM pEdcaParm, + OUT PQBSS_LOAD_PARM pQbssLoad, + OUT PQOS_CAPABILITY_PARM pQosCapability, + OUT ULONG *pRalinkIe, + OUT UCHAR *pHtCapabilityLen, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT EXT_CAP_INFO_ELEMENT *pExtCapInfo, + OUT UCHAR *AddHtInfoLen, + OUT ADD_HT_INFO_IE *AddHtInfo, + OUT UCHAR *NewExtChannel, + OUT USHORT *LengthVIE, + OUT PNDIS_802_11_VARIABLE_IEs pVIE); + + +BOOLEAN PeerBeaconAndProbeRspSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN UCHAR MsgChannel, + OUT BCN_IE_LIST *ie_list, + OUT USHORT *LengthVIE, + OUT PNDIS_802_11_VARIABLE_IEs pVIE, + IN BOOLEAN bGetDtim, + IN BOOLEAN bFromBeaconReport); + + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 +BOOLEAN PeerBeaconAndProbeRspSanity2( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + IN OVERLAP_BSS_SCAN_IE *BssScan, + OUT UCHAR *RegClass); +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + +BOOLEAN PeerAddBAReqActionSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2); + +BOOLEAN PeerAddBARspActionSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *pMsg, + IN ULONG MsgLen); + +BOOLEAN PeerDelBAActionSanity( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN VOID *pMsg, + IN ULONG MsgLen); + +BOOLEAN MlmeAssocReqSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pApAddr, + OUT USHORT *CapabilityInfo, + OUT ULONG *Timeout, + OUT USHORT *ListenIntv); + +BOOLEAN MlmeAuthReqSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT ULONG *Timeout, + OUT USHORT *Alg); + +BOOLEAN MlmeStartReqSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT CHAR Ssid[], + OUT UCHAR *Ssidlen); + +BOOLEAN PeerAuthSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr, + OUT USHORT *Alg, + OUT USHORT *Seq, + OUT USHORT *Status, + OUT CHAR ChlgText[]); + +BOOLEAN PeerAssocRspSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *pMsg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *pCapabilityInfo, + OUT USHORT *pStatus, + OUT USHORT *pAid, + OUT UCHAR SupRate[], + OUT UCHAR *pSupRateLen, + OUT UCHAR ExtRate[], + OUT UCHAR *pExtRateLen, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT ADD_HT_INFO_IE *pAddHtInfo, /* AP might use this additional ht info IE */ + OUT UCHAR *pHtCapabilityLen, + OUT UCHAR *pAddHtInfoLen, + OUT UCHAR *pNewExtChannelOffset, + OUT PEDCA_PARM pEdcaParm, + OUT EXT_CAP_INFO_ELEMENT *pExtCapInfo, + OUT UCHAR *pCkipFlag, + OUT IE_LISTS *ie_list); + +BOOLEAN PeerDisassocSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2, + OUT USHORT *Reason); + +BOOLEAN PeerDeauthSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr1, + OUT PUCHAR pAddr2, + OUT PUCHAR pAddr3, + OUT USHORT *Reason); + +BOOLEAN GetTimBit( + IN CHAR *Ptr, + IN USHORT Aid, + OUT UCHAR *TimLen, + OUT UCHAR *BcastFlag, + OUT UCHAR *DtimCount, + OUT UCHAR *DtimPeriod, + OUT UCHAR *MessageToMe); + +UCHAR ChannelSanity( + IN RTMP_ADAPTER *pAd, + IN UCHAR channel); + +NDIS_802_11_NETWORK_TYPE NetworkTypeInUseSanity( + IN BSS_ENTRY *pBss); + +BOOLEAN MlmeDelBAReqSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen); + +BOOLEAN MlmeAddBAReqSanity( + IN RTMP_ADAPTER *pAd, + IN VOID *Msg, + IN ULONG MsgLen, + OUT PUCHAR pAddr2); + +ULONG MakeOutgoingFrame( + OUT UCHAR *Buffer, + OUT ULONG *Length, ...); + +UCHAR RandomByte( + IN RTMP_ADAPTER *pAd); + +UCHAR RandomByte2( + IN RTMP_ADAPTER *pAd); + +VOID AsicUpdateAutoFallBackTable(RTMP_ADAPTER *pAd, UCHAR *pTxRate); +INT AsicSetAutoFallBack(RTMP_ADAPTER *pAd, BOOLEAN enable); +INT AsicAutoFallbackInit(RTMP_ADAPTER *pAd); + + + +VOID MlmePeriodicExecTimer( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +NTSTATUS MlmePeriodicExec(IN PRTMP_ADAPTER pAd, IN PCmdQElmt CMDQelmt); + +VOID LinkDownExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID LinkUpExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID STAMlmePeriodicExec( + RTMP_ADAPTER *pAd); + +VOID MlmeAutoScan( + IN RTMP_ADAPTER *pAd); + +VOID MlmeAutoReconnectLastSSID( + IN RTMP_ADAPTER *pAd); + +BOOLEAN MlmeValidateSSID( + IN PUCHAR pSsid, + IN UCHAR SsidLen); + +VOID MlmeCheckForRoaming( + IN RTMP_ADAPTER *pAd, + IN ULONG Now32); + +BOOLEAN MlmeCheckForFastRoaming( + IN RTMP_ADAPTER *pAd); + + +VOID MlmeCalculateChannelQuality( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pMacEntry, + IN ULONG Now); + +VOID MlmeCheckPsmChange( + IN RTMP_ADAPTER *pAd, + IN ULONG Now32); + +VOID MlmeSetPsmBit( + IN RTMP_ADAPTER *pAd, + IN USHORT psm); + +VOID RTMPSetEnterPsmNullBit(IN PPWR_MGMT_STRUCT pPwrMgmt); + +VOID RTMPClearEnterPsmNullBit(IN PPWR_MGMT_STRUCT pPwrMgmt); + +BOOLEAN RTMPEnterPsmNullBitStatus(IN PPWR_MGMT_STRUCT pPwrMgmt); + + +VOID MlmeSetTxPreamble( + IN RTMP_ADAPTER *pAd, + IN USHORT TxPreamble); + +#ifdef DYNAMIC_RX_RATE_ADJ +VOID UpdateBasicRateBitmap( + IN RTMP_ADAPTER *pAd, + IN UCHAR apidx); +#else +VOID UpdateBasicRateBitmap( + IN RTMP_ADAPTER *pAd); +#endif /* DYNAMIC_RX_RATE_ADJ */ + +VOID MlmeUpdateTxRates( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN bLinkUp, + IN UCHAR apidx); + +#ifdef DOT11_N_SUPPORT +VOID MlmeUpdateHtTxRates( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx); +#endif /* DOT11_N_SUPPORT */ + +VOID RTMPCheckRates( + IN RTMP_ADAPTER *pAd, + IN OUT UCHAR SupRate[], + IN OUT UCHAR *SupRateLen); + +BOOLEAN RTMPCheckHt( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + INOUT HT_CAPABILITY_IE *pHtCapability, + INOUT ADD_HT_INFO_IE *pAddHtInfo); + +#ifdef DOT11_VHT_AC +BOOLEAN RTMPCheckVht( + IN RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN VHT_CAP_IE *vht_cap, + IN VHT_OP_IE *vht_op); +#endif /* DOT11_VHT_AC */ + +VOID RTMPUpdateMlmeRate( + IN RTMP_ADAPTER *pAd); + +CHAR RTMPMaxRssi( + IN RTMP_ADAPTER *pAd, + IN CHAR Rssi0, + IN CHAR Rssi1, + IN CHAR Rssi2); + +CHAR RTMPAvgRssi( + IN RTMP_ADAPTER *pAd, + IN RSSI_SAMPLE *pRssi); + +CHAR RTMPMinRssi( + IN RTMP_ADAPTER *pAd, + IN CHAR Rssi0, + IN CHAR Rssi1, + IN CHAR Rssi2); + + +CHAR RTMPMinSnr( + IN RTMP_ADAPTER *pAd, + IN CHAR Snr0, + IN CHAR Snr1); + +VOID AsicSetRxAnt( + IN RTMP_ADAPTER *pAd, + IN UCHAR Ant); + +#ifdef MICROWAVE_OVEN_SUPPORT +INT Set_MO_FalseCCATh_Proc( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *arg); + +VOID AsicMeasureFalseCCA( + IN RTMP_ADAPTER *pAd +); + +VOID AsicMitigateMicrowave( + IN RTMP_ADAPTER *pAd +); +#endif /* MICROWAVE_OVEN_SUPPORT */ + +#ifdef RTMP_EFUSE_SUPPORT +INT set_eFuseGetFreeBlockCount_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_eFusedump_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_eFuseLoadFromBin_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +UCHAR eFuseReadRegisters(RTMP_ADAPTER *pAd, USHORT Offset, UINT16 Length, UINT16* pData); +VOID EfusePhysicalReadRegisters(RTMP_ADAPTER *pAd, USHORT Offset, USHORT Length, USHORT* pData); + +int RtmpEfuseSupportCheck(RTMP_ADAPTER *pAd); + +#ifdef CONFIG_ATE +INT Set_LoadEepromBufferFromEfuse_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_eFuseBufferModeWriteBack_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_BinModeWriteBack_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* CONFIG_ATE */ +#endif /* RTMP_EFUSE_SUPPORT */ + + + + +VOID AsicEvaluateRxAnt(RTMP_ADAPTER *pAd); + +VOID AsicRxAntEvalTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID APSDPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID RTMPSetPiggyBack(RTMP_ADAPTER *pAd, BOOLEAN bPiggyBack); + +BOOLEAN RTMPCheckEntryEnableAutoRateSwitch( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry); + +UCHAR RTMPStaFixedTxMode( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry); + +VOID RTMPUpdateLegacyTxSetting( + IN UCHAR fixed_tx_mode, + IN PMAC_TABLE_ENTRY pEntry); + +BOOLEAN RTMPAutoRateSwitchCheck(RTMP_ADAPTER *pAd); + + + +#ifdef RTMP_TEMPERATURE_COMPENSATION +VOID InitLookupTable(RTMP_ADAPTER *pAd); +#endif /* RTMP_TEMPERATURE_COMPENSATION */ + +VOID MlmeHalt(RTMP_ADAPTER *pAd); +NDIS_STATUS MlmeInit(RTMP_ADAPTER *pAd); + +VOID MlmeResetRalinkCounters(RTMP_ADAPTER *pAd); + +VOID BuildChannelList(RTMP_ADAPTER *pAd); +UCHAR FirstChannel(RTMP_ADAPTER *pAd); +UCHAR NextChannel(RTMP_ADAPTER *pAd, UCHAR channel); + +UCHAR RTMPFindScanChannel( + IN PRTMP_ADAPTER pAd, + IN UINT8 LastScanChannel); + +VOID ChangeToCellPowerLimit(RTMP_ADAPTER *pAd, UCHAR AironetCellPowerLimit); + + +VOID RTMPInitMICEngine( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pKey, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN UCHAR UserPriority, + IN PUCHAR pMICKey); + +BOOLEAN RTMPTkipCompareMICValue( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pSrc, + IN PUCHAR pDA, + IN PUCHAR pSA, + IN PUCHAR pMICKey, + IN UCHAR UserPriority, + IN UINT Len); + +VOID RTMPCalculateMICValue( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN PUCHAR pEncap, + IN PCIPHER_KEY pKey, + IN UCHAR apidx); + +VOID RTMPTkipAppendByte( TKIP_KEY_INFO *pTkip, UCHAR uChar); +VOID RTMPTkipAppend(TKIP_KEY_INFO *pTkip, UCHAR *pSrc, UINT nBytes); +VOID RTMPTkipGetMIC(TKIP_KEY_INFO *pTkip); + + +INT RT_CfgSetCountryRegion( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *arg, + IN INT band); + +INT RT_CfgSetWirelessMode(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +RT_802_11_PHY_MODE wmode_2_cfgmode(UCHAR wmode); +UCHAR cfgmode_2_wmode(UCHAR cfg_mode); +UCHAR *wmode_2_str(UCHAR wmode); + +#ifdef CONFIG_AP_SUPPORT +#ifdef MBSS_SUPPORT +INT RT_CfgSetMbssWirelessMode(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* MBSS_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +INT RT_CfgSetShortSlot(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT RT_CfgSetWepKey( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *keyString, + IN CIPHER_KEY *pSharedKey, + IN INT keyIdx); + +INT RT_CfgSetWPAPSKKey( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *keyString, + IN INT keyStringLen, + IN UCHAR *pHashStr, + IN INT hashStrLen, + OUT PUCHAR pPMKBuf); + +INT RT_CfgSetFixedTxPhyMode(RTMP_STRING *arg); +INT RT_CfgSetMacAddress(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT RT_CfgSetTxMCSProc(RTMP_STRING *arg, BOOLEAN *pAutoRate); +INT RT_CfgSetAutoFallBack(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef WSC_INCLUDED +INT RT_CfgSetWscPinCode( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *pPinCodeStr, + OUT PWSC_CTRL pWscControl); +#endif /* WSC_INCLUDED */ + +INT Set_Antenna_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + + +#ifdef HW_TX_RATE_LOOKUP_SUPPORT +INT Set_HwTxRateLookUp_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* HW_TX_RATE_LOOKUP_SUPPORT */ + +#ifdef MULTI_MAC_ADDR_EXT_SUPPORT +INT Set_EnMultiMacAddrExt_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_MultiMacAddrExt_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* MULTI_MAC_ADDR_EXT_SUPPORT */ + +INT set_tssi_enable(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef CONFIG_WIFI_TEST +INT set_pbf_loopback(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_pbf_rx_drop(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif + +#ifdef DYNAMIC_WMM +INT SetDynamicWMM(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* DYNAMIC_WMM */ +#ifdef INTERFERENCE_RA_SUPPORT +INT SetInterfRA(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif + +#ifdef MT_MAC +INT set_get_fid(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_fw_log(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT SetManualTxOP(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_themal_sensor(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_rx_pspoll_filter_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT SetManualTxOPThreshold(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT SetManualTxOPUpBound(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT SetManualTxOPLowBound(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif + +#ifdef RTMP_MAC_PCI +INT Set_PDMAWatchDog_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif +INT SetPSEWatchDog_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef TXRXCR_DEBUG_SUPPORT +INT SetTxRxCr_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* TXRXCR_DEBUG_SUPPORT */ + + +NDIS_STATUS RTMPWPARemoveKeyProc( + IN RTMP_ADAPTER *pAd, + IN PVOID pBuf); + +VOID RTMPWPARemoveAllKeys( + IN RTMP_ADAPTER *pAd); + +BOOLEAN RTMPCheckStrPrintAble( + IN CHAR *pInPutStr, + IN UCHAR strLen); + +VOID RTMPSetPhyMode( + IN RTMP_ADAPTER *pAd, + IN ULONG phymode); + +VOID RTMPUpdateHTIE( + IN RT_HT_CAPABILITY *pRtHt, + IN UCHAR *pMcsSet, + OUT HT_CAPABILITY_IE *pHtCapability, + OUT ADD_HT_INFO_IE *pAddHtInfo); + +VOID RTMPAddWcidAttributeEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR BssIdx, + IN UCHAR KeyIdx, + IN UCHAR CipherAlg, + IN MAC_TABLE_ENTRY *pEntry); + +RTMP_STRING *GetEncryptType(CHAR enc); +RTMP_STRING *GetAuthMode(CHAR auth); + +VOID set_sta_ra_cap(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *ent, ULONG ra_ie); + +#ifdef DOT11_N_SUPPORT +VOID set_sta_ht_cap(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *ent, HT_CAPABILITY_IE *ht_ie); + +VOID RTMPSetHT(RTMP_ADAPTER *pAd, OID_SET_HT_PHYMODE *pHTPhyMode); +VOID RTMPSetIndividualHT(RTMP_ADAPTER *pAd, UCHAR apidx); + +UCHAR get_cent_ch_by_htinfo( + RTMP_ADAPTER *pAd, + ADD_HT_INFO_IE *ht_op, + HT_CAPABILITY_IE *ht_cap); + +UCHAR RTMP_GetPrimaryCh( + RTMP_ADAPTER *pAd, + UCHAR ch); + +INT get_ht_cent_ch(RTMP_ADAPTER *pAd, UINT8 *rf_bw, UINT8 *ext_ch); +INT ht_mode_adjust(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, HT_CAPABILITY_IE *peer, RT_HT_CAPABILITY *my); +INT set_ht_fixed_mcs(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, UCHAR fixed_mcs, UCHAR mcs_bound); +INT get_ht_max_mcs(RTMP_ADAPTER *pAd, UCHAR *desire_mcs, UCHAR *cap_mcs); +#endif /* DOT11_N_SUPPORT */ + +VOID RTMPDisableDesiredHtInfo( + IN RTMP_ADAPTER *pAd); + +#ifdef SYSTEM_LOG_SUPPORT +VOID RtmpDrvSendWirelessEvent( + IN VOID *pAdSrc, + IN USHORT Event_flag, + IN PUCHAR pAddr, + IN UCHAR wdev_idx, + IN CHAR Rssi); +#else +#define RtmpDrvSendWirelessEvent(_pAd, _Event_flag, _pAddr, wdev_idx, _Rssi) +#endif /* SYSTEM_LOG_SUPPORT */ + +CHAR ConvertToRssi( + IN RTMP_ADAPTER *pAd, + IN struct raw_rssi_info *rssi_info, + IN UCHAR rssi_idx); + +CHAR ConvertToSnr(RTMP_ADAPTER *pAd, UCHAR Snr); + +#ifdef DOT11N_DRAFT3 +VOID BuildEffectedChannelList( + IN RTMP_ADAPTER *pAd); + + +VOID DeleteEffectedChannelList(RTMP_ADAPTER *pAd); + +VOID CntlChannelWidth( + IN RTMP_ADAPTER *pAd, + IN UCHAR PrimaryChannel, + IN UCHAR CentralChannel, + IN UCHAR ChannelWidth, + IN UCHAR SecondaryChannelOffset); + +#endif /* DOT11N_DRAFT3 */ + + +VOID APAsicEvaluateRxAnt( + IN RTMP_ADAPTER *pAd); + + +VOID APAsicRxAntEvalTimeout(RTMP_ADAPTER *pAd); + + +VOID RTMPGetTxTscFromAsic(RTMP_ADAPTER *pAd, UCHAR apidx, UCHAR *pTxTsc); + +MAC_TABLE_ENTRY *PACInquiry(RTMP_ADAPTER *pAd, UCHAR Wcid); + +UINT APValidateRSNIE( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pRsnIe, + IN UCHAR rsnie_len); + +VOID HandleCounterMeasure( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID WPAStart4WayHS( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN ULONG TimeInterval); + +VOID WPAStart2WayGroupHS( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry); + +VOID PeerPairMsg1Action( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerPairMsg2Action( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerPairMsg3Action( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerPairMsg4Action( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID WPAPairMsg3Retry( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN ULONG TimeInterval +); + +VOID PeerGroupMsg1Action( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID PeerGroupMsg2Action( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN VOID *Msg, + IN UINT MsgLen); + +VOID CMTimerExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID WPARetryExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + + +VOID EnqueueStartForPSKExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID RTMPHandleSTAKey( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN MLME_QUEUE_ELEM *Elem); + +VOID MlmeDeAuthAction( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN USHORT Reason, + IN BOOLEAN bDataFrameFirst); + +#ifdef DOT11W_PMF_SUPPORT +VOID PMF_SAQueryTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID PMF_SAQueryConfirmTimeOut( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* DOT11W_PMF_SUPPORT */ + +VOID GREKEYPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID AES_128_CMAC( + IN PUCHAR key, + IN PUCHAR input, + IN INT len, + OUT PUCHAR mac); + +#if defined(DOT1X_SUPPORT) || defined(CONFIG_OWE_SUPPORT) || defined(DOT11_SAE_SUPPORT) +VOID WpaSend( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pPacket, + IN ULONG Len); + +VOID RTMPAddPMKIDCache( + IN RTMP_ADAPTER *pAd, + IN INT apidx, + IN PUCHAR pAddr, + IN UCHAR *PMKID, + IN UCHAR *PMK +#ifdef CONFIG_OWE_SUPPORT + , IN UINT8 pmk_len +#endif + ); +INT RTMPSearchPMKIDCache( + IN RTMP_ADAPTER *pAd, + IN INT apidx, + IN PUCHAR pAddr); + +VOID RTMPDeletePMKIDCache( + IN RTMP_ADAPTER *pAd, + IN INT apidx, + IN INT idx); + +VOID RTMPMaintainPMKIDCache( + IN RTMP_ADAPTER *pAd); +#else +#define RTMPMaintainPMKIDCache(_pAd) +#endif /* DOT1X_SUPPORT */ + +#if defined(DOT1X_SUPPORT) || defined(CONFIG_OWE_SUPPORT) || defined(DOT11_SAE_SUPPORT) + +VOID store_pmkid_cache_in_entry( + IN RTMP_ADAPTER * pAd, + IN MAC_TABLE_ENTRY * pEntry, + IN INT32 cache_idx); + +UCHAR is_pmkid_cache_in_entry( + IN MAC_TABLE_ENTRY * pEntry); + +#endif + +#ifdef RESOURCE_PRE_ALLOC +VOID RTMPResetTxRxRingMemory( + IN RTMP_ADAPTER *pAd); +#endif /* RESOURCE_PRE_ALLOC */ + +VOID RTMPFreeTxRxRingMemory( + IN RTMP_ADAPTER *pAd); + +BOOLEAN RTMP_FillTxBlkInfo( + IN RTMP_ADAPTER *pAd, + IN TX_BLK *pTxBlk); + + void announce_802_3_packet( + IN VOID *pAdSrc, + IN PNDIS_PACKET pPacket, + IN UCHAR OpMode); + +#ifdef DOT11_N_SUPPORT +UINT BA_Reorder_AMSDU_Annnounce( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR OpMode); +#endif /* DOT11_N_SUPPORT */ + +PNET_DEV get_netdev_from_bssid(RTMP_ADAPTER *pAd, UCHAR FromWhichBSSID); + +#ifdef DOT11_N_SUPPORT +void ba_flush_reordering_timeout_mpdus( + IN RTMP_ADAPTER *pAd, + IN PBA_REC_ENTRY pBAEntry, + IN ULONG Now32); + +#ifdef CONFIG_BA_REORDER_MONITOR +void ba_timeout_flush(RTMP_ADAPTER *pAd); +void ba_timeout_monitor(RTMP_ADAPTER *pAd); +#endif + +VOID BAOriSessionSetUp( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR TID, + IN USHORT TimeOut, + IN ULONG DelayTime, + IN BOOLEAN isForced); + +VOID BASessionTearDownALL( + IN OUT RTMP_ADAPTER *pAd, + IN UCHAR Wcid); + +VOID BAOriSessionTearDown( + IN OUT RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive, + IN BOOLEAN bForceSend); + +VOID BARecSessionTearDown( + IN OUT RTMP_ADAPTER *pAd, + IN UCHAR Wcid, + IN UCHAR TID, + IN BOOLEAN bPassive); +#endif /* DOT11_N_SUPPORT */ + +BOOLEAN ba_reordering_resource_init(RTMP_ADAPTER *pAd, int num); +void ba_reordering_resource_release(RTMP_ADAPTER *pAd); + +INT ComputeChecksum( + IN UINT PIN); + +UINT GenerateWpsPinCode( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN bFromApcli, + IN UCHAR apidx); + +#ifdef WSC_INCLUDED +INT Set_WscGenPinCode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef BB_SOC +INT Set_WscResetPinCode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif + +INT Set_WscVendorPinCode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef WSC_AP_SUPPORT +VOID RTMPIoctlSetWSCOOB(IN RTMP_ADAPTER *pAd); +#endif + +/* */ +/* prototype in wsc.c */ +/* */ +BOOLEAN WscMsgTypeSubst( + IN UCHAR EAPType, + IN UCHAR EAPCode, + OUT INT *MsgType); + +VOID WscStateMachineInit( + IN RTMP_ADAPTER *pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + + +VOID WscEAPOLStartAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WscEAPAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WscEapEnrolleeAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem, + IN UCHAR MsgType, + IN MAC_TABLE_ENTRY *pEntry, + IN PWSC_CTRL pWscControl); + +#ifdef CONFIG_AP_SUPPORT +VOID WscEapApProxyAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem, + IN UCHAR MsgType, + IN MAC_TABLE_ENTRY *pEntry, + IN PWSC_CTRL pWscControl); +#endif /* CONFIG_AP_SUPPORT */ + +VOID WscEapRegistrarAction( + IN RTMP_ADAPTER *pAd, + IN MLME_QUEUE_ELEM *Elem, + IN UCHAR MsgType, + IN MAC_TABLE_ENTRY *pEntry, + IN PWSC_CTRL pWscControl); + +VOID WscEAPOLTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID Wsc2MinsTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +UCHAR WscRxMsgType( + IN RTMP_ADAPTER *pAd, + IN PMLME_QUEUE_ELEM pElem); + +VOID WscInitRegistrarPair( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN UCHAR apidx); + +VOID WscSendEapReqId( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR CurOpMode); + +VOID WscSendEapolStart( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pBssid, + IN UCHAR CurOpMode); + +VOID WscSendEapRspId( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PWSC_CTRL pWscControl); + +VOID WscMacHeaderInit( + IN RTMP_ADAPTER *pAd, + IN OUT PHEADER_802_11 Hdr, + IN PUCHAR pAddr1, + IN PUCHAR pBSSID, + IN BOOLEAN bFromApCli); + +VOID WscSendMessage( + IN RTMP_ADAPTER *pAd, + IN UCHAR OpCode, + IN PUCHAR pData, + IN INT Len, + IN PWSC_CTRL pWscControl, + IN UCHAR OpMode, /* 0: AP Mode, 1: AP Client Mode, 2: STA Mode */ + IN UCHAR EapType); + +VOID WscSendEapReqAck( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry); + +VOID WscSendEapReqDone( + IN RTMP_ADAPTER *pAd, + IN PMLME_QUEUE_ELEM pElem); + +VOID WscSendEapFail( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN BOOLEAN bSendDeAuth); + +VOID WscM2DTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID WscUPnPMsgTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +int WscSendUPnPConfReqMsg( + IN RTMP_ADAPTER *pAd, + IN UCHAR apIdx, + IN PUCHAR ssidStr, + IN PUCHAR macAddr, + IN INT Status, + IN UINT eventID, + IN UCHAR CurOpMode); + + +int WscSendUPnPMessage( + IN RTMP_ADAPTER *pAd, + IN UCHAR apIdx, + IN USHORT msgType, + IN USHORT msgSubType, + IN PUCHAR pData, + IN INT dataLen, + IN UINT eventID, + IN UINT toIPAddr, + IN PUCHAR pMACAddr, + IN UCHAR CurOpMode); + +VOID WscUPnPErrHandle( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN UINT eventID); + +VOID WscBuildBeaconIE( + IN RTMP_ADAPTER *pAd, + IN UCHAR b_configured, + IN BOOLEAN b_selRegistrar, + IN USHORT devPwdId, + IN USHORT selRegCfgMethods, + IN UCHAR apidx, + IN UCHAR *pAuthorizedMACs, + IN UCHAR AuthorizedMACsLen, + IN UCHAR CurOpMode); + +VOID WscBuildProbeRespIE( + IN RTMP_ADAPTER *pAd, + IN UCHAR respType, + IN UCHAR scState, + IN BOOLEAN b_selRegistrar, + IN USHORT devPwdId, + IN USHORT selRegCfgMethods, + IN UCHAR apidx, + IN UCHAR *pAuthorizedMACs, + IN INT AuthorizedMACsLen, + IN UCHAR CurOpMode); + + +#ifdef CONFIG_AP_SUPPORT +VOID WscBuildAssocRespIE( + IN RTMP_ADAPTER *pAd, + IN UCHAR ApIdx, + IN UCHAR Reason, + OUT PUCHAR pOutBuf, + OUT PUCHAR pIeLen); + +VOID WscSelectedRegistrar( + IN RTMP_ADAPTER *pAd, + IN PUCHAR RegInfo, + IN UINT length, + IN UCHAR apidx); + +VOID WscInformFromWPA( + IN PMAC_TABLE_ENTRY pEntry); +#endif /* CONFIG_AP_SUPPORT */ + + +VOID WscBuildProbeReqIE( + IN RTMP_ADAPTER *pAd, + IN UCHAR CurOpMode, + IN PWSC_CTRL pWpsCtrl, + OUT PUCHAR pOutBuf, + OUT PUCHAR pIeLen); + +VOID WscBuildAssocReqIE( + IN PWSC_CTRL pWscControl, + OUT PUCHAR pOutBuf, + OUT PUCHAR pIeLen); + + +VOID WscProfileRetryTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID WscPBCTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID WscScanTimeOutAction( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + + +INT WscGenerateUUID( + RTMP_ADAPTER *pAd, + UCHAR *uuidHexStr, + UCHAR *uuidAscStr, + int apIdx, + BOOLEAN bUseCurrentTime); + +VOID WscStop( + IN RTMP_ADAPTER *pAd, +#ifdef CONFIG_AP_SUPPORT + IN BOOLEAN bFromApcli, +#endif /* CONFIG_AP_SUPPORT */ + IN PWSC_CTRL pWscControl); + +VOID WscInit( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN bFromApcli, + IN UCHAR BssIndex); + +BOOLEAN ValidateChecksum(UINT PIN); + +UINT WscRandomGen4digitPinCode(RTMP_ADAPTER *pAd); + +UINT WscRandomGeneratePinCode( + IN RTMP_ADAPTER *pAd, + IN UCHAR apidx); + +int BuildMessageM1( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM2( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM2D( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM3( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM4( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM5( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM6( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM7( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageM8( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageDONE( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageACK( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int BuildMessageNACK( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + OUT VOID *pbuf); + +int ProcessMessageM1( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM2( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + IN UCHAR apidx, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM2D( + IN RTMP_ADAPTER *pAd, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM3( + IN RTMP_ADAPTER *pAd, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM4( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM5( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM6( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM7( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN VOID *precv, + IN INT Length, + OUT PWSC_REG_DATA pReg); + +int ProcessMessageM8( + IN RTMP_ADAPTER *pAd, + IN VOID *precv, + IN INT Length, + IN PWSC_CTRL pWscControl); + +USHORT WscGetAuthType( + IN NDIS_802_11_AUTHENTICATION_MODE authType); + +USHORT WscGetEncryType( + IN NDIS_802_11_WEP_STATUS encryType); + +NDIS_STATUS WscThreadInit(RTMP_ADAPTER *pAd); + +BOOLEAN WscThreadExit(RTMP_ADAPTER *pAd); + +int AppendWSCTLV( + IN USHORT index, + OUT UCHAR * obuf, + IN UCHAR * ibuf, + IN USHORT varlen); + +VOID WscGetRegDataPIN( + IN RTMP_ADAPTER *pAd, + IN UINT PinCode, + IN PWSC_CTRL pWscControl); + +VOID WscPushPBCAction( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl); + +VOID WscScanExec( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl); + +BOOLEAN WscPBCExec( + IN RTMP_ADAPTER *pAd, + IN BOOLEAN bFromM2, + IN PWSC_CTRL pWscControl); + +VOID WscPBCBssTableSort( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl); + +VOID WscGenRandomKey( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + INOUT PUCHAR pKey, + INOUT PUSHORT pKeyLen); + +VOID WscCreateProfileFromCfg( + IN RTMP_ADAPTER *pAd, + IN UCHAR OpMode, /* 0: AP Mode, 1: AP Client Mode, 2: STA Mode */ + IN PWSC_CTRL pWscControl, + OUT PWSC_PROFILE pWscProfile); + +void WscWriteConfToPortCfg( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN PWSC_CREDENTIAL pCredential, + IN BOOLEAN bEnrollee); + +#ifdef APCLI_SUPPORT +void WscWriteConfToApCliCfg( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN PWSC_CREDENTIAL pCredential, + IN BOOLEAN bEnrollee); +#endif /* APCLI_SUPPORT */ + +VOID WpsSmProcess( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WscPBCSessionOverlapCheck( + IN RTMP_ADAPTER *pAd); + +VOID WscPBCSessionOverlapClear( + IN RTMP_ADAPTER *pAd); + +VOID WscPBC_DPID_FromSTA( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pMacAddr); + +#ifdef CONFIG_AP_SUPPORT +INT WscGetConfWithoutTrigger( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN BOOLEAN bFromUPnP); + +BOOLEAN WscReadProfileFromUfdFile( + IN RTMP_ADAPTER *pAd, + IN UCHAR ApIdx, + IN RTMP_STRING *pUfdFileName); + +BOOLEAN WscWriteProfileToUfdFile( + IN RTMP_ADAPTER *pAd, + IN UCHAR ApIdx, + IN RTMP_STRING *pUfdFileName); +#endif /* CONFIG_AP_SUPPORT */ + +VOID WscCheckWpsIeFromWpsAP( + IN RTMP_ADAPTER *pAd, + IN PEID_STRUCT pEid, + OUT PUSHORT pDPIDFromAP); + + +/* WSC hardware push button function 0811 */ +VOID WSC_HDR_BTN_Init(RTMP_ADAPTER *pAd); +VOID WSC_HDR_BTN_Stop(RTMP_ADAPTER *pAd); +VOID WSC_HDR_BTN_CheckHandler(RTMP_ADAPTER *pAd); +#ifdef WSC_LED_SUPPORT +BOOLEAN WscSupportWPSLEDMode(RTMP_ADAPTER *pAd); +BOOLEAN WscSupportWPSLEDMode10(RTMP_ADAPTER *pAd); + +BOOLEAN WscAPHasSecuritySetting(RTMP_ADAPTER *pAd,PWSC_CTRL pWscControl); + +VOID WscLEDTimer( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID WscSkipTurnOffLEDTimer( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* WSC_LED_SUPPORT */ + + + +#ifdef CONFIG_AP_SUPPORT +VOID WscUpdatePortCfgTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* CONFIG_AP_SUPPORT */ + +VOID WscCheckPeerDPID( + IN RTMP_ADAPTER *pAd, + IN PFRAME_802_11 Fr, + IN PUCHAR eid_data, + IN INT eid_len); + +VOID WscClearPeerList(PLIST_HEADER pWscEnList); + +PWSC_PEER_ENTRY WscFindPeerEntry(PLIST_HEADER pWscEnList, UCHAR *pMacAddr); +VOID WscDelListEntryByMAC(PLIST_HEADER pWscEnList, UCHAR *pMacAddr); +VOID WscInsertPeerEntryByMAC(PLIST_HEADER pWscEnList, UCHAR *pMacAddr); + +#ifdef CONFIG_AP_SUPPORT +INT WscApShowPeerList(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +VOID WscSetupLockTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +VOID WscCheckPinAttackCount(RTMP_ADAPTER *pAd, PWSC_CTRL pWscControl); +#endif /* CONFIG_AP_SUPPORT */ + + +VOID WscMaintainPeerList(RTMP_ADAPTER *pAd, PWSC_CTRL pWpsCtrl); + +VOID WscAssignEntryMAC(RTMP_ADAPTER *pAd, PWSC_CTRL pWpsCtrl); + +#ifdef WSC_V2_SUPPORT +#ifdef CONFIG_AP_SUPPORT +VOID WscOnOff(RTMP_ADAPTER *pAd, INT ApIdx, BOOLEAN bOff); + +VOID WscAddEntryToAclList(RTMP_ADAPTER *pAd, INT ApIdx, UCHAR *pMacAddr); +#endif /* CONFIG_AP_SUPPORT */ + +BOOLEAN WscGenV2Msg( + IN PWSC_CTRL pWpsCtrl, + IN BOOLEAN bSelRegistrar, + IN PUCHAR pAuthorizedMACs, + IN INT AuthorizedMACsLen, + OUT UCHAR **pOutBuf, + OUT INT *pOutBufLen); + +BOOLEAN WscParseV2SubItem( + IN UCHAR SubID, + IN PUCHAR pData, + IN USHORT DataLen, + OUT PUCHAR pOutBuf, + OUT PUCHAR pOutBufLen); + +VOID WscSendEapFragAck( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN PMAC_TABLE_ENTRY pEntry); + +VOID WscSendEapFragData( + IN RTMP_ADAPTER *pAd, + IN PWSC_CTRL pWscControl, + IN PMAC_TABLE_ENTRY pEntry); +#endif /* WSC_V2_SUPPORT */ + +BOOLEAN WscGetDataFromPeerByTag( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pIeData, + IN INT IeDataLen, + IN USHORT WscTag, + OUT PUCHAR pWscBuf, + OUT PUSHORT pWscBufLen); + +#endif /* WSC_INCLUDED */ + +#ifdef DBG +INT32 ShowRFInfo(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT32 ShowBBPInfo(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* DBG */ +INT32 show_redirect_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#ifdef SMART_CARRIER_SENSE_SUPPORT +INT32 ShowSCSInfo(RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +#endif /* SMART_CARRIER_SENSE_SUPPORT */ + + + + +BOOLEAN rtstrmactohex(RTMP_STRING *s1, RTMP_STRING *s2); +BOOLEAN rtstrcasecmp(RTMP_STRING *s1, RTMP_STRING *s2); +RTMP_STRING *rtstrstruncasecmp(RTMP_STRING *s1, RTMP_STRING *s2); + +RTMP_STRING *rtstrstr( const RTMP_STRING *s1, const RTMP_STRING *s2); +RTMP_STRING *rstrtok( RTMP_STRING *s, const RTMP_STRING *ct); +int rtinet_aton(const RTMP_STRING *cp, unsigned int *addr); + +/*//////// common ioctl functions ////////*/ +INT Set_DriverVersion_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_CountryRegion_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_CountryRegionABand_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_WirelessMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_MBSS_WirelessMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_Channel_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ShortSlot_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_TxPower_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_MaxTxPwr_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_BGProtection_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_TxPreamble_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_RTSThreshold_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_FragThreshold_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_TxBurst_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_SendBMToAir_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef RTMP_MAC_PCI +INT Set_ShowRF_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* RTMP_MAC_PCI */ + +#ifdef AGGREGATION_SUPPORT +INT Set_PktAggregate_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* AGGREGATION_SUPPORT */ + +#ifdef INF_PPA_SUPPORT +INT Set_INF_AMAZON_SE_PPA_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT ifx_ra_start_xmit ( + IN struct net_device *rx_dev, + IN struct net_device *tx_dev, + IN struct sk_buff *skb, + IN int len); +#endif /* INF_PPA_SUPPORT */ + +INT Set_IEEE80211H_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef EXT_BUILD_CHANNEL_LIST +INT Set_ExtCountryCode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ExtDfsType_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ChannelListAdd_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ChannelListShow_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ChannelListDel_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* EXT_BUILD_CHANNEL_LIST */ + +#ifdef DBG +INT Set_Debug_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_DebugFunc_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +VOID RTMPIoctlMAC(RTMP_ADAPTER *pAd, RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif +INT Set_Ap_Probe_Rsp_Times(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#ifdef FAST_DETECT_STA_OFF +INT Set_FlagFastDetectStaOff_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif + +#ifdef THERMAL_PROTECT_SUPPORT +INT set_thermal_protection_criteria_proc( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *arg); +#endif /* THERMAL_PROTECT_SUPPORT */ + + +#ifdef VHT_TXBF_SUPPORT +INT Set_VhtNDPA_Sounding_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* VHT_TXBF_SUPPORT */ + +#if defined(CONFIG_WIFI_PKT_FWD) || defined(CONFIG_WIFI_PKT_FWD_MODULE) +#if (MT7615_MT7603_COMBO_FORWARDING == 1) +INT WifiFwdSet(IN int disabled); +INT Set_WifiFwd_Down(IN PRTMP_ADAPTER pAd, IN RTMP_STRING *arg); +INT Set_WifiFwdBpdu_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +#endif +INT Set_WifiFwd_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_WifiFwdAccessSchedule_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_WifiFwdHijack_Proc(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_WifiFwdRepDevice(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_WifiFwdShowEntry(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_WifiFwdDeleteEntry(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_PacketSourceShowEntry(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +INT Set_PacketSourceDeleteEntry(PRTMP_ADAPTER pAd, RTMP_STRING *arg); +#endif /* CONFIG_WIFI_PKT_FWD */ + + +INT Set_RateAdaptInterval(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + +#ifdef PRE_ANT_SWITCH +INT Set_PreAntSwitch_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_PreAntSwitchRSSI_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_PreAntSwitchTimeout_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#endif /* PRE_ANT_SWITCH */ + + + +#ifdef MT_MAC +#ifdef DBG +INT Set_Fixed_Rate_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* DBG */ +#ifdef ANTI_INTERFERENCE_SUPPORT +INT Set_DynamicRaInterval(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_SwiftTrainThrd(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* ANTI_INTERFERENCE_SUPPORT */ +#endif /* MT_MAC */ + +#ifdef MIXMODE_SUPPORT +INT32 ShowMixModeProc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT32 GetMacTableStaInfo_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT32 SetMixMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT32 MixModeCancel_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT32 GetMixModeRssi_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* MIXMODE_SUPPORT */ + +#ifdef CFO_TRACK +INT Set_CFOTrack_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef CFO_TRACK +#ifdef CONFIG_AP_SUPPORT +INT rtmp_cfo_track(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, INT lastClient); +#endif /* CONFIG_AP_SUPPORT */ +#endif /* CFO_TRACK */ + +#endif // CFO_TRACK // + +#ifdef DBG_CTRL_SUPPORT +INT Set_DebugFlags_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef INCLUDE_DEBUG_QUEUE +INT Set_DebugQueue_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +void dbQueueEnqueue(UCHAR type, UCHAR *data); +void dbQueueEnqueueTxFrame(UCHAR *pTxWI, UCHAR *pDot11Hdr); +void dbQueueEnqueueRxFrame(UCHAR *pRxWI, UCHAR *pDot11Hdr ULONG flags); +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ +#ifdef DBG +INT Show_DescInfo_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Show_MacTable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#ifdef ACL_BLK_COUNT_SUPPORT +INT Show_ACLRejectCount_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif/*ACL_BLK_COUNT_SUPPORT*/ + +#ifdef CONFIG_AP_SUPPORT +INT Show_StationKeepAliveTime_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef DOT11_N_SUPPORT +INT Show_BaTable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* DOT11_N_SUPPORT */ + +#ifdef MT_MAC +INT Show_PSTable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT show_wtbl_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT show_temp_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT show_mib_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT32 ShowTmacInfo(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT32 ShowAggInfo(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT ShowManualTxOP(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT32 ShowPseInfo(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT32 ShowPseData(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT) +INT32 ShowDMASchInfo(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif +#endif /* MT_MAC */ +INT Show_sta_tr_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT show_stainfo_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT show_devinfo_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT show_sysinfo_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT show_trinfo_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT show_txqinfo_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* DBG */ +#ifdef MULTI_CLIENT_SUPPORT +INT show_configinfo_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif +INT Set_ResetStatCounter_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#ifdef SW_ATF_SUPPORT +INT SetFixAtfPara_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT SetAtfDropDelta_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT SetAtfFalseCCAThr_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT SetGoodNodePara_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT SetBadNodePara_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT SetTxThr_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT SetBadNodeMinDeq_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif + +#ifdef DOT11_N_SUPPORT +INT Set_BASetup_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_BADecline_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_BAOriTearDown_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_BARecTearDown_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_HtBw_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_HtMcs_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_HtGi_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_HtOpMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_HtStbc_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_HtExtcha_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_HtMpduDensity_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_HtBaWinSize_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_HtRdg_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_HtLinkAdapt_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_HtAmsdu_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_HtAutoBa_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_HtProtect_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_HtMimoPs_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef DOT11N_DRAFT3 +INT Set_HT_BssCoex_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_HT_BssCoexApCntThr_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* DOT11N_DRAFT3 */ + + +#ifdef CONFIG_AP_SUPPORT +INT Set_HtTxStream_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_HtRxStream_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#ifdef DOT11_N_SUPPORT +#ifdef GREENAP_SUPPORT +INT Set_GreenAP_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* GREENAP_SUPPORT */ +#endif /* DOT11_N_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +INT SetCommonHT(RTMP_ADAPTER *pAd); + +INT Set_ForceShortGI_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ForceGF_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_SendSMPSAction_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +void convert_reordering_packet_to_preAMSDU_or_802_3_packet( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk, + IN UCHAR wdev_idx); + +INT Set_HtMIMOPSmode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_HtTxBASize_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_HtDisallowTKIP_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_BurstMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* DOT11_N_SUPPORT */ + + +#ifdef DOT11_VHT_AC +INT Set_VhtBw_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_VhtStbc_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_VhtBwSignal_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_VhtDisallowNonVHT_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* DOT11_VHT_AC */ + + +#ifdef APCLI_SUPPORT +INT RTMPIoctlConnStatus(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /*APCLI_SUPPORT*/ + + + + + + +#ifdef CONFIG_AP_SUPPORT +VOID detect_wmm_traffic(RTMP_ADAPTER *pAd, UCHAR up, UCHAR bOutput); +VOID dynamic_tune_be_tx_op(RTMP_ADAPTER *pAd, ULONG nonBEpackets); +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef DOT11_N_SUPPORT +VOID Handle_BSS_Width_Trigger_Events(RTMP_ADAPTER *pAd); + +void build_ext_channel_switch_ie( + IN RTMP_ADAPTER *pAd, + IN HT_EXT_CHANNEL_SWITCH_ANNOUNCEMENT_IE *pIE); + +#ifdef DBG +void assoc_ht_info_debugshow( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR ht_cap_len, + IN HT_CAPABILITY_IE *pHTCapability); +#endif /* DBG */ +#endif /* DOT11_N_SUPPORT */ + +BOOLEAN rtmp_rx_done_handle(RTMP_ADAPTER *pAd); + +#ifdef RTMP_PCI_SUPPORT +#ifdef CONFIG_ANDES_SUPPORT +BOOLEAN RxRing1DoneInterruptHandle(RTMP_ADAPTER *pAd); +VOID RTMPHandleTxRing8DmaDoneInterrupt(RTMP_ADAPTER *pAd); +#endif /* CONFIG_ANDES_SUPPORT */ + +#ifdef MT_MAC +VOID RTMPHandleBcnDmaDoneInterrupt(RTMP_ADAPTER *pAd); +#endif /* MT_MAC */ +#endif /* RTMP_PCI_SUPPORT */ + +INT wdev_bcn_buf_deinit(RTMP_ADAPTER *pAd, BCN_BUF_STRUC *bcn_info); +INT wdev_bcn_buf_init(RTMP_ADAPTER *pAd, BCN_BUF_STRUC *bcn_info); + +#ifdef DOT11_N_SUPPORT +VOID Indicate_AMPDU_Packet(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk, UCHAR wdev_idx); +VOID Indicate_AMSDU_Packet(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk, UCHAR wdev_idx); + +VOID BaReOrderingBufferMaintain(RTMP_ADAPTER *pAd); +#endif /* DOT11_N_SUPPORT */ + +#ifdef MAC_REPEATER_SUPPORT +VOID RxTrackingInit(struct wifi_dev *wdev); +VOID TaTidRecAndCmp( + struct _RTMP_ADAPTER *pAd, + struct rxd_base_struct *rx_base, + UINT16 SN, + BOOLEAN isBAR, + HEADER_802_11 *pHeader); +#endif /* MAC_REPEATER_SUPPORT */ + +/* Normal legacy Rx packet indication */ +VOID Indicate_Legacy_Packet(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk, UCHAR wdev_idx); +VOID Indicate_EAPOL_Packet(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk, UCHAR wdev_idx); + +UINT deaggregate_AMSDU_announce( + IN RTMP_ADAPTER *pAd, + PNDIS_PACKET pPacket, + IN PUCHAR pData, + IN ULONG DataSize, + IN UCHAR OpMode); + + +/* 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_AP)) \ + { \ + _pDA = _pRxBlk->pHeader->Addr1; \ + if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_DLS)) \ + _pSA = _pRxBlk->pHeader->Addr2; \ + else \ + _pSA = _pRxBlk->pHeader->Addr3; \ + } \ + else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_STA)) \ + { \ + _pDA = _pRxBlk->pHeader->Addr3; \ + _pSA = _pRxBlk->pHeader->Addr2; \ + } \ + else if (RX_BLK_TEST_FLAG(_pRxBlk, fRX_ADHOC)) \ + { \ + _pDA = _pRxBlk->pHeader->Addr1; \ + _pSA = _pRxBlk->pHeader->Addr2; \ + } \ + else \ + { /* TODO: shiang-usw, where shall we go here?? */ \ + DBGPRINT(RT_DEBUG_INFO, ("%s():Un-assigned Peer's Role!\n", __FUNCTION__));\ + _pDA = _pRxBlk->pHeader->Addr3; \ + _pSA = _pRxBlk->pHeader->Addr2; \ + } \ + \ + CONVERT_TO_802_3(_pHeader802_3, _pDA, _pSA, _pRxBlk->pData, \ + _pRxBlk->DataSize, _pRemovedLLCSNAP); \ + if(_pRemovedLLCSNAP != NULL) \ + { \ + DBGPRINT(RT_DEBUG_INFO, ("%s():LLC/SNAP field found!\n", __FUNCTION__)); \ + } \ +} + + +VOID Announce_or_Forward_802_3_Packet( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR wdev_idx, + IN UCHAR op_mode); + +VOID Indicate_ARalink_Packet( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN RX_BLK *pRxBlk, + IN UCHAR wdev_idx); + +VOID Update_Rssi_Sample( + IN RTMP_ADAPTER *pAd, + IN RSSI_SAMPLE *pRssi, + IN struct rx_signal_info *signal, + IN UCHAR phymode, + IN UCHAR bw); + +PNDIS_PACKET GetPacketFromRxRing( + RTMP_ADAPTER *pAd, + RX_BLK *pRxBlk, + BOOLEAN *pbReschedule, + UINT32 *pRxPending, + UCHAR RxRingNo); + +PNDIS_PACKET RTMPDeFragmentDataFrame( + IN RTMP_ADAPTER *pAd, + IN RX_BLK *pRxBlk); + +/*////////////////////////////////////*/ + +#if defined (AP_SCAN_SUPPORT) || defined (CONFIG_STA_SUPPORT) +VOID RTMPIoctlGetSiteSurvey( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +#endif + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +INT Set_ApCli_AuthMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ApCli_EncrypType_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ApCli_Enable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ApCli_Ssid_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#ifdef ROAMING_ENHANCE_SUPPORT +BOOLEAN ApCliDoRoamingRefresh( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN PNDIS_PACKET pRxPacket, + IN struct wifi_dev *wdev, + IN UCHAR *DestAddr); +#endif /* ROAMING_ENHANCE_SUPPORT */ + +#ifdef WH_EZ_SETUP +INT Set_ApCli_Hide_Ssid_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + + +#ifdef MAT_SUPPORT + +VOID getIPv6MacTbInfo(MAT_STRUCT *, char *, ULONG); +VOID getIPMacTbInfo(MAT_STRUCT *pMatCfg, char *pOutBuf, ULONG BufLen); + +NDIS_STATUS MATEngineInit(RTMP_ADAPTER *pAd); +NDIS_STATUS MATEngineExit(RTMP_ADAPTER *pAd); + +PUCHAR MATEngineRxHandle(RTMP_ADAPTER *pAd, PNDIS_PACKET pPkt, UINT infIdx); +PUCHAR MATEngineTxHandle(RTMP_ADAPTER *pAd, PNDIS_PACKET pPkt, UINT infIdx, UCHAR OpMode); + +BOOLEAN MATPktRxNeedConvert(RTMP_ADAPTER *pAd, PNET_DEV net_dev); + +#endif /* MAT_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT +typedef struct CountryCodeToCountryRegion { + USHORT CountryNum; + UCHAR IsoName[3]; + /*UCHAR CountryName[40]; */ + RTMP_STRING *pCountryName; + BOOLEAN SupportABand; + /*ULONG RegDomainNum11A; */ + UCHAR RegDomainNum11A; + BOOLEAN SupportGBand; + /*ULONG RegDomainNum11G; */ + UCHAR RegDomainNum11G; +} COUNTRY_CODE_TO_COUNTRY_REGION; +#endif /* CONFIG_AP_SUPPORT */ + +#ifdef SNMP_SUPPORT +/*for snmp */ +typedef struct _DefaultKeyIdxValue +{ + UCHAR KeyIdx; + UCHAR Value[16]; +} DefaultKeyIdxValue, *PDefaultKeyIdxValue; +#endif + +typedef struct _ASIC_TX_CNT_UPDATE +{ + MAC_TABLE_ENTRY *pEntry; + MT_TX_COUNTER *pTxInfo; +} ASIC_TX_CNT_UPDATE, *PASIC_TX_CNT_UPDATE; + + +void STA_MonPktSend(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); + + +INT Set_FixedTxMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef CONFIG_APSTA_MIXED_SUPPORT +INT Set_OpMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* CONFIG_APSTA_MIXED_SUPPORT */ + +INT Set_LongRetryLimit_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_ShortRetryLimit_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_AutoFallBack_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +VOID RT28XXDMADisable(RTMP_ADAPTER *pAd); +VOID RT28XXDMAEnable(RTMP_ADAPTER *pAd); + +#ifdef RTMP_MAC_PCI +VOID PDMAWatchDog(RTMP_ADAPTER *pAd); +VOID PDMAResetAndRecovery(RTMP_ADAPTER *pAd); +VOID DumpPseInfo(RTMP_ADAPTER *pAd); +#endif + +#ifdef DMA_RESET_SUPPORT +VOID PSEACStuckWatchDog(RTMP_ADAPTER *pAd); +#endif /* DMA_RESET_SUPPORT */ + +VOID PSEWatchDog(RTMP_ADAPTER *pAd); +VOID PSEResetAndRecovery(RTMP_ADAPTER *pAd); +#ifdef MT_PS +VOID PsRetrieveTimeout(RTMP_ADAPTER *pAd, STA_TR_ENTRY *tr_entry); +#endif + +VOID RT28xx_UpdateBeaconToAsic( + IN RTMP_ADAPTER * pAd, + IN INT apidx, + IN ULONG BeaconLen, + IN ULONG UpdatePos); + +void CfgInitHook(RTMP_ADAPTER *pAd); + + +NDIS_STATUS RtmpNetTaskInit(RTMP_ADAPTER *pAd); +NDIS_STATUS RtmpMgmtTaskInit(RTMP_ADAPTER *pAd); +VOID RtmpNetTaskExit(RTMP_ADAPTER *pAd); +VOID RtmpMgmtTaskExit(RTMP_ADAPTER *pAd); + +void tbtt_tasklet(unsigned long data); + +#ifdef MT_MAC +void mt_mac_int_0_tasklet(unsigned long data); +void mt_mac_int_1_tasklet(unsigned long data); +void mt_mac_int_2_tasklet(unsigned long data); +void mt_mac_int_3_tasklet(unsigned long data); +void mt_mac_int_4_tasklet(unsigned long data); +#endif /* MT_MAC */ + +#ifdef RTMP_MAC_PCI +BOOLEAN RT28xxPciAsicRadioOff( + IN RTMP_ADAPTER *pAd, + IN UCHAR Level, + IN USHORT TbttNumToNextWakeUp); + +BOOLEAN RT28xxPciAsicRadioOn(RTMP_ADAPTER *pAd, UCHAR Level); +VOID RTMPInitPCIeDevice(RT_CMD_PCIE_INIT *pConfig, VOID *pAd); + + +VOID PciMlmeRadioOn(RTMP_ADAPTER *pAd); +VOID PciMlmeRadioOFF(RTMP_ADAPTER *pAd); + +ra_dma_addr_t RtmpDrvPciMapSingle( + IN RTMP_ADAPTER *pAd, + IN VOID *ptr, + IN size_t size, + IN INT sd_idx, + IN INT direction); + +INT rtmp_irq_init(RTMP_ADAPTER *pAd); +#endif /* RTMP_MAC_PCI */ + + +VOID AsicTurnOffRFClk(RTMP_ADAPTER *pAd, UCHAR Channel); + + +#ifdef NEW_WOW_SUPPORT +VOID RT28xxAndesWOWEnable(RTMP_ADAPTER *pAd); +VOID RT28xxAndesWOWDisable(RTMP_ADAPTER *pAd); +#endif /* NEW_WOW_SUPPORT */ + +#ifdef MT_WOW_SUPPORT +VOID MT76xxAndesWOWEnable(RTMP_ADAPTER *pAd); +VOID MT76xxAndesWOWDisable(RTMP_ADAPTER *pAd); +VOID MT76xxAndesWOWInit(RTMP_ADAPTER *pAd); +#endif + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) +VOID RT28xxAsicWOWEnable(RTMP_ADAPTER *pAd); +VOID RT28xxAsicWOWDisable(RTMP_ADAPTER *pAd); +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) */ + +/*////////////////////////////////////*/ + + +/*///////////////////////////////////*/ +INT RTMPShowCfgValue(RTMP_ADAPTER *pAd, RTMP_STRING *name, RTMP_STRING *buf, UINT32 MaxLen); +RTMP_STRING *RTMPGetRalinkAuthModeStr(NDIS_802_11_AUTHENTICATION_MODE authMode); +RTMP_STRING *RTMPGetRalinkEncryModeStr(USHORT encryMode); +/*//////////////////////////////////*/ + + +VOID RTMPSetAGCInitValue(RTMP_ADAPTER *pAd, UCHAR BandWidth); + + +#ifdef MFB_SUPPORT +VOID MFB_PerPareMRQ(RTMP_ADAPTER *pAd, VOID* pBuf, MAC_TABLE_ENTRY *pEntry); +VOID MFB_PerPareMFB(RTMP_ADAPTER *pAd, VOID *pBuf, MAC_TABLE_ENTRY *pEntry); +#endif /* MFB_SUPPORT */ + +#define VIRTUAL_IF_INC(__pAd) ((__pAd)->VirtualIfCnt++) +#define VIRTUAL_IF_DEC(__pAd) ((__pAd)->VirtualIfCnt--) +#define VIRTUAL_IF_NUM(__pAd) ((__pAd)->VirtualIfCnt) + + + + +#ifdef SOFT_ENCRYPT +BOOLEAN RTMPExpandPacketForSwEncrypt(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk); +VOID RTMPUpdateSwCacheCipherInfo(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk, UCHAR *pHdr); +INT tx_sw_encrypt(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk, UCHAR *buf_ptr, HEADER_802_11 *wifi_hdr); +#endif /* SOFT_ENCRYPT */ + + +/* + OS Related funciton prototype definitions. + TODO: Maybe we need to move these function prototypes to other proper place. +*/ +VOID RTInitializeCmdQ(PCmdQ cmdq); + +INT RTPCICmdThread(ULONG Context); + +VOID CMDHandler(RTMP_ADAPTER *pAd); + +VOID RTThreadDequeueCmd(PCmdQ cmdq, PCmdQElmt *pcmdqelmt); + +NDIS_STATUS RTEnqueueInternalCmd( + IN RTMP_ADAPTER *pAd, + IN NDIS_OID Oid, + IN PVOID pInformationBuffer, + IN UINT32 InformationBufferLength); + +#ifdef HOSTAPD_SUPPORT +VOID ieee80211_notify_michael_failure( + IN RTMP_ADAPTER *pAd, + IN PHEADER_802_11 pHeader, + IN UINT keyix, + IN INT report); + +const CHAR* ether_sprintf(const UINT8 *mac); +#endif/*HOSTAPD_SUPPORT*/ + + +#ifdef VENDOR_FEATURE3_SUPPORT +VOID RTMP_IO_WRITE32(RTMP_ADAPTER *pAd, UINT32 Offset, UINT32 Value); +#endif /* VENDOR_FEATURE3_SUPPORT */ + + +BOOLEAN CHAN_PropertyCheck(RTMP_ADAPTER *pAd, UINT32 ChanNum, UCHAR Property); + +#ifdef SINGLE_SKU_V2 +INT SetSKUEnable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* SINGLE_SKU_V2 */ +#ifdef SMART_CARRIER_SENSE_SUPPORT +INT SetSCSEnable_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT SetSCSCfg_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#endif /* SMART_CARRIER_SENSE_SUPPORT */ + +INT Set_ed_chk_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#ifdef DBG +INT show_ed_stat_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* DBG */ +INT ed_status_read(RTMP_ADAPTER *pAd); +INT ed_monitor_init(RTMP_ADAPTER *pAd); +INT ed_monitor_exit(RTMP_ADAPTER *pAd); + + + + +#ifdef CONFIG_SNIFFER_SUPPORT +INT Set_AP_Monitor_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* CONFIG_SNIFFER_SUPPORT */ + +void getRate(HTTRANSMIT_SETTING HTSetting, ULONG* fLastTxRxRate); + + +#ifdef APCLI_SUPPORT + +VOID ApCliRTMPSendNullFrame( + IN RTMP_ADAPTER *pAd, + IN UCHAR TxRate, + IN BOOLEAN bQosNull, + IN MAC_TABLE_ENTRY *pMacEntry, + IN USHORT PwrMgmt); + +#endif/*APCLI_SUPPORT*/ + + +void RTMP_IndicateMediaState( + IN RTMP_ADAPTER *pAd, + IN NDIS_MEDIA_STATE media_state); + +#if defined(RT3350) || defined(RT33xx) +VOID RTMP_TxEvmCalibration( + IN RTMP_ADAPTER *pAd); +#endif /* defined(RT3350) || defined(RT33xx) */ + +INT RTMPSetInformation( + IN RTMP_ADAPTER *pAd, + IN OUT RTMP_IOCTL_INPUT_STRUCT *rq, + IN INT cmd); + +INT RTMPQueryInformation( + IN RTMP_ADAPTER *pAd, + INOUT RTMP_IOCTL_INPUT_STRUCT *rq, + IN INT cmd); + +VOID RTMPIoctlShow( + IN RTMP_ADAPTER *pAd, + IN RTMP_IOCTL_INPUT_STRUCT *rq, + IN UINT32 subcmd, + IN VOID *pData, + IN ULONG Data); + +INT RTMP_COM_IoctlHandle( + IN VOID *pAdSrc, + IN RTMP_IOCTL_INPUT_STRUCT *wrq, + IN INT cmd, + IN USHORT subcmd, + IN VOID *pData, + IN ULONG Data); + +#ifdef CONFIG_AP_SUPPORT +INT RTMP_AP_IoctlPrepare(RTMP_ADAPTER *pAd, VOID *pCB); +#endif /* CONFIG_AP_SUPPORT */ +#ifdef CONFIG_SNIFFER_SUPPORT +INT Set_MonitorMode_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* CONFIG_SNIFFER_SUPPORT */ + +INT Set_VcoPeriod_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_RateAlg_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef SINGLE_SKU +INT Set_ModuleTxpower_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* SINGLE_SKU */ + +NDIS_STATUS RtmpEnqueueTokenFrame( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + IN UCHAR TxRate, + IN UCHAR AID, + IN UCHAR apidx, + IN UCHAR OldUP); + +VOID RtmpEnqueueNullFrame( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + IN UCHAR TxRate, + IN UCHAR AID, + IN UCHAR apidx, + IN BOOLEAN bQosNull, + IN BOOLEAN bEOSP, + IN UCHAR OldUP); + +VOID RtmpCleanupPsQueue( + IN RTMP_ADAPTER *pAd, + IN PQUEUE_HEADER pQueue); + +NDIS_STATUS RtmpInsertPsQueue( + IN RTMP_ADAPTER *pAd, + IN PNDIS_PACKET pPacket, + IN MAC_TABLE_ENTRY *pMacEntry, + IN UCHAR QueIdx); + +VOID RtmpHandleRxPsPoll(RTMP_ADAPTER *pAd, UCHAR *pAddr, USHORT Aid, BOOLEAN isActive); +BOOLEAN RtmpPsIndicate(RTMP_ADAPTER *pAd, UCHAR *pAddr, UCHAR wcid, UCHAR Psm); + +#ifdef MT_MAC +#if defined(MT7603) && defined(RTMP_PCI_SUPPORT) +INT MtPSDummyCR(RTMP_ADAPTER *pAd); +BOOLEAN MtStartPSRetrieve(RTMP_ADAPTER *pAd, USHORT wcid); +#endif +VOID MtHandleRxPsPoll(RTMP_ADAPTER *pAd, UCHAR *pAddr, USHORT wcid, BOOLEAN isActive); +BOOLEAN MtPsIndicate(RTMP_ADAPTER *pAd, UCHAR *pAddr, UCHAR wcid, UCHAR Psm); +VOID MtPsRedirectDisableCheck(RTMP_ADAPTER *pAd, UCHAR wcid); +VOID MtPsSendToken(RTMP_ADAPTER *pAd, UINT32 WlanIdx); +VOID MtPsRecovery(RTMP_ADAPTER *pAd); +VOID MtSetIgnorePsm(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, UCHAR value); +VOID CheckSkipTX(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry); +VOID MtEnqTxSwqFromPsQueue(RTMP_ADAPTER *pAd, UCHAR qidx, STA_TR_ENTRY *tr_entry); +#endif /* MT_MAC */ + +#if defined(RTMP_MAC) || defined(RLT_MAC) +VOID RalHandleRxPsPoll(RTMP_ADAPTER *pAd, UCHAR *pAddr, USHORT wcid, BOOLEAN isActive); +BOOLEAN RalPsIndicate(RTMP_ADAPTER *pAd, UCHAR *pAddr, UCHAR wcid, UCHAR Psm); +#endif /* RTMP_MAC || RLT_MAC */ + +#ifdef CONFIG_MULTI_CHANNEL +VOID RtmpEnqueueLastNullFrame( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pAddr, + IN UCHAR TxRate, + IN UCHAR PID, + IN UCHAR apidx, + IN BOOLEAN bQosNull, + IN BOOLEAN bEOSP, + IN UCHAR OldUP, + IN UCHAR PwrMgmt, + IN UCHAR OpMode); + +VOID EnableMACTxPacket( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR PwrMgmt, + IN BOOLEAN bTxNullFramei, + IN UCHAR QSel); + +VOID DisableMACTxPacket( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN UCHAR PwrMgmt, + IN BOOLEAN bWaitACK, + IN UCHAR QSel); + +VOID InitMultiChannelRelatedValue( + IN RTMP_ADAPTER *pAd, + IN UCHAR Channel, + IN UCHAR CentralChannel); + +VOID EDCA_ActionTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID HCCA_ActionTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +NDIS_STATUS MultiChannelThreadInit(RTMP_ADAPTER *pAd); +BOOLEAN MultiChannelThreadExit(RTMP_ADAPTER *pAd); +VOID MultiChannelTimerStop(RTMP_ADAPTER *pAd); +VOID MultiChannelTimerStart(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry); +#endif /* CONFIG_MULTI_CHANNEL */ + +VOID RtmpPrepareHwNullFrame( + IN RTMP_ADAPTER *pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN BOOLEAN bQosNull, + IN BOOLEAN bEOSP, + IN UCHAR OldUP, + IN UCHAR OpMode, + IN UCHAR PwrMgmt, + IN BOOLEAN bWaitACK, + IN CHAR Index); + + +VOID dev_rx_mgmt_frm(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); +VOID dev_rx_ctrl_frm(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); + + +#ifdef DOT11_N_SUPPORT +void DisplayTxAgg (RTMP_ADAPTER *pAd); +#endif /* DOT11_N_SUPPORT */ + +VOID set_default_ap_edca_param(RTMP_ADAPTER *pAd); +VOID set_default_sta_edca_param(RTMP_ADAPTER *pAd); + +UCHAR dot11_2_ra_rate(UCHAR MaxSupportedRateIn500Kbps); +UCHAR dot11_max_sup_rate(INT SupRateLen, UCHAR *SupRate, INT ExtRateLen, UCHAR *ExtRate); + +VOID tr_tb_reset_entry(RTMP_ADAPTER *pAd, UCHAR tr_tb_idx); +VOID tr_tb_set_entry(RTMP_ADAPTER *pAd, UCHAR tr_tb_idx, MAC_TABLE_ENTRY *pEntry); +VOID tr_tb_set_mcast_entry(RTMP_ADAPTER *pAd, UCHAR tr_tb_idx, struct wifi_dev *wdev); +VOID dump_tr_entry(RTMP_ADAPTER *pAd, INT tr_idx, RTMP_STRING *caller, INT line); + +VOID mgmt_tb_set_mcast_entry(RTMP_ADAPTER *pAd, UCHAR wcid); +VOID set_entry_phy_cfg(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry); +VOID MacTableReset(RTMP_ADAPTER *pAd, INT startWcid); +VOID MacTableResetWdev(RTMP_ADAPTER *pAd, struct wifi_dev *wdev); + +MAC_TABLE_ENTRY *MacTableLookup(RTMP_ADAPTER *pAd, UCHAR *pAddr); +#ifdef WH_EZ_SETUP +MAC_TABLE_ENTRY *MacTableLookup2(RTMP_ADAPTER *pAd, UCHAR *pAddr, struct wifi_dev *wdev); +#endif +BOOLEAN MacTableDeleteEntry(RTMP_ADAPTER *pAd, USHORT wcid, UCHAR *pAddr); +MAC_TABLE_ENTRY *MacTableInsertEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr, + IN struct wifi_dev *wdev, + IN UINT32 ent_type, + IN UCHAR OpMode, + IN BOOLEAN CleanAll); + +#ifdef MAC_REPEATER_SUPPORT +REPEATER_CLIENT_ENTRY *RTMPLookupRepeaterCliEntry( + IN VOID *pData, + IN BOOLEAN bRealMAC, + IN PUCHAR pAddr, + IN BOOLEAN bIsPad, + OUT PUCHAR pIsLinkValid); + + +BOOLEAN RTMPQueryLookupRepeaterCliEntryMT( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pAddr); + +VOID RTMPInsertRepeaterAsicEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR CliIdx, + IN PUCHAR pAddr); + +VOID RTMPRemoveRepeaterAsicEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR CliIdx); + +VOID RTMPInsertRepeaterEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR apidx, + IN PUCHAR pAddr); + +VOID RTMPRemoveRepeaterEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR func_tb_idx, + IN UCHAR CliIdx); + +VOID RTMPRepeaterReconnectionCheck( + IN RTMP_ADAPTER *pAd); + +MAC_TABLE_ENTRY *RTMPInsertRepeaterMacEntry( + IN RTMP_ADAPTER *pAd, + IN PUCHAR pAddr, + IN struct wifi_dev *wdev, + IN UCHAR apidx, + IN UCHAR cliIdx, + IN BOOLEAN CleanAll); + +BOOLEAN RTMPRepeaterVaildMacEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr); + +INVAILD_TRIGGER_MAC_ENTRY *RepeaterInvaildMacLookup( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr); + +VOID RTMPRepeaterInsertInvaildMacEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR *pAddr); + +BOOLEAN RTMPRepeaterRemoveInvaildMacEntry( + IN RTMP_ADAPTER *pAd, + IN UCHAR idx, + IN UCHAR *pAddr); + +INT Show_Repeater_Cli_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef MT_MAC +void insert_repeater_root_entry( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR *pAddr, + IN UCHAR ReptCliIdx); +#endif /* MT_MAC */ +#endif /* MAC_REPEATER_SUPPORT */ + +VOID dump_rxblk(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); + + +#ifdef RTMP_MAC_PCI +VOID dump_rxd(RTMP_ADAPTER *pAd, RXD_STRUC *pRxD); +#endif /* RTMP_MAC_PCI */ + +#ifdef MT_MAC +UINT32 parse_rx_packet_type(RTMP_ADAPTER *, RX_BLK *, VOID *); +#endif /* MT_MAC */ + +#ifdef CONFIG_FPGA_MODE +INT set_vco_cal(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_tr_stop(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_tx_kickcnt(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_data_phy_mode(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_data_bw(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_data_ldpc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_data_mcs(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_data_gi(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_data_basize(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_fpga_mode(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_loopback_mode(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef MT_MAC +INT set_txs_report_type(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_no_bcn(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* MT_MAC */ + + +#ifdef CAPTURE_MODE +VOID cap_mode_init(RTMP_ADAPTER *pAd); +VOID cap_mode_deinit(RTMP_ADAPTER *pAd); +INT set_cap_start(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_cap_trigger(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT asic_cap_start(RTMP_ADAPTER *pAd); +INT asic_cap_stop(RTMP_ADAPTER *pAd); +INT cap_status_chk_and_get(RTMP_ADAPTER *pAd); +INT set_cap_dump(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +VOID cap_dump(RTMP_ADAPTER *pAd, CHAR *bank1, CHAR *bank2, INT len); +#endif /* CAPTURE_MODE */ +#endif /* CONFIG_FPGA_MODE */ + +#if defined(WFA_VHT_PF) || defined(MT7603_FPGA) || defined(MT7628_FPGA) +INT set_force_amsdu(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* defined(WFA_VHT_PF) || defined(MT7603_FPGA) */ + +#ifdef WFA_VHT_PF +/* for SIGMA */ +INT set_vht_nss_mcs_cap(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_vht_nss_mcs_opt(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_vht_opmode_notify_ie(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT set_force_operating_mode(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_force_noack(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_force_vht_sgi(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_force_vht_tx_stbc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT set_force_ext_cca(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* WFA_VHT_PF */ + + + +INT SetRF(RTMP_ADAPTER *pAd, RTMP_STRING *Arg); +int write_reg(RTMP_ADAPTER *ad, UINT32 base, UINT16 offset, UINT32 value); +int read_reg(struct _RTMP_ADAPTER *ad, UINT32 base, UINT16 offset, UINT32 *value); +#ifdef DBG +INT show_pwr_info(RTMP_ADAPTER *ad, RTMP_STRING *arg); +#endif /* DBG */ + +#ifdef WSC_INCLUDED +#ifdef WSC_NFC_SUPPORT +INT RtmpOSNotifyRawData( + IN PNET_DEV pNetDev, + IN PUCHAR buff, + IN INT len, + IN ULONG type, + IN USHORT protocol); + +#endif /* WSC_NFC_SUPPORT */ +BOOLEAN WscProcessCredential( + IN PRTMP_ADAPTER pAdapter, + IN PUCHAR pPlainData, + IN INT PlainLength, + IN PWSC_CTRL pWscCtrl); +#endif /* WSC_INCLUDED */ + +#ifdef MT_MAC +VOID StatRateToString(RTMP_ADAPTER *pAd, CHAR *Output, UCHAR TxRx, UINT32 RawData); +#endif /* MT_MAC */ + +#ifdef P2P_CHANNEL_LIST_SEPARATE +UCHAR P2PChannelSanity( + IN PRTMP_ADAPTER pAd, + IN UCHAR channel); + +VOID P2PBuildChannelList( + IN PRTMP_ADAPTER pAd); + +BOOLEAN P2P_CHAN_PropertyCheck( + IN PRTMP_ADAPTER pAd, + IN UINT32 ChanNum, + IN UCHAR Property); +#endif /* P2P_CHANNEL_LIST_SEPARATE */ + + +VOID rtmp_ee_load_from_efuse(RTMP_ADAPTER *pAd); +#ifdef CONFIG_SNIFFER_SUPPORT +VOID Monitor_Init(RTMP_ADAPTER *pAd, RTMP_OS_NETDEV_OP_HOOK *pNetDevOps); +VOID Monitor_Remove(RTMP_ADAPTER *pAd); +BOOLEAN Monitor_Open(RTMP_ADAPTER *pAd, PNET_DEV dev_p); +BOOLEAN Monitor_Close(RTMP_ADAPTER *pAd, PNET_DEV dev_p); +#endif /* CONFIG_SNIFFER_SUPPORT */ + +#if defined(MT_MAC) && defined(WSC_INCLUDED) && defined(CONFIG_AP_SUPPORT) +VOID WscEapReqIdRetryTimeout( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); +#endif /* defined(MT_MAC) && defined(WSC_INCLUDED) && defined(CONFIG_AP_SUPPORT) */ + +#ifdef DYNAMIC_RX_RATE_ADJ +VOID UpdateSuppRateBitmap( + IN RTMP_ADAPTER *pAd); + +VOID UpdateSuppHTRateBitmap( + IN RTMP_ADAPTER *pAd); +#endif /* DYNAMIC_RX_RATE_ADJ */ + +VOID APMlmeDeauthReqAction( + IN PRTMP_ADAPTER pAd, + IN PMLME_QUEUE_ELEM Elem); + +#ifdef WH_EZ_SETUP +VOID RTMPCommSiteSurveyData( + IN RTMP_STRING *msg, + IN BSS_ENTRY *pBss, + IN UINT32 MsgLen); + VOID ApCliCtrlDeAuthAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +void ap_send_broadcast_deauth(void *ad_obj, struct wifi_dev *wdev); + +#ifdef EZ_NETWORK_MERGE_SUPPORT +VOID ez_APMlmeBroadcastDeauthReqAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +#endif +INT Show_EasySetupInfo_Proc( + RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_Debug_Proc( + RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_RoamTime_Proc( + RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_ssid_psk_proc( + RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_conf_ssid_psk_proc( + RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_nonman_proc( + RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_Best_Ap_RSSI_Threshold( + RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_Delay_Disconnect_Count_Proc( + RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_Wait_For_Info_Transfer_Proc( + RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_WDL_Missing_Time_Proc( + RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_Force_Connect_Bssid_Time_Proc( + RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_Peer_Entry_Age_Out_time_Proc( + RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_Scan_Same_Channel_Time_Proc( + RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_Partial_Scan_Time_Proc( + RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_EasySetup_ConfStatus_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +INT Set_EasySetup_GroupID_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +INT Set_EasySetup_Start_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +INT Set_EasySetup_GenGroupID_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +INT Set_EasySetup_RssiThreshold_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT ez_send_broadcast_deauth_proc( + IN RTMP_ADAPTER *pAd, + IN RTMP_STRING *arg); + +#ifdef EZ_NETWORK_MERGE_SUPPORT +INT set_EasySetup_MergeGroup_proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +#endif +#ifdef EZ_API_SUPPORT +INT set_EasySetup_Api_Mode( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +#endif +#ifdef NEW_CONNECTION_ALGO +INT Set_EasySetup_MaxScanDelay( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_EasySetup_Open_GenGroupID_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +INT Set_ez_connection_allow_all( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + + + +INT Set_EasySetup_ForceSsid_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +INT Set_EasySetup_ForceBssid_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +INT Set_EasySetup_ForceChannel_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +void ez_handle_pairmsg4(void *ad_obj, + IN MAC_TABLE_ENTRY *pEntry); + +INT Set_EasySetup_RoamBssid_Proc( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +#endif +#ifdef EZ_PUSH_BW_SUPPORT +INT Set_EasySetup_BWPushConfig( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +#endif + +#ifdef EZ_DUAL_BAND_SUPPORT +INT Set_EasySetup_LoopPktSend( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +#endif +int ez_parse_query_command( + void *ad_obj, + RTMP_IOCTL_INPUT_STRUCT *wrq, + IN int cmd); +int ez_parse_set_command( + void *ad_obj, + RTMP_IOCTL_INPUT_STRUCT *wrq, + IN int cmd); +VOID RTMPIoctlGetEzScanTable( + IN PRTMP_ADAPTER pAdapter, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); +BOOLEAN ez_probe_count_handle( + PAPCLI_STRUCT pApCliEntry); +BOOLEAN ez_join_timeout_handle( + void *ad_obj, + unsigned char ifIndex); +VOID ez_ApCliCtrlJoinFailAction( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +BOOLEAN ez_probe_rsp_join_action(void *ad_obj, + void *wdev_obj, + OUT BCN_IE_LIST *ie_list, + unsigned long Bssidx); +void ez_update_bss_entry(OUT BSS_ENTRY *pBss, + IN BCN_IE_LIST *ie_list); +void ez_vendor_ie_parse(struct _vendor_ie_cap *vendor_ie, + PEID_STRUCT info_elem); +void ez_push_handling_mactabledel(void *ad_obj, + IN MAC_TABLE_ENTRY *pEntry); +#endif + +#ifdef STA_FORCE_ROAM_SUPPORT + + +INT Set_FroamEn( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_FroamStaLowRssi( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_FroamStaLowRssiRenotify( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_FroamStaAgeTime( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_FroamMntrAgeTime( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_FroamMntrMinPktCount( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_FroamMntrMinTime( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_FroamMntrRssiPktCount( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_FroamStaGoodRssi( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_FroamAclAgeTime( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); + +INT Set_FroamAclHoldTime( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *arg); +#endif + +#ifdef WH_EZ_SETUP +UCHAR wmode_2_rfic(UCHAR PhyMode); +VOID APScanCnclAction( + RTMP_ADAPTER *pAd, + MLME_QUEUE_ELEM *Elem); +#endif +#ifdef NEW_IXIA_METHOD +extern UCHAR force_connect; +INT force_connect_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_pkt_threshld_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_chkT_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +INT Set_statistic_pktlen_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +void wifi_txrx_parmtrs_dump(RTMP_ADAPTER *pAd); + +extern int tx_pkt_from_os; +extern int tx_pkt_len; +extern int tx_pkt_to_hw; +extern int rx_pkt_len; +extern int rx_pkt_to_os; +extern int rx_pkt_from_hw; +extern unsigned char ixiatestmode; +extern char *tdrop_reason[MAX_TDROP_RESON]; +extern char *rdrop_reason[MAX_RDROP_RESON]; +extern UINT txpktdetect2s; +extern UINT rxpktdetect2s; +extern unsigned short dectlen_l; +extern unsigned short dectlen_m; +extern unsigned short dectlen_h; +extern UCHAR debuglvl; +#define IS_EXPECTED_LENGTH(len) (((len >= (dectlen_l - 4)) && (len <= dectlen_l))\ + || ((len >= (dectlen_m - 8)) && (len <= (dectlen_m + 8)))\ + || ((len >= (dectlen_h - 8)) && (len <= (dectlen_h + 8)))) +INT set_Protection_Parameter_Set_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif +struct wifi_dev *get_wdev_by_ioctl_idx_and_iftype(RTMP_ADAPTER *pAd, INT idx, INT if_type); +PUCHAR get_channelset_by_reg_class(RTMP_ADAPTER *pAd, UINT8 OperatingClass); +INT Set_Reg_Domain_Proc(IN PRTMP_ADAPTER pAd, IN RTMP_STRING *arg); +BOOLEAN IsPublicActionFrame(IN PRTMP_ADAPTER pAd, IN VOID *pbuf); + +#endif /* __RTMP_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_chip.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_chip.h new file mode 100644 index 000000000..a0aa6d892 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_chip.h @@ -0,0 +1,1500 @@ +/* + *************************************************************************** + * 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" +#include "eeprom.h" +#include "tx_power.h" + +#ifdef RTMP_MAC_PCI +#include "iface/rtmp_reg_pcirbs.h" +#endif /* RTMP_MAC_PCI */ + +#include "iface/iface.h" + +#include "mac/mac.h" +#include "mcu/mcu.h" + + + + + + + + + + + + + + + + + + + + + + + +#ifdef MT7603 +#include "chip/mt7603.h" +#endif /* MT7603 */ + + +#define IS_RT3090A(_pAd) ((((_pAd)->MACVersion & 0xffff0000) == 0x30900000)) + +/* We will have a cost down version which mac version is 0x3090xxxx */ +#define IS_RT3090(_pAd) ((((_pAd)->MACVersion & 0xffff0000) == 0x30710000) || (IS_RT3090A(_pAd))) + +#define IS_RT3070(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x30700000) +#define IS_RT3071(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x30710000) +#define IS_RT2070(_pAd) (((_pAd)->RfIcType == RFIC_2020) || ((_pAd)->EFuseTag == 0x27)) + +#define IS_RT2860(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x28600000) +#define IS_RT2870(_pAd) (IS_RT2860(_pAd) && IS_USB_INF(_pAd)) +#define IS_RT2872(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x28720000) +#define IS_RT2880(_pAd) (IS_RT2860(_pAd) && IS_RBUS_INF(_pAd)) + +#define IS_RT30xx(_pAd) (((_pAd)->MACVersion & 0xfff00000) == 0x30700000||IS_RT3090A(_pAd)||IS_RT3390(_pAd)) + +#define IS_RT3052B(_pAd) (((_pAd)->CommonCfg.CID == 0x102) && (((_pAd)->CommonCfg.CN >> 16) == 0x3033)) +#define IS_RT3052(_pAd) (((_pAd)->MACVersion == 0x28720200) && (_pAd->Antenna.field.TxPath == 2)) +#define IS_RT3050(_pAd) (((_pAd)->MACVersion == 0x28720200) && ((_pAd)->RfIcType == RFIC_3020)) +#define IS_RT3350(_pAd) (((_pAd)->MACVersion == 0x28720200) && ((_pAd)->RfIcType == RFIC_3320)) +#define IS_RT3352(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x33520000) +#define IS_RT5350(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x53500000) +#define IS_RT305x(_pAd) (IS_RT3050(_pAd) || IS_RT3052(_pAd) || IS_RT3350(_pAd) || IS_RT3352(_pAd) || IS_RT5350(_pAd)) +#define IS_RT3050_3052_3350(_pAd) (\ + ((_pAd)->MACVersion == 0x28720200) && \ + ((((_pAd)->CommonCfg.CN >> 16) == 0x3333) || (((_pAd)->CommonCfg.CN >> 16) == 0x3033)) \ +) +#define IS_RT6352(_pAd) ((((_pAd)->MACVersion & 0xFFFF0000) == 0x53900000) && ((_pAd)->infType == RTMP_DEV_INF_RBUS)) + + +/* RT3572, 3592, 3562, 3062 share the same MAC version */ +#define IS_RT3572(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x35720000) + +/* Check if it is RT3xxx, or Specified ID in registry for debug */ +#define IS_DEV_RT3xxx(_pAd)( \ + (_pAd->DeviceID == NIC3090_PCIe_DEVICE_ID) || \ + (_pAd->DeviceID == NIC3091_PCIe_DEVICE_ID) || \ + (_pAd->DeviceID == NIC3092_PCIe_DEVICE_ID) || \ + (_pAd->DeviceID == NIC3592_PCIe_DEVICE_ID) || \ + ((_pAd->DeviceID == NIC3593_PCI_OR_PCIe_DEVICE_ID) && (RT3593OverPCIe(_pAd))) \ +) + +#define RT3593_DEVICE_ID_CHECK(__DevId) \ + (0) + +#define RT3592_DEVICE_ID_CHECK(__DevId) \ + (__DevId == NIC3592_PCIe_DEVICE_ID) + +#define IS_RT2883(_pAd) (0) + +#define IS_RT3883(_pAd) (0) + +#define IS_VERSION_BEFORE_F(_pAd) (((_pAd)->MACVersion&0xffff) <= 0x0211) +/* F version is 0x0212, E version is 0x0211. 309x can save more power after F version. */ +#define IS_VERSION_AFTER_F(_pAd) ((((_pAd)->MACVersion&0xffff) >= 0x0212) || (((_pAd)->b3090ESpecialChip == TRUE))) + +#define IS_RT3290(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x32900000) +#define IS_RT3290LE(_pAd) ((((_pAd)->MACVersion & 0xffffffff) >= 0x32900011)) + +/* 3593 */ +#define IS_RT3593(_pAd) (((_pAd)->MACVersion & 0xFFFF0000) == 0x35930000) + +/* RT5392 */ +#define IS_RT5392(_pAd) ((_pAd->MACVersion & 0xFFFF0000) == 0x53920000) /* Include RT5392, RT5372 and RT5362 */ + +/* RT5390 */ +#define IS_RT5390(_pAd) (((((_pAd)->MACVersion & 0xFFFF0000) == 0x53900000) || IS_RT5390H(_pAd)) && ((_pAd)->infType != RTMP_DEV_INF_RBUS)) /* Include RT5390, RT5370 and RT5360 */ + +/* RT5390F */ +#define IS_RT5390F(_pAd) ((IS_RT5390(_pAd)) && (((_pAd)->MACVersion & 0x0000FFFF) >= 0x0502)) + +/* RT5370G */ +#define IS_RT5370G(_pAd) ((IS_RT5390(_pAd)) && (((_pAd)->MACVersion & 0x0000FFFF) >= 0x0503)) /* support HW PPAD ( the hardware rx antenna diversity ) */ + +/* RT5390R */ +#define IS_RT5390R(_pAd) ((IS_RT5390(_pAd)) && (((_pAd)->MACVersion & 0x0000FFFF) == 0x1502)) /* support HW PPAD ( the hardware rx antenna diversity ) */ + +/* PCIe interface NIC */ +#define IS_MINI_CARD(_pAd) ((_pAd)->Antenna.field.BoardType == BOARD_TYPE_MINI_CARD) + +/* 5390U (5370 using PCIe interface) */ +#define IS_RT5390U(_pAd) (IS_MINI_CARD(_pAd) && (((_pAd)->MACVersion & 0xFFFF0000) == 0x53900000) && ((_pAd)->infType != RTMP_DEV_INF_RBUS)) + +/* RT5390H */ +#define IS_RT5390H(_pAd) (((_pAd->MACVersion & 0xFFFF0000) == 0x53910000) && (((_pAd)->MACVersion & 0x0000FFFF) >= 0x1500)) + +/* RT5390BC8 (WiFi + BT) */ + + +/* RT5390D */ +#define IS_RT5390D(_pAd) ((IS_RT5390(_pAd)) && (((_pAd)->MACVersion & 0x0000FFFF) >= 0x0502)) + +/* RT5392C */ +#define IS_RT5392C(_pAd) ((IS_RT5392(_pAd)) && (((_pAd)->MACVersion & 0x0000FFFF) >= 0x0222)) /* Include RT5392, RT5372 and RT5362 */ + +#define IS_RT5592(_pAd) (((_pAd)->MACVersion & 0xFFFF0000) == 0x55920000) +#define REV_RT5592C 0x0221 + +#define IS_RT8592(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x85590000) + +#define IS_MT7601(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x76010000) +#define IS_MT7601U(_pAd) (IS_MT7601(_pAd) && (IS_USB_INF(_pAd))) + +#define IS_MT7650(_pAd) (((_pAd)->ChipID & 0xffff0000) == 0x76500000) +#define IS_MT7650E(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76500000) && (IS_PCIE_INF(_pAd))) +#define IS_MT7650U(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76500000) && (IS_USB_INF(_pAd))) +#define IS_MT7630(_pAd) (((_pAd)->ChipID & 0xffff0000) == 0x76300000) +#define IS_MT7630E(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76300000) && (IS_PCIE_INF(_pAd))) +#define IS_MT7630U(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76300000) && (IS_USB_INF(_pAd))) +#define IS_MT7610(_pAd) (((_pAd)->ChipID & 0xffff0000) == 0x76100000) +#define IS_MT7610E(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76100000) && (IS_PCIE_INF(_pAd))) +#define IS_MT7610U(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76100000) && (IS_USB_INF(_pAd))) +#define IS_MT76x0(_pAd) (IS_MT7610(_pAd) || IS_MT7630(_pAd) || IS_MT7650(_pAd)) +#define IS_MT76x0E(_pAd) (IS_MT7650E(_pAd) || IS_MT7630E(_pAd) || IS_MT7610E(_pAd)) +#define IS_MT76x0U(_pAd) (IS_MT7650U(_pAd) || IS_MT7630U(_pAd) || IS_MT7610U(_pAd)) + +#define IS_MT7662(_pAd) (((_pAd)->ChipID & 0xffff0000) == 0x76620000) +#define IS_MT7662E(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76620000) && (IS_PCIE_INF(_pAd))) +#define IS_MT7662U(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76620000) && (IS_USB_INF(_pAd))) +#define IS_MT7632(_pAd) (((_pAd)->ChipID & 0xffff0000) == 0x76320000) +#define IS_MT7632E(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76320000) && (IS_PCIE_INF(_pAd))) +#define IS_MT7632U(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76320000) && (IS_USB_INF(_pAd))) +#define IS_MT7612(_pAd) (((_pAd)->ChipID & 0xffff0000) == 0x76120000) +#define IS_MT7612E(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76120000) && (IS_PCIE_INF(_pAd))) +#define IS_MT7612U(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76120000) && (IS_USB_INF(_pAd))) +#define IS_MT7602(_pAd) (((_pAd)->ChipID & 0xffff0000) == 0x76020000) +#define IS_MT7602E(_pAd) ((((_pAd)->ChipID & 0xffff0000) == 0x76020000) && (IS_PCIE_INF(_pAd))) +#define IS_MT76x2(_pAd) (IS_MT7662(_pAd) || IS_MT7632(_pAd) || IS_MT7612(_pAd) || IS_MT7602(_pAd)) +#define IS_MT76x2E(_pAd) (IS_MT7662E(_pAd) || IS_MT7632E(_pAd) || IS_MT7612E(_pAd) || IS_MT7602E(_pAd)) +#define IS_MT76x2U(_pAd) (IS_MT7662U(_pAd) || IS_MT7632U(_pAd) || IS_MT7612U(_pAd)) +#define REV_MT76x2E3 0x0022 + +#define IS_MT76xx(_pAd) (IS_MT76x0(_pAd) || IS_MT76x2(_pAd)) + +#define IS_RT65XX(_pAd) ((((_pAd)->MACVersion & 0xFFFF0000) == 0x65900000) ||\ + (IS_RT8592(_pAd))||\ + (IS_MT76x0(_pAd)) ||\ + (IS_MT76x2(_pAd))) + + +#define IS_MT7603(_pAd) (((_pAd)->ChipID & 0x0000ffff) == 0x00007603) +#define IS_MT7603E(_pAd) ((((_pAd)->ChipID & 0x0000ffff) == 0x00007603) && IS_PCIE_INF(_pAd)) +#define IS_MT7603U(_pAd) ((((_pAd)->ChipID & 0x0000ffff) == 0x00007603) && IS_USB_INF(_pAd) && (_pAd->AntMode == 0)) +#define IS_MT76031U(_pAd) ((((_pAd)->ChipID & 0x0000ffff) == 0x00007603) && IS_USB_INF(_pAd) && (_pAd->AntMode == 1)) + +#define IS_MT7636(_pAd) ((((_pAd)->ChipID & 0x0000ffff) == 0x00007606)||(((_pAd)->ChipID & 0x0000ffff) == 0x00007636)) +#define IS_MT7636U(_pAd) ((((_pAd)->ChipID & 0x0000ffff) == 0x00007606) && IS_USB_INF(_pAd) + +#define MT7603E1 0x0000 +#define MT7603E2 0x0010 + +#define IS_MT7628(_pAd) (((_pAd)->MACVersion & 0xffff0000) == 0x76280000) + +#define MT7628E1 0x0000 +#define MT7628E2 0x0010 + +/* RT3592BC8 (WiFi + BT) */ + +#define IS_USB_INF(_pAd) ((_pAd)->infType == RTMP_DEV_INF_USB) +#define IS_USB3_INF(_pAd) ((IS_USB_INF(_pAd)) && ((_pAd)->BulkOutMaxPacketSize == 1024)) +#define IS_PCIE_INF(_pAd) ((_pAd)->infType == RTMP_DEV_INF_PCIE) +#define IS_PCI_INF(_pAd) (((_pAd)->infType == RTMP_DEV_INF_PCI) || IS_PCIE_INF(_pAd)) +#define IS_PCI_ONLY_INF(_pAd) ((_pAd)->infType == RTMP_DEV_INF_PCI) +#define IS_RBUS_INF(_pAd) ((_pAd)->infType == RTMP_DEV_INF_RBUS) + +#define RT_REV_LT(_pAd, _chip, _rev)\ + IS_##_chip(_pAd) && (((_pAd)->MACVersion & 0x0000FFFF) < (_rev)) + +#define RT_REV_GTE(_pAd, _chip, _rev)\ + IS_##_chip(_pAd) && (((_pAd)->MACVersion & 0x0000FFFF) >= (_rev)) + +#define MT_REV_LT(_pAd, _chip, _rev)\ + IS_##_chip(_pAd) && (((_pAd)->ChipID & 0x0000FFFF) < (_rev)) + +#define MT_REV_GTE(_pAd, _chip, _rev)\ + IS_##_chip(_pAd) && (((_pAd)->ChipID & 0x0000FFFF) >= (_rev)) + +#define MTK_REV_LT(_pAd, _chip, _rev)\ + IS_##_chip(_pAd) && (((_pAd)->HWVersion & 0x000000ff) < (_rev)) + +#define MTK_REV_GTE(_pAd, _chip, _rev)\ + IS_##_chip(_pAd) && (((_pAd)->HWVersion & 0x000000ff) >= (_rev)) + +/* Dual-band NIC (RF/BBP/MAC are in the same chip.) */ + +#define IS_RT_NEW_DUAL_BAND_NIC(_pAd) ((FALSE)) + + +/* Is the NIC dual-band NIC? */ + +#define IS_DUAL_BAND_NIC(_pAd) (((_pAd->RfIcType == RFIC_2850) || (_pAd->RfIcType == RFIC_2750) || (_pAd->RfIcType == RFIC_3052) \ + || (_pAd->RfIcType == RFIC_3053) || (_pAd->RfIcType == RFIC_2853) || (_pAd->RfIcType == RFIC_3853) \ + || IS_RT_NEW_DUAL_BAND_NIC(_pAd)) && !IS_RT5390(_pAd)) + + +/* RT3593 over PCIe bus */ +#define RT3593OverPCIe(_pAd) (IS_RT3593(_pAd) && (_pAd->CommonCfg.bPCIeBus == TRUE)) + +/* RT3593 over PCI bus */ +#define RT3593OverPCI(_pAd) (IS_RT3593(_pAd) && (_pAd->CommonCfg.bPCIeBus == FALSE)) + +/*RT3390,RT3370 */ +#define IS_RT3390(_pAd) (((_pAd)->MACVersion & 0xFFFF0000) == 0x33900000) + +#define CCA_AVG_MAX_COUNT 5 + +/* ------------------------------------------------------ */ +/* PCI registers - base address 0x0000 */ +/* ------------------------------------------------------ */ +#define CHIP_PCI_CFG 0x0000 +#define CHIP_PCI_EECTRL 0x0004 +#define CHIP_PCI_MCUCTRL 0x0008 + +#define OPT_14 0x114 + +#define RETRY_LIMIT 10 + +/* ------------------------------------------------------ */ +/* BBP & RF definition */ +/* ------------------------------------------------------ */ +#define BUSY 1 +#define IDLE 0 + +/*------------------------------------------------------------------------- */ +/* EEPROM definition */ +/*------------------------------------------------------------------------- */ +#define EEDO 0x08 +#define EEDI 0x04 +#define EECS 0x02 +#define EESK 0x01 +#define EERL 0x80 + +#define EEPROM_WRITE_OPCODE 0x05 +#define EEPROM_READ_OPCODE 0x06 +#define EEPROM_EWDS_OPCODE 0x10 +#define EEPROM_EWEN_OPCODE 0x13 + +#define NUM_EEPROM_BBP_PARMS 19 /* Include NIC Config 0, 1, CR, TX ALC step, BBPs */ +#define NUM_EEPROM_TX_G_PARMS 7 + +#define VALID_EEPROM_VERSION 1 +#define EEPROM_VERSION_OFFSET 0x02 +#define EEPROM_NIC1_OFFSET 0x34 /* The address is from NIC config 0, not BBP register ID */ +#define EEPROM_NIC2_OFFSET 0x36 /* The address is from NIC config 1, not BBP register ID */ + + +#define EEPROM_COUNTRY_REGION 0x38 +#define COUNTRY_REGION_A_BAND_MASK (0xff) +#define COUNTRY_REGION_G_BAND (0xff << 8) + +#define EEPROM_DEFINE_MAX_TXPWR 0x4e +#define MAX_EIRP_TX_PWR_G_BAND_MASK (0xff) +#define MAX_EIRP_TX_PWR_A_BAND_MASK (0xff << 8) + +#define EEPROM_FREQ_OFFSET 0x3a +#define FREQ_OFFSET_MASK (0x7f) +#define FREQ_OFFSET_DIP (1 << 7) +#define LED_MODE_MASK (0xff << 8) + +#define EEPROM_LEDAG_CONF_OFFSET 0x3c +#define EEPROM_LEDACT_CONF_OFFSET 0x3e +#define EEPROM_LED_POLARITY_OFFSET 0x40 + +#define EEPROM_LNA_OFFSET 0x44 +#define LNA_GAIN_G_BAND_MASK (0x7f) +#define LNA_GAIN_G_BAND_EN (1 << 7) +#define LNA_GAIN_A_BAND_CH36_64_MASK (0x7f << 8) +#define LNA_GAIN_A_BAND_CH36_64_EN (1 << 15) + +#define EEPROM_RSSI_BG_OFFSET 0x46 +#define RSSI0_OFFSET_G_BAND_MASK (0x3f) +#define RSSI0_OFFSET_G_BAND_SIGN (1 << 6) +#define RSSI0_OFFSET_G_BAND_EN (1 << 7) +#define RSSI1_OFFSET_G_BAND_MASK (0x3f << 8) +#define RSSI1_OFFSET_G_BAND_SIGN (1 << 14) +#define RSSI1_OFFSET_G_BAND_EN (1 << 15) + +#define EEPROM_TXMIXER_GAIN_2_4G 0x48 +#define LNA_GAIN_A_BAND_CH100_128_MASK (0x7f << 8) +#define LNA_GAIN_A_BAND_CH100_128_EN (1 << 15) + +#define EEPROM_RSSI_A_OFFSET 0x4a +#define RSSI0_OFFSET_A_BAND_MASK (0x3f) +#define RSSI0_OFFSET_A_BAND_SIGN (1 << 6) +#define RSSI0_OFFSET_A_BANE_EN (1 << 7) +#define RSSI1_OFFSET_A_BAND_MASK (0x3f << 8) +#define RSSI1_OFFSET_A_BAND_SIGN (1 << 14) +#define RSSI1_OFFSET_A_BAND_EN (1 << 15) + +#define EEPROM_TXMIXER_GAIN_5G 0x4c +#define LNA_GAIN_A_BAND_CH132_165_MASK (0x7f << 8) +#define LNA_GAIN_A_BAND_CH132_165_EN (1 << 15) + +#define EEPROM_TXPOWER_DELTA 0x50 /* 20MHZ AND 40 MHZ use different power. This is delta in 40MHZ. */ + +#define EEPROM_G_TX_PWR_OFFSET 0x52 +#define EEPROM_G_TX2_PWR_OFFSET 0x60 + +#define EEPROM_G_TSSI_BOUND1 0x6e +#define EEPROM_G_TSSI_BOUND2 0x70 +#define EEPROM_G_TSSI_BOUND3 0x72 +#define EEPROM_G_TSSI_BOUND4 0x74 +#define EEPROM_G_TSSI_BOUND5 0x76 + + + +#define EEPROM_A_TX_PWR_OFFSET 0x78 +#define EEPROM_A_TX2_PWR_OFFSET 0xa6 + +#define MBSSID_MODE0 0 +#define MBSSID_MODE1 1 /* Enhance NEW MBSSID MODE mapping to mode 0 */ +//Force selectable +#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 */ + +enum FREQ_CAL_INIT_MODE { + FREQ_CAL_INIT_MODE0, + FREQ_CAL_INIT_MODE1, + FREQ_CAL_INIT_MODE2, + FREQ_CAL_INIT_UNKNOW, +}; + +enum FREQ_CAL_MODE { + FREQ_CAL_MODE0, + FREQ_CAL_MODE1, + FREQ_CAL_MODE2, +}; + +enum RXWI_FRQ_OFFSET_FIELD { + RXWI_FRQ_OFFSET_FIELD0, /* SNR1 */ + RXWI_FRQ_OFFSET_FIELD1, /* Frequency Offset */ +}; + + + +#define EEPROM_A_TSSI_BOUND1 0xd4 +#define EEPROM_A_TSSI_BOUND2 0xd6 +#define EEPROM_A_TSSI_BOUND3 0xd8 +#define EEPROM_A_TSSI_BOUND4 0xda +#define EEPROM_A_TSSI_BOUND5 0xdc + + + +#define EEPROM_TXPOWER_BYRATE 0xde /* 20MHZ power. */ +#define EEPROM_TXPOWER_BYRATE_20MHZ_2_4G 0xde /* 20MHZ 2.4G tx power. */ +#define EEPROM_TXPOWER_BYRATE_40MHZ_2_4G 0xee /* 40MHZ 2.4G tx power. */ +#define EEPROM_TXPOWER_BYRATE_20MHZ_5G 0xfa /* 20MHZ 5G tx power. */ +#define EEPROM_TXPOWER_BYRATE_40MHZ_5G 0x10a /* 40MHZ 5G tx power. */ + +#define EEPROM_BBP_BASE_OFFSET 0xf0 /* The address is from NIC config 0, not BBP register ID */ + +/* */ +/* Bit mask for the Tx ALC and the Tx fine power control */ +/* */ +#define GET_TX_ALC_BIT_MASK 0x1F /* Valid: 0~31, and in 0.5dB step */ +#define GET_TX_FINE_POWER_CTRL_BIT_MASK 0xE0 /* Valid: 0~4, and in 0.1dB step */ +#define NUMBER_OF_BITS_FOR_TX_ALC 5 /* The length, in bit, of the Tx ALC field */ + + +/* TSSI gain and TSSI attenuation */ + +#define EEPROM_TSSI_GAIN_AND_ATTENUATION 0x76 + +/*#define EEPROM_Japan_TX_PWR_OFFSET 0x90 // 802.11j */ +/*#define EEPROM_Japan_TX2_PWR_OFFSET 0xbe */ +/*#define EEPROM_TSSI_REF_OFFSET 0x54 */ +/*#define EEPROM_TSSI_DELTA_OFFSET 0x24 */ +/*#define EEPROM_CCK_TX_PWR_OFFSET 0x62 */ +/*#define EEPROM_CALIBRATE_OFFSET 0x7c */ + +#define EEPROM_NIC_CFG1_OFFSET 0 +#define EEPROM_NIC_CFG2_OFFSET 1 +#define EEPROM_NIC_CFG3_OFFSET 2 +#define EEPROM_COUNTRY_REG_OFFSET 3 +#define EEPROM_BBP_ARRAY_OFFSET 4 + +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) +/* */ +/* The TSSI over OFDM 54Mbps */ +/* */ +#define EEPROM_TSSI_OVER_OFDM_54 0x6E + +/* */ +/* The TSSI value/step (0.5 dB/unit) */ +/* */ +#define EEPROM_TSSI_STEP_OVER_2DOT4G 0x77 +#define EEPROM_TSSI_STEP_OVER_5DOT5G 0xDD +#define TSSI_READ_SAMPLE_NUM 3 + +/* */ +/* Per-channel Tx power offset (for the extended TSSI mode) */ +/* */ +#define EEPROM_TX_POWER_OFFSET_OVER_CH_1 0x6F +#define EEPROM_TX_POWER_OFFSET_OVER_CH_3 0x70 +#define EEPROM_TX_POWER_OFFSET_OVER_CH_5 0x71 +#define EEPROM_TX_POWER_OFFSET_OVER_CH_7 0x72 +#define EEPROM_TX_POWER_OFFSET_OVER_CH_9 0x73 +#define EEPROM_TX_POWER_OFFSET_OVER_CH_11 0x74 +#define EEPROM_TX_POWER_OFFSET_OVER_CH_13 0x75 + +/* */ +/* Tx power configuration (bit3:0 for Tx0 power setting and bit7:4 for Tx1 power setting) */ +/* */ +#define EEPROM_CCK_MCS0_MCS1 0xDE +#define EEPROM_CCK_MCS2_MCS3 0xDF +#define EEPROM_OFDM_MCS0_MCS1 0xE0 +#define EEPROM_OFDM_MCS2_MCS3 0xE1 +#define EEPROM_OFDM_MCS4_MCS5 0xE2 +#define EEPROM_OFDM_MCS6_MCS7 0xE3 +#define EEPROM_HT_MCS0_MCS1 0xE4 +#define EEPROM_HT_MCS2_MCS3 0xE5 +#define EEPROM_HT_MCS4_MCS5 0xE6 +#define EEPROM_HT_MCS6_MCS7 0xE7 +#define EEPROM_HT_MCS8_MCS9 0xE8 +#define EEPROM_HT_MCS10_MCS11 0xE9 +#define EEPROM_HT_MCS12_MCS13 0xEA +#define EEPROM_HT_MCS14_MCS15 0xEB +#define EEPROM_HT_USING_STBC_MCS0_MCS1 0xEC +#define EEPROM_HT_USING_STBC_MCS2_MCS3 0xED +#define EEPROM_HT_USING_STBC_MCS4_MCS5 0xEE +#define EEPROM_HT_USING_STBC_MCS6_MCS7 0xEF + +/* */ +/* Bit mask for the Tx ALC and the Tx fine power control */ +/* */ + +#define DEFAULT_BBP_TX_FINE_POWER_CTRL 0 + +#endif /* RTMP_INTERNAL_TX_ALC || RTMP_TEMPERATURE_COMPENSATION */ + + +#ifdef RT_BIG_ENDIAN +typedef union _EEPROM_ANTENNA_STRUC { + struct { + USHORT RssiIndicationMode:1; /* RSSI indication mode */ + USHORT Rsv:1; + USHORT BoardType:2; /* 0: mini card; 1: USB pen */ + USHORT RfIcType:4; /* see E2PROM document */ + USHORT TxPath:4; /* 1: 1T, 2: 2T, 3: 3T */ + USHORT RxPath:4; /* 1: 1R, 2: 2R, 3: 3R */ + } field; + USHORT word; +} EEPROM_ANTENNA_STRUC, *PEEPROM_ANTENNA_STRUC; +#else +typedef union _EEPROM_ANTENNA_STRUC { + struct { + USHORT RxPath:4; /* 1: 1R, 2: 2R, 3: 3R */ + USHORT TxPath:4; /* 1: 1T, 2: 2T, 3: 3T */ + USHORT RfIcType:4; /* see E2PROM document */ + USHORT BoardType:2; /* 0: mini card; 1: USB pen */ + USHORT Rsv:1; + USHORT RssiIndicationMode:1; /* RSSI indication mode */ + } field; + USHORT word; +} EEPROM_ANTENNA_STRUC, *PEEPROM_ANTENNA_STRUC; +#endif + + +/* + * EEPROM operation related marcos + */ +#define RT28xx_EEPROM_READ16(_pAd, _offset, _val) rt28xx_eeprom_read16(_pAd, _offset, &(_val)) + +#define RT28xx_EEPROM_WRITE16(_pAd, _offset, _val) \ + do {\ + if ((_pAd)->chipOps.eewrite) \ + (_pAd)->chipOps.eewrite(_pAd, (_offset), (USHORT)(_val));\ + } while(0) + +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) +/* The Tx power tuning entry */ +typedef struct _TX_POWER_TUNING_ENTRY_STRUCT { + CHAR RF_TX_ALC; /* 3390: RF R12[4:0]: Tx0 ALC, 5390: RF R49[5:0]: Tx0 ALC */ + CHAR MAC_PowerDelta; /* Tx power control over MAC 0x1314~0x1324 */ +} TX_POWER_TUNING_ENTRY_STRUCT, *PTX_POWER_TUNING_ENTRY_STRUCT; +#endif /* defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) */ + +struct RF_BANK_OFFSET { + UINT8 RFBankIndex; + UINT16 RFStart; + UINT16 RFEnd; +}; + +struct RF_INDEX_OFFSET { + UINT8 RFIndex; + UINT16 RFStart; + UINT16 RFEnd; +}; + +/* + 2860: 28xx + 2870: 28xx + + 30xx: + 3090 + 3070 + 2070 3070 + + 33xx: 30xx + 3390 3090 + 3370 3070 + + 35xx: 30xx + 3572, 2870, 28xx + 3062, 2860, 28xx + 3562, 2860, 28xx + + 3593, 28xx, 30xx, 35xx + + < Note: 3050, 3052, 3350 can not be compiled simultaneously. > + 305x: + 3052 + 3050 + 3350, 3050 + + 3352: 305x + + 2880: 28xx + 2883: + 3883: +*/ + +struct _RTMP_CHIP_CAP { + /* ------------------------ packet --------------------- */ + UINT8 TXWISize; // TxWI or LMAC TxD max size + UINT8 RXWISize; // RxWI or LMAC RxD max size + UINT8 tx_hw_hdr_len; // Tx Hw meta info size which including all hw info fields + UINT8 rx_hw_hdr_len; // Rx Hw meta info size + + enum ASIC_CAP asic_caps; + enum PHY_CAP phy_caps; + enum HIF_TYPE hif_type; + enum MAC_TYPE mac_type; + enum BBP_TYPE bbp_type; + enum MCU_TYPE MCUType; + enum RF_TYPE rf_type; + + /* 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] or RF5[7] */ + UINT8 FlgIsVcoReCalMode; + + BOOLEAN FlgIsHwAntennaDiversitySup; + BOOLEAN Flg7662ChipCap; +#ifdef STREAM_MODE_SUPPORT + BOOLEAN FlgHwStreamMode; +#endif /* STREAM_MODE_SUPPORT */ +#ifdef FIFO_EXT_SUPPORT + BOOLEAN FlgHwFifoExtCap; +#endif /* FIFO_EXT_SUPPORT */ + + UCHAR ba_max_cnt; + +#ifdef RTMP_MAC_PCI +#endif /* RTMP_MAC_PCI */ + +#ifdef TXRX_SW_ANTDIV_SUPPORT + BOOLEAN bTxRxSwAntDiv; +#endif /* TXRX_SW_ANTDIV_SUPPORT */ + +#ifdef DYNAMIC_VGA_SUPPORT + BOOLEAN dynamic_vga_support; +#endif /* DYNAMIC_VGA_SUPPORT */ + + /* ---------------------------- signal ---------------------------------- */ +#define SNR_FORMULA1 0 /* ((0xeb - pAd->StaCfg.wdev.LastSNR0) * 3) / 16; */ +#define SNR_FORMULA2 1 /* (pAd->StaCfg.wdev.LastSNR0 * 3 + 8) >> 4; */ +#define SNR_FORMULA3 2 /* (pAd->StaCfg.wdev.LastSNR0) * 3) / 16; */ +#define SNR_FORMULA4 3 /* for MT7603 */ + UINT8 SnrFormula; + + UINT8 max_nss; /* maximum Nss, 3 for 3883 or 3593 */ + UINT8 max_vht_mcs; /* Maximum Vht MCS */ + + BOOLEAN bTempCompTxALC; + BOOLEAN rx_temp_comp; + + BOOLEAN bLimitPowerRange; /* TSSI compensation range limit */ + +#if defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) + UINT8 TxAlcTxPowerUpperBound_2G; + const TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTable_2G; +#ifdef A_BAND_SUPPORT + UINT8 TxAlcTxPowerUpperBound_5G; + const TX_POWER_TUNING_ENTRY_STRUCT *TxPowerTuningTable_5G; +#endif /* A_BAND_SUPPORT */ + +#endif /* defined(RTMP_INTERNAL_TX_ALC) || defined(RTMP_TEMPERATURE_COMPENSATION) */ + +#if defined(RTMP_INTERNAL_TX_ALC) || defined(SINGLE_SKU_V2) + INT16 PAModeCCK[4]; + INT16 PAModeOFDM[8]; + INT16 PAModeHT[16]; +#ifdef DOT11_VHT_AC + INT16 PAModeVHT[10]; +#endif /* DOT11_VHT_AC */ +#endif /* defined(RTMP_INTERNAL_TX_ALC) || defined(SINGLE_SKU_V2) */ + + + /* ---------------------------- others ---------------------------------- */ +#ifdef RTMP_EFUSE_SUPPORT + UINT16 EFUSE_USAGE_MAP_START; + UINT16 EFUSE_USAGE_MAP_END; + UINT8 EFUSE_USAGE_MAP_SIZE; + UINT8 EFUSE_RESERVED_SIZE; +#endif /* RTMP_EFUSE_SUPPORT */ + + UCHAR *EEPROM_DEFAULT_BIN; + UINT16 EEPROM_DEFAULT_BIN_SIZE; + +#ifdef RTMP_FLASH_SUPPORT + BOOLEAN ee_inited; +#endif /* RTMP_FLASH_SUPPORT */ +#ifdef CARRIER_DETECTION_SUPPORT + UCHAR carrier_func; +#endif /* CARRIER_DETECTION_SUPPORT */ +#ifdef DFS_SUPPORT + UINT8 DfsEngineNum; +#endif /* DFS_SUPPORT */ + + /* + Define the burst size of WPDMA of PCI + 0 : 4 DWORD (16bytes) + 1 : 8 DWORD (32 bytes) + 2 : 16 DWORD (64 bytes) + 3 : 32 DWORD (128 bytes) + */ + UINT8 WPDMABurstSIZE; + + /* + * 0: MBSSID_MODE0 + * (The multiple MAC_ADDR/BSSID are distinguished by [bit2:bit0] of byte5) + * 1: MBSSID_MODE1 + * (The multiple MAC_ADDR/BSSID are distinguished by [bit4:bit2] of byte0) + */ + UINT8 MBSSIDMode; + +#ifdef DOT11W_PMF_SUPPORT +#define PMF_ENCRYPT_MODE_0 0 /* All packets must software encryption. */ +#define PMF_ENCRYPT_MODE_1 1 /* Data packets do hardware encryption, management packet do software encryption. */ +#define PMF_ENCRYPT_MODE_2 2 /* Data and management packets do hardware encryption. */ + UINT8 FlgPMFEncrtptMode; +#endif /* DOT11W_PMF_SUPPORT */ + + +#ifdef RT5592EP_SUPPORT + UINT32 Priv; /* Flag for RT5592 EP */ +#endif /* RT5592EP_SUPPORT */ + + +#ifdef CONFIG_ANDES_SUPPORT + UINT32 WlanMemmapOffset; + UINT32 InbandPacketMaxLen; /* must be 48 multible */ + UINT8 CmdRspRxRing; + BOOLEAN IsComboChip; + BOOLEAN need_load_fw; + BOOLEAN need_load_rom_patch; + UINT8 ram_code_protect; + UINT8 rom_code_protect; + UINT8 load_iv; + UINT32 ilm_offset; + UINT32 dlm_offset; + UINT32 rom_patch_offset; + UINT8 DownLoadType; +#endif + + UINT8 cmd_header_len; + UINT8 cmd_padding_len; + +#ifdef SINGLE_SKU_V2 + CHAR Apwrdelta; + CHAR Gpwrdelta; +#endif /* SINGLE_SKU_V2 */ + + +#ifdef CONFIG_SWITCH_CHANNEL_OFFLOAD + UINT16 ChannelParamsSize; + UCHAR *ChannelParam; + INT XtalType; +#endif + + UCHAR load_code_method; + UCHAR *FWImageName; + UCHAR *fw_header_image; + UCHAR *fw_bin_file_name; + UCHAR *rom_patch; + UCHAR *rom_patch_header_image; + UCHAR *rom_patch_bin_file_name; + UINT32 rom_patch_len; + UINT32 fw_len; + UCHAR *MACRegisterVer; + UCHAR *BBPRegisterVer; + UCHAR *RFRegisterVer; + +#ifdef CONFIG_WIFI_TEST + UINT32 MemMapStart; + UINT32 MemMapEnd; + UINT32 BBPMemMapOffset; + UINT16 BBPStart; + UINT16 BBPEnd; + UINT16 RFStart; + UINT16 RFEnd; +#ifdef RLT_RF + UINT8 RFBankNum; + struct RF_BANK_OFFSET *RFBankOffset; +#endif +#ifdef MT_RF + UINT8 RFIndexNum; + struct RF_INDEX_OFFSET *RFIndexOffset; +#endif + UINT32 MacMemMapOffset; + UINT32 MacStart; + UINT32 MacEnd; + UINT16 E2PStart; + UINT16 E2PEnd; + BOOLEAN pbf_loopback; + BOOLEAN pbf_rx_drop; +#endif /* CONFIG_WIFI_TEST */ + + BOOLEAN tssi_enable; + +#ifdef MT_MAC + struct MT_TX_PWR_CAP MTTxPwrCap; + UCHAR TmrEnable; +#endif + + + UINT8 TxBAWinSize; + UINT8 RxBAWinSize; + UINT8 AMPDUFactor; + UINT8 BiTxOpOn; + + UINT32 CurrentTxOP; +}; + + +struct _RSSI_SAMPLE; + +struct _RTMP_CHIP_OP { + int (*sys_onoff)(struct _RTMP_ADAPTER *pAd, BOOLEAN on, BOOLEAN reser); + + /* Calibration access related callback functions */ + int (*eeinit)(struct _RTMP_ADAPTER *pAd); + BOOLEAN (*eeread)(struct _RTMP_ADAPTER *pAd, UINT16 offset, USHORT *pValue); + int (*eewrite)(struct _RTMP_ADAPTER *pAd, USHORT offset, USHORT value); + + /* ITxBf calibration */ + int (*fITxBfDividerCalibration)(struct _RTMP_ADAPTER *pAd, int calFunction, int calMethod, UCHAR *divPhase); + void (*fITxBfLNAPhaseCompensate)(struct _RTMP_ADAPTER *pAd); + int (*fITxBfCal)(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); + int (*fITxBfLNACalibration)(struct _RTMP_ADAPTER *pAd, int calFunction, int calMethod, BOOLEAN gBand); + + /* MCU related callback functions */ + int (*load_rom_patch)(struct _RTMP_ADAPTER *ad); + int (*erase_rom_patch)(struct _RTMP_ADAPTER *ad); + int (*loadFirmware)(struct _RTMP_ADAPTER *pAd); + int (*eraseFirmware)(struct _RTMP_ADAPTER *pAd); + int (*sendCommandToMcu)(struct _RTMP_ADAPTER *pAd, UCHAR cmd, UCHAR token, UCHAR arg0, UCHAR arg1, BOOLEAN FlgIsNeedLocked); /* int (*sendCommandToMcu)(RTMP_ADAPTER *pAd, UCHAR cmd, UCHAR token, UCHAR arg0, UCHAR arg1); */ +#ifdef CONFIG_ANDES_SUPPORT + int (*sendCommandToAndesMcu)(struct _RTMP_ADAPTER *pAd, UCHAR QueIdx, UCHAR cmd, UCHAR *pData, USHORT DataLen, BOOLEAN FlgIsNeedLocked); +#endif + + void (*AsicRfInit)(struct _RTMP_ADAPTER *pAd); + void (*AsicBbpInit)(struct _RTMP_ADAPTER *pAd); + void (*AsicMacInit)(struct _RTMP_ADAPTER *pAd); + + void (*AsicRfTurnOn)(struct _RTMP_ADAPTER *pAd); + void (*AsicRfTurnOff)(struct _RTMP_ADAPTER *pAd); + void (*AsicReverseRfFromSleepMode)(struct _RTMP_ADAPTER *pAd, BOOLEAN FlgIsInitState); + void (*AsicHaltAction)(struct _RTMP_ADAPTER *pAd); + + /* Power save */ + void (*EnableAPMIMOPS)(struct _RTMP_ADAPTER *pAd, IN BOOLEAN ReduceCorePower); + void (*DisableAPMIMOPS)(struct _RTMP_ADAPTER *pAd); + INT (*PwrSavingOP)(struct _RTMP_ADAPTER *pAd, UINT32 PwrOP, UINT32 PwrLevel, + UINT32 ListenInterval, UINT32 PreTBTTLeadTime, + UINT8 TIMByteOffset, UINT8 TIMBytePattern); + + /* Chip tuning */ + VOID (*RxSensitivityTuning)(IN struct _RTMP_ADAPTER *pAd); + + /* MAC */ + VOID (*BeaconUpdate)(struct _RTMP_ADAPTER *pAd, USHORT Offset, UINT32 Value, UINT8 Unit); + + /* BBP adjust */ + VOID (*ChipBBPAdjust)(IN struct _RTMP_ADAPTER *pAd); + + /* AGC */ + VOID (*ChipAGCInit)(struct _RTMP_ADAPTER *pAd, UCHAR bw); + UCHAR (*ChipAGCAdjust)(struct _RTMP_ADAPTER *pAd, CHAR Rssi, UCHAR OrigR66Value); + + /* Channel */ + VOID (*ChipSwitchChannel)(struct _RTMP_ADAPTER *pAd, UCHAR ch, BOOLEAN bScan); + + /* EDCCA */ + VOID (*ChipSetEDCCA)(struct _RTMP_ADAPTER *pAd, BOOLEAN bOn); + + /* IQ Calibration */ + VOID (*ChipIQCalibration)(struct _RTMP_ADAPTER *pAd, UCHAR Channel); + + /* TX ALC */ + UINT32 (*TSSIRatio)(INT32 delta_power); + VOID (*InitDesiredTSSITable)(IN struct _RTMP_ADAPTER *pAd); + int (*ATETssiCalibration)(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); + int (*ATETssiCalibrationExtend)(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); + int (*ATEReadExternalTSSI)(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); + + VOID (*AsicTxAlcGetAutoAgcOffset)( + IN struct _RTMP_ADAPTER *pAd, + IN PCHAR pDeltaPwr, + IN PCHAR pTotalDeltaPwr, + IN PCHAR pAgcCompensate, + IN PCHAR pDeltaPowerByBbpR1); + + VOID (*AsicGetTxPowerOffset)(struct _RTMP_ADAPTER *pAd, ULONG *TxPwr); + VOID (*AsicExtraPowerOverMAC)(struct _RTMP_ADAPTER *pAd); + + VOID (*AsicAdjustTxPower)(struct _RTMP_ADAPTER *pAd); + + /* Antenna */ + VOID (*AsicAntennaDefaultReset)(struct _RTMP_ADAPTER *pAd, union _EEPROM_ANTENNA_STRUC *pAntenna); + VOID (*SetRxAnt)(struct _RTMP_ADAPTER *pAd, UCHAR Ant); + + /* EEPROM */ + VOID (*NICInitAsicFromEEPROM)(IN struct _RTMP_ADAPTER *pAd); + + /* Temperature Compensation */ + VOID (*InitTemperCompensation)(IN struct _RTMP_ADAPTER *pAd); + VOID (*TemperCompensation)(IN struct _RTMP_ADAPTER *pAd); + + /* high power tuning */ + VOID (*HighPowerTuning)(struct _RTMP_ADAPTER *pAd, struct _RSSI_SAMPLE *pRssi); + + /* Others */ + VOID (*NetDevNickNameInit)(IN struct _RTMP_ADAPTER *pAd); +#ifdef CAL_FREE_IC_SUPPORT + BOOLEAN (*is_cal_free_ic)(IN struct _RTMP_ADAPTER *pAd); + VOID (*cal_free_data_get)(IN struct _RTMP_ADAPTER *pAd); +#endif /* CAL_FREE_IC_SUPPORT */ + + /* The chip specific function list */ + + VOID (*AsicResetBbpAgent)(IN struct _RTMP_ADAPTER *pAd); + +#ifdef CARRIER_DETECTION_SUPPORT + VOID (*ToneRadarProgram)(struct _RTMP_ADAPTER *pAd, ULONG threshold); +#endif /* CARRIER_DETECTION_SUPPORT */ + VOID (*CckMrcStatusCtrl)(struct _RTMP_ADAPTER *pAd); + VOID (*RadarGLRTCompensate)(struct _RTMP_ADAPTER *pAd); + VOID (*SecondCCADetection)(struct _RTMP_ADAPTER *pAd); + + /* MCU */ + void (*MCUCtrlInit)(struct _RTMP_ADAPTER *ad); + void (*MCUCtrlExit)(struct _RTMP_ADAPTER *ad); + VOID (*FwInit)(struct _RTMP_ADAPTER *pAd); + VOID (*FwExit)(struct _RTMP_ADAPTER *pAd); + int (*BurstWrite)(struct _RTMP_ADAPTER *ad, UINT32 Offset, UINT32 *Data, UINT32 Cnt); + int (*BurstRead)(struct _RTMP_ADAPTER *ad, UINT32 Offset, UINT32 Cnt, UINT32 *Data); + int (*RandomRead)(struct _RTMP_ADAPTER *ad, RTMP_REG_PAIR *RegPair, UINT32 Num); + int (*RFRandomRead)(struct _RTMP_ADAPTER *ad, BANK_RF_REG_PAIR *RegPair, UINT32 Num); + int (*ReadModifyWrite)(struct _RTMP_ADAPTER *ad, R_M_W_REG *RegPair, UINT32 Num); + int (*RFReadModifyWrite)(struct _RTMP_ADAPTER *ad, RF_R_M_W_REG *RegPair, UINT32 Num); + int (*RandomWrite)(struct _RTMP_ADAPTER *ad, RTMP_REG_PAIR *RegPair, UINT32 Num); + int (*RFRandomWrite)(struct _RTMP_ADAPTER *ad, BANK_RF_REG_PAIR *RegPair, UINT32 Num); +#ifdef CONFIG_ANDES_BBP_RANDOM_WRITE_SUPPORT + int (*BBPRandomWrite)(struct _RTMP_ADAPTER *ad, RTMP_REG_PAIR *RegPair, UINT32 Num); +#endif /* CONFIG_ANDES_BBP_RANDOM_WRITE_SUPPORT */ + int (*sc_random_write)(struct _RTMP_ADAPTER *ad, CR_REG *table, UINT32 num, UINT32 flags); + int (*sc_rf_random_write)(struct _RTMP_ADAPTER *ad, BANK_RF_CR_REG *table, UINT32 num, UINT32 flags); + int (*DisableTxRx)(struct _RTMP_ADAPTER *ad, UCHAR Level); + void (*AsicRadioOn)(struct _RTMP_ADAPTER *ad, UCHAR Stage); + void (*AsicRadioOff)(struct _RTMP_ADAPTER *ad, UINT8 Stage); +#ifdef RLT_MAC + // TODO: shiang-usw, currently the "ANDES_CALIBRATION_PARAM" is defined in andes_rlt.h + int (*Calibration)(struct _RTMP_ADAPTER *pAd, UINT32 CalibrationID, ANDES_CALIBRATION_PARAM *param); +#endif /* RLT_MAC */ +#ifdef CONFIG_ANDES_SUPPORT +#ifdef RTMP_PCI_SUPPORT + int (*pci_kick_out_cmd_msg)(struct _RTMP_ADAPTER *ad, struct cmd_msg *msg); +#endif +#ifdef RTMP_SDIO_SUPPORT + int (*sdio_kick_out_cmd_msg)(struct _RTMP_ADAPTER *ad, struct cmd_msg *msg); +#endif + + void (*andes_fill_cmd_header)(struct cmd_msg *msg, PNDIS_PACKET net_pkt); + INT32 (*AndesMTChkCrc)(struct _RTMP_ADAPTER *pAd, UINT32 checksum_len); + UINT16 (*AndesMTGetCrc)(struct _RTMP_ADAPTER *pAd); +#endif /* CONFIG_ANDES_SUPPORT */ + void (*rx_event_handler)(struct _RTMP_ADAPTER *ad, UCHAR *data); + +#ifdef MICROWAVE_OVEN_SUPPORT + VOID (*AsicMeasureFalseCCA)(IN struct _RTMP_ADAPTER *pAd); + + VOID (*AsicMitigateMicrowave)(IN struct _RTMP_ADAPTER *pAd); +#endif /* MICROWAVE_OVEN_SUPPORT */ + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) || defined(MT_WOW_SUPPORT) + VOID (*AsicWOWEnable)(struct _RTMP_ADAPTER *ad); + VOID (*AsicWOWDisable)(struct _RTMP_ADAPTER *ad); + VOID (*AsicWOWInit)(struct _RTMP_ADAPTER *ad); +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) || defined(MT_WOW_SUPPORT) */ + + void (*usb_cfg_read)(struct _RTMP_ADAPTER *ad, UINT32 *value); + void (*usb_cfg_write)(struct _RTMP_ADAPTER *ad, UINT32 value); + void (*show_pwr_info)(struct _RTMP_ADAPTER *ad); + void (*cal_test)(struct _RTMP_ADAPTER *ad, UINT32 type); + +#ifdef GREENAP_SUPPORT + void (*EnableAPMIMOPSv2)(struct _RTMP_ADAPTER *ad, BOOLEAN ReduceCorePower); + void (*DisableAPMIMOPSv2)(struct _RTMP_ADAPTER *ad); +#endif /* GREENAP_SUPPORT */ + +}; + +#define RTMP_CHIP_ENABLE_AP_MIMOPS(__pAd, __ReduceCorePower) \ +do { \ + if (__pAd->chipOps.EnableAPMIMOPS != NULL) \ + __pAd->chipOps.EnableAPMIMOPS(__pAd, __ReduceCorePower); \ +} while (0) + +#define RTMP_CHIP_DISABLE_AP_MIMOPS(__pAd) \ +do { \ + if (__pAd->chipOps.DisableAPMIMOPS != NULL) \ + __pAd->chipOps.DisableAPMIMOPS(__pAd); \ +} while (0) + +#define PWR_SAVING_OP(__pAd, __PwrOP, __PwrLevel, __ListenInterval, \ + __PreTBTTLeadTime, __TIMByteOffset, __TIMBytePattern) \ +do { \ + if (__pAd->chipOps.PwrSavingOP != NULL) \ + __pAd->chipOps.PwrSavingOP(__pAd, __PwrOP, __PwrLevel, \ + __ListenInterval,__PreTBTTLeadTime, \ + __TIMByteOffset, __TIMBytePattern); \ +} while (0) + +#define RTMP_CHIP_RX_SENSITIVITY_TUNING(__pAd) \ +do { \ + if (__pAd->chipOps.RxSensitivityTuning != NULL) \ + __pAd->chipOps.RxSensitivityTuning(__pAd); \ +} while (0) + +#define RTMP_CHIP_ASIC_AGC_ADJUST(__pAd, __Rssi, __R66) \ +do { \ + if (__pAd->chipOps.ChipAGCAdjust != NULL) \ + __R66 = __pAd->chipOps.ChipAGCAdjust(__pAd, __Rssi, __R66); \ +} while (0) + +#define RTMP_CHIP_ASIC_TSSI_TABLE_INIT(__pAd) \ +do { \ + if (__pAd->chipOps.InitDesiredTSSITable != NULL) \ + __pAd->chipOps.InitDesiredTSSITable(__pAd); \ +} while (0) + +#define RTMP_CHIP_ATE_TSSI_CALIBRATION(__pAd, __pData) \ +do { \ + if (__pAd->chipOps.ATETssiCalibration != NULL) \ + __pAd->chipOps.ATETssiCalibration(__pAd, __pData); \ +} while (0) + +#define RTMP_CHIP_ATE_TSSI_CALIBRATION_EXTEND(__pAd, __pData) \ +do { \ + if (__pAd->chipOps.ATETssiCalibrationExtend != NULL) \ + __pAd->chipOps.ATETssiCalibrationExtend(__pAd, __pData); \ +} while (0) + +#define RTMP_CHIP_ATE_READ_EXTERNAL_TSSI(__pAd, __pData) \ +do { \ + if (__pAd->chipOps.ATEReadExternalTSSI != NULL) \ + __pAd->chipOps.ATEReadExternalTSSI(__pAd, __pData); \ +} while (0) + +#define RTMP_CHIP_ASIC_TX_POWER_OFFSET_GET(__pAd, __pCfgOfTxPwrCtrlOverMAC) \ +do { \ + if (__pAd->chipOps.AsicGetTxPowerOffset != NULL) \ + __pAd->chipOps.AsicGetTxPowerOffset(__pAd, __pCfgOfTxPwrCtrlOverMAC); \ +} while (0) + +#define RTMP_CHIP_ASIC_AUTO_AGC_OFFSET_GET( \ + __pAd, __pDeltaPwr, __pTotalDeltaPwr, __pAgcCompensate, __pDeltaPowerByBbpR1) \ +do { \ + if (__pAd->chipOps.AsicTxAlcGetAutoAgcOffset != NULL) \ + __pAd->chipOps.AsicTxAlcGetAutoAgcOffset( \ + __pAd, __pDeltaPwr, __pTotalDeltaPwr, __pAgcCompensate, __pDeltaPowerByBbpR1); \ +} while (0) + +#define RTMP_CHIP_ASIC_EXTRA_POWER_OVER_MAC(__pAd) \ +do { \ + if (__pAd->chipOps.AsicExtraPowerOverMAC != NULL) \ + __pAd->chipOps.AsicExtraPowerOverMAC(__pAd); \ +} while (0) + +#define RTMP_CHIP_ASIC_ADJUST_TX_POWER(__pAd) \ +do { \ + if (__pAd->chipOps.AsicAdjustTxPower != NULL) \ + __pAd->chipOps.AsicAdjustTxPower(__pAd); \ +} while (0) + +#define RTMP_CHIP_ASIC_GET_TSSI_RATIO(__pAd, __DeltaPwr) \ +do { \ + if (__pAd->chipOps.AsicFreqCalStop != NULL) \ + __pAd->chipOps.TSSIRatio(__DeltaPwr); \ +} while (0) + +#define RTMP_CHIP_ASIC_FREQ_CAL_STOP(__pAd) \ +do { \ + if (__pAd->chipOps.AsicFreqCalStop != NULL) \ + __pAd->chipOps.AsicFreqCalStop(__pAd); \ +} while (0) + +#define RTMP_CHIP_IQ_CAL(__pAd, __pChannel) \ +do { \ + if (__pAd->chipOps.ChipIQCalibration != NULL) \ + __pAd->chipOps.ChipIQCalibration(__pAd, __pChannel); \ +} while (0) + +#define RTMP_CHIP_HIGH_POWER_TUNING(__pAd, __pRssi) \ +do { \ + if (__pAd->chipOps.HighPowerTuning != NULL) \ + __pAd->chipOps.HighPowerTuning(__pAd, __pRssi); \ +} while (0) + +#define RTMP_CHIP_ANTENNA_INFO_DEFAULT_RESET(__pAd, __pAntenna) \ +do { \ + if (__pAd->chipOps.AsicAntennaDefaultReset != NULL) \ + __pAd->chipOps.AsicAntennaDefaultReset(__pAd, __pAntenna); \ +} while (0) + +#define RTMP_NET_DEV_NICKNAME_INIT(__pAd) \ +do { \ + if (__pAd->chipOps.NetDevNickNameInit != NULL) \ + __pAd->chipOps.NetDevNickNameInit(__pAd); \ +} while (0) + +#ifdef CAL_FREE_IC_SUPPORT +#define RTMP_CAL_FREE_IC_CHECK(__pAd, __is_cal_free) \ +do { \ + if (__pAd->chipOps.is_cal_free_ic != NULL) \ + __is_cal_free = __pAd->chipOps.is_cal_free_ic(__pAd); \ + else \ + __is_cal_free = FALSE; \ +} while (0) + +#define RTMP_CAL_FREE_DATA_GET(__pAd) \ +do { \ + if (__pAd->chipOps.cal_free_data_get != NULL) \ + __pAd->chipOps.cal_free_data_get(__pAd); \ +} while (0) +#endif /* CAL_FREE_IC_SUPPORT */ + +#define RTMP_EEPROM_ASIC_INIT(__pAd) \ +do { \ + if (__pAd->chipOps.NICInitAsicFromEEPROM != NULL) \ + __pAd->chipOps.NICInitAsicFromEEPROM(__pAd); \ +} while (0) + +#define RTMP_CHIP_ASIC_INIT_TEMPERATURE_COMPENSATION(__pAd) \ +do { \ + if (__pAd->chipOps.InitTemperCompensation != NULL) \ + __pAd->chipOps.InitTemperCompensation(__pAd); \ +} while (0) + +#define RTMP_CHIP_ASIC_TEMPERATURE_COMPENSATION(__pAd) \ +do { \ + if (__pAd->chipOps.TemperCompensation != NULL) \ + __pAd->chipOps.TemperCompensation(__pAd); \ +} while (0) + +#define RTMP_CHIP_ASIC_SET_EDCCA(__pAd,__bOn) \ +do { \ + if (__pAd->chipOps.ChipSetEDCCA != NULL) \ + __pAd->chipOps.ChipSetEDCCA(__pAd, __bOn); \ +} while (0) + + + +#define RTMP_CHIP_UPDATE_BEACON(__pAd, Offset, Value, Unit) \ +do { \ + if (__pAd->chipOps.BeaconUpdate != NULL) \ + __pAd->chipOps.BeaconUpdate(__pAd, Offset, Value, Unit); \ +} while (0) + +#ifdef CARRIER_DETECTION_SUPPORT +#define RTMP_CHIP_CARRIER_PROGRAM(__pAd, threshold) \ +do { \ + if(__pAd->chipOps.ToneRadarProgram != NULL) \ + __pAd->chipOps.ToneRadarProgram(__pAd, threshold); \ +} while (0) +#endif /* CARRIER_DETECTION_SUPPORT */ + +#define RTMP_CHIP_CCK_MRC_STATUS_CTRL(__pAd) \ +do { \ + if(__pAd->chipOps.CckMrcStatusCtrl != NULL) \ + __pAd->chipOps.CckMrcStatusCtrl(__pAd); \ +} while (0) + +#define RTMP_CHIP_RADAR_GLRT_COMPENSATE(__pAd) \ +do { \ + if(__pAd->chipOps.RadarGLRTCompensate != NULL) \ + __pAd->chipOps.RadarGLRTCompensate(__pAd); \ +} while (0) + + +#define CHIP_CALIBRATION(__pAd, __CalibrationID, param) \ +do { \ + ANDES_CALIBRATION_PARAM calibration_param; \ + calibration_param.generic = param; \ + if(__pAd->chipOps.Calibration != NULL) \ + __pAd->chipOps.Calibration(__pAd, __CalibrationID, &calibration_param); \ +} while (0) + +#define BURST_WRITE(_pAd, _Offset, _pData, _Cnt) \ +do { \ + if (_pAd->chipOps.BurstWrite != NULL) \ + _pAd->chipOps.BurstWrite(_pAd, _Offset, _pData, _Cnt);\ +} while (0) + +#define BURST_READ(_pAd, _Offset, _Cnt, _pData) \ +do { \ + if (_pAd->chipOps.BurstRead != NULL) \ + _pAd->chipOps.BurstRead(_pAd, _Offset, _Cnt, _pData); \ +} while (0) + +#define RANDOM_READ(_pAd, _RegPair, _Num) \ +do { \ + if (_pAd->chipOps.RandomRead != NULL) \ + _pAd->chipOps.RandomRead(_pAd, _RegPair, _Num); \ +} while (0) + +#define RF_RANDOM_READ(_pAd, _RegPair, _Num) \ +do { \ + if (_pAd->chipOps.RFRandomRead != NULL) \ + _pAd->chipOps.RFRandomRead(_pAd, _RegPair, _Num); \ +} while (0) + +#define READ_MODIFY_WRITE(_pAd, _RegPair, _Num) \ +do { \ + if (_pAd->chipOps.ReadModifyWrite != NULL) \ + _pAd->chipOps.ReadModifyWrite(_pAd, _RegPair, _Num); \ +} while (0) + +#define RF_READ_MODIFY_WRITE(_pAd, _RegPair, _Num) \ +do { \ + if (_pAd->chipOps.RFReadModifyWrite != NULL) \ + _pAd->chipOps.RFReadModifyWrite(_pAd, _RegPair, _Num); \ +} while (0) + +#define RANDOM_WRITE(_pAd, _RegPair, _Num) \ +do { \ + if (_pAd->chipOps.RandomWrite != NULL) \ + _pAd->chipOps.RandomWrite(_pAd, _RegPair, _Num); \ +} while (0) + +#define RF_RANDOM_WRITE(_pAd, _RegPair, _Num) \ +do { \ + if (_pAd->chipOps.RFRandomWrite != NULL) \ + _pAd->chipOps.RFRandomWrite(_pAd, _RegPair, _Num); \ +} while (0) + +#ifdef CONFIG_ANDES_BBP_RANDOM_WRITE_SUPPORT +#define BBP_RANDOM_WRITE(_pAd, _RegPair, _Num) \ +do { \ + if (_pAd->chipOps.BBPRandomWrite != NULL) \ + _pAd->chipOps.BBPRandomWrite(_pAd, _RegPair, _Num); \ +} while (0) +#endif /* CONFIG_ANDES_BBP_RANDOM_WRITE_SUPPORT */ + +#define RTMP_SECOND_CCA_DETECTION(__pAd) \ +do { \ + if (__pAd->chipOps.SecondCCADetection != NULL) \ + { \ + __pAd->chipOps.SecondCCADetection(__pAd); \ + } \ +} while (0) + +#define SC_RANDOM_WRITE(_ad, _table, _num, _flags) \ +do { \ + if (_ad->chipOps.sc_random_write != NULL) \ + _ad->chipOps.sc_random_write(_ad, _table, _num, _flags); \ +} while (0) + +#define SC_RF_RANDOM_WRITE(_ad, _table, _num, _flags) \ +do { \ + if (_ad->chipOps.sc_rf_random_write != NULL) \ + _ad->chipOps.sc_rf_random_write(_ad, _table, _num, _flags); \ +} while (0) + +#define DISABLE_TX_RX(_pAd, _Level) \ +do { \ + if (_pAd->chipOps.DisableTxRx != NULL) \ + _pAd->chipOps.DisableTxRx(_pAd, _Level); \ +} while (0) + +#define ASIC_RADIO_ON(_pAd, _Stage) \ +do { \ + if (_pAd->chipOps.AsicRadioOn != NULL) \ + _pAd->chipOps.AsicRadioOn(_pAd, _Stage); \ +} while (0) + +#define ASIC_RADIO_OFF(_pAd, _Stage) \ +do { \ + if (_pAd->chipOps.AsicRadioOff != NULL) \ + _pAd->chipOps.AsicRadioOff(_pAd, _Stage); \ +} while (0) + +#ifdef MICROWAVE_OVEN_SUPPORT +#define ASIC_MEASURE_FALSE_CCA(_pAd) \ +do { \ + if (_pAd->chipOps.AsicMeasureFalseCCA != NULL) \ + _pAd->chipOps.AsicMeasureFalseCCA(_pAd); \ +} while (0) + +#define ASIC_MITIGATE_MICROWAVE(_pAd) \ +do { \ + if (_pAd->chipOps.AsicMitigateMicrowave != NULL) \ + _pAd->chipOps.AsicMitigateMicrowave(_pAd); \ +} while (0) +#endif /* MICROWAVE_OVEN_SUPPORT */ + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) || defined(MT_WOW_SUPPORT) +#define ASIC_WOW_ENABLE(_pAd) \ +do { \ + if (_pAd->chipOps.AsicWOWEnable != NULL) \ + _pAd->chipOps.AsicWOWEnable(_pAd); \ +} while (0) + +#define ASIC_WOW_DISABLE(_pAd) \ +do { \ + if (_pAd->chipOps.AsicWOWDisable != NULL) \ + _pAd->chipOps.AsicWOWDisable(_pAd); \ +} while(0) + +#define ASIC_WOW_INIT(_pAd) \ +do { \ + if (_pAd->chipOps.AsicWOWInit != NULL) \ + _pAd->chipOps.AsicWOWInit(_pAd); \ +} while(0) + +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) || defined(MT_WOW_SUPPORT) */ + +#define MCU_CTRL_INIT(_pAd) \ +do { \ + if (_pAd->chipOps.MCUCtrlInit != NULL) \ + _pAd->chipOps.MCUCtrlInit(_pAd); \ +} while (0) + +#define MCU_CTRL_EXIT(_pAd) \ +do { \ + if (_pAd->chipOps.MCUCtrlExit != NULL) \ + _pAd->chipOps.MCUCtrlExit(_pAd); \ +} while (0) + +#define USB_CFG_READ(_ad, _pvalue) \ +do { \ + if (_ad->chipOps.usb_cfg_read != NULL) \ + _ad->chipOps.usb_cfg_read(_ad, _pvalue); \ + else {\ + DBGPRINT(RT_DEBUG_ERROR, ("%s(): usb_cfg_read not inited!\n", __FUNCTION__));\ + }\ +} while (0) + +#define USB_CFG_WRITE(_ad, _value) \ +do { \ + if (_ad->chipOps.usb_cfg_write != NULL) \ + _ad->chipOps.usb_cfg_write(_ad, _value); \ + else {\ + DBGPRINT(RT_DEBUG_ERROR, ("%s(): usb_cfg_write not inited!\n", __FUNCTION__));\ + }\ +} while (0) + +VOID AsicInitTxRxRing(struct _RTMP_ADAPTER *pAd); + +int RtmpChipOpsHook(VOID *pCB); +VOID RtmpChipBcnInit(struct _RTMP_ADAPTER *pAd); +VOID RtmpChipBcnSpecInit(struct _RTMP_ADAPTER *pAd); +#ifdef RLT_MAC +VOID rlt_bcn_buf_init(struct _RTMP_ADAPTER *pAd); +#endif /* RLT_MAC */ +#ifdef MT_MAC +VOID mt_bcn_buf_init(struct _RTMP_ADAPTER *pAd); +#endif /* MT_MAC */ + +UINT8 NICGetBandSupported(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(struct _RTMP_ADAPTER *pAd); +VOID RTMPReadTxPwrPerRate(struct _RTMP_ADAPTER *pAd); + +INT tx_pwr_comp_init(struct _RTMP_ADAPTER *pAd); + + +VOID NetDevNickNameInit(IN struct _RTMP_ADAPTER *pAd); + + + +#ifdef GREENAP_SUPPORT +VOID EnableAPMIMOPSv2(struct _RTMP_ADAPTER *pAd, BOOLEAN ReduceCorePower); +VOID DisableAPMIMOPSv2(struct _RTMP_ADAPTER *pAd); +VOID EnableAPMIMOPSv1(struct _RTMP_ADAPTER *pAd, BOOLEAN ReduceCorePower); +VOID DisableAPMIMOPSv1(struct _RTMP_ADAPTER *pAd); +#endif /* GREENAP_SUPPORT */ + +#ifdef RTMP_MAC +VOID RTxx_default_Init(struct _RTMP_ADAPTER *pAd); +#endif /* RTMP_MAC */ + + +/* global variable */ +extern FREQUENCY_ITEM RtmpFreqItems3020[]; +extern FREQUENCY_ITEM FreqItems3020_Xtal20M[]; +extern UCHAR NUM_OF_3020_CHNL; +extern FREQUENCY_ITEM *FreqItems3020; +extern RTMP_RF_REGS RF2850RegTable[]; +extern UCHAR NUM_OF_2850_CHNL; + +INT AsicGetMacVersion(struct _RTMP_ADAPTER *pAd); + +INT WaitForAsicReady(struct _RTMP_ADAPTER *pAd); + +INT AsicWaitMacTxRxIdle(struct _RTMP_ADAPTER *pAd); + +#define ASIC_MAC_TX 1 +#define ASIC_MAC_RX 2 +#define ASIC_MAC_TXRX 3 +#define ASIC_MAC_TXRX_RXV 4 +#define ASIC_MAC_RXV 5 +#define ASIC_MAC_RX_RXV 6 + +INT AsicSetMacTxRx(struct _RTMP_ADAPTER *pAd, INT32 txrx, BOOLEAN enable); + +enum { + PDMA_TX, + PDMA_RX, + PDMA_TX_RX, +}; + +INT AsicSetWPDMA(struct _RTMP_ADAPTER *pAd, INT32 TxRx, BOOLEAN enable); +BOOLEAN AsicWaitPDMAIdle(struct _RTMP_ADAPTER *pAd, INT round, INT wait_us); +INT AsicSetMacWD(struct _RTMP_ADAPTER *pAd); + +INT AsicReadAggCnt(struct _RTMP_ADAPTER *pAd, ULONG *aggCnt, int cnt_len); + +INT rtmp_asic_top_init(struct _RTMP_ADAPTER *pAd); + +#ifdef MT_MAC +INT mt_asic_top_init(struct _RTMP_ADAPTER *pAd); +INT mt_hif_sys_init(struct _RTMP_ADAPTER *pAd); +INT rt28xx_read16(struct _RTMP_ADAPTER *pAd, USHORT , USHORT *); +VOID AsicSetRxGroup(struct _RTMP_ADAPTER *pAd, UINT32 Port, UINT32 Group, BOOLEAN Enable); +#if defined(RTMP_MAC_PCI) || defined(RTMP_MAC_USB) +INT32 AsicDMASchedulerInit(struct _RTMP_ADAPTER *pAd, INT mode); +#endif +VOID AsicSetBARTxCntLimit(struct _RTMP_ADAPTER *pAd, BOOLEAN Enable, UINT32 Count); +VOID AsicSetRTSTxCntLimit(struct _RTMP_ADAPTER *pAd, BOOLEAN Enable, UINT32 Count); +VOID AsicSetTxSClassifyFilter(struct _RTMP_ADAPTER *pAd, UINT32 Port, UINT8 DestQ, + UINT32 AggNums, UINT32 Filter); + +BOOLEAN AsicSetBmcQCR( + IN struct _RTMP_ADAPTER *pAd, + IN UCHAR Operation, + IN UCHAR CrReadWrite, + IN UINT32 apidx, + INOUT UINT32 *pcr_val); + +#define CR_READ 1 +#define CR_WRITE 2 + +#define BMC_FLUSH 1 +#define BMC_ENABLE 2 +#define BMC_CNT_UPDATE 3 + +#define AC_QUEUE_STOP 0 +#define AC_QUEUE_FLUSH 1 +#define AC_QUEUE_START 2 + +#endif /* MT_MAC */ + +INT StopDmaTx(struct _RTMP_ADAPTER *pAd, UCHAR Level); +INT StopDmaRx(struct _RTMP_ADAPTER *pAd, UCHAR Level); + + +VOID MtAsicSetRxPspollFilter(struct _RTMP_ADAPTER *pAd, CHAR enable); + +#if defined(MT7603) || defined(MT7628) +INT32 MtAsicGetThemalSensor(struct _RTMP_ADAPTER *pAd, CHAR type); +VOID MtAsicACQueue(struct _RTMP_ADAPTER *pAd, UINT8 ucation, UINT8 BssidIdx, UINT32 u4AcQueueMap); +#endif /* MT7603 || MT7628 */ +#endif /* __RTMP_CHIP_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_cmd.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_cmd.h new file mode 100644 index 000000000..2e6e3d4ce --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_cmd.h @@ -0,0 +1,602 @@ +#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 +#define CMDTHREAD_PS_CLEAR 0x0D730106 +#define CMDTHREAD_PS_RETRIEVE_START 0x0D730107 +#define CMDTHREAD_APCLI_PBC_TIMEOUT 0x0D730108 + +#ifdef SNIFFER_MIB_CMD +#define CMDTHREAD_CHAN_RESTORE 0x0D730109 +#endif /* SNIFFER_MIB_CMD */ + +#define HWCMD_ID_BMC_CNT_UPDATE 0x0D73012C +#define CMDTHREAD_PERODIC_CR_ACCESS_ASIC_UPDATE_PROTECT 0x0D73012D +#define CMDTHREAD_PERODIC_CR_ACCESS_MLME_DYNAMIC_TX_RATE_SWITCHING 0x0D73012E +#define CMDTHREAD_PERODIC_CR_ACCESS_NIC_UPDATE_RAW_COUNTERS 0x0D73012F +#define CMDTHREAD_PERODIC_CR_ACCESS_WTBL_RATE_TABLE_UPDATE 0x0D730130 +#define CMDTHREAD_FORCE_WAKE_UP 0x0D730131 +#define CMDTHREAD_FORCE_SLEEP_AUTO_WAKEUP 0x0D730132 +#define CMDTHREAD_MLME_PERIOIDC_EXEC 0x0D730133 +#define CMDTHREAD_PWR_MGT_BIT 0x0D730134 + +#endif /* RTMP_MAC_PCI || RTMP_RBUS_SUPPORT */ + +#define CMDTHREAD_RESPONSE_EVENT_CALLBACK 0x0D730123 + +/* RALINK command status code */ +#define RTMP_IO_EINVAL 30000 +#define RTMP_IO_EOPNOTSUPP 30001 +#define RTMP_IO_EFAULT 30002 +#define RTMP_IO_ENETDOWN 30003 +#define RTMP_IO_E2BIG 30004 +#define RTMP_IO_ENOMEM 30005 +#define RTMP_IO_EAGAIN 30006 +#define RTMP_IO_ENOTCONN 30007 + +enum { +#ifdef MAT_SUPPORT + SHOW_IPV4_MAT_INFO = 1, + SHOW_IPV6_MAT_INFO = 2, + SHOW_ETH_CLONE_MAC = 3, +#endif /* MAT_SUPPORT */ + SHOW_CONN_STATUS = 4, + SHOW_DRVIER_VERION = 5, + SHOW_BA_INFO = 6, + SHOW_DESC_INFO = 7, + RAIO_OFF = 10, + RAIO_ON = 11, + SHOW_CFG_VALUE = 21, + SHOW_ADHOC_ENTRY_INFO = 22, +#if defined(DOT11Z_TDLS_SUPPORT) || defined(CFG_TDLS_SUPPORT) + SHOW_TDLS_ENTRY_INFO = 25, +#endif /* DOT11Z_TDLS_SUPPORT */ + SHOW_DEV_INFO = 26, + SHOW_STA_INFO = 27, + SHOW_TR_INFO = 28, + SHOW_SYS_INFO = 29, + SHOW_PWR_INFO = 30, + SHOW_DIAGNOSE_INFO = 31, + SHOW_WTBL_INFO = 32, + SHOW_MIB_INFO = 33, + SHOW_PS_INFO = 34, + SHOW_TEMP_INFO = 35, + +}; + + +/* 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, +#ifdef WIFI_DIAG + CMD_RTPRIV_IOCTL_GET_PROCESS_INFO, +#endif + /* 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, +#ifdef MT_MAC + CMD_RTPRIV_IOCTL_MBSS_CR_ENABLE, + CMD_RTPRIV_IOCTL_MBSS_CR_DISABLE, +#endif + + /* wsc */ + CMD_RTPRIV_IOCTL_WSC_PROFILE, + CMD_RTPRIV_IOCTL_WSC_INIT, + CMD_RTPRIV_IOCTL_NFC_STATUS, + + /* 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, + +/*driver version*/ + CMD_RTPRIV_IOCTL_GET_DRIVER_INFO, + +#ifdef WH_EZ_SETUP + CMD_RTPRIV_IOCTL_GET_EZ_SCAN_TABLE = 0x150, +#endif /* WH_EZ_SETUP */ + + /* can not exceed 0x5000 */ +} CMD_RTPRIV_IOCTL_AP; + +/* common commands */ +typedef enum _CMD_RTPRIV_IOCTL_COMMON { + + /* general */ + CMD_RTPRIV_IOCTL_NETDEV_GET = 0x5000, + CMD_RTPRIV_IOCTL_NETDEV_SET, + CMD_RTPRIV_IOCTL_OPMODE_GET, + CMD_RTPRIV_IOCTL_TASK_LIST_GET, + CMD_RTPRIV_IOCTL_IRQ_INIT, + CMD_RTPRIV_IOCTL_IRQ_RELEASE, + CMD_RTPRIV_IOCTL_MSI_ENABLE, + CMD_RTPRIV_IOCTL_NIC_NOT_EXIST, + CMD_RTPRIV_IOCTL_MCU_SLEEP_CLEAR, + CMD_RTPRIV_IOCTL_SANITY_CHECK, + CMD_RTPRIV_IOCTL_SANITY_CHECK_ON_SET_CMD, +#ifdef EXT_BUILD_CHANNEL_LIST + CMD_RTPRIV_SET_PRECONFIG_VALUE, +#endif /* EXT_BUILD_CHANNEL_LIST */ + + /* sniffer */ + CMD_RTPRIV_IOCTL_SNIFF_UP, + CMD_RTPRIV_IOCTL_SNIFF_DISCONNECT, + CMD_RTPRIV_IOCTL_SNIFF_INIT, + CMD_RTPRIV_IOCTL_SNIFF_OPEN, + CMD_RTPRIV_IOCTL_SNIFF_CLOSE, + CMD_RTPRIV_IOCTL_SNIFF_REMOVE, + + + /* mesh */ + CMD_RTPRIV_IOCTL_MESH_INIT, + CMD_RTPRIV_IOCTL_MESH_REMOVE, + CMD_RTPRIV_IOCTL_MESH_OPEN_PRE, + CMD_RTPRIV_IOCTL_MESH_OPEN_POST, + CMD_RTPRIV_IOCTL_MESH_IS_VALID, + CMD_RTPRIV_IOCTL_MESH_CLOSE, + + /* p2p */ + CMD_RTPRIV_IOCTL_P2P_INIT, + CMD_RTPRIV_IOCTL_P2P_REMOVE, + CMD_RTPRIV_IOCTL_P2P_OPEN_PRE, + CMD_RTPRIV_IOCTL_P2P_OPEN_POST, + CMD_RTPRIV_IOCTL_P2P_IS_VALID, + CMD_RTPRIV_IOCTL_P2P_CLOSE, + + /* usb */ + CMD_RTPRIV_IOCTL_USB_MORE_FLAG_SET, + CMD_RTPRIV_IOCTL_USB_CONFIG_INIT, + CMD_RTPRIV_IOCTL_USB_SUSPEND, + CMD_RTPRIV_IOCTL_USB_RESUME, + CMD_RTPRIV_IOCTL_USB_INIT, + + /* pci */ + CMD_RTPRIV_IOCTL_PCI_SUSPEND, + CMD_RTPRIV_IOCTL_PCI_RESUME, + CMD_RTPRIV_IOCTL_PCI_CSR_SET, + CMD_RTPRIV_IOCTL_PCIE_INIT, + + /* cfg80211 */ + CMD_RTPRIV_IOCTL_CFG80211_CFG_START, + + /* inf ppa */ + CMD_RTPRIV_IOCTL_INF_PPA_INIT, + CMD_RTPRIV_IOCTL_INF_PPA_EXIT, + + /* wireless */ + CMD_RTPRIV_IOCTL_BEACON_UPDATE, + CMD_RTPRIV_IOCTL_RXPATH_GET, + CMD_RTPRIV_IOCTL_CHAN_LIST_NUM_GET, + CMD_RTPRIV_IOCTL_CHAN_LIST_GET, + CMD_RTPRIV_IOCTL_FREQ_LIST_GET, + + /* interface */ + CMD_RTPRIV_IOCTL_VIRTUAL_INF_UP, + CMD_RTPRIV_IOCTL_VIRTUAL_INF_DOWN, + CMD_RTPRIV_IOCTL_VIRTUAL_INF_GET, + CMD_RTPRIV_IOCTL_INF_TYPE_GET, + CMD_RTPRIV_IOCTL_INF_STATS_GET, + CMD_RTPRIV_IOCTL_INF_IW_STATUS_GET, + CMD_RTPRIV_IOCTL_INF_MAIN_CREATE, + CMD_RTPRIV_IOCTL_INF_MAIN_ID_GET, + CMD_RTPRIV_IOCTL_INF_MAIN_CHECK, + CMD_RTPRIV_IOCTL_INF_P2P_CHECK, + + /* ioctl */ + CMD_RTPRIV_IOCTL_SIOCGIWFREQ, + CMD_RTPRIV_IOCTL_SIOCGIWNAME, + + /* wds */ + CMD_RTPRIV_IOCTL_WDS_INIT, + CMD_RTPRIV_IOCTL_WDS_REMOVE, + CMD_RTPRIV_IOCTL_WDS_STATS_GET, + + CMD_RTPRIV_IOCTL_MAC_ADDR_GET, + + + CMD_RTPRIV_IOCTL_ADAPTER_CSO_SUPPORT_TEST, + CMD_RTPRIV_IOCTL_ADAPTER_TSO_SUPPORT_TEST, +#ifdef CONFIG_HAS_EARLYSUSPEND + CMD_RTPRIV_IOCTL_LOAD_FIRMWARE_CHECK, + CMD_RTPRIV_IOCTL_REGISTER_EARLYSUSPEND, + CMD_RTPRIV_IOCTL_UNREGISTER_EARLYSUSPEND, + CMD_RTPRIV_IOCTL_CHECK_EARLYSUSPEND, + CMD_RTPRIV_IOCTL_OS_COOKIE_GET, + CMD_RTPRIV_IOCTL_SET_SUSPEND_FLAG, +#endif + CMD_RTPRIV_IOCTL_SDIO_INIT, + /* can not exceed 0xa000 */ + CMD_RTPRIV_IOCTL_80211_COM_LATEST_ONE, +} CMD_RTPRIV_IOCTL_COMMON; + + +/* station commands */ + +/* 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 RTMP_STRING *pThisChar; + IN RTMP_STRING *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 { + INT BssId; + USHORT Reason; +} RT_CMD_MBSS_KICKOUT; + +typedef struct __RT_CMD_USB_MORE_FLAG_CONFIG { + UINT32 VendorID; + UINT32 ProductID; +} RT_CMD_USB_MORE_FLAG_CONFIG; + +typedef struct __RT_CMD_USB_DEV_CONFIG { + UINT NumberOfPipes; + UINT8 BulkInEpAddr[2]; + USHORT BulkInMaxPacketSize; + UINT8 BulkOutEpAddr[6]; + USHORT BulkOutMaxPacketSize; + VOID *pConfig; +} RT_CMD_USB_DEV_CONFIG; + +typedef struct __RT_CMD_WAIT_QUEUE_LIST { + RTMP_OS_TASK *pMlmeTask; + RTMP_OS_TASK *pTimerTask; + RTMP_OS_TASK *pCmdQTask; + 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 { + VOID *pPciDev; + UINT32 ConfigDeviceID; + UINT32 ConfigSubsystemVendorID; + UINT32 ConfigSubsystemID; +} RT_CMD_PCIE_INIT; + +typedef struct __RT_CMD_AP_IOCTL_CONFIG { + VOID *net_dev; + VOID *wdev; + ULONG priv_flags; + char *pCmdData; + INT32 CmdId_RTPRIV_IOCTL_SET; + char *name; + INT apidx; + + INT32 Status; +} RT_CMD_AP_IOCTL_CONFIG; + +typedef struct __RT_CMD_AP_IOCTL_SSID { + ULONG priv_flags; + INT apidx; + + char *pSsidStr; + 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; + IN UINT ScanType; + OUT INT32 Status; +} RT_CMD_STA_IOCTL_SCAN; + +typedef struct __RT_CMD_STA_IOCTL_BSS_TABLE { + UCHAR Bssid[6]; + UCHAR Channel; + UCHAR BssType; + UCHAR HtCapabilityLen; + + UCHAR SupRate[12]; + UCHAR SupRateLen; + UCHAR ExtRate[12]; + UCHAR ExtRateLen; + + UCHAR SsidLen; + CHAR Ssid[32]; + + USHORT CapabilityInfo; + UCHAR ChannelWidth, ShortGIfor40, ShortGIfor20, MCSSet; + + USHORT WpaIeLen; + UCHAR *pWpaIe; + + USHORT RsnIeLen; + UCHAR *pRsnIe; + + USHORT WpsIeLen; + UCHAR *pWpsIe; + + UCHAR FlgIsPrivacyOn; + + RT_CMD_STA_IOCTL_BSS Signal; +} RT_CMD_STA_IOCTL_BSS_TABLE; + +typedef struct __RT_CMD_STA_IOCTL_SCAN_TABLE { + ULONG priv_flags; + UINT32 BssNr; + RT_CMD_STA_IOCTL_BSS_TABLE *pBssTable; /* must be freed by caller */ + UCHAR MainSharedKey[4][16]; +} RT_CMD_STA_IOCTL_SCAN_TABLE; + +typedef struct __RT_CMD_STA_IOCTL_SSID { + UCHAR FlgAnySsid; + UINT32 SsidLen; + CHAR *pSsid; + INT32 Status; +} RT_CMD_STA_IOCTL_SSID; + +typedef struct __RT_CMD_STA_IOCTL_NICK_NAME { + UINT NameLen; + CHAR *pName; +} RT_CMD_STA_IOCTL_NICK_NAME; + +typedef struct __RT_CMD_STA_IOCTL_SECURITY { + CHAR *pData; + UINT16 length; + INT32 KeyIdx; + 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 + UINT32 Alg; + +#define RT_CMD_STA_IOCTL_SECURTIY_EXT_SET_TX_KEY 0x01 +#define RT_CMD_STA_IOCTL_SECURTIY_EXT_GROUP_KEY 0x02 + 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 + UINT16 flags; + + INT32 Status; +} RT_CMD_STA_IOCTL_SECURITY; + +typedef struct __RT_CMD_STA_IOCTL_WSC_U32_ITEM { + IN UINT32 *pUWrq; + OUT INT32 Status; +} RT_CMD_STA_IOCTL_WSC_U32_ITEM; + +typedef struct __RT_CMD_STA_IOCTL_WSC_STR_ITEM { + IN UINT32 Subcmd; + IN CHAR *pData; + IN UINT32 length; + + OUT INT32 Status; +} RT_CMD_STA_IOCTL_WSC_STR_ITEM; + +typedef struct __RT_CMD_STA_IOCTL_SHOW { + IN CHAR *pData; + IN UINT32 MaxSize; + IN UINT32 InfType; +} RT_CMD_STA_IOCTL_SHOW; + +#define RT_CMD_STA_IOCTL_IW_MLME_DEAUTH 0x01 +#define RT_CMD_STA_IOCTL_IW_MLME_DISASSOC 0x02 + +typedef struct __RT_CMD_STA_IOCTL_SECURITY_ADV { + +#define RT_CMD_STA_IOCTL_WPA_VERSION 0x10 +#define RT_CMD_STA_IOCTL_WPA_VERSION1 0x11 +#define RT_CMD_STA_IOCTL_WPA_VERSION2 0x12 + +#define RT_CMD_STA_IOCTL_WPA_PAIRWISE 0x20 +#define RT_CMD_STA_IOCTL_WPA_PAIRWISE_NONE 0x21 +#define RT_CMD_STA_IOCTL_WPA_PAIRWISE_WEP40 0x22 +#define RT_CMD_STA_IOCTL_WPA_PAIRWISE_WEP104 0x23 +#define RT_CMD_STA_IOCTL_WPA_PAIRWISE_TKIP 0x24 +#define RT_CMD_STA_IOCTL_WPA_PAIRWISE_CCMP 0x25 + +#define RT_CMD_STA_IOCTL_WPA_GROUP 0x30 +#define RT_CMD_STA_IOCTL_WPA_GROUP_NONE 0x31 +#define RT_CMD_STA_IOCTL_WPA_GROUP_WEP40 0x32 +#define RT_CMD_STA_IOCTL_WPA_GROUP_WEP104 0x33 +#define RT_CMD_STA_IOCTL_WPA_GROUP_TKIP 0x34 +#define RT_CMD_STA_IOCTL_WPA_GROUP_CCMP 0x35 + +#define RT_CMD_STA_IOCTL_WPA_KEY_MGMT 0x40 +#define RT_CMD_STA_IOCTL_WPA_KEY_MGMT_1X 0x41 +#define RT_CMD_STA_IOCTL_WPA_KEY_MGMT_WPS 0x42 + +#define RT_CMD_STA_IOCTL_WPA_AUTH_RX_UNENCRYPTED_EAPOL 0x50 +#define RT_CMD_STA_IOCTL_WPA_AUTH_PRIVACY_INVOKED 0x60 +#define RT_CMD_STA_IOCTL_WPA_AUTH_DROP_UNENCRYPTED 0x70 + +#define RT_CMD_STA_IOCTL_WPA_AUTH_80211_AUTH_ALG 0x80 +#define RT_CMD_STA_IOCTL_WPA_AUTH_80211_AUTH_ALG_SHARED 0x81 +#define RT_CMD_STA_IOCTL_WPA_AUTH_80211_AUTH_ALG_OPEN 0x82 +#define RT_CMD_STA_IOCTL_WPA_AUTH_80211_AUTH_ALG_LEAP 0x83 + +#define RT_CMD_STA_IOCTL_WPA_AUTH_WPA_ENABLED 0x90 + +#define RT_CMD_STA_IOCTL_WPA_AUTH_COUNTERMEASURES 0xA0 + + UINT32 flags; + UINT32 value; +} RT_CMD_STA_IOCTL_SECURITY_ADV; + +typedef struct __RT_CMD_STA_IOCTL_RSN_IE { + UINT32 length; + 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 + UINT32 Cmd; + UCHAR *pBssid; + UCHAR *pPmkid; +} RT_CMD_STA_IOCTL_PMA_SA; + +typedef struct __RT_CMD_USB_INIT { + VOID *pUsbDev; + UINT32 driver_info; +} RT_CMD_USB_INIT; + +#endif /* __RTMP_CMD_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_comm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_comm.h new file mode 100644 index 000000000..f6897b974 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_comm.h @@ -0,0 +1,457 @@ +/**************************************************************************** + + Module Name: + rtmp_comm.h + + Abstract: + All common definitions and macros for UTIL/DRIVER/NETIF. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + +***************************************************************************/ + +#ifndef __RT_COMM_H__ +#define __RT_COMM_H__ + +#define VENDOR_FEATURE1_SUPPORT +#ifdef BB_SOC +#define VENDOR_FEATURE3_SUPPORT +#endif + +#ifdef WIFI_FWD_UPDATED +#define MT7615_MT7603_COMBO_FORWARDING 1 +#else +#define MT7615_MT7603_COMBO_FORWARDING 0 +#endif +#define MT7615_MT7603_COMBO_OID_FOR_WEBUI 0 + +/*#define MONITOR_FLAG_11N_SNIFFER_SUPPORT */ + + +#ifdef VENDOR_FEATURE3_SUPPORT +#ifndef BB_SOC +#ifdef DOT1X_SUPPORT +#undef DOT1X_SUPPORT +#endif /* DOT1X_SUPPORT */ +#ifdef SYSTEM_LOG_SUPPORT +#undef SYSTEM_LOG_SUPPORT +#endif /* SYSTEM_LOG_SUPPORT */ +#endif +#ifdef LED_CONTROL_SUPPORT +//#undef LED_CONTROL_SUPPORT +#endif /* LED_CONTROL_SUPPORT */ +#ifdef WSC_LED_SUPPORT +#undef WSC_LED_SUPPORT +#endif /* WSC_LED_SUPPORT */ +#endif /* VENDOR_FEATURE3_SUPPORT */ + + +#ifdef VENDOR_FEATURE1_SUPPORT +#define FIFO_STAT_READ_PERIOD 4 +#else +#define FIFO_STAT_READ_PERIOD 0 +#endif /* VENDOR_FEATURE1_SUPPORT */ + +#ifdef CONFIG_AP_SUPPORT + +#ifndef VENDOR_FEATURE3_SUPPORT +#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 + Refer to CH_HZ_ID_MAP[] in rt_channel.c +*/ +#ifdef DOT11_VHT_AC +#define MAX_NUM_OF_CHS (54 + 5) /* 5 channels for central channel of VHT 80MHz */ +#else +#define MAX_NUM_OF_CHS 54 +#endif /* DOT11_VHT_AC*/ +/* 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination */ +#define MAX_NUM_OF_CHANNELS MAX_NUM_OF_CHS +#define MAX_NUM_OF_SUB_CHANNELS MAX_NUM_OF_CHANNELS/2 /*Assume half size for sub channels*/ + + +#include "rtmp_type.h" +#include "rtmp_os.h" +#include "link_list.h" +#include "rtmp_cmd.h" +#include "iface/iface_util.h" +#ifdef CONFIG_SNIFFER_SUPPORT +#include "sniffer/sniffer.h" +#endif /* CONFIG_SNIFFER_SUPPORT */ + + + +/* ======================== Debug =========================================== */ +/* */ +/* Debug information verbosity: lower values indicate higher urgency */ +/* */ +#define RT_DEBUG_OFF 0 +#define RT_DEBUG_ERROR 1 +#define RT_DEBUG_WARN 2 +#define RT_DEBUG_TRACE 3 +#define RT_DEBUG_INFO 4 +#define RT_DEBUG_LOUD 5 +#define RT_DEBUG_FPGA 6 +#define RT_DEBUG_MAX RT_DEBUG_FPGA + +typedef enum{ + DBG_FUNC_RA = 0x100 << 8, /* debug flag for rate adaptation */ + DBG_FUNC_SA = 0x200 << 8, /* debug flag for smart antenna */ + DBG_FUNC_TX = 0x400 << 8, + DBG_FUNC_TXQ = 0x401 << 8, /* debug flag for tx Q mgmt */ + DBG_FUNC_TMAC_INFO = 0x402 << 8, /* debug flag for tmac info dump */ + DBG_FUNC_RX = 0x800 << 8, /* debug flag for tmac info dump */ + DBG_FUNC_PS = 0x1000 << 8, /* debug flag for power saving */ + DBG_FUNC_UAPSD = 0x2000 << 8, /* debug flag for uapsd */ + DBG_FUNC_MAX = DBG_FUNC_UAPSD, +}RT_DEBUG_FUNC; + + +/* ======================== Definition ====================================== */ +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#define BIT0 (1 << 0) +#define BIT1 (1 << 1) +#define BIT2 (1 << 2) +#define BIT3 (1 << 3) +#define BIT4 (1 << 4) +#define BIT5 (1 << 5) +#define BIT6 (1 << 6) +#define BIT7 (1 << 7) +#define BIT8 (1 << 8) +#define BIT9 (1 << 9) +#define BIT10 (1 << 10) +#define BIT11 (1 << 11) +#define BIT12 (1 << 12) +#define BIT13 (1 << 13) +#define BIT14 (1 << 14) +#define BIT15 (1 << 15) +#define BIT16 (1 << 16) +#define BIT17 (1 << 17) +#define BIT18 (1 << 18) +#define BIT19 (1 << 19) +#define BIT20 (1 << 20) +#define BIT21 (1 << 21) +#define BIT22 (1 << 22) +#define BIT23 (1 << 23) +#define BIT24 (1 << 24) +#define BIT25 (1 << 25) +#define BIT26 (1 << 26) +#define BIT27 (1 << 27) +#define BIT28 (1 << 28) +#define BIT29 (1 << 29) +#define BIT30 (1 << 30) +#define BIT31 (1 << 31) + + +/* 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 +#ifdef WH_EVENT_NOTIFIER +#define CUSTOM_IE_TOTAL_LEN 128 +#endif /* WH_EVENT_NOTIFIER */ + +/* */ +/* 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 */ + + +/* All PHY rate summary in TXD */ +/* Preamble MODE in TxD */ +#define MODE_CCK 0 +#define MODE_OFDM 1 +#ifdef DOT11_N_SUPPORT +#define MODE_HTMIX 2 +#define MODE_HTGREENFIELD 3 +#endif /* DOT11_N_SUPPORT */ +#define MODE_VHT 4 + +#ifdef NO_CONSISTENT_MEM_SUPPORT +/* current support RXD_SIZE = 16B and cache line = 16 or 32B */ +#define RTMP_DCACHE_FLUSH(__AddrStart, __Size) \ + RtmpOsDCacheFlush((ULONG)(__AddrStart), (ULONG)(__Size)) +#else +#define RTMP_DCACHE_FLUSH(__AddrStart, __Size) +#endif /* NO_CONSISTENT_MEM_SUPPORT */ + + +/* ======================== Interface ======================================= */ +typedef enum _RTMP_INF_TYPE_ +{ + RTMP_DEV_INF_UNKNOWN = 0, + RTMP_DEV_INF_PCI = 1, + RTMP_DEV_INF_USB = 2, + RTMP_DEV_INF_RBUS = 4, + RTMP_DEV_INF_PCIE = 5, + RTMP_DEV_INF_SDIO= 6, +}RTMP_INF_TYPE; + +#if defined(CONFIG_AP_SUPPORT) && defined(CONFIG_STA_SUPPORT) +#define IF_DEV_CONFIG_OPMODE_ON_AP(_pAd) if(_pAd->OpMode == OPMODE_AP) +#define IF_DEV_CONFIG_OPMODE_ON_STA(_pAd) if(_pAd->OpMode == OPMODE_STA) +#define RT_CONFIG_IF_OPMODE_ON_AP(__OpMode) if (__OpMode == OPMODE_AP) +#define RT_CONFIG_IF_OPMODE_ON_STA(__OpMode) if (__OpMode == OPMODE_STA) +#else +#define IF_DEV_CONFIG_OPMODE_ON_AP(_pAd) +#define IF_DEV_CONFIG_OPMODE_ON_STA(_pAd) +#define RT_CONFIG_IF_OPMODE_ON_AP(__OpMode) +#define RT_CONFIG_IF_OPMODE_ON_STA(__OpMode) +#endif + + + +/*********************************************************************************** + * IOCTL related definitions and data structures. + **********************************************************************************/ +typedef struct __RTMP_IOCTL_INPUT_STRUCT +{ + union + { + CHAR *name; + struct + { + CHAR *pointer; + UINT16 length; + UINT16 flags; + } data; + } u; +} RTMP_IOCTL_INPUT_STRUCT, *PRTMP_IOCTL_INPUT_STRUCT; + + +#define RT_CMD_STATUS_TRANSLATE(__Status) \ + { \ + if (__Status == RTMP_IO_EINVAL) \ + __Status = -EINVAL; \ + else if (__Status == RTMP_IO_EOPNOTSUPP) \ + __Status = -EOPNOTSUPP; \ + else if (__Status == RTMP_IO_EFAULT) \ + __Status = -EFAULT; \ + else if (__Status == RTMP_IO_E2BIG) \ + __Status = -E2BIG; \ + else if (__Status == RTMP_IO_ENOMEM) \ + __Status = -ENOMEM; \ + else if (__Status == RTMP_IO_EAGAIN) \ + __Status = -EAGAIN; \ + else if (__Status == RTMP_IO_ENOTCONN) \ + __Status = -ENOTCONN; \ + } + + + + +/* ======================== Timer =========================================== */ +typedef struct _LIST_RESOURCE_OBJ_ENTRY +{ + struct _LIST_RESOURCE_OBJ_ENTRY *pNext; + VOID *pRscObj; +} LIST_RESOURCE_OBJ_ENTRY, *PLIST_RESOURCE_OBJ_ENTRY; + + + + +/* ======================== IC =========================================== */ +#define RFIC_24GHZ 0x01 +#define RFIC_5GHZ 0x02 +#define RFIC_DUAL_BAND (RFIC_24GHZ | RFIC_5GHZ) + + + + +/* ======================== CFG80211 ======================================== */ +#define RT_CFG80211_DEBUG /* debug use */ + +#ifdef RT_CFG80211_DEBUG +#define CFG80211DBG(__Flg, __pMsg) DBGPRINT(__Flg, __pMsg) +#else +#define CFG80211DBG(__Flg, __pMsg) +#endif /* RT_CFG80211_DEBUG */ + +/* 1 ~ 14 */ +#define CFG80211_NUM_OF_CHAN_2GHZ 14 + +/* 36 ~ 64, 100 ~ 136, 140 ~ 161 */ +#define CFG80211_NUM_OF_CHAN_5GHZ \ + (sizeof(Cfg80211_Chan)-CFG80211_NUM_OF_CHAN_2GHZ) + + + + +/* ======================== Packet ========================================== */ +#define LENGTH_802_11 24 +#define LENGTH_802_11_AND_H 30 +#define LENGTH_802_11_CRC_H 34 +#define LENGTH_802_11_CRC 28 +#define LENGTH_802_11_WITH_ADDR4 30 +#define LENGTH_802_3 14 +#define LENGTH_802_3_TYPE 2 +#define LENGTH_802_1_H 8 +#define LENGTH_EAPOL_H 4 +#define LENGTH_WMMQOS_H 2 +#define LENGTH_CRC 4 +#define MAX_SEQ_NUMBER 0x0fff +#define LENGTH_802_3_NO_TYPE 12 +#define LENGTH_802_1Q 4 /* VLAN related */ + + +#ifdef TX_PKT_SG +#ifndef MAX_SKB_FRAGS +#define MAX_SKB_FRAGS (65536/(1UL << 12) + 2) +#endif +typedef struct _PTK_SG_T{ + VOID *data; + INT len; +}PKT_SG_T; +#endif /* TX_PKT_SG */ +/* + Packet information for NdisQueryPacket +*/ +typedef struct _PACKET_INFO { + UINT PhysicalBufferCount; /* Physical breaks of buffer descripor chained */ + UINT BufferCount; /* Number of Buffer descriptor chained */ + UINT TotalPacketLength ; /* Self explained */ + PNDIS_BUFFER pFirstBuffer; /* Pointer to first buffer descriptor */ +#ifdef TX_PKT_SG + PKT_SG_T sg_list[MAX_SKB_FRAGS]; +#endif /* TX_PKT_SG */ +} PACKET_INFO, *PPACKET_INFO; + + +#define MAC_ADDR_LEN 6 + +#define IS_BM_MAC_ADDR(Addr) (((Addr[0]) & 0x01) == 0x01) +#define IS_MULTICAST_MAC_ADDR(Addr) ((((Addr[0]) & 0x01) == 0x01) && ((Addr[0]) != 0xff)) +#define IS_BROADCAST_MAC_ADDR(Addr) ((((Addr[0]) & 0xff) == 0xff)) + + + +#define RLT_MAC_BASE 0x01 + +#ifdef USB_IOT_WORKAROUND2 +#define W2_IOT_MAX_PADDING_SIZE 1028 //512+512+4 +#define W2_MAX_TX_SIZE 3000 +#define W2_MAX_HTTX_SIZE 32768 +#endif + +#ifdef WH_EZ_SETUP +#define LINE_LEN (4+33+20+23+9+7+7+3) /* Channel+SSID+Bssid+Security+Signal+WiressMode+ExtCh+NetworkType*/ + +BOOLEAN ascii2int(RTMP_STRING *in, UINT32 *out); +#endif +#ifdef NEW_IXIA_METHOD +extern unsigned short dectlen_l; +extern unsigned short dectlen_m; +extern unsigned short dectlen_h; +#define IS_OSEXPECTED_LENGTH(len) (((len >= (dectlen_l - 4)) && (len <= dectlen_l))\ + || ((len >= (dectlen_m - 8)) && (len <= (dectlen_m + 8)))\ + || ((len >= (dectlen_h - 8)) && (len <= (dectlen_h + 8)))) +extern int rx_pkt_len; +extern int rx_pkt_to_os; +#endif +#endif /* __RT_COMM_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_def.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_def.h new file mode 100644 index 000000000..54d4f14cb --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_def.h @@ -0,0 +1,2447 @@ +/* + *************************************************************************** + * 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 */ + + +#if defined(AP_WSC_INCLUDED) || defined(STA_WSC_INCLUDED) +#define WSC_INCLUDED +#endif + + +#define BAND_5G 1 +#define BAND_24G 2 +#define BAND_BOTH (BAND_5G | BAND_24G) + + +#ifdef SNMP_SUPPORT +/* for snmp, to get manufacturer OUI, 2008_0220 */ +#define ManufacturerOUI_LEN 3 +#define ManufacturerNAME ("Ralink Technology Company.") +#define ResourceTypeIdName ("Ralink_ID") +#endif + +#define RALINK_2883_VERSION ((UINT32)0x28830300) +#define RALINK_2880E_VERSION ((UINT32)0x28720200) +#define RALINK_3883_VERSION ((UINT32)0x38830400) +#define RALINK_3070_VERSION ((UINT32)0x30700200) + +#define MAX_RX_PKT_LEN 1520 + + +#define PCI_VIRT_TO_PHYS(__Addr) (((UINT32)(__Addr)) & 0x0FFFFFFF) + + + +#ifdef MULTIPLE_CARD_SUPPORT +/* MC: Multple Cards */ +#define MAX_NUM_OF_MULTIPLE_CARD 32 +#endif /* MULTIPLE_CARD_SUPPORT */ + +#ifdef MEMORY_OPTIMIZATION +#define MAX_RX_PROCESS 32 +#else +#ifdef BB_SOC +#define MAX_RX_PROCESS 64 +#else +#define MAX_RX_PROCESS 128 /*64 //32 */ +#endif /* BB_SOC */ +#endif +#define NUM_OF_LOCAL_TXBUF 2 +#define TXD_SIZE 16 /* TXD_SIZE = TxD + TxInfo */ +#define RXD_SIZE 16 + +#define RXINFO_OFFSET 12 + +/* TXINFO_SIZE + TXWI_SIZE + 802.11 Header Size + AMSDU sub frame header */ +#define TX_DMA_1ST_BUFFER_SIZE 96 /* only the 1st physical buffer is pre-allocated */ + +/*#define MGMT_DMA_BUFFER_SIZE 1536 //2048 */ +/* + Note 20100212 by SampleLin: do not set MGMT_DMA_BUFFER_SIZE smaller than + 1600; Or kernel will crash in deaggregate_AMSDU_announce() for EAPOL packet + in enterprise WPA mode. +*/ +#define MGMT_DMA_BUFFER_SIZE 1600 /*2048 */ + +#define RX_BUFFER_AGGRESIZE 3840 /*3904 //3968 //4096 //2048 //4096 */ +#define RX_BUFFER_NORMSIZE 3840 /*3904 //3968 //4096 //2048 //4096 */ +#define TX_BUFFER_NORMSIZE RX_BUFFER_NORMSIZE +#define MAX_FRAME_SIZE 2346 /* Maximum 802.11 frame size */ +#define MAX_AGGREGATION_SIZE 3840 /*3904 //3968 //4096 */ +#define MAX_NUM_OF_TUPLE_CACHE 2 +#define MAX_MCAST_LIST_SIZE 32 +#define MAX_LEN_OF_VENDOR_DESC 64 +/*#define MAX_SIZE_OF_MCAST_PSQ (NUM_OF_LOCAL_TXBUF >> 2) // AP won't spend more than 1/4 of total buffers on M/BCAST PSQ */ +#define MAX_SIZE_OF_MCAST_PSQ 32 + +#define MAX_RX_PROCESS_CNT (RX_RING_SIZE) + +#ifdef WLAN_SKB_RECYCLE +#define NUM_RX_DESC 128 +#endif /* WLAN_SKB_RECYCLE */ + +#define NUM_OF_UP 9 /*number of user priority: 2set WMM+ non QoS*/ + + +/* + 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 128 +#ifdef BB_SOC +#define MAX_PACKETS_IN_PS_QUEUE 64 +#else /* BB_SOC */ +#define MAX_PACKETS_IN_PS_QUEUE 128 /*32 */ +#endif /* !BB_SOC */ +#define WMM_NUM_OF_AC 4 /* AC0, AC1, AC2, and AC3 */ + +#ifdef CONFIG_AP_SUPPORT +#ifdef IGMP_SNOOP_SUPPORT +#ifdef MEMORY_OPTIMIZATION +#define MAX_LEN_OF_MULTICAST_FILTER_TABLE 16 +#else +#define MAX_LEN_OF_MULTICAST_FILTER_TABLE 64 +#endif +/* Size of hash tab must be power of 2. */ +#define MAX_LEN_OF_MULTICAST_FILTER_HASH_TABLE ((MAX_LEN_OF_MULTICAST_FILTER_TABLE) * 2) +#define FREE_MEMBER_POOL_SIZE 64 +#endif /* IGMP_SNOOP_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#define MAX_AGG_3SS_BALIMIT 31 + +/* RxFilter */ +#define STANORMAL 0x17f97 +#ifdef MIXMODE_SUPPORT +#define APNORMAL 0x1ce70a +#else +#define APNORMAL 0x15f97 +#endif + +#ifdef EXT_BUILD_CHANNEL_LIST +#define MAX_PRECONFIG_DESP_ENTRY_SIZE 11 +#endif /* EXT_BUILD_CHANNEL_LIST */ + + +/* + RTMP_ADAPTER flags +*/ +#define fRTMP_ADAPTER_MAP_REGISTER 0x00000001 +#define fRTMP_ADAPTER_INTERRUPT_IN_USE 0x00000002 +#define fRTMP_HW_ERR 0x00000004 +#define fRTMP_SG 0x00000008 /* Scatter and Gather */ + +#define fRTMP_PKT_TX_ERR 0x00000010 +#define fRTMP_ADAPTER_MLME_RESET_IN_PROGRESS 0x00000020 +#define fRTMP_ADAPTER_HALT_IN_PROGRESS 0x00000040 +#define fRTMP_ADAPTER_RESET_IN_PROGRESS 0x00000080 + +#define fRTMP_ADAPTER_NIC_NOT_EXIST 0x00000100 +//#define fRTMP_ADAPTER_TX_RING_ALLOCATED 0x00000200 +#define fRTMP_ADAPTER_REMOVE_IN_PROGRESS 0x00000400 +#define fRTMP_ADAPTER_MIMORATE_INUSED 0x00000800 + +//#define fRTMP_ADAPTER_RX_RING_ALLOCATED 0x00001000 +#define fRTMP_ADAPTER_INTERRUPT_ACTIVE 0x00002000 +#define fRTMP_ADAPTER_BSS_SCAN_IN_PROGRESS 0x00004000 +#define fRTMP_ADAPTER_REASSOC_IN_PROGRESS 0x00008000 + +#define fRTMP_ADAPTER_MEDIA_STATE_PENDING 0x00010000 +#define fRTMP_ADAPTER_RADIO_OFF 0x00020000 +#define fRTMP_ADAPTER_BULKOUT_RESET 0x00040000 +#define fRTMP_ADAPTER_BULKIN_RESET 0x00080000 + +#define fRTMP_ADAPTER_RDG_ACTIVE 0x00100000 +#define fRTMP_ADAPTER_DYNAMIC_BE_TXOP_ACTIVE 0x00200000 +#define fRTMP_ADAPTER_RALINK_BURST_MODE 0x00400000 +#define fRTMP_ADAPTER_DISABLE_DEQUEUEPACKET 0x00800000 + +#define fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD 0x01000000 +#define fRTMP_ADAPTER_CMD_RADIO_OFF 0x02000000 +#define fRTMP_ADAPTER_SCAN_2040 0x04000000 +#define fRTMP_ADAPTER_RADIO_MEASUREMENT 0x08000000 + +#define fRTMP_ADAPTER_START_UP 0x10000000 /*Devive already initialized and enabled Tx/Rx. */ +//#ifdef CONFIG_PM +//#ifdef USB_SUPPORT_SELECTIVE_SUSPEND +#define fRTMP_ADAPTER_SUSPEND 0x20000000 +//#endif /* USB_SUPPORT_SELECTIVE_SUSPEND */ +//#endif /* CONFIG_PM */ +//#define fRTMP_ADAPTER_MEDIA_STATE_CHANGE 0x20000000 +#define fRTMP_ADAPTER_IDLE_RADIO_OFF 0x40000000 +#define fRTMP_ADAPTER_POLL_IDLE 0x80000000 + +enum ASIC_CAP{ + fASIC_CAP_RX_SC = 0x1, + fASIC_CAP_CSO = 0x2, + fASIC_CAP_TSO = 0x4, + fASIC_CAP_MCS_LUT = 0x8, + + fASIC_CAP_PMF_ENC = 0x10, +}; + +#define fRTMP_ADAPTER_DISABLE_DOT_11N 0x00000001 +#define fRTMP_ADAPTER_WSC_PBC_PIN0 0x00000002 +#define fRTMP_ADAPTER_DISABLE_DEQUEUE 0x00000004 + +enum PHY_CAP{ + fPHY_CAP_24G = 0x1, + fPHY_CAP_5G = 0x2, + + fPHY_CAP_HT = 0x10, + fPHY_CAP_VHT = 0x20, + + fPHY_CAP_TXBF = 0x100, + fPHY_CAP_LDPC = 0x200, +}; + +enum HIF_TYPE{ + HIF_RTMP = 0x0, + HIF_RLT = 0x1, + HIF_MT = 0x2, +}; + +enum MAC_TYPE{ + MAC_RTMP = 0x0, + MAC_MT = 0x1, +}; + +enum RF_TYPE { + RF_RT, + RF_RLT, + RF_MT76x2, + RF_MT, +}; + +enum BBP_TYPE{ + BBP_RTMP = 0x0, + BBP_RLT = 0x1, + BBP_MT = 0x2, +}; + +#define PHY_CAP_2G(_x) (((_x) & fPHY_CAP_24G) == fPHY_CAP_24G) +#define PHY_CAP_5G(_x) (((_x) & fPHY_CAP_5G) == fPHY_CAP_5G) +#define PHY_CAP_N(_x) (((_x) & fPHY_CAP_HT) == fPHY_CAP_HT) +#define PHY_CAP_AC(_x) (((_x) & fPHY_CAP_VHT) == fPHY_CAP_VHT) + +enum WIFI_MODE{ + WMODE_INVALID = 0, + WMODE_A = 1 << 0, + WMODE_B = 1 << 1, + WMODE_G = 1 << 2, + WMODE_GN = 1 << 3, + WMODE_AN = 1 << 4, + WMODE_AC = 1 << 5, + WMODE_COMP = 6, /* total types of supported wireless mode, add this value once yow add new type */ +}; + +#define WMODE_CAP_5G(_x) (((_x) & (WMODE_A | WMODE_AN | WMODE_AC)) != 0) +#define WMODE_CAP_2G(_x) (((_x) & (WMODE_B | WMODE_G | WMODE_GN)) != 0) +#define WMODE_CAP_N(_x) (((_x) & (WMODE_GN | WMODE_AN)) != 0) +#define WMODE_CAP_AC(_x) (((_x) & (WMODE_AC)) != 0) +#define WMODE_CAP(_x, _mode) (((_x) & (_mode)) != 0) + +#define WMODE_EQUAL(_x, _mode) ((_x) == (_mode)) + +#define WMODE_5G_ONLY(_x) (((_x) & (WMODE_B | WMODE_G | WMODE_GN)) == 0) +#define WMODE_2G_ONLY(_x) (((_x) & (WMODE_A | WMODE_AN | WMODE_AC)) == 0) +#define WMODE_HT_ONLY(_x) (((_x) & (~(WMODE_GN | WMODE_AN | WMODE_AC))) == 0) +#define WMODE_VHT_ONLY(_x) (((_x) & (~(WMODE_AC))) == 0) + + +/* + STA operation status flags +*/ +#define fOP_STATUS_INFRA_ON 0x00000001 +#define fOP_STATUS_ADHOC_ON 0x00000002 +#define fOP_STATUS_BG_PROTECTION_INUSED 0x00000004 +#define fOP_STATUS_SHORT_SLOT_INUSED 0x00000008 +#define fOP_STATUS_SHORT_PREAMBLE_INUSED 0x00000010 +#define fOP_STATUS_RECEIVE_DTIM 0x00000020 +/*#define fOP_STATUS_TX_RATE_SWITCH_ENABLED 0x00000040 */ +#define fOP_STATUS_MEDIA_STATE_CONNECTED 0x00000080 +#define fOP_STATUS_WMM_INUSED 0x00000100 +#define fOP_STATUS_DOZE 0x00000400 /* debug purpose */ +#define fOP_STATUS_APSD_INUSED 0x00001000 +#define fOP_STATUS_TX_AMSDU_INUSED 0x00002000 +#define fOP_STATUS_MAX_RETRY_ENABLED 0x00004000 +#define fOP_STATUS_WAKEUP_NOW 0x00008000 +#define fOP_STATUS_ADVANCE_POWER_SAVE_PCIE_DEVICE 0x00020000 + +#ifdef DOT11V_WNM_SUPPORT +#define fOP_STATUS_FMS_ENABLE 0x00400000 +#endif /* DOT11V_WNM_SUPPORT */ +#define fOP_AP_STATUS_MEDIA_STATE_CONNECTED 0x00200000 + + + +/* + RTMP_ADAPTER PSFlags : related to advanced power save +*/ +/* Indicate whether driver can go to sleep mode from now. This flag is useful AFTER link up */ +#define fRTMP_PS_CAN_GO_SLEEP 0x00000001 +/* Indicate whether driver has issue a LinkControl command to PCIe L1 */ +#define fRTMP_PS_SET_PCI_CLK_OFF_COMMAND 0x00000002 +/* Indicate driver should disable kick off hardware to send packets from now. */ +#define fRTMP_PS_DISABLE_TX 0x00000004 +/* Indicate driver should IMMEDIATELY fo to sleep after receiving AP's beacon in which doesn't indicate unicate nor multicast packets for me */ +/* This flag is used ONLY in RTMPHandleRxDoneInterrupt routine. */ +#define fRTMP_PS_GO_TO_SLEEP_NOW 0x00000008 +#define fRTMP_PS_TOGGLE_L1 0x00000010 /* Use Toggle L1 mechanism for rt28xx PCIe */ + +#define fRTMP_PS_MCU_SLEEP 0x00000020 + +#define WAKE_MCU_CMD 0x31 +#define SLEEP_MCU_CMD 0x30 +#define RFOFF_MCU_CMD 0x35 + +#ifdef DOT11N_DRAFT3 +#define fOP_STATUS_SCAN_2040 0x00040000 +#endif /* DOT11N_DRAFT3 */ + +#define CCKSETPROTECT 0x1 +#define OFDMSETPROTECT 0x2 +#define MM20SETPROTECT 0x4 +#define MM40SETPROTECT 0x8 +#define GF20SETPROTECT 0x10 +#define GR40SETPROTECT 0x20 +#define ALLN_SETPROTECT (GR40SETPROTECT | GF20SETPROTECT | MM40SETPROTECT | MM20SETPROTECT) + +/* + AP's client table operation status flags +*/ +#define fCLIENT_STATUS_WMM_CAPABLE 0x00000001 /* CLIENT can parse QOS DATA frame */ +#define fCLIENT_STATUS_AGGREGATION_CAPABLE 0x00000002 /* CLIENT can receive Ralink's proprietary TX aggregation frame */ +#define fCLIENT_STATUS_PIGGYBACK_CAPABLE 0x00000004 /* CLIENT support piggy-back */ +#define fCLIENT_STATUS_AMSDU_INUSED 0x00000008 +#define fCLIENT_STATUS_SGI20_CAPABLE 0x00000010 +#define fCLIENT_STATUS_SGI40_CAPABLE 0x00000020 +#define fCLIENT_STATUS_TxSTBC_CAPABLE 0x00000040 +#define fCLIENT_STATUS_RxSTBC_CAPABLE 0x00000080 +#define fCLIENT_STATUS_HTC_CAPABLE 0x00000100 +#define fCLIENT_STATUS_RDG_CAPABLE 0x00000200 +#define fCLIENT_STATUS_MCSFEEDBACK_CAPABLE 0x00000400 +#define fCLIENT_STATUS_APSD_CAPABLE 0x00000800 /* UAPSD STATION */ + +#ifdef DOT11N_DRAFT3 +#define fCLIENT_STATUS_BSSCOEXIST_CAPABLE 0x00001000 +#endif /* DOT11N_DRAFT3 */ +#define fCLIENT_STATUS_SOFTWARE_ENCRYPT 0x00002000 /* Indicate the client encrypt/decrypt by software */ +#ifdef DOT11W_PMF_SUPPORT +#define fCLIENT_STATUS_PMF_CAPABLE 0x00004000 +#define fCLIENT_STATUS_USE_SHA256 0x00008000 +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef DOT11_VHT_AC +#define fCLIENT_STATUS_SGI80_CAPABLE 0x00010000 +#define fCLIENT_STATUS_SGI160_CAPABLE 0x00020000 +#define fCLIENT_STATUS_VHT_TXSTBC_CAPABLE 0x00040000 +#define fCLIENT_STATUS_VHT_RXSTBC_CAPABLE 0x00080000 +#endif /* DOT11_VHT_AC */ + +#define fCLIENT_STATUS_RALINK_CHIPSET 0x00100000 + +#ifdef CLIENT_WDS +#define fCLIENT_STATUS_CLI_WDS 0x00200000 +#endif /* CLIENT_WDS */ + + +#define fCLIENT_STATUS_VHT_RX_LDPC_CAPABLE 0x00800000 +#define fCLIENT_STATUS_HT_RX_LDPC_CAPABLE 0x01000000 + +#ifdef CONFIG_HOTSPOT_R2 +#define fCLIENT_STATUS_OSEN_CAPABLE 0x02000000 +#endif + +/* + STA configuration flags +*/ +/*#define fSTA_CFG_ENABLE_TX_BURST 0x00000001 */ + +/* 802.11n Operating Mode Definition. 0-3 also used in ASICUPdateProtect switch case */ +#define HT_NO_PROTECT 0 +#define HT_LEGACY_PROTECT 1 +#define HT_40_PROTECT 2 +#define HT_2040_PROTECT 3 +#define HT_RTSCTS_6M 7 +/*following is our own definition in order to turn on our ASIC protection register in INFRASTRUCTURE. */ +#define HT_ATHEROS 8 /* rt2860c has problem with atheros chip. we need to turn on RTS/CTS . */ +#define HT_FORCERTSCTS 9 /* Force turn on RTS/CTS first. then go to evaluate if this force RTS is necessary. */ + +/* + RX Packet Filter control flags. Apply on pAd->PacketFilter +*/ +#define fRX_FILTER_ACCEPT_DIRECT NDIS_PACKET_TYPE_DIRECTED +#define fRX_FILTER_ACCEPT_MULTICAST NDIS_PACKET_TYPE_MULTICAST +#define fRX_FILTER_ACCEPT_BROADCAST NDIS_PACKET_TYPE_BROADCAST +#define fRX_FILTER_ACCEPT_ALL_MULTICAST NDIS_PACKET_TYPE_ALL_MULTICAST +#define fRX_FILTER_ACCEPT_PROMISCUOUS NDIS_PACKET_TYPE_PROMISCUOUS + +/* + Error code section +*/ +/* NDIS_ERROR_CODE_ADAPTER_NOT_FOUND */ +#define ERRLOG_READ_PCI_SLOT_FAILED 0x00000101L +#define ERRLOG_WRITE_PCI_SLOT_FAILED 0x00000102L +#define ERRLOG_VENDOR_DEVICE_NOMATCH 0x00000103L + +/* NDIS_ERROR_CODE_ADAPTER_DISABLED */ +#define ERRLOG_BUS_MASTER_DISABLED 0x00000201L + +/* NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION */ +#define ERRLOG_INVALID_SPEED_DUPLEX 0x00000301L +#define ERRLOG_SET_SECONDARY_FAILED 0x00000302L + +/* NDIS_ERROR_CODE_OUT_OF_RESOURCES */ +#define ERRLOG_OUT_OF_MEMORY 0x00000401L +#define ERRLOG_OUT_OF_SHARED_MEMORY 0x00000402L +#define ERRLOG_OUT_OF_MAP_REGISTERS 0x00000403L +#define ERRLOG_OUT_OF_BUFFER_POOL 0x00000404L +#define ERRLOG_OUT_OF_NDIS_BUFFER 0x00000405L +#define ERRLOG_OUT_OF_PACKET_POOL 0x00000406L +#define ERRLOG_OUT_OF_NDIS_PACKET 0x00000407L +#define ERRLOG_OUT_OF_LOOKASIDE_MEMORY 0x00000408L + +/* NDIS_ERROR_CODE_HARDWARE_FAILURE */ +#define ERRLOG_SELFTEST_FAILED 0x00000501L +#define ERRLOG_INITIALIZE_ADAPTER 0x00000502L +#define ERRLOG_REMOVE_MINIPORT 0x00000503L + +/* NDIS_ERROR_CODE_RESOURCE_CONFLICT */ +#define ERRLOG_MAP_IO_SPACE 0x00000601L +#define ERRLOG_QUERY_ADAPTER_RESOURCES 0x00000602L +#define ERRLOG_NO_IO_RESOURCE 0x00000603L +#define ERRLOG_NO_INTERRUPT_RESOURCE 0x00000604L +#define ERRLOG_NO_MEMORY_RESOURCE 0x00000605L + +/* WDS definition */ +#define MAX_WDS_ENTRY 0 +#ifdef WDS_SUPPORT +#undef MAX_WDS_ENTRY +#define MAX_WDS_ENTRY 4 +#endif /* WDS_SUPPORT */ +#define WDS_PAIRWISE_KEY_OFFSET 60 /* WDS links uses pairwise key#60 ~ 63 in ASIC pairwise key table */ + +#define WDS_DISABLE_MODE 0 +#define WDS_RESTRICT_MODE 1 +#define WDS_BRIDGE_MODE 2 +#define WDS_REPEATER_MODE 3 +#define WDS_LAZY_MODE 4 + +#define MAX_MESH_NUM 0 + +#define MAX_APCLI_NUM 0 +#ifdef APCLI_SUPPORT +#undef MAX_APCLI_NUM +#ifdef MULTI_APCLI_SUPPORT +#define MAX_APCLI_NUM 2 +#else /* MULTI_APCLI_SUPPORT*/ +#define MAX_APCLI_NUM 1 +#endif /* !MULTI_APCLI_SUPPORT */ +#endif /* APCLI_SUPPORT */ + +#ifdef APCLI_SAE_SUPPORT +enum _REPEATER_MLME_ENQ_IDX_CHK_TBL { + REPT_MLME_START_IDX = 64, + REPT_MLME_LAST_IDX = 95, + REPT_MLME_MAX_IDX = 96,/*shall not over this.*/ +}; +#endif + +#define MAX_P2P_NUM 0 + +#define MAX_MBSSID_NUM(__pAd) 1 + +#ifdef MAC_APCLI_SUPPORT +#define APCLI_BSS_BASE 8 +#else +#define APCLI_BSS_BASE 0 +#endif /* MAC_APCLI_SUPPORT */ + + +#ifdef MBSS_SUPPORT +#undef MAX_MBSSID_NUM +#define MAX_MBSSID_NUM(__pAd) ((__pAd)->chipCap.BcnMaxNum) +#define HW_BEACON_MAX_COUNT(__pAd) ((__pAd)->chipCap.BcnMaxHwNum) +#else +#define HW_BEACON_MAX_COUNT(__pAd) 8 +#endif /* MBSS_SUPPORT */ +#ifdef ECONET_ALPHA_RELEASE +#define HW_BEACON_MAX_NUM 8 +#else +#define HW_BEACON_MAX_NUM 16 +#endif /* ECONET_ALPHA_RELEASE */ + + +#define WDEV_NUM_MAX (HW_BEACON_MAX_NUM + MAX_WDS_ENTRY + \ + MAX_APCLI_NUM + MAX_P2P_NUM + MAX_MESH_NUM) + + +/* sanity check for apidx */ +#define MBSS_MR_APIDX_SANITY_CHECK(__pAd, apidx) \ + { if ((apidx >= MAX_MBSSID_NUM(__pAd)) || \ + (apidx >= HW_BEACON_MAX_NUM)) { \ + DBGPRINT(RT_DEBUG_ERROR, ("%s> Error! apidx = %d > MAX_MBSSID_NUM!\n", __FUNCTION__, apidx)); \ + apidx = MAIN_MBSSID; } } + +#define VALID_WCID(_wcid) ((_wcid) > 0 && (_wcid) < MAX_LEN_OF_MAC_TABLE ) + +#define VALID_MBSS(_pAd, _apidx) ((_apidx < MAX_MBSSID_NUM(_pAd)) && (_apidx < HW_BEACON_MAX_NUM)) + +#define MAX_BEACON_SIZE 512 +#define MAX_TIM_SIZE 256 +/* Carter: TIM ie max length could achieve 257 byte in spec, + but it will never reach this value in Ralink Driver */ + + +#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) + +#if defined(MT7603_FPGA) || defined(MT7628_FPGA) || defined(MT7636_FPGA) +#define LAST_SPECIFIC_WCID(__pAd) 20 +#define MAX_AVAILABLE_CLIENT_WCID(__pAd) (LAST_SPECIFIC_WCID(__pAd) - MAX_MBSSID_NUM(__pAd)) +#else +#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) +#endif /* MT7603_FPGA */ + + +/* 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; \ + } + +#ifdef DOT11W_PMF_SUPPORT +#define GET_PMF_GroupKey_WCID(__pAd, __wcid, __bssidx) \ + { \ + __wcid = LAST_SPECIFIC_WCID(__pAd) - (MAX_MBSSID_NUM(__pAd) * 2) + __bssidx; \ + } +#endif /* DOT11W_PMF_SUPPORT */ + +/*#define IsGroupKeyWCID(__pAd, __wcid) (((__wcid) < LAST_SPECIFIC_WCID) && ((__wcid) >= (LAST_SPECIFIC_WCID - (MAX_MBSSID_NUM(__pAd))))) */ + +/* definition to support multiple BSSID */ +#define BSS0 0 +#define BSS1 1 +#define BSS2 2 +#define BSS3 3 +#define BSS4 4 +#define BSS5 5 +#define BSS6 6 +#define BSS7 7 + +/*============================================================ */ +/* Length definitions */ +#define PEER_KEY_NO 2 +#define TIMESTAMP_LEN 8 +#define MAX_LEN_OF_SUPPORTED_RATES MAX_LENGTH_OF_SUPPORT_RATES /* 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54 */ +#define MAX_NUM_OF_REGULATORY_CLASS 16 +#define MAX_LEN_OF_KEY 32 /* 32 octets == 256 bits, Redefine for WPA */ +/* #define MAX_NUM_OF_CHANNELS MAX_NUM_OF_CHS */ /* 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination */ +#define MAX_NUM_OF_11JCHANNELS 20 /* 14 channels @2.4G + 12@UNII + 4 @MMAC + 11 @HiperLAN2 + 7 @Japan + 1 as NULL termination */ +#define MAX_LEN_OF_SSID 32 +#define CIPHER_TEXT_LEN 128 +#define HASH_TABLE_SIZE 256 /* Size of hash tab must be power of 2. */ +#define MAX_VIE_LEN 1024 /* New for WPA cipher suite variable IE sizes. */ +#define MAX_SUPPORT_MCS 32 +#define MAX_NUM_OF_BBP_LATCH 256 +#undef MAX_NUM_OF_BBP_LATCH +#define MAX_NUM_OF_BBP_LATCH 255 + +#define MAX_LEN_OF_CCK_RATES 4 +#define MAX_LEN_OF_OFDM_RATES 8 +#define MAX_LEN_OF_HT_RATES 24 +#ifdef DOT11_VHT_AC +#define MAX_LEN_OF_VHT_RATES 20 +#endif /* DOT11_VHT_AC */ +#define SUPPORT_CCK_MODE 1 +#define SUPPORT_OFDM_MODE 2 +#define SUPPORT_HT_MODE 4 +#define SUPPORT_VHT_MODE 8 + +/*============================================================ */ +/* ASIC WCID Table definition. */ +/*============================================================ */ +#define BSSID_WCID 1 /* in infra mode, always put bssid with this WCID */ +#define MCAST_WCID 0x0 + +#ifdef MULTI_APCLI_SUPPORT +#define APCLI_MCAST_WCID(_num)\ + (MAX_LEN_OF_MAC_TABLE + HW_BEACON_MAX_NUM + MAX_APCLI_NUM + _num) +#else /* MULTI_APCLI_SUPPORT */ +#define APCLI_MCAST_WCID (MAX_LEN_OF_MAC_TABLE + HW_BEACON_MAX_NUM + MAX_APCLI_NUM) +#endif /* !MULTI_APCLI_SUPPORT */ +#define BSS0Mcast_WCID 0x0 +#define BSS1Mcast_WCID 0xf8 +#define BSS2Mcast_WCID 0xf9 +#define BSS3Mcast_WCID 0xfa +#define BSS4Mcast_WCID 0xfb +#define BSS5Mcast_WCID 0xfc +#define BSS6Mcast_WCID 0xfd +#define BSS7Mcast_WCID 0xfe +#define RESERVED_WCID 0xff +#define WCID_ALL 0xff + + +#define MAX_NUM_OF_ACL_LIST MAX_NUMBER_OF_ACL + +#if defined(MAC_REPEATER_SUPPORT) /*&& !defined(MT_MAC)*/ +#define MAX_LEN_OF_MAC_TABLE (MAX_NUMBER_OF_MAC + ((MAX_EXT_MAC_ADDR_SIZE + 1) * MAX_APCLI_NUM)) +#else +#define MAX_LEN_OF_MAC_TABLE MAX_NUMBER_OF_MAC /* if MAX_MBSSID_NUM is 8, this value can't be larger than 211 */ +#endif + +#define MAX_LEN_OF_TR_TABLE (MAX_LEN_OF_MAC_TABLE + HW_BEACON_MAX_NUM) + +#define VALID_TR_WCID(_wcid) ((_wcid) < MAX_LEN_OF_TR_TABLE) + +/*#if MAX_LEN_OF_MAC_TABLE>MAX_AVAILABLE_CLIENT_WCID */ +/*#error MAX_LEN_OF_MAC_TABLE can not be larger than MAX_AVAILABLE_CLIENT_WCID!!!! */ +/*#endif */ + +#define MAX_NUM_OF_WDS_LINK_PERBSSID 3 +/*#define MAX_NUM_OF_WDS_LINK (MAX_NUM_OF_WDS_LINK_PERBSSID*MAX_MBSSID_NUM) // no use */ +#define MAX_NUM_OF_EVENT MAX_NUMBER_OF_EVENT +#define WDS_LINK_START_WCID (MAX_LEN_OF_MAC_TABLE-1) + +#define NUM_OF_TID 8 +#define MAX_AID_BA 4 + +#define MAX_LEN_OF_BA_REC_TABLE ((NUM_OF_TID * MAX_LEN_OF_MAC_TABLE)/2) /* (NUM_OF_TID*MAX_AID_BA + 32) //Block ACK recipient */ +#define MAX_LEN_OF_BA_ORI_TABLE ((NUM_OF_TID * MAX_LEN_OF_MAC_TABLE)/2) /* (NUM_OF_TID*MAX_AID_BA + 32) // Block ACK originator */ + +#ifdef MEMORY_OPTIMIZATION +#define MAX_LEN_OF_BSS_TABLE 1 +#define MAX_REORDERING_MPDU_NUM 256 +#else +#ifdef BB_SOC +#ifdef NEIGHBORING_AP_STAT +#define MAX_LEN_OF_BSS_TABLE 64 +#else +#define MAX_LEN_OF_BSS_TABLE 20 +#endif /*NEIGHBORING_AP_STAT*/ +#else /* BB_SOC */ +#ifdef ECONET_ALPHA_RELEASE +#define MAX_LEN_OF_BSS_TABLE 96 /* 64 */ +#else +#define MAX_LEN_OF_BSS_TABLE 128 /* 64 */ +#endif /* ECONET_ALPHA_RELEASE */ +#endif /* !BB_SOC */ +#define MAX_REORDERING_MPDU_NUM 512 +#endif + +#if defined(MAX_CONTINUOUS_TX_CNT) || defined(NEW_IXIA_METHOD) +#undef MAX_REORDERING_MPDU_NUM +#define MAX_REORDERING_MPDU_NUM 2048 +#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 +#ifdef WH_EZ_SETUP +#define LEN_PSK 64 +#endif +#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 */ + +/* For AP PS retrieve status */ +#define APPS_RETRIEVE_IDLE 0 +#define APPS_RETRIEVE_CR_PADDING 1 +#define APPS_RETRIEVE_START_PS 2 +#define APPS_RETRIEVE_GOING 3 +#define APPS_RETRIEVE_WAIT_EVENT 4 +#define APPS_RETRIEVE_DONE 5 + +#ifdef MTFWD +enum nl_msg_id { + FWD_CMD_ADD_TX_SRC = 3, + FWD_CMD_DEL_TX_SRC = 4, +}; +#endif + +/*#define PWR_UNKNOWN 2 */ + +/* Auth and Assoc mode related definitions */ +#define AUTH_MODE_OPEN 0x00 +#define AUTH_MODE_KEY 0x01 +#define AUTH_MODE_FT 0x02 +#define AUTH_MODE_SAE 0x03 +#define AUTH_MODE_VENDOR 0xffff + +/* BSS Type definitions */ +#define BSS_ADHOC 0 /* = Ndis802_11IBSS */ +#define BSS_INFRA 1 /* = Ndis802_11Infrastructure */ +#define BSS_ANY 2 /* = Ndis802_11AutoUnknown */ +#define BSS_MONITOR 3 /* = Ndis802_11Monitor */ + +/* Reason code definitions */ +#define REASON_RESERVED 0 +#define REASON_UNSPECIFY 1 +#define REASON_NO_LONGER_VALID 2 +#define REASON_DEAUTH_STA_LEAVING 3 +#define REASON_DISASSOC_INACTIVE 4 +#define REASON_DISASSPC_AP_UNABLE 5 +#define REASON_CLS2ERR 6 +#define REASON_CLS3ERR 7 +#define REASON_DISASSOC_STA_LEAVING 8 +#define REASON_STA_REQ_ASSOC_NOT_AUTH 9 +#define REASON_INVALID_IE 13 +#define REASON_MIC_FAILURE 14 +#define REASON_4_WAY_TIMEOUT 15 +#define REASON_GROUP_KEY_HS_TIMEOUT 16 +#define REASON_IE_DIFFERENT 17 +#define REASON_MCIPHER_NOT_VALID 18 +#define REASON_UCIPHER_NOT_VALID 19 +#define REASON_AKMP_NOT_VALID 20 +#define REASON_UNSUPPORT_RSNE_VER 21 +#define REASON_INVALID_RSNE_CAP 22 +#define REASON_8021X_AUTH_FAIL 23 +#define REASON_CIPHER_SUITE_REJECTED 24 +#define REASON_DECLINED 37 + +#define REASON_QOS_UNSPECIFY 32 +#define REASON_QOS_LACK_BANDWIDTH 33 +#define REASON_POOR_CHANNEL_CONDITION 34 +#define REASON_QOS_OUTSIDE_TXOP_LIMITION 35 +#define REASON_QOS_QSTA_LEAVING_QBSS 36 +#define REASON_QOS_UNWANTED_MECHANISM 37 +#define REASON_QOS_MECH_SETUP_REQUIRED 38 +#define REASON_QOS_REQUEST_TIMEOUT 39 +#define REASON_QOS_CIPHER_NOT_SUPPORT 45 + +#ifdef WIFI_DIAG +#define REASON_STANDARD_MAX 0xFFFF /* 65535 */ +#define REASON_UNKNOWN (REASON_STANDARD_MAX + 1) +#define REASON_AGING_TIME_OUT (REASON_STANDARD_MAX + 2) +#define REASON_CONTINUE_TX_FAIL (REASON_STANDARD_MAX + 3) +#define REASON_RSSI_TOO_LOW (REASON_STANDARD_MAX + 4) +#define REASON_AUTH_WRONG_ALGORITHM (REASON_STANDARD_MAX + 5) +#define REASON_CHALLENGE_FAIL (REASON_STANDARD_MAX + 6) +#define REASON_4WAY_HS_MSG1_FAIL (REASON_STANDARD_MAX + 7) +#define REASON_4WAY_HS_MSG2_FAIL (REASON_STANDARD_MAX + 8) +#define REASON_4WAY_HS_MSG3_FAIL (REASON_STANDARD_MAX + 9) +#define REASON_4WAY_HS_MSG4_FAIL (REASON_STANDARD_MAX + 10) +#define REASON_2WAY_HS_MSG1_FAIL (REASON_STANDARD_MAX + 11) +#define REASON_2WAY_HS_MSG2_FAIL (REASON_STANDARD_MAX + 12) +#define REASON_DECRYPTION_FAIL (REASON_STANDARD_MAX + 13) +#endif + +#ifdef DOT11V_WNM_SUPPORT +#define REASON_DISASSOC_DUE_TO_BSS_TRANSITION_MANAGEMENT 12 +#endif /* DOT11V_WNM_SUPPORT */ + +#define REASON_FT_INVALID_FTIE 55 + +/* Status code definitions */ +#define MLME_SUCCESS 0 +#define MLME_UNSPECIFY_FAIL 1 +#define MLME_SECURITY_WEAK 5 +#define MLME_CANNOT_SUPPORT_CAP 10 +#define MLME_REASSOC_DENY_ASSOC_EXIST 11 +#define MLME_ASSOC_DENY_OUT_SCOPE 12 +#define MLME_ALG_NOT_SUPPORT 13 +#define MLME_SEQ_NR_OUT_OF_SEQUENCE 14 +#define MLME_REJ_CHALLENGE_FAILURE 15 +#define MLME_REJ_TIMEOUT 16 +#define MLME_ASSOC_REJ_UNABLE_HANDLE_STA 17 +#define MLME_ASSOC_REJ_DATA_RATE 18 + +#define MLME_ASSOC_REJ_NO_EXT_RATE 22 +#define MLME_ASSOC_REJ_NO_EXT_RATE_PBCC 23 +#define MLME_ASSOC_REJ_NO_CCK_OFDM 24 + +#ifdef DOT11W_PMF_SUPPORT +#define MLME_ASSOC_REJ_TEMPORARILY 30 +#define MLME_ROBUST_MGMT_POLICY_VIOLATION 31 +#endif /* DOT11W_PMF_SUPPORT */ + +#ifdef WH_EZ_SETUP +#ifdef NEW_CONNECTION_ALGO +#undef MLME_ASSOC_REJ_TEMPORARILY +#define MLME_ASSOC_REJ_TEMPORARILY 30 +#endif +#endif + +#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 + +#ifdef DOT11_SAE_SUPPORT +#define MLME_INVALID_PMKID 53 +#define MLME_ANTI_CLOGGING_TOKEN_REQ 76 +#endif + +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +#define MLME_FINITE_CYCLIC_GROUP_NOT_SUPPORTED 77 +#endif + +#ifdef CONFIG_OWE_SUPPORT +#define IE_WLAN_EXTENSION 255 +#define IE_EXTENSION_ID_ECDH 32 +#endif +#ifdef WH_EZ_SETUP +#define MLME_EZ_CONNECTION_LOOP 110 +#define MLME_EZ_DISCONNECT_NON_EZ 111 +#endif + +/* IE code */ +#define IE_SSID 0 +#define IE_SUPP_RATES 1 +#define IE_FH_PARM 2 +#define IE_DS_PARM 3 +#define IE_CF_PARM 4 +#define IE_TIM 5 +#define IE_IBSS_PARM 6 +#define IE_COUNTRY 7 /* 802.11d */ +#define IE_802_11D_REQUEST 10 /* 802.11d */ +#define IE_QBSS_LOAD 11 /* 802.11e d9 */ +#define IE_EDCA_PARAMETER 12 /* 802.11e d9 */ +#define IE_TSPEC 13 /* 802.11e d9 */ +#define IE_TCLAS 14 /* 802.11e d9 */ +#define IE_SCHEDULE 15 /* 802.11e d9 */ +#define IE_CHALLENGE_TEXT 16 +#define IE_POWER_CONSTRAINT 32 /* 802.11h d3.3 */ +#define IE_POWER_CAPABILITY 33 /* 802.11h d3.3 */ +#define IE_TPC_REQUEST 34 /* 802.11h d3.3 */ +#define IE_TPC_REPORT 35 /* 802.11h d3.3 */ +#define IE_SUPP_CHANNELS 36 /* 802.11h d3.3 */ +#define IE_CHANNEL_SWITCH_ANNOUNCEMENT 37 /* 802.11h d3.3 */ +#define IE_MEASUREMENT_REQUEST 38 /* 802.11h d3.3 */ +#define IE_MEASUREMENT_REPORT 39 /* 802.11h d3.3 */ +#define IE_QUIET 40 /* 802.11h d3.3 */ +#define IE_IBSS_DFS 41 /* 802.11h d3.3 */ +#define IE_ERP 42 /* 802.11g */ +#define IE_TS_DELAY 43 /* 802.11e d9 */ +#define IE_TCLAS_PROCESSING 44 /* 802.11e d9 */ +#define IE_QOS_CAPABILITY 46 /* 802.11e d6 */ +#define IE_HT_CAP 45 /* 802.11n d1. HT CAPABILITY. ELEMENT ID TBD */ +#define IE_AP_CHANNEL_REPORT 51 /* 802.11k d6 */ +#define IE_HT_CAP2 52 /* 802.11n d1. HT CAPABILITY. ELEMENT ID TBD */ +#define IE_RSN 48 /* 802.11i d3.0 */ +#define IE_WPA2 48 /* WPA2 */ +#define IE_EXT_SUPP_RATES 50 /* 802.11g */ +#define IE_TIMEOUT_INTERVAL 56 /* 802.11w */ +#define IE_SUPP_REG_CLASS 59 /* 802.11y. Supported regulatory classes. */ +#define IE_EXT_CHANNEL_SWITCH_ANNOUNCEMENT 60 /* 802.11n */ +#define IE_ADD_HT 61 /* 802.11n d1. ADDITIONAL HT CAPABILITY. ELEMENT ID TBD */ +#define IE_ADD_HT2 53 /* 802.11n d1. ADDITIONAL HT CAPABILITY. ELEMENT ID TBD */ + +/* For 802.11n D3.03 */ +/*#define IE_NEW_EXT_CHA_OFFSET 62 // 802.11n d1. New extension channel offset elemet */ +#define IE_SECONDARY_CH_OFFSET 62 /* 802.11n D3.03 Secondary Channel Offset element */ +#define IE_WAPI 68 /* WAPI information element. Same as Bss Ac Access Dealy Element. */ +#define IE_TIME_ADVERTISEMENT 69 // 802.11p +#define IE_2040_BSS_COEXIST 72 /* 802.11n D3.0.3 */ +#define IE_2040_BSS_INTOLERANT_REPORT 73 /* 802.11n D3.03 */ +#define IE_OVERLAPBSS_SCAN_PARM 74 /* 802.11n D3.03 */ +#define IE_CHANNEL_USAGE 97 /* Cisco advertises suggested channel using this IE. */ +#define IE_TIME_ZONE 98 /* 802.11V */ +#define IE_INTERWORKING 107 /* 802.11u */ +#define IE_ADVERTISEMENT_PROTO 108 /* 802.11u */ +#define IE_QOS_MAP_SET 110 /* 802.11u */ +#define IE_ROAMING_CONSORTIUM 111 /* 802.11u */ +#define IE_EXT_CAPABILITY 127 /* 802.11n D3.03 */ +#define IE_LAST_BCN_REPORT_INDICATION_REQUEST 164 /*Last Beacon Report Indication Request*/ +#define IE_OPERATING_MODE_NOTIFY 199 + +#define IE_WPA 221 /* WPA */ +#define IE_VENDOR_SPECIFIC 221 /* Wifi WMM (WME) */ +#define IE_WFA_WSC 221 + +#if defined(DOT11R_FT_SUPPORT) || defined(DOT11K_RRM_SUPPORT) +#define IE_FT_MDIE 54 +#endif + +#define OUI_P2P 0x09 +#define OUI_HS2_INDICATION 0x10 +#define OUI_BROADCOM_HT 51 /* */ +#define OUI_BROADCOM_HTADD 52 /* */ +#define OUI_PREN_HT_CAP 51 /* */ +#define OUI_PREN_ADD_HT 52 /* */ + +/* CCX information */ +#define IE_AIRONET_CKIP 133 /* CCX1.0 ID 85H for CKIP */ +#define IE_AP_TX_POWER 150 /* CCX 2.0 for AP transmit power */ +#define IE_MEASUREMENT_CAPABILITY 221 /* CCX 2.0 */ +#define IE_CCX_V2 221 +#define IE_AIRONET_IPADDRESS 149 /* CCX ID 95H for IP Address */ +#define IE_AIRONET_CCKMREASSOC 156 /* CCX ID 9CH for CCKM Reassociation Request element */ +#define CKIP_NEGOTIATION_LENGTH 30 +#define AIRONET_IPADDRESS_LENGTH 10 +#define AIRONET_CCKMREASSOC_LENGTH 24 + +/* ======================================================== */ +/* MLME state machine definition */ +/* ======================================================== */ + +/* STA MLME state mahcines */ +#define ASSOC_STATE_MACHINE 1 +#define AUTH_STATE_MACHINE 2 +#define AUTH_RSP_STATE_MACHINE 3 +#define SYNC_STATE_MACHINE 4 +#define MLME_CNTL_STATE_MACHINE 5 +#define WPA_PSK_STATE_MACHINE 6 +/*#define LEAP_STATE_MACHINE 7 */ +#define AIRONET_STATE_MACHINE 8 +#define ACTION_STATE_MACHINE 9 + +/* AP MLME state machines */ +#define AP_ASSOC_STATE_MACHINE 11 +#define AP_AUTH_STATE_MACHINE 12 +#define AP_SYNC_STATE_MACHINE 14 +#define AP_CNTL_STATE_MACHINE 15 +#define WSC_STATE_MACHINE 17 +#define WSC_UPNP_STATE_MACHINE 18 + +#ifdef CONFIG_AP_SUPPORT +#ifdef APCLI_SUPPORT +#define APCLI_AUTH_STATE_MACHINE 19 +#define APCLI_ASSOC_STATE_MACHINE 20 +#define APCLI_SYNC_STATE_MACHINE 21 +#define APCLI_CTRL_STATE_MACHINE 22 +#endif /* APCLI_SUPPORT */ +#endif /* CONFIG_AP_SUPPORT */ + +#define WPA_STATE_MACHINE 23 + + + +#ifdef DOT11R_FT_SUPPORT +#define FT_OTA_AUTH_STATE_MACHINE 27 +#define FT_OTD_ACT_STATE_MACHINE 28 +#endif /* DOT11R_FT_SUPPORT */ + + + + +#ifdef DOT11V_WNM_SUPPORT +#define WNM_BSS_TM_STATE_MACHINE 37 +#endif /* DOT11V_WNM_SUPPORT */ + + + +#ifdef DOT11U_INTERWORKING +#define GAS_STATE_MACHINE 39 +#endif + +#ifdef CONFIG_DOT11V_WNM +#define BTM_STATE_MACHINE 40 +#define WNM_NOTIFY_STATE_MACHINE 41 +#endif + +#ifdef CONFIG_HOTSPOT +#define HSCTRL_STATE_MACHINE 42 +#endif + +#ifdef MIXMODE_SUPPORT +#define MIX_MODE_STATE_MACHINE 50//48 +#endif + +#ifdef WH_EZ_SETUP +#ifdef EZ_MOD_SUPPORT +#define EZ_STATE_MACHINE 98 +#else +//! Levarage from MP1.0 CL#170063 +#define EZ_ROAM_STATE_MACHINE 98 +#define AP_TRIBAND_STATE_MACHINE 99 +#endif +#endif + +#ifdef DOT11K_RRM_SUPPORT +#define NEIGHBOR_STATE_MACHINE 48 +#define BCN_STATE_MACHINE 49 +#endif + +#ifdef WIFI_DIAG +#define WIFI_DAIG_STATE_MACHINE 51 +#endif + +/* + STA's CONTROL/CONNECT state machine: states, events, total function # +*/ +#define CNTL_IDLE 0 +#define CNTL_WAIT_DISASSOC 1 +#define CNTL_WAIT_JOIN 2 +#define CNTL_WAIT_REASSOC 3 +#define CNTL_WAIT_START 4 +#define CNTL_WAIT_AUTH 5 +#define CNTL_WAIT_ASSOC 6 +#define CNTL_WAIT_AUTH2 7 +#define CNTL_WAIT_OID_LIST_SCAN 8 +#define CNTL_WAIT_OID_DISASSOC 9 +#define CNTL_WAIT_SCAN_FOR_CONNECT 10 + + +#define MT2_ASSOC_CONF 34 +#define MT2_AUTH_CONF 35 +#define MT2_DEAUTH_CONF 36 +#define MT2_DISASSOC_CONF 37 +#define MT2_REASSOC_CONF 38 +#define MT2_PWR_MGMT_CONF 39 +#define MT2_JOIN_CONF 40 +#define MT2_SCAN_CONF 41 +#define MT2_START_CONF 42 +#define MT2_GET_CONF 43 +#define MT2_SET_CONF 44 +#define MT2_RESET_CONF 45 +#define MT2_FT_OTD_CONF 46 +#define MT2_MLME_ROAMING_REQ 52 + +#define CNTL_FUNC_SIZE 1 + +/* + STA's ASSOC state machine: states, events, total function # +*/ +#define ASSOC_IDLE 0 +#define ASSOC_WAIT_RSP 1 +#define REASSOC_WAIT_RSP 2 +#define DISASSOC_WAIT_RSP 3 +#define MAX_ASSOC_STATE 4 + +#define ASSOC_MACHINE_BASE 0 +#define MT2_MLME_ASSOC_REQ 0 +#define MT2_MLME_REASSOC_REQ 1 +#define MT2_MLME_DISASSOC_REQ 2 +#define MT2_PEER_DISASSOC_REQ 3 +#define MT2_PEER_ASSOC_REQ 4 +#define MT2_PEER_ASSOC_RSP 5 +#define MT2_PEER_REASSOC_REQ 6 +#define MT2_PEER_REASSOC_RSP 7 +#define MT2_DISASSOC_TIMEOUT 8 +#define MT2_ASSOC_TIMEOUT 9 +#define MT2_REASSOC_TIMEOUT 10 +#define MAX_ASSOC_MSG 11 + +#define ASSOC_FUNC_SIZE (MAX_ASSOC_STATE * MAX_ASSOC_MSG) + +/* + ACT state machine: states, events, total function # +*/ +#define ACT_IDLE 0 +#define MAX_ACT_STATE 1 + +#define ACT_MACHINE_BASE 0 + +/* + Those PEER_xx_CATE number is based on real Categary value in IEEE spec. + Please doesn't modify it by yourself. + */ +/*Category */ +#define MT2_PEER_SPECTRUM_CATE 0 +#define MT2_PEER_QOS_CATE 1 +#define MT2_PEER_DLS_CATE 2 +#define MT2_PEER_BA_CATE 3 +#define MT2_PEER_PUBLIC_CATE 4 +#define MT2_PEER_RM_CATE 5 +/* "FT_CATEGORY_BSS_TRANSITION equal to 6" is defined file of "dot11r_ft.h" */ +#define MT2_PEER_HT_CATE 7 /* 7.4.7 */ +#define MT2_PEER_PMF_CATE 8 /* defined in IEEE 802.11w-D8.0 7.3.1.11 */ +#define MT2_PEER_RESV_9 9 +#define MT2_PEER_RESV_10 10 +#define MT2_PEER_RESV_11 11 +#define MT2_PEER_RESV_12 12 +#define MT2_PEER_RESV_13 13 +#define MT2_PEER_RESV_14 14 +#define MT2_PEER_RESV_15 15 +#define MT2_PEER_RESV_16 16 +/* + In WMM spec v1.1. the category must be 17 + (see Table 7 Management Action Frame Fields) +*/ +#define MT2_PEER_WMM 17 +#define WNM_CATEGORY_BSS_TRANSITION 18 +#define MT2_PEER_RESV_19 19 +#define MT2_PEER_RESV_20 20 +#define MT2_PEER_VHT_CATE 21 +#define MAX_IEEE_STD_CATE 21 /* Indicate the maximum category code defined in IEEE-802.11-Std */ +#define MAX_PEER_CATE_MSG MAX_IEEE_STD_CATE + +#define MT2_MLME_ADD_BA_CATE (MAX_IEEE_STD_CATE + 1) +#define MT2_MLME_ORI_DELBA_CATE (MAX_IEEE_STD_CATE + 2) +#define MT2_MLME_REC_DELBA_CATE (MAX_IEEE_STD_CATE + 3) +#define MT2_MLME_QOS_CATE (MAX_IEEE_STD_CATE + 4) +#define MT2_MLME_DLS_CATE (MAX_IEEE_STD_CATE + 5) +#define MT2_ACT_INVALID (MAX_IEEE_STD_CATE + 6) + +#define MAX_ACT_MSG (MAX_IEEE_STD_CATE + 7) + +#ifdef DOT11V_WNM_SUPPORT +#define WNM_CATEGORY_BSS_TRANSITION 18 +#undef MAX_ACT_MSG +#define MAX_ACT_MSG (MAX_IEEE_STD_CATE + 8) +#undef MAX_PEER_CATE_MSG +#define MAX_PEER_CATE_MSG (MAX_IEEE_STD_CATE + 8) +#endif /* DOT11V_WNM_SUPPORT */ + +#define MT2_ACT_VENDOR 0x7F + +/* Category field */ +#define CATEGORY_SPECTRUM 0 +#define CATEGORY_QOS 1 +#define CATEGORY_DLS 2 +#define CATEGORY_BA 3 +#define CATEGORY_PUBLIC 4 +#define CATEGORY_RM 5 +#define CATEGORY_FT 6 +#define CATEGORY_HT 7 +#ifdef DOT11W_PMF_SUPPORT +#define CATEGORY_SA 8 /* defined in IEEE 802.11w-D8.0 7.3.1.11*/ +#define CATEGORY_PD 9 /* Protected Dual of Action defined in IEEE 802.11w */ +#define CATEGORY_WNM 10 +#define CATEGORY_VSP 126 /* Vendor-specific Protected defined in IEEE 802.11w */ +#endif // DOT11W_PMF_SUPPORT // +//#ifdef WFD_SUPPORT +#define CATEGORY_VENDOR_SPECIFIC_WFD 127 //CFG_TODO CATEGORY_VENDOR, WHY ONLY WFD ? +//#endif /* WFD_SUPPORT */ + + +#ifdef DOT11_VHT_AC +#define CATEGORY_VHT 21 + +#define ACT_VHT_COMPRESS_BF 0 /* VHT Compressed Beamforming */ +#define ACT_VHT_GRP_ID_MGMT 1 /* Group ID Management */ +#define ACT_VHT_OPMODE_NOTIFY 2 /* Operating Mode Notification */ +#endif /* DOT11_VHT_AC */ + +#ifdef DOT11W_PMF_SUPPORT +/* SA Query Action frame definition */ +#define ACTION_SAQ_REQUEST 0 +#define ACTION_SAQ_RESPONSE 1 +#endif // DOT11W_PMF_SUPPORT // + +/* DLS Action frame definition */ +#define ACTION_DLS_REQUEST 0 +#define ACTION_DLS_RESPONSE 1 +#define ACTION_DLS_TEARDOWN 2 + +/* Spectrum Action field value 802.11h 7.4.1 */ +#define SPEC_MRQ 0 /* Request */ +#define SPEC_MRP 1 /*Report */ +#define SPEC_TPCRQ 2 +#define SPEC_TPCRP 3 +#define SPEC_CHANNEL_SWITCH 4 + +/* BA Action field value */ +#define ADDBA_REQ 0 +#define ADDBA_RESP 1 +#define DELBA 2 + +/* Public's Action field value in Public Category. Some in 802.11y and some in 11n */ +#define ACTION_BSS_2040_COEXIST 0 /* 11n */ +#define ACTION_DSE_ENABLEMENT 1 /* 11y D9.0 */ +#define ACTION_DSE_DEENABLEMENT 2 /* 11y D9.0 */ +#define ACTION_DSE_REG_LOCATION_ANNOUNCE 3 /* 11y D9.0 */ +#define ACTION_EXT_CH_SWITCH_ANNOUNCE 4 /* 11y D9.0 */ +#define ACTION_DSE_MEASUREMENT_REQ 5 /* 11y D9.0 */ +#define ACTION_DSE_MEASUREMENT_REPORT 6 /* 11y D9.0 */ +#define ACTION_MEASUREMENT_PILOT_ACTION 7 /* 11y D9.0 */ +#define ACTION_DSE_POWER_CONSTRAINT 8 /* 11y D9.0 */ +#define ACTION_WIFI_DIRECT 9 /* 11y */ +#define ACTION_GAS_INITIAL_REQ 10 /* 11U */ +#define ACTION_GAS_INITIAL_RSP 11 /* 11U */ +#define ACTION_GAS_COMEBACK_REQ 12 /* 11U */ +#define ACTION_GAS_COMEBACK_RSP 13 /* 11U */ +#define ACTION_TDLS_DISCOVERY_RSP 14 /* 11z D13.0 */ +#define ACTION_VENDOR_USAGE 221 + +/*HT Action field value */ +#define NOTIFY_BW_ACTION 0 +#define SMPS_ACTION 1 +#define PSMP_ACTION 2 +#define SETPCO_ACTION 3 +#define MIMO_CHA_MEASURE_ACTION 4 +#define MIMO_N_BEACONFORM 5 /* non-compressed beamforming report */ +#define MIMO_BEACONFORM 6 /* compressed beamforming report */ +#define ANTENNA_SELECT 7 + +/* VHT Action field value */ +#define ACT_VHT_COMP_BFING 0 /* VHT Compressed Beamforming */ +#define ACT_VHT_GRP_ID_MGMT 1 /* Group ID Management */ +#define ACT_VHT_OPMODE_NOTIFY 2 /* Operating Mode Notification */ + + +#define ACT_FUNC_SIZE (MAX_ACT_STATE * MAX_ACT_MSG) +/* + STA's AUTHENTICATION state machine: states, evvents, total function # +*/ +#define AUTH_REQ_IDLE 0 +#define AUTH_WAIT_SEQ2 1 +#define AUTH_WAIT_SEQ4 2 +#define MAX_AUTH_STATE 3 + +#define AUTH_MACHINE_BASE 0 +#define MT2_MLME_AUTH_REQ 0 +#define MT2_PEER_AUTH_EVEN 1 +#define MT2_AUTH_TIMEOUT 2 +#define MAX_AUTH_MSG 3 + +#define AUTH_FUNC_SIZE (MAX_AUTH_STATE * MAX_AUTH_MSG) + +/* + STA's AUTH_RSP state machine: states, events, total function # +*/ +#define AUTH_RSP_IDLE 0 +#define AUTH_RSP_WAIT_CHAL 1 +#define MAX_AUTH_RSP_STATE 2 + +#define AUTH_RSP_MACHINE_BASE 0 +#define MT2_AUTH_CHALLENGE_TIMEOUT 0 +#define MT2_PEER_AUTH_ODD 1 +#define MT2_PEER_DEAUTH 2 +#define MAX_AUTH_RSP_MSG 3 + +#define AUTH_RSP_FUNC_SIZE (MAX_AUTH_RSP_STATE * MAX_AUTH_RSP_MSG) + +/* + STA's SYNC state machine: states, events, total function # +*/ +#define SYNC_IDLE 0 /* merge NO_BSS,IBSS_IDLE,IBSS_ACTIVE and BSS in to 1 state */ +#ifdef WH_EZ_SETUP + +#ifdef EZ_MOD_SUPPORT + +#define EZ_IDLE 0 +#define EZ_MAX_STATE 1 +#define EZ_MAX_MSG 4 +#define EZ_MACHINE_BASE 0 + +#define EZ_ROAM_REQ 0 +#define EZ_TRIBAND_RESTART_NON_EZ_REQ 1 +#define EZ_PERIODIC_EXEC_REQ 2 +#define EZ_UPDATE_SSID_PSK_REQ 3 + +#define EZ_FUNC_SIZE (EZ_MAX_STATE * EZ_MAX_MSG) + +#else +//! Levarage from MP1.0 CL#170063 +#define EZ_ROAM_IDLE 0 +#define EZ_ROAM_MAX_STATE 1 +#define EZ_ROAM_MAX_MSG 1 +#define EZ_ROAM_MACHINE_BASE 0 + +#define EZ_ROAM_REQ 0 +#define EZ_ROAM_FUNC_SIZE (EZ_ROAM_MAX_STATE * EZ_ROAM_MAX_MSG) + + +#define AP_TRIBAND_IDLE 0 +#define AP_MAX_TRIBAND_STATE 1 +#define AP_MAX_TRIBAND_MSG 2 +#define AP_TRIBAND_MACHINE_BASE 0 + +#define AP_TRIBAND_UPDATE_CHANNEL_REQ 0 +#define AP_TRIBAND_RESTART_NON_EZ_REQ 1 +#define AP_TRIBAND_FUNC_SIZE (AP_MAX_TRIBAND_STATE * AP_MAX_TRIBAND_MSG) +#endif +#endif + +#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) + + +/* + 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) + +#endif /* WSC_INCLUDED */ + +/* + AP's CONTROL/CONNECT state machine: states, events, total function # +*/ +#define AP_CNTL_FUNC_SIZE 1 + +/* + AP's ASSOC state machine: states, events, total function # +*/ +#define AP_ASSOC_IDLE 0 +#define AP_MAX_ASSOC_STATE 1 + +#define AP_ASSOC_MACHINE_BASE 0 +#define APMT2_MLME_DISASSOC_REQ 0 +#define APMT2_PEER_DISASSOC_REQ 1 +#define APMT2_PEER_ASSOC_REQ 2 +#define APMT2_PEER_REASSOC_REQ 3 +#define APMT2_CLS3ERR 4 +#define AP_MAX_ASSOC_MSG 5 + +#define AP_ASSOC_FUNC_SIZE (AP_MAX_ASSOC_STATE * AP_MAX_ASSOC_MSG) + +/* + AP's AUTHENTICATION state machine: states, events, total function # +*/ +#define AP_AUTH_REQ_IDLE 0 +#define AP_MAX_AUTH_STATE 1 + +#define AP_AUTH_MACHINE_BASE 0 +#define APMT2_MLME_DEAUTH_REQ 0 +#define APMT2_CLS2ERR 1 +#define APMT2_PEER_DEAUTH 2 +#define APMT2_PEER_AUTH_REQ 3 +#define APMT2_PEER_AUTH_CONFIRM 4 +#define AP_MAX_AUTH_MSG 5 + +#define AP_AUTH_FUNC_SIZE (AP_MAX_AUTH_STATE * AP_MAX_AUTH_MSG) + +/* + AP's SYNC state machine: states, events, total function # +*/ +#define AP_SYNC_IDLE 0 +#ifdef AP_SCAN_SUPPORT +#define AP_SCAN_LISTEN 1 +#define AP_MAX_SYNC_STATE 2 +#else +#define AP_MAX_SYNC_STATE 1 +#endif + +#define AP_SYNC_MACHINE_BASE 0 +#define APMT2_PEER_PROBE_REQ 0 +#define APMT2_PEER_BEACON 1 +#define APMT2_PEER_PROBE_RSP 2 +#ifdef AP_SCAN_SUPPORT +#define APMT2_MLME_SCAN_REQ 3 +#define APMT2_SCAN_TIMEOUT 4 +#define APMT2_MLME_SCAN_CNCL 5 +#define AP_MAX_SYNC_MSG 6 +#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 +#ifdef APCLI_SAE_SUPPORT +#define APCLI_AUTH_WAIT_SAE 3 +#define APCLI_MAX_AUTH_STATE 4 +#else +#define APCLI_MAX_AUTH_STATE 3 +#endif + +#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 +#ifdef APCLI_SAE_SUPPORT +#define APCLI_MT2_MLME_SAE_AUTH_REQ 5 +#define APCLI_MT2_MLME_SAE_AUTH_COMMIT 6 +#define APCLI_MT2_MLME_SAE_AUTH_CONFIRM 7 +#define APCLI_MAX_AUTH_MSG 8 +#else +#define APCLI_MAX_AUTH_MSG 5 +#endif + +#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_DEL_MACREPENTRY 12 +//#define APCLI_MAX_CTRL_MSG 12 +#ifndef APCLI_CONNECTION_TRIAL +#define APCLI_MAX_CTRL_MSG 13 +#ifdef WH_EZ_SETUP +#undef APCLI_MAX_CTRL_MSG +#define APCLI_CTRL_JOIN_FAIL 14 +#define APCLI_MAX_CTRL_MSG 15 +#endif /* WH_EZ_SETUP */ +#else +#undef APCLI_MAX_CTRL_MSG +#define APCLI_CTRL_TRIAL_CONNECT 14 +#define APCLI_CTRL_TRIAL_CONNECT_TIMEOUT 15 +#define APCLI_CTRL_TRIAL_PHASE2_TIMEOUT 16 +#define APCLI_CTRL_TRIAL_RETRY_TIMEOUT 17 +#define APCLI_MAX_CTRL_MSG 18 +#endif /* APCLI_CONNECTION_TRIAL */ + +#define APCLI_CTRL_FUNC_SIZE (APCLI_MAX_CTRL_STATE * APCLI_MAX_CTRL_MSG) + +#ifdef WH_EZ_SETUP +#ifdef NEW_CONNECTION_ALGO +#define APCLI_DISCONNECT_SUB_REASON_APCLI_EZ_CONNECTION_LOOP 11 +#endif +#endif + + +#endif /* APCLI_SUPPORT */ + + +/* ============================================================================= */ + + +/* ACK policy of QOS Control field bit 6:5 */ +#define NORMAL_ACK 0x00 /* b6:5 = 00 */ +#define NO_ACK 0x20 /* b6:5 = 01 */ +#define NO_EXPLICIT_ACK 0x40 /* b6:5 = 10 */ +#define BLOCK_ACK 0x60 /* b6:5 = 11 */ + +#ifdef USB_BULK_BUF_ALIGMENT +#ifndef BUF_ALIGMENT_RINGSIZE +#undef BUF_ALIGMENT_RINGSIZE +#define BUF_ALIGMENT_RINGSIZE 6 /*BUF_ALIGMENT_RINGSIZE must >= 3 */ +#endif +#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_VHT_AC +#define MCS_VHT_2SS_MCS9 0x29 +#define MCS_VHT_2SS_MCS8 0x28 +#define MCS_VHT_2SS_MCS7 0x27 +#define MCS_VHT_2SS_MCS6 0x26 +#define MCS_VHT_2SS_MCS5 0x25 +#define MCS_VHT_2SS_MCS4 0x24 +#define MCS_VHT_2SS_MCS3 0x23 +#define MCS_VHT_2SS_MCS2 0x22 +#define MCS_VHT_2SS_MCS1 0x21 +#define MCS_VHT_2SS_MCS0 0x20 + +#define MCS_VHT_1SS_MCS9 0x19 +#define MCS_VHT_1SS_MCS8 0x18 +#define MCS_VHT_1SS_MCS7 0x17 +#define MCS_VHT_1SS_MCS6 0x16 +#define MCS_VHT_1SS_MCS5 0x15 +#define MCS_VHT_1SS_MCS4 0x14 +#define MCS_VHT_1SS_MCS3 0x13 +#define MCS_VHT_1SS_MCS2 0x12 +#define MCS_VHT_1SS_MCS1 0x11 +#define MCS_VHT_1SS_MCS0 0x10 + +#define VHT_RATE_IDX_1SS_MCS0 0 +#define VHT_RATE_IDX_1SS_MCS1 1 +#define VHT_RATE_IDX_1SS_MCS2 2 +#define VHT_RATE_IDX_1SS_MCS3 3 +#define VHT_RATE_IDX_1SS_MCS4 4 +#define VHT_RATE_IDX_1SS_MCS5 5 +#define VHT_RATE_IDX_1SS_MCS6 6 +#define VHT_RATE_IDX_1SS_MCS7 7 +#define VHT_RATE_IDX_1SS_MCS8 8 +#define VHT_RATE_IDX_1SS_MCS9 9 + +#define VHT_RATE_IDX_2SS_MCS0 10 +#define VHT_RATE_IDX_2SS_MCS1 11 +#define VHT_RATE_IDX_2SS_MCS2 12 +#define VHT_RATE_IDX_2SS_MCS3 13 +#define VHT_RATE_IDX_2SS_MCS4 14 +#define VHT_RATE_IDX_2SS_MCS5 15 +#define VHT_RATE_IDX_2SS_MCS6 16 +#define VHT_RATE_IDX_2SS_MCS7 17 +#define VHT_RATE_IDX_2SS_MCS8 18 +#define VHT_RATE_IDX_2SS_MCS9 19 +#endif /* DOT11_VHT_AC */ + +#ifdef DOT11_N_SUPPORT +/* OID_HTPHYMODE */ +/* MODE */ +#define HTMODE_MM 0 +#define HTMODE_GF 1 +#endif /* DOT11_N_SUPPORT */ + +/* Fixed Tx MODE - HT, CCK or OFDM */ +#define FIXED_TXMODE_HT 0 +#define FIXED_TXMODE_CCK 1 +#define FIXED_TXMODE_OFDM 2 +#define FIXED_TXMODE_VHT 3 + +/* BW */ +#define BW_20 BAND_WIDTH_20 +#define BW_40 BAND_WIDTH_40 +#define BW_80 BAND_WIDTH_80 +#define BW_160 BAND_WIDTH_160 +#define BW_10 BAND_WIDTH_10 /* 802.11j has 10MHz. This definition is for internal usage. doesn't fill in the IE or other field. */ +#define BW_5 BAND_WIDTH_5 +#define BW_8080 BAND_WIDTH_8080 +#define BW_25 BAND_WIDTH_25 +#define BW_NUM BAND_WIDTH_NUM + +#define RF_BW_20 1 +#define RF_BW_40 2 +#define RF_BW_10 4 +#define RF_BW_80 8 + +#define RF_MODE_CCK 1 +#define RF_MODE_OFDM 2 + +#ifdef DOT11_N_SUPPORT +#define HT_BW_20 0 +#define HT_BW_40 1 +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11_VHT_AC +#define VHT_BW_2040 0 +#define VHT_BW_80 1 +#define VHT_BW_160 2 +#define VHT_BW_8080 3 +#endif /* DOT11_VHT_AC */ + +#ifdef DOT11_N_SUPPORT +/* SHORTGI */ +#define GI_400 GAP_INTERVAL_400 /* only support in HT mode */ +#define GI_BOTH GAP_INTERVAL_BOTH +#endif /* DOT11_N_SUPPORT */ +#define GI_800 GAP_INTERVAL_800 + +/* STBC */ +#define STBC_NONE 0 +#ifdef DOT11_N_SUPPORT +#define STBC_USE 1 /* limited use in rt2860b phy */ +#define RXSTBC_ONE 1 /* rx support of one spatial stream */ +#define RXSTBC_TWO 2 /* rx support of 1 and 2 spatial stream */ +#define RXSTBC_THR 3 /* rx support of 1~3 spatial stream */ +/* MCS FEEDBACK */ +#define MCSFBK_NONE 0 /* not support mcs feedback / */ +#define MCSFBK_RSV 1 /* reserved */ +#define MCSFBK_UNSOLICIT 2 /* only support unsolict mcs feedback */ +#define MCSFBK_MRQ 3 /* response to both MRQ and unsolict mcs feedback */ + +/* MIMO power safe */ +#define MMPS_STATIC 0 +#define MMPS_DYNAMIC 1 +#define MMPS_RSV 2 +#define MMPS_DISABLE 3 + +/* A-MSDU size */ +#define AMSDU_0 0 +#define AMSDU_1 1 + +#endif /* DOT11_N_SUPPORT */ + +/* MCS use 7 bits */ +#define TXRATEMIMO 0x80 +#define TXRATEMCS 0x7F +#define TXRATEOFDM 0x7F +#define RATE_1 0 +#define RATE_2 1 +#define RATE_5_5 2 +#define RATE_11 3 +#define RATE_6 4 /* OFDM */ +#define RATE_9 5 /* OFDM */ +#define RATE_12 6 /* OFDM */ +#define RATE_18 7 /* OFDM */ +#define RATE_24 8 /* OFDM */ +#define RATE_36 9 /* OFDM */ +#define RATE_48 10 /* OFDM */ +#define RATE_54 11 /* OFDM */ +#define RATE_FIRST_OFDM_RATE RATE_6 +#define RATE_LAST_OFDM_RATE RATE_54 +#define RATE_6_5 12 /* HT mix */ +#define RATE_13 13 /* HT mix */ +#define RATE_19_5 14 /* HT mix */ +#define RATE_26 15 /* HT mix */ +#define RATE_39 16 /* HT mix */ +#define RATE_52 17 /* HT mix */ +#define RATE_58_5 18 /* HT mix */ +#define RATE_65 19 /* HT mix */ +#define RATE_78 20 /* HT mix */ +#define RATE_104 21 /* HT mix */ +#define RATE_117 22 /* HT mix */ +#define RATE_130 23 /* HT mix */ +/*#define RATE_AUTO_SWITCH 255 // for StaCfg.FixedTxRate only */ +#define HTRATE_0 12 +#define RATE_FIRST_MM_RATE HTRATE_0 +#define RATE_FIRST_HT_RATE HTRATE_0 +#define RATE_LAST_HT_RATE HTRATE_0 + +/* pTxWI->txop */ +#define IFS_HTTXOP 0 /* The txop will be handles by ASIC. */ +#define IFS_PIFS 1 +#define IFS_SIFS 2 +#define IFS_BACKOFF 3 + +/* pTxD->RetryMode */ +#define LONG_RETRY 1 +#define SHORT_RETRY 0 + +/* Country Region definition */ +#define REGION_MINIMUM_BG_BAND 0 +#define REGION_0_BG_BAND 0 /* 1-11 */ +#define REGION_1_BG_BAND 1 /* 1-13 */ +#define REGION_2_BG_BAND 2 /* 10-11 */ +#define REGION_3_BG_BAND 3 /* 10-13 */ +#define REGION_4_BG_BAND 4 /* 14 */ +#define REGION_5_BG_BAND 5 /* 1-14 */ +#define REGION_6_BG_BAND 6 /* 3-9 */ +#define REGION_7_BG_BAND 7 /* 5-13 */ +#define REGION_31_BG_BAND 31 /* 5-13 */ +#define REGION_32_BG_BAND 32 /* 1 - 13 */ +#define REGION_33_BG_BAND 33 /* 1 - 14 */ +#define REGION_MAXIMUM_BG_BAND 7 + +#define REGION_MINIMUM_A_BAND 0 +#define REGION_0_A_BAND 0 /* 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165 */ +#define REGION_1_A_BAND 1 /* 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 */ +#define REGION_2_A_BAND 2 /* 36, 40, 44, 48, 52, 56, 60, 64 */ +#define REGION_3_A_BAND 3 /* 52, 56, 60, 64, 149, 153, 157, 161 */ +#define REGION_4_A_BAND 4 /* 149, 153, 157, 161, 165 */ +#define REGION_5_A_BAND 5 /* 149, 153, 157, 161 */ +#define REGION_6_A_BAND 6 /* 36, 40, 44, 48 */ +#define REGION_7_A_BAND 7 /* 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165, 169, 173 */ +#define REGION_8_A_BAND 8 /* 52, 56, 60, 64 */ +#define REGION_9_A_BAND 9 /* 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165 */ +#define REGION_10_A_BAND 10 /* 36, 40, 44, 48, 149, 153, 157, 161, 165 */ +#define REGION_11_A_BAND 11 /* 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 149, 153, 157, 161 */ +#define REGION_12_A_BAND 12 /* 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 */ +#define REGION_13_A_BAND 13 /* 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161 */ +#define REGION_14_A_BAND 14 /* 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165 */ +#define REGION_15_A_BAND 15 /* 149, 153, 157, 161, 165, 169, 173 */ +#define REGION_16_A_BAND 16 /* 52, 56, 60, 64, 149, 153, 157, 161, 165 */ +#define REGION_17_A_BAND 17 +#define REGION_18_A_BAND 18 +#define REGION_19_A_BAND 19 +#define REGION_20_A_BAND 20 +#define REGION_21_A_BAND 21 +#define REGION_22_A_BAND 22 +#define REGION_MAXIMUM_A_BAND 37 + +/* The security mode definition in MAC register */ +#define CIPHER_NONE 0 +#define CIPHER_WEP64 1 +#define CIPHER_WEP128 2 +#define CIPHER_TKIP 3 +#define CIPHER_AES 4 +#define CIPHER_CKIP64 5 +#define CIPHER_CKIP128 6 +#define CIPHER_CKIP152 7 +#define CIPHER_SMS4 8 +#define CIPHER_WEP152 9 +#define CIPHER_BIP 10 + + +/* 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 */ + +#define SWIFT_TRAIN_UP_RECORD 8 + +/* 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 +#define TYPE_TMACINFO 0 +#define TYPE_RMACINFO 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_IDX_0 0 +#define RSSI_IDX_1 1 +#define RSSI_IDX_2 2 + +/* definition of radar detection */ +#define RD_NORMAL_MODE 0 /* Not found radar signal */ +#define RD_SWITCHING_MODE 1 /* Found radar signal, and doing channel switch */ +#define RD_SILENCE_MODE 2 /* After channel switch, need to be silence a while to ensure radar not found */ + +/*Driver defined cid for mapping status and command. */ +#define SLEEPCID 0x11 +#define WAKECID 0x22 +#define QUERYPOWERCID 0x33 +#define OWNERMCU 0x1 +#define OWNERCPU 0x0 + +/* MBSSID definition */ +#define ENTRY_NOT_FOUND 0xFF + +/* The signal threshold (RSSI) over new rate adaption */ +#define SIGNAL_THRESHOLD_OVER_NEW_RATE_ADAPT -65 + +/* After Linux 2.6.9, + * VLAN module use Private (from user) interface flags (netdevice->priv_flags). + * #define IFF_802_1Q_VLAN 0x1 -- 802.1Q VLAN device. in if.h + * ref to ip_sabotage_out() [ out->priv_flags & IFF_802_1Q_VLAN ] in br_netfilter.c + * + * For this reason, we MUST use EVEN value in priv_flags + */ +#define INT_MAIN 0x0100 +#define INT_MBSSID 0x0200 +#define INT_WDS 0x0300 +#define INT_APCLI 0x0400 +#define INT_MESH 0x0500 +#define INT_P2P 0x0600 +#define INT_MONITOR 0x0700 +#define MAX_INT_TYPES 7 + +// TODO: Shiang-usw, need to revise this, consider both wdev->wdev_type and pEntry->EntryType!! + + +/* + Connected peers can be seperate as following two sub groups: + Category + Type(Properties) + 1. Category: + NONE - Invalid Category to indicate/un-used entry + STA - entry which use 802.11 Auth/Assoc method to connect to us + AP - entry which provide 802.11 BSS feature and work as a AP mode + WDS - entry which are 4-address repeater mode + MESH - entry which are 4-address and follow 802.11s + + MCAST - entry which used internally for binding MCAT/BCAST info for a + specifi wifi_dev instance which work as a AP mode + WDEV - entry which are used internally for binding to a specific + wifi_dev instance + + 2. Type + +*/ +#define ENTRY_CAT_NONE 0x000 +#define ENTRY_CAT_STA 0x001 +#define ENTRY_CAT_AP 0x002 +#define ENTRY_CAT_WDS 0x004 +#define ENTRY_CAT_MESH 0x008 +#ifdef AIR_MONITOR + +#define ENTRY_CAT_MONITOR 0x010 +#endif +#define ENTRY_CAT_MCAST 0x400 +#define ENTRY_CAT_WDEV 0x800 +#define ENTRY_CAT_MASK 0xfff + +typedef struct _WIFI_NODE_TYPE { + UINT32 rsv:26; + UINT32 type: 3; + UINT32 cat:3; +}WIFI_NODE_TYPE; + + + +#define ENTRY_AP ENTRY_CAT_AP +#define ENTRY_GO (ENTRY_CAT_AP | 0x01000) + + +#define ENTRY_INFRA ENTRY_CAT_STA +#define ENTRY_GC (ENTRY_CAT_STA | 0x01000) +#define ENTRY_ADHOC (ENTRY_CAT_STA | 0x02000) +#define ENTRY_APCLI (ENTRY_CAT_STA | 0x04000) +#define ENTRY_DLS (ENTRY_CAT_STA | 0x08000) +#define ENTRY_TDLS (ENTRY_CAT_STA | 0x10000) +#define ENTRY_CLIENT (ENTRY_CAT_STA | 0x20000) + +#define ENTRY_WDS ENTRY_CAT_WDS +#define ENTRY_MESH ENTRY_CAT_MESH +#ifdef AIR_MONITOR +#define ENTRY_MONITOR ENTRY_CAT_MONITOR +#endif +#define ENTRY_NONE ENTRY_CAT_NONE + + +#define IS_ENTRY_NONE(_x) ((_x)->EntryType == ENTRY_CAT_NONE) +#define IS_ENTRY_CLIENT(_x) ((_x)->EntryType == ENTRY_CLIENT) +#define IS_ENTRY_WDS(_x) ((_x)->EntryType & ENTRY_CAT_WDS) +#ifdef AIR_MONITOR +#define IS_ENTRY_MONITOR(_x) ((_x)->EntryType == ENTRY_CAT_MONITOR) +#endif /* AIR_MONITOR */ +#define IS_ENTRY_APCLI(_x) ((_x)->EntryType == ENTRY_APCLI) +#define IS_ENTRY_ADHOC(_x) ((_x)->EntryType & ENTRY_ADHOC) +#define IS_ENTRY_AP(_x) ((_x)->EntryType & ENTRY_CAT_AP) +#define IS_ENTRY_MESH(_x) ((_x)->EntryType & ENTRY_CAT_MESH) +#define IS_ENTRY_DLS(_x) ((_x)->EntryType == ENTRY_DLS) +#define IS_ENTRY_TDLS(_x) ((_x)->EntryType == ENTRY_TDLS) +#ifdef CLIENT_WDS +#define IS_ENTRY_CLIWDS(_x) CLIENT_STATUS_TEST_FLAG((_x), fCLIENT_STATUS_CLI_WDS) +#endif /* CLIENT_WDS */ + +#define IS_VALID_ENTRY(_x) (((_x) != NULL) && ((_x)->EntryType != ENTRY_NONE)) + +#define SET_ENTRY_NONE(_x) ((_x)->EntryType = ENTRY_NONE) +#define SET_ENTRY_CLIENT(_x) ((_x)->EntryType = ENTRY_CLIENT) +#define SET_ENTRY_WDS(_x) ((_x)->EntryType = ENTRY_WDS) +#define SET_ENTRY_APCLI(_x) ((_x)->EntryType = ENTRY_APCLI) +#define SET_ENTRY_AP(_x) ((_x)->EntryType = ENTRY_AP) +#ifdef AIR_MONITOR +#define SET_ENTRY_MONITOR(_x) ((_x)->EntryType = ENTRY_MONITOR) +#endif /* AIR_MONITOR */ +#define SET_ENTRY_ADHOC(_x) ((_x)->EntryType = ENTRY_ADHOC) +#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 */ +//CFG_TODO +#define SET_PKT_OPMODE_AP(_x) ((_x)->OpMode = OPMODE_AP) +#define SET_PKT_OPMODE_STA(_x) ((_x)->OpMode = OPMODE_STA) +#define IS_PKT_OPMODE_AP(_x) ((_x)->OpMode == OPMODE_AP) +#define IS_PKT_OPMODE_STA(_x) ((_x)->OpMode == OPMODE_STA) + + +#define IS_OPMODE_AP(_x) ((_x)->OpMode == OPMODE_AP) +#define IS_OPMODE_STA(_x) ((_x)->OpMode == OPMODE_STA) + +#if defined(ANDROID_SUPPORT) || defined(RT_CFG80211_SUPPORT) +#if CONFIG_RTPCI_AP_RF_OFFSET == 0x48000 +#define INF_MAIN_DEV_NAME "wlani" +#define INF_MBSSID_DEV_NAME "wlani" +#else +#ifdef HE_BD_CFG80211_SUPPORT +#define INF_MAIN_DEV_NAME "ra" +#define INF_MBSSID_DEV_NAME "ra" +#else +#define INF_MAIN_DEV_NAME "wlan" +#define INF_MBSSID_DEV_NAME "wlan" +#endif /* HE_BD_CFG80211_SUPPORT */ + +#endif + +#else // !ANDROID_SUPPORT || RT_CFG80211_SUPPORT +#if CONFIG_RTPCI_AP_RF_OFFSET == 0x48000 +#define INF_MAIN_DEV_NAME "rai" +#define INF_MBSSID_DEV_NAME "rai" +#else +#define INF_MAIN_DEV_NAME "ra" +#define INF_MBSSID_DEV_NAME "ra" +#endif +#endif /* ANDROID_SUPPORT */ + + +#if CONFIG_RTPCI_AP_RF_OFFSET == 0x48000 +#define INF_WDS_DEV_NAME "wdsi" +#define INF_APCLI_DEV_NAME "apclii" +#define INF_MESH_DEV_NAME "meshi" +#define INF_P2P_DEV_NAME "p2pi" +#define INF_MONITOR_DEV_NAME "moni" +#else +#define INF_WDS_DEV_NAME "wds" +#define INF_APCLI_DEV_NAME "apcli" +#define INF_MESH_DEV_NAME "mesh" +#define INF_P2P_DEV_NAME "p2p" +#define INF_MONITOR_DEV_NAME "mon" +#endif + +/* WEP Key TYPE */ +#define WEP_HEXADECIMAL_TYPE 0 +#define WEP_ASCII_TYPE 1 + +/* WIRELESS EVENTS definition */ +/* Max number of char in custom event, refer to wireless_tools.28/wireless.20.h */ +#define IW_CUSTOM_MAX_LEN 255 /* In bytes */ + +/* For system event - start */ +#define IW_SYS_EVENT_FLAG_START 0x0200 +#define IW_ASSOC_EVENT_FLAG 0x0200 +#define IW_DISASSOC_EVENT_FLAG 0x0201 +#define IW_DEAUTH_EVENT_FLAG 0x0202 +#define IW_AGEOUT_EVENT_FLAG 0x0203 +#define IW_COUNTER_MEASURES_EVENT_FLAG 0x0204 +#define IW_REPLAY_COUNTER_DIFF_EVENT_FLAG 0x0205 +#define IW_RSNIE_DIFF_EVENT_FLAG 0x0206 +#define IW_MIC_DIFF_EVENT_FLAG 0x0207 +#define IW_ICV_ERROR_EVENT_FLAG 0x0208 +#define IW_MIC_ERROR_EVENT_FLAG 0x0209 +#define IW_GROUP_HS_TIMEOUT_EVENT_FLAG 0x020A +#define IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG 0x020B +#define IW_RSNIE_SANITY_FAIL_EVENT_FLAG 0x020C +#define IW_SET_KEY_DONE_WPA1_EVENT_FLAG 0x020D +#define IW_SET_KEY_DONE_WPA2_EVENT_FLAG 0x020E +#define IW_STA_LINKUP_EVENT_FLAG 0x020F +#define IW_STA_LINKDOWN_EVENT_FLAG 0x0210 +#define IW_SCAN_COMPLETED_EVENT_FLAG 0x0211 +#define IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG 0x0212 +#define IW_CHANNEL_CHANGE_EVENT_FLAG 0x0213 +#define IW_STA_MODE_EVENT_FLAG 0x0214 +#define IW_MAC_FILTER_LIST_EVENT_FLAG 0x0215 +#define IW_AUTH_REJECT_CHALLENGE_FAILURE 0x0216 +#define IW_SCANNING_EVENT_FLAG 0x0217 +#define IW_START_IBSS_FLAG 0x0218 +#define IW_JOIN_IBSS_FLAG 0x0219 +#define IW_SHARED_WEP_FAIL 0x021A +#define IW_WPS_END_EVENT_FLAG 0x021B +/* if add new system event flag, please upadte the IW_SYS_EVENT_FLAG_END */ +#define IW_SYS_EVENT_FLAG_END 0x021B +#define IW_SYS_EVENT_TYPE_NUM (IW_SYS_EVENT_FLAG_END - IW_SYS_EVENT_FLAG_START + 1) +/* For system event - end */ + +#ifdef IDS_SUPPORT +/* For spoof attack event - start */ +#define IW_SPOOF_EVENT_FLAG_START 0x0300 +#define IW_CONFLICT_SSID_EVENT_FLAG 0x0300 +#define IW_SPOOF_ASSOC_RESP_EVENT_FLAG 0x0301 +#define IW_SPOOF_REASSOC_RESP_EVENT_FLAG 0x0302 +#define IW_SPOOF_PROBE_RESP_EVENT_FLAG 0x0303 +#define IW_SPOOF_BEACON_EVENT_FLAG 0x0304 +#define IW_SPOOF_DISASSOC_EVENT_FLAG 0x0305 +#define IW_SPOOF_AUTH_EVENT_FLAG 0x0306 +#define IW_SPOOF_DEAUTH_EVENT_FLAG 0x0307 +#define IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG 0x0308 +#define IW_REPLAY_ATTACK_EVENT_FLAG 0x0309 +/* if add new spoof attack event flag, please upadte the IW_SPOOF_EVENT_FLAG_END */ +#define IW_SPOOF_EVENT_FLAG_END 0x0309 +#define IW_SPOOF_EVENT_TYPE_NUM (IW_SPOOF_EVENT_FLAG_END - IW_SPOOF_EVENT_FLAG_START + 1) +/* For spoof attack event - end */ + +/* For flooding attack event - start */ +#define IW_FLOOD_EVENT_FLAG_START 0x0400 +#define IW_FLOOD_AUTH_EVENT_FLAG 0x0400 +#define IW_FLOOD_ASSOC_REQ_EVENT_FLAG 0x0401 +#define IW_FLOOD_REASSOC_REQ_EVENT_FLAG 0x0402 +#define IW_FLOOD_PROBE_REQ_EVENT_FLAG 0x0403 +#define IW_FLOOD_DISASSOC_EVENT_FLAG 0x0404 +#define IW_FLOOD_DEAUTH_EVENT_FLAG 0x0405 +#define IW_FLOOD_EAP_REQ_EVENT_FLAG 0x0406 +/* if add new flooding attack event flag, please upadte the IW_FLOOD_EVENT_FLAG_END */ +#define IW_FLOOD_EVENT_FLAG_END 0x0406 +#define IW_FLOOD_EVENT_TYPE_NUM (IW_FLOOD_EVENT_FLAG_END - IW_FLOOD_EVENT_FLAG_START + 1) +/* For flooding attack - end */ +#endif /* IDS_SUPPORT */ + +#ifdef WSC_INCLUDED +/* For WSC wireless event - start */ +#define IW_WSC_EVENT_FLAG_START 0x0500 +#define IW_WSC_PBC_SESSION_OVERLAP 0x0500 +#define IW_WSC_REGISTRAR_SUPPORT_PBC 0x0501 +#define IW_WSC_REGISTRAR_SUPPORT_PIN 0x0502 +#define IW_WSC_STATUS_SUCCESS 0x0503 +#define IW_WSC_STATUS_FAIL 0x0504 +#define IW_WSC_2MINS_TIMEOUT 0x0505 +#define IW_WSC_SEND_EAPOL_START 0x0506 +#define IW_WSC_SEND_WSC_START 0x0507 +#define IW_WSC_SEND_M1 0x0508 +#define IW_WSC_SEND_M2 0x0509 +#define IW_WSC_SEND_M3 0x050a +#define IW_WSC_SEND_M4 0x050b +#define IW_WSC_SEND_M5 0x050c +#define IW_WSC_SEND_M6 0x050d +#define IW_WSC_SEND_M7 0x050e +#define IW_WSC_SEND_M8 0x050f +#define IW_WSC_SEND_DONE 0x0510 +#define IW_WSC_SEND_ACK 0x0511 +#define IW_WSC_SEND_NACK 0x0512 +#define IW_WSC_RECEIVE_WSC_START 0x0513 +#define IW_WSC_RECEIVE_M1 0x0514 +#define IW_WSC_RECEIVE_M2 0x0515 +#define IW_WSC_RECEIVE_M3 0x0516 +#define IW_WSC_RECEIVE_M4 0x0517 +#define IW_WSC_RECEIVE_M5 0x0518 +#define IW_WSC_RECEIVE_M6 0x0519 +#define IW_WSC_RECEIVE_M7 0x051a +#define IW_WSC_RECEIVE_M8 0x051b +#define IW_WSC_RECEIVE_DONE 0x051c +#define IW_WSC_RECEIVE_ACK 0x051d +#define IW_WSC_RECEIVE_NACK 0x051e +#define IW_WSC_MANY_CANDIDATE 0x051f +#define IW_WSC_NEXT_CANDIDATE 0x0520 +#define IW_WSC_T1_TIMER_TIMEOUT 0x0521 +#define IW_WSC_T2_TIMER_TIMEOUT 0x0522 +#define IW_WSC_EVENT_FLAG_END 0x0522 +#define IW_WSC_EVENT_TYPE_NUM (IW_WSC_EVENT_FLAG_END - IW_WSC_EVENT_FLAG_START + 1) +/* For WSC wireless event - end */ +#endif /* WSC_INCLUDED */ +/* End - WIRELESS EVENTS definition */ + + +#ifdef WH_EZ_SETUP +// For whole home coverage - easy setup wireless event - start +#define IW_WH_EZ_EVENT_FLAG_START 0x0700 +#define IW_WH_EZ_PROVIDER_SEARCHING 0x0700 +#define IW_WH_EZ_PROVIDER_FOUND 0x0701 +#define IW_WH_EZ_PROVIDER_STOP_SEARCHING 0x0702 +#define IW_WH_EZ_CONFIGURED_AP_SEARCHING 0x0703 +#define IW_WH_EZ_CONFIGURED_AP_FOUND 0x0704 +#define IW_WH_EZ_MY_APCLI_CONNECTED 0x0705 +#define IW_WH_EZ_MY_APCLI_DISCONNECTED 0x0706 +#define IW_WH_EZ_MY_AP_HAS_APCLI 0x0707 +#define IW_WH_EZ_MY_AP_DOES_NOT_HAS_APCLI 0x0708 +#define IW_WH_EZ_BECOME_CONFIGURED 0x0709 +#define IW_WH_EZ_EVENT_FLAG_END 0x0709 +#define IW_WH_EZ_EVENT_TYPE_NUM (IW_WH_EZ_EVENT_FLAG_END - IW_WH_EZ_EVENT_FLAG_START + 1) +/* For whole home coverage - easy setup wireless event - end */ +#endif /* WH_EZ_SETUP */ +#ifdef ALL_NET_EVENT +#define IW_ALL_NET_EVENT 0x0800 +#endif /* ALL_NET_EVENT */ + +#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 */ +// TODO: shiang-usw, check those RADIO ON/OFF values here!!! +#define DOT11POWERSAVE 0 +#define GUIRADIO_OFF 1 +#define RTMP_HALT 2 +#define GUI_IDLE_POWER_SAVE 3 + +enum { + RESUME_RADIO_ON, + SUSPEND_RADIO_OFF, + MLME_RADIO_ON, + MLME_RADIO_OFF, + DOT11_RADIO_ON, + DOT11_RADIO_OFF, +}; + +/* -- */ + +/* definition for WpaSupport flag */ +#define WPA_SUPPLICANT_DISABLE 0x00 +#define WPA_SUPPLICANT_ENABLE 0x01 +#define WPA_SUPPLICANT_ENABLE_WITH_WEB_UI 0x02 +#define WPA_SUPPLICANT_ENABLE_WPS 0x80 + +#ifdef MICROWAVE_OVEN_SUPPORT +/* definition for mitigating microwave interference */ +#define MO_FALSE_CCA_TH 25 +#define MO_MEAS_PERIOD 0 /* 0 ~ 100 ms */ +#define MO_IDLE_PERIOD 1 /* 100 ~ 1000 ms */ +#endif /* MICROWAVE_OVEN_SUPPORT */ + +typedef enum _ETHER_BAND_BINDDING { + EtherTrafficBand2G, + EtherTrafficBand5G, +} ETHER_BAND_BINDDING, *PETHER_BAND_BINDDING; + +/* definition for Antenna Diversity flag */ +typedef enum { + ANT_DIVERSITY_DISABLE, + ANT_DIVERSITY_ENABLE , + ANT_FIX_ANT0, + ANT_FIX_ANT1, + ANT_SW_DIVERSITY_ENABLE, + ANT_HW_DIVERSITY_ENABLE, + ANT_DIVERSITY_DEFAULT +}ANT_DIVERSITY_TYPE; + +enum IEEE80211_BAND { + IEEE80211_BAND_2G, + IEEE80211_BAND_5G, + IEEE80211_BAND_NUMS +}; + +#ifdef CONFIG_SWITCH_CHANNEL_OFFLOAD +#define CHANNEL_SWITCH_OFFLOAD 0x68 +#define CHANNEL_MCU_READY 0x7064 +#endif /* CONFIG_SWITCH_CHANNEL_OFFLOAD */ + +#if defined(CONFIG_MULTI_CHANNEL) || defined(DOT11Z_TDLS_SUPPORT) +#define HW_NULL_FRAME_1_OFFSET 0x7700 +#define HW_NULL_FRAME_2_OFFSET 0x7780 + +enum { + EDCA_AC0_DEQUEUE_DISABLE = (1 << 0), + EDCA_AC1_DEQUEUE_DISABLE = (1 << 1), + EDCA_AC2_DEQUEUE_DISABLE = (1 << 2), + EDCA_AC3_DEQUEUE_DISBALE = (1 << 3), + HCCA_DEQUEUE_DISABLE = (1 << 4) +}; + +enum { + HCCA_TO_EDCA, + EDCA_TO_HCCA = 0x55 +}; + +#define MUL_CHANNEL_ENABLE 0x77 +#define HCCA_TIMEOUT 400 +#define EDCA_TIMEOUT 400 +#endif /* defined(CONFIG_MULTI_CHANNEL) || defined(DOT11Z_TDLS_SUPPORT) */ + +#ifdef MT_PS +#define I_PSM_ENABLE 1 +#define I_PSM_DISABLE 0 +#endif /* MT_PS */ + +#ifdef SMART_CARRIER_SENSE_SUPPORT +enum { + SCS_DISABLE, + SCS_ENABLE, +}; + +enum { + SCS_STATUS_DEFAULT, + SCS_STATUS_MIDDLE, + SCS_STATUS_LOW, + SCS_STATUS_ULTRA_LOW, +}; + +enum { + Keep_Range, + Decrease_Range, + Increase_Range +}; +#endif /* SMART_CARRIER_SENSE_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) + + +#ifndef min +#define min(_a, _b) (((_a) < (_b)) ? (_a) : (_b)) +#endif + +#ifndef max +#define max(_a, _b) (((_a) > (_b)) ? (_a) : (_b)) +#endif + + +/* ========================================================================== */ +/* + 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, __TPID) \ +{ \ + VLAN_8023_Header_Copy(__VLAN_VID, __VLAN_Priority, \ + __pHeader8023, __HdrLen, __pData, \ + __TPID); \ +} + + +#define RT_80211_TO_8023_PACKET(__pAd, __VLAN_VID, __VLAN_Priority, \ + __pRxBlk, __pHeader802_3, \ + _wdev_idx, __TPID) \ +{ \ + wlan_802_11_to_802_3_packet( \ + get_netdev_from_bssid(__pAd, _wdev_idx), \ + __pRxBlk->OpMode, \ + __VLAN_VID, __VLAN_Priority, \ + __pRxBlk->pRxPacket, __pRxBlk->pData, __pRxBlk->DataSize, \ + __pHeader802_3, __TPID); \ +} + +// TODO: shiang-usw, fix me for pEntry->apidx to func_tb_idx +#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_UPDATE_OS_PACKET_INFO(__pAd, __pRxBlk, _wdev_idx) \ + RtmpOsPktInit(__pRxBlk->pRxPacket, \ + get_netdev_from_bssid(__pAd, _wdev_idx), \ + __pRxBlk->pData, __pRxBlk->DataSize); + +#ifdef SYSTEM_LOG_SUPPORT +/* + RTMPSendWirelessEvent --> RtmpOsSendWirelessEvent --> RtmpDrvSendWirelessEvent +*/ +#define RTMPSendWirelessEvent(__pAd, __Event_flag, __pAddr, _wdev_idx, __Rssi) \ + RtmpOsSendWirelessEvent(__pAd, __Event_flag, __pAddr, _wdev_idx, __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); +#define VALID_UCAST_ENTRY_WCID(_wcid) (_wcid < MAX_LEN_OF_MAC_TABLE) +#endif /* __RTMP_DEF_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_dot11.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_dot11.h new file mode 100644 index 000000000..7e8c1ea36 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_dot11.h @@ -0,0 +1,103 @@ +/* + +*/ + +#ifndef __DOT11_BASE_H__ +#define __DOT11_BASE_H__ + +#include "rtmp_type.h" +#include "dot11_base.h" +#include "dot11i_wpa.h" + +#ifdef DOT11_N_SUPPORT +#include "dot11n_ht.h" + +#ifdef DOT11_VHT_AC +#include "dot11ac_vht.h" +#endif /* DOT11_VHT_AC */ +#endif /* DOT11_N_SUPPORT */ + + +#ifdef DOT11K_RRM_SUPPORT +#include "dot11k_rrm.h" +#endif /* DOT11K_RRM_SUPPORT */ + + +/* 4-byte HTC field. maybe included in any frame except non-QOS data frame. The Order bit must set 1. */ +typedef struct GNU_PACKED _HT_CONTROL{ +#ifdef RT_BIG_ENDIAN + UINT32 RDG:1; + UINT32 ACConstraint:1; + UINT32 rsv2:5; + UINT32 NDPAnnounce:1; + UINT32 CSISTEERING:2; + UINT32 rsv1:2; + UINT32 CalSeq:2; + UINT32 CalPos:2; + UINT32 MFBorASC:7; + UINT32 MFSI:3; + UINT32 MSI:3; + UINT32 MRQ:1; + UINT32 TRQ:1; + UINT32 vht:1; +#else + UINT32 vht:1; /* indicate for VHT variant or HT variant */ + UINT32 TRQ:1; /*sounding request */ + UINT32 MRQ:1; /*MCS feedback. Request for a MCS feedback */ + UINT32 MSI:3; /*MCS Request, MRQ Sequence identifier */ + UINT32 MFSI:3; /*SET to the received value of MRS. 0x111 for unsolicited MFB. */ + UINT32 MFBorASC:7; /*Link adaptation feedback containing recommended MCS. 0x7f for no feedback or not available */ + UINT32 CalPos:2; /* calibration position */ + UINT32 CalSeq:2; /*calibration sequence */ + UINT32 rsv1:2; /* Reserved */ + UINT32 CSISTEERING:2; /*CSI/ STEERING */ + UINT32 NDPAnnounce:1; /* ZLF announcement */ + UINT32 rsv2:5; /*calibration sequence */ + UINT32 ACConstraint:1; /*feedback request */ + UINT32 RDG:1; /*RDG / More PPDU */ +#endif /* !RT_BIG_ENDIAN */ +} HT_CONTROL, *PHT_CONTROL; + +/* 2-byte QOS CONTROL field */ +typedef struct GNU_PACKED _QOS_CONTROL{ +#ifdef RT_BIG_ENDIAN + USHORT Txop_QueueSize:8; + USHORT AMsduPresent:1; + USHORT AckPolicy:2; /*0: normal ACK 1:No ACK 2:scheduled under MTBA/PSMP 3: BA */ + USHORT EOSP:1; + USHORT TID:4; +#else + USHORT TID:4; + USHORT EOSP:1; + USHORT AckPolicy:2; /*0: normal ACK 1:No ACK 2:scheduled under MTBA/PSMP 3: BA */ + USHORT AMsduPresent:1; + USHORT Txop_QueueSize:8; +#endif /* !RT_BIG_ENDIAN */ +} QOS_CONTROL, *PQOS_CONTROL; + + +typedef struct GNU_PACKED _AC_PARAM_RECORD{ + UINT8 aci_aifsn; + UINT8 ecw_max:4; + UINT8 ecw_min: 4; + UINT16 txop_limit; +}AC_PARAM_RECORD; + + +typedef struct GNU_PACKED _PSPOLL_FRAME { + FRAME_CONTROL FC; + USHORT Aid; + UCHAR Bssid[MAC_ADDR_LEN]; + UCHAR Ta[MAC_ADDR_LEN]; +} PSPOLL_FRAME, *PPSPOLL_FRAME; + + +typedef struct GNU_PACKED _RTS_FRAME { + FRAME_CONTROL FC; + USHORT Duration; + UCHAR Addr1[MAC_ADDR_LEN]; + UCHAR Addr2[MAC_ADDR_LEN]; +} RTS_FRAME, *PRTS_FRAME; + +#endif /* __DOT11_BASE_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_iface.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_iface.h new file mode 100644 index 000000000..bff173240 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_iface.h @@ -0,0 +1,62 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering 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_SDIO_SUPPORT +#include "iface/mt_sdio.h" +#endif /* RTMP_SDIO_SUPPORT */ + + +typedef struct _INF_PCI_CONFIG_ { + unsigned long CSRBaseAddress; /* PCI MMIO Base Address, all access will use */ + unsigned int irq_num; +} INF_PCI_CONFIG; + +typedef struct _INF_USB_CONFIG_ { + unsigned char BulkInEpAddr; /* bulk-in endpoint address */ + unsigned char BulkOutEpAddr[6]; /* bulk-out endpoint address */ +} INF_USB_CONFIG; + +typedef struct _INF_RBUS_CONFIG_ { + unsigned long csr_addr; + unsigned int irq; +} INF_RBUS_CONFIG; + + +typedef union _RTMP_INF_CONFIG_ { + struct _INF_PCI_CONFIG_ pciConfig; + struct _INF_USB_CONFIG_ usbConfig; + struct _INF_RBUS_CONFIG_ rbusConfig; +} RTMP_INF_CONFIG; + +#endif /* __RTMP_IFACE_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_os.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_os.h new file mode 100644 index 000000000..6c036a8a1 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_os.h @@ -0,0 +1,145 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + rtmp_os.h + + Abstract: + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + */ + +#ifndef __RTMP_OS_H__ +#define __RTMP_OS_H__ + +/* Driver Operators */ +typedef int (*RTMP_PRINTK)(const char *ftm, ...); +typedef int (*RTMP_SNPRINTF)(char *, ULONG, const char *ftm, ...); + +typedef struct _RTMP_OS_ABL_OPS { + int (*ra_printk)(const char *ftm, ...); + int (*ra_snprintf)(char *, ULONG, const char *ftm, ...); +} RTMP_OS_ABL_OPS; + +extern RTMP_OS_ABL_OPS *pRaOsOps; + +#ifndef CONFIG_RTPCI_AP_RF_OFFSET +#define CONFIG_RTPCI_AP_RF_OFFSET 0 +#endif + +#ifdef LINUX +#ifndef OS_ABL_FUNC_SUPPORT +#include "os/rt_linux.h" + +#else + +#ifdef RTMP_MODULE_OS +/* for util/netif */ +#include "os/rt_linux.h" +#else +/* for core */ +#include "os/rt_drv.h" +#endif /* RTMP_MODULE_OS */ +#endif /* OS_ABL_FUNC_SUPPORT */ +#endif /* LINUX */ + + + + + +// TODO: shiang, temporary put it here! +#include "os/pkt_meta.h" + +/* + This data structure mainly strip some callback function defined in + "struct net_device" in kernel source "include/linux/netdevice.h". + + The definition of this data structure may various depends on different + OS. Use it carefully. +*/ +typedef struct _RTMP_OS_NETDEV_OP_HOOK_ { + void *open; + void *stop; + void *xmit; + void *ioctl; + void *get_stats; + void *priv; + void *get_wstats; + void *iw_handler; + void *wdev; + int priv_flags; + unsigned char devAddr[6]; + unsigned char devName[16]; + unsigned char needProtcted; +} RTMP_OS_NETDEV_OP_HOOK, *PRTMP_OS_NETDEV_OP_HOOK; + + +typedef enum _RTMP_TASK_STATUS_ { + RTMP_TASK_STAT_UNKNOWN = 0, + RTMP_TASK_STAT_INITED = 1, + RTMP_TASK_STAT_RUNNING = 2, + RTMP_TASK_STAT_STOPED = 4, +} RTMP_TASK_STATUS; +#define RTMP_TASK_CAN_DO_INSERT (RTMP_TASK_STAT_INITED |RTMP_TASK_STAT_RUNNING) + +#define RTMP_OS_TASK_NAME_LEN 16 + +#if defined(RTMP_MODULE_OS) || !defined(OS_ABL_FUNC_SUPPORT) +/* used in UTIL/NETIF module */ +typedef struct _RTMP_OS_TASK_ { + char taskName[RTMP_OS_TASK_NAME_LEN]; + void *priv; + /*unsigned long taskFlags; */ + RTMP_TASK_STATUS taskStatus; +#ifndef KTHREAD_SUPPORT + RTMP_OS_SEM taskSema; + RTMP_OS_PID taskPID; +#ifdef LINUX + struct completion taskComplete; +#endif /* LINUX */ +#endif + unsigned char task_killed; +#ifdef KTHREAD_SUPPORT + struct task_struct *kthread_task; + wait_queue_head_t kthread_q; + BOOLEAN kthread_running; +#endif +} OS_TASK; +#endif /* RTMP_MODULE_OS || ! OS_ABL_FUNC_SUPPORT */ + + +int RtmpOSIRQRequest(PNET_DEV pNetDev); + + +#ifndef OS_ABL_SUPPORT +#define RTMP_MATOpsInit(__pAd) +#define RTMP_MATPktRxNeedConvert(__pAd, __pDev) \ + MATPktRxNeedConvert(__pAd, __pDev) +#define RTMP_MATEngineRxHandle(__pAd, __pPkt, __InfIdx) \ + MATEngineRxHandle(__pAd, __pPkt, __InfIdx) +#else + +#define RTMP_MATOpsInit(__pAd) \ + (__pAd)->MATPktRxNeedConvert = MATPktRxNeedConvert; \ + (__pAd)->MATEngineRxHandle = MATEngineRxHandle; +#define RTMP_MATPktRxNeedConvert(__pAd, __pDev) \ + ((__pAd)->MATPktRxNeedConvert(__pAd, __pDev)) +#define RTMP_MATEngineRxHandle(__pAd, __pPkt, __InfIdx) \ + ((__pAd)->MATEngineRxHandle(__pAd, __pPkt, __InfIdx)) +#endif /* OS_ABL_SUPPORT */ + +#endif /* __RMTP_OS_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_osabl.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_osabl.h new file mode 100644 index 000000000..32fdad5b3 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_osabl.h @@ -0,0 +1,65 @@ +/**************************************************************************** + + 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 +#define 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 +#define CONFIG_STA_SUPPORT +#endif /* OS_ABL_OS_STA_SUPPORT */ + +/* AP & STA con-current */ +#undef RT_CONFIG_IF_OPMODE_ON_AP +#undef RT_CONFIG_IF_OPMODE_ON_STA + +#if defined(CONFIG_AP_SUPPORT) && defined(CONFIG_STA_SUPPORT) +#define RT_CONFIG_IF_OPMODE_ON_AP(__OpMode) if (__OpMode == OPMODE_AP) +#define RT_CONFIG_IF_OPMODE_ON_STA(__OpMode) if (__OpMode == OPMODE_STA) +#else +#define RT_CONFIG_IF_OPMODE_ON_AP(__OpMode) +#define RT_CONFIG_IF_OPMODE_ON_STA(__OpMode) +#endif + +#endif /* OS_ABL_FUNC_SUPPORT */ + +#endif /* __RTMP_OS_ABL_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_timer.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_timer.h new file mode 100644 index 000000000..abd3ad366 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_timer.h @@ -0,0 +1,221 @@ +/* + *************************************************************************** + * 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; + + +INT RtmpTimerQThread(ULONG Context); + +struct _RTMP_ADAPTER; +RTMP_TIMER_TASK_ENTRY *RtmpTimerQInsert( + IN struct _RTMP_ADAPTER *pAd, + IN RALINK_TIMER_STRUCT *pTimer); + +BOOLEAN RtmpTimerQRemove( + IN struct _RTMP_ADAPTER *pAd, + IN RALINK_TIMER_STRUCT *pTimer); + +void RtmpTimerQExit(struct _RTMP_ADAPTER *pAd); +void RtmpTimerQInit(struct _RTMP_ADAPTER *pAd); + +#define BUILD_TIMER_FUNCTION(_func) \ + void rtmp_timer_##_func(struct timer_list *_timer) \ + { \ + PRALINK_TIMER_STRUCT _pTimer = from_timer(_pTimer,_timer,_timer); \ + 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(MlmePeriodicExecTimer); +DECLARE_TIMER_FUNCTION(MlmeRssiReportExec); +DECLARE_TIMER_FUNCTION(AsicRxAntEvalTimeout); +DECLARE_TIMER_FUNCTION(APSDPeriodicExec); +DECLARE_TIMER_FUNCTION(EnqueueStartForPSKExec); + +#ifdef DOT11W_PMF_SUPPORT +DECLARE_TIMER_FUNCTION(PMF_SAQueryTimeOut); +DECLARE_TIMER_FUNCTION(PMF_SAQueryConfirmTimeOut); +#endif /* DOT11W_PMF_SUPPORT */ + + +#ifdef CONFIG_AP_SUPPORT +DECLARE_TIMER_FUNCTION(APDetectOverlappingExec); + +#ifdef DOT11N_DRAFT3 +DECLARE_TIMER_FUNCTION(Bss2040CoexistTimeOut); +#endif /* DOT11N_DRAFT3 */ + +DECLARE_TIMER_FUNCTION(GREKEYPeriodicExec); +DECLARE_TIMER_FUNCTION(CMTimerExec); +DECLARE_TIMER_FUNCTION(WPARetryExec); +#ifdef AP_SCAN_SUPPORT +DECLARE_TIMER_FUNCTION(APScanTimeout); +#endif /* AP_SCAN_SUPPORT */ +DECLARE_TIMER_FUNCTION(APQuickResponeForRateUpExec); + +#ifdef IDS_SUPPORT +DECLARE_TIMER_FUNCTION(RTMPIdsPeriodicExec); +#endif /* IDS_SUPPORT */ + +#ifdef DOT11R_FT_SUPPORT +DECLARE_TIMER_FUNCTION(FT_KDP_InfoBroadcast); +#endif /* DOT11R_FT_SUPPORT */ + +#endif /* CONFIG_AP_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); +DECLARE_TIMER_FUNCTION(WscSetupLockTimeout); +#ifdef MT_MAC +DECLARE_TIMER_FUNCTION(WscEapReqIdRetryTimeout); +#endif /* MT_MAC */ +#endif /* CONFIG_AP_SUPPORT */ +#endif /* WSC_INCLUDED */ + + +#ifdef CONFIG_HOTSPOT + +#ifdef CONFIG_AP_SUPPORT +DECLARE_TIMER_FUNCTION(PostReplyTimeout); +#endif /* CONFIG_AP_SUPPORT */ +#endif /* CONFIG_HOTSPOT */ + + + +#ifdef CONFIG_ATE +DECLARE_TIMER_FUNCTION(ATEPeriodicExec); +#endif /* CONFIG_ATE */ + +#ifdef WH_EZ_SETUP +DECLARE_TIMER_FUNCTION(ez_scan_timeout); +//DECLARE_TIMER_FUNCTION(ez_stop_scan_timeout); +DECLARE_TIMER_FUNCTION(ez_scan_pause_timeout); +#ifdef EZ_NETWORK_MERGE_SUPPORT +DECLARE_TIMER_FUNCTION(ez_group_merge_timeout); +#endif +#ifdef NEW_CONNECTION_ALGO +DECLARE_TIMER_FUNCTION(ez_wait_for_connection_allow_timeout); +#endif +#ifdef EZ_DUAL_BAND_SUPPORT +DECLARE_TIMER_FUNCTION(ez_loop_chk_timeout); +#endif +#endif /* WH_EZ_SETUP */ + +#ifdef MIXMODE_SUPPORT +DECLARE_TIMER_FUNCTION(MixModeTimeout); +#endif + +#endif /* __RTMP_TIMER_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_type.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_type.h new file mode 100644 index 000000000..594440deb --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/rtmp_type.h @@ -0,0 +1,228 @@ +/* + *************************************************************************** + * 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 */ +#if defined(DOT11_SAE_SUPPORT) || defined(CONFIG_OWE_SUPPORT) +typedef char INT8; +#endif +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 char RTMP_STRING; + +typedef signed char CHAR; + +typedef signed short SHORT; +typedef signed int INT; +typedef signed long LONG; +typedef signed long long LONGLONG; + +typedef unsigned long long ULONGLONG; + +typedef unsigned char BOOLEAN; + +#ifdef LINUX +typedef void VOID; +#endif /* LINUX */ + +typedef char *PSTRING; +typedef VOID *PVOID; +typedef CHAR *PCHAR; +typedef UCHAR *PUCHAR; +typedef USHORT *PUSHORT; +typedef LONG *PLONG; +typedef ULONG *PULONG; +typedef UINT *PUINT; + +typedef unsigned int NDIS_MEDIA_STATE; + +typedef union _LARGE_INTEGER { + struct { +#ifdef RT_BIG_ENDIAN + INT32 HighPart; + UINT LowPart; +#else + UINT LowPart; + INT32 HighPart; +#endif + } u; + INT64 QuadPart; +} LARGE_INTEGER; + + +/* Register set pair for initialzation register set definition */ +typedef struct _RTMP_REG_PAIR { + UINT32 Register; + UINT32 Value; +} RTMP_REG_PAIR, *PRTMP_REG_PAIR; + +typedef struct _MT_RF_REG_PAIR { + UINT8 WiFiStream; + UINT32 Register; + UINT32 Value; +} MT_RF_REG_PAIR; + +typedef struct _REG_PAIR { + UCHAR Register; + UCHAR Value; +} REG_PAIR, *PREG_PAIR; + +typedef struct _REG_PAIR_CHANNEL { + UCHAR Register; + UCHAR FirstChannel; + UCHAR LastChannel; + UCHAR Value; +} REG_PAIR_CHANNEL, *PREG_PAIR_CHANNEL; + +typedef struct _REG_PAIR_BW { + UCHAR Register; + UCHAR BW; + UCHAR Value; +} REG_PAIR_BW, *PREG_PAIR_BW; + + +typedef struct _REG_PAIR_PHY{ + UCHAR reg; + UCHAR s_ch; + UCHAR e_ch; + UCHAR phy; /* RF_MODE_XXX */ + UCHAR bw; /* RF_BW_XX */ + UCHAR val; +}REG_PAIR_PHY; + + +/* Register set pair for initialzation register set definition */ +typedef struct _RTMP_RF_REGS { + UCHAR Channel; + UINT32 R1; + UINT32 R2; + UINT32 R3; + UINT32 R4; +} RTMP_RF_REGS, *PRTMP_RF_REGS; + +typedef struct _FREQUENCY_ITEM { + UCHAR Channel; + UCHAR N; + UCHAR R; + UCHAR K; +} FREQUENCY_ITEM, *PFREQUENCY_ITEM; + +typedef int NTSTATUS; + +#define STATUS_SUCCESS 0x00 +#define STATUS_UNSUCCESSFUL 0x01 + +typedef struct _QUEUE_ENTRY { + struct _QUEUE_ENTRY *Next; +} QUEUE_ENTRY, *PQUEUE_ENTRY; + +/* Queue structure */ +typedef struct _QUEUE_HEADER { + PQUEUE_ENTRY Head; + PQUEUE_ENTRY Tail; + UINT Number; +#ifdef MAX_CONTINUOUS_TX_CNT + UINT8 AlreadyDeqCnt;/* Add a flag to record already De-queue count*/ +#endif +} QUEUE_HEADER, *PQUEUE_HEADER; + +typedef struct _CR_REG { + UINT32 flags; + UINT32 offset; + UINT32 value; +} CR_REG, *PCR_REG; + +typedef struct _BANK_RF_CR_REG { + UINT32 flags; + UCHAR bank; + UCHAR offset; + UCHAR value; +} BANK_RF_CR_REG, *PBANK_RF_CR_REG; + + +typedef struct _BANK_RF_REG_PAIR { + UCHAR Bank; + UCHAR Register; + UCHAR Value; +} BANK_RF_REG_PAIR, *PBANK_RF_REG_PAIR; + +typedef struct _R_M_W_REG{ + UINT32 Register; + UINT32 ClearBitMask; + UINT32 Value; +} R_M_W_REG, *PR_M_W_REG; + +typedef struct _RF_R_M_W_REG{ + UCHAR Bank; + UCHAR Register; + UCHAR ClearBitMask; + UCHAR Value; +} RF_R_M_W_REG, *PRF_R_M_W_REG; + +struct mt_dev_priv{ + void *sys_handle; + void *wifi_dev; + unsigned long priv_flags; + UCHAR sniffer_mode; +}; + +#endif /* __RTMP_TYPE_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sae.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sae.h new file mode 100644 index 000000000..7297eb4b6 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sae.h @@ -0,0 +1,347 @@ +/* + *************************************************************************** + * 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: + sae.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Name Date Modification logs +*/ + +#ifndef __SAE_H__ +#define __SAE_H__ +#ifdef DOT11_SAE_SUPPORT + +INT show_sae_info_proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +VOID sae_cfg_init( + IN RTMP_ADAPTER * pAd, + IN SAE_CFG * pSaeCfg); + +VOID sae_cfg_deinit( + IN RTMP_ADAPTER * pAd, + IN SAE_CFG * pSaeCfg); + + +SAE_INSTANCE *search_sae_instance( + IN SAE_CFG * pSaeCfg, + IN UCHAR * own_mac, + IN UCHAR * peer_mac); + +SAE_INSTANCE *create_sae_instance( + IN RTMP_ADAPTER * pAd, + IN SAE_CFG * pSaeCfg, + IN UCHAR * own_mac, + IN UCHAR * peer_mac, + IN UCHAR * bssid, + IN UCHAR * psk); + + +VOID delete_sae_instance( + IN SAE_INSTANCE *pSaeIns); + +UCHAR set_sae_instance_removable( + IN SAE_CFG * pSaeCfg, + IN UCHAR *own_mac, + IN UCHAR *peer_mac); + +VOID sae_ins_init( + IN RTMP_ADAPTER * pAd, + IN SAE_CFG * pSaeCfg, + IN SAE_INSTANCE *pSaeIns, + IN UCHAR * own_mac, + IN UCHAR * peer_mac, + IN UCHAR * bssid, + IN UCHAR * psk); + +/* partial */ +VOID sae_clear_data( + IN SAE_INSTANCE *pSaeIns); + +VOID sae_dump_time( + IN SAE_TIME_INTERVAL * time_cost +); + +UCHAR sae_using_anti_clogging( + IN SAE_CFG * pSaeCfg); + + +VOID sae_set_retransmit_timer( + IN SAE_INSTANCE *pSaeIns); + + +VOID sae_clear_retransmit_timer( + IN SAE_INSTANCE *pSaeIns); + + +DECLARE_TIMER_FUNCTION(sae_auth_retransmit); + + +VOID sae_auth_retransmit( + IN VOID *SystemSpecific1, + IN VOID *FunctionContext, + IN VOID *SystemSpecific2, + IN VOID *SystemSpecific3); + + +UCHAR sae_auth_init( + IN RTMP_ADAPTER * pAd, + IN SAE_CFG * pSaeCfg, + IN UCHAR *own_mac, + IN UCHAR *peer_mac, + IN UCHAR *bssid, + IN UCHAR *psk, + IN INT32 group); + + + +UCHAR sae_handle_auth( + IN RTMP_ADAPTER *pAd, + IN SAE_CFG *pSaeCfg, + IN VOID *msg, + IN UINT32 msg_len, + IN UCHAR *psk, + IN USHORT auth_seq, + IN USHORT auth_status, + OUT UCHAR** pmk); + + +USHORT sae_sm_step( + IN RTMP_ADAPTER * pAd, + IN SAE_INSTANCE *pSaeIns, + IN USHORT auth_seq); + + +UCHAR sae_check_big_sync( + IN SAE_INSTANCE *pSaeIns); + +UCHAR sae_get_pmk_cache( + IN SAE_CFG * pSaeCfg, + IN UCHAR *own_mac, + IN UCHAR *peer_mac, + OUT UCHAR *pmkid, + OUT UCHAR *pmk); + +UCHAR sae_build_token_req( + IN RTMP_ADAPTER * pAd, + IN SAE_INSTANCE * pSaeIns, + OUT UCHAR *token, + OUT UINT32 * token_len); + +UCHAR sae_check_token( + IN SAE_INSTANCE * pSaeIns, + IN UCHAR *peer_token, + IN UINT32 peer_token_len); + + +USHORT sae_parse_commit( + IN SAE_CFG * pSaeCfg, + IN SAE_INSTANCE *pSaeIns, + IN UCHAR *msg, + IN UINT32 msg_len, + IN UCHAR **token, + IN UINT32 * token_len, + IN UCHAR is_token_req); + + +VOID sae_parse_commit_token( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR **pos, + IN UCHAR *end, + IN UCHAR **token, + IN UINT32 * token_len); + + +USHORT sae_parse_commit_scalar( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR **pos, + IN UCHAR *end); + + +USHORT sae_parse_commit_element( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR *pos, + IN UCHAR *end); + + +USHORT sae_prepare_commit( + IN SAE_INSTANCE *pSaeIns); + + +USHORT sae_derive_commit( + IN SAE_INSTANCE *pSaeIns); + + +USHORT sae_process_commit( + IN SAE_INSTANCE *pSaeIns); + + +UCHAR sae_derive_key( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR *k); + + +VOID sae_send_auth( + IN RTMP_ADAPTER * pAd, + IN UCHAR *own_mac, + IN UCHAR *peer_mac, + IN UCHAR *bssid, + IN USHORT alg, + IN USHORT seq, + IN USHORT status_code, + IN UCHAR *buf, + IN UINT32 buf_len); + + +UCHAR sae_send_auth_commit( + IN RTMP_ADAPTER * pAd, + IN SAE_INSTANCE *pSaeIns); + + +UCHAR sae_send_auth_confirm( + IN RTMP_ADAPTER * pAd, + IN SAE_INSTANCE *pSaeIns); + + +USHORT sae_parse_confirm( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR *msg, + IN UINT32 msg_len); + + +USHORT sae_check_confirm( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR *peer_confirm); + + +SAE_BN *sae_gen_rand( + IN SAE_INSTANCE *pSaeIns); + + +USHORT sae_group_allowed( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR *allowed_groups, + IN INT32 group); + + +UCHAR is_sae_group_ecc( + IN INT32 group); + + +UCHAR is_sae_group_ffc( + IN INT32 group); + + +#ifdef group_related +/* + ===================================== + group related + ===================================== +*/ +#endif +VOID sae_group_init_ecc( + IN SAE_INSTANCE *pSaeIns, + IN INT32 group); + +VOID sae_group_init_ffc( + IN SAE_INSTANCE *pSaeIns, + IN INT32 group); + + +VOID sae_group_deinit_ecc( + IN SAE_INSTANCE *pSaeIns); + + +VOID sae_group_deinit_ffc( + IN SAE_INSTANCE *pSaeIns); + + +VOID sae_cn_confirm_ecc( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR is_send, /* otherwise, is verfication */ + OUT UCHAR *confirm); + + +VOID sae_cn_confirm_ffc( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR is_send, /* otherwise, is verfication */ + OUT UCHAR *confirm); + + +VOID sae_cn_confirm_cmm( + IN SAE_INSTANCE *pSaeIns, + IN SAE_BN *scalar1, + IN SAE_BN *scalar2, + IN UCHAR *element_bin1, + IN UCHAR *element_bin2, + IN UINT32 element_len, + IN USHORT send_confirm, + OUT UCHAR *confirm); + + +USHORT sae_parse_commit_element_ecc( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR *pos, + IN UCHAR *end); + + +USHORT sae_parse_commit_element_ffc( + IN SAE_INSTANCE *pSaeIns, + IN UCHAR *pos, + IN UCHAR *end); + + +UCHAR sae_derive_commit_element_ecc( + IN SAE_INSTANCE *pSaeIns, + IN SAE_BN *mask); + + +UCHAR sae_derive_commit_element_ffc( + IN SAE_INSTANCE *pSaeIns, + IN SAE_BN *mask); + +USHORT sae_derive_pwe_ecc( + IN SAE_INSTANCE *pSaeIns); + + +USHORT sae_derive_pwe_ffc( + IN SAE_INSTANCE *pSaeIns); + + + +UCHAR sae_derive_k_ecc( + IN SAE_INSTANCE *pSaeIns, + OUT UCHAR *k); + + +UCHAR sae_derive_k_ffc( + IN SAE_INSTANCE *pSaeIns, + OUT UCHAR *k); + +USHORT sae_reflection_check_ecc( + IN SAE_INSTANCE *pSaeIns); + +USHORT sae_reflection_check_ffc( + IN SAE_INSTANCE *pSaeIns); + +#endif /* DOT11_SAE_SUPPORT */ +#endif /* __SAE_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sae_cmm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sae_cmm.h new file mode 100644 index 000000000..4df12ebdd --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sae_cmm.h @@ -0,0 +1,2099 @@ +#ifndef SAE_CMM_H +#define SAE_CMM_H + +#ifdef DOT11_SAE_SUPPORT + +#ifdef DOT11_SAE_OPENSSL_BN +#include "crypt_bignum.h" +#include "crypt_biginteger.h" +#include "bn.h" + +#define SAE_BN BIGNUM + +#define SAE_BN_INIT(_in) Bignum_Init(_in) +#define SAE_BN_FREE(_in) Bignum_Free(_in) +#define SAE_BN_PRINT(_in) Bignum_Print(_in) +#define SAE_BN_RELEASE_BACK_TO_POOL(_in) Bignum_Free(_in) +#define SAE_BN_COPY(_in, _out) Bignum_Copy(_in, _out) +#define SAE_BN_BIN2BI(_ptr, _len, _out) Bignum_Bin2BI(_ptr, _len, _out) +#define SAE_BN_BI2BIN_WITH_PAD(_in, _ptr, _len, _padlen) \ + Bignum_BI2Bin_with_pad(_in, _ptr, _len, _padlen) +#define SAE_BN_GET_LEN(_in) Bignum_getlen(_in) + +#define SAE_BN_UCMP(_a, _b) Bignum_UnsignedCompare(_a, _b) +#define SAE_BN_IS_ZERO(_in) Bignum_is_zero(_in) +#define SAE_BN_IS_ONE(_in) Bignum_is_one(_in) +#define SAE_BN_IS_ODD(_in) Bignum_is_odd(_in) +#define SAE_BN_RSHIFT1(_in, _out) Bignum_Shift_Right1(_in, _out) +#define SAE_BN_MOD_LSHIFT1(_in, _p, _out) Bignum_Mod_Shift_Left1(_in, _p, _out) +#define SAE_BN_MOD_LSHIFT(_in, _bit, _p, _out) Bignum_Mod_Shift_Left(_in, _bit, _p, _out) +#define SAE_BN_IS_QUADRATIC_RESIDE(_q, _p, _m) Bignum_is_quadratic_residue(_q, _p) + +#define SAE_BN_ADD(_a, _b, _r) Bignum_Add(_a, _b, _r) /* no use */ +#define SAE_BN_SUB(_a, _b, _r) Bignum_Sub(_a, _b, _r) +#define SAE_BN_ADD_DW(_inout, _v) Bignum_Add_DW(_inout, _v) + +#define SAE_BN_MOD(_a, _p, _r) Bignum_Mod(_a, _p, _r) +#define SAE_BN_MOD_ADD(_a, _b, _p, _r) Bignum_Mod_Add(_a, _b, _p, _r) +#define SAE_BN_MOD_ADD_QUICK(_a, _b, _p, _r) Bignum_Mod_Add_quick(_a, _b, _p, _r) +#define SAE_BN_MOD_SUB(_a, _b, _p, _r) Bignum_Mod_Sub(_a, _b, _p, _r) +#define SAE_BN_MOD_SUB_QUICK(_a, _b, _p, _r) Bignum_Mod_Sub_quick(_a, _b, _p, _r) +#define SAE_BN_MOD_MUL(_a, _b, _p, _r) Bignum_Mod_Mul(_a, _b, _p, _r) +#define SAE_BN_MOD_DIV(_a, _b, _p, _r) Bignum_Mod_Div(_a, _b, _p, _r) +#define SAE_BN_MOD_SQR(_a, _p, _r) Bignum_Mod_Square(_a, _p, _r) +#define SAE_BN_MOD_SQRT(_a, _p, _mont, _r) Bignum_Mod_Sqrt(_a, _p, _r) +#define SAE_BN_MOD_MUL_INV(_a, _p, _r) Bignum_Mod_Mul_Inverse(_a, _p, _r) +#define SAE_BN_MOD_DW(_inout, _v, _rem) Bignum_Mod_DW(_inout, _v, _rem) + +#define SAE_BN_MOD_EXP_MONT(_a, _b, _p, _r) Bignum_Montgomery_ExpMod(_a, _b, _p, _r) +#define SAE_LOG_TIME_BEGIN(_timerec) BigInteger_record_time_begin(_timerec) +#define SAE_LOG_TIME_END(_timerec) BigInteger_record_time_end(_timerec) +#define SAE_LOG_TIME_DUMP() BigInteger_dump_time() +#define SAE_GET_RAND_RANGE(_r, _range) Bignum_Get_rand_range(_range, _r) + + +#else +#include "crypt_biginteger.h" + +#define SAE_BN BIG_INTEGER + +#define SAE_BN_INIT(_in) BigInteger_Init(_in) +#define SAE_BN_FREE(_in) BigInteger_Free(_in) +#define SAE_BN_PRINT(_in) BigInteger_Print(_in) +#define SAE_BN_RELEASE_BACK_TO_POOL(_in) release_temporal_usage_big_interger(_in) +#define SAE_BN_COPY(_in, _out) BigInteger_Copy(_in, _out) +#define SAE_BN_BIN2BI(_ptr, _len, _out) BigInteger_Bin2BI(_ptr, _len, _out) +#define SAE_BN_BI2BIN_WITH_PAD(_in, _ptr, _len, _padlen) \ + BigInteger_BI2Bin_with_pad(_in, _ptr, _len, _padlen) +#define SAE_BN_GET_LEN(_in) BigInteger_getlen(_in) +#define SAE_BN_UCMP(_a, _b) BigInteger_UnsignedCompare(_a, _b) +#define SAE_BN_IS_ZERO(_in) BigInteger_is_zero(_in) +#define SAE_BN_IS_ONE(_in) BigInteger_is_one(_in) +#define SAE_BN_IS_ODD(_in) BigInteger_is_odd(_in) +#define SAE_BN_RSHIFT1(_in, _out) BigInteger_Shift_Right1(_in, _out) +#define SAE_BN_MOD_LSHIFT1(_in, _p, _out) BigInteger_Mod_Shift_Left(_in, 1, _p, _out) +#define SAE_BN_MOD_LSHIFT(_in, _bit, _p, _out) BigInteger_Mod_Shift_Left(_in, _bit, _p, _out) +#define SAE_BN_IS_QUADRATIC_RESIDE(_q, _p, _m) BigInteger_is_quadratic_residue(_q, _p, _m) + +#define SAE_BN_ADD(_a, _b, _r) BigInteger_Add(_a, _b, _r) /* no use */ +#define SAE_BN_SUB(_a, _b, _r) BigInteger_Sub(_a, _b, _r) +#define SAE_BN_ADD_DW(_inout, _v) BigInteger_Add_DW(_inout, _v) + +#define SAE_BN_MOD(_a, _p, _r) BigInteger_Mod(_a, _p, _r) +#define SAE_BN_MOD_ADD(_a, _b, _p, _r) BigInteger_Mod_Add(_a, _b, _p, _r) +#define SAE_BN_MOD_ADD_QUICK(_a, _b, _p, _r) BigInteger_Mod_Add_quick(_a, _b, _p, _r) +#define SAE_BN_MOD_SUB(_a, _b, _p, _r) BigInteger_Mod_Sub(_a, _b, _p, _r) +#define SAE_BN_MOD_SUB_QUICK(_a, _b, _p, _r) BigInteger_Mod_Sub_quick(_a, _b, _p, _r) +#define SAE_BN_MOD_MUL(_a, _b, _p, _r) BigInteger_Mod_Mul(_a, _b, _p, _r) +#define SAE_BN_MOD_DIV(_a, _b, _p, _r) BigInteger_Mod_Div(_a, _b, _p, _r) +#define SAE_BN_MOD_SQR(_a, _p, _r) BigInteger_Mod_Square(_a, _p, _r) +#define SAE_BN_MOD_SQRT(_a, _p, _mont, _r) BigInteger_Mod_Sqrt(_a, _p, _mont, _r) +#define SAE_BN_MOD_MUL_INV(_a, _p, _r) BigInteger_Mod_Mul_Inverse(_a, _p, _r) +#define SAE_BN_MOD_DW(_inout, _v, _rem) BigInteger_Mod_DW(_inout, _v, _rem) + +#define SAE_BN_MOD_EXP_MONT(_a, _b, _p, _r) BigInteger_Montgomery_ExpMod(_a, _b, _p, _r) +#define SAE_LOG_TIME_BEGIN(_timerec) BigInteger_record_time_begin(_timerec) +#define SAE_LOG_TIME_END(_timerec) BigInteger_record_time_end(_timerec) +#define SAE_LOG_TIME_DUMP() BigInteger_dump_time() +#define SAE_GET_RAND_RANGE(_r, _range) BigInteger_rand_range(_range, _r) + +#endif + +#define SAE_ECC_3D +#ifdef SAE_ECC_3D +#define SAE_ECC_3D_to_2D(_group_info, _inout) ecc_point_3d_to_2d(_group_info, _inout) +#define SAE_ECC_SET_Z_TO_1(_inout) ecc_point_set_z_to_one(_inout) +#else +#define SAE_ECC_3D_to_2D(_group_info, _inout) +#define SAE_ECC_SET_Z_TO_1(_inout) + +#endif + +#define SAE_TOKEN_KEY_LEN 6 /* this parameter is not defined in spec */ + +#define SAE_KCK_LEN 32 +#define SAE_PMKID_LEN 16 +#define SAE_KEYSEED_KEY_LEN 32 +#define SAE_MAX_PRIME_LEN 1024 +#define SAE_MAX_ECC_PRIME_LEN 66 +#define SAE_COMMIT_MAX_LEN (2 + 3 * SAE_MAX_PRIME_LEN) +#define SAE_CONFIRM_MAX_LEN (2 + SAE_MAX_PRIME_LEN) + +#define SAE_COMMIT_SEQ 1 +#define SAE_CONFIRM_SEQ 2 + +#define MAX_SIZE_OF_ALLOWED_GROUP 30 + +#define DOT11RSNASAESYNC 5 + +#define SAE_SILENTLY_DISCARDED 65535 +#define SAE_MAX_SEND_CONFIRM 65535 + + +#define SAE_DEFAULT_GROUP SAE_DEFAULT_GROUP_ECC +#define SAE_DEFAULT_GROUP_ECC 19 +#define SAE_DEFAULT_GROUP_FFC 5 + +#define ECC_POINT_MUL(_point, _scalar, _ec_group_bi, _ec_point_res) ecc_point_mul_windowed(_point, _scalar, _ec_group_bi, _ec_point_res) + + +#define SET_NOTHING_STATE(_pSaeIns) \ + {\ + if (_pSaeIns->pParentSaeCfg\ + && ((_pSaeIns->state == SAE_COMMITTED)\ + || (_pSaeIns->state == SAE_CONFIRMED)))\ + _pSaeIns->pParentSaeCfg->open--;\ + _pSaeIns->state = SAE_NOTHING;\ + } + +#define SET_COMMITTED_STATE(_pSaeIns) \ + {\ + if (_pSaeIns->pParentSaeCfg\ + && ((_pSaeIns->state == SAE_NOTHING)\ + || (_pSaeIns->state == SAE_ACCEPTED)))\ + _pSaeIns->pParentSaeCfg->open++;\ + _pSaeIns->state = SAE_COMMITTED;\ + } + +#define SET_CONFIRMED_STATE(_pSaeIns) \ + {\ + if (_pSaeIns->pParentSaeCfg\ + && ((_pSaeIns->state == SAE_NOTHING)\ + || (_pSaeIns->state == SAE_ACCEPTED)))\ + _pSaeIns->pParentSaeCfg->open++;\ + _pSaeIns->state = SAE_CONFIRMED;\ + } + +#define SET_ACCEPTED_STATE(_pSaeIns) \ + {\ + if (_pSaeIns->pParentSaeCfg\ + && ((_pSaeIns->state == SAE_COMMITTED)\ + || (_pSaeIns->state == SAE_CONFIRMED)))\ + _pSaeIns->pParentSaeCfg->open--;\ + _pSaeIns->state = SAE_ACCEPTED;\ + } + + + +typedef enum { + SAE_NOTHING, + SAE_COMMITTED, + SAE_CONFIRMED, + SAE_ACCEPTED +} SAE_STATE_TYPE, *PSAE_STATE_TYPE; + +typedef struct __SAE_GROUP_OP SAE_GROUP_OP; + +typedef struct __SAE_INSTANCE SAE_INSTANCE; + +typedef struct __SAE_CFG SAE_CFG; + +struct __SAE_GROUP_OP { + VOID(*sae_group_init) ( + IN SAE_INSTANCE * pSaeIns, + IN INT32 group); + VOID(*sae_group_deinit) ( + IN SAE_INSTANCE * pSaeIns); + VOID(*sae_cn_confirm) ( + IN SAE_INSTANCE * pSaeIns, + IN UCHAR is_send, + OUT UCHAR * confirm); + USHORT(*sae_parse_commit_element) ( + IN SAE_INSTANCE * pSaeIns, + IN UCHAR * pos, + IN UCHAR * end); + UCHAR(*sae_derive_commit_element) ( + IN SAE_INSTANCE * pSaeIns, + IN SAE_BN *mask); + USHORT(*sae_derive_pwe) ( + IN SAE_INSTANCE * pSaeIns); + UCHAR(*sae_derive_k) ( + IN SAE_INSTANCE * pSaeIns, + OUT UCHAR * k); + USHORT(*sae_reflection_check) ( + IN SAE_INSTANCE * pSaeIns); +}; + +/* NdisGetSystemUpTime */ +typedef struct __SAE_TIME_INTERVAL { + ULONG derive_pwe_time; + ULONG parse_commit_scalar_time; + ULONG parse_commit_element_time; + ULONG derive_commit_scalar_time; + ULONG derive_commit_element_time; + ULONG derive_k_time; + ULONG derive_pmk_time; +} SAE_TIME_INTERVAL, *PSAE_TIME_INTERVAL; + + +struct __SAE_INSTANCE { + SAE_STATE_TYPE state; + USHORT send_confirm; + USHORT last_peer_sc; + UCHAR pmk[LEN_PMK]; + SAE_BN *peer_commit_scalar; + USHORT group; + INT8 sync; + UINT8 support_group_idx; + UCHAR kck[SAE_KCK_LEN]; + SAE_BN *own_commit_scalar; + VOID *own_commit_element; + VOID *peer_commit_element; + VOID *pwe; + SAE_BN *sae_rand; + UINT32 prime_len; /* ellis */ + UINT32 order_len; /* ellis */ + VOID *group_info; + VOID *group_info_bi; + SAE_BN *prime; + SAE_BN *order; + UCHAR *anti_clogging_token; + UINT32 anti_clogging_token_len; + USHORT peer_send_confirm; + UCHAR need_recalculate_key; + const SAE_GROUP_OP *group_op; + SAE_TIME_INTERVAL sae_cost_time; + + UCHAR valid; + UCHAR removable; + RALINK_TIMER_STRUCT sae_retry_timer; + /* Each instance of the protocol is identified by a tuple consisting of the local MAC address and the peer MAC address */ + UCHAR own_mac[MAC_ADDR_LEN]; + UCHAR peer_mac[MAC_ADDR_LEN]; + UCHAR bssid[MAC_ADDR_LEN]; + UCHAR *psk; + SAE_INSTANCE *same_mac_ins; + SAE_CFG *pParentSaeCfg; +}; + + +struct __SAE_CFG { + SAE_INSTANCE sae_ins[MAX_LEN_OF_MAC_TABLE]; + UCHAR support_group[MAX_SIZE_OF_ALLOWED_GROUP]; + UINT32 open; + UINT32 total_ins; + ULONG last_token_key_time; + UCHAR token_key[SAE_TOKEN_KEY_LEN]; + UINT32 sae_anti_clogging_threshold; + ULONG dot11RSNASAERetransPeriod; + struct _RTMP_ADAPTER *pAd; + NDIS_SPIN_LOCK sae_cfg_lock; +}; + +typedef struct __BIG_INTEGER_EC_POINT { + SAE_BN *x; + SAE_BN *y; + SAE_BN *z; + UCHAR z_is_one; +} BIG_INTEGER_EC_POINT, *PBIG_INTEGER_EC_POINT; + +#ifdef group_related +/* + ===================================== + group related + ===================================== +*/ +#endif + + + + +#ifdef FFC_group_related +/* + ===================================== + FFC group related + ===================================== +*/ +#endif + +/* RFC 4306, B.1. Group 1 - 768 Bit MODP + * Generator: 2 + * Prime: 2^768 - 2 ^704 - 1 + 2^64 * { [2^638 pi] + 149686 } + */ +static const UCHAR dh_group1_generator[1] = { 0x02 }; +static const UCHAR dh_group1_prime[96] = { + 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, 0x3A, 0x36, 0x20, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const UCHAR dh_group1_order[96] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, + 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, + 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, + 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, + 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, + 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, + 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, + 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, + 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, + 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1D, 0x1B, 0x10, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +/* RFC 4306, B.2. Group 2 - 1024 Bit MODP + * Generator: 2 + * Prime: 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 } + */ +static const UCHAR dh_group2_generator[1] = { 0x02 }; +static const UCHAR dh_group2_prime[128] = { + 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, 0xE6, 0x53, 0x81, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const UCHAR dh_group2_order[128] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, + 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, + 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, + 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, + 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, + 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, + 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, + 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, + 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, + 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5, + 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6, + 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, + 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, + 0x24, 0x94, 0x33, 0x28, 0xF6, 0x73, 0x29, 0xC0, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +/* RFC 3526, 2. Group 5 - 1536 Bit MODP + * Generator: 2 + * Prime: 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 } + */ +static const UCHAR dh_group5_generator[1] = { 0x02 }; +static const UCHAR dh_group5_prime[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 const UCHAR dh_group5_order[192] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, + 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, + 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, + 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, + 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, + 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, + 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, + 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, + 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, + 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5, + 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6, + 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, + 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, + 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E, + 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82, + 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD, + 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF, + 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB, + 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, + 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, + 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02, + 0x78, 0xBA, 0x36, 0x04, 0x65, 0x11, 0xB9, 0x93, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +/* RFC 3526, 3. Group 14 - 2048 Bit MODP + * Generator: 2 + * Prime: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 } + */ +static const UCHAR dh_group14_generator[1] = { 0x02 }; +static const UCHAR dh_group14_prime[256] = { + 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, 0x18, 0x21, 0x7C, + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const UCHAR dh_group14_order[256] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, + 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, + 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, + 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, + 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, + 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, + 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, + 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, + 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, + 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5, + 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6, + 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, + 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, + 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E, + 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82, + 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD, + 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF, + 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB, + 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, + 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, + 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02, + 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, 0x10, 0xBE, + 0x19, 0x48, 0x2F, 0x23, 0x17, 0x1B, 0x67, 0x1D, + 0xF1, 0xCF, 0x3B, 0x96, 0x0C, 0x07, 0x43, 0x01, + 0xCD, 0x93, 0xC1, 0xD1, 0x76, 0x03, 0xD1, 0x47, + 0xDA, 0xE2, 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64, + 0xEF, 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C, + 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, 0x72, + 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, 0x02, 0x88, + 0x0A, 0xB9, 0x47, 0x2D, 0x45, 0x56, 0x55, 0x34, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +/* RFC 3526, 4. Group 15 - 3072 Bit MODP + * Generator: 2 + * Prime: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 } + */ +static const UCHAR dh_group15_generator[1] = { 0x02 }; +static const UCHAR dh_group15_prime[384] = { + 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, 0x18, 0x21, 0x7C, + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const UCHAR dh_group15_order[384] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, + 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, + 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, + 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, + 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, + 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, + 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, + 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, + 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, + 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5, + 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6, + 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, + 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, + 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E, + 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82, + 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD, + 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF, + 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB, + 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, + 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, + 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02, + 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, 0x10, 0xBE, + 0x19, 0x48, 0x2F, 0x23, 0x17, 0x1B, 0x67, 0x1D, + 0xF1, 0xCF, 0x3B, 0x96, 0x0C, 0x07, 0x43, 0x01, + 0xCD, 0x93, 0xC1, 0xD1, 0x76, 0x03, 0xD1, 0x47, + 0xDA, 0xE2, 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64, + 0xEF, 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C, + 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, 0x72, + 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, 0x02, 0x88, + 0x0A, 0xB9, 0x47, 0x2D, 0x45, 0x55, 0x62, 0x16, + 0xD6, 0x99, 0x8B, 0x86, 0x82, 0x28, 0x3D, 0x19, + 0xD4, 0x2A, 0x90, 0xD5, 0xEF, 0x8E, 0x5D, 0x32, + 0x76, 0x7D, 0xC2, 0x82, 0x2C, 0x6D, 0xF7, 0x85, + 0x45, 0x75, 0x38, 0xAB, 0xAE, 0x83, 0x06, 0x3E, + 0xD9, 0xCB, 0x87, 0xC2, 0xD3, 0x70, 0xF2, 0x63, + 0xD5, 0xFA, 0xD7, 0x46, 0x6D, 0x84, 0x99, 0xEB, + 0x8F, 0x46, 0x4A, 0x70, 0x25, 0x12, 0xB0, 0xCE, + 0xE7, 0x71, 0xE9, 0x13, 0x0D, 0x69, 0x77, 0x35, + 0xF8, 0x97, 0xFD, 0x03, 0x6C, 0xC5, 0x04, 0x32, + 0x6C, 0x3B, 0x01, 0x39, 0x9F, 0x64, 0x35, 0x32, + 0x29, 0x0F, 0x95, 0x8C, 0x0B, 0xBD, 0x90, 0x06, + 0x5D, 0xF0, 0x8B, 0xAB, 0xBD, 0x30, 0xAE, 0xB6, + 0x3B, 0x84, 0xC4, 0x60, 0x5D, 0x6C, 0xA3, 0x71, + 0x04, 0x71, 0x27, 0xD0, 0x3A, 0x72, 0xD5, 0x98, + 0xA1, 0xED, 0xAD, 0xFE, 0x70, 0x7E, 0x88, 0x47, + 0x25, 0xC1, 0x68, 0x90, 0x54, 0x9D, 0x69, 0x65, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +/* RFC 3526, 5. Group 16 - 4096 Bit MODP + * Generator: 2 + * Prime: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 } + */ +static const UCHAR dh_group16_generator[1] = { 0x02 }; +static const UCHAR dh_group16_prime[512] = { + 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, 0x18, 0x21, 0x7C, + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, + 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, + 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, + 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, + 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, + 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, + 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, + 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, + 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, + 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, + 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, + 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, + 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, + 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, + 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, + 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, + 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const UCHAR dh_group16_order[512] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, + 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, + 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, + 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, + 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, + 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, + 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, + 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, + 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, + 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5, + 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6, + 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, + 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, + 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E, + 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82, + 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD, + 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF, + 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB, + 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, + 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, + 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02, + 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, 0x10, 0xBE, + 0x19, 0x48, 0x2F, 0x23, 0x17, 0x1B, 0x67, 0x1D, + 0xF1, 0xCF, 0x3B, 0x96, 0x0C, 0x07, 0x43, 0x01, + 0xCD, 0x93, 0xC1, 0xD1, 0x76, 0x03, 0xD1, 0x47, + 0xDA, 0xE2, 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64, + 0xEF, 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C, + 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, 0x72, + 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, 0x02, 0x88, + 0x0A, 0xB9, 0x47, 0x2D, 0x45, 0x55, 0x62, 0x16, + 0xD6, 0x99, 0x8B, 0x86, 0x82, 0x28, 0x3D, 0x19, + 0xD4, 0x2A, 0x90, 0xD5, 0xEF, 0x8E, 0x5D, 0x32, + 0x76, 0x7D, 0xC2, 0x82, 0x2C, 0x6D, 0xF7, 0x85, + 0x45, 0x75, 0x38, 0xAB, 0xAE, 0x83, 0x06, 0x3E, + 0xD9, 0xCB, 0x87, 0xC2, 0xD3, 0x70, 0xF2, 0x63, + 0xD5, 0xFA, 0xD7, 0x46, 0x6D, 0x84, 0x99, 0xEB, + 0x8F, 0x46, 0x4A, 0x70, 0x25, 0x12, 0xB0, 0xCE, + 0xE7, 0x71, 0xE9, 0x13, 0x0D, 0x69, 0x77, 0x35, + 0xF8, 0x97, 0xFD, 0x03, 0x6C, 0xC5, 0x04, 0x32, + 0x6C, 0x3B, 0x01, 0x39, 0x9F, 0x64, 0x35, 0x32, + 0x29, 0x0F, 0x95, 0x8C, 0x0B, 0xBD, 0x90, 0x06, + 0x5D, 0xF0, 0x8B, 0xAB, 0xBD, 0x30, 0xAE, 0xB6, + 0x3B, 0x84, 0xC4, 0x60, 0x5D, 0x6C, 0xA3, 0x71, + 0x04, 0x71, 0x27, 0xD0, 0x3A, 0x72, 0xD5, 0x98, + 0xA1, 0xED, 0xAD, 0xFE, 0x70, 0x7E, 0x88, 0x47, + 0x25, 0xC1, 0x68, 0x90, 0x54, 0x90, 0x84, 0x00, + 0x8D, 0x39, 0x1E, 0x09, 0x53, 0xC3, 0xF3, 0x6B, + 0xC4, 0x38, 0xCD, 0x08, 0x5E, 0xDD, 0x2D, 0x93, + 0x4C, 0xE1, 0x93, 0x8C, 0x35, 0x7A, 0x71, 0x1E, + 0x0D, 0x4A, 0x34, 0x1A, 0x5B, 0x0A, 0x85, 0xED, + 0x12, 0xC1, 0xF4, 0xE5, 0x15, 0x6A, 0x26, 0x74, + 0x6D, 0xDD, 0xE1, 0x6D, 0x82, 0x6F, 0x47, 0x7C, + 0x97, 0x47, 0x7E, 0x0A, 0x0F, 0xDF, 0x65, 0x53, + 0x14, 0x3E, 0x2C, 0xA3, 0xA7, 0x35, 0xE0, 0x2E, + 0xCC, 0xD9, 0x4B, 0x27, 0xD0, 0x48, 0x61, 0xD1, + 0x11, 0x9D, 0xD0, 0xC3, 0x28, 0xAD, 0xF3, 0xF6, + 0x8F, 0xB0, 0x94, 0xB8, 0x67, 0x71, 0x6B, 0xD7, + 0xDC, 0x0D, 0xEE, 0xBB, 0x10, 0xB8, 0x24, 0x0E, + 0x68, 0x03, 0x48, 0x93, 0xEA, 0xD8, 0x2D, 0x54, + 0xC9, 0xDA, 0x75, 0x4C, 0x46, 0xC7, 0xEE, 0xE0, + 0xC3, 0x7F, 0xDB, 0xEE, 0x48, 0x53, 0x60, 0x47, + 0xA6, 0xFA, 0x1A, 0xE4, 0x9A, 0x03, 0x18, 0xCC, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +/* RFC 3526, 6. Group 17 - 6144 Bit MODP + * Generator: 2 + * Prime: 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 } + */ +static const UCHAR dh_group17_generator[1] = { 0x02 }; +static const UCHAR dh_group17_prime[768] = { + 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, 0x18, 0x21, 0x7C, + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, + 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, + 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, + 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, + 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, + 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, + 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, + 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, + 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, + 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, + 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, + 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, + 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, + 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, + 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, + 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, + 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, + 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, + 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, + 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, + 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, + 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, + 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, + 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, + 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, + 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, + 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, + 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, + 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, + 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, + 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, + 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, + 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, + 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, + 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, + 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, + 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, + 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, + 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, + 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, + 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, + 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, + 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, + 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, + 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, + 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, + 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, + 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, + 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xCC, 0x40, 0x24, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const UCHAR dh_group17_order[768] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, + 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, + 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, + 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, + 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, + 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, + 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, + 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, + 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, + 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5, + 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6, + 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, + 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, + 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E, + 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82, + 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD, + 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF, + 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB, + 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, + 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, + 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02, + 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, 0x10, 0xBE, + 0x19, 0x48, 0x2F, 0x23, 0x17, 0x1B, 0x67, 0x1D, + 0xF1, 0xCF, 0x3B, 0x96, 0x0C, 0x07, 0x43, 0x01, + 0xCD, 0x93, 0xC1, 0xD1, 0x76, 0x03, 0xD1, 0x47, + 0xDA, 0xE2, 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64, + 0xEF, 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C, + 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, 0x72, + 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, 0x02, 0x88, + 0x0A, 0xB9, 0x47, 0x2D, 0x45, 0x55, 0x62, 0x16, + 0xD6, 0x99, 0x8B, 0x86, 0x82, 0x28, 0x3D, 0x19, + 0xD4, 0x2A, 0x90, 0xD5, 0xEF, 0x8E, 0x5D, 0x32, + 0x76, 0x7D, 0xC2, 0x82, 0x2C, 0x6D, 0xF7, 0x85, + 0x45, 0x75, 0x38, 0xAB, 0xAE, 0x83, 0x06, 0x3E, + 0xD9, 0xCB, 0x87, 0xC2, 0xD3, 0x70, 0xF2, 0x63, + 0xD5, 0xFA, 0xD7, 0x46, 0x6D, 0x84, 0x99, 0xEB, + 0x8F, 0x46, 0x4A, 0x70, 0x25, 0x12, 0xB0, 0xCE, + 0xE7, 0x71, 0xE9, 0x13, 0x0D, 0x69, 0x77, 0x35, + 0xF8, 0x97, 0xFD, 0x03, 0x6C, 0xC5, 0x04, 0x32, + 0x6C, 0x3B, 0x01, 0x39, 0x9F, 0x64, 0x35, 0x32, + 0x29, 0x0F, 0x95, 0x8C, 0x0B, 0xBD, 0x90, 0x06, + 0x5D, 0xF0, 0x8B, 0xAB, 0xBD, 0x30, 0xAE, 0xB6, + 0x3B, 0x84, 0xC4, 0x60, 0x5D, 0x6C, 0xA3, 0x71, + 0x04, 0x71, 0x27, 0xD0, 0x3A, 0x72, 0xD5, 0x98, + 0xA1, 0xED, 0xAD, 0xFE, 0x70, 0x7E, 0x88, 0x47, + 0x25, 0xC1, 0x68, 0x90, 0x54, 0x90, 0x84, 0x00, + 0x8D, 0x39, 0x1E, 0x09, 0x53, 0xC3, 0xF3, 0x6B, + 0xC4, 0x38, 0xCD, 0x08, 0x5E, 0xDD, 0x2D, 0x93, + 0x4C, 0xE1, 0x93, 0x8C, 0x35, 0x7A, 0x71, 0x1E, + 0x0D, 0x4A, 0x34, 0x1A, 0x5B, 0x0A, 0x85, 0xED, + 0x12, 0xC1, 0xF4, 0xE5, 0x15, 0x6A, 0x26, 0x74, + 0x6D, 0xDD, 0xE1, 0x6D, 0x82, 0x6F, 0x47, 0x7C, + 0x97, 0x47, 0x7E, 0x0A, 0x0F, 0xDF, 0x65, 0x53, + 0x14, 0x3E, 0x2C, 0xA3, 0xA7, 0x35, 0xE0, 0x2E, + 0xCC, 0xD9, 0x4B, 0x27, 0xD0, 0x48, 0x61, 0xD1, + 0x11, 0x9D, 0xD0, 0xC3, 0x28, 0xAD, 0xF3, 0xF6, + 0x8F, 0xB0, 0x94, 0xB8, 0x67, 0x71, 0x6B, 0xD7, + 0xDC, 0x0D, 0xEE, 0xBB, 0x10, 0xB8, 0x24, 0x0E, + 0x68, 0x03, 0x48, 0x93, 0xEA, 0xD8, 0x2D, 0x54, + 0xC9, 0xDA, 0x75, 0x4C, 0x46, 0xC7, 0xEE, 0xE0, + 0xC3, 0x7F, 0xDB, 0xEE, 0x48, 0x53, 0x60, 0x47, + 0xA6, 0xFA, 0x1A, 0xE4, 0x9A, 0x01, 0x42, 0x49, + 0x1B, 0x61, 0xFD, 0x5A, 0x69, 0x3E, 0x38, 0x13, + 0x60, 0xEA, 0x6E, 0x59, 0x30, 0x13, 0x23, 0x6F, + 0x64, 0xBA, 0x8F, 0x3B, 0x1E, 0xDD, 0x1B, 0xDE, + 0xFC, 0x7F, 0xCA, 0x03, 0x56, 0xCF, 0x29, 0x87, + 0x72, 0xED, 0x9C, 0x17, 0xA0, 0x98, 0x00, 0xD7, + 0x58, 0x35, 0x29, 0xF6, 0xC8, 0x13, 0xEC, 0x18, + 0x8B, 0xCB, 0x93, 0xD8, 0x43, 0x2D, 0x44, 0x8C, + 0x6D, 0x1F, 0x6D, 0xF5, 0xE7, 0xCD, 0x8A, 0x76, + 0xA2, 0x67, 0x36, 0x5D, 0x67, 0x6A, 0x5D, 0x8D, + 0xED, 0xBF, 0x8A, 0x23, 0xF3, 0x66, 0x12, 0xA5, + 0x99, 0x90, 0x28, 0xA8, 0x95, 0xEB, 0xD7, 0xA1, + 0x37, 0xDC, 0x7A, 0x00, 0x9B, 0xC6, 0x69, 0x5F, + 0xAC, 0xC1, 0xE5, 0x00, 0xE3, 0x25, 0xC9, 0x76, + 0x78, 0x19, 0x75, 0x0A, 0xE8, 0xB9, 0x0E, 0x81, + 0xFA, 0x41, 0x6B, 0xE7, 0x37, 0x3A, 0x7F, 0x7B, + 0x6A, 0xAF, 0x38, 0x17, 0xA3, 0x4C, 0x06, 0x41, + 0x5A, 0xD4, 0x20, 0x18, 0xC8, 0x05, 0x8E, 0x4F, + 0x2C, 0xF3, 0xE4, 0xBF, 0xDF, 0x63, 0xF4, 0x79, + 0x91, 0xD4, 0xBD, 0x3F, 0x1B, 0x66, 0x44, 0x5F, + 0x07, 0x8E, 0xA2, 0xDB, 0xFF, 0xAC, 0x2D, 0x62, + 0xA5, 0xEA, 0x03, 0xD9, 0x15, 0xA0, 0xAA, 0x55, + 0x66, 0x47, 0xB6, 0xBF, 0x5F, 0xA4, 0x70, 0xEC, + 0x0A, 0x66, 0x2F, 0x69, 0x07, 0xC0, 0x1B, 0xF0, + 0x53, 0xCB, 0x8A, 0xF7, 0x79, 0x4D, 0xF1, 0x94, + 0x03, 0x50, 0xEA, 0xC5, 0xDB, 0xE2, 0xED, 0x3B, + 0x7A, 0xA8, 0x55, 0x1E, 0xC5, 0x0F, 0xDF, 0xF8, + 0x75, 0x8C, 0xE6, 0x58, 0xD1, 0x89, 0xEA, 0xAE, + 0x6D, 0x2B, 0x64, 0xF6, 0x17, 0x79, 0x4B, 0x19, + 0x1C, 0x3F, 0xF4, 0x6B, 0xB7, 0x1E, 0x02, 0x34, + 0x02, 0x1F, 0x47, 0xB3, 0x1F, 0xA4, 0x30, 0x77, + 0x09, 0x5F, 0x96, 0xAD, 0x85, 0xBA, 0x3A, 0x6B, + 0x73, 0x4A, 0x7C, 0x8F, 0x36, 0xE6, 0x20, 0x12, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +/* RFC 3526, 7. Group 18 - 8192 Bit MODP + * Generator: 2 + * Prime: 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 } + */ +static const UCHAR dh_group18_generator[1] = { 0x02 }; +static const UCHAR dh_group18_prime[1024] = { + 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, 0x18, 0x21, 0x7C, + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, + 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, + 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, + 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, + 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, + 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, + 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, + 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, + 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, + 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, + 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, + 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, + 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, + 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, + 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, + 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, + 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, + 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, + 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, + 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, + 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, + 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, + 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, + 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, + 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, + 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, + 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, + 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, + 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, + 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, + 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, + 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, + 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, + 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, + 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, + 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, + 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, + 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, + 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, + 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, + 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, + 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, + 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, + 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, + 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, + 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, + 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, + 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, + 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59, + 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4, + 0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, + 0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA, + 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00, + 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, + 0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66, + 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68, + 0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, + 0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D, + 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9, + 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, + 0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7, + 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B, + 0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, + 0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8, + 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A, + 0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, + 0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D, + 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36, + 0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, + 0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D, + 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1, + 0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, + 0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68, + 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92, + 0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, + 0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B, + 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47, + 0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, + 0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF, + 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71, + 0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const UCHAR dh_group18_order[1024] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, + 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, + 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, + 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, + 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, + 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, + 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, + 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, + 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, + 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5, + 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6, + 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, + 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, + 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E, + 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82, + 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD, + 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF, + 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB, + 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, + 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, + 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02, + 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, 0x10, 0xBE, + 0x19, 0x48, 0x2F, 0x23, 0x17, 0x1B, 0x67, 0x1D, + 0xF1, 0xCF, 0x3B, 0x96, 0x0C, 0x07, 0x43, 0x01, + 0xCD, 0x93, 0xC1, 0xD1, 0x76, 0x03, 0xD1, 0x47, + 0xDA, 0xE2, 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64, + 0xEF, 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C, + 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, 0x72, + 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, 0x02, 0x88, + 0x0A, 0xB9, 0x47, 0x2D, 0x45, 0x55, 0x62, 0x16, + 0xD6, 0x99, 0x8B, 0x86, 0x82, 0x28, 0x3D, 0x19, + 0xD4, 0x2A, 0x90, 0xD5, 0xEF, 0x8E, 0x5D, 0x32, + 0x76, 0x7D, 0xC2, 0x82, 0x2C, 0x6D, 0xF7, 0x85, + 0x45, 0x75, 0x38, 0xAB, 0xAE, 0x83, 0x06, 0x3E, + 0xD9, 0xCB, 0x87, 0xC2, 0xD3, 0x70, 0xF2, 0x63, + 0xD5, 0xFA, 0xD7, 0x46, 0x6D, 0x84, 0x99, 0xEB, + 0x8F, 0x46, 0x4A, 0x70, 0x25, 0x12, 0xB0, 0xCE, + 0xE7, 0x71, 0xE9, 0x13, 0x0D, 0x69, 0x77, 0x35, + 0xF8, 0x97, 0xFD, 0x03, 0x6C, 0xC5, 0x04, 0x32, + 0x6C, 0x3B, 0x01, 0x39, 0x9F, 0x64, 0x35, 0x32, + 0x29, 0x0F, 0x95, 0x8C, 0x0B, 0xBD, 0x90, 0x06, + 0x5D, 0xF0, 0x8B, 0xAB, 0xBD, 0x30, 0xAE, 0xB6, + 0x3B, 0x84, 0xC4, 0x60, 0x5D, 0x6C, 0xA3, 0x71, + 0x04, 0x71, 0x27, 0xD0, 0x3A, 0x72, 0xD5, 0x98, + 0xA1, 0xED, 0xAD, 0xFE, 0x70, 0x7E, 0x88, 0x47, + 0x25, 0xC1, 0x68, 0x90, 0x54, 0x90, 0x84, 0x00, + 0x8D, 0x39, 0x1E, 0x09, 0x53, 0xC3, 0xF3, 0x6B, + 0xC4, 0x38, 0xCD, 0x08, 0x5E, 0xDD, 0x2D, 0x93, + 0x4C, 0xE1, 0x93, 0x8C, 0x35, 0x7A, 0x71, 0x1E, + 0x0D, 0x4A, 0x34, 0x1A, 0x5B, 0x0A, 0x85, 0xED, + 0x12, 0xC1, 0xF4, 0xE5, 0x15, 0x6A, 0x26, 0x74, + 0x6D, 0xDD, 0xE1, 0x6D, 0x82, 0x6F, 0x47, 0x7C, + 0x97, 0x47, 0x7E, 0x0A, 0x0F, 0xDF, 0x65, 0x53, + 0x14, 0x3E, 0x2C, 0xA3, 0xA7, 0x35, 0xE0, 0x2E, + 0xCC, 0xD9, 0x4B, 0x27, 0xD0, 0x48, 0x61, 0xD1, + 0x11, 0x9D, 0xD0, 0xC3, 0x28, 0xAD, 0xF3, 0xF6, + 0x8F, 0xB0, 0x94, 0xB8, 0x67, 0x71, 0x6B, 0xD7, + 0xDC, 0x0D, 0xEE, 0xBB, 0x10, 0xB8, 0x24, 0x0E, + 0x68, 0x03, 0x48, 0x93, 0xEA, 0xD8, 0x2D, 0x54, + 0xC9, 0xDA, 0x75, 0x4C, 0x46, 0xC7, 0xEE, 0xE0, + 0xC3, 0x7F, 0xDB, 0xEE, 0x48, 0x53, 0x60, 0x47, + 0xA6, 0xFA, 0x1A, 0xE4, 0x9A, 0x01, 0x42, 0x49, + 0x1B, 0x61, 0xFD, 0x5A, 0x69, 0x3E, 0x38, 0x13, + 0x60, 0xEA, 0x6E, 0x59, 0x30, 0x13, 0x23, 0x6F, + 0x64, 0xBA, 0x8F, 0x3B, 0x1E, 0xDD, 0x1B, 0xDE, + 0xFC, 0x7F, 0xCA, 0x03, 0x56, 0xCF, 0x29, 0x87, + 0x72, 0xED, 0x9C, 0x17, 0xA0, 0x98, 0x00, 0xD7, + 0x58, 0x35, 0x29, 0xF6, 0xC8, 0x13, 0xEC, 0x18, + 0x8B, 0xCB, 0x93, 0xD8, 0x43, 0x2D, 0x44, 0x8C, + 0x6D, 0x1F, 0x6D, 0xF5, 0xE7, 0xCD, 0x8A, 0x76, + 0xA2, 0x67, 0x36, 0x5D, 0x67, 0x6A, 0x5D, 0x8D, + 0xED, 0xBF, 0x8A, 0x23, 0xF3, 0x66, 0x12, 0xA5, + 0x99, 0x90, 0x28, 0xA8, 0x95, 0xEB, 0xD7, 0xA1, + 0x37, 0xDC, 0x7A, 0x00, 0x9B, 0xC6, 0x69, 0x5F, + 0xAC, 0xC1, 0xE5, 0x00, 0xE3, 0x25, 0xC9, 0x76, + 0x78, 0x19, 0x75, 0x0A, 0xE8, 0xB9, 0x0E, 0x81, + 0xFA, 0x41, 0x6B, 0xE7, 0x37, 0x3A, 0x7F, 0x7B, + 0x6A, 0xAF, 0x38, 0x17, 0xA3, 0x4C, 0x06, 0x41, + 0x5A, 0xD4, 0x20, 0x18, 0xC8, 0x05, 0x8E, 0x4F, + 0x2C, 0xF3, 0xE4, 0xBF, 0xDF, 0x63, 0xF4, 0x79, + 0x91, 0xD4, 0xBD, 0x3F, 0x1B, 0x66, 0x44, 0x5F, + 0x07, 0x8E, 0xA2, 0xDB, 0xFF, 0xAC, 0x2D, 0x62, + 0xA5, 0xEA, 0x03, 0xD9, 0x15, 0xA0, 0xAA, 0x55, + 0x66, 0x47, 0xB6, 0xBF, 0x5F, 0xA4, 0x70, 0xEC, + 0x0A, 0x66, 0x2F, 0x69, 0x07, 0xC0, 0x1B, 0xF0, + 0x53, 0xCB, 0x8A, 0xF7, 0x79, 0x4D, 0xF1, 0x94, + 0x03, 0x50, 0xEA, 0xC5, 0xDB, 0xE2, 0xED, 0x3B, + 0x7A, 0xA8, 0x55, 0x1E, 0xC5, 0x0F, 0xDF, 0xF8, + 0x75, 0x8C, 0xE6, 0x58, 0xD1, 0x89, 0xEA, 0xAE, + 0x6D, 0x2B, 0x64, 0xF6, 0x17, 0x79, 0x4B, 0x19, + 0x1C, 0x3F, 0xF4, 0x6B, 0xB7, 0x1E, 0x02, 0x34, + 0x02, 0x1F, 0x47, 0xB3, 0x1F, 0xA4, 0x30, 0x77, + 0x09, 0x5F, 0x96, 0xAD, 0x85, 0xBA, 0x3A, 0x6B, + 0x73, 0x4A, 0x7C, 0x8F, 0x36, 0xDF, 0x08, 0xAC, + 0xBA, 0x51, 0xC9, 0x37, 0x89, 0x7F, 0x72, 0xF2, + 0x1C, 0x3B, 0xBE, 0x5B, 0x54, 0x99, 0x6F, 0xC6, + 0x6C, 0x5F, 0x62, 0x68, 0x39, 0xDC, 0x98, 0xDD, + 0x1D, 0xE4, 0x19, 0x5B, 0x46, 0xCE, 0xE9, 0x80, + 0x3A, 0x0F, 0xD3, 0xDF, 0xC5, 0x7E, 0x23, 0xF6, + 0x92, 0xBB, 0x7B, 0x49, 0xB5, 0xD2, 0x12, 0x33, + 0x1D, 0x55, 0xB1, 0xCE, 0x2D, 0x72, 0x7A, 0xB4, + 0x1A, 0x11, 0xDA, 0x3A, 0x15, 0xF8, 0xE4, 0xBC, + 0x11, 0xC7, 0x8B, 0x65, 0xF1, 0xCE, 0xB2, 0x96, + 0xF1, 0xFE, 0xDC, 0x5F, 0x7E, 0x42, 0x45, 0x6C, + 0x91, 0x11, 0x17, 0x02, 0x52, 0x01, 0xBE, 0x03, + 0x89, 0xF5, 0xAB, 0xD4, 0x0D, 0x11, 0xF8, 0x63, + 0x9A, 0x39, 0xFE, 0x32, 0x36, 0x75, 0x18, 0x35, + 0xA5, 0xE5, 0xE4, 0x43, 0x17, 0xC1, 0xC2, 0xEE, + 0xFD, 0x4E, 0xA5, 0xBF, 0xD1, 0x60, 0x43, 0xF4, + 0x3C, 0xB4, 0x19, 0x81, 0xF6, 0xAD, 0xEE, 0x9D, + 0x03, 0x15, 0x9E, 0x7A, 0xD9, 0xD1, 0x3C, 0x53, + 0x36, 0x95, 0x09, 0xFC, 0x1F, 0xA2, 0x7C, 0x16, + 0xEF, 0x98, 0x87, 0x70, 0x3A, 0x55, 0xB5, 0x1B, + 0x22, 0xCB, 0xF4, 0x4C, 0xD0, 0x12, 0xAE, 0xE0, + 0xB2, 0x79, 0x8E, 0x62, 0x84, 0x23, 0x42, 0x8E, + 0xFC, 0xD5, 0xA4, 0x0C, 0xAE, 0xF6, 0xBF, 0x50, + 0xD8, 0xEA, 0x88, 0x5E, 0xBF, 0x73, 0xA6, 0xB9, + 0xFD, 0x79, 0xB5, 0xE1, 0x8F, 0x67, 0xD1, 0x34, + 0x1A, 0xC8, 0x23, 0x7A, 0x75, 0xC3, 0xCF, 0xC9, + 0x20, 0x04, 0xA1, 0xC5, 0xA4, 0x0E, 0x36, 0x6B, + 0xC4, 0x4D, 0x00, 0x17, 0x6A, 0xF7, 0x1C, 0x15, + 0xE4, 0x8C, 0x86, 0xD3, 0x7E, 0x01, 0x37, 0x23, + 0xCA, 0xAC, 0x72, 0x23, 0xAB, 0x3B, 0xF4, 0xD5, + 0x4F, 0x18, 0x28, 0x71, 0x3B, 0x2B, 0x4A, 0x6F, + 0xE4, 0x0F, 0xAB, 0x74, 0x40, 0x5C, 0xB7, 0x38, + 0xB0, 0x64, 0xC0, 0x6E, 0xCC, 0x76, 0xE9, 0xEF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +/* + * RFC 5114, 2.1. + * Group 22 - 1024-bit MODP Group with 160-bit Prime Order Subgroup + */ +static const UCHAR dh_group22_generator[] = { + 0xA4, 0xD1, 0xCB, 0xD5, 0xC3, 0xFD, 0x34, 0x12, + 0x67, 0x65, 0xA4, 0x42, 0xEF, 0xB9, 0x99, 0x05, + 0xF8, 0x10, 0x4D, 0xD2, 0x58, 0xAC, 0x50, 0x7F, + 0xD6, 0x40, 0x6C, 0xFF, 0x14, 0x26, 0x6D, 0x31, + 0x26, 0x6F, 0xEA, 0x1E, 0x5C, 0x41, 0x56, 0x4B, + 0x77, 0x7E, 0x69, 0x0F, 0x55, 0x04, 0xF2, 0x13, + 0x16, 0x02, 0x17, 0xB4, 0xB0, 0x1B, 0x88, 0x6A, + 0x5E, 0x91, 0x54, 0x7F, 0x9E, 0x27, 0x49, 0xF4, + 0xD7, 0xFB, 0xD7, 0xD3, 0xB9, 0xA9, 0x2E, 0xE1, + 0x90, 0x9D, 0x0D, 0x22, 0x63, 0xF8, 0x0A, 0x76, + 0xA6, 0xA2, 0x4C, 0x08, 0x7A, 0x09, 0x1F, 0x53, + 0x1D, 0xBF, 0x0A, 0x01, 0x69, 0xB6, 0xA2, 0x8A, + 0xD6, 0x62, 0xA4, 0xD1, 0x8E, 0x73, 0xAF, 0xA3, + 0x2D, 0x77, 0x9D, 0x59, 0x18, 0xD0, 0x8B, 0xC8, + 0x85, 0x8F, 0x4D, 0xCE, 0xF9, 0x7C, 0x2A, 0x24, + 0x85, 0x5E, 0x6E, 0xEB, 0x22, 0xB3, 0xB2, 0xE5 +}; +static const UCHAR dh_group22_prime[] = { + 0xB1, 0x0B, 0x8F, 0x96, 0xA0, 0x80, 0xE0, 0x1D, + 0xDE, 0x92, 0xDE, 0x5E, 0xAE, 0x5D, 0x54, 0xEC, + 0x52, 0xC9, 0x9F, 0xBC, 0xFB, 0x06, 0xA3, 0xC6, + 0x9A, 0x6A, 0x9D, 0xCA, 0x52, 0xD2, 0x3B, 0x61, + 0x60, 0x73, 0xE2, 0x86, 0x75, 0xA2, 0x3D, 0x18, + 0x98, 0x38, 0xEF, 0x1E, 0x2E, 0xE6, 0x52, 0xC0, + 0x13, 0xEC, 0xB4, 0xAE, 0xA9, 0x06, 0x11, 0x23, + 0x24, 0x97, 0x5C, 0x3C, 0xD4, 0x9B, 0x83, 0xBF, + 0xAC, 0xCB, 0xDD, 0x7D, 0x90, 0xC4, 0xBD, 0x70, + 0x98, 0x48, 0x8E, 0x9C, 0x21, 0x9A, 0x73, 0x72, + 0x4E, 0xFF, 0xD6, 0xFA, 0xE5, 0x64, 0x47, 0x38, + 0xFA, 0xA3, 0x1A, 0x4F, 0xF5, 0x5B, 0xCC, 0xC0, + 0xA1, 0x51, 0xAF, 0x5F, 0x0D, 0xC8, 0xB4, 0xBD, + 0x45, 0xBF, 0x37, 0xDF, 0x36, 0x5C, 0x1A, 0x65, + 0xE6, 0x8C, 0xFD, 0xA7, 0x6D, 0x4D, 0xA7, 0x08, + 0xDF, 0x1F, 0xB2, 0xBC, 0x2E, 0x4A, 0x43, 0x71 +}; +static const UCHAR dh_group22_order[] = { + 0xF5, 0x18, 0xAA, 0x87, 0x81, 0xA8, 0xDF, 0x27, + 0x8A, 0xBA, 0x4E, 0x7D, 0x64, 0xB7, 0xCB, 0x9D, + 0x49, 0x46, 0x23, 0x53 +}; + +/* + * RFC 5114, 2.2. + * Group 23 - 2048-bit MODP Group with 224-bit Prime Order Subgroup + */ +static const UCHAR dh_group23_generator[] = { + 0xAC, 0x40, 0x32, 0xEF, 0x4F, 0x2D, 0x9A, 0xE3, + 0x9D, 0xF3, 0x0B, 0x5C, 0x8F, 0xFD, 0xAC, 0x50, + 0x6C, 0xDE, 0xBE, 0x7B, 0x89, 0x99, 0x8C, 0xAF, + 0x74, 0x86, 0x6A, 0x08, 0xCF, 0xE4, 0xFF, 0xE3, + 0xA6, 0x82, 0x4A, 0x4E, 0x10, 0xB9, 0xA6, 0xF0, + 0xDD, 0x92, 0x1F, 0x01, 0xA7, 0x0C, 0x4A, 0xFA, + 0xAB, 0x73, 0x9D, 0x77, 0x00, 0xC2, 0x9F, 0x52, + 0xC5, 0x7D, 0xB1, 0x7C, 0x62, 0x0A, 0x86, 0x52, + 0xBE, 0x5E, 0x90, 0x01, 0xA8, 0xD6, 0x6A, 0xD7, + 0xC1, 0x76, 0x69, 0x10, 0x19, 0x99, 0x02, 0x4A, + 0xF4, 0xD0, 0x27, 0x27, 0x5A, 0xC1, 0x34, 0x8B, + 0xB8, 0xA7, 0x62, 0xD0, 0x52, 0x1B, 0xC9, 0x8A, + 0xE2, 0x47, 0x15, 0x04, 0x22, 0xEA, 0x1E, 0xD4, + 0x09, 0x93, 0x9D, 0x54, 0xDA, 0x74, 0x60, 0xCD, + 0xB5, 0xF6, 0xC6, 0xB2, 0x50, 0x71, 0x7C, 0xBE, + 0xF1, 0x80, 0xEB, 0x34, 0x11, 0x8E, 0x98, 0xD1, + 0x19, 0x52, 0x9A, 0x45, 0xD6, 0xF8, 0x34, 0x56, + 0x6E, 0x30, 0x25, 0xE3, 0x16, 0xA3, 0x30, 0xEF, + 0xBB, 0x77, 0xA8, 0x6F, 0x0C, 0x1A, 0xB1, 0x5B, + 0x05, 0x1A, 0xE3, 0xD4, 0x28, 0xC8, 0xF8, 0xAC, + 0xB7, 0x0A, 0x81, 0x37, 0x15, 0x0B, 0x8E, 0xEB, + 0x10, 0xE1, 0x83, 0xED, 0xD1, 0x99, 0x63, 0xDD, + 0xD9, 0xE2, 0x63, 0xE4, 0x77, 0x05, 0x89, 0xEF, + 0x6A, 0xA2, 0x1E, 0x7F, 0x5F, 0x2F, 0xF3, 0x81, + 0xB5, 0x39, 0xCC, 0xE3, 0x40, 0x9D, 0x13, 0xCD, + 0x56, 0x6A, 0xFB, 0xB4, 0x8D, 0x6C, 0x01, 0x91, + 0x81, 0xE1, 0xBC, 0xFE, 0x94, 0xB3, 0x02, 0x69, + 0xED, 0xFE, 0x72, 0xFE, 0x9B, 0x6A, 0xA4, 0xBD, + 0x7B, 0x5A, 0x0F, 0x1C, 0x71, 0xCF, 0xFF, 0x4C, + 0x19, 0xC4, 0x18, 0xE1, 0xF6, 0xEC, 0x01, 0x79, + 0x81, 0xBC, 0x08, 0x7F, 0x2A, 0x70, 0x65, 0xB3, + 0x84, 0xB8, 0x90, 0xD3, 0x19, 0x1F, 0x2B, 0xFA +}; +static const UCHAR dh_group23_prime[] = { + 0xAD, 0x10, 0x7E, 0x1E, 0x91, 0x23, 0xA9, 0xD0, + 0xD6, 0x60, 0xFA, 0xA7, 0x95, 0x59, 0xC5, 0x1F, + 0xA2, 0x0D, 0x64, 0xE5, 0x68, 0x3B, 0x9F, 0xD1, + 0xB5, 0x4B, 0x15, 0x97, 0xB6, 0x1D, 0x0A, 0x75, + 0xE6, 0xFA, 0x14, 0x1D, 0xF9, 0x5A, 0x56, 0xDB, + 0xAF, 0x9A, 0x3C, 0x40, 0x7B, 0xA1, 0xDF, 0x15, + 0xEB, 0x3D, 0x68, 0x8A, 0x30, 0x9C, 0x18, 0x0E, + 0x1D, 0xE6, 0xB8, 0x5A, 0x12, 0x74, 0xA0, 0xA6, + 0x6D, 0x3F, 0x81, 0x52, 0xAD, 0x6A, 0xC2, 0x12, + 0x90, 0x37, 0xC9, 0xED, 0xEF, 0xDA, 0x4D, 0xF8, + 0xD9, 0x1E, 0x8F, 0xEF, 0x55, 0xB7, 0x39, 0x4B, + 0x7A, 0xD5, 0xB7, 0xD0, 0xB6, 0xC1, 0x22, 0x07, + 0xC9, 0xF9, 0x8D, 0x11, 0xED, 0x34, 0xDB, 0xF6, + 0xC6, 0xBA, 0x0B, 0x2C, 0x8B, 0xBC, 0x27, 0xBE, + 0x6A, 0x00, 0xE0, 0xA0, 0xB9, 0xC4, 0x97, 0x08, + 0xB3, 0xBF, 0x8A, 0x31, 0x70, 0x91, 0x88, 0x36, + 0x81, 0x28, 0x61, 0x30, 0xBC, 0x89, 0x85, 0xDB, + 0x16, 0x02, 0xE7, 0x14, 0x41, 0x5D, 0x93, 0x30, + 0x27, 0x82, 0x73, 0xC7, 0xDE, 0x31, 0xEF, 0xDC, + 0x73, 0x10, 0xF7, 0x12, 0x1F, 0xD5, 0xA0, 0x74, + 0x15, 0x98, 0x7D, 0x9A, 0xDC, 0x0A, 0x48, 0x6D, + 0xCD, 0xF9, 0x3A, 0xCC, 0x44, 0x32, 0x83, 0x87, + 0x31, 0x5D, 0x75, 0xE1, 0x98, 0xC6, 0x41, 0xA4, + 0x80, 0xCD, 0x86, 0xA1, 0xB9, 0xE5, 0x87, 0xE8, + 0xBE, 0x60, 0xE6, 0x9C, 0xC9, 0x28, 0xB2, 0xB9, + 0xC5, 0x21, 0x72, 0xE4, 0x13, 0x04, 0x2E, 0x9B, + 0x23, 0xF1, 0x0B, 0x0E, 0x16, 0xE7, 0x97, 0x63, + 0xC9, 0xB5, 0x3D, 0xCF, 0x4B, 0xA8, 0x0A, 0x29, + 0xE3, 0xFB, 0x73, 0xC1, 0x6B, 0x8E, 0x75, 0xB9, + 0x7E, 0xF3, 0x63, 0xE2, 0xFF, 0xA3, 0x1F, 0x71, + 0xCF, 0x9D, 0xE5, 0x38, 0x4E, 0x71, 0xB8, 0x1C, + 0x0A, 0xC4, 0xDF, 0xFE, 0x0C, 0x10, 0xE6, 0x4F +}; +static const UCHAR dh_group23_order[] = { + 0x80, 0x1C, 0x0D, 0x34, 0xC5, 0x8D, 0x93, 0xFE, + 0x99, 0x71, 0x77, 0x10, 0x1F, 0x80, 0x53, 0x5A, + 0x47, 0x38, 0xCE, 0xBC, 0xBF, 0x38, 0x9A, 0x99, + 0xB3, 0x63, 0x71, 0xEB +}; + +/* + * RFC 5114, 2.3. + * Group 24 - 2048-bit MODP Group with 256-bit Prime Order Subgroup + */ +static const UCHAR dh_group24_generator[] = { + 0x3F, 0xB3, 0x2C, 0x9B, 0x73, 0x13, 0x4D, 0x0B, + 0x2E, 0x77, 0x50, 0x66, 0x60, 0xED, 0xBD, 0x48, + 0x4C, 0xA7, 0xB1, 0x8F, 0x21, 0xEF, 0x20, 0x54, + 0x07, 0xF4, 0x79, 0x3A, 0x1A, 0x0B, 0xA1, 0x25, + 0x10, 0xDB, 0xC1, 0x50, 0x77, 0xBE, 0x46, 0x3F, + 0xFF, 0x4F, 0xED, 0x4A, 0xAC, 0x0B, 0xB5, 0x55, + 0xBE, 0x3A, 0x6C, 0x1B, 0x0C, 0x6B, 0x47, 0xB1, + 0xBC, 0x37, 0x73, 0xBF, 0x7E, 0x8C, 0x6F, 0x62, + 0x90, 0x12, 0x28, 0xF8, 0xC2, 0x8C, 0xBB, 0x18, + 0xA5, 0x5A, 0xE3, 0x13, 0x41, 0x00, 0x0A, 0x65, + 0x01, 0x96, 0xF9, 0x31, 0xC7, 0x7A, 0x57, 0xF2, + 0xDD, 0xF4, 0x63, 0xE5, 0xE9, 0xEC, 0x14, 0x4B, + 0x77, 0x7D, 0xE6, 0x2A, 0xAA, 0xB8, 0xA8, 0x62, + 0x8A, 0xC3, 0x76, 0xD2, 0x82, 0xD6, 0xED, 0x38, + 0x64, 0xE6, 0x79, 0x82, 0x42, 0x8E, 0xBC, 0x83, + 0x1D, 0x14, 0x34, 0x8F, 0x6F, 0x2F, 0x91, 0x93, + 0xB5, 0x04, 0x5A, 0xF2, 0x76, 0x71, 0x64, 0xE1, + 0xDF, 0xC9, 0x67, 0xC1, 0xFB, 0x3F, 0x2E, 0x55, + 0xA4, 0xBD, 0x1B, 0xFF, 0xE8, 0x3B, 0x9C, 0x80, + 0xD0, 0x52, 0xB9, 0x85, 0xD1, 0x82, 0xEA, 0x0A, + 0xDB, 0x2A, 0x3B, 0x73, 0x13, 0xD3, 0xFE, 0x14, + 0xC8, 0x48, 0x4B, 0x1E, 0x05, 0x25, 0x88, 0xB9, + 0xB7, 0xD2, 0xBB, 0xD2, 0xDF, 0x01, 0x61, 0x99, + 0xEC, 0xD0, 0x6E, 0x15, 0x57, 0xCD, 0x09, 0x15, + 0xB3, 0x35, 0x3B, 0xBB, 0x64, 0xE0, 0xEC, 0x37, + 0x7F, 0xD0, 0x28, 0x37, 0x0D, 0xF9, 0x2B, 0x52, + 0xC7, 0x89, 0x14, 0x28, 0xCD, 0xC6, 0x7E, 0xB6, + 0x18, 0x4B, 0x52, 0x3D, 0x1D, 0xB2, 0x46, 0xC3, + 0x2F, 0x63, 0x07, 0x84, 0x90, 0xF0, 0x0E, 0xF8, + 0xD6, 0x47, 0xD1, 0x48, 0xD4, 0x79, 0x54, 0x51, + 0x5E, 0x23, 0x27, 0xCF, 0xEF, 0x98, 0xC5, 0x82, + 0x66, 0x4B, 0x4C, 0x0F, 0x6C, 0xC4, 0x16, 0x59 +}; +static const UCHAR dh_group24_prime[] = { + 0x87, 0xA8, 0xE6, 0x1D, 0xB4, 0xB6, 0x66, 0x3C, + 0xFF, 0xBB, 0xD1, 0x9C, 0x65, 0x19, 0x59, 0x99, + 0x8C, 0xEE, 0xF6, 0x08, 0x66, 0x0D, 0xD0, 0xF2, + 0x5D, 0x2C, 0xEE, 0xD4, 0x43, 0x5E, 0x3B, 0x00, + 0xE0, 0x0D, 0xF8, 0xF1, 0xD6, 0x19, 0x57, 0xD4, + 0xFA, 0xF7, 0xDF, 0x45, 0x61, 0xB2, 0xAA, 0x30, + 0x16, 0xC3, 0xD9, 0x11, 0x34, 0x09, 0x6F, 0xAA, + 0x3B, 0xF4, 0x29, 0x6D, 0x83, 0x0E, 0x9A, 0x7C, + 0x20, 0x9E, 0x0C, 0x64, 0x97, 0x51, 0x7A, 0xBD, + 0x5A, 0x8A, 0x9D, 0x30, 0x6B, 0xCF, 0x67, 0xED, + 0x91, 0xF9, 0xE6, 0x72, 0x5B, 0x47, 0x58, 0xC0, + 0x22, 0xE0, 0xB1, 0xEF, 0x42, 0x75, 0xBF, 0x7B, + 0x6C, 0x5B, 0xFC, 0x11, 0xD4, 0x5F, 0x90, 0x88, + 0xB9, 0x41, 0xF5, 0x4E, 0xB1, 0xE5, 0x9B, 0xB8, + 0xBC, 0x39, 0xA0, 0xBF, 0x12, 0x30, 0x7F, 0x5C, + 0x4F, 0xDB, 0x70, 0xC5, 0x81, 0xB2, 0x3F, 0x76, + 0xB6, 0x3A, 0xCA, 0xE1, 0xCA, 0xA6, 0xB7, 0x90, + 0x2D, 0x52, 0x52, 0x67, 0x35, 0x48, 0x8A, 0x0E, + 0xF1, 0x3C, 0x6D, 0x9A, 0x51, 0xBF, 0xA4, 0xAB, + 0x3A, 0xD8, 0x34, 0x77, 0x96, 0x52, 0x4D, 0x8E, + 0xF6, 0xA1, 0x67, 0xB5, 0xA4, 0x18, 0x25, 0xD9, + 0x67, 0xE1, 0x44, 0xE5, 0x14, 0x05, 0x64, 0x25, + 0x1C, 0xCA, 0xCB, 0x83, 0xE6, 0xB4, 0x86, 0xF6, + 0xB3, 0xCA, 0x3F, 0x79, 0x71, 0x50, 0x60, 0x26, + 0xC0, 0xB8, 0x57, 0xF6, 0x89, 0x96, 0x28, 0x56, + 0xDE, 0xD4, 0x01, 0x0A, 0xBD, 0x0B, 0xE6, 0x21, + 0xC3, 0xA3, 0x96, 0x0A, 0x54, 0xE7, 0x10, 0xC3, + 0x75, 0xF2, 0x63, 0x75, 0xD7, 0x01, 0x41, 0x03, + 0xA4, 0xB5, 0x43, 0x30, 0xC1, 0x98, 0xAF, 0x12, + 0x61, 0x16, 0xD2, 0x27, 0x6E, 0x11, 0x71, 0x5F, + 0x69, 0x38, 0x77, 0xFA, 0xD7, 0xEF, 0x09, 0xCA, + 0xDB, 0x09, 0x4A, 0xE9, 0x1E, 0x1A, 0x15, 0x97 +}; +static const UCHAR dh_group24_order[] = { + 0x8C, 0xF8, 0x36, 0x42, 0xA7, 0x09, 0xA0, 0x97, + 0xB4, 0x47, 0x99, 0x76, 0x40, 0x12, 0x9D, 0xA2, + 0x99, 0xB1, 0xA4, 0x7D, 0x1E, 0xB3, 0x75, 0x0B, + 0xA3, 0x08, 0xB0, 0xFE, 0x64, 0xF5, 0xFB, 0xD3 +}; + +typedef struct __DH_GROUP_INFO { + INT32 group_id; + const UCHAR *generator; + UINT32 generator_len; + const UCHAR *prime; + UINT32 prime_len; + const UCHAR *order; + UINT32 order_len; + UCHAR safe_prime; +} DH_GROUP_INFO, *PDH_GROUP_INFO; + +typedef struct __DH_GROUP_INFO_BI { + INT32 group_id; + SAE_BN *generator; + SAE_BN *prime; + SAE_BN *order; + UCHAR safe_prime; + UCHAR is_init; +} DH_GROUP_INFO_BI, *PDH_GROUP_INFO_BI; + +#define DH_GROUP_NUM (sizeof(dh_groups)/sizeof(DH_GROUP_INFO)) + +#define DH_GROUP(id, safe) \ + { id, dh_group ## id ## _generator, sizeof(dh_group ## id ## _generator), \ + dh_group ## id ## _prime, sizeof(dh_group ## id ## _prime), \ + dh_group ## id ## _order, sizeof(dh_group ## id ## _order), safe } + + + + +#define DH_GROUP_BI(id, safe) \ + { .group_id = id, .safe_prime = safe, .is_init = FALSE} + + + +#ifdef ECC_group_related +/* + ===================================== + ECC group related + ===================================== +*/ +#endif + +/* + * RFC 5114, 2.6. + * Group 19 - 256-bit random ECP group + */ +static const UCHAR ec_group19_prime[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const UCHAR ec_group19_order[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, + 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 +}; +static const UCHAR ec_group19_a[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC + +}; +static const UCHAR ec_group19_b[] = { + 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, + 0xB3, 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC, + 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, + 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B +}; + +static const UCHAR ec_group19_gx[] = { + 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, + 0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, + 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, + 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96 + +}; +static const UCHAR ec_group19_gy[] = { + 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, + 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, + 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, + 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5 +}; + +#define EC_GROUP19_BITS_OF_R 257 + +static const UCHAR ec_group19_X[] = { + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, +}; + +static const UCHAR ec_group19_R[] = { + 0x00, 0x00, 0x00, 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, +}; + +static const UCHAR ec_group19_PInverse[] = { + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +}; + + +/* + * RFC 5114, 2.7. + * Group 20 - 384-bit random ECP group + */ +static const UCHAR ec_group20_prime[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const UCHAR ec_group20_order[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, + 0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A, + 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73 + +}; +static const UCHAR ec_group20_a[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC, +}; +static const UCHAR ec_group20_b[] = { + 0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, + 0x98, 0x8E, 0x05, 0x6B, 0xE3, 0xF8, 0x2D, 0x19, + 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12, + 0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, + 0xC6, 0x56, 0x39, 0x8D, 0x8A, 0x2E, 0xD1, 0x9D, + 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF +}; + +static const UCHAR ec_group20_gx[] = { + 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, + 0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD, 0x74, + 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98, + 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, + 0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29, 0x6C, + 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7 +}; + +static const UCHAR ec_group20_gy[] = { + 0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, + 0x5d, 0x9e, 0x98, 0xbf, 0x92, 0x92, 0xdc, 0x29, + 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c, + 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, + 0x0a, 0x60, 0xb1, 0xce, 0x1d, 0x7e, 0x81, 0x9d, + 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f +}; + +#define EC_GROUP20_BITS_OF_R 385 + +static const UCHAR ec_group20_X[] = { + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x01, +}; + +static const UCHAR ec_group20_R[] = { + 0x00, 0x00, 0x00, 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, +}; + +static const UCHAR ec_group20_PInverse[] = { + 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x02, + 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xfa, + 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, +}; + + +/* + * RFC 5114, 2.8. + * Group 21 - 521-bit random ECP group + */ +static const UCHAR ec_group21_prime[] = { + 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF +}; +static const UCHAR ec_group21_order[] = { + 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86, 0x87, 0x83, + 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, + 0xF7, 0x09, 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, + 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F, 0xB7, 0x1E, + 0x91, 0x38, 0x64, 0x09 +}; +static const UCHAR ec_group21_a[] = { + 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFC +}; +static const UCHAR ec_group21_b[] = { + 0x00, 0x00, 0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, + 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A, 0x21, 0xA0, + 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, + 0x99, 0xB3, 0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, + 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19, 0x39, 0x51, + 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, + 0x3B, 0xB1, 0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, + 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45, 0x1F, 0xD4, + 0x6B, 0x50, 0x3F, 0x00 +}; + +static const UCHAR ec_group21_gx[] = { + 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, + 0xE9, 0xCD, 0x9E, 0x3E, 0xCB, 0x66, 0x23, 0x95, + 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F, + 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, + 0x3D, 0xBA, 0xA1, 0x4B, 0x5E, 0x77, 0xEF, 0xE7, + 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF, + 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, + 0x42, 0x9B, 0xF9, 0x7E, 0x7E, 0x31, 0xC2, 0xE5, + 0xBD, 0x66 +}; + +static const UCHAR ec_group21_gy[] = { + 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, + 0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d, + 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b, + 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, + 0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4, + 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad, + 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, + 0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1, + 0x66, 0x50 +}; + +#define EC_GROUP21_BITS_OF_R 522 + +static const UCHAR ec_group21_X[] = { + 0x00, 0x00, 0x00, 0x01, +}; + +static const UCHAR ec_group21_R[] = { + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 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 const UCHAR ec_group21_PInverse[] = { + 0x00, 0x00, 0x00, 0x01, +}; + + +/* + * RFC 5114, 2.4. + * Group 25 - 192-bit random ECP group + */ +static const UCHAR ec_group25_prime[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +static const UCHAR ec_group25_order[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0xDE, 0xF8, 0x36, + 0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31 +}; +static const UCHAR ec_group25_a[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, +}; +static const UCHAR ec_group25_b[] = { + 0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7, + 0x0F, 0xA7, 0xE9, 0xAB, 0x72, 0x24, 0x30, 0x49, + 0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46, 0xB9, 0xB1 +}; + +#define EC_GROUP25_BITS_OF_R 193 + +static const UCHAR ec_group25_X[] = { + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, +}; + +static const UCHAR ec_group25_R[] = { + 0x00, 0x00, 0x00, 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, +}; + +static const UCHAR ec_group25_PInverse[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +}; + + + +/* + * RFC 5114, 2.5. + * Group 26 - 224-bit random ECP group + */ +static const UCHAR ec_group26_prime[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 +}; +static const UCHAR ec_group26_order[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x16, 0xA2, + 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45, + 0x5C, 0x5C, 0x2A, 0x3D +}; +static const UCHAR ec_group26_a[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE +}; +static const UCHAR ec_group26_b[] = { + 0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, + 0xF5, 0x41, 0x32, 0x56, 0x50, 0x44, 0xB0, 0xB7, + 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43, + 0x23, 0x55, 0xFF, 0xB4 +}; + +#define EC_GROUP26_BITS_OF_R 225 + +static const UCHAR ec_group26_X[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, +}; + +static const UCHAR ec_group26_R[] = { + 0x00, 0x00, 0x00, 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, +}; + +static const UCHAR ec_group26_PInverse[] = { + 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, +}; + + +/* + * RFC 6932, 2.1. + * Group 27 - 224-bit Brainpool ECP group + */ +static const UCHAR ec_group27_prime[] = { + 0xD7, 0xC1, 0x34, 0xAA, 0x26, 0x43, 0x66, 0x86, + 0x2A, 0x18, 0x30, 0x25, 0x75, 0xD1, 0xD7, 0x87, + 0xB0, 0x9F, 0x07, 0x57, 0x97, 0xDA, 0x89, 0xF5, + 0x7E, 0xC8, 0xC0, 0xFF +}; +static const UCHAR ec_group27_order[] = { + 0xD7, 0xC1, 0x34, 0xAA, 0x26, 0x43, 0x66, 0x86, + 0x2A, 0x18, 0x30, 0x25, 0x75, 0xD0, 0xFB, 0x98, + 0xD1, 0x16, 0xBC, 0x4B, 0x6D, 0xDE, 0xBC, 0xA3, + 0xA5, 0xA7, 0x93, 0x9F +}; +static const UCHAR ec_group27_a[] = { + 0x68, 0xA5, 0xE6, 0x2C, 0xA9, 0xCE, 0x6C, 0x1C, + 0x29, 0x98, 0x03, 0xA6, 0xC1, 0x53, 0x0B, 0x51, + 0x4E, 0x18, 0x2A, 0xD8, 0xB0, 0x04, 0x2A, 0x59, + 0xCA, 0xD2, 0x9F, 0x43 +}; +static const UCHAR ec_group27_b[] = { + 0x25, 0x80, 0xF6, 0x3C, 0xCF, 0xE4, 0x41, 0x38, + 0x87, 0x07, 0x13, 0xB1, 0xA9, 0x23, 0x69, 0xE3, + 0x3E, 0x21, 0x35, 0xD2, 0x66, 0xDB, 0xB3, 0x72, + 0x38, 0x6C, 0x40, 0x0B +}; + +#define EC_GROUP27_BITS_OF_R 225 + + +static const UCHAR ec_group27_X[] = { + 0x28, 0x3e, 0xcb, 0x55, 0xd9, 0xbc, 0x99, 0x79, + 0xd5, 0xe7, 0xcf, 0xda, 0x8a, 0x2e, 0x28, 0x78, + 0x4f, 0x60, 0xf8, 0xa8, 0x68, 0x25, 0x76, 0x0a, + 0x81, 0x37, 0x3f, 0x01, +}; + +static const UCHAR ec_group27_R[] = { + 0x00, 0x00, 0x00, 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, +}; + +static const UCHAR ec_group27_PInverse[] = { + 0x7e, 0xe4, 0x30, 0x06, 0x5c, 0x7f, 0x68, 0x4f, + 0x1a, 0x7f, 0x5f, 0xe3, 0xc1, 0xa3, 0x09, 0xe4, + 0x7d, 0xb2, 0xfa, 0x27, 0xe2, 0x4d, 0x21, 0x6a, + 0xe1, 0x49, 0xc1, 0x01, +}; + + +/* + * RFC 6932, 2.2. + * Group 28 - 256-bit Brainpool ECP group + */ +static const UCHAR ec_group28_prime[] = { + 0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, + 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72, + 0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28, + 0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x77, +}; +static const UCHAR ec_group28_order[] = { + 0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, + 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x71, + 0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7, + 0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7 +}; +static const UCHAR ec_group28_a[] = { + 0x7D, 0x5A, 0x09, 0x75, 0xFC, 0x2C, 0x30, 0x57, + 0xEE, 0xF6, 0x75, 0x30, 0x41, 0x7A, 0xFF, 0xE7, + 0xFB, 0x80, 0x55, 0xC1, 0x26, 0xDC, 0x5C, 0x6C, + 0xE9, 0x4A, 0x4B, 0x44, 0xF3, 0x30, 0xB5, 0xD9 +}; +static const UCHAR ec_group28_b[] = { + 0x26, 0xDC, 0x5C, 0x6C, 0xE9, 0x4A, 0x4B, 0x44, + 0xF3, 0x30, 0xB5, 0xD9, 0xBB, 0xD7, 0x7C, 0xBF, + 0x95, 0x84, 0x16, 0x29, 0x5C, 0xF7, 0xE1, 0xCE, + 0x6B, 0xCC, 0xDC, 0x18, 0xFF, 0x8C, 0x07, 0xB6 +}; + +#define EC_GROUP28_BITS_OF_R 257 + +static const UCHAR ec_group28_X[] = { + 0x56, 0x04, 0xa8, 0x24, 0x5e, 0x11, 0x56, 0x43, + 0xc1, 0x99, 0xf5, 0x6f, 0x62, 0x7c, 0x72, 0x8d, + 0x91, 0xc4, 0x09, 0xdc, 0x2a, 0xd9, 0xdf, 0xd7, + 0xdf, 0xec, 0xb7, 0xe2, 0xe0, 0x91, 0xac, 0x89, +}; + +static const UCHAR ec_group28_R[] = { + 0x00, 0x00, 0x00, 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, +}; + +static const UCHAR ec_group28_PInverse[] = { + 0xdb, 0x43, 0xf8, 0xe6, 0xd0, 0xbd, 0x5a, 0xf5, + 0xfd, 0xec, 0xce, 0xfb, 0x8a, 0xb1, 0xe8, 0x38, + 0xda, 0xb9, 0xe6, 0xa2, 0x27, 0x73, 0xca, 0x1f, + 0xc6, 0xa7, 0x55, 0x90, 0xce, 0xfd, 0x89, 0xb9, +}; + + + +/* + * RFC 6932, 2.3. + * Group 29 - 384-bit Brainpool ECP group + */ +static const UCHAR ec_group29_prime[] = { + 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, + 0x0F, 0x5D, 0x6F, 0x7E, 0x50, 0xE6, 0x41, 0xDF, + 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB4, + 0x12, 0xB1, 0xDA, 0x19, 0x7F, 0xB7, 0x11, 0x23, + 0xAC, 0xD3, 0xA7, 0x29, 0x90, 0x1D, 0x1A, 0x71, + 0x87, 0x47, 0x00, 0x13, 0x31, 0x07, 0xEC, 0x53 +}; +static const UCHAR ec_group29_order[] = { + 0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, + 0x0F, 0x5D, 0x6F, 0x7E, 0x50, 0xE6, 0x41, 0xDF, + 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB3, + 0x1F, 0x16, 0x6E, 0x6C, 0xAC, 0x04, 0x25, 0xA7, + 0xCF, 0x3A, 0xB6, 0xAF, 0x6B, 0x7F, 0xC3, 0x10, + 0x3B, 0x88, 0x32, 0x02, 0xE9, 0x04, 0x65, 0x65 +}; +static const UCHAR ec_group29_a[] = { + 0x7B, 0xC3, 0x82, 0xC6, 0x3D, 0x8C, 0x15, 0x0C, + 0x3C, 0x72, 0x08, 0x0A, 0xCE, 0x05, 0xAF, 0xA0, + 0xC2, 0xBE, 0xA2, 0x8E, 0x4F, 0xB2, 0x27, 0x87, + 0x13, 0x91, 0x65, 0xEF, 0xBA, 0x91, 0xF9, 0x0F, + 0x8A, 0xA5, 0x81, 0x4A, 0x50, 0x3A, 0xD4, 0xEB, + 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26 +}; +static const UCHAR ec_group29_b[] = { + 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26, + 0x8B, 0x39, 0xB5, 0x54, 0x16, 0xF0, 0x44, 0x7C, + 0x2F, 0xB7, 0x7D, 0xE1, 0x07, 0xDC, 0xD2, 0xA6, + 0x2E, 0x88, 0x0E, 0xA5, 0x3E, 0xEB, 0x62, 0xD5, + 0x7C, 0xB4, 0x39, 0x02, 0x95, 0xDB, 0xC9, 0x94, + 0x3A, 0xB7, 0x86, 0x96, 0xFA, 0x50, 0x4C, 0x11 +}; + +#define EC_GROUP29_BITS_OF_R 385 + +static const UCHAR ec_group29_X[] = { + 0x73, 0x46, 0xe1, 0x7d, 0x5c, 0xc7, 0x92, 0xd7, + 0xf0, 0xa2, 0x90, 0x81, 0xaf, 0x19, 0xbe, 0x20, + 0xea, 0xd0, 0x8e, 0xf6, 0x12, 0xab, 0xa9, 0x4b, + 0xed, 0x4e, 0x25, 0xe6, 0x80, 0x48, 0xee, 0xdc, + 0x53, 0x2c, 0x58, 0xd6, 0x6f, 0xe2, 0xe5, 0x8e, + 0x78, 0xb8, 0xff, 0xec, 0xce, 0xf8, 0x13, 0xad, +}; + +static const UCHAR ec_group29_R[] = { + 0x00, 0x00, 0x00, 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, +}; + +static const UCHAR ec_group29_PInverse[] = { + 0xa3, 0xdc, 0x38, 0xe9, 0xbb, 0xc1, 0xcf, 0xee, + 0x0f, 0xad, 0xd0, 0x2f, 0x4c, 0x6f, 0x86, 0xdf, + 0xf5, 0xd5, 0x6c, 0x42, 0x19, 0xe5, 0xc2, 0x92, + 0x1c, 0xba, 0xe5, 0x87, 0x4d, 0x80, 0xfc, 0x16, + 0x83, 0x4b, 0x1e, 0x52, 0xed, 0xf7, 0x75, 0x94, + 0x9a, 0x6e, 0xa9, 0x6c, 0xea, 0x9e, 0xc8, 0x25, +}; + + + +/* + * RFC 6932, 2.4. + * Group 30 - 512-bit Brainpool ECP group + */ +static const UCHAR ec_group30_prime[] = { + 0xAA, 0xDD, 0x9D, 0xB8, 0xDB, 0xE9, 0xC4, 0x8B, + 0x3F, 0xD4, 0xE6, 0xAE, 0x33, 0xC9, 0xFC, 0x07, + 0xCB, 0x30, 0x8D, 0xB3, 0xB3, 0xC9, 0xD2, 0x0E, + 0xD6, 0x63, 0x9C, 0xCA, 0x70, 0x33, 0x08, 0x71, + 0x7D, 0x4D, 0x9B, 0x00, 0x9B, 0xC6, 0x68, 0x42, + 0xAE, 0xCD, 0xA1, 0x2A, 0xE6, 0xA3, 0x80, 0xE6, + 0x28, 0x81, 0xFF, 0x2F, 0x2D, 0x82, 0xC6, 0x85, + 0x28, 0xAA, 0x60, 0x56, 0x58, 0x3A, 0x48, 0xF3 +}; +static const UCHAR ec_group30_order[] = { + 0xAA, 0xDD, 0x9D, 0xB8, 0xDB, 0xE9, 0xC4, 0x8B, + 0x3F, 0xD4, 0xE6, 0xAE, 0x33, 0xC9, 0xFC, 0x07, + 0xCB, 0x30, 0x8D, 0xB3, 0xB3, 0xC9, 0xD2, 0x0E, + 0xD6, 0x63, 0x9C, 0xCA, 0x70, 0x33, 0x08, 0x70, + 0x55, 0x3E, 0x5C, 0x41, 0x4C, 0xA9, 0x26, 0x19, + 0x41, 0x86, 0x61, 0x19, 0x7F, 0xAC, 0x10, 0x47, + 0x1D, 0xB1, 0xD3, 0x81, 0x08, 0x5D, 0xDA, 0xDD, + 0xB5, 0x87, 0x96, 0x82, 0x9C, 0xA9, 0x00, 0x69 +}; +static const UCHAR ec_group30_a[] = { + 0x78, 0x30, 0xA3, 0x31, 0x8B, 0x60, 0x3B, 0x89, + 0xE2, 0x32, 0x71, 0x45, 0xAC, 0x23, 0x4C, 0xC5, + 0x94, 0xCB, 0xDD, 0x8D, 0x3D, 0xF9, 0x16, 0x10, + 0xA8, 0x34, 0x41, 0xCA, 0xEA, 0x98, 0x63, 0xBC, + 0x2D, 0xED, 0x5D, 0x5A, 0xA8, 0x25, 0x3A, 0xA1, + 0x0A, 0x2E, 0xF1, 0xC9, 0x8B, 0x9A, 0xC8, 0xB5, + 0x7F, 0x11, 0x17, 0xA7, 0x2B, 0xF2, 0xC7, 0xB9, + 0xE7, 0xC1, 0xAC, 0x4D, 0x77, 0xFC, 0x94, 0xCA +}; +static const UCHAR ec_group30_b[] = { + 0x3D, 0xF9, 0x16, 0x10, 0xA8, 0x34, 0x41, 0xCA, + 0xEA, 0x98, 0x63, 0xBC, 0x2D, 0xED, 0x5D, 0x5A, + 0xA8, 0x25, 0x3A, 0xA1, 0x0A, 0x2E, 0xF1, 0xC9, + 0x8B, 0x9A, 0xC8, 0xB5, 0x7F, 0x11, 0x17, 0xA7, + 0x2B, 0xF2, 0xC7, 0xB9, 0xE7, 0xC1, 0xAC, 0x4D, + 0x77, 0xFC, 0x94, 0xCA, 0xDC, 0x08, 0x3E, 0x67, + 0x98, 0x40, 0x50, 0xB7, 0x5E, 0xBA, 0xE5, 0xDD, + 0x28, 0x09, 0xBD, 0x63, 0x80, 0x16, 0xF7, 0x23, +}; + +#define EC_GROUP30_BITS_OF_R 513 + +static const UCHAR ec_group30_X[] = { + 0x55, 0x22, 0x62, 0x47, 0x24, 0x16, 0x3b, 0x74, + 0xc0, 0x2b, 0x19, 0x51, 0xcc, 0x36, 0x03, 0xf8, + 0x34, 0xcf, 0x72, 0x4c, 0x4c, 0x36, 0x2d, 0xf1, + 0x29, 0x9c, 0x63, 0x35, 0x8f, 0xcc, 0xf7, 0x8e, + 0x82, 0xb2, 0x64, 0xff, 0x64, 0x39, 0x97, 0xbd, + 0x51, 0x32, 0x5e, 0xd5, 0x19, 0x5c, 0x7f, 0x19, + 0xd7, 0x7e, 0x00, 0xd0, 0xd2, 0x7d, 0x39, 0x7a, + 0xd7, 0x55, 0x9f, 0xa9, 0xa7, 0xc5, 0xb7, 0x0d, +}; + +static const UCHAR ec_group30_R[] = { + 0x00, 0x00, 0x00, 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, +}; + +static const UCHAR ec_group30_PInverse[] = { + 0x4c, 0x39, 0x8e, 0x09, 0x22, 0x96, 0x3f, 0x73, + 0xc8, 0x2b, 0x46, 0xfb, 0xfa, 0xae, 0xa0, 0x06, + 0x36, 0x82, 0xa0, 0x85, 0xd4, 0xf0, 0x55, 0x03, + 0x16, 0x09, 0x8b, 0x3e, 0x75, 0xc2, 0x05, 0x72, + 0xae, 0xf7, 0x52, 0x8b, 0xc5, 0xa7, 0xe2, 0x43, + 0x50, 0x65, 0x2e, 0xc0, 0x81, 0x5c, 0xfb, 0xcd, + 0xed, 0xaa, 0x1d, 0x85, 0xa2, 0xcd, 0x1e, 0x7c, + 0x83, 0x9b, 0x32, 0x20, 0x7d, 0x89, 0xef, 0xc5, +}; + +#define EC_GROUP(id, bits_of_R) \ + { id, ec_group ## id ## _prime, sizeof(ec_group ## id ## _prime), \ + ec_group ## id ## _order, sizeof(ec_group ## id ## _order), \ + ec_group ## id ## _a, sizeof(ec_group ## id ## _a), \ + ec_group ## id ## _b, sizeof(ec_group ## id ## _b), \ + ec_group ## id ## _X, sizeof(ec_group ## id ## _X), \ + ec_group ## id ## _R, sizeof(ec_group ## id ## _R), \ + ec_group ## id ## _PInverse, sizeof(ec_group ## id ## _PInverse), \ + bits_of_R \ + } + +#define EC_GROUP_NUM (sizeof(ec_groups)/sizeof(EC_GROUP_INFO)) + + +#define EC_GROUP_BI(id) {.group_id = id, .is_init = FALSE, .mont = NULL, .is_minus_3 = FALSE} + +#endif +#endif /* SAE_CMM_H */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sniffer/radiotap.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sniffer/radiotap.h new file mode 100644 index 000000000..dc74da402 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sniffer/radiotap.h @@ -0,0 +1,301 @@ +/*- + * Copyright (c) 2003, 2004 David Young. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of David Young may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID + * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + */ + +/* + * Modifications to fit into the linux IEEE 802.11 stack, + * Mike Kershaw (dragorn@kismetwireless.net) + */ + +#ifndef IEEE80211RADIOTAP_H +#define IEEE80211RADIOTAP_H + +/* Base version of the radiotap packet header data */ +#define PKTHDR_RADIOTAP_VERSION 0 + +/* A generic radio capture format is desirable. There is one for + * Linux, but it is neither rigidly defined (there were not even + * units given for some fields) nor easily extensible. + * + * I suggest the following extensible radio capture format. It is + * based on a bitmap indicating which fields are present. + * + * I am trying to describe precisely what the application programmer + * should expect in the following, and for that reason I tell the + * units and origin of each measurement (where it applies), or else I + * use sufficiently weaselly language ("is a monotonically nondecreasing + * function of...") that I cannot set false expectations for lawyerly + * readers. + */ + +/* The radio capture header precedes the 802.11 header. + * All data in the header is little endian on all platforms. + */ +struct ieee80211_radiotap_header { + uint8_t it_version; /* Version 0. Only increases + * for drastic changes, + * introduction of compatible + * new fields does not count. + */ + uint8_t it_pad; + uint16_t it_len; /* length of the whole + * header in bytes, including + * it_version, it_pad, + * it_len, and data fields. + */ + uint32_t it_present; /* A bitmap telling which + * fields are present. Set bit 31 + * (0x80000000) to extend the + * bitmap by another 32 bits. + * Additional extensions are made + * by setting bit 31. + */ +}; + +/* Name Data type Units + * ---- --------- ----- + * + * IEEE80211_RADIOTAP_TSFT __le64 microseconds + * + * Value in microseconds of the MAC's 64-bit 802.11 Time + * Synchronization Function timer when the first bit of the + * MPDU arrived at the MAC. For received frames, only. + * + * IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap + * + * Tx/Rx frequency in MHz, followed by flags (see below). + * + * IEEE80211_RADIOTAP_FHSS uint16_t see below + * + * For frequency-hopping radios, the hop set (first byte) + * and pattern (second byte). + * + * IEEE80211_RADIOTAP_RATE u8 500kb/s + * + * Tx/Rx data rate + * + * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from + * one milliwatt (dBm) + * + * RF signal power at the antenna, decibel difference from + * one milliwatt. + * + * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from + * one milliwatt (dBm) + * + * RF noise power at the antenna, decibel difference from one + * milliwatt. + * + * IEEE80211_RADIOTAP_DB_ANTSIGNAL u8 decibel (dB) + * + * RF signal power at the antenna, decibel difference from an + * arbitrary, fixed reference. + * + * IEEE80211_RADIOTAP_DB_ANTNOISE u8 decibel (dB) + * + * RF noise power at the antenna, decibel difference from an + * arbitrary, fixed reference point. + * + * IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless + * + * Quality of Barker code lock. Unitless. Monotonically + * nondecreasing with "better" lock strength. Called "Signal + * Quality" in datasheets. (Is there a standard way to measure + * this?) + * + * IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless + * + * Transmit power expressed as unitless distance from max + * power set at factory calibration. 0 is max power. + * Monotonically nondecreasing with lower power levels. + * + * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB) + * + * Transmit power expressed as decibel distance from max power + * set at factory calibration. 0 is max power. Monotonically + * nondecreasing with lower power levels. + * + * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from + * one milliwatt (dBm) + * + * Transmit power expressed as dBm (decibels from a 1 milliwatt + * reference). This is the absolute power level measured at + * the antenna port. + * + * IEEE80211_RADIOTAP_FLAGS u8 bitmap + * + * Properties of transmitted and received frames. See flags + * defined below. + * + * IEEE80211_RADIOTAP_ANTENNA u8 antenna index + * + * Unitless indication of the Rx/Tx antenna for this packet. + * The first antenna is antenna 0. + * + * IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap + * + * Properties of received frames. See flags defined below. + * + * IEEE80211_RADIOTAP_TX_FLAGS uint16_t bitmap + * + * Properties of transmitted frames. See flags defined below. + * + * IEEE80211_RADIOTAP_RTS_RETRIES u8 data + * + * Number of rts retries a transmitted frame used. + * + * IEEE80211_RADIOTAP_DATA_RETRIES u8 data + * + * Number of unicast retries a transmitted frame used. + * + * IEEE80211_RADIOTAP_MCS u8, u8, u8 unitless + * + * Contains a bitmap of known fields/flags, the flags, and + * the MCS index. + * + * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitlesss + * + * Contains the AMPDU information for the subframe. + * + * IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16 + * + * Contains VHT information about this frame. + */ +enum ieee80211_radiotap_type { + IEEE80211_RADIOTAP_TSFT = 0, + IEEE80211_RADIOTAP_FLAGS = 1, + IEEE80211_RADIOTAP_RATE = 2, + IEEE80211_RADIOTAP_CHANNEL = 3, + IEEE80211_RADIOTAP_FHSS = 4, + IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, + IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, + IEEE80211_RADIOTAP_LOCK_QUALITY = 7, + IEEE80211_RADIOTAP_TX_ATTENUATION = 8, + IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, + IEEE80211_RADIOTAP_DBM_TX_POWER = 10, + IEEE80211_RADIOTAP_ANTENNA = 11, + IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, + IEEE80211_RADIOTAP_DB_ANTNOISE = 13, + IEEE80211_RADIOTAP_RX_FLAGS = 14, + IEEE80211_RADIOTAP_TX_FLAGS = 15, + IEEE80211_RADIOTAP_RTS_RETRIES = 16, + IEEE80211_RADIOTAP_DATA_RETRIES = 17, + + IEEE80211_RADIOTAP_MCS = 19, + IEEE80211_RADIOTAP_AMPDU_STATUS = 20, + IEEE80211_RADIOTAP_VHT = 21, + + /* valid in every it_present bitmap, even vendor namespaces */ + IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, + IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30, + IEEE80211_RADIOTAP_EXT = 31 +}; + +/* Channel flags. */ +#define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */ +#define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */ +#define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */ +#define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */ +#define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */ +#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */ +#define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */ +#define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */ + +/* For IEEE80211_RADIOTAP_FLAGS */ +#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received + * during CFP + */ +#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received + * with short + * preamble + */ +#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received + * with WEP encryption + */ +#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received + * with fragmentation + */ +#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */ +#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between + * 802.11 header and payload + * (to 32-bit boundary) + */ +#define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* frame failed FCS check */ + +/* For IEEE80211_RADIOTAP_RX_FLAGS */ +#define IEEE80211_RADIOTAP_F_RX_BADPLCP 0x0002 /* bad PLCP */ + +/* For IEEE80211_RADIOTAP_TX_FLAGS */ +#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive + * retries */ +#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */ +#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */ + +/* For IEEE80211_RADIOTAP_AMPDU_STATUS */ +#define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001 +#define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002 +#define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004 +#define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008 +#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010 +#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020 + +/* For IEEE80211_RADIOTAP_MCS */ +#define IEEE80211_RADIOTAP_MCS_HAVE_BW 0x01 +#define IEEE80211_RADIOTAP_MCS_HAVE_MCS 0x02 +#define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04 +#define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08 +#define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10 + +#define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03 +#define IEEE80211_RADIOTAP_MCS_BW_20 0 +#define IEEE80211_RADIOTAP_MCS_BW_40 1 +#define IEEE80211_RADIOTAP_MCS_BW_20L 2 +#define IEEE80211_RADIOTAP_MCS_BW_20U 3 +#define IEEE80211_RADIOTAP_MCS_SGI 0x04 +#define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08 +#define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10 + +/* For IEEE80211_RADIOTAP_VHT */ +#define IEEE80211_RADIOTAP_VHT_KNOWN_STBC 0x0001 +#define IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA 0x0002 +#define IEEE80211_RADIOTAP_VHT_KNOWN_GI 0x0004 +#define IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS 0x0008 +#define IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM 0x0010 +#define IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED 0x0020 +#define IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH 0x0040 +#define IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID 0x0080 +#define IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID 0x0100 + +#define IEEE80211_RADIOTAP_VHT_FLAG_STBC 0x01 +#define IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA 0x02 +#define IEEE80211_RADIOTAP_VHT_FLAG_SGI 0x04 +#define IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 0x08 +#define IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM 0x10 +#define IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED 0x20 + +#endif /* IEEE80211_RADIOTAP_H */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sniffer/sniffer.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sniffer/sniffer.h new file mode 100644 index 000000000..72ffcfc8d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sniffer/sniffer.h @@ -0,0 +1,171 @@ +/* + *************************************************************************** + * MediaTek Inc. + * + * All rights reserved. source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of MediaTek. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of MediaTek, Inc. is obtained. + *************************************************************************** + + Module Name: + sniffer.h +*/ + +#ifndef __SNIFFER_H__ +#define __SNIFFER_H__ + +#include "radiotap.h" + +struct sniffer_control { + UINT8 sniffer_type; +}; + +#define RADIOTAP_TYPE 0 +#define PRISM_TYPE 1 + +enum { + DIDmsg_lnxind_wlansniffrm = 0x00000044, + DIDmsg_lnxind_wlansniffrm_hosttime = 0x00010044, + DIDmsg_lnxind_wlansniffrm_mactime = 0x00020044, + DIDmsg_lnxind_wlansniffrm_channel = 0x00030044, + DIDmsg_lnxind_wlansniffrm_rssi = 0x00040044, + DIDmsg_lnxind_wlansniffrm_sq = 0x00050044, + DIDmsg_lnxind_wlansniffrm_signal = 0x00060044, + DIDmsg_lnxind_wlansniffrm_noise = 0x00070044, + DIDmsg_lnxind_wlansniffrm_rate = 0x00080044, + DIDmsg_lnxind_wlansniffrm_istx = 0x00090044, + DIDmsg_lnxind_wlansniffrm_frmlen = 0x000A0044 +}; +enum { +P80211ENUM_msgitem_status_no_value = 0x00 +}; + +enum { +P80211ENUM_truth_false = 0x00, +P80211ENUM_truth_true = 0x01 +}; + + +/* Definition from madwifi */ +typedef struct { + UINT32 did; + UINT16 status; + UINT16 len; + UINT32 data; +} p80211item_uint32_t; + +typedef struct { + UINT32 msgcode; + UINT32 msglen; +#define WLAN_DEVNAMELEN_MAX 16 + UINT8 devname[WLAN_DEVNAMELEN_MAX]; + p80211item_uint32_t hosttime; + p80211item_uint32_t mactime; + p80211item_uint32_t channel; + p80211item_uint32_t rssi; + p80211item_uint32_t sq; + p80211item_uint32_t signal; + p80211item_uint32_t noise; + p80211item_uint32_t rate; + p80211item_uint32_t istx; + p80211item_uint32_t frmlen; +} wlan_ng_prism2_header; + +#ifdef MONITOR_FLAG_11N_SNIFFER_SUPPORT +/* + Note: 2009/11/10 + Used in WiFi Sigma Test Engine RT3593 (replace RT2883). +*/ +#ifdef RT_BIG_ENDIAN +typedef struct _ETHEREAL_RADIO { + UCHAR Flag_80211n; + UCHAR signal_level; /* dBm */ + UCHAR data_rate; /* rate index */ + UCHAR channel; /* Channel number */ +} ETHEREAL_RADIO, *PETHEREAL_RADIO; +#else +typedef struct _ETHEREAL_RADIO { + UCHAR channel; /* Channel number */ + UCHAR data_rate; /* rate index */ + UCHAR signal_level; /* dBm */ + UCHAR Flag_80211n; +} ETHEREAL_RADIO, *PETHEREAL_RADIO; +#endif + +#define WIRESHARK_11N_FLAG_3x3 0x01 +#define WIRESHARK_11N_FLAG_GF 0x02 +#define WIRESHARK_11N_FLAG_AMPDU 0x04 +#define WIRESHARK_11N_FLAG_STBC 0x08 +#define WIRESHARK_11N_FLAG_SGI 0x10 +#define WIRESHARK_11N_FLAG_BW20U 0x20 +#define WIRESHARK_11N_FLAG_BW20D 0x40 +#define WIRESHARK_11N_FLAG_BW40 0x80 +#endif /* MONITOR_FLAG_11N_SNIFFER_SUPPORT */ + +struct mtk_radiotap_header { + struct ieee80211_radiotap_header rt_hdr; + UCHAR variable[0]; +}; + +#define HT_BW(p) ((p) & IEEE80211_RADIOTAP_MCS_BW_MASK) +#define HT_GI(p) ((p << 2) & IEEE80211_RADIOTAP_MCS_SGI) +#define HT_FORMAT(p) ((p << 3) & IEEE80211_RADIOTAP_MCS_FMT_GF) +#define HT_FEC_TYPE(p) ((p << 4) & IEEE80211_RADIOTAP_MCS_FEC_LDPC) + +#define VHT_MCS_MASK 0x0f +#define GET_VHT_MCS(p) (((p) & VHT_MCS_MASK)) +#define VHT_NSS_MASK (0x03 << 4) +#define GET_VHT_NSS(p) ((((p) & VHT_NSS_MASK) >> 4) + 1) + + +// copy from dot11_base.h, here we duplicate this only for sniffer use! +/* 2-byte Frame control field */ +typedef struct GNU_PACKED _FC_FIELD{ +#ifdef RT_BIG_ENDIAN + UINT16 Order:1; /* Strict order expected */ + UINT16 Wep:1; /* Wep data */ + UINT16 MoreData:1; /* More data bit */ + UINT16 PwrMgmt:1; /* Power management bit */ + UINT16 Retry:1; /* Retry status bit */ + UINT16 MoreFrag:1; /* More fragment bit */ + UINT16 FrDs:1; /* From DS indication */ + UINT16 ToDs:1; /* To DS indication */ + UINT16 SubType:4; /* MSDU subtype */ + UINT16 Type:2; /* MSDU type */ + UINT16 Ver:2; /* Protocol version */ +#else + UINT16 Ver:2; /* Protocol version */ + UINT16 Type:2; /* MSDU type, refer to FC_TYPE_XX */ + UINT16 SubType:4; /* MSDU subtype, refer to SUBTYPE_XXX */ + UINT16 ToDs:1; /* To DS indication */ + UINT16 FrDs:1; /* From DS indication */ + UINT16 MoreFrag:1; /* More fragment bit */ + UINT16 Retry:1; /* Retry status bit */ + UINT16 PwrMgmt:1; /* Power management bit */ + UINT16 MoreData:1; /* More data bit */ + UINT16 Wep:1; /* Wep data */ + UINT16 Order:1; /* Strict order expected */ +#endif /* !RT_BIG_ENDIAN */ +} FC_FIELD; + +typedef struct GNU_PACKED _DOT_11_HDR { + FC_FIELD FC; + UINT16 Duration; + UCHAR Addr1[6]; + UCHAR Addr2[6]; + UCHAR Addr3[6]; +#ifdef RT_BIG_ENDIAN + UINT16 Sequence:12; + UINT16 Frag:4; +#else + UINT16 Frag:4; + UINT16 Sequence:12; +#endif /* !RT_BIG_ENDIAN */ + UCHAR Octet[0]; +}DOT_11_HDR; + + +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sniffer_mib.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sniffer_mib.h new file mode 100644 index 000000000..15e054227 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sniffer_mib.h @@ -0,0 +1,81 @@ +#ifndef __SNIFFER_MIB_H__ +#define __SNIFFER_MIB_H__ + +#include "link_list.h" + +//this use the MAC Repeater's function : MT7603's MAX is 16 +#define MAX_NUM_OF_SNIFFER_MAC 16 + +#ifdef CONFIG_SNIFFER_SUPPORT +#ifdef ALL_NET_EVENT +#define SNIFFER_MAC_MAX_RX_PACKET_COUNT 20 +#define SNIFFER_MAC_TIMEOUT 10000 //ms + +typedef struct _SNIFFER_MAC_NOTIFY { + UINT32 u4Channel; + INT32 i4RxPacketConut; + INT32 i4RssiAccum; + PNET_DEV pNetDev; +} SNIFFER_MAC_NOTIFY_T, *PSNIFFER_MAC_NOTIFY_T; +#endif /* ALL_NET_EVENT */ +#endif /* CONFIG_SNIFFER_SUPPORT */ + + +typedef struct _SNIFFER_MAC_CTRL { + DL_LIST List; + UCHAR MACAddr[MAC_ADDR_LEN]; +#ifdef CONFIG_SNIFFER_SUPPORT +#ifdef ALL_NET_EVENT + SNIFFER_MAC_NOTIFY_T rNotify; + RALINK_TIMER_STRUCT rNotifyTimer; +#endif /* ALL_NET_EVENT */ +#endif /* CONFIG_SNIFFER_SUPPORT */ +} SNIFFER_MAC_CTRL, *PSNIFFER_MAC_CTRL; + +typedef enum _SNIFFER_SCAN_SCOPE { + SCAN_ALL, /* no need */ + SCAN_ONE, +} SNIFFER_SCAN_SCOPE; + +typedef enum _SNIFFER_SCAN_TYPE { + UNKNOWN_TYPE, + PASSIVE_TYPE, + ACTIVE_TYPE, /* no need */ +} SNIFFER_SCAN_TYPE; + +typedef struct _SNIFFER_MIB_CTRL { + UINT32 MAC_ListNum; + PRTMP_ADAPTER pAd; + SNIFFER_SCAN_SCOPE scan_scope; + SNIFFER_SCAN_TYPE scan_type; + UINT32 scan_channel; // which channel to sniffer + + UINT8 bbp_bw; // keep original pAd->hw_cfg.bbp_bw + UCHAR vht_cent_ch; //keep original pAd->CommonCfg.vht_cent_ch + UCHAR CentralChannel; //kepp original pAd->CommonCfg.CentralChannel + UCHAR Channel;// keep original pAd->CommonCfg.Channel + + ULONG AgeOutTime; // ms for AgeOutTimer + RALINK_TIMER_STRUCT AgeOutTimer; + BOOLEAN AgeOutTimer_Running; + RTMP_OS_SEM MAC_ListLock; + DL_LIST MAC_List; + BOOLEAN CheckAllMAC; +} SNIFFER_MIB_CTRL, *PSNIFFER_MIB_CTRL; + +INT sniffer_channel_restore(IN RTMP_ADAPTER *pAd); + +VOID sniffer_mib_ctrlInit(IN PRTMP_ADAPTER pAd); +VOID sniffer_mib_ctrlExit(IN PRTMP_ADAPTER pAd); + +INT exsta_proc(IN RTMP_ADAPTER *pAd, IN RTMP_STRING *arg); +INT exsta_list_proc(IN RTMP_ADAPTER *pAd, IN RTMP_STRING *arg); +INT exsta_clear_proc(IN RTMP_ADAPTER *pAd, IN RTMP_STRING *arg); +INT exsta_scan_proc(IN RTMP_ADAPTER *pAd, IN RTMP_STRING *arg); + +INT set_mib_passive_scan_proc(IN RTMP_ADAPTER *pAd, IN RTMP_STRING *arg); +INT set_mib_scan_interval_proc(IN RTMP_ADAPTER *pAd, IN RTMP_STRING *arg); +INT set_mib_scan_scope_proc(IN RTMP_ADAPTER *pAd, IN RTMP_STRING *arg); +INT set_mib_scan_channel_proc(IN RTMP_ADAPTER *pAd, IN RTMP_STRING *arg); + +#endif /* __SNIFFER_MIB_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/spectrum.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/spectrum.h new file mode 100644 index 000000000..5ebc80fde --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/spectrum.h @@ -0,0 +1,219 @@ + +#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(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_TpcReq_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_PwrConstraint(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#ifdef DOT11K_RRM_SUPPORT +#endif /* DOT11K_RRM_SUPPORT */ + +NDIS_STATUS MeasureReqTabInit( + IN PRTMP_ADAPTER pAd); + +VOID MeasureReqTabExit( + IN PRTMP_ADAPTER pAd); + +PMEASURE_REQ_ENTRY MeasureReqLookUp( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken); + +PMEASURE_REQ_ENTRY MeasureReqInsert( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken); + +VOID MeasureReqDelete( + IN PRTMP_ADAPTER pAd, + IN UINT8 DialogToken); + +VOID InsertChannelRepIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN RTMP_STRING *pCountry, + IN UINT8 RegulatoryClass, + IN UINT8 *ChReptList); + +VOID InsertBcnReportIndicationReqIE( + IN RTMP_ADAPTER *pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Data +); + +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/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/spectrum_def.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/spectrum_def.h new file mode 100644 index 000000000..4589f9935 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/spectrum_def.h @@ -0,0 +1,261 @@ +/**************************************************************************** + * 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 enum { + REG_LOCAL, + REG_GLOBAL +} REG_DOMAIN; + +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. */ + BOOLEAN skip_time_check; + UINT8 CurrentState; + void *Priv; + RALINK_TIMER_STRUCT WaitNRRspTimer; + UINT8 StaMac[MAC_ADDR_LEN]; + UCHAR ControlIndex; + RALINK_TIMER_STRUCT WaitBCNRepTimer; +} 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; + + +typedef struct _DOT11_REGULATORY_INFO +{ + UCHAR RegulatoryClass; + DOT11_CHANNEL_SET ChannelSet; +} DOT11_REGULATORY_INFO; + + + +#define RM_TPC_REQ 0 +#define RM_MEASURE_REQ 1 + +#define RM_BASIC 0 +#define RM_CCA 1 +#define RM_RPI_HISTOGRAM 2 +#define RM_CH_LOAD 3 +#define RM_NOISE_HISTOGRAM 4 + + +typedef struct GNU_PACKED _TPC_REPORT_INFO +{ + UINT8 TxPwr; + UINT8 LinkMargin; +} TPC_REPORT_INFO, *PTPC_REPORT_INFO; + +typedef struct GNU_PACKED _CH_SW_ANN_INFO +{ + UINT8 ChSwMode; + UINT8 Channel; + UINT8 ChSwCnt; +} CH_SW_ANN_INFO, *PCH_SW_ANN_INFO; + +typedef union GNU_PACKED _MEASURE_REQ_MODE +{ +#ifdef RT_BIG_ENDIAN + struct GNU_PACKED + { + + UINT8 :3; + UINT8 DurationMandatory:1; + UINT8 Report:1; + UINT8 Request:1; + UINT8 Enable:1; + UINT8 Parallel:1; + } field; +#else + struct GNU_PACKED + { + UINT8 Parallel:1; + UINT8 Enable:1; + UINT8 Request:1; + UINT8 Report:1; + UINT8 DurationMandatory:1; + UINT8 :3; + } field; +#endif /* RT_BIG_ENDIAN */ + UINT8 word; +} MEASURE_REQ_MODE, *PMEASURE_REQ_MODE; + +typedef struct GNU_PACKED _MEASURE_REQ +{ + UINT8 ChNum; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; +} MEASURE_REQ, *PMEASURE_REQ; + +typedef struct GNU_PACKED _MEASURE_REQ_INFO +{ + UINT8 Token; + MEASURE_REQ_MODE ReqMode; + UINT8 ReqType; + UINT8 Oct[0]; +} MEASURE_REQ_INFO, *PMEASURE_REQ_INFO; + +typedef union GNU_PACKED _MEASURE_BASIC_REPORT_MAP +{ +#ifdef RT_BIG_ENDIAN + struct GNU_PACKED + { + UINT8 Rev:3; + + UINT8 Unmeasure:1; + UINT8 Radar:1; + UINT8 UnidentifiedSignal:1; + UINT8 OfdmPreamble:1; + UINT8 BSS:1; + } field; +#else + struct GNU_PACKED + { + UINT8 BSS:1; + + UINT8 OfdmPreamble:1; + UINT8 UnidentifiedSignal:1; + UINT8 Radar:1; + UINT8 Unmeasure:1; + UINT8 Rev:3; + } field; +#endif /* RT_BIG_ENDIAN */ + UINT8 word; +} MEASURE_BASIC_REPORT_MAP, *PMEASURE_BASIC_REPORT_MAP; + +typedef struct GNU_PACKED _MEASURE_BASIC_REPORT +{ + UINT8 ChNum; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; + MEASURE_BASIC_REPORT_MAP Map; +} MEASURE_BASIC_REPORT, *PMEASURE_BASIC_REPORT; + +typedef struct GNU_PACKED _MEASURE_CCA_REPORT +{ + UINT8 ChNum; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; + UINT8 CCA_Busy_Fraction; +} MEASURE_CCA_REPORT, *PMEASURE_CCA_REPORT; + +typedef struct GNU_PACKED _MEASURE_RPI_REPORT +{ + UINT8 ChNum; + UINT64 MeasureStartTime; + UINT16 MeasureDuration; + UINT8 RPI_Density[8]; +} MEASURE_RPI_REPORT, *PMEASURE_RPI_REPORT; + +typedef union GNU_PACKED _MEASURE_REPORT_MODE +{ + struct GNU_PACKED + { +#ifdef RT_BIG_ENDIAN + UINT8 Rev:5; + UINT8 Refused:1; + UINT8 Incapable:1; + UINT8 Late:1; +#else + UINT8 Late:1; + UINT8 Incapable:1; + UINT8 Refused:1; + UINT8 Rev:5; +#endif /* RT_BIG_ENDIAN */ + } field; + UINT8 word; +} MEASURE_REPORT_MODE, *PMEASURE_REPORT_MODE; + +typedef struct GNU_PACKED _MEASURE_REPORT_INFO +{ + UINT8 Token; + UINT8 ReportMode; + UINT8 ReportType; + UINT8 Octect[0]; +} MEASURE_REPORT_INFO, *PMEASURE_REPORT_INFO; + +typedef struct GNU_PACKED _QUIET_INFO +{ + UINT8 QuietCnt; + UINT8 QuietPeriod; + UINT16 QuietDuration; + UINT16 QuietOffset; +} QUIET_INFO, *PQUIET_INFO; + +#endif /* __SPECTRUM_DEF_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sta.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sta.h new file mode 100644 index 000000000..fc0aa8dc6 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sta.h @@ -0,0 +1,131 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + sta.h + + Abstract: + Miniport generic portion header file + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __STA_H__ +#define __STA_H__ + + +#define STA_NO_SECURITY_ON(_p) (_p->StaCfg.wdev.WepStatus == Ndis802_11EncryptionDisabled) +#define STA_WEP_ON(_p) (_p->StaCfg.wdev.WepStatus == Ndis802_11WEPEnabled) +#define STA_TKIP_ON(_p) (_p->StaCfg.wdev.WepStatus == Ndis802_11TKIPEnable) +#define STA_AES_ON(_p) (_p->StaCfg.wdev.WepStatus == Ndis802_11AESEnable) + +#define STA_TGN_WIFI_ON(_p) (_p->StaCfg.bTGnWifiTest == TRUE) + +#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 STA_EXTRA_SETTING(_pAd) +#ifdef DOT11R_FT_SUPPORT +#undef STA_EXTRA_SETTING +#define STA_EXTRA_SETTING(_pAd) \ +{ \ + if ((_pAd)->StaCfg.Dot11RCommInfo.bFtSupport && \ + (_pAd)->MlmeAux.MdIeInfo.Len && \ + (_pAd)->StaCfg.AuthMode == Ndis802_11AuthModeWPA2PSK) \ + (_pAd)->StaCfg.Dot11RCommInfo.bInMobilityDomain = TRUE; \ +} +#endif /* DOT11R_FT_SUPPORT */ + +#define STA_PORT_SECURED(_pAd) \ +{ \ + BOOLEAN Cancelled; \ + (_pAd)->StaCfg.wdev.PortSecured = WPA_802_1X_PORT_SECURED; \ + RTMP_IndicateMediaState(_pAd, NdisMediaStateConnected); \ + NdisAcquireSpinLock(&((_pAd)->MacTabLock)); \ + (_pAd)->MacTab.tr_entry[BSSID_WCID].PortSecured = (_pAd)->StaCfg.wdev.PortSecured; \ + (_pAd)->MacTab.Content[BSSID_WCID].PrivacyFilter = Ndis802_11PrivFilterAcceptAll;\ + NdisReleaseSpinLock(&(_pAd)->MacTabLock); \ + RTMPCancelTimer(&((_pAd)->Mlme.LinkDownTimer), &Cancelled);\ + STA_EXTRA_SETTING(_pAd); \ +} + + +BOOLEAN RTMPCheckChannel(RTMP_ADAPTER *pAd, UCHAR CentralCh, UCHAR Ch); + +VOID InitChannelRelatedValue(RTMP_ADAPTER *pAd); + +VOID AdjustChannelRelatedValue( + IN PRTMP_ADAPTER pAd, + OUT UCHAR *pBwFallBack, + IN USHORT ifIndex, + IN BOOLEAN BandWidth, + IN UCHAR PriCh, + IN UCHAR ExtraCh); + +VOID RTMPReportMicError( + IN PRTMP_ADAPTER pAd, + IN PCIPHER_KEY pWpaKey); + +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(RTMP_ADAPTER *pAd); +VOID WpaStaGroupKeySetting(RTMP_ADAPTER *pAd); +VOID WpaSendEapolStart(RTMP_ADAPTER *pAd, UCHAR *pBssid); + + +NDIS_STATUS STAHardTransmit(RTMP_ADAPTER *pAd, TX_BLK *pTxBlk); +INT STASendPacket(RTMP_ADAPTER *pAd, PNDIS_PACKET pPacket); +INT STASendPacket_New(RTMP_ADAPTER *pAd, PNDIS_PACKET pPacket); + +INT StaAllowToSendPacket( + RTMP_ADAPTER *pAd, + struct wifi_dev *wdev, + PNDIS_PACKET pPacket, + UCHAR *pWcid); + +INT StaAllowToSendPacket_new( + IN RTMP_ADAPTER *pAd, + IN struct wifi_dev *wdev, + IN PNDIS_PACKET pPacket, + IN UCHAR *pWcid); + +INT sta_rx_pkt_allow(RTMP_ADAPTER *pAd, RX_BLK *pRxBlk); +INT sta_rx_fwd_hnd(RTMP_ADAPTER *pAd, struct wifi_dev *wdev, PNDIS_PACKET pkt); + +INT sta_func_init(RTMP_ADAPTER *pAd); + +INT STAInitialize(RTMP_ADAPTER *pAd); + +/* AD-HOC Related Function */ +BOOLEAN Adhoc_AddPeerfromBeacon(RTMP_ADAPTER *pAd, BCN_IE_LIST *bcn_ie_list, + NDIS_802_11_VARIABLE_IEs *pVIE, USHORT LenVIE); + +VOID Adhoc_checkPeerBeaconLost(RTMP_ADAPTER *pAd); +VOID LinkUp_Adhoc(RTMP_ADAPTER *pAd, struct wifi_dev *wdev); +ULONG MakeIbssBeacon(RTMP_ADAPTER *pAd); +#endif /* __STA_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sta_cfg.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sta_cfg.h new file mode 100644 index 000000000..6cc008b11 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/sta_cfg.h @@ -0,0 +1,63 @@ +/* + *************************************************************************** + * 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 RTMP_STRING *SetProcName, + IN RTMP_STRING *ProcArg); + +#if (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) || defined(MT_WOW_SUPPORT) +/* set WOW enable */ +INT Set_WOW_Enable(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +/* set GPIO pin for wake-up signal */ +INT Set_WOW_GPIO(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +/* set delay time for WOW really enable */ +INT Set_WOW_Delay(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +/* set wake up hold time */ +INT Set_WOW_Hold(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +/* set wakeup signal type */ +INT Set_WOW_InBand(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +/* set wakeup interface */ +INT Set_WOW_Interface(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +/* set wakeup GPIO High Low */ +INT Set_WOW_GPIOHighLow(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +#endif /* (defined(WOW_SUPPORT) && defined(RTMP_MAC_USB)) || defined(NEW_WOW_SUPPORT) || defined(MT_WOW_SUPPORT)*/ + + +#ifdef HE_BD_CFG80211_SUPPORT +/* 1: recover to original bit setting + 0: reset to HT40_DISABLE_SHORT_GI and BSS_COEX_DISABLE setting */ +INT set_ht40_test_enable(RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif /* HE_BD_CFG80211_SUPPORT */ +#endif /* __STA_CFG_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/tx_power.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/tx_power.h new file mode 100644 index 000000000..4c8ae4bd2 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/tx_power.h @@ -0,0 +1,70 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ +#ifndef __TX_PWR_H__ +#define __TX_PWR_H__ + +#ifdef MT_MAC +#include "mt_tx_pwr.h" +#endif + +#define DEFAULT_BO 4 +#define LIN2DB_ERROR_CODE (-10000) + +#define G_BAND_LOW 0 +#define G_BAND_MID 1 +#define G_BAND_HI 2 + +#define A_BAND_LOW 0 +#define A_BAND_HI 1 + +#ifdef SINGLE_SKU_V2 +#define SKU_PHYMODE_CCK_1M_2M 0 +#define SKU_PHYMODE_CCK_5M_11M 1 +#define SKU_PHYMODE_OFDM_6M_9M 2 +#define SKU_PHYMODE_OFDM_12M_18M 3 +#define SKU_PHYMODE_OFDM_24M_36M 4 +#define SKU_PHYMODE_OFDM_48M_54M 5 +#define SKU_PHYMODE_HT_MCS0_MCS1 6 +#define SKU_PHYMODE_HT_MCS2_MCS3 7 +#define SKU_PHYMODE_HT_MCS4_MCS5 8 +#define SKU_PHYMODE_HT_MCS6_MCS7 9 +#define SKU_PHYMODE_HT_MCS8_MCS9 10 +#define SKU_PHYMODE_HT_MCS10_MCS11 11 +#define SKU_PHYMODE_HT_MCS12_MCS13 12 +#define SKU_PHYMODE_HT_MCS14_MCS15 13 +#define SKU_PHYMODE_STBC_MCS0_MCS1 14 +#define SKU_PHYMODE_STBC_MCS2_MCS3 15 +#define SKU_PHYMODE_STBC_MCS4_MCS5 16 +#define SKU_PHYMODE_STBC_MCS6_MCS7 17 +#endif /* SINGLE_SKU_V2 */ + +VOID LoadTssiInfoFromEEPROM(struct _RTMP_ADAPTER *pAd); +INT32 get_low_mid_hi_index(UINT8 Channel); +#ifdef RTMP_INTERNAL_TX_ALC +INT16 MT76xx_lin2dBd( + IN UINT16 linearValue); +#endif /* RTMP_INTERNAL_TX_ALC */ +#endif /* __TX_PWR_H__ */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/uapsd.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/uapsd.h new file mode 100644 index 000000000..20d494a48 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/uapsd.h @@ -0,0 +1,729 @@ +/**************************************************************************** + * 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 tsf_l=0, tsf_h=0; UINT64 __Value64; \ + AsicGetTsfTime((__pAd), &tsf_h, &tsf_l);\ + __TimeStamp = (UINT64)tsf_l; \ + __Value64 = (UINT64)tsf_h; \ + __TimeStamp |= (tsf_h << 32); \ + } + +#define UAPSD_TIME_GET(__pAd, __Time) \ + { \ + NdisGetSystemUpTime(&__Time); \ + } + + +/* uapsd initialization */ +#define UAPSD_INFO_INIT(__pInfo) \ +{ \ + (__pInfo)->bAPSDCapable = FALSE; \ +} + +#define UAPSD_SP_START(__pAd, __pEntry) \ + __pEntry->bAPSDFlagSPStart = 1; + +/* for AP, we maybe sleep until all SPs are closed */ +#define UAPSD_SP_END(__pAd, __pEntry) \ + __pEntry->bAPSDFlagSPStart = 0; + + + +/* 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", \ + PRINT_MAC(__pMacEntry->Addr), __pMacEntry->PsMode)); \ +} + +/* check if the peer virtual ps mode timeout */ +#define RTMP_PS_VIRTUAL_TIMEOUT_HANDLE(__pMacEntry) \ +{ \ + if (__pMacEntry->VirtualTimeout > 0) \ + { \ + __pMacEntry->VirtualTimeout --; \ + if (__pMacEntry->VirtualTimeout == 0) \ + { \ + DBGPRINT(RT_DEBUG_TRACE, \ + ("tdls uapsd> virtual ps timeout!\n")); \ + RTMP_PS_VIRTUAL_SLEEP(__pMacEntry); \ + } \ + } \ +} + +/* extern MACRO & function */ +#ifndef MODULE_WMM_UAPSD + +#define UAPSD_EXTERN extern + +/* Public Marco list */ + +/* + Init some parameters in packet structure for QoS Null frame; + purpose: is for management frame tx done use +*/ +#define UAPSD_MR_QOS_NULL_HANDLE(__pAd, __pData, __pPacket) \ + { \ + PHEADER_802_11 __pHeader = (PHEADER_802_11)(__pData); \ + MAC_TABLE_ENTRY *__pEntry; \ + if (__pHeader->FC.SubType == SUBTYPE_QOS_NULL) \ + { \ + RTMP_SET_PACKET_QOS_NULL((__pPacket)); \ + __pEntry = MacTableLookup((__pAd), __pHeader->Addr1); \ + if (__pEntry != NULL) \ + { \ + RTMP_SET_PACKET_WCID((__pPacket), __pEntry->wcid); \ + } \ + } \ + else \ + { \ + RTMP_SET_PACKET_NON_QOS_NULL((__pPacket)); \ + } \ + } + +/* + Init MAC entry UAPSD parameters; + purpose: initialize UAPSD PS queue and control parameters +*/ +#define UAPSD_MR_ENTRY_INIT(__pEntry) \ + { \ + UINT16 __IdAc; \ + for(__IdAc=0; __IdAcUAPSDQueue[__IdAc]); \ + (__pEntry)->UAPSDTxNum = 0; \ + (__pEntry)->pUAPSDEOSPFrame = NULL; \ + (__pEntry)->bAPSDFlagSPStart = 0; \ + (__pEntry)->bAPSDFlagEOSPOK = 0; \ + (__pEntry)->MaxSPLength = 0; \ + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> MaxSPLength = 0!\n")); \ + } + +/* + Reset MAC entry UAPSD parameters; + purpose: clean all UAPSD PS queue; release the EOSP frame if exists; + reset control parameters +*/ +#define UAPSD_MR_ENTRY_RESET(__pAd, __pEntry) \ + { \ + MAC_TABLE_ENTRY *__pSta; \ + UINT32 __IdAc; \ + __pSta = (__pEntry); \ + /* clear all U-APSD queues */ \ + for(__IdAc=0; __IdAcUAPSDQueue[__IdAc]); \ + /* clear EOSP frame */ \ + __pSta->UAPSDTxNum = 0; \ + if (__pSta->pUAPSDEOSPFrame != NULL) { \ + RELEASE_NDIS_PACKET((__pAd), \ + QUEUE_ENTRY_TO_PACKET(__pSta->pUAPSDEOSPFrame), \ + NDIS_STATUS_FAILURE); \ + __pSta->pUAPSDEOSPFrame = NULL; } \ + __pSta->bAPSDFlagSPStart = 0; \ + __pSta->bAPSDFlagEOSPOK = 0; \ + UAPSD_SP_END(__pAd, __pSta); \ + DBGPRINT(RT_DEBUG_TRACE, ("uapsd> clear UAPSD queues!\n")); } + +/* + * we can not use bMoreData bit to get EOSP bit because + * maybe bMoreData = 1 & EOSP = 1 when Max SP Length != 0 + */ +#define UAPSD_MR_EOSP_SET(__pQosCtrl, __pTxBlk) \ + if (CLIENT_STATUS_TEST_FLAG((__pTxBlk)->pMacEntry, \ + fCLIENT_STATUS_APSD_CAPABLE)) { \ + if (TX_BLK_TEST_FLAG((__pTxBlk), fTX_bWMM_UAPSD_EOSP)) \ + *(__pQosCtrl) |= (1 << 4); \ + } + +/* + Enable or disable UAPSD flag in WMM element in beacon frame; + purpose: set UAPSD enable/disable bit +*/ +#define UAPSD_MR_IE_FILL(__QosCtrlField, __pUapsdInfo) \ + (__QosCtrlField) |= ((__pUapsdInfo)->bAPSDCapable) ? 0x80 : 0x00; + +/* + Check if we do NOT need to control TIM bit for the station; + note: we control TIM bit only when all AC are UAPSD AC +*/ +#define UAPSD_MR_IS_NOT_TIM_BIT_NEEDED_HANDLED(__pMacEntry, __QueIdx) \ + (CLIENT_STATUS_TEST_FLAG((__pMacEntry), fCLIENT_STATUS_APSD_CAPABLE) && \ + (!(__pMacEntry)->bAPSDDeliverEnabledPerAC[QID_AC_VO] || \ + !(__pMacEntry)->bAPSDDeliverEnabledPerAC[QID_AC_VI] || \ + !(__pMacEntry)->bAPSDDeliverEnabledPerAC[QID_AC_BE] || \ + !(__pMacEntry)->bAPSDDeliverEnabledPerAC[QID_AC_BK]) && \ + (__pMacEntry)->bAPSDDeliverEnabledPerAC[__QueIdx]) + +/* check if the AC is UAPSD delivery-enabled AC */ +#define UAPSD_MR_IS_UAPSD_AC(__pMacEntry, __AcId) \ + (CLIENT_STATUS_TEST_FLAG((__pMacEntry), fCLIENT_STATUS_APSD_CAPABLE) && \ + ((0 <= (__AcId)) && ((__AcId) < WMM_NUM_OF_AC)) && /* 0 ~ 3 */ \ + (__pMacEntry)->bAPSDDeliverEnabledPerAC[(__AcId)]) + +/* check if all AC are UAPSD delivery-enabled AC */ +#define UAPSD_MR_IS_ALL_AC_UAPSD(__FlgIsActive, __pMacEntry) \ + (((__FlgIsActive) == FALSE) && ((__pMacEntry)->bAPSDAllAC == 1)) + +/* suspend SP */ +#define UAPSD_MR_SP_SUSPEND(__pAd) \ + (__pAd)->bAPSDFlagSPSuspend = 1; + +/* resume SP */ +#define UAPSD_MR_SP_RESUME(__pAd) \ + (__pAd)->bAPSDFlagSPSuspend = 0; + +/* mark PS poll frame sent in mix mode */ +#ifdef RTMP_MAC_PCI +/* + Note: + (1) When SP is not started, try to mark a flag to record if the legacy ps + packet is handled in statistics handler; + (2) When SP is started, increase the UAPSD count number for the legacy PS. +*/ +#define UAPSD_MR_MIX_PS_POLL_RCV(__pAd, __pMacEntry) \ + if ((__pMacEntry)->bAPSDFlagSpRoughUse == 0) \ + { \ + if ((__pMacEntry)->bAPSDFlagSPStart == 0) \ + { \ + if ((__pMacEntry)->bAPSDFlagLegacySent == 1) \ + NICUpdateFifoStaCounters((__pAd)); \ + (__pMacEntry)->bAPSDFlagLegacySent = 1; \ + } \ + else \ + { \ + (__pMacEntry)->UAPSDTxNum ++; \ + } \ + } +#endif /* RTMP_MAC_PCI */ + + +#else + +#define UAPSD_EXTERN +#define UAPSD_QOS_NULL_QUE_ID 0x7f + +#ifdef RTMP_MAC_PCI +/* + In RT2870, FIFO counter is for all stations, not for per-entry, + so we can not use accurate method in RT2870 +*/ + +/* + Note for SP ACCURATE Mechanism: + 1. When traffic is busy for the PS station + Statistics FIFO counter maybe overflow before we read it, so UAPSD + counting mechanism will not accurately. + + Solution: + We need to avoid the worse case so we suggest a maximum interval for + a SP that the interval between last frame from QAP and data frame from + QSTA is larger than UAPSD_EPT_SP_INT. + + 2. When traffic use CCK/1Mbps from QAP + Statistics FIFO will not count the packet. There are 2 cases: + (1) We force to downgrage ARP response & DHCP packet to 1Mbps; + (2) After rate switch mechanism, tx rate is fixed to 1Mbps. + + Solution: + Use old DMA UAPSD mechanism. + + 3. When part of AC uses legacy PS mode + Statistics count will inclue packet statistics for legacy PS packets + so we can not know which one is UAPSD, which one is legacy. + + Solution: + Cound the legacy PS packet. + + 4. Check FIFO statistics count in Rx Done function + We can not to check TX FIFO statistics count in Rx Done function or + the real packet tx/rx sequence will be disarranged. + + Solution: + Suspend SP handle before rx done and resume SP handle after rx done. +*/ +// TODO: shiang-usw, why PCI need to disable this when run P2P Sigma 6.1.12??? +#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, + IN BOOLEAN bFromHead); + + +/* +======================================================================== +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, + IN BOOLEAN FlgIsLocked); + + +/* +======================================================================== +Routine Description: + Maintenance our UAPSD PS queue. Release all queued packet if timeout. + +Arguments: + pAd Pointer to our adapter + *pEntry STATION + +Return Value: + None + +Note: + If in RT2870, pEntry can not be removed during UAPSD_QueueMaintenance() +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_QueueMaintenance( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry); + + +/* +======================================================================== +Routine Description: + Close SP in Tx Done, not Tx DMA Done. + +Arguments: + pAd Pointer to our adapter + pEntry destination entry + FlgSuccess 0:tx success, 1:tx fail + +Return Value: + None + +Note: + For RT28xx series, for packetID=0 or multicast frame, no statistics + count can be got, ex: ARP response or DHCP packets, we will use + low rate to set (CCK, MCS=0=packetID). + So SP will not be close until UAPSD_EPT_SP_INT timeout. + + So if the tx rate is 1Mbps for a entry, we will use DMA done, not + use UAPSD_SP_AUE_Handle(). +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_SP_AUE_Handle( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR FlgSuccess); + + +/* +======================================================================== +Routine Description: + Close current Service Period. + +Arguments: + pAd Pointer to our adapter + +Return Value: + None + +Note: + When we receive EOSP frame tx done interrupt and a uplink packet + from the station simultaneously, we will regard it as a new trigger + frame because the packet is received when EOSP frame tx done interrupt. + + We can not sure the uplink packet is sent after old SP or in the old SP. + So we must close the old SP in receive done ISR to avoid the problem. +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_SP_CloseInRVDone( + IN PRTMP_ADAPTER pAd); + + +/* +======================================================================== +Routine Description: + Check if we need to close current SP. + +Arguments: + pAd Pointer to our adapter + pPacket Completed TX packet + pDstMac Destinated MAC address + +Return Value: + None + +Note: + 1. We need to call the function in TxDone ISR. + 2. SMP protection by caller for packet enqueue. +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_SP_PacketCheck( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPacket, + IN UCHAR *pDstMac); + + +#ifdef UAPSD_TIMING_RECORD_FUNC +/* +======================================================================== +Routine Description: + Enable/Disable Timing Record Function. + +Arguments: + pAd Pointer to our adapter + Flag 1 (Enable) or 0 (Disable) + +Return Value: + None + +Note: +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_TimingRecordCtrl( + IN UINT32 Flag); + +/* +======================================================================== +Routine Description: + Record some timings. + +Arguments: + pAd Pointer to our adapter + Type The timing is for what type + +Return Value: + None + +Note: + UAPSD_TIMING_RECORD_ISR + UAPSD_TIMING_RECORD_TASKLET + UAPSD_TIMING_RECORD_TRG_RCV + UAPSD_TIMING_RECORD_MOVE2TX + UAPSD_TIMING_RECORD_TX2AIR +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_TimingRecord( + IN PRTMP_ADAPTER pAd, + IN UINT32 Type); + +/* +======================================================================== +Routine Description: + Record the loop index for received packet handle. + +Arguments: + pAd Pointer to our adapter + LoopIndex The RxProcessed in rtmp_rx_done_handle() + +Return Value: + None + +Note: +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_TimeingRecordLoopIndex( + IN UINT32 LoopIndex); +#endif /* UAPSD_TIMING_RECORD_FUNC */ + + +/* +======================================================================== +Routine Description: + Get the queue status for delivery-enabled AC. + +Arguments: + pAd Pointer to our adapter + pEntry the peer entry + pFlgIsAnyPktForBK TRUE: At lease a BK packet is queued + pFlgIsAnyPktForBE TRUE: At lease a BE packet is queued + pFlgIsAnyPktForVI TRUE: At lease a VI packet is queued + pFlgIsAnyPktForVO TRUE: At lease a VO packet is queued + +Return Value: + None + +Note: +======================================================================== +*/ +VOID UAPSD_QueueStatusGet( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + OUT BOOLEAN *pFlgIsAnyPktForBK, + OUT BOOLEAN *pFlgIsAnyPktForBE, + OUT BOOLEAN *pFlgIsAnyPktForVI, + OUT BOOLEAN *pFlgIsAnyPktForVO); + + +/* +======================================================================== +Routine Description: + Handle UAPSD Trigger Frame. + +Arguments: + pAd Pointer to our adapter + *pEntry the source STATION + UpOfFrame the UP of the trigger frame + +Return Value: + None + +Note: +======================================================================== +*/ +UAPSD_EXTERN VOID UAPSD_TriggerFrameHandle( + IN PRTMP_ADAPTER pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN UCHAR UpOfFrame); + + + +/* End of ap_uapsd.h */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/vendor.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/vendor.h new file mode 100644 index 000000000..ad327ff0c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/vendor.h @@ -0,0 +1,166 @@ +#ifdef CONFIG_OWE_SUPPORT +#include "rtmp.h" +#endif + +struct _RTMP_ADAPTER; + +#define RALINK_IE_LEN 0x9 +#define MEDIATEK_IE_LEN 0x9 + +#ifdef CONFIG_OWE_SUPPORT +#define OUI_LEN 3 +#define MAX_VENDOR_IE_LEN 255 +#endif + +#define RALINK_AGG_CAP (1 << 0) +#define RALINK_PIGGY_CAP (1 << 1) +#define RALINK_RDG_CAP (1 << 2) +#define RALINK_256QAM_CAP (1 << 3) + +#define MEDIATEK_256QAM_CAP (1 << 3) +#ifdef WH_EZ_SETUP +#define MEDIATEK_EASY_SETUP (1 << 6) +#endif +#ifdef MWDS +#define MEDIATEK_MWDS_CAP (1 << 7) +#endif +#define BROADCOM_256QAM_CAP (1 << 0) + + +#ifdef CONFIG_OWE_SUPPORT +#define VIE_BEACON_BITMAP (1 << VIE_BEACON) +#define VIE_PROBE_REQ_BITMAP (1 << VIE_PROBE_REQ) +#define VIE_PROBE_RESP_BITMAP (1 << VIE_PROBE_RESP) +#define VIE_ASSOC_REQ_BITMAP (1 << VIE_ASSOC_REQ) +#define VIE_ASSOC_RESP_BITMAP (1 << VIE_ASSOC_RESP) +#define VIE_AUTH_REQ_BITMAP (1 << VIE_AUTH_REQ) +#define VIE_AUTH_RESP_BITMAP (1 << VIE_AUTH_RESP) +#define VIE_FRM_TYPE_MAX_BITMAP (1 << VIE_FRM_TYPE_MAX) /*for sanity check purpose*/ + +#define GET_VIE_FRM_BITMAP(_frm_type) (1 << _frm_type) + + + +typedef enum vendor_ie_oper { + VIE_ADD = 1, + VIE_UPDATE, + VIE_REMOVE, + VIE_SHOW, + VIE_OPER_MAX, +} VIE_OPERATION; + + + +INT32 add_vie(struct _RTMP_ADAPTER *pAd, + struct wifi_dev *wdev, + UINT32 frm_type_map, + UINT32 oui_oitype, + ULONG ie_length, + UCHAR *frame_buffer); + +INT32 remove_vie(struct _RTMP_ADAPTER *pAd, + struct wifi_dev *wdev, + UINT32 frm_type_map, + UINT32 oui_oitype, + ULONG ie_length, + UCHAR *frame_buffer); + +VOID print_vie(struct wifi_dev *wdev, UINT32 frm_map); + +VOID init_vie_ctrl(struct wifi_dev *wdev); +VOID deinit_vie_ctrl(struct wifi_dev *wdev); +INT vie_oper_proc(struct _RTMP_ADAPTER *pAd, RTMP_STRING *arg); +#endif + +#ifdef STA_FORCE_ROAM_SUPPORT +#define MEDIATEK_CLI_ENTRY (1 << 4) +#endif + +typedef struct GNU_PACKED _ie_hdr { + UCHAR eid; + UINT8 len; +} IE_HEADER; + +#ifdef CONFIG_OWE_SUPPORT +struct GNU_PACKED _generic_vie_t { + IE_HEADER ie_hdr; + UCHAR vie_ctnt[MAX_VENDOR_IE_LEN]; +}; +#endif + +struct GNU_PACKED _ralink_ie { + IE_HEADER ie_hdr; + UCHAR oui[3]; + UCHAR cap0; + UCHAR cap1; + UCHAR cap2; + UCHAR cap3; +}; + + +typedef struct GNU_PACKED _vht_cap_ie { + IE_HEADER ie_hdr; + UCHAR vht_cap_info[4]; + UCHAR support_vht_mcs_nss[8]; +} VHT_CAP; + + +typedef struct GNU_PACKED _vht_op_ie { + IE_HEADER ie_hdr; + UCHAR vht_op_info[3]; + UCHAR basic_vht_mcs_nss[2]; +} VHT_OP; + + +typedef struct GNU_PACKED _vht_tx_pwr_env_ie { + IE_HEADER ie_hdr; + UCHAR tx_pwr_info; + UCHAR local_max_txpwr_20Mhz; + UCHAR local_max_txpwr_40Mhz; +} VHT_TX_PWR_ENV; + + +struct GNU_PACKED _mediatek_ie { + IE_HEADER ie_hdr; + UCHAR oui[3]; + UCHAR cap0; + UCHAR cap1; + UCHAR cap2; + UCHAR cap3; +}; + + +struct GNU_PACKED _mediatek_vht_ie { + VHT_CAP vht_cap; + VHT_OP vht_op; + VHT_TX_PWR_ENV vht_txpwr_env; +}; + + +struct GNU_PACKED _broadcom_ie { + IE_HEADER ie_hdr; + UCHAR oui[3]; + UCHAR fixed_pattern[2]; + VHT_CAP vht_cap; + VHT_OP vht_op; + VHT_TX_PWR_ENV vht_txpwr_env; +}; + + +ULONG build_vendor_ie(struct _RTMP_ADAPTER *pAd, + struct wifi_dev *wdev, + UCHAR *frame_buffer +#ifdef CONFIG_OWE_SUPPORT + , VIE_FRM_TYPE vie_frm_type +#endif +#ifdef WH_EZ_SETUP + , UCHAR SubType +#endif + ); + +#if defined(MWDS) || defined(MAP_SUPPORT) +VOID check_vendor_ie(struct _RTMP_ADAPTER *pAd, + UCHAR *ie_buffer, struct _vendor_ie_cap *vendor_ie); +#endif + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/vht.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/vht.h new file mode 100644 index 000000000..c7c2c8e74 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/vht.h @@ -0,0 +1,58 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "dot11ac_vht.h" + + +struct _RTMP_ADAPTER; +struct _RT_PHY_INFO; + + +VOID dump_vht_cap(struct _RTMP_ADAPTER *pAd, VHT_CAP_IE *vht_ie); +VOID dump_vht_op(struct _RTMP_ADAPTER *pAd, VHT_OP_IE *vht_ie); + +INT build_vht_txpwr_envelope(struct _RTMP_ADAPTER *pAd, UCHAR *buf); +INT build_vht_ies(struct _RTMP_ADAPTER *pAd, UCHAR *buf, UCHAR frm); +INT build_vht_cap_ie(struct _RTMP_ADAPTER *pAd, UCHAR *buf); + +UCHAR vht_prim_ch_idx(UCHAR vht_cent_ch, UCHAR prim_ch); +UCHAR vht_cent_ch_freq(struct _RTMP_ADAPTER *pAd, UCHAR prim_ch); +INT vht_mode_adjust(struct _RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, VHT_CAP_IE *cap, VHT_OP_IE *op); +INT SetCommonVHT(struct _RTMP_ADAPTER *pAd); +VOID rtmp_set_vht(struct _RTMP_ADAPTER *pAd, struct _RT_PHY_INFO *phy_info); + +#ifdef VHT_TXBF_SUPPORT +VOID trigger_vht_ndpa(struct _RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *entry); +#endif /* VHT_TXBF_SUPPORT */ + +void assoc_vht_info_debugshow( + IN RTMP_ADAPTER *pAd, + IN MAC_TABLE_ENTRY *pEntry, + IN VHT_CAP_IE *vht_cap, + IN VHT_OP_IE *vht_op); + +BOOLEAN vht80_channel_group( struct _RTMP_ADAPTER *pAd, UCHAR channel); + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/video.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/video.h new file mode 100644 index 000000000..54ec5e690 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/video.h @@ -0,0 +1,12 @@ +#ifdef VIDEO_TURBINE_SUPPORT +extern AP_VIDEO_STRUCT GLOBAL_AP_VIDEO_CONFIG; + +VOID VideoModeUpdate(IN PRTMP_ADAPTER pAd); +VOID VideoModeDynamicTune(IN PRTMP_ADAPTER pAd); +UINT32 GetAsicDefaultRetry(IN PRTMP_ADAPTER pAd); +UCHAR GetAsicDefaultTxBA(IN PRTMP_ADAPTER pAd); +UINT32 GetAsicVideoRetry(IN PRTMP_ADAPTER pAd); +UCHAR GetAsicVideoTxBA(IN PRTMP_ADAPTER pAd); +VOID VideoConfigInit(IN PRTMP_ADAPTER pAd); +#endif /* VIDEO_TURBINE_SUPPORT */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/vr_ikans.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/vr_ikans.h new file mode 100644 index 000000000..c5694cb85 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/vr_ikans.h @@ -0,0 +1,59 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + vr_ikans.h + + Abstract: + Only for IKANOS Vx160 or Vx180 platform. + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + Sample Lin 01-28-2008 Created + + */ + +#ifndef __VR_IKANS_H__ +#define __VR_IKANS_H__ + +#ifndef MODULE_IKANOS +#define IKANOS_EXTERN extern +#else +#define IKANOS_EXTERN +#endif /* MODULE_IKANOS */ + +#ifdef IKANOS_VX_1X0 + typedef void (*IkanosWlanTxCbFuncP)(void *, void *); + + struct IKANOS_TX_INFO + { + struct net_device *netdev; + IkanosWlanTxCbFuncP *fp; + }; +#endif /* IKANOS_VX_1X0 */ + + +IKANOS_EXTERN void VR_IKANOS_FP_Init(UINT8 BssNum, UINT8 *pApMac); + +IKANOS_EXTERN INT32 IKANOS_DataFramesTx(struct sk_buff *pSkb, + struct net_device *pNetDev); + +IKANOS_EXTERN void IKANOS_DataFrameRx(PRTMP_ADAPTER pAd, + struct sk_buff *pSkb); + +#endif /* __VR_IKANS_H__ */ + +/* End of vr_ikans.h */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/vrut_ubm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/vrut_ubm.h new file mode 100644 index 000000000..fab13c4ea --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/vrut_ubm.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * Ralink Tech Inc. + * Taiwan, R.O.C. + * + * (c) Copyright 2010, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + + Abstract: + + All Related Structure & Definition for UBICOM platform. + + Only used in UTIL module. + +***************************************************************************/ + +#ifndef __VR_UBICOM_H__ +#define __VR_UBICOM_H__ + +#ifdef PLATFORM_UBM_IPX8 + +#include + +#undef RTMP_UTIL_DCACHE_FLUSH +#define RTMP_UTIL_DCACHE_FLUSH(__AddrStart, __Size) \ + flush_dcache_range((ULONG)(__AddrStart), \ + (ULONG)(((UCHAR *)(__AddrStart)) + __Size - 1)) + +#endif /* PLATFORM_UBM_IPX8 */ + +#endif /* __VR_UBICOM_H__ */ + +/* End of vrut_ubm.h */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wapi.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wapi.h new file mode 100644 index 000000000..5fc26fa10 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wapi.h @@ -0,0 +1,185 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-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); + +VOID RTMPDeriveWapiGTK( + IN PUCHAR nmk, + OUT PUCHAR gtk_ptr); + +VOID RT_SMS4_TEST( + IN UINT8 test); + +INT SMS4_TEST(void); + +/* + ===================================== + function prototype in wapi.c + ===================================== +*/ + +BOOLEAN RTMPIsWapiCipher( + IN PRTMP_ADAPTER pAd, + IN UCHAR apidx); + +VOID RTMPIoctlQueryWapiConf( + IN PRTMP_ADAPTER pAd, + IN RTMP_IOCTL_INPUT_STRUCT *wrq); + +void rtmp_read_wapi_parms_from_file( + IN PRTMP_ADAPTER pAd, + char *tmpbuf, + char *buffer); + +VOID RTMPWapiUskRekeyPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID RTMPWapiMskRekeyPeriodicExec( + IN PVOID SystemSpecific1, + IN PVOID FunctionContext, + IN PVOID SystemSpecific2, + IN PVOID SystemSpecific3); + +VOID RTMPInitWapiRekeyTimerAction( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry); + +VOID RTMPStartWapiRekeyTimerAction( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry); + +VOID RTMPCancelWapiRekeyTimerAction( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry); + +VOID RTMPGetWapiTxTscFromAsic( + IN PRTMP_ADAPTER pAd, + IN UINT Wcid, + OUT UCHAR *tx_tsc); + +VOID WAPIInstallPairwiseKey( + PRTMP_ADAPTER pAd, + PMAC_TABLE_ENTRY pEntry, + BOOLEAN bAE); + +VOID WAPIInstallSharedKey( + PRTMP_ADAPTER pAd, + UINT8 GroupCipher, + UINT8 BssIdx, + UINT8 KeyIdx, + UINT8 Wcid, + PUINT8 pGtk); + +BOOLEAN WAPI_InternalCmdAction( + IN PRTMP_ADAPTER pAd, + IN UCHAR AuthMode, + IN UCHAR apidx, + IN PUCHAR pAddr, + IN UCHAR flag); + +#endif /* __WAPI_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wapi_def.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wapi_def.h new file mode 100644 index 000000000..774bdae1c --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wapi_def.h @@ -0,0 +1,179 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2005, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attempt + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + wapi_def.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __WAPI_DEF_H__ +#define __WAPI_DEF_H__ + +#ifndef IN +#define IN +#endif +#ifndef OUT +#define OUT +#endif +#ifndef INOUT +#define INOUT +#endif +#ifndef MAC_ADDR_LEN +#define MAC_ADDR_LEN 6 +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#define WAPI_IFNAMSIZ 16 +#define MAX_WAPI_MBSSID_NUM 8 +#define MAX_ID_NO 10 + +#define LENGTH_WAI_H 12 +#define LEN_WAPI_TSC 16 +#define LEN_WPI_MIC 16 +#define LEN_WPI_IV_HDR 18 +#define LEN_WAPI_NMK 16 +#define LEN_WAPI_GTK 32 + +/* trigger message from driver */ +#define WAI_MLME_CERT_AUTH_START 1 +#define WAI_MLME_KEY_HS_START 2 +#define WAI_MLME_UPDATE_BK 3 +#define WAI_MLME_UPDATE_USK 4 +#define WAI_MLME_UPDATE_MSK 5 +#define WAI_MLME_DISCONNECT 0xff + +#define WAPI_KEY_UPDATE_EXEC_INTV 1000 /* 1 sec */ + +/* WAPI rekey method */ +#define REKEY_METHOD_DISABLE 0 +#define REKEY_METHOD_TIME 1 +#define REKEY_METHOD_PKT 2 +/*#define REKEY_METHOD_TIME_PKT 3 */ + +#define STATUS_WAPI_KEY_INVALID 1 +#define STATUS_WAPI_IV_MISMATCH 2 +#define STATUS_WAPI_MIC_DIFF 3 + +extern UCHAR AE_BCAST_PN[LEN_WAPI_TSC]; +extern UCHAR ASUE_UCAST_PN[LEN_WAPI_TSC]; +extern UCHAR AE_UCAST_PN[LEN_WAPI_TSC]; + +/* WAPI authentication mode */ +typedef enum _WAPI_AUTH_MODE +{ + WAPI_AUTH_DISABLE, + WAPI_AUTH_PSK, + WAPI_AUTH_CERT, +} WAPI_AUTH_MODE, *PWAPI_AUTH_MODE; + +/* WAPI authentication mode */ +typedef enum _KEY_TYPE_MODE +{ + HEX_MODE, + ASCII_MODE +} KEY_TYPE_MODE, *PKEY_TYPE_MODE; + +/* the defintion of WAI header */ +typedef struct GNU_PACKED _HEADER_WAI { + USHORT version; + UCHAR type; + UCHAR sub_type; + USHORT reserved; + USHORT length; + USHORT pkt_seq; + UCHAR frag_seq; + UCHAR flag; +} HEADER_WAI, *PHEADER_WAI; + +/* For WAPI */ +typedef struct GNU_PACKED _WAPIIE { + USHORT version; + USHORT acount; + struct GNU_PACKED { + UCHAR oui[4]; + }auth[1]; +} WAPIIE, *PWAPIIE; + +/* unicast key suite */ +typedef struct GNU_PACKED _WAPIIE_UCAST { + USHORT ucount; + struct GNU_PACKED { + UCHAR oui[4]; + }ucast[1]; +} WAPIIE_UCAST,*PWAPIIE_UCAST; + +/* multi-cast key suite and capability */ +typedef struct GNU_PACKED _WAPIIE_MCAST { + UCHAR mcast[4]; + USHORT capability; +} WAPIIE_MCAST,*PWAPIIE_MCAST; + +/* the relative to wapi daemon */ +typedef struct GNU_PACKED _COMMON_WAPI_INFO +{ + UINT8 wapi_ifname[WAPI_IFNAMSIZ]; /* wai negotiation */ + UINT8 wapi_ifname_len; + UINT8 preauth_ifname[WAPI_IFNAMSIZ]; /* pre-authentication */ + UINT8 preauth_ifname_len; + UINT8 as_cert_no; + UINT8 as_cert_path[MAX_ID_NO][128]; /* the path of as certification */ + UINT8 as_cert_path_len[MAX_ID_NO]; + UINT8 ca_cert_path[128]; /* the path of ca certification */ + UINT8 ca_cert_path_len; + UINT8 user_cert_path[128]; /* the path of local user certification */ + UINT8 user_cert_path_len; + UINT32 wapi_as_ip; /* the ip address of authentication server */ + UINT32 wapi_as_port; /* the port of authentication server */ +} COMMON_WAPI_INFO, *PCOMMON_WAPI_INFO; + +typedef struct GNU_PACKED _MBSS_WAPI_INFO +{ + UINT8 ifname[WAPI_IFNAMSIZ]; + UINT8 ifname_len; + UINT8 auth_mode; + UINT8 psk[64]; + UINT8 psk_len; + UINT8 wie[128]; + UINT8 wie_len; +} MBSS_WAPI_INFO, *PMBSS_WAPI_INFO; + +/* It's used by wapi daemon to require relative configuration */ +typedef struct GNU_PACKED _WAPI_CONF +{ + UINT8 mbss_num; /* indicate multiple BSS number */ + COMMON_WAPI_INFO comm_wapi_info; + MBSS_WAPI_INFO mbss_wapi_info[MAX_WAPI_MBSSID_NUM]; +} WAPI_CONF, *PWAPI_CONF; + +#ifdef LINUX +#define WapiMoveMemory(Destination, Source, Length) memmove(Destination, Source, Length) +#define WapiZeroMemory(Destination, Length) memset(Destination, 0, Length) +#define WapiEqualMemory(Source1, Source2, Length) (!memcmp(Source1, Source2, Length)) +#endif /* LINUX */ + +#endif /* __WAPI_DEF_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wapi_sms4.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wapi_sms4.h new file mode 100644 index 000000000..ef90f2a46 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wapi_sms4.h @@ -0,0 +1,12 @@ + + +/* SMS4 encryption/decryption definition */ +/* Parameter : */ +/* Input - the incoming message packet */ +/* Ouput - the result ouput */ +/* rk - key */ +void SMS4Crypt(unsigned char *Input, unsigned char *Output, unsigned int *rk); + +/* SMS4 key extend algorithm */ +void SMS4KeyExt(unsigned char *Key, unsigned int *rk, unsigned int CryptFlag); + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wfa_p2p.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wfa_p2p.h new file mode 100644 index 000000000..233a40aa5 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wfa_p2p.h @@ -0,0 +1,37 @@ +/**************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * (c) Copyright 2002, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + **************************************************************************** + + Module Name: + wfa_p2p.h + + Abstract: + Defined status code, IE and frame structures that WiFi Direct needed. + + Revision History: + Who When What + --------- ---------- ---------------------------------------------- + + */ + + +#ifndef __WFA_P2P_H +#define __WFA_P2P_H + +#include "rtmp_type.h" + + + +#endif /* __WFA_P2P_H */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wfd.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wfd.h new file mode 100644 index 000000000..15700592d --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wfd.h @@ -0,0 +1,79 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2005-2011 Ralink Technology Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + Ralink Technology Corporation + 5F, No.5, Tai-Yuen 1st St., Jhubei City, + HsinChu Hsien 30265, Taiwan, R.O.C. + + + BSD LICENSE + + Copyright(c) 2005-2011 Ralink Technology Corporation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + + +/* + Module Name: + wfd.h + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + +*/ + + +#ifndef __WFD_H__ +#define __WFD_H__ + +#endif /* __WFD_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wfd_cmm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wfd_cmm.h new file mode 100644 index 000000000..2f33855f6 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wfd_cmm.h @@ -0,0 +1,79 @@ +/* + + This file is provided under a dual BSD/GPLv2 license. When using or + redistributing this file, you may do so under either license. + + GPL LICENSE SUMMARY + + Copyright(c) 2005-2011 Ralink Technology Corporation. + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + The full GNU General Public License is included in this distribution + in the file called LICENSE.GPL. + + Contact Information: + Ralink Technology Corporation + 5F, No.5, Tai-Yuen 1st St., Jhubei City, + HsinChu Hsien 30265, Taiwan, R.O.C. + + + BSD LICENSE + + Copyright(c) 2005-2011 Ralink Technology Corporation. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + + +/* + Module Name: + wfd.h + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- + +*/ + + +#ifndef __WFD_CMM_H__ +#define __WFD_CMM_H__ + +#endif /* __WFD_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wnm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wnm.h new file mode 100644 index 000000000..8a1749cbf --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wnm.h @@ -0,0 +1,660 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2011, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + wnm.h + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#ifndef __WNM_H__ +#define __WNM_H__ + +#include "ipv6.h" +#include "mat.h" + +#define BTM_MACHINE_BASE 0 +#define WaitPeerBTMRspTimeoutVale (15*1000) +#define WaitPeerBTMReqTimeoutVale (30*1000) + +#define BTM_ENABLE_OFFSET (1<<0) + +#define BTM_CANDIDATE_OFFSET (1<<0) +#define BTM_ABRIDGED_OFFSET (1<<1) +#define BTM_DISASSOC_OFFSET (1<<2) +#define BTM_TERMINATION_OFFSET (1<<3) +#define BTM_URL_OFFSET (1<<4) + +/* BTM states */ +enum BTM_STATE { + WAIT_BTM_QUERY, + WAIT_PEER_BTM_QUERY, + WAIT_BTM_REQ, + WAIT_BTM_RSP, + WAIT_PEER_BTM_REQ, + WAIT_PEER_BTM_RSP, + BTM_UNKNOWN, + MAX_BTM_STATE, +}; + + +/* BTM events */ +enum BTM_EVENT { + BTM_QUERY, + PEER_BTM_QUERY, + BTM_REQ, + BTM_REQ_IE, + BTM_REQ_PARAM, + BTM_RSP, + PEER_BTM_REQ, + PEER_BTM_RSP, + BTM_REQ_TIMEOUT, + PEER_BTM_RSP_TIMEOUT, + MAX_BTM_MSG, +}; + +#define BTM_FUNC_SIZE (MAX_BTM_STATE * MAX_BTM_MSG) + +enum IPV6_TYPE{ + IPV6_LINK_LOCAL, + IPV6_GLOBAL, +}; + +typedef struct GNU_PACKED _BTM_EVENT_DATA { + UCHAR ControlIndex; + UCHAR PeerMACAddr[MAC_ADDR_LEN]; + UINT16 EventType; + union { + +#ifdef CONFIG_AP_SUPPORT + struct { + UCHAR DialogToken; + UINT16 BTMReqLen; + UCHAR BTMReq[0]; + } GNU_PACKED BTM_REQ_DATA; + + struct { + UCHAR DialogToken; + UINT16 BTMQueryLen; + UCHAR BTMQuery[0]; + } GNU_PACKED PEER_BTM_QUERY_DATA; + + struct { + UCHAR DialogToken; + UINT16 BTMRspLen; + UCHAR BTMRsp[0]; + } GNU_PACKED PEER_BTM_RSP_DATA; +#endif /* CONFIG_AP_SUPPORT */ + }u; +} BTM_EVENT_DATA, *PBTM_EVENT_DATA; + +typedef struct _BTM_PEER_ENTRY { + DL_LIST List; + enum BTM_STATE CurrentState; + UCHAR ControlIndex; + UCHAR PeerMACAddr[MAC_ADDR_LEN]; + UCHAR DialogToken; + void *Priv; +#ifdef CONFIG_AP_SUPPORT + RALINK_TIMER_STRUCT WaitPeerBTMRspTimer; + RALINK_TIMER_STRUCT WaitPeerBTMReqTimer; +#endif /* CONFIG_AP_SUPPORT */ + UINT32 WaitPeerBTMRspTime; +} BTM_PEER_ENTRY, *PBTM_PEER_ENTRY; + +typedef struct _PROXY_ARP_IPV4_ENTRY { + DL_LIST List; + UCHAR TargetMACAddr[MAC_ADDR_LEN]; + UCHAR TargetIPAddr[4]; +} PROXY_ARP_IPV4_ENTRY, *PPROXY_ARP_IPV4_ENTRY; + +typedef struct _PROXY_ARP_IPV4_UNIT { + UCHAR TargetMACAddr[MAC_ADDR_LEN]; + UCHAR TargetIPAddr[4]; +} PROXY_ARP_IPV4_UNIT, *PPROXY_ARP_IPV4_UNIT; + +typedef struct _PROXY_ARP_IPV6_ENTRY { + DL_LIST List; + UCHAR TargetMACAddr[MAC_ADDR_LEN]; + UCHAR TargetIPType; + UCHAR TargetIPAddr[16]; +} PROXY_ARP_IPV6_ENTRY, *PPROXY_ARP_IPV6_ENTRY; + +typedef struct _PROXY_ARP_IPV6_UNIT { + UCHAR TargetMACAddr[MAC_ADDR_LEN]; + UCHAR TargetIPType; + UCHAR TargetIPAddr[16]; +} PROXY_ARP_IPV6_UNIT, *PPROXY_ARP_IPV6_UNIT; + +typedef struct _WNM_CTRL { + UINT32 TimeadvertisementIELen; + UINT32 TimezoneIELen; + PUCHAR TimeadvertisementIE; + PUCHAR TimezoneIE; + RTMP_OS_SEM BTMPeerListLock; + RTMP_OS_SEM WNMNotifyPeerListLock; + BOOLEAN ProxyARPEnable; + BOOLEAN WNMNotifyEnable; + BOOLEAN WNMBTMEnable; + RTMP_OS_SEM ProxyARPListLock; + RTMP_OS_SEM ProxyARPIPv6ListLock; + DL_LIST IPv4ProxyARPList; + DL_LIST IPv6ProxyARPList; + DL_LIST BTMPeerList; + DL_LIST WNMNotifyPeerList; +} WNM_CTRL, *PWNM_CTRL; + +enum IPTYPE { + IPV4, + IPV6 +}; + +struct _BSS_STRUCT; + +BOOLEAN IsGratuitousARP(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN UCHAR *DAMacAddr, + IN struct _BSS_STRUCT *pMbss); + +BOOLEAN IsUnsolicitedNeighborAdver(PRTMP_ADAPTER pAd, + PUCHAR pData); + +BOOLEAN IsIPv4ProxyARPCandidate(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData); + +BOOLEAN IsIPv6ProxyARPCandidate(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData); + +BOOLEAN IsIPv6DHCPv6Solicitation(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData); + +BOOLEAN IsIPv6RouterSolicitation(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData); + +BOOLEAN IsIPv6RouterAdvertisement(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData, + IN PUCHAR pOffset); + +BOOLEAN IsTDLSPacket(IN PRTMP_ADAPTER pAd, + IN PUCHAR pData); + +BOOLEAN IPv4ProxyARP(IN PRTMP_ADAPTER pAd, + IN struct _BSS_STRUCT *pMbss, + IN PUCHAR pData, + IN BOOLEAN FromDS); + +BOOLEAN IsIpv6DuplicateAddrDetect(PRTMP_ADAPTER pAd, + PUCHAR pData, + PUCHAR pOffset); + +BOOLEAN IPv6ProxyARP(IN PRTMP_ADAPTER pAd, + IN struct _BSS_STRUCT *pMbss, + IN PUCHAR pData, + IN BOOLEAN FromDS); + +UINT32 AddIPv4ProxyARPEntry(IN PRTMP_ADAPTER pAd, + IN struct _BSS_STRUCT *pMbss, + IN PUCHAR pTargetMACAddr, + IN PUCHAR pTargetIPAddr); + +UINT32 AddIPv6ProxyARPEntry(IN PRTMP_ADAPTER pAd, + IN struct _BSS_STRUCT *pMbss, + IN PUCHAR pTargetMACAddr, + IN PUCHAR pTargetIPAddr); + +UINT32 IPv4ProxyARPTableLen(IN PRTMP_ADAPTER pAd, + IN struct _BSS_STRUCT *pMbss); + +UINT32 IPv6ProxyARPTableLen(IN PRTMP_ADAPTER pAd, + IN struct _BSS_STRUCT *pMbss); + +BOOLEAN GetIPv4ProxyARPTable(IN PRTMP_ADAPTER pAd, + IN struct _BSS_STRUCT *pMbss, + OUT PUCHAR *ProxyARPTable); + +BOOLEAN GetIPv6ProxyARPTable(IN PRTMP_ADAPTER pAd, + IN struct _BSS_STRUCT *pMbss, + OUT PUCHAR *ProxyARPTable); + +VOID RemoveIPv4ProxyARPEntry(IN PRTMP_ADAPTER pAd, + IN struct _BSS_STRUCT *pMbss, + PUCHAR pTargetMACAddr); + +VOID RemoveIPv6ProxyARPEntry(IN PRTMP_ADAPTER pAd, + IN struct _BSS_STRUCT *pMbss, + PUCHAR pTargetMACAddr); + +VOID WNMCtrlInit(IN PRTMP_ADAPTER pAd); +VOID WNMCtrlExit(IN PRTMP_ADAPTER pAd); +VOID Clear_All_PROXY_TABLE(IN PRTMP_ADAPTER pAd); +#ifdef CONFIG_AP_SUPPORT +VOID WNMIPv4ProxyARPCheck( + IN PRTMP_ADAPTER pAd, + PNDIS_PACKET pPacket, + USHORT srcPort, + USHORT dstPort, + PUCHAR pSrcBuf); + +VOID WNMIPv6ProxyARPCheck( + IN PRTMP_ADAPTER pAd, + PNDIS_PACKET pPacket, + PUCHAR pSrcBuf); + +DECLARE_TIMER_FUNCTION(WaitPeerBTMRspTimeout); +DECLARE_TIMER_FUNCTION(WaitPeerWNMNotifyRspTimeout); +DECLARE_TIMER_FUNCTION(WaitPeerBTMReqTimeout); + +VOID BTMStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +enum BTM_STATE BTMPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); +VOID ReceiveWNMNotifyReq(IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +#ifndef WAPP_SUPPORT/*CONFIG_HOTSPOT_R2*/ +NDIS_STATUS wnm_handle_command( + IN PRTMP_ADAPTER pAd, + IN struct wnm_command *pCmd_data); +#endif +void WNM_ReadParametersFromFile( + IN PRTMP_ADAPTER pAd, + RTMP_STRING *tmpbuf, + RTMP_STRING *buffer); + +VOID ReceiveWNMNotifyRsp(IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID SendWNMNotifyConfirm(IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WNMNotifyStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); + +#define WNM_NOTIFY_MACHINE_BASE 0 +#define WaitPeerWNMNotifyRspTimeoutVale 1024 + +/* WNM Notification states */ +enum WNM_NOTIFY_STATE { + WAIT_WNM_NOTIFY_REQ, + WAIT_WNM_NOTIFY_RSP, + WNM_NOTIFY_UNKNOWN, + MAX_WNM_NOTIFY_STATE, +}; + +/* WNM Notification events */ +enum WNM_NOTIFY_EVENT { + WNM_NOTIFY_REQ, + WNM_NOTIFY_RSP, + MAX_WNM_NOTIFY_MSG, +}; + +#define WNM_NOTIFY_FUNC_SIZE (MAX_WNM_NOTIFY_STATE * MAX_WNM_NOTIFY_MSG) + +typedef struct GNU_PACKED _WNM_NOTIFY_EVENT_DATA { + UCHAR ControlIndex; + UCHAR PeerMACAddr[MAC_ADDR_LEN]; + UINT16 EventType; + union { + +#ifdef CONFIG_AP_SUPPORT + struct { + UCHAR DialogToken; + UINT16 WNMNotifyReqLen; + UCHAR WNMNotifyReq[0]; + } GNU_PACKED WNM_NOTIFY_REQ_DATA; + + struct { + UCHAR DialogToken; + UINT16 WNMNotifyRspLen; + UCHAR WNMNotifyRsp[0]; + } GNU_PACKED WNM_NOTIFY_RSP_DATA; +#endif /* CONFIG_AP_SUPPORT */ + }u; +} WNM_NOTIFY_EVENT_DATA, *PWNM_NOTIFY_EVENT_DATA; + +typedef struct _WNM_NOTIFY_PEER_ENTRY { + DL_LIST List; + enum WNM_NOTIFY_STATE CurrentState; + UCHAR ControlIndex; + UCHAR PeerMACAddr[MAC_ADDR_LEN]; + UCHAR DialogToken; + void *Priv; +#ifdef CONFIG_AP_SUPPORT + RALINK_TIMER_STRUCT WaitPeerWNMNotifyRspTimer; +#endif /* CONFIG_AP_SUPPORT */ +} WNM_NOTIFY_PEER_ENTRY, *PWNM_NOTIFY_PEER_ENTRY; + +INT Send_BTM_Req( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *PeerMACAddr, + IN RTMP_STRING *BTMReq, + IN UINT32 BTMReqLen); + +INT Send_WNM_Notify_Req( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *PeerMACAddr, + IN RTMP_STRING *WNMNotifyReq, + IN UINT32 WNMNotifyReqLen, + IN UINT32 type); + +INT Send_QOSMAP_Configure( + IN PRTMP_ADAPTER pAd, + IN RTMP_STRING *PeerMACAddr, + IN RTMP_STRING *QosMapBuf, + IN UINT32 QosMapLen, + IN UINT8 Apidx); + +#ifdef CONFIG_HOTSPOT_R2 +VOID WNMSetPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem, + IN enum WNM_NOTIFY_STATE State); + +enum WNM_NOTIFY_STATE WNMNotifyPeerCurrentState( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + +VOID WNMNotifyStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *S, + OUT STATE_MACHINE_FUNC Trans[]); +#endif /* CONFIG_HOTSPOT_R2 */ +#endif /* CONFIG_AP_SUPPORT */ + + +int send_btm_req_param( + IN PRTMP_ADAPTER pAd, + IN p_btm_reqinfo_t p_btm_req_data, + IN UINT32 btm_req_data_len); + +int send_btm_req_ie( + IN PRTMP_ADAPTER pAd, + IN p_btm_req_ie_data_t p_btm_req_data, + IN UINT32 btm_req_data_len); + + +int check_btm_custom_params( + IN PRTMP_ADAPTER pAd, + IN p_btm_reqinfo_t p_btm_req_data, + IN UINT32 btm_req_data_len); + +int compose_btm_req_ie( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR p_btm_req_ie, + OUT PUINT32 p_btm_req_ie_len, + IN p_btm_reqinfo_t p_btm_req_data, + IN UINT32 btm_req_data_len); + +VOID WNM_InsertBSSTerminationSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PUINT32 pFrameLen, + IN UINT64 TSF, + IN UINT16 Duration); + +VOID RRM_InsertPreferenceSubIE( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PUINT32 pFrameLen, + IN UINT8 preference); + + +#ifdef DOT11V_WNM_SUPPORT +#include "rtmp_type.h" +#include "wnm_cmm.h" + +#ifdef CONFIG_AP_SUPPORT +#define IS_BSS_TRANSIT_MANMT_SUPPORT(_P, _I) \ + ((_P)->ApCfg.MBSSID[(_I)].WnmCfg.bDot11vWNM_BSSEnable == TRUE) + +#define IS_WNMDMS_SUPPORT(_P, _I) \ + ((_P)->ApCfg.MBSSID[(_I)].WnmCfg.bDot11vWNM_DMSEnable == TRUE) + + +#define IS_WNMFMS_SUPPORT(_P, _I) \ + ((_P)->ApCfg.MBSSID[(_I)].WnmCfg.bDot11vWNM_FMSEnable == TRUE) + +#define IS_WNMSleepMode_SUPPORT(_P, _I) \ + ((_P)->ApCfg.MBSSID[(_I)].WnmCfg.bDot11vWNM_SleepModeEnable == TRUE) + +#define IS_WNMTFS_SUPPORT(_P, _I) \ + ((_P)->ApCfg.MBSSID[(_I)].WnmCfg.bDot11vWNM_TFSEnable == TRUE) + + +#endif /* CONFIG_AP_SUPPORT */ + + + + +#define WNM_MEM_COPY(__Dst, __Src, __Len) memcpy(__Dst, __Src, __Len) +#define WNMR_ARG_ATOI(__pArgv) simple_strtol((RTMP_STRING *) __pArgv, 0, 10) +#define WNMR_ARG_ATOH(__Buf, __Hex) AtoH((RTMP_STRING *) __Buf, __Hex, 1) + + + +VOID WNMAPBTMStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + + +VOID WNMSTABTMStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + + +/* +======================================================================== +Routine Description: + +Arguments: + +Return Value: + +Note: + +======================================================================== +*/ +VOID WNM_Action( + IN PRTMP_ADAPTER pAd, + IN MLME_QUEUE_ELEM *Elem); + + +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +void WNM_ReadParametersFromFile( + IN PRTMP_ADAPTER pAd, + RTMP_STRING *tmpbuf, + RTMP_STRING *buffer); + + +#ifdef CONFIG_AP_SUPPORT + +BOOLEAN DeleteDMSEntry( + IN PRTMP_ADAPTER pAd, + IN struct _MAC_TABLE_ENTRY *pEntry); + +VOID FMSTable_Release( + IN PRTMP_ADAPTER pAd); + +VOID DMSTable_Release( + IN PRTMP_ADAPTER pAd); + +BOOLEAN DeleteTFSID( + IN PRTMP_ADAPTER pAd, + IN struct _MAC_TABLE_ENTRY *pEntry); + +NDIS_STATUS FMSPktInfoQuery( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSrcBufVA, + IN PNDIS_PACKET pPacket, + IN UCHAR apidx, + IN UCHAR QueIdx, + IN UINT8 UserPriority); + +NDIS_STATUS TFSPktInfoQuery( + IN PRTMP_ADAPTER pAd, + IN PUCHAR pSrcBufVA, + IN PNDIS_PACKET pPacket, + IN UCHAR apidx, + IN UCHAR QueIdx, + IN UINT8 UserPriority); + +/* */ +/* + ========================================================================== + Description: + + Parametrs: + + Return : None. + ========================================================================== + */ +INT Set_WNMTransMantREQ_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +INT Set_APWNMDMSShow_Proc(RTMP_ADAPTER *pAd, RTMP_STRING *arg); + +/* + ========================================================================== + Description: + Insert WNM Max Idle Capabilitys IE into frame. + + Parametrs: + 1. frame buffer pointer. + 2. frame length. + + Return : None. + ========================================================================== + */ +VOID WNM_InsertMaxIdleCapIE( + IN PRTMP_ADAPTER pAd, + IN UCHAR aoidx, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen); + +VOID WNM_InsertFMSDescripotr( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 ElementID, + IN UINT8 Length, + IN UINT8 NumOfFMSCs); + +VOID WNM_InsertFMSStSubEelment( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN WNM_FMS_STATUS_SUBELMENT FMSSubElement); + +VOID InsertFMSRspSubElement( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN WNM_FMS_RESPONSE_ELEMENT FMSReqElement); +#endif /* CONFIG_AP_SUPPORT */ +VOID WNM_Init(IN PRTMP_ADAPTER pAd); + +VOID IS_WNM_DMS( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pRxPacket, + IN PHEADER_802_11 pHeader); + +VOID InsertDMSReqElement( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN WNM_DMS_REQUEST_ELEMENT DMSReqElement); + + +VOID WNM_InsertDMS( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UINT8 Len, + IN UCHAR DMSID, + IN WNM_TCLAS wmn_tclas, + IN ULONG IpAddr); + +VOID WNM_InsertFMSReqSubEelment( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN WNM_FMS_SUBELEMENT FMSSubElement, + IN WNM_TCLAS wmn_tclas, + IN ULONG IpAddr); + +VOID InsertFMSReqElement( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN WNM_FMS_REQUEST_ELEMENT FMSReqElement); + +VOID WNM_InsertTFSReqSubEelment( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN WNM_TFS_SUBELEMENT TFSSubElement, + IN WNM_TCLAS wmn_tclas, + IN ULONG IpAddr); + + +VOID InsertTFSReqElement( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN WNM_TFS_REQUEST_ELEMENT FMSReqElement); + + +VOID WNM_InsertSleepModeEelment( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN WNM_SLEEP_MODE_ELEMENT Sleep_Mode_Elmt); + +VOID InsertRequestTyppe( + IN PRTMP_ADAPTER pAd, + OUT PUCHAR pFrameBuf, + OUT PULONG pFrameLen, + IN UCHAR RequestTyppe); + + +BOOLEAN RxDMSHandle( + IN PRTMP_ADAPTER pAd, + IN PNDIS_PACKET pPkt); + +#endif /* DOT11V_WNM_SUPPORT */ + +#endif /* __WNM_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wnm_cmm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wnm_cmm.h new file mode 100644 index 000000000..92b0f48c0 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wnm_cmm.h @@ -0,0 +1,54 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2006, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + ***************************************************************************/ + +/**************************************************************************** + Abstract: + +***************************************************************************/ + +#ifndef __WNM_CONFIG_H__ +#define __WNM_CONFIG_H__ + +#ifdef DOT11V_WNM_SUPPORT +#include "rtmp_type.h" +#include "dot11v_wnm.h" + + +#define WNM_DEFAULT_QUIET_PERIOD 200 + + +typedef struct _WNM_CONFIG +{ + BOOLEAN bDot11vWNM_BSSEnable; + BOOLEAN bDot11vWNM_DMSEnable; + BOOLEAN bDot11vWNM_FMSEnable; + BOOLEAN bDot11vWNM_SleepModeEnable; + BOOLEAN bDot11vWNM_TFSEnable; +#ifdef CONFIG_AP_SUPPORT + VOID *DMSEntry[10]; +#endif /* CONFIG_AP_SUPPORT */ + +} WNM_CONFIG; + + + +#endif /* DOT11V_WNM_SUPPORT */ + +#endif /* __WNM_CONFIG_H__ */ + + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wpa.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wpa.h new file mode 100644 index 000000000..a4b4ae451 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wpa.h @@ -0,0 +1,566 @@ +/* + *************************************************************************** + * 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_11AuthModeOWE)) + +/* + 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_11WEPEnabled) || \ + ((_mode) == Ndis802_11TKIPEnable)) + +#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->func_tb_idx].PMK; \ +} + +#define WPA_GET_GTK(_pAd, _pEntry, _gtk) \ +{ \ + _gtk = _pAd->MBSS[_pEntry->func_tb_idx].GTK; \ +} + +#define WPA_GET_GROUP_CIPHER(_pAd, _pEntry, _cipher) \ +{ \ + _cipher = (_pAd)->MBSS[_pEntry->func_tb_idx].GroupEncrypType; \ +} + +#define WPA_GET_DEFAULT_KEY_ID(_pAd, _pEntry, _idx) \ +{ \ + _idx = (_pAd)->MBSS[_pEntry->func_tb_idx].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) +#ifdef APCLI_SUPPORT +#define WPA_GET_GROUP_CIPHER(_pAd, _pEntry, _cipher) \ + { \ + _cipher = Ndis802_11WEPDisabled; \ + if ((_pAd)->OpMode == OPMODE_AP) \ + { \ + if (IS_ENTRY_APCLI(_pEntry) && \ + ((_pEntry)->func_tb_idx < MAX_APCLI_NUM)) \ + _cipher = (_pAd)->ApCfg.ApCliTab[(_pEntry)->func_tb_idx].GroupCipher; \ + else if ((_pEntry)->func_tb_idx < (_pAd)->ApCfg.BssidNum) \ + _cipher = (_pAd)->ApCfg.MBSSID[_pEntry->func_tb_idx].wdev.GroupKeyWepStatus;\ + } \ + else \ + _cipher = (_pAd)->StaCfg.GroupCipher; \ + } +#else +#define WPA_GET_GROUP_CIPHER(_pAd, _pEntry, _cipher) \ + { \ + _cipher = Ndis802_11WEPDisabled; \ + if ((_pAd)->OpMode == OPMODE_AP) { \ + if ((_pEntry)->func_tb_idx < (_pAd)->ApCfg.BssidNum) \ + _cipher = (_pAd)->ApCfg.MBSSID[_pEntry->func_tb_idx].wdev.GroupKeyWepStatus;\ + } \ + else \ + _cipher = (_pAd)->StaCfg.GroupCipher; \ + } +#endif + +#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 +#ifdef APCLI_SUPPORT +#define WPA_GET_GROUP_CIPHER(_pAd, _pEntry, _cipher) \ + { \ + _cipher = Ndis802_11WEPDisabled; \ + if (IS_ENTRY_APCLI(_pEntry) && \ + ((_pEntry)->func_tb_idx < MAX_APCLI_NUM)) \ + _cipher = (_pAd)->ApCfg.ApCliTab[(_pEntry)->func_tb_idx].GroupCipher; \ + else if ((_pEntry)->func_tb_idx < (_pAd)->ApCfg.BssidNum) \ + _cipher = (_pAd)->ApCfg.MBSSID[_pEntry->func_tb_idx].wdev.GroupKeyWepStatus;\ + } +#else +#define WPA_GET_GROUP_CIPHER(_pAd, _pEntry, _cipher) \ + { \ + _cipher = Ndis802_11WEPDisabled; \ + if ((_pEntry)->func_tb_idx < (_pAd)->ApCfg.BssidNum) \ + _cipher = (_pAd)->ApCfg.MBSSID[_pEntry->func_tb_idx].wdev.GroupKeyWepStatus;\ + } +#endif +#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 WpaStateMachineInit( + IN PRTMP_ADAPTER pAd, + IN STATE_MACHINE *Sm, + OUT STATE_MACHINE_FUNC Trans[]); + +VOID RTMPToWirelessSta( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pHeader802_3, + IN UINT HdrLen, + IN PUCHAR pData, + IN UINT DataLen, + IN BOOLEAN bClearFrame); + +VOID WpaDerivePTK( + IN PRTMP_ADAPTER pAd, + IN UCHAR *PMK, + IN UCHAR *ANonce, + IN UCHAR *AA, + IN UCHAR *SNonce, + IN UCHAR *SA, + OUT UCHAR *output, + IN UINT len); + +VOID WpaDeriveGTK( + IN UCHAR *PMK, + IN UCHAR *GNonce, + IN UCHAR *AA, + OUT UCHAR *output, + IN UINT len); + +VOID GenRandom( + IN PRTMP_ADAPTER pAd, + IN UCHAR *macAddr, + OUT UCHAR *random); + +BOOLEAN RTMPCheckWPAframe( + IN PRTMP_ADAPTER pAd, + IN PMAC_TABLE_ENTRY pEntry, + IN PUCHAR pData, + IN ULONG DataByteCount, + IN UCHAR wdev_idx, + IN BOOLEAN eth_frm); + +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); + +#if defined(CONFIG_SECURITY_IMPROVEMENT_SUPPORT) || defined(APCLI_SECURITY_IMPROVEMENT_SUPPORT) +BOOLEAN wpa_rsne_sanity( + IN PUCHAR rsnie_ptr, + IN UCHAR rsnie_len, + OUT UCHAR *end_field); +#endif + +#if defined(CONFIG_OWE_SUPPORT) || defined(APCLI_SAE_SUPPORT) || defined(APCLI_OWE_SUPPORT) +VOID WPAMakeEntryRSNIE( + IN PRTMP_ADAPTER pAd, + IN UINT AuthMode, + IN UINT WepStatus, + IN MAC_TABLE_ENTRY * pEntry); +#endif + +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, +#ifdef CONFIG_OWE_SUPPORT + IN NDIS_802_11_AUTHENTICATION_MODE StaAuthMode, + IN UINT8 key_deri_alg, +#endif + OUT PEAPOL_PACKET pMsg); + +BOOLEAN rtmp_chk_tkip_mic(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry, RX_BLK *pRxBlk); + + + +RTMP_STRING *GetEapolMsgType(CHAR msg); + + +/* + ===================================== + 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); + + +#ifdef CONFIG_OWE_SUPPORT + +VOID HKDF_expand_sha384(IN UCHAR *secret, + IN INT secret_len, + IN UCHAR *info, + IN INT info_len, + OUT UCHAR *output, + INT output_Len); + +VOID HKDF_expand_sha256(IN UCHAR *secret, + IN INT secret_len, + IN UCHAR *info, + IN INT info_len, + OUT UCHAR *output, + INT output_Len); +#define LEN_PMK_SHA512 64 +#define LEN_PMK_SHA384 48 +#endif + +#endif diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wpa_cmm.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wpa_cmm.h new file mode 100644 index 000000000..0dcfe6c9a --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wpa_cmm.h @@ -0,0 +1,240 @@ + +#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 100 /* 100 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 MT2_EAPOLTIMEOUT 5 +#define MAX_WPA_MSG 6 + +#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 */ + UCHAR Type; /* Indicate Pairwise/Group when reporting MIC error */ +} CIPHER_KEY, *PCIPHER_KEY; + +typedef struct _CMD_802_11_KEY { + UINT8 ucAddRemove; + UINT8 ucTxKey; /* 1 : Tx key */ + UINT8 ucKeyType; /* 0 : group Key, 1 : Pairwise key */ + UINT8 ucIsAuthenticator; /* 1 : authenticator */ + UINT8 aucPeerAddr[6]; + UINT8 ucBssIndex; /* the BSS index */ + UINT8 ucAlgorithmId; + UINT8 ucKeyId; + UINT8 ucKeyLen; + UINT8 ucWlanIndex; + UINT8 ucReverved; + UINT8 aucKeyMaterial[32]; + UINT8 aucKeyRsc[16]; +} CMD_802_11_KEY, *P_CMD_802_11_KEY; +#ifdef CONFIG_SECURITY_IMPROVEMENT_SUPPORT +enum RSN_FIELD { + RSN_FIELD_NONE = 0, + RSN_FIELD_GROUP_CIPHER, + RSN_FIELD_PAIRWISE_CIPHER, + RSN_FIELD_AKM, + RSN_FIELD_RSN_CAP, + RSN_FIELD_PMKID, + RSN_FIELD_GROUP_MGMT_CIPHER, + RSN_FIELD_EXTENSIBLE_ELE +}; +#endif + +#endif /* WPA_CMM_H */ diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wsc.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wsc.h new file mode 100644 index 000000000..32139e740 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wsc.h @@ -0,0 +1,873 @@ +/* + *************************************************************************** + * 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 + +/* structure to store Simple Config Attributes Info */ +typedef struct GNU_PACKED _WSC_LV_INFO { + USHORT ValueLen; + UCHAR Value[512]; +} WSC_LV_INFO; + +typedef struct GNU_PACKED _WSC_IE_HEADER { + UCHAR elemId; + UCHAR length; + UCHAR oui[4]; +} WSC_IE_HEADER; + +/* WSC IE structure */ +typedef struct GNU_PACKED _WSC_IE +{ + USHORT Type; + USHORT Length; + UCHAR Data[1]; /* variable length data */ +} WSC_IE, *PWSC_IE; + +/* WSC fixed information within EAP */ +typedef struct GNU_PACKED _WSC_FRAME +{ + UCHAR SMI[3]; + UINT VendorType; + UCHAR OpCode; + UCHAR Flags; +} WSC_FRAME, *PWSC_FRAME; + +/* EAP frame format */ +typedef struct GNU_PACKED _EAP_FRAME { + UCHAR Code; /* 1 = Request, 2 = Response */ + UCHAR Id; + USHORT Length; + UCHAR Type; /* 1 = Identity, 0xfe = reserved, used by WSC */ +} EAP_FRAME, *PEAP_FRAME; + +static inline BOOLEAN WscCheckWSCHeader(UCHAR *pData) +{ + WSC_FRAME *pWsc = (WSC_FRAME *)pData; + + /* Verify SMI first */ + if (((pWsc->SMI[0] * 256 + pWsc->SMI[1]) * 256 + pWsc->SMI[2]) != WSC_SMI) + return FALSE; /* Wrong WSC SMI Vendor ID, Update WSC status */ + + /* Verify Vendor Type */ + if (cpu2be32(get_unaligned32(&pWsc->VendorType)) != WSC_VENDOR_TYPE) + return FALSE; /* Wrong WSC Vendor Type, Update WSC status */ + + return TRUE; +} + +#ifdef WSC_INCLUDED + + +/* 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; \ + if (__pAd->chipCap.hif_type == HIF_MT) {\ + if (RTMP_TEST_MORE_FLAG(__pAd, fRTMP_ADAPTER_WSC_PBC_PIN0)) \ + __FlgIsPressed = !GPIOGetValue(__pAd, WSC_HDR_BTN_GPIO_0); \ + else \ + __FlgIsPressed = !GPIOGetValue(__pAd, WSC_HDR_BTN_GPIO_3); \ + } else {\ + RTMP_IO_READ32(__pAd, GPIO_CTRL_CFG, (&__gpio_value)); \ + if (RTMP_TEST_MORE_FLAG(__pAd, fRTMP_ADAPTER_WSC_PBC_PIN0)) \ + mask = (1< 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; + + + +typedef struct GNU_PACKED _WSC_PEER_DEV_INFO { + UCHAR WscPeerDeviceName[32]; + UCHAR WscPeerManufacturer[64]; + UCHAR WscPeerModelName[32]; + UCHAR WscPeerModelNumber[32]; + UCHAR WscPeerSerialNumber[32]; + UCHAR WscPeerMAC[6]; +} WSC_PEER_DEV_INFO, *PWSC_PEER_DEV_INFO; + +#ifdef WSC_V2_SUPPORT +#define WSC_PIN_ATTACK_CHECK 600 +#define WSC_V2_VERSION 0x20 +#define TLV_ASCII 0 +#define TLV_HEX 1 + +#ifdef WSC_NFC_SUPPORT +/* + 0 ¡V Command Result (1 byte) + 1 - Configuration (WSC TLV) + 2 ¡V Password (32 bytes) + 3 ¡V IP address (4 bytes) + 4 ¡V RTSP port (4 bytes) + 5 ¡V NFC Status (1 byte) + 6 ¡V Wireless Radio Status (1byte) +*/ +#define TYPE_CMD_RESULT 0 +#define TYPE_CONFIGURATION 1 +#define TYPE_PASSWORD 2 +#define TYPE_IP_ADDR 3 +#define TYPE_RTSP_PORT 4 +#define TYPE_NFC_STATUS 5 +#define TYPE_WIFI_RADIO_STATUS 6 +#define TYPE_PASSWDHO_S 7 /* handover Select */ +#define TYPE_PASSWDHO_R 8 /* handover Request */ + +#define NFC_DEV_PASSWD_LEN 32 +#define NFC_DEV_PASSWD_HASH_LEN 20 + +/* NFC usage models */ +#define MODEL_PASSWORD_TOKEN 0 +#define MODEL_CONFIGURATION_TOKEN 1 +#define MODEL_HANDOVER 2 +#endif /* WSC_NFC_SUPPORT */ + +typedef struct _WSC_TLV { + USHORT TlvTag; + USHORT TlvLen; + PUCHAR pTlvData; + UCHAR TlvType; /* 0: ASCII, 1: Hex */ +} WSC_TLV, *PWSC_TLV; + +typedef struct _WSC_V2_INFO { + WSC_TLV ExtraTlv; + BOOLEAN bWpsEnable; /* FALSE: disable WSC , TRUE: enable WSC */ + BOOLEAN bEnableWpsV2; /* FALSE: not support WSC 2.0, TRUE: support WSC 2.0 */ +} 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 */ + UCHAR WscPeerUuid[UUID_LEN_HEX]; /* Peer AP UUID*/ + WSC_REG_DATA RegData; /* Registrar pair data */ + UCHAR lastId; + UCHAR WscUseUPnP; + BOOLEAN EapMsgRunning; /* already recived Eap-Rsp(Identity) and sent M1 or Eap-Req(Start) */ + UCHAR WscRetryCount; + UCHAR EntryIfIdx; + UCHAR EntryAddr[MAC_ADDR_LEN]; + BOOLEAN Wsc2MinsTimerRunning; + RALINK_TIMER_STRUCT Wsc2MinsTimer; + WSC_PROFILE WscProfile; /* Saved WSC profile after M8 */ + WSC_PROFILE WscBhProfiles;/* Saved Additional WSC profile after M8 */ + 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 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 WSC_NFC_SUPPORT + BOOLEAN bTriggerByNFC; + UCHAR NfcPasswdLen; + UCHAR NfcPasswd[NFC_DEV_PASSWD_LEN]; + USHORT NfcPasswdID; + UCHAR NfcPasswdHash[NFC_DEV_PASSWD_HASH_LEN]; + UCHAR PeerNfcPasswdLen; + UCHAR PeerNfcPasswd[NFC_DEV_PASSWD_LEN]; + USHORT PeerNfcPasswdID; + UCHAR PeerNfcPasswdHash[NFC_DEV_PASSWD_HASH_LEN]; + UCHAR NfcStatus; /* b'0: 1 - ON, 0 - OFF; b'1: 1 - nfc device detect */ + UCHAR NfcPasswdCaculate; + BOOLEAN bRegenPublicKey; /* For negative test */ + UCHAR NfcModel; /* 0:Password_Token, 1:Configuration_Token, 2:Handover */ +#endif /* WSC_NFC_SUPPORT */ +#ifdef CONFIG_AP_SUPPORT + BOOLEAN bWscAutoTriggerDisable; /* Default setting is FALSE */ +#endif /* CONFIG_AP_SUPPORT */ +#ifdef APCLI_SUPPORT + UCHAR WscApCliScanMode; /* Only for ApClient , default setting is full scan */ +#endif /* APCLI_SUPPORT */ +} WSC_CTRL, *PWSC_CTRL; + +typedef struct GNU_PACKED _WSC_CONFIGURED_VALUE { + USHORT WscConfigured; /* 1 un-configured; 2 configured */ + UCHAR WscSsid[32 + 1]; + USHORT WscAuthMode; /* mandatory, 0x01: open, 0x02: wpa-psk, 0x04: shared, 0x08:wpa, 0x10: wpa2, 0x20: wpa2-psk */ + USHORT WscEncrypType; /* 0x01: none, 0x02: wep, 0x04: tkip, 0x08: aes */ + UCHAR DefaultKeyIdx; + UCHAR WscWPAKey[64 + 1]; +} 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 + +RTMP_STRING *WscGetAuthTypeStr(USHORT authFlag); + +RTMP_STRING *WscGetEncryTypeStr(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]; +} 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]; +} WSC_PEER_ENTRY, *PWSC_PEER_ENTRY; + + +#endif /* WSC_INCLUDED */ + +#endif /* __WSC_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wsc_tlv.h b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wsc_tlv.h new file mode 100644 index 000000000..853d9c57b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/include/wsc_tlv.h @@ -0,0 +1,282 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-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 + +/* 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 +#define WFA_EXT_ID_MAP_EXT_ATTRIBUTE 0x06 + +/* Association states */ +#define WSC_ASSOC_NOT_ASSOCIATED 0 +#define WSC_ASSOC_CONN_SUCCESS 1 +#define WSC_ASSOC_CONFIG_FAIL 2 +#define WSC_ASSOC_ASSOC_FAIL 3 +#define WSC_ASSOC_IP_FAIL 4 + +/* Authentication types */ +#define WSC_AUTHTYPE_OPEN 0x0001 +#define WSC_AUTHTYPE_WPAPSK 0x0002 +#define WSC_AUTHTYPE_SHARED 0x0004 +#define WSC_AUTHTYPE_WPA 0x0008 +#define WSC_AUTHTYPE_WPA2 0x0010 +#define WSC_AUTHTYPE_WPA2PSK 0x0020 +#define WSC_AUTHTYPE_WPANONE 0x0080 + +/* Config methods */ +#define WSC_CONFMET_USBA 0x0001 +#define WSC_CONFMET_ETHERNET 0x0002 +#define WSC_CONFMET_LABEL 0x0004 +#define WSC_CONFMET_DISPLAY 0x0008 +#define WSC_CONFMET_EXT_NFC_TOK 0x0010 +#define WSC_CONFMET_INT_NFC_TOK 0x0020 +#define WSC_CONFMET_NFC_INTF 0x0040 +#define WSC_CONFMET_PBC 0x0080 +#define WSC_CONFMET_KEYPAD 0x0100 + +/* WSC error messages */ +#define WSC_ERROR_NO_ERROR 0 +#define WSC_ERROR_OOB_INT_READ_ERR 1 +#define WSC_ERROR_DECRYPT_CRC_FAIL 2 +#define WSC_ERROR_CHAN24_NOT_SUPP 3 +#define WSC_ERROR_CHAN50_NOT_SUPP 4 +#define WSC_ERROR_SIGNAL_WEAK 5 +#define WSC_ERROR_NW_AUTH_FAIL 6 +#define WSC_ERROR_NW_ASSOC_FAIL 7 +#define WSC_ERROR_NO_DHCP_RESP 8 +#define WSC_ERROR_FAILED_DHCP_CONF 9 +#define WSC_ERROR_IP_ADDR_CONFLICT 10 +#define WSC_ERROR_FAIL_CONN_REGISTRAR 11 +#define WSC_ERROR_MULTI_PBC_DETECTED 12 +#define WSC_ERROR_ROGUE_SUSPECTED 13 +#define WSC_ERROR_DEVICE_BUSY 14 +#define WSC_ERROR_SETUP_LOCKED 15 +#define WSC_ERROR_MSG_TIMEOUT 16 +#define WSC_ERROR_REG_SESSION_TIMEOUT 17 +#define WSC_ERROR_DEV_PWD_AUTH_FAIL 18 +#define WSC_ERROR_PUBLIC_KEY_HASH_MISMATCH 20 +#define WSC_ERROR_DO_MULTI_PBC_DETECTION 251 +#define WSC_ERROR_CAN_NOT_ALLOCMEM 252 +#define WSC_ERROR_WANTING_FIELD 253 +#define WSC_ERROR_HASH_FAIL 254 +#define WSC_ERROR_HMAC_FAIL 255 + +/* Connection types */ +#define WSC_CONNTYPE_ESS 0x01 +#define WSC_CONNTYPE_IBSS 0x02 + +/* Device password ID */ +#define WSC_DEVICEPWDID_DEFAULT 0x0000 +#define WSC_DEVICEPWDID_USER_SPEC 0x0001 +#define WSC_DEVICEPWDID_MACHINE_SPEC 0x0002 +#define WSC_DEVICEPWDID_REKEY 0x0003 +#define WSC_DEVICEPWDID_PUSH_BTN 0x0004 +#define WSC_DEVICEPWDID_REG_SPEC 0x0005 + +/* Device type */ +#define WSC_DEVICETYPE_COMPUTER "Computer" +#define WSC_DEVICETYPE_AP "Access_Point" +#define WSC_DEVICETYPE_ROUTER_AP "Router_AP" +#define WSC_DEVICETYPE_PRINTER "Printer" +#define WSC_DEVICETYPE_PRINTER_BRIDGE "Printer_Brigde" +#define WSC_DEVICETYPE_ELECT_PIC_FRAME "Electronic_Picture_Frame" +#define WSC_DEVICETYPE_DIG_AUDIO_RECV "Digital_Audio_Receiver" +#define WSC_DEVICETYPE_WIN_MCE "Windows_Media_Center_Extender" +#define WSC_DEVICETYPE_WIN_MOBILE "Windows_Mobile" +#define WSC_DEVICETYPE_PVR "Personal_Video_Recorder" +#define WSC_DEVICETYPE_VIDEO_STB "Video_STB" +#define WSC_DEVICETYPE_PROJECTOR "Projector" +#define WSC_DEVICETYPE_IP_TV "IP_TV" +#define WSC_DEVICETYPE_DIG_STILL_CAM "Digital_Still_Camera" +#define WSC_DEVICETYPE_PHONE "Phone" +#define WSC_DEVICETYPE_VOID_PHONE "VoIP_Phone" +#define WSC_DEVICETYPE_GAME_CONSOLE "Game_console" +#define WSC_DEVICETYPE_OTHER "Other" + +/* Encryption type */ +#define WSC_ENCRTYPE_NONE 0x0001 +#define WSC_ENCRTYPE_WEP 0x0002 +#define WSC_ENCRTYPE_TKIP 0x0004 +#define WSC_ENCRTYPE_AES 0x0008 + +/* WSC Message Types */ +#define WSC_ID_BEACON 0x01 +#define WSC_ID_PROBE_REQ 0x02 +#define WSC_ID_PROBE_RESP 0x03 +#define WSC_ID_MESSAGE_M1 0x04 +#define WSC_ID_MESSAGE_M2 0x05 +#define WSC_ID_MESSAGE_M2D 0x06 +#define WSC_ID_MESSAGE_M3 0x07 +#define WSC_ID_MESSAGE_M4 0x08 +#define WSC_ID_MESSAGE_M5 0x09 +#define WSC_ID_MESSAGE_M6 0x0A +#define WSC_ID_MESSAGE_M7 0x0B +#define WSC_ID_MESSAGE_M8 0x0C +#define WSC_ID_MESSAGE_ACK 0x0D +#define WSC_ID_MESSAGE_NACK 0x0E +#define WSC_ID_MESSAGE_DONE 0x0F +#define WSC_ID_MESSAGE_EAP_REQ_ID 0x21 +#define WSC_ID_MESSAGE_EAP_REQ_START 0x22 +#define WSC_ID_MESSAGE_EAP_FAIL 0x23 +#define WSC_ID_MESSAGE_UNKNOWN 0xFF + +/* Device Type categories for primary and secondary device types */ +#define WSC_DEVICE_TYPE_CAT_COMPUTER 1 +#define WSC_DEVICE_TYPE_CAT_INPUT_DEVICE 2 +#define WSC_DEVICE_TYPE_CAT_PRINTER 3 +#define WSC_DEVICE_TYPE_CAT_CAMERA 4 +#define WSC_DEVICE_TYPE_CAT_STORAGE 5 +#define WSC_DEVICE_TYPE_CAT_NW_INFRA 6 +#define WSC_DEVICE_TYPE_CAT_DISPLAYS 7 +#define WSC_DEVICE_TYPE_CAT_MM_DEVICES 8 +#define WSC_DEVICE_TYPE_CAT_GAME_DEVICES 9 +#define WSC_DEVICE_TYPE_CAT_TELEPHONE 10 + +/* Device Type sub categories for primary and secondary device types */ +#define WSC_DEVICE_TYPE_SUB_CAT_COMP_PC 1 +#define WSC_DEVICE_TYPE_SUB_CAT_COMP_SERVER 2 +#define WSC_DEVICE_TYPE_SUB_CAT_COMP_MEDIA_CTR 3 +#define WSC_DEVICE_TYPE_SUB_CAT_PRTR_PRINTER 1 +#define WSC_DEVICE_TYPE_SUB_CAT_PRTR_SCANNER 2 +#define WSC_DEVICE_TYPE_SUB_CAT_CAM_DGTL_STILL 1 +#define WSC_DEVICE_TYPE_SUB_CAT_STOR_NAS 1 +#define WSC_DEVICE_TYPE_SUB_CAT_NW_AP 1 +#define WSC_DEVICE_TYPE_SUB_CAT_NW_ROUTER 2 +#define WSC_DEVICE_TYPE_SUB_CAT_NW_SWITCH 3 +#define WSC_DEVICE_TYPE_SUB_CAT_DISP_TV 1 +#define WSC_DEVICE_TYPE_SUB_CAT_DISP_PIC_FRAME 2 +#define WSC_DEVICE_TYPE_SUB_CAT_DISP_PROJECTOR 3 +#define WSC_DEVICE_TYPE_SUB_CAT_MM_DAR 1 +#define WSC_DEVICE_TYPE_SUB_CAT_MM_PVR 2 +#define WSC_DEVICE_TYPE_SUB_CAT_MM_MCX 3 +#define WSC_DEVICE_TYPE_SUB_CAT_GAM_XBOX 1 +#define WSC_DEVICE_TYPE_SUB_CAT_GAM_XBOX_360 2 +#define WSC_DEVICE_TYPE_SUB_CAT_GAM_PS 3 +#define WSC_DEVICE_TYPE_SUB_CAT_PHONE_WM 1 + +typedef struct _WSC_TLV_0B { + /*USHORT tag;*/ + USHORT len; +} WSC_TLV_0B, *PWSC_TLV_0B; + +#endif /* __WSC_TLV_H__ */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/license/MTK_LICENSE b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/license/MTK_LICENSE new file mode 100644 index 000000000..4b5b2db35 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/license/MTK_LICENSE @@ -0,0 +1,42 @@ +/******************************************************************************* +* Copyright (c) 2017 MediaTek Inc. +* +* All rights reserved. Copying, compilation, modification, distribution +* or any other use whatsoever of this material is strictly prohibited +* except in accordance with a Software License Agreement with +* MediaTek Inc. +******************************************************************************** +*/ + +/******************************************************************************* +* LEGAL DISCLAIMER +* +* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND +* AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK +* SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE +* PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY +* DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +* LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +* PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE +* ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY +* WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK +* SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY +* WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE +* FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO +* CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. +* +* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE +* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL +* BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT +* ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY +* BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. +* +* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE +* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT +* OF LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING +* THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN +* FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE +* (ICC). +******************************************************************************** +*/ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/license/NOTICE b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/license/NOTICE new file mode 100644 index 000000000..cb7d8c2df --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/license/NOTICE @@ -0,0 +1,124 @@ + LICENSE ISSUES + ============== + + The OpenSSL toolkit stays under a double license, i.e. both the conditions of + the OpenSSL License and the original SSLeay license apply to the toolkit. + See below for the actual license texts. + + OpenSSL License + --------------- + +/* ==================================================================== + * Copyright (c) 1998-2018 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + + Original SSLeay License + ----------------------- + +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgment: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mac/mt_mac.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mac/mt_mac.c new file mode 100644 index 000000000..8aa1a977e --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mac/mt_mac.c @@ -0,0 +1,2181 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + +#ifdef DBG +VOID dump_rxinfo(RTMP_ADAPTER *pAd, RXINFO_STRUC *pRxInfo) +{ + hex_dump("RxInfo Raw Data", (UCHAR *)pRxInfo, sizeof(RXINFO_STRUC)); + + DBGPRINT(RT_DEBUG_OFF, ("RxInfo Fields:\n")); + + DBGPRINT(RT_DEBUG_OFF, ("\tBA=%d\n", pRxInfo->BA)); + DBGPRINT(RT_DEBUG_OFF, ("\tDATA=%d\n", pRxInfo->DATA)); + DBGPRINT(RT_DEBUG_OFF, ("\tNULLDATA=%d\n", pRxInfo->NULLDATA)); + DBGPRINT(RT_DEBUG_OFF, ("\tFRAG=%d\n", pRxInfo->FRAG)); + DBGPRINT(RT_DEBUG_OFF, ("\tU2M=%d\n", pRxInfo->U2M)); + DBGPRINT(RT_DEBUG_OFF, ("\tMcast=%d\n", pRxInfo->Mcast)); + DBGPRINT(RT_DEBUG_OFF, ("\tBcast=%d\n", pRxInfo->Bcast)); + DBGPRINT(RT_DEBUG_OFF, ("\tMyBss=%d\n", pRxInfo->MyBss)); + DBGPRINT(RT_DEBUG_OFF, ("\tCrc=%d\n", pRxInfo->Crc)); + DBGPRINT(RT_DEBUG_OFF, ("\tCipherErr=%d\n", pRxInfo->CipherErr)); + DBGPRINT(RT_DEBUG_OFF, ("\tAMSDU=%d\n", pRxInfo->AMSDU)); + DBGPRINT(RT_DEBUG_OFF, ("\tHTC=%d\n", pRxInfo->HTC)); + DBGPRINT(RT_DEBUG_OFF, ("\tRSSI=%d\n", pRxInfo->RSSI)); + DBGPRINT(RT_DEBUG_OFF, ("\tL2PAD=%d\n", pRxInfo->L2PAD)); + DBGPRINT(RT_DEBUG_OFF, ("\tAMPDU=%d\n", pRxInfo->AMPDU)); + DBGPRINT(RT_DEBUG_OFF, ("\tDecrypted=%d\n", pRxInfo->Decrypted)); + DBGPRINT(RT_DEBUG_OFF, ("\tBssIdx3=%d\n", pRxInfo->BssIdx3)); + DBGPRINT(RT_DEBUG_OFF, ("\twapi_kidx=%d\n", pRxInfo->wapi_kidx)); + DBGPRINT(RT_DEBUG_OFF, ("\tpn_len=%d\n", pRxInfo->pn_len)); + DBGPRINT(RT_DEBUG_OFF, ("\tsw_fc_type0=%d\n", pRxInfo->sw_fc_type0)); + DBGPRINT(RT_DEBUG_OFF, ("\tsw_fc_type1=%d\n", pRxInfo->sw_fc_type1)); +} + + +static char *hdr_fmt_str[]={ + "Non-80211-Frame", + "Command-Frame", + "Normal-80211-Frame", + "enhanced-80211-Frame", +}; + + +static char *p_idx_str[]={"LMAC", "MCU"}; +static char *q_idx_lmac_str[] = {"AC0", "AC1", "AC2", "AC3", "AC4", "AC5", "AC6", + "BCN", "BMC", + "AC10", "AC11", "AC12", "AC13", "AC14", + "Invalid"}; +static char *q_idx_mcu_str[] = {"RQ0", "RQ1", "RQ2", "RQ3", "Invalid"}; + +VOID dump_tmac_info(RTMP_ADAPTER *pAd, UCHAR *tmac_info) +{ + TMAC_TXD_S *txd_s = (TMAC_TXD_S *)tmac_info; + TMAC_TXD_0 *txd_0 = (TMAC_TXD_0 *)tmac_info; + TMAC_TXD_1 *txd_1 = (TMAC_TXD_1 *)(tmac_info + sizeof(TMAC_TXD_0)); + UCHAR q_idx = 0; + + hex_dump("TMAC_Info Raw Data: ", (UCHAR *)tmac_info, pAd->chipCap.TXWISize); + + DBGPRINT(RT_DEBUG_OFF, ("TMAC_TXD Fields:\n")); + + DBGPRINT(RT_DEBUG_OFF, ("\tTMAC_TXD_0:\n")); + DBGPRINT(RT_DEBUG_OFF, ("\t\tPortID=%d(%s)\n", txd_0->p_idx, + p_idx_str[txd_0->p_idx])); + if (txd_0->p_idx == P_IDX_LMAC) + q_idx = txd_0->q_idx % 0xf; + else + q_idx = txd_0->q_idx % 0x5; + DBGPRINT(RT_DEBUG_OFF, ("\t\tQueID=%d(%s %s)\n", txd_0->q_idx, + (txd_0->p_idx == P_IDX_LMAC ? "LMAC" : "MCU"), + txd_0->p_idx == P_IDX_LMAC ? q_idx_lmac_str[q_idx] : q_idx_mcu_str[q_idx])); + DBGPRINT(RT_DEBUG_OFF, ("\t\tTxByteCnt=%d\n", txd_0->tx_byte_cnt)); + + DBGPRINT(RT_DEBUG_OFF, ("\tTMAC_TXD_1:\n")); + DBGPRINT(RT_DEBUG_OFF, ("\t\tWlan_idx=%d\n", txd_1->wlan_idx)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tHdrInfo=0x%x\n", txd_1->hdr_info)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tHdrFmt=%d(%s)\n", + txd_1->hdr_format, + hdr_fmt_str[txd_1->hdr_format] )); + switch (txd_1->hdr_format) { + case TMI_HDR_FT_NON_80211: + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tMRD=%d, EOSP=%d, RMVL=%d, VLAN=%d, ETYP=%d\n", + txd_1->hdr_info & (1<< TMI_HDR_INFO_0_BIT_MRD), + txd_1->hdr_info & (1<< TMI_HDR_INFO_0_BIT_EOSP), + txd_1->hdr_info & (1<< TMI_HDR_INFO_0_BIT_RMVL), + txd_1->hdr_info & (1<< TMI_HDR_INFO_0_BIT_VLAN), + txd_1->hdr_info & (1<< TMI_HDR_INFO_0_BIT_ETYP))); + break; + case TMI_HDR_FT_CMD: + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tRsvd=0x%x\n", txd_1->hdr_info)); + break; + case TMI_HDR_FT_NOR_80211: + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tHeader Len=%d(WORD)\n", + txd_1->hdr_info & TMI_HDR_INFO_2_MASK_LEN)); + break; + case TMI_HDR_FT_ENH_80211: + DBGPRINT(RT_DEBUG_OFF, ("\t\t\tEOSP=%d, AMS=%d\n", + txd_1->hdr_info & (1<< TMI_HDR_INFO_3_BIT_EOSP), + txd_1->hdr_info & (1<< TMI_HDR_INFO_3_BIT_AMS))); + break; + } + DBGPRINT(RT_DEBUG_OFF, ("\t\tFormatType=%d(%s format)\n", txd_1->ft, + txd_1->ft == TMI_FT_LONG ? "Long - 8 DWORD" : "Short - 3 DWORD")); + DBGPRINT(RT_DEBUG_OFF, ("\t\tHdrPad=%d\n", txd_1->hdr_pad)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tNoAck=%d\n", txd_1->no_ack)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tTID=%d\n", txd_1->tid)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tProtect Frame=%d\n", txd_1->protect_frm)); + DBGPRINT(RT_DEBUG_OFF, ("\t\town_mac=%d\n", txd_1->own_mac)); + + if (txd_s->txd_1.ft == TMI_FT_LONG) { + TMAC_TXD_L *txd_l = (TMAC_TXD_L *)tmac_info; + TMAC_TXD_2 *txd_2 = &txd_l->txd_2; + TMAC_TXD_3 *txd_3 = &txd_l->txd_3; + TMAC_TXD_4 *txd_4 = &txd_l->txd_4; + TMAC_TXD_5 *txd_5 = &txd_l->txd_5; + TMAC_TXD_6 *txd_6 = &txd_l->txd_6; + + DBGPRINT(RT_DEBUG_OFF, ("\tTMAC_TXD_2:\n")); + DBGPRINT(RT_DEBUG_OFF, ("\t\tReamingLife/MaxTx time=%d\n", txd_2->max_tx_time)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tNDP=%d\n", txd_2->ndp)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tNDPA=%d\n", txd_2->ndpa)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tSounding=%d\n", txd_2->sounding)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tbc_mc_pkt=%d\n", txd_2->bc_mc_pkt)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tBIP=%d\n", txd_2->bip)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tDuration=%d\n", txd_2->duration)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tHE(HTC Exist)=%d\n", txd_2->htc_vld)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tFRAG=%d\n", txd_2->frag)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tpwr_offset=%d\n", txd_2->pwr_offset)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tba_disable=%d\n", txd_2->ba_disable)); + DBGPRINT(RT_DEBUG_OFF, ("\t\ttiming_measure=%d\n", txd_2->timing_measure)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tfix_rate=%d\n", txd_2->fix_rate)); + + DBGPRINT(RT_DEBUG_OFF, ("\tTMAC_TXD_3:\n")); + DBGPRINT(RT_DEBUG_OFF, ("\t\ttx_cnt=%d\n", txd_3->tx_cnt)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tremain_tx_cnt=%d\n", txd_3->remain_tx_cnt)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tsn=%d\n", txd_3->sn)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tpn_vld=%d\n", txd_3->pn_vld)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tsn_vld=%d\n", txd_3->sn_vld)); + + DBGPRINT(RT_DEBUG_OFF, ("\tTMAC_TXD_4:\n")); + DBGPRINT(RT_DEBUG_OFF, ("\t\tpn_low=0x%x\n", txd_4->pn_low)); + + DBGPRINT(RT_DEBUG_OFF, ("\tTMAC_TXD_5:\n")); + DBGPRINT(RT_DEBUG_OFF, ("\t\tpwr_mgmt=%d\n", txd_5->pwr_mgmt)); + DBGPRINT(RT_DEBUG_OFF, ("\t\ttx_status_2_host=%d\n", txd_5->tx_status_2_host)); + DBGPRINT(RT_DEBUG_OFF, ("\t\ttx_status_2_mcu=%d\n", txd_5->tx_status_2_mcu)); + DBGPRINT(RT_DEBUG_OFF, ("\t\ttx_status_fmt=%d\n", txd_5->tx_status_fmt)); + if (txd_5->tx_status_2_host || txd_5->tx_status_2_mcu) { + DBGPRINT(RT_DEBUG_OFF, ("\t\tpid=%d\n", txd_5->pid)); + } + if (txd_2->fix_rate) { + DBGPRINT(RT_DEBUG_OFF, ("\t\tda_select=%d\n", txd_5->da_select)); + } + DBGPRINT(RT_DEBUG_OFF, ("\t\tpn_high=0x%x\n", txd_5->pn_high)); + + DBGPRINT(RT_DEBUG_OFF, ("\tTMAC_TXD_6:\n")); + DBGPRINT(RT_DEBUG_OFF, ("\t\ttx_rate=0x%x\n", txd_6->tx_rate)); + if (txd_2->fix_rate) { + DBGPRINT(RT_DEBUG_OFF, ("\t\tfix_rate_mode=%d\n", txd_6->fix_rate_mode)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tant_id=%d\n", txd_6->ant_id)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tbw=%d\n", txd_6->bw)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tspe_en=%d\n", txd_6->spe_en)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tant_pri=%d\n", txd_6->ant_pri)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tdyn_bw=%d\n", txd_6->dyn_bw)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tETxBF=%d\n", txd_6->ETxBF)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tITxBF=%d\n", txd_6->ITxBF)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tldpc=%d(%s)\n", txd_6->ldpc, txd_6->ldpc == 0 ? "BCC" : "LDPC")); + DBGPRINT(RT_DEBUG_OFF, ("\t\tGI=%d(%s)\n", txd_6->gi, txd_6->gi == 0? "LONG" : "SHORT")); + } + } +} + + +static char *rmac_info_type_str[]={ + "TXS", + "RXV", + "RxNormal", + "DupRFB", + "TMR", + "Unknown", +}; + +static inline char *rxd_pkt_type_str(INT pkt_type) +{ + if (pkt_type <= 0x04) + return rmac_info_type_str[pkt_type]; + else + return rmac_info_type_str[5]; +} + + +VOID dump_rmac_info_normal(RTMP_ADAPTER *pAd, UCHAR *rmac_info) +{ + struct rxd_base_struct *rxd_base = (struct rxd_base_struct *)rmac_info; + + hex_dump("RMAC_Info Raw Data: ", rmac_info, sizeof(struct rxd_base_struct)); + + DBGPRINT(RT_DEBUG_TRACE, ("\tRxData_BASE:\n")); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tPktType=%d(%s)\n", + rxd_base->rxd_0.pkt_type, + rxd_pkt_type_str(rxd_base->rxd_0.pkt_type))); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tGroupValid=%x\n", rxd_base->rxd_0.grp_vld)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tRxByteCnt=%d\n", rxd_base->rxd_0.rx_byte_cnt)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tIP/UT=%d/%d\n", rxd_base->rxd_0.ip_sum, rxd_base->rxd_0.ut_sum)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tEtherTypeOffset=%d(WORD)\n", rxd_base->rxd_0.eth_type_offset)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tHTC/UC2ME/MC/BC=%d/%d/%d/%d\n", + rxd_base->rxd_1.htc_vld, rxd_base->rxd_1.u2m, + rxd_base->rxd_1.mcast, rxd_base->rxd_1.bcast)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tBeacon with BMCast/Ucast=%d/%d\n", + rxd_base->rxd_1.beacon_mc, rxd_base->rxd_1.beacon_uc)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tKeyID=%d\n", rxd_base->rxd_1.key_id)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tChFrequency=%x\n", rxd_base->rxd_1.ch_freq)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tHdearLength(MAC)=%d\n", rxd_base->rxd_1.mac_hdr_len)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tHeaerOffset(HO)=%d\n", rxd_base->rxd_1.hdr_offset)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tHeaerTrans(H)=%d\n", rxd_base->rxd_1.hdr_trans)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tPayloadFormat(PF)=%d\n", rxd_base->rxd_1.payload_format)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tBSSID=%d\n", rxd_base->rxd_1.bssid)); + + DBGPRINT(RT_DEBUG_TRACE, ("\t\tWlanIndex=%d\n", rxd_base->rxd_2.wlan_idx)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tTID=%d\n", rxd_base->rxd_2.tid)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tSEC Mode=%d\n", rxd_base->rxd_2.sec_mode)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tSW BIT=%d\n", rxd_base->rxd_2.sw_bit)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tFCE Error(FC)=%d\n", rxd_base->rxd_2.fcs_err)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tCipher Mismatch(CM)=%d\n", rxd_base->rxd_2.cm)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tCipher Length Mismatch(CLM)=%d\n", rxd_base->rxd_2.clm)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tICV Err(I)=%d\n", rxd_base->rxd_2.icv_err)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tTKIP MIC Err(T)=%d\n", rxd_base->rxd_2.tkip_mic_err)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tLength Mismatch(LM)=%d\n", rxd_base->rxd_2.len_mismatch)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tDeAMSDU Fail(DAF)=%d\n", rxd_base->rxd_2.de_amsdu_err)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tExceedMax Rx Length(EL)=%d\n", rxd_base->rxd_2.exceed_max_rx_len)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tLLC-SNAP mismatch(LLC-MIS, for HdrTrans)=%d\n", rxd_base->rxd_2.llc_mis)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tUndefined VLAN tagged Type(UDF_VLT)=%d\n", rxd_base->rxd_2.UDF_VLT)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tFragment Frame(FRAG)=%d\n", rxd_base->rxd_2.frag)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tNull Frame(NULL)=%d\n", rxd_base->rxd_2.null_frm)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tNon Data Frame(NDATA)=%d\n", rxd_base->rxd_2.ndata)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tNon-AMPDU Subframe(NASF)=%d\n", rxd_base->rxd_2.non_ampdu_sub_frm)); + DBGPRINT(RT_DEBUG_TRACE, ("\t\tNon AMPDU(NAMP)=%d\n", rxd_base->rxd_2.non_ampdu)); + + if (rxd_base->rxd_0.grp_vld) { + // TODO: dump group info!! + } +} + + +VOID dump_rmac_info_txs(RTMP_ADAPTER *pAd, UCHAR *rmac_info) +{ + //TXS_FRM_STRUC *txs_frm = (TXS_FRM_STRUC *)rmac_info; + +} + + +VOID dump_rmac_info_rxv(RTMP_ADAPTER *pAd, UCHAR *rmac_info) +{ + //RXV_FRM_STRUC *rxv_frm = (RXV_FRM_STRUC *)rmac_info; + +} + + +VOID dump_rmac_info_rfb(RTMP_ADAPTER *pAd, UCHAR *rmac_info) +{ + //RXD_BASE_STRUCT *rfb_frm = (RXD_BASE_STRUCT *)rmac_info; + +} + + +VOID dump_rmac_info_tmr(RTMP_ADAPTER *pAd, UCHAR *rmac_info) +{ + //TMR_FRM_STRUC *rxd_base = (TMR_FRM_STRUC *)rmac_info; + +} + + +VOID dump_rmac_info(RTMP_ADAPTER *pAd, UCHAR *rmac_info) +{ + union rmac_rxd_0 *rxd_0 = (union rmac_rxd_0 *)rmac_info; + INT pkt_type; + + rxd_0 = (union rmac_rxd_0 *)rmac_info; + pkt_type = RMAC_RX_PKT_TYPE(rxd_0->word); + DBGPRINT(RT_DEBUG_OFF, ("RMAC_RXD Header Format :%s\n", + rxd_pkt_type_str(pkt_type))); + switch (pkt_type) + { + case RMAC_RX_PKT_TYPE_RX_TXS: + dump_rmac_info_txs(pAd, rmac_info); + break; + case RMAC_RX_PKT_TYPE_RX_TXRXV: + dump_rmac_info_rxv(pAd, rmac_info); + break; + case RMAC_RX_PKT_TYPE_RX_NORMAL: + dump_rmac_info_normal(pAd, rmac_info); + break; + case RMAC_RX_PKT_TYPE_RX_DUP_RFB: + dump_rmac_info_rfb(pAd, rmac_info); + break; + case RMAC_RX_PKT_TYPE_RX_TMR: + dump_rmac_info_tmr(pAd, rmac_info); + break; + default: + break; + } +} + + +static RTMP_REG_PAIR mac_cr_seg[]={ + {0x20000, 0x20010}, /* WF_CFG */ + {WF_TRB_BASE, 0x21040}, /* WF_CFG */ + {WF_AGG_BASE, 0x21240}, /* WF_CFG */ + {WF_ARB_BASE, 0x21440}, /* WF_CFG */ + {0,0}, +}; + + +VOID dump_mt_mac_cr(RTMP_ADAPTER *pAd) +{ + INT index = 0; + UINT32 mac_val, mac_addr, seg_s, seg_e; + + while (mac_cr_seg[index].Register != 0) + { + seg_s = mac_cr_seg[index].Register; + seg_e = mac_cr_seg[index].Value; + DBGPRINT(RT_DEBUG_OFF, ("Dump WF_CFG Segment(Start=0x%x, End=0x%x)\n", + seg_s, seg_e)); + for (mac_addr = seg_s; mac_addr < seg_e; mac_addr += 4) + { + RTMP_IO_READ32(pAd, mac_addr, &mac_val); + DBGPRINT(RT_DEBUG_OFF, ("MAC[0x%x] = 0x%x\n", mac_addr, mac_val)); + } + + index++; + }; +} +#endif /* DBG */ + + +INT mt_mac_fifo_stat_update(RTMP_ADAPTER *pAd) +{ + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + } + + return FALSE; +} + + +VOID NicGetTxRawCounters( + IN RTMP_ADAPTER *pAd, + IN TX_STA_CNT0_STRUC *pStaTxCnt0, + IN TX_STA_CNT1_STRUC *pStaTxCnt1) +{ + // TODO: shiang-7603 + return; +} + + +/* + ======================================================================== + + Routine Description: + Read statistical counters from hardware registers and record them + in software variables for later on query + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID NICUpdateRawCounters(RTMP_ADAPTER *pAd) +{ + RTEnqueueInternalCmd(pAd, CMDTHREAD_PERODIC_CR_ACCESS_NIC_UPDATE_RAW_COUNTERS, NULL, 0); +} + +NTSTATUS MtCmdNICUpdateRawCounters(RTMP_ADAPTER *pAd, PCmdQElmt CMDQelmt) +{ + UINT32 OldValue, ampdu_range_cnt[4]; + UINT32 mac_val, rx_err_cnt, fcs_err_cnt; + //UINT32 TxSuccessCount = 0, bss_tx_cnt; + /* for PER debug */ + UINT32 AmpduTxCount = 0; + UINT32 AmpduTxSuccessCount = 0; + + UINT32 OFDM_PD_CNT, CCK_PD_CNT,OFDM_MDRDY_CNT, CCK_MDRDY_CNT; + UINT32 PDCnt = 0; + UINT32 MDRDYCnt = 0; + UINT32 value, CCAcount = 0; + +#ifdef DBG_DIAGNOSE + UINT32 bss_tx_cnt = 0; + UINT32 TxFailCount = 0; +#endif + //UINT32 TxRetryCount = 0; + COUNTER_RALINK *pRalinkCounters; + + + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) + { + DBGPRINT(RT_DEBUG_INFO, ("%s(%d): H/W in PM4, return\n", __FUNCTION__, __LINE__)); + return NDIS_STATUS_SUCCESS; + } + + + pRalinkCounters = &pAd->RalinkCounters; + + + + pRalinkCounters = &pAd->RalinkCounters; + + RTMP_IO_READ32(pAd, MIB_MSDR14, &AmpduTxCount); + AmpduTxCount &= 0xFFFFFF; + RTMP_IO_READ32(pAd, MIB_MSDR15, &AmpduTxSuccessCount); + AmpduTxSuccessCount &= 0xFFFFFF; + RTMP_IO_READ32(pAd, MIB_MSDR4, &rx_err_cnt); + fcs_err_cnt = (rx_err_cnt >> 16 ) & 0xffff; + RTMP_IO_READ32(pAd, MIB_MDR2, &mac_val); + ampdu_range_cnt[0] = mac_val & 0xffff; + ampdu_range_cnt[1] = (mac_val >> 16 ) & 0xffff; + RTMP_IO_READ32(pAd, MIB_MDR3, &mac_val); + ampdu_range_cnt[2] = mac_val & 0xffff; + ampdu_range_cnt[3] = (mac_val >> 16 ) & 0xffff; +#ifdef DBG_DIAGNOSE + RTMP_IO_READ32(pAd, MIB_MB0SDR1, &mac_val); + TxFailCount = (mac_val >> 16) & 0xffff; + // TODO: shiang, now only check BSS0 + RTMP_IO_READ32(pAd, WTBL_BTCRn, &bss_tx_cnt); + bss_tx_cnt = (bss_tx_cnt >> 16) & 0xffff; +#endif /* DBG_DIAGNOSE */ + +#ifdef ANTI_INTERFERENCE_SUPPORT + RTMP_IO_READ32(pAd, MIB_MSDR12, &mac_val); + pRalinkCounters->OneSecTxAMpduCnt = mac_val & 0xFFFF; + pRalinkCounters->OneSecTxBACnt = (mac_val >> 16) & 0xFFFF; +#endif /* ANTI_INTERFERENCE_SUPPORT */ + +#ifdef STATS_COUNT_SUPPORT + pAd->WlanCounters.AmpduSuccessCount.u.LowPart += AmpduTxSuccessCount; + pAd->WlanCounters.AmpduFailCount.u.LowPart += (AmpduTxCount - AmpduTxSuccessCount); +#endif /* STATS_COUNT_SUPPORT */ + + pAd->RalinkCounters.OneSecRxFcsErrCnt += fcs_err_cnt; + +#ifdef STATS_COUNT_SUPPORT + /* Update FCS counters*/ + OldValue= pAd->WlanCounters.FCSErrorCount.u.LowPart; + pAd->WlanCounters.FCSErrorCount.u.LowPart += fcs_err_cnt; /* >> 7);*/ + if (pAd->WlanCounters.FCSErrorCount.u.LowPart < OldValue) + pAd->WlanCounters.FCSErrorCount.u.HighPart++; +#endif /* STATS_COUNT_SUPPORT */ +#ifdef CONFIG_QA + if (pAd->ATECtrl.bQAEnabled == TRUE) + pAd->ATECtrl.RxMacFCSErrCount += fcs_err_cnt; +#endif + /* Add FCS error count to private counters*/ + pRalinkCounters->OneSecRxFcsErrCnt += fcs_err_cnt; + OldValue = pRalinkCounters->RealFcsErrCount.u.LowPart; + pRalinkCounters->RealFcsErrCount.u.LowPart += fcs_err_cnt; + if (pRalinkCounters->RealFcsErrCount.u.LowPart < OldValue) + pRalinkCounters->RealFcsErrCount.u.HighPart++; + + pAd->Counters8023.RxNoBuffer += (rx_err_cnt & 0xffff); + + pAd->WlanCounters.TxAggRange1Count.u.LowPart += ampdu_range_cnt[0]; + pAd->WlanCounters.TxAggRange2Count.u.LowPart += ampdu_range_cnt[1]; + pAd->WlanCounters.TxAggRange3Count.u.LowPart += ampdu_range_cnt[2]; + pAd->WlanCounters.TxAggRange4Count.u.LowPart += ampdu_range_cnt[3]; + +#ifdef DBG_DIAGNOSE + { + RtmpDiagStruct *pDiag; + UCHAR ArrayCurIdx, i; + struct dbg_diag_info *diag_info; + + pDiag = &pAd->DiagStruct; + ArrayCurIdx = pDiag->ArrayCurIdx; + + if (pDiag->inited == 0) + { + NdisZeroMemory(pDiag, sizeof(struct _RtmpDiagStrcut_)); + pDiag->ArrayStartIdx = pDiag->ArrayCurIdx = 0; + pDiag->wcid = 0; + pDiag->inited = 1; + pDiag->diag_cond = 0; + } + else + { + diag_info = &pDiag->diag_info[ArrayCurIdx]; + + if ((pDiag->wcid == 0) && (pAd->MacTab.Size > 0)) { + UCHAR idx; + MAC_TABLE_ENTRY *pEntry; + + for (idx = 1; idx < MAX_LEN_OF_MAC_TABLE; idx++) { + pEntry = &pAd->MacTab.Content[idx]; + if (IS_ENTRY_CLIENT(pEntry) && (pEntry->Sst==SST_ASSOC)) { + pDiag->wcid = idx; + DBGPRINT(RT_DEBUG_TRACE, ("%s(): DBG_DIAGNOSE Start to monitor the SwQ depth of WCID[%d], ArrayCurIdx=%d\n", + __FUNCTION__, pDiag->wcid, pDiag->ArrayCurIdx)); + break; + } + } + } + + /* Tx*/ + diag_info->TxFailCnt = TxFailCount; +#ifdef DBG_TX_AGG_CNT + diag_info->TxAggCnt = AmpduTxCount; + diag_info->TxNonAggCnt = bss_tx_cnt - AmpduTxCount; // only useful when only one BSS case + + diag_info->TxAMPDUCnt[0] = ampdu_range_cnt[0]; + diag_info->TxAMPDUCnt[1] = ampdu_range_cnt[1]; + diag_info->TxAMPDUCnt[2] = ampdu_range_cnt[2]; + diag_info->TxAMPDUCnt[3] = ampdu_range_cnt[3]; +#endif /* DBG_TX_AGG_CNT */ + + diag_info->RxCrcErrCnt = fcs_err_cnt; + + INC_RING_INDEX(pDiag->ArrayCurIdx, DIAGNOSE_TIME); + ArrayCurIdx = pDiag->ArrayCurIdx; + + NdisZeroMemory(&pDiag->diag_info[ArrayCurIdx], sizeof(pDiag->diag_info[ArrayCurIdx])); + + if (pDiag->ArrayCurIdx == pDiag->ArrayStartIdx) + INC_RING_INDEX(pDiag->ArrayStartIdx, DIAGNOSE_TIME); + } + } +#endif /* DBG_DIAGNOSE */ + + + /* update one sec falseCCA (PD CNT - MDRDY CNT) */ + RTMP_IO_READ32(pAd,RO_PHYCTRL_STS0,&PDCnt); + OFDM_PD_CNT = (PDCnt >> 16); + CCK_PD_CNT = (PDCnt & 0xFFFF); + RTMP_IO_READ32(pAd,RO_PHYCTRL_STS5,&MDRDYCnt); + OFDM_MDRDY_CNT = (MDRDYCnt >> 16); + CCK_MDRDY_CNT = (MDRDYCnt & 0xFFFF); + CCAcount = ((OFDM_PD_CNT - OFDM_MDRDY_CNT) + (CCK_PD_CNT - CCK_MDRDY_CNT)); + RTMP_IO_READ32(pAd,CR_PHYCTRL_2,&value); + value |= (1<<6); /* BIT6: CR_STSCNT_RST */ + RTMP_IO_WRITE32(pAd,CR_PHYCTRL_2,value); + value &= (~(1<<6)); + RTMP_IO_WRITE32(pAd,CR_PHYCTRL_2,value); + value |= (1<<7); /* BIT7: CR_STSCNT_EN */ + RTMP_IO_WRITE32(pAd,CR_PHYCTRL_2,value); + + //DBGPRINT(RT_DEBUG_WARN, ("one-sec FalseCCACnt %d (CCK %d + OFDM %d)\n" + //,CCAcount,(CCK_PD_CNT - CCK_MDRDY_CNT),(OFDM_PD_CNT - OFDM_MDRDY_CNT))); + + pAd->RalinkCounters.OneSecFalseCCACnt = CCAcount; + pAd->RalinkCounters.OneSecCCKFalseCCACnt = (CCK_PD_CNT - CCK_MDRDY_CNT); + pAd->RalinkCounters.OneSecOFDMFalseCCACnt = (OFDM_PD_CNT - OFDM_MDRDY_CNT); + pAd->RalinkCounters.FalseCCACnt = CCAcount; + +#ifdef SMART_CARRIER_SENSE_SUPPORT + pAd->SCSCtrl.PdCount = PDCnt; + pAd->SCSCtrl.MdrdyCount = MDRDYCnt; + DBGPRINT(RT_DEBUG_TRACE,("False CCA (one second) = %ld (CCK %d + OFDM %d)\n" , (ULONG)pAd->RalinkCounters.OneSecFalseCCACnt,pAd->RalinkCounters.OneSecCCKFalseCCACnt,pAd->RalinkCounters.OneSecOFDMFalseCCACnt)); + pAd->SCSCtrl.FalseCCA = pAd->RalinkCounters.FalseCCACnt; +#endif /* SMART_CARRIER_SENSE_SUPPORT */ + + return NDIS_STATUS_SUCCESS; +} + + +/* + ======================================================================== + + 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) +{ + return; +} + + +UCHAR tmi_rate_map_cck_lp[]={ + TMI_TX_RATE_CCK_1M_LP, + TMI_TX_RATE_CCK_2M_LP, + TMI_TX_RATE_CCK_5M_LP, + TMI_TX_RATE_CCK_11M_LP, +}; + +UCHAR tmi_rate_map_cck_sp[]={ + TMI_TX_RATE_CCK_2M_SP, + TMI_TX_RATE_CCK_2M_SP, + TMI_TX_RATE_CCK_5M_SP, + TMI_TX_RATE_CCK_11M_SP, +}; + +UCHAR tmi_rate_map_ofdm[]={ + TMI_TX_RATE_OFDM_6M, + TMI_TX_RATE_OFDM_9M, + TMI_TX_RATE_OFDM_12M, + TMI_TX_RATE_OFDM_18M, + TMI_TX_RATE_OFDM_24M, + TMI_TX_RATE_OFDM_36M, + TMI_TX_RATE_OFDM_48M, + TMI_TX_RATE_OFDM_54M, +}; + + +#define TMI_TX_RATE_CCK_VAL(_mcs) \ + ((TMI_TX_RATE_MODE_CCK << TMI_TX_RATE_BIT_MODE) | (_mcs)) + +#define TMI_TX_RATE_OFDM_VAL(_mcs) \ + ((TMI_TX_RATE_MODE_OFDM << TMI_TX_RATE_BIT_MODE) | (_mcs)) + +#define TMI_TX_RATE_HT_VAL(_mode, _mcs, _stbc) \ + (((_stbc) << TMI_TX_RATE_BIT_STBC) |\ + ((_mode) << TMI_TX_RATE_BIT_MODE) | \ + (_mcs)) + +#define TMI_TX_RATE_VHT_VAL(_nss, _mcs, _stbc) \ + (((_stbc) << TMI_TX_RATE_BIT_STBC) |\ + (((_nss -1) & (~TMI_TX_RATE_MASK_NSS)) << TMI_TX_RATE_BIT_NSS) | \ + (TMI_TX_RATE_MODE_VHT << TMI_TX_RATE_BIT_MODE) | \ + (_mcs)) + + +USHORT tx_rate_to_tmi_rate(UCHAR mode, UCHAR mcs, UCHAR nss, BOOLEAN stbc, UCHAR preamble) +{ + USHORT tmi_rate = 0, mcs_id = 0; + + stbc = (stbc== TRUE) ? 1 : 0; + switch (mode) { + case MODE_CCK: + if (preamble && mcs < ARRAY_SIZE(tmi_rate_map_cck_lp)) + mcs_id = tmi_rate_map_cck_lp[mcs]; + else if (mcs < ARRAY_SIZE(tmi_rate_map_cck_sp)) + mcs_id = tmi_rate_map_cck_sp[mcs]; + tmi_rate = (TMI_TX_RATE_MODE_CCK << TMI_TX_RATE_BIT_MODE) | (mcs_id); + break; + case MODE_OFDM: + if (mcs < ARRAY_SIZE(tmi_rate_map_ofdm)) { + mcs_id = tmi_rate_map_ofdm[mcs]; + tmi_rate = (TMI_TX_RATE_MODE_OFDM << TMI_TX_RATE_BIT_MODE) | (mcs_id); + } + break; + case MODE_HTMIX: + case MODE_HTGREENFIELD: + tmi_rate = ((USHORT)(stbc << TMI_TX_RATE_BIT_STBC)) | + (((nss -1) & TMI_TX_RATE_MASK_NSS) << TMI_TX_RATE_BIT_NSS) | + ((USHORT)(mode << TMI_TX_RATE_BIT_MODE)) | + ((USHORT)(mcs)); +// DBGPRINT(RT_DEBUG_OFF, ("%s(): mode=%d, mcs=%d, stbc=%d converted tmi_rate=0x%x\n", +// __FUNCTION__, mode, mcs, stbc, tmi_rate)); + break; + case MODE_VHT: + tmi_rate = TMI_TX_RATE_VHT_VAL(nss, mcs, stbc); + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s():Invalid mode(mode=%d)\n", + __FUNCTION__, mode)); + break; + } + + return tmi_rate; +} + + +UCHAR get_nss_by_mcs(UCHAR phy_mode, UCHAR mcs, BOOLEAN stbc) +{ + UCHAR nss = 1; + + switch (phy_mode) + { + case MODE_HTMIX: + case MODE_HTGREENFIELD: + if (mcs != 32) { + nss += (mcs >> 3); + if ( stbc && nss == 1 ) + nss ++; + } + break; + case MODE_CCK: + case MODE_OFDM: + default: + break; + } + + return nss; +} + + +/* + ======================================================================== + + Routine Description: + Calculates the duration which is required to transmit out frames + with given size and specified rate. + + Arguments: + pTxWI Pointer to head of each MPDU to HW. + Ack Setting for Ack requirement bit + Fragment Setting for Fragment bit + RetryMode Setting for retry mode + Ifs Setting for IFS gap + Rate Setting for transmit rate + Service Setting for service + Length Frame length + TxPreamble Short or Long preamble when using CCK rates + QueIdx - 0-3, according to 802.11e/d4.4 June/2003 + + Return Value: + None + + See also : BASmartHardTransmit() !!! + + ======================================================================== +*/ +const UCHAR wmm_aci_2_hw_ac_queue[18] = +{ + Q_IDX_AC1, /* 0: QID_AC_BE */ + Q_IDX_AC0, /* 1: QID_AC_BK */ + Q_IDX_AC2, /* 2: QID_AC_VI */ + Q_IDX_AC3, /* 3:QID_AC_VO */ + 4, /* 4:QID_AC_VO */ + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, +}; +VOID write_tmac_info( + IN RTMP_ADAPTER *pAd, + IN UCHAR *tmac_info, + IN MAC_TX_INFO *info, + IN HTTRANSMIT_SETTING *pTransmit) +{ + MAC_TABLE_ENTRY *mac_entry = NULL; + UCHAR stbc, bw, mcs, nss = 1, sgi, phy_mode, ldpc = 0, preamble = LONG_PREAMBLE; + UCHAR to_mcu = FALSE, q_idx = info->q_idx; + TMAC_TXD_L txd; + TMAC_TXD_0 *txd_0 = &txd.txd_0; + TMAC_TXD_1 *txd_1 = &txd.txd_1; + TMAC_TXD_2 *txd_2 = &txd.txd_2; + TMAC_TXD_3 *txd_3 = &txd.txd_3; + TMAC_TXD_5 *txd_5 = &txd.txd_5; + TMAC_TXD_6 *txd_6 = &txd.txd_6; + INT txd_size = sizeof(TMAC_TXD_S); + TXS_CTL *TxSCtl = &pAd->TxSCtl; + + if (info->WCID < MAX_LEN_OF_MAC_TABLE) + mac_entry = &pAd->MacTab.Content[info->WCID]; + + NdisZeroMemory(&txd, sizeof(TMAC_TXD_L)); + + ldpc = pTransmit->field.ldpc; + mcs = pTransmit->field.MCS; + sgi = pTransmit->field.ShortGI; + stbc = pTransmit->field.STBC; + phy_mode = pTransmit->field.MODE; + bw = (phy_mode <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); + +#ifdef DOT11_N_SUPPORT +#ifdef CONFIG_ATE + if (!ATE_ON(pAd)) +#endif + { + if (mac_entry) + { + if ((pAd->CommonCfg.bMIMOPSEnable) && (mac_entry->MmpsMode == MMPS_STATIC) + && (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7)) + mcs = 7; + } + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT + if (pAd->CommonCfg.VoPwrConstraintTest == TRUE) + { + info->AMPDU = 0; + mcs = 0; + ldpc = 0; + bw = 0; + sgi = 0; + stbc = 0; + phy_mode = MODE_OFDM; + } +#endif /* DOT11K_RRM_SUPPORT */ + + /* DWORD 0 */ + txd_0->p_idx = (to_mcu ? P_IDX_MCU : P_IDX_LMAC); + if (q_idx < 4) { + txd_0->q_idx = wmm_aci_2_hw_ac_queue[q_idx]; + } else + txd_0->q_idx = q_idx; + + + + /* DWORD 1 */ + txd_1->wlan_idx = info->WCID; + txd_1->ft = TMI_FT_LONG; + txd_1->hdr_format = TMI_HDR_FT_NOR_80211; + TMI_HDR_INFO_VAL(txd_1->hdr_format, 0, 0, 0, 0, 0, info->hdr_len, 0, txd_1->hdr_info); + if (info->hdr_pad) // TODO: depends on QoS to decide if need to padding + txd_1->hdr_pad = (TMI_HDR_PAD_MODE_TAIL << TMI_HDR_PAD_BIT_MODE) | info->hdr_pad; + txd_1->no_ack = (info->Ack ? 0 : 1); + txd_1->tid = info->TID; + + txd_1->own_mac = 0 ; + if (txd_0->q_idx == Q_IDX_BCN) { + if (info->bss_idx == 0) + txd_1->own_mac = 0 ;// info->bss_idx; + else if (info->bss_idx > 0 && info->bss_idx <=15) + txd_1->own_mac = 0x10 | info->bss_idx; + + //TODO:Carter, for Adhoc Beacon, use own_mac = 0 now, + //but what if need to consider GO/client case, it shall be refined. + } + + if (mac_entry && IS_ENTRY_APCLI(mac_entry)) + { +#ifdef MULTI_APCLI_SUPPORT + txd_1->own_mac = (0x1 + mac_entry->func_tb_idx); +#else /* MULTI_APCLI_SUPPORT */ + txd_1->own_mac = 0x1; //Carter, refine this +#endif /* !MULTI_APCLI_SUPPORT */ + + } else if (mac_entry && IS_ENTRY_CLIENT(mac_entry)) { + /* handle HW_BSSID_0 & Extend from 0 to 15 */ + if (mac_entry->func_tb_idx == 0) + txd_1->own_mac = 0x0; + else if (mac_entry->func_tb_idx >= 1 && mac_entry->func_tb_idx <= 15) + txd_1->own_mac = 0x10 | mac_entry->func_tb_idx; + + /* for concurrent to handle HW_BSSID_1/2/3 */ + if (mac_entry->wdev->hw_bssid_idx != 0) + txd_1->own_mac = mac_entry->wdev->hw_bssid_idx ; + } + + if (txd_1->ft == TMI_FT_LONG) { + txd_size = sizeof(TMAC_TXD_L); + + /* DWORD 2 */ + txd_2->max_tx_time = 0; + txd_2->bc_mc_pkt = info->BM; + txd_2->fix_rate = 1; + + txd_2->duration = 0; + txd_2->htc_vld = 0; + txd_2->frag = info->FRAG; // 0: no frag, 1: 1st frag, 2: mid frag, 3: last frag + txd_2->max_tx_time = 0; + txd_2->ba_disable = 1; + txd_2->timing_measure = 0; + txd_2->fix_rate = 1; + if (pAd->chipCap.TmrEnable == 1) { + if ((txd_1->no_ack == 0) && (txd_2->bc_mc_pkt == 0)) { + txd_2->timing_measure = 1; + } + } + + txd_2->sub_type = (*((UINT16 *)(tmac_info + sizeof(TMAC_TXD_L))) & (0xf << 4)) >> 4; + txd_2->frm_type = (*((UINT16 *)(tmac_info + sizeof(TMAC_TXD_L))) & (0x3 << 2)) >> 2; + + /* DWORD 3 */ + if (txd_0->q_idx == Q_IDX_BCN) + txd_3->remain_tx_cnt = MT_TX_RETRY_UNLIMIT; + else if ((txd_2->frm_type == FC_TYPE_CNTL) && (txd_2->sub_type == SUBTYPE_BLOCK_ACK_REQ)) + txd_3->remain_tx_cnt = 1; + else { + if (pAd->shortretry != 0) + txd_3->remain_tx_cnt = pAd->shortretry; + else + txd_3->remain_tx_cnt = MT_TX_SHORT_RETRY; + } + + /* DWORD 4 */ + + /* DWORD 6 */ + if (txd_2->fix_rate == 1) { + txd_6->fix_rate_mode = TMI_FIX_RATE_BY_TXD; + //txd_6->ant_id = 0; + txd_6->ant_pri = info->AntPri; + txd_6->spe_en = info->SpeEn; + txd_6->bw = ((1 << 2) |bw); + txd_6->dyn_bw = 0; + txd_6->ETxBF = 0; + txd_6->ITxBF = 0; + txd_6->ldpc = ldpc; + txd_6->gi = sgi; + +#ifdef GREENAP_SUPPORT + if (pAd->ApCfg.bGreenAPActive == TRUE) + txd_6->spe_en = 0; +#endif /* GREENAP_SUPPORT */ + + if (txd_6->fix_rate_mode == TMI_FIX_RATE_BY_TXD) + { + if (phy_mode == MODE_CCK) + preamble = info->Preamble; + + txd_6->tx_rate = tx_rate_to_tmi_rate(phy_mode, mcs, nss, stbc, preamble); + } + } + + /* DWORD 5 */ +#ifdef WH_EZ_SETUP + if (0)//mac_entry && IS_EZ_SETUP_ENABLED(mac_entry->wdev) && info->PID == PID_EZ_ACTION) + { + EZ_DEBUG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_OFF, ("Action Frame TXD initialized\n")); + + txd_5->pid = info->PID; + txd_5->tx_status_fmt = TXS_FORMAT0; + txd_5->tx_status_2_mcu = 0; + txd_5->tx_status_2_host = 1; + } + else +#endif + { + txd_5->pid = 0; + + if (info->PID) + { + if (TxSCtl->TxSFormatPerPkt & (1 << info->PID)) + txd_5->tx_status_fmt = TXS_FORMAT1; + else + txd_5->tx_status_fmt = TXS_FORMAT0; + + if (TxSCtl->TxS2McUStatusPerPkt & (1 << info->PID)) + txd_5->tx_status_2_mcu = 1; + else + txd_5->tx_status_2_mcu = 0; + + if (TxSCtl->TxS2HostStatusPerPkt & (1 << info->PID)) + { + txd_5->pid = AddTxSStatus(pAd, TXS_TYPE0, info->PID, 0, 0, + txd_6->tx_rate, info->TxSPriv); + txd_5->tx_status_2_host = 1; + } + else + { + txd_5->tx_status_2_host = 0; + } + } + else + { + ULONG TxSStatusPerWlanIdx; + if (txd_1->wlan_idx < 64) + { + TxSStatusPerWlanIdx = TxSCtl->TxSStatusPerWlanIdx[0]; + } + else + { + TxSStatusPerWlanIdx = TxSCtl->TxSStatusPerWlanIdx[1]; + } + + if (TxSStatusPerWlanIdx & (1 << txd_1->wlan_idx)) + { + + if (TxSCtl->TxSFormatPerPktType[txd_2->frm_type] & (1 << txd_2->sub_type)) + txd_5->tx_status_fmt = TXS_FORMAT1; + else + txd_5->tx_status_fmt = TXS_FORMAT0; + + if (TxSCtl->TxS2McUStatusPerPktType[txd_2->frm_type] & (1 << txd_2->sub_type)) + txd_5->tx_status_2_mcu = 1; + else + txd_5->tx_status_2_mcu = 0; + + if (TxSCtl->TxS2HostStatusPerPktType[txd_2->frm_type] & (1 << txd_2->sub_type)) + { + txd_5->pid = AddTxSStatus(pAd, TXS_TYPE1, 0, + txd_2->frm_type, txd_2->sub_type, txd_6->tx_rate, info->TxSPriv); + txd_5->tx_status_2_host = 1; + } + else + { + txd_5->tx_status_2_host = 0; + } + } + } +} +#ifdef HDR_TRANS_SUPPORT + //txd_5->da_select = TMI_DAS_FROM_MPDU; +#endif /* HDR_TRANS_SUPPORT */ + txd_5->bar_sn_ctrl = 1; + if (info->PsmBySw) + txd_5->pwr_mgmt = TMI_PM_BIT_CFG_BY_SW; + else + txd_5->pwr_mgmt = TMI_PM_BIT_CFG_BY_HW; + //txd_5->pn_high = 0; + + if (info->prot == 1) { + txd_1->protect_frm = 1; + } + else if (info->prot == 2) { +#ifdef DOT11W_PMF_SUPPORT + GET_PMF_GroupKey_WCID(pAd, info->WCID, info->bss_idx); +#else + GET_GroupKey_WCID(pAd, info->WCID, info->bss_idx); +#endif /* DOT11W_PMF_SUPPORT */ + txd_1->wlan_idx = info->WCID; + } + else { + txd_1->protect_frm = 0; + } + } + + txd_0->tx_byte_cnt = txd_size + info->Length; // TODO: shiang-7603, need to adjust + //txwi_n->MPDUtotalByteCnt = Length; + + // TODO: shiang-7603, any mapping to following parameters? + + NdisMoveMemory(tmac_info, &txd, sizeof(TMAC_TXD_L)); +#ifdef DBG + if ((RTDebugFunc & DBG_FUNC_TMAC_INFO) == DBG_FUNC_TMAC_INFO) { + dump_tmac_info(pAd, tmac_info); + } +#endif /* DBG */ +} + + +VOID write_tmac_info_Data(RTMP_ADAPTER *pAd, UCHAR *buf, TX_BLK *pTxBlk) +{ + MAC_TABLE_ENTRY *pMacEntry = pTxBlk->pMacEntry; + UCHAR stbc = 0, bw = BW_20, mcs = 0, nss = 1, sgi = 0, phy_mode = 0, preamble = 1, ldpc = 0; + UCHAR wcid, to_mcu = FALSE; + TMAC_TXD_S *txd_s = (TMAC_TXD_S *)buf; + TMAC_TXD_L *txd_l = (TMAC_TXD_L *)buf; + TMAC_TXD_0 *txd_0 = &txd_s->txd_0; + TMAC_TXD_1 *txd_1 = &txd_s->txd_1; + UCHAR txd_size; + BOOLEAN txd_long = FALSE; + struct rtmp_mac_ctrl *wtbl_ctrl = &pAd->mac_ctrl; + //STA_TR_ENTRY *tr_entry; + struct wtbl_entry tb_entry; + union WTBL_1_DW0 *dw0 = (union WTBL_1_DW0 *)&tb_entry.wtbl_1.wtbl_1_d0.word; + TXS_CTL *TxSCtl = &pAd->TxSCtl; + + wcid = pTxBlk->Wcid; + + if (pMacEntry == NULL) + { + //printk("##### MacEntry is NULL ##### \n"); + txd_long = TRUE; + //wcid = 0; // TODO: wcid + } + else + { + //printk("##### MacEntry Aid is %d ##### \n", pMacEntry->Aid); + wcid = pMacEntry->wcid; + if ((pMacEntry->bAutoTxRateSwitch == FALSE) || + (TX_BLK_TEST_FLAG(pTxBlk, fTX_ForceRate)) || + (TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag) && pTxBlk->FragIdx)) + txd_long = TRUE; + } + + /* E1 workaround of DMAS bug, must use long format */ + txd_long = TRUE; + + + if (txd_long == FALSE) { + NdisZeroMemory(txd_s, sizeof(TMAC_TXD_S)); + pTxBlk->hw_rsv_len = 5 * sizeof(UINT32); + txd_s = (TMAC_TXD_S *)(buf + pTxBlk->hw_rsv_len); + } else { + NdisZeroMemory(txd_l, sizeof(TMAC_TXD_L)); + } + txd_0 = &txd_s->txd_0; + txd_1 = &txd_s->txd_1; + + /* DWORD 0 */ + txd_0->p_idx = (to_mcu ? P_IDX_MCU : P_IDX_LMAC); + if (pTxBlk->QueIdx < 4) { + txd_0->q_idx = wmm_aci_2_hw_ac_queue[pTxBlk->QueIdx]; + } else { + // TODO: shiang-usw, consider about MCC case! + txd_0->q_idx = pTxBlk->QueIdx; + } + + txd_1->wlan_idx = wcid; + + + txd_1->hdr_format = TMI_HDR_FT_NOR_80211; + TMI_HDR_INFO_VAL(txd_1->hdr_format, 0, 0, 0, 0, 0, pTxBlk->wifi_hdr_len, 0, txd_1->hdr_info); + if (pTxBlk->HdrPadLen) // TODO: depends on QoS to decide if need to padding + txd_1->hdr_pad = (TMI_HDR_PAD_MODE_TAIL << TMI_HDR_PAD_BIT_MODE) | pTxBlk->HdrPadLen; + + txd_1->no_ack = (TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired) ? 0 : 1); + txd_1->tid = pTxBlk->UserPriority; + + if (pTxBlk->CipherAlg != CIPHER_NONE) + txd_1->protect_frm = 1; + else + txd_1->protect_frm = 0; + if (pMacEntry && IS_ENTRY_APCLI(pMacEntry)) { + //tr_entry = &pAd->MacTab.tr_entry[pMacEntry->wcid]; + tb_entry.wtbl_addr[0] = wtbl_ctrl->wtbl_base_addr[0] + + pMacEntry->wcid * wtbl_ctrl->wtbl_entry_size[0]; + RTMP_IO_READ32(pAd, tb_entry.wtbl_addr[0], &tb_entry.wtbl_1.wtbl_1_d0.word); + txd_1->own_mac = dw0->field.muar_idx; //Carter, refine this + //printk("txd_1->own_mac = %x\n", txd_1->own_mac); + } + else if (pMacEntry && IS_ENTRY_CLIENT(pMacEntry)) { + if (pMacEntry->func_tb_idx == 0) + txd_1->own_mac = 0x0; + else if (pMacEntry->func_tb_idx >= 1 && pMacEntry->func_tb_idx <= 15) + txd_1->own_mac = 0x10 | pMacEntry->func_tb_idx; + + /* for concurrent to handle HW_BSSID_1/2/3 */ + if (pTxBlk->wdev->hw_bssid_idx != 0) + txd_1->own_mac = pTxBlk->wdev->hw_bssid_idx ; + + } + else if (pMacEntry && IS_ENTRY_WDS(pMacEntry)) { + txd_1->own_mac = 0x0; + } + else { +#ifdef USE_BMC + if (pTxBlk->wdev_idx == 0) + txd_1->own_mac = 0x0; + else if (pTxBlk->wdev_idx >= 1 && pTxBlk->wdev_idx <= 15) + txd_1->own_mac = 0x10 | pTxBlk->wdev_idx; +#else + txd_1->own_mac = 0; // TODO: revise this +#endif /* USE_BMC */ + + if (pTxBlk->wdev->hw_bssid_idx != 0) + txd_1->own_mac = pTxBlk->wdev->hw_bssid_idx ; + } + + if (txd_long == FALSE) + { + txd_1->ft = TMI_FT_SHORT; + txd_size = sizeof(TMAC_TXD_S); + } else { + TMAC_TXD_2 *txd_2 = &txd_l->txd_2; + //TMAC_TXD_3 *txd_3 = &txd_l->txd_3; + TMAC_TXD_5 *txd_5 = &txd_l->txd_5; + TMAC_TXD_6 *txd_6 = &txd_l->txd_6; + HTTRANSMIT_SETTING *pTransmit = pTxBlk->pTransmit; + + txd_1->ft = TMI_FT_LONG; + txd_size = sizeof(TMAC_TXD_L); + if (pTransmit) { + ldpc = pTransmit->field.ldpc; + mcs = pTransmit->field.MCS; + sgi = pTransmit->field.ShortGI; + stbc = pTransmit->field.STBC; + phy_mode = pTransmit->field.MODE; + bw = (phy_mode <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); + nss = get_nss_by_mcs(phy_mode, mcs, stbc); + } + + txd_l->txd_2.max_tx_time = 0; + txd_l->txd_2.bc_mc_pkt = (pTxBlk->TxFrameType == TX_MCAST_FRAME ? 1 : 0); + + if (TX_BLK_TEST_FLAG(pTxBlk, fTX_ForceRate)) + txd_l->txd_2.fix_rate = 1; + + txd_l->txd_2.frag = pTxBlk->FragIdx; + + if (pAd->chipCap.TmrEnable == 1) { + if ((txd_1->no_ack == 0) /*&& (txd_l->txd_2.bc_mc_pkt == 0)*/) { + //printk("TMR trigger packet.\n"); + txd_l->txd_2.timing_measure = 1; + } + } + + txd_2->sub_type = (*((UINT16 *)(pTxBlk->wifi_hdr)) & (0xf << 4)) >> 4; + txd_2->frm_type = (*((UINT16 *)(pTxBlk->wifi_hdr)) & (0x3 << 2)) >> 2; + + /*start: fix ping rate*/ + if ((pMacEntry) && (RTMP_GET_PACKET_ICMP(pTxBlk->pPacket)) && PingFixRate) + { + /*solve ping tx hang when HT40, by dragon, 16.01.29 */ + //txd_l->txd_2.fix_rate = 1; + /*if((pMacEntry->RssiSample.AvgRssi[0] >= -60) || (pMacEntry->RssiSample.AvgRssi[1] >= -60)) + { + mcs = 6; + phy_mode = MODE_OFDM; + MTWF_LOG(DBG_CAT_ALL, DBG_SUBCAT_ALL, DBG_LVL_WARN | DBG_FUNC_UAPSD, ("write_tmac_info_Data,%-3d/%-3d,phy_mode=%d,mcs=%d\n", pMacEntry->RssiSample.AvgRssi[0],pMacEntry->RssiSample.AvgRssi[1],phy_mode,mcs)); + } + else*/ + { + mcs = 2; + phy_mode = MODE_CCK; + } + } + /*end: fix ping rate*/ + + if (pMacEntry) + { + if (pAd->shortretry != 0) + txd_l->txd_3.remain_tx_cnt = pAd->shortretry; + else + txd_l->txd_3.remain_tx_cnt = pMacEntry->ucMaxTxRetryCnt; + } else + txd_l->txd_3.remain_tx_cnt = MT_TX_SHORT_RETRY; + + if ((pTxBlk->TxFrameType == TX_LEGACY_FRAME) + || (pTxBlk->TxFrameType == TX_RALINK_FRAME)) + txd_2->ba_disable = 1; + +#ifdef MT7603 + if (MTK_REV_GTE(pAd, MT7603, MT7603E1)) + { + if (txd_0->q_idx == QID_BMC) + txd_l->txd_3.remain_tx_cnt = MT_TX_RETRY_UNLIMIT; + } +#endif /* MT7603 */ + + /* DWORD 6 */ + if (txd_2->fix_rate == 1) { + txd_6->fix_rate_mode = TMI_FIX_RATE_BY_TXD; + txd_6->bw = ((1 << 2) |bw); + txd_6->dyn_bw = 0; + txd_6->ETxBF = 0; + txd_6->ITxBF = 0; + txd_6->ldpc = ldpc; + txd_6->gi = sgi; + + if (txd_6->fix_rate_mode == TMI_FIX_RATE_BY_TXD) + { + if (phy_mode == MODE_CCK) + { + if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED)) + preamble = SHORT_PREAMBLE; + else + preamble = LONG_PREAMBLE; + } + + txd_6->tx_rate = tx_rate_to_tmi_rate(phy_mode, mcs, nss, stbc, preamble); + + } + } + + txd_5->pid = 0; + + if (pTxBlk->Pid) + { + if (TxSCtl->TxSFormatPerPkt & (1 << pTxBlk->Pid)) + txd_5->tx_status_fmt = TXS_FORMAT1; + else + txd_5->tx_status_fmt = TXS_FORMAT0; + + if (TxSCtl->TxS2McUStatusPerPkt & (1 << pTxBlk->Pid)) + txd_5->tx_status_2_mcu = 1; + else + txd_5->tx_status_2_mcu = 0; + + if (TxSCtl->TxS2HostStatusPerPkt & (1 << pTxBlk->Pid)) + { + txd_5->pid = AddTxSStatus(pAd, TXS_TYPE0, pTxBlk->Pid, 0, 0, + txd_6->tx_rate, pTxBlk->TxSPriv); + txd_5->tx_status_2_host = 1; + } + else + { + txd_5->tx_status_2_host = 0; + } + } + else + { + ULONG TxSStatusPerWlanIdx; + if (txd_1->wlan_idx < 64) + { + TxSStatusPerWlanIdx = TxSCtl->TxSStatusPerWlanIdx[0]; + } + else + { + TxSStatusPerWlanIdx = TxSCtl->TxSStatusPerWlanIdx[1]; + } + + if (TxSStatusPerWlanIdx & (1 << txd_1->wlan_idx)) + { + if (TxSCtl->TxSFormatPerPktType[txd_2->frm_type] & (1 << txd_2->sub_type)) + txd_5->tx_status_fmt = TXS_FORMAT1; + else + txd_5->tx_status_fmt = TXS_FORMAT0; + + if (TxSCtl->TxS2McUStatusPerPktType[txd_2->frm_type] & (1 << txd_2->sub_type)) + txd_5->tx_status_2_mcu = 1; + else + txd_5->tx_status_2_mcu = 0; + + if (TxSCtl->TxS2HostStatusPerPktType[txd_2->frm_type] & (1 << txd_2->sub_type)) + { + txd_5->pid = AddTxSStatus(pAd, TXS_TYPE1, 0, + txd_2->frm_type, txd_2->sub_type, txd_6->tx_rate, pTxBlk->TxSPriv); + txd_5->tx_status_2_host = 1; + } + else + { + txd_5->tx_status_2_host = 0; + } + } + } + +#ifdef HDR_TRANS_SUPPORT + //txd_5->da_select = TMI_DAS_FROM_MPDU; +#endif /* HDR_TRANS_SUPPORT */ + txd_5->bar_sn_ctrl = TMI_PM_BIT_CFG_BY_SW; + + /* For MT STA LP control, use H/W control mode for PM bit */ + txd_5->pwr_mgmt = TMI_PM_BIT_CFG_BY_SW; + } + + txd_0->tx_byte_cnt = txd_size + + pTxBlk->MpduHeaderLen + + pTxBlk->HdrPadLen + + pTxBlk->SrcBufLen; // TODO: shiang-7603, need to adjust + +#ifdef DBG_DIAGNOSE + if (pTxBlk->QueIdx== 0) + { + HTTRANSMIT_SETTING *pTransmit = pTxBlk->pTransmit; + UCHAR mcs = pTransmit->field.MCS; + + pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx].TxDataCnt++; +#ifdef DBG_TX_MCS + if (pTransmit->field.MODE == MODE_HTMIX || pTransmit->field.MODE == MODE_HTGREENFIELD) { + if (mcs < MAX_MCS_SET) + pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx].TxMcsCnt_HT[mcs]++; + } +#ifdef DOT11_VHT_AC + else if (pTransmit->field.MODE == MODE_VHT) { + INT mcs_idx = ((mcs >> 4) * 10) + (mcs & 0xf); + if (mcs_idx < MAX_VHT_MCS_SET) + pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx].TxMcsCnt_VHT[mcs_idx]++; + } +#endif /* DOT11_VHT_AC */ +#endif /* DBG_TX_MCS */ + } +#endif /* DBG_DIAGNOSE */ +} + + +VOID write_tmac_info_Cache(RTMP_ADAPTER *pAd, UCHAR *buf, TX_BLK *pTxBlk) +{ + // TODO: shiang-7603, for now, go following function first; + write_tmac_info_Data(pAd, buf, pTxBlk); + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not Finish yet for HT_MT!!!!\n", __FUNCTION__, __LINE__)); + return; +} + + +INT rtmp_mac_set_band(RTMP_ADAPTER *pAd, int band) +{ + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return FALSE; + } + + return TRUE; +} + + +INT mt_mac_set_ctrlch(RTMP_ADAPTER *pAd, UINT8 extch) +{ + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) + return FALSE; + + return TRUE; +} + + +INT rtmp_mac_set_mmps(RTMP_ADAPTER *pAd, INT ReduceCorePower) +{ + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return FALSE; + } + return TRUE; +} + + +#define BCN_TBTT_OFFSET 64 /*defer 64 us*/ +VOID ReSyncBeaconTime(RTMP_ADAPTER *pAd) +{ + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + } +} + + +#ifdef RTMP_MAC_PCI +VOID mt_asic_init_txrx_ring(RTMP_ADAPTER *pAd) +{ + DELAY_INT_CFG_STRUC IntCfg; + UINT32 phy_addr, offset; + INT i; + + /* Reset DMA Index */ + RTMP_IO_WRITE32(pAd, WPDMA_RST_PTR, 0xFFFFFFFF); + + /* + Write Tx Ring base address registers + + The Tx Ring arrangement: + RingIdx SwRingIdx AsicPriority WMM QID LMAC QID MCU QID + 0 Grp1_TxSw0 L QID_AC_BK AC0 + 1 Grp1_TxSw1 L QID_AC_BE AC1 + 2 Grp1_TxSw2 L QID_AC_VI AC2 + 3 Grp1_TxSw3 L QID_AC_VO AC3 + 4 Grp1_MGMT H - AC4 + + 5 CTRL - - + 6 PSMP - - + 7 BC/MC BC/MC + 8 BCN H BCN + + 9 Grp2_MGMT - AC14 + 10 Grp2_TxSw0 L QID_AC_BK AC10 + 11 Grp2_TxSw0 L QID_AC_BE AC11 + 12 Grp2_TxSw0 L QID_AC_VI AC12 + 13 Grp2_TxSw0 L QID_AC_VO AC13 + 14 - + 15 MCU H - MCU 0 + + Ring 0~3 for TxChannel 0 + Ring 10~14 for TxChannel 1 + */ + for (i = 0; i < NUM_OF_TX_RING; i++) { + if (i == QID_AC_BE) + offset = 0x10; + else if (i == QID_AC_BK) + offset = 0; + else + offset = i * 0x10; + phy_addr = RTMP_GetPhysicalAddressLow(pAd->TxRing[i].Cell[0].AllocPa); + pAd->TxRing[i].TxSwFreeIdx = 0; + pAd->TxRing[i].TxCpuIdx = 0; + + pAd->TxRing[i].hw_desc_base = MT_TX_RING_BASE + offset; + pAd->TxRing[i].hw_cidx_addr = MT_TX_RING_CIDX + offset; + pAd->TxRing[i].hw_didx_addr = MT_TX_RING_DIDX + offset; + pAd->TxRing[i].hw_cnt_addr = MT_TX_RING_CNT + offset; + RTMP_IO_WRITE32(pAd, pAd->TxRing[i].hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->TxRing[i].hw_cidx_addr, pAd->TxRing[i].TxCpuIdx); + RTMP_IO_WRITE32(pAd, pAd->TxRing[i].hw_cnt_addr, TX_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->TX_RING_%d[0x%x]: Base=0x%x, Cnt=%d!\n", + i, pAd->TxRing[i].hw_desc_base, phy_addr, TX_RING_SIZE)); + } + + /* init BMC ring */ + offset = QID_BMC * 0x10; + phy_addr = RTMP_GetPhysicalAddressLow(pAd->TxBmcRing.Cell[0].AllocPa); + pAd->TxBmcRing.TxSwFreeIdx = 0; + pAd->TxBmcRing.TxCpuIdx = 0; + pAd->TxBmcRing.hw_desc_base = MT_TX_RING_BASE + offset; + pAd->TxBmcRing.hw_cidx_addr = MT_TX_RING_CIDX + offset; + pAd->TxBmcRing.hw_didx_addr = MT_TX_RING_DIDX + offset; + pAd->TxBmcRing.hw_cnt_addr = MT_TX_RING_CNT + offset; + RTMP_IO_WRITE32(pAd, pAd->TxBmcRing.hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->TxBmcRing.hw_cidx_addr, pAd->TxBmcRing.TxCpuIdx); + RTMP_IO_WRITE32(pAd, pAd->TxBmcRing.hw_cnt_addr, TX_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->TX_BMC_RING [0x%x]: Base=0x%x, Cnt=%d!\n", + pAd->TxBmcRing.hw_desc_base, phy_addr, TX_RING_SIZE)); + + /* init MGMT ring Base/Size/Index pointer CSR */ + phy_addr = RTMP_GetPhysicalAddressLow(pAd->MgmtRing.Cell[0].AllocPa); + pAd->MgmtRing.TxSwFreeIdx = 0; + pAd->MgmtRing.TxCpuIdx = 0; + + pAd->MgmtRing.hw_desc_base = (MT_TX_RING_BASE + MT_RINGREG_DIFF * 4); + pAd->MgmtRing.hw_cnt_addr = (pAd->MgmtRing.hw_desc_base + 0x04); + pAd->MgmtRing.hw_cidx_addr = (pAd->MgmtRing.hw_desc_base + 0x08); + pAd->MgmtRing.hw_didx_addr = (pAd->MgmtRing.hw_desc_base + 0x0c); + RTMP_IO_WRITE32(pAd, pAd->MgmtRing.hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->MgmtRing.hw_cidx_addr, pAd->MgmtRing.TxCpuIdx); + RTMP_IO_WRITE32(pAd, pAd->MgmtRing.hw_cnt_addr, MGMT_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->TX_RING_MGMT[0x%x]: Base=0x%x, Cnt=%d!\n", + pAd->MgmtRing.hw_desc_base, phy_addr, MGMT_RING_SIZE)); + +#ifdef CONFIG_ANDES_SUPPORT + /* init CTRL ring index pointer */ + phy_addr = RTMP_GetPhysicalAddressLow(pAd->CtrlRing.Cell[0].AllocPa); + pAd->CtrlRing.TxSwFreeIdx = 0; + pAd->CtrlRing.TxCpuIdx = 0; + + pAd->CtrlRing.hw_desc_base = (MT_TX_RING_BASE + MT_RINGREG_DIFF * 5); + pAd->CtrlRing.hw_cnt_addr = (pAd->CtrlRing.hw_desc_base + 0x04); + pAd->CtrlRing.hw_cidx_addr = (pAd->CtrlRing.hw_desc_base + 0x08); + pAd->CtrlRing.hw_didx_addr = (pAd->CtrlRing.hw_desc_base + 0x0c); + + RTMP_IO_WRITE32(pAd, pAd->CtrlRing.hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->CtrlRing.hw_cidx_addr, pAd->CtrlRing.TxCpuIdx); + RTMP_IO_WRITE32(pAd, pAd->CtrlRing.hw_cnt_addr, MGMT_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->TX_RING_CTRL: Base=0x%x, Cnt=%d!\n", + phy_addr, MGMT_RING_SIZE)); +#endif /* CONFIG_ANDES_SUPPORT */ + + /* init BCN ring index pointer */ + phy_addr = RTMP_GetPhysicalAddressLow(pAd->BcnRing.Cell[0].AllocPa); + pAd->BcnRing.TxSwFreeIdx = 0; + pAd->BcnRing.TxCpuIdx = 0; + + pAd->BcnRing.hw_desc_base = (MT_TX_RING_BASE + MT_RINGREG_DIFF * MT_TX_RING_BCN_IDX); + pAd->BcnRing.hw_cnt_addr = (pAd->BcnRing.hw_desc_base + 0x4); + pAd->BcnRing.hw_cidx_addr = (pAd->BcnRing.hw_desc_base + 0x8); + pAd->BcnRing.hw_didx_addr = (pAd->BcnRing.hw_desc_base + 0xc); + RTMP_IO_WRITE32(pAd, pAd->BcnRing.hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->BcnRing.hw_cidx_addr, pAd->BcnRing.TxCpuIdx); + RTMP_IO_WRITE32(pAd, pAd->BcnRing.hw_cnt_addr, BCN_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->TX_RING_BCN: Base=0x%x, Cnt=%d!\n", + phy_addr, BCN_RING_SIZE)); + + /* Init RX Ring0 Base/Size/Index pointer CSR */ + for (i = 0; i < NUM_OF_RX_RING; i++) { + offset = i * 0x10; + phy_addr = RTMP_GetPhysicalAddressLow(pAd->RxRing[i].Cell[0].AllocPa); + pAd->RxRing[i].RxSwReadIdx = 0; + pAd->RxRing[i].RxCpuIdx = RX_RING_SIZE - 1; + pAd->RxRing[i].hw_desc_base = MT_RX_RING_BASE + offset; + pAd->RxRing[i].hw_cidx_addr = MT_RX_RING_CIDX + offset; + pAd->RxRing[i].hw_didx_addr = MT_RX_RING_DIDX + offset; + pAd->RxRing[i].hw_cnt_addr = MT_RX_RING_CNT + offset; + RTMP_IO_WRITE32(pAd, pAd->RxRing[i].hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->RxRing[i].hw_cidx_addr, pAd->RxRing[i].RxCpuIdx); + RTMP_IO_WRITE32(pAd, pAd->RxRing[i].hw_cnt_addr, RX_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->RX_RING%d[0x%x]: Base=0x%x, Cnt=%d\n", + i, pAd->RxRing[i].hw_desc_base, phy_addr, RX_RING_SIZE)); + } + + /* Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits */ + AsicWaitPDMAIdle(pAd, 100, 1000); + AsicSetWPDMA(pAd, PDMA_TX_RX, FALSE); + + IntCfg.word = 0; + RTMP_IO_WRITE32(pAd, MT_DELAY_INT_CFG, IntCfg.word); +} +#endif /* RTMP_MAC_PCI */ + + +VOID mt_mac_bcn_buf_init(IN RTMP_ADAPTER *pAd, BOOLEAN bHardReset) +{ + int idx; + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + + + for (idx = 0; idx < pChipCap->BcnMaxHwNum; idx++) + pAd->BeaconOffset[idx] = pChipCap->BcnBase[idx]; + + DBGPRINT(RT_DEBUG_TRACE, ("< Beacon Information: >\n")); + DBGPRINT(RT_DEBUG_TRACE, ("\tFlgIsSupSpecBcnBuf = %s\n", pChipCap->FlgIsSupSpecBcnBuf ? "TRUE" : "FALSE")); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnMaxHwNum = %d\n", pChipCap->BcnMaxHwNum)); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnMaxNum = %d\n", pChipCap->BcnMaxNum)); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnMaxHwSize = 0x%x\n", pChipCap->BcnMaxHwSize)); + DBGPRINT(RT_DEBUG_TRACE, ("\tWcidHwRsvNum = %d\n", pChipCap->WcidHwRsvNum)); + for (idx = 0; idx < pChipCap->BcnMaxHwNum; idx++) { + DBGPRINT(RT_DEBUG_TRACE, ("\t\tBcnBase[%d] = 0x%x, pAd->BeaconOffset[%d]=0x%x\n", + idx, pChipCap->BcnBase[idx], idx, pAd->BeaconOffset[idx])); + } + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return; + } + + /* 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 apidx; + for (apidx = 0; apidx < HW_BEACON_MAX_COUNT(pAd); apidx++) + { + if (pAd->BeaconOffset[apidx] > 0) { + } + } +#endif /* CONFIG_AP_SUPPORT */ + } + +} + + +INT mt_mac_pse_init(RTMP_ADAPTER *pAd) +{ + // TODO: shiang-7603 + + /* do PCI-E remap for physical address 0xa5000000 to 0x40000 */ + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_1, MT_PSE_WTBL_2_ADDR); + +// TODO: shaing, for MT7628, may need to change this as RTMP_MAC_PCI +#ifdef RTMP_PCI_SUPPORT + RTMP_IO_WRITE32(pAd, MCU_PCIE_REMAP_2, 0x80080000); +#endif /* RTMP_PCI_SUPPORT */ + + return TRUE; +} + + +#ifdef DBG +VOID dump_wtbl_1_info(RTMP_ADAPTER *pAd, struct wtbl_1_struc *tb) +{ + union WTBL_1_DW0 *wtbl_1_d0 = (union WTBL_1_DW0 *)&tb->wtbl_1_d0.word; + union WTBL_1_DW1 *wtbl_1_d1 = (union WTBL_1_DW1 *)&tb->wtbl_1_d1.word; + union WTBL_1_DW2 *wtbl_1_d2 = (union WTBL_1_DW2 *)&tb->wtbl_1_d2.word; + union WTBL_1_DW3 *wtbl_1_d3 = (union WTBL_1_DW3 *)&tb->wtbl_1_d3.word; + union WTBL_1_DW4 *wtbl_1_d4 = (union WTBL_1_DW4 *)&tb->wtbl_1_d4.word; + UCHAR addr[6]; + + NdisMoveMemory(&addr[0], &wtbl_1_d1->word, 4); + addr[0] = wtbl_1_d1->field.addr_0 & 0xff; + addr[1] = ((wtbl_1_d1->field.addr_0 & 0xff00) >> 8); + addr[2] = ((wtbl_1_d1->field.addr_0 & 0xff0000) >> 16); + addr[3] = ((wtbl_1_d1->field.addr_0 & 0xff000000) >> 24); + //addr[4] = wtbl_1_d0->field.addr_32 & 0xff; + //addr[5] = (wtbl_1_d0->field.addr_32 & 0xff00 >> 8); + addr[4] = wtbl_1_d0->field.addr_4 & 0xff; + addr[5] = wtbl_1_d0->field.addr_5 & 0xff; + hex_dump("WTBL Segment 1 Raw Data", (UCHAR *)tb, sizeof(struct wtbl_1_struc)); + + DBGPRINT(RT_DEBUG_OFF, ("WTBL Segment 1 Fields:\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tAddr: %02x:%02x:%02x:%02x:%02x:%02x\n", PRINT_MAC(addr))); + DBGPRINT(RT_DEBUG_OFF, ("\tMUAR_Idx:%d\n", wtbl_1_d0->field.muar_idx)); + DBGPRINT(RT_DEBUG_OFF, ("\trc_a1/rc_a2:%d/%d\n", + wtbl_1_d0->field.rc_a1, wtbl_1_d0->field.rc_a2)); + DBGPRINT(RT_DEBUG_OFF, ("\tkid:%d\n", wtbl_1_d0->field.kid)); + DBGPRINT(RT_DEBUG_OFF, ("\trkv/rv:%d/%d\n", wtbl_1_d0->field.rkv, wtbl_1_d0->field.rv)); + DBGPRINT(RT_DEBUG_OFF, ("\tsw:%d\n", wtbl_1_d0->field.sw)); + DBGPRINT(RT_DEBUG_OFF, ("\twm/mm:%d/%d\n", wtbl_1_d0->field.wm, wtbl_1_d2->field.mm)); + + DBGPRINT(RT_DEBUG_OFF, ("\tcipher_suit:%d\n", wtbl_1_d2->field.cipher_suit)); + DBGPRINT(RT_DEBUG_OFF, ("\ttd/fd:%d/%d\n", wtbl_1_d2->field.td, wtbl_1_d2->field.fd)); + DBGPRINT(RT_DEBUG_OFF, ("\tdis_rhtr:%d\n", wtbl_1_d2->field.dis_rhtr)); + DBGPRINT(RT_DEBUG_OFF, ("\taf:%d\n", wtbl_1_d2->field.af)); + DBGPRINT(RT_DEBUG_OFF, ("\ttx_ps:%d\n", wtbl_1_d2->field.tx_ps)); + DBGPRINT(RT_DEBUG_OFF, ("\tr:%d\n", wtbl_1_d2->field.r)); + DBGPRINT(RT_DEBUG_OFF, ("\trts:%d\n", wtbl_1_d2->field.rts)); + DBGPRINT(RT_DEBUG_OFF, ("\tcf_ack:%d\n", wtbl_1_d2->field.cf_ack)); + DBGPRINT(RT_DEBUG_OFF, ("\trdg_ba:%d\n", wtbl_1_d2->field.rdg_ba)); + DBGPRINT(RT_DEBUG_OFF, ("\tsmps:%d\n", wtbl_1_d2->field.smps)); + DBGPRINT(RT_DEBUG_OFF, ("\tbaf_en:%d\n", wtbl_1_d2->field.baf_en)); + DBGPRINT(RT_DEBUG_OFF, ("\tht/vht/ldpc/dyn_bw:%d/%d/%d/%d\n", + wtbl_1_d2->field.ht, wtbl_1_d2->field.vht, + wtbl_1_d2->field.ldpc, wtbl_1_d2->field.dyn_bw)); + DBGPRINT(RT_DEBUG_OFF, ("\tTxBF(tibf/tebf):%d / %d\n", wtbl_1_d2->field.tibf, wtbl_1_d2->field.tebf)); + DBGPRINT(RT_DEBUG_OFF, ("\ttxop_ps_cap:%d\n", wtbl_1_d2->field.txop_ps_cap)); + DBGPRINT(RT_DEBUG_OFF, ("\tmesh:%d\n", wtbl_1_d2->field.mesh)); + DBGPRINT(RT_DEBUG_OFF, ("\tqos:%d\n", wtbl_1_d2->field.qos)); + + DBGPRINT(RT_DEBUG_OFF, ("\tadm:%d\n", wtbl_1_d2->field.adm)); + DBGPRINT(RT_DEBUG_OFF, ("\tgid:%d\n", wtbl_1_d2->field.gid)); + + DBGPRINT(RT_DEBUG_OFF, ("\twtbl2_fid:%d\n", wtbl_1_d3->field.wtbl2_fid)); + DBGPRINT(RT_DEBUG_OFF, ("\twtbl2_eid:%d\n", wtbl_1_d3->field.wtbl2_eid)); + + DBGPRINT(RT_DEBUG_OFF, ("\twtbl3_fid:%d\n", wtbl_1_d4->field.wtbl3_fid)); + DBGPRINT(RT_DEBUG_OFF, ("\twtbl3_eid:%d\n", wtbl_1_d4->field.wtbl3_eid)); + + DBGPRINT(RT_DEBUG_OFF, ("\twtbl4_fid:%d\n", wtbl_1_d3->field.wtbl4_fid)); + DBGPRINT(RT_DEBUG_OFF, ("\twtbl4_eid:%d\n", wtbl_1_d4->field.wtbl4_eid)); + + DBGPRINT(RT_DEBUG_OFF, ("\tchk_per:%d\n", wtbl_1_d3->field.chk_per)); + DBGPRINT(RT_DEBUG_OFF, ("\tdu_i_psm:%d\n", wtbl_1_d3->field.du_i_psm)); + DBGPRINT(RT_DEBUG_OFF, ("\ti_psm:%d\n", wtbl_1_d3->field.i_psm)); + DBGPRINT(RT_DEBUG_OFF, ("\tpsm:%d\n", wtbl_1_d3->field.psm)); + DBGPRINT(RT_DEBUG_OFF, ("\tskip_tx:%d\n", wtbl_1_d3->field.skip_tx)); + + DBGPRINT(RT_DEBUG_OFF, ("\tpartial_aid:%d\n", wtbl_1_d4->field.partial_aid)); +} + + +static UCHAR ba_range[] = {4, 5, 8, 10, 16, 20, 21, 42}; +static UCHAR *bw_str[] = {"20", "40", "80", "160"}; +VOID dump_wtbl_2_info(RTMP_ADAPTER *pAd, struct wtbl_2_struc *tb) +{ + union WTBL_2_DW0 *dw_0 = &tb->wtbl_2_d0; + union WTBL_2_DW1 *dw_1 = &tb->wtbl_2_d1; + union WTBL_2_DW2 *dw_2 = &tb->wtbl_2_d2; + union WTBL_2_DW3 *dw_3 = &tb->wtbl_2_d3; + union WTBL_2_DW4 *dw_4 = &tb->wtbl_2_d4; + union WTBL_2_DW5 *dw_5 = &tb->wtbl_2_d5; + union WTBL_2_DW6 *dw_6 = &tb->wtbl_2_d6; + union WTBL_2_DW7 *dw_7 = &tb->wtbl_2_d7; + union WTBL_2_DW8 *dw_8 = &tb->wtbl_2_d8; + union WTBL_2_DW9 *dw_9 = &tb->wtbl_2_d9; + union WTBL_2_DW10 *dw_10 = &tb->wtbl_2_d10; + union WTBL_2_DW11 *dw_11 = &tb->wtbl_2_d11; + union WTBL_2_DW12 *dw_12 = &tb->wtbl_2_d12; + union WTBL_2_DW13 *dw_13 = &tb->wtbl_2_d13; + union WTBL_2_DW14 *dw_14 = &tb->wtbl_2_d14; + union WTBL_2_DW15 *dw_15 = &tb->wtbl_2_d15; + UINT32 idx, ba_size_idx, ba_size = 0; + BOOLEAN ba_en; + UINT32 rate_info[8]; + + hex_dump("WTBL Segment 2 Raw Data", (UCHAR *)tb, sizeof(struct wtbl_2_struc)); + DBGPRINT(RT_DEBUG_OFF, ("WTBL Segment 2 Fields:\n")); + DBGPRINT(RT_DEBUG_OFF, ("\tPN_0-31:0x%x\n", dw_0->pn_0)); + DBGPRINT(RT_DEBUG_OFF, ("\tPN_32-48:0x%x\n", dw_1->field.pn_32)); + DBGPRINT(RT_DEBUG_OFF, ("\tSN(NonQos/Mgmt Frame):%d\n", dw_1->field.com_sn)); + DBGPRINT(RT_DEBUG_OFF, ("\tSN(TID0~7 QoS Frame):%d - %d - %d - %d - %d - %d - %d - %d\n", + dw_2->field.tid_ac_0_sn, dw_2->field.tid_ac_1_sn, + dw_2->field.tid_ac_2_sn_0 | (dw_3->field.tid_ac_2_sn_9 << 9), + dw_3->field.tid_ac_3_sn, dw_3->field.tid_4_sn, + dw_3->field.tid_5_sn_0 | (dw_4->field.tid_5_sn_5 << 5), + dw_4->field.tid_6_sn, dw_4->field.tid_7_sn)); + DBGPRINT(RT_DEBUG_OFF, ("\tTxRateCnt(1-5):%d(%d) - %d - %d - %d - %d\n", + dw_5->field.rate_1_tx_cnt, dw_5->field.rate_1_fail_cnt, + dw_6->field.rate_2_tx_cnt, dw_6->field.rate_3_tx_cnt, + dw_6->field.rate_4_tx_cnt, dw_6->field.rate_5_tx_cnt)); + DBGPRINT(RT_DEBUG_OFF, ("\tTxBwCnt(Current-Other):%d(%d) - %d(%d)\n", + dw_7->field.current_bw_tx_cnt, dw_7->field.current_bw_fail_cnt, + dw_8->field.other_bw_tx_cnt, dw_8->field.other_bw_fail_cnt)); + DBGPRINT(RT_DEBUG_OFF, ("\tFreqCap:%d(%sMHz)\n", + dw_9->field.fcap, bw_str[dw_9->field.fcap])); + DBGPRINT(RT_DEBUG_OFF, ("\tRateIdx/CBRN/CCBW_SEL/SPE_EN: %d/%d/%d/%d\n", + dw_9->field.rate_idx, dw_9->field.cbrn, dw_9->field.ccbw_sel, dw_9->field.spe_en)); + DBGPRINT(RT_DEBUG_OFF, ("\tMpduCnt(Fail/OK):%d-%d\n", + dw_9->field.mpdu_fail_cnt, dw_9->field.mpdu_ok_cnt)); + DBGPRINT(RT_DEBUG_OFF, ("\tTxRate Info: G2/G4/G8/G16=%d/%d/%d/%d\n", + dw_9->field.g2, dw_9->field.g4, dw_9->field.g8, dw_9->field.g16)); + DBGPRINT(RT_DEBUG_OFF, ("\tTxRate Info: RateIdx/STBC/Nsts/PhyMode/TxRate (RawData)\n")); + rate_info[0] = (dw_10->word & 0xfff); + rate_info[1] = (dw_10->word & 0xfff000) >> 12; + rate_info[2] = ((dw_10->word & 0xff000000) >> 24) | ((dw_11->word & 0xf) << 8); + rate_info[3] = ((dw_11->word & 0xfff0) >> 4); + rate_info[4] = ((dw_11->word & 0xfff0000) >> 16); + rate_info[5] = ((dw_11->word & 0xf0000000) >> 28) | ((dw_12->word & 0xff) << 4); + rate_info[6] = ((dw_12->word & 0xfff00) >> 8); + rate_info[7] = ((dw_12->word & 0xfff00000) >> 20); + for (idx = 0; idx <=7; idx++) + { + UCHAR stbc, nss, phy_mode, rate; + UINT32 raw_data; + + raw_data = rate_info[idx] & 0xfff; + stbc = (raw_data & 0x800) ? 1 : 0; + nss = (raw_data & 0x600) >> 9; + phy_mode = (raw_data & 0x1c0) >> 6; + rate = (raw_data & 0x3f); + //DBGPRINT(RT_DEBUG_OFF, ("\t\t%d/%d/%d/%d/MCS%d 0x%x\n", idx + 1, stbc, nss, phy_mode, rate, rate_info[idx])); + + DBGPRINT(RT_DEBUG_OFF, ("\t\t%d/%d/%d/", idx + 1, stbc, nss)); + if ( phy_mode == MODE_CCK ) + DBGPRINT(RT_DEBUG_OFF, ("CCK/")); + else if ( phy_mode == MODE_OFDM ) + DBGPRINT(RT_DEBUG_OFF, ("OFDM/")); + else if ( phy_mode == MODE_HTMIX ) + DBGPRINT(RT_DEBUG_OFF, ("HT/")); + else if ( phy_mode == MODE_HTGREENFIELD ) + DBGPRINT(RT_DEBUG_OFF, ("GF/")); + else if ( phy_mode == MODE_VHT ) + DBGPRINT(RT_DEBUG_OFF, ("VHT/")); + else + DBGPRINT(RT_DEBUG_OFF, ("unkonw/")); + + if ( phy_mode == MODE_CCK ) { + if ( rate == TMI_TX_RATE_CCK_1M_LP ) + DBGPRINT(RT_DEBUG_OFF, ("1M")); + else if ( rate == TMI_TX_RATE_CCK_2M_LP ) + DBGPRINT(RT_DEBUG_OFF, ("2M")); + else if ( rate == TMI_TX_RATE_CCK_5M_LP ) + DBGPRINT(RT_DEBUG_OFF, ("5M")); + else if ( rate == TMI_TX_RATE_CCK_11M_LP ) + DBGPRINT(RT_DEBUG_OFF, ("11M")); + else if ( rate == TMI_TX_RATE_CCK_2M_SP ) + DBGPRINT(RT_DEBUG_OFF, ("2M")); + else if ( rate == TMI_TX_RATE_CCK_5M_SP ) + DBGPRINT(RT_DEBUG_OFF, ("5M")); + else if ( rate == TMI_TX_RATE_CCK_11M_SP ) + DBGPRINT(RT_DEBUG_OFF, ("11M")); + else + DBGPRINT(RT_DEBUG_OFF, ("unkonw")); + + } else if ( phy_mode == MODE_OFDM ) { + if ( rate == TMI_TX_RATE_OFDM_6M ) + DBGPRINT(RT_DEBUG_OFF, ("6M")); + else if ( rate == TMI_TX_RATE_OFDM_9M ) + DBGPRINT(RT_DEBUG_OFF, ("9M")); + else if ( rate == TMI_TX_RATE_OFDM_12M ) + DBGPRINT(RT_DEBUG_OFF, ("12M")); + else if ( rate == TMI_TX_RATE_OFDM_18M ) + DBGPRINT(RT_DEBUG_OFF, ("18M")); + else if ( rate == TMI_TX_RATE_OFDM_24M ) + DBGPRINT(RT_DEBUG_OFF, ("24M")); + else if ( rate == TMI_TX_RATE_OFDM_36M ) + DBGPRINT(RT_DEBUG_OFF, ("36M")); + else if ( rate == TMI_TX_RATE_OFDM_48M ) + DBGPRINT(RT_DEBUG_OFF, ("48M")); + else if ( rate == TMI_TX_RATE_OFDM_54M ) + DBGPRINT(RT_DEBUG_OFF, ("54M")); + else + DBGPRINT(RT_DEBUG_OFF, ("unkonw")); + } else { + DBGPRINT(RT_DEBUG_OFF, ("MCS%d", rate)); + } + + DBGPRINT(RT_DEBUG_OFF, (" 0x%x\n", rate_info[idx])); + + } + + DBGPRINT(RT_DEBUG_OFF, ("\tResp_RCPI0/Resp_RCPI1/Resp_RCPI2=0x%x/0x%x/0x%x\n", + dw_13->field.resp_rcpi_0, dw_13->field.resp_rcpi_1, dw_13->field.resp_rcpi_2)); + + DBGPRINT(RT_DEBUG_OFF, ("\t1CC(Noise)/2CC(Noise)/3CC(Noise)/CE_RMSD/CC_Sel/Ant_Sel=0x%x/0x%x/0x%x/0x%x/%d/%d\n", + dw_14->field.sts_1_ch_cap_noise, dw_14->field.sts_2_ch_cap_noise, dw_14->field.sts_3_ch_cap_noise, + dw_14->field.ce_rmsd, dw_14->field.cc_noise_sel, dw_14->field.ant_sel)); + + DBGPRINT(RT_DEBUG_OFF, ("\tBA Info: TID/BA_En/BAWinSizeIdx(Range)\n")); + for (idx = 0; idx <=7; idx++) + { + ba_en = (dw_15->field.ba_en & (1 << idx)) ? 1: 0; + ba_size_idx = (dw_15->field.ba_win_size_tid & (0x7 << (idx * 3))) >> ((idx * 3)); + if (ba_size_idx < 8) + ba_size = ba_range[ba_size_idx]; + DBGPRINT(RT_DEBUG_OFF, ("\t\t%d/%d/%d(%d)\n", idx, ba_en, ba_size_idx, ba_size)); + } +} + + +VOID dump_wtbl_3_info(RTMP_ADAPTER *pAd, union wtbl_3_struc *tb) +{ + //hex_dump("WTBL Segment 3 Raw Data", (UCHAR *)tb, sizeof(union wtbl_3_struc)); + //DBGPRINT(RT_DEBUG_OFF, ("WTBL Segment 3 Fields:\n")); +} + + +VOID dump_wtbl_4_info(RTMP_ADAPTER *pAd, struct wtbl_4_struc *tb) +{ + //hex_dump("WTBL Segment 4 Raw Data", (UCHAR *)tb, sizeof(struct wtbl_4_struc)); + //DBGPRINT(RT_DEBUG_OFF, ("WTBL Segment 4 Fields:\n")); +} + + +VOID dump_wtbl_base_info(RTMP_ADAPTER *pAd) +{ + INT idx; + + for (idx = 0; idx < 4; idx++) + { + DBGPRINT(RT_DEBUG_OFF, ("\tWTBL Segment %d info:\n", idx+1)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tMemBaseAddr/FID:0x%x/%d\n", + pAd->mac_ctrl.wtbl_base_addr[idx], + pAd->mac_ctrl.wtbl_base_fid[idx])); + DBGPRINT(RT_DEBUG_OFF, ("\t\tEntrySize/Cnt:%d/%d\n", + pAd->mac_ctrl.wtbl_entry_size[idx], + pAd->mac_ctrl.wtbl_entry_cnt[idx])); + } +} + + +VOID dump_wtbl_info(RTMP_ADAPTER *pAd, UINT wtbl_idx) +{ + INT idx, start_idx, end_idx, tok; + UINT32 addr, val[16]; + struct wtbl_1_struc wtbl_1; + struct wtbl_2_struc wtbl_2; + union wtbl_3_struc wtbl_3; + struct wtbl_4_struc wtbl_4; + + DBGPRINT(RT_DEBUG_OFF, ("Dump WTBL info of WLAN_IDX:%d\n", wtbl_idx)); + + if (wtbl_idx == RESERVED_WCID) { + start_idx = 0; + end_idx = (MT_WTBL_SIZE - 1); + } else if (wtbl_idx < MT_WTBL_SIZE) { + start_idx = end_idx = wtbl_idx; + } else { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Invalid WTBL index(%d)!\n", + __FUNCTION__, wtbl_idx)); + return; + } + + for (idx = start_idx; idx <= end_idx; idx++) + { + /* Read WTBL 1 */ + NdisZeroMemory((UCHAR *)&wtbl_1, sizeof(struct wtbl_1_struc)); + addr = pAd->mac_ctrl.wtbl_base_addr[0] + idx * pAd->mac_ctrl.wtbl_entry_size[0]; + DBGPRINT(RT_DEBUG_OFF, ("WTBL Segment 1 HW Addr:0x%x\n", addr)); + RTMP_IO_READ32(pAd, addr, &wtbl_1.wtbl_1_d0.word); + RTMP_IO_READ32(pAd, addr + 4, &wtbl_1.wtbl_1_d1.word); + RTMP_IO_READ32(pAd, addr + 8, &wtbl_1.wtbl_1_d2.word); + RTMP_IO_READ32(pAd, addr + 12, &wtbl_1.wtbl_1_d3.word); + RTMP_IO_READ32(pAd, addr + 16, &wtbl_1.wtbl_1_d4.word); + dump_wtbl_1_info(pAd, &wtbl_1); + + /* Read WTBL 2 */ + NdisZeroMemory((UCHAR *)&wtbl_2, sizeof(struct wtbl_2_struc)); + addr = pAd->mac_ctrl.wtbl_base_addr[1] + idx * pAd->mac_ctrl.wtbl_entry_size[1]; + DBGPRINT(RT_DEBUG_OFF, ("WTBL Segment 2 HW Addr:0x%x\n", addr)); + for (tok = 0; tok < sizeof(struct wtbl_2_struc) / 4; tok++) { + RTMP_IO_READ32(pAd, addr + tok * 4, &val[tok]); + } + dump_wtbl_2_info(pAd, (struct wtbl_2_struc *)&val[0]); + + /* Read WTBL 3 */ + NdisZeroMemory((UCHAR *)&wtbl_3, sizeof(union wtbl_3_struc)); + addr = pAd->mac_ctrl.wtbl_base_addr[2] + idx * pAd->mac_ctrl.wtbl_entry_size[2]; + DBGPRINT(RT_DEBUG_OFF, ("WTBL Segment 3 HW Addr:0x%x\n", addr)); + for (tok = 0; tok < sizeof(union wtbl_3_struc) / 4; tok++) { + RTMP_IO_READ32(pAd, addr + tok * 4, &val[tok]); + } + dump_wtbl_3_info(pAd, (union wtbl_3_struc *)&val[0]); + //RTMP_IO_READ32(pAd, addr, wtbl_3.); + //dump_wtbl_3_info(pAd, &wtbl_3); + + /* Read WTBL 4 */ + NdisZeroMemory((UCHAR *)&wtbl_4, sizeof(struct wtbl_4_struc)); + addr = pAd->mac_ctrl.wtbl_base_addr[3] + idx * pAd->mac_ctrl.wtbl_entry_size[3]; + DBGPRINT(RT_DEBUG_OFF, ("WTBL Segment 4 HW Addr:0x%x\n", addr)); + RTMP_IO_READ32(pAd, addr, &wtbl_4.ac0.word[0]); + RTMP_IO_READ32(pAd, addr+4, &wtbl_4.ac0.word[1]); + RTMP_IO_READ32(pAd, addr + 8, &wtbl_4.ac1.word[0]); + RTMP_IO_READ32(pAd, addr + 12, &wtbl_4.ac1.word[1]); + RTMP_IO_READ32(pAd, addr + 16, &wtbl_4.ac2.word[0]); + RTMP_IO_READ32(pAd, addr + 20, &wtbl_4.ac2.word[1]); + RTMP_IO_READ32(pAd, addr + 24, &wtbl_4.ac3.word[0]); + RTMP_IO_READ32(pAd, addr + 28, &wtbl_4.ac3.word[1]); + dump_wtbl_4_info(pAd, &wtbl_4); + } +} + + +VOID dump_wtbl_entry(RTMP_ADAPTER *pAd, struct wtbl_entry *ent) +{ + INT idx; + + DBGPRINT(RT_DEBUG_OFF, ("Dump WTBL SW Entry[%d] Cache info\n", ent->wtbl_idx)); + for (idx = 0; idx < 4; idx++) + { + DBGPRINT(RT_DEBUG_OFF, ("\tWTBL %d info:\n", idx+1)); + DBGPRINT(RT_DEBUG_OFF, ("\t\tAddr=0x%x, FID=%d, EID=%d\n", + ent->wtbl_addr[idx], ent->wtbl_fid[idx], ent->wtbl_eid[idx])); + switch (idx) { + case 0: + dump_wtbl_1_info(pAd, &ent->wtbl_1); + break; + case 1: + dump_wtbl_2_info(pAd, &ent->wtbl_2); + break; + case 2: + dump_wtbl_3_info(pAd, &ent->wtbl_3); + break; + case 3: + dump_wtbl_4_info(pAd, &ent->wtbl_4); + break; + default: + break; + } + } +} +#endif /* DBG */ + + +INT mt_wtbl_get_entry234(RTMP_ADAPTER *pAd, UCHAR widx, struct wtbl_entry *ent) +{ + struct rtmp_mac_ctrl *wtbl_ctrl; + UCHAR wtbl_idx, ecnt_per_page; + UINT page_offset, element_offset, idx; + + wtbl_ctrl = &pAd->mac_ctrl; + if (wtbl_ctrl->wtbl_entry_cnt[0] > 0) + wtbl_idx = (widx < wtbl_ctrl->wtbl_entry_cnt[0] ? widx : wtbl_ctrl->wtbl_entry_cnt[0] - 1); + else { + DBGPRINT(RT_DEBUG_ERROR, ("%s():PSE not init yet!\n", __FUNCTION__)); + return FALSE; + } + + ent->wtbl_idx = wtbl_idx; + + for (idx = 0; idx < 4; idx++) { + if (idx == 0) { + /* WTBL 1 */ + ent->wtbl_addr[idx] = wtbl_ctrl->wtbl_base_addr[0] + + wtbl_idx * wtbl_ctrl->wtbl_entry_size[0]; + ent->wtbl_fid[idx] = 0; + ent->wtbl_eid[idx] = 0; + } + else + { + /* WTBL 2/3/4 */ + ecnt_per_page = wtbl_ctrl->page_size / wtbl_ctrl->wtbl_entry_size[idx]; + page_offset = wtbl_idx / ecnt_per_page; + element_offset = wtbl_idx % ecnt_per_page; + ent->wtbl_fid[idx] = wtbl_ctrl->wtbl_base_fid[idx] + page_offset; + if (idx == 2) + ent->wtbl_eid[idx] = element_offset * 2; + else + ent->wtbl_eid[idx] = element_offset; + ent->wtbl_addr[idx] = wtbl_ctrl->wtbl_base_addr[idx] + + page_offset * wtbl_ctrl->page_size + + element_offset * wtbl_ctrl->wtbl_entry_size[idx]; + } + } + + return TRUE; +} + + +INT mt_wtbl_init(RTMP_ADAPTER *pAd) +{ + UINT32 page_cnt, ecnt_per_page, offset; + UCHAR cnt = 0; + struct wtbl_entry tb_entry; + union WTBL_1_DW3 *dw3 = (union WTBL_1_DW3 *)&tb_entry.wtbl_1.wtbl_1_d3.word; + union WTBL_1_DW4 *dw4 = (union WTBL_1_DW4 *)&tb_entry.wtbl_1.wtbl_1_d4.word; + + pAd->mac_ctrl.page_size = MT_PSE_PAGE_SIZE; // size in bytes of each PSE page + + pAd->mac_ctrl.wtbl_base_addr[0] = WTBL_WTBL1DW0; // Start address of WTBL2 in host view + pAd->mac_ctrl.wtbl_entry_size[0] = sizeof(struct wtbl_1_struc); + pAd->mac_ctrl.wtbl_entry_cnt[0] = MT_WTBL_SIZE; + pAd->mac_ctrl.wtbl_base_fid[0] = 0; + + pAd->mac_ctrl.wtbl_base_addr[1] = MT_PCI_REMAP_ADDR_1; // Start address of WTBL2 in host view + pAd->mac_ctrl.wtbl_entry_size[1] = sizeof(struct wtbl_2_struc); + pAd->mac_ctrl.wtbl_entry_cnt[1] = MT_WTBL_SIZE; + pAd->mac_ctrl.wtbl_base_fid[1] = 0; + ecnt_per_page = pAd->mac_ctrl.page_size / sizeof(struct wtbl_2_struc); + page_cnt = (pAd->mac_ctrl.wtbl_entry_cnt[1] + ecnt_per_page - 1) / ecnt_per_page; + offset = page_cnt * pAd->mac_ctrl.page_size; + + pAd->mac_ctrl.wtbl_base_fid[2] = pAd->mac_ctrl.wtbl_base_fid[1] + page_cnt; + pAd->mac_ctrl.wtbl_base_addr[2] = pAd->mac_ctrl.wtbl_base_addr[1] + offset; + pAd->mac_ctrl.wtbl_entry_size[2] = sizeof(union wtbl_3_struc); + pAd->mac_ctrl.wtbl_entry_cnt[2] = MT_WTBL_SIZE; + ecnt_per_page = pAd->mac_ctrl.page_size / sizeof(union wtbl_3_struc); + page_cnt = (pAd->mac_ctrl.wtbl_entry_cnt[2] + ecnt_per_page - 1) / ecnt_per_page; + offset = page_cnt * pAd->mac_ctrl.page_size; + + pAd->mac_ctrl.wtbl_base_fid[3] = pAd->mac_ctrl.wtbl_base_fid[2] + page_cnt; + pAd->mac_ctrl.wtbl_base_addr[3] = pAd->mac_ctrl.wtbl_base_addr[2] + offset; + pAd->mac_ctrl.wtbl_entry_size[3] = sizeof(struct wtbl_4_struc); + pAd->mac_ctrl.wtbl_entry_cnt[3] = MT_WTBL_SIZE; + + for (cnt = 0; cnt < MT_WTBL_SIZE; cnt++) + { + NdisZeroMemory(&tb_entry, sizeof(tb_entry)); + if (mt_wtbl_get_entry234(pAd, cnt, &tb_entry) == FALSE) { + DBGPRINT(RT_DEBUG_ERROR, ("%s():Cannot found WTBL2/3/4 for WCID(%d)\n", + __FUNCTION__, cnt)); + return FALSE; + } + + dw3->field.wtbl2_fid = tb_entry.wtbl_fid[1]; + dw3->field.wtbl2_eid = tb_entry.wtbl_eid[1]; + dw3->field.wtbl4_fid = tb_entry.wtbl_fid[3]; + dw4->field.wtbl3_fid = tb_entry.wtbl_fid[2]; + dw4->field.wtbl3_eid = tb_entry.wtbl_eid[2]; + dw4->field.wtbl4_eid = tb_entry.wtbl_eid[3]; + + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + 12, dw3->word); + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + 16, dw4->word); + + tb_entry.wtbl_1.wtbl_1_d0.field.rc_a2 = 1; + tb_entry.wtbl_1.wtbl_1_d0.field.rv = 1; + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0], tb_entry.wtbl_1.wtbl_1_d0.word); + } +#ifdef DBG + dump_wtbl_base_info(pAd); +#endif /* DBG */ + return TRUE; +} + + +INT mt_hw_tb_init(RTMP_ADAPTER *pAd, BOOLEAN bHardReset) +{ + // TODO: shiang-7603 + + mt_wtbl_init(pAd); + + /* Create default entry for rx packets which A2 is not in our table */ + AsicUpdateRxWCIDTable(pAd, RESERVED_WCID, BROADCAST_ADDR); + + +#if defined(RLT_MAC) || defined(RTMP_MAC) + /* + 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) + { + USHORT KeyIdx; + UINT32 wcid_attr_base = 0, wcid_attr_size = 0, share_key_mode_base = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + wcid_attr_base = RLT_MAC_WCID_ATTRIBUTE_BASE; + wcid_attr_size = RLT_HW_WCID_ATTRI_SIZE; + share_key_mode_base = RLT_SHARED_KEY_MODE_BASE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + wcid_attr_base = MAC_WCID_ATTRIBUTE_BASE; + wcid_attr_size = HW_WCID_ATTRI_SIZE; + share_key_mode_base = SHARED_KEY_MODE_BASE; + } +#endif /* RTMP_MAC */ + + for (KeyIdx = 0; KeyIdx < 4; KeyIdx++) + { + RTMP_IO_WRITE32(pAd, share_key_mode_base + 4*KeyIdx, 0); + } + + /* Clear all pairwise key table when initial*/ + for (KeyIdx = 0; KeyIdx < 256; KeyIdx++) + { + RTMP_IO_WRITE32(pAd, wcid_attr_base + (KeyIdx * wcid_attr_size), 1); + } + } +#endif /* defined(RLT_MAC) || defined(RTMP_MAC) */ + + return TRUE; +} + + +/* + ASIC register initialization sets +*/ +INT mt_mac_init(RTMP_ADAPTER *pAd) +{ + // TODO: shiang-7603 +DBGPRINT(RT_DEBUG_OFF, ("%s()-->\n", __FUNCTION__)); + + mt_mac_pse_init(pAd); + + /* re-set specific MAC registers for individual chip */ + if (pAd->chipOps.AsicMacInit != NULL) + pAd->chipOps.AsicMacInit(pAd); + + /* auto-fall back settings */ + AsicAutoFallbackInit(pAd); + + AsicSetMacMaxLen(pAd); + +DBGPRINT(RT_DEBUG_OFF, ("<--%s()\n", __FUNCTION__)); + return TRUE; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mac/ral_nmac.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mac/ral_nmac.c new file mode 100644 index 000000000..b89e0abba --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mac/ral_nmac.c @@ -0,0 +1,407 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + + + +#ifdef RLT_MAC +VOID dumpRxFCEInfo(RTMP_ADAPTER *pAd, RXFCE_INFO *pRxFceInfo) +{ + hex_dump("RxFCEInfo Raw Data", (UCHAR *)pRxFceInfo, sizeof(RXFCE_INFO)); + + DBGPRINT(RT_DEBUG_OFF, ("RxFCEInfo Fields:\n")); + + DBGPRINT(RT_DEBUG_OFF, ("\tinfo_type=%d\n", pRxFceInfo->info_type)); + DBGPRINT(RT_DEBUG_OFF, ("\ts_port=%d\n", pRxFceInfo->s_port)); + DBGPRINT(RT_DEBUG_OFF, ("\tqsel=%d\n", pRxFceInfo->qsel)); + DBGPRINT(RT_DEBUG_OFF, ("\tpcie_intr=%d\n", pRxFceInfo->pcie_intr)); + DBGPRINT(RT_DEBUG_OFF, ("\tmac_len=%d\n", pRxFceInfo->mac_len)); + DBGPRINT(RT_DEBUG_OFF, ("\tl3l4_done=%d\n", pRxFceInfo->l3l4_done)); + DBGPRINT(RT_DEBUG_OFF, ("\tpkt_80211=%d\n", pRxFceInfo->pkt_80211)); + DBGPRINT(RT_DEBUG_OFF, ("\tip_err=%d\n", pRxFceInfo->ip_err)); + DBGPRINT(RT_DEBUG_OFF, ("\ttcp_err=%d\n", pRxFceInfo->tcp_err)); + DBGPRINT(RT_DEBUG_OFF, ("\tudp_err=%d\n", pRxFceInfo->udp_err)); + DBGPRINT(RT_DEBUG_OFF, ("\tpkt_len=%d\n", pRxFceInfo->pkt_len)); +} +#endif /* RLT_MAC */ + + +static UCHAR *txwi_txop_str[]={"HT_TXOP", "PIFS", "SIFS", "BACKOFF", "Invalid"}; +#define TXWI_TXOP_STR(_x) ((_x) <= 3 ? txwi_txop_str[(_x)]: txwi_txop_str[4]) + +VOID dump_rlt_txwi(RTMP_ADAPTER *pAd, TXWI_STRUC *pTxWI) +{ + struct _TXWI_NMAC *txwi_nmac = (struct _TXWI_NMAC *)pTxWI; + + ASSERT((sizeof(struct _TXWI_NMAC) == pAd->chipCap.TXWISize)); + + DBGPRINT(RT_DEBUG_OFF, ("\tPHYMODE=%d(%s)\n", txwi_nmac->PHYMODE, get_phymode_str(txwi_nmac->PHYMODE))); + DBGPRINT(RT_DEBUG_OFF, ("\tITxBf=%d\n", txwi_nmac->iTxBF)); + DBGPRINT(RT_DEBUG_OFF, ("\tETxBf=%d\n", txwi_nmac->eTxBF)); + DBGPRINT(RT_DEBUG_OFF, ("\tSounding=%d\n", txwi_nmac->Sounding)); + DBGPRINT(RT_DEBUG_OFF, ("\tNDP Sounding BW=%d\n", txwi_nmac->NDPSndBW)); + DBGPRINT(RT_DEBUG_OFF, ("\tNDP Sounding Rate=%d\n", txwi_nmac->NDPSndRate)); + DBGPRINT(RT_DEBUG_OFF, ("\tSTBC=%d\n", txwi_nmac->STBC)); + DBGPRINT(RT_DEBUG_OFF, ("\tShortGI=%d\n", txwi_nmac->ShortGI)); + DBGPRINT(RT_DEBUG_OFF, ("\tBW=%d(%sMHz)\n", txwi_nmac->BW, get_bw_str(txwi_nmac->BW))); + DBGPRINT(RT_DEBUG_OFF, ("\tMCS=%d\n", txwi_nmac->MCS)); + DBGPRINT(RT_DEBUG_OFF, ("\tTxOP=%d(%s)\n", txwi_nmac->txop, TXWI_TXOP_STR(txwi_nmac->txop))); + DBGPRINT(RT_DEBUG_OFF, ("\tMpduDensity=%d\n", txwi_nmac->MpduDensity)); + DBGPRINT(RT_DEBUG_OFF, ("\tAMPDU=%d\n", txwi_nmac->AMPDU)); + DBGPRINT(RT_DEBUG_OFF, ("\tTS=%d\n", txwi_nmac->TS)); + DBGPRINT(RT_DEBUG_OFF, ("\tCF-ACK=%d\n", txwi_nmac->CFACK)); + DBGPRINT(RT_DEBUG_OFF, ("\tMIMO-PS=%d\n", txwi_nmac->MIMOps)); + DBGPRINT(RT_DEBUG_OFF, ("\tNSEQ=%d\n", txwi_nmac->NSEQ)); + DBGPRINT(RT_DEBUG_OFF, ("\tACK=%d\n", txwi_nmac->ACK)); + DBGPRINT(RT_DEBUG_OFF, ("\tFRAG=%d\n", txwi_nmac->FRAG)); + DBGPRINT(RT_DEBUG_OFF, ("\tWCID=%d\n", txwi_nmac->wcid)); + DBGPRINT(RT_DEBUG_OFF, ("\tBAWinSize=%d\n", txwi_nmac->BAWinSize)); + DBGPRINT(RT_DEBUG_OFF, ("\tMPDUtotalByteCnt=%d\n", txwi_nmac->MPDUtotalByteCnt)); + DBGPRINT(RT_DEBUG_OFF, ("\tPID=%d\n", txwi_nmac->TxPktId)); +} + + +VOID dump_rlt_rxwi(RTMP_ADAPTER *pAd, RXWI_STRUC *pRxWI) +{ + struct _RXWI_NMAC *rxwi_n = (struct _RXWI_NMAC *)pRxWI; + + ASSERT((sizeof(struct _RXWI_NMAC) == pAd->chipCap.RXWISize)); + + DBGPRINT(RT_DEBUG_OFF, ("\tWCID=%d\n", rxwi_n->wcid)); + DBGPRINT(RT_DEBUG_OFF, ("\tPhyMode=%d(%s)\n", rxwi_n->phy_mode, get_phymode_str(rxwi_n->phy_mode))); + + if (rxwi_n->phy_mode == MODE_VHT) + DBGPRINT(RT_DEBUG_OFF, ("\tMCS=%d(Nss:%d, MCS:%d)\n", + rxwi_n->mcs, (rxwi_n->mcs >> 4), (rxwi_n->mcs & 0xf))); + else + DBGPRINT(RT_DEBUG_OFF, ("\tMCS=%d\n", rxwi_n->mcs)); + + DBGPRINT(RT_DEBUG_OFF, ("\tBW=%d\n", rxwi_n->bw)); + DBGPRINT(RT_DEBUG_OFF, ("\tSGI=%d\n", rxwi_n->sgi)); + DBGPRINT(RT_DEBUG_OFF, ("\tMPDUtotalByteCnt=%d\n", rxwi_n->MPDUtotalByteCnt)); + DBGPRINT(RT_DEBUG_OFF, ("\tTID=%d\n", rxwi_n->tid)); + DBGPRINT(RT_DEBUG_OFF, ("\tSTBC=%d\n", rxwi_n->stbc)); + DBGPRINT(RT_DEBUG_OFF, ("\tkey_idx=%d\n", rxwi_n->key_idx)); + DBGPRINT(RT_DEBUG_OFF, ("\tBSS_IDX=%d\n", rxwi_n->bss_idx)); + DBGPRINT(RT_DEBUG_OFF,("\tRSSI=%d:%d:%d!\n", (CHAR)(rxwi_n->rssi[0]), (CHAR)(rxwi_n->rssi[1]), (CHAR)(rxwi_n->rssi[2]))); + DBGPRINT(RT_DEBUG_OFF,("\tSNR=%d:%d:%d!\n", (CHAR)rxwi_n->bbp_rxinfo[0], (CHAR)rxwi_n->bbp_rxinfo[1], (CHAR)rxwi_n->bbp_rxinfo[2])); + DBGPRINT(RT_DEBUG_OFF,("\tFreqOffset=%d!\n", (CHAR)rxwi_n->bbp_rxinfo[4])); +} + + +static UCHAR *txinfo_type_str[]={"PKT", "", "CMD", "RSV", "Invalid"}; +static UCHAR *txinfo_d_port_str[]={"WLAN", "CPU_RX", "CPU_TX", "HOST", "VIRT_RX", "VIRT_TX", "DROP", "Invalid"}; +static UCHAR *txinfo_que_str[]={"MGMT", "HCCA", "EDCA_1", "EDCA_2", "Invalid"}; + +#define TXINFO_TYPE_STR(_x) ((_x)<=3 ? txinfo_type_str[_x] : txinfo_type_str[4]) +#define TXINFO_DPORT_STR(_x) ((_x) <= 6 ? txinfo_d_port_str[_x]: txinfo_d_port_str[7]) +#define TXINFO_QUE_STR(_x) ((_x) <= 3 ? txinfo_que_str[_x]: txinfo_que_str[4]) + +VOID dump_rlt_txinfo(RTMP_ADAPTER *pAd, TXINFO_STRUC *pTxInfo) +{ + struct _TXINFO_NMAC_PKT *pkt_txinfo = (struct _TXINFO_NMAC_PKT *)pTxInfo; + + DBGPRINT(RT_DEBUG_OFF, ("\tInfo_Type=%d(%s)\n", pkt_txinfo->info_type, TXINFO_TYPE_STR(pkt_txinfo->info_type))); + DBGPRINT(RT_DEBUG_OFF, ("\td_port=%d(%s)\n", pkt_txinfo->d_port, TXINFO_DPORT_STR(pkt_txinfo->d_port))); + DBGPRINT(RT_DEBUG_OFF, ("\tQSEL=%d(%s)\n", pkt_txinfo->QSEL, TXINFO_QUE_STR(pkt_txinfo->QSEL))); + DBGPRINT(RT_DEBUG_OFF, ("\tWIV=%d\n", pkt_txinfo->wiv)); + DBGPRINT(RT_DEBUG_OFF, ("\t802.11=%d\n", pkt_txinfo->pkt_80211)); + DBGPRINT(RT_DEBUG_OFF, ("\tcso=%d\n", pkt_txinfo->cso)); + DBGPRINT(RT_DEBUG_OFF, ("\ttso=%d\n", pkt_txinfo->tso)); + DBGPRINT(RT_DEBUG_OFF, ("\tpkt_len=0x%x\n", pkt_txinfo->pkt_len)); +} + + +#ifdef RTMP_MAC_PCI +VOID rlt_asic_init_txrx_ring(RTMP_ADAPTER *pAd) +{ + DELAY_INT_CFG_STRUC IntCfg; + UINT32 phy_addr, offset; + INT i; + + /* Reset DMA Index */ + RTMP_IO_WRITE32(pAd, WPDMA_RST_IDX, 0xFFFFFFFF); + + /* + Write Tx Ring base address registers + + The Tx Ring arrangement: + RingIdx SwRingIdx AsicPriority WMM QID + 0 TxSw0 L QID_AC_BE + 1 TxSw1 L QID_AC_BK + 2 TxSw2 L QID_AC_VI + 3 TxSw3 L QID_AC_VO + + 4 CTRL M - + 5 MGMT H - + + 6 - L QID_AC_BE + 7 - L QID_AC_BK + 8 - L QID_AC_VI + 9 - L QID_AC_VO + + Ring 0~3 for TxChannel 0 + Ring 6~9 for TxChannel 1 + */ + for (i = 0; i < NUM_OF_TX_RING; i++) { + offset = i * 0x10; + phy_addr = RTMP_GetPhysicalAddressLow(pAd->TxRing[i].Cell[0].AllocPa); + pAd->TxRing[i].TxSwFreeIdx = 0; + pAd->TxRing[i].TxCpuIdx = 0; + pAd->TxRing[i].hw_desc_base = TX_RING_BASE + offset; + pAd->TxRing[i].hw_cidx_addr = TX_RING_CIDX + offset; + pAd->TxRing[i].hw_didx_addr = TX_RING_DIDX + offset; + pAd->TxRing[i].hw_cnt_addr = TX_RING_CNT + offset; + RTMP_IO_WRITE32(pAd, pAd->TxRing[i].hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->TxRing[i].hw_cidx_addr, pAd->TxRing[i].TxCpuIdx); + RTMP_IO_WRITE32(pAd, pAd->TxRing[i].hw_cnt_addr, TX_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->TX_RING_%d[0x%x]: Base=0x%x, Cnt=%d!\n", + i, pAd->TxRing[i].hw_desc_base, phy_addr, TX_RING_SIZE)); + } + + /* init MGMT ring Base/Size/Index pointer CSR */ + phy_addr = RTMP_GetPhysicalAddressLow(pAd->MgmtRing.Cell[0].AllocPa); + pAd->MgmtRing.TxSwFreeIdx = 0; + pAd->MgmtRing.TxCpuIdx = 0; + +#define TX_MGMT_CNT (pAd->MgmtRing.hw_desc_base + 0x04) +#define TX_MGMT_CIDX (pAd->MgmtRing.hw_desc_base + 0x08) +#define TX_MGMT_DIDX (pAd->MgmtRing.hw_desc_base + 0x0c) + + if (IS_RT8592(pAd)) + pAd->MgmtRing.hw_desc_base = (TX_RING_BASE + RLT_RINGREG_DIFF * 5); + else + pAd->MgmtRing.hw_desc_base = (TX_RING_BASE + RLT_RINGREG_DIFF * 9); + pAd->MgmtRing.hw_cidx_addr = TX_MGMT_CIDX; + pAd->MgmtRing.hw_didx_addr = TX_MGMT_DIDX; + pAd->MgmtRing.hw_cnt_addr = TX_MGMT_CNT; + RTMP_IO_WRITE32(pAd, pAd->MgmtRing.hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->MgmtRing.hw_cidx_addr, pAd->MgmtRing.TxCpuIdx); + RTMP_IO_WRITE32(pAd, pAd->MgmtRing.hw_cnt_addr, MGMT_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->TX_RING_MGMT[0x%x]: Base=0x%x, Cnt=%d!\n", + pAd->MgmtRing.hw_desc_base, phy_addr, MGMT_RING_SIZE)); + +#ifdef CONFIG_ANDES_SUPPORT + /* init CTRL ring index pointer */ + phy_addr = RTMP_GetPhysicalAddressLow(pAd->CtrlRing.Cell[0].AllocPa); + pAd->CtrlRing.TxSwFreeIdx = 0; + pAd->CtrlRing.TxCpuIdx = 0; + +#define TX_CTRL_CNT (pAd->CtrlRing.hw_desc_base + 0x04) +#define TX_CTRL_CIDX (pAd->CtrlRing.hw_desc_base + 0x08) +#define TX_CTRL_DIDX (pAd->CtrlRing.hw_desc_base + 0x0c) + + if (IS_RT8592(pAd)) + pAd->CtrlRing.hw_desc_base = (TX_RING_BASE + RLT_RINGREG_DIFF * 4); + else + pAd->CtrlRing.hw_desc_base = (TX_RING_BASE + RLT_RINGREG_DIFF * 8); + pAd->CtrlRing.hw_cidx_addr = TX_CTRL_CIDX; + pAd->CtrlRing.hw_didx_addr = TX_CTRL_DIDX; + pAd->CtrlRing.hw_cnt_addr = TX_CTRL_CNT; + RTMP_IO_WRITE32(pAd, pAd->CtrlRing.hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->CtrlRing.hw_cidx_addr, pAd->CtrlRing.TxCpuIdx); + RTMP_IO_WRITE32(pAd, pAd->CtrlRing.hw_cnt_addr, MGMT_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->TX_RING_CTRL: Base=0x%x, Cnt=%d!\n", + phy_addr, TX_RING_SIZE)); +#endif /* CONFIG_ANDES_SUPPORT */ + + /* Init RX Ring0 Base/Size/Index pointer CSR */ + for (i = 0; i < NUM_OF_RX_RING; i++) { + offset = i * 0x10; + phy_addr = RTMP_GetPhysicalAddressLow(pAd->RxRing[i].Cell[0].AllocPa); + pAd->RxRing[i].RxSwReadIdx = 0; + pAd->RxRing[i].RxCpuIdx = RX_RING_SIZE - 1; + pAd->RxRing[i].hw_desc_base = RX_RING_BASE + offset; + pAd->RxRing[i].hw_cidx_addr = RX_RING_CIDX + offset; + pAd->RxRing[i].hw_didx_addr = RX_RING_DIDX + offset; + pAd->RxRing[i].hw_cnt_addr = RX_RING_CNT + offset; + RTMP_IO_WRITE32(pAd, pAd->RxRing[i].hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->RxRing[i].hw_cidx_addr, pAd->RxRing[i].RxCpuIdx); + RTMP_IO_WRITE32(pAd, pAd->RxRing[i].hw_cnt_addr, RX_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->RX_RING%d[0x%x]: Base=0x%x, Cnt=%d\n", + i, pAd->RxRing[i].hw_desc_base, phy_addr, RX_RING_SIZE)); + } + + /* Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits */ + AsicWaitPDMAIdle(pAd, 100, 1000); + AsicSetWPDMA(pAd, PDMA_TX_RX, FALSE); + + IntCfg.word = 0; + RTMP_IO_WRITE32(pAd, DELAY_INT_CFG, IntCfg.word); +} +#endif /* RTMP_MAC_PCI */ + + +static UINT32 asic_set_wlan_func(RTMP_ADAPTER *pAd, BOOLEAN enable) +{ + UINT32 reg; + + RTMP_IO_FORCE_READ32(pAd, WLAN_FUN_CTRL, ®); + + if (enable == TRUE) + { + /* + Enable WLAN function and clock + WLAN_FUN_CTRL[1:0] = 0x3 + */ + reg |= WLAN_FUN_CTRL_WLAN_CLK_EN; + reg |= WLAN_FUN_CTRL_WLAN_EN; + } + else + { + /* + Diable WLAN function and clock + WLAN_FUN_CTRL[1:0] = 0x0 + */ + if (IS_PCIE_INF(pAd)) + reg &= ~WLAN_FUN_CTRL_PCIE_APP0_CLK_REQ; + + reg &= ~WLAN_FUN_CTRL_WLAN_EN; + reg &= ~WLAN_FUN_CTRL_WLAN_CLK_EN; + } + + DBGPRINT(RT_DEBUG_TRACE, ("WlanFunCtrl= 0x%x\n", reg)); + RTMP_IO_FORCE_WRITE32(pAd, WLAN_FUN_CTRL, reg); + RtmpusecDelay(20); + + return reg; +} + + +#define MAX_CHECK_COUNT 200 + +INT rlt_wlan_chip_onoff(RTMP_ADAPTER *pAd, BOOLEAN bOn, BOOLEAN bResetWLAN) +{ + UINT32 reg = 0; + +#ifdef RTMP_FLASH_SUPPORT +#endif /* RTMP_FLASH_SUPPORT */ + +#ifdef RTMP_PCI_SUPPORT + if (IS_PCI_INF(pAd)) + RTMP_SEM_LOCK(&pAd->WlanEnLock); +#endif /* RTMP_PCI_SUPPORT */ + + + RTMP_IO_FORCE_READ32(pAd, WLAN_FUN_CTRL, ®); + DBGPRINT(RT_DEBUG_OFF, ("==>%s(): OnOff:%d, Reset= %d, pAd->WlanFunCtrl:0x%x, Reg-WlanFunCtrl=0x%x\n", + __FUNCTION__, bOn, bResetWLAN, pAd->WlanFunCtrl.word, reg)); + + if (bResetWLAN == TRUE) + { + reg &= ~WLAN_FUN_CTRL_GPIO0_OUT_OE_N_MASK; + + reg &= ~WLAN_FUN_CTRL_FRC_WL_ANT_SEL; + + if (pAd->WlanFunCtrl.field.WLAN_EN) + { + /* + Restore all HW default value and reset RF. + */ + reg |= WLAN_FUN_CTRL_WLAN_RESET; + + reg |= WLAN_FUN_CTRL_WLAN_RESET_RF; + DBGPRINT(RT_DEBUG_TRACE, ("Reset(1) WlanFunCtrl.word = 0x%x\n", reg)); + RTMP_IO_FORCE_WRITE32(pAd, WLAN_FUN_CTRL, reg); + RtmpusecDelay(20); + + reg &= ~WLAN_FUN_CTRL_WLAN_RESET; + + reg &= ~WLAN_FUN_CTRL_WLAN_RESET_RF; + + DBGPRINT(RT_DEBUG_TRACE, ("Reset(2) WlanFunCtrl.word = 0x%x\n", reg)); + RTMP_IO_FORCE_WRITE32(pAd, WLAN_FUN_CTRL, reg); + RtmpusecDelay(20); + } else + RTMP_IO_FORCE_WRITE32(pAd, WLAN_FUN_CTRL, reg); + } + + reg = asic_set_wlan_func(pAd, bOn); + + if (bOn) + { + RTMP_IO_FORCE_READ32(pAd, MAC_CSR0, &pAd->MACVersion); + DBGPRINT(RT_DEBUG_TRACE, ("MACVersion = 0x%08x\n", pAd->MACVersion)); + } + + if (bOn == TRUE + ) + { + UINT index = 0; + UINT32 value; + + do + { + do + { + RTMP_IO_FORCE_READ32(pAd, CMB_CTRL, &value); + + /* + Check status of PLL_LD & XTAL_RDY. + HW issue: Must check PLL_LD&XTAL_RDY when setting EEP to disable PLL power down + */ + if (((value & CMB_CTRL_PLL_LD) == CMB_CTRL_PLL_LD) && + ((value & CMB_CTRL_XTAL_RDY) == CMB_CTRL_XTAL_RDY)) + break; + + RtmpusecDelay(20); + } while (index++ < MAX_CHECK_COUNT); + + if (index >= MAX_CHECK_COUNT) + { + DBGPRINT(RT_DEBUG_ERROR, + ("Lenny:[boundary]Check PLL_LD ..CMB_CTRL 0x%08x, index=%d!\n", + value, index)); + /* + Disable WLAN then enable WLAN again + */ + reg = asic_set_wlan_func(pAd, 0); + reg = asic_set_wlan_func(pAd, 1); + } + else + { + break; + } + } while (TRUE); + } + + pAd->WlanFunCtrl.word = reg; + RTMP_IO_FORCE_READ32(pAd, WLAN_FUN_CTRL, ®); + DBGPRINT(RT_DEBUG_TRACE, + ("<== %s():pAd->WlanFunCtrl.word = 0x%x, Reg->WlanFunCtrl=0x%x!\n", + __FUNCTION__, pAd->WlanFunCtrl.word, reg)); + +#ifdef RTMP_MAC_PCI + if (IS_PCI_INF(pAd)) + RTMP_SEM_UNLOCK(&pAd->WlanEnLock); +#endif /* RTMP_MAC_PCI */ + + + return 0; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mac/ral_omac.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mac/ral_omac.c new file mode 100644 index 000000000..9b09f150b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mac/ral_omac.c @@ -0,0 +1,172 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + + +static UCHAR *txwi_txop_str[]={"HT_TXOP", "PIFS", "SIFS", "BACKOFF", "Invalid"}; +#define TXWI_TXOP_STR(_x) ((_x) <= 3 ? txwi_txop_str[(_x)]: txwi_txop_str[4]) +VOID dump_rtmp_txwi(RTMP_ADAPTER *pAd, TXWI_STRUC *pTxWI) +{ + struct _TXWI_OMAC *txwi_o = (struct _TXWI_OMAC *)pTxWI; + + ASSERT((sizeof(struct _TXWI_OMAC) == pAd->chipCap.TXWISize)); + + if (pAd->chipCap.TXWISize != (sizeof(struct _TXWI_OMAC))) + DBGPRINT(RT_DEBUG_TRACE, ("%s():sizeof(struct _TXWI_OMAC)=%d, pAd->chipCap.TXWISize=%d\n", + __FUNCTION__, sizeof(struct _TXWI_OMAC), pAd->chipCap.TXWISize)); + + DBGPRINT(RT_DEBUG_OFF, ("\tPHYMODE=%d(%s)\n", txwi_o->PHYMODE, get_phymode_str(txwi_o->PHYMODE))); + DBGPRINT(RT_DEBUG_OFF, ("\tiTxBF=%d\n", txwi_o->iTxBF)); + DBGPRINT(RT_DEBUG_OFF, ("\tSounding=%d\n", txwi_o->Sounding)); + DBGPRINT(RT_DEBUG_OFF, ("\teTxBF=%d\n", txwi_o->eTxBF)); + DBGPRINT(RT_DEBUG_OFF, ("\tSTBC=%d\n", txwi_o->STBC)); + DBGPRINT(RT_DEBUG_OFF, ("\tShortGI=%d\n", txwi_o->ShortGI)); + DBGPRINT(RT_DEBUG_OFF, ("\tBW=%d(%sMHz)\n", txwi_o->BW, get_bw_str(txwi_o->BW))); + DBGPRINT(RT_DEBUG_OFF, ("\tMCS=%d\n", txwi_o->MCS)); + DBGPRINT(RT_DEBUG_OFF, ("\tTxOP=%d(%s)\n", txwi_o->txop, TXWI_TXOP_STR(txwi_o->txop))); + DBGPRINT(RT_DEBUG_OFF, ("\tMpduDensity=%d\n", txwi_o->MpduDensity)); + DBGPRINT(RT_DEBUG_OFF, ("\tAMPDU=%d\n", txwi_o->AMPDU)); + DBGPRINT(RT_DEBUG_OFF, ("\tTS=%d\n", txwi_o->TS)); + DBGPRINT(RT_DEBUG_OFF, ("\tCF-ACK=%d\n", txwi_o->CFACK)); + DBGPRINT(RT_DEBUG_OFF, ("\tMIMO-PS=%d\n", txwi_o->MIMOps)); + DBGPRINT(RT_DEBUG_OFF, ("\tFRAG=%d\n", txwi_o->FRAG)); + DBGPRINT(RT_DEBUG_OFF, ("\tPID=%d\n", txwi_o->PacketId)); + DBGPRINT(RT_DEBUG_OFF, ("\tMPDUtotalByteCnt=%d\n", txwi_o->MPDUtotalByteCnt)); + DBGPRINT(RT_DEBUG_OFF, ("\tWCID=%d\n", txwi_o->wcid)); + DBGPRINT(RT_DEBUG_OFF, ("\tBAWinSize=%d\n", txwi_o->BAWinSize)); + DBGPRINT(RT_DEBUG_OFF, ("\tNSEQ=%d\n", txwi_o->NSEQ)); + DBGPRINT(RT_DEBUG_OFF, ("\tACK=%d\n", txwi_o->ACK)); +} + + +VOID dump_rtmp_rxwi(RTMP_ADAPTER *pAd, RXWI_STRUC *pRxWI) +{ + struct _RXWI_OMAC *rxwi_o = (struct _RXWI_OMAC *)pRxWI; + + ASSERT((sizeof(struct _RXWI_OMAC) == pAd->chipCap.RXWISize)); + + if (pAd->chipCap.RXWISize != (sizeof(struct _RXWI_OMAC))) + DBGPRINT(RT_DEBUG_TRACE, ("%s():sizeof(struct _RXWI_OMAC)=%d, pAd->chipCap.RXWISize=%d\n", + __FUNCTION__, sizeof(struct _RXWI_OMAC), pAd->chipCap.RXWISize)); + + DBGPRINT(RT_DEBUG_OFF, ("\tWCID=%d\n", rxwi_o->wcid)); + DBGPRINT(RT_DEBUG_OFF, ("\tMPDUtotalByteCnt=%d\n", rxwi_o->MPDUtotalByteCnt)); + DBGPRINT(RT_DEBUG_OFF, ("\tPhyMode=%d(%s)\n", rxwi_o->phy_mode, get_phymode_str(rxwi_o->phy_mode))); + DBGPRINT(RT_DEBUG_OFF, ("\tMCS=%d\n", rxwi_o->mcs)); + DBGPRINT(RT_DEBUG_OFF, ("\tBW=%d\n", rxwi_o->bw)); + DBGPRINT(RT_DEBUG_OFF, ("\tSGI=%d\n", rxwi_o->sgi)); + DBGPRINT(RT_DEBUG_OFF, ("\tSTBC=%d\n", rxwi_o->stbc)); + + + DBGPRINT(RT_DEBUG_OFF, ("\tSequence=%d\n", rxwi_o->SEQUENCE)); + DBGPRINT(RT_DEBUG_OFF, ("\tFRAG=%d\n", rxwi_o->FRAG)); + DBGPRINT(RT_DEBUG_OFF, ("\tTID=%d\n", rxwi_o->tid)); + + DBGPRINT(RT_DEBUG_OFF, ("\tkey_idx=%d\n", rxwi_o->key_idx)); + DBGPRINT(RT_DEBUG_OFF, ("\tBSS_IDX=%d\n", rxwi_o->bss_idx)); + + DBGPRINT(RT_DEBUG_OFF, ("\tRSSI=%d:%d:%d\n", rxwi_o->RSSI0, rxwi_o->RSSI1, rxwi_o->RSSI2)); + DBGPRINT(RT_DEBUG_OFF, ("\tSNR=%d:%d:%d\n", rxwi_o->SNR0, rxwi_o->SNR1, rxwi_o->SNR2)); + DBGPRINT(RT_DEBUG_OFF, ("\tFreqOffset=%d\n", rxwi_o->FOFFSET)); +} + + +#ifdef RTMP_MAC_PCI +VOID rtmp_asic_init_txrx_ring(RTMP_ADAPTER *pAd) +{ + DELAY_INT_CFG_STRUC IntCfg; + UINT32 phy_addr, offset; + INT i; + + + /* + Write Tx Ring base address registers + + The Tx Ring arrangement: + RingIdx SwRingIdx AsicPriority WMM QID + 0 TxSw0 L QID_AC_BE + 1 TxSw1 L QID_AC_BK + 2 TxSw2 L QID_AC_VI + 3 TxSw3 L QID_AC_VO + + 4 HCCA M - + 5 MGMT H - + + Ring 0~3 for TxChannel 0 + Ring 6~9 for TxChannel 1 + */ + for (i = 0; i < NUM_OF_TX_RING; i++) { + offset = i * 0x10; + phy_addr = RTMP_GetPhysicalAddressLow(pAd->TxRing[i].Cell[0].AllocPa); + pAd->TxRing[i].TxSwFreeIdx = 0; + pAd->TxRing[i].TxCpuIdx = 0; + pAd->TxRing[i].hw_desc_base = TX_BASE_PTR0 + offset; + pAd->TxRing[i].hw_cidx_addr = TX_CTX_IDX0 + offset; + pAd->TxRing[i].hw_didx_addr = TX_DTX_IDX0 + offset; + RTMP_IO_WRITE32(pAd, pAd->TxRing[i].hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->TxRing[i].hw_cidx_addr, pAd->TxRing[i].TxCpuIdx); + RTMP_IO_WRITE32(pAd, TX_MAX_CNT0 + offset, TX_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->TX_RING_%d[0x%x]: Base=0x%x, Cnt=%d!\n", + i, pAd->TxRing[i].hw_desc_base, phy_addr, TX_RING_SIZE)); + } + + /* init MGMT ring index pointer */ + phy_addr = RTMP_GetPhysicalAddressLow(pAd->MgmtRing.Cell[0].AllocPa); + pAd->MgmtRing.TxSwFreeIdx = 0; + pAd->MgmtRing.TxCpuIdx = 0; + pAd->MgmtRing.hw_desc_base = TX_BASE_PTR5; + pAd->MgmtRing.hw_cidx_addr = TX_MGMTCTX_IDX; + pAd->MgmtRing.hw_didx_addr = TX_MGMTDTX_IDX; + RTMP_IO_WRITE32(pAd, pAd->MgmtRing.hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->MgmtRing.hw_cidx_addr, pAd->MgmtRing.TxCpuIdx); + RTMP_IO_WRITE32(pAd, TX_MGMTMAX_CNT, MGMT_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->TX_RING_MGMT[0x%x]: Base=0x%x, Cnt=%d!\n", + pAd->MgmtRing.hw_desc_base, phy_addr, MGMT_RING_SIZE)); + + /* Init RX Ring Base/Size/Index pointer CSR */ + phy_addr = RTMP_GetPhysicalAddressLow(pAd->RxRing[0].Cell[0].AllocPa); + pAd->RxRing[0].RxSwReadIdx = 0; + pAd->RxRing[0].RxCpuIdx = RX_RING_SIZE - 1; + pAd->RxRing[0].hw_desc_base = RX_BASE_PTR; + pAd->RxRing[0].hw_cidx_addr = RX_CRX_IDX; + pAd->RxRing[0].hw_didx_addr = RX_DRX_IDX; + RTMP_IO_WRITE32(pAd, pAd->RxRing[0].hw_desc_base, phy_addr); + RTMP_IO_WRITE32(pAd, pAd->RxRing[0].hw_cidx_addr, pAd->RxRing[0].RxCpuIdx); + RTMP_IO_WRITE32(pAd, RX_MAX_CNT, RX_RING_SIZE); + DBGPRINT(RT_DEBUG_TRACE, ("-->RX_RING[0x%x]: Base=0x%x, Cnt=%d\n", + pAd->RxRing[0].hw_desc_base, phy_addr, RX_RING_SIZE)); + + /* Set DMA global configuration except TX_DMA_EN and RX_DMA_EN bits */ + AsicWaitPDMAIdle(pAd, 100, 1000); + AsicSetWPDMA(pAd, PDMA_TX_RX, FALSE); + + IntCfg.word = 0; + RTMP_IO_WRITE32(pAd, DELAY_INT_CFG, IntCfg.word); +} +#endif /* RTMP_MAC_PCI */ + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mac/rtmp_mac.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mac/rtmp_mac.c new file mode 100644 index 000000000..3394a139b --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mac/rtmp_mac.c @@ -0,0 +1,1816 @@ +/* + *************************************************************************** + * Ralink Tech Inc. + * 4F, No. 2 Technology 5th Rd. + * Science-based Industrial Park + * Hsin-chu, Taiwan, R.O.C. + * + * (c) Copyright 2002-2004, Ralink Technology, Inc. + * + * All rights reserved. Ralink's source code is an unpublished work and the + * use of a copyright notice does not imply otherwise. This source code + * contains confidential trade secret material of Ralink Tech. Any attemp + * or participation in deciphering, decoding, reverse engineering or in any + * way altering the source code is stricitly prohibited, unless the prior + * written consent of Ralink Technology, Inc. is obtained. + *************************************************************************** + + Module Name: + + Abstract: + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" + + +VOID dump_rxinfo(RTMP_ADAPTER *pAd, RXINFO_STRUC *pRxInfo) +{ + hex_dump("RxInfo Raw Data", (UCHAR *)pRxInfo, sizeof(RXINFO_STRUC)); + + DBGPRINT(RT_DEBUG_OFF, ("RxInfo Fields:\n")); + + DBGPRINT(RT_DEBUG_OFF, ("\tBA=%d\n", pRxInfo->BA)); + DBGPRINT(RT_DEBUG_OFF, ("\tDATA=%d\n", pRxInfo->DATA)); + DBGPRINT(RT_DEBUG_OFF, ("\tNULLDATA=%d\n", pRxInfo->NULLDATA)); + DBGPRINT(RT_DEBUG_OFF, ("\tFRAG=%d\n", pRxInfo->FRAG)); + DBGPRINT(RT_DEBUG_OFF, ("\tU2M=%d\n", pRxInfo->U2M)); + DBGPRINT(RT_DEBUG_OFF, ("\tMcast=%d\n", pRxInfo->Mcast)); + DBGPRINT(RT_DEBUG_OFF, ("\tBcast=%d\n", pRxInfo->Bcast)); + DBGPRINT(RT_DEBUG_OFF, ("\tMyBss=%d\n", pRxInfo->MyBss)); + DBGPRINT(RT_DEBUG_OFF, ("\tCrc=%d\n", pRxInfo->Crc)); + DBGPRINT(RT_DEBUG_OFF, ("\tCipherErr=%d\n", pRxInfo->CipherErr)); + DBGPRINT(RT_DEBUG_OFF, ("\tAMSDU=%d\n", pRxInfo->AMSDU)); + DBGPRINT(RT_DEBUG_OFF, ("\tHTC=%d\n", pRxInfo->HTC)); + DBGPRINT(RT_DEBUG_OFF, ("\tRSSI=%d\n", pRxInfo->RSSI)); + DBGPRINT(RT_DEBUG_OFF, ("\tL2PAD=%d\n", pRxInfo->L2PAD)); + DBGPRINT(RT_DEBUG_OFF, ("\tAMPDU=%d\n", pRxInfo->AMPDU)); + DBGPRINT(RT_DEBUG_OFF, ("\tDecrypted=%d\n", pRxInfo->Decrypted)); + DBGPRINT(RT_DEBUG_OFF, ("\tBssIdx3=%d\n", pRxInfo->BssIdx3)); + DBGPRINT(RT_DEBUG_OFF, ("\twapi_kidx=%d\n", pRxInfo->wapi_kidx)); + DBGPRINT(RT_DEBUG_OFF, ("\tpn_len=%d\n", pRxInfo->pn_len)); + DBGPRINT(RT_DEBUG_OFF, ("\tsw_fc_type0=%d\n", pRxInfo->sw_fc_type0)); + DBGPRINT(RT_DEBUG_OFF, ("\tsw_fc_type1=%d\n", pRxInfo->sw_fc_type1)); +} + + +VOID dump_txinfo(RTMP_ADAPTER *pAd, TXINFO_STRUC *pTxInfo) +{ + hex_dump("TxInfo Raw Data: ", (UCHAR *)pTxInfo, sizeof(TXINFO_STRUC)); + + DBGPRINT(RT_DEBUG_OFF, ("TxInfo Fields:\n")); + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + dump_rlt_txinfo(pAd, pTxInfo); +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + DBGPRINT(RT_DEBUG_OFF, ("\n")); +#endif /* RTMP_MAC */ +} + + +VOID dump_tmac_info(RTMP_ADAPTER *pAd, UCHAR *tmac_info) +{ + TXWI_STRUC *pTxWI = (TXWI_STRUC *)tmac_info; + hex_dump("TxWI Raw Data: ", (UCHAR *)pTxWI, pAd->chipCap.TXWISize); + + DBGPRINT(RT_DEBUG_OFF, ("TxWI Fields:\n")); +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + dump_rlt_txwi(pAd, pTxWI); +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + dump_rtmp_txwi(pAd, pTxWI); +#endif /* RTMP_MAC */ +} + + +VOID dump_rmac_info(RTMP_ADAPTER *pAd, UCHAR *rmac_info) +{ + RXWI_STRUC *pRxWI = (RXWI_STRUC *)rmac_info; + + hex_dump("RxWI Raw Data", (UCHAR *)pRxWI, pAd->chipCap.RXWISize); + + DBGPRINT(RT_DEBUG_OFF, ("RxWI Fields:\n")); +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + dump_rlt_rxwi(pAd, pRxWI); +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + dump_rtmp_rxwi(pAd, pRxWI); +#endif /* RTMP_MAC */ +} + + +#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(RTMP_ADAPTER *pAd, MAC_TABLE_ENTRY *pEntry) +{ + UINT8 TXWISize; + + if (!pAd || !pEntry) + return; + + TXWISize = pAd->chipCap.TXWISize; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(): TBD for this function!\n", __FUNCTION__)); + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + INT index; + USHORT TxIdx; + RTMP_TX_RING *pTxRing; + TXD_STRUC *pTxD; + TXWI_STRUC *pTxWI; +#ifdef RT_BIG_ENDIAN + TXD_STRUC TxD, *pDestTxD; + TXWI_STRUC TxWI, *pDestTxWI; +#endif /* RT_BIG_ENDIAN */ + + for (index = 3; index >= 0; index--) + { + pTxRing = &pAd->TxRing[index]; + for (TxIdx = 0; TxIdx < TX_RING_SIZE; TxIdx++) + { +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *) pTxRing->Cell[TxIdx].AllocVa; + TxD = *pDestTxD; + pTxD = &TxD; + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#else + pTxD = (TXD_STRUC *) pTxRing->Cell[TxIdx].AllocVa; +#endif /* RT_BIG_ENDIAN */ + + if (!pTxD->DMADONE) + { +#ifdef RT_BIG_ENDIAN + pDestTxWI = (TXWI_STRUC *) pTxRing->Cell[TxIdx].DmaBuf.AllocVa; + NdisMoveMemory((PUCHAR)&TxWI, (PUCHAR)pDestTxWI, TXWISize); + pTxWI = &TxWI; + RTMPWIEndianChange(pAd, (PUCHAR)pTxWI, TYPE_TXWI); +#else + pTxWI = (TXWI_STRUC *)pTxRing->Cell[TxIdx].DmaBuf.AllocVa; +#endif /* RT_BIG_ENDIAN */ + + if (pTxWI->TXWI_O.wcid == pEntry->wcid) + pTxWI->TXWI_O.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 */ +} +#endif /* RTMP_MAC_PCI */ +#endif /* CONFIG_AP_SUPPORT */ + + +INT rtmp_mac_fifo_stat_update(RTMP_ADAPTER *pAd) +{ + TX_STA_FIFO_STRUC StaFifo; + TX_STA_FIFO_EXT_STRUC StaFifoExt; + MAC_TABLE_ENTRY *pEntry = NULL; + UINT32 i = 0; + UCHAR pid = 0, wcid = 0; + INT32 reTry; + UCHAR succMCS; + + + + do + { +#ifdef FIFO_EXT_SUPPORT + if (IS_RT65XX(pAd)) { + RTMP_IO_READ32(pAd, TX_STA_FIFO_EXT, &StaFifoExt.word); + } +#endif /* FIFO_EXT_SUPPORT */ + RTMP_IO_READ32(pAd, TX_STA_FIFO, &StaFifo.word); + + if (StaFifo.field.bValid == 0) + break; + + wcid = (UCHAR)StaFifo.field.wcid; + +#ifdef DBG_CTRL_SUPPORT +#ifdef INCLUDE_DEBUG_QUEUE + if (pAd->CommonCfg.DebugFlags & DBF_DBQ_TXFIFO) { + dbQueueEnqueue(0x73, (UCHAR *)(&StaFifo.word)); + } +#endif /* INCLUDE_DEBUG_QUEUE */ +#endif /* DBG_CTRL_SUPPORT */ + + /* ignore NoACK and MGMT frame use 0xFF as WCID */ + if ((StaFifo.field.TxAckRequired == 0) || (wcid >= MAX_LEN_OF_MAC_TABLE)) + { + i++; + continue; + } + + /* PID store Tx MCS Rate */ +#ifdef FIFO_EXT_SUPPORT + if (IS_RT65XX(pAd)) + pid = (UCHAR)StaFifoExt.field.pkt_id_65xx; + else +#endif /* FIFO_EXT_SUPPORT */ + pid = (UCHAR)StaFifo.field.PidType; + + pEntry = &pAd->MacTab.Content[wcid]; + + if (pEntry & pAd->MacTab.tr_entry[wcid].PsDeQWaitCnt) + pAd->MacTab.tr_entry[wcid].PsDeQWaitCnt = 0; + + pEntry->DebugFIFOCount++; + + +#ifdef DOT11_N_SUPPORT +#endif /* DOT11_N_SUPPORT */ + +#ifdef UAPSD_SUPPORT + UAPSD_SP_AUE_Handle(pAd, pEntry, StaFifo.field.TxSuccess); +#endif /* UAPSD_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 */ + + + /* Update the continuous transmission counter.*/ + pEntry->ContinueTxFailCnt++; + // TODO: shiang-usw, remove upper setting because we need to mirgate to tr_entry! + pAd->MacTab.tr_entry[pEntry->wcid].ContinueTxFailCnt++; + + if(pEntry->PsMode == PWR_ACTIVE) + { +#ifdef DOT11_N_SUPPORT + int tid; + for (tid=0; tidwcid, tid, FALSE, FALSE); +#endif /* DOT11_N_SUPPORT */ + +#ifdef WDS_SUPPORT + /* fix WDS Jam issue*/ + if(IS_ENTRY_WDS(pEntry) + && (pEntry->LockEntryTx == FALSE) + && (pEntry->ContinueTxFailCnt >= pAd->ApCfg.EntryLifeCheck)) + { + DBGPRINT(RT_DEBUG_TRACE, ("Entry %02x:%02x:%02x:%02x:%02x:%02x Blocked!! (Fail Cnt = %d)\n", + PRINT_MAC(pEntry->Addr), pEntry->ContinueTxFailCnt )); + + pEntry->LockEntryTx = TRUE; + // TODO: shiang-usw, remove upper setting because we need to mirgate to tr_entry! + pAd->MacTab.tr_entry[pEntry->wcid].LockEntryTx = TRUE; + + } +#endif /* WDS_SUPPORT */ + } + } +#ifdef CONFIG_AP_SUPPORT +#ifdef RTMP_MAC_PCI + /* if Tx fail >= 20, then clear TXWI ack in Tx Ring*/ + if (pEntry->ContinueTxFailCnt >= pAd->ApCfg.EntryLifeCheck) + ClearTxRingClientAck(pAd, pEntry); +#endif /* RTMP_MAC_PCI */ +#endif /* CONFIG_AP_SUPPORT */ + } + else + { +#ifdef DOT11_N_SUPPORT + if ((pEntry->PsMode != PWR_SAVE) && (pEntry->NoBADataCountDown > 0)) + { + pEntry->NoBADataCountDown--; + if (pEntry->NoBADataCountDown==0) + { + DBGPRINT(RT_DEBUG_TRACE, ("@\n")); + } + } +#endif /* DOT11_N_SUPPORT */ + pEntry->FIFOCount = 0; + pEntry->OneSecTxNoRetryOkCount++; + + + /* update NoDataIdleCount when sucessful send packet to STA.*/ + pEntry->NoDataIdleCount = 0; + pEntry->ContinueTxFailCnt = 0; +#ifdef WDS_SUPPORT + pEntry->LockEntryTx = FALSE; +#endif /* WDS_SUPPORT */ + // TODO: shiang-usw, remove upper setting because we need to mirgate to tr_entry! + pAd->MacTab.tr_entry[pEntry->wcid].NoDataIdleCount = 0; + pAd->MacTab.tr_entry[pEntry->wcid].ContinueTxFailCnt = 0; + pAd->MacTab.tr_entry[pEntry->wcid].LockEntryTx = FALSE; + + } + + 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) ); + +} + + +/* + ======================================================================== + + 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) +{ + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return; + } + + + // TODO: shiang-7603, fix this! + if (pAd->chipCap.hif_type != HIF_MT) { + RTMP_IO_READ32(pAd, TX_STA_CNT0, &pStaTxCnt0->word); + RTMP_IO_READ32(pAd, TX_STA_CNT1, &pStaTxCnt1->word); + } + pAd->bUpdateBcnCntDone = TRUE; /* not appear in Rory's code */ + pAd->RalinkCounters.OneSecBeaconSentCnt += pStaTxCnt0->field.TxBeaconCount; + pAd->RalinkCounters.OneSecTxRetryOkCount += pStaTxCnt1->field.TxRetransmit; + pAd->RalinkCounters.OneSecTxNoRetryOkCount += pStaTxCnt1->field.TxSuccess; + pAd->RalinkCounters.OneSecTxFailCount += pStaTxCnt0->field.TxFailCount; + +#ifdef STATS_COUNT_SUPPORT + pAd->WlanCounters.TransmittedFragmentCount.u.LowPart += pStaTxCnt1->field.TxSuccess; + pAd->WlanCounters.RetryCount.u.LowPart += pStaTxCnt1->field.TxRetransmit; + pAd->WlanCounters.FailedCount.u.LowPart += pStaTxCnt0->field.TxFailCount; +#endif /* STATS_COUNT_SUPPORT */ + +} + + +/* + ======================================================================== + + Routine Description: + Read statistical counters from hardware registers and record them + in software variables for later on query + + Arguments: + pAd Pointer to our adapter + + Return Value: + None + + IRQL = DISPATCH_LEVEL + + ======================================================================== +*/ +VOID NICUpdateRawCounters(RTMP_ADAPTER *pAd) +{ + UINT32 OldValue;/*, Value2;*/ + /*ULONG PageSum, OneSecTransmitCount;*/ + /*ULONG TxErrorRatio, Retry, Fail;*/ + RX_STA_CNT0_STRUC RxStaCnt0; + RX_STA_CNT1_STRUC RxStaCnt1; + RX_STA_CNT2_STRUC RxStaCnt2; + TX_STA_CNT0_STRUC TxStaCnt0; + TX_STA_CNT1_STRUC StaTx1; + TX_STA_CNT2_STRUC StaTx2; +#ifdef STATS_COUNT_SUPPORT + TX_NAG_AGG_CNT_STRUC TxAggCnt; + TX_AGG_CNT0_STRUC TxAggCnt0; + TX_AGG_CNT1_STRUC TxAggCnt1; + TX_AGG_CNT2_STRUC TxAggCnt2; + TX_AGG_CNT3_STRUC TxAggCnt3; + TX_AGG_CNT4_STRUC TxAggCnt4; + TX_AGG_CNT5_STRUC TxAggCnt5; + TX_AGG_CNT6_STRUC TxAggCnt6; + TX_AGG_CNT7_STRUC TxAggCnt7; +#endif /* STATS_COUNT_SUPPORT */ + COUNTER_RALINK *pRalinkCounters; + + + // TODO: shiang-7603 + if (pAd->chipCap.hif_type == HIF_MT) { + DBGPRINT(RT_DEBUG_OFF, ("%s(%d): Not support for HIF_MT yet!\n", + __FUNCTION__, __LINE__)); + return; + } + + + pRalinkCounters = &pAd->RalinkCounters; + + + // TODO: shiang-7603, fix this! + if (pAd->chipCap.hif_type != HIF_MT) { + RTMP_IO_READ32(pAd, RX_STA_CNT0, &RxStaCnt0.word); + RTMP_IO_READ32(pAd, RX_STA_CNT2, &RxStaCnt2.word); + } + + pAd->RalinkCounters.PhyErrCnt += RxStaCnt0.field.PhyErr; +#ifdef 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 */ + { + // TODO: shiang-7603, fix this! + if (pAd->chipCap.hif_type != HIF_MT) { + RTMP_IO_READ32(pAd, RX_STA_CNT1, &RxStaCnt1.word); + } + + /* Update RX PLCP error counter*/ + pAd->RalinkCounters.PlcpErrCnt += RxStaCnt1.field.PlcpErr; + /* Update False CCA counter*/ + pAd->RalinkCounters.OneSecFalseCCACnt = RxStaCnt1.field.FalseCca; + pAd->RalinkCounters.FalseCCACnt += RxStaCnt1.field.FalseCca; + } + +#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); + // TODO: shiang-7603, fix this! + if (pAd->chipCap.hif_type != HIF_MT) { + RTMP_IO_READ32(pAd, TX_STA_CNT2, &StaTx2.word); + } + } + + + /*if (pAd->bStaFifoTest == TRUE)*/ +#ifdef STATS_COUNT_SUPPORT + { + // TODO: shiang-7603, fix this! + if (pAd->chipCap.hif_type != HIF_MT) { + RTMP_IO_READ32(pAd, TX_AGG_CNT, &TxAggCnt.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT0, &TxAggCnt0.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT1, &TxAggCnt1.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT2, &TxAggCnt2.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT3, &TxAggCnt3.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT4, &TxAggCnt4.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT5, &TxAggCnt5.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT6, &TxAggCnt6.word); + RTMP_IO_READ32(pAd, TX_AGG_CNT7, &TxAggCnt7.word); + } + + pRalinkCounters->TxAggCount += TxAggCnt.field.AggTxCount; + pRalinkCounters->TxNonAggCount += TxAggCnt.field.NonAggTxCount; + pRalinkCounters->TxAgg1MPDUCount += TxAggCnt0.field.AggSize1Count; + pRalinkCounters->TxAgg2MPDUCount += TxAggCnt0.field.AggSize2Count; + + pRalinkCounters->TxAgg3MPDUCount += TxAggCnt1.field.AggSize3Count; + pRalinkCounters->TxAgg4MPDUCount += TxAggCnt1.field.AggSize4Count; + pRalinkCounters->TxAgg5MPDUCount += TxAggCnt2.field.AggSize5Count; + pRalinkCounters->TxAgg6MPDUCount += TxAggCnt2.field.AggSize6Count; + + pRalinkCounters->TxAgg7MPDUCount += TxAggCnt3.field.AggSize7Count; + pRalinkCounters->TxAgg8MPDUCount += TxAggCnt3.field.AggSize8Count; + pRalinkCounters->TxAgg9MPDUCount += TxAggCnt4.field.AggSize9Count; + pRalinkCounters->TxAgg10MPDUCount += TxAggCnt4.field.AggSize10Count; + + pRalinkCounters->TxAgg11MPDUCount += TxAggCnt5.field.AggSize11Count; + pRalinkCounters->TxAgg12MPDUCount += TxAggCnt5.field.AggSize12Count; + pRalinkCounters->TxAgg13MPDUCount += TxAggCnt6.field.AggSize13Count; + pRalinkCounters->TxAgg14MPDUCount += TxAggCnt6.field.AggSize14Count; + + pRalinkCounters->TxAgg15MPDUCount += TxAggCnt7.field.AggSize15Count; + pRalinkCounters->TxAgg16MPDUCount += TxAggCnt7.field.AggSize16Count; + + /* Calculate the transmitted A-MPDU count*/ + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += TxAggCnt0.field.AggSize1Count; + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt0.field.AggSize2Count >> 1); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt1.field.AggSize3Count / 3); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt1.field.AggSize4Count >> 2); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt2.field.AggSize5Count / 5); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt2.field.AggSize6Count / 6); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt3.field.AggSize7Count / 7); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt3.field.AggSize8Count >> 3); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt4.field.AggSize9Count / 9); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt4.field.AggSize10Count / 10); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt5.field.AggSize11Count / 11); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt5.field.AggSize12Count / 12); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt6.field.AggSize13Count / 13); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt6.field.AggSize14Count / 14); + + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt7.field.AggSize15Count / 15); + pRalinkCounters->TransmittedAMPDUCount.u.LowPart += (TxAggCnt7.field.AggSize16Count >> 4); + } +#endif /* STATS_COUNT_SUPPORT */ + +#ifdef DBG_DIAGNOSE + { + RtmpDiagStruct *pDiag; + UCHAR ArrayCurIdx, i; + struct dbg_diag_info *diag_info; + + pDiag = &pAd->DiagStruct; + ArrayCurIdx = pDiag->ArrayCurIdx; + + if (pDiag->inited == 0) + { + NdisZeroMemory(pDiag, sizeof(struct _RtmpDiagStrcut_)); + pDiag->ArrayStartIdx = pDiag->ArrayCurIdx = 0; + pDiag->inited = 1; + } + else + { + diag_info = &pDiag->diag_info[ArrayCurIdx]; + + /* Tx*/ + diag_info->TxFailCnt = TxStaCnt0.field.TxFailCount; +#ifdef DBG_TX_AGG_CNT + diag_info->TxAggCnt = TxAggCnt.field.AggTxCount; + diag_info->TxNonAggCnt = TxAggCnt.field.NonAggTxCount; + + diag_info->TxAMPDUCnt[0] = TxAggCnt0.field.AggSize1Count; + diag_info->TxAMPDUCnt[1] = TxAggCnt0.field.AggSize2Count; + diag_info->TxAMPDUCnt[2] = TxAggCnt1.field.AggSize3Count; + diag_info->TxAMPDUCnt[3] = TxAggCnt1.field.AggSize4Count; + diag_info->TxAMPDUCnt[4] = TxAggCnt2.field.AggSize5Count; + diag_info->TxAMPDUCnt[5] = TxAggCnt2.field.AggSize6Count; + diag_info->TxAMPDUCnt[6] = TxAggCnt3.field.AggSize7Count; + diag_info->TxAMPDUCnt[7] = TxAggCnt3.field.AggSize8Count; + diag_info->TxAMPDUCnt[8] = TxAggCnt4.field.AggSize9Count; + diag_info->TxAMPDUCnt[9] = TxAggCnt4.field.AggSize10Count; + diag_info->TxAMPDUCnt[10] = TxAggCnt5.field.AggSize11Count; + diag_info->TxAMPDUCnt[11] = TxAggCnt5.field.AggSize12Count; + diag_info->TxAMPDUCnt[12] = TxAggCnt6.field.AggSize13Count; + diag_info->TxAMPDUCnt[13] = TxAggCnt6.field.AggSize14Count; + diag_info->TxAMPDUCnt[14] = TxAggCnt7.field.AggSize15Count; + diag_info->TxAMPDUCnt[15] = TxAggCnt7.field.AggSize16Count; +#endif /* DBG_TX_AGG_CNT */ + + diag_info->RxCrcErrCnt = RxStaCnt0.field.CrcErr; + + INC_RING_INDEX(pDiag->ArrayCurIdx, DIAGNOSE_TIME); + ArrayCurIdx = pDiag->ArrayCurIdx; + + NdisZeroMemory(&pDiag->diag_info[ArrayCurIdx], sizeof(pDiag->diag_info[ArrayCurIdx])); + + if (pDiag->ArrayCurIdx == pDiag->ArrayStartIdx) + INC_RING_INDEX(pDiag->ArrayStartIdx, DIAGNOSE_TIME); + } + } +#endif /* DBG_DIAGNOSE */ +} + + +/* + ======================================================================== + + 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 val; + + RTMP_IO_READ32(pAd, RX_STA_CNT0, &val); + RTMP_IO_READ32(pAd, RX_STA_CNT1, &val); + RTMP_IO_READ32(pAd, RX_STA_CNT2, &val); + RTMP_IO_READ32(pAd, TX_STA_CNT0, &val); + RTMP_IO_READ32(pAd, TX_STA_CNT1, &val); + RTMP_IO_READ32(pAd, TX_STA_CNT2, &val); +} + + +/* + ======================================================================== + + 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 + + IN RTMP_ADAPTER *pAd, + UCHAR *tmac_info, + BOOLEAN FRAG, + BOOLEAN CFACK, + BOOLEAN InsTimestamp, + BOOLEAN AMPDU, + BOOLEAN Ack, + BOOLEAN NSeq, + UCHAR BASize, + UCHAR WCID, + ULONG Length, + UCHAR PID, + UCHAR TID, + UCHAR TxRate, + UCHAR Txopmode, + HTTRANSMIT_SETTING *pTransmit + + See also : BASmartHardTransmit() !!! + + ======================================================================== +*/ +VOID write_tmac_info( + IN RTMP_ADAPTER *pAd, + IN UCHAR *tmac_info, + IN MAC_TX_INFO *info, + IN HTTRANSMIT_SETTING *pTransmit) +{ + PMAC_TABLE_ENTRY pMac = NULL; + UINT8 TXWISize = pAd->chipCap.TXWISize; + TXWI_STRUC TxWI, *pTxWI, *pOutTxWI = (TXWI_STRUC *)tmac_info; + UINT TxEAPId_Cal = 0; + UCHAR lut_en = FALSE, eTxBf, iTxBf, sounding, ndp_rate, stbc, bw, mcs, sgi, phy_mode, mpdu_density = 0, mimops = 0, ldpc = 0; + + if (info->WCID < MAX_LEN_OF_MAC_TABLE) + pMac = &pAd->MacTab.Content[info->WCID]; + + /* + Always use Long preamble before verifiation short preamble functionality works well. + Todo: remove the following line if short preamble functionality works + */ + OPSTATUS_CLEAR_FLAG(pAd, fOP_STATUS_SHORT_PREAMBLE_INUSED); + NdisZeroMemory(&TxWI, TXWISize); + pTxWI = &TxWI; + +#ifdef DOT11_N_SUPPORT + info->BASize = 0; + stbc = pTransmit->field.STBC; +#endif /* DOT11_N_SUPPORT */ + + /* If CCK or OFDM, BW must be 20*/ + bw = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (bw) + bw = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); +#endif /* DOT11N_DRAFT3 */ +#endif /* DOT11_N_SUPPORT */ + + ldpc = pTransmit->field.ldpc; + mcs = pTransmit->field.MCS; + phy_mode = pTransmit->field.MODE; + sgi = pTransmit->field.ShortGI; + +#ifdef DOT11_N_SUPPORT + if (pMac) + { + if (pAd->CommonCfg.bMIMOPSEnable) + { + if ((pMac->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) + { + /* Dynamic MIMO Power Save Mode*/ + mimops = 1; + } + else if (pMac->MmpsMode == MMPS_STATIC) + { + /* Static MIMO Power Save Mode*/ + if (pTransmit->field.MODE >= MODE_HTMIX && pTransmit->field.MCS > 7) + { + mcs = 7; + mimops = 0; + } + } + } + + mpdu_density = pMac->MpduDensity; + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef DOT11K_RRM_SUPPORT + if (pAd->CommonCfg.VoPwrConstraintTest == TRUE) + { + info->AMPDU = 0; + mcs = 0; + ldpc = 0; + bw = 0; + sgi = 0; + stbc = 0; + phy_mode = MODE_OFDM; + } +#endif /* DOT11K_RRM_SUPPORT */ + + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + struct _TXWI_NMAC *txwi_n = (struct _TXWI_NMAC *)pTxWI; + + txwi_n->lut_en = lut_en; + txwi_n->FRAG = info->FRAG; + txwi_n->CFACK= info->CFACK; + txwi_n->TS = info->InsTimestamp; + txwi_n->AMPDU = info->AMPDU; + txwi_n->ACK = info->Ack; + txwi_n->txop = info->Txopmode; + txwi_n->NSEQ = info->NSeq; + txwi_n->BAWinSize = info->BASize; + txwi_n->ShortGI = sgi; + txwi_n->STBC = stbc; + txwi_n->LDPC = ldpc; + txwi_n->MCS= mcs; + txwi_n->BW = bw; + txwi_n->PHYMODE= phy_mode; + txwi_n->MpduDensity = mpdu_density; + txwi_n->MIMOps = mimops; + txwi_n->wcid = info->WCID; + txwi_n->MPDUtotalByteCnt = info->Length; + txwi_n->TxPktId = mcs; // PID is not used now! + txwi_n->GroupID = TRUE; // Group for AP --> Hauze + txwi_n->TxEAPId = TxEAPId_Cal; + + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + struct _TXWI_OMAC *txwi_o = (struct _TXWI_OMAC *)pTxWI; + txwi_o->FRAG = info->FRAG; + txwi_o->CFACK = info->CFACK; + txwi_o->TS = info->InsTimestamp; + txwi_o->AMPDU = info->AMPDU; + txwi_o->ACK = info->Ack; + txwi_o->txop = info->Txopmode; + txwi_o->NSEQ = info->NSeq; + txwi_o->BAWinSize = info->BASize; + txwi_o->ShortGI = sgi; + txwi_o->STBC = stbc; + txwi_o->MCS = mcs; + txwi_o->BW = bw; + txwi_o->PHYMODE = phy_mode; + txwi_o->MpduDensity = mpdu_density; + txwi_o->MIMOps = mimops; + txwi_o->wcid = info->WCID; + txwi_o->MPDUtotalByteCnt = info->Length; + txwi_o->PacketId = mcs; // PID is not used now! + } +#endif /* RTMP_MAC */ + + NdisMoveMemory(pOutTxWI, &TxWI, TXWISize); +//+++Add by shiang for debug +if (0){ + hex_dump("TxWI", (UCHAR *)pOutTxWI, TXWISize); + dump_tmac_info(pAd, (UCHAR *)pOutTxWI); +} +//---Add by shiang for debug +} + + +VOID write_tmac_info_Data(RTMP_ADAPTER *pAd, UCHAR *buf, TX_BLK *pTxBlk) +{ + HTTRANSMIT_SETTING *pTransmit; + MAC_TABLE_ENTRY *pMacEntry; + UINT8 TXWISize = pAd->chipCap.TXWISize; + UCHAR wcid, pkt_id; + UCHAR sgi, mcs, bw, stbc, phy_mode, ldpc; +#ifdef DOT11_N_SUPPORT + UCHAR basize, ampdu, mimops = 0, mpdu_density = 0; +#endif /* DOT11_N_SUPPORT */ +#ifdef MCS_LUT_SUPPORT + BOOLEAN lut_enable = 0; +#endif /* MCS_LUT_SUPPORT */ + TXWI_STRUC *pTxWI = NULL; + + pTransmit = pTxBlk->pTransmit; + pMacEntry = pTxBlk->pMacEntry; + + /* Reserve space for TXINFO_SIZE */ + pTxBlk->hw_rsv_len = TXINFO_SIZE; + pTxWI = (TXWI_STRUC *)(buf + TXINFO_SIZE); + + /* + 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); + + wcid = pTxBlk->Wcid; + + sgi = pTransmit->field.ShortGI; + stbc = pTransmit->field.STBC; + ldpc = pTransmit->field.ldpc; + mcs = pTransmit->field.MCS; + phy_mode = pTransmit->field.MODE; + /* If CCK or OFDM, BW must be 20 */ + bw = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); + +#ifdef DOT11_N_SUPPORT +#ifdef DOT11N_DRAFT3 + if (bw) + bw = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); +#endif /* DOT11N_DRAFT3 */ + + ampdu = ((pTxBlk->TxFrameType == TX_AMPDU_FRAME) ? TRUE : FALSE); + basize = pAd->CommonCfg.TxBASize; + if(ampdu && pMacEntry) + { + /* + * Under HT20, 2x2 chipset, OPEN, and with some atero chipsets + * reduce BASize to 7 to add one bulk A-MPDU during one TXOP + * to improve throughput + */ + if ((pAd->CommonCfg.BBPCurrentBW == BW_20) && (pAd->Antenna.field.TxPath == 2) + && (pMacEntry->bIAmBadAtheros) && (pMacEntry->WepStatus == Ndis802_11EncryptionDisabled)) + { + basize = 7; + } + else + { + UCHAR RABAOriIdx = pTxBlk->pMacEntry->BAOriWcidArray[pTxBlk->UserPriority]; + basize = pAd->BATable.BAOriEntry[RABAOriIdx].BAWinSize; + } + } + + +#endif /* DOT11_N_SUPPORT */ + + + +#ifdef DOT11_N_SUPPORT + if (pMacEntry) + { + if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (mcs > 7)) + mimops = 1; + else if (pMacEntry->MmpsMode == MMPS_STATIC) + { + if ((pTransmit->field.MODE == MODE_HTMIX || pTransmit->field.MODE == MODE_HTGREENFIELD) && + (mcs > 7)) + { + mcs = 7; + mimops = 0; + } + } + + if ((pAd->CommonCfg.BBPCurrentBW == BW_20) && (pMacEntry->bIAmBadAtheros)) + mpdu_density = 7; + else + mpdu_density = pMacEntry->MpduDensity; + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef DBG_DIAGNOSE + if (pTxBlk->QueIdx== 0) + { + pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx].TxDataCnt++; +#ifdef DBG_TX_MCS + if (pTransmit->field.MODE == MODE_HTMIX || pTransmit->field.MODE == MODE_HTGREENFIELD) { + if (mcs < MAX_MCS_SET) + pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx].TxMcsCnt_HT[mcs]++; + } +#ifdef DOT11_VHT_AC + else if (pTransmit->field.MODE == MODE_VHT) { + INT mcs_idx = ((mcs >> 4) * 10) + (mcs & 0xf); + if (mcs_idx < MAX_VHT_MCS_SET) + pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx].TxMcsCnt_VHT[mcs_idx]++; + } +#endif /* DOT11_VHT_AC */ +#endif /* DBG_TX_MCS */ + } +#endif /* DBG_DIAGNOSE */ + + /* for rate adapation*/ + pkt_id = mcs; + +#ifdef INF_AMAZON_SE + /*Iverson patch for WMM A5-T07 ,WirelessStaToWirelessSta do not bulk out aggregate */ + if( RTMP_GET_PACKET_NOBULKOUT(pTxBlk->pPacket)) + { + if(phy_mode == MODE_CCK) + pkt_id = 6; + } +#endif /* INF_AMAZON_SE */ + +#ifdef DOT11K_RRM_SUPPORT + if (pAd->CommonCfg.VoPwrConstraintTest == TRUE) + { + ampdu = 0; + mcs = 0; + ldpc = 0; + bw = 0; + sgi = 0; + stbc = 0; + phy_mode = MODE_OFDM; + } +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef CONFIG_FPGA_MODE + if (pAd->fpga_ctl.fpga_on & 0x6) + { + phy_mode = pAd->fpga_ctl.tx_data_phy; + mcs = pAd->fpga_ctl.tx_data_mcs; + ldpc = pAd->fpga_ctl.tx_data_ldpc; + bw = pAd->fpga_ctl.tx_data_bw; + sgi = pAd->fpga_ctl.tx_data_gi; + if (pAd->fpga_ctl.data_basize) + basize = pAd->fpga_ctl.data_basize; + } +#endif /* CONFIG_FPGA_MODE */ + +#ifdef MCS_LUT_SUPPORT + if ((RTMP_TEST_MORE_FLAG(pAd, fASIC_CAP_MCS_LUT)) && + (wcid < 128) && + (pMacEntry && pMacEntry->bAutoTxRateSwitch == TRUE)) + { + HTTRANSMIT_SETTING rate_ctrl; + + rate_ctrl.field.MODE = phy_mode; + rate_ctrl.field.STBC = stbc; + rate_ctrl.field.ShortGI = sgi; + rate_ctrl.field.BW = bw; + rate_ctrl.field.ldpc = ldpc; + rate_ctrl.field.MCS = mcs; + if (rate_ctrl.word == pTransmit->word) + lut_enable = 1; + } +#ifdef PEER_DELBA_TX_ADAPT + if (RTMP_GET_PACKET_LOWRATE(pTxBlk->pPacket) || (wcid == MCAST_WCID)) + lut_enable = 0; + else + lut_enable = 1; +#endif /* PEER_DELBA_TX_ADAPT */ +#endif /* MCS_LUT_SUPPORT */ + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + struct _TXWI_NMAC *txwi_n = (struct _TXWI_NMAC *)pTxWI; + + txwi_n->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag); + txwi_n->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); +#ifdef WFA_VHT_PF + if (pAd->force_noack == TRUE) + txwi_n->ACK = 0; +#endif /* WFA_VHT_PF */ + txwi_n->txop = pTxBlk->FrameGap; + txwi_n->wcid = wcid; + txwi_n->MPDUtotalByteCnt = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + txwi_n->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack); + txwi_n->ShortGI = sgi; + txwi_n->STBC = stbc; + txwi_n->LDPC = ldpc; + + +#ifdef MCS_LUT_SUPPORT + if (lut_enable) + txwi_n->MCS = 0; + else +#endif + txwi_n->MCS = mcs; + + txwi_n->PHYMODE = phy_mode; + txwi_n->BW = bw; + txwi_n->TxPktId = pkt_id; + +#ifdef DOT11_N_SUPPORT + txwi_n->AMPDU = ampdu; + txwi_n->BAWinSize = basize; + txwi_n->MIMOps = mimops; + txwi_n->MpduDensity = mpdu_density; +#endif /* DOT11_N_SUPPORT */ + + +#ifdef MCS_LUT_SUPPORT + txwi_n->lut_en = lut_enable; +#endif /* MCS_LUT_SUPPORT */ + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + struct _TXWI_OMAC *txwi_o = (struct _TXWI_OMAC *)pTxWI; + + txwi_o->FRAG = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAllowFrag); + txwi_o->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); +#ifdef WFA_VHT_PF + if (pAd->force_noack == TRUE) + txwi_o->ACK = 0; +#endif /* WFA_VHT_PF */ + txwi_o->txop = pTxBlk->FrameGap; + txwi_o->wcid = wcid; + txwi_o->MPDUtotalByteCnt = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + txwi_o->CFACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bPiggyBack); + txwi_o->ShortGI = sgi; + txwi_o->STBC = stbc; + txwi_o->MCS = mcs; + txwi_o->PHYMODE = phy_mode; + txwi_o->BW = bw; + txwi_o->PacketId = pkt_id; + +#ifdef DOT11_N_SUPPORT + txwi_o->AMPDU = ampdu; + txwi_o->BAWinSize = basize; + txwi_o->MIMOps = mimops; + txwi_o->MpduDensity= mpdu_density; +#endif /* DOT11_N_SUPPORT */ + + } +#endif /* RTMP_MAC */ +} + + +VOID write_tmac_info_Cache(RTMP_ADAPTER *pAd, UCHAR *buf, TX_BLK *pTxBlk) +{ + HTTRANSMIT_SETTING *pTransmit = pTxBlk->pTransmit; + HTTRANSMIT_SETTING tmpTransmit; + MAC_TABLE_ENTRY *pMacEntry = pTxBlk->pMacEntry; + STA_TR_ENTRY *tr_entry = pTxBlk->tr_entry; + UCHAR pkt_id; + UCHAR bw, mcs, stbc, phy_mode, sgi, ldpc; +#ifdef DOT11_N_SUPPORT + UCHAR ampdu, basize = 0, mimops, mpdu_density = 0; +#endif /* DOT11_N_SUPPORT */ +#ifdef MCS_LUT_SUPPORT + BOOLEAN lut_enable; +#endif /* MCS_LUT_SUPPORT */ + TXWI_STRUC *pTxWI; + + /* Reserve space for TXINFO_SIZE */ + pTxBlk->hw_rsv_len = TXINFO_SIZE; + pTxWI = (TXWI_STRUC *)(buf + TXINFO_SIZE); + + /* If CCK or OFDM, BW must be 20*/ + bw = (pTransmit->field.MODE <= MODE_OFDM) ? (BW_20) : (pTransmit->field.BW); + sgi = pTransmit->field.ShortGI; + stbc = pTransmit->field.STBC; + ldpc = pTransmit->field.ldpc; + mcs = pTransmit->field.MCS; + phy_mode = pTransmit->field.MODE; + pMacEntry->LastTxRate = pTransmit->word; + +#ifdef DOT11_N_SUPPORT + ampdu = ((pMacEntry->NoBADataCountDown == 0) ? TRUE: FALSE); + +#ifdef DOT11N_DRAFT3 + if (bw) + bw = (pAd->CommonCfg.AddHTInfo.AddHtInfo.RecomWidth == 0) ? (BW_20) : (pTransmit->field.BW); +#endif /* DOT11N_DRAFT3 */ + + mimops = 0; + if (pAd->CommonCfg.bMIMOPSEnable) + { + /* MIMO Power Save Mode*/ + if ((pMacEntry->MmpsMode == MMPS_DYNAMIC) && (pTransmit->field.MCS > 7)) + mimops = 1; + else if (pMacEntry->MmpsMode == MMPS_STATIC) + { + if ((pTransmit->field.MODE >= MODE_HTMIX) && (pTransmit->field.MCS > 7)) + { + mcs = 7; + mimops = 0; + } + } + } + + if(ampdu) + { + /* + * Under HT20, 2x2 chipset, OPEN, and with some atero chipsets + * reduce BASize to 7 to add one bulk A-MPDU during one TXOP + * to improve throughput + */ + if ((pAd->CommonCfg.BBPCurrentBW == BW_20) && (pMacEntry->bIAmBadAtheros)) + { + mpdu_density = 7; + if ((pAd->Antenna.field.TxPath == 2) && + (pMacEntry->WepStatus == Ndis802_11EncryptionDisabled)) + { + basize = 7; + } + } + + } +#endif /* DOT11_N_SUPPORT */ + +#ifdef DBG_DIAGNOSE + if (pTxBlk->QueIdx== 0) + { + pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx].TxDataCnt++; +#ifdef DBG_TX_MCS + if (pTransmit->field.MODE == MODE_HTMIX || pTransmit->field.MODE == MODE_HTGREENFIELD) { + if (mcs < MAX_MCS_SET) + pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx].TxMcsCnt_HT[mcs]++; + } +#ifdef DOT11_VHT_AC + else if (pTransmit->field.MODE == MODE_VHT) { + INT mcs_idx = ((mcs >> 4) * 10) + (mcs & 0xf); + if (mcs_idx < MAX_VHT_MCS_SET) + pAd->DiagStruct.diag_info[pAd->DiagStruct.ArrayCurIdx].TxMcsCnt_VHT[mcs_idx]++; + } +#endif /* DOT11_VHT_AC */ +#endif /* DBG_TX_MCS */ + } +#endif /* DBG_DIAGNOSE */ + + +#ifdef DOT11K_RRM_SUPPORT + if (pAd->CommonCfg.VoPwrConstraintTest == TRUE) + { + ampdu = 0; + mcs = 0; + ldpc = 0; + bw = 0; + sgi = 0; + stbc = 0; + phy_mode = MODE_OFDM; + } +#endif /* DOT11K_RRM_SUPPORT */ + +#ifdef CONFIG_FPGA_MODE + if (pAd->fpga_ctl.fpga_on & 0x6) + { + phy_mode = pAd->fpga_ctl.tx_data_phy; + mcs = pAd->fpga_ctl.tx_data_mcs; + ldpc = pAd->fpga_ctl.tx_data_ldpc; + bw = pAd->fpga_ctl.tx_data_bw; + sgi = pAd->fpga_ctl.tx_data_gi; + stbc = pAd->fpga_ctl.tx_data_stbc; + if (pAd->fpga_ctl.data_basize) + basize = pAd->fpga_ctl.data_basize; + + tmpTransmit.field.BW = bw; + tmpTransmit.field.ShortGI = sgi; + tmpTransmit.field.STBC = stbc; + tmpTransmit.field.ldpc = ldpc; + tmpTransmit.field.MCS = mcs; + tmpTransmit.field.MODE = phy_mode; + + pMacEntry->LastTxRate = tmpTransmit.word; + } +#endif /* CONFIG_FPGA_MODE */ + +#ifdef MCS_LUT_SUPPORT + lut_enable = 0; + if (RTMP_TEST_MORE_FLAG(pAd, fASIC_CAP_MCS_LUT) && + (pTxBlk->Wcid < 128) && + (pMacEntry->bAutoTxRateSwitch == TRUE)) + { + HTTRANSMIT_SETTING rate_ctrl; + + rate_ctrl.field.MODE = phy_mode; + rate_ctrl.field.STBC = stbc; + rate_ctrl.field.ShortGI = sgi; + rate_ctrl.field.BW = bw; + rate_ctrl.field.ldpc = ldpc; + rate_ctrl.field.MCS = mcs; + if (rate_ctrl.word == pTransmit->word) + lut_enable = 1; + } +#endif /* MCS_LUT_SUPPORT */ + + /* set PID for TxRateSwitching*/ + pkt_id = mcs; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + struct _TXWI_NMAC *txwi_n = (struct _TXWI_NMAC *)pTxWI; + + txwi_n->txop = IFS_HTTXOP; + txwi_n->BW = bw; + txwi_n->ShortGI = sgi; + txwi_n->STBC = stbc; + txwi_n->LDPC = ldpc; + +#ifdef MCS_LUT_SUPPORT + if (lut_enable) + txwi_n->MCS = 0; + else +#endif + txwi_n->MCS = mcs; + + txwi_n->PHYMODE = phy_mode; + txwi_n->TxPktId = pkt_id; + txwi_n->MPDUtotalByteCnt = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + txwi_n->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); +#ifdef WFA_VHT_PF + if (pAd->force_noack == TRUE) + txwi_n->ACK = 0; +#endif /* WFA_VHT_PF */ + +#ifdef DOT11_N_SUPPORT + txwi_n->AMPDU = ampdu; + if (basize) + txwi_n->BAWinSize = basize; + txwi_n->MIMOps = mimops; + if (mpdu_density) + txwi_n->MpduDensity = mpdu_density; +#endif /* DOT11_N_SUPPORT */ + + +#ifdef MCS_LUT_SUPPORT + txwi_n->lut_en = lut_enable; +#endif /* MCS_LUT_SUPPORT */ + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + struct _TXWI_OMAC *txwi_o = (struct _TXWI_OMAC *)pTxWI; + + txwi_o->txop = IFS_HTTXOP; + txwi_o->BW = bw; + txwi_o->ShortGI = sgi; + txwi_o->STBC = stbc; + txwi_o->MCS = mcs; + txwi_o->PHYMODE = phy_mode; + txwi_o->PacketId = pkt_id; + txwi_o->MPDUtotalByteCnt = pTxBlk->MpduHeaderLen + pTxBlk->SrcBufLen; + txwi_o->ACK = TX_BLK_TEST_FLAG(pTxBlk, fTX_bAckRequired); +#ifdef WFA_VHT_PF + if (pAd->force_noack == TRUE) + txwi_o->ACK = 0; +#endif /* WFA_VHT_PF */ + +#ifdef DOT11_N_SUPPORT + txwi_o->AMPDU = ampdu; + if (basize) + txwi_o->BAWinSize = basize; + txwi_o->MIMOps = mimops; + if (mpdu_density) + txwi_o->MpduDensity = mpdu_density; +#endif /* DOT11_N_SUPPORT */ + + } +#endif /* RTMP_MAC */ +} + + +INT rtmp_mac_set_band(RTMP_ADAPTER *pAd, int band) +{ + UINT32 val, band_cfg; + + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &band_cfg); + val = band_cfg & (~0x6); + switch (band) + { + case BAND_5G: + val |= 0x02; + break; + case BAND_24G: + default: + val |= 0x4; + break; + } + + if (val != band_cfg) + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, val); + + return TRUE; +} + + +INT rtmp_mac_set_ctrlch(RTMP_ADAPTER *pAd, UINT8 extch) +{ + UINT32 val, band_cfg; + + RTMP_IO_READ32(pAd, TX_BAND_CFG, &band_cfg); + val = band_cfg & (~0x1); + switch (extch) + { + case EXTCHA_ABOVE: + val &= (~0x1); + break; + case EXTCHA_BELOW: + val |= (0x1); + break; + case EXTCHA_NONE: + val &= (~0x1); + break; + } + + if (val != band_cfg) + RTMP_IO_WRITE32(pAd, TX_BAND_CFG, val); + + return TRUE; +} + + +INT rtmp_mac_set_mmps(RTMP_ADAPTER *pAd, INT ReduceCorePower) +{ + UINT32 mac_val, org_val; + + RTMP_IO_READ32(pAd, 0x1210, &org_val); + mac_val = org_val; + if (ReduceCorePower) + mac_val |= 0x09; + else + mac_val &= ~0x09; + + if (mac_val != org_val) + RTMP_IO_WRITE32(pAd, 0x1210, mac_val); + + return TRUE; +} + + +#define BCN_TBTT_OFFSET 64 /*defer 64 us*/ +VOID ReSyncBeaconTime(RTMP_ADAPTER *pAd) +{ + UINT32 Offset; + BCN_TIME_CFG_STRUC csr; + + Offset = (pAd->TbttTickCount) % (BCN_TBTT_OFFSET); + pAd->TbttTickCount++; + + /* + The updated BeaconInterval Value will affect Beacon Interval after two TBTT + beacasue the original BeaconInterval had been loaded into next TBTT_TIMER + */ + if (Offset == (BCN_TBTT_OFFSET-2)) + { + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + + /* ASIC register in units of 1/16 TU = 64us*/ + csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod << 4) - 1 ; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); + } + else if (Offset == (BCN_TBTT_OFFSET-1)) + { + RTMP_IO_READ32(pAd, BCN_TIME_CFG, &csr.word); + csr.field.BeaconInterval = (pAd->CommonCfg.BeaconPeriod) << 4; + RTMP_IO_WRITE32(pAd, BCN_TIME_CFG, csr.word); + } +} + + +VOID rtmp_mac_bcn_buf_init(IN RTMP_ADAPTER *pAd, BOOLEAN bHardReset) +{ + int idx, tb_size; + RTMP_CHIP_CAP *pChipCap = &pAd->chipCap; + + + for (idx = 0; idx < pChipCap->BcnMaxHwNum; idx++) + pAd->BeaconOffset[idx] = pChipCap->BcnBase[idx]; + + DBGPRINT(RT_DEBUG_TRACE, ("< Beacon Information: >\n")); + DBGPRINT(RT_DEBUG_TRACE, ("\tFlgIsSupSpecBcnBuf = %s\n", pChipCap->FlgIsSupSpecBcnBuf ? "TRUE" : "FALSE")); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnMaxHwNum = %d\n", pChipCap->BcnMaxHwNum)); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnMaxNum = %d\n", pChipCap->BcnMaxNum)); + DBGPRINT(RT_DEBUG_TRACE, ("\tBcnMaxHwSize = 0x%x\n", pChipCap->BcnMaxHwSize)); + DBGPRINT(RT_DEBUG_TRACE, ("\tWcidHwRsvNum = %d\n", pChipCap->WcidHwRsvNum)); + for (idx = 0; idx < pChipCap->BcnMaxHwNum; idx++) { + DBGPRINT(RT_DEBUG_TRACE, ("\t\tBcnBase[%d] = 0x%x, pAd->BeaconOffset[%d]=0x%x\n", + idx, pChipCap->BcnBase[idx], idx, pAd->BeaconOffset[idx])); + } + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + { + RTMP_REG_PAIR bcn_legacy_reg_tb[] = { +#if defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x200) + {BCN_OFFSET0, 0xf8f0e8e0}, + {BCN_OFFSET1, 0x6f77d0c8}, +#elif defined(HW_BEACON_OFFSET) && (HW_BEACON_OFFSET == 0x100) + {BCN_OFFSET0, 0xece8e4e0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */ + {BCN_OFFSET1, 0xfcf8f4f0}, /* 0x3800, 0x3A00, 0x3C00, 0x3E00, 512B for each beacon */ +#endif /* HW_BEACON_OFFSET */ + }; + + tb_size = (sizeof(bcn_legacy_reg_tb) / sizeof(RTMP_REG_PAIR)); + for (idx = 0; idx < tb_size; idx++) + { + RTMP_IO_WRITE32(pAd, (USHORT)bcn_legacy_reg_tb[idx].Register, + bcn_legacy_reg_tb[idx].Value); + } + } + } +#endif /* RTMP_MAC */ + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + RTMP_REG_PAIR bcn_mac_reg_tb[] = { + {RLT_BCN_OFFSET0, 0x18100800}, + {RLT_BCN_OFFSET1, 0x38302820}, + {RLT_BCN_OFFSET2, 0x58504840}, + {RLT_BCN_OFFSET3, 0x78706860}, + }; + + tb_size = (sizeof(bcn_mac_reg_tb) / sizeof(RTMP_REG_PAIR)); + for (idx = 0; idx < tb_size; idx ++) + { + RTMP_IO_WRITE32(pAd, (USHORT)bcn_mac_reg_tb[idx].Register, + bcn_mac_reg_tb[idx].Value); + } + } +#endif /* RLT_MAC */ + + /* It isn't necessary to clear this space when not hard reset. */ + if (bHardReset == TRUE) + { + /* clear all on-chip BEACON frame space */ +#ifdef CONFIG_AP_SUPPORT + INT i, apidx; + for (apidx = 0; apidx < HW_BEACON_MAX_COUNT(pAd); apidx++) + { + if (pAd->BeaconOffset[apidx] > 0) { + // TODO: shiang-6590, if we didn't define MBSS_SUPPORT, the pAd->BeaconOffset[x] may set as 0 when chipCap.BcnMaxHwNum != HW_BEACON_MAX_COUNT + for (i = 0; i < HW_BEACON_OFFSET; i+=4) + RTMP_CHIP_UPDATE_BEACON(pAd, pAd->BeaconOffset[apidx] + i, 0x00, 4); + + } + } +#endif /* CONFIG_AP_SUPPORT */ + } + +} + + +INT rtmp_mac_pbf_init(RTMP_ADAPTER *pAd) +{ + INT idx, tb_size = 0; + RTMP_REG_PAIR *pbf_regs = NULL; +#ifdef RLT_MAC + RTMP_REG_PAIR rlt_pbf_regs[]={ + {TX_MAX_PCNT, 0xefef3f1f}, + {RX_MAX_PCNT, 0xfebf}, + }; +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + RTMP_REG_PAIR rtmp_pbf_regs[]={ +#ifdef INF_AMAZON_SE + /* + iverson modify for usb issue, 2008/09/19 + 6F + 6F < total page count FE + so that RX doesn't occupy TX's buffer space when WMM congestion. + */ + {PBF_MAX_PCNT, 0x1F3F6F6F}, +#else + {PBF_MAX_PCNT, 0x1F3FBF9F}, /* 0x1F3f7f9f}, Jan, 2006/04/20 */ +#endif /* INF_AMAZON_SE */ + }; +#endif /* RTMP_MAC */ + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) + { + pbf_regs = &rlt_pbf_regs[0]; + tb_size = (sizeof(rlt_pbf_regs) / sizeof(RTMP_REG_PAIR)); + } +#endif /* RLT_MAC */ + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + pbf_regs = &rtmp_pbf_regs[0]; + tb_size = (sizeof(rtmp_pbf_regs) / sizeof(RTMP_REG_PAIR)); + } +#endif /* RTMP_MAC */ + + if ((pbf_regs != NULL) && (tb_size > 0)) + { + for (idx = 0; idx < tb_size; idx++) { + RTMP_IO_WRITE32(pAd, pbf_regs->Register, pbf_regs->Value); + pbf_regs++; + } + } + return TRUE; +} + + +INT rtmp_hw_tb_init(RTMP_ADAPTER *pAd, BOOLEAN bHardReset) +{ + + /* + 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) + { + USHORT KeyIdx; + UINT32 wcid_attr_base = 0, wcid_attr_size = 0, share_key_mode_base = 0; + +#ifdef RLT_MAC + if (pAd->chipCap.hif_type == HIF_RLT) { + wcid_attr_base = RLT_MAC_WCID_ATTRIBUTE_BASE; + wcid_attr_size = RLT_HW_WCID_ATTRI_SIZE; + share_key_mode_base = RLT_SHARED_KEY_MODE_BASE; + } +#endif /* RLT_MAC */ +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) { + wcid_attr_base = MAC_WCID_ATTRIBUTE_BASE; + wcid_attr_size = HW_WCID_ATTRI_SIZE; + share_key_mode_base = SHARED_KEY_MODE_BASE; + } +#endif /* RTMP_MAC */ + + for (KeyIdx = 0; KeyIdx < 4; KeyIdx++) + { + RTMP_IO_WRITE32(pAd, share_key_mode_base + 4*KeyIdx, 0); + } + + /* Clear all pairwise key table when initial*/ + for (KeyIdx = 0; KeyIdx < 256; KeyIdx++) + { + RTMP_IO_WRITE32(pAd, wcid_attr_base + (KeyIdx * wcid_attr_size), 1); + } + } + + return TRUE; +} + + +INT rtmp_mac_sys_reset(RTMP_ADAPTER *pAd, BOOLEAN bHardReset) +{ + UINT32 mac_val; + + + DBGPRINT(RT_DEBUG_TRACE, ("%s():MACVersion[Ver:Rev=0x%08x]\n", + __FUNCTION__, pAd->MACVersion)); + + +#ifdef RTMP_MAC_PCI + if (bHardReset == TRUE) + { + mac_val = 0x3; + } + else + mac_val = 0x1; +#endif /* RTMP_MAC_PCI */ + + // TODO: shiang-usw, shall we add some delay here?? + + return TRUE; +} + + +/* + ASIC register initialization sets +*/ +RTMP_REG_PAIR MACRegTable[] = { + {LEGACY_BASIC_RATE, 0x0000013f}, /* Basic rate set bitmap*/ + {HT_BASIC_RATE, 0x00008003}, /* Basic HT rate set , 20M, MCS=3, MM. Format is the same as in TXWI.*/ + {MAC_SYS_CTRL, 0x00}, /* 0x1004, , default Disable RX*/ + {RX_FILTR_CFG, 0x17f97}, /*0x1400 , RX filter control, */ + {BKOFF_SLOT_CFG, 0x209}, /* default set short slot time, CC_DELAY_TIME should be 2 */ + {TX_SW_CFG1, 0x80606}, /* Gary,2006-08-23 */ + {TX_LINK_CFG, 0x1020}, /* Gary,2006-08-23 */ + /*{TX_TIMEOUT_CFG, 0x00182090}, CCK has some problem. So increase timieout value. 2006-10-09 MArvek RT*/ + {TX_TIMEOUT_CFG, 0x000a2090}, /* CCK has some problem. So increase timieout value. 2006-10-09 MArvek RT , Modify for 2860E ,2007-08-01*/ + + // TODO: shiang-usw, why MT7601 don't need to set this register?? + {LED_CFG, 0x7f031e46}, /* Gary, 2006-08-23*/ + + /*{TX_RTY_CFG, 0x6bb80408}, Jan, 2006/11/16*/ +/* WMM_ACM_SUPPORT*/ +/* {TX_RTY_CFG, 0x6bb80101}, sample*/ + {TX_RTY_CFG, 0x47d01f0f}, /* Jan, 2006/11/16, Set TxWI->ACK =0 in Probe Rsp Modify for 2860E ,2007-08-03*/ + + {AUTO_RSP_CFG, 0x00000013}, /* Initial Auto_Responder, because QA will turn off Auto-Responder*/ + {CCK_PROT_CFG, 0x05740003 /*0x01740003*/}, /* Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. */ + {OFDM_PROT_CFG, 0x05740003 /*0x01740003*/}, /* Initial Auto_Responder, because QA will turn off Auto-Responder. And RTS threshold is enabled. */ + + + {GF20_PROT_CFG, 0x01744004}, /* set 19:18 --> Short NAV for MIMO PS*/ + {GF40_PROT_CFG, 0x03F44084}, + {MM20_PROT_CFG, 0x01744004}, + +#ifdef RTMP_MAC_PCI + {MM40_PROT_CFG, 0x03F54084}, +#endif /* RTMP_MAC_PCI */ + + {TXOP_CTRL_CFG, 0x0000583f, /*0x0000243f*/ /*0x000024bf*/}, /*Extension channel backoff.*/ + {TX_RTS_CFG, 0x00092b20}, + + {EXP_ACK_TIME, 0x002400ca}, /* default value */ + {TXOP_HLDR_ET, 0x00000002}, + + /* Jerry comments 2008/01/16: we use SIFS = 10us in CCK defaultly, but it seems that 10us + is too small for INTEL 2200bg card, so in MBSS mode, the delta time between beacon0 + and beacon1 is SIFS (10us), so if INTEL 2200bg card connects to BSS0, the ping + will always lost. So we change the SIFS of CCK from 10us to 16us. */ + {XIFS_TIME_CFG, 0x33a41010}, +}; + +#ifdef RTMP_MAC +RTMP_REG_PAIR MACRegTable_RTMP[] = { + {MAX_LEN_CFG, MAX_AGGREGATION_SIZE | 0x00001000}, /* 0x3018, MAX frame length. Max PSDU = 16kbytes.*/ + {PWR_PIN_CFG, 0x3}, /* patch for 2880-E*/ + /*{TX_SW_CFG0, 0x40a06}, Gary,2006-08-23 */ + {TX_SW_CFG0, 0x0}, /* Gary,2008-05-21 for CWC test */ +}; +#endif /* RTMP_MAC */ + +#ifdef CONFIG_AP_SUPPORT +RTMP_REG_PAIR APMACRegTable[] = { + {WMM_AIFSN_CFG, 0x00001173}, + {WMM_CWMIN_CFG, 0x00002344}, + {WMM_CWMAX_CFG, 0x000034a6}, + {WMM_TXOP0_CFG, 0x00100020}, + {WMM_TXOP1_CFG, 0x002F0038}, + {TBTT_SYNC_CFG, 0x00012000}, +#ifdef STREAM_MODE_SUPPORT + {TX_CHAIN_ADDR0_L, 0xFFFFFFFF}, /* Broadcast frames are in stream mode*/ + {TX_CHAIN_ADDR0_H, 0x3FFFF}, +#endif /* STREAM_MODE_SUPPORT */ +}; +#endif /* CONFIG_AP_SUPPORT */ + + + +#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 RTMP_MAC +#define NUM_RTMP_MAC_REG_PARAMS (sizeof(MACRegTable_RTMP)/ sizeof(RTMP_REG_PAIR)) +#endif /* RTMP_MAC */ + +INT rtmp_mac_init(RTMP_ADAPTER *pAd) +{ + INT idx; + + for (idx = 0; idx < NUM_MAC_REG_PARMS; idx++) + { + RTMP_IO_WRITE32(pAd, MACRegTable[idx].Register, MACRegTable[idx].Value); + } + +#ifdef RTMP_MAC + if (pAd->chipCap.hif_type == HIF_RTMP) + { + UINT32 reg, val; + + for (idx = 0; idx < NUM_RTMP_MAC_REG_PARAMS; idx++){ + reg = MACRegTable_RTMP[idx].Register; + val = MACRegTable_RTMP[idx].Value; + RTMP_IO_WRITE32(pAd, reg, val); + } + } +#endif /* RTMP_MAC */ + +#ifdef CONFIG_AP_SUPPORT + IF_DEV_CONFIG_OPMODE_ON_AP(pAd) + { + for (idx = 0; idx < NUM_AP_MAC_REG_PARMS; idx++) + { + RTMP_IO_WRITE32(pAd, + APMACRegTable[idx].Register, + APMACRegTable[idx].Value); + } + } +#endif /* CONFIG_AP_SUPPORT */ + + + rtmp_mac_pbf_init(pAd); + + /* re-set specific MAC registers for individual chip */ + if (pAd->chipOps.AsicMacInit != NULL) + pAd->chipOps.AsicMacInit(pAd); + + /* auto-fall back settings */ + AsicAutoFallbackInit(pAd); + + AsicSetMacMaxLen(pAd); + + + return TRUE; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/andes_core.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/andes_core.c new file mode 100644 index 000000000..6b430c071 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/andes_core.c @@ -0,0 +1,891 @@ +/* + *************************************************************************** + * 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: + andes_core.c +*/ +#include "rt_config.h" + +struct cmd_msg *AndesAllocCmdMsg(RTMP_ADAPTER *ad, unsigned int length) +{ + struct cmd_msg *msg = NULL; + RTMP_CHIP_CAP *cap = &ad->chipCap; + struct MCU_CTRL *ctl = &ad->MCUCtrl; + PNDIS_PACKET net_pkt = NULL; + INT32 AllocateSize = cap->cmd_header_len + length + cap->cmd_padding_len; + +#ifdef RTMP_SDIO_SUPPORT + if (AllocateSize >= ad->BlockSize) + AllocateSize = (AllocateSize + ((-AllocateSize) & (ad->BlockSize - 1))); +#endif + + net_pkt = RTMP_AllocateFragPacketBuffer(ad, AllocateSize); + + if (!net_pkt) { + DBGPRINT(RT_DEBUG_ERROR, ("can not allocate net_pkt\n")); + goto error0; + } + + OS_PKT_RESERVE(net_pkt, cap->cmd_header_len); + + os_alloc_mem(NULL, (PUCHAR *)&msg, sizeof(*msg)); + + if (!msg) { + DBGPRINT(RT_DEBUG_ERROR, ("can not allocate cmd msg\n")); + goto error1; + } + + CMD_MSG_CB(net_pkt)->msg = msg; + + memset(msg, 0x00, sizeof(*msg)); + + + msg->priv = (void *)ad; + msg->net_pkt = net_pkt; + + ctl->alloc_cmd_msg++; + + return msg; + + os_free_mem(NULL, msg); +error1: + RTMPFreeNdisPacket(ad, net_pkt); +error0: + return NULL; +} + + +VOID AndesInitCmdMsg(struct cmd_msg *msg, UINT16 pq_id, UINT8 cmd_type, UINT8 set_query, UINT8 ExtCmdType, BOOLEAN need_wait, UINT16 timeout, BOOLEAN need_retransmit, BOOLEAN need_rsp, UINT16 rsp_payload_len, char *rsp_payload, MSG_RSP_HANDLER rsp_handler) +{ + msg->pq_id = pq_id; + msg->cmd_type = cmd_type; + msg->set_query = set_query; + msg->ext_cmd_type = ExtCmdType; + msg->need_wait= need_wait; + msg->timeout = timeout; + + if (need_wait) { + RTMP_OS_INIT_COMPLETION(&msg->ack_done); + } + + msg->need_retransmit = 0; + + msg->retransmit_times = 0; + + msg->need_rsp = need_rsp; + msg->rsp_payload_len = rsp_payload_len; + msg->rsp_payload = rsp_payload; + msg->rsp_handler = rsp_handler; + +#ifdef RTMP_SDIO_SUPPORT + RTMP_OS_INIT_COMPLETION(&msg->tx_sdio_done); +#endif +} + + +VOID AndesAppendCmdMsg(struct cmd_msg *msg, char *data, unsigned int len) +{ + PNDIS_PACKET net_pkt = msg->net_pkt; + + if (data) + memcpy(OS_PKT_TAIL_BUF_EXTEND(net_pkt, len), data, len); +} + + +VOID AndesFreeCmdMsg(struct cmd_msg *msg) +{ +#if defined(RTMP_USB_SUPPORT) || defined(RTMP_SDIO_SUPPORT) + PNDIS_PACKET net_pkt = msg->net_pkt; +#endif + RTMP_ADAPTER *ad = (RTMP_ADAPTER *)(msg->priv); + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + if (msg->need_wait) { + RTMP_OS_EXIT_COMPLETION(&msg->ack_done); + } + +#ifdef RTMP_SDIO_SUPPORT + RTMP_OS_EXIT_COMPLETION(&msg->tx_sdio_done); +#endif + + + + os_free_mem(NULL, msg); + +#if defined(RTMP_USB_SUPPORT) || defined(RTMP_SDIO_SUPPORT) + if (net_pkt) + RTMPFreeNdisPacket(ad, net_pkt); +#endif + + ctl->free_cmd_msg++; +} + + + +VOID AndesForceFreeCmdMsg(struct cmd_msg *msg) +{ + PNDIS_PACKET net_pkt = msg->net_pkt; + RTMP_ADAPTER *ad = (RTMP_ADAPTER *)(msg->priv); + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + if (msg->need_wait) { + RTMP_OS_EXIT_COMPLETION(&msg->ack_done); + } + +#ifdef RTMP_SDIO_SUPPORT + RTMP_OS_EXIT_COMPLETION(&msg->tx_sdio_done); +#endif + + + + os_free_mem(NULL, msg); + + if (net_pkt) + RTMPFreeNdisPacket(ad, net_pkt); + + ctl->free_cmd_msg++; +} + + +BOOLEAN IsInbandCmdProcessing(RTMP_ADAPTER *ad) +{ + BOOLEAN ret = 0; + + return ret; +} + + +UCHAR GetCmdRspNum(RTMP_ADAPTER *ad) +{ + UCHAR Num = 0; + + return Num; +} + + +VOID AndesIncErrorCount(struct MCU_CTRL *ctl, enum cmd_msg_error_type type) +{ + if (OS_TEST_BIT(MCU_INIT, &ctl->flags)) { + switch (type) { + case error_tx_kickout_fail: + ctl->tx_kickout_fail_count++; + break; + case error_tx_timeout_fail: + ctl->tx_timeout_fail_count++; + break; + case error_rx_receive_fail: + ctl->rx_receive_fail_count++; + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s:unknown cmd_msg_error_type(%d)\n", __FUNCTION__, type)); + } + } +} + + +static NDIS_SPIN_LOCK *AndesGetSpinLock(struct MCU_CTRL *ctl, DL_LIST *list) +{ + NDIS_SPIN_LOCK *lock = NULL; + + if (list == &ctl->txq) + lock = &ctl->txq_lock; + else if (list == &ctl->rxq) + lock = &ctl->rxq_lock; + else if (list == &ctl->ackq) + lock = &ctl->ackq_lock; + else if (list == &ctl->kickq) + lock = &ctl->kickq_lock; + else if (list == &ctl->tx_doneq) + lock = &ctl->tx_doneq_lock; + else if (list == &ctl->rx_doneq) + lock = &ctl->rx_doneq_lock; +#ifdef RTMP_SDIO_SUPPORT + else if (list == &ctl->txq_sdio) + lock = &ctl->txq_sdio_lock; +#endif + else + DBGPRINT(RT_DEBUG_ERROR, ("%s:illegal list\n", __FUNCTION__)); + + return lock; +} + + +static inline UCHAR AndesGetCmdMsgSeq(RTMP_ADAPTER *ad) +{ + struct MCU_CTRL *ctl = &ad->MCUCtrl; + struct cmd_msg *msg; + unsigned long flags; + UINT8 msg_seq; + + RTMP_SPIN_LOCK_IRQSAVE(&ctl->ackq_lock, &flags); +get_seq: + ctl->cmd_seq >= 0xf ? ctl->cmd_seq = 1 : ctl->cmd_seq++; + DlListForEach(msg, &ctl->ackq, struct cmd_msg, list) { + if (msg->seq == ctl->cmd_seq) { + DBGPRINT(RT_DEBUG_ERROR, ("command(seq: %d) is still running\n", ctl->cmd_seq)); + DBGPRINT(RT_DEBUG_ERROR, ("command response nums = %d\n", GetCmdRspNum(ad))); + goto get_seq; + } + } + msg_seq = ctl->cmd_seq; + RTMP_SPIN_UNLOCK_IRQRESTORE(&ctl->ackq_lock, &flags); + + return msg_seq; +} + + +static VOID _AndesQueueTailCmdMsg(DL_LIST *list, struct cmd_msg *msg, + enum cmd_msg_state state) +{ + msg->state = state; + DlListAddTail(list, &msg->list); +} + + +VOID AndesQueueTailCmdMsg(DL_LIST *list, struct cmd_msg *msg, + enum cmd_msg_state state) +{ + unsigned long flags; + NDIS_SPIN_LOCK *lock; + RTMP_ADAPTER *ad = (RTMP_ADAPTER *)msg->priv; + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + lock = AndesGetSpinLock(ctl, list); + + RTMP_SPIN_LOCK_IRQSAVE(lock, &flags); + _AndesQueueTailCmdMsg(list, msg, state); + RTMP_SPIN_UNLOCK_IRQRESTORE(lock, &flags); +} + + +static VOID _AndesQueueHeadCmdMsg(DL_LIST *list, struct cmd_msg *msg, + enum cmd_msg_state state) +{ + msg->state = state; + DlListAdd(list, &msg->list); +} + + +VOID AndesQueueHeadCmdMsg(DL_LIST *list, struct cmd_msg *msg, + enum cmd_msg_state state) +{ + unsigned long flags; + NDIS_SPIN_LOCK *lock; + RTMP_ADAPTER *ad = (RTMP_ADAPTER *)msg->priv; + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + lock = AndesGetSpinLock(ctl, list); + + RTMP_SPIN_LOCK_IRQSAVE(lock, &flags); + _AndesQueueHeadCmdMsg(list, msg, state); + RTMP_SPIN_UNLOCK_IRQRESTORE(lock, &flags); +} + + +UINT32 AndesQueueLen(struct MCU_CTRL *ctl, DL_LIST *list) +{ + UINT32 qlen; + unsigned long flags; + NDIS_SPIN_LOCK *lock; + + lock = AndesGetSpinLock(ctl, list); + + RTMP_SPIN_LOCK_IRQSAVE(lock, &flags); + qlen = DlListLen(list); + RTMP_SPIN_UNLOCK_IRQRESTORE(lock, &flags); + + return qlen; +} + +/*Nobody uses it currently*/ + +static VOID AndesQueueInit(struct MCU_CTRL *ctl, DL_LIST *list) +{ + + unsigned long flags; + NDIS_SPIN_LOCK *lock; + + lock = AndesGetSpinLock(ctl, list); + + RTMP_SPIN_LOCK_IRQSAVE(lock, &flags); + DlListInit(list); + RTMP_SPIN_UNLOCK_IRQRESTORE(lock, &flags); +} + + +VOID _AndesUnlinkCmdMsg(struct cmd_msg *msg, DL_LIST *list) +{ + if (!msg) + return; + + DlListDel(&msg->list); +} + + +VOID AndesUnlinkCmdMsg(struct cmd_msg *msg, DL_LIST *list) +{ + unsigned long flags; + NDIS_SPIN_LOCK *lock; + RTMP_ADAPTER *ad = (RTMP_ADAPTER *)msg->priv; + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + lock = AndesGetSpinLock(ctl, list); + + RTMP_SPIN_LOCK_IRQSAVE(lock, &flags); + _AndesUnlinkCmdMsg(msg, list); + RTMP_SPIN_UNLOCK_IRQRESTORE(lock, &flags); +} + + +static struct cmd_msg *_AndesDequeueCmdMsg(DL_LIST *list) +{ + struct cmd_msg *msg; + + msg = DlListFirst(list, struct cmd_msg, list); + + _AndesUnlinkCmdMsg(msg, list); + + return msg; +} + + +struct cmd_msg *AndesDequeueCmdMsg(struct MCU_CTRL *ctl, DL_LIST *list) +{ + unsigned long flags; + struct cmd_msg *msg; + NDIS_SPIN_LOCK *lock; + + lock = AndesGetSpinLock(ctl, list); + + RTMP_SPIN_LOCK_IRQSAVE(lock, &flags); + msg = _AndesDequeueCmdMsg(list); + RTMP_SPIN_UNLOCK_IRQRESTORE(lock, &flags); + + return msg; +} + + +#ifdef RTMP_SDIO_SUPPORT +VOID SdioKickOutCmdMsgComplete(struct cmd_msg *msg) +{ + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv; + struct MCU_CTRL *ctl = &pAd->MCUCtrl; + + if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) + return; + + if (!msg->need_wait) { + AndesUnlinkCmdMsg(msg, &ctl->kickq); + DBGPRINT(RT_DEBUG_INFO, ("%s: msg state = %d\n", __FUNCTION__, msg->state)); + AndesQueueTailCmdMsg(&ctl->tx_doneq, msg, tx_done); + } + else + { + msg->state = wait_ack; + } + + AndesBhSchedule(pAd); +} +#endif + +#ifdef RTMP_PCI_SUPPORT +VOID PciKickOutCmdMsgComplete(PNDIS_PACKET net_pkt) +{ + struct cmd_msg *msg =CMD_MSG_CB(net_pkt)->msg; + RTMP_ADAPTER *ad = (RTMP_ADAPTER *)msg->priv; + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) + return; + + if (!msg->need_wait) { + AndesUnlinkCmdMsg(msg, &ctl->kickq); + DBGPRINT(RT_DEBUG_INFO, ("%s: msg state = %d\n", __FUNCTION__, msg->state)); + AndesQueueTailCmdMsg(&ctl->tx_doneq, msg, tx_done); + } else { + if (msg->state != tx_done) + msg->state = wait_ack; + } + + AndesBhSchedule(ad); +} +#endif /* RTMP_PCI_SUPPORT */ + + + + +VOID AndesRxProcessCmdMsg(RTMP_ADAPTER *ad, struct cmd_msg *rx_msg) +{ + RX_BLK RxBlk; +NdisZeroMemory(&RxBlk, sizeof(RxBlk)); +#ifdef MT_MAC + if (ad->chipCap.hif_type == HIF_MT) + { + /*rx_hw_hdr_len = */parse_rx_packet_type(ad, &RxBlk, rx_msg->net_pkt); + } +#endif /* MT_MAC */ + +#ifdef RLT_MAC + if (ad->chipCap.hif_type == HIF_RLT) + { + AndesRltRxProcessCmdMsg(ad, rx_msg); + } +#endif /* RLT_MAC */ + +} + + +VOID AndesCmdMsgBh(unsigned long param) +{ + RTMP_ADAPTER *ad = (RTMP_ADAPTER *)param; + struct MCU_CTRL *ctl = &ad->MCUCtrl; + struct cmd_msg *msg = NULL; + + while ((msg = AndesDequeueCmdMsg(ctl, &ctl->rx_doneq))) { + switch (msg->state) { + case rx_done: + AndesRxProcessCmdMsg(ad, msg); + AndesFreeCmdMsg(msg); + break; + case rx_receive_fail: + AndesFreeCmdMsg(msg); + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("unknow msg state(%d)\n", msg->state)); + AndesFreeCmdMsg(msg); + break; + } + } + + while ((msg = AndesDequeueCmdMsg(ctl, &ctl->tx_doneq))) { + switch (msg->state) { + case tx_done: + case tx_kickout_fail: + case tx_timeout_fail: + AndesFreeCmdMsg(msg); + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("unknow msg state(%d)\n", msg->state)); + AndesFreeCmdMsg(msg); + break; + } + } + + if (OS_TEST_BIT(MCU_INIT, &ctl->flags)) { + AndesBhSchedule(ad); + } +} + + + + +VOID AndesBhSchedule(RTMP_ADAPTER *ad) +{ + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) + return; + + if (((AndesQueueLen(ctl, &ctl->rx_doneq) > 0) + || (AndesQueueLen(ctl, &ctl->tx_doneq) > 0)) + && OS_TEST_BIT(MCU_INIT, &ctl->flags)) { +#ifndef WORKQUEUE_BH + RTMP_NET_TASK_DATA_ASSIGN(&ctl->cmd_msg_task, (unsigned long)(ad)); + RTMP_OS_TASKLET_SCHE(&ctl->cmd_msg_task); +#else + tasklet_hi_schedule(&ctl->cmd_msg_task); +#endif + } +} + + +VOID AndesCleanupCmdMsg(RTMP_ADAPTER *ad, DL_LIST *list) +{ + unsigned long flags; + struct cmd_msg *msg, *msg_tmp; + NDIS_SPIN_LOCK *lock; + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + lock = AndesGetSpinLock(ctl, list); + + RTMP_SPIN_LOCK_IRQSAVE(lock, &flags); + DlListForEachSafe(msg, msg_tmp, list, struct cmd_msg, list) { + _AndesUnlinkCmdMsg(msg, list); + AndesFreeCmdMsg(msg); + } + DlListInit(list); + RTMP_SPIN_UNLOCK_IRQRESTORE(lock, &flags); +} + + +#ifdef RTMP_PCI_SUPPORT +static VOID AndesCtrlPciInit(RTMP_ADAPTER *ad) +{ + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + RTMP_CLEAR_FLAG(ad, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD); + ctl->cmd_seq = 0; +#ifndef WORKQUEUE_BH + RTMP_OS_TASKLET_INIT(ad, &ctl->cmd_msg_task, AndesCmdMsgBh, (unsigned long)ad); +#else + tasklet_init(&ctl->cmd_msg_task, AndesCmdMsgBh, (unsigned long)ad); +#endif + NdisAllocateSpinLock(ad, &ctl->txq_lock); + AndesQueueInit(ctl, &ctl->txq); + NdisAllocateSpinLock(ad, &ctl->rxq_lock); + AndesQueueInit(ctl, &ctl->rxq); + NdisAllocateSpinLock(ad, &ctl->ackq_lock); + AndesQueueInit(ctl, &ctl->ackq); + NdisAllocateSpinLock(ad, &ctl->kickq_lock); + AndesQueueInit(ctl, &ctl->kickq); + NdisAllocateSpinLock(ad, &ctl->tx_doneq_lock); + AndesQueueInit(ctl, &ctl->tx_doneq); + NdisAllocateSpinLock(ad, &ctl->rx_doneq_lock); + AndesQueueInit(ctl, &ctl->rx_doneq); + ctl->tx_kickout_fail_count = 0; + ctl->tx_timeout_fail_count = 0; + ctl->rx_receive_fail_count = 0; + ctl->alloc_cmd_msg = 0; + ctl->free_cmd_msg = 0; + OS_SET_BIT(MCU_INIT, &ctl->flags); + ctl->ad = ad; +} +#endif + + + + +#ifdef RTMP_SDIO_SUPPORT +static VOID AndesCtrlSdioInit(RTMP_ADAPTER *pAd) +{ + struct MCU_CTRL *ctl = &pAd->MCUCtrl; + int ret = 0; + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD); + ctl->cmd_seq = 0; + RTMP_OS_TASKLET_INIT(pAd, &ctl->cmd_msg_task, AndesCmdMsgBh, (unsigned long)pAd); + NdisAllocateSpinLock(pAd, &ctl->txq_lock); + AndesQueueInit(ctl, &ctl->txq); + NdisAllocateSpinLock(pAd, &ctl->rxq_lock); + AndesQueueInit(ctl, &ctl->rxq); + NdisAllocateSpinLock(pAd, &ctl->ackq_lock); + AndesQueueInit(ctl, &ctl->ackq); + NdisAllocateSpinLock(pAd, &ctl->kickq_lock); + AndesQueueInit(ctl, &ctl->kickq); + NdisAllocateSpinLock(pAd, &ctl->tx_doneq_lock); + AndesQueueInit(ctl, &ctl->tx_doneq); + NdisAllocateSpinLock(pAd, &ctl->rx_doneq_lock); + AndesQueueInit(ctl, &ctl->rx_doneq); + NdisAllocateSpinLock(pAd, &ctl->txq_sdio_lock); + AndesQueueInit(ctl, &ctl->txq_sdio); + ctl->tx_kickout_fail_count = 0; + ctl->tx_timeout_fail_count = 0; + ctl->rx_receive_fail_count = 0; + ctl->alloc_cmd_msg = 0; + ctl->free_cmd_msg = 0; + ctl->ad = pAd; + OS_SET_BIT(MCU_INIT, &ctl->flags); +} +#endif + + +VOID AndesCtrlInit(RTMP_ADAPTER *pAd) +{ + struct MCU_CTRL *ctl = &pAd->MCUCtrl; + + if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) { +#ifdef RTMP_PCI_SUPPORT + AndesCtrlPciInit(pAd); +#endif + + +#ifdef RTMP_SDIO_SUPPORT + AndesCtrlSdioInit(pAd); +#endif + } + + ctl->power_on = FALSE; + ctl->dpd_on = FALSE; + ctl->RxStream0 = 0; + ctl->RxStream1 = 0; +} + + + + +#ifdef RTMP_PCI_SUPPORT +static VOID AndesCtrlPciExit(RTMP_ADAPTER *ad) +{ + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + RTMP_CLEAR_FLAG(ad, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD); + OS_CLEAR_BIT(MCU_INIT, &ctl->flags); + RTMP_OS_TASKLET_KILL(&ctl->cmd_msg_task); + AndesCleanupCmdMsg(ad, &ctl->txq); + NdisFreeSpinLock(&ctl->txq_lock); + AndesCleanupCmdMsg(ad, &ctl->ackq); + NdisFreeSpinLock(&ctl->ackq_lock); + AndesCleanupCmdMsg(ad, &ctl->rxq); + NdisFreeSpinLock(&ctl->rxq_lock); + AndesCleanupCmdMsg(ad, &ctl->kickq); + NdisFreeSpinLock(&ctl->kickq_lock); + AndesCleanupCmdMsg(ad, &ctl->tx_doneq); + NdisFreeSpinLock(&ctl->tx_doneq_lock); + AndesCleanupCmdMsg(ad, &ctl->rx_doneq); + NdisFreeSpinLock(&ctl->rx_doneq_lock); + DBGPRINT(RT_DEBUG_OFF, ("tx_kickout_fail_count = %ld\n", ctl->tx_kickout_fail_count)); + DBGPRINT(RT_DEBUG_OFF, ("tx_timeout_fail_count = %ld\n", ctl->tx_timeout_fail_count)); + DBGPRINT(RT_DEBUG_OFF, ("rx_receive_fail_count = %ld\n", ctl->rx_receive_fail_count)); + DBGPRINT(RT_DEBUG_OFF, ("alloc_cmd_msg = %ld\n", ctl->alloc_cmd_msg)); + DBGPRINT(RT_DEBUG_OFF, ("free_cmd_msg = %ld\n", ctl->free_cmd_msg)); +} +#endif + + +#ifdef RTMP_SDIO_SUPPORT +static VOID AndesCtrlSdioExit(RTMP_ADAPTER *pAd) +{ + struct MCU_CTRL *ctl = &pAd->MCUCtrl; + unsigned long flags; + INT32 Ret; + + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD); + OS_CLEAR_BIT(MCU_INIT, &ctl->flags); + RTMP_OS_TASKLET_KILL(&ctl->cmd_msg_task); + AndesCleanupCmdMsg(pAd, &ctl->txq); + NdisFreeSpinLock(&ctl->txq_lock); + AndesCleanupCmdMsg(pAd, &ctl->ackq); + NdisFreeSpinLock(&ctl->ackq_lock); + AndesCleanupCmdMsg(pAd, &ctl->rxq); + NdisFreeSpinLock(&ctl->rxq_lock); + AndesCleanupCmdMsg(pAd, &ctl->kickq); + NdisFreeSpinLock(&ctl->kickq_lock); + AndesCleanupCmdMsg(pAd, &ctl->tx_doneq); + NdisFreeSpinLock(&ctl->tx_doneq_lock); + AndesCleanupCmdMsg(pAd, &ctl->rx_doneq); + NdisFreeSpinLock(&ctl->rx_doneq_lock); + AndesCleanupCmdMsg(pAd, &ctl->txq_sdio); + NdisFreeSpinLock(&ctl->txq_sdio_lock); + DBGPRINT(RT_DEBUG_OFF, ("tx_kickout_fail_count = %ld\n", ctl->tx_kickout_fail_count)); + DBGPRINT(RT_DEBUG_OFF, ("tx_timeout_fail_count = %ld\n", ctl->tx_timeout_fail_count)); + DBGPRINT(RT_DEBUG_OFF, ("rx_receive_fail_count = %ld\n", ctl->rx_receive_fail_count)); + DBGPRINT(RT_DEBUG_OFF, ("alloc_cmd_msg = %ld\n", ctl->alloc_cmd_msg)); + DBGPRINT(RT_DEBUG_OFF, ("free_cmd_msg = %ld\n", ctl->free_cmd_msg)); +} +#endif + +VOID AndesCtrlExit(RTMP_ADAPTER *pAd) +{ + struct MCU_CTRL *ctl = &pAd->MCUCtrl; + + if (OS_TEST_BIT(MCU_INIT, &ctl->flags)) { +#ifdef RTMP_PCI_SUPPORT + AndesCtrlPciExit(pAd); +#endif + + +#ifdef RTMP_SDIO_SUPPORT + AndesCtrlSdioExit(pAd); +#endif + } + + ctl->Stage = FW_NO_INIT; + ctl->power_on = FALSE; + ctl->dpd_on = FALSE; +} + + +static INT32 AndesDequeueAndKickOutCmdMsgs(RTMP_ADAPTER *ad) +{ + struct cmd_msg *msg = NULL; + PNDIS_PACKET net_pkt = NULL; + struct MCU_CTRL *ctl = &ad->MCUCtrl; + int ret = NDIS_STATUS_SUCCESS; + + while ((msg = AndesDequeueCmdMsg(ctl, &ctl->txq)) != NULL) { + if (!RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD) + || RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_NIC_NOT_EXIST) + || RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_SUSPEND)) { + if (!msg->need_wait) + AndesForceFreeCmdMsg(msg); + continue; + } + + net_pkt = msg->net_pkt; + + if (msg->state != tx_retransmit) { + if (msg->need_wait) + msg->seq = AndesGetCmdMsgSeq(ad); + else + msg->seq = 0; + + if (ad->chipOps.andes_fill_cmd_header != NULL) + ad->chipOps.andes_fill_cmd_header(msg, net_pkt); + } + + +#ifdef RTMP_PCI_SUPPORT + if (ad->chipOps.pci_kick_out_cmd_msg != NULL) + ret = ad->chipOps.pci_kick_out_cmd_msg(ad, msg); +#endif + +#ifdef RTMP_SDIO_SUPPORT + if (ad->chipOps.sdio_kick_out_cmd_msg != NULL) + ret = ad->chipOps.sdio_kick_out_cmd_msg(ad, msg); +#endif + + if (ret) { + DBGPRINT(RT_DEBUG_ERROR, ("[03] kick out msg fail\n")); + if (ret == NDIS_STATUS_FAILURE) + AndesForceFreeCmdMsg(msg); + break; + } + } + + AndesBhSchedule(ad); + + return ret; +} + + +#ifdef RTMP_SDIO_SUPPORT +INT32 AndesWaitForSdioCompleteTimeout(struct cmd_msg *msg, long timeout) +{ + int ret = 0; + long expire = timeout ? RTMPMsecsToJiffies(timeout) : RTMPMsecsToJiffies(CMD_MSG_TIMEOUT); + + ret = RTMP_OS_WAIT_FOR_COMPLETION_TIMEOUT(&msg->tx_sdio_done, expire); + + return ret; +} +#endif + +static INT32 AndesWaitForCompleteTimeout(struct cmd_msg *msg, long timeout) +{ + int ret = 0; + long expire = timeout ? RTMPMsecsToJiffies(timeout) : RTMPMsecsToJiffies(CMD_MSG_TIMEOUT); + + ret = RTMP_OS_WAIT_FOR_COMPLETION_TIMEOUT(&msg->ack_done, expire); + + return ret; +} + + +INT32 AndesSendCmdMsg(PRTMP_ADAPTER ad, struct cmd_msg *msg) +{ + struct MCU_CTRL *ctl = &ad->MCUCtrl; + int ret = 0; + BOOLEAN need_wait = msg->need_wait; + + if(in_interrupt() && need_wait) + { + DBGPRINT(RT_DEBUG_ERROR, ("BUG: %s is called from invalid context\n", __FUNCTION__)); + DBGPRINT(RT_DEBUG_ERROR, ("%s: Command type = %x, Extension command type = %x\n", __FUNCTION__, msg->cmd_type, msg->ext_cmd_type)); + AndesForceFreeCmdMsg(msg); + return NDIS_STATUS_FAILURE; + } + + if (!RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD) + || RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_NIC_NOT_EXIST) + || RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_SUSPEND)) { + + if (!RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD)) + DBGPRINT(RT_DEBUG_ERROR, ("%s: Could not send in band command due to diable fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD\n", __FUNCTION__)); + else if (RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_NIC_NOT_EXIST)) + DBGPRINT(RT_DEBUG_ERROR, ("%s: Could not send in band command due to fRTMP_ADAPTER_NIC_NOT_EXIST\n", __FUNCTION__)); + else if (RTMP_TEST_FLAG(ad, fRTMP_ADAPTER_SUSPEND)) + DBGPRINT(RT_DEBUG_ERROR, ("%s: Could not send in band command due to fRTMP_ADAPTER_SUSPEND\n", __FUNCTION__)); + + AndesForceFreeCmdMsg(msg); + + return NDIS_STATUS_FAILURE; + } + + AndesQueueTailCmdMsg(&ctl->txq, msg, tx_start); + +retransmit: + AndesDequeueAndKickOutCmdMsgs(ad); + + /* Wait for response */ + if (need_wait) { + enum cmd_msg_state state; + if (!AndesWaitForCompleteTimeout(msg, msg->timeout)) { + ret = NDIS_STATUS_FAILURE; + DBGPRINT(RT_DEBUG_ERROR, ("command (%x), ext_cmd_type (%x), timeout(%dms)\n", msg->cmd_type, msg->ext_cmd_type, CMD_MSG_TIMEOUT)); + DBGPRINT(RT_DEBUG_ERROR, ("txq qlen = %d\n", AndesQueueLen(ctl, &ctl->txq))); + DBGPRINT(RT_DEBUG_ERROR, ("rxq qlen = %d\n", AndesQueueLen(ctl, &ctl->rxq))); + DBGPRINT(RT_DEBUG_ERROR, ("kickq qlen = %d\n", AndesQueueLen(ctl, &ctl->kickq))); + DBGPRINT(RT_DEBUG_ERROR, ("ackq qlen = %d\n", AndesQueueLen(ctl, &ctl->ackq))); + DBGPRINT(RT_DEBUG_ERROR, ("tx_doneq.qlen = %d\n", AndesQueueLen(ctl, &ctl->tx_doneq))); + DBGPRINT(RT_DEBUG_ERROR, ("rx_done qlen = %d\n", AndesQueueLen(ctl, &ctl->rx_doneq))); + if (OS_TEST_BIT(MCU_INIT, &ctl->flags)) { + if (msg->state == wait_cmd_out_and_ack) { + AndesUnlinkCmdMsg(msg, &ctl->ackq); + } else if (msg->state == wait_ack) { + AndesUnlinkCmdMsg(msg, &ctl->ackq); + } + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s: msg state = %d\n", __FUNCTION__, msg->state)); + AndesIncErrorCount(ctl, error_tx_timeout_fail); + state = tx_timeout_fail; + if (msg->retransmit_times > 0) + msg->retransmit_times--; +#ifdef MT_PS + else + { + /* timeout process */ + if ((msg->cmd_type == EXT_CID) && + (msg->ext_cmd_type == EXT_CMD_PS_RETRIEVE_START)) + { + MtPsSendToken(ad, msg->wcid); + } + } +#endif /* MT_PS */ + DBGPRINT(RT_DEBUG_ERROR, ("msg->retransmit_times = %d\n", msg->retransmit_times)); + } else { + if (msg->state == tx_kickout_fail) { + state = tx_kickout_fail; + msg->retransmit_times--; + } else { + + + if (msg->state == wait_cmd_out_and_ack) { + AndesUnlinkCmdMsg(msg, &ctl->ackq); + } else if (msg->state == wait_ack) { + AndesUnlinkCmdMsg(msg, &ctl->ackq); + } + + state = tx_done; + msg->retransmit_times = 0; + } + } + + if (OS_TEST_BIT(MCU_INIT, &ctl->flags)) { + if (msg->need_retransmit && (msg->retransmit_times > 0)) { + RTMP_OS_EXIT_COMPLETION(&msg->ack_done); + RTMP_OS_INIT_COMPLETION(&msg->ack_done); + state = tx_retransmit; + AndesQueueHeadCmdMsg(&ctl->txq, msg, state); + goto retransmit; + } else { + DBGPRINT(RT_DEBUG_INFO, ("%s: msg state = %d\n", __FUNCTION__, state)); + AndesQueueTailCmdMsg(&ctl->tx_doneq, msg, state); + } + } else { + AndesFreeCmdMsg(msg); + } + } + + return ret; +} + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/andes_mt.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/andes_mt.c new file mode 100644 index 000000000..cd3b3c371 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/andes_mt.c @@ -0,0 +1,4324 @@ +/* + *************************************************************************** + * 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: + andes_mt.c +*/ + +#include "rt_config.h" + +#ifdef RTMP_SDIO_SUPPORT +INT32 AndesMTSendCmdMsgToSdio(PRTMP_ADAPTER pAd) +{ + INT32 Ret = 0; + struct MCU_CTRL *ctl = &pAd->MCUCtrl; + PNDIS_PACKET NetPkt = NULL; + struct cmd_msg *msg = NULL; + + while ((msg = AndesDequeueCmdMsg(ctl, &ctl->txq_sdio)) != NULL) { + if (!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD) + || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST) + || RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_SUSPEND)) { + if (!msg->need_wait) + AndesFreeCmdMsg(msg); + continue; + } + + if (AndesQueueLen(ctl, &ctl->ackq) > 0) { + AndesQueueHeadCmdMsg(&ctl->txq_sdio, msg, msg->state); + Ret = NDIS_STATUS_FAILURE; + continue; + } + + NetPkt = msg->net_pkt; + + /* send to SDIO host */ + Ret = MTSDIOCmdTx(pAd, GET_OS_PKT_DATAPTR(NetPkt), + GET_OS_PKT_LEN(NetPkt)); + + if (Ret) + { + msg->state = tx_sdio_fail; + DBGPRINT(RT_DEBUG_ERROR, ("kick out cmd to sdio host fail\n")); + RTMP_OS_COMPLETE(&msg->tx_sdio_done); + break; + } + else + { + msg->state = tx_sdio_ok; + DBGPRINT(RT_DEBUG_TRACE, ("kick out cmd to sdio host ok\n")); + } + + RTMP_OS_COMPLETE(&msg->tx_sdio_done); + } + + return Ret; +} + + +static INT32 AndesMTSdioSubmitCmdMsgToSDIOWorker(PRTMP_ADAPTER pAd, struct cmd_msg *msg) +{ + INT32 Ret = 0; + struct MCU_CTRL *ctl = &pAd->MCUCtrl; + POS_COOKIE pObj = (POS_COOKIE)pAd->OS_Cookie; + + AndesQueueTailCmdMsg(&ctl->txq_sdio, msg, msg->state); + + MTSDIOAddWorkerTaskList(pAd); + queue_work(pObj->SdioWq, &pObj->SdioWork); + + /* Wait for SDIO tx timeout */ + if (!AndesWaitForSdioCompleteTimeout(msg, msg->tx_sdio_timeout)) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Wait for SDIO tx timeout(%d)\n", __FUNCTION__, + msg->tx_sdio_timeout)); + + AndesUnlinkCmdMsg(msg, &ctl->txq_sdio); + Ret = -1; + } + else + { + if (msg->state == tx_sdio_ok) + { + Ret = 0; + } + else + { + Ret = -1; + } + } + + return Ret; +} + + +INT32 AndesMTSdioKickOutCmdMsg(PRTMP_ADAPTER pAd, struct cmd_msg *msg) +{ + struct MCU_CTRL *ctl = &pAd->MCUCtrl; + INT32 Ret = 0; + PNDIS_PACKET net_pkt = msg->net_pkt; + + if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) + return -1; + + if (msg->state != tx_retransmit) { + /* + * append to meet block unit and zero four bytes padding + * when using sdio block mode + */ + memset(OS_PKT_TAIL_BUF_EXTEND(net_pkt, ctl->SDIOPadSize), 0x00, SDIO_END_PADDING); + } + + Ret = AndesMTSdioSubmitCmdMsgToSDIOWorker(pAd, msg); + + if (msg->need_wait) + AndesQueueTailCmdMsg(&ctl->ackq, msg, wait_cmd_out_and_ack); + else + AndesQueueTailCmdMsg(&ctl->kickq, msg, wait_cmd_out); + + if (Ret) { + if (!msg->need_wait) { + AndesUnlinkCmdMsg(msg, &ctl->kickq); + AndesQueueTailCmdMsg(&ctl->tx_doneq, msg, tx_kickout_fail); + AndesIncErrorCount(ctl, error_tx_kickout_fail); + } else { + AndesUnlinkCmdMsg(msg, &ctl->ackq); + msg->state = tx_kickout_fail; + AndesIncErrorCount(ctl, error_tx_kickout_fail); + RTMP_OS_COMPLETE(&msg->ack_done); + } + + DBGPRINT(RT_DEBUG_ERROR, ("%s:submit cmd msg to SDIO host fail(%d)\n", __FUNCTION__, Ret)); + } + + return Ret; +} + + +INT32 AndesMTSdioChkCrc(RTMP_ADAPTER *pAd, UINT32 checksum_len) +{ + + +} + + +UINT16 AndesMTSdioGetCrc(RTMP_ADAPTER *pAd) +{ + + + + +} +#endif + + + +#ifdef RTMP_PCI_SUPPORT +INT32 AndesMTPciKickOutCmdMsg(PRTMP_ADAPTER pAd, struct cmd_msg *msg) +{ + int ret = NDIS_STATUS_SUCCESS; + unsigned long flags = 0; + ULONG FreeNum; + PNDIS_PACKET net_pkt = msg->net_pkt; + UINT32 SwIdx = 0; + UCHAR *pSrcBufVA; + UINT SrcBufLen = 0; + PACKET_INFO PacketInfo; + TXD_STRUC *pTxD; + struct MCU_CTRL *ctl = &pAd->MCUCtrl; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; + UCHAR tx_hw_info[TXD_SIZE]; +#endif + + if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) + return -1; + + FreeNum = GET_CTRLRING_FREENO(pAd); + + if (FreeNum == 0) { + DBGPRINT(RT_DEBUG_WARN, ("%s FreeNum == 0 (TxCpuIdx = %d, TxDmaIdx = %d, TxSwFreeIdx = %d)\n", + __FUNCTION__, pAd->CtrlRing.TxCpuIdx, pAd->CtrlRing.TxDmaIdx, pAd->CtrlRing.TxSwFreeIdx)); + return NDIS_STATUS_FAILURE; + } + + RTMP_SPIN_LOCK_IRQSAVE(&pAd->CtrlRingLock, &flags); + + RTMP_QueryPacketInfo(net_pkt, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + if (pSrcBufVA == NULL) { + RTMP_SPIN_UNLOCK_IRQRESTORE(&pAd->CtrlRingLock, &flags); + return NDIS_STATUS_FAILURE; + } + + SwIdx = pAd->CtrlRing.TxCpuIdx; + +#ifdef RT_BIG_ENDIAN + pDestTxD = (TXD_STRUC *)pAd->CtrlRing.Cell[SwIdx].AllocVa; + NdisMoveMemory(&tx_hw_info[0], (UCHAR *)pDestTxD, TXD_SIZE); + pTxD = (TXD_STRUC *)&tx_hw_info[0]; +#else + pTxD = (TXD_STRUC *)pAd->CtrlRing.Cell[SwIdx].AllocVa; +#endif + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); +#endif /* RT_BIG_ENDIAN */ + + pAd->CtrlRing.Cell[SwIdx].pNdisPacket = net_pkt; + pAd->CtrlRing.Cell[SwIdx].pNextNdisPacket = NULL; + + pAd->CtrlRing.Cell[SwIdx].PacketPa = PCI_MAP_SINGLE(pAd, (pSrcBufVA) , (SrcBufLen), 0, RTMP_PCI_DMA_TODEVICE); + + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 0; + pTxD->SDLen0 = SrcBufLen; + pTxD->SDLen1 = 0; + pTxD->SDPtr0 = pAd->CtrlRing.Cell[SwIdx].PacketPa; + pTxD->Burst = 0; + pTxD->DMADONE = 0; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(SrcBufPA, SrcBufLen); + RTMP_DCACHE_FLUSH(pAd->CtrlRing.Cell[SwIdx].AllocPa, TXD_SIZE); + + /* Increase TX_CTX_IDX, but write to register later.*/ + INC_RING_INDEX(pAd->CtrlRing.TxCpuIdx, MGMT_RING_SIZE); + + if (msg->need_wait) + AndesQueueTailCmdMsg(&ctl->ackq, msg, wait_ack); + else + AndesQueueTailCmdMsg(&ctl->tx_doneq, msg, tx_done); + + if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) { + RTMP_SPIN_UNLOCK_IRQRESTORE(&pAd->CtrlRingLock, &flags); + return -1; + } + + RTMP_IO_WRITE32(pAd, pAd->CtrlRing.hw_cidx_addr, pAd->CtrlRing.TxCpuIdx); + + RTMP_SPIN_UNLOCK_IRQRESTORE(&pAd->CtrlRingLock, &flags); + + return ret; +} +#endif /* RTMP_PCI_SUPPORT */ + +VOID AndesMTFillCmdHeader(struct cmd_msg *msg, PNDIS_PACKET net_pkt) +{ + FW_TXD *fw_txd; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv; + struct MCU_CTRL *Ctl = &pAd->MCUCtrl; + + if ((Ctl->Stage == FW_NO_INIT) || (Ctl->Stage == FW_DOWNLOAD) || (Ctl->Stage == ROM_PATCH_DOWNLOAD)) + fw_txd = (FW_TXD *)OS_PKT_HEAD_BUF_EXTEND(net_pkt, 12); + else if (Ctl->Stage == FW_RUN_TIME) + fw_txd = (FW_TXD *)OS_PKT_HEAD_BUF_EXTEND(net_pkt, sizeof(*fw_txd)); + else + { + DBGPRINT(RT_DEBUG_OFF, ("%s: Unknown Control Stage(%d)\n", __FUNCTION__, + Ctl->Stage)); + return; + } + + fw_txd->fw_txd_0.field.length = GET_OS_PKT_LEN(net_pkt); + fw_txd->fw_txd_0.field.pq_id = msg->pq_id; + fw_txd->fw_txd_1.field.cid = msg->cmd_type; + fw_txd->fw_txd_1.field.pkt_type_id = PKT_ID_CMD; + fw_txd->fw_txd_1.field.set_query = msg->set_query; + fw_txd->fw_txd_1.field.seq_num = msg->seq; + fw_txd->fw_txd_2.field.ext_cid = msg->ext_cmd_type; + + if ((msg->cmd_type == EXT_CID) && ((msg->set_query == CMD_SET) || (msg->set_query == CMD_QUERY)) + && (msg->need_rsp == TRUE)) + { + fw_txd->fw_txd_2.field.ext_cid_option = EXT_CID_OPTION_NEED_ACK; + } + else + { + fw_txd->fw_txd_2.field.ext_cid_option = EXT_CID_OPTION_NO_NEED_ACK; + } + + fw_txd->fw_txd_0.word = cpu2le32(fw_txd->fw_txd_0.word); + fw_txd->fw_txd_1.word = cpu2le32(fw_txd->fw_txd_1.word); + fw_txd->fw_txd_2.word = cpu2le32(fw_txd->fw_txd_2.word); + +#ifdef CONFIG_TRACE_SUPPORT + TRACE_MCU_CMD_INFO(fw_txd->fw_txd_0.field.length, fw_txd->fw_txd_0.field.pq_id, + fw_txd->fw_txd_1.field.cid, fw_txd->fw_txd_1.field.pkt_type_id, + fw_txd->fw_txd_1.field.set_query, fw_txd->fw_txd_1.field.seq_num, + fw_txd->fw_txd_2.field.ext_cid, fw_txd->fw_txd_2.field.ext_cid_option, + (char *)(GET_OS_PKT_DATAPTR(net_pkt)), GET_OS_PKT_LEN(net_pkt)); +#endif /* CONFIG_TRACE_SUPPORT */ +} + + +INT32 CmdInitAccessRegWrite(RTMP_ADAPTER *ad, UINT32 address, UINT32 data) +{ + struct cmd_msg *msg; + struct _INIT_CMD_ACCESS_REG access_reg; + INT32 ret = 0; + + DBGPRINT(RT_DEBUG_INFO, ("%s: address = %x, data = %x\n", __FUNCTION__, address, data)); + + msg = AndesAllocCmdMsg(ad, sizeof(struct _INIT_CMD_ACCESS_REG)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, INIT_CMD_ACCESS_REG, CMD_SET, EXT_CMD_NA, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + memset(&access_reg, 0x00, sizeof(access_reg)); + + access_reg.ucSetQuery = 1; + access_reg.u4Address = cpu2le32(address); + access_reg.u4Data = cpu2le32(data); + + AndesAppendCmdMsg(msg, (char *)&access_reg, sizeof(access_reg)); + + ret = AndesSendCmdMsg(ad, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + + +static VOID CmdInitAccessRegReadCb(struct cmd_msg *msg, char *data, UINT16 len) +{ + struct _INIT_EVENT_ACCESS_REG *access_reg = (struct _INIT_EVENT_ACCESS_REG *)data; + + NdisMoveMemory(msg->rsp_payload, &access_reg->u4Data, len - 4); + *((UINT32 *)(msg->rsp_payload)) = le2cpu32(*((UINT32 *)msg->rsp_payload)); +} + + +INT32 CmdInitAccessRegRead(RTMP_ADAPTER *pAd, UINT32 address, UINT32 *data) +{ + struct cmd_msg *msg; + struct _INIT_CMD_ACCESS_REG access_reg; + INT32 ret = 0; + + DBGPRINT(RT_DEBUG_INFO, ("%s: address = %x\n", __FUNCTION__, address)); + + msg = AndesAllocCmdMsg(pAd, sizeof(struct _INIT_CMD_ACCESS_REG)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, INIT_CMD_ACCESS_REG, CMD_QUERY, EXT_CMD_NA, TRUE, 0, + TRUE, TRUE, 8, (CHAR *)data, CmdInitAccessRegReadCb); + + memset(&access_reg, 0x00, sizeof(access_reg)); + + access_reg.ucSetQuery = 0; + access_reg.u4Address = cpu2le32(address); + + AndesAppendCmdMsg(msg, (char *)&access_reg, sizeof(access_reg)); + + ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + + +static VOID CmdReStartDLRsp(struct cmd_msg *msg, char *Data, UINT16 Len) +{ + FW_RXD_2 Status; + Status = *(FW_RXD_2 *)Data; + + + switch (Status.field.ext_eid) + { + case WIFI_FW_DOWNLOAD_SUCCESS: + DBGPRINT(RT_DEBUG_OFF, ("%s: WiFI FW Download Success\n", __FUNCTION__)); + break; + case WIFI_FW_DOWNLOAD_INVALID_PARAM: + DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Invalid Parameter\n", __FUNCTION__)); + break; + case WIFI_FW_DOWNLOAD_INVALID_CRC: + DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Invalid CRC\n", __FUNCTION__)); + break; + case WIFI_FW_DOWNLOAD_DECRYPTION_FAIL: + DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Decryption Fail\n", __FUNCTION__)); + break; + case WIFI_FW_DOWNLOAD_UNKNOWN_CMD: + DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Unknown CMD\n", __FUNCTION__)); + break; + case WIFI_FW_DOWNLOAD_TIMEOUT: + DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Timeout\n", __FUNCTION__)); + break; + default: + DBGPRINT(RT_DEBUG_OFF, ("%s: Unknow Status(%u)\n", __FUNCTION__, Status.field.ext_eid)); + break; + } +} + + +static VOID CmdSecKeyRsp(struct cmd_msg *msg, char *Data, UINT16 Len) +{ + P_EVENT_SEC_ADDREMOVE_STRUC_T EvtSecKey; + UINT32 Status; + UINT32 WlanIndex; + + EvtSecKey = (struct _EVENT_SEC_ADDREMOVE_STRUC_T *)Data; + + Status = le2cpu32(EvtSecKey->u4Status); + WlanIndex = le2cpu32(EvtSecKey->u4WlanIdx); + + if (Status != 0) { + DBGPRINT(RT_DEBUG_ERROR, ("%s, error set key, wlan idx(%d), status: 0x%x\n", __FUNCTION__, WlanIndex, Status)); + } else { + DBGPRINT(RT_DEBUG_TRACE, ("%s, wlan idx(%d), status: 0x%x\n", __FUNCTION__, WlanIndex, Status)); + } +} + +static VOID CmdPsRetrieveRsp(struct cmd_msg *msg, char *Data, UINT16 Len) +{ + + P_EXT_EVENT_AP_PS_RETRIEVE_T EvtPsCapatibility; + UINT32 Status; + + EvtPsCapatibility = (P_EXT_EVENT_AP_PS_RETRIEVE_T)Data; + Status = le2cpu32(EvtPsCapatibility->u4Param1); + + DBGPRINT(RT_DEBUG_ERROR, ("%s Disable FW PS Supportstatus:%x !!!!!\n",__FUNCTION__,Status)); + +} + +#ifdef MT_PS +#if defined(MT7603) && defined(RTMP_PCI_SUPPORT) +static VOID CmdPsRetrieveStartRspFromCR(RTMP_ADAPTER *pAd, char *Data, UINT16 Len) +{ + MAC_TABLE_ENTRY *pEntry; + P_EXT_EVENT_AP_PS_RETRIEVE_T EvtPsRetrieveStart; + UINT32 WlanIdx; + STA_TR_ENTRY *tr_entry; + NDIS_STATUS token_status; + unsigned char q_idx; + struct tx_swq_fifo *ps_fifo_swq; + UINT deq_qid; + //unsigned long IrqFlags; + + EvtPsRetrieveStart = (P_EXT_EVENT_AP_PS_RETRIEVE_T)Data; + WlanIdx = le2cpu32(EvtPsRetrieveStart->u4Param1); + + if (!(VALID_TR_WCID(WlanIdx))) { + DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("---->%s INVALID_TR_WCID(WlanIndex)\n", __FUNCTION__)); + goto NEXT; + } + + if (WlanIdx >= MAX_LEN_OF_MAC_TABLE) { + DBGPRINT(RT_DEBUG_ERROR, ("Invalid value of WlanIdx")); + return; + } + + + pEntry = &pAd->MacTab.Content[WlanIdx]; + tr_entry = &pAd->MacTab.tr_entry[WlanIdx]; + if (IS_ENTRY_NONE(pEntry)) + { + tr_entry->ps_state = APPS_RETRIEVE_WAIT_EVENT; + RTEnqueueInternalCmd(pAd, CMDTHREAD_PS_CLEAR, (VOID *)&WlanIdx, sizeof(UINT32)); + DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_PS,("---->%s Entry(wcid=%d) left.\n", __func__, WlanIdx)); + goto NEXT; + } + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("---->%s: Start to send TOKEN frames, WlanIdx=%d\n", __FUNCTION__, WlanIdx)); + + if (tr_entry->ps_state != APPS_RETRIEVE_START_PS) + { + DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("---->%s Entry(wcid=%d) ps state(%d) is not APPS_RETRIEVE_START_PS\n", __FUNCTION__, WlanIdx, tr_entry->ps_state)); + goto NEXT; + } + + tr_entry->ps_state = APPS_RETRIEVE_GOING; + CheckSkipTX(pAd, pEntry); + tr_entry->ps_qbitmap = 0; + + for (q_idx = 0; q_idx < NUM_OF_TX_RING; q_idx++) + { + UINT16 IsEmpty = IS_TXRING_EMPTY(pAd, q_idx); + + if (!IsEmpty) + { + token_status = RtmpEnqueueTokenFrame(pAd, &(pEntry->Addr[0]), 0, WlanIdx, 0, q_idx); + if (!token_status) + tr_entry->ps_qbitmap |= (1 << q_idx); + else + DBGPRINT(RT_DEBUG_ERROR, ("%s(%d) Fail: Send TOKEN Frame, AC=%d\n", __FUNCTION__, __LINE__, q_idx)); + } + } + + if (tr_entry->ps_qbitmap == 0) + { + q_idx = QID_AC_VO; + + token_status = RtmpEnqueueTokenFrame(pAd, &(pEntry->Addr[0]), 0, WlanIdx, 0, q_idx); + + if (!token_status) + tr_entry->ps_qbitmap |= (1 << q_idx); + } + + if (tr_entry->ps_qbitmap == 0) + { + tr_entry->ps_state = APPS_RETRIEVE_WAIT_EVENT; + tr_entry->token_enq_all_fail = TRUE; + RTEnqueueInternalCmd(pAd, CMDTHREAD_PS_CLEAR, (VOID *)&WlanIdx, sizeof(UINT32)); + DBGPRINT(RT_DEBUG_WARN | DBG_FUNC_PS, ("%s(%d): (ps_state = %d) token_enq_all_fail!! ==> send CMDTHREAD_PS_CLEAR cmd.\n", + __FUNCTION__, __LINE__, tr_entry->ps_state)); + } + else + { + tr_entry->token_enq_all_fail = FALSE; + } + +NEXT: + ps_fifo_swq = &pAd->apps_cr_q; + deq_qid = ps_fifo_swq->deqIdx; + while (ps_fifo_swq->swq[deq_qid] != 0) { + WlanIdx = ps_fifo_swq->swq[deq_qid]; + pEntry = &pAd->MacTab.Content[WlanIdx]; + tr_entry = &pAd->MacTab.tr_entry[WlanIdx]; + + if (pEntry->PsMode == PWR_ACTIVE) { + ps_fifo_swq->swq[deq_qid] = 0; + INC_RING_INDEX(ps_fifo_swq->deqIdx, TX_SWQ_FIFO_LEN); + tr_entry->ps_state = APPS_RETRIEVE_IDLE; + MtHandleRxPsPoll(pAd, &pEntry->Addr[0], WlanIdx, TRUE); + deq_qid = ps_fifo_swq->deqIdx; + } else { + if (MtStartPSRetrieve(pAd, ps_fifo_swq->swq[deq_qid]) == TRUE) { + ps_fifo_swq->swq[deq_qid] = 0; + INC_RING_INDEX(ps_fifo_swq->deqIdx, TX_SWQ_FIFO_LEN); + tr_entry->ps_state = APPS_RETRIEVE_START_PS; + tr_entry->ps_start_time = jiffies; + } + break; + } + } +} +#endif /* MT7603 && RTMP_PCI_SUPPORT */ + +VOID AndesPsRetrieveStartRsp(RTMP_ADAPTER *pAd, char *Data, UINT16 Len) + { + MAC_TABLE_ENTRY *pEntry; + P_EXT_EVENT_AP_PS_RETRIEVE_T EvtPsRetrieveStart; + UINT32 WlanIdx; + STA_TR_ENTRY *tr_entry; + NDIS_STATUS token_status; + unsigned char q_idx; + + EvtPsRetrieveStart = (P_EXT_EVENT_AP_PS_RETRIEVE_T)Data; + WlanIdx = le2cpu32(EvtPsRetrieveStart->u4Param1); + + if (!(VALID_TR_WCID(WlanIdx))) { + DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("---->%s INVALID_TR_WCID(WlanIndex)\n", __FUNCTION__)); + return; + } + + if (WlanIdx >= MAX_LEN_OF_MAC_TABLE) { + DBGPRINT(RT_DEBUG_ERROR, ("Invalid value of WlanIdx")); + return; + } + + pEntry = &pAd->MacTab.Content[WlanIdx]; + tr_entry = &pAd->MacTab.tr_entry[WlanIdx]; + if (IS_ENTRY_NONE(pEntry)) + { + MtPsRedirectDisableCheck(pAd, WlanIdx); + DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_PS, ("---->%s Entry(wcid=%d) left.\n", __FUNCTION__, WlanIdx)); + return; + } + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("---->%s: Start to send TOKEN frames, WlanIdx=%d\n", __FUNCTION__, WlanIdx)); + + tr_entry->ps_state = APPS_RETRIEVE_GOING; + tr_entry->ps_qbitmap = 0; + + for (q_idx = 0; q_idx < NUM_OF_TX_RING; q_idx++) + { + //UINT16 IsEmpty = IS_TXRING_EMPTY(pAd, q_idx); + UINT16 IsEmpty = (pAd->TxRing[q_idx].TxDmaIdx == pAd->TxRing[q_idx].TxCpuIdx) ? 1: 0; + + if (!IsEmpty) + { + token_status = RtmpEnqueueTokenFrame(pAd, &(pEntry->Addr[0]), 0, WlanIdx, 0, q_idx); + + if (!token_status) + { + tr_entry->ps_qbitmap |= (1 << q_idx); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(%d) Fail: Send TOKEN Frame, AC=%d\n", __FUNCTION__, __LINE__, q_idx)); + } + } + } + + if (tr_entry->ps_qbitmap == 0) + { + q_idx = QID_AC_VO; + + token_status = RtmpEnqueueTokenFrame(pAd, &(pEntry->Addr[0]), 0, WlanIdx, 0, q_idx); + + if (!token_status) + tr_entry->ps_qbitmap |= (1 << q_idx); + } + + if (tr_entry->ps_qbitmap == 0) + { + tr_entry->ps_state = APPS_RETRIEVE_WAIT_EVENT; + tr_entry->token_enq_all_fail = TRUE; + RTEnqueueInternalCmd(pAd, CMDTHREAD_PS_CLEAR, (VOID *)&WlanIdx, sizeof(UINT32)); + DBGPRINT(RT_DEBUG_WARN | DBG_FUNC_PS, ("%s(%d): (ps_state = %d) token_enq_all_fail!! ==> send CMDTHREAD_PS_CLEAR cmd.\n", + __FUNCTION__, __LINE__, tr_entry->ps_state)); + } + else + { + tr_entry->token_enq_all_fail = FALSE; + } +} + +static VOID CmdPsRetrieveStartRsp(struct cmd_msg *msg, char *Data, UINT16 Len) +{ + RTMP_ADAPTER *ad = NULL; + + ad = (RTMP_ADAPTER *)msg->priv; + + DBGPRINT(RT_DEBUG_ERROR, ("------> %s(%d)\n", __FUNCTION__, __LINE__)); +#ifdef RTMP_PCI_SUPPORT + AndesPsRetrieveStartRsp(ad, Data, Len); +#endif /* RTMP_PCI_SUPPORT */ + +#if defined(RTMP_USB_SUPPORT) || defined(RTMP_SDIO_SUPPORT) + /* + We need to move AndesPsRetrieveStartRsp to cmd thread for CR read/write. + */ + RTEnqueueInternalCmd(ad, CMDTHREAD_PS_RETRIEVE_RSP, Data, Len); +#endif /* defined(RTMP_USB_SUPPORT) || defined(RTMP_SDIO_SUPPORT) */ + DBGPRINT(RT_DEBUG_ERROR, ("<------ %s(%d)\n", __FUNCTION__, __LINE__)); +} + + +static VOID CmdPsClearRsp(struct cmd_msg *msg, char *Data, UINT16 Len) +{ + //UINT8 Status; + MAC_TABLE_ENTRY *pEntry; + //QUEUE_ENTRY *pQEntry; + P_CMD_AP_PS_CLEAR_STRUC_T EvtPsClear; + RTMP_ADAPTER *ad = (RTMP_ADAPTER *)msg->priv; + STA_TR_ENTRY *tr_entry; + //unsigned long IrqFlags; + //struct wtbl_entry tb_entry; + UINT32 WlanIndex; + //union WTBL_1_DW3 *dw3 = (union WTBL_1_DW3 *)&tb_entry.wtbl_1.wtbl_1_d3.word; + unsigned char q_idx = 0; + + EvtPsClear = (struct _CMD_AP_PS_CLEAR_STRUC_T *)Data; + WlanIndex = le2cpu32(EvtPsClear->u4WlanIdx); + pEntry = &ad->MacTab.Content[WlanIndex]; + tr_entry = &ad->MacTab.tr_entry[WlanIndex]; + + + if (ad->MacTab.tr_entry[WlanIndex].PsMode == PWR_ACTIVE) + tr_entry->ps_state = APPS_RETRIEVE_IDLE; + else + tr_entry->ps_state = APPS_RETRIEVE_DONE; + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("wcid=%d, Receive Event of CmdPsClear tr_entry->ps_state=%d\n", WlanIndex,tr_entry->ps_state)); + + if(tr_entry->token_enq_all_fail) + { + tr_entry->token_enq_all_fail = FALSE; + + if (tr_entry->ps_queue.Number) + MtEnqTxSwqFromPsQueue(ad, q_idx, tr_entry); + + for (q_idx = 0; q_idx < NUM_OF_TX_RING; q_idx++) + { + if (q_idx < WMM_QUE_NUM) + tr_entry->TokenCount[q_idx] = tr_entry->tx_queue[q_idx].Number; + else + break; + } + } + if(IS_ENTRY_NONE(pEntry)) { + DBGPRINT(RT_DEBUG_TRACE | DBG_FUNC_PS, ("wcid=%d, pEntry none when CmdPsClearRsp\n", WlanIndex)); + return; + } + +#ifdef RTMP_MAC_PCI +#ifdef DOT11_N_SUPPORT + SendRefreshBAR(ad, pEntry); +#endif /* DOT11_N_SUPPORT */ +#endif /* RTMP_MAC_PCI */ + if (tr_entry->ps_state == APPS_RETRIEVE_IDLE) + MtHandleRxPsPoll(ad, &pEntry->Addr[0], WlanIndex, TRUE); +#ifdef UAPSD_SUPPORT + else + { + if (tr_entry->bEospNullSnd) + { + //UINT32 AcQueId; + + tr_entry->bEospNullSnd = FALSE; + /* sanity Check for UAPSD condition */ + if (tr_entry->EospNullUp >= 8) + tr_entry->EospNullUp = 1; /* shout not be here */ + + /* get the AC ID of incoming packet */ + //AcQueId = WMM_UP2AC_MAP[tr_entry->EospNullUp]; + + /* bQosNull = bEOSP = TRUE = 1 */ + + /* + Use management queue to tx QoS Null frame to avoid delay so + us_of_frame is not used. + */ +#ifdef CONFIG_AP_SUPPORT +#ifdef MT_PS + if (pEntry->i_psm == I_PSM_DISABLE) + { + MT_SET_IGNORE_PSM(ad, pEntry, I_PSM_ENABLE); + } +#endif /* MT_PS */ +#endif /* CONFIG_AP_SUPPORT */ + + RtmpEnqueueNullFrame(ad, pEntry->Addr, pEntry->CurrTxRate, + pEntry->Aid, pEntry->func_tb_idx, TRUE, TRUE, tr_entry->EospNullUp); + +#ifdef UAPSD_DEBUG + DBGPRINT(RT_DEBUG_ERROR, ("%s: send a EOSP QoS Null frame!\n", __FUNCTION__)); +#endif /* UAPSD_DEBUG */ + } + else if (pEntry->UAPSDTxNum != 0) + { + RTMPDeQueuePacket(ad, TRUE, NUM_OF_TX_RING, pEntry->wcid, pEntry->UAPSDTxNum); + } + } +#endif /* UAPSD_SUPPORT */ +} +#endif /* MT_PS */ + +static VOID CmdStartDLRsp(struct cmd_msg *msg, char *Data, UINT16 Len) +{ + UINT8 Status; + + Status = *Data; + + switch (Status) + { + case WIFI_FW_DOWNLOAD_SUCCESS: + DBGPRINT(RT_DEBUG_OFF, ("%s: WiFI FW Download Success\n", __FUNCTION__)); + break; + case WIFI_FW_DOWNLOAD_INVALID_PARAM: + DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Invalid Parameter\n", __FUNCTION__)); + break; + case WIFI_FW_DOWNLOAD_INVALID_CRC: + DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Invalid CRC\n", __FUNCTION__)); + break; + case WIFI_FW_DOWNLOAD_DECRYPTION_FAIL: + DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Decryption Fail\n", __FUNCTION__)); + break; + case WIFI_FW_DOWNLOAD_UNKNOWN_CMD: + DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Unknown CMD\n", __FUNCTION__)); + break; + case WIFI_FW_DOWNLOAD_TIMEOUT: + DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi FW Download Timeout\n", __FUNCTION__)); + break; + default: + DBGPRINT(RT_DEBUG_OFF, ("%s: Unknow Status(%d)\n", __FUNCTION__, Status)); + break; + } +} + +INT32 CmdSecKeyReq(RTMP_ADAPTER *ad, UINT8 AddRemove, UINT8 Keytype, UINT8 *pAddr, UINT8 Alg, UINT8 KeyID, UINT8 KeyLen, UINT8 WlanIdx, UINT8 *KeyMaterial) +{ + struct cmd_msg *msg; + struct _CMD_SEC_ADDREMOVE_KEY_STRUC_T CmdSecKey; + int ret = 0; + + msg = AndesAllocCmdMsg(ad, sizeof(struct _CMD_SEC_ADDREMOVE_KEY_STRUC_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_SEC_ADDREMOVE_KEY, FALSE, 0, FALSE, TRUE, sizeof(struct _EVENT_SEC_ADDREMOVE_STRUC_T), NULL, CmdSecKeyRsp); + + memset(&CmdSecKey, 0x00, sizeof(CmdSecKey)); + + CmdSecKey.ucAddRemove = AddRemove; + CmdSecKey.ucKeyType = Keytype; + memcpy(CmdSecKey.aucPeerAddr, pAddr, 6); + CmdSecKey.ucAlgorithmId = Alg; + CmdSecKey.ucKeyId = KeyID; + CmdSecKey.ucKeyLen = KeyLen; + memcpy(CmdSecKey.aucKeyMaterial, KeyMaterial, KeyLen); + CmdSecKey.ucWlanIndex = WlanIdx; + AndesAppendCmdMsg(msg, (char *)&CmdSecKey, sizeof(CmdSecKey)); + + ret = AndesSendCmdMsg(ad, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + +INT32 CmdPsRetrieveReq(RTMP_ADAPTER *ad, UINT32 enable) +{ + struct cmd_msg *msg; + struct _CMD_AP_PS_RETRIEVE_T CmdPsCapatibility; + + int ret = 0; + + msg = AndesAllocCmdMsg(ad, sizeof(struct _CMD_AP_PS_RETRIEVE_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_AP_PWR_SAVING_CAPABILITY, TRUE, 0, TRUE, TRUE, sizeof(struct _CMD_AP_PS_RETRIEVE_T), NULL, CmdPsRetrieveRsp); + + NdisZeroMemory(&CmdPsCapatibility, sizeof(CmdPsCapatibility)); + + CmdPsCapatibility.u4Option= cpu2le32(0); + CmdPsCapatibility.u4Param1= cpu2le32(enable); + + AndesAppendCmdMsg(msg, (char *)&CmdPsCapatibility, sizeof(CmdPsCapatibility)); + ret = AndesSendCmdMsg(ad, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + +#ifdef MT_PS +INT32 CmdPsRetrieveStartReq(RTMP_ADAPTER *ad, UINT32 WlanIdx) +{ + struct cmd_msg *msg; + struct _EXT_CMD_AP_PWS_START_T CmdApPwsStart; + + int ret = 0; + + /*how to handle memory allocate failure? */ + msg = AndesAllocCmdMsg(ad, sizeof(struct _EXT_CMD_AP_PWS_START_T)); + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + goto error; + } + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("%s(%d): RTEnqueueInternalCmd comming!! WlanIdx: %x\n",__FUNCTION__, __LINE__,WlanIdx)); + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_PS_RETRIEVE_START, TRUE, 0, TRUE, TRUE, sizeof(struct _EXT_CMD_AP_PWS_START_T), NULL, CmdPsRetrieveStartRsp); + + NdisZeroMemory(&CmdApPwsStart, sizeof(CmdApPwsStart)); + + CmdApPwsStart.u4WlanIdx= cpu2le32(WlanIdx); + + AndesAppendCmdMsg(msg, (char *)&CmdApPwsStart, sizeof(CmdApPwsStart)); + msg->wcid = WlanIdx; + ret = AndesSendCmdMsg(ad, msg); + +error: + return ret; +} + + + +INT32 CmdPsClearReq(RTMP_ADAPTER *ad, UINT32 wlanidx, BOOLEAN p_wait) +{ + struct cmd_msg *msg; + struct _CMD_AP_PS_CLEAR_STRUC_T CmdPsClear; + int ret = 0; + + msg = AndesAllocCmdMsg(ad, sizeof(struct _CMD_AP_PS_CLEAR_STRUC_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + DBGPRINT(RT_DEBUG_ERROR | DBG_FUNC_PS, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + goto error; + } + + DBGPRINT(RT_DEBUG_INFO | DBG_FUNC_PS, ("%s(%d): RTEnqueueInternalCmd comming!! WlanIdx: %x\n",__FUNCTION__, __LINE__,wlanidx)); + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_QUERY, EXT_CMD_PWR_SAVING, TRUE, 0, TRUE, TRUE, sizeof(struct _CMD_AP_PS_CLEAR_STRUC_T), NULL, CmdPsClearRsp); + + NdisZeroMemory(&CmdPsClear, sizeof(CmdPsClear)); + + CmdPsClear.u4WlanIdx = cpu2le32(wlanidx); + CmdPsClear.u4Status = cpu2le32(0); + + AndesAppendCmdMsg(msg, (char *)&CmdPsClear, sizeof(CmdPsClear)); + msg->wcid = wlanidx; + ret = AndesSendCmdMsg(ad, msg); + +error: + return ret; +} +#endif /* MT_PS */ + +static INT32 CmdRestartDLReq(RTMP_ADAPTER *ad) +{ + struct cmd_msg *msg; + int ret = 0; + + msg = AndesAllocCmdMsg(ad, 0); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, MT_RESTART_DL_REQ, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, CmdReStartDLRsp); + + ret = AndesSendCmdMsg(ad, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + +/*Nobody uses it currently*/ + +static VOID CmdAddrellLenRsp(struct cmd_msg *msg, char *Data, UINT16 Len) +{ + UINT8 Status; + + Status = *Data; + + switch (Status) + { + case TARGET_ADDRESS_LEN_SUCCESS: + DBGPRINT(RT_DEBUG_INFO, ("%s: Request target address and length success\n", __FUNCTION__)); + break; + default: + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Status(%d)\n", __FUNCTION__, Status)); + break; + } +} + + +static INT32 CmdAddressLenReq(RTMP_ADAPTER *ad, UINT32 address, UINT32 len, UINT32 data_mode) +{ + struct cmd_msg *msg; + int ret = 0; + UINT32 value; + + DBGPRINT(RT_DEBUG_TRACE, ("Start address = %x, DL length = %d, Data mode = %x\n", + address, len, data_mode)); + msg = AndesAllocCmdMsg(ad, 12); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + if (address == ROM_PATCH_START_ADDRESS) + AndesInitCmdMsg(msg, P1_Q0, MT_PATCH_START_REQ, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, CmdAddrellLenRsp); + else + AndesInitCmdMsg(msg, P1_Q0, MT_TARGET_ADDRESS_LEN_REQ, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, CmdAddrellLenRsp); + + /* start address */ + value = cpu2le32(address); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + /* dl length */ + value = cpu2le32(len); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + /* data mode */ + value = cpu2le32(data_mode); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + ret = AndesSendCmdMsg(ad, msg); + +error: + DBGPRINT(RT_DEBUG_OFF, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + +static INT32 CmdFwScatter(RTMP_ADAPTER *ad, UINT8 *dl_payload, UINT32 dl_len, UINT32 count) +{ + struct cmd_msg *msg; + int ret = 0; + + msg = AndesAllocCmdMsg(ad, dl_len); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, 0xC000, MT_FW_SCATTER, CMD_NA, EXT_CMD_NA, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + AndesAppendCmdMsg(msg, (char *)dl_payload, dl_len); + + ret = AndesSendCmdMsg(ad, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(scatter = %d, ret = %d)\n", __FUNCTION__, count, ret)); + return ret; +} + +static INT32 CmdFwScatters(RTMP_ADAPTER *ad, UINT8 *image, UINT32 image_len) +{ + INT32 sent_len; + UINT32 cur_len = 0, count = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + int ret = 0; + + while (1) + { + INT32 sent_len_max = MT_UPLOAD_FW_UNIT - cap->cmd_header_len; + sent_len = (image_len - cur_len) >= sent_len_max ? sent_len_max : (image_len - cur_len); + + if (sent_len > 0) { + ret = CmdFwScatter(ad, image + cur_len, sent_len, count); + count++; + if (ret) + goto error; + cur_len += sent_len; + } else { + break; + } + } + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + + +static VOID CmdPatchFinishRsp(struct cmd_msg *msg, char *Data, UINT16 Len) +{ + UINT8 Status; + + Status = *Data; + + switch (Status) + { + case WIFI_FW_DOWNLOAD_SUCCESS: + DBGPRINT(RT_DEBUG_OFF, ("%s: WiFI ROM Patch Download Success\n", __FUNCTION__)); + break; + default: + DBGPRINT(RT_DEBUG_OFF, ("%s: WiFi ROM Patch Fail (%d)\n", __FUNCTION__, Status)); + break; + } +} + + +static INT32 CmdPatchFinishReq(RTMP_ADAPTER *ad) +{ + struct cmd_msg *msg; + int ret = 0; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + msg = AndesAllocCmdMsg(ad, 0); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, MT_PATCH_FINISH_REQ, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, CmdPatchFinishRsp); + + ret = AndesSendCmdMsg(ad, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + + +static INT32 CmdFwStartReq(RTMP_ADAPTER *ad, UINT32 override, UINT32 address) +{ + struct cmd_msg *msg; + int ret = 0; + UINT32 value; + + DBGPRINT(RT_DEBUG_OFF, ("%s: override = %d, address = %d\n", __FUNCTION__, override, address)); + + msg = AndesAllocCmdMsg(ad, 8); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, MT_FW_START_REQ, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, CmdStartDLRsp); + + /* override */ + value = cpu2le32(override); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + /* entry point address */ + value = cpu2le32(address); + + AndesAppendCmdMsg(msg, (char *)&value, 4); + + ret = AndesSendCmdMsg(ad, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + + +INT32 CmdChPrivilege(RTMP_ADAPTER *ad, UINT8 Action, UINT8 control_chl, UINT8 central_chl, + UINT8 BW, UINT8 TXStream, UINT8 RXStream) +{ + struct cmd_msg *msg; + struct _CMD_CH_PRIVILEGE_T ch_privilege; + INT32 ret = 0; + struct MCU_CTRL *Ctl = &ad->MCUCtrl; + + if (central_chl == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: central channel = 0 is invalid\n", __FUNCTION__)); + return -1; + } + + DBGPRINT(RT_DEBUG_INFO, ("%s: control_chl = %d, central_chl = %d, BW = %d, \ + TXStream = %d, RXStream = %d\n", __FUNCTION__, \ + control_chl, central_chl, BW, TXStream, RXStream)); + + msg = AndesAllocCmdMsg(ad, sizeof(struct _CMD_CH_PRIVILEGE_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, CMD_CH_PRIVILEGE, CMD_SET, EXT_CMD_NA, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + memset(&ch_privilege, 0x00, sizeof(ch_privilege)); + + ch_privilege.ucAction = Action; + ch_privilege.ucPrimaryChannel = control_chl; + + if (BW == BAND_WIDTH_20) + { + ch_privilege.ucRfSco = CMD_CH_PRIV_SCO_SCN; + } + else if (BW == BAND_WIDTH_40) + { + if (control_chl < central_chl) + ch_privilege.ucRfSco = CMD_CH_PRIV_SCO_SCA; + else + ch_privilege.ucRfSco = CMD_CH_PRIV_SCO_SCB; + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("unknown bandwidth = %d\n", BW)); + } + + if (central_chl > 14) + ch_privilege.ucRfBand = CMD_CH_PRIV_BAND_A; + else + ch_privilege.ucRfBand = CMD_CH_PRIV_BAND_G; + + ch_privilege.ucRfChannelWidth = CMD_CH_PRIV_CH_WIDTH_20_40; + + ch_privilege.ucReqType = CMD_CH_PRIV_REQ_JOIN; + + AndesAppendCmdMsg(msg, (char *)&ch_privilege, sizeof(ch_privilege)); + + if (IS_MT7603(ad) || IS_MT7628(ad)) + { + UINT32 Value; + RTMP_IO_READ32(ad, RMAC_RMCR, &Value); + + if (Value & RMAC_RMCR_RX_STREAM_0) + Ctl->RxStream0 = 1; + + if (Value & RMAC_RMCR_RX_STREAM_1) + Ctl->RxStream1 = 1; + + Value |= RMAC_RMCR_RX_STREAM_0; + Value |= RMAC_RMCR_RX_STREAM_1; + RTMP_IO_WRITE32(ad, RMAC_RMCR, Value); + } + + ret = AndesSendCmdMsg(ad, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + + +static VOID CmdMultipleMacRegAccessWriteCb(struct cmd_msg *msg, + char *data, UINT16 len) +{ + EXT_EVENT_MULTI_CR_ACCESS_WR_T *EventMultiCRAccessWR + = (EXT_EVENT_MULTI_CR_ACCESS_WR_T *)(data + 20); + + EventMultiCRAccessWR->u4Status = le2cpu32(EventMultiCRAccessWR->u4Status); + + if (EventMultiCRAccessWR->u4Status) + DBGPRINT(RT_DEBUG_ERROR, ("%s: fail\n", __FUNCTION__)); +} + + +INT32 CmdMultipleMacRegAccessWrite(RTMP_ADAPTER *pAd, RTMP_REG_PAIR *RegPair, + UINT32 Num) +{ + struct cmd_msg *msg; + CMD_MULTI_CR_ACCESS_T MultiCR; + INT32 Ret; + UINT32 Index; + + msg = AndesAllocCmdMsg(pAd, sizeof(CMD_MULTI_CR_ACCESS_T) * Num); + + if (!msg) + { + Ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_MULTIPLE_REG_ACCESS, + TRUE, 0, TRUE, TRUE, 32, NULL, CmdMultipleMacRegAccessWriteCb); + + for (Index = 0; Index < Num; Index++) + { + memset(&MultiCR, 0x00, sizeof(MultiCR)); + MultiCR.u4Type = cpu2le32(MAC_CR); + MultiCR.u4Addr = cpu2le32(RegPair[Index].Register); + MultiCR.u4Data = cpu2le32(RegPair[Index].Value); +// DBGPRINT(RT_DEBUG_TRACE, ("%s: offset: = %x\n", __FUNCTION__,MultiCR.u4Addr)); + + AndesAppendCmdMsg(msg, (char *)&MultiCR, sizeof(MultiCR)); + } + + Ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, Ret)); + return Ret; +} + + +static VOID CmdMultipleRfRegAccessWriteCb(struct cmd_msg *msg, + char *data, UINT16 len) +{ + EXT_EVENT_MULTI_CR_ACCESS_WR_T *EventMultiCRAccessWR + = (EXT_EVENT_MULTI_CR_ACCESS_WR_T *)(data + 20); + + EventMultiCRAccessWR->u4Status = le2cpu32(EventMultiCRAccessWR->u4Status); + + if (EventMultiCRAccessWR->u4Status) + DBGPRINT(RT_DEBUG_ERROR, ("%s: fail\n", __FUNCTION__)); +} + + +INT32 CmdMultipleRfRegAccessWrite(RTMP_ADAPTER *pAd, MT_RF_REG_PAIR *RegPair, + UINT32 Num) +{ + struct cmd_msg *msg; + CMD_MULTI_CR_ACCESS_T MultiCR; + INT32 Ret; + UINT32 Index; + + msg = AndesAllocCmdMsg(pAd, sizeof(CMD_MULTI_CR_ACCESS_T) * Num); + + if (!msg) + { + Ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_MULTIPLE_REG_ACCESS, + TRUE, 0, TRUE, TRUE, 32, NULL, CmdMultipleRfRegAccessWriteCb); + + for (Index = 0; Index < Num; Index++) + { + memset(&MultiCR, 0x00, sizeof(MultiCR)); + MultiCR.u4Type = cpu2le32((RF_CR & 0xff) | + ((RegPair->WiFiStream & 0xffffff) << 8)); + MultiCR.u4Addr = cpu2le32(RegPair[Index].Register); + MultiCR.u4Data = cpu2le32(RegPair[Index].Value); + + AndesAppendCmdMsg(msg, (char *)&MultiCR, sizeof(MultiCR)); + } + + Ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, Ret)); + return Ret; +} + + +static VOID CmdMultipleRfRegAccessReadCb(struct cmd_msg *msg, + char *data, UINT16 len) +{ + UINT32 Index; + UINT32 Num = (len -20) / sizeof(EXT_EVENT_MULTI_CR_ACCESS_RD_T); + EXT_EVENT_MULTI_CR_ACCESS_RD_T *EventMultiCRAccessRD + = (EXT_EVENT_MULTI_CR_ACCESS_RD_T *)(data + 20); + MT_RF_REG_PAIR *RegPair = (MT_RF_REG_PAIR *)msg->rsp_payload; + + for (Index = 0; Index < Num; Index++) + { + RegPair->WiFiStream = (le2cpu32(EventMultiCRAccessRD->u4Type) + & (0xffffff << 8)) >> 8; + RegPair->Register = le2cpu32(EventMultiCRAccessRD->u4Addr); + RegPair->Value = le2cpu32(EventMultiCRAccessRD->u4Data); + + EventMultiCRAccessRD++; + RegPair++; + } +} + + +INT32 CmdMultiPleRfRegAccessRead(RTMP_ADAPTER *pAd, MT_RF_REG_PAIR *RegPair, + UINT32 Num) +{ + struct cmd_msg *msg; + CMD_MULTI_CR_ACCESS_T MultiCR; + INT32 Ret; + UINT32 Index; + + msg = AndesAllocCmdMsg(pAd, sizeof(CMD_MULTI_CR_ACCESS_T) * Num); + + if (!msg) + { + Ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_QUERY, EXT_CMD_MULTIPLE_REG_ACCESS, + TRUE, 0, TRUE, TRUE, (12 * Num) + 20, (char *)RegPair, + CmdMultipleRfRegAccessReadCb); + + for (Index = 0; Index < Num; Index++) + { + memset(&MultiCR, 0x00, sizeof(MultiCR)); + MultiCR.u4Type = cpu2le32((RF_CR & 0xff) | + ((RegPair->WiFiStream & 0xffffff) << 8)); + MultiCR.u4Addr = cpu2le32(RegPair[Index].Register); + + AndesAppendCmdMsg(msg, (char *)&MultiCR, sizeof(MultiCR)); + } + + Ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, Ret)); + return Ret; +} + + +static VOID CmdMultipleMacRegAccessReadCb(struct cmd_msg *msg, + char *data, UINT16 len) +{ + UINT32 Index; + UINT32 Num = (len - 20) / sizeof(EXT_EVENT_MULTI_CR_ACCESS_RD_T); + EXT_EVENT_MULTI_CR_ACCESS_RD_T *EventMultiCRAccessRD + = (EXT_EVENT_MULTI_CR_ACCESS_RD_T *)(data + 20); + RTMP_REG_PAIR *RegPair = (RTMP_REG_PAIR *)msg->rsp_payload; + + for (Index = 0; Index < Num; Index++) + { + RegPair->Register = le2cpu32(EventMultiCRAccessRD->u4Addr); + RegPair->Value = le2cpu32(EventMultiCRAccessRD->u4Data); + + EventMultiCRAccessRD++; + RegPair++; + } +} + + +INT32 CmdMultiPleMacRegAccessRead(RTMP_ADAPTER *pAd, RTMP_REG_PAIR *RegPair, + UINT32 Num) +{ + struct cmd_msg *msg; + CMD_MULTI_CR_ACCESS_T MultiCR; + INT32 Ret; + UINT32 Index; + + msg = AndesAllocCmdMsg(pAd, sizeof(CMD_MULTI_CR_ACCESS_T) * Num); + + if (!msg) + { + Ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_QUERY, EXT_CMD_MULTIPLE_REG_ACCESS, + TRUE, 0, TRUE, TRUE, (12 * Num) + 20, (char *)RegPair, + CmdMultipleMacRegAccessReadCb); + + for (Index = 0; Index < Num; Index++) + { + memset(&MultiCR, 0x00, sizeof(MultiCR)); + MultiCR.u4Type = cpu2le32(MAC_CR); + MultiCR.u4Addr = cpu2le32(RegPair[Index].Register); + + AndesAppendCmdMsg(msg, (char *)&MultiCR, sizeof(MultiCR)); + } + + Ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, Ret)); + return Ret; +} + + +INT32 CmdAccessRegWrite(RTMP_ADAPTER *ad, UINT32 address, UINT32 data) +{ + struct cmd_msg *msg; + struct _CMD_ACCESS_REG_T access_reg; + INT32 ret = 0; + + DBGPRINT(RT_DEBUG_INFO, ("%s: address = %x, data = %x\n", __FUNCTION__, address, data)); + + msg = AndesAllocCmdMsg(ad, sizeof(struct _CMD_ACCESS_REG_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, CMD_ACCESS_REG, CMD_SET, EXT_CMD_NA, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + memset(&access_reg, 0x00, sizeof(access_reg)); + + access_reg.u4Address = cpu2le32(address); + access_reg.u4Data = cpu2le32(data); + + AndesAppendCmdMsg(msg, (char *)&access_reg, sizeof(access_reg)); + + ret = AndesSendCmdMsg(ad, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + + +static VOID CmdAccessRegReadCb(struct cmd_msg *msg, char *data, UINT16 len) +{ + struct _CMD_ACCESS_REG_T *access_reg = (struct _CMD_ACCESS_REG_T *)data; + + DBGPRINT(RT_DEBUG_INFO, ("%s\n", __FUNCTION__)); + + NdisMoveMemory(msg->rsp_payload, &access_reg->u4Data, len - 4); + *((UINT32 *)(msg->rsp_payload)) = le2cpu32(*((UINT32 *)msg->rsp_payload)); +} + + +INT32 CmdAccessRegRead(RTMP_ADAPTER *pAd, UINT32 address, UINT32 *data) +{ + struct cmd_msg *msg; + struct _CMD_ACCESS_REG_T access_reg; + INT32 ret = 0; + + msg = AndesAllocCmdMsg(pAd, sizeof(struct _CMD_ACCESS_REG_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, CMD_ACCESS_REG, CMD_QUERY, EXT_CMD_NA, TRUE, 0, + TRUE, TRUE, 8, (CHAR *)data, CmdAccessRegReadCb); + + memset(&access_reg, 0x00, sizeof(access_reg)); + + access_reg.u4Address = cpu2le32(address); + + AndesAppendCmdMsg(msg, (char *)&access_reg, sizeof(access_reg)); + + ret = AndesSendCmdMsg(pAd, msg); + + DBGPRINT(RT_DEBUG_INFO, ("%s: address = %x, value = %x\n", __FUNCTION__, address, *data)); +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + + +INT32 CmdRFRegAccessWrite(RTMP_ADAPTER *pAd, UINT32 RFIdx, UINT32 Offset, UINT32 Value) +{ + struct cmd_msg *msg; + struct _CMD_RF_REG_ACCESS_T RFRegAccess; + INT32 ret = 0; + + DBGPRINT(RT_DEBUG_INFO, ("%s: RFIdx = %d, Offset = %x, Value = %x\n", __FUNCTION__,\ + RFIdx, Offset, Value)); + + msg = AndesAllocCmdMsg(pAd, sizeof(struct _CMD_RF_REG_ACCESS_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_RF_REG_ACCESS, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + memset(&RFRegAccess, 0x00, sizeof(RFRegAccess)); + + RFRegAccess.WiFiStream = cpu2le32(RFIdx); + RFRegAccess.Address = cpu2le32(Offset); + RFRegAccess.Data = cpu2le32(Value); + + AndesAppendCmdMsg(msg, (char *)&RFRegAccess, sizeof(RFRegAccess)); + + ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + + +static VOID CmdRFRegAccessReadCb(struct cmd_msg *msg, char *Data, UINT16 Len) +{ + struct _CMD_RF_REG_ACCESS_T *RFRegAccess = (struct _CMD_RF_REG_ACCESS_T *)Data; + + NdisMoveMemory(msg->rsp_payload, &RFRegAccess->Data, Len - 8); + *msg->rsp_payload = le2cpu32(*msg->rsp_payload); +} + + +INT32 CmdRFRegAccessRead(RTMP_ADAPTER *pAd, UINT32 RFIdx, UINT32 Offset, UINT32 *Value) +{ + struct cmd_msg *msg; + struct _CMD_RF_REG_ACCESS_T RFRegAccess; + INT32 ret = 0; + + DBGPRINT(RT_DEBUG_INFO, ("%s: RFIdx = %d, Offset = %x\n", __FUNCTION__, RFIdx, Offset)); + + msg = AndesAllocCmdMsg(pAd, sizeof(struct _CMD_RF_REG_ACCESS_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_QUERY, EXT_CMD_RF_REG_ACCESS, TRUE, 0, + TRUE, TRUE, 12, (CHAR *)Value, CmdRFRegAccessReadCb); + + memset(&RFRegAccess, 0x00, sizeof(RFRegAccess)); + + RFRegAccess.WiFiStream = cpu2le32(RFIdx); + RFRegAccess.Address = cpu2le32(Offset); + + AndesAppendCmdMsg(msg, (char *)&RFRegAccess, sizeof(RFRegAccess)); + + ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + + +VOID CmdIOWrite32(RTMP_ADAPTER *pAd, UINT32 Offset, UINT32 Value) +{ + struct MCU_CTRL *Ctl = &pAd->MCUCtrl; + RTMP_REG_PAIR RegPair; + + if (Ctl->Stage == FW_RUN_TIME) + { + RegPair.Register = Offset; + RegPair.Value = Value; + CmdMultipleMacRegAccessWrite(pAd, &RegPair, 1); + } +#ifdef E2P_WITHOUT_FW_SUPPORT + else if (Ctl->Stage == FW_NO_INIT) + { + RTMP_IO_WRITE32(pAd, Offset, Value); + } +#endif /* E2P_WITHOUT_FW_SUPPORT */ + else + { + CmdInitAccessRegWrite(pAd, Offset, Value); + } +} + + +VOID CmdIORead32(struct _RTMP_ADAPTER *pAd, UINT32 Offset, UINT32 *Value) +{ + + struct MCU_CTRL *Ctl = &pAd->MCUCtrl; + RTMP_REG_PAIR RegPair; + + if (Ctl->Stage == FW_RUN_TIME) + { + RegPair.Register = Offset; + CmdMultiPleMacRegAccessRead(pAd, &RegPair, 1); + *Value = RegPair.Value; + } +#ifdef E2P_WITHOUT_FW_SUPPORT + else if (Ctl->Stage == FW_NO_INIT) + { + RTMP_IO_READ32(pAd, Offset, Value); + } +#endif /* E2P_WITHOUT_FW_SUPPORT */ + else + { + CmdInitAccessRegRead(pAd, Offset, Value); + } +} + +static VOID EventExtCmdResult(struct cmd_msg *msg, char *Data, UINT16 Len) +{ + struct _EVENT_EXT_CMD_RESULT_T *EventExtCmdResult = (struct _EVENT_EXT_CMD_RESULT_T *)Data; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv; + + DBGPRINT(RT_DEBUG_INFO, ("%s: EventExtCmdResult.ucExTenCID = 0x%x\n", + __FUNCTION__, EventExtCmdResult->ucExTenCID)); + + EventExtCmdResult->u4Status = le2cpu32(EventExtCmdResult->u4Status); + + DBGPRINT(RT_DEBUG_INFO, ("%s: EventExtCmdResult.u4Status = 0x%x\n", + __FUNCTION__, EventExtCmdResult->u4Status)); + + RTMP_OS_TXRXHOOK_CALL(WLAN_CALIB_TEST_RSP,NULL,EventExtCmdResult->u4Status,pAd); +} + + +VOID EventExtCmdResultHandler(RTMP_ADAPTER *pAd, char *Data, UINT16 Len) +{ + struct _EVENT_EXT_CMD_RESULT_T *EventExtCmdResult = (struct _EVENT_EXT_CMD_RESULT_T *)Data; + //RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv; + + DBGPRINT(RT_DEBUG_INFO, ("%s: EventExtCmdResult.ucExTenCID = 0x%x\n", + __FUNCTION__, EventExtCmdResult->ucExTenCID)); + + EventExtCmdResult->u4Status = le2cpu32(EventExtCmdResult->u4Status); + + DBGPRINT(RT_DEBUG_INFO, ("%s: EventExtCmdResult.u4Status = 0x%x\n", + __FUNCTION__, EventExtCmdResult->u4Status)); + + RTMP_OS_TXRXHOOK_CALL(WLAN_CALIB_TEST_RSP,NULL,EventExtCmdResult->u4Status,pAd); +} + + +INT32 CmdIcapOverLap(RTMP_ADAPTER *pAd, UINT32 IcapLen) +{ + struct cmd_msg *msg; + struct _CMD_TEST_CTRL_T TestCtrl; + INT32 ret = 0; + + DBGPRINT(RT_DEBUG_INFO, ("%s: IcapLen = %d\n", __FUNCTION__, IcapLen)); + + msg = AndesAllocCmdMsg(pAd, sizeof(TestCtrl)); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_RF_TEST, TRUE, 0, + TRUE, TRUE, 8, NULL, EventExtCmdResult); + + memset(&TestCtrl, 0x00, sizeof(TestCtrl)); + + TestCtrl.ucAction = 0; + + TestCtrl.ucIcapLen = IcapLen; + + TestCtrl.u.u4OpMode =cpu2le32( OPERATION_ICAP_OVERLAP); + + AndesAppendCmdMsg(msg, (char *)&TestCtrl, sizeof(TestCtrl)); + + ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + + +INT32 CmdRfTest(RTMP_ADAPTER *pAd, UINT8 Action, UINT8 Mode, UINT8 CalItem) +{ + struct cmd_msg *msg; + struct _CMD_TEST_CTRL_T TestCtrl; + INT32 ret = 0; + + DBGPRINT(RT_DEBUG_INFO, ("%s: Action = %d Mode = %d CalItem = %d\n", __FUNCTION__, Action, Mode, CalItem)); + + msg = AndesAllocCmdMsg(pAd, sizeof(TestCtrl)); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_RF_TEST, TRUE, 0, + TRUE, TRUE, 8, NULL, EventExtCmdResult); + + memset(&TestCtrl, 0x00, sizeof(TestCtrl)); + + TestCtrl.ucAction = Action; + TestCtrl.u.u4OpMode = cpu2le32((UINT32)Mode); + + if (Action == ACTION_IN_RFTEST) { + /* set Cal Items */ + TestCtrl.u.rRfATInfo.u4FuncIndex = cpu2le32(1); + TestCtrl.u.rRfATInfo.u4FuncData = cpu2le32((UINT32)CalItem); + } + + AndesAppendCmdMsg(msg, (char *)&TestCtrl, sizeof(TestCtrl)); + + ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; + +} + +INT32 CmdRadioOnOffCtrl(RTMP_ADAPTER *pAd, UINT8 On) +{ + struct cmd_msg *msg; + struct _EXT_CMD_RADIO_ON_OFF_CTRL_T RadioOnOffCtrl; + INT32 ret = 0; + + DBGPRINT(RT_DEBUG_INFO, ("%s: On = %d\n", __FUNCTION__, On)); + + msg = AndesAllocCmdMsg(pAd, sizeof(RadioOnOffCtrl)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_RADIO_ON_OFF_CTRL, TRUE, 0, + TRUE, TRUE, 8, NULL, EventExtCmdResult); + + memset(&RadioOnOffCtrl, 0x00, sizeof(RadioOnOffCtrl)); + + if (On == WIFI_RADIO_ON) + RadioOnOffCtrl.ucWiFiRadioCtrl = WIFI_RADIO_ON; + else if (On == WIFI_RADIO_OFF) + RadioOnOffCtrl.ucWiFiRadioCtrl = WIFI_RADIO_OFF; + else + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknown state On = %d\n", __FUNCTION__, On)); + + AndesAppendCmdMsg(msg, (char *)&RadioOnOffCtrl, sizeof(RadioOnOffCtrl)); + + ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + + +INT32 CmdWiFiRxDisable(RTMP_ADAPTER *pAd, UINT RxDisable) +{ + struct cmd_msg *msg; + struct _EXT_CMD_WIFI_RX_DISABLE_T WiFiRxDisable; + INT32 ret = 0; + + DBGPRINT(RT_DEBUG_INFO, ("%s: WiFiRxDisable = %d\n", __FUNCTION__, RxDisable)); + + if (RxDisable != WIFI_RX_DISABLE) + { + DBGPRINT(RT_DEBUG_ERROR, ("Error: %s: RxDisable = %d\n", __FUNCTION__, RxDisable)); + return ret; + } + + msg = AndesAllocCmdMsg(pAd, sizeof(WiFiRxDisable)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_WIFI_RX_DISABLE, TRUE, 0, + TRUE, TRUE, 8, NULL, EventExtCmdResult); + + memset(&WiFiRxDisable, 0x00, sizeof(WiFiRxDisable)); + + WiFiRxDisable.ucWiFiRxDisableCtrl = RxDisable; + + AndesAppendCmdMsg(msg, (char *)&WiFiRxDisable, sizeof(WiFiRxDisable)); + + ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + + +//NoA +INT32 CmdP2pNoaOffloadCtrl(RTMP_ADAPTER *ad, UINT8 enable) +{ + struct cmd_msg *msg; + struct _EXT_CMD_NOA_CTRL_T extCmdNoaCtrl; + int ret = 0; + + msg = AndesAllocCmdMsg(ad, sizeof(struct _EXT_CMD_NOA_CTRL_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_NOA_OFFLOAD_CTRL, + TRUE, 0, TRUE, TRUE, + sizeof(struct _EXT_CMD_NOA_CTRL_T), NULL, EventExtCmdResult); + + NdisZeroMemory(&extCmdNoaCtrl, sizeof(extCmdNoaCtrl)); + + extCmdNoaCtrl.ucMode1 = enable; + //extCmdNoaCtrl.ucMode0 = enable; + + AndesAppendCmdMsg(msg, (char *)&extCmdNoaCtrl, sizeof(extCmdNoaCtrl)); + ret = AndesSendCmdMsg(ad, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + +#ifdef SINGLE_SKU_V2 +enum { + SKU_CCK_1_2=0, + SKU_CCK_55_11, + SKU_OFDM_6_9, + SKU_OFDM_12_18, + SKU_OFDM_24_36, + SKU_OFDM_48, + SKU_OFDM_54, + SKU_HT20_0_8, + SKU_HT20_32, + SKU_HT20_1_2_9_10, + SKU_HT20_3_4_11_12, + SKU_HT20_5_13, + SKU_HT20_6_14, + SKU_HT20_7_15, + SKU_HT40_0_8, + SKU_HT40_32, + SKU_HT40_1_2_9_10, + SKU_HT40_3_4_11_12, + SKU_HT40_5_13, + SKU_HT40_6_14, + SKU_HT40_7_15, +}; +static VOID mt_FillSkuParameter(RTMP_ADAPTER *pAd,UINT8 channel,UINT8 *txPowerSku) +{ + CH_POWER *ch, *ch_temp; + UCHAR start_ch; + //UCHAR base_pwr = pAd->DefaultTargetPwr; + UINT8 j; + + DlListForEachSafe(ch, ch_temp, &pAd->SingleSkuPwrList, CH_POWER, List) + { + start_ch = ch->StartChannel; + if ( channel >= start_ch ) + { + for ( j = 0; j < ch->num; j++ ) + { + if ( channel == ch->Channel[j] ) + { + + txPowerSku[SKU_CCK_1_2] = ch->PwrCCK[0] ? ch->PwrCCK[0] : 0xff; + txPowerSku[SKU_CCK_55_11] = ch->PwrCCK[2] ? ch->PwrCCK[2] : 0xff; + txPowerSku[SKU_OFDM_6_9] = ch->PwrOFDM[0] ? ch->PwrOFDM[0] : 0xff; + txPowerSku[SKU_OFDM_12_18]= ch->PwrOFDM[2] ? ch->PwrOFDM[2] : 0xff; + txPowerSku[SKU_OFDM_24_36]= ch->PwrOFDM[4] ? ch->PwrOFDM[4] : 0xff; + txPowerSku[SKU_OFDM_48] = ch->PwrOFDM[6] ? ch->PwrOFDM[6] : 0xff; + txPowerSku[SKU_OFDM_54] = ch->PwrOFDM[7] ? ch->PwrOFDM[7] : 0xff; + txPowerSku[SKU_HT20_0_8] = ch->PwrHT20[0] ? ch->PwrHT20[0] : 0xff; + txPowerSku[SKU_HT20_32] = 0xff; + txPowerSku[SKU_HT20_1_2_9_10] = ch->PwrHT20[1] ? ch->PwrHT20[1] : 0xff; + txPowerSku[SKU_HT20_3_4_11_12] = ch->PwrHT20[3] ? ch->PwrHT20[3] : 0xff; + txPowerSku[SKU_HT20_5_13] = ch->PwrHT20[5] ? ch->PwrHT20[5] : 0xff; + txPowerSku[SKU_HT20_6_14] = ch->PwrHT20[6] ? ch->PwrHT20[6] : 0xff; + txPowerSku[SKU_HT20_7_15] = ch->PwrHT20[7] ? ch->PwrHT20[7] : 0xff; + txPowerSku[SKU_HT40_0_8] = ch->PwrHT40[0] ? ch->PwrHT40[0] : 0xff; + txPowerSku[SKU_HT40_32] = 0xff; + txPowerSku[SKU_HT40_1_2_9_10] = ch->PwrHT40[1] ? ch->PwrHT40[1] : 0xff; + txPowerSku[SKU_HT40_3_4_11_12] = ch->PwrHT40[3] ? ch->PwrHT40[3] : 0xff; + txPowerSku[SKU_HT40_5_13] = ch->PwrHT40[5] ? ch->PwrHT40[5] : 0xff; + txPowerSku[SKU_HT40_6_14] = ch->PwrHT40[6] ? ch->PwrHT40[6] : 0xff; + txPowerSku[SKU_HT40_7_15] = ch->PwrHT40[7] ? ch->PwrHT40[7] : 0xff; + break; + } + } + } + } +} +#endif + +INT32 CmdChannelSwitch(RTMP_ADAPTER *pAd, UINT8 control_chl, UINT8 central_chl, + UINT8 BW, UINT8 TXStream, UINT8 RXStream) +{ + struct cmd_msg *msg; + struct _EXT_CMD_CHAN_SWITCH_T CmdChanSwitch; + INT32 ret = 0,i=0; +#ifdef RTMP_SDIO_SUPPORT + return 0; +#endif /*leonardo for SDIO FPGA pass*/ + + if (central_chl == 0) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: central channel = 0 is invalid\n", __FUNCTION__)); + return -1; + } + +#ifdef WH_EZ_SETUP + if(IS_ADPTR_EZ_SETUP_ENABLED(pAd)){ + EZ_DEBUG(DBG_CAT_FW, DBG_SUBCAT_ALL, DBG_LVL_ERROR, + ("control_chl = %d\n", control_chl)); + } + else +#endif + { + DBGPRINT(RT_DEBUG_INFO, ("%s: control_chl = %d, central_chl = %d, BW = %d, \ + TXStream = %d, RXStream = %d\n", __FUNCTION__, \ + control_chl, central_chl, BW, TXStream, RXStream)); + } + msg = AndesAllocCmdMsg(pAd, sizeof(CmdChanSwitch)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_CHANNEL_SWITCH, TRUE, 0, + TRUE, TRUE, 8, NULL, EventExtCmdResult); + + memset(&CmdChanSwitch, 0x00, sizeof(CmdChanSwitch)); + + CmdChanSwitch.ucCtrlCh = control_chl; + CmdChanSwitch.ucCentralCh = central_chl; + CmdChanSwitch.ucBW = BW; + CmdChanSwitch.ucTxStreamNum = TXStream; + CmdChanSwitch.ucRxStreamNum = RXStream; + + for(i=0;iSKUEn) + mt_FillSkuParameter(pAd,central_chl,CmdChanSwitch.aucTxPowerSKU); +#endif + AndesAppendCmdMsg(msg, (char *)&CmdChanSwitch, sizeof(CmdChanSwitch)); + + ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + + +INT32 CmdFlushFrameByWlanIdx(RTMP_ADAPTER *pAd, UINT8 WlanIdx) +{ + struct cmd_msg *msg; + EXT_CMD_FLUSH_FRAME_BY_WCID_INFO_T CmdFlushFrameByWcid; + INT32 ret=0; + + msg = AndesAllocCmdMsg(pAd, sizeof(CmdFlushFrameByWcid)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_QUERY, EXT_CMD_FLUSH_FRAME_WCID, + FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + memset(&CmdFlushFrameByWcid, 0x00, sizeof(CmdFlushFrameByWcid)); + CmdFlushFrameByWcid.ucWlanIdx = WlanIdx; + + AndesAppendCmdMsg(msg, (char *)&CmdFlushFrameByWcid, sizeof(CmdFlushFrameByWcid)); + + ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_OFF, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + +static VOID EventExtNicCapability(struct cmd_msg *msg, char *Data, UINT16 Len) +{ + struct _EXT_EVENT_NIC_CAPABILITY_T *ExtEventNicCapability = (EXT_EVENT_NIC_CAPABILITY *)Data; + UINT32 Loop; + + DBGPRINT(RT_DEBUG_OFF, ("The data code of firmware:")); + + for (Loop = 0; Loop < 16; Loop++) + { + DBGPRINT(RT_DEBUG_OFF, ("%c", ExtEventNicCapability->aucDateCode[Loop])); + } + + DBGPRINT(RT_DEBUG_OFF, ("\nThe version code of firmware:")); + + for (Loop = 0; Loop < 12; Loop++) + { + DBGPRINT(RT_DEBUG_OFF, ("%c", ExtEventNicCapability->aucVersionCode[Loop])); + } +} + + +INT32 CmdNicCapability(RTMP_ADAPTER *pAd) +{ + struct cmd_msg *msg; + INT32 ret = 0; + + msg = AndesAllocCmdMsg(pAd, 0); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_QUERY, EXT_CMD_NIC_CAPABILITY, TRUE, 0, + TRUE, TRUE, 28, NULL, EventExtNicCapability); + + ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + + +INT32 CmdFwLog2Host(RTMP_ADAPTER *pAd, UINT8 FWLog2HostCtrl) +{ + + struct cmd_msg *msg; + INT32 Ret = 0; + EXT_CMD_FW_LOG_2_HOST_CTRL_T CmdFwLog2HostCtrl; + + msg = AndesAllocCmdMsg(pAd, sizeof(CmdFwLog2HostCtrl)); + + if (!msg) + { + Ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_QUERY, EXT_CMD_FW_LOG_2_HOST, + FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + memset(&CmdFwLog2HostCtrl, 0x00, sizeof(CmdFwLog2HostCtrl)); + + CmdFwLog2HostCtrl.ucFwLog2HostCtrl = FWLog2HostCtrl; + + AndesAppendCmdMsg(msg, (char *)&CmdFwLog2HostCtrl, + sizeof(CmdFwLog2HostCtrl)); + + Ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, Ret)); + return Ret; +} + +#ifdef BCN_OFFLOAD_SUPPORT +static VOID ExtEventBcnUpdateHandler(RTMP_ADAPTER *pAd, UINT8 *Data, UINT32 Length) +{ + if ((RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_RESET_IN_PROGRESS)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_BULKOUT_RESET)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS)) || + (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST))) + { + return; + } + + RTMP_UPDATE_BCN(pAd); +} +#endif + +#ifdef THERMAL_PROTECT_SUPPORT +static VOID EventThermalProtect(RTMP_ADAPTER *pAd, UINT8 *Data, UINT32 Length) +{ + EXT_EVENT_THERMAL_PROTECT_T *EvtThermalProtect; + UINT8 HLType; + UINT32 ret; + + EvtThermalProtect = (EXT_EVENT_THERMAL_PROTECT_T *)Data; + + HLType = EvtThermalProtect->ucHLType; + pAd->last_thermal_pro_temp = EvtThermalProtect->cCurrentTemp; + + DBGPRINT(RT_DEBUG_OFF, ("%s: HLType = %d, CurrentTemp = %d\n", __FUNCTION__, HLType, pAd->last_thermal_pro_temp)); + + RTMP_SEM_EVENT_WAIT(&pAd->AutoRateLock, ret); + if (HLType == HIGH_TEMP_THD) + { + pAd->force_one_tx_stream = TRUE; + DBGPRINT(RT_DEBUG_OFF, ("Switch TX to 1 stram\n")); + } + else + { + DBGPRINT(RT_DEBUG_OFF, ("Switch TX to 2 stram\n")); + pAd->force_one_tx_stream = FALSE; + } + + pAd->fgThermalProtectToggle = TRUE; + + RTMP_SEM_EVENT_UP(&pAd->AutoRateLock); +} + + +INT32 CmdThermalProtect(RTMP_ADAPTER *ad, UINT8 HighEn, CHAR HighTempTh, UINT8 LowEn, CHAR LowTempTh) +{ + struct cmd_msg *msg; + INT32 ret = 0; + EXT_CMD_THERMAL_PROTECT_T ThermalProtect; + + msg = AndesAllocCmdMsg(ad, sizeof(EXT_CMD_THERMAL_PROTECT_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_THERMAL_PROTECT, TRUE, 0, TRUE, TRUE, 8, NULL, EventExtCmdResult); + + NdisZeroMemory(&ThermalProtect, sizeof(ThermalProtect)); + + ThermalProtect.ucHighEnable = HighEn; + ThermalProtect.cHighTempThreshold = HighTempTh; + ThermalProtect.ucLowEnable = LowEn; + ThermalProtect.cLowTempThreshold = LowTempTh; + + ad->thermal_pro_high_criteria = HighTempTh; + ad->thermal_pro_high_en = HighEn; + ad->thermal_pro_low_criteria = LowTempTh; + ad->thermal_pro_low_en = LowEn; + + AndesAppendCmdMsg(msg, (char *)&ThermalProtect, sizeof(ThermalProtect)); + ret = AndesSendCmdMsg(ad, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} +#endif + +#ifdef BCN_OFFLOAD_SUPPORT +/***************************************** + ExT_CID = 0x33 +*****************************************/ +INT32 CmdBcnUpdateSet(RTMP_ADAPTER *pAd, CMD_BCN_UPDATE_T bcn_update) +{ + struct cmd_msg *msg; + INT32 ret=0,size=0; + + size = sizeof(CMD_BCN_UPDATE_T); + + msg = AndesAllocCmdMsg(pAd, size); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_BCN_UPDATE, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + AndesAppendCmdMsg(msg, (char *)&bcn_update, size); + + ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_OFF, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} +#endif + +#define TOP_MISC2 0x1134 +#define SW_SYN0 0x81021250 +static NDIS_STATUS AndesMTLoadFwMethod1(RTMP_ADAPTER *ad) +{ + UINT32 value, loop, dl_len; + UINT32 ret = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; +#ifdef RTMP_PCI_SUPPORT + POS_COOKIE obj = (POS_COOKIE)ad->OS_Cookie; +#endif /* RTMP_PCI_SUPPORT */ + struct MCU_CTRL *Ctl = &ad->MCUCtrl; +#ifdef RTMP_PCI_SUPPORT + UINT32 RemapBase, RemapOffset; + UINT32 RestoreValue; +#endif + + if (cap->load_code_method == BIN_FILE_METHOD) { + DBGPRINT(RT_DEBUG_OFF, ("load fw image from /lib/firmware/%s\n", cap->fw_bin_file_name)); +#ifdef RTMP_PCI_SUPPORT + OS_LOAD_CODE_FROM_BIN(&cap->FWImageName, cap->fw_bin_file_name, obj->pci_dev, &cap->fw_len); +#endif + } else { + cap->FWImageName = cap->fw_header_image; + } + + if (!cap->FWImageName) { + if (cap->load_code_method == BIN_FILE_METHOD) { + DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a fw image(/lib/firmware/%s), load_method(%d)\n", __FUNCTION__, cap->fw_bin_file_name, cap->load_code_method)); + } else { + DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a fw image, load_method(%d)\n", + __FUNCTION__, cap->load_code_method)); + } + ret = NDIS_STATUS_FAILURE; + goto done; + } + + Ctl->Stage = FW_DOWNLOAD; + + DBGPRINT(RT_DEBUG_OFF, ("FW Version:")); + for (loop = 0; loop < 10; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->FWImageName + cap->fw_len - 29 + loop))); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("FW Build Date:")); + for (loop = 0; loop < 15; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->FWImageName + cap->fw_len - 19 + loop))); + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + dl_len = (*(cap->FWImageName + cap->fw_len - 1) << 24) | + (*(cap->FWImageName + cap->fw_len - 2) << 16) | + (*(cap->FWImageName + cap->fw_len -3) << 8) | + *(cap->FWImageName + cap->fw_len - 4); + + dl_len += 4; /* including crc value */ + + DBGPRINT(RT_DEBUG_INFO, ("\ndownload len = %d\n", dl_len)); + +#ifdef RTMP_PCI_SUPPORT + if (IS_MT7603(ad)) + { + RTMP_IO_READ32(ad, MCU_PCIE_REMAP_1, &RestoreValue); + RemapBase = GET_REMAP_1_BASE(0x50012498) << 18; + RemapOffset = GET_REMAP_1_OFFSET(0x50012498); + RTMP_IO_WRITE32(ad, MCU_PCIE_REMAP_1, RemapBase); + RTMP_IO_WRITE32(ad, 0x40000 + RemapOffset, 0x5); + RTMP_IO_WRITE32(ad, 0x40000 + RemapOffset, 0x5); + RtmpusecDelay(1); + RTMP_IO_WRITE32(ad, MCU_PCIE_REMAP_1, RestoreValue); + } +#endif + +#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT) + /* switch to bypass mode */ + RTMP_IO_READ32(ad, SCH_REG4, &value); + value &= ~SCH_REG4_BYPASS_MODE_MASK; + value |= SCH_REG4_BYPASS_MODE(1); + +#ifdef RTMP_PCI_SUPPORT + value &= ~SCH_REG4_FORCE_QID_MASK; + value |= SCH_REG4_FORCE_QID(5); +#endif + + + RTMP_IO_WRITE32(ad, SCH_REG4, value); +#endif + + /* optional CMD procedure */ + /* CMD restart download flow request */ + RTMP_IO_READ32(ad, TOP_MISC2, &value); + DBGPRINT(RT_DEBUG_INFO, ("TOP_MSIC = %x\n", value)); + + /* check ram code if running, if it is, need to do optional cmd procedure */ + if ((value & 0x02) == 0x02) { + +#ifdef LOAD_FW_ONE_TIME + ret = NDIS_STATUS_SUCCESS; + Ctl->Stage = FW_RUN_TIME; + ad->FWLoad = 1; + goto done; +#else /* LOAD_FW_ONE_TIME */ + ret = CmdRestartDLReq(ad); + + if (ret) + goto done; +#endif /* !LOAD_FW_ONE_TIME */ + } + + /* check rom code if ready */ + loop = 0; + + do + { + RTMP_IO_READ32(ad, TOP_MISC2, &value); + if((value & 0x01) == 0x01 && !(value & 0x02)) + break; + RtmpOsMsDelay(1); + loop++; + } while (loop <= 500); + + if (loop > 500) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: rom code is not ready(TOP_MISC2 = %d)\n", __FUNCTION__, value)); + goto done; + } + + /* standard CMD procedure */ + /* 1. Config PDA phase */ + ret = CmdAddressLenReq(ad, FW_CODE_START_ADDRESS1, dl_len, TARGET_ADDR_LEN_NEED_RSP); + + if (ret) + goto done; + + /* 2. Loading firmware image phase */ + ret = CmdFwScatters(ad, cap->FWImageName, dl_len); + + if (ret) + goto done; + + /* 3. Firmware start negotiation phase */ + ret = CmdFwStartReq(ad, 1, FW_CODE_START_ADDRESS1); + + /* 4. check Firmware running */ + for (loop = 0; loop < 500; loop++) + { + RTMP_IO_READ32(ad, TOP_MISC2, &value); + DBGPRINT(RT_DEBUG_INFO, ("TOP_MSIC = %x\n", value)); + if ((value & 0x02) == 0x02) + break; + + RtmpOsMsDelay(1); + } + + if (loop == 500) + { + ret = NDIS_STATUS_FAILURE; + DBGPRINT(RT_DEBUG_OFF, ("firmware loading failure\n")); + Ctl->Stage = FW_NO_INIT; + } + else + { + Ctl->Stage = FW_RUN_TIME; + } + +done: + +#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT) + /* Switch to normal mode */ + RTMP_IO_READ32(ad, SCH_REG4, &value); + value &= ~SCH_REG4_BYPASS_MODE_MASK; + value |= SCH_REG4_BYPASS_MODE(0); + value &= ~SCH_REG4_FORCE_QID_MASK; + value |= SCH_REG4_FORCE_QID(0); + RTMP_IO_WRITE32(ad, SCH_REG4, value); + + RTMP_IO_READ32(ad, SCH_REG4, &value); + value |= (1 << 8); + RTMP_IO_WRITE32(ad, SCH_REG4, value); + RTMP_IO_READ32(ad, SCH_REG4, &value); + value &= ~(1 << 8); + RTMP_IO_WRITE32(ad, SCH_REG4, value); +#endif + + return ret; +} + + +static NDIS_STATUS AndesMTLoadFwMethod2(RTMP_ADAPTER *ad) +{ + UINT32 value, loop, ilm_dl_len, dlm_dl_len; + UINT8 ilm_feature_set, dlm_feature_set; + UINT8 ilm_chip_info, dlm_chip_info; + UINT32 ilm_target_addr, dlm_target_addr; + UINT32 ret = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; +#ifdef RTMP_PCI_SUPPORT + POS_COOKIE obj = (POS_COOKIE)ad->OS_Cookie; +#endif /* RTMP_PCI_SUPPORT */ + struct MCU_CTRL *Ctl = &ad->MCUCtrl; + + if (cap->load_code_method == BIN_FILE_METHOD) { + DBGPRINT(RT_DEBUG_OFF, ("load fw image from /lib/firmware/%s\n", cap->fw_bin_file_name)); +#ifdef RTMP_PCI_SUPPORT + OS_LOAD_CODE_FROM_BIN(&cap->FWImageName, cap->fw_bin_file_name, obj->pci_dev, &cap->fw_len); +#endif + } else { + cap->FWImageName = cap->fw_header_image; + } + + if (!cap->FWImageName) { + if (cap->load_code_method == BIN_FILE_METHOD) { + DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a fw image(/lib/firmware/%s), load_method(%d)\n", __FUNCTION__, cap->fw_bin_file_name, cap->load_code_method)); + } else { + DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a fw image, load_method(%d)\n", + __FUNCTION__, cap->load_code_method)); + } + ret = NDIS_STATUS_FAILURE; + goto done; + } + + Ctl->Stage = FW_DOWNLOAD; + + ilm_target_addr = (*(cap->FWImageName + cap->fw_len - (33 + 36)) << 24) | + (*(cap->FWImageName + cap->fw_len - (34 + 36)) << 16) | + (*(cap->FWImageName + cap->fw_len -(35 + 36)) << 8) | + *(cap->FWImageName + cap->fw_len - (36 + 36)); + + DBGPRINT(RT_DEBUG_TRACE, ("ILM target address = %x\n", ilm_target_addr)); + + ilm_chip_info = *(cap->FWImageName + cap->fw_len - (32 + 36)); + DBGPRINT(RT_DEBUG_TRACE, ("\nILM chip information = %x\n", ilm_chip_info)); + + ilm_feature_set = *(cap->FWImageName + cap->fw_len - (31 + 36)); + DBGPRINT(RT_DEBUG_TRACE, ("\nILM feature set = %x\n", ilm_feature_set)); + + DBGPRINT(RT_DEBUG_TRACE, ("\nILM Build Date:")); + + for (loop = 0; loop < 8; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->FWImageName + cap->fw_len - (20 + 36) + loop))); + + ilm_dl_len = (*(cap->FWImageName + cap->fw_len - (1 + 36)) << 24) | + (*(cap->FWImageName + cap->fw_len - (2 + 36)) << 16) | + (*(cap->FWImageName + cap->fw_len -(3 + 36)) << 8) | + *(cap->FWImageName + cap->fw_len - (4 + 36)); + + ilm_dl_len += 4; /* including crc value */ + + DBGPRINT(RT_DEBUG_TRACE, ("\nILM download len = %d\n", ilm_dl_len)); + + dlm_target_addr = (*(cap->FWImageName + cap->fw_len - 33) << 24) | + (*(cap->FWImageName + cap->fw_len - 34) << 16) | + (*(cap->FWImageName + cap->fw_len - 35) << 8) | + *(cap->FWImageName + cap->fw_len - 36); + + DBGPRINT(RT_DEBUG_TRACE, ("DLM target address = %x\n", dlm_target_addr)); + + dlm_chip_info = *(cap->FWImageName + cap->fw_len - 32); + DBGPRINT(RT_DEBUG_TRACE, ("\nDLM chip information = %x\n", dlm_chip_info)); + + dlm_feature_set = *(cap->FWImageName + cap->fw_len - 31); + DBGPRINT(RT_DEBUG_TRACE, ("\nDLM feature set = %x\n", dlm_feature_set)); + + DBGPRINT(RT_DEBUG_TRACE, ("DLM Build Date:")); + + for (loop = 0; loop < 8; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->FWImageName + cap->fw_len - 20 + loop))); + + dlm_dl_len = (*(cap->FWImageName + cap->fw_len - 1) << 24) | + (*(cap->FWImageName + cap->fw_len - 2) << 16) | + (*(cap->FWImageName + cap->fw_len - 3) << 8) | + *(cap->FWImageName + cap->fw_len - 4); + + dlm_dl_len += 4; /* including crc value */ + + DBGPRINT(RT_DEBUG_TRACE, ("\nDLM download len = %d\n", dlm_dl_len)); + +#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT) + /* switch to bypass mode */ + RTMP_IO_READ32(ad, SCH_REG4, &value); + value &= ~SCH_REG4_BYPASS_MODE_MASK; + value |= SCH_REG4_BYPASS_MODE(1); + +#ifdef RTMP_PCI_SUPPORT + value &= ~SCH_REG4_FORCE_QID_MASK; + value |= SCH_REG4_FORCE_QID(5); +#endif + + + RTMP_IO_WRITE32(ad, SCH_REG4, value); +#endif + + /* optional CMD procedure */ + /* CMD restart download flow request */ +#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT) + RTMP_IO_READ32(ad, SW_SYN0, &value); + DBGPRINT(RT_DEBUG_TRACE, ("SW_SYN0 = %x\n", value)); + + /* check ram code if running, if it is, need to do optional cmd procedure */ + if ((value & 0x03) == 0x03) { + ret = CmdRestartDLReq(ad); + + if (ret) + goto done; + } + + /* check rom code if ready */ + loop = 0; + + do + { + RTMP_IO_READ32(ad, SW_SYN0, &value); + if ((value & 0x01) == 0x01) + break; + RtmpOsMsDelay(1); + loop++; + } while (loop <= 500); + + if (loop > 500) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: rom code is not ready(SW_SYN0 = %d)\n", __FUNCTION__, value)); + goto done; + } +#endif + + /* ILM */ + /* standard CMD procedure */ + /* 1. Config PDA phase */ + ret = CmdAddressLenReq(ad, ilm_target_addr, ilm_dl_len, + (ilm_feature_set & FW_FEATURE_SET_ENCRY) | + (FW_FEATURE_SET_KEY(GET_FEATURE_SET_KEY(ilm_feature_set))) | + ((ilm_feature_set & FW_FEATURE_SET_ENCRY) ? FW_FEATURE_RESET_IV: 0) | + TARGET_ADDR_LEN_NEED_RSP); + + if (ret) + goto done; + + + /* 2. Loading ilm firmware image phase */ + ret = CmdFwScatters(ad, cap->FWImageName, ilm_dl_len); + + if (ret) + goto done; + + /* DLM */ + /* standard CMD procedure */ + /* 1. Config PDA phase */ + ret = CmdAddressLenReq(ad, dlm_target_addr, dlm_dl_len, + (dlm_feature_set & FW_FEATURE_SET_ENCRY) | + (FW_FEATURE_SET_KEY(GET_FEATURE_SET_KEY(dlm_feature_set))) | + ((dlm_feature_set & FW_FEATURE_SET_ENCRY) ? FW_FEATURE_RESET_IV: 0) | + TARGET_ADDR_LEN_NEED_RSP); + + if (ret) + goto done; + + /* 2. Loading dlm firmware image phase */ + ret = CmdFwScatters(ad, cap->FWImageName + ilm_dl_len, dlm_dl_len); + + if (ret) + goto done; + + /* 3. Firmware start negotiation phase */ + ret = CmdFwStartReq(ad, 0, 0); + + +#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT) + /* 4. check Firmware running */ + for (loop = 0; loop < 500; loop++) + { + RTMP_IO_READ32(ad, SW_SYN0, &value); + DBGPRINT(RT_DEBUG_TRACE, ("SW_SYN0 = %x\n", value)); + if ((value & 0x03) == 0x03) + break; + + RtmpOsMsDelay(1); + } + + if (loop == 500) + { + ret = NDIS_STATUS_FAILURE; + DBGPRINT(RT_DEBUG_OFF, ("firmware loading failure\n")); + Ctl->Stage = FW_NO_INIT; + } + else + { + + Ctl->Stage = FW_RUN_TIME; + } +#endif +#ifdef RTMP_SDIO_SUPPORT + + RtmpOsMsDelay(1000); + Ctl->Stage = FW_RUN_TIME; + + printk("%s: &pAd->MCUCtrl=%p\n",__FUNCTION__,Ctl); + printk("%s(): findish download fw ya! \n", __FUNCTION__); +#endif + + +done: + +#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT) + /* Switch to normal mode */ + RTMP_IO_READ32(ad, SCH_REG4, &value); + value &= ~SCH_REG4_BYPASS_MODE_MASK; + value |= SCH_REG4_BYPASS_MODE(0); + value &= ~SCH_REG4_FORCE_QID_MASK; + value |= SCH_REG4_FORCE_QID(0); + RTMP_IO_WRITE32(ad, SCH_REG4, value); + + RTMP_IO_READ32(ad, SCH_REG4, &value); + value |= (1 << 8); + RTMP_IO_WRITE32(ad, SCH_REG4, value); + RTMP_IO_READ32(ad, SCH_REG4, &value); + value &= ~(1 << 8); + RTMP_IO_WRITE32(ad, SCH_REG4, value); +#endif + + return ret; +} + + +NDIS_STATUS AndesMTLoadFw(RTMP_ADAPTER *pAd) +{ + UINT32 Ret; + RTMP_CHIP_CAP *Cap = &pAd->chipCap; + + if (Cap->DownLoadType == DownLoadTypeA) + { + Ret = AndesMTLoadFwMethod1(pAd); + } + else if (Cap->DownLoadType == DownLoadTypeB) + { + Ret = AndesMTLoadFwMethod2(pAd); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("%s: Unknow Download type(%d)\n", __FUNCTION__, Cap->DownLoadType)); + Ret = -1; + } + + return Ret; +} + + +NDIS_STATUS AndesMTLoadRomPatch(RTMP_ADAPTER *ad) +{ + UINT32 value, loop; + UINT32 ret; + RTMP_CHIP_CAP *cap = &ad->chipCap; + RTMP_CHIP_OP *pChipOps = &ad->chipOps; + //POS_COOKIE obj = (POS_COOKIE)ad->OS_Cookie; + struct MCU_CTRL *Ctl = &ad->MCUCtrl; + UINT32 patch_len = 0, total_checksum = 0; + + if (cap->load_code_method == BIN_FILE_METHOD) { + DBGPRINT(RT_DEBUG_OFF, ("load fw image from /lib/firmware/%s\n", cap->fw_bin_file_name)); + DBGPRINT(RT_DEBUG_ERROR, ("%s:Not support now(/lib/firmware/%s), load_method(%d)\n", __FUNCTION__, cap->rom_patch_bin_file_name, cap->load_code_method)); + } else { + cap->rom_patch = cap->rom_patch_header_image; + } + + if (!cap->rom_patch) { + if (cap->load_code_method == BIN_FILE_METHOD) { + DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a fw image(/lib/firmware/%s), load_method(%d)\n", __FUNCTION__, cap->fw_bin_file_name, cap->load_code_method)); + } else { + DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a fw image, load_method(%d)\n", + __FUNCTION__, cap->load_code_method)); + } + ret = NDIS_STATUS_FAILURE; + goto done; + } + + Ctl->Stage = ROM_PATCH_DOWNLOAD; + + DBGPRINT(RT_DEBUG_TRACE, ("Build Date:")); + + for (loop = 0; loop < 16; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->rom_patch + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("platform = \n")); + + for (loop = 0; loop < 4; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->rom_patch + 16 + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("hw/sw version = \n")); + + for (loop = 0; loop < 4; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%02x", *(cap->rom_patch + 20 + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("patch version = \n")); + + for (loop = 0; loop < 4; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%02x", *(cap->rom_patch + 24 + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + total_checksum = *(cap->rom_patch + 28) | (*(cap->rom_patch + 29) << 8); + + patch_len = cap->rom_patch_len - PATCH_INFO_SIZE; + + DBGPRINT(RT_DEBUG_INFO, ("\ndownload len = %d\n", patch_len)); + +#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT) + /* switch to bypass mode */ + RTMP_IO_READ32(ad, SCH_REG4, &value); + value &= ~SCH_REG4_BYPASS_MODE_MASK; + value |= SCH_REG4_BYPASS_MODE(1); + RTMP_IO_WRITE32(ad, SCH_REG4, value); +#endif + + + /* standard CMD procedure */ + /* 1. Config PDA phase */ + ret = CmdAddressLenReq(ad, ROM_PATCH_START_ADDRESS, patch_len, TARGET_ADDR_LEN_NEED_RSP); + + if (ret) + goto done; + + /* 2. Loading rom patch image phase */ + ret = CmdFwScatters(ad, cap->rom_patch + PATCH_INFO_SIZE, patch_len); + + if (ret) + goto done; + + /* 3. ROM patch start negotiation phase */ + ret = CmdPatchFinishReq(ad); + + DBGPRINT(RT_DEBUG_OFF, ("Send checksum req..\n")); + + pChipOps->AndesMTChkCrc(ad, patch_len); + + RtmpOsMsDelay(20); + + if (total_checksum != pChipOps->AndesMTGetCrc(ad)) { + DBGPRINT(RT_DEBUG_OFF, ("checksum fail!, local(0x%x) <> fw(0x%x)\n", total_checksum, + pChipOps->AndesMTGetCrc(ad))); + + ret = NDIS_STATUS_FAILURE; + } + + DBGPRINT(RT_DEBUG_OFF, ("checksum=0x%x\n", pChipOps->AndesMTGetCrc(ad))); + + +done: + +#if defined(RTMP_PCI_SUPPORT) || defined(RTMP_USB_SUPPORT) + /* Switch to normal mode */ + RTMP_IO_READ32(ad, SCH_REG4, &value); + value &= ~SCH_REG4_BYPASS_MODE_MASK; + value |= SCH_REG4_BYPASS_MODE(0); + value &= ~SCH_REG4_FORCE_QID_MASK; + value |= SCH_REG4_FORCE_QID(0); + RTMP_IO_WRITE32(ad, SCH_REG4, value); + + RTMP_IO_READ32(ad, SCH_REG4, &value); + value |= (1 << 8); + RTMP_IO_WRITE32(ad, SCH_REG4, value); + RTMP_IO_READ32(ad, SCH_REG4, &value); + value &= ~(1 << 8); + RTMP_IO_WRITE32(ad, SCH_REG4, value); +#endif + + return ret; +} + + +INT32 AndesMTEraseFw(RTMP_ADAPTER *pAd) +{ + RTMP_CHIP_CAP *cap = &pAd->chipCap; + + if (cap->load_code_method == BIN_FILE_METHOD) { + + if (cap->FWImageName) { + os_free_mem(NULL, cap->FWImageName); + cap->FWImageName = NULL; + } + } + + return 0; +} + + +static VOID EventChPrivilegeHandler(RTMP_ADAPTER *pAd, UINT8 *Data, UINT32 Length) +{ + //struct cmd_msg *msg, *msg_tmp; + struct MCU_CTRL *ctl = &pAd->MCUCtrl; + UINT32 Value; + + if (IS_MT7603(pAd) || IS_MT7628(pAd)) + { + RTMP_IO_READ32(pAd, RMAC_RMCR, &Value); + + if (ctl->RxStream0 == 1) + Value |= RMAC_RMCR_RX_STREAM_0; + else + Value &= ~RMAC_RMCR_RX_STREAM_0; + + if (ctl->RxStream1 == 1) + Value |= RMAC_RMCR_RX_STREAM_1; + else + Value &= ~RMAC_RMCR_RX_STREAM_1; + + RTMP_IO_WRITE32(pAd, RMAC_RMCR, Value); + } + + DBGPRINT(RT_DEBUG_INFO, ("%s\n", __FUNCTION__)); +} + + +static VOID ExtEventFwLog2HostHandler(RTMP_ADAPTER *pAd, UINT8 *Data, UINT32 Length) +{ + DBGPRINT(RT_DEBUG_TRACE, ("FW LOG: %s\n", Data)); +} + + +static VOID EventExtEventHandler(RTMP_ADAPTER *pAd, UINT8 ExtEID, UINT8 *Data, UINT32 Length) +{ + switch (ExtEID) + { + case EXT_EVENT_CMD_RESULT: + EventExtCmdResultHandler(pAd, Data, Length); + break; + case EXT_EVENT_FW_LOG_2_HOST: + ExtEventFwLog2HostHandler(pAd, Data, Length); + break; +#ifdef MT_PS +#if defined(MT7603) && defined(RTMP_PCI_SUPPORT) + case EXT_CMD_PS_RETRIEVE_START: + CmdPsRetrieveStartRspFromCR(pAd, Data, Length); + break; +#endif /* MT7603 */ +#endif /* MT_PS */ +#ifdef THERMAL_PROTECT_SUPPORT + case EXT_EVENT_THERMAL_PROTECT: + EventThermalProtect(pAd, Data, Length); + break; +#endif +#ifdef BCN_OFFLOAD_SUPPORT + case EXT_EVENT_BCN_UPDATE: + ExtEventBcnUpdateHandler(pAd, Data, Length); + break; +#endif + + default: + DBGPRINT(RT_DEBUG_OFF, ("%s: Unknown Ext Event(%x)\n", __FUNCTION__, + ExtEID)); + break; + } + + +} + + +static VOID UnsolicitedEventHandler(RTMP_ADAPTER *pAd, UINT8 EID, UINT8 ExtEID, UINT8 *Data, UINT32 Length) +{ + switch (EID) + { + case EVENT_CH_PRIVILEGE: + EventChPrivilegeHandler(pAd, Data, Length); + break; + case EXT_EVENT: + EventExtEventHandler(pAd, ExtEID, Data, Length); + break; + default: + DBGPRINT(RT_DEBUG_OFF, ("%s: Unknown Event(%x)\n", __FUNCTION__, EID)); + break; + } +} + + +static VOID AndesMTRxProcessEvent(RTMP_ADAPTER *pAd, struct cmd_msg *rx_msg) +{ + PNDIS_PACKET net_pkt = rx_msg->net_pkt; + struct cmd_msg *msg, *msg_tmp; + EVENT_RXD *event_rxd = (EVENT_RXD *)GET_OS_PKT_DATAPTR(net_pkt); + struct MCU_CTRL *ctl = &pAd->MCUCtrl; +#ifdef RTMP_PCI_SUPPORT + unsigned long flags; +#endif /* RTMP_PCI_SUPPORT */ + //event_rxd->fw_rxd_0.word = le2cpu32(event_rxd->fw_rxd_0.word); + event_rxd->fw_rxd_1.word = le2cpu32(event_rxd->fw_rxd_1.word); + event_rxd->fw_rxd_2.word = le2cpu32(event_rxd->fw_rxd_2.word); + +#ifdef CONFIG_TRACE_SUPPORT + TRACE_MCU_EVENT_INFO(event_rxd->fw_rxd_0.field.length, event_rxd->fw_rxd_0.field.pkt_type_id, + event_rxd->fw_rxd_1.field.eid, event_rxd->fw_rxd_1.field.seq_num, + event_rxd->fw_rxd_2.field.ext_eid, GET_OS_PKT_DATAPTR(net_pkt) + sizeof(*event_rxd), event_rxd->fw_rxd_0.field.length - sizeof(*event_rxd)); +#endif + + + + if ((event_rxd->fw_rxd_1.field.seq_num == 0) || + (event_rxd->fw_rxd_2.field.ext_eid == EXT_EVENT_FW_LOG_2_HOST) || + (event_rxd->fw_rxd_2.field.ext_eid == EXT_EVENT_THERMAL_PROTECT)) { + /* if have callback function */ + UnsolicitedEventHandler(pAd, event_rxd->fw_rxd_1.field.eid, event_rxd->fw_rxd_2.field.ext_eid, GET_OS_PKT_DATAPTR(net_pkt) + sizeof(*event_rxd), + event_rxd->fw_rxd_0.field.length - sizeof(*event_rxd)); + } + else + { +#if defined(RTMP_USB_SUPPORT) || defined(RTMP_SDIO_SUPPORT) + RTMP_SPIN_LOCK_IRQ(&ctl->ackq_lock); +#endif + +#ifdef RTMP_PCI_SUPPORT + RTMP_SPIN_LOCK_IRQSAVE(&ctl->ackq_lock, &flags); +#endif + DlListForEachSafe(msg, msg_tmp, &ctl->ackq, struct cmd_msg, list) { + if (msg->seq == event_rxd->fw_rxd_1.field.seq_num) + { + #if defined(RTMP_USB_SUPPORT) || defined(RTMP_SDIO_SUPPORT) + RTMP_SPIN_UNLOCK_IRQ(&ctl->ackq_lock); +#endif + +#ifdef RTMP_PCI_SUPPORT + RTMP_SPIN_UNLOCK_IRQRESTORE(&ctl->ackq_lock, &flags); +#endif + + if ((event_rxd->fw_rxd_1.field.eid == MT_FW_START_RSP) + || (event_rxd->fw_rxd_1.field.eid == MT_RESTART_DL_RSP) + || (event_rxd->fw_rxd_1.field.eid == MT_TARGET_ADDRESS_LEN_RSP) + || (event_rxd->fw_rxd_1.field.eid == MT_PATCH_SEM_RSP)) { + msg->rsp_handler(msg, (char*)(GET_OS_PKT_DATAPTR(net_pkt) + sizeof(*event_rxd) - 4), + event_rxd->fw_rxd_0.field.length - sizeof(*event_rxd) + 4); + + } + else if ((msg->rsp_payload_len == event_rxd->fw_rxd_0.field.length - sizeof(*event_rxd)) + && (msg->rsp_payload_len != 0)) + { + if (msg->rsp_handler == NULL) + { + DBGPRINT(RT_DEBUG_ERROR, ("%s(): rsp_handler is NULL!!!! (cmd_type = 0x%x, ext_cmd_type = 0x%x)\n", + __FUNCTION__, msg->cmd_type, msg->ext_cmd_type)); + } + else + { + msg->rsp_handler(msg, GET_OS_PKT_DATAPTR(net_pkt) + sizeof(*event_rxd), + event_rxd->fw_rxd_0.field.length - sizeof(*event_rxd)); + } + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("expect response len(%d), command response len(%d) invalid\n", msg->rsp_payload_len, event_rxd->fw_rxd_0.field.length - sizeof(*event_rxd))); + msg->rsp_payload_len = event_rxd->fw_rxd_0.field.length - sizeof(*event_rxd); + } + + if (msg->need_wait) { + RTMP_OS_COMPLETE(&msg->ack_done); + } else { + AndesFreeCmdMsg(msg); + } +#if defined(RTMP_USB_SUPPORT) || defined(RTMP_SDIO_SUPPORT) + RTMP_SPIN_LOCK_IRQ(&ctl->ackq_lock); +#endif + +#ifdef RTMP_PCI_SUPPORT + RTMP_SPIN_LOCK_IRQSAVE(&ctl->ackq_lock, &flags); +#endif + + break; + } + } + +#if defined(RTMP_USB_SUPPORT) || defined(RTMP_SDIO_SUPPORT) + RTMP_SPIN_UNLOCK_IRQ(&ctl->ackq_lock); +#endif + +#ifdef RTMP_PCI_SUPPORT + RTMP_SPIN_UNLOCK_IRQRESTORE(&ctl->ackq_lock, &flags); +#endif + } +} + + +VOID AndesMTRxEventHandler(RTMP_ADAPTER *pAd, UCHAR *data) +{ + struct cmd_msg *msg; + struct MCU_CTRL *ctl = &pAd->MCUCtrl; + EVENT_RXD *event_rxd = (EVENT_RXD *)data; + + if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) { + return; + } + + DBGPRINT(RT_DEBUG_INFO, ("%s\n", __FUNCTION__)); + + msg = AndesAllocCmdMsg(pAd, event_rxd->fw_rxd_0.field.length); + + if (!msg || !msg->net_pkt) + return; + + AndesAppendCmdMsg(msg, (char *)data, event_rxd->fw_rxd_0.field.length); + + AndesMTRxProcessEvent(pAd, msg); + +#ifdef RTMP_PCI_SUPPORT + if (msg->net_pkt) + RTMPFreeNdisPacket(pAd, msg->net_pkt); +#endif + + AndesFreeCmdMsg(msg); +} + + +#ifdef RTMP_PCI_SUPPORT +VOID AndesMTPciFwInit(RTMP_ADAPTER *pAd) +{ + struct MCU_CTRL *Ctl = &pAd->MCUCtrl; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + Ctl->Stage = FW_NO_INIT; + /* Enable Interrupt*/ + RTMP_IRQ_ENABLE(pAd); + RT28XXDMAEnable(pAd); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD); +} + + +VOID AndesMTPciFwExit(RTMP_ADAPTER *pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD); + RT28XXDMADisable(pAd); + RTMP_ASIC_INTERRUPT_DISABLE(pAd); +} +#endif /* RTMP_PCI_SUPPORT */ + + + + +#ifdef RTMP_SDIO_SUPPORT +VOID AndesMTSdioFwInit(RTMP_ADAPTER *pAd) +{ + struct MCU_CTRL *Ctl = &pAd->MCUCtrl; + UINT32 value; + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + Ctl->Stage = FW_NO_INIT; + /* Enable Interrupt*/ + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_START_UP); + RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD); + + RTMP_SDIO_WRITE32(pAd, WHIER, (RX0_DONE_INT_EN |RX1_DONE_INT_EN)); + RTMP_SDIO_READ32(pAd, WHIER,&value); + printk("%s(): MCR_WHIER: value:%x\n", __FUNCTION__,value); + RTMP_SDIO_READ32(pAd, WHISR,&value); + printk("%s(): MCR_WHISR1: value:%x\n", __FUNCTION__,value); + RTMP_SDIO_WRITE32(pAd, WHLPCR, W_INT_EN_SET); + +} + + +VOID AndesMTSdioFwExit(RTMP_ADAPTER *pAd) +{ + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP); + RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD); +} +#endif + + +static VOID CmdEfuseBufferModeRsp(struct cmd_msg *msg, char *Data, UINT16 Len) +{ + struct _EVENT_EXT_CMD_RESULT_T *EventExtCmdResult = (struct _EVENT_EXT_CMD_RESULT_T *)Data; + //RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv; + + DBGPRINT(RT_DEBUG_INFO, ("%s: EventExtCmdResult.ucExTenCID = 0x%x\n",__FUNCTION__, EventExtCmdResult->ucExTenCID)); + EventExtCmdResult->u4Status = le2cpu32(EventExtCmdResult->u4Status); + DBGPRINT(RT_DEBUG_INFO, ("%s: EventExtCmdResult.u4Status = 0x%x\n",__FUNCTION__, EventExtCmdResult->u4Status)); +} + +static VOID CmdThemalSensorRsp(struct cmd_msg *msg, char *Data, UINT16 Len) +{ + struct _EXT_EVENT_GET_SENSOR_RESULT_T *EventExtCmdResult = (struct _EXT_EVENT_GET_SENSOR_RESULT_T *)Data; + //RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv; + + EventExtCmdResult->u4SensorResult = le2cpu32(EventExtCmdResult->u4SensorResult); + DBGPRINT(RT_DEBUG_OFF, ("ThemalSensor = 0x%x\n", EventExtCmdResult->u4SensorResult)); +} + + +static inline VOID bufferModeFieldSet(RTMP_ADAPTER *pAd,EXT_CMD_EFUSE_BUFFER_MODE_T *pCmd,UINT16 addr) +{ + UINT32 i = pCmd->ucCount; + pCmd->aBinContent[i].u2Addr = cpu2le16(addr); + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[addr] ; + pCmd->ucCount++; +} + +static VOID CmdExtPmMgtBitRsp(struct cmd_msg *msg, char *Data, UINT16 Len) +{ + struct _EVENT_EXT_CMD_RESULT_T *EventExtCmdResult = (struct _EVENT_EXT_CMD_RESULT_T *)Data; + //RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv; + + DBGPRINT(RT_DEBUG_OFF, ("%s: EventExtCmdResult.ucExTenCID = 0x%x\n",__FUNCTION__, EventExtCmdResult->ucExTenCID)); + EventExtCmdResult->u4Status = le2cpu32(EventExtCmdResult->u4Status); + DBGPRINT(RT_DEBUG_OFF, ("%s: EventExtCmdResult.u4Status = 0x%x\n",__FUNCTION__, EventExtCmdResult->u4Status)); +} + +static VOID CmdExtPmStateCtrlRsp(struct cmd_msg *msg, char *Data, UINT16 Len) +{ + struct _EVENT_EXT_CMD_RESULT_T *EventExtCmdResult = (struct _EVENT_EXT_CMD_RESULT_T *)Data; + //RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv; + + DBGPRINT(RT_DEBUG_OFF, ("%s: EventExtCmdResult.ucExTenCID = 0x%x\n",__FUNCTION__, EventExtCmdResult->ucExTenCID)); + EventExtCmdResult->u4Status = le2cpu32(EventExtCmdResult->u4Status); + DBGPRINT(RT_DEBUG_OFF, ("%s: EventExtCmdResult.u4Status = 0x%x\n",__FUNCTION__, EventExtCmdResult->u4Status)); +} + +static VOID CmdFillEeprom(RTMP_ADAPTER *pAd,EXT_CMD_EFUSE_BUFFER_MODE_T *pCmd) +{ + int i=0; + pCmd->aBinContent[i].u2Addr = NIC_CONFIGURE_0_TOP; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[NIC_CONFIGURE_0_TOP] ; + i++; + pCmd->aBinContent[i].u2Addr = NIC_CONFIGURE_1; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[NIC_CONFIGURE_1]; + i++; + pCmd->aBinContent[i].u2Addr = NIC_CONFIGURE_1_TOP; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[NIC_CONFIGURE_1_TOP]; + i++; + pCmd->aBinContent[i].u2Addr = WIFI_RF_SETTING; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[WIFI_RF_SETTING]; + i++; + pCmd->aBinContent[i].u2Addr = G_BAND_20_40_BW_PWR_DELTA; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[G_BAND_20_40_BW_PWR_DELTA]; + i++; + pCmd->aBinContent[i].u2Addr = A_BAND_20_80_BW_PWR_DELTA_ANALOG; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[A_BAND_20_80_BW_PWR_DELTA_ANALOG]; + i++; + pCmd->aBinContent[i].u2Addr = A_BAND_EXT_PA_SETTING; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[A_BAND_EXT_PA_SETTING]; + i++; + pCmd->aBinContent[i].u2Addr = TEMP_SENSOR_CAL; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TEMP_SENSOR_CAL]; + i++; + pCmd->aBinContent[i].u2Addr = TX0_G_BAND_TSSI_SLOPE; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX0_G_BAND_TSSI_SLOPE]; + i++; + pCmd->aBinContent[i].u2Addr = TX0_G_BAND_TSSI_SLOPE_TOP; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX0_G_BAND_TSSI_SLOPE_TOP]; + i++; + pCmd->aBinContent[i].u2Addr = TX0_G_BAND_TARGET_PWR; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX0_G_BAND_TARGET_PWR]; + i++; + pCmd->aBinContent[i].u2Addr = TX0_G_BAND_OFFSET_LOW; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX0_G_BAND_OFFSET_LOW]; + i++; + pCmd->aBinContent[i].u2Addr = TX0_G_BAND_CHL_PWR_DELTA_MID; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX0_G_BAND_CHL_PWR_DELTA_MID]; + i++; + pCmd->aBinContent[i].u2Addr = TX0_G_BAND_OFFSET_HIGH; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX0_G_BAND_OFFSET_HIGH]; + i++; + pCmd->aBinContent[i].u2Addr = TX1_G_BAND_TSSI_SLOPE; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX1_G_BAND_TSSI_SLOPE]; + i++; + pCmd->aBinContent[i].u2Addr = TX1_G_BAND_TSSI_SLOPE_TOP; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX1_G_BAND_TSSI_SLOPE_TOP]; + i++; + pCmd->aBinContent[i].u2Addr = TX1_G_BAND_TARGET_PWR; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX1_G_BAND_TARGET_PWR]; + i++; + pCmd->aBinContent[i].u2Addr = TX1_G_BAND_CHL_PWR_DELATE_LOW; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX1_G_BAND_CHL_PWR_DELATE_LOW]; + i++; + pCmd->aBinContent[i].u2Addr = TX1_G_BAND_CHL_PWR_DELTA_MID; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX1_G_BAND_CHL_PWR_DELTA_MID]; + i++; + pCmd->aBinContent[i].u2Addr = TX1_G_BAND_CHL_PWR_DELTA_HIGH; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX1_G_BAND_CHL_PWR_DELTA_HIGH]; + i++; + pCmd->aBinContent[i].u2Addr = TX_PWR_CCK_1_2M; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_CCK_1_2M]; + i++; + pCmd->aBinContent[i].u2Addr = TX_PWR_CCK_5_11M; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_CCK_5_11M]; + i++; + pCmd->aBinContent[i].u2Addr = TX_PWR_G_BAND_OFDM_6_9M; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_G_BAND_OFDM_6_9M]; + i++; + pCmd->aBinContent[i].u2Addr = TX_PWR_OFDM_12_18M; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_OFDM_12_18M]; + i++; + pCmd->aBinContent[i].u2Addr = TX_PWR_G_BAND_OFDM_24_36M; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_G_BAND_OFDM_24_36M]; + i++; + pCmd->aBinContent[i].u2Addr = TX_PWR_G_BNAD_OFDM_48; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_G_BNAD_OFDM_48]; + i++; + pCmd->aBinContent[i].u2Addr = TX_PWR_G_BAND_OFDM_54M; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_G_BAND_OFDM_54M]; + i++; + pCmd->aBinContent[i].u2Addr = TX_PWR_HT_BPSK_MCS_0_8; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_HT_BPSK_MCS_0_8]; + i++; + pCmd->aBinContent[i].u2Addr = TX_PWR_HT_BPSK_MCS_32; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_HT_BPSK_MCS_32]; + i++; + pCmd->aBinContent[i].u2Addr = TX_PWR_HT_QPSK_MCS_1_2_9_10; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_HT_QPSK_MCS_1_2_9_10]; + i++; + pCmd->aBinContent[i].u2Addr = TX_PWR_HT_16QAM_MCS_3_4_11_12; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_HT_16QAM_MCS_3_4_11_12]; + i++; + pCmd->aBinContent[i].u2Addr = TX_PWR_HT_64QAM_MCS_5_13; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_HT_64QAM_MCS_5_13]; + i++; + pCmd->aBinContent[i].u2Addr = TX_PWR_HT_64QAM_MCS_6_14; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_HT_64QAM_MCS_6_14]; + i++; + pCmd->aBinContent[i].u2Addr = TX_PWR_HT_64QAM_MCS_7_15; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[TX_PWR_HT_64QAM_MCS_7_15]; + i++; + pCmd->aBinContent[i].u2Addr = ELAN_RX_MODE_GAIN; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[ELAN_RX_MODE_GAIN]; + i++; + pCmd->aBinContent[i].u2Addr = ELAN_RX_MODE_NF; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[ELAN_RX_MODE_NF]; + i++; + pCmd->aBinContent[i].u2Addr = ELAN_RX_MODE_P1DB; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[ELAN_RX_MODE_P1DB]; + i++; + pCmd->aBinContent[i].u2Addr = ELAN_BYPASS_MODE_GAIN; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[ELAN_BYPASS_MODE_GAIN]; + i++; + pCmd->aBinContent[i].u2Addr = ELAN_BYPASS_MODE_NF; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[ELAN_BYPASS_MODE_NF]; + i++; + pCmd->aBinContent[i].u2Addr = ELAN_BYPASS_MODE_P1DB; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[ELAN_BYPASS_MODE_P1DB]; + i++; + pCmd->aBinContent[i].u2Addr = STEP_NUM_NEG_7; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_NEG_7]; + i++; + pCmd->aBinContent[i].u2Addr = STEP_NUM_NEG_6; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_NEG_6]; + i++; + pCmd->aBinContent[i].u2Addr = STEP_NUM_NEG_5; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_NEG_5]; + i++; + pCmd->aBinContent[i].u2Addr = STEP_NUM_NEG_4; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_NEG_4]; + i++; + pCmd->aBinContent[i].u2Addr = STEP_NUM_NEG_3; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_NEG_3]; + i++; + pCmd->aBinContent[i].u2Addr = STEP_NUM_NEG_2; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_NEG_2]; + i++; + pCmd->aBinContent[i].u2Addr = STEP_NUM_NEG_1; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_NEG_1]; + i++; + pCmd->aBinContent[i].u2Addr = STEP_NUM_NEG_0; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_NEG_0]; + i++; + pCmd->aBinContent[i].u2Addr = REF_STEP_24G; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[REF_STEP_24G]; + i++; + pCmd->aBinContent[i].u2Addr = REF_TEMP_24G; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[REF_TEMP_24G]; + i++; + pCmd->aBinContent[i].u2Addr = STEP_NUM_PLUS_1; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_PLUS_1]; + i++; + pCmd->aBinContent[i].u2Addr = STEP_NUM_PLUS_2; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_PLUS_2]; + i++; + pCmd->aBinContent[i].u2Addr = STEP_NUM_PLUS_3; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_PLUS_3]; + i++; + pCmd->aBinContent[i].u2Addr = STEP_NUM_PLUS_4; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_PLUS_4]; + i++; + pCmd->aBinContent[i].u2Addr = STEP_NUM_PLUS_5; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_PLUS_5]; + i++; + pCmd->aBinContent[i].u2Addr = STEP_NUM_PLUS_6; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_PLUS_6]; + i++; + pCmd->aBinContent[i].u2Addr = STEP_NUM_PLUS_7; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[STEP_NUM_PLUS_7]; + i++; + pCmd->aBinContent[i].u2Addr = XTAL_CALIB_FREQ_OFFSET; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[XTAL_CALIB_FREQ_OFFSET]; + i++; + pCmd->aBinContent[i].u2Addr = XTAL_TRIM_2_COMP; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[XTAL_TRIM_2_COMP]; + i++; + pCmd->aBinContent[i].u2Addr = XTAL_TRIM_3_COMP; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[XTAL_TRIM_3_COMP]; + i++; + pCmd->aBinContent[i].u2Addr = WF_RCAL; + pCmd->aBinContent[i].ucValue = pAd->EEPROMImage[WF_RCAL]; + i++; + + pCmd->ucCount = i; + /*check endian and transfer it is needed*/ + for(i=0;iucCount ;i++) + { + pCmd->aBinContent[i].u2Addr = cpu2le16(pCmd->aBinContent[i].u2Addr); + } + + /*extend for function requset, need backward compatible*/ + bufferModeFieldSet(pAd,pCmd,0x24); + bufferModeFieldSet(pAd,pCmd,0x25); + bufferModeFieldSet(pAd,pCmd,0x34); + bufferModeFieldSet(pAd,pCmd,0x39); + bufferModeFieldSet(pAd,pCmd,0x3b); + bufferModeFieldSet(pAd,pCmd,0x42); + bufferModeFieldSet(pAd,pCmd,0x43); + bufferModeFieldSet(pAd,pCmd,0x9e); + bufferModeFieldSet(pAd,pCmd,0x9f); + bufferModeFieldSet(pAd,pCmd,0xf2); + bufferModeFieldSet(pAd,pCmd,0xf8); + bufferModeFieldSet(pAd,pCmd,0xf9); + bufferModeFieldSet(pAd,pCmd,0xfa); + bufferModeFieldSet(pAd,pCmd,0x12e); + + for(i=0;i<=0xf;i++) + { + bufferModeFieldSet(pAd,pCmd,0x130+i); + } + + /*need minus 1 for add one more time*/ + pCmd->ucCount--; + +} + +VOID CmdEfusBufferModeSet(RTMP_ADAPTER *pAd) +{ + + struct cmd_msg *msg; + EXT_CMD_EFUSE_BUFFER_MODE_T CmdEfuseBufferMode; + int ret = 0; + msg = AndesAllocCmdMsg(pAd, sizeof(EXT_CMD_EFUSE_BUFFER_MODE_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_EFUSE_BUFFER_MODE, TRUE, 0,TRUE, TRUE, 8, NULL, CmdEfuseBufferModeRsp); + memset(&CmdEfuseBufferMode, 0x00, sizeof(CmdEfuseBufferMode)); + switch(pAd->eeprom_type){ + case EEPROM_EFUSE: + { + CmdEfuseBufferMode.ucSourceMode = EEPROM_MODE_EFUSE; + CmdEfuseBufferMode.ucCount = 0; + } + break; + case EEPROM_FLASH: + { + CmdEfuseBufferMode.ucSourceMode = EEPROM_MODE_BUFFER; + CmdFillEeprom(pAd,&CmdEfuseBufferMode); + } + break; + default: + goto error; + break; + } + + AndesAppendCmdMsg(msg, (char *)&CmdEfuseBufferMode, sizeof(CmdEfuseBufferMode)); + ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ; + +} + +VOID CmdSetTxPowerCtrl(RTMP_ADAPTER *pAd, UINT8 central_chl) +{ + struct cmd_msg *msg; + EXT_CMD_TX_POWER_CTRL_T CmdTxPwrCtrl; + int ret = 0; + int i, j; + UINT8 PwrPercentageDelta = 0; + USHORT Value; + struct MT_TX_PWR_CAP *cap = &pAd->chipCap.MTTxPwrCap; + + msg = AndesAllocCmdMsg(pAd, sizeof(EXT_CMD_TX_POWER_CTRL_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_SET_TX_POWER_CTRL, TRUE, 0, + TRUE, TRUE, 8, NULL, EventExtCmdResult); + memset(&CmdTxPwrCtrl, 0x00, sizeof(CmdTxPwrCtrl)); + + CmdTxPwrCtrl.ucCenterChannel = central_chl; + + if (pAd->eeprom_type == EEPROM_EFUSE) + { + + RT28xx_EEPROM_READ16(pAd, NIC_CONFIGURE_1, Value); + CmdTxPwrCtrl.ucTSSIEnable = ((Value & 0xff00) >> 8); + + RT28xx_EEPROM_READ16(pAd, NIC_CONFIGURE_1, Value); + CmdTxPwrCtrl.ucTempCompEnable = (Value & 0xff); + + RT28xx_EEPROM_READ16(pAd, TX0_G_BAND_TARGET_PWR, Value); + CmdTxPwrCtrl.aucTargetPower[0] = Value & 0xff; + RT28xx_EEPROM_READ16(pAd, TX1_G_BAND_TARGET_PWR, Value); + CmdTxPwrCtrl.aucTargetPower[1] = Value & 0xff; + + j = 0; + + for (i = 0; i < 7; i++) + { + RT28xx_EEPROM_READ16(pAd, TX_PWR_CCK_1_2M + (i * 2), Value); + CmdTxPwrCtrl.aucRatePowerDelta[j] = Value & 0xff; + j++; + CmdTxPwrCtrl.aucRatePowerDelta[j] = ((Value & 0xff00) >> 8); + j++; + } + + RT28xx_EEPROM_READ16(pAd, G_BAND_20_40_BW_PWR_DELTA, Value); + CmdTxPwrCtrl.ucBWPowerDelta = Value & 0xff; + + RT28xx_EEPROM_READ16(pAd, TX0_G_BAND_TARGET_PWR, Value); + CmdTxPwrCtrl.aucCHPowerDelta[0] = ((Value & 0xff00) >> 8); + + RT28xx_EEPROM_READ16(pAd, TX0_G_BAND_CHL_PWR_DELTA_MID, Value); + CmdTxPwrCtrl.aucCHPowerDelta[1] = Value & 0xff; + + CmdTxPwrCtrl.aucCHPowerDelta[2] = ((Value & 0xff00) >> 8); + + RT28xx_EEPROM_READ16(pAd, TX1_G_BAND_TARGET_PWR, Value); + CmdTxPwrCtrl.aucCHPowerDelta[3] = ((Value & 0xff00) >> 8); + + RT28xx_EEPROM_READ16(pAd, TX1_G_BAND_CHL_PWR_DELTA_MID, Value); + CmdTxPwrCtrl.aucCHPowerDelta[4] = Value & 0xff; + + CmdTxPwrCtrl.aucCHPowerDelta[5] = ((Value & 0xff00) >> 8); + + j = 0; + + for (i = 0; i < 9; i++) + { + RT28xx_EEPROM_READ16(pAd, STEP_NUM_NEG_7 + (i * 2), Value); + CmdTxPwrCtrl.aucTempCompPower[j] = Value & 0xff; + j++; + + if (i != 8) + { + CmdTxPwrCtrl.aucTempCompPower[j] = ((Value & 0xff00) >> 8); + j++; + } + } + } + else + { + CmdTxPwrCtrl.ucTSSIEnable = pAd->EEPROMImage[NIC_CONFIGURE_1_TOP]; + CmdTxPwrCtrl.ucTempCompEnable = pAd->EEPROMImage[NIC_CONFIGURE_1]; + + CmdTxPwrCtrl.aucTargetPower[0] = pAd->EEPROMImage[TX0_G_BAND_TARGET_PWR]; + CmdTxPwrCtrl.aucTargetPower[1] = pAd->EEPROMImage[TX1_G_BAND_TARGET_PWR]; + +#ifdef CONFIG_ATE + /* Replace Target Power from QA Tool manual setting*/ + if (ATE_ON(pAd)) { + DBGPRINT(RT_DEBUG_TRACE, ("%s,ATE set tx power\n", __FUNCTION__)); + CmdTxPwrCtrl.aucTargetPower[0] = pAd->ATECtrl.TxPower0; + CmdTxPwrCtrl.aucTargetPower[1] = pAd->ATECtrl.TxPower1; + } +#endif + + NdisCopyMemory(&CmdTxPwrCtrl.aucRatePowerDelta[0], &(pAd->EEPROMImage[TX_PWR_CCK_1_2M]), sizeof(CmdTxPwrCtrl.aucRatePowerDelta)); + CmdTxPwrCtrl.ucBWPowerDelta = pAd->EEPROMImage[G_BAND_20_40_BW_PWR_DELTA]; + NdisCopyMemory(&CmdTxPwrCtrl.aucCHPowerDelta[0], &(pAd->EEPROMImage[TX0_G_BAND_OFFSET_LOW]), sizeof(CmdTxPwrCtrl.aucCHPowerDelta[0])); + NdisCopyMemory(&CmdTxPwrCtrl.aucCHPowerDelta[1], &(pAd->EEPROMImage[TX0_G_BAND_CHL_PWR_DELTA_MID]), sizeof(CmdTxPwrCtrl.aucCHPowerDelta[1])); + NdisCopyMemory(&CmdTxPwrCtrl.aucCHPowerDelta[2], &(pAd->EEPROMImage[TX0_G_BAND_OFFSET_HIGH]), sizeof(CmdTxPwrCtrl.aucCHPowerDelta[2])); + NdisCopyMemory(&CmdTxPwrCtrl.aucCHPowerDelta[3], &(pAd->EEPROMImage[TX1_G_BAND_CHL_PWR_DELATE_LOW]), sizeof(CmdTxPwrCtrl.aucCHPowerDelta[3])); + + NdisCopyMemory(&CmdTxPwrCtrl.aucCHPowerDelta[4], &(pAd->EEPROMImage[TX1_G_BAND_CHL_PWR_DELTA_MID]), sizeof(CmdTxPwrCtrl.aucCHPowerDelta[4])); + + NdisCopyMemory(&CmdTxPwrCtrl.aucCHPowerDelta[5], &(pAd->EEPROMImage[TX1_G_BAND_CHL_PWR_DELTA_HIGH]), sizeof(CmdTxPwrCtrl.aucCHPowerDelta[5])); + + NdisCopyMemory(&CmdTxPwrCtrl.aucTempCompPower[0], &(pAd->EEPROMImage[STEP_NUM_NEG_7]), sizeof(CmdTxPwrCtrl.aucTempCompPower)); + } + + DBGPRINT(RT_DEBUG_INFO, ("PA type = %d\n", cap->pa_type)); + +// if (!(cap->pa_type & (1 << 1))) + if (1) + { + + if (pAd->CommonCfg.TxPowerPercentage > 90) + { + PwrPercentageDelta = 0; + } + else if (pAd->CommonCfg.TxPowerPercentage > 60) /* reduce Pwr for 1 dB. */ + { + PwrPercentageDelta = 1; + } + else if (pAd->CommonCfg.TxPowerPercentage > 30) /* reduce Pwr for 3 dB. */ + { + PwrPercentageDelta = 3; + } + else if (pAd->CommonCfg.TxPowerPercentage > 15) /* reduce Pwr for 6 dB. */ + { + PwrPercentageDelta = 6; + } + else if (pAd->CommonCfg.TxPowerPercentage > 9) /* reduce Pwr for 9 dB. */ + { + PwrPercentageDelta = 9; + } + else /* reduce Pwr for 12 dB. */ + { + PwrPercentageDelta = 12; + } + + DBGPRINT(RT_DEBUG_INFO, ("Before apply tx pwr percentage, CmdTxPwrCtrl.aucTargetPower[0] = 0x%x\n", CmdTxPwrCtrl.aucTargetPower[0])); + + DBGPRINT(RT_DEBUG_INFO, ("Before apply tx pwr percentage, CmdTxPwrCtrl.aucTargetPower[1] = 0x%x\n", CmdTxPwrCtrl.aucTargetPower[1])); + DBGPRINT(RT_DEBUG_INFO, ("Percentage = 0x%x\n", PwrPercentageDelta)); + + CmdTxPwrCtrl.ucReserved = PwrPercentageDelta; + } + else + { +#ifdef CONFIG_ATE + if (!ATE_ON(pAd)) +#endif + { + DBGPRINT(RT_DEBUG_TRACE, ("EPA, do not need to apply tx power percentage\n")); + goto error; + } + } + + DBGPRINT(RT_DEBUG_INFO, ("CmdTxPwrCtrl.ucCenterChannel=%x\n", CmdTxPwrCtrl.ucCenterChannel)); + DBGPRINT(RT_DEBUG_INFO, ("CmdTxPwrCtrl.ucTSSIEnable=%x \n", CmdTxPwrCtrl.ucTSSIEnable)); + DBGPRINT(RT_DEBUG_INFO, ("CmdTxPwrCtrl.ucTempCompEnable=%x\n", CmdTxPwrCtrl.ucTempCompEnable)); + DBGPRINT(RT_DEBUG_INFO, ("CmdTxPwrCtrl.aucTargetPower[0]=%x\n", CmdTxPwrCtrl.aucTargetPower[0])); + DBGPRINT(RT_DEBUG_INFO, ("CmdTxPwrCtrl.aucTargetPower[1]=%x\n", CmdTxPwrCtrl.aucTargetPower[1])); + for(i=0; i<14;i++) + DBGPRINT(RT_DEBUG_INFO, ("CmdTxPwrCtrl.aucRatePowerDelta[%d]=%x\n", i, CmdTxPwrCtrl.aucRatePowerDelta[i])); + DBGPRINT(RT_DEBUG_INFO, ("CmdTxPwrCtrl.ucBWPowerDelta=%x \n",CmdTxPwrCtrl.ucBWPowerDelta)); + for(i=0;i<6;i++) + DBGPRINT(RT_DEBUG_INFO, ("CmdTxPwrCtrl.aucCHPowerDelta[%d]=%x\n", i, CmdTxPwrCtrl.aucCHPowerDelta[i])); + for(i=0;i<17;i++) + DBGPRINT(RT_DEBUG_INFO, ("CmdTxPwrCtrl.aucTempCompPower[%d]=%x\n", i, CmdTxPwrCtrl.aucTempCompPower[i])); + + AndesAppendCmdMsg(msg, (char *)&CmdTxPwrCtrl, sizeof(CmdTxPwrCtrl)); + ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return; +} + +VOID CmdGetThemalSensorResult(struct _RTMP_ADAPTER *pAd, UINT8 option) +{ + struct cmd_msg *msg; + EXT_CMD_GET_SENSOR_RESULT_T CmdSensorResult; + INT32 ret; +#ifdef CONFIG_QA + ATE_CTRL *ATECtrl = &(pAd->ATECtrl); +#endif /* CONFIG_QA */ + ret = 0; + + msg = AndesAllocCmdMsg(pAd, sizeof(EXT_CMD_GET_SENSOR_RESULT_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } +#ifdef CONFIG_QA + //ATE_CTRL *ATECtrl = &(pAd->ATECtrl); + if(ATECtrl->bQAEnabled){ + DBGPRINT(RT_DEBUG_OFF, ("%s: Call to qa_agent\n", __FUNCTION__)); + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_GET_THEMAL_SENSOR, TRUE, 0, TRUE, TRUE, 8, NULL, HQA_GetThermalValue_CB); + } else +#endif + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_GET_THEMAL_SENSOR, TRUE, 0, TRUE, TRUE, 8, NULL, CmdThemalSensorRsp); + + CmdSensorResult.ucActionIdx = option; + + AndesAppendCmdMsg(msg, (char *)&CmdSensorResult, sizeof(CmdSensorResult)); + ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ; +} + +#ifdef LED_CONTROL_SUPPORT +INT AndesLedOP( + IN PRTMP_ADAPTER pAd, + IN UCHAR LedIdx, + IN UCHAR LinkStatus) +{ + struct cmd_msg *msg; + CHAR *Pos, *pBuf; + UINT32 VarLen; + UINT32 arg0, arg1; + INT32 ret; + UINT32 blinkSel = 2; // 2 : data only, 0 : all Tx frames, 1 : Exclude Tx Beacon and TIM broadcast frames + + ret = 0; + + msg = AndesAllocCmdMsg(pAd, sizeof(LED_NMAC_CMD)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_LED_CTRL, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + //memset(&CmdEfuseBufferMode, 0x00, sizeof(CmdEfuseBufferMode)); + + + /* Calibration ID and Parameter */ + VarLen = 8; + arg0 = cpu2le32(LedIdx); + arg1 = cpu2le32(LinkStatus | (blinkSel << 24)); + os_alloc_mem(pAd, (UCHAR **)&pBuf, VarLen); + if (pBuf == NULL) + { + return NDIS_STATUS_RESOURCES; + } + + NdisZeroMemory(pBuf, VarLen); + + Pos = pBuf; + /* Parameter */ + + NdisMoveMemory(Pos, &arg0, 4); + NdisMoveMemory(Pos+4, &arg1, 4); + + Pos += 4; + + hex_dump("AndesLedOP: ", pBuf, VarLen); + AndesAppendCmdMsg(msg, (char *)pBuf, VarLen); + + + ret = AndesSendCmdMsg(pAd, msg); + + os_free_mem(NULL, pBuf); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + +INT AndesLedEnhanceOP( + IN PRTMP_ADAPTER pAd, + IN UCHAR LedIdx, + IN UCHAR on_time, + IN UCHAR off_time, + IN UCHAR Led_Parameter + ) +{ + struct cmd_msg *msg; + CHAR *Pos, *pBuf; + UINT32 VarLen; + UINT32 arg0/*, arg1*/; + INT32 ret = 0; + //UCHAR parameter[4]={0}; + + LED_ENHANCE led_enhance; + msg = AndesAllocCmdMsg(pAd, sizeof(LED_NMAC_CMD)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_LED_CTRL, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + //memset(&CmdEfuseBufferMode, 0x00, sizeof(CmdEfuseBufferMode)); + + + /* Calibration ID and Parameter */ + VarLen = 8; + arg0 = LedIdx; + //arg1 = LinkStatus; + //parameter[1]=on_time; + //parameter[2]=off_time; + //parameter[3]=31; + led_enhance.word = 0; + led_enhance.field.on_time=on_time; + led_enhance.field.off_time=off_time; + led_enhance.field.idx = Led_Parameter; + os_alloc_mem(pAd, (UCHAR **)&pBuf, VarLen); + if (pBuf == NULL) + { + return NDIS_STATUS_RESOURCES; + } + + NdisZeroMemory(pBuf, VarLen); + + Pos = pBuf; + /* Parameter */ + + NdisMoveMemory(Pos, &arg0, 4); + //NdisMoveMemory(Pos+4, &arg1, 4); + NdisMoveMemory(Pos+4, &led_enhance, sizeof(led_enhance)); + + + Pos += 4; + + hex_dump("AndesLedOPEnhance: ", pBuf, VarLen); + AndesAppendCmdMsg(msg, (char *)pBuf, VarLen); + + + ret = AndesSendCmdMsg(pAd, msg); + + os_free_mem(NULL, pBuf); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} +#endif /*LED_CONTROL_SUPPORT*/ + +NTSTATUS MtCmdWtblTxpsUpdate(RTMP_ADAPTER *pAd, PCmdQElmt CMDQelmt) +{ + INT32 Ret = NDIS_STATUS_FAILURE; + struct wtbl_entry tb_entry; + union WTBL_1_DW2 *dw2 = (union WTBL_1_DW2 *)&tb_entry.wtbl_1.wtbl_1_d2.word; + PWTBL_TX_PS_UPDATE pWblTxpsUpdate = (PWTBL_TX_PS_UPDATE)(CMDQelmt->buffer); + UINT8 ucWlanIdx = pWblTxpsUpdate->ucWlanIdx; + UINT8 ucPwrMgtBit = pWblTxpsUpdate->ucPwrMgtBit; + + NdisZeroMemory(&tb_entry, sizeof(tb_entry)); + + if (mt_wtbl_get_entry234(pAd, ucWlanIdx, &tb_entry) == FALSE) + { + Ret = NDIS_STATUS_FAILURE; + DBGPRINT(RT_DEBUG_ERROR, ("%s():Cannot found WTBL2/3/4 for WCID(%d)\n", __FUNCTION__, ucWlanIdx)); + return Ret; + } + + RTMP_IO_READ32(pAd, tb_entry.wtbl_addr[0] + (2 * 4), &dw2->word); + dw2->field.tx_ps = ucPwrMgtBit; + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Set WCID(%d).TX_PS(%d)\n", __FUNCTION__, ucWlanIdx, dw2->field.tx_ps)); + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + (2 * 4), dw2->word); + + return Ret; +} + +INT32 CmdExtPwrMgtBitWifi(RTMP_ADAPTER *pAd, UINT8 ucWlanIdx, UINT8 ucPwrMgtBit, BOOLEAN ucDirectCall) +{ + if (IS_MT7603(pAd)) + { + INT32 Ret = NDIS_STATUS_FAILURE; + struct wtbl_entry tb_entry; + union WTBL_1_DW2 *dw2 = (union WTBL_1_DW2 *)&tb_entry.wtbl_1.wtbl_1_d2.word; + + WTBL_TX_PS_UPDATE rWblTxpsUpdate = {0}; + + if (ucDirectCall) + { + NdisZeroMemory(&tb_entry, sizeof(tb_entry)); + + if (mt_wtbl_get_entry234(pAd, ucWlanIdx, &tb_entry) == FALSE) + { + Ret = NDIS_STATUS_FAILURE; + DBGPRINT(RT_DEBUG_ERROR, ("%s():Cannot found WTBL2/3/4 for WCID(%d)\n", __FUNCTION__, ucWlanIdx)); + return Ret; + } + + RTMP_IO_READ32(pAd, tb_entry.wtbl_addr[0] + (2 * 4), &dw2->word); + dw2->field.tx_ps = ucPwrMgtBit; + DBGPRINT(RT_DEBUG_ERROR, ("%s(): Set WCID(%d).TX_PS(%d)\n", __FUNCTION__, ucWlanIdx, dw2->field.tx_ps)); + RTMP_IO_WRITE32(pAd, tb_entry.wtbl_addr[0] + (2 * 4), dw2->word); + + return Ret; + } + else + { + rWblTxpsUpdate.ucWlanIdx = ucWlanIdx; + rWblTxpsUpdate.ucPwrMgtBit = ucPwrMgtBit; + + return RTEnqueueInternalCmd(pAd, CMDTHREAD_PWR_MGT_BIT, &rWblTxpsUpdate, sizeof(rWblTxpsUpdate)); + } + } + else + { + INT32 Ret = 0; + struct cmd_msg *msg; + EXT_CMD_PWR_MGT_BIT_T PwrMgtBitWifi = {0}; + + + msg = AndesAllocCmdMsg(pAd, sizeof(EXT_CMD_PWR_MGT_BIT_T)); + + if (!msg) + { + Ret = NDIS_STATUS_RESOURCES; + goto error; + } + + PwrMgtBitWifi.ucWlanIdx = ucWlanIdx; + PwrMgtBitWifi.ucPwrMgtBit = ucPwrMgtBit; + + DBGPRINT(RT_DEBUG_OFF, ("%s:ucWlanIdx(%d), ucPwrMgtBit(%d)\n", __FUNCTION__, ucWlanIdx, ucPwrMgtBit)); + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_PWR_MGT_BIT_WIFI, TRUE, 0,TRUE, TRUE, 8, NULL, CmdExtPmMgtBitRsp); + + AndesAppendCmdMsg(msg, (char *)&PwrMgtBitWifi, sizeof(PwrMgtBitWifi)); + + Ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_OFF, ("%s:(Ret = %d)\n", __FUNCTION__, Ret)); + return Ret; + } + +} + + /*1: enter, 2: exit specific PM state*/ +INT32 CmdExtPmStateCtrl(RTMP_ADAPTER *pAd, UINT8 ucWlanIdx, UINT8 ucPmNumber, UINT8 ucPmState) +{ + struct cmd_msg *msg = NULL; + EXT_CMD_PM_STATE_CTRL_T CmdPmStateCtrl = {0}; + INT32 Ret = 0; + msg = AndesAllocCmdMsg(pAd, sizeof(EXT_CMD_PM_STATE_CTRL_T)); + + if (!msg) + { + Ret = NDIS_STATUS_RESOURCES; + goto error; + } + + /* Fill parameter here*/ + CmdPmStateCtrl.ucWlanIdx = ucWlanIdx; + CmdPmStateCtrl.ucPmNumber = ucPmNumber; + CmdPmStateCtrl.ucPmState = ucPmState; + + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_PM_STATE_CTRL, TRUE, 0,TRUE, TRUE, 8, NULL, CmdExtPmStateCtrlRsp); + + AndesAppendCmdMsg(msg, (char *)&CmdPmStateCtrl, sizeof(CmdPmStateCtrl)); + + Ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_OFF, ("%s:(Ret = %d)\n", __FUNCTION__, Ret)); + return Ret; +} + +INT32 CmdEdcaParameterSet(RTMP_ADAPTER *pAd, CMD_EDCA_SET_T EdcaParam) +{ + struct cmd_msg *msg; + INT32 ret=0,size=0; + + size = 4+sizeof(TX_AC_PARAM_T)*EdcaParam.ucTotalNum; + + msg = AndesAllocCmdMsg(pAd, size); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_EDCA_SET, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + AndesAppendCmdMsg(msg, (char *)&EdcaParam,size); + + + ret = AndesSendCmdMsg(pAd, msg); + + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + + + +INT32 CmdSlotTimeSet(RTMP_ADAPTER *pAd, UINT8 SlotTime,UINT8 SifsTime,UINT8 RifsTime,UINT16 EifsTime) +{ + struct cmd_msg *msg; + INT32 ret=0; + + CMD_SLOT_TIME_SET_T cmdSlotTime; + + NdisZeroMemory(&cmdSlotTime,sizeof(CMD_SLOT_TIME_SET_T)); + + msg = AndesAllocCmdMsg(pAd, sizeof(CMD_SLOT_TIME_SET_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_SLOT_TIME_SET, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + cmdSlotTime.u2Eifs = cpu2le16(EifsTime); + cmdSlotTime.ucRifs = RifsTime; + cmdSlotTime.ucSifs = SifsTime; + cmdSlotTime.ucSlotTime = SlotTime; + + AndesAppendCmdMsg(msg, (char *)&cmdSlotTime,sizeof(CMD_SLOT_TIME_SET_T)); + + + ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + + +INT32 CmdIdConfigInternalSetting(RTMP_ADAPTER *pAd, UINT8 SubOpCode, UINT8 Param) +{ + struct cmd_msg *msg; + INT32 ret=0; + CMD_CONFIG_INTERNAL_SETTING_T CmdConfigInternalSetting; + + NdisZeroMemory(&CmdConfigInternalSetting, sizeof(CMD_CONFIG_INTERNAL_SETTING_T)); + + msg = AndesAllocCmdMsg(pAd, sizeof(CMD_CONFIG_INTERNAL_SETTING_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_CONFIG_INTERNAL_SETTING, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + CmdConfigInternalSetting.ucSubOpcode = SubOpCode; + CmdConfigInternalSetting.aucPara[0] = Param; + + AndesAppendCmdMsg(msg, (char *)&CmdConfigInternalSetting, sizeof(CMD_CONFIG_INTERNAL_SETTING_T)); + + ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_INFO, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + return ret; +} + +#ifdef BCN_OFFLOAD_SUPPORT +VOID RT28xx_UpdateBeaconToMcu( + IN RTMP_ADAPTER *pAd, + IN INT apidx, + IN UCHAR HWBssidIdx, + IN BOOLEAN Enable, + IN ULONG FrameLen, + IN ULONG UpdatePos) +{ + CMD_BCN_UPDATE_T bcn_update; + + NdisZeroMemory(&bcn_update, sizeof(CMD_BCN_UPDATE_T)); + + bcn_update.ucHwBssidIdx = HWBssidIdx; + if (HWBssidIdx > 0) //HWBssid > 0 case, no extendable bssid. + bcn_update.ucExtBssidIdx = 0; + else + bcn_update.ucExtBssidIdx = apidx; + + bcn_update.ucEnable = Enable; + //bcn_update.ucWlanIdx = 0;//hardcode at present + bcn_update.u2BcnPeriod = pAd->CommonCfg.BeaconPeriod; + + CmdBcnUpdateSet(pAd, bcn_update); +} +#endif /*BCN_OFFLOAD_SUPPORT*/ + +#ifdef MT_WOW_SUPPORT +static VOID EventExtCmdPacketFilterRsp(struct cmd_msg *msg, char *Data, UINT16 Len) +{ + P_EXT_EVENT_PF_GENERAL_T pPFRsp = (P_EXT_EVENT_PF_GENERAL_T)Data; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv; + + DBGPRINT(RT_DEBUG_OFF, ("%s: u4PfCmdType = 0x%x u4Status = 0x%x\n", + __FUNCTION__, le2cpu32(pPFRsp->u4PfCmdType), le2cpu32(pPFRsp->u4Status))); +} + +static VOID EventExtCmdWakeupOptionRsp(struct cmd_msg *msg, char *Data, UINT16 Len) +{ + P_EXT_EVENT_WAKEUP_OPTION_T pWakeOptRsp = (P_EXT_EVENT_WAKEUP_OPTION_T)Data; + RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)msg->priv; + + DBGPRINT(RT_DEBUG_OFF, ("%s: u4PfCmdType = 0x%x u4Status = 0x%x\n", + __FUNCTION__, le2cpu32(pWakeOptRsp->u4PfCmdType), le2cpu32(pWakeOptRsp->u4Status))); + +} + +VOID MT76xxAndesWOWEnable( + IN PRTMP_ADAPTER pAd) +{ + + //hw-enable cmd + //1. magic, parameter=enable + //2. eapol , param = enable + //3. bssid , param = bssid[3:0] + //4. mode, parm = white + //5. PF, param = enable + //wakeup command param = choose usb. others dont' care + + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + MAC_TABLE_ENTRY *pEntry = NULL; + + struct cmd_msg *msg; + INT32 ret = NDIS_STATUS_SUCCESS; + + + //CMD_PACKET_FILTER_MAGIC_PACKET_T CmdMagicPacket; + CMD_PACKET_FILTER_GLOBAL_T CmdPFGlobal; + CMD_PACKET_FILTER_GTK_T CmdGTK; + CMD_PACKET_FILTER_WAKEUP_OPTION_T CmdWakeupOption; + CMD_PACKET_FILTER_ARPNS_T CmdARPNS; + + DBGPRINT(RT_DEBUG_OFF, ("%s:\n", __FUNCTION__)); + + /* security configuration */ + NdisZeroMemory(&CmdGTK, sizeof(CmdGTK)); + + msg = AndesAllocCmdMsg(pAd, sizeof(CMD_PACKET_FILTER_GTK_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_PACKET_FILTER, TRUE, 0, + TRUE, TRUE, sizeof(EXT_EVENT_PF_GENERAL_T), NULL, EventExtCmdPacketFilterRsp); + + CmdGTK.PFType = cpu2le32(_ENUM_TYPE_GTK_REKEY); + + if (wdev->AuthMode == Ndis802_11AuthModeWPAPSK) + CmdGTK.WPAVersion = cpu2le32(0); + else + CmdGTK.WPAVersion = cpu2le32(1); + + pEntry = &pAd->MacTab.Content[BSSID_WCID]; + +#ifdef RT_BIG_ENDIAN + { + int index = 0; + UINT32 *pKey = (UINT32 *)pEntry->PTK; + for (index=0; index < 64; index += 4) + { + *pKey = SWAP32(*pKey); + pKey++; + } + } +#else + NdisCopyMemory(CmdGTK.PTK, pEntry->PTK, 64); +#endif + + CmdGTK.BssidIndex = cpu2le32(0); + CmdGTK.OwnMacIndex = cpu2le32(0x0); + CmdGTK.WmmIndex = cpu2le32(0); + + if (wdev->AuthMode >= Ndis802_11AuthModeWPAPSK){ + NdisCopyMemory(CmdGTK.ReplayCounter, pEntry->R_Counter, LEN_KEY_DESC_REPLAY); + CmdGTK.GroupKeyIndex = cpu2le32(MCAST_WCID); + CmdGTK.PairKeyIndex = cpu2le32(pEntry->wcid); + } + + DBGPRINT(RT_DEBUG_OFF, ("%s: BssidIndex %d, GroupKeyIndex %d, OwnMacIndex %d, PairKeyIndex %d, WmmIndex %d\n", + __FUNCTION__, CmdGTK.BssidIndex, CmdGTK.GroupKeyIndex, CmdGTK.OwnMacIndex, CmdGTK.PairKeyIndex, CmdGTK.WmmIndex)); + + AndesAppendCmdMsg(msg, (char *)&CmdGTK, sizeof(CMD_PACKET_FILTER_GTK_T)); + + ret = AndesSendCmdMsg(pAd, msg); + + // Wakeup option + NdisZeroMemory(&CmdWakeupOption, sizeof(CMD_PACKET_FILTER_WAKEUP_OPTION_T)); + + msg = AndesAllocCmdMsg(pAd, sizeof(CMD_PACKET_FILTER_WAKEUP_OPTION_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_WAKEUP_OPTION, TRUE, 0, + TRUE, TRUE, sizeof(EXT_EVENT_WAKEUP_OPTION_T), NULL, EventExtCmdWakeupOptionRsp); + + CmdWakeupOption.WakeupInterface = cpu2le32(pAd->WOW_Cfg.nWakeupInterface); + CmdWakeupOption.GPIONumber = cpu2le32(pAd->WOW_Cfg.nSelectedGPIO); + CmdWakeupOption.GPIOTimer = cpu2le32(pAd->WOW_Cfg.nHoldTime); // unit is us + if (pAd->WOW_Cfg.nWakeupInterface == WOW_WAKEUP_BY_GPIO) + CmdWakeupOption.GpioParameter |= 0x1; + if (pAd->WOW_Cfg.bGPIOHighLow == WOW_GPIO_LOW_TO_HIGH) + CmdWakeupOption.GpioParameter |= 0x4; + else + CmdWakeupOption.GpioParameter |= 0x2; + + DBGPRINT(RT_DEBUG_OFF, ("%s:(WakeupInterface=%d, GPIONumber=%d, GPIOTimer=%d, GpioParameter=0x%x)\n", __FUNCTION__, CmdWakeupOption.WakeupInterface, + CmdWakeupOption.GPIONumber, CmdWakeupOption.GPIOTimer, CmdWakeupOption.GpioParameter)); + + AndesAppendCmdMsg(msg, (char *)&CmdWakeupOption, sizeof(CMD_PACKET_FILTER_WAKEUP_OPTION_T)); + + ret = AndesSendCmdMsg(pAd, msg); + + + // WOW enable + NdisZeroMemory(&CmdPFGlobal, sizeof(CMD_PACKET_FILTER_GLOBAL_T)); + + msg = AndesAllocCmdMsg(pAd, sizeof(CMD_PACKET_FILTER_GLOBAL_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_PACKET_FILTER, TRUE, 0, + TRUE, TRUE, sizeof(EXT_EVENT_PF_GENERAL_T), NULL, EventExtCmdPacketFilterRsp); + + CmdPFGlobal.PFType = cpu2le32(_ENUM_TYPE_GLOBAL_EN); + CmdPFGlobal.FunctionSelect = cpu2le32(_ENUM_GLOBAL_WOW_EN); + CmdPFGlobal.Enable = cpu2le32(1); //bit0=1 mean BSS0 for staion mode + + AndesAppendCmdMsg(msg, (char *)&CmdPFGlobal, sizeof(CMD_PACKET_FILTER_GLOBAL_T)); + + ret = AndesSendCmdMsg(pAd, msg); + +error: + DBGPRINT(RT_DEBUG_OFF, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + + return; + +} + +VOID MT76xxAndesWOWDisable( + IN PRTMP_ADAPTER pAd) +{ + CMD_PACKET_FILTER_GLOBAL_T CmdPFGlobal; + + struct cmd_msg *msg; + INT32 ret = NDIS_STATUS_SUCCESS; + + DBGPRINT(RT_DEBUG_OFF, ("%s:\n", __FUNCTION__)); + + // PF disable + NdisZeroMemory(&CmdPFGlobal, sizeof(CMD_PACKET_FILTER_GLOBAL_T)); + + msg = AndesAllocCmdMsg(pAd, sizeof(CMD_PACKET_FILTER_GLOBAL_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_PACKET_FILTER, TRUE, 0, + TRUE, TRUE, sizeof(EXT_EVENT_PF_GENERAL_T), NULL, EventExtCmdPacketFilterRsp); + + CmdPFGlobal.PFType = cpu2le32(_ENUM_TYPE_GLOBAL_EN); + CmdPFGlobal.FunctionSelect = cpu2le32(_ENUM_GLOBAL_WOW_EN); + CmdPFGlobal.Enable = cpu2le32(0); + + AndesAppendCmdMsg(msg, (char *)&CmdPFGlobal, sizeof(CMD_PACKET_FILTER_GLOBAL_T)); + + ret = AndesSendCmdMsg(pAd, msg); + + /* traffic to Host */ + NdisZeroMemory(&CmdPFGlobal, sizeof(CMD_PACKET_FILTER_GLOBAL_T)); + + msg = AndesAllocCmdMsg(pAd, sizeof(CMD_PACKET_FILTER_GLOBAL_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_PACKET_FILTER, TRUE, 0, + TRUE, TRUE, sizeof(EXT_EVENT_PF_GENERAL_T), NULL, EventExtCmdPacketFilterRsp); + + CmdPFGlobal.PFType = cpu2le32(_ENUM_TYPE_GLOBAL_EN); + CmdPFGlobal.FunctionSelect = cpu2le32(_ENUM_GLOBAL_ALL_TOMCU); + CmdPFGlobal.Enable = cpu2le32(0); + + AndesAppendCmdMsg(msg, (char *)&CmdPFGlobal, sizeof(CMD_PACKET_FILTER_GLOBAL_T)); + + ret = AndesSendCmdMsg(pAd, msg); + + + /* Restore MAC TX/RX */ + //AsicSetMacTxRx(pAd, ASIC_MAC_TXRX, TRUE); + + +error: + DBGPRINT(RT_DEBUG_OFF, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + + return; + + +} + +VOID MT76xxAndesWOWInit( + IN PRTMP_ADAPTER pAd) +{ + struct wifi_dev *wdev = &pAd->StaCfg.wdev; + MAC_TABLE_ENTRY *pEntry = NULL; + + struct cmd_msg *msg; + INT32 ret = NDIS_STATUS_SUCCESS; + + CMD_PACKET_FILTER_MAGIC_PACKET_T CmdMagicPacket; + CMD_PACKET_FILTER_GLOBAL_T CmdPFGlobal; + CMD_PACKET_FILTER_GTK_T CmdGTK; + CMD_PACKET_FILTER_WAKEUP_OPTION_T CmdWakeupOption; + + if (!pAd->WOW_Cfg.bEnable) + return; + + DBGPRINT(RT_DEBUG_OFF, ("%s:\n", __FUNCTION__)); + + + if (pAd->WOW_Cfg.nWakeupInterface == WOW_WAKEUP_BY_GPIO){ + + // Wakeup option + NdisZeroMemory(&CmdWakeupOption, sizeof(CMD_PACKET_FILTER_WAKEUP_OPTION_T)); + + msg = AndesAllocCmdMsg(pAd, sizeof(CMD_PACKET_FILTER_WAKEUP_OPTION_T)); + + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_WAKEUP_OPTION, TRUE, 0, + TRUE, TRUE, sizeof(EXT_EVENT_WAKEUP_OPTION_T), NULL, EventExtCmdWakeupOptionRsp); + + CmdWakeupOption.WakeupInterface = cpu2le32(pAd->WOW_Cfg.nWakeupInterface); + CmdWakeupOption.GPIONumber = cpu2le32(pAd->WOW_Cfg.nSelectedGPIO); + CmdWakeupOption.GPIOTimer = cpu2le32(pAd->WOW_Cfg.nHoldTime); // unit is us + if (pAd->WOW_Cfg.nWakeupInterface == WOW_WAKEUP_BY_GPIO) + CmdWakeupOption.GpioParameter |= 0x1; + if (pAd->WOW_Cfg.bGPIOHighLow == WOW_GPIO_LOW_TO_HIGH) + CmdWakeupOption.GpioParameter |= 0x4; + else + CmdWakeupOption.GpioParameter |= 0x2; + + DBGPRINT(RT_DEBUG_OFF, ("%s:(WakeupInterface=%d, GPIONumber=%d, GPIOTimer=%d, GpioParameter=0x%x)\n", __FUNCTION__, CmdWakeupOption.WakeupInterface, + CmdWakeupOption.GPIONumber, CmdWakeupOption.GPIOTimer, CmdWakeupOption.GpioParameter)); + + AndesAppendCmdMsg(msg, (char *)&CmdWakeupOption, sizeof(CMD_PACKET_FILTER_WAKEUP_OPTION_T)); + + ret = AndesSendCmdMsg(pAd, msg); + } + +error: + DBGPRINT(RT_DEBUG_OFF, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + + return; + +} + +#endif + +INT32 CmdACQueue_Control +( IN struct _RTMP_ADAPTER *ad, + IN UINT8 ucation, // 0: stop; 1: flush; 2: start + IN UINT8 BssidIdx, + IN UINT32 u4AcQueueMap) +{ + struct cmd_msg *msg; + EXT_CMD_AC_QUEUE_CONTROL_T ac_queue_control; + int ret; + + DBGPRINT(RT_DEBUG_TRACE, ("CmdACQueue_Control ucation %d BssidIdx %d u4AcQueueMap %d\n",ucation,BssidIdx,u4AcQueueMap)); + + msg = AndesAllocCmdMsg(ad, sizeof(EXT_CMD_AC_QUEUE_CONTROL_T)); + if (!msg) + { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, P1_Q0, EXT_CID, CMD_SET, EXT_CMD_ID_AC_QUEUE_CONTROL, FALSE, 0, + FALSE, FALSE, 0, NULL, NULL); + + NdisZeroMemory(&ac_queue_control, sizeof(EXT_CMD_AC_QUEUE_CONTROL_T)); + ac_queue_control.ucAction = ucation; + ac_queue_control.ucBssidIdx =BssidIdx; + ac_queue_control.u4AcQueueMap =cpu2le32(u4AcQueueMap); + + AndesAppendCmdMsg(msg, (char *)&ac_queue_control, sizeof(EXT_CMD_AC_QUEUE_CONTROL_T)); + ret = AndesSendCmdMsg(ad, msg); +error: + DBGPRINT(RT_DEBUG_OFF, ("%s:(ret = %d)\n", __FUNCTION__, ret)); + + return ret; + + +} + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/andes_rlt.c b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/andes_rlt.c new file mode 100644 index 000000000..a48985a31 --- /dev/null +++ b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/andes_rlt.c @@ -0,0 +1,1766 @@ +/* + *************************************************************************** + * 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: + andes_rlt.c + + Abstract: + on-chip CPU related codes + + Revision History: + Who When What + -------- ---------- ---------------------------------------------- +*/ + +#include "rt_config.h" +#ifdef RTMP_PCI_SUPPORT +INT32 AndesRltPciLoadRomPatch(RTMP_ADAPTER *ad) +{ + int ret = NDIS_STATUS_SUCCESS; + UINT32 start_offset, end_offset; + UINT32 loop = 0, idx = 0, val = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + UINT32 mac_value; + POS_COOKIE obj = (POS_COOKIE)ad->OS_Cookie; + + if (cap->rom_code_protect) { +loadfw_protect: + RTMP_IO_READ32(ad, SEMAPHORE_03, &mac_value); + loop++; + + if (((mac_value & 0x01) == 0x00) && (loop < GET_SEMAPHORE_RETRY_MAX)) { + RtmpOsMsDelay(1); + goto loadfw_protect; + } + + if (loop >= GET_SEMAPHORE_RETRY_MAX) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: can not get the hw semaphore\n", __FUNCTION__)); + return NDIS_STATUS_FAILURE; + } + } + + /* check rom patch if ready */ + if (MT_REV_GTE(ad, MT76x2, REV_MT76x2E3)) { + RTMP_IO_READ32(ad, CLOCK_CTL, &mac_value); + } else { + RTMP_IO_READ32(ad, COM_REG0, &mac_value); + } + + if (MT_REV_GTE(ad, MT76x2, REV_MT76x2E3)) { + if (((mac_value & 0x01) == 0x01) && (cap->rom_code_protect)) { + goto done; + } + } else { + if (((mac_value & 0x02) == 0x02) && (cap->rom_code_protect)) { + goto done; + } + } + + if (cap->load_code_method == BIN_FILE_METHOD) { + DBGPRINT(RT_DEBUG_OFF, ("load rom patch from /lib/firmware/%s\n", cap->rom_patch_bin_file_name)); + OS_LOAD_CODE_FROM_BIN(&cap->rom_patch, cap->rom_patch_bin_file_name, obj->pci_dev, &cap->rom_patch_len); + } else { + cap->rom_patch = cap->rom_patch_header_image; + } + + if (!cap->rom_patch) { + if (cap->load_code_method == BIN_FILE_METHOD) { + DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a rom patch(/lib/firmware/%s), load_method(%d)\n", __FUNCTION__, cap->rom_patch_bin_file_name, cap->load_code_method)); + } else { + DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a rom patch, load_method(%d)\n", + __FUNCTION__, cap->load_code_method)); + } + ret = NDIS_STATUS_FAILURE; + goto done; + } + + /* get rom patch information */ + DBGPRINT(RT_DEBUG_OFF, ("build time = \n")); + + for (loop = 0; loop < 16; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->rom_patch + loop))); + + if (IS_MT76x2(ad)) { + if (((strncmp(cap->rom_patch, "20130809", 8) >= 0)) && (MT_REV_GTE(ad, MT76x2, REV_MT76x2E3))) { + DBGPRINT(RT_DEBUG_OFF, ("rom patch for E3 IC\n")); + + } else if (((strncmp(cap->rom_patch, "20130809", 8) < 0)) && (MT_REV_LT(ad, MT76x2, REV_MT76x2E3))){ + + DBGPRINT(RT_DEBUG_OFF, ("rom patch for E2 IC\n")); + } else { + DBGPRINT(RT_DEBUG_OFF, ("rom patch do not match IC version\n")); + RTMP_IO_READ32(ad, 0x0, &mac_value); + DBGPRINT(RT_DEBUG_OFF, ("IC version(%x)\n", mac_value)); + ret = NDIS_STATUS_FAILURE; + goto done; + } + } + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("platform = \n")); + + for (loop = 0; loop < 4; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->rom_patch + 16 + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("hw/sw version = \n")); + + for (loop = 0; loop < 4; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->rom_patch + 20 + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + DBGPRINT(RT_DEBUG_OFF, ("patch version = \n")); + + for (loop = 0; loop < 4; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->rom_patch + 24 + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + + RTMP_IO_WRITE32(ad, PCIE_REMAP_BASE4, cap->rom_patch_offset - 10000); + + start_offset = PATCH_INFO_SIZE; + end_offset = cap->rom_patch_len; + + /* Load rom patch code */ + for (idx = start_offset; idx < end_offset; idx += 4) + { + val = (*(cap->rom_patch + idx)) + + (*(cap->rom_patch + idx + 3) << 24) + + (*(cap->rom_patch + idx + 2) << 16) + + (*(cap->rom_patch + idx + 1) << 8); + + RTMP_IO_WRITE32(ad, 0x90000 + (idx - PATCH_INFO_SIZE), val); + } + + RTMP_IO_WRITE32(ad, PCIE_REMAP_BASE4, 0x0); + + /* Trigger rom */ + RTMP_IO_WRITE32(ad, INT_LEVEL, 0x04); + + /* check rom if ready */ + loop = 0; + do + { + if (MT_REV_GTE(ad, MT76x2, REV_MT76x2E3)) { + RTMP_IO_READ32(ad, CLOCK_CTL, &mac_value); + if ((mac_value & 0x01)== 0x01) + break; + } else { + RTMP_IO_READ32(ad, COM_REG0, &mac_value); + if ((mac_value & 0x02)== 0x02) + break; + } + + RtmpOsMsDelay(10); + loop++; + } while (loop <= 200); + + if (MT_REV_GTE(ad, MT76x2, REV_MT76x2E3)) { + DBGPRINT(RT_DEBUG_TRACE, ("%s: CLOCK_CTL(0x%x) = 0x%x\n", __FUNCTION__, CLOCK_CTL, mac_value)); + if ((mac_value & 0x01) != 0x01) + ret = NDIS_STATUS_FAILURE; + } else { + DBGPRINT(RT_DEBUG_TRACE, ("%s: COM_REG0(0x%x) = 0x%x\n", __FUNCTION__, COM_REG0, mac_value)); + if ((mac_value & 0x02) != 0x02) + ret = NDIS_STATUS_FAILURE; + } + +done: + if (cap->rom_code_protect) + RTMP_IO_WRITE32(ad, SEMAPHORE_03, 0x1); + + return ret; +} + + +INT32 AndesRltPciEraseRomPatch(RTMP_ADAPTER *ad) +{ + RTMP_CHIP_CAP *cap = &ad->chipCap; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + if (cap->load_code_method == BIN_FILE_METHOD) { + if (cap->rom_patch) + os_free_mem(NULL, cap->rom_patch); + cap->rom_patch = NULL; + } + + return 0; +} + + +INT32 AndesRltPciEraseFw(RTMP_ADAPTER *ad) +{ + int ret = NDIS_STATUS_SUCCESS; + UINT32 ilm_len, dlm_len; + UINT16 fw_ver, build_ver; + UINT32 loop = 0, idx = 0, val = 0; + UINT32 mac_value; + UINT32 start_offset, end_offset; + RTMP_CHIP_CAP *cap = &ad->chipCap; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + if (!ad->chipCap.ram_code_protect) { + + ilm_len = (*(cap->FWImageName + 3) << 24) | (*(cap->FWImageName + 2) << 16) | + (*(cap->FWImageName + 1) << 8) | (*cap->FWImageName); + + dlm_len = (*(cap->FWImageName + 7) << 24) | (*(cap->FWImageName + 6) << 16) | + (*(cap->FWImageName + 5) << 8) | (*(cap->FWImageName + 4)); + + fw_ver = (*(cap->FWImageName + 11) << 8) | (*(cap->FWImageName + 10)); + + build_ver = (*(cap->FWImageName + 9) << 8) | (*(cap->FWImageName + 8)); + + DBGPRINT(RT_DEBUG_TRACE, ("FW Version:%d.%d.%02d ", (fw_ver & 0xf000) >> 8, + (fw_ver & 0x0f00) >> 8, fw_ver & 0x00ff)); + DBGPRINT(RT_DEBUG_TRACE, ("Build:%x\n", build_ver)); + DBGPRINT(RT_DEBUG_TRACE, ("Build Time:")); + + for (loop = 0; loop < 16; loop++) + DBGPRINT(RT_DEBUG_TRACE, ("%c", *(cap->FWImageName + 16 + loop))); + + DBGPRINT(RT_DEBUG_TRACE, ("\n")); + + DBGPRINT(RT_DEBUG_TRACE, ("ILM Length = %d(bytes)\n", ilm_len)); + DBGPRINT(RT_DEBUG_TRACE, ("DLM Length = %d(bytes)\n", dlm_len)); + + RTMP_IO_WRITE32(ad, PCIE_REMAP_BASE4, cap->ilm_offset); + + if (IS_MT76x2(ad)) { + start_offset = FW_INFO_SIZE; + RTMP_IO_WRITE32(ad, INT_LEVEL, 0x1); + RtmpOsMsDelay(20); + } else { + if (cap->ram_code_protect) { + RTMP_IO_WRITE32(ad, CPU_CTL, 0x0); + RTMP_IO_WRITE32(ad, CPU_CTL, (0x1<<20)); + RTMP_IO_WRITE32(ad, RESET_CTL, 0x10); + RTMP_IO_WRITE32(ad, RESET_CTL, 0x300); + RTMP_IO_WRITE32(ad, COM_REG0, 0x0); + + start_offset = FW_INFO_SIZE + IV_SIZE; + } else { + RTMP_IO_WRITE32(ad, RESET_CTL, 0x10); /* reset fce */ + RTMP_IO_WRITE32(ad, RESET_CTL, 0x200); /* reset cpu */ + RTMP_IO_WRITE32(ad, COM_REG0, 0x0); /* clear mcu ready bit */ + + start_offset = FW_INFO_SIZE; + } + } + + end_offset = FW_INFO_SIZE + ilm_len; + + if (!IS_MT76x2(ad)) { + /* erase ilm */ + for (idx = start_offset; idx < end_offset; idx += 4) { + val = (*(cap->FWImageName + idx)) + + (*(cap->FWImageName + idx + 3) << 24) + + (*(cap->FWImageName + idx + 2) << 16) + + (*(cap->FWImageName + idx + 1) << 8); + + RTMP_IO_WRITE32(ad, 0x80000 + (idx - FW_INFO_SIZE), 0); + } + + if (cap->ram_code_protect) { + /* Loading IV part into last 64 bytes of ILM */ + start_offset = FW_INFO_SIZE; + end_offset = FW_INFO_SIZE + IV_SIZE; + + for (idx = start_offset; idx < end_offset; idx += 4) + { + val = (*(cap->FWImageName + idx)) + + (*(cap->FWImageName + idx + 3) << 24) + + (*(cap->FWImageName + idx + 2) << 16) + + (*(cap->FWImageName + idx + 1) << 8); + + RTMP_IO_WRITE32(ad, 0x80000 + (0x54000 - IV_SIZE) + (idx - FW_INFO_SIZE), 0); + } + } + + RTMP_IO_WRITE32(ad, PCIE_REMAP_BASE4, cap->dlm_offset); + + start_offset = 32 + ilm_len; + end_offset = 32 + ilm_len + dlm_len; + + /* erase dlm */ + for (idx = start_offset; idx < end_offset; idx += 4) { + val = (*(cap->FWImageName + idx)) + + (*(cap->FWImageName + idx + 3) << 24) + + (*(cap->FWImageName + idx + 2) << 16) + + (*(cap->FWImageName + idx + 1) << 8); + + RTMP_IO_WRITE32(ad, 0x80000 + (0x54000 - IV_SIZE) + (idx - FW_INFO_SIZE), 0); + } + } + + RTMP_IO_READ32(ad, COM_REG0, &mac_value); + DBGPRINT(RT_DEBUG_TRACE, ("%s: COM_REG0(0x%x) = 0x%x\n", __FUNCTION__, COM_REG0, mac_value)); + RTMP_IO_READ32(ad, RESET_CTL, &mac_value); + DBGPRINT(RT_DEBUG_TRACE, ("%s: RESET_CTL(0x%x) = 0x%x\n", __FUNCTION__, RESET_CTL, mac_value)); + } + + if (cap->load_code_method == BIN_FILE_METHOD) { + if (cap->FWImageName) + os_free_mem(NULL, cap->FWImageName); + cap->FWImageName = NULL; + } + + return ret; +} + + +NDIS_STATUS AndesRltPciLoadFw(RTMP_ADAPTER *ad) +{ + int ret = NDIS_STATUS_SUCCESS; + UINT32 ilm_len, dlm_len; + USHORT fw_ver, build_ver; + UINT32 loop = 0, idx = 0, val = 0; + UINT32 mac_value; + UINT32 start_offset, end_offset; + RTMP_CHIP_CAP *cap = &ad->chipCap; + POS_COOKIE obj = (POS_COOKIE)ad->OS_Cookie; + + if (cap->ram_code_protect) { +loadfw_protect: + RTMP_IO_READ32(ad, SEMAPHORE_00, &mac_value); + loop++; + + if (((mac_value & 0x01) == 0) && (loop < GET_SEMAPHORE_RETRY_MAX)) { + RtmpOsMsDelay(1); + goto loadfw_protect; + } + + if (loop >= GET_SEMAPHORE_RETRY_MAX) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: can not get the hw semaphore\n", __FUNCTION__)); + return NDIS_STATUS_FAILURE; + } + } + + /* check MCU if ready */ + RTMP_IO_READ32(ad, COM_REG0, &mac_value); + + if (((mac_value & 0x01) == 0x01) && (cap->ram_code_protect)) { + goto done; + } + + if (cap->load_code_method == BIN_FILE_METHOD) { + DBGPRINT(RT_DEBUG_OFF, ("load fw image from /lib/firmware/%s\n", cap->fw_bin_file_name)); + OS_LOAD_CODE_FROM_BIN(&cap->FWImageName, cap->fw_bin_file_name, obj->pci_dev, &cap->fw_len); + } else { + cap->FWImageName = cap->fw_header_image; + } + + if (!cap->FWImageName) { + if (cap->load_code_method == BIN_FILE_METHOD) { + DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a fw image(/lib/firmware/%s), load_method(%d)\n", __FUNCTION__, cap->fw_bin_file_name, cap->load_code_method)); + } else { + DBGPRINT(RT_DEBUG_ERROR, ("%s:Please assign a fw image, load_method(%d)\n", + __FUNCTION__, cap->load_code_method)); + } + ret = NDIS_STATUS_FAILURE; + goto done; + } + + ilm_len = (*(cap->FWImageName + 3) << 24) | (*(cap->FWImageName + 2) << 16) | + (*(cap->FWImageName + 1) << 8) | (*cap->FWImageName); + + dlm_len = (*(cap->FWImageName + 7) << 24) | (*(cap->FWImageName + 6) << 16) | + (*(cap->FWImageName + 5) << 8) | (*(cap->FWImageName + 4)); + + fw_ver = (*(cap->FWImageName + 11) << 8) | (*(cap->FWImageName + 10)); + + build_ver = (*(cap->FWImageName + 9) << 8) | (*(cap->FWImageName + 8)); + + DBGPRINT(RT_DEBUG_OFF, ("FW Version:%d.%d.%02d ", (fw_ver & 0xf000) >> 8, + (fw_ver & 0x0f00) >> 8, fw_ver & 0x00ff)); + DBGPRINT(RT_DEBUG_OFF, ("Build:%x\n", build_ver)); + DBGPRINT(RT_DEBUG_OFF, ("Build Time:")); + + for (loop = 0; loop < 16; loop++) + DBGPRINT(RT_DEBUG_OFF, ("%c", *(cap->FWImageName + 16 + loop))); + + DBGPRINT(RT_DEBUG_OFF, ("\n")); + + if (IS_MT76x2(ad)) { + if (((strncmp(cap->FWImageName + 16, "20130811", 8) >= 0)) && (MT_REV_GTE(ad, MT76x2, REV_MT76x2E3))) { + DBGPRINT(RT_DEBUG_OFF, ("fw for E3 IC\n")); + + } else if (((strncmp(cap->FWImageName + 16, "20130811", 8) < 0)) && (MT_REV_LT(ad, MT76x2, REV_MT76x2E3))){ + + DBGPRINT(RT_DEBUG_OFF, ("fw for E2 IC\n")); + } else { + DBGPRINT(RT_DEBUG_OFF, ("fw do not match IC version\n")); + RTMP_IO_READ32(ad, 0x0, &mac_value); + DBGPRINT(RT_DEBUG_OFF, ("IC version(%x)\n", mac_value)); + ret = NDIS_STATUS_FAILURE; + goto done; + } + } + + DBGPRINT(RT_DEBUG_TRACE, ("ILM Length = %d(bytes)\n", ilm_len)); + DBGPRINT(RT_DEBUG_TRACE, ("DLM Length = %d(bytes)\n", dlm_len)); + + RTMP_IO_WRITE32(ad, PCIE_REMAP_BASE4, cap->ilm_offset); + + if (cap->ram_code_protect) + start_offset = FW_INFO_SIZE + IV_SIZE; + else + start_offset = FW_INFO_SIZE; + + end_offset = FW_INFO_SIZE + ilm_len; + + /* Load ILM code */ + for (idx = start_offset; idx < end_offset; idx += 4) + { + val = (*(cap->FWImageName + idx)) + + (*(cap->FWImageName + idx + 3) << 24) + + (*(cap->FWImageName + idx + 2) << 16) + + (*(cap->FWImageName + idx + 1) << 8); + + RTMP_IO_WRITE32(ad, 0x80000 + (idx - FW_INFO_SIZE), val); + } + + if (cap->ram_code_protect) + { + /* Loading IV part into last 64 bytes of ILM */ + start_offset = FW_INFO_SIZE; + end_offset = FW_INFO_SIZE + IV_SIZE; + + for (idx = start_offset; idx < end_offset; idx += 4) + { + val = (*(cap->FWImageName + idx)) + + (*(cap->FWImageName + idx + 3) << 24) + + (*(cap->FWImageName + idx + 2) << 16) + + (*(cap->FWImageName + idx + 1) << 8); + + RTMP_IO_WRITE32(ad, 0x80000 + (0x54000 - IV_SIZE) + (idx - FW_INFO_SIZE), val); + } + } + + if (IS_MT76x2(ad)) { + RTMP_IO_WRITE32(ad, PCIE_REMAP_BASE4, cap->dlm_offset - 0x10000); + } else + RTMP_IO_WRITE32(ad, PCIE_REMAP_BASE4, cap->dlm_offset); + + start_offset = FW_INFO_SIZE + ilm_len; + end_offset = FW_INFO_SIZE + ilm_len + dlm_len; + + /* Load DLM code */ + for (idx = start_offset; idx < end_offset; idx += 4) + { + val = (*(cap->FWImageName + idx)) + + (*(cap->FWImageName + idx + 3) << 24) + + (*(cap->FWImageName + idx + 2) << 16) + + (*(cap->FWImageName + idx + 1) << 8); + + if (IS_MT76x2(ad)) { + if (MT_REV_GTE(ad, MT76x2, REV_MT76x2E3)) + RTMP_IO_WRITE32(ad, 0x90800 + (idx - FW_INFO_SIZE - ilm_len), val); + else + RTMP_IO_WRITE32(ad, 0x90000 + (idx - FW_INFO_SIZE - ilm_len), val); + } else + RTMP_IO_WRITE32(ad, 0x80000 + (idx - FW_INFO_SIZE - ilm_len), val); + } + + RTMP_IO_WRITE32(ad, PCIE_REMAP_BASE4, 0x0); + + if (cap->ram_code_protect) + { + /* Trigger Firmware */ + RTMP_IO_WRITE32(ad, INT_LEVEL, 0x03); + } + else + { + if (IS_MT76x2(ad)) + RTMP_IO_WRITE32(ad, INT_LEVEL, 0x2); + else + RTMP_IO_WRITE32(ad, RESET_CTL, 0x300); + } + + /* check MCU if ready */ + loop = 0; + do + { + RTMP_IO_READ32(ad, COM_REG0, &mac_value); + if ((mac_value & 0x01)== 0x1) + break; + RtmpOsMsDelay(10); + loop++; + } while (loop <= 200); + + DBGPRINT(RT_DEBUG_TRACE, ("%s: COM_REG0(0x%x) = 0x%x\n", __FUNCTION__, COM_REG0, mac_value)); + + RTMP_IO_READ32(ad, COM_REG0, &mac_value); + mac_value |= (1 << 1); + RTMP_IO_WRITE32(ad, COM_REG0, mac_value); + + if ((mac_value & 0x01 ) != 0x1) + ret = NDIS_STATUS_FAILURE; + +done: + if (cap->ram_code_protect) + RTMP_IO_WRITE32(ad, SEMAPHORE_00, 0x1); + + return ret; +} +#endif + + + + +INT32 AndesRltUsbEraseFw(RTMP_ADAPTER *ad) +{ + RTMP_CHIP_CAP *cap = &ad->chipCap; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); + + if (cap->load_code_method == BIN_FILE_METHOD) { + if (cap->FWImageName) + os_free_mem(NULL, cap->FWImageName); + cap->FWImageName = NULL; + } + + return 0; +} + + +VOID AndesRltRxProcessCmdMsg(RTMP_ADAPTER *ad, struct cmd_msg *rx_msg) +{ + PNDIS_PACKET net_pkt = rx_msg->net_pkt; + struct cmd_msg *msg, *msg_tmp; + RXFCE_INFO_CMD *rx_info = (RXFCE_INFO_CMD *)GET_OS_PKT_DATAPTR(net_pkt); + struct MCU_CTRL *ctl = &ad->MCUCtrl; + unsigned long flags; +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)rx_info, TYPE_RXINFO); +#endif + + DBGPRINT(RT_DEBUG_INFO, ("(andex_rx_cmd)info_type=%d,evt_type=%d,d_port=%d," + "qsel=%d,pcie_intr=%d,cmd_seq=%d," + "self_gen=%d,pkt_len=%d\n", + rx_info->info_type, rx_info->evt_type,rx_info->d_port, + rx_info->qsel, rx_info->pcie_intr, rx_info->cmd_seq, + rx_info->self_gen, rx_info->pkt_len)); + + if ((rx_info->info_type != CMD_PACKET)) { + DBGPRINT(RT_DEBUG_ERROR, ("packet is not command response/self event\n")); + return; + } + + + if (rx_info->self_gen) { + /* if have callback function */ + RTEnqueueInternalCmd(ad, CMDTHREAD_RESPONSE_EVENT_CALLBACK, + GET_OS_PKT_DATAPTR(net_pkt) + sizeof(*rx_info), rx_info->pkt_len); + } else { + +#ifdef RTMP_PCI_SUPPORT + RTMP_SPIN_LOCK_IRQSAVE(&ctl->ackq_lock, &flags); +#endif + DlListForEachSafe(msg, msg_tmp, &ctl->ackq, struct cmd_msg, list) { + if (msg->seq == rx_info->cmd_seq) + { + _AndesUnlinkCmdMsg(msg, &ctl->ackq); + +#ifdef RTMP_PCI_SUPPORT + //RTMP_SPIN_UNLOCK_IRQRESTORE(&ctl->ackq_lock, &flags); +#endif + + if ((msg->rsp_payload_len == rx_info->pkt_len) && (msg->rsp_payload_len != 0)) + { + msg->rsp_handler(msg, GET_OS_PKT_DATAPTR(net_pkt) + sizeof(*rx_info), rx_info->pkt_len); + } + else if ((msg->rsp_payload_len == 0) && (rx_info->pkt_len == 8)) + { + DBGPRINT(RT_DEBUG_INFO, ("command response(ack) success\n")); + } + else + { + DBGPRINT(RT_DEBUG_ERROR, ("expect response len(%d), command response len(%d) invalid\n", msg->rsp_payload_len, rx_info->pkt_len)); + msg->rsp_payload_len = rx_info->pkt_len; + } + + if (msg->need_wait) { +#ifdef RTMP_PCI_SUPPORT + msg->ack_done = TRUE; +#endif + + } else { + AndesFreeCmdMsg(msg); + } + +#ifdef RTMP_PCI_SUPPORT + //RTMP_SPIN_LOCK_IRQSAVE(&ctl->ackq_lock, &flags); +#endif + break; + } + } + + +#ifdef RTMP_PCI_SUPPORT + RTMP_SPIN_UNLOCK_IRQRESTORE(&ctl->ackq_lock, &flags); +#endif + } +} + + +#ifdef RTMP_PCI_SUPPORT +#ifdef RLT_MAC +VOID PciRxCmdMsgComplete(RTMP_ADAPTER *ad, RXFCE_INFO *fce_info) +{ + struct cmd_msg *msg; + struct MCU_CTRL *ctl = &ad->MCUCtrl; + + if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) { + return; + } + + DBGPRINT(RT_DEBUG_TRACE, ("%s\n", __FUNCTION__)); + + msg = AndesAllocCmdMsg(ad, sizeof(*fce_info) + fce_info->pkt_len); + + if (!msg) + return; + + AndesAppendCmdMsg(msg, (char *)fce_info, sizeof(*fce_info) + fce_info->pkt_len); + + AndesRxProcessCmdMsg(ad, msg); + + AndesFreeCmdMsg(msg); +} +#endif /* RLT_MAC */ +#endif /* RTMP_PCI_SUPPORT */ + + +#ifdef RLT_MAC +static UCHAR *txinfo_type_str[]={"PKT", "CMD", "RSV"}; +static UCHAR *txinfo_d_port_str[]={"WLAN", "CPU_RX", "CPU_TX", "HOST", "VIRT_RX", "VIRT_TX", "DROP"}; + +VOID DumpCmdTxInfo(RTMP_ADAPTER *ad, TXINFO_STRUC *pTxInfo) +{ + DBGPRINT(RT_DEBUG_OFF, ("TxInfo:\n")); + { + struct _TXINFO_NMAC_CMD *cmd_txinfo = (struct _TXINFO_NMAC_CMD *)pTxInfo; + + hex_dump("Raw Data: ", (UCHAR *)pTxInfo, sizeof(TXINFO_STRUC)); + DBGPRINT(RT_DEBUG_OFF, ("\t Info_Type=%d(%s)\n", cmd_txinfo->info_type, txinfo_type_str[cmd_txinfo->info_type])); + DBGPRINT(RT_DEBUG_OFF, ("\t d_port=%d(%s)\n", cmd_txinfo->d_port, txinfo_d_port_str[cmd_txinfo->d_port])); + DBGPRINT(RT_DEBUG_OFF, ("\t cmd_type=%d\n", cmd_txinfo->cmd_type)); + DBGPRINT(RT_DEBUG_OFF, ("\t cmd_seq=%d\n", cmd_txinfo->cmd_seq)); + DBGPRINT(RT_DEBUG_OFF, ("\t pkt_len=0x%x\n", cmd_txinfo->pkt_len)); + } + + DBGPRINT(RT_DEBUG_OFF, ("\t")); +} + + +VOID AndesRltFillCmdHeader(struct cmd_msg *msg, PNDIS_PACKET net_pkt) +{ + TXINFO_NMAC_CMD *tx_info; + + tx_info = (TXINFO_NMAC_CMD *)OS_PKT_HEAD_BUF_EXTEND(net_pkt, sizeof(*tx_info)); + tx_info->info_type = CMD_PACKET; + tx_info->d_port = msg->pq_id; + tx_info->cmd_type = msg->cmd_type; + tx_info->cmd_seq = msg->seq; + tx_info->pkt_len = GET_OS_PKT_LEN(net_pkt) - sizeof(*tx_info); + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)tx_info, TYPE_TXINFO); +#endif + +} + + +#ifdef RTMP_PCI_SUPPORT +INT32 AndesRltPciKickOutCmdMsg( + PRTMP_ADAPTER ad, + struct cmd_msg *msg) +{ + int ret = NDIS_STATUS_SUCCESS; + unsigned long flags = 0; + ULONG FreeNum; + PNDIS_PACKET net_pkt = msg->net_pkt; + UINT32 SwIdx = 0, SrcBufPA; + UCHAR *pSrcBufVA; + UINT SrcBufLen = 0; + PACKET_INFO PacketInfo; + TXD_STRUC *pTxD; + TXINFO_STRUC *pTxInfo; + struct MCU_CTRL *ctl = &ad->MCUCtrl; +#ifdef RT_BIG_ENDIAN + TXD_STRUC *pDestTxD; +#endif + + if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) + return -1; + + FreeNum = GET_CTRLRING_FREENO(ad); + + if (FreeNum == 0) { + DBGPRINT(RT_DEBUG_WARN, ("%s FreeNum == 0 (TxCpuIdx = %d, TxDmaIdx = %d, TxSwFreeIdx = %d)\n", + __FUNCTION__, ad->CtrlRing.TxCpuIdx, ad->CtrlRing.TxDmaIdx, ad->CtrlRing.TxSwFreeIdx)); + return NDIS_STATUS_FAILURE; + } + + RTMP_SPIN_LOCK_IRQSAVE(&ad->CtrlRingLock, &flags); + + RTMP_QueryPacketInfo(net_pkt, &PacketInfo, &pSrcBufVA, &SrcBufLen); + + if (pSrcBufVA == NULL) { + RTMP_SPIN_UNLOCK_IRQRESTORE(&ad->CtrlRingLock, &flags); + return NDIS_STATUS_FAILURE; + } + + SwIdx = ad->CtrlRing.TxCpuIdx; +#ifdef RT_BIG_ENDIAN + pDestTxD = (PTXD_STRUC)ad->CtrlRing.Cell[SwIdx].AllocVa; +#else + pTxD = (PTXD_STRUC)ad->CtrlRing.Cell[SwIdx].AllocVa; +#endif + + pTxInfo = (TXINFO_STRUC *)((UCHAR *)pTxD + sizeof(TXD_STRUC)); + NdisMoveMemory(pTxInfo, pSrcBufVA, TXINFO_SIZE); + + ad->CtrlRing.Cell[SwIdx].pNdisPacket = net_pkt; + ad->CtrlRing.Cell[SwIdx].pNextNdisPacket = NULL; + + SrcBufPA = PCI_MAP_SINGLE(ad, (pSrcBufVA) + 4, (SrcBufLen) - 4, 0, RTMP_PCI_DMA_TODEVICE); + + pTxD->LastSec0 = 1; + pTxD->LastSec1 = 0; + pTxD->SDLen0 = (SrcBufLen - TXINFO_SIZE); + pTxD->SDLen1 = 0; + pTxD->SDPtr0 = SrcBufPA; + pTxD->DMADONE = 0; + +#ifdef RT_BIG_ENDIAN + RTMPDescriptorEndianChange((PUCHAR)pTxD, TYPE_TXD); + WriteBackToDescriptor((PUCHAR)pDestTxD, (PUCHAR)pTxD, FALSE, TYPE_TXD); +#endif + + /* flush dcache if no consistent memory is supported */ + RTMP_DCACHE_FLUSH(SrcBufPA, SrcBufLen); + RTMP_DCACHE_FLUSH(ad->CtrlRing.Cell[SwIdx].AllocPa, TXD_SIZE); + + /* Increase TX_CTX_IDX, but write to register later.*/ + INC_RING_INDEX(ad->CtrlRing.TxCpuIdx, MGMT_RING_SIZE); + + if (msg->need_rsp) + AndesQueueTailCmdMsg(&ctl->ackq, msg, wait_cmd_out_and_ack); + else + AndesQueueTailCmdMsg(&ctl->kickq, msg, wait_cmd_out); + + if (!OS_TEST_BIT(MCU_INIT, &ctl->flags)) { + RTMP_SPIN_UNLOCK_IRQRESTORE(&ad->CtrlRingLock, &flags); + return -1; + } + + RTMP_IO_WRITE32(ad, ad->CtrlRing.hw_cidx_addr, ad->CtrlRing.TxCpuIdx); + + RTMP_SPIN_UNLOCK_IRQRESTORE(&ad->CtrlRingLock, &flags); + + return ret; +} +#endif /* RTMP_PCI_SUPPORT */ +#endif /* RLT_MAC */ + + + + +static VOID AndesRltPwrEventHandler(RTMP_ADAPTER *ad, char *payload, UINT16 payload_len) +{ + + +} + + +static VOID AndesRltWowEventHandler(RTMP_ADAPTER *ad, char *payload, UINT16 payload_len) +{ + + +} + + +static VOID AndesRltCarrierDetectEventHandler(RTMP_ADAPTER *ad, char *payload, UINT16 payload_len) +{ + + + +} + + +static VOID AndesRltDfsDetectEventHandler(PRTMP_ADAPTER ad, char *payload, UINT16 payload_len) +{ + + + +} + + +MSG_EVENT_HANDLER msg_event_handler_tb[] = +{ + AndesRltPwrEventHandler, + AndesRltWowEventHandler, + AndesRltCarrierDetectEventHandler, + AndesRltDfsDetectEventHandler, +}; + + +INT32 AndesRltBurstWrite(RTMP_ADAPTER *ad, UINT32 offset, UINT32 *data, UINT32 cnt) +{ + struct cmd_msg *msg; + unsigned int var_len, offset_num, cur_len = 0, sent_len; + UINT32 value, i, cur_index = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + int ret = 0; + BOOLEAN last_packet = FALSE; + + if (!data) + return -1; + + offset_num = cnt / ((cap->InbandPacketMaxLen - sizeof(offset)) / 4); + + if (cnt % ((cap->InbandPacketMaxLen - sizeof(offset)) / 4)) + var_len = sizeof(offset) * (offset_num + 1) + 4 * cnt; + else + var_len = sizeof(offset) * offset_num + 4 * cnt; + + while (cur_len < var_len) { + sent_len = (var_len - cur_len) > cap->InbandPacketMaxLen + ? cap->InbandPacketMaxLen : (var_len - cur_len); + + if (((sent_len < cap->InbandPacketMaxLen) || ((cur_len + cap->InbandPacketMaxLen) == var_len))) + last_packet = TRUE; + + msg = AndesAllocCmdMsg(ad, sent_len); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + if (last_packet) { + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_BURST_WRITE, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + }else { + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_BURST_WRITE, CMD_NA, EXT_CMD_NA, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + } + + + value = cpu2le32(offset + cap->WlanMemmapOffset + cur_index * 4); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + for (i = 0; i < ((sent_len - 4) / 4); i++) { + value = cpu2le32(data[i + cur_index]); + AndesAppendCmdMsg(msg, (char *)&value, 4); + } + + ret = AndesSendCmdMsg(ad, msg); + + + cur_index += ((sent_len - 4) / 4); + cur_len += cap->InbandPacketMaxLen; + } + +error: + return ret; +} + + +static VOID AndesRltBurstReadCallback(struct cmd_msg *msg, char *rsp_payload, UINT16 rsp_payload_len) +{ + UINT32 i; + UINT32 *data; + NdisMoveMemory(msg->rsp_payload, rsp_payload + 4, rsp_payload_len - 4); + + for (i = 0; i < (msg->rsp_payload_len - 4) / 4; i++) { + data = (UINT32 *)(msg->rsp_payload + i * 4); + *data = le2cpu32(*data); + } +} + + +INT32 AndesRltBurstRead(RTMP_ADAPTER *ad, UINT32 offset, UINT32 cnt, UINT32 *data) +{ + struct cmd_msg *msg; + unsigned int cur_len = 0, rsp_len, offset_num, receive_len; + UINT32 value, cur_index = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + int ret = 0; + + if (!data) + return -1; + + offset_num = cnt / ((cap->InbandPacketMaxLen - sizeof(offset)) / 4); + + if (cnt % ((cap->InbandPacketMaxLen - sizeof(offset)) / 4)) + rsp_len = sizeof(offset) * (offset_num + 1) + 4 * cnt; + else + rsp_len = sizeof(offset) * offset_num + 4 * cnt; + + while (cur_len < rsp_len) { + receive_len = (rsp_len - cur_len) > cap->InbandPacketMaxLen + ? cap->InbandPacketMaxLen + : (rsp_len - cur_len); + + msg = AndesAllocCmdMsg(ad, 8); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_BURST_READ, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, receive_len, + (char *)(&data[cur_index]), AndesRltBurstReadCallback); + + value = cpu2le32(offset + cap->WlanMemmapOffset + cur_index * 4); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + value = cpu2le32((receive_len - 4) / 4); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + ret = AndesSendCmdMsg(ad, msg); + + if (ret) { + if (cnt == 1) + *data = 0xffffffff; + } + + cur_index += ((receive_len - 4) / 4); + cur_len += cap->InbandPacketMaxLen; + } + +error: + return ret; +} + + +static VOID AndesRltRandomReadCallback(struct cmd_msg *msg, char *rsp_payload, + UINT16 rsp_payload_len) +{ + UINT32 i; + RTMP_REG_PAIR *reg_pair = (RTMP_REG_PAIR *)msg->rsp_payload; + + for (i = 0; i < msg->rsp_payload_len / 8; i++) { + NdisMoveMemory(®_pair[i].Value, rsp_payload + 8 * i + 4, 4); + reg_pair[i].Value = le2cpu32(reg_pair[i].Value); + } +} + + +INT32 AndesRltRandomRead(RTMP_ADAPTER *ad, RTMP_REG_PAIR *reg_pair, UINT32 num) +{ + struct cmd_msg *msg; + unsigned int var_len = num * 8, cur_len = 0, receive_len; + UINT32 i, value, cur_index = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + int ret = 0; + + if (!reg_pair) + return -1; + + while (cur_len < var_len) + { + receive_len = (var_len - cur_len) > cap->InbandPacketMaxLen + ? cap->InbandPacketMaxLen + : (var_len - cur_len); + + msg = AndesAllocCmdMsg(ad, receive_len); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_RANDOM_READ, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, receive_len, + (char *)®_pair[cur_index], AndesRltRandomReadCallback); + + for (i = 0; i < receive_len / 8; i++) { + value = cpu2le32(reg_pair[i + cur_index].Register + cap->WlanMemmapOffset); + AndesAppendCmdMsg(msg, (char *)&value, 4); + value = 0; + AndesAppendCmdMsg(msg, (char *)&value, 4); + } + + + ret = AndesSendCmdMsg(ad, msg); + + + cur_index += receive_len / 8; + cur_len += cap->InbandPacketMaxLen; + } + +error: + return ret; +} + + +static VOID AndesRltRfRandomReadCallback(struct cmd_msg *msg, char *rsp_payload, UINT16 rsp_payload_len) +{ + UINT32 i; + BANK_RF_REG_PAIR *reg_pair = (BANK_RF_REG_PAIR *)msg->rsp_payload; + + for (i = 0; i < msg->rsp_payload_len / 8; i++) { + NdisMoveMemory(®_pair[i].Value, rsp_payload + 8 * i + 4, 1); + } +} + + +INT32 AndesRltRfRandomRead(RTMP_ADAPTER *ad, BANK_RF_REG_PAIR *reg_pair, UINT32 num) +{ + struct cmd_msg *msg; + unsigned int var_len = num * 8, cur_len = 0, receive_len; + UINT32 i, value, cur_index = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + int ret = 0; + + if (!reg_pair) + return -1; + + while (cur_len < var_len) + { + receive_len = (var_len - cur_len) > cap->InbandPacketMaxLen + ? cap->InbandPacketMaxLen + : (var_len - cur_len); + + msg = AndesAllocCmdMsg(ad, receive_len); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_RANDOM_READ, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, receive_len, + (char *)®_pair[cur_index], AndesRltRfRandomReadCallback); + + for (i = 0; i < (receive_len) / 8; i++) + { + value = 0; + + /* RF selection */ + value = (value & ~0x80000000) | 0x80000000; + + /* RF bank */ + value = (value & ~0x00ff0000) | (reg_pair[i + cur_index].Bank << 16); + + /* RF Index */ + value = (value & ~0x0000ffff) | reg_pair[i + cur_index].Register; + + value = cpu2le32(value); + AndesAppendCmdMsg(msg, (char *)&value, 4); + value = 0; + AndesAppendCmdMsg(msg, (char *)&value, 4); + } + + ret = AndesSendCmdMsg(ad, msg); + + + cur_index += receive_len / 8; + cur_len += cap->InbandPacketMaxLen; + } + +error: + return ret; +} + + +INT32 AndesRltReadModifyWrite(RTMP_ADAPTER *ad, R_M_W_REG *reg_pair, UINT32 num) +{ + struct cmd_msg *msg; + unsigned int var_len = num * 12, cur_len = 0, sent_len; + UINT32 value, i, cur_index = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + int ret = 0; + BOOLEAN last_packet = FALSE; + + if (!reg_pair) + return -1; + + while (cur_len < var_len) + { + sent_len = (var_len - cur_len) > cap->InbandPacketMaxLen + ? cap->InbandPacketMaxLen : (var_len - cur_len); + + if ((sent_len < cap->InbandPacketMaxLen) || (cur_len + cap->InbandPacketMaxLen) == var_len) + last_packet = TRUE; + + msg = AndesAllocCmdMsg(ad, sent_len); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + if (last_packet) + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_READ_MODIFY_WRITE, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + else + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_READ_MODIFY_WRITE, CMD_NA, EXT_CMD_NA, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + for (i = 0; i < (sent_len / 12); i++) + { + /* Address */ + value = cpu2le32(reg_pair[i + cur_index].Register + cap->WlanMemmapOffset); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + /* ClearBitMask */ + value = cpu2le32(reg_pair[i + cur_index].ClearBitMask); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + /* UpdateData */ + value = cpu2le32(reg_pair[i + cur_index].Value); + AndesAppendCmdMsg(msg, (char *)&value, 4); + } + + ret = AndesSendCmdMsg(ad, msg); + + + cur_index += (sent_len / 12); + cur_len += cap->InbandPacketMaxLen; + } + +error: + return ret; +} + + +INT32 AndesRltRfReadModifyWrite(RTMP_ADAPTER *ad, RF_R_M_W_REG *reg_pair, UINT32 num) +{ + struct cmd_msg *msg; + unsigned int var_len = num * 12, cur_len = 0, sent_len; + UINT32 value, i, cur_index = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + int ret = 0; + BOOLEAN last_packet = FALSE; + + if (!reg_pair) + return -1; + + while (cur_len < var_len) + { + sent_len = (var_len - cur_len) > cap->InbandPacketMaxLen + ? cap->InbandPacketMaxLen : (var_len - cur_len); + + if ((sent_len < cap->InbandPacketMaxLen) || (cur_len + cap->InbandPacketMaxLen) == var_len) + last_packet = TRUE; + + msg = AndesAllocCmdMsg(ad, sent_len); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + if (last_packet) + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_READ_MODIFY_WRITE, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + else + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_READ_MODIFY_WRITE, CMD_NA, EXT_CMD_NA, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + for (i = 0; i < sent_len / 12; i++) + { + value = 0; + /* RF selection */ + value = (value & ~0x80000000) | 0x80000000; + + /* RF bank */ + value = (value & ~0x00ff0000) | (reg_pair[i + cur_index].Bank << 16); + + /* RF Index */ + value = (value & ~0x000000ff) | reg_pair[i + cur_index].Register; + value = cpu2le32(value); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + value = 0; + /* ClearBitMask */ + value = (value & ~0x000000ff) | reg_pair[i + cur_index].ClearBitMask; + value = cpu2le32(value); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + value = 0; + /* UpdateData */ + value = (value & ~0x000000ff) | reg_pair[i + cur_index].Value; + value = cpu2le32(value); + AndesAppendCmdMsg(msg, (char *)&value, 4); + } + + ret = AndesSendCmdMsg(ad, msg); + + cur_index += (sent_len / 12); + cur_len += cap->InbandPacketMaxLen; + } + +error: + return ret; +} + + +INT32 AndesRltRandomWrite(RTMP_ADAPTER *ad, RTMP_REG_PAIR *reg_pair, UINT32 num) +{ + struct cmd_msg *msg; + unsigned int var_len = num * 8, cur_len = 0, sent_len; + UINT32 value, i, cur_index = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + int ret = 0; + BOOLEAN last_packet = FALSE; + + if (!reg_pair) + return -1; + + while (cur_len < var_len) + { + sent_len = (var_len - cur_len) > cap->InbandPacketMaxLen + ? cap->InbandPacketMaxLen : (var_len - cur_len); + + if ((sent_len < cap->InbandPacketMaxLen) || (cur_len + cap->InbandPacketMaxLen) == var_len) + last_packet = TRUE; + + msg = AndesAllocCmdMsg(ad, sent_len); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + if (last_packet) + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_RANDOM_WRITE, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + else + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_RANDOM_WRITE, CMD_NA, EXT_CMD_NA, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + for (i = 0; i < (sent_len / 8); i++) + { + /* Address */ + value = cpu2le32(reg_pair[i + cur_index].Register + cap->WlanMemmapOffset); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + /* UpdateData */ + value = cpu2le32(reg_pair[i + cur_index].Value); + AndesAppendCmdMsg(msg, (char *)&value, 4); + }; + + ret = AndesSendCmdMsg(ad, msg); + + + cur_index += (sent_len / 8); + cur_len += cap->InbandPacketMaxLen; + } + +error: + return ret; +} + + +INT32 AndesRltRfRandomWrite(RTMP_ADAPTER *ad, BANK_RF_REG_PAIR *reg_pair, UINT32 num) +{ + struct cmd_msg *msg; + unsigned int var_len = num * 8, cur_len = 0, sent_len; + UINT32 value, i, cur_index = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + int ret = 0; + BOOLEAN last_packet = FALSE; + + if (!reg_pair) + return -1; + + while (cur_len < var_len) + { + sent_len = (var_len - cur_len) > cap->InbandPacketMaxLen + ? cap->InbandPacketMaxLen : (var_len - cur_len); + + if ((sent_len < cap->InbandPacketMaxLen) || (cur_len + cap->InbandPacketMaxLen) == var_len) + last_packet = TRUE; + + msg = AndesAllocCmdMsg(ad, sent_len); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + if (last_packet) + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_RANDOM_WRITE, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + else + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_RANDOM_WRITE, CMD_NA, EXT_CMD_NA, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + for (i = 0; i < (sent_len / 8); i++) { + value = 0; + /* RF selection */ + value = (value & ~0x80000000) | 0x80000000; + + /* RF bank */ + value = (value & ~0x00ff0000) | (reg_pair[i + cur_index].Bank << 16); + + /* RF Index */ + value = (value & ~0x000000ff) | reg_pair[i + cur_index].Register; + + value = cpu2le32(value); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + value = 0; + /* UpdateData */ + value = (value & ~0x000000ff) | reg_pair[i + cur_index].Value; + value = cpu2le32(value); + AndesAppendCmdMsg(msg, (char *)&value, 4); + } + + ret = AndesSendCmdMsg(ad, msg); + + + cur_index += (sent_len / 8); + cur_len += cap->InbandPacketMaxLen; + } + +error: + return ret; +} + + +#ifdef CONFIG_ANDES_BBP_RANDOM_WRITE_SUPPORT +INT32 AndesBbpRandomWrite(RTMP_ADAPTER *ad, RTMP_REG_PAIR *reg_pair, UINT32 num) +{ + struct cmd_msg *msg; + unsigned int var_len = num * 8, cur_len = 0, sent_len; + UINT32 value, i, cur_index = 0; + RTMP_CHIP_CAP *cap = &ad->chipCap; + int ret = 0; + BOOLEAN last_packet = FALSE; + + if (!reg_pair) + return -1; + + while (cur_len < var_len) + { + sent_len = (var_len - cur_len) > cap->InbandPacketMaxLen + ? cap->InbandPacketMaxLen : (var_len - cur_len); + + if ((sent_len < cap->InbandPacketMaxLen) || (cur_len + cap->InbandPacketMaxLen) == var_len) + last_packet = TRUE; + + msg = AndesAllocCmdMsg(ad, sent_len); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + if (last_packet) + AndesInitCmdMsg(msg, CMD_RANDOM_WRITE, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + else + AndesInitCmdMsg(msg, CMD_RANDOM_WRITE, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + for (i = 0; i < (sent_len / 8); i++) + { + /* BBP selection */ + value = 0x40000000; + + /* Address */ + value |= reg_pair[i + cur_index].Register; + value = cpu2le32(value); + + AndesAppendCmdMsg(msg, (char *)&value, 4); + + /* UpdateData */ + value = cpu2le32(reg_pair[i + cur_index].Value); + AndesAppendCmdMsg(msg, (char *)&value, 4); + }; + + ret = AndesSendCmdmsg(ad, msg); + + + cur_index += (sent_len / 8); + cur_len += cap->InbandPacketMaxLen; + } + +error: + return ret; +} +#endif /* CONFIG_ANDES_BBP_RANDOM_WRITE_SUPPORT */ + + +INT32 AndesRltScRandomWrite(RTMP_ADAPTER *ad, CR_REG *table, UINT32 nums, UINT32 flags) +{ + UINT32 varlen = 0, i, j; + RTMP_REG_PAIR *sw_ch_table = NULL, temp; + + if (!table) + return -1; + + for (i = 0; i < nums; i++) { + if ((table[i].flags & (_BAND | _BW | _TX_RX_SETTING)) == flags) { + varlen += sizeof(RTMP_REG_PAIR); + } + } + + os_alloc_mem(NULL, (UCHAR **)&sw_ch_table, varlen); + + if (!sw_ch_table) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: memory is not available for allocating switch channel table\n", __FUNCTION__)); + return -1; + } + + for (i = 0, j = 0; i < nums; i++) { + if ((table[i].flags & (_BAND | _BW | _TX_RX_SETTING)) == flags) { + temp.Register = table[i].offset; + temp.Value = table[i].value; + NdisMoveMemory(&sw_ch_table[j], &temp, sizeof(temp)); + j++; + } + } + + AndesRltRandomWrite(ad, sw_ch_table, varlen / sizeof(RTMP_REG_PAIR)); + + os_free_mem(NULL, sw_ch_table); + + return 0; +} + + +INT32 AndesRltScRfRandomWrite(RTMP_ADAPTER *ad, BANK_RF_CR_REG *table, UINT32 nums, UINT32 flags) +{ + UINT32 varlen = 0, i, j; + BANK_RF_REG_PAIR *sw_ch_table = NULL, temp; + + if (!table) + return -1; + + for (i = 0; i < nums; i++) { + if ((table[i].flags & (_BAND | _BW | _TX_RX_SETTING)) == flags) { + varlen += sizeof(BANK_RF_REG_PAIR); + } + } + + os_alloc_mem(NULL, (UCHAR **)&sw_ch_table, varlen); + + if (!sw_ch_table) { + DBGPRINT(RT_DEBUG_ERROR, ("%s: memory is not available for allocating switch channel table\n", __FUNCTION__)); + return -1; + } + + for (i = 0, j = 0; i < nums; i++) { + if ((table[i].flags & (_BAND | _BW | _TX_RX_SETTING)) == flags) { + temp.Bank = table[i].bank; + temp.Register = table[i].offset; + temp.Value = table[i].value; + NdisMoveMemory(&sw_ch_table[j], &temp, sizeof(temp)); + j++; + } + } + + AndesRltRfRandomWrite(ad, sw_ch_table, varlen / sizeof(BANK_RF_REG_PAIR)); + + os_free_mem(NULL, sw_ch_table); + + return 0; +} + + +INT32 AndesRltPwrSaving(RTMP_ADAPTER *ad, UINT32 op, UINT32 level, + UINT32 listen_interval, UINT32 pre_tbtt_lead_time, + UINT8 tim_byte_offset, UINT8 tim_byte_pattern) +{ + struct cmd_msg *msg; + unsigned int var_len; + UINT32 value; + int ret = 0; + + /* Power operation and Power Level */ + var_len = 8; + + if (op == RADIO_OFF_ADVANCE) + { + /* Listen interval, Pre-TBTT, TIM info */ + var_len += 12; + } + + msg = AndesAllocCmdMsg(ad, var_len); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_POWER_SAVING_OP, CMD_NA, EXT_CMD_NA, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + /* Power operation */ + value = cpu2le32(op); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + /* Power Level */ + value = cpu2le32(level); + + AndesAppendCmdMsg(msg, (char *)&value, 4); + + if (op == RADIO_OFF_ADVANCE) + { + /* Listen interval */ + value = cpu2le32(listen_interval); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + + /* Pre TBTT lead time */ + value = cpu2le32(pre_tbtt_lead_time); + AndesAppendCmdMsg(msg, (char*)&value, 4); + + /* TIM Info */ + value = (value & ~0x000000ff) | tim_byte_pattern; + value = (value & ~0x0000ff00) | (tim_byte_offset << 8); + value = cpu2le32(value); + AndesAppendCmdMsg(msg, (char *)&value, 4); + } + + ret = AndesSendCmdMsg(ad, msg); + +error: + return ret; +} + + +INT32 AndesRltFunSet(RTMP_ADAPTER *ad, UINT32 fun_id, UINT32 param) +{ + struct cmd_msg *msg; + UINT32 value; + int ret = 0; + + /* Function ID and Parameter */ + msg = AndesAllocCmdMsg(ad, 8); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + if (fun_id != Q_SELECT) + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_FUN_SET_OP, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + else + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_FUN_SET_OP, CMD_NA, EXT_CMD_NA, FALSE, 0, FALSE, FALSE, 0, NULL, NULL); + + /* Function ID */ + value = cpu2le32(fun_id); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + /* Parameter */ + value = cpu2le32(param); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + ret = AndesSendCmdMsg(ad, msg); + +error: + return ret; +} + + +INT32 AndesRltCalibration(RTMP_ADAPTER *ad, UINT32 cal_id, ANDES_CALIBRATION_PARAM *param) +{ + struct cmd_msg *msg; + UINT32 value; + int ret = 0; + + DBGPRINT(RT_DEBUG_INFO, ("%s:cal_id(%d)\n ", __FUNCTION__, cal_id)); + + + msg = AndesAllocCmdMsg(ad, 8); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_CALIBRATION_OP, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + + /* Calibration ID */ + value = cpu2le32(cal_id); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + /* Parameter */ + { + value = cpu2le32(param->generic); + AndesAppendCmdMsg(msg, (char *)&value, 4); + } + + ret = AndesSendCmdMsg(ad, msg); + + +error: + return ret; +} + + +INT32 AndesRltLoadCr(RTMP_ADAPTER *ad, UINT32 cr_type, UINT8 temp_level, UINT8 channel) +{ + struct cmd_msg *msg; + UINT32 value = 0; + int ret = 0; + + DBGPRINT(RT_DEBUG_OFF, ("%s:cr_type(%d), channel(%d)\n", __FUNCTION__, cr_type, temp_level, channel)); + + msg = AndesAllocCmdMsg(ad, 8); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_LOAD_CR, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + + /* CR type */ + value &= ~LOAD_CR_MODE_MASK; + value |= LOAD_CR_MODE(cr_type); + + if (cr_type == HL_TEMP_CR_UPDATE) { + value &= ~LOAD_CR_TEMP_LEVEL_MASK; + value |= LOAD_CR_TEMP_LEVEL(temp_level); + + value &= ~LOAD_CR_CHL_MASK; + value |= LOAD_CR_CHL(channel); + } + + value = cpu2le32(value); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + value = 0x80000000; + value |= ((ad->EEPROMDefaultValue[EEPROM_NIC_CFG1_OFFSET] >> 8) & 0xFF); + value |= ((ad->EEPROMDefaultValue[EEPROM_NIC_CFG2_OFFSET] & 0xFF) << 8 ); + value = cpu2le32(value); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + ret = AndesSendCmdMsg(ad, msg); + +error: + return ret; +} + + +INT32 AndesRltSwitchChannel(RTMP_ADAPTER *ad, UINT8 channel, BOOLEAN scan, unsigned int bw, unsigned int tx_rx_setting, UINT8 bbp_ch_idx) +{ + struct cmd_msg *msg; + UINT32 value = 0; + int ret; + + DBGPRINT(RT_DEBUG_INFO, ("%s:channel(%d),scan(%d),bw(%d),trx(0x%x)\n", __FUNCTION__, channel, scan, bw, tx_rx_setting)); + + msg = AndesAllocCmdMsg(ad, 8); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_SWITCH_CHANNEL_OP, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + + /* + * switch channel related param + * channel, scan, bw, tx_rx_setting + */ + value &= ~SC_PARAM1_CHL_MASK; + value |= SC_PARAM1_CHL(channel); + value &= ~SC_PARAM1_SCAN_MASK; + value |= SC_PARAM1_SCAN(scan); + value &= ~SC_PARAM1_BW_MASK; + value |= SC_PARAM1_BW(bw); + value = cpu2le32(value); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + value = 0; + value |= SC_PARAM2_TR_SETTING(tx_rx_setting); + value = cpu2le32(value); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + ret = AndesSendCmdMsg(ad, msg); + + mdelay(5); + + msg = AndesAllocCmdMsg(ad, 8); + + if (!msg) { + ret = NDIS_STATUS_RESOURCES; + goto error; + } + + AndesInitCmdMsg(msg, CPU_TX_PORT, CMD_SWITCH_CHANNEL_OP, CMD_NA, EXT_CMD_NA, TRUE, 0, TRUE, TRUE, 0, NULL, NULL); + + /* + * switch channel related param + * channel, scan, bw, tx_rx_setting, extension channel + */ + value &= ~SC_PARAM1_CHL_MASK; + value |= SC_PARAM1_CHL(channel); + value &= ~SC_PARAM1_SCAN_MASK; + value |= SC_PARAM1_SCAN(scan); + value &= ~SC_PARAM1_BW_MASK; + value |= SC_PARAM1_BW(bw); + value = cpu2le32(value); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + value = 0; + value |= SC_PARAM2_TR_SETTING(tx_rx_setting); + value &= ~SC_PARAM2_EXTENSION_CHL_MASK; + + if (bbp_ch_idx == 0) + value |= SC_PARAM2_EXTENSION_CHL(0xe0); + else if (bbp_ch_idx == 1) + value |= SC_PARAM2_EXTENSION_CHL(0xe1); + else if (bbp_ch_idx == 2) + value |= SC_PARAM2_EXTENSION_CHL(0xe2); + else if (bbp_ch_idx == 3) + value |= SC_PARAM2_EXTENSION_CHL(0xe3); + + value = cpu2le32(value); + AndesAppendCmdMsg(msg, (char *)&value, 4); + + ret = AndesSendCmdMsg(ad, msg); + +error: + return ret; +} + + +#ifdef RTMP_PCI_SUPPORT +VOID AndesRltPciFwInit(RTMP_ADAPTER *ad) +{ + UINT32 value; + + DBGPRINT(RT_DEBUG_OFF, ("%s\n", __FUNCTION__)); +#ifdef RLT_MAC + /* Enable Interrupt*/ + RTMP_IRQ_ENABLE(ad); + RTMPEnableRxTx(ad); + RTMP_SET_FLAG(ad, fRTMP_ADAPTER_START_UP); + RTMP_SET_FLAG(ad, fRTMP_ADAPTER_MCU_SEND_IN_BAND_CMD); + /* clear garbage interrupts*/ + RTMP_IO_READ32(ad, 0x1300, &value); + DBGPRINT(RT_DEBUG_OFF, ("0x1300 = %08x\n", value)); + +#ifdef HDR_TRANS_SUPPORT + RTMP_IO_WRITE32(ad, HEADER_TRANS_CTRL_REG, 0X2); + RTMP_IO_WRITE32(ad, TSO_CTRL, 0x7050); +#else + RTMP_IO_WRITE32(ad, HEADER_TRANS_CTRL_REG, 0x0); + RTMP_IO_WRITE32(ad, TSO_CTRL, 0x0); +#endif + + AndesRltFunSet(ad, Q_SELECT, ad->chipCap.CmdRspRxRing); + PWR_SAVING_OP(ad, RADIO_ON, 0, 0, 0, 0, 0); +#endif /* RLT_MAC */ +} +#endif /* RTMP_PCI_SUPPORT */ + + + diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/MT7601_formal_1.7.bin b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/MT7601_formal_1.7.bin new file mode 100644 index 0000000000000000000000000000000000000000..da534ee0a88337ba207fab8bbabb8fae7cc3d98e GIT binary patch literal 47032 zcmb@v4R}<=y+1zZ?Agt3639tdBqEiQ5W-7Ul7K?JRA!fT0lUQo7F}B&36NUtn;_KM zUT-renGn<<5knGe0vm`S^wOYpU2V&Kxal6hriWu-UIUX6c?30aQc z_4rM~Zz6vA_+5ja7r#9GRQ$%;VJ1R1elGkJ{N(Kf|C8JJF7w}b;q)T14M~luIlccbyh(=F6!ULaXRI={6A=1*DNda@AT@t;lPwJi3eoIo_B^|hB{81u1-(%ALpCnF?e~(Cs z-?x3Qb;kZ%4Oc92M2USnHmA4HyO$}3Cw7R|yQQT&h{KRO=j+AsSA+HFxq;V*DpGI8 zJAUJd4N)m3*?p|C#{NTl?ClskI~h>_RL+v8ruC1d4t{rF*7#VXdGj<(5 zaEYBX99%mP3^KILm3j*fVz%)uw0;r^1&G`EK2d1oinKIBvXMX5+oVrt86&;MUEZgO z+>;~nltubfZv~NFa_uiobSqvWx4i0|Lu3Kfc8u)S2b&KC%hA_5tln&{bv~5%#s24e z+*ZFl(mShjwjrQquO!Ob^JzYG?g~qWbC`l$XY}%u^LuB-%6eqOvrFnMGa-%CZCHJl z91t)OWy1J!opoESn7A-xwZTq~YURhw)v~PfArlKk8!z|H8r{O#Yzrf>Lk`)P*KXC` z_8hQcJurG>ZPJ>RGyq7FD0key{{kycm;OSZCWSX{rok{76J5TQ)}46wyqy=ns--c} zja#YJlFUA(rMT4+>p@Fnqs#RH(Gtcr45MI)LgEVp;fGZ!QO}8t>Z8hP;`95DWp#`7 z!R)F7y|Xw$JWI`}6}^k_1@!5Nu5%UzKx?o!9Z|KmqPG}dx%Stl-eT0Uaya6W9d9s8 zU2A`}_ZC~REiu&1$Cru!)t!KoNrjYdq&T9NH?PMil8DQI_a@|)U_Pb1n={o{b-=rZ z-58dtx>zw^92}5Prq(UWC~CBH3)$ZiBqgNn%hb=5{nrhz?fgd4xOhj^&JBUGG37fy zOG*jdF_p*WZSazv2M!LjJ`h+>)OSDlK|^>s$qyG2b>2od$=^Vv-+mbO6K&oUFUc=t z(mNjpspO)X;)(jR$<9c_51W*@{Q75Jbw)~A4nJmmj<>y?5y@pa4X+0tOywA*yh`MR z@@NJvjkyC44y24}wDdW5U~*2%`0T6M!PTi8Q6jp0TZ)z@-IRD`qX4aBidJaJF?VqC zfJs>lFW>Wac4Q4wXP3K!59Xwz>vB?*y~Y z$!z1R2H1UPW-d#np5cAL7@+s8>(|&HCN17v!GmAun=bW?*R^mpaWOa2L5XW0<-x55 zW{xKiChAsKXnSgqOGZZP^Q|Ayk0-hM-{nN?;xv6he?x&1DLWElDgRfpiy}{vR6rvO z{S{j_HYKgqb`I@)j%!UCbLq|@ePkthQD}Wq;SR&YgP{#n;fkT~e}7luvg#nz*SE!; z`yTPJ>B03F{l?Ah%*F2QohBV6lu!9$GI`yQ6pmmGXJee|vZExw+mrY?bFk@raqqPF z0yfFWU{jexe6dMZD$8UuSP=LIYFvXIAojGFiP+O(7EQ#zHoM58>=^Zrb&0vSCgw9T zYSbP}GHNB>e!_vVE4<@G5m#>SBdQp+7;)H3w9#Y!Lf<5bAdl}ok%PQ>d~w)8RFR4> zA1Nh#vG}rfFh+Ff+&fL$$|Oq(Xf~ec4)7_V66WN$hf3-C8p`_gnR+IB*C^?j7bqdU zAt_nha;v?vl-pz7{OjIXJ=gC0x7x#@)%2QupCeB*SGcP3uMtjC;c?8(CbPwn2Ilyq zdWKrF+uYtetK%mv%OCUY{2=lyN$vY?%b%#!N$AHUqyJY%4u2&yo0c$*tzwf$YW%UN zU(+X9)Jo}Qi`jy(LsCcbxkeoFZR*qVe6}RKLQ>fp1{@G8usM$1FBvj0s>oW08cp{Y zzZ3i#FlfL`kE~1rpCD`K1>S?~TGSJixvzKDzOs&uv`ll;0bTj=kvak< z#+ZOgRI~gR)M&HH>W~u9Z$y;EIxZWTvB?$1IER2?->_z8&uIvC$CBDw$E9rkUQGcP z^l|mU^Xk)t9DJy2c6IfT-qh1rzqE>A7XUKXcg--IfNz31hIHUMUw#RTlCUbY)vb36bk(Rsf;YcoV1Qw*; zY{>SVs*~wK^s`XiOI+B0IauN9&_mQs@Ex5>Xjj5;0edP@=Gk{W`)&zLPBB`hD7>xf z(pxT+a-x*f^&&>=JpEq3Vq~L_2^}}z(??|N11HjR`QEo2sO{|dc9b&p;LS+O;J(lX zw7K_PtP7yAs8#|L)Vs=vvcrc_P4x9;Ux)f`Ko#^((50HXGzSptar*r;PRytn?M|^N zTRY0;viVpGO;9i7<{>vHe7(6grDBalI$1$z%S;t}(Qu=G1?8MZHcDom7kkmiK^p|0 z5xsB?Da%GM!Ni`nx3YmXL3>mU7(ej%vFs5_Vy*LEc#xqTp5YFclP`nz9Si5^<)W?L z=_Wl1$j(^B{FxHCA`MoX7`Zx$)`KB&h`8aB6M#9^}qjb&a96_TTWn-@d~$yoLVQ9>k{Z%e4% zHG#TWYJ1h^!wNgb9t}^ad^UWiUOsvUfdl$O5}h23VV$1^{dlx?bM7nh=fh5NtZtTF zgS3V)e|vw1C+j2)O)(xZE~J^zwIL=bU-`a=_sykcF*hx(SC-xae3Oj3K}Xjo1@5>E zKX-=KQ%Y82?EaOfSO(jT^>%;pB)z`lVd*`RLF-Z1dqrvZZ<`;qhga+CYc%g}w#r)f zZRlrk6}eO2&~^FXEyfr|ZGP8|75t687InR|&|kLMn@99U3+p|R0wK+F+VLIsRklS? zQ-McY1br%};5mXO{?DTpl-rNFEvc>NSx9<~}m6vEo$?tqU!tCsHPpqt^x%Kyox3)rd@Tz|XTGySZQWfM-l& zODw28nQu`8OV0rxYhg)2-v+BMY#Dm&;^UzbG6wr6KU7LQzCOhrT7bPg8M^zPC#N%s z_np@-H=!k)&ka=dC|uYCo(6;>X=*1VVnNR?NCPr`D%*oqb&GHQhls*b>@h!`w2>Co zxt-^j94@WAvOG*kq>80h9w8}uFq?!cQYr5?mVuR0F4uswW?kBR$)zB4B4rpmwy{;= zN)|F^?aSHyJiSeIbiLU-gUy8elEdcr&KPuHoLR~QJ#@i+dmkw6oh-mQkvC`jIX1z< zku3*IE*UWEL{K}EO@l->BYb^jN=P`{7MnS91Sefuk@`=JSQ*MV@1zS>pRuNox2ex$Sc0^8Dj0oc_8s_SN_jZDau#R4xR z?5`)AvA-^KJaQLdx8ysR6#9PU-vGV)g*0I1N3g#bVth=JWnjKNzykE6N$~|2B$gp! zB3&1|3+-)P3~6lOt^)S8{3%2Veamdk{m)wqKd56Cnk48mC|a@ACN$9D7K0_2N9pGF zKbD?xVJ)zqiE1b!#+H1cFI)PbNms$}^-qD}{U!|8+c11*7>4)%uVDBNU^wZMFw_ry zDh$`BXRSYyh9P<1gyB2?0EUw=V^D`}C;k}>KfN`;aFPu}?S*Ln}=cOy$XhN z(l7+)V9^2+4u%!dd?dQO>d^)Vr#qbuze@xX3&Vve=uX&?%UE{2ik3Av>9TscaWP+$ z*b~Z4y5fb%tuh?(!iIOLk7ZL?fvzX?Jm~!_x}1fB6z$eT{W99!8EAMqP)Z1AiLWH8 zf}qpU0(t%aW&3D1sFkc|?a=~9hPRNkdJEaE(QQJ~{AZ)yY$)dFxhO?tZjYOm_PMFA zUZDllE#^QA-OBJhUP;d*aeKq>I2G`z914U1pE46Z%j%r8%!E%{V(r_`QP4Rz8akG( z5O{HI<6^d!3ta<}1AiY>dDtE}T&4`r{@On)6I2xfj;BS4M3NqknBCqDz|@TNS2ZL7 z3pzxL7v9sig^WLmm5}0lnC35oUb@z*CCa5o0UQCZ;)@%XgmS6Ebt7ZPvg43aKU1V7qAMYmA(KlDiIT0GUM3PRltCHK2~$f;ott z66r0BPu}X=I{iJmbTAbKHyO4KG#}!7Sn~K(z88>dd;6x5wfvMZh?V}kUb0@cQmeoN zjIme2GXqdG;Ul1ZwVl(%y>iynI43!ttx*bqh0^~Q7Se^(y?uAL3vGfgLb{u^@;#N@ zc?w#W=x3}tfp3XS(a4cp@kJ)ozJnPFo4K%QoP_KyY6@H6&ldG5#QPv=g5|L3qMo*% zZYPaPA{ukhk}aOsRM?n$`o}OWP9a?@alJ+Q_uQ7yDaV<=aRM1uvTRb#^V_$qI!}7~ zuVLkTcE)i3eI6Vr>Suj8p0imeM-l5A>CDF!UNy6E|S6i^7QXjQQ{D;S2)iy2%uS@+c zh+S;j%nB44I`KOR%89W1h&{;O*ZsOfpDJt(P3~2L>~Q~53%8WGuvevJVU`?{l0Fkw zbE|KN6q20Cy(GtXlDer3>)ljF+8&~J5(P4$!*|N9c&nI1$@}h?ZVy*8H(fv!wkX0E zq}YtGjPDIG#o|&zuH^-ssN+ZubW?90^ppKV!**laR{HqsC}l!5jhXhj#!%y9O(#wV zOc)i$2`>l{Kmr^P671dj@62$n{@aUsq7rc-=|g7b6cX#txf2v}3wsyo*s+goLb`Lr z&MnSNnyS)}XzD>JTPx@h>+xC9vh+tlVg<{I+zF|@Ea|3s6@bJRx9=oZ+Wg>sZaUem z@GX1|DEcd%fgicl63kK~UeL~~Y{Az2MxVRD&W;|mY1OlM+i#=6az#~ENMmVL5)vTE zB6Bx?GXh)IdyX@OLOasdRhPZ-8Bs(1YIUhPrMisCLh=zadmMJ1q(emsE}`FYq^--W z|3Y8B#3f!RLQ#)Qt1daU_{@0dHIOVtdjWNtu)ttVO}aFJx4)gWDoh-lQQ12YIby6cj4b}_+n&2rBCR6K zgcDN#2lNqEU~xib?x6;jv@kDO)Dn*u!X}&DlwH>o560JZJMEUPjSwa$Gi$6iYHP1E z(`#$Zp1gDQSH-t?n%-k9<$F#ng$^Dj3&}Dvo2-C!S9x(hEWgX4SxAG`Lsgc2#Wf%_ zpN1d7o(GEx1D~|CWMM-g&@B8FJd0(*$|?0uSD&t0psuT;ki6B4LPDnMimLfx2Rk+> ztI(>49OI7a#p=SU+j^&)I*!nd(GELio|6DdwU3%Ra3Lr;}$R)IKaU<{#+#8(#w;oE9 zo<g=7PL*Exm!Hvby!Wl7KXK}l`l#X*FA5@^Nla1=f2fp&t9YT zNe|XHCC(qPYLp4u-~yND(Do_pzn<5E@%!RcIBO-e021UfRi=ekl-~Kq6hNv-%py`x z{;s|_Kep=^$2;Ox@vqXt2B+^NYR}3B-4=aR&jUWR9UEhekC(@bA+vjv4fsHcH3!JKWvl7CZ1OMXYjTY>u@?U z4HSLZDe26uyz|7DjpZ%gxJ^49H#BbPVyFFQU;{M1*y@c}Ko$}fm2beVk<;Zqt(FdE3Fo#%(PP@j?p&9XGA)V>!84kyR<8oGIZ`j2l~i9e2QrCr$`4ySfs{Dn+Ov z(=hc=^-+`Rs&{YxrodZuLiH@mnp0iU@f9)J-QZAS*5U$@b^P1DSyATKcDYEe)Ib?`?L6-P#$aLoyUuTS$WCJ zkd2?@St#Y})6U$$46rUfah%##Yz){ZIz4b=EjtPHzc zoPvv1pkqFJDYEhBDP!qKxf<|vBWQnv=WYS_Hf|fquX`Eaw~Ty0A!O~FXc6_aKO8HI zl#-nAELdX99v+{AyhrS^Zdj+I_|6|`n^AnLBW-OHeY;1#AItBZ^|T6JnFA}{%HV=j zPP7!KhZ|x4=hW?cFQ)icKjQH(|Iib>b0Fm}yW)}nd63fnUZ7fMQ0yO(G})+ z#uCUr_ngZ~1#_{Z{8wc9kfH$F9R3yWqm6#pv?|=R?26*waL5xG_w&^I)B7{1<7E#e z^W0JF=aujMJjL6_y+>T?3X&t_9COdY;$cbvpl+7^Q^+Bf4NdS+&}%PCvXeq~7Mi`V z=5?&^hq&b`|XZ=4IgXrti#vsNf z#_*5($N6MA$ydwCE}SS7u|Cskl`k~4VQ37HY9a-4QYR=5%p%K}BU*@A=a?0b+DU6O6d+Nb5rC-{RR(_)H(p8^QTecDFhUHVRYTscr%F7FKoC z;jnA7cfn(0=-rf8Kz~;0q^X|PvvF*)H40@Dfh{o&%QwcQJrRgcU;nz3RRI4|MmCZ3 z4M}IXR4-vc!^z7K%ZjVA=!EOD(t6-N5}O{1>oYm@6#Q=6pxy zirxK*xstQ(qxR0(n4cv(gtd`jpAO)(rL}HmS`HaL@dEw9Sx`MjI#!v${*soYyyMt* zwpxZv6PpuWfWGf!W3Aad-i{hFc~;aQcSDc#{Z>fFrXJZ-;CN4;4y|(xSy6T1w;nR3 zYS|GX?_ifRtc_jAYlahQ$J?WMr#1+|S#7_h3iOYv1e$a0&GP zet1YI;2AxJ3avaFR*%fPD02qF;~%AxdL5PPCmN0b$v9^AFt;}ESEdw7=GKmbohH|L zk}MH9(2xE~XXU#C)X~52RDDsnV43zz{jO{Mv&hD!)5u&?@&om*6%-hLM&LBZI+BqM zY~bDLZJS6Q%O^6s_SJE<-Ju*Rq-)^Ylb}rY=x;!ZumxbECsH3` zRdH7biD;z!wX8@9QIERY9@;k}vX*F#B|UOirrqxN!(-AAmT+2&m2!3HM})R4tU8v= z`cBuvpsAl^yc6FXTs=TwsY?Y*R08b)He^`1rQ{d(U3_yfynu#Rwqp}4PoE!Nom}p~ zYK<}1Cye!>SRY3N*2nvg*M};(O5w=*h_&&Z%y)-pEz|t|`l4s*mz_+d{DqH*70SA5 zg#;u|q^UOS2Zzq}vGR7;ssVEInVVu?YN^}TL>J}@IcBW7sCL8QqJ5981SPxkJ)%X{ z5!V}&3@uM1nR(?Tt0P8p-5y9Lj>C{bj?1Pu8dldlqmvBS=*3!Zj$r*h0DaRe%MEs> z5~gfYLhIB!kM5WE3l1*M>!kAW@4;SCZj7B5&L;C{ z9cg*{RE;SMx=*zulnv$7+A|k~r9$9E^ZXXc4Q;b=$-#ON9*mj)ckYYrqeIdg&ZYyu zaPY&hyCe@bN6Og8JHFge-#7J)dsoBGFEw_yE^GMrzCy@@#JGlr>pai=xv{xfZu~Xx zgj_t47S>&-5h8&L}6wvP(1Mu5u3F6k&}q<@9%Iw4v&}?S!zHyNYEF zRz0npukmh!JeOos(;5+z1=pB_^C?J5Di1=2AA8RmO1DT0uOmf)7%9T($mH-Yd6{v~ zfTKOx{H1#b^zZk7sbf8_3FVRNZ|@^hLz8K+#t|x_3-`TXuG&{?&svcG^j(Iz{fj7P z(xZa6g+C|cmD-cPDjZO1+#!Wd9*{@)p3PH0`Fir?>!sqC7BClE6rPhxg#)RN!jaU+ z(7JGnpQ#D@3w=}y-$~@1@y7xk&tG)5{1?sbB&XW?_kgz)0WxXc@}ZDZ^g@e6>y8nw zvacjCD|IYV21`lq7KOR;Rh&u(;cvJed}rfk=<+y!g3gF@=u9&{-HfXuZtY2>o2c@A z(2B1S>(p>I0viNupHCt7?gSAFK{eK~?4Z#J;fPDd7{UYm~8Z zfX_cX`DJ}cUt3k(i8Q>}ny{m?Kd3>&F35P)T7@T|CGmBzTkGb;@O9~xNctqK<&wDy{SDIt*E9odTA-hs_`zi56ieP(_-3rZZP`cK4mEzPf zn1*x99224{W@380rQwZGg`b#-x3;V>t6@Gy0DT31ayd*J&>?{)ZEoFuLE=Ae^$zJ& zX(sWtEfs9xe`lQ6cfJrW68K`AXRgFAEh+Y_+Plk=k1#jk(+a65tr5X8nH$rixg@*O zXYKQr`9Z3v!p{-BN{#xJdC}6xOQHptbGR1ohW&IMXu$L&_IZ3yuyP*KTW)k6QQ|KC5>>tO=rJXVKQXHIV0q3!+(DN&%Si{1 z8ID!UnG_cza=hY%2Ac{w*kZwt;r;z*qjY3cz+m~vt@gP7D8>cL?Ng9-F)r*5F|Jf- zA)ASDm7uni>NlncOPR0+iV;OsKxSR$95J4_4_Y{I%GfO62Dqv?cT=MTxdoXe(dB$z z+#lECPLxPm9+SfF&*pLY7IxU@#42+M91)l%)rB43-(-D_*mKNp3Mq+1H|p7JEpW$+ zodS(h`cKx{P1#2|Co0L@Dx32`=Sl4uv)~tv;1-|H?E<;0=XhXd_vK-$W z`>o;h7S#mxE|tH+CGQ5Z-@AtVP?hA0UwMJW#CeKb>t9Vg-sR+4^Q3~v zbK>QV_awAn=@c5*jL$&+y?4Zqgy_G;uw)PyYvXB(>tLv0QBGSW3~{wjm? ztkx-zRzwLxSiIbyn{+3%5gAF)wwNC}rMsgC6xkDzh_cinja4>Qe!TAy(CPB-vHwt8 z_}h!cgfl7PCG@acnNs<2N8ZXl$Wy1tUzCOT(jbA-qYnO_krN3M^%Vy{X=Fy$L)xll zDPBl7X%p%C*mbcVKYL4EG+b8MA9o$N)cIqnj}W?B^+XirPF~yoohW0Jddav0-|0}B z{7WOSPSrCx?`e`DYPS5>vQw2GcU}+{g$S%yDyaC2E`kHwhz#GJvF$Ilm9<~G=Ol5r zRD_>OeTZ@yoe!b5OR28>*e*wtS?!l$qm-k$ObzcQ@`3MoahoAlX4Cp#19NT7OwjgZ zCUUHlkfj~>Y>GY9eyL?CWYfQjk#s&}`ZU=bO6aW$+H1ch9AWaVDqgk!p#zD~L&UUw z<4#IXlec>u`0Ewm6L#O`fUqo{$b|pf6%)sRnWq1i4|=nb9uw>)))*p|hL|iHPFZE8 z;GAa9yVGEqR&3t)Ytz$P%%ohDm?S0hhg0B%B~p5FVh{1XQXiAPcq*CMo){U`HjFB5 zl^NboCVkl=Y++g633|Vc&2Il{DzI6|$%5YzQzsI4e(K`oiSn4`abq8lM;d8k-4S#5L(_c&Ho^NL=gWuFDQ`mVUhV6np2%d_g~LpKMa)8I z#qS1W-0WG_`1;Xw%I^abQWjIS+|!iZjeVvHDk;jIHa>6HC0aV|kH&1AohnCAj;7Q4 zjTsSm#-c7-vg`iIn2fp_`bB?s+MkW_s7p~7Q?S#{8d<2z8q0^r{y#xCA&dGH^`3KX z;>{tC4D*N8MV(>Hb zYHWkDo^0?xU6*xP*QKRTr~c~S$g|$Ogfjw1wBgD7A-`1sU*8WaQjCLB6@jZLDpEO8 z&qj&oxsg=6&LrfvBXZX}+Amk(arKeYei z{tNpD!Dq!;r|<%M4!cYt8=@L<4(PDFDCZ@wmuwipS#Zf4{khcbRmqJ)*0R0>SA9bg zlSb#`TTXw2m&`vmj7wpauo_LFWFajBw%~3Dqem+^ZCdrps>mAR@RpN>JgG3`2Q*K_ zPb%p{nwzeuSG-~JnLuUgmr9JuFG^ncb!=70L6*VV>9dn?Q-f$Kz9O4YqkWQxZfbEU zuz_v)lb10$T%Af8Zf}fS*ZRDI|063=YER64s^`q5$U0U@*P)N)Nq2N3sM$J_Pd7Fw zbcI(5-f!O{@s}gNS*9DsuU?^kjE9ndcRjhiG)eieQRm2dhpYxa2#WAI#}`6255JJDu%&<7* z4`x5JWm#ig%bBPjR0eRsdHx=?P}&07)Wj8(_$=Uag9V>66wuk*dVNECbJf1PAycsK zx#4B3c%FJqX2UyenaxKNRc#^fGIrgwW844Roa?t}DdxHib6v4-C7~>*5jjpj{Zz4JuOAu-**nE~o7$Lhr5781y&r zSlrDs3inNh{=trv%$wqp=RNJpWQDjd=KYmyIBmMwF1UTmZ4KQ!2RnWqxHFX$o+bw? zm2u>=Egr7}vz&t83UWi!uUo#q19vL6NH{SrZU&7IGNcl}^K|OXwB{}L(BF+=Vn+(I zVuz>C8<&YOWJ2@Tq>jptk6_79(lAq^KCE%&!Ox?o87;Z!bB3}IzZGO=V@1pBJKph~ zs<-8Lr9G^{vV0kRzBRf};o}0IO+sE4D>$HwRU_XgZ6r@R)cU=K1L?Vj_p(CzEjJ0R zXDd6tgY!WKNiHlycTemNnsSNo2#+)@NbQ)f6Ziv@0V%#4=d>9=yU{OoyI=m1G4FGK znJIH$-frSzw<*h5mO6`gy{m~b+yX3~^PZfU3H<=N)##f!9hVgjiX{PW=eBQr$wk9B zGg|(#J6gDz9(WSWnn{=pn$WVv*pA$?ynju~oV zhHphANP!W^%&*+}$@w)`iW%yp#k0dPYK|`9Tlupe8FS4UQfr27_x!Ktmy7v*=h@kq z-|~6({8*1YzfR0AHax$W5xZ)BAHu45m>rHS3nZ(N+-bUJ=}zd!F;w6FIQnMXRgfFW0)f|B^=}F@<_3??6D%a5}ejTmm6M5fIweAm6*kJq^#k9zr1u3I=P#>!5EgFE` zOGvT;V+N%mIjQ9_;!^8jd95co9p7pF0Qj{4=SUgPZlrlwY0x%bU!4Nk*%7PyVSJL4 zr0?FTr#?LM8(|+8qfg77rp*}=rI z(#KIhlM?)QrH>QE7#VyZL|W4oNM`SH zVduA@GtwvSTtiB?A$3i9reYSD!$+8doY*{4FMeO70MH8J&MC$jdmg@rA4OFncWxLB zKg;fo|3%yAk(EPp5oayXShiU*yofQ(K53^;#~B_xq{WSHOP6lan_e4LTVRe|`%Pzn zd`KuD1WStpT>C6_Xda=ZG+GuFtK=tIXD%^k%Qwli@8C{z&e;fKsiwoD`jLB!sUzm; zEpD9GTMU1l;$S&uu#SkCi2gB7;a%19v1M@?ZND>TDQx>!&k{98@agZ$+vhl=pmJ4t z@G^q?AB(-3?(%9V$1N3!iKqbxI0$uT{k_+iVH_2ds5p7$$I-?o>;*1x>%R3Ku`s1|Czk3EP zbIUDX+HptoD?wA=%HaF2jnkH83C*mB5y7JLa@^M}8;%M>U|W2qZ|Tjc55;Dl*Sw-qY|{Xo1G!0}3e zpl?b6J7@RTEnqBW^jg;b7xu@!YmfstdB4L3_MbOC7cYpDQ(C{{8AuY(xB<@sN|d=V z_~RhWEu@Ri+}Lq*P7~~!bJ;*F_f%hh)-xHMxuO>(OwRpQgJgNm_)P5SA6yA(sq;oY z^wWW4cDncUXyQK1+`$Vw9~wP3~cKnpgE>Ca>?brPXPgYN6iqxS-+vcwBI{TALKuBCBF zks3*-XE?pkE`ygv6rw-gs3aBc17<%C+|?8*w)`%_6hCoi30%Y84&$CexdLxaSDjMD z7|tozV-IiKd@L#xns5aON%cg>ZT z;3Wec&kc_+*|-+mWzulTnBUJl3A22higLb_*|PBYipN9^f8jBAg2sJO$pP!CML&e@ z*m$C`{#U}&!|}`)<0o0w^0j#3BV%4{Y-S{YvyC~p>!3Ff+MeyEdppO3w^ydZI+IS_ zcjnxVuh9)|&ofT$GrT(*=7k@Zai_kVR@IH!UGS1Cz({_R7Meqxb@#W%U%%M$RAYVL zsWZi||Jf*l<**QTILEIh;{?X>t4Z*R`Oui4z=GEHYFt+sw4@55CB@uy9Wl2bVmP*wU0Bhck9v0* zVy~p|y`*vRs~?%ESIl+Ru-gh8J@LZBZk!CvM2S}$qoPF5UyZD~$=jVq2A{s2?DjO4 zTdBRfL_Lh)P$Lm%K)_&O!P?YxoHB*rJfwL*wNtO1 zxrn;M`$4QBv{1SX@2$C*5mHD3Ejg3&Ec6$V_IZrXS z|G^tP-nGJ42X)0+m8dKH`vqrxxo45ZMKUyw+=gnrk>TdWpu~CR3mHYca95QXo5`m% zJYmLe;!}`+of*H`yhm}p8ULIapKQh-Mq69W*!RrT0yF-I880^Djb^;ajJKNcslCM( zmld#se0&!2p46m+&cF`m+SKH3+}`-xC|3x58h2It7A1*t&l_Z@W|1-RXx4=)$Z^7o zul3HqAVY$47!IN^((>Kb=kMCcq$3XMoHTKgfOAjN^IHo}y?^HPCuKCi1dyzO?Jvz0 zhv`O^oKgK7yxQV0Wi|oBjM^WMluy6?!r%F{x`6YGJ;LT=wt^PM1u5u7p0pQhtHM9Y z4aq*`T`ui~HGH11d3U>wTi{b1HkRQ3FQ#kuEVg5B1;Ru>_8IsIRQ0=0XZAaKa*R2< zA2>13C~f%~d@nWlUgozhIi|JVapESUu!)NP8g3M)63vRx6+wXrnP<|B$)G!$0go0l zEoxk{V~-ek>%~lKHqP3ymyJLEZ|0nI!XHvj?lpwfI7^;e{Tq0ElqG)vZZ9c5eJ?On zg+6;3{C=+@vnLn!1w7+Vu_xg*S#8$1yZSdvS0JvTw&W1At~&NFn00l3MsmaH%rn`T z^EZvD=A7>k{-&)CzUKNZ1ho4o3EE-co4EWK2uGy`L7c9(kF@fhA?il=SP{Ii^Wf{Hm!|N)O@R!=i z;DbF~YI;G?rlt>Y$Ms}ds}p^KhY8AYcWs<9qJ|>0G`&9q6qea?+?IG!rDQ99w;{d& z;q3^62tx?Jh;RkM2*NKR{4&Bd2-hOKAK?QCA4Iqw;bw%jLHM>1N5*qk&w*)dF)wF* zpn%gYIBi)a^c5@4K?_HqM^$L2h~x;e(%#0-FA@T_#j zfA7Sz0MGH6h8d#QTf(F=DSXx465s@D3|os{?;q8xkdpz=t9ymamW6w(n>giFs*gRX z7O<`O-G=xAgtsFMA`Bt?BEl62BM85Q@XH9-AY6;^euNJod=TM!gqso8runn5%|H*! zk`>2q_+Dtgp5wQ}H#-9!O=E;7aXVeOK=2_zwIKebd z7&X3|&gH@r40E#bFyBeWvf;d$pUBHI7UF~&x2LT1Cjfn8wORVBwJ*Qn0C$B}M0W8a zL%cc#X@?E5Vpw;k3B5?yaHrRfV}GZZcFakXj02~~oH3~eXy*Y?Oc%=R5o0zmGxIBs zuSxL!+Iyl1dB-@g*tk}B{I7hUrRX-IP)=akvTjM6qnS|q+~|>WA5N0YSv~=M>}m>b zd2yt5cR@W_g}AZcl_lcM)ul$^KmK=Xp5_|qdVr~Bo++c`lkbmkhIGC;D)15hsij7E zkKi9B#SgbWa4c*0*G>c$^?`z}miEFn>3)5o5wKh8+Wo+>Jd-OpledB|l)xWe@Pl!n zjalFaG!hiUyh<2s8Hk*INv9ec!p{BKkJY&-U{ks+w*4k!HS+|5%3*YM}$XBoE6 zE_fd9+=$m-2xelRkzGAslj1ManHZ;fckPR;8r)Aezb4cs*j}YTuTuPab)(u?PT@a^ zTew08%E|)=5OOq=m0XD{B~ne3yD3TwMF}-s;w`2@r`(L(+Q#z6d`dO=b1RA%z1hax z>J!{&Nj~1Y^)qI#(`sLUhFK@%G*f~S_XA!x^-#&g!iC;t`s3gOpM%~ic}t~c$ZuOX zL!OG%^#Kh$qb*EWeqs%%wGX&hn$TL8w1jrOw(GG(OwjLy#)@FyEa3ZFmL%xg;zpl@ zatqS^nljG&CVph8(`w`9nogGX0^6V|Gs%nft=^@t(q}3%*@l-7h&Xrg?q+hlQoJjm zdssjFrFR>1T;`W*;NLh8zD!Zr(H}`vUeM214LU9;=bex!pck-a_ zV%OBgckki}W!JBVq+JUWf$Coj$km$@<$7?)p%*8Lbk~5wPABM)lXal9mI!zkkcmIp z;~h_CdcCX+XH~a)r!YV6ZQbFO^}4g8?&1qQPQXqn*XwW}RM1Fqzw-u2sZ)si$OLOo z@x{Ox$y+GZVOQ-#8QkEieqC4tV2f?^`#*GheXKFE0%!5*7JiKu))DO&_P0(!>j7D3 zpHw&g9Fs}nZ#&% z7*vHcUo&r>Rwefq8shc|W>)(RSc#JA?2H#iQxY*t9uvKd){RGxQP_de0w@GtuA3$H znIh|ZF&eq&KK6%1ioFtFa7o9?y_{HZUShW+w&lEzkv`$gCB@Z8;;XA`5`{Wmn$V}} zPShx5uK+t!qGwnlW=8$4EkF4&R_s=+m>(;4hj$7vTP2@EDb+hpYEA_3WnpwtxQyf{ z6kdoljg)%x^u4WliG?jIcHhzRSYmIYIx!`&kWC4PNdbSLMM|{6zv*u#ZYPdmkyiJxR&}F)}+)Pv$@~ zyxChwYP{?8=JB934Z?5v;Kq43De0tNV!H*Bx|TKsfElV6^42&dB#s7`j?*)z%Tzh6>laG=HSKeyJ2}=tS_zT?p)OH1}i2uGx@Utu>12hdgjRk>~#JmBD zG1T+{n^d$;LH)=xryF-t;&$a})pqN)EC<|=uFH6?eYA|&j+&4v@ETNmQ!+kXjGisR z*%0C7*8D`UG0zo z#LJWI!&-12sb34e@6o&%_oAM9#+o|1f5UWMaCdc{n-J7h^BHQBf?JZjD0 zU-GfwH!l{}5cKsSRr0T+qm1}3laU#;QG`0Z|3)hq^jkoJ^kZ(bx4-B;7%UA zw~u|R_DCql|Bb~&dVm+B^d`P2B>5}w{T=>w)bO9q?)UJ=LbCjM{=<-bBto1B~W`gYX1VYSD3YfsJ#TW7oj#@5tde<_Fbrb6t(Y0 z?H<%#f!cUQSUO@u{J)z-skL-9LT1wPJ#dcErOWe|*T=@~o5}aG%1&?gp%a^lZ zQ`5k&3uF>6gjbH^RlGckZ?#H^>x<6W);XWJe->|}g;!+bX1)e*rNBCYI|upcvO@F2 zy|C5Ua-vP#X@eyWx7mESy*VB^c)x|jeUQ=8E&KTQE&CnvR-?3TzR_9el@q>Ti4$dM z0bbek#Wh%o#VgCNj+(ED?KLI6vjDvZ#LUIcjGr?^*bybblLiRN!loI&UDzn2641jbW*x5qM6-qEH*tGhic$wj=;+O3uYS9rqxYQ4 zH~`5(jcf8O_&61&^RPZhGm3}5%`!oI4`I&#KAfXrUlo|Gkhs=f-~5Gyc3=xi7$YSx z7OnZUgrJ0CM&)AGG7By>!f+YpK)}r_Sidv6utX14#aPZm$%1^ zBf{!|(R2>Cfp;W~qjuXPsm1Z~bbrlXFm6wm4u(;Cd98qmhPiYa&kW~iBE{G>{B4#< zw*hZuf|>+W%^r`5QCfR!aVquQ;XDmkrXl6g;S_;)!!s9<8-+=-X#o=ONOe0Lt&JkOxc>>1acZGVe`r~DF5`V!4rK8`@&i9ILPKQ$~%FfVjj4OjI%j04;Rkn+}Ix~PTka+C@ibu>_kC1 zFXB0f;}w`K+2-5B@R!!};rAi1RQU3~ZuKlY#JI+Ez#%hQFs39>;wC5osebJJb_qz0 zxKm_$Tt6XXT8vkm1PU6)+u+eCWHO{Z33%~gSd8eFkREz_;a`gsK*@%8sNqQSL~-IF z^rQbjKYKQv7@xSi@EkBdb-bW=S4AF?8$%T`Sy({`_Jim{r1@2blXa#b?hrX5UGP49 zn%&I@ed6tei)Q#${ZfxRKqO-K*WWwq z4SdU^zAda3X9xkj_iE4kIe&S>M%Jeaa_X0GFi_pDhij5S$aeQaJ{mGE&DypP1T@-@_a0nDv*jv2m7f;|*1MeZsA z1-$U{cycT_2@yV^QR3(azUGiZk*D6xpJ;UBR-oJVd(B|tEsB>5?%GN31#HF$B^^Uxi} z1WJ=QJ!%9l8w#Wd*}OxE(dc+jUqDD%K(@B*^v)t%4PbqGw+j3={X4a7jlUcqzKmniwrBV=&lohkM->;o7#XU>y4Z7mSGyV=JI_&6zM zogvYK@Dairy9(|pX8@`>gHqrd3sUe!!izod2VLM*26gEi`ls-;dobU#BSB}Yitwey z4Qr?1{g))~8i_Jtk+k30!2LJ-WEf+>Z6=(BOycEnHYDKXf=x|s(q5l3q^pyeQ>4J| zCO_K4z}%Y2y@Tn ztZlVu4dZv=1ZcQ5=&n^4O@Cl`H@n0r*up`n^R4t8#9JSjgY6kDXoP8NG38k7TD-|# zlMQWC3D7<@T99+)#ex?hFX2SN##8W6Ro)!JEwTdBV+PO^rNt_ma%5?Zf?l%|??GF42nbten5Yf8 z4#M3s($s>pRsQwn>Dwi|c=f@sue+w?GRDiDCrL)j+a@Lmc*;ypnwaprA-qyQQ~Iw3>lJmdCfZPw z9p4`;SJaCfwgM%-dC{8#1o|uE3vrGKueNM5RBhTjq{JPTjwyHIO|tpHaQF6 zb|QDWnC+>)4cGV7y2HwZ1~9dKIo*+%d8%jBAmX%a)8Te_?#Xzrsu5m*RdjS495cs2Vuc z#<_<*_T6@fZwLt5YZU{{#3MAxh#()W{nY9QG1Y2!P>xTbBq@9boB?P<&GPMij8J+-Zd}r>1Xd&Ei+)0i{Df~j zFTq<#8PHdDgCl3)jp?t2s*_*%d)QpGU{lDh(4}rg?3JNWb2ZD~Fd8<4qWldJ3FYr4 z3cLMkXqx4399@1$l)o`j2-x3-_7`$xG%StlYu^lQqmxkP6KgOuo?f5rj>uRA*z80- zQD$`Atv=wJ8fyFg-_p2c!VcJDhND&p&>PR;s{r_lm-+U!EO{I6^3}c;$^p#rGM@!= z3nzG>ch-e$t3`Rf=o9;*_(B$9d1fpVv2kWh>&P<)S4e-p-S_NrN4f=nj-hWd-%OD8e+1a2oQ26;aG(^xhZgxS43qEKLWh?egM#oG6bnMfOam zv!I?Mr&S50CbIzS?0JIV%G?|hE;}6DsDcb4(`{YR;j4NibV+p_uA}!r*NN1N9~$o zN2jett@QvVd^sN&$zkiZ+H>xGB;s z+!QejH$}`X-gHEmf%1iB%!Hzdofjv#vwEiuN&?>mo|#;)Kxnfz*Izq6$;eBTi*?CP z&rrN-b{03%EkEuUP-oV*@)66tZx0gdb?@iBu_&VY=7ZIC7U8j>yt$(A=SjNlPvj_GhRf|R}*8(kUp}e z0}`axKXM;lrI15wi0c;~zW4VT24KZh{DljZxk1C-Y1${~$cRL0%Pwb!M+%y*TRe}D zpPIC(kKKp&1GD*2$Oz({x$Z&T#L1uaPQly{;new#-udSpt#Qbnvvz)v#_>Vv_h)x~ z19SPA@VjPrSY<~>eaRtstH?vWx&GPSBHoA_wzus3>&a<&+k+U+dpD*o-G!IJNBpKt zIqQa?X(@7E8PIQ)vlZOlWIVYjspQ_O;BV8|cxsODr|}BYXt(n=KyNiZ8$T z8k~(--C!L`??M}*)NYY}VK$#~;R%t7QK_SIlrG69q%-e9mZ@;O>lB@wiY|Y$GFTD= z6$HoJM6%&4P<=$@SgX^D|5d zKZ%_?1E*%Q*dfSFGx%o_d)bWLh*(_2Fm@p)K4-_rBYwb+UxRq39TzfYyJ#2Xg*+Uy zkam-9^taX#phMowZZ^Re4BQjIp}^Uor-%#7WL*nANaV?n&gj*s8< zgdMvEscm*VEm4ZnLRJ+LWxA%2DChIEL^(fb%aJIlw&d7!@|%ztW6-<=jrkE1v#CB%mq@JEzH3norib#p*iq+sT+3wkp+yY=~_&H#gcTv0ic z?%(X|r)aSdE&L3jkZ2Df6m$jOXu)Tv2re{A)*bGLm~wlM=`Z7|nOeK0hT<)n2D9bs zz&%$pHZQN8ptiqv`uVa5VQLTTk>E6GIb6uf(`^nh-K;kr-vSChwbOrwn)0iH;xjQC zLs0xf_|mWDg*+){YtCDEf(acETxQ;XH3S|r8CZL1xp)JoAGX^lTIbS;qAY7;4ipj@@GSP zSPrwTuUn&_r)?)3HK15qeXvn~t410u!y8!Yn;vmnel*=3ULyf{u}0}|7QX)j-&5`M zbeK*T*dWTM!*u#IJKYXND|{Ass+?ZS*Gf!0NaF*-0a-v45cm%ZhlV6t(Clewy!Qeq zg?R1Hi`Pg^%2Da+7vFC1kOHD!c!3wD$8YyqXb9h2Yh-pP+O<|pw0;ry4``v;`heYf zzL9xZx_1zCNVF~Z6M973Q$EqQ-QM}xVosR3csX_2ken{{dhRFZm7Y7OrW3Zi`o9~Q z4IAOXVmJonqu;;m2XlqR%>C)-%CF6zFlZhFVlb3EZmG6^YbOgaqFv zK8ME>8QzSQ(BO~Oh`$&iFig;hLlzuHaBN^UeEZl^7jz_Gz2WY7*{`~bD2?3}&a-ww z?|i{UB}eNA7LDbB-=Em(<9kATQmc(guqgW-H+IDEcAn;3XHq{3nbM@_5+7MX zJ_T!9A;x5uDK}$ICV1W|q=_(UrWGR=v2slbHQZaQ7lTqy#a~Cs#|w@@euPp4)v- zpFVxM&*{^rPlqgRw;eN~;e&+$`M8&+Kx$rURnu*ZbSvn#KG@D=KJKn5FvNXi@)iRl z7S4cwQ$>o4;rrVZF~d4mvkYWJ5gXX z>n$#|X(5A-i?OiPuumK`=|&d5I>LQA-lOwzTiT%hl%Y0xI9UTo{4q&RoF{xh`Y4fcq=p; zD{~f~5dFV(dW(|t4YH+QO+&yMjNY!p+X`7*rfew_77l>abTg*psWcPQ>9u?&rdaJs zOtB7BLOG(Y{|L=pnrJpIXoi#Kv@0!ITE~a{Q(-Pa4pH> z#v6@B^f6|m0&yC=fvMvM5!JPtR&VAQ75SqDbT+-_^&S;|jRmNo+VG1K7`uR5A)wN@ zOGD$Z9|Ia+2|VthviPRaC`ybKV8z92&f!cG;NfmBn$hpQxVVeQx6x|VYOnDFjCn8F z$D_}mS%5O6*;*J;TZ^%Fk+3c8689ycoS66UP4kH*dxbncOe0KkLHl{Y+=@2z%hmDdd}BT0`l%Rc{nN*x%uVw(<;mKnakFKGoHlaO zoS2lH=$_7rfFLbu*io1^Zm&z+jDV1ez*a~_T2r-C8eU^UYC_lc&9sz)Yd42-#fTcG zb_tCX?I=`I^9?nGox_!b%oEzqv_r4NhX9YX_`~UuA?ZMGrtxM)oFeP&OolfkxIW^* zJ-J-3@6})_Nl3RKKH`3wv-le5 zkaQ3FHuo|7szbgr=*APbu|0l2_=#c|JnDWPd0*L(WYxo&DB-~RMp-ra>EK@ae{ozL zTr@ln*jI;q`W)0U3uSIKp*)fs!@C7|vN$L-C~bT0IR;)qIS-y zQ`i`sbrwS_TTEpvjCk|OZj`aG3Uju%7<%vi8x)TiHyCN|PI$dRf?zH^qn=Sru7%`C z^ID=n_MTdW{qCKhv(PBnRdO7!y ztpt?q$6bH>FrSE#jvF7vY^t7@)+Cx6y$Wu8N6~H7>X^h`s}#Nr13WRKTZt8){7lnoHy0BpY$F_OijrZ z$V(wF`=ocwCTEqf0W7y!^!>$GfCovA(qw_vuh1vo?LqY@_rb~;(3#EIR66ZM=dG1ao|(_1Ecb~;XIogb}h z;IZ+8z2CEN0=JZ5rds^r|I|T|w_m>ptMXl}11p4MjRwoc zdfsW_g1$RqrSUvKZ3bp5h1RtJsjonTAzc3)lrO_KR$C}THi9=qYA#aeMT#sccqS|* z@=18A6v33wI;Nhb-z4j*gth^gzMRIvs`G ztuty&V{f&QC~t^=6vB ze@@Thw0mb_Vb%TL(q6y@oH=NT!gWNCZedQuKY-nXxZGey4W-C4=$P1}l)j0$MXhq= zOSpe+eI2Bhr${M`9Ib~|N23O3IBtzRj9+x#A{#d`Er=Y!FFKP)c||y%;)#%7f3~MC z>|;4vYh;UAvKTYz-NTu+?g6?(4tJBZ!y^^?6izQ%UR74C8_17MTA;B9F%=Ps1r#Fd z@5|5rTHw6|zlGLJ(WLPF70MSjQ!4eUY#Wt9E#_J*9oL5D9gD{Z{<9Y>=wZZo!TX%v zM5>&<8qnD*dY*s2o_nl-N`V(?+)?h-UNtnQQmg~mYUI_w(SPPsrLeM%Igi zp_;S5u^=J$pQr@_tEJQiN|7c3OLbdB(cOB+8iXtm{tEZ69K`NR{SNhj@}?G8%UG{g zTW{wKm_Fu@7MQPf9!5vN_P5Un)N+(oFak2!WN8!zoQ2G5v z34Ie*TsKookz0VhT@~M9)J{7TW{Pk^`XljlAyValOf!<1LcX;VL;Ol><=;>Vq{%LD zM5JLKz;Ebjq7G<8L^W8#%h|7*D!N||tn{&HU9>y;jZqc+WX95_KA|27Z1F9KUNBnr zv(7q1+5Y0r-_hRP`d=dFYrf^t*C+>C|2v^-oXHRzY_1`pccIo7iPO>=9iIHqd?Gkc zlzB-$L0&ad(EE`3(Puo<@oWrQ;qAN|C5kNh+YY|CPFiA7(?Z^oI>Jj(AMF!Nt2d}a zCf929C3*0wC>Oe1i@}oJqq`Cv&`@#4%29TYrqOOb&P46tz6(?7s- zaz3HdtL8Jb*YI6jI$>+y9(LG`=akI%z-A z3q{iR{Z|^l$*SQALKYJvv{`qcd@-Wgy5JWeX85j3is%LmvUs8XkeBWiujXWpgjh&}Pod)9JOit>@aMJP=cZQB~@0h*joR)!h*e9G_JYiqAklDLp zxLx2OmqT~E3dZ-=qn&8qp7=fu`^`xkTg&&Lg?sCJxKjT(Q#)6ng}4e9d+2vD<@&DB z_x|qPlq<-oZ6z0!a>@6l%+IKQUV&a;J$6KJLurz@7<&i|@R0Xv z<3?URaZ}!2HCT@t9yI=9Z%t6FiL?Oh<8SZvuN;JLRX-#%N4|mczN_PJCe<~w+4n|g zfoFxMQFJqD!--7ziT^liM{Q$CNIJ3eCB{^GrbU|xn zcS1f#a_?j|QgTkrlin5|K4a~LNdFiS)gnKwH%Qx?;p}@Vf9ackXKOLxt9M_)_eupcsG1k4jw%Fyb^%;*v>nv{?)90lP za=b&x@h+0$$vvx>?U2Pmr~M?+!TFg@6^P}wLdfwhA;(KeW+eBJ)W9gWMO-Aw6Hn62 zcxDC0c_3k%A+^grMxcEIZs^3_?!Pf>Y-Z0ehIu`s(Zh4r=^UrLvmEh^#?8EX-JQ&b99Of#l^DU# z;Un=cCmj0YTsiRZnxoJxO-iT2(X+5)P_zYeJ(W@-XXDhjU#^hWxA%XHkEz-i?2xUdYSo@KG;Gr~c?!VOyHQm#gV| z347>W8KXHvZ6o$Xw*Dz|jAV}HVBa`yv_E@#`)A@n z7;r(C^m9?`QI;8OL9cGon%#(`MxLyDYZ_m`Jw-#IqmzY6dw)jF5Oc#T&yG`0Ui3z} zmNB}EdY1Zm-CAZ}x0BhLk1(Zq6C#qF;;xC^ojN>i80wsBlv1g5ou)mr`9wW`_iN`6 z>+BAmv-TXb*XK?q4!mW+_YHn<$;nTKHDkxUZ)-HE;6(W;J)_(Lhg z_nqGVQWHw!XN{)x6WM#|-{ZIq|GS&QQjPjc3H2 zjZY)W6P^<#_A0u;+@vFheMCcOHk11D9Smvm?iM|Z=93#aLH`Qt zg#{lzYf^h_K0)>MH|8;T#91vzE(0W{ef>mCQ<7}_%4)k8mR&)rIDJSv`Jmf)Y-g% zFLk!Lrp`9U)Y(W=lR6t|YEow-O-<@-Gz&?cEf?@gKQz)dWcaT<11w=Pc9b8`lkNA| zTnsbg7xM=otz1rC#@1{-u}$w&t$XZdfOdlJ)}KC2N`uLbG3i=u^SHPD>X7 z2U}VNX$L~9AUu(_ECZxLSegZuu`~sc$cp_Qz~o)C;Hy`_utVe z2<)Ql$En9GSdhx23&|z`?~Zp6{}UXET#j5&xyfLaXPhF}N&GrZ^PsiHAJsgJn^yIm zx}`yQPI1APpa!&t2^)I8a-w@;7yN^b@M3u8e4%omA5xXHIcp9gyF7l+ko4C0kz*gR8|2k8Nqg&3n}?@K^sLn9LH8%F~~`jSb%yDUtG$osD9D!L?t{4%Ds(kr;8%+ zMM6o_y4gf5 zjyQPDOt|AzmNc`&`ojZ&8`+6j4sj9e+akn+{d|R-rwIo=P)K@4He?1)i27LX$uUUT z4;~%{pSYNg$VxHr1a1{Ea2xc_1k*SA)ZV+}PTYoCt!s$9ek)ghZr97*b4HDLfl(YP zk2!Rodrqn|?lI0GmNTpY$^W5J~?rTn*a1U3)e|5{SR;@T0EyYv8zI)ZSjoe#O_~1xtN&xo=%;TcvR|bX6#M3IU_)wW&qz%|YZzoc z+_+vdd~ecTuXA5>3h6HfT5(pTxX%x2BjW!0?pn^jtt;LGwT8!EThr?gN@>$%YQ>EW zgKb{j@BY_%yr*wRoSzki6ZN=3FuF3@@xhmI$EPp4sPF0r+eh-DaZ25!G3tnCcg3b4 zNmK(hc6cYZkJ@!4~o>!VH7BPwTHSZ~kSPzr_r+I+Tk!X6F3l z!u-UL+l6t8vwmcYK->0<6SD&%$FyN2-B#OB-(1)`Naie_lD^WT0#>JVJ4dOV`S2}L zQm~$&EF(WRSVu*~nm)x?8e-7Teenrdvay(d%1cuFBm^TMqDA0rnH^=K=sU>cjHUJ~SBDc~`2u?nM`RegWni2knRKzUJ&?w1^E?x2Yx$)YgM=X62|&9?htijzP7`DM7Ex~n3ta0 zA=j&-JfLHRgqyYLv`zFWYce^9La~X(X#PpUuYVU#CaGUE4+sv@GWO?!?$;%NrwI{kEI*i~Ry;fUjMi1)qVmQy)6YVx| z8xP&RJC76n(Z*YVQ4jh6k)ZaWJ%EV#R)FWjU93N#+Q;|eoS;V0q;RXWcst;Bz75Y} z@|(LRw5S$9c?=LX#61^h016%>_ z@QJmA52srlp#F~N!^D+ih=}9#1%=eY8@M%Bf|uaSEcA5vB}SRz|yJtJ__top$J<7-M(q zhcU)VudW!G4V;O~dE`xaP+!yU)YRw}!=7r#sK)uxU5M?HQZbsSoeVrm_owjFRgn*j z`}7qCZZI+Ik=JU53^o5F7`&#v6$y5|r&sJyqkn-tQWm*Eaf9^7K31bQuzJEB7C7^Z z5M@=as1n?c=we6EKa+K_0jAgXs=C@rD=YLbc(Q_bM>@`B361CBLbYxfM+si{GCg~T z7KPnYV8tU-{ld0OP3Kk$sBY>B9;@+2((^Pdf$&{tsK0pbpIV!pf41A|HkauA4iBQ(2J@^;;ngm|24WL;%{OY zHCp5~_!{$QGkPUss$G4!S-~AGocdiz)N8`MFwrXTPb|_VaA?4NIIo>40WQ9X5?G5l zwA`&mHwsGkQ3-hAzK`-%I^8AjZg&|i(ZcA%XOyX#_zBaa>&cTb!tvw6Z#SrQf*Uya9Moz{hY>n&ts{I#onPgp?wGp)uT1)N}{K&KFM33f&K}s}eXL zdwuU9PU^x3L*BzN6(1@a_szchy6{!Pz2s%a^Zz0w8A-1IgAQ2F{VOj$HpgK4?H-(M zkl1$JH9gibos|VncOAefkC391KFI{keuDKfHtK-X!a7fjwa4NPEQSr0@X7hM1 zw18WTV{gw|=jQf+FTV}9M=0P)MVk)_G3T#?E#R3=&UXi1rCWe&8#KbitFQGa#~=Ux zfJHgNh1pmx?ky?TMAUikgYHqnM-hQfjlU-)tn~SS&q*1qPzo%XF?gOl2gy<%Sr{tO z9b84+5$Td(K^Z?=O?vi+2 zka~GR}kqbF#yd+Y1|49w00Z5h?Y~+E18+D&_<4F%@sb_ZAL+^oB z+p!hehYHy|9EZ0+nZmHv;IW_OaGymZ(m*ccam%t9K}4hH-+_KZ@f*xC$Aqp#xRr)C z%4hbrx84!hI>QSC<&ZtTtS|k{LG$^c2E@|)F3s^6KT7^!c;SY`?A;@pq2sn6qM6{w zpSh;d8IqrTz9{wq)W6UFKBvIv6!@G1pHtv-3Vcq1{|_nPMw?Z9THwv>xu3Cjp)C7W z%kRQE#`ps=U4{HBSW*_gqH38VqFC+dlj#vtE1dxmor0V8GSj`0yiF zgA=(8F61_3Ah#hCxec?B`(PGwAG`&*4`$za=d1@Mtk3#yH~%vK$e-KeE%cS&RavD6 zS~hRp*82F4Hs)WnxU}pG%Wk{9yrS~U_uN}`-|}iU$CKxFX@t0nH_+DNlBqmVf6hzn z#TRWNDZW2uxS;?BwC~~@Pj_8pY*PFo;PE7E7T=hK%zr&RO1eYWV$^ZZW literal 0 HcmV?d00001 diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/MT7603_ram_20140305_e2_drv_tv01.bin b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/MT7603_ram_20140305_e2_drv_tv01.bin new file mode 100644 index 0000000000000000000000000000000000000000..244d6821fc6d2a71777919223e00af3597f149b6 GIT binary patch literal 56484 zcmdSC4|rThmEc?V_EoDTx1}qo?Fd^~Em;JU@yN1l5|b6}QoG%;lE%Kam826)EdK%W zc*a)j0A4nW%6}5Pj3-tS594JF5sAa|uqpHrt!ojP^uoKtnP%29cxp1V;gb^VT!6B%D^ z%_%c`!hmg=36zs_N4r-k&y(&7D!s(#OxTq?S1N9Pw_i1qmWGS_>Tk{WDfQLVp>0RiR;4V=%_iD6vGjS$d40+o=u>l|ed^yG%lqUn zDi$+c`~pkw**{nB@#geRRDZ|9o~S;`Z;bcR@b_@uv$*fSQSDA%zvK9cKK0?%!uBRQ-@eU2Lr3VDYa6W%T1`CBYMj1_`Y*`X(1x2!>O`=}#8dSj zKA2cUUa|OHc?Q3OQqMlCYd!&vF~O1Fgx~}{=fg9`>jF>yJn#UoNP;>goR3PMU(JAb z|DY-6=ab(=|GQLeMyu}pdg=|CNMeUk{5kx=GgmbW{Ofld4aadrV2lY2>NWHmQ_Ku1 zS71R)C*Nz}BWD;mZsHKIhDxyd)a(nu@!{nV&J->dP6a*!3%0B%o zFdqL`V08Z*Vcb6*Mu{e!Ni{2PO0-=)U)93DPvsNPc)o#OFI@_0<_gVaZdm%S;CC%F zdK2AeZegtrvj*jD@cmi%R%QfWPia<2rlcboeEH?)Obm_$@tO1ABXa zYTh3|(WkC!m*7-0 zs*+4es%m)TziRDYsbpe} zahXTo^zMiM?@-Q$3(7-YemVW%#Eg8SQF^m!y5(-;=yexsQuX^H?UT%l#-|&X20&XMo)yWO0?$w*s0{Gv} z4Vb0O|443=z8gH2>E*FlZj+Jn4U~_AXH{;q>H$tPw?l8HOe!;?8glPfHwJ5so7+5^ zCvCOmk0#-pqBs5h(sy~!ddLM^CSl7+ot~*Wmp;w=((-%i%ZEkoC(G~9E6sby)cbEP z@ZM5>Pjx;dxHnF|fBBDcHx(8*q}5KQb^ejLsStC#dgHErM#X{=GIGn83m zin?(mrd7<<%JXQWs<&YLHD^@g%>}buCzCaL?QW;Pk+Q(nT~gMkY~0H(Q*8;y$XXaL zuT^C^(^&#xo=T!tk$ z^e=`d(yEA_7T4>Pzxrlmq??TO>*Xq)zB{(zb=zL&hSyCU?Oc;}z~3*#bYR@9iYwig zkEI(g#^5#HoiV+5G^UfZkL=Wo6J9pz4CsbokG{CfRX5!`F=KTaJ?}D{ve!y~kW*_% zV*R~`ih6OO#_wY8u6wRV$~Fc@HTIVErjZ`#;I4i{MWs)xlrxaM#p%kgGdkE=91Aw1 zd+#fb>5Q7A(`K$-Z|3OrYOa*c`KobsBXVE#I$tIDjpTei5Bf9)X%**JbiOL9^OfE& zk}fh|>O@J8mdZJCeq*+NQf&+A6t{fcZlD+VomZ=NEOvg$!0(OK^Gx=FiZr z>)=(D-8fO7Uw5dOSMW(gLe|V{MSf8hdLKpZ9hG?*r+h-nm&&!+^aSNp1AI@q%wfts z!CYZ~VCA{ejRyqY2>t%9m5E_nCD@1Ea{X*q^_alW{;0I|IOV@;am&{i1vgv1gxeA1 zrJHLE`|s<|Q9i-EQ(A*-x+Rui9!mKVUZ#xKGLQ7^BKq1^k8Fw2c37^LblW~K8nv|F zLwy;eICCzNYfwo`+s4s5$?KN3tbEc3+{@b%In>`!RC=-J$vmQbVB1|lKd#WO*G}8l z!Pkug%$b8O`;s%3_8UX``BOBq^eMw%3w-Dd{3N&vAI-7!4coEw^1)BWhxu=5Y1?7` zl-ems8FX;Zu3J|-$$T68g|&<$^F5#5hfePZ?TQI_Unk+`HZzxT@$zl1Vs0hbeWQkmm^bOZoNK zzYdZn&$Xo8NSztf5k8ka?zQ~ZQ05NGTuXa#+F7N?;=<=WJ`P;7;C3;eJPJqd5oZ~$k->sHXjeVhW@3$4Vf>p*f$u`L|Ou#GE>Bl=kN3onM^VGX+e0iTXzFy|d z<16(m=IL7p`X-`hNh^=9*o%JW_?E{adv&B8-IThKB>O{^Sgc0#ff3x3z)`)YNZZJQ z(T2jihIx$+Fg52}zDL_%l(sWkC35XUuLQnv0_yhs{>gSdc0l%6KL&QY7pPJ6BGFw( zEBP$kL!aq+&&hV-H$CRd91Har*JpjNXs_}2Xm6*qcf)AcTbzQaQpR{{z_jY&L8ZTv zjOn`%$MnrfPwYDEdA;GYVldN1keyp)fT9tB2CW<(jiH91GWKRH+TkH+*8 z^v`t(PcMlJehOTp*sH3XQRB>d7M!(-knUm+h^#rSqRbM{ubVT+)l54%40%TE{PH@XTr2Ig3GKDF0Y1ZuL>@+OSp`MX=8%R zRV7?5glQK9m*x^K6Jgqf;4-I#%f&G5qTrGQm)aXfwbH#~UTCk0rtdmiBQ`_UHRx?+ zrmuQcEOJV@dhf!RUan*A=atfj>bp&1I5uwo(uC&)u>iZO~)O~BI zZUwH!%%h*R+2gd)aNLtUKjRx+aq42ttaI>lyUH#S1K^Ci8^?<5z?^2Gt zM@5$DJvD)kF7*}iz`OUaQN-Ek1=>-OCouw$t`C1H_O8FKs?qy5#B8|+Rb$J|iRF=_OOONWF2=CIRJCCL(wjYCn25K=DD4ztdJFr@?Z}&TDn@xX=vMx$Zy6P^M**%Q zd(T9hQL?rmM_Q)rHX|oW>lHfOr2J4fiXJj0ue>9D6W%)Lh7Fj#k8A4q72U6qwNYc6 z_JS_ExADXGc=#R*-xKogQNQXG`04@dMC|zk>_tP#n)D$(!#B|3E>-1kLb+oP==Z8f z!zolEr?ehU*_V%r?eLd?*b@R_~|_d-5m1b$AQ|9HGiLBU(UYGlerYlZ8qz$Ay>nz&HTz9p_X6EyCIK> zPtc=WC+}6c0i6cE*i~yt>!55cbz~n^&3iMyF>K9Ulo5N)3~bnqnt5&Kc7Q&^#SK)O?pA)*GZ$eY(! z#!UxjE6Yb#6wXwZ_pk@WbocI>w0dENzXUyxwxE{->?*B~lXquLZ(*c{yqMplJaDKA z9OYFNklzgoJ%cr8BWunYO&JyO*Hd?eaw*3m17CI-gT7ma8SU3*x9*PD++5hJfLUX4 zhv)rWs=7beqo(?%qBj>tmCf%We~GH;*ZW0hj>;UNJT}fzblQtGQYWNOt?oL3os~3c zvs7+|4!(YQxwzI(pgZ4FQvq*gI(XXBDuh*+*3V%JorF`L4xX>f_tRZ3%&2ImAsxI} znctY!h06L(>EKLdej=?It10-i(!p3|{_J!YV?EW6tI`3yFxA)Q)d_I(p+%FL!Mtat2wmW?PN!dcLMVs4lK3Y@5-@f{vjx*0@x;Q~aXdk{%qKA$n-o=eg;wyGv~b zz+JCe(*Eul*t5#{ZzYBx97{EiHhmBN7Mk}KjzRacHG0vVHCn$&yPqsJW>kcB9e=5+ z@jLLDgI`&Gu?JJ&+iLAf$8`HuY$&vI3%x(L-OBr{AJu33*;@n!KGx1)EGnFNxI%zw1pS%=@FB=n;27 zJH_VcNQ|_D_@9imy$AUCO1v^w)B$`JC?$Hn9kVuI_F_ZVGH;Js8+bUkDrw_hnKo{j zHrG^)PkT5%b=ho0C0wfC-yrL)=djT%Djm_SHQ#09qP+GuHX}b zp8gGd0-u%ZU&bes_1}a8{_q~;%mQpyHl7K;KyA9)%IrB-j%_+vU6v$ z&sO-XW5o-Q+QEjM$T`I`+BHq|e}9Pog6y>d(}?b%JjcvPYvgiT?X>VV`&C{ba7#L~ zUN>BVyFS7C3EVc|YHR;G1I&C#^UGoC5az1?1(*_dAU+6L3q;mk4!bvmJ?DQGHmueJ zT`PGlF8(gzhqQk&hAdw|d)I_?itDa0ufgUmBro)zjK)Pju=VhNGQR~+*oV>KZk=d9fHjqqzGq{C%p{c_oB!?L0e%b3Y}by-@g-q3}f>n53QdO%wBhx$S7LTQ%vn$7^(37yf3uuBAd;8*RR;nzD;j z$aLiplLw_wGPZ(e2~NBC&bw;#;>Uqw^JQ;QnxoPVBI38e@$uKleh(gS#Fml+ zb}ebL7c8d*Wtm^LKTpaP87Ic$isSE28~>%H@w>wK+xpYSKOwRrYwJ&rf1+~y!7<$T z-rk%^HtD|cU(3GK+Csq5+Cs{>+P=I|S-#;_%FEtLF%H*ckT3XW=fI=FfB1vV980^# z(a%xF&JE}yym2^`(eivx#q%dBo(*+Hwl4TBFeL`63{!k}9}4Tr^SX-X{)*>YkZ*3z z(F;OcMgOYBmt4m4#tN7co2tXQ^1PtpxxB_m`a+9mqY)je-0zZZ(l{zQQW?jKJU53h zB(7ELB6i(@Ch{)4I9ZnWn8=7qUqN{sLY|pt*MT;*RQ$u~ZhQ;aWx>HzodWSz)x@51 zTWRkoW9whrH~y=B+7Nq%(6wBD*=6+yD(dGd>c5-%OT+pyU&8uM?6Ug0qW;2)`WfoW z*hu>_pRO+9@5C>wpRA}~!JGa~edGUfLF$L)W71#VJ^CCa-bePu9^*QVW@7)5m==kF z)Pts}{{ifbd-;1r{HWOMr}19%{2ZTG}Pe#|O>LpQM>JFyu(Qi`7jwyeof+4u8IT;i{{VlNlp#qTP2xV%S_ zICkN!vMpBhK8Xdw-l;F6#cXKNDYURU;g(pC9P zcYsU1@;sCr-F*c4eI#aMtf7TYmvzc=Y_pA9y?~GI*6g+6-i~;}M1yfNYW7*N6W)aV zBQv1ptsIS<&5Wq({4mVrf!9Ypl@2z@zWDmS@i%sA)gijiR-N>(Bev3U@ja|8yxkA{ zhYsjq@MGy@^R9IJ@m=r;wu0S%jGFYvl&>NliZyn4m-P{zFFx<7=;KM|JM(}zMau`7Wbu;rW3KqAWlqqy z_sCi={zf~-=;-BGFTKt*sfSIA`ie(q3oRHU&L?zv za}p1-P%hG*UOeFme0X<}P9BL%yb@zvg>Avc%j6g1=xir#(~-E|67v$9Ej?uZFVr2h z*-)DM^i%YFWnl$s5qbgkJL)t5D>&#%e9kSqj3euS_FLxahL$25DBaa6<^5^pr@N^BM7 zjK?qgxVUzSH*}5lRh9R1!hiUEE(q@?@MoNT|;=xAMmD@X7D}9joV$KVEhV`Js=5JIpgF~t-aW?@*``}G%riq?x~K5GkhuI8}a+Xb)5{*D*FCw-MO4Eb3gn$=7@mY#b^0sdomHia+=Zn-`Y+^F*=qGV_ zxC39Xlb}3jULuU0_+YE@`>}-&+jV#;F$EiLen~ml`y@8fNqBagRCK)j zeP5t0)u-lu8(LQQQ!Oozfvf57!o~q#>dnlL&G9)wJ^mRV9I>;n9EG;THS~@D;zfyT z2zC&2`W3S(c-Zs@hfF#cGJVk4Tl=iZtvzRgeg|Dd&VRg(b^KWq!FR35%aC_teko%G zGWqpJ@*MIw-_v#!Kd{wnf=+0<$cP`gim~z7tf9Jp^N^Fdip>{Ig(3V)RK zc=ov`;O*8D?vWS4d9S=9wjP(XAh_qnKtsMR&a5R>3;JhGA{bhhkntjRFp*?zf}!gY z{?NNfbI6a7F8i@4dDZ23{Z#!!cMH!Zpeuh4d2ZkN?1|l0UoAD11|Q zGUr^*SU5pfbQrskn`KnK??gnojrg`jF3Q-_M(D2&+gkq6-M0{flv-mJ z>UNL#(EW40O-gj9rrahy)pk>XfO64svq z%N1DQa6f;tPwmPlrEW|SL(1t7BR;q*;ql-5iZ7j!y209^qKqN5bo^fGu1Um$?jd3g zhP|qSafpSF>+}S6O*1Xtv&mS-5`hep>GTN+PZ?=AmU~p)R ze9lOI^6|<1uBxs2^&{nc**AHqA+r!2vBkq*hHbCe<(z}8C#+RIXHjNxex;H&SJCd> z(k^sqwDTGHjjVMNTlhoXCg7pOfKgtAGe-1%)=T_W@ML+6MRwXY5P9^mvW;75BQ0&P zSM@u)$X_xoKTm$Q&BwpOIoej;DC23`7|)hP1vP8UOVi44qP+DtBevnIiSL&BXVBFr zWDQ>yB#Z3(;D__7OU6sDiN%9;j8*%v*YoZ|VVyQf%C+Ry>e;=g&>1(z-PH1Z_h=or zbJWK+tQEde_(D5&9@i0Xtyppx=eVoSvxc89o<@vcwhtXSA@uiHk8@ilWk3(}-(fsd z#z4<*=n4NwEDL`Qdjgm9bj3uIl>t|?FX+&AzD(R9{X+gr%yo>uEs(hh-U;eVjn91G zG57OZSsNJ}_D4>Fu@c!)j>9SK2}-dz!2o&(eb3(oKXPuAHTw&USDZECcII|1ebjxb zMQk>=h>T@iWescr$BT{7!*9U#ver~FZ{q5qp$q;4MmaAH{led4+=f%e$r|q|HGk-r z`Ta9A=VT&6f7LWJA@#h67=yzj5$NFRj*dBcQO8`$R4LX<@}p|L@_4V#EGj?&;)@!X zo9GOQyG+F2WNK)427k2;1$>0y20ol)uD+whkL8%2BO;F{WWITdIpD(oKI@Dc&D!%^ zuBzqi(S70r?F=~2wO%z&ohiEgNMG^PtHcr22>qxh=YF?>OC4#RTB2Ii3iVcGden=k zsy_9W4d@A8U-74xM9<1B8b7DIV{YDIe3ye;@uxqmfFxYfh0mpbg2~9O)v_#GHyUfh0 zmy|cF0IupP)AQDow?pfgpESFOb-5kh^x(;))x(RwSqeQT&rO%-x6o3d1K2q{eU5{N z^E2=W1P^3HlKrvk){AZzJ($hGo8ZQNQv4E1yNNl->$#O{L8!x@=qG+hM~r{-C~~q& zU5}0>=Q*tomajL+sMlN2xt4}$@qCrYt=AjFcg{uHGPU_uV|6d9Yeh&ap6ik_T92`& zl2@6(1D;-E=Jgd{=>(@tS-%S9_J#fd!AbdYCK;R-qQkdZJz#!(m(a_O&{sowSgSUgXfDuE=bWj2&r2o_9(M0z&$A}MO(mbF-O2NEAuTS5f9 z(i}w}bl~ILMW+bvX8$~b9I9)c*$=EBGW0LV`z-69*rgk>X-O=5sy{+33d#_37rL)b zrdEGZ>@>6G3}yd{>3MS2Qepu5iZ6eaGEvH&xT)Yf@Wy=ow&wV<-p@L{r+n{Sr#@Q) z9+&g&6PaYg*}h`Ij(@O)_5xMMK26SePuelUeqAj02{_ql{h3F96nf!&`s1qZGXCM2 zs@kw$SEo83IRTDds`F7_&b|_3G+)mG$L_Z}I@n*O+Yh?S+TZ%y@I2mE{E6%{RRx|; z2``q%z0B|0%HUsYN9ac~%ZnrZY1XCoxaY!0K4+8Ii$2#ke(rNpmpaq*Gud~N{{s2< zvlh5P1U-;?%$)_yI~!NSna?)Zrd<4h^h5z2JJem;{h;) zcZf+-a)wpbfp*JdjiYH&z1{+Bd`4uQ^_w%6zZzk_avK3KxHkcKofbw{2m|>kwlmSu zSDq{W9J$d9U)QtVs0L&Ou`w}!zOsCbKHz57(7<}*H=^HIJym&+P{;ZR`JJYxmTB0J z4hS9l2`?gqSMyQa#@{JO#(+`o$S?F@22UCW&T+?y6{Dj6M6Q7@V4wBSp!-> zWB1Hq8nShsO&_1=l664#?9f8`G9q&ppG7UQI9`%>#ZmT$KLk(NCw{Mz7l;$Jx_vmF z7yHIv`$AvwwP$2Z#a5{HaSn@kIvc;zW$B&}oKmfSvUOP!`;g#PEFP1%EE&7L;%~ku zG7$MZqraUoffw>lXKmR$j)^>b z2H61JkY`o0_st(;Pk6|*vVU%2Pd$e<)YIJ^GyB=A0Ee^xlVj{AHlj<6)))KKykkO3 zaEpk1r%n|zEt0F_9ugOMT0DJFY_!53`YUR#oR_w7amCZ$m2$yhu}2}FJ~#ATSwHAY zM|tj-d8~gAX8<*Ep~%1dpi%vs;I{{n83|-BebeiQXZE*)W4o$**Qt9Q?85QhXZ^bV zFEgf(D(s;LJkE)he%Q^7(E~M>7 znUmAzB6elwB1k{T9x%d@^CfmZN(|%FTwD{*MdWsAF1mHnhte37=ic!Xf&=|d ziG2XwOwJ!U%ypG`i06ltU3)8D)F3$E+42pt9X759T^-y(iN~w^r=}t zo2ow|Hmdo;C#*m9vKP;5Bk{xYgFPy_Y)xBDut|0F{72rgb1)9xvK9ZiMq*G>_1g~S z8jG)b)Ri`aE)!taNZ=Du-XQepB5ez4Tg)uk<9M1j+R=LqbN!6kFzbxE${V1}dbI&s z;bgM;Zwd2{k^hb`{}}n#g!#WGdqMW5bD%|?;I!z$_9|l{Ge|#5`o}W^%RHe! zdh6A|a&9U#3ru?_5@{Xw9X*5R_R4(fL`X|Yey2tbtWb4st7&oivVpEe$+ zja8k47rwg|9%ZK9TO3)dsqaevZT>*zdyB)mCHJLNVIz-X$F0tta2FdeQj>2~j8{!uomwngOQdVdp@bI_Z654Zqh0IwO z4B*?2$k~z&*c<=pXVCR+GAH4?SHKIuP185P^9*y}<=t;2EitH~E;bUqXKBsaGeej9 zH>x7?zhT39=yP6WT>LZr?&sJKcGM7;81q-KuU!I7l15~5EO^xTiAPm6_#~Z|RJ8vP z>pJJsbkhN`hk3{$U$?PJP>=d9wuD-}{(xd$$B-FSqRWQ$e&zL|+p7?xl;&r^!2t%KHM~3eRF6{n500sZtxa9kKU8 zz%$}I&37B?7m{_rZ^xh2%e--+LsC_V?AD62s%yz>G*OY?HjQ^+$NaRZMvlK$nv=&* zc*s39KsjTQ*yZD12YNPo5M^y!mUcX<5%&AzuYJnu#>1i;kFw8kBII|I9#|QaL@yl_ zzCQa+bcux6w&+u|k@dL|9`&1y=Rb=5V3&zYpl!axi2qQ^IG)ElYl85*%)`VA~7jvPn})nB7Jbh2V?6(W6E*A2J@aeqQmF_x=^+Rn>xq|&UM=MB#r|K9s2M#bclO0U2We<4Q=1O{F%Sm z4X;V;l#9-Sp;vgy$XO`vfUx&%ti!IT#7A4wttgv}AH1m$=YXrU%|4gkzT)eLS#JWX zmuPg=-uw2;zEkS>I(nbbz)#lw<#@rk?aUsh#&Vg{ficJ7iN%eDI|(N$jTD}HZpD3`9Gte4qX zJcqoGXIcxYF$tlNH9mC0FC0_5OttWeKZyOk8@#~V?x6+8F8E=5Y_{!-Y7jT}G&+^> z^9GcQeT^MDYvYvteKY-(m`vz!{%1mG@;+tDu$Pi?0Vj#uMARCWwN>3v@SgIqVP}$JHBK=IEehE`H}K^6*)kC~I+b182~& zr^Wohyp=Xt-{H})%ux$Ez^*+u5I;Z=J|9BewL?+9e5d7~8@xO*~ z!^f>GzP?s*{1uKrpk`W_qKi$_>nywrz!RONMBAkB-HfjZT%kcWF8rrHBjXM|L%ZUL zU6W*d6@5+BzppD}c!pEb7ajC+;TfjOLieJ*Q(F(JX`YV z2W$1~PtabSwRLbF6;QF<-r@@x>Ioj$TdUC}?Ys!fAC>*=)PCdmi6Cj>qK|7lJYpy5 z8~0Rh7yAH%y^St08W9^!hga4W`^#xgnelGS&Y?X3O&9in&1s^{|KRZhOE9tkdjVjjCfW5fC zLU1q3VCZR-3(XgR+ZU}pk-qW#QTi(T$_0XN-}sp`ssr6f!?(*z?NX-(JxHd4qWPGJxLdy`hosw2b&k(0Xe%L5=jJr6;U)f;k z$(U5o6W!vK_7KlRi03dkCM=F(I|Q!S2`BMG?@^-1VW8(PjM z5kpGZm{Rb8Q`$RMwiB+&XV?c;iH!3U>uS@ivF^zkFi^F_wVH9V=+%_;)D zqq%jx*Q5uq8x}UrTTcpHYIjQ?!*$}ju9i_Ha8bv zS^HPTVt>lsp&)mmMuGVleQgfr7k_p0DbkDfj#NqiKS+-Uk>W3e-#5I0t@gb7A?bf= z+nA-U0=E&yAPY^O>AYdv=OtZl@fC4fMdF`4@*fXoskxL{DtmUyeS>(uKa>9Jt|K+M z?$O%*q*=cH6f&XJo&gXWS|rzPqR`Hz{V3zUoc*G^{Ml{R4!8DIJhg- zN_sbU0Vu``-KJ!V{r(ezS8nHMGxh^FRsXqzjNh!@GclX5w_po;NzKyiPvG&0)J1># zjM$;6SH~X6%RN~91h__21NzAHc~J)~s!DU?H)BG-koU!&czGP#87b$tnya9%*Vt-m zt43LeJGrOm-6xry5M>Ylw<*Wo)plNellGllyZJ_N7klI_2A;6K!>^)~ySWbRF32I; zOk_qJmAhBPZ&}LWx&mis9*)n^!v|$fd6ezYhfR~L8~8!x&g`r3gZg>ot;D#=9Yy>( za<7cUC8B%De&1v6m*=tQWcNUixb`HT$&tn-Gkyte6C^AY~;=5JTSv*sLsukrVD@|N*;UElbr+l5cO z5ytyoWY%F-r#m?J(19G%Vh48y@vl6=_-Nr-#^-5#E-&Ui126vM5g8-iel&?#oHM&z;*#ETT8nS9R_!o9&u!jw2Qd^+D6MM1Jmw;QUFMS-K*?i{ zL4)JS9>%+HmcCq~FSYdjS^oZx@s4GX`TipFEPsFJoMGID%+vV7s_Cz0qRtR`&e|{c z2sBHeB7Apt?X%_y*_-E4&a5Aveqv`Nj^l?5DKmpLKTcl{l<4#0kIK8G=a(9lF>M=C z^>;J_V^rigv}uMm$MY#*S$h8XSE9#AI=EfU*lZ9!LhqTKPe_06$Vk0Tnq0lFZ11~c zAd{@dcJkbp>5~$FJoS%LAKm9vPeon!dej}E?xWM{9-^-JkX3#jf9NvQWzT(TUPaww zw(bCRw@j6 z+ss|Y{}|G$&^P{*R~L<9cm1nrIDd`$%~GFrSUEpM|5$|nfxaL5Q#)CMtAn?xICct= zv(47WtsMUee@UZB@iyUOKX> zcnSNewc%f2?mMzCW<0JCZzJ@JKG|1%R@N;QG?}D}4JR^cs@$ZhcD3P5_DGH1?#FH} zsCvCmHT6E}*XYg3m^)%3?yzxPzEyGaGsLxQ;T+|bfHUCaX;Y&e&LnMb_Oi+1*bVqv z^`WFE=NNi_O1Z^_SpQ+}=>5u|s~HVAyd6c-L)5hR4+mqO1_9i~B_HkBo82g%%^Bv+>m9rT#F8S^eiI0=@6}^LBKk`rB zF@s-usLvvUz&~2HO(18= zu^Q~VL^l7+FUz`gStk#9W{zZ1M0jL^(eo6t}F-cII(liS?u;@gw;S^O7n zfS+BhH8JF4b7G@$T;lG~$vkXz5n!~ljzq96Ri#pYx=n0MA_MF`44EnRCGn4hawXa~ z{^RrgTTM~yKBC7kXJac1=y?whoe>&|9z^+w^fy(%5gGR5TJHAJlAh=QF7nYkWFk62 zTyXKUKeZ=4edpBksSi{p2QTZfo zck!o%XU^O+Rp!U0;`tTfKhYzpC;Ne|B4gmO%_7I;J-sg8kx}^Jpfi1Pbfa-ex8HaW zIK-!ZU3?nyEU~El4H5@ac&dD+mvj7z{fdo?C;xe|sp@X#?BWr7-VvI0iS3ndMg$4+ zJb2P;1Mc{bKEN4%U+k-t33$Il`c`W5H20zZ=yQTo>V|Dc;j0`vnM)jM&f6nv+nL?u ze_DLr)E%HM=U!Q$4g7rzXPMU-<2{JoICG#z?pCJEpxDt zt)Wh6H*rsy=b5V&u^H3tg~-OFj8o3noWqCz;e)>7|G1s>8U4&-;mL4J1!fonaYcIy z-=G*+Ao{Ddrz|mIPigeP8+(e4OR)A7=)|6BHa3w2_{a5K=)3`YPjryn&f*zpV);<| ziw`84_bT`Hm*E}(_W<18QE2#!e-L<UYg#N%Q<^J>)$6u|W&vYBn zKuMM%wW8qT8yK``RB2%Rf}zqauM+A z&#b}Tg8cx$kHXI+v0+t>P3Tqoj4$!aA{QFjgJV-VBK-!oJ7w3v)*^Tr8Wp?-!7DP_ zB6cyc5rP9Y%8mQ`icfcm{W)M?(5Lo3AIf{aL9y{TdF>&-*H9)#nFXS^(VvdK3Flkr zlGWDsA>XhdRs&o;@FQLgyT>l@7F*5T#0+P^1N<6^!3NhfFr)G(V=sM}!r89FugW@H zHLBdsq?+Zjk5qN&6uXKA(j%-bd{ffqBfY=>PZgFPeXVzHV0w@DFatf8Or1GG4-9&!K0Xe+T@R zf(Lw)L>@;p_e1!r;Yak|(AEk+4J7DW4EPRZ9M3^MgZs*J1@R5~O$8--9y}nQ3$Qxf zq~Ea|W8{hcg+G>9k|cA_hwo%OT=ALEpF1k#%q{55QEXqain*EtZnJtw{DXy$U%@8Y zL%Iehd&aEfAN=8$k=@OcHas8wbOrMYdF0PGp8t@k!k;2G)40qNV*HiF4#`3Z2HU+a8zo(b^v+CKwp3 zcR#hUNO^_+*fjJ)8Q(H~GNvJpp-wq)Hj{L^`ig)1D)mceRhak8^UD0igk zDPpX~WL(8g?FG!+fnqVYUM<7^H^$xe+;N9(D{1F?EWVRBZ z|LEwcfBC z|A@b@mb4zyO5emF#-2KIw^0pr&Oq~PfD^BPBXwqycP)9H!e{(;r&@DTc0sDO`zUyp z{3)&J49`{Yq0H4}ig$izr&`}3`g~)mHPyp!U8?n65_>g+XZ%hpNBH$ptv5bJJ<+|r z3{e1;^u(9`WaYS{b6qC;HpPKQ4E*10r@q*{Wv%x(A0TIVtK^(OCA{)jUKx%=R!8E^yz3Tk9!1R$JwpU(?Sm3cZ~F*jN1a_iR5S z%GLd>KQ}8~^^#JYSG??uj4i*1^52y5!m}c4Ty$UL^&GxCQA9_L&iX5L<+GRQ*u<9E zbA8mWWxcPGxx^zqf!q)9OSkZk4o$Z zvV4xz?LEUe{-1)YK|by)uX7gH5pcEfe_AD3-;3!I9n0U33(rLiFb-GbC5L$MZ?BTR zX4ESK_WbU7?zZTB?Dc$G)rg&6=dVc9cT&&Ff9~=5SZ3p_5&Sz%>4wCv#`(~S^P|BY zXtfXh8QubZi`X}?wTm7X~ZnxYwpiKw5191Y-(bDRSiuD|N`313!;FtQk#MdPD zDfy;aW6%3u{>RBPv!a)6HWC};26$c)j9-aDPhx^0C}T&QbHEzO+kQ-2L-xKRUa7-?4l?GSq`?yN}RrUT8_VPnBc3%5p*W7@p$8 zXAMMPbg5X{e|(0*H=ZL-8=Gn@wVd-Yz4+v0y-1r{?%D8`H5|ardWCG=~Ii2*b1I9P>{2AZZt-I}c|K3wAs_6`q z0b5#c;c(3DVC>&|@=wz~FoFpscNOs+jH^j|0vPSu_ip7(<6jbM_6@x*rg~rU{#dt9 zC^>uG-^d-RJ4~IAuBZoqwHE#G-N5Qf?9$E=m8cVWd-;C0#N(NPMWf>Pm$?0G5Z#h< z%^drjtRBd(jSydA8tr>m_2xYOa^AV?hO)YPOMYEc;!ixj&3ZJ1U$Lehx96=T9l9>y zo1aJ7Gx^N3VZQTuu=9rPFLd6z{cz_8w;u_=Dbgjll-dRlhdYf2s|VygziXfDI~%j6 zdb54s&t35z-vb%0-eTVm-^crCf_;HqLq%t{=Y`Ny#7A%Mz!6`ea(>Toqd2i2uJ^5(fgRbvP#^i1sdlx`PZD1UZ zWpC%bAsN#TdMfdtc^_pTE5p!_c{S1LpyA2fEf{sF*e7{Pb{gSAM@y+0T%_ z-)sbjFHGi1`!|xlS8alR$kHDkNX6WbrkdT|*j-=f;TTX)%(~UBhC6>}*&PiH4)w=!Q zhBx*~dONxw=R)D@E!5d@@)-H^xcAN0!T#$oXC*B`o#72{AkPFA(<7m*Y_PH|e7+tV zOPn)pN5G+*=b1bY^1Kk+c)idX{JzS2M{39Ruk-vO_$!`I0Q(sG)Z?k;+rN}rv;A@Q z)=x;^uoH}sKPvtV#`vSaOA1}U$KzLY)QWFg+ix`&xYwc-dxb1#UsWr-Ls>2Q18YW- z`^mWHDwyOQX-DAmC*R=a&N=)fJBVM|fh|X3W8~bjDi-_3zc&FK(bt?UcRv`cQ3$u)6$lb=1Q83iNrpH2H7us zm|izZ{5JL`i6y9q4z7AXzPa~jYZ-9T?HX}&al%vT{nke*X;PoEI-RIVuRF?lWfcK- zEB7=IQ_P=Z#|4>v#FI5w?q;BW_I`xyH4GdcP&pSU@Q{BofrtOwXH28gUfLb5kvzdc zd@YHj{g$SzyY{=kti95wiLg%*S+Dsc#*qEX5dHL#^VHAmD87Mt&DDbkxYN4Dep{%2 zld2X!O=hTgNUNi+p6|!>0H(|x)MM?E_Ro3Y$D)%9XJ+Q=! z-#;TZPS%X8(V_f|=yjWo_vSCKp67z}8@{pkd-WTBBdp60aF5FP_s*7Z85MaT`r?f;*8NQ;l1^W=^Q^xE zo`OGCoEnXB@0a5rGTaf_5|jJRL^nvU;5(|_+)YRsd)A^JUK#XUy^DK=DAT`1wF*pG zYjpZB-(2OJ44b**ZwF(!c+X+sOF8?Ia6~s|Q%4(;wz_IkS7jcS_aIh2PFy~g{d@3L zj(=}&*q0dVK$`KC__mbHmF%KR_5CYMtG#2tTgRAB;K#SN1wZx+_z#@)n*N$}I?p$w z`o+d+`y+VtCzO*O*ub|xUX1DWyXAg5$MW?W_&rnfqBEXUG7+6evW*x zKz=0uIVCm^t8)vy>`v#d{3i0(?sVmRQnuT5^BqzjTpm+j&hPr4lW!87kw(ucf%Z@|0UQD@i2yuatsY%uc=NQ;tI&Dh2$lh0;dY(7ThtjvL$ynpbi z?BaL4gEaX*nv8XA-oGz)+qdW=@1)fdi#3C~v$7+d4W!kQHiLd}KjD3Gi5DSl25E8n zH8b!3VHfXl-Z>YbIKO(I&-=^-eZQgbza5fs5m|TJx!5(>y_K{hV_=VCrfoq^)`O#*Ys6+^)8Hf0YDuff4o7}%)8Hf0;-t;U_=SQ^JA6Q5SZB)k ztt?diBYMXFmH4uA@2oSZyd+-#4|!G9ocI6W7tAfbxgcrhepO04^a|^b z>ipn`=ORy~ymN)}q)jiMZ-?(@Bz-wIyY`&vvFp1NS($JnEB)p8v6e$)?0(Qe;xKOE zjOVYUZ(8C4NJC$FH|e*M{u=sKl=xX$OXb_sw~&{zWrhqsvp0T>J;DodQ(6DpeqPOl z&y1!o&2sh$9~@^fjB|5A4e7=p#@)hvziz_QcjvgL*;Tr!g*iPlMjT_0=z`K;f3tBL zHyf2_k5+-B*xpS{(O*<5upBd^3&*D{y4re;JP0g76JEaxOuy2x9%N z8PbcxKlTLm!@3)W#zc43S^Ft9?lR9qr8E}>ZXAN)~xX-n<0>)j`X-+y> zqE=*1WIq6J07Kf&UJERL-yFSb#7$5x(GZZBacq!YgU}w zP?KK78ANF48DPzJRr>Ch8u9yhU3>2DJ$0D#fr(gtqneip_S`T2B=0U~Uv?ifUopac zR6JXl;M+z0jYW0aseMJ6Q~7oKiuh**rl(gNb~8H*O7BHKqaFN)pW^$xc5M`xH@y6} z5>GkvwsT&LeaWX}JwSHut2({s53^ka#4h6g+V(wvC}Z!bJ@=-&ay5yrJ@-=1t2%9Z z^27&ohi*^j+nGb{a+f>niK+D_(q;Gr|*rGr>z&w(AfF=@YN z(0LW}inEk5#*;9XQ;u(p<`+-GuzAuyz2dnNjJtr*P5+<+IPk3ni$hXqoegFrdruEQ z%Yj&a-To)_@`Tue8z;*MoFxU?D8#aZGfwAs-Md#WMqd?J*w8~jK8aVk|NBd@o*33`hVM1_0wdE|zun$_7~-|xOA78! z4ELT=O?r{Vx%-Z>p_HJNSm zmDUI3+c`1m+P6o}(|F0q{{Ds}zVPBjsf+zRo|$*9sPSrN+Q6MU z)UC}dlr-)kw=kfYV!s0n83#`TqZ=4YiWe=;?!J8`U5$Ha24D=krpdz?O4gvNlQk_gCbX(>_qvJ6xo zp~nu3o%noe$N#=RGZ>b|CV>COA&x`*D%TTp6T^2pOK{O|5J&Pxajf%WJ4&|koujqc zIR_4)n;rnS-9qbZ^VGZ40Y-D@$B<1s)$FX_kwI^RUQs{HtIhh$x%b1!Uanu#fRPBx zLAR(cF`n37ewl49m9yu;C`;O_oo{FDA^sujQ_eSgfN|F1;MdCgDS0oobLo57ET1Ay zT<)KkLw}#Ya(^#*!}U=TX9bQ8!xI=dkWp<|cd6(*CLJmnf~LtVtXBYcnh5 ztO@&A)^O9r9%ChS>*Ve(d=mI?Kk%Zb?cR*LTt0XYzUkPk)A-{Wi@y|nQ>`DohnN;w z!<^KjJ6j}Q?hDQ}4E?h6DsXI4iOw4yxyV|KTuR0g4SV;BEbDyxBfsfAm5j|QxO;&! zPv&7&fjsms;!KbiJhP5_?fl|^={*%ECVTH***oO@Ps;on#FlnJ`Zr}OD*O11oYR$g zB9xoA2@iI4b}Jh(&0zhge#YGqNoc?S8NzpX%eqj`Zc zo28$`*ZhF?KV3#I`u-aYfr;&cHx~yLt!hY=!`_&)z>(0u4^}O%we-S)s|CYSMUjLr6 zUqXK0DzP;^zkl|>(tcj-dzAYN%Gf^j%sl%w_EQJJrz7lFJHGO*#0veRj5l<+MPzB! zDf2yI>**IXX)xc%&XcFikI66f$uU0>IOsjre_!U^@;L+Mw>{H{zS_y&Rpq~oO#ig& z$$nP$DCmD)_9M6M&o-)y*>~RK&3aAv#l&a*lzrCzh?nq;&TsKr^1JRk5cIo#kRB!` zbLeb-@%=Yv;AimPYw>qSZ)9I(&x2(K+?DuAiT!6z_*(WKp73P&EiLvl#H&oEH`sJp z7xO#+pWe=Wk6`0f}< z!2-w{NjtK4%sqr@kgAbJtgxBeooz9|GTMM$}C7jL!>Q zG0$pS+&3NGCzrMQgX-9vGuzQyaL>z-O@C@SD`&f`gENc8)+e?864BSm`4zEMpJ$nu z{*P25WV&H;ZnMOSUo}6KxW`K;G<^D!QEg|8p1(O-J*T5HW|Uy#@_l_*7wt|_w~EbS z-)IK?=CXsrccs`v1_e%meet8LQ4gtD^%I%p{v7ap7I^8##UDZMpU&)SJTyKAy)UsY zediX5Lw+-Za$eQ&&-^ZTNZmIJ|EQDC5Z#WvF^4>PByP?8*m?d681`KRhBGb<5z?Hw zaGGqVq@ixH>yo;QtDnerUL@_Sk`}&3&MeIoKFEBRcc0OV)k9ONpJ;uNHL;ZSTg7e8 zf(*E4uixb!>NqwkO=ADv48Qf%k?QU3WwA}rojocS9tr!X_OiOy%KNdg&xxn8Z7N20 zVeUq5&DvEA4@sSzX_9xur?d8ya31_O4v*s5>1cWAtHR$P*A!mX*BA{PL009nN-q0Z z^#O1)yn6-VopQEZhtK&5V{+F5!dB@pXePgb@6Z0)g9G`sj|}EZy4qQTGXBYleBm3( zci)!@>zxRjEi_ae6u;0=p<_bFY2%|YQ~8-^BHu#xYwwgY;WaB#hoJ2vCNeqb+aCWw ziZm-vLjTy03r<+ELg+L1{Oq$A#CmfMK>O^-zJNLFwLlGTuG|r+2{edJW6&39u&#?j z+sC<~YG|ltWKirOuM_#Z9#hVw%lHr$wf=!M;8{}vqfghFp`J3nYyCNLF5C(h(zfA` z)QJqFhP%n{h!jz09qDe2qNAeTFm)#ULp9F^{j8_*E{k8*InlACY6D`I;MZqKO%;fk zD$ZS@m%!(Yiu@M2p?~El>mln}>K0pBLxEFr7oD|fQ?KwcmZ9v_a4v84rq0ZWQyd`?2;PrwT=xDHSM}G>> zHfb-V=e`{?imz@Mf3i)>fTGm7^e#N)Ty;Fzo> zHKUAAZT{o&L@#HJ1N-Ci;P-5Bp_lb-D~47C6TGc!{cYz2T8d>&h3oLnweU6cPBi)*djap+z{`>!E;JEF-19y zl`f~>9*@^iPQoik!>7v;UT5Rm`JIh(w!evOv)u6=2A5@Dw;g-v>bTIU3i~?zLNn#9 zWqE&(wrm%hw?*t#gN;i2&$w_1|0D5YuPyJJ^3H(v3*C$0&vX5!@XMKwkn0!w_#pXC z$Qe=%Kl1%}HP;A5*((Ip5&Egn{7ziUTZK*_Z!IU!bjt8G4viF=-8#-!JJX31{tmrS zfIi_YDRKySz|>yw{~-9jiMdcq|183;z54 zG48vNJ*Xq=E@tkie9;@o_&T!g8IxfX^QwaRWrE|id7^(6-ZT`cnL2l#{a5-rH|Vof zZJ0N6XMSY8+hIe}2_4{@ov=m-fq^hOnQw z5E+S<2QrtD`TDJR-l^5cfg?%*6Ja5>`uKux16nc)%}(4Mmi{v5L_{VNgeGl54hGM&U2wQe z;GB~0?38?Qp<@@y$N4*1Go}kaW)<;~E~18pz`Y^pXa(zUxhKCvX7mHAqy(Fm%a71c z&<#6}KJ0`SJSp}^(l;@c8y4QFHhhyS>k_{gr(TyhY{Q<5*_@S$9^~zz=3{c7iK!Nb z`108!`=xBNIE73rD0VR9naJPkl)cT9qv6NSDkyTJkzS{MS+Ax3ZJs<#r;#|3p9{Q` z<%O0>TGK8InX%6NFT`Epb9B3>r1fNVo{UEHF(PXd-e^+3aahYA#nxNoD%C~VSF6I) z{MGj{R`4ty|7iwxV`HC{Gd~V5SUgfzy`t@=su>6TUOLGm{Hv3;?I!qR&7Tq9>y?9E zrJV5}A?%ohalTW|WU(&)=y8X)50()Y=RL{%HBIAV=x{{;JT-lJOajH2KQs@j znb>w|TqJHG;ZakW^ouF$TcKO7gqNG#?qJHBjp2owk8;wF{dv-!%(1bsN_e*vd=eXb z>W9b6Hy?E%evUJjGb)@+8iWJ>v^8c<;t}W<>Is{xCMzV-c}8F< zz!m0uimG~o^$)OzJJ%VlHb3z{|e|qW~rD`j~+?jMBQx*RTb|dgY=624x zqwAWBUDS>}euoBt=fLOAyCdc!A#B{3OJ6P5Hgr<1lo{WLOmt53$*TCHzE~XxH!Jpp zVvD%n0v)DPPSC|`NpCndcgk0&>D4~waJu=Vxo@BH$KX*Hsd1}v9GV$-VByVBj~+Q~ zmwe}z5nRT6Q|RhcJY>!|!aO>H?$4{!NpH>JO^L7_2Ii-v94Vvv-tXD1c_+3@xtu}#_5;>Tr!IG_o?@&x z!|K_Fda_%_cZYK~pU`|6C)rm(3n%6k`IdY006LK?=eU4Fzdgsf`O(R^cNgm45y}4^ z;gl5-S~RxpTpZSW&NDLqkgczxz0kNb+o}(Al`)@VVv8za{0`lKJ-w_mrfrwHbMh+L ztI`L;%NA5czTpSQOO#LZgT8{Fv&=F^k4qw3;XXM_8fhVtedsm6TP`uMt%fI~e7x-?+{`H5czq5r7 zVYhATH)H6#1hSbI^!g}$z}$4pKIQboIeYIhE9(Dr@*wzT1Ybxky(g8L%Y7m1x%0l4 ze7u81J4#ctDCbIBiO!xo6s{0iq(jR_WFO+l-djd;Q#&SrZa2a<8e7GN3fvR5H z6Ru8wY9DE*v%lheC9pDIK8-aBJerm_${s2eqz=Z+yZ6W()B2Yalyeof-DhG-`Idj{ z>D#aW3GKh{mp`oD-2EYKI$x$I_vESNfup;Tr>YhId^vadd^iR_s*oxC9C^Za%7JI- z6?p<-Bk0G6ULq_u5jN+`tRbF^fpiCKg}kh=cKC2PXK^xS2HSf0W;3}vB)qT4J>@Pq z>GOCLdxItHA(2b4hs=?@qN}0&6U@C`sdB;3ckb0Xol4Q^Xx-H==|}hXT{^9k?shE` z=3J2lM~O|$Gm@Wp^dawbS|z%_r+aY{?w0>KYc>rMKEWyHhI7_;C#;cpaQ`2Fz*<|D zifFhtnMM%32~l>UJ=ev&63kH{gkyth@ST@ zc(F1ryJ#7aC$vq|S0ncV6Z>w?VPjNjYdccl4`Qbk5San{_kgAmwcIUYlLkNQ0%r@+ zFITD?kb7*1#9Vz&j~x)47x{-ZU>1sQ!!rDa=tWZfJJ73Lawul2O5`Nrm@nQQi^8xm z7r4i56#4u}WQ*@vY&f38Zhgod&rgVrl<@x6hQkZ3>$Vyy3I!;y|(G3AD&E~0G2J(8O84EHCtJm_Vmgf6jnT9aMv{NaIx0g z!8wdmhI^`$y!E+0)l9z>A!F8f@SmRH?0Pm?!vkS;ScC`=>$E={NfQXWZS<5-+zqt7d$e3yGBCE$mkE1=%Bu zUhJwAxB>rl1O1Y-5gH(8(}PRY1}R(H70$E&`;_utam(wL^4O!bGLDp`{+HNw3NFUE zm%+p~R^*9|{9Py?oxMtd0~$c7M6Z%+&kiheVs69 zk=^=j&!Fjv?Xv?hzZIEhfB+@WLUvd(Nt)tf;+?@zHXhl=6p!ZUD34j?t9x zVhIdFw zLFZ*$z%R~GRaqJG)R4Y;BK>!SUIi8D02qk72N~8smwir%e-ITON1S=9dF!w_M6OKg`Su9O%G(^EoxUhfgF=}tAv&Wd)322 z_o{ArpdeN27yh9DS>&N9VY`KI_?usUjWgYE4a=NHUs3LrM>%2SNq3W8&Wb!N@)UGg zU#71#FT(G;k#)(P7>B0B?G_o^1^9}w)F!3rfbgl@efD4BC$KxdSIbO<&utk0{UMp} z9`E3W?PuO}VK4kTW1#o#q`Ozo=^ALZ5B!RP_hImUDT6HUuZCGiTao|V$++wRXM4f> zMsQ{h>4%ZkC0RrJ?FI1)8<`O}KbJMs|Do)uuh6*DGIEv9d;f*Hqt{kEy(d?#q*B z!9xc)%bpvI*fI}-xFU~v#p(BxuLfswCk4%L{jbocAvrf4xgyX&dgmUXmXVNtiwfE* z{SO|%uf>D1#?y}X>qqr?)G&`tw;kmo#NwPy2%E9fA`jkp+-C0UHO)lt@jl}zZ%)*( z#(8gRG`s~MX=IME7l3d6d^@%zW_+I=Mvg!q zs*>87oJm`YED>1a#*Ptl2J>F|GlfxPxWJQ23~ejJMu#^IPE$uoZC$W@-ErS3?hnYA zb9g7%KmNj$v?(ub!}!VLF8)MiK1i9a%<`-m7J21;1E#qTyFO^lZ~VS8L+-ryZ)+^t z{#Lwb`wQo#J$8Y#DM@>Qxpn5;xplfscy+ClcKLM~L)nK;<<}>|&YN>OoxA4IU#^Tx z@`B?NvNQ2d;cwmY-La@}WCkMh`rXe>gZ1mm$@PmgE^hzsG0~r;lFSX(0C>O!dhCb6 zu_5rOLeFDE>+eRGi|7ljZQ$54KAFppFn)J1m(dl*lPZ|%haawGF3+=#c<_rdpPluq zWn|HW4)B6yFsCn42KN1b&zw{;zh!REI*u!JM&|ade(ao7K=4R-Guh)=QG>ZooY;Fd z*>PmIj$Zvv^HP`_L*e_pv52NSt?@E|=j&37D9ZKt3ytyag*y}st z8Ybq3wIFQB`4@24Kqj|R^o+bY=FXGvXLwVx5!!>S#^!E=@juFZ65i3elz9-g{q(!Q zw{r1az_)V(KIu(=3}Vy78!)D8 zo9B&F`xF>9Pk|ve2}9LIU~s~{aRS$kR3H67e^U-L{;98F3(yFza2}cWd<2F&fgwUa zIC2{ghQm`}cytO3yaD9l3U@eN5LcXVfkFD1b;wA;qp{cWU`RsG8^!*YyH?JHVFUQk zG=UE%roiyVBn-bDnS?>;>V@#t3D^BVAJ>m6W7caE;}GFqjYfUnYq7rXbz&SuJ{1hB z2RT3Ty2uf#W(wc(=0ca|hRFB7g|5<;2ceP3tk0FzET4IFx6nzEEifmw%?|R7lfrX3 zJjr{uRdQ-C=O7gA8JVDuCE*`4FU}Iy>4nL>z%M!$n|^Ti1w$iVnAnp$`+~`^gVJAa zo+Dm4_+N~LZD@x>pYd}J`N_SqN8vX(@#JpS{h+`n@)gsp;(o4y{5bL-Y|PM=2Y$=_ z^5@ABKYvrq$bYF}{GnT&@`W~e^#2rli^;a}yOTCd#N*d`BQL$kDe2!JZ-;cdG@ZAC zPMnnfk5{VEs=&S6<1MfTk*S;*MLu`DD)2zTxogyfr6qG59|_V3U6Wyxwq#xyd%iMY*K%QJZ8Of%sYn=g(TCr2?W<%xI&trm{glq@@ms{Tn3ZDx zYI7Hw*uRF@j|3gLsOGy)^ukj>^Mk9(g6w_!#>Z-2i-fp)ClgPrL38L~$1c`Md!wXr z)3-}nX_wR9;c2p8_1fXtvjJ<;3v=5xF)pmN7i-%#xBsPW#+0@8ob=qgGG^A%wjuS5 z@EPWCA#KZjaZ>(!!tcPEd(vy0hF9AVO@$X*pDA{I4!q^`vmT2a&;L<)C5;{n(Q}mv z%)oT)oUwrK6}w#0Y5st>&`*^xj~`K!fw z*vk7SZRNc*4iD$d8KFg98Ry`gdnSPTC-Bb6uMWmO@!nbVKmY3bHBG?(GW!gTS8g~m zh~FG@XsxG%c+eSM#Mm>ZH&iJd>HXo@P3i#m#edZ84p(1ob!(yX% zAcHL&H0$ysD}MI9{my(5JyN;PpQKO!ulgqUJ_oID(s>*mQyn@cPv7+sJ(Z)Ia_W-b z*x$u~D~gVZ^I&Fi)X_1`7ZEIV=6GX$5WMZ5d6|&@c7+&est+ zV}9hE{NPg9fgxxJ3`w~$&x-!J+z^Sz1kmQgrR3V zIXS+D&s5=jKKhz-q0Aq5zPWlxY#qKjRS#)6ddRitA&VFIVwLD2yU)tVajCUXB27Qb#vNxt0Hfy%niHRGwcq+AeP7iX& zOJppkTM8UfA(P*^mI7~3|4DpA*}|u)@LD^MFTfY%%i%*uc1Y|jK7}q_>*gEY|Cb*i zt1jg2kzlfk`==8s7yi<>;*B0zf3ER#?xZ`c(>c0!(L?6KkNc`cKdIEUq|0TGzC#AF_Se@6SwEeO(_AN z&%qDB2b@cw;Y*qKD}MQ0bx}{4KJYX4dE5>5e8ganItV^B*}>Z4(P@ksGGF9NQK#=E zp0y_r8lslpe02Bno6+&!jIMM0FMkM*)>8glaIb*&MyfaWTw1-MXBKzEyNMzua$$j?2gA7n?Iax$`m?e;yy_ zqLF7Ab`Hr3p;@8E%JF}5cw*;{`gmVYYqr1NSlzTT-4IJRuHBH1uia3eNH;as*T)M~ zqGq+x+LOr|ec9G*$E{hTZgtE^Wcvr2`v#0y&(`kFp5~0v*4eX_wDl`1D;73wY)U8B z#?z}Cn(8X9Hm*0KgYyRsQK0`d|BU{g&W?=H)7G}gXv}8T^jtSTv&iV}>1^)fmmx|1 zS`yFiFVN{HGITp}6r;8*BWGRr02!oMCBA{a&g;C2Cd>6=q>i?Z!MIz^B4c36@3psP z`>c*Zsh;(rK9){4tgc_XKAGMSZ%Q|C$N3LTTRBi|9@#WNFk1DNxP*{n@^OY-X^M7d$x2k$~~Qov$58S2~J4TEyQ;8 zbT2ND{HvQ=lY>nIJ-s!p>$YUKWH)pSwA16Av7YYib%tA}v9-Blprd=Uaf>7|`blnN zNFW25?b-qmQi9I^vGRP}cJ^-VOLuJ^m}u|ny7k7orA9|L6@R3RuFYKoOIo|T(p_2U zor}g3SARqOnq<0eRk|rzlU(1FPSpQxeO*#U?qcN*3`&{FR7|69GPU|TqrQ6}+Xqf| z)pccR*xJ=K_cph5bao8fw(x37x?q~7f#!iN{dJw$<~~W(+LbZ9`EarHeFM5Ur@YD9 zD2cherFBCRIQnk;%=|5%UBtjh@$$Ps6?{_vTOQle)oa9?>J6vvYA3irS$)~8vCfbg z2?k0I?q-P7zs&G%3AxVuucMTc??Qi}Ax$?dX-d=?s~RjaE}=AoqP(ApR616ZteN6< zy4?++;tQ4P!uc1*q)(3te~on%B~Y$w%zlQ6qz97lRn6U*&MX+77!-6iK#tmu?u^xu zslBafYoe{i=-$%VNxse50Rt%GpH8Ne8{_q97h+wG#AOFtv%NBBjDg#FvksnQI@@IA zt*wcyI~Lu|EuC3opvQm=^t8$hlx}a?($)r^{DpS3XS>p1f}YWWfl9s2w z=CI>8H@ZH|qi8I^E5fQGx^!8zGP(?}N_Y392imiJT|Ll;Y*+o@ z08ln%TetLqnKhYABHPt-YxdLG+l;Iru!ie1OFwIDNY*x1q^*XS;n6H7q`o0GHK6h% zNh;IlC0X{7B+Dj~==y3pH}?Qedsjnd;rtBb@#gGp9q!K!oz2}1nL!EHX*GI79*tzm za7dkDHFwCUU2Lwp{h97;zAf7q%?=Leo}DO%CN2SDuat>!`sn-$*7OV*nQU7}cQ#|x zb@bA!M$?uKCXBm=P2@c<(va>w57-*|QMWZQXmxbb^IosE^!Gb$XB~^PP+T*yXlQSx zyJ83iHOA8$8k(XBZw)!ODCXhnn!0pib=^b)`UqCxW^e**thd%T)u(HmrBUPghD1ZM zo^mJCG`9&++sfc%jcnVNeof+4y!kfa7$6MS%Shd3w} z+3t*yy>-Cogv?A9C&Q^wE2vlp3@7f`&0#ei_cVT3RP}f}!aCfWnz(cvcNP9z z+}+HNJluU56nwa&tejFtfR#!!v(jzdiw)59!fTD-VOLAfpfj;A zoJQ8G0T%8)o#^`OjYQ*WqpqgWSUA7`YUfXVBC$4M5aslHedC&%^varsHR)tcZDT!M z=%5u#KMWcxfA{7rE2NRI_}ej{GkvT)y0d8DCztwU9L&Kl`eYo`jV;=d@GM?04za%; zCy9U24Ilk!xq5T4Zp-s(>S5ZFgz)Z63>CH(sy-! zqjbM`HLmPhGG8s$@dfIzj-Q5K;&U_(h3n?4<)ur>A5=$6$8`SXI=(>T*8UsjtH0Ip z)71+)ej0wsU!-ZV@%i~GRa!y*kb1fFJ)J*Q`gP*DsFuHnzc^pDl~xk(SED+98h(k- z*Ekuyf4&;f@rCNG(m(3_13G@X#?@yYp09>VmythLozd~r@IOHQfW}?(nfdD8(rbuE zxN+J0I{&>oKBVW8@y2|0r1V-1-=fP-tG2dW{NEsTP|uNL``dix?D@V2W*4fXvwx?) zz=Sbp?^Qo7 z7`4UPVnNpp;UWx)6}oO1Hx`T4U`nOk<@86zKt-#GJFlgpwGnsr?AbYS+=7AvUrPLu zNX|{-&&%^=-1v4k{Qq}-XSZHrD_g0vTZmgiRi5FM$87L~#H7?ypvq;J){(11rjKPyJ-=3Iq3d zPrhAUj{Dn3pQv7l`}UJhR4>9Ee`CdpC~jHIR?Bd$SNHg7DS}L`9;uydtrlFIg_>X(aZ(k(@{oe{zZOeHpQP{W>`GV_E0?7c+06|s{E}9OrE9GEbX{|2 z#maPYFdd7>#G}+pJ8b<4jaAC7duhiG{5v$wC9C<;j-B{-x_%q~Fn&hou$TT0{CBv1 zNq-mqyS#Ywl#Rg(pO^lWy#qhx>->uNo%ku=DG&cJey@C0bIQI0|3vxt@51kuuWHV3 zTcW9{Aswq*Tjw-S75bg|sV*@#jntS!L0lE`&5hI=o9rB=%EiyWP=Vu`HI8cs99QA; zo-~I=9e*&-abL_eHXXWTp0a(EvvcV7Vcc7KzVK)qmj`0~NnBm7TfZrO8{X6n590o5 zt;&zoxaGS3u()I_!-W%KJ{X(o@dsTuro#!i+-(o8w5MEL{)LKNx72YX38$T_h+B{s zRSdcQ7vt|sL(13d`j6p`Acq_gzmb36E8_C+7kvNiOEYFi!~>2T#5wz3uE=2jpO$z2 zI5wryD`g1NZ9RSIy7qL_){cSJcJvKv(Z3XR-Bi8gA>MvRb{nRzkX1MOwx1RIBhecG z+QdKe--yKb(wkvr<1Wmfq5Yw0GgRo38Ol#sibn-EsvFg3cqC*KYkZurPw^dOHGdHI z5IG)FKHtO2=YK@`0{@_VIggU_u=3~r2j%xYru_bIDSzN`z>% literal 0 HcmV?d00001 diff --git a/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/MT7610.bin b/package/lean/mt/drivers/mt7603e/src/mt7603_wifi/mcu/bin/MT7610.bin new file mode 100644 index 0000000000000000000000000000000000000000..639702955b0dddcf67188986b291811f51a25563 GIT binary patch literal 80360 zcmcG%4R}=5wLiSi$4t&-CgdaxFd&sl2q7R!0ud5K*=HCg0V56=b?D`-5m0ICtwE@A z@3l93CMRKn6A3YdU;|Dhgy5wC>KN(2-0Og}jjgw0bu3m=BO)d(mGEJu)@%O1eP$+! zz1sWU_j%qt&t%ToA8W6@_S$Q&z1G@$uG$3h)+|EkV?=mNmB^g@g1H6x`2__x7tFm6 zf2D+M#^-u`CgU>+9|u0;@v-BRiI0lU7qH`Xh)jG$T&O#{or!1SR__%$HDJbkgb3^8K1s*_sHBs1Vvgjo5!4{! zI*CXngJl1zp=~5lmH-RpQ-egOG4XkSnOZf3oPdwm`jE55r|S75Iigl}xf=60WA2~Jh^uRN$??eU@N6H!LDM+85NIT8zqE4dj;bZair}}$m zdnODG`H4^6#(QA2PTOT-4-=X7MWSx;;b;2F42>X-8k#`)>6Q6)bvo zdjA+I>G!&4j|(>ou1aO&!FjKza17Y{F^t^7d87Kq09{XAO&cbYNM~6&QDm9ORA$0* znb=US#=bM~LzXhqVkFo8G!b7-=Xr8UpvAt92rrp=k5E%=73}!WDcNq|)pE>Jffm+c z#OCVG&PTg{e&9$C$3MmQDeLQ<-8naA##>_a7Ch3DpnuD;i`Q7xo6cn9T2OX#@9glL z9x-OwBXrJTybe+Ww0Aa(4ho4fA-tI{C~+vp_+O2~VDFED@+dR6F715O7Y7)C;uP9C_-a+9TR?{f;?jkVO{MbB3T z8bYVvyOhXdUxHNQ+Zbp_KsxmmkXRfN>xo0!LOCShm7tNq-22S-q||Ab3je0=hWoi5?VF;)(RKgkYt#TX3WQ;-dwz8B;HDUb5Sdv z44YwVDZ||Eduw4G`P4_#Dw;S;0WK+Bi!G6N%~NFY_1;QZ%9p{ z1z}}L`ruG(1}!+OxTmBK#cq7n=DBkyotN;r(uZh4RG~x_V^eE|G6%KtbkCGQq@Pl_ ztc#7)1Avsq(@WBM`95Wpf^R}G3q9%(QU;BZl*l3_Ho04j%UwejRVW%0bgkC1NSkEb|jLNzcOV!O~l~mT{ zm`T3@X(nBS5<=biL{;Y!jpZdN!pv-O?{tDZeQFtrPV$~44)0vxsd`@^j^)207M8~( zy|i~av$9#S6gF%4Ezd|zWiyy3&Zo6S@f9wDo-BCe=&_4^JDuf+*%0qR^XZc-(Lz2m z>C?*cqpXIqKL1RAs;3XQeiwoZa3yFr|Qw(*&pTfXZx+Jlr2h7 zKb)XA@=73sRw=0sx|1m4ZEUI6C#dXx=2u(9g>k9`9gspoOvETVK^4%Z#_6}j-r-{% zKE_A7nYbz(IU^(M7noUh@-ZJ7Sv=K{l+b_b?WZM-udH{R&e3IKJTZ2BOu@a*(WA;a z*%;Tor_+&Fq?dXnq8c+m!Wi30zFx}T;?myW^CpbSiSonXHzE>$mi-W$n809N@9d5r zcWk6tPK9R4a%+=!3R}k>)SvZkW96(5r666auR*5GWC}1>M=;mLvcq(e_Yjk>Ok@^T z!nR@_*!Mh)5|D#+gQ%mhnWO4}s$=dDuS;D8I_a8&mE^vzx&F0&eP>T|!}0);brBrcFa%!Rna#I}@Y?CMnT?c8PfQFE=STWTneR}B#HP4?LFrgQ@z-eki&K*VB3}&oo zT$b@ZA~)STj`5Kw;3LA*Ilr|Uk|w60k21=c(A$0QrLtKlr|Dc$BxV)fR~TGAnpfI> zYXgsX5?EEBG}gbZ4M{CDE{{Lfp~+Z$y4dcmApf8{cb>wUTfuSY%`+f+@lJa4ywCbK z8Sjt_JV$piOK%>tc*j;fue(Mt!Bc`m$|{KhDOCw6wWMqVosRY1i+ZKZ>fKw_m8ikB zg$D3@Q{c5E^;jyOOF06UNx(mq-4K6YE|Fj9TGJJ`bEN#O~20tT~)>%rOm;v@*JgOabPua+Rg9XEEMNSq8nn#>%=Ul3(OsU!cQ!ihc$_`Nf`%MN$zUI(u#*yI=92hNPmGok7yH<8NKQj@ zWZ8bAFJWf#O5j%VLLec->x&>`Dtc5|Vmr&B|3<&>5eZ>a8J{)KG`B+cjD6QTmRK;4 zlH)0{p57VASCQW{tgTkYF|TI5v;8!>LS{t7{9dj{x%Ma%=nccGIeU=RvJPfrx9hpy z2pQvjovGdL{n>AS+1O{IS5HDNd&dSaub2&O4Qm|O)r>dZu|M8+RCnQha_UV{at?t< zvE%u{@H-@O$E9+CvFMEb`Q;)R(=#4#N_1@Vx>ud(A9i)sx0GXziB9y$pyOyNs^u<{ zuJ1i#gI1{g%7V3FI$Ij2*|s3?!QP4Q`@982ZOmrXdN^hm2-kWuFd{+)5i-`0g-8+c zz8UXQtBjP$?yR$I0~fr6sVlrJrKLgpW>5(vtPaYo5=z*rWeSO{)V^(gT*#;z5(IJ! zSwS8r8hPQ)xnxT5f^Uk&l~_i-Dk-9FQd~iaHZg3`EKv*fHA$MXTB1uEByD1!MRS~% z?pDaq&hj~bR=5&ppE zP}%*=;-U}Bkz3!Xl_zF0p{%Itv(}|$87yVT zvfz(*33^5B(u&ui{fI1=t!_L4szWCD!P}U-sVkcEXH8{`lFD_6taL> zgh|XS%w(x#5=+TQWvNIvW$I(ooid{4|s| zT@jJPON>#G8!)lk*knN^qy#Omnqiq$Jkd=is_2=@NcPWI5jVSRQ1;EdLYaW=6;a@Q|4i4|v(bu$slj#h=QraYUoeDTl(K8hGAh0GioS&Wo*)QHL$(KL)$syfpc zRTIjl^ASZ|V}w}^-qJo1QO1n1w4kmDqiaL?F_&aMvhm(qW_1Lw2t`hXIKZD|HYmlP zXM^&c##1&%BpiPta#_aEA9R9w;9LT(jg7_rQ`qlqUCQUCLnDH&mt|Ic+A3g;HltiR z=9}G>Pji|Ap~~Qj;0E0p`$$>Agx00CIgS;8=NS5omu9Kp4pY;KU?rVFAX{S}Uy_=# zyM;gHV3r$ussD5AVk?Wf33TG%<+`g|KY6k&pQO2+nCAt=qE*OB*)7DRPr`cz&m zVZx;?SV<>f26Jr-t3);Hk#%lu?ld&^+~iIHx{a~ty_~`(WBpR-{Wc5V72G|R35bWC(UN2F)D>{#}8pj+WEFl7EeFqZuuR3Gvw2ZA2giMB%;Pzq?CBcTBPK~If zJ}5w1PRwQkx7_eLsPRW`2hdq8??qPc=j%wZ7#$Pp6huZ$DiP`qbIOn7PvQDbE<-c2 z@lhDzEfhN&NZoc`tB%2NuF#b|QqhVAWp@?}pA8KB)__f8_6Td;zB_BDvq)R8f(Rp>z{sHrR&iDvF!14aiH|S%p99ZT7}^rIf3-sosG#XV;;;6* z{nNl%QO-Mt&RxN#@MoqNZ+>gQ zuOwc+2AXR}KA?TaAwlLmF!WbLJN#QnQ<9LpkN63P0jMf$b-4ySe2+k5Ly(ddUqRsL zM+F0BmdbTFqQ+$Y#FpOPXA}Np2jz@84Enug&~N?Uq2F7>^jrVGpdYtO+W(e*Pr_I6 zmGoPmq~DW{B>hsELBF@YhJN;VkL$qmUroO+LE`i?Ac21N1pVy)oqinJDEi$zOh5aV z=m&dfoPLmjPYmiI$KW<-q4ZKZ$Ms7x!{c4VSZh;R*3i&p8M26me-mDDC184tk+!jz z^WxQNP1Q}2=R9eTJ+I}-BAs)FuWF)?$eT4skKA%PxIxavidAsV+VYN;tq`psWb!Nz z{fnmQqE;LgeXf*ywBl28-O0K)wHaRP<)=RJ(-}4*-@`;LOEHyXx>B_JZK75Rd+ZEZ zT;*WzYBPMYmg**TjheF1S{IPbOwvlJ$y0XS8Ew5HYEDM9Wj4Sb^Rc$f$6>#v&B(KU zQa>1?t0*yzhle8l-l&${WP(@k5M7V*uBfQZP{fuiz(THjMVqnCN|)LRq^eb($4n*m z%};3As%e#@cIK6>n#+#TR19w5rCWX%d=wT~Ys(p6V)o3emg$C&$(LmwOSd2H0TZct3C6q7)=+eBJTQL;g-GbKxQTD7r3GFa!i zr^N!;3f+9tz9;euH64cn&F4ryoq?Yaje~c-aa{pQSVI^7Rs98gIIz{bc zMWnw0#&5Txg=?~Q{u;Sr(Jnr0^_0n0I=hJYToT176Z(sMk-kwW)>-J=hh_R!A^F5i z-#%k4$$a2L>Io9Z*T0P(T;lp$r=-;Mb zl(#%jPoni(nh1R^kB?hN9x%mfn@acPTRpd~xkNv7678%C8nFL|{z4V$(GalQEY__t zpniA_P=Tp8N8^~%w?M6x`d#$6Q>44VJHIUy>vHJZg}^p~9s<{IY`tFlc@o!JKm9du zrS1f-Xe)v1RcjpEA1tEVDihc~*~77I`H*&f3D*<@*E!cuHgNqI^e?DCPk&MQb-0$z ztsKVHmGZWMYYQmCab1|i^%I+c?UXybBiPn&F|Zw`>?mv%1KaYu+eWa}|MZpEnhb0g z?73|OTg=6;#P({MLEHO&{n;?SE32>3BcN?#g0>53EHXmd@sADCdy=#byhDF{RHVnj z1B*f5Wx)2s!^3<~;`mKFy%SKt2df;Rt@Ov>gJN*ubDf+I_H}{}t{7afWKywUrBBAx zEiRdK`^R)&4xnsx(+?rK0r)6VT^`4WW8=B+ zyAh6!Z{?E}!`LhaB@ArPFJM!0-5>wTu>obkD+z3h-3e^!7JFQEFI~Y%<^bO@KR2*B zj&??2W8m_w=Q9mlR&M#sz~zTcqj142vl;l@y8McPPXVhL#-}tijL%hzK_73a-=NRR zdQ%dkmJj390i+b*bnEUr42%j`v4K$!VEipc%m48waq3t;q%UK%c8yTyV4ONDKAY}a z8M?+XqHiCBqY|S{u`a^SqMeIKXe*7&63?tLeJ+&b&EMB zo;zKQ^yVDoMIaMJH~qH;qG?!%Z`b~iBWWLUiL~D8DW7vlyAxc~-VWKZZRf5R>GOFq zeX|f0ut|03lh0Z*=_fAj`(8+i5V*B^Kiv$D{^K<{H~{G_X&+o8ms7Dapv6}gXpgKW z^mksgNQ$-NDxvQd%G$31|Lrpp{XL+*ebDN;=k6D^drlMI%DPwRyJt*v03-7|%%rzZ zOIiuqSyo7(d)TyP>#Ze@!Pm59<%Is5kI$4w+T$i1L+vrNv#(sLyO(3=nf=9(cC(lG zvg9Ao=if5XpMXOTbjsQTr%}o))!lPt4BZC|OMOeUX=RYZWyy(TRKBX9uy-B%{n zy;%4BCyM4cXe}{+wx#aJ^q*eC`ZwlI+K9DpbE|BuI~#kX;8nV@A1$8!wI-cJi{?K1 zPo*Y92iQDWt{Y1?o|J<9S1fenX{%>hzMb9`C0Z#~b(dt{)vCEL0zcQ5QAu0sC4(ky z8L-Of^V4N^z!KWHmZMc*v|Z3qy0vAP@kOTyEjVb!*jqj6-=E)dMq9(RnlS-wGb7sl zr{%hx+ILk+Tkj*42-QJ{#47SM9VxW*PYWGL82qjB8r>|OO*%fS}MJG)yPDELV)OAwSw1=%hJ1uCCT3(^0K`T=O z*>}ufX4o(nv-a2ruzb&EUcd>bSpdcJr#-8dS=;KGXtrCbW14osO0(=zT~l3vnP^_n z8kov!vvyX=0)~BNIg5i(6U^ znc(=lGQp9M36B3J6C98Uj<1mk^V%N&l1%9C{PZhi!a_qPaN9%DQX~=QSIPuP3dn?c zosW-_2~DG90&FP>DBM%UpFvq}vluNCw!$MfS|)J&1dk<%%LI=Taw>~>Jzkl#oIuRo z6HSs%o8H}J>UMW8_GS-Vb?1|zNC2a1qp%ua9*W&-noITj%QB+oNH%f9{)(GjYZhBg;=w9P-%2-WB?jiju_-*f)MnS(g8ajuG zXtqkW&X*;n*t5xQdluW1gx4hf4-ji(vH@8i4U@-cQLRCySyb_O38UGH>|2?@|7UUh zce%TlG`*`+PM4~$pbMzd*1hKI@s7v7LH15;E@f+UJ}WR@A*>1`vA4rz<^bAv{$80x z#G`o=VU z?;A7qws&qCDFw?WB7$Iet-#7A`qcVk`WocISL@%D^Z_dsZq<4;o*Dq;*cd&D6D;+y zl+mrmIXb>pUc6@XrGo5iE{u-K2XO~MV_fhcP)ulHbpKFZvsN z`=C#33{=)QN}@biL!9$746{{`MQocYphxM`PcF z2Re(}7h?}YZ*l@^mh~`3)C_7GZ?<*4*|BfwS>U8OF)J?}Pfwd1yK1CnU~O5${5&Qs zwro^Bjh&0@CE#n!zLo;azbAIQ(DG=L^wRw=!Nx!Ww8CMFq%=ahJC*K~ND5s`NBphAzh$(Ros|auis(jB7q~vt9$bBi^z=_)70>O8 z>|K4C(f$nhdQE8p5!kwy7|n7jjis&f?uqYyx+D8X;Qx3{c>a&EbAFd!@=xPYVdYUa zwE8kR-hX=>(^MAcVIIrCqEQMqN-v)V-x`mnnGk$}W_hs!QYAcxuXCPhj35$3qH`44 z&WP|5rRq7wTg?zdqRXtLTwgTAW`q>FA)JWF4j?8$7gP!H0Epow_Dn>U9Jo3h1>Jyl z5cj(UaypK2JW_$rmBY}vL8a|%=zPwAFG7r1K_1IiD^Cc_Grm&-H(&C1^RD|RoRf$Z0H#6f@*L29F06)#t>v=W zpmdfEn&>$rVlV9Sz(?GDT+ch`fdvkdO;t%cMG4)BCwr$3Noeq2>X+y`qBlVne9kIB zOAYcsp#Rl6IWk;>I-&p4u%$6yRc#Ne)b<_KY5T4>gDDXW|81F0^L%d>QzL%7*)yrR zDB?m|aU`p`G*dM%IG?lpvM@#O^KNI<%WQkRhi#kPeWb|0AJRi!^=o-`%Bu_;e#8RmEMIhQ|6mEkn<)H z>NUL`^HJU%DSK|{kGuckZDK`U9U&brVnuP#KqlDIsZ>~W_L1-kNE#jb+Zl&(1;Yu8*| z2G={(v1B6S61Ty4pZMR)K^|px6^1gqZf+8~=Hcz(uKBvc>*_ZAw}trsw2%Y;$21x9 zDfS>D4MSa(*okI#ZNPI&*Q0pO>Dq|r!(E&3T-x>hP*K-op;=vz>v_O|*Pa-=Lx1k{ zIE*~=c+uaLTj9r4UG+!2V*O4&+RTkUb8QXd5Syp(JtfBGqI9_B##W()oOKS&(i!3s zYF9b7orz6}XfLv6?~5MCfx(ib17mw zr=#Um#KI|vR-b`b(>RU$d#8s^A>!STZnigcPw(_dE@0N$Cj<%s@d%>k3G34LonF{d z5MeK}oz6)3d;?}{d*k7q>#<(?@w~@fNt#@bPR;@U*1&SyK&vz{lze zM3-nR6@GIor%RGj=$A@iTjP2PbPB}U)<4x!j8ukFI41(_OHo$sJ2< zk>?`!pO^aAonOn4dU z(f6Nr0d611#|t?S@khchvh!#A=bsPs-|P;PJeSlt3>ht{G~dnpRG}$y8sKlAjA-Z9 z>kgek8xM~anCZ|rezbb`UvRQwsnJ@38(e!kbBz8u(Z4L)Icib}@}1lR?i8?|txnEO zer^NnawSWl4MEH6*YCz)agLH3Vq+stO2SH`vfNHmv2a@WNf#X!Ca2Jo8X>zs>o$ja z_7t8S7`QMpMymJFloE;%P2zHbz8mJ0-^~k=$-)0yg4% zxb8Fh{0BdeQDbXfN}X*J=&7Iu@urKth!aK|QQ-b_xd9r0#rI;(rdUD5S&vzn=*1M; z5Ve5ohxkbja5ZHXLpPudkxjpJMjng=XjaG+d5C7IB43FOU7+ohEtVOnh~!2}D7@9M z42e8a78t%3y0EA4gS3HPkKo8XW3h})#+bNabfa3^LzPIIuF^D;E&wo?|&Uw151 zZ$C8)Jh3P?zqKin9iI=%6V0Vv^nCU}A>xi^AYCjcgllkC?2w@q#qxMsTpQl@8qe!e z&dUR`Zt7BElX@oVT30YOVHCU{K(3?%V$Oh7pV~!Z3Sjx=3CyOG?rhK&XI+x#C!3d^ z&ol6y$(+x<8d4%z5&DW4%l5d5%;hK*R2k=1&vXmW!%`6w^AL|#9Qv1taXTLP;;PJ;%#KsL*Wz~qw<@fUs(!9aCI4`)px>b% zcw_Flnf+G%xw1^QSMPiyM{mQ< z#H+;L@$T=5Vxchr=tjEq|!?WMR`k}@ zT5m%sbp+y8jx%)qWWS$;ynb3O*GW3!oA2^W8A>Q*(MG})abm#@kE z93^DFokiLE#$G?M=66(fL^=xef2A}eHi}ImEwG7)^1H5f73`lcNNjho9cB@m(A6e?oFyjjyF4tme=a@{H97dS(2)9a3)MDdB&@Qz1W>=fuer))X~$6hJ=E zu7ZvN7f~%;1#z7zZcF;x{ZB1s!HBe4@JQ#eixu3<0No?UutJ8}6#wE8{B;IDL5W_) zELW?q2Gm7t_e=NLw=p46BGfy(`6!ixr1h1?HBG;J<}_R6O=l{~J*&=!RnC}sPeI}u z_DRgbZK%QC!&($Z+lHKvrv4a-^t9fz4PPrG9ms_{PPPz9bVs9YQ0sny$2Tr1FExEV$SjWbW%a9R^3}2KQ zlJ)!FoScbsthy8btsR>ivym$u$IADHg!PrL`RIlJ45T>6n4kZ^sswFGs z6O)Vb6{U4MVnaXY>nvtwzSpAdS|bv*d=C3!$3Jv5^i3O3_B6FT)7;Ry zz3J(`>;XuL*m&r{mS^5B1) zZWZJ7XHl-1@zbfsJaYJD_5pgHlt+Ud1(0V_c@7g?K$MPCVHeP4N))-Pva0|w%AVmp zNFn#QLM9DMAOf2X&KgTZWqDiz@pG1Z7B86Hv=BZ8=p}w9#?LwE$BGb5%(tVL1^wmS z_N#s>w~)x1)^%+0n<cAB~nmXIF>_-lqot!}K*)NpQ=v^Ij2_e0^T{!7|-T8)rWr$a{5}YTZ zJ}07(b-DGsP0RZH1GoLsq-P!Ug_PJroC?pQ*+24y#>D2KZa!+}pAQY(h?*%K-_sPQ zf_;eWbr8|0nT49dK}YM%*c83(cP8vdNGLTn@rPOGYX`=*2(4m=wjVadFiw^=$vc+q z{!U-bKuWEMHcSV7K}6-^UJ3`t9lgTIhx9jervoLe>S2^8~iX2<*-LjiH-0C zs0A-j`WrZR?%Ypx{~24$YaR-%zy%t?bqPxotzXjYYZbjKASEtxN~;rsR-HJ6k(Pe< z*=RXn+_6xBme!iDCHSe`X#Xg`+anQ8eF28sVGQ_vhzlp*AAb2s>CajT%jgpv~ zNP9S*7Qm{A+SpYK!9J0Firb~0!0dL$F|55dq9?$9a1xR7PWcd6y=zGh z&JiesTQ1dJsX-fJN!(%>#X3FT+aFj_N`%`*;J+*NTbG4@g`M%v{rO9r3I|B~X9+4|Ztjk#(~Wu=-kwrq(?ZY?WiH7Ijie`@_JDE|TUmpNrr%fNJa&7DuG z$~3=;b3JOLAg#9CgIi4&3u&;oXQ3s>U~225z0-xM@LMC|#rHN7GV&Nf$b!{GJE6T2vKF2ZA&6}=#EKX*F24(T#K8-Sd%puemucQ|S9po9^HErIJl30h+n z!)en~c&ia7)P9edz4NPvuum_k`Y-RjRbSXI8oD#aJpic=Xg@vw&E;3f(ZTH2N8L^` zsdqXbUG#5~it%Q-BD&RagqoqqHllRv`Fl{hZE%`VdVKHnOF8KO_^uw{IE|n9I)CTD z9q8kAD*6{I#SI7|P8O<=IV!Xz_Xv(X&e4!rE_#22k4|f2%l6D^XxY5K;EK|^M%Q{5 zc3X89-r&(`S<}1FZel|0KHWVGch(5hILui3`8)bk2d5Y`N9+V}b8^~^v>3a&wJ?EI zo}Sd*`1(J0q)cn$*I;FiV+A}U125AsUUF>g3G?98)<=Q$^jI1-%jnO4hthFmP((k) z!N9H`cO1DS?#{eo*_Cy6-SW#{9O1X-7?uaD4#_h=D~A57$@`xFq~2HU_n$CiLKZAt zZhr+!^SK4ZesP`*?}_lkoUg8gZ9^%Vn4*J_Gg(5Wzy{1jMF{f#@ZI}t%#E= zDPP6WJ$#>5Gg>dhN?GgEQ*Nqp;&j1DcbF7;`mkc-1_|IH!?(zMZ$IVpMDhLeFwzjm4QtnBW&rTb-raQ&ESnAJal0rcDlobH_!UXgzKu;;lr{4%K z)LnosPzOp4?RmHP^!YUdGUAQ^z1aMe*mjFvv3qLFtUzCCedi8BOlKb$`0V%sZy~gn z0$BI3XI(V|UXFs$dcjUe@KFI{P3{Xk0E(<57)P8m%4%PQwf7tCzFK$LL^2MZSo84( zwXU*>bZjiO)`K+b**OEI+7hIs#?0s2`)`PuemNs1ouAa7yF07(%-QV&@4;6IUkJvl zR!pf5eBgx7(jA*73;e{iK%!2Mg4un$vEn38Opn*OH5!_2AO~7!I$|Med<9z@d+@V;5Eo1rUqDX9oB0;ZBxz@VVh}A!E}P!#|kL?j39*8`E5`{xg|s z`wn2G`3m$?CuAboz8f?C<7_v^+9t@d)X*$PZ${f+dp4W(fhz-T0dJwG!E2kNYpfdO z!Li);)`7jMJ{F!F(WN$6_&yc4N*wOm&^4!PE;RRt+)hN<89m#E{T6r)eqGoN)U*h0 z1IVB$qH2D(Wf?qQ?=mW8nBNrza}h8mI7xIEUXnDVAx2p0*O?3QQ`OQUULkETWv7oE_bE(tC*Iw*^== zOVz`mA=h2vK9>8~y?~OSrf?^_SD0GAqXa7`PH7ye5mpqDO)JLM{{ZKI@8zchYpO~p z@vmA&oRA(8&I$@hHH}-uQux}BQ!kd6ra-31_?Yc4Lk4|^ndAOg=^A#oUOpZy=<%ZU zmBD}I-c~`XZ^j;D(xBaYSADa0V}0FA&wgs0tVj7WR@#z}KKNlz$znlX{*rxgY>P73 zG(tt&!{?_BWD6wi$O<)W=b&BJP_q=c2rc=wixRc7SpczuWiLI8bTK2H@p~3{udnsa z2E|o$njojQ2qgg0s1PJDgI#Fu4QfbJWmlD(c);kH3-*e>;y85=XyZotx$iJ&OM>y#oI=V{LX~#_*mb_K$eN zNbAtDRf$U|yu+p*QVpshCr&Nyvy0mcaQ~TMC-CQu?BtTR{jbi8(|9Li=AAw9x~z{| z2!21KY$N4oe{0Ev+RtE#=Mgamg=;@EQd5lYq=i2db7iPKo~<|jv^ zk%Uj`VVrlDJHDYg!b-;;&B0`7jd>?B-IUx=mQB*3ThA(+L9C%5-jw>+@thN?E6b)+ z&K~K%p66-;BV{wFB0_XER=<{sXbWroFQDQINHy)w-jN-Xc4zIFy6a)CS+>Zr-@wNp z>QjvUDv>k78njAVrxsrez#oQG37rF%S)lo}^U<)J=DfzAgpgPIViSKJ-gK4+3mzhyd2R0^Ms;T@PP_6* z2#Q#xIE0qcvipbr91~l-lzZChdOoK_H#G|vXwuG;uwf-uE?LEjS$2G~oKG6je}3QP z5^q6ue_Uq^Hk@74Z;NQH+q<=M%LXj6Q`+vzs#NUwhSx{wRcGiX zzP9TmpF^vQbLX&!s9g-p=1UL6|~d$>&#T2GD5&<6Mni+su5#x)Nai9Yf({G7S!TTo|5FS; zO*cI4#@$`scHB>s&K&T(ryAb;Jb2^Rk$JG_2QfPEE5q(y*!5D^k%LFNUhL{-vqE04 zOm0JYoaqEKt}lT?)#rL=Q#Hw}vV5=rIz*m4jfsibebk!)n;N|QeD{J8Pg>m4xy|1p z;0~I&^^4!^39B6TIy3n#H)x0Nd6paJF2FU$-8R^3CC_GGyzuuq(C>_{kFP7_%j?Qm zGDa`$+Nyi7f`)3enl-w+tG;VYm(pcb53>|CJVM)1*utODJ6*ODS$BtuVB47-fAhXV zoFUi?ahp#v_a@|Gmke3OBQK7!S;)nxLP~j(@Zz$kLVWe$FRiAyN~F5LzjPlmPe}a=r-7m zNz97>CETl91+OkJoWom&{qd8yZ0CM`Prj_O#VlJV@(TYLSrbF6S2AIz^Q5SUWg4h2 zNgqtdt&xPTp|~6N*W!OF`pa)Uyo98jDpRWZV|OAtH3QM@CSOyXELStO`$#z?K@`6D z99Ub+0_9p-WJg;tQ1-B!tD9#%a|dkcIJh|rz7SZ8_A7gS)2Nq2W5meOZ-w%o#VV^-uFddF})6nF+Txc}wf zd+Z5+$3#~avDlrslaR=`+CnTu{9(aV+Pt*e8F9wG0hxO}a#Yz#p5irJS#GRAoii z;GU}r+{^Km{v?z+5S{~?LFys;-`pWK%gaUaS)(4Oqf{fs#(<(Ko`jeM<(#nAXH!Nd zQO2$dM?~DX6!Jag$i#PN1h9zFx)Plvj)fkHvsTSZGx5}+HV2mHAPyE@Q~r*ch=FQt z+_S7Rg7;KFPFE2Ln81cb)8V(WhBtBeT<2{q+aqTprE?Q+$rxvjb1H8oTnMOYs{yyO zFkF~eBlxPH@Cx$PC5m#1l!I|wE_y#R-a_m0J!Yc^n>c+jGVR=7McN^sbV%wr=V7cl zHsMWs#MWiJwEkS@Cd|vR$T$3e*!9>99Ti-?rITy8r)B1Wx;O<~W9+PDmF$GCM?C&8 z_F#HP&<$_L?;h+}itnO#)_95dN8PzZB~2?HVRCI1c9oeO?8Kce@5zLHB<){y8vJq0 zq0O|7xqAi??#xEqVG$uQDI*)U$#-f?>;1d4%8IKl1y|ByRoVURvMgqyw<|<&F)%hf zU>^wZH*tt@Ju$6Suh{kQwx`$*oO{YJO(n82hY7_?6=KPTHnzZqJCSq4Tg< z!0v18rm&I*L03R}V7UCTczIa5YV|c`epVgc)DgsN=TX46^Q*XJoaAGb^pcEsWyV+- z_w#m?%{lIF*}7lt$Q0m17czjmi))ci1rdK~)a8~bbSPLg{8~ONMa3GwQ@KW-kNe#U zn7n+BFb(>axO}C+cSbeh^x7xNG|Zu?0*}V#?>{ILjQ5NXUv0QX+#erR+vj{G0e_82 zzN6o;c?VfM9sT$;yeU}+k(dTAq}je)D~;dq`{i0^Kx3>iunqo((-nM}Xm^-WQQj`2 zXkiyKgQK>{dx_i?1je8%zY(_Ws&@x*?7F54^`&Kuu7`%T1yOw55({f3`i|I)>Cf)s8oSZ&l-dTmqCq|-_AKQdt3=v%>J9R=Me&HTBqh>vn4x3w z_^>23(sGjh;(Wq$dUF1zRv{wL6M4h6_)ImZk<96_=(wS0w0C`*P_C097*w(Bu`O;d zS#X-qRL)@^MQ_EOyk4^9bTPxtOYkntO|J5_4p{JR8m1sTI0kP{3vbf*c34iQa&NgY zhjF7EgWeo-^za=jb`qdg7Ew>Atz{iS`1NcZWw4N?GT_w2E&QN3zg_V{C~k>J=-G+; z{gEGlw|;>kT~wk#c3bTDMml_=PwB>*7{D(A^hEHB17WRG3%fdbZ+Px0V~ycY@Q5G{ z(uLm`jwi%d)vp`bg+sdu$OY0Zt^(da#HA6NY!{?k?1XJI_N2r4x}^m-n*VKyxOSv8 z6=jI2$W_6^kcDisem~`B!JIe`fj6Z5GvA#7>OUuJ0$0&5<5qH+kj>4sIdsB^Xofv} z8vOGAXh^(dN-liu>*7)G<+#D`guzq%w1ZoO9J?30w`9uAZiuSb@i4%B6S!Cs9|658bun=Poyo5 zWnx8QQH5KB6KQVfPu%u_k?_9;&VWzah`uIvfozV?YS@0V$mYxb-mD9@_^vVTL)V>` z{LmVyiqqNnz=sg0E>0a(kX9dju81APIU3M+gIq~Acu>qWHe~(O@6#3X>Zh)ay7l#| z&<@SMrY8}zTD1;0qMq~0LRg2VGzU9ZSw*Uj)C)dhIXsdYue0?qa@&!66}fCA7pW)r zMD#UCZ7{Sx;m{|CuBx)oiO*5{Mq)Yi>7hR#xO(7|1D6k6;rc)N4=s$}{|^S(;3Ld* z$*;omGAP((vLP9n)(Cvaja);q5RUzMyER`pZsRIMkG5Wi))FD|BXTDc~x{Jr2fhV+3qFZVC^PAeDOH9buO7Q z^b6Q;Q|eFR^uNe0w0BP=RT)Tm`WLuG&|LRp_!Wh5;K&tu@L4G1D7miQFMG*#kc(BC zE3ACbIPmAY6+FY=Pgh2jRq*$(!Xb_D{fQvXlQ3Y4d6;}9x_x8X-!yvqJz9XC;{3AG&Zw<&0b*B5|6AJ+2__c8IJ=pe(NKa-SI3|MRsC#(Nwco^t3sZW#hLV z?7tFYri4VS-2KIl&v$*w_fH**aB3$?i7a<5!aWT);1^QxpFhb{$*i3xTfb;J^GpLy zQ{=W_muqOuYW9*7yZLt^I6*Su3%&hF25eE!U;B(A$YT|R#3^hkS%F}ce6pxqwz zG|1|p-`5l*B~gA(RAM#9;l;&o0aTy#L?IJ@F1C|u)<(+x$6!wqcSMpfy%CbV>p!qh zaCbaz;JT=NW4ZeBQ1_zVg?>s4Ri)*xgF>K=Og+kHZF2u$$Go7v~JWju3zPt~b0Q%ZBzkTjYp2jg0_o%{hM-R?bb^lRB zl(w}B%`lC!w%8#qp_6|5ztgwqSM)86z8$3NRIIV_u|dzAM$Z-}dUo4L&uF0&`w>4* zo)7mfg|FvE&t@ij7Jlcy_baaPeSN=3kI}DA^edd`S2%WLq+k4ZFuI+c$Jz1lV!aQ) zc_KoSI*bu|G0^TWiKTHJv}67-C(fVTPK4cm37x`@1Xg&W;^f9f&H+h(5_kac{A)Xp zb8CyQpzbiD^i`V_egzt4&yE{9PtbsV9Sz8n@M{|h$|UR=mD+KAk`|S(^SeBKz~CdX zJwaFIpI&})(NOFg+^5eF`A{fCzmds^S#2O=@Ja7@eD`0#EsMGyZ{L`dT8HI>8^b4_ zzdG4Ogkfy|IPf0FmXB#%=QMN_{H9PsM-1RLb_;f*R_F+@Mi4oI(*^$j;%n`&H6fAK z?HpYZ` z3$!A1=W;#WC}%Dw!WZ4<<<&zU>Rii9V98RFGj4QSJEOd{nmovw6#TAGX~ay&wpyBS zFOl$9N|@Y@-#Os3J(8;%Z6O|8?#|t2oU~4+b#u&`7+QA%x8+X{y{GdC+C;m_Rul2Q zNlK0LBzhWwt{A6OckW272=B#zb(`_aFQ8~xOP1->MpJL}d3e-?&KQEl*oY(G&y`7? zJ|x5H7>$>B@*rZb3*$8tJ~RK$UyiCRC7x0Hb(5QXPWWkVPbHvl#I0SD6Sl(1LUTU< zpD6h^(3zR{IUZ*Ze^do(uC-N`Gd8sI_^5Wo-drk$ExozT_$4IRq;umX(`dX5$CF#E zd%hSQmp-aKx5s^{m%PRZKMngJl2qY-y}wf)YZQSMx76V+GFWrZURMt!aL9gz)XJe__SI(ds-70gDgDQq}_ zB^)+pF+3mXZvN|U5hunqtJ4*sVb>n)frGI9G%ahA7p+`ICe(5*8 zhJO>xi0u_v-|>Hem5YxU^m_i=Vmf|{&7f^Xz=L+oxb>33^kzZ=#`Hi* zxZnfQZ{4bN7VtjFUeWXWDfUXy6Pw)j!jq(|V(3zAf}I3PqKRL&Gk%4Rx1WMm5x3pB zV07rqtRwczyoe62@7Xw|LNHI9Z%i(&A0!{-n+*~Ro#2TYtQV-%;Z8Q z$ppehnS_u8ix3bcP%L{U!zAbc14a#%)}UCidMd5h(o;`ad$JRf5Fo}FQX4QRVr&(# z9S5K1@jV@ogAr{(?Y3w|5j|<>u{N0`UMe-u_qX<*N$}R5_kG^?ulK_z%x|ytTld>< z{ca1MeJ;c5GJ7{64>wyYwDmE&e*S=CxsB0HnB>)L?3%zVhHgx^&zOIJF{%Q_MXa55 zJCorBCJw@7rZ%<9F>tjomzzjmSeCjh@Ea_H;hjdhcQzGlJV0IPmEf zJr8FLwAB)L!~>5CYy*#QC=KEJ;BNu2RL!iAx*B^(`>FPp7Zy~7xb=Z$PwnC1Ybobh1(p_5A>v)kzjE?~Ci_1m-;hdb|WZ+ZKnb44%yS%(eX9}B8Vne~OK zRdewF6wtEg^$EB&N;bwV5p~biq&?tuDEPz8rxLfCRcGKU!Y!A5@*~Vn zGzL*ix|Lz-bpCkPlh@q^z2TQ}-L_4cG=)m*+4yL5v*sE{0a?L`% zP^1_%Bpg~1pd;e_y+W-3@b3j&CNPc*7=AGj-h;Di15?qjv$SdWe&KWxXzbeoooI#( zv0cLXR)QM6gc5NAQH|sretSScKl#|akOy~>7dzTQbNF-6jGq9X&7X!Ce=1R@cC19JnDwyDNADh5;ISuP z&p4cx3{Mf^@CS%I3#gaDl_U%LFzlEX_1q|U@~R6SSQ6#5OTD&p0+Zdk&GEa7&^}Nb z+cv>F0Fy4JS$iGy4!9z|rz&dtWTiHJk_dOP5v5d~tXw8f!cJYIS}|jBQMXAZQ_jYY+$9CM+r$N#*AAgtQ?~0D) z`zP$r-9KJaz@>N;@^I(=)aLoGlLnF~5z=Ez>{nt2Q_tLpn*(XD6Z~zI`w05scOurD zKX_$~vvAK0(ONfVga@t7XY&pWfwxBO8;`#U)Xt8p%yyEr+iWM3Ge+BZ`>DG{3o}Q0 z^zTs&+IWZXG4nO(E1cBVVdbo&x-gm_r(Z?(FO8ieckw)niCbZcf zV(Q6@U>O(gbM&V6S$pvEAmf%Me z<#Y%RiHtLlp(Lzi1yo!vYC$2@`iCa8NspUQhyE86dRp)M@3c2&gUz@l)(I(ovfcP@ z8{2Z6dmmD}v1e~bt4TJoUB4%R-}7%IS%B^@wKsfnKH6K`XOG>{n|dxCtzEC@i`E9v z+ADS~JyoMGLrc-G)vo%6>QYt{m7;4yr62P)TZc7L;C)EnvmW)Ma&PR7+afV{mMXQAM3v?`G`&Y_omepm8dPK4BeaQt zxm6oo6^VEnWvmOF(O-l$y6$N0i21%^*KH@$9{ld9a_UW)Ne|-;cl7x5awDhaPanMP zWVTonw%7u!irIRhm>)TqA8A+(Iam$TlXJZc7OaU`Ki-5k=~*V!ftOE>*r#=pn$YS2 zr=dfNFdxfH)6LsFt#&;Pk|ms!Xot_}jj^p2<3=sLew(ax;r*#=m20WKkb*AS?d-Mm zEx?y?f_s?QuRD%3Z}cln(G*uccO1yu|FZ*AVS}0m3ii^(F4z&&V5O;(S0`1TkCQEg zw5wpt?P>m(j?>)Rxm4?>l$~$A_KE&(=WF78$!wng$4~U!=SNd1NCj#GX~;{ILND)V z-TOQCPo#8|H^aFjevA3HO*t&>L>zo3JACz*5SLSZ_VhG(qTIkrjQOcPZp=TypQQQ8 zjrocBn9oyaKAxUc#fdWm-qWWT*^;+XxE;3PSCP*(%ua%Zbg7|_JDPfE-tGjQIumpA zcV|!=K{M?3_7?Qf9aWW!N9m@Hs^)pxP1-}QQuJKI{^t+uIOzyU>{8foOB(LgI_XT% z*>ne5K-%l`nlJ6Rntx~4lW2F(erM;3H$Tz)&1 zyhQo~*|A^iQ>j&$=M24*4Hzqi{2XEZFs|UN?@YvNB=Jqgf&!VM-<^!RvV0-g z$)^+jfE@k>Z`DsAy^5U&iTkwkN#aFQof0X==BIf%@ph2^Ru@*N2^(j#amS(6ExRy` zC=d4o8(`5hfK#{!CvzAfwe2qWND~&bf>ROBo>2c&+6|zQ=2A7;Bh|Iz%j z5;(}e6zR)p9NjBbk_kyT`xYR#4mvfl3%H_Q{J$aU)%f;MRK=|$4_ZX_avU} zet=DKJ9&ZI$u4m__*^&My>n-Cyz9cQLJl6cq(VQUTc$fO@xDZTYNTfP38lFKub;ez zynZrA^7|w4?Mi&B)%d=dd5)R*Y7A!|%^@Z=k9q`6@YX)V*8v`SkfYVzD2-OS4P#P+ znU|Ac#kkgBJUl0--hbOkcMnm|gpo3Ktz+kbM%ngtW!P3udxS3n)VTqi-F61+3G3Jy zPPHN*>r(ev4po9fMD0fjSQ%O=T7cPr_avGlwU8}ZUi??$*i>x5AN_{#r{E7b6(0P# zL@TydFr>Meb*%mge|q)ptYP&xc{k+RJ*yY+zST1%$fwm3@U4+LI)Akzr6hVq^z!Ju z=w;El(K+aak!UH+VL%J2SJl@T2GUWXV<%*bQl11=OLHRDm3c!pE zyCZ9VuMHJ2B z%U=WDlatt#t!}=ty1s>T@kN;G48g+(ehHR5ihvK;5kby>g8)A z9{&o&y5LvY69{FFfVy9`1Ac>GVE}G2Z2l2WcZ)O7-i%D6^zA{UcRlam5=z~Im-Z~1 z|E>?3rKLym{iPEhz^*ml3}F$K@}*qCiLyjhDlg*E;6H-OY_A42FoC?1;pT4bT-sh~ zw4B=Kuf|*TkWfbz^t(M$gEtQ$4R40muE63CMCd0r`LV_nHYMeWeuH-^Y%$JjF(rn(h`4)L z$)jNyQXx}k2wcLzMKi zYJ*zxnaZmTjBy*sQ-8 zF=$GDN;CPXeCVG`bqr;mSB~aQR$?8KNLE*UR~<7rk=v_iZ-#_w2(3z~ek9|Ro-3rc za~}HfzJp2%lN0S}ucVt(BxRd~)}&NH-uRC5+<&1|&`{e8%`sy2yvcdt3^4Tj#T;NL ziDiJ}X_T3fx{nFJqeVfczJl9Kao-hMWl*w|_B#8;{oZ=eSgYhGU(@Q}OO2AsJlH3Rs&fH5B!zeJo5aaSPjilF2j zL0kvoRw3>eNPUe+9RSAVz^DMm`@mQXjO&202dS?|+#`s)261N)_n@(&)6ef?+WMfx zx1se8(PkI5+53C_M@a2LOe0cf2if5lKqo(JjyLh`FrTr?(`j$5##_kI8tieVe>`x~ z{z~zNKRio1?%u{Jz#{oXZ#|!7e#;SWQtsfTJt_k4w2(PmCajdLx{SJH!IIEO4Q%bF z=I#t>1$JlJ)r{S`RALdx3H}*O8!(Ydj(UkdQ_IkxBOyX3k&iAvivKK>MLv4mE#uZK%eUX&Eptb|%C=X$$cfm&CC&_PU zJmCADBRGJ$WaI3_aZc%VQDooxJ ziK@hnOL+G(aT7TRi9n{2dq&DWdUZ5y4P$iwLaHr$PtV?83SNmZKXE=KX;Lwl#4eZW zVGJh|owZ``6Z@o!@{kIWNey{mwzwcKmFP~@3dwsI-oMeePOJo)n<#1fd&cUHFn{QW zu2$D6F%xCTCWMRu+!)})FJ8DB_~35W%D}GybhA~)UD$=a*%kIc;z644fVX!5&ID`$ zTndQ_Xi?mS*25E05n4+U`AtSnq?{b=l0)9$aT(xl-87@K~8cON|B|dnp?3&Nd{+-BOfM z|8{$$N>u93BG?#bu5hVqrIAY*>pC%-u)Ft06gn}xBtvI`_LoR3Sfj{VjNZI3)8NjV zpuokt3(Hy7g&h*C6&6CLgx2C`EGH;TtKnhYUKVO*59Y&@)DE>ck84!Y%@oahP>&Gp!;(O?PJ`_6n2QVO@T-6P74V z*O5gFXy_8`tNGSG@Pi5juc^*e+;n}rqsqe^rmciMyd0++M~LeP^%7|#t+~z|JzAsd^;!5Htx>gJgl{E@zgoW-b>PW5d{ZCaS_;k^R-P_{rn3kylhn2w4E;G7 zkBfIM#g4p9#~K}-N4Uc|G)2&g_d@E9dpJfEJ^{fq0!?zQ2RDm3b<8_skwfFx!dr6W z;bE2C$nDV9=R4Q`RvA_$Sbr~BF~Z9ibT}pWgrfJ5y^av+r^{K0gO?NAl0}S^6RXYaOH40(qX;G3r3qjTxhY zcI==r;>(k#1=5NlA6O0e-Qq457Qb8E6ZnX}032oFM1K($$!>wAN_vsD_e-&8za%WH zo})ctdS3l}i8S*G%ZBy5?^Gsz$y5(RE7#MliV&(%Dg28k;w_(zM_oKxcQPJaQ=#vi zOpjW)w8xV1DW8kC2|8D_*3abWK8Y2gWcqIKPyOVNK1sgI?;jlS=n-FZC+qS ze`d8Wa|B}qucE}uR!FZ(c6(~`pt?=|#qDnVihXcwzfTBnFyt74K8p3}XRx5#gnp-yM!y^NaTgo)!>JGc8T!%Hl!tmf zn#2-p%6YHfh2y$gg_Hsu&FheAT;e8A(jekoHqgk7Gxk@Zcg8{2 zX!0f%TpT%@-YfD*&}W@zK(y8ZGg&Ei;kUboc&)oMT!Whpq@9E(mxnj+EYwnu{w;xr zI;K-R_sWuGt-?wjt?5yx#-NW{lh9WgJJxJM6Y0LdL(~qj7vj6r{B9T>>oHhjW{kmV z8XfB~Slg&y#$Yv%j`bL<9iPG4PIo)eC#C2K?)KI$;4a|;yw%~iov8)wm9n?? z${xEvvwv~has{#n=qbW~JM~^i5Yh#gCc(4amC+P%0Y%T6J&7?1EJ9Cu_?c)CSEEI4 zm!-yCYWaL$66O?Eiv25va3Irjh1V*sgO1jj(HSHku_XHvCtfzrJJgKVwpm0y@#VHy z7jY|{LUO6~%IEF=siJ_ zXnZBN#Cm1tRj(i4RR!K$&P%zwf7$W!u89>M;c0PRLo1*yt7ll(C|Nx$8TteLSH^mR z-OD}bbvB^&*B*9g(4X($(vJtlz`HE0fDaNpo+1&A0!qmtXQ}19c0iSVk{1%Etf4J( z0e?SU7f|GEZk&JP@aPxec<)4nufz9DGkhk(e?;N@YJ^r&9`uXQZ%{76ugy{ljav~;P!T*~ zx!6@E=2cp`2&>deC`a4{wrG%mqx2wZ0|+^(&}>CL5mu?eTMoh65>;gYnj6n-eec*pp5tUuSmtzM;owkA}+@IR91^(I>^HjXl zw`@$f6V&S^{u;JW{te#pm<-9aXJ7#X|>Ixlu=?K?O3$%7Za zbMv{=$nE0ci47PkrR4LV zziyzOC@=UcZwR=VrN42YX+Z7|_uHynD(R?Z4`>4^{dN6z_zpNfP(J|A=KbIfbJzp*%uQ@NbM14RQkZygWtMWgGbU*e14%So&}y1)L; z9(|s;E&Y~gOvgK|Z;n6Y#J6P-R@sv6kTts0&)B-tm*W1L4POn@-~pYVn;FXA%=8)k za@2Wf+@W+Wb-)&#b^20mZS;06_4K8O()v@P>2COf)@`RR9k55F{_O+fv{dL1d_3rg z-l47ScSe*$=>w_J8HdJ2Z$E?=%0Vjz2hz?I^vUt9?gKmnE2|qT>*pV2XurXlaDscW z@zt~eEAHT#{pm`%jMgcZj)!zhJd@f)zHQ(0kFnKl2EAn&318*{Kur{y=Bjo}I z+_huTpoX2Pns&*-I-@U0XTIMuV66t_GiZ(*&!(}etEq^|+3FkW{y>+UJy1KS_19HD z;+zLhF~LyX58u%KD-c8dj@dTy7q+d%i&DShKco`NN-wrx##M5hQ-kX1nRo+&cA=%G zXTCcC-}EHMC0{^or)Rovl@7n#doEq4S-TW59(Ld9nc%xmkPbt$@O$oWNJk;FOLvcx zjt*F~RQGuGSoC=G`9W*+yXHt@Uq|n+AG^;-d*Hoaj@|~VRb#Y)GiZxUYY%Fvhd-ow zOS3OJL)@r6;k7htY5ql@H%5a>@k9Qv<)f^UXb-G&tPg&yL$m4Qk+YU_)?FX#jqhz7 z_1z4gn0-5Ay}fu-uN&*ZnFkUVJZC%Fsp(p!R?lni(j$#93b)2;AS zcPTuZGoG$5Mrbxd$00Nmp)Q1G>GQs@B^PV93tB?01N~#P1n~IQwN!IZBsOZx0C7`9 zJzEP&$E3U5sD0EkU`0KpZr^)(qjpJTgNPgHMyz=`(Z9Sx^cD4|)OvHQf`6 z7A@4`t_XO88_>?X>NZlF&9)W`e9SDu?|KUL!7I8Kw36ZsEX*~+61hc~HId zMgshG!0QOs=w>BuSejkjbJmQ9ToLU2GG*gmjhpk?6RN+vJXN`TjFrp^M~V8T}d z)=W4XFgM{G!1tK28}KF*CcgVd6J82<1HsyKKz9%nw=Gemp>NHBXXub6Ls|IZBxPZ6 z@)CtTu_VM|N-DlngOdmE?{BLB?O=oVJy5VN_;t^+<*8m!oG$noa@ic9Fhg=SZpE4M zD)lhkfQPr^UVL;QZAkTd*dP6+7O!7n?+j@1ErSh1jsB3dMbGSqon(;lalnZAOQm1$ z%1*|9Yq&|D+HVt{@?9FpP&D|I@EX ziw3sD8wMMPnurFjUPZ>$dp{c9)?beob7Z`JlM^~=d9Tj1yp>&te(r$(5z-u2S+V+& zIN28(=Pcby5Wfv}a1X^`gTbJCuYRo0p_@W%iTV9EJ#S345W3qn8qV0Ku-fR7Dw8m&j^PE6w&WF)u)SBoe z)E;UZPqgW4Xw(1K?O7C=d+0u@iB=OXjbumvC3=^;%(ARr%5`wrT?YIA|5i)=H~w`* zgPub4@#r%2Z=QeJ=FQPxM6VV*a5`TX$iwKp6a6J_3E7&2Ih(C@nIpFfBbW7mZ{&t( zCVgThljw z`4-l^gJSR0)L^TU*|tJqeEzTagw=SXOK} z@Zp_kZC$=@OTZzSOI0m+S@EG@>-l?zWo=sLjCR(q1=;zsc=qwdSZm@$#F;u0%;)1l zm#fUGej1d-?!Pc#avzC;VAIr3u_t{U`{_8rKe`|`KGE2lz@;(r{KOw(BZ>6E0=@;j zDCC0slZspWi2jpd%+phJzEBN5M$RKa56=}fxF*bAqC4dUC9r8>x`qF<<)0s0{>v3( zOSecm@mQ$bzkya6!3!CQaxK6AqH>8d@Xwa}_Y2BRyP#a_KAg3>9lSKr7x4*18xmdE zvm!n%(O2NJ5xrJ`GP4Af59mq(c>rY#Xeyu_0bLBpEg*3&35d=}gMT+!n@%CaS+q|) zwiY}T*N}^33%q8{ zx4qKmYAJ+8#*ZGj_lzQ54Yhqce{=jgi9suhxO=jT{l(|{h%B`KV#sO0r}#)aLpPQW zRjrW6lDA8{@veQpg#IptR?Y@keK%;3I*`?|2W@Fx*Y*Z1GMwP(6hXrtKJ#rGIe0sy zORr7Goqj3d4M>OW;7m;C6(5Qi@IA=ql#siiyh?frXbR$(Y zG`#dCpo-miB`PUJI!UlrfRyt9m1xi-Gh^v4Q;IoEB`zg;O{Afl(o8dyZ0hNDR16Hd zDbe~NY@+yT&2YLk6`J96Yx0Q{r@JFo$ZY(| zA|wFFDxeBLcqJBCm8ip*8J3Irn*V?MbtpWaKpr`Y{W08|4n=(<;Kfj#%skw=y9 z%NGAs*f6ZqERb#QIhh{I)*d=3Lto0Jr{UfByy}}bFg+EJtNP|rrrYQ(`RbcpEcks$ z+u&UX-wKTb#=sSEB>EjINs2l&Xg`z){g}rNlXM?;G1$mz1ifY=&fNB{|(?PUy2(raP=~*OS~r1c+g)1y)BO2LbGjr=znmWNVFgBdXn;e zlit83tT%v#zWqY10I<*+t?(<`f?eI+!lcA*M7o05kJ{QR2kNR~Y-D+k1^x!)tUdYS zY^vquw!><v7J^dB z#K0ctNeQHYH_jka&o-bGlC~Q$j2khwfPf%vmmu4>`ltSB1h%Y6iF;ywK}tFgQqn5O z+(Y1u2XPKnqMUDGA6SPo{Ie4G8jS2`CGN|=K;pgzcwZ!OuSWRiCGI4>#XV5$OrsKa zlEc%=F6KcKGNkaImAEhcoW$M#1rqm!%se4+|6Hw621(o#^6v{J?q$TS1V%#Q{ts#_ z>Z_pcUs+>dk;Gj{%Lz`(&`IJx(=2fwcFD04_YyPwLWz4Jg=)mtOGw-?Z=owiQZotG z?H5YiX-=15HXJ6+L=KxGj+?Djmb0W2;*MOS#f&#Gr4yJR9^8DFxfT4ag$_~;_LLT^ zmbR_WpfnF(j@dIs-UDmT4UB`Eo`QFlmYtq~RkaXSfbiN{w^7gX8**~I^*0k|x{>bm z4D9S4!i7xSF3uawfwS*GChj=<&bdF)%5!&FucTjC`IJSv>flFVWMo*YzH7&b8dI05 zw_)#?V#pesx|Q56M|2kXGMFa~*v}UC+4$R4_w$iDW!qY;cqRC&k^aCLIa?|0a;T5h z)rhn%)X;^rHh6HhTgOEg$5otp`Th3D;<$9y-Y4@jRgdryk%J34{DpE*zgve_VNr4- zwcO=sNHx+YQk!XikF@!s^wyF016?S6e3!#aeFkO!DYaXXp^;{zvW*vFscbWK#7yl9 zQfhDwT!(~4TAk|;O>=~2m25cp8&`+>j(Z1uukYa2+J-pk+LG>isgmV#wgo{s;>A<+ z;hg5O4oB1~Vk?^FM5g&~gr=kqnvyWSm<`;i zy^R@j;;|u4{2JJU(4G$e0rH>?vV1;lMe3}_R^n`M;l#w8gLY31S_qw<+?Z63J!K|t zP_&~!(vBHmNb57WA+0AVx*@G6$-E)0C&@hR3Xs18GS2uMK!&s)GuV{YX9;ON@$w95 zeIie~=NQs@;@cV0`hOx%lt(m$A+0Bx!jRSzO<_puoyIz&n;v$4?B4I0FUA@^U+Hv| zJ+%{R0QnSDnCW)5k;mL@f62}@`bj=_Rg2@@-!NlREln{W(Pa}q0| zNlRFyO^8>Gc5J877T9K9us1{qX(P7!+uFd%%S^1V4#T>yj?vtx@lPEyHz1`lXqt|9 zv@_8f_xCY3HmJwo-Qxs5?1QIBXc+?To;Nx(9vez{K{U_9$j+YUvb31GPd!#!uLjib zs3{-ReNg|wmJb>}X#Ak*gRPLT-KRdPK3BU%tx#{RBknvn^PuHpf-~>1jhD*9>EO|) zfk#hTYQ&>Y1&{tHotwj3z@tA#^L(gYo>M!^n0s=|U>(MdXlXyqB)~*Ji=7!T(aej? zaH5&ZOql5Vc_y5o&WjSWnexM)%oF(m2B%i!Ex5!cOw@Lw%*x%{6S?i)L6A8|WMBRi zyfjq{*)VQ~HJ}5g2|Az!tF>*5K?lqrIzW>mO9d6MbU;HNoA;jq8PakZP2!BoepWC+ zxB6Mp1a}H3`vKz^|VI0XSfl!;KT5I`jVTeN8zK9d`pv-CnyJd9xMd$ zQq+YZkivV6U0>S-jfxpmf5Py4WQM(2MjJ>2?>_k1ZseXik3M-oJ3SNoUeACGzECcW zP+;1~NFZh(!F{Z-^IiDf9jQK+If6YsgxzG-j+we6;@y@HnK{=|kH4+|=}@5}b5~^A zyOzE*b!g*MTRioaB?0Gkj899jqPFhQpe4diu6}%@&sitwZv#CD^k0 z2%qA!J$^S@wa&-nLiBqK{eH}eGptlnJ$#(cR&w`%OmP$vOMx5)UKzkGQUv`I+As-zC>R`bie52dM^`Q zQh-$@b6HD`OQ#FmNAb#0Et^Tb{(oBk`oy<}#CWS7w}N>gN~PM2&NM2WRvh#g?70@P z;#{_=JT*64^73^_+g!j_mgoGNXY%;Bw?Xj+6GHV{?hO_0e^Y;n+U1d z%-j>Ou{psl_)Ec`6@NDM8TAd~AjNFM*5Gxv;tJGDXw%kUr^@8xpuw&qM>tBIe0_o*))W!{&XB+Z<8WhC_ z%vI>=;&yNc_($sl=E;6!RcJPE0WSm8C!l7G9-W&6Hvp!SlVA-not*@8z=E0<+7N>3 z=amQ(lzzOBP9?1XHz1s{Vox1I6=O$DQo>1ESdyUT=0uH9+E-vHcU!o(eEBlwHzNckb}Fyg74xq#1@@IozMLf=5>Q4=QqN}mZQ zYiP`A#NfqX8e>gEzaP~@iJnHzbZS8k9x(e_)c%5#2k|5ur&gJ=KjRcaIQ0UB3;CZ2 zrSpv><`hb26QqVBoX$FupHp~cXR{efr`~!BHR{>9^>mT@sC1O}0C^Sf5hw2b$rE?0 zEUAaJhW?#s!(p^0OKW&+A}GELNH6g!)4`Pt<1F zy~=6>SM|PVgBCM;WRnicehTqIdtS9iO7OZSgaTUX^B*ifA_Zwzr1Og_{Y?YS@oj+| zoHZW%NI$d?;`j2J{#587W(;m01aFc~IA}mZuV@Lw=!MukrL}po(vd!?ziDt>ejYkbCtca?M$X0!N81Exgbi{S3-oR!2pP{;uY-kc zfO>SSbW?<2o*S!Pa92}Le~s#<#o$2#Fm}CCwECw0aqSzTv3O?00`GijgISOY<-n?j zDGb*9jt;AyuI+s-bA-3$5LoN_FdyC{B17Iv^uSZWjV=azs@~hSgFzPmgPCp8N6aw;F6q=>wdon z9Kg#Qg}hTyyME{kJdJa9b%U=!E`;AAq;$=1d_3g7Cr>Hua)e}SpW@{|RI=RHiCinp zTw%xNXE%@Fu4LU&s88~2P@!&HGuZk- z-%qy{#M1^+12tHCYop$fjY-`@Rb7xIp-mbiPd452)(o>-&bcw-5=NfR5E^9%M%zvr z*2c-*__(HG%y<0BzkG1Swq}Sg#;>F=4;;jtY{6eG=Hdp>J#Eb;)f%WC++O*MpxRR~ zvu3()sdcs=j5vFJeW_>9^ko|(Ok<7lOw;zh?u37RJB=@mGmY_aV~oe+4Lf6uv$Tg^ zH^w-9P{JtVMJ2r2J$XwNH=wUCVb;EKDOR||nwxs>$2<1Irp=9+HkJy4e-AM`$F>#o z?y}8_Z&h>QfK~CeM2%K9d1zjhdFxZPwcSG~&!pJh&oWt`j`R7jGEMA)nCo~Oq8?UU zQ(%F-m~6LxHWRj9Q^v$@!A?{Ysik7pSkAnBqZDxkcy|e`Hl7@W zMN9WNHz+(UzuyWgY{>Kf_J{W#AEjpxKJ(Y7+n1`I-qJquA-|cQd5C=6(#sj)h&{BI zi<>;YYAdkoMlOLQJl#FfqD2^Cc`BMnKZUUC=$BpJltI7w*Ef;hTH+7o(y#QRrp)}? zQb}{HjvZN--(;TjkqDK;Ay#wc{;)?u!qX9ys<^!`au04{6Q^r?=o`hy#&<7L5Z=#i0j5?@Rcz;Ey|9UBV{~ z-AmplFS+EKuaqqD+biSS`WprwTqrfL&|)BKJ;|m=!3&A+2{}p_7FSKZEr|0pG{+IBzw|DzF^0b^SJXZEln{odfs$?lM z@h+m{Pe+!=Q;O+Mfj1TBviEEj_MSYK|K+|GXn8G$kA%hF9^jsH*3g`h7%&Q0+?LJa zvXB2olUm!rBeVt;#i~oZ4%A;iF1>%os~(Fx-cY=;6lHD8WM#c;(z~b5r7H^*Cvu$n zvtNIEkQJVjtIABc^qlOkVY7A1&Vxe^^CbAFY)-4?1?R8>Jy2KeOJ!xg@s^_#ad#XO z;)Bf?v!1O#mqB`eXP-Uiq_(l^8;8)YjNoe9Gq%MXe)X5ljoAmp45xNu4+H(ibTYS^L|K);T}2W%2jS z(}6*kVDY;TopTO2c5N(MS)W>VQ%dT#y}BdrcyMFcs?^l7wN0rz_R@HvuaOE|t)IzW zwa0(sRN*rcbT;iKq^(MvFuHY4#%+`Ca9P6-*d%^Dphz+FoCh%%6V>ka^5aQ;)?J|7 zkBD45QSb4#d{~^V?r`4!J$etaYAF+1vBMoN%GH1$n<&o##V>9l;HT}>@3gA0Tn9|Z6gz^N} zPF-ih;M%D*CQNy*AsDT31@2(1;vP1mViA0f!n?@opVWm{-dll;UMpta$(4ecU&9?7pqk(XRG5^PE~^|H>*=t-l_U= zcXEJFl+{1p&G>up00uao2dj_w2FDHMM&60ma<}I3dzc&fS&^TN9m$5>iS}IDdnN2z zM;P9~Y={|luu05<`dYDaWQ@Db23#9(ZNUAl+*;hWLbuWXkO$e>LWbAXnbn0f zNGG$aST?Qf*5yimnFDt(E83^HfVEm;dDS64rB%DXP+OamiZtKE)Lh7HE~F8)%tM>0 zZf3nMs59y?rk+$I)QnByaB#*YQH}yxIBX(aS8?V-m}n{R_+`eNv@~mQr>eSeGRp&2 z4YGUKO-b}i;{utMG(x}^B_sbH}JEx!tRxtGL#u9 zL@&tELh2jQM^rPkLG&B-ANp}Pv-94F4e}KwCcL`5jyKJagVNo|5BHCYp5bTZ9EM#+ zXcrb=(CRN7Dbi`7J?MflqB5y$bDZA#1MIi|ov2IxHmn1JyFLcDw1gx}fiqKM)sNWo zU19s4E2?qTbszCA9MV6!%|w{$Q*6;?R9+({LMZG3oBNUi?%|`Xp+4+d#Iqf_z{P=7erk%c8Y@Prj`zyOUv;_w>7oo2%r>@Lvmg zWG-%5OSlvbMoLISia5HO8Z8N)RZ>KVBU(cGo|^OzdeXere$~invB;&wLFi)G%cuW? z{7l*%oPu>w#SQ3bgnV!=<-w1a zZyfm{z7N*hl)~5*xXD|#1++(?^Y|#JjIUnL(An5h3azX?UsaP+IYZ9jG&)BWrEHQC zDw~X(Yq}d_t8O1^9NxOZ%EG$5Egz)BTsj4Cl4K7Pcd;;H4dn1l;&>>~^NLy{R?W+6 zqgLEkQX*C#Qy@Q#SQQIah812l@}%SVVh(}nW9tyBNx_)nKt3Li3o*cpSp9`qA|g$I zx!BLX3%$DIr(TE@2Bx7ba8}?4#1h5c5h;uo1`o$lB8BwwbhMC{a=%=vzEEN1nUMnV zHnS^ci55f(e6DvL@M=vOuZ~DTKtWk}6BwS1T{!8GLeCQIhb@W{dU~?gUN$Mw1H)T! zB0AOWp<_7tEy38o1qU3@Pl-E^rwblb$iv_reHH2Sf#c&